Formatting
[jalview.git] / src / jalview / io / DasSequenceFeatureFetcher.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer\r
3  * Copyright (C) 2007 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 java.net.*;\r
22 import java.util.*;\r
23 \r
24 import javax.swing.*;\r
25 \r
26 import org.biojava.dasobert.das.*;\r
27 import org.biojava.dasobert.das2.*;\r
28 import org.biojava.dasobert.das2.io.*;\r
29 import org.biojava.dasobert.dasregistry.*;\r
30 import org.biojava.dasobert.eventmodel.*;\r
31 import jalview.bin.Cache;\r
32 import jalview.datamodel.*;\r
33 import jalview.gui.*;\r
34 \r
35 /**\r
36  * DOCUMENT ME!\r
37  *\r
38  * @author $author$\r
39  * @version $Revision$\r
40  */\r
41 public class DasSequenceFeatureFetcher\r
42 {\r
43   SequenceI[] sequences;\r
44   AlignFrame af;\r
45   FeatureSettings fsettings;\r
46   StringBuffer sbuffer = new StringBuffer();\r
47   Vector selectedSources;\r
48   boolean cancelled = false;\r
49 \r
50   long startTime;\r
51 \r
52   /**\r
53    * Creates a new SequenceFeatureFetcher object.\r
54    * Uses default\r
55    *\r
56    * @param align DOCUMENT ME!\r
57    * @param ap DOCUMENT ME!\r
58    */\r
59   public DasSequenceFeatureFetcher(SequenceI[] sequences,\r
60                                    FeatureSettings fsettings,\r
61                                    Vector selectedSources)\r
62   {\r
63     this.selectedSources = selectedSources;\r
64     this.sequences = sequences;\r
65     this.af = fsettings.af;\r
66     this.fsettings = fsettings;\r
67 \r
68     int uniprotCount = 0;\r
69     for (int i = 0; i < selectedSources.size(); i++)\r
70     {\r
71       DasSource source = (DasSource) selectedSources.elementAt(i);\r
72       DasCoordinateSystem[] coords = source.getCoordinateSystem();\r
73       for (int c = 0; c < coords.length; c++)\r
74       {\r
75         if (coords[c].getName().indexOf("UniProt") > -1)\r
76         {\r
77           uniprotCount++;\r
78           break;\r
79         }\r
80       }\r
81     }\r
82 \r
83     int refCount = 0;\r
84     for (int i = 0; i < sequences.length; i++)\r
85     {\r
86       DBRefEntry[] dbref = sequences[i].getDBRef();\r
87       if (dbref != null)\r
88       {\r
89         for (int j = 0; j < dbref.length; j++)\r
90         {\r
91           if (dbref[j].getSource()\r
92               .equals(jalview.datamodel.DBRefSource.UNIPROT))\r
93           {\r
94             refCount++;\r
95             break;\r
96           }\r
97         }\r
98       }\r
99     }\r
100 \r
101     if (refCount < sequences.length && uniprotCount > 0)\r
102     {\r
103 \r
104       int reply = JOptionPane.showInternalConfirmDialog(Desktop.desktop,\r
105           "Do you want Jalview to find\n"\r
106           + "Uniprot Accession ids for given sequence names?",\r
107           "Find Uniprot Accession Ids",\r
108           JOptionPane.YES_NO_OPTION,\r
109           JOptionPane.QUESTION_MESSAGE);\r
110 \r
111       if (reply == JOptionPane.YES_OPTION)\r
112       {\r
113         Thread thread = new Thread(new FetchDBRefs());\r
114         thread.start();\r
115       }\r
116       else\r
117       {\r
118         startFetching();\r
119       }\r
120     }\r
121     else\r
122     {\r
123       startFetching();\r
124     }\r
125 \r
126   }\r
127 \r
128   class FetchDBRefs\r
129       implements Runnable\r
130   {\r
131     public void run()\r
132     {\r
133       new DBRefFetcher(\r
134           af.getViewport().getAlignment(), af).fetchDBRefs(true);\r
135       startFetching();\r
136     }\r
137   }\r
138 \r
139   /**\r
140    * Spawns a number of dasobert Fetcher threads to add features to sequences in the dataset\r
141    */\r
142   void startFetching()\r
143   {\r
144     cancelled = false;\r
145     startTime = System.currentTimeMillis();\r
146     af.setProgressBar("Fetching DAS Sequence Features", startTime);\r
147 \r
148     DasSource[] sources = new jalview.gui.DasSourceBrowser().getDASSource();\r
149 \r
150     if (selectedSources == null || selectedSources.size() == 0)\r
151     {\r
152       String active = jalview.bin.Cache.getDefault("DAS_ACTIVE_SOURCE",\r
153           "uniprot");\r
154       StringTokenizer st = new StringTokenizer(active, "\t");\r
155       Vector selectedSources = new Vector();\r
156       String token;\r
157       while (st.hasMoreTokens())\r
158       {\r
159         token = st.nextToken();\r
160         for (int i = 0; i < sources.length; i++)\r
161         {\r
162           if (sources[i].getNickname().equals(token))\r
163           {\r
164             selectedSources.addElement(sources[i]);\r
165             break;\r
166           }\r
167         }\r
168       }\r
169     }\r
170 \r
171     if (selectedSources == null || selectedSources.size() == 0)\r
172     {\r
173       System.out.println("No DAS Sources active");\r
174       af.setProgressBar("No DAS Sources Active", startTime);\r
175       return;\r
176     }\r
177 \r
178     sourcesRemaining = selectedSources.size();\r
179     //Now sending requests one at a time to each server\r
180     for (int sourceIndex = 0;\r
181          sourceIndex < selectedSources.size()\r
182          && !cancelled;\r
183          sourceIndex++)\r
184     {\r
185       DasSource dasSource = (DasSource) selectedSources.elementAt(\r
186           sourceIndex);\r
187 \r
188       nextSequence(dasSource, sequences[0]);\r
189     }\r
190   }\r
191 \r
192   public void cancel()\r
193   {\r
194     af.setProgressBar("DAS Feature Fetching Cancelled", startTime);\r
195     cancelled = true;\r
196   }\r
197 \r
198   int sourcesRemaining = 0;\r
199   void responseComplete(DasSource dasSource, SequenceI seq)\r
200   {\r
201     if (seq != null)\r
202     {\r
203       for (int seqIndex = 0;\r
204            seqIndex < sequences.length - 1\r
205            && !cancelled; seqIndex++)\r
206       {\r
207         if (sequences[seqIndex] == seq)\r
208         {\r
209           nextSequence(dasSource, sequences[++seqIndex]);\r
210           return;\r
211         }\r
212       }\r
213     }\r
214 \r
215     sourcesRemaining--;\r
216 \r
217     if (sourcesRemaining == 0)\r
218     {\r
219       af.setProgressBar("DAS Feature Fetching Complete", startTime);\r
220 \r
221       if (af.featureSettings != null)\r
222       {\r
223         af.featureSettings.setTableData();\r
224       }\r
225 \r
226       fsettings.complete();\r
227     }\r
228 \r
229   }\r
230 \r
231   void featuresAdded(SequenceI seq)\r
232   {\r
233     af.getFeatureRenderer().featuresAdded();\r
234 \r
235     int start = af.getViewport().getStartSeq();\r
236     int end = af.getViewport().getEndSeq();\r
237     int index;\r
238     for (index = start; index < end; index++)\r
239     {\r
240       if (seq ==\r
241           af.getViewport().getAlignment().getSequenceAt(index).getDatasetSequence())\r
242       {\r
243         af.alignPanel.repaint();\r
244         break;\r
245       }\r
246     }\r
247   }\r
248 \r
249   void nextSequence(DasSource dasSource, SequenceI seq)\r
250   {\r
251     DBRefEntry[] uprefs = jalview.util.DBRefUtils.selectRefs(seq.getDBRef(),\r
252         new String[]\r
253         {\r
254         //  jalview.datamodel.DBRefSource.PDB,\r
255         jalview.datamodel.DBRefSource.UNIPROT\r
256     });\r
257 \r
258     if (uprefs != null)\r
259     {\r
260       // we know the id for this entry, so don't note its ID in the unknownSequences list\r
261       // for (int j = 0; j < uprefs.length; j++)\r
262       {\r
263         // Will have to pass any mapping information to the fetcher\r
264         //- the start/end for the DBRefEntry may not be the same as the sequence's start/end\r
265         DasCoordinateSystem cs[] = dasSource.getCoordinateSystem();\r
266         if (cs.length > 0)\r
267         {\r
268           // for (int l = 0; l < cs.length; l++)\r
269           {\r
270             //\r
271             if (jalview.util.DBRefUtils\r
272                 .isDasCoordinateSystem(cs[0].getName(), uprefs[0]))\r
273             {\r
274               Cache.log.debug("Launched fetcher for coordinate system " +\r
275                               cs[0].getName());\r
276 \r
277               createFeatureFetcher(seq,\r
278                                    dasSource,\r
279                                    uprefs[0].getAccessionId());\r
280             }\r
281           }\r
282         }\r
283       }\r
284     }\r
285     else\r
286     {\r
287       String id = null;\r
288       // try and use the name as the sequence id\r
289       if (seq.getName().indexOf("|") > -1)\r
290       {\r
291         id = seq.getName().substring(\r
292             seq.getName().lastIndexOf("|") + 1);\r
293       }\r
294       else\r
295       {\r
296         id = seq.getName();\r
297       }\r
298       if (id != null)\r
299       {\r
300         // Should try to call a general feature fetcher that\r
301         // queries many sources with name to discover applicable ID references\r
302         createFeatureFetcher(seq,\r
303                              dasSource,\r
304                              id);\r
305       }\r
306     }\r
307 \r
308   }\r
309 \r
310   /**\r
311    * fetch and add das features to a sequence using the given source URL and Id to create a feature request\r
312    * @param seq\r
313    * @param SourceUrl\r
314    * @param id\r
315    */\r
316   protected void createFeatureFetcher(final SequenceI seq,\r
317                                       final DasSource dasSource,\r
318                                       String id)\r
319   {\r
320     //////////////\r
321     /// fetch DAS features\r
322     final Das1Source source = new Das1Source();\r
323     source.setUrl(dasSource.getUrl());\r
324     source.setNickname(dasSource.getNickname());\r
325 \r
326     Cache.log.debug("new Das Feature Fetcher for " + id + " querying " +\r
327                     dasSource.getUrl());\r
328 \r
329     if (id != null && id.length() > 0)\r
330     {\r
331       FeatureThread fetcher = new FeatureThread(id\r
332                                                 //  +  ":" + start + "," + end,\r
333                                                 , source);\r
334 \r
335       fetcher.addFeatureListener(new FeatureListener()\r
336       {\r
337         public void comeBackLater(FeatureEvent e)\r
338         {\r
339           responseComplete(dasSource, seq);\r
340           Cache.log.debug("das source " + e.getDasSource().getNickname() +\r
341                           " asked us to come back in " + e.getComeBackLater() +\r
342                           " secs.");\r
343         }\r
344 \r
345         public void newFeatures(FeatureEvent e)\r
346         {\r
347 \r
348           Das1Source ds = e.getDasSource();\r
349 \r
350           Map[] features = e.getFeatures();\r
351           // add features to sequence\r
352           Cache.log.debug("das source " + ds.getUrl() + " returned " +\r
353                           features.length + " features");\r
354 \r
355           if (features.length > 0)\r
356           {\r
357             for (int i = 0; i < features.length; i++)\r
358             {\r
359               SequenceFeature f = newSequenceFeature(features[i],\r
360                   source.getNickname());\r
361 \r
362               seq.addSequenceFeature(f);\r
363             }\r
364 \r
365             featuresAdded(seq);\r
366           }\r
367           else\r
368           {\r
369             //  System.out.println("No features found for " + seq.getName()\r
370             //                     + " from: " + e.getDasSource().getNickname());\r
371           }\r
372           responseComplete(dasSource, seq);\r
373 \r
374         }\r
375       }\r
376 \r
377       );\r
378 \r
379       fetcher.start();\r
380     }\r
381   }\r
382 \r
383   /**\r
384    * creates a jalview sequence feature from a das feature document\r
385    * @param dasfeature\r
386    * @return sequence feature object created using dasfeature information\r
387    */\r
388   SequenceFeature newSequenceFeature(Map dasfeature, String nickname)\r
389   {\r
390     try\r
391     {\r
392       /**\r
393        * Different qNames for a DAS Feature - are string keys to the HashMaps in features\r
394        * "METHOD") ||\r
395                   qName.equals("TYPE") ||\r
396                   qName.equals("START") ||\r
397                   qName.equals("END") ||\r
398                   qName.equals("NOTE") ||\r
399                   qName.equals("LINK") ||\r
400                   qName.equals("SCORE")\r
401        */\r
402       String desc = new String();\r
403       if (dasfeature.containsKey("NOTE"))\r
404       {\r
405         desc += (String) dasfeature.get("NOTE");\r
406       }\r
407 \r
408       int start = 0, end = 0;\r
409       float score = 0f;\r
410 \r
411       try\r
412       {\r
413         start = Integer.parseInt(dasfeature.get("START").toString());\r
414       }\r
415       catch (Exception ex)\r
416       {}\r
417       try\r
418       {\r
419         end = Integer.parseInt(dasfeature.get("END").toString());\r
420       }\r
421       catch (Exception ex)\r
422       {}\r
423       try\r
424       {\r
425         score = Integer.parseInt(dasfeature.get("SCORE").toString());\r
426       }\r
427       catch (Exception ex)\r
428       {}\r
429 \r
430       SequenceFeature f = new SequenceFeature(\r
431           (String) dasfeature.get("TYPE"),\r
432           desc,\r
433           start,\r
434           end,\r
435           score,\r
436           nickname);\r
437 \r
438       if (dasfeature.containsKey("LINK"))\r
439       {\r
440         f.addLink(f.getType() + " " + f.begin + "_" + f.end\r
441                   + "|" + dasfeature.get("LINK"));\r
442       }\r
443 \r
444       return f;\r
445     }\r
446     catch (Exception e)\r
447     {\r
448       System.out.println("ERRR " + e);\r
449       e.printStackTrace();\r
450       System.out.println("############");\r
451       Cache.log.debug("Failed to parse " + dasfeature.toString(), e);\r
452       return null;\r
453     }\r
454   }\r
455 \r
456   public static DasSource[] getDASSources()\r
457   {\r
458     DasSourceReaderImpl reader = new DasSourceReaderImpl();\r
459 \r
460     String registryURL = jalview.bin.Cache.getDefault("DAS_REGISTRY_URL",\r
461         DasSourceBrowser.DEFAULT_REGISTRY\r
462         );\r
463 \r
464     try\r
465     {\r
466       URL url = new URL(registryURL);\r
467 \r
468       DasSource[] sources = reader.readDasSource(url);\r
469 \r
470       List das1sources = new ArrayList();\r
471       for (int i = 0; i < sources.length; i++)\r
472       {\r
473         DasSource ds = sources[i];\r
474         if (ds instanceof Das2Source)\r
475         {\r
476           Das2Source d2s = (Das2Source) ds;\r
477           if (d2s.hasDas1Capabilities())\r
478           {\r
479             Das1Source d1s = DasSourceConverter.toDas1Source(d2s);\r
480             das1sources.add(d1s);\r
481           }\r
482 \r
483         }\r
484         else if (ds instanceof Das1Source)\r
485         {\r
486           das1sources.add( (Das1Source) ds);\r
487         }\r
488       }\r
489 \r
490       return (Das1Source[]) das1sources.toArray(new Das1Source[das1sources.size()]);\r
491     }\r
492     catch (Exception ex)\r
493     {\r
494       ex.printStackTrace();\r
495       return null;\r
496     }\r
497   }\r
498 \r
499 }\r