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.*; 006import org.biopax.paxtools.pattern.Match; 007 008import java.util.Collection; 009import java.util.HashSet; 010import java.util.Set; 011 012/** 013 * This constraint is used to collect related EntityReference of the participant physical entities. 014 * The constraint let's users to set some participants as taboo, and they are excluded from 015 * analysis. 016 * 017 * Var0 - Interaction 018 * Var1 - Taboo element number 1 019 * ... 020 * Var(numTabooElements+1) - Last taboo element 021 * Var(numTabooElements+2) - The related EntityReference 022 * 023 * @author Ozgun Babur 024 */ 025public class InterToPartER extends ConstraintAdapter 026{ 027 /** 028 * Direction to go. When this parameter is used, the interaction has to be a Conversion. 029 */ 030 private Direction direction; 031 032 /** 033 * Constraint used for traversing towards simpler PE. 034 */ 035 private static final LinkedPE linker = new LinkedPE(LinkedPE.Type.TO_SPECIFIC); 036 037 /** 038 * Accessor from PE to ER. 039 */ 040 private static final PathAccessor pe2ER = 041 new PathAccessor("SimplePhysicalEntity/entityReference"); 042 043 /** 044 * Constructor with parameters. A taboo element is the participant that we want to exclude from 045 * the analysis. User should provide the number of taboo elements, then during execution, these 046 * elements will be fetched from the current match. 047 * 048 * @param numOfTabooElements the number of entities to exclude from the analysis 049 */ 050 public InterToPartER(int numOfTabooElements) 051 { 052 super(numOfTabooElements + 2); 053 } 054 055 /** 056 * Constructor with parameters. A taboo element is the participant that we want to exclude from 057 * the analysis. User should provide the number of taboo elements, then during execution, these 058 * elements will be fetched from the current match. The direction is left, or right, or both 059 * sides of the Conversion. 060 * 061 * @param direction ide(s) of an interaction to consider 062 * @param numOfTabooElements the number of entities to exclude from the analysis 063 */ 064 public InterToPartER(Direction direction, int numOfTabooElements) 065 { 066 this(numOfTabooElements); 067 this.direction = direction; 068 } 069 070 /** 071 * Constructor without parameters. There are no taboo elements. 072 */ 073 public InterToPartER() 074 { 075 this(0); 076 } 077 078 /** 079 * Constructor with direction. There are no taboo elements. 080 * 081 * @param direction - side(s) of an interaction to consider; 082 * see {@link org.biopax.paxtools.pattern.constraint.InterToPartER.Direction} 083 */ 084 public InterToPartER(Direction direction) 085 { 086 this(); 087 this.direction = direction; 088 } 089 090 /** 091 * This is a generative constraint. 092 * @return true if the constraint can generate candidates 093 */ 094 @Override 095 public boolean canGenerate() 096 { 097 return true; 098 } 099 100 /** 101 * Iterated over non-taboo participants and collectes related ER. 102 * @param match current pattern match 103 * @param ind mapped indices 104 * @return related participants 105 */ 106 @Override 107 public Collection<BioPAXElement> generate(Match match, int... ind) 108 { 109 Interaction inter = (Interaction) match.get(ind[0]); 110 111 Set<Entity> taboo = new HashSet<Entity>(); 112 113 for (int i = 1; i < getVariableSize() - 1; i++) 114 { 115 taboo.add((Entity) match.get(ind[i])); 116 } 117 118 if (direction == null) return generate(inter, taboo); 119 else return generate((Conversion) inter, direction, taboo); 120 } 121 122 /** 123 * Gets the related entity references of the given interaction. 124 * @param inter interaction 125 * @param taboo entities to ignore/skip 126 * @return entity references 127 */ 128 protected Collection<BioPAXElement> generate(Interaction inter, Set<Entity> taboo) 129 { 130 Set<BioPAXElement> simples = new HashSet<BioPAXElement>(); 131 132 for (Entity part : inter.getParticipant()) 133 { 134 if (part instanceof PhysicalEntity && !taboo.contains(part)) 135 { 136 simples.addAll(linker.getLinkedElements((PhysicalEntity) part)); 137 } 138 } 139 140 return pe2ER.getValueFromBeans(simples); 141 } 142 143 /** 144 * Gets the related entity references of the given interaction, 145 * @param conv conversion interaction 146 * @param direction which side(s) participants of the conversion to consider 147 * @param taboo skip list of entities 148 * @return entity references 149 */ 150 protected Collection<BioPAXElement> generate(Conversion conv, Direction direction, 151 Set<Entity> taboo) 152 { 153 if (direction == null) throw new IllegalArgumentException("Direction cannot be null"); 154 155 if (!(direction == Direction.BOTHSIDERS || direction == Direction.ONESIDERS)) 156 { 157 Set<BioPAXElement> simples = new HashSet<BioPAXElement>(); 158 159 for (Entity part : direction == Direction.ANY ? conv.getParticipant() : 160 direction == Direction.LEFT ? conv.getLeft() : conv.getRight()) 161 { 162 if (part instanceof PhysicalEntity && !taboo.contains(part)) 163 { 164 simples.addAll(linker.getLinkedElements((PhysicalEntity) part)); 165 } 166 } 167 168 return pe2ER.getValueFromBeans(simples); 169 } 170 else 171 { 172 Set<BioPAXElement> leftSimples = new HashSet<BioPAXElement>(); 173 Set<BioPAXElement> rightSimples = new HashSet<BioPAXElement>(); 174 175 for (PhysicalEntity pe : conv.getLeft()) 176 { 177 if (!taboo.contains(pe)) leftSimples.addAll(linker.getLinkedElements(pe)); 178 } 179 for (PhysicalEntity pe : conv.getRight()) 180 { 181 if (!taboo.contains(pe)) rightSimples.addAll(linker.getLinkedElements(pe)); 182 } 183 184 Set leftERs = pe2ER.getValueFromBeans(leftSimples); 185 Set rightERs = pe2ER.getValueFromBeans(rightSimples); 186 187 if (direction == Direction.ONESIDERS) 188 { 189 // get all but intersection 190 Set temp = new HashSet(leftERs); 191 leftERs.removeAll(rightERs); 192 rightERs.removeAll(temp); 193 leftERs.addAll(rightERs); 194 } 195 else // BOTHSIDERS 196 { 197 // get intersection 198 leftERs.retainAll(rightERs); 199 } 200 201 return leftERs; 202 } 203 } 204 205 public enum Direction 206 { 207 LEFT, 208 RIGHT, 209 ANY, 210 ONESIDERS, 211 BOTHSIDERS 212 } 213}