Iterate over two fields with different lengths

I’m trying to iterate over two fields with different lengths

def func(subject_id,x):
return {“id”:subject_id, “x2”:x**2, “x”:x}

funcnode = MapNode(Function(input_names=[“subject_id”,“x”],output_names=[“subjectdict”],function=func), name=“funcnode”, iterfield=[“subject_id”,“x”])
funcnode.inputs.subject_id = [“01”,“02”]
funcnode.inputs.x = [2,4,6,8]

funcnode.run()

ValueError: All iterfields of a MapNode have to have the same length.

I understand why I’m getting the error, but was wondering if there is way around this to get the following result list?

out = [{“id”:“01”, “x2”:4, “x”:2},
{“id”:“01”, “x2”:16, “x”:4},
{“id”:“01”, “x2”:36, “x”:6},
{“id”:“01”, “x2”:64, “x”:8}
{“id”:“02”, “x2”:4, “x”:2},
{“id”:“02”, “x2”:16, “x”:4},
{“id”:“02”, “x2”:36, “x”:6},
{“id”:“02”, “x2”:64, “x”:8}]

@mri

MapNodes will expand across all inputs, and thus required to be of the same length. However, iterables can be used with MapNodes to give the behavior you’re looking for.

Perhaps something like this can get you started:

wf = Workflow('iter', base_dir='.')

# iterate across subjects
info = Node(IdentityInterface(fields=['sid']), name='info')
info.iterables = ('sid', ['01', '02'])

def sqr(sid, x):
    return sid, x, x**2

square = MapNode(Function(output_names=['sid', 'x', 'x2'], function=sqr),
                 iterfield=['x'], name='square')
# iterate across these values per subject
square.inputs.x = [2,4,6,8]

wf.connect(info, 'sid', square, 'sid')

# combine across subjs
join = JoinNode(IdentityInterface(fields=['sid', 'x', 'x2']), joinfield=['sid', 'x', 'x2'],
                joinsource='info', name='join')
wf.connect(square, 'sid', join, 'sid')
wf.connect(square, 'x', join, 'x')
wf.connect(square, 'x2', join, 'x2')

Thank you @mgdx, but how do you extract the result? I modified the function to return a dictionary

def sqr(sid, x):
    d = {'sid':sid, 'x':x, 'x2':x**2}
    return d

wf = Workflow('iter', base_dir='/data')

info = Node(IdentityInterface(fields=['sid']), name='info')
info.iterables = ('sid', ['01', '02'])

square = MapNode(Function(output_names=['d'], function=sqr),
                 iterfield=['x'], name='square')

square.inputs.x = [2,4,6,8]

join = JoinNode(IdentityInterface(fields=['d']), joinfield=['d'],
                joinsource='info', name='join')

wf.connect(info, 'sid', square, 'sid')
wf.connect(square, 'd', join, 'd')

wf.run()

But when I run the script, I cannot find the resulting list

>> wf.outputs

info = 
sid = None

join = 
d = None

square = 
d = None

The closest I can get to the result I want is if I do eg=wf.run()

>> res = [node for node in eg.nodes() if 'square' in node.name][0].result
>> res.outputs

Bunch(d=[{'sid': '02', 'x': 2, 'x2': 4},
       {'sid': '02', 'x': 4, 'x2': 16},
       {'sid': '02', 'x': 6, 'x2': 36},
       {'sid': '02', 'x': 8, 'x2': 64}])

But subject 01 is missing for some reason. And isn’t there a more direct way to access the result?