From 17ced3107b4bfe0300268ec7cdacb97f2e7282c7 Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Fri, 31 Mar 2023 17:13:15 -0400 Subject: [PATCH 01/43] Prepare for new tests. --- .circleci/config.yml | 313 ++++++++++++++++-- .circleci/get_data.py | 10 + aslprep/tests/conftest.py | 8 +- ...xpected_outputs_examples_pasl_multipld.txt | 47 +++ ...ected_outputs_examples_pcasl_multipld.txt} | 0 ...ected_outputs_examples_pcasl_singlepld.txt | 46 +++ .../tests/data/expected_outputs_test_001.txt | 46 +++ ...1383.txt => expected_outputs_test_002.txt} | 0 ...6748.txt => expected_outputs_test_003.txt} | 0 aslprep/tests/test_cli.py | 193 +++++++++-- aslprep/tests/utils.py | 43 +++ 11 files changed, 654 insertions(+), 52 deletions(-) create mode 100644 .circleci/get_data.py create mode 100644 aslprep/tests/data/expected_outputs_examples_pasl_multipld.txt rename aslprep/tests/data/{test_outputs_sub01.txt => expected_outputs_examples_pcasl_multipld.txt} (100%) create mode 100644 aslprep/tests/data/expected_outputs_examples_pcasl_singlepld.txt create mode 100644 aslprep/tests/data/expected_outputs_test_001.txt rename aslprep/tests/data/{test_outputs_sub10R01383.txt => expected_outputs_test_002.txt} (100%) rename aslprep/tests/data/{test_outputs_subA00086748.txt => expected_outputs_test_003.txt} (100%) diff --git a/.circleci/config.yml b/.circleci/config.yml index e7303e31e..3698ccf85 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -33,24 +33,103 @@ jobs: - checkout - run: *runinstall - download_data: + download_data_examples_pcasl_singlepld: <<: *dockersetup steps: - checkout - restore_cache: - key: data-v4 + key: examples_pcasl_singlepld-v1 - run: name: Get test data and smriprep from box command: | cd /src/aslprep/.circleci - source get_data.sh - get_bids_data $PWD downsampled + python get_data.py ${PWD}/data downsampled - save_cache: - key: data-v4 + key: examples_pcasl_singlepld-v1 + paths: + - /src/aslprep/.circleci/data + + download_data_examples_pcasl_multipld: + <<: *dockersetup + steps: + - checkout + - restore_cache: + key: examples_pcasl_multipld-v1 + - run: + name: Get test data and smriprep from box + command: | + cd /src/aslprep/.circleci + python get_data.py ${PWD}/data downsampled + - save_cache: + key: examples_pcasl_multipld-v1 + paths: + - /src/aslprep/.circleci/data + + download_data_examples_pasl_multipld: + <<: *dockersetup + steps: + - checkout + - restore_cache: + key: examples_pasl_multipld-v1 + - run: + name: Get test data and smriprep from box + command: | + cd /src/aslprep/.circleci + python get_data.py ${PWD}/data downsampled + - save_cache: + key: examples_pasl_multipld-v1 + paths: + - /src/aslprep/.circleci/data + + download_data_test_001: + <<: *dockersetup + steps: + - checkout + - restore_cache: + key: test_001-v1 + - run: + name: Get test data and smriprep from box + command: | + cd /src/aslprep/.circleci + python get_data.py ${PWD}/data downsampled + - save_cache: + key: test_001-v1 + paths: + - /src/aslprep/.circleci/data + + download_data_test_002: + <<: *dockersetup + steps: + - checkout + - restore_cache: + key: test_002-v1 + - run: + name: Get test data and smriprep from box + command: | + cd /src/aslprep/.circleci + python get_data.py ${PWD}/data downsampled + - save_cache: + key: test_002-v1 + paths: + - /src/aslprep/.circleci/data + + download_data_test_003: + <<: *dockersetup + steps: + - checkout + - restore_cache: + key: test_003-v1 + - run: + name: Get test data and smriprep from box + command: | + cd /src/aslprep/.circleci + python get_data.py ${PWD}/data downsampled + - save_cache: + key: test_003-v1 paths: - /src/aslprep/.circleci/data - aslprep_sub01: + aslprep_examples_pcasl_singlepld: <<: *dockersetup steps: - checkout @@ -58,28 +137,28 @@ jobs: name: Check whether build should be skipped command: | cd /src/aslprep - if [[ "$( git log --format=oneline -n 1 $CIRCLE_SHA1 | grep -i -E '\[skip[ _]?aslprep_sub01\]' )" != "" ]]; then - echo "Skipping aslprep_sub01 build" + if [[ "$( git log --format=oneline -n 1 $CIRCLE_SHA1 | grep -i -E '\[skip[ _]?examples_pcasl_singlepld\]' )" != "" ]]; then + echo "Skipping examples_pcasl_singlepld build" circleci step halt fi - restore_cache: - key: data-v4 + key: examples_pcasl_singlepld-v1 - run: *runinstall - run: - name: Run full aslprep on aslprep_sub01 bold + name: Run full aslprep on examples_pcasl_singlepld dataset no_output_timeout: 5h command: | - pytest -rP -o log_cli=true -m "sub01" --cov-append --cov-report term-missing --cov=aslprep --data_dir=/src/aslprep/.circleci/data --output_dir=/src/aslprep/.circleci/out --working_dir=/src/aslprep/.circleci/work aslprep + pytest -rP -o log_cli=true -m "examples_pcasl_singlepld" --cov-append --cov-report term-missing --cov=aslprep --data_dir=/src/aslprep/.circleci/data --output_dir=/src/aslprep/.circleci/out --working_dir=/src/aslprep/.circleci/work aslprep mkdir /src/coverage - mv /src/aslprep/.coverage /src/coverage/.coverage.sub01 + mv /src/aslprep/.coverage /src/coverage/.coverage.examples_pcasl_singlepld - store_artifacts: path: /src/aslprep/.circleci/out - persist_to_workspace: root: /src/coverage paths: - - .coverage.sub01 + - .coverage.examples_pcasl_singlepld - aslprep_subA00086748: + aslprep_examples_pcasl_multipld: <<: *dockersetup steps: - checkout @@ -87,26 +166,142 @@ jobs: name: Check whether build should be skipped command: | cd /src/aslprep - if [[ "$( git log --format=oneline -n 1 $CIRCLE_SHA1 | grep -i -E '\[skip[ _]?aslprep_sub01\]' )" != "" ]]; then - echo "Skipping aslprep_sub01 build" + if [[ "$( git log --format=oneline -n 1 $CIRCLE_SHA1 | grep -i -E '\[skip[ _]?examples_pcasl_multipld\]' )" != "" ]]; then + echo "Skipping examples_pcasl_multipld build" circleci step halt fi - restore_cache: - key: data-v4 + key: examples_pcasl_multipld-v1 + - run: *runinstall + - run: + name: Run full aslprep on examples_pcasl_multipld dataset + no_output_timeout: 5h + command: | + pytest -rP -o log_cli=true -m "examples_pcasl_multipld" --cov-append --cov-report term-missing --cov=aslprep --data_dir=/src/aslprep/.circleci/data --output_dir=/src/aslprep/.circleci/out --working_dir=/src/aslprep/.circleci/work aslprep + mkdir /src/coverage + mv /src/aslprep/.coverage /src/coverage/.coverage.examples_pcasl_multipld + - store_artifacts: + path: /src/aslprep/.circleci/out + - persist_to_workspace: + root: /src/coverage + paths: + - .coverage.examples_pcasl_multipld + + aslprep_examples_pasl_multipld: + <<: *dockersetup + steps: + - checkout + - run: + name: Check whether build should be skipped + command: | + cd /src/aslprep + if [[ "$( git log --format=oneline -n 1 $CIRCLE_SHA1 | grep -i -E '\[skip[ _]?examples_pasl_multipld\]' )" != "" ]]; then + echo "Skipping examples_pasl_multipld build" + circleci step halt + fi + - restore_cache: + key: examples_pasl_multipld-v1 + - run: *runinstall + - run: + name: Run full aslprep on examples_pasl_multipld dataset + no_output_timeout: 5h + command: | + pytest -rP -o log_cli=true -m "examples_pasl_multipld" --cov-append --cov-report term-missing --cov=aslprep --data_dir=/src/aslprep/.circleci/data --output_dir=/src/aslprep/.circleci/out --working_dir=/src/aslprep/.circleci/work aslprep + mkdir /src/coverage + mv /src/aslprep/.coverage /src/coverage/.coverage.examples_pasl_multipld + - store_artifacts: + path: /src/aslprep/.circleci/out + - persist_to_workspace: + root: /src/coverage + paths: + - .coverage.examples_pasl_multipld + + aslprep_test_001: + <<: *dockersetup + steps: + - checkout + - run: + name: Check whether build should be skipped + command: | + cd /src/aslprep + if [[ "$( git log --format=oneline -n 1 $CIRCLE_SHA1 | grep -i -E '\[skip[ _]?test_001\]' )" != "" ]]; then + echo "Skipping test_001 build" + circleci step halt + fi + - restore_cache: + key: test_001-v1 + - run: *runinstall + - run: + name: Run full aslprep on test_001 dataset + no_output_timeout: 5h + command: | + pytest -rP -o log_cli=true -m "test_001" --cov-append --cov-report term-missing --cov=aslprep --data_dir=/src/aslprep/.circleci/data --output_dir=/src/aslprep/.circleci/out --working_dir=/src/aslprep/.circleci/work aslprep + mkdir /src/coverage + mv /src/aslprep/.coverage /src/coverage/.coverage.test_001 + - store_artifacts: + path: /src/aslprep/.circleci/out + - persist_to_workspace: + root: /src/coverage + paths: + - .coverage.test_001 + + aslprep_test_002: + <<: *dockersetup + steps: + - checkout + - run: + name: Check whether build should be skipped + command: | + cd /src/aslprep + if [[ "$( git log --format=oneline -n 1 $CIRCLE_SHA1 | grep -i -E '\[skip[ _]?test_002\]' )" != "" ]]; then + echo "Skipping test_002 build" + circleci step halt + fi + - restore_cache: + key: test_002-v1 + - run: *runinstall + - run: + name: Run full aslprep on test_002 dataset + no_output_timeout: 5h + command: | + pytest -rP -o log_cli=true -m "test_002" --cov-append --cov-report term-missing --cov=aslprep --data_dir=/src/aslprep/.circleci/data --output_dir=/src/aslprep/.circleci/out --working_dir=/src/aslprep/.circleci/work aslprep + mkdir /src/coverage + mv /src/aslprep/.coverage /src/coverage/.coverage.test_002 + - store_artifacts: + path: /src/aslprep/.circleci/out + - persist_to_workspace: + root: /src/coverage + paths: + - .coverage.test_002 + + aslprep_test_003: + <<: *dockersetup + steps: + - checkout + - run: + name: Check whether build should be skipped + command: | + cd /src/aslprep + if [[ "$( git log --format=oneline -n 1 $CIRCLE_SHA1 | grep -i -E '\[skip[ _]?aslprep_test_003\]' )" != "" ]]; then + echo "Skipping aslprep_test_003 build" + circleci step halt + fi + - restore_cache: + key: test_003-v1 - run: *runinstall - run: - name: Run full aslprep on aslprep_subA00086748 bold + name: Run full aslprep on test_003 dataset no_output_timeout: 5h command: | - pytest -rP -o log_cli=true -m "subA00086748" --cov-append --cov-report term-missing --cov=aslprep --data_dir=/src/aslprep/.circleci/data --output_dir=/src/aslprep/.circleci/out --working_dir=/src/aslprep/.circleci/work aslprep + pytest -rP -o log_cli=true -m "test_003" --cov-append --cov-report term-missing --cov=aslprep --data_dir=/src/aslprep/.circleci/data --output_dir=/src/aslprep/.circleci/out --working_dir=/src/aslprep/.circleci/work aslprep mkdir /src/coverage - mv /src/aslprep/.coverage /src/coverage/.coverage.subA00086748 + mv /src/aslprep/.coverage /src/coverage/.coverage.test_003 - store_artifacts: path: /src/aslprep/.circleci/out - persist_to_workspace: root: /src/coverage paths: - - .coverage.subA00086748 + - .coverage.test_003 pytests: <<: *dockersetup @@ -229,9 +424,57 @@ workflows: tags: only: /.*/ - - aslprep_sub01: + - aslprep_examples_pcasl_singlepld: + requires: + - download_data_examples_pcasl_singlepld + - build + filters: + branches: + ignore: + - /docs?\/.*/ + - /tests?\/.*/ + tags: + only: /.*/ + + - aslprep_examples_pcasl_multipld: + requires: + - download_data_examples_pcasl_multipld + - build + filters: + branches: + ignore: + - /docs?\/.*/ + - /tests?\/.*/ + tags: + only: /.*/ + + - aslprep_examples_pasl_multipld: + requires: + - download_data_examples_pasl_multipld + - build + filters: + branches: + ignore: + - /docs?\/.*/ + - /tests?\/.*/ + tags: + only: /.*/ + + - aslprep_test_001: + requires: + - download_data_test_001 + - build + filters: + branches: + ignore: + - /docs?\/.*/ + - /tests?\/.*/ + tags: + only: /.*/ + + - aslprep_test_002: requires: - - download_data + - download_data_test_002 - build filters: branches: @@ -241,9 +484,9 @@ workflows: tags: only: /.*/ - - aslprep_subA00086748: + - aslprep_test_003: requires: - - download_data + - download_data_test_003 - build filters: branches: @@ -255,7 +498,9 @@ workflows: - pytests: requires: - - download_data + - download_data_test_001 + - download_data_test_002 + - download_data_test_003 - build filters: branches: @@ -267,8 +512,12 @@ workflows: - merge_coverage: requires: - - aslprep_sub01 - - aslprep_subA00086748 + - aslprep_examples_pcasl_singlepld + - aslprep_examples_pcasl_multipld + - aslprep_examples_pasl_multipld + - aslprep_test_001 + - aslprep_test_002 + - aslprep_test_003 - pytests filters: branches: @@ -281,8 +530,12 @@ workflows: - deployable: requires: - build - - aslprep_sub01 - - aslprep_subA00086748 + - aslprep_examples_pcasl_singlepld + - aslprep_examples_pcasl_multipld + - aslprep_examples_pasl_multipld + - aslprep_test_001 + - aslprep_test_002 + - aslprep_test_003 filters: branches: only: main diff --git a/.circleci/get_data.py b/.circleci/get_data.py new file mode 100644 index 000000000..eff1d056d --- /dev/null +++ b/.circleci/get_data.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python3 +"""Download test data.""" +import sys + +from aslprep.tests.utils import download_test_data + +if __name__ == "__main__": + data_dir = sys.argv[1] + dset = sys.argv[2] + download_test_data(data_dir, dset) diff --git a/aslprep/tests/conftest.py b/aslprep/tests/conftest.py index 4f8193548..eeaca9697 100644 --- a/aslprep/tests/conftest.py +++ b/aslprep/tests/conftest.py @@ -39,8 +39,12 @@ def output_dir(request): def datasets(data_dir): """Locate downloaded datasets.""" return { - "dset": os.path.join(data_dir, "dset"), - "smriprep": os.path.join(data_dir, "dset/derivatives/smriprep"), + "examples_pasl_multipld": os.path.join(data_dir, "examples_pasl_multipld"), + "examples_pcasl_multipld": os.path.join(data_dir, "examples_pcasl_multipld"), + "examples_pcasl_singlepld": os.path.join(data_dir, "examples_pcasl_singlepld"), + "test_001": os.path.join(data_dir, "test_001"), + "test_002": os.path.join(data_dir, "test_002"), + "test_003": os.path.join(data_dir, "test_003"), } diff --git a/aslprep/tests/data/expected_outputs_examples_pasl_multipld.txt b/aslprep/tests/data/expected_outputs_examples_pasl_multipld.txt new file mode 100644 index 000000000..58de5f9f8 --- /dev/null +++ b/aslprep/tests/data/expected_outputs_examples_pasl_multipld.txt @@ -0,0 +1,47 @@ +aslprep/logs +aslprep/sub-01 +aslprep/sub-01/ses-BAS1 +aslprep/sub-01/ses-BAS1/perf +aslprep/sub-01/ses-BAS1/perf/sub-01_ses-BAS1_aslref.nii.gz +aslprep/sub-01/ses-BAS1/perf/sub-01_ses-BAS1_cbf.nii.gz +aslprep/sub-01/ses-BAS1/perf/sub-01_ses-BAS1_atlas-HarvardOxford_desc-mean_basil.csv +aslprep/sub-01/ses-BAS1/perf/sub-01_ses-BAS1_atlas-HarvardOxford_desc-mean_cbf.csv +aslprep/sub-01/ses-BAS1/perf/sub-01_ses-BAS1_atlas-HarvardOxford_desc-mean_pvc.csv +aslprep/sub-01/ses-BAS1/perf/sub-01_ses-BAS1_atlas-HarvardOxford_desc-mean_score.csv +aslprep/sub-01/ses-BAS1/perf/sub-01_ses-BAS1_atlas-HarvardOxford_desc-mean_scrub.csv +aslprep/sub-01/ses-BAS1/perf/sub-01_ses-BAS1_desc-basil_cbf.nii.gz +aslprep/sub-01/ses-BAS1/perf/sub-01_ses-BAS1_desc-bat_cbf.nii.gz +aslprep/sub-01/ses-BAS1/perf/sub-01_ses-BAS1_desc-brain_mask.json +aslprep/sub-01/ses-BAS1/perf/sub-01_ses-BAS1_desc-brain_mask.nii.gz +aslprep/sub-01/ses-BAS1/perf/sub-01_ses-BAS1_desc-confounds_regressors.tsv +aslprep/sub-01/ses-BAS1/perf/sub-01_ses-BAS1_desc-preproc_asl.json +aslprep/sub-01/ses-BAS1/perf/sub-01_ses-BAS1_desc-preproc_asl.nii.gz +aslprep/sub-01/ses-BAS1/perf/sub-01_ses-BAS1_desc-pvGM_cbf.nii.gz +aslprep/sub-01/ses-BAS1/perf/sub-01_ses-BAS1_desc-pvWM_cbf.nii.gz +aslprep/sub-01/ses-BAS1/perf/sub-01_ses-BAS1_desc-qualitycontrol_cbf.csv +aslprep/sub-01/ses-BAS1/perf/sub-01_ses-BAS1_atlas-schaefer200x17_desc-mean_basil.csv +aslprep/sub-01/ses-BAS1/perf/sub-01_ses-BAS1_atlas-schaefer200x17_desc-mean_cbf.csv +aslprep/sub-01/ses-BAS1/perf/sub-01_ses-BAS1_atlas-schaefer200x17_desc-mean_pvc.csv +aslprep/sub-01/ses-BAS1/perf/sub-01_ses-BAS1_atlas-schaefer200x17_desc-mean_score.csv +aslprep/sub-01/ses-BAS1/perf/sub-01_ses-BAS1_atlas-schaefer200x17_desc-mean_scrub.csv +aslprep/sub-01/ses-BAS1/perf/sub-01_ses-BAS1_atlas-schaefer200x7_desc-mean_basil.csv +aslprep/sub-01/ses-BAS1/perf/sub-01_ses-BAS1_atlas-schaefer200x7_desc-mean_cbf.csv +aslprep/sub-01/ses-BAS1/perf/sub-01_ses-BAS1_atlas-schaefer200x7_desc-mean_pvc.csv +aslprep/sub-01/ses-BAS1/perf/sub-01_ses-BAS1_atlas-schaefer200x7_desc-mean_score.csv +aslprep/sub-01/ses-BAS1/perf/sub-01_ses-BAS1_atlas-schaefer200x7_desc-mean_scrub.csv +aslprep/sub-01/ses-BAS1/perf/sub-01_ses-BAS1_atlas-schaefer400x17_desc-mean_basil.csv +aslprep/sub-01/ses-BAS1/perf/sub-01_ses-BAS1_atlas-schaefer400x17_desc-mean_cbf.csv +aslprep/sub-01/ses-BAS1/perf/sub-01_ses-BAS1_atlas-schaefer400x17_desc-mean_pvc.csv +aslprep/sub-01/ses-BAS1/perf/sub-01_ses-BAS1_atlas-schaefer400x17_desc-mean_score.csv +aslprep/sub-01/ses-BAS1/perf/sub-01_ses-BAS1_atlas-schaefer400x17_desc-mean_scrub.csv +aslprep/sub-01/ses-BAS1/perf/sub-01_ses-BAS1_atlas-schaefer400x7_desc-mean_basil.csv +aslprep/sub-01/ses-BAS1/perf/sub-01_ses-BAS1_atlas-schaefer400x7_desc-mean_cbf.csv +aslprep/sub-01/ses-BAS1/perf/sub-01_ses-BAS1_atlas-schaefer400x7_desc-mean_pvc.csv +aslprep/sub-01/ses-BAS1/perf/sub-01_ses-BAS1_atlas-schaefer400x7_desc-mean_score.csv +aslprep/sub-01/ses-BAS1/perf/sub-01_ses-BAS1_atlas-schaefer400x7_desc-mean_scrub.csv +aslprep/sub-01/ses-BAS1/perf/sub-01_ses-BAS1_desc-score_cbf.nii.gz +aslprep/sub-01/ses-BAS1/perf/sub-01_ses-BAS1_desc-meanScore_cbf.nii.gz +aslprep/sub-01/ses-BAS1/perf/sub-01_ses-BAS1_desc-scrub_cbf.nii.gz +aslprep/sub-01/ses-BAS1/perf/sub-01_ses-BAS1_from-T1w_to-scanner_mode-image_xfm.txt +aslprep/sub-01/ses-BAS1/perf/sub-01_ses-BAS1_from-scanner_to-T1w_mode-image_xfm.txt +aslprep/sub-01/ses-BAS1/perf/sub-01_ses-BAS1_desc-mean_cbf.nii.gz diff --git a/aslprep/tests/data/test_outputs_sub01.txt b/aslprep/tests/data/expected_outputs_examples_pcasl_multipld.txt similarity index 100% rename from aslprep/tests/data/test_outputs_sub01.txt rename to aslprep/tests/data/expected_outputs_examples_pcasl_multipld.txt diff --git a/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld.txt b/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld.txt new file mode 100644 index 000000000..06fa14369 --- /dev/null +++ b/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld.txt @@ -0,0 +1,46 @@ +aslprep/logs +aslprep/sub-103 +aslprep/sub-103/perf +aslprep/sub-103/perf/sub-103_aslref.nii.gz +aslprep/sub-103/perf/sub-103_cbf.nii.gz +aslprep/sub-103/perf/sub-103_atlas-HarvardOxford_desc-mean_basil.csv +aslprep/sub-103/perf/sub-103_atlas-HarvardOxford_desc-mean_cbf.csv +aslprep/sub-103/perf/sub-103_atlas-HarvardOxford_desc-mean_pvc.csv +aslprep/sub-103/perf/sub-103_atlas-HarvardOxford_desc-mean_score.csv +aslprep/sub-103/perf/sub-103_atlas-HarvardOxford_desc-mean_scrub.csv +aslprep/sub-103/perf/sub-103_desc-basil_cbf.nii.gz +aslprep/sub-103/perf/sub-103_desc-bat_cbf.nii.gz +aslprep/sub-103/perf/sub-103_desc-brain_mask.json +aslprep/sub-103/perf/sub-103_desc-brain_mask.nii.gz +aslprep/sub-103/perf/sub-103_desc-confounds_regressors.tsv +aslprep/sub-103/perf/sub-103_desc-preproc_asl.json +aslprep/sub-103/perf/sub-103_desc-preproc_asl.nii.gz +aslprep/sub-103/perf/sub-103_desc-pvGM_cbf.nii.gz +aslprep/sub-103/perf/sub-103_desc-pvWM_cbf.nii.gz +aslprep/sub-103/perf/sub-103_desc-qualitycontrol_cbf.csv +aslprep/sub-103/perf/sub-103_atlas-schaefer200x17_desc-mean_basil.csv +aslprep/sub-103/perf/sub-103_atlas-schaefer200x17_desc-mean_cbf.csv +aslprep/sub-103/perf/sub-103_atlas-schaefer200x17_desc-mean_pvc.csv +aslprep/sub-103/perf/sub-103_atlas-schaefer200x17_desc-mean_score.csv +aslprep/sub-103/perf/sub-103_atlas-schaefer200x17_desc-mean_scrub.csv +aslprep/sub-103/perf/sub-103_atlas-schaefer200x7_desc-mean_basil.csv +aslprep/sub-103/perf/sub-103_atlas-schaefer200x7_desc-mean_cbf.csv +aslprep/sub-103/perf/sub-103_atlas-schaefer200x7_desc-mean_pvc.csv +aslprep/sub-103/perf/sub-103_atlas-schaefer200x7_desc-mean_score.csv +aslprep/sub-103/perf/sub-103_atlas-schaefer200x7_desc-mean_scrub.csv +aslprep/sub-103/perf/sub-103_atlas-schaefer400x17_desc-mean_basil.csv +aslprep/sub-103/perf/sub-103_atlas-schaefer400x17_desc-mean_cbf.csv +aslprep/sub-103/perf/sub-103_atlas-schaefer400x17_desc-mean_pvc.csv +aslprep/sub-103/perf/sub-103_atlas-schaefer400x17_desc-mean_score.csv +aslprep/sub-103/perf/sub-103_atlas-schaefer400x17_desc-mean_scrub.csv +aslprep/sub-103/perf/sub-103_atlas-schaefer400x7_desc-mean_basil.csv +aslprep/sub-103/perf/sub-103_atlas-schaefer400x7_desc-mean_cbf.csv +aslprep/sub-103/perf/sub-103_atlas-schaefer400x7_desc-mean_pvc.csv +aslprep/sub-103/perf/sub-103_atlas-schaefer400x7_desc-mean_score.csv +aslprep/sub-103/perf/sub-103_atlas-schaefer400x7_desc-mean_scrub.csv +aslprep/sub-103/perf/sub-103_desc-score_cbf.nii.gz +aslprep/sub-103/perf/sub-103_desc-meanScore_cbf.nii.gz +aslprep/sub-103/perf/sub-103_desc-scrub_cbf.nii.gz +aslprep/sub-103/perf/sub-103_from-T1w_to-scanner_mode-image_xfm.txt +aslprep/sub-103/perf/sub-103_from-scanner_to-T1w_mode-image_xfm.txt +aslprep/sub-103/perf/sub-103_desc-mean_cbf.nii.gz diff --git a/aslprep/tests/data/expected_outputs_test_001.txt b/aslprep/tests/data/expected_outputs_test_001.txt new file mode 100644 index 000000000..a8634a258 --- /dev/null +++ b/aslprep/tests/data/expected_outputs_test_001.txt @@ -0,0 +1,46 @@ +aslprep/logs +aslprep/sub-01 +aslprep/sub-01/perf +aslprep/sub-01/perf/sub-01_aslref.nii.gz +aslprep/sub-01/perf/sub-01_cbf.nii.gz +aslprep/sub-01/perf/sub-01_atlas-HarvardOxford_desc-mean_basil.csv +aslprep/sub-01/perf/sub-01_atlas-HarvardOxford_desc-mean_cbf.csv +aslprep/sub-01/perf/sub-01_atlas-HarvardOxford_desc-mean_pvc.csv +aslprep/sub-01/perf/sub-01_atlas-HarvardOxford_desc-mean_score.csv +aslprep/sub-01/perf/sub-01_atlas-HarvardOxford_desc-mean_scrub.csv +aslprep/sub-01/perf/sub-01_desc-basil_cbf.nii.gz +aslprep/sub-01/perf/sub-01_desc-bat_cbf.nii.gz +aslprep/sub-01/perf/sub-01_desc-brain_mask.json +aslprep/sub-01/perf/sub-01_desc-brain_mask.nii.gz +aslprep/sub-01/perf/sub-01_desc-confounds_regressors.tsv +aslprep/sub-01/perf/sub-01_desc-preproc_asl.json +aslprep/sub-01/perf/sub-01_desc-preproc_asl.nii.gz +aslprep/sub-01/perf/sub-01_desc-pvGM_cbf.nii.gz +aslprep/sub-01/perf/sub-01_desc-pvWM_cbf.nii.gz +aslprep/sub-01/perf/sub-01_desc-qualitycontrol_cbf.csv +aslprep/sub-01/perf/sub-01_atlas-schaefer200x17_desc-mean_basil.csv +aslprep/sub-01/perf/sub-01_atlas-schaefer200x17_desc-mean_cbf.csv +aslprep/sub-01/perf/sub-01_atlas-schaefer200x17_desc-mean_pvc.csv +aslprep/sub-01/perf/sub-01_atlas-schaefer200x17_desc-mean_score.csv +aslprep/sub-01/perf/sub-01_atlas-schaefer200x17_desc-mean_scrub.csv +aslprep/sub-01/perf/sub-01_atlas-schaefer200x7_desc-mean_basil.csv +aslprep/sub-01/perf/sub-01_atlas-schaefer200x7_desc-mean_cbf.csv +aslprep/sub-01/perf/sub-01_atlas-schaefer200x7_desc-mean_pvc.csv +aslprep/sub-01/perf/sub-01_atlas-schaefer200x7_desc-mean_score.csv +aslprep/sub-01/perf/sub-01_atlas-schaefer200x7_desc-mean_scrub.csv +aslprep/sub-01/perf/sub-01_atlas-schaefer400x17_desc-mean_basil.csv +aslprep/sub-01/perf/sub-01_atlas-schaefer400x17_desc-mean_cbf.csv +aslprep/sub-01/perf/sub-01_atlas-schaefer400x17_desc-mean_pvc.csv +aslprep/sub-01/perf/sub-01_atlas-schaefer400x17_desc-mean_score.csv +aslprep/sub-01/perf/sub-01_atlas-schaefer400x17_desc-mean_scrub.csv +aslprep/sub-01/perf/sub-01_atlas-schaefer400x7_desc-mean_basil.csv +aslprep/sub-01/perf/sub-01_atlas-schaefer400x7_desc-mean_cbf.csv +aslprep/sub-01/perf/sub-01_atlas-schaefer400x7_desc-mean_pvc.csv +aslprep/sub-01/perf/sub-01_atlas-schaefer400x7_desc-mean_score.csv +aslprep/sub-01/perf/sub-01_atlas-schaefer400x7_desc-mean_scrub.csv +aslprep/sub-01/perf/sub-01_desc-score_cbf.nii.gz +aslprep/sub-01/perf/sub-01_desc-meanScore_cbf.nii.gz +aslprep/sub-01/perf/sub-01_desc-scrub_cbf.nii.gz +aslprep/sub-01/perf/sub-01_from-T1w_to-scanner_mode-image_xfm.txt +aslprep/sub-01/perf/sub-01_from-scanner_to-T1w_mode-image_xfm.txt +aslprep/sub-01/perf/sub-01_desc-mean_cbf.nii.gz diff --git a/aslprep/tests/data/test_outputs_sub10R01383.txt b/aslprep/tests/data/expected_outputs_test_002.txt similarity index 100% rename from aslprep/tests/data/test_outputs_sub10R01383.txt rename to aslprep/tests/data/expected_outputs_test_002.txt diff --git a/aslprep/tests/data/test_outputs_subA00086748.txt b/aslprep/tests/data/expected_outputs_test_003.txt similarity index 100% rename from aslprep/tests/data/test_outputs_subA00086748.txt rename to aslprep/tests/data/expected_outputs_test_003.txt diff --git a/aslprep/tests/test_cli.py b/aslprep/tests/test_cli.py index 4719661ca..763e96f16 100644 --- a/aslprep/tests/test_cli.py +++ b/aslprep/tests/test_cli.py @@ -9,12 +9,12 @@ from aslprep.tests.utils import check_generated_files, get_test_data_path -@pytest.mark.sub01 -def test_sub01(datasets, output_dir, working_dir): +@pytest.mark.examples_pcasl_singlepld +def test_examples_pcasl_singlepld(datasets, output_dir, working_dir): """Run aslprep on sub-01 data.""" from aslprep import config - test_name = "test_sub01" + test_name = "examples_pcasl_singlepld" data_dir = datasets["dset"] smriprep_dir = datasets["smriprep"] @@ -56,16 +56,16 @@ def test_sub01(datasets, output_dir, working_dir): aslprep_wf = retval.get("workflow", None) aslprep_wf.run() - output_list_file = os.path.join(test_data_dir, "test_outputs_sub01.txt") + output_list_file = os.path.join(test_data_dir, "expected_outputs_examples_pcasl_singlepld.txt") check_generated_files(out_dir, output_list_file) -@pytest.mark.subA00086748 -def test_subA00086748(datasets, output_dir, working_dir): # noqa: N802 - """Run aslprep on sub-A00086748.""" +@pytest.mark.examples_pcasl_multipld +def test_examples_pcasl_multipld(datasets, output_dir, working_dir): + """Run aslprep on sub-01 data.""" from aslprep import config - test_name = "test_subA00086748" + test_name = "examples_pcasl_multipld" data_dir = datasets["dset"] smriprep_dir = datasets["smriprep"] @@ -74,13 +74,58 @@ def test_subA00086748(datasets, output_dir, working_dir): # noqa: N802 # Patch the JSON file until I have enough changes to merit completely replacing the current # version of the data. - json_file = os.path.join( + json_file = os.path.join(data_dir, "sub-01", "perf", "sub-01_asl.json") + with open(json_file, "r") as fo: + metadata = json.load(fo) + + metadata["RepetitionTimePreparation"] = metadata["RepetitionTime"] + with open(json_file, "w") as fo: + json.dump(metadata, fo, sort_keys=True, indent=4) + + test_data_dir = get_test_data_path() + + parameters = [ data_dir, - "sub-A00086748", - "ses-BAS1", - "perf", - "sub-A00086748_ses-BAS1_asl.json", - ) + out_dir, + "participant", + "--participant-label=01", + f"-w={work_dir}", + "--nthreads=2", + "--omp-nthreads=2", + "--output-spaces=asl", + "--scorescrub", + "--basil", + "--use-syn-sdc", + f"--anat-derivatives={smriprep_dir}", + ] + parse_args(parameters) + config_file = config.execution.work_dir / f"config-{config.execution.run_uuid}.toml" + config.to_filename(config_file) + + retval = {} + retval = build_workflow(config_file, retval=retval) + aslprep_wf = retval.get("workflow", None) + aslprep_wf.run() + + output_list_file = os.path.join(test_data_dir, "expected_outputs_examples_pcasl_multipld.txt") + check_generated_files(out_dir, output_list_file) + + +@pytest.mark.examples_pasl_multipld +def test_examples_pasl_multipld(datasets, output_dir, working_dir): + """Run aslprep on sub-01 data.""" + from aslprep import config + + test_name = "examples_pasl_multipld" + + data_dir = datasets["dset"] + smriprep_dir = datasets["smriprep"] + out_dir = os.path.join(output_dir, test_name) + work_dir = os.path.join(working_dir, test_name) + + # Patch the JSON file until I have enough changes to merit completely replacing the current + # version of the data. + json_file = os.path.join(data_dir, "sub-01", "perf", "sub-01_asl.json") with open(json_file, "r") as fo: metadata = json.load(fo) @@ -94,7 +139,7 @@ def test_subA00086748(datasets, output_dir, working_dir): # noqa: N802 data_dir, out_dir, "participant", - "--participant-label=A00086748", + "--participant-label=01", f"-w={work_dir}", "--nthreads=2", "--omp-nthreads=2", @@ -113,12 +158,63 @@ def test_subA00086748(datasets, output_dir, working_dir): # noqa: N802 aslprep_wf = retval.get("workflow", None) aslprep_wf.run() - output_list_file = os.path.join(test_data_dir, "test_outputs_subA00086748.txt") + output_list_file = os.path.join(test_data_dir, "expected_outputs_examples_pasl_multipld.txt") check_generated_files(out_dir, output_list_file) -@pytest.mark.sub10R01383 -def test_sub10R01383(datasets, output_dir, working_dir): # noqa: N802 +@pytest.mark.test_001 +def test_test_001(datasets, output_dir, working_dir): + """Run aslprep on sub-01 data.""" + from aslprep import config + + test_name = "test_001" + + data_dir = datasets["dset"] + smriprep_dir = datasets["smriprep"] + out_dir = os.path.join(output_dir, test_name) + work_dir = os.path.join(working_dir, test_name) + + # Patch the JSON file until I have enough changes to merit completely replacing the current + # version of the data. + json_file = os.path.join(data_dir, "sub-01", "perf", "sub-01_asl.json") + with open(json_file, "r") as fo: + metadata = json.load(fo) + + metadata["RepetitionTimePreparation"] = metadata["RepetitionTime"] + with open(json_file, "w") as fo: + json.dump(metadata, fo, sort_keys=True, indent=4) + + test_data_dir = get_test_data_path() + + parameters = [ + data_dir, + out_dir, + "participant", + "--participant-label=01", + f"-w={work_dir}", + "--nthreads=2", + "--omp-nthreads=2", + "--output-spaces=asl", + "--scorescrub", + "--basil", + "--use-syn-sdc", + f"--anat-derivatives={smriprep_dir}", + ] + parse_args(parameters) + config_file = config.execution.work_dir / f"config-{config.execution.run_uuid}.toml" + config.to_filename(config_file) + + retval = {} + retval = build_workflow(config_file, retval=retval) + aslprep_wf = retval.get("workflow", None) + aslprep_wf.run() + + output_list_file = os.path.join(test_data_dir, "expected_outputs_test_001.txt") + check_generated_files(out_dir, output_list_file) + + +@pytest.mark.test_002 +def test_test_002(datasets, output_dir, working_dir): """Run aslprep on sub-10R01383. Currently skipped. @@ -130,7 +226,7 @@ def test_sub10R01383(datasets, output_dir, working_dir): # noqa: N802 """ from aslprep import config - test_name = "test_sub10R01383" + test_name = "test_002" data_dir = datasets["dset"] smriprep_dir = datasets["smriprep"] @@ -161,5 +257,62 @@ def test_sub10R01383(datasets, output_dir, working_dir): # noqa: N802 aslprep_wf = retval.get("workflow", None) aslprep_wf.run() - output_list_file = os.path.join(test_data_dir, "test_outputs_sub10R01383.txt") + output_list_file = os.path.join(test_data_dir, "expected_outputs_test_002.txt") + check_generated_files(out_dir, output_list_file) + + +@pytest.mark.test_003 +def test_test_003(datasets, output_dir, working_dir): + """Run aslprep on sub-A00086748.""" + from aslprep import config + + test_name = "test_003" + + data_dir = datasets["dset"] + smriprep_dir = datasets["smriprep"] + out_dir = os.path.join(output_dir, test_name) + work_dir = os.path.join(working_dir, test_name) + + # Patch the JSON file until I have enough changes to merit completely replacing the current + # version of the data. + json_file = os.path.join( + data_dir, + "sub-A00086748", + "ses-BAS1", + "perf", + "sub-A00086748_ses-BAS1_asl.json", + ) + with open(json_file, "r") as fo: + metadata = json.load(fo) + + metadata["RepetitionTimePreparation"] = metadata["RepetitionTime"] + with open(json_file, "w") as fo: + json.dump(metadata, fo, sort_keys=True, indent=4) + + test_data_dir = get_test_data_path() + + parameters = [ + data_dir, + out_dir, + "participant", + "--participant-label=A00086748", + f"-w={work_dir}", + "--nthreads=2", + "--omp-nthreads=2", + "--output-spaces=asl", + "--scorescrub", + "--basil", + "--use-syn-sdc", + f"--anat-derivatives={smriprep_dir}", + ] + parse_args(parameters) + config_file = config.execution.work_dir / f"config-{config.execution.run_uuid}.toml" + config.to_filename(config_file) + + retval = {} + retval = build_workflow(config_file, retval=retval) + aslprep_wf = retval.get("workflow", None) + aslprep_wf.run() + + output_list_file = os.path.join(test_data_dir, "expected_outputs_test_003.txt") check_generated_files(out_dir, output_list_file) diff --git a/aslprep/tests/utils.py b/aslprep/tests/utils.py index e5f73ee63..795dd052b 100644 --- a/aslprep/tests/utils.py +++ b/aslprep/tests/utils.py @@ -1,14 +1,57 @@ """Utility functions for tests.""" import os import subprocess +import tarfile from contextlib import contextmanager from glob import glob +from gzip import GzipFile +from io import BytesIO import nibabel as nb import numpy as np +import requests from bids.layout import BIDSLayout +def download_test_data(dset, data_dir=None): + """Download test data.""" + URLS = { + "examples_pasl_multipld": ( + "https://upenn.box.com/shared/static/njb5tqs2n53775qumtwc1wyxo5362sp7.tar.gz" + ), + "examples_pcasl_multipld": ( + "https://upenn.box.com/shared/static/pm0ysafvg69jimk1bcm3ewtljiwzk899.tar.gz" + ), + "examples_pcasl_singlepld": ( + "https://upenn.box.com/shared/static/il6cfea6f0wjnmjjvcpg6baw3e7yrwa3.tar.gz" + ), + "test_001": "https://upenn.box.com/shared/static/cudw5yyh3j6jwymmlzdw2nwc6knmxdu9.tar.gz", + "test_002": "https://upenn.box.com/shared/static/wpuvn06zl4v5nwd9o8tysyfs3kg4a2p0.tar.gz", + "test_003": "https://upenn.box.com/shared/static/1c64kn7btb5dodksnn06wer2kfk00px5.tar.gz", + } + if dset not in URLS: + raise ValueError(f"dset ({dset}) must be one of: {', '.join(URLS.keys())}") + + if not data_dir: + data_dir = os.path.join(get_test_data_path(), "test_datasets") + + out_dir = os.path.join(data_dir, dset) + + if os.path.isdir(out_dir): + print( + f"Dataset {dset} already exists. " + "If you need to re-download the data, please delete the folder." + ) + return out_dir + + os.makedirs(out_dir, exist_ok=True) + with requests.get(URLS[dset], stream=True) as req: + with tarfile.open(fileobj=GzipFile(fileobj=BytesIO(req.content))) as t: + t.extractall(out_dir) + + return out_dir + + def get_test_data_path(): """Return the path to test datasets, terminated with separator. From 0b42bca8df3f2d586a922d701d09b25f3ae8411c Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Fri, 31 Mar 2023 17:16:07 -0400 Subject: [PATCH 02/43] Fix. --- .circleci/config.yml | 47 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 3698ccf85..1d4fef350 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -415,7 +415,52 @@ workflows: tags: only: /.*/ - - download_data: + - download_data_examples_pcasl_singlepld: + filters: + branches: + ignore: + - /docs?\/.*/ + - /tests?\/.*/ + tags: + only: /.*/ + + - download_data_examples_pcasl_multipld: + filters: + branches: + ignore: + - /docs?\/.*/ + - /tests?\/.*/ + tags: + only: /.*/ + + - download_data_examples_pasl_multipld: + filters: + branches: + ignore: + - /docs?\/.*/ + - /tests?\/.*/ + tags: + only: /.*/ + + - download_data_test_001: + filters: + branches: + ignore: + - /docs?\/.*/ + - /tests?\/.*/ + tags: + only: /.*/ + + - download_data_test_002: + filters: + branches: + ignore: + - /docs?\/.*/ + - /tests?\/.*/ + tags: + only: /.*/ + + - download_data_test_003: filters: branches: ignore: From 37f849f6932fc719f5534452f81db08162f1d106 Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Fri, 31 Mar 2023 17:25:22 -0400 Subject: [PATCH 03/43] Update config.yml --- .circleci/config.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1d4fef350..c3c0419fa 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -39,6 +39,7 @@ jobs: - checkout - restore_cache: key: examples_pcasl_singlepld-v1 + - run: *runinstall - run: name: Get test data and smriprep from box command: | @@ -55,6 +56,7 @@ jobs: - checkout - restore_cache: key: examples_pcasl_multipld-v1 + - run: *runinstall - run: name: Get test data and smriprep from box command: | @@ -71,6 +73,7 @@ jobs: - checkout - restore_cache: key: examples_pasl_multipld-v1 + - run: *runinstall - run: name: Get test data and smriprep from box command: | @@ -87,6 +90,7 @@ jobs: - checkout - restore_cache: key: test_001-v1 + - run: *runinstall - run: name: Get test data and smriprep from box command: | @@ -103,6 +107,7 @@ jobs: - checkout - restore_cache: key: test_002-v1 + - run: *runinstall - run: name: Get test data and smriprep from box command: | @@ -119,6 +124,7 @@ jobs: - checkout - restore_cache: key: test_003-v1 + - run: *runinstall - run: name: Get test data and smriprep from box command: | From 8416c10ed8a0042a8a9a2691200c9fda84691b65 Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Fri, 31 Mar 2023 17:33:15 -0400 Subject: [PATCH 04/43] Fix again. --- .circleci/get_data.py | 2 +- aslprep/tests/test_cli.py | 101 +++++--------------------------------- 2 files changed, 14 insertions(+), 89 deletions(-) diff --git a/.circleci/get_data.py b/.circleci/get_data.py index eff1d056d..a7dfa6b16 100644 --- a/.circleci/get_data.py +++ b/.circleci/get_data.py @@ -7,4 +7,4 @@ if __name__ == "__main__": data_dir = sys.argv[1] dset = sys.argv[2] - download_test_data(data_dir, dset) + download_test_data(dset, data_dir) diff --git a/aslprep/tests/test_cli.py b/aslprep/tests/test_cli.py index 763e96f16..902e8e327 100644 --- a/aslprep/tests/test_cli.py +++ b/aslprep/tests/test_cli.py @@ -1,5 +1,4 @@ """Command-line interface tests.""" -import json import os import pytest @@ -15,29 +14,16 @@ def test_examples_pcasl_singlepld(datasets, output_dir, working_dir): from aslprep import config test_name = "examples_pcasl_singlepld" - - data_dir = datasets["dset"] - smriprep_dir = datasets["smriprep"] + data_dir = datasets[test_name] out_dir = os.path.join(output_dir, test_name) work_dir = os.path.join(working_dir, test_name) - - # Patch the JSON file until I have enough changes to merit completely replacing the current - # version of the data. - json_file = os.path.join(data_dir, "sub-01", "perf", "sub-01_asl.json") - with open(json_file, "r") as fo: - metadata = json.load(fo) - - metadata["RepetitionTimePreparation"] = metadata["RepetitionTime"] - with open(json_file, "w") as fo: - json.dump(metadata, fo, sort_keys=True, indent=4) - test_data_dir = get_test_data_path() parameters = [ data_dir, out_dir, "participant", - "--participant-label=01", + "--participant-label=103", f"-w={work_dir}", "--nthreads=2", "--omp-nthreads=2", @@ -45,7 +31,7 @@ def test_examples_pcasl_singlepld(datasets, output_dir, working_dir): "--scorescrub", "--basil", "--use-syn-sdc", - f"--anat-derivatives={smriprep_dir}", + f"--anat-derivatives={os.path.join(data_dir, 'derivatives/smriprep')}", ] parse_args(parameters) config_file = config.execution.work_dir / f"config-{config.execution.run_uuid}.toml" @@ -66,22 +52,9 @@ def test_examples_pcasl_multipld(datasets, output_dir, working_dir): from aslprep import config test_name = "examples_pcasl_multipld" - - data_dir = datasets["dset"] - smriprep_dir = datasets["smriprep"] + data_dir = datasets[test_name] out_dir = os.path.join(output_dir, test_name) work_dir = os.path.join(working_dir, test_name) - - # Patch the JSON file until I have enough changes to merit completely replacing the current - # version of the data. - json_file = os.path.join(data_dir, "sub-01", "perf", "sub-01_asl.json") - with open(json_file, "r") as fo: - metadata = json.load(fo) - - metadata["RepetitionTimePreparation"] = metadata["RepetitionTime"] - with open(json_file, "w") as fo: - json.dump(metadata, fo, sort_keys=True, indent=4) - test_data_dir = get_test_data_path() parameters = [ @@ -96,7 +69,7 @@ def test_examples_pcasl_multipld(datasets, output_dir, working_dir): "--scorescrub", "--basil", "--use-syn-sdc", - f"--anat-derivatives={smriprep_dir}", + f"--anat-derivatives={os.path.join(data_dir, 'derivatives/smriprep')}", ] parse_args(parameters) config_file = config.execution.work_dir / f"config-{config.execution.run_uuid}.toml" @@ -117,22 +90,9 @@ def test_examples_pasl_multipld(datasets, output_dir, working_dir): from aslprep import config test_name = "examples_pasl_multipld" - - data_dir = datasets["dset"] - smriprep_dir = datasets["smriprep"] + data_dir = datasets[test_name] out_dir = os.path.join(output_dir, test_name) work_dir = os.path.join(working_dir, test_name) - - # Patch the JSON file until I have enough changes to merit completely replacing the current - # version of the data. - json_file = os.path.join(data_dir, "sub-01", "perf", "sub-01_asl.json") - with open(json_file, "r") as fo: - metadata = json.load(fo) - - metadata["RepetitionTimePreparation"] = metadata["RepetitionTime"] - with open(json_file, "w") as fo: - json.dump(metadata, fo, sort_keys=True, indent=4) - test_data_dir = get_test_data_path() parameters = [ @@ -147,7 +107,7 @@ def test_examples_pasl_multipld(datasets, output_dir, working_dir): "--scorescrub", "--basil", "--use-syn-sdc", - f"--anat-derivatives={smriprep_dir}", + f"--anat-derivatives={os.path.join(data_dir, 'derivatives/smriprep')}", ] parse_args(parameters) config_file = config.execution.work_dir / f"config-{config.execution.run_uuid}.toml" @@ -168,22 +128,9 @@ def test_test_001(datasets, output_dir, working_dir): from aslprep import config test_name = "test_001" - - data_dir = datasets["dset"] - smriprep_dir = datasets["smriprep"] + data_dir = datasets[test_name] out_dir = os.path.join(output_dir, test_name) work_dir = os.path.join(working_dir, test_name) - - # Patch the JSON file until I have enough changes to merit completely replacing the current - # version of the data. - json_file = os.path.join(data_dir, "sub-01", "perf", "sub-01_asl.json") - with open(json_file, "r") as fo: - metadata = json.load(fo) - - metadata["RepetitionTimePreparation"] = metadata["RepetitionTime"] - with open(json_file, "w") as fo: - json.dump(metadata, fo, sort_keys=True, indent=4) - test_data_dir = get_test_data_path() parameters = [ @@ -198,7 +145,7 @@ def test_test_001(datasets, output_dir, working_dir): "--scorescrub", "--basil", "--use-syn-sdc", - f"--anat-derivatives={smriprep_dir}", + f"--anat-derivatives={os.path.join(data_dir, 'derivatives/smriprep')}", ] parse_args(parameters) config_file = config.execution.work_dir / f"config-{config.execution.run_uuid}.toml" @@ -227,12 +174,9 @@ def test_test_002(datasets, output_dir, working_dir): from aslprep import config test_name = "test_002" - - data_dir = datasets["dset"] - smriprep_dir = datasets["smriprep"] + data_dir = datasets[test_name] out_dir = os.path.join(output_dir, test_name) work_dir = os.path.join(working_dir, test_name) - test_data_dir = get_test_data_path() parameters = [ @@ -246,7 +190,7 @@ def test_test_002(datasets, output_dir, working_dir): "--output-spaces=asl", "--basil", "--use-syn-sdc", - f"--anat-derivatives={smriprep_dir}", + f"--anat-derivatives={os.path.join(data_dir, 'derivatives/smriprep')}", ] parse_args(parameters) config_file = config.execution.work_dir / f"config-{config.execution.run_uuid}.toml" @@ -267,28 +211,9 @@ def test_test_003(datasets, output_dir, working_dir): from aslprep import config test_name = "test_003" - - data_dir = datasets["dset"] - smriprep_dir = datasets["smriprep"] + data_dir = datasets[test_name] out_dir = os.path.join(output_dir, test_name) work_dir = os.path.join(working_dir, test_name) - - # Patch the JSON file until I have enough changes to merit completely replacing the current - # version of the data. - json_file = os.path.join( - data_dir, - "sub-A00086748", - "ses-BAS1", - "perf", - "sub-A00086748_ses-BAS1_asl.json", - ) - with open(json_file, "r") as fo: - metadata = json.load(fo) - - metadata["RepetitionTimePreparation"] = metadata["RepetitionTime"] - with open(json_file, "w") as fo: - json.dump(metadata, fo, sort_keys=True, indent=4) - test_data_dir = get_test_data_path() parameters = [ @@ -303,7 +228,7 @@ def test_test_003(datasets, output_dir, working_dir): "--scorescrub", "--basil", "--use-syn-sdc", - f"--anat-derivatives={smriprep_dir}", + f"--anat-derivatives={os.path.join(data_dir, 'derivatives/smriprep')}", ] parse_args(parameters) config_file = config.execution.work_dir / f"config-{config.execution.run_uuid}.toml" From 61f67cc0c4f1b3732750cb3cddee11edaa27cd17 Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Fri, 31 Mar 2023 17:42:42 -0400 Subject: [PATCH 05/43] Update config.yml --- .circleci/config.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index c3c0419fa..6da2eeed2 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -44,7 +44,7 @@ jobs: name: Get test data and smriprep from box command: | cd /src/aslprep/.circleci - python get_data.py ${PWD}/data downsampled + python get_data.py ${PWD}/data examples_pcasl_singlepld - save_cache: key: examples_pcasl_singlepld-v1 paths: @@ -61,7 +61,7 @@ jobs: name: Get test data and smriprep from box command: | cd /src/aslprep/.circleci - python get_data.py ${PWD}/data downsampled + python get_data.py ${PWD}/data examples_pcasl_multipld - save_cache: key: examples_pcasl_multipld-v1 paths: @@ -78,7 +78,7 @@ jobs: name: Get test data and smriprep from box command: | cd /src/aslprep/.circleci - python get_data.py ${PWD}/data downsampled + python get_data.py ${PWD}/data examples_pasl_multipld - save_cache: key: examples_pasl_multipld-v1 paths: @@ -95,7 +95,7 @@ jobs: name: Get test data and smriprep from box command: | cd /src/aslprep/.circleci - python get_data.py ${PWD}/data downsampled + python get_data.py ${PWD}/data test_001 - save_cache: key: test_001-v1 paths: @@ -112,7 +112,7 @@ jobs: name: Get test data and smriprep from box command: | cd /src/aslprep/.circleci - python get_data.py ${PWD}/data downsampled + python get_data.py ${PWD}/data test_002 - save_cache: key: test_002-v1 paths: @@ -129,7 +129,7 @@ jobs: name: Get test data and smriprep from box command: | cd /src/aslprep/.circleci - python get_data.py ${PWD}/data downsampled + python get_data.py ${PWD}/data test_003 - save_cache: key: test_003-v1 paths: From c5f799e155c792925345bcb9cc096a0117073a07 Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Fri, 31 Mar 2023 17:52:07 -0400 Subject: [PATCH 06/43] Update cbf.py --- aslprep/workflows/asl/cbf.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/aslprep/workflows/asl/cbf.py b/aslprep/workflows/asl/cbf.py index 6c8a189d9..6e9c62f5e 100644 --- a/aslprep/workflows/asl/cbf.py +++ b/aslprep/workflows/asl/cbf.py @@ -481,8 +481,10 @@ def _getfiledir(file): return os.path.dirname(file) - collect_cbf = niu.IdentityInterface( - fields=["deltam", "cbf"], + collect_cbf = pe.Node( + niu.IdentityInterface( + fields=["deltam", "cbf"], + ), name="collect_cbf", ) From d6c7d426b62793c4c96e2d06f5627872f7d8481f Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Fri, 31 Mar 2023 18:03:05 -0400 Subject: [PATCH 07/43] Update pyproject.toml --- pyproject.toml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 7ed01f49f..da52d9cd0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,9 +34,12 @@ exclude = ''' ''' [tool.pytest.ini_options] -addopts = '-m "not sub01 and not subA00086748 and not sub10R01383"' +addopts = '-m "not examples_pcasl_singlepld and not examples_pcasl_multipld and not examples_pasl_multipld and not test_001 and not test_002 and not test_003"' markers = [ - "sub01: mark integration test for subject 01", - "subA00086748: mark integration test for subject A00086748", - "sub10R01383: mark integration test for subject 10R01383", + "examples_pcasl_singlepld: mark integration test", + "examples_pcasl_multipld: mark integration test", + "examples_pasl_multipld: mark integration test", + "test_001: mark integration test for subject 01", + "test_002: mark integration test for subject 10R01383", + "test_003: mark integration test for subject A00086748", ] From 26bf7d1d4d654dc396c07c2e53ac90d6ea0dab8c Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Fri, 31 Mar 2023 19:16:45 -0400 Subject: [PATCH 08/43] Try that. --- aslprep/workflows/asl/base.py | 2 +- aslprep/workflows/asl/confounds.py | 2 +- aslprep/workflows/asl/gecbf.py | 2 +- aslprep/workflows/asl/plotting.py | 2 +- aslprep/workflows/asl/stc.py | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/aslprep/workflows/asl/base.py b/aslprep/workflows/asl/base.py index 482f88cf1..7f457e180 100644 --- a/aslprep/workflows/asl/base.py +++ b/aslprep/workflows/asl/base.py @@ -282,7 +282,7 @@ def init_asl_preproc_wf(asl_file): registration_dof=config.workflow.asl2t1w_dof, registration_init=config.workflow.asl2t1w_init, pe_direction=metadata.get("PhaseEncodingDirection"), - tr=metadata.get("RepetitionTime"), + tr=metadata.get("RepetitionTime", metadata["RepetitionTimePreparation"]), ), name="summary", mem_gb=config.DEFAULT_MEMORY_MIN_GB, diff --git a/aslprep/workflows/asl/confounds.py b/aslprep/workflows/asl/confounds.py index e8db3a190..0d53e5ffe 100644 --- a/aslprep/workflows/asl/confounds.py +++ b/aslprep/workflows/asl/confounds.py @@ -246,7 +246,7 @@ def init_carpetplot_wf(mem_gb, metadata, name="asl_carpet_wf"): # Carpetplot and confounds plot conf_plot = pe.Node( ASLSummary( - tr=metadata["RepetitionTime"], + tr=metadata.get("RepetitionTime", metadata["RepetitionTimePreparation"]), confounds_list=[("std_dvars", None, "DVARS"), ("framewise_displacement", "mm", "FD")], ), name="conf_plot", diff --git a/aslprep/workflows/asl/gecbf.py b/aslprep/workflows/asl/gecbf.py index dcf2d348a..285ead65d 100644 --- a/aslprep/workflows/asl/gecbf.py +++ b/aslprep/workflows/asl/gecbf.py @@ -267,7 +267,7 @@ def init_asl_gepreproc_wf(asl_file): registration_init=config.workflow.asl2t1w_init, distortion_correction="No distortion correction", pe_direction=metadata.get("PhaseEncodingDirection"), - tr=metadata.get("RepetitionTime"), + tr=metadata.get("RepetitionTime", metadata["RepetitionTimePreparation"]), ), name="summary", mem_gb=config.DEFAULT_MEMORY_MIN_GB, diff --git a/aslprep/workflows/asl/plotting.py b/aslprep/workflows/asl/plotting.py index 8dd21339e..aa4f3db15 100644 --- a/aslprep/workflows/asl/plotting.py +++ b/aslprep/workflows/asl/plotting.py @@ -86,7 +86,7 @@ def init_cbfplot_wf( ) cbftssummary = pe.Node( - CBFtsSummary(tr=metadata["RepetitionTime"]), + CBFtsSummary(tr=metadata.get("RepetitionTime", metadata["RepetitionTimePreparation"])), name="cbf_ts_summary", mem_gb=2, ) diff --git a/aslprep/workflows/asl/stc.py b/aslprep/workflows/asl/stc.py index a6cd8df25..1bc14ab53 100644 --- a/aslprep/workflows/asl/stc.py +++ b/aslprep/workflows/asl/stc.py @@ -66,7 +66,7 @@ def init_asl_stc_wf(metadata, name="asl_stc_wf"): slice_timing_correction = pe.Node( afni.TShift( outputtype="NIFTI_GZ", - tr=f"{metadata['RepetitionTime']}s", + tr=f"{metadata.get('RepetitionTime', metadata['RepetitionTimePreparation'])}s", slice_timing=metadata["SliceTiming"], slice_encoding_direction=metadata.get("SliceEncodingDirection", "k"), ), From 2499b9999038150a4ebf5228cfc51376aec668e4 Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Fri, 31 Mar 2023 19:43:35 -0400 Subject: [PATCH 09/43] Update gecbf.py --- aslprep/workflows/asl/gecbf.py | 1 + 1 file changed, 1 insertion(+) diff --git a/aslprep/workflows/asl/gecbf.py b/aslprep/workflows/asl/gecbf.py index 2ba2bd25a..f5ce4fa47 100644 --- a/aslprep/workflows/asl/gecbf.py +++ b/aslprep/workflows/asl/gecbf.py @@ -350,6 +350,7 @@ def init_asl_gepreproc_wf(asl_file): cbf_compt_wf = init_gecbf_compt_wf( name_source=asl_file, + aslcontext=run_data["aslcontext"], metadata=metadata, scorescrub=scorescrub, basil=basil, From d8ee95b69ca08868e435bc1e6db6015fbd096c80 Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Fri, 31 Mar 2023 20:43:21 -0400 Subject: [PATCH 10/43] Update cbf_computation.py --- aslprep/interfaces/cbf_computation.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/aslprep/interfaces/cbf_computation.py b/aslprep/interfaces/cbf_computation.py index 2290236a1..c724fa483 100644 --- a/aslprep/interfaces/cbf_computation.py +++ b/aslprep/interfaces/cbf_computation.py @@ -162,7 +162,11 @@ def _run_interface(self, runtime): else: m0data = mask_data * m0data_smooth - m0tr = m0file_metadata["RepetitionTimePreparation"] + try: + m0tr = m0file_metadata["RepetitionTimePreparation"] + except KeyError: + raise ValueError(m0file_metadata) + if np.array(m0tr).size > 1 and np.std(m0tr) > 0: raise ValueError("M0 scans have variable TR. ASLPrep does not support this.") From ac7c1da4199333625692343534693ddc0ceb1276 Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Fri, 31 Mar 2023 20:45:51 -0400 Subject: [PATCH 11/43] Update bids.py --- aslprep/utils/bids.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aslprep/utils/bids.py b/aslprep/utils/bids.py index 6fd90cd93..50ab79e9a 100644 --- a/aslprep/utils/bids.py +++ b/aslprep/utils/bids.py @@ -117,6 +117,8 @@ def collect_run_data(layout, asl_file, multiecho): raise FileNotFoundError(f"M0 file for {asl_file} not found.") elif asl_metadata["M0Type"] == "Separate": m0scan_metadata = layout.get_metadata(run_data["m0scan"]) + if not m0scan_metadata: + raise Exception(f"No metadata for m0scan: {run_data['m0scan']}") elif run_data["m0scan"]: raise ValueError( f"M0Type is {run_data['asl_metadata']['M0Type']}, " From 8a54b596c2a6d9cae56080285f09e7ccf9744965 Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Fri, 31 Mar 2023 20:49:09 -0400 Subject: [PATCH 12/43] Update bids.py --- aslprep/utils/bids.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aslprep/utils/bids.py b/aslprep/utils/bids.py index 50ab79e9a..b6e0c4c29 100644 --- a/aslprep/utils/bids.py +++ b/aslprep/utils/bids.py @@ -116,7 +116,7 @@ def collect_run_data(layout, asl_file, multiecho): if (asl_metadata["M0Type"] == "Separate") and not run_data["m0scan"]: raise FileNotFoundError(f"M0 file for {asl_file} not found.") elif asl_metadata["M0Type"] == "Separate": - m0scan_metadata = layout.get_metadata(run_data["m0scan"]) + m0scan_metadata = layout.get_file(run_data["m0scan"]).get_metadata() if not m0scan_metadata: raise Exception(f"No metadata for m0scan: {run_data['m0scan']}") elif run_data["m0scan"]: From be76e3ff5475a04b137ca88af0f99e7ff47223c4 Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Sat, 1 Apr 2023 09:16:45 -0400 Subject: [PATCH 13/43] Update unit tests. --- aslprep/tests/test_interfaces_cbf_computation.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aslprep/tests/test_interfaces_cbf_computation.py b/aslprep/tests/test_interfaces_cbf_computation.py index 030c9f26e..66879ed3f 100644 --- a/aslprep/tests/test_interfaces_cbf_computation.py +++ b/aslprep/tests/test_interfaces_cbf_computation.py @@ -12,7 +12,7 @@ def test_computecbf_casl(datasets, tmp_path_factory): """Test aslprep.interfaces.cbf_computation.ComputeCBF with (P)CASL.""" tmpdir = tmp_path_factory.mktemp("test_computecbf_casl") - aslcontext_file = os.path.join(datasets["dset"], "sub-01/perf/sub-01_aslcontext.tsv") + aslcontext_file = os.path.join(datasets["test_001"], "sub-01/perf/sub-01_aslcontext.tsv") aslcontext = pd.read_table(aslcontext_file) n_deltam = aslcontext.loc[aslcontext["volume_type"] == "label"].shape[0] @@ -143,7 +143,7 @@ def test_computecbf_casl(datasets, tmp_path_factory): def test_computecbf_pasl(datasets, tmp_path_factory): """Test aslprep.interfaces.cbf_computation.ComputeCBF with PASL.""" tmpdir = tmp_path_factory.mktemp("test_computecbf_pasl") - aslcontext_file = os.path.join(datasets["dset"], "sub-01/perf/sub-01_aslcontext.tsv") + aslcontext_file = os.path.join(datasets["test_001"], "sub-01/perf/sub-01_aslcontext.tsv") aslcontext = pd.read_table(aslcontext_file) n_deltam = aslcontext.loc[aslcontext["volume_type"] == "label"].shape[0] From e6b4f97dce707f2f6a556b88e9e3b74f3dab7fe6 Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Sat, 1 Apr 2023 09:48:36 -0400 Subject: [PATCH 14/43] Extract m0tr for GE data. --- aslprep/interfaces/cbf_computation.py | 183 +++++++++++++------------- aslprep/interfaces/ge.py | 40 +++++- aslprep/workflows/asl/cbf.py | 3 +- aslprep/workflows/asl/ge_utils.py | 34 ++++- aslprep/workflows/asl/gecbf.py | 2 + 5 files changed, 156 insertions(+), 106 deletions(-) diff --git a/aslprep/interfaces/cbf_computation.py b/aslprep/interfaces/cbf_computation.py index c724fa483..ac7a26944 100644 --- a/aslprep/interfaces/cbf_computation.py +++ b/aslprep/interfaces/cbf_computation.py @@ -152,7 +152,6 @@ def _run_interface(self, runtime): # extract m0 file and register it to ASL if separate if metadata["M0Type"] == "Separate": m0file = self.inputs.m0scan - m0file_metadata = self.inputs.m0scan_metadata m0_in_asl = fname_presuffix(self.inputs.asl_file, suffix="_m0file") m0_in_asl = regmotoasl(asl=self.inputs.asl_file, m0file=m0file, m02asl=m0_in_asl) @@ -162,11 +161,7 @@ def _run_interface(self, runtime): else: m0data = mask_data * m0data_smooth - try: - m0tr = m0file_metadata["RepetitionTimePreparation"] - except KeyError: - raise ValueError(m0file_metadata) - + m0tr = self.inputs.m0scan_metadata["RepetitionTimePreparation"] if np.array(m0tr).size > 1 and np.std(m0tr) > 0: raise ValueError("M0 scans have variable TR. ASLPrep does not support this.") @@ -197,8 +192,6 @@ def _run_interface(self, runtime): control_img = smooth_image(control_img, fwhm=self.inputs.fwhm).get_fdata() m0data = mask_data * np.mean(control_img, axis=3) - m0tr = None - elif cbf_volume_idx: # If we have precalculated CBF data, we don't need M0, so we'll just use the mask. m0data = mask_data @@ -209,6 +202,8 @@ def _run_interface(self, runtime): "and there are no control volumes that can be used as a substitute" ) + m0tr = None + else: raise RuntimeError("no pathway to m0scan") @@ -283,6 +278,92 @@ def _run_interface(self, runtime): return runtime +class _ExtractCBForDeltaMInputSpec(BaseInterfaceInputSpec): + asl_file = File(exists=True, mandatory=True, desc="raw asl file") + aslcontext = File(exists=True, mandatory=True, desc="aslcontext TSV file for run.") + in_aslmask = File(exists=True, mandatory=True, desct="asl mask") + file_type = traits.Str(desc="file type, c for cbf, d for deltam", mandatory=True) + + +class _ExtractCBForDeltaMOutputSpec(TraitedSpec): + out_file = File(exists=False, desc="cbf or deltam") + + +class ExtractCBForDeltaM(SimpleInterface): + """Load an ASL file and grab the CBF or DeltaM volumes from it.""" + + input_spec = _ExtractCBForDeltaMInputSpec + output_spec = _ExtractCBForDeltaMOutputSpec + + def _run_interface(self, runtime): + self._results["out_file"] = fname_presuffix( + self.inputs.in_aslmask, + suffix="_cbfdeltam", + newpath=runtime.cwd, + ) + asl_img = nb.load(self.inputs.asl_file) + asl_data = asl_img.get_fdata() + + aslcontext = pd.read_table(self.inputs.aslcontext) + vol_types = aslcontext["volume_type"].tolist() + control_volume_idx = [i for i, vol_type in enumerate(vol_types) if vol_type == "control"] + label_volume_idx = [i for i, vol_type in enumerate(vol_types) if vol_type == "label"] + deltam_volume_idx = [i for i, vol_type in enumerate(vol_types) if vol_type == "deltam"] + cbf_volume_idx = [i for i, vol_type in enumerate(vol_types) if vol_type == "CBF"] + + if self.inputs.file_type == "d": + if len(control_volume_idx) > 0: + # Grab control and label volumes from ASL file, + # then calculate deltaM by subtracting label volumes from control volumes. + deltam_data = ( + asl_data[:, :, :, control_volume_idx] - asl_data[:, :, :, label_volume_idx] + ) + out_img = nb.Nifti1Image( + dataobj=deltam_data, + affine=asl_img.affine, + header=asl_img.header, + ) + else: + # Grab deltaM volumes from ASL file. + if len(asl_data.shape) < 4: + # 3D volume is written out without any changes. + # NOTE: Why not return the original file then? + out_img = nb.Nifti1Image( + dataobj=asl_data, + affine=asl_img.affine, + header=asl_img.header, + ) + else: + deltam_data = asl_data[:, :, :, deltam_volume_idx] + out_img = nb.Nifti1Image( + dataobj=deltam_data, + affine=asl_img.affine, + header=asl_img.header, + ) + + elif self.inputs.file_type == "c": + if len(asl_data.shape) < 4: + # 3D volume is written out without any changes. + # NOTE: Why not return the original file then? + out_img = nb.Nifti1Image( + dataobj=asl_data, + affine=asl_img.affine, + header=asl_img.header, + ) + else: + # Grab CBF volumes from ASL file. + cbf_data = asl_data[:, :, :, cbf_volume_idx] + out_img = nb.Nifti1Image( + dataobj=cbf_data, + affine=asl_img.affine, + header=asl_img.header, + ) + + out_img.to_filename(self._results["out_file"]) + + return runtime + + class _ComputeCBFInputSpec(BaseInterfaceInputSpec): deltam = File( exists=True, @@ -1176,92 +1257,6 @@ def _run_interface(self, runtime): return runtime -class _ExtractCBForDeltaMInputSpec(BaseInterfaceInputSpec): - asl_file = File(exists=True, mandatory=True, desc="raw asl file") - aslcontext = File(exists=True, mandatory=True, desc="aslcontext TSV file for run.") - in_aslmask = File(exists=True, mandatory=True, desct="asl mask") - file_type = traits.Str(desc="file type, c for cbf, d for deltam", mandatory=True) - - -class _ExtractCBForDeltaMOutputSpec(TraitedSpec): - out_file = File(exists=False, desc="cbf or deltam") - - -class ExtractCBForDeltaM(SimpleInterface): - """Load an ASL file and grab the CBF or DeltaM volumes from it.""" - - input_spec = _ExtractCBForDeltaMInputSpec - output_spec = _ExtractCBForDeltaMOutputSpec - - def _run_interface(self, runtime): - self._results["out_file"] = fname_presuffix( - self.inputs.in_aslmask, - suffix="_cbfdeltam", - newpath=runtime.cwd, - ) - asl_img = nb.load(self.inputs.asl_file) - asl_data = asl_img.get_fdata() - - aslcontext = pd.read_table(self.inputs.aslcontext) - vol_types = aslcontext["volume_type"].tolist() - control_volume_idx = [i for i, vol_type in enumerate(vol_types) if vol_type == "control"] - label_volume_idx = [i for i, vol_type in enumerate(vol_types) if vol_type == "label"] - deltam_volume_idx = [i for i, vol_type in enumerate(vol_types) if vol_type == "deltam"] - cbf_volume_idx = [i for i, vol_type in enumerate(vol_types) if vol_type == "CBF"] - - if self.inputs.file_type == "d": - if len(control_volume_idx) > 0: - # Grab control and label volumes from ASL file, - # then calculate deltaM by subtracting label volumes from control volumes. - deltam_data = ( - asl_data[:, :, :, control_volume_idx] - asl_data[:, :, :, label_volume_idx] - ) - out_img = nb.Nifti1Image( - dataobj=deltam_data, - affine=asl_img.affine, - header=asl_img.header, - ) - else: - # Grab deltaM volumes from ASL file. - if len(asl_data.shape) < 4: - # 3D volume is written out without any changes. - # NOTE: Why not return the original file then? - out_img = nb.Nifti1Image( - dataobj=asl_data, - affine=asl_img.affine, - header=asl_img.header, - ) - else: - deltam_data = asl_data[:, :, :, deltam_volume_idx] - out_img = nb.Nifti1Image( - dataobj=deltam_data, - affine=asl_img.affine, - header=asl_img.header, - ) - - elif self.inputs.file_type == "c": - if len(asl_data.shape) < 4: - # 3D volume is written out without any changes. - # NOTE: Why not return the original file then? - out_img = nb.Nifti1Image( - dataobj=asl_data, - affine=asl_img.affine, - header=asl_img.header, - ) - else: - # Grab CBF volumes from ASL file. - cbf_data = asl_data[:, :, :, cbf_volume_idx] - out_img = nb.Nifti1Image( - dataobj=cbf_data, - affine=asl_img.affine, - header=asl_img.header, - ) - - out_img.to_filename(self._results["out_file"]) - - return runtime - - def regmotoasl(asl, m0file, m02asl): """Calculate mean M0 image and mean ASL image, then FLIRT M0 image to ASL space. diff --git a/aslprep/interfaces/ge.py b/aslprep/interfaces/ge.py index ad4378823..b3a2fc372 100644 --- a/aslprep/interfaces/ge.py +++ b/aslprep/interfaces/ge.py @@ -28,12 +28,23 @@ class _GeReferenceFileInputSpec(BaseInterfaceInputSpec): mandatory=True, desc="M0 file.", ) + m0scan_metadata = traits.Either( + traits.Dict, + None, + mandatory=True, + desc="metadata for M0 scan. Only defined if M0Type is 'Separate'.", + ) aslcontext = File(exists=True, mandatory=True, desc="aslcontext file.") class _GeReferenceFileOutputSpec(TraitedSpec): ref_file = File(exists=True, mandatory=True, desc="ref file") m0_file = File(exists=True, mandatory=True, desc="Averaged and smoothed m0 file") + m0tr = traits.Either( + traits.Float, + None, + desc="RepetitionTimePreparation for M0 scans.", + ) class GeReferenceFile(SimpleInterface): @@ -46,6 +57,7 @@ class GeReferenceFile(SimpleInterface): output_spec = _GeReferenceFileOutputSpec def _run_interface(self, runtime): + metadata = self.inputs.metadata aslcontext_df = pd.read_table(self.inputs.aslcontext) vol_types = aslcontext_df["volume_type"].tolist() control_volume_idx = [i for i, vol_type in enumerate(vol_types) if vol_type == "control"] @@ -58,7 +70,7 @@ def _run_interface(self, runtime): m0_file = fname_presuffix(self.inputs.in_file, suffix="_m0file", newpath=os.getcwd()) ref_file = fname_presuffix(self.inputs.in_file, suffix="_ref", newpath=os.getcwd()) - if self.inputs.metadata["M0Type"] == "Separate": + if metadata["M0Type"] == "Separate": # Average and smooth the M0 data m0_img = nb.load(self.inputs.m0scan) m0_data = m0_img.get_fdata() @@ -71,7 +83,11 @@ def _run_interface(self, runtime): self._results["m0_file"] = m0_file self._results["ref_file"] = m0_file # The reference file is the averaged, smoothed M0 - elif self.inputs.metadata["M0Type"] == "Included": + m0tr = self.inputs.m0scan_metadata["RepetitionTimePreparation"] + if np.array(m0tr).size > 1 and np.std(m0tr) > 0: + raise ValueError("M0 scans have variable TR. ASLPrep does not support this.") + + elif metadata["M0Type"] == "Included": m0_volume_idx = [i for i, vol_type in enumerate(vol_types) if vol_type == "m0scan"] m0_data = asl_data[:, :, :, m0_volume_idx] @@ -84,7 +100,15 @@ def _run_interface(self, runtime): self._results["m0_file"] = m0_file self._results["ref_file"] = m0_file # The reference file is the averaged, smoothed M0 - elif self.inputs.metadata["M0Type"] == "Estimate": + if np.array(metadata["RepetitionTimePreparation"]).size > 1: + m0tr = np.array(metadata["RepetitionTimePreparation"])[m0_volume_idx] + else: + m0tr = metadata["RepetitionTimePreparation"] + + if np.array(m0tr).size > 1 and np.std(m0tr) > 0: + raise ValueError("M0 scans have variable TR. ASLPrep does not support this.") + + elif metadata["M0Type"] == "Estimate": if deltam_volume_idx: idx = deltam_volume_idx elif control_volume_idx: @@ -96,7 +120,7 @@ def _run_interface(self, runtime): mean_data = np.mean(selected_data, axis=3) # XXX: Why not use an existing brain mask here? - m0_data = self.inputs.metadata["M0Estimate"] * np.ones(mean_data.shape) + m0_data = metadata["M0Estimate"] * np.ones(mean_data.shape) m0_img = nb.Nifti1Image(m0_data, asl_img.affine, asl_img.header) m0_img.to_filename(m0_file) @@ -107,7 +131,9 @@ def _run_interface(self, runtime): self._results["m0_file"] = m0_file self._results["ref_file"] = ref_file - elif self.inputs.metadata["M0Type"] == "Absent": + m0tr = None + + elif metadata["M0Type"] == "Absent": if not control_volume_idx: raise RuntimeError("M0 could not be estimated from control volumes.") @@ -122,7 +148,11 @@ def _run_interface(self, runtime): self._results["m0_file"] = m0_file self._results["ref_file"] = ref_file + m0tr = None + else: raise RuntimeError("no path way to obtain real m0scan") + self._results["m0tr"] = m0tr + return runtime diff --git a/aslprep/workflows/asl/cbf.py b/aslprep/workflows/asl/cbf.py index f7b3eff31..f55344d1e 100644 --- a/aslprep/workflows/asl/cbf.py +++ b/aslprep/workflows/asl/cbf.py @@ -402,6 +402,7 @@ def init_gecbf_compt_wf( "t1_asl_xform", "itk_asl_to_t1", "m0_file", + "m0tr", ] ), name="inputnode", @@ -657,8 +658,8 @@ def _getfiledir(file): (inputnode, basilcbf, [ (("asl_mask", _getfiledir), "out_basename"), ("m0_file", "mzero"), + ("m0tr", "m0tr"), ]), - (extract_deltam, basilcbf, [("m0tr", "m0tr")]), (collect_cbf, basilcbf, [("deltam", "in_file")]), (gm_tfm, basilcbf, [("output_image", "pvgm")]), (wm_tfm, basilcbf, [("output_image", "pvwm")]), diff --git a/aslprep/workflows/asl/ge_utils.py b/aslprep/workflows/asl/ge_utils.py index 0b835f8f2..f1e3966ad 100644 --- a/aslprep/workflows/asl/ge_utils.py +++ b/aslprep/workflows/asl/ge_utils.py @@ -52,6 +52,7 @@ def init_asl_geref_wf( fields=[ "asl_file", "m0scan", + "m0scan_metadata", "aslcontext", ], ), @@ -65,6 +66,7 @@ def init_asl_geref_wf( "ref_image_brain", "asl_mask", "m0_file", + "m0tr", "mask_report", ] ), @@ -77,27 +79,47 @@ def init_asl_geref_wf( mem_gb=1, name="gen_ge_ref", ) - skull_strip_wf = pe.Node(fsl.BET(frac=0.5, mask=True), name="fslbet") - apply_mask = pe.Node(fsl.ApplyMask(), name="apply_mask") - mask_reportlet = pe.Node(SimpleShowMaskRPT(), name="mask_reportlet") # fmt:off workflow.connect([ (inputnode, gen_ref, [ ("asl_file", "in_file"), ("m0scan", "m0scan"), + ("m0scan_metadata", "m0scan_metadata"), ("aslcontext", "aslcontext"), ]), - (gen_ref, skull_strip_wf, [("ref_file", "in_file")]), (gen_ref, outputnode, [ ("ref_file", "raw_ref_image"), ("m0_file", "m0_file"), + ("m0tr", "m0tr"), ]), - (gen_ref, mask_reportlet, [("ref_file", "background_file")]), - (gen_ref, apply_mask, [("ref_file", "in_file")]), + ]) + # fmt:on + + skull_strip_wf = pe.Node(fsl.BET(frac=0.5, mask=True), name="fslbet") + + # fmt:off + workflow.connect([ + (gen_ref, skull_strip_wf, [("ref_file", "in_file")]), (skull_strip_wf, outputnode, [("mask_file", "asl_mask")]), + ]) + # fmt:on + + apply_mask = pe.Node(fsl.ApplyMask(), name="apply_mask") + + # fmt:off + workflow.connect([ + (gen_ref, apply_mask, [("ref_file", "in_file")]), (skull_strip_wf, apply_mask, [("mask_file", "mask_file")]), (apply_mask, outputnode, [("out_file", "ref_image_brain")]), + ]) + # fmt:on + + mask_reportlet = pe.Node(SimpleShowMaskRPT(), name="mask_reportlet") + + # fmt:off + workflow.connect([ + (gen_ref, mask_reportlet, [("ref_file", "background_file")]), (skull_strip_wf, mask_reportlet, [("mask_file", "mask_file")]), ]) # fmt:on diff --git a/aslprep/workflows/asl/gecbf.py b/aslprep/workflows/asl/gecbf.py index f5ce4fa47..20e051949 100644 --- a/aslprep/workflows/asl/gecbf.py +++ b/aslprep/workflows/asl/gecbf.py @@ -316,6 +316,7 @@ def init_asl_gepreproc_wf(asl_file): (inputnode, gen_ref_wf, [ ("asl_file", "inputnode.asl_file"), ("m0scan", "inputnode.m0scan"), + ("m0scan_metadata", "inputnode.m0scan_metadata"), ("aslcontext", "inputnode.aslcontext"), ]), ]) @@ -370,6 +371,7 @@ def init_asl_gepreproc_wf(asl_file): (gen_ref_wf, cbf_compt_wf, [ ("outputnode.asl_mask", "inputnode.asl_mask"), ("outputnode.m0_file", "inputnode.m0_file"), + ("outputnode.m0tr", "inputnode.m0tr"), ]), (asl_reg_wf, cbf_compt_wf, [ ("outputnode.itk_asl_to_t1", "inputnode.itk_asl_to_t1"), From 8b918c43f66ed56ac80282f11f61d5a2ac143f39 Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Sat, 1 Apr 2023 09:58:15 -0400 Subject: [PATCH 15/43] Remove undefined connection. --- aslprep/workflows/asl/gecbf.py | 1 - 1 file changed, 1 deletion(-) diff --git a/aslprep/workflows/asl/gecbf.py b/aslprep/workflows/asl/gecbf.py index 20e051949..597fccedb 100644 --- a/aslprep/workflows/asl/gecbf.py +++ b/aslprep/workflows/asl/gecbf.py @@ -363,7 +363,6 @@ def init_asl_gepreproc_wf(asl_file): # fmt:off workflow.connect([ (inputnode, cbf_compt_wf, [ - ("asl_file", "inputnode.in_file"), ("asl_file", "inputnode.asl_file"), ("t1w_tpms", "inputnode.t1w_tpms"), ("t1w_mask", "inputnode.t1w_mask"), From 6b2aab32e7eba48b4fe18fbef97ff9b2f2e0c7e4 Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Sat, 1 Apr 2023 09:59:26 -0400 Subject: [PATCH 16/43] Update config.yml --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 6da2eeed2..f70f6124e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -336,7 +336,7 @@ jobs: paths: - .coverage.pytests - store_artifacts: - path: /src/aslprep/.circleci/out/ + path: /src/aslprep/.circleci/ merge_coverage: <<: *dockersetup From 0baf10b9accef187c7f83c26a6d1b78199cb41b6 Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Sat, 1 Apr 2023 10:09:56 -0400 Subject: [PATCH 17/43] Patch in aslcontext. --- aslprep/workflows/asl/ge_utils.py | 5 ++--- aslprep/workflows/asl/gecbf.py | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/aslprep/workflows/asl/ge_utils.py b/aslprep/workflows/asl/ge_utils.py index f1e3966ad..6bfd0efe7 100644 --- a/aslprep/workflows/asl/ge_utils.py +++ b/aslprep/workflows/asl/ge_utils.py @@ -25,6 +25,7 @@ def init_asl_geref_wf( metadata, + aslcontext, smooth_kernel=5, name="asl_gereference_wf", ): @@ -53,7 +54,6 @@ def init_asl_geref_wf( "asl_file", "m0scan", "m0scan_metadata", - "aslcontext", ], ), name="inputnode", @@ -74,7 +74,7 @@ def init_asl_geref_wf( ) gen_ref = pe.Node( - GeReferenceFile(fwhm=smooth_kernel, metadata=metadata), + GeReferenceFile(fwhm=smooth_kernel, metadata=metadata, aslcontext=aslcontext), omp_nthreads=1, mem_gb=1, name="gen_ge_ref", @@ -86,7 +86,6 @@ def init_asl_geref_wf( ("asl_file", "in_file"), ("m0scan", "m0scan"), ("m0scan_metadata", "m0scan_metadata"), - ("aslcontext", "aslcontext"), ]), (gen_ref, outputnode, [ ("ref_file", "raw_ref_image"), diff --git a/aslprep/workflows/asl/gecbf.py b/aslprep/workflows/asl/gecbf.py index 597fccedb..36b2499f3 100644 --- a/aslprep/workflows/asl/gecbf.py +++ b/aslprep/workflows/asl/gecbf.py @@ -306,8 +306,9 @@ def init_asl_gepreproc_wf(asl_file): # begin workflow # Extract averaged, smoothed M0 image and reference image (which is generally the M0 image). gen_ref_wf = init_asl_geref_wf( - smooth_kernel=smoothkernel, metadata=metadata, + aslcontext=run_data["aslcontext"], + smooth_kernel=smoothkernel, name="asl_gereference_wf", ) @@ -317,7 +318,6 @@ def init_asl_gepreproc_wf(asl_file): ("asl_file", "inputnode.asl_file"), ("m0scan", "inputnode.m0scan"), ("m0scan_metadata", "inputnode.m0scan_metadata"), - ("aslcontext", "inputnode.aslcontext"), ]), ]) # fmt:on From add43561f33fc9bbe35eee5c3ed25e08c2709113 Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Sat, 1 Apr 2023 10:21:08 -0400 Subject: [PATCH 18/43] Save M0 file. --- aslprep/interfaces/ge.py | 1 + 1 file changed, 1 insertion(+) diff --git a/aslprep/interfaces/ge.py b/aslprep/interfaces/ge.py index b3a2fc372..0f7b57bdb 100644 --- a/aslprep/interfaces/ge.py +++ b/aslprep/interfaces/ge.py @@ -79,6 +79,7 @@ def _run_interface(self, runtime): mean_img = nb.Nifti1Image(m0_data, asl_img.affine, asl_img.header) smoothed_img = nb.processing.smooth_image(mean_img, fwhm=self.inputs.fwhm) + smoothed_img.to_filename(m0_file) self._results["m0_file"] = m0_file self._results["ref_file"] = m0_file # The reference file is the averaged, smoothed M0 From 05617d3827d0faa51a434a6a7918c952472b67de Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Sat, 1 Apr 2023 10:29:49 -0400 Subject: [PATCH 19/43] Fix test. --- aslprep/tests/test_interfaces_cbf_computation.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aslprep/tests/test_interfaces_cbf_computation.py b/aslprep/tests/test_interfaces_cbf_computation.py index 66879ed3f..0f792a32d 100644 --- a/aslprep/tests/test_interfaces_cbf_computation.py +++ b/aslprep/tests/test_interfaces_cbf_computation.py @@ -12,7 +12,7 @@ def test_computecbf_casl(datasets, tmp_path_factory): """Test aslprep.interfaces.cbf_computation.ComputeCBF with (P)CASL.""" tmpdir = tmp_path_factory.mktemp("test_computecbf_casl") - aslcontext_file = os.path.join(datasets["test_001"], "sub-01/perf/sub-01_aslcontext.tsv") + aslcontext_file = os.path.join(datasets["test_001"], "dset/sub-01/perf/sub-01_aslcontext.tsv") aslcontext = pd.read_table(aslcontext_file) n_deltam = aslcontext.loc[aslcontext["volume_type"] == "label"].shape[0] @@ -143,7 +143,7 @@ def test_computecbf_casl(datasets, tmp_path_factory): def test_computecbf_pasl(datasets, tmp_path_factory): """Test aslprep.interfaces.cbf_computation.ComputeCBF with PASL.""" tmpdir = tmp_path_factory.mktemp("test_computecbf_pasl") - aslcontext_file = os.path.join(datasets["test_001"], "sub-01/perf/sub-01_aslcontext.tsv") + aslcontext_file = os.path.join(datasets["test_001"], "dset/sub-01/perf/sub-01_aslcontext.tsv") aslcontext = pd.read_table(aslcontext_file) n_deltam = aslcontext.loc[aslcontext["volume_type"] == "label"].shape[0] From ec7bb6e87f87ec83482c8abd39fc8cb7db6a8527 Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Sat, 1 Apr 2023 10:41:02 -0400 Subject: [PATCH 20/43] Okay, maybe fix that now. --- .circleci/config.yml | 4 +++- aslprep/tests/test_interfaces_cbf_computation.py | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index f70f6124e..173a8c01e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -322,7 +322,9 @@ jobs: circleci step halt fi - restore_cache: - key: data-v4 + key: test_001-v1 + - restore_cache: + key: test_003-v1 - run: *runinstall - run: name: Run pytest on the tests directory diff --git a/aslprep/tests/test_interfaces_cbf_computation.py b/aslprep/tests/test_interfaces_cbf_computation.py index 0f792a32d..66879ed3f 100644 --- a/aslprep/tests/test_interfaces_cbf_computation.py +++ b/aslprep/tests/test_interfaces_cbf_computation.py @@ -12,7 +12,7 @@ def test_computecbf_casl(datasets, tmp_path_factory): """Test aslprep.interfaces.cbf_computation.ComputeCBF with (P)CASL.""" tmpdir = tmp_path_factory.mktemp("test_computecbf_casl") - aslcontext_file = os.path.join(datasets["test_001"], "dset/sub-01/perf/sub-01_aslcontext.tsv") + aslcontext_file = os.path.join(datasets["test_001"], "sub-01/perf/sub-01_aslcontext.tsv") aslcontext = pd.read_table(aslcontext_file) n_deltam = aslcontext.loc[aslcontext["volume_type"] == "label"].shape[0] @@ -143,7 +143,7 @@ def test_computecbf_casl(datasets, tmp_path_factory): def test_computecbf_pasl(datasets, tmp_path_factory): """Test aslprep.interfaces.cbf_computation.ComputeCBF with PASL.""" tmpdir = tmp_path_factory.mktemp("test_computecbf_pasl") - aslcontext_file = os.path.join(datasets["test_001"], "dset/sub-01/perf/sub-01_aslcontext.tsv") + aslcontext_file = os.path.join(datasets["test_001"], "sub-01/perf/sub-01_aslcontext.tsv") aslcontext = pd.read_table(aslcontext_file) n_deltam = aslcontext.loc[aslcontext["volume_type"] == "label"].shape[0] From 68be1fc91e91c804575a3bc849f1adc46c4664c2 Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Sat, 1 Apr 2023 11:20:52 -0400 Subject: [PATCH 21/43] Enable debug mode. --- aslprep/tests/test_cli.py | 3 +++ aslprep/workflows/base.py | 3 +++ 2 files changed, 6 insertions(+) diff --git a/aslprep/tests/test_cli.py b/aslprep/tests/test_cli.py index 902e8e327..5d7e3f9de 100644 --- a/aslprep/tests/test_cli.py +++ b/aslprep/tests/test_cli.py @@ -2,11 +2,14 @@ import os import pytest +from nipype import config as nipype_config from aslprep.cli.parser import parse_args from aslprep.cli.workflow import build_workflow from aslprep.tests.utils import check_generated_files, get_test_data_path +nipype_config.enable_debug_mode() + @pytest.mark.examples_pcasl_singlepld def test_examples_pcasl_singlepld(datasets, output_dir, working_dir): diff --git a/aslprep/workflows/base.py b/aslprep/workflows/base.py index 3b5c18e6b..233f6a86c 100644 --- a/aslprep/workflows/base.py +++ b/aslprep/workflows/base.py @@ -307,11 +307,14 @@ def init_single_subject_wf(subject_id): ) for asl_file in subject_data["asl"]: + config.loggers.workflow.log(25, f"Processing {asl_file}") + # If number of volume of ASL is less than 5, motion correction, # slice-timing correction, etc. will be skipped. n_vols = get_n_volumes(asl_file) asl_preproc_func = init_asl_preproc_wf if n_vols > 5 else init_asl_gepreproc_wf asl_preproc_wf = asl_preproc_func(asl_file) + # fmt:off workflow.connect([ (anat_preproc_wf, asl_preproc_wf, [ From d9dc89ae65b97f272d642f3252813d79fafedcdc Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Sat, 1 Apr 2023 12:17:10 -0400 Subject: [PATCH 22/43] Connect things better. --- aslprep/workflows/asl/cbf.py | 80 ++++++++++++++++++++++-------------- aslprep/workflows/asl/qc.py | 8 ++-- 2 files changed, 53 insertions(+), 35 deletions(-) diff --git a/aslprep/workflows/asl/cbf.py b/aslprep/workflows/asl/cbf.py index f55344d1e..dbb09831c 100644 --- a/aslprep/workflows/asl/cbf.py +++ b/aslprep/workflows/asl/cbf.py @@ -159,7 +159,7 @@ def _pick_wm(files): return files[1] def _pick_csf(files): - return files[-1] + return files[2] def _getfiledir(file): import os @@ -424,23 +424,71 @@ def init_gecbf_compt_wf( ), name="outputnode", ) + + def _pick_gm(files): + return files[0] + + def _pick_wm(files): + return files[1] + + def _pick_csf(files): + return files[2] + + def _getfiledir(file): + import os + + return os.path.dirname(file) + # convert tmps to asl_space + # extract probability maps csf_tfm = pe.Node( ApplyTransforms(interpolation="NearestNeighbor", float=True), name="csf_tfm", mem_gb=0.1, ) + + # fmt:off + workflow.connect([ + (inputnode, csf_tfm, [ + ("asl_mask", "reference_image"), + ("t1_asl_xform", "transforms"), + (("t1w_tpms", _pick_csf), "input_image"), + ]), + ]) + # fmt:on + wm_tfm = pe.Node( ApplyTransforms(interpolation="NearestNeighbor", float=True), name="wm_tfm", mem_gb=0.1, ) + + # fmt:off + workflow.connect([ + (inputnode, wm_tfm, [ + ("asl_mask", "reference_image"), + ("t1_asl_xform", "transforms"), + (("t1w_tpms", _pick_wm), "input_image"), + ]), + ]) + # fmt:on + gm_tfm = pe.Node( ApplyTransforms(interpolation="NearestNeighbor", float=True), name="gm_tfm", mem_gb=0.1, ) + # fmt:off + workflow.connect([ + (inputnode, gm_tfm, [ + ("asl_mask", "reference_image"), + ("t1_asl_xform", "transforms"), + (("t1w_tpms", _pick_gm), "input_image"), + ]), + ]) + # fmt:on + aslcontext_df = pd.read_table(aslcontext) cbf_only = all(aslcontext_df["volume_type"].isin(("m0scan", "cbf"))) if cbf_only and not basil: @@ -471,20 +519,6 @@ def init_gecbf_compt_wf( ]) # fmt:on - def _pick_gm(files): - return files[0] - - def _pick_wm(files): - return files[1] - - def _pick_csf(files): - return files[-1] - - def _getfiledir(file): - import os - - return os.path.dirname(file) - collect_cbf = pe.Node( niu.IdentityInterface( fields=["deltam", "cbf"], @@ -591,22 +625,6 @@ def _getfiledir(file): # fmt:off workflow.connect([ - # extract probability maps - (inputnode, csf_tfm, [ - ("asl_mask", "reference_image"), - ("t1_asl_xform", "transforms"), - (("t1w_tpms", _pick_csf), "input_image"), - ]), - (inputnode, wm_tfm, [ - ("asl_mask", "reference_image"), - ("t1_asl_xform", "transforms"), - (("t1w_tpms", _pick_wm), "input_image"), - ]), - (inputnode, gm_tfm, [ - ("asl_mask", "reference_image"), - ("t1_asl_xform", "transforms"), - (("t1w_tpms", _pick_gm), "input_image"), - ]), (refine_mask, score_and_scrub_cbf, [("out_mask", "in_mask")]), (gm_tfm, score_and_scrub_cbf, [("output_image", "in_greyM")]), (wm_tfm, score_and_scrub_cbf, [("output_image", "in_whiteM")]), diff --git a/aslprep/workflows/asl/qc.py b/aslprep/workflows/asl/qc.py index 614e2ec49..3c9d968b7 100644 --- a/aslprep/workflows/asl/qc.py +++ b/aslprep/workflows/asl/qc.py @@ -90,7 +90,7 @@ def _pick_wm(files): return files[1] def _pick_csf(files): - return files[-1] + return files[2] gm_tfm = pe.Node( ApplyTransforms(interpolation="NearestNeighbor", float=True), @@ -262,15 +262,15 @@ def init_cbfgeqc_compt_wf( ) outputnode = pe.Node(niu.IdentityInterface(fields=["qc_file"]), name="outputnode") - def _pick_csf(files): - return files[-1] - def _pick_gm(files): return files[0] def _pick_wm(files): return files[1] + def _pick_csf(files): + return files[2] + csf_tfm = pe.Node( ApplyTransforms(interpolation="NearestNeighbor", float=True), name="csf_tfm", From 2d6518a75ca90a97f2c45210dcf1c72f3d00f933 Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Sat, 1 Apr 2023 12:47:01 -0400 Subject: [PATCH 23/43] Update qc.py --- aslprep/workflows/asl/qc.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/aslprep/workflows/asl/qc.py b/aslprep/workflows/asl/qc.py index 3c9d968b7..618bd4203 100644 --- a/aslprep/workflows/asl/qc.py +++ b/aslprep/workflows/asl/qc.py @@ -11,6 +11,7 @@ from aslprep.niworkflows.interfaces.fixes import ( FixHeaderApplyTransforms as ApplyTransforms, ) +from aslprep.utils.misc import _select_last_in_list def init_cbfqc_compt_wf( @@ -158,9 +159,9 @@ def _pick_csf(files): ("asl_mask", "in_aslmask"), ("confmat", "in_confmat"), ]), - (inputnode, qccompute, [(("asl_mask_std", _pick_csf), "in_aslmaskstd")]), + (inputnode, qccompute, [(("asl_mask_std", _select_last_in_list), "in_aslmaskstd")]), (inputnode, qccompute, [("rmsd_file", "rmsd_file")]), - (inputnode, resample, [(("asl_mask_std", _pick_csf), "master")]), + (inputnode, resample, [(("asl_mask_std", _select_last_in_list), "master")]), (resample, qccompute, [("out_file", "in_templatemask")]), (gm_tfm, qccompute, [("output_image", "in_greyM")]), (wm_tfm, qccompute, [("output_image", "in_whiteM")]), @@ -334,8 +335,8 @@ def _pick_csf(files): ]), (mask_tfm, qccompute, [("output_image", "in_t1mask")]), (inputnode, qccompute, [("asl_mask", "in_aslmask")]), - (inputnode, qccompute, [(("asl_mask_std", _pick_csf), "in_aslmaskstd")]), - (inputnode, resample, [(("asl_mask_std", _pick_csf), "master")]), + (inputnode, qccompute, [(("asl_mask_std", _select_last_in_list), "in_aslmaskstd")]), + (inputnode, resample, [(("asl_mask_std", _select_last_in_list), "master")]), (resample, qccompute, [("out_file", "in_templatemask")]), (gm_tfm, qccompute, [("output_image", "in_greyM")]), (wm_tfm, qccompute, [("output_image", "in_whiteM")]), From 71d53eeda3184219cf2c72a58130fd6cb2dbeb80 Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Sat, 1 Apr 2023 13:16:08 -0400 Subject: [PATCH 24/43] Update cbf_computation.py --- aslprep/interfaces/cbf_computation.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aslprep/interfaces/cbf_computation.py b/aslprep/interfaces/cbf_computation.py index ac7a26944..f300c8936 100644 --- a/aslprep/interfaces/cbf_computation.py +++ b/aslprep/interfaces/cbf_computation.py @@ -1156,6 +1156,7 @@ def _run_interface(self, runtime): dict1 = { "FD": 0, "relRMS": 0, + "rmsd": np.nan, "coregDC": [regDC], "coregJC": [regJC], "coregCC": [regCC], @@ -1182,6 +1183,7 @@ def _run_interface(self, runtime): dict1 = { "FD": 0, "relRMS": 0, + "rmsd": np.nan, "coregDC": [regDC], "coregJC": [regJC], "coregCC": [regCC], From 707512da54d62bfbba73993b185ad3fabc11b437 Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Sun, 2 Apr 2023 10:11:15 -0400 Subject: [PATCH 25/43] Update stuff. --- .circleci/config.yml | 113 ++++++++++++------ .circleci/get_data.sh | 90 -------------- .../data/examples_pcasl_singlepld_filter.json | 5 + .../examples_pcasl_singlepld_ge_filter.json | 5 + aslprep/tests/test_cli.py | 48 +++++++- pyproject.toml | 3 +- 6 files changed, 137 insertions(+), 127 deletions(-) delete mode 100644 .circleci/get_data.sh create mode 100644 aslprep/tests/data/examples_pcasl_singlepld_filter.json create mode 100644 aslprep/tests/data/examples_pcasl_singlepld_ge_filter.json diff --git a/.circleci/config.yml b/.circleci/config.yml index 173a8c01e..14a0fc250 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -33,7 +33,7 @@ jobs: - checkout - run: *runinstall - download_data_examples_pcasl_singlepld: + download_pcasl_singlepld: <<: *dockersetup steps: - checkout @@ -50,7 +50,7 @@ jobs: paths: - /src/aslprep/.circleci/data - download_data_examples_pcasl_multipld: + download_pcasl_multipld: <<: *dockersetup steps: - checkout @@ -67,7 +67,7 @@ jobs: paths: - /src/aslprep/.circleci/data - download_data_examples_pasl_multipld: + download_pasl_multipld: <<: *dockersetup steps: - checkout @@ -135,7 +135,7 @@ jobs: paths: - /src/aslprep/.circleci/data - aslprep_examples_pcasl_singlepld: + pcasl_singlepld: <<: *dockersetup steps: - checkout @@ -164,7 +164,36 @@ jobs: paths: - .coverage.examples_pcasl_singlepld - aslprep_examples_pcasl_multipld: + pcasl_singlepld_ge: + <<: *dockersetup + steps: + - checkout + - run: + name: Check whether build should be skipped + command: | + cd /src/aslprep + if [[ "$( git log --format=oneline -n 1 $CIRCLE_SHA1 | grep -i -E '\[skip[ _]?examples_pcasl_singlepld\]' )" != "" ]]; then + echo "Skipping examples_pcasl_singlepld build" + circleci step halt + fi + - restore_cache: + key: examples_pcasl_singlepld-v1 + - run: *runinstall + - run: + name: Run full aslprep on examples_pcasl_singlepld dataset + no_output_timeout: 5h + command: | + pytest -rP -o log_cli=true -m "examples_pcasl_singlepld_ge" --cov-append --cov-report term-missing --cov=aslprep --data_dir=/src/aslprep/.circleci/data --output_dir=/src/aslprep/.circleci/out --working_dir=/src/aslprep/.circleci/work aslprep + mkdir /src/coverage + mv /src/aslprep/.coverage /src/coverage/.coverage.examples_pcasl_singlepld_ge + - store_artifacts: + path: /src/aslprep/.circleci/out + - persist_to_workspace: + root: /src/coverage + paths: + - .coverage.examples_pcasl_singlepld_ge + + pcasl_multipld: <<: *dockersetup steps: - checkout @@ -193,7 +222,7 @@ jobs: paths: - .coverage.examples_pcasl_multipld - aslprep_examples_pasl_multipld: + pasl_multipld: <<: *dockersetup steps: - checkout @@ -222,7 +251,7 @@ jobs: paths: - .coverage.examples_pasl_multipld - aslprep_test_001: + test_001: <<: *dockersetup steps: - checkout @@ -251,7 +280,7 @@ jobs: paths: - .coverage.test_001 - aslprep_test_002: + test_002: <<: *dockersetup steps: - checkout @@ -280,7 +309,7 @@ jobs: paths: - .coverage.test_002 - aslprep_test_003: + test_003: <<: *dockersetup steps: - checkout @@ -288,8 +317,8 @@ jobs: name: Check whether build should be skipped command: | cd /src/aslprep - if [[ "$( git log --format=oneline -n 1 $CIRCLE_SHA1 | grep -i -E '\[skip[ _]?aslprep_test_003\]' )" != "" ]]; then - echo "Skipping aslprep_test_003 build" + if [[ "$( git log --format=oneline -n 1 $CIRCLE_SHA1 | grep -i -E '\[skip[ _]?test_003\]' )" != "" ]]; then + echo "Skipping test_003 build" circleci step halt fi - restore_cache: @@ -423,7 +452,7 @@ workflows: tags: only: /.*/ - - download_data_examples_pcasl_singlepld: + - download_pcasl_singlepld: filters: branches: ignore: @@ -432,7 +461,7 @@ workflows: tags: only: /.*/ - - download_data_examples_pcasl_multipld: + - download_pcasl_multipld: filters: branches: ignore: @@ -441,7 +470,7 @@ workflows: tags: only: /.*/ - - download_data_examples_pasl_multipld: + - download_pasl_multipld: filters: branches: ignore: @@ -477,9 +506,21 @@ workflows: tags: only: /.*/ - - aslprep_examples_pcasl_singlepld: + - pcasl_singlepld: + requires: + - download_pcasl_singlepld + - build + filters: + branches: + ignore: + - /docs?\/.*/ + - /tests?\/.*/ + tags: + only: /.*/ + + - pcasl_singlepld_ge: requires: - - download_data_examples_pcasl_singlepld + - download_pcasl_singlepld - build filters: branches: @@ -489,9 +530,9 @@ workflows: tags: only: /.*/ - - aslprep_examples_pcasl_multipld: + - pcasl_multipld: requires: - - download_data_examples_pcasl_multipld + - download_pcasl_multipld - build filters: branches: @@ -501,9 +542,9 @@ workflows: tags: only: /.*/ - - aslprep_examples_pasl_multipld: + - pasl_multipld: requires: - - download_data_examples_pasl_multipld + - download_pasl_multipld - build filters: branches: @@ -513,7 +554,7 @@ workflows: tags: only: /.*/ - - aslprep_test_001: + - test_001: requires: - download_data_test_001 - build @@ -525,7 +566,7 @@ workflows: tags: only: /.*/ - - aslprep_test_002: + - test_002: requires: - download_data_test_002 - build @@ -537,7 +578,7 @@ workflows: tags: only: /.*/ - - aslprep_test_003: + - test_003: requires: - download_data_test_003 - build @@ -565,12 +606,13 @@ workflows: - merge_coverage: requires: - - aslprep_examples_pcasl_singlepld - - aslprep_examples_pcasl_multipld - - aslprep_examples_pasl_multipld - - aslprep_test_001 - - aslprep_test_002 - - aslprep_test_003 + - pcasl_singlepld + - pcasl_singlepld_ge + - pcasl_multipld + - pasl_multipld + - test_001 + - test_002 + - test_003 - pytests filters: branches: @@ -583,12 +625,13 @@ workflows: - deployable: requires: - build - - aslprep_examples_pcasl_singlepld - - aslprep_examples_pcasl_multipld - - aslprep_examples_pasl_multipld - - aslprep_test_001 - - aslprep_test_002 - - aslprep_test_003 + - pcasl_singlepld + - pcasl_singlepld_ge + - pcasl_multipld + - pasl_multipld + - test_001 + - test_002 + - test_003 filters: branches: only: main diff --git a/.circleci/get_data.sh b/.circleci/get_data.sh deleted file mode 100644 index ac51d07b6..000000000 --- a/.circleci/get_data.sh +++ /dev/null @@ -1,90 +0,0 @@ - -if [[ "$SHELL" == zsh ]]; then - setopt SH_WORD_SPLIT -fi - -# Edit these for project-wide testing -WGET="wget --retry-connrefused --waitretry=5 --read-timeout=20 --timeout=15 -t 0 -q" -IMAGE="pennlinc/aslprep:unstable" - -# Determine if we're in a CI test -if [[ "${CIRCLECI}" = "true" ]]; then - IN_CI="true" - NTHREADS=2 - OMP_NTHREADS=2 - - if [[ -n "${CIRCLE_CPUS}" ]]; then - NTHREADS=${CIRCLE_CPUS} - OMP_NTHREADS=$(expr $NTHREADS - 1) - fi - -else - IN_CI="false" - NTHREADS=2 - OMP_NTHREADS=2 - - LOCAL_PATCH_FILE="local_aslprep_path.txt" - - # check that the patch file exists - if [ ! -f $LOCAL_PATCH_FILE ] - then - echo "File $LOCAL_PATCH_FILE DNE" - exit 1 - fi - - LOCAL_PATCH="$( cat ${LOCAL_PATCH_FILE} )" # Load path from file - - # check that the local aslprep path exists - if [ ! -d $LOCAL_PATCH ] - then - echo "Path $LOCAL_PATCH DNE" - exit 1 - fi - -fi -export IN_CI NTHREADS OMP_NTHREADS - - -get_bids_data() { - WORKDIR=$1 - DS=$2 - echo "working dir: ${WORKDIR}" - echo "fetching dataset: ${DS}" - ENTRYDIR=`pwd` - TEST_DATA_DIR="${WORKDIR}/data" - mkdir -p $TEST_DATA_DIR - cd $TEST_DATA_DIR - - # without freesurfer, sub-01 - if [[ ${DS} = downsampled ]] - then - dataset_dir="$TEST_DATA_DIR/dset" - # Do not re-download if the folder exists - if [ ! -d $dataset_dir ] - then - echo "Downloading ${DS} data to $dataset_dir" - - # Download the raw BIDS dataset - ${WGET} \ - -O downsampled.tar.xz \ - "https://upenn.box.com/shared/static/og1ixccv5v8eir76emii6rrgnwu4thad.xz" - tar xvfJ downsampled.tar.xz -C $TEST_DATA_DIR - mv testingbids dset - rm downsampled.tar.xz - - # Download the pre-generated smriprep derivatives - ${WGET} \ - -O smriprepx.tar.xz \ - "https://upenn.box.com/shared/static/i64rbrpzfinpej0vct96mjw6ve7yycov.xz" - tar xvfJ smriprepx.tar.xz -C $TEST_DATA_DIR - mkdir dset/derivatives - mv smriprep dset/derivatives/smriprep - rm smriprepx.tar.xz - - else - echo "Data directory ($dataset_dir) already exists. If you need to re-download the data, remove the data folder." - fi - fi - - cd ${ENTRYDIR} -} diff --git a/aslprep/tests/data/examples_pcasl_singlepld_filter.json b/aslprep/tests/data/examples_pcasl_singlepld_filter.json new file mode 100644 index 000000000..d7d17e156 --- /dev/null +++ b/aslprep/tests/data/examples_pcasl_singlepld_filter.json @@ -0,0 +1,5 @@ +{ + "asl": { + "session": ["philips2d", "siemens3d"] + } +} \ No newline at end of file diff --git a/aslprep/tests/data/examples_pcasl_singlepld_ge_filter.json b/aslprep/tests/data/examples_pcasl_singlepld_ge_filter.json new file mode 100644 index 000000000..4b3bae43c --- /dev/null +++ b/aslprep/tests/data/examples_pcasl_singlepld_ge_filter.json @@ -0,0 +1,5 @@ +{ + "asl": { + "session": ["ge3d"] + } +} \ No newline at end of file diff --git a/aslprep/tests/test_cli.py b/aslprep/tests/test_cli.py index 5d7e3f9de..a418f281e 100644 --- a/aslprep/tests/test_cli.py +++ b/aslprep/tests/test_cli.py @@ -21,6 +21,7 @@ def test_examples_pcasl_singlepld(datasets, output_dir, working_dir): out_dir = os.path.join(output_dir, test_name) work_dir = os.path.join(working_dir, test_name) test_data_dir = get_test_data_path() + filter_file = os.path.join(test_data_dir, "examples_pcasl_singlepld_ge_filter.json") parameters = [ data_dir, @@ -28,6 +29,7 @@ def test_examples_pcasl_singlepld(datasets, output_dir, working_dir): "participant", "--participant-label=103", f"-w={work_dir}", + f"--bids-filter-file={filter_file}", "--nthreads=2", "--omp-nthreads=2", "--output-spaces=asl", @@ -49,6 +51,49 @@ def test_examples_pcasl_singlepld(datasets, output_dir, working_dir): check_generated_files(out_dir, output_list_file) +@pytest.mark.examples_pcasl_singlepld_ge +def test_examples_pcasl_singlepld_ge(datasets, output_dir, working_dir): + """Run aslprep on sub-01 data.""" + from aslprep import config + + test_name = "examples_pcasl_singlepld_ge" + data_dir = datasets["examples_pcasl_singlepld"] + out_dir = os.path.join(output_dir, test_name) + work_dir = os.path.join(working_dir, test_name) + test_data_dir = get_test_data_path() + filter_file = os.path.join(test_data_dir, "examples_pcasl_singlepld_ge_filter.json") + + parameters = [ + data_dir, + out_dir, + "participant", + "--participant-label=103", + f"-w={work_dir}", + f"--bids-filter-file={filter_file}", + "--nthreads=2", + "--omp-nthreads=2", + "--output-spaces=asl", + "--scorescrub", + "--basil", + "--use-syn-sdc", + f"--anat-derivatives={os.path.join(data_dir, 'derivatives/smriprep')}", + ] + parse_args(parameters) + config_file = config.execution.work_dir / f"config-{config.execution.run_uuid}.toml" + config.to_filename(config_file) + + retval = {} + retval = build_workflow(config_file, retval=retval) + aslprep_wf = retval.get("workflow", None) + aslprep_wf.run() + + output_list_file = os.path.join( + test_data_dir, + "expected_outputs_examples_pcasl_singlepld_ge.txt", + ) + check_generated_files(out_dir, output_list_file) + + @pytest.mark.examples_pcasl_multipld def test_examples_pcasl_multipld(datasets, output_dir, working_dir): """Run aslprep on sub-01 data.""" @@ -167,7 +212,8 @@ def test_test_001(datasets, output_dir, working_dir): def test_test_002(datasets, output_dir, working_dir): """Run aslprep on sub-10R01383. - Currently skipped. + This dataset contains PCASL data from a GE scanner. + There are two ASL volumes (both deltam) and separate M0 scan. Notes ----- diff --git a/pyproject.toml b/pyproject.toml index da52d9cd0..ebe8b4b77 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,9 +34,10 @@ exclude = ''' ''' [tool.pytest.ini_options] -addopts = '-m "not examples_pcasl_singlepld and not examples_pcasl_multipld and not examples_pasl_multipld and not test_001 and not test_002 and not test_003"' +addopts = '-m "not examples_pcasl_singlepld and not examples_pcasl_singlepld_ge and not examples_pcasl_multipld and not examples_pasl_multipld and not test_001 and not test_002 and not test_003"' markers = [ "examples_pcasl_singlepld: mark integration test", + "examples_pcasl_singlepld_ge: mark integration test", "examples_pcasl_multipld: mark integration test", "examples_pasl_multipld: mark integration test", "test_001: mark integration test for subject 01", From 7aae24b1f403e6ee1f39a5d765af314ba3d40a9a Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Sun, 2 Apr 2023 10:56:51 -0400 Subject: [PATCH 26/43] Update test_cli.py --- aslprep/tests/test_cli.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/aslprep/tests/test_cli.py b/aslprep/tests/test_cli.py index a418f281e..74f4d3c3a 100644 --- a/aslprep/tests/test_cli.py +++ b/aslprep/tests/test_cli.py @@ -21,7 +21,7 @@ def test_examples_pcasl_singlepld(datasets, output_dir, working_dir): out_dir = os.path.join(output_dir, test_name) work_dir = os.path.join(working_dir, test_name) test_data_dir = get_test_data_path() - filter_file = os.path.join(test_data_dir, "examples_pcasl_singlepld_ge_filter.json") + filter_file = os.path.join(test_data_dir, "examples_pcasl_singlepld_filter.json") parameters = [ data_dir, @@ -237,6 +237,7 @@ def test_test_002(datasets, output_dir, working_dir): "--nthreads=2", "--omp-nthreads=2", "--output-spaces=asl", + "--scorescrub", "--basil", "--use-syn-sdc", f"--anat-derivatives={os.path.join(data_dir, 'derivatives/smriprep')}", From 7fc18f42d90525f7fac76733b0075628888517ba Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Sun, 2 Apr 2023 12:59:59 -0400 Subject: [PATCH 27/43] Expect errors. --- aslprep/tests/test_cli.py | 6 +++-- aslprep/utils/misc.py | 55 +++++++++++++++++++++++---------------- 2 files changed, 37 insertions(+), 24 deletions(-) diff --git a/aslprep/tests/test_cli.py b/aslprep/tests/test_cli.py index 74f4d3c3a..84d5a20c6 100644 --- a/aslprep/tests/test_cli.py +++ b/aslprep/tests/test_cli.py @@ -126,7 +126,8 @@ def test_examples_pcasl_multipld(datasets, output_dir, working_dir): retval = {} retval = build_workflow(config_file, retval=retval) aslprep_wf = retval.get("workflow", None) - aslprep_wf.run() + with pytest.raises(ValueError, match="ASLPrep cannot currently process multi-PLD data."): + aslprep_wf.run() output_list_file = os.path.join(test_data_dir, "expected_outputs_examples_pcasl_multipld.txt") check_generated_files(out_dir, output_list_file) @@ -164,7 +165,8 @@ def test_examples_pasl_multipld(datasets, output_dir, working_dir): retval = {} retval = build_workflow(config_file, retval=retval) aslprep_wf = retval.get("workflow", None) - aslprep_wf.run() + with pytest.raises(ValueError, match="ASLPrep cannot currently process multi-PLD data."): + aslprep_wf.run() output_list_file = os.path.join(test_data_dir, "expected_outputs_examples_pasl_multipld.txt") check_generated_files(out_dir, output_list_file) diff --git a/aslprep/utils/misc.py b/aslprep/utils/misc.py index e90ec6cdd..7d2a8b81e 100644 --- a/aslprep/utils/misc.py +++ b/aslprep/utils/misc.py @@ -9,6 +9,7 @@ import nibabel as nb import numpy as np from pkg_resources import resource_filename as pkgrf +from scipy.stats import median_abs_deviation def check_deps(workflow): @@ -529,28 +530,29 @@ def _getcbfscore(cbfts, wm, gm, csf, mask, thresh=0.7): mask numpy array of mask """ - gm[gm < thresh] = 0 - gm[gm > 0] = 1 - wm[wm < thresh] = 0 - wm[wm > 0] = 1 - csf[csf < thresh] = 0 - csf[csf > 0] = 1 + gm_bin = gm >= thresh + wm_bin = wm >= thresh + csf_bin = csf >= thresh + # get the total number of voxle within csf,gm and wm - nogm = np.sum(gm == 1) - 1 - nowm = np.sum(wm == 1) - 1 - nocf = np.sum(csf == 1) - 1 - mask1 = gm + wm + csf - # msk=sum(mask>0) + n_gm_voxels = np.sum(gm_bin) - 1 + n_wm_voxels = np.sum(wm_bin) - 1 + n_csf_voxels = np.sum(csf_bin) - 1 + mask1 = gm_bin + wm_bin + csf_bin + # mean of times series cbf within greymatter - mgmts = np.squeeze(np.mean(cbfts[gm == 1, :], axis=0)) - # robiust mean and meadian - from scipy.stats import median_abs_deviation + gm_cbf_ts = np.squeeze(np.mean(cbfts[gm_bin, :], axis=0)) - medmngm = np.median(mgmts) - sdmngm = median_abs_deviation(mgmts) / 0.675 - indx = 1 * (np.abs(mgmts - medmngm) > (2.5 * sdmngm)) + # robust mean and median + median_gm_cbf = np.median(gm_cbf_ts) + mad_gm_cbf = median_abs_deviation(gm_cbf_ts) / 0.675 + indx = 1 * (np.abs(gm_cbf_ts - median_gm_cbf) > (2.5 * mad_gm_cbf)) R = np.mean(cbfts[:, :, :, indx == 0], axis=3) - V = nogm * np.var(R[gm == 1]) + nowm * np.var(R[wm == 1]) + nocf * np.var(R[csf == 1]) + V = ( + n_gm_voxels * np.var(R[gm == 1]) + + n_wm_voxels * np.var(R[wm == 1]) + + n_csf_voxels * np.var(R[csf == 1]) + ) V1 = V + 1 while V < V1: V1 = V @@ -561,14 +563,20 @@ def _getcbfscore(cbfts, wm, gm, csf, mask, thresh=0.7): else: tmp1 = cbfts[:, :, :, s] CC[s] = np.corrcoef(R[mask1 > 0], tmp1[mask1 > 0])[0][1] + inx = np.argmax(CC) indx[inx] = 2 R = np.mean(cbfts[:, :, :, indx == 0], axis=3) - V = nogm * np.var(R[gm == 1]) + nowm * np.var(R[wm == 1]) + nocf * np.var(R[csf == 1]) + V = ( + n_gm_voxels * np.var(R[gm == 1]) + + n_wm_voxels * np.var(R[wm == 1]) + + n_csf_voxels * np.var(R[csf == 1]) + ) cbfts_recon = cbfts[:, :, :, indx == 0] cbfts_recon1 = np.zeros_like(cbfts_recon) for i in range(cbfts_recon.shape[3]): cbfts_recon1[:, :, :, i] = cbfts_recon[:, :, :, i] * mask + cbfts_recon1 = np.nan_to_num(cbfts_recon1) return cbfts_recon1, indx @@ -640,7 +648,7 @@ def _scrubcbf(cbf_ts, gm, wm, csf, mask, wfun="huber", thresh=0.7): ---------- cbf_ts nd array of 3D or 4D computed cbf - gm,wm,csf + gm,wm,csf numpy array of grey matter, whitematter, and csf mask numpy array of mask @@ -648,18 +656,21 @@ def _scrubcbf(cbf_ts, gm, wm, csf, mask, wfun="huber", thresh=0.7): wave function """ gm = mask * gm - wm = mask * wm - csf = csf * mask gmidx = gm[mask == 1] gmidx[gmidx < thresh] = 0 gmidx[gmidx > 0] = 1 + + wm = mask * wm wmidx = wm[mask == 1] wmidx[wmidx < thresh] = 0 wmidx[wmidx > 0] = 1 + + csf = csf * mask csfidx = csf[mask == 1] csfidx[csfidx < thresh] = 0 csfidx[csfidx > 0] = 1 # midx = mask[mask==1] + meancbf = np.mean(cbf_ts, axis=3) y = np.transpose( cbf_ts[ From 3905c7d30775cbd0437c3905eaf5c2d38aa94dc9 Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Sun, 2 Apr 2023 13:01:32 -0400 Subject: [PATCH 28/43] Update expected outputs. --- ...ected_outputs_examples_pcasl_singlepld.txt | 134 ++++++++++++------ ...ed_outputs_examples_pcasl_singlepld_ge.txt | 47 ++++++ 2 files changed, 137 insertions(+), 44 deletions(-) create mode 100644 aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_ge.txt diff --git a/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld.txt b/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld.txt index 06fa14369..71af43e35 100644 --- a/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld.txt +++ b/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld.txt @@ -1,46 +1,92 @@ aslprep/logs aslprep/sub-103 -aslprep/sub-103/perf -aslprep/sub-103/perf/sub-103_aslref.nii.gz -aslprep/sub-103/perf/sub-103_cbf.nii.gz -aslprep/sub-103/perf/sub-103_atlas-HarvardOxford_desc-mean_basil.csv -aslprep/sub-103/perf/sub-103_atlas-HarvardOxford_desc-mean_cbf.csv -aslprep/sub-103/perf/sub-103_atlas-HarvardOxford_desc-mean_pvc.csv -aslprep/sub-103/perf/sub-103_atlas-HarvardOxford_desc-mean_score.csv -aslprep/sub-103/perf/sub-103_atlas-HarvardOxford_desc-mean_scrub.csv -aslprep/sub-103/perf/sub-103_desc-basil_cbf.nii.gz -aslprep/sub-103/perf/sub-103_desc-bat_cbf.nii.gz -aslprep/sub-103/perf/sub-103_desc-brain_mask.json -aslprep/sub-103/perf/sub-103_desc-brain_mask.nii.gz -aslprep/sub-103/perf/sub-103_desc-confounds_regressors.tsv -aslprep/sub-103/perf/sub-103_desc-preproc_asl.json -aslprep/sub-103/perf/sub-103_desc-preproc_asl.nii.gz -aslprep/sub-103/perf/sub-103_desc-pvGM_cbf.nii.gz -aslprep/sub-103/perf/sub-103_desc-pvWM_cbf.nii.gz -aslprep/sub-103/perf/sub-103_desc-qualitycontrol_cbf.csv -aslprep/sub-103/perf/sub-103_atlas-schaefer200x17_desc-mean_basil.csv -aslprep/sub-103/perf/sub-103_atlas-schaefer200x17_desc-mean_cbf.csv -aslprep/sub-103/perf/sub-103_atlas-schaefer200x17_desc-mean_pvc.csv -aslprep/sub-103/perf/sub-103_atlas-schaefer200x17_desc-mean_score.csv -aslprep/sub-103/perf/sub-103_atlas-schaefer200x17_desc-mean_scrub.csv -aslprep/sub-103/perf/sub-103_atlas-schaefer200x7_desc-mean_basil.csv -aslprep/sub-103/perf/sub-103_atlas-schaefer200x7_desc-mean_cbf.csv -aslprep/sub-103/perf/sub-103_atlas-schaefer200x7_desc-mean_pvc.csv -aslprep/sub-103/perf/sub-103_atlas-schaefer200x7_desc-mean_score.csv -aslprep/sub-103/perf/sub-103_atlas-schaefer200x7_desc-mean_scrub.csv -aslprep/sub-103/perf/sub-103_atlas-schaefer400x17_desc-mean_basil.csv -aslprep/sub-103/perf/sub-103_atlas-schaefer400x17_desc-mean_cbf.csv -aslprep/sub-103/perf/sub-103_atlas-schaefer400x17_desc-mean_pvc.csv -aslprep/sub-103/perf/sub-103_atlas-schaefer400x17_desc-mean_score.csv -aslprep/sub-103/perf/sub-103_atlas-schaefer400x17_desc-mean_scrub.csv -aslprep/sub-103/perf/sub-103_atlas-schaefer400x7_desc-mean_basil.csv -aslprep/sub-103/perf/sub-103_atlas-schaefer400x7_desc-mean_cbf.csv -aslprep/sub-103/perf/sub-103_atlas-schaefer400x7_desc-mean_pvc.csv -aslprep/sub-103/perf/sub-103_atlas-schaefer400x7_desc-mean_score.csv -aslprep/sub-103/perf/sub-103_atlas-schaefer400x7_desc-mean_scrub.csv -aslprep/sub-103/perf/sub-103_desc-score_cbf.nii.gz -aslprep/sub-103/perf/sub-103_desc-meanScore_cbf.nii.gz -aslprep/sub-103/perf/sub-103_desc-scrub_cbf.nii.gz -aslprep/sub-103/perf/sub-103_from-T1w_to-scanner_mode-image_xfm.txt -aslprep/sub-103/perf/sub-103_from-scanner_to-T1w_mode-image_xfm.txt -aslprep/sub-103/perf/sub-103_desc-mean_cbf.nii.gz +aslprep/sub-103/ses-philips2d +aslprep/sub-103/ses-philips2d/perf +aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_aslref.nii.gz +aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_atlas-HarvardOxford_desc-mean_basil.csv +aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_atlas-HarvardOxford_desc-mean_cbf.csv +aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_atlas-HarvardOxford_desc-mean_pvc.csv +aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_atlas-HarvardOxford_desc-mean_score.csv +aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_atlas-HarvardOxford_desc-mean_scrub.csv +aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_atlas-schaefer200x17_desc-mean_basil.csv +aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_atlas-schaefer200x17_desc-mean_cbf.csv +aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_atlas-schaefer200x17_desc-mean_pvc.csv +aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_atlas-schaefer200x17_desc-mean_score.csv +aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_atlas-schaefer200x17_desc-mean_scrub.csv +aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_atlas-schaefer200x7_desc-mean_basil.csv +aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_atlas-schaefer200x7_desc-mean_cbf.csv +aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_atlas-schaefer200x7_desc-mean_pvc.csv +aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_atlas-schaefer200x7_desc-mean_score.csv +aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_atlas-schaefer200x7_desc-mean_scrub.csv +aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_atlas-schaefer400x17_desc-mean_basil.csv +aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_atlas-schaefer400x17_desc-mean_cbf.csv +aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_atlas-schaefer400x17_desc-mean_pvc.csv +aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_atlas-schaefer400x17_desc-mean_score.csv +aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_atlas-schaefer400x17_desc-mean_scrub.csv +aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_atlas-schaefer400x7_desc-mean_basil.csv +aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_atlas-schaefer400x7_desc-mean_cbf.csv +aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_atlas-schaefer400x7_desc-mean_pvc.csv +aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_atlas-schaefer400x7_desc-mean_score.csv +aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_atlas-schaefer400x7_desc-mean_scrub.csv +aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_cbf.nii.gz +aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_desc-basil_cbf.nii.gz +aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_desc-bat_cbf.nii.gz +aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_desc-brain_mask.json +aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_desc-brain_mask.nii.gz +aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_desc-confounds_regressors.tsv +aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_desc-meanScore_cbf.nii.gz +aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_desc-mean_cbf.nii.gz +aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_desc-preproc_asl.json +aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_desc-preproc_asl.nii.gz +aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_desc-pvGM_cbf.nii.gz +aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_desc-pvWM_cbf.nii.gz +aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_desc-qualitycontrol_cbf.csv +aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_desc-score_cbf.nii.gz +aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_desc-scrub_cbf.nii.gz +aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_from-T1w_to-scanner_mode-image_xfm.txt +aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_from-scanner_to-T1w_mode-image_xfm.txt +aslprep/sub-103/ses-siemens3d +aslprep/sub-103/ses-siemens3d/perf +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_aslref.nii.gz +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-HarvardOxford_desc-mean_basil.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-HarvardOxford_desc-mean_cbf.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-HarvardOxford_desc-mean_pvc.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-HarvardOxford_desc-mean_score.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-HarvardOxford_desc-mean_scrub.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer200x17_desc-mean_basil.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer200x17_desc-mean_cbf.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer200x17_desc-mean_pvc.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer200x17_desc-mean_score.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer200x17_desc-mean_scrub.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer200x7_desc-mean_basil.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer200x7_desc-mean_cbf.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer200x7_desc-mean_pvc.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer200x7_desc-mean_score.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer200x7_desc-mean_scrub.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer400x17_desc-mean_basil.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer400x17_desc-mean_cbf.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer400x17_desc-mean_pvc.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer400x17_desc-mean_score.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer400x17_desc-mean_scrub.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer400x7_desc-mean_basil.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer400x7_desc-mean_cbf.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer400x7_desc-mean_pvc.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer400x7_desc-mean_score.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer400x7_desc-mean_scrub.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_cbf.nii.gz +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_desc-basil_cbf.nii.gz +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_desc-bat_cbf.nii.gz +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_desc-brain_mask.json +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_desc-brain_mask.nii.gz +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_desc-confounds_regressors.tsv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_desc-meanScore_cbf.nii.gz +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_desc-mean_cbf.nii.gz +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_desc-preproc_asl.json +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_desc-preproc_asl.nii.gz +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_desc-pvGM_cbf.nii.gz +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_desc-pvWM_cbf.nii.gz +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_desc-qualitycontrol_cbf.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_desc-score_cbf.nii.gz +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_desc-scrub_cbf.nii.gz +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_from-T1w_to-scanner_mode-image_xfm.txt +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_from-scanner_to-T1w_mode-image_xfm.txt diff --git a/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_ge.txt b/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_ge.txt new file mode 100644 index 000000000..12b7df3fd --- /dev/null +++ b/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_ge.txt @@ -0,0 +1,47 @@ +aslprep/logs +aslprep/sub-103 +aslprep/sub-103/ses-ge3d +aslprep/sub-103/ses-ge3d/perf +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_aslref.nii.gz +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-HarvardOxford_desc-mean_basil.csv +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-HarvardOxford_desc-mean_cbf.csv +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-HarvardOxford_desc-mean_pvc.csv +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-HarvardOxford_desc-mean_score.csv +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-HarvardOxford_desc-mean_scrub.csv +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer200x17_desc-mean_basil.csv +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer200x17_desc-mean_cbf.csv +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer200x17_desc-mean_pvc.csv +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer200x17_desc-mean_score.csv +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer200x17_desc-mean_scrub.csv +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer200x7_desc-mean_basil.csv +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer200x7_desc-mean_cbf.csv +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer200x7_desc-mean_pvc.csv +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer200x7_desc-mean_score.csv +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer200x7_desc-mean_scrub.csv +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer400x17_desc-mean_basil.csv +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer400x17_desc-mean_cbf.csv +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer400x17_desc-mean_pvc.csv +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer400x17_desc-mean_score.csv +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer400x17_desc-mean_scrub.csv +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer400x7_desc-mean_basil.csv +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer400x7_desc-mean_cbf.csv +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer400x7_desc-mean_pvc.csv +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer400x7_desc-mean_score.csv +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer400x7_desc-mean_scrub.csv +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_cbf.nii.gz +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_desc-basil_cbf.nii.gz +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_desc-bat_cbf.nii.gz +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_desc-brain_mask.json +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_desc-brain_mask.nii.gz +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_desc-confounds_regressors.tsv +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_desc-meanScore_cbf.nii.gz +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_desc-mean_cbf.nii.gz +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_desc-preproc_asl.json +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_desc-preproc_asl.nii.gz +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_desc-pvGM_cbf.nii.gz +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_desc-pvWM_cbf.nii.gz +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_desc-qualitycontrol_cbf.csv +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_desc-score_cbf.nii.gz +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_desc-scrub_cbf.nii.gz +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_from-T1w_to-scanner_mode-image_xfm.txt +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_from-scanner_to-T1w_mode-image_xfm.txt From cd0571a4fc21118463412fee253df03c7a22ca37 Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Sun, 2 Apr 2023 14:18:09 -0400 Subject: [PATCH 29/43] Update test_cli.py --- aslprep/tests/test_cli.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/aslprep/tests/test_cli.py b/aslprep/tests/test_cli.py index 84d5a20c6..c2fabfa13 100644 --- a/aslprep/tests/test_cli.py +++ b/aslprep/tests/test_cli.py @@ -3,6 +3,7 @@ import pytest from nipype import config as nipype_config +from nipype.pipeline.engine.nodes import NodeExecutionError from aslprep.cli.parser import parse_args from aslprep.cli.workflow import build_workflow @@ -126,7 +127,7 @@ def test_examples_pcasl_multipld(datasets, output_dir, working_dir): retval = {} retval = build_workflow(config_file, retval=retval) aslprep_wf = retval.get("workflow", None) - with pytest.raises(ValueError, match="ASLPrep cannot currently process multi-PLD data."): + with pytest.raises(NodeExecutionError, match="cannot currently process multi-PLD data."): aslprep_wf.run() output_list_file = os.path.join(test_data_dir, "expected_outputs_examples_pcasl_multipld.txt") @@ -165,7 +166,7 @@ def test_examples_pasl_multipld(datasets, output_dir, working_dir): retval = {} retval = build_workflow(config_file, retval=retval) aslprep_wf = retval.get("workflow", None) - with pytest.raises(ValueError, match="ASLPrep cannot currently process multi-PLD data."): + with pytest.raises(NodeExecutionError, match="cannot currently process multi-PLD data."): aslprep_wf.run() output_list_file = os.path.join(test_data_dir, "expected_outputs_examples_pasl_multipld.txt") From ec8718ba7b5da05e9b89704c1c8b8d6fb47c8ddd Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Mon, 3 Apr 2023 09:20:43 -0400 Subject: [PATCH 30/43] Document tests. --- aslprep/tests/test_cli.py | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/aslprep/tests/test_cli.py b/aslprep/tests/test_cli.py index c2fabfa13..27184bfc8 100644 --- a/aslprep/tests/test_cli.py +++ b/aslprep/tests/test_cli.py @@ -14,7 +14,10 @@ @pytest.mark.examples_pcasl_singlepld def test_examples_pcasl_singlepld(datasets, output_dir, working_dir): - """Run aslprep on sub-01 data.""" + """Run aslprep on the asl_002 and asl_005 ASL-BIDS examples datasets. + + This test uses two ASL sessions: one on a Siemens and one on a Philips. + """ from aslprep import config test_name = "examples_pcasl_singlepld" @@ -54,7 +57,10 @@ def test_examples_pcasl_singlepld(datasets, output_dir, working_dir): @pytest.mark.examples_pcasl_singlepld_ge def test_examples_pcasl_singlepld_ge(datasets, output_dir, working_dir): - """Run aslprep on sub-01 data.""" + """Run aslprep on the asl_001 ASL-BIDS examples dataset. + + This test uses a GE session with two volumes: one deltam and one M0. + """ from aslprep import config test_name = "examples_pcasl_singlepld_ge" @@ -97,14 +103,19 @@ def test_examples_pcasl_singlepld_ge(datasets, output_dir, working_dir): @pytest.mark.examples_pcasl_multipld def test_examples_pcasl_multipld(datasets, output_dir, working_dir): - """Run aslprep on sub-01 data.""" + """Run aslprep on the asl_004 ASL-BIDS examples dataset. + + This dataset has 48 control-label pairs at 6 different PLDs, along with a separate M0 scan. + + NOTE: MultiPLD is not currently working, so we expect the workflow to fail. + """ from aslprep import config test_name = "examples_pcasl_multipld" data_dir = datasets[test_name] out_dir = os.path.join(output_dir, test_name) work_dir = os.path.join(working_dir, test_name) - test_data_dir = get_test_data_path() + # test_data_dir = get_test_data_path() parameters = [ data_dir, @@ -130,20 +141,28 @@ def test_examples_pcasl_multipld(datasets, output_dir, working_dir): with pytest.raises(NodeExecutionError, match="cannot currently process multi-PLD data."): aslprep_wf.run() - output_list_file = os.path.join(test_data_dir, "expected_outputs_examples_pcasl_multipld.txt") - check_generated_files(out_dir, output_list_file) + # output_list_file = os.path.join( + # test_data_dir, "expected_outputs_examples_pcasl_multipld.txt" + # ) + # check_generated_files(out_dir, output_list_file) @pytest.mark.examples_pasl_multipld def test_examples_pasl_multipld(datasets, output_dir, working_dir): - """Run aslprep on sub-01 data.""" + """Run aslprep on the asl_003 ASL-BIDS examples dataset. + + This dataset has 10 control-label pairs at 10 different PLDs, along with a separate M0 scan. + The BolusCutOffTechnique is Q2TIPS. + + NOTE: MultiPLD is not currently working, so we expect the workflow to fail. + """ from aslprep import config test_name = "examples_pasl_multipld" data_dir = datasets[test_name] out_dir = os.path.join(output_dir, test_name) work_dir = os.path.join(working_dir, test_name) - test_data_dir = get_test_data_path() + # test_data_dir = get_test_data_path() parameters = [ data_dir, @@ -169,8 +188,8 @@ def test_examples_pasl_multipld(datasets, output_dir, working_dir): with pytest.raises(NodeExecutionError, match="cannot currently process multi-PLD data."): aslprep_wf.run() - output_list_file = os.path.join(test_data_dir, "expected_outputs_examples_pasl_multipld.txt") - check_generated_files(out_dir, output_list_file) + # output_list_file = os.path.join(test_data_dir, "expected_outputs_examples_pasl_multipld.txt") + # check_generated_files(out_dir, output_list_file) @pytest.mark.test_001 From a76d71dec6aa1bb1ae1d2d271e1f0f2189cc004c Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Mon, 3 Apr 2023 10:27:55 -0400 Subject: [PATCH 31/43] Disable SCORE/SCRUB for GE data. --- aslprep/utils/misc.py | 8 +++++--- aslprep/workflows/asl/gecbf.py | 4 ++++ aslprep/workflows/base.py | 21 +++++++++++++++++---- 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/aslprep/utils/misc.py b/aslprep/utils/misc.py index 7d2a8b81e..16df8785f 100644 --- a/aslprep/utils/misc.py +++ b/aslprep/utils/misc.py @@ -11,6 +11,8 @@ from pkg_resources import resource_filename as pkgrf from scipy.stats import median_abs_deviation +from aslprep import config + def check_deps(workflow): """Make sure dependencies are present in this system.""" @@ -568,9 +570,9 @@ def _getcbfscore(cbfts, wm, gm, csf, mask, thresh=0.7): indx[inx] = 2 R = np.mean(cbfts[:, :, :, indx == 0], axis=3) V = ( - n_gm_voxels * np.var(R[gm == 1]) - + n_wm_voxels * np.var(R[wm == 1]) - + n_csf_voxels * np.var(R[csf == 1]) + (n_gm_voxels * np.var(R[gm == 1])) + + (n_wm_voxels * np.var(R[wm == 1])) + + (n_csf_voxels * np.var(R[csf == 1])) ) cbfts_recon = cbfts[:, :, :, indx == 0] cbfts_recon1 = np.zeros_like(cbfts_recon) diff --git a/aslprep/workflows/asl/gecbf.py b/aslprep/workflows/asl/gecbf.py index 36b2499f3..c3a1b8d26 100644 --- a/aslprep/workflows/asl/gecbf.py +++ b/aslprep/workflows/asl/gecbf.py @@ -165,6 +165,10 @@ def init_asl_gepreproc_wf(asl_file): basil = config.workflow.basil smoothkernel = config.workflow.smooth_kernel + if scorescrub: + config.loggers.warning(f"SCORE/SCRUB processing will be disabled for {asl_file}") + scorescrub = False + ref_file = asl_file asl_tlen, mem_gb = _create_mem_gb(ref_file) diff --git a/aslprep/workflows/base.py b/aslprep/workflows/base.py index 233f6a86c..c261e178f 100644 --- a/aslprep/workflows/base.py +++ b/aslprep/workflows/base.py @@ -108,12 +108,12 @@ def init_single_subject_wf(subject_id): """ name = f"single_subject_{subject_id}_wf" - subject_data = collect_data( + subject_data, layout = collect_data( config.execution.bids_dir, subject_id, echo=config.execution.echo_idx, bids_filters=config.execution.bids_filters, - )[0] + ) if "flair" in config.workflow.ignore: subject_data["flair"] = [] @@ -131,7 +131,7 @@ def init_single_subject_wf(subject_id): ) if not subject_data["t1w"]: - raise Exception( + raise RuntimeError( f"No T1w images found for participant {subject_id}. " "All workflows require T1w images." ) @@ -311,8 +311,21 @@ def init_single_subject_wf(subject_id): # If number of volume of ASL is less than 5, motion correction, # slice-timing correction, etc. will be skipped. + metadata = layout.get_metadata(asl_file) n_vols = get_n_volumes(asl_file) - asl_preproc_func = init_asl_preproc_wf if n_vols > 5 else init_asl_gepreproc_wf + use_ge = False + if metadata.get("Manufacturer") == "GE": + config.loggers.workflow.warning( + "ASL file is acquired with a GE scanner. Using GE-specific processing." + ) + use_ge = True + elif n_vols <= 5: + config.loggers.workflow.warning( + f"ASL file is very short ({n_vols} volumes). Using GE-specific processing." + ) + use_ge = True + + asl_preproc_func = init_asl_preproc_wf if use_ge else init_asl_gepreproc_wf asl_preproc_wf = asl_preproc_func(asl_file) # fmt:off From 6e4047169c1b5f2e605fbd5ecad0ac650de1b787 Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Mon, 3 Apr 2023 10:29:27 -0400 Subject: [PATCH 32/43] Update expected outputs for GE scans. --- ...expected_outputs_examples_pcasl_singlepld_ge.txt | 13 ------------- aslprep/tests/data/expected_outputs_test_002.txt | 13 ------------- 2 files changed, 26 deletions(-) diff --git a/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_ge.txt b/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_ge.txt index 12b7df3fd..402411ea7 100644 --- a/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_ge.txt +++ b/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_ge.txt @@ -6,42 +6,29 @@ aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_aslref.nii.gz aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-HarvardOxford_desc-mean_basil.csv aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-HarvardOxford_desc-mean_cbf.csv aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-HarvardOxford_desc-mean_pvc.csv -aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-HarvardOxford_desc-mean_score.csv -aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-HarvardOxford_desc-mean_scrub.csv aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer200x17_desc-mean_basil.csv aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer200x17_desc-mean_cbf.csv aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer200x17_desc-mean_pvc.csv -aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer200x17_desc-mean_score.csv -aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer200x17_desc-mean_scrub.csv aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer200x7_desc-mean_basil.csv aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer200x7_desc-mean_cbf.csv aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer200x7_desc-mean_pvc.csv -aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer200x7_desc-mean_score.csv -aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer200x7_desc-mean_scrub.csv aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer400x17_desc-mean_basil.csv aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer400x17_desc-mean_cbf.csv aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer400x17_desc-mean_pvc.csv -aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer400x17_desc-mean_score.csv -aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer400x17_desc-mean_scrub.csv aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer400x7_desc-mean_basil.csv aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer400x7_desc-mean_cbf.csv aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer400x7_desc-mean_pvc.csv -aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer400x7_desc-mean_score.csv -aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer400x7_desc-mean_scrub.csv aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_cbf.nii.gz aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_desc-basil_cbf.nii.gz aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_desc-bat_cbf.nii.gz aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_desc-brain_mask.json aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_desc-brain_mask.nii.gz aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_desc-confounds_regressors.tsv -aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_desc-meanScore_cbf.nii.gz aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_desc-mean_cbf.nii.gz aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_desc-preproc_asl.json aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_desc-preproc_asl.nii.gz aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_desc-pvGM_cbf.nii.gz aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_desc-pvWM_cbf.nii.gz aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_desc-qualitycontrol_cbf.csv -aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_desc-score_cbf.nii.gz -aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_desc-scrub_cbf.nii.gz aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_from-T1w_to-scanner_mode-image_xfm.txt aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_from-scanner_to-T1w_mode-image_xfm.txt diff --git a/aslprep/tests/data/expected_outputs_test_002.txt b/aslprep/tests/data/expected_outputs_test_002.txt index 2f88441f3..78c499b9c 100644 --- a/aslprep/tests/data/expected_outputs_test_002.txt +++ b/aslprep/tests/data/expected_outputs_test_002.txt @@ -6,8 +6,6 @@ aslprep/sub-10R01383/perf/sub-10R01383_cbf.nii.gz aslprep/sub-10R01383/perf/sub-10R01383_atlas-HarvardOxford_desc-mean_basil.csv aslprep/sub-10R01383/perf/sub-10R01383_atlas-HarvardOxford_desc-mean_cbf.csv aslprep/sub-10R01383/perf/sub-10R01383_atlas-HarvardOxford_desc-mean_pvc.csv -aslprep/sub-10R01383/perf/sub-10R01383_atlas-HarvardOxford_desc-mean_score.csv -aslprep/sub-10R01383/perf/sub-10R01383_atlas-HarvardOxford_desc-mean_scrub.csv aslprep/sub-10R01383/perf/sub-10R01383_desc-basil_cbf.nii.gz aslprep/sub-10R01383/perf/sub-10R01383_desc-bat_cbf.nii.gz aslprep/sub-10R01383/perf/sub-10R01383_desc-brain_mask.json @@ -21,26 +19,15 @@ aslprep/sub-10R01383/perf/sub-10R01383_desc-qualitycontrol_cbf.csv aslprep/sub-10R01383/perf/sub-10R01383_atlas-schaefer200x17_desc-mean_basil.csv aslprep/sub-10R01383/perf/sub-10R01383_atlas-schaefer200x17_desc-mean_cbf.csv aslprep/sub-10R01383/perf/sub-10R01383_atlas-schaefer200x17_desc-mean_pvc.csv -aslprep/sub-10R01383/perf/sub-10R01383_atlas-schaefer200x17_desc-mean_score.csv -aslprep/sub-10R01383/perf/sub-10R01383_atlas-schaefer200x17_desc-mean_scrub.csv aslprep/sub-10R01383/perf/sub-10R01383_atlas-schaefer200x7_desc-mean_basil.csv aslprep/sub-10R01383/perf/sub-10R01383_atlas-schaefer200x7_desc-mean_cbf.csv aslprep/sub-10R01383/perf/sub-10R01383_atlas-schaefer200x7_desc-mean_pvc.csv -aslprep/sub-10R01383/perf/sub-10R01383_atlas-schaefer200x7_desc-mean_score.csv -aslprep/sub-10R01383/perf/sub-10R01383_atlas-schaefer200x7_desc-mean_scrub.csv aslprep/sub-10R01383/perf/sub-10R01383_atlas-schaefer400x17_desc-mean_basil.csv aslprep/sub-10R01383/perf/sub-10R01383_atlas-schaefer400x17_desc-mean_cbf.csv aslprep/sub-10R01383/perf/sub-10R01383_atlas-schaefer400x17_desc-mean_pvc.csv -aslprep/sub-10R01383/perf/sub-10R01383_atlas-schaefer400x17_desc-mean_score.csv -aslprep/sub-10R01383/perf/sub-10R01383_atlas-schaefer400x17_desc-mean_scrub.csv aslprep/sub-10R01383/perf/sub-10R01383_atlas-schaefer400x7_desc-mean_basil.csv aslprep/sub-10R01383/perf/sub-10R01383_atlas-schaefer400x7_desc-mean_cbf.csv aslprep/sub-10R01383/perf/sub-10R01383_atlas-schaefer400x7_desc-mean_pvc.csv -aslprep/sub-10R01383/perf/sub-10R01383_atlas-schaefer400x7_desc-mean_score.csv -aslprep/sub-10R01383/perf/sub-10R01383_atlas-schaefer400x7_desc-mean_scrub.csv -aslprep/sub-10R01383/perf/sub-10R01383_desc-score_cbf.nii.gz -aslprep/sub-10R01383/perf/sub-10R01383_desc-meanScore_cbf.nii.gz -aslprep/sub-10R01383/perf/sub-10R01383_desc-scrub_cbf.nii.gz aslprep/sub-10R01383/perf/sub-10R01383_from-T1w_to-scanner_mode-image_xfm.txt aslprep/sub-10R01383/perf/sub-10R01383_from-scanner_to-T1w_mode-image_xfm.txt aslprep/sub-10R01383/perf/sub-10R01383_desc-mean_cbf.nii.gz From ebd46b309a27f7433d368a15ade1ede9a8142903 Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Mon, 3 Apr 2023 10:31:59 -0400 Subject: [PATCH 33/43] Remove unused import. --- aslprep/utils/misc.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/aslprep/utils/misc.py b/aslprep/utils/misc.py index 16df8785f..5cdd7a262 100644 --- a/aslprep/utils/misc.py +++ b/aslprep/utils/misc.py @@ -11,8 +11,6 @@ from pkg_resources import resource_filename as pkgrf from scipy.stats import median_abs_deviation -from aslprep import config - def check_deps(workflow): """Make sure dependencies are present in this system.""" From 220963c79590bc34ab0f93e2dc947bcddcfba0c4 Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Mon, 3 Apr 2023 10:50:17 -0400 Subject: [PATCH 34/43] Update gecbf.py --- aslprep/workflows/asl/gecbf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aslprep/workflows/asl/gecbf.py b/aslprep/workflows/asl/gecbf.py index c3a1b8d26..19a6e8f34 100644 --- a/aslprep/workflows/asl/gecbf.py +++ b/aslprep/workflows/asl/gecbf.py @@ -166,7 +166,7 @@ def init_asl_gepreproc_wf(asl_file): smoothkernel = config.workflow.smooth_kernel if scorescrub: - config.loggers.warning(f"SCORE/SCRUB processing will be disabled for {asl_file}") + config.loggers.workflow.warning(f"SCORE/SCRUB processing will be disabled for {asl_file}") scorescrub = False ref_file = asl_file From b1de1d7c950bd26ed2dcb7d04891f9cd54b82b93 Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Mon, 3 Apr 2023 11:21:49 -0400 Subject: [PATCH 35/43] I had the workflows swapped. --- aslprep/workflows/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aslprep/workflows/base.py b/aslprep/workflows/base.py index c261e178f..a4d4fb77d 100644 --- a/aslprep/workflows/base.py +++ b/aslprep/workflows/base.py @@ -325,7 +325,7 @@ def init_single_subject_wf(subject_id): ) use_ge = True - asl_preproc_func = init_asl_preproc_wf if use_ge else init_asl_gepreproc_wf + asl_preproc_func = init_asl_gepreproc_wf if use_ge else init_asl_preproc_wf asl_preproc_wf = asl_preproc_func(asl_file) # fmt:off From a9d40c0880abdc4df726dc3a5f50a0aed93937b3 Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Mon, 3 Apr 2023 12:01:14 -0400 Subject: [PATCH 36/43] Update expected_outputs_examples_pcasl_singlepld_ge.txt --- ...ed_outputs_examples_pcasl_singlepld_ge.txt | 60 +++++++++---------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_ge.txt b/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_ge.txt index 402411ea7..5c83c2929 100644 --- a/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_ge.txt +++ b/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_ge.txt @@ -2,33 +2,33 @@ aslprep/logs aslprep/sub-103 aslprep/sub-103/ses-ge3d aslprep/sub-103/ses-ge3d/perf -aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_aslref.nii.gz -aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-HarvardOxford_desc-mean_basil.csv -aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-HarvardOxford_desc-mean_cbf.csv -aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-HarvardOxford_desc-mean_pvc.csv -aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer200x17_desc-mean_basil.csv -aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer200x17_desc-mean_cbf.csv -aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer200x17_desc-mean_pvc.csv -aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer200x7_desc-mean_basil.csv -aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer200x7_desc-mean_cbf.csv -aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer200x7_desc-mean_pvc.csv -aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer400x17_desc-mean_basil.csv -aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer400x17_desc-mean_cbf.csv -aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer400x17_desc-mean_pvc.csv -aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer400x7_desc-mean_basil.csv -aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer400x7_desc-mean_cbf.csv -aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_atlas-schaefer400x7_desc-mean_pvc.csv -aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_cbf.nii.gz -aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_desc-basil_cbf.nii.gz -aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_desc-bat_cbf.nii.gz -aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_desc-brain_mask.json -aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_desc-brain_mask.nii.gz -aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_desc-confounds_regressors.tsv -aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_desc-mean_cbf.nii.gz -aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_desc-preproc_asl.json -aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_desc-preproc_asl.nii.gz -aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_desc-pvGM_cbf.nii.gz -aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_desc-pvWM_cbf.nii.gz -aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_desc-qualitycontrol_cbf.csv -aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_from-T1w_to-scanner_mode-image_xfm.txt -aslprep/sub-103/ses-ge3d/perf/sub-103_ses-philips2d_from-scanner_to-T1w_mode-image_xfm.txt +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-ge3d_aslref.nii.gz +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-ge3d_atlas-HarvardOxford_desc-mean_basil.csv +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-ge3d_atlas-HarvardOxford_desc-mean_cbf.csv +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-ge3d_atlas-HarvardOxford_desc-mean_pvc.csv +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-ge3d_atlas-schaefer200x17_desc-mean_basil.csv +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-ge3d_atlas-schaefer200x17_desc-mean_cbf.csv +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-ge3d_atlas-schaefer200x17_desc-mean_pvc.csv +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-ge3d_atlas-schaefer200x7_desc-mean_basil.csv +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-ge3d_atlas-schaefer200x7_desc-mean_cbf.csv +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-ge3d_atlas-schaefer200x7_desc-mean_pvc.csv +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-ge3d_atlas-schaefer400x17_desc-mean_basil.csv +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-ge3d_atlas-schaefer400x17_desc-mean_cbf.csv +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-ge3d_atlas-schaefer400x17_desc-mean_pvc.csv +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-ge3d_atlas-schaefer400x7_desc-mean_basil.csv +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-ge3d_atlas-schaefer400x7_desc-mean_cbf.csv +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-ge3d_atlas-schaefer400x7_desc-mean_pvc.csv +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-ge3d_cbf.nii.gz +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-ge3d_desc-basil_cbf.nii.gz +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-ge3d_desc-bat_cbf.nii.gz +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-ge3d_desc-brain_mask.json +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-ge3d_desc-brain_mask.nii.gz +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-ge3d_desc-confounds_regressors.tsv +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-ge3d_desc-mean_cbf.nii.gz +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-ge3d_desc-preproc_asl.json +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-ge3d_desc-preproc_asl.nii.gz +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-ge3d_desc-pvGM_cbf.nii.gz +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-ge3d_desc-pvWM_cbf.nii.gz +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-ge3d_desc-qualitycontrol_cbf.csv +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-ge3d_from-T1w_to-scanner_mode-image_xfm.txt +aslprep/sub-103/ses-ge3d/perf/sub-103_ses-ge3d_from-scanner_to-T1w_mode-image_xfm.txt From a51216b79a90a75c26fee07521e6dd92c947c2f1 Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Mon, 3 Apr 2023 12:02:35 -0400 Subject: [PATCH 37/43] I guess we don't get confound regressors with GE? --- .../tests/data/expected_outputs_examples_pcasl_singlepld_ge.txt | 1 - aslprep/tests/data/expected_outputs_test_002.txt | 1 - 2 files changed, 2 deletions(-) diff --git a/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_ge.txt b/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_ge.txt index 5c83c2929..f3ede5a9c 100644 --- a/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_ge.txt +++ b/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_ge.txt @@ -23,7 +23,6 @@ aslprep/sub-103/ses-ge3d/perf/sub-103_ses-ge3d_desc-basil_cbf.nii.gz aslprep/sub-103/ses-ge3d/perf/sub-103_ses-ge3d_desc-bat_cbf.nii.gz aslprep/sub-103/ses-ge3d/perf/sub-103_ses-ge3d_desc-brain_mask.json aslprep/sub-103/ses-ge3d/perf/sub-103_ses-ge3d_desc-brain_mask.nii.gz -aslprep/sub-103/ses-ge3d/perf/sub-103_ses-ge3d_desc-confounds_regressors.tsv aslprep/sub-103/ses-ge3d/perf/sub-103_ses-ge3d_desc-mean_cbf.nii.gz aslprep/sub-103/ses-ge3d/perf/sub-103_ses-ge3d_desc-preproc_asl.json aslprep/sub-103/ses-ge3d/perf/sub-103_ses-ge3d_desc-preproc_asl.nii.gz diff --git a/aslprep/tests/data/expected_outputs_test_002.txt b/aslprep/tests/data/expected_outputs_test_002.txt index 78c499b9c..120adf714 100644 --- a/aslprep/tests/data/expected_outputs_test_002.txt +++ b/aslprep/tests/data/expected_outputs_test_002.txt @@ -10,7 +10,6 @@ aslprep/sub-10R01383/perf/sub-10R01383_desc-basil_cbf.nii.gz aslprep/sub-10R01383/perf/sub-10R01383_desc-bat_cbf.nii.gz aslprep/sub-10R01383/perf/sub-10R01383_desc-brain_mask.json aslprep/sub-10R01383/perf/sub-10R01383_desc-brain_mask.nii.gz -aslprep/sub-10R01383/perf/sub-10R01383_desc-confounds_regressors.tsv aslprep/sub-10R01383/perf/sub-10R01383_desc-preproc_asl.json aslprep/sub-10R01383/perf/sub-10R01383_desc-preproc_asl.nii.gz aslprep/sub-10R01383/perf/sub-10R01383_desc-pvGM_cbf.nii.gz From d73c642739888b8aefa7c4252771f5662f3f75d2 Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Mon, 3 Apr 2023 13:12:11 -0400 Subject: [PATCH 38/43] Split up pcasl singlepld test. --- .circleci/config.yml | 63 +++++++-- .../data/examples_pcasl_singlepld_filter.json | 5 - ...amples_pcasl_singlepld_filter_philips.json | 5 + ...amples_pcasl_singlepld_filter_siemens.json | 5 + ...puts_examples_pcasl_singlepld_philips.txt} | 45 ------ ...tputs_examples_pcasl_singlepld_siemens.txt | 47 +++++++ aslprep/tests/test_cli.py | 131 ++++++++++++------ pyproject.toml | 9 +- 8 files changed, 205 insertions(+), 105 deletions(-) delete mode 100644 aslprep/tests/data/examples_pcasl_singlepld_filter.json create mode 100644 aslprep/tests/data/examples_pcasl_singlepld_filter_philips.json create mode 100644 aslprep/tests/data/examples_pcasl_singlepld_filter_siemens.json rename aslprep/tests/data/{expected_outputs_examples_pcasl_singlepld.txt => expected_outputs_examples_pcasl_singlepld_philips.txt} (50%) create mode 100644 aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_siemens.txt diff --git a/.circleci/config.yml b/.circleci/config.yml index 14a0fc250..c7a2420f4 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -135,7 +135,7 @@ jobs: paths: - /src/aslprep/.circleci/data - pcasl_singlepld: + pcasl_singlepld_philips: <<: *dockersetup steps: - checkout @@ -143,26 +143,55 @@ jobs: name: Check whether build should be skipped command: | cd /src/aslprep - if [[ "$( git log --format=oneline -n 1 $CIRCLE_SHA1 | grep -i -E '\[skip[ _]?examples_pcasl_singlepld\]' )" != "" ]]; then - echo "Skipping examples_pcasl_singlepld build" + if [[ "$( git log --format=oneline -n 1 $CIRCLE_SHA1 | grep -i -E '\[skip[ _]?examples_pcasl_singlepld_philips\]' )" != "" ]]; then + echo "Skipping examples_pcasl_singlepld_philips build" circleci step halt fi - restore_cache: key: examples_pcasl_singlepld-v1 - run: *runinstall - run: - name: Run full aslprep on examples_pcasl_singlepld dataset + name: Run full aslprep on examples_pcasl_singlepld_philips dataset + no_output_timeout: 5h + command: | + pytest -rP -o log_cli=true -m "examples_pcasl_singlepld_philips" --cov-append --cov-report term-missing --cov=aslprep --data_dir=/src/aslprep/.circleci/data --output_dir=/src/aslprep/.circleci/out --working_dir=/src/aslprep/.circleci/work aslprep + mkdir /src/coverage + mv /src/aslprep/.coverage /src/coverage/.coverage.examples_pcasl_singlepld_philips + - store_artifacts: + path: /src/aslprep/.circleci/out + - persist_to_workspace: + root: /src/coverage + paths: + - .coverage.examples_pcasl_singlepld_philips + + pcasl_singlepld_siemens: + <<: *dockersetup + steps: + - checkout + - run: + name: Check whether build should be skipped + command: | + cd /src/aslprep + if [[ "$( git log --format=oneline -n 1 $CIRCLE_SHA1 | grep -i -E '\[skip[ _]?examples_pcasl_singlepld_siemens\]' )" != "" ]]; then + echo "Skipping examples_pcasl_singlepld_siemens build" + circleci step halt + fi + - restore_cache: + key: examples_pcasl_singlepld-v1 + - run: *runinstall + - run: + name: Run full aslprep on examples_pcasl_singlepld_siemens dataset no_output_timeout: 5h command: | - pytest -rP -o log_cli=true -m "examples_pcasl_singlepld" --cov-append --cov-report term-missing --cov=aslprep --data_dir=/src/aslprep/.circleci/data --output_dir=/src/aslprep/.circleci/out --working_dir=/src/aslprep/.circleci/work aslprep + pytest -rP -o log_cli=true -m "examples_pcasl_singlepld_siemens" --cov-append --cov-report term-missing --cov=aslprep --data_dir=/src/aslprep/.circleci/data --output_dir=/src/aslprep/.circleci/out --working_dir=/src/aslprep/.circleci/work aslprep mkdir /src/coverage - mv /src/aslprep/.coverage /src/coverage/.coverage.examples_pcasl_singlepld + mv /src/aslprep/.coverage /src/coverage/.coverage.examples_pcasl_singlepld_siemens - store_artifacts: path: /src/aslprep/.circleci/out - persist_to_workspace: root: /src/coverage paths: - - .coverage.examples_pcasl_singlepld + - .coverage.examples_pcasl_singlepld_siemens pcasl_singlepld_ge: <<: *dockersetup @@ -506,7 +535,19 @@ workflows: tags: only: /.*/ - - pcasl_singlepld: + - pcasl_singlepld_philips: + requires: + - download_pcasl_singlepld + - build + filters: + branches: + ignore: + - /docs?\/.*/ + - /tests?\/.*/ + tags: + only: /.*/ + + - pcasl_singlepld_siemens: requires: - download_pcasl_singlepld - build @@ -606,7 +647,8 @@ workflows: - merge_coverage: requires: - - pcasl_singlepld + - pcasl_singlepld_philips + - pcasl_singlepld_siemens - pcasl_singlepld_ge - pcasl_multipld - pasl_multipld @@ -625,7 +667,8 @@ workflows: - deployable: requires: - build - - pcasl_singlepld + - pcasl_singlepld_philips + - pcasl_singlepld_siemens - pcasl_singlepld_ge - pcasl_multipld - pasl_multipld diff --git a/aslprep/tests/data/examples_pcasl_singlepld_filter.json b/aslprep/tests/data/examples_pcasl_singlepld_filter.json deleted file mode 100644 index d7d17e156..000000000 --- a/aslprep/tests/data/examples_pcasl_singlepld_filter.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "asl": { - "session": ["philips2d", "siemens3d"] - } -} \ No newline at end of file diff --git a/aslprep/tests/data/examples_pcasl_singlepld_filter_philips.json b/aslprep/tests/data/examples_pcasl_singlepld_filter_philips.json new file mode 100644 index 000000000..83c058959 --- /dev/null +++ b/aslprep/tests/data/examples_pcasl_singlepld_filter_philips.json @@ -0,0 +1,5 @@ +{ + "asl": { + "session": ["philips2d"] + } +} \ No newline at end of file diff --git a/aslprep/tests/data/examples_pcasl_singlepld_filter_siemens.json b/aslprep/tests/data/examples_pcasl_singlepld_filter_siemens.json new file mode 100644 index 000000000..5ebc8e7ac --- /dev/null +++ b/aslprep/tests/data/examples_pcasl_singlepld_filter_siemens.json @@ -0,0 +1,5 @@ +{ + "asl": { + "session": ["siemens3d"] + } +} \ No newline at end of file diff --git a/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld.txt b/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_philips.txt similarity index 50% rename from aslprep/tests/data/expected_outputs_examples_pcasl_singlepld.txt rename to aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_philips.txt index 71af43e35..4fd79b1fa 100644 --- a/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld.txt +++ b/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_philips.txt @@ -45,48 +45,3 @@ aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_desc-score_cbf.nii.gz aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_desc-scrub_cbf.nii.gz aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_from-T1w_to-scanner_mode-image_xfm.txt aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_from-scanner_to-T1w_mode-image_xfm.txt -aslprep/sub-103/ses-siemens3d -aslprep/sub-103/ses-siemens3d/perf -aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_aslref.nii.gz -aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-HarvardOxford_desc-mean_basil.csv -aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-HarvardOxford_desc-mean_cbf.csv -aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-HarvardOxford_desc-mean_pvc.csv -aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-HarvardOxford_desc-mean_score.csv -aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-HarvardOxford_desc-mean_scrub.csv -aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer200x17_desc-mean_basil.csv -aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer200x17_desc-mean_cbf.csv -aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer200x17_desc-mean_pvc.csv -aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer200x17_desc-mean_score.csv -aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer200x17_desc-mean_scrub.csv -aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer200x7_desc-mean_basil.csv -aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer200x7_desc-mean_cbf.csv -aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer200x7_desc-mean_pvc.csv -aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer200x7_desc-mean_score.csv -aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer200x7_desc-mean_scrub.csv -aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer400x17_desc-mean_basil.csv -aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer400x17_desc-mean_cbf.csv -aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer400x17_desc-mean_pvc.csv -aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer400x17_desc-mean_score.csv -aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer400x17_desc-mean_scrub.csv -aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer400x7_desc-mean_basil.csv -aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer400x7_desc-mean_cbf.csv -aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer400x7_desc-mean_pvc.csv -aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer400x7_desc-mean_score.csv -aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer400x7_desc-mean_scrub.csv -aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_cbf.nii.gz -aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_desc-basil_cbf.nii.gz -aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_desc-bat_cbf.nii.gz -aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_desc-brain_mask.json -aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_desc-brain_mask.nii.gz -aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_desc-confounds_regressors.tsv -aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_desc-meanScore_cbf.nii.gz -aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_desc-mean_cbf.nii.gz -aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_desc-preproc_asl.json -aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_desc-preproc_asl.nii.gz -aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_desc-pvGM_cbf.nii.gz -aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_desc-pvWM_cbf.nii.gz -aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_desc-qualitycontrol_cbf.csv -aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_desc-score_cbf.nii.gz -aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_desc-scrub_cbf.nii.gz -aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_from-T1w_to-scanner_mode-image_xfm.txt -aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_from-scanner_to-T1w_mode-image_xfm.txt diff --git a/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_siemens.txt b/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_siemens.txt new file mode 100644 index 000000000..1c3a9f966 --- /dev/null +++ b/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_siemens.txt @@ -0,0 +1,47 @@ +aslprep/logs +aslprep/sub-103 +aslprep/sub-103/ses-siemens3d +aslprep/sub-103/ses-siemens3d/perf +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_aslref.nii.gz +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-HarvardOxford_desc-mean_basil.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-HarvardOxford_desc-mean_cbf.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-HarvardOxford_desc-mean_pvc.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-HarvardOxford_desc-mean_score.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-HarvardOxford_desc-mean_scrub.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer200x17_desc-mean_basil.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer200x17_desc-mean_cbf.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer200x17_desc-mean_pvc.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer200x17_desc-mean_score.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer200x17_desc-mean_scrub.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer200x7_desc-mean_basil.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer200x7_desc-mean_cbf.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer200x7_desc-mean_pvc.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer200x7_desc-mean_score.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer200x7_desc-mean_scrub.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer400x17_desc-mean_basil.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer400x17_desc-mean_cbf.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer400x17_desc-mean_pvc.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer400x17_desc-mean_score.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer400x17_desc-mean_scrub.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer400x7_desc-mean_basil.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer400x7_desc-mean_cbf.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer400x7_desc-mean_pvc.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer400x7_desc-mean_score.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_atlas-schaefer400x7_desc-mean_scrub.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_cbf.nii.gz +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_desc-basil_cbf.nii.gz +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_desc-bat_cbf.nii.gz +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_desc-brain_mask.json +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_desc-brain_mask.nii.gz +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_desc-confounds_regressors.tsv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_desc-meanScore_cbf.nii.gz +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_desc-mean_cbf.nii.gz +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_desc-preproc_asl.json +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_desc-preproc_asl.nii.gz +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_desc-pvGM_cbf.nii.gz +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_desc-pvWM_cbf.nii.gz +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_desc-qualitycontrol_cbf.csv +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_desc-score_cbf.nii.gz +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_desc-scrub_cbf.nii.gz +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_from-T1w_to-scanner_mode-image_xfm.txt +aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_from-scanner_to-T1w_mode-image_xfm.txt diff --git a/aslprep/tests/test_cli.py b/aslprep/tests/test_cli.py index 27184bfc8..fe8ce39f9 100644 --- a/aslprep/tests/test_cli.py +++ b/aslprep/tests/test_cli.py @@ -12,28 +12,29 @@ nipype_config.enable_debug_mode() -@pytest.mark.examples_pcasl_singlepld -def test_examples_pcasl_singlepld(datasets, output_dir, working_dir): - """Run aslprep on the asl_002 and asl_005 ASL-BIDS examples datasets. +@pytest.mark.examples_pasl_multipld +def test_examples_pasl_multipld(datasets, output_dir, working_dir): + """Run aslprep on the asl_003 ASL-BIDS examples dataset. + + This dataset has 10 control-label pairs at 10 different PLDs, along with a separate M0 scan. + The BolusCutOffTechnique is Q2TIPS. - This test uses two ASL sessions: one on a Siemens and one on a Philips. + NOTE: MultiPLD is not currently working, so we expect the workflow to fail. """ from aslprep import config - test_name = "examples_pcasl_singlepld" + test_name = "examples_pasl_multipld" data_dir = datasets[test_name] out_dir = os.path.join(output_dir, test_name) work_dir = os.path.join(working_dir, test_name) - test_data_dir = get_test_data_path() - filter_file = os.path.join(test_data_dir, "examples_pcasl_singlepld_filter.json") + # test_data_dir = get_test_data_path() parameters = [ data_dir, out_dir, "participant", - "--participant-label=103", + "--participant-label=01", f"-w={work_dir}", - f"--bids-filter-file={filter_file}", "--nthreads=2", "--omp-nthreads=2", "--output-spaces=asl", @@ -49,10 +50,57 @@ def test_examples_pcasl_singlepld(datasets, output_dir, working_dir): retval = {} retval = build_workflow(config_file, retval=retval) aslprep_wf = retval.get("workflow", None) - aslprep_wf.run() + with pytest.raises(NodeExecutionError, match="cannot currently process multi-PLD data."): + aslprep_wf.run() - output_list_file = os.path.join(test_data_dir, "expected_outputs_examples_pcasl_singlepld.txt") - check_generated_files(out_dir, output_list_file) + # output_list_file = os.path.join(test_data_dir, "expected_outputs_examples_pasl_multipld.txt") + # check_generated_files(out_dir, output_list_file) + + +@pytest.mark.examples_pcasl_multipld +def test_examples_pcasl_multipld(datasets, output_dir, working_dir): + """Run aslprep on the asl_004 ASL-BIDS examples dataset. + + This dataset has 48 control-label pairs at 6 different PLDs, along with a separate M0 scan. + + NOTE: MultiPLD is not currently working, so we expect the workflow to fail. + """ + from aslprep import config + + test_name = "examples_pcasl_multipld" + data_dir = datasets[test_name] + out_dir = os.path.join(output_dir, test_name) + work_dir = os.path.join(working_dir, test_name) + # test_data_dir = get_test_data_path() + + parameters = [ + data_dir, + out_dir, + "participant", + "--participant-label=01", + f"-w={work_dir}", + "--nthreads=2", + "--omp-nthreads=2", + "--output-spaces=asl", + "--scorescrub", + "--basil", + "--use-syn-sdc", + f"--anat-derivatives={os.path.join(data_dir, 'derivatives/smriprep')}", + ] + parse_args(parameters) + config_file = config.execution.work_dir / f"config-{config.execution.run_uuid}.toml" + config.to_filename(config_file) + + retval = {} + retval = build_workflow(config_file, retval=retval) + aslprep_wf = retval.get("workflow", None) + with pytest.raises(NodeExecutionError, match="cannot currently process multi-PLD data."): + aslprep_wf.run() + + # output_list_file = os.path.join( + # test_data_dir, "expected_outputs_examples_pcasl_multipld.txt" + # ) + # check_generated_files(out_dir, output_list_file) @pytest.mark.examples_pcasl_singlepld_ge @@ -101,28 +149,28 @@ def test_examples_pcasl_singlepld_ge(datasets, output_dir, working_dir): check_generated_files(out_dir, output_list_file) -@pytest.mark.examples_pcasl_multipld -def test_examples_pcasl_multipld(datasets, output_dir, working_dir): - """Run aslprep on the asl_004 ASL-BIDS examples dataset. - - This dataset has 48 control-label pairs at 6 different PLDs, along with a separate M0 scan. +@pytest.mark.examples_pcasl_singlepld_philips +def test_examples_pcasl_singlepld_philips(datasets, output_dir, working_dir): + """Run aslprep on the asl_002 ASL-BIDS examples datasets. - NOTE: MultiPLD is not currently working, so we expect the workflow to fail. + This test a Philips session. """ from aslprep import config - test_name = "examples_pcasl_multipld" + test_name = "examples_pcasl_singlepld" data_dir = datasets[test_name] out_dir = os.path.join(output_dir, test_name) work_dir = os.path.join(working_dir, test_name) - # test_data_dir = get_test_data_path() + test_data_dir = get_test_data_path() + filter_file = os.path.join(test_data_dir, "examples_pcasl_singlepld_filter_philips.json") parameters = [ data_dir, out_dir, "participant", - "--participant-label=01", + "--participant-label=103", f"-w={work_dir}", + f"--bids-filter-file={filter_file}", "--nthreads=2", "--omp-nthreads=2", "--output-spaces=asl", @@ -138,38 +186,37 @@ def test_examples_pcasl_multipld(datasets, output_dir, working_dir): retval = {} retval = build_workflow(config_file, retval=retval) aslprep_wf = retval.get("workflow", None) - with pytest.raises(NodeExecutionError, match="cannot currently process multi-PLD data."): - aslprep_wf.run() - - # output_list_file = os.path.join( - # test_data_dir, "expected_outputs_examples_pcasl_multipld.txt" - # ) - # check_generated_files(out_dir, output_list_file) + aslprep_wf.run() + output_list_file = os.path.join( + test_data_dir, + "expected_outputs_examples_pcasl_singlepld_philips.txt", + ) + check_generated_files(out_dir, output_list_file) -@pytest.mark.examples_pasl_multipld -def test_examples_pasl_multipld(datasets, output_dir, working_dir): - """Run aslprep on the asl_003 ASL-BIDS examples dataset. - This dataset has 10 control-label pairs at 10 different PLDs, along with a separate M0 scan. - The BolusCutOffTechnique is Q2TIPS. +@pytest.mark.examples_pcasl_singlepld_siemens +def test_examples_pcasl_singlepld_siemens(datasets, output_dir, working_dir): + """Run aslprep on the asl_005 ASL-BIDS examples datasets. - NOTE: MultiPLD is not currently working, so we expect the workflow to fail. + This test a Siemens session. """ from aslprep import config - test_name = "examples_pasl_multipld" + test_name = "examples_pcasl_singlepld" data_dir = datasets[test_name] out_dir = os.path.join(output_dir, test_name) work_dir = os.path.join(working_dir, test_name) - # test_data_dir = get_test_data_path() + test_data_dir = get_test_data_path() + filter_file = os.path.join(test_data_dir, "examples_pcasl_singlepld_filter_siemens.json") parameters = [ data_dir, out_dir, "participant", - "--participant-label=01", + "--participant-label=103", f"-w={work_dir}", + f"--bids-filter-file={filter_file}", "--nthreads=2", "--omp-nthreads=2", "--output-spaces=asl", @@ -185,11 +232,13 @@ def test_examples_pasl_multipld(datasets, output_dir, working_dir): retval = {} retval = build_workflow(config_file, retval=retval) aslprep_wf = retval.get("workflow", None) - with pytest.raises(NodeExecutionError, match="cannot currently process multi-PLD data."): - aslprep_wf.run() + aslprep_wf.run() - # output_list_file = os.path.join(test_data_dir, "expected_outputs_examples_pasl_multipld.txt") - # check_generated_files(out_dir, output_list_file) + output_list_file = os.path.join( + test_data_dir, + "expected_outputs_examples_pcasl_singlepld_siemens.txt", + ) + check_generated_files(out_dir, output_list_file) @pytest.mark.test_001 diff --git a/pyproject.toml b/pyproject.toml index ebe8b4b77..341af3bc8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,12 +34,13 @@ exclude = ''' ''' [tool.pytest.ini_options] -addopts = '-m "not examples_pcasl_singlepld and not examples_pcasl_singlepld_ge and not examples_pcasl_multipld and not examples_pasl_multipld and not test_001 and not test_002 and not test_003"' +addopts = '-m "not examples_pcasl_singlepld_philips and not examples_pcasl_singlepld_siemens and not examples_pcasl_singlepld_ge and not examples_pcasl_multipld and not examples_pasl_multipld and not test_001 and not test_002 and not test_003"' markers = [ - "examples_pcasl_singlepld: mark integration test", - "examples_pcasl_singlepld_ge: mark integration test", - "examples_pcasl_multipld: mark integration test", "examples_pasl_multipld: mark integration test", + "examples_pcasl_multipld: mark integration test", + "examples_pcasl_singlepld_ge: mark integration test", + "examples_pcasl_singlepld_philips: mark integration test", + "examples_pcasl_singlepld_siemens: mark integration test", "test_001: mark integration test for subject 01", "test_002: mark integration test for subject 10R01383", "test_003: mark integration test for subject A00086748", From 9d7264692d97de90ad3b78087f35ef30f8a455a0 Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Mon, 3 Apr 2023 14:08:09 -0400 Subject: [PATCH 39/43] Streamline test code. --- ...mples_pcasl_singlepld_philips_filter.json} | 0 ...mples_pcasl_singlepld_siemens_filter.json} | 0 aslprep/tests/test_cli.py | 237 +++++++----------- 3 files changed, 93 insertions(+), 144 deletions(-) rename aslprep/tests/data/{examples_pcasl_singlepld_filter_philips.json => examples_pcasl_singlepld_philips_filter.json} (100%) rename aslprep/tests/data/{examples_pcasl_singlepld_filter_siemens.json => examples_pcasl_singlepld_siemens_filter.json} (100%) diff --git a/aslprep/tests/data/examples_pcasl_singlepld_filter_philips.json b/aslprep/tests/data/examples_pcasl_singlepld_philips_filter.json similarity index 100% rename from aslprep/tests/data/examples_pcasl_singlepld_filter_philips.json rename to aslprep/tests/data/examples_pcasl_singlepld_philips_filter.json diff --git a/aslprep/tests/data/examples_pcasl_singlepld_filter_siemens.json b/aslprep/tests/data/examples_pcasl_singlepld_siemens_filter.json similarity index 100% rename from aslprep/tests/data/examples_pcasl_singlepld_filter_siemens.json rename to aslprep/tests/data/examples_pcasl_singlepld_siemens_filter.json diff --git a/aslprep/tests/test_cli.py b/aslprep/tests/test_cli.py index fe8ce39f9..48598b94c 100644 --- a/aslprep/tests/test_cli.py +++ b/aslprep/tests/test_cli.py @@ -4,9 +4,11 @@ import pytest from nipype import config as nipype_config from nipype.pipeline.engine.nodes import NodeExecutionError +from pkg_resources import resource_filename as pkgrf from aslprep.cli.parser import parse_args from aslprep.cli.workflow import build_workflow +from aslprep.niworkflows.reports import generate_reports from aslprep.tests.utils import check_generated_files, get_test_data_path nipype_config.enable_debug_mode() @@ -21,19 +23,18 @@ def test_examples_pasl_multipld(datasets, output_dir, working_dir): NOTE: MultiPLD is not currently working, so we expect the workflow to fail. """ - from aslprep import config + TEST_NAME = "examples_pasl_multipld" + PARTICIPANT_LABEL = "01" - test_name = "examples_pasl_multipld" - data_dir = datasets[test_name] - out_dir = os.path.join(output_dir, test_name) - work_dir = os.path.join(working_dir, test_name) - # test_data_dir = get_test_data_path() + data_dir = datasets[TEST_NAME] + out_dir = os.path.join(output_dir, TEST_NAME) + work_dir = os.path.join(working_dir, TEST_NAME) parameters = [ data_dir, out_dir, "participant", - "--participant-label=01", + f"--participant-label={PARTICIPANT_LABEL}", f"-w={work_dir}", "--nthreads=2", "--omp-nthreads=2", @@ -43,18 +44,8 @@ def test_examples_pasl_multipld(datasets, output_dir, working_dir): "--use-syn-sdc", f"--anat-derivatives={os.path.join(data_dir, 'derivatives/smriprep')}", ] - parse_args(parameters) - config_file = config.execution.work_dir / f"config-{config.execution.run_uuid}.toml" - config.to_filename(config_file) - retval = {} - retval = build_workflow(config_file, retval=retval) - aslprep_wf = retval.get("workflow", None) - with pytest.raises(NodeExecutionError, match="cannot currently process multi-PLD data."): - aslprep_wf.run() - - # output_list_file = os.path.join(test_data_dir, "expected_outputs_examples_pasl_multipld.txt") - # check_generated_files(out_dir, output_list_file) + _run_and_fail(parameters) @pytest.mark.examples_pcasl_multipld @@ -65,19 +56,18 @@ def test_examples_pcasl_multipld(datasets, output_dir, working_dir): NOTE: MultiPLD is not currently working, so we expect the workflow to fail. """ - from aslprep import config + TEST_NAME = "examples_pcasl_multipld" + PARTICIPANT_LABEL = "01" - test_name = "examples_pcasl_multipld" - data_dir = datasets[test_name] - out_dir = os.path.join(output_dir, test_name) - work_dir = os.path.join(working_dir, test_name) - # test_data_dir = get_test_data_path() + data_dir = datasets[TEST_NAME] + out_dir = os.path.join(output_dir, TEST_NAME) + work_dir = os.path.join(working_dir, TEST_NAME) parameters = [ data_dir, out_dir, "participant", - "--participant-label=01", + f"--participant-label={PARTICIPANT_LABEL}", f"-w={work_dir}", "--nthreads=2", "--omp-nthreads=2", @@ -87,20 +77,8 @@ def test_examples_pcasl_multipld(datasets, output_dir, working_dir): "--use-syn-sdc", f"--anat-derivatives={os.path.join(data_dir, 'derivatives/smriprep')}", ] - parse_args(parameters) - config_file = config.execution.work_dir / f"config-{config.execution.run_uuid}.toml" - config.to_filename(config_file) - - retval = {} - retval = build_workflow(config_file, retval=retval) - aslprep_wf = retval.get("workflow", None) - with pytest.raises(NodeExecutionError, match="cannot currently process multi-PLD data."): - aslprep_wf.run() - # output_list_file = os.path.join( - # test_data_dir, "expected_outputs_examples_pcasl_multipld.txt" - # ) - # check_generated_files(out_dir, output_list_file) + _run_and_fail(parameters) @pytest.mark.examples_pcasl_singlepld_ge @@ -109,20 +87,20 @@ def test_examples_pcasl_singlepld_ge(datasets, output_dir, working_dir): This test uses a GE session with two volumes: one deltam and one M0. """ - from aslprep import config + TEST_NAME = "examples_pcasl_singlepld_ge" + PARTICIPANT_LABEL = "103" - test_name = "examples_pcasl_singlepld_ge" data_dir = datasets["examples_pcasl_singlepld"] - out_dir = os.path.join(output_dir, test_name) - work_dir = os.path.join(working_dir, test_name) + out_dir = os.path.join(output_dir, TEST_NAME) + work_dir = os.path.join(working_dir, TEST_NAME) test_data_dir = get_test_data_path() - filter_file = os.path.join(test_data_dir, "examples_pcasl_singlepld_ge_filter.json") + filter_file = os.path.join(test_data_dir, f"{TEST_NAME}_filter.json") parameters = [ data_dir, out_dir, "participant", - "--participant-label=103", + f"--participant-label={PARTICIPANT_LABEL}", f"-w={work_dir}", f"--bids-filter-file={filter_file}", "--nthreads=2", @@ -133,20 +111,8 @@ def test_examples_pcasl_singlepld_ge(datasets, output_dir, working_dir): "--use-syn-sdc", f"--anat-derivatives={os.path.join(data_dir, 'derivatives/smriprep')}", ] - parse_args(parameters) - config_file = config.execution.work_dir / f"config-{config.execution.run_uuid}.toml" - config.to_filename(config_file) - - retval = {} - retval = build_workflow(config_file, retval=retval) - aslprep_wf = retval.get("workflow", None) - aslprep_wf.run() - output_list_file = os.path.join( - test_data_dir, - "expected_outputs_examples_pcasl_singlepld_ge.txt", - ) - check_generated_files(out_dir, output_list_file) + _run_and_generate(TEST_NAME, PARTICIPANT_LABEL, parameters, out_dir) @pytest.mark.examples_pcasl_singlepld_philips @@ -155,20 +121,20 @@ def test_examples_pcasl_singlepld_philips(datasets, output_dir, working_dir): This test a Philips session. """ - from aslprep import config + TEST_NAME = "examples_pcasl_singlepld_philips" + PARTICIPANT_LABEL = "103" - test_name = "examples_pcasl_singlepld" - data_dir = datasets[test_name] - out_dir = os.path.join(output_dir, test_name) - work_dir = os.path.join(working_dir, test_name) + data_dir = datasets["examples_pcasl_singlepld"] + out_dir = os.path.join(output_dir, TEST_NAME) + work_dir = os.path.join(working_dir, TEST_NAME) test_data_dir = get_test_data_path() - filter_file = os.path.join(test_data_dir, "examples_pcasl_singlepld_filter_philips.json") + filter_file = os.path.join(test_data_dir, f"{TEST_NAME}_filter.json") parameters = [ data_dir, out_dir, "participant", - "--participant-label=103", + f"--participant-label={PARTICIPANT_LABEL}", f"-w={work_dir}", f"--bids-filter-file={filter_file}", "--nthreads=2", @@ -179,20 +145,8 @@ def test_examples_pcasl_singlepld_philips(datasets, output_dir, working_dir): "--use-syn-sdc", f"--anat-derivatives={os.path.join(data_dir, 'derivatives/smriprep')}", ] - parse_args(parameters) - config_file = config.execution.work_dir / f"config-{config.execution.run_uuid}.toml" - config.to_filename(config_file) - - retval = {} - retval = build_workflow(config_file, retval=retval) - aslprep_wf = retval.get("workflow", None) - aslprep_wf.run() - output_list_file = os.path.join( - test_data_dir, - "expected_outputs_examples_pcasl_singlepld_philips.txt", - ) - check_generated_files(out_dir, output_list_file) + _run_and_generate(TEST_NAME, PARTICIPANT_LABEL, parameters, out_dir) @pytest.mark.examples_pcasl_singlepld_siemens @@ -201,20 +155,20 @@ def test_examples_pcasl_singlepld_siemens(datasets, output_dir, working_dir): This test a Siemens session. """ - from aslprep import config + TEST_NAME = "examples_pcasl_singlepld_siemens" + PARTICIPANT_LABEL = "103" - test_name = "examples_pcasl_singlepld" - data_dir = datasets[test_name] - out_dir = os.path.join(output_dir, test_name) - work_dir = os.path.join(working_dir, test_name) + data_dir = datasets["examples_pcasl_singlepld"] + out_dir = os.path.join(output_dir, TEST_NAME) + work_dir = os.path.join(working_dir, TEST_NAME) test_data_dir = get_test_data_path() - filter_file = os.path.join(test_data_dir, "examples_pcasl_singlepld_filter_siemens.json") + filter_file = os.path.join(test_data_dir, f"{TEST_NAME}_filter.json") parameters = [ data_dir, out_dir, "participant", - "--participant-label=103", + f"--participant-label={PARTICIPANT_LABEL}", f"-w={work_dir}", f"--bids-filter-file={filter_file}", "--nthreads=2", @@ -225,38 +179,25 @@ def test_examples_pcasl_singlepld_siemens(datasets, output_dir, working_dir): "--use-syn-sdc", f"--anat-derivatives={os.path.join(data_dir, 'derivatives/smriprep')}", ] - parse_args(parameters) - config_file = config.execution.work_dir / f"config-{config.execution.run_uuid}.toml" - config.to_filename(config_file) - retval = {} - retval = build_workflow(config_file, retval=retval) - aslprep_wf = retval.get("workflow", None) - aslprep_wf.run() - - output_list_file = os.path.join( - test_data_dir, - "expected_outputs_examples_pcasl_singlepld_siemens.txt", - ) - check_generated_files(out_dir, output_list_file) + _run_and_generate(TEST_NAME, PARTICIPANT_LABEL, parameters, out_dir) @pytest.mark.test_001 def test_test_001(datasets, output_dir, working_dir): """Run aslprep on sub-01 data.""" - from aslprep import config + TEST_NAME = "test_001" + PARTICIPANT_LABEL = "01" - test_name = "test_001" - data_dir = datasets[test_name] - out_dir = os.path.join(output_dir, test_name) - work_dir = os.path.join(working_dir, test_name) - test_data_dir = get_test_data_path() + data_dir = datasets[TEST_NAME] + out_dir = os.path.join(output_dir, TEST_NAME) + work_dir = os.path.join(working_dir, TEST_NAME) parameters = [ data_dir, out_dir, "participant", - "--participant-label=01", + f"--participant-label={PARTICIPANT_LABEL}", f"-w={work_dir}", "--nthreads=2", "--omp-nthreads=2", @@ -266,17 +207,8 @@ def test_test_001(datasets, output_dir, working_dir): "--use-syn-sdc", f"--anat-derivatives={os.path.join(data_dir, 'derivatives/smriprep')}", ] - parse_args(parameters) - config_file = config.execution.work_dir / f"config-{config.execution.run_uuid}.toml" - config.to_filename(config_file) - - retval = {} - retval = build_workflow(config_file, retval=retval) - aslprep_wf = retval.get("workflow", None) - aslprep_wf.run() - output_list_file = os.path.join(test_data_dir, "expected_outputs_test_001.txt") - check_generated_files(out_dir, output_list_file) + _run_and_generate(TEST_NAME, PARTICIPANT_LABEL, parameters, out_dir) @pytest.mark.test_002 @@ -285,25 +217,19 @@ def test_test_002(datasets, output_dir, working_dir): This dataset contains PCASL data from a GE scanner. There are two ASL volumes (both deltam) and separate M0 scan. - - Notes - ----- - scorescrub fails on this dataset, so I've dropped that parameter. - I'll probably need to dig into why that happens at some point. """ - from aslprep import config + TEST_NAME = "test_002" + PARTICIPANT_LABEL = "10R01383" - test_name = "test_002" - data_dir = datasets[test_name] - out_dir = os.path.join(output_dir, test_name) - work_dir = os.path.join(working_dir, test_name) - test_data_dir = get_test_data_path() + data_dir = datasets[TEST_NAME] + out_dir = os.path.join(output_dir, TEST_NAME) + work_dir = os.path.join(working_dir, TEST_NAME) parameters = [ data_dir, out_dir, "participant", - "--participant-label=10R01383", + f"--participant-label={PARTICIPANT_LABEL}", f"-w={work_dir}", "--nthreads=2", "--omp-nthreads=2", @@ -313,35 +239,25 @@ def test_test_002(datasets, output_dir, working_dir): "--use-syn-sdc", f"--anat-derivatives={os.path.join(data_dir, 'derivatives/smriprep')}", ] - parse_args(parameters) - config_file = config.execution.work_dir / f"config-{config.execution.run_uuid}.toml" - config.to_filename(config_file) - retval = {} - retval = build_workflow(config_file, retval=retval) - aslprep_wf = retval.get("workflow", None) - aslprep_wf.run() - - output_list_file = os.path.join(test_data_dir, "expected_outputs_test_002.txt") - check_generated_files(out_dir, output_list_file) + _run_and_generate(TEST_NAME, PARTICIPANT_LABEL, parameters, out_dir) @pytest.mark.test_003 def test_test_003(datasets, output_dir, working_dir): """Run aslprep on sub-A00086748.""" - from aslprep import config + TEST_NAME = "test_003" + PARTICIPANT_LABEL = "A00086748" - test_name = "test_003" - data_dir = datasets[test_name] - out_dir = os.path.join(output_dir, test_name) - work_dir = os.path.join(working_dir, test_name) - test_data_dir = get_test_data_path() + data_dir = datasets[TEST_NAME] + out_dir = os.path.join(output_dir, TEST_NAME) + work_dir = os.path.join(working_dir, TEST_NAME) parameters = [ data_dir, out_dir, "participant", - "--participant-label=A00086748", + f"--participant-label={PARTICIPANT_LABEL}", f"-w={work_dir}", "--nthreads=2", "--omp-nthreads=2", @@ -351,14 +267,47 @@ def test_test_003(datasets, output_dir, working_dir): "--use-syn-sdc", f"--anat-derivatives={os.path.join(data_dir, 'derivatives/smriprep')}", ] + + _run_and_generate(TEST_NAME, PARTICIPANT_LABEL, parameters, out_dir) + + +def _run_and_generate(test_name, participant_label, parameters, out_dir): + from aslprep import config + parse_args(parameters) config_file = config.execution.work_dir / f"config-{config.execution.run_uuid}.toml" + config.loggers.cli.warning(f"Saving config file to {config_file}") config.to_filename(config_file) + test_data_dir = get_test_data_path() + retval = {} retval = build_workflow(config_file, retval=retval) + run_uuid = retval.get("run_uuid", None) aslprep_wf = retval.get("workflow", None) aslprep_wf.run() - output_list_file = os.path.join(test_data_dir, "expected_outputs_test_003.txt") + generate_reports( + participant_label, + out_dir, + run_uuid, + config=pkgrf("aslprep", "data/reports-spec.yml"), + packagename="aslprep", + ) + + output_list_file = os.path.join(test_data_dir, f"expected_outputs_{test_name}.txt") check_generated_files(out_dir, output_list_file) + + +def _run_and_fail(parameters): + from aslprep import config + + parse_args(parameters) + config_file = config.execution.work_dir / f"config-{config.execution.run_uuid}.toml" + config.to_filename(config_file) + + retval = {} + retval = build_workflow(config_file, retval=retval) + aslprep_wf = retval.get("workflow", None) + with pytest.raises(NodeExecutionError, match="cannot currently process multi-PLD data."): + aslprep_wf.run() From 1fa5bb5b567a22a2532d05214d74e5c77b18c429 Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Mon, 3 Apr 2023 14:41:14 -0400 Subject: [PATCH 40/43] Update test_cli.py --- aslprep/tests/test_cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aslprep/tests/test_cli.py b/aslprep/tests/test_cli.py index 48598b94c..36e8883ef 100644 --- a/aslprep/tests/test_cli.py +++ b/aslprep/tests/test_cli.py @@ -288,7 +288,7 @@ def _run_and_generate(test_name, participant_label, parameters, out_dir): aslprep_wf.run() generate_reports( - participant_label, + [participant_label], out_dir, run_uuid, config=pkgrf("aslprep", "data/reports-spec.yml"), From 5c430b696d021118df5517604bbf07866c6753a9 Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Mon, 3 Apr 2023 15:13:12 -0400 Subject: [PATCH 41/43] Update test_cli.py --- aslprep/tests/test_cli.py | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/aslprep/tests/test_cli.py b/aslprep/tests/test_cli.py index 36e8883ef..642a27039 100644 --- a/aslprep/tests/test_cli.py +++ b/aslprep/tests/test_cli.py @@ -279,23 +279,19 @@ def _run_and_generate(test_name, participant_label, parameters, out_dir): config.loggers.cli.warning(f"Saving config file to {config_file}") config.to_filename(config_file) - test_data_dir = get_test_data_path() - - retval = {} - retval = build_workflow(config_file, retval=retval) - run_uuid = retval.get("run_uuid", None) - aslprep_wf = retval.get("workflow", None) + retval = build_workflow(config_file, retval={}) + aslprep_wf = retval["workflow"] aslprep_wf.run() generate_reports( [participant_label], out_dir, - run_uuid, + config.execution.run_uuid, config=pkgrf("aslprep", "data/reports-spec.yml"), packagename="aslprep", ) - output_list_file = os.path.join(test_data_dir, f"expected_outputs_{test_name}.txt") + output_list_file = os.path.join(get_test_data_path(), f"expected_outputs_{test_name}.txt") check_generated_files(out_dir, output_list_file) @@ -306,8 +302,7 @@ def _run_and_fail(parameters): config_file = config.execution.work_dir / f"config-{config.execution.run_uuid}.toml" config.to_filename(config_file) - retval = {} - retval = build_workflow(config_file, retval=retval) - aslprep_wf = retval.get("workflow", None) + retval = build_workflow(config_file, retval={}) + aslprep_wf = retval["workflow"] with pytest.raises(NodeExecutionError, match="cannot currently process multi-PLD data."): aslprep_wf.run() From 28766fea446f94b02e5140308e61fa9e1bda5985 Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Mon, 3 Apr 2023 15:47:37 -0400 Subject: [PATCH 42/43] Expect the report. --- .../tests/data/expected_outputs_examples_pasl_multipld.txt | 1 + .../tests/data/expected_outputs_examples_pcasl_multipld.txt | 1 + .../data/expected_outputs_examples_pcasl_singlepld_ge.txt | 1 + .../expected_outputs_examples_pcasl_singlepld_philips.txt | 1 + .../expected_outputs_examples_pcasl_singlepld_siemens.txt | 1 + aslprep/tests/data/expected_outputs_test_001.txt | 1 + aslprep/tests/data/expected_outputs_test_002.txt | 1 + aslprep/tests/data/expected_outputs_test_003.txt | 1 + aslprep/tests/test_cli.py | 4 ++-- 9 files changed, 10 insertions(+), 2 deletions(-) diff --git a/aslprep/tests/data/expected_outputs_examples_pasl_multipld.txt b/aslprep/tests/data/expected_outputs_examples_pasl_multipld.txt index 58de5f9f8..71b96fa87 100644 --- a/aslprep/tests/data/expected_outputs_examples_pasl_multipld.txt +++ b/aslprep/tests/data/expected_outputs_examples_pasl_multipld.txt @@ -1,5 +1,6 @@ aslprep/logs aslprep/sub-01 +aslprep/sub-01.html aslprep/sub-01/ses-BAS1 aslprep/sub-01/ses-BAS1/perf aslprep/sub-01/ses-BAS1/perf/sub-01_ses-BAS1_aslref.nii.gz diff --git a/aslprep/tests/data/expected_outputs_examples_pcasl_multipld.txt b/aslprep/tests/data/expected_outputs_examples_pcasl_multipld.txt index a8634a258..dd2a66c04 100644 --- a/aslprep/tests/data/expected_outputs_examples_pcasl_multipld.txt +++ b/aslprep/tests/data/expected_outputs_examples_pcasl_multipld.txt @@ -1,5 +1,6 @@ aslprep/logs aslprep/sub-01 +aslprep/sub-01.html aslprep/sub-01/perf aslprep/sub-01/perf/sub-01_aslref.nii.gz aslprep/sub-01/perf/sub-01_cbf.nii.gz diff --git a/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_ge.txt b/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_ge.txt index f3ede5a9c..fe135ebaa 100644 --- a/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_ge.txt +++ b/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_ge.txt @@ -1,5 +1,6 @@ aslprep/logs aslprep/sub-103 +aslprep/sub-103.html aslprep/sub-103/ses-ge3d aslprep/sub-103/ses-ge3d/perf aslprep/sub-103/ses-ge3d/perf/sub-103_ses-ge3d_aslref.nii.gz diff --git a/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_philips.txt b/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_philips.txt index 4fd79b1fa..bc04e1dca 100644 --- a/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_philips.txt +++ b/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_philips.txt @@ -1,5 +1,6 @@ aslprep/logs aslprep/sub-103 +aslprep/sub-103.html aslprep/sub-103/ses-philips2d aslprep/sub-103/ses-philips2d/perf aslprep/sub-103/ses-philips2d/perf/sub-103_ses-philips2d_aslref.nii.gz diff --git a/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_siemens.txt b/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_siemens.txt index 1c3a9f966..e7dc1a69f 100644 --- a/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_siemens.txt +++ b/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_siemens.txt @@ -1,5 +1,6 @@ aslprep/logs aslprep/sub-103 +aslprep/sub-103.html aslprep/sub-103/ses-siemens3d aslprep/sub-103/ses-siemens3d/perf aslprep/sub-103/ses-siemens3d/perf/sub-103_ses-siemens3d_aslref.nii.gz diff --git a/aslprep/tests/data/expected_outputs_test_001.txt b/aslprep/tests/data/expected_outputs_test_001.txt index a8634a258..dd2a66c04 100644 --- a/aslprep/tests/data/expected_outputs_test_001.txt +++ b/aslprep/tests/data/expected_outputs_test_001.txt @@ -1,5 +1,6 @@ aslprep/logs aslprep/sub-01 +aslprep/sub-01.html aslprep/sub-01/perf aslprep/sub-01/perf/sub-01_aslref.nii.gz aslprep/sub-01/perf/sub-01_cbf.nii.gz diff --git a/aslprep/tests/data/expected_outputs_test_002.txt b/aslprep/tests/data/expected_outputs_test_002.txt index 120adf714..f8ad60ab2 100644 --- a/aslprep/tests/data/expected_outputs_test_002.txt +++ b/aslprep/tests/data/expected_outputs_test_002.txt @@ -1,5 +1,6 @@ aslprep/logs aslprep/sub-10R01383 +aslprep/sub-10R01383.html aslprep/sub-10R01383/perf aslprep/sub-10R01383/perf/sub-10R01383_aslref.nii.gz aslprep/sub-10R01383/perf/sub-10R01383_cbf.nii.gz diff --git a/aslprep/tests/data/expected_outputs_test_003.txt b/aslprep/tests/data/expected_outputs_test_003.txt index f531c4362..daa5a3b7f 100644 --- a/aslprep/tests/data/expected_outputs_test_003.txt +++ b/aslprep/tests/data/expected_outputs_test_003.txt @@ -1,5 +1,6 @@ aslprep/logs aslprep/sub-A00086748 +aslprep/sub-A00086748.html aslprep/sub-A00086748/ses-BAS1 aslprep/sub-A00086748/ses-BAS1/perf aslprep/sub-A00086748/ses-BAS1/perf/sub-A00086748_ses-BAS1_aslref.nii.gz diff --git a/aslprep/tests/test_cli.py b/aslprep/tests/test_cli.py index 642a27039..ab4aa6c2e 100644 --- a/aslprep/tests/test_cli.py +++ b/aslprep/tests/test_cli.py @@ -7,7 +7,7 @@ from pkg_resources import resource_filename as pkgrf from aslprep.cli.parser import parse_args -from aslprep.cli.workflow import build_workflow +from aslprep.cli.workflow import build_boilerplate, build_workflow from aslprep.niworkflows.reports import generate_reports from aslprep.tests.utils import check_generated_files, get_test_data_path @@ -282,7 +282,7 @@ def _run_and_generate(test_name, participant_label, parameters, out_dir): retval = build_workflow(config_file, retval={}) aslprep_wf = retval["workflow"] aslprep_wf.run() - + build_boilerplate(str(config_file), aslprep_wf) generate_reports( [participant_label], out_dir, From 6b0e74cfaec00f0013613331c07938fb231f1a3e Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Mon, 3 Apr 2023 16:17:24 -0400 Subject: [PATCH 43/43] Expect the boilerplates. --- .../tests/data/expected_outputs_examples_pasl_multipld.txt | 4 ++++ .../tests/data/expected_outputs_examples_pcasl_multipld.txt | 4 ++++ .../data/expected_outputs_examples_pcasl_singlepld_ge.txt | 4 ++++ .../expected_outputs_examples_pcasl_singlepld_philips.txt | 4 ++++ .../expected_outputs_examples_pcasl_singlepld_siemens.txt | 4 ++++ aslprep/tests/data/expected_outputs_test_001.txt | 4 ++++ aslprep/tests/data/expected_outputs_test_002.txt | 4 ++++ aslprep/tests/data/expected_outputs_test_003.txt | 4 ++++ 8 files changed, 32 insertions(+) diff --git a/aslprep/tests/data/expected_outputs_examples_pasl_multipld.txt b/aslprep/tests/data/expected_outputs_examples_pasl_multipld.txt index 71b96fa87..740d07acf 100644 --- a/aslprep/tests/data/expected_outputs_examples_pasl_multipld.txt +++ b/aslprep/tests/data/expected_outputs_examples_pasl_multipld.txt @@ -1,4 +1,8 @@ aslprep/logs +aslprep/logs/CITATION.bib +aslprep/logs/CITATION.html +aslprep/logs/CITATION.md +aslprep/logs/CITATION.tex aslprep/sub-01 aslprep/sub-01.html aslprep/sub-01/ses-BAS1 diff --git a/aslprep/tests/data/expected_outputs_examples_pcasl_multipld.txt b/aslprep/tests/data/expected_outputs_examples_pcasl_multipld.txt index dd2a66c04..215853c98 100644 --- a/aslprep/tests/data/expected_outputs_examples_pcasl_multipld.txt +++ b/aslprep/tests/data/expected_outputs_examples_pcasl_multipld.txt @@ -1,4 +1,8 @@ aslprep/logs +aslprep/logs/CITATION.bib +aslprep/logs/CITATION.html +aslprep/logs/CITATION.md +aslprep/logs/CITATION.tex aslprep/sub-01 aslprep/sub-01.html aslprep/sub-01/perf diff --git a/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_ge.txt b/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_ge.txt index fe135ebaa..6afff1ee2 100644 --- a/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_ge.txt +++ b/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_ge.txt @@ -1,4 +1,8 @@ aslprep/logs +aslprep/logs/CITATION.bib +aslprep/logs/CITATION.html +aslprep/logs/CITATION.md +aslprep/logs/CITATION.tex aslprep/sub-103 aslprep/sub-103.html aslprep/sub-103/ses-ge3d diff --git a/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_philips.txt b/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_philips.txt index bc04e1dca..052a46e0f 100644 --- a/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_philips.txt +++ b/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_philips.txt @@ -1,4 +1,8 @@ aslprep/logs +aslprep/logs/CITATION.bib +aslprep/logs/CITATION.html +aslprep/logs/CITATION.md +aslprep/logs/CITATION.tex aslprep/sub-103 aslprep/sub-103.html aslprep/sub-103/ses-philips2d diff --git a/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_siemens.txt b/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_siemens.txt index e7dc1a69f..b68bc20bf 100644 --- a/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_siemens.txt +++ b/aslprep/tests/data/expected_outputs_examples_pcasl_singlepld_siemens.txt @@ -1,4 +1,8 @@ aslprep/logs +aslprep/logs/CITATION.bib +aslprep/logs/CITATION.html +aslprep/logs/CITATION.md +aslprep/logs/CITATION.tex aslprep/sub-103 aslprep/sub-103.html aslprep/sub-103/ses-siemens3d diff --git a/aslprep/tests/data/expected_outputs_test_001.txt b/aslprep/tests/data/expected_outputs_test_001.txt index dd2a66c04..215853c98 100644 --- a/aslprep/tests/data/expected_outputs_test_001.txt +++ b/aslprep/tests/data/expected_outputs_test_001.txt @@ -1,4 +1,8 @@ aslprep/logs +aslprep/logs/CITATION.bib +aslprep/logs/CITATION.html +aslprep/logs/CITATION.md +aslprep/logs/CITATION.tex aslprep/sub-01 aslprep/sub-01.html aslprep/sub-01/perf diff --git a/aslprep/tests/data/expected_outputs_test_002.txt b/aslprep/tests/data/expected_outputs_test_002.txt index f8ad60ab2..923539d64 100644 --- a/aslprep/tests/data/expected_outputs_test_002.txt +++ b/aslprep/tests/data/expected_outputs_test_002.txt @@ -1,4 +1,8 @@ aslprep/logs +aslprep/logs/CITATION.bib +aslprep/logs/CITATION.html +aslprep/logs/CITATION.md +aslprep/logs/CITATION.tex aslprep/sub-10R01383 aslprep/sub-10R01383.html aslprep/sub-10R01383/perf diff --git a/aslprep/tests/data/expected_outputs_test_003.txt b/aslprep/tests/data/expected_outputs_test_003.txt index daa5a3b7f..0b08c7a31 100644 --- a/aslprep/tests/data/expected_outputs_test_003.txt +++ b/aslprep/tests/data/expected_outputs_test_003.txt @@ -1,4 +1,8 @@ aslprep/logs +aslprep/logs/CITATION.bib +aslprep/logs/CITATION.html +aslprep/logs/CITATION.md +aslprep/logs/CITATION.tex aslprep/sub-A00086748 aslprep/sub-A00086748.html aslprep/sub-A00086748/ses-BAS1