Source code for macapype.nodes.prepare

"""
copied from https://stackoverrun.com/fr/q/6768689
seems was never wrapped in nipype
"""
import os
import json

from nipype.interfaces.fsl.base import FSLCommand, FSLCommandInputSpec
from nipype.interfaces.base import (CommandLine, CommandLineInputSpec,
                                    TraitedSpec, File, traits)


# FslOrient
class FslOrientInputSpec(FSLCommandInputSpec):

    main_option = traits.Str(
        desc='main option', argstr='-%s', position=0, mandatory=True)

    code = traits.Int(
        argstr='%d', desc='code for setsformcode', position=1)

    in_file = File(
        exists=True, desc='input file', argstr='%s', position=2,
        mandatory=True)


class FslOrientOutputSpec(TraitedSpec):

    out_file = File(desc="out file", exists=True)


class FslOrient(FSLCommand):
    """
    copied and adapted from https://stackoverrun.com/fr/q/6768689
    seems was never wrapped in nipype
    """
    _cmd = 'fslorient'
    input_spec = FslOrientInputSpec
    output_spec = FslOrientOutputSpec

    def _list_outputs(self):
        outputs = self.output_spec().get()
        outputs['out_file'] = os.path.abspath(self.inputs.in_file)
        return outputs


# CropVolume
class CropVolumeInputSpec(CommandLineInputSpec):

    # mandatory
    i_file = File(
        exists=True,
        desc='Volume to crop (you can specify as many -in as you want)',
        mandatory=True, position=0, argstr="-i %s")

    b_file = File(
        exists=True,
        desc='Brain image or brain mask, in the same space as the in-file(s)',
        mandatory=True, position=1, argstr="-b %s")

    # optional
    o = traits.String(
        desc="Prefix for the cropped image(s) (Must provide as many prefixes\
            as input images with -o, default is the base name of each input \
            image).",
        argstr="-o %s", mandatory=False)

    s = traits.String(
        "_cropped", usedefault=True,
        desc="Suffix for the cropped image(s) (default is \"_cropped\")",
        argstr="-s %s", mandatory=False)

    c = traits.Int(
        10, usedefault=True,
        desc='c is the space between the brain and the limits of\
            the crop box expressed in percentage of the brain size (eg. if the\
            brain size is 200 voxels in one dimension and c=10: the sides of\
            the brain in this dimension will be 20 voxels away from the\
            borders of the resulting crop box in this dimension). \
            Default: c=10',
        argstr="-c %d", mandatory=False)

    p = traits.String(
        desc="Prefix for running FSL functions\
            (can be a path or just a prefix)",
        argstr="-p %s", mandatory=False)


class CropVolumeOutputSpec(TraitedSpec):
    cropped_file = File(
        exists=True,
        desc="cropped image from CropVolume.sh")


[docs]class CropVolume(CommandLine): """ Description: Crop image(s) based on a brain extraction. Multiple images can be cropped at once. Will crop each volume preceeded by the -i option Inputs: Mandatory: i_file Volume to crop (you can specify as many -in as you want) b_file Brain image or brain mask, in the same space as the in-file(s) Optional: o Prefix for the cropped image(s) (Must provide as many prefixes as input images with -o, default is the base name of each input image). s Suffix for the cropped image(s) (default is "_cropped") c c is the space between the brain and the limits of\ the crop box expressed in percentage of the brain size (eg. if the brain size is 200 voxels in one dimension and c=10: the sides of the brain in this dimension will be 20 voxels away from the borders of the resulting crop box in this dimension). Default: c=10 p Prefix for running FSL functions (can be a path or just a prefix) Outputs: cropped_file: cropped image from CropVolume.sh """ input_spec = CropVolumeInputSpec output_spec = CropVolumeOutputSpec package_directory = os.path.dirname(os.path.abspath(__file__)) _cmd = 'bash {}/../bash/CropVolume.sh'.format(package_directory) def _list_outputs(self): import os from nipype.utils.filemanip import split_filename as split_f outputs = self._outputs().get() path, fname, ext = split_f(self.inputs.i_file) outfile = fname + self.inputs.s if self.inputs.o: outfile = self.inputs.o + outfile outputs["cropped_file"] = os.path.abspath(outfile + ".nii.gz") return outputs
############################################################################### # Equivalent of flirt_average in FSL def average_align(list_img): import os import nibabel as nib import numpy as np from nipype.utils.filemanip import split_filename as split_f import nipype.interfaces.fsl as fsl print("average_align:", list_img) if isinstance(list_img, list): assert len(list_img) > 0, "Error, list should have at least one file" if len(list_img) == 1: assert os.path.exists(list_img[0]) av_img_file = list_img[0] else: img_0 = nib.load(list_img[0]) path, fname, ext = split_f(list_img[0]) list_data = [img_0.get_data()] for i, img in enumerate(list_img[1:]): print("running flirt on {}".format(img)) flirt = fsl.FLIRT(dof=6) flirt.inputs.in_file = img flirt.inputs.reference = list_img[0] flirt.inputs.interp = "sinc" flirt.inputs.no_search = True out_file = flirt.run().outputs.out_file print(out_file) data = nib.load(out_file).get_data() list_data.append(data) avg_data = np.mean(np.array(list_data), axis=0) print(avg_data.shape) av_img_file = os.path.abspath("avg_" + fname + ext) nib.save(nib.Nifti1Image(avg_data, header=img_0.get_header(), affine=img_0.get_affine()), av_img_file) else: assert os.path.exists(list_img) av_img_file = list_img return av_img_file # on the fly def read_cropbox(cropbox_file): import os.path as op assert op.exists(cropbox_file), \ "Error {} do not exists".format(cropbox_file) with open(cropbox_file) as f: crop_list = [] for line in f.readlines(): print(line.strip().split()) crop_list.append(tuple(map(int, map(float, line.strip().split())))) return crop_list def padding_cropped_img(cropped_img_file, orig_img_file, indiv_crop): import os import nibabel as nib import numpy as np from nipype.utils.filemanip import split_filename as split_f # orig image orig_img = nib.load(orig_img_file) data_orig = orig_img.get_data() header_orig = orig_img.get_header() affine_orig = orig_img.get_affine() padded_img_data = np.zeros(shape=data_orig.shape) fpath, fname, ext = split_f(cropped_img_file) print("Padded img shape:", padded_img_data.shape) # cropped image cropped_img = nib.load(cropped_img_file) data_cropped = cropped_img.get_data() print("Cropped img shape:", data_cropped.shape) crop = indiv_crop['crop']['args'].split() xmin = int(crop[0]) xmax = xmin + int(crop[1]) ymin = int(crop[2]) ymax = ymin + int(crop[3]) zmin = int(crop[4]) zmax = zmin + int(crop[5]) padded_img_data[xmin:xmax, ymin:ymax, zmin:zmax] = data_cropped padded_img_file = os.path.abspath(fname + "_padded" + ext) img_padded_res = nib.Nifti1Image(padded_img_data, affine=affine_orig, header=header_orig) nib.save(img_padded_res, padded_img_file) return padded_img_file def reg_aladin_dirty(reference, in_file): import os cwd = os.path.abspath("") os.chdir(cwd) out_file = os.path.abspath("outputResult.nii") cmd = "reg_aladin -flo {} -ref {} -res {}".format( in_file, reference, out_file) os.system(cmd) assert os.path.exists(out_file) return out_file if __name__ == '__main__': data_path = "/hpc/meca/data/Macaques/Macaque_hiphop/results/ucdavis" orig_file = os.path.join(data_path, "sub-032139/ses-001/anat/\ sub-032139_ses-001_run-1_T1w.nii.gz") mask_file = os.path.join( data_path, "derivatives/macapype_ANTS/sub-032139/ses-001/anat/\ sub-032139_ses-001_space-orig_desc-brain_mask.nii.gz") indiv_file = os.path.join( "/hpc/meca/users/essamlali.a/Packages", "indiv_params_segment_macaque_ants_based_crop.json") indiv = json.load(open(indiv_file)) indiv_crop = indiv['sub-032139']['ses-001'] res = padding_cropped_img(mask_file, orig_file, indiv_crop) print(res)