001package org.biopax.paxtools.pattern.constraint; 002 003import org.biopax.paxtools.controller.PathAccessor; 004import org.biopax.paxtools.model.BioPAXElement; 005import org.biopax.paxtools.model.level3.EntityReference; 006import org.biopax.paxtools.model.level3.ModificationFeature; 007import org.biopax.paxtools.model.level3.SimplePhysicalEntity; 008import org.biopax.paxtools.pattern.Match; 009 010import java.util.HashMap; 011import java.util.HashSet; 012import java.util.Map; 013import java.util.Set; 014 015/** 016 * This is a very specialized constraint that checks if two PhysicalEntity of the same 017 * EntityReference have differential features, such that we can predict an activity change based on 018 * gain or loss of these features. To use this constraint, user should be able to supply maps that 019 * categorize features as activating or inhibiting. 020 * 021 * @author Ozgun Babur 022 */ 023public class ActivityModificationChangeConstraint extends ConstraintAdapter 024{ 025 /** 026 * Desired change. 027 */ 028 boolean activating; 029 030 /** 031 * Accessor to modification features. 032 */ 033 static PathAccessor pa = new PathAccessor("PhysicalEntity/feature:ModificationFeature"); 034 035 /** 036 * Some general modification sub-strings to use if exact terms are not conclusive. 037 */ 038 protected final static String[] general = new String[]{ 039 "phospho", "ubiqutin", "acetyl", "myristoyl", "palmitoyl", "glucosyl"}; 040 041 /** 042 * Map from EntityReference to the activity related features. 043 */ 044 Map<EntityReference, Set<ModificationFeature>> activityFeat; 045 046 /** 047 * Map from EntityReference to the inactivity related features. 048 */ 049 Map<EntityReference, Set<ModificationFeature>> inactivityFeat; 050 051 /** 052 * Map from EntityReference to the activity related terms. 053 */ 054 Map<EntityReference, Set<String>> activityStr; 055 056 /** 057 * Map from EntityReference to the inactivity related terms. 058 */ 059 Map<EntityReference, Set<String>> inactivityStr; 060 061 /** 062 * Constructor with the desired change and maps to activating and inactivating features, 063 * @param activating desired change 064 * @param activityFeat map from EntityReference to the activating features 065 * @param inactivityFeat map from EntityReference to the inactivating features 066 */ 067 public ActivityModificationChangeConstraint(boolean activating, 068 Map<EntityReference, Set<ModificationFeature>> activityFeat, 069 Map<EntityReference, Set<ModificationFeature>> inactivityFeat) 070 { 071 super(2); 072 this.activating = activating; 073 this.activityFeat = activityFeat; 074 this.inactivityFeat = inactivityFeat; 075 076 activityStr = extractModifNames(activityFeat); 077 inactivityStr = extractModifNames(inactivityFeat); 078 } 079 080 /** 081 * Checks the gained and and lost features to predict the activity change is the desired change. 082 * If exact matching (terms with locations) is not conclusive, then terms without locations are 083 * checked. If still not conclusive, then approximate matching is used. 084 * @param match current pattern match 085 * @param ind mapped indices 086 * @return true if the modification gain or loss is mapped to the desired change 087 */ 088 @Override 089 public boolean satisfies(Match match, int... ind) 090 { 091 BioPAXElement ele1 = match.get(ind[0]); 092 BioPAXElement ele2 = match.get(ind[1]); 093 094 EntityReference er = ((SimplePhysicalEntity) ele1).getEntityReference(); 095 096 Set set1 = pa.getValueFromBean(ele1); 097 Set set2 = pa.getValueFromBean(ele2); 098 099 Set gain = new HashSet(set2); 100 gain.removeAll(set1); 101 102 Set loss = new HashSet(set1); 103 loss.removeAll(set2); 104 105 int activatingCnt = 0; 106 int inhibitingCnt = 0; 107 108 for (Object o : gain) 109 { 110 if (activityFeat.get(er).contains(o)) activatingCnt++; 111 if (inactivityFeat.get(er).contains(o)) inhibitingCnt++; 112 } 113 for (Object o : loss) 114 { 115 if (inactivityFeat.get(er).contains(o)) activatingCnt++; 116 if (activityFeat.get(er).contains(o)) inhibitingCnt++; 117 } 118 119 // Match without considering the locations 120 121 Set<String> gainTypes = null; 122 Set<String> lossTypes = null; 123 124 if (activatingCnt + inhibitingCnt == 0) 125 { 126 gainTypes = extractModifNames(gain); 127 lossTypes = extractModifNames(loss); 128 129 for (String s : gainTypes) 130 { 131 if (activityStr.get(er).contains(s)) activatingCnt++; 132 if (inactivityStr.get(er).contains(s)) inhibitingCnt++; 133 } 134 for (String s : lossTypes) 135 { 136 if (inactivityStr.get(er).contains(s)) activatingCnt++; 137 if (activityStr.get(er).contains(s)) inhibitingCnt++; 138 } 139 } 140 141 // Try to match modifications with approximate name matching 142 143 if (activatingCnt + inhibitingCnt == 0) 144 { 145 for (String genName : general) 146 { 147 boolean foundInActivating = setContainsGeneralTerm(activityStr.get(er), genName); 148 boolean foundInInhibiting = setContainsGeneralTerm(inactivityStr.get(er), genName); 149 150 if (foundInActivating == foundInInhibiting) continue; 151 152 boolean foundInGain = setContainsGeneralTerm(gainTypes, genName); 153 boolean foundInLose = setContainsGeneralTerm(lossTypes, genName); 154 155 if (foundInGain == foundInLose) continue; 156 157 if (foundInActivating && foundInGain) activatingCnt++; 158 else if (foundInInhibiting && foundInLose) activatingCnt++; 159 else if (foundInActivating && foundInLose) inhibitingCnt++; 160 else /*if (foundInInhibiting && foundInGain)*/ inhibitingCnt++; 161 } 162 } 163 164 if (activatingCnt > 0 && inhibitingCnt > 0) return false; 165 return activating ? activatingCnt > 0 : inhibitingCnt > 0; 166 } 167 168 169 /** 170 * Extracts the modification terms from the moficiation features. 171 * @param mfMap map for the features 172 * @return map from EntityReference to the set of the extracted terms 173 */ 174 protected Map<EntityReference, Set<String>> extractModifNames(Map mfMap) 175 { 176 Map<EntityReference, Set<String>> map = new HashMap<EntityReference, Set<String>>(); 177 178 for (Object o : mfMap.keySet()) 179 { 180 EntityReference er = (EntityReference) o; 181 map.put(er, extractModifNames((Set) mfMap.get(er))); 182 } 183 184 return map; 185 } 186 187 /** 188 * Extracts terms of the modification features. 189 * @param mfSet set of modification features 190 * @return set of extracted terms 191 */ 192 protected Set<String> extractModifNames(Set mfSet) 193 { 194 Set<String> set = new HashSet<String>(); 195 196 for (Object o : mfSet) 197 { 198 ModificationFeature mf = (ModificationFeature) o; 199 if (mf.getModificationType() != null && !mf.getModificationType().getTerm().isEmpty()) 200 { 201 set.add(mf.getModificationType().getTerm().iterator().next()); 202 } 203 } 204 return set; 205 } 206 207 /** 208 * Checks if any element in the set contains the term. 209 * @param set set to check 210 * @param term term to search for 211 * @return true if any element contains the term 212 */ 213 protected boolean setContainsGeneralTerm(Set<String> set, String term) 214 { 215 for (String s : set) 216 { 217 if (s.contains(term)) return true; 218 } 219 return false; 220 } 221}