From 97f0c33a90d2b8fe702fe6c5d8b75a11a18ed844 Mon Sep 17 00:00:00 2001 From: Piotr Gawron <piotr.gawron@uni.lu> Date: Tue, 9 Jan 2018 15:43:32 +0100 Subject: [PATCH] export of sbml reaction with few graphical representation handled --- .../model/sbml/SbmlBioEntityParser.java | 6 ++++ .../converter/model/sbml/SbmlParser.java | 5 +-- .../model/sbml/SbmlReactionExporter.java | 31 +++++++++++++++++-- .../model/sbml/SbmlReactionParser.java | 2 +- .../model/sbml/SbmlExporterTest.java | 28 +++++++++++++++++ .../layout/ApplyLayoutModelCommand.java | 19 ++++++++++-- .../layout/ApplySimpleLayoutModelCommand.java | 16 ++++++++-- .../layout/ApplyLayoutModelCommandTest.java | 4 +-- 8 files changed, 99 insertions(+), 12 deletions(-) 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 c4fcd05ea7..2a03a7bd52 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 @@ -21,6 +21,8 @@ public class SbmlBioEntityParser { protected Layout layout; protected lcsb.mapviewer.model.map.model.Model minervaModel; + private int idCounter = 0; + public SbmlBioEntityParser() { super(); } @@ -65,4 +67,8 @@ public class SbmlBioEntityParser { return notes; } + protected String getNextId() { + return (idCounter++) + ""; + } + } \ No newline at end of file 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 8014fbbc69..b72c589162 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 @@ -59,6 +59,7 @@ public class SbmlParser implements IConverter { model.setIdModel(sbmlModel.getId()); Layout layout = getSbmlLayout(sbmlModel); + boolean layoutExists = layout != null; SbmlCompartmentParser compartmentParser = new SbmlCompartmentParser(layout, model); SbmlSpeciesParser speciesParser = new SbmlSpeciesParser(layout, model); @@ -72,7 +73,7 @@ public class SbmlParser implements IConverter { model.addElements(speciesParser.parseList(sbmlModel)); model.addReactions(reactionParser.parseList(sbmlModel)); - if (layout != null) { + if (layoutExists) { if (layout.getDimensions() != null) { model.setWidth(layout.getDimensions().getWidth()); model.setHeight(layout.getDimensions().getHeight()); @@ -149,7 +150,7 @@ public class SbmlParser implements IConverter { } } try { - new ApplySimpleLayoutModelCommand(model, bioEntitesRequiringLayout).execute(); + new ApplySimpleLayoutModelCommand(model, bioEntitesRequiringLayout, true).execute(); } catch (CommandExecutionException e) { throw new InvalidInputDataExecption("Problem with generating layout", e); } 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 55b4d7cac4..82f63a0e25 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 @@ -40,7 +40,13 @@ public class SbmlReactionExporter extends SbmlBioEntityExporter<Reaction, org.sb @Override public org.sbml.jsbml.Reaction createSbmlElement(Reaction reaction) throws InconsistentModelException { - org.sbml.jsbml.Reaction result = sbmlModel.createReaction("reaction_" + (getNextId())); + String reactionId = getReactionId(reaction); + logger.debug(reactionId); + org.sbml.jsbml.Reaction result = super.sbmlElementByElementId.get(reactionId); + if (result != null) { + return result; + } + result = sbmlModel.createReaction(reactionId); for (Product product : reaction.getProducts()) { Species sbmlSymbol = speciesExporter.sbmlElementByElementId.get(product.getElement().getElementId()); SpeciesReference speciesReference = result.createProduct(sbmlSymbol); @@ -59,9 +65,30 @@ public class SbmlReactionExporter extends SbmlBioEntityExporter<Reaction, org.sb return result; } + private String getReactionId(Reaction reaction) { + int separatorIndex = reaction.getElementId().indexOf("__"); + if (separatorIndex > 0) { + return reaction.getElementId().substring(0, separatorIndex); + } + return reaction.getElementId(); + } + @Override protected AbstractReferenceGlyph createElementGlyph(String sbmlElementId, String glyphId) { - ReactionGlyph reactionGlyph = layout.createReactionGlyph(glyphId, sbmlElementId); + int separatorIndex = glyphId.indexOf("__"); + if (separatorIndex > 0) { + glyphId = glyphId.substring(separatorIndex + 2); + } + logger.debug(glyphId); + ReactionGlyph reactionGlyph; + try { + // handle case when input data cannot doesn't come from SBML parser and contains + // "__" that mess up identifier uniqueness + reactionGlyph = layout.createReactionGlyph(glyphId, sbmlElementId); + } catch (IllegalArgumentException e) { + glyphId += "_" + getNextId(); + reactionGlyph = layout.createReactionGlyph(glyphId, sbmlElementId); + } return reactionGlyph; } 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 02364cefab..fc91aa0314 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 @@ -96,7 +96,7 @@ public class SbmlReactionParser extends SbmlBioEntityParser { try { Reaction reactionWithLayout = source.copy(); // getId doesn't have to be unique, therefore we concatenate with reaction - reactionWithLayout.setIdReaction(glyph.getId() + "_" + glyph.getReaction()); + reactionWithLayout.setIdReaction(glyph.getReaction() + "__" + glyph.getId()); for (SpeciesReferenceGlyph speciesRefernceGlyph : glyph.getListOfSpeciesReferenceGlyphs()) { SpeciesGlyph speciesGlyph = layout.getSpeciesGlyph(speciesRefernceGlyph.getSpeciesGlyph()); ReactionNode minervaNode = null; 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 520b8295c0..cde6d4d78d 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 @@ -16,12 +16,14 @@ import org.junit.Test; import lcsb.mapviewer.common.Configuration; import lcsb.mapviewer.converter.ConverterParams; +import lcsb.mapviewer.converter.IConverter; 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.ModelComparator; import lcsb.mapviewer.model.map.model.ModelFullIndexed; import lcsb.mapviewer.model.map.reaction.Product; import lcsb.mapviewer.model.map.reaction.Reactant; @@ -218,4 +220,30 @@ public class SbmlExporterTest { } + @Test + public void testExportModelWithReaction() throws Exception { + IConverter converter = new SbmlParser(); + + Model model = converter.createModel(new ConverterParams().filename("testFiles/layoutExample/example1.xml")); + model.setName(null); + + converter.exportModelToFile(model, "tmp.xml"); + + Model model2 = converter.createModel(new ConverterParams().filename("tmp.xml")); + model2.setName(null); + + for (Reaction r: model.getReactions()) { + logger.debug(r.getIdReaction()); + } + logger.debug("---"); + for (Reaction r: model2.getReactions()) { + logger.debug(r.getIdReaction()); + } + + assertNotNull(model2); + ModelComparator comparator = new ModelComparator(1.0); + assertEquals(0, comparator.compare(model, model2)); + + } + } diff --git a/model-command/src/main/java/lcsb/mapviewer/commands/layout/ApplyLayoutModelCommand.java b/model-command/src/main/java/lcsb/mapviewer/commands/layout/ApplyLayoutModelCommand.java index f3c17b1e67..fe321ba070 100644 --- a/model-command/src/main/java/lcsb/mapviewer/commands/layout/ApplyLayoutModelCommand.java +++ b/model-command/src/main/java/lcsb/mapviewer/commands/layout/ApplyLayoutModelCommand.java @@ -1,6 +1,5 @@ package lcsb.mapviewer.commands.layout; -import java.awt.Dimension; import java.awt.geom.Dimension2D; import java.awt.geom.Point2D; import java.util.Collection; @@ -25,9 +24,12 @@ public abstract class ApplyLayoutModelCommand extends ModelCommand { private Double minY; private Double maxX; private Double maxY; + private boolean addReactionPrefixes; + + private int idCounter = 0; public ApplyLayoutModelCommand(Model model, Collection<BioEntity> bioEntities, Double minX, Double minY, Double maxX, - Double maxY) { + Double maxY, boolean addReactionPrefixes) { super(model); if (bioEntities == null) { bioEntities = new HashSet<>(); @@ -43,6 +45,7 @@ public abstract class ApplyLayoutModelCommand extends ModelCommand { this.setMinY(minY); this.setMaxX(maxX); this.setMaxY(maxY); + this.addReactionPrefixes = addReactionPrefixes; } protected Collection<BioEntity> getBioEntities() { @@ -101,4 +104,16 @@ public abstract class ApplyLayoutModelCommand extends ModelCommand { } } + public boolean isAddReactionPrefixes() { + return addReactionPrefixes; + } + + public void setAddReactionPrefixes(boolean addReactionPrefixes) { + this.addReactionPrefixes = addReactionPrefixes; + } + + protected String getNextId() { + return (idCounter++) + ""; + } + } diff --git a/model-command/src/main/java/lcsb/mapviewer/commands/layout/ApplySimpleLayoutModelCommand.java b/model-command/src/main/java/lcsb/mapviewer/commands/layout/ApplySimpleLayoutModelCommand.java index 041820ea04..9d89405b3b 100644 --- a/model-command/src/main/java/lcsb/mapviewer/commands/layout/ApplySimpleLayoutModelCommand.java +++ b/model-command/src/main/java/lcsb/mapviewer/commands/layout/ApplySimpleLayoutModelCommand.java @@ -50,12 +50,16 @@ public class ApplySimpleLayoutModelCommand extends ApplyLayoutModelCommand { private static final double COMPLEX_PADDING = 5; public ApplySimpleLayoutModelCommand(Model model, Collection<BioEntity> bioEntities, Double minX, Double minY, - Double maxX, Double maxY) { - super(model, bioEntities, minX, minY, maxX, maxY); + Double maxX, Double maxY, boolean addReactionPrefixes) { + super(model, bioEntities, minX, minY, maxX, maxY, addReactionPrefixes); } public ApplySimpleLayoutModelCommand(Model model, Collection<BioEntity> bioEntities) { - this(model, bioEntities, null, null, null, null); + this(model, bioEntities, null, null, null, null, false); + } + + public ApplySimpleLayoutModelCommand(Model model, Collection<BioEntity> bioEntities, boolean addReactionPrefixes) { + this(model, bioEntities, null, null, null, null, addReactionPrefixes); } public ApplySimpleLayoutModelCommand(Model model) { @@ -217,6 +221,12 @@ public class ApplySimpleLayoutModelCommand extends ApplyLayoutModelCommand { modifyProducts(reaction, middle); modifyReactants(reaction, middle); modifyModifiers(reaction, middle); + + if (super.isAddReactionPrefixes()) { + super.getModel().removeReaction(reaction); + reaction.setIdReaction("reaction_glyph_" + getNextId() + "__" + reaction.getIdReaction()); + super.getModel().addReaction(reaction); + } } private Point2D.Double getMiddlePoint(Point2D middle, Point2D productPoint) { diff --git a/model-command/src/test/java/lcsb/mapviewer/commands/layout/ApplyLayoutModelCommandTest.java b/model-command/src/test/java/lcsb/mapviewer/commands/layout/ApplyLayoutModelCommandTest.java index ab4e586288..df63c2e9c2 100644 --- a/model-command/src/test/java/lcsb/mapviewer/commands/layout/ApplyLayoutModelCommandTest.java +++ b/model-command/src/test/java/lcsb/mapviewer/commands/layout/ApplyLayoutModelCommandTest.java @@ -18,7 +18,7 @@ public class ApplyLayoutModelCommandTest { Double minX = 1.0; Double minY = 2.0; ApplyLayoutModelCommand command = new ApplySimpleLayoutModelCommand(new ModelFullIndexed(null), new ArrayList<>(), - minX, minY, null, null); + minX, minY, null, null, false); Point2D minPoint = command.getStartPoint(); assertNotNull(minPoint); @@ -31,7 +31,7 @@ public class ApplyLayoutModelCommandTest { Double maxX = 1.0; Double maxY = 2.0; ApplyLayoutModelCommand command = new ApplySimpleLayoutModelCommand(new ModelFullIndexed(null), new ArrayList<>(), - 0.0, 0.0, maxX, maxY); + 0.0, 0.0, maxX, maxY, false); Dimension2D minPoint = command.getStartDimension(); assertNotNull(minPoint); -- GitLab