From 23a161c895257f4a06357c6f46f9c3f99b4a9ed6 Mon Sep 17 00:00:00 2001
From: Piotr Gawron <piotr.gawron@uni.lu>
Date: Thu, 21 Dec 2017 17:38:05 +0100
Subject: [PATCH] simple export of reaction layout

---
 .../model/sbml/SbmlBioEntityExporter.java     |  2 +-
 .../model/sbml/SbmlReactionExporter.java      | 85 +++++++++++++++++--
 .../model/sbml/SbmlExporterTest.java          | 43 ++++++++++
 3 files changed, 121 insertions(+), 9 deletions(-)

diff --git a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlBioEntityExporter.java b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlBioEntityExporter.java
index 4e9d5a26ab..97f1c528a8 100644
--- a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlBioEntityExporter.java
+++ b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlBioEntityExporter.java
@@ -57,7 +57,7 @@ public abstract class SbmlBioEntityExporter<T extends BioEntity, S extends org.s
   public abstract S createSbmlElement(T element) throws InconsistentModelException;
 
   protected S getSbmlElement(T element, String compartmentName) throws InconsistentModelException {
-    String mapKey = element.getName() + "\n" + compartmentName;
+    String mapKey = element.getClass().getSimpleName() + "\n" + element.getElementId() + "\n" + compartmentName;
     if (sbmlElementByElementNameAndCompartmentName.get(mapKey) == null) {
       S sbmlElement = createSbmlElement(element);
       sbmlElement.setName(element.getName());
diff --git a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlReactionExporter.java b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlReactionExporter.java
index e6be4a1c1e..de7951c7cb 100644
--- a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlReactionExporter.java
+++ b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlReactionExporter.java
@@ -1,17 +1,30 @@
 package lcsb.mapviewer.converter.model.sbml;
 
+import java.awt.geom.Line2D;
 import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
 
 import org.apache.log4j.Logger;
+import org.sbml.jsbml.SimpleSpeciesReference;
 import org.sbml.jsbml.Species;
+import org.sbml.jsbml.SpeciesReference;
 import org.sbml.jsbml.ext.layout.AbstractReferenceGlyph;
+import org.sbml.jsbml.ext.layout.Curve;
 import org.sbml.jsbml.ext.layout.Layout;
+import org.sbml.jsbml.ext.layout.LineSegment;
+import org.sbml.jsbml.ext.layout.Point;
+import org.sbml.jsbml.ext.layout.ReactionGlyph;
+import org.sbml.jsbml.ext.layout.SpeciesReferenceGlyph;
+import org.sbml.jsbml.ext.layout.SpeciesReferenceRole;
 
 import lcsb.mapviewer.model.map.InconsistentModelException;
+import lcsb.mapviewer.model.map.modifier.Inhibition;
 import lcsb.mapviewer.model.map.reaction.Modifier;
 import lcsb.mapviewer.model.map.reaction.Product;
 import lcsb.mapviewer.model.map.reaction.Reactant;
 import lcsb.mapviewer.model.map.reaction.Reaction;
+import lcsb.mapviewer.model.map.reaction.ReactionNode;
 
 public class SbmlReactionExporter extends SbmlBioEntityExporter<Reaction, org.sbml.jsbml.Reaction> {
   Logger logger = Logger.getLogger(SbmlReactionExporter.class);
@@ -23,29 +36,36 @@ public class SbmlReactionExporter extends SbmlBioEntityExporter<Reaction, org.sb
     this.speciesExporter = speciesExporter;
   }
 
+  Map<ReactionNode, SimpleSpeciesReference> speciesReferenceByReactionNode = new HashMap<>();
+
   @Override
   public org.sbml.jsbml.Reaction createSbmlElement(Reaction reaction) throws InconsistentModelException {
+    logger.debug(reaction);
     org.sbml.jsbml.Reaction result = sbmlModel.createReaction("reaction_" + (getNextId()));
     for (Product product : reaction.getProducts()) {
       Species sbmlSymbol = speciesExporter.sbmlElementByElementId.get(product.getElement().getElementId());
-      result.createProduct(sbmlSymbol);
+      SpeciesReference speciesReference = result.createProduct(sbmlSymbol);
+      speciesReferenceByReactionNode.put(product, speciesReference);
     }
     for (Reactant reactant : reaction.getReactants()) {
       Species sbmlSymbol = speciesExporter.sbmlElementByElementId.get(reactant.getElement().getElementId());
-      result.createReactant(sbmlSymbol);
+      SpeciesReference speciesReference = result.createReactant(sbmlSymbol);
+      logger.debug(reactant);
+      speciesReferenceByReactionNode.put(reactant, speciesReference);
     }
     for (Modifier modifier : reaction.getModifiers()) {
       Species sbmlSymbol = speciesExporter.sbmlElementByElementId.get(modifier.getElement().getElementId());
-      result.createModifier(sbmlSymbol);
+      SimpleSpeciesReference speciesReference = result.createModifier(sbmlSymbol);
+      speciesReferenceByReactionNode.put(modifier, speciesReference);
     }
     return result;
   }
 
   @Override
   protected AbstractReferenceGlyph createElementGlyph(String sbmlElementId, String glyphId) {
-//    AbstractReferenceGlyph speciesGlyph = layout.createReactionGlyph(glyphId, sbmlElementId);
-//    return speciesGlyph;
-    return null;
+    ReactionGlyph reactionGlyph = layout.createReactionGlyph(glyphId, sbmlElementId);
+
+    return reactionGlyph;
   }
 
   @Override
@@ -54,9 +74,58 @@ public class SbmlReactionExporter extends SbmlBioEntityExporter<Reaction, org.sb
   }
 
   @Override
-  protected void assignLayoutToGlyph(Reaction element, AbstractReferenceGlyph compartmentGlyph) {
-    // TODO Auto-generated method stub
+  protected void assignLayoutToGlyph(Reaction reaction, AbstractReferenceGlyph compartmentGlyph) {
+    logger.debug(reaction);
+    ReactionGlyph reactionGlyph = (ReactionGlyph) compartmentGlyph;
+    boolean firstReactant = true;
+    for (Reactant reactant : reaction.getReactants()) {
+      SpeciesReferenceGlyph reactantGlyph = createNodeGlyph(reactionGlyph, reactant);
+      if (firstReactant) {
+        reactantGlyph.setRole(SpeciesReferenceRole.SUBSTRATE);
+      } else {
+        reactantGlyph.setRole(SpeciesReferenceRole.SIDESUBSTRATE);
+      }
+      firstReactant = false;
+    }
+    boolean firstProduct = true;
+    for (Product product : reaction.getProducts()) {
+      SpeciesReferenceGlyph productGlyph = createNodeGlyph(reactionGlyph, product);
+      if (firstProduct) {
+        productGlyph.setRole(SpeciesReferenceRole.PRODUCT);
+      } else {
+        productGlyph.setRole(SpeciesReferenceRole.SIDEPRODUCT);
+      }
+      firstProduct = false;
+    }
+    for (Modifier modifier : reaction.getModifiers()) {
+      SpeciesReferenceGlyph modifierGlyph = createNodeGlyph(reactionGlyph, modifier);
+      if (modifier instanceof Inhibition) {
+        modifierGlyph.setRole(SpeciesReferenceRole.INHIBITOR);
+      } else {
+        modifierGlyph.setRole(SpeciesReferenceRole.MODIFIER);
+      }
+    }
+
+  }
 
+  private SpeciesReferenceGlyph createNodeGlyph(ReactionGlyph reactionGlyph, ReactionNode node) {
+    SpeciesReferenceGlyph reactantGlyph = reactionGlyph.createSpeciesReferenceGlyph("node_" + getNextId());
+    reactantGlyph.setSpeciesGlyph(speciesExporter.sbmlGlyphByElementId.get(node.getElement().getElementId()).getId());
+    reactantGlyph.setCurve(createCurve(node));
+    logger.debug(node);
+    reactantGlyph.setSpeciesReference(speciesReferenceByReactionNode.get(node));
+    return reactantGlyph;
+  }
+
+  private Curve createCurve(ReactionNode reactant) {
+    Curve curve = new Curve();
+    for (Line2D line : reactant.getLine().getLines()) {
+      LineSegment segment = new LineSegment();
+      segment.setStart(new Point(line.getX1(), line.getY1()));
+      segment.setEnd(new Point(line.getX2(), line.getY2()));
+      curve.addCurveSegment(segment);
+    }
+    return curve;
   }
 
 }
diff --git a/converter-sbml/src/test/java/lcsb/mapviewer/converter/model/sbml/SbmlExporterTest.java b/converter-sbml/src/test/java/lcsb/mapviewer/converter/model/sbml/SbmlExporterTest.java
index 32345a0b66..54d333f7fc 100644
--- a/converter-sbml/src/test/java/lcsb/mapviewer/converter/model/sbml/SbmlExporterTest.java
+++ b/converter-sbml/src/test/java/lcsb/mapviewer/converter/model/sbml/SbmlExporterTest.java
@@ -6,6 +6,7 @@ import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
 import java.awt.Desktop;
+import java.awt.geom.Point2D;
 import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.nio.file.Files;
@@ -13,15 +14,21 @@ import java.nio.file.Files;
 import org.apache.log4j.Logger;
 import org.junit.Test;
 
+import lcsb.mapviewer.common.Configuration;
 import lcsb.mapviewer.converter.ConverterParams;
 import lcsb.mapviewer.converter.graphics.AbstractImageGenerator;
 import lcsb.mapviewer.converter.graphics.NormalImageGenerator;
 import lcsb.mapviewer.converter.graphics.PngImageGenerator;
+import lcsb.mapviewer.model.graphics.PolylineData;
 import lcsb.mapviewer.model.map.compartment.Compartment;
 import lcsb.mapviewer.model.map.model.Model;
 import lcsb.mapviewer.model.map.model.ModelFullIndexed;
+import lcsb.mapviewer.model.map.reaction.Product;
+import lcsb.mapviewer.model.map.reaction.Reactant;
 import lcsb.mapviewer.model.map.reaction.Reaction;
 import lcsb.mapviewer.model.map.reaction.ReactionNode;
+import lcsb.mapviewer.model.map.reaction.type.StateTransitionReaction;
+import lcsb.mapviewer.model.map.species.GenericProtein;
 import lcsb.mapviewer.model.map.species.Species;
 
 public class SbmlExporterTest {
@@ -152,4 +159,40 @@ public class SbmlExporterTest {
     assertNotNull(deserializedModel);
   }
 
+  @Test
+  public void testExportReactionWithLayout() throws Exception {
+    Model model = new ModelFullIndexed(null);
+    GenericProtein p1 = new GenericProtein("s1");
+    p1.setWidth(100);
+    p1.setHeight(20);
+    p1.setX(10);
+    p1.setY(10);
+    model.addElement(p1);
+    GenericProtein p2 = new GenericProtein("s2");
+    p2.setWidth(100);
+    p2.setHeight(20);
+    p2.setX(10);
+    p2.setY(50);
+    model.addElement(p2);
+    Reaction reaction = new StateTransitionReaction();
+    Reactant reactant = new Reactant(p1);
+    Product product = new Product(p2);
+    PolylineData reactantLine = new PolylineData();
+    reactantLine.addPoint(new Point2D.Double(50, 20));
+    reactantLine.addPoint(new Point2D.Double(50, 30));
+    reactant.setLine(reactantLine);
+    PolylineData productLine = new PolylineData();
+    productLine.addPoint(new Point2D.Double(50, 40));
+    productLine.addPoint(new Point2D.Double(50, 60));
+    product.setLine(productLine);
+    reaction.addReactant(reactant);
+    reaction.addProduct(product);
+    model.addReaction(reaction);
+    Model deserializedModel = getModelAfterSerializing(model);
+    Reaction deserializedReaction = deserializedModel.getReactions().iterator().next();
+    assertEquals(reactantLine.length(), deserializedReaction.getReactants().get(0).getLine().length(), Configuration.EPSILON);
+    assertEquals(productLine.length(), deserializedReaction.getProducts().get(0).getLine().length(), Configuration.EPSILON);
+
+  }
+
 }
-- 
GitLab