Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ENH: Add MSMSulc #313

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions nibabies/cli/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,12 @@ def _slice_time_ref(value, parser):
dest="hires",
help="disable sub-millimeter (hires) reconstruction",
)
g_surfs.add_argument(
"--no-msm",
action="store_false",
dest="run_msmsulc",
help="Disable Multimodal Surface Matching surface registration.",
)
g_surfs_xor = g_surfs.add_mutually_exclusive_group()
g_surfs_xor.add_argument(
"--cifti-output",
Expand Down
8 changes: 8 additions & 0 deletions nibabies/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,8 @@ class workflow(_Config):
"""Threshold for DVARS."""
regressors_fd_th = None
"""Threshold for :abbr:`FD (frame-wise displacement)`."""
run_msmsulc = False
"""Run Multimodal Surface Matching surface registration."""
run_reconall = True
"""Run FreeSurfer's surface reconstruction."""
skull_strip_fixed_seed = False
Expand Down Expand Up @@ -597,6 +599,12 @@ class workflow(_Config):
"""Run *fieldmap-less* susceptibility-derived distortions estimation
in the absence of any alternatives."""

@classmethod
def init(cls):
# Avoid additional runtime if not required
if not cls.cifti_output:
cls.run_msmsulc = False


class loggers:
"""Keep loggers easily accessible (see :py:func:`init`)."""
Expand Down
5 changes: 3 additions & 2 deletions nibabies/workflows/anatomical/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ def init_infant_anat_wf(
freesurfer: bool,
hires: bool | None,
longitudinal: bool,
msm_sulc: bool,
omp_nthreads: int,
output_dir: str | Path,
segmentation_atlases: str | Path | None,
Expand Down Expand Up @@ -486,7 +487,7 @@ def init_infant_anat_wf(
mcribs_dir=str(config.execution.mcribs_dir), # Needed to preserve runs
)
# M-CRIB-S to dHCP42week (32k)
sphere_reg_wf = init_mcribs_sphere_reg_wf()
sphere_reg_wf = init_mcribs_sphere_reg_wf(sloppy=sloppy, msm_sulc=msm_sulc)

# fmt:off
wf.connect([
Expand All @@ -505,7 +506,7 @@ def init_infant_anat_wf(
from smriprep.workflows.surfaces import init_sphere_reg_wf

# fsaverage to fsLR
sphere_reg_wf = init_sphere_reg_wf()
sphere_reg_wf = init_sphere_reg_wf(msm_sulc=msm_sulc)

# fmt:off
wf.connect([
Expand Down
53 changes: 43 additions & 10 deletions nibabies/workflows/anatomical/surfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,19 +202,22 @@ def init_mcribs_surface_recon_wf(
return wf


def init_mcribs_sphere_reg_wf(*, name="mcribs_sphere_reg_wf"):
def init_mcribs_sphere_reg_wf(
*, msm_sulc: bool = False, sloppy: bool = False, name="mcribs_sphere_reg_wf"
):
"""
Generate GIFTI registration sphere files from MCRIBS template to dHCP42 (32k).

TODO: Clarify any distinction with fsLR
"""
from smriprep.interfaces.surf import FixGiftiMetadata
from smriprep.interfaces.workbench import SurfaceSphereProjectUnproject
from smriprep.workflows.surfaces import init_msm_sulc_wf

workflow = LiterateWorkflow(name=name)

inputnode = pe.Node(
niu.IdentityInterface(["subjects_dir", "subject_id"]),
niu.IdentityInterface(["subjects_dir", "subject_id", "sulc"]),
name="inputnode",
)
outputnode = pe.Node(
Expand All @@ -228,14 +231,16 @@ def init_mcribs_sphere_reg_wf(*, name="mcribs_sphere_reg_wf"):
run_without_submitting=True,
)

get_surfaces = pe.Node(nio.FreeSurferSource(), name="get_surfaces")

# Via FreeSurfer2CaretConvertAndRegisterNonlinear.sh#L270-L273
#
# See https://github.com/DCAN-Labs/DCAN-HCP/tree/9291324
sphere_gii = pe.MapNode(
fs.MRIsConvert(out_datatype="gii"), iterfield="in_file", name="sphere_gii"
sphere_reg_gii = pe.MapNode(
fs.MRIsConvert(out_datatype="gii"), iterfield="in_file", name="sphere_reg_gii"
)

fix_meta = pe.MapNode(FixGiftiMetadata(), iterfield="in_file", name="fix_meta")
fix_reg_meta = pe.MapNode(FixGiftiMetadata(), iterfield="in_file", name="fix_reg_meta")

# load template files
atlases = load_resource('atlases')
Expand Down Expand Up @@ -266,14 +271,42 @@ def init_mcribs_sphere_reg_wf(*, name="mcribs_sphere_reg_wf"):
('subjects_dir', 'subjects_dir'),
('subject_id', 'subject_id'),
]),
(get_spheres, sphere_gii, [(('out', _sorted_by_basename), 'in_file')]),
(sphere_gii, fix_meta, [('converted', 'in_file')]),
(fix_meta, project_unproject, [('out_file', 'sphere_in')]),
(sphere_gii, outputnode, [('converted', 'sphere_reg')]),
(project_unproject, outputnode, [('sphere_out', 'sphere_reg_fsLR')]),
(inputnode, get_surfaces, [
('subjects_dir', 'subjects_dir'),
('subject_id', 'subject_id'),
]),
(get_spheres, sphere_reg_gii, [(('out', _sorted_by_basename), 'in_file')]),
(sphere_reg_gii, fix_reg_meta, [('converted', 'in_file')]),
(fix_reg_meta, project_unproject, [('out_file', 'sphere_in')]),
(sphere_reg_gii, outputnode, [('converted', 'sphere_reg')]),
])
# fmt:on

if not msm_sulc:
workflow.connect(project_unproject, 'sphere_out', outputnode, 'sphere_reg_fsLR')
return workflow

sphere_gii = pe.MapNode(
fs.MRIsConvert(out_datatype='gii'),
iterfield='in_file',
name='sphere_gii',
)
fix_sphere_meta = pe.MapNode(
FixGiftiMetadata(),
iterfield='in_file',
name='fix_sphere_meta',
)
msm_sulc_wf = init_msm_sulc_wf(sloppy=sloppy)
# fmt:off
workflow.connect([
(get_surfaces, sphere_gii, [(('sphere', _sorted_by_basename), 'in_file')]),
(sphere_gii, fix_sphere_meta, [('converted', 'in_file')]),
(fix_sphere_meta, msm_sulc_wf, [('out_file', 'inputnode.sphere')]),
(inputnode, msm_sulc_wf, [('sulc', 'inputnode.sulc')]),
(project_unproject, msm_sulc_wf, [('sphere_out', 'inputnode.sphere_reg_fsLR')]),
(msm_sulc_wf, outputnode, [('outputnode.sphere_reg_fsLR', 'sphere_reg_fsLR')]),
])
# fmt:on
return workflow


Expand Down
1 change: 1 addition & 0 deletions nibabies/workflows/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,7 @@ def init_single_subject_wf(
freesurfer=config.workflow.run_reconall,
hires=config.workflow.hires,
longitudinal=config.workflow.longitudinal,
msm_sulc=config.workflow.run_msmsulc,
omp_nthreads=config.nipype.omp_nthreads,
output_dir=nibabies_dir,
segmentation_atlases=config.execution.segmentation_atlases_dir,
Expand Down