We've learned from the Workflow tutorial that every Nipype workflow is a directed acyclic graphs. Some workflow structures are easy to understand directly from the script and some others are too complex for that. Luckily, there is the write_graph
method!
write_graph
write_graph
allows us to visualize any workflow in five different ways:
orig
- creates a top level graph without expanding internal workflow nodesflat
- expands workflow nodes recursivelyhierarchical
- expands workflow nodes recursively with a notion on hierarchycolored
- expands workflow nodes recursively with a notion on hierarchy in colorexec
- expands workflows to depict iterablesWhich graph visualization should be used is chosen by the graph2use
parameter.
Additionally, we can also choose the format of the output file (png or svg) with the format
parameter.
A third parameter, called simple_form
can be used to specify if the node names used in the graph should be of the form nodename (package)
or nodename.Class.package
.
In [ ]:
# Import the function to create an spm fmri preprocessing workflow
from nipype.workflows.fmri.spm import create_spm_preproc
# Create the workflow object
spmflow = create_spm_preproc()
For a reason that will become clearer under the exec
visualization, let's add an iternode at the beginning of the spmflow
and connect them together under a new workflow, called metaflow
. The iternode will cause the workflow to be executed three times, once with the fwhm
value set to 4, once set to 6 and once set to 8. For more about this see the Iteration tutorial.
In [ ]:
# Import relevant modules
from nipype import IdentityInterface, Node, Workflow
# Create an iternode that iterates over three different fwhm values
inputNode = Node(IdentityInterface(fields=['fwhm']), name='iternode')
inputNode.iterables = ('fwhm', [4, 6, 8])
# Connect inputNode and spmflow in a workflow
metaflow = Workflow(name='metaflow')
metaflow.connect(inputNode, "fwhm", spmflow, "inputspec.fwhm")
In [ ]:
# Write graph of type orig
spmflow.write_graph(graph2use='orig', dotfilename='./graph_orig.dot')
# Visulaize graph
from IPython.display import Image
Image(filename="graph_orig.dot.png")
Out[ ]:
In [ ]:
# Write graph of type flat
spmflow.write_graph(graph2use='flat', dotfilename='./graph_flat.dot')
# Visulaize graph
from IPython.display import Image
Image(filename="graph_flat.dot.png")
Out[ ]:
hierarchical
graphTo better appreciate this visualization, let's look at the metaflow
workflow that has one hierarchical level more than the spmflow
.
As you can see, this visualization makes it much clearer which elements of a workflow are nodes and which ones are internal workflows. Also, each connection is shown as an individual arrow, and not just represented by one single arrow between two nodes. Additionally, iternodes and mapnodes are visualized differently than normal nodes to make them pop out more.
In [ ]:
# Write graph of type hierarchical
metaflow.write_graph(graph2use='hierarchical', dotfilename='./graph_hierarchical.dot')
# Visulaize graph
from IPython.display import Image
Image(filename="graph_hierarchical.dot.png")
Out[ ]:
In [ ]:
# Write graph of type colored
metaflow.write_graph(graph2use='colored', dotfilename='./graph_colored.dot')
# Visulaize graph
from IPython.display import Image
Image(filename="graph_colored.dot.png")
Out[ ]:
exec
graphThis visualization is the most different from the rest. Like the flat
visualization, it depicts all individual nodes. But additionally, it drops the utility
nodes from the workflow and expands workflows to depict iterables (can be seen in the detailed_graph
visualization further down below).
In [ ]:
# Write graph of type exec
metaflow.write_graph(graph2use='exec', dotfilename='./graph_exec.dot')
# Visulaize graph
from IPython.display import Image
Image(filename="graph_exec.dot.png")
Out[ ]:
The orig
, flat
and exec
visualization also create a detailed graph whenever write_graph
is executed. A detailed graph shows a node with not just the node name, but also with all its input and output parameters.
flat
graphFor example, the detailed graph of the flat
graph looks as follows:
In [ ]:
from IPython.display import Image
Image(filename="graph_flat_detailed.dot.png")
Out[ ]: