Merge branch 'JAL-1164_disorderforselection' into Release_2_8_1_Branch
authorJim Procter <jprocter@compbio.dundee.ac.uk>
Fri, 11 Oct 2013 11:24:08 +0000 (12:24 +0100)
committerJim Procter <jprocter@compbio.dundee.ac.uk>
Fri, 11 Oct 2013 11:24:08 +0000 (12:24 +0100)
Conflicts:
src/jalview/api/AlignViewportI.java
src/jalview/ws/jws2/JabawsAlignCalcWorker.java

1  2 
src/jalview/datamodel/SequenceGroup.java
src/jalview/ws/jws2/AADisorderClient.java
src/jalview/ws/jws2/JabawsAlignCalcWorker.java
src/jalview/ws/jws2/JabawsCalcWorker.java

   */
  package jalview.ws.jws2;
  
 -import jalview.analysis.AlignSeq;
 -import jalview.analysis.SeqsetUtils;
  import jalview.api.AlignViewportI;
  import jalview.api.AlignmentViewPanel;
 -import jalview.datamodel.AlignmentAnnotation;
 -import jalview.datamodel.AlignmentI;
 -import jalview.datamodel.AnnotatedCollectionI;
 -import jalview.datamodel.Annotation;
 -import jalview.datamodel.SequenceI;
  import jalview.gui.AlignFrame;
- import jalview.workers.AlignCalcWorker;
 -import jalview.gui.IProgressIndicator;
 -import jalview.workers.AlignCalcWorker;
 -import jalview.ws.jws2.dm.JabaWsParamSet;
 +import jalview.ws.jws2.dm.AAConSettings;
  import jalview.ws.jws2.jabaws2.Jws2Instance;
  import jalview.ws.params.WsParamSetI;
  
 -import java.util.ArrayList;
 -import java.util.HashMap;
 -import java.util.Iterator;
  import java.util.List;
 -import java.util.Map;
  
--import compbio.data.msa.SequenceAnnotation;
 -import compbio.data.sequence.FastaSequence;
 -import compbio.data.sequence.Score;
 -import compbio.data.sequence.ScoreManager;
  import compbio.metadata.Argument;
 -import compbio.metadata.ChunkHolder;
 -import compbio.metadata.JobStatus;
 -import compbio.metadata.JobSubmissionException;
 -import compbio.metadata.Option;
 -import compbio.metadata.ResultNotAvailableException;
 -import compbio.metadata.WrongParameterException;
  
 -public abstract class JabawsAlignCalcWorker extends AlignCalcWorker
 +public abstract class JabawsAlignCalcWorker extends JabawsCalcWorker
  {
 -  Jws2Instance service;
 -
 -  @SuppressWarnings("unchecked")
 -  protected SequenceAnnotation aaservice;
 -
 -  protected ScoreManager scoremanager;
 -
 -  protected WsParamSetI preset;
 -
 -  protected List<Argument> arguments;
  
    public JabawsAlignCalcWorker(AlignViewportI alignViewport,
            AlignmentViewPanel alignPanel)
    public JabawsAlignCalcWorker(Jws2Instance service, AlignFrame alignFrame,
            WsParamSetI preset, List<Argument> paramset)
    {
 -    this(alignFrame.getCurrentView(), alignFrame.alignPanel);
 -    this.guiProgress = alignFrame;
 -    this.preset = preset;
 -    this.arguments = paramset;
 -    this.service = service;
 -    aaservice = (SequenceAnnotation) service.service;
 -
 -  }
 -
 -  public WsParamSetI getPreset()
 -  {
 -    return preset;
 -  }
 -
 -  public List<Argument> getArguments()
 -  {
 -    return arguments;
 +    super(service, alignFrame, preset, paramset);
    }
  
    /**
 -   * reconfigure and restart the AAConClient. This method will spawn a new
 -   * thread that will wait until any current jobs are finished, modify the
 -   * parameters and restart the conservation calculation with the new values.
 -   * 
 -   * @param newpreset
 -   * @param newarguments
 +   * Recover any existing parameters for this service 
     */
 -  public void updateParameters(final WsParamSetI newpreset,
 -          final List<Argument> newarguments)
 -  {
 -    preset = newpreset;
 -    arguments = newarguments;
 -    calcMan.startWorker(this);
 -  }
 -
 -  public List<Option> getJabaArguments()
 +  protected void initViewportParams()
    {
 -    List<Option> newargs = new ArrayList<Option>();
 -    if (preset != null && preset instanceof JabaWsParamSet)
 -    {
 -      newargs.addAll(((JabaWsParamSet) preset).getjabaArguments());
 -    }
 -    if (arguments != null && arguments.size() > 0)
 -    {
 -      for (Argument rg : arguments)
 -      {
 -        if (Option.class.isAssignableFrom(rg.getClass()))
 -        {
 -          newargs.add((Option) rg);
 -        }
 -      }
 -    }
 -    return newargs;
 +    ((jalview.gui.AlignViewport) alignViewport).setCalcIdSettingsFor(
 +            getCalcId(),
 +            new AAConSettings(true, service, this.preset,
 +                    (arguments != null) ? JabaParamStore
 +                            .getJwsArgsfromJaba(arguments) : null), true);
    }
  
 -  @Override
 -  public void run()
 -  {
 -    if (aaservice == null)
 -    {
 -      return;
 -    }
 -    long progressId = -1;
 -
 -    int serverErrorsLeft = 3;
 -
 -    String rslt = "JOB NOT DEFINED";
 -    StringBuffer msg = new StringBuffer();
 -    try
 -    {
 -      if (checkDone())
 -      {
 -        return;
 -      }
 -      List<compbio.data.sequence.FastaSequence> seqs = getInputSequences(alignViewport
 -              .getAlignment(), bySequence ? alignViewport.getSelectionGroup() : null);
 -
 -      if (seqs == null)
 -      {
 -        calcMan.workerComplete(this);
 -        return;
 -      }
 -
 -      AlignmentAnnotation[] aa = alignViewport.getAlignment()
 -              .getAlignmentAnnotation();
 -      if (guiProgress != null)
 -      {
 -        guiProgress.setProgressBar("JABA " + getServiceActionText(),
 -                progressId = System.currentTimeMillis());
 -      }
 -      if (preset == null && arguments == null)
 -      {
 -        rslt = aaservice.analize(seqs);
 -      }
 -      else
 -      {
 -        try
 -        {
 -          rslt = aaservice.customAnalize(seqs, getJabaArguments());
 -        } catch (WrongParameterException x)
 -        {
 -          throw new JobSubmissionException(
 -                  "Invalid parameter set. Check Jalview implementation.", x);
 -
 -        }
 -      }
 -      boolean finished = false;
 -      long rpos = 0;
 -      do
 -      {
 -        JobStatus status = aaservice.getJobStatus(rslt);
 -        if (status.equals(JobStatus.FINISHED))
 -        {
 -          finished = true;
 -        }
 -        if (calcMan.isPending(this) && this instanceof AAConClient)
 -        {
 -          finished = true;
 -          // cancel this job and yield to the new job
 -          try
 -          {
 -            if (aaservice.cancelJob(rslt))
 -            {
 -              System.err.println("Cancelled AACon job: " + rslt);
 -            }
 -            else
 -            {
 -              System.err.println("FAILED TO CANCEL AACon job: " + rslt);
 -            }
 -
 -          } catch (Exception x)
 -          {
 -
 -          }
 -
 -          return;
 -        }
 -        long cpos;
 -        ChunkHolder stats = null;
 -        do
 -        {
 -          cpos = rpos;
 -          boolean retry = false;
 -          do
 -          {
 -            try
 -            {
 -              stats = aaservice.pullExecStatistics(rslt, rpos);
 -            } catch (Exception x)
 -            {
 -
 -              if (x.getMessage().contains(
 -                      "Position in a file could not be negative!"))
 -              {
 -                // squash index out of bounds exception- seems to happen for
 -                // disorder predictors which don't (apparently) produce any
 -                // progress information and JABA server throws an exception
 -                // because progress length is -1.
 -                stats = null;
 -              }
 -              else
 -              {
 -                if (--serverErrorsLeft > 0)
 -                {
 -                  retry = true;
 -                  try
 -                  {
 -                    Thread.sleep(200);
 -                  } catch (InterruptedException q)
 -                  {
 -                  }
 -                  ;
 -                }
 -                else
 -                {
 -                  throw x;
 -                }
 -              }
 -            }
 -          } while (retry);
 -          if (stats != null)
 -          {
 -            System.out.print(stats.getChunk());
 -            msg.append(stats);
 -            rpos = stats.getNextPosition();
 -          }
 -        } while (stats != null && rpos > cpos);
 -
 -        if (!finished && status.equals(JobStatus.FAILED))
 -        {
 -          try
 -          {
 -            Thread.sleep(200);
 -          } catch (InterruptedException x)
 -          {
 -          }
 -          ;
 -        }
 -      } while (!finished);
 -      if (serverErrorsLeft > 0)
 -      {
 -        try
 -        {
 -          Thread.sleep(200);
 -        } catch (InterruptedException x)
 -        {
 -        }
 -        ;
 -        scoremanager = aaservice.getAnnotation(rslt);
 -        if (scoremanager != null)
 -        {
 -          jalview.bin.Cache.log
 -                  .debug("Updating result annotation from Job " + rslt
 -                          + " at " + service.getUri());
 -          updateResultAnnotation(true);
 -          ap.adjustAnnotationHeight();
 -        }
 -      }
 -    }
 -
 -    catch (JobSubmissionException x)
 -    {
 -
 -      System.err.println("submission error with " + getServiceActionText()
 -              + " :");
 -      x.printStackTrace();
 -      calcMan.workerCannotRun(this);
 -    } catch (ResultNotAvailableException x)
 -    {
 -      System.err.println("collection error:\nJob ID: " + rslt);
 -      x.printStackTrace();
 -      calcMan.workerCannotRun(this);
 -
 -    } catch (OutOfMemoryError error)
 -    {
 -      calcMan.workerCannotRun(this);
 -
 -      // consensus = null;
 -      // hconsensus = null;
 -      ap.raiseOOMWarning(getServiceActionText(), error);
 -    } catch (Exception x)
 -    {
 -      calcMan.workerCannotRun(this);
 -
 -      // consensus = null;
 -      // hconsensus = null;
 -      System.err
 -              .println("Blacklisting worker due to unexpected exception:");
 -      x.printStackTrace();
 -    } finally
 -    {
 -
 -      calcMan.workerComplete(this);
 -      if (ap != null)
 -      {
 -        calcMan.workerComplete(this);
 -        if (guiProgress != null && progressId != -1)
 -        {
 -          guiProgress.setProgressBar("", progressId);
 -        }
 -        ap.paintAlignment(true);
 -      }
 -      if (msg.length() > 0)
 -      {
 -        // TODO: stash message somewhere in annotation or alignment view.
 -        // code below shows result in a text box popup
 -        /*
 -         * jalview.gui.CutAndPasteTransfer cap = new
 -         * jalview.gui.CutAndPasteTransfer(); cap.setText(msg.toString());
 -         * jalview.gui.Desktop.addInternalFrame(cap,
 -         * "Job Status for "+getServiceActionText(), 600, 400);
 -         */
 -      }
 -    }
 -
 -  }
 -
 -  @Override
 -  public void updateAnnotation()
 -  {
 -    updateResultAnnotation(false);
 -  }
 -
 -  public abstract void updateResultAnnotation(boolean immediate);
 -
 -  public abstract String getServiceActionText();
 -
 -  boolean submitGaps = true;
 -
 -  boolean alignedSeqs = true;
 -
 -  boolean nucleotidesAllowed = false;
 -
 -  boolean proteinAllowed = false;
 -
    /**
 -   * record sequences for mapping result back to afterwards
 -   */
 -  protected boolean bySequence = false;
 -
 -  Map<String, SequenceI> seqNames;
 -
 -  boolean[] gapMap;
 -
 -  int realw;
 -  
 -  int start,end;
 -
 -  public List<FastaSequence> getInputSequences(AlignmentI alignment, AnnotatedCollectionI inputSeqs)
 -  {
 -    if (alignment == null || alignment.getWidth() <= 0
 -            || alignment.getSequences() == null
 -            // || (alignedSeqs && !alignment.isAligned() && !submitGaps)
 -            || alignment.isNucleotide() ? !nucleotidesAllowed
 -            : !proteinAllowed)
 -    {
 -      return null;
 -    }
 -    if (inputSeqs==null || inputSeqs.getWidth()<=0 || inputSeqs.getSequences()==null || inputSeqs.getSequences().size()<1)
 -    {
 -      inputSeqs = alignment;
 -    }
 -    
 -    List<compbio.data.sequence.FastaSequence> seqs = new ArrayList<compbio.data.sequence.FastaSequence>();
 -
 -    int minlen = 10;
 -    int ln = -1;
 -    if (bySequence)
 -    {
 -      seqNames = new HashMap<String, SequenceI>();
 -    }
 -    gapMap = new boolean[0];
 -    start=inputSeqs.getStartRes();
 -    end=inputSeqs.getEndRes();
 -    
 -    for (SequenceI sq : (List<SequenceI>) inputSeqs.getSequences())
 -    {
 -      if (sq.findPosition(end+1) -sq.findPosition(start+1) > minlen - 1)
 -      {
 -        String newname = SeqsetUtils.unique_name(seqs.size() + 1);
 -        // make new input sequence with or without gaps
 -        if (seqNames != null)
 -        {
 -          seqNames.put(newname, sq);
 -        }
 -        FastaSequence seq;
 -        if (submitGaps)
 -        {
 -          seqs.add(seq = new compbio.data.sequence.FastaSequence(newname,
 -                  sq.getSequenceAsString()));
 -          if (gapMap == null || gapMap.length < seq.getSequence().length())
 -          {
 -            boolean[] tg = gapMap;
 -            gapMap = new boolean[seq.getLength()];
 -            System.arraycopy(tg, 0, gapMap, 0, tg.length);
 -            for (int p = tg.length; p < gapMap.length; p++)
 -            {
 -              gapMap[p] = false; // init as a gap
 -            }
 -          }
 -          for (int apos : sq.gapMap())
 -          {
 -            gapMap[apos] = true; // aligned.
 -          }
 -        }
 -        else
 -        {
 -          seqs.add(seq = new compbio.data.sequence.FastaSequence(newname,
 -                  AlignSeq.extractGaps(jalview.util.Comparison.GapChars,
 -                          sq.getSequenceAsString(start,end+1))));
 -        }
 -        if (seq.getSequence().length() > ln)
 -        {
 -          ln = seq.getSequence().length();
 -        }
 -      }
 -    }
 -    if (alignedSeqs && submitGaps)
 -    {
 -      realw = 0;
 -      for (int i = 0; i < gapMap.length; i++)
 -      {
 -        if (gapMap[i])
 -        {
 -          realw++;
 -        }
 -      }
 -      // try real hard to return something submittable
 -      // TODO: some of AAcon measures need a minimum of two or three amino
 -      // acids at each position, and AAcon doesn't gracefully degrade.
 -      for (int p = 0; p < seqs.size(); p++)
 -      {
 -        FastaSequence sq = seqs.get(p);
 -        int l = sq.getSequence().length();
 -        // strip gapped columns
 -        char[] padded = new char[realw], orig = sq.getSequence()
 -                .toCharArray();
 -        for (int i = 0, pp = 0; i < realw; pp++)
 -        {
 -          if (gapMap[pp])
 -          {
 -            if (orig.length > pp)
 -            {
 -              padded[i++] = orig[pp];
 -            }
 -            else
 -            {
 -              padded[i++] = '-';
 -            }
 -          }
 -        }
 -        seqs.set(p, new compbio.data.sequence.FastaSequence(sq.getId(),
 -                new String(padded)));
 -      }
 -    }
 -    return seqs;
 -  }
 -
 -  /**
 -   * notify manager that we have started, and wait for a free calculation slot
     * 
 -   * @return true if slot is obtained and work still valid, false if another
 -   *         thread has done our work for us.
 +   * @return
     */
 -  boolean checkDone()
 -  {
 -    calcMan.notifyStart(this);
 -    ap.paintAlignment(false);
 -    while (!calcMan.notifyWorking(this))
 -    {
 -      if (calcMan.isWorking(this))
 -      {
 -        return true;
 -      }
 -      try
 -      {
 -        if (ap != null)
 -        {
 -          ap.paintAlignment(false);
 -        }
 -
 -        Thread.sleep(200);
 -      } catch (Exception ex)
 -      {
 -        ex.printStackTrace();
 -      }
 -    }
 -    if (alignViewport.isClosed())
 -    {
 -      abortAndDestroy();
 -      return true;
 -    }
 -    return false;
 -  }
 +  public abstract String getCalcId();
  
 -  protected void createAnnotationRowsForScores(
 -          List<AlignmentAnnotation> ourAnnot, String calcId, int alWidth,
 -          Score scr)
 -  {
 -    // simple annotation row
 -    AlignmentAnnotation annotation = alignViewport.getAlignment()
 -            .findOrCreateAnnotation(scr.getMethod(), calcId, true, null,
 -                    null);
 -    if (alWidth == gapMap.length) // scr.getScores().size())
 -    {
 -      constructAnnotationFromScore(annotation, 0, alWidth, scr);
 -      ourAnnot.add(annotation);
 -    }
 -  }
  
 -  protected AlignmentAnnotation createAnnotationRowsForScores(
 -          List<AlignmentAnnotation> ourAnnot, String typeName,
 -          String calcId, SequenceI dseq, int base, Score scr)
 -  {
 -    System.out.println("Creating annotation on dseq:" + dseq.getStart()
 -            + " base is " + base + " and length=" + dseq.getLength()
 -            + " == " + scr.getScores().size());
 -    // AlignmentAnnotation annotation = new AlignmentAnnotation(
 -    // scr.getMethod(), typeName, new Annotation[]
 -    // {}, 0, -1, AlignmentAnnotation.LINE_GRAPH);
 -    // annotation.setCalcId(calcId);
 -    AlignmentAnnotation annotation = alignViewport.getAlignment()
 -            .findOrCreateAnnotation(typeName, calcId, false, dseq, null);
 -    constructAnnotationFromScore(annotation, 0, dseq.getLength(), scr);
 -    annotation.createSequenceMapping(dseq, base, false);
 -    annotation.adjustForAlignment();
 -    dseq.addAlignmentAnnotation(annotation);
 -    ourAnnot.add(annotation);
 -    return annotation;
 -  }
  
 -  private void constructAnnotationFromScore(AlignmentAnnotation annotation,
 -          int base, int alWidth, Score scr)
 -  {
 -    Annotation[] elm = new Annotation[alWidth];
 -    Iterator<Float> vals = scr.getScores().iterator();
 -    float m = 0f, x = 0f;
 -    for (int i = 0; vals.hasNext(); i++)
 -    {
 -      float val = vals.next().floatValue();
 -      if (i == 0)
 -      {
 -        m = val;
 -        x = val;
 -      }
 -      else
 -      {
 -        if (m > val)
 -        {
 -          m = val;
 -        }
 -        ;
 -        if (x < val)
 -        {
 -          x = val;
 -        }
 -      }
 -      // if we're at a gapped column then skip to next ungapped position
 -      if (gapMap != null && gapMap.length > 0)
 -      {
 -        while (!gapMap[i])
 -        {
 -          elm[i++] = new Annotation("", "", ' ', Float.NaN);
 -        }
 -      }
 -      elm[i] = new Annotation("", "" + val, ' ', val);
 -    }
  
 -    annotation.annotations = elm;
 -    annotation.belowAlignment = true;
 -    if (x < 0)
 -    {
 -      x = 0;
 -    }
 -    x += (x - m) * 0.1;
 -    annotation.graphMax = x;
 -    annotation.graphMin = m;
 -    annotation.validateRangeAndDisplay();
 -  }
 -
 -  protected void updateOurAnnots(List<AlignmentAnnotation> ourAnnot)
 +  @Override
 +  public void updateParameters(WsParamSetI newpreset, java.util.List<Argument> newarguments)
    {
 -    List<AlignmentAnnotation> our = ourAnnots;
 -    ourAnnots = ourAnnot;
 -    AlignmentI alignment = alignViewport.getAlignment();
 -    if (our != null)
 -    {
 -      if (our.size() > 0)
 -      {
 -        for (AlignmentAnnotation an : our)
 -        {
 -          if (!ourAnnots.contains(an))
 -          {
 -            // remove the old annotation
 -            alignment.deleteAnnotation(an);
 -          }
 -        }
 -      }
 -      our.clear();
 -
 -      ap.adjustAnnotationHeight();
 -    }
 +    super.updateParameters(newpreset, newarguments);
 +    initViewportParams();
    }
  }
index 4a78209,0000000..8515dbc
mode 100644,000000..100644
--- /dev/null
@@@ -1,599 -1,0 +1,609 @@@
 +package jalview.ws.jws2;
 +
 +import java.util.ArrayList;
 +import java.util.HashMap;
 +import java.util.Iterator;
 +import java.util.List;
 +import java.util.Map;
 +
 +import compbio.data.msa.SequenceAnnotation;
 +import compbio.data.sequence.FastaSequence;
 +import compbio.data.sequence.Score;
 +import compbio.data.sequence.ScoreManager;
 +import compbio.metadata.Argument;
 +import compbio.metadata.ChunkHolder;
 +import compbio.metadata.JobStatus;
 +import compbio.metadata.JobSubmissionException;
 +import compbio.metadata.Option;
 +import compbio.metadata.ResultNotAvailableException;
 +import compbio.metadata.WrongParameterException;
 +import jalview.analysis.AlignSeq;
 +import jalview.analysis.SeqsetUtils;
 +import jalview.api.AlignViewportI;
 +import jalview.api.AlignmentViewPanel;
 +import jalview.datamodel.AlignmentAnnotation;
 +import jalview.datamodel.AlignmentI;
++import jalview.datamodel.AnnotatedCollectionI;
 +import jalview.datamodel.Annotation;
 +import jalview.datamodel.SequenceI;
 +import jalview.gui.AlignFrame;
 +import jalview.gui.IProgressIndicator;
 +import jalview.workers.AlignCalcWorker;
 +import jalview.ws.jws2.dm.JabaWsParamSet;
 +import jalview.ws.jws2.jabaws2.Jws2Instance;
 +import jalview.ws.params.WsParamSetI;
 +
 +public abstract class JabawsCalcWorker extends AlignCalcWorker
 +{
 +
 +  protected Jws2Instance service;
 +  @SuppressWarnings("unchecked")
 +  protected SequenceAnnotation aaservice;
 +  protected ScoreManager scoremanager;
 +  protected WsParamSetI preset;
 +  protected List<Argument> arguments;
 +  protected IProgressIndicator guiProgress;
 +
 +  public JabawsCalcWorker(AlignViewportI alignViewport,
 +          AlignmentViewPanel alignPanel)
 +  {
 +    super(alignViewport, alignPanel);
 +  }
 +
 +  public JabawsCalcWorker(Jws2Instance service, AlignFrame alignFrame,
 +          WsParamSetI preset, List<Argument> paramset)
 +  {
 +    this(alignFrame.getCurrentView(), alignFrame.alignPanel);
 +    this.guiProgress = alignFrame;
 +    this.preset = preset;
 +    this.arguments = paramset;
 +    this.service = service;
 +    aaservice = (SequenceAnnotation) service.service;
 +
 +  }
 +
 +  public WsParamSetI getPreset()
 +  {
 +    return preset;
 +  }
 +
 +  public List<Argument> getArguments()
 +  {
 +    return arguments;
 +  }
 +
 +  /**
 +   * reconfigure and restart the AAConClient. This method will spawn a new
 +   * thread that will wait until any current jobs are finished, modify the
 +   * parameters and restart the conservation calculation with the new values.
 +   * 
 +   * @param newpreset
 +   * @param newarguments
 +   */
 +  public void updateParameters(final WsParamSetI newpreset, final List<Argument> newarguments)
 +  {
 +    preset = newpreset;
 +    arguments = newarguments;
 +    calcMan.startWorker(this);
 +  }
 +
 +  public List<Option> getJabaArguments()
 +  {
 +    List<Option> newargs = new ArrayList<Option>();
 +    if (preset != null && preset instanceof JabaWsParamSet)
 +    {
 +      newargs.addAll(((JabaWsParamSet) preset).getjabaArguments());
 +    }
 +    if (arguments != null && arguments.size() > 0)
 +    {
 +      for (Argument rg : arguments)
 +      {
 +        if (Option.class.isAssignableFrom(rg.getClass()))
 +        {
 +          newargs.add((Option) rg);
 +        }
 +      }
 +    }
 +    return newargs;
 +  }
 +
 +  @Override
 +  public void run()
 +  {
 +    if (aaservice == null)
 +    {
 +      return;
 +    }
 +    long progressId = -1;
 +  
 +    int serverErrorsLeft = 3;
 +  
 +    String rslt = "JOB NOT DEFINED";
 +    StringBuffer msg = new StringBuffer();
 +    try
 +    {
 +      if (checkDone())
 +      {
 +        return;
 +      }
 +      List<compbio.data.sequence.FastaSequence> seqs = getInputSequences(alignViewport
-               .getAlignment());
++              .getAlignment(), bySequence ? alignViewport.getSelectionGroup() : null);
 +  
 +      if (seqs == null)
 +      {
 +        calcMan.workerComplete(this);
 +        return;
 +      }
 +  
 +      AlignmentAnnotation[] aa = alignViewport.getAlignment()
 +              .getAlignmentAnnotation();
 +      if (guiProgress != null)
 +      {
 +        guiProgress.setProgressBar("JABA " + getServiceActionText(),
 +                progressId = System.currentTimeMillis());
 +      }
 +      if (preset == null && arguments == null)
 +      {
 +        rslt = aaservice.analize(seqs);
 +      }
 +      else
 +      {
 +        try
 +        {
 +          rslt = aaservice.customAnalize(seqs, getJabaArguments());
 +        } catch (WrongParameterException x)
 +        {
 +          throw new JobSubmissionException(
 +                  "Invalid parameter set. Check Jalview implementation.", x);
 +  
 +        }
 +      }
 +      boolean finished = false;
 +      long rpos = 0;
 +      do
 +      {
 +        JobStatus status = aaservice.getJobStatus(rslt);
 +        if (status.equals(JobStatus.FINISHED))
 +        {
 +          finished = true;
 +        }
 +        if (calcMan.isPending(this) && this instanceof AAConClient)
 +        {
 +          finished = true;
 +          // cancel this job and yield to the new job
 +          try
 +          {
 +            if (aaservice.cancelJob(rslt))
 +            {
 +              System.err.println("Cancelled AACon job: " + rslt);
 +            }
 +            else
 +            {
 +              System.err.println("FAILED TO CANCEL AACon job: " + rslt);
 +            }
 +  
 +          } catch (Exception x)
 +          {
 +  
 +          }
 +  
 +          return;
 +        }
 +        long cpos;
 +        ChunkHolder stats = null;
 +        do
 +        {
 +          cpos = rpos;
 +          boolean retry = false;
 +          do
 +          {
 +            try
 +            {
 +              stats = aaservice.pullExecStatistics(rslt, rpos);
 +            } catch (Exception x)
 +            {
 +  
 +              if (x.getMessage().contains(
 +                      "Position in a file could not be negative!"))
 +              {
 +                // squash index out of bounds exception- seems to happen for
 +                // disorder predictors which don't (apparently) produce any
 +                // progress information and JABA server throws an exception
 +                // because progress length is -1.
 +                stats = null;
 +              }
 +              else
 +              {
 +                if (--serverErrorsLeft > 0)
 +                {
 +                  retry = true;
 +                  try
 +                  {
 +                    Thread.sleep(200);
 +                  } catch (InterruptedException q)
 +                  {
 +                  }
 +                  ;
 +                }
 +                else
 +                {
 +                  throw x;
 +                }
 +              }
 +            }
 +          } while (retry);
 +          if (stats != null)
 +          {
 +            System.out.print(stats.getChunk());
 +            msg.append(stats);
 +            rpos = stats.getNextPosition();
 +          }
 +        } while (stats != null && rpos > cpos);
 +  
 +        if (!finished && status.equals(JobStatus.FAILED))
 +        {
 +          try
 +          {
 +            Thread.sleep(200);
 +          } catch (InterruptedException x)
 +          {
 +          }
 +          ;
 +        }
 +      } while (!finished);
 +      if (serverErrorsLeft > 0)
 +      {
 +        try
 +        {
 +          Thread.sleep(200);
 +        } catch (InterruptedException x)
 +        {
 +        }
 +        ;
 +        scoremanager = aaservice.getAnnotation(rslt);
 +        if (scoremanager != null)
 +        {
 +          jalview.bin.Cache.log
 +                  .debug("Updating result annotation from Job " + rslt
 +                          + " at " + service.getUri());
 +          updateResultAnnotation(true);
 +          ap.adjustAnnotationHeight();
 +        }
 +      }
 +    }
 +  
 +    catch (JobSubmissionException x)
 +    {
 +  
 +      System.err.println("submission error with " + getServiceActionText()
 +              + " :");
 +      x.printStackTrace();
 +      calcMan.workerCannotRun(this);
 +    } catch (ResultNotAvailableException x)
 +    {
 +      System.err.println("collection error:\nJob ID: " + rslt);
 +      x.printStackTrace();
 +      calcMan.workerCannotRun(this);
 +  
 +    } catch (OutOfMemoryError error)
 +    {
 +      calcMan.workerCannotRun(this);
 +  
 +      // consensus = null;
 +      // hconsensus = null;
 +      ap.raiseOOMWarning(getServiceActionText(), error);
 +    } catch (Exception x)
 +    {
 +      calcMan.workerCannotRun(this);
 +  
 +      // consensus = null;
 +      // hconsensus = null;
 +      System.err
 +              .println("Blacklisting worker due to unexpected exception:");
 +      x.printStackTrace();
 +    } finally
 +    {
 +  
 +      calcMan.workerComplete(this);
 +      if (ap != null)
 +      {
 +        calcMan.workerComplete(this);
 +        if (guiProgress != null && progressId != -1)
 +        {
 +          guiProgress.setProgressBar("", progressId);
 +        }
 +        ap.paintAlignment(true);
 +      }
 +      if (msg.length() > 0)
 +      {
 +        // TODO: stash message somewhere in annotation or alignment view.
 +        // code below shows result in a text box popup
 +        /*
 +         * jalview.gui.CutAndPasteTransfer cap = new
 +         * jalview.gui.CutAndPasteTransfer(); cap.setText(msg.toString());
 +         * jalview.gui.Desktop.addInternalFrame(cap,
 +         * "Job Status for "+getServiceActionText(), 600, 400);
 +         */
 +      }
 +    }
 +  
 +  }
 +
 +  @Override
 +  public void updateAnnotation()
 +  {
 +    updateResultAnnotation(false);
 +  }
 +
 +  public abstract void updateResultAnnotation(boolean immediate);
 +
 +  public abstract String getServiceActionText();
 +
 +  protected boolean submitGaps = true;
 +  protected boolean alignedSeqs = true;
 +  protected boolean nucleotidesAllowed = false;
 +  protected boolean proteinAllowed = false;
 +  /**
 +   * record sequences for mapping result back to afterwards
 +   */
 +  protected boolean bySequence = false;
 +  protected Map<String, SequenceI> seqNames;
 +  protected boolean[] gapMap;
 +  int realw;
++  int start,end;
 +
-   public List<FastaSequence> getInputSequences(AlignmentI alignment)
++  public List<FastaSequence> getInputSequences(AlignmentI alignment, AnnotatedCollectionI inputSeqs)
 +  {
 +    if (alignment == null || alignment.getWidth() <= 0
 +            || alignment.getSequences() == null
-             // || (alignedSeqs && !alignment.isAligned() && !submitGaps)
 +            || alignment.isNucleotide() ? !nucleotidesAllowed
 +            : !proteinAllowed)
 +    {
 +      return null;
 +    }
++    if (inputSeqs==null || inputSeqs.getWidth()<=0 || inputSeqs.getSequences()==null || inputSeqs.getSequences().size()<1)
++    {
++      inputSeqs = alignment;
++    }
++    
 +    List<compbio.data.sequence.FastaSequence> seqs = new ArrayList<compbio.data.sequence.FastaSequence>();
-   
++
 +    int minlen = 10;
 +    int ln = -1;
 +    if (bySequence)
 +    {
 +      seqNames = new HashMap<String, SequenceI>();
 +    }
 +    gapMap = new boolean[0];
++    start=inputSeqs.getStartRes();
++    end=inputSeqs.getEndRes();
++    
++
 +    for (SequenceI sq : ((List<SequenceI>) alignment.getSequences()))
 +    {
-       if (sq.getEnd() - sq.getStart() > minlen - 1)
++      if (bySequence ? sq.findPosition(end+1) -sq.findPosition(start+1) > minlen - 1 : sq.getEnd() - sq.getStart() > minlen - 1)
 +      {
 +        String newname = SeqsetUtils.unique_name(seqs.size() + 1);
 +        // make new input sequence with or without gaps
 +        if (seqNames != null)
 +        {
 +          seqNames.put(newname, sq);
 +        }
 +        FastaSequence seq;
 +        if (submitGaps)
 +        {
 +          seqs.add(seq = new compbio.data.sequence.FastaSequence(newname,
 +                  sq.getSequenceAsString()));
 +          if (gapMap == null || gapMap.length < seq.getSequence().length())
 +          {
 +            boolean[] tg = gapMap;
 +            gapMap = new boolean[seq.getLength()];
 +            System.arraycopy(tg, 0, gapMap, 0, tg.length);
 +            for (int p = tg.length; p < gapMap.length; p++)
 +            {
 +              gapMap[p] = false; // init as a gap
 +            }
 +          }
 +          for (int apos : sq.gapMap())
 +          {
 +            gapMap[apos] = true; // aligned.
 +          }
 +        }
 +        else
 +        {
 +          seqs.add(seq = new compbio.data.sequence.FastaSequence(newname,
 +                  AlignSeq.extractGaps(jalview.util.Comparison.GapChars,
-                           sq.getSequenceAsString())));
++                          sq.getSequenceAsString(start,end+1))));
 +        }
 +        if (seq.getSequence().length() > ln)
 +        {
 +          ln = seq.getSequence().length();
 +        }
 +      }
 +    }
 +    if (alignedSeqs && submitGaps)
 +    {
 +      realw = 0;
 +      for (int i = 0; i < gapMap.length; i++)
 +      {
 +        if (gapMap[i])
 +        {
 +          realw++;
 +        }
 +      }
 +      // try real hard to return something submittable
 +      // TODO: some of AAcon measures need a minimum of two or three amino
 +      // acids at each position, and AAcon doesn't gracefully degrade.
 +      for (int p = 0; p < seqs.size(); p++)
 +      {
 +        FastaSequence sq = seqs.get(p);
 +        int l = sq.getSequence().length();
 +        // strip gapped columns
 +        char[] padded = new char[realw], orig = sq.getSequence()
 +                .toCharArray();
 +        for (int i = 0, pp = 0; i < realw; pp++)
 +        {
 +          if (gapMap[pp])
 +          {
 +            if (orig.length > pp)
 +            {
 +              padded[i++] = orig[pp];
 +            }
 +            else
 +            {
 +              padded[i++] = '-';
 +            }
 +          }
 +        }
 +        seqs.set(p, new compbio.data.sequence.FastaSequence(sq.getId(),
 +                new String(padded)));
 +      }
 +    }
 +    return seqs;
 +  }
 +
 +  /**
 +   * notify manager that we have started, and wait for a free calculation slot
 +   * 
 +   * @return true if slot is obtained and work still valid, false if another
 +   *         thread has done our work for us.
 +   */
 +  boolean checkDone()
 +  {
 +    calcMan.notifyStart(this);
 +    ap.paintAlignment(false);
 +    while (!calcMan.notifyWorking(this))
 +    {
 +      if (calcMan.isWorking(this))
 +      {
 +        return true;
 +      }
 +      try
 +      {
 +        if (ap != null)
 +        {
 +          ap.paintAlignment(false);
 +        }
 +  
 +        Thread.sleep(200);
 +      } catch (Exception ex)
 +      {
 +        ex.printStackTrace();
 +      }
 +    }
 +    if (alignViewport.isClosed())
 +    {
 +      abortAndDestroy();
 +      return true;
 +    }
 +    return false;
 +  }
 +
 +  protected void createAnnotationRowsForScores(List<AlignmentAnnotation> ourAnnot, String calcId,
 +          int alWidth, Score scr)
 +  {
 +    // simple annotation row
 +    AlignmentAnnotation annotation = alignViewport.getAlignment()
 +            .findOrCreateAnnotation(scr.getMethod(), calcId, true, null,
 +                    null);
 +    if (alWidth == gapMap.length) // scr.getScores().size())
 +    {
 +      constructAnnotationFromScore(annotation, 0, alWidth, scr);
 +      ourAnnot.add(annotation);
 +    }
 +  }
 +
 +  protected AlignmentAnnotation createAnnotationRowsForScores(List<AlignmentAnnotation> ourAnnot, String typeName,
 +          String calcId, SequenceI dseq, int base, Score scr)
 +  {
 +    System.out.println("Creating annotation on dseq:" + dseq.getStart()
 +            + " base is " + base + " and length=" + dseq.getLength()
 +            + " == " + scr.getScores().size());
 +    // AlignmentAnnotation annotation = new AlignmentAnnotation(
 +    // scr.getMethod(), typeName, new Annotation[]
 +    // {}, 0, -1, AlignmentAnnotation.LINE_GRAPH);
 +    // annotation.setCalcId(calcId);
 +    AlignmentAnnotation annotation = alignViewport.getAlignment()
 +            .findOrCreateAnnotation(typeName, calcId, false, dseq, null);
 +    constructAnnotationFromScore(annotation, 0, dseq.getLength(), scr);
 +    annotation.createSequenceMapping(dseq, base, false);
 +    annotation.adjustForAlignment();
 +    dseq.addAlignmentAnnotation(annotation);
 +    ourAnnot.add(annotation);
 +    return annotation;
 +  }
 +
 +  private void constructAnnotationFromScore(AlignmentAnnotation annotation, int base,
 +          int alWidth, Score scr)
 +  {
 +    Annotation[] elm = new Annotation[alWidth];
 +    Iterator<Float> vals = scr.getScores().iterator();
 +    float m = 0f, x = 0f;
 +    for (int i = 0; vals.hasNext(); i++)
 +    {
 +      float val = vals.next().floatValue();
 +      if (i == 0)
 +      {
 +        m = val;
 +        x = val;
 +      }
 +      else
 +      {
 +        if (m > val)
 +        {
 +          m = val;
 +        }
 +        ;
 +        if (x < val)
 +        {
 +          x = val;
 +        }
 +      }
 +      // if we're at a gapped column then skip to next ungapped position
 +      if (gapMap != null && gapMap.length > 0)
 +      {
 +        while (!gapMap[i])
 +        {
 +          elm[i++] = new Annotation("", "", ' ', Float.NaN);
 +        }
 +      }
 +      elm[i] = new Annotation("", "" + val, ' ', val);
 +    }
 +  
 +    annotation.annotations = elm;
 +    annotation.belowAlignment = true;
 +    if (x < 0)
 +    {
 +      x = 0;
 +    }
 +    x += (x - m) * 0.1;
 +    annotation.graphMax = x;
 +    annotation.graphMin = m;
 +    annotation.validateRangeAndDisplay();
 +  }
 +
 +  protected void updateOurAnnots(List<AlignmentAnnotation> ourAnnot)
 +  {
 +    List<AlignmentAnnotation> our = ourAnnots;
 +    ourAnnots = ourAnnot;
 +    AlignmentI alignment = alignViewport.getAlignment();
 +    if (our != null)
 +    {
 +      if (our.size() > 0)
 +      {
 +        for (AlignmentAnnotation an : our)
 +        {
 +          if (!ourAnnots.contains(an))
 +          {
 +            // remove the old annotation
 +            alignment.deleteAnnotation(an);
 +          }
 +        }
 +      }
 +      our.clear();
 +  
 +      ap.adjustAnnotationHeight();
 +    }
 +  }
 +
 +}