Hi everyone,
I have happily integrated a custom function of mine in a nipype workflow for the first time. Although generally speaking it works fine, in the sense that the input of the previous node get correctly fed to the function and the output of the function get correctly fed to the following node, I am left wondering about what i should do if I wanted to collect the output of my custom function using a datasink.
Below the code that I have up until now:
    from nipype.interfaces.dcm2nii import Dcm2niix
    from nipype.interfaces.spm.preprocess import Normalize
    from nipype.pipeline import Node
    from nipype.pipeline import Workflow
    from nipype.interfaces.io import DataSink
    from nipype.interfaces.utility import Function
    from glob import glob
    from os import chdir
def center_volumes(to_be_centered_file, out_files = None):
    """
This function center the volume(s) given as input by setting
the offset of the volume so that the center is in the middle of the box.
If no out_files name is given than the "centered_" will be added to the 
original name. 
:in_files: name of the volume as a string
:out_files (optional): the name of the centered volumes, default 
to None
:return: centered image as a nifti file
    """
    from nipy import load_image
    import nibabel as nib
    import os
    import numpy as np
    img_name = os.path.basename(to_be_centered_file)
    img = load_image(to_be_centered_file)
    img_centered_header = img.metadata["header"]
    img_dim = img_centered_header["dim"][1:4]
    img_pixdim = img_centered_header["pixdim"][1:4]
    img_centered_header["qoffset_z"] = (img_dim[2]* img_pixdim[2]*
                        np.sign(img.metadata["header"]["srow_z"][2])*-1)/2
    img_centered_header["srow_z"][3] = img_centered_header["qoffset_z"]
    img_centered_header["qoffset_y"] = (img_dim[1]* img_pixdim[1]*
                        np.sign(img.metadata["header"]["srow_y"][1])*-1)/2
    img_centered_header["srow_y"][3] = img_centered_header["qoffset_y"]
    img_centered_header["qoffset_x"] = (img_dim[0]* img_pixdim[0]*
                        np.sign(img.metadata["header"]["srow_x"][0])*-1)/2
    img_centered_header["srow_x"][3] = img_centered_header["qoffset_x"]
    img_original_affine = img.affine
    img_centered_affine = img_original_affine[~(img_original_affine==0).all(0)]
    img_centered_affine = img_centered_affine[:,~(img_centered_affine==0).all(0)]
    img_centered_affine[[0,1,2],3] = np.array([img_centered_header["qoffset_x"],
                         img_centered_header["qoffset_y"],
                         img_centered_header["qoffset_z"]])
    img_centered = nib.Nifti1Image(img.get_data(), img_centered_affine, header = img_centered_header)
    if out_files is None:
        centered_filename = "centered_{}".format(img_name)
        img_centered.to_filename(centered_filename)
    else:
        img_centered.to_filename(out_files)
    return(os.path.abspath(centered_filename))
dcm2nii = Node(Dcm2niix(compress = "n"), "dcm2nii")
norm = Node(Normalize(template = "/mnt/mydir/TEMPLATE_FDGPET_100.nii"), "norm")
func = Node(Function(input_names=["to_be_centered_file"],
                             output_names=["centered_filename"],
                             function=center_volumes), "func")
dsk = Node(DataSink(base_directory="/mnt/mydir/", container="spm_preproc"), "dsk")
app_spm = Workflow(name = "app_spm")
app_spm.base_dir = "/mnt/mydir/"
app_spm.connect([
        (dcm2nii, func, [("converted_files", "to_be_centered_file")]),
        (func, norm, [("centered_filename", "source")]),
        (norm, dsk, [("normalized_source", "norm")]),
        ])
chdir("/mnt/mydir/")    
ss = glob("*")[0:70]
for s in ss:    
    app_spm.inputs.dcm2nii.source_dir = "/mnt/mydir/" + s
    app_spm.run()
My point is that I do not know which output of my custom function use in the connection with datasink, since in this case the output I am interested in is not something that the function return, but a side effect of the function.
Any suggestion or tip will be greatly appreciated