diff --git a/converter-CellDesigner/src/main/java/lcsb/mapviewer/converter/model/celldesigner/reaction/ReactionCollectionXmlParser.java b/converter-CellDesigner/src/main/java/lcsb/mapviewer/converter/model/celldesigner/reaction/ReactionCollectionXmlParser.java index 2f06de27b17abbeb88ad01bbe0543a0ba359c362..3125c6585a97b3531fc6039344a622db4fe65b23 100644 --- a/converter-CellDesigner/src/main/java/lcsb/mapviewer/converter/model/celldesigner/reaction/ReactionCollectionXmlParser.java +++ b/converter-CellDesigner/src/main/java/lcsb/mapviewer/converter/model/celldesigner/reaction/ReactionCollectionXmlParser.java @@ -9,6 +9,7 @@ import org.w3c.dom.Node; import org.w3c.dom.NodeList; import lcsb.mapviewer.common.XmlParser; +import lcsb.mapviewer.common.exception.InvalidArgumentException; import lcsb.mapviewer.common.exception.InvalidXmlSchemaException; import lcsb.mapviewer.converter.ConverterException; import lcsb.mapviewer.converter.model.celldesigner.CellDesignerElementCollection; @@ -17,6 +18,7 @@ import lcsb.mapviewer.converter.model.celldesigner.structure.CellDesignerElement import lcsb.mapviewer.model.map.InconsistentModelException; import lcsb.mapviewer.model.map.model.Model; import lcsb.mapviewer.model.map.reaction.Reaction; +import lcsb.mapviewer.modelutils.map.ElementUtils; /** * Parser used for extracting collections of reaction from CellDesigner xml. @@ -26,88 +28,92 @@ import lcsb.mapviewer.model.map.reaction.Reaction; */ public class ReactionCollectionXmlParser extends XmlParser { - /** - * Default class logger. - */ - @SuppressWarnings("unused") - private Logger logger = Logger.getLogger(ReactionCollectionXmlParser.class.getName()); + /** + * Default class logger. + */ + @SuppressWarnings("unused") + private Logger logger = Logger.getLogger(ReactionCollectionXmlParser.class.getName()); - /** - * Model for which parsing (or transformation to xml) is being done. - */ - private Model model = null; + /** + * Model for which parsing (or transformation to xml) is being done. + */ + private Model model = null; - /** - * Object used for parsing single reaction. - */ - private ReactionXmlParser xmlStructureFactory; + /** + * Object used for parsing single reaction. + */ + private ReactionXmlParser xmlStructureFactory; - /** - * Default constructor. Model is required because some nodes require access to - * other parts of the model. - * - * @param sbgn - * should sbgn standard be used - * @param elements - * collection of {@link CellDesignerElement cell designer elements} - * parsed from xml - * @param model - * model that is parsed/transformed into xml - */ - public ReactionCollectionXmlParser(Model model, CellDesignerElementCollection elements, boolean sbgn) { - this.model = model; - xmlStructureFactory = new ReactionXmlParser(elements, sbgn); - } + /** + * Default constructor. Model is required because some nodes require access to + * other parts of the model. + * + * @param sbgn + * should sbgn standard be used + * @param elements + * collection of {@link CellDesignerElement cell designer elements} + * parsed from xml + * @param model + * model that is parsed/transformed into xml + */ + public ReactionCollectionXmlParser(Model model, CellDesignerElementCollection elements, boolean sbgn) { + this.model = model; + xmlStructureFactory = new ReactionXmlParser(elements, sbgn); + } - /** - * Parse CellDesigner xml node with set of reactions into list of - * {@link Reaction}. - * - * @param reactionsNode - * xml node - * @return list of reaction taken from xml node - * @throws CellDesignerParserException - * thrown when there is a problem with xml node - * @throws InvalidXmlSchemaException - * thrown when reactionsNode is invalid xml - */ - public List<Reaction> parseXmlReactionCollection(Node reactionsNode) throws CellDesignerParserException, InvalidXmlSchemaException { - List<Reaction> result = new ArrayList<Reaction>(); - NodeList nodes = reactionsNode.getChildNodes(); - for (int x = 0; x < nodes.getLength(); x++) { - Node node = nodes.item(x); - if (node.getNodeType() == Node.ELEMENT_NODE) { - if (node.getNodeName().equalsIgnoreCase("reaction")) { - Reaction reaction = xmlStructureFactory.getReaction(node, model); - result.add(reaction); - } else { - throw new InvalidXmlSchemaException("Unknown element of model/listOfReactions: " + node.getNodeName()); - } - } - } + /** + * Parse CellDesigner xml node with set of reactions into list of + * {@link Reaction}. + * + * @param reactionsNode + * xml node + * @return list of reaction taken from xml node + * @throws CellDesignerParserException + * thrown when there is a problem with xml node + * @throws InvalidXmlSchemaException + * thrown when reactionsNode is invalid xml + */ + public List<Reaction> parseXmlReactionCollection(Node reactionsNode) + throws CellDesignerParserException, InvalidXmlSchemaException { + List<Reaction> result = new ArrayList<Reaction>(); + NodeList nodes = reactionsNode.getChildNodes(); + for (int x = 0; x < nodes.getLength(); x++) { + Node node = nodes.item(x); + if (node.getNodeType() == Node.ELEMENT_NODE) { + if (node.getNodeName().equalsIgnoreCase("reaction")) { + Reaction reaction = xmlStructureFactory.getReaction(node, model); + result.add(reaction); + } else { + throw new InvalidXmlSchemaException("Unknown element of model/listOfReactions: " + node.getNodeName()); + } + } + } - return result; - } + return result; + } - /** - * Transforms set of reactions into CellDesigner xml string. - * - * @param collection - * set of reactions - * @return CellDesigner xml string representing set of reactions - * @throws ConverterException - */ - public String reactionCollectionToXmlString(Collection<Reaction> collection) throws InconsistentModelException { - String result = ""; - result += "<listOfReactions>\n"; - for (Reaction reaction : collection) { - try { - result += xmlStructureFactory.toXml(reaction); - } catch (SelfReactionException e) { - logger.warn("Reaction omitted: " + e.getMessage()); - } - } - result += "</listOfReactions>\n"; - return result; - } + /** + * Transforms set of reactions into CellDesigner xml string. + * + * @param collection + * set of reactions + * @return CellDesigner xml string representing set of reactions + * @throws ConverterException + */ + public String reactionCollectionToXmlString(Collection<Reaction> collection) throws InconsistentModelException { + String result = ""; + result += "<listOfReactions>\n"; + for (Reaction reaction : collection) { + try { + result += xmlStructureFactory.toXml(reaction); + } catch (InvalidArgumentException e) { + throw new InconsistentModelException( + new ElementUtils().getElementTag(reaction) + "Problem with exporting reaction", e); + } catch (SelfReactionException e) { + logger.warn("Reaction omitted: " + e.getMessage()); + } + } + result += "</listOfReactions>\n"; + return result; + } } diff --git a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/reaction/SbmlReactionExporter.java b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/reaction/SbmlReactionExporter.java index 05889cd4ff94cab9cbf1ebecdcd9c47234cca9b8..488a9f8b896b10da6c3698cb75ecbd4dfca507a7 100644 --- a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/reaction/SbmlReactionExporter.java +++ b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/reaction/SbmlReactionExporter.java @@ -1,7 +1,6 @@ package lcsb.mapviewer.converter.model.sbml.reaction; import java.awt.geom.Line2D; -import java.awt.geom.Point2D; import java.util.Collection; import java.util.HashMap; import java.util.List; diff --git a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/reaction/SbmlReactionParser.java b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/reaction/SbmlReactionParser.java index 749de4d4cf47559cc9fedb40f769e74033260b31..675593c468f9965859d0f7983c466e38eb0121dc 100644 --- a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/reaction/SbmlReactionParser.java +++ b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/reaction/SbmlReactionParser.java @@ -319,6 +319,11 @@ public class SbmlReactionParser extends SbmlBioEntityParser { } line.addPoint(new Point2D.Double(segment.getEnd().getX(), segment.getEnd().getY())); } + if (line.getPoints().size()==0) { + Point2D point = reactionWithLayout.getReactants().get(0).getLine().getEndPoint(); + line.addPoint(new Point2D.Double(point.getX(), point.getY())); + line.addPoint(new Point2D.Double(point.getX(), point.getY())); + } NodeOperator operator; if (reactionWithLayout instanceof HeterodimerAssociationReaction) { 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 8144beb26ab92392654e69bd2c9c0310f9cc3255..8397387884e3d26a5621edd3ed662c967a01f4da 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 @@ -675,4 +675,18 @@ public class SbmlExporterTest { } + @Test + public void testExportImportBooleanGate() throws Exception { + Model originalModel = new CellDesignerXmlParser() + .createModel(new ConverterParams().filename("testFiles/cell_designer_problems/boolean_logic_gate.xml")); + Model model = getModelAfterSerializing(originalModel); + + new CellDesignerXmlParser().toXml(model); + List<Line2D> lines1 = originalModel.getReactions().iterator().next().getLines(); + List<Line2D> lines2 = model.getReactions().iterator().next().getLines(); + + ListComparator<Line2D> comparator = new ListComparator<>(new LineComparator(Configuration.EPSILON)); + assertEquals(0, comparator.compare(lines1, lines2)); + + } } diff --git a/converter-sbml/testFiles/cell_designer_problems/boolean_logic_gate.xml b/converter-sbml/testFiles/cell_designer_problems/boolean_logic_gate.xml new file mode 100644 index 0000000000000000000000000000000000000000..af4d6c8f71fdcd7ea8e68d4e9fa9f1a971ea9564 --- /dev/null +++ b/converter-sbml/testFiles/cell_designer_problems/boolean_logic_gate.xml @@ -0,0 +1,224 @@ +<?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="190.0" y="44.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:speciesAlias id="sa2" species="s2"> +<celldesigner:activity>inactive</celldesigner:activity> +<celldesigner:bounds x="184.0" y="183.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:speciesAlias id="sa3" species="s3"> +<celldesigner:activity>inactive</celldesigner:activity> +<celldesigner:bounds x="414.0" y="113.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:protein id="pr2" name="s2" type="GENERIC"/> +<celldesigner:protein id="pr3" name="s3" type="GENERIC"/> +</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="CDMT00004" kind="mole"/> +</listOfUnits> +</unitDefinition> +<unitDefinition metaid="volume" id="volume" name="volume"> +<listOfUnits> +<unit metaid="CDMT00005" kind="litre"/> +</listOfUnits> +</unitDefinition> +<unitDefinition metaid="area" id="area" name="area"> +<listOfUnits> +<unit metaid="CDMT00006" kind="metre" exponent="2"/> +</listOfUnits> +</unitDefinition> +<unitDefinition metaid="length" id="length" name="length"> +<listOfUnits> +<unit metaid="CDMT00007" kind="metre"/> +</listOfUnits> +</unitDefinition> +<unitDefinition metaid="time" id="time" name="time"> +<listOfUnits> +<unit metaid="CDMT00008" 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> +<species metaid="s2" id="s2" name="s2" compartment="default" initialAmount="0"> +<annotation> +<celldesigner:extension> +<celldesigner:positionToCompartment>inside</celldesigner:positionToCompartment> +<celldesigner:speciesIdentity> +<celldesigner:class>PROTEIN</celldesigner:class> +<celldesigner:proteinReference>pr2</celldesigner:proteinReference> +</celldesigner:speciesIdentity> +</celldesigner:extension> +</annotation> +</species> +<species metaid="s3" id="s3" name="s3" compartment="default" initialAmount="0"> +<annotation> +<celldesigner:extension> +<celldesigner:positionToCompartment>inside</celldesigner:positionToCompartment> +<celldesigner:speciesIdentity> +<celldesigner:class>PROTEIN</celldesigner:class> +<celldesigner:proteinReference>pr3</celldesigner:proteinReference> +</celldesigner:speciesIdentity> +</celldesigner:extension> +</annotation> +</species> +</listOfSpecies> +<listOfReactions> +<reaction metaid="re1" id="re1" reversible="false"> +<annotation> +<celldesigner:extension> +<celldesigner:reactionType>BOOLEAN_LOGIC_GATE</celldesigner:reactionType> +<celldesigner:baseReactants> +<celldesigner:baseReactant species="s1" alias="sa1"/> +<celldesigner:baseReactant species="s2" alias="sa2"/> +</celldesigner:baseReactants> +<celldesigner:baseProducts> +<celldesigner:baseProduct species="s3" alias="sa3"/> +</celldesigner:baseProducts> +<celldesigner:connectScheme connectPolicy="direct"/> +<celldesigner:editPoints>297.6666666666667,136.66666666666666</celldesigner:editPoints> +<celldesigner:line width="1.0" color="ff000000"/> +<celldesigner:listOfGateMember> +<celldesigner:GateMember type="BOOLEAN_LOGIC_GATE_AND" aliases="sa1,sa2" modificationType="REDUCED_TRIGGER" targetLineIndex="-1,-1" editPoints="297.6666666666667,136.66666666666666"> +<celldesigner:connectScheme connectPolicy="direct"> +<celldesigner:listOfLineDirection> +<celldesigner:lineDirection index="0" value="unknown"/> +</celldesigner:listOfLineDirection> +</celldesigner:connectScheme> +<celldesigner:line width="1.0" color="ff000000"/> +</celldesigner:GateMember> +<celldesigner:GateMember type="REDUCED_TRIGGER" aliases="sa1"> +<celldesigner:connectScheme connectPolicy="direct"> +<celldesigner:listOfLineDirection> +<celldesigner:lineDirection index="0" value="unknown"/> +</celldesigner:listOfLineDirection> +</celldesigner:connectScheme> +<celldesigner:linkTarget species="s1" alias="sa1"> +<celldesigner:linkAnchor position="INACTIVE"/> +</celldesigner:linkTarget> +<celldesigner:line width="1.0" color="ff000000"/> +</celldesigner:GateMember> +<celldesigner:GateMember type="REDUCED_TRIGGER" aliases="sa2"> +<celldesigner:connectScheme connectPolicy="direct"> +<celldesigner:listOfLineDirection> +<celldesigner:lineDirection index="0" value="unknown"/> +</celldesigner:listOfLineDirection> +</celldesigner:connectScheme> +<celldesigner:linkTarget species="s2" alias="sa2"> +<celldesigner:linkAnchor position="INACTIVE"/> +</celldesigner:linkTarget> +<celldesigner:line width="1.0" color="ff000000"/> +</celldesigner:GateMember> +</celldesigner:listOfGateMember> +</celldesigner:extension> +</annotation> +<listOfReactants> +<speciesReference metaid="CDMT00001" species="s1"> +<annotation> +<celldesigner:extension> +<celldesigner:alias>sa1</celldesigner:alias> +</celldesigner:extension> +</annotation> +</speciesReference> +<speciesReference metaid="CDMT00002" species="s2"> +<annotation> +<celldesigner:extension> +<celldesigner:alias>sa2</celldesigner:alias> +</celldesigner:extension> +</annotation> +</speciesReference> +</listOfReactants> +<listOfProducts> +<speciesReference metaid="CDMT00003" species="s3"> +<annotation> +<celldesigner:extension> +<celldesigner:alias>sa3</celldesigner:alias> +</celldesigner:extension> +</annotation> +</speciesReference> +</listOfProducts> +</reaction> +</listOfReactions> +</model> +</sbml>