From a00c1ad102dcc86e14c6f5db6dd3bd3c2b5f2c71 Mon Sep 17 00:00:00 2001 From: Piotr Gawron <piotr.gawron@uni.lu> Date: Thu, 23 Nov 2017 17:54:18 +0100 Subject: [PATCH] parsing of relation between compartment and species added --- .../model/sbml/SbmlCompartmentParser.java | 10 ++-- .../model/sbml/SbmlElementParser.java | 16 +++--- .../converter/model/sbml/SbmlParser.java | 42 ++++++++++++++-- .../model/sbml/SbmlSpeciesParser.java | 50 +++++++++++++++++-- .../model/sbml/GenericSbmlParserTest.java | 3 +- .../converter/model/sbml/SbmlParserTest.java | 48 +++++++++++++++--- 6 files changed, 143 insertions(+), 26 deletions(-) diff --git a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlCompartmentParser.java b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlCompartmentParser.java index 9e119bfbaf..2e19442c08 100644 --- a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlCompartmentParser.java +++ b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlCompartmentParser.java @@ -20,15 +20,19 @@ import lcsb.mapviewer.model.map.compartment.SquareCompartment; public class SbmlCompartmentParser extends SbmlElementParser<org.sbml.jsbml.Compartment> { Logger logger = Logger.getLogger(SbmlCompartmentParser.class); - public SbmlCompartmentParser(Layout layout) { - super(layout); + public SbmlCompartmentParser(Layout layout, lcsb.mapviewer.model.map.model.Model minervaModel) { + super(layout, minervaModel); } @Override - protected Compartment parse(org.sbml.jsbml.Compartment compartment) throws InvalidInputDataExecption { + protected Compartment parse(org.sbml.jsbml.Compartment compartment, Model sbmlModel) + throws InvalidInputDataExecption { Compartment result = new SquareCompartment(compartment.getId()); result.setMiriamData(parseAnnotation(compartment.getAnnotation())); result.setName(compartment.getName()); + if (result.getName() == null || result.getName().isEmpty()) { + result.setName(result.getElementId()); + } try { result.setNotes(compartment.getNotesString()); } catch (XMLStreamException e) { diff --git a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlElementParser.java b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlElementParser.java index 5b7c7edcb9..8530ae1a6b 100644 --- a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlElementParser.java +++ b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlElementParser.java @@ -25,17 +25,20 @@ public abstract class SbmlElementParser<T extends org.sbml.jsbml.Symbol> { Layout layout; - public SbmlElementParser(Layout layout) { - this.layout = layout; + lcsb.mapviewer.model.map.model.Model minervaModel; + + public SbmlElementParser(Layout sbmlLayout, lcsb.mapviewer.model.map.model.Model minervaModel) { + this.layout = sbmlLayout; + this.minervaModel = minervaModel; } public List<Element> parseList(Model sbmlModel) throws InvalidInputDataExecption { List<Element> result = new ArrayList<>(); for (T sbmlElement : getSbmlElementList(sbmlModel)) { - result.add(parse(sbmlElement)); + result.add(parse(sbmlElement, sbmlModel)); } if (layout != null) { - return mergeLayout(result, layout); + return mergeLayout(result, layout, sbmlModel); } else { return result; } @@ -43,7 +46,8 @@ public abstract class SbmlElementParser<T extends org.sbml.jsbml.Symbol> { protected abstract ListOf<T> getSbmlElementList(Model sbmlModel); - private List<Element> mergeLayout(List<Element> elements, Layout sbmlLayout) throws InvalidInputDataExecption { + protected List<Element> mergeLayout(List<Element> elements, Layout sbmlLayout, Model sbmlModel) + throws InvalidInputDataExecption { Set<Element> used = new HashSet<>(); Map<String, Element> elementById = new HashMap<>(); for (Element species : elements) { @@ -81,7 +85,7 @@ public abstract class SbmlElementParser<T extends org.sbml.jsbml.Symbol> { protected abstract List<Pair<String, AbstractReferenceGlyph>> getGlyphs(Layout sbmlLayout); - protected abstract Element parse(T species) throws InvalidInputDataExecption; + protected abstract Element parse(T species, Model sbmlModel) throws InvalidInputDataExecption; protected Set<MiriamData> parseAnnotation(Annotation annotation) { if (annotation.getCVTermCount() > 0) { 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 7e32722234..a14a15c80c 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 @@ -1,5 +1,6 @@ package lcsb.mapviewer.converter.model.sbml; +import java.awt.Point; import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -48,8 +49,8 @@ public class SbmlParser implements IConverter { Layout layout = getSbmlLayout(sbmlModel); - SbmlCompartmentParser compartmentParser = new SbmlCompartmentParser(layout); - SbmlSpeciesParser speciesParser = new SbmlSpeciesParser(layout); + SbmlCompartmentParser compartmentParser = new SbmlCompartmentParser(layout, model); + SbmlSpeciesParser speciesParser = new SbmlSpeciesParser(layout, model); Set<MiriamData> annotations = compartmentParser.parseAnnotation(sbmlModel.getAnnotation()); if (annotations.size() > 0) { @@ -108,6 +109,17 @@ public class SbmlParser implements IConverter { } private void createLayout(Model model, Layout layout) { + + for (Element element : model.getElements()) { + if (element.getWidth() == 0 || element.getHeight() == 0) { + element.setWidth(100); + element.setHeight(20); + Point coord = nextCoordinates(); + element.setX(coord.x * 120); + element.setX(coord.y * 30); + } + } + double width; double height; if (layout != null) { @@ -119,9 +131,6 @@ public class SbmlParser implements IConverter { double minX = Double.MAX_VALUE; double minY = Double.MAX_VALUE; for (Element element : model.getElements()) { - if (element.getWidth() == 0.0) { - throw new NotImplementedException("Element without layout not implemented"); - } width = Math.max(width, element.getX() + element.getWidth()); height = Math.max(height, element.getY() + element.getHeight()); minX = Math.min(minX, element.getX()); @@ -139,6 +148,29 @@ public class SbmlParser implements IConverter { model.setHeight(height); } + Point coordinates = null; + int radius = 0; + + protected Point nextCoordinates() { + if (coordinates == null) { + coordinates = new Point(0, 0); + } else { + if (coordinates.x == coordinates.y) { + radius++; + coordinates = new Point(radius, 0); + } else if (coordinates.x == radius) { + if (coordinates.y == radius - 1) { + coordinates = new Point(0, radius); + } else { + coordinates = new Point(coordinates.x, coordinates.y + 1); + } + } else { + coordinates = new Point(coordinates.x + 1, coordinates.y); + } + } + return coordinates; + } + private Layout getSbmlLayout(org.sbml.jsbml.Model sbmlModel) { Layout layout = null; if (sbmlModel.getExtensionCount() > 0) { diff --git a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlSpeciesParser.java b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlSpeciesParser.java index e5d5547c4d..b2cf5c6150 100644 --- a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlSpeciesParser.java +++ b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlSpeciesParser.java @@ -10,23 +10,27 @@ import org.apache.log4j.Logger; import org.sbml.jsbml.ListOf; import org.sbml.jsbml.Model; import org.sbml.jsbml.ext.layout.AbstractReferenceGlyph; +import org.sbml.jsbml.ext.layout.CompartmentGlyph; import org.sbml.jsbml.ext.layout.Layout; import org.sbml.jsbml.ext.layout.SpeciesGlyph; import lcsb.mapviewer.common.Pair; import lcsb.mapviewer.common.exception.InvalidStateException; import lcsb.mapviewer.converter.InvalidInputDataExecption; +import lcsb.mapviewer.model.map.compartment.Compartment; +import lcsb.mapviewer.model.map.species.Element; import lcsb.mapviewer.model.map.species.Species; import lcsb.mapviewer.model.map.species.Unknown; public class SbmlSpeciesParser extends SbmlElementParser<org.sbml.jsbml.Species> { Logger logger = Logger.getLogger(SbmlSpeciesParser.class); - public SbmlSpeciesParser(Layout layout) { - super(layout); + public SbmlSpeciesParser(Layout layout, lcsb.mapviewer.model.map.model.Model minervaModel) { + super(layout, minervaModel); } - protected Species parse(org.sbml.jsbml.Species species) throws InvalidInputDataExecption { + @Override + protected Species parse(org.sbml.jsbml.Species species, Model sbmlModel) throws InvalidInputDataExecption { String type = species.getSpeciesType(); Class<? extends Species> clazz = null; if (type == null || type.isEmpty()) { @@ -40,6 +44,9 @@ public class SbmlSpeciesParser extends SbmlElementParser<org.sbml.jsbml.Species> result = clazz.getConstructor(String.class).newInstance(species.getId()); result.setMiriamData(parseAnnotation(species.getAnnotation())); result.setName(species.getName()); + if (result.getName() == null || result.getName().isEmpty()) { + result.setName(result.getElementId()); + } try { result.setNotes(species.getNotesString()); } catch (XMLStreamException e) { @@ -52,6 +59,43 @@ public class SbmlSpeciesParser extends SbmlElementParser<org.sbml.jsbml.Species> } } + @Override + protected List<Element> mergeLayout(List<Element> elements, Layout sbmlLayout, Model sbmlModel) throws InvalidInputDataExecption { + List<Element> result = super.mergeLayout(elements, sbmlLayout, sbmlModel); + + for (Element element : result) { + String compartmentId = null; + if (sbmlLayout.getSpeciesGlyph(element.getElementId())!=null) { + compartmentId = ((org.sbml.jsbml.Species)sbmlLayout.getSpeciesGlyph(element.getElementId()).getSpeciesInstance()).getCompartment(); + } else { + compartmentId = sbmlModel.getSpecies(element.getElementId()).getCompartment(); + } + assignCompartment(element, compartmentId); + } + return result; + } + + private void assignCompartment(Element element, String compartmentId) { + Compartment compartment = minervaModel.getElementByElementId(compartmentId); + if (compartment == null) { + List<Compartment> compartments = new ArrayList<>(); + for (CompartmentGlyph glyph : layout.getListOfCompartmentGlyphs()) { + if (glyph.getCompartment().equals(compartmentId)) { + compartments.add(minervaModel.getElementByElementId(glyph.getId())); + } + } + for (Compartment compartment2 : compartments) { + if (compartment2.contains(element)) { + compartment = compartment2; + } + } + } + if (compartment != null) { + compartment.addElement(element); + } + + } + @Override protected ListOf<org.sbml.jsbml.Species> getSbmlElementList(Model sbmlModel) { return sbmlModel.getListOfSpecies(); diff --git a/converter-sbml/src/test/java/lcsb/mapviewer/converter/model/sbml/GenericSbmlParserTest.java b/converter-sbml/src/test/java/lcsb/mapviewer/converter/model/sbml/GenericSbmlParserTest.java index d28517873a..252a952df8 100644 --- a/converter-sbml/src/test/java/lcsb/mapviewer/converter/model/sbml/GenericSbmlParserTest.java +++ b/converter-sbml/src/test/java/lcsb/mapviewer/converter/model/sbml/GenericSbmlParserTest.java @@ -27,8 +27,6 @@ import lcsb.mapviewer.converter.graphics.AbstractImageGenerator; import lcsb.mapviewer.converter.graphics.NormalImageGenerator; import lcsb.mapviewer.converter.graphics.PngImageGenerator; import lcsb.mapviewer.converter.model.celldesigner.CellDesignerXmlParser; -import lcsb.mapviewer.model.map.compartment.Compartment; -import lcsb.mapviewer.model.map.compartment.SquareCompartment; import lcsb.mapviewer.model.map.model.Model; import lcsb.mapviewer.model.map.model.ModelComparator; @@ -63,6 +61,7 @@ public class GenericSbmlParserTest { Model model = converter.createModel(new ConverterParams().filename(filePath.toString())); model.setName(null); + logger.debug(model.getElements().size()); // Create and display image of parsed map AbstractImageGenerator.Params params = new AbstractImageGenerator.Params().height(model.getHeight()) 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 72a079086f..adef0ecf5b 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,6 +5,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import java.awt.Point; import java.io.FileNotFoundException; import org.apache.log4j.Logger; @@ -29,8 +30,8 @@ public class SbmlParserTest { Compartment compartment = model.getElementByElementId("CompartmentGlyph_1"); assertNotNull(compartment.getX()); assertNotNull(compartment.getY()); - assertTrue(compartment.getWidth()>0); - assertTrue(compartment.getHeight()>0); + assertTrue(compartment.getWidth() > 0); + assertTrue(compartment.getHeight() > 0); assertNotNull(model.getHeight()); assertNotNull(model.getWidth()); assertTrue(model.getWidth() >= compartment.getX() + compartment.getWidth()); @@ -40,15 +41,15 @@ public class SbmlParserTest { @Test public void testParseSpecies() throws FileNotFoundException, InvalidInputDataExecption { - Model model = parser.createModel( - new ConverterParams().filename("testFiles/layoutExample/SpeciesGlyph_Example_level2_level3.xml")); + Model model = parser + .createModel(new ConverterParams().filename("testFiles/layoutExample/SpeciesGlyph_Example_level2_level3.xml")); assertNotNull(model); assertEquals(1, model.getElements().size()); Species glucoseSpecies = model.getElementByElementId("SpeciesGlyph_Glucose"); assertNotNull(glucoseSpecies.getX()); assertNotNull(glucoseSpecies.getY()); - assertTrue(glucoseSpecies.getWidth()>0); - assertTrue(glucoseSpecies.getHeight()>0); + assertTrue(glucoseSpecies.getWidth() > 0); + assertTrue(glucoseSpecies.getHeight() > 0); assertNotNull(model.getHeight()); assertNotNull(model.getWidth()); assertTrue(model.getWidth() >= glucoseSpecies.getX() + glucoseSpecies.getWidth()); @@ -56,5 +57,38 @@ public class SbmlParserTest { assertFalse(glucoseSpecies.getClass().equals(Species.class)); } - + @Test + public void testParseSpeciesInCompartments() throws FileNotFoundException, InvalidInputDataExecption { + Model model = parser + .createModel(new ConverterParams().filename("testFiles/layoutExample/SpeciesGlyph_Example.xml")); + assertNotNull(model); + assertEquals(2, model.getElements().size()); + Compartment compartment = model.getElementByElementId("Yeast"); + assertNotNull(compartment.getX()); + assertNotNull(compartment.getY()); + assertTrue(compartment.getWidth() > 0); + assertTrue(compartment.getHeight() > 0); + assertNotNull(model.getHeight()); + assertNotNull(model.getWidth()); + assertTrue(model.getWidth() >= compartment.getX() + compartment.getWidth()); + assertTrue(model.getHeight() >= compartment.getY() + compartment.getHeight()); + assertFalse(compartment.getClass().equals(Compartment.class)); + assertTrue(compartment.getElements().size() > 0); + } + + @Test + public void testNextCoordinates() throws FileNotFoundException, InvalidInputDataExecption { + parser = new SbmlParser(); + assertEquals(new Point(0, 0), parser.nextCoordinates()); + assertEquals(new Point(1, 0), parser.nextCoordinates()); + assertEquals(new Point(0, 1), parser.nextCoordinates()); + assertEquals(new Point(1, 1), parser.nextCoordinates()); + assertEquals(new Point(2, 0), parser.nextCoordinates()); + assertEquals(new Point(2, 1), parser.nextCoordinates()); + assertEquals(new Point(0, 2), parser.nextCoordinates()); + assertEquals(new Point(1, 2), parser.nextCoordinates()); + assertEquals(new Point(2, 2), parser.nextCoordinates()); + assertEquals(new Point(3, 0), parser.nextCoordinates()); + + } } -- GitLab