Commit b035e206 authored by Piotr Gawron's avatar Piotr Gawron
Browse files

Merge remote-tracking branch 'origin/master' into migration-script-issues

parents a3c80ff3 407e5243
Pipeline #38715 passed with stage
in 20 minutes and 41 seconds
......@@ -15,13 +15,22 @@ minerva (16.0.0~alpha.1) stable; urgency=medium
(#1376)
* Small improvement: context menu exporting map is more precise about scope
(#1447)
* Small improvement: styling of GENERIC search tab title improved (#1364)
* Small improvement: SBML render contains information about species shapes
(#1055)
* Small improvement: SBML render contains information about modification
residues (#1456)
* Small improvement: SBML render contains information about structural states
(#1456)
* Small improvement: SBML render contains process rectangle for reactions
(#1457)
* Bug fix: refreshing page after removing last project on the page redirect to
proper page (#1051)
* Bug fix: removing plugin that does not exist anymore does not raise an error
(#1289)
* Bug fix: broken overlays crashed minerva upgrade (#1453)
-- Piotr Gawron <piotr.gawron@uni.lu> Tue, 9 Feb 2020 08:00:00 +0200
-- Piotr Gawron <piotr.gawron@uni.lu> Fri, 19 Mar 2021 10:00:00 +0200
minerva (16.0.0~alpha.0) stable; urgency=medium
* Backward incompatibility: deprecated columns in data overlay table are no
......
[![build status](https://git-r3lab.uni.lu/piotr.gawron/minerva/badges/master/build.svg)](https://git-r3lab.uni.lu/piotr.gawron/minerva/commits/master)
[![build status](https://git-r3lab.uni.lu/minerva/core/badges/master/pipeline.svg)](https://git-r3lab.uni.lu/minerva/core/badges/master/pipeline.svg)
[![coverage report](https://git-r3lab.uni.lu/minerva/core/badges/master/coverage.svg)](https://git-r3lab.uni.lu/minerva/core/commits/master)
# For users
......
......@@ -36,7 +36,7 @@ public class EnsemblAnnotator extends ElementAnnotator implements IExternalServi
/**
* Version of the rest API that is supported by this annotator.
*/
static final String SUPPORTED_VERSION = "13.1";
static final String SUPPORTED_VERSION = "14.0";
/**
* Url address of ensembl restful service.
......
......@@ -171,7 +171,7 @@ public class KeggAnnotatorTest extends AnnotationTestFunctions {
mdPubmed.add(md);
}
}
assertEquals("Wrong number of publications extracted from KEGG annotator", 11, mdPubmed.size());
assertTrue("Wrong number of publications extracted from KEGG annotator", 11 <= mdPubmed.size());
}
@Test
......
......@@ -27,6 +27,15 @@ public class NotesUtility {
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
*
......
......@@ -9,15 +9,12 @@ import javax.xml.stream.XMLStreamException;
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.multi.MultiModelPlugin;
import org.sbml.jsbml.ext.render.*;
import org.sbml.jsbml.xml.XMLNode;
import lcsb.mapviewer.common.XmlParser;
import lcsb.mapviewer.common.exception.InvalidStateException;
import lcsb.mapviewer.model.graphics.ArrowType;
import lcsb.mapviewer.model.map.BioEntity;
import lcsb.mapviewer.model.map.InconsistentModelException;
import lcsb.mapviewer.modelutils.map.ElementUtils;
......@@ -56,10 +53,13 @@ public abstract class SbmlBioEntityExporter<T extends BioEntity, S extends org.s
*/
private Map<String, String> correctedElementId = new HashMap<>();
private SbmlModelUtils sbmlModelUtils;
public SbmlBioEntityExporter(Model sbmlModel, lcsb.mapviewer.model.map.model.Model minervaModel,
Collection<SbmlExtension> sbmlExtensions) {
this.sbmlModel = sbmlModel;
this.layout = getLayout(sbmlModel);
this.sbmlModelUtils = new SbmlModelUtils(sbmlModel);
this.layout = sbmlModelUtils.getLayout();
this.minervaModel = minervaModel;
this.sbmlExtensions.addAll(sbmlExtensions);
......@@ -157,38 +157,10 @@ public abstract class SbmlBioEntityExporter<T extends BioEntity, S extends org.s
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() {
return layout;
}
protected RenderLayoutPlugin getRenderPlugin() {
if (getLayout().getExtensionCount() > 0) {
return (RenderLayoutPlugin) getLayout().getExtension("render");
}
return null;
}
protected MultiModelPlugin getMultiPlugin() {
return (MultiModelPlugin) sbmlModel.getExtension("multi");
}
......@@ -209,208 +181,21 @@ public abstract class SbmlBioEntityExporter<T extends BioEntity, S extends org.s
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) {
RenderGraphicalObjectPlugin rgop = new RenderGraphicalObjectPlugin(speciesGlyph);
if (style.getGroup().isSetEndHead()) {
LineEnding lineEnding = createLineEndingStyle(style.getGroup().getEndHead());
LineEnding lineEnding = sbmlModelUtils.createLineEndingStyle(style.getGroup().getEndHead());
style.getGroup().setEndHead(lineEnding.getId());
}
style.getIDList().add(speciesGlyph.getId());
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.setAbsoluteCx(false);
ellipse.setAbsoluteCy(false);
ellipse.setAbsoluteRx(true);
ellipse.setAbsoluteRy(true);
ellipse.setCx(0.0);
ellipse.setCy(0.0);
ellipse.setRx(4.0);
ellipse.setRy(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.setAbsoluteX(false);
result.setX(percentX);
result.setAbsoluteY(false);
result.setY(percentY);
return result;
}
protected BoundingBox createBoundingBox(double x, double y, int z, double w, double h) {
BoundingBox boundingBox = new BoundingBox();
boundingBox.setPosition(new Point(x, y, z));
Dimensions dimensions = new Dimensions();
dimensions.setWidth(w);
dimensions.setHeight(h);
boundingBox.setDimensions(dimensions);
return boundingBox;
return sbmlModelUtils.createBoundingBox(x, y, z, w, h);
}
protected LocalStyle createStyle(T element) {
LocalRenderInformation renderInformation = getRenderInformation(getRenderPlugin());
LocalStyle style = new LocalStyle();
style.setGroup(new RenderGroup());
renderInformation.addLocalStyle(style);
return style;
}
protected abstract LocalStyle createStyle(T element);
protected boolean isProvideDefaults() {
return provideDefaults;
......@@ -435,4 +220,18 @@ public abstract class SbmlBioEntityExporter<T extends BioEntity, S extends org.s
return result;
}
protected ColorDefinition getColorDefinition(Color color) {
return sbmlModelUtils.getColorDefinition(color);
}
protected LocalStyle createStyle() {
return sbmlModelUtils.createStyle();
}
protected void createAbsolutePoint(Polygon polygon, double x, double y) {
RenderPoint p1 = polygon.createRenderPoint();
p1.setX(new RelAbsVector(Math.round(x)));
p1.setY(new RelAbsVector(Math.round(y)));
}
}
......@@ -51,11 +51,9 @@ public abstract class SbmlElementExporter<T extends Element, S extends org.sbml.
textGlyph.setGraphicalObject(speciesGlyph.getId());
if (isExtensionEnabled(SbmlExtension.RENDER)) {
LocalRenderInformation renderInformation = getRenderInformation(getRenderPlugin());
LocalStyle style = new LocalStyle();
LocalStyle style = createStyle();
style.getIDList().add(textGlyph.getId());
RenderGroup group = new RenderGroup();
style.setGroup(group);
RenderGroup group = style.getGroup();
group.setVTextAnchor(VTextAnchor.MIDDLE);
group.setTextAnchor(HTextAnchor.MIDDLE);
switch (element.getNameHorizontalAlign()) {
......@@ -81,7 +79,6 @@ public abstract class SbmlElementExporter<T extends Element, S extends org.sbml.
break;
}
group.setStroke(getColorDefinition(element.getFontColor()).getId());
renderInformation.addLocalStyle(style);
}
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.
@Override
protected LocalStyle createStyle(T element) {
LocalStyle result = super.createStyle(element);
LocalStyle result = createStyle();
ColorDefinition color = getColorDefinition(element.getFillColor());
result.getGroup().setFill(color.getId());
result.getGroup().setFontSize(element.getFontSize().shortValue());
......
......@@ -52,9 +52,10 @@ public class SbmlExporter {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
SBMLWriter.write(doc, stream, "minerva", Configuration.getSystemVersion(null));
return stream.toString("UTF-8")
// TODO bug: https://github.com/sbmlteam/jsbml/issues/158
.replace("<listOfSpeciesFeatures>", "<multi:listOfSpeciesFeatures>")
.replace("</listOfSpeciesFeatures>", "</multi:listOfSpeciesFeatures>");
// COPASI does not accept double coordinates
.replace(".0\"", "\"")
.replace(".0+", "+")
.replace(".0%\"", "%\"");
} catch (UnsupportedEncodingException | XMLStreamException 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;
case OPEN:
createOpenLineEnding(result);
break;
case CIRCLE:
createCircleLineEnding(result);
break;
default:
logger.warn("Unknown arrow type: " + arrowType);
case NONE:
break;
}
return result;
}