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