Source code for pm4py.visualization.petrinet.common.visualize

'''
    This file is part of PM4Py (More Info: https://pm4py.fit.fraunhofer.de).

    PM4Py is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    PM4Py is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with PM4Py.  If not, see <https://www.gnu.org/licenses/>.
'''
import tempfile

from graphviz import Digraph

from pm4py.objects.petri_net.obj import Marking
from pm4py.util import exec_utils, constants
from pm4py.visualization.petrinet.parameters import Parameters

FORMAT = Parameters.FORMAT
DEBUG = Parameters.DEBUG
RANKDIR = Parameters.RANKDIR


[docs]def apply(net, initial_marking, final_marking, decorations=None, parameters=None): """ Apply method for Petri net visualization (it calls the graphviz_visualization method) Parameters ----------- net Petri net initial_marking Initial marking final_marking Final marking decorations Decorations for elements in the Petri net parameters Algorithm parameters Returns ----------- viz Graph object """ if parameters is None: parameters = {} image_format = exec_utils.get_param_value(Parameters.FORMAT, parameters, "png") debug = exec_utils.get_param_value(Parameters.DEBUG, parameters, False) set_rankdir = exec_utils.get_param_value(Parameters.RANKDIR, parameters, None) font_size = exec_utils.get_param_value(Parameters.FONT_SIZE, parameters, "12") return graphviz_visualization(net, image_format=image_format, initial_marking=initial_marking, final_marking=final_marking, decorations=decorations, debug=debug, set_rankdir=set_rankdir, font_size=font_size)
[docs]def graphviz_visualization(net, image_format="png", initial_marking=None, final_marking=None, decorations=None, debug=False, set_rankdir=None, font_size="12", bgcolor=constants.DEFAULT_BGCOLOR): """ Provides visualization for the petrinet Parameters ---------- net: :class:`pm4py.entities.petri.petrinet.PetriNet` Petri net image_format Format that should be associated to the image initial_marking Initial marking of the Petri net final_marking Final marking of the Petri net decorations Decorations of the Petri net (says how element must be presented) debug Enables debug mode set_rankdir Sets the rankdir to LR (horizontal layout) Returns ------- viz : Returns a graph object """ if initial_marking is None: initial_marking = Marking() if final_marking is None: final_marking = Marking() if decorations is None: decorations = {} font_size = str(font_size) filename = tempfile.NamedTemporaryFile(suffix='.gv') viz = Digraph(net.name, filename=filename.name, engine='dot', graph_attr={'bgcolor': bgcolor}) if set_rankdir: viz.graph_attr['rankdir'] = set_rankdir else: viz.graph_attr['rankdir'] = 'LR' # transitions viz.attr('node', shape='box') for t in net.transitions: if t.label is not None: if t in decorations and "label" in decorations[t] and "color" in decorations[t]: viz.node(str(id(t)), decorations[t]["label"], style='filled', fillcolor=decorations[t]["color"], border='1', fontsize=font_size) else: viz.node(str(id(t)), str(t.label), fontsize=font_size) else: if debug: viz.node(str(id(t)), str(t.name), fontsize=font_size) elif t in decorations and "color" in decorations[t] and "label" in decorations[t]: viz.node(str(id(t)), decorations[t]["label"], style='filled', fillcolor=decorations[t]["color"], fontsize=font_size) else: viz.node(str(id(t)), "", style='filled', fillcolor="black", fontsize=font_size) # places viz.attr('node', shape='circle', fixedsize='true', width='0.75') # add places, in order by their (unique) name, to avoid undeterminism in the visualization places_sort_list_im = sorted([x for x in list(net.places) if x in initial_marking], key=lambda x: x.name) places_sort_list_fm = sorted([x for x in list(net.places) if x in final_marking and not x in initial_marking], key=lambda x: x.name) places_sort_list_not_im_fm = sorted( [x for x in list(net.places) if x not in initial_marking and x not in final_marking], key=lambda x: x.name) # making the addition happen in this order: # - first, the places belonging to the initial marking # - after, the places not belonging neither to the initial marking and the final marking # - at last, the places belonging to the final marking (but not to the initial marking) # in this way, is more probable that the initial marking is on the left and the final on the right places_sort_list = places_sort_list_im + places_sort_list_not_im_fm + places_sort_list_fm for p in places_sort_list: if p in initial_marking: viz.node(str(id(p)), str(initial_marking[p]), style='filled', fillcolor="green", fontsize=font_size) elif p in final_marking: viz.node(str(id(p)), "", style='filled', fillcolor="orange", fontsize=font_size) else: if debug: viz.node(str(id(p)), str(p.name), fontsize=font_size) else: if p in decorations and "color" in decorations[p] and "label" in decorations[p]: viz.node(str(id(p)), decorations[p]["label"], style='filled', fillcolor=decorations[p]["color"], fontsize=font_size) else: viz.node(str(id(p)), "") # add arcs, in order by their source and target objects names, to avoid undeterminism in the visualization arcs_sort_list = sorted(list(net.arcs), key=lambda x: (x.source.name, x.target.name)) for a in arcs_sort_list: if a in decorations and "label" in decorations[a] and "penwidth" in decorations[a]: viz.edge(str(id(a.source)), str(id(a.target)), label=decorations[a]["label"], penwidth=decorations[a]["penwidth"], fontsize=font_size) elif a in decorations and "color" in decorations[a]: viz.edge(str(id(a.source)), str(id(a.target)), color=decorations[a]["color"], fontsize=font_size) else: viz.edge(str(id(a.source)), str(id(a.target)), fontsize=font_size) viz.attr(overlap='false') viz.format = image_format return viz