apply gpl development license
[jalview.git] / src / jalview / io / WSWUBlastClient.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Development Version 2.4.1)
3  * Copyright (C) 2009 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
4  * 
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  * 
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  * 
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
18  */
19 package jalview.io;
20
21 import java.util.*;
22
23 import javax.swing.*;
24
25 import jalview.analysis.*;
26 import jalview.datamodel.*;
27 import jalview.gui.*;
28 import uk.ac.ebi.www.*;
29
30 /**
31  * DOCUMENT ME!
32  * 
33  * @author $author$
34  * @version $Revision$
35  */
36 public class WSWUBlastClient
37 {
38   AlignmentPanel ap;
39
40   AlignmentI al;
41
42   CutAndPasteTransfer output = new CutAndPasteTransfer();
43
44   int jobsRunning = 0;
45
46   Vector suggestedIds = new Vector();
47
48   /**
49    * Creates a new WSWUBlastClient object.
50    * 
51    * @param al
52    *                DOCUMENT ME!
53    * @param ids
54    *                DOCUMENT ME!
55    */
56   public WSWUBlastClient(AlignmentPanel ap, AlignmentI al, ArrayList ids)
57   {
58     this.ap = ap;
59     this.al = al;
60     output
61             .setText("To display sequence features an exact Uniprot id with 100% sequence identity match must be entered."
62                     + "\nIn order to display these features, try changing the names of your sequences to the ids suggested below."
63                     + "\n\nRunning WSWUBlast at EBI."
64                     + "\nPlease quote Pillai S., Silventoinen V., Kallio K., Senger M., Sobhany S., Tate J., Velankar S., Golovin A., Henrick K., Rice P., Stoehr P., Lopez R."
65                     + "\nSOAP-based services provided by the European Bioinformatics Institute."
66                     + "\nNucleic Acids Res. 33(1):W25-W28 (2005));");
67
68     Desktop.addInternalFrame(output,
69             "BLASTing for unidentified sequences ", 800, 300);
70
71     for (int i = 0; i < ids.size(); i++)
72     {
73       Sequence sequence = (Sequence) ids.get(i);
74       System.out.println(sequence.getName());
75
76       BlastThread thread = new BlastThread(sequence);
77       thread.start();
78       jobsRunning++;
79     }
80
81     ImageTwirler thread = new ImageTwirler();
82     thread.start();
83   }
84
85   /**
86    * DOCUMENT ME!
87    * 
88    * @param id1
89    *                DOCUMENT ME!
90    * @param res
91    *                DOCUMENT ME!
92    */
93   void parseResult(Sequence seq, String res)
94   {
95     StringTokenizer st = new StringTokenizer(res, "\n");
96     String data;
97     String id2;
98     int maxFound = 90;
99     StringBuffer buffer = new StringBuffer("\n\n" + seq.getName() + " :");
100
101     while (st.hasMoreTokens())
102     {
103       data = st.nextToken();
104
105       if (data.indexOf(">UNIPROT") > -1)
106       {
107         int index = data.indexOf(">UNIPROT") + 9;
108         id2 = data.substring(index, data.indexOf(" ", index));
109
110         boolean identitiesFound = false;
111         while (!identitiesFound)
112         {
113           data = st.nextToken();
114
115           if (data.indexOf("Identities") > -1)
116           {
117             identitiesFound = true;
118
119             int value = Integer.parseInt(data.substring(
120                     data.indexOf("(") + 1, data.indexOf("%")));
121
122             if (value >= maxFound)
123             {
124               maxFound = value;
125               buffer.append(" " + id2 + " " + value + "%; ");
126               suggestedIds.addElement(new Object[]
127               { seq, id2 });
128             }
129           }
130         }
131       }
132     }
133
134     output.appendText(buffer.toString());
135   }
136
137   void updateIds()
138   {
139     // This must be outside the run() body as java 1.5
140     // will not return any value from the OptionPane to the expired thread.
141     int reply = JOptionPane.showConfirmDialog(Desktop.desktop,
142             "Automatically update suggested ids?",
143             "Auto replace sequence ids", JOptionPane.YES_NO_OPTION);
144
145     if (reply == JOptionPane.YES_OPTION)
146     {
147       Enumeration keys = suggestedIds.elements();
148       while (keys.hasMoreElements())
149       {
150         Object[] object = (Object[]) keys.nextElement();
151
152         Sequence oldseq = (Sequence) object[0];
153
154         oldseq.setName(object[1].toString());
155
156         // Oldseq is actually in the dataset, we must find the
157         // Visible seq and change its name also.
158         for (int i = 0; i < al.getHeight(); i++)
159         {
160           if (al.getSequenceAt(i).getDatasetSequence() == oldseq)
161           {
162             al.getSequenceAt(i).setName(oldseq.getName());
163             break;
164           }
165         }
166
167         DBRefEntry[] entries = oldseq.getDBRef();
168         if (entries != null)
169         {
170           oldseq.addDBRef(new jalview.datamodel.DBRefEntry(
171                   jalview.datamodel.DBRefSource.UNIPROT, "0", entries[0]
172                           .getAccessionId()));
173         }
174       }
175     }
176     ap.paintAlignment(true);
177
178   }
179
180   class ImageTwirler extends Thread
181   {
182     ImageIcon[] imageIcon;
183
184     int imageIndex = 0;
185
186     public ImageTwirler()
187     {
188       imageIcon = new ImageIcon[9];
189
190       for (int i = 0; i < 9; i++)
191       {
192         java.net.URL url = getClass().getResource(
193                 "/images/dna" + (i + 1) + ".gif");
194
195         if (url != null)
196         {
197           imageIcon[i] = new ImageIcon(url);
198         }
199       }
200     }
201
202     public void run()
203     {
204       while (jobsRunning > 0)
205       {
206         try
207         {
208           Thread.sleep(100);
209           imageIndex++;
210           imageIndex %= 9;
211           output.setFrameIcon(imageIcon[imageIndex]);
212           output.setTitle("BLASTing for unidentified sequences - "
213                   + jobsRunning + " jobs running.");
214         } catch (Exception ex)
215         {
216         }
217       }
218
219       if (jobsRunning == 0)
220       {
221         updateIds();
222       }
223     }
224   }
225
226   class BlastThread extends Thread
227   {
228     Sequence sequence;
229
230     String jobid;
231
232     boolean jobComplete = false;
233
234     BlastThread(Sequence sequence)
235     {
236       System.out.println("blasting for: " + sequence.getName());
237       this.sequence = sequence;
238     }
239
240     public void run()
241     {
242       StartJob();
243
244       while (!jobComplete)
245       {
246         try
247         {
248           WSWUBlastService service = new WSWUBlastServiceLocator();
249           WSWUBlast wublast = service.getWSWUBlast();
250           WSFile[] results = wublast.getResults(jobid);
251
252           if (results != null)
253           {
254             String result = new String(wublast.poll(jobid, "tooloutput"));
255             parseResult(sequence, result);
256             jobComplete = true;
257             jobsRunning--;
258           }
259           else
260           {
261             Thread.sleep(10000);
262             System.out.println("WSWuBlastClient: I'm alive "
263                     + sequence.getName() + " " + jobid); // log.debug
264           }
265         } catch (Exception ex)
266         {
267         }
268       }
269     }
270
271     void StartJob()
272     {
273       InputParams params = new InputParams();
274
275       params.setProgram("blastp");
276       params.setDatabase("uniprot");
277       params.setMatrix("pam10");
278
279       params.setNumal(5);
280       params.setSensitivity("low");
281       params.setSort("totalscore");
282       params.setOutformat("txt");
283       params.setAsync(true);
284
285       try
286       {
287         Data inputs[] = new Data[1];
288         Data input = new Data();
289         input.setType("sequence");
290         input.setContent(AlignSeq.extractGaps("-. ", sequence
291                 .getSequenceAsString()));
292         inputs[0] = input;
293
294         WSWUBlastService service = new WSWUBlastServiceLocator();
295         WSWUBlast wublast = service.getWSWUBlast();
296         jobid = wublast.runWUBlast(params, inputs);
297       } catch (Exception exp)
298       {
299         jobComplete = true;
300         jobsRunning--;
301         System.err.println("WSWUBlastClient error:\n" + exp.toString());
302         exp.printStackTrace();
303       }
304     }
305   }
306 }