001package org.biopax.paxtools.io.sif.level3; 002 003import org.biopax.paxtools.controller.PathAccessor; 004import org.biopax.paxtools.model.BioPAXElement; 005import org.biopax.paxtools.model.level3.*; 006 007import java.util.HashMap; 008import java.util.HashSet; 009import java.util.Map; 010import java.util.Set; 011 012/** 013 * This experimental class is used by Activity Network Analyzer to capture state change events. 014 * 015 * Note: The idea here is similar to converting SBGN-PD to SBGN-ER and this class in the future can be a 016 * basis for that. But currently it makes assumptions about the representation which is compatible with the 017 * existing pathway data sources but might not be compatible with all usages of BioPAX. 018 * 019 * Use with caution. 020 * 021 * @author Emek Demir 022 */ 023public class PEStateChange { 024 025 /** 026 * A map of features that are changed and how they changed. 027 */ 028 Map<EntityFeature, ChangeType> deltaFeatures; 029 030 /** 031 * A map of changes in the types of controls. For example if as a result of the state change the entity can now 032 * phosphorylate a downstream event, this is registered as a control that is gained. 033 */ 034 HashMap<Control, Boolean> deltaControls = new HashMap<Control, Boolean>(); 035 036 /** 037 * Left physical entity. Must belong to the same entity reference with right. 038 */ 039 SimplePhysicalEntity left; 040 041 /** 042 * Right physical entity, must belong to the same entity reference with left. 043 */ 044 SimplePhysicalEntity right; 045 046 /** 047 * Conversion event leading to state change, 048 */ 049 Conversion conv; 050 051 /** 052 * 053 */ 054 private PhysicalEntity leftRoot; 055 private PhysicalEntity rightRoot; 056 static PathAccessor controllers = new PathAccessor("Conversion/controlledOf/controller"); 057 058 059 public PEStateChange( 060 SimplePhysicalEntity left, 061 SimplePhysicalEntity right, 062 PhysicalEntity leftRoot, 063 PhysicalEntity rightRoot, 064 BioPAXElement element, 065 Conversion conv) { 066 this.left = left; 067 this.right = right; 068 this.leftRoot = leftRoot; 069 this.rightRoot = rightRoot; 070 this.conv = conv; 071 this.deltaFeatures = ChangeType.getDeltaFeatures(left, right, leftRoot, rightRoot); 072 calculateDeltaControls(); 073 } 074 075 076 @Override 077 public String toString() { 078 return this.left.getStandardName() + "--" + this.right.getDisplayName() + "(" + this.deltaFeatures + ")"; 079 } 080 081 @Override 082 public boolean equals(Object o) { 083 if (this == o) return true; 084 if (!(o instanceof PEStateChange)) return false; 085 086 PEStateChange that = (PEStateChange) o; 087 088 if (conv != null ? !conv.equals(that.conv) : that.conv != null) return false; 089 if (deltaFeatures != null ? !deltaFeatures.equals(that.deltaFeatures) : that.deltaFeatures != null) 090 return false; 091 if (left != null ? !left.equals(that.left) : that.left != null) return false; 092 if (right != null ? !right.equals(that.right) : that.right != null) return false; 093 094 return true; 095 } 096 097 public Map<EntityFeature, ChangeType> getDeltaFeatures() { 098 return deltaFeatures; 099 } 100 101 public Conversion getConv() { 102 return conv; 103 } 104 105 public SimplePhysicalEntity getLeft() { 106 return left; 107 } 108 109 public SimplePhysicalEntity getRight() { 110 return right; 111 } 112 113 public SimplePhysicalEntity changedFrom(SimplePhysicalEntity source) { 114 if (this.left == source) return getFlow(true, true); 115 else if (this.right == source) return getFlow(false, false); 116 else return null; 117 } 118 119 public SimplePhysicalEntity changedInto(SimplePhysicalEntity source) { 120 if (this.left == source) return getFlow(true, false); 121 else if (this.right == source) return getFlow(false, true); 122 else return null; 123 } 124 125 private SimplePhysicalEntity getFlow(boolean onLeft, boolean forward) { 126 boolean flow = canFlow(onLeft, forward); 127 128 return flow ? onLeft ? this.right : this.left : null; 129 } 130 131 /** 132 * This method returns true iff conversion can go from/to the side specified by the first parameter in the direction 133 * specified by the second parameter 134 * 135 * @param targetSide true if flow needs to be checked from/to the left side false otherwise 136 * @param forward true if we are asking if a flow can start from the targetSide, false if we are asking if a flow 137 * can go to the targetSide. 138 * @return 139 */ 140 private boolean canFlow(boolean targetSide, boolean forward) { 141 boolean flow = true; 142 ConversionDirectionType cd = conv.getConversionDirection(); 143 if (cd != null) 144 switch (cd) { 145 case LEFT_TO_RIGHT: 146 flow = !(targetSide ^ forward); 147 break; 148 case RIGHT_TO_LEFT: 149 flow = (targetSide ^ forward); 150 break; 151 default: 152 flow = true; 153 154 } 155 return flow; 156 } 157 158 @Override 159 public int hashCode() { 160 int result = deltaFeatures != null ? deltaFeatures.hashCode() : 0; 161 result = 31 * result + (conv != null ? conv.hashCode() : 0); 162 result = 31 * result + (left != null ? left.hashCode() : 0); 163 result = 31 * result + (right != null ? right.hashCode() : 0); 164 return result; 165 } 166 167 public PhysicalEntity getLeftRoot() { 168 return leftRoot; 169 } 170 171 public PhysicalEntity getRightRoot() { 172 return rightRoot; 173 } 174 175 public Map<Control, Boolean> getDeltaControls() { 176 return deltaControls; 177 178 } 179 180 private void calculateDeltaControls() { 181 Set<Control> left = this.leftRoot == null ? null : this.getLeftRoot().getControllerOf(); 182 Set<Control> right = this.rightRoot == null ? null : this.getRightRoot().getControllerOf(); 183 184 if (left != null) 185 for (Control control : left) { 186 deltaControls.put(control, true); 187 } 188 if (right != null) 189 for (Control control : right) { 190 if (deltaControls.containsKey(control)) { 191 deltaControls.remove(control); 192 } else 193 deltaControls.put(control, false); 194 195 } 196 197 } 198 199 public String getControllersAsString() { 200 Set valueFromBean = controllers.getValueFromBean(conv); 201 StringBuilder value = new StringBuilder(); 202 for (Object o : valueFromBean) { 203 Controller controller = (Controller) o; 204 value.append(controller.getName()).append( "["); 205 appendXrefs(controller, value); 206 value.append( "] "); 207 } 208 return value.toString(); 209 } 210 211 private void appendXrefs(Controller controller, StringBuilder builder) 212 { 213 HashSet<SimplePhysicalEntity> simple = new HashSet<SimplePhysicalEntity>(); 214 if(controller instanceof PhysicalEntity) { 215 Simplify.getSimpleMembers((PhysicalEntity) controller, simple); 216 for (SimplePhysicalEntity spe : simple) 217 { 218 219 builder.append("(").append(spe.getEntityReference().getXref()).append(")"); 220 } 221 } 222 } 223}