pub mod advanced_interactive;
pub mod backends;
pub mod calibration;
pub mod confusion_matrix;
pub mod helpers;
pub mod interactive;
pub mod learning_curve;
pub mod precision_recall;
pub mod roc_curve;
pub use advanced_interactive::{
CollaborationConfig, CollaborationManager, DashboardConfig, DashboardState, DataSource,
EventResponse, EventSystem, ExportConfig, InteractionConfig, InteractiveDashboard,
InteractiveWidget, LayoutConfig, LayoutManager, RealtimeConfig, RenderingEngine, ThemeConfig,
UpdateManager, WidgetConfig, WidgetEvent, WidgetType,
};
pub use backends::PlottingBackend;
pub use calibration::CalibrationVisualizer;
pub use confusion_matrix::ConfusionMatrixVisualizer;
pub use helpers::*;
pub use interactive::{
interactive_roc_curve_from_labels, interactive_roc_curve_visualization, InteractiveOptions,
InteractiveROCVisualizer,
};
pub use learning_curve::LearningCurveVisualizer;
pub use precision_recall::PrecisionRecallVisualizer;
pub use roc_curve::ROCCurveVisualizer;
use std::collections::HashMap;
use std::error::Error;
use std::path::Path;
pub trait MetricVisualizer {
fn prepare_data(&self) -> Result<VisualizationData, Box<dyn Error>>;
fn get_metadata(&self) -> VisualizationMetadata;
}
pub trait Visualization {
fn save_to_file(
&self,
path: impl AsRef<Path>,
options: Option<VisualizationOptions>,
) -> Result<(), Box<dyn Error>>;
fn render_svg(&self, options: Option<VisualizationOptions>) -> Result<Vec<u8>, Box<dyn Error>>;
fn render_png(&self, options: Option<VisualizationOptions>) -> Result<Vec<u8>, Box<dyn Error>>;
}
impl<T: MetricVisualizer> Visualization for T {
fn save_to_file(
&self,
path: impl AsRef<Path>,
options: Option<VisualizationOptions>,
) -> Result<(), Box<dyn Error>> {
let data = self.prepare_data()?;
let metadata = self.get_metadata();
let options = options.unwrap_or_default();
let backend = backends::default_backend();
backend.save_to_file(&data, &metadata, &options, path)?;
Ok(())
}
fn render_svg(&self, options: Option<VisualizationOptions>) -> Result<Vec<u8>, Box<dyn Error>> {
let data = self.prepare_data()?;
let metadata = self.get_metadata();
let options = options.unwrap_or_default();
let backend = backends::default_backend();
backend.render_svg(&data, &metadata, &options)
}
fn render_png(&self, options: Option<VisualizationOptions>) -> Result<Vec<u8>, Box<dyn Error>> {
let data = self.prepare_data()?;
let metadata = self.get_metadata();
let options = options.unwrap_or_default();
let backend = backends::default_backend();
backend.render_png(&data, &metadata, &options)
}
}
#[derive(Debug, Clone)]
pub struct VisualizationData {
pub x: Vec<f64>,
pub y: Vec<f64>,
pub z: Option<Vec<Vec<f64>>>,
pub series_names: Option<Vec<String>>,
pub x_labels: Option<Vec<String>>,
pub y_labels: Option<Vec<String>>,
pub auxiliary_data: HashMap<String, Vec<f64>>,
pub auxiliary_metadata: HashMap<String, String>,
pub series: HashMap<String, Vec<f64>>,
}
impl VisualizationData {
pub fn new() -> Self {
Self {
x: Vec::new(),
y: Vec::new(),
z: None,
series_names: None,
x_labels: None,
y_labels: None,
auxiliary_data: HashMap::new(),
auxiliary_metadata: HashMap::new(),
series: HashMap::new(),
}
}
pub fn add_series(&mut self, name: impl Into<String>, data: Vec<f64>) {
let name = name.into();
if self.x.is_empty() && name.to_lowercase().contains("x") {
self.x = data;
return;
}
if self.y.is_empty() && name.to_lowercase().contains("y") {
self.y = data;
return;
}
self.series.insert(name, data);
}
pub fn add_heatmap_data(&mut self, data: Vec<Vec<f64>>) {
self.z = Some(data);
}
pub fn add_x_labels(&mut self, labels: Vec<String>) {
self.x_labels = Some(labels);
}
pub fn add_y_labels(&mut self, labels: Vec<String>) {
self.y_labels = Some(labels);
}
pub fn add_series_names(&mut self, names: Vec<String>) {
self.series_names = Some(names);
}
pub fn add_auxiliary_data(&mut self, key: impl Into<String>, data: Vec<f64>) {
self.auxiliary_data.insert(key.into(), data);
}
pub fn add_auxiliary_metadata(&mut self, key: impl Into<String>, value: impl Into<String>) {
self.auxiliary_metadata.insert(key.into(), value.into());
}
}
impl Default for VisualizationData {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct VisualizationMetadata {
pub title: String,
pub x_label: String,
pub y_label: String,
pub plot_type: PlotType,
pub description: Option<String>,
}
impl VisualizationMetadata {
pub fn new(title: impl Into<String>) -> Self {
Self {
title: title.into(),
x_label: "X".to_string(),
y_label: "Y".to_string(),
plot_type: PlotType::Line,
description: None,
}
}
pub fn set_plot_type(&mut self, plottype: PlotType) {
self.plot_type = plottype;
}
pub fn set_x_label(&mut self, xlabel: impl Into<String>) {
self.x_label = xlabel.into();
}
pub fn set_y_label(&mut self, ylabel: impl Into<String>) {
self.y_label = ylabel.into();
}
pub fn set_description(&mut self, description: impl Into<String>) {
self.description = Some(description.into());
}
pub fn line_plot(
title: impl Into<String>,
x_label: impl Into<String>,
y_label: impl Into<String>,
) -> Self {
let mut metadata = Self::new(title);
metadata.set_plot_type(PlotType::Line);
metadata.set_x_label(x_label);
metadata.set_y_label(y_label);
metadata
}
pub fn scatter_plot(
title: impl Into<String>,
x_label: impl Into<String>,
y_label: impl Into<String>,
) -> Self {
let mut metadata = Self::new(title);
metadata.set_plot_type(PlotType::Scatter);
metadata.set_x_label(x_label);
metadata.set_y_label(y_label);
metadata
}
pub fn bar_chart(
title: impl Into<String>,
x_label: impl Into<String>,
y_label: impl Into<String>,
) -> Self {
let mut metadata = Self::new(title);
metadata.set_plot_type(PlotType::Bar);
metadata.set_x_label(x_label);
metadata.set_y_label(y_label);
metadata
}
pub fn heatmap(
title: impl Into<String>,
x_label: impl Into<String>,
y_label: impl Into<String>,
) -> Self {
let mut metadata = Self::new(title);
metadata.set_plot_type(PlotType::Heatmap);
metadata.set_x_label(x_label);
metadata.set_y_label(y_label);
metadata
}
pub fn histogram(
title: impl Into<String>,
x_label: impl Into<String>,
y_label: impl Into<String>,
) -> Self {
let mut metadata = Self::new(title);
metadata.set_plot_type(PlotType::Histogram);
metadata.set_x_label(x_label);
metadata.set_y_label(y_label);
metadata
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum PlotType {
Line,
Scatter,
Bar,
Heatmap,
Histogram,
}
#[derive(Debug, Clone, PartialEq)]
pub enum ColorMap {
BlueRed,
GreenRed,
Grayscale,
Viridis,
Magma,
}
#[derive(Debug, Clone)]
pub struct VisualizationOptions {
pub width: usize,
pub height: usize,
pub dpi: usize,
pub color_map: Option<ColorMap>,
pub show_grid: bool,
pub show_legend: bool,
pub title_font_size: Option<f64>,
pub label_font_size: Option<f64>,
pub tick_font_size: Option<f64>,
pub line_width: Option<f64>,
pub marker_size: Option<f64>,
pub show_colorbar: bool,
pub color_palette: Option<String>,
}
impl Default for VisualizationOptions {
fn default() -> Self {
VisualizationOptions {
width: 800,
height: 600,
dpi: 100,
color_map: None,
show_grid: true,
show_legend: true,
title_font_size: None,
label_font_size: None,
tick_font_size: None,
line_width: None,
marker_size: None,
show_colorbar: true,
color_palette: None,
}
}
}
impl VisualizationOptions {
pub fn new() -> Self {
Self::default()
}
pub fn with_width(mut self, width: usize) -> Self {
self.width = width;
self
}
pub fn with_height(mut self, height: usize) -> Self {
self.height = height;
self
}
pub fn with_dpi(mut self, dpi: usize) -> Self {
self.dpi = dpi;
self
}
pub fn with_color_map(mut self, colormap: ColorMap) -> Self {
self.color_map = Some(colormap);
self
}
pub fn with_grid(mut self, showgrid: bool) -> Self {
self.show_grid = showgrid;
self
}
pub fn with_legend(mut self, showlegend: bool) -> Self {
self.show_legend = showlegend;
self
}
pub fn with_font_sizes(
mut self,
title: Option<f64>,
label: Option<f64>,
tick: Option<f64>,
) -> Self {
self.title_font_size = title;
self.label_font_size = label;
self.tick_font_size = tick;
self
}
pub fn with_line_width(mut self, linewidth: f64) -> Self {
self.line_width = Some(linewidth);
self
}
pub fn with_marker_size(mut self, markersize: f64) -> Self {
self.marker_size = Some(markersize);
self
}
pub fn with_colorbar(mut self, showcolorbar: bool) -> Self {
self.show_colorbar = showcolorbar;
self
}
pub fn with_color_palette(mut self, colorpalette: impl Into<String>) -> Self {
self.color_palette = Some(colorpalette.into());
self
}
}