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