Skip to content
Merged
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
27 changes: 20 additions & 7 deletions +io/+backend/+hdf5/@HDF5LazyArray/load_mat_style.m
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

%% Select from Space
dataDimensions = obj.dims;
spaceId = obj.getSpace();
userSelection = varargin;

selectionErrorId = 'NWB:DataStub:Load:InvalidSelection';
Expand Down Expand Up @@ -41,8 +40,15 @@
data = obj.load_mat_style(1);
data = getEmptyRepresentation(data);
return
end

% The dataspace and the read use the same open dataset, so each call
% opens the file once.
fileId = H5F.open(obj.Filename);
datasetId = H5D.open(fileId, obj.DatasetPath);
spaceId = H5D.get_space(datasetId);

elseif isscalar(userSelection) && ~ischar(userSelection{1})
if isscalar(userSelection) && ~ischar(userSelection{1})
% linear index into the fast dimension.
orderedSelection = unique(userSelection{1});

Expand All @@ -66,11 +72,20 @@
dataDimensions = [dataDimensions, 1];
end

[points{:}] = ind2sub(dataDimensions, orderedSelection);
readSpaceId = H5S.copy(spaceId);
H5S.select_none(readSpaceId);
H5S.select_elements(readSpaceId, 'H5S_SELECT_SET', ...
cell2mat(flipud(points)) - 1);
isOneRun = orderedSelection(end) - orderedSelection(1) + 1 == numel(orderedSelection);
if isscalar(obj.dims) && isOneRun
% One contiguous run of a one-dimensional dataset is a single
% hyperslab, which HDF5 selects faster than one point per element.
% The selection can be of any integer class, and H5S takes doubles.
H5S.select_hyperslab(readSpaceId, 'H5S_SELECT_SET', ...
double(orderedSelection(1)) - 1, [], numel(orderedSelection), []);
else
[points{:}] = ind2sub(dataDimensions, orderedSelection);
H5S.select_elements(readSpaceId, 'H5S_SELECT_SET', ...
cell2mat(flipud(points)) - 1);
end
memorySpaceId = H5S.create_simple(length(selectionDimensions), ...
selectionDimensions, selectionDimensions);
else
Expand All @@ -81,8 +96,6 @@
H5S.close(spaceId);

%% Read Data
fileId = H5F.open(obj.Filename);
datasetId = H5D.open(fileId, obj.DatasetPath);
data = H5D.read(datasetId, 'H5ML_DEFAULT', memorySpaceId, readSpaceId, 'H5P_DEFAULT');

%% Retype Data
Expand Down
18 changes: 18 additions & 0 deletions +tests/+unit/+io/+backend/HDF5LazyArrayTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,24 @@ function reorderedFirstSubscriptBeforeFoldedColon(testCase, Subscript)

testCase.verifyEqual(lazyArray.load_mat_style(Subscript, ':'), data(Subscript, :));
end

function loadMatStyleReadsOneDimensionalSelections(testCase)
% A selection that is one contiguous run is read as a hyperslab
% and any other selection as points. Both return the elements
% in the order they were asked for.
filename = "lazy-array-1d.h5";
data = (101:120)';
h5create(filename, "/data", numel(data));
h5write(filename, "/data", data);
lazyArray = io.backend.hdf5.HDF5LazyArray(filename, "/data");

selections = {5:9, (9:-1:5)', [3 3 4], 1:20, 20, uint64(5:9), [2 5 9]};
for iSelection = 1:numel(selections)
selection = selections{iSelection};
testCase.verifyEqual(lazyArray.load_mat_style(selection), data(selection), ...
sprintf('Unexpected data for selection %s.', mat2str(selection)));
end
end
end

methods (Access = private)
Expand Down
Loading