Skip to content

Commit 805ba52

Browse files
committed
support graph2html and simple_form options
1 parent 76eb881 commit 805ba52

File tree

5 files changed

+62
-42
lines changed

5 files changed

+62
-42
lines changed

doc/conf.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,11 @@
4242
# Add any Sphinx extension module names here, as strings. They can be extensions
4343
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
4444
extensions = ['sphinx.ext.todo',
45-
'sphinx.ext.pngmath',
45+
'sphinx.ext.imgmath',
4646
'sphinx.ext.inheritance_diagram',
4747
'sphinx.ext.graphviz',
4848
'sphinx.ext.autodoc',
4949
'sphinx.ext.doctest',
50-
'sphinx.ext.pngmath',
5150
'sphinx.ext.autosummary',
5251
'numpy_ext.numpydoc',
5352
'matplotlib.sphinxext.plot_directive',

nipype/info.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ def get_nipype_gitversion():
152152
]
153153

154154
EXTRA_REQUIRES = {
155-
'doc': ['Sphinx>=0.3', 'matplotlib', 'pydotplus'],
155+
'doc': ['Sphinx>=1.4', 'matplotlib', 'pydotplus'],
156156
'tests': TESTS_REQUIRES,
157157
'fmri': ['nitime', 'nilearn', 'dipy', 'nipy', 'matplotlib'],
158158
'profiler': ['psutil'],

nipype/pipeline/engine/utils.py

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1018,20 +1018,18 @@ def export_graph(graph_in, base_dir=None, show=False, use_execgraph=False,
10181018
suffix='_detailed.dot',
10191019
use_ext=False,
10201020
newpath=base_dir)
1021-
logger.info('Creating detailed dot file: %s' % outfname)
10221021
_write_detailed_dot(graph, outfname)
10231022
cmd = 'dot -T%s -O %s' % (format, outfname)
10241023
res = CommandLine(cmd, terminal_output='allatonce').run()
10251024
if res.runtime.returncode:
10261025
logger.warn('dot2png: %s', res.runtime.stderr)
10271026
pklgraph = _create_dot_graph(graph, show_connectinfo, simple_form)
1028-
outfname = fname_presuffix(dotfilename,
1029-
suffix='.dot',
1030-
use_ext=False,
1031-
newpath=base_dir)
1032-
nx.drawing.nx_pydot.write_dot(pklgraph, outfname)
1033-
logger.info('Creating dot file: %s' % outfname)
1034-
cmd = 'dot -T%s -O %s' % (format, outfname)
1027+
simplefname = fname_presuffix(dotfilename,
1028+
suffix='.dot',
1029+
use_ext=False,
1030+
newpath=base_dir)
1031+
nx.drawing.nx_pydot.write_dot(pklgraph, simplefname)
1032+
cmd = 'dot -T%s -O %s' % (format, simplefname)
10351033
res = CommandLine(cmd, terminal_output='allatonce').run()
10361034
if res.runtime.returncode:
10371035
logger.warn('dot2png: %s', res.runtime.stderr)
@@ -1041,6 +1039,10 @@ def export_graph(graph_in, base_dir=None, show=False, use_execgraph=False,
10411039
if show_connectinfo:
10421040
nx.draw_networkx_edge_labels(pklgraph, pos)
10431041

1042+
if format != 'dot':
1043+
outfname += '.%s' % format
1044+
return outfname
1045+
10441046

10451047
def format_dot(dotfilename, format=None):
10461048
"""Dump a directed graph (Linux only; install via `brew` on OSX)"""
@@ -1052,8 +1054,10 @@ def format_dot(dotfilename, format=None):
10521054
raise IOError("Cannot draw directed graph; executable 'dot' is unavailable")
10531055
else:
10541056
raise ioe
1055-
else:
1056-
logger.info('Converting dotfile: %s to %s format' % (dotfilename, format))
1057+
1058+
if format != 'dot':
1059+
dotfilename += '.%s' % format
1060+
return dotfilename
10571061

10581062

10591063
def make_output_dir(outdir):

nipype/pipeline/engine/workflows.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -429,15 +429,19 @@ def write_graph(self, dotfilename='graph.dot', graph2use='hierarchical',
429429
self.write_hierarchical_dotfile(dotfilename=dotfilename,
430430
colored=graph2use == "colored",
431431
simple_form=simple_form)
432-
format_dot(dotfilename, format=format)
432+
outfname = format_dot(dotfilename, format=format)
433433
else:
434434
graph = self._graph
435435
if graph2use in ['flat', 'exec']:
436436
graph = self._create_flat_graph()
437437
if graph2use == 'exec':
438438
graph = generate_expanded_graph(deepcopy(graph))
439-
export_graph(graph, base_dir, dotfilename=dotfilename,
440-
format=format, simple_form=simple_form)
439+
outfname = export_graph(graph, base_dir, dotfilename=dotfilename,
440+
format=format, simple_form=simple_form)
441+
442+
logger.info('Generated workflow graph: %s (graph2use=%s, simple_form=%s).' % (
443+
outfname, graph2use, simple_form))
444+
return outfname
441445

442446
def write_hierarchical_dotfile(self, dotfilename=None, colored=False,
443447
simple_form=True):

nipype/sphinxext/plot_workflow.py

Lines changed: 39 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
.pdf.
1111
The source code for the workflow may be included as **inline content** to
1212
the directive::
13+
1314
.. workflow::
1415
from mriqc.workflows.anatomical import airmsk_wf
1516
wf = airmsk_wf()
@@ -38,6 +39,11 @@
3839
Configuration options
3940
---------------------
4041
The workflow directive has the following configuration options:
42+
graph2use
43+
Select a graph type to use
44+
simple_form
45+
determines if the node name shown in the visualization is either of the form nodename
46+
(package) when set to True or nodename.Class.package when set to False.
4147
wf_include_source
4248
Default value for the include-source option
4349
wf_html_show_source_link
@@ -121,6 +127,8 @@ def _option_boolean(arg):
121127
else:
122128
raise ValueError('"%s" unknown boolean' % arg)
123129

130+
def _option_graph2use(arg):
131+
return directives.choice(arg, ('hierarchical', 'colored', 'flat', 'orig', 'exec'))
124132

125133
def _option_context(arg):
126134
if arg in [None, 'reset', 'close-figs']:
@@ -183,14 +191,18 @@ def setup(app):
183191
'format': _option_format,
184192
'context': _option_context,
185193
'nofigs': directives.flag,
186-
'encoding': directives.encoding
194+
'encoding': directives.encoding,
195+
'graph2use': _option_graph2use,
196+
'simple_form': _option_boolean
187197
}
188198

189199
app.add_directive('workflow', wf_directive, True, (0, 2, False), **options)
200+
app.add_config_value('graph2use', 'hierarchical', 'html')
201+
app.add_config_value('simple_form', True, 'html')
190202
app.add_config_value('wf_pre_code', None, True)
191203
app.add_config_value('wf_include_source', False, True)
192204
app.add_config_value('wf_html_show_source_link', True, True)
193-
app.add_config_value('wf_formats', ['png', 'hires.png', 'pdf'], True)
205+
app.add_config_value('wf_formats', ['png', 'svg', 'pdf'], True)
194206
app.add_config_value('wf_basedir', None, True)
195207
app.add_config_value('wf_html_show_formats', True, True)
196208
app.add_config_value('wf_rcparams', {}, True)
@@ -255,21 +267,6 @@ def remove_coding(text):
255267
TEMPLATE = """
256268
{{ source_code }}
257269
{{ only_html }}
258-
{% if source_link or (html_show_formats and not multi_image) %}
259-
(
260-
{%- if source_link -%}
261-
`Source code <{{ source_link }}>`__
262-
{%- endif -%}
263-
{%- if html_show_formats and not multi_image -%}
264-
{%- for img in images -%}
265-
{%- for fmt in img.formats -%}
266-
{%- if source_link or not loop.first -%}, {% endif -%}
267-
`{{ fmt }} <{{ dest_dir }}/{{ img.basename }}.{{ fmt }}>`__
268-
{%- endfor -%}
269-
{%- endfor -%}
270-
{%- endif -%}
271-
)
272-
{% endif %}
273270
{% for img in images %}
274271
.. figure:: {{ build_dir }}/{{ img.basename }}.{{ default_fmt }}
275272
{% for option in options -%}
@@ -285,6 +282,21 @@ def remove_coding(text):
285282
{%- endif -%}
286283
{{ caption }}
287284
{% endfor %}
285+
{% if source_link or (html_show_formats and not multi_image) %}
286+
(
287+
{%- if source_link -%}
288+
`Source code <{{ source_link }}>`__
289+
{%- endif -%}
290+
{%- if html_show_formats and not multi_image -%}
291+
{%- for img in images -%}
292+
{%- for fmt in img.formats -%}
293+
{%- if source_link or not loop.first -%}, {% endif -%}
294+
`{{ fmt }} <{{ dest_dir }}/{{ img.basename }}.{{ fmt }}>`__
295+
{%- endfor -%}
296+
{%- endfor -%}
297+
{%- endif -%}
298+
)
299+
{% endif %}
288300
{{ only_latex }}
289301
{% for img in images %}
290302
{% if 'pdf' in img.formats -%}
@@ -411,7 +423,6 @@ def _dummy_print(*arg, **kwarg):
411423
sys.stdout = stdout
412424
return ns
413425

414-
415426
def get_wf_formats(config):
416427
default_dpi = {'png': 80, 'hires.png': 200, 'pdf': 200}
417428
formats = []
@@ -436,15 +447,14 @@ def get_wf_formats(config):
436447

437448

438449
def render_figures(code, code_path, output_dir, output_base, context,
439-
function_name, config, context_reset=False,
440-
close_figs=False):
450+
function_name, config, graph2use, simple_form,
451+
context_reset=False, close_figs=False):
441452
"""
442453
Run a nipype workflow creation script and save the graph in *output_dir*.
443454
Save the images under *output_dir* with file names derived from
444455
*output_base*
445456
"""
446457
formats = get_wf_formats(config)
447-
448458
ns = wf_context if context else {}
449459
if context_reset:
450460
wf_context.clear()
@@ -457,11 +467,9 @@ def render_figures(code, code_path, output_dir, output_base, context,
457467
img_path = img.filename(fmt)
458468
imgname, ext = os.path.splitext(os.path.basename(img_path))
459469
ns['wf'].base_dir = output_dir
460-
ns['wf'].write_graph(imgname, format=ext[1:])
461-
462-
src = os.path.join(os.path.dirname(img_path), ns['wf'].name,
463-
os.path.basename(img_path))
464-
print(src, img_path)
470+
src = ns['wf'].write_graph(imgname, format=ext[1:],
471+
graph2use=graph2use,
472+
simple_form=simple_form)
465473
shutil.move(src, img_path)
466474
except Exception as err:
467475
raise GraphError(traceback.format_exc())
@@ -479,6 +487,9 @@ def run(arguments, content, options, state_machine, state, lineno):
479487
formats = get_wf_formats(config)
480488
default_fmt = formats[0][0]
481489

490+
graph2use = options.get('graph2use', 'hierarchical')
491+
simple_form = options.get('simple_form', True)
492+
482493
options.setdefault('include-source', config.wf_include_source)
483494
keep_context = 'context' in options
484495
context_opt = None if not keep_context else options['context']
@@ -577,6 +588,8 @@ def run(arguments, content, options, state_machine, state, lineno):
577588
keep_context,
578589
function_name,
579590
config,
591+
graph2use,
592+
simple_form,
580593
context_reset=context_opt == 'reset',
581594
close_figs=context_opt == 'close-figs')
582595
errors = []

0 commit comments

Comments
 (0)