def align(self, sequence):
        """
        Aligns the primer to the given query sequence, returning a tuple of:

            hamming_distance, start, end

        Where hamming distance is the distance between the primer and aligned
        sequence, and start and end give the start and end index of the primer
        relative to the input sequence.
        """
        seq_aln, primer_aln, score, start, end = pairwise2.align.globalms(
            str(sequence).upper(), str(self.primer).upper(),
            self.match, self.difference, self.gap_open,
            self.gap_extend, one_alignment_only=True,
            penalize_end_gaps=self.penalize_end_gaps)[0]

        # Get an ungapped mapping on the sequence
        index_map = gap_index_map(seq_aln)
        ungap_map = ungap_index_map(primer_aln)

        # Trim to primer
        start = ungap_map[0]
        end = ungap_map[len(self.primer) - 1]

        trimmed = seq_aln[start:end + 1]

        ham_dist = hamming_distance(primer_aln[start:end + 1], trimmed,
                                    _iupac_ambiguous_equal)
        # assert primer_aln[start:end].replace('-', '') == str(self.primer)

        # TODO: handle start or end being gap better. For now, just give up
        # and return maxint for the hamming distance
        if trimmed.endswith('-'):
            tail = len(trimmed) - len(trimmed.rstrip('-'))
            end = index_map[end - tail] + 1
            ham_dist = sys.maxsize
        else:
            end = index_map[end]
        if trimmed.startswith('-'):
            start = 0
            ham_dist = sys.maxsize
        else:
            start = index_map[start]

        return ham_dist, start, end