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