Skip to content

Commit 4998690

Browse files
author
Lawrence
committed
Fixed DataPipe off-by-one Errors
Also allowed DataPipes through the checkDType function.
1 parent 2889aa1 commit 4998690

File tree

3 files changed

+40
-18
lines changed

3 files changed

+40
-18
lines changed

+types/+untyped/DataPipe.m

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121

2222
properties (Access = private, Constant)
2323
SUPPORTED_DATATYPES = {...
24-
'float', 'double', 'uint8', 'int8', 'uint16', 'int16', 'uint32',...
25-
'int32', 'uint64', 'int64'
24+
'float', 'double', 'uint8', 'int8', 'uint16', 'int16',...
25+
'uint32', 'int32', 'uint64', 'int64'
2626
};
2727
end
2828

@@ -33,11 +33,12 @@
3333
p = inputParser;
3434
p.addParameter('filename', '');
3535
p.addParameter('path', '');
36-
p.addParameter('offset', 1);
36+
p.addParameter('offset', 0);
3737
p.addParameter('axis', 1);
3838
p.addParameter('chunkSize', []);
3939
p.addParameter('dataType', 'uint8');
4040
p.addParameter('compressionLevel', -1);
41+
p.addParameter('data', []);
4142
p.parse(varargin{:});
4243

4344
obj.filename = p.Results.filename;
@@ -47,6 +48,7 @@
4748
obj.chunkSize = p.Results.chunkSize;
4849
obj.dataType = p.Results.dataType;
4950
obj.compressionLevel = p.Results.compressionLevel;
51+
obj.data = cast(p.Results.data, obj.dataType);
5052
end
5153
end
5254

@@ -83,7 +85,7 @@
8385
end
8486

8587
function set.offset(obj, val)
86-
assert(isscalar(val) && isnumeric(val) && val > 0,...
88+
assert(isscalar(val) && isnumeric(val) && val >= 0,...
8789
'NWB:Untyped:DataPipe:SetOffset:InvalidType',...
8890
'Offset should be a nonzero scalar indicating axis offset.');
8991
val = ceil(val);
@@ -204,22 +206,32 @@ function append(obj, data)
204206

205207
fid = H5F.open(obj.filename, 'H5F_ACC_RDWR', default_pid);
206208
did = H5D.open(fid, obj.path, default_pid);
209+
sid = H5D.get_space(did);
210+
[~, h5_dims, ~] = H5S.get_simple_extent_dims(sid);
211+
H5S.close(sid);
207212

208213
rank = length(obj.maxSize);
209-
stride_coords = ones(1, rank);
210-
stride_coords(1:length(size(data))) = size(data);
211-
new_extents = obj.maxSize;
212-
new_extents(obj.axis) = obj.offset + stride_coords(obj.axis) - 1;
214+
stride_coords = size(data);
215+
if length(stride_coords) > rank && ~all(stride_coords(rank+1:end) == 1)
216+
warning('Nwb:Types:Untyped:DataPipe:InvalidRank',...
217+
['Expected rank %d not expected for data of size %s. '...
218+
'Data may be lost on write.'],...
219+
rank, mat2str(size(stride_coords)));
220+
end
221+
stride_coords = stride_coords(1:rank);
222+
new_extents = fliplr(h5_dims);
223+
new_extents(obj.axis) = obj.offset;
224+
new_extents = new_extents + stride_coords;
213225
h5_extents = fliplr(new_extents);
214-
H5D.set_extent(did, h5_extents);
215-
226+
H5D.set_extent(did, h5_extents);
227+
216228
sid = H5D.get_space(did);
217229
H5S.select_none(sid);
218230

219-
offset_coords = ones(1, rank);
231+
offset_coords = zeros(1, rank);
220232
offset_coords(obj.axis) = obj.offset;
221233

222-
h5_start = fliplr(offset_coords) - 1;
234+
h5_start = fliplr(offset_coords);
223235
h5_stride = [];
224236
h5_count = fliplr(stride_coords);
225237
h5_block = [];

+types/+util/checkDtype.m

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,16 @@
6363
return;
6464
end
6565

66+
if isa(val, 'types.untyped.DataPipe')
67+
if strcmp(type, 'float64')
68+
type = 'double';
69+
end
70+
assert(strcmp(val.dataType, type),...
71+
'NWB:Types:Util:CheckDType:InvalidType',...
72+
'DataPipe should be configured with type `%s`', type);
73+
return;
74+
end
75+
6676
if isa(val, 'types.untyped.DataStub')
6777
%grab first element and check
6878
truval = val;
@@ -85,7 +95,7 @@
8595
if any(strcmpi(type, {'single' 'double' 'logical' 'numeric'})) ||...
8696
startsWith(type, {'int' 'uint' 'float'})
8797
if isa(val, 'types.untyped.SoftLink')
88-
%derefing through softlink would require writing and/or the root NwbFile object
98+
% derefing through softlink would require writing and/or the root NwbFile object
8999
return;
90100
end
91101

+types/+util/checkUnset.m

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
function checkUnset(obj, argin)
22
props = properties(obj);
33
anonNames = {};
4-
for i=1:length(props)
4+
for i = 1:length(props)
55
p = obj.(props{i});
66
if isa(p, 'types.untyped.Anon')
77
anonNames = [anonNames;{p.name}];
@@ -10,8 +10,8 @@ function checkUnset(obj, argin)
1010
end
1111
end
1212
dropped = setdiff(argin, [props;anonNames]);
13-
if ~isempty(dropped)
14-
error('Properties {%s} are not valid property names.',...
15-
misc.cellPrettyPrint(dropped));
16-
end
13+
assert(isempty(dropped),...
14+
'Nwb:Types:Util:CheckUnset:InvalidProperties',...
15+
'Properties {%s} are not valid property names.',...
16+
misc.cellPrettyPrint(dropped));
1717
end

0 commit comments

Comments
 (0)