nale 0.1.2

Nale is a library that performs profile Hidden Markov Model (PHMM) biological sequence alignment.
Documentation
use crate::align::bounded::structs::RowBounds;
use crate::structs::dp_matrix::DpMatrix;
use crate::structs::Profile;

pub fn posterior_bounded(
    profile: &Profile,
    forward_matrix: &impl DpMatrix,
    backward_matrix: &impl DpMatrix,
    posterior_matrix: &mut impl DpMatrix,
    row_bounds: &RowBounds,
) {
    let overall_score: f32 = forward_matrix
        .get_special(row_bounds.target_end, Profile::SPECIAL_C_IDX)
        + profile.special_transition_score(Profile::SPECIAL_C_IDX, Profile::SPECIAL_MOVE_IDX);

    let mut denominator: f32;

    posterior_matrix.set_special(row_bounds.target_start - 1, Profile::SPECIAL_E_IDX, 0.0);
    posterior_matrix.set_special(row_bounds.target_start - 1, Profile::SPECIAL_N_IDX, 0.0);
    posterior_matrix.set_special(row_bounds.target_start - 1, Profile::SPECIAL_J_IDX, 0.0);
    posterior_matrix.set_special(row_bounds.target_start - 1, Profile::SPECIAL_B_IDX, 0.0);
    posterior_matrix.set_special(row_bounds.target_start - 1, Profile::SPECIAL_C_IDX, 0.0);

    let profile_start_in_first_row = row_bounds.left_row_bounds[row_bounds.target_start];
    let profile_end_in_first_row = row_bounds.right_row_bounds[row_bounds.target_start];

    for profile_idx in (profile_start_in_first_row - 1)..=profile_end_in_first_row {
        posterior_matrix.set_match(row_bounds.target_start - 1, profile_idx, 0.0);
        posterior_matrix.set_insert(row_bounds.target_start - 1, profile_idx, 0.0);
        posterior_matrix.set_delete(row_bounds.target_start - 1, profile_idx, 0.0);
    }

    for target_idx in row_bounds.target_start..=row_bounds.target_end {
        denominator = 0.0;

        let profile_start_in_current_row = row_bounds.left_row_bounds[target_idx];
        let profile_end_in_current_row = row_bounds.right_row_bounds[target_idx];

        posterior_matrix.set_match(target_idx, profile_start_in_current_row - 1, 0.0);
        posterior_matrix.set_insert(target_idx, profile_start_in_current_row - 1, 0.0);
        posterior_matrix.set_delete(target_idx, profile_start_in_current_row - 1, 0.0);

        for profile_idx in profile_start_in_current_row..profile_end_in_current_row {
            posterior_matrix.set_match(
                target_idx,
                profile_idx,
                (forward_matrix.get_match(target_idx, profile_idx)
                    + backward_matrix.get_match(target_idx, profile_idx)
                    - overall_score)
                    .exp(),
            );

            denominator += posterior_matrix.get_match(target_idx, profile_idx);

            posterior_matrix.set_insert(
                target_idx,
                profile_idx,
                (forward_matrix.get_insert(target_idx, profile_idx)
                    + backward_matrix.get_insert(target_idx, profile_idx)
                    - overall_score)
                    .exp(),
            );

            denominator += posterior_matrix.get_insert(target_idx, profile_idx);

            posterior_matrix.set_delete(target_idx, profile_idx, 0.0);
        }

        posterior_matrix.set_match(
            target_idx,
            profile_end_in_current_row,
            (forward_matrix.get_match(target_idx, profile_end_in_current_row)
                + backward_matrix.get_match(target_idx, profile_end_in_current_row)
                - overall_score)
                .exp(),
        );

        denominator += posterior_matrix.get_match(target_idx, profile_end_in_current_row);
        posterior_matrix.set_insert(target_idx, profile_end_in_current_row, 0.0);
        posterior_matrix.set_delete(target_idx, profile_end_in_current_row, 0.0);

        posterior_matrix.set_special(target_idx, Profile::SPECIAL_E_IDX, 0.0);

        posterior_matrix.set_special(
            target_idx,
            Profile::SPECIAL_N_IDX,
            (forward_matrix.get_special(target_idx - 1, Profile::SPECIAL_N_IDX)
                + backward_matrix.get_special(target_idx, Profile::SPECIAL_N_IDX)
                + profile
                    .special_transition_score(Profile::SPECIAL_N_IDX, Profile::SPECIAL_LOOP_IDX)
                - overall_score)
                .exp(),
        );

        posterior_matrix.set_special(
            target_idx,
            Profile::SPECIAL_J_IDX,
            (forward_matrix.get_special(target_idx - 1, Profile::SPECIAL_J_IDX)
                + backward_matrix.get_special(target_idx, Profile::SPECIAL_J_IDX)
                + profile
                    .special_transition_score(Profile::SPECIAL_J_IDX, Profile::SPECIAL_LOOP_IDX)
                - overall_score)
                .exp(),
        );

        posterior_matrix.set_special(target_idx, Profile::SPECIAL_B_IDX, 0.0);

        posterior_matrix.set_special(
            target_idx,
            Profile::SPECIAL_C_IDX,
            (forward_matrix.get_special(target_idx - 1, Profile::SPECIAL_C_IDX)
                + backward_matrix.get_special(target_idx, Profile::SPECIAL_C_IDX)
                + profile
                    .special_transition_score(Profile::SPECIAL_C_IDX, Profile::SPECIAL_LOOP_IDX)
                - overall_score)
                .exp(),
        );

        denominator += posterior_matrix.get_special(target_idx, Profile::SPECIAL_N_IDX);
        denominator += posterior_matrix.get_special(target_idx, Profile::SPECIAL_J_IDX);
        denominator += posterior_matrix.get_special(target_idx, Profile::SPECIAL_C_IDX);

        denominator = 1.0 / denominator;

        for profile_idx in profile_start_in_current_row..profile_end_in_current_row {
            posterior_matrix.set_match(
                target_idx,
                profile_idx,
                posterior_matrix.get_match(target_idx, profile_idx) * denominator,
            );

            posterior_matrix.set_insert(
                target_idx,
                profile_idx,
                posterior_matrix.get_insert(target_idx, profile_idx) * denominator,
            );
        }

        posterior_matrix.set_match(
            target_idx,
            profile_end_in_current_row,
            posterior_matrix.get_match(target_idx, profile_end_in_current_row) * denominator,
        );

        posterior_matrix.set_special(
            target_idx,
            Profile::SPECIAL_N_IDX,
            posterior_matrix.get_special(target_idx, Profile::SPECIAL_N_IDX) * denominator,
        );

        posterior_matrix.set_special(
            target_idx,
            Profile::SPECIAL_J_IDX,
            posterior_matrix.get_special(target_idx, Profile::SPECIAL_J_IDX) * denominator,
        );

        posterior_matrix.set_special(
            target_idx,
            Profile::SPECIAL_C_IDX,
            posterior_matrix.get_special(target_idx, Profile::SPECIAL_C_IDX) * denominator,
        );
    }
}