From d3d9df9ff3f0f4d2b684895100a6bd25ca9731a7 Mon Sep 17 00:00:00 2001 From: Synchon Mandal Date: Thu, 21 Sep 2023 13:24:05 +0200 Subject: [PATCH 01/13] update: skip Warp data type reading in DefaultDataReader --- junifer/datareader/default.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/junifer/datareader/default.py b/junifer/datareader/default.py index c2a486e93..6cc159e95 100644 --- a/junifer/datareader/default.py +++ b/junifer/datareader/default.py @@ -104,6 +104,10 @@ class DefaultDataReader(PipelineStepMixin, UpdateMetaMixin): params = {} # For each type of data, try to read it for type_ in input.keys(): + # Skip Warp data type + if type_ == "Warp": + continue + # Check for malformed datagrabber specification if "path" not in input[type_]: warn_with_log( -- 2.52.0 From d546059feb1a23d5edf16cf6af03c85cbe8b4de8 Mon Sep 17 00:00:00 2001 From: Synchon Mandal Date: Thu, 21 Sep 2023 13:27:11 +0200 Subject: [PATCH 02/13] update: add T1w and Warp data types for HCP1200 --- junifer/datagrabber/hcp1200/hcp1200.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/junifer/datagrabber/hcp1200/hcp1200.py b/junifer/datagrabber/hcp1200/hcp1200.py index 351ad2b9d..9df1adfc7 100644 --- a/junifer/datagrabber/hcp1200/hcp1200.py +++ b/junifer/datagrabber/hcp1200/hcp1200.py @@ -98,7 +98,7 @@ class HCP1200(PatternDataGrabber): ) suffix = "_hp2000_clean" if ica_fix else "" # The types of data - types = ["BOLD"] + types = ["BOLD", "T1w", "Warp"] # The patterns patterns = { "BOLD": ( @@ -106,7 +106,9 @@ class HCP1200(PatternDataGrabber): "{task}_{phase_encoding}/" "{task}_{phase_encoding}" f"{suffix}.nii.gz" - ) + ), + "T1w": "{subject}/T1w/T1w_acpc_dc_restore.nii.gz", + "Warp": "{subject}/MNINonLinear/xfms/standard2acpc_dc.nii.gz", } # The replacements replacements = ["subject", "task", "phase_encoding"] -- 2.52.0 From 8c5d1c356145a9a1d2be3dcd007cc610a379e1e7 Mon Sep 17 00:00:00 2001 From: Synchon Mandal Date: Fri, 22 Sep 2023 13:43:48 +0200 Subject: [PATCH 03/13] update: add space for T1w data type of HCP1200 --- junifer/datagrabber/hcp1200/hcp1200.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/junifer/datagrabber/hcp1200/hcp1200.py b/junifer/datagrabber/hcp1200/hcp1200.py index 9df1adfc7..ab3145e52 100644 --- a/junifer/datagrabber/hcp1200/hcp1200.py +++ b/junifer/datagrabber/hcp1200/hcp1200.py @@ -149,6 +149,9 @@ class HCP1200(PatternDataGrabber): out = super().get_item( subject=subject, task=new_task, phase_encoding=phase_encoding ) + # Add space for T1w data type + if "T1w" in out: + out["T1w"].update({"space": "native"}) return out def get_elements(self) -> List: -- 2.52.0 From 5080bc373f943d9bfe1e3a4005ad70fa50174596 Mon Sep 17 00:00:00 2001 From: Synchon Mandal Date: Wed, 27 Sep 2023 10:19:29 +0200 Subject: [PATCH 04/13] update: add space for BOLD data type of HCP1200 --- junifer/datagrabber/hcp1200/hcp1200.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/junifer/datagrabber/hcp1200/hcp1200.py b/junifer/datagrabber/hcp1200/hcp1200.py index ab3145e52..2fa8a1de4 100644 --- a/junifer/datagrabber/hcp1200/hcp1200.py +++ b/junifer/datagrabber/hcp1200/hcp1200.py @@ -149,6 +149,9 @@ class HCP1200(PatternDataGrabber): out = super().get_item( subject=subject, task=new_task, phase_encoding=phase_encoding ) + # Add space for BOLD data type + if "BOLD" in out: + out["BOLD"].update({"space": "MNI"}) # Add space for T1w data type if "T1w" in out: out["T1w"].update({"space": "native"}) -- 2.52.0 From 40a9605012a58feb791b7ad3ed02dc14bb31af90 Mon Sep 17 00:00:00 2001 From: Synchon Mandal Date: Mon, 16 Oct 2023 15:36:17 +0200 Subject: [PATCH 05/13] chore: add changelogs 252.change, 252.enh and 252.feature --- docs/changes/newsfragments/252.change | 1 + docs/changes/newsfragments/252.enh | 1 + docs/changes/newsfragments/252.feature | 1 + 3 files changed, 3 insertions(+) create mode 100644 docs/changes/newsfragments/252.change create mode 100644 docs/changes/newsfragments/252.enh create mode 100644 docs/changes/newsfragments/252.feature diff --git a/docs/changes/newsfragments/252.change b/docs/changes/newsfragments/252.change new file mode 100644 index 000000000..54387806e --- /dev/null +++ b/docs/changes/newsfragments/252.change @@ -0,0 +1 @@ +Add ``space`` parameter to :func:`.register_coordinates`, :func:`.register_parcellation` and :func:`.register_mask`; return space from :func:`.load_coordinates`, :func:`.load_parcellation` and :func:`.load_mask`; modify ``preprocessor`` parameter to ``preprocessors`` in :func:`.run` to accept multiple preprocessors; modify ``preprocessing`` parameter to ``preprocessors`` in :class:`.MarkerCollection` by `Synchon Mandal`_ and `Fede Raimondo`_ diff --git a/docs/changes/newsfragments/252.enh b/docs/changes/newsfragments/252.enh new file mode 100644 index 000000000..59047055c --- /dev/null +++ b/docs/changes/newsfragments/252.enh @@ -0,0 +1 @@ +Add ``space`` information to existing datagrabbers, masks, parcellations and coordinates; extend Docker support to FSL to allow FSL commands to be called by ``junifer``; improve :class:`.BasePreprocessor` and :class:`.fMRIPrepConfoundRemover` by `Synchon Mandal`_ and `Fede Raimondo`_ diff --git a/docs/changes/newsfragments/252.feature b/docs/changes/newsfragments/252.feature new file mode 100644 index 000000000..29401fb57 --- /dev/null +++ b/docs/changes/newsfragments/252.feature @@ -0,0 +1 @@ +Add support for subject-native space computation; introduce :func:`.get_coordinates` and :func:`.get_parcellation` for coordinates and parcellation respectively tailored for the data; introduce ``_ApplyWarper`` to wrap FSL's ``applywarp`` and :class:`.BOLDWarper` to specifically warp BOLD data by `Synchon Mandal`_ and `Fede Raimondo`_ -- 2.52.0 From ee73569abdddeaffa774cf24a480a3f2c2ad0b88 Mon Sep 17 00:00:00 2001 From: Synchon Mandal Date: Wed, 25 Oct 2023 18:12:29 +0200 Subject: [PATCH 06/13] chore: remove 252.change and 252.enh changelogs --- docs/changes/newsfragments/252.change | 1 - docs/changes/newsfragments/252.enh | 1 - 2 files changed, 2 deletions(-) delete mode 100644 docs/changes/newsfragments/252.change delete mode 100644 docs/changes/newsfragments/252.enh diff --git a/docs/changes/newsfragments/252.change b/docs/changes/newsfragments/252.change deleted file mode 100644 index 54387806e..000000000 --- a/docs/changes/newsfragments/252.change +++ /dev/null @@ -1 +0,0 @@ -Add ``space`` parameter to :func:`.register_coordinates`, :func:`.register_parcellation` and :func:`.register_mask`; return space from :func:`.load_coordinates`, :func:`.load_parcellation` and :func:`.load_mask`; modify ``preprocessor`` parameter to ``preprocessors`` in :func:`.run` to accept multiple preprocessors; modify ``preprocessing`` parameter to ``preprocessors`` in :class:`.MarkerCollection` by `Synchon Mandal`_ and `Fede Raimondo`_ diff --git a/docs/changes/newsfragments/252.enh b/docs/changes/newsfragments/252.enh deleted file mode 100644 index 59047055c..000000000 --- a/docs/changes/newsfragments/252.enh +++ /dev/null @@ -1 +0,0 @@ -Add ``space`` information to existing datagrabbers, masks, parcellations and coordinates; extend Docker support to FSL to allow FSL commands to be called by ``junifer``; improve :class:`.BasePreprocessor` and :class:`.fMRIPrepConfoundRemover` by `Synchon Mandal`_ and `Fede Raimondo`_ -- 2.52.0 From 2d0f7b12344eabf844b229e047bbeea9b75e8702 Mon Sep 17 00:00:00 2001 From: Synchon Mandal Date: Wed, 25 Oct 2023 18:14:19 +0200 Subject: [PATCH 07/13] chore: update 252.feature changelog --- docs/changes/newsfragments/252.feature | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/changes/newsfragments/252.feature b/docs/changes/newsfragments/252.feature index 29401fb57..57f767c22 100644 --- a/docs/changes/newsfragments/252.feature +++ b/docs/changes/newsfragments/252.feature @@ -1 +1 @@ -Add support for subject-native space computation; introduce :func:`.get_coordinates` and :func:`.get_parcellation` for coordinates and parcellation respectively tailored for the data; introduce ``_ApplyWarper`` to wrap FSL's ``applywarp`` and :class:`.BOLDWarper` to specifically warp BOLD data by `Synchon Mandal`_ and `Fede Raimondo`_ +Add support for subject-native space by `Synchon Mandal`_ and `Fede Raimondo`_ -- 2.52.0 From 60a9a24ad2413dcb8a570d4a14d390ec60d9610f Mon Sep 17 00:00:00 2001 From: Synchon Mandal Date: Thu, 26 Oct 2023 15:20:47 +0200 Subject: [PATCH 08/13] fix: update space info for HCP1200 BOLD --- junifer/datagrabber/hcp1200/hcp1200.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/junifer/datagrabber/hcp1200/hcp1200.py b/junifer/datagrabber/hcp1200/hcp1200.py index 2fa8a1de4..df5ec43a1 100644 --- a/junifer/datagrabber/hcp1200/hcp1200.py +++ b/junifer/datagrabber/hcp1200/hcp1200.py @@ -151,7 +151,7 @@ class HCP1200(PatternDataGrabber): ) # Add space for BOLD data type if "BOLD" in out: - out["BOLD"].update({"space": "MNI"}) + out["BOLD"].update({"space": "MNI152NLin6Asym"}) # Add space for T1w data type if "T1w" in out: out["T1w"].update({"space": "native"}) -- 2.52.0 From 6ebced6bc215332e8d9f8a443e39fb6f04a95115 Mon Sep 17 00:00:00 2001 From: Synchon Mandal Date: Thu, 26 Oct 2023 15:21:42 +0200 Subject: [PATCH 09/13] update: improve space information for DataladAOMICID1000 --- junifer/datagrabber/aomic/id1000.py | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/junifer/datagrabber/aomic/id1000.py b/junifer/datagrabber/aomic/id1000.py index a955f6b8a..e8b4af1cb 100644 --- a/junifer/datagrabber/aomic/id1000.py +++ b/junifer/datagrabber/aomic/id1000.py @@ -28,6 +28,8 @@ class DataladAOMICID1000(PatternDataladDataGrabber): "probseg_WM", "DWI"} or a list of the options, optional AOMIC data types. If None, all available data types are selected. (default None). + native_t1w : bool, optional + Whether to use T1w in native space (default False). """ @@ -35,6 +37,7 @@ class DataladAOMICID1000(PatternDataladDataGrabber): self, datadir: Union[str, Path, None] = None, types: Union[str, List[str], None] = None, + native_t1w: bool = False, ) -> None: # The patterns patterns = { @@ -84,6 +87,27 @@ class DataladAOMICID1000(PatternDataladDataGrabber): "sub-{subject}_desc-preproc_dwi.nii.gz" ), } + # Use native T1w assets + self.native_t1w = False + if native_t1w: + self.native_t1w = True + patterns.update( + { + "T1w": ( + "derivatives/fmriprep/sub-{subject}/anat/" + "sub-{subject}_desc-preproc_T1w.nii.gz" + ), + "T1w_mask": ( + "derivatives/fmriprep/sub-{subject}/anat/" + "sub-{subject}_desc-brain_mask.nii.gz" + ), + "Warp": ( + "derivatives/fmriprep/sub-{subject}/anat/" + "sub-{subject}_from-MNI152NLin2009cAsym_to-T1w_" + "mode-image_xfm.h5" + ), + } + ) # Set default types if types is None: types = list(patterns.keys()) @@ -126,5 +150,8 @@ class DataladAOMICID1000(PatternDataladDataGrabber): if out.get("T1w"): out["T1w"]["mask_item"] = "T1w_mask" # Add space information - out["T1w"].update({"space": "native"}) + if self.native_t1w: + out["T1w"].update({"space": "native"}) + else: + out["T1w"].update({"space": "MNI152NLin2009cAsym"}) return out -- 2.52.0 From ae55f937d1b4b15cc1f01c835c1ce1b4105b492a Mon Sep 17 00:00:00 2001 From: Synchon Mandal Date: Thu, 26 Oct 2023 15:22:22 +0200 Subject: [PATCH 10/13] update: improve space information for DataladAOMICPIOP1 --- junifer/datagrabber/aomic/piop1.py | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/junifer/datagrabber/aomic/piop1.py b/junifer/datagrabber/aomic/piop1.py index 88a59005c..888d1511c 100644 --- a/junifer/datagrabber/aomic/piop1.py +++ b/junifer/datagrabber/aomic/piop1.py @@ -34,6 +34,8 @@ class DataladAOMICPIOP1(PatternDataladDataGrabber): "gstroop", "workingmemory"} or list of the options, optional AOMIC PIOP1 task sessions. If None, all available task sessions are selected (default None). + native_t1w : bool, optional + Whether to use T1w in native space (default False). """ @@ -42,6 +44,7 @@ class DataladAOMICPIOP1(PatternDataladDataGrabber): datadir: Union[str, Path, None] = None, types: Union[str, List[str], None] = None, tasks: Union[str, List[str], None] = None, + native_t1w: bool = False, ) -> None: # Declare all tasks all_tasks = [ @@ -114,6 +117,27 @@ class DataladAOMICPIOP1(PatternDataladDataGrabber): "sub-{subject}_desc-preproc_dwi.nii.gz" ), } + # Use native T1w assets + self.native_t1w = False + if native_t1w: + self.native_t1w = True + patterns.update( + { + "T1w": ( + "derivatives/fmriprep/sub-{subject}/anat/" + "sub-{subject}_desc-preproc_T1w.nii.gz" + ), + "T1w_mask": ( + "derivatives/fmriprep/sub-{subject}/anat/" + "sub-{subject}_desc-brain_mask.nii.gz" + ), + "Warp": ( + "derivatives/fmriprep/sub-{subject}/anat/" + "sub-{subject}_from-MNI152NLin2009cAsym_to-T1w_" + "mode-image_xfm.h5" + ), + } + ) # Set default types if types is None: types = list(patterns.keys()) @@ -171,7 +195,10 @@ class DataladAOMICPIOP1(PatternDataladDataGrabber): if out.get("T1w"): out["T1w"]["mask_item"] = "T1w_mask" # Add space information - out["T1w"].update({"space": "native"}) + if self.native_t1w: + out["T1w"].update({"space": "native"}) + else: + out["T1w"].update({"space": "MNI152NLin2009cAsym"}) return out def get_elements(self) -> List: -- 2.52.0 From 9ec463e3747cadd3faa67921d02a5ecf366365a5 Mon Sep 17 00:00:00 2001 From: Synchon Mandal Date: Thu, 26 Oct 2023 15:23:15 +0200 Subject: [PATCH 11/13] update: improve space information for DataladAOMICPIOP2 --- junifer/datagrabber/aomic/piop2.py | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/junifer/datagrabber/aomic/piop2.py b/junifer/datagrabber/aomic/piop2.py index a973d93e2..00b55f076 100644 --- a/junifer/datagrabber/aomic/piop2.py +++ b/junifer/datagrabber/aomic/piop2.py @@ -34,6 +34,8 @@ class DataladAOMICPIOP2(PatternDataladDataGrabber): or list of the options, optional AOMIC PIOP2 task sessions. If None, all available task sessions are selected (default None). + native_t1w : bool, optional + Whether to use T1w in native space (default False). """ @@ -42,6 +44,7 @@ class DataladAOMICPIOP2(PatternDataladDataGrabber): datadir: Union[str, Path, None] = None, types: Union[str, List[str], None] = None, tasks: Union[str, List[str], None] = None, + native_t1w: bool = False, ) -> None: # Declare all tasks all_tasks = [ @@ -111,6 +114,27 @@ class DataladAOMICPIOP2(PatternDataladDataGrabber): "sub-{subject}_desc-preproc_dwi.nii.gz" ), } + # Use native T1w assets + self.native_t1w = False + if native_t1w: + self.native_t1w = True + patterns.update( + { + "T1w": ( + "derivatives/fmriprep/sub-{subject}/anat/" + "sub-{subject}_desc-preproc_T1w.nii.gz" + ), + "T1w_mask": ( + "derivatives/fmriprep/sub-{subject}/anat/" + "sub-{subject}_desc-brain_mask.nii.gz" + ), + "Warp": ( + "derivatives/fmriprep/sub-{subject}/anat/" + "sub-{subject}_from-MNI152NLin2009cAsym_to-T1w_" + "mode-image_xfm.h5" + ), + } + ) # Set default types if types is None: types = list(patterns.keys()) @@ -171,5 +195,8 @@ class DataladAOMICPIOP2(PatternDataladDataGrabber): if out.get("T1w"): out["T1w"]["mask_item"] = "T1w_mask" # Add space information - out["T1w"].update({"space": "native"}) + if self.native_t1w: + out["T1w"].update({"space": "native"}) + else: + out["T1w"].update({"space": "MNI152NLin2009cAsym"}) return out -- 2.52.0 From da1b57ddb83da7d7ab3feeeed66d75b12b94d799 Mon Sep 17 00:00:00 2001 From: Synchon Mandal Date: Thu, 26 Oct 2023 15:42:14 +0200 Subject: [PATCH 12/13] chore: add 252.change changelog --- docs/changes/newsfragments/252.change | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs/changes/newsfragments/252.change diff --git a/docs/changes/newsfragments/252.change b/docs/changes/newsfragments/252.change new file mode 100644 index 000000000..70bf6bd8d --- /dev/null +++ b/docs/changes/newsfragments/252.change @@ -0,0 +1 @@ +Add ``native_t1w`` parameter to :class:`.DataladAOMICID1000`, :class:`.DataladAOMICPIOP1`, :class:`.DataladAOMICPIOP2`, enabling fetching of T1w data in subject-native space by `Synchon Mandal`_ -- 2.52.0 From dbbf651d4c4267dca9efe1ec449a77982e6d1688 Mon Sep 17 00:00:00 2001 From: Synchon Mandal Date: Fri, 27 Oct 2023 11:21:24 +0200 Subject: [PATCH 13/13] chore: update tools/create_hcp1200_example_dataset.py to allow T1w and Warp data creation --- tools/create_hcp1200_example_dataset.py | 45 ++++++++++++++++++------- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/tools/create_hcp1200_example_dataset.py b/tools/create_hcp1200_example_dataset.py index 5a3bd0637..0759cbb9b 100644 --- a/tools/create_hcp1200_example_dataset.py +++ b/tools/create_hcp1200_example_dataset.py @@ -4,8 +4,8 @@ # License: AGPL from itertools import product -from tempfile import TemporaryDirectory from pathlib import Path +from tempfile import TemporaryDirectory import datalad.api as dl @@ -15,7 +15,6 @@ DST = "git@gin.g-node.org:/juaml/datalad-example-hcp1200.git" if __name__ == "__main__": - with TemporaryDirectory() as tmpdir: # Convert str to Path tmpdir_path = Path(tmpdir) @@ -29,7 +28,30 @@ if __name__ == "__main__": # Create subject directory subdir.mkdir() - for (task, phase_encoding) in product( + # T1w data + # Set subject data directory + sub_t1w_datadir = subdir / "T1w" + # Create subject data directory + sub_t1w_datadir.mkdir(parents=True) + # Set subject data file + sub_t1w_datafile = sub_t1w_datadir / "T1w_acpc_dc_restore.nii.gz" + # Write subject data file + with open(sub_t1w_datafile, "w") as f: + f.write("placeholder") + + # Warp data + # Set subject data directory + sub_warp_datadir = subdir / "MNINonLinear" / "xfms" + # Create subject data directory + sub_warp_datadir.mkdir(parents=True) + # Set subject data file + sub_warp_datafile = sub_warp_datadir / "standard2acpc_dc.nii.gz" + # Write subject data file + with open(sub_warp_datafile, "w") as f: + f.write("placeholder") + + # BOLD data + for task, phase_encoding in product( [ "REST1", "REST2", @@ -49,32 +71,31 @@ if __name__ == "__main__": else: new_task = f"tfMRI_{task}" # Set subject data directory - sub_datadir = ( + sub_bold_datadir = ( subdir / "MNINonLinear" / "Results" / f"{new_task}_{phase_encoding}" ) # Create subject data directory - sub_datadir.mkdir(parents=True) + sub_bold_datadir.mkdir(parents=True) # Set subject data file - sub_datafile = ( - sub_datadir - / f"{new_task}_{phase_encoding}.nii.gz" + sub_bold_datafile = ( + sub_bold_datadir / f"{new_task}_{phase_encoding}.nii.gz" ) # Create subject data file - with open(sub_datafile, "w") as f: + with open(sub_bold_datafile, "w") as f: f.write("placeholder") if "REST" in task: # Set subject data file with ICA+FIX - sub_datafile = ( - sub_datadir + sub_bold_datafile = ( + sub_bold_datadir / f"{new_task}_{phase_encoding}_hp2000_clean.nii.gz" ) # Create subject data file with ICA+FIX - with open(sub_datafile, "w") as f: + with open(sub_bold_datafile, "w") as f: f.write("placeholder") # Save datalad dataset -- 2.52.0