diff --git a/src/block.py b/src/block.py index 4c2d7fd49b6a412ffcc07ae970f6793c8b766a1a..4a4b5c4c5b6bd803d426ab8baa9fb0ba4bc50807 100644 --- a/src/block.py +++ b/src/block.py @@ -3,12 +3,14 @@ from .root import Root from .condition import Condition class Block(Root): - def __init__(self, code, origin, condition, modules_defined): - Root.__init__(self = self, code = code, origin = origin, modules_defined = modules_defined) + def __init__(self, code, origin, condition, modules_defined, existing_channels): + Root.__init__(self = self, code = code, origin = origin, modules_defined = modules_defined, subworkflow_inputs = existing_channels) self.condition = Condition(origin=self, condition = condition) def initialise(self): - return super().initialise() + print(self.condition.condition) + if(self.condition.condition not in ["params.downloadFastq == true", "params.downloadGenome == true"]): + return super().initialise() def get_type(self): return "Root" @@ -18,6 +20,9 @@ class Block(Root): def get_executors(self): return self.executors+self.origin.get_executors() + + def get_structure(self, dico): + return super().get_structure(dico) #def check_in_channels(self, channel): # for c in self.get_channels(): diff --git a/src/call.py b/src/call.py index 9fee23aaeb35af5c7f54463053517cc60455fabb..77f63f932bc9680c0cc0383a3e8781b8a20c85d1 100644 --- a/src/call.py +++ b/src/call.py @@ -80,7 +80,6 @@ class Call(Executor): elif(param.get_type()=="Emitted"): None else: - print(param.get_code(), param.get_type()) raise Exception("This shouldn't happen") index+=1 return code.replace(tag_to_add, "").strip() @@ -224,34 +223,35 @@ class Call(Executor): add_parameter(p) #If they are not -> we check that the right number isn't implied else: - num_inputs = 0 - for p in self.parameters: - if(p.get_type()=="Call"): - num_inputs+= p.get_nb_outputs() - elif(p.get_type()=="Emitted"): - emitted = p - if(emitted.get_emitted_by().get_type()=="Subworkflow"): - if(emitted.get_emits()==None): - num_inputs+= emitted.get_emitted_by().get_nb_emit() - else: - num_inputs+=1 - elif(emitted.get_emitted_by().get_type()=="Process"): - if(emitted.get_emits()==None): - num_inputs+= emitted.get_emitted_by().get_nb_outputs() - else: - num_inputs+=1 - else: - raise Exception("This shoudn't happen") - else: - #Cause in case channel, operation or emit, it is only one channel given - num_inputs+=1 - if(num_inputs==process.get_nb_inputs()): - for p in self.parameters: - add_parameter(p) - - else: - print(num_inputs, process.get_nb_inputs()) - raise BioFlowInsightError(f"Not the same number of parameters given as input for the process '{process.get_alias()}'{self.get_string_line(self.get_code(get_OG=True))}.", num=2, origin=self) + #TODO this needs to be checked + #num_inputs = 0 + #for p in self.parameters: + # if(p.get_type()=="Call"): + # num_inputs+= p.get_nb_outputs() + # elif(p.get_type()=="Emitted"): + # emitted = p + # if(emitted.get_emitted_by().get_type()=="Subworkflow"): + # if(emitted.get_emits()==None): + # num_inputs+= emitted.get_emitted_by().get_nb_emit() + # else: + # num_inputs+=1 + # elif(emitted.get_emitted_by().get_type()=="Process"): + # if(emitted.get_emits()==None): + # num_inputs+= emitted.get_emitted_by().get_nb_outputs() + # else: + # num_inputs+=1 + # else: + # raise Exception("This shoudn't happen") + # else: + # #Cause in case channel, operation or emit, it is only one channel given + # num_inputs+=1 + #if(num_inputs==process.get_nb_inputs()): + # for p in self.parameters: + # add_parameter(p) + # + #else: + # raise BioFlowInsightError(f"Not the same number of parameters given as input for the process '{process.get_alias()}'{self.get_string_line(self.get_code(get_OG=True))}.", num=2, origin=self) + raise BioFlowInsightError(f"Not the same number of parameters given as input for the process '{process.get_alias()}'{self.get_string_line(self.get_code(get_OG=True))}.", num=2, origin=self) elif(self.get_first_element_called().get_type()=="Subworkflow"): sub = self.get_first_element_called() @@ -281,7 +281,7 @@ class Call(Executor): operation = p if(operation.show_in_structure): operation.get_structure(dico) - dico["edges"].append({'A':str(operation), 'B':str(sub_input), "label":""}) + #dico["edges"].append({'A':str(operation), 'B':str(sub_input), "label":""}) #Case parameter is a Call elif(p.get_type()=="Call"): @@ -304,22 +304,24 @@ class Call(Executor): #If the name number of parameters are given if(len(self.parameters)==sub.get_nb_takes()): for p in self.parameters: - param_index = add_parameter(p, param_index ) - #If they are not -> we check that the right number isn't implied + param_index = add_parameter(p, param_index) + ##If they are not -> we check that the right number isn't implied else: - num_inputs = 0 - for p in self.parameters: - if(p.get_type()=="Call"): - num_inputs+= p.get_nb_outputs() - else: - #Cause in case channel, operation or emit, it is only one channel given - num_inputs+=1 - if(num_inputs==sub.get_nb_takes()): - for p in self.parameters: - param_index = add_parameter(p, param_index ) - - else: - raise BioFlowInsightError(f"Not the same number of parameters given as input for the subworklfow '{sub.get_alias()}' in the call{self.get_string_line(self.get_code())}.", num = 2, origin=self) + #TODO check this + raise BioFlowInsightError(f"Not the same number of parameters given as input for the subworklfow '{sub.get_alias()}' in the call{self.get_string_line(self.get_code())}.", num = 2, origin=self) + # num_inputs = 0 + # for p in self.parameters: + # if(p.get_type()=="Call"): + # num_inputs+= p.get_nb_outputs() + # else: + # #Cause in case channel, operation or emit, it is only one channel given + # num_inputs+=1 + # if(num_inputs==sub.get_nb_takes()): + # for p in self.parameters: + # param_index = add_parameter(p, param_index ) + # + # else: + # raise BioFlowInsightError(f"Not the same number of parameters given as input for the subworklfow '{sub.get_alias()}' in the call{self.get_string_line(self.get_code())}.", num = 2, origin=self) elif(self.get_first_element_called().get_type()=="Function"): @@ -328,87 +330,6 @@ class Call(Executor): else: raise Exception(f"This shoudn't happen! is type") - #This function synthaxes the one above -> needs to be rechecked - def get_structure_2(self, dico): - - def add_parameter(p, to_link): - - #Case parameter is a channel - if(p.get_type()=="Channel"): - channel = p - channel.get_structure(dico, B=to_link) - - #Case parameter is a Emitted - elif(p.get_type()=="Emitted"): - emitted = p - emitted.get_structure(dico, B=to_link) - - #Case parameter is a Operation - elif(p.get_type()=="Operation"): - operation = p - operation.get_structure(dico) - dico["edges"].append({'A':str(operation), 'B':str(to_link), "label":""}) - - #Case parameter is a Call - elif(p.get_type()=="Call"): - call = p - call.get_structure(dico) - #Case the first call is a process - if(call.get_first_element_called().get_type()=="Process"): - for output in call.get_first_element_called().get_outputs(): - dico["edges"].append({'A':str(call.get_first_element_called()), 'B':str(to_link), "label":""})#TODO check name of channel - #Case the first call is a subworkflow - elif(call.get_first_element_called().get_type()=="Subworkflow"): - for emit in call.get_first_element_called().get_emit(): - dico["edges"].append({'A':str(emit), 'B':str(to_link), "label":""})#TODO check name of channel - - else: - raise Exception(f"Type '{p.get_type()}' was given as a parameter -> I don't know how to handle this!") - - - first_call = self.get_first_element_called() - param_index = 0 - if(first_call.get_type()=="Process" or first_call.get_type()=="Subworkflow"): - if(first_call.get_type()=="Process"): - first_call.get_structure(dico) - else: - temp_dico = {} - temp_dico['nodes'] = [] - temp_dico['edges'] = [] - temp_dico['subworkflows'] = {} - first_call.get_structure(temp_dico) - dico['subworkflows'][first_call.get_alias()] = temp_dico - - #If the name number of parameters are given - if(len(self.parameters)==first_call.get_nb_inputs()): - for p in self.parameters: - if(first_call.get_type()=="Subworklow"): - sub_input = first_call.get_takes()[param_index] - add_parameter(p, sub_input) - param_index+=1 - else: - add_parameter(p, first_call) - #If they are not -> we check that the right number isn't implied - else: - num_inputs = 0 - for p in self.parameters: - if(p.get_type()=="Call"): - num_inputs+= p.get_nb_outputs() - else: - #Cause in case channel, operation or emit, it is only one channel given - num_inputs+=1 - if(num_inputs==first_call.get_nb_inputs()): - for p in self.parameters: - if(first_call.get_type()=="Subworklow"): - sub_input = first_call.get_takes()[param_index] - add_parameter(p, sub_input) - param_index+=1 - else: - add_parameter(p, first_call) - - else: - raise Exception(f"Not the same number of parameters given as input for the process '{first_call.get_alias()}' in the call ('{self.get_code()}')") - def analyse_call(self, call): @@ -420,7 +341,6 @@ class Call(Executor): if(params[-1]==')'): params = params[:-1] else: - print(self.get_code()) raise Exception("This shouldn't happens") self.analye_parameters(params) diff --git a/src/condition.py b/src/condition.py index a7de014c1f972527e41319863b9b4a8eaddf1b30..f081c0126b02a6ed0e4a5466b27643e3971a70fb 100644 --- a/src/condition.py +++ b/src/condition.py @@ -4,29 +4,6 @@ from .outils import extract_conditions class Condition: def __init__(self, origin, condition): self.origin = origin - self.conditions = condition + self.condition = condition #self.initialise() - #def get_conditions(self): - # return self.conditions - - - #def initialise(self): - # thing_defined = self.origin.get_code(get_OG=True) - # code = self.origin.get_workflow_code() - # #print(f"'{thing_defined}'") - # #print(f"'{code}'") - # - # - # conditions_dico = self.origin.get_file_conditions() - # #conditions_dico_temp = extract_conditions(code) - # #print(conditions_dico==conditions_dico_temp) - # pos = code.find(thing_defined) - # for c in conditions_dico: - # condition_extend = conditions_dico[c] - # if(condition_extend[0]<pos and pos<condition_extend[1]): - # self.conditions.append(c) - # #print(conditions_dico) - # #print(thing_defined, self.conditions) - # #print() - diff --git a/src/emitted.py b/src/emitted.py index 40745c4e634f537fb25f7c9292865e575dfc196d..e5b6f5232cab6c1f462f21bd026cd340f3b79862 100644 --- a/src/emitted.py +++ b/src/emitted.py @@ -9,8 +9,6 @@ class Emitted(Channel): def __init__(self, name, origin, emitted_by): Channel.__init__(self, name=name, origin=origin) - print(self, emitted_by) - self.emitted_by = emitted_by emitted_by.add_to_emits(self) @@ -47,7 +45,6 @@ class Emitted(Channel): self.emits = o if(self.emits==None): - print(self.get_code()) raise Exception(f"No emitted matched with '{name}' (in file '{self.get_file_address()}'). Should match with emittes from '{self.emitted_by.get_name()}' (in file '{self.emitted_by.get_file_address()}'") def set_emits(self, input): @@ -71,30 +68,16 @@ class Emitted(Channel): def get_structure(self, dico, B): emits = self.get_emitted_by() - #if(not emits.is_called(self)): - # end = "in the file" - # if(self.origin.get_type()=="Subworkflow"): - # end = f"in the subworkflow '{self.origin.get_name()}'" - # raise BioFlowInsightError(f"Tried to access the emit '{self.get_code()}' but the {emits.get_type()} '{emits.get_name()}' ({emits}) has not been called {end}.", num = 8, origin=self) - # - - #Case if the emit emits a process - if(emits.get_type()=="Process"): - #emits.get_structure(dico) - if(self.emits==None): - #for i in range(emits.get_nb_outputs()): - # print("here") - # #I don't need to add the process (node) to the structure -> cause it's either there or will be added later on - dico["edges"].append({'A':str(emits), 'B':str(B), "label":self.get_code()}) - else: - dico["edges"].append({'A':str(self.emits), 'B':str(B), "label":self.get_code()}) - #Case if the emit emits a subworkflow - elif(emits.get_type()=="Subworkflow"): - if(self.emits==None): - raise Exception("Just a check") - for ope in emits.get_emit(): - dico["edges"].append({'A':str(ope), 'B':str(B), "label":self.get_code()}) - else: - dico["edges"].append({'A':str(self.emits), 'B':str(B), "label":self.get_name()}) + if(emits.get_type()=="Call"): + first_element_called = emits.get_first_element_called() + if(first_element_called.get_type()=="Process"): + dico["edges"].append({'A':str(first_element_called), 'B':str(B), "label":self.get_code()}) + elif(first_element_called.get_type()=="Subworkflow"): + if(self.emits==None): + raise Exception("Just a check") + else: + dico["edges"].append({'A':str(self.emits), 'B':str(B), "label":self.get_name()}) + else: + raise Exception("This shouldn't happen") diff --git a/src/executor.py b/src/executor.py index adf9b5541aaf52695e0dd93eee108cf067ae62ec..9c6b57cc99e5857f9b0deb6cfd0eb8a9bf5336b2 100644 --- a/src/executor.py +++ b/src/executor.py @@ -148,8 +148,6 @@ class Executor(Nextflow_Building_Blocks): pipe = pipe + '|'+'|'.join(pipe_split[2:]) if not added: if(re.fullmatch(constant.OPERATOR_IN_PIPE, thing)): - print(pipe, self.get_file_address()) - print(f"'{thing}'") raise Exception('problem') raise BioFlowInsightError(f"Don't know how to handle '{thing}' in a pipe operator{self.get_string_line(thing)}. Try using the recommended operator composition.", num=3,origin = self) @@ -216,9 +214,7 @@ class Executor(Nextflow_Building_Blocks): return None else: - print(self.get_code()) return self.origin.get_call_by_name(name) - #print(self.origin.get_calls()) - #print(self.origin) + diff --git a/src/graph.py b/src/graph.py index bce297469f066ec9506ceb9dc0a4e50804d30d0f..c74c3ec4cb6b944ae86bc5983b4a5b26c76ec5c0 100644 --- a/src/graph.py +++ b/src/graph.py @@ -74,8 +74,8 @@ class Graph(): remove_node(self.full_dico, node_id) - self.get_dependency_graph() - self.get_process_dependency_graph() + #self.get_dependency_graph() + #self.get_process_dependency_graph() #self.networkX_wo_operations = self.get_networkx_graph(self.dico_process_dependency_graph, self.networkX_wo_operations) @@ -453,7 +453,6 @@ class Graph(): node_B_temp = tmp exists, _ = exist_path_dico(node_A_temp, node_B_temp, dependency_level) if(not exists): - print("False dependency", edge_user) return True @@ -485,7 +484,7 @@ class Graph(): dico = {} for node in G.nodes(data=True): if(node[1]=={}): - print(node) + None process_nodes = [node for node, data in G.nodes(data=True) if data['type'] == 'Process'] operation_nodes = [node for node, data in G.nodes(data=True) if data['type'] == 'Operation'] diff --git a/src/main.py b/src/main.py index ed6fdf98d9384210902797fd6213c09e35ffc97d..522bde77c2048d390b8bcd83a775a9cfea9e606f 100644 --- a/src/main.py +++ b/src/main.py @@ -56,8 +56,7 @@ class Main(Nextflow_Building_Blocks): def initialise(self): if(not self.initialised): - #print(self, self.get_all_processes()) - + self.initialised=True #Get the modules (Processes defined for the main/subworkflow) @@ -74,7 +73,6 @@ class Main(Nextflow_Building_Blocks): def get_structure(self, dico): - self.root.get_structure(dico) return dico \ No newline at end of file diff --git a/src/operation.py b/src/operation.py index d72bbdc0e946f5ac56db8da0d8775d03bd9b2964..0cbb3a54c0e961ad1ec1f40a9881b99897494b68 100644 --- a/src/operation.py +++ b/src/operation.py @@ -86,9 +86,6 @@ class Operation(Executor): #and Check that the thing extarcted is not WorkflowNameFile like 'WorkflowHgtseq' in nf-core/hgtseq if(name not in constant.ERROR_WORDS_ORIGINS):# and name.lower()!=f"workflow{self.get_name_file().lower()}"): channel = Channel(name=name, origin=self.origin) - #TODO -> problem might be here - - #TODO -> this needs to be checked if(self.origin.get_type()!="Subworkflow"): if(not self.origin.check_in_channels(channel)): self.origin.add_channel(channel) @@ -120,10 +117,8 @@ class Operation(Executor): if( splited[-1] in constant.LIST_OPERATORS): full_code = '.'.join(splited[:-1]) if(name_called not in IGNORE_NAMES): - #print(self.origin.origin.get_name(), self.origin.origin.get_processes()) call = self.get_call_by_name(name_called) #process = self.get_process_from_name(name_called) - ##print(process) #subworkflow = self.get_subworkflow_from_name(name_called) # #if(process!=None and subworkflow!=None): @@ -228,12 +223,10 @@ class Operation(Executor): #subworkflow = self.origin.get_subworkflow_from_name(name) #process = self.origin.get_process_from_name(name) #if(subworkflow!=None): - # print("George it's a subworkflow") # #Case suborkflow # self.origins.append(subworkflow) ##Case process #elif(process!=None): - # print("George it's a process") # #Case process # self.origins.append(process) ##In this case it's a channel @@ -533,7 +526,6 @@ class Operation(Executor): # if(bool(re.fullmatch(r'\w+', name))): # self.add_origin(name) - #print(self.origin) #self.origins = list(set(origin)) @@ -561,7 +553,6 @@ class Operation(Executor): raise Exception("Something unexpected") #else: - # print(self.get_code()) # raise Exception("Something unexpected!") @@ -589,7 +580,6 @@ class Operation(Executor): raise Exception(f"I don't know what i'm looking at '{c}' in '{self.get_code()}'") - #print(operator, s, start, end) @@ -610,15 +600,7 @@ class Operation(Executor): tab.append(g) return tab - def print_operation(self): - print(self.get_code()) - #TODO -> put this somewhere - def check_loop(self): - for g in self.gives: - for o in self.origins: - if(g==o): - print(f"Loop here:\n- {self.get_code()}\n- For the {o.get_name()} channel") #This method checks if an operation is just a full emited #This is in the case of a parameter in a call @@ -634,17 +616,7 @@ class Operation(Executor): return False - #def print_summary(self, tab = 0, print_code=False): - # print(" "*tab+f"{self}") - # if(print_code): - # print(" "*(tab+1)+"* Code :", self.get_code()) - # print(" "*(tab+1)+"* Origins") - # for o in self.get_origins(): - # print(" "*(tab+1+2)+o.get_code(), f"'{o.get_type()}'") - # print(" "*(tab+1)+"* Gives") - # for g in self.get_gives(): - # print(" "*(tab+1+2)+g.get_code(), f"'{g.get_type()}'") - + def write_summary(self, address, tab = 0): file = open(address, "a") file.write(" "*tab+f"{self}\n") @@ -696,7 +668,6 @@ class Operation(Executor): p = p.strip() if(p!=""): name = p - #print(name) if(bool(re.fullmatch(constant.WORD, name))): self.add_origin(name) elif(self.check_is_emit(name)): @@ -739,7 +710,6 @@ class Operation(Executor): # text = text.replace(self.calls[c].get_code(), "") # for match in re.finditer(pattern_call_pipe, text): # if(match.group(1) in to_call): - # print(match.group(1), text) # start, end = match.span(0) # from .outils import checks_in_condition_if, checks_in_string, extract_inside_parentheses # if(not checks_in_condition_if(text, match.group(1)) and not checks_in_string(text, match.group(1))): @@ -790,7 +760,6 @@ class Operation(Executor): def initialise_from_call(self): if(self.get_code()!="" and self.get_code()[0]=="[" and self.get_code()[-1]=="]"): - #print("in list", self.get_code()) None #TODO #basically in this code -> i want to do the same thing for analye_parameters for a call @@ -815,89 +784,78 @@ class Operation(Executor): self.write_summary(self.get_output_dir() / "debug/operations_in_call.nf") def get_structure(self, dico, to_remove = False): - if(self.show_in_structure): - code = self.get_code(replace_calls=False) - #Need to replace /* and */ by /\* and *\/ so graphivz doesn't think it's a comment - #Same for // -> replace it by /\/\ - code = code.replace("/*", "/\*").replace("*/", "*\/").replace("//", "/\/\\") - code = code.replace('"', "'") - if(self.get_operation_type()=="Branch"): - fillcolor = "white" - else: - fillcolor = "" + code = self.get_code(replace_calls=False) + #Need to replace /* and */ by /\* and *\/ so graphivz doesn't think it's a comment + #Same for // -> replace it by /\/\ + code = code.replace("/*", "/\*").replace("*/", "*\/").replace("//", "/\/\\") + code = code.replace('"', "'") + if(self.get_operation_type()=="Branch"): + fillcolor = "white" + else: + fillcolor = "" - #TODO check this -> IMPORTANT - if(not to_remove): - dico['nodes'].append({'id':str(self), 'name':"", "shape":"point", 'xlabel': code, 'fillcolor':fillcolor}) - else: - #The ones which have the 'to_remove' name is because they are used in as takes and emits in subworkflow (they will be removed in post) - dico['nodes'].append({'id':str(self), 'name':"to_remove", "shape":"point", 'xlabel': code, 'fillcolor':fillcolor}) + dico['nodes'].append({'id':str(self), 'name':"", "shape":"point", 'xlabel': code, 'fillcolor':fillcolor}) - for o in self.origins: - #Case origins is a channel - if(o.get_type()=="Channel"): - channel = o - channel.get_structure(dico, B=self) - - #Case origins is a call - elif(o.get_type()=="Call"): - call = o - call.get_structure(dico) - #Case the first call is a process - if(call.get_first_element_called().get_type()=="Process"): - dico["edges"].append({'A':str(call.get_first_element_called()), 'B':str(self), "label":""})#TODO check name of channel - #Case the first call is a subworkflow - elif(call.get_first_element_called().get_type()=="Subworkflow"): - sub = call.get_first_element_called() - if(sub.get_nb_emit()==0): - raise BioFlowInsightError(f"The subworkflow '{sub.get_name()}' doesn't emit anything. It is given to an operation{self.get_string_line(call.get_code())}.", num=20, origin=self) - elif(sub.get_nb_emit()>1): - #In the case test().a.view() and test is a subworkflow - added = False - element_after_call = self.get_element_after_call(o) - emits = sub.get_emit() - for e in emits: - if(e.get_gives()==[]): - for o in e.get_origins(): - if(o.get_code()==element_after_call): - dico["edges"].append({'A':str(e), 'B':str(self), "label":e.get_code()}) - added =True - else: - for g in e.get_gives(): - if(g.get_code()==element_after_call): - dico["edges"].append({'A':str(e), 'B':str(self), "label":e.get_code()}) - added =True - - if(not added): - raise BioFlowInsightError(f"To much to unpack : The subworkflow '{sub.get_name()}' emits over one channel in a operation{self.get_string_line(call.get_code())}.", num=20, origin=self) - #TODO recommendation -> try using an emit subworkflow.out - else: - emit = sub.get_emit()[0] - dico["edges"].append({'A':str(emit), 'B':str(self), "label":emit.get_code()}) - #for out in sub.get_emit(): - # print(out, out.get_code()) - # #These are channels - # #TODO check this -> it was the one line 644 before - # #out.get_structure(dico, B=self) - # out.get_structure(dico) - - elif(call.get_first_element_called().get_type()=="Function"): - #TODO check if this is actually the cas - None + for o in self.origins: + #Case origins is a channel + if(o.get_type()=="Channel"): + channel = o + channel.get_structure(dico, B=self) + + #Case origins is a call + elif(o.get_type()=="Call"): + call = o + call.get_structure(dico) + #Case the first call is a process + if(call.get_first_element_called().get_type()=="Process"): + dico["edges"].append({'A':str(call.get_first_element_called()), 'B':str(self), "label":""})#TODO check name of channel + #Case the first call is a subworkflow + elif(call.get_first_element_called().get_type()=="Subworkflow"): + sub = call.get_first_element_called() + if(sub.get_nb_emit()==0): + raise BioFlowInsightError(f"The subworkflow '{sub.get_name()}' doesn't emit anything. It is given to an operation{self.get_string_line(call.get_code())}.", num=20, origin=self) + elif(sub.get_nb_emit()>1): + #In the case test().a.view() and test is a subworkflow + added = False + element_after_call = self.get_element_after_call(o) + emits = sub.get_emit() + for e in emits: + if(e.get_gives()==[]): + for o in e.get_origins(): + if(o.get_code()==element_after_call): + dico["edges"].append({'A':str(e), 'B':str(self), "label":e.get_code()}) + added =True + else: + for g in e.get_gives(): + if(g.get_code()==element_after_call): + dico["edges"].append({'A':str(e), 'B':str(self), "label":e.get_code()}) + added =True + + if(not added): + raise BioFlowInsightError(f"To much to unpack : The subworkflow '{sub.get_name()}' emits over one channel in a operation{self.get_string_line(call.get_code())}.", num=20, origin=self) + #TODO recommendation -> try using an emit subworkflow.out else: - raise Exception("This souldn't happen!") - - - #Case origins is a Emmited - elif(o.get_type()=="Emitted"): - emitted = o - emitted.get_structure(dico, B=self) - + emit = sub.get_emit()[0] + dico["edges"].append({'A':str(emit), 'B':str(self), "label":emit.get_code()}) + #for out in sub.get_emit(): + # #These are channels + # #TODO check this -> it was the one line 644 before + # #out.get_structure(dico, B=self) + # out.get_structure(dico) + elif(call.get_first_element_called().get_type()=="Function"): + #TODO check if this is actually the cas + None else: - print(self.get_code()) - print(self.get_file_address()) - raise Exception(f"This souldn't happen! The origin of an operation is of type '{o.get_type()}'. It's code is '{o.get_code()}'") + raise Exception("This souldn't happen!") + + + #Case origins is a Emmited + elif(o.get_type()=="Emitted"): + emitted = o + emitted.get_structure(dico, B=self) + else: + raise Exception(f"This souldn't happen! The origin of an operation is of type '{o.get_type()}'. It's code is '{o.get_code()}'") def convert_to_DSL2(self): code = self.get_code(get_OG=True) diff --git a/src/outils.py b/src/outils.py index 61906be272f0af809b6ff52afde9fb0e6a79b27a..84da8804f8eb0ece59bb8ab29f83048940ff76fc 100644 --- a/src/outils.py +++ b/src/outils.py @@ -369,7 +369,6 @@ def extract_curly(text, start): while(parenthese_count!=0 or curly_count!=0 or quote_single or quote_double or triple_single or triple_double): - #print(parenthese_count, curly_count, quote_single, quote_double, triple_single, triple_double) checked_triple = False @@ -489,7 +488,7 @@ def remove_comments(input_text): #input_text = re.sub(r'\/([^($\/)]+)\$\/', r'"\g<1>"', input_text) #if(temp!=input_text): - # print("-",start) + to_remove = [] quote_single, quote_double = False, False @@ -1029,7 +1028,7 @@ def extract_conditions(code): start_inside, end_inside = match.span(0)[1]+end, end_else-1 conditions_dico[' && '.join(["!({})".format(v) for v in conditions])] = (start_inside, end_inside) #conditions_dico = adding_inside(conditions_dico, code, start_inside, end_inside) - #print(code[start_else:end_else]) + break end = end_else if(found_if_bloc): @@ -1233,8 +1232,6 @@ def replace_thing_by_call(tab): call = ele.get_call() #This verification is really important if(len(call)!=1): - for c in call: - print(c.get_code(get_OG=True)) raise Exception("This shoudn't happen since duplicate mode is activated") call = call[0] to_add.append(call) @@ -1265,10 +1262,9 @@ def group_together_ifs(code): big_start, end_1 = match.span(0) end = extract_curly(code, end_1) inside_1 = code[end_1:end-1].strip() - #print(re.escape(code[big_start:end])+r'\s*'+pattern) + for motch in re.finditer(re.escape(code[big_start:end])+r'\s*'+pattern, code): condition_2 = motch.group(1) - #print('-', motch.group(1)) _, end_2 = motch.span(0) end = extract_curly(code, end_2) big_end = end diff --git a/src/outils_graph.py b/src/outils_graph.py index 48401ac717f2f7c3189d888c64fbbdf5ad6f0f9b..01eb94fcd343d57a7a977615a235b65084ec3f5e 100644 --- a/src/outils_graph.py +++ b/src/outils_graph.py @@ -765,15 +765,14 @@ def relev_user_view_builder(dico_param, relevant_modules): return True, i return False, -1 - #print('n', get_name_from_id(dico, n), '-> rPred', get_names_tab(dico, rPred(n, dico, R, ['input']))) - #print('n', get_name_from_id(dico, n), '-> rSucc', get_names_tab(dico, rSucc(n, dico, R, ['output']))) + check, index = condition_line_13(NRC, n, dico, R, ["input"], ['output']) if(check): NRC[index].append(n) else: M = [n] NRC.append(M) - #print(get_names_tab(dico, NRC)) + #Step 3 changes_in_NRC = True @@ -918,7 +917,6 @@ def get_graph_level_l(dico, level): node_2_subworkflows = {} fill_node_2_subworkflows(dico, node_2_subworkflows) - #print(node_2_subworkflows) def add_nodes(dico, level, current_level): diff --git a/src/process.py b/src/process.py index 0baa5363d6d68d9cfc7ed7bf1d1e98e79f302bb5..affecbe0c3bd6e48c8a3ffccae61827fe2883323 100644 --- a/src/process.py +++ b/src/process.py @@ -245,7 +245,7 @@ class Process(Nextflow_Building_Blocks): for match in re.finditer(pattern, line+"\n"): extracted = match.group(1).strip() self.raw_input_names.append(extracted) - #print(extracted) + if(bool(re.fullmatch(constant.WORD, extracted))): add_channel(extracted) else: diff --git a/src/root.py b/src/root.py index 3006ead384f22cda73ca4e308e278e7d420c30d1..cddaca9d8e039325fdb8031154ecd99df82520d0 100644 --- a/src/root.py +++ b/src/root.py @@ -69,7 +69,7 @@ class Root(Nextflow_Building_Blocks): for c in conditions: from .block import Block body = code[conditions[c][0]:conditions[c][1]] - block = Block(code=body, origin=self, condition=c, modules_defined=self.modules_defined) + block = Block(code=body, origin=self, condition=c, modules_defined=self.modules_defined, existing_channels = self.channels) block.initialise() self.blocks.append(block) @@ -330,8 +330,7 @@ class Root(Nextflow_Building_Blocks): # tab_to_call = txt_call.split('|') # start = f"{tab_to_call[0]}({params})" # txt_call = start + '|' + '|'.join(tab_to_call[1:]) - # print(start) - #print(params, full_executor) + #If the thing which is extracted is not in the conditon of an if if(not checks_in_condition_if(text, full_executor) and not checks_in_string(text, full_executor)): @@ -378,10 +377,8 @@ class Root(Nextflow_Building_Blocks): self.executors.remove(e) def get_structure(self, dico): - for block in self.blocks: block.get_structure(dico) - for e in self.executors: if(e.get_type()=="Operation"): e.get_structure(dico) diff --git a/src/subworkflow.py b/src/subworkflow.py index 655c65ba1578adc0f9140fa76ee43d1e99ab0562..3402a3c062e727d3e500388452fb0a7dbbfdc285 100644 --- a/src/subworkflow.py +++ b/src/subworkflow.py @@ -64,9 +64,6 @@ class Subworkflow(Main): return re.sub(r"workflow\s*(\w+)\s*\{", replacer, code) - def print_summary(self, tab = 0): - print(" "*tab+f"* {self.name} ({self})") - super().print_summary(tab) def set_alias(self, alias): self.alias = alias @@ -187,6 +184,7 @@ class Subworkflow(Main): + def initialise_emit(self): from .operation import Operation if(self.emit!=[]): @@ -215,7 +213,6 @@ class Subworkflow(Main): # #TODO -> check not add origin too! # gives.add_sink(operation) #tab.append(operation) - #print(operation) ##self.add_operation(operation) ##self.executors.append(operation) self.emit = tab @@ -258,10 +255,10 @@ class Subworkflow(Main): for ope in self.get_takes(): #ope.set_operation_type("Branch") - ope.get_structure(dico, to_remove = True) - + ope.get_structure(dico) + for ope in self.get_emit(): #ope.set_operation_type("Branch") - ope.get_structure(dico, to_remove = True) + ope.get_structure(dico) \ No newline at end of file diff --git a/src/workflow.py b/src/workflow.py index cc4ef304fd33c58f500c18c6a2f6816367cb3449..5e4248f95f292962184cb7d47c947d7daac8da77 100644 --- a/src/workflow.py +++ b/src/workflow.py @@ -124,9 +124,8 @@ class Workflow: if(self.display_info): - citation = """To cite BioFlow-Insight, please use the following publication: + citation = """\nTo cite BioFlow-Insight, please use the following publication: George Marchment, Bryan Brancotte, Marie Schmit, Frédéric Lemoine, Sarah Cohen-Boulakia, BioFlow-Insight: facilitating reuse of Nextflow workflows with structure reconstruction and visualization, NAR Genomics and Bioinformatics, Volume 6, Issue 3, September 2024, lqae092, https://doi.org/10.1093/nargab/lqae092""" - print() print(citation) if(self.graph==None):