use faer::{Mat, MatRef};
use std::collections::BTreeMap;
use crate::prelude::*;
#[derive(Clone, Debug)]
pub struct NamedMatrix<'a, T> {
pub col_names: BTreeMap<String, usize>,
pub row_names: BTreeMap<String, usize>,
pub values: faer::MatRef<'a, T>,
}
impl<'a, T> NamedMatrix<'a, T>
where
T: BixverseFloat,
{
pub fn get_sub_mat(
&self,
rows_to_select: Option<&[&str]>,
cols_to_select: Option<&[&str]>,
) -> Option<Mat<T>> {
let row_indices: Vec<usize> = match rows_to_select {
None => (0..self.values.nrows()).collect(), Some(rows) => {
if rows.is_empty() {
return None;
}
let mut indices = Vec::new();
for &row_name in rows {
if let Some(&index) = self.row_names.get(row_name) {
indices.push(index);
}
}
if indices.is_empty() {
return None;
}
indices
}
};
let col_indices: Vec<usize> = match cols_to_select {
None => (0..self.values.ncols()).collect(), Some(cols) => {
if cols.is_empty() {
return None;
}
let mut indices = Vec::new();
for &col_name in cols {
if let Some(&index) = self.col_names.get(col_name) {
indices.push(index);
}
}
if indices.is_empty() {
return None;
}
indices
}
};
let mut result = Mat::<T>::zeros(row_indices.len(), col_indices.len());
for (new_row, &old_row) in row_indices.iter().enumerate() {
for (new_col, &old_col) in col_indices.iter().enumerate() {
result[(new_row, new_col)] = self.values[(old_row, old_col)];
}
}
Some(result)
}
pub fn get_full_mat(&self) -> Mat<T> {
self.get_sub_mat(None, None).unwrap()
}
pub fn get_rows(&self, rows_to_select: &[&str]) -> Option<Mat<T>> {
self.get_sub_mat(Some(rows_to_select), None)
}
pub fn get_cols(&self, cols_to_select: &[&str]) -> Option<Mat<T>> {
self.get_sub_mat(None, Some(cols_to_select))
}
pub fn get_col_names_refs(&self) -> Vec<&String> {
self.col_names.keys().collect()
}
pub fn get_row_names_refs(&self) -> Vec<&String> {
self.row_names.keys().collect()
}
pub fn get_row_indices(&self, rows_to_select: Option<&[&str]>) -> Vec<usize> {
let row_indices: Vec<usize> = match rows_to_select {
None => (0..self.values.nrows()).collect(), Some(rows) => {
if rows.is_empty() {
return vec![];
}
let mut indices = Vec::new();
for &row_name in rows {
if let Some(&index) = self.row_names.get(row_name) {
indices.push(index);
}
}
if indices.is_empty() {
return vec![];
}
indices
}
};
row_indices
}
pub fn get_col_indices(&self, cols_to_select: Option<&[&str]>) -> Vec<usize> {
let col_indices: Vec<usize> = match cols_to_select {
None => (0..self.values.ncols()).collect(), Some(cols) => {
if cols.is_empty() {
return vec![];
}
let mut indices = Vec::new();
for &col_name in cols {
if let Some(&index) = self.col_names.get(col_name) {
indices.push(index);
}
}
if indices.is_empty() {
return vec![];
}
indices
}
};
col_indices
}
}
#[derive(Clone, Debug)]
pub struct MatSliceView<'a, 'r, 'c, T> {
data: MatRef<'a, T>,
row_indices: &'r [usize],
col_indices: &'c [usize],
}
impl<'a, 'r, 'c, T> MatSliceView<'a, 'r, 'c, T>
where
T: BixverseFloat,
{
pub fn new(data: MatRef<'a, T>, row_indices: &'r [usize], col_indices: &'c [usize]) -> Self {
let max_col_index = col_indices.iter().max().copied().unwrap_or(0);
let max_row_index = row_indices.iter().max().copied().unwrap_or(0);
assert!(
max_col_index < data.ncols(),
"You selected indices larger than ncol."
);
assert!(
max_row_index < data.nrows(),
"You selected indices larger than nrow."
);
Self {
data,
row_indices,
col_indices,
}
}
pub fn nrows(&self) -> usize {
self.row_indices.len()
}
pub fn ncols(&self) -> usize {
self.col_indices.len()
}
pub fn to_owned(&self) -> Mat<T> {
Mat::from_fn(self.nrows(), self.ncols(), |i, j| {
*self.data.get(self.row_indices[i], self.col_indices[j])
})
}
}