JAL-98 ProfileI interface for Profile
[jalview.git] / src / jalview / datamodel / SequenceGroup.java
index c6b9cbd..2870a2c 100755 (executable)
@@ -1,6 +1,6 @@
 /*
- * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2)
- * Copyright (C) 2014 The Jalview Authors
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
  * 
  * This file is part of Jalview.
  * 
@@ -23,14 +23,11 @@ package jalview.datamodel;
 import jalview.analysis.AAFrequency;
 import jalview.analysis.Conservation;
 import jalview.schemes.ColourSchemeI;
-import jalview.schemes.ResidueProperties;
 
 import java.awt.Color;
 import java.util.ArrayList;
-import java.util.Hashtable;
 import java.util.List;
 import java.util.Map;
-import java.util.Vector;
 
 /**
  * Collects a set contiguous ranges on a set of sequences
@@ -46,8 +43,6 @@ public class SequenceGroup implements AnnotatedCollectionI
 
   Conservation conserve;
 
-  Vector aaFrequency;
-
   boolean displayBoxes = true;
 
   boolean displayText = true;
@@ -76,8 +71,10 @@ public class SequenceGroup implements AnnotatedCollectionI
    */
   public ColourSchemeI cs;
 
+  // start column (base 0)
   int startRes = 0;
 
+  // end column (base 0)
   int endRes = 0;
 
   public Color outlineColour = Color.black;
@@ -207,7 +204,7 @@ public class SequenceGroup implements AnnotatedCollectionI
       if (seqs[ipos] != null)
       {
         seqs[ipos].setDescription(seq.getDescription());
-        seqs[ipos].setDBRef(seq.getDBRef());
+        seqs[ipos].setDBRefs(seq.getDBRefs());
         seqs[ipos].setSequenceFeatures(seq.getSequenceFeatures());
         if (seq.getDatasetSequence() != null)
         {
@@ -502,33 +499,52 @@ public class SequenceGroup implements AnnotatedCollectionI
   }
 
   /**
-   * calculate residue conservation for group - but only if necessary.
+   * calculate residue conservation and colourschemes for group - but only if
+   * necessary. returns true if the calculation resulted in a visible change to
+   * group
+   */
+  public boolean recalcConservation()
+  {
+    return recalcConservation(false);
+  }
+
+  /**
+   * calculate residue conservation for group - but only if necessary. returns
+   * true if the calculation resulted in a visible change to group
+   * 
+   * @param defer
+   *          when set, colourschemes for this group are not refreshed after
+   *          recalculation
    */
-  public void recalcConservation()
+  public boolean recalcConservation(boolean defer)
   {
     if (cs == null && consensus == null && conservation == null)
     {
-      return;
+      return false;
     }
+    // TODO: try harder to detect changes in state in order to minimise
+    // recalculation effort
+    boolean upd = false;
     try
     {
-      Hashtable cnsns[] = AAFrequency.calculate(sequences, startRes,
+      ProfileI[] cnsns = AAFrequency.calculate(sequences, startRes,
               endRes + 1, showSequenceLogo);
       if (consensus != null)
       {
         _updateConsensusRow(cnsns, sequences.size());
+        upd = true;
       }
       if (cs != null)
       {
         cs.setConsensus(cnsns);
+        upd = true;
       }
 
       if ((conservation != null)
               || (cs != null && cs.conservationApplied()))
       {
-        Conservation c = new Conservation(groupName,
-                ResidueProperties.propHash, 3, sequences, startRes,
-                endRes + 1);
+        Conservation c = new Conservation(groupName, 3, sequences,
+                startRes, endRes + 1);
         c.calculate();
         c.verdict(false, consPercGaps);
         if (conservation != null)
@@ -542,17 +558,25 @@ public class SequenceGroup implements AnnotatedCollectionI
             cs.setConservation(c);
           }
         }
+        // eager update - will cause a refresh of overview regardless
+        upd = true;
       }
-      if (cs != null)
+      if (cs != null && !defer)
       {
+        // TODO: JAL-2034 should cs.alignmentChanged modify return state
         cs.alignmentChanged(context != null ? context : this, null);
+        return true;
+      }
+      else
+      {
+        return upd;
       }
     } catch (java.lang.OutOfMemoryError err)
     {
       // TODO: catch OOM
       System.out.println("Out of memory loading groups: " + err);
     }
-
+    return upd;
   }
 
   private void _updateConservationRow(Conservation c)
@@ -575,9 +599,9 @@ public class SequenceGroup implements AnnotatedCollectionI
     c.completeAnnotations(conservation, null, startRes, endRes + 1);
   }
 
-  public Hashtable[] consensusData = null;
+  public ProfileI[] consensusData = null;
 
-  private void _updateConsensusRow(Hashtable[] cnsns, long nseq)
+  private void _updateConsensusRow(ProfileI[] cnsns, long nseq)
   {
     if (consensus == null)
     {
@@ -611,13 +635,13 @@ public class SequenceGroup implements AnnotatedCollectionI
   {
     synchronized (sequences)
     {
-    if (sequences.contains(s))
-    {
-      deleteSequence(s, recalc);
-    }
-    else
-    {
-      addSequence(s, recalc);
+      if (sequences.contains(s))
+      {
+        deleteSequence(s, recalc);
+      }
+      else
+      {
+        addSequence(s, recalc);
       }
     }
   }
@@ -773,8 +797,9 @@ public class SequenceGroup implements AnnotatedCollectionI
     synchronized (sequences)
     {
       // MC This needs to get reset when characters are inserted and deleted
-      boolean first=true;
-      for (SequenceI seq:sequences) {
+      boolean first = true;
+      for (SequenceI seq : sequences)
+      {
         if (first || seq.getLength() > width)
         {
           width = seq.getLength();
@@ -891,6 +916,7 @@ public class SequenceGroup implements AnnotatedCollectionI
   /**
    * @return the representative sequence for this group
    */
+  @Override
   public SequenceI getSeqrep()
   {
     return seqrep;
@@ -903,6 +929,7 @@ public class SequenceGroup implements AnnotatedCollectionI
    * @param seqrep
    *          the seqrep to set (null means no sequence representative)
    */
+  @Override
   public void setSeqrep(SequenceI seqrep)
   {
     this.seqrep = seqrep;
@@ -912,6 +939,7 @@ public class SequenceGroup implements AnnotatedCollectionI
    * 
    * @return true if group has a sequence representative
    */
+  @Override
   public boolean hasSeqrep()
   {
     return seqrep != null;
@@ -1033,7 +1061,8 @@ public class SequenceGroup implements AnnotatedCollectionI
 
   /**
    * 
-   * @return automatically calculated consensus row
+   * @return automatically calculated consensus row note: the row is a stub if a
+   *         consensus calculation has not yet been performed on the group
    */
   public AlignmentAnnotation getConsensus()
   {
@@ -1295,6 +1324,9 @@ public class SequenceGroup implements AnnotatedCollectionI
     return false;
   }
 
+  /**
+   * Remove all sequences from the group (leaving other properties unchanged).
+   */
   public void clear()
   {
     synchronized (sequences)