Commit 2fcf69ec authored by Piotr Gawron's avatar Piotr Gawron
Browse files

Merge branch '1063-import-sbgn-file' into 'devel_14.0.x'

Resolve "import of sbgn files"

See merge request !1071
parents 5d5470c9 9aca65b0
Pipeline #21473 passed with stage
in 13 minutes and 6 seconds
......@@ -18,6 +18,11 @@ minerva (14.0.9) stable; urgency=medium
crashed (#1063)
* Bug fix: when SBGN file contained reaction where every node started in the
same process port minerva crashed crashed (#1063)
* Bug fix: activity flow reaction inside SBGN PD caused upload of map to
crash
* Bug fix: reaction without product in SBGN crashed upload of map
* Bug fix: when SBGN production pointed directly to process instead of
process port upload crashed
-- Piotr Gawron <piotr.gawron@uni.lu> Mon, 3 Feb 2020 15:00:00 +0200
......
......@@ -61,14 +61,22 @@ public class SbgnmlXmlParser {
* Default class logger.
*/
private Logger logger = LogManager.getLogger(SbgnmlXmlParser.class.getName());
/**
* List of all processes to be parsed.
*/
private List<Process> processes = new ArrayList<Process>();
/**
* List of all arcs that should be translated as activity flow reactions.
*/
private List<Arc> activityFlowArcs = new ArrayList<>();
/**
* List of all logic operator glyphs parsed so far.
*/
private List<Glyph> logicOperators = new ArrayList<Glyph>();
/**
* List of all logic arcs parsed so far.
*/
......@@ -130,6 +138,15 @@ public class SbgnmlXmlParser {
}
}
for (Arc arc : activityFlowArcs) {
try {
Reaction r = createActivityFlowReaction(arc, model);
model.addReaction(r);
} catch (Exception e) {
throw new InvalidInputDataExecption("Unable to parse the reaction: " + arc.getId(), e);
}
}
for (Element element : model.getElements()) {
if (element.getCompartment() == null) {
Compartment parent = null;
......@@ -149,6 +166,52 @@ public class SbgnmlXmlParser {
return model;
}
private Reaction createActivityFlowReaction(Arc arc, Model model) {
Reaction result;
switch (ArcClazz.fromClazz(arc.getClazz())) {
case PRODUCTION:
logger.warn(getTag(arc) + "Activity flow arc type is invalid. Changing to "
+ StateTransitionReaction.class.getSimpleName());
result = new StateTransitionReaction(arc.getId());
break;
default:
throw new InvalidArgumentException("Don't know how to translate to activity flow reaction");
}
List<Point2D> pointList = getLinePoints(arc);
List<Point2D> reactantPoints = new ArrayList<>();
List<Point2D> centerPoints = new ArrayList<>();
List<Point2D> productPoints = new ArrayList<>();
if (pointList.size() > 3) {
reactantPoints.addAll(pointList.subList(0, pointList.size() / 2));
centerPoints.addAll(pointList.subList(pointList.size() / 2 - 1, pointList.size() / 2 + 1));
productPoints.addAll(pointList.subList(pointList.size() / 2, pointList.size() + 1));
} else {
reactantPoints.add(pointList.get(0));
reactantPoints.add(new PointTransformation().getPointOnLine(pointList.get(0), pointList.get(1), 0.3));
centerPoints.add(new PointTransformation().getPointOnLine(pointList.get(0), pointList.get(1), 0.3));
centerPoints.add(new PointTransformation().getPointOnLine(pointList.get(0), pointList.get(1), 0.7));
productPoints.add(new PointTransformation().getPointOnLine(pointList.get(0), pointList.get(1), 0.7));
for (int i = 1; i < pointList.size(); i++) {
productPoints.add(pointList.get(i));
}
}
Glyph source = getSourceGlyph(arc);
Reactant reactant = new Reactant(model.getElementByElementId(source.getId()));
reactant.setLine(new PolylineData(reactantPoints));
result.addReactant(reactant);
Glyph target = getTargetGlyph(arc);
Product product = new Product(model.getElementByElementId(target.getId()));
product.setLine(parseLine(arc, productPoints));
result.addProduct(product);
result.setLine(new PolylineData(centerPoints));
return result;
}
/**
* Method used to adjust the size of elements that have their size represented
* different in the SBGN-ML file. Adjusted elements: Source and Sink / Degraded
......@@ -399,7 +462,7 @@ public class SbgnmlXmlParser {
if (a.getTarget() instanceof Port) {
arcTargetPort = (Port) a.getTarget();
} else if (a.getSource() instanceof Port) {
logger.warn("[" + a.getId() + "]\tConsumption is going from process");
logger.warn(getTag(a) + "Consumption is going from process");
arcTargetPort = (Port) a.getSource();
} else {
throw new InvalidInputDataExecption("[" + a.getId() + "]\tConsumption must be connected to a Port");
......@@ -412,13 +475,42 @@ public class SbgnmlXmlParser {
}
break;
case PRODUCTION:
Port arcSourcePort = (Port) a.getSource();
for (Process p : processes) {
if (p.getCentralPoint().getPort().contains(arcSourcePort)) {
p.addProductArc(a);
boolean processFound = false;
Port arcSourcePort = null;
if (a.getSource() instanceof Port) {
arcSourcePort = (Port) a.getSource();
} else if (a.getTarget() instanceof Port) {
logger.warn(getTag(a) + "Production is going to process");
arcSourcePort = (Port) a.getTarget();
} else {
for (Process p : processes) {
if (p.getCentralPoint().equals(a.getTarget())) {
p.addReagentArc(a);
logger.warn(getTag(a) + "Invalid target port");
processFound = true;
break;
}
if (p.getCentralPoint().equals(a.getSource())) {
p.addProductArc(a);
logger.warn(getTag(a) + "Invalid source port");
processFound = true;
break;
}
}
if (!processFound) {
logger.warn(getTag(a) + "Activity flow reaction found in PD");
activityFlowArcs.add(a);
break;
}
}
if (!processFound) {
for (Process p : processes) {
if (p.getCentralPoint().getPort().contains(arcSourcePort)) {
p.addProductArc(a);
break;
}
}
}
break;
case EQUIVALENCE_ARC:
logger.warn("Submaps are not supported. Equivalence arc: " + a.getId() + " has not been parsed.");
......@@ -490,6 +582,14 @@ public class SbgnmlXmlParser {
}
}
private String getTag(Arc arc) {
return "[" + ArcClazz.fromClazz(arc.getClazz()) + "; " + arc.getId() + "]\t";
}
private String getTag(Process process) {
return "[" + process.getClass() + "; " + process.getCentralPoint().getId() + "]\t";
}
/**
* Method used to parse arc going to or from a phenotype.
*
......@@ -1212,8 +1312,8 @@ public class SbgnmlXmlParser {
*/
private void parseProcess(Process p, Model model) throws Exception {
if (p.getProductArcs().isEmpty()) {
throw new InvalidArgumentException(
p.getCentralPoint().getId() + ": The process must have at least one outgoing arc.");
logger.warn(getTag(p) + "The process must have at least one outgoing arc.");
return;
}
p.setProductsPort((Port) p.getProductArcs().get(0).getSource());
......@@ -1233,14 +1333,7 @@ public class SbgnmlXmlParser {
}
if (p.getReagentsPort() == null && !p.getReagentArcs().isEmpty()) {
Port port;
if (p.getReagentArcs().get(0).getTarget() instanceof Port) {
port = (Port) p.getReagentArcs().get(0).getTarget();
} else if (p.getReagentArcs().get(0).getSource() instanceof Port) {
port = (Port) p.getReagentArcs().get(0).getSource();
} else {
throw new InvalidArgumentException("Cannot find proces for arc: " + p.getReagentArcs().get(0).getId());
}
Port port = getTargetPort(p.getReagentArcs().get(0));
p.setReagentsPort(port);
}
......@@ -1286,7 +1379,7 @@ public class SbgnmlXmlParser {
if (getSourcePort(a).equals(p.getProductsPort()) && ports.size() == 2 || reaction.getProducts().size() == 0) {
Product product = new Product();
product.setReaction(reaction);
Glyph target = (Glyph) a.getTarget();
Glyph target = getTargetGlyph(a);
product.setElement(model.getElementByElementId(target.getId()));
List<Point2D> pointList = getLinePoints(a);
PolylineData line = parseLine(a, pointList);
......@@ -1369,8 +1462,12 @@ public class SbgnmlXmlParser {
return (Port) a.getTarget();
} else if (a.getSource() instanceof Port) {
return (Port) a.getSource();
} else if (a.getTarget() instanceof Glyph && ((Glyph) a.getTarget()).getPort().size()>0) {
return ((Glyph) a.getTarget()).getPort().get(0);
} else if (a.getSource() instanceof Glyph && ((Glyph) a.getSource()).getPort().size()>0) {
return ((Glyph) a.getSource()).getPort().get(0);
} else {
throw new InvalidArgumentException("Arc is not connected to glyph: " + a.getId());
throw new InvalidArgumentException("Arc is not connected to port: " + a.getId());
}
}
......@@ -1379,8 +1476,12 @@ public class SbgnmlXmlParser {
return (Port) a.getSource();
} else if (a.getTarget() instanceof Port) {
return (Port) a.getTarget();
} else if (a.getSource() instanceof Glyph && ((Glyph) a.getSource()).getPort().size()>0) {
return ((Glyph) a.getSource()).getPort().get(0);
} else if (a.getTarget() instanceof Glyph && ((Glyph) a.getTarget()).getPort().size()>0) {
return ((Glyph) a.getTarget()).getPort().get(0);
} else {
throw new InvalidArgumentException("Arc is not connected to glyph: " + a.getId());
throw new InvalidArgumentException("Arc is not connected to port: " + a.getId());
}
}
......@@ -1394,6 +1495,16 @@ public class SbgnmlXmlParser {
}
}
private Glyph getTargetGlyph(Arc a) {
if (a.getTarget() instanceof Glyph) {
return (Glyph) a.getTarget();
} else if (a.getSource() instanceof Glyph) {
return (Glyph) a.getSource();
} else {
throw new InvalidArgumentException("Arc is not connected to glyph: " + a.getId());
}
}
/**
* Returns {@link ArrowTypeData} based on given {@link ArcClazz}.
*
......
......@@ -147,4 +147,45 @@ public class SbgnmlXmlParserTest2 extends SbgnmlTestFunctions {
}
@Test
public void testActivityFlowReactionInPd() throws Exception {
Converter converter = new SbgnmlXmlConverter();
Model model = converter.createModel(
new ConverterParams().filename("testFiles/sbgnmlParserTestFiles/sbgnmlFiles/af_in_pd.sbgn"));
assertEquals(1, model.getReactions().size());
Reaction r = model.getReactions().iterator().next();
assertEquals(1, r.getReactants().size());
assertEquals(1, r.getProducts().size());
assertNotNull(r.getLine());
}
@Test
public void testReactionWithoutProduct() throws Exception {
Converter converter = new SbgnmlXmlConverter();
Model model = converter.createModel(
new ConverterParams().filename("testFiles/sbgnmlParserTestFiles/sbgnmlFiles/reaction_without_product.sbgn"));
assertEquals(0, model.getReactions().size());
}
@Test
public void testInvalidTargetPort() throws Exception {
Converter converter = new SbgnmlXmlConverter();
Model model = converter.createModel(
new ConverterParams().filename("testFiles/sbgnmlParserTestFiles/sbgnmlFiles/target_port_invalid.sbgn"));
assertEquals(1, model.getReactions().size());
Reaction r = model.getReactions().iterator().next();
assertEquals(1, r.getReactants().size());
assertEquals(1, r.getProducts().size());
assertNotNull(r.getLine());
}
}
<?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="#ffcc99ff"/>
<colorDefinition id="color_2" value="#000000"/>
<colorDefinition id="color_3" value="#ffff99ff"/>
<colorDefinition id="color_4" value="#ff6600"/>
</listOfColorDefinitions>
<listOfBackgroundImages>
<backgroundImage id="image_1" value="http://newteditor.org/color-scheme-images/pg5_3d.png"/>
</listOfBackgroundImages>
<listOfStyles>
<style id="nodeFFCC991000000112normalnormalHelvetica000image_1cover5050" id-list="n9">
<g font-size="12" font-family="Helvetica" font-weight="normal" font-style="normal" font-color="#000" stroke="color_2" stroke-width="1" fill="color_1" background-image="image_1" background-fit="cover" background-pos-x="50%" background-pos-y="50%"/>
</style>
<style id="nodeFFFF991FF6600112normalnormalHelvetica000image_1cover5050" id-list="n12">
<g font-size="12" font-family="Helvetica" font-weight="normal" font-style="normal" font-color="#000" stroke="color_4" stroke-width="1" fill="color_3" background-image="image_1" background-fit="cover" background-pos-x="50%" background-pos-y="50%"/>
</style>
<style id="edge0000001" id-list="e4">
<g stroke="color_2" stroke-width="1"/>
</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>Pathway #sbgn-network-container-0</mapName>
<mapDescription/>
<defaultInfoboxHeight>12</defaultInfoboxHeight>
<defaultInfoboxWidth>8</defaultInfoboxWidth>
<rearrangeAfterExpandCollapse>true</rearrangeAfterExpandCollapse>
</mapProperties>
</extension>
<glyph id="n9" class="macromolecule">
<label text="C3a"/>
<bbox x="1249.1849" y="857.0031" w="80" h="33"/>
</glyph>
<glyph id="n12" class="macromolecule">
<label text="C3AR1"/>
<bbox x="1249.1849" y="932.5061" w="80" h="40"/>
</glyph>
<arc id="e4" class="production" source="n9" target="n12">
<start x="1289.1849" y="890.5031"/>
<end x="1289.1849" y="929.5061"/>
</arc>
</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="#ffffffff"/>
<colorDefinition id="color_2" value="#000000"/>
<colorDefinition id="color_3" value="#ffcc99ff"/>
</listOfColorDefinitions>
<listOfBackgroundImages>
<backgroundImage id="image_1" value="http://newteditor.org/color-scheme-images/bw1_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"/>
</listOfBackgroundImages>
<listOfStyles>
<style id="nodeFFFFFF1000000114image_1cover5050" id-list="n42">
<g font-size="14" stroke="color_2" stroke-width="1" fill="color_1" background-image="image_1" background-fit="cover" background-pos-x="50%" background-pos-y="50%"/>
</style>
<style id="nodeFFFFFF1000000112normalnormalHelvetica000image_2cover5050" id-list="n43::n0">
<g font-size="12" font-family="Helvetica" font-weight="normal" font-style="normal" font-color="#000" stroke="color_2" stroke-width="1" fill="color_1" background-image="image_2" background-fit="cover" background-pos-x="50%" background-pos-y="50%"/>
</style>
<style id="nodeFFCC991000000112normalnormalHelvetica000image_2cover5050" id-list="n23 n44 n43::n1">
<g font-size="12" font-family="Helvetica" font-weight="normal" font-style="normal" font-color="#000" stroke="color_2" stroke-width="1" fill="color_3" background-image="image_2" background-fit="cover" background-pos-x="50%" background-pos-y="50%"/>
</style>
<style id="nodeFFFFFF1000000112normalnormalHelvetica000image_3cover5050" id-list="n43">
<g font-size="12" font-family="Helvetica" font-weight="normal" font-style="normal" font-color="#000" stroke="color_2" stroke-width="1" fill="color_1" background-image="image_3" background-fit="cover" background-pos-x="50%" background-pos-y="50%"/>
</style>
<style id="edge0000001" id-list="e16 e144 e143">
<g stroke="color_2" stroke-width="1"/>
</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>Pathway #sbgn-network-container-0</mapName>
<mapDescription/>
<defaultInfoboxHeight>12</defaultInfoboxHeight>
<defaultInfoboxWidth>8</defaultInfoboxWidth>
<rearrangeAfterExpandCollapse>true</rearrangeAfterExpandCollapse>
</mapProperties>
</extension>
<glyph id="n42" class="process">
<bbox x="1394.876" y="79.73557" w="9" h="9"/>
<port id="n42.1" x="1390.376" y="84.23557"/>
<port id="n42.2" x="1408.376" y="84.23557"/>
</glyph>
<glyph id="n23" class="macromolecule">
<label text="C3(H2O)"/>
<bbox x="1278.7437" y="67.73558" w="80" h="33"/>
</glyph>
<glyph id="n43" class="complex">
<label text="LABEL"/>
<bbox x="1357.6849" y="165.34087" w="83" h="83"/>
<glyph id="n43::n0" class="macromolecule">
<label text="C3(H2O)"/>
<bbox x="1359.1849" y="166.84087" w="80" h="40"/>
</glyph>
<glyph id="n43::n1" class="macromolecule">
<label text="CFB"/>
<bbox x="1359.1849" y="206.84087" w="80" h="40"/>
</glyph>
</glyph>
<glyph id="n44" class="macromolecule">
<label text="CFB"/>
<bbox x="1438.376" y="64.23558" w="106" h="40"/>
</glyph>
<arc id="e16" class="consumption" source="n43" target="n42.1">
<start x="1399.0247443657386" y="153.84087"/>
<next x="1399.0116" y="149.4910299999948"/>
<next x="1399.3760000000002" y="149.49102999992817"/>
<end x="1399.376" y="93.73557"/>
</arc>
<arc id="e144" class="consumption" source="n44" target="n42.1">
<start x="1437.876" y="84.2355741847826"/>
<end x="1408.876" y="84.23557103260869"/>
</arc>
<arc id="e143" class="consumption" source="n23" target="n42.1">
<start x="1359.2437" y="84.23557497719897"/>
<end x="1389.876" y="84.2355711781879"/>
</arc>
</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="#ffffffff"/>
<colorDefinition id="color_2" value="#000000"/>
<colorDefinition id="color_3" value="#ffff99ff"/>
</listOfColorDefinitions>
<listOfBackgroundImages>
<backgroundImage id="image_1" value="http://newteditor.org/color-scheme-images/pg5_3d.png"/>
<backgroundImage id="image_2" value="http://newteditor.org/color-scheme-images/bw1_3d.png"/>
<backgroundImage id="image_3" value="http://newteditor.org/color-scheme-images/pg4_3d.png"/>
</listOfBackgroundImages>
<listOfStyles>
<style id="nodeFFFFFF1000000112normalnormalHelvetica000image_1cover5050" id-list="n59 n72 n61 n62 n73">
<g font-size="12" font-family="Helvetica" font-weight="normal" font-style="normal" font-color="#000" stroke="color_2" stroke-width="1" fill="color_1" background-image="image_1" background-fit="cover" background-pos-x="50%" background-pos-y="50%"/>
</style>
<style id="nodeFFFFFF1000000114image_2cover5050" id-list="n60">
<g font-size="14" stroke="color_2" stroke-width="1" fill="color_1" background-image="image_2" background-fit="cover" background-pos-x="50%" background-pos-y="50%"/>
</style>
<style id="nodeFFFF991000000112normalnormalHelvetica000image_1cover5050" id-list="n78 n74">
<g font-size="12" font-family="Helvetica" font-weight="normal" font-style="normal" font-color="#000" stroke="color_2" stroke-width="1" fill="color_3" background-image="image_1" background-fit="cover" background-pos-x="50%" background-pos-y="50%"/>
</style>
<style id="nodeFFFFFF1000000112normalnormalHelvetica000image_3cover5050" id-list="n71">
<g font-size="12" font-family="Helvetica" font-weight="normal" font-style="normal" font-color="#000" stroke="color_2" stroke-width="1" fill="color_1" background-image="image_3" background-fit="cover" background-pos-x="50%" background-pos-y="50%"/>
</style>
<style id="edge0000001" id-list="e28 e30 e29 e41 e40">
<g stroke="color_2" stroke-width="1"/>
</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>Pathway #sbgn-network-container-0</mapName>
<mapDescription/>
<defaultInfoboxHeight>12</defaultInfoboxHeight>
<defaultInfoboxWidth>8</defaultInfoboxWidth>
<rearrangeAfterExpandCollapse>true</rearrangeAfterExpandCollapse>
</mapProperties>
</extension>
<glyph id="n59" class="macromolecule">
<label text="C4"/>
<bbox x="662.16473" y="277.00546" w="80" h="40"/>
</glyph>
<glyph id="n60" class="process">
<bbox x="697.66473" y="390.42825" w="9" h="9"/>
<port id="n60.1" x="693.16473" y="394.92825"/>
<port id="n60.2" x="711.16473" y="394.92825"/>
</glyph>
<glyph id="n72" class="macromolecule">
<label text="C1q"/>
<clone/>
<bbox x="546.1714" y="231.18143" w="80" h="40"/>
</glyph>
<glyph id="n78" class="macromolecule">
<label text="MASP2"/>
<bbox x="538.3813" y="393.2951" w="80" h="40"/>
</glyph>
<glyph id="n61" class="macromolecule">
<label text="C4a"/>
<bbox x="662.16473" y="472.85104" w="80" h="40"/>
</glyph>
<glyph id="n62" class="macromolecule">
<label text="C4b"/>
<bbox x="543.0634" y="472.85104" w="80" h="40"/>
</glyph>
<glyph id="n71" class="complex">