1use super::{PlotContext, PlotData, Plotter};
2use crate::measurement::ValueFormatter;
3use crate::report::{BenchmarkId, ComparisonData, MeasurementData, ValueType};
4use plotters::data::float::pretty_print_float;
5use plotters::prelude::*;
6
7use crate::kde;
8use crate::stats::bivariate::Data;
9use crate::stats::univariate::Sample;
10
11static DEFAULT_FONT: FontFamily = FontFamily::SansSerif;
12static KDE_POINTS: usize = 500;
13static SIZE: (u32, u32) = (960, 540);
14static POINT_SIZE: u32 = 3;
15
16const DARK_BLUE: RGBColor = RGBColor(31, 120, 180);
17const DARK_ORANGE: RGBColor = RGBColor(255, 127, 0);
18const DARK_RED: RGBColor = RGBColor(227, 26, 28);
19
20mod distributions;
21mod iteration_times;
22mod pdf;
23mod regression;
24mod summary;
25mod t_test;
26
27fn convert_size(size: Option<(usize, usize)>) -> Option<(u32, u32)> {
28 if let Some((w, h)) = size {
29 return Some((w as u32, h as u32));
30 }
31 None
32}
33#[derive(Default)]
34pub struct PlottersBackend;
35
36#[allow(unused_variables)]
37impl Plotter for PlottersBackend {
38 fn pdf(&mut self, ctx: PlotContext<'_>, data: PlotData<'_>) {
39 if let Some(cmp) = data.comparison {
40 let (path, title) = if ctx.is_thumbnail {
41 (
42 ctx.context.report_path(ctx.id, "relative_pdf_small.svg"),
43 None,
44 )
45 } else {
46 (
47 ctx.context.report_path(ctx.id, "both/pdf.svg"),
48 Some(ctx.id.as_title()),
49 )
50 };
51 pdf::pdf_comparison_figure(
52 path.as_ref(),
53 title,
54 data.formatter,
55 data.measurements,
56 cmp,
57 convert_size(ctx.size),
58 );
59 return;
60 }
61 if ctx.is_thumbnail {
62 pdf::pdf_small(
63 ctx.id,
64 ctx.context,
65 data.formatter,
66 data.measurements,
67 convert_size(ctx.size),
68 );
69 } else {
70 pdf::pdf(
71 ctx.id,
72 ctx.context,
73 data.formatter,
74 data.measurements,
75 convert_size(ctx.size),
76 );
77 }
78 }
79
80 fn regression(&mut self, ctx: PlotContext<'_>, data: PlotData<'_>) {
81 let (title, path) = match (data.comparison.is_some(), ctx.is_thumbnail) {
82 (true, true) => (
83 None,
84 ctx.context
85 .report_path(ctx.id, "relative_regression_small.svg"),
86 ),
87 (true, false) => (
88 Some(ctx.id.as_title()),
89 ctx.context.report_path(ctx.id, "both/regression.svg"),
90 ),
91 (false, true) => (
92 None,
93 ctx.context.report_path(ctx.id, "regression_small.svg"),
94 ),
95 (false, false) => (
96 Some(ctx.id.as_title()),
97 ctx.context.report_path(ctx.id, "regression.svg"),
98 ),
99 };
100
101 if let Some(cmp) = data.comparison {
102 let base_data = Data::new(&cmp.base_iter_counts, &cmp.base_sample_times);
103 regression::regression_comparison_figure(
104 title,
105 path.as_path(),
106 data.formatter,
107 data.measurements,
108 cmp,
109 &base_data,
110 convert_size(ctx.size),
111 );
112 } else {
113 regression::regression_figure(
114 title,
115 path.as_path(),
116 data.formatter,
117 data.measurements,
118 convert_size(ctx.size),
119 );
120 }
121 }
122
123 fn iteration_times(&mut self, ctx: PlotContext<'_>, data: PlotData<'_>) {
124 let (title, path) = match (data.comparison.is_some(), ctx.is_thumbnail) {
125 (true, true) => (
126 None,
127 ctx.context
128 .report_path(ctx.id, "relative_iteration_times_small.svg"),
129 ),
130 (true, false) => (
131 Some(ctx.id.as_title()),
132 ctx.context.report_path(ctx.id, "both/iteration_times.svg"),
133 ),
134 (false, true) => (
135 None,
136 ctx.context.report_path(ctx.id, "iteration_times_small.svg"),
137 ),
138 (false, false) => (
139 Some(ctx.id.as_title()),
140 ctx.context.report_path(ctx.id, "iteration_times.svg"),
141 ),
142 };
143
144 if let Some(cmp) = data.comparison {
145 let base_data = Data::new(&cmp.base_iter_counts, &cmp.base_sample_times);
146 iteration_times::iteration_times_comparison_figure(
147 title,
148 path.as_path(),
149 data.formatter,
150 data.measurements,
151 cmp,
152 convert_size(ctx.size),
153 );
154 } else {
155 iteration_times::iteration_times_figure(
156 title,
157 path.as_path(),
158 data.formatter,
159 data.measurements,
160 convert_size(ctx.size),
161 );
162 }
163 }
164
165 fn abs_distributions(&mut self, ctx: PlotContext<'_>, data: PlotData<'_>) {
166 distributions::abs_distributions(
167 ctx.id,
168 ctx.context,
169 data.formatter,
170 data.measurements,
171 convert_size(ctx.size),
172 );
173 }
174
175 fn rel_distributions(&mut self, ctx: PlotContext<'_>, data: PlotData<'_>) {
176 distributions::rel_distributions(
177 ctx.id,
178 ctx.context,
179 data.measurements,
180 data.comparison.unwrap(),
181 convert_size(ctx.size),
182 );
183 }
184
185 fn line_comparison(
186 &mut self,
187 ctx: PlotContext<'_>,
188 formatter: &dyn ValueFormatter,
189 all_curves: &[&(&BenchmarkId, Vec<f64>)],
190 value_type: ValueType,
191 ) {
192 let path = ctx.line_comparison_path();
193 summary::line_comparison(
194 formatter,
195 ctx.id.as_title(),
196 all_curves,
197 &path,
198 value_type,
199 ctx.context.plot_config.summary_scale,
200 );
201 }
202
203 fn violin(
204 &mut self,
205 ctx: PlotContext<'_>,
206 formatter: &dyn ValueFormatter,
207 all_curves: &[&(&BenchmarkId, Vec<f64>)],
208 ) {
209 let violin_path = ctx.violin_path();
210
211 summary::violin(
212 formatter,
213 ctx.id.as_title(),
214 all_curves,
215 &violin_path,
216 ctx.context.plot_config.summary_scale,
217 );
218 }
219
220 fn t_test(&mut self, ctx: PlotContext<'_>, data: PlotData<'_>) {
221 let title = ctx.id.as_title();
222 let path = ctx.context.report_path(ctx.id, "change/t-test.svg");
223 t_test::t_test(
224 path.as_path(),
225 title,
226 data.comparison.unwrap(),
227 convert_size(ctx.size),
228 );
229 }
230
231 fn wait(&mut self) {}
232}
233