def single_layer(list_of_task_dicts: list, list_of_task_tuples: list,
                 recursive_depth: int, parent: str, file_name: str) -> None:
    """
    each SVG has nodes and hyperlinks; no subgraphs
    """
    use_case = AGraph(directed=True)
    use_case.clear()
    use_case.graph_attr.update(compound="true")
    for task_tup in list_of_task_tuples:
        #print(task_tup)
        if task_has_children_in_list_of_task_dicts(task_tup,
                                                   list_of_task_dicts):
            #print("    has child, so hyperlink")
            use_case.add_node(
                smush(task_tup),
                label=with_spaces(task_tup),
                color="blue",  # to indicate hyperlink
                shape=
                "rectangle",  # to distinguish from nodes that do not have children
                href="single_layer_" + str(recursive_depth + 1) + "_" +
                smush(task_tup) + ".svg")
            for task_dist in list_of_task_dicts:
                if task_tup in task_dist.keys():
                    #for task_tup in task_dist[task_tup]:
                    single_layer(list_of_task_dicts,
                                 task_dist[task_tup],
                                 recursive_depth + 1,
                                 "single_layer_" + str(recursive_depth) + "_" +
                                 file_name,
                                 file_name=smush(task_tup))
        else:
            #print("    no children, so create node")
            use_case.add_node(smush(task_tup), label=with_spaces(task_tup))
    if recursive_depth > 0:
        use_case.add_node("zoom out",
                          href=parent + ".svg",
                          color="red",
                          shape="triangle")

    for index, task_tup in enumerate(list_of_task_tuples[1:]):
        use_case.add_edge(smush(list_of_task_tuples[index]), smush(task_tup))
    use_case.write("single_layer_" + str(recursive_depth) + "_" + file_name +
                   ".dot")
    use_case.draw("single_layer_" + str(recursive_depth) + "_" + file_name +
                  ".svg",
                  format="svg",
                  prog="dot")

    return
def generate_single_svg(list_of_task_dicts: list, list_of_toplevel_steps: list,
                        file_name: str) -> None:
    """
    make a single graph with a bunch of subgraphs
    in contrast to the layered SVG approach, here each node name must be unique
    """
    use_case = AGraph(directed=True)
    use_case.clear()
    use_case.graph_attr.update(compound="true")
    add_subgraph(list_of_task_dicts,
                 use_case,
                 list_of_toplevel_steps,
                 parent="")
    use_case.write(file_name + ".dot")
    use_case.draw(file_name + ".svg", format="svg", prog="dot")
    return
def create_allinone(edge_list:list, list_of_dicts:list, parent_name: str) -> None:
    """

    """
    use_case = AGraph(directed=True)
    use_case.clear()
    use_case.graph_attr.update(compound="true")

    for edge_pair in edge_list:
        #print(with_spaces(edge_pair[0]),"to", with_spaces(edge_pair[1]))
        allinone(graph=use_case,
                     edge_pair=edge_pair,
                     list_of_dicts=list_of_dicts,
                     parent_name=parent_name)

    use_case.write("allinone.dot")
    use_case.draw("allinone.svg", format="svg", prog="dot")
    return
示例#4
0
class Graph(object):
    def __init__(self, graph_dict={}):
        self.__graph_dict = graph_dict
        self.__G = AGraph()

    def add_vertex(self, v):
        if (v not in self.__graph_dict):
            self.__graph_dict[v] = []
        self.__G.add_node(v)

    def add_edge(self, u, v):
        if (u not in self.__graph_dict):
            self.__graph_dict[u] = [v]
        else:
            self.__graph_dict[u].append(v)

        self.__G.add_edge(u, v)

    def draw(self, fn):
        print(self.__graph_dict)
        self.__G.draw(fn, prog="circo")
        Image.open(fn).show()

    def clear(self):
        self.__graph_dict = {}
        self.__G.clear()

    def isConnected(self, path=None, start_vertex=None):
        if path == None:
            path = set()
        vertices = list(
            self.__graph_dict.keys())  # "list" necessary in Python 3
        if start_vertex == None:
            start_vertex = vertices[0]
        path.add(start_vertex)

        if len(path) == len(vertices):
            return True
        else:
            for v in self.__graph_dict[start_vertex]:
                if v not in path:
                    if self.isConnected(path, v):
                        return True
        return False
def linked_layers(edge_list:list,list_of_dicts:list,parent_name:str) -> None:
    """

    """
    use_case = AGraph(directed=True)
    use_case.clear()
    use_case.graph_attr.update(compound="true")
    # use_case.add_node("up",
    #                   label="up",
    #                   shape="rectangle",
    #                   color="blue",
    #                   href=parent_name+".svg")

    for edge_pair in edge_list:
        if task_has_children_in_list_of_dicts(edge_pair[0], list_of_dicts):
            sg = use_case.subgraph(name="cluster_"+parent_name+smush(edge_pair[0]),
                                   label=with_spaces(edge_pair[0]))
            sg.add_node(parent_name+smush(edge_pair[0]), style="invis")
            for sg_edge_pair in get_subgraph(edge_pair[0],list_of_dicts):
                if task_has_children_in_list_of_dicts(sg_edge_pair[0],list_of_dicts):
                    sg.add_node(parent_name+smush(edge_pair[0])+smush(sg_edge_pair[0]),
                                label=with_spaces(sg_edge_pair[0]),
                                shape="rectangle",
                                color="blue",
                                # name length is limited to 10 characters to
                                # avoid file names that exceed OS limits.
                                href=parent_name+"_"+smush(edge_pair[0])[:10]+".svg")
                    if not path.exists(parent_name+"_"+smush(edge_pair[0])[:10]+".svg"):
                        linked_layers(get_subgraph(edge_pair[0],list_of_dicts),
                                      list_of_dicts,
                                      parent_name+"_"+smush(edge_pair[0])[:10])
                else:
                    sg.add_node(parent_name+smush(edge_pair[0])+smush(sg_edge_pair[0]),
                                label=with_spaces(sg_edge_pair[0]))
                if sg_edge_pair[1] is not None:
                    if task_has_children_in_list_of_dicts(sg_edge_pair[1],list_of_dicts):
                        sg.add_node(parent_name+smush(edge_pair[0])+smush(sg_edge_pair[1]),
                                    label=with_spaces(sg_edge_pair[1]),
                                    shape="rectangle",
                                    color="blue",
                                    href=parent_name+"_"+smush(edge_pair[0])[:10]+".svg")
                        if not path.exists(parent_name+"_"+smush(edge_pair[0])[:10]+".svg"):
                            linked_layers(get_subgraph(edge_pair[0],list_of_dicts),
                                          list_of_dicts,
                                          parent_name+"_"+smush(edge_pair[0])[:10])
                    else:
                        sg.add_node(parent_name+smush(edge_pair[0])+smush(sg_edge_pair[1]),
                                    label=with_spaces(sg_edge_pair[1]))
                    sg.add_edge(parent_name+smush(edge_pair[0])+smush(sg_edge_pair[0]),
                                parent_name+smush(edge_pair[0])+smush(sg_edge_pair[1]))#,constraint=False)
        else: # node does not have children
            use_case.add_node(parent_name+smush(edge_pair[0]),
                              label=with_spaces(edge_pair[0]))
        if edge_pair[1] is not None:
            if task_has_children_in_list_of_dicts(edge_pair[1], list_of_dicts):
                sg = use_case.subgraph(name="cluster_"+parent_name+smush(edge_pair[1]),
                                       label=with_spaces(edge_pair[1]))
                sg.add_node(parent_name+smush(edge_pair[1]), style="invis")
                for sg_edge_pair in get_subgraph(edge_pair[1],list_of_dicts):
                    if task_has_children_in_list_of_dicts(sg_edge_pair[0], list_of_dicts):
                        sg.add_node(parent_name+smush(edge_pair[1])+smush(sg_edge_pair[0]),
                                    label=with_spaces(sg_edge_pair[0]),
                                    shape="rectangle",
                                    color="blue",
                                    href=parent_name+"_"+smush(edge_pair[1])[:10]+".svg")
                        if not path.exists(parent_name+"_"+smush(edge_pair[1])[:10]+".svg"):
                            linked_layers(get_subgraph(edge_pair[1],list_of_dicts),
                                          list_of_dicts,
                                          parent_name+"_"+smush(edge_pair[1])[:10])
                    else:
                        sg.add_node(parent_name+smush(edge_pair[1])+smush(sg_edge_pair[0]),
                                    label=with_spaces(sg_edge_pair[0]))
                    if sg_edge_pair[1] is not None:
                        if task_has_children_in_list_of_dicts(sg_edge_pair[1], list_of_dicts):
                            sg.add_node(parent_name+smush(edge_pair[1])+smush(sg_edge_pair[1]),
                                        label=with_spaces(sg_edge_pair[1]),
                                        shape="rectangle",
                                        color="blue",
                                        href=parent_name+"_"+smush(edge_pair[1])[:10]+".svg")
                            if not path.exists(parent_name+"_"+smush(edge_pair[1])[:10]+".svg"):
                                linked_layers(get_subgraph(edge_pair[1],list_of_dicts),
                                              list_of_dicts,
                                              parent_name+"_"+smush(edge_pair[1])[:10])
                        else:
                            sg.add_node(parent_name+smush(edge_pair[1])+smush(sg_edge_pair[1]),
                                        label=with_spaces(sg_edge_pair[1]))
                        sg.add_edge(parent_name+smush(edge_pair[1])+smush(sg_edge_pair[0]),
                                    parent_name+smush(edge_pair[1])+smush(sg_edge_pair[1]))#,constraint=False)
            else: # node does not have children
                use_case.add_node(parent_name+smush(edge_pair[1]),
                                  label=with_spaces(edge_pair[1]))
            use_case.add_edge(parent_name+smush(edge_pair[0]),
                              parent_name+smush(edge_pair[1]))
    print("parent name =",parent_name)
    use_case.write(parent_name+".dot")
    use_case.draw(parent_name+".svg", format="svg", prog="dot")

    return
示例#6
0
#!/usr/bin/env python3

# Useful introduction to Graphviz:
# https://www.worthe-it.co.za/blog/2017-09-19-quick-introduction-to-graphviz.html

# need "pip install pygraphviz"
# which requires a local installation of graphviz
from pygraphviz import AGraph
# https://pygraphviz.github.io/documentation/latest/reference/agraph.html

# import generate_graphviz as gg
if __name__ == "__main__":
    use_case = AGraph(directed=True,
                      comment="an example")  #, ratio="0.5")#, compound=True)
    use_case.clear()

    width = 40

    use_case.add_node("TOF repair with PR", shape="rectangle")
    use_case.add_node("lv_or_rv",
                      label="severly decreased LV or RV systolic function")
    use_case.add_edge("TOF repair with PR", "lv_or_rv")
    use_case.add_node(
        "achd_class_1",
        label=
        "evaluation by an ACHD cardiologist and \nadvanced HF team (class I)",
        shape="rectangle",
        constraint=False)
    use_case.add_edge("lv_or_rv", "achd_class_1", label="yes", color="green")
    use_case.add_edge("achd_class_1", "symptoms?", style="invis")
    use_case.add_edge("lv_or_rv", "PR severity", label="no", color="red")
def this_layer_plus_one(list_of_task_dicts: list, list_of_subtasks: list,
                        output_filename: str, recursive_depth: int,
                        parent: str) -> None:
    """
    recursively create hyperlinked SVGs using GraphViz
    input data structure is a list of dicts
    """

    # need the filename prefix for both this file and the child files
    fnamel = "layer_plus_one_" + str(recursive_depth) + "_"
    fnamel1 = "layer_plus_one_" + str(recursive_depth + 1) + "_"

    # initialize a new graph for this layer
    use_case = AGraph(directed=True,
                      comment=output_filename)  #, compound=True)
    use_case.clear()
    use_case.graph_attr.update(compound="true")
    for task in list_of_subtasks:
        #print(task)
        for this_dict in list_of_task_dicts:
            if list(this_dict.keys())[0] == task:

                #unique_subgraph_name = task_without_spaces#+"_"+str(random.randint(1000,9999))
                if (task_has_children_in_list_of_task_dicts(
                        task, list_of_task_dicts)):
                    sg = use_case.subgraph(name="cluster_" + smush(task),
                                           label=with_spaces(task),
                                           href=fnamel1 + smush(task) + ".svg")
                else:  # no href to SVG because there are no child nodes
                    sg = use_case.subgraph(name="cluster_" + smush(task),
                                           label=with_spaces(task))

                sg.add_node(smush(task), style="invis")

                #print(task)
                #print(list(this_dict.keys())[0])
                subitem_list = list(this_dict.values())[0]
                #                print(subitem_list)

                if len(subitem_list) < 2:  # no edges to connect
                    if (task_has_children_in_list_of_task_dicts(
                            subitem_list[0], list_of_task_dicts)):
                        sg.add_node(smush(task) + smush(subitem_list[0]),
                                    label=with_spaces(subitem_list[0]),
                                    href=fnamel1 + smush(task) + ".svg",
                                    color="blue",
                                    shape="rectangle")
                    else:
                        sg.add_node(smush(task) + smush(subitem_list[0]),
                                    label=with_spaces(subitem_list[0]),
                                    shape="rectangle")
                    sg.add_edge(smush(task) + smush(subitem_list[0]),
                                smush(task),
                                style="invis")

                else:
                    for index, subitem in enumerate(subitem_list[1:]):
                        #print('   ',subitem)
                        if (task_has_children_in_list_of_task_dicts(
                                subitem_list[index], list_of_task_dicts)):
                            sg.add_node(smush(task) +
                                        smush(subitem_list[index]),
                                        label=with_spaces(subitem_list[index]),
                                        href=fnamel1 + smush(task) + ".svg",
                                        color="blue",
                                        shape="rectangle")
                        else:  # no children to link to
                            sg.add_node(smush(task) +
                                        smush(subitem_list[index]),
                                        label=with_spaces(subitem_list[index]),
                                        shape="rectangle")
                        if (task_has_children_in_list_of_task_dicts(
                                subitem, list_of_task_dicts)):
                            sg.add_node(smush(task) + smush(subitem),
                                        label=with_spaces(subitem),
                                        href=fnamel1 + smush(task) + ".svg",
                                        color="blue",
                                        shape="rectangle")
                        else:
                            sg.add_node(smush(task) + smush(subitem),
                                        label=with_spaces(subitem),
                                        shape="rectangle")

                        # every sequence of tasks is ordered, so link task with prior task
                        sg.add_edge(
                            smush(task) + smush(subitem_list[index]),
                            smush(task) + smush(subitem))
                        if index == len(
                                subitem_list
                        ):  # last item links to invisible node in order to force invisible node to bottom of subgraph
                            sg.add_edge(smush(task) +
                                        smush(subitem_list[index]),
                                        smush(task),
                                        style="invis")

    for index, task_tup in enumerate(list_of_subtasks[1:]):
        # use_case.add_node(smush(list_of_subtasks[index]),label=with_spaces(task_tup),shape="rectangle")
        # use_case.add_node(smush(task_tup),label=with_spaces(task_tup),shape="rectangle")
        use_case.add_edge(smush(list_of_subtasks[index]),
                          smush(task_tup),
                          ltail="cluster_" + smush(list_of_subtasks[index]),
                          lhead="cluster_" + smush(task_tup))

    if recursive_depth > 0:
        use_case.add_node("zoom out",
                          href=parent + ".svg",
                          color="red",
                          shape="triangle")
    #use_case.write()
    use_case.draw(fnamel + output_filename + ".svg", format="svg", prog="dot")
    #print("drew SVG for ", output_filename)

    for task_tuple in list_of_subtasks:
        for index, this_dict in enumerate(list_of_task_dicts):
            if task_tuple in this_dict.keys():
                this_layer_plus_one(list_of_task_dicts,
                                    list_of_task_dicts[index][task_tuple],
                                    smush(task_tuple), recursive_depth + 1,
                                    fnamel + output_filename)
    return