001package org.biopax.paxtools.pattern.miner;
002
003import org.biopax.paxtools.controller.PathAccessor;
004import org.biopax.paxtools.model.BioPAXElement;
005import org.biopax.paxtools.model.level3.Pathway;
006import org.biopax.paxtools.model.level3.PublicationXref;
007
008import java.util.*;
009
010/**
011 * @author Ozgun Babur
012 */
013public class SIFInteraction implements Comparable
014{
015        public Set<BioPAXElement> sourceERs;
016        public Set<BioPAXElement> targetERs;
017        public Set<BioPAXElement> sourcePEs;
018        public Set<BioPAXElement> targetPEs;
019        public String sourceID;
020        public String targetID;
021        public SIFType type;
022        public Set<BioPAXElement> mediators;
023
024        public SIFInteraction(String sourceID, String targetID, BioPAXElement sourceER,
025                BioPAXElement targetER, SIFType type, Set<BioPAXElement> mediators,
026                Set<BioPAXElement> sourcePEs, Set<BioPAXElement> targetPEs)
027        {
028                this.sourceID = sourceID;
029                this.targetID = targetID;
030                this.sourceERs = new HashSet<BioPAXElement>();
031                this.targetERs = new HashSet<BioPAXElement>();
032
033                this.sourceERs.add(sourceER);
034                this.targetERs.add(targetER);
035                this.type = type;
036
037                this.mediators = mediators;
038                this.sourcePEs = sourcePEs;
039                this.targetPEs = targetPEs;
040        }
041
042        public boolean hasIDs()
043        {
044                return sourceID != null && targetID != null;
045        }
046
047        @Override
048        public int hashCode()
049        {
050                return sourceID.hashCode() + targetID.hashCode() + type.hashCode();
051        }
052
053        @Override
054        public boolean equals(Object obj)
055        {
056                if (obj instanceof SIFInteraction)
057                {
058                        SIFInteraction i = (SIFInteraction) obj;
059
060                        return i.type.equals(type) && i.sourceID.equals(sourceID) && i.targetID.equals(targetID);
061                }
062
063                return false;
064        }
065
066        @Override
067        public int compareTo(Object o)
068        {
069                if (o instanceof SIFInteraction)
070                {
071                        SIFInteraction i = (SIFInteraction) o;
072
073                        return (sourceID + targetID + type.getTag()).compareTo(
074                                i.sourceID + i.targetID + i.type.getTag());
075                }
076
077                return 0;
078        }
079
080        /**
081         * Merges publications of the parameter equivalent sif with this one.
082         * @param equivalent the equivalent sif interaction to get its publications.
083         */
084        public void mergeWith(SIFInteraction equivalent)
085        {
086                if (!this.equals(equivalent))
087                        throw new IllegalArgumentException("SIF interactions are not equivalent.");
088
089                sourceERs.addAll(equivalent.sourceERs);
090                targetERs.addAll(equivalent.targetERs);
091
092                sourcePEs.addAll(equivalent.sourcePEs);
093                targetPEs.addAll(equivalent.targetPEs);
094
095                if (mediators == null) mediators = equivalent.mediators;
096                else if (equivalent.mediators != null)
097                {
098                        mediators.addAll(equivalent.mediators);
099                }
100        }
101
102        @Override
103        public String toString()
104        {
105                return toString(false);
106        }
107
108        public String toString(boolean withMediators)
109        {
110                String s = sourceID + "\t" + type.getTag() + "\t" + targetID;
111
112                if (withMediators)
113                {
114                        String m = getMediatorsInString();
115                        if (!m.isEmpty()) s += "\t" + m;
116                }
117
118                return s;
119        }
120
121        /**
122         * Collects IDs of mediators.
123         * @return mediator IDs
124         */
125        public List<String> getMediatorIDs()
126        {
127                List<String> ids = new ArrayList<String>(mediators.size());
128
129                for (BioPAXElement ele : mediators)
130                {
131                        ids.add(ele.getRDFId());
132                }
133                return ids;
134        }
135
136        /**
137         * Gets the mediator IDs in a String with a space between each ID.
138         *
139         * @return mediator IDs joined with spaces.
140         */
141        public String getMediatorsInString()
142        {
143                String m = "";
144                for (String mid : getMediatorIDs())
145                {
146                        m+= " " + mid;
147                }
148                return m.trim();
149        }
150
151        /**
152         * Collects PMIDs from mediators.
153         * @return PMIDs
154         */
155        public List<String> getPubmedIDs()
156        {
157                if (mediators == null) return Collections.emptyList();
158
159                Set<String> set = harvestPMIDs(harvestPublicationXrefs(
160                        mediators.toArray(new BioPAXElement[mediators.size()])));
161
162                List<String> list = new ArrayList<String>(set);
163                Collections.sort(list);
164
165                return list;
166        }
167
168        private static final PathAccessor xrefAcc = new PathAccessor("XReferrable/xref:PublicationXref");
169        private static final PathAccessor evidAcc = new PathAccessor("Observable/evidence/xref:PublicationXref");
170
171        /**
172         * Collects publication xrefs of the given elements.
173         * @param ele element array
174         * @return publication xrefs
175         */
176        private Set<PublicationXref> harvestPublicationXrefs(BioPAXElement... ele)
177        {
178                Set<PublicationXref> set = new HashSet<PublicationXref>();
179
180                for (Object o : xrefAcc.getValueFromBeans(Arrays.asList(ele)))
181                {
182                        set.add((PublicationXref) o);
183                }
184                for (Object o : evidAcc.getValueFromBeans(Arrays.asList(ele)))
185                {
186                        set.add((PublicationXref) o);
187                }
188                return set;
189        }
190
191        /**
192         * Collects PubMed IDs fromt the given publication xrefs.
193         * @param xrefs publication xrefs
194         * @return PMIDs
195         */
196        private Set<String> harvestPMIDs(Set<PublicationXref> xrefs)
197        {
198                Set<String> set = new HashSet<String>();
199
200                for (PublicationXref xref : xrefs)
201                {
202                        if (xref.getDb() != null && xref.getDb().equalsIgnoreCase("pubmed"))
203                                if (xref.getId() != null && !xref.getId().isEmpty())
204                                        set.add(xref.getId());
205                }
206                return set;
207        }
208
209        private static final PathAccessor pathwayAcc1 = new PathAccessor("Interaction/pathwayComponentOf*");
210        private static final PathAccessor pathwayAcc2 = new PathAccessor("Interaction/stepProcessOf/pathwayOrderOf");
211
212        /**
213         * Collects Pathway objects that the Interactions among the mediators are members.
214         * @return related pathways
215         */
216        public Set<Pathway> getPathways()
217        {
218                Set<Pathway> set = new HashSet<Pathway>();
219
220                for (Object o : pathwayAcc1.getValueFromBeans(mediators))
221                {
222                        set.add((Pathway) o);
223                }
224                for (Object o : pathwayAcc2.getValueFromBeans(mediators))
225                {
226                        set.add((Pathway) o);
227                }
228
229                return set;
230        }
231
232        /**
233         * Collects the names of the related pathways.
234         * @return pathway names
235         */
236        public List<String> getPathwayNames()
237        {
238                Set<Pathway> set = getPathways();
239                List<String> names = new ArrayList<String>();
240
241                for (Pathway p : set)
242                {
243                        String name = p.getDisplayName();
244                        if (!names.contains(name)) names.add(name);
245                }
246
247                Collections.sort(names);
248                return names;
249        }
250
251        private static final PathAccessor dataSourceAcc = new PathAccessor("Entity/dataSource/displayName");
252
253        /**
254         * Collects data source names (Provenance display names) of mediators.
255         * @return related data sources
256         */
257        public Set<String> getDataSources()
258        {
259                Set<String> set = new HashSet<String>();
260
261                for (Object o : dataSourceAcc.getValueFromBeans(mediators))
262                {
263                        set.add((String) o);
264                }
265
266                return set;
267        }
268
269        private static final PathAccessor locAcc = new PathAccessor("PhysicalEntity/cellularLocation/term");
270
271        /**
272         * Collects cellular location terms of target objects.
273         * @return cellular locations
274         */
275        public Set<String> getCellularLocationsOfTarget()
276        {
277                return getCellularLocations(targetPEs);
278        }
279
280        /**
281         * Collects cellular location terms of source objects.
282         * @return cellular locations
283         */
284        public Set<String> getCellularLocationsOfSource()
285        {
286                return getCellularLocations(sourcePEs);
287        }
288
289        /**
290         * Collects cellular location terms of related objects.
291         * @return cellular locations
292         */
293        private Set<String> getCellularLocations(Set<BioPAXElement> eles)
294        {
295                Set<String> set = new HashSet<String>();
296
297                for (Object o : locAcc.getValueFromBeans(eles))
298                {
299                        set.add((String) o);
300                }
301
302                return set;
303        }
304
305
306
307        //---- Section: Static methods ----------------------------------------------------------------|
308
309        /**
310         * Collects and sorts sourceID and targetID of the given collection of sif interactions.
311         * @param sifInts interactions to consider
312         * @param type types of interest, all types accepted if empty
313         * @return sorted source and target IDS
314         */
315        public static List<String> getSortedGeneNames(Collection<SIFInteraction> sifInts,
316                SIFType... type)
317        {
318                Set<String> genes = new HashSet<String>();
319                Set<SIFType> types = new HashSet<SIFType>(Arrays.asList(type));
320
321                // collect gene names
322
323                for (SIFInteraction sifInt : sifInts)
324                {
325                        if (!types.isEmpty() && !types.contains(sifInt.type)) continue;
326
327                        genes.add(sifInt.sourceID);
328                        genes.add(sifInt.targetID);
329                }
330
331                // sort all gene names
332
333                List<String> names = new ArrayList<String>(genes);
334                Collections.sort(names);
335
336                return names;
337        }
338
339        /**
340         * Converts the given collection of interactions into an adjacency matrix.
341         * @param sifInts interactions to consider
342         * @param type types of interest, all types accepted if empty
343         * @return the sif network as adjacency matrix
344         */
345        public static boolean[][] convertToAdjacencyMatrix(Collection<SIFInteraction> sifInts,
346                SIFType... type)
347        {
348                Set<SIFType> types = new HashSet<SIFType>(Arrays.asList(type));
349
350                // collect gene names
351                List<String> names = getSortedGeneNames(sifInts, type);
352
353                // record name indexes for efficient lookup
354
355                Map<String, Integer> name2ind = new HashMap<String, Integer>();
356                int i = 0;
357                for (String name : names)
358                {
359                        name2ind.put(name, i++);
360                }
361
362                // generate adjacency matrix
363
364                boolean[][] matrix = new boolean[names.size()][names.size()];
365                for (boolean[] m : matrix) Arrays.fill(m, false);
366
367                for (SIFInteraction sifInt : sifInts)
368                {
369                        if (!types.isEmpty() && !types.contains(sifInt.type)) continue;
370
371                        matrix[name2ind.get(sifInt.sourceID)][name2ind.get(sifInt.targetID)] = true;
372
373                        if (!sifInt.type.isDirected())
374                        {
375                                matrix[name2ind.get(sifInt.targetID)][name2ind.get(sifInt.sourceID)] = true;
376                        }
377                }
378
379                return matrix;
380        }
381}