Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhanced graphviz functionality #2596

Merged
merged 102 commits into from
Jul 7, 2019

Conversation

chrisjsewell
Copy link
Member

@chrisjsewell chrisjsewell commented Mar 13, 2019

fix #2585

So I don't expect this to be merged any time soon,
since all the tests would need to be rewritten (plus style fixes).
But the basic idea is I've:

  1. Used the python-graphviz package which;
    • simplifies the code and make it more 'pythonic'.
    • has a _repr_svg_() method for rendering in the notebook.
  2. Rewritten the function as a class, which
    • maintains a cache of the added nodes and graphs (as sets)
    • splits up the function and allows for multiple additions to the same graph
    • has separate _style_ functions for different node classes

Here are two examples of using it in the notebook.

The first is a replication of the original function, with some extras.

Screen Shot 2019-03-13 at 20 47 04

The second is new functionality, that was the original reason I started writing this.
It visualizes a root node and filtered connecting nodes, without any intermediate connections.

Screen Shot 2019-03-13 at 21 27 36

@chrisjsewell
Copy link
Member Author

Oh and I've just noticed the actual name of the file would need to be change
(from graphviz.py), so there is not an import clash

@chrisjsewell
Copy link
Member Author

chrisjsewell commented Mar 13, 2019

and if you were to get really fancy;
plugins could provide something like aiida.graph.style entry_points, to define how any of their node classes are styled in the graph (e.g. adding class specific information to the label, like I have done for CifData)

@ltalirz
Copy link
Member

ltalirz commented Mar 14, 2019

@chrisjsewell very cool!
I would propose to schedule a discussion on this during the plugin migration week unless others want to move forward with this even before.
mentioning @giovannipizzi @sphuber

@giovannipizzi
Copy link
Member

Very nice! Indeed let's discuss in person - I'd also like to brainstorm if we can unify in a single place the routines to describe a node (e.g. we now have get_desc()that should probably move out of the Node subclasses, we should unify with the generation of text-only (for Graphviz), HTML string (for Materials Cloud), information on what to visualise (for Materials Cloud), ...

I.e., we should probably have a "visualiser" class that for every class know what an how to visualise it (and I see some possibilities to merge with @chrisjsewell idea of 'style' entry points).
We should also look at how jupyter provides multiple output formats when displaying classes (text, html, ...) to get inspiration.

@chrisjsewell
Copy link
Member Author

chrisjsewell commented Apr 17, 2019

@ltalirz @sphuber @giovannipizzi I have updated this module to be compatible with the current develop branch (i.e. v1.0.0b2). I have also streamlined (to some extent) the mapping of node/link -> visualisation, implementing four default mapping functions:

  1. LinkType's -> graphviz edge style dict, e.g. {"style": "dashed", "color": "blue"}
  2. Data.class_node_type -> graphviz node style dict, e.g. {"shape": "diamond", "color": "blue"} (defaulting to node.get_style_default() if available)
  3. Data.class_node_type -> a data-type specific sub-label (defaulting to node.get_description())
  4. ProcessNode.class_node_type -> graphviz node style dict, similar to Data, but also colour by success/failure

The default mapping functions can also be overridden by the user, on instantiation of the Graph class, (by providing alternate functions), making it easy to customise.

Below, I attach a notebook and screenshot, replicating your AddAndMultiplyWorkChain example:

Provenance_Graphviz.ipynb.txt

image

@coveralls
Copy link

Coverage Status

Coverage decreased (-0.1%) to 71.544% when pulling 07fe0f5 on chrisjsewell:enhanced-graphviz into 3a35710 on aiidateam:develop.

@coveralls
Copy link

coveralls commented Apr 18, 2019

Coverage Status

Coverage increased (+0.1%) to 74.435% when pulling 4753cf1 on chrisjsewell:enhanced-graphviz into 19ed82e on aiidateam:develop.

@chrisjsewell
Copy link
Member Author

chrisjsewell commented Jul 4, 2019

does this seem reasonable to you as well

Yeh as I've mentioned, I added the functionality, for it to be fairly easy to change styles, at the user level. So I'm not necessarily to bothered what the defaults are, as I may choose not to use them :)
Personally, the edges are fine, but I'd prefer a shape difference between Work processes and Calc processes, and I think there's probably a case for two color "modes":

  • Process analysis: Data = white, Failed Processes = red, Running Processes = orange, Successful processes = green.
  • Presentational: with distinct colors for different node types.

You could maybe mix them (using different background/font colors), but that gets a bit messy.

Perhaps I should add an easy way of switching?

@chrisjsewell
Copy link
Member Author

chrisjsewell commented Jul 4, 2019

Ok, in b0c2be0, I have applied @ltalirz's style format. I have also merged default_process_styles and default_data_styles into default_node_styles, and added a pstate_node_styles.

From aiida/backends/tests/tools/visualization/test_graph.py, you can create (just uncomment the render line):

test_graph_graphviz_source:

graph = graph_mod.Graph()
graph.recurse_descendants(nodes.pd0)

image

test_graph_graphviz_source_pstate:

graph = graph_mod.Graph(node_style_fn=pstate_node_styles)
graph.recurse_descendants(nodes.pd0)

image

and obviously, you can just copy one of these functions, and make your own style very easily.

Copy link
Member

@ltalirz ltalirz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dear @chrisjsewell, thank you so much for implementing all these changes!

Here come my final comments, after this I'm happy to merge:

  • I'm now getting the following warnings - not quite sure why?
verdi graph generate 31317b2e-d126-4fdc-a2a8-80f1a9aa773b
Info: Initiating graphviz engine: dot
Info: Recursing ancestors, max depth=None
Info: Recursing descendants, max depth=None
Warning: gvrender_set_style: unsupported style rectangle - ignoring
Warning: gvrender_set_style: unsupported style rectangle - ignoring
Warning: gvrender_set_style: unsupported style rectangle - ignoring
Warning: gvrender_set_style: unsupported style rectangle - ignoring
Warning: gvrender_set_style: unsupported style rectangle - ignoring
Warning: gvrender_set_style: unsupported style rectangle - ignoring
Warning: gvrender_set_style: unsupported style rectangle - ignoring
Warning: gvrender_set_style: unsupported style rectangle - ignoring
Warning: gvrender_set_style: unsupported style rectangle - ignoring
Warning: gvrender_set_style: unsupported style rectangle - ignoring
Warning: gvrender_set_style: unsupported style rectangle - ignoring
Warning: gvrender_set_style: unsupported style rectangle - ignoring
Warning: gvrender_set_style: unsupported style rectangle - ignoring
Warning: gvrender_set_style: unsupported style rectangle - ignoring
Success: Output file: 32.dot.pdf
  • Please add a uuid/pk switch at the command line as well. I would personally even vote to make uuid the default but that is not an issue as long as one can easily switch (something like --id-label)
  • Could we move to a color different from white for workfunctions? Something that looks related to the color of the WorkChain?
  • My style, by default, removed the borders of the shapes because I feel they are just adding lines that aren't really needed (?)
  • Do we still want to add the hint on the status of process nodes by adding a red/yellow/green border for those?

@chrisjsewell
Copy link
Member Author

chrisjsewell commented Jul 5, 2019

Thanks @ltalirz

I'm now getting the following warnings

Oops, there was a typo in specifying styles for WorkFunctionNodes (the only process type I didn't include in the tests!), hopefully fixed in 0b5087f

Could we move to a color different from white for workfunctions?

It was white because of the above error, should be the same color as WorkChains now

Please add a uuid/pk switch at the command line

added in 9076f2b

My style, by default, removed the borders of the shapes

fixed in a8f6009

Do we still want to add the hint on the status of process nodes by adding a red/yellow/green border for those?

I leave that up to you, @giovannipizzi and @sphuber?

@ltalirz
Copy link
Member

ltalirz commented Jul 5, 2019

@chrisjsewell Thanks, for me it's good to merge
Let's give @sphuber and @giovannipizzi a few hours to reply - otherwise I'll go ahead.

I would simply "squash & merge" if that's OK with you.
If you like to keep any topical commits separated, I would ask you to rebase into, say, no more than 5.

@chrisjsewell
Copy link
Member Author

Yep "squash & merge" will be fine thanks @ltalirz

@ltalirz ltalirz self-requested a review July 5, 2019 12:58
ltalirz
ltalirz previously approved these changes Jul 5, 2019
Copy link
Contributor

@sphuber sphuber left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just some minor comments/questions. Other than that I'd be happy to merge this. Great work @chrisjsewell and thanks a lot for all the reviewing @ltalirz ! 👍

aiida/cmdline/commands/cmd_graph.py Show resolved Hide resolved
aiida/cmdline/commands/cmd_graph.py Show resolved Hide resolved
def generate(root_node, link_types, id_label, ancestor_depth, descendant_depth, process_out, process_in, engine,
verbose, output_format, show):
"""
Generate a graph from a ROOT_NODE (specified by pk or uuid).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think technically the node label could also be used. Granted it won't be that common. I think it would maybe be better to use the term "identifier". This is used across the CLI to mean one of PK, UUID, or label.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in 6e599e9

aiida/cmdline/commands/cmd_graph.py Outdated Show resolved Hide resolved
'aiida.transports',
'aiida.tools.dbimporters.plugins',
'aiida.cmdline.utils', 'aiida.cmdline.params.types', 'aiida.cmdline.params.options', 'aiida.common',
'aiida.schedulers', 'aiida.transports', 'aiida.tools.dbimporters.plugins', 'aiida.tools.visualization'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think all the tests are actually in the module aiida.backends correct? And I don't see any in aiida.tools.visualization, so it is not necessary to add it here

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in 6e599e9

"process.calculation.calcjob.CalcJobNode.": {
"shape": "ellipse",
"style": "filled",
# "pencolor": "black",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we are not using the pencolor, maybe get rid of the commented out code

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in 6e599e9

node_style['fillcolor'] = '#de707fff' # red
elif node.is_finished_ok:
node_style['fillcolor'] = '#8cd499ff' # green
else: # specifically look for waiting state?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that this conditional will hit the states CREATED and RUNNING as well. Think that the same color as WAITING is fine, just thought I'd mention it. Maybe update the comment to include them

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in 6e599e9

"""
# pylint: disable=too-many-branches

class_node_type = node.class_node_type
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I take it this code can be cleaned up when we address #3087 and we define a node method that will provide this type of descriptor?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes indeed. Basically all the node classes should supply their own (default) description, and this function (which is injected into the Graph class) can just be used by the user, to override any descriptions they wish.

@ltalirz
Copy link
Member

ltalirz commented Jul 7, 2019

@sphuber Looks to me like your points have been addressed
I leave the final merge up to you

@sphuber sphuber merged commit ad5d26f into aiidateam:develop Jul 7, 2019
@sphuber
Copy link
Contributor

sphuber commented Jul 7, 2019

Thanks a lot to both !

@chrisjsewell chrisjsewell deleted the enhanced-graphviz branch July 8, 2019 03:52
d-tomerini pushed a commit to d-tomerini/aiida_core that referenced this pull request Sep 30, 2019
The `python-graphviz` package is employed to simplify the code that can
build a visual representation of a sub set of the provenance graph. The
main graphing function is rewritten as a class, which:

 * maintains a cache of the added nodes and graphs (as sets)
 * splits up the function and allows for multiple additions to the graph
 * has separate `_style_` functions for different node classes

This gives larger control to define the graph that is to be visualized
as well as the style to be used. The current style is adapted to resemble
that of the documentation for a coherent look.
d-tomerini pushed a commit to d-tomerini/aiida_core that referenced this pull request Oct 16, 2019
The `python-graphviz` package is employed to simplify the code that can
build a visual representation of a sub set of the provenance graph. The
main graphing function is rewritten as a class, which:

 * maintains a cache of the added nodes and graphs (as sets)
 * splits up the function and allows for multiple additions to the graph
 * has separate `_style_` functions for different node classes

This gives larger control to define the graph that is to be visualized
as well as the style to be used. The current style is adapted to resemble
that of the documentation for a coherent look.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

verdi graph generate should create a pdf by default
7 participants