pmcore/structs/
psi.rs

1use faer::Mat;
2use faer_ext::IntoFaer;
3use faer_ext::IntoNdarray;
4use ndarray::{Array2, ArrayView2};
5use pharmsol::prelude::simulator::psi;
6use pharmsol::Data;
7use pharmsol::Equation;
8use pharmsol::ErrorModel;
9
10use super::theta::Theta;
11
12/// [Psi] is a structure that holds the likelihood for each subject (row), for each support point (column)
13#[derive(Debug, Clone, PartialEq)]
14pub struct Psi {
15    matrix: Mat<f64>,
16}
17
18impl Psi {
19    pub fn new() -> Self {
20        Psi { matrix: Mat::new() }
21    }
22
23    pub fn matrix(&self) -> &Mat<f64> {
24        &self.matrix
25    }
26
27    pub fn nspp(&self) -> usize {
28        self.matrix.nrows()
29    }
30
31    pub fn nsub(&self) -> usize {
32        self.matrix.ncols()
33    }
34
35    /// Modify the [Psi::matrix] to only include the columns specified by `indices`
36    pub(crate) fn filter_column_indices(&mut self, indices: &[usize]) {
37        let matrix = self.matrix.to_owned();
38
39        let new = Mat::from_fn(matrix.nrows(), indices.len(), |r, c| {
40            *matrix.get(r, indices[c])
41        });
42
43        self.matrix = new;
44    }
45}
46
47impl Default for Psi {
48    fn default() -> Self {
49        Psi::new()
50    }
51}
52
53impl From<Array2<f64>> for Psi {
54    fn from(array: Array2<f64>) -> Self {
55        let matrix = array.view().into_faer().to_owned();
56        Psi { matrix }
57    }
58}
59
60impl From<Mat<f64>> for Psi {
61    fn from(matrix: Mat<f64>) -> Self {
62        Psi { matrix }
63    }
64}
65
66impl From<ArrayView2<'_, f64>> for Psi {
67    fn from(array_view: ArrayView2<'_, f64>) -> Self {
68        let matrix = array_view.into_faer().to_owned();
69        Psi { matrix }
70    }
71}
72
73impl From<&Array2<f64>> for Psi {
74    fn from(array: &Array2<f64>) -> Self {
75        let matrix = array.view().into_faer().to_owned();
76        Psi { matrix }
77    }
78}
79
80pub(crate) fn calculate_psi(
81    equation: &impl Equation,
82    subjects: &Data,
83    theta: &Theta,
84    error_model: &ErrorModel,
85    progress: bool,
86    cache: bool,
87) -> Psi {
88    let psi_ndarray = psi(
89        equation,
90        subjects,
91        &theta.matrix().clone().as_ref().into_ndarray().to_owned(),
92        error_model,
93        progress,
94        cache,
95    );
96
97    psi_ndarray.view().into()
98}