How to use the nilearn plotting functions inside a workflow? (Exporting nifti as PNG)

I would like to export some nifti volumes as .png images inside a workflow.
Since plot_anat() from nilearn.plotting creates nice orthogonal slices that can be saved by simply providing an output_file argument, I thought I could create a function interface for it.

Below is this function that enters a node. It runs without errors, but doesn’t produce any outputs. I expected some pngs in the working folder, but it remains empty. Is it even possible, or some problem with calling matplotlib functions in this closed environment of a node?

def generate_png(scan,nslices=20):
    from nilearn import plotting
    import os
    nifti_filename = os.path.basename(scan)
    nifti_filename_noext = os.path.splitext(os.path.splitext(nifti_filename)[0])[0]
    workfolder = os.getcwd()
    imagefile1 = f"{workfolder}/{nifti_filename_noext}.png"
    plotting.plot_anat(scan, display_mode='ortho', annotate=True, output_file=imagefile1)
    imagefile2 = f"{workfolder}/{nifti_filename_noext}_slices.png"
    plotting.plot_anat(scan, display_mode='y', cut_coords=nslices, annotate=True, output_file=imagefile2)
    return imagefile1

get_pngs = Node(name='get_png',
               interface=Function(input_names=['scan'],
                                  output_names=['out_files'],
                                  function=generate_png))

Btw. I am sure there must be some simpler way to do this, or some more straightforward interface from FSL or others… but all examples involving images that I found involve only plots inside notebooks.
Since plot_anat() doesn’t return any values, I had to awkwardly construct the absolute path of the output image files myself with getcw…

This is reasonable. I would recommend against specifying input_names for Function, though, parameter names are auto-detected, and input_names is only there to keep old workflows from breaking.

I assume you’ve tested that running generate_png directly produces the files that you want? If so, the missing files might be an effect of remove_unnecessary_outputs. See Basic Execution Configuration.

Just as an additional note, Nipype has nipype.utils.filemanip.split_filename, which is designed to work with common imaging formats, so you don’t need to call basename/splitext as you do

1 Like