def get_graph( heu_net: HeuristicsNet, parameters: Optional[Dict[Union[str, Parameters], Any]] = None ) -> pydotplus.graphviz.Dot: """ Gets a representation of an Heuristics Net Parameters ------------- heu_net Heuristics net parameters Possible parameters of the algorithm, including: - Parameters.FORMAT Returns ------------ graph Pydotplus graph """ if parameters is None: parameters = {} graph = pydotplus.Dot(strict=True) graph.obj_dict['attributes']['bgcolor'] = 'transparent' corr_nodes = {} corr_nodes_names = {} is_frequency = False for node_name in heu_net.nodes: node = heu_net.nodes[node_name] node_occ = node.node_occ graycolor = transform_to_hex_2(max(255 - math.log(node_occ) * 9, 0)) if node.node_type == "frequency": is_frequency = True n = pydotplus.Node(name=node_name, shape="box", style="filled", label=node_name + " (" + str(node_occ) + ")", fillcolor=node.get_fill_color(graycolor), fontcolor=node.get_font_color()) else: n = pydotplus.Node( name=node_name, shape="box", style="filled", label=node_name + " (" + human_readable_stat(heu_net.sojourn_times[node_name]) + ")" if node_name in heu_net.sojourn_times else node_name + " (0s)", fillcolor=node.get_fill_color(graycolor), fontcolor=node.get_font_color()) corr_nodes[node] = n corr_nodes_names[node_name] = n graph.add_node(n) # gets max arc value max_arc_value = -1 for node_name in heu_net.nodes: node = heu_net.nodes[node_name] for other_node in node.output_connections: if other_node in corr_nodes: for edge in node.output_connections[other_node]: max_arc_value = max(max_arc_value, edge.repr_value) for node_name in heu_net.nodes: node = heu_net.nodes[node_name] for other_node in node.output_connections: if other_node in corr_nodes: for edge in node.output_connections[other_node]: this_pen_width = 1.0 + math.log(1 + edge.repr_value) / 11.0 repr_value = str(edge.repr_value) if edge.net_name: if node.node_type == "frequency": e = pydotplus.Edge( src=corr_nodes[node], dst=corr_nodes[other_node], label=edge.net_name + " (" + repr_value + ")", color=edge.get_color(), fontcolor=edge.get_font_color(), penwidth=edge.get_penwidth(this_pen_width)) else: e = pydotplus.Edge( src=corr_nodes[node], dst=corr_nodes[other_node], label=edge.net_name + " (" + human_readable_stat(repr_value) + ")", color=edge.get_color(), fontcolor=edge.get_font_color(), penwidth=edge.get_penwidth(this_pen_width)) else: if node.node_type == "frequency": e = pydotplus.Edge( src=corr_nodes[node], dst=corr_nodes[other_node], label=repr_value, color=edge.get_color(), fontcolor=edge.get_font_color(), penwidth=edge.get_penwidth(this_pen_width)) else: e = pydotplus.Edge( src=corr_nodes[node], dst=corr_nodes[other_node], label=human_readable_stat(repr_value), color=edge.get_color(), fontcolor=edge.get_font_color(), penwidth=edge.get_penwidth(this_pen_width)) graph.add_edge(e) for index, sa_list in enumerate(heu_net.start_activities): effective_sa_list = [n for n in sa_list if n in corr_nodes_names] if effective_sa_list: start_i = pydotplus.Node(name="start_" + str(index), label="@@S", color=heu_net.default_edges_color[index], fontsize="8", fontcolor="#32CD32", fillcolor="#32CD32", style="filled") graph.add_node(start_i) for node_name in effective_sa_list: sa = corr_nodes_names[node_name] if type(heu_net.start_activities[index]) is dict: occ = heu_net.start_activities[index][node_name] if occ >= heu_net.min_dfg_occurrences: if is_frequency: this_pen_width = 1.0 + math.log(1 + occ) / 11.0 if heu_net.net_name[index]: e = pydotplus.Edge( src=start_i, dst=sa, label=heu_net.net_name[index] + " (" + str(occ) + ")", color=heu_net.default_edges_color[index], fontcolor=heu_net. default_edges_color[index], penwidth=this_pen_width) else: e = pydotplus.Edge( src=start_i, dst=sa, label=str(occ), color=heu_net.default_edges_color[index], fontcolor=heu_net. default_edges_color[index], penwidth=this_pen_width) else: e = pydotplus.Edge( src=start_i, dst=sa, label=heu_net.net_name[index], color=heu_net.default_edges_color[index], fontcolor=heu_net.default_edges_color[index]) else: e = pydotplus.Edge( src=start_i, dst=sa, label=heu_net.net_name[index], color=heu_net.default_edges_color[index], fontcolor=heu_net.default_edges_color[index]) graph.add_edge(e) for index, ea_list in enumerate(heu_net.end_activities): effective_ea_list = [n for n in ea_list if n in corr_nodes_names] if effective_ea_list: end_i = pydotplus.Node(name="end_" + str(index), label="@@E", color="#FFA500", fillcolor="#FFA500", fontcolor="#FFA500", fontsize="8", style="filled") graph.add_node(end_i) for node_name in effective_ea_list: ea = corr_nodes_names[node_name] if type(heu_net.end_activities[index]) is dict: occ = heu_net.end_activities[index][node_name] if occ >= heu_net.min_dfg_occurrences: if is_frequency: this_pen_width = 1.0 + math.log(1 + occ) / 11.0 if heu_net.net_name[index]: e = pydotplus.Edge( src=ea, dst=end_i, label=heu_net.net_name[index] + " (" + str(occ) + ")", color=heu_net.default_edges_color[index], fontcolor=heu_net. default_edges_color[index], penwidth=this_pen_width) else: e = pydotplus.Edge( src=ea, dst=end_i, label=str(occ), color=heu_net.default_edges_color[index], fontcolor=heu_net. default_edges_color[index], penwidth=this_pen_width) else: e = pydotplus.Edge( src=ea, dst=end_i, label=heu_net.net_name[index], color=heu_net.default_edges_color[index], fontcolor=heu_net.default_edges_color[index]) else: e = pydotplus.Edge( src=ea, dst=end_i, label=heu_net.net_name[index], color=heu_net.default_edges_color[index], fontcolor=heu_net.default_edges_color[index]) graph.add_edge(e) return graph
def apply(heu_net, parameters=None): """ Gets a representation of an Heuristics Net Parameters ------------- heu_net Heuristics net parameters Possible parameters of the algorithm, including: - Parameters.FORMAT Returns ------------ gviz Representation of the Heuristics Net """ if parameters is None: parameters = {} image_format = exec_utils.get_param_value(Parameters.FORMAT, parameters, "png") graph = pydotplus.Dot(strict=True) graph.obj_dict['attributes']['bgcolor'] = 'transparent' corr_nodes = {} corr_nodes_names = {} is_frequency = False for node_name in heu_net.nodes: node = heu_net.nodes[node_name] node_occ = node.node_occ graycolor = transform_to_hex_2(max(255 - math.log(node_occ) * 9, 0)) if node.node_type == "frequency": is_frequency = True n = pydotplus.Node(name=node_name, shape="box", style="filled", label=node_name + " (" + str(node_occ) + ")", fillcolor=node.get_fill_color(graycolor), fontcolor=node.get_font_color()) else: n = pydotplus.Node(name=node_name, shape="box", style="filled", label=node_name, fillcolor=node.get_fill_color(graycolor), fontcolor=node.get_font_color()) corr_nodes[node] = n corr_nodes_names[node_name] = n graph.add_node(n) # gets max arc value max_arc_value = -1 for node_name in heu_net.nodes: node = heu_net.nodes[node_name] for other_node in node.output_connections: if other_node in corr_nodes: for edge in node.output_connections[other_node]: max_arc_value = max(max_arc_value, edge.repr_value) for node_name in heu_net.nodes: node = heu_net.nodes[node_name] for other_node in node.output_connections: if other_node in corr_nodes: for edge in node.output_connections[other_node]: this_pen_width = 1.0 + math.log(1 + edge.repr_value) / 11.0 repr_value = str(edge.repr_value) if edge.net_name: if node.node_type == "frequency": e = pydotplus.Edge( src=corr_nodes[node], dst=corr_nodes[other_node], label=edge.net_name + " (" + repr_value + ")", color=edge.get_color(), fontcolor=edge.get_font_color(), penwidth=edge.get_penwidth(this_pen_width)) else: e = pydotplus.Edge( src=corr_nodes[node], dst=corr_nodes[other_node], label=edge.net_name + " (" + human_readable_stat(repr_value) + ")", color=edge.get_color(), fontcolor=edge.get_font_color(), penwidth=edge.get_penwidth(this_pen_width)) else: if node.node_type == "frequency": e = pydotplus.Edge( src=corr_nodes[node], dst=corr_nodes[other_node], label=repr_value, color=edge.get_color(), fontcolor=edge.get_font_color(), penwidth=edge.get_penwidth(this_pen_width)) else: e = pydotplus.Edge( src=corr_nodes[node], dst=corr_nodes[other_node], label=human_readable_stat(repr_value), color=edge.get_color(), fontcolor=edge.get_font_color(), penwidth=edge.get_penwidth(this_pen_width)) graph.add_edge(e) for index, sa_list in enumerate(heu_net.start_activities): effective_sa_list = [n for n in sa_list if n in corr_nodes_names] if effective_sa_list: start_i = pydotplus.Node(name="start_" + str(index), label="@@S", color=heu_net.default_edges_color[index], fontsize="8", fontcolor="#32CD32", fillcolor="#32CD32", style="filled") graph.add_node(start_i) for node_name in effective_sa_list: sa = corr_nodes_names[node_name] if type(heu_net.start_activities[index]) is dict: if is_frequency: occ = heu_net.start_activities[index][node_name] this_pen_width = 1.0 + math.log(1 + occ) / 11.0 if heu_net.net_name[index]: e = pydotplus.Edge( src=start_i, dst=sa, label=heu_net.net_name[index] + " (" + str(occ) + ")", color=heu_net.default_edges_color[index], fontcolor=heu_net.default_edges_color[index], penwidth=this_pen_width) else: e = pydotplus.Edge( src=start_i, dst=sa, label=str(occ), color=heu_net.default_edges_color[index], fontcolor=heu_net.default_edges_color[index], penwidth=this_pen_width) else: e = pydotplus.Edge( src=start_i, dst=sa, label=heu_net.net_name[index], color=heu_net.default_edges_color[index], fontcolor=heu_net.default_edges_color[index]) else: e = pydotplus.Edge( src=start_i, dst=sa, label=heu_net.net_name[index], color=heu_net.default_edges_color[index], fontcolor=heu_net.default_edges_color[index]) graph.add_edge(e) for index, ea_list in enumerate(heu_net.end_activities): effective_ea_list = [n for n in ea_list if n in corr_nodes_names] if effective_ea_list: end_i = pydotplus.Node(name="end_" + str(index), label="@@E", color="#", fillcolor="#FFA500", fontcolor="#FFA500", fontsize="8", style="filled") graph.add_node(end_i) for node_name in effective_ea_list: ea = corr_nodes_names[node_name] if type(heu_net.end_activities[index]) is dict: if is_frequency: occ = heu_net.end_activities[index][node_name] this_pen_width = 1.0 + math.log(1 + occ) / 11.0 if heu_net.net_name[index]: e = pydotplus.Edge( src=ea, dst=end_i, label=heu_net.net_name[index] + " (" + str(occ) + ")", color=heu_net.default_edges_color[index], fontcolor=heu_net.default_edges_color[index], penwidth=this_pen_width) else: e = pydotplus.Edge( src=ea, dst=end_i, label=str(occ), color=heu_net.default_edges_color[index], fontcolor=heu_net.default_edges_color[index], penwidth=this_pen_width) else: e = pydotplus.Edge( src=ea, dst=end_i, label=heu_net.net_name[index], color=heu_net.default_edges_color[index], fontcolor=heu_net.default_edges_color[index]) else: e = pydotplus.Edge( src=ea, dst=end_i, label=heu_net.net_name[index], color=heu_net.default_edges_color[index], fontcolor=heu_net.default_edges_color[index]) graph.add_edge(e) file_name = tempfile.NamedTemporaryFile(suffix='.' + image_format) file_name.close() graph.write(file_name.name, format=image_format) return file_name
def graphviz_visualization( activities_count, dfg, measure="frequency", max_no_of_edges_in_diagram=170, start_activities=None, end_activities=None, ): """ Do GraphViz visualization of a DFG graph Parameters ----------- activities_count Count of attributes in the log (may include attributes that are not in the DFG graph) dfg DFG graph image_format GraphViz should be represented in this format measure Describes which measure is assigned to edges in direcly follows graph (frequency/performance) max_no_of_edges_in_diagram Maximum number of edges in the diagram allowed for visualization Returns ----------- node_edge_data node and edge dict data """ if start_activities is None: start_activities = [] if end_activities is None: end_activities = [] # first, remove edges in diagram that exceeds the maximum number of edges in the diagram dfg_key_value_list = [] for edge in dfg: dfg_key_value_list.append([edge, dfg[edge]]) dfg_key_value_list = sorted(dfg_key_value_list, key=lambda x: x[1], reverse=True) dfg_key_value_list = dfg_key_value_list[ 0 : min(len(dfg_key_value_list), max_no_of_edges_in_diagram) ] dfg_allowed_keys = [x[0] for x in dfg_key_value_list] dfg_keys = list(dfg.keys()) for edge in dfg_keys: if edge not in dfg_allowed_keys: del dfg[edge] activities_in_dfg = set() activities_count_int = copy(activities_count) for edge in dfg: activities_in_dfg.add(edge[0]) activities_in_dfg.add(edge[1]) if len(activities_in_dfg) == 0: activities_to_include = set(activities_count_int) else: activities_to_include = set(activities_in_dfg) node_edge_data = {"nodes": [], "edges": []} activities_map = {} for act in activities_to_include: if act in activities_count_int: node_edge_data["nodes"].append( {"data": {"id": act, "label": str(activities_count_int[act])}} ) activities_map[act] = str(hash(act)) else: node_edge_data["nodes"].append({"data": {"id": act, "label": None}}) activities_map[act] = str(hash(act)) # represent edges for edge in dfg: if "frequency" in measure: label = str(dfg[edge]) else: label = human_readable_stat(dfg[edge]) node_edge_data["edges"].append( {"data": {"source": edge[0], "target": edge[1], "id": label}} ) start_activities_to_include = [ act for act in start_activities if act in activities_map ] end_activities_to_include = [act for act in end_activities if act in activities_map] if start_activities_to_include: node_edge_data["nodes"].append( {"data": {"id": "start", "label": str(activities_count_int["start"])}} ) for act in start_activities_to_include: if "frequency" in measure: node_edge_data["edges"].append( { "data": { "source": "start", "target": act, "id": str(activities_count_int[act]), } } ) else: node_edge_data["edges"].append( {"data": {"source": "start", "target": act, "id": None,}} ) if end_activities_to_include: node_edge_data["nodes"].append( {"data": {"id": "end", "label": str(activities_count_int["start"])}} ) for act in end_activities_to_include: if "frequency" in measure: node_edge_data["edges"].append( { "data": { "source": act, "target": "end", "id": str(activities_count_int[act]), } } ) else: node_edge_data["edges"].append( {"data": {"source": act, "target": "end", "id": None,}} ) return node_edge_data