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