plotlars/plots/array2dplot.rs
1use bon::bon;
2
3use plotly::{
4 Image as ImagePlotly,
5 Layout as LayoutPlotly,
6 Trace,
7 image::ColorModel,
8};
9
10use serde::Serialize;
11
12use crate::{
13 common::{Layout, PlotHelper},
14 components::{Axis, Rgb, Text},
15};
16
17/// A structure representing a 2D array plot.
18///
19/// The `Array2dPlot` struct allows for visualizing 2D arrays of RGB color values as images or heatmaps.
20/// Each element in the 2D array corresponds to a pixel, with its color defined by an `[u8; 3]` RGB triplet.
21/// This struct supports customizable titles, axis labels, and axis configurations for better presentation.
22///
23/// # Arguments
24///
25/// * `data` - A 2D vector of RGB triplets (`&[Vec<[u8; 3]>]`) representing pixel colors for the plot.
26/// * `plot_title` - An optional `Text` struct specifying the title of the plot.
27/// * `x_title` - An optional `Text` struct specifying the title of the x-axis.
28/// * `y_title` - An optional `Text` struct specifying the title of the y-axis.
29/// * `x_axis` - An optional reference to an `Axis` struct for customizing the x-axis.
30/// * `y_axis` - An optional reference to an `Axis` struct for customizing the y-axis.
31///
32/// # Example
33///
34/// ## Basic 2D Array Plot
35///
36/// ```rust
37/// use plotlars::{Array2dPlot, Plot, Text};
38///
39/// let data = vec![
40/// vec![[255, 0, 0], [0, 255, 0], [0, 0, 255]],
41/// vec![[0, 0, 255], [255, 0, 0], [0, 255, 0]],
42/// vec![[0, 255, 0], [0, 0, 255], [255, 0, 0]],
43/// ];
44///
45/// Array2dPlot::builder()
46/// .data(&data)
47/// .plot_title(
48/// Text::from("Array2D Plot")
49/// .font("Arial")
50/// .size(18)
51/// )
52/// .build()
53/// .plot();
54/// ```
55///
56/// 
57#[derive(Clone, Serialize)]
58pub struct Array2dPlot {
59 traces: Vec<Box<dyn Trace + 'static>>,
60 layout: LayoutPlotly,
61}
62
63#[bon]
64impl Array2dPlot {
65 #[builder(on(String, into), on(Text, into))]
66 pub fn new(
67 data: &[Vec<[u8; 3]>],
68 plot_title: Option<Text>,
69 x_title: Option<Text>,
70 y_title: Option<Text>,
71 x_axis: Option<&Axis>,
72 y_axis: Option<&Axis>,
73 ) -> Self {
74 let z_title = None;
75 let legend_title = None;
76 let z_axis = None;
77 let legend = None;
78
79 let layout = Self::create_layout(
80 plot_title,
81 x_title,
82 y_title,
83 None, // y2_title,
84 z_title,
85 legend_title,
86 x_axis,
87 y_axis,
88 None, // y2_axis,
89 z_axis,
90 legend,
91 );
92
93 let mut traces = vec![];
94
95 let trace = Self::create_trace(data);
96
97 traces.push(trace);
98
99 Self { traces, layout }
100 }
101
102 fn create_trace(data: &[Vec<[u8; 3]>]) -> Box<dyn Trace + 'static> {
103 let pixels = data
104 .iter()
105 .map(|row| {
106 row.iter()
107 .map(|&rgb| Rgb(rgb[0], rgb[1], rgb[2]).to_plotly())
108 .collect::<Vec<_>>()
109 })
110 .collect::<Vec<_>>();
111
112 ImagePlotly::new(pixels).color_model(ColorModel::RGB)
113 }
114}
115
116impl Layout for Array2dPlot {}
117
118impl PlotHelper for Array2dPlot {
119 fn get_layout(&self) -> &LayoutPlotly {
120 &self.layout
121 }
122
123 fn get_traces(&self) -> &Vec<Box<dyn Trace + 'static>> {
124 &self.traces
125 }
126}