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
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