Skip to content

Commit 83bb10e

Browse files
authored
Merge pull request #811 from mgxd/enh/cifti-interfaces
ENH: Port GIFTI/CIFTI interfaces from fMRIPrep
2 parents c2d46e1 + f4ac201 commit 83bb10e

File tree

11 files changed

+914
-5
lines changed

11 files changed

+914
-5
lines changed

docs/requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ furo ~= 2022.4.7
33
nipype >= 1.5.1
44
traits < 6.4
55
packaging
6+
pytest
67
sphinx ~= 4.2
78
sphinxcontrib-apidoc
89
sphinxcontrib-napoleon

niworkflows/interfaces/conftest.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
from pathlib import Path
2+
from shutil import copytree
3+
4+
import pytest
5+
6+
try:
7+
from contextlib import chdir as _chdir
8+
except ImportError: # PY310
9+
import os
10+
from contextlib import contextmanager
11+
12+
@contextmanager # type: ignore
13+
def _chdir(path):
14+
cwd = os.getcwd()
15+
os.chdir(path)
16+
try:
17+
yield
18+
finally:
19+
os.chdir(cwd)
20+
21+
22+
@pytest.fixture(scope="module")
23+
def data_dir():
24+
return Path(__file__).parent / "tests" / "data"
25+
26+
27+
@pytest.fixture(autouse=True)
28+
def _docdir(request, tmp_path):
29+
# Trigger ONLY for the doctests.
30+
doctest_plugin = request.config.pluginmanager.getplugin("doctest")
31+
if isinstance(request.node, doctest_plugin.DoctestItem):
32+
copytree(Path(__file__).parent / "tests" / "data", tmp_path, dirs_exist_ok=True)
33+
34+
# Chdir only for the duration of the test.
35+
with _chdir(tmp_path):
36+
yield
37+
38+
else:
39+
# For normal tests, we have to yield, since this is a yield-fixture.
40+
yield

niworkflows/interfaces/surf.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,66 @@ def _run_interface(self, runtime):
558558
return runtime
559559

560560

561+
class CreateSurfaceROIInputSpec(TraitedSpec):
562+
subject_id = traits.Str(desc='subject ID')
563+
hemisphere = traits.Enum(
564+
"L",
565+
"R",
566+
mandatory=True,
567+
desc='hemisphere',
568+
)
569+
thickness_file = File(exists=True, mandatory=True, desc='input GIFTI file')
570+
571+
572+
class CreateSurfaceROIOutputSpec(TraitedSpec):
573+
roi_file = File(desc='output GIFTI file')
574+
575+
576+
class CreateSurfaceROI(SimpleInterface):
577+
"""Prepare GIFTI shape file for use in cortical masking
578+
579+
Distilled from the FreeSurfer2CaretConvertAndRegisterNonlinear.sh script in
580+
DCAN-HCP PostFreeSurfer scripts (as of commit 9291324). The relevant lines
581+
are 277-290.
582+
"""
583+
584+
input_spec = CreateSurfaceROIInputSpec
585+
output_spec = CreateSurfaceROIOutputSpec
586+
587+
def _run_interface(self, runtime):
588+
subject, hemi = self.inputs.subject_id, self.inputs.hemisphere
589+
if not isdefined(subject):
590+
subject = 'sub-XYZ'
591+
img = nb.GiftiImage.from_filename(self.inputs.thickness_file)
592+
# wb_command -set-structure (L282)
593+
img.meta["AnatomicalStructurePrimary"] = {'L': 'CortexLeft', 'R': 'CortexRight'}[hemi]
594+
darray = img.darrays[0]
595+
# wb_command -set-map-names (L284)
596+
meta = darray.meta
597+
meta['Name'] = f"{subject}_{hemi}_ROI"
598+
# wb_command -metric-palette calls (L285, L289) have no effect on ROI files
599+
600+
# Compiling an odd sequence of math operations (L283, L288, L290) that work out to:
601+
# wb_command -metric-math "abs(var * -1) > 0"
602+
roi = np.abs(darray.data) > 0
603+
604+
darray = nb.gifti.GiftiDataArray(
605+
roi,
606+
intent=darray.intent,
607+
datatype=darray.datatype,
608+
encoding=darray.encoding,
609+
endian=darray.endian,
610+
coordsys=darray.coordsys,
611+
ordering=darray.ind_ord,
612+
meta=meta,
613+
)
614+
615+
out_filename = os.path.join(runtime.cwd, f"{subject}.{hemi}.roi.native.shape.gii")
616+
img.to_filename(out_filename)
617+
self._results["roi_file"] = out_filename
618+
return runtime
619+
620+
561621
def normalize_surfs(in_file, transform_file, newpath=None):
562622
"""
563623
Re-center GIFTI coordinates to fit align to native T1w space.

niworkflows/interfaces/tests/data/bold.nii.gz

Whitespace-only changes.

niworkflows/interfaces/tests/data/lh.bold.func.gii

Whitespace-only changes.

niworkflows/interfaces/tests/data/lh.midthickness.surf.gii

Whitespace-only changes.

niworkflows/interfaces/tests/data/lh.pial.surf.gii

Whitespace-only changes.

niworkflows/interfaces/tests/data/lh.roi.shape.gii

Whitespace-only changes.

niworkflows/interfaces/tests/data/lh.white.surf.gii

Whitespace-only changes.

0 commit comments

Comments
 (0)