diff --git a/src/graph.py b/src/graph.py index e4910e4e713b9f1f837d2ddec5de77b38396bb4c..15177a5fd58d9a4542d9e729237bda059320186f 100644 --- a/src/graph.py +++ b/src/graph.py @@ -308,6 +308,19 @@ class Graph(): generate_graph(self.get_output_dir()/'graphs'/"user_view", user_view, label_edge=True, label_node=True, render_graphs = render_graphs) generate_graph(self.get_output_dir()/'graphs'/"user_view_with_subworkflows", user_view_with_subworkflows, label_edge=True, label_node=True, render_graphs = render_graphs) + #============================ + #GENERATE LEVEL GRAPHS + #============================ + def generate_level_graphs(self, render_graphs = True, label_edge=True, label_node=True): + #dico = self.dico_process_dependency_graph + dico = self.full_dico + max_level = get_max_level(dico) + for l in range(max_level+1): + new_dico = get_graph_level_l(dico, l) + #print(new_dico) + generate_graph(self.get_output_dir()/'graphs'/f"level_{l}", new_dico, label_edge=label_edge, label_node=label_node, render_graphs = render_graphs) + + diff --git a/src/nextflow_file.py b/src/nextflow_file.py index a90e4bbb78488d148f1a2606410d51aa2d66ea0a..3566e4ebafe81a44e15416d3e7b25497523cfa96 100644 --- a/src/nextflow_file.py +++ b/src/nextflow_file.py @@ -711,6 +711,10 @@ class Nextflow_File(Nextflow_Building_Blocks): self.graph.initialise(processes_2_remove = processes_2_remove) self.graph.generate_user_view(relevant_processes = relevant_processes, render_graphs = render_graphs) + def generate_level_graphs(self, render_graphs = True, processes_2_remove = [], label_edge=True, label_node=True): + self.graph.initialise(processes_2_remove = processes_2_remove) + self.graph.generate_level_graphs(render_graphs = render_graphs, label_edge=label_edge, label_node=label_node) + def get_graph(self): return self.graph #def get_metadata_graph_wo_operations(self): diff --git a/src/outils_graph.py b/src/outils_graph.py index a6394466581dcb7f0f66436b0aaf27196d8b323f..8ea7184ef6f5f09b72f4194573e2b9d84ff87bf6 100644 --- a/src/outils_graph.py +++ b/src/outils_graph.py @@ -799,5 +799,99 @@ def add_subworkflows_2_dico(full_dico, flattened_dico, add_root_nodes = True): new_dico["nodes"].append({"id": "output","name": "o","shape": "triangle", "fillcolor":"#ffffff"}) return new_dico +def get_max_level(dico, val = 0): + max_val = val + for sub in dico["subworkflows"]: + tmp = get_max_level(dico["subworkflows"][sub], val = val+1) + if(max_val<tmp): + max_val = tmp + return max_val + +def get_graph_level_l(dico, level): + + import time + tag = str(time.time()) + + def fill_node_2_subworkflows(dico, node_2_subworkflows, back_log_subworklows = []): + for n in dico["nodes"]: + node_2_subworkflows[n['id']] = back_log_subworklows + for sub in dico["subworkflows"]: + fill_node_2_subworkflows(dico["subworkflows"][sub], node_2_subworkflows, back_log_subworklows+[sub]) + node_2_subworkflows = {} + fill_node_2_subworkflows(dico, node_2_subworkflows) + #print(node_2_subworkflows) + + def add_nodes(dico, level, current_level): + + + new_dico = {} + new_dico['nodes'] = [] + new_dico['edges'] = [] + new_dico['subworkflows'] = {} + for n in dico["nodes"]: + new_dico["nodes"].append(n) + if(current_level==level): + for sub in dico["subworkflows"]: + n = {"id": f"id_{tag}_{sub}","name": sub,"shape": "rectangle", "fillcolor":"#FFA500"} + new_dico["nodes"].append(n) + else: + for sub in dico["subworkflows"]: + new_dico['subworkflows'][sub] = add_nodes(dico["subworkflows"][sub], level, current_level+1) + return new_dico + + new_dico = add_nodes(dico, level, current_level=0) + + def get_all_edges(dico): + edges = [] + edges+=dico["edges"] + for sub in dico["subworkflows"]: + edges+=get_all_edges(dico["subworkflows"][sub]) + return edges + + already_added = [] + for edge in get_all_edges(dico): + tmp = -1 + #Case A and B not in the level + if(len(node_2_subworkflows[edge['A']])<=level and + len(node_2_subworkflows[edge['B']])<=level): + new_dico['edges'].append(edge) + + + #Case A and B are in the level + elif(len(node_2_subworkflows[edge['A']])>level and + len(node_2_subworkflows[edge['B']])>level): + sub1 = node_2_subworkflows[edge['A']][level] + sub2 = node_2_subworkflows[edge['B']][level] + if(sub1!=sub2): + tmp = {'A':f"id_{tag}_{sub1}", + 'B':f"id_{tag}_{sub2}", "label": ""} + + + #Case A in level but not B + elif(len(node_2_subworkflows[edge['A']])<=level and + len(node_2_subworkflows[edge['B']])>level): + sub2 = node_2_subworkflows[edge['B']][level] + tmp = {'A':edge['A'], + 'B':f"id_{tag}_{sub2}", "label": ""} + + + #Case B in level but not A + elif(len(node_2_subworkflows[edge['A']])>level and + len(node_2_subworkflows[edge['B']])<=level): + sub1 = node_2_subworkflows[edge['A']][level] + tmp = {'A':f"id_{tag}_{sub1}", + 'B':edge['B'], "label": ""} + else: + raise Exception("This shloudn't happen") + + #TODO Here i have enforced single edge between subworkflows + if(tmp!=-1 and tmp not in already_added): + already_added.append(tmp) + new_dico['edges'].append(tmp) + + return new_dico + + + diff --git a/src/workflow.py b/src/workflow.py index 310bcd47bbe671b28ef649cbc1de3fb4102d01c6..574f66f82048b96f11c18247a0b381ac10661b7e 100644 --- a/src/workflow.py +++ b/src/workflow.py @@ -553,6 +553,10 @@ George Marchment, Bryan Brancotte, Marie Schmit, Frédéric Lemoine, Sarah Cohen self.iniatilise_tab_processes_2_remove() self.nextflow_file.generate_user_view(relevant_processes = relevant_processes, render_graphs = render_graphs, processes_2_remove = self.tab_processes_2_remove) + def generate_level_graphs(self, render_graphs = True, label_edge=True, label_node=True): + self.iniatilise_tab_processes_2_remove() + self.nextflow_file.generate_level_graphs(render_graphs = render_graphs, processes_2_remove = self.tab_processes_2_remove, label_edge=label_edge, label_node=label_node) + def build_processes_2_tools(self): if(self.processes_2_tools==None):