Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions +file/fillConstructor.m
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@
catch
description = 'No description';
end
description = formatConstructorArgumentDescription(description);

docString = [docString, ...
sprintf("%% - %s (%s) - %s", propName, valueType, description), ...
Expand All @@ -270,6 +271,16 @@
docString = char( strjoin(docString, newline) );
end

function description = formatConstructorArgumentDescription(description)
descriptionLines = splitlines(string(description));

if numel(descriptionLines) > 1
descriptionLines(2:end) = "% " + descriptionLines(2:end);
end

description = char(strjoin(descriptionLines, newline));
end

% Todo: Mostly duplicate code from file.fillProps. Should consolidate
function typeStr = getTypeStr(prop)
if ischar(prop)
Expand Down
50 changes: 50 additions & 0 deletions +tests/+sanity/GeneratedClassSmokeTest.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
classdef (SharedTestFixtures = {tests.fixtures.GenerateCoreFixture}) ...
GeneratedClassSmokeTest < matlab.unittest.TestCase

methods (Test)
function testGeneratedClassDefinitionsHaveMetaClasses(testCase)
typeClassNames = schemes.utility.listGeneratedTypes();
typesRoot = string(schemes.utility.findRootDirectoryForGeneratedTypes());
isClassDefinition = arrayfun( ...
@(className) startsWithGeneratedClassdef(typesRoot, className), ...
typeClassNames);
typeClassNames = typeClassNames(isClassDefinition);

testCase.verifyNotEmpty(typeClassNames, ...
'Expected generated neurodata type classes to be available.')

for i = 1:numel(typeClassNames)
typeClassName = typeClassNames(i);
typeClassNameAsChar = char(typeClassName);

try
metaClass = meta.class.fromName(typeClassNameAsChar);
catch ME
testCase.verifyFail(sprintf( ...
'Could not get metaclass for generated class "%s": %s', ...
typeClassNameAsChar, ME.message))
continue
end

testCase.verifyNotEmpty(metaClass, sprintf( ...
'Expected generated class "%s" to resolve to a metaclass.', ...
typeClassNameAsChar))

if ~isempty(metaClass)
testCase.verifyEqual(string(metaClass.Name), typeClassName)
end
end
end
end
end

function tf = startsWithGeneratedClassdef(typesRoot, typeClassName)
arguments
typesRoot (1,1) string
typeClassName (1,1) string
end

relativeFilePath = matnwb.common.internal.classname2path(typeClassName);
fileText = fileread(fullfile(typesRoot, relativeFilePath));
tf = startsWith(strtrim(fileText), "classdef");
end
2 changes: 1 addition & 1 deletion +types/+core/AbstractFeatureSeries.m
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
%
% - data (numeric) - Values of each feature at each time.
%
% - data_continuity (char) - Optionally describe the continuity of the data. Can be "continuous", "instantaneous", or "step". For example, a voltage trace would be "continuous", because samples are recorded from a continuous process. An array of lick times would be "instantaneous", because the data represents distinct moments in time. Times of image presentations would be "step" because the picture remains the same until the next timepoint. This field is optional, but is useful in providing information about the underlying data. It may inform the way this data is interpreted, the way it is visualized, and what analysis methods are applicable.
% - data_continuity (char) - Optionally describe the continuity of the data. Can be "continuous", "instantaneous", or "step". For example, a voltage trace would be "continuous", because samples are recorded from a continuous process. An array of lick times would be "instantaneous", because the data represents distinct moments in time. Times of image presentations would be "step" because the picture remains the same until the next timepoint. This field is optional, but is useful in providing information about the underlying data. It may inform the way this data is interpreted, the way it is visualized, and what analysis methods are applicable. For storing instantaneous event information, it is recommended to use an EventsTable instead of a TimeSeries with continuity set to "instantaneous".
%
% - data_conversion (single) - Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.
%
Expand Down
4 changes: 2 additions & 2 deletions +types/+core/AnnotationSeries.m
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
classdef AnnotationSeries < types.core.TimeSeries & types.untyped.GroupClass
% ANNOTATIONSERIES - Stores user annotations made during an experiment. The data[] field stores a text array, and timestamps are stored for each annotation (ie, interval=1). This is largely an alias to a standard TimeSeries storing a text array but that is identifiable as storing annotations in a machine-readable way.
% ANNOTATIONSERIES - DEPRECATED. Use an EventsTable instead. Stores user annotations made during an experiment. The data[] field stores a text array, and timestamps are stored for each annotation (ie, interval=1). This is largely an alias to a standard TimeSeries storing a text array but that is identifiable as storing annotations in a machine-readable way.
%
% Required Properties:
% data
Expand All @@ -24,7 +24,7 @@
%
% - data (char) - Annotations made during an experiment.
%
% - data_continuity (char) - Optionally describe the continuity of the data. Can be "continuous", "instantaneous", or "step". For example, a voltage trace would be "continuous", because samples are recorded from a continuous process. An array of lick times would be "instantaneous", because the data represents distinct moments in time. Times of image presentations would be "step" because the picture remains the same until the next timepoint. This field is optional, but is useful in providing information about the underlying data. It may inform the way this data is interpreted, the way it is visualized, and what analysis methods are applicable.
% - data_continuity (char) - Optionally describe the continuity of the data. Can be "continuous", "instantaneous", or "step". For example, a voltage trace would be "continuous", because samples are recorded from a continuous process. An array of lick times would be "instantaneous", because the data represents distinct moments in time. Times of image presentations would be "step" because the picture remains the same until the next timepoint. This field is optional, but is useful in providing information about the underlying data. It may inform the way this data is interpreted, the way it is visualized, and what analysis methods are applicable. For storing instantaneous event information, it is recommended to use an EventsTable instead of a TimeSeries with continuity set to "instantaneous".
%
% - data_conversion (single) - Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.
%
Expand Down
2 changes: 1 addition & 1 deletion +types/+core/BehavioralEvents.m
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
classdef BehavioralEvents < types.core.NWBDataInterface & types.untyped.GroupClass & matnwb.mixin.HasUnnamedGroups
% BEHAVIORALEVENTS - TimeSeries for storing behavioral events. See description of BehavioralEpochs for more details.
% BEHAVIORALEVENTS - DEPRECATED. Use an EventsTable instead. TimeSeries for storing behavioral events. See description of BehavioralEpochs for more details.
%
% Required Properties:
% timeseries
Expand Down
2 changes: 1 addition & 1 deletion +types/+core/CurrentClampSeries.m
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
%
% - data (numeric) - Recorded voltage.
%
% - data_continuity (char) - Optionally describe the continuity of the data. Can be "continuous", "instantaneous", or "step". For example, a voltage trace would be "continuous", because samples are recorded from a continuous process. An array of lick times would be "instantaneous", because the data represents distinct moments in time. Times of image presentations would be "step" because the picture remains the same until the next timepoint. This field is optional, but is useful in providing information about the underlying data. It may inform the way this data is interpreted, the way it is visualized, and what analysis methods are applicable.
% - data_continuity (char) - Optionally describe the continuity of the data. Can be "continuous", "instantaneous", or "step". For example, a voltage trace would be "continuous", because samples are recorded from a continuous process. An array of lick times would be "instantaneous", because the data represents distinct moments in time. Times of image presentations would be "step" because the picture remains the same until the next timepoint. This field is optional, but is useful in providing information about the underlying data. It may inform the way this data is interpreted, the way it is visualized, and what analysis methods are applicable. For storing instantaneous event information, it is recommended to use an EventsTable instead of a TimeSeries with continuity set to "instantaneous".
%
% - data_conversion (single) - Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.
%
Expand Down
2 changes: 1 addition & 1 deletion +types/+core/CurrentClampStimulusSeries.m
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
%
% - data (numeric) - Stimulus current applied.
%
% - data_continuity (char) - Optionally describe the continuity of the data. Can be "continuous", "instantaneous", or "step". For example, a voltage trace would be "continuous", because samples are recorded from a continuous process. An array of lick times would be "instantaneous", because the data represents distinct moments in time. Times of image presentations would be "step" because the picture remains the same until the next timepoint. This field is optional, but is useful in providing information about the underlying data. It may inform the way this data is interpreted, the way it is visualized, and what analysis methods are applicable.
% - data_continuity (char) - Optionally describe the continuity of the data. Can be "continuous", "instantaneous", or "step". For example, a voltage trace would be "continuous", because samples are recorded from a continuous process. An array of lick times would be "instantaneous", because the data represents distinct moments in time. Times of image presentations would be "step" because the picture remains the same until the next timepoint. This field is optional, but is useful in providing information about the underlying data. It may inform the way this data is interpreted, the way it is visualized, and what analysis methods are applicable. For storing instantaneous event information, it is recommended to use an EventsTable instead of a TimeSeries with continuity set to "instantaneous".
%
% - data_conversion (single) - Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.
%
Expand Down
2 changes: 1 addition & 1 deletion +types/+core/DecompositionSeries.m
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
%
% - data (numeric) - Data decomposed into frequency bands.
%
% - data_continuity (char) - Optionally describe the continuity of the data. Can be "continuous", "instantaneous", or "step". For example, a voltage trace would be "continuous", because samples are recorded from a continuous process. An array of lick times would be "instantaneous", because the data represents distinct moments in time. Times of image presentations would be "step" because the picture remains the same until the next timepoint. This field is optional, but is useful in providing information about the underlying data. It may inform the way this data is interpreted, the way it is visualized, and what analysis methods are applicable.
% - data_continuity (char) - Optionally describe the continuity of the data. Can be "continuous", "instantaneous", or "step". For example, a voltage trace would be "continuous", because samples are recorded from a continuous process. An array of lick times would be "instantaneous", because the data represents distinct moments in time. Times of image presentations would be "step" because the picture remains the same until the next timepoint. This field is optional, but is useful in providing information about the underlying data. It may inform the way this data is interpreted, the way it is visualized, and what analysis methods are applicable. For storing instantaneous event information, it is recommended to use an EventsTable instead of a TimeSeries with continuity set to "instantaneous".
%
% - data_conversion (single) - Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.
%
Expand Down
84 changes: 84 additions & 0 deletions +types/+core/DurationVectorData.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
classdef DurationVectorData < types.hdmf_common.VectorData & types.untyped.DatasetClass
% DURATIONVECTORDATA - A 1-dimensional VectorData that stores durations in seconds.
%
% Required Properties:
% data, description


% READONLY PROPERTIES
properties(SetAccess = protected)
unit = "seconds"; % (char) The unit of measurement for the durations, fixed to 'seconds'.
end
% OPTIONAL PROPERTIES
properties
resolution; % (single) The temporal resolution of the durations, in seconds. This is typically the sampling period (1 / sampling_rate), also known as the clock period, of the data acquisition system from which the durations were recorded or derived.
end

methods
function obj = DurationVectorData(varargin)
% DURATIONVECTORDATA - Constructor for DurationVectorData
%
% Syntax:
% durationVectorData = types.core.DURATIONVECTORDATA() creates a DurationVectorData object with unset property values.
%
% durationVectorData = types.core.DURATIONVECTORDATA(Name, Value) creates a DurationVectorData object where one or more property values are specified using name-value pairs.
%
% Input Arguments (Name-Value Arguments):
% - data (single) - Data property for dataset class (DurationVectorData)
%
% - description (char) - Description of what these vectors represent.
%
% - resolution (single) - The temporal resolution of the durations, in seconds. This is typically the sampling period (1 / sampling_rate), also known as the clock period, of the data acquisition system from which the durations were recorded or derived.
%
% Output Arguments:
% - durationVectorData (types.core.DurationVectorData) - A DurationVectorData object

varargin = [{'unit' 'seconds'} varargin];
obj = obj@types.hdmf_common.VectorData(varargin{:});


p = inputParser;
p.KeepUnmatched = true;
p.PartialMatching = false;
p.StructExpand = false;
addParameter(p, 'resolution',[]);
addParameter(p, 'unit',[]);
misc.parseSkipInvalidName(p, varargin);
obj.resolution = p.Results.resolution;
obj.unit = p.Results.unit;

% Only execute validation/setup code when called directly in this class's
% constructor, not when invoked through superclass constructor chain
if strcmp(class(obj), 'types.core.DurationVectorData') %#ok<STISA>
cellStringArguments = convertContainedStringsToChars(varargin(1:2:end));
types.util.checkUnset(obj, unique(cellStringArguments));
end
end
%% SETTERS
function set.resolution(obj, val)
obj.resolution = obj.validate_resolution(val);
end
%% VALIDATORS

function val = validate_data(obj, val)
val = types.util.checkDtype('data', 'single', val);
types.util.validateShape('data', {[Inf]}, val)
end
function val = validate_resolution(obj, val)
val = types.util.checkDtype('resolution', 'single', val);
types.util.validateShape('resolution', {[1]}, val)
end
%% EXPORT
function refs = export(obj, writer, fullpath, refs)
refs = export@types.hdmf_common.VectorData(obj, writer, fullpath, refs);
if any(strcmp(refs, fullpath))
return;
end
if ~isempty(obj.resolution)
writer.writeAttribute([fullpath '/resolution'], obj.resolution);
end
writer.writeAttribute([fullpath '/unit'], obj.unit);
end
end

end
Loading
Loading