From b64538d8f0135b448518eafbc1176fc055ceace6 Mon Sep 17 00:00:00 2001
From: cfrainay <clement.frainay@inrae.fr>
Date: Thu, 9 Feb 2023 17:37:12 +0100
Subject: [PATCH 1/5] Create app for pathwayNetwork creation

+ added alternative building in BioNetwork2Biograph + improve edge label for pathway graph + expand handled attributes for gml export
---
 .../core/pathway/PathwayGraphEdge.java        |   7 +
 .../met4j_graph/io/Bionetwork2BioGraph.java   |  45 ++++-
 .../met4j_graph/io/ExportGraph.java           |  21 +-
 .../met4j_graph/TestBionetwork2BioGraph.java  |  71 +++++++
 .../networkAnalysis/PathwayNet.java           | 181 ++++++++++++++++++
 5 files changed, 317 insertions(+), 8 deletions(-)
 create mode 100644 met4j-toolbox/src/main/java/fr/inrae/toulouse/metexplore/met4j_toolbox/networkAnalysis/PathwayNet.java

diff --git a/met4j-graph/src/main/java/fr/inrae/toulouse/metexplore/met4j_graph/core/pathway/PathwayGraphEdge.java b/met4j-graph/src/main/java/fr/inrae/toulouse/metexplore/met4j_graph/core/pathway/PathwayGraphEdge.java
index dc4c01ec8..8ffb8d878 100644
--- a/met4j-graph/src/main/java/fr/inrae/toulouse/metexplore/met4j_graph/core/pathway/PathwayGraphEdge.java
+++ b/met4j-graph/src/main/java/fr/inrae/toulouse/metexplore/met4j_graph/core/pathway/PathwayGraphEdge.java
@@ -40,6 +40,8 @@ import fr.inrae.toulouse.metexplore.met4j_graph.core.Edge;
 import fr.inrae.toulouse.metexplore.met4j_core.biodata.BioPathway;
 import fr.inrae.toulouse.metexplore.met4j_core.biodata.BioMetabolite;
 
+import java.util.stream.Collectors;
+
 /**
  * The edge Class linking two {@link fr.inrae.toulouse.metexplore.met4j_core.biodata.BioPathway}, linked by {@link fr.inrae.toulouse.metexplore.met4j_core.biodata.BioMetabolite}
  *
@@ -116,4 +118,9 @@ public class PathwayGraphEdge extends Edge<BioPathway>{
         connectingCompounds.remove(e);
     }
 
+    @Override
+    public String toString(){
+        return connectingCompounds.stream().map(BioMetabolite::getId).collect(Collectors.joining(","));
+    }
+
 }
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..647802e71 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
@@ -196,13 +196,24 @@ public class Bionetwork2BioGraph {
 		}
 		return g;
 	}
-	
+
 	/**
-	 * Builds the graph.
+	 * Builds a pathway "seed" graph, where a directed edge exists between two pathways if one produces a sink that is a source of the other.
+	 * i.e. it constructs an overlap graph that is ignoring intermediary compounds and consider only inputs and outputs of pathways
 	 *
 	 * @return the pathway graph
 	 */
 	public PathwayGraph getPathwayGraph(){
+		return getPathwayGraph(new BioCollection<BioMetabolite>());
+	}
+
+	/**
+	 * Builds a pathway "seed" graph, where a directed edge exists between two pathways if one produces a sink that is a source of the other.
+	 * i.e. it constructs an overlap graph that is ignoring intermediary compounds and consider only inputs and outputs of pathways
+	 * @param cofactors a list of compounds to ignore for connecting pathways
+	 * @return
+	 */
+	public PathwayGraph getPathwayGraph(BioCollection<BioMetabolite> cofactors){
 
 		PathwayGraph g = new PathwayGraph();
 		HashMap<BioPathway,BioCollection<BioMetabolite>> pathwaysSources = new HashMap<>();
@@ -242,6 +253,36 @@ public class Bionetwork2BioGraph {
 							pathwaysSources.get(p2).stream()
 							.filter(m -> pathwaysProducts.get(p1).contains(m))
 							.collect(Collectors.toCollection(BioCollection::new));
+					connectors.removeAll(cofactors);
+					if(!connectors.isEmpty()) {
+						PathwayGraphEdge edge = new PathwayGraphEdge(p1, p2, connectors);
+						g.addEdge(p1, p2, edge);
+					}
+				}
+			}
+		}
+		return g;
+	}
+
+	/**
+	 * Builds a pathway "overlap" graph, where an undirected edge exists between two pathways they share a common compound.
+	 *
+	 * @param cofactors a list of compounds to ignore for connecting pathways
+	 * @return the pathway graph
+	 */
+	public PathwayGraph getPathwayOverlapGraph(BioCollection<BioMetabolite> cofactors){
+		PathwayGraph g = new PathwayGraph();
+		//add nodes
+		for(BioPathway p : bn.getPathwaysView()){
+			g.addVertex(p);
+		}
+		//create connections
+		for(BioPathway p1 : bn.getPathwaysView()){
+			for(BioPathway p2 : bn.getPathwaysView()){
+				if(p1!=p2){
+					BioCollection<BioMetabolite> connectors = new BioCollection<>(bn.getMetabolitesFromPathway(p1));
+					connectors.retainAll(bn.getMetabolitesFromPathway(p2));
+					connectors.removeAll(cofactors);
 					if(!connectors.isEmpty()) {
 						PathwayGraphEdge edge = new PathwayGraphEdge(p1, p2, connectors);
 						g.addEdge(p1, p2, edge);
diff --git a/met4j-graph/src/main/java/fr/inrae/toulouse/metexplore/met4j_graph/io/ExportGraph.java b/met4j-graph/src/main/java/fr/inrae/toulouse/metexplore/met4j_graph/io/ExportGraph.java
index 1aee1efd8..8baf626cd 100644
--- a/met4j-graph/src/main/java/fr/inrae/toulouse/metexplore/met4j_graph/io/ExportGraph.java
+++ b/met4j-graph/src/main/java/fr/inrae/toulouse/metexplore/met4j_graph/io/ExportGraph.java
@@ -43,6 +43,7 @@ import java.io.PrintWriter;
 import java.util.HashMap;
 import java.util.Map;
 
+import fr.inrae.toulouse.metexplore.met4j_core.biodata.*;
 import fr.inrae.toulouse.metexplore.met4j_graph.core.BioGraph;
 import fr.inrae.toulouse.metexplore.met4j_graph.core.compound.CompoundGraph;
 import fr.inrae.toulouse.metexplore.met4j_graph.core.compound.ReactionEdge;
@@ -50,13 +51,10 @@ import fr.inrae.toulouse.metexplore.met4j_graph.core.compound.ReactionEdge;
 import fr.inrae.toulouse.metexplore.met4j_graph.core.Edge;
 import fr.inrae.toulouse.metexplore.met4j_graph.core.bipartite.BipartiteEdge;
 import fr.inrae.toulouse.metexplore.met4j_graph.core.bipartite.BipartiteGraph;
-import fr.inrae.toulouse.metexplore.met4j_core.biodata.BioReactant;
-import fr.inrae.toulouse.metexplore.met4j_core.biodata.BioReaction;
-import fr.inrae.toulouse.metexplore.met4j_core.biodata.BioEntity;
-import fr.inrae.toulouse.metexplore.met4j_core.biodata.BioNetwork;
-import fr.inrae.toulouse.metexplore.met4j_core.biodata.BioMetabolite;
 import fr.inrae.toulouse.metexplore.met4j_core.biodata.collection.BioCollection;
 import fr.inrae.toulouse.metexplore.met4j_core.biodata.collection.BioCollections;
+import fr.inrae.toulouse.metexplore.met4j_graph.core.pathway.PathwayGraph;
+import fr.inrae.toulouse.metexplore.met4j_graph.core.pathway.PathwayGraphEdge;
 import fr.inrae.toulouse.metexplore.met4j_graph.core.reaction.CompoundEdge;
 import fr.inrae.toulouse.metexplore.met4j_graph.core.reaction.ReactionGraph;
 import org.jgrapht.nio.Attribute;
@@ -329,19 +327,30 @@ public class ExportGraph {
 			e.printStackTrace();
 		}
 	}
-
 	public static <V extends BioEntity, E extends Edge<V>, G extends BioGraph<V,E>> void toGmlWithAttributes(G graph, String outputPath, Map<V,?> att, String attName){
+		toGmlWithAttributes(graph, outputPath, att, attName,false);
+	}
+
+	public static <V extends BioEntity, E extends Edge<V>, G extends BioGraph<V,E>> void toGmlWithAttributes(G graph, String outputPath, Map<V,?> att, String attName, boolean weight){
 		try {
 			GmlExporter<V, E> gml
 					= new GmlExporter<>();
 			gml.setParameter(GmlExporter.Parameter.EXPORT_EDGE_LABELS, true);
 			gml.setParameter(GmlExporter.Parameter.EXPORT_VERTEX_LABELS, true);
 			gml.setParameter(GmlExporter.Parameter.EXPORT_CUSTOM_VERTEX_ATTRIBUTES, true);
+			gml.setParameter(GmlExporter.Parameter.EXPORT_CUSTOM_EDGE_ATTRIBUTES, true);
 			gml.setVertexAttributeProvider(v -> {
 				Map<String, Attribute> att2 = new HashMap<>();
 				att2.put(attName, DefaultAttribute.createAttribute(att.get(v).toString()));
 				return att2;
 			});
+			if(weight){
+				gml.setEdgeAttributeProvider(e -> {
+					Map<String, Attribute> att3 = new HashMap<>();
+					att3.put("Weight", DefaultAttribute.createAttribute(graph.getEdgeWeight(e)));
+					return att3;
+				});
+			}
 
 			FileWriter fw = new FileWriter(new File(outputPath).getAbsoluteFile());
 			PrintWriter pw = new PrintWriter(fw);
diff --git a/met4j-graph/src/test/java/fr/inrae/toulouse/metexplore/met4j_graph/TestBionetwork2BioGraph.java b/met4j-graph/src/test/java/fr/inrae/toulouse/metexplore/met4j_graph/TestBionetwork2BioGraph.java
index 61879ebb1..49b06a417 100644
--- a/met4j-graph/src/test/java/fr/inrae/toulouse/metexplore/met4j_graph/TestBionetwork2BioGraph.java
+++ b/met4j-graph/src/test/java/fr/inrae/toulouse/metexplore/met4j_graph/TestBionetwork2BioGraph.java
@@ -271,4 +271,75 @@ public class TestBionetwork2BioGraph {
 
 	}
 
+	@Test
+	public void testGetPathwayOverlapGraph(){
+		PathwayGraph g = builder.getPathwayOverlapGraph(new BioCollection<>());
+		Assert.assertEquals("wrong number of vertices",4, g.vertexSet().size());
+		Assert.assertEquals("wrong number of edges",10, g.edgeSet().size());
+
+		Assert.assertEquals("wrong in-degree of compound "+p1.getId(), 2, g.inDegreeOf(p1));
+		Assert.assertEquals("wrong out-degree of compound "+p1.getId(), 2, g.outDegreeOf(p1));
+		Assert.assertEquals("wrong in-degree of compound "+p2.getId(), 2, g.inDegreeOf(p2));
+		Assert.assertEquals("wrong out-degree of compound "+p2.getId(), 2, g.outDegreeOf(p2));
+		Assert.assertEquals("wrong in-degree of compound "+p3.getId(), 3, g.inDegreeOf(p3));
+		Assert.assertEquals("wrong out-degree of compound "+p3.getId(), 3, g.outDegreeOf(p3));
+		Assert.assertEquals("wrong in-degree of compound "+p4.getId(), 3, g.inDegreeOf(p4));
+		Assert.assertEquals("wrong out-degree of compound "+p4.getId(), 3, g.outDegreeOf(p4));
+
+		Assert.assertEquals("wrong compound connecting pathway", 3,g.getEdge(p3,p1).getConnectingCompounds().size());
+		Assert.assertEquals("wrong compound connecting pathway", g.getEdge(p1,p3).getConnectingCompounds(),g.getEdge(p3,p1).getConnectingCompounds());
+		assertTrue("wrong compound connecting pathway", g.getEdge(p3,p1).getConnectingCompounds().contains(a));
+		assertTrue("wrong compound connecting pathway", g.getEdge(p3,p1).getConnectingCompounds().contains(b));
+		assertTrue("wrong compound connecting pathway", g.getEdge(p3,p1).getConnectingCompounds().contains(e));
+		Assert.assertEquals("wrong compound connecting pathway", 2,g.getEdge(p3,p4).getConnectingCompounds().size());
+		Assert.assertEquals("wrong compound connecting pathway", g.getEdge(p4,p3).getConnectingCompounds(),g.getEdge(p3,p4).getConnectingCompounds());
+		assertTrue("wrong compound connecting pathway", g.getEdge(p3,p4).getConnectingCompounds().contains(b));
+		assertTrue("wrong compound connecting pathway", g.getEdge(p3,p4).getConnectingCompounds().contains(c));
+		Assert.assertEquals("wrong compound connecting pathway", 2,g.getEdge(p1,p4).getConnectingCompounds().size());
+		Assert.assertEquals("wrong compound connecting pathway", g.getEdge(p4,p1).getConnectingCompounds(),g.getEdge(p1,p4).getConnectingCompounds());
+		assertTrue("wrong compound connecting pathway", g.getEdge(p1,p4).getConnectingCompounds().contains(b));
+		assertTrue("wrong compound connecting pathway", g.getEdge(p1,p4).getConnectingCompounds().contains(h));
+		Assert.assertEquals("wrong compound connecting pathway", 1,g.getEdge(p2,p3).getConnectingCompounds().size());
+		Assert.assertEquals("wrong compound connecting pathway", g.getEdge(p3,p2).getConnectingCompounds(),g.getEdge(p2,p3).getConnectingCompounds());
+		assertTrue("wrong compound connecting pathway", g.getEdge(p2,p3).getConnectingCompounds().contains(f));
+		Assert.assertEquals("wrong compound connecting pathway", 1,g.getEdge(p2,p4).getConnectingCompounds().size());
+		Assert.assertEquals("wrong compound connecting pathway", g.getEdge(p4,p2).getConnectingCompounds(),g.getEdge(p2,p4).getConnectingCompounds());
+		assertTrue("wrong compound connecting pathway", g.getEdge(p2,p4).getConnectingCompounds().contains(d));
+	}
+
+	@Test
+	public void testGetPathwayOverlapGraphII(){
+		BioCollection<BioMetabolite> sides = new BioCollection<>();
+		sides.add(f);
+		PathwayGraph g = builder.getPathwayOverlapGraph(sides);
+		Assert.assertEquals("wrong number of vertices",4, g.vertexSet().size());
+		Assert.assertEquals("wrong number of edges",8, g.edgeSet().size());
+
+		Assert.assertEquals("wrong in-degree of compound "+p1.getId(), 2, g.inDegreeOf(p1));
+		Assert.assertEquals("wrong out-degree of compound "+p1.getId(), 2, g.outDegreeOf(p1));
+		Assert.assertEquals("wrong in-degree of compound "+p2.getId(), 1, g.inDegreeOf(p2));
+		Assert.assertEquals("wrong out-degree of compound "+p2.getId(), 1, g.outDegreeOf(p2));
+		Assert.assertEquals("wrong in-degree of compound "+p3.getId(), 2, g.inDegreeOf(p3));
+		Assert.assertEquals("wrong out-degree of compound "+p3.getId(), 2, g.outDegreeOf(p3));
+		Assert.assertEquals("wrong in-degree of compound "+p4.getId(), 3, g.inDegreeOf(p4));
+		Assert.assertEquals("wrong out-degree of compound "+p4.getId(), 3, g.outDegreeOf(p4));
+
+		Assert.assertEquals("wrong compound connecting pathway", 3,g.getEdge(p3,p1).getConnectingCompounds().size());
+		Assert.assertEquals("wrong compound connecting pathway", g.getEdge(p1,p3).getConnectingCompounds(),g.getEdge(p3,p1).getConnectingCompounds());
+		assertTrue("wrong compound connecting pathway", g.getEdge(p3,p1).getConnectingCompounds().contains(a));
+		assertTrue("wrong compound connecting pathway", g.getEdge(p3,p1).getConnectingCompounds().contains(b));
+		assertTrue("wrong compound connecting pathway", g.getEdge(p3,p1).getConnectingCompounds().contains(e));
+		Assert.assertEquals("wrong compound connecting pathway", 2,g.getEdge(p3,p4).getConnectingCompounds().size());
+		Assert.assertEquals("wrong compound connecting pathway", g.getEdge(p4,p3).getConnectingCompounds(),g.getEdge(p3,p4).getConnectingCompounds());
+		assertTrue("wrong compound connecting pathway", g.getEdge(p3,p4).getConnectingCompounds().contains(b));
+		assertTrue("wrong compound connecting pathway", g.getEdge(p3,p4).getConnectingCompounds().contains(c));
+		Assert.assertEquals("wrong compound connecting pathway", 2,g.getEdge(p1,p4).getConnectingCompounds().size());
+		Assert.assertEquals("wrong compound connecting pathway", g.getEdge(p4,p1).getConnectingCompounds(),g.getEdge(p1,p4).getConnectingCompounds());
+		assertTrue("wrong compound connecting pathway", g.getEdge(p1,p4).getConnectingCompounds().contains(b));
+		assertTrue("wrong compound connecting pathway", g.getEdge(p1,p4).getConnectingCompounds().contains(h));
+		Assert.assertEquals("wrong compound connecting pathway", 1,g.getEdge(p2,p4).getConnectingCompounds().size());
+		Assert.assertEquals("wrong compound connecting pathway", g.getEdge(p4,p2).getConnectingCompounds(),g.getEdge(p2,p4).getConnectingCompounds());
+		assertTrue("wrong compound connecting pathway", g.getEdge(p2,p4).getConnectingCompounds().contains(d));
+	}
+
 }
diff --git a/met4j-toolbox/src/main/java/fr/inrae/toulouse/metexplore/met4j_toolbox/networkAnalysis/PathwayNet.java b/met4j-toolbox/src/main/java/fr/inrae/toulouse/metexplore/met4j_toolbox/networkAnalysis/PathwayNet.java
new file mode 100644
index 000000000..ad4a8ad76
--- /dev/null
+++ b/met4j-toolbox/src/main/java/fr/inrae/toulouse/metexplore/met4j_toolbox/networkAnalysis/PathwayNet.java
@@ -0,0 +1,181 @@
+package fr.inrae.toulouse.metexplore.met4j_toolbox.networkAnalysis;
+
+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.BioPathway;
+import fr.inrae.toulouse.metexplore.met4j_core.biodata.collection.BioCollection;
+import fr.inrae.toulouse.metexplore.met4j_graph.computation.connect.weighting.CustomWeightPolicy;
+import fr.inrae.toulouse.metexplore.met4j_graph.computation.connect.weighting.UnweightedPolicy;
+import fr.inrae.toulouse.metexplore.met4j_graph.computation.connect.weighting.WeightsFromFile;
+import fr.inrae.toulouse.metexplore.met4j_graph.computation.utils.ComputeAdjacencyMatrix;
+import fr.inrae.toulouse.metexplore.met4j_graph.core.WeightingPolicy;
+import fr.inrae.toulouse.metexplore.met4j_graph.core.pathway.PathwayGraph;
+import fr.inrae.toulouse.metexplore.met4j_graph.core.pathway.PathwayGraphEdge;
+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;
+import fr.inrae.toulouse.metexplore.met4j_io.jsbml.reader.Met4jSbmlReaderException;
+import fr.inrae.toulouse.metexplore.met4j_io.jsbml.reader.plugin.FBCParser;
+import fr.inrae.toulouse.metexplore.met4j_io.jsbml.reader.plugin.GroupPathwayParser;
+import fr.inrae.toulouse.metexplore.met4j_io.jsbml.reader.plugin.NotesParser;
+import fr.inrae.toulouse.metexplore.met4j_io.jsbml.reader.plugin.PackageParser;
+import fr.inrae.toulouse.metexplore.met4j_mapping.Mapper;
+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.EnumFormats;
+import fr.inrae.toulouse.metexplore.met4j_toolbox.generic.annotations.EnumParameterTypes;
+import fr.inrae.toulouse.metexplore.met4j_toolbox.generic.annotations.Format;
+import fr.inrae.toulouse.metexplore.met4j_toolbox.generic.annotations.ParameterType;
+import org.kohsuke.args4j.Option;
+
+import java.io.IOException;
+import java.util.*;
+import java.util.stream.Collectors;
+
+public class PathwayNet extends AbstractMet4jApplication {
+
+    @Format(name= EnumFormats.Sbml)
+    @ParameterType(name= EnumParameterTypes.InputFile)
+    @Option(name = "-s", usage = "input SBML file", required = true)
+    public String inputPath = null;
+
+    @ParameterType(name= EnumParameterTypes.InputFile)
+    @Format(name= EnumFormats.Txt)
+    @Option(name = "-sc", usage = "input Side compound file (recommended)", required = false)
+    public String inputSide = null;
+
+    @ParameterType(name= EnumParameterTypes.OutputFile)
+    @Format(name= EnumFormats.Gml)
+    @Option(name = "-o", usage = "output Graph file", required = true)
+    public String outputPath = null;
+
+    @Option(name = "-ri", aliases = {"--removeIsolatedNodes"}, usage = "remove isolated nodes", required = false)
+    public boolean removeIsolated = false;
+
+    @Option(name = "-oss", aliases = {"--onlySourcesAndSinks"}, usage = "consider only metabolites that are source or sink in the pathway (i.e non-intermediary compounds)", required = false)
+    public boolean onlySourcesAndSinks = false;
+
+    @ParameterType(name=EnumParameterTypes.InputFile)
+    @Format(name=EnumFormats.Tsv)
+    @Option(name = "-cw", aliases = {"--customWeights"}, usage = "an optional file containing weights for compound pairs", forbids = {"-ncw"})
+    public String weightFile = null;
+
+    @Option(name = "-ncw", aliases = {"--connectorWeights"}, usage = "set number of connecting compounds as weight", forbids = {"-cw"})
+    public Boolean connectors = false;
+
+    @Option(name = "-un", aliases = {"--undirected"}, usage = "create as undirected", required = false)
+    public boolean undirected = false;
+
+    @Option(name = "-am", aliases = {"--asmatrix"}, usage = "export as matrix (implies simple graph conversion). Default export as GML file", required = false)
+    public boolean asMatrix = false;
+
+    public static void main(String[] args)  {
+
+        PathwayNet app = new PathwayNet();
+
+        app.parseArguments(args);
+
+        app.run();
+
+    }
+
+
+    public void run() {
+        System.out.print("Reading SBML...");
+        JsbmlReader reader = new JsbmlReader(this.inputPath);
+        ArrayList<PackageParser> pkgs = new ArrayList<>(Arrays.asList(
+                new NotesParser(false), new FBCParser(), new GroupPathwayParser()));
+
+        BioNetwork network = null;
+
+        try {
+            network = reader.read(pkgs);
+        } catch (Met4jSbmlReaderException e) {
+            System.err.println("Error while reading the SBML file");
+            System.err.println(e.getMessage());
+            System.exit(1);
+        }
+        System.out.println(" Done.");
+
+        //Graph processing: side compound removal [optional]
+        BioCollection<BioMetabolite> sideCpds = new BioCollection<>();
+        if (inputSide != null) {
+            System.err.println("importing side compounds...");
+            Mapper<BioMetabolite> cmapper = new Mapper<>(network, BioNetwork::getMetabolitesView).skipIfNotFound();
+
+            try {
+                sideCpds = cmapper.map(inputSide);
+            } catch (IOException e) {
+                System.err.println("Error while reading the side compound file");
+                System.err.println(e.getMessage());
+                System.exit(1);
+            }
+            if (cmapper.getNumberOfSkippedEntries() > 0)
+                System.err.println(cmapper.getNumberOfSkippedEntries() + " side compounds not found in network.");
+        }
+
+        System.out.print("Buildinig Network...");
+        Bionetwork2BioGraph builder = new Bionetwork2BioGraph(network);
+        PathwayGraph graph = onlySourcesAndSinks ? builder.getPathwayGraph(sideCpds) : builder.getPathwayOverlapGraph(sideCpds);
+        System.out.println(" Done.");
+
+        //Graph processing: set weights [optional]
+        WeightingPolicy<BioPathway, PathwayGraphEdge, PathwayGraph> wp = new UnweightedPolicy<>();
+        if (weightFile != null) {
+            System.err.println("Setting edge weights...");
+            wp = new WeightsFromFile(weightFile);
+        } else if (connectors) {
+            wp = new CustomWeightPolicy<>(e -> Double.valueOf(e.getConnectingCompounds().size()));
+        }
+        wp.setWeight(graph);
+        System.out.println(" Done.");
+
+        //invert graph as undirected (copy edge weight to reversed edge)
+        if(undirected){
+            System.out.print("Create Undirected...");
+            graph.asUndirected();
+            System.out.println(" Done.");
+        }
+
+        //remove isolated nodes
+        if(removeIsolated){
+            System.out.println("Remove isolated nodes...");
+            HashSet<BioPathway> nodes = new HashSet<>(graph.vertexSet());
+            graph.removeIsolatedNodes();
+            nodes.removeAll(graph.vertexSet());
+            for(BioPathway n : nodes){
+                System.out.println("\tremoving " + n.getName());
+            }
+            System.out.println(" Done.");
+        }
+
+        //export graph
+        System.out.print("Exporting...");
+        if(asMatrix){
+            ComputeAdjacencyMatrix adjBuilder = new ComputeAdjacencyMatrix(graph);
+            ExportMatrix.toCSV(this.outputPath,adjBuilder.getadjacencyMatrix());
+        }else{
+            BioNetwork finalNetwork = network;
+            Map<BioPathway,Integer> size = graph.vertexSet().stream()
+                    .collect(Collectors.toMap(p -> p, p -> finalNetwork.getMetabolitesFromPathway(p).size()));
+            ExportGraph.toGmlWithAttributes(graph, this.outputPath, size, "size",true);
+        }
+        System.out.println(" Done.");
+        return;
+    }
+
+    @Override
+    public String getLabel() {return this.getClass().getSimpleName();}
+
+    @Override
+    public String getLongDescription() {
+        return "Genome-scale metabolic networks are often partitioned into metabolic pathways. Pathways are frequently " +
+                "considered independently despite frequent coupling in their activity due to shared metabolites. In " +
+                "order to decipher the interconnections linking overlapping pathways, this app proposes the creation of " +
+                "\"Pathway Network\", where two pathways are linked if they share compounds.";
+    }
+
+    @Override
+    public String getShortDescription() {return "Creation of a Pathway Network representation of a SBML file content";}
+}
+
-- 
GitLab


From 77f9b5d6371149a5f52f18283eac56ffda431530 Mon Sep 17 00:00:00 2001
From: cfrainay <clement.frainay@inrae.fr>
Date: Fri, 10 Feb 2023 18:14:58 +0100
Subject: [PATCH 2/5] add name attribute in export graph + improve overlap
 graph (no edge duplication)

---
 .../met4j_graph/io/Bionetwork2BioGraph.java   | 21 ++++++++++---------
 .../met4j_graph/io/ExportGraph.java           |  1 +
 2 files changed, 12 insertions(+), 10 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 647802e71..896626863 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
@@ -277,16 +277,17 @@ public class Bionetwork2BioGraph {
 			g.addVertex(p);
 		}
 		//create connections
-		for(BioPathway p1 : bn.getPathwaysView()){
-			for(BioPathway p2 : bn.getPathwaysView()){
-				if(p1!=p2){
-					BioCollection<BioMetabolite> connectors = new BioCollection<>(bn.getMetabolitesFromPathway(p1));
-					connectors.retainAll(bn.getMetabolitesFromPathway(p2));
-					connectors.removeAll(cofactors);
-					if(!connectors.isEmpty()) {
-						PathwayGraphEdge edge = new PathwayGraphEdge(p1, p2, connectors);
-						g.addEdge(p1, p2, edge);
-					}
+		ArrayList<BioPathway> plist = new ArrayList<>(bn.getPathwaysView());
+		for (int i = 0; i < plist.size()-1; i++){
+			for (int j = i+1; j < plist.size(); j++){
+				BioPathway p1 = plist.get(i);
+				BioPathway p2 = plist.get(j);
+				BioCollection<BioMetabolite> connectors = new BioCollection<>(bn.getMetabolitesFromPathway(p1));
+				connectors.retainAll(bn.getMetabolitesFromPathway(p2));
+				connectors.removeAll(cofactors);
+				if(!connectors.isEmpty()) {
+					PathwayGraphEdge edge = new PathwayGraphEdge(p1, p2, connectors);
+					g.addEdge(p1, p2, edge);
 				}
 			}
 		}
diff --git a/met4j-graph/src/main/java/fr/inrae/toulouse/metexplore/met4j_graph/io/ExportGraph.java b/met4j-graph/src/main/java/fr/inrae/toulouse/metexplore/met4j_graph/io/ExportGraph.java
index 8baf626cd..06b296ce4 100644
--- a/met4j-graph/src/main/java/fr/inrae/toulouse/metexplore/met4j_graph/io/ExportGraph.java
+++ b/met4j-graph/src/main/java/fr/inrae/toulouse/metexplore/met4j_graph/io/ExportGraph.java
@@ -342,6 +342,7 @@ public class ExportGraph {
 			gml.setVertexAttributeProvider(v -> {
 				Map<String, Attribute> att2 = new HashMap<>();
 				att2.put(attName, DefaultAttribute.createAttribute(att.get(v).toString()));
+				att2.put("Name",DefaultAttribute.createAttribute(v.getName()));
 				return att2;
 			});
 			if(weight){
-- 
GitLab


From 965f5a73664af55f3b5cf2ec358861702c040a85 Mon Sep 17 00:00:00 2001
From: cfrainay <clement.frainay@inrae.fr>
Date: Tue, 14 Feb 2023 14:21:42 +0100
Subject: [PATCH 3/5] add undirected graph simplification for export. remove
 undirected option in app to avoid confusion

---
 .../computation/transform/EdgeMerger.java     | 35 ++++++++++++++++++-
 .../met4j_graph/io/Bionetwork2BioGraph.java   |  2 ++
 .../met4j_graph/TestEdgeMerger.java           | 14 ++++++++
 .../networkAnalysis/PathwayNet.java           | 14 ++------
 4 files changed, 53 insertions(+), 12 deletions(-)

diff --git a/met4j-graph/src/main/java/fr/inrae/toulouse/metexplore/met4j_graph/computation/transform/EdgeMerger.java b/met4j-graph/src/main/java/fr/inrae/toulouse/metexplore/met4j_graph/computation/transform/EdgeMerger.java
index 8eaaf1be9..c3a7b0872 100644
--- a/met4j-graph/src/main/java/fr/inrae/toulouse/metexplore/met4j_graph/computation/transform/EdgeMerger.java
+++ b/met4j-graph/src/main/java/fr/inrae/toulouse/metexplore/met4j_graph/computation/transform/EdgeMerger.java
@@ -36,6 +36,7 @@
 package fr.inrae.toulouse.metexplore.met4j_graph.computation.transform;
 
 import java.util.*;
+import java.util.stream.Collectors;
 
 import com.google.common.primitives.Doubles;
 import fr.inrae.toulouse.metexplore.met4j_graph.core.BioGraph;
@@ -240,5 +241,37 @@ public class EdgeMerger {
 		};
 	}
 
-
+	/**
+	 * Merge parallel and reversed edges, keep only one. This can be used to avoid edge duplications during undirected graph export
+	 *
+	 * @param g a G object.
+	 * @param comparator a {@link java.util.Comparator} object.
+	 * @param <V> a V object.
+	 * @param <E> a E object.
+	 * @param <G> a G object.
+	 */
+	public static <V extends BioEntity,E extends Edge<V>, G extends BioGraph<V,E>> void undirectedMergeEdgesWithOverride(G g, Comparator<E> comparator){
+		List<List<E>> mergingGroups = new ArrayList<>();
+		Set<E> visited = new HashSet<>();
+		for(E edge : g.edgeSet()){
+			if(!visited.contains(edge)){
+				Double w = g.getEdgeWeight(edge);
+				List<E> parallelAndReversed=new ArrayList<>();
+				//get parallel edges
+				parallelAndReversed.addAll(g.getAllEdges(edge.getV1(), edge.getV2()));
+				//get reversed edges
+				parallelAndReversed.addAll(g.getAllEdges(edge.getV2(), edge.getV1()));
+				//set ignore edges in merging group during next iterations.
+				visited.addAll(parallelAndReversed);
+				mergingGroups.add(parallelAndReversed);
+			}
+		}
+		for(List<E> mergingGroup : mergingGroups){
+			//get 'best' edge
+			if(comparator!=null) mergingGroup.sort(comparator);
+			mergingGroup.remove(0);
+			//remove other edges
+			g.removeAllEdges(mergingGroup);
+		}
+	}
 }
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 896626863..a81eb265b 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
@@ -288,6 +288,8 @@ public class Bionetwork2BioGraph {
 				if(!connectors.isEmpty()) {
 					PathwayGraphEdge edge = new PathwayGraphEdge(p1, p2, connectors);
 					g.addEdge(p1, p2, edge);
+					PathwayGraphEdge edger = new PathwayGraphEdge(p2, p1, connectors);
+					g.addEdge(p2, p1, edger);
 				}
 			}
 		}
diff --git a/met4j-graph/src/test/java/fr/inrae/toulouse/metexplore/met4j_graph/TestEdgeMerger.java b/met4j-graph/src/test/java/fr/inrae/toulouse/metexplore/met4j_graph/TestEdgeMerger.java
index 2dcf39805..3fd515755 100644
--- a/met4j-graph/src/test/java/fr/inrae/toulouse/metexplore/met4j_graph/TestEdgeMerger.java
+++ b/met4j-graph/src/test/java/fr/inrae/toulouse/metexplore/met4j_graph/TestEdgeMerger.java
@@ -43,6 +43,7 @@ import static org.junit.Assert.*;
 
 import fr.inrae.toulouse.metexplore.met4j_graph.computation.transform.EdgeMerger;
 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.compound.CompoundGraph;
 import fr.inrae.toulouse.metexplore.met4j_graph.core.compound.ReactionEdge;
 import fr.inrae.toulouse.metexplore.met4j_graph.core.parallel.MergedGraph;
@@ -212,4 +213,17 @@ public class TestEdgeMerger {
 		Assert.assertTrue("Wrong edge kept", g2.containsEdge(ab3));
 	}
 
+	@Test
+	public void testMergeUndirected() {
+		CompoundGraph g4 = new CompoundGraph(g);
+		g4.setEdgeWeight(g4.getEdge(ba1.getV1(),ba1.getV2(),ba1.getReaction()),0.1);
+		g4.setEdgeWeight(g4.getEdge(ab1.getV1(),ab1.getV2(),ab1.getReaction()),2.0);
+		g4.setEdgeWeight(g4.getEdge(ab2.getV1(),ab2.getV2(),ab2.getReaction()),5.0);
+		g4.setEdgeWeight(g4.getEdge(ab3.getV1(),ab3.getV2(),ab3.getReaction()),10.0);
+		EdgeMerger.undirectedMergeEdgesWithOverride(g4, EdgeMerger.lowWeightFirst(g4));
+		Assert.assertEquals("Error while creating the initial graph", 10, g.edgeSet().size());
+		Assert.assertEquals("Wrong final number of edges", 5, g4.edgeSet().size());
+		Assert.assertTrue("Wrong edge kept", g4.containsEdge(ba1));
+	}
+
 }
diff --git a/met4j-toolbox/src/main/java/fr/inrae/toulouse/metexplore/met4j_toolbox/networkAnalysis/PathwayNet.java b/met4j-toolbox/src/main/java/fr/inrae/toulouse/metexplore/met4j_toolbox/networkAnalysis/PathwayNet.java
index ad4a8ad76..37f8cf21c 100644
--- a/met4j-toolbox/src/main/java/fr/inrae/toulouse/metexplore/met4j_toolbox/networkAnalysis/PathwayNet.java
+++ b/met4j-toolbox/src/main/java/fr/inrae/toulouse/metexplore/met4j_toolbox/networkAnalysis/PathwayNet.java
@@ -7,6 +7,7 @@ import fr.inrae.toulouse.metexplore.met4j_core.biodata.collection.BioCollection;
 import fr.inrae.toulouse.metexplore.met4j_graph.computation.connect.weighting.CustomWeightPolicy;
 import fr.inrae.toulouse.metexplore.met4j_graph.computation.connect.weighting.UnweightedPolicy;
 import fr.inrae.toulouse.metexplore.met4j_graph.computation.connect.weighting.WeightsFromFile;
+import fr.inrae.toulouse.metexplore.met4j_graph.computation.transform.EdgeMerger;
 import fr.inrae.toulouse.metexplore.met4j_graph.computation.utils.ComputeAdjacencyMatrix;
 import fr.inrae.toulouse.metexplore.met4j_graph.core.WeightingPolicy;
 import fr.inrae.toulouse.metexplore.met4j_graph.core.pathway.PathwayGraph;
@@ -57,15 +58,12 @@ public class PathwayNet extends AbstractMet4jApplication {
 
     @ParameterType(name=EnumParameterTypes.InputFile)
     @Format(name=EnumFormats.Tsv)
-    @Option(name = "-cw", aliases = {"--customWeights"}, usage = "an optional file containing weights for compound pairs", forbids = {"-ncw"})
+    @Option(name = "-cw", aliases = {"--customWeights"}, usage = "an optional file containing weights for pathway pairs", forbids = {"-ncw"})
     public String weightFile = null;
 
     @Option(name = "-ncw", aliases = {"--connectorWeights"}, usage = "set number of connecting compounds as weight", forbids = {"-cw"})
     public Boolean connectors = false;
 
-    @Option(name = "-un", aliases = {"--undirected"}, usage = "create as undirected", required = false)
-    public boolean undirected = false;
-
     @Option(name = "-am", aliases = {"--asmatrix"}, usage = "export as matrix (implies simple graph conversion). Default export as GML file", required = false)
     public boolean asMatrix = false;
 
@@ -130,13 +128,6 @@ public class PathwayNet extends AbstractMet4jApplication {
         wp.setWeight(graph);
         System.out.println(" Done.");
 
-        //invert graph as undirected (copy edge weight to reversed edge)
-        if(undirected){
-            System.out.print("Create Undirected...");
-            graph.asUndirected();
-            System.out.println(" Done.");
-        }
-
         //remove isolated nodes
         if(removeIsolated){
             System.out.println("Remove isolated nodes...");
@@ -155,6 +146,7 @@ public class PathwayNet extends AbstractMet4jApplication {
             ComputeAdjacencyMatrix adjBuilder = new ComputeAdjacencyMatrix(graph);
             ExportMatrix.toCSV(this.outputPath,adjBuilder.getadjacencyMatrix());
         }else{
+            if (onlySourcesAndSinks) EdgeMerger.undirectedMergeEdgesWithOverride(graph,null);
             BioNetwork finalNetwork = network;
             Map<BioPathway,Integer> size = graph.vertexSet().stream()
                     .collect(Collectors.toMap(p -> p, p -> finalNetwork.getMetabolitesFromPathway(p).size()));
-- 
GitLab


From dc7502a46a48e85ec06e8e5c6a8a7634fe7f2c2a Mon Sep 17 00:00:00 2001
From: cfrainay <clement.frainay@inrae.fr>
Date: Tue, 14 Feb 2023 14:35:57 +0100
Subject: [PATCH 4/5] fix undirected export

---
 .../metexplore/met4j_toolbox/networkAnalysis/PathwayNet.java    | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/met4j-toolbox/src/main/java/fr/inrae/toulouse/metexplore/met4j_toolbox/networkAnalysis/PathwayNet.java b/met4j-toolbox/src/main/java/fr/inrae/toulouse/metexplore/met4j_toolbox/networkAnalysis/PathwayNet.java
index 37f8cf21c..14bc91bb4 100644
--- a/met4j-toolbox/src/main/java/fr/inrae/toulouse/metexplore/met4j_toolbox/networkAnalysis/PathwayNet.java
+++ b/met4j-toolbox/src/main/java/fr/inrae/toulouse/metexplore/met4j_toolbox/networkAnalysis/PathwayNet.java
@@ -146,7 +146,7 @@ public class PathwayNet extends AbstractMet4jApplication {
             ComputeAdjacencyMatrix adjBuilder = new ComputeAdjacencyMatrix(graph);
             ExportMatrix.toCSV(this.outputPath,adjBuilder.getadjacencyMatrix());
         }else{
-            if (onlySourcesAndSinks) EdgeMerger.undirectedMergeEdgesWithOverride(graph,null);
+            if (!onlySourcesAndSinks) EdgeMerger.undirectedMergeEdgesWithOverride(graph,null);
             BioNetwork finalNetwork = network;
             Map<BioPathway,Integer> size = graph.vertexSet().stream()
                     .collect(Collectors.toMap(p -> p, p -> finalNetwork.getMetabolitesFromPathway(p).size()));
-- 
GitLab


From 13ef635b565a4f96a2277c584ca6c00753de69f5 Mon Sep 17 00:00:00 2001
From: cfrainay <clement.frainay@inrae.fr>
Date: Tue, 14 Feb 2023 14:39:44 +0100
Subject: [PATCH 5/5] update README

---
 met4j-toolbox/README.md | 87 +++++++++++++++++++++++++++++++----------
 1 file changed, 66 insertions(+), 21 deletions(-)

diff --git a/met4j-toolbox/README.md b/met4j-toolbox/README.md
index 63ec06a78..cab825c51 100644
--- a/met4j-toolbox/README.md
+++ b/met4j-toolbox/README.md
@@ -448,27 +448,44 @@ Wrappers launch the met4j singularity container, so the server where your Galaxy
 <table>
 <thead><tr><th colspan="2">Package fr.inrae.toulouse.metexplore.met4j_toolbox.networkAnalysis</th></tr></thead>
 <tbody>
-<tr><td>CarbonSkeletonNet</td><td>Create a carbon skeleton graph representation of a SBML file content, using GSAM atom-mapping file (see https://forgemia.inra.fr/metexplore/gsam)<details><summary><small>more</small></summary>Metabolic networks used for quantitative analysis often contain links that are irrelevant for graph-based structural analysis. For example, inclusion of side compounds or modelling artifacts such as 'biomass' nodes. Focusing on links between compounds that share parts of their carbon skeleton allows to avoid many transitions involving side compounds, and removes entities without defined chemical structure. This app produce a Carbon Skeleton Network relevant for graph-based analysis of metabolism, in GML or matrix format, from a SBML and an GSAM atom mapping file. GSAM (see https://forgemia.inra.fr/metexplore/gsam) perform atom mapping at genome-scale level using the Reaction Decoder Tool (https://github.com/asad/ReactionDecoder) and allows to compute the number of conserved atoms of a given type between reactants.This app also enable Markov-chain based analysis of metabolic networks by computing reaction-normalized transition probabilities on the Carbon Skeleton Network.<br/><br/><pre><code> -am (--asmatrix)            : export as matrix (implies simple graph
-                               conversion). Default export as GML file
-                               (default: false)
- -g VAL                      : input GSAM file
- -h                          : prints the help (default: false)
- -i (--fromIndexes)          : Use GSAM output with carbon indexes (default:
-                               false)
- -ks (--keepSingleCarbon)    : keep edges involving single-carbon compounds,
-                               such as CO2 (requires formulas in SBML)
-                               (default: false)
- -mc (--nocomp)              : merge compartments (requires unique compound
-                               names that are consistent across compartments)
-                               (default: false)
- -me (--simple)              : merge parallel edges to produce a simple graph
-                               (default: false)
- -o VAL                      : output Graph file
- -ri (--removeIsolatedNodes) : remove isolated nodes (default: false)
- -s VAL                      : input SBML file
- -tp (--transitionproba)     : set transition probability as weight (default:
-                               false)
- -un (--undirected)          : create as undirected (default: false)
+<tr><td>BipartiteDistanceMatrix</td><td>Create a compound to reactions distance matrix.<details><summary><small>more</small></summary>Create a compound to reactions distance matrix.<br/>The distance between two nodes (metabolite or reaction) is computed as the length of the shortest path connecting the two in the bipartite graph, Bipartite graph are composed of two distinct sets of nodes and two nodes can be linked only if they are from distinct sets.<br/>Therefore a metabolite node can be linked to a reaction node if the metabolite is a substrate or product of the reaction.<br/>An optional custom edge weighting can be used, turning the distances into the sum of edge weights in the lightest path, rather than the length of the shortest path.Custom weighting can be provided in a file. In that case, edges without weight are ignored during path search.<br/>If no edge weighting is set, it is recommended to provide a list of side compounds to ignore during network traversal.<br/><br/><pre><code> -f (--full)          : compute full pairwise matrix from both reactions and
+                        compounds lists (default: false)
+ -h                   : prints the help (default: false)
+ -i VAL               : input SBML file
+ -m (--mets) VAL      : an optional file containing list of compounds of
+                        interest.
+ -o VAL               : output Matrix file
+ -r (--rxns) VAL      : an optional file containing list of reactions of
+                        interest.
+ -re (--rExclude) VAL : an optional file containing list of reactions to ignore
+ -sc (--side) VAL     : an optional file containing list of side compounds to
+                        ignore
+ -u (--undirected)    : Ignore reaction direction (default: false)
+ -w (--weights) VAL   : an optional file containing weights for compound pairs
+</code></pre></details></td></tr>
+<tr><td>CarbonSkeletonNet</td><td>Create a carbon skeleton graph representation of a SBML file content, using GSAM atom-mapping file (see https://forgemia.inra.fr/metexplore/gsam)<details><summary><small>more</small></summary>Metabolic networks used for quantitative analysis often contain links that are irrelevant for graph-based structural analysis. For example, inclusion of side compounds or modelling artifacts such as 'biomass' nodes. Focusing on links between compounds that share parts of their carbon skeleton allows to avoid many transitions involving side compounds, and removes entities without defined chemical structure. This app produce a Carbon Skeleton Network relevant for graph-based analysis of metabolism, in GML or matrix format, from a SBML and an GSAM atom mapping file. GSAM (see https://forgemia.inra.fr/metexplore/gsam) perform atom mapping at genome-scale level using the Reaction Decoder Tool (https://github.com/asad/ReactionDecoder) and allows to compute the number of conserved atoms of a given type between reactants.This app also enable Markov-chain based analysis of metabolic networks by computing reaction-normalized transition probabilities on the Carbon Skeleton Network.<br/><br/><pre><code> -am (--asmatrix)             : export as matrix (implies simple graph
+                                conversion). Default export as GML file
+                                (default: false)
+ -g VAL                       : input GSAM file
+ -h                           : prints the help (default: false)
+ -i (--fromIndexes)           : Use GSAM output with carbon indexes (default:
+                                false)
+ -ks (--keepSingleCarbon)     : keep edges involving single-carbon compounds,
+                                such as CO2 (requires formulas in SBML)
+                                (default: false)
+ -main (--onlyMainTransition) : Compute RPAIRS-like tags and keep only main
+                                transitions for each reaction (default: false)
+ -mc (--nocomp)               : merge compartments (requires unique compound
+                                names that are consistent across compartments)
+                                (default: false)
+ -me (--simple)               : merge parallel edges to produce a simple graph
+                                (default: false)
+ -o VAL                       : output Graph file
+ -ri (--removeIsolatedNodes)  : remove isolated nodes (default: false)
+ -s VAL                       : input SBML file
+ -tp (--transitionproba)      : set transition probability as weight (default:
+                                false)
+ -un (--undirected)           : create as undirected (default: false)
 </code></pre></details></td></tr>
 <tr><td>ChemSimilarityWeighting</td><td>Provides tabulated compound graph edge list, with one column with reactant pair's chemical similarity.<details><summary><small>more</small></summary>Provides tabulated compound graph edge list, with one column with reactant pair's chemical similarity.Chemical similarity has been proposed as edge weight for finding meaningful paths in metabolic networks, using shortest (lightest) path search. See McSha et al. 2003 (https://doi.org/10.1093/bioinformatics/btg217), Rahman et al. 2005 (https://doi.org/10.1093/bioinformatics/bti116) and Pertusi et al. 2014 (https://doi.org/10.1093/bioinformatics/btu760)<br/><br/><pre><code> -d (--asDist)                          : Use distance rather than similarity
                                           (default: false)
@@ -651,6 +668,22 @@ Wrappers launch the met4j singularity container, so the server where your Galaxy
  -sd (--skipdist) : skip full distance matrix computation (quick summary)
                     (default: false)
 </code></pre></details></td></tr>
+<tr><td>PathwayNet</td><td>Creation of a Pathway Network representation of a SBML file content<details><summary><small>more</small></summary>Genome-scale metabolic networks are often partitioned into metabolic pathways. Pathways are frequently considered independently despite frequent coupling in their activity due to shared metabolites. In order to decipher the interconnections linking overlapping pathways, this app proposes the creation of "Pathway Network", where two pathways are linked if they share compounds.<br/><br/><pre><code> -am (--asmatrix)             : export as matrix (implies simple graph
+                                conversion). Default export as GML file
+                                (default: false)
+ -cw (--customWeights) VAL    : an optional file containing weights for pathway
+                                pairs
+ -h                           : prints the help (default: false)
+ -ncw (--connectorWeights)    : set number of connecting compounds as weight
+                                (default: false)
+ -o VAL                       : output Graph file
+ -oss (--onlySourcesAndSinks) : consider only metabolites that are source or
+                                sink in the pathway (i.e non-intermediary
+                                compounds) (default: false)
+ -ri (--removeIsolatedNodes)  : remove isolated nodes (default: false)
+ -s VAL                       : input SBML file
+ -sc VAL                      : input Side compound file (recommended)
+</code></pre></details></td></tr>
 <tr><td>PrecursorNetwork</td><td>Perform a network expansion from a set of compound targets to create a precursor network.<details><summary><small>more</small></summary>Perform a network expansion from a set of compound targets to create a precursor network.<br/>The precursor network of a set of compounds (targets) refer to the sub-part of a metabolic network from which a target can be reachedThe network expansion process consist of adding a reaction to the network if any of its products are either a targets or a substrate of a previously added reaction<br/><br/><pre><code> -h                 : prints the help (default: false)
  -i VAL             : input SBML file: path to network used for computing
                       scope, in sbml format.
@@ -737,3 +770,15 @@ Wrappers launch the met4j singularity container, so the server where your Galaxy
 </code></pre></details></td></tr>
 </tbody>
 </table>
+<table>
+<thead><tr><th colspan="2">Package fr.inrae.toulouse.metexplore.met4j_toolbox.reconstruction</th></tr></thead>
+<tbody>
+<tr><td>SbmlCheckBalance</td><td>Check balance of all the reactions in a SBML.<details><summary><small>more</small></summary>Check balance of all the reactions in a SBML.<br/>A reaction is balanced if all its reactants have a chemical formula with a good syntax and if the quantity of each atom is the same in both sides of the reaction.<br/>For each reaction, indicates if the reaction is balanced, the list of the atoms and the sum of their quantity, and the list of the metabolites that don't have a correct chemical formula.<br/><br/><pre><code> -h        : prints the help (default: false)
+ -out VAL  : [checkBalances.tsv] Output tabulated file (1st col: reaction id,
+             2nd col: boolean indicating if the reaction is balanced, 3rd col:
+             atom balances, 4th col: metabolites with bad formula (default:
+             checkBalances.tsv)
+ -sbml VAL : Original sbml file
+</code></pre></details></td></tr>
+</tbody>
+</table>
-- 
GitLab