Clover icon

jalviewX

  1. Project Clover database Wed Oct 31 2018 15:13:58 GMT
  2. Package jalview.ws.jws2

File AbstractJabaCalcWorker.java

 

Coverage histogram

../../../img/srcFileCovDistChart0.png
56% of files have more coverage

Code metrics

108
187
15
1
658
500
99
0.53
12.47
15
6.6

Classes

Class Line # Actions
AbstractJabaCalcWorker 54 187 99 310
0.00%
 

Contributing tests

No tests hitting this source file were found.

Source view

1    /*
2    * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3    * Copyright (C) $$Year-Rel$$ 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
10    * of the License, or (at your option) any later version.
11    *
12    * Jalview is distributed in the hope that it will be useful, but
13    * WITHOUT ANY WARRANTY; without even the implied warranty
14    * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15    * PURPOSE. See the GNU General Public License for more details.
16    *
17    * You should have received a copy of the GNU General Public License
18    * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19    * The Jalview Authors are detailed in the 'AUTHORS' file.
20    */
21    package jalview.ws.jws2;
22   
23    import jalview.analysis.AlignSeq;
24    import jalview.analysis.SeqsetUtils;
25    import jalview.api.AlignViewportI;
26    import jalview.api.AlignmentViewPanel;
27    import jalview.datamodel.AlignmentAnnotation;
28    import jalview.datamodel.AlignmentI;
29    import jalview.datamodel.AnnotatedCollectionI;
30    import jalview.datamodel.SequenceI;
31    import jalview.gui.AlignFrame;
32    import jalview.gui.IProgressIndicator;
33    import jalview.gui.IProgressIndicatorHandler;
34    import jalview.schemes.ResidueProperties;
35    import jalview.workers.AlignCalcWorker;
36    import jalview.ws.jws2.dm.AAConSettings;
37    import jalview.ws.jws2.dm.JabaWsParamSet;
38    import jalview.ws.jws2.jabaws2.Jws2Instance;
39    import jalview.ws.params.WsParamSetI;
40   
41    import java.util.ArrayList;
42    import java.util.HashMap;
43    import java.util.List;
44    import java.util.Map;
45   
46    import compbio.data.sequence.FastaSequence;
47    import compbio.metadata.Argument;
48    import compbio.metadata.ChunkHolder;
49    import compbio.metadata.JobStatus;
50    import compbio.metadata.JobSubmissionException;
51    import compbio.metadata.Option;
52    import compbio.metadata.ResultNotAvailableException;
53   
 
54    public abstract class AbstractJabaCalcWorker extends AlignCalcWorker
55    {
56   
57    protected Jws2Instance service;
58   
59    protected WsParamSetI preset;
60   
61    protected List<Argument> arguments;
62   
63    protected IProgressIndicator guiProgress;
64   
65    protected boolean submitGaps = true;
66   
67    /**
68    * by default, we filter out non-standard residues before submission
69    */
70    protected boolean filterNonStandardResidues = true;
71   
72    /**
73    * Recover any existing parameters for this service
74    */
 
75  0 toggle protected void initViewportParams()
76    {
77  0 if (getCalcId() != null)
78    {
79  0 ((jalview.gui.AlignViewport) alignViewport).setCalcIdSettingsFor(
80    getCalcId(),
81    new AAConSettings(true, service, this.preset,
82  0 (arguments != null)
83    ? JabaParamStore.getJwsArgsfromJaba(arguments)
84    : null),
85    true);
86    }
87    }
88   
89    /**
90    *
91    * @return null or a string used to recover all annotation generated by this
92    * worker
93    */
94    public abstract String getCalcId();
95   
 
96  0 toggle public WsParamSetI getPreset()
97    {
98  0 return preset;
99    }
100   
 
101  0 toggle public List<Argument> getArguments()
102    {
103  0 return arguments;
104    }
105   
106    /**
107    * reconfigure and restart the AAConClient. This method will spawn a new
108    * thread that will wait until any current jobs are finished, modify the
109    * parameters and restart the conservation calculation with the new values.
110    *
111    * @param newpreset
112    * @param newarguments
113    */
 
114  0 toggle public void updateParameters(final WsParamSetI newpreset,
115    final List<Argument> newarguments)
116    {
117  0 preset = newpreset;
118  0 arguments = newarguments;
119  0 calcMan.startWorker(this);
120  0 initViewportParams();
121    }
122   
 
123  0 toggle public List<Option> getJabaArguments()
124    {
125  0 List<Option> newargs = new ArrayList<>();
126  0 if (preset != null && preset instanceof JabaWsParamSet)
127    {
128  0 newargs.addAll(((JabaWsParamSet) preset).getjabaArguments());
129    }
130  0 if (arguments != null && arguments.size() > 0)
131    {
132  0 for (Argument rg : arguments)
133    {
134  0 if (Option.class.isAssignableFrom(rg.getClass()))
135    {
136  0 newargs.add((Option) rg);
137    }
138    }
139    }
140  0 return newargs;
141    }
142   
143    protected boolean alignedSeqs = true;
144   
145    protected boolean nucleotidesAllowed = false;
146   
147    protected boolean proteinAllowed = false;
148   
149    /**
150    * record sequences for mapping result back to afterwards
151    */
152    protected boolean bySequence = false;
153   
154    protected Map<String, SequenceI> seqNames;
155   
156    protected boolean[] gapMap;
157   
158    int realw;
159   
160    protected int start;
161   
162    int end;
163   
 
164  0 toggle public AbstractJabaCalcWorker(AlignViewportI alignViewport,
165    AlignmentViewPanel alignPanel)
166    {
167  0 super(alignViewport, alignPanel);
168    }
169   
 
170  0 toggle public AbstractJabaCalcWorker(Jws2Instance service, AlignFrame alignFrame,
171    WsParamSetI preset, List<Argument> paramset)
172    {
173  0 this(alignFrame.getCurrentView(), alignFrame.alignPanel);
174  0 this.guiProgress = alignFrame;
175  0 this.preset = preset;
176  0 this.arguments = paramset;
177  0 this.service = service;
178    }
179   
180    /**
181    *
182    * @return true if the submission thread should attempt to submit data
183    */
184    abstract boolean hasService();
185   
186    volatile String rslt = "JOB NOT DEFINED";
187   
 
188  0 toggle @Override
189    public void run()
190    {
191  0 if (!hasService())
192    {
193  0 return;
194    }
195  0 long progressId = -1;
196   
197  0 int serverErrorsLeft = 3;
198   
199  0 StringBuffer msg = new StringBuffer();
200  0 try
201    {
202  0 if (checkDone())
203    {
204  0 return;
205    }
206  0 List<compbio.data.sequence.FastaSequence> seqs = getInputSequences(
207    alignViewport.getAlignment(),
208  0 bySequence ? alignViewport.getSelectionGroup() : null);
209   
210  0 if (seqs == null || !checkValidInputSeqs(true, seqs))
211    {
212  0 calcMan.workerComplete(this);
213  0 return;
214    }
215   
216  0 AlignmentAnnotation[] aa = alignViewport.getAlignment()
217    .getAlignmentAnnotation();
218  0 if (guiProgress != null)
219    {
220  0 guiProgress.setProgressBar("JABA " + getServiceActionText(),
221    progressId = System.currentTimeMillis());
222    }
223  0 rslt = submitToService(seqs);
224  0 if (guiProgress != null)
225    {
226  0 guiProgress.registerHandler(progressId,
227    new IProgressIndicatorHandler()
228    {
229   
 
230  0 toggle @Override
231    public boolean cancelActivity(long id)
232    {
233  0 cancelCurrentJob();
234  0 return true;
235    }
236   
 
237  0 toggle @Override
238    public boolean canCancel()
239    {
240  0 return true;
241    }
242    });
243    }
244  0 boolean finished = false;
245  0 long rpos = 0;
246  0 do
247    {
248  0 JobStatus status = getJobStatus(rslt);
249  0 if (status.equals(JobStatus.FINISHED))
250    {
251  0 finished = true;
252    }
253  0 if (calcMan.isPending(this) && isInteractiveUpdate())
254    {
255  0 finished = true;
256    // cancel this job and yield to the new job
257  0 try
258    {
259  0 if (cancelJob(rslt))
260    {
261  0 System.err.println("Cancelled AACon job: " + rslt);
262    }
263    else
264    {
265  0 System.err.println("FAILED TO CANCEL AACon job: " + rslt);
266    }
267   
268    } catch (Exception x)
269    {
270   
271    }
272  0 rslt = "CANCELLED JOB";
273  0 return;
274    }
275  0 long cpos;
276  0 ChunkHolder stats = null;
277  0 do
278    {
279  0 cpos = rpos;
280  0 boolean retry = false;
281  0 do
282    {
283  0 try
284    {
285  0 stats = pullExecStatistics(rslt, rpos);
286    } catch (Exception x)
287    {
288   
289  0 if (x.getMessage().contains(
290    "Position in a file could not be negative!"))
291    {
292    // squash index out of bounds exception- seems to happen for
293    // disorder predictors which don't (apparently) produce any
294    // progress information and JABA server throws an exception
295    // because progress length is -1.
296  0 stats = null;
297    }
298    else
299    {
300  0 if (--serverErrorsLeft > 0)
301    {
302  0 retry = true;
303  0 try
304    {
305  0 Thread.sleep(200);
306    } catch (InterruptedException q)
307    {
308    }
309  0 ;
310    }
311    else
312    {
313  0 throw x;
314    }
315    }
316    }
317  0 } while (retry);
318  0 if (stats != null)
319    {
320  0 System.out.print(stats.getChunk());
321  0 msg.append(stats);
322  0 rpos = stats.getNextPosition();
323    }
324  0 } while (stats != null && rpos > cpos);
325   
326  0 if (!finished && status.equals(JobStatus.FAILED))
327    {
328  0 try
329    {
330  0 Thread.sleep(200);
331    } catch (InterruptedException x)
332    {
333    }
334  0 ;
335    }
336  0 } while (!finished);
337  0 if (serverErrorsLeft > 0)
338    {
339  0 try
340    {
341  0 Thread.sleep(200);
342    } catch (InterruptedException x)
343    {
344    }
345  0 if (collectAnnotationResultsFor(rslt))
346    {
347  0 jalview.bin.Cache.log.debug("Updating result annotation from Job "
348    + rslt + " at " + service.getUri());
349  0 updateResultAnnotation(true);
350  0 ap.adjustAnnotationHeight();
351    }
352    }
353    }
354   
355    catch (JobSubmissionException x)
356    {
357   
358  0 System.err.println(
359    "submission error with " + getServiceActionText() + " :");
360  0 x.printStackTrace();
361  0 calcMan.disableWorker(this);
362    } catch (ResultNotAvailableException x)
363    {
364  0 System.err.println("collection error:\nJob ID: " + rslt);
365  0 x.printStackTrace();
366  0 calcMan.disableWorker(this);
367   
368    } catch (OutOfMemoryError error)
369    {
370  0 calcMan.disableWorker(this);
371   
372    // consensus = null;
373    // hconsensus = null;
374  0 ap.raiseOOMWarning(getServiceActionText(), error);
375    } catch (Exception x)
376    {
377  0 calcMan.disableWorker(this);
378   
379    // consensus = null;
380    // hconsensus = null;
381  0 System.err
382    .println("Blacklisting worker due to unexpected exception:");
383  0 x.printStackTrace();
384    } finally
385    {
386   
387  0 calcMan.workerComplete(this);
388  0 if (ap != null)
389    {
390  0 calcMan.workerComplete(this);
391  0 if (guiProgress != null && progressId != -1)
392    {
393  0 guiProgress.setProgressBar("", progressId);
394    }
395    // TODO: may not need to paintAlignment again !
396  0 ap.paintAlignment(false, false);
397    }
398  0 if (msg.length() > 0)
399    {
400    // TODO: stash message somewhere in annotation or alignment view.
401    // code below shows result in a text box popup
402    /*
403    * jalview.gui.CutAndPasteTransfer cap = new
404    * jalview.gui.CutAndPasteTransfer(); cap.setText(msg.toString());
405    * jalview.gui.Desktop.addInternalFrame(cap,
406    * "Job Status for "+getServiceActionText(), 600, 400);
407    */
408    }
409    }
410   
411    }
412   
413    /**
414    * validate input for dynamic/non-dynamic update context
415    *
416    * @param dynamic
417    * @param seqs
418    * @return true if input is valid
419    */
420    abstract boolean checkValidInputSeqs(boolean dynamic,
421    List<FastaSequence> seqs);
422   
423    abstract String submitToService(
424    List<compbio.data.sequence.FastaSequence> seqs)
425    throws JobSubmissionException;
426   
427    abstract boolean cancelJob(String rslt) throws Exception;
428   
429    abstract JobStatus getJobStatus(String rslt) throws Exception;
430   
431    abstract ChunkHolder pullExecStatistics(String rslt, long rpos);
432   
433    abstract boolean collectAnnotationResultsFor(String rslt)
434    throws ResultNotAvailableException;
435   
 
436  0 toggle public void cancelCurrentJob()
437    {
438  0 try
439    {
440  0 String id = rslt;
441  0 if (cancelJob(rslt))
442    {
443  0 System.err.println("Cancelled job " + id);
444    }
445    else
446    {
447  0 System.err.println("Job " + id + " couldn't be cancelled.");
448    }
449    } catch (Exception q)
450    {
451  0 q.printStackTrace();
452    }
453    }
454   
455    /**
456    * Interactive updating. Analysis calculations that work on the currently
457    * displayed alignment data should cancel existing jobs when the input data
458    * has changed.
459    *
460    * @return true if a running job should be cancelled because new input data is
461    * available for analysis
462    */
463    abstract boolean isInteractiveUpdate();
464   
 
465  0 toggle public List<FastaSequence> getInputSequences(AlignmentI alignment,
466    AnnotatedCollectionI inputSeqs)
467    {
468  0 if (alignment == null || alignment.getWidth() <= 0
469    || alignment.getSequences() == null || alignment.isNucleotide()
470    ? !nucleotidesAllowed
471    : !proteinAllowed)
472    {
473  0 return null;
474    }
475  0 if (inputSeqs == null || inputSeqs.getWidth() <= 0
476    || inputSeqs.getSequences() == null
477    || inputSeqs.getSequences().size() < 1)
478    {
479  0 inputSeqs = alignment;
480    }
481   
482  0 List<compbio.data.sequence.FastaSequence> seqs = new ArrayList<>();
483   
484  0 int minlen = 10;
485  0 int ln = -1;
486  0 if (bySequence)
487    {
488  0 seqNames = new HashMap<>();
489    }
490  0 gapMap = new boolean[0];
491  0 start = inputSeqs.getStartRes();
492  0 end = inputSeqs.getEndRes();
493   
494  0 for (SequenceI sq : (inputSeqs.getSequences()))
495    {
496  0 if (bySequence
497    ? sq.findPosition(end + 1)
498    - sq.findPosition(start + 1) > minlen - 1
499    : sq.getEnd() - sq.getStart() > minlen - 1)
500    {
501  0 String newname = SeqsetUtils.unique_name(seqs.size() + 1);
502    // make new input sequence with or without gaps
503  0 if (seqNames != null)
504    {
505  0 seqNames.put(newname, sq);
506    }
507  0 FastaSequence seq;
508  0 if (submitGaps)
509    {
510  0 seqs.add(seq = new compbio.data.sequence.FastaSequence(newname,
511    sq.getSequenceAsString()));
512  0 if (gapMap == null || gapMap.length < seq.getSequence().length())
513    {
514  0 boolean[] tg = gapMap;
515  0 gapMap = new boolean[seq.getLength()];
516  0 System.arraycopy(tg, 0, gapMap, 0, tg.length);
517  0 for (int p = tg.length; p < gapMap.length; p++)
518    {
519  0 gapMap[p] = false; // init as a gap
520    }
521    }
522  0 for (int apos : sq.gapMap())
523    {
524  0 char sqc = sq.getCharAt(apos);
525  0 if (!filterNonStandardResidues
526  0 || (sq.isProtein() ? ResidueProperties.aaIndex[sqc] < 20
527    : ResidueProperties.nucleotideIndex[sqc] < 5))
528    {
529  0 gapMap[apos] = true; // aligned and real amino acid residue
530    }
531  0 ;
532    }
533    }
534    else
535    {
536  0 seqs.add(seq = new compbio.data.sequence.FastaSequence(newname,
537    AlignSeq.extractGaps(jalview.util.Comparison.GapChars,
538    sq.getSequenceAsString(start, end + 1))));
539    }
540  0 if (seq.getSequence().length() > ln)
541    {
542  0 ln = seq.getSequence().length();
543    }
544    }
545    }
546  0 if (alignedSeqs && submitGaps)
547    {
548  0 realw = 0;
549  0 for (int i = 0; i < gapMap.length; i++)
550    {
551  0 if (gapMap[i])
552    {
553  0 realw++;
554    }
555    }
556    // try real hard to return something submittable
557    // TODO: some of AAcon measures need a minimum of two or three amino
558    // acids at each position, and AAcon doesn't gracefully degrade.
559  0 for (int p = 0; p < seqs.size(); p++)
560    {
561  0 FastaSequence sq = seqs.get(p);
562  0 int l = sq.getSequence().length();
563    // strip gapped columns
564  0 char[] padded = new char[realw],
565    orig = sq.getSequence().toCharArray();
566  0 for (int i = 0, pp = 0; i < realw; pp++)
567    {
568  0 if (gapMap[pp])
569    {
570  0 if (orig.length > pp)
571    {
572  0 padded[i++] = orig[pp];
573    }
574    else
575    {
576  0 padded[i++] = '-';
577    }
578    }
579    }
580  0 seqs.set(p, new compbio.data.sequence.FastaSequence(sq.getId(),
581    new String(padded)));
582    }
583    }
584  0 return seqs;
585    }
586   
 
587  0 toggle @Override
588    public void updateAnnotation()
589    {
590  0 updateResultAnnotation(false);
591    }
592   
593    public abstract void updateResultAnnotation(boolean immediate);
594   
595    public abstract String getServiceActionText();
596   
597    /**
598    * notify manager that we have started, and wait for a free calculation slot
599    *
600    * @return true if slot is obtained and work still valid, false if another
601    * thread has done our work for us.
602    */
 
603  0 toggle protected boolean checkDone()
604    {
605  0 calcMan.notifyStart(this);
606  0 ap.paintAlignment(false, false);
607  0 while (!calcMan.notifyWorking(this))
608    {
609  0 if (calcMan.isWorking(this))
610    {
611  0 return true;
612    }
613  0 try
614    {
615  0 if (ap != null)
616    {
617  0 ap.paintAlignment(false, false);
618    }
619   
620  0 Thread.sleep(200);
621    } catch (Exception ex)
622    {
623  0 ex.printStackTrace();
624    }
625    }
626  0 if (alignViewport.isClosed())
627    {
628  0 abortAndDestroy();
629  0 return true;
630    }
631  0 return false;
632    }
633   
 
634  0 toggle protected void updateOurAnnots(List<AlignmentAnnotation> ourAnnot)
635    {
636  0 List<AlignmentAnnotation> our = ourAnnots;
637  0 ourAnnots = ourAnnot;
638  0 AlignmentI alignment = alignViewport.getAlignment();
639  0 if (our != null)
640    {
641  0 if (our.size() > 0)
642    {
643  0 for (AlignmentAnnotation an : our)
644    {
645  0 if (!ourAnnots.contains(an))
646    {
647    // remove the old annotation
648  0 alignment.deleteAnnotation(an);
649    }
650    }
651    }
652  0 our.clear();
653   
654  0 ap.adjustAnnotationHeight();
655    }
656    }
657   
658    }