001package org.biopax.paxtools.pattern.miner;
002
003import org.biopax.paxtools.model.BioPAXElement;
004import org.biopax.paxtools.model.Model;
005import org.biopax.paxtools.pattern.Match;
006import org.biopax.paxtools.pattern.Searcher;
007import org.biopax.paxtools.pattern.util.AdjacencyMatrix;
008import org.biopax.paxtools.pattern.util.Blacklist;
009
010import java.io.IOException;
011import java.io.OutputStream;
012import java.io.OutputStreamWriter;
013import java.util.*;
014
015/**
016 * Searches a model and generates SIF network using the pattern matches.
017 *
018 * @author Ozgun Babur
019 */
020public class SIFSearcher
021{
022        /**
023         * SIF miners to use.
024         */
025        private List<SIFMiner> miners;
026
027        /**
028         * SIF types to mine.
029         */
030        private Set<SIFType> types;
031
032        /**
033         * Used for getting an ID out of BioPAX elements.
034         */
035        private IDFetcher idFetcher;
036
037        /**
038         * Blacklist used for detecting ubiquitous molecules.
039         */
040        private Blacklist blacklist;
041
042        /**
043         * Constructor with binary interaction types.
044         * @param types sif types
045         */
046        public SIFSearcher(SIFType... types)
047        {
048                this(null, types);
049        }
050
051        /**
052         * Constructor with miners.
053         * @param miners sif miners
054         */
055        public SIFSearcher(SIFMiner... miners)
056        {
057                this(null, miners);
058        }
059
060        /**
061         * Constructor with ID fetcher and binary interaction types.
062         *
063         * @param idFetcher ID fetcher
064         * @param types sif types
065         */
066        public SIFSearcher(IDFetcher idFetcher, SIFType... types)
067        {
068                this.idFetcher = idFetcher;
069                this.types = new HashSet<SIFType>(Arrays.asList(types));
070
071                if (idFetcher == null) this.idFetcher = new CommonIDFetcher();
072        }
073
074        /**
075         * Constructor with ID fetcher and miners.
076         *
077         * @param idFetcher ID fetcher
078         * @param miners sif miners
079         */
080        public SIFSearcher(IDFetcher idFetcher, SIFMiner... miners)
081        {
082                this.idFetcher = idFetcher;
083                this.miners = Arrays.asList(miners);
084
085                if (idFetcher == null) this.idFetcher = new CommonIDFetcher();
086        }
087
088        private void initMiners()
089        {
090                try
091                {
092                        this.miners = new ArrayList<SIFMiner>();
093
094                        for (SIFType type : types)
095                        {
096                                for (Class<? extends SIFMiner> clazz : type.getMiners())
097                                {
098                                        SIFMiner miner = clazz.newInstance();
099                                        miner.setBlacklist(blacklist);
100                                        miner.setIDFetcher(idFetcher);
101                                        miners.add(miner);
102                                }
103                        }
104                }
105                catch (InstantiationException e)
106                {
107                        e.printStackTrace();
108                }
109                catch (IllegalAccessException e)
110                {
111                        e.printStackTrace();
112                }
113        }
114
115        /**
116         * Sets the blacklist that manages IDs of ubique molecules. This is not mandatory but need if
117         * ubiquitous small molecules are needed to be handled.
118         * @param blacklist for identifying ubiquitous small molecules
119         */
120        public void setBlacklist(Blacklist blacklist)
121        {
122                this.blacklist = blacklist;
123        }
124
125        /**
126         * Searches the given model with the contained miners.
127         * @param model model to search
128         * @return sif interactions
129         */
130        public AdjacencyMatrix searchSIFGetMatrix(Model model)
131        {
132                Set<SIFInteraction> sifInts = searchSIF(model);
133                return new AdjacencyMatrix(
134                        SIFInteraction.convertToAdjacencyMatrix(sifInts),
135                        SIFInteraction.getSortedGeneNames(sifInts));
136        }
137
138        /**
139         * Searches the given model with the contained miners.
140         * @param model model to search
141         * @return sif interactions
142         */
143        public Set<SIFInteraction> searchSIF(Model model)
144        {
145                if (miners == null) initMiners();
146
147                Map<SIFInteraction, SIFInteraction> map = new HashMap<SIFInteraction, SIFInteraction>();
148
149                Map<BioPAXElement, Set<String>> idMap = new HashMap<BioPAXElement, Set<String>>();
150
151                for (SIFMiner miner : miners)
152                {
153                        if (miner instanceof MinerAdapter) ((MinerAdapter) miner).setIdMap(idMap);
154
155                        Map<BioPAXElement,List<Match>> matches = Searcher.search(model, miner.getPattern());
156
157                        for (List<Match> matchList : matches.values())
158                        {
159                                for (Match m : matchList)
160                                {
161                                        Set<SIFInteraction> sifs = miner.createSIFInteraction(m, idFetcher);
162
163                                        //----debug-block
164//                                      if (sif.sourceID.equals("limonin") && sif.targetID.equals("GNG11"))
165//                                      {
166//                                              System.out.println();
167//                                      }
168                                        //----end-of-debug-block
169
170                                        for (SIFInteraction sif : sifs)
171                                        {
172                                                if (sif != null && sif.hasIDs() && !sif.sourceID.equals(sif.targetID) &&
173                                                        (types == null || types.contains(sif.type)))
174                                                {
175                                                        if (map.containsKey(sif))
176                                                        {
177                                                                SIFInteraction existing = map.get(sif);
178                                                                existing.mergeWith(sif);
179                                                        }
180                                                        else map.put(sif, sif);
181                                                }
182                                        }
183                                }
184                        }
185                }
186                return new HashSet<SIFInteraction>(map.values());
187        }
188
189        /**
190         * Searches the given model with the contained miners. Writes the textual result to the given
191         * output stream. Closes the stream at the end. Produces simplest version of SIF format.
192         * @param model model to search
193         * @param out stream to write
194         * @return true if any output produced successfully
195         */
196        public boolean searchSIF(Model model, OutputStream out)
197        {
198                return searchSIF(model, out, false);
199        }
200
201        /**
202         * Searches the given model with the contained miners. Writes the textual result to the given
203         * output stream. Closes the stream at the end.
204         * @param model model to search
205         * @param out stream to write
206         * @param withMediators whether to write the IDs of the mediator elements to the output
207         * @return true if any output produced successfully
208         */
209        public boolean searchSIF(Model model, OutputStream out, final boolean withMediators)
210        {
211                return searchSIF(model, out, new SIFToText()
212                {
213                        @Override
214                        public String convert(SIFInteraction inter)
215                        {
216                                return inter.toString(withMediators);
217                        }
218                });
219        }
220
221        /**
222         * Searches the given model with the contained miners. Writes the textual result to the given
223         * output stream. Closes the stream at the end.
224         * @param model model to search
225         * @param out stream to write
226         * @param stt sif to text converter
227         * @return true if any output produced successfully
228         */
229        public boolean searchSIF(Model model, OutputStream out, SIFToText stt)
230        {
231                Set<SIFInteraction> inters = searchSIF(model);
232
233                if (!inters.isEmpty())
234                {
235                        List<SIFInteraction> interList = new ArrayList<SIFInteraction>(inters);
236                        Collections.sort(interList);
237                        try
238                        {
239                                boolean first = true;
240                                OutputStreamWriter writer = new OutputStreamWriter(out);
241                                for (SIFInteraction inter : interList)
242                                {
243                                        if (first) first = false;
244                                        else writer.write("\n");
245
246                                        writer.write(stt.convert(inter));
247                                }
248                                writer.close();
249                                return true;
250                        }
251                        catch (IOException e)
252                        {
253                                e.printStackTrace();
254                        }
255                }
256                return false;
257        }
258}