Commit 85db0ad2 authored by Piotr Gawron's avatar Piotr Gawron
Browse files

Merge branch 'release-14.0.8-issues' into 'devel_14.0.x'

bug fixes for 14.0.8

See merge request minerva/core!1046
parents a4409a4c 0e377ab0
......@@ -318,6 +318,8 @@ build_debian_package:
dependencies:
- build_war
artifacts:
# you cannot enforce never here yet
expire_in: 1000 yrs
paths:
- "debian/*.deb"
script:
......@@ -432,6 +434,8 @@ build_rpm:
tags:
- privileged
artifacts:
# you cannot enforce never here yet
expire_in: 1000 yrs
paths:
- "rpm/rpmbuildtemp/RPMS/noarch/minerva-*.rpm"
script:
......
minerva (14.0.8) stable; urgency=medium
* Bug fix: API didn't allow to upload pluins with local url (#1084,
regression 14.0.7)
* Bug fix: upload of data overlay with two entries having different uniprot
identifier but pointing to the same gene crashed (#1083)
* Bug fix: don't allow to remove plugin twice (#1081)
* Bug fix: upload of SBML file with very short reaction length could produce
a map that couldn't be exported to SBML anymore (#1078)
* Bug fix: import of structural state from SBGN-ML PD that cannot be
normalized to residue is changed into structural state without losing
information (#1062)
* Bug fix: import of stimulation modifiers from SBGN-ML crashed converter
(#1063)
* Bug fix: export to SBGN files created from newt source produced corrupted
disconnected reactions
* Bug fix: upload from zip file allowed empty overlay name (#1065)
* Bug fix: genome browser slider didn't work properly in Safari on
non-default Browser zoom level (#1048)
* Bug fix: project without background overlay but with some custom data
overlays crashed with an error (#1066)
* Bug fix: when session expires updating options in configuration panel threw
unhandled error (#1068)
-- Piotr Gawron <piotr.gawron@uni.lu> Tue, 28 Jan 2020 11:00:00 +0200
minerva (14.0.7) stable; urgency=high
* Bug fix: API allowed to provide malformed plugin url that could be used for
xss attack (#1073)
......
......@@ -10,8 +10,8 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.sbgn.*;
import org.sbgn.bindings.*;
import org.sbgn.bindings.Map;
import org.sbgn.bindings.Arc.*;
import org.sbgn.bindings.Map;
import lcsb.mapviewer.common.comparator.DoubleComparator;
import lcsb.mapviewer.common.exception.InvalidArgumentException;
......@@ -192,7 +192,7 @@ public class SbgnmlXmlExporter {
}
}
sourceTargetMap.put(newGlyph.getId(), newGlyph);
sourceTargetMap.put(element.getElementId(), newGlyph);
return newGlyph;
}
......@@ -202,7 +202,13 @@ public class SbgnmlXmlExporter {
glyph.setClazz(GlyphClazz.STATE_VARIABLE.getClazz());
Glyph.State state = new Glyph.State();
state.setValue(structuralState);
if (structuralState.indexOf("@") >= 0) {
state.setValue(structuralState.substring(0, structuralState.indexOf("@")));
state.setVariable(structuralState.substring(structuralState.indexOf("@") + 1));
} else {
state.setValue(structuralState);
}
glyph.setState(state);
Bbox bbox = new Bbox();
......@@ -838,6 +844,7 @@ public class SbgnmlXmlExporter {
if (!node.getLine().getEndAtd().getArrowType().equals(ArrowType.NONE)) {
arc.setTarget(sourceTargetMap.get(node.getReaction().getIdReaction()));
} else {
boolean found = false;
for (NodeOperator operator : node.getReaction().getOperators()) {
if (operator.getInputs().contains(node)) {
if (!parsedOperators.contains(operator)) {
......@@ -845,8 +852,13 @@ public class SbgnmlXmlExporter {
glyphList.add(newOperator);
}
arc.setTarget(sourceTargetMap.get(operatorIds.get(operator).concat(".1")));
found = true;
}
}
if (!found) {
throw new InvalidArgumentException(
new ElementUtils().getElementTag((Modifier) node) + "Problem with exportin modifier");
}
}
} else if (node instanceof NodeOperator) {
if ((node instanceof DissociationOperator) || (node instanceof AssociationOperator)) {
......@@ -867,7 +879,7 @@ public class SbgnmlXmlExporter {
}
}
}
List<Point2D> arcPoints = node.getLine().getPoints();
Start start = new Start();
if ((node instanceof Product) || (node instanceof NodeOperator)) {
......
package lcsb.mapviewer.converter.model.sbgnml;
import java.awt.*;
import java.awt.Color;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.*;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.sbgn.*;
import org.sbgn.bindings.*;
import org.sbgn.bindings.Arc.*;
import org.sbgn.bindings.Map;
import lcsb.mapviewer.common.comparator.DoubleComparator;
import lcsb.mapviewer.common.exception.InvalidArgumentException;
......@@ -390,8 +390,9 @@ public class SbgnmlXmlParser {
* arc to be parsed
* @param model
* model to be updated
* @throws InvalidInputDataExecption
*/
private void parseArc(Arc a, Model model) {
private void parseArc(Arc a, Model model) throws InvalidInputDataExecption {
switch (ArcClazz.fromClazz(a.getClazz())) {
case CONSUMPTION:
Port arcTargetPort = (Port) a.getTarget();
......@@ -422,35 +423,56 @@ public class SbgnmlXmlParser {
case MODULATION:
case NECESSARY_STIMULATION:
case STIMULATION:
Glyph targetGlyph = (Glyph) a.getTarget();
if (GlyphClazz.fromClazz(targetGlyph.getClazz()).equals(GlyphClazz.PHENOTYPE)) {
if (!(a.getSource() instanceof Glyph)) {
logger.warn("Invalid phenotype arc: " + a.getId());
break;
}
try {
parsePhenotypeArc(a, model);
} catch (Exception e) {
logger.warn(e.getMessage(), e);
}
break;
}
if (a.getSource() instanceof Glyph) {
Glyph sourceGlyph = (Glyph) a.getSource();
if (GlyphClazz.fromClazz(sourceGlyph.getClazz()).equals(GlyphClazz.PHENOTYPE)
&& (model.getElementByElementId(targetGlyph.getId()) instanceof Species)) {
if (a.getTarget() instanceof Glyph) {
Glyph targetGlyph = (Glyph) a.getTarget();
if (GlyphClazz.fromClazz(targetGlyph.getClazz()).equals(GlyphClazz.PHENOTYPE)) {
if (!(a.getSource() instanceof Glyph)) {
logger.warn("Invalid phenotype arc: " + a.getId());
break;
}
try {
parsePhenotypeArc(a, model);
} catch (InvalidArgumentException ex) {
logger.warn("The arc " + a.getId() + " of class " + a.getClazz() + " is not a valid reduced notation arc.");
} catch (Exception e) {
logger.warn(e.getMessage(), e);
}
break;
}
}
for (Process p : processes) {
if (p.getCentralPoint().getId().equals(targetGlyph.getId())) {
p.addInfluenceArc(a);
break;
if (a.getSource() instanceof Glyph) {
Glyph sourceGlyph = (Glyph) a.getSource();
if (GlyphClazz.fromClazz(sourceGlyph.getClazz()).equals(GlyphClazz.PHENOTYPE)
&& (model.getElementByElementId(targetGlyph.getId()) instanceof Species)) {
try {
parsePhenotypeArc(a, model);
} catch (InvalidArgumentException ex) {
logger
.warn("The arc " + a.getId() + " of class " + a.getClazz() + " is not a valid reduced notation arc.");
}
break;
}
}
for (Process p : processes) {
if (p.getCentralPoint().getId().equals(targetGlyph.getId())) {
p.addInfluenceArc(a);
break;
}
}
} else {
Port targetPort = (Port) a.getTarget();
boolean found = false;
for (Process p : processes) {
Set<String> ids = new HashSet<>();
ids.add(p.getCentralPoint().getId());
for (Port port : p.getCentralPoint().getPort()) {
ids.add(port.getId());
}
if (ids.contains(targetPort.getId())) {
p.addInfluenceArc(a);
found = true;
break;
}
}
if (!found) {
throw new InvalidInputDataExecption("Problem with processing arc: " + a.getId());
}
}
break;
......@@ -584,19 +606,42 @@ public class SbgnmlXmlParser {
for (Glyph child : children) {
if (GlyphClazz.fromClazz(child.getClazz()).equals(GlyphClazz.STATE_VARIABLE)) {
if (child.getState() == null || child.getState().getVariable() != null) {
try {
parseStateVariable(child, newSpecies);
} catch (Exception ex) {
logger.warn(ex.getMessage());
Residue residue = stateVariableToResidue(child);
if (residue != null) {
if (newSpecies instanceof Protein) {
((Protein) newSpecies).addResidue(residue);
} else if (newSpecies instanceof Complex) {
String state = createStructuralState(child);
if (state != null) {
Complex complex = (Complex) newSpecies;
complex.setStructuralState(state);
}
} else {
logger.warn("Only macromolecule elements can have state variables.");
}
} else {
String state = createStructuralState(child);
if (state != null) {
if (newSpecies instanceof Protein) {
((Protein) newSpecies).setStructuralState(state);
} else if (newSpecies instanceof Complex) {
Complex complex = (Complex) newSpecies;
complex.setStructuralState(state);
} else {
logger.warn("Only macromolecule elements can have state.");
}
}
}
} else {
String structuralState = child.getState().getValue();
if (newSpecies instanceof Protein) {
Protein protein = (Protein) newSpecies;
protein.setStructuralState(structuralState);
} else if (newSpecies instanceof Complex) {
Complex complex = (Complex) newSpecies;
complex.setStructuralState(structuralState);
String structuralState = createStructuralState(child);
if (structuralState != null) {
if (newSpecies instanceof Protein) {
Protein protein = (Protein) newSpecies;
protein.setStructuralState(structuralState);
} else if (newSpecies instanceof Complex) {
Complex complex = (Complex) newSpecies;
complex.setStructuralState(structuralState);
}
}
}
}
......@@ -608,6 +653,63 @@ public class SbgnmlXmlParser {
}
/**
* Method used to parse state variable.
*
* @param glyph
* unit of information glyph from sbgn-ml file
* @throws Exception
* Exception is thrown if state variable is parsed for species other
* than Protein
*/
private Residue stateVariableToResidue(Glyph glyph) {
if (glyph.getState() != null && (glyph.getState().getVariable() == null
|| glyph.getState().getVariable().trim().isEmpty())) {
return null;
}
Residue mr = new Residue();
mr.setIdModificationResidue(glyph.getId());
if (glyph.getState() != null) {
// If State variable consists of value and variable
mr.setName(glyph.getState().getVariable());
for (ModificationState ms : ModificationState.values()) {
if (ms.getAbbreviation().equals(glyph.getState().getValue())) {
mr.setState(ms);
}
}
}
if (mr.getState() == null) {
return null;
}
// Compute the angle from coordinates and dimensions
double x = glyph.getBbox().getX() + glyph.getBbox().getW() / 2;
double y = glyph.getBbox().getY() + glyph.getBbox().getH() / 2;
mr.setPosition(new Point2D.Double(x, y));
return mr;
}
private String createStructuralState(Glyph glyph) {
if (glyph.getState() == null) {
return null;
}
String result = "";
if (glyph.getState().getValue() != null) {
result += glyph.getState().getValue();
}
if (glyph.getState().getVariable() != null && !glyph.getState().getVariable().isEmpty()) {
result += "@";
result += glyph.getState().getVariable();
}
return result;
}
/**
* {@link ModificationResidue} in element might have slightly off coordinates
* (due to different symbol shapes). For that we need to align them to match our
......@@ -751,45 +853,6 @@ public class SbgnmlXmlParser {
return rna;
}
/**
* Method used to parse state variable.
*
* @param unitOfInformationGlyph
* unit of information glyph from sbgn-ml file
* @param species
* species that the unit of information considers
* @throws Exception
* Exception is thrown if state variable is parsed for species other
* than Protein
*/
private void parseStateVariable(Glyph unitOfInformationGlyph, Species species) {
if (!(species instanceof Protein)) {
throw new InvalidArgumentException("Only macromolecule elements can have state variables.");
}
Protein protein = (Protein) species;
Residue mr = new Residue();
mr.setSpecies(protein);
mr.setIdModificationResidue(unitOfInformationGlyph.getId());
if (unitOfInformationGlyph.getState() != null) {
// If State variable consists of value and variable
mr.setName(unitOfInformationGlyph.getState().getVariable());
for (ModificationState ms : ModificationState.values()) {
if (ms.getAbbreviation().equals(unitOfInformationGlyph.getState().getValue())) {
mr.setState(ms);
}
}
}
// Compute the angle from coordinates and dimensions
double x = unitOfInformationGlyph.getBbox().getX() + unitOfInformationGlyph.getBbox().getW() / 2;
double y = unitOfInformationGlyph.getBbox().getY() + unitOfInformationGlyph.getBbox().getH() / 2;
mr.setPosition(new Point2D.Double(x, y));
protein.addResidue(mr);
}
/**
* Method used for parsing units of information.
*
......@@ -1144,6 +1207,7 @@ public class SbgnmlXmlParser {
throw new InvalidArgumentException(
p.getCentralPoint().getId() + ": The process must have at least one outgoing arc.");
}
p.setProductsPort((Port) p.getProductArcs().get(0).getSource());
for (Arc productArc : p.getProductArcs()) {
if (!((Port) productArc.getSource()).equals(p.getProductsPort())) {
......
......@@ -3,6 +3,7 @@ package lcsb.mapviewer.converter.model.sbgnml;
import static org.junit.Assert.*;
import java.awt.geom.Point2D;
import java.io.InputStream;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
......@@ -105,4 +106,45 @@ public class SbgnmlXmlParserTest2 extends SbgnmlTestFunctions {
assertEquals(p2.getLine().getBeginPoint(), outputOperator.getLine().getBeginPoint());
}
@Test
public void testImportExportStateWithVariable() throws Exception {
Converter converter = new SbgnmlXmlConverter();
Model model = converter.createModel(
new ConverterParams().filename("testFiles/sbgnmlParserTestFiles/sbgnmlFiles/state_with_variable.sbgn"));
String sbgn = converter.model2String(model);
assertTrue("State variable is missing", sbgn.contains("state variable"));
assertTrue("State variable doesn't contain variable", sbgn.contains("variable=\"g\""));
}
@Test
public void testStimulationModification() throws Exception {
Converter converter = new SbgnmlXmlConverter();
Model model = converter.createModel(
new ConverterParams().filename("testFiles/sbgnmlParserTestFiles/sbgnmlFiles/stimulation_modification.sbgn"));
for (Reaction r : model.getReactions()) {
assertEquals(1, r.getModifiers().size());
}
}
@Test
public void testExportStimulationModification() throws Exception {
Converter converter = new SbgnmlXmlConverter();
Model model = converter.createModel(
new ConverterParams().filename("testFiles/sbgnmlParserTestFiles/sbgnmlFiles/stimulation_modification.sbgn"));
InputStream is = converter.model2InputStream(model);
Model model2 = converter.createModel(new ConverterParams().inputStream(is));
for (Reaction r : model2.getReactions()) {
assertEquals(1, r.getModifiers().size());
}
}
}
<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<sbgn xmlns="http://sbgn.org/libsbgn/0.2">
<map language="process description">
<glyph id="nwtN_a529363c-d32c-4b03-bce7-1b79e6066b2d" class="complex">
<label text="complex"/>
<bbox x="1001.671875" y="148.375" w="63.25" h="33.25"/>
<glyph id="nwtSV_439e2238-3d15-46da-aa67-77a1119a3552" class="state variable">
<state value="xxx" variable="g"/>
<bbox x="1049.1945435615057" y="142.375" w="22.39697265625" h="12"/>
</glyph>
<glyph id="nwtN_d5109825-20cd-40f4-a9ba-1fd707c6b2a1" class="macromolecule">
<label text="macromolecule"/>
<bbox x="1018.296875" y="165" w="60" h="30"/>
</glyph>
</glyph>
</map>
</sbgn>
\ No newline at end of file
<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<sbgn xmlns="http://sbgn.org/libsbgn/0.2">
<map language="process description">
<extension>
<renderInformation
xmlns="http://www.sbml.org/sbml/level3/version1/render/version1" id="renderInformation" program-name="sbgnviz" program-version="5.0.0" background-color="#00000000">
<listOfColorDefinitions>
<colorDefinition id="color_1" value="#ffffff7f"/>
<colorDefinition id="color_2" value="#838383"/>
<colorDefinition id="color_3" value="#ffffffff"/>
<colorDefinition id="color_4" value="#555555"/>
<colorDefinition id="color_5" value="#ffffff"/>
<colorDefinition id="color_6" value="#000000"/>
<colorDefinition id="color_7" value="#ff0000"/>
</listOfColorDefinitions>
<listOfBackgroundImages>
<backgroundImage id="image_1" value="http://newteditor.org/color-scheme-images/rb3_3d.png"/>
<backgroundImage id="image_2" value="http://newteditor.org/color-scheme-images/pg5_3d.png"/>
<backgroundImage id="image_3" value="http://newteditor.org/color-scheme-images/pg4_3d.png"/>
<backgroundImage id="image_4" value="http://newteditor.org/color-scheme-images/bw1_3d.png"/>
</listOfBackgroundImages>
<listOfStyles>
<style id="nodeffffff0.58383833.2514normalnormalHelvetica000image_1none5050100100" id-list="nwtN_3ab42db3-7946-4642-a215-98b2f74f5061 nwtN_31dec67c-8c37-40ec-bfad-d038cf1dc815">
<g font-size="14" font-family="Helvetica" font-weight="normal" font-style="normal" font-color="#000" stroke="color_2" stroke-width="3.25" fill="color_1" background-image="image_1" background-fit="none" background-pos-x="50%" background-pos-y="50%" background-width="100%" background-height="100%"/>
</style>
<style id="nodeffffff15555551.2518normalnormalHelvetica000image_2none5050100100" id-list="6cde7a25-b41a-b8cb-d3d3-188533472dae 7813a623-ae26-a5e1-d4e2-e2eb1d2c14d7 1e1a9dc6-32ae-464a-9912-68fc274f8fb4 6f6a1c77-176d-7188-cdd5-048d3908a8b1 2f567801-fc2c-e128-f352-1dfab2f0dbce 7626c6b6-b0e0-b4b7-e5f3-f803fe319ef8 35a3e0be-6e00-7a99-fca5-18ed65c2fac1 bf4e242a-2a4e-49c2-0bf4-9cc45e2eae34 7c5c9a6d-976b-72b0-0c28-422b3279aeba nwtN_5a3ef454-8d2b-46de-b3a1-f9a0c2409ee4 0c291302-4021-844a-0dd2-97d76ee79ad1 nwtN_1eb9a857-e6fe-43e0-ae92-94ac8318e427 a2ee1683-eb5f-030d-3bbe-46c0a02cb659">
<g font-size="18" font-family="Helvetica" font-weight="normal" font-style="normal" font-color="#000" stroke="color_4" stroke-width="1.25" fill="color_3" background-image="image_2" background-fit="none" background-pos-x="50%" background-pos-y="50%" background-width="100%" background-height="100%"/>
</style>
<style id="infoboxffffff5555552.259normalnormalArial0f0f0fstadium" id-list="6cde7a25-b41a-b8cb-d3d3-188533472dae_0 89360553-bab4-532a-c6c7-624272c4e43b_0 c3a94e68-cca7-3c6a-f546-33c23dc59923_0 7813a623-ae26-a5e1-d4e2-e2eb1d2c14d7_0 6f6a1c77-176d-7188-cdd5-048d3908a8b1_0 2f567801-fc2c-e128-f352-1dfab2f0dbce_0 7626c6b6-b0e0-b4b7-e5f3-f803fe319ef8_0 35a3e0be-6e00-7a99-fca5-18ed65c2fac1_0 bf4e242a-2a4e-49c2-0bf4-9cc45e2eae34_0 0c291302-4021-844a-0dd2-97d76ee79ad1_0 nwtN_1eb9a857-e6fe-43e0-ae92-94ac8318e427_0 a2ee1683-eb5f-030d-3bbe-46c0a02cb659_0">
<g font-size="9" font-family="Arial" font-weight="normal" font-style="normal" font-color="#0f0f0f" stroke="color_4" stroke-width="2.25" fill="color_5" shape-name="stadium"/>
</style>
<style id="nodeffffff0.55555551.2511normalnormalHelvetica000image_3none5050100100" id-list="89360553-bab4-532a-c6c7-624272c4e43b c3a94e68-cca7-3c6a-f546-33c23dc59923">
<g font-size="11" font-family="Helvetica" font-weight="normal" font-style="normal" font-color="#000" stroke="color_4" stroke-width="1.25" fill="color_1" background-image="image_3" background-fit="none" background-pos-x="50%" background-pos-y="50%" background-width="100%" background-height="100%"/>
</style>
<style id="nodeffffff10000001.25image_4none5050100100" id-list="9615ba87-e042-ef50-d78e-1ef00df34a6e 2785fbb1-18d0-0b2f-dcf2-968acc6869c0 a8404458-8ee5-6465-5d2e-4be53abad9f9 nwtN_78d6cd14-2e5f-463f-9a30-27ce3baea7d9">
<g stroke="color_6" stroke-width="1.25" fill="color_3" background-image="image_4" background-fit="none" background-pos-x="50%" background-pos-y="50%" background-width="100%" background-height="100%"/>
</style>
<style id="nodeffffff15555551.25image_4none5050100100" id-list="nwtN_7ffe3be6-9a33-4696-a593-d5c0a8a45a4c">
<g stroke="color_4" stroke-width="1.25" fill="color_3" background-image="image_4" background-fit="none" background-pos-x="50%" background-pos-y="50%" background-width="100%" background-height="100%"/>
</style>
<style id="nodeffffff15555551.2511normalnormalHelvetica000image_1none5050100100" id-list="nwtN_617312c5-bae0-423e-a711-c6adfee4193b">
<g font-size="11" font-family="Helvetica" font-weight="normal" font-style="normal" font-color="#000" stroke="color_4" stroke-width="1.25" fill="color_3" background-image="image_1" background-fit="none" background-pos-x="50%" background-pos-y="50%" background-width="100%" background-height="100%"/>
</style>
<style id="edge0000001.25" id-list="nwtE_68ee44c6-86ba-499b-a798-db1c00254138">
<g stroke="color_6" stroke-width="1.25"/>
</style>
<style id="edge5555551.25" id-list="nwtE_4b37b92d-3b8f-4aa1-9e1b-ea807137d5c9 35db2b35-7414-81f4-77de-567e66e3e58c 9711fea3-2f48-6cbb-b419-9d7f84a6affd 0017dd1d-a2d2-0bd9-83f5-ab16e0091265 nwtE_34b23376-b68c-4b93-9c19-53c7db6d0a10 nwtE_bcf805de-7c8e-443d-8982-977ec5a34365 nwtE_98183863-8822-4e5b-b625-59eaac7ba2f6 8efed2fc-1ba9-c12e-7f12-37512a4aa7ce 7e62d9bc-21f2-bd26-2540-40093f96f9cd 2c9b0dc2-d5bd-f6aa-22e6-f93fde1a35ff">
<g stroke="color_4" stroke-width="1.25"/>
</style>
<style id="edgeff00001.25" id-list="nwtE_1fcb9fb6-ba5a-4ccf-bd50-155ce657fedb nwtE_8a9898a8-7aec-4d2a-be12-2050f58ccc80 nwtE_9f593961-7d71-49ac-8c9b-eb8e899665e4 nwtE_b9e23793-a56e-4277-b278-6724f6a4d68a">
<g stroke="color_7" stroke-width="1.25"/>
</style>
</listOfStyles>
</renderInformation>
<mapProperties>
<compoundPadding>20</compoundPadding>
<extraCompartmentPadding>14</extraCompartmentPadding>
<extraComplexPadding>10</extraComplexPadding>
<arrowScale>1.25</arrowScale>
<showComplexName>true</showComplexName>
<dynamicLabelSize>regular</dynamicLabelSize>
<inferNestingOnLoad>false</inferNestingOnLoad>
<fitLabelsToNodes>false</fitLabelsToNodes>
<fitLabelsToInfoboxes>false</fitLabelsToInfoboxes>
<recalculateLayoutOnComplexityManagement>true</recalculateLayoutOnComplexityManagement>
<rearrangeOnComplexityManagement>true</rearrangeOnComplexityManagement>
<animateOnDrawingChanges>true</animateOnDrawingChanges>
<adjustNodeLabelFontSizeAutomatically>false</adjustNodeLabelFontSizeAutomatically>
<enablePorts>false</enablePorts>
<enableSIFTopologyGrouping>false</enableSIFTopologyGrouping>
<allowCompoundNodeResize>false</allowCompoundNodeResize>
<mapColorScheme>opposed_purple_green</mapColorScheme>
<mapColorSchemeStyle>3D</mapColorSchemeStyle>
<mapName>PD map of the Drosophila cell cycle</mapName>
<mapDescription>doi:10.1371/journal.pcbi.1005740</mapDescription>
<defaultInfoboxHeight>12</defaultInfoboxHeight>
<defaultInfoboxWidth>8</defaultInfoboxWidth>
<rearrangeAfterExpandCollapse>true</rearrangeAfterExpandCollapse>
</mapProperties>
</extension>
<glyph id="nwtN_3ab42db3-7946-4642-a215-98b2f74f5061" class="compartment">
<label text="Cytoplasm"/>
<bbox x="572.125" y="16.149999999999977" w="477.4263309352516" h="641.725"/>
</glyph>
<glyph id="nwtN_31dec67c-8c37-40ec-bfad-d038cf1dc815" class="compartment" compartmentRef="nwtN_3ab42db3-7946-4642-a215-98b2f74f5061">
<label text="Nucleus"/>
<bbox x="594.8263309352517" y="270.3339698656986" w="432.5" h="302.3749999999997"/>
</glyph>
<glyph id="c3a94e68-cca7-3c6a-f546-33c23dc59923" class="complex" compartmentRef="nwtN_31dec67c-8c37-40ec-bfad-d038cf1dc815">
<label text="MPF"/>
<bbox x="883.0763309352517" y="359.8652198656986" w="74.25" h="86.87500000000011"/>
<glyph id="c3a94e68-cca7-3c6a-f546-33c23dc59923_0" class="state variable">