Nipype: iterables at runtime

Hi all,

Background/Use Case
I have a workflow where I am trying to iterate over two sources. One source is the betaseries_files, and the other is the rois. Essentially every roi has to be applied to every betaseries_file, or in other words I want the Cartesian product of roi x betaseries_file.

Problem/Road Block
The type of functionality I want sounds like it should be accomplished by iterables, not MapNode, but the problem is that I don’t know the lists I’m going to iterate over before runtime.

Question

  1. Can iterables be defined after runtime (e.g. after I start the script)?
    Related: To support iterables, is the following syntax valid?:
inputnode = pe.Node(niu.IdentityInterface(fields=['betaseries_files',
                                                  'bold_mask',
                                                  'mni_roi_coords',
                                                  't1w_space_mni_mask',
                                                  'target_t1w_warp',
                                                  'target_mni_warp']),
                        name='inputnode')

    betaseries_file = pe.Node(niu.IdentityInterface(fields=['betaseries_file']),
                              name='betaseries_file',
                              iterables=('betaseries_file', inputnode.inputs.betaseries_files))

Or should I figure out how to use nested MapNodes, and find a way to represent nesting rois within betaseries_files? Or is there another option I haven’t considered?

EDIT
iterables aren’t a solution
many thanks!
James

You could imagine a node that takes N lists, and returns the cartesian product as N lists repeated such that each tuple in the cartesian product corresponds to some index taken in each list. For N=2 you could use a function like the following:

def cart(A, B):
    AxB = [a for a in A for b in B]
    BxA = [b for a in A for b in B]
    return AxB, BxA

So if A = [1, 2, 3] and B = [10, 20] you get [1, 1, 2, 2, 3, 3] and [10, 20, 10, 20, 10, 20]. You can now just use a MapNode with both iterfields set, pass your inputs to Function(function=cart) before passing to your MapNode.

1 Like

Thank you so much @effigies, this is exactly what I was looking for, I guess the clue was in the Cartesian product.