From 7ce96a212d884aa3acf66cb34090a99c6803d7ae Mon Sep 17 00:00:00 2001 From: Kay Robbins <1189050+VisLab@users.noreply.github.com> Date: Sun, 9 Jun 2024 09:26:45 -0500 Subject: [PATCH 1/2] Tests now working. Changed name of getHedFactors to searchHed --- hedmat/hedtools/HedTools.m | 8 +- hedmat/hedtools/HedToolsPython.m | 112 ++++++++++--------- hedmat/hedtools/HedToolsService.m | 123 ++++++++++++--------- tests/test_hed_tools/TestHedToolsPython.m | 49 ++++---- tests/test_hed_tools/TestHedToolsService.m | 59 +++++----- 5 files changed, 187 insertions(+), 164 deletions(-) diff --git a/hedmat/hedtools/HedTools.m b/hedmat/hedtools/HedTools.m index 759e9f0..c269aaf 100644 --- a/hedmat/hedtools/HedTools.m +++ b/hedmat/hedtools/HedTools.m @@ -56,13 +56,13 @@ annotations = getHedAnnotations(obj, eventsIn, sidecar, ... removeTypesOn, includeContext, replaceDefs); - factors = getHedFactors(obj, annotations, queries); + factors = searchHed(obj, annotations, queries); - issueString = validateEvents(obj, eventsIn, sidecar, checkWarnings); + issues = validateEvents(obj, eventsIn, sidecar, checkWarnings); - issueString = validateSidecar(obj, sidecar, checkWarnings); + issues = validateSidecar(obj, sidecar, checkWarnings); - issueString = validateTags(obj, hedtags, checkWarnings); + issues = validateTags(obj, hedtags, checkWarnings); resetHedVersion(obj, hedVersion) end diff --git a/hedmat/hedtools/HedToolsPython.m b/hedmat/hedtools/HedToolsPython.m index 60eb6f3..7076841 100644 --- a/hedmat/hedtools/HedToolsPython.m +++ b/hedmat/hedtools/HedToolsPython.m @@ -18,12 +18,12 @@ obj.resetHedVersion(version) end - function annotations = getHedAnnotations(obj, eventsIn, ... + function annotations = getHedAnnotations(obj, events, ... sidecar, removeTypesOn, includeContext, replaceDefs) % Return a cell array of HED annotations of same length as events. % % Parameters: - % eventsIn - char, string or rectified struct. + % events - char, string or rectified struct. % sidecar - char, string or struct representing sidecar % removeTypesOn - boolean true->remove Condition-variable % and Task @@ -38,14 +38,14 @@ % line. % - events = HedToolsPython.getTabularObj(eventsIn, sidecar); - issueString = obj.validateEvents(events, sidecar, false); + eventsTab = HedToolsPython.getTabularObj(events, sidecar); + issueString = obj.validateEvents(eventsTab, sidecar, false); if ~isempty(issueString) throw(MException( ... 'HedToolsPythonGetHedAnnotations:InvalidData', ... "Input errors:\n" + issueString)); end - hedObjs = HedToolsPython.getHedStringObjs(events, ... + hedObjs = HedToolsPython.getHedStringObjs(eventsTab, ... obj.HedSchema, removeTypesOn, includeContext, replaceDefs); strs = ... py.hed.tools.analysis.annotation_util.to_strlist(hedObjs); @@ -54,7 +54,7 @@ annotations = cellfun(@char, cStrs(:), 'UniformOutput', false); end - function factors = getHedFactors(obj, annotations, queries) + function factors = searchHed(obj, annotations, queries) %% Return an array of 0's and 1's indicating query truth % % Parameters: @@ -83,118 +83,128 @@ factors = double(df_factors.to_numpy()); end - function [] = resetHedVersion(obj, version) - % Change the HED Version used. - % - % Parameters: - % version - cell array or char array or string with HED - % version specification. - obj.HedVersion = version; - obj.setHedSchema(version); - end - - function [] = setHedSchema(obj, schema) - % Set a HedSchema or HedSchemaGroup object based on hedVersion - % - % Parameters: - % schema - a single string or a cell array of strings representing - % the HED schema version or a schema object. - % - obj.HedSchema = HedToolsPython.getHedSchemaObj(schema); - end - - function issueString = validateEvents(obj, events, sidecar, checkWarnings) + function issues = validateEvents(obj, events, sidecar, checkWarnings) % Validate HED in events or other tabular-type input. % % Parameters: % events - char array, string, struct (or tabularInput) % sidecar - char, string or struct representing sidecar - % checkWarnings - Boolean indicating checking for warnings + % checkWarnings - boolean (optional, default false) + % indicates whether to include warnings. % % Returns: - % issueString - A string with the validation issues suitable for + % issues - A string with the validation issues suitable for % printing (has newlines). - issueString = ''; sidecarObj = py.None; + if nargin <= 2 + checkWarnings = false; + end + issues = ''; ehandler = py.hed.errors.error_reporter.ErrorHandler(... check_for_warnings=checkWarnings); if ~isempty(sidecar) && ~isequal(sidecar, py.None) sidecar = HedTools.formatSidecar(sidecar); sidecarObj = py.hed.tools.analysis.annotation_util.strs_to_sidecar(sidecar); issues = sidecarObj.validate(obj.HedSchema, error_handler=ehandler); - issueString = ... - char(py.hed.get_printable_issue_string(issues)); - if py.hed.errors.error_reporter.check_for_any_errors(issues) + hasErrors = py.hed.errors.error_reporter.check_for_any_errors(issues); + issues = char(py.hed.get_printable_issue_string(issues)); + if hasErrors return; end end eventsObj = HedToolsPython.getTabularObj(events, sidecarObj); - issues = eventsObj.validate(obj.HedSchema, error_handler=ehandler); - issueString = [issueString, ... - char(py.hed.get_printable_issue_string(issues))]; + issuesEvents = eventsObj.validate(obj.HedSchema, error_handler=ehandler); + issues = [issues, ... + char(py.hed.get_printable_issue_string(issuesEvents))]; end - function issueString = validateSidecar(obj, sidecar, checkWarnings) + function issues = validateSidecar(obj, sidecar, checkWarnings) % Validate a sidecar containing HED tags. % % Parameters: % sidecar - a char, string, struct, or SidecarObj - % checkWarnings - boolean indicating checking for warnings + % checkWarnings - boolean (optional, default false) + % indicates whether to include warnings. % % Returns: - % issueString - A string with the validation issues suitable for - % printing (has newlines). + % issues - Char array with the validation issues suitable + % for printing (has newlines). + if nargin <= 2 + checkWarnings = false; + end ehandler = py.hed.errors.error_reporter.ErrorHandler(... check_for_warnings=checkWarnings); sidecarObj = HedToolsPython.getSidecarObj(sidecar); issues = sidecarObj.validate(obj.HedSchema, error_handler=ehandler); if isempty(issues) - issueString = ''; + issues = ''; else - issueString = ... + issues = ... char(py.hed.get_printable_issue_string(issues)); end end - function issueString = validateTags(obj, hedTags, checkWarnings) + function issues = validateTags(obj, hedTags, checkWarnings) % Validate a string containing HED tags. % % Parameters: % hedTags - A MATLAB string or character array. - % checkWarnings - Boolean indicating checking for warnings + % checkWarnings - boolean (optional, default false) + % indicates whether to include warnings. % % Returns: - % issueString - A string with the validation issues suitable for + % issues - A string with the validation issues suitable for % printing (has newlines). % ToDo: Make hedDefinitions optional. % - % vmod = py.importlib.import_module('hed.validator'); - if ~ischar(hedTags) && ~isstring(hedTags) throw(MException(... 'HedToolsPythonValidateHedTags:InvalidHedTagInput', ... 'Must provide a string or char array as input')) end + + if nargin <= 2 + checkWarnings = false; + end hedStringObj = py.hed.HedString(hedTags, obj.HedSchema); ehandler = py.hed.errors.error_reporter.ErrorHandler(... check_for_warnings=checkWarnings); validator = ... py.hed.validator.hed_validator.HedValidator(obj.HedSchema); - issues = ... - validator.validate(hedStringObj, false, ... + issues = validator.validate(hedStringObj, false, ... error_handler=ehandler); if isempty(issues) - issueString = ''; + issues = ''; else - issueString = ... + issues = ... char(py.hed.get_printable_issue_string(issues)); end end + + function [] = resetHedVersion(obj, version) + % Change the HED Version used. + % + % Parameters: + % version - cell array or char array or string with HED + % version specification. + obj.HedVersion = version; + obj.setHedSchema(version); + end + + function [] = setHedSchema(obj, schema) + % Set a HedSchema or HedSchemaGroup object based on hedVersion + % + % Parameters: + % schema - a single string or a cell array of strings representing + % the HED schema version or a schema object. + % + obj.HedSchema = HedToolsPython.getHedSchemaObj(schema); + end end diff --git a/hedmat/hedtools/HedToolsService.m b/hedmat/hedtools/HedToolsService.m index f22deae..d23ccb1 100644 --- a/hedmat/hedtools/HedToolsService.m +++ b/hedmat/hedtools/HedToolsService.m @@ -65,7 +65,7 @@ annotations = response.results.data; end - function factors = getHedFactors(obj, annotations, queries) + function factors = searchHed(obj, annotations, queries) %% Return an array of 0's and 1's indicating query truth % % Parameters: @@ -86,54 +86,26 @@ error_msg = HedToolsService.getResponseError(response); if error_msg throw(MException(... - 'HedToolsServiceGetHedAnnotations:ServiceError', error_msg)); + 'HedToolsServiceSearchHed:ServiceError', error_msg)); elseif strcmpi(response.results.msg_category, 'warning') throw(MException( ... - 'HedToolsServiceGetHedFactors:InvalidData', ... + 'HedToolsServiceSearchHed:InvalidData', ... "Input errors:\n" + response.results.data)); end factors = response.results.data; end - function [] = resetHedVersion(obj, hedVersion) - obj.HedVersion = hedVersion; - end - - function [] = resetSessionInfo(obj, host) - %% Reset the session for accessing the HED webservices - % Parameters: - % host = URL for the services - % - % Notes: sets obj.Cookie, obj.CRSFToken and obj.Options. - obj.ServicesUrl = [host '/services_submit']; - request = matlab.net.http.RequestMessage; - uri = matlab.net.URI([host '/services']); - response1 = send(request,uri); - cookies = response1.getFields('Set-Cookie'); - obj.Cookie = cookies.Value; - data = response1.Body.char; - csrfIdx = strfind(data,'csrf_token'); - tmp = data(csrfIdx(1)+length('csrf_token')+1:end); - csrftoken = regexp(tmp,'".*?"','match'); - obj.CSRFToken = string(csrftoken{1}(2:end-1)); - header = ["Content-Type" "application/json"; ... - "Accept" "application/json"; ... - "X-CSRFToken" obj.CSRFToken; "Cookie" obj.Cookie]; - - obj.WebOptions = weboptions('MediaType', 'application/json',... - 'Timeout', 120, 'HeaderFields', header); - end - - function issueString = validateEvents(obj, events, sidecar, checkWarnings) + function issues = validateEvents(obj, events, sidecar, checkWarnings) % Validate HED in events or other tabular-type input. % % Parameters: % events - char, string or rectified struct. % sidecar - char, string or struct representing sidecar - % checkWarnings - Boolean indicating checking for warnings + % checkWarnings - boolean (optional, default false) + % indicates whether to include warnings. % % Returns: - % issueString - A string with the validation issues suitable for + % issues - A string with the validation issues suitable for % printing (has newlines). request = obj.getRequestTemplate(); @@ -141,7 +113,11 @@ request.schema_version = obj.HedVersion; request.events_string = HedTools.formatEvents(events); request.sidecar_string = HedTools.formatSidecar(sidecar); - request.check_for_warnings = checkWarnings; + if nargin == 4 + request.check_for_warnings = checkWarnings; + else + request.check_for_warnings = false; + end response = webwrite(obj.ServicesUrl, request, obj.WebOptions); response = jsondecode(response); error_msg = HedToolsService.getResponseError(response); @@ -150,29 +126,34 @@ 'HedToolsServiceValidateEvents:ServiceError', error_msg)); end if strcmpi(response.results.msg_category, 'warning') - issueString = response.results.data; + issues = response.results.data; else - issueString = ''; + issues = ''; end end - function issueString = validateSidecar(obj, sidecar, checkWarnings) + function issues = validateSidecar(obj, sidecar, checkWarnings) % Validate a sidecar % % Parameters: % sidecar - a string, struct, or char array representing % a sidecar - % checkWarnings - boolean indicating whether warnings - % should also be reported. + % checkWarnings - boolean (optional, default false) + % indicates whether to include warnings. % % Returns: - % issueSstring - printable issue string or empty + % issues - printable issue string or empty % request = obj.getRequestTemplate(); request.service = 'sidecar_validate'; request.schema_version = obj.HedVersion; request.sidecar_string = HedTools.formatSidecar(sidecar); - request.check_for_warnings = checkWarnings; + + if nargin == 3 + request.check_for_warnings = checkWarnings; + else + request.check_for_warnings = false; + end response = webwrite(obj.ServicesUrl, request, obj.WebOptions); response = jsondecode(response); error_msg = HedToolsService.getResponseError(response); @@ -181,22 +162,22 @@ 'HedToolsServiceValidateSidecar:ServiceError', error_msg)); end if strcmpi(response.results.msg_category, 'warning') - issueString = response.results.data; + issues = response.results.data; else - issueString = ''; + issues = ''; end end - function issueString = validateTags(obj, hedtags, checkWarnings) + function issues = validateTags(obj, hedtags, checkWarnings) % Validate a single string of HED tags. % % Parameters: % hedtags - a string or char array with a hed tag string. - % check_warnings - boolean indicating whether to include - % warnings. + % checkWarnings - boolean (optional, default false) + % indicates whether to include warnings. % - % Returns: - % issueString - printable string with issues or an empty + % Returns: + % issues - printable string with issues or an empty % string if no issues. request = obj.getRequestTemplate(); request.service = 'strings_validate'; @@ -205,10 +186,15 @@ throw(MException(... 'HedToolsServiceValidateHedTags:InvalidHedTagInput', ... 'Must provide HED tags as string or char')) - + end + + if nargin == 3 + request.check_for_warnings = checkWarnings; + else + request.check_for_warnings = false; + end request.string_list = {hedtags}; - request.check_for_warnings = checkWarnings; response = webwrite(obj.ServicesUrl, request, obj.WebOptions); response = jsondecode(response); error_msg = HedToolsService.getResponseError(response); @@ -217,12 +203,41 @@ 'HedToolsServiceValidateHedTags:ServiceError', error_msg)); end if strcmpi(response.results.msg_category, 'warning') - issueString = response.results.data; + issues = response.results.data; else - issueString = ''; + issues = ''; end end + function [] = resetHedVersion(obj, hedVersion) + obj.HedVersion = hedVersion; + end + + function [] = resetSessionInfo(obj, host) + %% Reset the session for accessing the HED webservices + % Parameters: + % host = URL for the services + % + % Notes: sets obj.Cookie, obj.CRSFToken and obj.Options. + obj.ServicesUrl = [host '/services_submit']; + request = matlab.net.http.RequestMessage; + uri = matlab.net.URI([host '/services']); + response1 = send(request,uri); + cookies = response1.getFields('Set-Cookie'); + obj.Cookie = cookies.Value; + data = response1.Body.char; + csrfIdx = strfind(data,'csrf_token'); + tmp = data(csrfIdx(1)+length('csrf_token')+1:end); + csrftoken = regexp(tmp,'".*?"','match'); + obj.CSRFToken = string(csrftoken{1}(2:end-1)); + header = ["Content-Type" "application/json"; ... + "Accept" "application/json"; ... + "X-CSRFToken" obj.CSRFToken; "Cookie" obj.Cookie]; + + obj.WebOptions = weboptions('MediaType', 'application/json',... + 'Timeout', 120, 'HeaderFields', header); + end + end methods (Static) diff --git a/tests/test_hed_tools/TestHedToolsPython.m b/tests/test_hed_tools/TestHedToolsPython.m index d8ae644..8c09e65 100644 --- a/tests/test_hed_tools/TestHedToolsPython.m +++ b/tests/test_hed_tools/TestHedToolsPython.m @@ -92,22 +92,6 @@ function testGetHedAnnotations(testCase) testCase.verifyGreaterThan(length(data4_str), length(data3_str)); end - function testGetHedFactors(testCase) - % Simple tests of HED queries on valid strings - annotations = {'Red', 'Sensory-event', 'Blue'}; - queries1 = {'Sensory-event'}; - factors1 = testCase.hed.getHedFactors(annotations, queries1); - testCase.verifyEqual(length(factors1), 3); - testCase.verifyTrue(factors1(2) == 1); - - % Test 2 queries on 3 strings. - queries2 = {'Sensory-event', 'Red'}; - factors2 = testCase.hed.getHedFactors(annotations, queries2); - testCase.verifyTrue(size(factors2, 1) == 3); - testCase.verifyTrue(size(factors2, 2) == 2); - end - - function testGetHedAnnotationsInvalid(testCase) events = fileread(testCase.goodEventsPath); sidecar = fileread(testCase.badSidecarPath); @@ -120,6 +104,21 @@ function testGetHedAnnotationsInvalid(testCase) 'HedToolsPythonGetHedAnnotations:InvalidData'); end + function testSearchHed(testCase) + % Simple tests of HED queries on valid strings + annotations = {'Red', 'Sensory-event', 'Blue'}; + queries1 = {'Sensory-event'}; + factors1 = testCase.hed.searchHed(annotations, queries1); + testCase.verifyEqual(length(factors1), 3); + testCase.verifyTrue(factors1(2) == 1); + + % Test 2 queries on 3 strings. + queries2 = {'Sensory-event', 'Red'}; + factors2 = testCase.hed.searchHed(annotations, queries2); + testCase.verifyTrue(size(factors2, 1) == 3); + testCase.verifyTrue(size(factors2, 2) == 2); + end + function testEventsValidNoSidecar(testCase) % Valid char sidecar should not have errors or warnings eventsChar = fileread(testCase.goodEventsPath); @@ -130,7 +129,7 @@ function testEventsValidNoSidecar(testCase) 'Valid char events no sidecar should not have errors.'); issueString = testCase.hed.validateEvents(... HedTools.formatEvents(eventsChar), py.None, true); - testCase.verifyGreaterThan(strlength(issueString), 0, ... + testCase.verifyGreaterThan(length(issueString), 0, ... 'Valid char events no sidecar has warnings.'); end @@ -353,33 +352,29 @@ function testSidecarInvalid(testCase) end function testTagsValid(testCase) - % Test valid check warnings no warnings - issues = testCase.hed.validateTags('Red, Blue', true); - testCase.verifyEqual(strlength(issues), 0); - % Test valid check warnings has warnings issues = testCase.hed.validateTags('Red, Blue/Apple', true); - testCase.verifyGreaterThan(strlength(issues), 0); + testCase.verifyGreaterThan(length(issues), 0); % Test valid no check warnings has warnings issues = testCase.hed.validateTags('Red, Blue/Apple', false); - testCase.verifyEqual(strlength(issues), 0); + testCase.verifyEqual(length(issues), 0); % Test with extension and no check warnings - issues = testCase.hed.validateTags('Red, Blue/Apple', false); - testCase.verifyEqual(strlength(issues), 0); + issues = testCase.hed.validateTags('Red, Blue/Apple'); + testCase.verifyEqual(length(issues), 0); end function testTagsInvalid(testCase) % Test check warnings with errors issues1 = testCase.hed.validateTags(... 'Red, Blue/Apple, Green, Blech', true); - testCase.verifyGreaterThan(strlength(issues1), 0); + testCase.verifyGreaterThan(length(issues1), 0); % Test no check warnings with errors issues2 = testCase.hed.validateTags(... 'Red, Blue/Apple, Green, Blech', false); - testCase.verifyGreaterThan(strlength(issues2), 0); + testCase.verifyGreaterThan(length(issues2), 0); end function testTagsInvalidFormat(testCase) diff --git a/tests/test_hed_tools/TestHedToolsService.m b/tests/test_hed_tools/TestHedToolsService.m index 746f5a4..2a49979 100644 --- a/tests/test_hed_tools/TestHedToolsService.m +++ b/tests/test_hed_tools/TestHedToolsService.m @@ -13,7 +13,8 @@ methods (TestClassSetup) function setUp(testCase) testCase.hed = ... - HedToolsService('8.2.0', 'http://127.0.0.1:5000'); + HedToolsService('8.2.0', 'https://hedtools.org/hed_dev'); + % HedToolsService('8.2.0', 'http://127.0.0.1:5000'); [curDir, ~, ~] = fileparts(mfilename("fullpath")); dataPath = fullfile(curDir, filesep, '..', filesep, '..', ... filesep, 'data', filesep); @@ -97,20 +98,6 @@ function testGetHedAnnotations(testCase) testCase.verifyGreaterThan(length(data4_str), length(data3_str)); end - function testGetHedFactors(testCase) - % Simple tests of HED queries on valid strings - annotations = {'Red', 'Sensory-event', 'Blue'}; - queries1 = {'Sensory-event'}; - factors1 = testCase.hed.getHedFactors(annotations, queries1); - testCase.verifyEqual(length(factors1), 3); - testCase.verifyEqual(factors1(2), 1); - - % Test 2 queries on 3 strings. - queries2 = {'Sensory-event', 'Red'}; - factors2 = testCase.hed.getHedFactors(annotations, queries2); - testCase.verifyEqual(size(factors2), [3, 2]) - end - function testGetHedAnnotationsInvalid(testCase) events = fileread(testCase.goodEventsPath); sidecar = fileread(testCase.badSidecarPath); @@ -128,13 +115,29 @@ function testEventsValidNoSidecar(testCase) eventsChar = fileread(testCase.goodEventsPath); testCase.verifyTrue(ischar(eventsChar)) issueString = testCase.hed.validateEvents(eventsChar, '', false); - testCase.verifyEqual(strlength(issueString), 0, ... + testCase.verifyEqual(length(issueString), 0, ... 'Valid char events no sidecar should not have errors.'); issueString = testCase.hed.validateEvents(eventsChar, '', true); - testCase.verifyGreaterThan(strlength(issueString), 0, ... + testCase.verifyGreaterThan(length(issueString), 0, ... 'Valid char events no sidecar has warnings.'); end + + function testSearchHed(testCase) + % Simple tests of HED queries on valid strings + annotations = {'Red', 'Sensory-event', 'Blue'}; + queries1 = {'Sensory-event'}; + factors1 = testCase.hed.searchHed(annotations, queries1); + testCase.verifyEqual(length(factors1), 3); + testCase.verifyEqual(factors1(2), 1); + + % Test 2 queries on 3 strings. + queries2 = {'Sensory-event', 'Red'}; + factors2 = testCase.hed.searchHed(annotations, queries2); + testCase.verifyEqual(size(factors2), [3, 2]) + end + + function testEventsValidGoodSidecar(testCase) % Valid char events should not have errors or warnings sidecarChar = fileread(testCase.goodSidecarPath); @@ -142,20 +145,20 @@ function testEventsValidGoodSidecar(testCase) testCase.verifyTrue(ischar(eventsChar)) issueString = testCase.hed.validateEvents(eventsChar, ... sidecarChar, false); - testCase.verifyEqual(strlength(issueString), 0); + testCase.verifyEqual(length(issueString), 0); issueString = testCase.hed.validateEvents(... eventsChar, sidecarChar, true); - testCase.verifyEqual(strlength(issueString), 0); + testCase.verifyEqual(length(issueString), 0); % Valid string events should not have errors or warnings eventsString = string(eventsChar); testCase.verifyTrue(isstring(eventsString)) issueString = testCase.hed.validateEvents(... eventsString, sidecarChar, false); - testCase.verifyEqual(strlength(issueString), 0'); + testCase.verifyEqual(length(issueString), 0'); issueString = testCase.hed.validateEvents(... (eventsString), sidecarChar, true); - testCase.verifyEqual(strlength(issueString), 0); + testCase.verifyEqual(length(issueString), 0); end function testEventsValidBadSidecar(testCase) @@ -329,31 +332,31 @@ function testSidecarInvalid(testCase) function testTagsValid(testCase) % Test valid check warnings no warnings issues = testCase.hed.validateTags('Red, Blue', true); - testCase.verifyEqual(strlength(issues), 0); + testCase.verifyEqual(length(issues), 0); % Test valid check warnings has warnings issues = testCase.hed.validateTags('Red, Blue/Apple', true); - testCase.verifyGreaterThan(strlength(issues), 0); + testCase.verifyGreaterThan(length(issues), 0); % Test valid no check warnings has warnings issues = testCase.hed.validateTags('Red, Blue/Apple', false); - testCase.verifyEqual(strlength(issues), 0); + testCase.verifyEqual(length(issues), 0); % Test with extension and no check warnings - issues = testCase.hed.validateTags('Red, Blue/Apple', false); - testCase.verifyEqual(strlength(issues), 0); + issues = testCase.hed.validateTags('Red, Blue/Apple'); + testCase.verifyEqual(length(issues), 0); end function testTagsInvalid(testCase) % Test check warnings with errors issues1 = testCase.hed.validateTags(... 'Red, Blue/Apple, Green, Blech', true); - testCase.verifyGreaterThan(strlength(issues1), 0); + testCase.verifyGreaterThan(length(issues1), 0); % Test no check warnings with errors issues2 = testCase.hed.validateTags(... 'Red, Blue/Apple, Green, Blech', false); - testCase.verifyGreaterThan(strlength(issues2), 0); + testCase.verifyGreaterThan(length(issues2), 0); end function testTagsInvalidFormat(testCase) From b0a066e96f0b926ee192e8d1094af5a7c29994a6 Mon Sep 17 00:00:00 2001 From: Kay Robbins <1189050+VisLab@users.noreply.github.com> Date: Sun, 9 Jun 2024 13:46:22 -0500 Subject: [PATCH 2/2] Changed interface to use Name-value pairs for optional boolean flags --- README.md | 27 +--- hedmat/hedtools/HedToolsPython.m | 68 +++++---- hedmat/hedtools/HedToolsService.m | 81 ++++++----- tests/test_hed_tools/TestHedToolsPython.m | 137 ++++++++--------- tests/test_hed_tools/TestHedToolsService.m | 162 +++++++++++---------- 5 files changed, 244 insertions(+), 231 deletions(-) diff --git a/README.md b/README.md index d8d46f3..65a0106 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,8 @@ [![Documentation Status](https://readthedocs.org/projects/hed-matlab/badge/?version=latest)](https://www.hed-matlab.org/en/latest/?badge=latest) -[![@HEDstandard](http://img.shields.io/twitter/follow/hedstandard.svg?style=social)](https://twitter.com/HEDstandard) # HED-MATLAB -This repository contains the MATLAB supporting code infrastructure for Hierarchical Event Descriptors (HED). +This repository contains the MATLAB supporting code infrastructure +for Hierarchical Event Descriptors (HED). - -### Installation of hedtools - -The most of the Python-related resources in this repository -require the installation of the HEDTools Python module, which can be -installed using `pip` or directly from its GitHub repository as follows: - -To use `pip` to install `hedtools` from PyPI: - - ``` - pip install hedtools - ``` - -To install directly from the -[GitHub](https://github.com/hed-standard/hed-python) repository: - - ``` - pip install git+https://github.com/hed-standard/hed-python/@master - ``` - -HEDTools require python 3.7 or greater. +The documentation for this repository can be found at +[**HED MATLAB Tools**](https://www.hed-resources.org/en/latest/HedMatlabTools.html). \ No newline at end of file diff --git a/hedmat/hedtools/HedToolsPython.m b/hedmat/hedtools/HedToolsPython.m index 7076841..3e031c7 100644 --- a/hedmat/hedtools/HedToolsPython.m +++ b/hedmat/hedtools/HedToolsPython.m @@ -19,16 +19,18 @@ end function annotations = getHedAnnotations(obj, events, ... - sidecar, removeTypesOn, includeContext, replaceDefs) + sidecar, varargin) % Return a cell array of HED annotations of same length as events. % % Parameters: % events - char, string or rectified struct. % sidecar - char, string or struct representing sidecar - % removeTypesOn - boolean true->remove Condition-variable - % and Task - % includeContext - boolean true->expand context (usually true). - % replaceDefs - boolean true->replace def with definition (usually true). + % + % Optional name-value: + % 'includeContext' - boolean true->expand context (usually true). + % 'removeTypesOn' - boolean true-> remove Condition-variable + % and Task + % 'replaceDefs' - boolean true->replace def with definition (usually true). % % Returns: % annotations - cell array with the HED annotations. @@ -38,15 +40,22 @@ % line. % + p = inputParser; + p.addParameter('includeContext', true, @(x) islogical(x)) + p.addParameter('removeTypesOn', true, @(x) islogical(x)) + p.addParameter('replaceDefs', true, @(x) islogical(x)) + parse(p, varargin{:}); eventsTab = HedToolsPython.getTabularObj(events, sidecar); - issueString = obj.validateEvents(eventsTab, sidecar, false); + issueString = obj.validateEvents(eventsTab, sidecar, ... + 'checkWarnings', false); if ~isempty(issueString) throw(MException( ... 'HedToolsPythonGetHedAnnotations:InvalidData', ... "Input errors:\n" + issueString)); end hedObjs = HedToolsPython.getHedStringObjs(eventsTab, ... - obj.HedSchema, removeTypesOn, includeContext, replaceDefs); + obj.HedSchema, p.Results.removeTypesOn, ... + p.Results.includeContext, p.Results.replaceDefs); strs = ... py.hed.tools.analysis.annotation_util.to_strlist(hedObjs); cStrs = cell(strs); @@ -83,23 +92,25 @@ factors = double(df_factors.to_numpy()); end - function issues = validateEvents(obj, events, sidecar, checkWarnings) + function issues = validateEvents(obj, events, sidecar, varargin) % Validate HED in events or other tabular-type input. % % Parameters: % events - char array, string, struct (or tabularInput) % sidecar - char, string or struct representing sidecar - % checkWarnings - boolean (optional, default false) - % indicates whether to include warnings. % + % Optional name-value: + % 'checkWarnings' - boolean (optional, default false) + % indicates whether to include warnings. % Returns: % issues - A string with the validation issues suitable for % printing (has newlines). sidecarObj = py.None; - if nargin <= 2 - checkWarnings = false; - end + p = inputParser; + p.addParameter('checkWarnings', false, @(x) islogical(x)) + parse(p, varargin{:}); + checkWarnings = p.Results.checkWarnings; issues = ''; ehandler = py.hed.errors.error_reporter.ErrorHandler(... check_for_warnings=checkWarnings); @@ -120,23 +131,25 @@ end - function issues = validateSidecar(obj, sidecar, checkWarnings) + function issues = validateSidecar(obj, sidecar, varargin) % Validate a sidecar containing HED tags. % % Parameters: % sidecar - a char, string, struct, or SidecarObj - % checkWarnings - boolean (optional, default false) + % + % Optional name-value: + % 'checkWarnings' - boolean (optional, default false) % indicates whether to include warnings. % % Returns: % issues - Char array with the validation issues suitable % for printing (has newlines). - if nargin <= 2 - checkWarnings = false; - end + p = inputParser; + p.addParameter('checkWarnings', false, @(x) islogical(x)) + parse(p, varargin{:}); ehandler = py.hed.errors.error_reporter.ErrorHandler(... - check_for_warnings=checkWarnings); + check_for_warnings=p.Results.checkWarnings); sidecarObj = HedToolsPython.getSidecarObj(sidecar); issues = sidecarObj.validate(obj.HedSchema, error_handler=ehandler); if isempty(issues) @@ -147,12 +160,14 @@ end end - function issues = validateTags(obj, hedTags, checkWarnings) + function issues = validateTags(obj, hedTags, varargin) % Validate a string containing HED tags. % % Parameters: % hedTags - A MATLAB string or character array. - % checkWarnings - boolean (optional, default false) + % + % Optional name-value: + % 'checkWarnings' - boolean (optional, default false) % indicates whether to include warnings. % % Returns: @@ -163,17 +178,16 @@ if ~ischar(hedTags) && ~isstring(hedTags) throw(MException(... - 'HedToolsPythonValidateHedTags:InvalidHedTagInput', ... + 'HedToolsPythonValidateTags:InvalidHedTagInput', ... 'Must provide a string or char array as input')) end + p = inputParser; + p.addParameter('checkWarnings', false, @(x) islogical(x)) + parse(p, varargin{:}); - if nargin <= 2 - checkWarnings = false; - end - hedStringObj = py.hed.HedString(hedTags, obj.HedSchema); ehandler = py.hed.errors.error_reporter.ErrorHandler(... - check_for_warnings=checkWarnings); + check_for_warnings=p.Results.checkWarnings); validator = ... py.hed.validator.hed_validator.HedValidator(obj.HedSchema); issues = validator.validate(hedStringObj, false, ... diff --git a/hedmat/hedtools/HedToolsService.m b/hedmat/hedtools/HedToolsService.m index d23ccb1..3722bba 100644 --- a/hedmat/hedtools/HedToolsService.m +++ b/hedmat/hedtools/HedToolsService.m @@ -23,16 +23,18 @@ end function annotations = getHedAnnotations(obj, eventsIn, ... - sidecar, removeTypesOn, includeContext, replaceDefs) + sidecar, varargin) % Return a cell array of HED annotations of same length as events. % % Parameters: % eventsIn - char, string or rectified struct. % sidecar - char, string or struct representing sidecar - % removeTypesOn - boolean true-> remove Condition-variable + % + % Optional name-value: + % 'includeContext' - boolean true->expand context (usually true). + % 'removeTypesOn' - boolean true-> remove Condition-variable % and Task - % includeContext - boolean true->expand context (usually true). - % replaceDefs - boolean true->replace def with definition (usually true). + % 'replaceDefs' - boolean true->replace def with definition (usually true). % % Returns: % annotations - cell array with the HED annotations. @@ -41,16 +43,20 @@ % events in char or string form is assumed to have a header % line. % - + p = inputParser; + p.addParameter('includeContext', true, @(x) islogical(x)) + p.addParameter('removeTypesOn', true, @(x) islogical(x)) + p.addParameter('replaceDefs', true, @(x) islogical(x)) + parse(p, varargin{:}); request = obj.getRequestTemplate(); request.service = 'events_assemble'; request.schema_version = obj.HedVersion; request.events_string = HedTools.formatEvents(eventsIn); request.sidecar_string = HedTools.formatSidecar(sidecar); request.check_for_warnings = false; - request.remove_types_on = removeTypesOn; - request.include_context = includeContext; - request.replace_defs = replaceDefs; + request.remove_types_on = p.Results.removeTypesOn; + request.include_context = p.Results.includeContext; + request.replace_defs = p.Results.replaceDefs; response = webwrite(obj.ServicesUrl, request, obj.WebOptions); response = jsondecode(response); error_msg = HedToolsService.getResponseError(response); @@ -95,29 +101,30 @@ factors = response.results.data; end - function issues = validateEvents(obj, events, sidecar, checkWarnings) + function issues = validateEvents(obj, events, sidecar, varargin) % Validate HED in events or other tabular-type input. % % Parameters: % events - char, string or rectified struct. % sidecar - char, string or struct representing sidecar - % checkWarnings - boolean (optional, default false) + % + % Optional name-value: + % 'checkWarnings' - boolean (optional, default false) % indicates whether to include warnings. % % Returns: % issues - A string with the validation issues suitable for % printing (has newlines). + p = inputParser; + p.addParameter('checkWarnings', false, @(x) islogical(x)) + parse(p, varargin{:}); request = obj.getRequestTemplate(); request.service = 'events_validate'; request.schema_version = obj.HedVersion; request.events_string = HedTools.formatEvents(events); request.sidecar_string = HedTools.formatSidecar(sidecar); - if nargin == 4 - request.check_for_warnings = checkWarnings; - else - request.check_for_warnings = false; - end + request.check_for_warnings = p.Results.checkWarnings; response = webwrite(obj.ServicesUrl, request, obj.WebOptions); response = jsondecode(response); error_msg = HedToolsService.getResponseError(response); @@ -132,28 +139,29 @@ end end - function issues = validateSidecar(obj, sidecar, checkWarnings) + function issues = validateSidecar(obj, sidecar, varargin) % Validate a sidecar % % Parameters: % sidecar - a string, struct, or char array representing % a sidecar - % checkWarnings - boolean (optional, default false) + % + % Optional name-value: + % 'checkWarnings' - boolean (optional, default false) % indicates whether to include warnings. % % Returns: % issues - printable issue string or empty % + p = inputParser; + p.addParameter('checkWarnings', false, @(x) islogical(x)) + parse(p, varargin{:}); + request = obj.getRequestTemplate(); request.service = 'sidecar_validate'; request.schema_version = obj.HedVersion; request.sidecar_string = HedTools.formatSidecar(sidecar); - - if nargin == 3 - request.check_for_warnings = checkWarnings; - else - request.check_for_warnings = false; - end + request.check_for_warnings = p.Results.checkWarnings; response = webwrite(obj.ServicesUrl, request, obj.WebOptions); response = jsondecode(response); error_msg = HedToolsService.getResponseError(response); @@ -168,39 +176,40 @@ end end - function issues = validateTags(obj, hedtags, checkWarnings) + function issues = validateTags(obj, hedtags, varargin) % Validate a single string of HED tags. % % Parameters: % hedtags - a string or char array with a hed tag string. - % checkWarnings - boolean (optional, default false) + % + % Optional name-value: + % 'checkWarnings' - boolean (optional, default false) % indicates whether to include warnings. % - % Returns: + % % issues - printable string with issues or an empty % string if no issues. + + p = inputParser; + p.addParameter('checkWarnings', false, @(x) islogical(x)) + parse(p, varargin{:}); + request = obj.getRequestTemplate(); request.service = 'strings_validate'; request.schema_version = obj.HedVersion; if ~ischar(hedtags) && ~isstring(hedtags) throw(MException(... - 'HedToolsServiceValidateHedTags:InvalidHedTagInput', ... - 'Must provide HED tags as string or char')) - + 'HedToolsServiceValidateTags:InvalidHedTagInput', ... + 'Must provide HED tags as string or char')) end - - if nargin == 3 - request.check_for_warnings = checkWarnings; - else - request.check_for_warnings = false; - end + request.check_for_warnings = p.Results.checkWarnings; request.string_list = {hedtags}; response = webwrite(obj.ServicesUrl, request, obj.WebOptions); response = jsondecode(response); error_msg = HedToolsService.getResponseError(response); if error_msg throw(MException(... - 'HedToolsServiceValidateHedTags:ServiceError', error_msg)); + 'HedToolsServiceValidateTags:ServiceError', error_msg)); end if strcmpi(response.results.msg_category, 'warning') issues = response.results.data; diff --git a/tests/test_hed_tools/TestHedToolsPython.m b/tests/test_hed_tools/TestHedToolsPython.m index 8c09e65..263ea31 100644 --- a/tests/test_hed_tools/TestHedToolsPython.m +++ b/tests/test_hed_tools/TestHedToolsPython.m @@ -50,43 +50,35 @@ function testGetHedAnnotations(testCase) testCase.verifyTrue(ischar(eventsChar)) % no types, no context, no replace - removeTypesOn = false; - includeContext = false; - replaceDefs = false; annotations = testCase.hed.getHedAnnotations(eventsChar, ... - sidecarChar, removeTypesOn, includeContext, replaceDefs); + sidecarChar, 'removeTypesOn', true, ... + 'includeContext', false, 'replaceDefs', false); testCase.verifyEqual(length(annotations), 199); testCase.verifyEmpty(annotations{195}); data1_str = strjoin(annotations, '\n'); - testCase.verifyEqual(length(data1_str), 14678); + testCase.verifyEqual(length(data1_str), 10547); % With context, no remove, no replace - removeTypesOn = false; - includeContext = true; - replaceDefs = false; annotations = testCase.hed.getHedAnnotations(eventsChar, ... - sidecarChar, removeTypesOn, includeContext, replaceDefs); + sidecarChar, 'removeTypesOn', false, ... + 'includeContext', true, 'replaceDefs', false); testCase.verifyEqual(length(annotations), 199); testCase.verifyGreaterThan(length(annotations{195}), 0); data2_str = strjoin(annotations, '\n'); testCase.verifyGreaterThan(length(data2_str), length(data1_str)); % With context, remove, no replace - removeTypesOn = true; - replaceDefs = false; - includeContext = true; annotations = testCase.hed.getHedAnnotations(eventsChar, ... - sidecarChar, removeTypesOn, includeContext, replaceDefs); + sidecarChar, 'removeTypesOn', true, ... + 'includeContext', true, 'replaceDefs', false); testCase.verifyEqual(length(annotations), 199); data3_str = strjoin(annotations, '\n'); testCase.verifyGreaterThan(length(data2_str), length(data3_str)); % With context, remove, replace - removeTypesOn = true; - replaceDefs = true; - includeContext = true; annotations = testCase.hed.getHedAnnotations(eventsChar, ... - sidecarChar, removeTypesOn, includeContext, replaceDefs); + sidecarChar, 'removeTypesOn', true, ... + 'includeContext', true, 'replaceDefs', true); testCase.verifyEqual(length(annotations), 199); data4_str = strjoin(annotations, '\n'); testCase.verifyGreaterThan(length(data4_str), length(data3_str)); @@ -95,12 +87,10 @@ function testGetHedAnnotations(testCase) function testGetHedAnnotationsInvalid(testCase) events = fileread(testCase.goodEventsPath); sidecar = fileread(testCase.badSidecarPath); - removeTypes = {'Condition-variable', 'Task'}; - includeContext = true; - replaceDefs = false; testCase.verifyError( ... @ ()testCase.hed.getHedAnnotations(events, sidecar, ... - removeTypes, includeContext, replaceDefs), ... + 'removeTypesOn', true, ... + 'includeContext', true, 'replaceDefs', false), ... 'HedToolsPythonGetHedAnnotations:InvalidData'); end @@ -124,11 +114,13 @@ function testEventsValidNoSidecar(testCase) eventsChar = fileread(testCase.goodEventsPath); testCase.verifyTrue(ischar(eventsChar)) issueString = testCase.hed.validateEvents( ... - HedTools.formatEvents(eventsChar), '', false); + HedTools.formatEvents(eventsChar), '', ... + 'checkWarnings', false); testCase.verifyEqual(strlength(issueString), 0, ... 'Valid char events no sidecar should not have errors.'); issueString = testCase.hed.validateEvents(... - HedTools.formatEvents(eventsChar), py.None, true); + HedTools.formatEvents(eventsChar), py.None, ... + 'checkWarnings', true); testCase.verifyGreaterThan(length(issueString), 0, ... 'Valid char events no sidecar has warnings.'); end @@ -140,21 +132,23 @@ function testEventsValidGoodSidecar(testCase) testCase.verifyTrue(ischar(eventsChar)) issueString = testCase.hed.validateEvents(... HedTools.formatEvents(eventsChar), ... - sidecarChar, false); + sidecarChar, 'checkWarnings', false); testCase.verifyEqual(strlength(issueString), 0); issueString = testCase.hed.validateEvents(... HedTools.formatEvents(eventsChar), ... - sidecarChar, true); + sidecarChar, 'checkWarnings', true); testCase.verifyEqual(strlength(issueString), 0); % Valid string events should not have errors or warnings eventsString = string(eventsChar); testCase.verifyTrue(isstring(eventsString)) issueString = testCase.hed.validateEvents( ... - HedTools.formatEvents(eventsString), sidecarChar, false); + HedTools.formatEvents(eventsString), sidecarChar, ... + 'checkWarnings', false); testCase.verifyEqual(strlength(issueString), 0'); issueString = testCase.hed.validateEvents(... - HedTools.formatEvents(eventsString), sidecarChar, true); + HedTools.formatEvents(eventsString), sidecarChar, ... + 'checkWarnings', true); testCase.verifyEqual(strlength(issueString), 0); end @@ -164,20 +158,22 @@ function testEventsValidBadSidecar(testCase) eventsChar = fileread(testCase.goodEventsPath); testCase.verifyTrue(ischar(eventsChar)) issueString = testCase.hed.validateEvents(eventsChar, ... - sidecarChar, false); + sidecarChar, 'checkWarnings', false); testCase.verifyGreaterThan(strlength(issueString), 0); issueString = testCase.hed.validateEvents(eventsChar, ... - sidecarChar, true); + sidecarChar, 'checkWarnings', true); testCase.verifyGreaterThan(strlength(issueString), 0); % Valid string events should not have errors or warnings eventsString = string(eventsChar); testCase.verifyTrue(isstring(eventsString)) issueString = testCase.hed.validateEvents( ... - HedTools.formatEvents(eventsString), sidecarChar, false); + HedTools.formatEvents(eventsString), sidecarChar, ... + 'checkWarnings', false); testCase.verifyGreaterThan(strlength(issueString), 0'); issueString = testCase.hed.validateEvents(... - HedTools.formatEvents(eventsString), sidecarChar, true); + HedTools.formatEvents(eventsString), sidecarChar, ... + 'checkWarnings', true); testCase.verifyGreaterThan(strlength(issueString), 0); end @@ -189,19 +185,21 @@ function testEventsValidStructWithOnset(testCase) testCase.verifyTrue(isstruct(eventsRectified)); issueString = testCase.hed.validateEvents( ... HedTools.formatEvents(eventsRectified), ... - testCase.sidecarStructGood, true); + testCase.sidecarStructGood, 'checkWarnings', true); testCase.verifyGreaterThan(strlength(issueString), 0); issueString = testCase.hed.validateEvents( ... HedTools.formatEvents(eventsRectified), ... - testCase.sidecarStructGood, false); + testCase.sidecarStructGood, 'checkWarnings', false); testCase.verifyEqual(strlength(issueString), 0); issueString = testCase.hed.validateEvents( ... - HedTools.formatEvents(eventsRectified), '', true); + HedTools.formatEvents(eventsRectified), '', ... + 'checkWarnings', true); testCase.verifyGreaterThan(strlength(issueString), 0); issueString = testCase.hed.validateEvents( ... - HedTools.formatEvents(eventsRectified), '', false); + HedTools.formatEvents(eventsRectified), '', ... + 'checkWarnings', false); testCase.verifyEqual(strlength(issueString), 0); end @@ -212,19 +210,21 @@ function testEventsValidStructNoOnset(testCase) testCase.verifyTrue(isstruct(eventsRectified)); issueString = testCase.hed.validateEvents( ... HedTools.formatEvents(eventsRectified), ... - testCase.sidecarStructGood, true); + testCase.sidecarStructGood, 'checkWarnings', true); testCase.verifyGreaterThan(strlength(issueString), 0); issueString = testCase.hed.validateEvents( ... HedTools.formatEvents(eventsRectified), ... - testCase.sidecarStructGood, false); + testCase.sidecarStructGood, 'checkWarnings', false); testCase.verifyEqual(strlength(issueString), 0); issueString = testCase.hed.validateEvents( ... - HedTools.formatEvents(eventsRectified), '', true); + HedTools.formatEvents(eventsRectified), '', ... + 'checkWarnings', true); testCase.verifyGreaterThan(strlength(issueString), 0); issueString = testCase.hed.validateEvents( ... - HedTools.formatEvents(eventsRectified), '', false); + HedTools.formatEvents(eventsRectified), '', ... + 'checkWarnings', false); testCase.verifyEqual(strlength(issueString), 0); end @@ -232,11 +232,11 @@ function testEventsValidStructNoOnsetNoSampling(testCase) % Unrectified struct events no onset. issueString = testCase.hed.validateEvents( ... testCase.eventsStructNoOnset, ... - testCase.sidecarStructGood, false); + testCase.sidecarStructGood, 'checkWarnings', false); testCase.verifyEmpty(issueString); issueString = testCase.hed.validateEvents( ... testCase.eventsStructNoOnset, ... - testCase.sidecarStructGood, true); + testCase.sidecarStructGood, 'checkWarnings', true); testCase.verifyGreaterThan(length(issueString), 0); end @@ -244,7 +244,8 @@ function testEventsInvalid(testCase) sidecarChar = fileread(testCase.badSidecarPath); eventsChar = fileread(testCase.goodEventsPath); issueString = testCase.hed.validateEvents(... - HedTools.formatEvents(eventsChar), sidecarChar, true); + HedTools.formatEvents(eventsChar), sidecarChar, ... + 'checkWarnings', true); testCase.verifyTrue(ischar(issueString)); testCase.verifyGreaterThan(length(issueString), 0); end @@ -254,36 +255,36 @@ function testSidecarValid(testCase) sidecarChar = fileread(testCase.goodSidecarPath); testCase.verifyTrue(ischar(sidecarChar)) issueString = testCase.hed.validateSidecar( ... - sidecarChar, false); + sidecarChar, 'checkWarnings', false); testCase.verifyEqual(strlength(issueString), 0); % Valid char sidecar should not have errors or warnings issueString = testCase.hed.validateSidecar(... - sidecarChar, true); + sidecarChar, 'checkWarnings', true); testCase.verifyEqual(strlength(issueString), 0); % Valid string sidecar should not have errors sidecarString = string(sidecarChar); testCase.verifyTrue(isstring(sidecarString)) issueString = testCase.hed.validateSidecar( ... - sidecarString, false); + sidecarString, 'checkWarnings', false); testCase.verifyEqual(strlength(issueString), 0); % Valid char sidecar should not have errors or warnings. issueString = testCase.hed.validateSidecar(... - sidecarString, true); + sidecarString, 'checkWarnings', true); testCase.verifyEqual(strlength(issueString), 0); % Valid struct sidecar should not have errors or warnings sidecarStruct = jsondecode(sidecarChar); testCase.verifyTrue(isstruct(sidecarStruct)) issueString = testCase.hed.validateSidecar( ... - sidecarStruct, false); + sidecarStruct, 'checkWarnings', false); testCase.verifyEqual(strlength(issueString), 0); % Valid struct sidecar should not have errors or warnings issueString = testCase.hed.validateSidecar(... - sidecarStruct, true); + sidecarStruct, 'checkWarnings', true); testCase.verifyEqual(strlength(issueString), 0); % Valid sidecar obj should not have errors or warnings @@ -291,12 +292,12 @@ function testSidecarValid(testCase) testCase.verifyTrue(py.isinstance(sidecarObj, ... testCase.hmod.Sidecar)) issueString = testCase.hed.validateSidecar( ... - sidecarObj, false); + sidecarObj, 'checkWarnings', false); testCase.verifyEqual(strlength(issueString), 0); % Valid sidecar obj should not have errors or warnings issueString = testCase.hed.validateSidecar(... - sidecarObj, true); + sidecarObj, 'checkWarnings', true); testCase.verifyEqual(strlength(issueString), 0); end @@ -305,36 +306,36 @@ function testSidecarInvalid(testCase) sidecarChar = fileread(testCase.badSidecarPath); testCase.verifyTrue(ischar(sidecarChar)) issueString = testCase.hed.validateSidecar( ... - sidecarChar, false); + sidecarChar, 'checkWarnings', false); testCase.verifyGreaterThan(strlength(issueString), 0); % Invalid char sidecar should have errors with warning on issueString = testCase.hed.validateSidecar(... - sidecarChar, true); + sidecarChar, 'checkWarnings', true); testCase.verifyGreaterThan(strlength(issueString), 0); % Invalid string sidecar should have errors sidecarString = string(sidecarChar); testCase.verifyTrue(isstring(sidecarString)) issueString = testCase.hed.validateSidecar( ... - sidecarString, false); + sidecarString, 'checkWarnings', false); testCase.verifyGreaterThan(strlength(issueString), 0); % Invalid string sidecar should have errors with warning on issueString = testCase.hed.validateSidecar(... - sidecarString, true); + sidecarString, 'checkWarnings', true); testCase.verifyGreaterThan(strlength(issueString), 0); % Invalid struct sidecar should have errors sidecarStruct = jsondecode(sidecarChar); testCase.verifyTrue(isstruct(sidecarStruct)) issueString = testCase.hed.validateSidecar( ... - sidecarStruct, false); + sidecarStruct, 'checkWarnings', false); testCase.verifyGreaterThan(strlength(issueString), 0); % Invalid struct sidecar should have errors with warning on issueString = testCase.hed.validateSidecar(... - sidecarStruct, true); + sidecarStruct, 'checkWarnings', true); testCase.verifyGreaterThan(strlength(issueString), 0); % Invalid sidecar obj should have errors @@ -342,22 +343,24 @@ function testSidecarInvalid(testCase) testCase.verifyTrue(py.isinstance(sidecarObj, ... testCase.hmod.Sidecar)) issueString = testCase.hed.validateSidecar( ... - sidecarObj, false); + sidecarObj, 'checkWarnings', false); testCase.verifyGreaterThan(strlength(issueString), 0); % Invalid sidecar obj should have errors with warning on issueString = testCase.hed.validateSidecar(... - sidecarObj, true); + sidecarObj, 'checkWarnings', true); testCase.verifyGreaterThan(strlength(issueString), 0); end function testTagsValid(testCase) % Test valid check warnings has warnings - issues = testCase.hed.validateTags('Red, Blue/Apple', true); + issues = testCase.hed.validateTags('Red, Blue/Apple', ... + 'checkWarnings', true); testCase.verifyGreaterThan(length(issues), 0); % Test valid no check warnings has warnings - issues = testCase.hed.validateTags('Red, Blue/Apple', false); + issues = testCase.hed.validateTags('Red, Blue/Apple', ... + 'checkWarnings', false); testCase.verifyEqual(length(issues), 0); % Test with extension and no check warnings @@ -368,23 +371,25 @@ function testTagsValid(testCase) function testTagsInvalid(testCase) % Test check warnings with errors issues1 = testCase.hed.validateTags(... - 'Red, Blue/Apple, Green, Blech', true); + 'Red, Blue/Apple, Green, Blech', 'checkWarnings', true); testCase.verifyGreaterThan(length(issues1), 0); % Test no check warnings with errors issues2 = testCase.hed.validateTags(... - 'Red, Blue/Apple, Green, Blech', false); + 'Red, Blue/Apple, Green, Blech', 'checkWarnings', false); testCase.verifyGreaterThan(length(issues2), 0); end function testTagsInvalidFormat(testCase) % Test pass cell array (should only take strings) testCase.verifyError(@() testCase.hed.validateTags( ... - {'Red, Blue/Apple', 'Green, Blech'}, true), ... - 'HedToolsPythonValidateHedTags:InvalidHedTagInput'); + {'Red, Blue/Apple', 'Green, Blech'}, ... + 'checkWarnings', true), ... + 'HedToolsPythonValidateTags:InvalidHedTagInput'); testCase.verifyError(@() testCase.hed.validateTags( ... - {'Red, Blue/Apple', 'Green, Blech'}, false), ... - 'HedToolsPythonValidateHedTags:InvalidHedTagInput'); + {'Red, Blue/Apple', 'Green, Blech'}, ... + 'checkWarnings', false), ... + 'HedToolsPythonValidateTags:InvalidHedTagInput'); end function testGetHedQueryHandler(testCase) diff --git a/tests/test_hed_tools/TestHedToolsService.m b/tests/test_hed_tools/TestHedToolsService.m index 2a49979..f99e254 100644 --- a/tests/test_hed_tools/TestHedToolsService.m +++ b/tests/test_hed_tools/TestHedToolsService.m @@ -56,43 +56,35 @@ function testGetHedAnnotations(testCase) testCase.verifyTrue(ischar(eventsChar)) % no types, no context, no replace - removeTypes = {}; - includeContext = false; - replaceDefs = false; annotations = testCase.hed.getHedAnnotations(eventsChar, ... - sidecarChar, removeTypes, includeContext, replaceDefs); + sidecarChar, 'removeTypesOn', true, ... + 'includeContext', false, 'replaceDefs', false); testCase.verifyEqual(length(annotations), 199); testCase.verifyEmpty(annotations{195}); data1_str = strjoin(annotations, '\n'); - testCase.verifyEqual(length(data1_str), 14678); + testCase.verifyEqual(length(data1_str), 10547); - % With context, no remove, no replace - removeTypesOn = false; - includeContext = true; - replaceDefs = false; + % With context, no remove, no replace annotations = testCase.hed.getHedAnnotations(eventsChar, ... - sidecarChar, removeTypesOn, includeContext, replaceDefs); + sidecarChar, 'removeTypesOn', false, ... + 'includeContext', true, 'replaceDefs', false); testCase.verifyEqual(length(annotations), 199); testCase.verifyGreaterThan(length(annotations{195}), 0); data2_str = strjoin(annotations, '\n'); testCase.verifyGreaterThan(length(data2_str), length(data1_str)); % With context, remove, no replace - removeTypesOn = true; - replaceDefs = false; - includeContext = true; annotations = testCase.hed.getHedAnnotations(eventsChar, ... - sidecarChar, removeTypesOn, includeContext, replaceDefs); + sidecarChar, 'removeTypesOn', true, ... + 'includeContext', true, 'replaceDefs', false); testCase.verifyEqual(length(annotations), 199); data3_str = strjoin(annotations, '\n'); testCase.verifyGreaterThan(length(data2_str), length(data3_str)); % With context, remove, replace - removeTypesOn = true; - replaceDefs = true; - includeContext = true; annotations = testCase.hed.getHedAnnotations(eventsChar, ... - sidecarChar, removeTypesOn, includeContext, replaceDefs); + sidecarChar, 'removeTypesOn', true, ... + 'includeContext', true, 'replaceDefs', true); testCase.verifyEqual(length(annotations), 199); data4_str = strjoin(annotations, '\n'); testCase.verifyGreaterThan(length(data4_str), length(data3_str)); @@ -101,28 +93,13 @@ function testGetHedAnnotations(testCase) function testGetHedAnnotationsInvalid(testCase) events = fileread(testCase.goodEventsPath); sidecar = fileread(testCase.badSidecarPath); - removeTypesOn = true; - includeContext = true; - replaceDefs = false; testCase.verifyError( ... @ ()testCase.hed.getHedAnnotations(events, sidecar, ... - removeTypesOn, includeContext, replaceDefs), ... + 'removeTypesOn', true, ... + 'includeContext', true, 'replaceDefs', false), ... 'HedToolsServiceGetHedAnnotations:InvalidData'); end - function testEventsValidNoSidecar(testCase) - % Valid char sidecar should not have errors or warnings - eventsChar = fileread(testCase.goodEventsPath); - testCase.verifyTrue(ischar(eventsChar)) - issueString = testCase.hed.validateEvents(eventsChar, '', false); - testCase.verifyEqual(length(issueString), 0, ... - 'Valid char events no sidecar should not have errors.'); - issueString = testCase.hed.validateEvents(eventsChar, '', true); - testCase.verifyGreaterThan(length(issueString), 0, ... - 'Valid char events no sidecar has warnings.'); - end - - function testSearchHed(testCase) % Simple tests of HED queries on valid strings annotations = {'Red', 'Sensory-event', 'Blue'}; @@ -137,6 +114,18 @@ function testSearchHed(testCase) testCase.verifyEqual(size(factors2), [3, 2]) end + function testEventsValidNoSidecar(testCase) + % Valid char sidecar should not have errors or warnings + eventsChar = fileread(testCase.goodEventsPath); + testCase.verifyTrue(ischar(eventsChar)) + issueString = testCase.hed.validateEvents(eventsChar, ''); + testCase.verifyEqual(length(issueString), 0, ... + 'Valid char events no sidecar should not have errors.'); + issueString = testCase.hed.validateEvents(eventsChar, '', ... + 'checkWarnings', true); + testCase.verifyGreaterThan(length(issueString), 0, ... + 'Valid char events no sidecar has warnings.'); + end function testEventsValidGoodSidecar(testCase) % Valid char events should not have errors or warnings @@ -144,20 +133,20 @@ function testEventsValidGoodSidecar(testCase) eventsChar = fileread(testCase.goodEventsPath); testCase.verifyTrue(ischar(eventsChar)) issueString = testCase.hed.validateEvents(eventsChar, ... - sidecarChar, false); + sidecarChar, 'checkWarnings', false); testCase.verifyEqual(length(issueString), 0); issueString = testCase.hed.validateEvents(... - eventsChar, sidecarChar, true); + eventsChar, sidecarChar, 'checkWarnings', true); testCase.verifyEqual(length(issueString), 0); % Valid string events should not have errors or warnings eventsString = string(eventsChar); testCase.verifyTrue(isstring(eventsString)) issueString = testCase.hed.validateEvents(... - eventsString, sidecarChar, false); - testCase.verifyEqual(length(issueString), 0'); + eventsString, sidecarChar, 'checkWarnings', false); + testCase.verifyEqual(length(issueString), 0); issueString = testCase.hed.validateEvents(... - (eventsString), sidecarChar, true); + eventsString, sidecarChar, 'checkWarnings', true); testCase.verifyEqual(length(issueString), 0); end @@ -167,10 +156,10 @@ function testEventsValidBadSidecar(testCase) eventsChar = fileread(testCase.goodEventsPath); testCase.verifyTrue(ischar(eventsChar)) issueString = testCase.hed.validateEvents(eventsChar, ... - sidecarChar, false); + sidecarChar, 'checkWarnings', false); testCase.verifyGreaterThan(strlength(issueString), 0); issueString = testCase.hed.validateEvents(eventsChar, ... - sidecarChar, true); + sidecarChar, 'checkWarnings', true); testCase.verifyGreaterThan(strlength(issueString), 0); @@ -178,10 +167,12 @@ function testEventsValidBadSidecar(testCase) eventsString = string(eventsChar); testCase.verifyTrue(isstring(eventsString)) issueString = testCase.hed.validateEvents( ... - HedTools.formatEvents(eventsString), sidecarChar, false); - testCase.verifyGreaterThan(strlength(issueString), 0'); + HedTools.formatEvents(eventsString), sidecarChar, ... + 'checkWarnings', false); + testCase.verifyGreaterThan(strlength(issueString), 0); issueString = testCase.hed.validateEvents(... - HedTools.formatEvents(eventsString), sidecarChar, true); + HedTools.formatEvents(eventsString), sidecarChar, ... + 'checkWarnings', true); testCase.verifyGreaterThan(strlength(issueString), 0); end @@ -193,19 +184,21 @@ function testEventsValidStructWithOnset(testCase) testCase.verifyTrue(isstruct(eventsRectified)); issueString = testCase.hed.validateEvents( ... HedTools.formatEvents(eventsRectified), ... - testCase.sidecarStructGood, true); + testCase.sidecarStructGood, 'checkWarnings', true); testCase.verifyGreaterThan(strlength(issueString), 0); issueString = testCase.hed.validateEvents( ... HedTools.formatEvents(eventsRectified), ... - testCase.sidecarStructGood, false); + testCase.sidecarStructGood, 'checkWarnings', false); testCase.verifyEqual(strlength(issueString), 0); issueString = testCase.hed.validateEvents( ... - HedTools.formatEvents(eventsRectified), '', true); + HedTools.formatEvents(eventsRectified), '', ... + 'checkWarnings', true); testCase.verifyGreaterThan(strlength(issueString), 0); issueString = testCase.hed.validateEvents( ... - HedTools.formatEvents(eventsRectified), '', false); + HedTools.formatEvents(eventsRectified), '', ... + 'checkWarnings', false); testCase.verifyEqual(strlength(issueString), 0); end @@ -216,19 +209,22 @@ function testEventsValidStructNoOnset(testCase) testCase.verifyTrue(isstruct(eventsRectified)); issueString = testCase.hed.validateEvents( ... HedTools.formatEvents(eventsRectified), ... - testCase.sidecarStructGood, true); + testCase.sidecarStructGood, ... + 'checkWarnings', true); testCase.verifyGreaterThan(strlength(issueString), 0); issueString = testCase.hed.validateEvents( ... HedTools.formatEvents(eventsRectified), ... - testCase.sidecarStructGood, false); + testCase.sidecarStructGood, 'checkWarnings', false); testCase.verifyEqual(strlength(issueString), 0); issueString = testCase.hed.validateEvents( ... - HedTools.formatEvents(eventsRectified), '', true); + HedTools.formatEvents(eventsRectified), '', ... + 'checkWarnings', true); testCase.verifyGreaterThan(strlength(issueString), 0); issueString = testCase.hed.validateEvents( ... - HedTools.formatEvents(eventsRectified), '', false); + HedTools.formatEvents(eventsRectified), '', ... + 'checkWarnings', false); testCase.verifyEqual(strlength(issueString), 0); end @@ -236,11 +232,12 @@ function testEventsValidStructNoOnsetNoSampling(testCase) % Unrectified struct events no onset. issueString = testCase.hed.validateEvents( ... testCase.eventsStructNoOnset, ... - testCase.sidecarStructGood, false); + testCase.sidecarStructGood, ... + 'checkWarnings', false); testCase.verifyEmpty(issueString); issueString = testCase.hed.validateEvents( ... testCase.eventsStructNoOnset, ... - testCase.sidecarStructGood, true); + testCase.sidecarStructGood, 'checkWarnings', true); testCase.verifyGreaterThan(length(issueString), 0); end @@ -248,7 +245,8 @@ function testEventsInvalid(testCase) sidecarChar = fileread(testCase.badSidecarPath); eventsChar = fileread(testCase.goodEventsPath); issueString = testCase.hed.validateEvents(... - HedTools.formatEvents(eventsChar), sidecarChar, true); + HedTools.formatEvents(eventsChar), sidecarChar, ... + 'checkWarnings', true); testCase.verifyTrue(ischar(issueString)); testCase.verifyGreaterThan(length(issueString), 0); end @@ -258,36 +256,36 @@ function testSidecarValid(testCase) sidecarChar = fileread(testCase.goodSidecarPath); testCase.verifyTrue(ischar(sidecarChar)) issueString = testCase.hed.validateSidecar( ... - sidecarChar, false); + sidecarChar, 'checkWarnings', false); testCase.verifyEqual(strlength(issueString), 0); % Valid char sidecar should not have errors or warnings issueString = testCase.hed.validateSidecar(... - sidecarChar, true); + sidecarChar, 'checkWarnings', true); testCase.verifyEqual(strlength(issueString), 0); % Valid string sidecar should not have errors sidecarString = string(sidecarChar); testCase.verifyTrue(isstring(sidecarString)) issueString = testCase.hed.validateSidecar( ... - sidecarString, false); + sidecarString, 'checkWarnings', false); testCase.verifyEqual(strlength(issueString), 0); % Valid char sidecar should not have errors or warnings. issueString = testCase.hed.validateSidecar(... - sidecarString, true); + sidecarString, 'checkWarnings', true); testCase.verifyEqual(strlength(issueString), 0); % Valid struct sidecar should not have errors sidecarStruct = jsondecode(sidecarChar); testCase.verifyTrue(isstruct(sidecarStruct)) issueString = testCase.hed.validateSidecar( ... - sidecarStruct, false); + sidecarStruct, 'checkWarnings', false); testCase.verifyEqual(strlength(issueString), 0); % Valid struct sidecar should not have errors or warnings issueString = testCase.hed.validateSidecar(... - sidecarStruct, true); + sidecarStruct, 'checkWarnings', true); testCase.verifyEqual(strlength(issueString), 0); end @@ -296,77 +294,83 @@ function testSidecarInvalid(testCase) sidecarChar = fileread(testCase.badSidecarPath); testCase.verifyTrue(ischar(sidecarChar)) issueString = testCase.hed.validateSidecar( ... - sidecarChar, false); + sidecarChar, 'checkWarnings', false); testCase.verifyGreaterThan(strlength(issueString), 0); % Invalid char sidecar should have errors with warning on issueString = testCase.hed.validateSidecar(... - sidecarChar, true); + sidecarChar, 'checkWarnings', true); testCase.verifyGreaterThan(strlength(issueString), 0); % Invalid string sidecar should have errors sidecarString = string(sidecarChar); testCase.verifyTrue(isstring(sidecarString)) issueString = testCase.hed.validateSidecar( ... - sidecarString, false); + sidecarString, 'checkWarnings', false); testCase.verifyGreaterThan(strlength(issueString), 0); % Invalid string sidecar should have errors with warning on issueString = testCase.hed.validateSidecar(... - sidecarString, true); + sidecarString, 'checkWarnings', true); testCase.verifyGreaterThan(strlength(issueString), 0); % Invalid struct sidecar should not have errors or warnings sidecarStruct = jsondecode(sidecarChar); testCase.verifyTrue(isstruct(sidecarStruct)) issueString = testCase.hed.validateSidecar( ... - sidecarStruct, false); + sidecarStruct, 'checkWarnings', false); testCase.verifyGreaterThan(strlength(issueString), 0); % Invalid struct sidecar should have errors with warning on issueString = testCase.hed.validateSidecar(... - sidecarStruct, true); + sidecarStruct, 'checkWarnings', true); testCase.verifyGreaterThan(strlength(issueString), 0); end function testTagsValid(testCase) % Test valid check warnings no warnings - issues = testCase.hed.validateTags('Red, Blue', true); + issues = testCase.hed.validateTags('Red, Blue', ... + 'checkWarnings', true); testCase.verifyEqual(length(issues), 0); % Test valid check warnings has warnings - issues = testCase.hed.validateTags('Red, Blue/Apple', true); + issues = testCase.hed.validateTags('Red, Blue/Apple', ... + 'checkWarnings', true); testCase.verifyGreaterThan(length(issues), 0); - % Test valid no check warnings has warnings - issues = testCase.hed.validateTags('Red, Blue/Apple', false); + % Test valid no check warnings has no warnings + issues = testCase.hed.validateTags('Red, Blue/Apple', ... + 'checkWarnings', false); testCase.verifyEqual(length(issues), 0); % Test with extension and no check warnings - issues = testCase.hed.validateTags('Red, Blue/Apple'); + issues = testCase.hed.validateTags('Red, Blue/Apple', ... + 'checkWarnings', false); testCase.verifyEqual(length(issues), 0); end function testTagsInvalid(testCase) % Test check warnings with errors issues1 = testCase.hed.validateTags(... - 'Red, Blue/Apple, Green, Blech', true); + 'Red, Blue/Apple, Green, Blech', 'checkWarnings', true); testCase.verifyGreaterThan(length(issues1), 0); % Test no check warnings with errors issues2 = testCase.hed.validateTags(... - 'Red, Blue/Apple, Green, Blech', false); + 'Red, Blue/Apple, Green, Blech', 'checkWarnings', false); testCase.verifyGreaterThan(length(issues2), 0); end function testTagsInvalidFormat(testCase) % Test pass cell array (should only take strings) testCase.verifyError(@() testCase.hed.validateTags( ... - {'Red, Blue/Apple', 'Green, Blech'}, true), ... - 'HedToolsServiceValidateHedTags:InvalidHedTagInput'); + {'Red, Blue/Apple', 'Green, Blech'}, ... + 'checkWarnings', true), ... + 'HedToolsServiceValidateTags:InvalidHedTagInput'); testCase.verifyError(@() testCase.hed.validateTags( ... - {'Red, Blue/Apple', 'Green, Blech'}, false), ... - 'HedToolsServiceValidateHedTags:InvalidHedTagInput'); + {'Red, Blue/Apple', 'Green, Blech'}, ... + 'checkWarnings', false), ... + 'HedToolsServiceValidateTags:InvalidHedTagInput'); end end