Commit 894d6e1a authored by Piotr Gawron's avatar Piotr Gawron
Browse files

modification residues are rendered in SBML

parent 61074fc5
...@@ -18,6 +18,8 @@ minerva (16.0.0~alpha.1) stable; urgency=medium ...@@ -18,6 +18,8 @@ minerva (16.0.0~alpha.1) stable; urgency=medium
* Small improvement: styling of GENERIC search tab title improved (#1364) * Small improvement: styling of GENERIC search tab title improved (#1364)
* Small improvement: SBML render contains information about species shapes * Small improvement: SBML render contains information about species shapes
(#1055) (#1055)
* Small improvement: SBML render contains information about modification
residues (#1456)
* Bug fix: refreshing page after removing last project on the page redirect to * Bug fix: refreshing page after removing last project on the page redirect to
proper page (#1051) proper page (#1051)
* Bug fix: removing plugin that does not exist anymore does not raise an error * Bug fix: removing plugin that does not exist anymore does not raise an error
......
...@@ -27,6 +27,15 @@ public class NotesUtility { ...@@ -27,6 +27,15 @@ public class NotesUtility {
static Logger logger = LogManager.getLogger(); static Logger logger = LogManager.getLogger();
static {
try {
// there is a bug in JSBML with initialization
new SBMLReader().readNotes(StringTools.toXMLNotesString(""));
} catch (XMLStreamException e) {
logger.error(e, e);
}
}
/** /**
* Extract notes from SBML node * Extract notes from SBML node
* *
......
...@@ -9,15 +9,12 @@ import javax.xml.stream.XMLStreamException; ...@@ -9,15 +9,12 @@ import javax.xml.stream.XMLStreamException;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.sbml.jsbml.Model; import org.sbml.jsbml.Model;
import org.sbml.jsbml.ext.SBasePlugin;
import org.sbml.jsbml.ext.layout.*; import org.sbml.jsbml.ext.layout.*;
import org.sbml.jsbml.ext.multi.MultiModelPlugin; import org.sbml.jsbml.ext.multi.MultiModelPlugin;
import org.sbml.jsbml.ext.render.*; import org.sbml.jsbml.ext.render.*;
import org.sbml.jsbml.xml.XMLNode; import org.sbml.jsbml.xml.XMLNode;
import lcsb.mapviewer.common.XmlParser;
import lcsb.mapviewer.common.exception.InvalidStateException; import lcsb.mapviewer.common.exception.InvalidStateException;
import lcsb.mapviewer.model.graphics.ArrowType;
import lcsb.mapviewer.model.map.BioEntity; import lcsb.mapviewer.model.map.BioEntity;
import lcsb.mapviewer.model.map.InconsistentModelException; import lcsb.mapviewer.model.map.InconsistentModelException;
import lcsb.mapviewer.modelutils.map.ElementUtils; import lcsb.mapviewer.modelutils.map.ElementUtils;
...@@ -56,10 +53,13 @@ public abstract class SbmlBioEntityExporter<T extends BioEntity, S extends org.s ...@@ -56,10 +53,13 @@ public abstract class SbmlBioEntityExporter<T extends BioEntity, S extends org.s
*/ */
private Map<String, String> correctedElementId = new HashMap<>(); private Map<String, String> correctedElementId = new HashMap<>();
private SbmlModelUtils sbmlModelUtils;
public SbmlBioEntityExporter(Model sbmlModel, lcsb.mapviewer.model.map.model.Model minervaModel, public SbmlBioEntityExporter(Model sbmlModel, lcsb.mapviewer.model.map.model.Model minervaModel,
Collection<SbmlExtension> sbmlExtensions) { Collection<SbmlExtension> sbmlExtensions) {
this.sbmlModel = sbmlModel; this.sbmlModel = sbmlModel;
this.layout = getLayout(sbmlModel); this.sbmlModelUtils = new SbmlModelUtils(sbmlModel);
this.layout = sbmlModelUtils.getLayout();
this.minervaModel = minervaModel; this.minervaModel = minervaModel;
this.sbmlExtensions.addAll(sbmlExtensions); this.sbmlExtensions.addAll(sbmlExtensions);
...@@ -157,38 +157,10 @@ public abstract class SbmlBioEntityExporter<T extends BioEntity, S extends org.s ...@@ -157,38 +157,10 @@ public abstract class SbmlBioEntityExporter<T extends BioEntity, S extends org.s
return (idCounter++) + ""; return (idCounter++) + "";
} }
private Layout getLayout(org.sbml.jsbml.Model sbmlModel) {
Layout layout = null;
if (sbmlModel.getExtensionCount() > 0) {
for (SBasePlugin plugin : sbmlModel.getExtensionPackages().values()) {
if (plugin.getClass().equals(org.sbml.jsbml.ext.layout.LayoutModelPlugin.class)) {
LayoutModelPlugin layoutPlugin = (LayoutModelPlugin) plugin;
if (layoutPlugin.getLayoutCount() == 0) {
logger.warn("Layout plugin available but no layouts defined");
} else if (layoutPlugin.getLayoutCount() > 1) {
logger.warn(layoutPlugin.getLayoutCount() + " layouts defined. Using first one.");
layout = layoutPlugin.getLayout(0);
} else {
layout = layoutPlugin.getLayout(0);
}
}
}
}
return layout;
}
protected Layout getLayout() { protected Layout getLayout() {
return layout; return layout;
} }
protected RenderLayoutPlugin getRenderPlugin() {
if (getLayout().getExtensionCount() > 0) {
return (RenderLayoutPlugin) getLayout().getExtension("render");
}
return null;
}
protected MultiModelPlugin getMultiPlugin() { protected MultiModelPlugin getMultiPlugin() {
return (MultiModelPlugin) sbmlModel.getExtension("multi"); return (MultiModelPlugin) sbmlModel.getExtension("multi");
} }
...@@ -209,202 +181,21 @@ public abstract class SbmlBioEntityExporter<T extends BioEntity, S extends org.s ...@@ -209,202 +181,21 @@ public abstract class SbmlBioEntityExporter<T extends BioEntity, S extends org.s
return sbmlGlyphByElementId.get(elementId); return sbmlGlyphByElementId.get(elementId);
} }
protected ColorDefinition getColorDefinition(Color color) {
RenderLayoutPlugin renderPlugin = getRenderPlugin();
LocalRenderInformation renderInformation = getRenderInformation(renderPlugin);
for (ColorDefinition cd : renderInformation.getListOfColorDefinitions()) {
if (cd.getValue().equals(color)) {
return cd;
}
}
ColorDefinition colorDefinition = new ColorDefinition("color_" + XmlParser.colorToString(color), color);
renderInformation.addColorDefinition(colorDefinition);
return colorDefinition;
}
protected LocalRenderInformation getRenderInformation(RenderLayoutPlugin renderPlugin) {
LocalRenderInformation renderInformation = null;
for (LocalRenderInformation lri : renderPlugin.getListOfLocalRenderInformation()) {
if (lri.getId().equals("minerva_definitions")) {
renderInformation = lri;
}
}
if (renderInformation == null) {
renderInformation = new LocalRenderInformation("minerva_definitions");
renderPlugin.addLocalRenderInformation(renderInformation);
}
return renderInformation;
}
protected void assignStyleToGlyph(AbstractReferenceGlyph speciesGlyph, LocalStyle style) { protected void assignStyleToGlyph(AbstractReferenceGlyph speciesGlyph, LocalStyle style) {
RenderGraphicalObjectPlugin rgop = new RenderGraphicalObjectPlugin(speciesGlyph); RenderGraphicalObjectPlugin rgop = new RenderGraphicalObjectPlugin(speciesGlyph);
if (style.getGroup().isSetEndHead()) { if (style.getGroup().isSetEndHead()) {
LineEnding lineEnding = createLineEndingStyle(style.getGroup().getEndHead()); LineEnding lineEnding = sbmlModelUtils.createLineEndingStyle(style.getGroup().getEndHead());
style.getGroup().setEndHead(lineEnding.getId()); style.getGroup().setEndHead(lineEnding.getId());
} }
style.getIDList().add(speciesGlyph.getId()); style.getIDList().add(speciesGlyph.getId());
speciesGlyph.addExtension(RenderConstants.shortLabel, rgop); speciesGlyph.addExtension(RenderConstants.shortLabel, rgop);
} }
protected LineEnding createLineEndingStyle(String endHead) {
String arrowTypeId = endHead.replaceAll("line_ending_", "");
LocalRenderInformation renderInformation = getRenderInformation(getRenderPlugin());
LineEnding result = renderInformation.getListOfLineEndings().get("line_ending_" + arrowTypeId);
if (result != null) {
return result;
}
ArrowType arrowType = ArrowType.valueOf(arrowTypeId);
result = new LineEnding();
result.setId("line_ending_" + arrowTypeId);
result.setGroup(new RenderGroup());
renderInformation.getListOfLineEndings().add(result);
switch (arrowType) {
case FULL:
createFullLineEnding(result);
break;
case BLANK:
createBlankLineEnding(result);
break;
case FULL_CROSSBAR:
createFullCrossBarLineEnding(result);
break;
case BLANK_CROSSBAR:
createBlankCrossBarLineEnding(result);
break;
case CROSSBAR:
createCrossBarLineEnding(result);
break;
case DIAMOND:
createDiamondLineEnding(result);
break;
case OPEN:
createOpenLineEnding(result);
break;
case CIRCLE:
createCircleLineEnding(result);
break;
default:
logger.warn("Unknown arrow type: " + arrowType);
case NONE:
break;
}
return result;
}
private void createCircleLineEnding(LineEnding result) {
BoundingBox boundingBox = createBoundingBox(-2, 0, 0, 4, 4);
result.getGroup().setFill(getColorDefinition(Color.WHITE).getId());
result.setBoundingBox(boundingBox);
Ellipse ellipse = new Ellipse();
ellipse.setCx(new RelAbsVector(0, 0));
ellipse.setCy(new RelAbsVector(0, 0));
ellipse.setRx(new RelAbsVector(4, 0));
ellipse.setRy(new RelAbsVector(4, 0));
result.getGroup().addElement(ellipse);
}
private void createOpenLineEnding(LineEnding result) {
BoundingBox boundingBox = createBoundingBox(-12, -6, 0, 12, 12);
result.setBoundingBox(boundingBox);
Polygon polygon = new Polygon();
polygon.addElement(createRenderPoint(0, 0));
polygon.addElement(createRenderPoint(100, 50));
polygon.addElement(createRenderPoint(0, 100));
polygon.addElement(createRenderPoint(100, 50));
result.getGroup().addElement(polygon);
}
private void createDiamondLineEnding(LineEnding result) {
BoundingBox boundingBox = createBoundingBox(-18, -6, 0, 18, 12);
result.setBoundingBox(boundingBox);
result.getGroup().setFill(getColorDefinition(Color.WHITE).getId());
Polygon polygon = new Polygon();
polygon.addElement(createRenderPoint(50, 0));
polygon.addElement(createRenderPoint(100, 50));
polygon.addElement(createRenderPoint(50, 100));
polygon.addElement(createRenderPoint(0, 50));
polygon.addElement(createRenderPoint(50, 0));
result.getGroup().addElement(polygon);
}
private void createCrossBarLineEnding(LineEnding result) {
BoundingBox boundingBox = createBoundingBox(0, -6, 0, 1, 12);
result.setBoundingBox(boundingBox);
Polygon crossBar = new Polygon();
crossBar.addElement(createRenderPoint(0, 0));
crossBar.addElement(createRenderPoint(0, 100));
result.getGroup().addElement(crossBar);
}
private void createBlankLineEnding(LineEnding result) {
createFullLineEnding(result);
result.getGroup().setFill(getColorDefinition(Color.WHITE).getId());
}
private void createFullLineEnding(LineEnding result) {
BoundingBox boundingBox = createBoundingBox(-12, -6, 0, 12, 12);
result.setBoundingBox(boundingBox);
result.getGroup().setFill(getColorDefinition(Color.BLACK).getId());
Polygon polygon = new Polygon();
polygon.addElement(createRenderPoint(0, 0));
polygon.addElement(createRenderPoint(100, 50));
polygon.addElement(createRenderPoint(0, 100));
polygon.addElement(createRenderPoint(0, 0));
result.getGroup().addElement(polygon);
}
private void createBlankCrossBarLineEnding(LineEnding result) {
BoundingBox boundingBox = createBoundingBox(-18, -6, 0, 18, 12);
result.setBoundingBox(boundingBox);
result.getGroup().setFill(getColorDefinition(Color.WHITE).getId());
Polygon polygon = new Polygon();
polygon.addElement(createRenderPoint(33, 0));
polygon.addElement(createRenderPoint(100, 50));
polygon.addElement(createRenderPoint(33, 100));
polygon.addElement(createRenderPoint(33, 0));
result.getGroup().addElement(polygon);
Polygon crossBar = new Polygon();
crossBar.addElement(createRenderPoint(0, 0));
crossBar.addElement(createRenderPoint(0, 100));
result.getGroup().addElement(crossBar);
}
private void createFullCrossBarLineEnding(LineEnding result) {
createBlankCrossBarLineEnding(result);
result.getGroup().setFill(getColorDefinition(Color.BLACK).getId());
}
protected RenderPoint createRenderPoint(double percentX, int percentY) {
RenderPoint result = new RenderPoint();
result.setX(new RelAbsVector(0, percentX));
result.setY(new RelAbsVector(0, percentY));
return result;
}
protected BoundingBox createBoundingBox(double x, double y, int z, double w, double h) { protected BoundingBox createBoundingBox(double x, double y, int z, double w, double h) {
BoundingBox boundingBox = new BoundingBox(); return sbmlModelUtils.createBoundingBox(x, y, z, w, h);
boundingBox.setPosition(new Point(x, y, z));
Dimensions dimensions = new Dimensions();
dimensions.setWidth(w);
dimensions.setHeight(h);
boundingBox.setDimensions(dimensions);
return boundingBox;
} }
protected LocalStyle createStyle(T element) { protected abstract LocalStyle createStyle(T element);
LocalRenderInformation renderInformation = getRenderInformation(getRenderPlugin());
LocalStyle style = new LocalStyle();
style.setGroup(new RenderGroup());
renderInformation.addLocalStyle(style);
return style;
}
protected boolean isProvideDefaults() { protected boolean isProvideDefaults() {
return provideDefaults; return provideDefaults;
...@@ -429,4 +220,12 @@ public abstract class SbmlBioEntityExporter<T extends BioEntity, S extends org.s ...@@ -429,4 +220,12 @@ public abstract class SbmlBioEntityExporter<T extends BioEntity, S extends org.s
return result; return result;
} }
protected ColorDefinition getColorDefinition(Color color) {
return sbmlModelUtils.getColorDefinition(color);
}
protected LocalStyle createStyle() {
return sbmlModelUtils.createStyle();
}
} }
...@@ -51,11 +51,9 @@ public abstract class SbmlElementExporter<T extends Element, S extends org.sbml. ...@@ -51,11 +51,9 @@ public abstract class SbmlElementExporter<T extends Element, S extends org.sbml.
textGlyph.setGraphicalObject(speciesGlyph.getId()); textGlyph.setGraphicalObject(speciesGlyph.getId());
if (isExtensionEnabled(SbmlExtension.RENDER)) { if (isExtensionEnabled(SbmlExtension.RENDER)) {
LocalRenderInformation renderInformation = getRenderInformation(getRenderPlugin()); LocalStyle style = createStyle();
LocalStyle style = new LocalStyle();
style.getIDList().add(textGlyph.getId()); style.getIDList().add(textGlyph.getId());
RenderGroup group = new RenderGroup(); RenderGroup group = style.getGroup();
style.setGroup(group);
group.setVTextAnchor(VTextAnchor.MIDDLE); group.setVTextAnchor(VTextAnchor.MIDDLE);
group.setTextAnchor(HTextAnchor.MIDDLE); group.setTextAnchor(HTextAnchor.MIDDLE);
switch (element.getNameHorizontalAlign()) { switch (element.getNameHorizontalAlign()) {
...@@ -81,7 +79,6 @@ public abstract class SbmlElementExporter<T extends Element, S extends org.sbml. ...@@ -81,7 +79,6 @@ public abstract class SbmlElementExporter<T extends Element, S extends org.sbml.
break; break;
} }
group.setStroke(getColorDefinition(element.getFontColor()).getId()); group.setStroke(getColorDefinition(element.getFontColor()).getId());
renderInformation.addLocalStyle(style);
} }
textGlyph.setBoundingBox(createBoundingBox(x, y, element.getZ() + 1, width, height)); textGlyph.setBoundingBox(createBoundingBox(x, y, element.getZ() + 1, width, height));
...@@ -89,7 +86,7 @@ public abstract class SbmlElementExporter<T extends Element, S extends org.sbml. ...@@ -89,7 +86,7 @@ public abstract class SbmlElementExporter<T extends Element, S extends org.sbml.
@Override @Override
protected LocalStyle createStyle(T element) { protected LocalStyle createStyle(T element) {
LocalStyle result = super.createStyle(element); LocalStyle result = createStyle();
ColorDefinition color = getColorDefinition(element.getFillColor()); ColorDefinition color = getColorDefinition(element.getFillColor());
result.getGroup().setFill(color.getId()); result.getGroup().setFill(color.getId());
result.getGroup().setFontSize(element.getFontSize().shortValue()); result.getGroup().setFontSize(element.getFontSize().shortValue());
......
...@@ -51,7 +51,10 @@ public class SbmlExporter { ...@@ -51,7 +51,10 @@ public class SbmlExporter {
ByteArrayOutputStream stream = new ByteArrayOutputStream(); ByteArrayOutputStream stream = new ByteArrayOutputStream();
SBMLWriter.write(doc, stream, "minerva", Configuration.getSystemVersion(null)); SBMLWriter.write(doc, stream, "minerva", Configuration.getSystemVersion(null));
return stream.toString("UTF-8"); return stream.toString("UTF-8")
// COPASI does not accept double coordinates
.replace(".0\"", "\"")
.replace(".0%\"", "%\"");
} catch (UnsupportedEncodingException | XMLStreamException e) { } catch (UnsupportedEncodingException | XMLStreamException e) {
throw new InvalidStateException(e); throw new InvalidStateException(e);
} }
......
package lcsb.mapviewer.converter.model.sbml;
import java.awt.Color;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.sbml.jsbml.Model;
import org.sbml.jsbml.ext.SBasePlugin;
import org.sbml.jsbml.ext.layout.*;
import org.sbml.jsbml.ext.render.*;
import lcsb.mapviewer.common.XmlParser;
import lcsb.mapviewer.model.graphics.ArrowType;
public class SbmlModelUtils {
private Logger logger = LogManager.getLogger();
private final Model sbmlModel;
private Layout layout;
public SbmlModelUtils(Model model) {
this.sbmlModel = model;
this.layout = computeLayout();
}
private Layout computeLayout() {
Layout layout = null;
if (sbmlModel.getExtensionCount() > 0) {
for (SBasePlugin plugin : sbmlModel.getExtensionPackages().values()) {
if (plugin.getClass().equals(org.sbml.jsbml.ext.layout.LayoutModelPlugin.class)) {
LayoutModelPlugin layoutPlugin = (LayoutModelPlugin) plugin;
if (layoutPlugin.getLayoutCount() == 0) {
logger.warn("Layout plugin available but no layouts defined");
} else if (layoutPlugin.getLayoutCount() > 1) {
logger.warn(layoutPlugin.getLayoutCount() + " layouts defined. Using first one.");
layout = layoutPlugin.getLayout(0);
} else {
layout = layoutPlugin.getLayout(0);
}
}
}
}
return layout;
}
public Layout getLayout() {
return layout;
}
public RenderLayoutPlugin getRenderPlugin() {
if (getLayout().getExtensionCount() > 0) {
return (RenderLayoutPlugin) getLayout().getExtension("render");
}
return null;
}
public ColorDefinition getColorDefinition(Color color) {
RenderLayoutPlugin renderPlugin = getRenderPlugin();
LocalRenderInformation renderInformation = getRenderInformation(renderPlugin);
for (ColorDefinition cd : renderInformation.getListOfColorDefinitions()) {
if (cd.getValue().equals(color)) {
return cd;
}
}
ColorDefinition colorDefinition = new ColorDefinition("color_" + XmlParser.colorToString(color), color);
renderInformation.addColorDefinition(colorDefinition);
return colorDefinition;
}
public LocalRenderInformation getRenderInformation() {
return getRenderInformation(getRenderPlugin());
}
public LocalRenderInformation getRenderInformation(RenderLayoutPlugin renderPlugin) {
LocalRenderInformation renderInformation = null;
for (LocalRenderInformation lri : renderPlugin.getListOfLocalRenderInformation()) {
if (lri.getId().equals("minerva_definitions")) {
renderInformation = lri;
}
}
if (renderInformation == null) {
renderInformation = new LocalRenderInformation("minerva_definitions");
renderPlugin.addLocalRenderInformation(renderInformation);
}
return renderInformation;
}
public LocalStyle createStyle() {
LocalRenderInformation renderInformation = getRenderInformation(getRenderPlugin());
LocalStyle style = new LocalStyle();
style.setGroup(new RenderGroup());
renderInformation.addLocalStyle(style);
return style;
}
protected LineEnding createLineEndingStyle(String endHead) {
String arrowTypeId = endHead.replaceAll("line_ending_", "");
LocalRenderInformation renderInformation = getRenderInformation();
LineEnding result = renderInformation.getListOfLineEndings().get("line_ending_" + arrowTypeId);
if (result != null) {
return result;
}
ArrowType arrowType = ArrowType.valueOf(arrowTypeId);
result = new LineEnding();
result.setId("line_ending_" + arrowTypeId);
result.setGroup(new RenderGroup());
renderInformation.getListOfLineEndings().add(result);
switch (arrowType) {
case FULL:
createFullLineEnding(result);
break;
case BLANK:
createBlankLineEnding(result);
break;
case FULL_CROSSBAR:
createFullCrossBarLineEnding(result);
break;
case BLANK_CROSSBAR:
createBlankCrossBarLineEnding(result);
break;
case CROSSBAR:
createCrossBarLineEnding(result);
break;
case DIAMOND:
createDiamondLineEnding(result);
break;