674743e875533493be242e56dcde215f906158ac
[jalview.git] / src / jalview / ws / JPredClient.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 \r
20 package jalview.ws;\r
21 \r
22 import org.apache.axis.client.*;\r
23 import javax.xml.namespace.QName;\r
24 import java.util.*;\r
25 import jalview.datamodel.*;\r
26 import jalview.gui.*;\r
27 import javax.swing.*;\r
28 import java.util.*;\r
29 import java.awt.*;\r
30 import jalview.analysis.AlignSeq;\r
31 import ext.vamsas.*;\r
32 \r
33 public class JPredClient\r
34     extends WSClient\r
35 {\r
36   ext.vamsas.JPredWS server;\r
37   String altitle = "";\r
38   java.util.Hashtable SequenceInfo = null;\r
39   private WebserviceInfo setWebService()\r
40   {\r
41     WebServiceName = "JNetWS";\r
42     WebServiceJobTitle = "JNet secondary structure prediction";\r
43     WebServiceReference =\r
44         "\"Cuff J. A and Barton G.J (1999) Application of enhanced "\r
45         + "multiple sequence alignment profiles to improve protein secondary structure prediction, "\r
46         + "Proteins 40:502-511\".";\r
47     WsURL = "http://www.compbio.dundee.ac.uk/JalviewWS/services/jpred";\r
48     WebserviceInfo wsInfo = new WebserviceInfo(WebServiceJobTitle,\r
49                                                WebServiceReference);\r
50 \r
51     return wsInfo;\r
52   }\r
53 \r
54     private boolean locateWebService()\r
55     {\r
56 \r
57       JPredWSServiceLocator loc = new JPredWSServiceLocator(); // Default\r
58       try\r
59       {\r
60         this.server = loc.getjpred(new java.net.URL(WsURL)); // JBPNote will be set from properties\r
61         ( (JpredSoapBindingStub)this.server).setTimeout(60000); // one minute stub\r
62       }\r
63       catch (Exception ex)\r
64       {\r
65         JOptionPane.showMessageDialog(Desktop.desktop,\r
66             "The Secondary Structure Prediction Service named "\r
67                                       + WebServiceName + " at " + WsURL +\r
68                                       " couldn't be located.",\r
69                                       "Internal Jalview Error",\r
70                                       JOptionPane.WARNING_MESSAGE);\r
71         wsInfo.setProgressText("Serious! " + WebServiceName +\r
72                                " Service location failed\nfor URL :"\r
73                                + WsURL + "\n" + ex.getMessage());\r
74         wsInfo.setStatus(wsInfo.STATE_STOPPED_SERVERERROR);\r
75         return false;\r
76       }\r
77       return true;\r
78     }\r
79 \r
80     public JPredClient(String title, SequenceI[] msf)\r
81     {\r
82       wsInfo = setWebService();\r
83       SequenceI seq = msf[0];\r
84       altitle = "JNet prediction on " + seq.getName() +\r
85           " using alignment from " + title;\r
86 \r
87       wsInfo.setProgressText("Job details for MSA based prediction (" + title +\r
88                              ") on sequence :\n>"\r
89                              + seq.getName() + "\n"\r
90                              + AlignSeq.extractGaps("-. ", seq.getSequence()) +\r
91                              "\n");\r
92 \r
93       SequenceInfo = jalview.analysis.SeqsetUtils.SeqCharacterHash(seq);\r
94       if (!locateWebService())\r
95         return;\r
96 \r
97       JPredThread jthread = new JPredThread(msf);\r
98       jthread.start();\r
99     }\r
100 \r
101     public JPredClient(String title, SequenceI seq)\r
102     {\r
103       wsInfo = setWebService();\r
104       wsInfo.setProgressText("Job details for prediction on sequence :\n>"\r
105                              + seq.getName() + "\n" +\r
106                              AlignSeq.extractGaps("-. ", seq.getSequence()) +\r
107                              "\n");\r
108       altitle = "JNet prediction for sequence " + seq.getName() + " from " +\r
109           title;\r
110 \r
111       SequenceInfo = jalview.analysis.SeqsetUtils.SeqCharacterHash(seq);\r
112 \r
113       if (!locateWebService())\r
114               return;\r
115 \r
116       JPredThread jthread = new JPredThread(seq);\r
117       jthread.start();\r
118     }\r
119 \r
120     class JPredThread\r
121         extends Thread\r
122     {\r
123       String OutputHeader;\r
124       ext.vamsas.JpredResult result;\r
125       ext.vamsas.Sequence sequence;\r
126       ext.vamsas.Msfalignment msa;\r
127       String jobId;\r
128       boolean jobComplete = false;\r
129       int allowedServerExceptions = 3; // thread dies if too many exceptions.\r
130       JPredThread(SequenceI seq)\r
131       {\r
132         OutputHeader = wsInfo.getProgressText();\r
133         this.sequence = new ext.vamsas.Sequence();\r
134         this.sequence.setId(seq.getName());\r
135         this.sequence.setSeq(AlignSeq.extractGaps("-. ", seq.getSequence()));\r
136       }\r
137 \r
138       JPredThread(SequenceI[] msf)\r
139       {\r
140         OutputHeader = wsInfo.getProgressText();\r
141         this.sequence = new ext.vamsas.Sequence();\r
142         this.sequence.setId(msf[0].getName());\r
143         this.sequence.setSeq(AlignSeq.extractGaps("-. ", msf[0].getSequence()));\r
144         jalview.io.PileUpfile mwrite = new jalview.io.PileUpfile();\r
145         this.msa = new ext.vamsas.Msfalignment();\r
146         msa.setMsf(mwrite.print(msf));\r
147       }\r
148 \r
149       public void run()\r
150       {\r
151 \r
152         StartJob();\r
153 \r
154         while (!jobComplete && (allowedServerExceptions > 0))\r
155         {\r
156           try\r
157           {\r
158             if ( (result = server.getresult(jobId)) == null)\r
159             {\r
160               throw (new Exception(\r
161                   "Timed out when communicating with server\nTry again later.\n"));\r
162             }\r
163 \r
164             if (result.isRunning())\r
165             {\r
166               wsInfo.setStatus(WebserviceInfo.STATE_RUNNING);\r
167             }\r
168             else if (result.isQueued())\r
169             {\r
170               wsInfo.setStatus(WebserviceInfo.STATE_QUEUING);\r
171             }\r
172 \r
173             if (result.isFinished())\r
174             {\r
175               parseResult();\r
176               jobComplete = true;\r
177               jobsRunning--;\r
178             }\r
179             else\r
180             {\r
181               wsInfo.setProgressText(OutputHeader + "\n" + result.getStatus());\r
182               if (! (result.isJobFailed() || result.isServerError()))\r
183               {\r
184                 try\r
185                 {\r
186                   Thread.sleep(5000);\r
187                 }\r
188                 catch (InterruptedException ex1)\r
189                 {\r
190                 }\r
191                 //  System.out.println("I'm alive "+seqid+" "+jobid);\r
192               }\r
193               else\r
194               {\r
195                 wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);\r
196               }\r
197             }\r
198           }\r
199           catch (Exception ex)\r
200           {\r
201             allowedServerExceptions--;\r
202             wsInfo.appendProgressText("\nJPredWS Server exception!\n" +\r
203                                       ex.getMessage());\r
204             try\r
205             {\r
206               if (allowedServerExceptions > 0)\r
207               {\r
208                 Thread.sleep(5000);\r
209               }\r
210             }\r
211             catch (InterruptedException ex1)\r
212             {\r
213             }\r
214           }\r
215         }\r
216 \r
217         if (! (result.isJobFailed() || result.isServerError()))\r
218         {\r
219           wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_OK);\r
220         }\r
221         else\r
222         {\r
223           wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);\r
224         }\r
225       }\r
226 \r
227       void StartJob()\r
228       {\r
229         try\r
230         {\r
231           if (msa != null)\r
232           {\r
233             jobId = server.predictOnMsa(msa);\r
234           }\r
235           else\r
236           {\r
237             jobId = server.predict(sequence);\r
238           }\r
239           if (jobId != null)\r
240           {\r
241             if (jobId.startsWith("Broken"))\r
242             {\r
243               throw new Exception("Submission " + jobId);\r
244             }\r
245             else\r
246             {\r
247               System.out.println(WsURL + " Job Id '" + jobId + "'");\r
248             }\r
249           }\r
250           else\r
251           {\r
252             throw new Exception("Server timed out - try again later\n");\r
253 \r
254           }\r
255         }\r
256         catch (Exception e)\r
257         {\r
258           wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR);\r
259           allowedServerExceptions = 0;\r
260           jobComplete = false;\r
261           wsInfo.appendProgressText("Failed to submit the prediction: " +\r
262                                     e.toString() + "\nJust close the window\n");\r
263           System.err.println(\r
264               "JPredWS Client: Failed to submit the prediction\n" +\r
265               e.toString() + "\n");\r
266           // e.printStackTrace(); TODO: JBPNote DEBUG\r
267         }\r
268       }\r
269 \r
270       private void addFloatAnnotations(Alignment al, int[] gapmap,\r
271                                        Vector values, String Symname,\r
272                                        String Visname, float min, float max,\r
273                                        int winLength)\r
274       {\r
275 \r
276         Annotation[] annotations = new Annotation[al.getWidth()];\r
277         for (int j = 0; j < values.size(); j++)\r
278         {\r
279           float value = Float.parseFloat(values.get(j).toString());\r
280           annotations[gapmap[j]] = new Annotation("", value + "", ' ', value);\r
281         }\r
282         al.addAnnotation(new AlignmentAnnotation(Symname, Visname, annotations,\r
283                                                  min, max, winLength));\r
284       }\r
285 \r
286       void parseResult()\r
287       {\r
288         // OutputHeader = output.getText();\r
289         if (result.isFailed())\r
290         {\r
291           OutputHeader += "Job failed.\n";\r
292         }\r
293         if (result.getStatus() != null)\r
294         {\r
295           OutputHeader += "\n" + result.getStatus();\r
296         }\r
297         if (result.getPredfile() != null)\r
298         {\r
299           OutputHeader += "\n" + result.getPredfile();\r
300           // JBPNote The returned files from a webservice could be hidden behind icons in the monitor window that, when clicked, pop up their corresponding data\r
301         }\r
302         if (result.getAligfile() != null)\r
303         {\r
304           OutputHeader += "\n" + result.getAligfile();\r
305         }\r
306         wsInfo.setProgressText(OutputHeader);\r
307         try\r
308         {\r
309           // JPredFile prediction = new JPredFile("C:/JalviewX/files/jpred.txt", "File");\r
310           jalview.io.JPredFile prediction = new jalview.io.JPredFile(result.\r
311               getPredfile(), "Paste");\r
312           SequenceI[] preds = prediction.getSeqsAsArray();\r
313           Alignment al;\r
314           int FirstSeq; // the position of the query sequence in Alignment al\r
315           boolean noMsa = true; // set if no MSA has been returned by JPred\r
316 \r
317           if (this.msa != null && result.getAligfile() != null)\r
318           {\r
319             // we ignore the returned alignment if we only predicted on a single sequence\r
320             String format = jalview.io.IdentifyFile.Identify(result.getAligfile(),\r
321                 "Paste");\r
322             if (jalview.io.FormatAdapter.formats.contains(format))\r
323             {\r
324               al = new Alignment(jalview.io.FormatAdapter.readFile(result.\r
325                   getAligfile(), "Paste", format));\r
326               noMsa = false;\r
327               FirstSeq = 0;\r
328             }\r
329             else\r
330             {\r
331               throw (new Exception("Unknown format 'format' for file : \n" +\r
332                                    result.getAligfile()));\r
333             }\r
334 \r
335           }\r
336           else\r
337           {\r
338             al = new Alignment(preds);\r
339             FirstSeq = prediction.getQuerySeqPosition();\r
340           }\r
341 \r
342           if (!jalview.analysis.SeqsetUtils.SeqCharacterUnhash(al.getSequenceAt(\r
343               FirstSeq), SequenceInfo))\r
344           {\r
345             throw (new Exception(\r
346                 "Couldn't recover sequence properties for JNet Query sequence!"));\r
347           }\r
348 \r
349           AlignmentAnnotation annot;\r
350           Annotation[] annotations = null;\r
351           int i = 0;\r
352           int width = preds[0].getSequence().length();\r
353 \r
354           int[] gapmap = al.getSequenceAt(FirstSeq).gapMap();\r
355 \r
356           if (gapmap.length != width)\r
357           {\r
358             throw (new Exception(\r
359                 "Jnet Client Error\nNumber of residues in supposed query sequence :\n"\r
360                 + al.getSequenceAt(FirstSeq).getName() + "\n"\r
361                 + al.getSequenceAt(FirstSeq).getSequence()\r
362                 + "\nDiffer from number of prediction sites in \n" +\r
363                 result.getPredfile() + "\n"));\r
364           }\r
365           // JBPNote Should also rename the query sequence sometime...\r
366           i = 0;\r
367           while (i < preds.length)\r
368           {\r
369             String id = preds[i].getName().toUpperCase();\r
370             if (id.startsWith("LUPAS") || id.startsWith("JNET") ||\r
371                 id.startsWith("JPRED"))\r
372             {\r
373               annotations = new Annotation[al.getWidth()];\r
374 \r
375               if (id.equals("JNETPRED")\r
376                   || id.equals("JNETPSSM")\r
377                   || id.equals("JNETFREQ")\r
378                   || id.equals("JNETHMM")\r
379                   || id.equals("JNETALIGN")\r
380                   || id.equals("JPRED"))\r
381               {\r
382                 for (int j = 0; j < width; j++)\r
383                 {\r
384                   annotations[gapmap[j]] = new Annotation("", "",\r
385                       preds[i].getCharAt(j), 0);\r
386                 }\r
387               }\r
388               else if (id.equals("JNETCONF"))\r
389               {\r
390                 for (int j = 0; j < width; j++)\r
391                 {\r
392                   float value = Float.parseFloat(preds[i].getCharAt(j) + "");\r
393                   annotations[gapmap[j]] = new Annotation(preds[i].getCharAt(j) +\r
394                       "", "", preds[i].getCharAt(j), value);\r
395                 }\r
396               }\r
397               else\r
398               {\r
399                 for (int j = 0; j < width; j++)\r
400                 {\r
401                   annotations[gapmap[j]] = new Annotation(preds[i].getCharAt(j) +\r
402                       "", "", ' ', 0);\r
403                 }\r
404               }\r
405 \r
406               if (id.equals("JNETCONF"))\r
407               {\r
408                 annot = new AlignmentAnnotation(preds[i].getName(),\r
409                                                 "JNet Output",\r
410                                                 annotations, 0f, 10f, 1);\r
411               }\r
412 \r
413               else\r
414               {\r
415                 annot = new AlignmentAnnotation(preds[i].getName(),\r
416                                                 "JNet Output",\r
417                                                 annotations);\r
418               }\r
419               al.addAnnotation(annot);\r
420               if (noMsa)\r
421               {\r
422                 al.deleteSequence(preds[i]);\r
423               }\r
424             }\r
425             i++;\r
426           }\r
427 \r
428           Hashtable scores = prediction.getScores();\r
429           /*  addFloatAnnotations(al, gapmap,  (Vector)scores.get("JNETPROPH"),\r
430                                 "JnetpropH", "Jnet Helix Propensity", 0f,1f,1);\r
431 \r
432             addFloatAnnotations(al, gapmap,  (Vector)scores.get("JNETPROPB"),\r
433            "JnetpropB", "Jnet Beta Sheet Propensity", 0f,1f,1);\r
434 \r
435             addFloatAnnotations(al, gapmap,  (Vector)scores.get("JNETPROPC"),\r
436                                 "JnetpropC", "Jnet Coil Propensity", 0f,1f,1);\r
437            */\r
438           AlignFrame af = new AlignFrame(al);\r
439 \r
440           Desktop.addInternalFrame(af,\r
441                                    altitle,\r
442                                    AlignFrame.NEW_WINDOW_WIDTH,\r
443                                    AlignFrame.NEW_WINDOW_HEIGHT);\r
444         }\r
445         catch (Exception ex)\r
446         {\r
447           ex.printStackTrace();\r
448         }\r
449 \r
450       }\r
451 \r
452     }\r
453   }\r