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