From 268ed73d71a58ca6cce2e599dc3a48f8bf076136 Mon Sep 17 00:00:00 2001
From: George Marchment <georgemarchment@yahoo.fr>
Date: Tue, 22 Apr 2025 12:19:29 +0200
Subject: [PATCH] Added case there is a cycle in the workflow and the relevant
 processes inderectly don't group together -> i raise the error explaining
 this

---
 src/executor.py      | 2 ++
 src/main.py          | 4 ++++
 src/nextflow_file.py | 3 +++
 src/operation.py     | 2 ++
 src/root.py          | 3 +++
 src/workflow.py      | 8 ++++++++
 6 files changed, 22 insertions(+)

diff --git a/src/executor.py b/src/executor.py
index 0080ea3..6a3611c 100644
--- a/src/executor.py
+++ b/src/executor.py
@@ -27,6 +27,8 @@ class Executor(Nextflow_Building_Blocks):
     #---------------------------------
     #AUXILIARY METHODS FOR ALL CLASSES
     #---------------------------------
+    def get_cycle_status(self):
+        return self.origin.get_cycle_status()
 
     def get_list_name_processes(self):
         return self.origin.get_list_name_processes()
diff --git a/src/main.py b/src/main.py
index 0a72807..5bfec99 100644
--- a/src/main.py
+++ b/src/main.py
@@ -15,6 +15,10 @@ class Main(Nextflow_Building_Blocks):
         self.initialised = False
         self.root = None 
 
+
+    def get_cycle_status(self):
+        return self.nextflow_file.get_cycle_status()
+    
     def get_order_execution_executors(self, dico, seen):
         executors = self.get_all_executors_in_subworkflow()
         pos = {}
diff --git a/src/nextflow_file.py b/src/nextflow_file.py
index 4a16634..14c6fa2 100644
--- a/src/nextflow_file.py
+++ b/src/nextflow_file.py
@@ -37,6 +37,9 @@ class Nextflow_File(Nextflow_Building_Blocks):
     #GENERAL
     #----------------------
 
+    def get_cycle_status(self):
+        return self.workflow.get_cycle_status()
+
     def add_to_ternary_operation_dico(self, old, new):
         self.workflow.add_to_ternary_operation_dico(old, new)
     
diff --git a/src/operation.py b/src/operation.py
index ffb8816..d8933aa 100644
--- a/src/operation.py
+++ b/src/operation.py
@@ -189,6 +189,8 @@ class Operation(Executor):
                         emitted.add_sink(self)
                         self.origins.append(emitted)
                 else:
+                    if(self.get_cycle_status()):
+                        raise BioFlowInsightError(f"A cycle (inderect or direct) exists in the workflow. The rewrite could not be done with the proprosed relavant processes. Either correct the defintion of the workflow or give another set of relevant processes.", type="Cycle exists in workflow")
                     if(name_called[:5]=="Call_"):
                         name_called = self.calls[name_called].get_code()
                     raise BioFlowInsightError(f"The call for '{name_called}' coudn't be found, before its use in the operation '{self.get_code(get_OG=True)}'{self.get_string_line(self.get_code(get_OG=True))}. Either because the call wasn't made before the operation or that the element it is calling doesn't exist.", type =8, origin=self)
diff --git a/src/root.py b/src/root.py
index 004e0d6..2904c4b 100644
--- a/src/root.py
+++ b/src/root.py
@@ -27,6 +27,9 @@ class Root(Nextflow_Building_Blocks):
     def get_type(self):
         return "Root"
     
+    def get_cycle_status(self):
+        return self.origin.get_cycle_status()
+    
     def get_position_in_main(self, executor):
         return self.origin.get_position_in_main(executor)
     
diff --git a/src/workflow.py b/src/workflow.py
index 8bbd39a..8df04af 100644
--- a/src/workflow.py
+++ b/src/workflow.py
@@ -87,6 +87,7 @@ class Workflow:
         self.create_empty_results()
         if(self.display_info):
             print(f"Workflow is written in {self.DSL}")
+        self.cycle_in_workflow = False
         
 
     def create_empty_results(self):
@@ -101,6 +102,9 @@ class Workflow:
         with open(self.output_dir / "debug" / "operations_in_call.nf",'w') as file:
             pass
 
+    def get_cycle_status(self):
+        return self.cycle_in_workflow 
+    
     def get_root_directory(self):
         first_file = self.get_first_file()
         return '/'.join(str(first_file.get_file_address()).split('/')[:-1])+"/"
@@ -600,6 +604,7 @@ George Marchment, Bryan Brancotte, Marie Schmit, Frédéric Lemoine, Sarah Cohen
         return min_relevant_processes
 
     #TODO -> add excpetion Channel exists in multiple forms -> check with 132
+    #Cycle exists in workflow too -> 667
     def get_relevant_following_best_general_score(self, 
                                                   reduction_alpha = 0.2, 
                                                   reduction_beta = 0.8, 
@@ -834,7 +839,9 @@ George Marchment, Bryan Brancotte, Marie Schmit, Frédéric Lemoine, Sarah Cohen
         f.close()
 
         #Replace old analysis with new analysis (simplified code)
+        temp = self.get_cycle_status()
         self.__init__(str(temp_file), display_info = False, duplicate=True, processes_2_remove=processes_2_remove)
+        self.cycle_in_workflow = temp
         self.initialise()
         os.remove(temp_file)
         self.graph.initialise(processes_2_remove = self.processes_2_remove)
@@ -1084,6 +1091,7 @@ George Marchment, Bryan Brancotte, Marie Schmit, Frédéric Lemoine, Sarah Cohen
             #    raise BioFlowInsightError("An indirect cycle was detected in the workflow. This happens often when a same channel is used multiple times in the workflow. This is a norm that we do not recommend. Try rewritting the workflow in a different way. See [link] for more details", type="Cycle detected")
             edges_create_cycles_objects = []
             for e in edges_create_cycles:
+                self.cycle_in_workflow = True
                 edges_create_cycles_objects.append((get_object(e[0]), get_object(e[1])))
             for e in edges_create_cycles_objects:
                 n1 = e[0].get_alias()
-- 
GitLab