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