From 29565253c3eda9d399c43c89e006634f3f4441e7 Mon Sep 17 00:00:00 2001 From: metincansiper Date: Mon, 30 Apr 2018 16:18:16 -0700 Subject: [PATCH] first commit --- .gitignore | 5 + WebContent/META-INF/MANIFEST.MF | 3 + WebContent/WEB-INF/web.xml | 12 + pom.xml | 93 +++++ src/main/java/converter/FactoidToBiopax.java | 284 ++++++++++++++ src/main/java/model/BioPAXModel.java | 377 +++++++++++++++++++ src/main/java/model/TemplatesModel.java | 255 +++++++++++++ src/main/java/web/ConvertToOwlServlet.java | 57 +++ src/test/java/model/BioPAXModelTest.java | 192 ++++++++++ 9 files changed, 1278 insertions(+) create mode 100644 .gitignore create mode 100644 WebContent/META-INF/MANIFEST.MF create mode 100644 WebContent/WEB-INF/web.xml create mode 100644 pom.xml create mode 100644 src/main/java/converter/FactoidToBiopax.java create mode 100644 src/main/java/model/BioPAXModel.java create mode 100644 src/main/java/model/TemplatesModel.java create mode 100644 src/main/java/web/ConvertToOwlServlet.java create mode 100644 src/test/java/model/BioPAXModelTest.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bc1be14 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.DS_Store +.classpath +.project +.settings +target \ No newline at end of file diff --git a/WebContent/META-INF/MANIFEST.MF b/WebContent/META-INF/MANIFEST.MF new file mode 100644 index 0000000..5e94951 --- /dev/null +++ b/WebContent/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Class-Path: + diff --git a/WebContent/WEB-INF/web.xml b/WebContent/WEB-INF/web.xml new file mode 100644 index 0000000..302a113 --- /dev/null +++ b/WebContent/WEB-INF/web.xml @@ -0,0 +1,12 @@ + + + factoid-to-biopax-server + + index.html + index.htm + index.jsp + default.html + default.htm + default.jsp + + \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..93b707c --- /dev/null +++ b/pom.xml @@ -0,0 +1,93 @@ + + 4.0.0 + factoid-to-biopax-server + factoid-to-biopax-server + 0.0.1-SNAPSHOT + war + + TomcatServer + + + src/main/java + + + maven-compiler-plugin + 3.7.0 + + 1.8 + 1.8 + + + + maven-war-plugin + 3.0.0 + + WebContent + + + + org.apache.tomcat.maven + tomcat7-maven-plugin + 2.2 + + http://localhost:8080/manager/text + ${tomcat.server.name} + /FactoidToBiopaxServer + + + + + + + + org.biopax.paxtools + paxtools-core + 5.0.1 + + + + + org.apache.commons + commons-collections4 + 4.1 + + + + + org.apache.commons + commons-lang3 + 3.7 + + + + + com.google.guava + guava + 24.1-jre + + + org.slf4j + slf4j-api + 1.7.25 + + + + com.google.code.gson + gson + 2.8.2 + + + + junit + junit + 4.12 + test + + + + javax.servlet + javax.servlet-api + 3.1.0 + + + \ No newline at end of file diff --git a/src/main/java/converter/FactoidToBiopax.java b/src/main/java/converter/FactoidToBiopax.java new file mode 100644 index 0000000..6ccf83c --- /dev/null +++ b/src/main/java/converter/FactoidToBiopax.java @@ -0,0 +1,284 @@ +package converter; + +import java.io.Reader; +/* + * A converter class that gets a JSON object that includes sequence of BioPAX templates and enables + * conversion to BioPAX by adding these templates to underlying Templates Model instance. + */ +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.biopax.paxtools.model.level3.ControlType; + +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import model.*; + +public class FactoidToBiopax { + + private TemplatesModel model; + private JsonParser jsonParser; + private Gson gson; + + public FactoidToBiopax() { + model = new TemplatesModel(); + jsonParser = new JsonParser(); + gson = new Gson(); + } + + public void addToModel(String templatesContent) { + JsonArray templates = jsonParser.parse(templatesContent).getAsJsonArray(); + addToModel(templates); + } + + public void addToModel(Reader contentReader) { + JsonArray templates = jsonParser.parse(contentReader).getAsJsonArray(); + addToModel(templates); + } + + public void addToModel(JsonArray templates) { + + Iterator it = templates.iterator(); + + while (it.hasNext()) { + JsonObject template = (JsonObject) it.next(); + String typeStr = template.get("type").getAsString(); + System.out.println(typeStr); + + if (matchesTemplateType(typeStr, TemplateType.ACTIVITION_INHIBITION)) { + String regulatorProteinName = template.get("regulatorProtein").getAsString(); + String effectTypeStr = (String) template.get("effectType").getAsString(); + String targetProteinName = (String) template.get("targetProtein").getAsString(); + + addActivationInhibition(regulatorProteinName, targetProteinName, effectTypeStr); + } + else if (matchesTemplateType(typeStr, TemplateType.BIOCHEMICAL_REACTION)) { + String catalyzerName = template.get("catalyzerName").getAsString(); + + JsonArray inputMoleculeNamesJSON = template.get("inputSmallMolecules").getAsJsonArray(); + JsonArray outputMoleculeNamesJSON = template.get("outputSmallMolecules").getAsJsonArray(); + + List inputMoleculeNames = gson.fromJson(inputMoleculeNamesJSON, List.class); + List outputMoleculeNames = gson.fromJson(outputMoleculeNamesJSON, List.class); + + addBiochemicalReaction(catalyzerName, inputMoleculeNames, outputMoleculeNames); + } + else if (matchesTemplateType(typeStr, TemplateType.COMPLEX_ASSOCIATION)) { + JsonArray moleculeNamesJSON = template.get("moleculeList").getAsJsonArray(); + List moleculeNames = gson.fromJson(moleculeNamesJSON, List.class); + + addComplexAssociation(moleculeNames); + } + else if(matchesTemplateType(typeStr, TemplateType.COMPLEX_DISSOCIATION)) { + JsonArray moleculeNamesJSON = template.get("moleculeList").getAsJsonArray(); + List moleculeNames = gson.fromJson(moleculeNamesJSON, List.class); + + addComplexDissociation(moleculeNames); + } + else if (matchesTemplateType(typeStr, TemplateType.EXPRESSION_REGULATION)) { + String transcriptionFactorName = template.get("transcriptionFactor").getAsString(); + String targetProtName = template.get("targetProtein").getAsString(); + String effectTypeStr = template.get("effectType").getAsString(); + + addRegulationOfExpression(transcriptionFactorName, targetProtName, effectTypeStr); + } + else if(matchesTemplateType(typeStr, TemplateType.LOCATION_CHANGE)) { + JsonArray macromoleculeNamesJSON = template.get("macromoleculeList").getAsJsonArray(); + List macromoleculeNames = gson.fromJson(macromoleculeNamesJSON, List.class); + + String controllerProteinName = template.get("contollerProtein").getAsString(); + String oldLocation = template.get("oldLocation").getAsString(); + String newLocation = template.get("newLocation").getAsString(); + String controlTypeStr = template.get("controlType").getAsString(); + + addLocationChange(macromoleculeNames, controllerProteinName, oldLocation, newLocation, controlTypeStr); + } + else if(matchesTemplateType(typeStr, TemplateType.PHYSICAL_INTERACTION)) { + JsonArray moleculeNamesJSON = template.get("moleculeList").getAsJsonArray(); + List moleculeNames = gson.fromJson(moleculeNamesJSON, List.class); + + addComplexDissociation(moleculeNames); + } + else if(matchesTemplateType(typeStr, TemplateType.PROTEIN_MODIFICATION)) { + String modifiedProteinName = template.get("modifiedProtein").getAsString(); + String controllerProteinName = template.get("controllerProtein").getAsString(); + String modificationType = template.get("modification").getAsString(); + String controlTypeStr = template.get("controlType").getAsString(); + + addProteinModification(modifiedProteinName, controllerProteinName, modificationType, controlTypeStr); + } + } + } + + public String convertToOwl() { + return model.convertToOwl(); + } + + private static String getTemplateName(TemplateType templateType) { + return templateType.getName(); + } + + private static boolean matchesTemplateType(String typeStr, TemplateType templateType) { + return typeStr.equalsIgnoreCase(getTemplateName(templateType)); + } + + private ControlType getControlType(String controlTypeStr) { + return CONTROL_TYPE_MAP.get(controlTypeStr.toUpperCase()); + } + + private void addLocationChange(List macromoleculeNames, String controllerProteinName, String oldLocation, + String newLocation, String controlTypeStr) { + + ControlType controlType = getControlType(controlTypeStr); + model.addLocationChange(macromoleculeNames, controllerProteinName, oldLocation, newLocation, controlType); + } + + private void addProteinModification(String modifiedProteinName, String controllerProteinName, String modificationType, String controlTypeStr) { + ControlType controlType = getControlType(controlTypeStr); + model.addProteinModification(modifiedProteinName, controllerProteinName, modificationType, controlType); + } + + private void addComplexAssociation(List moleculeNames) { + model.addComplexAssociation(moleculeNames); + } + + private void addComplexDissociation(List macromoleculeNames) { + model.addComplexDissociation(macromoleculeNames); + } + + private void addPhysicalInteraction(List moleculeNames) { + model.addPhysicalInteraction(moleculeNames); + } + + private void addBiochemicalReaction(String catalyzerName, List inputMoleculeNames, List outputMoleculeNames) { + model.addBiochemicalReaction(catalyzerName, inputMoleculeNames, outputMoleculeNames); + } + + private void addActivationInhibition(String regulatorProteinName, String targetProteinName, String effectTypeStr) { + ControlType effectType = getControlType(effectTypeStr); + model.addActivationInhibition(regulatorProteinName, targetProteinName, effectType); + } + + private void addRegulationOfExpression(String transcriptionFactorName, String targetProtName, String effectTypeStr) { + ControlType effectType = getControlType(effectTypeStr); + model.addRegulationOfExpression(transcriptionFactorName, targetProtName, effectType); + } + + private static Map createControlTypeMap() { + Map map = new HashMap(); + map.put("ACTIVATION", ControlType.ACTIVATION); + map.put("INHIBITION", ControlType.INHIBITION); + + return map; + } + + private static enum TemplateType { + PROTEIN_MODIFICATION("Protein Modification"), + COMPLEX_ASSOCIATION("Complex Association"), + COMPLEX_DISSOCIATION("Complex Dissociation"), + LOCATION_CHANGE("Location Change"), + BIOCHEMICAL_REACTION("Biochemical Reaction"), + PHYSICAL_INTERACTION("Physical Interaction"), + ACTIVITION_INHIBITION("Activation Inhibition"), + EXPRESSION_REGULATION("Expression Regulation"); + + private String name; + + TemplateType(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public String toString() { + return getName(); + } + } + + private static final Map CONTROL_TYPE_MAP = createControlTypeMap(); + + public static void main(String[] args) { + JsonArray templates = new JsonArray(); + + JsonArray inputList = new JsonArray(); + JsonArray outputList = new JsonArray(); + JsonArray moleculeList = new JsonArray(); + + inputList.add("input1"); + inputList.add("input2"); + + outputList.add("output1"); + outputList.add("output2"); + + moleculeList.add("molecule1"); + moleculeList.add("molecule2"); + + JsonObject template1 = new JsonObject(); + template1.addProperty("type", TemplateType.ACTIVITION_INHIBITION.getName()); + template1.addProperty("regulatorProtein", "regulatorProtein"); + template1.addProperty("effectType", "effectType"); + template1.addProperty("targetProtein", "targetProtein"); + templates.add(template1); + + JsonObject template2 = new JsonObject(); + template2.addProperty("type", TemplateType.BIOCHEMICAL_REACTION.getName()); + template2.addProperty("catalyzerName", "catalyzerName"); + template2.add("inputSmallMolecules", inputList); + template2.add("outputSmallMolecules", outputList); + templates.add(template2); + + JsonObject template3 = new JsonObject(); + template3.addProperty("type", TemplateType.COMPLEX_ASSOCIATION.getName()); + template3.add("moleculeList", moleculeList); + templates.add(template3); + + JsonObject template4 = new JsonObject(); + template4.addProperty("type", TemplateType.COMPLEX_DISSOCIATION.getName()); + template4.add("moleculeList", moleculeList); + templates.add(template4); + + JsonObject template5 = new JsonObject(); + template5.addProperty("type", TemplateType.EXPRESSION_REGULATION.getName()); + template5.addProperty("transcriptionFactor", "transcriptionFactor"); + template5.addProperty("targetProtein", "targetProtein"); + template5.addProperty("effectType", "activation"); + templates.add(template5); + + JsonObject template6 = new JsonObject(); + template6.addProperty("type", TemplateType.LOCATION_CHANGE.getName()); + template6.add("macromoleculeList", moleculeList); + template6.addProperty("controlType", "activation"); + template6.addProperty("contollerProtein", "contollerProtein"); + template6.addProperty("oldLocation", "oldLocation"); + template6.addProperty("newLocation", "newLocation"); + templates.add(template6); + + JsonObject template7 = new JsonObject(); + template7.addProperty("type", TemplateType.PHYSICAL_INTERACTION.getName()); + template7.add("moleculeList", moleculeList); + templates.add(template7); + + JsonObject template8 = new JsonObject(); + template8.addProperty("type", TemplateType.PROTEIN_MODIFICATION.getName()); + template8.addProperty("modifiedProtein", "modifiedProtein"); + template8.addProperty("controllerProtein", "controllerProtein"); + template8.addProperty("controlType", "activation"); + template8.addProperty("modification", "phosphorylated"); + templates.add(template8); + + FactoidToBiopax converter = new FactoidToBiopax(); + converter.addToModel(templates); + + System.out.println(converter.convertToOwl()); + + System.out.println(TemplateType.ACTIVITION_INHIBITION.getName().equals("Activation Inhibition")); + } +} diff --git a/src/main/java/model/BioPAXModel.java b/src/main/java/model/BioPAXModel.java new file mode 100644 index 0000000..32cd1a0 --- /dev/null +++ b/src/main/java/model/BioPAXModel.java @@ -0,0 +1,377 @@ +/* + * A model class that keeps an underlying PaxTools model and enables updating it by wrapper functions. + * This model is designed to avoid duplications of BioPAX elements in certain conditions. + */ + +package model; + +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.UUID; +import java.util.stream.Collectors; + +import org.apache.commons.collections4.map.MultiKeyMap; +import org.biopax.paxtools.io.SimpleIOHandler; +import org.biopax.paxtools.model.BioPAXElement; +import org.biopax.paxtools.model.BioPAXFactory; +import org.biopax.paxtools.model.BioPAXLevel; +import org.biopax.paxtools.model.Model; +import org.biopax.paxtools.model.level3.CellularLocationVocabulary; +import org.biopax.paxtools.model.level3.Control; +import org.biopax.paxtools.model.level3.ControlType; +import org.biopax.paxtools.model.level3.ControlledVocabulary; +import org.biopax.paxtools.model.level3.Controller; +import org.biopax.paxtools.model.level3.Conversion; +import org.biopax.paxtools.model.level3.ConversionDirectionType; +import org.biopax.paxtools.model.level3.EntityFeature; +import org.biopax.paxtools.model.level3.EntityReference; +import org.biopax.paxtools.model.level3.ModificationFeature; +import org.biopax.paxtools.model.level3.PhysicalEntity; +import org.biopax.paxtools.model.level3.Process; +import org.biopax.paxtools.model.level3.Protein; +import org.biopax.paxtools.model.level3.ProteinReference; +import org.biopax.paxtools.model.level3.SequenceModificationVocabulary; +import org.biopax.paxtools.model.level3.SimplePhysicalEntity; + +public class BioPAXModel { + + // Underlying paxtools model + private Model model; + // Map of term to cellular location + private Map cellularLocationMap; + // Multiple key map of entity reference class and name to entity reference itself + private MultiKeyMap entityReferenceMap; + + // Section: constructors + + public BioPAXModel() { + BioPAXFactory factory = BioPAXLevel.L3.getDefaultFactory(); + model = factory.createModel(); + + cellularLocationMap = new HashMap(); + entityReferenceMap = new MultiKeyMap(); + } + + // Section: public methods + + // add a new element to model with given id + public T addNew(Class c, String id) { + return model.addNew(c, id); + } + + // add a new element to model by generating element id + public T addNew(Class c) { + return addNew(c, generateUUID()); + } + + // Just get a physical entity, create it if not available yet. + // Do not create duplicate entities if entity references, cellular locations and modifications set matches. + public T getOrCreatePhysicalEntity(Class c, String name, CellularLocationVocabulary cellularLocation, EntityReference entityRef, Set modificationTypes) { + + T entity = null; + + if (entityRef != null) { + assertSimplePhysicalEntityOrSubclass(c); + + Set entities = (Set) entityRef.getEntityReferenceOf(); + entity = findMatchingEntity(entities, cellularLocation, modificationTypes); + } + + if (entity == null) { + entity = addNewPhysicalEntity(c, name, cellularLocation, entityRef, modificationTypes); + } + + return entity; + } + + public T getOrCreatePhysicalEntity(Class c, String name, CellularLocationVocabulary cellularLocation, EntityReference entityRef) { + return getOrCreatePhysicalEntity(c, name, cellularLocation, entityRef, null); + } + + public T getOrCreatePhysicalEntity(Class c, String name) { + return getOrCreatePhysicalEntity(c, name, null, null); + } + + public T getOrCreatePhysicalEntity(Class c) { + return getOrCreatePhysicalEntity(c, null); + } + + // Get cellular location mathcing the given term, create one if not available + public CellularLocationVocabulary getOrCreateCellularLocationVocabulary(String term) { + + CellularLocationVocabulary clv = cellularLocationMap.get(term); + + // if a clv does not exists for the term create one here and put it to the map + if(clv == null) { + clv = addNewControlledVocabulary(CellularLocationVocabulary.class, term); + cellularLocationMap.put(term, clv); + } + + return clv; + } + + // Get modification feature that has the given modification type. Create one if not available. + public ModificationFeature getOrCreateModificationFeature(String modificationType, EntityReference entityRef) { + + Set referenceModifications = entityRef.getEntityFeature(); + ModificationFeature modificationFeature = getFeatureByModificationType((Set)referenceModifications, modificationType); + + // if a modification feature does not exists for the modification type create one here and put it to the map + if (modificationFeature == null) { + modificationFeature = addNewModificationFeature(modificationType); + entityRef.addEntityFeature(modificationFeature); + } + + return modificationFeature; + } + + // Get entity reference that has given name and class, create a new one is not available yet. + public T getOrCreateEntityReference(Class c, String name) { + + T entityRef = (T) entityReferenceMap.get(c, name); + + if (entityRef == null) { + entityRef = addNewEntityReference(c, name); + entityReferenceMap.put(c, name, entityRef); + } + + return entityRef; + } + + // Create a new conversion by given properties + public T addNewConversion(Class c, PhysicalEntity left, PhysicalEntity right, ConversionDirectionType dir) { + + T conversion = addNew(c); + + if(left != null) { + conversion.addLeft(left); + } + + if(right != null) { + conversion.addRight(right); + } + + if(dir != null) { + conversion.setConversionDirection(dir); + } + + return conversion; + } + + public T addNewConversion(Class c) { + return addNewConversion(c, null, null); + } + + public T addNewConversion(Class c, PhysicalEntity left, PhysicalEntity right) { + return addNewConversion(c, left, right, ConversionDirectionType.LEFT_TO_RIGHT); + } + + // Create a new control instance by given properties + public T addNewControl(Class c, Controller controller, Process controlled, ControlType controlType) { + + T control = addNew(c); + + if(controller != null) { + control.addController(controller); + } + + if(controlled != null) { + control.addControlled(controlled); + } + + if(controlType != null) { + control.setControlType(controlType); + } + + return control; + } + + public String convertToOwl() { + return SimpleIOHandler.convertToOwl(model); + } + + // Section: private helper methods + + // Generate unique id for new elements + private static String generateUUID() { + return UUID.randomUUID().toString(); + } + + // Find the physical entity that has the expected cellular location and modification types + private T findMatchingEntity(Set entities, CellularLocationVocabulary cellularLocation, Set modificationTypes){ + + Optional match = entities.stream().filter(t -> { + CellularLocationVocabulary clv = t.getCellularLocation(); + return clv != null && clv.equals(cellularLocation) + && isAbstractionOf(getModificationFeatureOfEntity(t), modificationTypes); + } ).findFirst(); + + if (match.isPresent()) { + return match.get(); + } + + return null; + } + + private static Set getModificationFeatureOfEntity(PhysicalEntity entity){ + + Set entityFeatures = entity.getFeature(); + + // Assert that any entity feature is a ModificationFeature since other kind of entity features are + // not supposed to be created + assert allAreInstanceOfModificationFeature(entityFeatures) : + "All members of feature set is expected to have modification feature type"; + + // Do not filter modification features by relying on the assumption that all features are + // modification feature for better performance. If that is not the case the assertion above is + // suppose to fail. + return (Set) entityFeatures; + } + + // TODO why cannot make static? + private void assertSimplePhysicalEntityOrSubclass(Class c, String messageOpt) { + + String message = null; + + if (messageOpt == null) { + message = "Entity reference field is valid only for instances of SimplePhysicalEntity and its subclasses"; + } + else { + message = messageOpt; + } + + assert SimplePhysicalEntity.class.isAssignableFrom(c) : message; + } + + private void assertSimplePhysicalEntityOrSubclass(Class c) { + assertSimplePhysicalEntityOrSubclass(c, null); + } + + // TODO try converting this to allInstanceOfModificationFeature(Class? c, Collection collection) + private static boolean allAreInstanceOfModificationFeature(Collection collection) { + Iterator it = collection.iterator(); + while(it.hasNext()) { + Object o = it.next(); + if (!(o instanceof ModificationFeature)) { + return false; + } + } + return true; + } + + // Check if modificationTypes set is an abstraction of modifications set + private static boolean isAbstractionOf(Set modifications, Set modificationTypes) { + + // return false if only one side is null + if ( (modifications == null) == !(modificationTypes == null) ) { + return false; + } + + // return true if both sides are null + // note that we made sure that either both or none is null + if (modifications == null) { + return true; + } + + if (modifications.isEmpty() && modificationTypes.isEmpty()) { + return true; + } + + if (modifications.size() != modificationTypes.size()) { + return false; + } + + return modifications.stream().map(t -> getOnlyElement(t.getModificationType().getTerm())).collect(Collectors.toSet()).equals(modificationTypes); + } + + // get only element of collection + // TODO this method would be moved to a utility file + private static T getOnlyElement(Collection collection) { + return collection.iterator().next(); + } + + // Create a new physical entity with given properties + private T addNewPhysicalEntity(Class c, String name, CellularLocationVocabulary cellularLocation, + EntityReference entityRef, Set modificationTypes) { + + T entity = addNew(c); + + if (name != null) { + entity.setDisplayName(name); + } + + if (entityRef != null) { + assertSimplePhysicalEntityOrSubclass(c); + + ((SimplePhysicalEntity) entity).setEntityReference(entityRef); + } + + if (cellularLocation != null) { + entity.setCellularLocation(cellularLocation); + } + + if (modificationTypes != null) { + for(String modificationType : modificationTypes) { + ModificationFeature modificationFeature = getOrCreateModificationFeature(modificationType, entityRef); + entity.addFeature(modificationFeature); + } + } + + return entity; + } + + // create a new controlled vocabulary initialized with the given term + private T addNewControlledVocabulary(Class c, String term) { + T vocab = addNew(c); + + if (term != null) { + vocab.addTerm(term); + } + + return vocab; + } + + // Create a new modification feature that has the given modification type + private ModificationFeature addNewModificationFeature(String modificationType) { + SequenceModificationVocabulary seqModVocab = addNewControlledVocabulary(SequenceModificationVocabulary.class, modificationType); + + ModificationFeature modificationFeature = addNew(ModificationFeature.class); + modificationFeature.setModificationType(seqModVocab); + + return modificationFeature; + } + + // Get modification feature with the given modification type from a set of modification features + private ModificationFeature getFeatureByModificationType(Set modificationFeatures, + String modificationType) { + + Iterator it = modificationFeatures.iterator(); + + while (it.hasNext()) { + ModificationFeature modificationFeature = it.next(); + Set terms = modificationFeature.getModificationType().getTerm(); + if ( getOnlyElement(terms).equals(modificationType) ) { + return modificationFeature; + } + } + + return null; + } + + // Create a new entity reference by given properties + private T addNewEntityReference(Class c, String name) { + + T entityRef = addNew(c); + + if(name != null) { + entityRef.setDisplayName(name); + } + + return entityRef; + } +} diff --git a/src/main/java/model/TemplatesModel.java b/src/main/java/model/TemplatesModel.java new file mode 100644 index 0000000..e136ecd --- /dev/null +++ b/src/main/java/model/TemplatesModel.java @@ -0,0 +1,255 @@ +package model; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.biopax.paxtools.model.level3.BiochemicalReaction; +import org.biopax.paxtools.model.level3.Catalysis; +import org.biopax.paxtools.model.level3.CellularLocationVocabulary; +import org.biopax.paxtools.model.level3.Complex; +import org.biopax.paxtools.model.level3.ComplexAssembly; +import org.biopax.paxtools.model.level3.Control; +import org.biopax.paxtools.model.level3.ControlType; +import org.biopax.paxtools.model.level3.Conversion; +import org.biopax.paxtools.model.level3.MolecularInteraction; +import org.biopax.paxtools.model.level3.PhysicalEntity; +import org.biopax.paxtools.model.level3.Protein; +import org.biopax.paxtools.model.level3.ProteinReference; +import org.biopax.paxtools.model.level3.SmallMolecule; +import org.biopax.paxtools.model.level3.SmallMoleculeReference; +import org.biopax.paxtools.model.level3.TemplateReaction; +import org.biopax.paxtools.model.level3.TemplateReactionRegulation; +import org.biopax.paxtools.model.level3.Transport; + +/* + * A model class that keeps an underlying BioPAX model and enables updating it by adding templates. + */ +public class TemplatesModel { + + BioPAXModel model; + + public TemplatesModel() { + model = new BioPAXModel(); + } + + // Section: public methods + + // modifiers + + public void addLocationChange(List macromoleculeNames, String controllerProteinName, String oldLocation, + String newLocation, ControlType controlType) { + + Transport transport = model.addNewConversion(Transport.class); + + Complex leftComplex = null; + Complex rightComplex = null; + + boolean multipleMolecules = false; + + if (macromoleculeNames.size() > 0) { + multipleMolecules = true; + + leftComplex = model.getOrCreatePhysicalEntity(Complex.class); + rightComplex = model.getOrCreatePhysicalEntity(Complex.class); + + transport.addLeft(leftComplex); + transport.addRight(rightComplex); + } + + CellularLocationVocabulary oldClv = model.getOrCreateCellularLocationVocabulary(oldLocation); + CellularLocationVocabulary newClv = model.getOrCreateCellularLocationVocabulary(newLocation); + + for(String macromoleculeName : macromoleculeNames) { + + ProteinReference mmRef = model.getOrCreateEntityReference(ProteinReference.class, macromoleculeName); + Protein left = model.getOrCreatePhysicalEntity(Protein.class, macromoleculeName, oldClv, mmRef); + Protein right = model.getOrCreatePhysicalEntity(Protein.class, macromoleculeName, newClv, mmRef); + + if (multipleMolecules) { + leftComplex.addComponent(left); + rightComplex.addComponent(right); + } + else { + transport.addLeft(left); + transport.addRight(right); + } + } + + ProteinReference controllerRef = model.getOrCreateEntityReference(ProteinReference.class, controllerProteinName); + Protein controller = model.getOrCreatePhysicalEntity(Protein.class, controllerProteinName, null, controllerRef); + + model.addNewControl(Control.class, controller, transport, controlType); + } + + public void addProteinModification(String modifiedProteinName, String controllerProteinName, String modificationType, ControlType controlType) { + + Set leftModificationTypes = new HashSet(); + Set rightModificationTypes = new HashSet(); + + rightModificationTypes.add(modificationType); + + addActiveInactiveModifications(controlType, leftModificationTypes, rightModificationTypes); + + ProteinReference protRef = model.getOrCreateEntityReference(ProteinReference.class, modifiedProteinName); + Protein left = model.getOrCreatePhysicalEntity(Protein.class, modifiedProteinName, null, protRef, leftModificationTypes); + Protein right = model.getOrCreatePhysicalEntity(Protein.class, modifiedProteinName, null, protRef, rightModificationTypes); + + ProteinReference controllerRef = model.getOrCreateEntityReference(ProteinReference.class, controllerProteinName); + Protein controller = model.getOrCreatePhysicalEntity(Protein.class, controllerProteinName, null, controllerRef); + + Conversion conversion = model.addNewConversion(Conversion.class, left, right); + model.addNewControl(Control.class, controller, conversion, controlType); + } + + public void addComplexAssociation(List moleculeNames) { + addComplexAssembly(moleculeNames, ComplexAssemblyType.ASSOCIATION); + } + + public void addComplexDissociation(List moleculeNames) { + addComplexAssembly(moleculeNames, ComplexAssemblyType.DISSOCIATION); + } + + public void addPhysicalInteraction(List moleculeNames) { + MolecularInteraction molecularInteraction = model.addNew(MolecularInteraction.class); + + for(String moleculeName : moleculeNames) { + ProteinReference protRef = model.getOrCreateEntityReference(ProteinReference.class, moleculeName); + Protein molecule = model.getOrCreatePhysicalEntity(Protein.class, moleculeName, null, protRef); + molecularInteraction.addParticipant(molecule); + } + } + + public void addBiochemicalReaction(String catalyzerName, List inputMoleculeNames, List outputMoleculeNames) { + BiochemicalReaction reaction = model.addNewConversion(BiochemicalReaction.class); + + addNewSmallMoleculesToConversion(reaction, inputMoleculeNames, SideType.LEFT); + addNewSmallMoleculesToConversion(reaction, outputMoleculeNames, SideType.RIGHT); + + ProteinReference catalyzerRef = model.getOrCreateEntityReference(ProteinReference.class, catalyzerName); + Protein catalyzer = model.getOrCreatePhysicalEntity(Protein.class, catalyzerName, null, catalyzerRef); + + model.addNewControl(Catalysis.class, catalyzer, reaction, null); + } + + public void addActivationInhibition(String regulatorProteinName, String targetProteinName, ControlType effectType) { + + Set leftModificationTypes = new HashSet(); + Set rightModificationTypes = new HashSet(); + + addActiveInactiveModifications(effectType, leftModificationTypes, rightModificationTypes); + + ProteinReference targetProtRef = model.getOrCreateEntityReference(ProteinReference.class, targetProteinName); + ProteinReference regulatorProtRef = model.getOrCreateEntityReference(ProteinReference.class, regulatorProteinName); + + Protein regulatorProtein = model.getOrCreatePhysicalEntity(Protein.class, regulatorProteinName, null, regulatorProtRef); + Protein leftProtein = model.getOrCreatePhysicalEntity(Protein.class, targetProteinName, null, targetProtRef, leftModificationTypes); + Protein rightProtein = model.getOrCreatePhysicalEntity(Protein.class, targetProteinName, null, targetProtRef, rightModificationTypes); + + Conversion conversion = model.addNewConversion(Conversion.class, leftProtein, rightProtein); + model.addNewControl(Control.class, regulatorProtein, conversion, effectType); + } + + public void addRegulationOfExpression(String transcriptionFactorName, String targetProtName, ControlType effectType) { + + ProteinReference targetRef = model.getOrCreateEntityReference(ProteinReference.class, targetProtName); + ProteinReference tfRef = model.getOrCreateEntityReference(ProteinReference.class, transcriptionFactorName); + + Protein tf = model.getOrCreatePhysicalEntity(Protein.class, transcriptionFactorName, null, tfRef); + Protein product = model.getOrCreatePhysicalEntity(Protein.class, targetProtName, null, targetRef); + + TemplateReaction reaction = model.addNew(TemplateReaction.class); + reaction.addProduct(product); + + model.addNewControl(TemplateReactionRegulation.class, tf, reaction, effectType); + } + + // accessors + + public String convertToOwl() { + return model.convertToOwl(); + } + + // Section: private helper methods + + private void addComplexAssembly(List moleculeNames, ComplexAssemblyType assemblyType) { + + ComplexAssembly complexAssembly = model.addNewConversion(ComplexAssembly.class); + Complex complex = model.getOrCreatePhysicalEntity(Complex.class); + + SideType moleculeSide = SideType.LEFT; + SideType complexSide = SideType.RIGHT; + + // Association by default + if (assemblyType == ComplexAssemblyType.DISSOCIATION) { + moleculeSide = SideType.RIGHT; + complexSide = SideType.LEFT; + } + + addSideToConversion(complexAssembly, complex, complexSide); + + for (String moleculeName : moleculeNames) { + ProteinReference moleculeRef = model.getOrCreateEntityReference(ProteinReference.class, moleculeName); + + Protein molecule = model.getOrCreatePhysicalEntity(Protein.class, moleculeName, null, moleculeRef); + Protein moleculeOfComplex = model.getOrCreatePhysicalEntity(Protein.class, moleculeName, null, moleculeRef); + + addSideToConversion(complexAssembly, molecule, moleculeSide); + + complex.addComponent(moleculeOfComplex); + } + } + + // Add a new small molecule to the given side of conversion + private void addNewSmallMoleculeToConversion(Conversion conversion, String moleculeName, SideType sideType) { + SmallMoleculeReference moleculeRef = model.getOrCreateEntityReference(SmallMoleculeReference.class, moleculeName); + SmallMolecule molecule = model.getOrCreatePhysicalEntity(SmallMolecule.class, moleculeName, null, moleculeRef); + addSideToConversion(conversion, molecule, sideType); + } + + // Add new small molecules to given side of conversion + private void addNewSmallMoleculesToConversion(Conversion conversion, List moleculeNames, SideType sideType) { + for (String moleculeName : moleculeNames) { + addNewSmallMoleculeToConversion(conversion, moleculeName, sideType); + } + } + + // Add a physical entity to given side of conversation. + private static void addSideToConversion(Conversion conversion, PhysicalEntity entity, SideType side) { + if (side == SideType.LEFT) { + conversion.addLeft(entity); + } + else if (side == SideType.RIGHT) { + conversion.addRight(entity); + } + } + + // Update modification types set by adding ACTIVE and INACTIVE modifications to the sides according to control type + private static void addActiveInactiveModifications(ControlType controlType, Set leftModificationTypes, Set rightModificationTypes){ + String leftType = INACTIVE; + String rightType = ACTIVE; + + // ACTIVATION by default + if (controlType == ControlType.INHIBITION) { + leftType = ACTIVE; + rightType = INACTIVE; + } + + leftModificationTypes.add(leftType); + rightModificationTypes.add(rightType); + } + + // Section: static variables + + private static final String ACTIVE = "active"; + private static final String INACTIVE = "inactive"; + + private static enum SideType { + LEFT, + RIGHT + } + private static enum ComplexAssemblyType { + ASSOCIATION, + DISSOCIATION + } +} diff --git a/src/main/java/web/ConvertToOwlServlet.java b/src/main/java/web/ConvertToOwlServlet.java new file mode 100644 index 0000000..b368685 --- /dev/null +++ b/src/main/java/web/ConvertToOwlServlet.java @@ -0,0 +1,57 @@ +package web; + +import java.io.IOException; +import java.io.InputStreamReader; + +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import converter.FactoidToBiopax; + +//import org.apache.commons.io.IOUtils; + +/** + * Servlet implementation class ConvertToOwl + */ +@WebServlet("/ConvertToOwl") +public class ConvertToOwlServlet extends HttpServlet { + private static final long serialVersionUID = 1L; + + /** + * @see HttpServlet#HttpServlet() + */ + public ConvertToOwlServlet() { + super(); + // TODO Auto-generated constructor stub + } + + /** + * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) + */ + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + // TODO Auto-generated method stub + response.getWriter().append("Served at: ").append(request.getContextPath()); + } + + /** + * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) + */ + protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + // Create input stream reader by the request + InputStreamReader reader = new InputStreamReader(request.getInputStream()); + + // Add templates to converter by the reader + FactoidToBiopax converter = new FactoidToBiopax(); + converter.addToModel(reader); + + // Convert the model to biopax string + String biopaxStr = converter.convertToOwl(); + + // Append the result to the writer + response.getWriter().append(biopaxStr); + } + +} diff --git a/src/test/java/model/BioPAXModelTest.java b/src/test/java/model/BioPAXModelTest.java new file mode 100644 index 0000000..94701a9 --- /dev/null +++ b/src/test/java/model/BioPAXModelTest.java @@ -0,0 +1,192 @@ +package model; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; + +import java.lang.reflect.Field; +import java.util.HashSet; +import java.util.Set; + +import org.biopax.paxtools.model.Model; +import org.biopax.paxtools.model.level3.CellularLocationVocabulary; +import org.biopax.paxtools.model.level3.Control; +import org.biopax.paxtools.model.level3.ControlType; +import org.biopax.paxtools.model.level3.Conversion; +import org.biopax.paxtools.model.level3.ConversionDirectionType; +import org.biopax.paxtools.model.level3.Protein; +import org.biopax.paxtools.model.level3.ProteinReference; +import org.biopax.paxtools.model.level3.SmallMoleculeReference; +import org.junit.Test; + +public class BioPAXModelTest { + + // Assess private model field and make it accessible + private static Field getModelField() { + return getModelField(true); + } + + private static Field getModelField(boolean accessible) { + Field modelField = null; + + try { + modelField = BioPAXModel.class.getDeclaredField("model"); + modelField.setAccessible(accessible); + } catch (NoSuchFieldException e) { + e.printStackTrace(); + } catch (SecurityException e) { + e.printStackTrace(); + } + + return modelField; + } + + // Accessor for private model proterty of given BioPAXModel instance + private Model getInnerPaxtoolsModel(BioPAXModel biopaxModel) { + Model innerModel = null; + + try { + innerModel = (Model) modelField.get(biopaxModel); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + + return innerModel; + } + + @Test + public void addPhysicalEntityTest() throws NoSuchFieldException, SecurityException { + + BioPAXModel model = new BioPAXModel(); + + // Underlying PAXTools model + Model innerModel = getInnerPaxtoolsModel(model); + + String protName = "TP53"; + String cellularLocationName = "cytoplasm"; + String cellularLocationName2 = "cytoplasm2"; + + Set modificationTypes = new HashSet(); + modificationTypes.add("active"); + + Set modificationTypes2 = new HashSet(); + modificationTypes2.add("inactive"); + + ProteinReference protRef = model.getOrCreateEntityReference(ProteinReference.class, protName); + CellularLocationVocabulary cellularLocation = model.getOrCreateCellularLocationVocabulary(cellularLocationName); + CellularLocationVocabulary cellularLocation2 = model.getOrCreateCellularLocationVocabulary(cellularLocationName2); + + Protein prot1 = model.getOrCreatePhysicalEntity(Protein.class, protName, cellularLocation, protRef, modificationTypes); + + assertTrue("Protein is added to the model", innerModel.contains(prot1)); + assertEquals("Protein name is set", prot1.getDisplayName(), protName); + assertEquals("Protein cellular location is set", cellularLocation, prot1.getCellularLocation()); + assertEquals("Protein reference is set", protRef, prot1.getEntityReference()); + assertEquals("Protein modification types are set", modificationTypes.size(), prot1.getFeature().size()); + assertEquals("Protein reference has a new modification", 1, protRef.getEntityFeature().size()); + + Protein prot2 = model.getOrCreatePhysicalEntity(Protein.class, protName, cellularLocation, protRef, modificationTypes); + assertEquals("No duplication in adding the second Protein with same features", prot1, prot2); + + Protein prot3 = model.getOrCreatePhysicalEntity(Protein.class, protName, cellularLocation, protRef); + assertNotEquals("A new protein is added with no modification", prot1, prot3); + + Protein prot4 = model.getOrCreatePhysicalEntity(Protein.class, protName, cellularLocation, protRef, modificationTypes2); + assertNotEquals("A new protein is added with with different modifications", prot1, prot4); + assertEquals("Protein reference has a new modification", 2, protRef.getEntityFeature().size()); + + Protein prot5 = model.getOrCreatePhysicalEntity(Protein.class, protName, cellularLocation2, protRef, modificationTypes); + assertNotEquals("A new protein is added with with different cellular location", prot1, prot5); + assertEquals("Protein reference already had this modification", 2, protRef.getEntityFeature().size()); + } + + @Test + public void addEntityReferenceTest() { + + BioPAXModel model = new BioPAXModel(); + + // Underlying PAXTools model + Model innerModel = getInnerPaxtoolsModel(model); + + String commonName = "Protein1"; + String uniqueName = "Protein2"; + + ProteinReference protRef1 = model.getOrCreateEntityReference(ProteinReference.class, commonName); + assertTrue("Protein reference is added to the model", innerModel.contains(protRef1)); + assertEquals("Protein reference name is set", commonName, protRef1.getDisplayName()); + + ProteinReference protRef2 = model.getOrCreateEntityReference(ProteinReference.class, commonName); + assertEquals("No duplication in adding second protein modification with same name", protRef1, protRef2); + + SmallMoleculeReference smRef = model.getOrCreateEntityReference(SmallMoleculeReference.class, commonName); + assertNotEquals("A new small molecule reference is added that has an existing protein reference name", protRef2, smRef); + + ProteinReference protRef3 = model.getOrCreateEntityReference(ProteinReference.class, uniqueName); + assertNotEquals("A new protein is added with a new name", protRef1, protRef3); + } + + @Test + public void addCellularLocationVocabularyTest() { + + BioPAXModel model = new BioPAXModel(); + + // Underlying PAXTools model + Model innerModel = getInnerPaxtoolsModel(model); + + String commonLocationName = "location1"; + String uniqueLocationName = "location2"; + + CellularLocationVocabulary clv1 = model.getOrCreateCellularLocationVocabulary(commonLocationName); + assertTrue("Cellular location vocabulary is added to the model", innerModel.contains(clv1)); + assertEquals("Cellular location vocabulary has the name", 1, clv1.getTerm().size()); + + CellularLocationVocabulary clv2 = model.getOrCreateCellularLocationVocabulary(commonLocationName); + assertEquals("No duplication in adding the second cellular location with the same name", clv1, clv2); + + CellularLocationVocabulary clv3 = model.getOrCreateCellularLocationVocabulary(uniqueLocationName); + assertNotEquals("A new cellular location is added with a new name", clv1, clv3); + } + + @Test + public void addConversionTest() { + + BioPAXModel model = new BioPAXModel(); + + // Underlying PAXTools model + Model innerModel = getInnerPaxtoolsModel(model); + + ConversionDirectionType dir = ConversionDirectionType.LEFT_TO_RIGHT; + Protein left = model.addNew(Protein.class); + Protein right = model.addNew(Protein.class); + + Conversion conversion = model.addNewConversion(Conversion.class, left, right, dir); + assertTrue("Conversion is added to the model", innerModel.contains(conversion)); + assertTrue("Coversions left side is set", conversion.getLeft().contains(left)); + assertTrue("Coversions right side is set", conversion.getRight().contains(right)); + assertEquals("Conversion direction is set", dir, conversion.getConversionDirection()); + } + + @Test + public void addControlTest() { + + BioPAXModel model = new BioPAXModel(); + + // Underlying PAXTools model + Model innerModel = getInnerPaxtoolsModel(model); + + Conversion controlled = model.addNewConversion(Conversion.class); + Protein controller = model.getOrCreatePhysicalEntity(Protein.class); + ControlType controlType = ControlType.ACTIVATION; + + Control control = model.addNewControl(Control.class, controller, controlled, controlType); + + assertTrue("Control is added to the model", innerModel.contains(control)); + assertTrue("Controller is set", control.getController().contains(controller)); + assertTrue("Controlled is set", control.getControlled().contains(controlled)); + assertEquals("Control type is set", controlType, control.getControlType()); + } + + private static Field modelField = getModelField(); +}