2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.0b1)
3 * Copyright (C) 2014 The Jalview Authors
5 * This file is part of Jalview.
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 of the License, or (at your option) any later version.
11 * Jalview is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty
13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along with Jalview. If not, see <http://www.gnu.org/licenses/>.
17 * The Jalview Authors are detailed in the 'AUTHORS' file.
19 package jalview.ws.jws2;
21 import jalview.analysis.AlignSeq;
22 import jalview.analysis.SeqsetUtils;
23 import jalview.api.AlignViewportI;
24 import jalview.api.AlignmentViewPanel;
25 import jalview.datamodel.AlignmentAnnotation;
26 import jalview.datamodel.AlignmentI;
27 import jalview.datamodel.AnnotatedCollectionI;
28 import jalview.datamodel.Annotation;
29 import jalview.datamodel.SequenceI;
30 import jalview.gui.AlignFrame;
31 import jalview.gui.IProgressIndicator;
32 import jalview.workers.AlignCalcWorker;
33 import jalview.ws.jws2.dm.JabaWsParamSet;
34 import jalview.ws.jws2.jabaws2.Jws2Instance;
35 import jalview.ws.params.WsParamSetI;
37 import java.util.ArrayList;
38 import java.util.HashMap;
39 import java.util.Iterator;
40 import java.util.List;
43 import compbio.data.msa.SequenceAnnotation;
44 import compbio.data.sequence.FastaSequence;
45 import compbio.data.sequence.Score;
46 import compbio.data.sequence.ScoreManager;
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 import compbio.metadata.WrongParameterException;
55 public abstract class JabawsAlignCalcWorker extends AlignCalcWorker
59 @SuppressWarnings("unchecked")
60 protected SequenceAnnotation aaservice;
62 protected ScoreManager scoremanager;
64 protected WsParamSetI preset;
66 protected List<Argument> arguments;
68 public JabawsAlignCalcWorker(AlignViewportI alignViewport,
69 AlignmentViewPanel alignPanel)
71 super(alignViewport, alignPanel);
74 IProgressIndicator guiProgress;
76 public JabawsAlignCalcWorker(Jws2Instance service, AlignFrame alignFrame,
77 WsParamSetI preset, List<Argument> paramset)
79 this(alignFrame.getCurrentView(), alignFrame.alignPanel);
80 this.guiProgress = alignFrame;
82 this.arguments = paramset;
83 this.service = service;
84 aaservice = (SequenceAnnotation) service.service;
88 public WsParamSetI getPreset()
93 public List<Argument> getArguments()
99 * reconfigure and restart the AAConClient. This method will spawn a new
100 * thread that will wait until any current jobs are finished, modify the
101 * parameters and restart the conservation calculation with the new values.
104 * @param newarguments
106 public void updateParameters(final WsParamSetI newpreset,
107 final List<Argument> newarguments)
110 arguments = newarguments;
111 calcMan.startWorker(this);
114 public List<Option> getJabaArguments()
116 List<Option> newargs = new ArrayList<Option>();
117 if (preset != null && preset instanceof JabaWsParamSet)
119 newargs.addAll(((JabaWsParamSet) preset).getjabaArguments());
121 if (arguments != null && arguments.size() > 0)
123 for (Argument rg : arguments)
125 if (Option.class.isAssignableFrom(rg.getClass()))
127 newargs.add((Option) rg);
137 if (aaservice == null)
141 long progressId = -1;
143 int serverErrorsLeft = 3;
145 String rslt = "JOB NOT DEFINED";
146 StringBuffer msg = new StringBuffer();
153 List<compbio.data.sequence.FastaSequence> seqs = getInputSequences(alignViewport
154 .getAlignment(), bySequence ? alignViewport.getSelectionGroup() : null);
158 calcMan.workerComplete(this);
162 AlignmentAnnotation[] aa = alignViewport.getAlignment()
163 .getAlignmentAnnotation();
164 if (guiProgress != null)
166 guiProgress.setProgressBar("JABA " + getServiceActionText(),
167 progressId = System.currentTimeMillis());
169 if (preset == null && arguments == null)
171 rslt = aaservice.analize(seqs);
177 rslt = aaservice.customAnalize(seqs, getJabaArguments());
178 } catch (WrongParameterException x)
180 throw new JobSubmissionException(
181 "Invalid parameter set. Check Jalview implementation.", x);
185 boolean finished = false;
189 JobStatus status = aaservice.getJobStatus(rslt);
190 if (status.equals(JobStatus.FINISHED))
194 if (calcMan.isPending(this) && this instanceof AAConClient)
197 // cancel this job and yield to the new job
200 if (aaservice.cancelJob(rslt))
202 System.err.println("Cancelled AACon job: " + rslt);
206 System.err.println("FAILED TO CANCEL AACon job: " + rslt);
209 } catch (Exception x)
217 ChunkHolder stats = null;
221 boolean retry = false;
226 stats = aaservice.pullExecStatistics(rslt, rpos);
227 } catch (Exception x)
230 if (x.getMessage().contains(
231 "Position in a file could not be negative!"))
233 // squash index out of bounds exception- seems to happen for
234 // disorder predictors which don't (apparently) produce any
235 // progress information and JABA server throws an exception
236 // because progress length is -1.
241 if (--serverErrorsLeft > 0)
247 } catch (InterruptedException q)
261 System.out.print(stats.getChunk());
263 rpos = stats.getNextPosition();
265 } while (stats != null && rpos > cpos);
267 if (!finished && status.equals(JobStatus.FAILED))
272 } catch (InterruptedException x)
278 if (serverErrorsLeft > 0)
283 } catch (InterruptedException x)
287 scoremanager = aaservice.getAnnotation(rslt);
288 if (scoremanager != null)
290 jalview.bin.Cache.log
291 .debug("Updating result annotation from Job " + rslt
292 + " at " + service.getUri());
293 updateResultAnnotation(true);
294 ap.adjustAnnotationHeight();
299 catch (JobSubmissionException x)
302 System.err.println("submission error with " + getServiceActionText()
305 calcMan.workerCannotRun(this);
306 } catch (ResultNotAvailableException x)
308 System.err.println("collection error:\nJob ID: " + rslt);
310 calcMan.workerCannotRun(this);
312 } catch (OutOfMemoryError error)
314 calcMan.workerCannotRun(this);
317 // hconsensus = null;
318 ap.raiseOOMWarning(getServiceActionText(), error);
319 } catch (Exception x)
321 calcMan.workerCannotRun(this);
324 // hconsensus = null;
326 .println("Blacklisting worker due to unexpected exception:");
331 calcMan.workerComplete(this);
334 calcMan.workerComplete(this);
335 if (guiProgress != null && progressId != -1)
337 guiProgress.setProgressBar("", progressId);
339 ap.paintAlignment(true);
341 if (msg.length() > 0)
343 // TODO: stash message somewhere in annotation or alignment view.
344 // code below shows result in a text box popup
346 * jalview.gui.CutAndPasteTransfer cap = new
347 * jalview.gui.CutAndPasteTransfer(); cap.setText(msg.toString());
348 * jalview.gui.Desktop.addInternalFrame(cap,
349 * "Job Status for "+getServiceActionText(), 600, 400);
357 public void updateAnnotation()
359 updateResultAnnotation(false);
362 public abstract void updateResultAnnotation(boolean immediate);
364 public abstract String getServiceActionText();
366 boolean submitGaps = true;
368 boolean alignedSeqs = true;
370 boolean nucleotidesAllowed = false;
372 boolean proteinAllowed = false;
375 * record sequences for mapping result back to afterwards
377 protected boolean bySequence = false;
379 Map<String, SequenceI> seqNames;
387 public List<FastaSequence> getInputSequences(AlignmentI alignment, AnnotatedCollectionI inputSeqs)
389 if (alignment == null || alignment.getWidth() <= 0
390 || alignment.getSequences() == null
391 // || (alignedSeqs && !alignment.isAligned() && !submitGaps)
392 || alignment.isNucleotide() ? !nucleotidesAllowed
397 if (inputSeqs==null || inputSeqs.getWidth()<=0 || inputSeqs.getSequences()==null || inputSeqs.getSequences().size()<1)
399 inputSeqs = alignment;
402 List<compbio.data.sequence.FastaSequence> seqs = new ArrayList<compbio.data.sequence.FastaSequence>();
408 seqNames = new HashMap<String, SequenceI>();
410 gapMap = new boolean[0];
411 start=inputSeqs.getStartRes();
412 end=inputSeqs.getEndRes();
414 for (SequenceI sq : (List<SequenceI>) inputSeqs.getSequences())
416 if (sq.findPosition(end+1) -sq.findPosition(start+1) > minlen - 1)
418 String newname = SeqsetUtils.unique_name(seqs.size() + 1);
419 // make new input sequence with or without gaps
420 if (seqNames != null)
422 seqNames.put(newname, sq);
427 seqs.add(seq = new compbio.data.sequence.FastaSequence(newname,
428 sq.getSequenceAsString()));
429 if (gapMap == null || gapMap.length < seq.getSequence().length())
431 boolean[] tg = gapMap;
432 gapMap = new boolean[seq.getLength()];
433 System.arraycopy(tg, 0, gapMap, 0, tg.length);
434 for (int p = tg.length; p < gapMap.length; p++)
436 gapMap[p] = false; // init as a gap
439 for (int apos : sq.gapMap())
441 gapMap[apos] = true; // aligned.
446 seqs.add(seq = new compbio.data.sequence.FastaSequence(newname,
447 AlignSeq.extractGaps(jalview.util.Comparison.GapChars,
448 sq.getSequenceAsString(start,end+1))));
450 if (seq.getSequence().length() > ln)
452 ln = seq.getSequence().length();
456 if (alignedSeqs && submitGaps)
459 for (int i = 0; i < gapMap.length; i++)
466 // try real hard to return something submittable
467 // TODO: some of AAcon measures need a minimum of two or three amino
468 // acids at each position, and AAcon doesn't gracefully degrade.
469 for (int p = 0; p < seqs.size(); p++)
471 FastaSequence sq = seqs.get(p);
472 int l = sq.getSequence().length();
473 // strip gapped columns
474 char[] padded = new char[realw], orig = sq.getSequence()
476 for (int i = 0, pp = 0; i < realw; pp++)
480 if (orig.length > pp)
482 padded[i++] = orig[pp];
490 seqs.set(p, new compbio.data.sequence.FastaSequence(sq.getId(),
491 new String(padded)));
498 * notify manager that we have started, and wait for a free calculation slot
500 * @return true if slot is obtained and work still valid, false if another
501 * thread has done our work for us.
505 calcMan.notifyStart(this);
506 ap.paintAlignment(false);
507 while (!calcMan.notifyWorking(this))
509 if (calcMan.isWorking(this))
517 ap.paintAlignment(false);
521 } catch (Exception ex)
523 ex.printStackTrace();
526 if (alignViewport.isClosed())
534 protected void createAnnotationRowsForScores(
535 List<AlignmentAnnotation> ourAnnot, String calcId, int alWidth,
538 // simple annotation row
539 AlignmentAnnotation annotation = alignViewport.getAlignment()
540 .findOrCreateAnnotation(scr.getMethod(), calcId, true, null,
542 if (alWidth == gapMap.length) // scr.getScores().size())
544 constructAnnotationFromScore(annotation, 0, alWidth, scr);
545 ourAnnot.add(annotation);
549 protected AlignmentAnnotation createAnnotationRowsForScores(
550 List<AlignmentAnnotation> ourAnnot, String typeName,
551 String calcId, SequenceI dseq, int base, Score scr)
553 System.out.println("Creating annotation on dseq:" + dseq.getStart()
554 + " base is " + base + " and length=" + dseq.getLength()
555 + " == " + scr.getScores().size());
556 // AlignmentAnnotation annotation = new AlignmentAnnotation(
557 // scr.getMethod(), typeName, new Annotation[]
558 // {}, 0, -1, AlignmentAnnotation.LINE_GRAPH);
559 // annotation.setCalcId(calcId);
560 AlignmentAnnotation annotation = alignViewport.getAlignment()
561 .findOrCreateAnnotation(typeName, calcId, false, dseq, null);
562 constructAnnotationFromScore(annotation, 0, dseq.getLength(), scr);
563 annotation.createSequenceMapping(dseq, base, false);
564 annotation.adjustForAlignment();
565 dseq.addAlignmentAnnotation(annotation);
566 ourAnnot.add(annotation);
570 private void constructAnnotationFromScore(AlignmentAnnotation annotation,
571 int base, int alWidth, Score scr)
573 Annotation[] elm = new Annotation[alWidth];
574 Iterator<Float> vals = scr.getScores().iterator();
575 float m = 0f, x = 0f;
576 for (int i = 0; vals.hasNext(); i++)
578 float val = vals.next().floatValue();
596 // if we're at a gapped column then skip to next ungapped position
597 if (gapMap != null && gapMap.length > 0)
601 elm[i++] = new Annotation("", "", ' ', Float.NaN);
604 elm[i] = new Annotation("", "" + val, ' ', val);
607 annotation.annotations = elm;
608 annotation.belowAlignment = true;
614 annotation.graphMax = x;
615 annotation.graphMin = m;
616 annotation.validateRangeAndDisplay();
619 protected void updateOurAnnots(List<AlignmentAnnotation> ourAnnot)
621 List<AlignmentAnnotation> our = ourAnnots;
622 ourAnnots = ourAnnot;
623 AlignmentI alignment = alignViewport.getAlignment();
628 for (AlignmentAnnotation an : our)
630 if (!ourAnnots.contains(an))
632 // remove the old annotation
633 alignment.deleteAnnotation(an);
639 ap.adjustAnnotationHeight();