use ndarray::{Array2, Axis, ShapeBuilder};
use rayon::prelude::*;
use crate::data::error_model::AssayErrorModels;
use crate::{Data, Equation, PharmsolError};
use super::progress::ProgressTracker;
pub fn log_likelihood_matrix(
equation: &impl Equation,
subjects: &Data,
support_points: &Array2<f64>,
error_models: &AssayErrorModels,
progress: bool,
) -> Result<Array2<f64>, PharmsolError> {
let mut log_psi: Array2<f64> = Array2::default((subjects.len(), support_points.nrows()).f());
let subjects_vec = subjects.subjects();
let progress_tracker = if progress {
let total = subjects_vec.len() * support_points.nrows();
println!(
"Computing log-likelihood matrix: {} subjects × {} support points...",
subjects_vec.len(),
support_points.nrows()
);
Some(ProgressTracker::new(total))
} else {
None
};
let result: Result<(), PharmsolError> = log_psi
.axis_iter_mut(Axis(0))
.into_par_iter()
.enumerate()
.try_for_each(|(i, mut row)| {
row.axis_iter_mut(Axis(0))
.into_par_iter()
.enumerate()
.try_for_each(|(j, mut element)| {
let subject = subjects_vec.get(i).unwrap();
match equation.estimate_log_likelihood(
subject,
&support_points.row(j).to_vec(),
error_models,
) {
Ok(log_likelihood) => {
element.fill(log_likelihood);
if let Some(ref tracker) = progress_tracker {
tracker.inc();
}
}
Err(e) => return Err(e),
};
Ok(())
})
});
if let Some(tracker) = progress_tracker {
tracker.finish();
}
result?;
Ok(log_psi)
}
#[deprecated(
since = "0.23.0",
note = "Use log_likelihood_matrix() with LikelihoodMatrixOptions instead"
)]
pub fn log_psi(
equation: &impl Equation,
subjects: &Data,
support_points: &Array2<f64>,
error_models: &AssayErrorModels,
progress: bool,
) -> Result<Array2<f64>, PharmsolError> {
log_likelihood_matrix(equation, subjects, support_points, error_models, progress)
}
#[deprecated(
since = "0.23.0",
note = "Use log_likelihood_matrix() instead and exponentiate if needed"
)]
pub fn psi(
equation: &impl Equation,
subjects: &Data,
support_points: &Array2<f64>,
error_models: &AssayErrorModels,
progress: bool,
) -> Result<Array2<f64>, PharmsolError> {
let log_psi_matrix =
log_likelihood_matrix(equation, subjects, support_points, error_models, progress)?;
Ok(log_psi_matrix.mapv(f64::exp))
}