JAL-1365 refactored core methods from RNAAliFold and AACon service clients to a commo...
authorJim Procter <jprocter@compbio.dundee.ac.uk>
Wed, 25 Sep 2013 15:28:31 +0000 (16:28 +0100)
committerJim Procter <jprocter@compbio.dundee.ac.uk>
Wed, 25 Sep 2013 15:28:31 +0000 (16:28 +0100)
src/jalview/ws/jws2/AAConClient.java
src/jalview/ws/jws2/AADisorderClient.java
src/jalview/ws/jws2/JabawsAlignCalcWorker.java
src/jalview/ws/jws2/JabawsCalcWorker.java [new file with mode: 0644]
src/jalview/ws/jws2/RNAalifoldClient.java

index 7f3847b..3d50026 100644 (file)
@@ -48,23 +48,6 @@ public class AAConClient extends JabawsAlignCalcWorker
     initViewportParams();
   }
 
-  protected void initViewportParams()
-  {
-    ((jalview.gui.AlignViewport) alignViewport).setCalcIdSettingsFor(
-            getCalcId(),
-            new AAConSettings(true, service, this.preset,
-                    (arguments != null) ? JabaParamStore
-                            .getJwsArgsfromJaba(arguments) : null), true);
-  }
-
-  @Override
-  public void updateParameters(WsParamSetI newpreset,
-          java.util.List<Argument> newarguments)
-  {
-    super.updateParameters(newpreset, newarguments);
-    initViewportParams();
-  };
-
   public String getServiceActionText()
   {
     return "calculating Amino acid consensus using AACon service";
@@ -114,17 +97,13 @@ public class AAConClient extends JabawsAlignCalcWorker
     }
   }
 
+  @Override
   public String getCalcId()
   {
-    return SequenceAnnotationWSClient.AAConCalcId;
+    return CALC_ID;
   }
+  private static String CALC_ID="jabaws2.AACon";
 
-  public static void removeAAConsAnnotation(AlignmentPanel alignPanel)
   {
-    for (AlignmentAnnotation aa : alignPanel.getAlignment().findAnnotation(
-            SequenceAnnotationWSClient.AAConCalcId))
-    {
-      alignPanel.getAlignment().deleteAnnotation(aa);
-    }
   }
 }
index 3c19dc5..8db1358 100644 (file)
@@ -41,7 +41,7 @@ import compbio.data.sequence.Score;
 import compbio.data.sequence.ScoreManager.ScoreHolder;
 import compbio.metadata.Argument;
 
-public class AADisorderClient extends JabawsAlignCalcWorker implements
+public class AADisorderClient extends JabawsCalcWorker implements
         AlignCalcWorkerI
 {
 
index 720e76a..baafc8a 100644 (file)
  */
 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.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.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)
   {
     super(alignViewport, alignPanel);
   }
-
-  IProgressIndicator guiProgress;
-
+  
+  
+  
+  
   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;
-  }
-
-  /**
-   * 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;
+    super(service, alignFrame, preset, paramset);
   }
 
-  @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());
-
-      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
+   * Recover any existing parameters for this service 
    */
-  protected boolean bySequence = false;
-
-  Map<String, SequenceI> seqNames;
-
-  boolean[] gapMap;
-
-  int realw;
-
-  public List<FastaSequence> getInputSequences(AlignmentI alignment)
+  protected void initViewportParams()
   {
-    if (alignment == null || alignment.getWidth() <= 0
-            || alignment.getSequences() == null
-            // || (alignedSeqs && !alignment.isAligned() && !submitGaps)
-            || alignment.isNucleotide() ? !nucleotidesAllowed
-            : !proteinAllowed)
-    {
-      return null;
-    }
-    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];
-    for (SequenceI sq : ((List<SequenceI>) alignment.getSequences()))
-    {
-      if (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())));
-        }
-        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;
+    ((jalview.gui.AlignViewport) alignViewport).setCalcIdSettingsFor(
+            getCalcId(),
+            new AAConSettings(true, service, this.preset,
+                    (arguments != null) ? JabaParamStore
+                            .getJwsArgsfromJaba(arguments) : null), true);
   }
 
   /**
-   * 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;
-  }
-
-  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);
-    }
-  }
+  public abstract String getCalcId();
 
-  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();
   }
 }
diff --git a/src/jalview/ws/jws2/JabawsCalcWorker.java b/src/jalview/ws/jws2/JabawsCalcWorker.java
new file mode 100644 (file)
index 0000000..4a78209
--- /dev/null
@@ -0,0 +1,599 @@
+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.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());
+  
+      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;
+
+  public List<FastaSequence> getInputSequences(AlignmentI alignment)
+  {
+    if (alignment == null || alignment.getWidth() <= 0
+            || alignment.getSequences() == null
+            // || (alignedSeqs && !alignment.isAligned() && !submitGaps)
+            || alignment.isNucleotide() ? !nucleotidesAllowed
+            : !proteinAllowed)
+    {
+      return null;
+    }
+    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];
+    for (SequenceI sq : ((List<SequenceI>) alignment.getSequences()))
+    {
+      if (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())));
+        }
+        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();
+    }
+  }
+
+}
index d86f15a..b8b30c5 100644 (file)
@@ -21,6 +21,12 @@ import compbio.data.sequence.Range;
 import compbio.data.sequence.Score;
 import compbio.metadata.Argument;
 
+/**
+ * Client for the JABA RNA Alifold Service
+ * @author daluke - Daniel Barton
+ *
+ */
+
 public class RNAalifoldClient extends JabawsAlignCalcWorker implements
         AlignCalcWorkerI
 {
@@ -38,24 +44,25 @@ public class RNAalifoldClient extends JabawsAlignCalcWorker implements
   {
     super(sh, alignFrame, preset, paramset);
 
-    if (arguments == null)
-      arguments = new ArrayList<Argument>();
+    //if (arguments == null)
+    //  arguments = new ArrayList<Argument>();
 
     af = alignFrame;
     methodName = sh.serviceType;
-
+    alignedSeqs=true;
+    submitGaps=true;
     nucleotidesAllowed = true;
     proteinAllowed = false;
     initViewportParams();
   }
+  
+  public String getCalcId()
+  {
+    return CALC_ID;
+  }
+  private static String CALC_ID="jalview.ws.jws2.RNAalifoldClient";
 
-  protected void initViewportParams()
   {
-    ((jalview.gui.AlignViewport) alignViewport).setCalcIdSettingsFor(
-            getCalcId(),
-            new AAConSettings(true, service, this.preset,
-                    (arguments != null) ? JabaParamStore
-                            .getJwsArgsfromJaba(arguments) : null), true);
   }
 
   @Override
@@ -332,10 +339,4 @@ public class RNAalifoldClient extends JabawsAlignCalcWorker implements
     char ss = (Pattern.matches(regex, Character.toString(chr))) ? 'S' : ' ';
     return ss;
   }
-
-  public String getCalcId()
-  {
-    return SequenceAnnotationWSClient.AAConCalcId;
-  }
-
 }