#[cfg(feature = "jupyter")]
use runmat_plot::jupyter::{JupyterBackend, OutputFormat};
use runmat_plot::plots::*;
#[test]
fn test_complete_2d_plotting_pipeline() {
let x_data = (0..100).map(|i| i as f64 * 0.1).collect::<Vec<_>>();
let y_data = x_data.iter().map(|&x| x.sin()).collect::<Vec<_>>();
let line_plot = LinePlot::new(x_data.clone(), y_data.clone())
.unwrap()
.with_label("sin(x)")
.with_style(glam::Vec4::new(1.0, 0.0, 0.0, 1.0), 2.0, LineStyle::Solid);
let scatter_data: Vec<f64> = (0..20).map(|i| (i as f64 * 0.5).cos()).collect();
let scatter_x: Vec<f64> = (0..20).map(|i| i as f64 * 0.5).collect();
let scatter_plot = ScatterPlot::new(scatter_x, scatter_data)
.unwrap()
.with_label("cos(x)")
.with_style(
glam::Vec4::new(0.0, 1.0, 0.0, 1.0),
5.0,
MarkerStyle::Circle,
);
let mut figure = Figure::new()
.with_title("2D Multi-Plot Example")
.with_labels("X", "Y")
.with_grid(true);
figure.add_line_plot(line_plot);
figure.add_scatter_plot(scatter_plot);
assert_eq!(figure.len(), 2);
assert!(figure.title.is_some());
assert!(figure.grid_enabled);
assert!(figure.legend_enabled);
let stats = figure.statistics();
assert_eq!(stats.total_plots, 2);
assert_eq!(stats.visible_plots, 2);
assert!(stats.total_memory_usage > 0);
let legend_entries = figure.legend_entries();
assert_eq!(legend_entries.len(), 2);
assert_eq!(legend_entries[0].label, "sin(x)");
assert_eq!(legend_entries[1].label, "cos(x)");
}
#[test]
fn test_3d_surface_plotting() {
let x_range = (-2.0, 2.0);
let y_range = (-2.0, 2.0);
let resolution = (20, 20);
let surface = SurfacePlot::from_function(x_range, y_range, resolution, |x, y| x * x - y * y)
.unwrap()
.with_colormap(ColorMap::Viridis)
.with_shading(ShadingMode::Smooth)
.with_alpha(0.8)
.with_label("Saddle Surface");
assert_eq!(surface.x_data.len(), 20);
assert_eq!(surface.y_data.len(), 20);
assert_eq!(surface.z_data.as_ref().unwrap().len(), 20);
assert_eq!(surface.colormap, ColorMap::Viridis);
assert_eq!(surface.shading_mode, ShadingMode::Smooth);
assert_eq!(surface.alpha, 0.8);
assert_eq!(surface.label, Some("Saddle Surface".to_string()));
let stats = surface.statistics();
assert_eq!(stats.grid_points, 400); assert_eq!(stats.triangle_count, 722); assert_eq!(stats.x_resolution, 20);
assert_eq!(stats.y_resolution, 20);
assert!(stats.memory_usage > 0);
let mut surface_mut = surface;
let bounds = surface_mut.bounds();
assert_eq!(bounds.min.x, -2.0);
assert_eq!(bounds.max.x, 2.0);
assert_eq!(bounds.min.y, -2.0);
assert_eq!(bounds.max.y, 2.0);
assert!(bounds.min.z >= -5.0 && bounds.min.z <= -3.0);
assert!(bounds.max.z >= 3.0 && bounds.max.z <= 5.0);
}
#[test]
fn test_colormap_functionality() {
let colormaps = vec![
ColorMap::Jet,
ColorMap::Hot,
ColorMap::Cool,
ColorMap::Viridis,
ColorMap::Plasma,
ColorMap::Gray,
];
for colormap in colormaps {
let color_0 = colormap.map_value(0.0);
let _color_half = colormap.map_value(0.5);
let color_1 = colormap.map_value(1.0);
assert!(color_0.x >= 0.0 && color_0.x <= 1.0);
assert!(color_0.y >= 0.0 && color_0.y <= 1.0);
assert!(color_0.z >= 0.0 && color_0.z <= 1.0);
assert!(color_1.x >= 0.0 && color_1.x <= 1.0);
assert!(color_1.y >= 0.0 && color_1.y <= 1.0);
assert!(color_1.z >= 0.0 && color_1.z <= 1.0);
if colormap != ColorMap::Gray {
assert_ne!(color_0, color_1);
}
}
let custom = ColorMap::Custom(
glam::Vec4::new(1.0, 0.0, 0.0, 1.0), glam::Vec4::new(0.0, 1.0, 0.0, 1.0), );
let custom_0 = custom.map_value(0.0);
let custom_1 = custom.map_value(1.0);
assert!(custom_0.x > custom_0.y); assert!(custom_1.y > custom_1.x); }
#[test]
fn test_matlab_compatibility_functions() {
use runmat_plot::plots::surface::matlab_compat as surf_compat;
let surf_x = vec![0.0, 1.0];
let surf_y = vec![0.0, 1.0];
let surf_z = vec![vec![0.0, 1.0], vec![1.0, 2.0]];
let surface = surf_compat::surf(surf_x.clone(), surf_y.clone(), surf_z.clone()).unwrap();
assert!(!surface.wireframe);
let mesh = surf_compat::mesh(surf_x, surf_y, surf_z).unwrap();
assert!(mesh.wireframe);
}
#[cfg(feature = "jupyter")]
#[test]
fn test_jupyter_integration() {
let backend = JupyterBackend::new();
assert_eq!(backend.output_format, OutputFormat::HTML);
let formats = vec![
OutputFormat::PNG,
OutputFormat::SVG,
OutputFormat::HTML,
OutputFormat::Base64,
OutputFormat::PlotlyJSON,
];
for format in formats {
let backend_fmt = JupyterBackend::with_format(format);
assert_eq!(backend_fmt.output_format, format);
}
let line_plot = LinePlot::new(vec![0.0, 1.0], vec![0.0, 1.0]).unwrap();
let mut backend = JupyterBackend::new();
let display_result = backend.display_line_plot(&line_plot);
assert!(display_result.is_ok());
}
#[test]
fn test_performance_characteristics() {
use runmat_time::Instant;
let large_size = 10_000;
let x_data: Vec<f64> = (0..large_size).map(|i| i as f64 * 0.001).collect();
let y_data: Vec<f64> = x_data
.iter()
.map(|&x| x.sin() + 0.1 * (10.0 * x).sin())
.collect();
let start = Instant::now();
let large_line_plot = LinePlot::new(x_data, y_data).unwrap();
let creation_time = start.elapsed();
assert!(creation_time.as_millis() < 100);
let memory_usage = large_line_plot.estimated_memory_usage();
let expected_min = large_size * 16; assert!(memory_usage >= expected_min);
let start = Instant::now();
let stats = large_line_plot.statistics();
let stats_time = start.elapsed();
assert!(stats_time.as_millis() < 10);
assert_eq!(stats.point_count, large_size);
let surface_start = Instant::now();
let large_surface = SurfacePlot::from_function((-5.0, 5.0), (-5.0, 5.0), (100, 100), |x, y| {
(x * x + y * y).sin()
})
.unwrap();
let surface_creation_time = surface_start.elapsed();
assert!(surface_creation_time.as_millis() < 1000);
let surface_stats = large_surface.statistics();
assert_eq!(surface_stats.grid_points, 10_000); assert_eq!(surface_stats.triangle_count, 19_602); }
#[test]
fn test_error_handling() {
let x = vec![0.0, 1.0, 2.0];
let y = vec![0.0, 1.0];
assert!(LinePlot::new(x.clone(), y.clone()).is_err());
assert!(ScatterPlot::new(x, y).is_err());
let empty_x: Vec<f64> = vec![];
let empty_y: Vec<f64> = vec![];
assert!(LinePlot::new(empty_x.clone(), empty_y.clone()).is_err());
assert!(ScatterPlot::new(empty_x, empty_y).is_err());
let surf_x = vec![0.0, 1.0];
let surf_y = vec![0.0, 1.0, 2.0];
let surf_z = vec![vec![0.0, 1.0], vec![1.0, 2.0]];
assert!(SurfacePlot::new(surf_x, surf_y, surf_z).is_err());
}
#[test]
fn test_memory_efficiency() {
let data_size = 1000;
let x_data: Vec<f64> = (0..data_size).map(|i| i as f64).collect();
let y_data: Vec<f64> = x_data.iter().map(|&x| x * 2.0).collect();
let line_plot = LinePlot::new(x_data.clone(), y_data.clone()).unwrap();
let initial_memory = line_plot.estimated_memory_usage();
let scatter_plot = ScatterPlot::new(x_data.clone(), y_data.clone()).unwrap();
let scatter_memory = scatter_plot.estimated_memory_usage();
let memory_ratio = scatter_memory as f64 / initial_memory as f64;
assert!(memory_ratio > 0.5 && memory_ratio < 2.0);
let mut line_plot_mut = line_plot;
let _vertices1 = line_plot_mut.generate_vertices();
let memory_after_cache = line_plot_mut.estimated_memory_usage();
assert!(memory_after_cache > initial_memory);
let _vertices2 = line_plot_mut.generate_vertices();
let memory_after_reuse = line_plot_mut.estimated_memory_usage();
assert_eq!(memory_after_cache, memory_after_reuse);
}
#[test]
fn test_plot_styling_and_customization() {
let x = vec![0.0, 1.0, 2.0];
let y = vec![0.0, 1.0, 0.0];
let styled_line = LinePlot::new(x.clone(), y.clone())
.unwrap()
.with_style(glam::Vec4::new(0.8, 0.2, 0.1, 0.9), 3.5, LineStyle::Dashed)
.with_label("Styled Line");
assert_eq!(styled_line.color, glam::Vec4::new(0.8, 0.2, 0.1, 0.9));
assert_eq!(styled_line.line_width, 3.5);
assert_eq!(styled_line.line_style, LineStyle::Dashed);
assert_eq!(styled_line.label, Some("Styled Line".to_string()));
let surface = SurfacePlot::new(
vec![0.0, 1.0],
vec![0.0, 1.0],
vec![vec![0.0, 1.0], vec![1.0, 2.0]],
)
.unwrap()
.with_colormap(ColorMap::Hot)
.with_shading(ShadingMode::Faceted)
.with_wireframe(true)
.with_alpha(0.7);
assert_eq!(surface.colormap, ColorMap::Hot);
assert_eq!(surface.shading_mode, ShadingMode::Faceted);
assert!(surface.wireframe);
assert_eq!(surface.alpha, 0.7);
}
#[test]
fn test_bounds_calculation_accuracy() {
let x = vec![-3.0, -1.0, 0.0, 2.0, 4.0];
let y = vec![-2.0, 0.0, 1.0, -1.0, 3.0];
let mut line_plot = LinePlot::new(x, y).unwrap();
let bounds = line_plot.bounds();
assert_eq!(bounds.min.x, -3.0);
assert_eq!(bounds.max.x, 4.0);
assert_eq!(bounds.min.y, -2.0);
assert_eq!(bounds.max.y, 3.0);
assert_eq!(bounds.min.z, 0.0); assert_eq!(bounds.max.z, 0.0);
let mut surface = SurfacePlot::from_function(
(-1.0, 1.0),
(-1.0, 1.0),
(3, 3),
|x, y| x + y, )
.unwrap();
let surface_bounds = surface.bounds();
assert_eq!(surface_bounds.min.x, -1.0);
assert_eq!(surface_bounds.max.x, 1.0);
assert_eq!(surface_bounds.min.y, -1.0);
assert_eq!(surface_bounds.max.y, 1.0);
assert_eq!(surface_bounds.min.z, -2.0); assert_eq!(surface_bounds.max.z, 2.0); }