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