#![cfg_attr(docsrs, feature(doc_cfg))]
#![doc(html_root_url = "https://docs.rs/data-matrix/0.2.0")]
#![doc = include_str!("../README.rustdoc.md")]
mod datamatrix_builder;
mod errors;
pub use crate::errors::Error;
use crate::Error::IncorrectMatrixLabels;
pub use datamatrix_builder::DataMatrixBuilder;
#[derive(Debug, Clone)]
pub struct DataMatrix {
data: Vec<Vec<f64>>,
row_labels: Vec<String>,
col_labels: Vec<String>,
}
impl DataMatrix {
pub fn new(
data: Vec<Vec<f64>>,
row_labels: Vec<String>,
col_labels: Vec<String>,
) -> Result<Self, Error> {
if data.len() != row_labels.len() {
return Err(IncorrectMatrixLabels {
expected: row_labels.len(),
actual: data.len(),
});
}
if data.is_empty() || data[0].len() != col_labels.len() {
return Err(IncorrectMatrixLabels {
expected: col_labels.len(),
actual: data[0].len(),
});
}
Ok(Self {
data,
row_labels,
col_labels,
})
}
pub fn nrows(&self) -> usize {
self.data.len()
}
pub fn ncols(&self) -> usize {
if let Some(first_row) = self.data.first() {
first_row.len()
} else {
0
}
}
pub fn get(&self, i: usize, j: usize) -> Option<f64> {
self.data.get(i).and_then(|row| row.get(j)).copied()
}
pub fn get_by_label(&self, row_label: &str, col_label: &str) -> Option<f64> {
let row_idx = self.row_labels.iter().position(|r| r == row_label)?;
let col_idx = self.col_labels.iter().position(|c| c == col_label)?;
self.get(row_idx, col_idx)
}
pub fn row_index(&self, label: &str) -> Option<usize> {
self.row_labels.iter().position(|r| r == label)
}
pub fn col_index(&self, label: &str) -> Option<usize> {
self.col_labels.iter().position(|r| r == label)
}
pub fn row_label(&self, index: usize) -> &String {
&self.row_labels[index]
}
pub fn col_label(&self, index: usize) -> &String {
&self.col_labels[index]
}
pub fn row_labels(&self) -> &[String] {
&self.row_labels
}
pub fn col_labels(&self) -> &[String] {
&self.col_labels
}
pub fn data(&self) -> &Vec<Vec<f64>> {
&self.data
}
pub fn is_square(&self) -> bool {
self.nrows() == self.ncols()
}
}