From 54f86c738e57485b79da35dc5ef6e9557a0ad748 Mon Sep 17 00:00:00 2001 From: George Marchment <georgemarchment@yahoo.fr> Date: Mon, 10 Mar 2025 14:49:53 +0100 Subject: [PATCH] Adding a few updates --- src/call.py | 85 ++++++++++++++++++++++++---------------------- src/operation.py | 6 ++-- src/subworkflow.py | 4 ++- src/workflow.py | 45 ++++++++++++++---------- 4 files changed, 79 insertions(+), 61 deletions(-) diff --git a/src/call.py b/src/call.py index 9e22063..b50e93b 100644 --- a/src/call.py +++ b/src/call.py @@ -64,49 +64,54 @@ class Call(Executor): def simplify_code(self, new_name = ""): - new_call_name = self.get_first_element_called().get_alias_and_id() - code = self.get_code() - code = re.sub(fr'{re.escape(self.get_first_element_called().get_alias())} *\(', f'{new_call_name}(', code) - if(new_name!=""): - code = f"{new_name} = {code}" - tag_to_add = "//AREA TO ADD PARAMS" - code = f"{tag_to_add}\n{code}" - index = 1 - for param in self.parameters: - param_new_name = f"{self.get_first_element_called().get_alias_and_id()}_param_{index}" - - #Case the param is a call - if(param.get_type()=="Call"): - code = code.replace(param.get_code(get_OG=True), param_new_name) - new_bit = param.simplify_code(new_name = param_new_name) - code = code.replace(tag_to_add, f"{tag_to_add}\n{new_bit}") - - #Case the param is an operation - elif(param.get_type()=="Operation"): - #If it's an artificial operation -> we don't need to do anything - if(not param.get_artificial_status()): + if(self.get_first_element_called().get_type()=="Function"): + return self.get_code() + else: + new_call_name = self.get_first_element_called().get_alias_and_id() + code = self.get_code(clean_pipe = True) + code = re.sub(fr'{re.escape(self.get_first_element_called().get_alias())} *\(', f'{new_call_name}(', code) + if(new_name!=""): + code = f"{new_name} = {code}" + tag_to_add = "//AREA TO ADD PARAMS" + code = f"{tag_to_add}\n{code}" + index = 1 + for param in self.parameters: + param_new_name = f"{self.get_first_element_called().get_alias_and_id()}_param_{index}" + #Case the param is a call + if(param.get_type()=="Call"): + #If it's not a function -> then we rewrite it + if(param.get_first_element_called().get_type()!="Function"): + code = code.replace(param.get_code(get_OG=True), param_new_name) + new_bit = param.simplify_code(new_name = param_new_name) + code = code.replace(tag_to_add, f"{tag_to_add}\n{new_bit}") + + #Case the param is an operation + elif(param.get_type()=="Operation"): + #If it's an artificial operation -> we don't need to do anything + if(not param.get_artificial_status()): + + code = code.replace(param.get_code(get_OG=True), param_new_name) + lines = param.simplify_code().split('\n') + if(len(lines)==1): + new_bit = f"{param_new_name} = {lines[0]}" + else: + head = '\n'.join(lines[:-1]) + new_bit = f"{head}\n{param_new_name} = {lines[-1]}" + code = code.replace(tag_to_add, f"{tag_to_add}\n{new_bit}") + + #Case Channel + elif(param.get_type()=="Channel"): + raise Exception("This shouldn't happen") + None + elif(param.get_type()=="Emitted"): code = code.replace(param.get_code(get_OG=True), param_new_name) - lines = param.simplify_code().split('\n') - if(len(lines)==1): - new_bit = f"{param_new_name} = {lines[0]}" - else: - head = '\n'.join(lines[:-1]) - new_bit = f"{head}\n{param_new_name} = {lines[-1]}" + new_bit = f"{param_new_name} = {param.simplify_code()}" code = code.replace(tag_to_add, f"{tag_to_add}\n{new_bit}") - - #Case Channel - elif(param.get_type()=="Channel"): - raise Exception("This shouldn't happen") - None - elif(param.get_type()=="Emitted"): - code = code.replace(param.get_code(get_OG=True), param_new_name) - new_bit = f"{param_new_name} = {param.simplify_code()}" - code = code.replace(tag_to_add, f"{tag_to_add}\n{new_bit}") - else: - raise Exception("This shouldn't happen") - index+=1 - return code.replace(tag_to_add, "").strip() + else: + raise Exception("This shouldn't happen") + index+=1 + return code.replace(tag_to_add, "").strip() diff --git a/src/operation.py b/src/operation.py index 6e1bf5a..1a88d6e 100644 --- a/src/operation.py +++ b/src/operation.py @@ -902,8 +902,10 @@ class Operation(Executor): to_add = [] for o in self.origins: if(o.get_type()=="Call"): - to_add.append(add_origin_equals(o, index)) - code = code.replace(o.get_code(get_OG=True), f"operation_{operation_id}_{index}") + #If it's not a function -> then we rewrite it + if(o.get_first_element_called().get_type()!="Function"): + to_add.append(add_origin_equals(o, index)) + code = code.replace(o.get_code(get_OG=True), f"operation_{operation_id}_{index}") elif(o.get_type()=="Emitted"): code = code.replace(o.get_code(get_OG=True), o.simplify_code()) index += 1 diff --git a/src/subworkflow.py b/src/subworkflow.py index 774a7d2..0e0d1ad 100644 --- a/src/subworkflow.py +++ b/src/subworkflow.py @@ -169,7 +169,9 @@ class Subworkflow(Main): #Case nothing is there if(take_pos==(0, 0) and main_pos==(0, 0) and emit_pos==(0, 0)): #raise Exception(f"Subworkflow {code} doesn't have anything defined") - self.work = Code(code, origin = self) + firt_curly = code.find("{") + last_curly = code.rfind('}') + self.work = Code(code[firt_curly+1:last_curly], origin = self) #Case there is an input but no output if(take_pos!=(0, 0) and main_pos!=(0, 0) and emit_pos==(0, 0)): if(take_pos[0]<main_pos[0]): diff --git a/src/workflow.py b/src/workflow.py index ace12fe..be488f2 100644 --- a/src/workflow.py +++ b/src/workflow.py @@ -359,7 +359,7 @@ George Marchment, Bryan Brancotte, Marie Schmit, Frédéric Lemoine, Sarah Cohen #Putting || back code = code.replace("$OR$", "||") - self.rewrite_and_initialise(code, self.processes_2_remove) + self.rewrite_and_initialise(code, self.processes_2_remove, render_graphs=False) return code #This methods generates a random set of processes to consider as relavant @@ -515,7 +515,7 @@ George Marchment, Bryan Brancotte, Marie Schmit, Frédéric Lemoine, Sarah Cohen return subs - def rewrite_and_initialise(self, code, processes_2_remove): + def rewrite_and_initialise(self, code, processes_2_remove, render_graphs): temp_process_dependency_graph = self.graph.get_process_dependency_graph() temp_spec_graph = self.graph.full_dico #Write new code in temporary file @@ -532,10 +532,12 @@ George Marchment, Bryan Brancotte, Marie Schmit, Frédéric Lemoine, Sarah Cohen self.initialise() self.graph.initialise(processes_2_remove = self.processes_2_remove) if(not self.graph.check_if_process_dependendy_is_equivalent_to_other_without_subworkflows(temp_process_dependency_graph)): - generate_graph(self.get_output_dir()/ "debug" /"spec_graph_OG", temp_spec_graph, render_graphs = True) - generate_graph(self.get_output_dir()/ "debug" /"spec_graph", self.graph.full_dico, render_graphs = True) - generate_graph(self.get_output_dir()/ "debug" /"process_dependency_graph_OG", temp_process_dependency_graph, render_graphs = True) - generate_graph(self.get_output_dir()/ "debug" /"process_dependency_graph", self.graph.get_process_dependency_graph() , render_graphs = True) + print(render_graphs) + if(render_graphs==True): + generate_graph(self.get_output_dir()/ "debug" /"spec_graph_OG", temp_spec_graph, render_graphs = True) + generate_graph(self.get_output_dir()/ "debug" /"spec_graph", self.graph.full_dico, render_graphs = True) + generate_graph(self.get_output_dir()/ "debug" /"process_dependency_graph_OG", temp_process_dependency_graph, render_graphs = True) + generate_graph(self.get_output_dir()/ "debug" /"process_dependency_graph", self.graph.get_process_dependency_graph() , render_graphs = True) raise Exception("Something went wrong: The flat dependency graph is not the same!") @@ -574,7 +576,7 @@ George Marchment, Bryan Brancotte, Marie Schmit, Frédéric Lemoine, Sarah Cohen code = code.replace(subworklfow.get_code(), "") OG_call = subworklfow.get_call() OG_body = subworklfow.get_work() - + #REPLACE HEADER TAKES subworkflow_takes = subworklfow.get_takes() parameters = OG_call.get_parameters() @@ -614,8 +616,9 @@ George Marchment, Bryan Brancotte, Marie Schmit, Frédéric Lemoine, Sarah Cohen old, new = r temp_code = code #Case of channel = channel - if(new.split("=")[0].strip()==new.split("=")[1].strip()): - new = '' + if(new.find("=")!=-1): + if(new.split("=")[0].strip()==new.split("=")[1].strip()): + new = '' code = code.replace(old, new) if(temp_code==code): raise Exception("Something went wrong: The code hasn't changed") @@ -659,7 +662,7 @@ George Marchment, Bryan Brancotte, Marie Schmit, Frédéric Lemoine, Sarah Cohen #This Function returns the channels the subworkflow (things_added_in_cluster) emits (other things depend on) def get_emits(self, things_added_in_cluster): channel_2_sink = {} - #Basiccaly this is a deco of channels to opeartions -> when the value is an empty list + #Basiccaly this is a deco of channels to opea -> this doesn't really work yetrtions -> when the value is an empty list #This means that the channel is totally definied in the subworkflow -> so we are searching for #Channels which aren't totatly defined in the subworkflow #This means that things outside the subworkflow depend on this channel @@ -689,13 +692,16 @@ George Marchment, Bryan Brancotte, Marie Schmit, Frédéric Lemoine, Sarah Cohen #Method which rewrites the workflow follwong the user view #Conert workflow to user_view only makes sense when the option duplicate is activated -> otherwise is doesn't make sense + it makes the analysis way more complicated - def convert_workflow_2_user_view(self, relevant_processes = []): + def convert_workflow_2_user_view(self, relevant_processes = [], render_graphs = True): + self.iniatilise_tab_processes_2_remove() + self.graph.initialise(processes_2_remove = self.processes_2_remove) + if(self.get_DSL()=="DSL1"): code = self.convert_to_DSL2() if(self.duplicate): code = self.simplify_workflow_code() - self.rewrite_and_initialise(code, self.processes_2_remove) + self.rewrite_and_initialise(code, self.processes_2_remove, render_graphs=render_graphs) @@ -757,7 +763,7 @@ George Marchment, Bryan Brancotte, Marie Schmit, Frédéric Lemoine, Sarah Cohen #Get the clusters and the code relevant_processes = self.check_relevant_processes_in_workflow(relevant_processes) - self.generate_user_view(relevant_processes = relevant_processes, processes_2_remove = []) + self.generate_user_view(relevant_processes = relevant_processes, processes_2_remove = [], render_graphs=render_graphs) clusters = self.graph.get_clusters_from_user_view() broken_subworkflows = get_workflows_broken(get_subworkflow_2_executors(), get_clusters_with_calls(clusters)) #While there still are broken workflows -> need to redo the analysis @@ -765,11 +771,12 @@ George Marchment, Bryan Brancotte, Marie Schmit, Frédéric Lemoine, Sarah Cohen #Rewrite broken subworkflows sub = broken_subworkflows[0] code = self.rewrite_subworkflow_call(code, sub) - self.rewrite_and_initialise(code, self.processes_2_remove) + self.rewrite_and_initialise(code, self.processes_2_remove, render_graphs=render_graphs) #Get the clusters and the code #TODO -> remove the generate all_graphs -> it is not necessary - self.generate_all_graphs() - self.generate_user_view(relevant_processes = relevant_processes, processes_2_remove = []) + if(render_graphs): + self.generate_all_graphs() + self.generate_user_view(relevant_processes = relevant_processes, processes_2_remove = [], render_graphs=render_graphs) clusters = self.graph.get_clusters_from_user_view() broken_subworkflows = get_workflows_broken(get_subworkflow_2_executors(), get_clusters_with_calls(clusters)) @@ -795,7 +802,9 @@ George Marchment, Bryan Brancotte, Marie Schmit, Frédéric Lemoine, Sarah Cohen new_clusters.append(tab) clusters = new_clusters #clusters = self.graph.get_topogical_order(clusters) - + #for e in executors_in_order: + # print(e.get_code()[:20]) + #print(executors_in_order) #Creating the subworkflows from clusters @@ -1085,7 +1094,7 @@ George Marchment, Bryan Brancotte, Marie Schmit, Frédéric Lemoine, Sarah Cohen f = open(self.get_output_dir()/ "debug" / "rewritten.nf", "w") f.write(code) f.close() - self.rewrite_and_initialise(code, self.processes_2_remove) + self.rewrite_and_initialise(code, self.processes_2_remove, render_graphs=render_graphs) return code #return code # -- GitLab