From c0ddcc203ca278f18d8b797ad3979a852e8337e1 Mon Sep 17 00:00:00 2001
From: LouisonF <fresnaislouison@gmail.com>
Date: Wed, 12 Oct 2022 19:04:49 +0200
Subject: [PATCH 1/8] add getReactionSudeCompounds public method

---
 .../connect/weighting/RPAIRSlikePolicy.java   | 42 +++++++++++++++++--
 1 file changed, 39 insertions(+), 3 deletions(-)

diff --git a/met4j-graph/src/main/java/fr/inrae/toulouse/metexplore/met4j_graph/computation/connect/weighting/RPAIRSlikePolicy.java b/met4j-graph/src/main/java/fr/inrae/toulouse/metexplore/met4j_graph/computation/connect/weighting/RPAIRSlikePolicy.java
index 269cbcf03..1049bd9dd 100644
--- a/met4j-graph/src/main/java/fr/inrae/toulouse/metexplore/met4j_graph/computation/connect/weighting/RPAIRSlikePolicy.java
+++ b/met4j-graph/src/main/java/fr/inrae/toulouse/metexplore/met4j_graph/computation/connect/weighting/RPAIRSlikePolicy.java
@@ -3,11 +3,10 @@ package fr.inrae.toulouse.metexplore.met4j_graph.computation.connect.weighting;
 import fr.inrae.toulouse.metexplore.met4j_core.biodata.BioEntity;
 import fr.inrae.toulouse.metexplore.met4j_core.biodata.BioMetabolite;
 import fr.inrae.toulouse.metexplore.met4j_core.biodata.BioReaction;
+import fr.inrae.toulouse.metexplore.met4j_core.biodata.collection.BioCollection;
 import fr.inrae.toulouse.metexplore.met4j_graph.computation.analyze.GraphMeasure;
 import fr.inrae.toulouse.metexplore.met4j_graph.computation.transform.GraphFilter;
-import fr.inrae.toulouse.metexplore.met4j_graph.core.BioGraph;
 import fr.inrae.toulouse.metexplore.met4j_graph.core.Edge;
-import fr.inrae.toulouse.metexplore.met4j_graph.core.GraphFactory;
 import fr.inrae.toulouse.metexplore.met4j_graph.core.WeightingPolicy;
 import fr.inrae.toulouse.metexplore.met4j_graph.core.compound.CompoundGraph;
 import fr.inrae.toulouse.metexplore.met4j_graph.core.compound.ReactionEdge;
@@ -34,6 +33,44 @@ public class RPAIRSlikePolicy extends WeightingPolicy<BioMetabolite, ReactionEdg
         preprocess.removeNotFound=false;
     }
 
+    /**
+     * get Reaction specific side compounds from edge weights
+     * @return rSideCpds
+     */
+    public HashMap<BioReaction,BioCollection<BioMetabolite>> getReactionSideCompounds(CompoundGraph compoundGraph){
+        HashMap<BioReaction,BioCollection<BioMetabolite>> rSideCpds = new HashMap<>();
+        HashMap<String,BioReaction> rList = compoundGraph.getBiochemicalReactionList();
+        HashMap<ReactionEdge,Double> weightMap = compoundGraph.getEdgeWeightMap();
+        for(ReactionEdge test : weightMap.keySet()){
+            System.out.println(test.getV1()+" / "+test.getV2()+" / "+weightMap.get(test).toString()+" / "+test.getReaction().getId());
+        }
+        //To be able to identy side compounds from side and spurious edges (that are not in the csn)
+        //we need to consider every cpd not main as side, reaction-wise.
+        
+        for(BioReaction tmpR : rList.values()){
+            //get all weightMap entry for edges associated with this reaction
+            BioCollection<BioMetabolite> tmpMain = new BioCollection<>();
+            for(ReactionEdge rEdge : compoundGraph.getEdgesFromReaction(tmpR.getId())){
+                if(weightMap.get(rEdge).equals(mainValue)){
+                    tmpMain.add(rEdge.getV1());
+                    tmpMain.add(rEdge.getV2());
+                }
+            }
+            //get all metabolites associated with this reaction
+            BioCollection<BioMetabolite> rMets = tmpR.getMetabolitesView();
+            //remove main metabolites from rMets
+            rMets.removeAll(tmpMain);
+            if(rMets.size()>0){
+                if(rSideCpds.containsKey(tmpR)){
+                    rSideCpds.get(tmpR).addAll(rMets);
+                }else{
+                    rSideCpds.put(tmpR, rMets);
+                }
+            }
+        }
+        return rSideCpds;
+    }
+
     /**
      * remove side transitions , estimated from edge redundancy
      * @return
@@ -76,7 +113,6 @@ public class RPAIRSlikePolicy extends WeightingPolicy<BioMetabolite, ReactionEdg
                 compoundGraph.setEdgeWeight(e,sideValue);
             }
         }
-
         if(removeSide){
             GraphFilter.weightFilter(compoundGraph,sideValue,GraphFilter.EQUALITY);
         }
-- 
GitLab


From 597ccf795a335c508026850ee184026b05dad05c Mon Sep 17 00:00:00 2001
From: LouisonF <fresnaislouison@gmail.com>
Date: Wed, 12 Oct 2022 19:06:02 +0200
Subject: [PATCH 2/8] add getReactionGraph overload

---
 .../met4j_graph/io/Bionetwork2BioGraph.java   | 48 +++++++++++++++++++
 1 file changed, 48 insertions(+)

diff --git a/met4j-graph/src/main/java/fr/inrae/toulouse/metexplore/met4j_graph/io/Bionetwork2BioGraph.java b/met4j-graph/src/main/java/fr/inrae/toulouse/metexplore/met4j_graph/io/Bionetwork2BioGraph.java
index b2515df34..86ab7e080 100644
--- a/met4j-graph/src/main/java/fr/inrae/toulouse/metexplore/met4j_graph/io/Bionetwork2BioGraph.java
+++ b/met4j-graph/src/main/java/fr/inrae/toulouse/metexplore/met4j_graph/io/Bionetwork2BioGraph.java
@@ -161,6 +161,54 @@ public class Bionetwork2BioGraph {
 		return g;
 	}
 
+	/**
+	 * Builds the graph.
+	 *
+	 * @param rcofactors a {@link fr.inrae.toulouse.metexplore.met4j_core.biodata.collection.BioCollection} object.
+	 * @return a {@link fr.inrae.toulouse.metexplore.met4j_graph.core.reaction.ReactionGraph} object.
+	 */
+	public ReactionGraph getReactionGraph(HashMap<BioReaction,BioCollection<BioMetabolite>> rcofactors){
+
+		ReactionGraph g = new ReactionGraph();
+		HashMap<BioMetabolite,BioCollection<BioReaction>> consumingReaction = new HashMap<>();
+		HashMap<BioMetabolite,BioCollection<BioReaction>> productingReaction = new HashMap<>();
+
+		for(BioReaction r : bn.getReactionsView()){
+			if(!r.getLeftsView().isEmpty() && !r.getRightsView().isEmpty()) {
+				g.addVertex(r);
+				BioCollection<BioMetabolite> rLeftView = r.getLeftsView();
+				BioCollection<BioMetabolite> rRightView = r.getRightsView();
+				if(!Objects.isNull(rcofactors.get(r))){
+					rLeftView.removeAll(rcofactors.get(r));
+					rRightView.removeAll(rcofactors.get(r));
+				}
+				rLeftView.forEach(s -> {
+							consumingReaction.computeIfAbsent(s, k -> new BioCollection<>()).add(r);
+							if (r.isReversible()) {
+								productingReaction.computeIfAbsent(s, k -> new BioCollection<>()).add(r);
+							}
+						});
+				
+				rRightView.forEach(p -> {
+							productingReaction.computeIfAbsent(p, k -> new BioCollection<>()).add(r);
+							if (r.isReversible()) {
+								consumingReaction.computeIfAbsent(p, k -> new BioCollection<>()).add(r);
+							}
+						});
+			}
+		}
+
+		consumingReaction.keySet().retainAll(productingReaction.keySet());
+
+		consumingReaction.forEach((c, sources) -> sources.forEach((r1) -> {
+			productingReaction.get(c).forEach(r2 -> {
+
+				if(r1!=r2) g.addEdge(r2,r1,new CompoundEdge(r2,r1,c));
+
+			});
+		}));
+		return g;
+	}
 	
 	/**
 	 * <p>getBipartiteGraph.</p>
-- 
GitLab


From a1a738bc37ddc202ac74d37229012ff42aaca7bc Mon Sep 17 00:00:00 2001
From: LouisonF <fresnaislouison@gmail.com>
Date: Wed, 12 Oct 2022 19:07:21 +0200
Subject: [PATCH 3/8] add RPAIRS and ReactionGraph options

---
 .../networkAnalysis/CarbonSkeletonNet.java    | 87 ++++++++++++++++++-
 1 file changed, 83 insertions(+), 4 deletions(-)

diff --git a/met4j-toolbox/src/main/java/fr/inrae/toulouse/metexplore/met4j_toolbox/networkAnalysis/CarbonSkeletonNet.java b/met4j-toolbox/src/main/java/fr/inrae/toulouse/metexplore/met4j_toolbox/networkAnalysis/CarbonSkeletonNet.java
index 043e7d799..19208ffdb 100644
--- a/met4j-toolbox/src/main/java/fr/inrae/toulouse/metexplore/met4j_toolbox/networkAnalysis/CarbonSkeletonNet.java
+++ b/met4j-toolbox/src/main/java/fr/inrae/toulouse/metexplore/met4j_toolbox/networkAnalysis/CarbonSkeletonNet.java
@@ -3,13 +3,16 @@ package fr.inrae.toulouse.metexplore.met4j_toolbox.networkAnalysis;
 import fr.inrae.toulouse.metexplore.met4j_chemUtils.FormulaParser;
 import fr.inrae.toulouse.metexplore.met4j_core.biodata.BioMetabolite;
 import fr.inrae.toulouse.metexplore.met4j_core.biodata.BioNetwork;
+import fr.inrae.toulouse.metexplore.met4j_core.biodata.BioReaction;
+import fr.inrae.toulouse.metexplore.met4j_core.biodata.collection.BioCollection;
 import fr.inrae.toulouse.metexplore.met4j_graph.computation.connect.weighting.AtomMappingWeightPolicy;
+import fr.inrae.toulouse.metexplore.met4j_graph.computation.connect.weighting.RPAIRSlikePolicy;
 import fr.inrae.toulouse.metexplore.met4j_graph.computation.connect.weighting.ReactionProbabilityWeight;
 import fr.inrae.toulouse.metexplore.met4j_graph.computation.transform.EdgeMerger;
 import fr.inrae.toulouse.metexplore.met4j_graph.computation.transform.VertexContraction;
 import fr.inrae.toulouse.metexplore.met4j_graph.computation.utils.ComputeAdjacencyMatrix;
-import fr.inrae.toulouse.metexplore.met4j_graph.computation.transform.GraphOperation;
 import fr.inrae.toulouse.metexplore.met4j_graph.core.compound.CompoundGraph;
+import fr.inrae.toulouse.metexplore.met4j_graph.core.reaction.ReactionGraph;
 import fr.inrae.toulouse.metexplore.met4j_graph.io.Bionetwork2BioGraph;
 import fr.inrae.toulouse.metexplore.met4j_graph.io.ExportGraph;
 import fr.inrae.toulouse.metexplore.met4j_io.jsbml.reader.JsbmlReader;
@@ -22,13 +25,20 @@ import fr.inrae.toulouse.metexplore.met4j_mathUtils.matrix.ExportMatrix;
 import fr.inrae.toulouse.metexplore.met4j_toolbox.generic.AbstractMet4jApplication;
 import fr.inrae.toulouse.metexplore.met4j_toolbox.generic.annotations.*;
 
-import org.apache.commons.lang3.StringUtils;
 import org.kohsuke.args4j.Option;
 
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
 import java.io.IOException;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.FileWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Objects;
 
 import static fr.inrae.toulouse.metexplore.met4j_toolbox.generic.annotations.EnumFormats.*;
 import static fr.inrae.toulouse.metexplore.met4j_toolbox.generic.annotations.EnumFormats.Sbml;
@@ -72,10 +82,19 @@ public class CarbonSkeletonNet extends AbstractMet4jApplication {
     @Option(name = "-am", aliases = {"--asmatrix"}, usage = "export as matrix (implies simple graph conversion). Default export as GML file", required = false)
     public boolean asMatrix = false;
 
+    @Option(name = "-rf", aliases = {"--reactionscps"}, usage = "input Reaction Side compounds file", required = false)
+    public String reactionSideCompoundsFile = null;
+    
+    @Option(name = "-rg", aliases = {"--reactiongraph"}, usage = "export the reaction graph of the carbon skeleton network", required = false)
+    public boolean reactiongraph = false;
+
+    @Option(name = "-ws", aliases = {"--writeReactionSideCompounds"}, usage = "export the list of reaction side compounds in a tabulated file", required = false)
+    public boolean writeReactionSideCompounds = false;
+
     @Option(name = "-i", aliases = {"--fromIndexes"}, usage = "Use GSAM output with carbon indexes", required = false)
     public boolean fromIndexes = false;
 
-    public static void main(String[] args)  {
+    public static void main(String[] args)  throws IOException, Met4jSbmlReaderException {
 
         CarbonSkeletonNet app = new CarbonSkeletonNet();
 
@@ -86,7 +105,7 @@ public class CarbonSkeletonNet extends AbstractMet4jApplication {
     }
 
 
-    public void run()  {
+    public void run() throws IOException, Met4jSbmlReaderException {
         System.out.print("Reading SBML...");
         JsbmlReader reader = new JsbmlReader(this.inputPath);
         ArrayList<PackageParser> pkgs = new ArrayList<>(Arrays.asList(
@@ -184,6 +203,66 @@ public class CarbonSkeletonNet extends AbstractMet4jApplication {
             System.out.println(" Done.");
         }
 
+        //get the reaction graph
+        if(reactiongraph){
+            //instanciate rgraph variable
+            ReactionGraph rgraph;
+            if(!Objects.isNull(reactionSideCompoundsFile)){
+                //create the hashmap
+                HashMap<BioReaction,BioCollection<BioMetabolite>> reactionSideCompounds = new HashMap<BioReaction,BioCollection<BioMetabolite>>();
+                BufferedReader rscpsReader = new BufferedReader(new FileReader(reactionSideCompoundsFile));
+                String currentLine;
+                //get the Biochemical reaction list
+                HashMap<String,BioReaction> ReactionMap = graph.getBiochemicalReactionList();
+                //Read each line and fill the Reaction Side Compounds Hashmap
+                while ((currentLine = rscpsReader.readLine()) != null){
+                    String[] splitLine = currentLine.split("\t");
+                    BioCollection<BioMetabolite> scpsSet = new BioCollection<BioMetabolite>();
+                    for(String met : splitLine[1].replaceAll("[\\[\\]]", "").split(",")){
+                        scpsSet.add(graph.getVertex(met));
+                        System.out.println(met);
+                    }
+                    reactionSideCompounds.put(ReactionMap.get(splitLine[0]), scpsSet);
+                }
+                rscpsReader.close();
+                rgraph = builder.getReactionGraph(reactionSideCompounds);
+            }else{
+                RPAIRSlikePolicy rp = new RPAIRSlikePolicy(wp);
+                rp.setWeight(graph);      
+                HashMap<BioReaction,BioCollection<BioMetabolite>> reactionSideCompounds = rp.getReactionSideCompounds(graph);
+                rgraph = builder.getReactionGraph(reactionSideCompounds);
+            }
+            ExportGraph.toGmlWithAttributes(rgraph, "reactiongraph_"+this.outputPath, true);
+        }
+
+        //write reaction side compounds
+        if(writeReactionSideCompounds){
+            RPAIRSlikePolicy rp = new RPAIRSlikePolicy(wp);
+            rp.setWeight(graph);      
+            HashMap<BioReaction,BioCollection<BioMetabolite>> reactionSideCompounds = rp.getReactionSideCompounds(graph);
+            BufferedWriter fw = new BufferedWriter(new FileWriter("reactionSCs_"+outputPath.replace(".gml", ".tab"),false),8*1024);
+            try{
+                fw.write("ReactionID\tSideCpds\n");
+                for(BioReaction elem : reactionSideCompounds.keySet()){
+                    //Instanciate iterator
+                    Iterator<BioMetabolite> it = reactionSideCompounds.get(elem).iterator();
+                    fw.write(elem.getId()+"\t");
+                    while(it.hasNext()){
+                        String met = it.next().getId();
+                        if(it.hasNext()){
+                            fw.write(met+",");
+                        }else{
+                            fw.write(met);
+                        }
+                    }
+                    fw.write("\n");
+                            }
+                fw.close();
+            } catch (FileNotFoundException e) {
+                e.printStackTrace();
+            }
+        }
+
         //export graph
         System.out.print("Exporting...");
         if (asMatrix) {
-- 
GitLab


From bf9cc47bbad559d27e577e00a42e61cb551e6dfb Mon Sep 17 00:00:00 2001
From: LouisonF <fresnaislouison@gmail.com>
Date: Thu, 13 Oct 2022 08:48:12 +0200
Subject: [PATCH 4/8] remove debugging verbose in getReactionSideCompounds

---
 .../computation/connect/weighting/RPAIRSlikePolicy.java     | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/met4j-graph/src/main/java/fr/inrae/toulouse/metexplore/met4j_graph/computation/connect/weighting/RPAIRSlikePolicy.java b/met4j-graph/src/main/java/fr/inrae/toulouse/metexplore/met4j_graph/computation/connect/weighting/RPAIRSlikePolicy.java
index 1049bd9dd..af3c43d16 100644
--- a/met4j-graph/src/main/java/fr/inrae/toulouse/metexplore/met4j_graph/computation/connect/weighting/RPAIRSlikePolicy.java
+++ b/met4j-graph/src/main/java/fr/inrae/toulouse/metexplore/met4j_graph/computation/connect/weighting/RPAIRSlikePolicy.java
@@ -39,15 +39,11 @@ public class RPAIRSlikePolicy extends WeightingPolicy<BioMetabolite, ReactionEdg
      */
     public HashMap<BioReaction,BioCollection<BioMetabolite>> getReactionSideCompounds(CompoundGraph compoundGraph){
         HashMap<BioReaction,BioCollection<BioMetabolite>> rSideCpds = new HashMap<>();
-        HashMap<String,BioReaction> rList = compoundGraph.getBiochemicalReactionList();
         HashMap<ReactionEdge,Double> weightMap = compoundGraph.getEdgeWeightMap();
-        for(ReactionEdge test : weightMap.keySet()){
-            System.out.println(test.getV1()+" / "+test.getV2()+" / "+weightMap.get(test).toString()+" / "+test.getReaction().getId());
-        }
         //To be able to identy side compounds from side and spurious edges (that are not in the csn)
         //we need to consider every cpd not main as side, reaction-wise.
         
-        for(BioReaction tmpR : rList.values()){
+        for(BioReaction tmpR : compoundGraph.getBiochemicalReactionList().values()){
             //get all weightMap entry for edges associated with this reaction
             BioCollection<BioMetabolite> tmpMain = new BioCollection<>();
             for(ReactionEdge rEdge : compoundGraph.getEdgesFromReaction(tmpR.getId())){
-- 
GitLab


From e2e098907411917f4d52348cf86ea6c6fef1ea90 Mon Sep 17 00:00:00 2001
From: LouisonF <fresnaislouison@gmail.com>
Date: Thu, 13 Oct 2022 10:00:59 +0200
Subject: [PATCH 5/8] Add a globalsidecompound feature (to remove CoA)

---
 .../met4j_graph/io/Bionetwork2BioGraph.java   | 55 ++++++++++++++++++-
 .../networkAnalysis/CarbonSkeletonNet.java    | 20 +++++--
 2 files changed, 70 insertions(+), 5 deletions(-)

diff --git a/met4j-graph/src/main/java/fr/inrae/toulouse/metexplore/met4j_graph/io/Bionetwork2BioGraph.java b/met4j-graph/src/main/java/fr/inrae/toulouse/metexplore/met4j_graph/io/Bionetwork2BioGraph.java
index 86ab7e080..d236dd10e 100644
--- a/met4j-graph/src/main/java/fr/inrae/toulouse/metexplore/met4j_graph/io/Bionetwork2BioGraph.java
+++ b/met4j-graph/src/main/java/fr/inrae/toulouse/metexplore/met4j_graph/io/Bionetwork2BioGraph.java
@@ -164,7 +164,7 @@ public class Bionetwork2BioGraph {
 	/**
 	 * Builds the graph.
 	 *
-	 * @param rcofactors a {@link fr.inrae.toulouse.metexplore.met4j_core.biodata.collection.BioCollection} object.
+	 * @param rcofactors a {@link java.util.HashMap } object.
 	 * @return a {@link fr.inrae.toulouse.metexplore.met4j_graph.core.reaction.ReactionGraph} object.
 	 */
 	public ReactionGraph getReactionGraph(HashMap<BioReaction,BioCollection<BioMetabolite>> rcofactors){
@@ -210,6 +210,59 @@ public class Bionetwork2BioGraph {
 		return g;
 	}
 	
+		/**
+	 * Builds the graph.
+	 *
+	 * @param rcofactors a {@link java.util.HashMap} object.
+	 * @param globalcofactors a {@link fr.inrae.toulouse.metexplore.met4j_core.biodata.collection.BioCollection} object.
+	 * @return a {@link fr.inrae.toulouse.metexplore.met4j_graph.core.reaction.ReactionGraph} object.
+	 */
+	public ReactionGraph getReactionGraph(HashMap<BioReaction,BioCollection<BioMetabolite>> rcofactors, BioCollection<BioMetabolite> globalcofactors){
+
+		ReactionGraph g = new ReactionGraph();
+		HashMap<BioMetabolite,BioCollection<BioReaction>> consumingReaction = new HashMap<>();
+		HashMap<BioMetabolite,BioCollection<BioReaction>> productingReaction = new HashMap<>();
+
+		for(BioReaction r : bn.getReactionsView()){
+			if(!r.getLeftsView().isEmpty() && !r.getRightsView().isEmpty()) {
+				g.addVertex(r);
+				BioCollection<BioMetabolite> rLeftView = r.getLeftsView();
+				BioCollection<BioMetabolite> rRightView = r.getRightsView();
+				if(!Objects.isNull(rcofactors.get(r))){
+					rLeftView.removeAll(rcofactors.get(r));
+					rRightView.removeAll(rcofactors.get(r));
+				}
+				rLeftView.forEach(s -> {
+							consumingReaction.computeIfAbsent(s, k -> new BioCollection<>()).add(r);
+							if (r.isReversible()) {
+								productingReaction.computeIfAbsent(s, k -> new BioCollection<>()).add(r);
+							}
+						});
+				
+				rRightView.forEach(p -> {
+							productingReaction.computeIfAbsent(p, k -> new BioCollection<>()).add(r);
+							if (r.isReversible()) {
+								consumingReaction.computeIfAbsent(p, k -> new BioCollection<>()).add(r);
+							}
+						});
+			}
+		}
+
+		if(!Objects.isNull(globalcofactors)){
+			consumingReaction.keySet().removeAll(globalcofactors);
+			productingReaction.keySet().removeAll(globalcofactors);
+		}
+		consumingReaction.keySet().retainAll(productingReaction.keySet());
+
+		consumingReaction.forEach((c, sources) -> sources.forEach((r1) -> {
+			productingReaction.get(c).forEach(r2 -> {
+
+				if(r1!=r2) g.addEdge(r2,r1,new CompoundEdge(r2,r1,c));
+
+			});
+		}));
+		return g;
+	}
 	/**
 	 * <p>getBipartiteGraph.</p>
 	 *
diff --git a/met4j-toolbox/src/main/java/fr/inrae/toulouse/metexplore/met4j_toolbox/networkAnalysis/CarbonSkeletonNet.java b/met4j-toolbox/src/main/java/fr/inrae/toulouse/metexplore/met4j_toolbox/networkAnalysis/CarbonSkeletonNet.java
index 19208ffdb..86807029e 100644
--- a/met4j-toolbox/src/main/java/fr/inrae/toulouse/metexplore/met4j_toolbox/networkAnalysis/CarbonSkeletonNet.java
+++ b/met4j-toolbox/src/main/java/fr/inrae/toulouse/metexplore/met4j_toolbox/networkAnalysis/CarbonSkeletonNet.java
@@ -12,9 +12,11 @@ import fr.inrae.toulouse.metexplore.met4j_graph.computation.transform.EdgeMerger
 import fr.inrae.toulouse.metexplore.met4j_graph.computation.transform.VertexContraction;
 import fr.inrae.toulouse.metexplore.met4j_graph.computation.utils.ComputeAdjacencyMatrix;
 import fr.inrae.toulouse.metexplore.met4j_graph.core.compound.CompoundGraph;
+import fr.inrae.toulouse.metexplore.met4j_graph.core.compound.ReactionEdge;
 import fr.inrae.toulouse.metexplore.met4j_graph.core.reaction.ReactionGraph;
 import fr.inrae.toulouse.metexplore.met4j_graph.io.Bionetwork2BioGraph;
 import fr.inrae.toulouse.metexplore.met4j_graph.io.ExportGraph;
+import fr.inrae.toulouse.metexplore.met4j_graph.io.NodeMapping;
 import fr.inrae.toulouse.metexplore.met4j_io.jsbml.reader.JsbmlReader;
 import fr.inrae.toulouse.metexplore.met4j_io.jsbml.reader.Met4jSbmlReaderException;
 import fr.inrae.toulouse.metexplore.met4j_io.jsbml.reader.plugin.FBCParser;
@@ -84,6 +86,9 @@ public class CarbonSkeletonNet extends AbstractMet4jApplication {
 
     @Option(name = "-rf", aliases = {"--reactionscps"}, usage = "input Reaction Side compounds file", required = false)
     public String reactionSideCompoundsFile = null;
+
+    @Option(name = "-gs", aliases = {"--globalscps"}, usage = "input Global Side compounds file", required = false)
+    public String globalSideCompoundsFile = null;
     
     @Option(name = "-rg", aliases = {"--reactiongraph"}, usage = "export the reaction graph of the carbon skeleton network", required = false)
     public boolean reactiongraph = false;
@@ -207,9 +212,9 @@ public class CarbonSkeletonNet extends AbstractMet4jApplication {
         if(reactiongraph){
             //instanciate rgraph variable
             ReactionGraph rgraph;
+            //create the hashmap
+            HashMap<BioReaction,BioCollection<BioMetabolite>> reactionSideCompounds = new HashMap<BioReaction,BioCollection<BioMetabolite>>();
             if(!Objects.isNull(reactionSideCompoundsFile)){
-                //create the hashmap
-                HashMap<BioReaction,BioCollection<BioMetabolite>> reactionSideCompounds = new HashMap<BioReaction,BioCollection<BioMetabolite>>();
                 BufferedReader rscpsReader = new BufferedReader(new FileReader(reactionSideCompoundsFile));
                 String currentLine;
                 //get the Biochemical reaction list
@@ -225,11 +230,18 @@ public class CarbonSkeletonNet extends AbstractMet4jApplication {
                     reactionSideCompounds.put(ReactionMap.get(splitLine[0]), scpsSet);
                 }
                 rscpsReader.close();
-                rgraph = builder.getReactionGraph(reactionSideCompounds);
             }else{
                 RPAIRSlikePolicy rp = new RPAIRSlikePolicy(wp);
                 rp.setWeight(graph);      
-                HashMap<BioReaction,BioCollection<BioMetabolite>> reactionSideCompounds = rp.getReactionSideCompounds(graph);
+                reactionSideCompounds = rp.getReactionSideCompounds(graph);
+            }
+            //If a globalSideCompounds file is provided
+            if(!Objects.isNull(globalSideCompoundsFile)){
+                //read content of file
+                NodeMapping<BioMetabolite, ReactionEdge, CompoundGraph> mapper = new NodeMapping<>(graph).skipIfNotFound();
+                BioCollection<BioMetabolite> sideCpds = mapper.map(globalSideCompoundsFile);
+                rgraph = builder.getReactionGraph(reactionSideCompounds,sideCpds);
+            }else{
                 rgraph = builder.getReactionGraph(reactionSideCompounds);
             }
             ExportGraph.toGmlWithAttributes(rgraph, "reactiongraph_"+this.outputPath, true);
-- 
GitLab


From b32ea655de109ac6a3e876ca766ed562d5763aa4 Mon Sep 17 00:00:00 2001
From: LouisonF <fresnaislouison@gmail.com>
Date: Thu, 13 Oct 2022 18:11:45 +0200
Subject: [PATCH 6/8] add getReactionMainCompounds

---
 .../connect/weighting/RPAIRSlikePolicy.java   | 39 +++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/met4j-graph/src/main/java/fr/inrae/toulouse/metexplore/met4j_graph/computation/connect/weighting/RPAIRSlikePolicy.java b/met4j-graph/src/main/java/fr/inrae/toulouse/metexplore/met4j_graph/computation/connect/weighting/RPAIRSlikePolicy.java
index af3c43d16..b032ff8d9 100644
--- a/met4j-graph/src/main/java/fr/inrae/toulouse/metexplore/met4j_graph/computation/connect/weighting/RPAIRSlikePolicy.java
+++ b/met4j-graph/src/main/java/fr/inrae/toulouse/metexplore/met4j_graph/computation/connect/weighting/RPAIRSlikePolicy.java
@@ -62,11 +62,50 @@ public class RPAIRSlikePolicy extends WeightingPolicy<BioMetabolite, ReactionEdg
                 }else{
                     rSideCpds.put(tmpR, rMets);
                 }
+            }else{
+                if(!rSideCpds.containsKey(tmpR)){
+                    rSideCpds.put(tmpR, null);
+                }
             }
         }
         return rSideCpds;
     }
 
+        /**
+     * get Reaction specific main compounds from edge weights
+     * @return rSideCpds
+     */
+    public HashMap<BioReaction,BioCollection<BioMetabolite>> getReactionMainCompounds(CompoundGraph compoundGraph){
+        HashMap<BioReaction,BioCollection<BioMetabolite>> rMainCpds = new HashMap<>();
+        HashMap<ReactionEdge,Double> weightMap = compoundGraph.getEdgeWeightMap();
+        //To be able to identy side compounds from side and spurious edges (that are not in the csn)
+        //we need to consider every cpd not main as side, reaction-wise.
+        
+        for(BioReaction tmpR : compoundGraph.getBiochemicalReactionList().values()){
+            //get all weightMap entry for edges associated with this reaction
+            BioCollection<BioMetabolite> tmpMain = new BioCollection<>();
+            for(ReactionEdge rEdge : compoundGraph.getEdgesFromReaction(tmpR.getId())){
+                if(weightMap.get(rEdge).equals(mainValue)){
+                    tmpMain.add(rEdge.getV1());
+                    tmpMain.add(rEdge.getV2());
+                }
+            }
+            if(tmpMain.size()>0){
+                if(rMainCpds.containsKey(tmpR)){
+                    rMainCpds.get(tmpR).addAll(tmpMain);
+                }else{
+                    rMainCpds.put(tmpR, tmpMain);
+                }
+            }
+            // }else{
+            //     if(!rSideCpds.containsKey(tmpR)){
+            //         rSideCpds.put(tmpR, null);
+            //     }
+            // }
+        }
+        return rMainCpds;
+    }
+
     /**
      * remove side transitions , estimated from edge redundancy
      * @return
-- 
GitLab


From 17aaaeeb8fe45cd7a15c7941229531e19f319e42 Mon Sep 17 00:00:00 2001
From: LouisonF <fresnaislouison@gmail.com>
Date: Thu, 13 Oct 2022 18:12:38 +0200
Subject: [PATCH 7/8] Add getSimplifiedReactionGraph option

---
 .../met4j_graph/io/Bionetwork2BioGraph.java   | 80 ++++++++++++++++---
 1 file changed, 71 insertions(+), 9 deletions(-)

diff --git a/met4j-graph/src/main/java/fr/inrae/toulouse/metexplore/met4j_graph/io/Bionetwork2BioGraph.java b/met4j-graph/src/main/java/fr/inrae/toulouse/metexplore/met4j_graph/io/Bionetwork2BioGraph.java
index d236dd10e..2bfe15210 100644
--- a/met4j-graph/src/main/java/fr/inrae/toulouse/metexplore/met4j_graph/io/Bionetwork2BioGraph.java
+++ b/met4j-graph/src/main/java/fr/inrae/toulouse/metexplore/met4j_graph/io/Bionetwork2BioGraph.java
@@ -174,7 +174,9 @@ public class Bionetwork2BioGraph {
 		HashMap<BioMetabolite,BioCollection<BioReaction>> productingReaction = new HashMap<>();
 
 		for(BioReaction r : bn.getReactionsView()){
-			if(!r.getLeftsView().isEmpty() && !r.getRightsView().isEmpty()) {
+			//check that current reaction have metabolites and is in the rcofactors map
+			//(if not it means that there is no mention of this reaction in the CSN)
+			if(!r.getLeftsView().isEmpty() && !r.getRightsView().isEmpty() && rcofactors.keySet().contains(r)) {
 				g.addVertex(r);
 				BioCollection<BioMetabolite> rLeftView = r.getLeftsView();
 				BioCollection<BioMetabolite> rRightView = r.getRightsView();
@@ -224,14 +226,16 @@ public class Bionetwork2BioGraph {
 		HashMap<BioMetabolite,BioCollection<BioReaction>> productingReaction = new HashMap<>();
 
 		for(BioReaction r : bn.getReactionsView()){
-			if(!r.getLeftsView().isEmpty() && !r.getRightsView().isEmpty()) {
+			//check that current reaction have metabolites and is in the rcofactors map
+			//(if not it means that there is no mention of this reaction in the CSN)
+			BioCollection<BioMetabolite> rLeftView = r.getLeftsView();
+			BioCollection<BioMetabolite> rRightView = r.getRightsView();
+			if(!Objects.isNull(rcofactors.get(r))){
+				rLeftView.removeAll(rcofactors.get(r));
+				rRightView.removeAll(rcofactors.get(r));
+			}
+			if(!rLeftView.isEmpty() && !rRightView.isEmpty() && rcofactors.keySet().contains(r)) {
 				g.addVertex(r);
-				BioCollection<BioMetabolite> rLeftView = r.getLeftsView();
-				BioCollection<BioMetabolite> rRightView = r.getRightsView();
-				if(!Objects.isNull(rcofactors.get(r))){
-					rLeftView.removeAll(rcofactors.get(r));
-					rRightView.removeAll(rcofactors.get(r));
-				}
 				rLeftView.forEach(s -> {
 							consumingReaction.computeIfAbsent(s, k -> new BioCollection<>()).add(r);
 							if (r.isReversible()) {
@@ -239,7 +243,7 @@ public class Bionetwork2BioGraph {
 							}
 						});
 				
-				rRightView.forEach(p -> {
+						rRightView.forEach(p -> {
 							productingReaction.computeIfAbsent(p, k -> new BioCollection<>()).add(r);
 							if (r.isReversible()) {
 								consumingReaction.computeIfAbsent(p, k -> new BioCollection<>()).add(r);
@@ -263,6 +267,64 @@ public class Bionetwork2BioGraph {
 		}));
 		return g;
 	}
+
+			/**
+	 * Builds the graph.
+	 *
+	 * @param rcofactors a {@link java.util.HashMap} object.
+	 * @param globalcofactors a {@link fr.inrae.toulouse.metexplore.met4j_core.biodata.collection.BioCollection} object.
+	 * @return a {@link fr.inrae.toulouse.metexplore.met4j_graph.core.reaction.ReactionGraph} object.
+	 */
+	public ReactionGraph getSimplifiedReactionGraph(HashMap<BioReaction,BioCollection<BioMetabolite>> rcofactors, BioCollection<BioMetabolite> globalcofactors){
+
+		ReactionGraph g = new ReactionGraph();
+		HashMap<BioMetabolite,BioCollection<BioReaction>> consumingReaction = new HashMap<>();
+		HashMap<BioMetabolite,BioCollection<BioReaction>> productingReaction = new HashMap<>();
+
+		for(BioReaction r : bn.getReactionsView()){
+			//check that current reaction have metabolites and is in the rcofactors map
+			//(if not it means that there is no mention of this reaction in the CSN)
+			BioCollection<BioMetabolite> rLeftView = r.getLeftsView();
+			BioCollection<BioMetabolite> rRightView = r.getRightsView();
+			if(!Objects.isNull(rcofactors.get(r))){
+				rLeftView.removeAll(rcofactors.get(r));
+				rRightView.removeAll(rcofactors.get(r));
+			}
+			if(!rLeftView.isEmpty() && !rRightView.isEmpty() && rcofactors.keySet().contains(r)) {
+				g.addVertex(r);
+				rLeftView.forEach(s -> {
+							consumingReaction.computeIfAbsent(s, k -> new BioCollection<>()).add(r);
+							if (r.isReversible()) {
+								productingReaction.computeIfAbsent(s, k -> new BioCollection<>()).add(r);
+							}
+						});
+				
+						rRightView.forEach(p -> {
+							productingReaction.computeIfAbsent(p, k -> new BioCollection<>()).add(r);
+							if (r.isReversible()) {
+								consumingReaction.computeIfAbsent(p, k -> new BioCollection<>()).add(r);
+							}
+						});
+			}
+		}
+
+		if(!Objects.isNull(globalcofactors)){
+			consumingReaction.keySet().removeAll(globalcofactors);
+			productingReaction.keySet().removeAll(globalcofactors);
+		}
+		consumingReaction.keySet().retainAll(productingReaction.keySet());
+
+		consumingReaction.forEach((c, sources) -> sources.forEach((r1) -> {
+			productingReaction.get(c).forEach(r2 -> {
+				if(r1 != r2 && Objects.isNull(g.getEdge(r1.getId(), r2.getId(),c.getId())) && Objects.isNull(g.getEdge(r2.getId(), r1.getId(),c.getId()))){
+					g.addEdge(r2,r1,new CompoundEdge(r2,r1,c));
+				}
+			});
+		}));
+		return g;
+	}
+
+
 	/**
 	 * <p>getBipartiteGraph.</p>
 	 *
-- 
GitLab


From 5080ce6473a829bcf90cb409540bee8d80eb650d Mon Sep 17 00:00:00 2001
From: LouisonF <fresnaislouison@gmail.com>
Date: Thu, 13 Oct 2022 18:13:18 +0200
Subject: [PATCH 8/8] Add write reaction main compounds

---
 .../networkAnalysis/CarbonSkeletonNet.java    | 86 ++++++++++++++-----
 1 file changed, 63 insertions(+), 23 deletions(-)

diff --git a/met4j-toolbox/src/main/java/fr/inrae/toulouse/metexplore/met4j_toolbox/networkAnalysis/CarbonSkeletonNet.java b/met4j-toolbox/src/main/java/fr/inrae/toulouse/metexplore/met4j_toolbox/networkAnalysis/CarbonSkeletonNet.java
index 86807029e..0d20a766b 100644
--- a/met4j-toolbox/src/main/java/fr/inrae/toulouse/metexplore/met4j_toolbox/networkAnalysis/CarbonSkeletonNet.java
+++ b/met4j-toolbox/src/main/java/fr/inrae/toulouse/metexplore/met4j_toolbox/networkAnalysis/CarbonSkeletonNet.java
@@ -95,6 +95,9 @@ public class CarbonSkeletonNet extends AbstractMet4jApplication {
 
     @Option(name = "-ws", aliases = {"--writeReactionSideCompounds"}, usage = "export the list of reaction side compounds in a tabulated file", required = false)
     public boolean writeReactionSideCompounds = false;
+    
+    @Option(name = "-wm", aliases = {"--writeReactionMainCompounds"}, usage = "export the list of reaction main compounds in a tabulated file", required = false)
+    public boolean writeReactionMainCompounds = false;
 
     @Option(name = "-i", aliases = {"--fromIndexes"}, usage = "Use GSAM output with carbon indexes", required = false)
     public boolean fromIndexes = false;
@@ -207,6 +210,16 @@ public class CarbonSkeletonNet extends AbstractMet4jApplication {
             EdgeMerger.mergeEdgesWithOverride(graph);
             System.out.println(" Done.");
         }
+        //Save compoundgraph version before the reactiongraph phase
+        //export graph
+        System.out.print("Exporting...");
+        if (asMatrix) {
+            ComputeAdjacencyMatrix adjBuilder = new ComputeAdjacencyMatrix(graph);
+            if (!computeWeight) adjBuilder.parallelEdgeWeightsHandling((u, v) -> Math.max(u, v));
+            ExportMatrix.toCSV(this.outputPath, adjBuilder.getadjacencyMatrix());
+        } else {
+            ExportGraph.toGmlWithAttributes(graph,this.outputPath, true);
+        }
 
         //get the reaction graph
         if(reactiongraph){
@@ -223,9 +236,9 @@ public class CarbonSkeletonNet extends AbstractMet4jApplication {
                 while ((currentLine = rscpsReader.readLine()) != null){
                     String[] splitLine = currentLine.split("\t");
                     BioCollection<BioMetabolite> scpsSet = new BioCollection<BioMetabolite>();
-                    for(String met : splitLine[1].replaceAll("[\\[\\]]", "").split(",")){
+                    //TODO clean this
+                    for(String met : splitLine[1].split(",")){
                         scpsSet.add(graph.getVertex(met));
-                        System.out.println(met);
                     }
                     reactionSideCompounds.put(ReactionMap.get(splitLine[0]), scpsSet);
                 }
@@ -237,15 +250,47 @@ public class CarbonSkeletonNet extends AbstractMet4jApplication {
             }
             //If a globalSideCompounds file is provided
             if(!Objects.isNull(globalSideCompoundsFile)){
-                //read content of file
                 NodeMapping<BioMetabolite, ReactionEdge, CompoundGraph> mapper = new NodeMapping<>(graph).skipIfNotFound();
                 BioCollection<BioMetabolite> sideCpds = mapper.map(globalSideCompoundsFile);
-                rgraph = builder.getReactionGraph(reactionSideCompounds,sideCpds);
+                // rgraph = builder.getReactionGraph(reactionSideCompounds,sideCpds);
+                rgraph = builder.getSimplifiedReactionGraph(reactionSideCompounds,sideCpds);
             }else{
                 rgraph = builder.getReactionGraph(reactionSideCompounds);
             }
             ExportGraph.toGmlWithAttributes(rgraph, "reactiongraph_"+this.outputPath, true);
         }
+        //write reaction main compounds
+        if(writeReactionMainCompounds){
+            RPAIRSlikePolicy rp = new RPAIRSlikePolicy(wp);
+            rp.setWeight(graph);      
+            HashMap<BioReaction,BioCollection<BioMetabolite>> reactionMainCompounds = rp.getReactionMainCompounds(graph);
+            BufferedWriter fw = new BufferedWriter(new FileWriter("reactionMCs_"+outputPath.replace(".gml", ".tab"),false),8*1024);
+            try{
+                fw.write("ReactionID\tMainCpds\n");
+                for(BioReaction elem : reactionMainCompounds.keySet()){
+                    //Instanciate iterator
+                    try {
+                        Iterator<BioMetabolite> it = reactionMainCompounds.get(elem).iterator();
+                        fw.write(elem.getId()+"\t");
+                        while(it.hasNext()){
+                            String met = it.next().getId();
+                            if(it.hasNext()){
+                                fw.write(met+",");
+                            }else{
+                                fw.write(met);
+                            }
+                        }
+                        fw.write("\n");
+                    } catch (NullPointerException e) {
+                        fw.write(elem.getId()+"\t"+"\n");
+                    }
+
+                            }
+                fw.close();
+            } catch (FileNotFoundException e) {
+                e.printStackTrace();
+            }
+        }
 
         //write reaction side compounds
         if(writeReactionSideCompounds){
@@ -257,33 +302,28 @@ public class CarbonSkeletonNet extends AbstractMet4jApplication {
                 fw.write("ReactionID\tSideCpds\n");
                 for(BioReaction elem : reactionSideCompounds.keySet()){
                     //Instanciate iterator
-                    Iterator<BioMetabolite> it = reactionSideCompounds.get(elem).iterator();
-                    fw.write(elem.getId()+"\t");
-                    while(it.hasNext()){
-                        String met = it.next().getId();
-                        if(it.hasNext()){
-                            fw.write(met+",");
-                        }else{
-                            fw.write(met);
+                    try {
+                        Iterator<BioMetabolite> it = reactionSideCompounds.get(elem).iterator();
+                        fw.write(elem.getId()+"\t");
+                        while(it.hasNext()){
+                            String met = it.next().getId();
+                            if(it.hasNext()){
+                                fw.write(met+",");
+                            }else{
+                                fw.write(met);
+                            }
                         }
+                        fw.write("\n");
+                    } catch (NullPointerException e) {
+                        fw.write(elem.getId()+"\t"+"\n");
                     }
-                    fw.write("\n");
+
                             }
                 fw.close();
             } catch (FileNotFoundException e) {
                 e.printStackTrace();
             }
         }
-
-        //export graph
-        System.out.print("Exporting...");
-        if (asMatrix) {
-            ComputeAdjacencyMatrix adjBuilder = new ComputeAdjacencyMatrix(graph);
-            if (!computeWeight) adjBuilder.parallelEdgeWeightsHandling((u, v) -> Math.max(u, v));
-            ExportMatrix.toCSV(this.outputPath, adjBuilder.getadjacencyMatrix());
-        } else {
-            ExportGraph.toGmlWithAttributes(graph, this.outputPath, true);
-        }
         System.out.println(" Done.");
         return;
     }
-- 
GitLab