Skip to content

Commit

Permalink
Update TutorialTest.m
Browse files Browse the repository at this point in the history
  • Loading branch information
ehennestad committed Nov 6, 2024
1 parent ef82026 commit d965607
Showing 1 changed file with 91 additions and 43 deletions.
134 changes: 91 additions & 43 deletions +tests/+unit/TutorialTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ function setupClass(testCase)
testCase.applyFixture(matlab.unittest.fixtures.PathFixture(rootPath));
testCase.applyFixture(matlab.unittest.fixtures.PathFixture(tutorialsFolder));

% Note: The following seems to not be working on the azure pipeline
% Note: The following seems to not be working on the azure
% pipeline / github runner.
% Keep for reference

% % % Make sure pynwb is installed in MATLAB's Python Environment
Expand All @@ -64,32 +65,12 @@ function setupClass(testCase)
% % insert(py.sys.path,int32(0),pynwbPath);
% % end

% This is also not working on github runner
% installNWBInspector()

% % Alternative: Use python script for reading file with pynwb
tests.util.addFolderToPythonPath( fileparts(mfilename('fullpath')) )

installNWBInspector()

disp(pyenv)

generator = py.pkgutil.iter_modules();

py.dir(generator)
methodNext = py.getattr(generator, '__next__');
finished = false;
moduleNames = string.empty;
while ~finished
try
module = methodNext();
moduleNames(end+1) = string(module.name);
catch;
finished = true;
end
end
moduleNames'

py.nwbinspector.inspect_nwbfile('test.nwb')

nwbClearGenerated()
testCase.addTeardown(@generateCore)
end
Expand Down Expand Up @@ -154,16 +135,18 @@ function inspectTutorialFileWithNwbInspector(testCase)
for nwbFilename = nwbFileNameList
try
results = py.list(py.nwbinspector.inspect_nwbfile(nwbfile_path=nwbFilename));
results = testCase.convertNwbInspectorResultsToStruct(results);
catch
[s,m] = system(sprintf('nwbinspector %s', nwbFilename))
disp(m)
[~, m] = system(sprintf('nwbinspector %s --levels importance', nwbFilename));
results = testCase.parseInspectorTextOutput(m);
end

if isempty(cell(results))
return
end

results = testCase.filterResults(results);

results = testCase.convertNwbInspectorResultsToStruct(results);
T = struct2table(results); disp(T)

for j = 1:numel(results)
Expand Down Expand Up @@ -191,21 +174,10 @@ function inspectTutorialFileWithNwbInspector(testCase)

methods (Static)
function resultsOut = convertNwbInspectorResultsToStruct(resultsIn)
CHECK_IGNORE = [...
"check_image_series_external_file_valid", ...
"check_regular_timestamps"
];

resultsOut = tests.unit.TutorialTest.getEmptyNwbInspectorResultStruct();

C = cell(resultsIn);

resultsOut = struct(...
'importance', {}, ...
'severity', {}, ...
'location', {}, ...
'filepath', {}, ...
'check_name', {}, ...
'ignore', {});

for i = 1:numel(C)
resultsOut(i).importance = double( py.getattr(C{i}.importance, 'value') );
resultsOut(i).severity = double( py.getattr(C{i}.severity, 'value') );
Expand All @@ -219,14 +191,74 @@ function inspectTutorialFileWithNwbInspector(testCase)
resultsOut(i).message = string(C{i}.message);
resultsOut(i).filepath = string(C{i}.file_path);
resultsOut(i).check_name = string(C{i}.check_function_name);
resultsOut(i).ignore = any(strcmp(CHECK_IGNORE, resultsOut(i).check_name));
end
end

function resultsOut = parseInspectorTextOutput(systemCommandOutput)
resultsOut = tests.unit.TutorialTest.getEmptyNwbInspectorResultStruct();

importanceLevels = containers.Map(...
["BEST_PRACTICE_SUGGESTION", ...
"BEST_PRACTICE_VIOLATION", ...
"CRITICAL", ...
"PYNWB_VALIDATION", ...
"ERROR"], 0:4 );

lines = splitlines(systemCommandOutput);
count = 0;
for i = 1:numel(lines)
% Example line:
% '.0 Importance.BEST_PRACTICE_VIOLATION: behavior_tutorial.nwb - check_regular_timestamps - 'SpatialSeries' object at location '/processing/behavior/Position/SpatialSeries'
% ^2 ^1 ^2 ^ ^ ^ 3
% [-----------importance------------] [------filepath------] [------check_name------] [-----------------location----------------]
% Splitting and components is exemplified above.

if ~isempty(regexp( lines{i}, '^\.\d{1}', 'once' ) )
count = count+1;
% Split line into separate components
splitLine = strsplit(lines{i}, ':');
splitLine = [...
strsplit(splitLine{1}, ' '), ...
strsplit(splitLine{2}, '-') ...
];

resultsOut(count).importance = importanceLevels( extractAfter(splitLine{2}, 'Importance.') );
resultsOut(count).filepath = string(strtrim( splitLine{3} ));
resultsOut(count).check_name = string(strtrim(splitLine{4} ));

locationInfo = strsplit(splitLine{end}, 'at location');
resultsOut(count).location = string(strtrim(eval(locationInfo{2})));
resultsOut(count).message = string(strtrim(lines{i+1}));
end
end
end

function emptyResults = getEmptyNwbInspectorResultStruct()
emptyResults = struct(...
'importance', {}, ...
'severity', {}, ...
'location', {}, ...
'filepath', {}, ...
'check_name', {}, ...
'ignore', {});
end

function resultsOut = filterResults(resultsIn)
CHECK_IGNORE = [...
"check_image_series_external_file_valid", ...
"check_regular_timestamps"
];

for i = 1:numel(resultsIn)
resultsIn(i).ignore = any(strcmp(CHECK_IGNORE, resultsIn(i).check_name));

% Special case to ignore
if resultsOut(i).location == "/acquisition/ExternalVideos" && ...
resultsOut(i).check_name == "check_timestamps_match_first_dimension"
resultsOut(i).ignore = true;
if resultsIn(i).location == "/acquisition/ExternalVideos" && ...
resultsIn(i).check_name == "check_timestamps_match_first_dimension"
resultsIn(i).ignore = true;
end
end
resultsOut = resultsIn;
resultsOut([resultsOut.ignore]) = [];
end
end
Expand Down Expand Up @@ -270,3 +302,19 @@ function checkAndUpdatePythonPath(installLocation, packageName)
disp('py path')
disp( py.sys.path() )
end

function listPythonModules()
generator = py.pkgutil.iter_modules();
methodNext = py.getattr(generator, '__next__');
finished = false;
moduleNames = string.empty;
while ~finished
try
module = methodNext();
moduleNames(end+1) = string(module.name);
catch;
finished = true;
end
end
moduleNames'
end

0 comments on commit d965607

Please sign in to comment.