6e4491059267415a949777d7c87eec82235ab77d
[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              remainingIds.append(ids.get(i) + ";");\r
151            }\r
152           EBIFetchClient ebi = new EBIFetchClient();\r
153           File file = ebi.fetchDataAsFile(remainingIds.toString(),\r
154                                           "xml", "raw");\r
155 \r
156 \r
157 \r
158           if (file != null)\r
159           {\r
160             ReadUniprotFile(file, ids);\r
161           }\r
162         }\r
163       }\r
164     }\r
165     catch (Exception ex)\r
166     {\r
167       ex.printStackTrace();\r
168     }\r
169 \r
170     if (sbuffer.length() > 0)\r
171     {\r
172       output.setText(\r
173           "Your sequences have been matched to Uniprot. Some of the ids have been\n" +\r
174           "altered, most likely the start/end residue will have been updated.\n" +\r
175           "Save your alignment to maintain the updated id.\n\n" +\r
176           sbuffer.toString());\r
177       Desktop.addInternalFrame(output, "Sequence names updated ", 600, 300);\r
178       // The above is the dataset, we must now find out the index\r
179       // of the viewed sequence\r
180 \r
181     }\r
182 \r
183     af.setProgressBar("DBRef search completed", startTime);\r
184    // promptBeforeBlast();\r
185 \r
186   }\r
187 \r
188 \r
189   void promptBeforeBlast()\r
190    {\r
191      // This must be outside the run() body as java 1.5\r
192      // will not return any value from the OptionPane to the expired thread.\r
193       if (unknownSequences.size() > 0)\r
194       {\r
195        // int reply = javax.swing.JOptionPane.showConfirmDialog(\r
196        //     Desktop.desktop, "Couldn't find a match for "+unknownSequences.size()+" sequences."\r
197         //        +"\nPerform blast for unknown sequences?",\r
198         //            "Blast for Unidentified Sequences",\r
199         //             javax.swing.JOptionPane.YES_NO_OPTION, javax.swing.JOptionPane.QUESTION_MESSAGE);\r
200      javax.swing.JOptionPane.showMessageDialog(\r
201     Desktop.desktop, "Couldn't find a match for "+unknownSequences.size()+" sequences.",\r
202             "Unidentified Sequences",\r
203              javax.swing.JOptionPane.WARNING_MESSAGE);\r
204 \r
205 \r
206       //  if(reply == javax.swing.JOptionPane.YES_OPTION)\r
207      //    new WSWUBlastClient(ap, align, unknownSequences);\r
208       }\r
209   }\r
210 \r
211   /**\r
212    * DOCUMENT ME!\r
213    *\r
214    * @param result DOCUMENT ME!\r
215    * @param out DOCUMENT ME!\r
216    * @param align DOCUMENT ME!\r
217    */\r
218   void ReadUniprotFile(File file, Vector ids)\r
219   {\r
220     if(!file.exists())\r
221       return;\r
222 \r
223     SequenceI sequence = null;\r
224 \r
225     Vector entries = getUniprotEntries(file);\r
226 \r
227     int i, iSize = entries==null?0:entries.size();\r
228     UniprotEntry entry;\r
229     for (i = 0; i < iSize; i++)\r
230     {\r
231       entry = (UniprotEntry) entries.elementAt(i);\r
232       String idmatch = entry.getAccession().elementAt(0).toString();\r
233       sequence = dataset.findName(idmatch);\r
234 \r
235       if (sequence == null)\r
236       {\r
237         //Sequence maybe Name, not Accession\r
238         idmatch = entry.getName().elementAt(0).toString();\r
239         sequence = dataset.findName(idmatch);\r
240       }\r
241 \r
242       if(sequence!=null)\r
243         ids.remove(sequence.getName());\r
244 \r
245       else  if (sequence == null && uniprotFlag)\r
246       {\r
247           sequence = dataset.findName("UniProt/Swiss-Prot|"+entry.getAccession().elementAt(0)+"|"+idmatch);\r
248           ids.remove(idmatch);\r
249       }\r
250 \r
251       if(sequence ==null)\r
252       {\r
253         System.out.println(idmatch+" not found");\r
254         continue;\r
255       }\r
256 \r
257 \r
258       sequence.addDBRef(new DBRefEntry(DBRefSource.UNIPROT,\r
259                                        "1.0",\r
260                                        entry.getAccession().elementAt(0).toString()));\r
261 \r
262       System.out.println("Adding dbref to "+sequence.getName()+" : "+\r
263                          entry.getAccession().elementAt(0).toString());\r
264 \r
265       String nonGapped = AlignSeq.extractGaps("-. ", sequence.getSequence());\r
266 \r
267       int absStart = entry.getUniprotSequence().getContent().indexOf(\r
268           nonGapped.toString());\r
269 \r
270       if (absStart == -1)\r
271       {\r
272         // Is UniprotSequence contained in dataset sequence?\r
273         absStart = nonGapped.toString().indexOf(entry.getUniprotSequence().getContent());\r
274         if(absStart == -1)\r
275         {\r
276           sbuffer.append(sequence.getName() +\r
277                          " SEQUENCE NOT %100 MATCH \n");\r
278 \r
279           continue;\r
280         }\r
281         else\r
282         {\r
283 \r
284           if(entry.getFeature()!=null)\r
285           {\r
286             Enumeration e = entry.getFeature().elements();\r
287             while (e.hasMoreElements())\r
288             {\r
289               SequenceFeature sf = (SequenceFeature) e.nextElement();\r
290               sf.setBegin(sf.getBegin() + absStart + 1);\r
291               sf.setEnd(sf.getEnd() + absStart + 1);\r
292             }\r
293           }\r
294 \r
295           sbuffer.append(sequence.getName() +\r
296                          " HAS "+absStart+" PREFIXED RESIDUES COMPARED TO UNIPROT - ANY SEQUENCE FEATURES"\r
297                         +" HAVE BEEN ADJUSTED ACCORDINGLY \n");\r
298           absStart = 0;\r
299         }\r
300 \r
301       }\r
302 \r
303       unknownSequences.remove(sequence);\r
304 \r
305       int absEnd = absStart + nonGapped.toString().length();\r
306       absStart += 1;\r
307 \r
308       Enumeration e = entry.getDbReference().elements();\r
309       Vector onlyPdbEntries = new Vector();\r
310       while(e.hasMoreElements())\r
311       {\r
312         PDBEntry pdb = (PDBEntry)e.nextElement();\r
313         if(!pdb.getType().equals("PDB"))\r
314           continue;\r
315 \r
316         onlyPdbEntries.addElement(pdb);\r
317       }\r
318 \r
319       sequence.setPDBId(onlyPdbEntries);\r
320 \r
321       if (entry.getFeature()!=null) {\r
322         //e = entry.getFeature().elements();\r
323       //  while (e.hasMoreElements())\r
324         {\r
325         //  SequenceFeature sf = (SequenceFeature) e.nextElement();\r
326          // sf.setFeatureGroup("Uniprot");\r
327         //  sequence.addSequenceFeature( sf );\r
328         }\r
329       }\r
330       sequence.setStart(absStart);\r
331       sequence.setEnd(absEnd);\r
332 \r
333 \r
334       int n = 0;\r
335       SequenceI seq2;\r
336       while (n < align.getHeight())\r
337       {\r
338         //This loop enables multiple sequences with the same\r
339         //id to have features added and seq limits updated\r
340         seq2 = align.getSequenceAt(n);\r
341         if (seq2.getName().equals(idmatch))\r
342         {\r
343           nonGapped = AlignSeq.extractGaps("-. ", seq2.getSequence());\r
344 \r
345           absStart = sequence.getSequence().indexOf(nonGapped);\r
346           absEnd = absStart + nonGapped.toString().length() - 1;\r
347 \r
348           // This is the Viewd alignment sequences\r
349           // No need to tell the user of the dataset updates\r
350           if ( (seq2.getStart() != absStart+sequence.getStart())\r
351              || (seq2.getEnd() != absEnd+sequence.getStart()))\r
352           {\r
353             sbuffer.append("Updated: " + seq2.getName() + " " +\r
354                            seq2.getStart() + "/" + seq2.getEnd() +\r
355                            "  to  " + (absStart + sequence.getStart()) + "/" +\r
356                            (absEnd + sequence.getStart()) + "\n");\r
357 \r
358             seq2.setStart(absStart + sequence.getStart());\r
359             seq2.setEnd(absEnd + sequence.getStart());\r
360           }\r
361         }\r
362 \r
363         n++;\r
364       }\r
365     }\r
366   }\r
367 }\r
368 \r
369 \r