From e83abc8c8b1797c28ee6f94f1a3854eb62984d26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Boris=20Cl=C3=A9net?= Date: Tue, 26 Sep 2023 10:40:39 +0200 Subject: [PATCH] [TEST] testing json and markdown export for team description --- narps_open/data/description/__main__.py | 2 + tests/data/test_description.py | 36 +++++++ tests/data/test_results.py | 3 +- .../data/description/test_markdown.md | 98 ++++++++++++++++++ .../test_data/data/description/test_str.json | 57 ++++++++++ .../results/team_2T6S/hypo1_unthresh.nii.gz | Bin .../results/team_2T6S/hypo2_unthresh.nii.gz | Bin .../results/team_2T6S/hypo3_unthresh.nii.gz | Bin .../results/team_2T6S/hypo4_unthresh.nii.gz | Bin .../results/team_2T6S/hypo5_unthresh.nii.gz | Bin .../results/team_2T6S/hypo6_unthresh.nii.gz | Bin .../results/team_2T6S/hypo7_unthresh.nii.gz | Bin .../results/team_2T6S/hypo8_unthresh.nii.gz | Bin .../results/team_2T6S/hypo9_unthresh.nii.gz | Bin 14 files changed, 195 insertions(+), 1 deletion(-) create mode 100644 tests/test_data/data/description/test_markdown.md create mode 100644 tests/test_data/data/description/test_str.json rename tests/test_data/{ => data}/results/team_2T6S/hypo1_unthresh.nii.gz (100%) rename tests/test_data/{ => data}/results/team_2T6S/hypo2_unthresh.nii.gz (100%) rename tests/test_data/{ => data}/results/team_2T6S/hypo3_unthresh.nii.gz (100%) rename tests/test_data/{ => data}/results/team_2T6S/hypo4_unthresh.nii.gz (100%) rename tests/test_data/{ => data}/results/team_2T6S/hypo5_unthresh.nii.gz (100%) rename tests/test_data/{ => data}/results/team_2T6S/hypo6_unthresh.nii.gz (100%) rename tests/test_data/{ => data}/results/team_2T6S/hypo7_unthresh.nii.gz (100%) rename tests/test_data/{ => data}/results/team_2T6S/hypo8_unthresh.nii.gz (100%) rename tests/test_data/{ => data}/results/team_2T6S/hypo9_unthresh.nii.gz (100%) diff --git a/narps_open/data/description/__main__.py b/narps_open/data/description/__main__.py index 99b64fe8..49daad22 100644 --- a/narps_open/data/description/__main__.py +++ b/narps_open/data/description/__main__.py @@ -49,3 +49,5 @@ print(dumps(information.categorized_for_analysis, indent = 4)) elif arguments.dictionary == 'derived': print(dumps(information.derived, indent = 4)) + else: + print(dumps(information, indent = 4)) diff --git a/tests/data/test_description.py b/tests/data/test_description.py index 3bdc7c2c..03f95d4b 100644 --- a/tests/data/test_description.py +++ b/tests/data/test_description.py @@ -11,8 +11,11 @@ pytest -q test_description.py -k """ +from os.path import join + from pytest import raises, mark +from narps_open.utils.configuration import Configuration from narps_open.data.description import TeamDescription class TestUtilsDescription: @@ -86,3 +89,36 @@ def test_arguments_properties(): assert description['general.softwares'] == 'FSL 5.0.11, MRIQC, FMRIPREP' assert isinstance(description.general, dict) assert description.general['softwares'] == 'FSL 5.0.11, MRIQC, FMRIPREP' + + @staticmethod + @mark.unit_test + def test_markdown(): + """ Test writing a TeamDescription as Markdown """ + + # Generate markdown from description + description = TeamDescription('9Q6R') + markdown = description.markdown() + + # Compare markdown with test file + test_file_path = join( + Configuration()['directories']['test_data'], + 'data', 'description', 'test_markdown.md' + ) + with open(test_file_path, 'r', encoding = 'utf-8') as file: + assert markdown == file.read() + + @staticmethod + @mark.unit_test + def test_str(): + """ Test writing a TeamDescription as JSON """ + + # Generate report + description = TeamDescription('9Q6R') + + # Compare string version of the description with test file + test_file_path = join( + Configuration()['directories']['test_data'], + 'data', 'description', 'test_str.json' + ) + with open(test_file_path, 'r', encoding = 'utf-8') as file: + assert str(description) == file.read() diff --git a/tests/data/test_results.py b/tests/data/test_results.py index 46d2d1f5..2465eb7d 100644 --- a/tests/data/test_results.py +++ b/tests/data/test_results.py @@ -103,7 +103,8 @@ def test_rectify(): """ Test the rectify method """ # Get raw data - orig_directory = join(Configuration()['directories']['test_data'], 'results', 'team_2T6S') + orig_directory = join( + Configuration()['directories']['test_data'], 'data', 'results', 'team_2T6S') # Create test data test_directory = join(Configuration()['directories']['test_runs'], 'results_team_2T6S') diff --git a/tests/test_data/data/description/test_markdown.md b/tests/test_data/data/description/test_markdown.md new file mode 100644 index 00000000..080d397c --- /dev/null +++ b/tests/test_data/data/description/test_markdown.md @@ -0,0 +1,98 @@ +# NARPS team description : 9Q6R +## General +* `teamID` : 9Q6R +* `NV_collection_link` : https://neurovault.org/collections/4765/ +* `results_comments` : Note: Amygdala wasn't recruited for hypothesis tests 7-9, but the extended salience network was recruited in all contrasts (e.g. aINS, ACC). Based on looking at the unthresholded maps, hypotheses 8 and 9 would've been confirmed at lower cluster thresholds (i.e. z≥2.3 rather than z≥3.1). +* `preregistered` : No +* `link_preregistration_form` : NA +* `regions_definition` : Harvard-Oxford probabilistic cortical and subcortical atlases (Frontal Median Cortex, L+R Amyg, and L+R Accum for vmPFC, amyg, and VS, respectively). Also used Neurosynth to generate a mask based on the search term "ventral striatum" (height threshold at z>12, and cluster-extent at > 400mm^3) +* `softwares` : FSL 5.0.11, MRIQC, FMRIPREP +* `general_comments` : NA +## Exclusions +* `n_participants` : 104 +* `exclusions_details` : N=104 (54 eq_indiff, 50 eq_range). Excluded sub-018, sub-030, sub-088, and sub-100. High motion during function runs: All four participants had at least one run where > 50% of the TRs contained FD > 0.2mm. 18, 30, and 100 in particular were constant movers (all 4 runs > 50% TRS > 0.2 mm FD) +## Preprocessing +* `used_fmriprep_data` : No +* `preprocessing_order` : - MRIQC and FMRIPREP run on a local HPC +- FSL used for mass univariate analyses, avoiding re-registration using this approach: https://www.youtube.com/watch?time_continue=7&v=U3tG7JMEf7M +* `brain_extraction` : Freesurfer (i.e. part of fmriprep default pipeline) +* `segmentation` : Freesurfer +* `slice_time_correction` : Not performed +* `motion_correction` : Framewise displacement, and six standard motion regressors (x, y, z, rotx, rotx, and rotz) within subjects.; generated via MRIQC +* `motion` : 6 +* `gradient_distortion_correction` : NA +* `intra_subject_coreg` : bbregister, flirt, default FMRIPREP +* `distortion_correction` : Fieldmap-less distortion correction within fmriprep pipeline (--use-syn-sdc) +* `inter_subject_reg` : ANTs, multiscale nonlinear mutual-information default within FMRIPREP pipeline. +* `intensity_correction` : Default fMRIPREP INU correction +* `intensity_normalization` : Default fMRIPREP INU normalization +* `noise_removal` : None +* `volume_censoring` : None +* `spatial_smoothing` : 5mm FWHM +* `preprocessing_comments` : NA +## Analysis +* `data_submitted_to_model` : 453 total volumes, 104 participants (54 eq_indiff, 50 eq_range) +* `spatial_region_modeled` : Whole-Brain +* `independent_vars_first_level` : Event-related design predictors: +- Modeled duration = 4 +- EVs (3): Mean-centered Gain, Mean-Centered Loss, Events (constant) +Block design: +- baseline not explicitly modeled +HRF: +- FMRIB's Linear Optimal Basis Sets +Movement regressors: +- FD, six parameters (x, y, z, RotX, RotY, RotZ) +* `RT_modeling` : none +* `movement_modeling` : 1 +* `independent_vars_higher_level` : EVs (2): eq_indiff, eq_range +Contrasts in the group-level design matrix: +1 --> mean (1, 1) +2 --> eq_indiff (1, 0) +3 --> eq_range (0, 1) +4 --> indiff_gr_range (1, -1) +5 --> range_gr_indiff (-1, 1) +* `model_type` : Mass Univariate +* `model_settings` : First model: individual runs; +Second model: higher-level analysis on lower-level FEAT directories in a fixed effects model at the participant-level; +Third model: higher-level analysis on 3D COPE images from *.feat directories within second model *.gfeat; FLAME 1 (FMRIB's Local Analysis of Mixed Effects), with a cluster threshold of z≥3.1 +* `inference_contrast_effect` : First-Level A (Run-level; not listed: linear basis functions, FSL FLOBs): +Model EVs (3): gain, loss, event +- COPE1: Pos Gain (1, 0, 0) +- COPE4: Neg Gain (-1, 0, 0) +- COPE7: Pos Loss (0, 1, 0) +- COPE10: Neg Loss (0, -1, 0) +- COPE13: Events (0, 0, 1) +Confound EVs (7): Framewise Displacement, x, y, z, RotX, RotY, RotZ. Generated in MRIQC. + +First-Level B (Participant-level): +- All COPEs from the runs modeled in a high-level FEAT fixed effect model + +Second-Level (Group-level): +- Separate high-level FLAME 1 models run on COPE1, COPE4, COPE7, and COPE10. Hypotheses 1-4 answered using the COPE1 model, Hypotheses 5-6 answered using the COPE10 model, and Hypotheses 7-9 answered using the COPE7 model. +Model EVs (2): eq_indiff, eq_range +- mean (1, 1) +- eq_indiff (1, 0) +- eq_range (0, 1) +- indiff_gr_range (1, -1) +- range_gr_indiff (-1, 1) +* `search_region` : Whole brain +* `statistic_type` : Cluster size +* `pval_computation` : Standard parametric inference +* `multiple_testing_correction` : GRF_theory based FEW correction at z≥3.1 in FSL +* `comments_analysis` : NA +## Categorized for analysis +* `region_definition_vmpfc` : atlas HOA +* `region_definition_striatum` : atlas HOA, neurosynth +* `region_definition_amygdala` : atlas HOA +* `analysis_SW` : FSL +* `analysis_SW_with_version` : FSL 5.0.11 +* `smoothing_coef` : 5 +* `testing` : parametric +* `testing_thresh` : p<0.001 +* `correction_method` : GRTFWE cluster +* `correction_thresh_` : p<0.05 +## Derived +* `n_participants` : 104 +* `excluded_participants` : 018, 030, 088, 100 +* `func_fwhm` : 5 +* `con_fwhm` : diff --git a/tests/test_data/data/description/test_str.json b/tests/test_data/data/description/test_str.json new file mode 100644 index 00000000..0d27767e --- /dev/null +++ b/tests/test_data/data/description/test_str.json @@ -0,0 +1,57 @@ +{ + "general.teamID": "9Q6R", + "general.NV_collection_link": "https://neurovault.org/collections/4765/", + "general.results_comments": "Note: Amygdala wasn't recruited for hypothesis tests 7-9, but the extended salience network was recruited in all contrasts (e.g. aINS, ACC). Based on looking at the unthresholded maps, hypotheses 8 and 9 would've been confirmed at lower cluster thresholds (i.e. z\u22652.3 rather than z\u22653.1).", + "general.preregistered": "No", + "general.link_preregistration_form": "NA", + "general.regions_definition": "Harvard-Oxford probabilistic cortical and subcortical atlases (Frontal Median Cortex, L+R Amyg, and L+R Accum for vmPFC, amyg, and VS, respectively). Also used Neurosynth to generate a mask based on the search term \"ventral striatum\" (height threshold at z>12, and cluster-extent at > 400mm^3)", + "general.softwares": "FSL 5.0.11, MRIQC, FMRIPREP", + "exclusions.n_participants": "104", + "exclusions.exclusions_details": "N=104 (54 eq_indiff, 50 eq_range). Excluded sub-018, sub-030, sub-088, and sub-100. High motion during function runs: All four participants had at least one run where > 50% of the TRs contained FD > 0.2mm. 18, 30, and 100 in particular were constant movers (all 4 runs > 50% TRS > 0.2 mm FD) ", + "preprocessing.used_fmriprep_data": "No", + "preprocessing.preprocessing_order": " - MRIQC and FMRIPREP run on a local HPC\n- FSL used for mass univariate analyses, avoiding re-registration using this approach: https://www.youtube.com/watch?time_continue=7&v=U3tG7JMEf7M", + "preprocessing.brain_extraction": "Freesurfer (i.e. part of fmriprep default pipeline)", + "preprocessing.segmentation": "Freesurfer", + "preprocessing.slice_time_correction": "Not performed", + "preprocessing.motion_correction": "Framewise displacement, and six standard motion regressors (x, y, z, rotx, rotx, and rotz) within subjects.; generated via MRIQC ", + "preprocessing.motion": "6", + "preprocessing.gradient_distortion_correction": "NA", + "preprocessing.intra_subject_coreg": "bbregister, flirt, default FMRIPREP", + "preprocessing.distortion_correction": "Fieldmap-less distortion correction within fmriprep pipeline (--use-syn-sdc)", + "preprocessing.inter_subject_reg": "ANTs, multiscale nonlinear mutual-information default within FMRIPREP pipeline.", + "preprocessing.intensity_correction": "Default fMRIPREP INU correction", + "preprocessing.intensity_normalization": "Default fMRIPREP INU normalization", + "preprocessing.noise_removal": "None", + "preprocessing.volume_censoring": "None", + "preprocessing.spatial_smoothing": "5mm FWHM", + "preprocessing.preprocessing_comments": "NA", + "analysis.data_submitted_to_model": "453 total volumes, 104 participants (54 eq_indiff, 50 eq_range)", + "analysis.spatial_region_modeled": "Whole-Brain", + "analysis.independent_vars_first_level": "Event-related design predictors:\n- Modeled duration = 4\n- EVs (3): Mean-centered Gain, Mean-Centered Loss, Events (constant)\nBlock design:\n- baseline not explicitly modeled\nHRF:\n- FMRIB's Linear Optimal Basis Sets\nMovement regressors:\n- FD, six parameters (x, y, z, RotX, RotY, RotZ)", + "analysis.RT_modeling": "none", + "analysis.movement_modeling": "1", + "analysis.independent_vars_higher_level": "EVs (2): eq_indiff, eq_range\nContrasts in the group-level design matrix:\n1 --> mean (1, 1)\n2 --> eq_indiff (1, 0)\n3 --> eq_range (0, 1)\n4 --> indiff_gr_range (1, -1)\n5 --> range_gr_indiff (-1, 1)", + "analysis.model_type": "Mass Univariate", + "analysis.model_settings": "First model: individual runs; \nSecond model: higher-level analysis on lower-level FEAT directories in a fixed effects model at the participant-level; \nThird model: higher-level analysis on 3D COPE images from *.feat directories within second model *.gfeat; FLAME 1 (FMRIB's Local Analysis of Mixed Effects), with a cluster threshold of z\u22653.1", + "analysis.inference_contrast_effect": "First-Level A (Run-level; not listed: linear basis functions, FSL FLOBs):\nModel EVs (3): gain, loss, event\n- COPE1: Pos Gain (1, 0, 0)\n- COPE4: Neg Gain (-1, 0, 0)\n- COPE7: Pos Loss (0, 1, 0)\n- COPE10: Neg Loss (0, -1, 0)\n- COPE13: Events (0, 0, 1)\nConfound EVs (7): Framewise Displacement, x, y, z, RotX, RotY, RotZ. Generated in MRIQC.\n\nFirst-Level B (Participant-level):\n- All COPEs from the runs modeled in a high-level FEAT fixed effect model\n\nSecond-Level (Group-level):\n- Separate high-level FLAME 1 models run on COPE1, COPE4, COPE7, and COPE10. Hypotheses 1-4 answered using the COPE1 model, Hypotheses 5-6 answered using the COPE10 model, and Hypotheses 7-9 answered using the COPE7 model.\nModel EVs (2): eq_indiff, eq_range\n- mean (1, 1)\n- eq_indiff (1, 0)\n- eq_range (0, 1)\n- indiff_gr_range (1, -1)\n- range_gr_indiff (-1, 1) ", + "analysis.search_region": "Whole brain", + "analysis.statistic_type": "Cluster size", + "analysis.pval_computation": "Standard parametric inference", + "analysis.multiple_testing_correction": "GRF_theory based FEW correction at z\u22653.1 in FSL", + "analysis.comments_analysis": "NA", + "general.general_comments": "NA", + "categorized_for_analysis.region_definition_vmpfc": "atlas HOA", + "categorized_for_analysis.region_definition_striatum": "atlas HOA, neurosynth", + "categorized_for_analysis.region_definition_amygdala": "atlas HOA", + "categorized_for_analysis.analysis_SW": "FSL", + "categorized_for_analysis.analysis_SW_with_version": "FSL 5.0.11", + "categorized_for_analysis.smoothing_coef": "5", + "categorized_for_analysis.testing": "parametric", + "categorized_for_analysis.testing_thresh": "p<0.001", + "categorized_for_analysis.correction_method": "GRTFWE cluster", + "categorized_for_analysis.correction_thresh_": "p<0.05", + "derived.n_participants": "104", + "derived.excluded_participants": "018, 030, 088, 100", + "derived.func_fwhm": "5", + "derived.con_fwhm": "" +} \ No newline at end of file diff --git a/tests/test_data/results/team_2T6S/hypo1_unthresh.nii.gz b/tests/test_data/data/results/team_2T6S/hypo1_unthresh.nii.gz similarity index 100% rename from tests/test_data/results/team_2T6S/hypo1_unthresh.nii.gz rename to tests/test_data/data/results/team_2T6S/hypo1_unthresh.nii.gz diff --git a/tests/test_data/results/team_2T6S/hypo2_unthresh.nii.gz b/tests/test_data/data/results/team_2T6S/hypo2_unthresh.nii.gz similarity index 100% rename from tests/test_data/results/team_2T6S/hypo2_unthresh.nii.gz rename to tests/test_data/data/results/team_2T6S/hypo2_unthresh.nii.gz diff --git a/tests/test_data/results/team_2T6S/hypo3_unthresh.nii.gz b/tests/test_data/data/results/team_2T6S/hypo3_unthresh.nii.gz similarity index 100% rename from tests/test_data/results/team_2T6S/hypo3_unthresh.nii.gz rename to tests/test_data/data/results/team_2T6S/hypo3_unthresh.nii.gz diff --git a/tests/test_data/results/team_2T6S/hypo4_unthresh.nii.gz b/tests/test_data/data/results/team_2T6S/hypo4_unthresh.nii.gz similarity index 100% rename from tests/test_data/results/team_2T6S/hypo4_unthresh.nii.gz rename to tests/test_data/data/results/team_2T6S/hypo4_unthresh.nii.gz diff --git a/tests/test_data/results/team_2T6S/hypo5_unthresh.nii.gz b/tests/test_data/data/results/team_2T6S/hypo5_unthresh.nii.gz similarity index 100% rename from tests/test_data/results/team_2T6S/hypo5_unthresh.nii.gz rename to tests/test_data/data/results/team_2T6S/hypo5_unthresh.nii.gz diff --git a/tests/test_data/results/team_2T6S/hypo6_unthresh.nii.gz b/tests/test_data/data/results/team_2T6S/hypo6_unthresh.nii.gz similarity index 100% rename from tests/test_data/results/team_2T6S/hypo6_unthresh.nii.gz rename to tests/test_data/data/results/team_2T6S/hypo6_unthresh.nii.gz diff --git a/tests/test_data/results/team_2T6S/hypo7_unthresh.nii.gz b/tests/test_data/data/results/team_2T6S/hypo7_unthresh.nii.gz similarity index 100% rename from tests/test_data/results/team_2T6S/hypo7_unthresh.nii.gz rename to tests/test_data/data/results/team_2T6S/hypo7_unthresh.nii.gz diff --git a/tests/test_data/results/team_2T6S/hypo8_unthresh.nii.gz b/tests/test_data/data/results/team_2T6S/hypo8_unthresh.nii.gz similarity index 100% rename from tests/test_data/results/team_2T6S/hypo8_unthresh.nii.gz rename to tests/test_data/data/results/team_2T6S/hypo8_unthresh.nii.gz diff --git a/tests/test_data/results/team_2T6S/hypo9_unthresh.nii.gz b/tests/test_data/data/results/team_2T6S/hypo9_unthresh.nii.gz similarity index 100% rename from tests/test_data/results/team_2T6S/hypo9_unthresh.nii.gz rename to tests/test_data/data/results/team_2T6S/hypo9_unthresh.nii.gz