(JAL-975) client for amino acid conservation service that allows dynamic recalculatio...
authorjprocter <jprocter@compbio.dundee.ac.uk>
Thu, 3 Nov 2011 18:15:42 +0000 (18:15 +0000)
committerjprocter <jprocter@compbio.dundee.ac.uk>
Thu, 3 Nov 2011 18:15:42 +0000 (18:15 +0000)
src/jalview/ws/jws2/AAConsClient.java [new file with mode: 0644]

diff --git a/src/jalview/ws/jws2/AAConsClient.java b/src/jalview/ws/jws2/AAConsClient.java
new file mode 100644 (file)
index 0000000..4b5a440
--- /dev/null
@@ -0,0 +1,450 @@
+package jalview.ws.jws2;
+
+import groovy.swing.impl.Startable;
+
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeSet;
+
+import sun.tools.tree.AssignAddExpression;
+
+import compbio.data.msa.SequenceAnnotation;
+import compbio.data.sequence.Range;
+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.analysis.StructureFrequency;
+import jalview.api.AlignViewportI;
+import jalview.api.AlignmentViewPanel;
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.Annotation;
+import jalview.datamodel.SequenceGroup;
+import jalview.datamodel.SequenceI;
+import jalview.gui.AlignFrame;
+import jalview.workers.AlignCalcWorker;
+import jalview.ws.jws2.dm.JabaWsParamSet;
+import jalview.ws.jws2.jabaws2.Jws2Instance;
+import jalview.ws.params.WsParamSetI;
+
+public class AAConsClient extends AlignCalcWorker
+{
+
+  public AAConsClient(AlignViewportI alignViewport,
+          AlignmentViewPanel alignPanel)
+  {
+    super(alignViewport, alignPanel);
+  }
+
+  @SuppressWarnings("unchecked")
+  SequenceAnnotation aaservice;
+
+  private ScoreManager scoremanager;
+
+  private WsParamSetI preset;
+
+  private List<Argument> arguments;
+  
+  public WsParamSetI getPreset()
+  {
+    return preset;
+  }
+  public List<Argument> getArguments()
+  {
+    return arguments;
+  }
+  /**
+   * reconfigure and restart the AAConsClient. 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)
+  {
+    if (calcMan.isWorking(this))
+    {
+      new Thread(new Runnable() {
+        @Override
+        public void run()
+        {
+         
+          try {Thread.sleep(200);
+          } catch (InterruptedException x) {};
+            updateParameters(newpreset, newarguments);
+          }
+        }
+      ).start();
+    } else {
+      preset=newpreset;
+      arguments=newarguments;
+      calcMan.startWorker(this);
+    }
+  }
+
+  public AAConsClient(Jws2Instance service, AlignFrame alignFrame,
+          WsParamSetI preset, List<Argument> paramset)
+  {
+    this(alignFrame.getCurrentView(), alignFrame.alignPanel);
+    this.preset = preset;
+    this.arguments = paramset;
+    aaservice = (SequenceAnnotation) service.service;
+
+  }
+
+  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;
+    }
+
+    try
+    {
+      if (checkDone())
+      {
+        return; 
+      }
+      AlignmentI alignment = alignViewport.getAlignment();
+
+      int aWidth = -1;
+
+      if (alignment == null || (aWidth = alignment.getWidth()) < 0)
+      {
+        calcMan.workerComplete(this);
+        return;
+      }
+
+      /*
+       * AlignmentAnnotation
+       * strucConsensus=alignViewport.getAlignmentStrucConsensusAnnotation();
+       * Hashtable[]
+       * hStrucConsensus=alignViewport.getRnaStructureConsensusHash();
+       * strucConsensus.annotations = null; strucConsensus.annotations = new
+       * Annotation[aWidth];
+       * 
+       * hStrucConsensus = new Hashtable[aWidth];
+       */
+      AlignmentAnnotation[] aa = alignViewport.getAlignment()
+              .getAlignmentAnnotation();
+      /*
+       * AlignmentAnnotation rnaStruc = null; // select rna struct to use for
+       * calculation for (int i = 0; i < aa.length; i++) { if
+       * (aa[i].getRNAStruc() != null && aa[i].isValidStruc()) { rnaStruc =
+       * aa[i]; break; } } // check to see if its valid
+       * 
+       * if (rnaStruc==null || !rnaStruc.isValidStruc()) {
+       * calcMan.workerComplete(this); return; }
+       */
+      List<compbio.data.sequence.FastaSequence> seqs = new ArrayList<compbio.data.sequence.FastaSequence>();
+
+      boolean submitGaps = true;
+      int minlen = 10;
+      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
+          seqs.add(new compbio.data.sequence.FastaSequence(newname,
+                  (submitGaps) ? sq.getSequenceAsString() : AlignSeq
+                          .extractGaps(jalview.util.Comparison.GapChars,
+                                  sq.getSequenceAsString())));
+        }
+      }
+
+      String rslt;
+      if (preset == null)
+      {
+        rslt=aaservice.analize(seqs);
+      }
+      else
+      {
+        try {
+        rslt=aaservice.customAnalize(seqs,  getJabaArguments());
+        } catch (WrongParameterException x)
+        {
+          throw new JobSubmissionException("Invalid paremeter set. Check Jalview implementation.",x);
+          
+        }
+      }
+      boolean finished = false;
+      long rpos = 0;
+      do
+      {
+        JobStatus status = aaservice.getJobStatus(rslt);
+        if (status.equals(JobStatus.FINISHED))
+        {
+          finished = true;
+        }
+        long cpos;
+        do
+        {
+          cpos = rpos;
+          ChunkHolder stats = aaservice.pullExecStatistics(rslt, rpos);
+          if (stats != null)
+          {
+            System.out.print(stats.getChunk());
+            rpos = stats.getNextPosition();
+          }
+        } while (rpos > cpos);
+
+        if (!finished && status.equals(JobStatus.FAILED))
+        {
+          try
+          {
+            Thread.sleep(200);
+          } catch (InterruptedException x)
+          {
+          }
+          ;
+        }
+
+      } while (!finished);
+      try
+      {
+        Thread.sleep(200);
+      } catch (InterruptedException x)
+      {
+      }
+      ;
+      scoremanager = aaservice.getAnnotation(rslt);
+      if (scoremanager != null)
+      {
+        updateResultAnnotation(true);
+      }
+    } catch (JobSubmissionException x)
+    {
+
+      System.err.println("submission error:");
+      x.printStackTrace();
+      calcMan.workerCannotRun(this);
+    } catch (ResultNotAvailableException x)
+    {
+      System.err.println("collection error:");
+      x.printStackTrace();
+      calcMan.workerCannotRun(this);
+
+    } catch (OutOfMemoryError error)
+    {
+      calcMan.workerCannotRun(this);
+
+      // consensus = null;
+      // hconsensus = null;
+      ap.raiseOOMWarning("calculating Amino acid consensus using AACons service", 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)
+    {
+      ap.paintAlignment(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.
+   */
+  private 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;
+  }
+
+  /**
+   * update the consensus annotation from the sequence profile data using
+   * current visualization settings.
+   */
+  public void updateAnnotation()
+  {
+    updateResultAnnotation(false);
+  }
+
+  private AlignmentAnnotation findOrCreate(String name, boolean autoCalc,
+          SequenceI seqRef, SequenceGroup groupRef)
+  {
+    for (AlignmentAnnotation annot : alignViewport.getAlignment()
+            .getAlignmentAnnotation())
+    {
+      if (annot.autoCalculated == autoCalc
+              && annot.getCalcId().equals(name)
+              && annot.sequenceRef == seqRef && annot.groupRef == groupRef)
+      {
+        return annot;
+      }
+    }
+    AlignmentAnnotation annot = new AlignmentAnnotation(name, name,
+            new Annotation[1], 0f, 0f, AlignmentAnnotation.BAR_GRAPH);
+    annot.hasText=false;
+    annot.setCalcId(new String(name));
+    annot.autoCalculated = autoCalc;
+    if (seqRef != null)
+    {
+      annot.setSequenceRef(seqRef);
+    }
+    annot.groupRef = groupRef;
+    alignViewport.getAlignment().addAnnotation(annot);
+
+    return annot;
+  }
+  public void updateResultAnnotation(boolean immediate)
+  {
+
+    if (immediate || !calcMan.isWorking(this) && scoremanager != null)
+    {
+      AlignmentAnnotation annotation;
+      ;
+      Map<String, TreeSet<Score>> scoremap = scoremanager.asMap();
+      int alWidth = alignViewport.getAlignment().getWidth();
+      AlignmentI alignment;
+      int ann = (alignment=alignViewport.getAlignment()).getAlignmentAnnotation().length;
+      ArrayList<AlignmentAnnotation> ourAnnot=new ArrayList<AlignmentAnnotation>();
+      for (String score : scoremap.keySet())
+      {
+        TreeSet<Score> scores = scoremap.get(score);
+        for (Score scr : scores)
+        {
+          if (scr.getRanges() != null && scr.getRanges().size() > 0)
+          {
+            /**
+             * annotation in range annotation = findOrCreate(scr.getMethod(),
+             * true, null, null); Annotation[] elm = new Annotation[alWidth];
+             * Iterator<Float> vals = scr.getScores().iterator(); for (Range rng
+             * : scr.getRanges()) { float val = vals.next().floatValue(); for
+             * (int i = rng.from; i <= rng.to; i++) { elm[i] = new
+             * Annotation("", "", ' ', val); } } annotation.annotations = elm;
+             * annotation.validateRangeAndDisplay();
+             */
+          }
+          else
+          {
+            // simple annotation row
+            annotation = findOrCreate(scr.getMethod(), true, null, null);
+            Annotation[] elm = new Annotation[alWidth];
+            if (alWidth==scr.getScores().size())
+            {
+            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;}}
+              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();
+            ourAnnot.add(annotation);
+            }
+          }
+        }
+      }
+      if (ourAnnot.size()>0)
+      {
+        List<AlignmentAnnotation> our=ourAnnots;
+        ourAnnots = ourAnnot;
+        if (our!=null) {
+          if (our.size()>0)
+          {
+            for (AlignmentAnnotation an:our)
+            {
+              if (!ourAnnots.contains(an))
+              {
+                // remove the old annotation
+                alignment.deleteAnnotation(an);
+              }
+            }
+          }
+          our.clear();
+        }
+      }
+      //if (ann != alignViewport.getAlignment().getAlignmentAnnotation().length)
+      {
+        ap.adjustAnnotationHeight();
+      }
+     /* else
+      {
+        ap.paintAlignment(true);
+      }*/
+    }
+  }
+
+}