Towards an auto dbref fetcher
[jalview.git] / src / jalview / io / DasSequenceFeatureFetcher.java
1 /*\r
2 * Jalview - A Sequence Alignment Editor and Viewer\r
3 * Copyright (C) 2005 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
4 *\r
5 * This program is free software; you can redistribute it and/or\r
6 * modify it under the terms of the GNU General Public License\r
7 * as published by the Free Software Foundation; either version 2\r
8 * of the License, or (at your option) any later version.\r
9 *\r
10 * This program is distributed in the hope that it will be useful,\r
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13 * GNU General Public License for more details.\r
14 *\r
15 * You should have received a copy of the GNU General Public License\r
16 * along with this program; if not, write to the Free Software\r
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA\r
18 */\r
19 package jalview.io;\r
20 \r
21 import jalview.datamodel.*;\r
22 \r
23 import jalview.gui.*;\r
24 \r
25 import java.util.*;\r
26 \r
27 import java.net.URL;\r
28 \r
29 import org.biojava.dasobert.das.FeatureThread;\r
30 import org.biojava.dasobert.dasregistry.Das1Source;\r
31 import org.biojava.dasobert.eventmodel.FeatureEvent;\r
32 import org.biojava.dasobert.eventmodel.FeatureListener;\r
33 import org.biojava.dasobert.dasregistry.DasSource;\r
34 \r
35 import org.biojava.dasobert.das2.io.DasSourceReaderImpl;\r
36 import org.biojava.dasobert.dasregistry.Das1Source;\r
37 import org.biojava.dasobert.dasregistry.DasSource;\r
38 import org.biojava.dasobert.das2.Das2Source;\r
39 import org.biojava.dasobert.das2.DasSourceConverter;\r
40 \r
41 \r
42 import jalview.bin.Cache;\r
43 import org.biojava.dasobert.dasregistry.DasCoordinateSystem;\r
44 \r
45 import javax.swing.*;\r
46 \r
47 /**\r
48  * DOCUMENT ME!\r
49  *\r
50  * @author $author$\r
51  * @version $Revision$\r
52  */\r
53 public class DasSequenceFeatureFetcher implements Runnable\r
54 {\r
55   SequenceI [] sequences;\r
56   AlignFrame af;\r
57   StringBuffer sbuffer = new StringBuffer();\r
58   Vector selectedSources;\r
59 \r
60   long startTime;\r
61   int threadsRunning = 0;\r
62 \r
63 \r
64   /**\r
65    * Creates a new SequenceFeatureFetcher object.\r
66    * Uses default\r
67    *\r
68    * @param align DOCUMENT ME!\r
69    * @param ap DOCUMENT ME!\r
70    */\r
71   public DasSequenceFeatureFetcher(SequenceI [] sequences,\r
72                                    final AlignFrame af,\r
73                                    Vector selectedSources)\r
74   {\r
75     this.selectedSources = selectedSources;\r
76     this.sequences = sequences;\r
77     this.af = af;\r
78 \r
79     int uniprotCount = 0;\r
80     for (int i = 0; i < selectedSources.size(); i++)\r
81     {\r
82       DasSource source = (DasSource) selectedSources.elementAt(i);\r
83       DasCoordinateSystem[] coords = source.getCoordinateSystem();\r
84       for (int c = 0; c < coords.length; c++)\r
85       {\r
86         if (coords[c].getName().equalsIgnoreCase("UniProt"))\r
87         {\r
88           uniprotCount++;\r
89           break;\r
90         }\r
91       }\r
92     }\r
93 \r
94     int refCount = 0;\r
95     for(int i=0; i<sequences.length; i++)\r
96     {\r
97       if(sequences[i].getDBRef()!=null)\r
98       {\r
99         for(int j=0; j<sequences[i].getDBRef().size(); j++)\r
100         {\r
101           System.out.println(sequences[i].getDBRef().elementAt(j)\r
102                              +" "+jalview.datamodel.DBRefSource.UNIPROT);\r
103           if(sequences[i].getDBRef().elementAt(j)\r
104              .equals(jalview.datamodel.DBRefSource.UNIPROT))\r
105           {\r
106             System.out.println("got a match");\r
107             refCount++;\r
108             break;\r
109           }\r
110         }\r
111       }\r
112     }\r
113 \r
114    System.out.println(refCount+" "+uniprotCount+" "+sequences.length);\r
115     if(refCount<sequences.length && uniprotCount>0)\r
116     {\r
117 \r
118      int reply = JOptionPane.showInternalConfirmDialog(Desktop.desktop,\r
119           "Do you want Jalview to find\n"\r
120          +"Uniprot Accession ids for given sequence names?",\r
121          "Find Uniprot Accession Ids",\r
122          JOptionPane.YES_NO_OPTION,\r
123          JOptionPane.QUESTION_MESSAGE);\r
124 \r
125      if(reply == JOptionPane.YES_OPTION)\r
126      {\r
127        new DBRefFetcher(\r
128              af.getViewport().getAlignment(), af).fetchDBRefs(true);\r
129 \r
130      }\r
131     }\r
132 \r
133    System.out.println("User selection is "\r
134                       +\r
135                        ( ( (float) uniprotCount / (float) selectedSources.size()) * 100)\r
136                       + " % Uniprot,  and "+refCount+" / " +sequences.length+" have uniprot accession");\r
137 \r
138 \r
139     Thread thread = new Thread(this);\r
140     thread.start();\r
141   }\r
142   /**\r
143    * creates a jalview sequence feature from a das feature document\r
144    * @param dasfeature\r
145    * @return sequence feature object created using dasfeature information\r
146    */\r
147   SequenceFeature newSequenceFeature(Map dasfeature, String nickname)\r
148   {\r
149           try {\r
150                 /**\r
151            * Different qNames for a DAS Feature - are string keys to the HashMaps in features\r
152            * "METHOD") ||\r
153            qName.equals("TYPE") ||\r
154            qName.equals("START") ||\r
155            qName.equals("END") ||\r
156            qName.equals("NOTE") ||\r
157            qName.equals("LINK") ||\r
158            qName.equals("SCORE")\r
159            */\r
160                   String desc = new String();\r
161                   if (dasfeature.containsKey("NOTE"))\r
162                                 desc+=(String) dasfeature.get("NOTE");\r
163 \r
164 \r
165                   int start = 0, end = 0;\r
166                   float score = 0f;\r
167 \r
168                   try{ start = Integer.parseInt( dasfeature.get("START").toString()); }\r
169                   catch( Exception ex){}\r
170                   try{ end = Integer.parseInt( dasfeature.get("END").toString()); }\r
171                   catch (Exception ex){}\r
172                   try{ score = Integer.parseInt( dasfeature.get("SCORE").toString()); }\r
173                   catch (Exception ex){}\r
174 \r
175 \r
176                   SequenceFeature f = new SequenceFeature(\r
177                                   (String) dasfeature.get("TYPE"),\r
178                                   desc,\r
179                                   start,\r
180                                   end,\r
181                                   score,\r
182                                   nickname);\r
183 \r
184                   if (dasfeature.containsKey("LINK"))\r
185                  {\r
186                       f.addLink(f.getType()+" "+f.begin+"_"+f.end\r
187                                 +"|"+ dasfeature.get("LINK"));\r
188                   }\r
189                   // (String) dasfeature.get("ID"),\r
190                   ////  (String) dasfeature.get("METHOD"),\r
191                                 //  (String) dasfeature.get("SCORE"),\r
192                                 //  null\r
193                         // );\r
194 \r
195                      // System.out.println(nickname+" "+f.getType()+" "+f.begin+" "+f.end);\r
196           return f;\r
197           }\r
198           catch (Exception e) {\r
199             e.printStackTrace();\r
200                   Cache.log.debug("Failed to parse "+dasfeature.toString(), e);\r
201                   return null;\r
202           }\r
203   }\r
204   /**\r
205    * fetch and add das features to a sequence using the given source URL and Id to create a feature request\r
206    * @param seq\r
207    * @param SourceUrl\r
208    * @param id\r
209    */\r
210   protected void createFeatureFetcher(final SequenceI seq,\r
211                                       final String sourceUrl,\r
212                                       String id,\r
213                                       String nickname)  {\r
214           //////////////\r
215           /// fetch DAS features\r
216           final Das1Source source = new Das1Source();\r
217           source.setUrl(sourceUrl);\r
218           source.setNickname(nickname);\r
219 \r
220 \r
221           Cache.log.debug("new Das Feature Fetcher for " + id + " querying " +\r
222                           sourceUrl);\r
223           if (id != null && id.length() > 0)\r
224           {\r
225             setThreadsRunning(+1);\r
226 \r
227             FeatureThread fetcher = new FeatureThread(id\r
228                +  ":" + seq.getStart() + "," +seq.getEnd()\r
229                  , source);\r
230 \r
231             fetcher.addFeatureListener(new FeatureListener()\r
232             {\r
233               public void comeBackLater(FeatureEvent e)\r
234               {\r
235                 setThreadsRunning(-1);\r
236                 Cache.log.debug("das source " + e.getDasSource().getNickname() +\r
237                                 " asked us to come back in " + e.getComeBackLater() +\r
238                                 " secs.");\r
239               }\r
240 \r
241               public void newFeatures(FeatureEvent e)\r
242               {\r
243                 setThreadsRunning(-1);\r
244                 Das1Source ds = e.getDasSource();\r
245 \r
246                 Map[] features = e.getFeatures();\r
247                 // add features to sequence\r
248                 Cache.log.debug("das source " + ds.getUrl() + " returned " +\r
249                                 features.length + " features");\r
250 \r
251                 if (features.length > 0)\r
252                 {\r
253                   for (int i = 0; i < features.length; i++)\r
254                   {\r
255                       SequenceFeature f = newSequenceFeature(features[i],\r
256                         source.getNickname());\r
257 \r
258                       seq.addSequenceFeature(f);\r
259                   }\r
260                 }\r
261                 else\r
262                 {\r
263                   System.out.println("No features found for sequence " +seq.getName()\r
264                                      +" from: "+ e.getDasSource().getNickname());\r
265                 }\r
266 \r
267               }\r
268             }\r
269 \r
270             );\r
271 \r
272             //NOTE alignPanel listener will be called after the previous\r
273             //anonymous listener!!!\r
274             fetcher.addFeatureListener(af);\r
275 \r
276             fetcher.start();\r
277           }\r
278   }\r
279 \r
280   synchronized void setThreadsRunning(int i)\r
281   {\r
282     threadsRunning += i;\r
283     if(threadsRunning<1)\r
284       af.setProgressBar("DAS Feature Fetching Complete", startTime);\r
285   }\r
286 \r
287   /**\r
288    * Spawns a number of dasobert Fetcher threads to add features to sequences in the dataset\r
289    */\r
290   public void run()\r
291   {\r
292     startTime = System.currentTimeMillis();\r
293     af.setProgressBar("Fetching DAS Sequence Features", startTime);\r
294 \r
295     DasSource [] sources = new jalview.gui.DasSourceBrowser().getDASSource();\r
296 \r
297     if(selectedSources==null || selectedSources.size()==0)\r
298     {\r
299       String active = jalview.bin.Cache.getDefault("DAS_ACTIVE_SOURCE", "uniprot");\r
300       StringTokenizer st = new StringTokenizer(active, "\t");\r
301       Vector selectedSources = new Vector();\r
302       String token;\r
303       while (st.hasMoreTokens())\r
304       {\r
305         token = st.nextToken();\r
306         for (int i = 0; i < sources.length; i++)\r
307         {\r
308           if (sources[i].getNickname().equals(token))\r
309           {\r
310             selectedSources.addElement(sources[i]);\r
311             break;\r
312           }\r
313         }\r
314       }\r
315     }\r
316 \r
317     if(selectedSources == null || selectedSources.size()==0)\r
318     {\r
319       System.out.println("No DAS Sources active");\r
320       af.setProgressBar("No DAS Sources Active", startTime);\r
321       return;\r
322     }\r
323 \r
324     try\r
325     {\r
326       int seqIndex = 0;\r
327       while (seqIndex < sequences.length)\r
328       {\r
329           Vector uprefs = jalview.util.DBRefUtils.selectRefs(sequences[seqIndex].getDBRef(),\r
330               new String[]  {\r
331               jalview.datamodel.DBRefSource.PDB,\r
332               jalview.datamodel.DBRefSource.UNIPROT});\r
333 \r
334           for(int sourceIndex=0; sourceIndex<selectedSources.size(); sourceIndex++)\r
335           {\r
336             DasSource dasSource = (DasSource)selectedSources.elementAt(sourceIndex);\r
337 \r
338             if (uprefs != null)\r
339             {\r
340               // we know the id for this entry, so don't note its ID in the unknownSequences list\r
341               for (int j = 0;  j < uprefs.size(); j++)\r
342               {\r
343 \r
344                 // Will have to pass any mapping information to the fetcher - the start/end for the DBRefEntry may not be the same as the sequence's start/end\r
345                 org.biojava.dasobert.dasregistry.DasCoordinateSystem cs[] = dasSource.getCoordinateSystem();\r
346                 for (int l=0; l<cs.length; l++)\r
347                 {\r
348                   if (jalview.util.DBRefUtils.isDasCoordinateSystem(cs[l].getName(), (DBRefEntry)\r
349                       uprefs.get(j)))\r
350                   {\r
351                     Cache.log.debug("Launched fetcher for coordinate system " +\r
352                                     cs[l].getName());\r
353 \r
354 \r
355                     createFeatureFetcher(sequences[seqIndex],\r
356                                          dasSource.getUrl(),\r
357                                          ( (DBRefEntry) uprefs.get(j)).\r
358                                          getAccessionId(),\r
359                                          dasSource.getNickname());\r
360                   }\r
361                 }\r
362               }\r
363             }\r
364             else\r
365             {\r
366               String id = null;\r
367               // try and use the name as the sequence id\r
368               if (sequences[seqIndex].getName().indexOf("|") > -1)\r
369               {\r
370                 id = sequences[seqIndex].getName().substring(\r
371                     sequences[seqIndex].getName().lastIndexOf("|") + 1);\r
372               }\r
373               else\r
374               {\r
375                 id = sequences[seqIndex].getName();\r
376               }\r
377               if (id != null)\r
378               {\r
379                 // Should try to call a general feature fetcher that queries many sources with name to discover applicable ID references\r
380                 createFeatureFetcher(sequences[seqIndex],\r
381                                      dasSource.getUrl(),\r
382                                      id,\r
383                                      dasSource.getNickname());\r
384               }\r
385             }\r
386           }\r
387 \r
388           seqIndex++;\r
389     }\r
390     }\r
391     catch (Exception ex)\r
392     {\r
393       ex.printStackTrace();\r
394     }\r
395   }\r
396 \r
397 \r
398   public static DasSource[] getDASSources()\r
399   {\r
400     DasSourceReaderImpl reader = new DasSourceReaderImpl();\r
401 \r
402     String registryURL =jalview.bin.Cache.getDefault("DAS_REGISTRY_URL",\r
403         "http://das.sanger.ac.uk/registry/das1/sources/"\r
404       );\r
405 \r
406     try\r
407     {\r
408       URL url = new URL(registryURL);\r
409 \r
410       DasSource[] sources = reader.readDasSource(url);\r
411 \r
412       List das1sources = new ArrayList();\r
413       for (int i = 0; i < sources.length; i++)\r
414       {\r
415         DasSource ds = sources[i];\r
416         if (ds instanceof Das2Source)\r
417         {\r
418           Das2Source d2s = (Das2Source) ds;\r
419           if (d2s.hasDas1Capabilities())\r
420           {\r
421             Das1Source d1s = DasSourceConverter.toDas1Source(d2s);\r
422             das1sources.add(d1s);\r
423           }\r
424 \r
425         }\r
426         else if (ds instanceof Das1Source)\r
427         {\r
428           das1sources.add( (Das1Source) ds);\r
429         }\r
430       }\r
431 \r
432       return (Das1Source[]) das1sources.toArray(new Das1Source[das1sources.size()]);\r
433     }\r
434     catch (Exception ex)\r
435     {\r
436       ex.printStackTrace();\r
437       return null;\r
438     }\r
439 \r
440   }\r
441 }\r
442 \r
443 \r