diff --git a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/MultiPackageNamingUtils.java b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/MultiPackageNamingUtils.java index c2905e08ce4d8401345fc39676fbd83d93e85150..a4f69ebc8e2b35d142e2f37b3167ee16d0f0c6eb 100644 --- a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/MultiPackageNamingUtils.java +++ b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/MultiPackageNamingUtils.java @@ -1,9 +1,12 @@ package lcsb.mapviewer.converter.model.sbml; +import org.apache.log4j.Logger; import org.sbml.jsbml.ext.multi.MultiSpeciesType; import lcsb.mapviewer.model.map.species.Element; import lcsb.mapviewer.model.map.species.Species; +import lcsb.mapviewer.model.map.species.field.ModificationResidue; +import lcsb.mapviewer.model.map.species.field.ModificationState; /** * Class responsible for providing identifiers of structures inside multi @@ -13,7 +16,9 @@ import lcsb.mapviewer.model.map.species.Species; * */ public final class MultiPackageNamingUtils { + private static Logger logger = Logger.getLogger(MultiPackageNamingUtils.class); + private static final String MINERVA_MODIFICATION_TYPE_PREFIX = "minerva_modification_type_"; private static final String MINERVA_POSITION_TO_COMPARTMENT_PREFIX = "minerva_position_to_compartment_"; private static final String MINERVA_STRUCTURAL_STATE_PREFIX = "minerva_structural_state_"; @@ -65,4 +70,37 @@ public final class MultiPackageNamingUtils { return featureTypeId.startsWith(MINERVA_POSITION_TO_COMPARTMENT_PREFIX); } + public static String getModificationFeatureId(Species species, Class<? extends ModificationResidue> class1) { + return MINERVA_MODIFICATION_TYPE_PREFIX + species.getClass().getSimpleName() + "_" + class1.getSimpleName(); + } + + public static String getModificationFeatureId(Species species, Class<? extends ModificationResidue> class1, + ModificationState state) { + String stateName = "null"; + if (state != null) { + stateName = state.name(); + } + + return MINERVA_MODIFICATION_TYPE_PREFIX + species.getClass().getSimpleName() + "_" + class1.getSimpleName() + "_" + + stateName; + } + + public static boolean isModificationFeatureId(String featureTypeString) { + return featureTypeString.startsWith(MINERVA_MODIFICATION_TYPE_PREFIX); + } + + public static boolean isModificationFeatureId(String speciesFeatureType, + Class<? extends ModificationResidue> class1) { + return isModificationFeatureId(speciesFeatureType) && speciesFeatureType.contains("_" + class1.getSimpleName()); + } + + public static ModificationState getModificationStateFromFeatureTypeName(String featureTypeString) { + for (ModificationState state : ModificationState.values()) { + if (featureTypeString.endsWith(state.name())) { + return state; + } + } + return null; + } + } diff --git a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlParser.java b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlParser.java index bacbc978770ff222d6dfe8aa64bb20a9d1039005..48f4e8d3ac934dcef3fc4d6ce5690df21ed3d58d 100644 --- a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlParser.java +++ b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/SbmlParser.java @@ -46,6 +46,8 @@ import lcsb.mapviewer.model.map.reaction.type.BooleanLogicGateReaction; import lcsb.mapviewer.model.map.species.Complex; import lcsb.mapviewer.model.map.species.Element; import lcsb.mapviewer.model.map.species.Species; +import lcsb.mapviewer.model.map.species.field.ModificationResidue; +import lcsb.mapviewer.model.map.species.field.SpeciesWithModificationResidue; public class SbmlParser implements IConverter { @@ -184,6 +186,12 @@ public class SbmlParser implements IConverter { for (Element element : model.getElements()) { if (element.getWidth() == 0 || element.getHeight() == 0) { bioEntitesRequiringLayout.add(element); + } else if (element instanceof SpeciesWithModificationResidue) { + for (ModificationResidue mr : ((SpeciesWithModificationResidue) element).getModificationResidues()) { + if (mr.getPosition() == null) { + bioEntitesRequiringLayout.add(element); + } + } } } for (Reaction reaction : model.getReactions()) { diff --git a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/species/SbmlSpeciesExporter.java b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/species/SbmlSpeciesExporter.java index eb1b3053c6da1e9d591440e0dc0659d53af24a72..670c655dbc548660877cc1b995a479600597597e 100644 --- a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/species/SbmlSpeciesExporter.java +++ b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/species/SbmlSpeciesExporter.java @@ -1,11 +1,19 @@ package lcsb.mapviewer.converter.model.sbml.species; +import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; import org.sbml.jsbml.Model; import org.sbml.jsbml.ext.layout.AbstractReferenceGlyph; +import org.sbml.jsbml.ext.layout.BoundingBox; +import org.sbml.jsbml.ext.layout.Dimensions; +import org.sbml.jsbml.ext.layout.Point; import org.sbml.jsbml.ext.multi.MultiModelPlugin; import org.sbml.jsbml.ext.multi.MultiSpeciesPlugin; import org.sbml.jsbml.ext.multi.MultiSpeciesType; @@ -20,10 +28,24 @@ import lcsb.mapviewer.converter.model.sbml.SbmlElementExporter; import lcsb.mapviewer.converter.model.sbml.SbmlExtension; import lcsb.mapviewer.converter.model.sbml.compartment.SbmlCompartmentExporter; import lcsb.mapviewer.model.map.InconsistentModelException; +import lcsb.mapviewer.model.map.species.AntisenseRna; import lcsb.mapviewer.model.map.species.Complex; import lcsb.mapviewer.model.map.species.Element; +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.AbstractRegionModification; +import lcsb.mapviewer.model.map.species.field.AbstractSiteModification; +import lcsb.mapviewer.model.map.species.field.BindingRegion; +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; +import lcsb.mapviewer.model.map.species.field.RegulatoryRegion; +import lcsb.mapviewer.model.map.species.field.Residue; +import lcsb.mapviewer.model.map.species.field.SpeciesWithModificationResidue; +import lcsb.mapviewer.model.map.species.field.TranscriptionSite; public class SbmlSpeciesExporter extends SbmlElementExporter<Species, org.sbml.jsbml.Species> { @@ -32,7 +54,6 @@ public class SbmlSpeciesExporter extends SbmlElementExporter<Species, org.sbml.j /** * Default class logger. */ - @SuppressWarnings("unused") private static Logger logger = Logger.getLogger(SbmlSpeciesExporter.class); private SbmlCompartmentExporter compartmentExporter; @@ -75,6 +96,113 @@ public class SbmlSpeciesExporter extends SbmlElementExporter<Species, org.sbml.j result.addExtension("multi", multiExtension); assignStructuralStateToMulti(element, multiExtension, speciesType); assignPostionToCompartmentToMulti(element, multiExtension, speciesType); + assignElementModificationResiduesToMulti(element, multiExtension, speciesType); + } + + private void assignElementModificationResiduesToMulti(Species element, MultiSpeciesPlugin multiExtension, + MultiSpeciesType speciesType) { + if (element instanceof Protein) { + assignModificationResiduesToMulti(((Protein) element).getModificationResidues(), multiExtension, speciesType); + } else if (element instanceof Gene) { + assignModificationResiduesToMulti(((Gene) element).getModificationResidues(), multiExtension, speciesType); + } else if (element instanceof Rna) { + assignModificationResiduesToMulti(((Rna) element).getRegions(), multiExtension, speciesType); + } else if (element instanceof AntisenseRna) { + assignModificationResiduesToMulti(((AntisenseRna) element).getRegions(), multiExtension, speciesType); + } + + } + + private void assignModificationResiduesToMulti(Collection<ModificationResidue> modificationResidues, + MultiSpeciesPlugin multiExtension, MultiSpeciesType speciesType) { + for (ModificationResidue mr : modificationResidues) { + SpeciesFeatureType feature = null; + PossibleSpeciesFeatureValue value; + + if (mr instanceof BindingRegion) { + feature = getBindingRegionFeature(mr.getSpecies(), speciesType); + } else if (mr instanceof CodingRegion) { + feature = getCodingRegionFeature(mr.getSpecies(), speciesType); + } else if (mr instanceof ProteinBindingDomain) { + feature = getProteinBindingDomainFeature(mr.getSpecies(), speciesType); + } else if (mr instanceof RegulatoryRegion) { + feature = getRegulatoryRegionFeature(mr.getSpecies(), speciesType); + } else if (mr instanceof TranscriptionSite) { + feature = getTranscriptionSiteFeature(mr.getSpecies(), speciesType); + } else if (mr instanceof ModificationSite) { + feature = getModificationSiteFeature((ModificationSite) mr, speciesType); + } else if (mr instanceof Residue) { + feature = getResidueFeature((Residue) mr, speciesType); + } else { + logger.warn("Don't know how to export modification: " + mr.getClass()); + } + value = getPosibleFeatureIdByName(mr.getName(), feature); + SpeciesFeatureValue featureValue = addSpeciesFeatureValue(multiExtension, feature, value); + featureValue.setId(getModificationResidueUniqueId(mr)); + } + } + + private SpeciesFeatureType getCodingRegionFeature(Species species, MultiSpeciesType speciesType) { + String featureId = MultiPackageNamingUtils.getModificationFeatureId(species, CodingRegion.class); + String featureName = "Coding region"; + return getOrCreateFeatureById(featureId, featureName, speciesType); + } + + private SpeciesFeatureType getBindingRegionFeature(Species species, MultiSpeciesType speciesType) { + String featureId = MultiPackageNamingUtils.getModificationFeatureId(species, BindingRegion.class); + String featureName = "Binding region"; + return getOrCreateFeatureById(featureId, featureName, speciesType); + } + + private SpeciesFeatureType getProteinBindingDomainFeature(Species species, MultiSpeciesType speciesType) { + String featureId = MultiPackageNamingUtils.getModificationFeatureId(species, ProteinBindingDomain.class); + String featureName = "Protein binding domain"; + return getOrCreateFeatureById(featureId, featureName, speciesType); + } + + private SpeciesFeatureType getRegulatoryRegionFeature(Species species, MultiSpeciesType speciesType) { + String featureId = MultiPackageNamingUtils.getModificationFeatureId(species, RegulatoryRegion.class); + String featureName = "Regulatory region"; + return getOrCreateFeatureById(featureId, featureName, speciesType); + } + + private SpeciesFeatureType getTranscriptionSiteFeature(Species species, MultiSpeciesType speciesType) { + String featureId = MultiPackageNamingUtils.getModificationFeatureId(species, TranscriptionSite.class); + String featureName = "Transcription site"; + return getOrCreateFeatureById(featureId, featureName, speciesType); + } + + private SpeciesFeatureType getModificationSiteFeature(ModificationSite modificationSite, + MultiSpeciesType speciesType) { + String featureId = MultiPackageNamingUtils.getModificationFeatureId(modificationSite.getSpecies(), + ModificationSite.class, modificationSite.getState()); + String featureName = ""; + if (modificationSite.getState() != null) { + featureName = modificationSite.getState().getFullName(); + } + return getOrCreateFeatureById(featureId, featureName, speciesType); + } + + private SpeciesFeatureType getResidueFeature(Residue residue, MultiSpeciesType speciesType) { + String featureId = MultiPackageNamingUtils.getModificationFeatureId(residue.getSpecies(), Residue.class, + residue.getState()); + String featureName = ""; + if (residue.getState() != null) { + featureName = residue.getState().getFullName(); + } + return getOrCreateFeatureById(featureId, featureName, speciesType); + } + + private SpeciesFeatureType getOrCreateFeatureById(String featureId, String featureName, + MultiSpeciesType speciesType) { + SpeciesFeatureType feature = speciesType.getSpeciesFeatureType(featureId); + if (feature == null) { + feature = new SpeciesFeatureType(); + feature.setName(featureName); + feature.setId(featureId); + speciesType.getListOfSpeciesFeatureTypes().add(feature); + } + return feature; } private void assignStructuralStateToMulti(Species element, MultiSpeciesPlugin multiExtension, @@ -90,14 +218,28 @@ public class SbmlSpeciesExporter extends SbmlElementExporter<Species, org.sbml.j PossibleSpeciesFeatureValue structuralStateFeatureValue = getPosibleFeatureIdByName(structuralState, structuralStateFeature); - SpeciesFeature feature = multiExtension.createSpeciesFeature(); - feature.setSpeciesFeatureType(structuralStateFeature.getId()); - SpeciesFeatureValue value = new SpeciesFeatureValue(); - value.setValue(structuralStateFeatureValue.getId()); - feature.addSpeciesFeatureValue(value); + addSpeciesFeatureValue(multiExtension, structuralStateFeature, structuralStateFeatureValue); } } + private SpeciesFeatureValue addSpeciesFeatureValue(MultiSpeciesPlugin multiExtension, SpeciesFeatureType fetureType, + PossibleSpeciesFeatureValue possibleValue) { + SpeciesFeature feature = null; + for (SpeciesFeature existingFeature : multiExtension.getListOfSpeciesFeatures()) { + if (existingFeature.getSpeciesFeatureType().equals(fetureType.getId())) { + feature = existingFeature; + } + } + if (feature == null) { + feature = multiExtension.createSpeciesFeature(); + feature.setSpeciesFeatureType(fetureType.getId()); + } + SpeciesFeatureValue value = new SpeciesFeatureValue(); + value.setValue(possibleValue.getId()); + feature.addSpeciesFeatureValue(value); + return value; + } + private PossibleSpeciesFeatureValue getPosibleFeatureIdByName(String featureValueName, SpeciesFeatureType speciesFeature) { PossibleSpeciesFeatureValue structuralStateFeatureValue = null; @@ -122,11 +264,7 @@ public class SbmlSpeciesExporter extends SbmlElementExporter<Species, org.sbml.j PossibleSpeciesFeatureValue structuralStateFeatureValue = getPosibleFeatureIdByName(positionToCompartmentName, structuralStateFeature); - SpeciesFeature feature = multiExtension.createSpeciesFeature(); - feature.setSpeciesFeatureType(structuralStateFeature.getId()); - SpeciesFeatureValue value = new SpeciesFeatureValue(); - value.setValue(structuralStateFeatureValue.getId()); - feature.addSpeciesFeatureValue(value); + addSpeciesFeatureValue(multiExtension, structuralStateFeature, structuralStateFeatureValue); } private MultiSpeciesType getMultiSpeciesType(Species element) { @@ -168,6 +306,19 @@ public class SbmlSpeciesExporter extends SbmlElementExporter<Species, org.sbml.j structuralState = ((Complex) element).getStructuralState(); } multiDistinguisher = structuralState; + + if (element instanceof SpeciesWithModificationResidue) { + List<String> modifications = new ArrayList<>(); + for (ModificationResidue mr : ((SpeciesWithModificationResidue) element).getModificationResidues()) { + String modificationId = mr.getName() + mr.getClass().getSimpleName(); + if (mr instanceof AbstractSiteModification) { + modificationId += ((AbstractSiteModification) mr).getState(); + } + modifications.add(modificationId); + } + Collections.sort(modifications); + multiDistinguisher += "\n" + StringUtils.join(modifications, ","); + } } String result = element.getClass().getSimpleName() + "\n" + element.getName() + "\n" + compartmentName + "\n" + complexName @@ -234,12 +385,73 @@ public class SbmlSpeciesExporter extends SbmlElementExporter<Species, org.sbml.j return result; } - private void addPositionToCompartmentToPossibleValues(MultiSpeciesType speciesType, Species species) { - if (species.getPositionToCompartment() != null) { - SpeciesFeatureType feature = speciesType.getListOfSpeciesFeatureTypes() - .get(MultiPackageNamingUtils.getPositionToCompartmentFeatureId(species)); - addPosibleValueToFeature(feature, species.getPositionToCompartment().name()); + @Override + protected void assignLayoutToGlyph(Species element, AbstractReferenceGlyph speciesGlyph) { + super.assignLayoutToGlyph(element, speciesGlyph); + if (isExtensionEnabled(SbmlExtension.MULTI)) { + if (element instanceof SpeciesWithModificationResidue) { + for (ModificationResidue mr : ((SpeciesWithModificationResidue) element).getModificationResidues()) { + org.sbml.jsbml.Species sbmlSpecies = getSbmlModel().getSpecies(speciesGlyph.getReference()); + createModificationGlyph(mr, sbmlSpecies); + } + } } } + private void createModificationGlyph(ModificationResidue mr, org.sbml.jsbml.Species sbmlSpecies) { + MultiSpeciesPlugin speciesExtension = (MultiSpeciesPlugin) sbmlSpecies.getExtension("multi"); + SpeciesFeature feature = null; + String featureTypeId = MultiPackageNamingUtils.getModificationFeatureId(mr.getSpecies(), mr.getClass()); + if (mr instanceof AbstractSiteModification) { + featureTypeId = MultiPackageNamingUtils.getModificationFeatureId(mr.getSpecies(), mr.getClass(), + ((AbstractSiteModification) mr).getState()); + } + for (SpeciesFeature existingFeature : speciesExtension.getListOfSpeciesFeatures()) { + if (existingFeature.getSpeciesFeatureType().equals(featureTypeId)) { + feature = existingFeature; + } + } + + SpeciesFeatureValue modificationFeatureValue = null; + for (SpeciesFeatureValue featureValue : feature.getListOfSpeciesFeatureValues()) { + if (featureValue.getId().equals(getModificationResidueUniqueId(mr))) { + modificationFeatureValue = featureValue; + } + } + + AbstractReferenceGlyph modificationGlyph = getLayout().createGeneralGlyph("modification_" + (idCounter++), + modificationFeatureValue.getId()); + double width, height; + if (mr instanceof AbstractRegionModification) { + width = ((AbstractRegionModification) mr).getWidth(); + height = ((AbstractRegionModification) mr).getHeight(); + } else { + width = 12; + height = 12; + } + double x = mr.getPosition().getX() - width / 2; + double y = mr.getPosition().getY() - height / 2; + logger.debug(mr.getPosition().getX() + ";" + mr.getPosition().getY() + ";" + modificationFeatureValue.getId()); + logger.debug(x + ";" + y + ";" + modificationFeatureValue.getId()); + BoundingBox boundingBox = new BoundingBox(); + boundingBox.setPosition(new Point(x, y)); + Dimensions dimensions = new Dimensions(); + dimensions.setWidth(width); + dimensions.setHeight(height); + boundingBox.setDimensions(dimensions); + modificationGlyph.setBoundingBox(boundingBox); + } + + private int modificationResidueCounter = 0; + private Map<String, String> modificationResidueIds = new HashMap<>(); + + private String getModificationResidueUniqueId(ModificationResidue mr) { + String result = modificationResidueIds.get(mr.getIdModificationResidue() + "_" + getSbmlIdKey(mr.getSpecies())); + if (result == null) { + result = "modification_residue_" + (modificationResidueCounter++); + modificationResidueIds.put(mr.getIdModificationResidue() + "_" + getSbmlIdKey(mr.getSpecies()), result); + } + return result; + } + } diff --git a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/species/SbmlSpeciesParser.java b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/species/SbmlSpeciesParser.java index 1c184c16710a917e5e6da8ce3fc1632eef486f14..4fb0cf872e70171ca46f853ac62ffd1f7d6175d3 100644 --- a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/species/SbmlSpeciesParser.java +++ b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/species/SbmlSpeciesParser.java @@ -1,5 +1,6 @@ package lcsb.mapviewer.converter.model.sbml.species; +import java.awt.geom.Point2D; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.List; @@ -9,6 +10,8 @@ import org.sbml.jsbml.ListOf; import org.sbml.jsbml.Model; import org.sbml.jsbml.ext.layout.AbstractReferenceGlyph; import org.sbml.jsbml.ext.layout.CompartmentGlyph; +import org.sbml.jsbml.ext.layout.GeneralGlyph; +import org.sbml.jsbml.ext.layout.GraphicalObject; import org.sbml.jsbml.ext.layout.SpeciesGlyph; import org.sbml.jsbml.ext.multi.MultiModelPlugin; import org.sbml.jsbml.ext.multi.MultiSpeciesPlugin; @@ -33,7 +36,24 @@ import lcsb.mapviewer.model.map.species.Element; import lcsb.mapviewer.model.map.species.Protein; import lcsb.mapviewer.model.map.species.Species; import lcsb.mapviewer.model.map.species.Unknown; +import lcsb.mapviewer.model.map.species.field.AbstractRegionModification; +import lcsb.mapviewer.model.map.species.field.BindingRegion; +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.PositionToCompartment; +import lcsb.mapviewer.model.map.species.field.ProteinBindingDomain; +import lcsb.mapviewer.model.map.species.field.RegulatoryRegion; +import lcsb.mapviewer.model.map.species.field.Residue; +import lcsb.mapviewer.model.map.species.field.SpeciesWithBindingRegion; +import lcsb.mapviewer.model.map.species.field.SpeciesWithCodingRegion; +import lcsb.mapviewer.model.map.species.field.SpeciesWithModificationResidue; +import lcsb.mapviewer.model.map.species.field.SpeciesWithModificationSite; +import lcsb.mapviewer.model.map.species.field.SpeciesWithProteinBindingDomain; +import lcsb.mapviewer.model.map.species.field.SpeciesWithRegulatoryRegion; +import lcsb.mapviewer.model.map.species.field.SpeciesWithResidue; +import lcsb.mapviewer.model.map.species.field.SpeciesWithTranscriptionSite; +import lcsb.mapviewer.model.map.species.field.TranscriptionSite; import lcsb.mapviewer.modelutils.map.ElementUtils; public class SbmlSpeciesParser extends SbmlElementParser<org.sbml.jsbml.Species> { @@ -142,13 +162,91 @@ public class SbmlSpeciesParser extends SbmlElementParser<org.sbml.jsbml.Species> minervaElement.setPositionToCompartment(PositionToCompartment.getByString(positionToCompartments.get(0))); } } else { - logger.warn(warnPrefix + "Invalid structural state for class " + featureTypeString); + logger.warn(warnPrefix + "Position to compartment for class " + featureTypeString); } + } else if (MultiPackageNamingUtils.isModificationFeatureId(featureTypeString)) { + createModificationResidues(minervaElement, speciesType, feature); } else { logger.warn(warnPrefix + "Feature not supported: " + featureTypeString); } } + private void createModificationResidues(Species minervaElement, MultiSpeciesType speciesType, + SpeciesFeature feature) { + String warnPrefix = new ElementUtils().getElementTag(minervaElement); + ModificationResidue mr = null; + + String featureTypeString = feature.getSpeciesFeatureType(); + SpeciesFeatureType featureType = speciesType.getListOfSpeciesFeatureTypes().get(featureTypeString); + for (SpeciesFeatureValue featureValue : feature.getListOfSpeciesFeatureValues()) { + if (MultiPackageNamingUtils.isModificationFeatureId(featureTypeString, BindingRegion.class)) { + mr = new BindingRegion(); + if (minervaElement instanceof SpeciesWithBindingRegion) { + ((SpeciesWithBindingRegion) minervaElement).addBindingRegion((BindingRegion) mr); + } else { + logger.warn(warnPrefix + "Object class doesn't support " + mr.getClass()); + } + } else if (MultiPackageNamingUtils.isModificationFeatureId(featureTypeString, CodingRegion.class)) { + mr = new CodingRegion(); + if (minervaElement instanceof SpeciesWithCodingRegion) { + ((SpeciesWithCodingRegion) minervaElement).addCodingRegion((CodingRegion) mr); + } else { + logger.warn(warnPrefix + "Object class doesn't support " + mr.getClass()); + } + } else if (MultiPackageNamingUtils.isModificationFeatureId(featureTypeString, ProteinBindingDomain.class)) { + mr = new ProteinBindingDomain(); + if (minervaElement instanceof SpeciesWithProteinBindingDomain) { + ((SpeciesWithProteinBindingDomain) minervaElement).addProteinBindingDomain((ProteinBindingDomain) mr); + } else { + logger.warn(warnPrefix + "Object class doesn't support " + mr.getClass()); + } + } else if (MultiPackageNamingUtils.isModificationFeatureId(featureTypeString, RegulatoryRegion.class)) { + mr = new RegulatoryRegion(); + if (minervaElement instanceof SpeciesWithRegulatoryRegion) { + ((SpeciesWithRegulatoryRegion) minervaElement).addRegulatoryRegion((RegulatoryRegion) mr); + } else { + logger.warn(warnPrefix + "Object class doesn't support " + mr.getClass()); + } + } else if (MultiPackageNamingUtils.isModificationFeatureId(featureTypeString, TranscriptionSite.class)) { + mr = new TranscriptionSite(); + if (minervaElement instanceof SpeciesWithTranscriptionSite) { + ((SpeciesWithTranscriptionSite) minervaElement).addTranscriptionSite((TranscriptionSite) mr); + } else { + logger.warn(warnPrefix + "Object class doesn't support " + mr.getClass()); + } + } else if (MultiPackageNamingUtils.isModificationFeatureId(featureTypeString, ModificationSite.class)) { + mr = new ModificationSite(); + ((ModificationSite) mr) + .setState(MultiPackageNamingUtils.getModificationStateFromFeatureTypeName(featureTypeString)); + if (minervaElement instanceof SpeciesWithModificationSite) { + ((SpeciesWithModificationSite) minervaElement).addModificationSite((ModificationSite) mr); + } else { + logger.warn(warnPrefix + "Object class doesn't support " + mr.getClass()); + } + } else if (MultiPackageNamingUtils.isModificationFeatureId(featureTypeString, Residue.class)) { + mr = new Residue(); + ((Residue) mr) + .setState(MultiPackageNamingUtils.getModificationStateFromFeatureTypeName(featureTypeString)); + if (minervaElement instanceof SpeciesWithResidue) { + ((SpeciesWithResidue) minervaElement).addResidue((Residue) mr); + } else { + logger.warn(warnPrefix + "Object class doesn't support " + mr.getClass()); + } + } else { + logger.warn(warnPrefix + "Unsupported modification type: " + featureTypeString); + } + PossibleSpeciesFeatureValue possibleSpeciesFeatureValue = featureType.getListOfPossibleSpeciesFeatureValues() + .get(featureValue.getValue()); + if (possibleSpeciesFeatureValue != null) { + mr.setName(possibleSpeciesFeatureValue.getName()); + mr.setIdModificationResidue(featureValue.getId()); + } else { + logger.warn(warnPrefix + "Invalid feature value: " + featureValue.getValue()); + } + } + + } + private String extractSBOTermFromSpecies(org.sbml.jsbml.Species species) { String sboTerm = species.getSBOTermID(); MultiSpeciesPlugin multiExtension = (MultiSpeciesPlugin) species.getExtension("multi"); @@ -184,10 +282,42 @@ public class SbmlSpeciesParser extends SbmlElementParser<org.sbml.jsbml.Species> } } assignCompartment(element, compartmentId); + assignModificationResiduesLayout(element); } return result; } + private void assignModificationResiduesLayout(Element element) { + if (element instanceof SpeciesWithModificationResidue) { + for (ModificationResidue mr : ((SpeciesWithModificationResidue) element).getModificationResidues()) { + GeneralGlyph residueGlyph = null; + for (GraphicalObject graphicalObject : getLayout().getListOfAdditionalGraphicalObjects()) { + if (graphicalObject instanceof GeneralGlyph) { + if (((GeneralGlyph) graphicalObject).getReference().equals(mr.getIdModificationResidue())) { + residueGlyph = (GeneralGlyph) graphicalObject; + } + } + } + if (residueGlyph != null) { + if (residueGlyph.getBoundingBox() == null || residueGlyph.getBoundingBox().getDimensions() == null) { + logger.warn(new ElementUtils().getElementTag(mr) + "Layout doesn't contain coordinates"); + } else { + double width = residueGlyph.getBoundingBox().getDimensions().getWidth(); + double height = residueGlyph.getBoundingBox().getDimensions().getHeight(); + double x = residueGlyph.getBoundingBox().getPosition().getX(); + double y = residueGlyph.getBoundingBox().getPosition().getY(); + mr.setPosition(new Point2D.Double(x + width / 2, y + height / 2)); + if (mr instanceof AbstractRegionModification) { + ((AbstractRegionModification) mr).setWidth(width); + ((AbstractRegionModification) mr).setHeight(height); + } + } + } + } + } + + } + private void assignCompartment(Element element, String compartmentId) { Compartment compartment = getMinervaModel().getElementByElementId(compartmentId); if (compartment == null && getLayout() != null) { diff --git a/converter-sbml/src/test/java/lcsb/mapviewer/converter/model/sbml/SbmlExporterTest.java b/converter-sbml/src/test/java/lcsb/mapviewer/converter/model/sbml/SbmlExporterTest.java index 5181a0ff31165f12502c278e49534c43a73b1f49..1a6733fff5661640f0fedf4dfee8a79ca2536727 100644 --- a/converter-sbml/src/test/java/lcsb/mapviewer/converter/model/sbml/SbmlExporterTest.java +++ b/converter-sbml/src/test/java/lcsb/mapviewer/converter/model/sbml/SbmlExporterTest.java @@ -595,14 +595,17 @@ public class SbmlExporterTest { Residue mr = new Residue("x1"); mr.setName("217U"); mr.setState(ModificationState.PHOSPHORYLATED); + mr.setPosition(new Point2D.Double(10,11)); element.addResidue(mr); mr = new Residue("Y"); mr.setName("218"); mr.setState(ModificationState.PHOSPHORYLATED); + mr.setPosition(new Point2D.Double(10,12)); element.addResidue(mr); mr = new Residue("Z"); mr.setName("219"); mr.setState(ModificationState.UBIQUITINATED); + mr.setPosition(new Point2D.Double(10,13)); element.addResidue(mr); model.addElement(element); Model deserializedModel = getModelAfterSerializing(model); diff --git a/model/src/main/java/lcsb/mapviewer/modelutils/map/ElementUtils.java b/model/src/main/java/lcsb/mapviewer/modelutils/map/ElementUtils.java index 94777c846e43dc0a6bfa7ddac3d4dadeaccef60e..5313c5b44f9ddb33b98d4fc1981c46e7e9f43957 100644 --- a/model/src/main/java/lcsb/mapviewer/modelutils/map/ElementUtils.java +++ b/model/src/main/java/lcsb/mapviewer/modelutils/map/ElementUtils.java @@ -16,6 +16,7 @@ import lcsb.mapviewer.model.map.BioEntity; import lcsb.mapviewer.model.map.reaction.Reaction; import lcsb.mapviewer.model.map.reaction.ReactionNode; import lcsb.mapviewer.model.map.species.Element; +import lcsb.mapviewer.model.map.species.field.ModificationResidue; /** * Class with some util method for {@link BioEntity} objects. @@ -262,4 +263,9 @@ public final class ElementUtils { return "[" + node.getClass().getSimpleName() + "]" + getElementTag(node.getElement()); } + public String getElementTag(ModificationResidue mr) { + return "[" + mr.getClass().getSimpleName() + "," + mr.getIdModificationResidue() + "]" + + getElementTag(mr.getSpecies()); + } + }