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