Skip to content

Commit

Permalink
Fix: Bug in writeCompound / parseCompound functions (#620)
Browse files Browse the repository at this point in the history
* Fix bug with writing and parsing logical data in compound data type

* Fix variableName in test
  • Loading branch information
ehennestad authored Nov 14, 2024
1 parent fe4849a commit 7caa336
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 2 deletions.
8 changes: 7 additions & 1 deletion +io/parseCompound.m
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@
logicalFieldName = fieldName(isLogicalType);
for iFieldName = 1:length(logicalFieldName)
name = logicalFieldName{iFieldName};
data.(name) = strcmp('TRUE', data.(name));
if isa(data.(name), 'int8')
data.(name) = logical(data.(name));
elseif isa(data.(name), 'cell') && ismember(string(data.(name){1}), ["TRUE", "FALSE"])
data.(name) = strcmp('TRUE', data.(name));
else
error('NWB:ParseCompound:UnknownLogicalFormat', 'Could not resolve data of logical type')
end
end
end
5 changes: 4 additions & 1 deletion +io/writeCompound.m
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ function writeCompound(fid, fullpath, data, varargin)
% convert logical values
boolNames = names(strcmp(classes, 'logical'));
for iField = 1:length(boolNames)
data.(boolNames{iField}) = strcmp('TRUE', data.(boolNames{iField}));
data.(boolNames{iField}) = int8(data.(boolNames{iField}));
end

%transpose numeric column arrays to row arrays
Expand Down Expand Up @@ -134,6 +134,9 @@ function writeCompound(fid, fullpath, data, varargin)
warning('NWB:WriteCompund:ContinuousCompoundResize', ...
'Attempted to change size of continuous compound `%s`. Skipping.', ...
fullpath);
H5D.close(did);
H5S.close(sid);
return
end
end
H5P.close(create_plist);
Expand Down
70 changes: 70 additions & 0 deletions +tests/+unit/+io/WriteTest.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
classdef WriteTest < matlab.unittest.TestCase
% WriteTest - Unit test for io.write* functions.

methods (TestMethodSetup)
function setup(testCase)
% Use a fixture to create a temporary working directory
testCase.applyFixture(matlab.unittest.fixtures.WorkingFolderFixture);
end
end

methods (Test)

function testWriteBooleanAttribute(testCase)
filename = 'temp_test_file.h5';
fid = H5F.create(filename, 'H5F_ACC_TRUNC', 'H5P_DEFAULT', 'H5P_DEFAULT');
fileCleanupObj = onCleanup(@(id) H5F.close(fid));

targetPath = '/';
io.writeGroup(fid, targetPath)

% Define target dataset path and create it in the HDF5 file
io.writeAttribute(fid, '/test', true); % First write to create the dataset

% Read using h5readatt and confirm value
value = h5readatt(filename, '/', 'test');
testCase.verifyTrue( strcmp(value, 'TRUE'))

% Read using io.parseAttributes and confirm value
blackList = struct(...
'attributes', {{'.specloc', 'object_id'}},...
'groups', {{}});

S = h5info(filename);
[attributeProperties, ~] =...
io.parseAttributes(filename, S.Attributes, S.Name, blackList);
testCase.verifyTrue(attributeProperties('test'))
end

function testWriteCompound(testCase)
% Create a temporary HDF5 file
filename = 'temp_test_file.h5';
fullPath = '/test_dataset';
fid = H5F.create(filename, 'H5F_ACC_TRUNC', 'H5P_DEFAULT', 'H5P_DEFAULT');
fileCleanupObj = onCleanup(@(id) H5F.close(fid));

% Data to write
data = struct('a', {1,2}, 'b', {true, false}, 'c', {'test', 'new test'});
io.writeCompound(fid, fullPath, data); % First write to create the dataset

loadedData = h5read(filename, '/test_dataset');
tempT = struct2table(loadedData);
% Booleans are loaded as int8, need to manually fix
tempT.b = logical( tempT.b );
loadedData = table2struct(tempT)';
testCase.verifyEqual(data, loadedData);

% Use parse compound
did = H5D.open(fid, '/test_dataset');
fsid = H5D.get_space(did);
loadedData = H5D.read(did, 'H5ML_DEFAULT', fsid, fsid,...
'H5P_DEFAULT');
parsedData = io.parseCompound(did, loadedData);
H5S.close(fsid);
H5D.close(did);

parsedData = table2struct( struct2table(parsedData) )';
testCase.verifyEqual(data, parsedData);
end
end
end

0 comments on commit 7caa336

Please sign in to comment.