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