package jalview.analysis; import jalview.datamodel.AlignedCodon; import java.util.Comparator; /** * Implements rules for comparing two aligned codons, i.e. determining whether * they should occupy the same position in a translated protein alignment, or * one or the other should 'follow' (by preceded by a gap). * * @author gmcarstairs * */ public final class CodonComparator implements Comparator { @Override public int compare(AlignedCodon ac1, AlignedCodon ac2) { if (ac1 == null || ac2 == null || ac1.equals(ac2)) { return 0; } /** *
     * Case 1: if one starts before the other, and doesn't end after it, then it
     * precedes. We ignore the middle base position here.
     * A--GT
     * -CT-G
     * 
*/ if (ac1.pos1 < ac2.pos1 && ac1.pos3 <= ac2.pos3) { return -1; } if (ac2.pos1 < ac1.pos1 && ac2.pos3 <= ac1.pos3) { return 1; } /** *
     * Case 2: if one ends after the other, and doesn't start before it, then it
     * follows. We ignore the middle base position here.
     * -TG-A
     * G-TC
     * 
*/ if (ac1.pos3 > ac2.pos3 && ac1.pos1 >= ac2.pos1) { return 1; } if (ac2.pos3 > ac1.pos3 && ac2.pos1 >= ac1.pos1) { return -1; } /* * Case 3: if start and end match, compare middle base positions. */ if (ac1.pos1 == ac2.pos1 && ac1.pos3 == ac2.pos3) { return Integer.compare(ac1.pos2, ac2.pos2); } /* * That just leaves the 'enclosing' case - one codon starts after but ends * before the other. If the middle bases don't match, use their comparison * (majority vote). */ int compareMiddles = Integer.compare(ac1.pos2, ac2.pos2); if (compareMiddles != 0) { return compareMiddles; } /** *
     * Finally just leaves overlap with matching middle base, e.g. 
     * -A-A-A
     * G--GG 
     * In this case the choice is arbitrary whether to compare based on
     * first or last base position. We pick the first. Note this preserves
     * symmetricality of the comparison.
     * 
*/ return Integer.compare(ac1.pos1, ac2.pos1); } }