1 package jalview.analysis;
3 import jalview.datamodel.AlignmentAnnotation;
4 import jalview.datamodel.AlignmentI;
5 import jalview.datamodel.SequenceI;
7 import java.util.Arrays;
8 import java.util.Comparator;
11 * A helper class to sort all annotations associated with an alignment in
17 public class AnnotationSorter
20 private final AlignmentI alignment;
22 public AnnotationSorter(AlignmentI alignmentI)
24 this.alignment = alignmentI;
28 * Default comparator sorts as follows by annotation type within sequence
31 * <li>annotations with a reference to a sequence in the alignment are sorted
32 * on sequence ordering</li>
33 * <li>other annotations go 'at the end', with their mutual order unchanged</li>
34 * <li>within the same sequence ref, sort by label (non-case-sensitive)</li>
37 private final Comparator<? super AlignmentAnnotation> bySequenceAndType = new Comparator<AlignmentAnnotation>()
40 public int compare(AlignmentAnnotation o1, AlignmentAnnotation o2)
42 if (o1 == null && o2 == null)
56 * Ignore label (keep existing ordering) for
57 * Conservation/Quality/Consensus etc
59 if (o1.sequenceRef == null && o2.sequenceRef == null)
63 int sequenceOrder = compareSequences(o1, o2);
64 return sequenceOrder == 0 ? compareLabels(o1, o2) : sequenceOrder;
69 * This comparator sorts as follows by sequence order within annotation type
71 * <li>annotations with a reference to a sequence in the alignment are sorted
72 * on label (non-case-sensitive)</li>
73 * <li>other annotations go 'at the end', with their mutual order unchanged</li>
74 * <li>within the same label, sort by order of the related sequences</li>
77 private final Comparator<? super AlignmentAnnotation> byTypeAndSequence = new Comparator<AlignmentAnnotation>()
80 public int compare(AlignmentAnnotation o1, AlignmentAnnotation o2)
82 if (o1 == null && o2 == null)
96 * Ignore label (keep existing ordering) for
97 * Conservation/Quality/Consensus etc
99 if (o1.sequenceRef == null && o2.sequenceRef == null)
105 * Sort non-sequence-related after sequence-related.
107 if (o1.sequenceRef == null)
111 if (o2.sequenceRef == null)
115 int labelOrder = compareLabels(o1, o2);
116 return labelOrder == 0 ? compareSequences(o1, o2) : labelOrder;
121 * Sort by annotation type (label), within sequence order.
122 * Non-sequence-related annotations sort to the end.
124 * @param alignmentAnnotations
126 public void sortBySequenceAndType(
127 AlignmentAnnotation[] alignmentAnnotations)
129 if (alignmentAnnotations != null)
131 synchronized (alignmentAnnotations)
133 Arrays.sort(alignmentAnnotations, bySequenceAndType);
139 * Sort by sequence order within annotation type (label). Non-sequence-related
140 * annotations sort to the end.
142 * @param alignmentAnnotations
144 public void sortByTypeAndSequence(
145 AlignmentAnnotation[] alignmentAnnotations)
147 if (alignmentAnnotations != null)
149 synchronized (alignmentAnnotations)
151 Arrays.sort(alignmentAnnotations, byTypeAndSequence);
157 * Non-case-sensitive comparison of annotation labels. Returns zero if either
164 private int compareLabels(AlignmentAnnotation o1, AlignmentAnnotation o2)
166 if (o1 == null || o2 == null)
170 String label1 = o1.label;
171 String label2 = o2.label;
172 if (label1 == null && label2 == null)
184 return label1.toUpperCase().compareTo(label2.toUpperCase());
188 * Comparison based on position of associated sequence (if any) in the
189 * alignment. Returns zero if either argument is null.
195 private int compareSequences(AlignmentAnnotation o1,
196 AlignmentAnnotation o2)
198 SequenceI seq1 = o1.sequenceRef;
199 SequenceI seq2 = o2.sequenceRef;
200 if (seq1 == null && seq2 == null)
212 // get sequence index - but note -1 means 'at end' so needs special handling
213 int index1 = AlignmentUtils.getSequenceIndex(alignment, seq1);
214 int index2 = AlignmentUtils.getSequenceIndex(alignment, seq2);
215 if (index1 == index2)
227 return Integer.compare(index1, index2);