Skip to content

Commit 0a8caad

Browse files
FredLoneysatra
authored andcommitted
Support a Set join field.
1 parent 2a7bdda commit 0a8caad

File tree

2 files changed

+62
-6
lines changed

2 files changed

+62
-6
lines changed

nipype/pipeline/engine.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1855,9 +1855,10 @@ def _override_join_traits(self, basetraits, fields):
18551855
raise ValueError("The JoinNode %s does not have a field"
18561856
" named %s" % (self.name, field))
18571857
for name, trait in basetraits.items():
1858-
# if a join field is a list, then the item trait is the list
1859-
# inner trait. Otherwise, the item trait is a new Any trait.
1860-
if name in fields and isinstance(trait.trait_type, traits.List):
1858+
# if a join field has a single inner trait, then the item
1859+
# trait is that inner trait. Otherwise, the item trait is
1860+
# a new Any trait.
1861+
if name in fields and len(trait.inner_traits) == 1:
18611862
item_trait = trait.inner_traits[0]
18621863
dyntraits.add_trait(name, item_trait)
18631864
logger.debug("Converted the join node %s field %s"
@@ -1880,13 +1881,17 @@ def _collate_join_field_inputs(self):
18801881
for field in self.joinfield:
18811882
val = self._collate_input_value(field)
18821883
setattr(self._interface.inputs, field, val)
1883-
logger.debug("Collated %d inputs into each %s node join field"
1884+
logger.debug("Collated %d inputs into the %s node join fields"
18841885
% (self._next_slot_index, self))
18851886

18861887
def _collate_input_value(self, field):
1887-
return [getattr(self._inputs, self._join_item_field_name(field, idx))
1888+
val = [getattr(self._inputs, self._join_item_field_name(field, idx))
18881889
for idx in range(self._next_slot_index)]
1889-
1890+
basetrait = self._interface.inputs.trait(field)
1891+
if isinstance(basetrait.trait_type, traits.Set):
1892+
return set(val)
1893+
else:
1894+
return val
18901895

18911896
class MapNode(Node):
18921897
"""Wraps interface objects that need to be iterated on a list of inputs.

nipype/pipeline/tests/test_join.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,31 @@ def _list_outputs(self):
6363
return outputs
6464

6565

66+
_set_len = None
67+
"""The Set interface execution result."""
68+
69+
class SetInputSpec(nib.TraitedSpec):
70+
input1 = nib.traits.Set(nib.traits.Int, mandatory=True, desc='input')
71+
72+
class SetOutputSpec(nib.TraitedSpec):
73+
output1 = nib.traits.Int(desc='ouput')
74+
75+
class SetInterface(nib.BaseInterface):
76+
input_spec = SetInputSpec
77+
output_spec = SetOutputSpec
78+
79+
def _run_interface(self, runtime):
80+
runtime.returncode = 0
81+
return runtime
82+
83+
def _list_outputs(self):
84+
global _set_len
85+
outputs = self._outputs().get()
86+
_set_len = outputs['output1'] = len(self.inputs.input1)
87+
print ">>>>>>>>SET LEN: %d" % _set_len
88+
return outputs
89+
90+
6691
_products = []
6792
"""The Products interface execution results."""
6893

@@ -136,6 +161,32 @@ def test_join_expansion():
136161
os.chdir(cwd)
137162
rmtree(wd)
138163

164+
def test_set_join_node():
165+
cwd = os.getcwd()
166+
wd = mkdtemp()
167+
os.chdir(wd)
168+
169+
# Make the workflow.
170+
wf = pe.Workflow(name='test')
171+
# the iterated input node
172+
inputspec = pe.Node(IdentityInterface(fields=['n']), name='inputspec')
173+
inputspec.iterables = [('n', [1, 2, 1, 3, 2])]
174+
# a pre-join node in the iterated path
175+
pre_join1 = pe.Node(IncrementInterface(), name='pre_join1')
176+
wf.connect(inputspec, 'n', pre_join1, 'input1')
177+
# the set join node
178+
join = pe.JoinNode(SetInterface(), joinsource='inputspec',
179+
joinfield='input1', name='join')
180+
wf.connect(pre_join1, 'output1', join, 'input1')
181+
182+
wf.run()
183+
184+
# the join length is the number of unique inputs
185+
assert_equal(_set_len, 3, "The join Set output value is incorrect: %s." % _set_len)
186+
187+
os.chdir(cwd)
188+
rmtree(wd)
189+
139190

140191
if __name__ == "__main__":
141192
import nose

0 commit comments

Comments
 (0)