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