diff --git a/src/channel.py b/src/channel.py index 1e9cdfb01205034ce17fbd2f0b93ceadcf062117..c51a20547b3202c6183d97ac8a05a4aff6bb17ee 100644 --- a/src/channel.py +++ b/src/channel.py @@ -23,7 +23,7 @@ class Channel(Nextflow_Building_Blocks): self.sink = [] - def get_code(self): + def get_code(self, get_OG = True): """Method that returns the channels code Keyword arguments: diff --git a/src/workflow.py b/src/workflow.py index 9dcb91366f6d6037bee4669e0d12cec226a72608..2b6e5387922b8afe21ec2d15a4757d1234e8b6d1 100644 --- a/src/workflow.py +++ b/src/workflow.py @@ -810,6 +810,46 @@ George Marchment, Bryan Brancotte, Marie Schmit, Frédéric Lemoine, Sarah Cohen raise Exception("This shouldn't happen") return code + #I do not recommand that the dev uses the same name for the channels inside and outside the channels + #Since the local channels become local at the upper level + def rewrite_subworkflow_call(seld, code, subworklfow): + print(subworklfow.get_name()) + #Remove the defintion from the code + code = code.replace(subworklfow.get_code(), "") + OG_call = subworklfow.get_call() + if(len(OG_call)>1): + raise Exception("This shouldn't happen") + OG_call = OG_call[0] + OG_body = subworklfow.get_work() + + #REPLACE HEADER TAKES + subworkflow_takes = subworklfow.get_takes() + parameters = OG_call.get_parameters() + if(len(subworkflow_takes)!=len(parameters)): + raise Exception("This shouldn't happen -> the same number of parameters should be kept") + #This is to replace the paramters and the takes + new_header = "" + for i in range(len(parameters)): + param = parameters[i] + takes = subworkflow_takes[i].get_gives()[0] + if(takes.get_code()!=param.get_code(get_OG = True)): + new_header+=f"{takes.get_code()} = {param.get_code(get_OG = True)}" + + code = code.replace(OG_call.get_code(get_OG = True), f"{new_header}\n\n{OG_body}") + + #REPLACE THE EMITS + emits = subworklfow.get_emit() + for o in emits: + origin = o.get_origins()[0] + gives = o.get_gives() + #TODO finish this -> i think that the gives is empty + print(o.get_type()) + print(o.get_code(), origin.get_code(), gives) + + + #print(code) + return code + #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 @@ -832,7 +872,7 @@ George Marchment, Bryan Brancotte, Marie Schmit, Frédéric Lemoine, Sarah Cohen self.nextflow_file.generate_user_view(relevant_processes = relevant_processes, processes_2_remove = []) clusters = self.nextflow_file.graph.get_clusters_from_user_view() - """#DETERMING WHICH SUBWORKFLOWS ARE BROKEN WITH THE CLUSTER + #DETERMING WHICH SUBWORKFLOWS ARE BROKEN WITH THE CLUSTER #Creating the clusters with calls instead of processes or subworkflows set_clusters_with_calls = [] for c in clusters: @@ -847,30 +887,68 @@ George Marchment, Bryan Brancotte, Marie Schmit, Frédéric Lemoine, Sarah Cohen raise Exception("This shouldn't happen") tab.append(call[0]) set_clusters_with_calls.append(set(tab)) - print(set_clusters_with_calls) + #Getting subworkflows to executors subworkflow_2_executors = {} for sub in self.get_subworkflows_called(): dico = {} sub.get_all_executors(dico) - subworkflow_2_executors[sub.get_name()] = set(list(dico.keys())) - print(subworkflow_2_executors) - - def check_subworkflow_intact(original_sets, new_sets): - results = {} - for sub in original_sets: - original = original_sets[sub] - #temp = [] - #for new in new_sets: - # print(original, new, new.issubset(original)) - # #temp.append(original.issubset(new)) - #print(temp) - intact = all(new.issubset(original) for new in new_sets) - results[sub] = intact - return results - - print(check_subworkflow_intact(subworkflow_2_executors, set_clusters_with_calls)) - 1/0""" + temp = set(list(dico.keys())) + subworkflow_2_executors[sub] = [] + for ele in temp: + #Cannot add calls to subworkflows -> they are already present by definition + if(ele.get_type()=="Call" and ele.get_first_element_called().get_type()=="Subworkflow"): + None + #We don't add it + else: + subworkflow_2_executors[sub].append(ele) + #subworkflow_2_executors[sub.get_name()] = set(list(dico.keys())) + + def get_workflows_broken(subworkflow_2_executors, set_clusters_with_calls): + broken_subworkflows = [] + for sub in subworkflow_2_executors: + #You want this list (set) to be equal to subworkflow_2_executors[sub] + elements_in_sub_with_clusters = [] + for cluster in set_clusters_with_calls: + if(len(elements_in_sub_with_clusters)>len(subworkflow_2_executors[sub])): + break + for c in cluster: + if(len(elements_in_sub_with_clusters)>len(subworkflow_2_executors[sub])): + break + if(c in subworkflow_2_executors[sub]): + elements_in_sub_with_clusters+=list(cluster) + break + if(set(elements_in_sub_with_clusters)==set(subworkflow_2_executors[sub])): + None + #This means that the subworkflow is Intact + else: + #This means that the subworkflow is broken + broken_subworkflows.append(sub) + return broken_subworkflows + + broken_subworkflows = get_workflows_broken(subworkflow_2_executors, set_clusters_with_calls) + + #Rewrite broken subworkflows + for sub in broken_subworkflows: + code = self.rewrite_subworkflow_call(code, sub) + + 1/0 + + #def check_subworkflow_intact(original_sets, new_sets): + # results = {} + # for sub in original_sets: + # original = original_sets[sub] + # #temp = [] + # #for new in new_sets: + # # print(original, new, new.issubset(original)) + # # #temp.append(original.issubset(new)) + # #print(temp) + # intact = all(new.issubset(original) for new in new_sets) + # results[sub] = intact + # return results + + #print(check_subworkflow_intact(subworkflow_2_executors, set_clusters_with_calls)) + 1/0 #cluster_2_subworkflows = [] #print(clusters)