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