Commit 1eff0b42 authored by Piotr Gawron's avatar Piotr Gawron
Browse files

antesense rna region is a subclass of modification residue

parent 14a66f69
...@@ -17,7 +17,6 @@ import lcsb.mapviewer.model.map.species.Gene; ...@@ -17,7 +17,6 @@ import lcsb.mapviewer.model.map.species.Gene;
import lcsb.mapviewer.model.map.species.Protein; import lcsb.mapviewer.model.map.species.Protein;
import lcsb.mapviewer.model.map.species.Rna; import lcsb.mapviewer.model.map.species.Rna;
import lcsb.mapviewer.model.map.species.Species; import lcsb.mapviewer.model.map.species.Species;
import lcsb.mapviewer.model.map.species.field.AntisenseRnaRegion;
import lcsb.mapviewer.model.map.species.field.ModificationResidue; import lcsb.mapviewer.model.map.species.field.ModificationResidue;
import lcsb.mapviewer.model.map.species.field.RnaRegion; import lcsb.mapviewer.model.map.species.field.RnaRegion;
...@@ -28,216 +27,217 @@ import lcsb.mapviewer.model.map.species.field.RnaRegion; ...@@ -28,216 +27,217 @@ import lcsb.mapviewer.model.map.species.field.RnaRegion;
*/ */
public class CellDesignerElementCollection { public class CellDesignerElementCollection {
/** /**
* Element by element identifier (it's CellDesigner identifier). * Element by element identifier (it's CellDesigner identifier).
*/ */
private Map<String, CellDesignerElement<?>> elementById = new HashMap<>(); private Map<String, CellDesignerElement<?>> elementById = new HashMap<>();
/** /**
* Returns element by given identifier. * Returns element by given identifier.
* *
* @param speciesId * @param speciesId
* element identifier * element identifier
* @return element by given identifier * @return element by given identifier
* *
* @param <T> * @param <T>
* type of returned object * type of returned object
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T extends CellDesignerElement<?>> T getElementByElementId(String speciesId) { public <T extends CellDesignerElement<?>> T getElementByElementId(String speciesId) {
return (T) elementById.get(speciesId); return (T) elementById.get(speciesId);
} }
/** /**
* *
*/ */
private Map<String, String> sbmlIdByElement = new HashMap<>(); private Map<String, String> sbmlIdByElement = new HashMap<>();
/** /**
* Returns element identifier that should be used for model element when * Returns element identifier that should be used for model element when
* creating cell designer xml file. * creating cell designer xml file.
* *
* @param modelElement * @param modelElement
* model element for which we want to obtain identifier * model element for which we want to obtain identifier
* @return identifier of cell designer element that will be exported * @return identifier of cell designer element that will be exported
*/ */
public String getElementId(Element modelElement) { public String getElementId(Element modelElement) {
if ("default".equals(modelElement.getElementId())) { if ("default".equals(modelElement.getElementId())) {
return modelElement.getElementId(); return modelElement.getElementId();
} else { } else {
String sbmlId = getSbmlId(modelElement, true); String sbmlId = getSbmlId(modelElement, true);
if (sbmlIdByElement.get(sbmlId) == null) { if (sbmlIdByElement.get(sbmlId) == null) {
String id = "s_id_" + modelElement.getElementId(); String id = "s_id_" + modelElement.getElementId();
if (sbmlIdByElement.values().contains(id)) { if (sbmlIdByElement.values().contains(id)) {
throw new InvalidArgumentException("id duplicates"); throw new InvalidArgumentException("id duplicates");
} }
sbmlIdByElement.put(sbmlId, id); sbmlIdByElement.put(sbmlId, id);
} }
return sbmlIdByElement.get(sbmlId); return sbmlIdByElement.get(sbmlId);
} }
} }
/** /**
* Creates a String that identifies element as distinct SBML entity. * Creates a String that identifies element as distinct SBML entity.
* *
* @param modelElement * @param modelElement
* element that we want to identify * element that we want to identify
* @param useComplex * @param useComplex
* should we use identifier of a complex. This should be used by * should we use identifier of a complex. This should be used by
* default (because if the complex is different then element should * default (because if the complex is different then element should
* have different identifier). However, when element asks complex for * have different identifier). However, when element asks complex for
* id, complex will try to resolve ids of children (because this is * id, complex will try to resolve ids of children (because this is
* what defines complex identity), and in such situation it should * what defines complex identity), and in such situation it should
* disable resolving complex, because there will by infinity cyclic * disable resolving complex, because there will by infinity cyclic
* calls and stack overflow error will be thrown. * calls and stack overflow error will be thrown.
* @return unique String for SBML entity * @return unique String for SBML entity
*/ */
private String getSbmlId(Element modelElement, boolean useComplex) { private String getSbmlId(Element modelElement, boolean useComplex) {
String compartmenName = "default"; String compartmenName = "default";
if (modelElement.getCompartment() != null) { if (modelElement.getCompartment() != null) {
compartmenName = modelElement.getCompartment().getName(); compartmenName = modelElement.getCompartment().getName();
} }
String modifications = ""; String modifications = "";
if (modelElement instanceof AntisenseRna) { if (modelElement instanceof AntisenseRna) {
AntisenseRna asAntisenseRna = ((AntisenseRna) modelElement); AntisenseRna asAntisenseRna = ((AntisenseRna) modelElement);
for (AntisenseRnaRegion region : asAntisenseRna.getRegions()) { for (ModificationResidue region : asAntisenseRna.getRegions()) {
modifications += region.getState(); modifications += region.getState();
} }
} else if (modelElement instanceof Gene) { } else if (modelElement instanceof Gene) {
Gene asGene = ((Gene) modelElement); Gene asGene = ((Gene) modelElement);
for (ModificationResidue region : asGene.getModificationResidues()) { for (ModificationResidue region : asGene.getModificationResidues()) {
modifications += region.getState(); modifications += region.getState();
} }
} else if (modelElement instanceof Protein) { } else if (modelElement instanceof Protein) {
Protein asProtein = ((Protein) modelElement); Protein asProtein = ((Protein) modelElement);
modifications = asProtein.getStructuralState(); modifications = asProtein.getStructuralState();
for (ModificationResidue region : asProtein.getModificationResidues()) { for (ModificationResidue region : asProtein.getModificationResidues()) {
modifications += region.getState(); modifications += region.getState();
} }
} else if (modelElement instanceof Rna) { } else if (modelElement instanceof Rna) {
Rna asRna = ((Rna) modelElement); Rna asRna = ((Rna) modelElement);
for (RnaRegion region : asRna.getRegions()) { for (RnaRegion region : asRna.getRegions()) {
modifications += region.getState(); modifications += region.getState();
} }
} else if (modelElement instanceof Complex) { } else if (modelElement instanceof Complex) {
Complex asComplex = ((Complex) modelElement); Complex asComplex = ((Complex) modelElement);
modifications = asComplex.getStructuralState(); modifications = asComplex.getStructuralState();
} }
String complexId = ""; String complexId = "";
String homodimer = ""; String homodimer = "";
if (modelElement instanceof Species) { if (modelElement instanceof Species) {
homodimer = ((Species) modelElement).getHomodimer() + ""; homodimer = ((Species) modelElement).getHomodimer() + "";
if (((Species) modelElement).getComplex() != null) { if (((Species) modelElement).getComplex() != null) {
if (useComplex) { if (useComplex) {
if (!isCyclicNesting(((Species) modelElement).getComplex())) { if (!isCyclicNesting(((Species) modelElement).getComplex())) {
complexId = getElementId(((Species) modelElement).getComplex()); complexId = getElementId(((Species) modelElement).getComplex());
} else { } else {
throw new InvalidArgumentException("Cycling nested structure found in element: " + modelElement.getElementId()); throw new InvalidArgumentException(
} "Cycling nested structure found in element: " + modelElement.getElementId());
} else { }
complexId = ((Species) modelElement).getComplex().getName(); } else {
} complexId = ((Species) modelElement).getComplex().getName();
} }
} }
String childrenId = ""; }
if (modelElement instanceof Complex) { String childrenId = "";
Complex asComplex = (Complex) modelElement; if (modelElement instanceof Complex) {
List<String> childIds = new ArrayList<>(); Complex asComplex = (Complex) modelElement;
for (Species child : asComplex.getAllChildren()) { List<String> childIds = new ArrayList<>();
childIds.add(getSbmlId(child, false)); for (Species child : asComplex.getAllChildren()) {
} childIds.add(getSbmlId(child, false));
Collections.sort(childIds); }
for (String string : childIds) { Collections.sort(childIds);
childrenId += string + "\n"; for (String string : childIds) {
} childrenId += string + "\n";
} }
}
// identifier that distinguish elements in SBML depends only on type,
// name, compartment, modifications, homodimer, state, complex where it's // identifier that distinguish elements in SBML depends only on type,
// located, // name, compartment, modifications, homodimer, state, complex where it's
// children of the complex // located,
String sbmlId = compartmenName + "\n" + modelElement.getName() + "\n" + modelElement.getStringType() + "\n" + modifications + "\n" + complexId + "\n" // children of the complex
+ homodimer + "\n" + childrenId; String sbmlId = compartmenName + "\n" + modelElement.getName() + "\n" + modelElement.getStringType() + "\n"
+ modifications + "\n" + complexId + "\n" + homodimer + "\n" + childrenId;
return sbmlId;
} return sbmlId;
}
/**
* Checks if complex parenting is cyclic. /**
* * Checks if complex parenting is cyclic.
* @param complex *
* complex for which data is checked * @param complex
* @return true if parent of the complex is also a (grand)child of this * complex for which data is checked
* complex, false otherwise * @return true if parent of the complex is also a (grand)child of this complex,
*/ * false otherwise
private boolean isCyclicNesting(Complex complex) { */
Set<Complex> foundComplexes = new HashSet<>(); private boolean isCyclicNesting(Complex complex) {
while (complex != null) { Set<Complex> foundComplexes = new HashSet<>();
if (foundComplexes.contains(complex)) { while (complex != null) {
return true; if (foundComplexes.contains(complex)) {
} return true;
foundComplexes.add(complex); }
complex = complex.getComplex(); foundComplexes.add(complex);
} complex = complex.getComplex();
return false; }
} return false;
}
/**
* Adds cell designer structures. /**
* * Adds cell designer structures.
* @param elements *
* list of objects to add * @param elements
*/ * list of objects to add
public void addElements(List<? extends CellDesignerElement<?>> elements) { */
for (CellDesignerElement<?> element : elements) { public void addElements(List<? extends CellDesignerElement<?>> elements) {
addElement(element); for (CellDesignerElement<?> element : elements) {
} addElement(element);
} }
}
/**
* Adds cell designer object. /**
* * Adds cell designer object.
* @param element *
* object to add * @param element
*/ * object to add
public void addElement(CellDesignerElement<?> element) { */
addElement(element, element.getElementId()); public void addElement(CellDesignerElement<?> element) {
} addElement(element, element.getElementId());
}
/**
* Adds CellDesigner element with custom id (instead the one obtained from /**
* CellDesigner structure). * Adds CellDesigner element with custom id (instead the one obtained from
* * CellDesigner structure).
* @param element *
* element to be add * @param element
* @param id * element to be add
* id that should be used for identifying element * @param id
*/ * id that should be used for identifying element
public void addElement(CellDesignerElement<?> element, String id) { */
if (elementById.get(id) != null) { public void addElement(CellDesignerElement<?> element, String id) {
throw new InvalidArgumentException( if (elementById.get(id) != null) {
"[" + element.getClass().getSimpleName() + " " + element.getElementId() + "]\t" + "Element with given id alread exists. ID: " + id); throw new InvalidArgumentException("[" + element.getClass().getSimpleName() + " " + element.getElementId() + "]\t"
} + "Element with given id alread exists. ID: " + id);
elementById.put(id, element); }
} elementById.put(id, element);
}
/**
* Adds CellDesigner structure in a way that it would be accessed via /**
* identifier for model structure. Method used only for unit test. * Adds CellDesigner structure in a way that it would be accessed via identifier
* * for model structure. Method used only for unit test.
* @param modelElement *
* model element that will create identifier * @param modelElement
* @param element * model element that will create identifier
* element to be added * @param element
*/ * element to be added
public void addModelElement(Element modelElement, CellDesignerElement<?> element) { */
addElement(element, getElementId(modelElement)); public void addModelElement(Element modelElement, CellDesignerElement<?> element) {
if (getElementByElementId(element.getElementId()) == null) { addElement(element, getElementId(modelElement));
addElement(element); if (getElementByElementId(element.getElementId()) == null) {
} addElement(element);
} }
}
} }
...@@ -5,6 +5,7 @@ import org.w3c.dom.Node; ...@@ -5,6 +5,7 @@ import org.w3c.dom.Node;
import org.w3c.dom.NodeList; import org.w3c.dom.NodeList;
import lcsb.mapviewer.common.Pair; import lcsb.mapviewer.common.Pair;
import lcsb.mapviewer.common.exception.InvalidArgumentException;
import lcsb.mapviewer.common.exception.InvalidXmlSchemaException; import lcsb.mapviewer.common.exception.InvalidXmlSchemaException;
import lcsb.mapviewer.converter.model.celldesigner.CellDesignerElementCollection; import lcsb.mapviewer.converter.model.celldesigner.CellDesignerElementCollection;
import lcsb.mapviewer.converter.model.celldesigner.annotation.RestAnnotationParser; import lcsb.mapviewer.converter.model.celldesigner.annotation.RestAnnotationParser;
...@@ -12,8 +13,10 @@ import lcsb.mapviewer.converter.model.celldesigner.structure.CellDesignerAntisen ...@@ -12,8 +13,10 @@ import lcsb.mapviewer.converter.model.celldesigner.structure.CellDesignerAntisen
import lcsb.mapviewer.converter.model.celldesigner.structure.CellDesignerElement; import lcsb.mapviewer.converter.model.celldesigner.structure.CellDesignerElement;
import lcsb.mapviewer.converter.model.celldesigner.structure.fields.CellDesignerAntisenseRnaRegion; import lcsb.mapviewer.converter.model.celldesigner.structure.fields.CellDesignerAntisenseRnaRegion;
import lcsb.mapviewer.model.map.species.AntisenseRna; import lcsb.mapviewer.model.map.species.AntisenseRna;
import lcsb.mapviewer.model.map.species.field.AntisenseRnaRegion; import lcsb.mapviewer.model.map.species.field.CodingRegion;
import lcsb.mapviewer.model.map.species.field.AntisenseRnaRegionType; import lcsb.mapviewer.model.map.species.field.ModificationResidue;
import lcsb.mapviewer.model.map.species.field.ModificationSite;
import lcsb.mapviewer.model.map.species.field.ProteinBindingDomain;
/** /**
* Class that performs parsing of the CellDesigner xml for AntisenseRna object. * Class that performs parsing of the CellDesigner xml for AntisenseRna object.
...@@ -100,7 +103,7 @@ public class AntisenseRnaXmlParser extends AbstractElementXmlParser<CellDesigner ...@@ -100,7 +103,7 @@ public class AntisenseRnaXmlParser extends AbstractElementXmlParser<CellDesigner
result += "</celldesigner:notes>"; result += "</celldesigner:notes>";
if (antisenseRna.getRegions().size() > 0) { if (antisenseRna.getRegions().size() > 0) {
result += "<celldesigner:listOfRegions>"; result += "<celldesigner:listOfRegions>";
for (AntisenseRnaRegion region : antisenseRna.getRegions()) { for (ModificationResidue region : antisenseRna.getRegions()) {
result += toXml(region); result += toXml(region);
} }
result += "</celldesigner:listOfRegions>"; result += "</celldesigner:listOfRegions>";
...@@ -116,17 +119,30 @@ public class AntisenseRnaXmlParser extends AbstractElementXmlParser<CellDesigner ...@@ -116,17 +119,30 @@ public class AntisenseRnaXmlParser extends AbstractElementXmlParser<CellDesigner
* object to be transformed * object to be transformed
* @return xml representation of the given region * @return xml representation of the given region
*/ */
private String toXml(AntisenseRnaRegion region) { private String toXml(ModificationResidue region) {
String result = ""; String result = "";
String attributes = ""; String attributes = "";
if (!region.getIdAntisenseRnaRegion().equals("")) { if (!region.getIdModificationResidue().equals("")) {
attributes += " id=\"" + region.getIdAntisenseRnaRegion() + "\""; attributes += " id=\"" + region.getIdModificationResidue() + "\"";
} }
if (!region.getName().equals("")) { if (!region.getName().equals("")) {
attributes += " name=\"" + escapeXml(region.getName()) + "\""; attributes += " name=\"" + escapeXml(region.getName()) + "\"";
} }
if (region.getWidth() != 0) { double width = 0;
attributes += " size=\"" + region.getWidth() / region.getSpecies().getWidth() + "\""; String type = null;
if (region instanceof CodingRegion) {
width = ((CodingRegion) region).getWidth();
type = "CodingRegion";
} else if (region instanceof ModificationSite) {
type = "Modification Site";
} else if (region instanceof ProteinBindingDomain) {
width = ((ProteinBindingDomain) region).getWidth();
type = "proteinBindingDomain";
} else {
throw new InvalidArgumentException("Unknown modificatin type: " + region.getClass());
}
if (width != 0) {
attributes += " size=\"" + width / region.getSpecies().getWidth() + "\"";
} }
if (region.getPosition() != null) { if (region.getPosition() != null) {
double pos = (region.getPosition().getX() - region.getSpecies().getWidth()) double pos = (region.getPosition().getX() - region.getSpecies().getWidth())
...@@ -134,9 +150,7 @@ public class AntisenseRnaXmlParser extends AbstractElementXmlParser<CellDesigner ...@@ -134,9 +150,7 @@ public class AntisenseRnaXmlParser extends AbstractElementXmlParser<CellDesigner
attributes += " pos=\"" + pos + "\""; attributes += " pos=\"" + pos + "\"";
} }
if (region.getType() != null) { attributes += " type=\"" + type + "\"";
attributes += " type=\"" + region.getType().getName() + "\"";
}
result += "<celldesigner:region " + attributes + ">"; result += "<celldesigner:region " + attributes + ">";
result += "</celldesigner:region>"; result += "</celldesigner:region>";
...@@ -160,12 +174,18 @@ public class AntisenseRnaXmlParser extends AbstractElementXmlParser<CellDesigner ...@@ -160,12 +174,18 @@ public class AntisenseRnaXmlParser extends AbstractElementXmlParser<CellDesigner
residue.setPos(getNodeAttr("pos", regionNode)); residue.setPos(getNodeAttr("pos", regionNode));
String typeString = getNodeAttr("type", regionNode); String typeString = getNodeAttr("type", regionNode);
if (typeString != null) { if (typeString != null) {
AntisenseRnaRegionType type = AntisenseRnaRegionType.getTypeByString(typeString); String type;
if (type == null) { if (typeString.equals("CodingRegion")) {
type = "CODING_REGION";
} else if (typeString.equals("Modification Site")) {
type = "MODIFICATION_SITE";
} else if (typeString.equals("proteinBindingDomain")) {
type = "PROTEIN_BINDING_DOMAIN";
} else
throw new InvalidXmlSchemaException("Unknown antisense rna region type: " + typeString); throw new InvalidXmlSchemaException("Unknown antisense rna region type: " + typeString);
} residue.setModificationType(type);
residue.setType(type);
} }
NodeList list = regionNode.getChildNodes(); NodeList list = regionNode.getChildNodes();
for (int i = 0; i < list.getLength(); i++) { for (int i = 0; i < list.getLength(); i++) {
Node node = list.item(i); Node node = list.item(i);
......
...@@ -9,9 +9,11 @@ import lcsb.mapviewer.common.exception.InvalidArgumentException; ...@@ -9,9 +9,11 @@ import lcsb.mapviewer.common.exception.InvalidArgumentException;