From 7f88dcd670899b2dcc26b700257c532ea05ecd06 Mon Sep 17 00:00:00 2001
From: Piotr Gawron <piotr.gawron@uni.lu>
Date: Fri, 24 Nov 2017 16:57:28 +0100
Subject: [PATCH] operators for reaction added

---
 .../model/sbml/SbmlReactionParser.java        | 107 +++++++++++++++++-
 .../converter/model/sbml/SbmlParserTest.java  |  15 ++-
 2 files changed, 117 insertions(+), 5 deletions(-)

diff --git a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlReactionParser.java b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlReactionParser.java
index bec76e8dcd..2acf38c9ff 100644
--- a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlReactionParser.java
+++ b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlReactionParser.java
@@ -1,6 +1,7 @@
 package lcsb.mapviewer.converter.model.sbml;
 
 import java.awt.geom.Point2D;
+import java.lang.reflect.InvocationTargetException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
@@ -23,15 +24,24 @@ import org.sbml.jsbml.ext.layout.SpeciesReferenceGlyph;
 import org.sbml.jsbml.util.NotImplementedException;
 
 import lcsb.mapviewer.common.exception.InvalidArgumentException;
+import lcsb.mapviewer.common.exception.InvalidStateException;
 import lcsb.mapviewer.converter.InvalidInputDataExecption;
+import lcsb.mapviewer.converter.model.celldesigner.types.ModifierType;
+import lcsb.mapviewer.model.graphics.ArrowType;
+import lcsb.mapviewer.model.graphics.ArrowTypeData;
 import lcsb.mapviewer.model.graphics.PolylineData;
 import lcsb.mapviewer.model.map.MiriamData;
-import lcsb.mapviewer.model.map.modifier.Catalysis;
+import lcsb.mapviewer.model.map.modifier.Inhibition;
+import lcsb.mapviewer.model.map.modifier.Modulation;
+import lcsb.mapviewer.model.map.modifier.Trigger;
+import lcsb.mapviewer.model.map.reaction.AndOperator;
 import lcsb.mapviewer.model.map.reaction.Modifier;
+import lcsb.mapviewer.model.map.reaction.NodeOperator;
 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.SplitOperator;
 import lcsb.mapviewer.model.map.reaction.type.StateTransitionReaction;
 import lcsb.mapviewer.model.map.species.Element;
 import lcsb.mapviewer.model.map.species.Species;
@@ -84,9 +94,40 @@ public class SbmlReactionParser {
       for (SpeciesReferenceGlyph speciesRefernceGlyph : glyph.getListOfSpeciesReferenceGlyphs()) {
         SpeciesGlyph speciesGlyph = layout.getSpeciesGlyph(speciesRefernceGlyph.getSpeciesGlyph());
         ReactionNode minervaNode = null;
+        Class<? extends ReactionNode> nodeClass = null;
+        switch (speciesRefernceGlyph.getRole()) {
+        case ACTIVATOR:
+          nodeClass = Trigger.class;
+          break;
+        case INHIBITOR:
+          nodeClass = Inhibition.class;
+          break;
+        case MODIFIER:
+          nodeClass = Modulation.class;
+          break;
+        case PRODUCT:
+          nodeClass = Product.class;
+          break;
+        case SIDEPRODUCT:
+          nodeClass = Product.class;
+          break;
+        case SIDESUBSTRATE:
+          nodeClass = Reactant.class;
+          break;
+        case SUBSTRATE:
+          nodeClass = Reactant.class;
+          break;
+        case UNDEFINED:
+          nodeClass = null;
+          break;
+        }
         for (ReactionNode node : reactionWithLayout.getReactionNodes()) {
           if (node.getElement().getElementId().equals(speciesGlyph.getSpecies())) {
-            minervaNode = node;
+            if (nodeClass == null) {
+              minervaNode = node;
+            } else if (node.getClass().isAssignableFrom(nodeClass)) {
+              minervaNode = node;
+            }
           }
         }
         if (minervaNode == null) {
@@ -109,22 +150,80 @@ public class SbmlReactionParser {
             line.addPoint(end);
           }
         }
+        if (minervaNode instanceof Reactant) {
+          line = line.reverse();
+        }
+        if (minervaNode instanceof Product) {
+          ArrowTypeData atd = new ArrowTypeData();
+          atd.setArrowType(ArrowType.FULL);
+          line.setEndAtd(atd);
+        } else if (minervaNode instanceof Modifier) {
+          for (ModifierType mt : ModifierType.values()) {
+            if (mt.getClazz().equals(nodeClass)) {
+              line.setEndAtd(mt.getAtd());
+              line.setType(mt.getLineType());
+            }
+          }
+        }
         minervaNode.setLine(line);
         minervaNode.setElement(minervaElement);
+        if (nodeClass != minervaNode.getClass()) {
+          reactionWithLayout.removeModifier((Modifier) minervaNode);
+
+          try {
+            ReactionNode newNode = nodeClass.getConstructor().newInstance();
+            newNode.setElement(minervaElement);
+            newNode.setLine(line);
+            reactionWithLayout.addNode(newNode);
+          } catch (InstantiationException | IllegalAccessException | IllegalArgumentException
+              | InvocationTargetException | NoSuchMethodException | SecurityException e) {
+            throw new InvalidStateException(e);
+          }
+        }
+      }
+      if (reactionWithLayout.getReactants().size()>1 && reactionWithLayout.getProducts().size()>0) {
+        PolylineData line = new PolylineData();
+        Point2D p1 = reactionWithLayout.getReactants().get(0).getLine().getEndPoint();
+        Point2D p2 = reactionWithLayout.getProducts().get(0).getLine().getBeginPoint();
+        Point2D center = new Point2D.Double((p1.getX()+p2.getX())/2, (p1.getY()+p2.getY())/2);
+        line.addPoint(p1);
+        line.addPoint(center);
+        NodeOperator operator = new AndOperator();
+        operator.addInputs(reactionWithLayout.getReactants());
+        operator.setLine(line);
+        reactionWithLayout.addNode(operator);
       }
+      if (reactionWithLayout.getReactants().size()>0 && reactionWithLayout.getProducts().size()>1) {
+        PolylineData line = new PolylineData();
+        Point2D p1 = reactionWithLayout.getReactants().get(0).getLine().getEndPoint();
+        Point2D p2 = reactionWithLayout.getProducts().get(0).getLine().getBeginPoint();
+        Point2D center = new Point2D.Double((p1.getX()+p2.getX())/2, (p1.getY()+p2.getY())/2);
+        line.addPoint(p2);
+        line.addPoint(center);
+        NodeOperator operator = new SplitOperator();
+        operator.addOutputs(reactionWithLayout.getProducts());
+        operator.setLine(line);
+        reactionWithLayout.addNode(operator);
+      }
+      
+      logger.debug(glyph.getCurve().getListOfCurveSegments().get(0));
       try {
         minervaModel.addReaction(new StateTransitionReaction(reactionWithLayout));
       } catch (InvalidArgumentException e) {
         throw new InvalidInputDataExecption(e);
       }
     }
+    Set<Reaction> elementsToRemove = new HashSet<>();
     for (Reaction reaction : elements) {
       if (!used.contains(reaction)) {
         logger.warn("Layout doesn't contain information about Element: " + reaction.getIdReaction());
       } else {
-        minervaModel.removeReaction(reaction);
+        elementsToRemove.add(reaction);
       }
     }
+    for (Reaction reaction : elementsToRemove) {
+      minervaModel.removeReaction(reaction);
+    }
   }
 
   protected Reaction parse(org.sbml.jsbml.Reaction sbmlReaction, Model sbmlModel) throws InvalidInputDataExecption {
@@ -144,7 +243,7 @@ public class SbmlReactionParser {
 
     for (ModifierSpeciesReference modifier : sbmlReaction.getListOfModifiers()) {
       Species element = minervaModel.getElementByElementId(modifier.getSpecies());
-      reaction.addModifier(new Catalysis(element));
+      reaction.addModifier(new Modifier(element));
     }
 
     return reaction;
diff --git a/converter-sbml/src/test/java/lcsb/mapviewer/converter/model/sbml/SbmlParserTest.java b/converter-sbml/src/test/java/lcsb/mapviewer/converter/model/sbml/SbmlParserTest.java
index 6673591d17..260e80486d 100644
--- a/converter-sbml/src/test/java/lcsb/mapviewer/converter/model/sbml/SbmlParserTest.java
+++ b/converter-sbml/src/test/java/lcsb/mapviewer/converter/model/sbml/SbmlParserTest.java
@@ -5,7 +5,9 @@ import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
+import java.awt.Desktop;
 import java.awt.Point;
+import java.io.File;
 import java.io.FileNotFoundException;
 
 import org.apache.log4j.Logger;
@@ -13,6 +15,9 @@ import org.junit.Test;
 
 import lcsb.mapviewer.converter.ConverterParams;
 import lcsb.mapviewer.converter.InvalidInputDataExecption;
+import lcsb.mapviewer.converter.graphics.AbstractImageGenerator;
+import lcsb.mapviewer.converter.graphics.NormalImageGenerator;
+import lcsb.mapviewer.converter.graphics.PngImageGenerator;
 import lcsb.mapviewer.model.map.compartment.Compartment;
 import lcsb.mapviewer.model.map.model.Model;
 import lcsb.mapviewer.model.map.reaction.Reaction;
@@ -94,7 +99,7 @@ public class SbmlParserTest {
   }
 
   @Test
-  public void testParseReaction() throws FileNotFoundException, InvalidInputDataExecption {
+  public void testParseReaction() throws Exception {
     Model model = parser.createModel(new ConverterParams().filename("testFiles/layoutExample/Complete_Example.xml"));
     assertNotNull(model);
     assertEquals(1, model.getReactions().size());
@@ -103,6 +108,14 @@ public class SbmlParserTest {
       assertNotNull(node.getLine());
       assertTrue(node.getLine().length() > 0);
     }
+//    assertEquals(2, reaction.getOperators().size());
+
+    AbstractImageGenerator.Params params = new AbstractImageGenerator.Params().height(model.getHeight())
+        .width(model.getWidth()).nested(true).scale(1).level(20).x(0).y(0).model(model);
+    NormalImageGenerator nig = new PngImageGenerator(params);
+    nig.saveToFile("tmp.png");
+    Desktop.getDesktop().open(new File("tmp.png"));
+
   }
 
 }
-- 
GitLab