From abd318d18c02ff9da2efb24080d945d69813fe99 Mon Sep 17 00:00:00 2001
From: Piotr Gawron <piotr.gawron@uni.lu>
Date: Fri, 2 Feb 2018 11:16:53 +0100
Subject: [PATCH] import of sbml reaction kinetics added

---
 converter-sbml/.gitignore                     |  1 +
 .../model/sbml/SbmlBioEntityParser.java       |  3 +-
 .../converter/model/sbml/SbmlParser.java      |  3 --
 .../model/sbml/SbmlReactionParser.java        | 53 +++++++++++++++++--
 .../converter/model/sbml/SbmlParserTest.java  | 19 +++++++
 5 files changed, 71 insertions(+), 8 deletions(-)

diff --git a/converter-sbml/.gitignore b/converter-sbml/.gitignore
index 7bca1630c9..3ef28bc255 100644
--- a/converter-sbml/.gitignore
+++ b/converter-sbml/.gitignore
@@ -1,2 +1,3 @@
 /bin/
 tmp.png
+tmp.xml
diff --git a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlBioEntityParser.java b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlBioEntityParser.java
index 2a03a7bd52..fc53759d70 100644
--- a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlBioEntityParser.java
+++ b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlBioEntityParser.java
@@ -11,11 +11,12 @@ import org.sbml.jsbml.Annotation;
 import org.sbml.jsbml.ext.layout.Layout;
 import org.sbml.jsbml.util.NotImplementedException;
 
+import lcsb.mapviewer.common.XmlParser;
 import lcsb.mapviewer.converter.InvalidInputDataExecption;
 import lcsb.mapviewer.model.map.BioEntity;
 import lcsb.mapviewer.model.map.MiriamData;
 
-public class SbmlBioEntityParser {
+public class SbmlBioEntityParser extends XmlParser{
   Logger logger = Logger.getLogger(SbmlBioEntityParser.class);
 
   protected Layout layout;
diff --git a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlParser.java b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlParser.java
index 32a2964d99..7cbaa961dc 100644
--- a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlParser.java
+++ b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlParser.java
@@ -106,9 +106,6 @@ public class SbmlParser implements IConverter {
       if (sbmlModel.getInitialAssignmentCount() > 0) {
         throw new NotImplementedException("InitialAssignment not implemented for model");
       }
-      if (sbmlModel.getKineticLawCount() > 0) {
-        throw new NotImplementedException("KineticLaw not implemented for model");
-      }
       if (sbmlModel.getParameterCount() > 0) {
         throw new NotImplementedException("Parameter not implemented for model");
       }
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 fc91aa0314..0f91b7a80c 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
@@ -11,8 +11,9 @@ import java.util.Map;
 import java.util.Set;
 
 import org.apache.log4j.Logger;
-import org.sbml.jsbml.Annotation;
+import org.sbml.jsbml.KineticLaw;
 import org.sbml.jsbml.ListOf;
+import org.sbml.jsbml.LocalParameter;
 import org.sbml.jsbml.Model;
 import org.sbml.jsbml.ModifierSpeciesReference;
 import org.sbml.jsbml.SpeciesReference;
@@ -21,16 +22,19 @@ import org.sbml.jsbml.ext.layout.Layout;
 import org.sbml.jsbml.ext.layout.ReactionGlyph;
 import org.sbml.jsbml.ext.layout.SpeciesGlyph;
 import org.sbml.jsbml.ext.layout.SpeciesReferenceGlyph;
-import org.sbml.jsbml.util.NotImplementedException;
+import org.w3c.dom.Node;
 
 import lcsb.mapviewer.common.exception.InvalidArgumentException;
 import lcsb.mapviewer.common.exception.InvalidStateException;
+import lcsb.mapviewer.common.exception.InvalidXmlSchemaException;
 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.kinetics.SbmlArgument;
+import lcsb.mapviewer.model.map.kinetics.SbmlKinetics;
+import lcsb.mapviewer.model.map.kinetics.SbmlParameter;
 import lcsb.mapviewer.model.map.modifier.Inhibition;
 import lcsb.mapviewer.model.map.modifier.Modulation;
 import lcsb.mapviewer.model.map.modifier.Trigger;
@@ -248,7 +252,7 @@ public class SbmlReactionParser extends SbmlBioEntityParser {
     reaction.setIdReaction(sbmlReaction.getId());
     reaction.setReversible(sbmlReaction.isReversible());
     if (sbmlReaction.getKineticLaw() != null) {
-      throw new NotImplementedException("KineticLaw not implemented");
+      reaction.setKinetics(createMinervaKinetics(sbmlReaction.getKineticLaw()));
     }
     for (SpeciesReference reactant : sbmlReaction.getListOfReactants()) {
       Species element = minervaModel.getElementByElementId(reactant.getSpecies());
@@ -267,6 +271,47 @@ public class SbmlReactionParser extends SbmlBioEntityParser {
     return reaction;
   }
 
+  private SbmlKinetics createMinervaKinetics(KineticLaw kineticLaw) throws InvalidInputDataExecption {
+    SbmlKinetics result = new SbmlKinetics();
+    result.setDefinition(kineticLaw.getMath().toMathML());
+    for (LocalParameter parameter : kineticLaw.getListOfLocalParameters()) {
+      SbmlParameter minervaParameter = new SbmlParameter(parameter.getId());
+      minervaParameter.setName(parameter.getName());
+      minervaParameter.setValue(parameter.getValue());
+      minervaParameter.setUnits(minervaModel.getUnitsByUnitId(parameter.getUnits()));
+      result.addParameter(minervaParameter);
+    }
+
+    try {
+      Node node = super.getXmlDocumentFromString(result.getDefinition());
+      Set<SbmlArgument> elementsUsedInKinetics = new HashSet<>();
+      for (Node ciNode : super.getAllNotNecessirellyDirectChild("ci", node)) {
+        String id = super.getNodeValue(ciNode).trim();
+        SbmlArgument element = minervaModel.getElementByElementId(id);
+        if (element == null) {
+          element = result.getParameterById(id);
+        }
+        if (element == null) {
+          element = minervaModel.getParameterById(id);
+        }
+        if (element == null) {
+          element = minervaModel.getFunctionById(id);
+        }
+        if (element != null) {
+          ciNode.setTextContent(element.getElementId());
+        } else {
+          throw new InvalidXmlSchemaException("Unknown symbol in kinetics: " + id);
+        }
+        elementsUsedInKinetics.add(element);
+      }
+      result.addArguments(elementsUsedInKinetics);
+    } catch (InvalidXmlSchemaException e) {
+      throw new InvalidInputDataExecption(e);
+    }
+
+    return result;
+  }
+
   public void validateReactions(Set<Reaction> reactions) throws InvalidInputDataExecption {
     for (Reaction reaction : reactions) {
       if (reaction.getReactants().size() == 0) {
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 aa8225c4f0..91893ec7d4 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
@@ -40,6 +40,25 @@ public class SbmlParserTest {
     assertFalse(compartment.getClass().equals(Compartment.class));
   }
 
+  @Test
+  public void testParseUnits() throws FileNotFoundException, InvalidInputDataExecption {
+    Model model = parser.createModel(
+        new ConverterParams().filename("testFiles/layoutExample/CompartmentGlyph_Example_level2_level3.xml"));
+    assertNotNull(model);
+    assertTrue("Units weren't parsed", model.getUnits().size() > 0);
+  }
+
+  @Test
+  public void testParseKinetics() throws FileNotFoundException, InvalidInputDataExecption {
+    Model model = parser.createModel(new ConverterParams().filename("testFiles/layoutExample/SBML.xml"));
+    for (Reaction reaction : model.getReactions()) {
+      assertNotNull("Kinetics is not parsed", reaction.getKinetics());
+      assertNotNull("No math definition for kinetic law", reaction.getKinetics().getDefinition());
+      assertTrue("There should be a kinetic parameter defined", reaction.getKinetics().getParameters().size() > 0);
+      assertTrue("Elements used by kinetics are not available", reaction.getKinetics().getElements().size() > 0);
+    }
+  }
+
   @Test
   public void testParseSpecies() throws FileNotFoundException, InvalidInputDataExecption {
     Model model = parser
-- 
GitLab