seqset)
{
if (node == null)
{
@@ -533,9 +551,11 @@ public class AlignmentSorter
{
if (node.element() instanceof SequenceI)
{
- if (!tmp.contains(node.element()))
+ if (!tmp.contains(node.element())) // && (seqset==null ||
+ // seqset.size()==0 ||
+ // seqset.contains(tmp)))
{
- tmp.addElement((SequenceI) node.element());
+ tmp.add((SequenceI) node.element());
}
}
}
@@ -566,7 +586,7 @@ public class AlignmentSorter
for (int i = 0; i < alignment.length; i++)
{
- ids[i] = (new Float(alignment[i].getName().substring(8)))
+ ids[i] = (Float.valueOf(alignment[i].getName().substring(8)))
.floatValue();
}
@@ -578,17 +598,17 @@ public class AlignmentSorter
* particular scoreLabel. Or reverse if same label was used previously
*
* @param scoreLabel
- * exact label for sequence associated AlignmentAnnotation
- * scores to use for sorting.
+ * exact label for sequence associated AlignmentAnnotation scores to
+ * use for sorting.
* @param alignment
- * sequences to be sorted
+ * sequences to be sorted
*/
public static void sortByAnnotationScore(String scoreLabel,
AlignmentI alignment)
{
SequenceI[] seqs = alignment.getSequencesArray();
boolean[] hasScore = new boolean[seqs.length]; // per sequence score
- // presence
+ // presence
int hasScores = 0; // number of scores present on set
double[] scores = new double[seqs.length];
double min = 0, max = 0;
@@ -600,7 +620,7 @@ public class AlignmentSorter
hasScores++;
hasScore[i] = true;
scores[i] = scoreAnn[0].getScore(); // take the first instance of this
- // score.
+ // score.
if (hasScores == 1)
{
max = min = scores[i];
@@ -632,15 +652,15 @@ public class AlignmentSorter
{
if (!hasScore[i])
{
- scores[i] = (max + i+1.0);
+ scores[i] = (max + i + 1.0);
}
}
}
jalview.util.QuickSort.sort(scores, seqs);
- if (lastSortByScore != scoreLabel)
+ if (lastSortByAnnotation != scoreLabel)
{
- lastSortByScore = scoreLabel;
+ lastSortByAnnotation = scoreLabel;
setOrder(alignment, seqs);
}
else
@@ -648,231 +668,232 @@ public class AlignmentSorter
setReverseOrder(alignment, seqs);
}
}
+
/**
- * types of feature ordering:
- * Sort by score : average score - or total score - over all features in region
- * Sort by feature label text: (or if null - feature type text) - numerical or alphabetical
- * Sort by feature density: based on counts - ignoring individual text or scores for each feature
+ * types of feature ordering: Sort by score : average score - or total score -
+ * over all features in region Sort by feature label text: (or if null -
+ * feature type text) - numerical or alphabetical Sort by feature density:
+ * based on counts - ignoring individual text or scores for each feature
*/
- public static String FEATURE_SCORE="average_score";
- public static String FEATURE_LABEL="text";
- public static String FEATURE_DENSITY="density";
-
+ public static String FEATURE_SCORE = "average_score";
+
+ public static String FEATURE_LABEL = "text";
+
+ public static String FEATURE_DENSITY = "density";
+
/**
- * sort the alignment using the features on each sequence found between start and stop with the given featureLabel (and optional group qualifier)
- * @param featureLabel (may not be null)
- * @param groupLabel (may be null)
- * @param start (-1 to include non-positional features)
- * @param stop (-1 to only sort on non-positional features)
- * @param alignment - aligned sequences containing features
- * @param method - one of the string constants FEATURE_SCORE, FEATURE_LABEL, FEATURE_DENSITY
+ * Sort sequences by feature score or density, optionally restricted by
+ * feature types, feature groups, or alignment start/end positions.
+ *
+ * If the sort is repeated for the same combination of types and groups, sort
+ * order is reversed.
+ *
+ * @param featureTypes
+ * a list of feature types to include (or null for all)
+ * @param groups
+ * a list of feature groups to include (or null for all)
+ * @param startCol
+ * start column position to include (base zero)
+ * @param endCol
+ * end column position to include (base zero)
+ * @param alignment
+ * the alignment to be sorted
+ * @param method
+ * either "average_score" or "density" ("text" not yet implemented)
*/
- public static void sortByFeature(String featureLabel, String groupLabel, int start, int stop,
- AlignmentI alignment, String method)
- {
- sortByFeature(featureLabel==null ? null : new String[] {featureLabel},
- groupLabel==null ? null : new String[] {groupLabel}, start, stop, alignment, method);
- }
- private static boolean containsIgnoreCase(final String lab, final String[] labs)
- {
- if (labs==null)
- {
- return true;
- }
- if (lab==null)
- {
- return false;
- }
- for (int q=0;q featureTypes,
+ List groups, final int startCol, final int endCol,
AlignmentI alignment, String method)
{
- if (method!=FEATURE_SCORE && method!=FEATURE_LABEL && method!=FEATURE_DENSITY)
- {
- throw new Error("Implementation Error - sortByFeature method must be one of FEATURE_SCORE, FEATURE_LABEL or FEATURE_DENSITY.");
- }
- boolean ignoreScore=method!=FEATURE_SCORE;
- StringBuffer scoreLabel = new StringBuffer();
- scoreLabel.append(start+stop+method);
- // This doesn't 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 sfs = seqs[i].findFeatures(startCol + 1,
+ endCol + 1, types);
+
+ seqScores[i] = 0;
+ scores[i] = 0.0;
+
+ Iterator it = sfs.listIterator();
+ while (it.hasNext())
{
- sf = new SequenceFeature[0];
- } else {
- SequenceFeature[] tmp = new SequenceFeature[sf.length];
- for (int s=0; s sstop)
- ||
- // or ignore based on selection criteria
- (featureLabels != null && !AlignmentSorter.containsIgnoreCase(sf[f].type, featureLabels))
- || (groupLabels != null
- // problem here: we cannot eliminate null feature group features
- && (sf[f].getFeatureGroup() != null
- && !AlignmentSorter.containsIgnoreCase(sf[f].getFeatureGroup(), groupLabels))))
+ else
{
- // forget about this feature
- sf[f] = null;
- n--;
- } else {
- // or, also take a look at the scores if necessary.
- if (!ignoreScore && sf[f].getScore()!=Float.NaN)
+ float score = sf.getScore();
+ if (FEATURE_SCORE.equals(method) && !Float.isNaN(score))
{
- if (seqScores[i]==0)
+ if (seqScores[i] == 0)
{
hasScores++;
}
seqScores[i]++;
hasScore[i] = true;
- scores[i] += sf[f].getScore(); // take the first instance of this
- // score.
+ scores[i] += score;
+ // take the first instance of this score // ??
}
}
}
- SequenceFeature[] fs;
- feats[i] = fs = new SequenceFeature[n];
- if (n>0)
+
+ feats[i] = sfs.toArray(new SequenceFeature[sfs.size()]);
+ if (!sfs.isEmpty())
{
- n=0;
- for (int f=0;f scores[i])
+ else
{
- min = scores[i];
+ // 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]);
}
}
}
+ QuickSort.sortByDouble(scores, seqs, sortByFeatureAscending);
}
-
- if (method==FEATURE_SCORE)
- {
- if (hasScores == 0)
- {
- return; // do nothing - no scores present to sort by.
- }
- // pad score matrix
- if (hasScores < seqs.length)
+ else if (FEATURE_DENSITY.equals(method))
{
for (int i = 0; i < seqs.length; i++)
{
- if (!hasScore[i])
- {
- scores[i] = (max + 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]);
- }
+ int featureCount = feats[i] == null ? 0
+ : ((SequenceFeature[]) feats[i]).length;
+ scores[i] = featureCount;
+ // System.err.println("Sorting on Density: seq "+seqs[i].getName()+
+ // " Feats: "+featureCount+" Score : "+scores[i]);
}
+ QuickSort.sortByDouble(scores, seqs, sortByFeatureAscending);
}
- jalview.util.QuickSort.sort(scores, seqs);
+ setOrder(alignment, seqs);
+ }
+
+ /**
+ * Builds a string hash of criteria for sorting, and if unchanged from last
+ * time, reverse the sort order
+ *
+ * @param method
+ * @param featureTypes
+ * @param groups
+ * @param startCol
+ * @param endCol
+ */
+ protected static void flipFeatureSortIfUnchanged(String method,
+ List featureTypes, List groups,
+ final int startCol, final int endCol)
+ {
+ StringBuilder sb = new StringBuilder(64);
+ sb.append(startCol).append(method).append(endCol);
+ if (featureTypes != null)
+ {
+ Collections.sort(featureTypes);
+ sb.append(featureTypes.toString());
}
- else
- if (method==FEATURE_DENSITY)
- {
-
- // break ties between equivalent numbers for adjacent sequences by adding 1/Nseq*i on the original order
- double fr = 0.9/(1.0*seqs.length);
- for (int i=0;i