Crop image with fsl in nypipe

I want to implement an image cropping step into my nipype pipeline. The command to crop an image using fsl is (from the mailing list):

fslroi T1image T1cropped `fslstats DesiredMask -w`

Basically you need to provide it with the x, y, z coordinates for the cropping to take place. fslstats takes can give us these coordinates when it reads the mask and it then passes them on to fslroi. How can I implement these steps into nipype if the masks are subject specific?

Or is there another way to crop niftis in nipype that I am not aware of?

You might want to look into using this http://nilearn.github.io/modules/generated/nilearn.image.crop_img.html inside a Function interface.

The nilearn way would definitley work but there is an in-between step required which writes additional files to disk, and that is to mask the functional images and make all unimportant areas zero. I tried it and I had trouble with python 2.7 and the zlib compression with large file sizes, and thus didn’t work. You could use python 3 of course. Instead I implemented it using fslstats in the following way using a function and an args input:

   def fsl_stats_command(subject_id):
        # Create the command line to run fsl stats in order to calculate
        # size of ROI.
        from os.path import join as opj
        mask_dir = '/data/pt_nmc002/ROIs/prism_mask_mgb_ic_per_subject/'
        command = "`fslstats " + opj(mask_dir,
                   '%s_roi-mid-ic-mgb_binarized.nii'%subject_id) + " -w`"
        return command

    fsl_stats = Node(Function(input_names=['subject_id'],
                                 output_names=['fslstats_command'],
                                 function=fsl_stats_command),
                        name="fsl_stats")
    preproc_freq_loc.connect(infosource, 'subject_id', fsl_stats, 'subject_id')

    crop_func = MapNode(ExtractROI(), iterfield="in_file",
                              name="crop_func")
    crop_func.inputs.output_type = 'NIFTI_GZ'

    preproc_freq_loc.connect([
        (warpbbreg, crop_func, [('output_image', 'in_file')]),
        (fsl_stats, crop_func, [('fslstats_command', 'args')])
        ])

However, doing it like this results in a 3D file instead of a 4D because the last two arguments from the ROI size are 0 and 1 which represent t_min and t_size. They should either be omitted altogether or replaced by 0 and -1. Here’s my final working version:

def get_roi_size(subject_id):
    # Generate output regarding size of ROI from fslstats, and get rid
    # of the last two numbers which represent t_min and t_size.
    from os.path import join as opj
    import subprocess
    mask_dir = '/data/pt_nmc002/ROIs/prism_mask_mgb_ic_per_subject/'
    command = "`fslstats " + opj(mask_dir,
               '%s_roi-mid-ic-mgb_binarized.nii'%subject_id) + " -w`"
    process = subprocess.Popen(command.split(), stdout=subprocess.PIPE)
    output, error = process.communicate()
    output = output[:-6]  # get rid of last 2 numbers and extra chars
    return output
roi_size = Node(Function(input_names=['subject_id'],
                             output_names=['roi_size'],
                             function=get_roi_size),
                    name="roi_size")
preproc_freq_loc.connect(infosource, 'subject_id', roi_size, 'subject_id')

crop_func = MapNode(ExtractROI(), iterfield="in_file",
                          name="crop_func")
crop_func.inputs.output_type = 'NIFTI_GZ'


preproc_freq_loc.connect([
    (warpbbreg, crop_func, [('output_image', 'in_file')]),
    (roi_size, crop_func, [('roi_size', 'args')])
    ])