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

Merge branch '597-handle-coloring-of-reaction-parts' into 'master'

Resolve "Handle coloring of reaction parts"

Closes #597

See merge request minerva/core!706
parents ce50f412 8655b439
......@@ -22,6 +22,8 @@ minerva (12.3.0~alpha.0) unstable; urgency=low
(#666)
* Small improvement: passwords to email account and ldap are not sent over
API (#732)
* Small improvement: reactant/product/modifier specific colors are parsed
properly from CellDesigner file (#597)
* Bug fix: progress bar of gene genome mapping upload is refreshing properly
(#728)
* Bug fix: when editing project Disease and Organism could not be removed
......
package lcsb.mapviewer.common.comparator;
import java.util.Comparator;
import lcsb.mapviewer.common.Configuration;
/**
* Comparator used for {@link Float} class.
*
* @author Piotr Gawron
*
*/
public class FloatComparator implements Comparator<Float> {
/**
* Epsilon value used for comparison of doubles.
*/
private double epsilon;
/**
* Default constructor.
*/
public FloatComparator() {
this(Configuration.EPSILON);
}
/**
* Constructor that requires {@link #epsilon} parameter.
*
* @param epsilon
* {@link #epsilon}
*/
public FloatComparator(double epsilon) {
this.epsilon = epsilon;
}
@Override
public int compare(Float arg0, Float arg1) {
if (arg0 == null) {
if (arg1 == null) {
return 0;
} else {
return 1;
}
} else if (arg1 == null) {
return -1;
}
if (Math.abs(arg0 - arg1) < epsilon) {
return 0;
} else {
return arg0.compareTo(arg1);
}
}
}
......@@ -106,6 +106,11 @@ public class ReactionFromXml {
*/
private Map<ReactionNode, List<Point2D>> pointsByModifier = new HashMap<>();
/**
* Stores information about list of points that create line describing modifier.
*/
private Map<ReactionNode, LineProperties> linePropertiesByModifier = new HashMap<>();
/**
* Helps to determine if the key Modifier should be treats as part of
* NodeOperator (value in the map).
......@@ -446,6 +451,11 @@ public class ReactionFromXml {
throw new ReactionParserException(
"Problem with parsing lines. Unknown reaction: " + type + "; " + result.getClass().getName(), result);
}
for (AbstractNode rNode : result.getNodes()) {
applyStylingToLine(line, rNode.getLine());
}
if (reactantsLinkNode != null) {
parseReactantLinks(result, reactantsLinkNode, model);
}
......@@ -480,12 +490,6 @@ public class ReactionFromXml {
}
}
if (line != null) {
for (AbstractNode rNode : result.getNodes()) {
rNode.getLine().setWidth(line.getWidth());
rNode.getLine().setColor(line.getColor());
}
}
if (result.isReversible()) {
for (Reactant reactant : result.getReactants()) {
reactant.getLine().getBeginAtd()
......@@ -499,6 +503,13 @@ public class ReactionFromXml {
}
}
private void applyStylingToLine(LineProperties style, PolylineData line) {
if (style != null) {
line.setWidth(style.getWidth());
line.setColor(style.getColor());
}
}
/**
* Creates reaction with a new type.
*
......@@ -581,7 +592,7 @@ public class ReactionFromXml {
*
* @param modifier
* modifier to update
* @throws ReactionParserException
* @throws ReactionParserException
*/
private void createLineForModifier(Modifier modifier) throws ReactionParserException {
try {
......@@ -599,6 +610,7 @@ public class ReactionFromXml {
line.setStartPoint(startPoint);
modifier.setLine(line);
modifierTypeUtils.updateLineEndPoint(modifier);
applyStylingToLine(linePropertiesByModifier.get(modifier), line);
} catch (Exception e) {
throw new ReactionParserException("Problem with creating layout for modifier.", modifier.getReaction());
}
......@@ -729,6 +741,7 @@ public class ReactionFromXml {
if (nodes.size() > 1) {
AndOperator inputOperator = new AndOperator();
inputOperator.setLine(ld);
applyStylingToLine(new LineProperties(nodes.iterator().next().getLine()), ld);
inputOperator.addInputs(nodes);
for (Reactant reactant : result.getReactants()) {
if (!toExclude.contains(reactant)) {
......@@ -773,6 +786,7 @@ public class ReactionFromXml {
if (nodes.size() > 1) {
SplitOperator outputOperator = new SplitOperator();
outputOperator.setLine(ld);
applyStylingToLine(new LineProperties(nodes.iterator().next().getLine()), ld);
outputOperator.addOutputs(nodes);
for (Product product : result.getProducts()) {
if (!toExclude.contains(product)) {
......@@ -1024,7 +1038,7 @@ public class ReactionFromXml {
} else {
centerPoint = pointP;
}
int startId0 = 0;
int num0 = points.getNum0();
int startId1 = num0;
......@@ -1270,6 +1284,7 @@ public class ReactionFromXml {
Reactant result = new Reactant(element);
CellDesignerAnchor anchor = null;
EditPoints points = null;
LineProperties style = null;
NodeList nodes = rootNode.getChildNodes();
for (int x = 0; x < nodes.getLength(); x++) {
......@@ -1280,7 +1295,7 @@ public class ReactionFromXml {
} else if (node.getNodeName().equalsIgnoreCase("celldesigner:linkAnchor")) {
anchor = CellDesignerAnchor.valueOf(XmlParser.getNodeAttr("position", node).toUpperCase());
} else if (node.getNodeName().equalsIgnoreCase("celldesigner:line")) {
continue;
style = getLineProperties(node);
} else if (node.getNodeName().equalsIgnoreCase("celldesigner:editPoints")) {
points = parseEditPoints(node);
} else {
......@@ -1309,6 +1324,7 @@ public class ReactionFromXml {
additionalPoint = reactantConverter.getAnchorPointCoordinates(element, anchor, polyline);
polyline.setStartPoint(additionalPoint);
result.setLine(polyline);
applyStylingToLine(style, polyline);
return result;
}
......@@ -1371,6 +1387,7 @@ public class ReactionFromXml {
CellDesignerAnchor anchor = null;
EditPoints points = null;
LineProperties style = null;
NodeList nodes = rootNode.getChildNodes();
for (int x = 0; x < nodes.getLength(); x++) {
......@@ -1381,7 +1398,7 @@ public class ReactionFromXml {
} else if (node.getNodeName().equalsIgnoreCase("celldesigner:linkAnchor")) {
anchor = CellDesignerAnchor.valueOf(XmlParser.getNodeAttr("position", node).toUpperCase());
} else if (node.getNodeName().equalsIgnoreCase("celldesigner:line")) {
continue;
style = getLineProperties(node);
} else if (node.getNodeName().equalsIgnoreCase("celldesigner:editPoints")) {
points = parseEditPoints(node);
} else {
......@@ -1429,6 +1446,7 @@ public class ReactionFromXml {
polyline.getEndAtd().setArrowType(ArrowType.FULL);
result.setLine(polyline);
applyStylingToLine(style, polyline);
return result;
}
......@@ -1450,7 +1468,7 @@ public class ReactionFromXml {
}
/**
* PArse reaction modifiactions and add them into reaction.
* PArse reaction modifications and add them into reaction.
*
* @param result
* reaction currently processed
......@@ -1550,7 +1568,7 @@ public class ReactionFromXml {
if (node.getNodeName().equalsIgnoreCase("celldesigner:connectScheme")) {
continue;
} else if (node.getNodeName().equalsIgnoreCase("celldesigner:line")) {
continue;
linePropertiesByModifier.put(result, getLineProperties(node));
} else if (node.getNodeName().equalsIgnoreCase("celldesigner:linkTarget")) {
try {
CellDesignerAnchor anchor = getAnchorFromLinkTarget(node);
......@@ -1604,6 +1622,7 @@ public class ReactionFromXml {
startPoint = reactantConverter.getAnchorPointCoordinates(param.getElement(), anchorsByNodes.get(param), polyline);
polyline.setStartPoint(startPoint);
param.setLine(polyline);
applyStylingToLine(linePropertiesByModifier.get(modifier), polyline);
}
}
......
......@@ -2,6 +2,8 @@ package lcsb.mapviewer.converter.model.celldesigner.structure.fields;
import java.awt.Color;
import lcsb.mapviewer.model.graphics.PolylineData;
/**
* Structure used in CellDEsigner model to store information about line
* properties.
......@@ -10,80 +12,91 @@ import java.awt.Color;
*
*/
public class LineProperties {
/**
* Width of the line.
*/
private double width;
/**
* Color of the line.
*/
private Color color;
/**
* Line type (no idea what is the format).
*/
private String type;
/**
* Width of the line.
*/
private double width;
/**
* Color of the line.
*/
private Color color;
/**
* Line type (no idea what is the format).
*/
private String type;
/**
* Default constructor.
*/
public LineProperties() {
width = 1;
color = Color.BLACK;
type = "";
}
/**
* Default constructor.
*/
public LineProperties() {
width = 1;
color = Color.BLACK;
type = "";
}
/**
* Create properties from {@link PolylineData}.
*
* @param line
*/
public LineProperties(PolylineData line) {
width = line.getWidth();
color = line.getColor();
type = "";
}
/**
* @return the width
* @see #width
*/
public double getWidth() {
return width;
}
/**
* @return the width
* @see #width
*/
public double getWidth() {
return width;
}
/**
* @param width
* the width to set
* @see #width
*/
public void setWidth(double width) {
this.width = width;
}
/**
* @param width
* the width to set
* @see #width
*/
public void setWidth(double width) {
this.width = width;
}
/**
* @return the color
* @see #color
*/
public Color getColor() {
return color;
}
/**
* @return the color
* @see #color
*/
public Color getColor() {
return color;
}
/**
* @param color
* the color to set
* @see #color
*/
public void setColor(Color color) {
this.color = color;
}
/**
* @param color
* the color to set
* @see #color
*/
public void setColor(Color color) {
this.color = color;
}
/**
* @return the type
* @see #type
*/
public String getType() {
return type;
}
/**
* @return the type
* @see #type
*/
public String getType() {
return type;
}
/**
* @param type
* the type to set
* @see #type
*/
public void setType(String type) {
this.type = type;
}
/**
* @param type
* the type to set
* @see #type
*/
public void setType(String type) {
this.type = type;
}
}
......@@ -8,6 +8,7 @@ import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.when;
import java.awt.Color;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
......@@ -19,7 +20,9 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.log4j.Logger;
import org.junit.After;
......@@ -41,6 +44,7 @@ import lcsb.mapviewer.model.map.layout.graphics.LayerText;
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.AbstractNode;
import lcsb.mapviewer.model.map.reaction.Product;
import lcsb.mapviewer.model.map.reaction.Reactant;
import lcsb.mapviewer.model.map.reaction.Reaction;
......@@ -1041,4 +1045,42 @@ public class CellDesignerXmlParserTest extends CellDesignerTestFunctions {
throw e;
}
}
@Test
public void testParseReactionWithColors() throws Exception {
try {
CellDesignerXmlParser parser = new CellDesignerXmlParser();
Model model = parser.createModel(new ConverterParams().filename("testFiles/reactions/coloring.xml"));
Reaction r1 = model.getReactionByReactionId("re1");
Set<Color> colors = new HashSet<>();
for (AbstractNode node : r1.getNodes()) {
colors.add(node.getLine().getColor());
}
assertEquals("Four different colors were used to draw the reaction", 4, colors.size());
assertFalse("Black wasn't used in reaction coloring", colors.contains(Color.BLACK));
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
@Test
public void testExportReactionWithColors() throws Exception {
try {
CellDesignerXmlParser parser = new CellDesignerXmlParser();
Model model = parser.createModel(new ConverterParams().filename("testFiles/reactions/coloring.xml"));
model.setName(null);
assertNotNull(model);
String str = parser.model2String(model);
Model model2 = parser.createModel(
new ConverterParams().inputStream(new ByteArrayInputStream(str.getBytes(StandardCharsets.UTF_8))));
assertEquals(0, new ModelComparator().compare(model, model2));
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
}
......@@ -515,7 +515,6 @@ public class LayerXmlParserTest extends CellDesignerTestFunctions {
LayerText text = new LayerText();
text.setBackgroundColor(Color.BLUE);
String xml = parser.layerTextToXml(text);
logger.debug(xml);
assertTrue(xml.contains("BackgroundColor"));
} catch (Exception e) {
e.printStackTrace();
......
......@@ -132,8 +132,6 @@ public class RnaTest {
copy.addRegion(new CellDesignerModificationResidue());
copy.getRegions().get(0).setState(ModificationState.ACETYLATED);
logger.debug(copy.getRegions().size());
original.update(copy);
boolean acetylatedFound = false;
......
......@@ -18,4 +18,30 @@ log4j.appender.R.layout.ConversionPattern=%d %5p [%t] (%F:%L) - %m%n
log4j.logger.org.springframework=warn
log4j.logger.org.hibernate=warn
log4j.logger.lcsb=debug
log4j.logger.lcsb.mapviewer.common.comparator=info
log4j.logger.lcsb.mapviewer.common.Comparator=info
log4j.logger.lcsb.mapviewer.model.map.species.ElementComparator=info
log4j.logger.lcsb.mapviewer.model.map.species.SpeciesComparator=info
log4j.logger.lcsb.mapviewer.model.map.species.SimpleMoleculeComparator=info
log4j.logger.lcsb.mapviewer.model.map.species.ProteinComparator=info
log4j.logger.lcsb.mapviewer.model.map.species.AssociatedElementComparator=info
log4j.logger.lcsb.mapviewer.model.map.species.ComplexSpeciesComparator=info
log4j.logger.lcsb.mapviewer.model.map.species.AssociatedElementComparator=info
log4j.logger.lcsb.mapviewer.model.map.species.PhenotypeComparator=info
log4j.logger.lcsb.mapviewer.model.map.species.fields.AssociatedElementComparator=info
log4j.logger.lcsb.mapviewer.model.map.layout.alias.SpeciesAliasComparator=info
log4j.logger.lcsb.mapviewer.model.map.layout.alias.AliasComparator=info
log4j.logger.lcsb.mapviewer.model.map.layout.alias.ComplexAliasComparator=info
log4j.logger.lcsb.mapviewer.model.map.layout.alias.CompartmentAliasComparator=info
log4j.logger.lcsb.mapviewer.model.map.reaction.ReactionNodeComparator=info
log4j.logger.lcsb.mapviewer.model.map.reaction.ReactionComparator=info
log4j.logger.lcsb.mapviewer.model.map.reaction.NodeOperatorComparator=info
log4j.logger.lcsb.mapviewer.model.map.reaction.AbstractNodeComparator=info
log4j.logger.lcsb.mapviewer.model.map.model.ModelComparator=info
log4j.logger.lcsb.mapviewer.model.graphics.PolylineDataComparator=info
log4j.logger.lcsb.mapviewer.model.map.kinetics.SbmlUnitComparator = info
\ No newline at end of file
<?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="46.0" y="300.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="s1">
<celldesigner:activity>inactive</celldesigner:activity>
<celldesigner:bounds x="361.0" y="220.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="s1">