Selected DAS sources may differ from default
[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 \r
44 \r
45 /**\r
46  * DOCUMENT ME!\r
47  *\r
48  * @author $author$\r
49  * @version $Revision$\r
50  */\r
51 public class DasSequenceFeatureFetcher implements Runnable\r
52 {\r
53   final AlignmentI dataset;\r
54   final AlignFrame af;\r
55   StringBuffer sbuffer = new StringBuffer();\r
56   Vector selectedSources;\r
57 \r
58   long startTime;\r
59   int threadsRunning = 0;\r
60 \r
61 \r
62   /**\r
63    * Creates a new SequenceFeatureFetcher object.\r
64    * Uses default\r
65    *\r
66    * @param align DOCUMENT ME!\r
67    * @param ap DOCUMENT ME!\r
68    */\r
69   public DasSequenceFeatureFetcher(AlignmentI align,\r
70                                    AlignFrame af,\r
71                                    Vector selectedSources)\r
72   {\r
73     this.selectedSources = selectedSources;\r
74     this.dataset = align.getDataset();\r
75     this.af = af;\r
76 \r
77     Thread thread = new Thread(this);\r
78     thread.start();\r
79   }\r
80   /**\r
81    * creates a jalview sequence feature from a das feature document\r
82    * @param dasfeature\r
83    * @return sequence feature object created using dasfeature information\r
84    */\r
85   SequenceFeature newSequenceFeature(Map dasfeature, String nickname)\r
86   {\r
87           try {\r
88                 /**\r
89            * Different qNames for a DAS Feature - are string keys to the HashMaps in features\r
90            * "METHOD") ||\r
91            qName.equals("TYPE") ||\r
92            qName.equals("START") ||\r
93            qName.equals("END") ||\r
94            qName.equals("NOTE") ||\r
95            qName.equals("LINK") ||\r
96            qName.equals("SCORE")\r
97            */\r
98                   String desc = new String();\r
99                   if (dasfeature.containsKey("NOTE"))\r
100                                 desc+=(String) dasfeature.get("NOTE");\r
101 \r
102 \r
103                   int start = 0, end = 0;\r
104                   float score = 0f;\r
105 \r
106                   try{ start = Integer.parseInt( dasfeature.get("START").toString()); }\r
107                   catch( Exception ex){}\r
108                   try{ end = Integer.parseInt( dasfeature.get("END").toString()); }\r
109                   catch (Exception ex){}\r
110                   try{ score = Integer.parseInt( dasfeature.get("SCORE").toString()); }\r
111                   catch (Exception ex){}\r
112 \r
113 \r
114                   SequenceFeature f = new SequenceFeature(\r
115                                   (String) dasfeature.get("TYPE"),\r
116                                   desc,\r
117                                   start,\r
118                                   end,\r
119                                   score,\r
120                                   nickname);\r
121 \r
122                   if (dasfeature.containsKey("LINK"))\r
123                  {\r
124                       f.addLink(f.getType()+" "+f.begin+"_"+f.end\r
125                                 +"|"+ dasfeature.get("LINK"));\r
126                   }\r
127                   // (String) dasfeature.get("ID"),\r
128                   ////  (String) dasfeature.get("METHOD"),\r
129                                 //  (String) dasfeature.get("SCORE"),\r
130                                 //  null\r
131                         // );\r
132 \r
133                      // System.out.println(nickname+" "+f.getType()+" "+f.begin+" "+f.end);\r
134           return f;\r
135           }\r
136           catch (Exception e) {\r
137             e.printStackTrace();\r
138                   Cache.log.debug("Failed to parse "+dasfeature.toString(), e);\r
139                   return null;\r
140           }\r
141   }\r
142   /**\r
143    * fetch and add das features to a sequence using the given source URL and Id to create a feature request\r
144    * @param seq\r
145    * @param SourceUrl\r
146    * @param id\r
147    */\r
148   protected void createFeatureFetcher(final Sequence seq,\r
149                                       final String sourceUrl,\r
150                                       String id,\r
151                                       String nickname)  {\r
152           //////////////\r
153           /// fetch DAS features\r
154           final Das1Source source = new Das1Source();\r
155           source.setUrl(sourceUrl);\r
156           source.setNickname(nickname);\r
157 \r
158 \r
159           Cache.log.debug("new Das Feature Fetcher for " + id + " querying " +\r
160                           sourceUrl);\r
161           if (id != null && id.length() > 0)\r
162           {\r
163             setThreadsRunning(+1);\r
164 \r
165             FeatureThread fetcher = new FeatureThread(id\r
166                +  ":" + seq.getStart() + "," +seq.getEnd()\r
167                  , source);\r
168 \r
169             fetcher.addFeatureListener(new FeatureListener()\r
170             {\r
171               public void comeBackLater(FeatureEvent e)\r
172               {\r
173                 setThreadsRunning(-1);\r
174                 Cache.log.debug("das source " + e.getDasSource().getNickname() +\r
175                                 " asked us to come back in " + e.getComeBackLater() +\r
176                                 " secs.");\r
177               }\r
178 \r
179               public void newFeatures(FeatureEvent e)\r
180               {\r
181                 setThreadsRunning(-1);\r
182                 Das1Source ds = e.getDasSource();\r
183 \r
184                 Map[] features = e.getFeatures();\r
185                 // add features to sequence\r
186                 Cache.log.debug("das source " + ds.getUrl() + " returned " +\r
187                                 features.length + " features");\r
188 \r
189                 if (features.length > 0)\r
190                 {\r
191                   for (int i = 0; i < features.length; i++)\r
192                   {\r
193                       SequenceFeature f = newSequenceFeature(features[i],\r
194                         source.getNickname());\r
195 \r
196                       seq.addSequenceFeature(f);\r
197                   }\r
198                 }\r
199                 else\r
200                 {\r
201                   System.out.println("No features found for sequence " +seq.getName()\r
202                                      +" from: "+ e.getDasSource().getNickname());\r
203                 }\r
204 \r
205               }\r
206             }\r
207 \r
208             );\r
209 \r
210             //NOTE alignPanel listener will be called after the previous\r
211             //anonymous listener!!!\r
212             fetcher.addFeatureListener(af);\r
213 \r
214             fetcher.start();\r
215           }\r
216   }\r
217 \r
218   synchronized void setThreadsRunning(int i)\r
219   {\r
220     threadsRunning += i;\r
221     if(threadsRunning<1)\r
222       af.setProgressBar("DAS Feature Fetching Complete", startTime);\r
223   }\r
224 \r
225   /**\r
226    * Spawns a number of dasobert Fetcher threads to add features to sequences in the dataset\r
227    */\r
228   public void run()\r
229   {\r
230     startTime = System.currentTimeMillis();\r
231     af.setProgressBar("Fetching DAS Sequence Features", startTime);\r
232 \r
233     DasSource [] sources = new jalview.gui.DasSourceBrowser().getDASSource();\r
234 \r
235     if(selectedSources==null || selectedSources.size()==0)\r
236     {\r
237       String active = jalview.bin.Cache.getDefault("DAS_ACTIVE_SOURCE", "uniprot");\r
238       StringTokenizer st = new StringTokenizer(active, "\t");\r
239       Vector selectedSources = new Vector();\r
240       String token;\r
241       while (st.hasMoreTokens())\r
242       {\r
243         token = st.nextToken();\r
244         for (int i = 0; i < sources.length; i++)\r
245         {\r
246           if (sources[i].getNickname().equals(token))\r
247           {\r
248             selectedSources.addElement(sources[i]);\r
249             break;\r
250           }\r
251         }\r
252       }\r
253     }\r
254 \r
255     if(selectedSources == null || selectedSources.size()==0)\r
256     {\r
257       System.out.println("No DAS Sources active");\r
258       af.setProgressBar("No DAS Sources Active", startTime);\r
259       return;\r
260     }\r
261 \r
262     try\r
263     {\r
264       int seqIndex = 0;\r
265       Vector sequences = dataset.getSequences();\r
266       while (seqIndex < sequences.size())\r
267       {\r
268           Sequence sequence = (Sequence) sequences.get(seqIndex);\r
269           Vector uprefs = jalview.util.DBRefUtils.selectRefs(sequence.getDBRef(),\r
270               new String[]  {\r
271               jalview.datamodel.DBRefSource.PDB,\r
272               jalview.datamodel.DBRefSource.UNIPROT});\r
273 \r
274           for(int sourceIndex=0; sourceIndex<selectedSources.size(); sourceIndex++)\r
275           {\r
276             DasSource dasSource = (DasSource)selectedSources.elementAt(sourceIndex);\r
277 \r
278             if (uprefs != null)\r
279             {\r
280               // we know the id for this entry, so don't note its ID in the unknownSequences list\r
281               for (int j = 0;  j < uprefs.size(); j++)\r
282               {\r
283 \r
284                 // 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
285                 org.biojava.dasobert.dasregistry.DasCoordinateSystem cs[] = dasSource.getCoordinateSystem();\r
286                 for (int l=0; l<cs.length; l++)\r
287                 {\r
288                   if (jalview.util.DBRefUtils.isDasCoordinateSystem(cs[l].getName(), (DBRefEntry)\r
289                       uprefs.get(j)))\r
290                   {\r
291                     Cache.log.debug("Launched fetcher for coordinate system " +\r
292                                     cs[l].getName());\r
293 \r
294 \r
295                     createFeatureFetcher(sequence,\r
296                                          dasSource.getUrl(),\r
297                                          ( (DBRefEntry) uprefs.get(j)).\r
298                                          getAccessionId(),\r
299                                          dasSource.getNickname());\r
300                   }\r
301                 }\r
302               }\r
303             }\r
304             else\r
305             {\r
306               String id = null;\r
307               // try and use the name as the sequence id\r
308               if (sequence.getName().indexOf("|") > -1)\r
309               {\r
310                 id = sequence.getName().substring(\r
311                     sequence.getName().lastIndexOf("|") + 1);\r
312               }\r
313               else\r
314               {\r
315                 id = sequence.getName();\r
316               }\r
317               if (id != null)\r
318               {\r
319                 // Should try to call a general feature fetcher that queries many sources with name to discover applicable ID references\r
320                 createFeatureFetcher(sequence,\r
321                                      dasSource.getUrl(),\r
322                                      id,\r
323                                      dasSource.getNickname());\r
324               }\r
325             }\r
326           }\r
327 \r
328           seqIndex++;\r
329     }\r
330     }\r
331     catch (Exception ex)\r
332     {\r
333       ex.printStackTrace();\r
334     }\r
335   }\r
336 \r
337 \r
338   public static DasSource[] getDASSources()\r
339   {\r
340     DasSourceReaderImpl reader = new DasSourceReaderImpl();\r
341 \r
342     String registryURL =jalview.bin.Cache.getDefault("DAS_REGISTRY_URL",\r
343         "http://www.spice-3d.org/dasregistry/das1/sources"\r
344       );\r
345 \r
346     try\r
347     {\r
348       URL url = new URL(registryURL);\r
349 \r
350       DasSource[] sources = reader.readDasSource(url);\r
351 \r
352       List das1sources = new ArrayList();\r
353       for (int i = 0; i < sources.length; i++)\r
354       {\r
355         DasSource ds = sources[i];\r
356         if (ds instanceof Das2Source)\r
357         {\r
358           Das2Source d2s = (Das2Source) ds;\r
359           if (d2s.hasDas1Capabilities())\r
360           {\r
361             Das1Source d1s = DasSourceConverter.toDas1Source(d2s);\r
362             das1sources.add(d1s);\r
363           }\r
364 \r
365         }\r
366         else if (ds instanceof Das1Source)\r
367         {\r
368           das1sources.add( (Das1Source) ds);\r
369         }\r
370       }\r
371 \r
372       return (Das1Source[]) das1sources.toArray(new Das1Source[das1sources.size()]);\r
373     }\r
374     catch (Exception ex)\r
375     {\r
376       ex.printStackTrace();\r
377       return null;\r
378     }\r
379 \r
380   }\r
381 }\r
382 \r
383 \r