109f4b45ce5ba3d7205e6b65f974ff9d76da780c
[jalview.git] / src / jalview / ws / DBRefFetcher.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer\r
3  * Copyright (C) 2007 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.io.*;\r
22 import java.util.*;\r
23 \r
24 import org.exolab.castor.mapping.*;\r
25 import org.exolab.castor.xml.*;\r
26 import jalview.analysis.*;\r
27 import jalview.datamodel.*;\r
28 import jalview.gui.*;\r
29 import jalview.ws.ebi.EBIFetchClient;\r
30 \r
31 /**\r
32  * DOCUMENT ME!\r
33  *\r
34  * @author $author$\r
35  * @version $Revision$\r
36  */\r
37 public class DBRefFetcher\r
38     implements Runnable\r
39 {\r
40   SequenceI [] dataset;\r
41   AlignFrame af;\r
42   CutAndPasteTransfer output = new CutAndPasteTransfer();\r
43   StringBuffer sbuffer = new StringBuffer();\r
44   boolean running = false;\r
45 \r
46   ///This will be a collection of Vectors of sequenceI refs.\r
47   //The key will be the seq name or accession id of the seq\r
48   Hashtable seqRefs;\r
49 \r
50   public DBRefFetcher()\r
51   {}\r
52 \r
53   public Vector getUniprotEntries(File file)\r
54   {\r
55     UniprotFile uni = new UniprotFile();\r
56     try\r
57     {\r
58       // 1. Load the mapping information from the file\r
59       org.exolab.castor.mapping.Mapping map = new org.exolab.castor.mapping.Mapping(uni.getClass().getClassLoader());\r
60       java.net.URL url = getClass().getResource("/uniprot_mapping.xml");\r
61       map.loadMapping(url);\r
62 \r
63       // 2. Unmarshal the data\r
64       Unmarshaller unmar = new Unmarshaller(uni);\r
65       unmar.setIgnoreExtraElements(true);\r
66       unmar.setMapping(map);\r
67 \r
68       uni = (UniprotFile) unmar.unmarshal(new FileReader(file));\r
69     }\r
70     catch (Exception e)\r
71     {\r
72       System.out.println("Error getUniprotEntries() " + e);\r
73     }\r
74 \r
75     return uni.getUniprotEntries();\r
76   }\r
77 \r
78   /**\r
79    * Creates a new SequenceFeatureFetcher object.\r
80    *\r
81    * @param align DOCUMENT ME!\r
82    * @param ap DOCUMENT ME!\r
83    */\r
84   public DBRefFetcher(SequenceI [] seqs, AlignFrame af)\r
85   {\r
86     this.af = af;\r
87     SequenceI [] ds = new SequenceI[seqs.length];\r
88     for (int i = 0; i < seqs.length; i++)\r
89     {\r
90       if(seqs[i].getDatasetSequence()!=null)\r
91         ds[i] = seqs[i].getDatasetSequence();\r
92       else\r
93         ds[i] = seqs[i];\r
94     }\r
95     this.dataset = ds;\r
96   }\r
97 \r
98   public boolean fetchDBRefs(boolean waitTillFinished)\r
99   {\r
100     Thread thread = new Thread(this);\r
101     thread.start();\r
102     running = true;\r
103 \r
104     if (waitTillFinished)\r
105     {\r
106       while (running)\r
107       {\r
108         try\r
109         {\r
110           Thread.sleep(500);\r
111         }\r
112         catch (Exception ex)\r
113         {}\r
114       }\r
115     }\r
116 \r
117     return true;\r
118   }\r
119 \r
120   /**\r
121    * The sequence will be added to a vector of sequences\r
122    * belonging to key which could be either seq name or dbref id\r
123    * @param seq SequenceI\r
124    * @param key String\r
125    */\r
126   void addSeqId(SequenceI seq, String key)\r
127   {\r
128     key = key.toUpperCase();\r
129 \r
130     Vector seqs;\r
131     if (seqRefs.containsKey(key))\r
132     {\r
133       seqs = (Vector) seqRefs.get(key);\r
134 \r
135       if (seqs != null && !seqs.contains(seq))\r
136       {\r
137         seqs.addElement(seq);\r
138       }\r
139       else if (seqs == null)\r
140       {\r
141         seqs = new Vector();\r
142         seqs.addElement(seq);\r
143       }\r
144 \r
145     }\r
146     else\r
147     {\r
148       seqs = new Vector();\r
149       seqs.addElement(seq);\r
150     }\r
151 \r
152     seqRefs.put(key, seqs);\r
153   }\r
154 \r
155   /**\r
156    * DOCUMENT ME!\r
157    */\r
158   public void run()\r
159   {\r
160     long startTime = System.currentTimeMillis();\r
161     af.setProgressBar("Fetching db refs", startTime);\r
162     running = true;\r
163 \r
164     seqRefs = new Hashtable();\r
165 \r
166     try\r
167     {\r
168       int seqIndex = 0;\r
169 \r
170       while (seqIndex < dataset.length)\r
171       {\r
172         StringBuffer queryString = new StringBuffer("uniprot:");\r
173 \r
174         for (int i = 0; (seqIndex < dataset.length) && (i < 50);\r
175              seqIndex++, i++)\r
176         {\r
177           SequenceI sequence = dataset[seqIndex];\r
178           DBRefEntry[] uprefs = jalview.util.DBRefUtils.selectRefs(sequence.\r
179               getDBRef(), new String[]\r
180               {\r
181               jalview.datamodel.DBRefSource.UNIPROT});\r
182           if (uprefs != null)\r
183           {\r
184             if (uprefs.length + i > 50)\r
185             {\r
186               break;\r
187             }\r
188 \r
189             for (int j = 0; j < uprefs.length; j++)\r
190             {\r
191               addSeqId(sequence, uprefs[j].getAccessionId());\r
192               queryString.append(uprefs[j].getAccessionId() + ";");\r
193             }\r
194           }\r
195           else\r
196           {\r
197             StringTokenizer st = new StringTokenizer(sequence.getName(), "|");\r
198             if (st.countTokens() + i > 50)\r
199             {\r
200               //Dont send more than 50 id strings to dbFetch!!\r
201               seqIndex--;\r
202             }\r
203             else\r
204             {\r
205               while (st.hasMoreTokens())\r
206               {\r
207                 String token = st.nextToken();\r
208                 addSeqId(sequence, token);\r
209                 queryString.append(token + ";");\r
210               }\r
211             }\r
212           }\r
213         }\r
214 \r
215         ///////////////////////////////////\r
216         ///READ FROM EBI\r
217         EBIFetchClient ebi = new EBIFetchClient();\r
218         File file = ebi.fetchDataAsFile(queryString.toString(), "xml", "raw");\r
219         if (file != null)\r
220         {\r
221           ReadUniprotFile(file);\r
222         }\r
223       }\r
224     }\r
225     catch (Exception ex)\r
226     {\r
227       ex.printStackTrace();\r
228     }\r
229 \r
230     if (sbuffer.length() > 0)\r
231     {\r
232       output.setText(\r
233           "Your sequences have been matched to Uniprot. Some of the ids have been\n" +\r
234           "altered, most likely the start/end residue will have been updated.\n" +\r
235           "Save your alignment to maintain the updated id.\n\n" +\r
236           sbuffer.toString());\r
237       Desktop.addInternalFrame(output, "Sequence names updated ", 600, 300);\r
238       // The above is the dataset, we must now find out the index\r
239       // of the viewed sequence\r
240 \r
241     }\r
242 \r
243     af.setProgressBar("DBRef search completed", startTime);\r
244     // promptBeforeBlast();\r
245 \r
246     running = false;\r
247 \r
248   }\r
249 \r
250   /**\r
251    * DOCUMENT ME!\r
252    *\r
253    * @param result DOCUMENT ME!\r
254    * @param out DOCUMENT ME!\r
255    * @param align DOCUMENT ME!\r
256    */\r
257   void ReadUniprotFile(File file)\r
258   {\r
259     if (!file.exists())\r
260     {\r
261       return;\r
262     }\r
263 \r
264     SequenceI sequence = null;\r
265 \r
266     Vector entries = getUniprotEntries(file);\r
267 \r
268     int i, iSize = entries == null ? 0 : entries.size();\r
269     UniprotEntry entry;\r
270     for (i = 0; i < iSize; i++)\r
271     {\r
272       entry = (UniprotEntry) entries.elementAt(i);\r
273 \r
274       //Work out which sequences this Uniprot file has matches to,\r
275       //taking into account all accessionIds and names in the file\r
276       Vector sequenceMatches = new Vector();\r
277       for (int j = 0; j < entry.getAccession().size(); j++)\r
278       {\r
279         String accessionId = entry.getAccession().elementAt(j).toString();\r
280         if (seqRefs.containsKey(accessionId))\r
281         {\r
282           Vector seqs = (Vector) seqRefs.get(accessionId);\r
283           for (int jj = 0; jj < seqs.size(); jj++)\r
284           {\r
285             sequence = (SequenceI) seqs.elementAt(jj);\r
286             if (!sequenceMatches.contains(sequence))\r
287             {\r
288               sequenceMatches.addElement(sequence);\r
289             }\r
290           }\r
291         }\r
292       }\r
293       for (int j = 0; j < entry.getName().size(); j++)\r
294       {\r
295         String name = entry.getName().elementAt(j).toString();\r
296         if (seqRefs.containsKey(name))\r
297         {\r
298           Vector seqs = (Vector) seqRefs.get(name);\r
299           for (int jj = 0; jj < seqs.size(); jj++)\r
300           {\r
301             sequence = (SequenceI) seqs.elementAt(jj);\r
302             if (!sequenceMatches.contains(sequence))\r
303             {\r
304               sequenceMatches.addElement(sequence);\r
305             }\r
306           }\r
307         }\r
308       }\r
309 \r
310       for (int m = 0; m < sequenceMatches.size(); m++)\r
311       {\r
312         sequence = (SequenceI) sequenceMatches.elementAt(m);\r
313         sequence.addDBRef(new DBRefEntry(DBRefSource.UNIPROT,\r
314                                          "0", // TODO: VERSION FROM UNIPROT\r
315                                          entry.getAccession().elementAt(0).\r
316                                          toString()));\r
317 \r
318         System.out.println("Adding dbref to " + sequence.getName() + " : " +\r
319                            entry.getAccession().elementAt(0).toString());\r
320 \r
321         String nonGapped = AlignSeq.extractGaps("-. ",\r
322                                                 sequence.getSequenceAsString()).\r
323             toUpperCase();\r
324 \r
325         int absStart = entry.getUniprotSequence().getContent().indexOf(\r
326             nonGapped.toString());\r
327 \r
328         if (absStart == -1)\r
329         {\r
330           // Is UniprotSequence contained in dataset sequence?\r
331           absStart = nonGapped.toString().indexOf(entry.getUniprotSequence().\r
332                                                   getContent());\r
333           if (absStart == -1)\r
334           {\r
335             sbuffer.append(sequence.getName() + " SEQUENCE NOT %100 MATCH \n");\r
336             continue;\r
337           }\r
338 \r
339           if (entry.getFeature() != null)\r
340           {\r
341             Enumeration e = entry.getFeature().elements();\r
342             while (e.hasMoreElements())\r
343             {\r
344               SequenceFeature sf = (SequenceFeature) e.nextElement();\r
345               sf.setBegin(sf.getBegin() + absStart + 1);\r
346               sf.setEnd(sf.getEnd() + absStart + 1);\r
347             }\r
348 \r
349             sbuffer.append(sequence.getName() +\r
350                            " HAS " + absStart +\r
351                            " PREFIXED RESIDUES COMPARED TO UNIPROT - ANY SEQUENCE FEATURES"\r
352                            + " HAVE BEEN ADJUSTED ACCORDINGLY \n");\r
353             absStart = 0;\r
354           }\r
355 \r
356         }\r
357 \r
358         //unknownSequences.remove(sequence);\r
359 \r
360         int absEnd = absStart + nonGapped.toString().length();\r
361         absStart += 1;\r
362 \r
363         Enumeration e = entry.getDbReference().elements();\r
364         Vector onlyPdbEntries = new Vector();\r
365         while (e.hasMoreElements())\r
366         {\r
367           PDBEntry pdb = (PDBEntry) e.nextElement();\r
368           if (!pdb.getType().equals(DBRefSource.PDB))\r
369           {\r
370             DBRefEntry xref = new DBRefEntry(pdb.getType(), DBRefSource.UNIPROT, pdb.getId());\r
371             sequence.addDBRef(xref);\r
372             continue;\r
373           }\r
374           \r
375           sequence.addDBRef(new DBRefEntry(DBRefSource.PDB,\r
376                                            "0",\r
377                                            pdb.getId()));\r
378 \r
379           onlyPdbEntries.addElement(pdb);\r
380         }\r
381 \r
382         sequence.setPDBId(onlyPdbEntries);\r
383 \r
384         sequence.setStart(absStart);\r
385         sequence.setEnd(absEnd);\r
386 \r
387       }\r
388     }\r
389   }\r
390 }\r