public static <S extends Sequence<S>> Alignment<S> leftTrimAlignment(Alignment<S> alignment,
                                                                         LinearGapAlignmentScoring<S> scoring) {
        S seq1 = alignment.getSequence1();
        AlignmentIteratorForward<S> iterator = alignment.forwardIterator();

        int score = 0;
        int minScore = 1;
        int minSeq1Position = 0, minSeq2Position = 0, minMutPointer = 0;

        while (iterator.advance()) {
            final int mut = iterator.getCurrentMutation();
            switch (Mutation.getRawTypeCode(mut)) {
                case RAW_MUTATION_TYPE_SUBSTITUTION:
                    score += scoring.getScore(Mutation.getFrom(mut), Mutation.getTo(mut));
                    break;

                case RAW_MUTATION_TYPE_DELETION:
                case RAW_MUTATION_TYPE_INSERTION:
                    score += scoring.getGapPenalty();
                    break;

                default:
                    byte c = seq1.codeAt(iterator.getSeq1Position());
                    score += scoring.getScore(c, c);
                    break;
            }

            // score <= minScore to maximally trim alignment with several equal trimming options
            if (score <= 0 && score <= minScore) {
                minScore = score;
                minSeq1Position = Mutation.isInsertion(mut) ? iterator.getSeq1Position() : iterator.getSeq1Position() + 1;
                minSeq2Position = Mutation.isDeletion(mut) ? iterator.getSeq2Position() : iterator.getSeq2Position() + 1;
                minMutPointer = iterator.getMutationsPointer();
            }
        }

        if (minScore == 1)
            return alignment;

        Mutations<S> mutations = alignment.getAbsoluteMutations();

        return new Alignment<>(seq1, mutations.getRange(minMutPointer + 1, mutations.size()),
                new Range(minSeq1Position, alignment.getSequence1Range().getTo()),
                new Range(minSeq2Position, alignment.getSequence2Range().getTo()),
                score - minScore);
    }
public static < S extends Sequence < S > > Alignment < S > leftTrimAlignment ( Alignment < S > alignment , LinearGapAlignmentScoring < S > scoring ) { S seq1 = alignment . getSequence1 ( ) ; AlignmentIteratorForward < S > iterator = alignment . forwardIterator ( ) ; int score = 0 ; int minScore = 1 ; int minSeq1Position = 0 , minSeq2Position = 0 , minMutPointer = 0 ; while ( iterator . advance ( ) ) { final int mut = iterator . getCurrentMutation ( ) ; switch ( Mutation . getRawTypeCode ( mut ) ) { case RAW_MUTATION_TYPE_SUBSTITUTION : score += scoring . getScore ( Mutation . getFrom ( mut ) , Mutation . getTo ( mut ) ) ; break ; case RAW_MUTATION_TYPE_DELETION : case RAW_MUTATION_TYPE_INSERTION : score += scoring . getGapPenalty ( ) ; break ; default : byte c = seq1 . codeAt ( iterator . getSeq1Position ( ) ) ; score += scoring . getScore ( c , c ) ; break ; } if ( score <= 0 && score <= minScore ) { minScore = score ; minSeq1Position = Mutation . isInsertion ( mut ) ? iterator . getSeq1Position ( ) : iterator . getSeq1Position ( ) + 1 ; minSeq2Position = Mutation . isDeletion ( mut ) ? iterator . getSeq2Position ( ) : iterator . getSeq2Position ( ) + 1 ; minMutPointer = iterator . getMutationsPointer ( ) ; } } if ( minScore == 1 ) return alignment ; Mutations < S > mutations = alignment . getAbsoluteMutations ( ) ; return new Alignment < > ( seq1 , mutations . getRange ( minMutPointer + 1 , mutations . size ( ) ) , new Range ( minSeq1Position , alignment . getSequence1Range ( ) . getTo ( ) ) , new Range ( minSeq2Position , alignment . getSequence2Range ( ) . getTo ( ) ) , score - minScore ) ; }
Try increase total alignment score by partially (or fully) trimming it from left side. If score can't be
increased the same alignment will be returned.

LinearGapAlignmentScoring case.

@param alignment input alignment
@param scoring   scoring
@return resulting alignment