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