1#[cfg(all(feature = "plotters", not(target_arch = "wasm32")))]
2use plotters::prelude::IntoDrawingArea;
3
4use crate::aes::Aes;
5use crate::annotate::Annotation;
6use crate::build::PlotBuilder;
7use crate::coord::cartesian::CoordCartesian;
8use crate::coord::fixed::CoordFixed;
9use crate::coord::flip::CoordFlip;
10use crate::coord::polar::CoordPolar;
11use crate::coord::Coord;
12use crate::data::{DataFrame, GGData, Value};
13use crate::facet::{Facet, FacetLabeller, FacetScales, FacetSpace};
14use crate::geom::area::GeomArea;
15use crate::geom::bar::GeomBar;
16use crate::geom::bin2d::GeomBin2d;
17use crate::geom::blank::GeomBlank;
18use crate::geom::boxplot::GeomBoxplot;
19use crate::geom::col::GeomCol;
20use crate::geom::contour::GeomContour;
21use crate::geom::count::GeomCount;
22use crate::geom::crossbar::GeomCrossbar;
23use crate::geom::curve::GeomCurve;
24use crate::geom::density::GeomDensity;
25use crate::geom::density2d::GeomDensity2d;
26use crate::geom::dotplot::GeomDotplot;
27use crate::geom::errorbar::GeomErrorbar;
28use crate::geom::freqpoly::GeomFreqpoly;
29use crate::geom::hex::GeomHex;
30use crate::geom::histogram::GeomHistogram;
31use crate::geom::jitter::GeomJitter;
32use crate::geom::line::GeomLine;
33use crate::geom::linerange::GeomLinerange;
34use crate::geom::path::GeomPath;
35use crate::geom::point::GeomPoint;
36use crate::geom::pointrange::GeomPointrange;
37use crate::geom::polygon::GeomPolygon;
38use crate::geom::qq::{GeomQQ, GeomQQLine};
39use crate::geom::rect::GeomRect;
40use crate::geom::refline::{GeomAbline, GeomHline, GeomVline};
41use crate::geom::ribbon::GeomRibbon;
42use crate::geom::rug::GeomRug;
43use crate::geom::segment::GeomSegment;
44use crate::geom::smooth::GeomSmooth;
45use crate::geom::spoke::GeomSpoke;
46use crate::geom::step::GeomStep;
47use crate::geom::text::{GeomLabel, GeomText};
48use crate::geom::tile::GeomTile;
49use crate::geom::violin::GeomViolin;
50use crate::geom::{Geom, GeomParams};
51use crate::position::Position;
52use crate::render::layout::PlotLayout;
53#[cfg(all(feature = "plotters", not(target_arch = "wasm32")))]
54use crate::render::plotters_backend::PlottersAdapter;
55use crate::render::renderer::PlotRenderer;
56use crate::render::RenderError;
57use crate::scale::continuous::ScaleContinuous;
58use crate::scale::transform::ScaleTransform;
59use crate::scale::Scale;
60use crate::stat::Stat;
61use crate::theme::Theme;
62
63mod stat_layers;
66
67#[derive(Clone, Debug, Default)]
69pub struct Labels {
70 pub title: Option<String>,
71 pub subtitle: Option<String>,
72 pub x: Option<String>,
73 pub y: Option<String>,
74 pub caption: Option<String>,
75 pub tag: Option<String>,
77}
78
79pub struct Layer {
81 pub data: Option<DataFrame>,
82 pub mapping: Aes,
83 pub geom: Box<dyn Geom>,
84 pub stat: Box<dyn Stat>,
85 pub position: Box<dyn Position>,
86 pub params: GeomParams,
87 pub show_legend: Option<bool>,
88 pub explicit_style: bool,
91}
92
93pub struct GGPlot {
95 pub(crate) data: DataFrame,
96 pub(crate) mapping: Aes,
97 pub(crate) layers: Vec<Layer>,
98 pub(crate) scales: Vec<Box<dyn Scale>>,
99 pub(crate) coord: Box<dyn Coord>,
100 pub(crate) theme: Theme,
101 pub(crate) labels: Labels,
102 pub(crate) facet: Facet,
103 pub(crate) annotations: Vec<Annotation>,
104 pub(crate) guide_legend: crate::guide::config::GuideLegend,
105 pub(crate) warnings: Vec<String>,
108 pub(crate) default_aspect_ratio: Option<f64>,
111 pub(crate) locale: Option<crate::locale::Locale>,
113 pub(crate) svg_root_data: bool,
118}
119
120impl GGPlot {
121 pub fn new(data: impl GGData) -> Self {
128 GGPlot {
129 data: data.into_dataframe(),
130 mapping: Aes::default(),
131 layers: Vec::new(),
132 scales: Vec::new(),
133 coord: Box::new(CoordCartesian::new()),
134 theme: Theme::default(),
135 labels: Labels::default(),
136 facet: Facet::default(),
137 annotations: Vec::new(),
138 guide_legend: crate::guide::config::GuideLegend::default(),
139 warnings: Vec::new(),
140 default_aspect_ratio: None,
141 locale: None,
142 svg_root_data: true,
143 }
144 }
145
146 pub fn aes(mut self, mapping: Aes) -> Self {
148 self.warnings.extend(mapping.warnings.iter().cloned());
149 self.mapping = mapping;
150 self
151 }
152
153 pub fn geom_point(self) -> Self {
156 self.add_geom(GeomPoint::default())
157 }
158
159 pub fn geom_point_with(self, geom: GeomPoint) -> Self {
160 self.add_geom_with(geom)
161 }
162
163 pub fn geom_line(self) -> Self {
164 self.add_geom(GeomLine::default())
165 }
166
167 pub fn geom_line_with(self, geom: GeomLine) -> Self {
168 self.add_geom_with(geom)
169 }
170
171 pub fn geom_bar(self) -> Self {
172 self.add_geom(GeomBar::default())
173 }
174
175 pub fn geom_bar_with(self, geom: GeomBar) -> Self {
176 self.add_geom_with(geom)
177 }
178
179 pub fn geom_histogram(self) -> Self {
180 self.add_geom(GeomHistogram::default())
181 }
182
183 pub fn geom_histogram_with(self, geom: GeomHistogram) -> Self {
184 self.add_geom_with(geom)
185 }
186
187 pub fn geom_boxplot(self) -> Self {
188 self.add_geom(GeomBoxplot::default())
189 }
190
191 pub fn geom_boxplot_with(self, geom: GeomBoxplot) -> Self {
192 self.add_geom_with(geom)
193 }
194
195 pub fn geom_smooth(self) -> Self {
196 self.add_geom(GeomSmooth::default())
197 }
198
199 pub fn geom_smooth_with(self, geom: GeomSmooth) -> Self {
200 self.add_geom_with(geom)
201 }
202
203 pub fn geom_col(self) -> Self {
204 self.add_geom(GeomCol::default())
205 }
206
207 pub fn geom_col_with(self, geom: GeomCol) -> Self {
208 self.add_geom_with(geom)
209 }
210
211 pub fn geom_hline(self, yintercept: f64) -> Self {
215 self.add_refline(
216 GeomHline::new(yintercept),
217 false,
218 &[("yintercept", yintercept)],
219 )
220 }
221
222 pub fn geom_hline_with(self, geom: GeomHline) -> Self {
224 let y = geom.yintercept;
225 self.add_refline(geom, true, &[("yintercept", y)])
226 }
227
228 pub fn geom_hline_aes(self, mapping: Aes) -> Self {
252 self.add_geom(GeomHline::mapped()).layer_aes(mapping)
253 }
254
255 pub fn geom_hline_aes_with(self, geom: GeomHline, mapping: Aes) -> Self {
257 self.add_geom_with(geom).layer_aes(mapping)
258 }
259
260 pub fn geom_vline(self, xintercept: f64) -> Self {
263 self.add_refline(
264 GeomVline::new(xintercept),
265 false,
266 &[("xintercept", xintercept)],
267 )
268 }
269
270 pub fn geom_vline_with(self, geom: GeomVline) -> Self {
272 let x = geom.xintercept;
273 self.add_refline(geom, true, &[("xintercept", x)])
274 }
275
276 pub fn geom_vline_aes(self, mapping: Aes) -> Self {
279 self.add_geom(GeomVline::mapped()).layer_aes(mapping)
280 }
281
282 pub fn geom_vline_aes_with(self, geom: GeomVline, mapping: Aes) -> Self {
284 self.add_geom_with(geom).layer_aes(mapping)
285 }
286
287 pub fn geom_abline(self, slope: f64, intercept: f64) -> Self {
290 self.add_refline(
291 GeomAbline::new(slope, intercept),
292 false,
293 &[("slope", slope), ("intercept", intercept)],
294 )
295 }
296
297 pub fn geom_abline_with(self, geom: GeomAbline) -> Self {
299 let (b, a) = (geom.slope, geom.intercept);
300 self.add_refline(geom, true, &[("slope", b), ("intercept", a)])
301 }
302
303 pub fn geom_abline_aes(self, mapping: Aes) -> Self {
306 self.add_geom(GeomAbline::mapped()).layer_aes(mapping)
307 }
308
309 pub fn geom_abline_aes_with(self, geom: GeomAbline, mapping: Aes) -> Self {
311 self.add_geom_with(geom).layer_aes(mapping)
312 }
313
314 fn add_refline(
317 self,
318 geom: impl Geom + 'static,
319 explicit: bool,
320 values: &[(&str, f64)],
321 ) -> Self {
322 let mut data = DataFrame::new();
323 let mut mapping = Aes::new();
324 for (col, v) in values {
325 data.add_column(col.to_string(), vec![Value::Float(*v)]);
326 mapping = match *col {
327 "xintercept" => mapping.xintercept(col),
328 "yintercept" => mapping.yintercept(col),
329 "slope" => mapping.slope(col),
330 _ => mapping.intercept(col),
331 };
332 }
333 let plot = if explicit {
334 self.add_geom_with(geom)
335 } else {
336 self.add_geom(geom)
337 };
338 plot.layer_aes(mapping).layer_data(data)
339 }
340
341 pub fn geom_text(self) -> Self {
342 self.add_geom(GeomText::default())
343 }
344
345 pub fn geom_text_with(self, geom: GeomText) -> Self {
346 self.add_geom_with(geom)
347 }
348
349 #[cfg(feature = "ggpubr")]
354 pub fn stat_cor(self) -> Self {
355 self.geom_text().stat(crate::stat::cor::StatCor::default())
356 }
357
358 #[cfg(feature = "ggpubr")]
361 pub fn stat_cor_with(self, stat: crate::stat::cor::StatCor) -> Self {
362 self.geom_text().stat(stat)
363 }
364
365 #[cfg(feature = "ggpubr")]
370 pub fn stat_compare_means(self) -> Self {
371 self.geom_text()
372 .stat(crate::stat::compare_means::StatCompareMeans::default())
373 }
374
375 #[cfg(feature = "ggpubr")]
378 pub fn stat_compare_means_with(
379 self,
380 stat: crate::stat::compare_means::StatCompareMeans,
381 ) -> Self {
382 self.geom_text().stat(stat)
383 }
384
385 #[cfg(feature = "ggpubr")]
391 pub fn stat_compare_means_pairwise(self, comparisons: &[(&str, &str)]) -> Self {
392 self.stat_compare_means_pairwise_with(
393 crate::stat::compare_means::CompareMethod::Auto,
394 comparisons,
395 )
396 }
397
398 #[cfg(feature = "ggpubr")]
401 pub fn stat_compare_means_pairwise_with(
402 self,
403 method: crate::stat::compare_means::CompareMethod,
404 comparisons: &[(&str, &str)],
405 ) -> Self {
406 let col_for = |a: crate::aes::Aesthetic| {
408 self.mapping
409 .mappings
410 .iter()
411 .find(|m| m.aesthetic == a)
412 .map(|m| m.column.clone())
413 };
414 let (xcol, ycol) = match (
415 col_for(crate::aes::Aesthetic::X),
416 col_for(crate::aes::Aesthetic::Y),
417 ) {
418 (Some(x), Some(y)) => (x, y),
419 _ => return self,
420 };
421 let (xc, yc) = match (self.data.column(&xcol), self.data.column(&ycol)) {
422 (Some(x), Some(y)) => (x, y),
423 _ => return self,
424 };
425
426 let mut groups: Vec<(String, Vec<f64>)> = Vec::new();
428 let mut ymax = f64::NEG_INFINITY;
429 let mut ymin = f64::INFINITY;
430 for (xv, yv) in xc.iter().zip(yc.iter()) {
431 let y = match yv.as_f64() {
432 Some(y) if y.is_finite() => y,
433 _ => continue,
434 };
435 ymax = ymax.max(y);
436 ymin = ymin.min(y);
437 let key = xv.to_group_key();
438 if let Some(g) = groups.iter_mut().find(|(k, _)| *k == key) {
439 g.1.push(y);
440 } else {
441 groups.push((key, vec![y]));
442 }
443 }
444 if groups.len() < 2 {
445 return self;
446 }
447 let step = if ymax > ymin {
448 (ymax - ymin) * 0.12
449 } else {
450 1.0
451 };
452
453 let (mut xmin_v, mut xmax_v, mut y_v, mut label_v) =
455 (Vec::new(), Vec::new(), Vec::new(), Vec::new());
456 let mut placed = 0usize;
457 for (a, b) in comparisons {
458 let ga = groups.iter().find(|(k, _)| k == a).map(|g| &g.1);
459 let gb = groups.iter().find(|(k, _)| k == b).map(|g| &g.1);
460 let (ga, gb) = match (ga, gb) {
461 (Some(x), Some(y)) if x.len() >= 2 && y.len() >= 2 => (x, y),
462 _ => continue,
463 };
464 let p = match crate::stat::compare_means::pairwise_p(method, ga, gb) {
465 Some(p) => p,
466 None => continue,
467 };
468 xmin_v.push(Value::Str((*a).to_string()));
469 xmax_v.push(Value::Str((*b).to_string()));
470 y_v.push(Value::Float(ymax + step * (placed as f64 + 1.0)));
471 label_v.push(Value::Str(crate::stat::cor::format_p_value(p)));
472 placed += 1;
473 }
474 if xmin_v.is_empty() {
475 return self;
476 }
477
478 let data = vec![
479 ("xmin".to_string(), xmin_v),
480 ("xmax".to_string(), xmax_v),
481 ("y".to_string(), y_v),
482 ("label".to_string(), label_v),
483 ];
484 self.add_geom(crate::geom::bracket::GeomBracket::default())
485 .layer_data(data)
486 .layer_aes(Aes::new().xmin("xmin").xmax("xmax").y("y").label("label"))
487 }
488
489 pub fn geom_bracket(self, xmin: &str, xmax: &str, y: f64, label: &str) -> Self {
494 self.geom_bracket_many(
495 crate::geom::bracket::GeomBracket::default(),
496 &[(xmin, xmax, y, label)],
497 )
498 }
499
500 pub fn geom_bracket_many(
504 self,
505 geom: crate::geom::bracket::GeomBracket,
506 brackets: &[(&str, &str, f64, &str)],
507 ) -> Self {
508 let xmin = brackets
509 .iter()
510 .map(|b| Value::Str(b.0.to_string()))
511 .collect::<Vec<_>>();
512 let xmax = brackets
513 .iter()
514 .map(|b| Value::Str(b.1.to_string()))
515 .collect::<Vec<_>>();
516 let y = brackets
517 .iter()
518 .map(|b| Value::Float(b.2))
519 .collect::<Vec<_>>();
520 let label = brackets
521 .iter()
522 .map(|b| Value::Str(b.3.to_string()))
523 .collect::<Vec<_>>();
524 let data = vec![
525 ("xmin".to_string(), xmin),
526 ("xmax".to_string(), xmax),
527 ("y".to_string(), y),
528 ("label".to_string(), label),
529 ];
530 self.add_geom(geom)
531 .layer_data(data)
532 .layer_aes(Aes::new().xmin("xmin").xmax("xmax").y("y").label("label"))
533 }
534
535 pub fn geom_bracket_table(
544 mut self,
545 table: impl GGData,
546 spec: crate::geom::bracket::BracketTable,
547 ) -> Self {
548 let table = table.into_dataframe();
549 let col_for = |a: crate::aes::Aesthetic| {
550 self.mapping
551 .mappings
552 .iter()
553 .find(|m| m.aesthetic == a)
554 .map(|m| m.column.clone())
555 };
556 let x_levels: Vec<String> = col_for(crate::aes::Aesthetic::X)
559 .and_then(|c| self.data.column(&c))
560 .filter(|col| col.iter().any(|v| matches!(v, Value::Str(_))))
561 .map(|col| {
562 let mut seen = std::collections::HashSet::new();
563 col.iter()
564 .filter(|v| !v.is_na())
565 .map(|v| v.to_group_key())
566 .filter(|k| seen.insert(k.clone()))
567 .collect()
568 })
569 .unwrap_or_default();
570 let y_range = col_for(crate::aes::Aesthetic::Y)
571 .and_then(|c| self.data.column(&c))
572 .and_then(|col| {
573 let (lo, hi) = col
574 .iter()
575 .filter_map(|v| v.as_f64())
576 .filter(|v| v.is_finite())
577 .fold((f64::INFINITY, f64::NEG_INFINITY), |(lo, hi), v| {
578 (lo.min(v), hi.max(v))
579 });
580 (lo <= hi).then_some((lo, hi))
581 });
582 let mut warnings = Vec::new();
583 let resolved = spec.resolve(&table, &x_levels, y_range, &mut warnings);
584 self.warnings.extend(warnings);
585 match resolved {
586 Some(data) => self
587 .add_geom(crate::geom::bracket::GeomBracket::from(spec.geom))
588 .layer_data(data)
589 .layer_aes(Aes::new().xmin("xmin").xmax("xmax").y("y").label("label")),
590 None => self,
591 }
592 }
593
594 pub fn geom_text_repel(self) -> Self {
599 self.add_geom(crate::geom::repel::GeomTextRepel::default())
600 }
601
602 pub fn geom_text_repel_with(self, geom: crate::geom::repel::GeomTextRepel) -> Self {
605 self.add_geom_with(geom)
606 }
607
608 pub fn geom_label_repel(self) -> Self {
611 self.add_geom(crate::geom::repel::GeomLabelRepel::default())
612 }
613
614 pub fn geom_label_repel_with(self, geom: crate::geom::repel::GeomLabelRepel) -> Self {
616 self.add_geom_with(geom)
617 }
618
619 pub fn geom_label(self) -> Self {
620 self.add_geom(GeomLabel::default())
621 }
622
623 pub fn geom_label_with(self, geom: GeomLabel) -> Self {
624 self.add_geom_with(geom)
625 }
626
627 pub fn geom_area(self) -> Self {
628 self.add_geom(GeomArea::default())
629 }
630
631 pub fn geom_area_with(self, geom: GeomArea) -> Self {
632 self.add_geom_with(geom)
633 }
634
635 pub fn geom_ribbon(self) -> Self {
636 self.add_geom(GeomRibbon::default())
637 }
638
639 pub fn geom_ribbon_with(self, geom: GeomRibbon) -> Self {
640 self.add_geom_with(geom)
641 }
642
643 pub fn geom_errorbar(self) -> Self {
644 self.add_geom(GeomErrorbar::default())
645 }
646
647 pub fn geom_errorbar_with(self, geom: GeomErrorbar) -> Self {
648 self.add_geom_with(geom)
649 }
650
651 pub fn geom_segment(self) -> Self {
652 self.add_geom(GeomSegment::default())
653 }
654
655 pub fn geom_segment_with(self, geom: GeomSegment) -> Self {
656 self.add_geom_with(geom)
657 }
658
659 pub fn geom_density(self) -> Self {
660 self.add_geom(GeomDensity::default())
661 }
662
663 pub fn geom_density_with(self, geom: GeomDensity) -> Self {
664 self.add_geom_with(geom)
665 }
666
667 pub fn geom_rug(self) -> Self {
668 self.add_geom(GeomRug::default())
669 }
670
671 pub fn geom_rug_with(self, geom: GeomRug) -> Self {
672 self.add_geom_with(geom)
673 }
674
675 pub fn geom_jitter(self) -> Self {
676 self.add_geom(GeomJitter::default())
677 }
678
679 pub fn geom_jitter_with(self, geom: GeomJitter) -> Self {
680 self.add_geom_with(geom)
681 }
682
683 pub fn geom_path(self) -> Self {
684 self.add_geom(GeomPath::default())
685 }
686
687 pub fn geom_path_with(self, geom: GeomPath) -> Self {
688 self.add_geom_with(geom)
689 }
690
691 pub fn stat_ellipse(self) -> Self {
693 self.geom_path()
694 .stat(crate::stat::ellipse::StatEllipse::default())
695 }
696
697 pub fn stat_ellipse_level(self, level: f64) -> Self {
699 self.geom_path()
700 .stat(crate::stat::ellipse::StatEllipse::new(level))
701 }
702
703 #[cfg(feature = "regression")]
706 pub fn stat_quantile(mut self, taus: &[f64]) -> Self {
707 for &tau in taus {
708 self = self
709 .geom_path()
710 .stat(crate::stat::quantile::StatQuantile::new(tau));
711 }
712 self
713 }
714
715 #[cfg(feature = "regression")]
717 pub fn geom_quantile(self) -> Self {
718 self.stat_quantile(&[0.25, 0.5, 0.75])
719 }
720
721 pub fn geom_step(self) -> Self {
722 self.add_geom(GeomStep::default())
723 }
724
725 pub fn geom_step_with(self, geom: GeomStep) -> Self {
726 self.add_geom_with(geom)
727 }
728
729 pub fn geom_freqpoly(self) -> Self {
730 self.add_geom(GeomFreqpoly::default())
731 }
732
733 pub fn geom_freqpoly_with(self, geom: GeomFreqpoly) -> Self {
734 self.add_geom_with(geom)
735 }
736
737 pub fn geom_linerange(self) -> Self {
738 self.add_geom(GeomLinerange::default())
739 }
740
741 pub fn geom_linerange_with(self, geom: GeomLinerange) -> Self {
742 self.add_geom_with(geom)
743 }
744
745 pub fn geom_pointrange(self) -> Self {
746 self.add_geom(GeomPointrange::default())
747 }
748
749 pub fn geom_pointrange_with(self, geom: GeomPointrange) -> Self {
750 self.add_geom_with(geom)
751 }
752
753 pub fn geom_crossbar(self) -> Self {
754 self.add_geom(GeomCrossbar::default())
755 }
756
757 pub fn geom_crossbar_with(self, geom: GeomCrossbar) -> Self {
758 self.add_geom_with(geom)
759 }
760
761 pub fn geom_spoke(self) -> Self {
762 self.add_geom(GeomSpoke::default())
763 }
764
765 pub fn geom_spoke_with(self, geom: GeomSpoke) -> Self {
766 self.add_geom_with(geom)
767 }
768
769 pub fn geom_rect(self) -> Self {
770 self.add_geom(GeomRect::default())
771 }
772
773 pub fn geom_rect_with(self, geom: GeomRect) -> Self {
774 self.add_geom_with(geom)
775 }
776
777 pub fn geom_tile(self) -> Self {
778 self.add_geom(GeomTile::default())
779 }
780
781 pub fn geom_tile_with(self, geom: GeomTile) -> Self {
782 self.add_geom_with(geom)
783 }
784
785 pub fn geom_raster(self) -> Self {
787 self.add_geom(crate::geom::raster::GeomRaster::default())
788 }
789
790 pub fn geom_raster_with(self, geom: crate::geom::raster::GeomRaster) -> Self {
791 self.add_geom_with(geom)
792 }
793
794 pub fn geom_polygon(self) -> Self {
795 self.add_geom(GeomPolygon::default())
796 }
797
798 pub fn geom_polygon_with(self, geom: GeomPolygon) -> Self {
799 self.add_geom_with(geom)
800 }
801
802 #[cfg(feature = "sf")]
804 pub fn geom_sf(self) -> Self {
805 self.add_geom(crate::geom::sf::GeomSf::default())
806 }
807
808 #[cfg(feature = "sf")]
809 pub fn geom_sf_with(self, geom: crate::geom::sf::GeomSf) -> Self {
810 self.add_geom_with(geom)
811 }
812
813 pub fn geom_curve(self) -> Self {
814 self.add_geom(GeomCurve::default())
815 }
816
817 pub fn geom_curve_with(self, geom: GeomCurve) -> Self {
818 self.add_geom_with(geom)
819 }
820
821 pub fn geom_violin(self) -> Self {
822 self.add_geom(GeomViolin::default())
823 }
824
825 pub fn geom_violin_with(self, geom: GeomViolin) -> Self {
826 self.add_geom_with(geom)
827 }
828
829 pub fn geom_dotplot(self) -> Self {
830 self.add_geom(GeomDotplot::default())
831 }
832
833 pub fn geom_dotplot_with(self, geom: GeomDotplot) -> Self {
834 self.add_geom_with(geom)
835 }
836
837 pub fn geom_qq(self) -> Self {
838 self.add_geom(GeomQQ::default())
839 }
840
841 pub fn geom_qq_with(self, geom: GeomQQ) -> Self {
842 self.add_geom_with(geom)
843 }
844
845 pub fn geom_qq_line(self) -> Self {
846 self.add_geom(GeomQQLine::default())
847 }
848
849 pub fn geom_qq_line_with(self, geom: GeomQQLine) -> Self {
850 self.add_geom_with(geom)
851 }
852
853 pub fn geom_bin2d(self) -> Self {
854 self.add_geom(GeomBin2d::default())
855 }
856
857 pub fn geom_bin2d_with(self, geom: GeomBin2d) -> Self {
858 self.add_geom_with(geom)
859 }
860
861 pub fn geom_hex(self) -> Self {
862 self.add_geom(GeomHex::default())
863 }
864
865 pub fn geom_hex_with(self, geom: GeomHex) -> Self {
866 self.add_geom_with(geom)
867 }
868
869 pub fn geom_count(self) -> Self {
870 self.add_geom(GeomCount::default())
871 }
872
873 pub fn geom_count_with(self, geom: GeomCount) -> Self {
874 self.add_geom_with(geom)
875 }
876
877 pub fn geom_contour(self) -> Self {
878 self.add_geom(GeomContour::default())
879 }
880
881 pub fn geom_contour_with(self, geom: GeomContour) -> Self {
882 self.add_geom_with(geom)
883 }
884
885 pub fn geom_contour_filled(self) -> Self {
888 self.add_geom(GeomPolygon {
889 line_width: 0.0,
890 alpha: 1.0,
891 ..GeomPolygon::default()
892 })
893 .stat(crate::stat::contour_filled::StatContourFilled::default())
894 }
895
896 pub fn geom_density2d(self) -> Self {
897 self.add_geom(GeomDensity2d::default())
898 }
899
900 pub fn geom_density2d_with(self, geom: GeomDensity2d) -> Self {
901 self.add_geom_with(geom)
902 }
903
904 pub fn geom_candlestick(self) -> Self {
907 self.add_geom(crate::geom::candlestick::GeomCandlestick::default())
908 }
909
910 pub fn geom_candlestick_with(self, geom: crate::geom::candlestick::GeomCandlestick) -> Self {
911 self.add_geom_with(geom)
912 }
913
914 pub fn geom_ohlc(self) -> Self {
917 self.add_geom(crate::geom::candlestick::GeomOhlc::default())
918 }
919
920 pub fn geom_ohlc_with(self, geom: crate::geom::candlestick::GeomOhlc) -> Self {
921 self.add_geom_with(geom)
922 }
923
924 pub fn geom_calendar(self) -> Self {
935 self.geom_calendar_with(
936 GeomTile {
937 color: (255, 255, 255),
938 line_width: 1.5,
939 ..Default::default()
940 },
941 false,
942 )
943 }
944
945 pub fn geom_calendar_with(mut self, tile: GeomTile, monday_first: bool) -> Self {
948 use crate::stat::calendar::{
949 day_number, month_boundaries, month_breaks, month_breaks_localized, weekday_labels,
950 CalendarGrid, StatCalendar, MAX_CALENDAR_YEARS,
951 };
952 let grid = self
953 .mapping
954 .get_mapping(&crate::aes::Aesthetic::X)
955 .and_then(|c| self.data.column(c))
956 .and_then(|col| {
957 CalendarGrid::from_days(col.iter().filter_map(day_number), monday_first)
958 });
959 let Some((grid, clipped)) = grid else {
960 return self.add_geom_with(tile).stat(StatCalendar {
962 grid: None,
963 monday_first,
964 });
965 };
966 if clipped {
967 self.warnings.push(format!(
968 "geom_calendar: dates more than {MAX_CALENDAR_YEARS} years before the newest were dropped"
969 ));
970 }
971 let (xb, _) = month_breaks(&grid);
972 let yb = if monday_first {
974 vec![6.0, 4.0, 2.0]
975 } else {
976 vec![5.0, 3.0, 1.0]
977 };
978 let segs = month_boundaries(&grid);
979 let col = |f: fn(&(f64, f64, f64, f64)) -> f64| -> Vec<Value> {
980 segs.iter().map(|s| Value::Float(f(s))).collect()
981 };
982 let boundaries = vec![
983 ("x".to_string(), col(|s| s.0)),
984 ("y".to_string(), col(|s| s.1)),
985 ("xend".to_string(), col(|s| s.2)),
986 ("yend".to_string(), col(|s| s.3)),
987 ];
988 self.default_aspect_ratio = Some(7.0 / grid.n_weeks().max(1) as f64);
989 let plot = self
990 .add_geom_with(tile)
991 .stat(StatCalendar {
992 grid: Some(grid),
993 monday_first,
994 })
995 .scale_x_continuous(
996 ScaleContinuous::new()
997 .with_breaks(xb)
998 .with_localized_labels(move |l| month_breaks_localized(&grid, l).1)
1000 .with_expand(0.0, 0.0),
1001 )
1002 .scale_y_continuous(
1003 ScaleContinuous::new()
1004 .with_breaks(yb)
1005 .with_localized_labels(weekday_labels)
1006 .with_expand(0.0, 0.0),
1007 );
1008 if segs.is_empty() {
1009 return plot;
1010 }
1011 plot.add_geom_with(crate::geom::segment::GeomCalendarBorder)
1013 .layer_data(boundaries)
1014 .layer_aes(Aes::new().x("x").y("y").xend("xend").yend("yend"))
1015 .show_legend(false)
1016 }
1017
1018 pub fn geom_blank(self) -> Self {
1019 self.add_geom(GeomBlank)
1020 }
1021
1022 fn add_geom_with(self, geom: impl Geom + 'static) -> Self {
1025 let mut plot = self.add_geom(geom);
1026 if let Some(layer) = plot.layers.last_mut() {
1027 layer.explicit_style = true;
1028 }
1029 plot
1030 }
1031
1032 fn add_geom(mut self, geom: impl Geom + 'static) -> Self {
1033 let stat = geom.default_stat();
1034 let position = geom.default_position();
1035 let params = geom.default_params();
1036 self.layers.push(Layer {
1037 data: None,
1038 mapping: Aes::default(),
1039 geom: Box::new(geom),
1040 stat,
1041 position,
1042 params,
1043 show_legend: None,
1044 explicit_style: false,
1045 });
1046 self
1047 }
1048
1049 pub fn stat(mut self, stat: impl Stat + 'static) -> Self {
1053 if let Some(layer) = self.layers.last_mut() {
1054 layer.stat = Box::new(stat);
1055 }
1056 self
1057 }
1058
1059 pub fn position(mut self, pos: impl Position + 'static) -> Self {
1061 if let Some(layer) = self.layers.last_mut() {
1062 layer.position = Box::new(pos);
1063 }
1064 self
1065 }
1066
1067 pub fn layer_data(mut self, data: impl GGData) -> Self {
1069 if let Some(layer) = self.layers.last_mut() {
1070 layer.data = Some(data.into_dataframe());
1071 }
1072 self
1073 }
1074
1075 pub fn layer_aes(mut self, mapping: Aes) -> Self {
1077 self.warnings.extend(mapping.warnings.iter().cloned());
1078 if let Some(layer) = self.layers.last_mut() {
1079 layer.mapping = mapping;
1080 }
1081 self
1082 }
1083
1084 pub fn show_legend(mut self, show: bool) -> Self {
1087 if let Some(layer) = self.layers.last_mut() {
1088 layer.show_legend = Some(show);
1089 }
1090 self
1091 }
1092
1093 pub fn scale_x_continuous(mut self, s: ScaleContinuous) -> Self {
1096 let s = s.for_aesthetic(crate::aes::Aesthetic::X);
1097 self.scales.push(Box::new(s));
1098 self
1099 }
1100
1101 pub fn scale_y_continuous(mut self, s: ScaleContinuous) -> Self {
1102 let s = s.for_aesthetic(crate::aes::Aesthetic::Y);
1103 self.scales.push(Box::new(s));
1104 self
1105 }
1106
1107 pub fn scale_x_discrete(mut self, s: crate::scale::discrete::ScaleDiscrete) -> Self {
1108 let s = s.for_aesthetic(crate::aes::Aesthetic::X);
1109 self.scales.push(Box::new(s));
1110 self
1111 }
1112
1113 pub fn scale_y_discrete(mut self, s: crate::scale::discrete::ScaleDiscrete) -> Self {
1114 let s = s.for_aesthetic(crate::aes::Aesthetic::Y);
1115 self.scales.push(Box::new(s));
1116 self
1117 }
1118
1119 pub fn scale_color(mut self, s: impl Scale + 'static) -> Self {
1120 self.scales.push(Box::new(s));
1121 self
1122 }
1123
1124 pub fn scale_fill(mut self, s: impl Scale + 'static) -> Self {
1125 self.scales.push(Box::new(s));
1126 self
1127 }
1128
1129 pub fn scale_color_manual(self, values: Vec<(&str, crate::scale::color::RGBAColor)>) -> Self {
1130 let s = crate::scale::manual::ScaleManual::new(crate::aes::Aesthetic::Color, values);
1131 self.scale_color(s)
1132 }
1133
1134 pub fn scale_fill_manual(self, values: Vec<(&str, crate::scale::color::RGBAColor)>) -> Self {
1135 let s = crate::scale::manual::ScaleManual::new(crate::aes::Aesthetic::Fill, values);
1136 self.scale_fill(s)
1137 }
1138
1139 pub fn scale_colour_identity(self) -> Self {
1142 let s = crate::scale::identity::ScaleColorIdentity::new(crate::aes::Aesthetic::Color);
1143 self.scale_color(s)
1144 }
1145
1146 pub fn scale_color_identity(self) -> Self {
1148 self.scale_colour_identity()
1149 }
1150
1151 pub fn scale_fill_identity(self) -> Self {
1154 let s = crate::scale::identity::ScaleColorIdentity::new(crate::aes::Aesthetic::Fill);
1155 self.scale_fill(s)
1156 }
1157
1158 pub fn scale_color_viridis(self) -> Self {
1159 use crate::scale::color::ScaleColorDiscrete;
1160 use crate::scale::palettes::PaletteName;
1161 let s = ScaleColorDiscrete::new(crate::aes::Aesthetic::Color)
1162 .with_named_palette(&PaletteName::Viridis);
1163 self.scale_color(s)
1164 }
1165
1166 pub fn scale_color_brewer(self, name: crate::scale::palettes::PaletteName) -> Self {
1167 use crate::scale::color::ScaleColorDiscrete;
1168 let s = ScaleColorDiscrete::new(crate::aes::Aesthetic::Color).with_named_palette(&name);
1169 self.scale_color(s)
1170 }
1171
1172 pub fn scale_color_gradient(
1173 self,
1174 low: crate::scale::color::RGBAColor,
1175 high: crate::scale::color::RGBAColor,
1176 ) -> Self {
1177 use crate::scale::color::ScaleColorContinuous;
1178 let s = ScaleColorContinuous::new(crate::aes::Aesthetic::Color).with_colors(low, high);
1179 self.scale_color(s)
1180 }
1181
1182 pub fn scale_fill_gradient(
1183 self,
1184 low: crate::scale::color::RGBAColor,
1185 high: crate::scale::color::RGBAColor,
1186 ) -> Self {
1187 use crate::scale::color::ScaleColorContinuous;
1188 let s = ScaleColorContinuous::new(crate::aes::Aesthetic::Fill).with_colors(low, high);
1189 self.scale_fill(s)
1190 }
1191
1192 pub fn scale_color_gradient2(
1193 self,
1194 low: crate::scale::color::RGBAColor,
1195 mid: crate::scale::color::RGBAColor,
1196 high: crate::scale::color::RGBAColor,
1197 ) -> Self {
1198 use crate::scale::gradient::ScaleColorGradient2;
1199 let s = ScaleColorGradient2::new(crate::aes::Aesthetic::Color).with_colors(low, mid, high);
1200 self.scale_color(s)
1201 }
1202
1203 pub fn scale_fill_gradient2(
1204 self,
1205 low: crate::scale::color::RGBAColor,
1206 mid: crate::scale::color::RGBAColor,
1207 high: crate::scale::color::RGBAColor,
1208 ) -> Self {
1209 use crate::scale::gradient::ScaleColorGradient2;
1210 let s = ScaleColorGradient2::new(crate::aes::Aesthetic::Fill).with_colors(low, mid, high);
1211 self.scale_fill(s)
1212 }
1213
1214 pub fn scale_fill_viridis(self) -> Self {
1215 use crate::scale::color::ScaleColorDiscrete;
1216 use crate::scale::palettes::PaletteName;
1217 let s = ScaleColorDiscrete::new(crate::aes::Aesthetic::Fill)
1218 .with_named_palette(&PaletteName::Viridis);
1219 self.scale_fill(s)
1220 }
1221
1222 pub fn scale_color_viridis_c(self) -> Self {
1224 use crate::scale::gradient_n::ScaleColorGradientN;
1225 let s = ScaleColorGradientN::viridis(crate::aes::Aesthetic::Color);
1226 self.scale_color(s)
1227 }
1228
1229 pub fn scale_fill_viridis_c(self) -> Self {
1231 use crate::scale::gradient_n::ScaleColorGradientN;
1232 let s = ScaleColorGradientN::viridis(crate::aes::Aesthetic::Fill);
1233 self.scale_fill(s)
1234 }
1235
1236 pub fn scale_color_gradientn(self, stops: Vec<(f64, crate::scale::color::RGBAColor)>) -> Self {
1238 use crate::scale::gradient_n::ScaleColorGradientN;
1239 let s = ScaleColorGradientN::new(crate::aes::Aesthetic::Color, stops);
1240 self.scale_color(s)
1241 }
1242
1243 pub fn scale_fill_gradientn(self, stops: Vec<(f64, crate::scale::color::RGBAColor)>) -> Self {
1245 use crate::scale::gradient_n::ScaleColorGradientN;
1246 let s = ScaleColorGradientN::new(crate::aes::Aesthetic::Fill, stops);
1247 self.scale_fill(s)
1248 }
1249
1250 pub fn scale_color_steps(
1253 self,
1254 low: crate::scale::color::RGBAColor,
1255 high: crate::scale::color::RGBAColor,
1256 n_bins: usize,
1257 ) -> Self {
1258 let s = crate::scale::steps::ScaleColorSteps::two(
1259 crate::aes::Aesthetic::Color,
1260 (low.r, low.g, low.b),
1261 (high.r, high.g, high.b),
1262 n_bins,
1263 );
1264 self.scale_color(s)
1265 }
1266
1267 pub fn scale_color_stepsn(
1269 self,
1270 stops: Vec<crate::scale::color::RGBAColor>,
1271 n_bins: usize,
1272 ) -> Self {
1273 let s = crate::scale::steps::ScaleColorSteps::new(
1274 crate::aes::Aesthetic::Color,
1275 stops.iter().map(|c| (c.r, c.g, c.b)).collect(),
1276 n_bins,
1277 );
1278 self.scale_color(s)
1279 }
1280
1281 pub fn scale_color_fermenter(
1283 self,
1284 name: crate::scale::palettes::PaletteName,
1285 n_bins: usize,
1286 ) -> Self {
1287 let stops = crate::scale::palettes::palette(&name)
1288 .iter()
1289 .map(|c| (c.r, c.g, c.b))
1290 .collect();
1291 let s =
1292 crate::scale::steps::ScaleColorSteps::new(crate::aes::Aesthetic::Color, stops, n_bins);
1293 self.scale_color(s)
1294 }
1295
1296 pub fn scale_fill_steps(
1298 self,
1299 low: crate::scale::color::RGBAColor,
1300 high: crate::scale::color::RGBAColor,
1301 n_bins: usize,
1302 ) -> Self {
1303 let s = crate::scale::steps::ScaleColorSteps::two(
1304 crate::aes::Aesthetic::Fill,
1305 (low.r, low.g, low.b),
1306 (high.r, high.g, high.b),
1307 n_bins,
1308 );
1309 self.scale_fill(s)
1310 }
1311
1312 pub fn scale_fill_fermenter(
1314 self,
1315 name: crate::scale::palettes::PaletteName,
1316 n_bins: usize,
1317 ) -> Self {
1318 let stops = crate::scale::palettes::palette(&name)
1319 .iter()
1320 .map(|c| (c.r, c.g, c.b))
1321 .collect();
1322 let s =
1323 crate::scale::steps::ScaleColorSteps::new(crate::aes::Aesthetic::Fill, stops, n_bins);
1324 self.scale_fill(s)
1325 }
1326
1327 pub fn scale_fill_discrete_sorted(self) -> Self {
1332 use crate::scale::color::ScaleColorDiscrete;
1333 self.scale_fill(ScaleColorDiscrete::new(crate::aes::Aesthetic::Fill).sorted())
1334 }
1335
1336 pub fn scale_color_discrete_sorted(self) -> Self {
1339 use crate::scale::color::ScaleColorDiscrete;
1340 self.scale_color(ScaleColorDiscrete::new(crate::aes::Aesthetic::Color).sorted())
1341 }
1342
1343 pub fn scale_fill_brewer(self, name: crate::scale::palettes::PaletteName) -> Self {
1344 use crate::scale::color::ScaleColorDiscrete;
1345 let s = ScaleColorDiscrete::new(crate::aes::Aesthetic::Fill).with_named_palette(&name);
1346 self.scale_fill(s)
1347 }
1348
1349 pub fn scale_linetype_manual(
1350 self,
1351 values: Vec<(&str, crate::render::backend::Linetype)>,
1352 ) -> Self {
1353 let s = crate::scale::linetype_manual::ScaleLinetypeManual::new(values);
1354 self.scale_color(s)
1355 }
1356
1357 pub fn scale_shape_manual(
1358 self,
1359 values: Vec<(&str, crate::render::backend::PointShape)>,
1360 ) -> Self {
1361 let s = crate::scale::shape_manual::ScaleShapeManual::new(values);
1362 self.scale_color(s)
1363 }
1364
1365 pub fn scale_color_grey(self) -> Self {
1366 let s = crate::scale::grey::ScaleColorGrey::new(crate::aes::Aesthetic::Color);
1367 self.scale_color(s)
1368 }
1369
1370 pub fn scale_fill_grey(self) -> Self {
1371 let s = crate::scale::grey::ScaleColorGrey::new(crate::aes::Aesthetic::Fill);
1372 self.scale_fill(s)
1373 }
1374
1375 pub fn scale_color_grey_with(self, s: crate::scale::grey::ScaleColorGrey) -> Self {
1376 self.scale_color(s)
1377 }
1378
1379 pub fn scale_fill_grey_with(self, s: crate::scale::grey::ScaleColorGrey) -> Self {
1380 self.scale_fill(s)
1381 }
1382
1383 pub fn scale_x_reverse(self) -> Self {
1384 self.scale_x_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Reverse))
1385 }
1386
1387 pub fn scale_y_reverse(self) -> Self {
1388 self.scale_y_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Reverse))
1389 }
1390
1391 pub fn scale_x_datetime(mut self, s: crate::scale::datetime::ScaleDateTime) -> Self {
1392 let s = s.for_aesthetic(crate::aes::Aesthetic::X);
1393 self.scales.push(Box::new(s));
1394 self
1395 }
1396
1397 pub fn scale_y_datetime(mut self, s: crate::scale::datetime::ScaleDateTime) -> Self {
1398 let s = s.for_aesthetic(crate::aes::Aesthetic::Y);
1399 self.scales.push(Box::new(s));
1400 self
1401 }
1402
1403 pub fn scale_size(mut self, s: crate::scale::size::ScaleSizeContinuous) -> Self {
1404 self.scales.push(Box::new(s));
1405 self
1406 }
1407
1408 pub fn scale_alpha(mut self, s: crate::scale::alpha::ScaleAlphaContinuous) -> Self {
1409 self.scales.push(Box::new(s));
1410 self
1411 }
1412
1413 pub fn scale_linewidth(mut self, s: crate::scale::linewidth::ScaleLinewidthContinuous) -> Self {
1417 self.scales.push(Box::new(s));
1418 self
1419 }
1420
1421 pub fn xlim(self, min: f64, max: f64) -> Self {
1422 self.scale_x_continuous(ScaleContinuous::new().with_limits(min, max))
1423 }
1424
1425 pub fn ylim(self, min: f64, max: f64) -> Self {
1426 self.scale_y_continuous(ScaleContinuous::new().with_limits(min, max))
1427 }
1428
1429 pub fn scale_x_log10(self) -> Self {
1430 self.scale_x_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Log10))
1431 }
1432
1433 pub fn scale_y_log10(self) -> Self {
1434 self.scale_y_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Log10))
1435 }
1436
1437 pub fn scale_x_sqrt(self) -> Self {
1438 self.scale_x_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Sqrt))
1439 }
1440
1441 pub fn scale_y_sqrt(self) -> Self {
1442 self.scale_y_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Sqrt))
1443 }
1444
1445 pub fn scale_x_log2(self) -> Self {
1446 self.scale_x_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Log2))
1447 }
1448
1449 pub fn scale_y_log2(self) -> Self {
1450 self.scale_y_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Log2))
1451 }
1452
1453 pub fn scale_x_ln(self) -> Self {
1454 self.scale_x_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Ln))
1455 }
1456
1457 pub fn scale_y_ln(self) -> Self {
1458 self.scale_y_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Ln))
1459 }
1460
1461 pub fn scale_x_logit(self) -> Self {
1463 self.scale_x_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Logit))
1464 }
1465
1466 pub fn scale_y_logit(self) -> Self {
1467 self.scale_y_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Logit))
1468 }
1469
1470 pub fn scale_x_probit(self) -> Self {
1472 self.scale_x_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Probit))
1473 }
1474
1475 pub fn scale_y_probit(self) -> Self {
1476 self.scale_y_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Probit))
1477 }
1478
1479 pub fn scale_x_pseudo_log(self) -> Self {
1481 self.scale_x_continuous(ScaleContinuous::new().with_transform(ScaleTransform::PseudoLog))
1482 }
1483
1484 pub fn scale_y_pseudo_log(self) -> Self {
1485 self.scale_y_continuous(ScaleContinuous::new().with_transform(ScaleTransform::PseudoLog))
1486 }
1487
1488 pub fn scale_x_reciprocal(self) -> Self {
1490 self.scale_x_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Reciprocal))
1491 }
1492
1493 pub fn scale_y_reciprocal(self) -> Self {
1494 self.scale_y_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Reciprocal))
1495 }
1496
1497 pub fn scale_x_exp(self) -> Self {
1499 self.scale_x_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Exp))
1500 }
1501
1502 pub fn scale_y_exp(self) -> Self {
1503 self.scale_y_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Exp))
1504 }
1505
1506 pub fn scale_x_boxcox(self, lambda: f64) -> Self {
1508 self.scale_x_continuous(
1509 ScaleContinuous::new().with_transform(ScaleTransform::BoxCox(lambda)),
1510 )
1511 }
1512
1513 pub fn scale_y_boxcox(self, lambda: f64) -> Self {
1514 self.scale_y_continuous(
1515 ScaleContinuous::new().with_transform(ScaleTransform::BoxCox(lambda)),
1516 )
1517 }
1518
1519 pub fn facet_wrap(mut self, var: &str, ncol: Option<usize>) -> Self {
1522 self.facet = Facet::Wrap {
1523 var: var.to_string(),
1524 ncol,
1525 scales: FacetScales::Fixed,
1526 labeller: FacetLabeller::default(),
1527 };
1528 self
1529 }
1530
1531 pub fn facet_wrap_free(mut self, var: &str, ncol: Option<usize>, scales: FacetScales) -> Self {
1532 self.facet = Facet::Wrap {
1533 var: var.to_string(),
1534 ncol,
1535 scales,
1536 labeller: FacetLabeller::default(),
1537 };
1538 self
1539 }
1540
1541 pub fn facet_wrap_labeller(
1542 mut self,
1543 var: &str,
1544 ncol: Option<usize>,
1545 labeller: FacetLabeller,
1546 ) -> Self {
1547 self.facet = Facet::Wrap {
1548 var: var.to_string(),
1549 ncol,
1550 scales: FacetScales::Fixed,
1551 labeller,
1552 };
1553 self
1554 }
1555
1556 pub fn facet_grid(mut self, row: Option<&str>, col: Option<&str>) -> Self {
1557 self.facet = Facet::Grid {
1558 row_var: row.map(String::from),
1559 col_var: col.map(String::from),
1560 scales: FacetScales::Fixed,
1561 labeller: FacetLabeller::default(),
1562 space: FacetSpace::Fixed,
1563 };
1564 self
1565 }
1566
1567 pub fn facet_grid_free(
1568 mut self,
1569 row: Option<&str>,
1570 col: Option<&str>,
1571 scales: FacetScales,
1572 ) -> Self {
1573 self.facet = Facet::Grid {
1574 row_var: row.map(String::from),
1575 col_var: col.map(String::from),
1576 scales,
1577 labeller: FacetLabeller::default(),
1578 space: FacetSpace::Fixed,
1579 };
1580 self
1581 }
1582
1583 pub fn facet_grid_multi(
1587 mut self,
1588 row: Option<&str>,
1589 cols: &[&str],
1590 scales: FacetScales,
1591 space: FacetSpace,
1592 ) -> Self {
1593 let col_var = if cols.len() > 1 {
1594 let n = self.data.nrows();
1596 let mut combined = Vec::with_capacity(n);
1597 for i in 0..n {
1598 let parts: Vec<String> = cols
1599 .iter()
1600 .map(|c| {
1601 self.data
1602 .column(c)
1603 .and_then(|col| col.get(i))
1604 .map(|v| v.to_group_key())
1605 .unwrap_or_default()
1606 })
1607 .collect();
1608 combined.push(crate::data::Value::Str(parts.join(" . ")));
1609 }
1610 let name = "__facet_cols__".to_string();
1611 self.data.add_column(name.clone(), combined);
1612 Some(name)
1613 } else {
1614 cols.first().map(|s| s.to_string())
1615 };
1616 self.facet = Facet::Grid {
1617 row_var: row.map(String::from),
1618 col_var,
1619 scales,
1620 labeller: FacetLabeller::default(),
1621 space,
1622 };
1623 self
1624 }
1625
1626 pub fn facet_grid_space(
1629 mut self,
1630 row: Option<&str>,
1631 col: Option<&str>,
1632 scales: FacetScales,
1633 space: FacetSpace,
1634 ) -> Self {
1635 self.facet = Facet::Grid {
1636 row_var: row.map(String::from),
1637 col_var: col.map(String::from),
1638 scales,
1639 labeller: FacetLabeller::default(),
1640 space,
1641 };
1642 self
1643 }
1644
1645 pub fn facet_grid_labeller(
1646 mut self,
1647 row: Option<&str>,
1648 col: Option<&str>,
1649 labeller: FacetLabeller,
1650 ) -> Self {
1651 self.facet = Facet::Grid {
1652 row_var: row.map(String::from),
1653 col_var: col.map(String::from),
1654 scales: FacetScales::Fixed,
1655 labeller,
1656 space: FacetSpace::Fixed,
1657 };
1658 self
1659 }
1660
1661 pub fn coord_flip(mut self) -> Self {
1664 self.coord = Box::new(CoordFlip);
1665 self
1666 }
1667
1668 pub fn coord_fixed(mut self, ratio: f64) -> Self {
1669 self.coord = Box::new(CoordFixed::new(ratio));
1670 self
1671 }
1672
1673 #[cfg(feature = "sf")]
1677 pub fn coord_sf(mut self) -> Self {
1678 self.coord = Box::new(crate::coord::sf::CoordSf::new());
1679 self
1680 }
1681
1682 #[cfg(feature = "sf")]
1687 pub fn coord_sf_with(mut self, coord: crate::coord::sf::CoordSf) -> Self {
1688 self.coord = Box::new(coord);
1689 self
1690 }
1691
1692 pub fn svg_root_data(mut self, on: bool) -> Self {
1699 self.svg_root_data = on;
1700 self
1701 }
1702
1703 pub fn coord_trans(mut self, x: Option<ScaleTransform>, y: Option<ScaleTransform>) -> Self {
1708 self.coord = Box::new(crate::coord::trans::CoordTrans::new(x, y));
1709 self
1710 }
1711
1712 pub fn coord_trans_y(self, y: ScaleTransform) -> Self {
1714 self.coord_trans(None, Some(y))
1715 }
1716
1717 pub fn coord_trans_x(self, x: ScaleTransform) -> Self {
1719 self.coord_trans(Some(x), None)
1720 }
1721
1722 pub fn coord_cartesian_zoom(
1724 mut self,
1725 xlim: Option<(f64, f64)>,
1726 ylim: Option<(f64, f64)>,
1727 ) -> Self {
1728 let mut c = CoordCartesian::new();
1729 if let Some((min, max)) = xlim {
1730 c = c.xlim(min, max);
1731 }
1732 if let Some((min, max)) = ylim {
1733 c = c.ylim(min, max);
1734 }
1735 self.coord = Box::new(c);
1736 self
1737 }
1738
1739 pub fn coord_polar(mut self) -> Self {
1740 self.coord = Box::new(CoordPolar::new());
1741 self
1742 }
1743
1744 pub fn coord_radar(mut self) -> Self {
1748 self.coord = Box::new(crate::coord::radar::CoordRadar::new());
1749 self
1750 }
1751
1752 pub fn coord_radar_with(mut self, coord: crate::coord::radar::CoordRadar) -> Self {
1753 self.coord = Box::new(coord);
1754 self
1755 }
1756
1757 pub fn coord_polar_with(mut self, coord: CoordPolar) -> Self {
1758 self.coord = Box::new(coord);
1759 self
1760 }
1761
1762 pub fn theme(mut self, theme: Theme) -> Self {
1767 self.apply_preset(theme);
1768 self
1769 }
1770
1771 fn apply_preset(&mut self, theme: Theme) {
1772 let primary = self.theme.primary;
1773 self.theme = theme;
1774 if self.theme.primary.is_none() {
1775 self.theme.primary = primary;
1776 }
1777 }
1778
1779 pub fn axis_text_x_angle(mut self, degrees: f64) -> Self {
1783 self.theme.axis_text_x.angle = degrees;
1784 self
1785 }
1786
1787 pub fn axis_text_y_angle(mut self, degrees: f64) -> Self {
1789 self.theme.axis_text_y.angle = degrees;
1790 self
1791 }
1792
1793 pub fn axis_text_x_dodge(mut self, n: usize) -> Self {
1796 self.theme.axis_text_x_dodge = n.max(1);
1797 self
1798 }
1799
1800 pub fn aspect_ratio(mut self, ratio: f64) -> Self {
1803 self.theme.aspect_ratio = Some(ratio);
1804 self
1805 }
1806
1807 pub fn panel_ontop(mut self) -> Self {
1809 self.theme.panel_ontop = true;
1810 self
1811 }
1812
1813 pub fn axis_minor_ticks(mut self) -> Self {
1815 self.theme.axis_minor_ticks = true;
1816 self
1817 }
1818
1819 pub fn title_position(mut self, pos: crate::theme::TitlePosition) -> Self {
1822 self.theme.title_position = pos;
1823 self
1824 }
1825
1826 pub fn tag_position(mut self, pos: crate::theme::TagPosition) -> Self {
1828 self.theme.tag_position = pos;
1829 self
1830 }
1831
1832 pub fn legend_direction(mut self, dir: crate::theme::LegendDirection) -> Self {
1834 self.theme.legend_direction = Some(dir);
1835 self
1836 }
1837
1838 pub fn legend_position_inside(mut self, x: f64, y: f64) -> Self {
1845 self.theme.legend_position = crate::theme::LegendPosition::Inside(x, y);
1846 self
1847 }
1848
1849 pub fn legend_position(mut self, pos: crate::theme::LegendPosition) -> Self {
1851 self.theme.legend_position = pos;
1852 self
1853 }
1854
1855 pub fn primary_color(mut self, color: (u8, u8, u8)) -> Self {
1856 self.theme.primary = Some(color);
1857 self
1858 }
1859
1860 pub fn theme_minimal(mut self) -> Self {
1861 self.apply_preset(crate::theme::presets::theme_minimal());
1862 self
1863 }
1864
1865 pub fn theme_bw(mut self) -> Self {
1866 self.apply_preset(crate::theme::presets::theme_bw());
1867 self
1868 }
1869
1870 pub fn theme_gray(mut self) -> Self {
1871 self.apply_preset(crate::theme::presets::theme_gray());
1872 self
1873 }
1874
1875 pub fn theme_classic(mut self) -> Self {
1876 self.apply_preset(crate::theme::presets::theme_classic());
1877 self
1878 }
1879
1880 pub fn theme_pubr(mut self) -> Self {
1882 self.apply_preset(crate::theme::presets::theme_pubr());
1883 self
1884 }
1885
1886 pub fn theme_linedraw(mut self) -> Self {
1887 self.apply_preset(crate::theme::presets::theme_linedraw());
1888 self
1889 }
1890
1891 pub fn theme_light(mut self) -> Self {
1892 self.apply_preset(crate::theme::presets::theme_light());
1893 self
1894 }
1895
1896 pub fn theme_dark(mut self) -> Self {
1897 self.apply_preset(crate::theme::presets::theme_dark());
1898 self
1899 }
1900
1901 pub fn theme_void(mut self) -> Self {
1902 self.apply_preset(crate::theme::presets::theme_void());
1903 self
1904 }
1905
1906 pub fn theme_update(mut self, update: crate::theme::ThemeUpdate) -> Self {
1909 self.theme = self.theme.update(update);
1910 self
1911 }
1912
1913 pub fn guides(mut self, guide: crate::guide::config::GuideLegend) -> Self {
1917 self.guide_legend = guide;
1918 self
1919 }
1920
1921 pub fn labs(mut self, labels: Labels) -> Self {
1924 if labels.title.is_some() {
1925 self.labels.title = labels.title;
1926 }
1927 if labels.subtitle.is_some() {
1928 self.labels.subtitle = labels.subtitle;
1929 }
1930 if labels.x.is_some() {
1931 self.labels.x = labels.x;
1932 }
1933 if labels.y.is_some() {
1934 self.labels.y = labels.y;
1935 }
1936 if labels.caption.is_some() {
1937 self.labels.caption = labels.caption;
1938 }
1939 if labels.tag.is_some() {
1940 self.labels.tag = labels.tag;
1941 }
1942 self
1943 }
1944
1945 pub fn title(mut self, title: &str) -> Self {
1946 self.labels.title = Some(title.to_string());
1947 self
1948 }
1949
1950 pub fn tag(mut self, tag: &str) -> Self {
1953 self.labels.tag = Some(tag.to_string());
1954 self
1955 }
1956
1957 pub fn subtitle(mut self, subtitle: &str) -> Self {
1958 self.labels.subtitle = Some(subtitle.to_string());
1959 self
1960 }
1961
1962 pub fn xlab(mut self, label: &str) -> Self {
1963 self.labels.x = Some(label.to_string());
1964 self
1965 }
1966
1967 pub fn ylab(mut self, label: &str) -> Self {
1968 self.labels.y = Some(label.to_string());
1969 self
1970 }
1971
1972 pub fn caption(mut self, caption: &str) -> Self {
1973 self.labels.caption = Some(caption.to_string());
1974 self
1975 }
1976
1977 pub fn annotate(mut self, annotation: Annotation) -> Self {
1981 self.annotations.push(annotation);
1982 self
1983 }
1984
1985 pub fn annotate_text(self, label: &str, x: f64, y: f64) -> Self {
1987 self.annotate(Annotation::text(label, x, y))
1988 }
1989
1990 pub fn annotate_rect(self, xmin: f64, xmax: f64, ymin: f64, ymax: f64) -> Self {
1992 self.annotate(Annotation::rect(xmin, xmax, ymin, ymax))
1993 }
1994
1995 pub fn annotate_segment(self, x: f64, y: f64, xend: f64, yend: f64) -> Self {
1997 self.annotate(Annotation::segment(x, y, xend, yend))
1998 }
1999
2000 pub fn locale(mut self, locale: crate::locale::Locale) -> Self {
2023 self.locale = Some(locale);
2024 self
2025 }
2026
2027 pub fn try_build(self) -> Result<crate::build::BuiltPlot, GGError> {
2031 PlotBuilder::build(self)
2032 }
2033
2034 pub fn build(self) -> crate::build::BuiltPlot {
2038 self.try_build().expect("plot build failed")
2039 }
2040
2041 #[cfg(all(feature = "plotters", not(target_arch = "wasm32")))]
2045 pub fn save(self, path: &str) -> Result<(), GGError> {
2046 self.save_with_size(path, 800, 600)
2047 }
2048
2049 #[cfg(all(feature = "plotters", not(target_arch = "wasm32")))]
2051 pub fn save_with_size(self, path: &str, w: u32, h: u32) -> Result<(), GGError> {
2052 let (built, layout) = self.prepare(w, h)?;
2053
2054 let ext = path.rsplit('.').next().unwrap_or("svg").to_lowercase();
2056
2057 match ext.as_str() {
2058 "svg" => {
2059 let backend = plotters::prelude::SVGBackend::new(path, (w, h));
2060 Self::render_into(backend.into_drawing_area(), &built, &layout)?;
2061 }
2062 "png" | "bmp" | "gif" | "jpeg" | "jpg" | "tiff" => {
2063 let backend = plotters::prelude::BitMapBackend::new(path, (w, h));
2064 Self::render_into(backend.into_drawing_area(), &built, &layout)?;
2065 }
2066 _ => {
2067 return Err(GGError::UnsupportedFormat(ext));
2068 }
2069 }
2070
2071 Ok(())
2072 }
2073
2074 #[cfg(all(feature = "plotters", not(target_arch = "wasm32")))]
2080 pub fn render_svg(self) -> Result<String, GGError> {
2081 self.render_svg_with_size(800, 600)
2082 }
2083
2084 #[cfg(all(feature = "plotters", not(target_arch = "wasm32")))]
2088 pub fn render_svg_with_size(self, w: u32, h: u32) -> Result<String, GGError> {
2089 let (built, layout) = self.prepare(w, h)?;
2090 let mut buf = String::new();
2091 {
2092 let backend = plotters::prelude::SVGBackend::with_string(&mut buf, (w, h));
2093 Self::render_into(backend.into_drawing_area(), &built, &layout)?;
2094 }
2095 Ok(buf)
2096 }
2097
2098 pub fn render_svg_native(self) -> Result<String, GGError> {
2102 self.render_svg_native_with_size(800, 600)
2103 }
2104
2105 pub fn render_svg_native_with_size(self, w: u32, h: u32) -> Result<String, GGError> {
2113 Ok(self.render_native(w, h)?.0.finish())
2114 }
2115
2116 pub fn render_svg_native_with_warnings(
2121 self,
2122 w: u32,
2123 h: u32,
2124 ) -> Result<(String, Vec<String>), GGError> {
2125 let (backend, warnings, _) = self.render_native(w, h)?;
2126 Ok((backend.finish(), warnings))
2127 }
2128
2129 pub fn render_svg_native_at(self, x: f64, y: f64, w: u32, h: u32) -> Result<String, GGError> {
2141 Ok(self.render_native(w, h)?.0.finish_fragment(x, y))
2142 }
2143
2144 pub fn render_svg_area_with_size(self, w: u32, h: u32) -> Result<(String, [f64; 4]), GGError> {
2148 let (backend, _, pa) = self.render_native(w, h)?;
2149 Ok((backend.finish(), [pa.x, pa.y, pa.width, pa.height]))
2150 }
2151
2152 fn render_native(
2156 self,
2157 w: u32,
2158 h: u32,
2159 ) -> Result<
2160 (
2161 crate::render::svg_backend::SvgBackend,
2162 Vec<String>,
2163 crate::render::Rect,
2164 ),
2165 GGError,
2166 > {
2167 let svg_root_data = self.svg_root_data;
2168 let (built, layout) = self.prepare(w, h)?;
2169 let pa = layout.plot_area.clone();
2170 let mut backend = crate::render::svg_backend::SvgBackend::new(w, h, pa.clone());
2171 if svg_root_data {
2172 backend.set_root_attrs(crate::render::svg_backend::root_data_attrs(&built));
2173 } else {
2174 backend.without_plot_attr();
2175 }
2176 PlotRenderer::render(&built, &mut backend).map_err(GGError::Render)?;
2177 let mut warnings = built.warnings;
2178 warnings.extend(backend.take_warnings());
2179 Ok((backend, warnings, pa))
2180 }
2181
2182 #[cfg(feature = "canvas")]
2187 pub fn render_rgba_with_size(self, w: u32, h: u32) -> Result<(u32, u32, Vec<u8>), GGError> {
2188 let (built, layout) = self.prepare(w, h)?;
2189 let mut backend =
2190 crate::render::pixel_backend::PixelBackend::new(w, h, layout.plot_area.clone());
2191 PlotRenderer::render(&built, &mut backend).map_err(GGError::Render)?;
2192 let (ow, oh) = backend.dimensions();
2193 Ok((ow, oh, backend.into_rgba()))
2194 }
2195
2196 #[cfg(feature = "canvas")]
2200 pub fn render_rgba_area_with_size(
2201 self,
2202 w: u32,
2203 h: u32,
2204 ) -> Result<(Vec<u8>, [f64; 4]), GGError> {
2205 let (built, layout) = self.prepare(w, h)?;
2206 let pa = layout.plot_area.clone();
2207 let mut backend = crate::render::pixel_backend::PixelBackend::new(w, h, pa.clone());
2208 PlotRenderer::render(&built, &mut backend).map_err(GGError::Render)?;
2209 Ok((backend.into_rgba(), [pa.x, pa.y, pa.width, pa.height]))
2210 }
2211
2212 #[cfg(feature = "canvas")]
2216 pub fn render_png_raster_with_size(self, w: u32, h: u32) -> Result<Vec<u8>, GGError> {
2217 let (built, layout) = self.prepare(w, h)?;
2218 let mut backend =
2219 crate::render::pixel_backend::PixelBackend::new(w, h, layout.plot_area.clone());
2220 PlotRenderer::render(&built, &mut backend).map_err(GGError::Render)?;
2221 backend.into_png().map_err(GGError::Render)
2222 }
2223
2224 #[cfg(all(feature = "plotters", not(target_arch = "wasm32")))]
2231 pub fn render_png(self) -> Result<Vec<u8>, GGError> {
2232 self.render_png_with_size(800, 600)
2233 }
2234
2235 #[cfg(all(feature = "plotters", not(target_arch = "wasm32")))]
2238 pub fn render_png_with_size(self, w: u32, h: u32) -> Result<Vec<u8>, GGError> {
2239 let (built, layout) = self.prepare(w, h)?;
2240
2241 let mut rgb = vec![0u8; (w as usize) * (h as usize) * 3];
2244 {
2245 let backend = plotters::prelude::BitMapBackend::with_buffer(&mut rgb, (w, h));
2246 Self::render_into(backend.into_drawing_area(), &built, &layout)?;
2247 }
2248
2249 let img = image::RgbImage::from_raw(w, h, rgb).ok_or_else(|| {
2250 GGError::Render(RenderError::BackendError(
2251 "PNG buffer size mismatch".to_string(),
2252 ))
2253 })?;
2254 let mut out = std::io::Cursor::new(Vec::new());
2255 img.write_to(&mut out, image::ImageOutputFormat::Png)
2256 .map_err(|e| GGError::Render(RenderError::BackendError(format!("{:?}", e))))?;
2257 Ok(out.into_inner())
2258 }
2259
2260 pub(crate) fn prepare(
2262 self,
2263 w: u32,
2264 h: u32,
2265 ) -> Result<(crate::build::BuiltPlot, PlotLayout), GGError> {
2266 let (mut built, meta) = self.build_for_render()?;
2267 let layout = Self::layout_built(&mut built, &meta, w, h);
2268 Ok((built, layout))
2269 }
2270
2271 pub(crate) fn build_for_render(self) -> Result<(crate::build::BuiltPlot, RenderMeta), GGError> {
2274 let plot = self;
2275
2276 let has_title = plot.labels.title.is_some();
2277 let has_subtitle = plot.labels.subtitle.is_some();
2278 let has_caption = plot.labels.caption.is_some();
2279 let has_legend = plot.has_legend_mapping();
2280 let x_label = plot.labels.x.clone();
2281 let y_label = plot.labels.y.clone();
2282
2283 let mut built = PlotBuilder::build(plot)?;
2284
2285 built.theme.resolve_inheritance();
2287
2288 if let Some(ref label) = x_label {
2290 if let Some(s) = built.scales.get_mut(&crate::aes::Aesthetic::X) {
2291 s.set_name(label);
2292 }
2293 }
2294 if let Some(ref label) = y_label {
2295 if let Some(s) = built.scales.get_mut(&crate::aes::Aesthetic::Y) {
2296 s.set_name(label);
2297 }
2298 }
2299
2300 Ok((
2301 built,
2302 RenderMeta {
2303 has_title,
2304 has_subtitle,
2305 has_caption,
2306 has_legend,
2307 },
2308 ))
2309 }
2310
2311 pub(crate) fn layout_built(
2314 built: &mut crate::build::BuiltPlot,
2315 meta: &RenderMeta,
2316 w: u32,
2317 h: u32,
2318 ) -> PlotLayout {
2319 let RenderMeta {
2320 has_title,
2321 has_subtitle,
2322 has_caption,
2323 has_legend,
2324 } = *meta;
2325 let x_axis_top = built
2326 .scales
2327 .get(&crate::aes::Aesthetic::X)
2328 .map(|s| s.axis_position_opposite())
2329 .unwrap_or(false);
2330
2331 let flipped = built.coord.is_flipped();
2335 let h_aes = if flipped {
2336 crate::aes::Aesthetic::Y
2337 } else {
2338 crate::aes::Aesthetic::X
2339 };
2340 let v_aes = if flipped {
2341 crate::aes::Aesthetic::X
2342 } else {
2343 crate::aes::Aesthetic::Y
2344 };
2345
2346 let x_rot: Option<(f64, f64)> =
2350 if built.theme.axis_text_x.visible && built.theme.axis_text_x.angle.abs() < 1.0 {
2351 built.scales.get(&h_aes).and_then(|hs| {
2352 if !hs.is_discrete() {
2353 return None;
2354 }
2355 let breaks = hs.breaks();
2356 let n = breaks.len().max(1) as f64;
2357 let max_ch = breaks
2358 .iter()
2359 .map(|(_, l)| l.chars().count())
2360 .max()
2361 .unwrap_or(0) as f64;
2362 let font = built.theme.axis_text_x.size;
2363 let label_w = max_ch * font * 0.6; let spacing = 0.9 * w as f64 / n; if label_w <= spacing {
2366 return None; }
2368 let vertical = label_w * 0.707 > spacing;
2372 let angle = if vertical { 270.0 } else { 45.0 };
2373 let drop = if vertical { label_w } else { label_w * 0.707 };
2374 Some((angle, drop + font + 4.0))
2375 })
2376 } else {
2377 None
2378 };
2379 let x_label_height = x_rot.map(|(_, drop)| drop);
2380 if let Some((angle, _)) = x_rot {
2381 built.theme.axis_text_x.angle = angle;
2382 }
2383
2384 let y_label_width = if built.theme.axis_text_y.visible {
2388 built.scales.get(&v_aes).map(|vs| {
2389 let max_ch = vs
2390 .breaks()
2391 .iter()
2392 .map(|(_, l)| l.chars().count())
2393 .max()
2394 .unwrap_or(0);
2395 let measured = max_ch as f64 * built.theme.axis_text_y.size * 0.6 + 4.0;
2396 let default = built.theme.axis_text_y.size * 3.5 + 4.0;
2397 measured.max(default).min(0.35 * w as f64)
2398 })
2399 } else {
2400 None
2401 };
2402
2403 PlotLayout::compute_full(
2404 w as f64,
2405 h as f64,
2406 &built.theme,
2407 has_title,
2408 has_subtitle,
2409 has_caption,
2410 has_legend,
2411 x_axis_top,
2412 y_label_width,
2413 x_label_height,
2414 )
2415 }
2416
2417 #[cfg(all(feature = "plotters", not(target_arch = "wasm32")))]
2420 fn render_into<DB>(
2421 area: plotters::drawing::DrawingArea<DB, plotters::coord::Shift>,
2422 built: &crate::build::BuiltPlot,
2423 layout: &PlotLayout,
2424 ) -> Result<(), GGError>
2425 where
2426 DB: plotters::prelude::DrawingBackend,
2427 DB::ErrorType: 'static,
2428 {
2429 area.fill(&plotters::prelude::WHITE)
2430 .map_err(|e| GGError::Render(RenderError::BackendError(format!("{:?}", e))))?;
2431 let mut adapter = PlottersAdapter::new(&area, layout.plot_area.clone());
2432 PlotRenderer::render(built, &mut adapter).map_err(GGError::Render)?;
2433 area.present()
2434 .map_err(|e| GGError::Render(RenderError::BackendError(format!("{:?}", e))))?;
2435 Ok(())
2436 }
2437
2438 #[cfg(all(feature = "plotters", not(target_arch = "wasm32")))]
2441 pub fn ggsave(
2442 self,
2443 path: &str,
2444 width_inches: f64,
2445 height_inches: f64,
2446 dpi: f64,
2447 ) -> Result<(), GGError> {
2448 let w = (width_inches * dpi) as u32;
2449 let h = (height_inches * dpi) as u32;
2450 self.save_with_size(path, w, h)
2451 }
2452
2453 fn has_legend_mapping(&self) -> bool {
2454 self.mapping.mappings.iter().any(|m| {
2455 matches!(
2456 m.aesthetic,
2457 crate::aes::Aesthetic::Color
2458 | crate::aes::Aesthetic::Fill
2459 | crate::aes::Aesthetic::Shape
2460 | crate::aes::Aesthetic::Linetype
2461 | crate::aes::Aesthetic::Size
2462 | crate::aes::Aesthetic::Alpha
2463 )
2464 })
2465 }
2466}
2467
2468#[derive(Clone, Copy, Debug)]
2470pub(crate) struct RenderMeta {
2471 pub(crate) has_title: bool,
2472 pub(crate) has_subtitle: bool,
2473 pub(crate) has_caption: bool,
2474 pub(crate) has_legend: bool,
2475}
2476
2477#[derive(Debug)]
2479pub enum GGError {
2480 Render(RenderError),
2481 UnsupportedFormat(String),
2482 Io(std::io::Error),
2483 ValidationError(String),
2484}
2485
2486impl std::fmt::Display for GGError {
2487 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2488 match self {
2489 GGError::Render(e) => write!(f, "Render error: {e}"),
2490 GGError::UnsupportedFormat(ext) => write!(f, "Unsupported output format: {ext}"),
2491 GGError::Io(e) => write!(f, "IO error: {e}"),
2492 GGError::ValidationError(msg) => write!(f, "Validation error: {msg}"),
2493 }
2494 }
2495}
2496
2497impl std::error::Error for GGError {}