nale 0.1.2

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

pub fn posterior(
    profile: &Profile,
    forward_matrix: &impl DpMatrix,
    backward_matrix: &impl DpMatrix,
    posterior_matrix: &mut impl DpMatrix,
) {
    let target_length = forward_matrix.target_length();
    let overall_score: f32 = forward_matrix.get_special(target_length, Profile::SPECIAL_C_IDX)
        + profile.special_transition_score(Profile::SPECIAL_C_IDX, Profile::SPECIAL_MOVE_IDX);
    let mut denominator: f32;

    posterior_matrix.set_special(0, Profile::SPECIAL_E_IDX, 0.0);
    posterior_matrix.set_special(0, Profile::SPECIAL_N_IDX, 0.0);
    posterior_matrix.set_special(0, Profile::SPECIAL_J_IDX, 0.0);
    posterior_matrix.set_special(0, Profile::SPECIAL_B_IDX, 0.0);
    posterior_matrix.set_special(0, Profile::SPECIAL_C_IDX, 0.0);

    for k in 0..=profile.length {
        posterior_matrix.set_match(0, k, 0.0);
        posterior_matrix.set_insert(0, k, 0.0);
        posterior_matrix.set_delete(0, k, 0.0);
    }

    for i in 1..=target_length {
        denominator = 0.0;
        posterior_matrix.set_match(i, 0, 0.0);
        posterior_matrix.set_insert(i, 0, 0.0);
        posterior_matrix.set_delete(i, 0, 0.0);

        for k in 1..profile.length {
            posterior_matrix.set_match(
                i,
                k,
                (forward_matrix.get_match(i, k) + backward_matrix.get_match(i, k) - overall_score)
                    .exp(),
            );

            denominator += posterior_matrix.get_match(i, k);

            posterior_matrix.set_insert(
                i,
                k,
                (forward_matrix.get_insert(i, k) + backward_matrix.get_insert(i, k)
                    - overall_score)
                    .exp(),
            );
            denominator += posterior_matrix.get_insert(i, k);

            posterior_matrix.set_delete(i, k, 0.0);
        }

        posterior_matrix.set_match(
            i,
            profile.length,
            (forward_matrix.get_match(i, profile.length)
                + backward_matrix.get_match(i, profile.length)
                - overall_score)
                .exp(),
        );

        denominator += posterior_matrix.get_match(i, profile.length);
        posterior_matrix.set_insert(i, profile.length, 0.0);
        posterior_matrix.set_delete(i, profile.length, 0.0);

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

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

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

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

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

        denominator = 1.0 / denominator;

        for k in 1..profile.length {
            posterior_matrix.set_match(i, k, posterior_matrix.get_match(i, k) * denominator);
            posterior_matrix.set_insert(i, k, posterior_matrix.get_insert(i, k) * denominator);
        }
        posterior_matrix.set_match(
            i,
            profile.length,
            posterior_matrix.get_match(i, profile.length) * denominator,
        );
        posterior_matrix.set_special(
            i,
            Profile::SPECIAL_N_IDX,
            posterior_matrix.get_special(i, Profile::SPECIAL_N_IDX) * denominator,
        );
        posterior_matrix.set_special(
            i,
            Profile::SPECIAL_J_IDX,
            posterior_matrix.get_special(i, Profile::SPECIAL_J_IDX) * denominator,
        );
        posterior_matrix.set_special(
            i,
            Profile::SPECIAL_C_IDX,
            posterior_matrix.get_special(i, Profile::SPECIAL_C_IDX) * denominator,
        );
    }
}