diff --git a/src/graph.py b/src/graph.py index ebbabe68cda82852735b517e266ddaa913323971..b9157e7844f30462f34b73e9e0053e32c8bd0cb2 100644 --- a/src/graph.py +++ b/src/graph.py @@ -15,12 +15,13 @@ class Graph(): #This dico give for the nodes its sister nodes self.link_dico = None #Dico to graph without operations - self.dico_wo_operation = {} + self.dico_process_dependency_graph = {} self.dico_wo_branch_operation = {} #Dictionaries for metadata #Dico flattened (without any subworkflows) self.dico_flattened = {} + self.initialised = False @@ -69,11 +70,15 @@ class Graph(): self.get_process_dependency_graph() - #self.networkX_wo_operations = self.get_networkx_graph(self.dico_wo_operation, self.networkX_wo_operations) + #self.networkX_wo_operations = self.get_networkx_graph(self.dico_process_dependency_graph, self.networkX_wo_operations) self.dico_flattened["nodes"] = [] self.dico_flattened["edges"] = [] #This will stay empty -> it's just so we can use the same function self.dico_flattened["subworkflows"] = [] + self.initialised = True + + def is_initialised(self): + return self.initialised def get_output_dir(self): return self.workflow.get_output_dir() @@ -130,11 +135,14 @@ class Graph(): def get_specification_graph_wo_orphan_operations_wo_labels(self, filename = "specification_wo_orphan_operations_wo_labels", render_graphs = True): generate_graph(self.get_output_dir()/'graphs'/filename, graph_dico_wo_orphan_operations(self.full_dico), label_edge=False, label_node=False, render_graphs = render_graphs) + def get_process_dependency_graph_dico(self): + return self.dico_process_dependency_graph + def get_process_dependency_graph(self): self.intia_link_dico() #Function that replicates the workflow's structure wo the operations in the nodes - def replicate_dico_wo_operations(dico_struct): + def replicate_dico_process_dependency_graphs(dico_struct): dico = {} dico['nodes'] = [] dico['edges'] = [] @@ -143,10 +151,10 @@ class Graph(): if(is_process(node['id'])): dico['nodes'].append(node) for sub in dico_struct['subworkflows']: - dico['subworkflows'][sub] = replicate_dico_wo_operations(dico_struct['subworkflows'][sub]) + dico['subworkflows'][sub] = replicate_dico_process_dependency_graphs(dico_struct['subworkflows'][sub]) return dico - dico = replicate_dico_wo_operations(self.full_dico) + dico = replicate_dico_process_dependency_graphs(self.full_dico) #This is a dictionnary which links every node to it's connected process node_2_processes = copy.deepcopy(self.link_dico) @@ -190,14 +198,14 @@ class Graph(): add_edges(dico) - self.dico_wo_operation = dico + self.dico_process_dependency_graph = dico with open(f"{self.get_output_dir()}/graphs/process_dependency_graph.json", 'w') as output_file : - json.dump(self.dico_wo_operation, output_file, indent=4) + json.dump(self.dico_process_dependency_graph, output_file, indent=4) def render_graph_wo_operations(self, filename = "process_dependency_graph", render_graphs = True): - generate_graph(self.get_output_dir()/'graphs'/filename, self.dico_wo_operation, render_graphs = render_graphs, label_edge=False, label_node=False) + generate_graph(self.get_output_dir()/'graphs'/filename, self.dico_process_dependency_graph, render_graphs = render_graphs, label_edge=False, label_node=False) def get_dependency_graph(self): @@ -283,12 +291,14 @@ class Graph(): #============================ def initialise_flattened_dico(self, dico): - for node in dico["nodes"]: - self.dico_flattened["nodes"].append(node) - for edge in dico["edges"]: - self.dico_flattened["edges"].append(edge) - for subworkflow in dico["subworkflows"]: - self.initialise_flattened_dico(dico["subworkflows"][subworkflow]) + + flatten_dico(dico, self.dico_flattened) + #for node in dico["nodes"]: + # self.dico_flattened["nodes"].append(node) + #for edge in dico["edges"]: + # self.dico_flattened["edges"].append(edge) + #for subworkflow in dico["subworkflows"]: + # self.initialise_flattened_dico(dico["subworkflows"][subworkflow]) def get_metadata(self, graph): G = self.get_networkx_graph(graph, None) @@ -439,7 +449,7 @@ class Graph(): def get_metadata_process_dependency_graph(self): - dico = self.get_metadata(self.dico_wo_operation) + dico = self.get_metadata(self.dico_process_dependency_graph) with open(self.get_output_dir()/ "graphs/metadata_process_dependency_graph.json", 'w') as output_file : json.dump(dico, output_file, indent=4) diff --git a/src/nextflow_file.py b/src/nextflow_file.py index 1309305cc29772111dc606b6074ef7b0bb934b0a..a4a8cc4a8657c23b2f7d9d5ef1d3796c91933d22 100644 --- a/src/nextflow_file.py +++ b/src/nextflow_file.py @@ -692,6 +692,8 @@ class Nextflow_File(Nextflow_Building_Blocks): self.graph.get_metadata_dependency_graph() self.graph.get_metadata_process_dependency_graph() + def get_graph(self): + return self.graph #def get_metadata_graph_wo_operations(self): # self.graph.get_metadata_graph_wo_operations() diff --git a/src/outils_graph.py b/src/outils_graph.py index 95a931351ab64c0a6bf20652f43833c14dc2e46d..4f18d9abc6c840bbab06476172bdb989e8614f15 100644 --- a/src/outils_graph.py +++ b/src/outils_graph.py @@ -333,4 +333,14 @@ def get_longest_distance(graph): # longest_path = longest_path["nb"] # smallest_path = shortest_path["nb"] # -# return number_paths_source_2_sink, longest_path, smallest_path \ No newline at end of file +# return number_paths_source_2_sink, longest_path, smallest_path + + +def flatten_dico(dico, dico_flattened): + for node in dico["nodes"]: + dico_flattened["nodes"].append(node) + for edge in dico["edges"]: + dico_flattened["edges"].append(edge) + for subworkflow in dico["subworkflows"]: + flatten_dico(dico["subworkflows"][subworkflow], dico_flattened) + return dico_flattened \ No newline at end of file diff --git a/src/workflow.py b/src/workflow.py index 57c8686e87a63c04a42804777e833f7dcfd54972..da73fd34f4734120d5fae47a075a7fada7844bc3 100644 --- a/src/workflow.py +++ b/src/workflow.py @@ -2,6 +2,7 @@ from .nextflow_file import Nextflow_File from .ro_crate import RO_Crate from . import constant +from .outils_graph import flatten_dico import os import re @@ -261,7 +262,63 @@ class Workflow: self.rocrate = RO_Crate(self) self.rocrate.initialise() + def get_layers(self): + graph = self.nextflow_file.get_graph() + if(not graph.is_initialised()): + graph.initialise() + process_dependency_graph = graph.get_process_dependency_graph_dico() + dico_flattened = {"nodes": [], "edges": []} + + def get_node(dico, id): + for n in dico['nodes']: + if(n['id']==id): + return n + return None + def remove_node(dico, id): + node = None + for n in dico['nodes']: + if(n['id']==id): + node = n.copy() + break + try: + dico['nodes'].remove(node) + except: + print("prob1") + + def remove_edge_if_A(dico, id_A): + edges = [] + for edge in dico['edges']: + if(edge['A']==id_A): + edges.append(edge) + for edge in edges: + try: + dico['edges'].remove(edge) + except: + print("prob2") + + flatten_dico(process_dependency_graph, dico_flattened) + layers = [] + while(dico_flattened["nodes"]!=[]): + + layer = dico_flattened["nodes"].copy() + + for edge in dico_flattened["edges"]: + try: + layer.remove(get_node(dico_flattened, edge['B'])) + except: + None + + + for node in layer: + dico_flattened['nodes'].remove(node) + remove_edge_if_A(dico_flattened, node['id']) + layers.append(layer) + + + return layers + + print(flatten_dico(process_dependency_graph, dico_flattened)) def initialise(self, create_rocrate = True): self.nextflow_file.initialise()