apply gpl development license
[jalview.git] / src / jalview / ws / SequenceFetcher.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer (Development Version 2.4.1)\r
3  * Copyright (C) 2009 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.ws;\r
20 \r
21 import java.util.ArrayList;\r
22 import java.util.Enumeration;\r
23 import java.util.Vector;\r
24 \r
25 import org.biojava.dasobert.das2.Das2Source;\r
26 import org.biojava.dasobert.dasregistry.Das1Source;\r
27 import org.biojava.dasobert.dasregistry.DasCoordinateSystem;\r
28 import org.biojava.dasobert.dasregistry.DasSource;\r
29 \r
30 import jalview.datamodel.Alignment;\r
31 import jalview.datamodel.AlignmentI;\r
32 import jalview.datamodel.DBRefSource;\r
33 import jalview.datamodel.SequenceI;\r
34 import jalview.ws.dbsources.DasSequenceSource;\r
35 import jalview.ws.seqfetcher.ASequenceFetcher;\r
36 import jalview.ws.seqfetcher.DbSourceProxy;\r
37 \r
38 /**\r
39  * This is the the concrete implementation of the sequence retrieval interface\r
40  * and abstract class in jalview.ws.seqfetcher. This implements the run-time\r
41  * discovery of sequence database clients, and provides a hardwired main for\r
42  * testing all registered handlers.\r
43  * \r
44  */\r
45 public class SequenceFetcher extends ASequenceFetcher\r
46 {\r
47   /**\r
48    * Thread safe construction of database proxies TODO: extend to a configurable\r
49    * database plugin mechanism where classes are instantiated by reflection and\r
50    * queried for their DbRefSource and version association.\r
51    * \r
52    */\r
53   public SequenceFetcher()\r
54   {\r
55     addDBRefSourceImpl(jalview.ws.dbsources.EmblSource.class);\r
56     addDBRefSourceImpl(jalview.ws.dbsources.EmblCdsSouce.class);\r
57     addDBRefSourceImpl(jalview.ws.dbsources.Uniprot.class);\r
58     addDBRefSourceImpl(jalview.ws.dbsources.UnprotName.class);\r
59     addDBRefSourceImpl(jalview.ws.dbsources.Pdb.class);\r
60     addDBRefSourceImpl(jalview.ws.dbsources.PfamFull.class);\r
61     addDBRefSourceImpl(jalview.ws.dbsources.PfamSeed.class); // ensures Seed\r
62                                                               // alignment is\r
63                                                               // 'default' for\r
64                                                               // PFAM\r
65     registerDasSequenceSources();\r
66   }\r
67 \r
68   /**\r
69    * return an ordered list of database sources suitable for using in a GUI\r
70    * element\r
71    */\r
72   public String[] getOrderedSupportedSources()\r
73   {\r
74     String[] srcs = this.getSupportedDb();\r
75     ArrayList dassrc = new ArrayList(), nondas = new ArrayList();\r
76     for (int i = 0; i < srcs.length; i++)\r
77     {\r
78       String nm = getSourceProxy(srcs[i]).getDbName();\r
79       if (getSourceProxy(srcs[i]) instanceof jalview.ws.dbsources.DasSequenceSource)\r
80       {\r
81         if (nm.startsWith("das:"))\r
82         {\r
83           nm = nm.substring(4);\r
84         }\r
85         dassrc.add(new String[]\r
86         { srcs[i], nm.toUpperCase() });\r
87       }\r
88       else\r
89       {\r
90         nondas.add(new String[]\r
91         { srcs[i], nm.toUpperCase() });\r
92       }\r
93     }\r
94     Object[] sorted = nondas.toArray();\r
95     String[] tosort = new String[sorted.length];\r
96     nondas.clear();\r
97     for (int j = 0; j < sorted.length; j++)\r
98     {\r
99       tosort[j] = ((String[]) sorted[j])[1];\r
100     }\r
101     jalview.util.QuickSort.sort(tosort, sorted);\r
102     int i = 0;\r
103     for (int j = sorted.length - 1; j >= 0; j--, i++)\r
104     {\r
105       srcs[i] = ((String[]) sorted[j])[0];\r
106       sorted[j] = null;\r
107     }\r
108 \r
109     sorted = dassrc.toArray();\r
110     tosort = new String[sorted.length];\r
111     dassrc.clear();\r
112     for (int j = 0; j < sorted.length; j++)\r
113     {\r
114       tosort[j] = ((String[]) sorted[j])[1];\r
115     }\r
116     jalview.util.QuickSort.sort(tosort, sorted);\r
117     for (int j = sorted.length - 1; j >= 0; j--, i++)\r
118     {\r
119       srcs[i] = ((String[]) sorted[j])[0];\r
120       sorted[j] = null;\r
121     }\r
122     return srcs;\r
123   }\r
124 \r
125   /**\r
126    * simple run method to test dbsources.\r
127    * \r
128    * @param argv\r
129    */\r
130   public static void main(String[] argv)\r
131   {\r
132     AlignmentI ds = null;\r
133     Vector noProds = new Vector();\r
134     String usage = "SequenceFetcher.main [<DBNAME> <ACCNO>]\n"\r
135             + "With no arguments, all DbSources will be queried with their test Accession number.\n"\r
136             + "If given two arguments, SequenceFetcher will try to find the DbFetcher corresponding to <DBNAME> and retrieve <ACCNO> from it.";\r
137     if (argv != null && argv.length > 0)\r
138     {\r
139       DbSourceProxy sp = new SequenceFetcher().getSourceProxy(argv[0]);\r
140       if (sp != null)\r
141       {\r
142         AlignmentI al = null;\r
143         try\r
144         {\r
145           al = sp.getSequenceRecords(argv[1]);\r
146         } catch (Exception e)\r
147         {\r
148           e.printStackTrace();\r
149           System.err.println("Error when retrieving " + argv[1] + " from "\r
150                   + argv[0] + "\nUsage: " + usage);\r
151         }\r
152         SequenceI[] prod = al.getSequencesArray();\r
153         if (al != null)\r
154         {\r
155           for (int p = 0; p < prod.length; p++)\r
156           {\r
157             System.out.println("Prod " + p + ": "\r
158                     + prod[p].getDisplayId(true) + " : "\r
159                     + prod[p].getDescription());\r
160           }\r
161         }\r
162         return;\r
163       }\r
164       else\r
165       {\r
166         System.err.println("Can't resolve " + argv[0]\r
167                 + " as a database name. Allowed values are :\n"\r
168                 + new SequenceFetcher().getSupportedDb());\r
169       }\r
170       System.out.println(usage);\r
171     }\r
172     ASequenceFetcher sfetcher = new SequenceFetcher();\r
173     String[] dbSources = sfetcher.getSupportedDb();\r
174     for (int dbsource = 0; dbsource < dbSources.length; dbsource++)\r
175     {\r
176       String db = dbSources[dbsource];\r
177       // skip me\r
178       if (db.equals(DBRefSource.PDB))\r
179         continue;\r
180       DbSourceProxy sp = sfetcher.getSourceProxy(db);\r
181       System.out.println("Source: " + sp.getDbName() + " (" + db\r
182               + "): retrieving test:" + sp.getTestQuery());\r
183       AlignmentI al = null;\r
184       try\r
185       {\r
186         al = sp.getSequenceRecords(sp.getTestQuery());\r
187         if (al != null && al.getHeight() > 0\r
188                 && sp.getDbSourceProperties() != null)\r
189         {\r
190           boolean dna = sp.getDbSourceProperties().containsKey(\r
191                   DBRefSource.DNACODINGSEQDB)\r
192                   || sp.getDbSourceProperties().containsKey(\r
193                           DBRefSource.DNASEQDB)\r
194                   || sp.getDbSourceProperties().containsKey(\r
195                           DBRefSource.CODINGSEQDB);\r
196           // try and find products\r
197           String types[] = jalview.analysis.CrossRef.findSequenceXrefTypes(\r
198                   dna, al.getSequencesArray());\r
199           if (types != null)\r
200           {\r
201             System.out.println("Xref Types for: " + (dna ? "dna" : "prot"));\r
202             for (int t = 0; t < types.length; t++)\r
203             {\r
204               System.out.println("Type: " + types[t]);\r
205               SequenceI[] prod = jalview.analysis.CrossRef\r
206                       .findXrefSequences(al.getSequencesArray(), dna,\r
207                               types[t]).getSequencesArray();\r
208               System.out.println("Found "\r
209                       + ((prod == null) ? "no" : "" + prod.length)\r
210                       + " products");\r
211               if (prod != null)\r
212               {\r
213                 for (int p = 0; p < prod.length; p++)\r
214                 {\r
215                   System.out.println("Prod " + p + ": "\r
216                           + prod[p].getDisplayId(true));\r
217                 }\r
218               }\r
219             }\r
220           }\r
221           else\r
222           {\r
223             noProds.addElement((dna ? new Object[]\r
224             { al, al } : new Object[]\r
225             { al }));\r
226           }\r
227 \r
228         }\r
229       } catch (Exception ex)\r
230       {\r
231         System.out.println("ERROR:Failed to retrieve test query.");\r
232         ex.printStackTrace(System.out);\r
233       }\r
234       if (al == null)\r
235       {\r
236         System.out.println("ERROR:No alignment retrieved.");\r
237         StringBuffer raw = sp.getRawRecords();\r
238         if (raw != null)\r
239           System.out.println(raw.toString());\r
240         else\r
241           System.out.println("ERROR:No Raw results.");\r
242       }\r
243       else\r
244       {\r
245         System.out.println("Retrieved " + al.getHeight() + " sequences.");\r
246         for (int s = 0; s < al.getHeight(); s++)\r
247         {\r
248           SequenceI sq = al.getSequenceAt(s);\r
249           while (sq.getDatasetSequence() != null)\r
250           {\r
251             sq = sq.getDatasetSequence();\r
252 \r
253           }\r
254           if (ds == null)\r
255           {\r
256             ds = new Alignment(new SequenceI[]\r
257             { sq });\r
258 \r
259           }\r
260           else\r
261           {\r
262             ds.addSequence(sq);\r
263           }\r
264         }\r
265       }\r
266       System.out.flush();\r
267       System.err.flush();\r
268 \r
269     }\r
270     if (noProds.size() > 0)\r
271     {\r
272       Enumeration ts = noProds.elements();\r
273       while (ts.hasMoreElements())\r
274 \r
275       {\r
276         Object[] typeSq = (Object[]) ts.nextElement();\r
277         boolean dna = (typeSq.length > 1);\r
278         AlignmentI al = (AlignmentI) typeSq[0];\r
279         System.out.println("Trying getProducts for "\r
280                 + al.getSequenceAt(0).getDisplayId(true));\r
281         System.out.println("Search DS Xref for: " + (dna ? "dna" : "prot"));\r
282         // have a bash at finding the products amongst all the retrieved\r
283         // sequences.\r
284         SequenceI[] seqs = al.getSequencesArray();\r
285         Alignment prodal = jalview.analysis.CrossRef.findXrefSequences(\r
286                 seqs, dna, null, ds);\r
287         System.out.println("Found "\r
288                 + ((prodal == null) ? "no" : "" + prodal.getHeight())\r
289                 + " products");\r
290         if (prodal != null)\r
291         {\r
292           SequenceI[] prod = prodal.getSequencesArray(); // note\r
293           // should\r
294           // test\r
295           // rather\r
296           // than\r
297           // throw\r
298           // away\r
299           // codon\r
300           // mapping\r
301           // (if\r
302           // present)\r
303           for (int p = 0; p < prod.length; p++)\r
304           {\r
305             System.out.println("Prod " + p + ": "\r
306                     + prod[p].getDisplayId(true));\r
307           }\r
308         }\r
309       }\r
310 \r
311     }\r
312   }\r
313 \r
314   /**\r
315    * query the currently defined DAS source registry for sequence sources and\r
316    * add a DasSequenceSource instance for each source to the SequenceFetcher\r
317    * source list.\r
318    */\r
319   public void registerDasSequenceSources()\r
320   {\r
321     DasSource[] sources = jalview.ws.DasSequenceFeatureFetcher\r
322             .getDASSources();\r
323     if (sources!=null)\r
324     {\r
325       for (int s=0; sources!=null && s<sources.length; s++)\r
326       {\r
327         addDasSequenceSource(sources[s]);\r
328       }\r
329     }\r
330     \r
331     Vector localsources = jalview.bin.Cache.getLocalDasSources();\r
332     if (localsources!=null)\r
333     {   \r
334       for (Enumeration ls = localsources.elements(); ls.hasMoreElements(); )\r
335       {\r
336         addDasSequenceSource((DasSource) ls.nextElement());\r
337       }\r
338     } \r
339   }\r
340   /**\r
341    * Try to create and add a DasSequenceSource to the list of sources.\r
342    * @param source\r
343    * @return null if no source was added, or the new DasSequenceSource created\r
344    */\r
345   DasSequenceSource addDasSequenceSource(DasSource source) {\r
346     DasSequenceSource ds=null;\r
347     Das1Source d1s = null;\r
348     if (source.hasCapability("sequence"))\r
349     {\r
350       if (source instanceof Das2Source)\r
351       {\r
352           if (((Das2Source) source).hasDas1Capabilities())\r
353           {\r
354             try\r
355             {\r
356               d1s = org.biojava.dasobert.das2.DasSourceConverter\r
357                       .toDas1Source((Das2Source) source);\r
358             } catch (Exception e)\r
359             {\r
360               System.err.println("Ignoring DAS2 sequence source "\r
361                       + source.getNickname()\r
362                       + " - couldn't map to Das1Source.\n");\r
363               e.printStackTrace();\r
364             }\r
365           }\r
366         }\r
367         else\r
368         {\r
369           if (source instanceof Das1Source)\r
370           {\r
371             d1s = (Das1Source) source;\r
372           }\r
373         }\r
374       }\r
375       if (d1s != null)\r
376       {\r
377         DasCoordinateSystem[] css = d1s.getCoordinateSystem();\r
378         if (css==null || css.length==0)\r
379         {\r
380           // TODO: query das source directly to identify coordinate system... or\r
381           // have to make up a coordinate system\r
382           css = new DasCoordinateSystem[] { new DasCoordinateSystem()};\r
383           css[0].setName(d1s.getNickname());\r
384           css[0].setUniqueId(d1s.getNickname());\r
385         }\r
386         for (int c = 0; c < css.length; c++)\r
387         {\r
388           try\r
389           {\r
390             addDbRefSourceImpl(ds=new DasSequenceSource(\r
391                     "das:" + d1s.getNickname() + " (" + css[c].getName()\r
392                             + ")", css[c].getName(), d1s, css[c]));\r
393           } catch (Exception e)\r
394           {\r
395             System.err.println("Ignoring sequence coord system " + c + " ("\r
396                     + css[c].getName() + ") for source "\r
397                     + d1s.getNickname()\r
398                     + "- threw exception when constructing fetcher.\n");\r
399             e.printStackTrace();\r
400           }\r
401         }\r
402       }\r
403       return ds;\r
404   }\r
405 }\r