Skip to content

Commit 28c6731

Browse files
authored
Merge branch 'develop' into fix/check_s3
2 parents 7469a36 + c72d516 commit 28c6731

File tree

14 files changed

+1273
-648
lines changed

14 files changed

+1273
-648
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3535
- Functionality to convert `space-T1w_desc-loose_brain_mask` and `space-T1w_desc-tight_brain_mask` into generic brain mask `space-T1w_desc-brain_mask` to use in brain extraction nodeblock downstream.
3636
- `desc-ABCDpreproc_T1w` to the outputs
3737
- `bc` to `lite` container images.
38+
- Robust method to classify `fmap` types reading in the json metadata during workflow build process.
3839
- validation node to match the pixdim4 of CPAC processed bold outputs with the original raw bold sources.
3940

4041
### Changed

CPAC/anat_preproc/anat_preproc.py

Lines changed: 103 additions & 205 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
fsl_aff_to_rigid,
2929
fslmaths_command,
3030
mri_convert,
31-
normalize_wmparc,
3231
pad,
3332
VolumeRemoveIslands,
3433
wb_command,
@@ -696,13 +695,15 @@ def afni_brain_connector(wf, cfg, strat_pool, pipe_num, opt):
696695

697696
wf.connect(anat_skullstrip, "out_file", anat_brain_mask, "in_file_a")
698697

698+
outputs = {}
699+
699700
if strat_pool.check_rpool("desc-preproc_T1w"):
700701
outputs = {"space-T1w_desc-brain_mask": (anat_brain_mask, "out_file")}
701702

702703
elif strat_pool.check_rpool("desc-preproc_T2w"):
703704
outputs = {"space-T2w_desc-brain_mask": (anat_brain_mask, "out_file")}
704705

705-
return (wf, outputs)
706+
return wf, outputs
706707

707708

708709
def fsl_brain_connector(wf, cfg, strat_pool, pipe_num, opt):
@@ -1322,22 +1323,29 @@ def freesurfer_fsl_brain_connector(wf, cfg, strat_pool, pipe_num, opt):
13221323

13231324
wf.connect(combine_mask, "out_file", binarize_combined_mask, "in_file")
13241325

1325-
if opt == "FreeSurfer-BET-Tight":
1326-
outputs = {
1327-
"space-T1w_desc-tight_brain_mask": (
1328-
binarize_combined_mask,
1329-
"out_file",
1330-
)
1331-
}
1332-
elif opt == "FreeSurfer-BET-Loose":
1333-
outputs = {
1334-
"space-T1w_desc-loose_brain_mask": (
1335-
binarize_combined_mask,
1336-
"out_file",
1337-
)
1338-
}
1326+
# CCS brain mask is in FS space, transfer it back to native T1 space
1327+
match_fov_ccs_brain_mask = pe.Node(
1328+
interface=fsl.FLIRT(), name=f"match_fov_CCS_brain_mask_{node_id}"
1329+
)
1330+
match_fov_ccs_brain_mask.inputs.apply_xfm = True
1331+
match_fov_ccs_brain_mask.inputs.uses_qform = True
1332+
match_fov_ccs_brain_mask.inputs.interp = "nearestneighbour"
13391333

1340-
return (wf, outputs)
1334+
node, out = strat_pool.get_data("pipeline-fs_raw-average")
1335+
convert_fs_T1_to_nifti = pe.Node(
1336+
Function(
1337+
input_names=["in_file"], output_names=["out_file"], function=mri_convert
1338+
),
1339+
name=f"convert_fs_T1_to_nifti_for_ccs_{node_id}",
1340+
)
1341+
wf.connect(node, out, convert_fs_T1_to_nifti, "in_file")
1342+
wf.connect(
1343+
convert_fs_T1_to_nifti, "out_file", match_fov_ccs_brain_mask, "reference"
1344+
)
1345+
1346+
wf.connect(binarize_combined_mask, "out_file", match_fov_ccs_brain_mask, "in_file")
1347+
1348+
return wf, {"space-T1w_desc-brain_mask": (match_fov_ccs_brain_mask, "out_file")}
13411349

13421350

13431351
def mask_T2(wf_name="mask_T2"):
@@ -1408,9 +1416,8 @@ def mask_T2(wf_name="mask_T2"):
14081416
)
14091417
def anatomical_init(wf, cfg, strat_pool, pipe_num, opt=None):
14101418
if opt not in anatomical_init.option_val:
1411-
raise ValueError(
1412-
f"\n[!] Error: Invalid option for deoblique: {opt}. \nExpected one of {anatomical_init.option_val}"
1413-
)
1419+
msg = f"\n[!] Error: Invalid option for deoblique: {opt}. \nExpected one of {anatomical_init.option_val}"
1420+
raise ValueError(msg)
14141421

14151422
if opt == "warp":
14161423
anat_deoblique = pe.Node(
@@ -1500,15 +1507,15 @@ def acpc_align_head(wf, cfg, strat_pool, pipe_num, opt=None):
15001507
(
15011508
"desc-head_T1w",
15021509
"desc-preproc_T1w",
1503-
["space-T1w_desc-brain_mask", "space-T1w_desc-brain_mask"],
1510+
"space-T1w_desc-brain_mask",
15041511
),
15051512
"T1w-ACPC-template",
15061513
"T1w-brain-ACPC-template",
15071514
],
15081515
outputs=[
15091516
"desc-head_T1w",
15101517
"desc-preproc_T1w",
1511-
["space-T1w_desc-brain_mask", "space-T1w_desc-brain_mask"],
1518+
"space-T1w_desc-brain_mask",
15121519
"from-T1w_to-ACPC_mode-image_desc-aff2rig_xfm",
15131520
],
15141521
)
@@ -1939,211 +1946,102 @@ def brain_mask_acpc_unet(wf, cfg, strat_pool, pipe_num, opt=None):
19391946
["anatomical_preproc", "run"],
19401947
],
19411948
option_key=["anatomical_preproc", "brain_extraction", "using"],
1942-
option_val="FreeSurfer-Brainmask",
1943-
inputs=[
1944-
"pipeline-fs_raw-average",
1945-
"pipeline-fs_brainmask",
1946-
"freesurfer-subject-dir",
1949+
option_val=[
1950+
"FreeSurfer-ABCD",
1951+
"FreeSurfer-BET-Loose",
1952+
"FreeSurfer-BET-Tight",
1953+
"FreeSurfer-Brainmask",
19471954
],
1948-
outputs=["space-T1w_desc-brain_mask"],
1949-
)
1950-
def brain_mask_freesurfer(wf, cfg, strat_pool, pipe_num, opt=None):
1951-
wf, outputs = freesurfer_brain_connector(wf, cfg, strat_pool, pipe_num, opt)
1952-
1953-
return (wf, outputs)
1954-
1955-
1956-
@nodeblock(
1957-
name="brain_mask_acpc_freesurfer",
1958-
switch=[
1959-
["anatomical_preproc", "brain_extraction", "run"],
1960-
["anatomical_preproc", "run"],
1961-
],
1962-
option_key=["anatomical_preproc", "brain_extraction", "using"],
1963-
option_val="FreeSurfer-Brainmask",
1964-
inputs=[
1965-
"space-T1w_desc-brain_mask",
1966-
"pipeline-fs_raw-average",
1967-
"freesurfer-subject-dir",
1968-
],
1969-
outputs=["space-T1w_desc-acpcbrain_mask"],
1970-
)
1971-
def brain_mask_acpc_freesurfer(wf, cfg, strat_pool, pipe_num, opt=None):
1972-
wf, wf_outputs = freesurfer_brain_connector(wf, cfg, strat_pool, pipe_num, opt)
1973-
1974-
outputs = {"space-T1w_desc-acpcbrain_mask": wf_outputs["space-T1w_desc-brain_mask"]}
1975-
1976-
return (wf, outputs)
1977-
1978-
1979-
@nodeblock(
1980-
name="brain_mask_freesurfer_abcd",
1981-
switch=[
1982-
["anatomical_preproc", "brain_extraction", "run"],
1983-
["anatomical_preproc", "run"],
1984-
],
1985-
option_key=["anatomical_preproc", "brain_extraction", "using"],
1986-
option_val="FreeSurfer-ABCD",
19871955
inputs=[
1988-
["desc-restore_T1w", "desc-preproc_T1w"],
1989-
"pipeline-fs_wmparc",
1990-
"pipeline-fs_raw-average",
1991-
"freesurfer-subject-dir",
1992-
],
1993-
outputs=["space-T1w_desc-brain_mask"],
1994-
)
1995-
def brain_mask_freesurfer_abcd(wf, cfg, strat_pool, pipe_num, opt=None):
1996-
wf, outputs = freesurfer_abcd_brain_connector(wf, cfg, strat_pool, pipe_num, opt)
1997-
1998-
return (wf, outputs)
1999-
2000-
2001-
@nodeblock(
2002-
name="brain_mask_freesurfer_fsl_tight",
2003-
switch=[
2004-
["anatomical_preproc", "brain_extraction", "run"],
2005-
["anatomical_preproc", "run"],
2006-
],
2007-
option_key=["anatomical_preproc", "brain_extraction", "using"],
2008-
option_val="FreeSurfer-BET-Tight",
2009-
inputs=[
2010-
"pipeline-fs_brainmask",
2011-
"pipeline-fs_T1",
2012-
"pipeline-fs_raw-average",
2013-
"freesurfer-subject-dir",
1956+
(
1957+
["desc-restore_T1w", "desc-preproc_T1w"],
1958+
"space-T1w_desc-brain_mask",
1959+
"pipeline-fs_T1",
1960+
"pipeline-fs_wmparc",
1961+
"pipeline-fs_raw-average",
1962+
"pipeline-fs_brainmask",
1963+
"freesurfer-subject-dir",
1964+
),
20141965
"T1w-brain-template-mask-ccs",
20151966
"T1w-ACPC-template",
20161967
],
2017-
outputs={
2018-
"space-T1w_desc-brain_mask": {
2019-
"Description": "Brain mask extracted using FreeSurfer-BET-Tight method",
2020-
"Method": "FreeSurfer-BET-Tight",
2021-
"Threshold": "tight",
2022-
}
2023-
},
1968+
outputs={"space-T1w_desc-brain_mask": {}},
20241969
)
2025-
def brain_mask_freesurfer_fsl_tight(wf, cfg, strat_pool, pipe_num, opt=None):
2026-
wf, outputs = freesurfer_fsl_brain_connector(wf, cfg, strat_pool, pipe_num, opt)
2027-
2028-
# Convert the tight brain mask to generic brain mask
2029-
outputs["space-T1w_desc-brain_mask"] = outputs.pop(
2030-
"space-T1w_desc-tight_brain_mask"
2031-
)
2032-
return (wf, outputs)
1970+
def brain_mask_freesurfer(wf, cfg, strat_pool, pipe_num, opt=None):
1971+
assert isinstance(brain_mask_freesurfer.outputs, dict)
1972+
brain_mask_freesurfer.outputs["space-T1w_desc-brain_mask"] = {
1973+
"Description": f"Brain mask extracted using {opt} method",
1974+
"Method": opt,
1975+
}
1976+
match opt:
1977+
case "FreeSurfer-ABCD":
1978+
return freesurfer_abcd_brain_connector(wf, cfg, strat_pool, pipe_num, opt)
1979+
case "FreeSurfer-BET-Loose" | "FreeSurfer-BET-Tight":
1980+
brain_mask_freesurfer.outputs["space-T1w_desc-brain_mask"]["Threshold"] = (
1981+
opt.rsplit("-")[-1].lower()
1982+
)
1983+
return freesurfer_fsl_brain_connector(wf, cfg, strat_pool, pipe_num, opt)
1984+
case "FreeSurfer-Brainmask":
1985+
return freesurfer_brain_connector(wf, cfg, strat_pool, pipe_num, opt)
1986+
return wf, {}
20331987

20341988

20351989
@nodeblock(
2036-
name="brain_mask_acpc_freesurfer_abcd",
1990+
name="brain_mask_acpc_freesurfer",
20371991
switch=[
20381992
["anatomical_preproc", "brain_extraction", "run"],
20391993
["anatomical_preproc", "run"],
20401994
],
20411995
option_key=["anatomical_preproc", "brain_extraction", "using"],
2042-
option_val="FreeSurfer-ABCD",
2043-
inputs=[
2044-
["desc-restore_T1w", "desc-preproc_T1w"],
2045-
"pipeline-fs_wmparc",
2046-
"pipeline-fs_raw-average",
2047-
"freesurfer-subject-dir",
2048-
],
2049-
outputs=["space-T1w_desc-acpcbrain_mask"],
2050-
)
2051-
def brain_mask_acpc_freesurfer_abcd(wf, cfg, strat_pool, pipe_num, opt=None):
2052-
wf, wf_outputs = freesurfer_abcd_brain_connector(wf, cfg, strat_pool, pipe_num, opt)
2053-
2054-
outputs = {"space-T1w_desc-acpcbrain_mask": wf_outputs["space-T1w_desc-brain_mask"]}
2055-
2056-
return (wf, outputs)
2057-
2058-
2059-
@nodeblock(
2060-
name="brain_mask_freesurfer_fsl_loose",
2061-
switch=[
2062-
["anatomical_preproc", "brain_extraction", "run"],
2063-
["anatomical_preproc", "run"],
1996+
option_val=[
1997+
"FreeSurfer-ABCD",
1998+
"FreeSurfer-Brainmask",
1999+
"FreeSurfer-BET-Loose",
2000+
"FreeSurfer-BET-Tight",
20642001
],
2065-
option_key=["anatomical_preproc", "brain_extraction", "using"],
2066-
option_val="FreeSurfer-BET-Loose",
20672002
inputs=[
2068-
"pipeline-fs_brainmask",
2069-
"pipeline-fs_T1",
2070-
"pipeline-fs_raw-average",
2071-
"freesurfer-subject-dir",
2072-
"T1w-brain-template-mask-ccs",
2073-
"T1w-ACPC-template",
2074-
],
2075-
outputs={
2076-
"space-T1w_desc-brain_mask": {
2077-
"Description": "Brain mask extracted using FreeSurfer-BET-Loose method",
2078-
"Method": "FreeSurfer-BET-Loose",
2079-
"Threshold": "loose",
2080-
}
2081-
},
2082-
)
2083-
def brain_mask_freesurfer_fsl_loose(wf, cfg, strat_pool, pipe_num, opt=None):
2084-
wf, outputs = freesurfer_fsl_brain_connector(wf, cfg, strat_pool, pipe_num, opt)
2085-
2086-
# Convert the loose brain mask to generic brain mask
2087-
outputs["space-T1w_desc-brain_mask"] = outputs.pop(
2088-
"space-T1w_desc-loose_brain_mask"
2089-
)
2090-
return (wf, outputs)
2091-
2092-
2093-
@nodeblock(
2094-
name="brain_mask_acpc_freesurfer_fsl_tight",
2095-
switch=[
2096-
["anatomical_preproc", "brain_extraction", "run"],
2097-
["anatomical_preproc", "run"],
2098-
],
2099-
option_key=["anatomical_preproc", "brain_extraction", "using"],
2100-
option_val="FreeSurfer-BET-Tight",
2101-
inputs=[
2102-
"pipeline-fs_brainmask",
2103-
"pipeline-fs_T1",
2104-
"T1w-brain-template-mask-ccs",
2003+
(
2004+
["desc-restore_T1w", "desc-preproc_T1w"],
2005+
"space-T1w_desc-brain_mask",
2006+
"space-T1w_desc-acpcbrain_mask",
2007+
"pipeline-fs_brainmask",
2008+
"pipeline-fs_raw-average",
2009+
"pipeline-fs_T1",
2010+
"pipeline-fs_wmparc",
2011+
"freesurfer-subject-dir",
2012+
),
21052013
"T1w-ACPC-template",
2106-
],
2107-
outputs=["space-T1w_desc-tight_acpcbrain_mask"],
2108-
)
2109-
def brain_mask_acpc_freesurfer_fsl_tight(wf, cfg, strat_pool, pipe_num, opt=None):
2110-
wf, wf_outputs = freesurfer_fsl_brain_connector(wf, cfg, strat_pool, pipe_num, opt)
2111-
2112-
outputs = {
2113-
"space-T1w_desc-tight_acpcbrain_mask": wf_outputs[
2114-
"space-T1w_desc-tight_brain_mask"
2115-
]
2116-
}
2117-
2118-
return (wf, outputs)
2119-
2120-
2121-
@nodeblock(
2122-
name="brain_mask_acpc_freesurfer_fsl_loose",
2123-
switch=[
2124-
["anatomical_preproc", "brain_extraction", "run"],
2125-
["anatomical_preproc", "run"],
2126-
],
2127-
option_key=["anatomical_preproc", "brain_extraction", "using"],
2128-
option_val="FreeSurfer-BET-Loose",
2129-
inputs=[
2130-
"pipeline-fs_brainmask",
2131-
"pipeline-fs_T1",
21322014
"T1w-brain-template-mask-ccs",
2133-
"T1w-ACPC-template",
21342015
],
2135-
outputs=["space-T1w_desc-loose_acpcbrain_mask"],
2016+
outputs={"space-T1w_desc-acpcbrain_mask": {}},
21362017
)
2137-
def brain_mask_acpc_freesurfer_fsl_loose(wf, cfg, strat_pool, pipe_num, opt=None):
2138-
wf, wf_outputs = freesurfer_fsl_brain_connector(wf, cfg, strat_pool, pipe_num, opt)
2139-
2140-
outputs = {
2141-
"space-T1w_desc-loose_acpcbrain_mask": wf_outputs[
2142-
"space-T1w_desc-loose_brain_mask"
2143-
]
2018+
def brain_mask_acpc_freesurfer(wf, cfg, strat_pool, pipe_num, opt=None):
2019+
if opt != strat_pool.get_json("space-T1w_desc-brain_mask").get(
2020+
"CpacVariant", {}
2021+
).get("space-T1w_mask", opt):
2022+
# https://tenor.com/baIhQ.gif
2023+
return wf, {}
2024+
assert isinstance(brain_mask_acpc_freesurfer.outputs, dict)
2025+
outputs = wf_outputs = {}
2026+
key = "space-T1w_desc-brain_mask"
2027+
functions = {
2028+
"FreeSurfer-ABCD": freesurfer_abcd_brain_connector,
2029+
"FreeSurfer-Brainmask": freesurfer_brain_connector,
2030+
"FreeSurfer-BET-Loose": freesurfer_fsl_brain_connector,
2031+
"FreeSurfer-BET-Tight": freesurfer_fsl_brain_connector,
21442032
}
2033+
if opt in ["FreeSurfer-BET-Loose", "FreeSurfer-BET-Tight"]:
2034+
brain_mask_acpc_freesurfer.outputs["space-T1w_desc-acpcbrain_mask"] = {
2035+
"Description": f"Brain mask extracted using {opt} method",
2036+
"Method": opt,
2037+
"Threshold": opt.rsplit("-")[-1].lower(),
2038+
}
2039+
if opt in functions:
2040+
wf, wf_outputs = functions[opt](wf, cfg, strat_pool, pipe_num, opt)
2041+
if key in wf_outputs:
2042+
outputs = {"space-T1w_desc-acpcbrain_mask": wf_outputs[key]}
21452043

2146-
return (wf, outputs)
2044+
return wf, outputs
21472045

21482046

21492047
@nodeblock(

0 commit comments

Comments
 (0)