Skip to content
Open
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
47 changes: 27 additions & 20 deletions +io/getNeurodataTypeInfo.m
Original file line number Diff line number Diff line change
Expand Up @@ -49,31 +49,38 @@
typeInfo.typename = char( matnwb.common.composeFullClassName(...
typeInfo.namespace, typeInfo.name) );

if strcmp(typeInfo.namespace, 'hdmf-experimental') && ~exist(typeInfo.typename, 'class')
typeInfo = correctNamespaceIfShouldBeHdmfCommon(typeInfo);
end
if ~exist(typeInfo.typename, 'class')
typeInfo = tryCorrectNamespace(typeInfo);
end
end
end

function typeInfo = correctNamespaceIfShouldBeHdmfCommon(typeInfo)
% correctNamespaceIfShouldBeHdmfCommon - Correct namespace if value in file is wrong.
function typeInfo = tryCorrectNamespace(typeInfo)
% tryCorrectNamespace - Try to correct namespace if type class doesn't exist
%
% This function provides a workaround for a bug where the namespace of a
% neurodata type was wrongly written to file as hdmf-experimental instead
% of hdmf-common.
%
% If the namespace of a type is hdmf-experimental, and the corresponding type
% class does not exist in MATLAB, but the equivalent hdmf_common class exists,
% the namespace is changed from hdmf-experimental to hdmf-common.
% Some NWB files have incorrect namespace values written to them.
% This function attempts to find the correct namespace by checking
% if an equivalent class exists in hdmf_common.
%
% The bug is described in this issue:
% https://github.com/hdmf-dev/hdmf/issues/1347
% Known issues:
% - hdmf-experimental instead of hdmf-common (https://github.com/hdmf-dev/hdmf/issues/1347)
% - core instead of hdmf-common (https://github.com/NeurodataWithoutBorders/helpdesk/discussions/104)

if strcmp(typeInfo.namespace, 'hdmf-experimental') && ~exist(typeInfo.typename, 'class')
correctedTypename = replace(typeInfo.typename, 'hdmf_experimental', 'hdmf_common');
if exist(correctedTypename, 'class') == 8
typeInfo.typename = correctedTypename;
typeInfo.namespace = 'hdmf-common';
end
% Map of namespace values that might be incorrectly used instead of hdmf-common
namespaceNames = {'hdmf-experimental', 'core'};
packageNames = {'hdmf_experimental', 'core'}; % Corresponding MATLAB package names
namespaceToPackage = containers.Map(namespaceNames, packageNames);

if ~isKey(namespaceToPackage, typeInfo.namespace)
return
end

currentPackage = namespaceToPackage(typeInfo.namespace);
correctedTypename = strrep(typeInfo.typename, ...
[currentPackage '.'], 'hdmf_common.');

if exist(correctedTypename, 'class') == 8
typeInfo.typename = correctedTypename;
typeInfo.namespace = 'hdmf-common';
end
end
15 changes: 15 additions & 0 deletions +tests/+unit/+io/GetNeurodataTypeInfoTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,21 @@ function testHdmfExperimentalFallbackToHdmfCommon(testCase, HDMFCommonType)
testCase.verifyEqual(typeInfo.name, HDMFCommonType);
testCase.verifyEqual(typeInfo.typename, sprintf('types.hdmf_common.%s', HDMFCommonType));
end

function testCoreFallbackToHdmfCommon(testCase, HDMFCommonType)
% Test fallback correction for hdmf-common types with incorrect
% core namespace (should be hdmf-common)
attributeInfo = struct(...
'Name', {'neurodata_type', 'namespace'}, ...
'Value', {HDMFCommonType, 'core'});

typeInfo = io.getNeurodataTypeInfo(attributeInfo);

% Should be corrected to hdmf-common
testCase.verifyEqual(typeInfo.namespace, 'hdmf-common');
testCase.verifyEqual(typeInfo.name, HDMFCommonType);
testCase.verifyEqual(typeInfo.typename, sprintf('types.hdmf_common.%s', HDMFCommonType));
end

function testCellStringValueHandling(testCase)
% Test that cell string values are handled correctly
Expand Down