Count uniprot refs
[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         System.out.println(coords[c].getName());\r
87         if (coords[c].getName().indexOf("UniProt")>-1)\r
88         {\r
89           uniprotCount++;\r
90           break;\r
91         }\r
92       }\r
93     }\r
94 \r
95     int refCount = 0;\r
96     for(int i=0; i<sequences.length; i++)\r
97     {\r
98       Vector dbref = sequences[i].getDBRef();\r
99       if(dbref!=null)\r
100       {\r
101         for(int j=0; j<dbref.size(); j++)\r
102         {\r
103           DBRefEntry entry = (DBRefEntry)dbref.elementAt(j);\r
104           System.out.println(entry.getSource()\r
105                              +" "+jalview.datamodel.DBRefSource.UNIPROT);\r
106           if(entry.getSource()\r
107              .equals(jalview.datamodel.DBRefSource.UNIPROT))\r
108           {\r
109             System.out.println("got a match");\r
110             refCount++;\r
111             break;\r
112           }\r
113         }\r
114       }\r
115     }\r
116 \r
117    System.out.println(refCount+" "+uniprotCount+" "+sequences.length);\r
118     if(refCount<sequences.length && uniprotCount>0)\r
119     {\r
120 \r
121      int reply = JOptionPane.showInternalConfirmDialog(Desktop.desktop,\r
122           "Do you want Jalview to find\n"\r
123          +"Uniprot Accession ids for given sequence names?",\r
124          "Find Uniprot Accession Ids",\r
125          JOptionPane.YES_NO_OPTION,\r
126          JOptionPane.QUESTION_MESSAGE);\r
127 \r
128      if(reply == JOptionPane.YES_OPTION)\r
129      {\r
130        new DBRefFetcher(\r
131              af.getViewport().getAlignment(), af).fetchDBRefs(true);\r
132 \r
133      }\r
134     }\r
135 \r
136    System.out.println("User selection is "\r
137                       +\r
138                        ( ( (float) uniprotCount / (float) selectedSources.size()) * 100)\r
139                       + " % Uniprot,  and "+refCount+" / " +sequences.length+" have uniprot accession");\r
140 \r
141 \r
142     Thread thread = new Thread(this);\r
143     thread.start();\r
144   }\r
145   /**\r
146    * creates a jalview sequence feature from a das feature document\r
147    * @param dasfeature\r
148    * @return sequence feature object created using dasfeature information\r
149    */\r
150   SequenceFeature newSequenceFeature(Map dasfeature, String nickname)\r
151   {\r
152           try {\r
153                 /**\r
154            * Different qNames for a DAS Feature - are string keys to the HashMaps in features\r
155            * "METHOD") ||\r
156            qName.equals("TYPE") ||\r
157            qName.equals("START") ||\r
158            qName.equals("END") ||\r
159            qName.equals("NOTE") ||\r
160            qName.equals("LINK") ||\r
161            qName.equals("SCORE")\r
162            */\r
163                   String desc = new String();\r
164                   if (dasfeature.containsKey("NOTE"))\r
165                                 desc+=(String) dasfeature.get("NOTE");\r
166 \r
167 \r
168                   int start = 0, end = 0;\r
169                   float score = 0f;\r
170 \r
171                   try{ start = Integer.parseInt( dasfeature.get("START").toString()); }\r
172                   catch( Exception ex){}\r
173                   try{ end = Integer.parseInt( dasfeature.get("END").toString()); }\r
174                   catch (Exception ex){}\r
175                   try{ score = Integer.parseInt( dasfeature.get("SCORE").toString()); }\r
176                   catch (Exception ex){}\r
177 \r
178 \r
179                   SequenceFeature f = new SequenceFeature(\r
180                                   (String) dasfeature.get("TYPE"),\r
181                                   desc,\r
182                                   start,\r
183                                   end,\r
184                                   score,\r
185                                   nickname);\r
186 \r
187                   if (dasfeature.containsKey("LINK"))\r
188                  {\r
189                       f.addLink(f.getType()+" "+f.begin+"_"+f.end\r
190                                 +"|"+ dasfeature.get("LINK"));\r
191                   }\r
192                   // (String) dasfeature.get("ID"),\r
193                   ////  (String) dasfeature.get("METHOD"),\r
194                                 //  (String) dasfeature.get("SCORE"),\r
195                                 //  null\r
196                         // );\r
197 \r
198                      // System.out.println(nickname+" "+f.getType()+" "+f.begin+" "+f.end);\r
199           return f;\r
200           }\r
201           catch (Exception e) {\r
202             e.printStackTrace();\r
203                   Cache.log.debug("Failed to parse "+dasfeature.toString(), e);\r
204                   return null;\r
205           }\r
206   }\r
207   /**\r
208    * fetch and add das features to a sequence using the given source URL and Id to create a feature request\r
209    * @param seq\r
210    * @param SourceUrl\r
211    * @param id\r
212    */\r
213   protected void createFeatureFetcher(final SequenceI seq,\r
214                                       final String sourceUrl,\r
215                                       String id,\r
216                                       String nickname)\r
217   {\r
218           //////////////\r
219           /// fetch DAS features\r
220           final Das1Source source = new Das1Source();\r
221           source.setUrl(sourceUrl);\r
222           source.setNickname(nickname);\r
223 \r
224 \r
225           Cache.log.debug("new Das Feature Fetcher for " + id + " querying " +\r
226                           sourceUrl);\r
227 \r
228           if (id != null && id.length() > 0)\r
229           {\r
230             setThreadsRunning(+1);\r
231 \r
232             int start=seq.getStart(), end = seq.getEnd();\r
233 \r
234             if(af.getViewport().getSelectionGroup()!=null)\r
235             {\r
236               SequenceI tmp = af.getViewport().getAlignment().findName(seq.getName());\r
237               start = tmp.findPosition(\r
238               af.getViewport().getSelectionGroup().getStartRes()\r
239                   );\r
240 \r
241               end = tmp.findPosition(\r
242                  af.getViewport().getSelectionGroup().getEndRes()\r
243                  );\r
244             }\r
245 \r
246             FeatureThread fetcher = new FeatureThread(id\r
247                +  ":" + start + "," + end, source);\r
248 \r
249             fetcher.addFeatureListener(new FeatureListener()\r
250             {\r
251               public void comeBackLater(FeatureEvent e)\r
252               {\r
253                 setThreadsRunning(-1);\r
254                 Cache.log.debug("das source " + e.getDasSource().getNickname() +\r
255                                 " asked us to come back in " + e.getComeBackLater() +\r
256                                 " secs.");\r
257               }\r
258 \r
259               public void newFeatures(FeatureEvent e)\r
260               {\r
261                 setThreadsRunning(-1);\r
262                 Das1Source ds = e.getDasSource();\r
263 \r
264                 Map[] features = e.getFeatures();\r
265                 // add features to sequence\r
266                 Cache.log.debug("das source " + ds.getUrl() + " returned " +\r
267                                 features.length + " features");\r
268 \r
269                 if (features.length > 0)\r
270                 {\r
271                   for (int i = 0; i < features.length; i++)\r
272                   {\r
273                       SequenceFeature f = newSequenceFeature(features[i],\r
274                         source.getNickname());\r
275 \r
276                       seq.addSequenceFeature(f);\r
277                   }\r
278                 }\r
279                 else\r
280                 {\r
281                   System.out.println("No features found for sequence " +seq.getName()\r
282                                      +" from: "+ e.getDasSource().getNickname());\r
283                 }\r
284 \r
285               }\r
286             }\r
287 \r
288             );\r
289 \r
290             //NOTE alignPanel listener will be called after the previous\r
291             //anonymous listener!!!\r
292             fetcher.addFeatureListener(af);\r
293 \r
294             fetcher.start();\r
295           }\r
296   }\r
297 \r
298   synchronized void setThreadsRunning(int i)\r
299   {\r
300     threadsRunning += i;\r
301     if(threadsRunning<1)\r
302       af.setProgressBar("DAS Feature Fetching Complete", startTime);\r
303   }\r
304 \r
305   /**\r
306    * Spawns a number of dasobert Fetcher threads to add features to sequences in the dataset\r
307    */\r
308   public void run()\r
309   {\r
310     startTime = System.currentTimeMillis();\r
311     af.setProgressBar("Fetching DAS Sequence Features", startTime);\r
312 \r
313     DasSource [] sources = new jalview.gui.DasSourceBrowser().getDASSource();\r
314 \r
315     if(selectedSources==null || selectedSources.size()==0)\r
316     {\r
317       String active = jalview.bin.Cache.getDefault("DAS_ACTIVE_SOURCE", "uniprot");\r
318       StringTokenizer st = new StringTokenizer(active, "\t");\r
319       Vector selectedSources = new Vector();\r
320       String token;\r
321       while (st.hasMoreTokens())\r
322       {\r
323         token = st.nextToken();\r
324         for (int i = 0; i < sources.length; i++)\r
325         {\r
326           if (sources[i].getNickname().equals(token))\r
327           {\r
328             selectedSources.addElement(sources[i]);\r
329             break;\r
330           }\r
331         }\r
332       }\r
333     }\r
334 \r
335     if(selectedSources == null || selectedSources.size()==0)\r
336     {\r
337       System.out.println("No DAS Sources active");\r
338       af.setProgressBar("No DAS Sources Active", startTime);\r
339       return;\r
340     }\r
341 \r
342     try\r
343     {\r
344       int seqIndex = 0;\r
345       while (seqIndex < sequences.length)\r
346       {\r
347           Vector uprefs = jalview.util.DBRefUtils.selectRefs(sequences[seqIndex].getDBRef(),\r
348               new String[]  {\r
349               jalview.datamodel.DBRefSource.PDB,\r
350               jalview.datamodel.DBRefSource.UNIPROT});\r
351 \r
352           for(int sourceIndex=0; sourceIndex<selectedSources.size(); sourceIndex++)\r
353           {\r
354             DasSource dasSource = (DasSource)selectedSources.elementAt(sourceIndex);\r
355 \r
356             if (uprefs != null)\r
357             {\r
358               // we know the id for this entry, so don't note its ID in the unknownSequences list\r
359               for (int j = 0;  j < uprefs.size(); j++)\r
360               {\r
361 \r
362                 // 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
363                 org.biojava.dasobert.dasregistry.DasCoordinateSystem cs[] = dasSource.getCoordinateSystem();\r
364                 for (int l=0; l<cs.length; l++)\r
365                 {\r
366                   if (jalview.util.DBRefUtils.isDasCoordinateSystem(cs[l].getName(), (DBRefEntry)\r
367                       uprefs.get(j)))\r
368                   {\r
369                     Cache.log.debug("Launched fetcher for coordinate system " +\r
370                                     cs[l].getName());\r
371 \r
372 \r
373                     createFeatureFetcher(sequences[seqIndex],\r
374                                          dasSource.getUrl(),\r
375                                          ( (DBRefEntry) uprefs.get(j)).\r
376                                          getAccessionId(),\r
377                                          dasSource.getNickname());\r
378                   }\r
379                 }\r
380               }\r
381             }\r
382             else\r
383             {\r
384               String id = null;\r
385               // try and use the name as the sequence id\r
386               if (sequences[seqIndex].getName().indexOf("|") > -1)\r
387               {\r
388                 id = sequences[seqIndex].getName().substring(\r
389                     sequences[seqIndex].getName().lastIndexOf("|") + 1);\r
390               }\r
391               else\r
392               {\r
393                 id = sequences[seqIndex].getName();\r
394               }\r
395               if (id != null)\r
396               {\r
397                 // Should try to call a general feature fetcher that queries many sources with name to discover applicable ID references\r
398                 createFeatureFetcher(sequences[seqIndex],\r
399                                      dasSource.getUrl(),\r
400                                      id,\r
401                                      dasSource.getNickname());\r
402               }\r
403             }\r
404           }\r
405 \r
406           seqIndex++;\r
407     }\r
408     }\r
409     catch (Exception ex)\r
410     {\r
411       ex.printStackTrace();\r
412     }\r
413   }\r
414 \r
415 \r
416   public static DasSource[] getDASSources()\r
417   {\r
418     DasSourceReaderImpl reader = new DasSourceReaderImpl();\r
419 \r
420     String registryURL =jalview.bin.Cache.getDefault("DAS_REGISTRY_URL",\r
421         "http://das.sanger.ac.uk/registry/das1/sources/"\r
422       );\r
423 \r
424     try\r
425     {\r
426       URL url = new URL(registryURL);\r
427 \r
428       DasSource[] sources = reader.readDasSource(url);\r
429 \r
430       List das1sources = new ArrayList();\r
431       for (int i = 0; i < sources.length; i++)\r
432       {\r
433         DasSource ds = sources[i];\r
434         if (ds instanceof Das2Source)\r
435         {\r
436           Das2Source d2s = (Das2Source) ds;\r
437           if (d2s.hasDas1Capabilities())\r
438           {\r
439             Das1Source d1s = DasSourceConverter.toDas1Source(d2s);\r
440             das1sources.add(d1s);\r
441           }\r
442 \r
443         }\r
444         else if (ds instanceof Das1Source)\r
445         {\r
446           das1sources.add( (Das1Source) ds);\r
447         }\r
448       }\r
449 \r
450       return (Das1Source[]) das1sources.toArray(new Das1Source[das1sources.size()]);\r
451     }\r
452     catch (Exception ex)\r
453     {\r
454       ex.printStackTrace();\r
455       return null;\r
456     }\r
457 \r
458   }\r
459 }\r
460 \r
461 \r