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