From 2ddb6c3fa7662413491fab9551ab5af0893e3032 Mon Sep 17 00:00:00 2001 From: ehennestad Date: Tue, 19 May 2026 17:01:38 +0200 Subject: [PATCH 01/14] fix: remove VectorData unit generation patch --- +file/+internal/isPropertyHidden.m | 2 +- +file/fillClass.m | 2 +- +file/fillExport.m | 12 +----------- +file/processClass.m | 12 ------------ +tests/+unit/+file/VectorDataPatchTest.m | 20 ++++++++++++++++++++ 5 files changed, 23 insertions(+), 25 deletions(-) create mode 100644 +tests/+unit/+file/VectorDataPatchTest.m diff --git a/+file/+internal/isPropertyHidden.m b/+file/+internal/isPropertyHidden.m index c000810ab..0b8d5abef 100644 --- a/+file/+internal/isPropertyHidden.m +++ b/+file/+internal/isPropertyHidden.m @@ -4,7 +4,7 @@ if isa(propertyInfo, 'file.Attribute') || isa(propertyInfo, 'file.Dataset') if strcmp(namespace.name, 'hdmf_common') ... && strcmp(className, 'VectorData') ... - && any(strcmp(propertyInfo.name, {'unit', 'sampling_rate', 'resolution'})) + && any(strcmp(propertyInfo.name, {'sampling_rate', 'resolution'})) result = true; else result = false; diff --git a/+file/fillClass.m b/+file/fillClass.m index ad10e294f..b5a2587db 100644 --- a/+file/fillClass.m +++ b/+file/fillClass.m @@ -68,7 +68,7 @@ if strcmp(namespace.name, 'hdmf_common') ... && strcmp(name, 'VectorData') ... - && any(strcmp(prop.name, {'unit', 'sampling_rate', 'resolution'})) + && any(strcmp(prop.name, {'sampling_rate', 'resolution'})) hidden{end+1} = propertyName; end end diff --git a/+file/fillExport.m b/+file/fillExport.m index 87da582e2..98cd2ab97 100644 --- a/+file/fillExport.m +++ b/+file/fillExport.m @@ -38,9 +38,7 @@ needsElisionGroupWrite = ~isempty(elideProps) ... && all(cellfun('isclass', elideProps, 'file.Group')); - if strcmp(propertyName, 'unit') && strcmp(RawClass.type, 'VectorData') - exportBody{end+1} = fillVectorDataUnitConditional(); - elseif strcmp(propertyName, 'sampling_rate') && strcmp(RawClass.type, 'VectorData') + if strcmp(propertyName, 'sampling_rate') && strcmp(RawClass.type, 'VectorData') exportBody{end+1} = fillVectorDataSamplingRateConditional(); elseif strcmp(propertyName, 'resolution') && strcmp(RawClass.type, 'VectorData') exportBody{end+1} = fillVectorDataResolutionConditional(); @@ -63,14 +61,6 @@ , 'end'}, newline); end -function exportBody = fillVectorDataUnitConditional() - exportBody = strjoin({... - 'validUnitPaths = strcat(''units/'', {''waveform_mean'', ''waveform_sd'', ''waveforms''});' ... - , 'if ~isempty(obj.unit) && any(endsWith(fullpath, validUnitPaths))' ... - , ' writer.writeAttribute([fullpath ''/unit''], obj.unit);' ... - , 'end'}, newline); -end - function exportBody = fillVectorDataSamplingRateConditional() exportBody = strjoin({... 'validDataSamplingPaths = strcat(''units/'', {''waveform_mean'', ''waveform_sd'', ''waveforms''});' ... diff --git a/+file/processClass.m b/+file/processClass.m index 09a418d49..a7a4fea66 100644 --- a/+file/processClass.m +++ b/+file/processClass.m @@ -130,18 +130,6 @@ end function class = patchVectorData(class) - %% Unit Attribute - % derived from schema 2.6.0 - source = containers.Map(); - source('name') = 'unit'; - source('doc') = ['NOTE: this is a special value for compatibility with the Units table and is ' ... - 'only written to file when detected to be in that specific HDF5 Group. ' ... - 'The value must be ''volts''']; - source('dtype') = 'text'; - source('value') = 'volts'; - source('required') = false; - class.attributes(end+1) = file.Attribute(source); - %% Sampling Rate Attribute % derived from schema 2.6.0 diff --git a/+tests/+unit/+file/VectorDataPatchTest.m b/+tests/+unit/+file/VectorDataPatchTest.m new file mode 100644 index 000000000..ecdeb4795 --- /dev/null +++ b/+tests/+unit/+file/VectorDataPatchTest.m @@ -0,0 +1,20 @@ +classdef VectorDataPatchTest < tests.abstract.NwbTestCase + + methods (Test) + function testVectorDataUnitIsNotInjected(testCase) + vectorDataClass = ?types.hdmf_common.VectorData; + vectorDataPropertyNames = {vectorDataClass.PropertyList.Name}; + + testCase.verifyFalse(ismember('unit', vectorDataPropertyNames)) + testCase.verifyTrue(ismember('sampling_rate', vectorDataPropertyNames)) + testCase.verifyTrue(ismember('resolution', vectorDataPropertyNames)) + + unitsClass = ?types.core.Units; + unitsPropertyNames = {unitsClass.PropertyList.Name}; + + testCase.verifyTrue(ismember('waveform_mean_unit', unitsPropertyNames)) + testCase.verifyTrue(ismember('waveform_sd_unit', unitsPropertyNames)) + testCase.verifyTrue(ismember('waveforms_unit', unitsPropertyNames)) + end + end +end From b501a43864b03c26b0dd1084e0def7c255df0b7a Mon Sep 17 00:00:00 2001 From: ehennestad Date: Tue, 19 May 2026 17:23:55 +0200 Subject: [PATCH 02/14] Regenerate VectorData --- +types/+hdmf_common/VectorData.m | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/+types/+hdmf_common/VectorData.m b/+types/+hdmf_common/VectorData.m index 30ab16381..4758409c1 100644 --- a/+types/+hdmf_common/VectorData.m +++ b/+types/+hdmf_common/VectorData.m @@ -5,10 +5,6 @@ % data, description -% HIDDEN READONLY PROPERTIES -properties(Hidden, SetAccess = protected) - unit = "volts"; % (char) NOTE: this is a special value for compatibility with the Units table and is only written to file when detected to be in that specific HDF5 Group. The value must be 'volts' -end % HIDDEN PROPERTIES properties(Hidden) resolution; % (double) NOTE: this is a special value for compatibility with the Units table and is only written to file when detected to be in that specific HDF5 Group. The smallest possible difference between two spike times. Usually 1 divided by the acquisition sampling rate from which spike times were extracted, but could be larger if the acquisition time series was downsampled or smaller if the acquisition time series was smoothed/interpolated and it is possible for the spike time to be between samples. @@ -40,7 +36,6 @@ % Output Arguments: % - vectorData (types.hdmf_common.VectorData) - A VectorData object - varargin = [{'unit' 'volts'} varargin]; obj = obj@types.hdmf_common.Data(varargin{:}); @@ -51,12 +46,10 @@ addParameter(p, 'description',[]); addParameter(p, 'resolution',[]); addParameter(p, 'sampling_rate',[]); - addParameter(p, 'unit',[]); misc.parseSkipInvalidName(p, varargin); obj.description = p.Results.description; obj.resolution = p.Results.resolution; obj.sampling_rate = p.Results.sampling_rate; - 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 @@ -107,10 +100,6 @@ if ~isempty(obj.sampling_rate) && any(endsWith(fullpath, validDataSamplingPaths)) writer.writeAttribute([fullpath '/sampling_rate'], obj.sampling_rate); end - validUnitPaths = strcat('units/', {'waveform_mean', 'waveform_sd', 'waveforms'}); - if ~isempty(obj.unit) && any(endsWith(fullpath, validUnitPaths)) - writer.writeAttribute([fullpath '/unit'], obj.unit); - end end end From f3116cbf6cc5f99d0032c27547700aee4c3875cd Mon Sep 17 00:00:00 2001 From: ehennestad Date: Tue, 19 May 2026 17:45:27 +0200 Subject: [PATCH 03/14] fix: stop syncing promoted unit attributes --- +file/fillExport.m | 2 +- +file/fillSetters.m | 2 +- +tests/+unit/+file/VectorDataPatchTest.m | 11 +++++++++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/+file/fillExport.m b/+file/fillExport.m index 98cd2ab97..500920213 100644 --- a/+file/fillExport.m +++ b/+file/fillExport.m @@ -256,7 +256,7 @@ sprintf('obj.throwErrorIfRequiredDependencyMissing(''%s'', ''%s'', fullpath)', name, depPropname); end - if prop.promoted_to_container + if prop.promoted_to_container && ~strcmp(prop.name, 'unit') preExportString = sprintf([ ... 'if %s && %s && isobject(obj.%s) && isprop(obj.%s, ''%s'') && ~isempty(obj.%s.%s)\n' ... ' obj.%s = obj.%s.%s;\n' ... diff --git a/+file/fillSetters.m b/+file/fillSetters.m index 4a22de307..3f89accd2 100644 --- a/+file/fillSetters.m +++ b/+file/fillSetters.m @@ -46,7 +46,7 @@ propName, parentname); syncPromotedDatasetAttributeString = ''; - if prop.promoted_to_container + if prop.promoted_to_container && ~strcmp(prop.name, 'unit') syncPromotedDatasetAttributeString = sprintf([ ... 'if ~isempty(obj.%1$s) && isobject(obj.%1$s) && isprop(obj.%1$s, ''%2$s'')\n' ... ' if ~isempty(obj.%3$s)\n' ... diff --git a/+tests/+unit/+file/VectorDataPatchTest.m b/+tests/+unit/+file/VectorDataPatchTest.m index ecdeb4795..56c2256a5 100644 --- a/+tests/+unit/+file/VectorDataPatchTest.m +++ b/+tests/+unit/+file/VectorDataPatchTest.m @@ -16,5 +16,16 @@ function testVectorDataUnitIsNotInjected(testCase) testCase.verifyTrue(ismember('waveform_sd_unit', unitsPropertyNames)) testCase.verifyTrue(ismember('waveforms_unit', unitsPropertyNames)) end + + function testUnitsDoesNotSyncPromotedUnitAttributesFromVectorData(testCase) + unitsFile = fullfile( ... + testCase.getTypesOutputFolder(), ... + '+types', '+core', 'Units.m'); + unitsContents = string(fileread(unitsFile)); + + testCase.verifyFalse(contains(unitsContents, 'obj.waveform_mean.unit')) + testCase.verifyFalse(contains(unitsContents, 'obj.waveform_sd.unit')) + testCase.verifyFalse(contains(unitsContents, 'obj.waveforms.unit')) + end end end From 1e2fbbc229ef3bfb415f9f4f71fca4e9adc61686 Mon Sep 17 00:00:00 2001 From: ehennestad Date: Tue, 19 May 2026 17:59:37 +0200 Subject: [PATCH 04/14] Regenerate Units --- +types/+core/Units.m | 9 --------- 1 file changed, 9 deletions(-) diff --git a/+types/+core/Units.m b/+types/+core/Units.m index 5242017e6..27aeb8ae9 100644 --- a/+types/+core/Units.m +++ b/+types/+core/Units.m @@ -400,9 +400,6 @@ function postset_waveforms_sampling_rate(obj) if ~isempty(obj.waveform_mean) && ~isa(obj.waveform_mean, 'types.untyped.SoftLink') && ~isa(obj.waveform_mean, 'types.untyped.ExternalLink') && ~isempty(obj.waveform_mean_sampling_rate) writer.writeAttribute([fullpath '/waveform_mean/sampling_rate'], obj.waveform_mean_sampling_rate); end - if isempty(obj.waveform_mean_unit) && ~isempty(obj.waveform_mean) && isobject(obj.waveform_mean) && isprop(obj.waveform_mean, 'unit') && ~isempty(obj.waveform_mean.unit) - obj.waveform_mean_unit = obj.waveform_mean.unit; - end if ~isempty(obj.waveform_mean) && ~isa(obj.waveform_mean, 'types.untyped.SoftLink') && ~isa(obj.waveform_mean, 'types.untyped.ExternalLink') && ~isempty(obj.waveform_mean_unit) writer.writeAttribute([fullpath '/waveform_mean/unit'], obj.waveform_mean_unit); end @@ -415,9 +412,6 @@ function postset_waveforms_sampling_rate(obj) if ~isempty(obj.waveform_sd) && ~isa(obj.waveform_sd, 'types.untyped.SoftLink') && ~isa(obj.waveform_sd, 'types.untyped.ExternalLink') && ~isempty(obj.waveform_sd_sampling_rate) writer.writeAttribute([fullpath '/waveform_sd/sampling_rate'], obj.waveform_sd_sampling_rate); end - if isempty(obj.waveform_sd_unit) && ~isempty(obj.waveform_sd) && isobject(obj.waveform_sd) && isprop(obj.waveform_sd, 'unit') && ~isempty(obj.waveform_sd.unit) - obj.waveform_sd_unit = obj.waveform_sd.unit; - end if ~isempty(obj.waveform_sd) && ~isa(obj.waveform_sd, 'types.untyped.SoftLink') && ~isa(obj.waveform_sd, 'types.untyped.ExternalLink') && ~isempty(obj.waveform_sd_unit) writer.writeAttribute([fullpath '/waveform_sd/unit'], obj.waveform_sd_unit); end @@ -436,9 +430,6 @@ function postset_waveforms_sampling_rate(obj) if ~isempty(obj.waveforms) && ~isa(obj.waveforms, 'types.untyped.SoftLink') && ~isa(obj.waveforms, 'types.untyped.ExternalLink') && ~isempty(obj.waveforms_sampling_rate) writer.writeAttribute([fullpath '/waveforms/sampling_rate'], obj.waveforms_sampling_rate); end - if isempty(obj.waveforms_unit) && ~isempty(obj.waveforms) && isobject(obj.waveforms) && isprop(obj.waveforms, 'unit') && ~isempty(obj.waveforms.unit) - obj.waveforms_unit = obj.waveforms.unit; - end if ~isempty(obj.waveforms) && ~isa(obj.waveforms, 'types.untyped.SoftLink') && ~isa(obj.waveforms, 'types.untyped.ExternalLink') && ~isempty(obj.waveforms_unit) writer.writeAttribute([fullpath '/waveforms/unit'], obj.waveforms_unit); end From 04163f7470306ed793ba6d47da1e5e7b1985ec84 Mon Sep 17 00:00:00 2001 From: ehennestad Date: Sun, 31 May 2026 11:25:31 +0200 Subject: [PATCH 05/14] Remove hidden VectorData special props from code/type generation Remove the units, sampling_rate and resolution props from VectorData generation. Was added after nwb v2.6.0 as a workaround to support Units table properties where VectorData was reused by inclusion in addition to adding its own properties locally --- +file/fillExport.m | 37 +------------------------------------ +file/fillSetters.m | 15 --------------- +file/processClass.m | 36 +----------------------------------- 3 files changed, 2 insertions(+), 86 deletions(-) diff --git a/+file/fillExport.m b/+file/fillExport.m index 500920213..02f35caff 100644 --- a/+file/fillExport.m +++ b/+file/fillExport.m @@ -38,13 +38,7 @@ needsElisionGroupWrite = ~isempty(elideProps) ... && all(cellfun('isclass', elideProps, 'file.Group')); - if strcmp(propertyName, 'sampling_rate') && strcmp(RawClass.type, 'VectorData') - exportBody{end+1} = fillVectorDataSamplingRateConditional(); - elseif strcmp(propertyName, 'resolution') && strcmp(RawClass.type, 'VectorData') - exportBody{end+1} = fillVectorDataResolutionConditional(); - else - exportBody{end+1} = fillDataExport(propertyName, prop, elisions, required, needsElisionGroupWrite, classprops); - end + exportBody{end+1} = fillDataExport(propertyName, prop, elisions, required, needsElisionGroupWrite, classprops); end festr = strjoin({ ... @@ -54,21 +48,6 @@ }, newline); end -function exportBody = fillVectorDataResolutionConditional() - exportBody = strjoin({... - 'if ~isempty(obj.resolution) && any(endsWith(fullpath, ''units/spike_times''))' ... - , ' writer.writeAttribute([fullpath ''/resolution''], obj.resolution);' ... - , 'end'}, newline); -end - -function exportBody = fillVectorDataSamplingRateConditional() - exportBody = strjoin({... - 'validDataSamplingPaths = strcat(''units/'', {''waveform_mean'', ''waveform_sd'', ''waveforms''});' ... - , 'if ~isempty(obj.sampling_rate) && any(endsWith(fullpath, validDataSamplingPaths))' ... - , ' writer.writeAttribute([fullpath ''/sampling_rate''], obj.sampling_rate);' ... - , 'end'}, newline); -end - function path = traverseRaw(propertyName, RawClass) % returns a cell array of named tokens which may or may not indicate an identifier. % these tokens are relative to the Raw class @@ -255,16 +234,6 @@ warnIfMissingRequiredDependentAttributeStr = ... sprintf('obj.throwErrorIfRequiredDependencyMissing(''%s'', ''%s'', fullpath)', name, depPropname); end - - if prop.promoted_to_container && ~strcmp(prop.name, 'unit') - preExportString = sprintf([ ... - 'if %s && %s && isobject(obj.%s) && isprop(obj.%s, ''%s'') && ~isempty(obj.%s.%s)\n' ... - ' obj.%s = obj.%s.%s;\n' ... - 'end'], ... - isCurrentPropertyUnset, isDependentPropertySet, ... - depPropname, depPropname, prop.name, depPropname, prop.name, ... - name, depPropname, prop.name); - end end if ~prop.required @@ -292,10 +261,6 @@ end end - if ~isempty(preExportString) - dataExportString = sprintf('%s\n%s', preExportString, dataExportString); - end - if ~isempty(dependencyCheck) dataExportString = sprintf('%s\nif %s\n%s\nend', ... dataExportString, ... diff --git a/+file/fillSetters.m b/+file/fillSetters.m index 3f89accd2..0f18d022e 100644 --- a/+file/fillSetters.m +++ b/+file/fillSetters.m @@ -45,25 +45,10 @@ 'obj.warnIfAttributeDependencyMissing(''%s'', ''%s'')', ... propName, parentname); - syncPromotedDatasetAttributeString = ''; - if prop.promoted_to_container && ~strcmp(prop.name, 'unit') - syncPromotedDatasetAttributeString = sprintf([ ... - 'if ~isempty(obj.%1$s) && isobject(obj.%1$s) && isprop(obj.%1$s, ''%2$s'')\n' ... - ' if ~isempty(obj.%3$s)\n' ... - ' obj.%1$s.%2$s = obj.%3$s;\n' ... - ' elseif ~isempty(obj.%1$s.%2$s)\n' ... - ' obj.%3$s = obj.%1$s.%2$s;\n' ... - ' end\n' ... - 'end'], parentname, prop.name, propName); - end - postsetStatements = [postsetStatements, ... {conditionStr}, ... {file.addSpaces(warnIfDependencyMissingString, 4)}, ... {'end'}]; - if ~isempty(syncPromotedDatasetAttributeString) - postsetStatements{end+1} = syncPromotedDatasetAttributeString; - end end end diff --git a/+file/processClass.m b/+file/processClass.m index a7a4fea66..12f41592a 100644 --- a/+file/processClass.m +++ b/+file/processClass.m @@ -28,9 +28,7 @@ error('NWB:FileGen:InvalidClassType',... 'Class type %s is invalid', node('class_type')); end - if strcmp(nodename, 'VectorData') && strcmp(namespace.name, 'hdmf_common') - class = patchVectorData(class); - end + props = class.getProps(); props = markPromotedAttributesForIncludedTypedDatasets(class, props, namespace); @@ -128,35 +126,3 @@ attributeNames = propNames(isAttribute); schemaAttributeNameCache(cacheKey) = attributeNames; end - -function class = patchVectorData(class) - %% Sampling Rate Attribute - % derived from schema 2.6.0 - - source = containers.Map(); - source('name') = 'sampling_rate'; - source('doc') = ['NOTE: this is a special value for compatibility with the Units table and is ' ... - 'only written to file when detected to be in that specific HDF5 Group. ' ... - 'Must be Hertz']; - source('dtype') = 'float32'; - source('required') = false; - - class.attributes(end+1) = file.Attribute(source); - %% Resolution Attribute - % derived from schema 2.6.0 - - source = containers.Map(); - source('name') = 'resolution'; - source('doc') = ['NOTE: this is a special value for compatibility with the Units table and is ' ... - 'only written to file when detected to be in that specific HDF5 Group. ' ... - 'The smallest possible difference between two spike times. ' ... - 'Usually 1 divided by the acquisition sampling rate from which spike times were extracted, ' ... - 'but could be larger if the acquisition time series was downsampled or smaller if the ' ... - 'acquisition time series was smoothed/interpolated ' ... - 'and it is possible for the spike time to be between samples.' ... - ]; - source('dtype') = 'float64'; - source('required') = false; - - class.attributes(end+1) = file.Attribute(source); -end From e4a2dd68fdf1a5f142c378defd8a71aeba8743c0 Mon Sep 17 00:00:00 2001 From: ehennestad Date: Sun, 31 May 2026 11:31:27 +0200 Subject: [PATCH 06/14] Remove internal helper checking for Hidden properties --- +file/+internal/isPropertyHidden.m | 15 --------------- +schemes/+internal/getRequiredPropsForClass.m | 5 ++--- 2 files changed, 2 insertions(+), 18 deletions(-) delete mode 100644 +file/+internal/isPropertyHidden.m diff --git a/+file/+internal/isPropertyHidden.m b/+file/+internal/isPropertyHidden.m deleted file mode 100644 index 0b8d5abef..000000000 --- a/+file/+internal/isPropertyHidden.m +++ /dev/null @@ -1,15 +0,0 @@ -function result = isPropertyHidden(propertyInfo, className, namespace) -% isPropertyHidden - Determine if a property is hidden - - if isa(propertyInfo, 'file.Attribute') || isa(propertyInfo, 'file.Dataset') - if strcmp(namespace.name, 'hdmf_common') ... - && strcmp(className, 'VectorData') ... - && any(strcmp(propertyInfo.name, {'sampling_rate', 'resolution'})) - result = true; - else - result = false; - end - else - result = false; - end -end diff --git a/+schemes/+internal/getRequiredPropsForClass.m b/+schemes/+internal/getRequiredPropsForClass.m index 5d6111834..da6304d25 100644 --- a/+schemes/+internal/getRequiredPropsForClass.m +++ b/+schemes/+internal/getRequiredPropsForClass.m @@ -37,15 +37,14 @@ % Resolve the required properties. For the final list of required properties, % we ignore both hidden and read-only properties. allPropertieNames = keys(classprops); - [isRequired, isReadOnly, isHidden] = deal( false(1, classprops.Count) ); + [isRequired, isReadOnly] = deal( false(1, classprops.Count) ); for iProp = 1:length(allPropertieNames) propertyName = allPropertieNames{iProp}; prop = classprops(propertyName); isRequired(iProp) = file.internal.isPropertyRequired(prop, propertyName, classprops); isReadOnly(iProp) = file.internal.isPropertyReadonly(prop); - isHidden(iProp) = file.internal.isPropertyHidden(prop, className, namespace); end - requiredPropertyNames = allPropertieNames(isRequired & ~isReadOnly & ~isHidden); + requiredPropertyNames = allPropertieNames(isRequired & ~isReadOnly); end From ca31168e92d312279c64d3d734ca4ded14f746c4 Mon Sep 17 00:00:00 2001 From: ehennestad Date: Sun, 31 May 2026 11:40:04 +0200 Subject: [PATCH 07/14] Remove logic for hiding properties in type generator The hidden attribute for properties was only applied to properties that were hardcoded to support the VectorData workaround --- +file/fillClass.m | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/+file/fillClass.m b/+file/fillClass.m index b5a2587db..cd5c7dad1 100644 --- a/+file/fillClass.m +++ b/+file/fillClass.m @@ -11,7 +11,6 @@ readonly = {}; defaults = {}; dependent = {}; - hidden = {}; % special hidden properties for hard-coded workarounds %separate into readonly, required, and optional properties for iGroup = 1:length(allProperties) @@ -65,19 +64,12 @@ dependent = [dependent {propertyName}]; end end - - if strcmp(namespace.name, 'hdmf_common') ... - && strcmp(name, 'VectorData') ... - && any(strcmp(prop.name, {'sampling_rate', 'resolution'})) - hidden{end+1} = propertyName; - end end end nonInherited = setdiff(allProperties, inherited); readonly = intersect(readonly, nonInherited); - exclusivePropertyGroups = union(readonly, hidden); - required = setdiff(intersect(required, nonInherited), exclusivePropertyGroups); - optional = setdiff(intersect(optional, nonInherited), exclusivePropertyGroups); + required = intersect(required, nonInherited); + optional = intersect(optional, nonInherited); %% CLASSDEF superclassNames = {}; @@ -115,20 +107,13 @@ '% Required Properties:', newline, ... sprintf('%% %s', strjoin(allRequiredPropertyNames, ', '))]; - hiddenAndReadonly = intersect(hidden, readonly); - hidden = setdiff(hidden, hiddenAndReadonly); - readonly = setdiff(readonly, hiddenAndReadonly); PropertyGroups = struct(... 'Function', {... - @()file.fillProps(classprops, hiddenAndReadonly, 'PropertyAttributes', 'Hidden, SetAccess = protected') ... - , @()file.fillProps(classprops, hidden, 'PropertyAttributes', 'Hidden') ... , @()file.fillProps(classprops, readonly, 'PropertyAttributes', 'SetAccess = protected') ... , @()file.fillProps(classprops, required, 'IsRequired', true) ... , @()file.fillProps(classprops, optional)... } ... , 'Separator', { ... - '% HIDDEN READONLY PROPERTIES' ... - , '% HIDDEN PROPERTIES' ... , '% READONLY PROPERTIES' ... , '% REQUIRED PROPERTIES' ... , '% OPTIONAL PROPERTIES' ... @@ -165,7 +150,7 @@ class, ... inherited); setterFcns = file.fillSetters( ... - setdiff(nonInherited, union(readonly, hiddenAndReadonly)), ... + setdiff(nonInherited, readonly), ... classprops, ... name, ... namespace); From 9a63a6bcb51baa8efd04ee05d8e7a3fc43d750e7 Mon Sep 17 00:00:00 2001 From: ehennestad Date: Sun, 31 May 2026 11:41:33 +0200 Subject: [PATCH 08/14] Remove unused promoted_to_container property of file.Attribute class --- +file/Attribute.m | 2 -- +file/processClass.m | 4 ---- 2 files changed, 6 deletions(-) diff --git a/+file/Attribute.m b/+file/Attribute.m index 2319daafc..90df92642 100644 --- a/+file/Attribute.m +++ b/+file/Attribute.m @@ -8,7 +8,6 @@ dtype; %type of value dependent; %set externally. If the attribute is actually dependent on an untyped dataset/group dependent_fullname; %set externally. This is the full name, including names of potential parent groups separated by underscore. A value will only be present if it would differ from dependent. - promoted_to_container = false; % set externally when promoted from a typed dataset onto the containing class API scalar; %if the value is scalar or an array dimnames; shape; @@ -26,7 +25,6 @@ obj.dtype = ''; obj.dependent = ''; obj.dependent_fullname = ''; - obj.promoted_to_container = false; obj.scalar = true; obj.shape = {}; obj.dimnames = {}; diff --git a/+file/processClass.m b/+file/processClass.m index 12f41592a..d6771181b 100644 --- a/+file/processClass.m +++ b/+file/processClass.m @@ -78,10 +78,6 @@ if any(strcmp(attribute.name, schemaAttributeNames)) remove(props, propertyName); - else - promotedAttribute = props(propertyName); - promotedAttribute.promoted_to_container = true; - props(propertyName) = promotedAttribute; end end end From 1e250c4a3ec88760226c863fd81c382a5b0e6863 Mon Sep 17 00:00:00 2001 From: ehennestad Date: Sun, 31 May 2026 11:48:35 +0200 Subject: [PATCH 09/14] Fix introduced syntax errors in file.fillClass --- +file/fillClass.m | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/+file/fillClass.m b/+file/fillClass.m index cd5c7dad1..daf26500f 100644 --- a/+file/fillClass.m +++ b/+file/fillClass.m @@ -108,17 +108,17 @@ sprintf('%% %s', strjoin(allRequiredPropertyNames, ', '))]; PropertyGroups = struct(... - 'Function', {... - , @()file.fillProps(classprops, readonly, 'PropertyAttributes', 'SetAccess = protected') ... - , @()file.fillProps(classprops, required, 'IsRequired', true) ... - , @()file.fillProps(classprops, optional)... + 'Function', { ... + @()file.fillProps(classprops, readonly, 'PropertyAttributes', 'SetAccess = protected'), ... + @()file.fillProps(classprops, required, 'IsRequired', true), ... + @()file.fillProps(classprops, optional)... + }, ... + 'Separator', { ... + '% READONLY PROPERTIES', ... + '% REQUIRED PROPERTIES', ... + '% OPTIONAL PROPERTIES' ... } ... - , 'Separator', { ... - , '% READONLY PROPERTIES' ... - , '% REQUIRED PROPERTIES' ... - , '% OPTIONAL PROPERTIES' ... - } ... - ); + ); fullPropertyDefinition = ''; for iGroup = 1:length(PropertyGroups) From 5bedf730106fabf500dda2447e98034f99310ed7 Mon Sep 17 00:00:00 2001 From: ehennestad Date: Sun, 31 May 2026 12:10:29 +0200 Subject: [PATCH 10/14] Fix fileClass: exclude readonly properties from required/optional blocks Previous commit removed too much --- +file/fillClass.m | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/+file/fillClass.m b/+file/fillClass.m index daf26500f..a00d8f2bd 100644 --- a/+file/fillClass.m +++ b/+file/fillClass.m @@ -66,10 +66,16 @@ end end end + + % Each property is emitted in exactly one properties block, with readonly + % taking precedence over required/optional. Restrict each bucket to + % non-inherited names and remove anything already going into the readonly + % block to avoid duplicate property declarations. nonInherited = setdiff(allProperties, inherited); readonly = intersect(readonly, nonInherited); - required = intersect(required, nonInherited); - optional = intersect(optional, nonInherited); + settable = setdiff(nonInherited, readonly); % what's left for required/optional + required = intersect(required, settable); + optional = intersect(optional, settable); %% CLASSDEF superclassNames = {}; From 4ebb45c546b99ae7d0ac82aa754f07a231d9f9df Mon Sep 17 00:00:00 2001 From: ehennestad Date: Sun, 31 May 2026 12:10:39 +0200 Subject: [PATCH 11/14] Regenerate types --- +types/+core/Units.m | 40 ------------------------ +types/+hdmf_common/DynamicTableRegion.m | 4 --- +types/+hdmf_common/VectorData.m | 34 -------------------- +types/+hdmf_common/VectorIndex.m | 4 --- 4 files changed, 82 deletions(-) diff --git a/+types/+core/Units.m b/+types/+core/Units.m index 27aeb8ae9..607e02b26 100644 --- a/+types/+core/Units.m +++ b/+types/+core/Units.m @@ -186,13 +186,6 @@ function postset_spike_times_resolution(obj) if isempty(obj.spike_times) && ~isempty(obj.spike_times_resolution) obj.warnIfAttributeDependencyMissing('spike_times_resolution', 'spike_times') end - if ~isempty(obj.spike_times) && isobject(obj.spike_times) && isprop(obj.spike_times, 'resolution') - if ~isempty(obj.spike_times_resolution) - obj.spike_times.resolution = obj.spike_times_resolution; - elseif ~isempty(obj.spike_times.resolution) - obj.spike_times_resolution = obj.spike_times.resolution; - end - end end function set.waveform_mean(obj, val) obj.waveform_mean = obj.validate_waveform_mean(val); @@ -209,13 +202,6 @@ function postset_waveform_mean_sampling_rate(obj) if isempty(obj.waveform_mean) && ~isempty(obj.waveform_mean_sampling_rate) obj.warnIfAttributeDependencyMissing('waveform_mean_sampling_rate', 'waveform_mean') end - if ~isempty(obj.waveform_mean) && isobject(obj.waveform_mean) && isprop(obj.waveform_mean, 'sampling_rate') - if ~isempty(obj.waveform_mean_sampling_rate) - obj.waveform_mean.sampling_rate = obj.waveform_mean_sampling_rate; - elseif ~isempty(obj.waveform_mean.sampling_rate) - obj.waveform_mean_sampling_rate = obj.waveform_mean.sampling_rate; - end - end end function set.waveform_sd(obj, val) obj.waveform_sd = obj.validate_waveform_sd(val); @@ -232,13 +218,6 @@ function postset_waveform_sd_sampling_rate(obj) if isempty(obj.waveform_sd) && ~isempty(obj.waveform_sd_sampling_rate) obj.warnIfAttributeDependencyMissing('waveform_sd_sampling_rate', 'waveform_sd') end - if ~isempty(obj.waveform_sd) && isobject(obj.waveform_sd) && isprop(obj.waveform_sd, 'sampling_rate') - if ~isempty(obj.waveform_sd_sampling_rate) - obj.waveform_sd.sampling_rate = obj.waveform_sd_sampling_rate; - elseif ~isempty(obj.waveform_sd.sampling_rate) - obj.waveform_sd_sampling_rate = obj.waveform_sd.sampling_rate; - end - end end function set.waveforms(obj, val) obj.waveforms = obj.validate_waveforms(val); @@ -261,13 +240,6 @@ function postset_waveforms_sampling_rate(obj) if isempty(obj.waveforms) && ~isempty(obj.waveforms_sampling_rate) obj.warnIfAttributeDependencyMissing('waveforms_sampling_rate', 'waveforms') end - if ~isempty(obj.waveforms) && isobject(obj.waveforms) && isprop(obj.waveforms, 'sampling_rate') - if ~isempty(obj.waveforms_sampling_rate) - obj.waveforms.sampling_rate = obj.waveforms_sampling_rate; - elseif ~isempty(obj.waveforms.sampling_rate) - obj.waveforms_sampling_rate = obj.waveforms.sampling_rate; - end - end end %% VALIDATORS @@ -385,18 +357,12 @@ function postset_waveforms_sampling_rate(obj) if ~isempty(obj.spike_times_index) refs = obj.spike_times_index.export(writer, [fullpath '/spike_times_index'], refs); end - if isempty(obj.spike_times_resolution) && ~isempty(obj.spike_times) && isobject(obj.spike_times) && isprop(obj.spike_times, 'resolution') && ~isempty(obj.spike_times.resolution) - obj.spike_times_resolution = obj.spike_times.resolution; - end if ~isempty(obj.spike_times) && ~isa(obj.spike_times, 'types.untyped.SoftLink') && ~isa(obj.spike_times, 'types.untyped.ExternalLink') && ~isempty(obj.spike_times_resolution) writer.writeAttribute([fullpath '/spike_times/resolution'], obj.spike_times_resolution); end if ~isempty(obj.waveform_mean) refs = obj.waveform_mean.export(writer, [fullpath '/waveform_mean'], refs); end - if isempty(obj.waveform_mean_sampling_rate) && ~isempty(obj.waveform_mean) && isobject(obj.waveform_mean) && isprop(obj.waveform_mean, 'sampling_rate') && ~isempty(obj.waveform_mean.sampling_rate) - obj.waveform_mean_sampling_rate = obj.waveform_mean.sampling_rate; - end if ~isempty(obj.waveform_mean) && ~isa(obj.waveform_mean, 'types.untyped.SoftLink') && ~isa(obj.waveform_mean, 'types.untyped.ExternalLink') && ~isempty(obj.waveform_mean_sampling_rate) writer.writeAttribute([fullpath '/waveform_mean/sampling_rate'], obj.waveform_mean_sampling_rate); end @@ -406,9 +372,6 @@ function postset_waveforms_sampling_rate(obj) if ~isempty(obj.waveform_sd) refs = obj.waveform_sd.export(writer, [fullpath '/waveform_sd'], refs); end - if isempty(obj.waveform_sd_sampling_rate) && ~isempty(obj.waveform_sd) && isobject(obj.waveform_sd) && isprop(obj.waveform_sd, 'sampling_rate') && ~isempty(obj.waveform_sd.sampling_rate) - obj.waveform_sd_sampling_rate = obj.waveform_sd.sampling_rate; - end if ~isempty(obj.waveform_sd) && ~isa(obj.waveform_sd, 'types.untyped.SoftLink') && ~isa(obj.waveform_sd, 'types.untyped.ExternalLink') && ~isempty(obj.waveform_sd_sampling_rate) writer.writeAttribute([fullpath '/waveform_sd/sampling_rate'], obj.waveform_sd_sampling_rate); end @@ -424,9 +387,6 @@ function postset_waveforms_sampling_rate(obj) if ~isempty(obj.waveforms_index_index) refs = obj.waveforms_index_index.export(writer, [fullpath '/waveforms_index_index'], refs); end - if isempty(obj.waveforms_sampling_rate) && ~isempty(obj.waveforms) && isobject(obj.waveforms) && isprop(obj.waveforms, 'sampling_rate') && ~isempty(obj.waveforms.sampling_rate) - obj.waveforms_sampling_rate = obj.waveforms.sampling_rate; - end if ~isempty(obj.waveforms) && ~isa(obj.waveforms, 'types.untyped.SoftLink') && ~isa(obj.waveforms, 'types.untyped.ExternalLink') && ~isempty(obj.waveforms_sampling_rate) writer.writeAttribute([fullpath '/waveforms/sampling_rate'], obj.waveforms_sampling_rate); end diff --git a/+types/+hdmf_common/DynamicTableRegion.m b/+types/+hdmf_common/DynamicTableRegion.m index 3c2127a9c..457276a1b 100644 --- a/+types/+hdmf_common/DynamicTableRegion.m +++ b/+types/+hdmf_common/DynamicTableRegion.m @@ -24,10 +24,6 @@ % % - description (char) - Description of what this table region points to. % - % - resolution (double) - NOTE: this is a special value for compatibility with the Units table and is only written to file when detected to be in that specific HDF5 Group. The smallest possible difference between two spike times. Usually 1 divided by the acquisition sampling rate from which spike times were extracted, but could be larger if the acquisition time series was downsampled or smaller if the acquisition time series was smoothed/interpolated and it is possible for the spike time to be between samples. - % - % - sampling_rate (single) - NOTE: this is a special value for compatibility with the Units table and is only written to file when detected to be in that specific HDF5 Group. Must be Hertz - % % - table (Object reference to DynamicTable) - Reference to the DynamicTable object that this region applies to. % % Output Arguments: diff --git a/+types/+hdmf_common/VectorData.m b/+types/+hdmf_common/VectorData.m index 4758409c1..c84f4307a 100644 --- a/+types/+hdmf_common/VectorData.m +++ b/+types/+hdmf_common/VectorData.m @@ -5,11 +5,6 @@ % data, description -% HIDDEN PROPERTIES -properties(Hidden) - resolution; % (double) NOTE: this is a special value for compatibility with the Units table and is only written to file when detected to be in that specific HDF5 Group. The smallest possible difference between two spike times. Usually 1 divided by the acquisition sampling rate from which spike times were extracted, but could be larger if the acquisition time series was downsampled or smaller if the acquisition time series was smoothed/interpolated and it is possible for the spike time to be between samples. - sampling_rate; % (single) NOTE: this is a special value for compatibility with the Units table and is only written to file when detected to be in that specific HDF5 Group. Must be Hertz -end % REQUIRED PROPERTIES properties description; % REQUIRED (char) Description of what these vectors represent. @@ -29,10 +24,6 @@ % % - description (char) - Description of what these vectors represent. % - % - resolution (double) - NOTE: this is a special value for compatibility with the Units table and is only written to file when detected to be in that specific HDF5 Group. The smallest possible difference between two spike times. Usually 1 divided by the acquisition sampling rate from which spike times were extracted, but could be larger if the acquisition time series was downsampled or smaller if the acquisition time series was smoothed/interpolated and it is possible for the spike time to be between samples. - % - % - sampling_rate (single) - NOTE: this is a special value for compatibility with the Units table and is only written to file when detected to be in that specific HDF5 Group. Must be Hertz - % % Output Arguments: % - vectorData (types.hdmf_common.VectorData) - A VectorData object @@ -44,12 +35,8 @@ p.PartialMatching = false; p.StructExpand = false; addParameter(p, 'description',[]); - addParameter(p, 'resolution',[]); - addParameter(p, 'sampling_rate',[]); misc.parseSkipInvalidName(p, varargin); obj.description = p.Results.description; - obj.resolution = p.Results.resolution; - obj.sampling_rate = p.Results.sampling_rate; % Only execute validation/setup code when called directly in this class's % constructor, not when invoked through superclass constructor chain @@ -62,12 +49,6 @@ function set.description(obj, val) obj.description = obj.validate_description(val); end - function set.resolution(obj, val) - obj.resolution = obj.validate_resolution(val); - end - function set.sampling_rate(obj, val) - obj.sampling_rate = obj.validate_sampling_rate(val); - end %% VALIDATORS function val = validate_data(obj, val) @@ -78,14 +59,6 @@ val = types.util.checkDtype('description', 'char', val); types.util.validateShape('description', {[1]}, val) end - function val = validate_resolution(obj, val) - val = types.util.checkDtype('resolution', 'double', val); - types.util.validateShape('resolution', {[1]}, val) - end - function val = validate_sampling_rate(obj, val) - val = types.util.checkDtype('sampling_rate', 'single', val); - types.util.validateShape('sampling_rate', {[1]}, val) - end %% EXPORT function refs = export(obj, writer, fullpath, refs) refs = export@types.hdmf_common.Data(obj, writer, fullpath, refs); @@ -93,13 +66,6 @@ return; end writer.writeAttribute([fullpath '/description'], obj.description); - if ~isempty(obj.resolution) && any(endsWith(fullpath, 'units/spike_times')) - writer.writeAttribute([fullpath '/resolution'], obj.resolution); - end - validDataSamplingPaths = strcat('units/', {'waveform_mean', 'waveform_sd', 'waveforms'}); - if ~isempty(obj.sampling_rate) && any(endsWith(fullpath, validDataSamplingPaths)) - writer.writeAttribute([fullpath '/sampling_rate'], obj.sampling_rate); - end end end diff --git a/+types/+hdmf_common/VectorIndex.m b/+types/+hdmf_common/VectorIndex.m index c26d7d2d8..c72782ab8 100644 --- a/+types/+hdmf_common/VectorIndex.m +++ b/+types/+hdmf_common/VectorIndex.m @@ -24,10 +24,6 @@ % % - description (char) - Description of what these vectors represent. % - % - resolution (double) - NOTE: this is a special value for compatibility with the Units table and is only written to file when detected to be in that specific HDF5 Group. The smallest possible difference between two spike times. Usually 1 divided by the acquisition sampling rate from which spike times were extracted, but could be larger if the acquisition time series was downsampled or smaller if the acquisition time series was smoothed/interpolated and it is possible for the spike time to be between samples. - % - % - sampling_rate (single) - NOTE: this is a special value for compatibility with the Units table and is only written to file when detected to be in that specific HDF5 Group. Must be Hertz - % % - target (Object reference to VectorData) - Reference to the target dataset that this index applies to. % % Output Arguments: From fb1f35f31f6de1bd8056ee3ed2b9fd7706d93049 Mon Sep 17 00:00:00 2001 From: ehennestad Date: Sun, 31 May 2026 12:16:40 +0200 Subject: [PATCH 12/14] Fix tests that break after removing the hidden vectordata props --- +tests/+system/UnitTimesIOTest.m | 17 ----------------- +tests/+unit/+file/VectorDataPatchTest.m | 4 ++-- 2 files changed, 2 insertions(+), 19 deletions(-) diff --git a/+tests/+system/UnitTimesIOTest.m b/+tests/+system/UnitTimesIOTest.m index 3a87b4e24..12ab205df 100644 --- a/+tests/+system/UnitTimesIOTest.m +++ b/+tests/+system/UnitTimesIOTest.m @@ -54,21 +54,4 @@ function addContainer(~, file) c = file.units; end end - - methods (Test) - function testLegacyNestedSpikeTimesResolutionIsPreserved(testCase) - spikeTimes = types.hdmf_common.VectorData( ... - 'data', 11, ... - 'description', 'the spike times for each unit in seconds'); - spikeTimes.resolution = 1/20000; - - units = types.core.Units( ... - 'colnames', {'spike_times'}, ... - 'description', 'data on spiking units', ... - 'spike_times', spikeTimes); - - testCase.verifyEqual(units.spike_times.resolution, 1/20000); - testCase.verifyEqual(units.spike_times_resolution, 1/20000); - end - end end diff --git a/+tests/+unit/+file/VectorDataPatchTest.m b/+tests/+unit/+file/VectorDataPatchTest.m index 56c2256a5..6bf53bbbe 100644 --- a/+tests/+unit/+file/VectorDataPatchTest.m +++ b/+tests/+unit/+file/VectorDataPatchTest.m @@ -6,8 +6,8 @@ function testVectorDataUnitIsNotInjected(testCase) vectorDataPropertyNames = {vectorDataClass.PropertyList.Name}; testCase.verifyFalse(ismember('unit', vectorDataPropertyNames)) - testCase.verifyTrue(ismember('sampling_rate', vectorDataPropertyNames)) - testCase.verifyTrue(ismember('resolution', vectorDataPropertyNames)) + testCase.verifyFalse(ismember('sampling_rate', vectorDataPropertyNames)) + testCase.verifyFalse(ismember('resolution', vectorDataPropertyNames)) unitsClass = ?types.core.Units; unitsPropertyNames = {unitsClass.PropertyList.Name}; From 1058d0ca5b2791662f4cc49e9bb7341be35ecf6b Mon Sep 17 00:00:00 2001 From: ehennestad Date: Sun, 31 May 2026 12:48:09 +0200 Subject: [PATCH 13/14] Update ecephys.mlx --- tutorials/ecephys.mlx | Bin 360796 -> 360802 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/tutorials/ecephys.mlx b/tutorials/ecephys.mlx index f111adfdc7e2890456e4403fd5f74680ccf6e0ca..bf0fa0f1fb7c55f4ac1b9f9b52c587fa97ba0af9 100644 GIT binary patch delta 15817 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 From d0eb1b2c1961d3aaab7c3eb285551b81b31e2669 Mon Sep 17 00:00:00 2001 From: ehennestad Date: Sun, 31 May 2026 12:52:24 +0200 Subject: [PATCH 14/14] Update ecephys tutorial: set `spike_times_resolution` on Units construction --- tutorials/ecephys.mlx | Bin 360802 -> 360761 bytes tutorials/private/mcode/ecephys.m | 5 +++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/tutorials/ecephys.mlx b/tutorials/ecephys.mlx index bf0fa0f1fb7c55f4ac1b9f9b52c587fa97ba0af9..526df08b3d586f47eafadaf7f214889b141a5775 100644 GIT binary patch delta 12561 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 delta 12623 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 diff --git a/tutorials/private/mcode/ecephys.m b/tutorials/private/mcode/ecephys.m index 5879aeb67..a7b87c29b 100644 --- a/tutorials/private/mcode/ecephys.m +++ b/tutorials/private/mcode/ecephys.m @@ -306,13 +306,14 @@ % [spike_times_vector, spike_times_index] = util.create_indexed_column(spike_times); -spike_times_vector.resolution = 1/20000; % If original sampling rate was 20 kHz +spike_times_resolution = 1/20000; % If original sampling rate was 20 kHz nwb.units = types.core.Units( ... 'colnames', {'spike_times'}, ... 'description', 'units table', ... 'spike_times', spike_times_vector, ... - 'spike_times_index', spike_times_index ... + 'spike_times_index', spike_times_index, ... + 'spike_times_resolution', spike_times_resolution ... ); nwb.units.toTable()