001package org.biopax.paxtools.io.sif.level2; 002 003import org.biopax.paxtools.io.sif.BinaryInteractionType; 004import org.biopax.paxtools.io.sif.InteractionSet; 005import org.biopax.paxtools.io.sif.SimpleInteraction; 006import org.biopax.paxtools.model.Model; 007import org.biopax.paxtools.model.level2.*; 008 009import java.util.*; 010 011/** 012 * This is an experimental rule that mines ACTIVATES and INHIBITS relations between molecules. 013 * @author Ozgun Babur 014 */ 015public class AffectsRule extends InteractionRuleL2Adaptor 016{ 017 /** 018 * Supported interaction types. 019 */ 020 private static List<BinaryInteractionType> binaryInteractionTypes = 021 Arrays.asList(BinaryInteractionType.ACTIVATES, BinaryInteractionType .INACTIVATES); 022 023 /** 024 * Infers interactions using the given physicalEntity as seed. 025 * @param interactionSet to be populated 026 * @param pe first physicalEntity 027 * @param model BioPAX model 028 */ 029 @Override public void inferInteractionsFromPE(InteractionSet interactionSet, physicalEntity pe, 030 Model model) 031 { 032 for (control cont : pe.getAllInteractions(control.class)) 033 { 034 for (process prcs : cont.getCONTROLLED()) 035 { 036 if (prcs instanceof conversion) 037 { 038 createInteractions(interactionSet, pe, (conversion) prcs, cont); 039 } 040 } 041 } 042 } 043 044 /** 045 * Gets supported interactions types. 046 * @return supported interactions types 047 */ 048 public List<BinaryInteractionType> getRuleTypes() 049 { 050 return binaryInteractionTypes; 051 } 052 053 /** 054 * Checks of the participant has an activity. 055 * @param pep participant to check 056 * @return true if there is evidence for activity 057 */ 058 private boolean isActive(physicalEntityParticipant pep) 059 { 060 if (affectsSomething(pep) && !isAnnotatedInactive(pep) && 061 (!(pep.getPHYSICAL_ENTITY() instanceof complex) || !complexHasInactiveMember( 062 (complex) pep.getPHYSICAL_ENTITY()))) 063 { 064 return true; 065 } 066 067 if (isAnnotatedActive(pep)) 068 { 069 return true; 070 } 071 072 if (pep.getPHYSICAL_ENTITY() instanceof 073 complex && complexHasActiveMember((complex) pep.getPHYSICAL_ENTITY()) && 074 !complexHasInactiveMember((complex) pep.getPHYSICAL_ENTITY())) 075 { 076 return true; 077 } 078 079 return false; 080 } 081 082 /** 083 * Checks of the participant has evidence for inactivity. 084 * @param pep participant to check 085 * @return true if there is evidence for inactivity 086 */ 087 private boolean isInactive(physicalEntityParticipant pep) 088 { 089 if (isAnnotatedInactive(pep)) 090 { 091 return true; 092 } 093 094 if (pep.getPHYSICAL_ENTITY() instanceof complex && 095 complexHasInactiveMember((complex) pep.getPHYSICAL_ENTITY()) && 096 !complexHasActiveMember((complex) pep.getPHYSICAL_ENTITY())) 097 { 098 return true; 099 } 100 101 return false; 102 } 103 104 /** 105 * Checks if there is an annotation for the participant for its activity. 106 * @param pep participant to check 107 * @return true if there is an annotation for activity 108 */ 109 private boolean isAnnotatedActive(physicalEntityParticipant pep) 110 { 111 if (pep instanceof sequenceParticipant) 112 { 113 for (sequenceFeature sf : ((sequenceParticipant) pep).getSEQUENCE_FEATURE_LIST()) 114 { 115 if (sf.getFEATURE_TYPE() != null) 116 { 117 for (String term : sf.getFEATURE_TYPE().getTERM()) 118 { 119 if (term.startsWith("active")) 120 { 121 return true; 122 } 123 } 124 } 125 } 126 } 127 128 return false; 129 } 130 131 /** 132 * Checks if there is an annotation for the participant for its inactivity. 133 * @param pep participant to check 134 * @return true if there is an annotation for inactivity 135 */ 136 private boolean isAnnotatedInactive(physicalEntityParticipant pep) 137 { 138 if (pep instanceof sequenceParticipant) 139 { 140 for (sequenceFeature sf : ((sequenceParticipant) pep).getSEQUENCE_FEATURE_LIST()) 141 { 142 if (sf.getFEATURE_TYPE() != null) 143 { 144 for (String term : sf.getFEATURE_TYPE().getTERM()) 145 { 146 if (term.startsWith("inactive") || term.startsWith("ubiquitin")) 147 { 148 return true; 149 } 150 } 151 } 152 } 153 } 154 155 return false; 156 } 157 158 /** 159 * Checks if this participant or the the ones in equivalent state are effecting something. 160 * @param pep participant to check 161 * @return true if this one or an equivalent affects something 162 */ 163 private boolean affectsSomething(physicalEntityParticipant pep) 164 { 165 physicalEntity pe = pep.getPHYSICAL_ENTITY(); 166 167 for (physicalEntityParticipant par : pe.isPHYSICAL_ENTITYof()) 168 { 169 if (par != pep && par.isInEquivalentState(pep)) 170 { 171 for (interaction inter : par.isPARTICIPANTSof()) 172 { 173 if (inter instanceof control) 174 { 175 return true; 176 } 177 } 178 } 179 } 180 181 return false; 182 } 183 184 /** 185 * Checks if the complex has an active member. 186 * @param cmp complex to check 187 * @return true if complex has an active member 188 */ 189 private boolean complexHasActiveMember(complex cmp) 190 { 191 for (physicalEntityParticipant pep : cmp.getCOMPONENTS()) 192 { 193 if (isAnnotatedActive(pep)) 194 { 195 return true; 196 } else if (pep.getPHYSICAL_ENTITY() instanceof complex && complexHasActiveMember( 197 (complex) pep.getPHYSICAL_ENTITY())) 198 { 199 return true; 200 } 201 } 202 return false; 203 } 204 205 /** 206 * Checks if the complex has an inactive member. 207 * @param cmp complex to check 208 * @return true if complex has an inactive member 209 */ 210 private boolean complexHasInactiveMember(complex cmp) 211 { 212 for (physicalEntityParticipant pep : cmp.getCOMPONENTS()) 213 { 214 if (isAnnotatedInactive(pep)) 215 { 216 return true; 217 } else if (pep.getPHYSICAL_ENTITY() instanceof complex && complexHasInactiveMember( 218 (complex) pep.getPHYSICAL_ENTITY())) 219 { 220 return true; 221 } 222 } 223 return false; 224 } 225 226 /** 227 * Gets active or inactive members of a complex. 228 * @param cmp complex to get members 229 * @param active desired activity state 230 * @param set set to collect to, initialized if null 231 * @return same set 232 */ 233 private Set<physicalEntity> getMembers(complex cmp, boolean active, Set<physicalEntity> set) 234 { 235 if (set == null) set = new HashSet<physicalEntity>(); 236 237 for (physicalEntityParticipant pep : cmp.getCOMPONENTS()) 238 { 239 if (!(pep.getPHYSICAL_ENTITY() instanceof complex) && 240 ((active && isAnnotatedActive(pep)) || (!active && isAnnotatedInactive(pep)))) 241 { 242 set.add(pep.getPHYSICAL_ENTITY()); 243 } else if (pep.getPHYSICAL_ENTITY() instanceof complex) 244 { 245 getMembers((complex) pep.getPHYSICAL_ENTITY(), active, set); 246 } 247 } 248 return set; 249 } 250 251 /** 252 * Gets members of the complex recursively. 253 * @param cmp complex to get members 254 * @param set set to collect to 255 * @return members 256 */ 257 private Set<physicalEntityParticipant> getMembers(complex cmp, 258 Set<physicalEntityParticipant> set) 259 { 260 if (set == null) set = new HashSet<physicalEntityParticipant>(); 261 262 for (physicalEntityParticipant pep : cmp.getCOMPONENTS()) 263 { 264 if (pep.getPHYSICAL_ENTITY() instanceof complex) 265 { 266 getMembers((complex) pep.getPHYSICAL_ENTITY(), set); 267 } else 268 { 269 set.add(pep); 270 } 271 } 272 return set; 273 } 274 275 /** 276 * Creates the inferred interaction. 277 * @param interactionSet set to add new interactions 278 * @param A seed of the interaction 279 * @param conv conversion that affects B 280 * @param cont control where A is controller 281 */ 282 private void createInteractions(InteractionSet interactionSet, physicalEntity A, 283 conversion conv, control cont) 284 { 285 boolean l2r = true; 286 287 if (cont instanceof catalysis) 288 { 289 Direction dir = ((catalysis) cont).getDIRECTION(); 290 291 if (dir != null) 292 { 293 if (dir == Direction.REVERSIBLE) return; 294 295 if (dir == Direction.IRREVERSIBLE_RIGHT_TO_LEFT || 296 dir == Direction.PHYSIOL_RIGHT_TO_LEFT) 297 { 298 l2r = false; 299 } 300 } 301 } 302 303 int effect = 1; 304 if (cont != null && cont.getCONTROL_TYPE() != null) 305 { 306 effect = cont.getCONTROL_TYPE().toString().startsWith("ACT") ? 1 : -1; 307 } 308 309 Set<physicalEntityParticipant> input = l2r ? conv.getLEFT() : conv.getRIGHT(); 310 Set<physicalEntityParticipant> output = !l2r ? conv.getLEFT() : conv.getRIGHT(); 311 312 enrichWithMembers(input); 313 enrichWithMembers(output); 314 315 Set<physicalEntityParticipant[]> matching = getEntityMatching(input, output); 316 317 for (physicalEntityParticipant[] tuple : matching) 318 { 319 int inp = isActive(tuple[0]) ? 1 : isInactive(tuple[0]) ? -1 : 0; 320 int oup = isActive(tuple[1]) ? 1 : isInactive(tuple[1]) ? -1 : 0; 321 322 if (oup != 0 && inp != oup) 323 { 324 int sign = oup * effect; 325 326 assert sign != 0; 327 328 if (sign == 1) 329 { 330 interactionSet.add(new SimpleInteraction( 331 A, tuple[1].getPHYSICAL_ENTITY(), BinaryInteractionType.ACTIVATES)); 332 } else 333 { 334 assert sign == -1; 335 336 interactionSet.add(new SimpleInteraction( 337 A, tuple[1].getPHYSICAL_ENTITY(), BinaryInteractionType.INACTIVATES)); 338 } 339 } 340 } 341 342 for (physicalEntityParticipant pep : output) 343 { 344 if (pep.getPHYSICAL_ENTITY() instanceof complex) 345 { 346 int eff = isActive(pep) ? 1 : isInactive(pep) ? -1 : 0; 347 int sign = eff * effect; 348 349 if (sign == 1) 350 { 351 interactionSet.add(new SimpleInteraction( 352 A, pep.getPHYSICAL_ENTITY(), BinaryInteractionType.ACTIVATES)); 353 } 354 else if (sign == -1) 355 { 356 interactionSet.add(new SimpleInteraction( 357 A, pep.getPHYSICAL_ENTITY(), BinaryInteractionType.INACTIVATES)); 358 } 359 360 if (sign != 0) 361 { 362 for (physicalEntity pe : 363 eff == 1 ? getMembers((complex) pep.getPHYSICAL_ENTITY(), true, null) : 364 getMembers((complex) pep.getPHYSICAL_ENTITY(), false, null)) 365 { 366 interactionSet.add(new SimpleInteraction( 367 pe, pep.getPHYSICAL_ENTITY(), BinaryInteractionType.ACTIVATES)); 368 } 369 } 370 } 371 } 372 } 373 374 /** 375 * Enriches the given set with members of the complexes in the set. 376 * @param set set to enrich 377 */ 378 private void enrichWithMembers(Set<physicalEntityParticipant> set) 379 { 380 for (physicalEntityParticipant pep : new HashSet<physicalEntityParticipant>(set)) 381 { 382 if (pep.getPHYSICAL_ENTITY() instanceof complex) 383 { 384 set.addAll(getMembers((complex) pep.getPHYSICAL_ENTITY(), null)); 385 } 386 } 387 } 388 389 /** 390 * Gets the pairs of participants in two sets, where their physicalEntity is the same. 391 * @param set1 first set 392 * @param set2 second set 393 * @return pairs of participants 394 */ 395 private Set<physicalEntityParticipant[]> getEntityMatching(Set<physicalEntityParticipant> set1, 396 Set<physicalEntityParticipant> set2) 397 { 398 Set<physicalEntityParticipant[]> tuples = new HashSet<physicalEntityParticipant[]>(); 399 400 for (physicalEntityParticipant pep1 : set1) 401 { 402 for (physicalEntityParticipant pep2 : set2) 403 { 404 if (pep1.getPHYSICAL_ENTITY() == pep2.getPHYSICAL_ENTITY()) 405 { 406 tuples.add(new physicalEntityParticipant[]{pep1, pep2}); 407 } 408 } 409 } 410 return tuples; 411 } 412}