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

parse and draw process rectangle that does not have to be on the center of line

parent f37b3e83
Pipeline #28878 failed with stage
in 12 minutes and 32 seconds
......@@ -10,6 +10,8 @@ minerva (15.1.0) unstable; urgency=medium
defining font color
* Small improvement: when SBML with layout contains different glyph text and
species name those two values are assigned to name and full name (#1275)
* Small improvement: process rectangle can be specified in SBML with reaction
bounding box (#1292)
* Bug fix: export to image from selected polygon contained all elements
inside rectangle bounded by the polygon coordinates (#1096)
* Bug fix: continuous refreshing list of project when uploading/removing
......
......@@ -116,7 +116,8 @@ public class ReactionConverter extends BioEntityConverter<Reaction> {
* @param graphics
* where the rectangle should be drawn
*/
protected void drawRectangleData(final PolylineData line, final ReactionRect insideType, final Graphics2D graphics) {
protected void drawRectangleData(final PolylineData line, Point2D processCoordinates, final ReactionRect insideType,
final Graphics2D graphics) {
Color color = graphics.getColor();
graphics.setColor(line.getColor());
......@@ -149,13 +150,21 @@ public class ReactionConverter extends BioEntityConverter<Reaction> {
PolylineData preRectangleLine = line.getSubline(0, line.getPoints().size() / 2);
arrowTransformation.drawLine(preRectangleLine, graphics);
}
double pointX = (startPoint.getX() + endPoint.getX()) / 2;
double pointY = (startPoint.getY() + endPoint.getY()) / 2;
Point2D centerPoint = new Point2D.Double(pointX, pointY);
double dx = endPoint.getX() - startPoint.getX();
double dy = endPoint.getY() - startPoint.getY();
double angle = Math.atan2(dy, dx);
if (processCoordinates != null) {
angle = 0;
pointX = processCoordinates.getX();
pointY = processCoordinates.getY();
graphics.draw(new Line2D.Double(startPoint, endPoint));
}
Point2D centerPoint = new Point2D.Double(pointX, pointY);
if (insideType == null) {
Point2D topPoint = new Point2D.Double(pointX + RECT_SIZE / 2, pointY);
topPoint = new PointTransformation().rotatePoint(topPoint, angle, centerPoint);
......@@ -237,7 +246,7 @@ public class ReactionConverter extends BioEntityConverter<Reaction> {
}
// in the end we draw rectangle in the middle
drawRectangleData(reaction.getLine(), reaction.getReactionRect(), graphics);
drawRectangleData(reaction.getLine(), reaction.getProcessCoordinates(), reaction.getReactionRect(), graphics);
graphics.setColor(color);
}
......@@ -360,7 +369,8 @@ public class ReactionConverter extends BioEntityConverter<Reaction> {
if (sbgnFormat) {
radius *= SBGN_RADIUS_MULTIPLIER;
} else if (operator instanceof AndOperator || operator instanceof SplitOperator
|| operator instanceof DissociationOperator || operator instanceof AssociationOperator || operator instanceof TruncationOperator) {
|| operator instanceof DissociationOperator || operator instanceof AssociationOperator
|| operator instanceof TruncationOperator) {
radius = 1.5;
fillColor = operator.getLine().getColor();
}
......
......@@ -8,7 +8,8 @@ import static org.mockito.Mockito.verify;
import java.awt.*;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.imageio.ImageIO;
......@@ -440,86 +441,66 @@ public class ReactionConverterTest extends GraphicsTestFunctions {
@Test
public void testDrawRectangleDataSimple() throws Exception {
try {
Graphics2D graphics = createGraphicsMock();
ReactionConverter rc = new ReactionConverter(colorExtractor);
PolylineData line = new PolylineData(new Point2D.Double(10, 20),
new Point2D.Double(10 + ReactionConverter.RECT_SIZE, 20));
Graphics2D graphics = createGraphicsMock();
ReactionConverter rc = new ReactionConverter(colorExtractor);
rc.drawRectangleData(line, ReactionRect.RECT_EMPTY, graphics);
PolylineData line = new PolylineData(new Point2D.Double(10, 20),
new Point2D.Double(10 + ReactionConverter.RECT_SIZE, 20));
Mockito.verify(graphics, times(1)).fill(any(Shape.class));
Mockito.verify(graphics, times(1)).draw(any(Shape.class));
rc.drawRectangleData(line, null, ReactionRect.RECT_EMPTY, graphics);
} catch (Exception e) {
throw e;
}
Mockito.verify(graphics, times(1)).fill(any(Shape.class));
Mockito.verify(graphics, times(1)).draw(any(Shape.class));
}
@Test
public void testDrawRectangleDataWithLineAround() throws Exception {
try {
Graphics2D graphics = createGraphicsMock();
ReactionConverter rc = new ReactionConverter(colorExtractor);
Graphics2D graphics = createGraphicsMock();
ReactionConverter rc = new ReactionConverter(colorExtractor);
PolylineData line = new PolylineData(new Point2D.Double(10, 20),
new Point2D.Double(10 + ReactionConverter.RECT_SIZE + 100, 20));
PolylineData line = new PolylineData(new Point2D.Double(10, 20),
new Point2D.Double(10 + ReactionConverter.RECT_SIZE + 100, 20));
rc.drawRectangleData(line, ReactionRect.RECT_EMPTY, graphics);
rc.drawRectangleData(line, null, ReactionRect.RECT_EMPTY, graphics);
Mockito.verify(graphics, times(1)).fill(any(Shape.class));
Mockito.verify(graphics, times(3)).draw(any(Shape.class));
} catch (Exception e) {
throw e;
}
Mockito.verify(graphics, times(1)).fill(any(Shape.class));
Mockito.verify(graphics, times(3)).draw(any(Shape.class));
}
@Test
public void testDrawRectangleDataWithOneSidePolyLineAround() throws Exception {
try {
Graphics2D graphics = createGraphicsMock();
ReactionConverter rc = new ReactionConverter(colorExtractor);
PolylineData line = new PolylineData();
line.addPoint(new Point2D.Double(10, 20));
line.addPoint(new Point2D.Double(100, 20));
line.addPoint(new Point2D.Double(200, 20));
Graphics2D graphics = createGraphicsMock();
ReactionConverter rc = new ReactionConverter(colorExtractor);
rc.drawRectangleData(line, ReactionRect.RECT_EMPTY, graphics);
PolylineData line = new PolylineData();
line.addPoint(new Point2D.Double(10, 20));
line.addPoint(new Point2D.Double(100, 20));
line.addPoint(new Point2D.Double(200, 20));
Mockito.verify(graphics, times(1)).fill(any(Shape.class));
Mockito.verify(graphics, times(4)).draw(any(Shape.class));
rc.drawRectangleData(line, null, ReactionRect.RECT_EMPTY, graphics);
} catch (Exception e) {
throw e;
}
Mockito.verify(graphics, times(1)).fill(any(Shape.class));
Mockito.verify(graphics, times(4)).draw(any(Shape.class));
}
@Test
public void testDrawRectangleDataWithPolyLineAround() throws Exception {
try {
Graphics2D graphics = createGraphicsMock();
ReactionConverter rc = new ReactionConverter(colorExtractor);
PolylineData line = new PolylineData();
line.addPoint(new Point2D.Double(10, 20));
line.addPoint(new Point2D.Double(100, 20));
line.addPoint(new Point2D.Double(100, 200));
line.addPoint(new Point2D.Double(200, 200));
line.addPoint(new Point2D.Double(200, 300));
line.addPoint(new Point2D.Double(300, 300));
line.addPoint(new Point2D.Double(300, 400));
rc.drawRectangleData(line, ReactionRect.RECT_EMPTY, graphics);
Mockito.verify(graphics, times(1)).fill(any(Shape.class));
Mockito.verify(graphics, times(5)).draw(any(Shape.class));
} catch (Exception e) {
throw e;
}
Graphics2D graphics = createGraphicsMock();
ReactionConverter rc = new ReactionConverter(colorExtractor);
PolylineData line = new PolylineData();
line.addPoint(new Point2D.Double(10, 20));
line.addPoint(new Point2D.Double(100, 20));
line.addPoint(new Point2D.Double(100, 200));
line.addPoint(new Point2D.Double(200, 200));
line.addPoint(new Point2D.Double(200, 300));
line.addPoint(new Point2D.Double(300, 300));
line.addPoint(new Point2D.Double(300, 400));
rc.drawRectangleData(line, null, ReactionRect.RECT_EMPTY, graphics);
Mockito.verify(graphics, times(1)).fill(any(Shape.class));
Mockito.verify(graphics, times(5)).draw(any(Shape.class));
}
}
......@@ -210,6 +210,7 @@ public class SbmlReactionParser extends SbmlBioEntityParser {
reactionWithLayout.addNode(operator);
}
reactionWithLayout.setLine(extractCurve(glyph, reactionWithLayout, null));
reactionWithLayout.setProcessCoordinates(extractProcessCoordinates(glyph));
createCenterLineForReaction(reactionWithLayout);
assignRenderDataToReaction(glyph, reactionWithLayout);
......@@ -244,6 +245,18 @@ public class SbmlReactionParser extends SbmlBioEntityParser {
}
}
private Point2D extractProcessCoordinates(ReactionGlyph glyph) {
if (glyph.getCurve() != null && glyph.getBoundingBox() != null) {
BoundingBox box = glyph.getBoundingBox();
if (box.getDimensions() != null && box.getPosition() != null) {
return new Point2D.Double(box.getPosition().getX() + box.getDimensions().getWidth() / 2,
box.getPosition().getY() + box.getDimensions().getHeight() / 2);
}
}
return null;
}
/**
* Creates center line for assembled reaction with operators.
*
......
......@@ -259,9 +259,11 @@ public class SbmlParserTest extends SbmlTestFunctions {
Model m = parser.createModel(new ConverterParams().filename("testFiles/small/kinetics_with_reference.xml"));
assertNotNull(m.getReactions().iterator().next().getKinetics());
}
@Test
public void testLayoutContainDuplicatesOfReactionNode() throws Exception {
Model m = parser.createModel(new ConverterParams().filename("testFiles/layoutExample/reaction_with_duplicated_product.xml"));
Model m = parser
.createModel(new ConverterParams().filename("testFiles/layoutExample/reaction_with_duplicated_product.xml"));
assertNotNull(m.getReactions().iterator().next().getKinetics());
}
......@@ -273,4 +275,11 @@ public class SbmlParserTest extends SbmlTestFunctions {
assertEquals("Synuclein Alpha", species.getFullName());
}
@Test
public void testExtractProcessCoordinates() throws Exception {
Model m = parser.createModel(new ConverterParams().filename("testFiles/small/process_coordinates.xml"));
Reaction reaction = m.getReactions().iterator().next();
assertNotNull(reaction.getProcessCoordinates());
}
}
<?xml version='1.0' encoding='utf-8' standalone='no'?>
<sbml xmlns="http://www.sbml.org/sbml/level3/version1/core" layout:required="false" level="3" version="1" xmlns:layout="http://www.sbml.org/sbml/level3/version1/layout/version1">
<notes>
<annotation>
<p xmlns="http://www.w3.org/1999/xhtml">SBML generated from Reactome version 0 on 6/8/20 4:54 PM using JSBML version 1.5.</p>
</annotation>
</notes>
<model id="pathway_9678108" metaid="metaid_0" name="SARS-CoV-1 Infection">
<notes>
<p xmlns="http://www.w3.org/1999/xhtml">The SARS-CoV-1 coronavirus is the causative agent of the outbreak of severe acute respiratory syndrome in 2003 that caused 8,098 known cases of the disease and 774 deaths. The molecular events involved in viral infection and the response of the human host to it have since been studied in detail and are annotated here (de Wit et al. 2016; Marra et al. 2003). The SARS-CoV-1 viral infection pathway here uses entries listed in the UniProt "Human SARS coronavirus (SARS-CoV) (Severe acute respiratory syndrome coronavirus)" taxonomy.SARS-CoV-1 infection begins with the binding of viral S (spike) protein to cell surface angiotensin converting enzyme 2 (ACE2) and endocytosis of the bound virion. Within the endocytic vesicle, host proteases mediate cleavage of S protein into S1 and S2 fragments, leading to S2-mediated fusion of the viral and host endosome membranes and release of the viral capsid into the host cell cytosol. The capsid is uncoated to free the viral genomic RNA, whose cap-dependent translation produces polyprotein pp1a and, by means of a 1-base frameshift, polyprotein pp1ab. Autoproteolytic cleavage of pp1a and pp1ab generates 15 or 16 nonstructural proteins (nsps) with various functions. Importantly, the RNA dependent RNA polymerase (RdRP) activity is encoded in nsp12. Nsp3, 4, and 6 induce rearrangement of the cellular endoplasmic reticulum membrane to form cytosolic double membrane vesicles (DMVs) where the viral replication transcription complex is assembled and anchored. With viral genomic RNA as a template, viral replicase-transcriptase synthesizes a full length negative sense antigenome, which in turn serves as a template for the synthesis of new genomic RNA. The replicase-transcriptase can also switch template during discontinuous transcription of the genome at transcription regulated sequences to produce a nested set of negative-sense subgenomic (sg) RNAs, which are used as templates for the synthesis of positive-sense sgRNAs that are translated to generate viral proteins. Finally, viral particle assembly occurs in the ER Golgi intermediate compartment (ERGIC). Viral M protein provides the scaffold for virion morphogenesis (Fung and Liu 2019; Masters 2006).</p>
</notes>
<annotation>
</annotation>
<layout:listOfLayouts xmlns:layout="http://www.sbml.org/sbml/level3/version1/layout/version1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<layout:layout>
<layout:listOfCompartmentGlyphs>
</layout:listOfCompartmentGlyphs>
<layout:listOfSpeciesGlyphs>
<layout:speciesGlyph layout:id="layout_714" layout:species="species_9686311">
<layout:boundingBox>
<layout:position layout:x="1971" layout:y="735" />
<layout:dimensions layout:height="97" layout:width="136" />
</layout:boundingBox>
</layout:speciesGlyph>
<layout:speciesGlyph layout:id="layout_842" layout:species="species_9686703">
<layout:boundingBox>
<layout:position layout:x="1982" layout:y="1142" />
<layout:dimensions layout:height="92" layout:width="136" />
</layout:boundingBox>
</layout:speciesGlyph>
<layout:speciesGlyph layout:id="layout_893" layout:species="species_9686707">
<layout:boundingBox>
<layout:position layout:x="2184" layout:y="785" />
<layout:dimensions layout:height="22" layout:width="68" />
</layout:boundingBox>
</layout:speciesGlyph>
<layout:speciesGlyph layout:id="layout_1045" layout:species="species_9681532">
<layout:boundingBox>
<layout:position layout:x="2360" layout:y="774" />
<layout:dimensions layout:height="50" layout:width="83" />
</layout:boundingBox>
</layout:speciesGlyph>
</layout:listOfSpeciesGlyphs>
<layout:listOfReactionGlyphs>
<layout:reactionGlyph layout:id="layout_892" layout:reaction="reaction_9686731">
<layout:boundingBox>
<layout:position layout:x="2050" layout:y="998" />
<layout:dimensions layout:height="6" layout:width="6" />
</layout:boundingBox>
<layout:curve>
<layout:listOfCurveSegments>
<layout:curveSegment xsi:type="LineSegment">
<layout:start layout:x="2047" layout:y="918" />
<layout:end layout:x="2053" layout:y="1001" />
</layout:curveSegment>
<layout:curveSegment xsi:type="LineSegment">
<layout:start layout:x="2053" layout:y="1001" />
<layout:end layout:x="2051" layout:y="1070" />
</layout:curveSegment>
</layout:listOfCurveSegments>
</layout:curve>
<layout:listOfSpeciesReferenceGlyphs>
<layout:speciesReferenceGlyph layout:id="layout_892_substrate_0" layout:speciesGlyph="layout_714">
<layout:curve>
<layout:listOfCurveSegments>
<layout:curveSegment xsi:type="LineSegment">
<layout:start layout:x="2047" layout:y="918" />
<layout:end layout:x="2042" layout:y="835" />
</layout:curveSegment>
</layout:listOfCurveSegments>
</layout:curve>
</layout:speciesReferenceGlyph>
<layout:speciesReferenceGlyph layout:id="layout_892_product_0" layout:speciesGlyph="layout_842">
<layout:curve>
<layout:listOfCurveSegments>
<layout:curveSegment xsi:type="LineSegment">
<layout:start layout:x="2051" layout:y="1070" />
<layout:end layout:x="2050" layout:y="1139" />
</layout:curveSegment>
</layout:listOfCurveSegments>
</layout:curve>
</layout:speciesReferenceGlyph>
<layout:speciesReferenceGlyph layout:id="layout_892_modifier_0" layout:speciesGlyph="layout_893">
<layout:curve>
<layout:listOfCurveSegments>
<layout:curveSegment xsi:type="LineSegment">
<layout:start layout:x="2209" layout:y="810" />
<layout:end layout:x="2053" layout:y="1001" />
</layout:curveSegment>
</layout:listOfCurveSegments>
</layout:curve>
</layout:speciesReferenceGlyph>
<layout:speciesReferenceGlyph layout:id="layout_892_inhibitor_0" layout:speciesGlyph="layout_1045">
<layout:curve>
<layout:listOfCurveSegments>
<layout:curveSegment xsi:type="LineSegment">
<layout:start layout:x="2369" layout:y="827" />
<layout:end layout:x="2148" layout:y="1000" />
</layout:curveSegment>
<layout:curveSegment xsi:type="LineSegment">
<layout:start layout:x="2148" layout:y="1000" />
<layout:end layout:x="2053" layout:y="1001" />
</layout:curveSegment>
</layout:listOfCurveSegments>
</layout:curve>
</layout:speciesReferenceGlyph>
</layout:listOfSpeciesReferenceGlyphs>
</layout:reactionGlyph>
</layout:listOfReactionGlyphs>
<layout:listOfTextGlyphs>
</layout:listOfTextGlyphs>
</layout:layout>
</layout:listOfLayouts>
<listOfCompartments>
<compartment constant="true" id="default" metaid="metaid_2" name="endoplasmic reticulum lumen" sboTerm="SBO:0000290">
<annotation>
</annotation>
</compartment>
</listOfCompartments>
<listOfSpecies>
<species boundaryCondition="false" compartment="default" constant="false" hasOnlySubstanceUnits="false" id="species_9681532" metaid="metaid_102" name="TMPRSS2:TMPRSS2 inhibitors" sboTerm="SBO:0000297">
<notes>
<p xmlns="http://www.w3.org/1999/xhtml">Derived from a Reactome Complex. Here is Reactomes nested structure for this complex: (10733, O15393, 6432, 10732). Reactome uses a nested structure for complexes, which cannot be fully represented in SBML Level 3 Version 1 core</p>
</notes>
<annotation>
</annotation>
</species>
<species boundaryCondition="false" compartment="default" constant="false" hasOnlySubstanceUnits="false" id="species_9686707" metaid="metaid_159" name="TMPRSS2" sboTerm="SBO:0000252">
<notes>
<p xmlns="http://www.w3.org/1999/xhtml">Derived from a Reactome EntityWithAccessionedSequence. This is a protein</p>
</notes>
<annotation>
</annotation>
</species>
<species boundaryCondition="false" compartment="default" constant="false" hasOnlySubstanceUnits="false" id="species_9686703" metaid="metaid_64" name="S1:S2:M:E:encapsidated SARS coronavirus genomic RNA: 7a:O-glycosyl 3a tetramer" sboTerm="SBO:0000297">
<notes>
<p xmlns="http://www.w3.org/1999/xhtml">Derived from a Reactome Complex. Here is Reactomes nested structure for this complex: (1200xP59596, 15xP59637, NC_004718.3, 300xP59595, P59635, 4xP59632, 450xP59594). Reactome uses a nested structure for complexes, which cannot be fully represented in SBML Level 3 Version 1 core</p>
</notes>
<annotation>
</annotation>
</species>
<species boundaryCondition="false" compartment="default" constant="false" hasOnlySubstanceUnits="false" id="species_9686311" metaid="metaid_207" name="S3:M:E:encapsidated SARS coronavirus genomic RNA: 7a:O-glycosyl 3a tetramer:glycosylated-ACE2" sboTerm="SBO:0000297">
<notes>
<p xmlns="http://www.w3.org/1999/xhtml">Derived from a Reactome Complex. Here is Reactomes nested structure for this complex: (1200xP59596, Q9BYF1, NC_004718.3, 15xP59637, 300xP59595, P59635, 4xP59632, 225xP59594). Reactome uses a nested structure for complexes, which cannot be fully represented in SBML Level 3 Version 1 core</p>
</notes>
<annotation>
</annotation>
</species>
</listOfSpecies>
<listOfReactions>
<reaction compartment="default" fast="false" id="reaction_9686731" metaid="metaid_272" name="TMPRSS2 Mediated SARS-CoV-1 Spike Protein Cleavage and Endocytosis" reversible="false">
<notes>
<p xmlns="http://www.w3.org/1999/xhtml">Transmembrane protease serine 2 (TMPRSS2), associated with the plasma membrane of the host cell, mediates the hydrolytic cleavage of SARS-CoV-1 Spike (S) protein component of the viral membrane-associate S3:M:E:encapsidated SARS coronavirus genomic RNA: 7a:O-glycosyl 3a tetramer complex associated with ACE2 (Matsuyama et al. 2010; Glowacka et al. 2011; Shulla et al. 2011).</p>
</notes>
<annotation>
</annotation>
<listOfReactants>
<speciesReference constant="true" id="speciesreference_9686731_input_9686311" sboTerm="SBO:0000010" species="species_9686311" stoichiometry="1" />
</listOfReactants>
<listOfProducts>
<speciesReference constant="true" id="speciesreference_9686731_output_9686703" sboTerm="SBO:0000011" species="species_9686703" stoichiometry="1" />
</listOfProducts>
<listOfModifiers>
<modifierSpeciesReference id="modifierspeciesreference_9686731_catalyst_9686707" sboTerm="SBO:0000013" species="species_9686707" />
<modifierSpeciesReference id="modifierspeciesreference_9686731_negativeregulator_9681532" species="species_9681532">
<notes>
<p xmlns="http://www.w3.org/1999/xhtml">This describes an Event/CatalystActivity that is negatively regulated by the Regulator (e.g., allosteric inhibition, competitive inhibition</p>
</notes>
</modifierSpeciesReference>
</listOfModifiers>
</reaction>
</listOfReactions>
</model>
</sbml>
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment