Commit 49b1e4f8 authored by Piotr Gawron's avatar Piotr Gawron
Browse files

Merge remote-tracking branch 'origin/devel_15.1.x' into merge-15.1.3

parents c41c3402 8db5c05a
Pipeline #37373 passed with stage
in 16 minutes and 41 seconds
minerva (16.0.0~alpha.1) stable; urgency=medium
* Backward incompatibilty: deprecated columns in data overlays are no longer
* Backward incompatibility: deprecated columns in data overlays are no longer
supported (#958)
* Backward incompatibilty: comment does not contain name anymore (#1070)
* Backward incompatibilty: publication pagination API slightly changed (#1007)
* Backward incompatibilty: elements in data overlay are returned differently
* Backward incompatibility: comment does not contain name anymore (#1070)
* Backward incompatibility: publication pagination API slightly changed (#1007)
* Backward incompatibility: elements in data overlay are returned differently
when using data overlay API (#1007)
* Improvement: perormance improved - map is available immediatelly after
* Improvement: performance improved - map is available immediatelly after
tomcat starts (#1007)
* Improvement: minerva does not require huge amounts of memory anymore (#1007)
* Improvement: data overlay allows for multiple hits per element (#1007)
......@@ -17,12 +17,12 @@ minerva (16.0.0~alpha.1) stable; urgency=medium
-- Piotr Gawron <piotr.gawron@uni.lu> Tue, 9 Feb 2020 08:00:00 +0200
minerva (16.0.0~alpha.0) stable; urgency=medium
* Backward incompatibilty: deprecated columns in data overlay table are no
* Backward incompatibility: deprecated columns in data overlay table are no
longer supported: reverseReaction, reaction_identifier, reactionIdentifier,
reference_genome_type, reference_genome_version, allel_frequency, lineWidth,
elementIdentifier, references, model_name (#958)
* Backward incompatibilty: informationm about old search queries removed from
databsae (it can be still accessed using proper log managing)
* Backward incompatibility: information about old search queries removed from
database (it can be still accessed using proper log managing)
* Improvement: automatically generated API documentation available in the
package (#1016)
* Bug fix: md5 hash function of plugin was not computed properly
......@@ -31,6 +31,17 @@ minerva (16.0.0~alpha.0) stable; urgency=medium
-- Piotr Gawron <piotr.gawron@uni.lu> Thu, 27 Aug 2020 13:00:00 +0200
minerva (15.1.3) stable; urgency=medium
* Bug fix: modifier reactions to phenotype were incorrectly translated to
Process Description reactions when exporting to SBGN-ML (#1445)
* Bug fix: AND/OR text was missing when drawing diagram as SBGN (#1428)
* Bug fix: annotators details changes were not saved in few consecutive
updates (#1446)
* Bug fix: SearchListener was not triggered when clicking on highlighted
elements (#1449)
-- Piotr Gawron <piotr.gawron@uni.lu> Tue, 9 Feb 2021 09:00:00 +0200
minerva (15.1.2) stable; urgency=medium
* Bug fix: automatic annotations are sometimes missing after project upload
(#1434)
......@@ -46,7 +57,7 @@ minerva (15.1.2) stable; urgency=medium
minerva (15.1.1) stable; urgency=medium
* Bug fix: export to CD maps with species containing ":" or "." in species id
generated files that could not be opened in CellDesigner (#1363)
generated files that could not be opened in CellDesigner (#1363)
* Bug fix: zoom level change was not reflected in the url when submap was
opened (#1338)
* Bug fix: API call returning list of overlays returned for non existing
......
......@@ -152,9 +152,8 @@ public class SbgnmlXmlExporter {
}
}
} catch (Exception ex) {
ex.printStackTrace();
logger.warn(new LogMarker(ProjectLogEntryType.EXPORT_ISSUE, reaction),
"Unexpected problem with exporting reaction.");
"Unexpected problem with exporting reaction.", ex);
}
}
try {
......@@ -742,7 +741,7 @@ public class SbgnmlXmlExporter {
* {@link Reaction} to extract {@link GlyphClazz} from
* @return {@link GlyphClazz} appropriate to given reaction
*/
private GlyphClazz getGlyphClazzFromReaction(Reaction reaction) {
GlyphClazz getGlyphClazzFromReaction(Reaction reaction) {
if (reaction instanceof HeterodimerAssociationReaction) {
return GlyphClazz.ASSOCIATION;
}
......@@ -758,6 +757,9 @@ public class SbgnmlXmlExporter {
if (reaction instanceof ReducedNotation) {
return null;
}
if (reaction instanceof ModifierReactionNotation) {
return null;
}
return GlyphClazz.PROCESS;
}
......@@ -768,7 +770,7 @@ public class SbgnmlXmlExporter {
* reduced notation reaction
* @return arc extracted from given reduced notation reaction
*/
private Arc getArcFromReducedReaction(Reaction reaction) {
Arc getArcFromReducedReaction(Reaction reaction) {
if ((reaction.getReactants().size() != 1) || (reaction.getProducts().size() != 1)) {
logger.warn(new LogMarker(ProjectLogEntryType.PARSING_ISSUE, reaction),
"Reduced notation does not allow to have multiple reactants/products. Reaction skipped");
......@@ -777,25 +779,15 @@ public class SbgnmlXmlExporter {
Arc arc = new Arc();
arc.setId(reaction.getIdReaction());
if (reaction instanceof NegativeInfluenceReaction) {
arc.setClazz(ArcClazz.INHIBITION.getClazz());
} else if (reaction instanceof ReducedModulationReaction) {
arc.setClazz(ArcClazz.MODULATION.getClazz());
} else if (reaction instanceof ReducedTriggerReaction) {
arc.setClazz(ArcClazz.NECESSARY_STIMULATION.getClazz());
} else if (reaction instanceof ReducedPhysicalStimulationReaction) {
arc.setClazz(ArcClazz.STIMULATION.getClazz());
ArcClazz clazz = getArcClassForReducedNotationReaction(reaction);
if (clazz != null) {
arc.setClazz(clazz.getClazz());
} else {
logger.warn(new LogMarker(ProjectLogEntryType.EXPORT_ISSUE, reaction), "Invalid arc type."
+ " Reduced notation reaction found of type that is not compliant with SBGN-ML format.");
return null;
}
if (reaction.getProducts().get(0).getElement() instanceof Phenotype) {
logger.warn(new LogMarker(ProjectLogEntryType.PARSING_ISSUE, reaction.getProducts().get(0).getElement()),
"Found Phenotype being a reactant in process. That is discouraged");
}
arc.setSource(sourceTargetMap.get(reaction.getReactants().get(0).getElement().getElementId()));
arc.setTarget(sourceTargetMap.get(reaction.getProducts().get(0).getElement().getElementId()));
......@@ -833,6 +825,45 @@ public class SbgnmlXmlExporter {
return arc;
}
ArcClazz getArcClassForReducedNotationReaction(Reaction reaction) {
if (reaction instanceof NegativeInfluenceReaction) {
return ArcClazz.INHIBITION;
} else if (reaction instanceof ReducedModulationReaction) {
return ArcClazz.MODULATION;
} else if (reaction instanceof ReducedTriggerReaction) {
return ArcClazz.NECESSARY_STIMULATION;
} else if (reaction instanceof ReducedPhysicalStimulationReaction) {
return ArcClazz.STIMULATION;
} else if (reaction instanceof CatalysisReaction) {
return ArcClazz.CATALYSIS;
} else if (reaction instanceof InhibitionReaction) {
return ArcClazz.INHIBITION;
} else if (reaction instanceof ModulationReaction) {
return ArcClazz.MODULATION;
} else if (reaction instanceof PhysicalStimulationReaction) {
return ArcClazz.STIMULATION;
} else if (reaction instanceof PositiveInfluenceReaction) {
return ArcClazz.STIMULATION;
} else if (reaction instanceof TriggerReaction) {
return ArcClazz.NECESSARY_STIMULATION;
} else if (reaction instanceof UnknownCatalysisReaction) {
return ArcClazz.CATALYSIS;
} else if (reaction instanceof UnknownInhibitionReaction) {
return ArcClazz.INHIBITION;
} else if (reaction instanceof UnknownNegativeInfluenceReaction) {
return ArcClazz.INHIBITION;
} else if (reaction instanceof UnknownReducedModulationReaction) {
return ArcClazz.MODULATION;
} else if (reaction instanceof UnknownReducedPhysicalStimulationReaction) {
return ArcClazz.STIMULATION;
} else if (reaction instanceof UnknownPositiveInfluenceReaction) {
return ArcClazz.STIMULATION;
} else if (reaction instanceof UnknownReducedTriggerReaction) {
return ArcClazz.NECESSARY_STIMULATION;
}
return null;
}
/**
* Removes redundant points from the list.
*
......@@ -954,7 +985,7 @@ public class SbgnmlXmlExporter {
if (logicArc) {
arc.setClazz(ArcClazz.LOGIC_ARC.getClazz());
} else {
arc.setClazz(getArcClazzFromNode(node));
arc.setClazz(getArcClazzFromNode(node).getClazz());
}
if (node instanceof Reactant) {
......@@ -981,7 +1012,7 @@ public class SbgnmlXmlExporter {
}
if (!found) {
throw new InvalidArgumentException(
new ElementUtils().getElementTag((Modifier) node) + "Problem with exportin modifier");
new ElementUtils().getElementTag((Modifier) node) + "Problem with exporting modifier");
}
}
} else if (node instanceof NodeOperator) {
......@@ -1078,46 +1109,45 @@ public class SbgnmlXmlExporter {
* Node to extract {@link ArcClazz} from
* @return {@link ArcClazz} for given node
*/
private String getArcClazzFromNode(AbstractNode node) {
private ArcClazz getArcClazzFromNode(AbstractNode node) {
if (node instanceof Reactant) {
return ArcClazz.CONSUMPTION.getClazz();
return ArcClazz.CONSUMPTION;
}
if (node instanceof Product) {
return ArcClazz.PRODUCTION.getClazz();
return ArcClazz.PRODUCTION;
}
if (node instanceof Catalysis) {
return ArcClazz.CATALYSIS.getClazz();
return ArcClazz.CATALYSIS;
}
if (node instanceof Inhibition) {
return ArcClazz.INHIBITION.getClazz();
return ArcClazz.INHIBITION;
}
if (node instanceof Modulation) {
return ArcClazz.MODULATION.getClazz();
return ArcClazz.MODULATION;
}
if (node instanceof Trigger) {
return ArcClazz.NECESSARY_STIMULATION.getClazz();
return ArcClazz.NECESSARY_STIMULATION;
}
if (node instanceof PhysicalStimulation) {
return ArcClazz.STIMULATION.getClazz();
return ArcClazz.STIMULATION;
}
if (node instanceof NodeOperator) {
ArrowType arrowType = node.getLine().getEndAtd().getArrowType();
switch (arrowType) {
case BLANK:
return ArcClazz.STIMULATION.getClazz();
return ArcClazz.STIMULATION;
case BLANK_CROSSBAR:
return ArcClazz.NECESSARY_STIMULATION.getClazz();
return ArcClazz.NECESSARY_STIMULATION;
case CIRCLE:
return ArcClazz.CATALYSIS.getClazz();
return ArcClazz.CATALYSIS;
case CROSSBAR:
return ArcClazz.INHIBITION.getClazz();
return ArcClazz.INHIBITION;
case DIAMOND:
return ArcClazz.MODULATION.getClazz();
return ArcClazz.MODULATION;
case NONE:
return ArcClazz.LOGIC_ARC.getClazz();
return ArcClazz.LOGIC_ARC;
default:
throw new InvalidArgumentException();
}
}
throw new InvalidArgumentException();
......
......@@ -605,7 +605,8 @@ public class SbgnmlXmlParser {
try {
parsePhenotypeArc(a, model);
} catch (Exception e) {
logger.warn(getTag(a) + "Probelm with exporting arc", e);
logger.warn(new SbgnLogMarker(ProjectLogEntryType.PARSING_ISSUE, a, model), "Probelm with importing arc",
e);
}
break;
}
......@@ -622,12 +623,19 @@ public class SbgnmlXmlParser {
break;
}
}
boolean found = false;
for (Process p : processes) {
if (p.getCentralPoint().getId().equals(targetGlyph.getId())) {
p.addInfluenceArc(a);
found = true;
break;
}
}
if (!found) {
logger.warn(new SbgnLogMarker(ProjectLogEntryType.PARSING_ISSUE, a, model),
"Expected PHENOTYPE in reduced notation arc. Arc skipped.");
}
break;
} else {
Port targetPort = (Port) a.getTarget();
boolean found = false;
......
......@@ -11,6 +11,7 @@ import org.junit.runners.Suite.SuiteClasses;
ParseNewtExtensionTest.class,
SbgnmlSerializationTest.class,
SbgnmlXmlExporterGenericTest.class,
SbgnmlXmlExporterGeneric2Test.class,
SbgnmlXmlExporterTest.class,
SbgnmlXmlParserTest.class,
SbgnmlXmlParserTest2.class,
......
package lcsb.mapviewer.converter.model.sbgnml;
import static org.junit.Assert.assertEquals;
import java.awt.geom.Point2D;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import lcsb.mapviewer.common.geometry.PointTransformation;
import lcsb.mapviewer.converter.*;
import lcsb.mapviewer.model.graphics.PolylineData;
import lcsb.mapviewer.model.map.InconsistentModelException;
import lcsb.mapviewer.model.map.model.Model;
import lcsb.mapviewer.model.map.model.ModelFullIndexed;
import lcsb.mapviewer.model.map.reaction.*;
import lcsb.mapviewer.model.map.reaction.type.*;
import lcsb.mapviewer.model.map.species.Ion;
@RunWith(Parameterized.class)
public class SbgnmlXmlExporterGeneric2Test extends SbgnmlTestFunctions {
Logger logger = LogManager.getLogger();
private Model model;
public SbgnmlXmlExporterGeneric2Test(String name, Model model) {
this.model = model;
}
@Parameters(name = "{index} : {0}")
public static Collection<Object[]> data() throws Exception {
Collection<Object[]> data = new ArrayList<>();
data.add(createTestEntry(createReaction(TransportReaction.class)));
data.add(createTestEntry(createReaction(TranslationReaction.class)));
data.add(createTestEntry(createReaction(TranscriptionReaction.class)));
return data;
}
@Test
public void test() throws InconsistentModelException, ConverterException, InvalidInputDataExecption {
Converter converter = new SbgnmlXmlConverter();
String content = converter.model2String(model);
assertEquals(0, super.getWarnings().size());
InputStream is = new ByteArrayInputStream(content.getBytes());
Model model2 = converter.createModel(new ConverterParams().inputStream(is));
assertEquals(1, model2.getReactions().size());
}
private static Object[] createTestEntry(Reaction element) {
Model result = new ModelFullIndexed(null);
result.setIdModel("X");
result.setWidth(200);
result.setHeight(200);
for (ReactionNode node : ((Reaction) element).getReactionNodes()) {
result.addElement(node.getElement());
}
result.addReaction((Reaction) element);
return new Object[] { element.getClass().getSimpleName(), result };
}
static int counter = 0;
private static Reaction createReaction(Class<? extends Reaction> clazz) throws Exception {
Reaction reaction = clazz.getConstructor(String.class).newInstance(new Object[] { "re" + (counter++) });
Ion ion = createIon(counter++);
Ion ion2 = createIon(counter);
PointTransformation pt = new PointTransformation();
Point2D p1 = ion.getCenter();
Point2D p4 = ion.getCenter();
Point2D p2 = pt.getPointOnLine(p1, p4, 0.3);
Point2D p3 = pt.getPointOnLine(p1, p4, 0.6);
reaction.setLine(new PolylineData(p2, p3));
Reactant reactant = createReactant(ion);
reactant.setLine(new PolylineData(p1, p2));
reaction.addReactant(reactant);
Product product = createProduct(ion2);
product.setLine(new PolylineData(p3, p4));
reaction.addProduct(product);
return reaction;
}
private static Reactant createReactant(Ion ion) {
Reactant result = new Reactant(ion);
Point2D point = ion.getCenter();
point.setLocation(point.getX() + 300, point.getY());
result.setLine(new PolylineData(ion.getCenter(), point));
return result;
}
private static Product createProduct(Ion ion) {
Product result = new Product(ion);
Point2D point = ion.getCenter();
point.setLocation(point.getX() + 300, point.getY());
result.setLine(new PolylineData(ion.getCenter(), point));
return result;
}
private static Ion createIon(int id) {
Ion ion = new Ion("x" + id);
ion.setName("ion " + id);
ion.setWidth(100);
ion.setHeight(100);
ion.setX(200 * (id % 2 + 1));
ion.setY(50 * (id / 2 + 1));
ion.setNameBorder(ion.getBorder());
ion.setOnlySubstanceUnits(true);
ion.setConstant(true);
ion.setInitialAmount(2.0);
ion.setBoundaryCondition(true);
return ion;
}
}
package lcsb.mapviewer.converter.model.sbgnml;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.Collection;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.sbgn.ArcClazz;
import org.sbgn.GlyphClazz;
import lcsb.mapviewer.common.geometry.PointTransformation;
import lcsb.mapviewer.converter.Converter;
import lcsb.mapviewer.converter.ConverterException;
import lcsb.mapviewer.model.graphics.PolylineData;
import lcsb.mapviewer.model.map.InconsistentModelException;
import lcsb.mapviewer.model.map.model.Model;
import lcsb.mapviewer.model.map.model.ModelFullIndexed;
import lcsb.mapviewer.model.map.reaction.*;
import lcsb.mapviewer.model.map.reaction.type.*;
import lcsb.mapviewer.model.map.reaction.type.ModifierReactionNotation;
import lcsb.mapviewer.model.map.reaction.type.ReducedNotation;
import lcsb.mapviewer.model.map.species.Ion;
import lcsb.mapviewer.modelutils.map.ElementUtils;
@RunWith(Parameterized.class)
public class SbgnmlXmlExporterTest extends SbgnmlTestFunctions {
Logger logger = LogManager.getLogger();
private Model model;
public SbgnmlXmlExporterTest(String name, Model model) {
this.model = model;
}
@Parameters(name = "{index} : {0}")
public static Collection<Object[]> data() throws Exception {
Collection<Object[]> data = new ArrayList<>();
data.add(createTestEntry(createReaction(TransportReaction.class)));
data.add(createTestEntry(createReaction(TranslationReaction.class)));
data.add(createTestEntry(createReaction(TranscriptionReaction.class)));
return data;
}
@Test
public void test() throws InconsistentModelException, ConverterException {
Converter converter = new SbgnmlXmlConverter();
converter.model2String(model);
assertEquals(0, super.getWarnings().size());
public void testGetGlyphClazzFromReaction() throws Exception {
ElementUtils eu = new ElementUtils();
SbgnmlXmlExporter exporter = new SbgnmlXmlExporter();
for (Class<? extends Reaction> clazz : eu.getAvailableReactionSubclasses()) {
Reaction reaction = createReaction(clazz);
GlyphClazz glyph = exporter.getGlyphClazzFromReaction(reaction);
if (reaction instanceof ReducedNotation) {
assertNull(eu.getElementTag(reaction) + "Reduced notation should be not treated as PROCESS", glyph);
} else if (reaction instanceof ModifierReactionNotation) {
assertNull(eu.getElementTag(reaction) + "Modifier reactions should be not treated as PROCESS", glyph);
} else {
assertNotNull(eu.getElementTag(reaction) + "No glyph found", glyph);
}
}
}
private static Object[] createTestEntry(Reaction element) {
Model result = new ModelFullIndexed(null);
result.setIdModel("X");
result.setWidth(200);
result.setHeight(200);
for (ReactionNode node : ((Reaction) element).getReactionNodes()) {
result.addElement(node.getElement());
@Test
public void testGetArcClassForReducedNotationReaction() throws Exception {
ElementUtils eu = new ElementUtils();
SbgnmlXmlExporter exporter = new SbgnmlXmlExporter();
for (Class<? extends Reaction> clazz : eu.getAvailableReactionSubclasses()) {
Reaction reaction = createReaction(clazz);
ArcClazz arc = exporter.getArcClassForReducedNotationReaction(reaction);
if (reaction instanceof ReducedNotation) {
assertNotNull(eu.getElementTag(reaction) + "Reduced notation is not translated properly", arc);
} else if (reaction instanceof ModifierReactionNotation) {
assertNotNull(eu.getElementTag(reaction) + "Modifier reaction is not translated properly", arc);
}
}
result.addReaction((Reaction) element);
return new Object[] { element.getClass().getSimpleName(), result };
}
static int counter = 0;
......@@ -71,24 +63,22 @@ public class SbgnmlXmlExporterTest extends SbgnmlTestFunctions {
Ion ion = createIon(counter++);
Ion ion2 = createIon(counter);
PointTransformation pt = new PointTransformation();
Point2D p1 = ion.getCenter();
Point2D p4 = ion.getCenter();
Point2D p2 = pt.getPointOnLine(p1, p4, 0.3);
Point2D p3 = pt.getPointOnLine(p1, p4, 0.6);
reaction.setLine(new PolylineData(p2, p3));
Reactant reactant = createReactant(ion);
reactant.setLine(new PolylineData(p1, p2));
reaction.addReactant(reactant);
Product product =createProduct(ion2);
Product product = createProduct(ion2);
product.setLine(new PolylineData(p3, p4));
reaction.addProduct(product);
......
......@@ -366,7 +366,7 @@ public class ReactionConverter extends BioEntityConverter<Reaction> {
* @param sbgnFormat
* true if operator is to be drawn in SBGN format