AnnotationId is hashcode of object
[jalview.git] / src / jalview / io / DBRefFetcher.java
1 /*\r
2 * Jalview - A Sequence Alignment Editor and Viewer\r
3 * Copyright (C) 2006 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 jalview.datamodel.*;\r
22 \r
23 import jalview.gui.*;\r
24 \r
25 import java.io.*;\r
26 \r
27 import java.util.*;\r
28 \r
29 import org.exolab.castor.mapping.Mapping;\r
30 \r
31 import org.exolab.castor.xml.*;\r
32 import jalview.analysis.AlignSeq;\r
33 \r
34 \r
35 \r
36 /**\r
37  * DOCUMENT ME!\r
38  *\r
39  * @author $author$\r
40  * @version $Revision$\r
41  */\r
42 public class DBRefFetcher implements Runnable\r
43 {\r
44   AlignmentI dataset;\r
45   AlignFrame af;\r
46   CutAndPasteTransfer output = new CutAndPasteTransfer();\r
47   StringBuffer sbuffer = new StringBuffer();\r
48   boolean running = false;\r
49 \r
50   ///This will be a collection of Vectors of sequenceI refs.\r
51   //The key will be the seq name or accession id of the seq\r
52   Hashtable seqRefs;\r
53 \r
54   public DBRefFetcher()\r
55   {}\r
56 \r
57   public Vector getUniprotEntries(File file)\r
58   {\r
59     UniprotFile uni = new UniprotFile();\r
60     try\r
61     {\r
62       // 1. Load the mapping information from the file\r
63       Mapping map = new Mapping(uni.getClass().getClassLoader());\r
64       java.net.URL url = getClass().getResource("/uniprot_mapping.xml");\r
65       map.loadMapping(url);\r
66 \r
67       // 2. Unmarshal the data\r
68       Unmarshaller unmar = new Unmarshaller(uni);\r
69       unmar.setIgnoreExtraElements(true);\r
70       unmar.setMapping(map);\r
71 \r
72       uni = (UniprotFile) unmar.unmarshal(new FileReader(file));\r
73     }\r
74     catch (Exception e)\r
75     {\r
76       System.out.println("Error getUniprotEntries() "+e);\r
77     }\r
78 \r
79 \r
80     return uni.getUniprotEntries();\r
81   }\r
82 \r
83   /**\r
84    * Creates a new SequenceFeatureFetcher object.\r
85    *\r
86    * @param align DOCUMENT ME!\r
87    * @param ap DOCUMENT ME!\r
88    */\r
89   public DBRefFetcher(AlignmentI align, AlignFrame af)\r
90   {\r
91     this.af = af;\r
92     this.dataset = align.getDataset();\r
93   }\r
94 \r
95   public boolean fetchDBRefs(boolean waitTillFinished)\r
96   {\r
97     Thread thread = new Thread(this);\r
98     thread.start();\r
99     running = true;\r
100 \r
101     if(waitTillFinished)\r
102     {\r
103       while(running)\r
104       {\r
105         try{\r
106           Thread.sleep(500);\r
107         }catch(Exception ex){}\r
108       }\r
109     }\r
110 \r
111     return true;\r
112   }\r
113 \r
114   /**\r
115    * The sequence will be added to a vector of sequences\r
116    * belonging to key which could be either seq name or dbref id\r
117    * @param seq SequenceI\r
118    * @param key String\r
119    */\r
120   void addSeqId(SequenceI seq, String key)\r
121   {\r
122     key = key.toUpperCase();\r
123 \r
124     Vector seqs;\r
125     if(seqRefs.containsKey(key))\r
126     {\r
127       seqs = (Vector)seqRefs.get(key);\r
128 \r
129       if(seqs!=null && !seqs.contains(seq))\r
130       {\r
131         seqs.addElement(seq);\r
132       }\r
133       else if(seqs==null)\r
134       {\r
135         seqs = new Vector();\r
136         seqs.addElement(seq);\r
137       }\r
138 \r
139     }\r
140     else\r
141     {\r
142       seqs = new Vector();\r
143       seqs.addElement(seq);\r
144     }\r
145 \r
146     seqRefs.put(key, seqs);\r
147   }\r
148 \r
149 \r
150   /**\r
151    * DOCUMENT ME!\r
152    */\r
153   public void run()\r
154   {\r
155     long startTime = System.currentTimeMillis();\r
156     af.setProgressBar("Fetching db refs", startTime);\r
157     running = true;\r
158 \r
159     seqRefs = new Hashtable();\r
160 \r
161     try\r
162     {\r
163       int seqIndex = 0;\r
164       Vector sequences = dataset.getSequences();\r
165 \r
166       while (seqIndex < sequences.size())\r
167       {\r
168         StringBuffer queryString = new StringBuffer("uniprot:");\r
169 \r
170         for (int i = 0; (seqIndex < sequences.size()) && (i < 50);\r
171              seqIndex++, i++)\r
172         {\r
173           Sequence sequence = (Sequence) sequences.get(seqIndex);\r
174           DBRefEntry [] uprefs = jalview.util.DBRefUtils.selectRefs(sequence.getDBRef(), new String[] {\r
175               jalview.datamodel.DBRefSource.UNIPROT});\r
176           if (uprefs!=null)\r
177           {\r
178             if(uprefs.length+i>50)\r
179               break;\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   /**\r
244    * DOCUMENT ME!\r
245    *\r
246    * @param result DOCUMENT ME!\r
247    * @param out DOCUMENT ME!\r
248    * @param align DOCUMENT ME!\r
249    */\r
250   void ReadUniprotFile(File file)\r
251   {\r
252     if (!file.exists())\r
253       return;\r
254 \r
255     SequenceI sequence = null;\r
256 \r
257     Vector entries = getUniprotEntries(file);\r
258 \r
259     int i, iSize = entries == null ? 0 : entries.size();\r
260     UniprotEntry entry;\r
261     for (i = 0; i < iSize; i++)\r
262     {\r
263       entry = (UniprotEntry) entries.elementAt(i);\r
264 \r
265       //Work out which sequences this Uniprot file has matches to,\r
266       //taking into account all accessionIds and names in the file\r
267       Vector sequenceMatches = new Vector();\r
268       for (int j = 0; j < entry.getAccession().size(); j++)\r
269       {\r
270         String accessionId = entry.getAccession().elementAt(j).toString();\r
271         if (seqRefs.containsKey(accessionId))\r
272         {\r
273           Vector seqs = (Vector) seqRefs.get(accessionId);\r
274           for (int jj = 0; jj < seqs.size(); jj++)\r
275           {\r
276             sequence = (SequenceI) seqs.elementAt(jj);\r
277             if (!sequenceMatches.contains(sequence))\r
278               sequenceMatches.addElement(sequence);\r
279           }\r
280         }\r
281       }\r
282       for (int j = 0; j < entry.getName().size(); j++)\r
283       {\r
284         String name = entry.getName().elementAt(j).toString();\r
285         if (seqRefs.containsKey(name))\r
286         {\r
287           Vector seqs = (Vector) seqRefs.get(name);\r
288           for (int jj = 0; jj < seqs.size(); jj++)\r
289           {\r
290             sequence = (SequenceI) seqs.elementAt(jj);\r
291             if (!sequenceMatches.contains(sequence))\r
292               sequenceMatches.addElement(sequence);\r
293           }\r
294         }\r
295       }\r
296 \r
297       for (int m = 0; m < sequenceMatches.size(); m++)\r
298       {\r
299         sequence = (SequenceI) sequenceMatches.elementAt(m);\r
300         sequence.addDBRef(new DBRefEntry(DBRefSource.UNIPROT,\r
301                                          "0",\r
302                                          entry.getAccession().elementAt(0).\r
303                                          toString()));\r
304 \r
305         System.out.println("Adding dbref to " + sequence.getName() + " : " +\r
306                            entry.getAccession().elementAt(0).toString());\r
307 \r
308         String nonGapped = AlignSeq.extractGaps("-. ",\r
309                                                 sequence.getSequenceAsString()).\r
310             toUpperCase();\r
311 \r
312         int absStart = entry.getUniprotSequence().getContent().indexOf(\r
313             nonGapped.toString());\r
314 \r
315         if (absStart == -1)\r
316         {\r
317           // Is UniprotSequence contained in dataset sequence?\r
318           absStart = nonGapped.toString().indexOf(entry.getUniprotSequence().\r
319                                                   getContent());\r
320           if (absStart == -1)\r
321           {\r
322             sbuffer.append(sequence.getName() + " SEQUENCE NOT %100 MATCH \n");\r
323             continue;\r
324           }\r
325 \r
326           if (entry.getFeature() != null)\r
327           {\r
328             Enumeration e = entry.getFeature().elements();\r
329             while (e.hasMoreElements())\r
330             {\r
331               SequenceFeature sf = (SequenceFeature) e.nextElement();\r
332               sf.setBegin(sf.getBegin() + absStart + 1);\r
333               sf.setEnd(sf.getEnd() + absStart + 1);\r
334             }\r
335 \r
336             sbuffer.append(sequence.getName() +\r
337                            " HAS " + absStart +\r
338                            " PREFIXED RESIDUES COMPARED TO UNIPROT - ANY SEQUENCE FEATURES"\r
339                            + " HAVE BEEN ADJUSTED ACCORDINGLY \n");\r
340             absStart = 0;\r
341           }\r
342 \r
343         }\r
344 \r
345         //unknownSequences.remove(sequence);\r
346 \r
347         int absEnd = absStart + nonGapped.toString().length();\r
348         absStart += 1;\r
349 \r
350         Enumeration e = entry.getDbReference().elements();\r
351         Vector onlyPdbEntries = new Vector();\r
352         while (e.hasMoreElements())\r
353         {\r
354           PDBEntry pdb = (PDBEntry) e.nextElement();\r
355           if (!pdb.getType().equals(DBRefSource.PDB))\r
356             continue;\r
357 \r
358           sequence.addDBRef(new DBRefEntry(DBRefSource.PDB,\r
359                                            "0",\r
360                                            pdb.getId()));\r
361 \r
362           onlyPdbEntries.addElement(pdb);\r
363         }\r
364 \r
365         sequence.setPDBId(onlyPdbEntries);\r
366 \r
367         sequence.setStart(absStart);\r
368         sequence.setEnd(absEnd);\r
369 \r
370       }\r
371     }\r
372   }\r
373 }\r
374 \r
375 \r