From 994a828eccd5b53c981cf9206d79ca452d186fa2 Mon Sep 17 00:00:00 2001
From: Piotr Gawron <piotr.gawron@uni.lu>
Date: Thu, 12 Jul 2018 11:26:17 +0200
Subject: [PATCH] BindingRegion data model

---
 .../species/ProteinXmlParser.java             | 100 +++++++++++++++++-
 .../CellDesignerModificationResidue.java      |  29 +++++
 .../structure/fields/ModificationType.java    |   1 +
 .../CellDesignerXmlParserTest.java            |  29 +++++
 .../testFiles/gene_modifications.xml          |  94 ++++++++++++++++
 .../testFiles/protein_with_binding_region.xml |  90 ++++++++++++++++
 .../field/AbstractRegionModification.java     |  23 +++-
 .../map/species/field/BindingRegion.java      |  73 +++++++++++++
 .../model/map/species/field/CodingRegion.java |   1 -
 .../src/db/12.1.0~alpha.0/fix_db_20180712.sql |   3 +
 .../resources/applicationContext-persist.xml  |   1 +
 11 files changed, 436 insertions(+), 8 deletions(-)
 create mode 100644 converter-CellDesigner/testFiles/gene_modifications.xml
 create mode 100644 converter-CellDesigner/testFiles/protein_with_binding_region.xml
 create mode 100644 model/src/main/java/lcsb/mapviewer/model/map/species/field/BindingRegion.java
 create mode 100644 persist/src/db/12.1.0~alpha.0/fix_db_20180712.sql

diff --git a/converter-CellDesigner/src/main/java/lcsb/mapviewer/converter/model/celldesigner/species/ProteinXmlParser.java b/converter-CellDesigner/src/main/java/lcsb/mapviewer/converter/model/celldesigner/species/ProteinXmlParser.java
index 3db9f9e7fa..4f1e6d4cdc 100644
--- a/converter-CellDesigner/src/main/java/lcsb/mapviewer/converter/model/celldesigner/species/ProteinXmlParser.java
+++ b/converter-CellDesigner/src/main/java/lcsb/mapviewer/converter/model/celldesigner/species/ProteinXmlParser.java
@@ -1,5 +1,8 @@
 package lcsb.mapviewer.converter.model.celldesigner.species;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import org.apache.log4j.Logger;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
@@ -14,7 +17,9 @@ import lcsb.mapviewer.converter.model.celldesigner.structure.CellDesignerProtein
 import lcsb.mapviewer.converter.model.celldesigner.structure.fields.CellDesignerModificationResidue;
 import lcsb.mapviewer.converter.model.celldesigner.structure.fields.ModificationType;
 import lcsb.mapviewer.model.map.species.Protein;
+import lcsb.mapviewer.model.map.species.field.BindingRegion;
 import lcsb.mapviewer.model.map.species.field.ModificationResidue;
+import lcsb.mapviewer.model.map.species.field.Residue;
 
 /**
  * Class that performs parsing of the CellDesigner xml for
@@ -80,6 +85,19 @@ public class ProteinXmlParser extends AbstractElementXmlParser<CellDesignerProte
               }
             }
           }
+        } else if (node.getNodeName().equals("celldesigner:listOfBindingRegions")) {
+          NodeList residueList = node.getChildNodes();
+          for (int j = 0; j < residueList.getLength(); j++) {
+            Node residueNode = residueList.item(j);
+            if (residueNode.getNodeType() == Node.ELEMENT_NODE) {
+              if (residueNode.getNodeName().equalsIgnoreCase("celldesigner:bindingRegion")) {
+                protein.addModificationResidue(getBindingRegion(residueNode));
+              } else {
+                throw new InvalidXmlSchemaException(
+                    "Unknown element of celldesigner:listOfModificationResidues " + residueNode.getNodeName());
+              }
+            }
+          }
         } else if (node.getNodeName().equals("celldesigner:notes")) {
           protein.setNotes(getRap().getNotes(node));
         } else {
@@ -108,13 +126,32 @@ public class ProteinXmlParser extends AbstractElementXmlParser<CellDesignerProte
     }
     attributes += " type=\"" + type + "\"";
     result += "<celldesigner:protein" + attributes + ">\n";
-    if (protein.getModificationResidues().size() > 0) {
+
+    List<Residue> residues = new ArrayList<>();
+    List<BindingRegion> bindingRegions = new ArrayList<>();
+    for (ModificationResidue mr : protein.getModificationResidues()) {
+      if (mr instanceof Residue) {
+        residues.add((Residue) mr);
+      } else if (mr instanceof BindingRegion) {
+        bindingRegions.add((BindingRegion) mr);
+      } else {
+        throw new InvalidArgumentException("Don't know how to handle: " + mr.getClass());
+      }
+    }
+    if (residues.size() > 0) {
       result += "<celldesigner:listOfModificationResidues>";
-      for (ModificationResidue mr : protein.getModificationResidues()) {
+      for (Residue mr : residues) {
         result += toXml(mr);
       }
       result += "</celldesigner:listOfModificationResidues>\n";
     }
+    if (bindingRegions.size() > 0) {
+      result += "<celldesigner:listOfBindingRegions>";
+      for (BindingRegion mr : bindingRegions) {
+        result += toXml(mr);
+      }
+      result += "</celldesigner:listOfBindingRegions>\n";
+    }
     // ignore notes - all notes will be stored in species
     // result +=
     // "<celldesigner:notes>"+protein.getNotes()+"</celldesigner:notes>";
@@ -123,13 +160,13 @@ public class ProteinXmlParser extends AbstractElementXmlParser<CellDesignerProte
   }
 
   /**
-   * Generates CellDesigner xml for {@link CellDesignerModificationResidue}.
+   * Generates CellDesigner xml for {@link Residue}.
    * 
    * @param mr
    *          object to transform into xml
-   * @return CellDesigner xml for {@link CellDesignerModificationResidue}
+   * @return CellDesigner xml for {@link Residue}
    */
-  private String toXml(ModificationResidue mr) {
+  private String toXml(Residue mr) {
     CellDesignerAliasConverter converter = new CellDesignerAliasConverter(mr.getSpecies(), false);
 
     String result = "";
@@ -147,6 +184,32 @@ public class ProteinXmlParser extends AbstractElementXmlParser<CellDesignerProte
     return result;
   }
 
+  /**
+   * Generates CellDesigner xml for {@link BindingRegion}.
+   * 
+   * @param mr
+   *          object to transform into xml
+   * @return CellDesigner xml for {@link BindingRegion}
+   */
+  private String toXml(BindingRegion mr) {
+
+    CellDesignerModificationResidue cellDesignerModificationResidue = new CellDesignerModificationResidue(mr);
+    String result = "";
+    String attributes = "";
+    if (!mr.getIdModificationResidue().equals("")) {
+      attributes += " id=\"" + mr.getIdModificationResidue() + "\"";
+    }
+    if (!mr.getName().equals("")) {
+      attributes += " name=\"" + escapeXml(mr.getName()) + "\"";
+    }
+    attributes += " angle=\"" + cellDesignerModificationResidue.getAngle() + "\"";
+    attributes += " size=\"" + cellDesignerModificationResidue.getSize() + "\"";
+    result += "<celldesigner:bindingRegion " + attributes + ">";
+    result += "</celldesigner:bindingRegion>";
+
+    return result;
+  }
+
   /**
    * Parses CellDesigner xml node for ModificationResidue.
    * 
@@ -174,4 +237,31 @@ public class ProteinXmlParser extends AbstractElementXmlParser<CellDesignerProte
     return residue;
   }
 
+  /**
+   * Parses CellDesigner xml node for ModificationResidue.
+   * 
+   * @param residueNode
+   *          xml node to parse
+   * @return {@link CellDesignerModificationResidue} object created from the node
+   * @throws InvalidXmlSchemaException
+   *           thrown when input xml node doesn't follow defined schema
+   */
+  private CellDesignerModificationResidue getBindingRegion(Node residueNode) throws InvalidXmlSchemaException {
+    CellDesignerModificationResidue residue = new CellDesignerModificationResidue();
+    residue.setIdModificationResidue(getNodeAttr("id", residueNode));
+    residue.setName(getNodeAttr("name", residueNode));
+    residue.setSize(getNodeAttr("size", residueNode));
+    residue.setAngle(getNodeAttr("angle", residueNode));
+    residue.setModificationType(ModificationType.BINDING_REGION);
+    NodeList list = residueNode.getChildNodes();
+    for (int i = 0; i < list.getLength(); i++) {
+      Node node = list.item(i);
+      if (node.getNodeType() == Node.ELEMENT_NODE) {
+        throw new InvalidXmlSchemaException(
+            "Unknown element of celldesigner:modificationResidue " + node.getNodeName());
+      }
+    }
+    return residue;
+  }
+
 }
diff --git a/converter-CellDesigner/src/main/java/lcsb/mapviewer/converter/model/celldesigner/structure/fields/CellDesignerModificationResidue.java b/converter-CellDesigner/src/main/java/lcsb/mapviewer/converter/model/celldesigner/structure/fields/CellDesignerModificationResidue.java
index b0db18cfe3..96a93eeaca 100644
--- a/converter-CellDesigner/src/main/java/lcsb/mapviewer/converter/model/celldesigner/structure/fields/CellDesignerModificationResidue.java
+++ b/converter-CellDesigner/src/main/java/lcsb/mapviewer/converter/model/celldesigner/structure/fields/CellDesignerModificationResidue.java
@@ -4,11 +4,13 @@ import java.io.Serializable;
 
 import org.apache.log4j.Logger;
 
+import lcsb.mapviewer.common.Configuration;
 import lcsb.mapviewer.common.exception.InvalidArgumentException;
 import lcsb.mapviewer.common.exception.NotImplementedException;
 import lcsb.mapviewer.converter.model.celldesigner.geometry.CellDesignerAliasConverter;
 import lcsb.mapviewer.converter.model.celldesigner.structure.CellDesignerSpecies;
 import lcsb.mapviewer.model.map.species.Element;
+import lcsb.mapviewer.model.map.species.field.BindingRegion;
 import lcsb.mapviewer.model.map.species.field.CodingRegion;
 import lcsb.mapviewer.model.map.species.field.ModificationResidue;
 import lcsb.mapviewer.model.map.species.field.ModificationSite;
@@ -123,6 +125,16 @@ public class CellDesignerModificationResidue implements Serializable {
     } else if (mr instanceof ProteinBindingDomain) {
       this.size = ((CodingRegion) mr).getWidth() / mr.getSpecies().getWidth();
       this.modificationType = ModificationType.PROTEIN_BINDING_DOMAIN;
+    } else if (mr instanceof BindingRegion) {
+      this.modificationType = ModificationType.BINDING_REGION;
+      if (Math.abs(mr.getPosition().getX() - mr.getSpecies().getX()) < Configuration.EPSILON) {
+        this.size = ((BindingRegion) mr).getHeight() / mr.getSpecies().getHeight();
+      } else if (Math.abs(mr.getPosition().getX() - mr.getSpecies().getX() - mr.getSpecies().getWidth()) < Configuration.EPSILON) {
+        this.size = ((BindingRegion) mr).getHeight() / mr.getSpecies().getHeight();
+      } else {
+        this.size = ((BindingRegion) mr).getWidth() / mr.getSpecies().getWidth();
+      }
+      
     } else {
       throw new InvalidArgumentException("Unknown modification type: " + mr.getClass());
     }
@@ -357,6 +369,8 @@ public class CellDesignerModificationResidue implements Serializable {
       throw new InvalidArgumentException("No type information for modification: " + idModificationResidue);
     } else if (modificationType.equals(ModificationType.RESIDUE)) {
       return createResidue(element, converter);
+    } else if (modificationType.equals(ModificationType.BINDING_REGION)) {
+      return createBindingRegion(element, converter);
     } else if (modificationType.equals(ModificationType.MODIFICATION_SITE)) {
       return createModificationSite(element, converter);
     } else if (modificationType.equals(ModificationType.CODING_REGION)) {
@@ -378,6 +392,21 @@ public class CellDesignerModificationResidue implements Serializable {
     return result;
   }
 
+  private BindingRegion createBindingRegion(Element element, CellDesignerAliasConverter converter) {
+    BindingRegion result = new BindingRegion();
+    result.setIdModificationResidue(idModificationResidue);
+    result.setName(name);
+    result.setPosition(converter.getResidueCoordinates(element, angle));
+    if (Math.abs(result.getPosition().getX() - element.getX()) < Configuration.EPSILON) {
+      result.setHeight(element.getHeight() * size);
+    } else if (Math.abs(result.getPosition().getX() - element.getX() - element.getWidth()) < Configuration.EPSILON) {
+      result.setHeight(element.getHeight() * size);
+    } else {
+      result.setWidth(element.getWidth() * size);
+    }
+    return result;
+  }
+
   private CodingRegion createCodingRegion(Element element, CellDesignerAliasConverter converter) {
     CodingRegion result = new CodingRegion();
     result.setWidth(element.getWidth() * size);
diff --git a/converter-CellDesigner/src/main/java/lcsb/mapviewer/converter/model/celldesigner/structure/fields/ModificationType.java b/converter-CellDesigner/src/main/java/lcsb/mapviewer/converter/model/celldesigner/structure/fields/ModificationType.java
index 28733f0632..73220c2ffa 100644
--- a/converter-CellDesigner/src/main/java/lcsb/mapviewer/converter/model/celldesigner/structure/fields/ModificationType.java
+++ b/converter-CellDesigner/src/main/java/lcsb/mapviewer/converter/model/celldesigner/structure/fields/ModificationType.java
@@ -3,6 +3,7 @@ package lcsb.mapviewer.converter.model.celldesigner.structure.fields;
 import lcsb.mapviewer.common.exception.InvalidArgumentException;
 
 public enum ModificationType {
+  BINDING_REGION(null), //
   CODING_REGION("CodingRegion"), //
   PROTEIN_BINDING_DOMAIN("proteinBindingDomain"), //
   RESIDUE(null), //
diff --git a/converter-CellDesigner/src/test/java/lcsb/mapviewer/converter/model/celldesigner/CellDesignerXmlParserTest.java b/converter-CellDesigner/src/test/java/lcsb/mapviewer/converter/model/celldesigner/CellDesignerXmlParserTest.java
index 362268ede5..102960dae0 100644
--- a/converter-CellDesigner/src/test/java/lcsb/mapviewer/converter/model/celldesigner/CellDesignerXmlParserTest.java
+++ b/converter-CellDesigner/src/test/java/lcsb/mapviewer/converter/model/celldesigner/CellDesignerXmlParserTest.java
@@ -47,8 +47,11 @@ import lcsb.mapviewer.model.map.reaction.type.StateTransitionReaction;
 import lcsb.mapviewer.model.map.species.Element;
 import lcsb.mapviewer.model.map.species.Gene;
 import lcsb.mapviewer.model.map.species.GenericProtein;
+import lcsb.mapviewer.model.map.species.Protein;
 import lcsb.mapviewer.model.map.species.SimpleMolecule;
 import lcsb.mapviewer.model.map.species.Species;
+import lcsb.mapviewer.model.map.species.field.BindingRegion;
+import lcsb.mapviewer.model.map.species.field.ModificationResidue;
 
 public class CellDesignerXmlParserTest extends CellDesignerTestFunctions {
   Logger logger = Logger.getLogger(CellDesignerXmlParserTest.class);
@@ -1000,4 +1003,30 @@ public class CellDesignerXmlParserTest extends CellDesignerTestFunctions {
     }
   }
 
+  @Test
+  public void testBindingRegion() throws Exception {
+    try {
+      CellDesignerXmlParser parser = new CellDesignerXmlParser();
+      Model model = parser.createModel(new ConverterParams().filename("testFiles/protein_with_binding_region.xml"));
+      Protein protein = model.getElementByElementId("sa1");
+      assertEquals(1, protein.getModificationResidues().size());
+      ModificationResidue residue = protein.getModificationResidues().get(0);
+      assertTrue(residue instanceof BindingRegion);
+      BindingRegion bindingRegion = (BindingRegion) residue;
+      assertEquals(bindingRegion.getPosition().getX(), protein.getX(), Configuration.EPSILON);
+      assertTrue(bindingRegion.getWidth() < bindingRegion.getHeight());
+
+      String xml = parser.toXml(model);
+      InputStream is = new ByteArrayInputStream(xml.getBytes("UTF-8"));
+      Model model2 = parser.createModel(new ConverterParams().inputStream(is));
+      
+      model.setName(null);
+      ModelComparator comparator = new ModelComparator();
+      assertEquals(0, comparator.compare(model, model2));
+    } catch (Exception e) {
+      e.printStackTrace();
+      throw e;
+    }
+  }
+
 }
diff --git a/converter-CellDesigner/testFiles/gene_modifications.xml b/converter-CellDesigner/testFiles/gene_modifications.xml
new file mode 100644
index 0000000000..0d9d681ce5
--- /dev/null
+++ b/converter-CellDesigner/testFiles/gene_modifications.xml
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<sbml xmlns="http://www.sbml.org/sbml/level2/version4" xmlns:celldesigner="http://www.sbml.org/2001/ns/celldesigner" level="2" version="4">
+<model metaid="untitled" id="untitled">
+<annotation>
+<celldesigner:extension>
+<celldesigner:modelVersion>4.0</celldesigner:modelVersion>
+<celldesigner:modelDisplay sizeX="600" sizeY="400"/>
+<celldesigner:listOfCompartmentAliases/>
+<celldesigner:listOfComplexSpeciesAliases/>
+<celldesigner:listOfSpeciesAliases>
+<celldesigner:speciesAlias id="sa2" species="s2">
+<celldesigner:activity>inactive</celldesigner:activity>
+<celldesigner:bounds x="192.0" y="114.5" w="189.0" h="42.0"/>
+<celldesigner:font size="12"/>
+<celldesigner:view state="usual"/>
+<celldesigner:usualView>
+<celldesigner:innerPosition x="0.0" y="0.0"/>
+<celldesigner:boxSize width="189.0" height="42.0"/>
+<celldesigner:singleLine width="1.0"/>
+<celldesigner:paint color="ffffff66" scheme="Color"/>
+</celldesigner:usualView>
+<celldesigner:briefView>
+<celldesigner:innerPosition x="0.0" y="0.0"/>
+<celldesigner:boxSize width="80.0" height="60.0"/>
+<celldesigner:singleLine width="0.0"/>
+<celldesigner:paint color="3fff0000" scheme="Color"/>
+</celldesigner:briefView>
+<celldesigner:info state="empty" angle="-1.5707963267948966"/>
+</celldesigner:speciesAlias>
+</celldesigner:listOfSpeciesAliases>
+<celldesigner:listOfGroups/>
+<celldesigner:listOfProteins/>
+<celldesigner:listOfGenes>
+<celldesigner:gene id="gn1" name="s2" type="GENE">
+<celldesigner:listOfRegions>
+<celldesigner:region id="tr1" name="p1" size="0.0" pos="0.3" type="Modification Site" active="false"/>
+<celldesigner:region id="tr2" name="p2" size="0.1" pos="0.41000000000000003" type="CodingRegion" active="false"/>
+<celldesigner:region id="tr3" name="p3" size="0.1" pos="0.57" type="RegulatoryRegion" active="false"/>
+<celldesigner:region id="tr4" name="p4" size="0.1" pos="0.75" type="transcriptionStartingSiteL" active="true"/>
+<celldesigner:region id="tr5" name="p5" size="0.14" pos="0.8599999999999999" type="transcriptionStartingSiteR" active="false"/>
+</celldesigner:listOfRegions>
+</celldesigner:gene>
+</celldesigner:listOfGenes>
+<celldesigner:listOfRNAs/>
+<celldesigner:listOfAntisenseRNAs/>
+<celldesigner:listOfLayers/>
+<celldesigner:listOfBlockDiagrams/>
+</celldesigner:extension>
+</annotation>
+<listOfUnitDefinitions>
+<unitDefinition metaid="substance" id="substance" name="substance">
+<listOfUnits>
+<unit metaid="CDMT00001" kind="mole"/>
+</listOfUnits>
+</unitDefinition>
+<unitDefinition metaid="volume" id="volume" name="volume">
+<listOfUnits>
+<unit metaid="CDMT00002" kind="litre"/>
+</listOfUnits>
+</unitDefinition>
+<unitDefinition metaid="area" id="area" name="area">
+<listOfUnits>
+<unit metaid="CDMT00003" kind="metre" exponent="2"/>
+</listOfUnits>
+</unitDefinition>
+<unitDefinition metaid="length" id="length" name="length">
+<listOfUnits>
+<unit metaid="CDMT00004" kind="metre"/>
+</listOfUnits>
+</unitDefinition>
+<unitDefinition metaid="time" id="time" name="time">
+<listOfUnits>
+<unit metaid="CDMT00005" kind="second"/>
+</listOfUnits>
+</unitDefinition>
+</listOfUnitDefinitions>
+<listOfCompartments>
+<compartment metaid="default" id="default" size="1" units="volume"/>
+</listOfCompartments>
+<listOfSpecies>
+<species metaid="s2" id="s2" name="s2" compartment="default" initialAmount="0">
+<annotation>
+<celldesigner:extension>
+<celldesigner:positionToCompartment>inside</celldesigner:positionToCompartment>
+<celldesigner:speciesIdentity>
+<celldesigner:class>GENE</celldesigner:class>
+<celldesigner:geneReference>gn1</celldesigner:geneReference>
+</celldesigner:speciesIdentity>
+</celldesigner:extension>
+</annotation>
+</species>
+</listOfSpecies>
+</model>
+</sbml>
diff --git a/converter-CellDesigner/testFiles/protein_with_binding_region.xml b/converter-CellDesigner/testFiles/protein_with_binding_region.xml
new file mode 100644
index 0000000000..87ded13083
--- /dev/null
+++ b/converter-CellDesigner/testFiles/protein_with_binding_region.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<sbml xmlns="http://www.sbml.org/sbml/level2/version4" xmlns:celldesigner="http://www.sbml.org/2001/ns/celldesigner" level="2" version="4">
+<model metaid="untitled" id="untitled">
+<annotation>
+<celldesigner:extension>
+<celldesigner:modelVersion>4.0</celldesigner:modelVersion>
+<celldesigner:modelDisplay sizeX="600" sizeY="400"/>
+<celldesigner:listOfCompartmentAliases/>
+<celldesigner:listOfComplexSpeciesAliases/>
+<celldesigner:listOfSpeciesAliases>
+<celldesigner:speciesAlias id="sa1" species="s1">
+<celldesigner:activity>inactive</celldesigner:activity>
+<celldesigner:bounds x="238.0" y="123.0" w="80.0" h="40.0"/>
+<celldesigner:font size="12"/>
+<celldesigner:view state="usual"/>
+<celldesigner:usualView>
+<celldesigner:innerPosition x="0.0" y="0.0"/>
+<celldesigner:boxSize width="80.0" height="40.0"/>
+<celldesigner:singleLine width="1.0"/>
+<celldesigner:paint color="ffccffcc" scheme="Color"/>
+</celldesigner:usualView>
+<celldesigner:briefView>
+<celldesigner:innerPosition x="0.0" y="0.0"/>
+<celldesigner:boxSize width="80.0" height="60.0"/>
+<celldesigner:singleLine width="0.0"/>
+<celldesigner:paint color="3fff0000" scheme="Color"/>
+</celldesigner:briefView>
+<celldesigner:info state="empty" angle="-1.5707963267948966"/>
+</celldesigner:speciesAlias>
+</celldesigner:listOfSpeciesAliases>
+<celldesigner:listOfGroups/>
+<celldesigner:listOfProteins>
+<celldesigner:protein id="pr1" name="s1" type="GENERIC">
+<celldesigner:listOfBindingRegions>
+<celldesigner:bindingRegion angle="3.141592653589793" id="rs1" name="test" size="0.42"/>
+</celldesigner:listOfBindingRegions>
+</celldesigner:protein>
+</celldesigner:listOfProteins>
+<celldesigner:listOfGenes/>
+<celldesigner:listOfRNAs/>
+<celldesigner:listOfAntisenseRNAs/>
+<celldesigner:listOfLayers/>
+<celldesigner:listOfBlockDiagrams/>
+</celldesigner:extension>
+</annotation>
+<listOfUnitDefinitions>
+<unitDefinition metaid="substance" id="substance" name="substance">
+<listOfUnits>
+<unit metaid="CDMT00001" kind="mole"/>
+</listOfUnits>
+</unitDefinition>
+<unitDefinition metaid="volume" id="volume" name="volume">
+<listOfUnits>
+<unit metaid="CDMT00002" kind="litre"/>
+</listOfUnits>
+</unitDefinition>
+<unitDefinition metaid="area" id="area" name="area">
+<listOfUnits>
+<unit metaid="CDMT00003" kind="metre" exponent="2"/>
+</listOfUnits>
+</unitDefinition>
+<unitDefinition metaid="length" id="length" name="length">
+<listOfUnits>
+<unit metaid="CDMT00004" kind="metre"/>
+</listOfUnits>
+</unitDefinition>
+<unitDefinition metaid="time" id="time" name="time">
+<listOfUnits>
+<unit metaid="CDMT00005" kind="second"/>
+</listOfUnits>
+</unitDefinition>
+</listOfUnitDefinitions>
+<listOfCompartments>
+<compartment metaid="default" id="default" size="1" units="volume"/>
+</listOfCompartments>
+<listOfSpecies>
+<species metaid="s1" id="s1" name="s1" compartment="default" initialAmount="0">
+<annotation>
+<celldesigner:extension>
+<celldesigner:positionToCompartment>inside</celldesigner:positionToCompartment>
+<celldesigner:speciesIdentity>
+<celldesigner:class>PROTEIN</celldesigner:class>
+<celldesigner:proteinReference>pr1</celldesigner:proteinReference>
+</celldesigner:speciesIdentity>
+</celldesigner:extension>
+</annotation>
+</species>
+</listOfSpecies>
+</model>
+</sbml>
diff --git a/model/src/main/java/lcsb/mapviewer/model/map/species/field/AbstractRegionModification.java b/model/src/main/java/lcsb/mapviewer/model/map/species/field/AbstractRegionModification.java
index 328407e43e..6ee21ba60c 100644
--- a/model/src/main/java/lcsb/mapviewer/model/map/species/field/AbstractRegionModification.java
+++ b/model/src/main/java/lcsb/mapviewer/model/map/species/field/AbstractRegionModification.java
@@ -28,6 +28,12 @@ public abstract class AbstractRegionModification extends ModificationResidue {
   @Column(name = "width")
   private double width = DEFAULT_SIZE;
 
+  /**
+   * Height of the region in the graphic representation.
+   */
+  @Column(name = "height")
+  private double height = DEFAULT_SIZE;
+
   public AbstractRegionModification() {
     super();
   }
@@ -35,6 +41,7 @@ public abstract class AbstractRegionModification extends ModificationResidue {
   public AbstractRegionModification(AbstractRegionModification mr) {
     super(mr);
     this.width = mr.getWidth();
+    this.height = mr.getHeight();
   }
 
   @Override
@@ -46,7 +53,8 @@ public abstract class AbstractRegionModification extends ModificationResidue {
     } else {
       position = "Point2D[" + format.format(getPosition().getX()) + "," + format.format(getPosition().getY()) + "]";
     }
-    String result = getIdModificationResidue() + "," + getName() + "," + getWidth() + "," + position;
+    String result = getIdModificationResidue() + "," + getName() + "," + getWidth() + "," + getHeight() + ","
+        + position;
     return result;
   }
 
@@ -70,9 +78,12 @@ public abstract class AbstractRegionModification extends ModificationResidue {
         && !this.getIdModificationResidue().equals(mr.getIdModificationResidue())) {
       throw new InvalidArgumentException("Cannot update from mr with different id");
     }
-    if (mr.getWidth() > 0) {
+    if (mr.getWidth() > 0 && mr.getWidth() != DEFAULT_SIZE) {
       this.setWidth(mr.getWidth());
     }
+    if (mr.getHeight() > 0 && mr.getHeight() != DEFAULT_SIZE) {
+      this.setHeight(mr.getHeight());
+    }
     if (mr.getName() != null) {
       this.setName(mr.getName());
     }
@@ -80,4 +91,12 @@ public abstract class AbstractRegionModification extends ModificationResidue {
       this.setPosition(mr.getPosition());
     }
   }
+
+  public double getHeight() {
+    return height;
+  }
+
+  public void setHeight(double height) {
+    this.height = height;
+  }
 }
\ No newline at end of file
diff --git a/model/src/main/java/lcsb/mapviewer/model/map/species/field/BindingRegion.java b/model/src/main/java/lcsb/mapviewer/model/map/species/field/BindingRegion.java
new file mode 100644
index 0000000000..f2b163b7c7
--- /dev/null
+++ b/model/src/main/java/lcsb/mapviewer/model/map/species/field/BindingRegion.java
@@ -0,0 +1,73 @@
+package lcsb.mapviewer.model.map.species.field;
+
+import java.io.Serializable;
+
+import javax.persistence.DiscriminatorValue;
+import javax.persistence.Entity;
+
+import org.apache.log4j.Logger;
+
+import lcsb.mapviewer.common.exception.NotImplementedException;
+import lcsb.mapviewer.model.map.species.AntisenseRna;
+import lcsb.mapviewer.model.map.species.Gene;
+import lcsb.mapviewer.model.map.species.Rna;
+import lcsb.mapviewer.model.map.species.Species;
+
+/**
+ * This structure contains information about Coding Region for one of the
+ * following {@link Species}:
+ * <ul>
+ * <li>{@link Rna}</li>
+ * <li>{@link AntisenseRna}</li>
+ * <li>{@link Gene}</li>
+ * </ul>
+ * 
+ * @author Piotr Gawron
+ * 
+ */
+@Entity
+@DiscriminatorValue("MODIFICATION_SITE")
+public class BindingRegion extends AbstractRegionModification implements Serializable {
+
+  /**
+   * 
+   */
+  private static final long serialVersionUID = 1L;
+
+  /**
+   * Default class logger.
+   */
+  @SuppressWarnings("unused")
+  private static Logger logger = Logger.getLogger(BindingRegion.class);
+
+  /**
+   * Default constructor.
+   */
+  public BindingRegion() {
+
+  }
+
+  /**
+   * Constructor that initialize object with the data from the parameter.
+   * 
+   * @param original
+   *          object from which we initialize data
+   */
+  public BindingRegion(BindingRegion original) {
+    super(original);
+  }
+
+  /**
+   * Creates a copy of current object.
+   * 
+   * @return copy of the object
+   */
+  public BindingRegion copy() {
+    if (this.getClass() == BindingRegion.class) {
+      return new BindingRegion(this);
+    } else {
+      throw new NotImplementedException("Method copy() should be overriden in class " + this.getClass());
+    }
+
+  }
+}
diff --git a/model/src/main/java/lcsb/mapviewer/model/map/species/field/CodingRegion.java b/model/src/main/java/lcsb/mapviewer/model/map/species/field/CodingRegion.java
index 1c15fdfaa1..0f8eac1c4b 100644
--- a/model/src/main/java/lcsb/mapviewer/model/map/species/field/CodingRegion.java
+++ b/model/src/main/java/lcsb/mapviewer/model/map/species/field/CodingRegion.java
@@ -55,7 +55,6 @@ public class CodingRegion extends AbstractRegionModification implements Serializ
    */
   public CodingRegion(CodingRegion original) {
     super(original);
-    this.setWidth(original.getWidth());
   }
 
   /**
diff --git a/persist/src/db/12.1.0~alpha.0/fix_db_20180712.sql b/persist/src/db/12.1.0~alpha.0/fix_db_20180712.sql
new file mode 100644
index 0000000000..2d1ffbe846
--- /dev/null
+++ b/persist/src/db/12.1.0~alpha.0/fix_db_20180712.sql
@@ -0,0 +1,3 @@
+-- modification residue should have height 
+alter table modification_residue_table add column height numeric(6,2);
+update modification_residue_table set height = 10.0;
diff --git a/persist/src/main/resources/applicationContext-persist.xml b/persist/src/main/resources/applicationContext-persist.xml
index 45c6df43f0..041bf72849 100644
--- a/persist/src/main/resources/applicationContext-persist.xml
+++ b/persist/src/main/resources/applicationContext-persist.xml
@@ -176,6 +176,7 @@
 				<value>lcsb.mapviewer.model.map.species.TruncatedProtein</value>
 				<value>lcsb.mapviewer.model.map.species.Unknown</value>
 
+				<value>lcsb.mapviewer.model.map.species.field.BindingRegion</value>
 				<value>lcsb.mapviewer.model.map.species.field.CodingRegion</value>
 				<value>lcsb.mapviewer.model.map.species.field.ModificationSite</value>
 				<value>lcsb.mapviewer.model.map.species.field.ProteinBindingDomain</value>
-- 
GitLab