Multiple inputs to c3d from seperate nodes

Hi all,
I’m running a fairly simple pipeline on anatomical data to resize and reshape images from different subjects.

I want to do preprocessing on two seperate files in different nodes (file_a.nii (which has an iterable left/right side) and file_b.nii) in two nodes (node a and node b). The outputs would then be resliced together in node c using C3d to be the same size. Node d would then take the output from node a and c again to multiply them to make a mask.

However, I can’t work out how to get two outputs from seperate nodes as inputs to a different node, and I don’t believe that this is a job for a join node based on the docs.
Here’s some code:

node_a = MapNode(C3d(interp = "Sinc", pix_type = 'float', args = 'resample-mm 0.35x0.35x0.35mm pad-to 176x144x128 0 -binarize'),
                            name='node_a', iterfield=['in_file']) 
wf.connect([(selectfiles, node_a, [('file_a','in_file')])])

node_b = MapNode(C3d(interp = "Sinc", pix_type = 'float', args = 'resample-mm 0.35x0.35x0.35mm'),
                             name='node_b', iterfield=['in_file']) 
wf.connect([(selectfiles, node_b, [('file_b','in_file')])])

node_c =  MapNode(C3d(interp = "Sinc", pix_type = 'float', args = '-reslice-identity'),
wf.connect([(node_a, node_c, [('out_file','in_file')])])
wf.connect([(node_b, node_c, [('out_file','in_file')])])

node_d=  Node(C3d(interp = "Sinc", pix_type = 'float', args = '-multiply'),
wf.connect([(node_c, node_d, [('out_file','in_file')])])
wf.connect([(node_a, node_d, [('out_file','in_file')])])

The error:

Exception: Trying to connect preprocess.node_b:file_a to preprocess.node_c:in_file but input ‘in_file’ of node ‘preprocess.node_c’ is already connected.

Could anyone help please?

The more general solution may depend on the details of your task, but to answer this specific problem, you will need a Merge node to collate two sets of outputs.

One way to think about Nipype is a set of pipes from outputs to inputs. Each input can only accept one pipe.

Hi @satra,
Thanks, that makes sense. :smile:
However, I’m still a bit lost, especially considering the merge node documentation does not give an example that would make sense in any neuro pipeline.
I think the more general solution would be nice to understand, especially in the docs, as many tools including C3D and Ants require multiple inputs to function, and I was wondering how this one would be solved. Would I connect the previous node to a new node using merge like this?

mi = Merge(2)
wf.connect ([(node_a, mi.inputs.in1, [('out_file', in_file )])])

or something similar?
and then I can feed the output of the mi node to the input of node_c?

Thanks again for your help!

In your example, i think the merge should look like this

mi = Merge(2)
wf.connect ([(node_a, mi, [("out_file", "in1")])])
wf.connect ([(node_b, mi, [("out_file", "in2")])])
wf.connect ([(mi, node_c, [("out", "in_file")])])

and node_c would need to be a MapNode as well, which then connects to Node_d

However, if the situation you are trying to solve is that a and b goes through c and to d, and the ouput of a goes to d, then you will need another merge node after node_c

Here are the more general concepts:

Merge is for concatenating two or more inputs into a single output (in a few ways - see the examples) and MapNodes can take multiple inputs that are lists and pair them up. Generally MapNodes are used for dynamic parallelization, where you don’t know ahead of time what the number of inputs will be. And iterables are used when you know before running the workflow what you want iterate over.

and given these easiest is to draw out the flow in a piece of paper or board, noting that two pipes cannot go into the same input.

Is there a specific reason why the input is restricted to one pipe? Being able to dynamically change a node’s input and output pipes, like with a usual function, would have saved me a lot of coding :slight_smile: