(
chart: &mut ChartContext<
DB,
Cartesian2d<plotters::coord::types::RangedCoordf64, plotters::coord::types::RangedCoordf64>,
>,
ir: &plotlars_core::ir::trace::BoxPlotIR,
| 246 | /// Draw vertical boxes: categories on x-axis, values on y-axis. |
| 247 | #[allow(clippy::too_many_arguments)] |
| 248 | fn draw_boxes_vertical<DB: DrawingBackend>( |
| 249 | chart: &mut ChartContext< |
| 250 | DB, |
| 251 | Cartesian2d<plotters::coord::types::RangedCoordf64, plotters::coord::types::RangedCoordf64>, |
| 252 | >, |
| 253 | ir: &plotlars_core::ir::trace::BoxPlotIR, |
| 254 | trace_idx: usize, |
| 255 | categories: &[String], |
| 256 | n_cats: usize, |
| 257 | n_groups: usize, |
| 258 | slot_width: f64, |
| 259 | box_width: f64, |
| 260 | has_legend: &mut bool, |
| 261 | legend_entries: &mut Vec<LegendEntry>, |
| 262 | ) { |
| 263 | let color = resolve_trace_color(&ir.marker, trace_idx); |
| 264 | let opacity = ir.marker.as_ref().and_then(|m| m.opacity).unwrap_or(1.0); |
| 265 | let fill_style = color.mix(opacity).filled(); |
| 266 | let line_style = ShapeStyle { |
| 267 | color: color.mix(opacity), |
| 268 | filled: false, |
| 269 | stroke_width: 2, |
| 270 | }; |
| 271 | |
| 272 | let labels = extract_strings(&ir.labels); |
| 273 | let values = extract_f64(&ir.values); |
| 274 | |
| 275 | let mut cat_values: Vec<Vec<f64>> = vec![Vec::new(); n_cats]; |
| 276 | for (label, val) in labels.iter().zip(values.iter()) { |
| 277 | if let Some(cat_idx) = categories.iter().position(|c| c == label) { |
| 278 | cat_values[cat_idx].push(*val); |
| 279 | } |
| 280 | } |
| 281 | |
| 282 | let group_offset = if n_groups > 1 { |
| 283 | (trace_idx as f64 - (n_groups as f64 - 1.0) / 2.0) * slot_width |
| 284 | } else { |
| 285 | 0.0 |
| 286 | }; |
| 287 | |
| 288 | for (cat_idx, mut vals) in cat_values.into_iter().enumerate() { |
| 289 | if vals.len() < 2 { |
| 290 | continue; |
| 291 | } |
| 292 | let stats = compute_box_stats(&mut vals); |
| 293 | let c = cat_idx as f64 + group_offset; |
| 294 | let hw = box_width / 2.0 * 0.9; |
| 295 | |
| 296 | chart |
| 297 | .draw_series(std::iter::once(Rectangle::new( |
| 298 | [(c - hw, stats.q1), (c + hw, stats.q3)], |
| 299 | fill_style, |
| 300 | ))) |
| 301 | .unwrap(); |
| 302 | chart |
| 303 | .draw_series(std::iter::once(PathElement::new( |
| 304 | vec![ |
| 305 | (c - hw, stats.q1), |
no test coverage detected