Search code examples
pythonlistnodesnipype

Taking two outputs from two different nodes and feeding them as a list to another node as one single input


it's Pablo!

I'm trying to make a script for DTI. I already have it with functions and nipype but now I'm trying with nodes yet there is one node which needs a list of two inputs -Merge()- to merge both images. However, it only accepts one input and connect() does not allow to input several inputs at a time. In this function, it neither lets me do it separately and trying util.merge rises an error.

I'm wondering if I can take two inputs from the outputs of two different nodes each, and join them into a list with another node maybe and feed it into the node that takes the list as input. Or maybe there is another way to define a node that allows this?

Does anyone knows anything at all?

Thank you so much in advance


Solution

  • If I understood well, you just want to merge two items in a list.

    This is what the merge interface is made for. You just need to provide the number of inputs upon initialization, as described in the doc. The no_flatten and ravel_input options will help you is the inputs are lists, which can often happen.

    EDIT: a small example:

    from nipype import Node, Workflow
    from nipype.interfaces.utility import Function, Merge
    
    #create a workflow
    example_wf = Workflow('merging_example')
    
    #this function just injects stuff in the pipeline
    def func_stuffSource(stuff):
        return stuff
    
    sourceA=Node(Function(input_names=["stuff"], 
                          output_names=["returnedStuff"], 
                          function=func_stuffSource), 
                 name='sourceA_node')
    sourceB=Node(Function(input_names=["stuff"], 
                          output_names=["returnedStuff"], 
                          function=func_stuffSource), 
                 name='sourceB_node')
    
    merger = Node(Merge(2), name='merger_node')
    
    #we just give stuff to inject to the two nodes
    sourceA.inputs.stuff=['a0', 'a1', 'a2']
    sourceB.inputs.stuff=['b0', 'b1', 'b2', 'b3']
    
    example_wf.connect([
        ( sourceA, merger, [('returnedStuff' , 'in1')]), 
        ( sourceB, merger, [('returnedStuff' , 'in2')])
    ])
    
    #simple function to print whatever the node gets
    def printStuff(stuff):
        from nipype import logging
        logger = logging.getLogger("nipype.interface")
        logger.info(str(stuff))
    
    printer = Node(Function(input_names=['stuff'], 
                            output_names=[], 
                            function=printStuff), 
                   name='print_node')
    
    example_wf.connect([ 
        (merger, printer, [('out', 'stuff')]) 
    ])
    
    
    example_wf.run()
    
    

    RESULT:

    200306-08:32:22,463 nipype.workflow INFO:
             Workflow merging_example settings: ['check', 'execution', 'logging', 'monitoring']
    200306-08:32:22,475 nipype.workflow INFO:
             Running serially.
    200306-08:32:22,476 nipype.workflow INFO:
             [Node] Setting-up "merging_example.sourceB_node" in "/tmp/tmpzfklhqwq/merging_example/sourceB_node".
    200306-08:32:22,484 nipype.workflow INFO:
             [Node] Running "sourceB_node" ("nipype.interfaces.utility.wrappers.Function")
    200306-08:32:22,491 nipype.workflow INFO:
             [Node] Finished "merging_example.sourceB_node".
    200306-08:32:22,491 nipype.workflow INFO:
             [Node] Setting-up "merging_example.sourceA_node" in "/tmp/tmppssiddpk/merging_example/sourceA_node".
    200306-08:32:22,496 nipype.workflow INFO:
             [Node] Running "sourceA_node" ("nipype.interfaces.utility.wrappers.Function")
    200306-08:32:22,501 nipype.workflow INFO:
             [Node] Finished "merging_example.sourceA_node".
    200306-08:32:22,502 nipype.workflow INFO:
             [Node] Setting-up "merging_example.merger_node" in "/tmp/tmp_h6t6h7o/merging_example/merger_node".
    200306-08:32:22,505 nipype.workflow INFO:
             [Node] Running "merger_node" ("nipype.interfaces.utility.base.Merge")
    200306-08:32:22,511 nipype.workflow INFO:
             [Node] Finished "merging_example.merger_node".
    200306-08:32:22,511 nipype.workflow INFO:
             [Node] Setting-up "merging_example.print_node" in "/tmp/tmpg4zggeq6/merging_example/print_node".
    200306-08:32:22,517 nipype.workflow INFO:
             [Node] Running "print_node" ("nipype.interfaces.utility.wrappers.Function")
    200306-08:32:22,518 nipype.interface INFO:
             ['a0', 'a1', 'a2', 'b0', 'b1', 'b2', 'b3']
    200306-08:32:22,522 nipype.workflow INFO:
             [Node] Finished "merging_example.print_node".
    

    Note that our lists are correctly merged. To check it for yourself, you can create to other printer nodes, and connecte them to the outputs of sourceA and sourceB