From 1d6dd74ad81cfba9ea94fd8eea26d6cbe13e7d2a Mon Sep 17 00:00:00 2001 From: ehennestad Date: Wed, 27 Nov 2024 23:02:00 +0100 Subject: [PATCH] Fix: Make inherited read-only datasets in schema read-only properties in matnwb --- +file/Attribute.m | 2 +- +file/Dataset.m | 19 ++++++++++++ +file/fillClass.m | 12 ++++++-- +file/fillValidators.m | 4 +-- +types/+core/IZeroClampSeries.m | 53 +++++++-------------------------- 5 files changed, 41 insertions(+), 49 deletions(-) diff --git a/+file/Attribute.m b/+file/Attribute.m index e465429b..3131d3ae 100644 --- a/+file/Attribute.m +++ b/+file/Attribute.m @@ -48,7 +48,7 @@ else obj.value = []; obj.readonly = false; - end + end if isKey(source, 'dims') obj.dimnames = source('dims'); diff --git a/+file/Dataset.m b/+file/Dataset.m index ff3a3323..80b7e94c 100644 --- a/+file/Dataset.m +++ b/+file/Dataset.m @@ -6,6 +6,8 @@ dtype; isConstrainedSet; required; + value; + readonly; %determines whether value can be changed or not scalar; shape; dimnames; @@ -22,12 +24,15 @@ obj.type = ''; obj.dtype = 'any'; obj.required = true; + obj.value = []; + obj.readonly = false; obj.scalar = true; obj.definesType = false; obj.shape = {}; obj.dimnames = {}; obj.attributes = []; + if nargin < 1 return; @@ -42,6 +47,20 @@ if isKey(source, nameKey) obj.name = source(nameKey); end + + % Todo: same as for attribute, should consolidate + valueKey = 'value'; + defaultKey = 'default_value'; + if isKey(source, defaultKey) + obj.value = source(defaultKey); + obj.readonly = false; + elseif isKey(source, valueKey) + obj.value = source(valueKey); + obj.readonly = true; + else + obj.value = []; + obj.readonly = false; + end typeKeys = {'neurodata_type_def', 'data_type_def'}; parentKeys = {'neurodata_type_inc', 'data_type_inc'}; diff --git a/+file/fillClass.m b/+file/fillClass.m index 2f4c48eb..58723bfd 100644 --- a/+file/fillClass.m +++ b/+file/fillClass.m @@ -33,16 +33,22 @@ optional = [optional {propertyName}]; end - if isa(prop, 'file.Attribute') + if isa(prop, 'file.Attribute') || isa(prop, 'file.Dataset') if prop.readonly readonly = [readonly {propertyName}]; end if ~isempty(prop.value) - defaults = [defaults {propertyName}]; + if isa(prop, 'file.Attribute') + defaults = [defaults {propertyName}]; + else % file.Dataset + if isRequired || all(isPropertyRequired) + defaults = [defaults {propertyName}]; + end + end end - if ~isempty(prop.dependent) + if isa(prop, 'file.Attribute') && ~isempty(prop.dependent) %extract prefix parentName = strrep(propertyName, ['_' prop.name], ''); parent = classprops(parentName); diff --git a/+file/fillValidators.m b/+file/fillValidators.m index 57d474e7..ebd9cbf3 100644 --- a/+file/fillValidators.m +++ b/+file/fillValidators.m @@ -4,8 +4,8 @@ nm = propnames{i}; prop = props(nm); - - if isa(prop, 'file.Attribute') && prop.readonly && ~isempty(prop.value) + if (isa(prop, 'file.Attribute') || isa(prop, 'file.Dataset')) ... + && prop.readonly && ~isempty(prop.value) % Need to add a validator for inherited and readonly properties. In % the superclass these properties might not be read only and due to % inheritance its not possible to change property attributes diff --git a/+types/+core/IZeroClampSeries.m b/+types/+core/IZeroClampSeries.m index 03049eb6..880a25c2 100644 --- a/+types/+core/IZeroClampSeries.m +++ b/+types/+core/IZeroClampSeries.m @@ -6,7 +6,7 @@ methods function obj = IZeroClampSeries(varargin) % IZEROCLAMPSERIES Constructor for IZeroClampSeries - varargin = [{'stimulus_description' 'N/A'} varargin]; + varargin = [{'bias_current' types.util.correctType(0, 'single') 'bridge_balance' types.util.correctType(0, 'single') 'capacitance_compensation' types.util.correctType(0, 'single') 'stimulus_description' 'N/A'} varargin]; obj = obj@types.core.CurrentClampSeries(varargin{:}); @@ -33,58 +33,25 @@ %% VALIDATORS function val = validate_bias_current(obj, val) - val = types.util.checkDtype('bias_current', 'single', val); - if isa(val, 'types.untyped.DataStub') - if 1 == val.ndims - valsz = [val.dims 1]; - else - valsz = val.dims; - end - elseif istable(val) - valsz = [height(val) 1]; - elseif ischar(val) - valsz = [size(val, 1) 1]; + if isequal(val, 0) + val = 0; else - valsz = size(val); + error('NWB:Type:ReadOnlyProperty', 'Unable to set the ''bias_current'' property of class ''IZeroClampSeries'' because it is read-only.') end - validshapes = {[1]}; - types.util.checkDims(valsz, validshapes); end function val = validate_bridge_balance(obj, val) - val = types.util.checkDtype('bridge_balance', 'single', val); - if isa(val, 'types.untyped.DataStub') - if 1 == val.ndims - valsz = [val.dims 1]; - else - valsz = val.dims; - end - elseif istable(val) - valsz = [height(val) 1]; - elseif ischar(val) - valsz = [size(val, 1) 1]; + if isequal(val, 0) + val = 0; else - valsz = size(val); + error('NWB:Type:ReadOnlyProperty', 'Unable to set the ''bridge_balance'' property of class ''IZeroClampSeries'' because it is read-only.') end - validshapes = {[1]}; - types.util.checkDims(valsz, validshapes); end function val = validate_capacitance_compensation(obj, val) - val = types.util.checkDtype('capacitance_compensation', 'single', val); - if isa(val, 'types.untyped.DataStub') - if 1 == val.ndims - valsz = [val.dims 1]; - else - valsz = val.dims; - end - elseif istable(val) - valsz = [height(val) 1]; - elseif ischar(val) - valsz = [size(val, 1) 1]; + if isequal(val, 0) + val = 0; else - valsz = size(val); + error('NWB:Type:ReadOnlyProperty', 'Unable to set the ''capacitance_compensation'' property of class ''IZeroClampSeries'' because it is read-only.') end - validshapes = {[1]}; - types.util.checkDims(valsz, validshapes); end function val = validate_stimulus_description(obj, val) if isequal(val, 'N/A')