(JAL-974) - remove sun-internal class and use message to determine if we should ignor...
[jalview.git] / src / jalview / ws / jws2 / JabawsAlignCalcWorker.java
1 package jalview.ws.jws2;
2
3 import jalview.analysis.AlignSeq;
4 import jalview.analysis.SeqsetUtils;
5 import jalview.api.AlignViewportI;
6 import jalview.api.AlignmentViewPanel;
7 import jalview.datamodel.AlignmentAnnotation;
8 import jalview.datamodel.AlignmentI;
9 import jalview.datamodel.Annotation;
10 import jalview.datamodel.SequenceGroup;
11 import jalview.datamodel.SequenceI;
12 import jalview.gui.AlignFrame;
13 import jalview.workers.AlignCalcWorker;
14 import jalview.ws.jws2.dm.JabaWsParamSet;
15 import jalview.ws.jws2.jabaws2.Jws2Instance;
16 import jalview.ws.params.WsParamSetI;
17
18 import java.util.ArrayList;
19 import java.util.HashMap;
20 import java.util.List;
21 import java.util.Map;
22
23 import compbio.data.msa.SequenceAnnotation;
24 import compbio.data.sequence.FastaSequence;
25 import compbio.data.sequence.ScoreManager;
26 import compbio.metadata.Argument;
27 import compbio.metadata.ChunkHolder;
28 import compbio.metadata.JobStatus;
29 import compbio.metadata.JobSubmissionException;
30 import compbio.metadata.Option;
31 import compbio.metadata.ResultNotAvailableException;
32 import compbio.metadata.WrongParameterException;
33
34 public abstract class JabawsAlignCalcWorker extends AlignCalcWorker
35 {
36
37   @SuppressWarnings("unchecked")
38   protected SequenceAnnotation aaservice;
39
40   protected ScoreManager scoremanager;
41
42   protected WsParamSetI preset;
43
44   protected List<Argument> arguments;
45
46   public JabawsAlignCalcWorker(AlignViewportI alignViewport,
47           AlignmentViewPanel alignPanel)
48   {
49     super(alignViewport, alignPanel);
50   }
51
52   public JabawsAlignCalcWorker(Jws2Instance service, AlignFrame alignFrame,
53           WsParamSetI preset, List<Argument> paramset)
54   {
55     this(alignFrame.getCurrentView(), alignFrame.alignPanel);
56     this.preset = preset;
57     this.arguments = paramset;
58     aaservice = (SequenceAnnotation) service.service;
59
60   }
61
62   public WsParamSetI getPreset()
63   {
64     return preset;
65   }
66
67   public List<Argument> getArguments()
68   {
69     return arguments;
70   }
71
72   /**
73    * reconfigure and restart the AAConsClient. This method will spawn a new
74    * thread that will wait until any current jobs are finished, modify the
75    * parameters and restart the conservation calculation with the new values.
76    * 
77    * @param newpreset
78    * @param newarguments
79    */
80   public void updateParameters(final WsParamSetI newpreset,
81           final List<Argument> newarguments)
82   {
83     if (calcMan.isWorking(this))
84     {
85       new Thread(new Runnable()
86       {
87         @Override
88         public void run()
89         {
90
91           try
92           {
93             Thread.sleep(200);
94           } catch (InterruptedException x)
95           {
96           }
97           ;
98           updateParameters(newpreset, newarguments);
99         }
100       }).start();
101     }
102     else
103     {
104       preset = newpreset;
105       arguments = newarguments;
106       calcMan.startWorker(this);
107     }
108   }
109
110   public List<Option> getJabaArguments()
111   {
112     List<Option> newargs = new ArrayList<Option>();
113     if (preset != null && preset instanceof JabaWsParamSet)
114     {
115       newargs.addAll(((JabaWsParamSet) preset).getjabaArguments());
116     }
117     if (arguments != null && arguments.size() > 0)
118     {
119       for (Argument rg : arguments)
120       {
121         if (Option.class.isAssignableFrom(rg.getClass()))
122         {
123           newargs.add((Option) rg);
124         }
125       }
126     }
127     return newargs;
128   }
129
130   @Override
131   public void run()
132   {
133     if (aaservice == null)
134     {
135       return;
136     }
137
138     try
139     {
140       if (checkDone())
141       {
142         return;
143       }
144       List<compbio.data.sequence.FastaSequence> seqs = getInputSequences(alignViewport
145               .getAlignment());
146
147       if (seqs == null)
148       {
149         calcMan.workerComplete(this);
150         return;
151       }
152
153       AlignmentAnnotation[] aa = alignViewport.getAlignment()
154               .getAlignmentAnnotation();
155
156       String rslt;
157       if (preset == null)
158       {
159         rslt = aaservice.analize(seqs);
160       }
161       else
162       {
163         try
164         {
165           rslt = aaservice.customAnalize(seqs, getJabaArguments());
166         } catch (WrongParameterException x)
167         {
168           throw new JobSubmissionException(
169                   "Invalid paremeter set. Check Jalview implementation.", x);
170
171         }
172       }
173       boolean finished = false;
174       long rpos = 0;
175       do
176       {
177         JobStatus status = aaservice.getJobStatus(rslt);
178         if (status.equals(JobStatus.FINISHED))
179         {
180           finished = true;
181         }
182         long cpos;
183         ChunkHolder stats;
184         do
185         {
186           cpos = rpos;
187           try
188           {
189             stats = aaservice.pullExecStatistics(rslt, rpos);
190           } catch (Exception x)
191           {
192
193             if (x.getMessage().contains(
194                     "Position in a file could not be negative!"))
195             {
196               // squash index out of bounds exception- seems to happen for
197               // disorder predictors which don't (apparently) produce any
198               // progress information and JABA server throws an exception
199               // because progress length is -1.
200               stats = null;
201             }
202             else
203             {
204               throw x;
205             }
206           }
207           if (stats != null)
208           {
209             System.out.print(stats.getChunk());
210             rpos = stats.getNextPosition();
211           }
212         } while (stats != null && rpos > cpos);
213
214         if (!finished && status.equals(JobStatus.FAILED))
215         {
216           try
217           {
218             Thread.sleep(200);
219           } catch (InterruptedException x)
220           {
221           }
222           ;
223         }
224
225       } while (!finished);
226       try
227       {
228         Thread.sleep(200);
229       } catch (InterruptedException x)
230       {
231       }
232       ;
233       scoremanager = aaservice.getAnnotation(rslt);
234       if (scoremanager != null)
235       {
236         updateResultAnnotation(true);
237       }
238     } catch (JobSubmissionException x)
239     {
240
241       System.err.println("submission error:");
242       x.printStackTrace();
243       calcMan.workerCannotRun(this);
244     } catch (ResultNotAvailableException x)
245     {
246       System.err.println("collection error:");
247       x.printStackTrace();
248       calcMan.workerCannotRun(this);
249
250     } catch (OutOfMemoryError error)
251     {
252       calcMan.workerCannotRun(this);
253
254       // consensus = null;
255       // hconsensus = null;
256       ap.raiseOOMWarning(getServiceActionText(), error);
257     } catch (Exception x)
258     {
259       calcMan.workerCannotRun(this);
260
261       // consensus = null;
262       // hconsensus = null;
263       System.err
264               .println("Blacklisting worker due to unexpected exception:");
265       x.printStackTrace();
266     } finally
267     {
268
269       calcMan.workerComplete(this);
270       if (ap != null)
271       {
272         ap.paintAlignment(true);
273       }
274     }
275
276   }
277
278   public void updateAnnotation()
279   {
280     updateResultAnnotation(false);
281   }
282
283   public abstract void updateResultAnnotation(boolean immediate);
284
285   public abstract String getServiceActionText();
286
287   boolean submitGaps = true;
288
289   boolean alignedSeqs = true;
290
291   boolean nucleotidesAllowed = false;
292
293   boolean proteinAllowed = false;
294
295   /**
296    * record sequences for mapping result back to afterwards
297    */
298   protected boolean bySequence = false;
299
300   Map<String, SequenceI> seqNames;
301
302   public List<FastaSequence> getInputSequences(AlignmentI alignment)
303   {
304
305     if (alignment == null || alignment.getWidth() <= 0
306             || alignment.getSequences() == null
307             || (alignedSeqs && !alignment.isAligned())
308             || alignment.isNucleotide() ? !nucleotidesAllowed
309             : !proteinAllowed)
310     {
311       return null;
312     }
313     List<compbio.data.sequence.FastaSequence> seqs = new ArrayList<compbio.data.sequence.FastaSequence>();
314
315     int minlen = 10;
316     if (bySequence)
317     {
318       seqNames = new HashMap<String, SequenceI>();
319     }
320     for (SequenceI sq : ((List<SequenceI>) alignment.getSequences()))
321     {
322
323       if (sq.getEnd() - sq.getStart() > minlen - 1)
324       {
325         String newname = SeqsetUtils.unique_name(seqs.size() + 1);
326         // make new input sequence with or without gaps
327         if (seqNames != null)
328         {
329           seqNames.put(newname, sq);
330         }
331         seqs.add(new compbio.data.sequence.FastaSequence(newname,
332                 (submitGaps) ? sq.getSequenceAsString() : AlignSeq
333                         .extractGaps(jalview.util.Comparison.GapChars,
334                                 sq.getSequenceAsString())));
335       }
336     }
337     return seqs;
338   }
339
340   protected AlignmentAnnotation findOrCreate(String name, boolean autoCalc,
341           SequenceI seqRef, SequenceGroup groupRef)
342   {
343     for (AlignmentAnnotation annot : alignViewport.getAlignment()
344             .getAlignmentAnnotation())
345     {
346       if (annot.autoCalculated == autoCalc
347               && annot.getCalcId().equals(name)
348               && annot.sequenceRef == seqRef && annot.groupRef == groupRef)
349       {
350         return annot;
351       }
352     }
353     AlignmentAnnotation annot = new AlignmentAnnotation(name, name,
354             new Annotation[1], 0f, 0f, AlignmentAnnotation.BAR_GRAPH);
355     annot.hasText = false;
356     annot.setCalcId(new String(name));
357     annot.autoCalculated = autoCalc;
358     if (seqRef != null)
359     {
360       annot.setSequenceRef(seqRef);
361     }
362     annot.groupRef = groupRef;
363     alignViewport.getAlignment().addAnnotation(annot);
364
365     return annot;
366   }
367
368   /**
369    * notify manager that we have started, and wait for a free calculation slot
370    * 
371    * @return true if slot is obtained and work still valid, false if another
372    *         thread has done our work for us.
373    */
374   boolean checkDone()
375   {
376     calcMan.notifyStart(this);
377     // ap.paintAlignment(false);
378     while (!calcMan.notifyWorking(this))
379     {
380       if (calcMan.isWorking(this))
381       {
382         return true;
383       }
384       try
385       {
386         if (ap != null)
387         {
388           ap.paintAlignment(false);
389         }
390
391         Thread.sleep(200);
392       } catch (Exception ex)
393       {
394         ex.printStackTrace();
395       }
396     }
397     if (alignViewport.isClosed())
398     {
399       abortAndDestroy();
400       return true;
401     }
402     return false;
403   }
404
405 }