From ebaca839976f409bb90f82b9515c24ea936418f7 Mon Sep 17 00:00:00 2001 From: Michael Joseph Date: Mon, 8 Jul 2019 17:30:15 -0400 Subject: [PATCH 01/18] updating cli --- dmriprep/cli.py | 11 ++++++++++ dmriprep/workflows/base.py | 40 +++++++++++++++++++++++++++------- dmriprep/workflows/dwi/base.py | 12 +++++----- 3 files changed, 50 insertions(+), 13 deletions(-) diff --git a/dmriprep/cli.py b/dmriprep/cli.py index 338dd4b..9dce15c 100644 --- a/dmriprep/cli.py +++ b/dmriprep/cli.py @@ -28,6 +28,15 @@ "can be specified with a space separated list.", default=None, ) +@click.command() +@click.option( + "--ignore", + help="Ignore selected parts of the workflow.", + type=click.Choice(["denoise", "unring"]), +) +@click.option( + "--resize-scale", help="Scale factor to resize DWI image", type=(float) +) @click.option( "--eddy-niter", help="Fixed number of eddy iterations. See " @@ -73,6 +82,7 @@ def main( participant_label, bids_dir, output_dir, + resize_scale, eddy_niter=5, bet_dwi=0.3, bet_mag=0.3, @@ -109,6 +119,7 @@ def main( subject_list, work_dir, output_dir, + resize_scale, bet_dwi, bet_mag, total_readout, diff --git a/dmriprep/workflows/base.py b/dmriprep/workflows/base.py index 42d0a1e..588db76 100644 --- a/dmriprep/workflows/base.py +++ b/dmriprep/workflows/base.py @@ -8,8 +8,14 @@ def init_dmriprep_wf( - layout, subject_list, work_dir, output_dir, - bet_dwi, bet_mag, total_readout + layout, + subject_list, + work_dir, + output_dir, + resize_scale, + bet_dwi, + bet_mag, + total_readout, ): dmriprep_wf = pe.Workflow(name="dmriprep_wf") dmriprep_wf.base_dir = work_dir @@ -22,6 +28,7 @@ def init_dmriprep_wf( name="single_subject_" + subject_id + "_wf", work_dir=work_dir, output_dir=output_dir, + resize_scale=resize_scale, bet_dwi=bet_dwi, bet_mag=bet_mag, total_readout=total_readout, @@ -40,8 +47,15 @@ def init_dmriprep_wf( def init_single_subject_wf( - layout, subject_id, name, work_dir, output_dir, - bet_dwi, bet_mag, total_readout + layout, + subject_id, + name, + work_dir, + output_dir, + resize_scale, + bet_dwi, + bet_mag, + total_readout, ): dwi_files = layout.get( @@ -65,14 +79,24 @@ def init_single_subject_wf( session_id = entities["session"] metadata = layout.get_metadata(dwi_file) dwi_preproc_wf = init_dwi_preproc_wf( - subject_id=subject_id, dwi_file=dwi_file, metadata=metadata, layout=layout, - bet_dwi_frac=bet_dwi, bet_mag_frac=bet_mag, total_readout=total_readout + subject_id=subject_id, + dwi_file=dwi_file, + dwi_meta=metadata, + layout=layout, + resize_scale=resize_scale, + bet_dwi_frac=bet_dwi, + bet_mag_frac=bet_mag, + total_readout=total_readout, ) datasink_wf = init_output_wf( - subject_id=subject_id, session_id=session_id, output_folder=output_dir + subject_id=subject_id, + session_id=session_id, + output_folder=output_dir, ) - dwi_preproc_wf.base_dir = os.path.join(os.path.abspath(work_dir), subject_id) + dwi_preproc_wf.base_dir = os.path.join( + os.path.abspath(work_dir), subject_id + ) inputspec = dwi_preproc_wf.get_node("inputnode") inputspec.inputs.subject_id = subject_id diff --git a/dmriprep/workflows/dwi/base.py b/dmriprep/workflows/dwi/base.py index 43d829f..e133b63 100755 --- a/dmriprep/workflows/dwi/base.py +++ b/dmriprep/workflows/dwi/base.py @@ -19,8 +19,9 @@ def init_dwi_preproc_wf( subject_id, dwi_file, - metadata, + dwi_meta, layout, + resize_scale, bet_dwi_frac, bet_mag_frac, total_readout, @@ -38,7 +39,7 @@ def init_dwi_preproc_wf( for fmap in fmaps: fmap["metadata"] = layout.get_metadata(fmap[fmap["suffix"]]) - sdc_wf = init_sdc_prep_wf(fmaps, metadata, layout, bet_mag_frac) + sdc_wf = init_sdc_prep_wf(fmaps, dwi_meta, layout, bet_mag_frac) dwi_wf = pe.Workflow(name="dwi_preproc_wf") @@ -47,7 +48,7 @@ def init_dwi_preproc_wf( fields=[ "subject_id", "dwi_file", - "metadata", + "di_meta", "bvec_file", "bval_file", "out_dir", @@ -66,7 +67,8 @@ def init_dwi_preproc_wf( unring = pe.Node(mrtrix3.MRDeGibbs(), name="unring") - resize = pe.Node(mrtrix3.MRResize(), name="resize") + if resize_scale: + resize = pe.Node(mrtrix3.MRResize(scale=resize_scale), name="resize") def gen_index(in_file): @@ -234,7 +236,7 @@ def get_b0_mask_fn(b0_file): ( inputnode, acqp, - [("dwi_file", "in_file"), ("metadata", "metadata")], + [("dwi_file", "in_file"), ("dwi_meta", "metadata")], ), (unring, ecc, [("out_file", "in_file")]), ( From d39949ac03702a92915525867a8ae82932cdd665 Mon Sep 17 00:00:00 2001 From: Michael Joseph Date: Mon, 8 Jul 2019 17:30:27 -0400 Subject: [PATCH 02/18] move package imports to top --- dmriprep/workflows/dwi/outputs.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/dmriprep/workflows/dwi/outputs.py b/dmriprep/workflows/dwi/outputs.py index 30cd1bc..c14fe3a 100644 --- a/dmriprep/workflows/dwi/outputs.py +++ b/dmriprep/workflows/dwi/outputs.py @@ -1,9 +1,12 @@ #!/usr/bin/env python +import os + +from nipype.pipeline import engine as pe +from nipype.interfaces import io as nio, utility as niu + def init_output_wf(subject_id, session_id, output_folder): - from nipype.pipeline import engine as pe - from nipype.interfaces import io as nio, utility as niu op_wf = pe.Workflow(name="output_wf") @@ -30,10 +33,13 @@ def init_output_wf(subject_id, session_id, output_folder): ) def build_path(output_folder, subject_id, session_id): - import os.path as op - return op.join( - output_folder, "dmriprep", "sub-" + subject_id, "ses-" + session_id, "dwi" + return os.path.join( + output_folder, + "dmriprep", + "sub-" + subject_id, + "ses-" + session_id, + "dwi", ) concat = pe.Node( From e2c08434ebfa7e6b8397e4c47139b53acc64b85d Mon Sep 17 00:00:00 2001 From: Michael Joseph Date: Mon, 8 Jul 2019 17:30:49 -0400 Subject: [PATCH 03/18] update docs --- docs/dmriprep.interfaces.rst | 30 ++++++++++++++++++ docs/dmriprep.rst | 46 ++++++++++++++++++++++++++++ docs/dmriprep.workflows.dwi.rst | 38 +++++++++++++++++++++++ docs/dmriprep.workflows.fieldmap.rst | 38 +++++++++++++++++++++++ docs/dmriprep.workflows.rst | 30 ++++++++++++++++++ docs/modules.rst | 7 +++++ 6 files changed, 189 insertions(+) create mode 100644 docs/dmriprep.interfaces.rst create mode 100644 docs/dmriprep.rst create mode 100644 docs/dmriprep.workflows.dwi.rst create mode 100644 docs/dmriprep.workflows.fieldmap.rst create mode 100644 docs/dmriprep.workflows.rst create mode 100644 docs/modules.rst diff --git a/docs/dmriprep.interfaces.rst b/docs/dmriprep.interfaces.rst new file mode 100644 index 0000000..a751746 --- /dev/null +++ b/docs/dmriprep.interfaces.rst @@ -0,0 +1,30 @@ +dmriprep.interfaces package +=========================== + +Submodules +---------- + +dmriprep.interfaces.fmap module +------------------------------- + +.. automodule:: dmriprep.interfaces.fmap + :members: + :undoc-members: + :show-inheritance: + +dmriprep.interfaces.mrtrix3 module +---------------------------------- + +.. automodule:: dmriprep.interfaces.mrtrix3 + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: dmriprep.interfaces + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/dmriprep.rst b/docs/dmriprep.rst new file mode 100644 index 0000000..4fef8f4 --- /dev/null +++ b/docs/dmriprep.rst @@ -0,0 +1,46 @@ +dmriprep package +================ + +Subpackages +----------- + +.. toctree:: + + dmriprep.interfaces + dmriprep.workflows + +Submodules +---------- + +dmriprep.cli module +------------------- + +.. automodule:: dmriprep.cli + :members: + :undoc-members: + :show-inheritance: + +dmriprep.qc module +------------------ + +.. automodule:: dmriprep.qc + :members: + :undoc-members: + :show-inheritance: + +dmriprep.utils module +--------------------- + +.. automodule:: dmriprep.utils + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: dmriprep + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/dmriprep.workflows.dwi.rst b/docs/dmriprep.workflows.dwi.rst new file mode 100644 index 0000000..187803f --- /dev/null +++ b/docs/dmriprep.workflows.dwi.rst @@ -0,0 +1,38 @@ +dmriprep.workflows.dwi package +============================== + +Submodules +---------- + +dmriprep.workflows.dwi.base module +---------------------------------- + +.. automodule:: dmriprep.workflows.dwi.base + :members: + :undoc-members: + :show-inheritance: + +dmriprep.workflows.dwi.outputs module +------------------------------------- + +.. automodule:: dmriprep.workflows.dwi.outputs + :members: + :undoc-members: + :show-inheritance: + +dmriprep.workflows.dwi.tensor module +------------------------------------ + +.. automodule:: dmriprep.workflows.dwi.tensor + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: dmriprep.workflows.dwi + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/dmriprep.workflows.fieldmap.rst b/docs/dmriprep.workflows.fieldmap.rst new file mode 100644 index 0000000..73619ae --- /dev/null +++ b/docs/dmriprep.workflows.fieldmap.rst @@ -0,0 +1,38 @@ +dmriprep.workflows.fieldmap package +=================================== + +Submodules +---------- + +dmriprep.workflows.fieldmap.base module +--------------------------------------- + +.. automodule:: dmriprep.workflows.fieldmap.base + :members: + :undoc-members: + :show-inheritance: + +dmriprep.workflows.fieldmap.fmap module +--------------------------------------- + +.. automodule:: dmriprep.workflows.fieldmap.fmap + :members: + :undoc-members: + :show-inheritance: + +dmriprep.workflows.fieldmap.phasediff module +-------------------------------------------- + +.. automodule:: dmriprep.workflows.fieldmap.phasediff + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: dmriprep.workflows.fieldmap + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/dmriprep.workflows.rst b/docs/dmriprep.workflows.rst new file mode 100644 index 0000000..8dc264f --- /dev/null +++ b/docs/dmriprep.workflows.rst @@ -0,0 +1,30 @@ +dmriprep.workflows package +========================== + +Subpackages +----------- + +.. toctree:: + + dmriprep.workflows.dwi + dmriprep.workflows.fieldmap + +Submodules +---------- + +dmriprep.workflows.base module +------------------------------ + +.. automodule:: dmriprep.workflows.base + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: dmriprep.workflows + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/modules.rst b/docs/modules.rst new file mode 100644 index 0000000..05dd5a9 --- /dev/null +++ b/docs/modules.rst @@ -0,0 +1,7 @@ +dmriprep +======== + +.. toctree:: + :maxdepth: 4 + + dmriprep From d02c7bcdaa60d6f709669468c63ece902d539619 Mon Sep 17 00:00:00 2001 From: Michael Joseph Date: Mon, 8 Jul 2019 17:31:04 -0400 Subject: [PATCH 04/18] temp tensor module --- dmriprep/workflows/dwi/tensor.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 dmriprep/workflows/dwi/tensor.py diff --git a/dmriprep/workflows/dwi/tensor.py b/dmriprep/workflows/dwi/tensor.py new file mode 100644 index 0000000..e69de29 From c4690b67f30f2a47e92374aac9fe3b92463a374c Mon Sep 17 00:00:00 2001 From: Michael Joseph Date: Mon, 8 Jul 2019 17:34:57 -0400 Subject: [PATCH 05/18] update grabbing fmap metadata --- dmriprep/workflows/dwi/base.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/dmriprep/workflows/dwi/base.py b/dmriprep/workflows/dwi/base.py index e133b63..dfc3588 100755 --- a/dmriprep/workflows/dwi/base.py +++ b/dmriprep/workflows/dwi/base.py @@ -37,7 +37,12 @@ def init_dwi_preproc_wf( ) for fmap in fmaps: - fmap["metadata"] = layout.get_metadata(fmap[fmap["suffix"]]) + if fmap["suffix"] == "phase": + fmap["metadata"] = {} + fmap["metadata"]["phase1"] = layout.get_metadata(fmap["phase1"]) + fmap["metadata"]["phase2"] = layout.get_metadata(fmap["phase2"]) + else: + fmap["metadata"] = layout.get_metadata(fmap[fmap["suffix"]]) sdc_wf = init_sdc_prep_wf(fmaps, dwi_meta, layout, bet_mag_frac) From 80005d0cc97f9c1ad75620a2d7c4ce2b660a420b Mon Sep 17 00:00:00 2001 From: Michael Joseph Date: Mon, 8 Jul 2019 17:36:12 -0400 Subject: [PATCH 06/18] rename dmriprep to dmripreproc --- .github/ISSUE_TEMPLATE.md | 2 +- .travis.yml | 2 +- CONTRIBUTING.rst | 28 ++++++++-------- Makefile | 8 ++--- README.md | 32 +++++++++---------- {dmriprep => dmripreproc}/__init__.py | 8 ++--- {dmriprep => dmripreproc}/cli.py | 8 ++--- .../interfaces/__init__.py | 0 {dmriprep => dmripreproc}/interfaces/fmap.py | 0 .../interfaces/mrtrix3.py | 0 {dmriprep => dmripreproc}/qc.py | 0 {dmriprep => dmripreproc}/utils.py | 0 .../workflows/__init__.py | 0 {dmriprep => dmripreproc}/workflows/base.py | 12 +++---- .../workflows/dwi/__init__.py | 0 .../workflows/dwi/base.py | 0 .../workflows/dwi/outputs.py | 2 +- .../workflows/dwi/tensor.py | 0 .../workflows/fieldmap/__init__.py | 0 .../workflows/fieldmap/base.py | 0 .../workflows/fieldmap/fmap.py | 0 .../workflows/fieldmap/phasediff.py | 0 docs/Makefile | 2 +- docs/conf.py | 26 +++++++-------- docs/dmriprep.interfaces.rst | 12 +++---- docs/dmriprep.rst | 20 ++++++------ docs/dmriprep.workflows.dwi.rst | 16 +++++----- docs/dmriprep.workflows.fieldmap.rst | 16 +++++----- docs/dmriprep.workflows.rst | 12 +++---- docs/img/dmriprep_icon.svg | 4 +-- docs/index.rst | 2 +- docs/installation.rst | 16 +++++----- docs/make.bat | 2 +- docs/modules.rst | 4 +-- docs/usage.rst | 4 +-- setup.cfg | 2 +- setup.py | 14 ++++---- tests/test_dmriprep.py | 4 +-- tests/test_utils.py | 4 +-- tox.ini | 2 +- 40 files changed, 132 insertions(+), 132 deletions(-) rename {dmriprep => dmripreproc}/__init__.py (85%) rename {dmriprep => dmripreproc}/cli.py (95%) rename {dmriprep => dmripreproc}/interfaces/__init__.py (100%) rename {dmriprep => dmripreproc}/interfaces/fmap.py (100%) rename {dmriprep => dmripreproc}/interfaces/mrtrix3.py (100%) rename {dmriprep => dmripreproc}/qc.py (100%) rename {dmriprep => dmripreproc}/utils.py (100%) rename {dmriprep => dmripreproc}/workflows/__init__.py (100%) rename {dmriprep => dmripreproc}/workflows/base.py (93%) rename {dmriprep => dmripreproc}/workflows/dwi/__init__.py (100%) rename {dmriprep => dmripreproc}/workflows/dwi/base.py (100%) rename {dmriprep => dmripreproc}/workflows/dwi/outputs.py (98%) rename {dmriprep => dmripreproc}/workflows/dwi/tensor.py (100%) rename {dmriprep => dmripreproc}/workflows/fieldmap/__init__.py (100%) rename {dmriprep => dmripreproc}/workflows/fieldmap/base.py (100%) rename {dmriprep => dmripreproc}/workflows/fieldmap/fmap.py (100%) rename {dmriprep => dmripreproc}/workflows/fieldmap/phasediff.py (100%) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 8221575..b1e3287 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,4 +1,4 @@ -* dmriprep version: +* dmriprepoc version: * Python version: * Operating System: diff --git a/.travis.yml b/.travis.yml index fee7fbc..3f5e833 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,5 +24,5 @@ deploy: secure: PLEASE_REPLACE_ME on: tags: true - repo: tigrlab/dmripreproc + repo: tigrlab/dmriprepocroc python: 3.7 diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 2896e4d..7b7906a 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -7,10 +7,10 @@ Contributing Contributions are welcome, and they are greatly appreciated! Every little bit helps, and credit will always be given. -Installing a development version of dmriprep +Installing a development version of dmriprepoc -------------------------------------------- -First, you can install a development version of dmriprep by cloning this repository +First, you can install a development version of dmriprepoc by cloning this repository and then typing:: $ pip install -e .[dev] @@ -32,7 +32,7 @@ You can contribute in many ways: Report Bugs ~~~~~~~~~~~ -Report bugs at https://github.com/nipy/dmriprep/issues. +Report bugs at https://github.com/nipy/dmriprepoc/issues. If you are reporting a bug, please include: @@ -55,14 +55,14 @@ and "help wanted" is open to whoever wants to implement it. Write Documentation ~~~~~~~~~~~~~~~~~~~ -dmriprep could always use more documentation, whether as part of the -official dmriprep docs, in docstrings, or even on the web in blog posts, +dmriprepoc could always use more documentation, whether as part of the +official dmriprepoc docs, in docstrings, or even on the web in blog posts, articles, and such. Submit Feedback ~~~~~~~~~~~~~~~ -The best way to send feedback is to file an issue at https://github.com/nipy/dmriprep/issues. +The best way to send feedback is to file an issue at https://github.com/nipy/dmriprepoc/issues. If you are proposing a feature: @@ -74,17 +74,17 @@ If you are proposing a feature: Get Started! ------------ -Ready to contribute? Here's how to set up `dmriprep` for local development. +Ready to contribute? Here's how to set up `dmriprepoc` for local development. -1. Fork the `dmriprep` repo on GitHub. +1. Fork the `dmriprepoc` repo on GitHub. 2. Clone your fork locally:: - $ git clone git@github.com:your_name_here/dmriprep.git + $ git clone git@github.com:your_name_here/dmriprepoc.git 3. Install your local copy into a virtualenv. Assuming you have virtualenvwrapper installed, this is how you set up your fork for local development:: - $ mkvirtualenv dmriprep - $ cd dmriprep/ + $ mkvirtualenv dmriprepoc + $ cd dmriprepoc/ $ python setup.py develop 4. Create a branch for local development:: @@ -96,7 +96,7 @@ Ready to contribute? Here's how to set up `dmriprep` for local development. 5. When you're done making changes, check that your changes pass flake8 and the tests, including testing other Python versions with tox:: - $ flake8 dmriprep tests + $ flake8 dmriprepoc tests $ python setup.py test or py.test $ tox @@ -120,7 +120,7 @@ Before you submit a pull request, check that it meets these guidelines: your new functionality into a function with a docstring, and add the feature to the list in README.rst. 3. The pull request should work for Python 3.5, 3.6 and 3.7, and for PyPy. Check - https://travis-ci.org/nipy/dmriprep/pull_requests + https://travis-ci.org/nipy/dmriprepoc/pull_requests and make sure that the tests pass for all supported Python versions. When opening a pull request, please use one of the following prefixes: @@ -137,7 +137,7 @@ Tips To run a subset of tests:: -$ py.test tests.test_dmriprep +$ py.test tests.test_dmriprepoc Deploying diff --git a/Makefile b/Makefile index 7f76d45..88ba6d8 100644 --- a/Makefile +++ b/Makefile @@ -51,7 +51,7 @@ clean-test: ## remove test and coverage artifacts rm -fr .pytest_cache lint: ## check style with flake8 - flake8 dmriprep tests + flake8 dmriprepoc tests test: ## run tests quickly with the default Python py.test @@ -60,15 +60,15 @@ test-all: ## run tests on every Python version with tox tox coverage: ## check code coverage quickly with the default Python - coverage run --source dmriprep -m pytest + coverage run --source dmriprepoc -m pytest coverage report -m coverage html $(BROWSER) htmlcov/index.html docs: ## generate Sphinx HTML documentation, including API docs - rm -f docs/dmriprep.rst + rm -f docs/dmriprepoc.rst rm -f docs/modules.rst - sphinx-apidoc -o docs/ dmriprep + sphinx-apidoc -o docs/ dmriprepoc $(MAKE) -C docs clean $(MAKE) -C docs html $(BROWSER) docs/_build/html/index.html diff --git a/README.md b/README.md index ed75296..dc65c3e 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,16 @@ -[![Known Vulnerabilities](https://snyk.io/test/github/nipy/dmriprep/badge.svg)](https://snyk.io/test/github/nipy/dmriprep) -[![Documentation Status](https://readthedocs.org/projects/dmriprep/badge/?version=latest)](httpsL//dmriprep.readthredocs.io/en/latest/?badge=latest) -[![Build Status](https://travis-ci.org/nipy/dmriprep.png?branch=master)](https://travis-ci.org/nipy/dmriprep) -[![Coverage Status](https://coveralls.io/repos/github/nipy/dmriprep/badge.svg?branch=master)](https://coveralls.io/github/nipy/dmriprep?branch=master) +[![Known Vulnerabilities](https://snyk.io/test/github/nipy/dmriprepoc/badge.svg)](https://snyk.io/test/github/nipy/dmriprepoc) +[![Documentation Status](https://readthedocs.org/projects/dmriprepoc/badge/?version=latest)](httpsL//dmriprepoc.readthredocs.io/en/latest/?badge=latest) +[![Build Status](https://travis-ci.org/nipy/dmriprepoc.png?branch=master)](https://travis-ci.org/nipy/dmriprepoc) +[![Coverage Status](https://coveralls.io/repos/github/nipy/dmriprepoc/badge.svg?branch=master)](https://coveralls.io/github/nipy/dmriprepoc?branch=master) [![License](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause) [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/python/black) -# dmriprep dmriprep +# dmriprepoc dmriprepoc Preprocessing of neuroimaging data in preparation for AFQ analysis * Free software: BSD license -* Documentation: https://dmriprep.readthedocs.io. +* Documentation: https://dmriprepoc.readthedocs.io. ## Preparing your data @@ -34,28 +34,28 @@ You should have raw data organized in the BIDS format. Also, you should have run ## Quickstart ```bash -git clone https://github.com/nipy/dmriprep -cd dmriprep +git clone https://github.com/nipy/dmriprepoc +cd dmriprepoc python setup.py install -dmriprep $BIDS_INPUT_DIR $OUTPUT_DIR --participant-label 01 +dmriprepoc $BIDS_INPUT_DIR $OUTPUT_DIR --participant-label 01 ``` ```bash -git clone https://github.com/nipy/dmriprep -cd dmriprep +git clone https://github.com/nipy/dmriprepoc +cd dmriprepoc make docker # If you don't want to log into the docker image: -docker run -ti -v $BIDS_INPUT_DIR:/inputs -v $OUTPUT_DIR:/outputs dmriprep:prod dmriprep /inputs /outputs +docker run -ti -v $BIDS_INPUT_DIR:/inputs -v $OUTPUT_DIR:/outputs dmriprepoc:prod dmriprepoc /inputs /outputs # If you want to log into the image: -docker run -ti -v $BIDS_INPUT_DIR:/inputs -v $OUTPUT_DIR:/outputs dmriprep:prod +docker run -ti -v $BIDS_INPUT_DIR:/inputs -v $OUTPUT_DIR:/outputs dmriprepoc:prod # Run this inside the docker image: -dmriprep /inputs /outpus --participant-label 01 +dmriprepoc /inputs /outpus --participant-label 01 ``` ## Features @@ -64,11 +64,11 @@ dmriprep /inputs /outpus --participant-label 01 ## Contributing -We love contributions! dmriprep is open source, built on open source, +We love contributions! dmriprepoc is open source, built on open source, and we'd love to have you hang out in our community. We have developed some [guidelines](CONTRIBUTING.rst) for contributing to -dmriprep. +dmriprepoc. **Imposter syndrome disclaimer**: We want your help. No, really. diff --git a/dmriprep/__init__.py b/dmripreproc/__init__.py similarity index 85% rename from dmriprep/__init__.py rename to dmripreproc/__init__.py index d7678e1..ea3a9a8 100644 --- a/dmriprep/__init__.py +++ b/dmripreproc/__init__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -"""Top-level package for dmriprep.""" +"""Top-level package for dmriprepoc.""" __author__ = """Anisha Keshavan""" __email__ = "anishakeshavan@gmail.com" @@ -22,13 +22,13 @@ # get the log level from environment variable if "DMIRPREP_LOGLEVEL" in os.environ: - loglevel = os.environ["DMRIPREP_LOGLEVEL"] + loglevel = os.environ["dmriprepoc_LOGLEVEL"] module_logger.setLevel(getattr(logging, loglevel.upper())) else: module_logger.setLevel(logging.WARNING) # create a file handler -logpath = os.path.join(os.path.expanduser("~"), ".dmriprep", "dmriprep.log") +logpath = os.path.join(os.path.expanduser("~"), ".dmriprepoc", "dmriprepoc.log") # Create the config directory if it doesn't exist logdir = os.path.dirname(logpath) @@ -52,4 +52,4 @@ # add the handlers to the logger module_logger.addHandler(handler) -module_logger.info("Started new dmriprep session") +module_logger.info("Started new dmriprepoc session") diff --git a/dmriprep/cli.py b/dmripreproc/cli.py similarity index 95% rename from dmriprep/cli.py rename to dmripreproc/cli.py index 9dce15c..ad21a3c 100644 --- a/dmriprep/cli.py +++ b/dmripreproc/cli.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -"""Console script for dmriprep.""" +"""Console script for dmriprepoc.""" import os import sys import warnings @@ -9,7 +9,7 @@ import click from . import utils -from .workflows.base import init_dmriprep_wf +from .workflows.base import init_dmriprepoc_wf # Filter warnings that are visible whenever you import another package that # was compiled against an older numpy than is installed. @@ -104,7 +104,7 @@ def main( """ if analysis_level is not "participant": raise NotImplementedError( - "The only valid analysis level for dmriprep " + "The only valid analysis level for dmriprepoc " "is participant at the moment." ) @@ -114,7 +114,7 @@ def main( ) work_dir = os.path.join(output_dir, "scratch") - wf = init_dmriprep_wf( + wf = init_dmriprepoc_wf( layout, subject_list, work_dir, diff --git a/dmriprep/interfaces/__init__.py b/dmripreproc/interfaces/__init__.py similarity index 100% rename from dmriprep/interfaces/__init__.py rename to dmripreproc/interfaces/__init__.py diff --git a/dmriprep/interfaces/fmap.py b/dmripreproc/interfaces/fmap.py similarity index 100% rename from dmriprep/interfaces/fmap.py rename to dmripreproc/interfaces/fmap.py diff --git a/dmriprep/interfaces/mrtrix3.py b/dmripreproc/interfaces/mrtrix3.py similarity index 100% rename from dmriprep/interfaces/mrtrix3.py rename to dmripreproc/interfaces/mrtrix3.py diff --git a/dmriprep/qc.py b/dmripreproc/qc.py similarity index 100% rename from dmriprep/qc.py rename to dmripreproc/qc.py diff --git a/dmriprep/utils.py b/dmripreproc/utils.py similarity index 100% rename from dmriprep/utils.py rename to dmripreproc/utils.py diff --git a/dmriprep/workflows/__init__.py b/dmripreproc/workflows/__init__.py similarity index 100% rename from dmriprep/workflows/__init__.py rename to dmripreproc/workflows/__init__.py diff --git a/dmriprep/workflows/base.py b/dmripreproc/workflows/base.py similarity index 93% rename from dmriprep/workflows/base.py rename to dmripreproc/workflows/base.py index 588db76..80f0278 100644 --- a/dmriprep/workflows/base.py +++ b/dmripreproc/workflows/base.py @@ -7,7 +7,7 @@ from .dwi import init_dwi_preproc_wf, init_output_wf -def init_dmriprep_wf( +def init_dmriprepoc_wf( layout, subject_list, work_dir, @@ -17,8 +17,8 @@ def init_dmriprep_wf( bet_mag, total_readout, ): - dmriprep_wf = pe.Workflow(name="dmriprep_wf") - dmriprep_wf.base_dir = work_dir + dmriprepoc_wf = pe.Workflow(name="dmriprepoc_wf") + dmriprepoc_wf.base_dir = work_dir for subject_id in subject_list: @@ -35,15 +35,15 @@ def init_dmriprep_wf( ) single_subject_wf.config["execution"]["crashdump_dir"] = os.path.join( - output_dir, "dmriprep", "sub-" + subject_id, "log" + output_dir, "dmriprepoc", "sub-" + subject_id, "log" ) for node in single_subject_wf._get_all_nodes(): node.config = deepcopy(single_subject_wf.config) - dmriprep_wf.add_nodes([single_subject_wf]) + dmriprepoc_wf.add_nodes([single_subject_wf]) - return dmriprep_wf + return dmriprepoc_wf def init_single_subject_wf( diff --git a/dmriprep/workflows/dwi/__init__.py b/dmripreproc/workflows/dwi/__init__.py similarity index 100% rename from dmriprep/workflows/dwi/__init__.py rename to dmripreproc/workflows/dwi/__init__.py diff --git a/dmriprep/workflows/dwi/base.py b/dmripreproc/workflows/dwi/base.py similarity index 100% rename from dmriprep/workflows/dwi/base.py rename to dmripreproc/workflows/dwi/base.py diff --git a/dmriprep/workflows/dwi/outputs.py b/dmripreproc/workflows/dwi/outputs.py similarity index 98% rename from dmriprep/workflows/dwi/outputs.py rename to dmripreproc/workflows/dwi/outputs.py index c14fe3a..a69322f 100644 --- a/dmriprep/workflows/dwi/outputs.py +++ b/dmripreproc/workflows/dwi/outputs.py @@ -36,7 +36,7 @@ def build_path(output_folder, subject_id, session_id): return os.path.join( output_folder, - "dmriprep", + "dmriprepoc", "sub-" + subject_id, "ses-" + session_id, "dwi", diff --git a/dmriprep/workflows/dwi/tensor.py b/dmripreproc/workflows/dwi/tensor.py similarity index 100% rename from dmriprep/workflows/dwi/tensor.py rename to dmripreproc/workflows/dwi/tensor.py diff --git a/dmriprep/workflows/fieldmap/__init__.py b/dmripreproc/workflows/fieldmap/__init__.py similarity index 100% rename from dmriprep/workflows/fieldmap/__init__.py rename to dmripreproc/workflows/fieldmap/__init__.py diff --git a/dmriprep/workflows/fieldmap/base.py b/dmripreproc/workflows/fieldmap/base.py similarity index 100% rename from dmriprep/workflows/fieldmap/base.py rename to dmripreproc/workflows/fieldmap/base.py diff --git a/dmriprep/workflows/fieldmap/fmap.py b/dmripreproc/workflows/fieldmap/fmap.py similarity index 100% rename from dmriprep/workflows/fieldmap/fmap.py rename to dmripreproc/workflows/fieldmap/fmap.py diff --git a/dmriprep/workflows/fieldmap/phasediff.py b/dmripreproc/workflows/fieldmap/phasediff.py similarity index 100% rename from dmriprep/workflows/fieldmap/phasediff.py rename to dmripreproc/workflows/fieldmap/phasediff.py diff --git a/docs/Makefile b/docs/Makefile index 9b90b86..22b578e 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -4,7 +4,7 @@ # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = python -msphinx -SPHINXPROJ = dmriprep +SPHINXPROJ = dmriprepoc SOURCEDIR = . BUILDDIR = _build diff --git a/docs/conf.py b/docs/conf.py index 97b2a08..1969c5d 100755 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- # -# dmriprep documentation build configuration file, created by +# dmriprepoc documentation build configuration file, created by # sphinx-quickstart on Fri Jun 9 13:47:02 2017. # # This file is execfile()d with the current directory set to its @@ -22,7 +22,7 @@ import sys sys.path.insert(0, os.path.abspath('..')) -import dmriprep +import dmriprepoc # -- General configuration --------------------------------------------- @@ -47,7 +47,7 @@ master_doc = 'index' # General information about the project. -project = u'dmriprep' +project = u'dmriprepoc' copyright = u"2018, Anisha Keshavan" author = u"Anisha Keshavan" @@ -56,9 +56,9 @@ # the built documents. # # The short X.Y version. -version = dmriprep.__version__ +version = dmriprepoc.__version__ # The full version, including alpha/beta/rc tags. -release = dmriprep.__version__ +release = dmriprepoc.__version__ # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -101,7 +101,7 @@ # -- Options for HTMLHelp output --------------------------------------- # Output file base name for HTML help builder. -htmlhelp_basename = 'dmriprepdoc' +htmlhelp_basename = 'dmriprepocdoc' # -- Options for LaTeX output ------------------------------------------ @@ -128,8 +128,8 @@ # (source start file, target name, title, author, documentclass # [howto, manual, or own class]). latex_documents = [ - (master_doc, 'dmriprep.tex', - u'dmriprep Documentation', + (master_doc, 'dmriprepoc.tex', + u'dmriprepoc Documentation', u'Anisha Keshavan', 'manual'), ] @@ -139,8 +139,8 @@ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - (master_doc, 'dmriprep', - u'dmriprep Documentation', + (master_doc, 'dmriprepoc', + u'dmriprepoc Documentation', [author], 1) ] @@ -151,10 +151,10 @@ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - (master_doc, 'dmriprep', - u'dmriprep Documentation', + (master_doc, 'dmriprepoc', + u'dmriprepoc Documentation', author, - 'dmriprep', + 'dmriprepoc', 'One line description of project.', 'Miscellaneous'), ] diff --git a/docs/dmriprep.interfaces.rst b/docs/dmriprep.interfaces.rst index a751746..8189058 100644 --- a/docs/dmriprep.interfaces.rst +++ b/docs/dmriprep.interfaces.rst @@ -1,21 +1,21 @@ -dmriprep.interfaces package +dmriprepoc.interfaces package =========================== Submodules ---------- -dmriprep.interfaces.fmap module +dmriprepoc.interfaces.fmap module ------------------------------- -.. automodule:: dmriprep.interfaces.fmap +.. automodule:: dmriprepoc.interfaces.fmap :members: :undoc-members: :show-inheritance: -dmriprep.interfaces.mrtrix3 module +dmriprepoc.interfaces.mrtrix3 module ---------------------------------- -.. automodule:: dmriprep.interfaces.mrtrix3 +.. automodule:: dmriprepoc.interfaces.mrtrix3 :members: :undoc-members: :show-inheritance: @@ -24,7 +24,7 @@ dmriprep.interfaces.mrtrix3 module Module contents --------------- -.. automodule:: dmriprep.interfaces +.. automodule:: dmriprepoc.interfaces :members: :undoc-members: :show-inheritance: diff --git a/docs/dmriprep.rst b/docs/dmriprep.rst index 4fef8f4..dd17d08 100644 --- a/docs/dmriprep.rst +++ b/docs/dmriprep.rst @@ -1,4 +1,4 @@ -dmriprep package +dmriprepoc package ================ Subpackages @@ -6,32 +6,32 @@ Subpackages .. toctree:: - dmriprep.interfaces - dmriprep.workflows + dmriprepoc.interfaces + dmriprepoc.workflows Submodules ---------- -dmriprep.cli module +dmriprepoc.cli module ------------------- -.. automodule:: dmriprep.cli +.. automodule:: dmriprepoc.cli :members: :undoc-members: :show-inheritance: -dmriprep.qc module +dmriprepoc.qc module ------------------ -.. automodule:: dmriprep.qc +.. automodule:: dmriprepoc.qc :members: :undoc-members: :show-inheritance: -dmriprep.utils module +dmriprepoc.utils module --------------------- -.. automodule:: dmriprep.utils +.. automodule:: dmriprepoc.utils :members: :undoc-members: :show-inheritance: @@ -40,7 +40,7 @@ dmriprep.utils module Module contents --------------- -.. automodule:: dmriprep +.. automodule:: dmriprepoc :members: :undoc-members: :show-inheritance: diff --git a/docs/dmriprep.workflows.dwi.rst b/docs/dmriprep.workflows.dwi.rst index 187803f..66a921f 100644 --- a/docs/dmriprep.workflows.dwi.rst +++ b/docs/dmriprep.workflows.dwi.rst @@ -1,29 +1,29 @@ -dmriprep.workflows.dwi package +dmriprepoc.workflows.dwi package ============================== Submodules ---------- -dmriprep.workflows.dwi.base module +dmriprepoc.workflows.dwi.base module ---------------------------------- -.. automodule:: dmriprep.workflows.dwi.base +.. automodule:: dmriprepoc.workflows.dwi.base :members: :undoc-members: :show-inheritance: -dmriprep.workflows.dwi.outputs module +dmriprepoc.workflows.dwi.outputs module ------------------------------------- -.. automodule:: dmriprep.workflows.dwi.outputs +.. automodule:: dmriprepoc.workflows.dwi.outputs :members: :undoc-members: :show-inheritance: -dmriprep.workflows.dwi.tensor module +dmriprepoc.workflows.dwi.tensor module ------------------------------------ -.. automodule:: dmriprep.workflows.dwi.tensor +.. automodule:: dmriprepoc.workflows.dwi.tensor :members: :undoc-members: :show-inheritance: @@ -32,7 +32,7 @@ dmriprep.workflows.dwi.tensor module Module contents --------------- -.. automodule:: dmriprep.workflows.dwi +.. automodule:: dmriprepoc.workflows.dwi :members: :undoc-members: :show-inheritance: diff --git a/docs/dmriprep.workflows.fieldmap.rst b/docs/dmriprep.workflows.fieldmap.rst index 73619ae..6ad3e48 100644 --- a/docs/dmriprep.workflows.fieldmap.rst +++ b/docs/dmriprep.workflows.fieldmap.rst @@ -1,29 +1,29 @@ -dmriprep.workflows.fieldmap package +dmriprepoc.workflows.fieldmap package =================================== Submodules ---------- -dmriprep.workflows.fieldmap.base module +dmriprepoc.workflows.fieldmap.base module --------------------------------------- -.. automodule:: dmriprep.workflows.fieldmap.base +.. automodule:: dmriprepoc.workflows.fieldmap.base :members: :undoc-members: :show-inheritance: -dmriprep.workflows.fieldmap.fmap module +dmriprepoc.workflows.fieldmap.fmap module --------------------------------------- -.. automodule:: dmriprep.workflows.fieldmap.fmap +.. automodule:: dmriprepoc.workflows.fieldmap.fmap :members: :undoc-members: :show-inheritance: -dmriprep.workflows.fieldmap.phasediff module +dmriprepoc.workflows.fieldmap.phasediff module -------------------------------------------- -.. automodule:: dmriprep.workflows.fieldmap.phasediff +.. automodule:: dmriprepoc.workflows.fieldmap.phasediff :members: :undoc-members: :show-inheritance: @@ -32,7 +32,7 @@ dmriprep.workflows.fieldmap.phasediff module Module contents --------------- -.. automodule:: dmriprep.workflows.fieldmap +.. automodule:: dmriprepoc.workflows.fieldmap :members: :undoc-members: :show-inheritance: diff --git a/docs/dmriprep.workflows.rst b/docs/dmriprep.workflows.rst index 8dc264f..11d0f65 100644 --- a/docs/dmriprep.workflows.rst +++ b/docs/dmriprep.workflows.rst @@ -1,4 +1,4 @@ -dmriprep.workflows package +dmriprepoc.workflows package ========================== Subpackages @@ -6,16 +6,16 @@ Subpackages .. toctree:: - dmriprep.workflows.dwi - dmriprep.workflows.fieldmap + dmriprepoc.workflows.dwi + dmriprepoc.workflows.fieldmap Submodules ---------- -dmriprep.workflows.base module +dmriprepoc.workflows.base module ------------------------------ -.. automodule:: dmriprep.workflows.base +.. automodule:: dmriprepoc.workflows.base :members: :undoc-members: :show-inheritance: @@ -24,7 +24,7 @@ dmriprep.workflows.base module Module contents --------------- -.. automodule:: dmriprep.workflows +.. automodule:: dmriprepoc.workflows :members: :undoc-members: :show-inheritance: diff --git a/docs/img/dmriprep_icon.svg b/docs/img/dmriprep_icon.svg index ce8ba16..e6df76d 100644 --- a/docs/img/dmriprep_icon.svg +++ b/docs/img/dmriprep_icon.svg @@ -1,9 +1,9 @@ -dmriprepdmriprepoc \ No newline at end of file diff --git a/docs/index.rst b/docs/index.rst index d654265..92dcb5b 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,4 +1,4 @@ -Welcome to dmriprep's documentation! +Welcome to dmriprepoc's documentation! ====================================== .. toctree:: diff --git a/docs/installation.rst b/docs/installation.rst index 9a80cbc..d56cd9c 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -8,13 +8,13 @@ Installation Stable release -------------- -To install dmriprep, run this command in your terminal: +To install dmriprepoc, run this command in your terminal: .. code-block:: console - $ pip install dmriprep + $ pip install dmriprepoc -This is the preferred method to install dmriprep, as it will always install the most recent stable release. +This is the preferred method to install dmriprepoc, as it will always install the most recent stable release. If you don't have `pip`_ installed, this `Python installation guide`_ can guide you through the process. @@ -26,19 +26,19 @@ you through the process. From sources ------------ -The sources for dmriprep can be downloaded from the `Github repo`_. +The sources for dmriprepoc can be downloaded from the `Github repo`_. You can either clone the public repository: .. code-block:: console - $ git clone git://github.com/nipy/dmriprep + $ git clone git://github.com/nipy/dmriprepoc Or download the `tarball`_: .. code-block:: console - $ curl -OL https://github.com/nipy/dmriprep/tarball/master + $ curl -OL https://github.com/nipy/dmriprepoc/tarball/master Once you have a copy of the source, you can install it with: @@ -47,5 +47,5 @@ Once you have a copy of the source, you can install it with: $ python setup.py install -.. _Github repo: https://github.com/nipy/dmriprep -.. _tarball: https://github.com/nipy/dmriprep/tarball/master +.. _Github repo: https://github.com/nipy/dmriprepoc +.. _tarball: https://github.com/nipy/dmriprepoc/tarball/master diff --git a/docs/make.bat b/docs/make.bat index c8af47b..265138e 100644 --- a/docs/make.bat +++ b/docs/make.bat @@ -9,7 +9,7 @@ if "%SPHINXBUILD%" == "" ( ) set SOURCEDIR=. set BUILDDIR=_build -set SPHINXPROJ=dmriprep +set SPHINXPROJ=dmriprepoc if "%1" == "" goto help diff --git a/docs/modules.rst b/docs/modules.rst index 05dd5a9..1e0222c 100644 --- a/docs/modules.rst +++ b/docs/modules.rst @@ -1,7 +1,7 @@ -dmriprep +dmriprepoc ======== .. toctree:: :maxdepth: 4 - dmriprep + dmriprepoc diff --git a/docs/usage.rst b/docs/usage.rst index a747741..56bc3cf 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -2,6 +2,6 @@ Usage ===== -To use dmriprep in a project:: +To use dmriprepoc in a project:: - import dmriprep + import dmriprepoc diff --git a/setup.cfg b/setup.cfg index c9b349a..da6c0ce 100644 --- a/setup.cfg +++ b/setup.cfg @@ -7,7 +7,7 @@ tag = True search = version='{current_version}' replace = version='{new_version}' -[bumpversion:file:dmriprep/__init__.py] +[bumpversion:file:dmriprepoc/__init__.py] search = __version__ = '{current_version}' replace = __version__ = '{new_version}' diff --git a/setup.py b/setup.py index b4add0a..c093d64 100644 --- a/setup.py +++ b/setup.py @@ -44,9 +44,9 @@ description="Preprocessing of neuroimaging data in preparation for AFQ analysis", entry_points={ "console_scripts": [ - "dmriprep=dmriprep.cli:main", - "dmriprep-data=dmriprep.cli:data", - "dmriprep-upload=dmriprep.cli:upload", + "dmriprepoc=dmriprepoc.cli:main", + "dmriprepoc-data=dmriprepoc.cli:data", + "dmriprepoc-upload=dmriprepoc.cli:upload", ] }, install_requires=requirements, @@ -54,13 +54,13 @@ license="BSD license", long_description=readme + "\n\n" + history, include_package_data=True, - keywords="dmriprep", - name="dmriprep", - packages=find_packages(include=["dmriprep*"]), + keywords="dmriprepoc", + name="dmriprepoc", + packages=find_packages(include=["dmriprepoc*"]), setup_requires=setup_requirements, test_suite="tests", tests_require=test_requirements, - url="https://github.com/nipy/dmriprep", + url="https://github.com/nipy/dmriprepoc", version="0.1.0", zip_safe=False, ) diff --git a/tests/test_dmriprep.py b/tests/test_dmriprep.py index 1786035..783ccb6 100644 --- a/tests/test_dmriprep.py +++ b/tests/test_dmriprep.py @@ -1,13 +1,13 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -"""Tests for `dmriprep` package.""" +"""Tests for `dmriprepoc` package.""" import pytest from click.testing import CliRunner -from dmriprep import cli +from dmriprepoc import cli @pytest.fixture diff --git a/tests/test_utils.py b/tests/test_utils.py index f5fa1b1..1ab5c05 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,11 +1,11 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -"""Tests for `dmriprep` package.""" +"""Tests for `dmriprepoc` package.""" import numpy as np -from dmriprep.utils import is_hemispherical +from dmriprepoc.utils import is_hemispherical def uniform_points_on_sphere(npoints=1, hemisphere=True, rotate=(0, 0, 0)): diff --git a/tox.ini b/tox.ini index 4347a53..589cce4 100644 --- a/tox.ini +++ b/tox.ini @@ -10,7 +10,7 @@ python = [testenv:flake8] basepython = python deps = flake8 -commands = flake8 dmriprep +commands = flake8 dmriprepoc [testenv] setenv = From 62221c9cf3a81a6cee9f3456e65052979238e5b6 Mon Sep 17 00:00:00 2001 From: Michael Joseph Date: Tue, 9 Jul 2019 06:25:13 -0400 Subject: [PATCH 07/18] add data to gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 3cae9a4..b54dbe2 100644 --- a/.gitignore +++ b/.gitignore @@ -103,3 +103,6 @@ ENV/ # Mac OS nonsense: .DS_Store + +# data +notebooks/data/ From dbee40dd5ba4ee912da9ea2a37452e790f418eb4 Mon Sep 17 00:00:00 2001 From: Michael Joseph Date: Tue, 9 Jul 2019 06:26:07 -0400 Subject: [PATCH 08/18] add topup workflow --- dmriprep/workflows/fieldmap/__init__.py | 1 + dmriprep/workflows/fieldmap/base.py | 98 +++++++++++++++++++------ dmriprep/workflows/fieldmap/pepolar.py | 79 ++++++++++++++++++++ 3 files changed, 156 insertions(+), 22 deletions(-) create mode 100644 dmriprep/workflows/fieldmap/pepolar.py diff --git a/dmriprep/workflows/fieldmap/__init__.py b/dmriprep/workflows/fieldmap/__init__.py index 2b2d1f4..0b2ecdd 100644 --- a/dmriprep/workflows/fieldmap/__init__.py +++ b/dmriprep/workflows/fieldmap/__init__.py @@ -1,5 +1,6 @@ #!/usr/bin/env python from .base import init_sdc_prep_wf +from .pepolar import init_pepolar_wf from .fmap import init_fmap_wf from .phasediff import init_phase_wf, init_phdiff_wf diff --git a/dmriprep/workflows/fieldmap/base.py b/dmriprep/workflows/fieldmap/base.py index 1447c7f..c84fe67 100644 --- a/dmriprep/workflows/fieldmap/base.py +++ b/dmriprep/workflows/fieldmap/base.py @@ -1,15 +1,20 @@ #!/usr/bin/env python +from nipype.pipeline import engine as pe +from nipype.interfaces import utility as niu + FMAP_PRIORITY = {"epi": 0, "fieldmap": 1, "phasediff": 2, "phase": 3, "syn": 4} -def init_sdc_prep_wf(fmaps, metadata, layout, bet_mag_frac, omp_nthreads=1, fmap_bspline=False): - from nipype.pipeline import engine as pe - from nipype.interfaces import utility as niu +def init_sdc_prep_wf( + fmaps, metadata, layout, bet_mag_frac, omp_nthreads=1, fmap_bspline=False +): sdc_prep_wf = pe.Workflow(name="sdc_prep_wf") - inputnode = pe.Node(niu.IdentityInterface(fields=["b0_stripped"]), name="inputnode") + inputnode = pe.Node( + niu.IdentityInterface(fields=["b0_stripped"]), name="inputnode" + ) outputnode = pe.Node( niu.IdentityInterface( @@ -20,7 +25,7 @@ def init_sdc_prep_wf(fmaps, metadata, layout, bet_mag_frac, omp_nthreads=1, fmap "bold_ref_brain", "out_warp", "syn_bold_ref", - "method" + "method", ] ), name="outputnode", @@ -29,6 +34,11 @@ def init_sdc_prep_wf(fmaps, metadata, layout, bet_mag_frac, omp_nthreads=1, fmap fmaps.sort(key=lambda fmap: FMAP_PRIORITY[fmap["suffix"]]) fmap = fmaps[0] + if fmap["suffix"] == "epi": + from .pepolar import init_pepolar_wf + + pepolar_wf = init_pepolar_wf() + if fmap["suffix"] == "fieldmap": from .fmap import init_fmap_wf @@ -38,41 +48,69 @@ def init_sdc_prep_wf(fmaps, metadata, layout, bet_mag_frac, omp_nthreads=1, fmap sdc_prep_wf.connect( [ - (inputnode, fmap_wf, [("b0_stripped", "inputnode.b0_stripped")]), + ( + inputnode, + fmap_wf, + [("b0_stripped", "inputnode.b0_stripped")], + ), (fmap_wf, outputnode, [("outputnode.out_fmap", "out_fmap")]), ] ) - if fmap['suffix'] in ('phasediff', 'phase'): + if fmap["suffix"] in ("phasediff", "phase"): from .phasediff import init_phase_wf, init_phdiff_wf from .fmap import init_fmap_wf - if fmap['suffix'] == 'phasediff': + + if fmap["suffix"] == "phasediff": phase_wf = init_phdiff_wf(bet_mag_frac) - phase_wf.inputs.inputnode.phasediff = fmap['phasediff'] + phase_wf.inputs.inputnode.phasediff = fmap["phasediff"] phase_wf.inputs.inputnode.magnitude1 = [ - fmap_ for key, fmap_ in sorted(fmap.items()) + fmap_ + for key, fmap_ in sorted(fmap.items()) if key.startswith("magnitude1") ][0] - phase_wf.inputs.inputnode.phases_meta = layout.get_metadata(phase_wf.inputs.inputnode.phasediff) + phase_wf.inputs.inputnode.phases_meta = layout.get_metadata( + phase_wf.inputs.inputnode.phasediff + ) post_phase_wf = init_fmap_wf() sdc_prep_wf.connect( [ - (inputnode, post_phase_wf, [("b0_stripped", "inputnode.b0_stripped")]), - (phase_wf, post_phase_wf, [("outputnode.out_fmap", "inputnode.fieldmap")]), - (phase_wf, post_phase_wf, [("outputnode.out_mag", "inputnode.magnitude")]), - (post_phase_wf, outputnode, [("outputnode.out_fmap", "out_fmap")]) + ( + inputnode, + post_phase_wf, + [("b0_stripped", "inputnode.b0_stripped")], + ), + ( + phase_wf, + post_phase_wf, + [("outputnode.out_fmap", "inputnode.fieldmap")], + ), + ( + phase_wf, + post_phase_wf, + [("outputnode.out_mag", "inputnode.magnitude")], + ), + ( + post_phase_wf, + outputnode, + [("outputnode.out_fmap", "out_fmap")], + ), ] ) - elif fmap['suffix'] == 'phase': + elif fmap["suffix"] == "phase": phase_wf = init_phase_wf(bet_mag_frac) - phase_wf.inputs.inputnode.phasediff = [fmap['phase1'], fmap['phase2']] + phase_wf.inputs.inputnode.phasediff = [ + fmap["phase1"], + fmap["phase2"], + ] phase_wf.inputs.inputnode.magnitude1 = [ - fmap_ for key, fmap_ in sorted(fmap.items()) + fmap_ + for key, fmap_ in sorted(fmap.items()) if key.startswith("magnitude1") ][0] @@ -84,10 +122,26 @@ def init_sdc_prep_wf(fmaps, metadata, layout, bet_mag_frac, omp_nthreads=1, fmap sdc_prep_wf.connect( [ - (inputnode, post_phase_wf, [("b0_stripped", "inputnode.b0_stripped")]), - (phase_wf, post_phase_wf, [("outputnode.out_fmap", "inputnode.fieldmap")]), - (phase_wf, post_phase_wf, [("outputnode.out_mag", "inputnode.magnitude")]), - (post_phase_wf, outputnode, [("outputnode.out_fmap", "out_fmap")]) + ( + inputnode, + post_phase_wf, + [("b0_stripped", "inputnode.b0_stripped")], + ), + ( + phase_wf, + post_phase_wf, + [("outputnode.out_fmap", "inputnode.fieldmap")], + ), + ( + phase_wf, + post_phase_wf, + [("outputnode.out_mag", "inputnode.magnitude")], + ), + ( + post_phase_wf, + outputnode, + [("outputnode.out_fmap", "out_fmap")], + ), ] ) return sdc_prep_wf diff --git a/dmriprep/workflows/fieldmap/pepolar.py b/dmriprep/workflows/fieldmap/pepolar.py new file mode 100644 index 0000000..34ca318 --- /dev/null +++ b/dmriprep/workflows/fieldmap/pepolar.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python + +from nipype.pipeline import engine as pe +from nipype.interfaces import fsl, utility as niu + + +def init_pepolar_wf(subject_id, dwi_meta, epi_fmaps): + + dwi_file_pe = dwi_meta["PhaseEncodingDirection"] + + usable_fieldmaps_matching_pe = [] + usable_fieldmaps_opposite_pe = [] + + for fmap, pe_dir in epi_fmaps: + if pe_dir == dwi_file_pe: + usable_fieldmaps_matching_pe.append(fmap) + elif pe_dir[0] == dwi_file_pe[0]: + usable_fieldmaps_opposite_pe.append(fmap) + + if not usable_fieldmaps_opposite_pe: + raise Exception("None of the discovered fieldmaps for " + "participant {} has the right phase " + "encoding direction".format(subject_id)) + + wf = pe.Workflow(name="pepolar_wf") + + inputnode = pe.Node(niu.IdentityInterface(fields=["b0_stripped"])) + + outputnode = pe.Node(niu.IdentityInterface(fields=["out_topup"])) + + topup_wf = init_topup_wf() + topup_wf.inputnode.altepi_file = usable_fieldmaps_opposite_pe[0] + + if not usable_fieldmaps_matching_pe: + wf.connect( + [ + (inputnode, topup_wf, [("b0_stripped", "inputnode.epi_file")]) + ] + ) + else: + topup_wf.inputnode.epi_file = usable_fieldmaps_matching_pe[0] + + return wf + + +def init_topup_wf(): + + wf = pe.Workflow(name="topup_wf") + + inputnode = pe.Node( + niu.IdentityInterface(fields=["epi_file", "altepi_file", "encoding_directions"]), + name="inputnode") + + outputnode = pe.Node( + niu.IdentityInterface(fields=["out_fmap"]), + name="outputnode") + + list_merge = pe.Node(niu.Merge(numinputs=2), name="list_merge") + + merge = pe.Node(fsl.Merge(dimension="t"), name="mergeAPPA") + + topup = pe.Node(fsl.TOPUP(), name="topup") + topup.inputs.readout_times = [0.05, 0.05] + + wf.connect( + [ + ( + inputnode, + list_merge, + [("epi_file", "in1"), ("altepi_file", "in2")] + ), + (list_merge, merge, [("out", "in_files")]), + (merge, topup, [("merged_file", "in_file")]), + (inputnode, topup, [("encoding_directions", "encoding_direction")]), + (topup, outputnode, [("out_field", "out_fmap")]), + ] + ) + + return wf From f54fd7f992eb1fb943ee969a76cc1019286861b0 Mon Sep 17 00:00:00 2001 From: Michael Joseph Date: Tue, 9 Jul 2019 06:26:20 -0400 Subject: [PATCH 09/18] style changes --- dmriprep/workflows/fieldmap/fmap.py | 14 ++- dmriprep/workflows/fieldmap/phasediff.py | 108 ++++++++++++++--------- 2 files changed, 77 insertions(+), 45 deletions(-) diff --git a/dmriprep/workflows/fieldmap/fmap.py b/dmriprep/workflows/fieldmap/fmap.py index df002a5..72aa061 100644 --- a/dmriprep/workflows/fieldmap/fmap.py +++ b/dmriprep/workflows/fieldmap/fmap.py @@ -1,15 +1,21 @@ #!/usr/bin/env python +from nipype.pipeline import engine as pe +from nipype.interfaces import fsl, utility as niu + def init_fmap_wf(): - from nipype.pipeline import engine as pe - from nipype.interfaces import fsl, utility as niu wf = pe.Workflow(name="fmap_prep_wf") - inputnode = pe.Node(niu.IdentityInterface(fields=["fieldmap", "magnitude", "b0_stripped"]), name="inputnode") + inputnode = pe.Node( + niu.IdentityInterface(fields=["fieldmap", "magnitude", "b0_stripped"]), + name="inputnode", + ) - outputnode = pe.Node(niu.IdentityInterface(fields=["out_fmap"]), name="outputnode") + outputnode = pe.Node( + niu.IdentityInterface(fields=["out_fmap"]), name="outputnode" + ) rad_to_hz = pe.Node( fsl.BinaryMaths(operation="div", operand_value=6.28), name="radToHz" diff --git a/dmriprep/workflows/fieldmap/phasediff.py b/dmriprep/workflows/fieldmap/phasediff.py index de5e7ca..c47ec56 100644 --- a/dmriprep/workflows/fieldmap/phasediff.py +++ b/dmriprep/workflows/fieldmap/phasediff.py @@ -1,29 +1,41 @@ #!/usr/bin/env python +from nipype.pipeline import engine as pe +from nipype.interfaces import fsl, utility as niu +from ...interfaces import Phasediff2Fieldmap, Phases2Fieldmap + + def init_phase_wf(bet_mag_frac): - from nipype.pipeline import engine as pe - from nipype.interfaces import fsl, utility as niu - from ...interfaces import Phasediff2Fieldmap, Phases2Fieldmap wf = pe.Workflow(name="phase_prep_wf") - inputnode = pe.Node(niu.IdentityInterface(fields=["magnitude1", "phasediff", "b0_stripped", "phases_meta"]), name="inputnode") + inputnode = pe.Node( + niu.IdentityInterface( + fields=["magnitude1", "phasediff", "b0_stripped", "phases_meta"] + ), + name="inputnode", + ) - outputnode = pe.Node(niu.IdentityInterface(fields=["out_fmap", "out_mag"]), name="outputnode") + outputnode = pe.Node( + niu.IdentityInterface(fields=["out_fmap", "out_mag"]), + name="outputnode", + ) - phases2fmap = pe.Node(Phases2Fieldmap(), name='phases2fmap') + phases2fmap = pe.Node(Phases2Fieldmap(), name="phases2fmap") - mag_bet = pe.Node(fsl.BET(frac=bet_mag_frac, robust=True), - name='mag_bet') + mag_bet = pe.Node(fsl.BET(frac=bet_mag_frac, robust=True), name="mag_bet") - prep_fmap = pe.Node(fsl.PrepareFieldmap(scanner='SIEMENS', nocheck=True), - name='prep_fmap') + prep_fmap = pe.Node( + fsl.PrepareFieldmap(scanner="SIEMENS", nocheck=True), name="prep_fmap" + ) fslroi = pe.Node(fsl.ExtractROI(t_min=0, t_size=1), name="fslroi_phase") delta = pe.Node( niu.Function( - input_names=["in_values"], output_names=["out_value"], function=delta_te + input_names=["in_values"], + output_names=["out_value"], + function=delta_te, ), name="delta", ) @@ -33,66 +45,74 @@ def init_phase_wf(bet_mag_frac): # Mag bet (inputnode, mag_bet, [("magnitude1", "in_file")]), # phases -> phdiff - (inputnode, phases2fmap, [('phases_meta', 'metadatas')]), - (inputnode, phases2fmap, [('phasediff', 'phase_files')]), + (inputnode, phases2fmap, [("phases_meta", "metadatas")]), + (inputnode, phases2fmap, [("phasediff", "phase_files")]), # phdiff delta_te - (phases2fmap, delta, [('phasediff_metadata', 'in_values')]), + (phases2fmap, delta, [("phasediff_metadata", "in_values")]), # prep fmap (mag_bet, prep_fmap, [("out_file", "in_magnitude")]), - (phases2fmap, prep_fmap, [('out_file', 'in_phase')]), - (delta, prep_fmap, [('out_value', 'delta_TE')]), + (phases2fmap, prep_fmap, [("out_file", "in_phase")]), + (delta, prep_fmap, [("out_value", "delta_TE")]), # Remove second empty volume (prep_fmap, fslroi, [("out_fieldmap", "in_file")]), (fslroi, outputnode, [("roi_file", "out_fmap")]), - (inputnode, outputnode, [("magnitude1", "out_mag")]) + (inputnode, outputnode, [("magnitude1", "out_mag")]), ] ) return wf + def init_phdiff_wf(bet_mag_frac): - from nipype.pipeline import engine as pe - from nipype.interfaces import fsl, utility as niu - from ...interfaces import Phasediff2Fieldmap wf = pe.Workflow(name="phdiff_prep_wf") - inputnode = pe.Node(niu.IdentityInterface(fields=["magnitude1", "phasediff", "b0_stripped", "phases_meta"]), name="inputnode") + inputnode = pe.Node( + niu.IdentityInterface( + fields=["magnitude1", "phasediff", "b0_stripped", "phases_meta"] + ), + name="inputnode", + ) - outputnode = pe.Node(niu.IdentityInterface(fields=["out_fmap", "out_mag"]), name="outputnode") + outputnode = pe.Node( + niu.IdentityInterface(fields=["out_fmap", "out_mag"]), + name="outputnode", + ) - mag_bet = pe.Node(fsl.BET(frac=bet_mag_frac, robust=True), - name='mag_bet') + mag_bet = pe.Node(fsl.BET(frac=bet_mag_frac, robust=True), name="mag_bet") - prep_fmap = pe.Node(fsl.PrepareFieldmap(scanner='SIEMENS'), - name='prep_fmap') + prep_fmap = pe.Node( + fsl.PrepareFieldmap(scanner="SIEMENS"), name="prep_fmap" + ) fslroi = pe.Node(fsl.ExtractROI(t_min=0, t_size=1), name="fslroi_phase") delta = pe.Node( niu.Function( - input_names=["in_values"], output_names=["out_value"], function=delta_te + input_names=["in_values"], + output_names=["out_value"], + function=delta_te, ), name="delta", ) - #phdiff2fmap = pe.Node(Phasediff2Fieldmap(), name='phdiff2fmap') + # phdiff2fmap = pe.Node(Phasediff2Fieldmap(), name='phdiff2fmap') wf.connect( [ # mag bet (inputnode, mag_bet, [("magnitude1", "in_file")]), # phdiff delta_te - (inputnode, delta, [('phases_meta', 'in_values')]), + (inputnode, delta, [("phases_meta", "in_values")]), # prep fmap (mag_bet, prep_fmap, [("out_file", "in_magnitude")]), - (inputnode, prep_fmap, [('phasediff', 'in_phase')]), - (delta, prep_fmap, [('out_value', 'delta_TE')]), + (inputnode, prep_fmap, [("phasediff", "in_phase")]), + (delta, prep_fmap, [("out_value", "delta_TE")]), # Remove second empty volume (prep_fmap, fslroi, [("out_fieldmap", "in_file")]), # Output (fslroi, outputnode, [("roi_file", "out_fmap")]), - (inputnode, outputnode, [("magnitude1", "out_mag")]) + (inputnode, outputnode, [("magnitude1", "out_mag")]), ] ) return wf @@ -100,22 +120,24 @@ def init_phdiff_wf(bet_mag_frac): def get_metadata(in_file, bids_dir): from bids import BIDSLayout + layout = BIDSLayout(bids_dir, validate=False) out_dict = layout.get_metadata(in_file) return out_dict + def delta_te(in_values, te1=None, te2=None): """Read :math:`\Delta_\text{TE}` from BIDS metadata dict""" if isinstance(in_values, float): te2 = in_values - te1 = 0. + te1 = 0.0 if isinstance(in_values, dict): - te1 = in_values.get('EchoTime1') - te2 = in_values.get('EchoTime2') + te1 = in_values.get("EchoTime1") + te2 = in_values.get("EchoTime2") if not all((te1, te2)): - te2 = in_values.get('EchoTimeDifference') + te2 = in_values.get("EchoTimeDifference") te1 = 0 if isinstance(in_values, list): @@ -127,13 +149,17 @@ def delta_te(in_values, te1=None, te2=None): # For convienience if both are missing we should give one error about them if te1 is None and te2 is None: - raise RuntimeError('EchoTime1 and EchoTime2 metadata fields not found. ' - 'Please consult the BIDS specification.') + raise RuntimeError( + "EchoTime1 and EchoTime2 metadata fields not found. " + "Please consult the BIDS specification." + ) if te1 is None: raise RuntimeError( - 'EchoTime1 metadata field not found. Please consult the BIDS specification.') + "EchoTime1 metadata field not found. Please consult the BIDS specification." + ) if te2 is None: raise RuntimeError( - 'EchoTime2 metadata field not found. Please consult the BIDS specification.') + "EchoTime2 metadata field not found. Please consult the BIDS specification." + ) - return 1000*abs(float(te2) - float(te1)) + return 1000 * abs(float(te2) - float(te1)) From cff00f95533a2bf583af2d08009a3bee5e47abd4 Mon Sep 17 00:00:00 2001 From: Michael Joseph Date: Tue, 9 Jul 2019 06:26:39 -0400 Subject: [PATCH 10/18] roll back nipype version in requirements --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 29ffc90..38c6685 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ Click>=6.0 dipy==0.16.0 -nipype==1.2.1 +nipype==1.2.0 pandas==0.24.2 parse==1.12.0 tqdm==4.32.1 From be1066b6b42ed8efcc3d6a0408540819514b51be Mon Sep 17 00:00:00 2001 From: Michael Joseph Date: Tue, 9 Jul 2019 06:27:41 -0400 Subject: [PATCH 11/18] add testing jupyter notebooks --- notebooks/acq_param_testing.ipynb | 125 ++++ notebooks/fmap_testing.ipynb | 618 ++++++++++++++++++++ notebooks/make_qc.ipynb | 395 +++++++++++++ notebooks/slice_timing.ipynb | 939 ++++++++++++++++++++++++++++++ notebooks/test_wf.ipynb | 348 +++++++++++ 5 files changed, 2425 insertions(+) create mode 100644 notebooks/acq_param_testing.ipynb create mode 100644 notebooks/fmap_testing.ipynb create mode 100644 notebooks/make_qc.ipynb create mode 100644 notebooks/slice_timing.ipynb create mode 100644 notebooks/test_wf.ipynb diff --git a/notebooks/acq_param_testing.ipynb b/notebooks/acq_param_testing.ipynb new file mode 100644 index 0000000..73a5476 --- /dev/null +++ b/notebooks/acq_param_testing.ipynb @@ -0,0 +1,125 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "base_dir = \"/projects/mjoseph/pipelines/testing/data\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- GE/Philips: EchoTrainLength it will be Echo train length/PE steps \n", + "- SIEMENS: EPIFactor \n", + "acquisition direction A>>P or P>>A" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "total_readout_time = 1 / PE bandwidth \n", + "effective echo spacing = 1 / (PE bandwidth * (ETL - 1) * acc factor)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- echo spacing = .53ms\n", + "- number of in plane lines in the reconstructed epi image = 64\n", + "- acceleration factor = 2\n", + "- number of in plane reference lines = 24\n", + "\n", + "My questions: \n", + "What do I have to enter as the echo spacing for b0 field unwarping with \n", + "feat/fugue?\n", + "(a) .53ms/2 (echo_spacing*#lines_in_images / acceleration factor) \n", + "(b) .53*64/(32+24) (echo_spacing*#lines_in_images/(#lines_in_images + \n", + "#reference_lines))\n", + "(c) something else ..." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "from bids import BIDSLayout\n", + "\n", + "layout = BIDSLayout(base_dir)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "dwi_file = \"{}/sub-CMP0178/ses-01/dwi/sub-CMP0178_ses-01_acq-singleshell_dwi.nii.gz\"" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "metadata = layout.get_metadata(dwi_file)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{}" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "metadata" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "dmriprep_venv", + "language": "python", + "name": "dmriprep_venv" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/notebooks/fmap_testing.ipynb b/notebooks/fmap_testing.ipynb new file mode 100644 index 0000000..ff9defb --- /dev/null +++ b/notebooks/fmap_testing.ipynb @@ -0,0 +1,618 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "https://fmriprep.readthedocs.io/en/0.5.0/sdc/estimation.html" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "\n", + "from bids import BIDSLayout" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [], + "source": [ + "base_dir = os.path.abspath(\"data\")\n", + "output_dir = os.path.abspath(\"outputs\")\n", + "\n", + "layout = BIDSLayout(base_dir)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [], + "source": [ + "def get_fmaps(dwi_file):\n", + " dwi_metadata = layout.get_metadata(dwi_file)\n", + " fmaps = []\n", + " fmaps = layout.get_fieldmap(dwi_file, return_list=True)\n", + " if not fmaps:\n", + " print(\"No fmaps found\")\n", + " for fmap in fmaps:\n", + " if fmap[\"suffix\"] == \"phase\":\n", + " fmap[\"metadata\"] = {}\n", + " fmap[\"metadata\"][\"phase1\"] = layout.get_metadata(fmap[\"phase1\"])\n", + " fmap[\"metadata\"][\"phase2\"] = layout.get_metadata(fmap[\"phase2\"])\n", + " else:\n", + " fmap[\"metadata\"] = layout.get_metadata(fmap[fmap[\"suffix\"]])\n", + " \n", + " FMAP_PRIORITY = {\"epi\": 0, \"fieldmap\": 1, \"phasediff\": 2, \"phase\": 3, \"syn\": 4}\n", + " \n", + " fmaps.sort(key=lambda fmap: FMAP_PRIORITY[fmap[\"suffix\"]])\n", + " \n", + " return fmaps" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Topup" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/Michael/.pyenv/versions/dwi_venv/lib/python3.7/site-packages/bids/layout/layout.py:659: UserWarning: In pybids 0.9.0, the 'extensions' filter was deprecated in favor of 'extension'. The former will stop working in 0.11.0.\n", + " warnings.warn(\"In pybids 0.9.0, the 'extensions' filter was \"\n" + ] + } + ], + "source": [ + "subject_id = \"NDARAJ366ZFA\"\n", + "dwi_files = layout.get(subject=subject_id, datatype=\"dwi\", suffix=\"dwi\", extensions=[\".nii\", \".nii.gz\"], return_type=\"filename\")" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [], + "source": [ + "for dwi_file in dwi_files:\n", + " dwi_metadata = layout.get_metadata(dwi_file)\n", + " fmaps = get_fmaps(dwi_file)" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [], + "source": [ + "fmap = fmaps[0]\n", + "if fmap[\"suffix\"] == \"epi\":\n", + " epi_fmaps = [(fmap_['epi'], fmap_['metadata'][\"PhaseEncodingDirection\"]) for fmap_ in fmaps if fmap_['suffix'] == 'epi']" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [], + "source": [ + "dwi_file_pe = dwi_metadata[\"PhaseEncodingDirection\"]\n", + "\n", + "usable_fieldmaps_matching_pe = []\n", + "usable_fieldmaps_opposite_pe = []\n", + "\n", + "for fmap, pe_dir in epi_fmaps:\n", + " if pe_dir == dwi_file_pe:\n", + " usable_fieldmaps_matching_pe.append(fmap)\n", + " elif pe_dir[0] == dwi_file_pe[0]:\n", + " usable_fieldmaps_opposite_pe.append(fmap)\n", + " \n", + "if not usable_fieldmaps_opposite_pe:\n", + " print(\"Can't use topup\")" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [], + "source": [ + "from nipype.pipeline import engine as pe\n", + "from nipype.interfaces import fsl, utility as niu\n", + "\n", + "def init_topup_wf(epi_fmaps):\n", + " \n", + " PE_DIRECTION_MAPPING = {\n", + " \"i\" : \"x\",\n", + " \"i-\": \"x-\",\n", + " \"j\" : \"y\",\n", + " \"j-\" : \"y-\",\n", + " \"k\" : \"z\",\n", + " \"k-\" : \"z-\"\n", + " }\n", + " \n", + " epi_file = epi_fmaps[0][0]\n", + " epi_dir = PE_DIRECTION_MAPPING[epi_fmaps[0][1]]\n", + " altepi_file = epi_fmaps[1][0]\n", + " altepi_dir = PE_DIRECTION_MAPPING[epi_fmaps[1][1]]\n", + " \n", + " wf = pe.Workflow(name=\"topup_wf\")\n", + " \n", + " inputnode = pe.Node(\n", + " niu.IdentityInterface(fields=[\"epi_file\", \"altepi_file\"]),\n", + " name=\"inputnode\") \n", + " inputnode.epi_file = epi_file\n", + " inputnode.altepi_file = altepi_file\n", + " \n", + " outputnode = pe.Node(\n", + " niu.IdentityInterface(fields=[\"out_fmap\"]),\n", + " name=\"outputnode\")\n", + " \n", + " list_merge = pe.Node(niu.Merge(numinputs=2), name=\"list_merge\")\n", + " \n", + " merge = pe.Node(fsl.Merge(dimension=\"t\"), name=\"mergeAPPA\")\n", + " \n", + " topup = pe.Node(fsl.TOPUP(), name=\"topup\")\n", + " topup.inputs.encoding_direction = [epi_dir, altepi_dir]\n", + " topup.inputs.readout_times = [0.05, 0.05]\n", + " \n", + " wf.connect(\n", + " [\n", + " (\n", + " inputnode,\n", + " list_merge,\n", + " [(\"epi_file\", \"in1\"), (\"altepi_file\", \"in2\")]\n", + " ),\n", + " (list_merge, merge, [(\"out\", \"in_files\")]),\n", + " (merge, topup, [(\"merged_file\", \"in_file\")]),\n", + " (topup, outputnode, [(\"out_field\", \"out_fmap\")]),\n", + " ]\n", + " )\n", + " \n", + " return wf" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "190708-19:55:05,845 nipype.workflow INFO:\n", + "\t Workflow topup_wf settings: ['check', 'execution', 'logging', 'monitoring']\n", + "190708-19:55:05,931 nipype.workflow INFO:\n", + "\t Running serially.\n", + "190708-19:55:05,933 nipype.workflow INFO:\n", + "\t [Node] Setting-up \"topup_wf.list_merge\" in \"/Users/Michael/projects/pipelines/dmripreproc/notebooks/outputs/topup_wf/list_merge\".\n", + "190708-19:55:05,943 nipype.workflow INFO:\n", + "\t [Node] Running \"list_merge\" (\"nipype.interfaces.utility.base.Merge\")\n", + "190708-19:55:06,71 nipype.workflow INFO:\n", + "\t [Node] Finished \"topup_wf.list_merge\".\n", + "190708-19:55:06,73 nipype.workflow INFO:\n", + "\t [Node] Setting-up \"topup_wf.mergeAPPA\" in \"/Users/Michael/projects/pipelines/dmripreproc/notebooks/outputs/topup_wf/mergeAPPA\".\n", + "190708-19:55:06,80 nipype.workflow WARNING:\n", + "\t [Node] Error on \"topup_wf.mergeAPPA\" (/Users/Michael/projects/pipelines/dmripreproc/notebooks/outputs/topup_wf/mergeAPPA)\n", + "190708-19:55:06,86 nipype.workflow ERROR:\n", + "\t Node mergeAPPA failed to run on host Michaels-iMac.local.\n", + "190708-19:55:06,209 nipype.workflow ERROR:\n", + "\t Saving crash info to /Users/Michael/projects/pipelines/dmripreproc/notebooks/crash-20190708-195506-Michael-mergeAPPA-ce285b5c-427d-40a6-81d3-1f832935f05c.pklz\n", + "Traceback (most recent call last):\n", + " File \"/Users/Michael/.pyenv/versions/dwi_venv/lib/python3.7/site-packages/nipype/pipeline/plugins/linear.py\", line 48, in run\n", + " node.run(updatehash=updatehash)\n", + " File \"/Users/Michael/.pyenv/versions/dwi_venv/lib/python3.7/site-packages/nipype/pipeline/engine/nodes.py\", line 472, in run\n", + " result = self._run_interface(execute=True)\n", + " File \"/Users/Michael/.pyenv/versions/dwi_venv/lib/python3.7/site-packages/nipype/pipeline/engine/nodes.py\", line 563, in _run_interface\n", + " return self._run_command(execute)\n", + " File \"/Users/Michael/.pyenv/versions/dwi_venv/lib/python3.7/site-packages/nipype/pipeline/engine/nodes.py\", line 631, in _run_command\n", + " cmd = self._interface.cmdline\n", + " File \"/Users/Michael/.pyenv/versions/dwi_venv/lib/python3.7/site-packages/nipype/interfaces/base/core.py\", line 674, in cmdline\n", + " allargs = [self._cmd_prefix + self.cmd] + self._parse_inputs()\n", + " File \"/Users/Michael/.pyenv/versions/dwi_venv/lib/python3.7/site-packages/nipype/interfaces/base/core.py\", line 916, in _parse_inputs\n", + " value = self._filename_from_source(name)\n", + " File \"/Users/Michael/.pyenv/versions/dwi_venv/lib/python3.7/site-packages/nipype/interfaces/base/core.py\", line 845, in _filename_from_source\n", + " source = source[0]\n", + "IndexError: list index out of range\n", + "\n", + "190708-19:55:06,211 nipype.workflow INFO:\n", + "\t ***********************************\n", + "190708-19:55:06,212 nipype.workflow ERROR:\n", + "\t could not run node: topup_wf.mergeAPPA\n", + "190708-19:55:06,213 nipype.workflow INFO:\n", + "\t crashfile: /Users/Michael/projects/pipelines/dmripreproc/notebooks/crash-20190708-195506-Michael-mergeAPPA-ce285b5c-427d-40a6-81d3-1f832935f05c.pklz\n", + "190708-19:55:06,214 nipype.workflow INFO:\n", + "\t ***********************************\n" + ] + }, + { + "ename": "RuntimeError", + "evalue": "Workflow did not execute cleanly. Check log for details", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------\u001b[0m", + "\u001b[0;31mRuntimeError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0mtopup_wf\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0minit_topup_wf\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mepi_fmaps\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0mtopup_wf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mbase_dir\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0moutput_dir\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0mtopup_wf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrun\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m~/.pyenv/versions/dwi_venv/lib/python3.7/site-packages/nipype/pipeline/engine/workflows.py\u001b[0m in \u001b[0;36mrun\u001b[0;34m(self, plugin, plugin_args, updatehash)\u001b[0m\n\u001b[1;32m 597\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mstr2bool\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mconfig\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'execution'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'create_report'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 598\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_write_report_info\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mbase_dir\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mexecgraph\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 599\u001b[0;31m \u001b[0mrunner\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrun\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mexecgraph\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mupdatehash\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mupdatehash\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mconfig\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mconfig\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 600\u001b[0m \u001b[0mdatestr\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mdatetime\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mutcnow\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstrftime\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'%Y%m%dT%H%M%S'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 601\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mstr2bool\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mconfig\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'execution'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'write_provenance'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/.pyenv/versions/dwi_venv/lib/python3.7/site-packages/nipype/pipeline/plugins/linear.py\u001b[0m in \u001b[0;36mrun\u001b[0;34m(self, graph, config, updatehash)\u001b[0m\n\u001b[1;32m 69\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 70\u001b[0m \u001b[0mos\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mchdir\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mold_wd\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# Return wherever we were before\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 71\u001b[0;31m \u001b[0mreport_nodes_not_run\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnotrun\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m~/.pyenv/versions/dwi_venv/lib/python3.7/site-packages/nipype/pipeline/plugins/tools.py\u001b[0m in \u001b[0;36mreport_nodes_not_run\u001b[0;34m(notrun)\u001b[0m\n\u001b[1;32m 80\u001b[0m \u001b[0mlogger\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdebug\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msubnode\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_id\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 81\u001b[0m \u001b[0mlogger\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minfo\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"***********************************\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 82\u001b[0;31m raise RuntimeError(('Workflow did not execute cleanly. '\n\u001b[0m\u001b[1;32m 83\u001b[0m 'Check log for details'))\n\u001b[1;32m 84\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mRuntimeError\u001b[0m: Workflow did not execute cleanly. Check log for details" + ] + } + ], + "source": [ + "topup_wf = init_topup_wf(epi_fmaps)\n", + "topup_wf.base_dir = output_dir\n", + "topup_wf.run()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "if using single dwi image, both dwi images or synthetic b0, must register both images before fslmerge" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Topup using dwi image" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Topup using synthetic b0" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Phasediff" + ] + }, + { + "cell_type": "code", + "execution_count": 116, + "metadata": {}, + "outputs": [], + "source": [ + "subject_id = \"CMP0178\"\n", + "dwi_files = layout.get(subject=subject_id, datatype=\"dwi\", suffix=\"dwi\", extensions=[\".nii\", \".nii.gz\"], return_type=\"filename\")" + ] + }, + { + "cell_type": "code", + "execution_count": 117, + "metadata": {}, + "outputs": [], + "source": [ + "for dwi_file in dwi_files:\n", + " fmaps = get_fmaps(dwi_file)" + ] + }, + { + "cell_type": "code", + "execution_count": 118, + "metadata": {}, + "outputs": [], + "source": [ + "fmap = fmaps[0]\n", + "if fmap[\"suffix\"] == \"phasediff\":\n", + " phasediff_file = fmap[\"phasediff\"]\n", + " phasediff_metadata = fmap[\"metadata\"]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Phase" + ] + }, + { + "cell_type": "code", + "execution_count": 119, + "metadata": {}, + "outputs": [], + "source": [ + "subject_id = \"ZHP0130\"\n", + "dwi_files = layout.get(subject=subject_id, datatype=\"dwi\", suffix=\"dwi\", extensions=[\".nii\", \".nii.gz\"], return_type=\"filename\")" + ] + }, + { + "cell_type": "code", + "execution_count": 120, + "metadata": {}, + "outputs": [], + "source": [ + "for dwi_file in dwi_files:\n", + " fmaps = get_fmaps(dwi_file)" + ] + }, + { + "cell_type": "code", + "execution_count": 105, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'phase1': {'AcquisitionMatrixPE': 64, 'AcquisitionNumber': 1, 'AcquisitionTime': '06:05:0.000000', 'BaseResolution': 64, 'BodyPartExamined': 'BRAIN', 'ConsistencyInfo': 'N4_VE11B_LATEST_20150530', 'ConversionSoftware': 'dcm2niix', 'ConversionSoftwareVersion': 'v1.0.20180622 (JP2:OpenJPEG) (JP-LS:CharLS) GCC5.5.0', 'DeviceSerialNumber': '66106', 'DwellTime': 1.61e-05, 'EchoTime': 0.0065, 'FlipAngle': 60, 'ImageOrientationPatientDICOM': [0.998672, 0.040619, 0.0316926, -0.0416821, 0.998565, 0.0336378], 'ImageType': ['ORIGINAL', 'PRIMARY', 'P', 'ND'], 'InPlanePhaseEncodingDirectionDICOM': 'COL', 'InstitutionAddress': 'Community_Drive_300_Manhasset_NYC_US_11030', 'InstitutionalDepartmentName': 'RADIOLOGY', 'IntendedFor': ['ses-01/dwi/sub-ZHP0130_ses-01_acq-ZHP601000_run-01_dwi.nii.gz'], 'MRAcquisitionType': '2D', 'MagneticFieldStrength': 3, 'Manufacturer': 'Siemens', 'ManufacturersModelName': 'Prisma', 'Modality': 'MR', 'PartialFourier': 1, 'PatientPosition': 'HFS', 'PercentPhaseFOV': 100, 'PhaseEncodingDirection': 'j-', 'PhaseEncodingSteps': 64, 'PhaseResolution': 1, 'PixelBandwidth': 485, 'ProcedureStepDescription': 'MR_BRAIN', 'ProtocolName': 'field_map_TE=6.5ms', 'PulseSequenceDetails': '%SiemensSeq%_gre', 'ReceiveCoilActiveElements': 'HC1-7', 'ReceiveCoilName': 'HeadNeck_64', 'ReconMatrixPE': 64, 'RepetitionTime': 1.06, 'SAR': 0.122978, 'ScanOptions': 'FS', 'ScanningSequence': 'GR', 'SequenceName': '_fl2d1', 'SequenceVariant': 'SP', 'SeriesDescription': 'field_map_TE=6.5ms', 'SeriesNumber': 17, 'ShimSetting': [-1322, -10948, 554, 258, -169, -237, 5, -7], 'SliceThickness': 4, 'SoftwareVersions': 'syngo_MR_E11', 'SpacingBetweenSlices': 4, 'StationName': 'MHMRSIEM3T', 'TxRefAmp': 286.233}, 'phase2': {'AcquisitionMatrixPE': 64, 'AcquisitionNumber': 1, 'AcquisitionTime': '06:05:0.000000', 'BaseResolution': 64, 'BodyPartExamined': 'BRAIN', 'ConsistencyInfo': 'N4_VE11B_LATEST_20150530', 'ConversionSoftware': 'dcm2niix', 'ConversionSoftwareVersion': 'v1.0.20180622 (JP2:OpenJPEG) (JP-LS:CharLS) GCC5.5.0', 'DeviceSerialNumber': '66106', 'DwellTime': 1.61e-05, 'EchoTime': 0.0085, 'FlipAngle': 60, 'ImageOrientationPatientDICOM': [0.998672, 0.040619, 0.0316926, -0.0416821, 0.998565, 0.0336378], 'ImageType': ['ORIGINAL', 'PRIMARY', 'P', 'ND'], 'InPlanePhaseEncodingDirectionDICOM': 'COL', 'InstitutionAddress': 'Community_Drive_300_Manhasset_NYC_US_11030', 'InstitutionalDepartmentName': 'RADIOLOGY', 'IntendedFor': ['ses-01/dwi/sub-ZHP0130_ses-01_acq-ZHP601000_run-01_dwi.nii.gz'], 'MRAcquisitionType': '2D', 'MagneticFieldStrength': 3, 'Manufacturer': 'Siemens', 'ManufacturersModelName': 'Prisma', 'Modality': 'MR', 'PartialFourier': 1, 'PatientPosition': 'HFS', 'PercentPhaseFOV': 100, 'PhaseEncodingDirection': 'j-', 'PhaseEncodingSteps': 64, 'PhaseResolution': 1, 'PixelBandwidth': 485, 'ProcedureStepDescription': 'MR_BRAIN', 'ProtocolName': 'field_map_TE=8.5ms', 'PulseSequenceDetails': '%SiemensSeq%_gre', 'ReceiveCoilActiveElements': 'HC1-7', 'ReceiveCoilName': 'HeadNeck_64', 'ReconMatrixPE': 64, 'RepetitionTime': 1.06, 'SAR': 0.122978, 'ScanOptions': 'FS', 'ScanningSequence': 'GR', 'SequenceName': '_fl2d1', 'SequenceVariant': 'SP', 'SeriesDescription': 'field_map_TE=8.5ms', 'SeriesNumber': 19, 'ShimSetting': [-1322, -10948, 554, 258, -169, -237, 5, -7], 'SliceThickness': 4, 'SoftwareVersions': 'syngo_MR_E11', 'SpacingBetweenSlices': 4, 'StationName': 'MHMRSIEM3T', 'TxRefAmp': 286.233}}\n" + ] + } + ], + "source": [ + "fmap = fmaps[0]\n", + "if fmap[\"suffix\"] == \"phase\":\n", + " phase1_file = fmap" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Fieldmap" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [], + "source": [ + "def to_rads(in_file, out_file):\n", + " from math import pi\n", + " import nibabel as nib\n", + " \n", + " fmap_img = nib.load(in_file)\n", + " fmap_data = fmap_img.get_data()\n", + " \n", + " fmap_range = max(abs(fmap_data.min()), fmap_data.max())\n", + " \n", + " fmap_data = fmap_data * (pi / fmap_range)\n", + " \n", + " out_img = nib.Nifti1Image(fmap_data, fmap_img.affine, fmap_img.header)\n", + " out_img.set_data_dtype('float32')\n", + " out_img.to_filename(out_file)\n", + " \n", + " return out_file, fmap_range" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [], + "source": [ + "def to_hz(in_file, range_hz, out_file):\n", + " from math import pi\n", + " import nibabel as nib\n", + " \n", + " fmap_img = nib.load(in_file)\n", + " fmap_data = fmap_img.get_data()\n", + " \n", + " fmap_data = fmap_data * (range_hz / pi)\n", + " out_img = nib.Nifti1Image(fmap_data, fmap_img.affine, fmap_img.header)\n", + " out_img.set_data_dtype('float32')\n", + " out_img.to_filename(out_file)\n", + " \n", + " return out_file" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": {}, + "outputs": [], + "source": [ + "fmap_file = \"{}/sub-CMH0171/ses-01/fmap/sub-CMH0171_ses-01_run-01_fieldmap.nii.gz\".format(base_dir)\n", + "\n", + "out_file, fmap_range = to_rads(fmap_file, fmap_file.replace('.nii.gz', '_rad.nii.gz'))\n", + "\n", + "new_out_file = to_hz(out_file, fmap_range, out_file.replace('_rad.nii.gz', '_hz.nii.gz'))" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2048.7444\n" + ] + } + ], + "source": [ + "fmap_img = nib.load(fmap_file)\n", + "fmap_data = fmap_img.get_data()\n", + "\n", + "fmap_range = max(abs(fmap_data.min()), fmap_data.max())\n", + "print(fmap_range)" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3.1415927\n" + ] + } + ], + "source": [ + "fmap_img = nib.load(out_file)\n", + "fmap_data = fmap_img.get_data()\n", + "\n", + "fmap_range = max(abs(fmap_data.min()), fmap_data.max())\n", + "print(fmap_range)" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2048.7446\n" + ] + } + ], + "source": [ + "fmap_img = nib.load(new_out_file)\n", + "fmap_data = fmap_img.get_data()\n", + "\n", + "fmap_range = max(abs(fmap_data.min()), fmap_data.max())\n", + "print(fmap_range)" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAekAAADJCAYAAAAHFcoVAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjAsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+17YcXAAAcr0lEQVR4nO3df2yV1R3H8U8ttFxaaIu2Fg200zkB5zCIIzNu4kLC8A8l1sUf66DbAsMl28jifmTsDyBjuiwh2f4Aw4yK6TKnYOpYAsn4w2Rb3KIb1Dk0Mhd0TMpkUPoTrLb7A8/Tc2/PfZ7n/uo99973KyFen/v8OLfP6T093+d7zqmamJiYEAAA8M5lxS4AAABwo5EGAMBTNNIAAHiKRhoAAE/RSAMA4CkaaQAAPEUjDQCAp2ikAQDwFI00AACeopEGAMBTNNIAAHiKRhoAAE/RSAMA4CkaaQAAPEUjDQCAp2ikAQDwFI00AACeopEGAMBTNNIAAHiKRhoAAE/NKHYBAMAX3d3dxS4CKlRnZ6dzOz1pAAA8RSMNAICnaKQBAPAUjTQAAJ6ikQYAwFM00gAAeIpGGgCQk+7uboavFQjjpAEgTzo6OpRIJKZsHx0d1f79+4tQounx9ttvF7sIBZXuvtoKdY/pSQNAnqT7Io/6goff4ty/Qt1jGmkAyKP29nYdPny42MVAnrW3tyuRSKi+vl6tra3q6urS0NBQwa9LIw0AQAwHDhzQ0NCQjh49qiNHjuiRRx4p+DVppAEAyEBra6tWr16to0ePFvxaNNIAAGTg5MmTOnjwoD7+8Y8X/Fo00gAAxLB27VrNmTNHCxYsUEtLi7Zt21bwa9JIAwAQQ09PjwYHB/Xiiy/qjTfe0JkzZwp+TRppAAAycPvtt6urq0sPP/xwwa/FZCYAkGdjY2O6cOFC8P8zZvBVW242b96s9vZ29fb2aunSpQW7Dj1pAMizO++8U4lEIvi3devWYhcJedbc3Kx169Zp+/btBb0Of94BQB6dOHHCuZ25rUub677u3r274NelJw0AgKdopAEgT0ZHRzPajtIQ5/4V6h6HhrsJzwBAfOW80lUlK+Z9pScNAICnaKQBAPAUjTQAAJ6ikQYAwFOMk87ByMhI8Hp8fFySdPr0aR08eFANDQ3q7OyUJM2aNStpH0kaHh6eco7GxsaClxl+6u/v1/79+zU6Oqo1a9ZIujT1oKSkheXff/99SdLExESwraqqSpL04YcfJv3XZvaxj7XPYWbEunjxYu4fBkDeFLSR7ujoUCKRcL43OjpatpmQfX19On/+fLGLUVBh91Yq7/tbKCdPntTY2FixiwHAIwUNdycSCbW3t+vw4cPO91C6zL1NJBKqr69Xa2ururq6gl4f9xcAcke4O8LAwICk5FB0dXX1lG3GvHnzVFdXp/Hx8SDE+MEHH0zZz4TAzX+lyXD44OBgsG3OnDm5foSCOnDggFatWqW+vj6tXr1ajzzyiHbs2FHsYnnHftRx2WWX/ja2F1248sorVVNTo5qaGi1evFjSpYhMKhOitsPXqe+5wt3mmum4wtymzHb9rampCT0PgPwicQx50draqtWrV+vo0aPFLgoAlI2K70mfO3cueN3Q0CApuYczd+7cKceYnoqrNyMlJ+TY+0fta87n6j3b5zh79qykS6uw+OLkyZM6ePCgPv/5zxe7KNPKvn+uXqbpwdr7pdYP6dL9Te0JZ1pv7N566n5h57LPYddp89r1uVpaWoLX//3vf0PPDSB79KSRk7Vr12rOnDlasGCBWlpatG3btmIXCQDKBo00ctLT06PBwUG9+OKLeuONN3TmzJliFwkAykZFhbvthKzZs2dLSk7+CgsburalkzoONSzJxw5buq7hCkNefvnlkpJDmGbI17x582KXM59uv/12dXV16eGHH1ZPT09RylAM9qMRw76nrjBzunufGpp2hcVdx4ZdP4wrZO5iv2fC966kNjsJ0oznBpCbaWmkx8bGdOHChcmLzpjh/HJDadu8ebPa29vV29urpUuXFrs4AFDypiXcfeeddyqRSAT/tm7dOh2XxTRrbm7WunXrtH379mIXBQDKQsG7sydOnCj0JSKZKTjtcJwJ9dkhZlfIL24YMPW8qa/D9gsTFma3z1FfXy8peQpJEwK/+uqrY10rU657u3v37oJcqxSEZVdn87jE9f9x600cYXXbZpfd9TlMCNye4taUc+bMmbkUEah4JI4BAOApGmkAADxV0HD36Oho6AIbhWCyTu2s7bCQmyt86FoxKCq0nem2TLlCnq5tdkKeyfS2J2xpamrKuSxS+L0175cLE8a165H57FH3OywEnk6m9SWfIXCXqLofFsq3s9tNWDxumB1AgRtpVkEqX9xbACg8wt0AAHiqLAYr/+9//wtemzC3K2TtEhXKM+9nE4JMDZXn47z2semum6q2tjZ4bULf+Qp7lys7U9n8vE0GveSecCRuJn6m70cdm0tdSj1H3OtmE7IOe3QEwI2eNAAAnqKRBgDAUyUd7h4YGJA0OQ+3zQ7VuRa8jxtyyzREZ4e5XWUJ25YPUeU0oW97eUF72cFKZ7LS7YlvTP2yM5U/+OCDWOfLNIztqj9Rx+QzfJyv84fNMW4/FnD9bgKYxG8IAACeopEGAMBTJRfutrNuzeQScefcjpqkJNOJS4otbma665i5c+cG2/r7+yUlTwBTqVyTwoyNjUlyLzvpOjbue3Eei6RyZXIXaj7vfGeLu84bNhc4AHrSAAB4i0YaAABPlUy4e3BwUFL00nflMFFC3PnE072fqbq6OknJjxJcGfOVwIS57eztTCePiRL2qMUnmdYpJjgB8o+eNAAAnvK6J20SmqTkqS1TZTrm2T4m7jafhE0DGTcRznWMPTbY9KoroUdtxttLkz8DO6GpUHUgl154Lgo1jWg2SBIDwvEbAgCAp2ikAQDwlNfh7qjpPl3ijpmO816xxB2nnUsymf2eCTnaocdKCHObxyn2mGjXuN1M61Q2+8WV7SMZ17jq6aj7cR+1AHCjJw0AgKdopAEA8JSX4e73339fklRdXR1sc4UhDR/HmOZL3M8WFiLPJlzrGi9cbsxns8P85mfmyu6OypzPZTrZ6VzJyrVCVabXz+bYTK/hyvwO+x4AyhE9aQAAPEUjDQCAp7wMd5upP10hx0Ivel+I8+Uil4kncvkc5no1NTXBNvMYopQdP348eN3U1CQpuZ6Z1/maZKNQIwvyfd7p+L2Km1Xu+tmbY+xHYFGrkgHlgJ40AACeopEGAMBTXoa7TRgrmwk8CqXY83nnkjkcxZXRbF77FPrPhzlz5gSvXZO4uDKfXeJm04eFePNdp+Ku1hX3EUrcEHjc/fIR3rfPceLECUnSggULsj4v4Dt60gAAeIpGGgAAT3kZ7jbihrbzNZlCLhmzhco+j/u5Mw19u/aPu62U2aHtsNDtdGTTT+e81lEh+LifN5d5v/NxrF3OtrY2SUxwgvJGTxoAAE/RSAMA4Ckvw93TGb7K97zDVVVVzkzUbOUymYmRS5a8PXd3KWd6//Wvf5Uktbe3T3nPrm9msozpmNzDxa4/ceXjUUc+zht36dSorHbXhDKuiUvM5Dr2hDtAuaEnDQCAp2ikAQDwlJfhbpd8TwqRy2QLhVqazyWXTNw45416f2xsLNhWymHFa665RpK/mcC5PCZJ3d++t66s6LB7n00oPN9Z7YbrXtnXZe5uVAJ60gAAeMrLnnSmf+lHjQHNdPxzoRKEsukNhyXbZDOtY9yfrWuq0FLrSb/yyivB60984hOS4v/M8lUHwnrHuYyTDru3UT1p1zni9rjj/i65PnfYymJxf95xIwIovHvuuSd4vWfPnqRtzz//fFHKVI7oSQMA4CkaaQAAPOVluNuMzbUXeHeJO+7S9V5Y+DHfoc5M37NlurJSVLJN3BDhjBkz0p6vVCxatCh4bY/3DpNLElRYiDcq3J1pIlamj07sfcw9zSXBzFUW1+d2rTDmOjab3+Gw8DkK77333pN06Z6MjY1pYmIi2HbrrbdKki5evBjsb+YqQGao5QAAeMrLnjQAYPqsWrUqeH3+/HlJUktLS7BtaGhI0uQsb1JydMpEZ8w28/+uZFM74YwEs2heNtIm1GoLC+Pma8xz3GOiQphmu/kcmWZZ25810wxf1/tRIXDDtUJU1CMHn7lC3Nlk/cetX2ab6+fo2j91v9R6Y0Rl3Ydl+4eFse1xxuZ89nnDMsNdPx+7roTVTdd+2YSuCXejElDLAQDwlJc9aQBA4d1yyy2SpOHh4WDbrFmzJEkDAwPBNpMAli7ZMHWGQleU8zOf+YykyXC6JK1cuTLp/JL00ksv5fKRyo6XjbQJh7meebjEDXtFZeKGnS+bsHjY+cJCk64Qsys7N+754mb22uU0+9llKeXQt/lsrlW9ouqPq664jnU9Bon72CAspByV2Z96rKt+2NtMmNv+WZhtrhB4VLjbfDb7Gq5HVq6wvOtnb87n+oxMBYpK42UjDQDIryVLlkhK/sPIJILZfzi5cjnMH0fpOkvm+LChjq5OgymLfV7Tu3/55ZfTnquS8EwaAABPedOTtv8CM3/d2aEt89qVOWsz70dNjhB2bNyweLqwd5wwathqXplmg6fbzxUiND9nVwjcVaa6urpY1/VRY2Nj8HpkZERS/IzvqPudab1w9R7SHZtpvUnt3bgytO06YH6/7BXOzGtXWNwVYrbLaELb9nCbsNEDrt9hOzxuXrsmQrHLDFQCbxppAED2brjhhuD1zJkzJcXPZbHHPxuunIB0M9KlC3fb5zDXt//oM/kHrnIuW7Zsyn6JRCLYdsUVV0gq/7HWhLsBAPCUNz3pCxcuBK9NSMuVaerKprVDZXEnmTDsrNu48yzHDXGm/pUYFQZ1bQtbetP++YSFQV0hTDts6AoBm9Cl/Rd2bW3tlP1KxenTpyVJTU1NwTbX/Q4LyUZlcsfNVHbtd9lll6XNBI+qN6mhd1e4277HZriLPezF1AdXvbC3mfPZv3Omd+PqqdmfxfW++VmYnp80Wc/MUCBpsj6+8847U86BS1y9YZurN5zLZEmufVMfjUR9V5r94y7batfZU6dOxS5fKaMnDQCAp7zpSQNAse3YsaPYRcia/bw2LPmwED3pN998U5K0cePGpO3ZTM8c9r5rP3vSlVK1ZcuWtO9500jX19cHr0+cOJF2Pzt8ZkJkrokVbK4QZti2XMPdqRmrYROxuBIrbJmGqFzs85rQpf14wWQ+29vspI1y8LGPfUxS8i+0ud92nQmbuMQW9qUR9Qglqp6l1mFXlrN9bOrSrnZdMffUlaH97rvvBq9dGdXmvPa1TEjVrlNmP/tY18IKYT8LO9xtwtxz584NtplGAFOZxwPZLDOay36uyWlS62cmDX2m5TDXsNsOsxBIOfGmkQaAYgvr0fjq6quvluR+rm+Lmjkudb+oDoTdED/00EOSpN27dye9l6+hjOYPUPsPQdfMlL29vVPOU+popAGgzJjISVRiatxwd9yecVjU0HXNuI20+TyuRMRynyrWy0a6vb1dknT8+PFgmwnb2TfJhDlcIXDXX1x2RmpYFm/cSmSz90vN0nWFIVOPk+LPye2a2MWIyqY17GPNdIGVwA6hmkUF7HoRNnVhVIa2OU9UtrhrmzmuqqpqyrzXUXPJp75v33cTOrbDzzfddJMkadeuXcG2c+fOSZJWrFgRbLMngwnzyiuvTLmuCYvPnj072GZ6d1E9pL6+vqT/ApWM7G4AADzlZU/auO6660LfP3PmjKTknpDpSdvbTC8iqiftWoXKNT7bSJdc5JrqMB27xxbW47a59gvL5nStTlTKK1rli2vKU9eSfEZUkphrnHPcbWa73ZPOdJpa1xhmE22aN29esO3VV1+VJN12221TzpGN5cuXZ32sa8w2MuP63XdN/+uSaRKqi71UZZzQczarztnXcr0uZ/SkAQDwlNc9aQBAOFfvNW4vM5OFg8LOm9qTztf469Qy2ZncdjZ7OSvpRtpMsG5PW2hCmPbA/rDwc9hqWOnEHVaQWokKGZ4xSTl2gpBJtnNdN04ovhKZsKvrCyAq+Ss1UTDdfq5wd3V19ZQxw66kqjiJaK4xzOUw4QNQiQh3AwDgKbpTAFBiTBRRci+kEyabIaZxpZYhX+cNm2AlX9fwVVk00nZoctGiRZKSw3uusa/mBsfNfsxkDlrXVIdxj00VlmUcNd7UhMBfe+21jMpRyVzj7MNCzFGhbdd+rrB4dXV1kN2dWga7HpnHFK5trnHag4ODksKn2gXgr7JopAGgkpjhp9Lk8LpspuDMZQIn13CofPSkXZ2quJ2V1tZWSeU1EQ7PpAEA8FTZ9aRNprcdDnSFtl3bssn0dkmXTZ7pcIfU8oUd6wqrInNz5syRNDmtpeSeACZdyFpyZ3xHZYHb4e7U8LVdl81re/SCeaxhpgC1F1cwiy8cO3Ys4pMD8FHZNdIAUElci2nEXUo10xB4lNRORVTOT1hoO2qbYYfYs+lU+a78PhEAAGWi7HrSJtxtz0xjuEKO2fy1GHfZNtfczGHXyvdQgnJfwq0QLr/8cknS2bNnp7znmvvdld2dTQh8xowZUyY5CQuz2yFwE+Y283Tv27cv8nOifJw/f15S8lz05rvJNdLAxVWPox4Fur4H4ySORT12dCWhuXrS5vvN3q8cH/fRkwYAwFM00gAAeKrswt1m7mU77GFCg65wc9xkC5vrWNd5UpcajBvidpUzaoIME/qxw/xMYpK506dPS5rM8pYmH6HEDXfHnfTEFca2J8MJO58t0xmnUJ6Gh4eD12YOf9djlqhEK/Nd4ppvPt13aGqI2hVuN1xhbHubqz6H7WeXaWhoaMr1Sh09aQAAPFV2PWkAqHRmnL+dYOjq3ZreqCvhyk48da3sZy9PaV6nJuza5zXvxe0h29cPSyYrx2FXtrJrpP/9739Lkq677rpgm718o+HKFsx0DdSobO3UyhMV2k4Nj6c7V2r2rzT5GV966SX3B0BGzJzX0mTo2/7CMT97VyjadU+j5gK3hX3pmC8pe3lWw2R3AygfoY30jh07pqsceWfPyBT2pZdLI53Om2++KUnauHFj0vZMh3hFve/aj3WD8y9suF7ce+Xalvre8ePHJU3Wm7gTTaQuxPHee++FlqmStbW1qbOzs9jFAGIru540AOASO+Iye/ZsSe4pb6Nm9wpbec8Od6fOfmZf3xzrSlyzrxUWFrc7XK5oUjkKbaS3bNkyXeUoqBtvvFGS+1mMa33SqNVXoubTNj2hPXv2ZFRO1yQXrkxy14QW5pftT3/6U0bXRHzNzc3Ba9f822GPKaLC3dXV1dq0aZOqqqqCeuPKAk+d8MTe7+WXX87mYwHwWGgj3dHRkRQ2LoTR0VHt37+/oNdA6Sl03aPeodKMjIxM2eaamdGwH5uYWe3soYk204O2czlS/etf/5KU/MduuvNhUmgjXegGerquYZLInn/++WDbsmXLJCWHTEyFdY1fjZpiM+zZZNS46rD9TO/e1bv+y1/+ElqmUlboepHN+e0vrfnz50tKjma4vvDi9q7D6k/U+GemfwXK17Tkrl+8eFFf/epXNXfuXLW2tmrnzp3TcVlUOOodgFI3LYljW7du1fHjx/X222+rr69Pd9xxh5YsWaIvfOEL03F5VCjqHZA9OyydD9dcc01ez1cpIhvpn/3sZ/rzn/+c9PzuW9/6lqqqqvTzn/881kX27t2rp556Sk1NTWpqatKGDRv01FNPTduXpR3mNv72t79ldI7FixcHr8MG0buGxpj9o1aEMfsfPXo0o7KVo7feeku33HKLDh8+rGXLlundd9/V0qVL9dxzz2nlypWxzlHIenfq1Km071111VXBa5PQZ49pd031GjbMyvVoxA5x//3vf8+o7ABKR2S4u7OzU4cOHVJ/f7+kS8/dnnnmGa1bt07f+MY31NjY6Pz3qU99SpJ07tw5nTp1SkuXLg3OuXTpUv3jH/8o0EdCObj22mv105/+VJ2dnRoZGdFXvvIVrV+/XitXrqTeAagYkT3p+fPn63Of+5yee+45bdiwQYcOHdIVV1yhm2++WTfffLN27doVeryZ8LyhoSHY1tDQEJoFCEjShg0bdODAAa1YsUJVVVX67W9/K0natWsX9Q5ARYj1THr9+vXavXu3NmzYoO7ubn35y1+OfQEzVeHAwECQxj8wMFByqfevv/568HrJkiWSwkOU9mpGYWOtWakq3IYNG3TXXXdpz549qq2tjX1cMetdXV1d8NrcZzvcbaSOf063epq9nzlfb29vnksNwEexsrvXrl2rV199Va+99pp+97vf6Utf+pIkadOmTaqvr3f+u+GGGyRJTU1Nmj9/ftKXSm9vb/B+Obr++ut1/fXXF7sYJW9oaEibN2/W1772NW3dulVnz56VVL71jnoDIFWsnvSsWbN077336sEHH9SnP/1pLVy4UJL02GOP6bHHHos8ft26dfrxj3+s5cuX6/Tp0/rlL3+pJ598MreSe+x73/te7Hm6kd63v/1tLV++XI8//rg2btyoTZs26dlnny3bevfd736XegMgSewhWOvXr9fjjz+uJ554IuOLbNu2TQ899JDa2tqUSCT0/e9/v6SHwSxatEiS9M9//nPKe2GLeZC1Hd8LL7ygQ4cOBZnLO3fu1E033aRf/epXQSQnSrHqnVkow2YS2qTwbH/X9KGZjkQAUD5iN9ILFy5UIpFQR0dHxhepra3VE088kVUDj8p099136+677w7+v76+3vlHURjqHYBSF+uZ9Pj4uHbu3Kn7779fc+fOLXSZAACAYvSkh4eHdeWVV6qtrU2HDh0qSCFKdX1XO4QZxyc/+ckClQTZKJV6Z0YToPC6u7uLXQQgSWQjXVdXF4w5BQAA02daFtgAAACZo5EGAMBTNNIAAHiKRhoAAE/RSAMA4CkaaQAAPEUjDQCAp2JPCwoA5a6jo0OJRKLYxQiMjo5q//79xS4GioieNAB8xKcGWvKvPJh+NNIAUCDHjh3T8uXL1dTUpKamJq1atUrHjh0L3l+zZk3Seug1NTW68cYbi1hi+IZGGgAK5KqrrtK+fft09uxZnTlzRnfddZfuv//+4P2DBw9qaGgo+Hfrrbfqi1/8YhFLDN/QSAPAR37zm98k9Wxra2u1cuXKrM/X2Nio9vZ2VVVVaWJiQtXV1WmXXD1x4oT+8Ic/aN26dVlfD+WHxDEA+Mh9992n++67T5I0MDCgFStW6IEHHtCjjz6qRx99NO1x/f39oedtbGzU0NCQxsfHtX37duc+Tz/9tD772c+qvb096/IXS1tbW7GLULZopAEgxfj4uB588EGtXLlSX//61yVJP/jBD7I+X39/v4aHh7V37960DdrTTz+tH/3oR1lfo5hKZdnXUkQjDQAptmzZosHBQf3iF7+Ifcw777yTtPZ36hK/dXV12rRpk5qbm/X666+rpaUleO+Pf/yj+vr6dO+99+ZeeJQVnkkDgOWZZ57Rr3/9a+3bt08zZ86UJP3kJz9Jelad+k+SFi5cmJQE5jI+Pq6RkRH95z//Sdq+d+9e3XPPPcG5AINGGgA+cuTIEX3zm99UT0+Pmpubg+0//OEPkxrg1H/p/P73v9eRI0f04YcfamBgQN/5znfU1NSkxYsXB/uMjo7q2WefVVdXVyE/GkoUjTQAfOSFF17QuXPndNtttwW95DVr1mR9vv7+fj3wwANqaGjQtddeq7feekuHDh3SrFmzgn16enrU2NioO+64Ix8fAWWmamJiYqLYhQAAuHV3dxe7CJgG6ZLv6EkDAOApetIAAHiKnjQAAJ6ikQYAwFM00gAAeIpGGgAAT9FIAwDgKRppAAA8RSMNAICnaKQBAPAUjTQAAJ6ikQYAwFM00gAAeIpGGgAAT9FIAwDgKRppAAA8RSMNAICnaKQBAPAUjTQAAJ6ikQYAwFM00gAAeIpGGgAAT9FIAwDgqf8DR/uDeCgxviIAAAAASUVORK5CYII=\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plot_anat(fmap_file)" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAekAAADJCAYAAAAHFcoVAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjAsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+17YcXAAAcr0lEQVR4nO3df2yV1R3H8U8ttFxaaIu2Fg200zkB5zCIIzNu4kLC8A8l1sUf66DbAsMl28jifmTsDyBjuiwh2f4Aw4yK6TKnYOpYAsn4w2Rb3KIb1Dk0Mhd0TMpkUPoTrLb7A8/Tc2/PfZ7n/uo99973KyFen/v8OLfP6T093+d7zqmamJiYEAAA8M5lxS4AAABwo5EGAMBTNNIAAHiKRhoAAE/RSAMA4CkaaQAAPEUjDQCAp2ikAQDwFI00AACeopEGAMBTNNIAAHiKRhoAAE/RSAMA4CkaaQAAPEUjDQCAp2ikAQDwFI00AACeopEGAMBTNNIAAHiKRhoAAE/NKHYBAMAX3d3dxS4CKlRnZ6dzOz1pAAA8RSMNAICnaKQBAPAUjTQAAJ6ikQYAwFM00gAAeIpGGgCQk+7uboavFQjjpAEgTzo6OpRIJKZsHx0d1f79+4tQounx9ttvF7sIBZXuvtoKdY/pSQNAnqT7Io/6goff4ty/Qt1jGmkAyKP29nYdPny42MVAnrW3tyuRSKi+vl6tra3q6urS0NBQwa9LIw0AQAwHDhzQ0NCQjh49qiNHjuiRRx4p+DVppAEAyEBra6tWr16to0ePFvxaNNIAAGTg5MmTOnjwoD7+8Y8X/Fo00gAAxLB27VrNmTNHCxYsUEtLi7Zt21bwa9JIAwAQQ09PjwYHB/Xiiy/qjTfe0JkzZwp+TRppAAAycPvtt6urq0sPP/xwwa/FZCYAkGdjY2O6cOFC8P8zZvBVW242b96s9vZ29fb2aunSpQW7Dj1pAMizO++8U4lEIvi3devWYhcJedbc3Kx169Zp+/btBb0Of94BQB6dOHHCuZ25rUub677u3r274NelJw0AgKdopAEgT0ZHRzPajtIQ5/4V6h6HhrsJzwBAfOW80lUlK+Z9pScNAICnaKQBAPAUjTQAAJ6ikQYAwFOMk87ByMhI8Hp8fFySdPr0aR08eFANDQ3q7OyUJM2aNStpH0kaHh6eco7GxsaClxl+6u/v1/79+zU6Oqo1a9ZIujT1oKSkheXff/99SdLExESwraqqSpL04YcfJv3XZvaxj7XPYWbEunjxYu4fBkDeFLSR7ujoUCKRcL43OjpatpmQfX19On/+fLGLUVBh91Yq7/tbKCdPntTY2FixiwHAIwUNdycSCbW3t+vw4cPO91C6zL1NJBKqr69Xa2ururq6gl4f9xcAcke4O8LAwICk5FB0dXX1lG3GvHnzVFdXp/Hx8SDE+MEHH0zZz4TAzX+lyXD44OBgsG3OnDm5foSCOnDggFatWqW+vj6tXr1ajzzyiHbs2FHsYnnHftRx2WWX/ja2F1248sorVVNTo5qaGi1evFjSpYhMKhOitsPXqe+5wt3mmum4wtymzHb9rampCT0PgPwicQx50draqtWrV+vo0aPFLgoAlI2K70mfO3cueN3Q0CApuYczd+7cKceYnoqrNyMlJ+TY+0fta87n6j3b5zh79qykS6uw+OLkyZM6ePCgPv/5zxe7KNPKvn+uXqbpwdr7pdYP6dL9Te0JZ1pv7N566n5h57LPYddp89r1uVpaWoLX//3vf0PPDSB79KSRk7Vr12rOnDlasGCBWlpatG3btmIXCQDKBo00ctLT06PBwUG9+OKLeuONN3TmzJliFwkAykZFhbvthKzZs2dLSk7+CgsburalkzoONSzJxw5buq7hCkNefvnlkpJDmGbI17x582KXM59uv/12dXV16eGHH1ZPT09RylAM9qMRw76nrjBzunufGpp2hcVdx4ZdP4wrZO5iv2fC966kNjsJ0oznBpCbaWmkx8bGdOHChcmLzpjh/HJDadu8ebPa29vV29urpUuXFrs4AFDypiXcfeeddyqRSAT/tm7dOh2XxTRrbm7WunXrtH379mIXBQDKQsG7sydOnCj0JSKZKTjtcJwJ9dkhZlfIL24YMPW8qa/D9gsTFma3z1FfXy8peQpJEwK/+uqrY10rU657u3v37oJcqxSEZVdn87jE9f9x600cYXXbZpfd9TlMCNye4taUc+bMmbkUEah4JI4BAOApGmkAADxV0HD36Oho6AIbhWCyTu2s7bCQmyt86FoxKCq0nem2TLlCnq5tdkKeyfS2J2xpamrKuSxS+L0175cLE8a165H57FH3OywEnk6m9SWfIXCXqLofFsq3s9tNWDxumB1AgRtpVkEqX9xbACg8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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plot_anat(out_file)" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAekAAADJCAYAAAAHFcoVAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjAsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+17YcXAAAcr0lEQVR4nO3df2yV1R3H8U8ttFxaaIu2Fg200zkB5zCIIzNu4kLC8A8l1sUf66DbAsMl28jifmTsDyBjuiwh2f4Aw4yK6TKnYOpYAsn4w2Rb3KIb1Dk0Mhd0TMpkUPoTrLb7A8/Tc2/PfZ7n/uo99973KyFen/v8OLfP6T093+d7zqmamJiYEAAA8M5lxS4AAABwo5EGAMBTNNIAAHiKRhoAAE/RSAMA4CkaaQAAPEUjDQCAp2ikAQDwFI00AACeopEGAMBTNNIAAHiKRhoAAE/RSAMA4CkaaQAAPEUjDQCAp2ikAQDwFI00AACeopEGAMBTNNIAAHiKRhoAAE/NKHYBAMAX3d3dxS4CKlRnZ6dzOz1pAAA8RSMNAICnaKQBAPAUjTQAAJ6ikQYAwFM00gAAeIpGGgCQk+7uboavFQjjpAEgTzo6OpRIJKZsHx0d1f79+4tQounx9ttvF7sIBZXuvtoKdY/pSQNAnqT7Io/6goff4ty/Qt1jGmkAyKP29nYdPny42MVAnrW3tyuRSKi+vl6tra3q6urS0NBQwa9LIw0AQAwHDhzQ0NCQjh49qiNHjuiRRx4p+DVppAEAyEBra6tWr16to0ePFvxaNNIAAGTg5MmTOnjwoD7+8Y8X/Fo00gAAxLB27VrNmTNHCxYsUEtLi7Zt21bwa9JIAwAQQ09PjwYHB/Xiiy/qjTfe0JkzZwp+TRppAAAycPvtt6urq0sPP/xwwa/FZCYAkGdjY2O6cOFC8P8zZvBVW242b96s9vZ29fb2aunSpQW7Dj1pAMizO++8U4lEIvi3devWYhcJedbc3Kx169Zp+/btBb0Of94BQB6dOHHCuZ25rUub677u3r274NelJw0AgKdopAEgT0ZHRzPajtIQ5/4V6h6HhrsJzwBAfOW80lUlK+Z9pScNAICnaKQBAPAUjTQAAJ6ikQYAwFOMk87ByMhI8Hp8fFySdPr0aR08eFANDQ3q7OyUJM2aNStpH0kaHh6eco7GxsaClxl+6u/v1/79+zU6Oqo1a9ZIujT1oKSkheXff/99SdLExESwraqqSpL04YcfJv3XZvaxj7XPYWbEunjxYu4fBkDeFLSR7ujoUCKRcL43OjpatpmQfX19On/+fLGLUVBh91Yq7/tbKCdPntTY2FixiwHAIwUNdycSCbW3t+vw4cPO91C6zL1NJBKqr69Xa2ururq6gl4f9xcAcke4O8LAwICk5FB0dXX1lG3GvHnzVFdXp/Hx8SDE+MEHH0zZz4TAzX+lyXD44OBgsG3OnDm5foSCOnDggFatWqW+vj6tXr1ajzzyiHbs2FHsYnnHftRx2WWX/ja2F1248sorVVNTo5qaGi1evFjSpYhMKhOitsPXqe+5wt3mmum4wtymzHb9rampCT0PgPwicQx50draqtWrV+vo0aPFLgoAlI2K70mfO3cueN3Q0CApuYczd+7cKceYnoqrNyMlJ+TY+0fta87n6j3b5zh79qykS6uw+OLkyZM6ePCgPv/5zxe7KNPKvn+uXqbpwdr7pdYP6dL9Te0JZ1pv7N566n5h57LPYddp89r1uVpaWoLX//3vf0PPDSB79KSRk7Vr12rOnDlasGCBWlpatG3btmIXCQDKBo00ctLT06PBwUG9+OKLeuONN3TmzJliFwkAykZFhbvthKzZs2dLSk7+CgsburalkzoONSzJxw5buq7hCkNefvnlkpJDmGbI17x582KXM59uv/12dXV16eGHH1ZPT09RylAM9qMRw76nrjBzunufGpp2hcVdx4ZdP4wrZO5iv2fC966kNjsJ0oznBpCbaWmkx8bGdOHChcmLzpjh/HJDadu8ebPa29vV29urpUuXFrs4AFDypiXcfeeddyqRSAT/tm7dOh2XxTRrbm7WunXrtH379mIXBQDKQsG7sydOnCj0JSKZKTjtcJwJ9dkhZlfIL24YMPW8qa/D9gsTFma3z1FfXy8peQpJEwK/+uqrY10rU657u3v37oJcqxSEZVdn87jE9f9x600cYXXbZpfd9TlMCNye4taUc+bMmbkUEah4JI4BAOApGmkAADxV0HD36Oho6AIbhWCyTu2s7bCQmyt86FoxKCq0nem2TLlCnq5tdkKeyfS2J2xpamrKuSxS+L0175cLE8a165H57FH3OywEnk6m9SWfIXCXqLofFsq3s9tNWDxumB1AgRtpVkEqX9xbACg8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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plot_anat(new_out_file)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "dwi_venv", + "language": "python", + "name": "dwi_venv" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.1" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/notebooks/make_qc.ipynb b/notebooks/make_qc.ipynb new file mode 100644 index 0000000..96691f8 --- /dev/null +++ b/notebooks/make_qc.ipynb @@ -0,0 +1,395 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 67, + "metadata": {}, + "outputs": [], + "source": [ + "from docopt import docopt\n", + "import pandas as pd\n", + "import os\n", + "import tempfile\n", + "import shutil\n", + "from glob import glob\n", + "import sys\n", + "import subprocess as proc\n", + "\n", + "import datman as dm\n", + "import datman.utils" + ] + }, + { + "cell_type": "code", + "execution_count": 68, + "metadata": {}, + "outputs": [], + "source": [ + "output_dir = '/scratch/smansour/CARTBIND/combined/dmriprep'\n", + "dtifit_dir = '/scratch/mjoseph/test/dtifit'\n", + "QCdir = os.path.join(dtifit_dir, 'QC')\n", + "tmpdirbase = os.path.join(QCdir,'tmp')\n", + "QC_bet_dir = os.path.join(QCdir,'BET')\n", + "QC_V1_dir = os.path.join(QCdir, 'directions')\n", + "QC_FM_dir = os.path.join(QCdir, 'FM')\n", + "QC_Mag_dir = os.path.join(QCdir, 'Mag')\n", + "QC_res_dir = os.path.join(QCdir, 'res')\n", + "QC_SH_dir = os.path.join(QCdir, 'SH')\n", + "\n", + "dir_list = [tmpdirbase, QC_bet_dir, QC_V1_dir, QC_res_dir, QC_SH_dir]" + ] + }, + { + "cell_type": "code", + "execution_count": 69, + "metadata": {}, + "outputs": [], + "source": [ + "for qc_dir in dir_list:\n", + " if not os.path.exists(qc_dir):\n", + " os.makedirs(qc_dir)" + ] + }, + { + "cell_type": "code", + "execution_count": 70, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "grad_out = os.path.join(tmpdirbase,'ramp.gif')\n", + "create_gradient_file(grad_out,'red-yellow')" + ] + }, + { + "cell_type": "code", + "execution_count": 71, + "metadata": {}, + "outputs": [], + "source": [ + "maskpics = []\n", + "V1pics = []\n", + "Respics = []\n", + "SHpics = []" + ] + }, + { + "cell_type": "code", + "execution_count": 72, + "metadata": {}, + "outputs": [], + "source": [ + "allFAmaps = glob('{}/sub-*/ses-*/dwi/dtifit__FA*'.format(output_dir))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for FAmap in allFAmaps:\n", + " subid = FAmap.split('/')[-4]\n", + " sesid = FAmap.split('/')[-3]\n", + " tmpdir = os.path.join(tmpdirbase, subid, sesid)\n", + " if not os.path.exists(tmpdir):\n", + " os.makedirs(tmpdir)\n", + " basename = '{}_{}_'.format(subid, sesid)\n", + " pathbase = FAmap.replace('dtifit__FA.nii.gz','')\n", + " pathdir = os.path.dirname(pathbase)\n", + " SHtmp = os.path.join(tmpdir,'SHmap.gif')\n", + " SHpic = os.path.join(QC_SH_dir,basename + 'SH.gif')\n", + " SHpics.append(SHpic)\n", + " SH_overlay(os.path.join(pathdir,'eddy_corrected_noise.nii.gz'), SHtmp, grad_out)\n", + " if os.path.exists(os.path.join(pathdir,'eddy_corrected_noise.nii.gz')):\n", + " gif_gridtoline(SHtmp,SHpic)" + ] + }, + { + "cell_type": "code", + "execution_count": 81, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "run(slices /scratch/smansour/CARTBIND/combined/dmriprep/sub-034/ses-01/dwi/sub-034_ses-01_dwi_denoised_unr_avg_b0_brain.nii.gz /scratch/smansour/CARTBIND/combined/dmriprep/sub-034/ses-01/dwi/sub-034_ses-01_dwi_denoised_unr_avg_b0_brain_mask.nii.gz -o /scratch/mjoseph/test/dtifit/QC/tmp/sub-034/ses-01/B0masked.gif) failed with returncode 1. STDERR: b''\n", + "run(convert /scratch/mjoseph/test/dtifit/QC/tmp/sub-034/ses-01/B0masked.gif -resize 384x384 /scratch/mjoseph/test/dtifit/QC/tmp/sub-034/ses-01/B0masked.gif) failed with returncode 1. STDERR: b\"convert: unable to open image `/scratch/mjoseph/test/dtifit/QC/tmp/sub-034/ses-01/B0masked.gif': No such file or directory @ error/blob.c/OpenBlob/2712.\\nconvert: no images defined `/scratch/mjoseph/test/dtifit/QC/tmp/sub-034/ses-01/B0masked.gif' @ error/convert.c/ConvertImageCommand/3210.\\n\"\n", + "run(convert /scratch/mjoseph/test/dtifit/QC/tmp/sub-034/ses-01/B0masked.gif -crop 100x33%+0+0 /scratch/mjoseph/test/dtifit/QC/tmp/sub-034/ses-01/sag.gif) failed with returncode 1. STDERR: b\"convert: unable to open image `/scratch/mjoseph/test/dtifit/QC/tmp/sub-034/ses-01/B0masked.gif': No such file or directory @ error/blob.c/OpenBlob/2712.\\nconvert: no images defined `/scratch/mjoseph/test/dtifit/QC/tmp/sub-034/ses-01/sag.gif' @ error/convert.c/ConvertImageCommand/3210.\\n\"\n", + "run(convert /scratch/mjoseph/test/dtifit/QC/tmp/sub-034/ses-01/B0masked.gif -crop 100x33%+0+128 /scratch/mjoseph/test/dtifit/QC/tmp/sub-034/ses-01/cor.gif) failed with returncode 1. STDERR: b\"convert: unable to open image `/scratch/mjoseph/test/dtifit/QC/tmp/sub-034/ses-01/B0masked.gif': No such file or directory @ error/blob.c/OpenBlob/2712.\\nconvert: no images defined `/scratch/mjoseph/test/dtifit/QC/tmp/sub-034/ses-01/cor.gif' @ error/convert.c/ConvertImageCommand/3210.\\n\"\n", + "run(convert /scratch/mjoseph/test/dtifit/QC/tmp/sub-034/ses-01/B0masked.gif -crop 100x33%+0+256 /scratch/mjoseph/test/dtifit/QC/tmp/sub-034/ses-01/ax.gif) failed with returncode 1. STDERR: b\"convert: unable to open image `/scratch/mjoseph/test/dtifit/QC/tmp/sub-034/ses-01/B0masked.gif': No such file or directory @ error/blob.c/OpenBlob/2712.\\nconvert: no images defined `/scratch/mjoseph/test/dtifit/QC/tmp/sub-034/ses-01/ax.gif' @ error/convert.c/ConvertImageCommand/3210.\\n\"\n", + "run(slices /scratch/smansour/CARTBIND/combined/dmriprep/sub-098/ses-01/dwi/sub-098_ses-01_dwi_denoised_unr_avg_b0_brain.nii.gz /scratch/smansour/CARTBIND/combined/dmriprep/sub-098/ses-01/dwi/sub-098_ses-01_dwi_denoised_unr_avg_b0_brain_mask.nii.gz -o /scratch/mjoseph/test/dtifit/QC/tmp/sub-098/ses-01/B0masked.gif) failed with returncode 1. STDERR: b''\n", + "run(convert /scratch/mjoseph/test/dtifit/QC/tmp/sub-098/ses-01/B0masked.gif -resize 384x384 /scratch/mjoseph/test/dtifit/QC/tmp/sub-098/ses-01/B0masked.gif) failed with returncode 1. STDERR: b\"convert: unable to open image `/scratch/mjoseph/test/dtifit/QC/tmp/sub-098/ses-01/B0masked.gif': No such file or directory @ error/blob.c/OpenBlob/2712.\\nconvert: no images defined `/scratch/mjoseph/test/dtifit/QC/tmp/sub-098/ses-01/B0masked.gif' @ error/convert.c/ConvertImageCommand/3210.\\n\"\n", + "run(convert /scratch/mjoseph/test/dtifit/QC/tmp/sub-098/ses-01/B0masked.gif -crop 100x33%+0+0 /scratch/mjoseph/test/dtifit/QC/tmp/sub-098/ses-01/sag.gif) failed with returncode 1. STDERR: b\"convert: unable to open image `/scratch/mjoseph/test/dtifit/QC/tmp/sub-098/ses-01/B0masked.gif': No such file or directory @ error/blob.c/OpenBlob/2712.\\nconvert: no images defined `/scratch/mjoseph/test/dtifit/QC/tmp/sub-098/ses-01/sag.gif' @ error/convert.c/ConvertImageCommand/3210.\\n\"\n", + "run(convert /scratch/mjoseph/test/dtifit/QC/tmp/sub-098/ses-01/B0masked.gif -crop 100x33%+0+128 /scratch/mjoseph/test/dtifit/QC/tmp/sub-098/ses-01/cor.gif) failed with returncode 1. STDERR: b\"convert: unable to open image `/scratch/mjoseph/test/dtifit/QC/tmp/sub-098/ses-01/B0masked.gif': No such file or directory @ error/blob.c/OpenBlob/2712.\\nconvert: no images defined `/scratch/mjoseph/test/dtifit/QC/tmp/sub-098/ses-01/cor.gif' @ error/convert.c/ConvertImageCommand/3210.\\n\"\n", + "run(convert /scratch/mjoseph/test/dtifit/QC/tmp/sub-098/ses-01/B0masked.gif -crop 100x33%+0+256 /scratch/mjoseph/test/dtifit/QC/tmp/sub-098/ses-01/ax.gif) failed with returncode 1. STDERR: b\"convert: unable to open image `/scratch/mjoseph/test/dtifit/QC/tmp/sub-098/ses-01/B0masked.gif': No such file or directory @ error/blob.c/OpenBlob/2712.\\nconvert: no images defined `/scratch/mjoseph/test/dtifit/QC/tmp/sub-098/ses-01/ax.gif' @ error/convert.c/ConvertImageCommand/3210.\\n\"\n" + ] + } + ], + "source": [ + "for FAmap in allFAmaps:\n", + " subid = FAmap.split('/')[-4]\n", + " sesid = FAmap.split('/')[-3]\n", + " tmpdir = os.path.join(tmpdirbase, subid, sesid)\n", + " if not os.path.exists(tmpdir):\n", + " os.makedirs(tmpdir)\n", + " basename = '{}_{}_'.format(subid, sesid)\n", + " pathbase = FAmap.replace('dtifit__FA.nii.gz','')\n", + " pathdir = os.path.dirname(pathbase)\n", + "\n", + " maskpic = os.path.join(QC_bet_dir,basename + 'b0_bet_mask.gif')\n", + " maskpics.append(maskpic)\n", + " mask_overlay(os.path.join(pathdir,'{}_{}_dwi_denoised_unr_avg_b0_brain.nii.gz'.format(subid, sesid)), \n", + " os.path.join(pathdir,'{}_{}_dwi_denoised_unr_avg_b0_brain_mask.nii.gz'.format(subid, sesid)), maskpic)\n", + " V1pic = os.path.join(QC_V1_dir,basename + 'dtifit_V1.gif')\n", + " V1pics.append(V1pic)\n", + " V1_overlay(FAmap,pathbase + 'dtifit__V1.nii.gz', V1pic)\n", + "\n", + "# SHtmp = os.path.join(tmpdir,'SHmap.gif')\n", + "# SHpic = os.path.join(QC_SH_dir,basename + 'SH.gif')\n", + "# SHpics.append(SHpic)\n", + "# SH_overlay(os.path.join(pathdir,'eddy_corrected_noise.nii.gz'), SHtmp, grad_out)\n", + "# gif_gridtoline(SHtmp,SHpic)" + ] + }, + { + "cell_type": "code", + "execution_count": 76, + "metadata": {}, + "outputs": [], + "source": [ + "qchtml = open(os.path.join(QCdir,'qc_BET.html'),'w')\n", + "qchtml.write('DTIFIT BET QC page')\n", + "qchtml.write('\\n')\n", + "qchtml.write('

DTIFIT BET QC page

')\n", + "for pic in maskpics:\n", + " relpath = os.path.relpath(pic,QCdir)\n", + " qchtml.write('')\n", + " qchtml.write(' ')\n", + " qchtml.write(relpath + '
\\n')\n", + "qchtml.write('\\n')\n", + "qchtml.close() # you can omit in most cases as the destructor will call it\n", + "\n", + "## write an html page that shows all the V1 pics\n", + "qchtml = open(os.path.join(QCdir,'qc_directions.html'),'w')\n", + "qchtml.write('DTIFIT directions QC page')\n", + "qchtml.write('\\n')\n", + "qchtml.write('

DTIFIT directions QC page

')\n", + "for pic in V1pics:\n", + " relpath = os.path.relpath(pic,QCdir)\n", + " qchtml.write('')\n", + " qchtml.write(' ')\n", + " qchtml.write(relpath + '
\\n')\n", + "qchtml.write('\\n')\n", + "qchtml.close() # you can omit in most cases as the destructor will call it\n", + "\n", + "# write an html page that shows all the SH residual pics\n", + "qchtml = open(os.path.join(QCdir,'qc_SH.html'),'w')\n", + "qchtml.write('SH residual QC page')\n", + "qchtml.write('\\n')\n", + "qchtml.write('

SH residual QC page

')\n", + "for pic in SHpics:\n", + " relpath = os.path.relpath(pic,QCdir)\n", + " qchtml.write('')\n", + " qchtml.write(' ')\n", + " qchtml.write(relpath + '
\\n')\n", + "qchtml.write('\\n')\n", + "qchtml.close() # you can omit in most cases as the destructor will call it\n", + "\n", + "## write an html page that shows all the Res pics\n", + "qchtml = open(os.path.join(QCdir,'qc_res.html'),'w')\n", + "qchtml.write('DTIFIT residual QC page')\n", + "qchtml.write('\\n')\n", + "qchtml.write('

DTIFIT residual QC page

')\n", + "for pic in Respics:\n", + " relpath = os.path.relpath(pic,QCdir)\n", + " qchtml.write('')\n", + " qchtml.write(' ')\n", + " qchtml.write(relpath + '
\\n')\n", + "qchtml.write('\\n')\n", + "qchtml.close() # you can omit in most cases as the destructor will call it" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": {}, + "outputs": [], + "source": [ + "def gif_gridtoline(input_gif,output_gif):\n", + " '''\n", + " uses imagemagick to take a grid from fsl slices and convert to one line (like in slicesdir)\n", + " '''\n", + " dm.utils.run(['convert',input_gif, '-resize', '384x384',input_gif])\n", + " dm.utils.run(['convert', input_gif,\\\n", + " '-crop', '100x33%+0+0', os.path.join(tmpdir,'sag.gif')])\n", + " dm.utils.run(['convert', input_gif,\\\n", + " '-crop', '100x33%+0+128', os.path.join(tmpdir,'cor.gif')])\n", + " dm.utils.run(['convert', input_gif,\\\n", + " '-crop', '100x33%+0+256', os.path.join(tmpdir,'ax.gif')])\n", + " dm.utils.run(['montage', '-mode', 'concatenate', '-tile', '3x1', \\\n", + " os.path.join(tmpdir,'sag.gif'),\\\n", + " os.path.join(tmpdir,'cor.gif'),\\\n", + " os.path.join(tmpdir,'ax.gif'),\\\n", + " os.path.join(output_gif)])" + ] + }, + { + "cell_type": "code", + "execution_count": 74, + "metadata": {}, + "outputs": [], + "source": [ + "def mask_overlay(background_nii,mask_nii, overlay_gif):\n", + " '''\n", + " use slices from fsl to overlay the mask on the background (both nii)\n", + " then make the grid to a line for easier scrolling during QC\n", + " '''\n", + " dm.utils.run(['slices', background_nii, mask_nii, '-o', os.path.join(tmpdir,'B0masked.gif')])\n", + " gif_gridtoline(os.path.join(tmpdir,'B0masked.gif'),overlay_gif)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "def V1_overlay(background_nii,V1_nii, overlay_gif):\n", + " '''\n", + " use fslsplit to split the V1 image and take pictures of each direction\n", + " use slices from fsl to get the background and V1 picks (both nii)\n", + " recolor the V1 image using imagemagick\n", + " then make the grid to a line for easier scrolling during QC\n", + " '''\n", + " dm.utils.run(['slices',background_nii,'-o',os.path.join(tmpdir,\"background.gif\")])\n", + " dm.utils.run(['fslmaths',background_nii,'-thr','0.15','-bin',os.path.join(tmpdir,'FAmask.nii.gz')])\n", + " dm.utils.run(['fslsplit', V1_nii, os.path.join(tmpdir,\"V1\")])\n", + " for axis in ['0000','0001','0002']:\n", + " dm.utils.run(['fslmaths',os.path.join(tmpdir,'V1'+axis+'.nii.gz'), '-abs', \\\n", + " '-mul', os.path.join(tmpdir,'FAmask.nii.gz'), os.path.join(tmpdir,'V1'+axis+'abs.nii.gz')])\n", + " dm.utils.run(['slices',os.path.join(tmpdir,'V1'+axis+'abs.nii.gz'),'-o',os.path.join(tmpdir,'V1'+axis+'abs.gif')])\n", + " # docmd(['convert', os.path.join(tmpdir,'V1'+axis+'abs.gif'),\\\n", + " # '-fuzz', '15%', '-transparent', 'black', os.path.join(tmpdir,'V1'+axis+'set.gif')])\n", + " dm.utils.run(['convert', os.path.join(tmpdir,'V10000abs.gif'),\\\n", + " os.path.join(tmpdir,'V10001abs.gif'), os.path.join(tmpdir,'V10002abs.gif'),\\\n", + " '-set', 'colorspace', 'RGB', '-combine', '-set', 'colorspace', 'sRGB',\\\n", + " os.path.join(tmpdir,'dirmap.gif')])\n", + " gif_gridtoline(os.path.join(tmpdir,'dirmap.gif'),overlay_gif)" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "def SSE_overlay(sse,out,grad):\n", + " '''\n", + " Arguments:\n", + " sse Full path to SSE file\n", + " out Full path to output\n", + " grad Full path to gradient look-up map\n", + "\n", + " Steps:\n", + " 1. Clever/Hacky thresholding so maximum intensity is 2\n", + " 2. Generate slices\n", + " 3. Use gradient map to color greyscale image\n", + " 4. Background filling with 0 fuzziness to prevent leakage\n", + " '''\n", + " slice_out = out.replace('.nii.gz','.gif')\n", + " cmd1 = 'fslmaths {} -sub 3 -mul -1 -thr 0 -mul -1 -add 3 {}'.format(sse,out)\n", + " cmd2 = 'slices {} -o {}'.format(out, slice_out)\n", + " cmd3 = 'convert {} {} -clut {}'.format(slice_out, grad, slice_out)\n", + " cmd4 = 'convert {} -fill black -draw \"color 0,0 floodfill\" {}'.format(slice_out,slice_out)\n", + " cmdlist = [cmd1, cmd2, cmd3, cmd4]\n", + " outputs = [call(c) for c in cmdlist]\n", + " return" + ] + }, + { + "cell_type": "code", + "execution_count": 58, + "metadata": {}, + "outputs": [], + "source": [ + "def SH_overlay(SH,out,grad):\n", + " '''\n", + " Arguments:\n", + " SH Full path to SSE file\n", + " out Full path to output\n", + " grad Full path to gradient look-up map\n", + "\n", + " Steps:\n", + " 1. Clever/Hacky thresholding so maximum intensity is 2\n", + " 2. Generate slices\n", + " 3. Use gradient map to color greyscale image\n", + " 4. Background filling with 0 fuzziness to prevent leakage\n", + " '''\n", + " slice_out = out.replace('.nii.gz','.gif')\n", + " cmd1 = 'fslmaths {} -sub 0.3 -mul -1 -thr 0 -mul -1 -add 0.3 {}'.format(SH,out)\n", + " cmd2 = 'slices {} -o {}'.format(out, slice_out)\n", + " cmd3 = 'convert {} {} -clut {}'.format(slice_out, grad, slice_out)\n", + " cmd4 = 'convert {} -fill black -draw \"color 0,0 floodfill\" {}'.format(slice_out,slice_out)\n", + " cmdlist = [cmd1, cmd2, cmd3, cmd4]\n", + " outputs = [call(c) for c in cmdlist]\n", + " return" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [], + "source": [ + "def create_gradient_file(output,color):\n", + " '''\n", + " Arguments:\n", + " output Full path to output file\n", + " color String argument of Image-Magick 'color:color'\n", + " '''\n", + "\n", + " cmd = 'convert -size 10x20 gradient:{} {}'.format(color,output)\n", + " call(cmd)\n", + " return" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [], + "source": [ + "def call(cmd):\n", + " p = proc.Popen(cmd,shell=True,stdin=proc.PIPE, stderr=proc.PIPE)\n", + " std, err = p.communicate()\n", + "\n", + " if p.returncode:\n", + " print('{} failed with error {}'.format(cmd,err))\n", + " return" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "def get_sse(sub):\n", + " sse = '{}_dtifit_sse.nii.gz'.format(sub)\n", + " return os.path.join(dtifitdir,sub,sse)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "tigrlab_venv", + "language": "python", + "name": "tigrlab_venv" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/notebooks/slice_timing.ipynb b/notebooks/slice_timing.ipynb new file mode 100644 index 0000000..fdda1ad --- /dev/null +++ b/notebooks/slice_timing.ipynb @@ -0,0 +1,939 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 89, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import json\n", + "from glob import glob\n", + "\n", + "from collections import defaultdict\n", + "\n", + "import nibabel as nib" + ] + }, + { + "cell_type": "code", + "execution_count": 120, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "/archive/data/SPINS/data/nii/SPN01_CMH_0001_01/SPN01_CMH_0001_01_01_DTI60-1000_20_Ax-DTI-60plus5.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0002_01/SPN01_CMH_0002_01_02_DTI60-1000_05_Ax-DTI-60plus5.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0004_01/SPN01_CMH_0004_01_02_DTI60-1000_05_Ax-DTI-60plus5.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0005_01/SPN01_CMH_0005_01_01_DTI60-1000_22_Ax-DTI-60plus5.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0007_01/SPN01_CMH_0007_01_01_DTI60-1000_17_Ax-DTI-60plus5.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0008_01/SPN01_CMH_0008_01_01_DTI60-1000_19_Ax-DTI-60plus5.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0009_01/SPN01_CMH_0009_01_01_DTI60-1000_21_Ax-DTI-60plus5.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0011_01/SPN01_CMH_0011_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0012_01/SPN01_CMH_0012_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0013_01/SPN01_CMH_0013_01_01_DTI60-1000_18_Ax-DTI-60plus5.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0014_01/SPN01_CMH_0014_01_01_DTI60-1000_15_Ax-DTI-60plus5.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0015_01/SPN01_CMH_0015_01_01_DTI60-1000_15_Ax-DTI-60plus5.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0016_01/SPN01_CMH_0016_01_01_DTI60-1000_15_Ax-DTI-60plus5.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0017_01/SPN01_CMH_0017_01_01_DTI60-1000_16_Ax-DTI-60plus5.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0020_01/SPN01_CMH_0020_01_01_DTI60-1000_15_Ax-DTI-60plus5.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0021_01/SPN01_CMH_0021_01_01_DTI60-1000_15_Ax-DTI-60plus5.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0023_01/SPN01_CMH_0023_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0024_01/SPN01_CMH_0024_01_01_DTI60-1000_16_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0026_01/SPN01_CMH_0026_01_01_DTI60-1000_17_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0027_01/SPN01_CMH_0027_01_01_DTI60-1000_18_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0028_01/SPN01_CMH_0028_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0029_01/SPN01_CMH_0029_01_01_DTI60-1000_20_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0030_01/SPN01_CMH_0030_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0031_01/SPN01_CMH_0031_01_01_DTI60-1000_19_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0033_01/SPN01_CMH_0033_01_01_DTI60-1000_17_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0034_01/SPN01_CMH_0034_01_01_DTI60-1000_18_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0036_01/SPN01_CMH_0036_01_01_DTI60-1000_18_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0038_01/SPN01_CMH_0038_01_01_DTI60-1000_18_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0039_01/SPN01_CMH_0039_01_01_DTI60-1000_17_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0040_01/SPN01_CMH_0040_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0041_01/SPN01_CMH_0041_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0042_01/SPN01_CMH_0042_01_01_DTI60-1000_16_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0043_01/SPN01_CMH_0043_01_01_DTI60-1000_17_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0044_01/SPN01_CMH_0044_01_01_DTI60-1000_16_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0046_01/SPN01_CMH_0046_01_01_DTI60-1000_16_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0047_01/SPN01_CMH_0047_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0048_01/SPN01_CMH_0048_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0050_01/SPN01_CMH_0050_01_01_DTI60-1000_17_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0051_01/SPN01_CMH_0051_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0052_01/SPN01_CMH_0052_01_01_DTI60-1000_16_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0054_01/SPN01_CMH_0054_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0055_01/SPN01_CMH_0055_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0056_01/SPN01_CMH_0056_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0057_01/SPN01_CMH_0057_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0058_01/SPN01_CMH_0058_01_01_DTI60-1000_18_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0059_01/SPN01_CMH_0059_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0061_01/SPN01_CMH_0061_01_01_DTI60-1000_16_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0062_01/SPN01_CMH_0062_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0063_01/SPN01_CMH_0063_01_01_DTI60-1000_17_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0065_01/SPN01_CMH_0065_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0066_01/SPN01_CMH_0066_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0067_01/SPN01_CMH_0067_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0068_01/SPN01_CMH_0068_01_01_DTI60-1000_16_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0069_01/SPN01_CMH_0069_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0070_01/SPN01_CMH_0070_01_01_DTI60-1000_22_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0072_01/SPN01_CMH_0072_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0073_01/SPN01_CMH_0073_01_01_DTI60-1000_16_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0075_01/SPN01_CMH_0075_01_01_DTI60-1000_16_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0076_01/SPN01_CMH_0076_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0079_01/SPN01_CMH_0079_01_01_DTI60-1000_17_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0080_01/SPN01_CMH_0080_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0086_01/SPN01_CMH_0086_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0087_01/SPN01_CMH_0087_01_01_DTI60-1000_16_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0091_01/SPN01_CMH_0091_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0093_01/SPN01_CMH_0093_01_01_DTI60-1000_17_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0094_01/SPN01_CMH_0094_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0095_01/SPN01_CMH_0095_01_01_DTI60-1000_06_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0096_01/SPN01_CMH_0096_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0097_01/SPN01_CMH_0097_01_01_DTI60-1000_16_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0100_01/SPN01_CMH_0100_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0101_01/SPN01_CMH_0101_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0103_01/SPN01_CMH_0103_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0104_01/SPN01_CMH_0104_01_02_DTI60-1000_05_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0105_01/SPN01_CMH_0105_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0106_01/SPN01_CMH_0106_01_01_DTI60-1000_12_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0107_01/SPN01_CMH_0107_01_01_DTI60-1000_12_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0109_01/SPN01_CMH_0109_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0110_01/SPN01_CMH_0110_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0111_01/SPN01_CMH_0111_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0113_01/SPN01_CMH_0113_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0114_01/SPN01_CMH_0114_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0117_01/SPN01_CMH_0117_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0119_01/SPN01_CMH_0119_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0120_01/SPN01_CMH_0120_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0123_01/SPN01_CMH_0123_01_01_DTI60-1000_18_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0125_01/SPN01_CMH_0125_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0126_01/SPN01_CMH_0126_01_01_DTI60-1000_16_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0128_01/SPN01_CMH_0128_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0129_01/SPN01_CMH_0129_01_01_DTI60-1000_08_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0130_01/SPN01_CMH_0130_01_01_DTI60-1000_16_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0131_01/SPN01_CMH_0131_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0133_01/SPN01_CMH_0133_01_01_DTI60-1000_20_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0134_01/SPN01_CMH_0134_01_01_DTI60-1000_16_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0135_01/SPN01_CMH_0135_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0136_01/SPN01_CMH_0136_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0137_01/SPN01_CMH_0137_01_01_DTI60-1000_16_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0139_01/SPN01_CMH_0139_01_01_DTI60-1000_16_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0140_01/SPN01_CMH_0140_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0142_01/SPN01_CMH_0142_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0143_01/SPN01_CMH_0143_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0144_01/SPN01_CMH_0144_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0145_01/SPN01_CMH_0145_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0146_01/SPN01_CMH_0146_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0147_01/SPN01_CMH_0147_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0148_01/SPN01_CMH_0148_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0149_01/SPN01_CMH_0149_01_01_DTI60-1000_16_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0150_01/SPN01_CMH_0150_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0151_01/SPN01_CMH_0151_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0152_01/SPN01_CMH_0152_01_01_DTI60-1000_16_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0153_01/SPN01_CMH_0153_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0155_01/SPN01_CMH_0155_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0156_01/SPN01_CMH_0156_01_01_DTI60-1000_16_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0157_01/SPN01_CMH_0157_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0158_01/SPN01_CMH_0158_01_01_DTI60-1000_16_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0159_01/SPN01_CMH_0159_01_01_DTI60-1000_16_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0160_01/SPN01_CMH_0160_01_01_DTI60-1000_16_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0162_01/SPN01_CMH_0162_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0164_01/SPN01_CMH_0164_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0165_01/SPN01_CMH_0165_01_01_DTI60-1000_18_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0167_01/SPN01_CMH_0167_01_01_DTI60-1000_08_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0168_01/SPN01_CMH_0168_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0169_01/SPN01_CMH_0169_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0170_01/SPN01_CMH_0170_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0171_01/SPN01_CMH_0171_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0176_01/SPN01_CMH_0176_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0180_01/SPN01_CMH_0180_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0181_01/SPN01_CMH_0181_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0184_01/SPN01_CMH_0184_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0191_01/SPN01_CMH_0191_01_01_DTI60-1000_16_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0194_01/SPN01_CMH_0194_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0196_01/SPN01_CMH_0196_01_01_DTI60-1000_16_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0197_01/SPN01_CMH_0197_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0198_01/SPN01_CMH_0198_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0200_01/SPN01_CMH_0200_01_01_DTI60-1000_16_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_P001_01/SPN01_CMH_P001_01_01_DTI60-1000_17_Ax-DTI-60plus5.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_P001_02/SPN01_CMH_P001_02_01_DTI60-1000_08_Ax-DTI-60plus5-20iso.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "/archive/data/SPINS/data/nii/SPN01_CMH_P001_03/SPN01_CMH_P001_03_01_DTI60-1000_10_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_P002_01/SPN01_CMH_P002_01_01_DTI60-1000_16_Ax-DTI-60plus5.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_P002_02/SPN01_CMH_P002_02_01_DTI60-1000_08_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_P002_03/SPN01_CMH_P002_03_01_DTI60-1000_10_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_P003_01/SPN01_CMH_P003_01_01_DTI60-1000_16_Ax-DTI-60plus5.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_P003_02/SPN01_CMH_P003_02_01_DTI60-1000_08_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_P003_03/SPN01_CMH_P003_03_01_DTI60-1000_10_Ax-DTI-60plus5-20iso.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMP_0172_01/SPN01_CMP_0172_01_01_DTI60-1000_17_ep2d-diff-4scan-trace-p2-2mm.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMP_0175_01/SPN01_CMP_0175_01_01_DTI60-1000_17_ep2d-diff-4scan-trace-p2-2mm.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMP_0178_01/SPN01_CMP_0178_01_01_DTI60-1000_17_ep2d-diff-4scan-trace-p2-2mm.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMP_0179_01/SPN01_CMP_0179_01_01_DTI60-1000_18_ep2d-diff-4scan-trace-p2-2mm.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMP_0180_02/SPN01_CMP_0180_02_01_DTI60-1000_17_ep2d-diff-4scan-trace-p2-2mm.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMP_0182_02/SPN01_CMP_0182_02_01_DTI60-1000_17_ep2d-diff-4scan-trace-p2-2mm.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMP_0183_01/SPN01_CMP_0183_01_01_DTI60-1000_18_ep2d-diff-4scan-trace-p2-2mm.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMP_0185_01/SPN01_CMP_0185_01_01_DTI60-1000_18_ep2d-diff-4scan-trace-p2-2mm.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMP_0186_01/SPN01_CMP_0186_01_01_DTI60-1000_18_ep2d-diff-4scan-trace-p2-2mm.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMP_0187_01/SPN01_CMP_0187_01_01_DTI60-1000_19_ep2d-diff-4scan-trace-p2-2mm.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMP_0188_01/SPN01_CMP_0188_01_01_DTI60-1000_28_ep2d-diff-4scan-trace-p2-2mm.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMP_0190_01/SPN01_CMP_0190_01_01_DTI60-1000_20_ep2d-diff-4scan-trace-p2-2mm.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMP_0191_02/SPN01_CMP_0191_02_01_DTI60-1000_21_ep2d-diff-4scan-trace-p2-2mm.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMP_0192_01/SPN01_CMP_0192_01_01_DTI60-1000_18_ep2d-diff-4scan-trace-p2-2mm.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMP_0193_01/SPN01_CMP_0193_01_01_DTI60-1000_18_ep2d-diff-4scan-trace-p2-2mm.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMP_0196_02/SPN01_CMP_0196_02_01_DTI60-1000_18_ep2d-diff-4scan-trace-p2-2mm.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMP_0198_02/SPN01_CMP_0198_02_01_DTI60-1000_21_ep2d-diff-4scan-trace-p2-2mm.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMP_0199_01/SPN01_CMP_0199_01_01_DTI60-1000_18_ep2d-diff-4scan-trace-p2-2mm.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMP_0201_01/SPN01_CMP_0201_01_01_DTI60-1000_18_ep2d-diff-4scan-trace-p2-2mm.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMP_P001_04/SPN01_CMP_P001_04_02_DTI60-1000_07_ep2d-diff-4scan-trace-p2-2mm.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMP_P002_04/SPN01_CMP_P002_04_01_DTI60-1000_10_ep2d-diff-4scan-trace-p2-2mm.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMP_P003_04/SPN01_CMP_P003_04_01_DTI60-1000_10_ep2d-diff-4scan-trace-p2-2mm.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMP_P998_01/SPN01_CMP_P998_01_01_DTI60-1000_12_ep2d-diff-4scan-trace-p2-2mm.json\n", + "/archive/data/SPINS/data/nii/SPN01_CMP_P999_01/SPN01_CMP_P999_01_01_DTI60-1000_19_ep2d-diff-4scan-trace-p2-2mm.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0019_01/SPN01_MRP_0019_01_01_DTI60-1000_32_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0067_01/SPN01_MRP_0067_01_01_DTI60-1000_28_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0076_01/SPN01_MRP_0076_01_02_DTI60-1000_12_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0080_01/SPN01_MRP_0080_01_01_DTI60-1000_23_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0081_01/SPN01_MRP_0081_01_01_DTI60-1000_25_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0082_01/SPN01_MRP_0082_01_02_DTI60-1000_13_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0083_01/SPN01_MRP_0083_01_01_DTI60-1000_23_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0084_01/SPN01_MRP_0084_01_01_DTI60-1000_24_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0085_01/SPN01_MRP_0085_01_01_DTI60-1000_23_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0086_01/SPN01_MRP_0086_01_01_DTI60-1000_23_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0088_01/SPN01_MRP_0088_01_01_DTI60-1000_23_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0091_01/SPN01_MRP_0091_01_01_DTI60-1000_23_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0092_01/SPN01_MRP_0092_01_01_DTI60-1000_25_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0093_01/SPN01_MRP_0093_01_01_DTI60-1000_23_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0094_01/SPN01_MRP_0094_01_01_DTI60-1000_23_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0095_01/SPN01_MRP_0095_01_01_DTI60-1000_23_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0096_01/SPN01_MRP_0096_01_01_DTI60-1000_30_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0097_01/SPN01_MRP_0097_01_01_DTI60-1000_24_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0098_01/SPN01_MRP_0098_01_01_DTI60-1000_24_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0099_01/SPN01_MRP_0099_01_01_DTI60-1000_27_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0100_01/SPN01_MRP_0100_01_01_DTI60-1000_25_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0101_01/SPN01_MRP_0101_01_01_DTI60-1000_25_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0102_01/SPN01_MRP_0102_01_01_DTI60-1000_24_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0103_01/SPN01_MRP_0103_01_01_DTI60-1000_28_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0104_01/SPN01_MRP_0104_01_03_DTI60-1000_24_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0105_01/SPN01_MRP_0105_01_01_DTI60-1000_26_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0106_01/SPN01_MRP_0106_01_01_DTI60-1000_24_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0107_01/SPN01_MRP_0107_01_01_DTI60-1000_26_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0109_01/SPN01_MRP_0109_01_01_DTI60-1000_26_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0110_01/SPN01_MRP_0110_01_01_DTI60-1000_26_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0112_01/SPN01_MRP_0112_01_01_DTI60-1000_24_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0113_01/SPN01_MRP_0113_01_01_DTI60-1000_24_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0115_01/SPN01_MRP_0115_01_01_DTI60-1000_25_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0116_01/SPN01_MRP_0116_01_01_DTI60-1000_25_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0117_01/SPN01_MRP_0117_01_01_DTI60-1000_24_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0118_01/SPN01_MRP_0118_01_01_DTI60-1000_23_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0120_01/SPN01_MRP_0120_01_01_DTI60-1000_23_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0121_01/SPN01_MRP_0121_01_01_DTI60-1000_23_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0122_01/SPN01_MRP_0122_01_01_DTI60-1000_23_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0123_01/SPN01_MRP_0123_01_01_DTI60-1000_23_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0125_01/SPN01_MRP_0125_01_01_DTI60-1000_23_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0127_01/SPN01_MRP_0127_01_01_DTI60-1000_25_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0128_01/SPN01_MRP_0128_01_01_DTI60-1000_23_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0132_01/SPN01_MRP_0132_01_01_DTI60-1000_23_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0134_01/SPN01_MRP_0134_01_01_DTI60-1000_23_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0135_01/SPN01_MRP_0135_01_01_DTI60-1000_23_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0136_01/SPN01_MRP_0136_01_01_DTI60-1000_30_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0137_01/SPN01_MRP_0137_01_01_DTI60-1000_23_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0139_01/SPN01_MRP_0139_01_01_DTI60-1000_25_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_0140_01/SPN01_MRP_0140_01_01_DTI60-1000_24_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_P001_03/SPN01_MRP_P001_03_01_DTI60-1000_14_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_P003_03/SPN01_MRP_P003_03_02_DTI60-1000_14_DTI-60Dir-5B0.json\n", + "/archive/data/SPINS/data/nii/SPN01_MRP_P005_03/SPN01_MRP_P005_03_01_DTI60-1000_14_DTI-60Dir-5B0.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "/archive/data/SPINS/data/nii/SPN01_ZHH_0001_01/SPN01_ZHH_0001_01_01_DTI60-1000_16_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_0002_01/SPN01_ZHH_0002_01_01_DTI60-1000_20_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_0003_01/SPN01_ZHH_0003_01_01_DTI60-1000_20_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_0004_01/SPN01_ZHH_0004_01_01_DTI60-1000_23_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_0005_01/SPN01_ZHH_0005_01_01_DTI60-1000_16_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_0006_01/SPN01_ZHH_0006_01_01_DTI60-1000_17_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_0007_01/SPN01_ZHH_0007_01_01_DTI60-1000_15_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_0008_01/SPN01_ZHH_0008_01_01_DTI60-1000_17_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_0009_01/SPN01_ZHH_0009_01_01_DTI60-1000_15_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_0010_01/SPN01_ZHH_0010_01_01_DTI60-1000_19_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_0011_01/SPN01_ZHH_0011_01_01_DTI60-1000_16_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_0012_01/SPN01_ZHH_0012_01_01_DTI60-1000_16_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_0013_01/SPN01_ZHH_0013_01_01_DTI60-1000_16_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_0014_01/SPN01_ZHH_0014_01_01_DTI60-1000_21_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_0015_01/SPN01_ZHH_0015_01_01_DTI60-1000_17_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_0017_01/SPN01_ZHH_0017_01_01_DTI60-1000_16_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_0018_01/SPN01_ZHH_0018_01_01_DTI60-1000_15_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_0019_01/SPN01_ZHH_0019_01_01_DTI60-1000_20_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_0020_01/SPN01_ZHH_0020_01_01_DTI60-1000_18_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_0021_01/SPN01_ZHH_0021_01_01_DTI60-1000_16_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_0022_01/SPN01_ZHH_0022_01_01_DTI60-1000_23_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_0023_01/SPN01_ZHH_0023_01_01_DTI60-1000_21_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_0024_01/SPN01_ZHH_0024_01_01_DTI60-1000_17_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_0025_01/SPN01_ZHH_0025_01_01_DTI60-1000_15_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_0028_01/SPN01_ZHH_0028_01_01_DTI60-1000_18_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_0029_01/SPN01_ZHH_0029_01_01_DTI60-1000_17_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_0030_01/SPN01_ZHH_0030_01_01_DTI60-1000_21_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_0031_01/SPN01_ZHH_0031_01_01_DTI60-1000_13_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_0032_01/SPN01_ZHH_0032_01_01_DTI60-1000_25_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_0033_01/SPN01_ZHH_0033_01_01_DTI60-1000_15_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_0037_01/SPN01_ZHH_0037_01_01_DTI60-1000_20_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_0038_01/SPN01_ZHH_0038_01_01_DTI60-1000_18_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_0039_01/SPN01_ZHH_0039_01_01_DTI60-1000_22_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_0040_01/SPN01_ZHH_0040_01_01_DTI60-1000_16_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_0041_01/SPN01_ZHH_0041_01_01_DTI60-1000_18_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_0043_01/SPN01_ZHH_0043_01_01_DTI60-1000_16_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_0045_01/SPN01_ZHH_0045_01_01_DTI60-1000_16_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_0047_01/SPN01_ZHH_0047_01_01_DTI60-1000_17_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_0048_01/SPN01_ZHH_0048_01_01_DTI60-1000_14_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_0052_01/SPN01_ZHH_0052_01_01_DTI60-1000_21_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_0053_01/SPN01_ZHH_0053_01_01_DTI60-1000_17_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_0054_01/SPN01_ZHH_0054_01_01_DTI60-1000_17_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_0056_01/SPN01_ZHH_0056_01_01_DTI60-1000_16_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_0057_01/SPN01_ZHH_0057_01_01_DTI60-1000_14_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_0060_01/SPN01_ZHH_0060_01_01_DTI60-1000_18_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_9999_01/SPN01_ZHH_9999_01_01_DTI60-1000_19_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_P001_01/SPN01_ZHH_P001_01_01_DTI60-1000_15_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_P001_02/SPN01_ZHH_P001_02_01_DTI60-1000_11_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_P002_01/SPN01_ZHH_P002_01_01_DTI60-1000_15_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_P002_02/SPN01_ZHH_P002_02_01_DTI60-1000_14_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_P003_01/SPN01_ZHH_P003_01_01_DTI60-1000_16_DTI-B-1000-60+5.json\n", + "/archive/data/SPINS/data/nii/SPN01_ZHH_P003_02/SPN01_ZHH_P003_02_01_DTI60-1000_10_DTI-B-1000-60+5.json\n" + ] + } + ], + "source": [ + "dwi_jsons = sorted(glob('/archive/data/SPINS/data/nii/SPN01_*_0*/*DTI*json'))\n", + "\n", + "slice_timings = []\n", + "\n", + "for i in dwi_jsons:\n", + " with open(i, 'r') as f:\n", + " json_dict = json.load(f)\n", + " try:\n", + " timing = json_dict['SliceTiming']\n", + " if not timing in slice_timings:\n", + " slice_timings.append(timing)\n", + " except:\n", + " print(i)\n", + " continue" + ] + }, + { + "cell_type": "code", + "execution_count": 136, + "metadata": {}, + "outputs": [], + "source": [ + "dwi_jsons = sorted(glob('/archive/data/SPINS/data/nii/SPN01_*_0*/*DTI*json'))\n", + "\n", + "slice_orders = []\n", + "\n", + "for i in dwi_jsons:\n", + " with open(i, 'r') as f:\n", + " json_dict = json.load(f)\n", + " try:\n", + " timing = json_dict['SliceTiming']\n", + " slice_order = sorted(range(len(timing)),key=timing.__getitem__)\n", + " if not slice_order in slice_orders:\n", + " slice_orders.append(slice_order)\n", + " except:\n", + " continue" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "slice_order" + ] + }, + { + "cell_type": "code", + "execution_count": 138, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[[1,\n", + " 3,\n", + " 5,\n", + " 7,\n", + " 9,\n", + " 11,\n", + " 13,\n", + " 15,\n", + " 17,\n", + " 19,\n", + " 21,\n", + " 23,\n", + " 25,\n", + " 27,\n", + " 29,\n", + " 31,\n", + " 33,\n", + " 35,\n", + " 37,\n", + " 39,\n", + " 41,\n", + " 43,\n", + " 45,\n", + " 47,\n", + " 49,\n", + " 51,\n", + " 53,\n", + " 55,\n", + " 57,\n", + " 59,\n", + " 61,\n", + " 63,\n", + " 65,\n", + " 0,\n", + " 2,\n", + " 4,\n", + " 6,\n", + " 8,\n", + " 10,\n", + " 12,\n", + " 14,\n", + " 16,\n", + " 18,\n", + " 20,\n", + " 22,\n", + " 24,\n", + " 26,\n", + " 28,\n", + " 30,\n", + " 32,\n", + " 34,\n", + " 36,\n", + " 38,\n", + " 40,\n", + " 42,\n", + " 44,\n", + " 46,\n", + " 48,\n", + " 50,\n", + " 52,\n", + " 54,\n", + " 56,\n", + " 58,\n", + " 60,\n", + " 62,\n", + " 64],\n", + " [1,\n", + " 3,\n", + " 5,\n", + " 7,\n", + " 9,\n", + " 11,\n", + " 13,\n", + " 15,\n", + " 17,\n", + " 19,\n", + " 21,\n", + " 23,\n", + " 25,\n", + " 27,\n", + " 29,\n", + " 31,\n", + " 33,\n", + " 35,\n", + " 37,\n", + " 39,\n", + " 41,\n", + " 43,\n", + " 45,\n", + " 47,\n", + " 49,\n", + " 51,\n", + " 53,\n", + " 55,\n", + " 57,\n", + " 59,\n", + " 61,\n", + " 63,\n", + " 65,\n", + " 67,\n", + " 69,\n", + " 71,\n", + " 73,\n", + " 0,\n", + " 2,\n", + " 4,\n", + " 6,\n", + " 8,\n", + " 10,\n", + " 12,\n", + " 14,\n", + " 16,\n", + " 18,\n", + " 20,\n", + " 22,\n", + " 24,\n", + " 26,\n", + " 28,\n", + " 30,\n", + " 32,\n", + " 34,\n", + " 36,\n", + " 38,\n", + " 40,\n", + " 42,\n", + " 44,\n", + " 46,\n", + " 48,\n", + " 50,\n", + " 52,\n", + " 54,\n", + " 56,\n", + " 58,\n", + " 60,\n", + " 62,\n", + " 64,\n", + " 66,\n", + " 68,\n", + " 70,\n", + " 72]]" + ] + }, + "execution_count": 138, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "slice_orders" + ] + }, + { + "cell_type": "code", + "execution_count": 135, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[2,\n", + " 4,\n", + " 6,\n", + " 8,\n", + " 10,\n", + " 12,\n", + " 14,\n", + " 16,\n", + " 18,\n", + " 20,\n", + " 22,\n", + " 24,\n", + " 26,\n", + " 28,\n", + " 30,\n", + " 32,\n", + " 34,\n", + " 36,\n", + " 38,\n", + " 40,\n", + " 42,\n", + " 44,\n", + " 46,\n", + " 48,\n", + " 50,\n", + " 52,\n", + " 54,\n", + " 56,\n", + " 58,\n", + " 60,\n", + " 62,\n", + " 64,\n", + " 66,\n", + " 1,\n", + " 3,\n", + " 5,\n", + " 7,\n", + " 9,\n", + " 11,\n", + " 13,\n", + " 15,\n", + " 17,\n", + " 19,\n", + " 21,\n", + " 23,\n", + " 25,\n", + " 27,\n", + " 29,\n", + " 31,\n", + " 33,\n", + " 35,\n", + " 37,\n", + " 39,\n", + " 41,\n", + " 43,\n", + " 45,\n", + " 47,\n", + " 49,\n", + " 51,\n", + " 53,\n", + " 55,\n", + " 57,\n", + " 59,\n", + " 61,\n", + " 63,\n", + " 65]" + ] + }, + "execution_count": 135, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "slice_order" + ] + }, + { + "cell_type": "code", + "execution_count": 132, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[[2,\n", + " 4,\n", + " 6,\n", + " 8,\n", + " 10,\n", + " 12,\n", + " 14,\n", + " 16,\n", + " 18,\n", + " 20,\n", + " 22,\n", + " 24,\n", + " 26,\n", + " 28,\n", + " 30,\n", + " 32,\n", + " 34,\n", + " 36,\n", + " 38,\n", + " 40,\n", + " 42,\n", + " 44,\n", + " 46,\n", + " 48,\n", + " 50,\n", + " 52,\n", + " 54,\n", + " 56,\n", + " 58,\n", + " 60,\n", + " 62,\n", + " 64,\n", + " 66,\n", + " 1,\n", + " 3,\n", + " 5,\n", + " 7,\n", + " 9,\n", + " 11,\n", + " 13,\n", + " 15,\n", + " 17,\n", + " 19,\n", + " 21,\n", + " 23,\n", + " 25,\n", + " 27,\n", + " 29,\n", + " 31,\n", + " 33,\n", + " 35,\n", + " 37,\n", + " 39,\n", + " 41,\n", + " 43,\n", + " 45,\n", + " 47,\n", + " 49,\n", + " 51,\n", + " 53,\n", + " 55,\n", + " 57,\n", + " 59,\n", + " 61,\n", + " 63,\n", + " 65],\n", + " [2,\n", + " 4,\n", + " 6,\n", + " 8,\n", + " 10,\n", + " 12,\n", + " 14,\n", + " 16,\n", + " 18,\n", + " 20,\n", + " 22,\n", + " 24,\n", + " 26,\n", + " 28,\n", + " 30,\n", + " 32,\n", + " 34,\n", + " 36,\n", + " 38,\n", + " 40,\n", + " 42,\n", + " 44,\n", + " 46,\n", + " 48,\n", + " 50,\n", + " 52,\n", + " 54,\n", + " 56,\n", + " 58,\n", + " 60,\n", + " 62,\n", + " 64,\n", + " 66,\n", + " 68,\n", + " 70,\n", + " 72,\n", + " 74,\n", + " 1,\n", + " 3,\n", + " 5,\n", + " 7,\n", + " 9,\n", + " 11,\n", + " 13,\n", + " 15,\n", + " 17,\n", + " 19,\n", + " 21,\n", + " 23,\n", + " 25,\n", + " 27,\n", + " 29,\n", + " 31,\n", + " 33,\n", + " 35,\n", + " 37,\n", + " 39,\n", + " 41,\n", + " 43,\n", + " 45,\n", + " 47,\n", + " 49,\n", + " 51,\n", + " 53,\n", + " 55,\n", + " 57,\n", + " 59,\n", + " 61,\n", + " 63,\n", + " 65,\n", + " 67,\n", + " 69,\n", + " 71,\n", + " 73]]" + ] + }, + "execution_count": 132, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "slice_orders" + ] + }, + { + "cell_type": "code", + "execution_count": 142, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "/archive/data/SPINS/data/nii/SPN01_CMH_0001_01/SPN01_CMH_0001_01_01_DTI60-1000_20_Ax-DTI-60plus5.nii.gz\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0023_01/SPN01_CMH_0023_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.nii.gz\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0026_01/SPN01_CMH_0026_01_01_DTI60-1000_17_Ax-DTI-60plus5-20iso.nii.gz\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0134_01/SPN01_CMH_0134_01_01_DTI60-1000_16_Ax-DTI-60plus5-20iso.nii.gz\n", + "/archive/data/SPINS/data/nii/SPN01_CMH_0164_01/SPN01_CMH_0164_01_01_DTI60-1000_15_Ax-DTI-60plus5-20iso.nii.gz\n", + "/archive/data/SPINS/data/nii/SPN01_CMP_0191_02/SPN01_CMP_0191_02_01_DTI60-1000_21_ep2d-diff-4scan-trace-p2-2mm.nii.gz\n", + "/archive/data/SPINS/data/nii/SPN01_ZHP_P001_03/SPN01_ZHP_P001_03_01_DTI60-1000_11_DTI-60Dir-5B0.nii.gz\n", + "/archive/data/SPINS/data/nii/SPN01_ZHP_P002_03/SPN01_ZHP_P002_03_01_DTI60-1000_11_DTI-60Dir-5B0.nii.gz\n" + ] + } + ], + "source": [ + "dwi_niis = sorted(glob('/archive/data/SPINS/data/nii/SPN01_*_0*/*DTI*nii.gz'))\n", + "\n", + "unique_shapes = defaultdict(set)\n", + "\n", + "for i in dwi_niis:\n", + " site = i.split('/')[6].split('_')[1]\n", + " data = nib.load(i)\n", + " if not data.shape[2] == 66:\n", + " print(i)\n", + " unique_shapes[site].add(data.shape)" + ] + }, + { + "cell_type": "code", + "execution_count": 140, + "metadata": {}, + "outputs": [], + "source": [ + "dwi_niis = sorted(glob('/archive/data/SPINS/data/nii/SPN01_*_0*/*DTI*nii.gz'))\n", + "\n", + "for i in dwi_niis:\n", + " data = nib.load(i)\n", + " slice_num = data.shape[2]\n", + " slices = list(range(1, slice_num))\n", + " even_slices = [slice for slice in slices if slice % 2 == 0]\n", + " odd_slices = [slice for slice in slices if slice % 2 == 1]\n", + " slice_reorder = odd_slices + even_slices\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "slice_reorder" + ] + }, + { + "cell_type": "code", + "execution_count": 98, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "defaultdict(set,\n", + " {'CMH': {(128, 128, 66, 65), (128, 128, 71, 65)},\n", + " 'CMP': {(128, 128, 66, 66), (128, 128, 70, 66)},\n", + " 'MRC': {(128, 128, 66, 66)},\n", + " 'MRP': {(128, 128, 66, 66)},\n", + " 'ZHH': {(128, 128, 66, 65)},\n", + " 'ZHP': {(128, 128, 66, 61),\n", + " (128, 128, 66, 66),\n", + " (128, 128, 74, 66)}})" + ] + }, + "execution_count": 98, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "unique_shapes" + ] + }, + { + "cell_type": "code", + "execution_count": 102, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "/archive/data/SPINS/data/nii/SPN01_ZHP_P001_03/SPN01_ZHP_P001_03_01_DTI60-1000_11_DTI-60Dir-5B0.nii.gz\n", + "/archive/data/SPINS/data/nii/SPN01_ZHP_P002_03/SPN01_ZHP_P002_03_01_DTI60-1000_11_DTI-60Dir-5B0.nii.gz\n" + ] + } + ], + "source": [ + "dwi_niis = sorted(glob('/archive/data/SPINS/data/nii/SPN01_*_0*/*DTI*nii.gz'))\n", + "\n", + "for i in dwi_niis:\n", + " data = nib.load(i)\n", + " if data.shape[2] == 74:\n", + " print(i)" + ] + }, + { + "cell_type": "code", + "execution_count": 82, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[(128, 128, 71, 65),\n", + " (128, 128, 66, 65),\n", + " (128, 128, 66, 66),\n", + " (128, 128, 70, 66),\n", + " (128, 128, 66, 61),\n", + " (128, 128, 74, 66)]" + ] + }, + "execution_count": 82, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "unique_shapes" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "71, 65\n", + "66, 65\n", + "66, 66\n", + "70, 66\n", + "66, 61\n", + "74, 66" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "dwi_venv", + "language": "python", + "name": "dwi_venv" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.1" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/notebooks/test_wf.ipynb b/notebooks/test_wf.ipynb new file mode 100644 index 0000000..8aebdd4 --- /dev/null +++ b/notebooks/test_wf.ipynb @@ -0,0 +1,348 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from nipype.pipeline import engine as pe\n", + "from nipype.interfaces import utility as niu" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "dwi_file = '/projects/mjoseph/pipelines/testing/data/sub-0880002/ses-01/dwi/sub-0880002_ses-01_acq-singleshell19dir_dwi.nii.gz'" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": {}, + "outputs": [], + "source": [ + "def init_test_wf():\n", + " wf = pe.Workflow(name=\"test\")\n", + "\n", + " inputnode = pe.Node(niu.IdentityInterface(fields=[\"dwi_file\"]), name=\"inputnode\")\n", + "\n", + " outputnode = pe.Node(niu.IdentityInterface(fields=[\"out_file\"]), name=\"outputnode\")\n", + "\n", + " denoise = pe.Node(DWIDenoise(), name=\"denoise\")\n", + " \n", + " unring = pe.Node(MRDeGibbs(), name=\"unring\")\n", + "\n", + " wf.connect([(inputnode, denoise, [(\"dwi_file\", \"in_file\")]),\n", + " (denoise, unring, [(\"out_file\", \"in_file\")]),\n", + " (unring, outputnode, [(\"out_file\", \"out_file\")])])\n", + " \n", + " return wf" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "190627-17:38:59,948 nipype.workflow INFO:\n", + "\t Workflow test settings: ['check', 'execution', 'logging', 'monitoring']\n", + "190627-17:39:00,35 nipype.workflow INFO:\n", + "\t Running serially.\n", + "190627-17:39:00,37 nipype.workflow INFO:\n", + "\t [Node] Setting-up \"test.denoise\" in \"/tmp/tmpbinecjkb/test/denoise\".\n", + "190627-17:39:00,42 nipype.workflow INFO:\n", + "\t [Node] Running \"denoise\" (\"__main__.DWIDenoise\"), a CommandLine Interface with command:\n", + "dwidenoise -noise sub-0880002_ses-01_acq-singleshell19dir_dwi_noise.nii.gz /projects/mjoseph/pipelines/testing/data/sub-0880002/ses-01/dwi/sub-0880002_ses-01_acq-singleshell19dir_dwi.nii.gz sub-0880002_ses-01_acq-singleshell19dir_dwi_denoised.nii.gz\n", + "190627-17:39:00,529 nipype.interface INFO:\n", + "dwidenoise: [100%] uncompressing image \"/projects/mjoseph/pipelines/testing/data/sub-0880002/ses-01/dwi/sub-0880002_ses-01_acq-singleshell19dir_dwi.nii.gz\"\u001b[0K\u001b[0K\n", + "190627-17:39:00,823 nipype.interface INFO:\n", + "dwidenoise: [100%] preloading data for \"/projects/mjoseph/pipelines/testing/data/sub-0880002/ses-01/dwi/sub-0880002_ses-01_acq-singleshell19dir_dwi.nii.gz\"\u001b[0K\u001b[0K\n", + "190627-17:39:03,881 nipype.interface INFO:\n", + "dwidenoise: [100%] running MP-PCA denoising\u001b[0K\u001b[0K\n", + "190627-17:39:04,110 nipype.interface INFO:\n", + "dwidenoise: [100%] compressing image \"sub-0880002_ses-01_acq-singleshell19dir_dwi_noise.nii.gz\"\u001b[0K\u001b[0K\n", + "190627-17:39:08,812 nipype.interface INFO:\n", + "dwidenoise: [100%] compressing image \"sub-0880002_ses-01_acq-singleshell19dir_dwi_denoised.nii.gz\"\u001b[0K\u001b[0K\n", + "190627-17:39:08,932 nipype.workflow INFO:\n", + "\t [Node] Finished \"test.denoise\".\n", + "190627-17:39:08,933 nipype.workflow INFO:\n", + "\t [Node] Setting-up \"test.unring\" in \"/tmp/tmpi_3ouhxh/test/unring\".\n", + "190627-17:39:08,937 nipype.workflow INFO:\n", + "\t [Node] Running \"unring\" (\"__main__.MRDeGibbs\"), a CommandLine Interface with command:\n", + "mrdegibbs -axes 0,1 -maxW 3 -minW 1 -nshifts 20 /tmp/tmpbinecjkb/test/denoise/sub-0880002_ses-01_acq-singleshell19dir_dwi_denoised.nii.gz sub-0880002_ses-01_acq-singleshell19dir_dwi_denoised_unr.nii.gz\n", + "190627-17:39:09,795 nipype.interface INFO:\n", + "mrdegibbs: [100%] uncompressing image \"/tmp/tmpbinecjkb/test/denoise/sub-0880002_ses-01_acq-singleshell19dir_dwi_denoised.nii.gz\"\u001b[0K\u001b[0K\n", + "190627-17:39:16,918 nipype.interface INFO:\n", + "mrdegibbs: [100%] performing Gibbs ringing removal\u001b[0K\u001b[0K\n", + "190627-17:39:21,387 nipype.interface INFO:\n", + "mrdegibbs: [100%] compressing image \"sub-0880002_ses-01_acq-singleshell19dir_dwi_denoised_unr.nii.gz\"\u001b[0K\u001b[0K\n", + "190627-17:39:21,492 nipype.workflow INFO:\n", + "\t [Node] Finished \"test.unring\".\n" + ] + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 34, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "test_wf = init_test_wf()\n", + "inputspec = test_wf.get_node(\"inputnode\")\n", + "inputspec.inputs.dwi_file = dwi_file\n", + "test_wf.run()" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [], + "source": [ + "from __future__ import (print_function, division, unicode_literals,\n", + " absolute_import)\n", + "\n", + "import os\n", + "\n", + "from nipype.interfaces.base import (CommandLineInputSpec, CommandLine, traits, TraitedSpec,\n", + " File, isdefined, Undefined, InputMultiObject)\n", + "from nipype.interfaces.mrtrix3.base import MRTrix3BaseInputSpec, MRTrix3Base\n", + "\n", + "\n", + "class DWIDenoiseInputSpec(MRTrix3BaseInputSpec):\n", + " in_file = File(\n", + " exists=True,\n", + " argstr='%s',\n", + " position=-2,\n", + " mandatory=True,\n", + " desc='input DWI image')\n", + " mask = File(\n", + " exists=True,\n", + " argstr='-mask %s',\n", + " position=1,\n", + " desc='mask image')\n", + " extent = traits.Tuple((traits.Int, traits.Int, traits.Int),\n", + " argstr='-extent %d,%d,%d',\n", + " desc='set the window size of the denoising filter. (default = 5,5,5)')\n", + " noise = File(\n", + " argstr='-noise %s',\n", + " name_template='%s_noise',\n", + " name_source=['in_file'],\n", + " keep_extension=True,\n", + " desc='the output noise map')\n", + " out_file = File(\n", + " argstr='%s',\n", + " name_template='%s_denoised',\n", + " name_source=['in_file'],\n", + " keep_extension=True,\n", + " position=-1,\n", + " desc='the output denoised DWI image')\n", + "\n", + "class DWIDenoiseOutputSpec(TraitedSpec):\n", + " out_file = File(desc='the output denoised DWI image', exists=True)\n", + " noise = File(desc='the output noise map (if generated)', exists=True)\n", + "\n", + "class DWIDenoise(MRTrix3Base):\n", + " \"\"\"\n", + " Denoise DWI data and estimate the noise level based on the optimal\n", + " threshold for PCA.\n", + " DWI data denoising and noise map estimation by exploiting data redundancy\n", + " in the PCA domain using the prior knowledge that the eigenspectrum of\n", + " random covariance matrices is described by the universal Marchenko Pastur\n", + " distribution.\n", + " Important note: image denoising must be performed as the first step of the\n", + " image processing pipeline. The routine will fail if interpolation or\n", + " smoothing has been applied to the data prior to denoising.\n", + " Note that this function does not correct for non-Gaussian noise biases.\n", + " For more information, see\n", + " \n", + " Example\n", + " -------\n", + " >>> import nipype.interfaces.mrtrix3 as mrt\n", + " >>> denoise = mrt.DWIDenoise()\n", + " >>> denoise.inputs.in_file = 'dwi.mif'\n", + " >>> denoise.inputs.mask = 'mask.mif'\n", + " >>> denoise.cmdline # doctest: +ELLIPSIS\n", + " 'dwidenoise -mask mask.mif dwi.mif dwi_denoised.mif'\n", + " >>> denoise.run() # doctest: +SKIP\n", + " \"\"\"\n", + "\n", + " _cmd = 'dwidenoise'\n", + " input_spec = DWIDenoiseInputSpec\n", + " output_spec = DWIDenoiseOutputSpec" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [], + "source": [ + "class MRDeGibbsInputSpec(MRTrix3BaseInputSpec):\n", + " in_file = File(\n", + " exists=True,\n", + " argstr='%s',\n", + " position=-2,\n", + " mandatory=True,\n", + " desc='input DWI image')\n", + " axes = traits.ListInt(\n", + " default_value=[0,1],\n", + " usedefault=True,\n", + " sep=',',\n", + " minlen=2,\n", + " maxlen=2,\n", + " argstr='-axes %s',\n", + " desc='indicate the plane in which the data was acquired (axial = 0,1; '\n", + " 'coronal = 0,2; sagittal = 1,2')\n", + " nshifts = traits.Int(\n", + " default_value=20,\n", + " usedefault=True,\n", + " argstr='-nshifts %d',\n", + " desc='discretization of subpixel spacing (default = 20)')\n", + " minW = traits.Int(\n", + " default_value=1,\n", + " usedefault=True,\n", + " argstr='-minW %d',\n", + " desc='left border of window used for total variation (TV) computation '\n", + " '(default = 1)')\n", + " maxW = traits.Int(\n", + " default_value=3,\n", + " usedefault=True,\n", + " argstr='-maxW %d',\n", + " desc='right border of window used for total variation (TV) computation '\n", + " '(default = 3)')\n", + " out_file = File(name_template='%s_unr',\n", + " name_source='in_file',\n", + " keep_extension=True,\n", + " argstr='%s',\n", + " position=-1,\n", + " desc='the output unringed DWI image',\n", + " genfile=True)\n", + "\n", + "class MRDeGibbsOutputSpec(TraitedSpec):\n", + " out_file = File(desc='the output unringed DWI image', exists=True)\n", + "\n", + "class MRDeGibbs(MRTrix3Base):\n", + " \"\"\"\n", + " Remove Gibbs ringing artifacts.\n", + " This application attempts to remove Gibbs ringing artefacts from MRI images\n", + " using the method of local subvoxel-shifts proposed by Kellner et al.\n", + " This command is designed to run on data directly after it has been\n", + " reconstructed by the scanner, before any interpolation of any kind has\n", + " taken place. You should not run this command after any form of motion\n", + " correction (e.g. not after dwipreproc). Similarly, if you intend running\n", + " dwidenoise, you should run this command afterwards, since it has the\n", + " potential to alter the noise structure, which would impact on dwidenoise's\n", + " performance.\n", + " Note that this method is designed to work on images acquired with full\n", + " k-space coverage. Running this method on partial Fourier ('half-scan') data\n", + " may lead to suboptimal and/or biased results, as noted in the original\n", + " reference below. There is currently no means of dealing with this; users\n", + " should exercise caution when using this method on partial Fourier data, and\n", + " inspect its output for any obvious artefacts.\n", + " For more information, see\n", + " \n", + " Example\n", + " -------\n", + " >>> import nipype.interfaces.mrtrix3 as mrt\n", + " >>> unring = mrt.MRDeGibbs()\n", + " >>> unring.inputs.in_file = 'dwi.mif'\n", + " >>> unring.cmdline\n", + " 'mrdegibbs -axes 0,1 -maxW 3 -minW 1 -nshifts 20 dwi.mif dwi_unr.mif'\n", + " >>> unring.run() # doctest: +SKIP\n", + " \"\"\"\n", + "\n", + " _cmd = 'mrdegibbs'\n", + " input_spec = MRDeGibbsInputSpec\n", + " output_spec = MRDeGibbsOutputSpec" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + " def _gen_outfilename(self):\n", + " out_file = self.inputs.out_file\n", + " if not isdefined(out_file) and isdefined(self.inputs.in_file):\n", + " out_file = self._gen_fname(self.inputs.in_file, suffix='_denoised')\n", + " return os.path.abspath(out_file)\n", + " \n", + " def _gen_fname(self,\n", + " basename,\n", + " cwd=None,\n", + " suffix=None,\n", + " change_ext=True,\n", + " ext=None):\n", + "\n", + " if basename == '':\n", + " msg = 'Unable to generate filename for command %s. ' % self.cmd\n", + " msg += 'basename is not set!'\n", + " raise ValueError(msg)\n", + " if cwd is None:\n", + " cwd = os.getcwd()\n", + " if ext is None:\n", + " ext = Info.output_type_to_ext(self.inputs.output_type)\n", + " if change_ext:\n", + " if suffix:\n", + " suffix = ''.join((suffix, ext))\n", + " else:\n", + " suffix = ext\n", + " if suffix is None:\n", + " suffix = ''\n", + " fname = fname_presuffix(\n", + " basename, suffix=suffix, use_ext=False, newpath=cwd)\n", + " return fname\n", + "\n", + " def _list_outputs(self):\n", + " outputs = self.output_spec().get()\n", + " outputs['out_file'] = self._gen_outfilename()\n", + " if (isdefined(self.inputs.noise) and self.inputs.noise):\n", + " outputs['noise_file'] = self._gen_fname(outputs['out_file'], suffix='_noise')\n", + " return outputs" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "dwi_venv", + "language": "python", + "name": "dwi_venv" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.1" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 2b34b0af3e9f52156775a39ff09b77c7ae19fd69 Mon Sep 17 00:00:00 2001 From: mjoseph Date: Tue, 16 Jul 2019 11:22:05 -0400 Subject: [PATCH 12/18] add wip topup wf --- dmripreproc/workflows/fieldmap/pepolar.py | 79 +++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 dmripreproc/workflows/fieldmap/pepolar.py diff --git a/dmripreproc/workflows/fieldmap/pepolar.py b/dmripreproc/workflows/fieldmap/pepolar.py new file mode 100644 index 0000000..34ca318 --- /dev/null +++ b/dmripreproc/workflows/fieldmap/pepolar.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python + +from nipype.pipeline import engine as pe +from nipype.interfaces import fsl, utility as niu + + +def init_pepolar_wf(subject_id, dwi_meta, epi_fmaps): + + dwi_file_pe = dwi_meta["PhaseEncodingDirection"] + + usable_fieldmaps_matching_pe = [] + usable_fieldmaps_opposite_pe = [] + + for fmap, pe_dir in epi_fmaps: + if pe_dir == dwi_file_pe: + usable_fieldmaps_matching_pe.append(fmap) + elif pe_dir[0] == dwi_file_pe[0]: + usable_fieldmaps_opposite_pe.append(fmap) + + if not usable_fieldmaps_opposite_pe: + raise Exception("None of the discovered fieldmaps for " + "participant {} has the right phase " + "encoding direction".format(subject_id)) + + wf = pe.Workflow(name="pepolar_wf") + + inputnode = pe.Node(niu.IdentityInterface(fields=["b0_stripped"])) + + outputnode = pe.Node(niu.IdentityInterface(fields=["out_topup"])) + + topup_wf = init_topup_wf() + topup_wf.inputnode.altepi_file = usable_fieldmaps_opposite_pe[0] + + if not usable_fieldmaps_matching_pe: + wf.connect( + [ + (inputnode, topup_wf, [("b0_stripped", "inputnode.epi_file")]) + ] + ) + else: + topup_wf.inputnode.epi_file = usable_fieldmaps_matching_pe[0] + + return wf + + +def init_topup_wf(): + + wf = pe.Workflow(name="topup_wf") + + inputnode = pe.Node( + niu.IdentityInterface(fields=["epi_file", "altepi_file", "encoding_directions"]), + name="inputnode") + + outputnode = pe.Node( + niu.IdentityInterface(fields=["out_fmap"]), + name="outputnode") + + list_merge = pe.Node(niu.Merge(numinputs=2), name="list_merge") + + merge = pe.Node(fsl.Merge(dimension="t"), name="mergeAPPA") + + topup = pe.Node(fsl.TOPUP(), name="topup") + topup.inputs.readout_times = [0.05, 0.05] + + wf.connect( + [ + ( + inputnode, + list_merge, + [("epi_file", "in1"), ("altepi_file", "in2")] + ), + (list_merge, merge, [("out", "in_files")]), + (merge, topup, [("merged_file", "in_file")]), + (inputnode, topup, [("encoding_directions", "encoding_direction")]), + (topup, outputnode, [("out_field", "out_fmap")]), + ] + ) + + return wf From e824ebc883cb7f9e6242ade7457d8239e11cafec Mon Sep 17 00:00:00 2001 From: mjoseph Date: Tue, 16 Jul 2019 16:46:16 -0400 Subject: [PATCH 13/18] add pe direction to topup workflow --- dmriprep/workflows/dwi/dwiprep.py | 82 -------------------------- dmripreproc/workflows/dwi/base.py | 2 +- dmripreproc/workflows/fieldmap/base.py | 20 ++++++- 3 files changed, 19 insertions(+), 85 deletions(-) delete mode 100644 dmriprep/workflows/dwi/dwiprep.py diff --git a/dmriprep/workflows/dwi/dwiprep.py b/dmriprep/workflows/dwi/dwiprep.py deleted file mode 100644 index 8334cbe..0000000 --- a/dmriprep/workflows/dwi/dwiprep.py +++ /dev/null @@ -1,82 +0,0 @@ -#!/usr/bin/env python - -def init_dwiprep_wf(ignore_nodes): - from ...interfaces import mrtrix3 - from nipype.pipeline import engine as pe - from nipype.interfaces import fsl, utility as niu - - # Generate the prep workflow for dwi (denoise, unring, resize) - - dwi_prep_wf = pe.Workflow(name="dwi_prep_wf") - - denoise = pe.Node(mrtrix3.DWIDenoise(), name="denoise") - - unring = pe.Node(mrtrix3.MRDeGibbs(), name="unring") - - resize = pe.Node(mrtrix3.MRResize(voxel_size=[1]), name="resize") - - dwi_prep_inputnode = pe.Node( - niu.IdentityInterface( - fields=["dwi_file"] - ), - name="dwi_prep_inputnode", - ) - - dwi_prep_outputnode = pe.Node( - niu.IdentityInterface(fields=["out_file"]), - name="dwi_prep_outputnode", - ) - - # Turn the string input of nodes into a list - ignore_nodes_list = [option.lower() for option in ignore_nodes.strip()] - - prep_full = ['d', 'u', 'r'] - prep_wanted_str = [node for node in prep_full if not(node in ignore_nodes_list)] - - # Translate string input to node names - str2node = { - 'd': denoise, - 'u': unring, - 'r': resize - } - - # Convert the string list to a node list - prep_wanted = [str2node[str_node] for str_node in prep_wanted_str] - - # If no steps selected, just connect input to output - if not(prep_wanted): - dwi_prep_wf.connect( - [ - (dwi_prep_inputnode, dwi_prep_outputnode, [("dwi_file", "out_file")]) - ] - ) - - # If there are steps - else: - # Must at least connect input node to first node - first_node = prep_wanted[0] - dwi_prep_wf.connect( - [ - (dwi_prep_inputnode, first_node, [("dwi_file", "in_file")]), - ] - ) - # Loop through the prep order - # Note: only works if each node has in_file and out_file - # Can work around this by wrapping in node/workflow with in_file+out_file - prev = first_node - for curr_node in prep_wanted[1:]: - dwi_prep_wf.connect( - [ - (prev, curr_node, [("out_file", "in_file")]), - ] - ) - prev = curr_node - # Connect last node to output node - last_node = prep_wanted[-1] - dwi_prep_wf.connect( - [ - (last_node, dwi_prep_outputnode, [("out_file", "out_file")]), - ] - ) - - return dwi_prep_wf diff --git a/dmripreproc/workflows/dwi/base.py b/dmripreproc/workflows/dwi/base.py index 8a1ae2e..fdce43d 100755 --- a/dmripreproc/workflows/dwi/base.py +++ b/dmripreproc/workflows/dwi/base.py @@ -32,7 +32,7 @@ def init_dwi_preproc_wf(subject_id, dwi_file, metadata, parameters): fmap["metadata"] = parameters.layout.get_metadata(fmap[fmap["suffix"]]) sdc_wf = init_sdc_prep_wf( - fmaps, metadata, parameters.layout, parameters.bet_mag + subject_id, fmaps, metadata, parameters.layout, parameters.bet_mag ) dwi_wf = pe.Workflow(name="dwi_preproc_wf") diff --git a/dmripreproc/workflows/fieldmap/base.py b/dmripreproc/workflows/fieldmap/base.py index c84fe67..d8a1325 100644 --- a/dmripreproc/workflows/fieldmap/base.py +++ b/dmripreproc/workflows/fieldmap/base.py @@ -7,7 +7,13 @@ def init_sdc_prep_wf( - fmaps, metadata, layout, bet_mag_frac, omp_nthreads=1, fmap_bspline=False + subject_id, + fmaps, + metadata, + layout, + bet_mag_frac, + omp_nthreads=1, + fmap_bspline=False, ): sdc_prep_wf = pe.Workflow(name="sdc_prep_wf") @@ -37,7 +43,17 @@ def init_sdc_prep_wf( if fmap["suffix"] == "epi": from .pepolar import init_pepolar_wf - pepolar_wf = init_pepolar_wf() + epi_fmaps = [ + (fmap_["epi"], fmap_["metadata"]["PhaseEncodingDirection"]) + for fmap_ in fmaps + if fmap_["suffix"] == "epi" + ] + + pepolar_wf = init_pepolar_wf(subject_id, metadata, epi_fmaps) + + sdc_prep_wf.connect( + [(pepolar_wf, outputnode, [("outputnode.out_fmap", "out_fmap")])] + ) if fmap["suffix"] == "fieldmap": from .fmap import init_fmap_wf From 299b7a15162ad1c4bb602f2af9b06f0836d104a6 Mon Sep 17 00:00:00 2001 From: Salim Mansour Date: Fri, 19 Jul 2019 10:29:56 -0400 Subject: [PATCH 14/18] Added support for topup --- dmripreproc/cli.py | 15 +- dmripreproc/interfaces/fsl.py | 505 ++++++++++++++++++++++ dmripreproc/workflows/base.py | 12 +- dmripreproc/workflows/dwi/base.py | 38 +- dmripreproc/workflows/dwi/outputs.py | 1 + dmripreproc/workflows/fieldmap/base.py | 21 +- dmripreproc/workflows/fieldmap/pepolar.py | 59 ++- setup.py | 4 +- 8 files changed, 625 insertions(+), 30 deletions(-) create mode 100644 dmripreproc/interfaces/fsl.py diff --git a/dmripreproc/cli.py b/dmripreproc/cli.py index a0a09d2..8a3675a 100644 --- a/dmripreproc/cli.py +++ b/dmripreproc/cli.py @@ -9,7 +9,7 @@ import click from . import utils -from .workflows.base import init_dmriprepoc_wf +from .workflows.base import init_dmripreproc_wf # Filter warnings that are visible whenever you import another package that # was compiled against an older numpy than is installed. @@ -28,12 +28,11 @@ "can be specified with a space separated list.", default=None, ) -@click.command() -@click.option( - "--ignore", - help="Ignore selected parts of the workflow.", - type=click.Choice(["denoise", "unring"]), -) +#@click.option( +# "--ignore", +# help="Ignore selected parts of the workflow.", +# type=click.Choice(["denoise", "unring"]), +#) @click.option( "--resize-scale", help="Scale factor to resize DWI image", type=(float) ) @@ -142,7 +141,7 @@ def main( parameters.ignore_nodes = ignore_nodes parameters.analysis_level = analysis_level - wf = init_dmriprep_wf(parameters) + wf = init_dmripreproc_wf(parameters) wf.write_graph(graph2use="colored") wf.config["execution"]["remove_unnecessary_outputs"] = False wf.config["execution"]["keep_inputs"] = True diff --git a/dmripreproc/interfaces/fsl.py b/dmripreproc/interfaces/fsl.py new file mode 100644 index 0000000..9696213 --- /dev/null +++ b/dmripreproc/interfaces/fsl.py @@ -0,0 +1,505 @@ +#!/usr/bin/env python + +from __future__ import ( + print_function, + division, + unicode_literals, + absolute_import, +) + +from builtins import str + +import os +import numpy as np +import nibabel as nb +import warnings + +from nipype.interfaces.base import traits, TraitedSpec, InputMultiPath, File, isdefined +from nipype.interfaces.fsl.base import FSLCommand, FSLCommandInputSpec, Info + +class EddyInputSpec(FSLCommandInputSpec): + in_file = File( + exists=True, + mandatory=True, + argstr='--imain=%s', + desc=('File containing all the images to estimate ' + 'distortions for')) + in_mask = File( + exists=True, + mandatory=True, + argstr='--mask=%s', + desc='Mask to indicate brain') + in_index = File( + exists=True, + mandatory=True, + argstr='--index=%s', + desc=('File containing indices for all volumes in --imain ' + 'into --acqp and --topup')) + in_acqp = File( + exists=True, + mandatory=True, + argstr='--acqp=%s', + desc='File containing acquisition parameters') + in_bvec = File( + exists=True, + mandatory=True, + argstr='--bvecs=%s', + desc=('File containing the b-vectors for all volumes in ' + '--imain')) + in_bval = File( + exists=True, + mandatory=True, + argstr='--bvals=%s', + desc=('File containing the b-values for all volumes in ' + '--imain')) + out_base = traits.Str( + 'eddy_corrected', + argstr='--out=%s', + usedefault=True, + desc=('basename for output (warped) image')) + session = File( + exists=True, + argstr='--session=%s', + desc=('File containing session indices for all volumes in ' + '--imain')) + in_topup_fieldcoef = File( + #exists=True, + argstr="--topup=%s", + requires=['in_topup_movpar'], + desc=('topup file containing the field ' + 'coefficients')) + in_topup_movpar = File( + exists=True, + requires=['in_topup_fieldcoef'], + desc='topup movpar.txt file') + + flm = traits.Enum( + 'linear', + 'quadratic', + 'cubic', + argstr='--flm=%s', + desc='First level EC model') + + slm = traits.Enum( + 'none', + 'linear', + 'quadratic', + argstr='--slm=%s', + desc='Second level EC model') + + fep = traits.Bool( + False, argstr='--fep', desc='Fill empty planes in x- or y-directions') + + interp = traits.Enum( + 'spline', + 'trilinear', + argstr='--interp=%s', + desc='Interpolation model for estimation step') + + nvoxhp = traits.Int( + 1000, usedefault=True, + argstr='--nvoxhp=%s', + desc=('# of voxels used to estimate the ' + 'hyperparameters')) + + fudge_factor = traits.Float( + 10.0, usedefault=True, + argstr='--ff=%s', + desc=('Fudge factor for hyperparameter ' + 'error variance')) + + dont_sep_offs_move = traits.Bool( + False, + argstr='--dont_sep_offs_move', + desc=('Do NOT attempt to separate ' + 'field offset from subject ' + 'movement')) + + dont_peas = traits.Bool( + False, + argstr='--dont_peas', + desc="Do NOT perform a post-eddy alignment of " + "shells") + + fwhm = traits.Float( + desc=('FWHM for conditioning filter when estimating ' + 'the parameters'), + argstr='--fwhm=%s') + + niter = traits.Int(5, usedefault=True, + argstr='--niter=%s', desc='Number of iterations') + + method = traits.Enum( + 'jac', + 'lsr', + argstr='--resamp=%s', + desc=('Final resampling method (jacobian/least ' + 'squares)')) + repol = traits.Bool( + False, argstr='--repol', desc='Detect and replace outlier slices') + num_threads = traits.Int( + 1, + usedefault=True, + nohash=True, + desc="Number of openmp threads to use") + is_shelled = traits.Bool( + False, + argstr='--data_is_shelled', + desc="Override internal check to ensure that " + "date are acquired on a set of b-value " + "shells") + field = traits.Str( + argstr='--field=%s', + desc="NonTOPUP fieldmap scaled in Hz - filename has " + "to be provided without an extension. TOPUP is " + "strongly recommended") + field_mat = File( + exists=True, + argstr='--field_mat=%s', + desc="Matrix that specifies the relative locations of " + "the field specified by --field and first volume " + "in file --imain") + use_cuda = traits.Bool(False, desc="Run eddy using cuda gpu") + cnr_maps = traits.Bool( + False, desc='Output CNR-Maps', argstr='--cnr_maps', min_ver='5.0.10') + residuals = traits.Bool( + False, desc='Output Residuals', argstr='--residuals', min_ver='5.0.10') + + +class EddyOutputSpec(TraitedSpec): + out_corrected = File( + exists=True, desc='4D image file containing all the corrected volumes') + out_parameter = File( + exists=True, + desc=('text file with parameters definining the field and' + 'movement for each scan')) + out_rotated_bvecs = File( + exists=True, desc='File containing rotated b-values for all volumes') + out_movement_rms = File( + exists=True, desc='Summary of the "total movement" in each volume') + out_restricted_movement_rms = File( + exists=True, + desc=('Summary of the "total movement" in each volume ' + 'disregarding translation in the PE direction')) + out_shell_alignment_parameters = File( + exists=True, + desc=('File containing rigid body movement parameters ' + 'between the different shells as estimated by a ' + 'post-hoc mutual information based registration')) + out_outlier_report = File( + exists=True, + desc=('Text-file with a plain language report on what ' + 'outlier slices eddy has found')) + out_cnr_maps = File( + exists=True, desc='path/name of file with the cnr_maps') + out_residuals = File( + exists=True, desc='path/name of file with the residuals') + + +class Eddy(FSLCommand): + """ + Interface for FSL eddy, a tool for estimating and correcting eddy + currents induced distortions. `User guide + `_ and + `more info regarding acqp file + `_. + Examples + -------- + >>> from nipype.interfaces.fsl import Eddy + >>> eddy = Eddy() + >>> eddy.inputs.in_file = 'epi.nii' + >>> eddy.inputs.in_mask = 'epi_mask.nii' + >>> eddy.inputs.in_index = 'epi_index.txt' + >>> eddy.inputs.in_acqp = 'epi_acqp.txt' + >>> eddy.inputs.in_bvec = 'bvecs.scheme' + >>> eddy.inputs.in_bval = 'bvals.scheme' + >>> eddy.inputs.use_cuda = True + >>> eddy.cmdline # doctest: +ELLIPSIS + 'eddy_cuda --ff=10.0 --acqp=epi_acqp.txt --bvals=bvals.scheme \ +--bvecs=bvecs.scheme --imain=epi.nii --index=epi_index.txt \ +--mask=epi_mask.nii --niter=5 --nvoxhp=1000 --out=.../eddy_corrected' + >>> eddy.inputs.use_cuda = False + >>> eddy.cmdline # doctest: +ELLIPSIS + 'eddy_openmp --ff=10.0 --acqp=epi_acqp.txt --bvals=bvals.scheme \ +--bvecs=bvecs.scheme --imain=epi.nii --index=epi_index.txt \ +--mask=epi_mask.nii --niter=5 --nvoxhp=1000 --out=.../eddy_corrected' + >>> res = eddy.run() # doctest: +SKIP + """ + _cmd = 'eddy_openmp' + input_spec = EddyInputSpec + output_spec = EddyOutputSpec + + _num_threads = 1 + + def __init__(self, **inputs): + super(Eddy, self).__init__(**inputs) + self.inputs.on_trait_change(self._num_threads_update, 'num_threads') + if not isdefined(self.inputs.num_threads): + self.inputs.num_threads = self._num_threads + else: + self._num_threads_update() + self.inputs.on_trait_change(self._use_cuda, 'use_cuda') + if isdefined(self.inputs.use_cuda): + self._use_cuda() + + def _num_threads_update(self): + self._num_threads = self.inputs.num_threads + if not isdefined(self.inputs.num_threads): + if 'OMP_NUM_THREADS' in self.inputs.environ: + del self.inputs.environ['OMP_NUM_THREADS'] + else: + self.inputs.environ['OMP_NUM_THREADS'] = str( + self.inputs.num_threads) + + def _use_cuda(self): + self._cmd = 'eddy_cuda' if self.inputs.use_cuda else 'eddy_openmp' + + def _run_interface(self, runtime): + # If 'eddy_openmp' is missing, use 'eddy' + FSLDIR = os.getenv('FSLDIR', '') + cmd = self._cmd + if all((FSLDIR != '', cmd == 'eddy_openmp', + not os.path.exists(os.path.join(FSLDIR, 'bin', cmd)))): + self._cmd = 'eddy' + runtime = super(Eddy, self)._run_interface(runtime) + + # Restore command to avoid side-effects + self._cmd = cmd + return runtime + + def _format_arg(self, name, spec, value): + if name == 'in_topup_fieldcoef': + return spec.argstr % value.split('_fieldcoef')[0] + if name == 'out_base': + return spec.argstr % os.path.abspath(value) + return super(Eddy, self)._format_arg(name, spec, value) + + def _list_outputs(self): + outputs = self.output_spec().get() + outputs['out_corrected'] = os.path.abspath( + '%s.nii.gz' % self.inputs.out_base) + outputs['out_parameter'] = os.path.abspath( + '%s.eddy_parameters' % self.inputs.out_base) + + # File generation might depend on the version of EDDY + out_rotated_bvecs = os.path.abspath( + '%s.eddy_rotated_bvecs' % self.inputs.out_base) + out_movement_rms = os.path.abspath( + '%s.eddy_movement_rms' % self.inputs.out_base) + out_restricted_movement_rms = os.path.abspath( + '%s.eddy_restricted_movement_rms' % self.inputs.out_base) + out_shell_alignment_parameters = os.path.abspath( + '%s.eddy_post_eddy_shell_alignment_parameters' % + self.inputs.out_base) + out_outlier_report = os.path.abspath( + '%s.eddy_outlier_report' % self.inputs.out_base) + if isdefined(self.inputs.cnr_maps) and self.inputs.cnr_maps: + out_cnr_maps = os.path.abspath( + '%s.eddy_cnr_maps.nii.gz' % self.inputs.out_base) + if os.path.exists(out_cnr_maps): + outputs['out_cnr_maps'] = out_cnr_maps + if isdefined(self.inputs.residuals) and self.inputs.residuals: + out_residuals = os.path.abspath( + '%s.eddy_residuals.nii.gz' % self.inputs.out_base) + if os.path.exists(out_residuals): + outputs['out_residuals'] = out_residuals + + if os.path.exists(out_rotated_bvecs): + outputs['out_rotated_bvecs'] = out_rotated_bvecs + if os.path.exists(out_movement_rms): + outputs['out_movement_rms'] = out_movement_rms + if os.path.exists(out_restricted_movement_rms): + outputs['out_restricted_movement_rms'] = \ + out_restricted_movement_rms + if os.path.exists(out_shell_alignment_parameters): + outputs['out_shell_alignment_parameters'] = \ + out_shell_alignment_parameters + if os.path.exists(out_outlier_report): + outputs['out_outlier_report'] = out_outlier_report + + return outputs + +class EddyQuadInputSpec(FSLCommandInputSpec): + base_name = traits.Str( + 'eddy_corrected', + usedefault=True, + argstr='%s', + desc=("Basename (including path) for EDDY output files, i.e., " + "corrected images and QC files"), + position=0, + ) + idx_file = File( + exists=True, + mandatory=True, + argstr="--eddyIdx %s", + desc=("File containing indices for all volumes into acquisition " + "parameters") + ) + param_file = File( + exists=True, + mandatory=True, + argstr="--eddyParams %s", + desc="File containing acquisition parameters" + ) + mask_file = File( + exists=True, + mandatory=True, + argstr="--mask %s", + desc="Binary mask file" + ) + bval_file = File( + exists=True, + mandatory=True, + argstr="--bvals %s", + desc="b-values file" + ) + bvec_file = File( + exists=True, + argstr="--bvecs %s", + desc=("b-vectors file - only used when .eddy_residuals " + "file is present") + ) + output_dir = traits.Str( + name_template='%s.qc', + name_source=['base_name'], + argstr='--output-dir %s', + desc="Output directory - default = '.qc'", + ) + field = File( + exists=True, + argstr='--field %s', + desc="TOPUP estimated field (in Hz)", + ) + slice_spec = File( + exists=True, + argstr='--slspec %s', + desc="Text file specifying slice/group acquisition", + ) + verbose = traits.Bool( + argstr='--verbose', + desc="Display debug messages", + ) + + +class EddyQuadOutputSpec(TraitedSpec): + qc_json = File( + exists=True, + desc=("Single subject database containing quality metrics and data " + "info.") + ) + qc_pdf = File( + exists=True, + desc="Single subject QC report." + ) + avg_b_png = traits.List( + File(exists=True), + desc=("Image showing mid-sagittal, -coronal and -axial slices of " + "each averaged b-shell volume.") + ) + avg_b0_pe_png = traits.List( + File(exists=True), + desc=("Image showing mid-sagittal, -coronal and -axial slices of " + "each averaged pe-direction b0 volume. Generated when using " + "the -f option.") + ) + cnr_png = traits.List( + File(exists=True), + desc=("Image showing mid-sagittal, -coronal and -axial slices of " + "each b-shell CNR volume. Generated when CNR maps are " + "available.") + ) + vdm_png = File( + exists=True, + desc=("Image showing mid-sagittal, -coronal and -axial slices of " + "the voxel displacement map. Generated when using the -f " + "option.") + ) + residuals = File( + exists=True, + desc=("Text file containing the volume-wise mask-averaged squared " + "residuals. Generated when residual maps are available.") + ) + clean_volumes = File( + exists=True, + desc=("Text file containing a list of clean volumes, based on " + "the eddy squared residuals. To generate a version of the " + "pre-processed dataset without outlier volumes, use: " + "`fslselectvols -i -o " + "eddy_corrected_data_clean --vols=vols_no_outliers.txt`") + ) + + +class EddyQuad(FSLCommand): + """ + Interface for FSL eddy_quad, a tool for generating single subject reports + and storing the quality assessment indices for each subject. + `User guide `_ + Examples + -------- + >>> from nipype.interfaces.fsl import EddyQuad + >>> quad = EddyQuad() + >>> quad.inputs.base_name = 'eddy_corrected' + >>> quad.inputs.idx_file = 'epi_index.txt' + >>> quad.inputs.param_file = 'epi_acqp.txt' + >>> quad.inputs.mask_file = 'epi_mask.nii' + >>> quad.inputs.bval_file = 'bvals.scheme' + >>> quad.inputs.bvec_file = 'bvecs.scheme' + >>> quad.inputs.output_dir = 'eddy_corrected.qc' + >>> quad.inputs.field = 'fieldmap_phase_fslprepared.nii' + >>> quad.inputs.verbose = True + >>> quad.cmdline + 'eddy_quad eddy_corrected --bvals bvals.scheme --bvecs bvecs.scheme \ +--field fieldmap_phase_fslprepared.nii --eddyIdx epi_index.txt \ +--mask epi_mask.nii --output-dir eddy_corrected.qc --eddyParams epi_acqp.txt \ +--verbose' + >>> res = quad.run() # doctest: +SKIP + """ + _cmd = 'eddy_quad' + input_spec = EddyQuadInputSpec + output_spec = EddyQuadOutputSpec + + def _list_outputs(self): + from glob import glob + outputs = self.output_spec().get() + + # If the output directory isn't defined, the interface seems to use + # the default but not set its value in `self.inputs.output_dir` + if not isdefined(self.inputs.output_dir): + out_dir = os.path.abspath(os.path.basename(self.inputs.base_name) + '.qc') + else: + out_dir = os.path.abspath(self.inputs.output_dir) + + outputs['qc_json'] = os.path.join(out_dir, 'qc.json') + outputs['qc_pdf'] = os.path.join(out_dir, 'qc.pdf') + + # Grab all b* files here. This will also grab the b0_pe* files + # as well, but only if the field input was provided. So we'll remove + # them later in the next conditional. + outputs['avg_b_png'] = sorted(glob( + os.path.join(out_dir, 'avg_b*.png') + )) + + if isdefined(self.inputs.field): + outputs['avg_b0_pe_png'] = sorted(glob( + os.path.join(out_dir, 'avg_b0_pe*.png') + )) + + # The previous glob for `avg_b_png` also grabbed the + # `avg_b0_pe_png` files so we have to remove them + # from `avg_b_png`. + for fname in outputs['avg_b0_pe_png']: + outputs['avg_b_png'].remove(fname) + + outputs['vdm_png'] = os.path.join(out_dir, 'vdm.png') + + outputs['cnr_png'] = sorted(glob(os.path.join(out_dir, 'cnr*.png'))) + + residuals = os.path.join(out_dir, 'eddy_msr.txt') + if os.path.isfile(residuals): + outputs['residuals'] = residuals + + clean_volumes = os.path.join(out_dir, 'vols_no_outliers.txt') + if os.path.isfile(clean_volumes): + outputs['clean_volumes'] = clean_volumes + + return outputs diff --git a/dmripreproc/workflows/base.py b/dmripreproc/workflows/base.py index d7e8aa6..20f8636 100644 --- a/dmripreproc/workflows/base.py +++ b/dmripreproc/workflows/base.py @@ -7,9 +7,9 @@ from .dwi import init_dwi_preproc_wf, init_output_wf -def init_dmriprep_wf(parameters): - dmriprep_wf = pe.Workflow(name="dmriprep_wf") - dmriprep_wf.base_dir = parameters.work_dir +def init_dmripreproc_wf(parameters): + dmripreproc_wf = pe.Workflow(name="dmripreproc_wf") + dmripreproc_wf.base_dir = parameters.work_dir for subject_id in parameters.subject_list: @@ -26,9 +26,9 @@ def init_dmriprep_wf(parameters): for node in single_subject_wf._get_all_nodes(): node.config = deepcopy(single_subject_wf.config) - dmriprepoc_wf.add_nodes([single_subject_wf]) + dmripreproc_wf.add_nodes([single_subject_wf]) - return dmriprepoc_wf + return dmripreproc_wf def init_single_subject_wf(subject_id, name, parameters): @@ -72,7 +72,7 @@ def init_single_subject_wf(subject_id, name, parameters): inputspec = dwi_preproc_wf.get_node("inputnode") inputspec.inputs.subject_id = subject_id inputspec.inputs.dwi_file = dwi_file - inputspec.inputs.metadata = metadata + inputspec.inputs.dwi_meta = metadata inputspec.inputs.bvec_file = parameters.layout.get_bvec(dwi_file) inputspec.inputs.bval_file = parameters.layout.get_bval(dwi_file) inputspec.inputs.out_dir = os.path.abspath(parameters.output_dir) diff --git a/dmripreproc/workflows/dwi/base.py b/dmripreproc/workflows/dwi/base.py index fdce43d..9c775d4 100755 --- a/dmripreproc/workflows/dwi/base.py +++ b/dmripreproc/workflows/dwi/base.py @@ -13,9 +13,11 @@ from numba import cuda from ...interfaces import mrtrix3 +from ...interfaces import fsl as dmri_fsl from ..fieldmap.base import init_sdc_prep_wf from .dwiprep import init_dwiprep_wf +FMAP_PRIORITY = {"epi": 0, "fieldmap": 1, "phasediff": 2, "phase": 3, "syn": 4} def init_dwi_preproc_wf(subject_id, dwi_file, metadata, parameters): @@ -42,7 +44,7 @@ def init_dwi_preproc_wf(subject_id, dwi_file, metadata, parameters): fields=[ "subject_id", "dwi_file", - "di_meta", + "dwi_meta", "bvec_file", "bval_file", "out_dir", @@ -190,7 +192,7 @@ def b0_average(in_dwi, in_bval, b0_thresh=10.0, out_file=None): # mrtrix3.MaskFilter ecc = pe.Node( - fsl.Eddy(repol=True, cnr_maps=True, residuals=True, method="jac"), + dmri_fsl.Eddy(repol=True, cnr_maps=True, residuals=True, method="jac"), name="fsl_eddy", ) @@ -238,6 +240,35 @@ def get_b0_mask_fn(b0_file): name="getB0Mask", ) + # Decide what ecc will take: topup or fmap + fmaps.sort(key=lambda fmap: FMAP_PRIORITY[fmap["suffix"]]) + fmap = fmaps[0] + # If epi files detected + if fmap["suffix"] == "epi" or True: + dwi_wf.connect( + [ + ( + sdc_wf, + ecc, + [ + ("outputnode.out_topup", "in_topup_fieldcoef"), + ("outputnode.out_enc_file", "in_acqp"), + ("outputnode.out_movpar", "in_topup_movpar"), + ], + ), + (sdc_wf, eddy_quad, [("outputnode.out_enc_file", "param_file")]) + ] + ) + # Otherwise (fieldmaps) + else: + dwi_wf.connect( + [ + (sdc_wf, ecc, [(("outputnode.out_fmap", get_path), "field")]), + (acqp, ecc, [("out_file", "in_acqp")]), + (acqp, eddy_quad, [("out_file", "param_file")]) + ] + ) + dtifit = pe.Node(fsl.DTIFit(save_tensor=True, sse=True), name="dtifit") dwi_wf.connect( @@ -268,7 +299,6 @@ def get_b0_mask_fn(b0_file): ), (bet_dwi0, ecc, [("mask_file", "in_mask")]), (gen_idx, ecc, [("out_file", "in_index")]), - (acqp, ecc, [("out_file", "in_acqp")]), (ecc, denoise_eddy, [("out_corrected", "in_file")]), (ecc, fslroi, [("out_corrected", "in_file")]), (fslroi, b0mask_node, [("roi_file", "b0_file")]), @@ -284,12 +314,10 @@ def get_b0_mask_fn(b0_file): (ecc, eddy_quad, [("out_rotated_bvecs", "bvec_file")]), (b0mask_node, eddy_quad, [("mask_file", "mask_file")]), (gen_idx, eddy_quad, [("out_file", "idx_file")]), - (acqp, eddy_quad, [("out_file", "param_file")]), (ecc, outputnode, [("out_corrected", "out_file")]), (b0mask_node, outputnode, [("mask_file", "out_mask")]), (ecc, outputnode, [("out_rotated_bvecs", "out_bvec")]), (bet_dwi0, sdc_wf, [("out_file", "inputnode.b0_stripped")]), - (sdc_wf, ecc, [(("outputnode.out_fmap", get_path), "field")]), (sdc_wf, eddy_quad, [("outputnode.out_fmap", "field")]), ( ecc, diff --git a/dmripreproc/workflows/dwi/outputs.py b/dmripreproc/workflows/dwi/outputs.py index a69322f..3d09c9d 100644 --- a/dmripreproc/workflows/dwi/outputs.py +++ b/dmripreproc/workflows/dwi/outputs.py @@ -33,6 +33,7 @@ def init_output_wf(subject_id, session_id, output_folder): ) def build_path(output_folder, subject_id, session_id): + import os return os.path.join( output_folder, diff --git a/dmripreproc/workflows/fieldmap/base.py b/dmripreproc/workflows/fieldmap/base.py index d8a1325..c656e72 100644 --- a/dmripreproc/workflows/fieldmap/base.py +++ b/dmripreproc/workflows/fieldmap/base.py @@ -26,12 +26,15 @@ def init_sdc_prep_wf( niu.IdentityInterface( fields=[ "out_fmap", + "out_topup", "bold_ref", "bold_mask", "bold_ref_brain", "out_warp", "syn_bold_ref", "method", + "out_movpar", + "out_enc_file", ] ), name="outputnode", @@ -52,7 +55,23 @@ def init_sdc_prep_wf( pepolar_wf = init_pepolar_wf(subject_id, metadata, epi_fmaps) sdc_prep_wf.connect( - [(pepolar_wf, outputnode, [("outputnode.out_fmap", "out_fmap")])] + [ + ( + inputnode, + pepolar_wf, + [("b0_stripped", "inputnode.b0_stripped")], + ), + ( + pepolar_wf, + outputnode, + [ + ("outputnode.out_topup", "out_topup"), + ("outputnode.out_movpar", "out_movpar"), + ("outputnode.out_enc_file", "out_enc_file"), + ("outputnode.out_fmap", "out_fmap") + ], + ) + ] ) if fmap["suffix"] == "fieldmap": diff --git a/dmripreproc/workflows/fieldmap/pepolar.py b/dmripreproc/workflows/fieldmap/pepolar.py index 34ca318..413299c 100644 --- a/dmripreproc/workflows/fieldmap/pepolar.py +++ b/dmripreproc/workflows/fieldmap/pepolar.py @@ -8,14 +8,18 @@ def init_pepolar_wf(subject_id, dwi_meta, epi_fmaps): dwi_file_pe = dwi_meta["PhaseEncodingDirection"] + file2dir = dict() + usable_fieldmaps_matching_pe = [] usable_fieldmaps_opposite_pe = [] for fmap, pe_dir in epi_fmaps: if pe_dir == dwi_file_pe: usable_fieldmaps_matching_pe.append(fmap) + file2dir[fmap] = pe_dir elif pe_dir[0] == dwi_file_pe[0]: usable_fieldmaps_opposite_pe.append(fmap) + file2dir[fmap] = pe_dir if not usable_fieldmaps_opposite_pe: raise Exception("None of the discovered fieldmaps for " @@ -24,12 +28,13 @@ def init_pepolar_wf(subject_id, dwi_meta, epi_fmaps): wf = pe.Workflow(name="pepolar_wf") - inputnode = pe.Node(niu.IdentityInterface(fields=["b0_stripped"])) + inputnode = pe.Node(niu.IdentityInterface(fields=["b0_stripped"]), name = "inputnode") - outputnode = pe.Node(niu.IdentityInterface(fields=["out_topup"])) + outputnode = pe.Node(niu.IdentityInterface(fields=["out_topup", "out_movpar", "out_fmap", "out_enc_file"]), name = "outputnode") topup_wf = init_topup_wf() - topup_wf.inputnode.altepi_file = usable_fieldmaps_opposite_pe[0] + topup_wf.inputs.inputnode.altepi_file = usable_fieldmaps_opposite_pe[0] + wf.add_nodes([inputnode]) if not usable_fieldmaps_matching_pe: wf.connect( @@ -38,7 +43,33 @@ def init_pepolar_wf(subject_id, dwi_meta, epi_fmaps): ] ) else: - topup_wf.inputnode.epi_file = usable_fieldmaps_matching_pe[0] + topup_wf.inputs.inputnode.epi_file = usable_fieldmaps_matching_pe[0] + + epi_list = [topup_wf.inputs.inputnode.epi_file, topup_wf.inputs.inputnode.altepi_file] + dir_map = { + 'i': 'x', + 'i-': 'x-', + 'j': 'y', + 'j-': 'y-', + 'k': 'z', + 'k-': 'z-' + } + topup_wf.inputs.inputnode.encoding_directions = [dir_map[file2dir[file]] for file in epi_list] + + wf.connect( + [ + ( + topup_wf, + outputnode, + [ + ("outputnode.out_fmap", "out_fmap"), + ("outputnode.out_movpar", "out_movpar"), + ("outputnode.out_base", "out_topup"), + ("outputnode.out_enc_file", "out_enc_file"), + ] + ), + ] + ) return wf @@ -48,11 +79,12 @@ def init_topup_wf(): wf = pe.Workflow(name="topup_wf") inputnode = pe.Node( - niu.IdentityInterface(fields=["epi_file", "altepi_file", "encoding_directions"]), + niu.IdentityInterface(fields=["epi_file", "altepi_file", "encoding_directions", "topup_name"]), name="inputnode") + inputnode.inputs.topup_name = "topup_base" outputnode = pe.Node( - niu.IdentityInterface(fields=["out_fmap"]), + niu.IdentityInterface(fields=["out_fmap", "out_movpar", "out_base", "out_enc_file"]), name="outputnode") list_merge = pe.Node(niu.Merge(numinputs=2), name="list_merge") @@ -62,6 +94,8 @@ def init_topup_wf(): topup = pe.Node(fsl.TOPUP(), name="topup") topup.inputs.readout_times = [0.05, 0.05] + get_base_movpar = lambda x: x.split("_movpar.txt")[0] + wf.connect( [ ( @@ -70,9 +104,18 @@ def init_topup_wf(): [("epi_file", "in1"), ("altepi_file", "in2")] ), (list_merge, merge, [("out", "in_files")]), - (merge, topup, [("merged_file", "in_file")]), (inputnode, topup, [("encoding_directions", "encoding_direction")]), - (topup, outputnode, [("out_field", "out_fmap")]), + (merge, topup, [("merged_file", "in_file")]), + ( + topup, + outputnode, + [ + ("out_field", "out_fmap"), + ("out_movpar", "out_movpar"), + ("out_enc_file", "out_enc_file"), + (("out_movpar", get_base_movpar), "out_base") + ] + ), ] ) diff --git a/setup.py b/setup.py index 90e755b..0a14d1b 100644 --- a/setup.py +++ b/setup.py @@ -45,7 +45,7 @@ description="Preprocessing of neuroimaging data in preparation for AFQ analysis", entry_points={ "console_scripts": [ - "dmriprepoc=dmriprepoc.cli:main", + "dmriprepoc=dmripreproc.cli:main", "dmriprepoc-data=dmriprepoc.cli:data", "dmriprepoc-upload=dmriprepoc.cli:upload", ] @@ -57,7 +57,7 @@ include_package_data=True, keywords="dmriprepoc", name="dmriprepoc", - packages=find_packages(include=["dmriprepoc*"]), + packages=find_packages(include=["dmripreproc*"]), setup_requires=setup_requirements, test_suite="tests", tests_require=test_requirements, From dc30025d94cd945e8926c32193090257910a53d2 Mon Sep 17 00:00:00 2001 From: Salim Mansour Date: Fri, 19 Jul 2019 11:04:17 -0400 Subject: [PATCH 15/18] dmripreproc renaming --- .github/ISSUE_TEMPLATE.md | 2 +- .travis.yml | 2 +- CONTRIBUTING.rst | 28 ++++++++++++++-------------- Makefile | 8 ++++---- README.rst | 24 ++++++++++++------------ dmripreproc/__init__.py | 8 ++++---- dmripreproc/cli.py | 4 ++-- dmripreproc/workflows/dwi/outputs.py | 2 +- docs/Makefile | 2 +- docs/conf.py | 26 +++++++++++++------------- docs/dmriprep.interfaces.rst | 12 ++++++------ docs/dmriprep.rst | 20 ++++++++++---------- docs/dmriprep.workflows.dwi.rst | 16 ++++++++-------- docs/dmriprep.workflows.fieldmap.rst | 16 ++++++++-------- docs/dmriprep.workflows.rst | 12 ++++++------ docs/img/dmriprep_icon.svg | 4 ++-- docs/index.rst | 2 +- docs/installation.rst | 16 ++++++++-------- docs/make.bat | 2 +- docs/modules.rst | 4 ++-- docs/usage.rst | 4 ++-- setup.cfg | 2 +- setup.py | 12 ++++++------ tests/test_dmriprep.py | 4 ++-- tests/test_utils.py | 4 ++-- tox.ini | 2 +- 26 files changed, 119 insertions(+), 119 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index b1e3287..48e9668 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,4 +1,4 @@ -* dmriprepoc version: +* dmripreproc version: * Python version: * Operating System: diff --git a/.travis.yml b/.travis.yml index 3f5e833..bd44759 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,5 +24,5 @@ deploy: secure: PLEASE_REPLACE_ME on: tags: true - repo: tigrlab/dmriprepocroc + repo: tigrlab/dmripreprocroc python: 3.7 diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 7b7906a..0162eab 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -7,10 +7,10 @@ Contributing Contributions are welcome, and they are greatly appreciated! Every little bit helps, and credit will always be given. -Installing a development version of dmriprepoc +Installing a development version of dmripreproc -------------------------------------------- -First, you can install a development version of dmriprepoc by cloning this repository +First, you can install a development version of dmripreproc by cloning this repository and then typing:: $ pip install -e .[dev] @@ -32,7 +32,7 @@ You can contribute in many ways: Report Bugs ~~~~~~~~~~~ -Report bugs at https://github.com/nipy/dmriprepoc/issues. +Report bugs at https://github.com/nipy/dmripreproc/issues. If you are reporting a bug, please include: @@ -55,14 +55,14 @@ and "help wanted" is open to whoever wants to implement it. Write Documentation ~~~~~~~~~~~~~~~~~~~ -dmriprepoc could always use more documentation, whether as part of the -official dmriprepoc docs, in docstrings, or even on the web in blog posts, +dmripreproc could always use more documentation, whether as part of the +official dmripreproc docs, in docstrings, or even on the web in blog posts, articles, and such. Submit Feedback ~~~~~~~~~~~~~~~ -The best way to send feedback is to file an issue at https://github.com/nipy/dmriprepoc/issues. +The best way to send feedback is to file an issue at https://github.com/nipy/dmripreproc/issues. If you are proposing a feature: @@ -74,17 +74,17 @@ If you are proposing a feature: Get Started! ------------ -Ready to contribute? Here's how to set up `dmriprepoc` for local development. +Ready to contribute? Here's how to set up `dmripreproc` for local development. -1. Fork the `dmriprepoc` repo on GitHub. +1. Fork the `dmripreproc` repo on GitHub. 2. Clone your fork locally:: - $ git clone git@github.com:your_name_here/dmriprepoc.git + $ git clone git@github.com:your_name_here/dmripreproc.git 3. Install your local copy into a virtualenv. Assuming you have virtualenvwrapper installed, this is how you set up your fork for local development:: - $ mkvirtualenv dmriprepoc - $ cd dmriprepoc/ + $ mkvirtualenv dmripreproc + $ cd dmripreproc/ $ python setup.py develop 4. Create a branch for local development:: @@ -96,7 +96,7 @@ Ready to contribute? Here's how to set up `dmriprepoc` for local development. 5. When you're done making changes, check that your changes pass flake8 and the tests, including testing other Python versions with tox:: - $ flake8 dmriprepoc tests + $ flake8 dmripreproc tests $ python setup.py test or py.test $ tox @@ -120,7 +120,7 @@ Before you submit a pull request, check that it meets these guidelines: your new functionality into a function with a docstring, and add the feature to the list in README.rst. 3. The pull request should work for Python 3.5, 3.6 and 3.7, and for PyPy. Check - https://travis-ci.org/nipy/dmriprepoc/pull_requests + https://travis-ci.org/nipy/dmripreproc/pull_requests and make sure that the tests pass for all supported Python versions. When opening a pull request, please use one of the following prefixes: @@ -137,7 +137,7 @@ Tips To run a subset of tests:: -$ py.test tests.test_dmriprepoc +$ py.test tests.test_dmripreproc Deploying diff --git a/Makefile b/Makefile index 88ba6d8..4c04871 100644 --- a/Makefile +++ b/Makefile @@ -51,7 +51,7 @@ clean-test: ## remove test and coverage artifacts rm -fr .pytest_cache lint: ## check style with flake8 - flake8 dmriprepoc tests + flake8 dmripreproc tests test: ## run tests quickly with the default Python py.test @@ -60,15 +60,15 @@ test-all: ## run tests on every Python version with tox tox coverage: ## check code coverage quickly with the default Python - coverage run --source dmriprepoc -m pytest + coverage run --source dmripreproc -m pytest coverage report -m coverage html $(BROWSER) htmlcov/index.html docs: ## generate Sphinx HTML documentation, including API docs - rm -f docs/dmriprepoc.rst + rm -f docs/dmripreproc.rst rm -f docs/modules.rst - sphinx-apidoc -o docs/ dmriprepoc + sphinx-apidoc -o docs/ dmripreproc $(MAKE) -C docs clean $(MAKE) -C docs html $(BROWSER) docs/_build/html/index.html diff --git a/README.rst b/README.rst index e882d9e..0426ffc 100644 --- a/README.rst +++ b/README.rst @@ -3,12 +3,12 @@ .. image:: https://img.shields.io/badge/code%20style-black-000000.svg :target: https://github.com/python/black -# dmriprepoc dmriprepoc +# dmripreproc dmripreproc Preprocessing of neuroimaging data in preparation for AFQ analysis * Free software: BSD license -* Documentation: https://dmriprepoc.readthedocs.io. +* Documentation: https://dmripreproc.readthedocs.io. ## Preparing your data @@ -32,28 +32,28 @@ You should have raw data organized in the BIDS format. Also, you should have run ## Quickstart ```bash -git clone https://github.com/nipy/dmriprepoc -cd dmriprepoc +git clone https://github.com/nipy/dmripreproc +cd dmripreproc python setup.py install -dmriprepoc $BIDS_INPUT_DIR $OUTPUT_DIR --participant-label 01 +dmripreproc $BIDS_INPUT_DIR $OUTPUT_DIR --participant-label 01 ``` ```bash -git clone https://github.com/nipy/dmriprepoc -cd dmriprepoc +git clone https://github.com/nipy/dmripreproc +cd dmripreproc make docker # If you don't want to log into the docker image: -docker run -ti -v $BIDS_INPUT_DIR:/inputs -v $OUTPUT_DIR:/outputs dmriprepoc:prod dmriprepoc /inputs /outputs +docker run -ti -v $BIDS_INPUT_DIR:/inputs -v $OUTPUT_DIR:/outputs dmripreproc:prod dmripreproc /inputs /outputs # If you want to log into the image: -docker run -ti -v $BIDS_INPUT_DIR:/inputs -v $OUTPUT_DIR:/outputs dmriprepoc:prod +docker run -ti -v $BIDS_INPUT_DIR:/inputs -v $OUTPUT_DIR:/outputs dmripreproc:prod # Run this inside the docker image: -dmriprepoc /inputs /outpus --participant-label 01 +dmripreproc /inputs /outpus --participant-label 01 ``` ## Features @@ -62,11 +62,11 @@ dmriprepoc /inputs /outpus --participant-label 01 ## Contributing -We love contributions! dmriprepoc is open source, built on open source, +We love contributions! dmripreproc is open source, built on open source, and we'd love to have you hang out in our community. We have developed some [guidelines](CONTRIBUTING.rst) for contributing to -dmriprepoc. +dmripreproc. **Imposter syndrome disclaimer**: We want your help. No, really. diff --git a/dmripreproc/__init__.py b/dmripreproc/__init__.py index ea3a9a8..c1bef0e 100644 --- a/dmripreproc/__init__.py +++ b/dmripreproc/__init__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -"""Top-level package for dmriprepoc.""" +"""Top-level package for dmripreproc.""" __author__ = """Anisha Keshavan""" __email__ = "anishakeshavan@gmail.com" @@ -22,13 +22,13 @@ # get the log level from environment variable if "DMIRPREP_LOGLEVEL" in os.environ: - loglevel = os.environ["dmriprepoc_LOGLEVEL"] + loglevel = os.environ["dmripreproc_LOGLEVEL"] module_logger.setLevel(getattr(logging, loglevel.upper())) else: module_logger.setLevel(logging.WARNING) # create a file handler -logpath = os.path.join(os.path.expanduser("~"), ".dmriprepoc", "dmriprepoc.log") +logpath = os.path.join(os.path.expanduser("~"), ".dmripreproc", "dmripreproc.log") # Create the config directory if it doesn't exist logdir = os.path.dirname(logpath) @@ -52,4 +52,4 @@ # add the handlers to the logger module_logger.addHandler(handler) -module_logger.info("Started new dmriprepoc session") +module_logger.info("Started new dmripreproc session") diff --git a/dmripreproc/cli.py b/dmripreproc/cli.py index 8a3675a..3d3eb41 100644 --- a/dmripreproc/cli.py +++ b/dmripreproc/cli.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -"""Console script for dmriprepoc.""" +"""Console script for dmripreproc.""" import os import sys import warnings @@ -115,7 +115,7 @@ def main( """ if analysis_level is not "participant": raise NotImplementedError( - "The only valid analysis level for dmriprepoc " + "The only valid analysis level for dmripreproc " "is participant at the moment." ) diff --git a/dmripreproc/workflows/dwi/outputs.py b/dmripreproc/workflows/dwi/outputs.py index 3d09c9d..8e1a6f8 100644 --- a/dmripreproc/workflows/dwi/outputs.py +++ b/dmripreproc/workflows/dwi/outputs.py @@ -37,7 +37,7 @@ def build_path(output_folder, subject_id, session_id): return os.path.join( output_folder, - "dmriprepoc", + "dmripreproc", "sub-" + subject_id, "ses-" + session_id, "dwi", diff --git a/docs/Makefile b/docs/Makefile index 22b578e..de207f3 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -4,7 +4,7 @@ # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = python -msphinx -SPHINXPROJ = dmriprepoc +SPHINXPROJ = dmripreproc SOURCEDIR = . BUILDDIR = _build diff --git a/docs/conf.py b/docs/conf.py index bbc5fb7..263b8ac 100755 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- # -# dmriprepoc documentation build configuration file, created by +# dmripreproc documentation build configuration file, created by # sphinx-quickstart on Fri Jun 9 13:47:02 2017. # # This file is execfile()d with the current directory set to its @@ -22,7 +22,7 @@ import sys sys.path.insert(0, os.path.abspath('..')) -import dmriprepoc +import dmripreproc # -- General configuration --------------------------------------------- @@ -47,7 +47,7 @@ master_doc = 'index' # General information about the project. -project = u'dmriprepoc' +project = u'dmripreproc' copyright = u"2018, Anisha Keshavan" author = u"Anisha Keshavan" @@ -56,9 +56,9 @@ # the built documents. # # The short X.Y version. -version = dmriprepoc.__version__ +version = dmripreproc.__version__ # The full version, including alpha/beta/rc tags. -release = dmriprepoc.__version__ +release = dmripreproc.__version__ # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -101,7 +101,7 @@ # -- Options for HTMLHelp output --------------------------------------- # Output file base name for HTML help builder. -htmlhelp_basename = 'dmriprepocdoc' +htmlhelp_basename = 'dmripreprocdoc' # -- Options for LaTeX output ------------------------------------------ @@ -128,8 +128,8 @@ # (source start file, target name, title, author, documentclass # [howto, manual, or own class]). latex_documents = [ - (master_doc, 'dmriprepoc.tex', - u'dmriprepoc Documentation', + (master_doc, 'dmripreproc.tex', + u'dmripreproc Documentation', u'Anisha Keshavan', 'manual'), ] @@ -139,8 +139,8 @@ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - (master_doc, 'dmriprepoc', - u'dmriprepoc Documentation', + (master_doc, 'dmripreproc', + u'dmripreproc Documentation', [author], 1) ] @@ -151,10 +151,10 @@ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - (master_doc, 'dmriprepoc', - u'dmriprepoc Documentation', + (master_doc, 'dmripreproc', + u'dmripreproc Documentation', author, - 'dmriprepoc', + 'dmripreproc', 'One line description of project.', 'Miscellaneous'), ] diff --git a/docs/dmriprep.interfaces.rst b/docs/dmriprep.interfaces.rst index 8189058..beb6f85 100644 --- a/docs/dmriprep.interfaces.rst +++ b/docs/dmriprep.interfaces.rst @@ -1,21 +1,21 @@ -dmriprepoc.interfaces package +dmripreproc.interfaces package =========================== Submodules ---------- -dmriprepoc.interfaces.fmap module +dmripreproc.interfaces.fmap module ------------------------------- -.. automodule:: dmriprepoc.interfaces.fmap +.. automodule:: dmripreproc.interfaces.fmap :members: :undoc-members: :show-inheritance: -dmriprepoc.interfaces.mrtrix3 module +dmripreproc.interfaces.mrtrix3 module ---------------------------------- -.. automodule:: dmriprepoc.interfaces.mrtrix3 +.. automodule:: dmripreproc.interfaces.mrtrix3 :members: :undoc-members: :show-inheritance: @@ -24,7 +24,7 @@ dmriprepoc.interfaces.mrtrix3 module Module contents --------------- -.. automodule:: dmriprepoc.interfaces +.. automodule:: dmripreproc.interfaces :members: :undoc-members: :show-inheritance: diff --git a/docs/dmriprep.rst b/docs/dmriprep.rst index dd17d08..5f279a7 100644 --- a/docs/dmriprep.rst +++ b/docs/dmriprep.rst @@ -1,4 +1,4 @@ -dmriprepoc package +dmripreproc package ================ Subpackages @@ -6,32 +6,32 @@ Subpackages .. toctree:: - dmriprepoc.interfaces - dmriprepoc.workflows + dmripreproc.interfaces + dmripreproc.workflows Submodules ---------- -dmriprepoc.cli module +dmripreproc.cli module ------------------- -.. automodule:: dmriprepoc.cli +.. automodule:: dmripreproc.cli :members: :undoc-members: :show-inheritance: -dmriprepoc.qc module +dmripreproc.qc module ------------------ -.. automodule:: dmriprepoc.qc +.. automodule:: dmripreproc.qc :members: :undoc-members: :show-inheritance: -dmriprepoc.utils module +dmripreproc.utils module --------------------- -.. automodule:: dmriprepoc.utils +.. automodule:: dmripreproc.utils :members: :undoc-members: :show-inheritance: @@ -40,7 +40,7 @@ dmriprepoc.utils module Module contents --------------- -.. automodule:: dmriprepoc +.. automodule:: dmripreproc :members: :undoc-members: :show-inheritance: diff --git a/docs/dmriprep.workflows.dwi.rst b/docs/dmriprep.workflows.dwi.rst index 66a921f..6758e8c 100644 --- a/docs/dmriprep.workflows.dwi.rst +++ b/docs/dmriprep.workflows.dwi.rst @@ -1,29 +1,29 @@ -dmriprepoc.workflows.dwi package +dmripreproc.workflows.dwi package ============================== Submodules ---------- -dmriprepoc.workflows.dwi.base module +dmripreproc.workflows.dwi.base module ---------------------------------- -.. automodule:: dmriprepoc.workflows.dwi.base +.. automodule:: dmripreproc.workflows.dwi.base :members: :undoc-members: :show-inheritance: -dmriprepoc.workflows.dwi.outputs module +dmripreproc.workflows.dwi.outputs module ------------------------------------- -.. automodule:: dmriprepoc.workflows.dwi.outputs +.. automodule:: dmripreproc.workflows.dwi.outputs :members: :undoc-members: :show-inheritance: -dmriprepoc.workflows.dwi.tensor module +dmripreproc.workflows.dwi.tensor module ------------------------------------ -.. automodule:: dmriprepoc.workflows.dwi.tensor +.. automodule:: dmripreproc.workflows.dwi.tensor :members: :undoc-members: :show-inheritance: @@ -32,7 +32,7 @@ dmriprepoc.workflows.dwi.tensor module Module contents --------------- -.. automodule:: dmriprepoc.workflows.dwi +.. automodule:: dmripreproc.workflows.dwi :members: :undoc-members: :show-inheritance: diff --git a/docs/dmriprep.workflows.fieldmap.rst b/docs/dmriprep.workflows.fieldmap.rst index 6ad3e48..c1139a3 100644 --- a/docs/dmriprep.workflows.fieldmap.rst +++ b/docs/dmriprep.workflows.fieldmap.rst @@ -1,29 +1,29 @@ -dmriprepoc.workflows.fieldmap package +dmripreproc.workflows.fieldmap package =================================== Submodules ---------- -dmriprepoc.workflows.fieldmap.base module +dmripreproc.workflows.fieldmap.base module --------------------------------------- -.. automodule:: dmriprepoc.workflows.fieldmap.base +.. automodule:: dmripreproc.workflows.fieldmap.base :members: :undoc-members: :show-inheritance: -dmriprepoc.workflows.fieldmap.fmap module +dmripreproc.workflows.fieldmap.fmap module --------------------------------------- -.. automodule:: dmriprepoc.workflows.fieldmap.fmap +.. automodule:: dmripreproc.workflows.fieldmap.fmap :members: :undoc-members: :show-inheritance: -dmriprepoc.workflows.fieldmap.phasediff module +dmripreproc.workflows.fieldmap.phasediff module -------------------------------------------- -.. automodule:: dmriprepoc.workflows.fieldmap.phasediff +.. automodule:: dmripreproc.workflows.fieldmap.phasediff :members: :undoc-members: :show-inheritance: @@ -32,7 +32,7 @@ dmriprepoc.workflows.fieldmap.phasediff module Module contents --------------- -.. automodule:: dmriprepoc.workflows.fieldmap +.. automodule:: dmripreproc.workflows.fieldmap :members: :undoc-members: :show-inheritance: diff --git a/docs/dmriprep.workflows.rst b/docs/dmriprep.workflows.rst index 11d0f65..744abc8 100644 --- a/docs/dmriprep.workflows.rst +++ b/docs/dmriprep.workflows.rst @@ -1,4 +1,4 @@ -dmriprepoc.workflows package +dmripreproc.workflows package ========================== Subpackages @@ -6,16 +6,16 @@ Subpackages .. toctree:: - dmriprepoc.workflows.dwi - dmriprepoc.workflows.fieldmap + dmripreproc.workflows.dwi + dmripreproc.workflows.fieldmap Submodules ---------- -dmriprepoc.workflows.base module +dmripreproc.workflows.base module ------------------------------ -.. automodule:: dmriprepoc.workflows.base +.. automodule:: dmripreproc.workflows.base :members: :undoc-members: :show-inheritance: @@ -24,7 +24,7 @@ dmriprepoc.workflows.base module Module contents --------------- -.. automodule:: dmriprepoc.workflows +.. automodule:: dmripreproc.workflows :members: :undoc-members: :show-inheritance: diff --git a/docs/img/dmriprep_icon.svg b/docs/img/dmriprep_icon.svg index e6df76d..68296c3 100644 --- a/docs/img/dmriprep_icon.svg +++ b/docs/img/dmriprep_icon.svg @@ -1,9 +1,9 @@ -dmriprepocdmripreproc \ No newline at end of file diff --git a/docs/index.rst b/docs/index.rst index 1851504..f3ef5b3 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,4 +1,4 @@ -Welcome to dmriprepoc's documentation! +Welcome to dmripreproc's documentation! ====================================== .. toctree:: diff --git a/docs/installation.rst b/docs/installation.rst index d56cd9c..b618ae6 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -8,13 +8,13 @@ Installation Stable release -------------- -To install dmriprepoc, run this command in your terminal: +To install dmripreproc, run this command in your terminal: .. code-block:: console - $ pip install dmriprepoc + $ pip install dmripreproc -This is the preferred method to install dmriprepoc, as it will always install the most recent stable release. +This is the preferred method to install dmripreproc, as it will always install the most recent stable release. If you don't have `pip`_ installed, this `Python installation guide`_ can guide you through the process. @@ -26,19 +26,19 @@ you through the process. From sources ------------ -The sources for dmriprepoc can be downloaded from the `Github repo`_. +The sources for dmripreproc can be downloaded from the `Github repo`_. You can either clone the public repository: .. code-block:: console - $ git clone git://github.com/nipy/dmriprepoc + $ git clone git://github.com/nipy/dmripreproc Or download the `tarball`_: .. code-block:: console - $ curl -OL https://github.com/nipy/dmriprepoc/tarball/master + $ curl -OL https://github.com/nipy/dmripreproc/tarball/master Once you have a copy of the source, you can install it with: @@ -47,5 +47,5 @@ Once you have a copy of the source, you can install it with: $ python setup.py install -.. _Github repo: https://github.com/nipy/dmriprepoc -.. _tarball: https://github.com/nipy/dmriprepoc/tarball/master +.. _Github repo: https://github.com/nipy/dmripreproc +.. _tarball: https://github.com/nipy/dmripreproc/tarball/master diff --git a/docs/make.bat b/docs/make.bat index 265138e..5d078c4 100644 --- a/docs/make.bat +++ b/docs/make.bat @@ -9,7 +9,7 @@ if "%SPHINXBUILD%" == "" ( ) set SOURCEDIR=. set BUILDDIR=_build -set SPHINXPROJ=dmriprepoc +set SPHINXPROJ=dmripreproc if "%1" == "" goto help diff --git a/docs/modules.rst b/docs/modules.rst index 1e0222c..6109e78 100644 --- a/docs/modules.rst +++ b/docs/modules.rst @@ -1,7 +1,7 @@ -dmriprepoc +dmripreproc ======== .. toctree:: :maxdepth: 4 - dmriprepoc + dmripreproc diff --git a/docs/usage.rst b/docs/usage.rst index 56bc3cf..80bb694 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -2,6 +2,6 @@ Usage ===== -To use dmriprepoc in a project:: +To use dmripreproc in a project:: - import dmriprepoc + import dmripreproc diff --git a/setup.cfg b/setup.cfg index da6c0ce..065bb7e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -7,7 +7,7 @@ tag = True search = version='{current_version}' replace = version='{new_version}' -[bumpversion:file:dmriprepoc/__init__.py] +[bumpversion:file:dmripreproc/__init__.py] search = __version__ = '{current_version}' replace = __version__ = '{new_version}' diff --git a/setup.py b/setup.py index 0a14d1b..1d9ceec 100644 --- a/setup.py +++ b/setup.py @@ -45,9 +45,9 @@ description="Preprocessing of neuroimaging data in preparation for AFQ analysis", entry_points={ "console_scripts": [ - "dmriprepoc=dmripreproc.cli:main", - "dmriprepoc-data=dmriprepoc.cli:data", - "dmriprepoc-upload=dmriprepoc.cli:upload", + "dmripreproc=dmripreproc.cli:main", + "dmripreproc-data=dmripreproc.cli:data", + "dmripreproc-upload=dmripreproc.cli:upload", ] }, install_requires=requirements, @@ -55,13 +55,13 @@ license="BSD license", long_description=readme + "\n\n" + history, include_package_data=True, - keywords="dmriprepoc", - name="dmriprepoc", + keywords="dmripreproc", + name="dmripreproc", packages=find_packages(include=["dmripreproc*"]), setup_requires=setup_requirements, test_suite="tests", tests_require=test_requirements, - url="https://github.com/nipy/dmriprepoc", + url="https://github.com/nipy/dmripreproc", version="0.1.0", zip_safe=False, ) diff --git a/tests/test_dmriprep.py b/tests/test_dmriprep.py index 783ccb6..eebb40d 100644 --- a/tests/test_dmriprep.py +++ b/tests/test_dmriprep.py @@ -1,13 +1,13 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -"""Tests for `dmriprepoc` package.""" +"""Tests for `dmripreproc` package.""" import pytest from click.testing import CliRunner -from dmriprepoc import cli +from dmripreproc import cli @pytest.fixture diff --git a/tests/test_utils.py b/tests/test_utils.py index 1ab5c05..b3f1a66 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,11 +1,11 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -"""Tests for `dmriprepoc` package.""" +"""Tests for `dmripreproc` package.""" import numpy as np -from dmriprepoc.utils import is_hemispherical +from dmripreproc.utils import is_hemispherical def uniform_points_on_sphere(npoints=1, hemisphere=True, rotate=(0, 0, 0)): diff --git a/tox.ini b/tox.ini index 589cce4..16279fc 100644 --- a/tox.ini +++ b/tox.ini @@ -10,7 +10,7 @@ python = [testenv:flake8] basepython = python deps = flake8 -commands = flake8 dmriprepoc +commands = flake8 dmripreproc [testenv] setenv = From b5fc4496cf67f132ef6c923d17375ffe3dca19bb Mon Sep 17 00:00:00 2001 From: Salim Mansour Date: Mon, 22 Jul 2019 10:33:04 -0400 Subject: [PATCH 16/18] Added dwiprep file --- dmripreproc/workflows/dwi/dwiprep.py | 82 ++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 dmripreproc/workflows/dwi/dwiprep.py diff --git a/dmripreproc/workflows/dwi/dwiprep.py b/dmripreproc/workflows/dwi/dwiprep.py new file mode 100644 index 0000000..8334cbe --- /dev/null +++ b/dmripreproc/workflows/dwi/dwiprep.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python + +def init_dwiprep_wf(ignore_nodes): + from ...interfaces import mrtrix3 + from nipype.pipeline import engine as pe + from nipype.interfaces import fsl, utility as niu + + # Generate the prep workflow for dwi (denoise, unring, resize) + + dwi_prep_wf = pe.Workflow(name="dwi_prep_wf") + + denoise = pe.Node(mrtrix3.DWIDenoise(), name="denoise") + + unring = pe.Node(mrtrix3.MRDeGibbs(), name="unring") + + resize = pe.Node(mrtrix3.MRResize(voxel_size=[1]), name="resize") + + dwi_prep_inputnode = pe.Node( + niu.IdentityInterface( + fields=["dwi_file"] + ), + name="dwi_prep_inputnode", + ) + + dwi_prep_outputnode = pe.Node( + niu.IdentityInterface(fields=["out_file"]), + name="dwi_prep_outputnode", + ) + + # Turn the string input of nodes into a list + ignore_nodes_list = [option.lower() for option in ignore_nodes.strip()] + + prep_full = ['d', 'u', 'r'] + prep_wanted_str = [node for node in prep_full if not(node in ignore_nodes_list)] + + # Translate string input to node names + str2node = { + 'd': denoise, + 'u': unring, + 'r': resize + } + + # Convert the string list to a node list + prep_wanted = [str2node[str_node] for str_node in prep_wanted_str] + + # If no steps selected, just connect input to output + if not(prep_wanted): + dwi_prep_wf.connect( + [ + (dwi_prep_inputnode, dwi_prep_outputnode, [("dwi_file", "out_file")]) + ] + ) + + # If there are steps + else: + # Must at least connect input node to first node + first_node = prep_wanted[0] + dwi_prep_wf.connect( + [ + (dwi_prep_inputnode, first_node, [("dwi_file", "in_file")]), + ] + ) + # Loop through the prep order + # Note: only works if each node has in_file and out_file + # Can work around this by wrapping in node/workflow with in_file+out_file + prev = first_node + for curr_node in prep_wanted[1:]: + dwi_prep_wf.connect( + [ + (prev, curr_node, [("out_file", "in_file")]), + ] + ) + prev = curr_node + # Connect last node to output node + last_node = prep_wanted[-1] + dwi_prep_wf.connect( + [ + (last_node, dwi_prep_outputnode, [("out_file", "out_file")]), + ] + ) + + return dwi_prep_wf From d1fa940094d39aa9870d2ff3ec1ed7e46f1e0fe2 Mon Sep 17 00:00:00 2001 From: Salim Mansour Date: Mon, 22 Jul 2019 12:05:04 -0400 Subject: [PATCH 17/18] Added synb0 topup functionality --- dmripreproc/cli.py | 21 +++ dmripreproc/utils.py | 2 + dmripreproc/workflows/base.py | 9 +- dmripreproc/workflows/dwi/base.py | 71 ++++--- dmripreproc/workflows/fieldmap/base.py | 215 ++++++++++++---------- dmripreproc/workflows/fieldmap/pepolar.py | 76 +++++++- 6 files changed, 267 insertions(+), 127 deletions(-) diff --git a/dmripreproc/cli.py b/dmripreproc/cli.py index 3d3eb41..68fc811 100644 --- a/dmripreproc/cli.py +++ b/dmripreproc/cli.py @@ -81,6 +81,21 @@ default=None, type=(str), ) +@click.option( + "--synb0_dir", + help="If you want to use Synb0-DISCO for preprocessing.", + #is_flag=True + default=None, + type=(str), +) +@click.option( + "--acqp_file", + help="If you want to pass in an acqp file for topup/eddy instead of" + "generating it from the json by default.", + #is_flag=True + default=None, + type=(str), +) @click.argument("bids_dir") @click.argument("output_dir") @click.argument( @@ -99,6 +114,8 @@ def main( total_readout=None, ignore_nodes="", analysis_level="participant", + synb0_dir=None, + acqp_file=None, ): """ BIDS_DIR: The directory with the input dataset formatted according to @@ -113,6 +130,7 @@ def main( participant level analyses can be run independently (in parallel). """ + if analysis_level is not "participant": raise NotImplementedError( "The only valid analysis level for dmripreproc " @@ -120,6 +138,7 @@ def main( ) layout = BIDSLayout(bids_dir, validate=False) + print(layout) subject_list = utils.collect_participants( layout, participant_label=participant_label ) @@ -140,6 +159,8 @@ def main( parameters.total_readout = total_readout parameters.ignore_nodes = ignore_nodes parameters.analysis_level = analysis_level + parameters.synb0_dir = synb0_dir + parameters.acqp_file = acqp_file wf = init_dmripreproc_wf(parameters) wf.write_graph(graph2use="colored") diff --git a/dmripreproc/utils.py b/dmripreproc/utils.py index fe55506..2728406 100644 --- a/dmripreproc/utils.py +++ b/dmripreproc/utils.py @@ -102,6 +102,8 @@ def __init__(self): self.total_readout = None self.ignore_nodes = '' self.analysis_level = 'participant' + self.synb0_dir = '' + self.acqp_file = '' def collect_participants( bids_dir, participant_label=None, strict=False, bids_validate=True diff --git a/dmripreproc/workflows/base.py b/dmripreproc/workflows/base.py index dc7f067..5b27353 100644 --- a/dmripreproc/workflows/base.py +++ b/dmripreproc/workflows/base.py @@ -4,8 +4,8 @@ from copy import deepcopy from nipype.pipeline import engine as pe -from .dwi import init_dwi_preproc_wf, init_output_wf - +from .dwi.base import init_dwi_preproc_wf +from .dwi.outputs import init_output_wf def init_dmripreproc_wf(parameters): dmripreproc_wf = pe.Workflow(name="dmripreproc_wf") @@ -51,7 +51,10 @@ def init_single_subject_wf(subject_id, name, parameters): for dwi_file in dwi_files: entities = parameters.layout.parse_file_entities(dwi_file) - session_id = entities["session"] + if "session" in entities: + session_id = entities["session"] + else: + session_id = "01" metadata = parameters.layout.get_metadata(dwi_file) dwi_preproc_wf = init_dwi_preproc_wf( subject_id=subject_id, diff --git a/dmripreproc/workflows/dwi/base.py b/dmripreproc/workflows/dwi/base.py index 9c775d4..ee1411c 100755 --- a/dmripreproc/workflows/dwi/base.py +++ b/dmripreproc/workflows/dwi/base.py @@ -11,6 +11,7 @@ from nipype.utils.filemanip import fname_presuffix from dipy.segment.mask import median_otsu from numba import cuda +from bids import BIDSLayout from ...interfaces import mrtrix3 from ...interfaces import fsl as dmri_fsl @@ -21,20 +22,27 @@ def init_dwi_preproc_wf(subject_id, dwi_file, metadata, parameters): + fmaps = [] - fmaps = parameters.layout.get_fieldmap(dwi_file, return_list=True) + synb0 = "" - if not fmaps: - raise Exception( - "No fieldmaps found for participant {}. " - "All workflows require fieldmaps".format(subject_id) - ) + # If use_synb0 set, get synb0 from files + if parameters.synb0_dir: + synb0_layout = BIDSLayout(parameters.synb0_dir, validate=False, derivatives=True) + synb0 = synb0_layout.get(subject=subject_id, return_type='file')[0] + else: + fmaps = parameters.layout.get_fieldmap(dwi_file, return_list=True) + if not fmaps: + raise Exception( + "No fieldmaps found for participant {}. " + "All workflows require fieldmaps".format(subject_id) + ) - for fmap in fmaps: - fmap["metadata"] = parameters.layout.get_metadata(fmap[fmap["suffix"]]) + for fmap in fmaps: + fmap["metadata"] = parameters.layout.get_metadata(fmap[fmap["suffix"]]) sdc_wf = init_sdc_prep_wf( - subject_id, fmaps, metadata, parameters.layout, parameters.bet_mag + subject_id, fmaps, metadata, parameters.layout, parameters.bet_mag, synb0 ) dwi_wf = pe.Workflow(name="dwi_preproc_wf") @@ -240,11 +248,8 @@ def get_b0_mask_fn(b0_file): name="getB0Mask", ) - # Decide what ecc will take: topup or fmap - fmaps.sort(key=lambda fmap: FMAP_PRIORITY[fmap["suffix"]]) - fmap = fmaps[0] - # If epi files detected - if fmap["suffix"] == "epi" or True: + # If synb0 is meant to be used + if parameters.synb0_dir: dwi_wf.connect( [ ( @@ -252,22 +257,42 @@ def get_b0_mask_fn(b0_file): ecc, [ ("outputnode.out_topup", "in_topup_fieldcoef"), - ("outputnode.out_enc_file", "in_acqp"), ("outputnode.out_movpar", "in_topup_movpar"), ], ), (sdc_wf, eddy_quad, [("outputnode.out_enc_file", "param_file")]) ] ) - # Otherwise (fieldmaps) + ecc.inputs.in_acqp = parameters.acqp_file else: - dwi_wf.connect( - [ - (sdc_wf, ecc, [(("outputnode.out_fmap", get_path), "field")]), - (acqp, ecc, [("out_file", "in_acqp")]), - (acqp, eddy_quad, [("out_file", "param_file")]) - ] - ) + # Decide what ecc will take: topup or fmap + fmaps.sort(key=lambda fmap: FMAP_PRIORITY[fmap["suffix"]]) + fmap = fmaps[0] + # Else If epi files detected + if fmap["suffix"] == "epi": + dwi_wf.connect( + [ + ( + sdc_wf, + ecc, + [ + ("outputnode.out_topup", "in_topup_fieldcoef"), + ("outputnode.out_enc_file", "in_acqp"), + ("outputnode.out_movpar", "in_topup_movpar"), + ], + ), + (sdc_wf, eddy_quad, [("outputnode.out_enc_file", "param_file")]) + ] + ) + # Otherwise (fieldmaps) + else: + dwi_wf.connect( + [ + (sdc_wf, ecc, [(("outputnode.out_fmap", get_path), "field")]), + (acqp, ecc, [("out_file", "in_acqp")]), + (acqp, eddy_quad, [("out_file", "param_file")]) + ] + ) dtifit = pe.Node(fsl.DTIFit(save_tensor=True, sse=True), name="dtifit") diff --git a/dmripreproc/workflows/fieldmap/base.py b/dmripreproc/workflows/fieldmap/base.py index c656e72..189c2bf 100644 --- a/dmripreproc/workflows/fieldmap/base.py +++ b/dmripreproc/workflows/fieldmap/base.py @@ -12,6 +12,7 @@ def init_sdc_prep_wf( metadata, layout, bet_mag_frac, + synb0, omp_nthreads=1, fmap_bspline=False, ): @@ -39,30 +40,20 @@ def init_sdc_prep_wf( ), name="outputnode", ) + if (synb0): + from .pepolar import init_synb0_wf - fmaps.sort(key=lambda fmap: FMAP_PRIORITY[fmap["suffix"]]) - fmap = fmaps[0] - - if fmap["suffix"] == "epi": - from .pepolar import init_pepolar_wf - - epi_fmaps = [ - (fmap_["epi"], fmap_["metadata"]["PhaseEncodingDirection"]) - for fmap_ in fmaps - if fmap_["suffix"] == "epi" - ] - - pepolar_wf = init_pepolar_wf(subject_id, metadata, epi_fmaps) + synb0_wf = init_synb0_wf(subject_id, metadata, synb0) sdc_prep_wf.connect( [ ( inputnode, - pepolar_wf, + synb0_wf, [("b0_stripped", "inputnode.b0_stripped")], ), ( - pepolar_wf, + synb0_wf, outputnode, [ ("outputnode.out_topup", "out_topup"), @@ -73,110 +64,144 @@ def init_sdc_prep_wf( ) ] ) + else: + fmaps.sort(key=lambda fmap: FMAP_PRIORITY[fmap["suffix"]]) + fmap = fmaps[0] - if fmap["suffix"] == "fieldmap": - from .fmap import init_fmap_wf + if fmap["suffix"] == "epi": + from .pepolar import init_pepolar_wf - fmap_wf = init_fmap_wf() - fmap_wf.inputs.inputnode.fieldmap = fmap["fieldmap"] - fmap_wf.inputs.inputnode.magnitude = fmap["magnitude"] - - sdc_prep_wf.connect( - [ - ( - inputnode, - fmap_wf, - [("b0_stripped", "inputnode.b0_stripped")], - ), - (fmap_wf, outputnode, [("outputnode.out_fmap", "out_fmap")]), + epi_fmaps = [ + (fmap_["epi"], fmap_["metadata"]["PhaseEncodingDirection"]) + for fmap_ in fmaps + if fmap_["suffix"] == "epi" ] - ) - - if fmap["suffix"] in ("phasediff", "phase"): - from .phasediff import init_phase_wf, init_phdiff_wf - from .fmap import init_fmap_wf - if fmap["suffix"] == "phasediff": - phase_wf = init_phdiff_wf(bet_mag_frac) - phase_wf.inputs.inputnode.phasediff = fmap["phasediff"] - - phase_wf.inputs.inputnode.magnitude1 = [ - fmap_ - for key, fmap_ in sorted(fmap.items()) - if key.startswith("magnitude1") - ][0] - - phase_wf.inputs.inputnode.phases_meta = layout.get_metadata( - phase_wf.inputs.inputnode.phasediff - ) - post_phase_wf = init_fmap_wf() + pepolar_wf = init_pepolar_wf(subject_id, metadata, epi_fmaps) sdc_prep_wf.connect( [ ( inputnode, - post_phase_wf, + pepolar_wf, [("b0_stripped", "inputnode.b0_stripped")], ), ( - phase_wf, - post_phase_wf, - [("outputnode.out_fmap", "inputnode.fieldmap")], - ), - ( - phase_wf, - post_phase_wf, - [("outputnode.out_mag", "inputnode.magnitude")], - ), - ( - post_phase_wf, + pepolar_wf, outputnode, - [("outputnode.out_fmap", "out_fmap")], - ), + [ + ("outputnode.out_topup", "out_topup"), + ("outputnode.out_movpar", "out_movpar"), + ("outputnode.out_enc_file", "out_enc_file"), + ("outputnode.out_fmap", "out_fmap") + ], + ) ] ) - elif fmap["suffix"] == "phase": - phase_wf = init_phase_wf(bet_mag_frac) - phase_wf.inputs.inputnode.phasediff = [ - fmap["phase1"], - fmap["phase2"], - ] + if fmap["suffix"] == "fieldmap": + from .fmap import init_fmap_wf - phase_wf.inputs.inputnode.magnitude1 = [ - fmap_ - for key, fmap_ in sorted(fmap.items()) - if key.startswith("magnitude1") - ][0] - - phase_wf.inputs.inputnode.phases_meta = [ - layout.get_metadata(i) - for i in phase_wf.inputs.inputnode.phasediff - ] - post_phase_wf = init_fmap_wf() + fmap_wf = init_fmap_wf() + fmap_wf.inputs.inputnode.fieldmap = fmap["fieldmap"] + fmap_wf.inputs.inputnode.magnitude = fmap["magnitude"] sdc_prep_wf.connect( [ ( inputnode, - post_phase_wf, + fmap_wf, [("b0_stripped", "inputnode.b0_stripped")], ), - ( - phase_wf, - post_phase_wf, - [("outputnode.out_fmap", "inputnode.fieldmap")], - ), - ( - phase_wf, - post_phase_wf, - [("outputnode.out_mag", "inputnode.magnitude")], - ), - ( - post_phase_wf, - outputnode, - [("outputnode.out_fmap", "out_fmap")], - ), + (fmap_wf, outputnode, [("outputnode.out_fmap", "out_fmap")]), ] ) + + if fmap["suffix"] in ("phasediff", "phase"): + from .phasediff import init_phase_wf, init_phdiff_wf + from .fmap import init_fmap_wf + + if fmap["suffix"] == "phasediff": + phase_wf = init_phdiff_wf(bet_mag_frac) + phase_wf.inputs.inputnode.phasediff = fmap["phasediff"] + + phase_wf.inputs.inputnode.magnitude1 = [ + fmap_ + for key, fmap_ in sorted(fmap.items()) + if key.startswith("magnitude1") + ][0] + + phase_wf.inputs.inputnode.phases_meta = layout.get_metadata( + phase_wf.inputs.inputnode.phasediff + ) + post_phase_wf = init_fmap_wf() + + sdc_prep_wf.connect( + [ + ( + inputnode, + post_phase_wf, + [("b0_stripped", "inputnode.b0_stripped")], + ), + ( + phase_wf, + post_phase_wf, + [("outputnode.out_fmap", "inputnode.fieldmap")], + ), + ( + phase_wf, + post_phase_wf, + [("outputnode.out_mag", "inputnode.magnitude")], + ), + ( + post_phase_wf, + outputnode, + [("outputnode.out_fmap", "out_fmap")], + ), + ] + ) + + elif fmap["suffix"] == "phase": + phase_wf = init_phase_wf(bet_mag_frac) + phase_wf.inputs.inputnode.phasediff = [ + fmap["phase1"], + fmap["phase2"], + ] + + phase_wf.inputs.inputnode.magnitude1 = [ + fmap_ + for key, fmap_ in sorted(fmap.items()) + if key.startswith("magnitude1") + ][0] + + phase_wf.inputs.inputnode.phases_meta = [ + layout.get_metadata(i) + for i in phase_wf.inputs.inputnode.phasediff + ] + post_phase_wf = init_fmap_wf() + + sdc_prep_wf.connect( + [ + ( + inputnode, + post_phase_wf, + [("b0_stripped", "inputnode.b0_stripped")], + ), + ( + phase_wf, + post_phase_wf, + [("outputnode.out_fmap", "inputnode.fieldmap")], + ), + ( + phase_wf, + post_phase_wf, + [("outputnode.out_mag", "inputnode.magnitude")], + ), + ( + post_phase_wf, + outputnode, + [("outputnode.out_fmap", "out_fmap")], + ), + ] + ) return sdc_prep_wf diff --git a/dmripreproc/workflows/fieldmap/pepolar.py b/dmripreproc/workflows/fieldmap/pepolar.py index 413299c..a3ae9b2 100644 --- a/dmripreproc/workflows/fieldmap/pepolar.py +++ b/dmripreproc/workflows/fieldmap/pepolar.py @@ -73,16 +73,58 @@ def init_pepolar_wf(subject_id, dwi_meta, epi_fmaps): return wf +def init_synb0_wf(subject_id, dwi_meta, synb0): + dwi_file_pe = dwi_meta["PhaseEncodingDirection"] + + file2dir = dict() + + usable_fieldmaps_matching_pe = [] + usable_fieldmaps_opposite_pe = [] + + wf = pe.Workflow(name="synb0_wf") + + inputnode = pe.Node(niu.IdentityInterface(fields=["b0_stripped"]), name = "inputnode") + + outputnode = pe.Node(niu.IdentityInterface(fields=["out_topup", "out_movpar", "out_fmap", "out_enc_file"]), name = "outputnode") + + topup_wf = init_topup_wf(use_acqp=True) + topup_wf.inputs.inputnode.altepi_file = synb0 + wf.add_nodes([inputnode]) + wf.connect( + [ + (inputnode, topup_wf, [("b0_stripped", "inputnode.epi_file")]) + ] + ) + topup_wf.inputs.inputnode.acqp = '/scratch/smansour/synb0_acqp.txt' + + wf.connect( + [ + ( + topup_wf, + outputnode, + [ + ("outputnode.out_fmap", "out_fmap"), + ("outputnode.out_movpar", "out_movpar"), + ("outputnode.out_base", "out_topup"), + ] + ), + ] + ) + + return wf -def init_topup_wf(): +def init_topup_wf(use_acqp=False): + from ...interfaces import mrtrix3 wf = pe.Workflow(name="topup_wf") inputnode = pe.Node( - niu.IdentityInterface(fields=["epi_file", "altepi_file", "encoding_directions", "topup_name"]), + niu.IdentityInterface(fields=["epi_file", "altepi_file", "encoding_directions", "topup_name", "acqp"]), name="inputnode") inputnode.inputs.topup_name = "topup_base" + epi_flirt = pe.Node(fsl.FLIRT(), name="epi_flirt") + outputnode = pe.Node( niu.IdentityInterface(fields=["out_fmap", "out_movpar", "out_base", "out_enc_file"]), name="outputnode") @@ -91,21 +133,43 @@ def init_topup_wf(): merge = pe.Node(fsl.Merge(dimension="t"), name="mergeAPPA") + # Resize (make optional) + resize = pe.Node(mrtrix3.MRResize(voxel_size=[1]), name="epi_resize") + topup = pe.Node(fsl.TOPUP(), name="topup") - topup.inputs.readout_times = [0.05, 0.05] get_base_movpar = lambda x: x.split("_movpar.txt")[0] + if use_acqp: + wf.connect( + [ + (inputnode, topup, [("acqp", "encoding_file")]) + ] + ) + else: + topup.inputs.readout_times = [0.05, 0.05] + wf.connect( + [ + (inputnode, topup, [("encoding_directions", "encoding_direction")]) + ] + ) + wf.connect( [ ( inputnode, list_merge, - [("epi_file", "in1"), ("altepi_file", "in2")] + [("epi_file", "in1")] + ), + ( + inputnode, + epi_flirt, + [("altepi_file", "in_file"), ("epi_file", "reference")] ), + (epi_flirt, list_merge, [("out_file", "in2")]), (list_merge, merge, [("out", "in_files")]), - (inputnode, topup, [("encoding_directions", "encoding_direction")]), - (merge, topup, [("merged_file", "in_file")]), + (merge, resize, [("merged_file", "in_file")]), + (resize, topup, [("out_file", "in_file")]), ( topup, outputnode, From f289b7f8f7d4e8210c17ecd16314c310f0ff9d32 Mon Sep 17 00:00:00 2001 From: Salim Mansour Date: Tue, 23 Jul 2019 09:33:57 -0400 Subject: [PATCH 18/18] Fixed eddy quad acqp input --- dmripreproc/workflows/dwi/base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dmripreproc/workflows/dwi/base.py b/dmripreproc/workflows/dwi/base.py index ee1411c..3ca171e 100755 --- a/dmripreproc/workflows/dwi/base.py +++ b/dmripreproc/workflows/dwi/base.py @@ -259,11 +259,11 @@ def get_b0_mask_fn(b0_file): ("outputnode.out_topup", "in_topup_fieldcoef"), ("outputnode.out_movpar", "in_topup_movpar"), ], - ), - (sdc_wf, eddy_quad, [("outputnode.out_enc_file", "param_file")]) + ) ] ) ecc.inputs.in_acqp = parameters.acqp_file + eddy_quad.inputs.param_file = parameters.acqp_file else: # Decide what ecc will take: topup or fmap fmaps.sort(key=lambda fmap: FMAP_PRIORITY[fmap["suffix"]])