Replaced by AnnotationFile
[jalview.git] / src / jalview / io / DBRefFetcher.java
1 /*\r
2 * Jalview - A Sequence Alignment Editor and Viewer\r
3 * Copyright (C) 2005 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 align;\r
45   AlignmentI dataset;\r
46   AlignFrame af;\r
47   ArrayList unknownSequences;\r
48   CutAndPasteTransfer output = new CutAndPasteTransfer();\r
49   StringBuffer sbuffer = new StringBuffer();\r
50   boolean uniprotFlag = false;\r
51 \r
52   public DBRefFetcher()\r
53   {}\r
54 \r
55   public Vector getUniprotEntries(File file)\r
56   {\r
57     UniprotFile uni = new UniprotFile();\r
58     try\r
59     {\r
60       // 1. Load the mapping information from the file\r
61       Mapping map = new Mapping(uni.getClass().getClassLoader());\r
62       java.net.URL url = getClass().getResource("/uniprot_mapping.xml");\r
63       map.loadMapping(url);\r
64 \r
65       // 2. Unmarshal the data\r
66       Unmarshaller unmar = new Unmarshaller(uni);\r
67       unmar.setIgnoreExtraElements(true);\r
68       unmar.setMapping(map);\r
69    //   unmar.setDebug(true);\r
70 \r
71       uni = (UniprotFile) unmar.unmarshal(new FileReader(file));\r
72     }\r
73     catch (Exception e)\r
74     {\r
75       System.out.println("Error getUniprotEntries() "+e);\r
76     }\r
77 \r
78 \r
79     return uni.getUniprotEntries();\r
80   }\r
81 \r
82   /**\r
83    * Creates a new SequenceFeatureFetcher object.\r
84    *\r
85    * @param align DOCUMENT ME!\r
86    * @param ap DOCUMENT ME!\r
87    */\r
88   public DBRefFetcher(AlignmentI align, AlignFrame af)\r
89   {\r
90     this.af = af;\r
91     unknownSequences = new ArrayList();\r
92     this.align = align;\r
93     this.dataset = align.getDataset();\r
94 \r
95     Thread thread = new Thread(this);\r
96     thread.start();\r
97   }\r
98 \r
99   /**\r
100    * DOCUMENT ME!\r
101    */\r
102   public void run()\r
103   {\r
104     long startTime = System.currentTimeMillis();\r
105     af.setProgressBar("Fetching db refs", startTime);\r
106 \r
107     try\r
108     {\r
109       int seqIndex = 0;\r
110       Vector sequences = dataset.getSequences();\r
111 \r
112       while (seqIndex < sequences.size())\r
113       {\r
114         Vector ids = new Vector();\r
115 \r
116         for (int i = 0; (seqIndex < sequences.size()) && (i < 50);\r
117              seqIndex++, i++)\r
118         {\r
119           Sequence sequence = (Sequence) sequences.get(seqIndex);\r
120           Vector uprefs = jalview.util.DBRefUtils.selectRefs(sequence.getDBRef(), new String[] {\r
121               jalview.datamodel.DBRefSource.UNIPROT});\r
122           if (uprefs!=null)\r
123           {\r
124             // we know the id for this entry, so don't note its ID in the unknownSequences list\r
125             for (int j=0,k=uprefs.size(); j<k; j++)\r
126               ids.add(((DBRefEntry) uprefs.get(j)).getAccessionId());\r
127             unknownSequences.add(sequence);\r
128           } else {\r
129             if (!ids.contains(sequence.getName()))\r
130             {\r
131               ids.add(sequence.getName());\r
132               unknownSequences.add(sequence);\r
133             }\r
134           }\r
135         }\r
136 \r
137         ///////////////////////////////////\r
138         ///READ FROM EBI\r
139         if (ids.size() > 0)\r
140         {\r
141           StringBuffer remainingIds = new StringBuffer("uniprot:");\r
142           for (int i = 0; i < ids.size(); i++)\r
143            {\r
144              if(ids.get(i).toString().indexOf("|")>-1)\r
145              {\r
146                remainingIds.append(ids.get(i).toString().substring(\r
147                    ids.get(i).toString().lastIndexOf("|") + 1));\r
148                uniprotFlag = true;\r
149              }\r
150              else\r
151                remainingIds.append(ids.get(i));\r
152 \r
153              remainingIds.append(";");\r
154            }\r
155 \r
156           EBIFetchClient ebi = new EBIFetchClient();\r
157           File file = ebi.fetchDataAsFile(remainingIds.toString(),\r
158                                           "xml", "raw");\r
159 \r
160 \r
161 \r
162           if (file != null)\r
163           {\r
164             ReadUniprotFile(file, ids);\r
165           }\r
166         }\r
167       }\r
168     }\r
169     catch (Exception ex)\r
170     {\r
171       ex.printStackTrace();\r
172     }\r
173 \r
174     if (sbuffer.length() > 0)\r
175     {\r
176       output.setText(\r
177           "Your sequences have been matched to Uniprot. Some of the ids have been\n" +\r
178           "altered, most likely the start/end residue will have been updated.\n" +\r
179           "Save your alignment to maintain the updated id.\n\n" +\r
180           sbuffer.toString());\r
181       Desktop.addInternalFrame(output, "Sequence names updated ", 600, 300);\r
182       // The above is the dataset, we must now find out the index\r
183       // of the viewed sequence\r
184 \r
185     }\r
186 \r
187     af.setProgressBar("DBRef search completed", startTime);\r
188    // promptBeforeBlast();\r
189 \r
190   }\r
191 \r
192 \r
193   void promptBeforeBlast()\r
194    {\r
195      // This must be outside the run() body as java 1.5\r
196      // will not return any value from the OptionPane to the expired thread.\r
197       if (unknownSequences.size() > 0)\r
198       {\r
199        // int reply = javax.swing.JOptionPane.showConfirmDialog(\r
200        //     Desktop.desktop, "Couldn't find a match for "+unknownSequences.size()+" sequences."\r
201         //        +"\nPerform blast for unknown sequences?",\r
202         //            "Blast for Unidentified Sequences",\r
203         //             javax.swing.JOptionPane.YES_NO_OPTION, javax.swing.JOptionPane.QUESTION_MESSAGE);\r
204      javax.swing.JOptionPane.showMessageDialog(\r
205     Desktop.desktop, "Couldn't find a match for "+unknownSequences.size()+" sequences.",\r
206             "Unidentified Sequences",\r
207              javax.swing.JOptionPane.WARNING_MESSAGE);\r
208 \r
209 \r
210       //  if(reply == javax.swing.JOptionPane.YES_OPTION)\r
211      //    new WSWUBlastClient(ap, align, unknownSequences);\r
212       }\r
213   }\r
214 \r
215   /**\r
216    * DOCUMENT ME!\r
217    *\r
218    * @param result DOCUMENT ME!\r
219    * @param out DOCUMENT ME!\r
220    * @param align DOCUMENT ME!\r
221    */\r
222   void ReadUniprotFile(File file, Vector ids)\r
223   {\r
224     if(!file.exists())\r
225       return;\r
226 \r
227     SequenceI sequence = null;\r
228 \r
229     Vector entries = getUniprotEntries(file);\r
230 \r
231     int i, iSize = entries==null?0:entries.size();\r
232     UniprotEntry entry;\r
233     for (i = 0; i < iSize; i++)\r
234     {\r
235       entry = (UniprotEntry) entries.elementAt(i);\r
236       String idmatch = entry.getAccession().elementAt(0).toString();\r
237       sequence = dataset.findName(idmatch);\r
238 \r
239       if (sequence == null)\r
240       {\r
241         //Sequence maybe Name, not Accession\r
242         idmatch = entry.getName().elementAt(0).toString();\r
243         sequence = dataset.findName(idmatch);\r
244       }\r
245 \r
246       if(sequence!=null)\r
247         ids.remove(sequence.getName());\r
248 \r
249       else  if (sequence == null && uniprotFlag)\r
250       {\r
251           StringBuffer upid = new StringBuffer("UniProt/Swiss-Prot|");\r
252           for(int u=0; u<entry.getAccession().size(); u++)\r
253             upid.append(entry.getAccession().elementAt(u)+"|");\r
254 \r
255           sequence = dataset.findName(upid+idmatch);\r
256           ids.remove(idmatch);\r
257       }\r
258 \r
259       if(sequence ==null)\r
260       {\r
261         System.out.println(idmatch+" not found");\r
262         continue;\r
263       }\r
264 \r
265 \r
266       sequence.addDBRef(new DBRefEntry(DBRefSource.UNIPROT,\r
267                                        "1.0",\r
268                                        entry.getAccession().elementAt(0).toString()));\r
269 \r
270       System.out.println("Adding dbref to "+sequence.getName()+" : "+\r
271                          entry.getAccession().elementAt(0).toString());\r
272 \r
273       String nonGapped = AlignSeq.extractGaps("-. ", sequence.getSequence());\r
274 \r
275       int absStart = entry.getUniprotSequence().getContent().indexOf(\r
276           nonGapped.toString());\r
277 \r
278       if (absStart == -1)\r
279       {\r
280         // Is UniprotSequence contained in dataset sequence?\r
281         absStart = nonGapped.toString().indexOf(entry.getUniprotSequence().getContent());\r
282         if(absStart == -1)\r
283         {\r
284           sbuffer.append(sequence.getName() +\r
285                          " SEQUENCE NOT %100 MATCH \n");\r
286 \r
287           continue;\r
288         }\r
289         else\r
290         {\r
291 \r
292           if(entry.getFeature()!=null)\r
293           {\r
294             Enumeration e = entry.getFeature().elements();\r
295             while (e.hasMoreElements())\r
296             {\r
297               SequenceFeature sf = (SequenceFeature) e.nextElement();\r
298               sf.setBegin(sf.getBegin() + absStart + 1);\r
299               sf.setEnd(sf.getEnd() + absStart + 1);\r
300             }\r
301           }\r
302 \r
303           sbuffer.append(sequence.getName() +\r
304                          " HAS "+absStart+" PREFIXED RESIDUES COMPARED TO UNIPROT - ANY SEQUENCE FEATURES"\r
305                         +" HAVE BEEN ADJUSTED ACCORDINGLY \n");\r
306           absStart = 0;\r
307         }\r
308 \r
309       }\r
310 \r
311       unknownSequences.remove(sequence);\r
312 \r
313       int absEnd = absStart + nonGapped.toString().length();\r
314       absStart += 1;\r
315 \r
316       Enumeration e = entry.getDbReference().elements();\r
317       Vector onlyPdbEntries = new Vector();\r
318       while(e.hasMoreElements())\r
319       {\r
320         PDBEntry pdb = (PDBEntry)e.nextElement();\r
321         if(!pdb.getType().equals("PDB"))\r
322           continue;\r
323 \r
324         onlyPdbEntries.addElement(pdb);\r
325       }\r
326 \r
327       sequence.setPDBId(onlyPdbEntries);\r
328 \r
329       if (entry.getFeature()!=null) {\r
330         //e = entry.getFeature().elements();\r
331       //  while (e.hasMoreElements())\r
332         {\r
333         //  SequenceFeature sf = (SequenceFeature) e.nextElement();\r
334          // sf.setFeatureGroup("Uniprot");\r
335         //  sequence.addSequenceFeature( sf );\r
336         }\r
337       }\r
338       sequence.setStart(absStart);\r
339       sequence.setEnd(absEnd);\r
340 \r
341 \r
342       int n = 0;\r
343       SequenceI seq2;\r
344       while (n < align.getHeight())\r
345       {\r
346         //This loop enables multiple sequences with the same\r
347         //id to have features added and seq limits updated\r
348         seq2 = align.getSequenceAt(n);\r
349         if (seq2.getName().equals(idmatch))\r
350         {\r
351           nonGapped = AlignSeq.extractGaps("-. ", seq2.getSequence());\r
352 \r
353           absStart = sequence.getSequence().indexOf(nonGapped);\r
354           absEnd = absStart + nonGapped.toString().length() - 1;\r
355 \r
356           // This is the Viewd alignment sequences\r
357           // No need to tell the user of the dataset updates\r
358           if ( (seq2.getStart() != absStart+sequence.getStart())\r
359              || (seq2.getEnd() != absEnd+sequence.getStart()))\r
360           {\r
361             sbuffer.append("Updated: " + seq2.getName() + " " +\r
362                            seq2.getStart() + "/" + seq2.getEnd() +\r
363                            "  to  " + (absStart + sequence.getStart()) + "/" +\r
364                            (absEnd + sequence.getStart()) + "\n");\r
365 \r
366             seq2.setStart(absStart + sequence.getStart());\r
367             seq2.setEnd(absEnd + sequence.getStart());\r
368           }\r
369         }\r
370 \r
371         n++;\r
372       }\r
373     }\r
374   }\r
375 }\r
376 \r
377 \r