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