Add aomic masks #179

Merged
LeSasse merged 4 commits from add_aomic_masks into main 2023-02-27 11:03:38 +00:00
10 changed files with 190 additions and 64 deletions

View file

@ -40,6 +40,9 @@ Enhancements
- Add support for nilearn computed masks (``compute_epi_mask``, ``compute_brain_mask``, ``compute_background_mask``, - Add support for nilearn computed masks (``compute_epi_mask``, ``compute_brain_mask``, ``compute_background_mask``,
synchon commented 2023-01-30 10:43:28 +00:00 (Migrated from github.com)

Just to follow the naming convention: Add fMRIPrep ...

Just to follow the naming convention: Add fMRIPrep ...
synchon commented 2023-01-30 10:43:30 +00:00 (Migrated from github.com)

. at the end.

`.` at the end.
LeSasse commented 2023-01-30 10:48:55 +00:00 (Migrated from github.com)

oops yeah always get that wrong

oops yeah always get that wrong
``fetch_icbm152_brain_gm_mask``) (:gh:`175` by `Fede Raimondo`_). ``fetch_icbm152_brain_gm_mask``) (:gh:`175` by `Fede Raimondo`_).
- Add fMRIPrep brain masks to the datagrabber patterns for all datagrabbers in the aomic sub-package
(:gh:`177` by `Leonard Sasse`_).
Bugs Bugs
~~~~ ~~~~

View file

@ -7,7 +7,7 @@
# License: AGPL # License: AGPL
from pathlib import Path from pathlib import Path
from typing import Union from typing import Union, Dict
from junifer.datagrabber import PatternDataladDataGrabber from junifer.datagrabber import PatternDataladDataGrabber
@ -34,7 +34,9 @@ class DataladAOMICID1000(PatternDataladDataGrabber):
types = [ types = [
"BOLD", "BOLD",
"BOLD_confounds", "BOLD_confounds",
"BOLD_mask",
"T1w", "T1w",
"T1w_mask",
"probseg_CSF", "probseg_CSF",
"probseg_GM", "probseg_GM",
"probseg_WM", "probseg_WM",
@ -52,11 +54,22 @@ class DataladAOMICID1000(PatternDataladDataGrabber):
"sub-{subject}_task-moviewatching_" "sub-{subject}_task-moviewatching_"
"desc-confounds_regressors.tsv" "desc-confounds_regressors.tsv"
), ),
"BOLD_mask": (
"derivatives/fmriprep/sub-{subject}/func/"
"sub-{subject}_task-moviewatching_"
"space-MNI152NLin2009cAsym_"
"desc-brain_mask.nii.gz"
),
"T1w": ( "T1w": (
"derivatives/fmriprep/sub-{subject}/anat/" "derivatives/fmriprep/sub-{subject}/anat/"
"sub-{subject}_space-MNI152NLin2009cAsym_" "sub-{subject}_space-MNI152NLin2009cAsym_"
"desc-preproc_T1w.nii.gz" "desc-preproc_T1w.nii.gz"
), ),
"T1w_mask": (
"derivatives/fmriprep/sub-{subject}/anat/"
"sub-{subject}_space-MNI152NLin2009cAsym_"
"desc-brain_mask.nii.gz"
),
"probseg_CSF": ( "probseg_CSF": (
"derivatives/fmriprep/sub-{subject}/anat/" "derivatives/fmriprep/sub-{subject}/anat/"
"sub-{subject}_space-MNI152NLin2009cAsym_label-" "sub-{subject}_space-MNI152NLin2009cAsym_label-"
@ -88,3 +101,22 @@ class DataladAOMICID1000(PatternDataladDataGrabber):
replacements=replacements, replacements=replacements,
confounds_format="fmriprep", confounds_format="fmriprep",
) )
def get_item(self, subject: str) -> Dict:
"""Index one element in the dataset.
Parameters
----------
subject : str
The subject ID.
Returns
-------
out : dict
Dictionary of paths for each type of data required for the
specified element.
"""
out = super().get_item(subject=subject)
out["BOLD"]["mask_item"] = "BOLD_mask"
out["T1w"]["mask_item"] = "T1w_mask"
return out

View file

@ -41,7 +41,9 @@ class DataladAOMICPIOP1(PatternDataladDataGrabber):
types = [ types = [
"BOLD", "BOLD",
"BOLD_confounds", "BOLD_confounds",
"BOLD_mask",
"T1w", "T1w",
"T1w_mask",
"probseg_CSF", "probseg_CSF",
"probseg_GM", "probseg_GM",
"probseg_WM", "probseg_WM",
@ -83,11 +85,21 @@ class DataladAOMICPIOP1(PatternDataladDataGrabber):
"sub-{subject}_task-{task}_" "sub-{subject}_task-{task}_"
"desc-confounds_regressors.tsv" "desc-confounds_regressors.tsv"
), ),
"BOLD_mask": (
"derivatives/fmriprep/sub-{subject}/func/"
"sub-{subject}_task-{task}_"
"space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz"
),
"T1w": ( "T1w": (
"derivatives/fmriprep/sub-{subject}/anat/" "derivatives/fmriprep/sub-{subject}/anat/"
"sub-{subject}_space-MNI152NLin2009cAsym_" "sub-{subject}_space-MNI152NLin2009cAsym_"
"desc-preproc_T1w.nii.gz" "desc-preproc_T1w.nii.gz"
), ),
"T1w_mask": (
"derivatives/fmriprep/sub-{subject}/anat/"
"sub-{subject}_space-MNI152NLin2009cAsym_"
"desc-brain_mask.nii.gz"
),
"probseg_CSF": ( "probseg_CSF": (
"derivatives/fmriprep/sub-{subject}/anat/" "derivatives/fmriprep/sub-{subject}/anat/"
"sub-{subject}_space-MNI152NLin2009cAsym_label-" "sub-{subject}_space-MNI152NLin2009cAsym_label-"
@ -149,6 +161,8 @@ class DataladAOMICPIOP1(PatternDataladDataGrabber):
new_task = f"{task}_acq-{acq}" new_task = f"{task}_acq-{acq}"
out = super().get_item(subject=subject, task=new_task) out = super().get_item(subject=subject, task=new_task)
out["BOLD"]["mask_item"] = "BOLD_mask"
out["T1w"]["mask_item"] = "T1w_mask"
return out return out
def get_elements(self) -> List: def get_elements(self) -> List:

View file

@ -7,7 +7,7 @@
# License: AGPL # License: AGPL
from pathlib import Path from pathlib import Path
from typing import List, Union from typing import List, Union, Dict
from junifer.datagrabber import PatternDataladDataGrabber from junifer.datagrabber import PatternDataladDataGrabber
@ -40,7 +40,9 @@ class DataladAOMICPIOP2(PatternDataladDataGrabber):
types = [ types = [
"BOLD", "BOLD",
"BOLD_confounds", "BOLD_confounds",
"BOLD_mask",
"T1w", "T1w",
"T1w_mask",
"probseg_CSF", "probseg_CSF",
"probseg_GM", "probseg_GM",
"probseg_WM", "probseg_WM",
@ -80,11 +82,21 @@ class DataladAOMICPIOP2(PatternDataladDataGrabber):
"sub-{subject}_task-{task}_acq-seq_" "sub-{subject}_task-{task}_acq-seq_"
"desc-confounds_regressors.tsv" "desc-confounds_regressors.tsv"
), ),
"BOLD_mask": (
"derivatives/fmriprep/sub-{subject}/func/"
"sub-{subject}_task-{task}_acq-seq_space"
"-MNI152NLin2009cAsym_desc-brain_mask.nii.gz"
),
"T1w": ( "T1w": (
"derivatives/fmriprep/sub-{subject}/anat/" "derivatives/fmriprep/sub-{subject}/anat/"
"sub-{subject}_space-MNI152NLin2009cAsym_" "sub-{subject}_space-MNI152NLin2009cAsym_"
"desc-preproc_T1w.nii.gz" "desc-preproc_T1w.nii.gz"
), ),
"T1w_mask": (
"derivatives/fmriprep/sub-{subject}/anat/"
"sub-{subject}_space-MNI152NLin2009cAsym_"
"desc-brain_mask.nii.gz"
),
"probseg_CSF": ( "probseg_CSF": (
"derivatives/fmriprep/sub-{subject}/anat/" "derivatives/fmriprep/sub-{subject}/anat/"
"sub-{subject}_space-MNI152NLin2009cAsym_label-" "sub-{subject}_space-MNI152NLin2009cAsym_label-"
@ -127,3 +139,25 @@ class DataladAOMICPIOP2(PatternDataladDataGrabber):
""" """
all_elements = super().get_elements() all_elements = super().get_elements()
return [x for x in all_elements if x[1] in self.tasks] return [x for x in all_elements if x[1] in self.tasks]
def get_item(self, subject: str, task: str) -> Dict:
"""Index one element in the dataset.
Parameters
----------
subject : str
The subject ID.
task : str
The task to get. Possible values are:
{"restingstate", "stopsignal", "emomatching", "workingmemory"}
Returns
-------
out : dict
Dictionary of paths for each type of data required for the
specified element.
"""
out = super().get_item(subject=subject, task=task)
out["BOLD"]["mask_item"] = "BOLD_mask"
out["T1w"]["mask_item"] = "T1w_mask"
return out

View file

@ -51,6 +51,9 @@ def test_aomic1000_datagrabber() -> None:
assert out["BOLD_confounds"]["path"].exists() assert out["BOLD_confounds"]["path"].exists()
assert out["BOLD_confounds"]["path"].is_file() assert out["BOLD_confounds"]["path"].is_file()
# assert BOLD_mask
assert out["BOLD_mask"]["path"].exists()
# asserts type "T1w" # asserts type "T1w"
assert "T1w" in out assert "T1w" in out
@ -63,6 +66,9 @@ def test_aomic1000_datagrabber() -> None:
assert out["T1w"]["path"].exists() assert out["T1w"]["path"].exists()
assert out["T1w"]["path"].is_file() assert out["T1w"]["path"].is_file()
# asserts T1w_mask
assert out["T1w_mask"]["path"].exists()
# asserts type "probseg_CSF" # asserts type "probseg_CSF"
assert "probseg_CSF" in out assert "probseg_CSF" in out

View file

@ -66,6 +66,9 @@ def test_aomic_piop1_datagrabber() -> None:
assert out["BOLD_confounds"]["path"].exists() assert out["BOLD_confounds"]["path"].exists()
assert out["BOLD_confounds"]["path"].is_file() assert out["BOLD_confounds"]["path"].is_file()
# assert BOLD_mask
assert out["BOLD_mask"]["path"].exists()
# asserts type "T1w" # asserts type "T1w"
assert "T1w" in out assert "T1w" in out
@ -78,6 +81,9 @@ def test_aomic_piop1_datagrabber() -> None:
assert out["T1w"]["path"].exists() assert out["T1w"]["path"].exists()
assert out["T1w"]["path"].is_file() assert out["T1w"]["path"].is_file()
# asserts T1w_mask
assert out["T1w_mask"]["path"].exists()
# asserts type "probseg_CSF" # asserts type "probseg_CSF"
assert "probseg_CSF" in out assert "probseg_CSF" in out

View file

@ -35,7 +35,6 @@ def test_aomic_piop2_datagrabber() -> None:
test_element = all_elements[0] test_element = all_elements[0]
sub, task = test_element sub, task = test_element
out = dg[test_element] out = dg[test_element]
# asserts type "BOLD" # asserts type "BOLD"
@ -62,6 +61,9 @@ def test_aomic_piop2_datagrabber() -> None:
assert out["BOLD_confounds"]["path"].exists() assert out["BOLD_confounds"]["path"].exists()
assert out["BOLD_confounds"]["path"].is_file() assert out["BOLD_confounds"]["path"].is_file()
# assert BOLD_mask
assert out["BOLD_mask"]["path"].exists()
# asserts type "T1w" # asserts type "T1w"
assert "T1w" in out assert "T1w" in out
@ -74,6 +76,9 @@ def test_aomic_piop2_datagrabber() -> None:
assert out["T1w"]["path"].exists() assert out["T1w"]["path"].exists()
assert out["T1w"]["path"].is_file() assert out["T1w"]["path"].is_file()
# asserts T1w_mask
assert out["T1w_mask"]["path"].exists()
# asserts type "probseg_CSF" # asserts type "probseg_CSF"
assert "probseg_CSF" in out assert "probseg_CSF" in out

View file

@ -1,3 +1,5 @@
"""Create a testing dataset for the DataladAOMICID1000 pattern datagrabber."""
# Authors: Federico Raimondo <f.raimondo@fz-juelich.de> # Authors: Federico Raimondo <f.raimondo@fz-juelich.de>
# Vera Komeyer <v.komeyer@fz-juelich.de> # Vera Komeyer <v.komeyer@fz-juelich.de>
# Xuan Li <xu.li@fz-juelich.de> # Xuan Li <xu.li@fz-juelich.de>
@ -8,7 +10,7 @@ from pathlib import Path
import datalad.api as dl import datalad.api as dl
# repo has to be created on gin manually beforehand if not owner # repo has to be created on gin manually beforehand if not owner
dst = 'git@gin.g-node.org:/juaml/datalad-example-aomic1000.git' dst = "git@gin.g-node.org:/juaml/datalad-example-aomic1000.git"
# Use this if you create repo directly when pushing (see below) # Use this if you create repo directly when pushing (see below)
# dst_api = 'git@gin.g-node.org' # dst_api = 'git@gin.g-node.org'
@ -19,57 +21,81 @@ with TemporaryDirectory() as tmpdir_name:
tmpdir = Path(tmpdir_name) tmpdir = Path(tmpdir_name)
ds = dl.create(tmpdir) # type: ignore ds = dl.create(tmpdir) # type: ignore
base_dir = tmpdir / 'derivatives' base_dir = tmpdir / "derivatives"
base_dir.mkdir(exist_ok=True, parents=True) base_dir.mkdir(exist_ok=True, parents=True)
for dtype in ['dwipreproc', 'fmriprep']: for dtype in ["dwipreproc", "fmriprep"]:
dtype_dir = base_dir / dtype dtype_dir = base_dir / dtype
dtype_dir.mkdir() dtype_dir.mkdir()
for i_sub in range(1, 10): for i_sub in range(1, 10):
t_sub = f'sub-{i_sub:04d}' t_sub = f"sub-{i_sub:04d}"
sub_dir = dtype_dir / t_sub sub_dir = dtype_dir / t_sub
sub_dir.mkdir() sub_dir.mkdir()
if dtype == 'fmriprep': if dtype == "fmriprep":
for dname in ['func', 'anat']: for dname in ["func", "anat"]:
(sub_dir / dname).mkdir() (sub_dir / dname).mkdir()
fnames = [ fnames = [
(f'anat/{t_sub}_space-MNI152NLin2009cAsym_desc-preproc' (
'_T1w.nii.gz'), f"anat/{t_sub}_space-MNI152NLin2009cAsym_desc-preproc"
(f'anat/{t_sub}_space-MNI152NLin2009cAsym_label-' "_T1w.nii.gz"
'CSF_probseg.nii.gz'), ),
(f'anat/{t_sub}_space-MNI152NLin2009cAsym_label-' (
'GM_probseg.nii.gz'), f"anat/{t_sub}_space-MNI152NLin2009cAsym_label-"
(f'anat/{t_sub}_space-MNI152NLin2009cAsym_label-' "CSF_probseg.nii.gz"
'WM_probseg.nii.gz'), ),
(f'func/{t_sub}_task-moviewatching_space-' (
'MNI152NLin2009cAsym_desc-preproc_bold.nii.gz'), f"anat/{t_sub}_space-MNI152NLin2009cAsym_label-"
(f'func/{t_sub}_task-moviewatching_space-' "GM_probseg.nii.gz"
'MNI152NLin2009cAsym_desc-preproc_bold.json'), ),
(f'func/{t_sub}_task-moviewatching_desc-confounds' (
'_regressors.tsv'), f"anat/{t_sub}_space-MNI152NLin2009cAsym_label-"
(f'func/{t_sub}_task-moviewatching_desc-confounds' "WM_probseg.nii.gz"
'_regressors.json'), ),
(
f"func/{t_sub}_task-moviewatching_space-"
"MNI152NLin2009cAsym_desc-preproc_bold.nii.gz"
),
(
f"func/{t_sub}_task-moviewatching_space-"
"MNI152NLin2009cAsym_desc-preproc_bold.json"
),
(
f"func/{t_sub}_task-moviewatching_desc-confounds"
"_regressors.tsv"
),
(
f"func/{t_sub}_task-moviewatching_desc-confounds"
"_regressors.json"
),
(
f"func/{t_sub}_task-moviewatching_"
"space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz"
),
(
f"anat/{t_sub}_space-MNI152NLin2009cAsym_"
"desc-brain_mask.nii.gz"
),
] ]
elif dtype == 'dwipreproc': elif dtype == "dwipreproc":
dname = 'dwi' dname = "dwi"
(sub_dir / dname).mkdir() (sub_dir / dname).mkdir()
fnames = [ fnames = [
(f'{dname}/{t_sub}_desc-preproc_dwi.nii.gz'), (f"{dname}/{t_sub}_desc-preproc_dwi.nii.gz"),
] ]
for fname in fnames: for fname in fnames:
with open(sub_dir / fname, 'w') as f: with open(sub_dir / fname, "w") as f:
f.write('placeholder') f.write("placeholder")
ds.save(recursive=True) ds.save(recursive=True)
# use this to create the repo automatically, only possible for juaml owner # use this to create the repo automatically, only possible for juaml owner
# ds.create_sibling_gin( # ds.create_sibling_gin(
# (org_name/repo_basename).as_posix(), name='gin', existing='reconfigure', # (org_name/repo_basename).as_posix(), name='gin', existing='reconfigure',
# api=dst_api, access_protocol='ssh') # api=dst_api, access_protocol='ssh')
ds.siblings('add', name='gin', url=dst) ds.siblings("add", name="gin", url=dst)
ds.push(to='gin', force='all') ds.push(to="gin", force="all")

View file

@ -38,6 +38,10 @@ with TemporaryDirectory() as tmpdir_name:
f"anat/{t_sub}_space-MNI152NLin2009cAsym_desc-preproc" f"anat/{t_sub}_space-MNI152NLin2009cAsym_desc-preproc"
"_T1w.nii.gz" "_T1w.nii.gz"
), ),
(
f"anat/{t_sub}_space-MNI152NLin2009cAsym_"
"desc-brain_mask.nii.gz"
),
( (
f"anat/{t_sub}_space-MNI152NLin2009cAsym_label-" f"anat/{t_sub}_space-MNI152NLin2009cAsym_label-"
"CSF_probseg.nii.gz" "CSF_probseg.nii.gz"
@ -62,29 +66,25 @@ with TemporaryDirectory() as tmpdir_name:
] ]
for t in tasks: for t in tasks:
fnames.append( fnames.append(
(
f"func/{t_sub}_task-{t}_space-" f"func/{t_sub}_task-{t}_space-"
"MNI152NLin2009cAsym_desc-preproc_bold.nii.gz" "MNI152NLin2009cAsym_desc-preproc_bold.nii.gz"
) )
)
fnames.append( fnames.append(
(
f"func/{t_sub}_task-{t}_space-" f"func/{t_sub}_task-{t}_space-"
"MNI152NLin2009cAsym_desc-preproc_bold.json" "MNI152NLin2009cAsym_desc-preproc_bold.json"
) )
fnames.append(
f"func/{t_sub}_task-{t}_space-"
"MNI152NLin2009cAsym_desc-brain_mask.nii.gz"
) )
fnames.append( fnames.append(
(
f"func/{t_sub}_task-{t}_desc-confounds" f"func/{t_sub}_task-{t}_desc-confounds"
"_regressors.tsv" "_regressors.tsv"
) )
)
fnames.append( fnames.append(
(
f"func/{t_sub}_task-{t}_desc-confounds" f"func/{t_sub}_task-{t}_desc-confounds"
"_regressors.json" "_regressors.json"
) )
)
elif dtype == "dwipreproc": elif dtype == "dwipreproc":
dname = "dwi" dname = "dwi"

View file

@ -38,6 +38,10 @@ with TemporaryDirectory() as tmpdir_name:
f"anat/{t_sub}_space-MNI152NLin2009cAsym_desc-preproc" f"anat/{t_sub}_space-MNI152NLin2009cAsym_desc-preproc"
"_T1w.nii.gz" "_T1w.nii.gz"
), ),
(
f"anat/{t_sub}_space-MNI152NLin2009cAsym"
"_desc-brain_mask.nii.gz"
),
( (
f"anat/{t_sub}_space-MNI152NLin2009cAsym_label-" f"anat/{t_sub}_space-MNI152NLin2009cAsym_label-"
"CSF_probseg.nii.gz" "CSF_probseg.nii.gz"
@ -60,29 +64,25 @@ with TemporaryDirectory() as tmpdir_name:
] ]
for t in tasks: for t in tasks:
fnames.append( fnames.append(
(
f"func/{t_sub}_task-{t}_space-" f"func/{t_sub}_task-{t}_space-"
"MNI152NLin2009cAsym_desc-preproc_bold.nii.gz" "MNI152NLin2009cAsym_desc-preproc_bold.nii.gz"
) )
)
fnames.append( fnames.append(
(
f"func/{t_sub}_task-{t}_space-" f"func/{t_sub}_task-{t}_space-"
"MNI152NLin2009cAsym_desc-preproc_bold.json" "MNI152NLin2009cAsym_desc-preproc_bold.json"
) )
fnames.append(
f"func/{t_sub}_task-{t}_space-"
"MNI152NLin2009cAsym_desc-brain_mask.nii.gz"
) )
fnames.append( fnames.append(
(
f"func/{t_sub}_task-{t}_desc-confounds" f"func/{t_sub}_task-{t}_desc-confounds"
"_regressors.tsv" "_regressors.tsv"
) )
)
fnames.append( fnames.append(
(
f"func/{t_sub}_task-{t}_desc-confounds" f"func/{t_sub}_task-{t}_desc-confounds"
"_regressors.json" "_regressors.json"
) )
)
elif dtype == "dwipreproc": elif dtype == "dwipreproc":
dname = "dwi" dname = "dwi"