Skip to content

Commit dd064a9

Browse files
committed
ENH: add JoinNode notebook
1 parent 6e360d2 commit dd064a9

File tree

3 files changed

+229
-321
lines changed

3 files changed

+229
-321
lines changed

notebooks/basic_joinnodes.ipynb

Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"<img src=\"../static/images/joinnode.png\" width=\"240\">\n",
8+
"\n",
9+
"# JoinNode\n",
10+
"\n",
11+
"JoinNode have the opposite effect of a [MapNode](basic_mapnodes.ipynb) or [iterables](basic_iteration.ipynb). Where they split up the execution workflow into many different branches, a JoinNode merges them back into on node. For a more detailed explanation, check out [JoinNode, synchronize and itersource](http://nipype.readthedocs.io/en/latest/users/joinnode_and_itersource.html) from the main homepage."
12+
]
13+
},
14+
{
15+
"cell_type": "markdown",
16+
"metadata": {},
17+
"source": [
18+
"## Simple example\n",
19+
"\n",
20+
"Let's consider the very simple example depicted at the top of this page:"
21+
]
22+
},
23+
{
24+
"cell_type": "code",
25+
"execution_count": null,
26+
"metadata": {
27+
"collapsed": false
28+
},
29+
"outputs": [],
30+
"source": [
31+
"from nipype import Node, JoinNode, Workflow\n",
32+
"\n",
33+
"# Specify fake input node A\n",
34+
"a = Node(interface=A(), name=\"a\")\n",
35+
"\n",
36+
"# Iterate over fake node B's input 'in_file?\n",
37+
"b = Node(interface=B(), name=\"b\")\n",
38+
"b.iterables = ('in_file', [file1, file2])\n",
39+
"\n",
40+
"# Pass results on to fake node C\n",
41+
"c = Node(interface=C(), name=\"c\")\n",
42+
"\n",
43+
"# Join forked execution workflow in fake node D\n",
44+
"d = JoinNode(interface=D(),\n",
45+
" joinsource=\"b\",\n",
46+
" joinfield=\"in_files\",\n",
47+
" name=\"d\")\n",
48+
"\n",
49+
"# Put everything into a workflow as usual\n",
50+
"workflow = Workflow(name=\"workflow\")\n",
51+
"workflow.connect([(a, b, [('subject', 'subject')]),\n",
52+
" (b, c, [('out_file', 'in_file')])\n",
53+
" (c, d, [('out_file', 'in_files')])\n",
54+
" ])"
55+
]
56+
},
57+
{
58+
"cell_type": "markdown",
59+
"metadata": {},
60+
"source": [
61+
"As you can see, setting up a ``JoinNode`` is rather simple. The only difference to a normal ``Node`` are the ``joinsource`` and the ``joinfield``. ``joinsource`` specifies from which node the information to join is coming and the ``joinfield`` specifies the input field of the JoinNode where the information to join will be entering the node."
62+
]
63+
},
64+
{
65+
"cell_type": "markdown",
66+
"metadata": {},
67+
"source": [
68+
"## More realistic example\n",
69+
"\n",
70+
"Let's consider another example where we have one node that iterates over 3 different numbers and another node that joins those three different numbers (each coming from a separate branch of the workflow) into one list. To make the whole thing a bit more realistic, the second node will use the ``Function`` interface to do something with those numbers, before we spit them out again."
71+
]
72+
},
73+
{
74+
"cell_type": "code",
75+
"execution_count": null,
76+
"metadata": {
77+
"collapsed": true
78+
},
79+
"outputs": [],
80+
"source": [
81+
"from nipype import JoinNode, Node, Workflow\n",
82+
"from nipype.interfaces.utility import Function, IdentityInterface"
83+
]
84+
},
85+
{
86+
"cell_type": "code",
87+
"execution_count": null,
88+
"metadata": {
89+
"collapsed": true
90+
},
91+
"outputs": [],
92+
"source": [
93+
"# Create iteration node\n",
94+
"from nipype import IdentityInterface\n",
95+
"iternode = Node(IdentityInterface(fields=['number_id']),\n",
96+
" name=\"iternode\")\n",
97+
"iternode.iterables = [('number_id', [1, 4, 9])]"
98+
]
99+
},
100+
{
101+
"cell_type": "code",
102+
"execution_count": null,
103+
"metadata": {
104+
"collapsed": false
105+
},
106+
"outputs": [],
107+
"source": [
108+
"# Create join node - compute square root for each element in the joined list\n",
109+
"def compute_sqrt(numbers):\n",
110+
" from math import sqrt\n",
111+
" return [sqrt(e) for e in numbers]\n",
112+
"\n",
113+
"joinnode = JoinNode(Function(input_names=['numbers'],\n",
114+
" output_names=['sqrts'],\n",
115+
" function=compute_sqrt),\n",
116+
" name='joinnode',\n",
117+
" joinsource='iternode',\n",
118+
" joinfield=['numbers'])"
119+
]
120+
},
121+
{
122+
"cell_type": "code",
123+
"execution_count": null,
124+
"metadata": {
125+
"collapsed": false
126+
},
127+
"outputs": [
128+
{
129+
"name": "stdout",
130+
"output_type": "stream",
131+
"text": [
132+
"170306-22:38:22,861 workflow INFO:\n",
133+
"\t Workflow joinflow settings: ['check', 'execution', 'logging']\n",
134+
"170306-22:38:22,871 workflow INFO:\n",
135+
"\t Running serially.\n",
136+
"170306-22:38:22,873 workflow INFO:\n",
137+
"\t Executing node joinnode in dir: /tmp/tmpm8NCMb/joinflow/joinnode\n"
138+
]
139+
}
140+
],
141+
"source": [
142+
"# Create the workflow and run it\n",
143+
"joinflow = Workflow(name='joinflow')\n",
144+
"joinflow.connect(iternode, 'number_id', joinnode, 'numbers')\n",
145+
"res = joinflow.run()"
146+
]
147+
},
148+
{
149+
"cell_type": "markdown",
150+
"metadata": {},
151+
"source": [
152+
"Now, let's look at the input and output of the joinnode:"
153+
]
154+
},
155+
{
156+
"cell_type": "code",
157+
"execution_count": null,
158+
"metadata": {
159+
"collapsed": false
160+
},
161+
"outputs": [
162+
{
163+
"data": {
164+
"text/plain": [
165+
"\n",
166+
"sqrts = [1.0, 2.0, 3.0]"
167+
]
168+
},
169+
"execution_count": null,
170+
"metadata": {},
171+
"output_type": "execute_result"
172+
}
173+
],
174+
"source": [
175+
"res.nodes()[0].result.outputs"
176+
]
177+
},
178+
{
179+
"cell_type": "code",
180+
"execution_count": null,
181+
"metadata": {
182+
"collapsed": false
183+
},
184+
"outputs": [
185+
{
186+
"data": {
187+
"text/plain": [
188+
"\n",
189+
"function_str = <undefined>\n",
190+
"ignore_exception = <undefined>\n",
191+
"numbers = <undefined>\n",
192+
"numbersJ1 = 1\n",
193+
"numbersJ2 = 4\n",
194+
"numbersJ3 = 9"
195+
]
196+
},
197+
"execution_count": null,
198+
"metadata": {},
199+
"output_type": "execute_result"
200+
}
201+
],
202+
"source": [
203+
"res.nodes()[0].inputs"
204+
]
205+
}
206+
],
207+
"metadata": {
208+
"anaconda-cloud": {},
209+
"kernelspec": {
210+
"display_name": "Python [conda root]",
211+
"language": "python",
212+
"name": "conda-root-py"
213+
},
214+
"language_info": {
215+
"codemirror_mode": {
216+
"name": "ipython",
217+
"version": 2
218+
},
219+
"file_extension": ".py",
220+
"mimetype": "text/x-python",
221+
"name": "python",
222+
"nbconvert_exporter": "python",
223+
"pygments_lexer": "ipython2",
224+
"version": "2.7.13"
225+
}
226+
},
227+
"nbformat": 4,
228+
"nbformat_minor": 0
229+
}

0 commit comments

Comments
 (0)