ID tooltip preference settings and doc
[jalview.git] / src / jalview / analysis / AlignmentSorter.java
index d801ad8..c4436eb 100755 (executable)
@@ -1,6 +1,6 @@
 /*
- * Jalview - A Sequence Alignment Editor and Viewer (Version 2.4)
- * Copyright (C) 2008 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
+ * Jalview - A Sequence Alignment Editor and Viewer (Development Version 2.4.1)
+ * Copyright (C) 2009 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -40,6 +40,10 @@ import jalview.util.*;
  */
 public class AlignmentSorter
 {
+  /**
+   * todo: refactor searches to follow a basic pattern:
+   * (search property, last search state, current sort direction)
+   */
   static boolean sortIdAscending = true;
 
   static int lastGroupHash = 0;
@@ -58,11 +62,14 @@ public class AlignmentSorter
    * last Annotation Label used by sortByScore
    */
   private static String lastSortByScore;
-
+  private static boolean sortByScoreAscending = true;
   /**
    * compact representation of last arguments to SortByFeatureScore
    */
   private static String lastSortByFeatureScore;
+  private static boolean sortByFeatureScoreAscending = true;
+
+  private static boolean sortLengthAscending;
 
   /**
    * Sort by Percentage Identity w.r.t. s
@@ -77,6 +84,23 @@ public class AlignmentSorter
   public static void sortByPID(AlignmentI align, SequenceI s,
           SequenceI[] tosort)
   {
+    sortByPID(align,s,tosort,0,-1);
+  }
+  /**
+   * Sort by Percentage Identity w.r.t. s
+   * 
+   * @param align
+   *                AlignmentI
+   * @param s
+   *                SequenceI
+   * @param tosort
+   *                sequences from align that are to be sorted.
+   * @param start   start column (0 for beginning 
+   * @param end
+   */
+  public static void sortByPID(AlignmentI align, SequenceI s,
+          SequenceI[] tosort,int start, int end)
+  {
     int nSeq = align.getHeight();
 
     float[] scores = new float[nSeq];
@@ -202,6 +226,38 @@ public class AlignmentSorter
 
     sortIdAscending = !sortIdAscending;
   }
+  /**
+   * Sorts by sequence length
+   * 
+   * @param align
+   *                The alignment object to sort
+   */
+  public static void sortByLength(AlignmentI align)
+  {
+    int nSeq = align.getHeight();
+
+    float[] length = new float[nSeq];
+    SequenceI[] seqs = new SequenceI[nSeq];
+    
+    for (int i = 0; i < nSeq; i++)
+    {
+      seqs[i] = align.getSequenceAt(i);
+      length[i] = (float) (seqs[i].getEnd()-seqs[i].getStart());
+    }
+
+    QuickSort.sort(length, seqs);
+
+    if (sortLengthAscending)
+    {
+      setReverseOrder(align, seqs);
+    }
+    else
+    {
+      setOrder(align, seqs);
+    }
+
+    sortLengthAscending = !sortLengthAscending;
+  }
 
   /**
    * Sorts the alignment by size of group. <br>
@@ -310,7 +366,7 @@ public class AlignmentSorter
   private static SequenceI[] vectorSubsetToArray(Vector tmp, Vector mask)
   {
     Vector seqs = new Vector();
-    int i;
+    int i,idx;
     boolean[] tmask = new boolean[mask.size()];
 
     for (i = 0; i < mask.size(); i++)
@@ -321,10 +377,10 @@ public class AlignmentSorter
     for (i = 0; i < tmp.size(); i++)
     {
       Object sq = tmp.elementAt(i);
-
-      if (mask.contains(sq) && tmask[mask.indexOf(sq)])
+      idx = mask.indexOf(sq); 
+      if (idx>-1 && tmask[idx])
       {
-        tmask[mask.indexOf(sq)] = false;
+        tmask[idx] = false;
         seqs.addElement(sq);
       }
     }
@@ -668,6 +724,7 @@ public class AlignmentSorter
     boolean ignoreScore=method!=FEATURE_SCORE;
     StringBuffer scoreLabel = new StringBuffer();
     scoreLabel.append(start+stop+method);
+    // This doesn't quite work yet - we'd like to have a canonical ordering that can be preserved from call to call
     for (int i=0;featureLabels!=null && i<featureLabels.length; i++)
     {
       scoreLabel.append(featureLabels[i]==null ? "null" : featureLabels[i]);
@@ -717,9 +774,10 @@ public class AlignmentSorter
                 ||
                 // or ignore based on selection criteria
                 (featureLabels != null && !AlignmentSorter.containsIgnoreCase(sf[f].type, featureLabels))
-                || (groupLabels != null 
-                        && (sf[f].getFeatureGroup() == null 
-                                || !AlignmentSorter.containsIgnoreCase(sf[f].getFeatureGroup(), groupLabels))))
+                || (groupLabels != null
+                        // problem here: we cannot eliminate null feature group features
+                        && (sf[f].getFeatureGroup() != null 
+                                && !AlignmentSorter.containsIgnoreCase(sf[f].getFeatureGroup(), groupLabels))))
         {
           // forget about this feature
           sf[f] = null;
@@ -798,7 +856,10 @@ public class AlignmentSorter
       {
         if (!hasScore[i])
         {
-          scores[i] = (max + i);
+          scores[i] = (max + 1+i);
+        } else {
+          int nf=(feats[i]==null) ? 0 :((SequenceFeature[]) feats[i]).length;
+          // System.err.println("Sorting on Score: seq "+seqs[i].getName()+ " Feats: "+nf+" Score : "+scores[i]);
         }
       }
     }
@@ -815,7 +876,7 @@ public class AlignmentSorter
         {
           double nf;
           scores[i] = (0.05+fr*i)+(nf=((feats[i]==null) ? 0.0 :1.0*((SequenceFeature[]) feats[i]).length));
-          System.err.println("Sorting on Density: seq "+seqs[i].getName()+ " Feats: "+nf+" Score : "+scores[i]);
+          // System.err.println("Sorting on Density: seq "+seqs[i].getName()+ " Feats: "+nf+" Score : "+scores[i]);
         }
         jalview.util.QuickSort.sort(scores, seqs);
       }
@@ -825,12 +886,17 @@ public class AlignmentSorter
           throw new Error("Not yet implemented.");
         }
       }
-    if (lastSortByFeatureScore ==null || scoreLabel.equals(lastSortByFeatureScore))
+    if (lastSortByFeatureScore ==null || !scoreLabel.toString().equals(lastSortByFeatureScore))
     {
+      sortByFeatureScoreAscending = true;
+    } else {
+      sortByFeatureScoreAscending = !sortByFeatureScoreAscending;
+    }
+    if (sortByFeatureScoreAscending) {
       setOrder(alignment, seqs);
     }
     else
-    {
+    {      
       setReverseOrder(alignment, seqs);
     }
     lastSortByFeatureScore = scoreLabel.toString();