JAL-1432 updated copyright notices
[jalview.git] / src / jalview / io / WSWUBlastClient.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.0b1)
3  * Copyright (C) 2014 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 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  * The Jalview Authors are detailed in the 'AUTHORS' file.
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.setText("To display sequence features an exact Uniprot id with 100% sequence identity match must be entered."
61             + "\nIn order to display these features, try changing the names of your sequences to the ids suggested below."
62             + "\n\nRunning WSWUBlast at EBI."
63             + "\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."
64             + "\nSOAP-based services provided by the European Bioinformatics Institute."
65             + "\nNucleic Acids Res. 33(1):W25-W28 (2005));");
66
67     Desktop.addInternalFrame(output,
68             "BLASTing for unidentified sequences ", 800, 300);
69
70     for (int i = 0; i < ids.size(); i++)
71     {
72       Sequence sequence = (Sequence) ids.get(i);
73       System.out.println(sequence.getName());
74
75       BlastThread thread = new BlastThread(sequence);
76       thread.start();
77       jobsRunning++;
78     }
79
80     ImageTwirler thread = new ImageTwirler();
81     thread.start();
82   }
83
84   /**
85    * DOCUMENT ME!
86    * 
87    * @param id1
88    *          DOCUMENT ME!
89    * @param res
90    *          DOCUMENT ME!
91    */
92   void parseResult(Sequence seq, String res)
93   {
94     StringTokenizer st = new StringTokenizer(res, "\n");
95     String data;
96     String id2;
97     int maxFound = 90;
98     StringBuffer buffer = new StringBuffer("\n\n" + seq.getName() + " :");
99
100     while (st.hasMoreTokens())
101     {
102       data = st.nextToken();
103
104       if (data.indexOf(">UNIPROT") > -1)
105       {
106         int index = data.indexOf(">UNIPROT") + 9;
107         id2 = data.substring(index, data.indexOf(" ", index));
108
109         boolean identitiesFound = false;
110         while (!identitiesFound)
111         {
112           data = st.nextToken();
113
114           if (data.indexOf("Identities") > -1)
115           {
116             identitiesFound = true;
117
118             int value = Integer.parseInt(data.substring(
119                     data.indexOf("(") + 1, data.indexOf("%")));
120
121             if (value >= maxFound)
122             {
123               maxFound = value;
124               buffer.append(" " + id2 + " " + value + "%; ");
125               suggestedIds.addElement(new Object[]
126               { seq, id2 });
127             }
128           }
129         }
130       }
131     }
132
133     output.appendText(buffer.toString());
134   }
135
136   void updateIds()
137   {
138     // This must be outside the run() body as java 1.5
139     // will not return any value from the OptionPane to the expired thread.
140     int reply = JOptionPane.showConfirmDialog(Desktop.desktop,
141             "Automatically update suggested ids?",
142             "Auto replace sequence ids", JOptionPane.YES_NO_OPTION);
143
144     if (reply == JOptionPane.YES_OPTION)
145     {
146       Enumeration keys = suggestedIds.elements();
147       while (keys.hasMoreElements())
148       {
149         Object[] object = (Object[]) keys.nextElement();
150
151         Sequence oldseq = (Sequence) object[0];
152
153         oldseq.setName(object[1].toString());
154
155         // Oldseq is actually in the dataset, we must find the
156         // Visible seq and change its name also.
157         for (int i = 0; i < al.getHeight(); i++)
158         {
159           if (al.getSequenceAt(i).getDatasetSequence() == oldseq)
160           {
161             al.getSequenceAt(i).setName(oldseq.getName());
162             break;
163           }
164         }
165
166         DBRefEntry[] entries = oldseq.getDBRef();
167         if (entries != null)
168         {
169           oldseq.addDBRef(new jalview.datamodel.DBRefEntry(
170                   jalview.datamodel.DBRefSource.UNIPROT, "0", entries[0]
171                           .getAccessionId()));
172         }
173       }
174     }
175     ap.paintAlignment(true);
176
177   }
178
179   class ImageTwirler extends Thread
180   {
181     ImageIcon[] imageIcon;
182
183     int imageIndex = 0;
184
185     public ImageTwirler()
186     {
187       imageIcon = new ImageIcon[9];
188
189       for (int i = 0; i < 9; i++)
190       {
191         java.net.URL url = getClass().getResource(
192                 "/images/dna" + (i + 1) + ".gif");
193
194         if (url != null)
195         {
196           imageIcon[i] = new ImageIcon(url);
197         }
198       }
199     }
200
201     public void run()
202     {
203       while (jobsRunning > 0)
204       {
205         try
206         {
207           Thread.sleep(100);
208           imageIndex++;
209           imageIndex %= 9;
210           output.setFrameIcon(imageIcon[imageIndex]);
211           output.setTitle("BLASTing for unidentified sequences - "
212                   + jobsRunning + " jobs running.");
213         } catch (Exception ex)
214         {
215         }
216       }
217
218       if (jobsRunning == 0)
219       {
220         updateIds();
221       }
222     }
223   }
224
225   class BlastThread extends Thread
226   {
227     Sequence sequence;
228
229     String jobid;
230
231     boolean jobComplete = false;
232
233     BlastThread(Sequence sequence)
234     {
235       System.out.println("blasting for: " + sequence.getName());
236       this.sequence = sequence;
237     }
238
239     public void run()
240     {
241       StartJob();
242
243       while (!jobComplete)
244       {
245         try
246         {
247           WSWUBlastService service = new WSWUBlastServiceLocator();
248           WSWUBlast wublast = service.getWSWUBlast();
249           WSFile[] results = wublast.getResults(jobid);
250
251           if (results != null)
252           {
253             String result = new String(wublast.poll(jobid, "tooloutput"));
254             parseResult(sequence, result);
255             jobComplete = true;
256             jobsRunning--;
257           }
258           else
259           {
260             Thread.sleep(10000);
261             System.out.println("WSWuBlastClient: I'm alive "
262                     + sequence.getName() + " " + jobid); // log.debug
263           }
264         } catch (Exception ex)
265         {
266         }
267       }
268     }
269
270     void StartJob()
271     {
272       InputParams params = new InputParams();
273
274       params.setProgram("blastp");
275       params.setDatabase("uniprot");
276       params.setMatrix("pam10");
277
278       params.setNumal(5);
279       params.setSensitivity("low");
280       params.setSort("totalscore");
281       params.setOutformat("txt");
282       params.setAsync(true);
283
284       try
285       {
286         Data inputs[] = new Data[1];
287         Data input = new Data();
288         input.setType("sequence");
289         input.setContent(AlignSeq.extractGaps("-. ",
290                 sequence.getSequenceAsString()));
291         inputs[0] = input;
292
293         WSWUBlastService service = new WSWUBlastServiceLocator();
294         WSWUBlast wublast = service.getWSWUBlast();
295         jobid = wublast.runWUBlast(params, inputs);
296       } catch (Exception exp)
297       {
298         jobComplete = true;
299         jobsRunning--;
300         System.err.println("WSWUBlastClient error:\n" + exp.toString());
301         exp.printStackTrace();
302       }
303     }
304   }
305 }