From 990ed3aef33bf1b129354fd656a93f895bf560d7 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Thu, 17 Aug 2023 13:01:45 -0400 Subject: [PATCH 01/13] update timing --- +bids/layout.m | 4 +- tests/tests_layout/layout_timing.m | 264 +++++++---------------------- tests/tests_layout/plot_timing.m | 47 +++++ tests/tests_layout/timing.png | Bin 0 -> 44423 bytes tests/tests_layout/timing.tsv | 79 +++++++++ 5 files changed, 193 insertions(+), 201 deletions(-) create mode 100644 tests/tests_layout/plot_timing.m create mode 100644 tests/tests_layout/timing.png create mode 100644 tests/tests_layout/timing.tsv diff --git a/+bids/layout.m b/+bids/layout.m index 2cda6653..a0a6c5bb 100644 --- a/+bids/layout.m +++ b/+bids/layout.m @@ -26,8 +26,8 @@ % any ``derivatives`` folder in the BIDS dataset. % :type index_derivatives: logical % - % :param index_dependencies: if ``true`` this will index the dependencies - % (json files, associated TSV files for each file...) + % :param index_dependencies: if ``true`` this will index the explicit dependencies + % (with "IntendedFor" in json files) % :type index_dependencies: logical % % :param filter: Can be used to index only a subset of the dataset. diff --git a/tests/tests_layout/layout_timing.m b/tests/tests_layout/layout_timing.m index 201a4384..d18773a4 100644 --- a/tests/tests_layout/layout_timing.m +++ b/tests/tests_layout/layout_timing.m @@ -1,216 +1,82 @@ function layout_timing % - % runs bids.layout on the bids-examples and gives an estimate of the timing - % for each + % runs bids.layout on the bids-examples + % and gives an estimate of the timing for each % - use_schema = false; - - %% WITH SCHEMA - % data time (sec) - % asl001 0.084 - % asl005 0.094 - % asl003 0.095 - % asl002 0.098 - % asl004 0.109 - % pet004 0.114 - % pet003 0.127 - % qmri_tb1tfl 0.137 - % qmri_qsm 0.138 - % qmri_irt1 0.139 - % qmri_sa2rage 0.153 - % micr_SEMzarr 0.159 - % pet001 0.165 - % qmri_mp2rage 0.174 - % pet005 0.182 - % qmri_vfa 0.185 - % qmri_mtsat 0.187 - % micr_SEM 0.198 - % ds000246 0.215 - % qmri_megre 0.217 - % hcp_example_bids 0.244 - % eeg_ds003645s_hed_inheritance 0.257 - % pet002 0.259 - % ds000248 0.292 - % micr_SPIM 0.312 - % qmri_mp2rageme 0.334 - % eeg_ds003645s_hed_longform 0.383 - % ieeg_visual 0.396 - % eeg_ds003645s_hed_library 0.405 - % ieeg_epilepsy_ecog 0.475 - % fnirs_tapping 0.557 - % eeg_rest_fmri 0.602 - % ds000247 0.693 - % ieeg_epilepsyNWB 0.752 - % motion_systemvalidation 0.817 - % eeg_matchingpennies 0.819 - % qmri_mese 0.862 - % eeg_face13 0.871 - % ieeg_epilepsy 1.097 - % ds004332 1.127 - % eeg_ds003645s_hed 1.209 - % ieeg_filtered_speech 1.783 - % ds005 1.904 - % ds003 2.030 - % ds101 2.090 - % qmri_mpm 2.333 - % ds105 2.390 - % motion_spotrotation 2.525 - % ieeg_visual_multimodal 2.544 - % ds052 2.627 - % ds001 2.692 - % genetics_ukbb 2.812 - % synthetic 3.061 - % ds011 3.139 - % ds008 3.390 - % eeg_cbm 3.691 - % ds051 3.726 - % ds114 3.818 - % ds002 3.877 - % ds102 4.276 - % ds007 4.544 - % ds109 4.726 - % ds116 5.002 - % eeg_rishikesh 5.175 - % ieeg_motorMiller2007 5.342 - % ds009 5.821 - % ds006 6.574 - % ds107 6.991 - % ds110 7.362 - % ds113b 7.766 - % eeg_ds000117 8.033 - % ds210 8.614 - % motion_dualtask 8.633 - % ds108 10.668 - % ds000117 15.543 - % 7t_trt 15.960 - % fnirs_automaticity 19.642 - % docs NaN - % ds000001-fmriprep NaN - % tools NaN - - %% WITHOUT SCHEMA - % qmri_qsm 0.071 - % qmri_tb1tfl 0.073 - % qmri_sa2rage 0.081 - % qmri_vfa 0.105 - % qmri_irt1 0.108 - % hcp_example_bids 0.113 - % asl001 0.120 - % pet004 0.122 - % pet001 0.126 - % qmri_mp2rage 0.128 - % asl003 0.128 - % qmri_mtsat 0.132 - % asl002 0.133 - % asl005 0.135 - % pet003 0.145 - % micr_SEMzarr 0.152 - % qmri_megre 0.176 - % asl004 0.177 - % micr_SEM 0.183 - % eeg_ds003645s_hed_inheritance 0.217 - % pet005 0.220 - % qmri_mp2rageme 0.243 - % ds000248 0.264 - % pet002 0.268 - % micr_SPIM 0.292 - % ds000246 0.307 - % ieeg_epilepsyNWB 0.333 - % eeg_ds003645s_hed_longform 0.335 - % ieeg_visual 0.351 - % eeg_ds003645s_hed_library 0.359 - % eeg_ds003645s_hed 0.362 - % ieeg_epilepsy 0.380 - % fnirs_tapping 0.463 - % ieeg_epilepsy_ecog 0.468 - % motion_systemvalidation 0.508 - % eeg_rest_fmri 0.523 - % qmri_mese 0.716 - % eeg_face13 0.767 - % ieeg_filtered_speech 0.775 - % eeg_matchingpennies 0.813 - % ds003 1.049 - % ds000247 1.092 - % ds004332 1.406 - % qmri_mpm 1.735 - % ieeg_motorMiller2007 1.781 - % motion_spotrotation 1.857 - % genetics_ukbb 1.915 - % ieeg_visual_multimodal 2.170 - % ds005 2.202 - % ds101 2.350 - % synthetic 2.446 - % ds052 2.544 - % eeg_cbm 2.554 - % ds001 2.638 - % eeg_rishikesh 2.776 - % ds102 2.939 - % ds105 3.204 - % ds109 3.461 - % ds114 3.507 - % ds011 4.585 - % ds051 4.758 - % ds002 4.927 - % ds008 5.239 - % ds116 5.307 - % eeg_ds000117 5.373 - % ds107 6.259 - % ds113b 6.300 - % ds210 7.619 - % ds110 7.992 - % motion_dualtask 8.380 - % ds108 8.887 - % ds007 10.000 - % ds009 10.363 - % ds006 10.371 - % fnirs_automaticity 14.192 - % 7t_trt 15.023 - % ds000117 23.928 - % docs NaN - % ds000001-fmriprep NaN - % tools NaN - - pth_bids_example = get_test_data_dir(); - - d = dir(pth_bids_example); - d(arrayfun(@(x) ~x.isdir || ismember(x.name, {'.', '..', '.git', '.github'}), d)) = []; - - tab = '\t\t\t'; - - fprintf('\n'); - fprintf(['data' tab 'time (sec)\n']); - fprintf('\n'); - for i = 1:numel(d) + DEBUG = false; + + use_schema_list = [true false]; + index_dependencies_list = [true false]; + + output = struct('name', {{}}); + + for j = 1:numel(use_schema_list) + use_schema = use_schema_list(j); + + for k = 1:numel(index_dependencies_list) + index_dependencies = index_dependencies_list(k); - ds{i} = d(i).name; + output.(field(use_schema, index_dependencies, '_nb_files')) = []; + output.(field(use_schema, index_dependencies, '_time')) = []; + end + end - fprintf(1, '%s', d(i).name); + d = dir(get_test_data_dir()); + d(arrayfun(@(x) ~x.isdir || ismember(x.name, ... + {'.', '..', '.git', '.github', ... + 'docs', 'tools'}), ... + d)) = []; - if exist(fullfile(pth_bids_example, d(i).name, '.SKIP_VALIDATION'), 'file') - fprintf([tab 'skip\n']); - T(i) = nan; - continue + for i = 1:numel(d) + + if DEBUG && i > 4 + break end - tic; - bids.layout(fullfile(pth_bids_example, d(i).name), ... - 'use_schema', use_schema, ... - 'verbose', false); - T(i) = toc; + output.name{i} = d(i).name; + fprintf(1, '%s\n', d(i).name); + + for j = 1:numel(use_schema_list) + use_schema = use_schema_list(j); - fprintf(1, [tab '%0.3f\n'], T(i)); + for k = 1:numel(index_dependencies_list) + index_dependencies = index_dependencies_list(k); + + [time, nb_files] = run_on_examples(d(i).name, use_schema, index_dependencies); + + output.(field(use_schema, index_dependencies, '_nb_files'))(end + 1) = nb_files; + output.(field(use_schema, index_dependencies, '_time'))(end + 1) = time; + end + end end - fprintf('\n'); - [T, I] = sort(T); - ds = ds(I); - fprintf('\n sorted results\n'); - fprintf(['data' tab 'time (sec)\n']); + bids.util.tsvwrite('timing.tsv', output); + +end - for i = 1:numel(ds) - fprintf(1, ['%s' tab '%0.3f\n'], ds{i}, T(i)); +function value = field(use_schema, index_dependencies, suffix) + pattern = 'schema_%i_depedencies_%i'; + value = sprintf([pattern suffix], ... + use_schema, ... + index_dependencies); +end + +function [time, nb_files] = run_on_examples(name, use_schema, index_dependencies) + + if use_schema && exist(fullfile(get_test_data_dir(), name, '.SKIP_VALIDATION'), 'file') + time = nan; + nb_files = nan; + return end + tic; + BIDS = bids.layout(fullfile(get_test_data_dir(), name), ... + 'use_schema', use_schema, ... + 'index_dependencies', index_dependencies, ... + 'verbose', false); + time = toc; + nb_files = numel(bids.query(BIDS, 'data')); + end diff --git a/tests/tests_layout/plot_timing.m b/tests/tests_layout/plot_timing.m new file mode 100644 index 00000000..18cf9aa7 --- /dev/null +++ b/tests/tests_layout/plot_timing.m @@ -0,0 +1,47 @@ +close all; +clear; + +use_schema_list = [true false]; +index_dependencies_list = [true false]; + +data = bids.util.tsvread('timing.tsv'); + +figure(); + +hold on; + +legend_name = {}; + +for j = 1:numel(use_schema_list) + use_schema = use_schema_list(j); + + for k = 1:numel(index_dependencies_list) + index_dependencies = index_dependencies_list(k); + + legend_name{end + 1} = strrep(field(use_schema, index_dependencies, ''), ... + '_', ' '); %#ok<*SAGROW> + + nb_files = data.(field(use_schema, index_dependencies, '_nb_files')); + time = data.(field(use_schema, index_dependencies, '_time')); + + s = scatter(nb_files, time, 100, '.'); + + end +end + +xlabel('number of files'); +ylabel('time (sec)'); + +% axis([0 50 0 2.5]) + +legend(legend_name, 'location', 'NorthWest'); + +print(gcf, 'timing.png', '-dpng'); + +%% +function value = field(use_schema, index_dependencies, suffix) + pattern = 'schema_%i_depedencies_%i'; + value = sprintf([pattern suffix], ... + use_schema, ... + index_dependencies); +end diff --git a/tests/tests_layout/timing.png b/tests/tests_layout/timing.png new file mode 100644 index 0000000000000000000000000000000000000000..b7a9174b22d6c333662411cb659b564847282814 GIT binary patch literal 44423 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 literal 0 HcmV?d00001 diff --git a/tests/tests_layout/timing.tsv b/tests/tests_layout/timing.tsv new file mode 100644 index 00000000..ad6796d4 --- /dev/null +++ b/tests/tests_layout/timing.tsv @@ -0,0 +1,79 @@ +name schema_1_depedencies_1_nb_files schema_1_depedencies_1_time schema_1_depedencies_0_nb_files schema_1_depedencies_0_time schema_0_depedencies_1_nb_files schema_0_depedencies_1_time schema_0_depedencies_0_nb_files schema_0_depedencies_0_time +7t_trt 635 12.878057 635 5.746334 635 13.23332 635 5.226321 +asl001 4 0.122762 4 0.21057 4 0.130981 4 0.053013 +asl002 5 0.110307 5 0.08017299999999999 5 0.107406 5 0.067231 +asl003 5 0.158618 5 0.08215500000000001 5 0.101119 5 0.065372 +asl004 6 0.123305 6 0.101505 6 0.13708 6 0.071115 +asl005 5 0.130211 5 0.097418 5 0.096479 5 0.061447 +ds000001-fmriprep n/a n/a n/a n/a 418 8.171611 418 3.111228 +ds000117 640 18.295967 640 6.784899 864 21.10377 864 8.487672999999999 +ds000246 13 0.358794 13 0.189625 13 0.311395 13 0.102036 +ds000247 40 2.127618 40 0.877923 40 0.842565 40 0.296761 +ds000248 9 0.21457 9 0.201783 11 0.246136 11 0.09224300000000001 +ds001 128 2.715686 128 2.292915 128 2.08474 128 0.944258 +ds002 238 3.989296 238 2.376058 238 3.516501 238 1.991699 +ds003 52 1.810685 52 0.99124 52 0.915794 52 0.455082 +ds004332 58 1.425477 58 0.944766 58 1.45826 58 0.69469 +ds005 128 4.766503 128 2.233034 128 2.671854 128 1.332702 +ds006 384 17.304357 384 7.715079 384 15.992915 384 4.734097 +ds007 276 7.026251 276 3.500368 276 5.600689 276 2.774765 +ds008 197 4.643136 197 3.006904 197 5.059259 197 2.042414 +ds009 360 11.121226 360 3.930276 360 7.077274 360 3.145282 +ds011 196 3.979 196 2.044542 196 2.911879 196 1.32229 +ds051 245 5.41513 245 2.811987 245 3.61198 245 1.586959 +ds052 142 2.900416 142 1.462075 142 2.401136 142 1.380542 +ds101 105 2.566284 105 1.209946 105 1.640797 105 0.785391 +ds102 130 3.285882 130 3.613964 130 2.254736 130 1.235791 +ds105 148 2.344433 148 1.159552 148 2.294374 148 0.936268 +ds107 245 7.439544 245 5.018268 245 5.353551 245 3.352455 +ds108 442 9.877881 442 5.824762 442 9.772868000000001 442 3.719578 +ds109 174 4.845315 174 3.845052 174 3.711721 174 1.60113 +ds110 396 8.428979 396 3.9203 396 7.632956 396 4.624585 +ds113b 312 7.856034 312 4.047022 312 5.895564 312 2.860994 +ds114 164 3.635015 164 2.326693 164 3.986292 164 1.541886 +ds116 238 5.358747 238 2.236292 238 4.713165 238 1.895178 +ds210 300 9.889874000000001 300 3.460661 300 7.280257 300 3.151618 +eeg_cbm 80 2.375438 80 1.20596 80 3.103752 80 0.847672 +eeg_ds000117 321 8.917916999999999 321 3.816874 321 6.344976 321 2.20161 +eeg_ds003645s_hed 20 0.547461 20 0.220162 20 0.37045 20 0.185295 +eeg_ds003645s_hed_inheritance 10 0.491762 10 0.146763 10 0.220385 10 0.116235 +eeg_ds003645s_hed_library 18 0.563624 18 0.206467 18 0.326917 18 0.161759 +eeg_ds003645s_hed_longform 18 0.48201 18 0.248961 18 0.328663 18 0.16511 +eeg_face13 40 1.512921 40 0.475066 40 0.708877 40 0.363321 +eeg_matchingpennies 35 1.223818 35 0.26424 35 0.752654 35 0.197893 +eeg_rest_fmri 36 0.751157 36 0.2244 36 0.571695 36 0.309812 +eeg_rishikesh 120 3.728327 120 2.092848 120 3.96413 120 1.80132 +fnirs_automaticity 624 19.444088 624 7.064014 624 14.293472 624 4.859085 +fnirs_tapping 25 1.105406 25 0.303453 25 0.402494 25 0.229565 +genetics_ukbb 112 2.44505 112 1.405501 112 2.696068 112 1.230629 +hcp_example_bids 5 0.17511 5 0.160794 5 0.130965 5 0.06297800000000001 +ieeg_epilepsy 21 0.534711 21 0.330119 21 0.391636 21 0.302818 +ieeg_epilepsyNWB 15 0.522953 15 0.171177 15 0.349226 15 0.154569 +ieeg_epilepsy_ecog 18 0.607453 18 0.186014 18 0.445421 18 0.205806 +ieeg_filtered_speech 49 1.330714 49 0.409764 49 0.693241 49 0.300797 +ieeg_motorMiller2007 103 2.640748 103 0.9111629999999999 103 1.962946 103 0.669125 +ieeg_visual 19 0.871592 19 0.317233 19 0.334786 19 0.143083 +ieeg_visual_multimodal 101 2.419473 101 1.069651 101 2.70493 101 1.291842 +micr_SEM 6 0.297653 6 0.12262 6 0.202291 6 0.093598 +micr_SEMzarr 4 0.245839 4 0.273165 4 0.147603 4 0.068276 +micr_SPIM 11 0.671759 11 0.185743 11 0.373255 11 0.170519 +motion_dualtask 355 10.028597 355 3.714179 355 9.046773 355 3.525084 +motion_spotrotation 100 2.140386 100 0.78505 100 1.775886 100 0.939034 +motion_systemvalidation 27 0.720349 27 0.318322 27 0.518885 27 0.189777 +pet001 4 0.270659 4 0.221607 4 0.11098 4 0.06858300000000001 +pet002 8 0.391504 8 0.158324 8 0.221316 8 0.108903 +pet003 3 0.132492 3 0.07571700000000001 3 0.091964 3 0.061076 +pet004 3 0.168884 3 0.236781 3 0.094412 3 0.057697 +pet005 5 0.267879 5 0.246028 5 0.138186 5 0.087008 +qmri_irt1 4 0.18725 4 0.176378 4 0.130704 4 0.063917 +qmri_megre 8 0.202014 8 0.117488 8 0.183043 8 0.09503200000000001 +qmri_mese 32 0.920145 32 0.444109 32 0.704209 32 0.323025 +qmri_mp2rage 5 0.228771 5 0.235643 5 0.127973 5 0.07502 +qmri_mp2rageme 11 0.399368 11 0.149428 11 0.258685 11 0.126593 +qmri_mpm 53 1.840644 53 0.654851 53 2.045668 53 0.475899 +qmri_mtsat 5 0.270519 5 0.188931 5 0.164588 5 0.121687 +qmri_qsm 2 0.202867 2 0.16589 2 0.116158 2 0.043784 +qmri_sa2rage 2 0.15133 2 0.20459 2 0.219949 2 0.048966 +qmri_tb1tfl 2 0.117524 2 0.127355 2 0.130369 2 0.04258 +qmri_vfa 4 0.168128 4 0.182997 4 0.130711 4 0.071682 +synthetic 111 2.869342 111 1.188585 111 2.506092 111 1.370206 From 49ba5e1d90a0a71589c308db96ebb4bfcaf716b0 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Thu, 17 Aug 2023 14:33:38 -0400 Subject: [PATCH 02/13] try speed up test by not indexing dependencies --- +bids/+internal/list_all_trial_types.m | 2 + +bids/diagnostic.m | 3 +- tests/test_diagnostic.m | 2 +- tests/test_report.m | 8 +-- tests/tests_layout/test_layout.m | 12 +--- tests/tests_layout/test_layout_derivatives.m | 47 ++++++------ tests/tests_layout/test_layout_schemaless.m | 2 + tests/tests_private/test_append_to_layout.m | 12 ++-- tests/tests_query/test_bids_query.m | 72 ++++++++++++------- tests/tests_query/test_bids_query_asl.m | 6 +- .../tests_query/test_bids_query_derivatives.m | 1 + tests/tests_query/test_bids_query_dwi.m | 3 +- tests/tests_query/test_bids_query_eeg.m | 6 +- tests/tests_query/test_bids_query_func.m | 3 +- tests/tests_query/test_bids_query_ieeg.m | 6 +- .../test_bids_query_matlab_octave.m | 3 +- tests/tests_query/test_bids_query_meg.m | 8 +-- .../tests_query/test_bids_query_microscopy.m | 6 +- tests/tests_query/test_bids_query_motion.m | 3 +- tests/tests_query/test_bids_query_nirs.m | 3 +- tests/tests_query/test_bids_query_qmri.m | 6 +- tests/tests_query/test_query_bug_453.m | 3 +- tests/tests_utils/test_plot_events.m | 6 +- 23 files changed, 130 insertions(+), 93 deletions(-) diff --git a/+bids/+internal/list_all_trial_types.m b/+bids/+internal/list_all_trial_types.m index 594e143b..7b12f0a1 100644 --- a/+bids/+internal/list_all_trial_types.m +++ b/+bids/+internal/list_all_trial_types.m @@ -54,6 +54,8 @@ trial_type_list = {}; + BIDS = bids.layout(BIDS, 'index_dependencies', false); + event_files = bids.query(BIDS, 'data', ... 'suffix', 'events', ... 'extension', '.tsv', ... diff --git a/+bids/diagnostic.m b/+bids/diagnostic.m index f1c20313..c2f70a76 100644 --- a/+bids/diagnostic.m +++ b/+bids/diagnostic.m @@ -78,7 +78,8 @@ parse(args, varargin{:}); %% - BIDS = bids.layout(args.Results.BIDS, 'use_schema', args.Results.use_schema); + BIDS = bids.layout(args.Results.BIDS, 'use_schema', args.Results.use_schema, ... + 'index_dependencies', false); output_path = args.Results.output_path; diff --git a/tests/test_diagnostic.m b/tests/test_diagnostic.m index 697d81b3..80eca978 100644 --- a/tests/test_diagnostic.m +++ b/tests/test_diagnostic.m @@ -19,7 +19,7 @@ function test_diagnostic_basic() for i = 1:size(examples, 1) - BIDS = bids.layout(deblank(examples(i, :))); + BIDS = bids.layout(deblank(examples(i, :)), 'index_dependencies', false); diagnostic_table = bids.diagnostic(BIDS, 'output_path', pwd); diagnostic_table = bids.diagnostic(BIDS, 'split_by', {'suffix'}, 'output_path', pwd); diff --git a/tests/test_report.m b/tests/test_report.m index a4ca04b5..99540620 100644 --- a/tests/test_report.m +++ b/tests/test_report.m @@ -14,7 +14,7 @@ function test_report_asl() BIDS = fullfile(cfg.pth_bids_example, datasets); - BIDS = bids.layout(BIDS, 'use_schema', true); + BIDS = bids.layout(BIDS, 'use_schema', true, 'index_dependencies', false); filter.modality = 'perf'; @@ -46,7 +46,7 @@ function test_report_basic() for i = 1:numel(datasets) BIDS = fullfile(cfg.pth_bids_example, datasets{i}); - BIDS = bids.layout(BIDS, 'use_schema', true); + BIDS = bids.layout(BIDS, 'use_schema', true, 'index_dependencies', false); for j = 1:numel(modalities) @@ -81,7 +81,7 @@ function test_report_pet() BIDS = fullfile(cfg.pth_bids_example, datasets); - BIDS = bids.layout(BIDS, 'use_schema', true); + BIDS = bids.layout(BIDS, 'use_schema', true, 'index_dependencies', false); filter.modality = 'pet'; @@ -120,7 +120,7 @@ function test_report_moae_data() 'verbose', true, ... 'delete_previous', false); - BIDS = bids.layout(pth, 'use_schema', true); + BIDS = bids.layout(pth, 'use_schema', true, 'index_dependencies', false); report = bids.report(BIDS, ... 'output_path', cfg.output_path, ... diff --git a/tests/tests_layout/test_layout.m b/tests/tests_layout/test_layout.m index fe48199b..65cff4f3 100644 --- a/tests/tests_layout/test_layout.m +++ b/tests/tests_layout/test_layout.m @@ -61,6 +61,7 @@ function test_layout_filter() BIDS = bids.layout(fullfile(get_test_data_dir(), '7t_trt'), ... 'verbose', verbose, ... + 'index_dependencies', false, ... 'filter', struct('sub', {{'01', '02'}}, ... 'modality', {{'anat', 'func'}}, ... 'ses', {{'1', '2'}})); @@ -82,6 +83,7 @@ function test_layout_filter_regex() BIDS = bids.layout(fullfile(get_test_data_dir(), '7t_trt'), ... 'verbose', verbose, ... + 'index_dependencies', false, ... 'filter', struct('sub', {{'^.*0[12]'}}, ... 'modality', {{'anat', 'func'}}, ... 'ses', {{'[1]'}})); @@ -96,13 +98,3 @@ function test_layout_filter_regex() assertEqual(subjects, {'1'}); end - -function test_layout_smoke_test() - - verbose = false; - - BIDS = bids.layout(fullfile(get_test_data_dir(), 'genetics_ukbb'), 'verbose', verbose); - - BIDS = bids.layout(fullfile(get_test_data_dir(), 'ds210'), 'verbose', verbose); - -end diff --git a/tests/tests_layout/test_layout_derivatives.m b/tests/tests_layout/test_layout_derivatives.m index 8bc4970c..ad024bf2 100644 --- a/tests/tests_layout/test_layout_derivatives.m +++ b/tests/tests_layout/test_layout_derivatives.m @@ -6,24 +6,6 @@ initTestSuite; end -function test_layout_warning_invalid_subfolder_struct_fieldname() - - % https://github.com/bids-standard/bids-matlab/issues/332 - - invalid_subfolder = fullfile(get_test_data_dir(), '..', ... - 'data', 'synthetic', 'derivatives', 'invalid_subfolder'); - - if bids.internal.is_octave() - moxunit_throw_test_skipped_exception('Octave:mixed-string-concat warning thrown'); - end - - assertWarning(@()bids.layout(invalid_subfolder, ... - 'use_schema', false, ... - 'verbose', true), ... - 'layout:invalidSubfolderName'); - -end - function test_layout_nested() pth_bids_example = get_test_data_dir(); @@ -41,7 +23,8 @@ function test_layout_nested() for i = 1:numel(dataset_to_test) BIDS = bids.layout(fullfile(pth_bids_example, dataset_to_test{i}), ... 'use_schema', true, 'tolerant', false, ... - 'index_derivatives', true); + 'index_derivatives', true, ... + 'index_dependencies', false); fprintf(1, '.'); end @@ -55,7 +38,8 @@ function test_layout_meg_derivatives() 'ds000117', ... 'derivatives', ... 'meg_derivatives'), ... - 'use_schema', false); + 'use_schema', false, ... + 'index_dependencies', false); modalities = {'meg'}; assertEqual(bids.query(BIDS, 'modalities'), modalities); @@ -80,6 +64,7 @@ function test_layout_prefix() 'swuasub-01_acq-anat_TB1TFL.nii.gz')); BIDS = bids.layout(fullfile(pth_bids_example, 'qmri_tb1tfl'), ... + 'index_dependencies', false, ... 'use_schema', false); data = bids.query(BIDS, 'data', ... @@ -99,8 +84,8 @@ function test_layout_schemaless() pth_bids_example = get_test_data_dir(); - BIDS = bids.layout(fullfile(pth_bids_example, ... - 'ds000001-fmriprep'), ... + BIDS = bids.layout(fullfile(pth_bids_example, 'ds000001-fmriprep'), ... + 'index_dependencies', false, ... 'use_schema', false); modalities = {'anat', 'figures', 'func'}; @@ -132,3 +117,21 @@ function test_layout_schemaless() '_space-MNI152NLin6Asym_desc-smoothAROMAnonaggr_bold.nii'] }); end + +function test_layout_warning_invalid_subfolder_struct_fieldname() + + % https://github.com/bids-standard/bids-matlab/issues/332 + + invalid_subfolder = fullfile(get_test_data_dir(), '..', ... + 'data', 'synthetic', 'derivatives', 'invalid_subfolder'); + + if bids.internal.is_octave() + moxunit_throw_test_skipped_exception('Octave:mixed-string-concat warning thrown'); + end + + assertWarning(@()bids.layout(invalid_subfolder, ... + 'use_schema', false, ... + 'verbose', true), ... + 'layout:invalidSubfolderName'); + +end diff --git a/tests/tests_layout/test_layout_schemaless.m b/tests/tests_layout/test_layout_schemaless.m index aca7e848..829886b7 100644 --- a/tests/tests_layout/test_layout_schemaless.m +++ b/tests/tests_layout/test_layout_schemaless.m @@ -23,6 +23,7 @@ function test_layout_no_schema_no_ses_in_filename() BIDS = bids.layout(bids_dir, ... 'verbose', verbose, ... + 'index_dependencies', false, ... 'use_schema', true, ... 'filter', filter); @@ -31,6 +32,7 @@ function test_layout_no_schema_no_ses_in_filename() BIDS = bids.layout(bids_dir, ... 'verbose', verbose, ... + 'index_dependencies', false, ... 'use_schema', false, ... 'filter', filter); diff --git a/tests/tests_private/test_append_to_layout.m b/tests/tests_private/test_append_to_layout.m index 26b0d1a6..95c68b88 100644 --- a/tests/tests_private/test_append_to_layout.m +++ b/tests/tests_private/test_append_to_layout.m @@ -32,8 +32,7 @@ function test_append_to_layout_schema_unknown_entity() file = 'sub-16_task-bar_foo-bar_meg.ds'; - assertWarning( ... - @()bids.internal.append_to_layout(file, subject, modality, schema, previous), ... + assertWarning(@()bids.internal.append_to_layout(file, subject, modality, schema, previous), ... 'append_to_layout:unknownEntity'); end @@ -61,8 +60,7 @@ function test_append_to_layout_basic() file = 'sub-16_ses-mri_run-1_acq-hd_T1w.nii.gz'; subject = bids.internal.append_to_layout(file, subject, modality, schema, previous); - expected.anat = struct( ... - 'filename', 'sub-16_ses-mri_run-1_acq-hd_T1w.nii.gz', ... + expected.anat = struct('filename', 'sub-16_ses-mri_run-1_acq-hd_T1w.nii.gz', ... 'suffix', 'T1w', ... 'ext', '.nii.gz', ... 'prefix', '', ... @@ -114,8 +112,7 @@ function test_append_to_structure_basic_test() subject = bids.internal.append_to_layout(file, subject, ... modality, schema, previous); - expected.anat(1, 1) = struct( ... - 'filename', 'sub-16_ses-mri_run-1_acq-hd_T1w.nii.gz', ... + expected.anat(1, 1) = struct('filename', 'sub-16_ses-mri_run-1_acq-hd_T1w.nii.gz', ... 'suffix', 'T1w', ... 'ext', '.nii.gz', ... 'prefix', '', ... @@ -203,8 +200,7 @@ function test_append_to_layout_schemaless() schema = bids.Schema(use_schema); schema.verbose = true; - subject = struct( ... - modality, struct([]), ... + subject = struct(modality, struct([]), ... 'path', fullfile(pwd, 'sub-01')); previous = struct('group', struct('index', 0, 'base', '', 'len', 1), ... diff --git a/tests/tests_query/test_bids_query.m b/tests/tests_query/test_bids_query.m index 27d93437..913e9136 100644 --- a/tests/tests_query/test_bids_query.m +++ b/tests/tests_query/test_bids_query.m @@ -8,7 +8,8 @@ function test_query_phenotype() - BIDS = bids.layout(fullfile(get_test_data_dir(), 'pet002')); + BIDS = bids.layout(fullfile(get_test_data_dir(), 'pet002'), ... + 'index_dependencies', false); phenotype = bids.query(BIDS, 'phenotype'); @@ -32,11 +33,13 @@ function test_query_phenotype() function test_query_participants() - BIDS = bids.layout(fullfile(get_test_data_dir(), 'pet002')); + BIDS = bids.layout(fullfile(get_test_data_dir(), 'pet002'), ... + 'index_dependencies', false); participants = bids.query(BIDS, 'participants'); - BIDS = bids.layout(fullfile(get_test_data_dir(), 'asl001')); + BIDS = bids.layout(fullfile(get_test_data_dir(), 'asl001'), ... + 'index_dependencies', false); participants = bids.query(BIDS, 'participants'); @@ -44,7 +47,8 @@ function test_query_participants() function test_query_impossible_suffix_should_return_empty() - BIDS = bids.layout(fullfile(get_test_data_dir(), 'synthetic')); + BIDS = bids.layout(fullfile(get_test_data_dir(), 'synthetic'), ... + 'index_dependencies', false); % no suffix bold in anat filter = struct('sub', '01', ... @@ -60,12 +64,14 @@ function test_query_impossible_suffix_should_return_empty() function test_query_suffixes() - BIDS = bids.layout(fullfile(get_test_data_dir(), 'pet002')); + BIDS = bids.layout(fullfile(get_test_data_dir(), 'pet002'), ... + 'index_dependencies', false); suffixes = {'T1w', 'pet'}; assertEqual(bids.query(BIDS, 'suffixes'), suffixes); - BIDS = bids.layout(fullfile(get_test_data_dir(), 'synthetic')); + BIDS = bids.layout(fullfile(get_test_data_dir(), 'synthetic'), ... + 'index_dependencies', false); suffixes = {'T1w'}; assertEqual(bids.query(BIDS, 'suffixes', 'modality', 'anat'), suffixes); @@ -74,7 +80,8 @@ function test_query_suffixes() function test_query_subjects() - BIDS = bids.layout(fullfile(get_test_data_dir(), 'ieeg_visual')); + BIDS = bids.layout(fullfile(get_test_data_dir(), 'ieeg_visual'), ... + 'index_dependencies', false); subjs = arrayfun(@(x) sprintf('%02d', x), 1:2, 'UniformOutput', false); assertEqual(bids.query(BIDS, 'subjects'), subjs); @@ -95,7 +102,8 @@ function test_query_regex_subjects_no_regex_by_default() % end - BIDS = bids.layout(fullfile(get_test_data_dir(), '..', 'data', 'synthetic')); + BIDS = bids.layout(fullfile(get_test_data_dir(), '..', 'data', 'synthetic'), ... + 'index_dependencies', false); data = bids.query(BIDS, 'subjects', 'sub', '01'); @@ -109,7 +117,8 @@ function test_query_regex_subjects_no_regex_by_default() function test_query_regex_subjects() - BIDS = bids.layout(fullfile(get_test_data_dir(), 'ds000247')); + BIDS = bids.layout(fullfile(get_test_data_dir(), 'ds000247'), ... + 'index_dependencies', false); data = bids.query(BIDS, 'data', 'sub', '.*', 'suffix', 'T1w'); @@ -123,7 +132,8 @@ function test_query_regex_subjects() function test_query_with_indices() - BIDS = bids.layout(fullfile(get_test_data_dir(), 'ds105')); + BIDS = bids.layout(fullfile(get_test_data_dir(), 'ds105'), ... + 'index_dependencies', false); data_1 = bids.query(BIDS, 'data', 'sub', '1', 'run', {3, 5, '7', '01'}, 'suffix', 'bold'); data_2 = bids.query(BIDS, 'data', 'sub', '1', 'run', 1:2:7, 'suffix', 'bold'); @@ -134,7 +144,8 @@ function test_query_with_indices() function test_query_entities() - BIDS = bids.layout(fullfile(get_test_data_dir(), 'qmri_qsm')); + BIDS = bids.layout(fullfile(get_test_data_dir(), 'qmri_qsm'), ... + 'index_dependencies', false); entities = bids.query(BIDS, 'entities'); @@ -144,7 +155,8 @@ function test_query_entities() assertEqual(entities, expected); %% - BIDS = bids.layout(fullfile(get_test_data_dir(), 'pet002')); + BIDS = bids.layout(fullfile(get_test_data_dir(), 'pet002'), ... + 'index_dependencies', false); entities = bids.query(BIDS, 'entities', 'suffix', 'pet'); @@ -157,7 +169,8 @@ function test_query_entities() function test_query_events_tsv_in_root() - BIDS = bids.layout(fullfile(get_test_data_dir(), 'synthetic')); + BIDS = bids.layout(fullfile(get_test_data_dir(), 'synthetic'), ... + 'index_dependencies', false); data = bids.query(BIDS, 'data', 'sub', '01', 'ses', '01', 'task', 'nback', 'suffix', 'events'); @@ -170,7 +183,8 @@ function test_query_events_tsv_in_root() function test_query_exclude_entity() - BIDS = bids.layout(fullfile(get_test_data_dir(), 'ds000246')); + BIDS = bids.layout(fullfile(get_test_data_dir(), 'ds000246'), ... + 'index_dependencies', false); filter = struct('sub', '0001'); assertEqual(bids.query(BIDS, 'modalities', filter), {'anat', 'meg'}); @@ -189,7 +203,8 @@ function test_query_exclude_entity() function test_query_basic() - BIDS = bids.layout(fullfile(get_test_data_dir(), 'pet005')); + BIDS = bids.layout(fullfile(get_test_data_dir(), 'pet005'), ... + 'index_dependencies', false); tasks = {'eyes'}; assertEqual(bids.query(BIDS, 'tasks'), tasks); @@ -204,7 +219,8 @@ function test_query_basic() function test_query_data_filter() - BIDS = bids.layout(fullfile(get_test_data_dir(), 'pet005')); + BIDS = bids.layout(fullfile(get_test_data_dir(), 'pet005'), ... + 'index_dependencies', false); % make sure that query can work with filter filters = {'sub', {'01'}; ... @@ -225,7 +241,8 @@ function test_query_data_filter() function test_query_extension() - BIDS = bids.layout(fullfile(get_test_data_dir(), 'qmri_tb1tfl')); + BIDS = bids.layout(fullfile(get_test_data_dir(), 'qmri_tb1tfl'), ... + 'index_dependencies', false); extensions = bids.query(BIDS, 'extensions'); @@ -244,7 +261,8 @@ function test_query_extension() function test_query_metadata() - BIDS = bids.layout(fullfile(get_test_data_dir(), 'qmri_tb1tfl')); + BIDS = bids.layout(fullfile(get_test_data_dir(), 'qmri_tb1tfl'), ... + 'index_dependencies', false); md = bids.query(BIDS, 'metadata', ... 'sub', '01', ... @@ -258,7 +276,8 @@ function test_query_metadata() function test_query_modalities() - BIDS = bids.layout(fullfile(get_test_data_dir(), 'pet002')); + BIDS = bids.layout(fullfile(get_test_data_dir(), 'pet002'), ... + 'index_dependencies', false); modalities = {'anat', 'pet'}; @@ -270,7 +289,8 @@ function test_query_modalities() function test_query_tsv_content() - BIDS = bids.layout(fullfile(get_test_data_dir(), 'eeg_ds003645s_hed_inheritance')); + BIDS = bids.layout(fullfile(get_test_data_dir(), 'eeg_ds003645s_hed_inheritance'), ... + 'index_dependencies', false); tsv_content = bids.query(BIDS, 'tsv_content', 'suffix', 'events'); @@ -291,7 +311,8 @@ function test_query_tsv_content() function test_query_tsv_content_error() - BIDS = bids.layout(fullfile(get_test_data_dir(), 'qmri_tb1tfl')); + BIDS = bids.layout(fullfile(get_test_data_dir(), 'qmri_tb1tfl'), ... + 'index_dependencies', false); assertExceptionThrown(@()bids.query(BIDS, 'tsv_content', 'extension', '.nii.gz'), ... 'query:notJustTsvFiles'); @@ -299,7 +320,8 @@ function test_query_tsv_content_error() function test_query_sessions() - BIDS = bids.layout(fullfile(get_test_data_dir(), 'synthetic')); + BIDS = bids.layout(fullfile(get_test_data_dir(), 'synthetic'), ... + 'index_dependencies', false); sessions = {'01', '02'}; assertEqual(bids.query(BIDS, 'sessions'), sessions); assertEqual(bids.query(BIDS, 'sessions', 'sub', '02'), sessions); @@ -312,7 +334,8 @@ function test_query_sessions() function test_query_sessions_tsv() - BIDS = bids.layout(fullfile(get_test_data_dir(), 'synthetic')); + BIDS = bids.layout(fullfile(get_test_data_dir(), 'synthetic'), ... + 'index_dependencies', false); suffixes = bids.query(BIDS, 'suffixes'); assert(ismember('sessions', suffixes)); @@ -354,7 +377,8 @@ function test_query_sessions_tsv() function test_query_scans_tsv() - BIDS = bids.layout(fullfile(get_test_data_dir(), 'motion_spotrotation')); + BIDS = bids.layout(fullfile(get_test_data_dir(), 'motion_spotrotation'), ... + 'index_dependencies', false); suffixes = bids.query(BIDS, 'suffixes'); assert(ismember('scans', suffixes)); diff --git a/tests/tests_query/test_bids_query_asl.m b/tests/tests_query/test_bids_query_asl.m index d1eb644f..7dd29e38 100644 --- a/tests/tests_query/test_bids_query_asl.m +++ b/tests/tests_query/test_bids_query_asl.m @@ -35,7 +35,8 @@ function test_bids_query_asl_basic_asl002() function test_bids_query_asl_basic_asl001() - BIDS = bids.layout(fullfile(get_test_data_dir(), 'asl001')); + BIDS = bids.layout(fullfile(get_test_data_dir(), 'asl001'), ... + 'index_dependencies', false); modalities = {'anat', 'perf'}; assertEqual(bids.query(BIDS, 'modalities'), modalities); @@ -64,7 +65,8 @@ function test_bids_query_asl_basic_asl001() function test_bids_query_asl_basic_asl003() - BIDS = bids.layout(fullfile(get_test_data_dir(), 'asl003')); + BIDS = bids.layout(fullfile(get_test_data_dir(), 'asl003'), ... + 'index_dependencies', false); modalities = {'anat', 'perf'}; assertEqual(bids.query(BIDS, 'modalities'), modalities); diff --git a/tests/tests_query/test_bids_query_derivatives.m b/tests/tests_query/test_bids_query_derivatives.m index f22d6279..f61c857b 100644 --- a/tests/tests_query/test_bids_query_derivatives.m +++ b/tests/tests_query/test_bids_query_derivatives.m @@ -9,6 +9,7 @@ function test_bids_query_derivatives_basic() BIDS = bids.layout(fullfile(get_test_data_dir(), 'ds000001-fmriprep'), ... + 'index_dependencies', false, ... 'use_schema', false); spaces = bids.query(BIDS, 'spaces'); diff --git a/tests/tests_query/test_bids_query_dwi.m b/tests/tests_query/test_bids_query_dwi.m index 4e8fc39b..1ccea623 100644 --- a/tests/tests_query/test_bids_query_dwi.m +++ b/tests/tests_query/test_bids_query_dwi.m @@ -11,7 +11,8 @@ function test_bids_query_dwi_basic() % dwi queries % %% - BIDS = bids.layout(fullfile(get_test_data_dir(), 'eeg_rest_fmri')); + BIDS = bids.layout(fullfile(get_test_data_dir(), 'eeg_rest_fmri'), ... + 'index_dependencies', false); modalities = {'anat', 'dwi', 'eeg', 'func'}; assertEqual(bids.query(BIDS, 'modalities'), modalities); diff --git a/tests/tests_query/test_bids_query_eeg.m b/tests/tests_query/test_bids_query_eeg.m index cc480d8d..cc66e1aa 100644 --- a/tests/tests_query/test_bids_query_eeg.m +++ b/tests/tests_query/test_bids_query_eeg.m @@ -12,7 +12,8 @@ function test_bids_query_eeg_basic_1() % %% - BIDS = bids.layout(fullfile(get_test_data_dir, 'eeg_face13')); + BIDS = bids.layout(fullfile(get_test_data_dir, 'eeg_face13'), ... + 'index_dependencies', false); modalities = {'eeg'}; assertEqual(bids.query(BIDS, 'modalities'), modalities); @@ -38,7 +39,8 @@ function test_bids_query_eeg_basic_2() % %% - BIDS = bids.layout(fullfile(get_test_data_dir, 'eeg_ds000117')); + BIDS = bids.layout(fullfile(get_test_data_dir, 'eeg_ds000117'), ... + 'index_dependencies', false); modalities = {'anat', 'eeg'}; assertEqual(bids.query(BIDS, 'modalities'), modalities); diff --git a/tests/tests_query/test_bids_query_func.m b/tests/tests_query/test_bids_query_func.m index 0e541954..6c3d8666 100644 --- a/tests/tests_query/test_bids_query_func.m +++ b/tests/tests_query/test_bids_query_func.m @@ -11,7 +11,8 @@ function test_bids_query_func_basic() % func queries % - BIDS = bids.layout(fullfile(get_test_data_dir(), 'ds001')); + BIDS = bids.layout(fullfile(get_test_data_dir(), 'ds001'), ... + 'index_dependencies', false); %% dependencies dependencies = bids.query(BIDS, 'dependencies', ... diff --git a/tests/tests_query/test_bids_query_ieeg.m b/tests/tests_query/test_bids_query_ieeg.m index 89c85260..ca52e765 100644 --- a/tests/tests_query/test_bids_query_ieeg.m +++ b/tests/tests_query/test_bids_query_ieeg.m @@ -12,7 +12,8 @@ function test_bids_query_ieeg_basic_1() % %% - BIDS = bids.layout(fullfile(get_test_data_dir(), 'ieeg_epilepsy')); + BIDS = bids.layout(fullfile(get_test_data_dir(), 'ieeg_epilepsy'), ... + 'index_dependencies', false); modalities = {'anat', 'ieeg'}; assertEqual(bids.query(BIDS, 'modalities'), modalities); @@ -38,7 +39,8 @@ function test_bids_query_ieeg_basic_2() % %% - BIDS = bids.layout(fullfile(get_test_data_dir(), 'ieeg_epilepsy_ecog')); + BIDS = bids.layout(fullfile(get_test_data_dir(), 'ieeg_epilepsy_ecog'), ... + 'index_dependencies', false); modalities = {'anat', 'ieeg'}; assertEqual(bids.query(BIDS, 'modalities'), modalities); diff --git a/tests/tests_query/test_bids_query_matlab_octave.m b/tests/tests_query/test_bids_query_matlab_octave.m index 1d74463a..bb73dd71 100644 --- a/tests/tests_query/test_bids_query_matlab_octave.m +++ b/tests/tests_query/test_bids_query_matlab_octave.m @@ -11,7 +11,8 @@ function test_query_impossible_suffix_should_return_empty() - BIDS = bids.layout(fullfile(get_test_data_dir(), '7t_trt')); + BIDS = bids.layout(fullfile(get_test_data_dir(), '7t_trt'), ... + 'index_dependencies', false); subjects = bids.query(BIDS, 'subjects'); assertEqual(size(subjects), [1, 22]); diff --git a/tests/tests_query/test_bids_query_meg.m b/tests/tests_query/test_bids_query_meg.m index 9a50d795..f56a4465 100644 --- a/tests/tests_query/test_bids_query_meg.m +++ b/tests/tests_query/test_bids_query_meg.m @@ -11,7 +11,8 @@ function test_bids_query_meg_basic() % meg queries % - BIDS = bids.layout(fullfile(get_test_data_dir(), 'ds000246')); + BIDS = bids.layout(fullfile(get_test_data_dir(), 'ds000246'), ... + 'index_dependencies', false); modalities = {'anat', 'meg'}; assertEqual(bids.query(BIDS, 'modalities'), modalities); @@ -21,9 +22,8 @@ function test_bids_query_meg_basic() assertEqual(bids.query(BIDS, 'suffixes'), suffixes); % smoke tests - BIDS = bids.layout(fullfile(get_test_data_dir(), 'ds000247')); - - BIDS = bids.layout(fullfile(get_test_data_dir(), 'ds000248')); + BIDS = bids.layout(fullfile(get_test_data_dir(), 'ds000248'), ... + 'index_dependencies', false); dependencies = bids.query(BIDS, 'dependencies', 'sub', '01', 'suffix', 'meg'); diff --git a/tests/tests_query/test_bids_query_microscopy.m b/tests/tests_query/test_bids_query_microscopy.m index 1bc991a6..043f8bd1 100644 --- a/tests/tests_query/test_bids_query_microscopy.m +++ b/tests/tests_query/test_bids_query_microscopy.m @@ -8,12 +8,14 @@ function test_bids_query_microscopy_basic() - BIDS = bids.layout(fullfile(get_test_data_dir(), 'micr_SEM')); + BIDS = bids.layout(fullfile(get_test_data_dir(), 'micr_SEM'), ... + 'index_dependencies', false); data = bids.query(BIDS, 'data'); assertEqual(numel(data), 6); - BIDS = bids.layout(fullfile(get_test_data_dir(), 'micr_SPIM')); + BIDS = bids.layout(fullfile(get_test_data_dir(), 'micr_SPIM'), ... + 'index_dependencies', false); data = bids.query(BIDS, 'data'); assertEqual(numel(data), 11); diff --git a/tests/tests_query/test_bids_query_motion.m b/tests/tests_query/test_bids_query_motion.m index 62ee47ee..3d199607 100644 --- a/tests/tests_query/test_bids_query_motion.m +++ b/tests/tests_query/test_bids_query_motion.m @@ -11,7 +11,8 @@ function test_bids_query_motion_basic() % motion queries % - BIDS = bids.layout(fullfile(get_test_data_dir(), 'motion_spotrotation')); + BIDS = bids.layout(fullfile(get_test_data_dir(), 'motion_spotrotation'), ... + 'index_dependencies', false); optodes_files = bids.query(BIDS, 'data', ... 'suffix', 'channels'); diff --git a/tests/tests_query/test_bids_query_nirs.m b/tests/tests_query/test_bids_query_nirs.m index 44d39b6e..ab345c1b 100644 --- a/tests/tests_query/test_bids_query_nirs.m +++ b/tests/tests_query/test_bids_query_nirs.m @@ -11,7 +11,8 @@ function test_bids_query_nirs_basic() % nirs queries % - BIDS = bids.layout(fullfile(get_test_data_dir(), 'fnirs_tapping')); + BIDS = bids.layout(fullfile(get_test_data_dir(), 'fnirs_tapping'), ... + 'index_dependencies', false); optodes_files = bids.query(BIDS, 'data', ... 'suffix', 'optodes'); diff --git a/tests/tests_query/test_bids_query_qmri.m b/tests/tests_query/test_bids_query_qmri.m index fd6676ff..b44a8e2d 100644 --- a/tests/tests_query/test_bids_query_qmri.m +++ b/tests/tests_query/test_bids_query_qmri.m @@ -8,7 +8,8 @@ function test_bids_query_qmri_megre_echos() - BIDS = bids.layout(fullfile(get_test_data_dir(), 'qmri_megre')); + BIDS = bids.layout(fullfile(get_test_data_dir(), 'qmri_megre'), ... + 'index_dependencies', false); echos = bids.query(BIDS, 'echos', 'modality', 'anat'); assertEqual(numel(echos), 8); @@ -17,7 +18,8 @@ function test_bids_query_qmri_megre_echos() function test_bids_query_qmri_irt1_inv() - BIDS = bids.layout(fullfile(get_test_data_dir(), 'qmri_irt1')); + BIDS = bids.layout(fullfile(get_test_data_dir(), 'qmri_irt1'), ... + 'index_dependencies', false); inversions = bids.query(BIDS, 'inversions'); assertEqual(numel(inversions), 4); diff --git a/tests/tests_query/test_query_bug_453.m b/tests/tests_query/test_query_bug_453.m index 56c2a8e5..f7804072 100644 --- a/tests/tests_query/test_query_bug_453.m +++ b/tests/tests_query/test_query_bug_453.m @@ -1,6 +1,7 @@ function test_query_bug_453() - BIDS = bids.layout(fullfile(get_test_data_dir(), 'ds000248')); + BIDS = bids.layout(fullfile(get_test_data_dir(), 'ds000248'), ... + 'index_dependencies', false); assertEqual(bids.query(BIDS, 'modalities'), {'anat', 'meg'}); assertEqual(bids.query(BIDS, 'modalities', 'task', '.*'), {'meg'}); diff --git a/tests/tests_utils/test_plot_events.m b/tests/tests_utils/test_plot_events.m index a0084bf2..7e61f17f 100644 --- a/tests/tests_utils/test_plot_events.m +++ b/tests/tests_utils/test_plot_events.m @@ -12,7 +12,7 @@ function test_plot_events_ds101() data_dir = fullfile(get_test_data_dir(), 'ds001'); - BIDS = bids.layout(data_dir); + BIDS = bids.layout(data_dir, 'index_dependencies', false); events_files = bids.query(BIDS, ... 'data', ... @@ -33,7 +33,7 @@ function test_plot_events_ds101_with_model() 'model', ... 'model-balloonanalogrisktask_smdl.json'); - BIDS = bids.layout(data_dir); + BIDS = bids.layout(data_dir, 'index_dependencies', false); events_files = bids.query(BIDS, ... 'data', ... @@ -49,7 +49,7 @@ function test_plot_events_ds108() data_dir = fullfile(get_test_data_dir(), 'ds108'); - BIDS = bids.layout(data_dir); + BIDS = bids.layout(data_dir, 'index_dependencies', false); events_files = bids.query(BIDS, ... 'data', ... From 8c82ef4bae06d9732af0052a7da2ea76ccccf2f2 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Thu, 17 Aug 2023 15:21:20 -0400 Subject: [PATCH 03/13] run on latest and oldest matlab --- .github/workflows/run_tests_matlab.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run_tests_matlab.yml b/.github/workflows/run_tests_matlab.yml index 4e530097..b5ecaf29 100644 --- a/.github/workflows/run_tests_matlab.yml +++ b/.github/workflows/run_tests_matlab.yml @@ -19,7 +19,7 @@ jobs: strategy: fail-fast: false matrix: - version: [R2021a, R2021b, R2022a, R2022b] + version: [R2020a, R2023a] os: [ubuntu-latest, macos-latest, windows-latest] From 82266715792d9b87a66e7bc75f6a0fa6d24d113d Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Thu, 17 Aug 2023 15:24:50 -0400 Subject: [PATCH 04/13] [DATALAD] Recorded changes --- .github/workflows/run_tests_matlab.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run_tests_matlab.yml b/.github/workflows/run_tests_matlab.yml index b5ecaf29..3737f433 100644 --- a/.github/workflows/run_tests_matlab.yml +++ b/.github/workflows/run_tests_matlab.yml @@ -19,7 +19,7 @@ jobs: strategy: fail-fast: false matrix: - version: [R2020a, R2023a] + version: [R2020b, R2023a] os: [ubuntu-latest, macos-latest, windows-latest] From ad97276dd51fc4f34f89c3b7c673194fa8c52718 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Thu, 17 Aug 2023 15:25:55 -0400 Subject: [PATCH 05/13] [DATALAD] Recorded changes --- .github/workflows/run_tests_matlab.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run_tests_matlab.yml b/.github/workflows/run_tests_matlab.yml index 3737f433..fd8babfc 100644 --- a/.github/workflows/run_tests_matlab.yml +++ b/.github/workflows/run_tests_matlab.yml @@ -19,7 +19,7 @@ jobs: strategy: fail-fast: false matrix: - version: [R2020b, R2023a] + version: [R2021a, R2023a] os: [ubuntu-latest, macos-latest, windows-latest] From fb2afec0c564eb8eb9f0ebefba264c6e0de3bc3d Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Thu, 17 Aug 2023 15:29:13 -0400 Subject: [PATCH 06/13] cancel previous runs --- .github/workflows/run_examples.yml | 5 +++++ .github/workflows/run_tests_matlab.yml | 4 ++++ .github/workflows/run_tests_octave.yml | 4 ++++ .github/workflows/update_schema.yml | 4 ++++ .github/workflows/validate.yml | 4 ++++ 5 files changed, 21 insertions(+) diff --git a/.github/workflows/run_examples.yml b/.github/workflows/run_examples.yml index 6e4c385f..db2b3687 100644 --- a/.github/workflows/run_examples.yml +++ b/.github/workflows/run_examples.yml @@ -1,6 +1,11 @@ --- name: tests_examples + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + on: push: branches: diff --git a/.github/workflows/run_tests_matlab.yml b/.github/workflows/run_tests_matlab.yml index fd8babfc..6602323f 100644 --- a/.github/workflows/run_tests_matlab.yml +++ b/.github/workflows/run_tests_matlab.yml @@ -1,6 +1,10 @@ --- name: 'matlab: tests' +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + on: push: branches: diff --git a/.github/workflows/run_tests_octave.yml b/.github/workflows/run_tests_octave.yml index 0a823c5d..c45f20ea 100644 --- a/.github/workflows/run_tests_octave.yml +++ b/.github/workflows/run_tests_octave.yml @@ -1,6 +1,10 @@ --- name: 'octave: tests' +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + on: push: branches: diff --git a/.github/workflows/update_schema.yml b/.github/workflows/update_schema.yml index 560d08e0..38a5632e 100644 --- a/.github/workflows/update_schema.yml +++ b/.github/workflows/update_schema.yml @@ -21,6 +21,10 @@ name: update schema # │ │ │ │ │ # * * * * * +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + on: push: branches: diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index aef92fb9..15476d11 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -1,6 +1,10 @@ --- name: validate +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + on: push: branches: ['*'] From 6bd12779e12b8129beb43d33a94a0bf3c1f8a1e3 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Thu, 17 Aug 2023 18:22:46 -0400 Subject: [PATCH 07/13] speed up some tests or functions --- +bids/+util/create_sessions_tsv.m | 3 ++- tests/tests_private/test_list_events.m | 6 ++---- tests/tests_utils/test_create_data_dict.m | 12 ++++++++---- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/+bids/+util/create_sessions_tsv.m b/+bids/+util/create_sessions_tsv.m index d5e2e3f7..e1551466 100644 --- a/+bids/+util/create_sessions_tsv.m +++ b/+bids/+util/create_sessions_tsv.m @@ -49,7 +49,8 @@ %% output_filenames = {}; - layout = bids.layout(layout_or_path, 'use_schema', use_schema); + layout = bids.layout(layout_or_path, 'use_schema', use_schema, ... + 'index_dependencies', false); sessions_list = bids.query(layout, 'sessions'); if isempty(sessions_list) && use_schema diff --git a/tests/tests_private/test_list_events.m b/tests/tests_private/test_list_events.m index 23e57753..99af8d16 100644 --- a/tests/tests_private/test_list_events.m +++ b/tests/tests_private/test_list_events.m @@ -14,19 +14,17 @@ function test_list_events_basic() pth_bids_example = get_test_data_dir(); - data_sets_to_test = '^ds00.*[0-9]$'; % '^ds.*[0-9]$' + data_sets_to_test = '^ds00[0-9]$'; % '^ds.*[0-9]$' examples = bids.internal.file_utils('FPList', get_test_data_dir(), 'dir', data_sets_to_test); for i = 1:size(examples, 1) - BIDS = bids.layout(deblank(examples(i, :))); + BIDS = bids.layout(deblank(examples(i, :)), 'index_dependencies', false); tasks = bids.query(BIDS, 'tasks'); for j = 1:numel(tasks) - [bids.internal.file_utils(BIDS.pth, 'basename'), ' - ', tasks{j}]; - [data, headers, y_labels] = bids.internal.list_events(BIDS, 'func', tasks{j}); bids.internal.plot_diagnostic_table(data, ... diff --git a/tests/tests_utils/test_create_data_dict.m b/tests/tests_utils/test_create_data_dict.m index efbb9158..b573594d 100644 --- a/tests/tests_utils/test_create_data_dict.m +++ b/tests/tests_utils/test_create_data_dict.m @@ -10,7 +10,8 @@ function test_create_data_dict_basic() pth_bids_example = get_test_data_dir(); - BIDS = bids.layout(fullfile(pth_bids_example, 'ds001')); + BIDS = bids.layout(fullfile(pth_bids_example, 'ds001'), ... + 'index_dependencies', false); tsv_files = bids.query(BIDS, 'data', ... 'sub', '01', ... @@ -48,7 +49,8 @@ function test_create_data_dict_schema() pth_bids_example = get_test_data_dir(); - BIDS = bids.layout(fullfile(pth_bids_example, 'ds001')); + BIDS = bids.layout(fullfile(pth_bids_example, 'ds001'), ... + 'index_dependencies', false); tsv_files = bids.query(BIDS, 'data', ... 'suffix', 'events'); @@ -76,7 +78,8 @@ function test_create_data_dict_schema() pth_bids_example = get_test_data_dir(); - BIDS = bids.layout(fullfile(pth_bids_example, dataset)); + BIDS = bids.layout(fullfile(pth_bids_example, dataset), ... + 'index_dependencies', false); tasks = bids.query(BIDS, 'tasks'); @@ -154,7 +157,8 @@ function test_create_data_dict_several_tsv() dataset = datasets{i_dataset}; - BIDS = bids.layout(fullfile(pth_bids_example, dataset)); + BIDS = bids.layout(fullfile(pth_bids_example, dataset), ... + 'index_dependencies', false); tasks = bids.query(BIDS, 'tasks'); From f08620887c9d81c89383b54abc27d3ee0a6cb4f3 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Thu, 17 Aug 2023 18:45:44 -0400 Subject: [PATCH 08/13] run slow and fast tests in parallel --- +bids/+internal/is_github_ci.m | 2 +- .github/workflows/run_tests_matlab.yml | 5 +++ .github/workflows/run_tests_octave.yml | 9 +++++ run_tests.m | 5 ++- tests/tests_slow/test_download_ds.m | 53 ++++++++++++++++++++++++++ tests/utils/run_slow_test_only.m | 8 ++++ 6 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 tests/tests_slow/test_download_ds.m create mode 100644 tests/utils/run_slow_test_only.m diff --git a/+bids/+internal/is_github_ci.m b/+bids/+internal/is_github_ci.m index 3b4ee8e3..0519163c 100644 --- a/+bids/+internal/is_github_ci.m +++ b/+bids/+internal/is_github_ci.m @@ -3,7 +3,7 @@ % (C) Copyright 2021 Remi Gau is_github = false; - GITHUB_WORKSPACE = getenv('HOME'); + GITHUB_WORKSPACE = bg; IS_CI = getenv('CI'); if IS_CI diff --git a/.github/workflows/run_tests_matlab.yml b/.github/workflows/run_tests_matlab.yml index 6602323f..9239108c 100644 --- a/.github/workflows/run_tests_matlab.yml +++ b/.github/workflows/run_tests_matlab.yml @@ -25,6 +25,7 @@ jobs: matrix: version: [R2021a, R2023a] os: [ubuntu-latest, macos-latest, windows-latest] + test: [slow, fast] runs-on: ${{matrix.os}} @@ -61,6 +62,10 @@ jobs: git clone https://github.com/MOxUnit/MOxUnit.git --depth 1 git clone https://github.com/MOcov/MOcov.git --depth 1 + - name: set environment variable + if: matrix.test == 'slow' + run: export SLOW=true + - name: Run commands uses: matlab-actions/run-command@v1.1.3 with: diff --git a/.github/workflows/run_tests_octave.yml b/.github/workflows/run_tests_octave.yml index c45f20ea..f65cfb33 100644 --- a/.github/workflows/run_tests_octave.yml +++ b/.github/workflows/run_tests_octave.yml @@ -21,6 +21,11 @@ env: jobs: test: + strategy: + fail-fast: false + matrix: + test: [slow, fast] + runs-on: ubuntu-22.04 steps: @@ -70,6 +75,10 @@ jobs: mkoctfile --mex jsonread.c jsmn.c -DJSMN_PARENT_LINKS octave $OCTFLAGS --eval "addpath(fullfile(pwd)); savepath();" + - name: set environment variable + if: matrix.test == 'slow' + run: export SLOW=true + - name: Run unit tests Octave run: | octave $OCTFLAGS --eval "success = run_tests(); assert(success);" diff --git a/run_tests.m b/run_tests.m index d895e89a..cc7214e9 100644 --- a/run_tests.m +++ b/run_tests.m @@ -16,12 +16,15 @@ addpath(fullfile(pwd, 'tests', 'utils')); folderToCover = fullfile(pwd, '+bids'); + testFolder = fullfile(pwd, 'tests'); + if run_slow_test_only + testFolder = fullfile(pwd, 'tests', 'tests_slow'); + end if with_coverage success = moxunit_runtests(testFolder, ... '-verbose', ... - '-randomize_order', ... '-recursive', ... '-with_coverage', ... '-cover', folderToCover, ... diff --git a/tests/tests_slow/test_download_ds.m b/tests/tests_slow/test_download_ds.m new file mode 100644 index 00000000..948f3410 --- /dev/null +++ b/tests/tests_slow/test_download_ds.m @@ -0,0 +1,53 @@ +function test_suite = test_download_ds %#ok<*STOUT> + + try % assignment of 'localfunctions' is necessary in Matlab >= 2016 + test_functions = localfunctions(); %#ok<*NASGU> + catch % no problem; early Matlab versions can use initTestSuite fine + end + initTestSuite; + +end + +function test_download_ds_moae() + + if ~run_slow_test_only() + moxunit_throw_test_skipped_exception('slow test only'); + end + + output_dir = bids.util.download_ds('source', 'spm', ... + 'demo', 'moae', ... + 'out_path', temp_dir(), ... + 'force', false, ... + 'verbose', true, ... + 'delete_previous', false); + + output_dir = bids.util.download_ds('source', 'spm', ... + 'demo', 'moae', ... + 'out_path', temp_dir(), ... + 'force', true, ... + 'verbose', true, ... + 'delete_previous', false); + + output_dir = bids.util.download_ds('source', 'spm', ... + 'demo', 'moae', ... + 'out_path', temp_dir(), ... + 'force', true, ... + 'verbose', true, ... + 'delete_previous', true); + +end + +function test_download_ds_facerep() + + if ~run_slow_test_only() + moxunit_throw_test_skipped_exception('slow test only'); + end + + output_dir = bids.util.download_ds('source', 'spm', ... + 'demo', 'facerep', ... + 'out_path', temp_dir(), ... + 'force', true, ... + 'verbose', true, ... + 'delete_previous', true); + +end diff --git a/tests/utils/run_slow_test_only.m b/tests/utils/run_slow_test_only.m new file mode 100644 index 00000000..70cde4ba --- /dev/null +++ b/tests/utils/run_slow_test_only.m @@ -0,0 +1,8 @@ +function value = run_slow_test_only() + % (C) Copyright 2023 BIDS-MATLAB developers + SLOW = getenv('SLOW'); + value = false; + if ~isempty(SLOW) + value = true; + end +end From e127f3e4610f0b239012f4b45e26f3a2a20162d6 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Thu, 17 Aug 2023 19:17:00 -0400 Subject: [PATCH 09/13] windows env var fix --- .github/workflows/run_tests_matlab.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/run_tests_matlab.yml b/.github/workflows/run_tests_matlab.yml index 9239108c..51acc7b0 100644 --- a/.github/workflows/run_tests_matlab.yml +++ b/.github/workflows/run_tests_matlab.yml @@ -62,10 +62,15 @@ jobs: git clone https://github.com/MOxUnit/MOxUnit.git --depth 1 git clone https://github.com/MOcov/MOcov.git --depth 1 - - name: set environment variable - if: matrix.test == 'slow' + - name: set environment variable unix + if: matrix.test == 'slow' && matrix.os == 'ubuntu-latest' run: export SLOW=true + - name: set environment variable windows + if: matrix.test == 'slow' && matrix.os == 'windows-latest' + run: | + setx SLOW "true" + - name: Run commands uses: matlab-actions/run-command@v1.1.3 with: From 91cedd6ccbdc8903cc0a70015fabd02458c6b15d Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Thu, 17 Aug 2023 21:23:05 -0400 Subject: [PATCH 10/13] try using globals --- +bids/+internal/is_github_ci.m | 2 +- .github/workflows/run_tests_matlab.yml | 17 +++++----- .github/workflows/run_tests_octave.yml | 11 ++++--- run_tests.m | 2 ++ tests/test_download_ds.m | 45 -------------------------- tests/utils/run_slow_test_only.m | 5 +-- 6 files changed, 21 insertions(+), 61 deletions(-) delete mode 100644 tests/test_download_ds.m diff --git a/+bids/+internal/is_github_ci.m b/+bids/+internal/is_github_ci.m index 0519163c..3b4ee8e3 100644 --- a/+bids/+internal/is_github_ci.m +++ b/+bids/+internal/is_github_ci.m @@ -3,7 +3,7 @@ % (C) Copyright 2021 Remi Gau is_github = false; - GITHUB_WORKSPACE = bg; + GITHUB_WORKSPACE = getenv('HOME'); IS_CI = getenv('CI'); if IS_CI diff --git a/.github/workflows/run_tests_matlab.yml b/.github/workflows/run_tests_matlab.yml index 51acc7b0..2abf14f7 100644 --- a/.github/workflows/run_tests_matlab.yml +++ b/.github/workflows/run_tests_matlab.yml @@ -62,16 +62,15 @@ jobs: git clone https://github.com/MOxUnit/MOxUnit.git --depth 1 git clone https://github.com/MOcov/MOcov.git --depth 1 - - name: set environment variable unix - if: matrix.test == 'slow' && matrix.os == 'ubuntu-latest' - run: export SLOW=true - - - name: set environment variable windows - if: matrix.test == 'slow' && matrix.os == 'windows-latest' - run: | - setx SLOW "true" + - name: Run slow tests + if: matrix.test == 'slow' + uses: matlab-actions/run-command@v1.1.3 + with: + command: run MOxUnit/MOxUnit/moxunit_set_path(); addpath(fullfile(pwd, 'MOcov', 'MOcov')); global SLOW; SLOW=true; addpath(getenv('GITHUB_WORKSPACE')); + success = run_tests(); assert(success); - - name: Run commands + - name: Run fast commands + if: matrix.test == 'fast' uses: matlab-actions/run-command@v1.1.3 with: command: run MOxUnit/MOxUnit/moxunit_set_path(); addpath(fullfile(pwd, 'MOcov', 'MOcov')); addpath(getenv('GITHUB_WORKSPACE')); success = run_tests(); diff --git a/.github/workflows/run_tests_octave.yml b/.github/workflows/run_tests_octave.yml index f65cfb33..9e855168 100644 --- a/.github/workflows/run_tests_octave.yml +++ b/.github/workflows/run_tests_octave.yml @@ -75,10 +75,13 @@ jobs: mkoctfile --mex jsonread.c jsmn.c -DJSMN_PARENT_LINKS octave $OCTFLAGS --eval "addpath(fullfile(pwd)); savepath();" - - name: set environment variable - if: matrix.test == 'slow' - run: export SLOW=true + - name: Run fast tests Octave + if: matrix.test == 'fast' + run: | + octave $OCTFLAGS --eval "success = run_tests(); assert(success);" - - name: Run unit tests Octave + - name: Run slow tests Octave + if: matrix.test == 'slow' run: | + export SLOW=true octave $OCTFLAGS --eval "success = run_tests(); assert(success);" diff --git a/run_tests.m b/run_tests.m index cc7214e9..67c6d533 100644 --- a/run_tests.m +++ b/run_tests.m @@ -19,12 +19,14 @@ testFolder = fullfile(pwd, 'tests'); if run_slow_test_only + fprintf('Running only slow tests\n'); testFolder = fullfile(pwd, 'tests', 'tests_slow'); end if with_coverage success = moxunit_runtests(testFolder, ... '-verbose', ... + '-randomize_order', ... '-recursive', ... '-with_coverage', ... '-cover', folderToCover, ... diff --git a/tests/test_download_ds.m b/tests/test_download_ds.m deleted file mode 100644 index 2fc4bde0..00000000 --- a/tests/test_download_ds.m +++ /dev/null @@ -1,45 +0,0 @@ -function test_suite = test_download_ds %#ok<*STOUT> - - try % assignment of 'localfunctions' is necessary in Matlab >= 2016 - test_functions = localfunctions(); %#ok<*NASGU> - catch % no problem; early Matlab versions can use initTestSuite fine - end - initTestSuite; - -end - -function test_download_ds_moae() - - output_dir = bids.util.download_ds('source', 'spm', ... - 'demo', 'moae', ... - 'out_path', temp_dir(), ... - 'force', false, ... - 'verbose', true, ... - 'delete_previous', false); - - output_dir = bids.util.download_ds('source', 'spm', ... - 'demo', 'moae', ... - 'out_path', temp_dir(), ... - 'force', true, ... - 'verbose', true, ... - 'delete_previous', false); - - output_dir = bids.util.download_ds('source', 'spm', ... - 'demo', 'moae', ... - 'out_path', temp_dir(), ... - 'force', true, ... - 'verbose', true, ... - 'delete_previous', true); - -end - -function test_download_ds_facerep() - - output_dir = bids.util.download_ds('source', 'spm', ... - 'demo', 'facerep', ... - 'out_path', temp_dir(), ... - 'force', true, ... - 'verbose', true, ... - 'delete_previous', true); - -end diff --git a/tests/utils/run_slow_test_only.m b/tests/utils/run_slow_test_only.m index 70cde4ba..1afd5b6c 100644 --- a/tests/utils/run_slow_test_only.m +++ b/tests/utils/run_slow_test_only.m @@ -1,8 +1,9 @@ function value = run_slow_test_only() % (C) Copyright 2023 BIDS-MATLAB developers - SLOW = getenv('SLOW'); + global SLOW + ENV_SLOW = getenv('SLOW'); value = false; - if ~isempty(SLOW) + if ~isempty(ENV_SLOW) || SLOW value = true; end end From 3f57165a8d4eedf30472ea13d96f8b906b4558c3 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Thu, 17 Aug 2023 22:32:25 -0400 Subject: [PATCH 11/13] fix --- tests/utils/run_slow_test_only.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/utils/run_slow_test_only.m b/tests/utils/run_slow_test_only.m index 1afd5b6c..72156ed1 100644 --- a/tests/utils/run_slow_test_only.m +++ b/tests/utils/run_slow_test_only.m @@ -3,7 +3,7 @@ global SLOW ENV_SLOW = getenv('SLOW'); value = false; - if ~isempty(ENV_SLOW) || SLOW + if ~isempty(ENV_SLOW) || (~isempty(SLOW) && SLOW) value = true; end end From a282a4d14f6493db97cc21330c4ff5413c1a4cfe Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Fri, 18 Aug 2023 05:45:37 -0400 Subject: [PATCH 12/13] add more slow test --- .github/workflows/run_tests_matlab.yml | 2 +- run_tests.m | 4 ++++ tests/{ => tests_slow}/test_diagnostic.m | 4 ++++ 3 files changed, 9 insertions(+), 1 deletion(-) rename tests/{ => tests_slow}/test_diagnostic.m (91%) diff --git a/.github/workflows/run_tests_matlab.yml b/.github/workflows/run_tests_matlab.yml index 2abf14f7..98486fee 100644 --- a/.github/workflows/run_tests_matlab.yml +++ b/.github/workflows/run_tests_matlab.yml @@ -69,7 +69,7 @@ jobs: command: run MOxUnit/MOxUnit/moxunit_set_path(); addpath(fullfile(pwd, 'MOcov', 'MOcov')); global SLOW; SLOW=true; addpath(getenv('GITHUB_WORKSPACE')); success = run_tests(); assert(success); - - name: Run fast commands + - name: Run fast tests if: matrix.test == 'fast' uses: matlab-actions/run-command@v1.1.3 with: diff --git a/run_tests.m b/run_tests.m index 67c6d533..ca200bb9 100644 --- a/run_tests.m +++ b/run_tests.m @@ -3,6 +3,8 @@ % (C) Copyright 2021 BIDS-MATLAB developers + tic; + fprintf('\nRunning tests\n'); if nargin < 1 @@ -40,4 +42,6 @@ end + toc; + end diff --git a/tests/test_diagnostic.m b/tests/tests_slow/test_diagnostic.m similarity index 91% rename from tests/test_diagnostic.m rename to tests/tests_slow/test_diagnostic.m index 80eca978..a1657697 100644 --- a/tests/test_diagnostic.m +++ b/tests/tests_slow/test_diagnostic.m @@ -10,6 +10,10 @@ function test_diagnostic_basic() + if ~run_slow_test_only() + moxunit_throw_test_skipped_exception('slow test only'); + end + close all; pth_bids_example = get_test_data_dir(); From 368ea3fba905cb23ab9c39b58d73805f8239c383 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Fri, 18 Aug 2023 06:54:38 -0400 Subject: [PATCH 13/13] add doc --- +bids/File.m | 1 + .../source/images}/timing.png | Bin docs/source/index.rst | 1 + docs/source/performance.rst | 21 ++++++++++++++++++ 4 files changed, 23 insertions(+) rename {tests/tests_layout => docs/source/images}/timing.png (100%) create mode 100644 docs/source/performance.rst diff --git a/+bids/File.m b/+bids/File.m index 0dd8e5fd..772aced8 100644 --- a/+bids/File.m +++ b/+bids/File.m @@ -83,6 +83,7 @@ % Modify metadata % % .. code-block:: matlab + % % % Adding new value % f = f.metadata_add('NewField', 'new value'); % f.metadata() diff --git a/tests/tests_layout/timing.png b/docs/source/images/timing.png similarity index 100% rename from tests/tests_layout/timing.png rename to docs/source/images/timing.png diff --git a/docs/source/index.rst b/docs/source/index.rst index 659d1393..228951c6 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -24,6 +24,7 @@ To see how to install BIDS-Matlab, please check stats_model transformers schema + performance dev_doc diff --git a/docs/source/performance.rst b/docs/source/performance.rst new file mode 100644 index 00000000..0e9e57da --- /dev/null +++ b/docs/source/performance.rst @@ -0,0 +1,21 @@ +Performance +*********** + +bids-matlab's performance may vary +depending on which options you choose for indexing with :func:`bids.layout`. + +Relying on the BIDS schema (``'use_schema', true``) to only include files that comply with it +may slow down performance a bit. + +Index dependencies (``'index_dependencies', true``) to detect files +with explicit dependencies between them +(for example when a fieldmap mentions that is intended for a specific bold run) +is much slower and you may consider setting this to ``false`` +when if you know that you have no such dependencies in your dataset. + + +.. _fig_benchmark: +.. figure:: images/timing.png + :align: center + + layout indexing performance depending on chosen options