1 package jalview.ws.jws2;
3 import java.util.ArrayList;
4 import java.util.HashMap;
5 import java.util.Iterator;
9 import compbio.data.msa.SequenceAnnotation;
10 import compbio.data.sequence.FastaSequence;
11 import compbio.data.sequence.Score;
12 import compbio.data.sequence.ScoreManager;
13 import compbio.metadata.Argument;
14 import compbio.metadata.ChunkHolder;
15 import compbio.metadata.JobStatus;
16 import compbio.metadata.JobSubmissionException;
17 import compbio.metadata.Option;
18 import compbio.metadata.ResultNotAvailableException;
19 import compbio.metadata.WrongParameterException;
20 import jalview.analysis.AlignSeq;
21 import jalview.analysis.SeqsetUtils;
22 import jalview.api.AlignViewportI;
23 import jalview.api.AlignmentViewPanel;
24 import jalview.datamodel.AlignmentAnnotation;
25 import jalview.datamodel.AlignmentI;
26 import jalview.datamodel.AnnotatedCollectionI;
27 import jalview.datamodel.Annotation;
28 import jalview.datamodel.SequenceI;
29 import jalview.gui.AlignFrame;
30 import jalview.gui.IProgressIndicator;
31 import jalview.workers.AlignCalcWorker;
32 import jalview.ws.jws2.dm.JabaWsParamSet;
33 import jalview.ws.jws2.jabaws2.Jws2Instance;
34 import jalview.ws.params.WsParamSetI;
36 public abstract class JabawsCalcWorker extends AlignCalcWorker
39 protected Jws2Instance service;
40 @SuppressWarnings("unchecked")
41 protected SequenceAnnotation aaservice;
42 protected ScoreManager scoremanager;
43 protected WsParamSetI preset;
44 protected List<Argument> arguments;
45 protected IProgressIndicator guiProgress;
47 public JabawsCalcWorker(AlignViewportI alignViewport,
48 AlignmentViewPanel alignPanel)
50 super(alignViewport, alignPanel);
53 public JabawsCalcWorker(Jws2Instance service, AlignFrame alignFrame,
54 WsParamSetI preset, List<Argument> paramset)
56 this(alignFrame.getCurrentView(), alignFrame.alignPanel);
57 this.guiProgress = alignFrame;
59 this.arguments = paramset;
60 this.service = service;
61 aaservice = (SequenceAnnotation) service.service;
65 public WsParamSetI getPreset()
70 public List<Argument> getArguments()
76 * reconfigure and restart the AAConClient. This method will spawn a new
77 * thread that will wait until any current jobs are finished, modify the
78 * parameters and restart the conservation calculation with the new values.
83 public void updateParameters(final WsParamSetI newpreset, final List<Argument> newarguments)
86 arguments = newarguments;
87 calcMan.startWorker(this);
90 public List<Option> getJabaArguments()
92 List<Option> newargs = new ArrayList<Option>();
93 if (preset != null && preset instanceof JabaWsParamSet)
95 newargs.addAll(((JabaWsParamSet) preset).getjabaArguments());
97 if (arguments != null && arguments.size() > 0)
99 for (Argument rg : arguments)
101 if (Option.class.isAssignableFrom(rg.getClass()))
103 newargs.add((Option) rg);
113 if (aaservice == null)
117 long progressId = -1;
119 int serverErrorsLeft = 3;
121 String rslt = "JOB NOT DEFINED";
122 StringBuffer msg = new StringBuffer();
129 List<compbio.data.sequence.FastaSequence> seqs = getInputSequences(alignViewport
130 .getAlignment(), bySequence ? alignViewport.getSelectionGroup() : null);
134 calcMan.workerComplete(this);
138 AlignmentAnnotation[] aa = alignViewport.getAlignment()
139 .getAlignmentAnnotation();
140 if (guiProgress != null)
142 guiProgress.setProgressBar("JABA " + getServiceActionText(),
143 progressId = System.currentTimeMillis());
145 if (preset == null && arguments == null)
147 rslt = aaservice.analize(seqs);
153 rslt = aaservice.customAnalize(seqs, getJabaArguments());
154 } catch (WrongParameterException x)
156 throw new JobSubmissionException(
157 "Invalid parameter set. Check Jalview implementation.", x);
161 boolean finished = false;
165 JobStatus status = aaservice.getJobStatus(rslt);
166 if (status.equals(JobStatus.FINISHED))
170 if (calcMan.isPending(this) && this instanceof AAConClient)
173 // cancel this job and yield to the new job
176 if (aaservice.cancelJob(rslt))
178 System.err.println("Cancelled AACon job: " + rslt);
182 System.err.println("FAILED TO CANCEL AACon job: " + rslt);
185 } catch (Exception x)
193 ChunkHolder stats = null;
197 boolean retry = false;
202 stats = aaservice.pullExecStatistics(rslt, rpos);
203 } catch (Exception x)
206 if (x.getMessage().contains(
207 "Position in a file could not be negative!"))
209 // squash index out of bounds exception- seems to happen for
210 // disorder predictors which don't (apparently) produce any
211 // progress information and JABA server throws an exception
212 // because progress length is -1.
217 if (--serverErrorsLeft > 0)
223 } catch (InterruptedException q)
237 System.out.print(stats.getChunk());
239 rpos = stats.getNextPosition();
241 } while (stats != null && rpos > cpos);
243 if (!finished && status.equals(JobStatus.FAILED))
248 } catch (InterruptedException x)
254 if (serverErrorsLeft > 0)
259 } catch (InterruptedException x)
263 scoremanager = aaservice.getAnnotation(rslt);
264 if (scoremanager != null)
266 jalview.bin.Cache.log
267 .debug("Updating result annotation from Job " + rslt
268 + " at " + service.getUri());
269 updateResultAnnotation(true);
270 ap.adjustAnnotationHeight();
275 catch (JobSubmissionException x)
278 System.err.println("submission error with " + getServiceActionText()
281 calcMan.workerCannotRun(this);
282 } catch (ResultNotAvailableException x)
284 System.err.println("collection error:\nJob ID: " + rslt);
286 calcMan.workerCannotRun(this);
288 } catch (OutOfMemoryError error)
290 calcMan.workerCannotRun(this);
293 // hconsensus = null;
294 ap.raiseOOMWarning(getServiceActionText(), error);
295 } catch (Exception x)
297 calcMan.workerCannotRun(this);
300 // hconsensus = null;
302 .println("Blacklisting worker due to unexpected exception:");
307 calcMan.workerComplete(this);
310 calcMan.workerComplete(this);
311 if (guiProgress != null && progressId != -1)
313 guiProgress.setProgressBar("", progressId);
315 ap.paintAlignment(true);
317 if (msg.length() > 0)
319 // TODO: stash message somewhere in annotation or alignment view.
320 // code below shows result in a text box popup
322 * jalview.gui.CutAndPasteTransfer cap = new
323 * jalview.gui.CutAndPasteTransfer(); cap.setText(msg.toString());
324 * jalview.gui.Desktop.addInternalFrame(cap,
325 * "Job Status for "+getServiceActionText(), 600, 400);
333 public void updateAnnotation()
335 updateResultAnnotation(false);
338 public abstract void updateResultAnnotation(boolean immediate);
340 public abstract String getServiceActionText();
342 protected boolean submitGaps = true;
343 protected boolean alignedSeqs = true;
344 protected boolean nucleotidesAllowed = false;
345 protected boolean proteinAllowed = false;
347 * record sequences for mapping result back to afterwards
349 protected boolean bySequence = false;
350 protected Map<String, SequenceI> seqNames;
351 protected boolean[] gapMap;
355 public List<FastaSequence> getInputSequences(AlignmentI alignment, AnnotatedCollectionI inputSeqs)
357 if (alignment == null || alignment.getWidth() <= 0
358 || alignment.getSequences() == null
359 || alignment.isNucleotide() ? !nucleotidesAllowed
364 if (inputSeqs==null || inputSeqs.getWidth()<=0 || inputSeqs.getSequences()==null || inputSeqs.getSequences().size()<1)
366 inputSeqs = alignment;
369 List<compbio.data.sequence.FastaSequence> seqs = new ArrayList<compbio.data.sequence.FastaSequence>();
375 seqNames = new HashMap<String, SequenceI>();
377 gapMap = new boolean[0];
378 start=inputSeqs.getStartRes();
379 end=inputSeqs.getEndRes();
382 for (SequenceI sq : ((List<SequenceI>) alignment.getSequences()))
384 if (bySequence ? sq.findPosition(end+1) -sq.findPosition(start+1) > minlen - 1 : sq.getEnd() - sq.getStart() > minlen - 1)
386 String newname = SeqsetUtils.unique_name(seqs.size() + 1);
387 // make new input sequence with or without gaps
388 if (seqNames != null)
390 seqNames.put(newname, sq);
395 seqs.add(seq = new compbio.data.sequence.FastaSequence(newname,
396 sq.getSequenceAsString()));
397 if (gapMap == null || gapMap.length < seq.getSequence().length())
399 boolean[] tg = gapMap;
400 gapMap = new boolean[seq.getLength()];
401 System.arraycopy(tg, 0, gapMap, 0, tg.length);
402 for (int p = tg.length; p < gapMap.length; p++)
404 gapMap[p] = false; // init as a gap
407 for (int apos : sq.gapMap())
409 gapMap[apos] = true; // aligned.
414 seqs.add(seq = new compbio.data.sequence.FastaSequence(newname,
415 AlignSeq.extractGaps(jalview.util.Comparison.GapChars,
416 sq.getSequenceAsString(start,end+1))));
418 if (seq.getSequence().length() > ln)
420 ln = seq.getSequence().length();
424 if (alignedSeqs && submitGaps)
427 for (int i = 0; i < gapMap.length; i++)
434 // try real hard to return something submittable
435 // TODO: some of AAcon measures need a minimum of two or three amino
436 // acids at each position, and AAcon doesn't gracefully degrade.
437 for (int p = 0; p < seqs.size(); p++)
439 FastaSequence sq = seqs.get(p);
440 int l = sq.getSequence().length();
441 // strip gapped columns
442 char[] padded = new char[realw], orig = sq.getSequence()
444 for (int i = 0, pp = 0; i < realw; pp++)
448 if (orig.length > pp)
450 padded[i++] = orig[pp];
458 seqs.set(p, new compbio.data.sequence.FastaSequence(sq.getId(),
459 new String(padded)));
466 * notify manager that we have started, and wait for a free calculation slot
468 * @return true if slot is obtained and work still valid, false if another
469 * thread has done our work for us.
473 calcMan.notifyStart(this);
474 ap.paintAlignment(false);
475 while (!calcMan.notifyWorking(this))
477 if (calcMan.isWorking(this))
485 ap.paintAlignment(false);
489 } catch (Exception ex)
491 ex.printStackTrace();
494 if (alignViewport.isClosed())
502 protected void createAnnotationRowsForScores(List<AlignmentAnnotation> ourAnnot, String calcId,
503 int alWidth, Score scr)
505 // simple annotation row
506 AlignmentAnnotation annotation = alignViewport.getAlignment()
507 .findOrCreateAnnotation(scr.getMethod(), calcId, true, null,
509 if (alWidth == gapMap.length) // scr.getScores().size())
511 constructAnnotationFromScore(annotation, 0, alWidth, scr);
512 ourAnnot.add(annotation);
516 protected AlignmentAnnotation createAnnotationRowsForScores(List<AlignmentAnnotation> ourAnnot, String typeName,
517 String calcId, SequenceI dseq, int base, Score scr)
519 System.out.println("Creating annotation on dseq:" + dseq.getStart()
520 + " base is " + base + " and length=" + dseq.getLength()
521 + " == " + scr.getScores().size());
522 // AlignmentAnnotation annotation = new AlignmentAnnotation(
523 // scr.getMethod(), typeName, new Annotation[]
524 // {}, 0, -1, AlignmentAnnotation.LINE_GRAPH);
525 // annotation.setCalcId(calcId);
526 AlignmentAnnotation annotation = alignViewport.getAlignment()
527 .findOrCreateAnnotation(typeName, calcId, false, dseq, null);
528 constructAnnotationFromScore(annotation, 0, dseq.getLength(), scr);
529 annotation.createSequenceMapping(dseq, base, false);
530 annotation.adjustForAlignment();
531 dseq.addAlignmentAnnotation(annotation);
532 ourAnnot.add(annotation);
536 private void constructAnnotationFromScore(AlignmentAnnotation annotation, int base,
537 int alWidth, Score scr)
539 Annotation[] elm = new Annotation[alWidth];
540 Iterator<Float> vals = scr.getScores().iterator();
541 float m = 0f, x = 0f;
542 for (int i = 0; vals.hasNext(); i++)
544 float val = vals.next().floatValue();
562 // if we're at a gapped column then skip to next ungapped position
563 if (gapMap != null && gapMap.length > 0)
567 elm[i++] = new Annotation("", "", ' ', Float.NaN);
570 elm[i] = new Annotation("", "" + val, ' ', val);
573 annotation.annotations = elm;
574 annotation.belowAlignment = true;
580 annotation.graphMax = x;
581 annotation.graphMin = m;
582 annotation.validateRangeAndDisplay();
585 protected void updateOurAnnots(List<AlignmentAnnotation> ourAnnot)
587 List<AlignmentAnnotation> our = ourAnnots;
588 ourAnnots = ourAnnot;
589 AlignmentI alignment = alignViewport.getAlignment();
594 for (AlignmentAnnotation an : our)
596 if (!ourAnnots.contains(an))
598 // remove the old annotation
599 alignment.deleteAnnotation(an);
605 ap.adjustAnnotationHeight();