-
Notifications
You must be signed in to change notification settings - Fork 32
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor: Add arguments block to main MatNWB api functions
- Move some functions io.spec namespace - Add validation functions in matnwb.common namespace
- Loading branch information
1 parent
5aa27d9
commit 4a305d0
Showing
16 changed files
with
390 additions
and
282 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
function specLocation = readEmbeddedSpecLocation(fid, specLocAttributeName) | ||
arguments | ||
fid (1,1) H5ML.id | ||
specLocAttributeName (1,1) string = '.specloc' | ||
end | ||
|
||
specLocation = ''; | ||
try % Check .specloc | ||
attributeId = H5A.open(fid, specLocAttributeName); | ||
attributeCleanup = onCleanup(@(id) H5A.close(attributeId)); | ||
referenceRawData = H5A.read(attributeId); | ||
specLocation = H5R.get_name(attributeId, 'H5R_OBJECT', referenceRawData); | ||
catch ME | ||
if ~strcmp(ME.identifier, 'MATLAB:imagesci:hdf5lib:libraryError') | ||
rethrow(ME); | ||
end % don't error if the attribute doesn't exist. | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
function specLocation = getEmbeddedSpecLocation(filename, options) | ||
% getEmbeddedSpecLocation - Get location of embedded specs in NWB file | ||
% | ||
% Note: Returns an empty string if the spec location does not exist | ||
% | ||
% See also io.spec.internal.readEmbeddedSpecLocation | ||
|
||
arguments | ||
filename (1,1) string {matnwb.common.mustBeNwbFile} | ||
options.SpecLocAttributeName (1,1) string = '.specloc' | ||
end | ||
|
||
fid = H5F.open(filename); | ||
fileCleanup = onCleanup(@(id) H5F.close(fid) ); | ||
specLocation = io.spec.internal.readEmbeddedSpecLocation(fid, options.SpecLocAttributeName); | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
function specs = readEmbeddedSpecifications(filename, specLocation) | ||
% readEmbeddedSpecifications - Read embedded specs from an NWB file | ||
% | ||
% specs = io.spec.readEmbeddedSpecifications(filename, specLocation) read | ||
% embedded specs from the specLocation in an NWB file | ||
% | ||
% Inputs: | ||
% filename (string) : Absolute path of an nwb file | ||
% specLocation (string) : h5 path for the location of specs inside the NWB file | ||
% | ||
% Outputs | ||
% specs cell: A cell array of structs with one element for each embedded | ||
% specification. Each struct has two fields: | ||
% | ||
% - namespaceName (char) : Name of the namespace for a specification | ||
% - namespaceText (char) : The namespace declaration for a specification | ||
% - schemaMap (containers.Map): A set of schema specifications for the namespace | ||
|
||
arguments | ||
filename (1,1) string {matnwb.common.mustBeNwbFile} | ||
specLocation (1,1) string | ||
end | ||
|
||
specInfo = h5info(filename, specLocation); | ||
specs = deal( cell(size(specInfo.Groups)) ); | ||
|
||
fid = H5F.open(filename); | ||
fileCleanup = onCleanup(@(id) H5F.close(fid) ); | ||
|
||
for iGroup = 1:length(specInfo.Groups) | ||
location = specInfo.Groups(iGroup).Groups(1); | ||
|
||
namespaceName = split(specInfo.Groups(iGroup).Name, '/'); | ||
namespaceName = namespaceName{end}; | ||
|
||
filenames = {location.Datasets.Name}; | ||
if ~any(strcmp('namespace', filenames)) | ||
warning('NWB:Read:GenerateSpec:CacheInvalid',... | ||
'Couldn''t find a `namespace` in namespace `%s`. Skipping cache generation.',... | ||
namespaceName); | ||
return; | ||
end | ||
sourceNames = {location.Datasets.Name}; | ||
fileLocation = strcat(location.Name, '/', sourceNames); | ||
schemaMap = containers.Map; | ||
for iFileLocation = 1:length(fileLocation) | ||
did = H5D.open(fid, fileLocation{iFileLocation}); | ||
if strcmp('namespace', sourceNames{iFileLocation}) | ||
namespaceText = H5D.read(did); | ||
else | ||
schemaMap(sourceNames{iFileLocation}) = H5D.read(did); | ||
end | ||
H5D.close(did); | ||
end | ||
|
||
specs{iGroup}.namespaceName = namespaceName; | ||
specs{iGroup}.namespaceText = namespaceText; | ||
specs{iGroup}.schemaMap = schemaMap; | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
function writeEmbeddedSpecifications(fid, jsonSpecs) | ||
specLocation = io.spec.internal.readEmbeddedSpecLocation(fid); | ||
|
||
if isempty(specLocation) | ||
specLocation = '/specifications'; | ||
io.writeGroup(fid, specLocation); | ||
specView = types.untyped.ObjectView(specLocation); | ||
io.writeAttribute(fid, '/.specloc', specView); | ||
end | ||
|
||
for iJson = 1:length(jsonSpecs) | ||
JsonDatum = jsonSpecs(iJson); | ||
schemaNamespaceLocation = strjoin({specLocation, JsonDatum.name}, '/'); | ||
namespaceExists = io.writeGroup(fid, schemaNamespaceLocation); | ||
if namespaceExists | ||
namespaceGroupId = H5G.open(fid, schemaNamespaceLocation); | ||
names = getVersionNames(namespaceGroupId); | ||
H5G.close(namespaceGroupId); | ||
for iNames = 1:length(names) | ||
H5L.delete(fid, [schemaNamespaceLocation '/' names{iNames}],... | ||
'H5P_DEFAULT'); | ||
end | ||
end | ||
schemaLocation =... | ||
strjoin({schemaNamespaceLocation, JsonDatum.version}, '/'); | ||
io.writeGroup(fid, schemaLocation); | ||
Json = JsonDatum.json; | ||
schemeNames = keys(Json); | ||
for iScheme = 1:length(schemeNames) | ||
name = schemeNames{iScheme}; | ||
path = [schemaLocation '/' name]; | ||
io.writeDataset(fid, path, Json(name)); | ||
end | ||
end | ||
end | ||
|
||
function versionNames = getVersionNames(namespaceGroupId) | ||
[~, ~, versionNames] = H5L.iterate(namespaceGroupId,... | ||
'H5_INDEX_NAME', 'H5_ITER_NATIVE',... | ||
0, @removeGroups, {}); | ||
function [status, versionNames] = removeGroups(~, name, versionNames) | ||
versionNames{end+1} = name; | ||
status = 0; | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
function latestVersion = findLatestSchemaVersion() | ||
% findLatestSchemaVersion - Find latest available schema version. | ||
|
||
schemaListing = dir(fullfile(misc.getMatnwbDir(), 'nwb-schema')); | ||
schemaVersionNumbers = setdiff({schemaListing.name}, {'.', '..'}); | ||
|
||
% Split each version number into major, minor, and patch components | ||
versionComponents = cellfun(@(v) sscanf(v, '%d.%d.%d'), ... | ||
schemaVersionNumbers, 'UniformOutput', false); | ||
|
||
% Convert the components into an array for easy comparison | ||
versionMatrix = cat(2, versionComponents{:})'; | ||
|
||
% Find the row with the highest version number, weighting major | ||
% and minor with factors of 6 and 3 respectively | ||
[~, latestIndex] = max(versionMatrix * [1e6; 1e3; 1]); % Weight major, minor, patch | ||
|
||
% Return the latest version | ||
latestVersion = schemaVersionNumbers{latestIndex}; | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
function mustBeNwbFile(filePath) | ||
% mustBeNwbFile - Check that file path points to existing file with .nwb extension | ||
arguments | ||
filePath (1,1) string {mustBeFile} | ||
end | ||
assert(endsWith(filePath, ".nwb", "IgnoreCase", true)) | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
function mustBeValidSchemaVersion(versionNumber) | ||
% mustBeValidSchemaVersion - Validate version number against available schemas | ||
arguments | ||
versionNumber (1,1) string | ||
end | ||
|
||
persistent schemaVersionNumbers | ||
|
||
if versionNumber == "latest" | ||
return % Should be resolved downstream. | ||
end | ||
|
||
versionPattern = "^\d+\.\d+\.\d+$"; % i.e 2.0.0 | ||
if isempty(regexp(versionNumber, versionPattern, 'once')) | ||
error('NWB:VersionValidator:InvalidVersionNumber', ... | ||
"Version number should formatted as <major>.<minor>.<patch>") | ||
end | ||
|
||
% Validate supported schema version | ||
if isempty(schemaVersionNumbers) | ||
schemaListing = dir(fullfile(misc.getMatnwbDir(), 'nwb-schema')); | ||
schemaVersionNumbers = setdiff({schemaListing.name}, {'.', '..'}); | ||
end | ||
|
||
if ~any(strcmp(versionNumber, schemaVersionNumbers)) | ||
error('NWB:VersionValidator:UnsupportedSchemaVersion', ... | ||
"The provided version number ('%s') is not supported by this version of MatNWB", ... | ||
versionNumber) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.