# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
# vi: set ft=python sts=4 ts=4 sw=4 et:
#
# Copyright The NiPreps Developers <nipreps@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# We support and encourage derived works from this project, please read
# about our expectations at
#
# https://www.nipreps.org/community/licensing/
#
"""Interfaces for manipulating GIFTI files."""
import os
import nibabel as nb
from nipype.interfaces.base import File, SimpleInterface, TraitedSpec, isdefined, traits
class MetricMathInputSpec(TraitedSpec):
subject_id = traits.Str(desc='subject ID')
hemisphere = traits.Enum(
'L',
'R',
mandatory=True,
desc='hemisphere',
)
metric = traits.Str(desc='name of metric to invert')
metric_file = File(exists=True, mandatory=True, desc='input GIFTI file')
operation = traits.Enum(
'invert',
'abs',
'bin',
mandatory=True,
desc='operation to perform',
)
class MetricMathOutputSpec(TraitedSpec):
metric_file = File(desc='output GIFTI file')
[docs]
class MetricMath(SimpleInterface):
"""Prepare GIFTI metric file for use in MSMSulc
This interface mirrors the action of the following portion
of FreeSurfer2CaretConvertAndRegisterNonlinear.sh::
wb_command -set-structure ${metric_file} CORTEX_[LEFT|RIGHT]
wb_command -metric-math "var * -1" ${metric_file} -var var ${metric_file}
wb_command -set-map-names ${metric_file} -map 1 ${subject}_[L|R]_${metric}
# If abs:
wb_command -metric-math "abs(var)" ${metric_file} -var var ${metric_file}
We do not add palette information to the output file.
"""
input_spec = MetricMathInputSpec
output_spec = MetricMathOutputSpec
def _run_interface(self, runtime):
subject, hemi, metric = self.inputs.subject_id, self.inputs.hemisphere, self.inputs.metric
if not isdefined(subject):
subject = 'sub-XYZ'
img = nb.GiftiImage.from_filename(self.inputs.metric_file)
# wb_command -set-structure
img.meta['AnatomicalStructurePrimary'] = {'L': 'CortexLeft', 'R': 'CortexRight'}[hemi]
darray = img.darrays[0]
# wb_command -set-map-names
meta = darray.meta
meta['Name'] = f'{subject}_{hemi}_{metric}'
datatype = darray.datatype
if self.inputs.operation == 'abs':
# wb_command -metric-math "abs(var)"
data = abs(darray.data)
elif self.inputs.operation == 'invert':
# wb_command -metric-math "var * -1"
data = -darray.data
elif self.inputs.operation == 'bin':
# wb_command -metric-math "var > 0"
data = darray.data > 0
datatype = 'uint8'
darray = nb.gifti.GiftiDataArray(
data,
intent=darray.intent,
datatype=datatype,
encoding=darray.encoding,
endian=darray.endian,
coordsys=darray.coordsys,
ordering=darray.ind_ord,
meta=meta,
)
img.darrays[0] = darray
out_filename = os.path.join(runtime.cwd, f'{subject}.{hemi}.{metric}.native.shape.gii')
img.to_filename(out_filename)
self._results['metric_file'] = out_filename
return runtime