From 42e06096a26c2e7f2c5dc2c337ba314d7ee44310 Mon Sep 17 00:00:00 2001 From: mathiasg Date: Tue, 1 Feb 2022 20:04:53 -0500 Subject: [PATCH 1/7] FIX: Relabel sub-structures before discarding Addresses problem raised in https://github.com/nipreps/nibabies/issues/149 Initial implementation using a custom `Function`, but this may be worth a proper interface. --- nibabies/workflows/bold/alignment.py | 83 +++++++++++++++------------- 1 file changed, 44 insertions(+), 39 deletions(-) diff --git a/nibabies/workflows/bold/alignment.py b/nibabies/workflows/bold/alignment.py index e88afd12..3f7c7822 100644 --- a/nibabies/workflows/bold/alignment.py +++ b/nibabies/workflows/bold/alignment.py @@ -68,6 +68,11 @@ def init_subcortical_rois_wf(*, name="subcortical_rois_wf"): # name="applywarp_std" # ) + generalize_rois = pe.Node( + niu.Function(function=generalize_labels), + name='generalize_rois', + ) + subcortical_labels = resource_filename( "nibabies", "data/FreeSurferSubcorticalLabelTableLut.txt" ) @@ -78,7 +83,8 @@ def init_subcortical_rois_wf(*, name="subcortical_rois_wf"): # fmt: off workflow.connect([ - (inputnode, refine_bold_rois, [("MNIInfant_aseg", "in_file")]), + (inputnode, generalize_rois, [("MNIInfant_aseg", "in_file")]), + (generalize_rois, refine_bold_rois, [("out", "in_file")]), # (applywarp_tpl, refine_std_rois, [("out_file", "in_file")]), (refine_bold_rois, outputnode, [("out_file", "MNIInfant_rois")]), ]) @@ -352,45 +358,44 @@ def format_agg_rois(rois): return rois[0], rois[1:], ("-add %s " * (len(rois) - 1)).strip() -def drop_labels(in_file): - """Drop non-subcortical labels""" - from pathlib import Path +def generalize_labels(in_file, out_file='aseg.nii.gz'): + """ + Ensure FreeSurfer LUT sub-structures are accounted for, prior to being discarded. + + Parameters + ---------- + in_file : str + Input aseg file + out_file : str + Generalized output aseg file + + Returns + ------- + out_file : str + Generalized output aseg file + """ + import os import nibabel as nb import numpy as np - from niworkflows.interfaces.cifti import _reorient_image - - # FreeSurfer LUT values - expected_labels = { - 8, - 10, - 11, - 12, - 13, - 16, - 17, - 18, - 26, - 28, - 47, - 49, - 50, - 51, - 52, - 53, - 54, - 58, - 60, + + # https://surfer.nmr.mgh.harvard.edu/fswiki/FsTutorial/AnatomicalROI/FreeSurferColorLUT + # v 1.105 + label_subsitutions = { + 16: (173, 174, 175), # brain stem sub-structures + 17: (550, 551, 552, 553, 554, 555, 556, 557, 558), # HighRes Hippocampus (L) + 53: (500, 501, 502, 503, 504, 505, 506, 507, 508), # HighRes Hippocampus (R) } - img = _reorient_image(nb.load(in_file), orientation="LAS") - hdr = img.header - data = np.asanyarray(img.dataobj).astype("int16") - hdr.set_data_dtype("int16") - labels = np.unique(data) - - for label in labels: - if label not in expected_labels: - data[data == label] = 0 - - out_file = str(Path("ROIs.nii.gz").absolute()) - img.__class__(data, img.affine, header=hdr).to_filename(out_file) + + img = nb.load(in_file) + data = np.asarray(img.dataobj) + labels = set(np.unique(data)) + + for target, subs in label_subsitutions.items(): + if set(subs) - labels: + continue + data[np.isin(data, subs)] = target + + nimg = img.__class__(data, img.affine, header=img.header) + out_file = os.path.abspath(out_file) + nimg.to_filename(out_file) return out_file From cd537eee64bccf49df371f094a96b3f3b9edf19f Mon Sep 17 00:00:00 2001 From: mathiasg Date: Wed, 2 Feb 2022 17:17:12 -0500 Subject: [PATCH 2/7] TST: Add test for new interface --- nibabies/interfaces/tests/test_nibabel.py | 43 ++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/nibabies/interfaces/tests/test_nibabel.py b/nibabies/interfaces/tests/test_nibabel.py index 4b40d384..689f30c0 100644 --- a/nibabies/interfaces/tests/test_nibabel.py +++ b/nibabies/interfaces/tests/test_nibabel.py @@ -1,10 +1,12 @@ +import json +from pathlib import Path import uuid import nibabel as nb import numpy as np import pytest -from ..nibabel import MergeROIs +from ..nibabel import MergeROIs, MapLabels @pytest.fixture @@ -25,6 +27,11 @@ def _create_roi(affine, img_data, roi_index): f.unlink() +def create_image(data, filename): + nb.Nifti1Image(data, affine=np.eye(4)).to_filename(str(filename)) + return filename + + # create a slightly off affine bad_affine = np.eye(4) bad_affine[0, -1] = -1 @@ -71,3 +78,37 @@ def test_merge_rois(tmpdir, create_roi, affine, data, roi_index, error, err_mess with pytest.raises(AssertionError) as err: merge.run() assert err_message in str(err.value) + + +DEFAULT_MAPPING = {5: 1, 6: 1, 7: 2} +DEFAULT_INPUT = np.arange(8).reshape(2, 2, 2) +DEFAULT_OUTPUT = np.asarray([0, 1, 2, 3, 4, 1, 1, 2]).reshape(2, 2, 2) + + +@pytest.mark.parametrize( + "data,mapping,tojson,expected", + [ + (DEFAULT_INPUT, DEFAULT_MAPPING, False, DEFAULT_OUTPUT), + (DEFAULT_INPUT, DEFAULT_MAPPING, True, DEFAULT_OUTPUT), + ], +) +def test_map_labels(tmpdir, data, mapping, tojson, expected): + tmpdir.chdir() + in_file = create_image(data, Path("test.nii.gz")) + maplbl = MapLabels(in_file=in_file) + if tojson: + map_file = Path('mapping.json') + map_file.write_text(json.dumps(mapping)) + maplbl.inputs.mappings_file = map_file + else: + maplbl.inputs.mappings = mapping + out_file = maplbl.run().outputs.out_file + + orig = nb.load(in_file).get_fdata() + labels = nb.load(out_file).get_fdata() + assert orig.shape == labels.shape + assert np.all(labels == expected) + + Path(in_file).unlink() + if tojson: + Path(map_file).unlink() From f17315adde3526af4f4a91726e5fba6a9ba1db45 Mon Sep 17 00:00:00 2001 From: mathiasg Date: Wed, 2 Feb 2022 17:18:13 -0500 Subject: [PATCH 3/7] ENH: Add interface for label remapping --- nibabies/interfaces/nibabel.py | 67 ++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/nibabies/interfaces/nibabel.py b/nibabies/interfaces/nibabel.py index d79acf29..9802e6f2 100644 --- a/nibabies/interfaces/nibabel.py +++ b/nibabies/interfaces/nibabel.py @@ -54,6 +54,37 @@ def _run_interface(self, runtime): return runtime +class _MapLabelsInputSpec(BaseInterfaceInputSpec): + in_file = File(exists=True, desc="Segmented NIfTI") + mappings = traits.Dict( + xor=["mappings_file"], + desc="Dictionary of label / replacement label pairs", + ) + mappings_file = File( + exists=True, xor=["mappings"], help="JSON composed of label / replacement label pairs." + ) + + +class _MapLabelsOutputSpec(TraitedSpec): + out_file = File(exists=True, desc="Labeled file") + + +class MapLabels(SimpleInterface): + """Remap discrete labels""" + + input_spec = _MapLabelsInputSpec + output_spec = _MapLabelsOutputSpec + + def _run_interface(self, runtime): + mapping = self.inputs.mappings or _load_int_json(self.inputs.mappings_file) + self._results["out_file"] = _remap_labels( + self.inputs.in_file, + mapping, + newpath=runtime.cwd, + ) + return runtime + + def _dilate(in_file, radius=3, iterations=1, newpath=None): """Dilate (binary) input mask.""" from pathlib import Path @@ -113,3 +144,39 @@ def _merge_rois(in_files, newpath=None): out_file = str((Path(newpath) / "combined.nii.gz").absolute()) img.__class__(data, affine, header).to_filename(out_file) return out_file + + +def _remap_labels(in_file, mapping, newpath=None): + from pathlib import Path + import nibabel as nb + import numpy as np + + img = nb.load(in_file) + data = np.asarray(img.dataobj) + vec = data.ravel() + + def _relabel(label): + return mapping.get(label, label) + + labels = np.unique(vec) # include all labels present + subs = np.array(list(map(_relabel, labels))) # copy values and substitute mappings + subbed = np.zeros(labels.max() + 1, dtype=data.dtype) + subbed[labels] = subs + out = subbed[vec].reshape(data.shape) + + if newpath is None: + newpath = Path() + out_file = str((Path(newpath) / "relabeled.nii.gz").absolute()) + img.__class__(out, img.affine, header=img.header).to_filename(out_file) + return out_file + + +def _load_int_json(json_file): + import json + + def _keys_as_ints(d): + return {int(k): v for k, v in d.items()} + + with open(json_file) as fp: + data = json.load(fp, object_hook=_keys_as_ints) + return data From 20d05178eb05361c4bf29074aa06d80e21ea5574 Mon Sep 17 00:00:00 2001 From: mathiasg Date: Wed, 2 Feb 2022 17:27:31 -0500 Subject: [PATCH 4/7] ENH: Incoporate new interface into CIFTI workflow --- nibabies/data/FreeSurferLabelRemappings.json | 25 +++++++++ nibabies/workflows/bold/alignment.py | 56 +++----------------- 2 files changed, 33 insertions(+), 48 deletions(-) create mode 100644 nibabies/data/FreeSurferLabelRemappings.json diff --git a/nibabies/data/FreeSurferLabelRemappings.json b/nibabies/data/FreeSurferLabelRemappings.json new file mode 100644 index 00000000..23f29827 --- /dev/null +++ b/nibabies/data/FreeSurferLabelRemappings.json @@ -0,0 +1,25 @@ +{ + "173": 16, + "174": 16, + "175": 16, + + "500": 53, + "501": 53, + "502": 53, + "503": 53, + "504": 53, + "505": 53, + "506": 53, + "507": 53, + "508": 53, + + "550": 17, + "551": 17, + "552": 17, + "553": 17, + "554": 17, + "555": 17, + "556": 17, + "557": 17, + "558": 17 +} diff --git a/nibabies/workflows/bold/alignment.py b/nibabies/workflows/bold/alignment.py index 3f7c7822..2ea4f178 100644 --- a/nibabies/workflows/bold/alignment.py +++ b/nibabies/workflows/bold/alignment.py @@ -34,6 +34,7 @@ def init_subcortical_rois_wf(*, name="subcortical_rois_wf"): Subcortical ROIs in `MNI152NLin6Asym` space """ from templateflow.api import get as get_template + from ...interfaces.nibabel import MapLabels # TODO: Implement BOLD refinement once InfantFS outputs subj/mri/wmparc.mgz # The code is found at @@ -68,9 +69,11 @@ def init_subcortical_rois_wf(*, name="subcortical_rois_wf"): # name="applywarp_std" # ) - generalize_rois = pe.Node( - niu.Function(function=generalize_labels), - name='generalize_rois', + map_labels = pe.Node( + MapLabels( + mappings_file=resource_filename("nibabies", "data/FreeSurferLabelRemappings.json") + ), + name='map_labels', ) subcortical_labels = resource_filename( @@ -83,8 +86,8 @@ def init_subcortical_rois_wf(*, name="subcortical_rois_wf"): # fmt: off workflow.connect([ - (inputnode, generalize_rois, [("MNIInfant_aseg", "in_file")]), - (generalize_rois, refine_bold_rois, [("out", "in_file")]), + (inputnode, map_labels, [("MNIInfant_aseg", "in_file")]), + (map_labels, refine_bold_rois, [("out_file", "in_file")]), # (applywarp_tpl, refine_std_rois, [("out_file", "in_file")]), (refine_bold_rois, outputnode, [("out_file", "MNIInfant_rois")]), ]) @@ -356,46 +359,3 @@ def format_agg_rois(rois): """ return rois[0], rois[1:], ("-add %s " * (len(rois) - 1)).strip() - - -def generalize_labels(in_file, out_file='aseg.nii.gz'): - """ - Ensure FreeSurfer LUT sub-structures are accounted for, prior to being discarded. - - Parameters - ---------- - in_file : str - Input aseg file - out_file : str - Generalized output aseg file - - Returns - ------- - out_file : str - Generalized output aseg file - """ - import os - import nibabel as nb - import numpy as np - - # https://surfer.nmr.mgh.harvard.edu/fswiki/FsTutorial/AnatomicalROI/FreeSurferColorLUT - # v 1.105 - label_subsitutions = { - 16: (173, 174, 175), # brain stem sub-structures - 17: (550, 551, 552, 553, 554, 555, 556, 557, 558), # HighRes Hippocampus (L) - 53: (500, 501, 502, 503, 504, 505, 506, 507, 508), # HighRes Hippocampus (R) - } - - img = nb.load(in_file) - data = np.asarray(img.dataobj) - labels = set(np.unique(data)) - - for target, subs in label_subsitutions.items(): - if set(subs) - labels: - continue - data[np.isin(data, subs)] = target - - nimg = img.__class__(data, img.affine, header=img.header) - out_file = os.path.abspath(out_file) - nimg.to_filename(out_file) - return out_file From a1aefbb737d1bfa6fc068e12cc8c78d8487af8f1 Mon Sep 17 00:00:00 2001 From: mathiasg Date: Wed, 2 Feb 2022 18:21:41 -0500 Subject: [PATCH 5/7] FIX: Coerce values to integers --- nibabies/interfaces/nibabel.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/nibabies/interfaces/nibabel.py b/nibabies/interfaces/nibabel.py index 9802e6f2..09277ca5 100644 --- a/nibabies/interfaces/nibabel.py +++ b/nibabies/interfaces/nibabel.py @@ -151,16 +151,18 @@ def _remap_labels(in_file, mapping, newpath=None): import nibabel as nb import numpy as np + dtype = np.int16 img = nb.load(in_file) - data = np.asarray(img.dataobj) + data = np.asarray(img.dataobj, dtype=dtype) vec = data.ravel() def _relabel(label): return mapping.get(label, label) labels = np.unique(vec) # include all labels present - subs = np.array(list(map(_relabel, labels))) # copy values and substitute mappings - subbed = np.zeros(labels.max() + 1, dtype=data.dtype) + # copy values and substitute mappings + subs = np.asarray(list(map(_relabel, labels)), dtype=dtype) + subbed = np.zeros(labels.max() + 1, dtype=dtype) subbed[labels] = subs out = subbed[vec].reshape(data.shape) From 04a9defac07db5666b75b007ee8d449f8d0b007e Mon Sep 17 00:00:00 2001 From: mathiasg Date: Mon, 7 Feb 2022 16:02:12 -0500 Subject: [PATCH 6/7] ENH: Upgrade to `niworkflows` 1.5.x Since nibabel interfaces have been ported over, they can be removed from this codebase. --- nibabies/interfaces/nibabel.py | 184 ------------------ nibabies/interfaces/tests/test_nibabel.py | 114 ----------- .../workflows/anatomical/brain_extraction.py | 3 +- nibabies/workflows/anatomical/registration.py | 3 +- nibabies/workflows/bold/alignment.py | 4 +- setup.cfg | 2 +- 6 files changed, 5 insertions(+), 305 deletions(-) delete mode 100644 nibabies/interfaces/nibabel.py delete mode 100644 nibabies/interfaces/tests/test_nibabel.py diff --git a/nibabies/interfaces/nibabel.py b/nibabies/interfaces/nibabel.py deleted file mode 100644 index 09277ca5..00000000 --- a/nibabies/interfaces/nibabel.py +++ /dev/null @@ -1,184 +0,0 @@ -"""Nibabel-based interfaces to eventually upstream to NiWorkflows.""" -from nipype.interfaces.base import ( - traits, - TraitedSpec, - BaseInterfaceInputSpec, - File, - SimpleInterface, - InputMultiObject, -) - - -class _BinaryDilationInputSpec(BaseInterfaceInputSpec): - in_file = File(exists=True, mandatory=True, desc="binary file to dilate") - radius = traits.Float(3, usedefault=True, desc="structure element (ball) radius") - iterations = traits.Range(low=0, value=1, usedefault=True, desc="repeat dilation") - - -class _BinaryDilationOutputSpec(TraitedSpec): - out_file = File(exists=True, desc="the input file, after binary dilation") - - -class BinaryDilation(SimpleInterface): - """Morphological binary dilation using Scipy.""" - - input_spec = _BinaryDilationInputSpec - output_spec = _BinaryDilationOutputSpec - - def _run_interface(self, runtime): - self._results["out_file"] = _dilate( - self.inputs.in_file, - radius=self.inputs.radius, - iterations=self.inputs.iterations, - newpath=runtime.cwd, - ) - return runtime - - -class MergeROIsInputSpec(BaseInterfaceInputSpec): - in_files = InputMultiObject(File(exists=True), desc="ROI files to be merged") - - -class MergeROIsOutputSpec(TraitedSpec): - out_file = File(exists=True, desc="NIfTI containing all ROIs") - - -class MergeROIs(SimpleInterface): - """Combine multiple region of interest files (3D or 4D) into a single file""" - - input_spec = MergeROIsInputSpec - output_spec = MergeROIsOutputSpec - - def _run_interface(self, runtime): - self._results["out_file"] = _merge_rois(self.inputs.in_files, newpath=runtime.cwd) - return runtime - - -class _MapLabelsInputSpec(BaseInterfaceInputSpec): - in_file = File(exists=True, desc="Segmented NIfTI") - mappings = traits.Dict( - xor=["mappings_file"], - desc="Dictionary of label / replacement label pairs", - ) - mappings_file = File( - exists=True, xor=["mappings"], help="JSON composed of label / replacement label pairs." - ) - - -class _MapLabelsOutputSpec(TraitedSpec): - out_file = File(exists=True, desc="Labeled file") - - -class MapLabels(SimpleInterface): - """Remap discrete labels""" - - input_spec = _MapLabelsInputSpec - output_spec = _MapLabelsOutputSpec - - def _run_interface(self, runtime): - mapping = self.inputs.mappings or _load_int_json(self.inputs.mappings_file) - self._results["out_file"] = _remap_labels( - self.inputs.in_file, - mapping, - newpath=runtime.cwd, - ) - return runtime - - -def _dilate(in_file, radius=3, iterations=1, newpath=None): - """Dilate (binary) input mask.""" - from pathlib import Path - import numpy as np - import nibabel as nb - from scipy import ndimage - from skimage.morphology import ball - from nipype.utils.filemanip import fname_presuffix - - mask = nb.load(in_file) - newdata = ndimage.binary_dilation( - np.asanyarray(mask.dataobj) > 0, - structure=ball(radius), - iterations=iterations, - ) - - hdr = mask.header.copy() - hdr.set_data_dtype("uint8") - out_file = fname_presuffix(in_file, suffix="_dil", newpath=newpath or Path.cwd()) - mask.__class__(newdata.astype("uint8"), mask.affine, hdr).to_filename(out_file) - return out_file - - -def _merge_rois(in_files, newpath=None): - """ - Aggregate individual 4D ROI files together into a single subcortical NIfTI. - All ROI images are sanity checked with regards to: - 1) Shape - 2) Affine - 3) Overlap - - If any of these checks fail, an ``AssertionError`` will be raised. - """ - from pathlib import Path - import nibabel as nb - import numpy as np - - img = nb.load(in_files[0]) - data = np.array(img.dataobj) - affine = img.affine - header = img.header - - nonzero = np.any(data, axis=3) - for roi in in_files[1:]: - img = nb.load(roi) - assert img.shape == data.shape, "Mismatch in image shape" - assert np.allclose(img.affine, affine), "Mismatch in affine" - roi_data = np.asanyarray(img.dataobj) - roi_nonzero = np.any(roi_data, axis=3) - assert not np.any(roi_nonzero & nonzero), "Overlapping ROIs" - nonzero |= roi_nonzero - data += roi_data - del roi_data - - if newpath is None: - newpath = Path() - out_file = str((Path(newpath) / "combined.nii.gz").absolute()) - img.__class__(data, affine, header).to_filename(out_file) - return out_file - - -def _remap_labels(in_file, mapping, newpath=None): - from pathlib import Path - import nibabel as nb - import numpy as np - - dtype = np.int16 - img = nb.load(in_file) - data = np.asarray(img.dataobj, dtype=dtype) - vec = data.ravel() - - def _relabel(label): - return mapping.get(label, label) - - labels = np.unique(vec) # include all labels present - # copy values and substitute mappings - subs = np.asarray(list(map(_relabel, labels)), dtype=dtype) - subbed = np.zeros(labels.max() + 1, dtype=dtype) - subbed[labels] = subs - out = subbed[vec].reshape(data.shape) - - if newpath is None: - newpath = Path() - out_file = str((Path(newpath) / "relabeled.nii.gz").absolute()) - img.__class__(out, img.affine, header=img.header).to_filename(out_file) - return out_file - - -def _load_int_json(json_file): - import json - - def _keys_as_ints(d): - return {int(k): v for k, v in d.items()} - - with open(json_file) as fp: - data = json.load(fp, object_hook=_keys_as_ints) - return data diff --git a/nibabies/interfaces/tests/test_nibabel.py b/nibabies/interfaces/tests/test_nibabel.py deleted file mode 100644 index 689f30c0..00000000 --- a/nibabies/interfaces/tests/test_nibabel.py +++ /dev/null @@ -1,114 +0,0 @@ -import json -from pathlib import Path -import uuid - -import nibabel as nb -import numpy as np -import pytest - -from ..nibabel import MergeROIs, MapLabels - - -@pytest.fixture -def create_roi(tmp_path): - files = [] - - def _create_roi(affine, img_data, roi_index): - img_data[tuple(roi_index)] = 1 - nii = nb.Nifti1Image(img_data, affine) - filename = tmp_path / f"{str(uuid.uuid4())}.nii.gz" - files.append(filename) - nii.to_filename(filename) - return filename - - yield _create_roi - - for f in files: - f.unlink() - - -def create_image(data, filename): - nb.Nifti1Image(data, affine=np.eye(4)).to_filename(str(filename)) - return filename - - -# create a slightly off affine -bad_affine = np.eye(4) -bad_affine[0, -1] = -1 - - -@pytest.mark.parametrize( - "affine, data, roi_index, error, err_message", - [ - (np.eye(4), np.zeros((2, 2, 2, 2), dtype=int), [1, 0], None, None), - ( - np.eye(4), - np.zeros((2, 2, 3, 2), dtype=int), - [1, 0], - True, - "Mismatch in image shape", - ), - ( - bad_affine, - np.zeros((2, 2, 2, 2), dtype=int), - [1, 0], - True, - "Mismatch in affine", - ), - ( - np.eye(4), - np.zeros((2, 2, 2, 2), dtype=int), - [0, 0, 0], - True, - "Overlapping ROIs", - ), - ], -) -def test_merge_rois(tmpdir, create_roi, affine, data, roi_index, error, err_message): - tmpdir.chdir() - roi0 = create_roi(np.eye(4), np.zeros((2, 2, 2, 2), dtype=int), [0, 0]) - roi1 = create_roi(np.eye(4), np.zeros((2, 2, 2, 2), dtype=int), [0, 1]) - test_roi = create_roi(affine, data, roi_index) - - merge = MergeROIs(in_files=[roi0, roi1, test_roi]) - if error is None: - merge.run() - return - # otherwise check expected exceptions - with pytest.raises(AssertionError) as err: - merge.run() - assert err_message in str(err.value) - - -DEFAULT_MAPPING = {5: 1, 6: 1, 7: 2} -DEFAULT_INPUT = np.arange(8).reshape(2, 2, 2) -DEFAULT_OUTPUT = np.asarray([0, 1, 2, 3, 4, 1, 1, 2]).reshape(2, 2, 2) - - -@pytest.mark.parametrize( - "data,mapping,tojson,expected", - [ - (DEFAULT_INPUT, DEFAULT_MAPPING, False, DEFAULT_OUTPUT), - (DEFAULT_INPUT, DEFAULT_MAPPING, True, DEFAULT_OUTPUT), - ], -) -def test_map_labels(tmpdir, data, mapping, tojson, expected): - tmpdir.chdir() - in_file = create_image(data, Path("test.nii.gz")) - maplbl = MapLabels(in_file=in_file) - if tojson: - map_file = Path('mapping.json') - map_file.write_text(json.dumps(mapping)) - maplbl.inputs.mappings_file = map_file - else: - maplbl.inputs.mappings = mapping - out_file = maplbl.run().outputs.out_file - - orig = nb.load(in_file).get_fdata() - labels = nb.load(out_file).get_fdata() - assert orig.shape == labels.shape - assert np.all(labels == expected) - - Path(in_file).unlink() - if tojson: - Path(map_file).unlink() diff --git a/nibabies/workflows/anatomical/brain_extraction.py b/nibabies/workflows/anatomical/brain_extraction.py index 645a9216..e0dcd108 100644 --- a/nibabies/workflows/anatomical/brain_extraction.py +++ b/nibabies/workflows/anatomical/brain_extraction.py @@ -80,14 +80,13 @@ def init_infant_brain_extraction_wf( from nipype.interfaces.ants import N4BiasFieldCorrection, ImageMath # niworkflows - from niworkflows.interfaces.nibabel import ApplyMask, Binarize, IntensityClip + from niworkflows.interfaces.nibabel import ApplyMask, Binarize, IntensityClip, BinaryDilation from niworkflows.interfaces.fixes import ( FixHeaderRegistration as Registration, FixHeaderApplyTransforms as ApplyTransforms, ) from templateflow.api import get as get_template - from ...interfaces.nibabel import BinaryDilation from ...utils.misc import cohort_by_months # handle template specifics diff --git a/nibabies/workflows/anatomical/registration.py b/nibabies/workflows/anatomical/registration.py index c3fda7cc..0ac73a82 100644 --- a/nibabies/workflows/anatomical/registration.py +++ b/nibabies/workflows/anatomical/registration.py @@ -81,8 +81,7 @@ def init_coregistration_wf( FixHeaderRegistration as Registration, FixHeaderApplyTransforms as ApplyTransforms, ) - from niworkflows.interfaces.nibabel import ApplyMask, Binarize - from ...interfaces.nibabel import BinaryDilation + from niworkflows.interfaces.nibabel import ApplyMask, Binarize, BinaryDilation workflow = pe.Workflow(name) diff --git a/nibabies/workflows/bold/alignment.py b/nibabies/workflows/bold/alignment.py index 2ea4f178..306a465a 100644 --- a/nibabies/workflows/bold/alignment.py +++ b/nibabies/workflows/bold/alignment.py @@ -34,7 +34,7 @@ def init_subcortical_rois_wf(*, name="subcortical_rois_wf"): Subcortical ROIs in `MNI152NLin6Asym` space """ from templateflow.api import get as get_template - from ...interfaces.nibabel import MapLabels + from niworkflows.interfaces.nibabel import MapLabels # TODO: Implement BOLD refinement once InfantFS outputs subj/mri/wmparc.mgz # The code is found at @@ -128,7 +128,7 @@ def init_subcortical_mni_alignment_wf(*, vol_sigma=0.8, name="subcortical_mni_al Volume file containing all labels """ from niworkflows.engine.workflows import LiterateWorkflow as Workflow - from ...interfaces.nibabel import MergeROIs + from niworkflows.interfaces.nibabel import MergeROIs from ...interfaces.workbench import ( CiftiCreateDenseTimeseries, CiftiCreateLabel, diff --git a/setup.cfg b/setup.cfg index 5b28366f..04dbf5c3 100644 --- a/setup.cfg +++ b/setup.cfg @@ -24,7 +24,7 @@ install_requires = nibabel >= 3.0.1 nipype >= 1.5.1 nitime - niworkflows ~= 1.4.0 + niworkflows ~= 1.5.0 numpy >= 1.16.5 pybids >= 0.12.1 sdcflows ~= 2.0.7 From 25d9f952ac7612849ef9759975c833699c0f07e5 Mon Sep 17 00:00:00 2001 From: mathiasg Date: Tue, 8 Feb 2022 11:38:19 -0500 Subject: [PATCH 7/7] PIN: Latest sdcflows --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 04dbf5c3..9c39ffea 100644 --- a/setup.cfg +++ b/setup.cfg @@ -27,7 +27,7 @@ install_requires = niworkflows ~= 1.5.0 numpy >= 1.16.5 pybids >= 0.12.1 - sdcflows ~= 2.0.7 + sdcflows ~= 2.0.12 smriprep ~= 0.8.1 templateflow >= 0.6.0 test_requires =