1#[cfg(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(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
63#[derive(Clone, Debug, Default)]
65pub struct Labels {
66 pub title: Option<String>,
67 pub subtitle: Option<String>,
68 pub x: Option<String>,
69 pub y: Option<String>,
70 pub caption: Option<String>,
71 pub tag: Option<String>,
73}
74
75pub struct Layer {
77 pub data: Option<DataFrame>,
78 pub mapping: Aes,
79 pub geom: Box<dyn Geom>,
80 pub stat: Box<dyn Stat>,
81 pub position: Box<dyn Position>,
82 pub params: GeomParams,
83 pub show_legend: Option<bool>,
84}
85
86pub struct GGPlot {
88 pub(crate) data: DataFrame,
89 pub(crate) mapping: Aes,
90 pub(crate) layers: Vec<Layer>,
91 pub(crate) scales: Vec<Box<dyn Scale>>,
92 pub(crate) coord: Box<dyn Coord>,
93 pub(crate) theme: Theme,
94 pub(crate) labels: Labels,
95 pub(crate) facet: Facet,
96 pub(crate) annotations: Vec<Annotation>,
97 pub(crate) guide_legend: crate::guide::config::GuideLegend,
98}
99
100impl GGPlot {
101 pub fn new(data: impl GGData) -> Self {
103 GGPlot {
104 data: data.into_dataframe(),
105 mapping: Aes::default(),
106 layers: Vec::new(),
107 scales: Vec::new(),
108 coord: Box::new(CoordCartesian::new()),
109 theme: Theme::default(),
110 labels: Labels::default(),
111 facet: Facet::default(),
112 annotations: Vec::new(),
113 guide_legend: crate::guide::config::GuideLegend::default(),
114 }
115 }
116
117 pub fn aes(mut self, mapping: Aes) -> Self {
119 self.mapping = mapping;
120 self
121 }
122
123 pub fn geom_point(self) -> Self {
126 self.add_geom(GeomPoint::default())
127 }
128
129 pub fn geom_point_with(self, geom: GeomPoint) -> Self {
130 self.add_geom(geom)
131 }
132
133 pub fn geom_line(self) -> Self {
134 self.add_geom(GeomLine::default())
135 }
136
137 pub fn geom_line_with(self, geom: GeomLine) -> Self {
138 self.add_geom(geom)
139 }
140
141 pub fn geom_bar(self) -> Self {
142 self.add_geom(GeomBar::default())
143 }
144
145 pub fn geom_bar_with(self, geom: GeomBar) -> Self {
146 self.add_geom(geom)
147 }
148
149 pub fn geom_histogram(self) -> Self {
150 self.add_geom(GeomHistogram::default())
151 }
152
153 pub fn geom_histogram_with(self, geom: GeomHistogram) -> Self {
154 self.add_geom(geom)
155 }
156
157 pub fn geom_boxplot(self) -> Self {
158 self.add_geom(GeomBoxplot::default())
159 }
160
161 pub fn geom_boxplot_with(self, geom: GeomBoxplot) -> Self {
162 self.add_geom(geom)
163 }
164
165 pub fn geom_smooth(self) -> Self {
166 self.add_geom(GeomSmooth::default())
167 }
168
169 pub fn geom_smooth_with(self, geom: GeomSmooth) -> Self {
170 self.add_geom(geom)
171 }
172
173 pub fn geom_col(self) -> Self {
174 self.add_geom(GeomCol::default())
175 }
176
177 pub fn geom_col_with(self, geom: GeomCol) -> Self {
178 self.add_geom(geom)
179 }
180
181 pub fn geom_hline(self, yintercept: f64) -> Self {
182 self.add_geom(GeomHline::new(yintercept))
183 }
184
185 pub fn geom_hline_with(self, geom: GeomHline) -> Self {
187 self.add_geom(geom)
188 }
189
190 pub fn geom_vline(self, xintercept: f64) -> Self {
191 self.add_geom(GeomVline::new(xintercept))
192 }
193
194 pub fn geom_vline_with(self, geom: GeomVline) -> Self {
196 self.add_geom(geom)
197 }
198
199 pub fn geom_abline(self, slope: f64, intercept: f64) -> Self {
200 self.add_geom(GeomAbline::new(slope, intercept))
201 }
202
203 pub fn geom_abline_with(self, geom: GeomAbline) -> Self {
205 self.add_geom(geom)
206 }
207
208 pub fn geom_text(self) -> Self {
209 self.add_geom(GeomText::default())
210 }
211
212 pub fn geom_text_with(self, geom: GeomText) -> Self {
213 self.add_geom(geom)
214 }
215
216 #[cfg(feature = "ggpubr")]
221 pub fn stat_cor(self) -> Self {
222 self.geom_text().stat(crate::stat::cor::StatCor::default())
223 }
224
225 #[cfg(feature = "ggpubr")]
228 pub fn stat_cor_with(self, stat: crate::stat::cor::StatCor) -> Self {
229 self.geom_text().stat(stat)
230 }
231
232 #[cfg(feature = "ggpubr")]
237 pub fn stat_compare_means(self) -> Self {
238 self.geom_text()
239 .stat(crate::stat::compare_means::StatCompareMeans::default())
240 }
241
242 #[cfg(feature = "ggpubr")]
245 pub fn stat_compare_means_with(
246 self,
247 stat: crate::stat::compare_means::StatCompareMeans,
248 ) -> Self {
249 self.geom_text().stat(stat)
250 }
251
252 #[cfg(feature = "ggpubr")]
258 pub fn stat_compare_means_pairwise(self, comparisons: &[(&str, &str)]) -> Self {
259 self.stat_compare_means_pairwise_with(
260 crate::stat::compare_means::CompareMethod::Auto,
261 comparisons,
262 )
263 }
264
265 #[cfg(feature = "ggpubr")]
268 pub fn stat_compare_means_pairwise_with(
269 self,
270 method: crate::stat::compare_means::CompareMethod,
271 comparisons: &[(&str, &str)],
272 ) -> Self {
273 let col_for = |a: crate::aes::Aesthetic| {
275 self.mapping
276 .mappings
277 .iter()
278 .find(|m| m.aesthetic == a)
279 .map(|m| m.column.clone())
280 };
281 let (xcol, ycol) = match (
282 col_for(crate::aes::Aesthetic::X),
283 col_for(crate::aes::Aesthetic::Y),
284 ) {
285 (Some(x), Some(y)) => (x, y),
286 _ => return self,
287 };
288 let (xc, yc) = match (self.data.column(&xcol), self.data.column(&ycol)) {
289 (Some(x), Some(y)) => (x, y),
290 _ => return self,
291 };
292
293 let mut groups: Vec<(String, Vec<f64>)> = Vec::new();
295 let mut ymax = f64::NEG_INFINITY;
296 let mut ymin = f64::INFINITY;
297 for (xv, yv) in xc.iter().zip(yc.iter()) {
298 let y = match yv.as_f64() {
299 Some(y) if y.is_finite() => y,
300 _ => continue,
301 };
302 ymax = ymax.max(y);
303 ymin = ymin.min(y);
304 let key = xv.to_group_key();
305 if let Some(g) = groups.iter_mut().find(|(k, _)| *k == key) {
306 g.1.push(y);
307 } else {
308 groups.push((key, vec![y]));
309 }
310 }
311 if groups.len() < 2 {
312 return self;
313 }
314 let step = if ymax > ymin {
315 (ymax - ymin) * 0.12
316 } else {
317 1.0
318 };
319
320 let (mut xmin_v, mut xmax_v, mut y_v, mut label_v) =
322 (Vec::new(), Vec::new(), Vec::new(), Vec::new());
323 let mut placed = 0usize;
324 for (a, b) in comparisons {
325 let ga = groups.iter().find(|(k, _)| k == a).map(|g| &g.1);
326 let gb = groups.iter().find(|(k, _)| k == b).map(|g| &g.1);
327 let (ga, gb) = match (ga, gb) {
328 (Some(x), Some(y)) if x.len() >= 2 && y.len() >= 2 => (x, y),
329 _ => continue,
330 };
331 let p = match crate::stat::compare_means::pairwise_p(method, ga, gb) {
332 Some(p) => p,
333 None => continue,
334 };
335 xmin_v.push(Value::Str((*a).to_string()));
336 xmax_v.push(Value::Str((*b).to_string()));
337 y_v.push(Value::Float(ymax + step * (placed as f64 + 1.0)));
338 label_v.push(Value::Str(crate::stat::cor::format_p_value(p)));
339 placed += 1;
340 }
341 if xmin_v.is_empty() {
342 return self;
343 }
344
345 let data = vec![
346 ("xmin".to_string(), xmin_v),
347 ("xmax".to_string(), xmax_v),
348 ("y".to_string(), y_v),
349 ("label".to_string(), label_v),
350 ];
351 self.add_geom(crate::geom::bracket::GeomBracket::default())
352 .layer_data(data)
353 .layer_aes(Aes::new().xmin("xmin").xmax("xmax").y("y").label("label"))
354 }
355
356 pub fn geom_bracket(self, xmin: &str, xmax: &str, y: f64, label: &str) -> Self {
361 self.geom_bracket_many(
362 crate::geom::bracket::GeomBracket::default(),
363 &[(xmin, xmax, y, label)],
364 )
365 }
366
367 pub fn geom_bracket_many(
371 self,
372 geom: crate::geom::bracket::GeomBracket,
373 brackets: &[(&str, &str, f64, &str)],
374 ) -> Self {
375 let xmin = brackets
376 .iter()
377 .map(|b| Value::Str(b.0.to_string()))
378 .collect::<Vec<_>>();
379 let xmax = brackets
380 .iter()
381 .map(|b| Value::Str(b.1.to_string()))
382 .collect::<Vec<_>>();
383 let y = brackets
384 .iter()
385 .map(|b| Value::Float(b.2))
386 .collect::<Vec<_>>();
387 let label = brackets
388 .iter()
389 .map(|b| Value::Str(b.3.to_string()))
390 .collect::<Vec<_>>();
391 let data = vec![
392 ("xmin".to_string(), xmin),
393 ("xmax".to_string(), xmax),
394 ("y".to_string(), y),
395 ("label".to_string(), label),
396 ];
397 self.add_geom(geom)
398 .layer_data(data)
399 .layer_aes(Aes::new().xmin("xmin").xmax("xmax").y("y").label("label"))
400 }
401
402 pub fn geom_label(self) -> Self {
403 self.add_geom(GeomLabel::default())
404 }
405
406 pub fn geom_label_with(self, geom: GeomLabel) -> Self {
407 self.add_geom(geom)
408 }
409
410 pub fn geom_area(self) -> Self {
411 self.add_geom(GeomArea::default())
412 }
413
414 pub fn geom_area_with(self, geom: GeomArea) -> Self {
415 self.add_geom(geom)
416 }
417
418 pub fn geom_ribbon(self) -> Self {
419 self.add_geom(GeomRibbon::default())
420 }
421
422 pub fn geom_ribbon_with(self, geom: GeomRibbon) -> Self {
423 self.add_geom(geom)
424 }
425
426 pub fn geom_errorbar(self) -> Self {
427 self.add_geom(GeomErrorbar::default())
428 }
429
430 pub fn geom_errorbar_with(self, geom: GeomErrorbar) -> Self {
431 self.add_geom(geom)
432 }
433
434 pub fn geom_segment(self) -> Self {
435 self.add_geom(GeomSegment::default())
436 }
437
438 pub fn geom_segment_with(self, geom: GeomSegment) -> Self {
439 self.add_geom(geom)
440 }
441
442 pub fn geom_density(self) -> Self {
443 self.add_geom(GeomDensity::default())
444 }
445
446 pub fn geom_density_with(self, geom: GeomDensity) -> Self {
447 self.add_geom(geom)
448 }
449
450 pub fn geom_rug(self) -> Self {
451 self.add_geom(GeomRug::default())
452 }
453
454 pub fn geom_rug_with(self, geom: GeomRug) -> Self {
455 self.add_geom(geom)
456 }
457
458 pub fn geom_jitter(self) -> Self {
459 self.add_geom(GeomJitter::default())
460 }
461
462 pub fn geom_jitter_with(self, geom: GeomJitter) -> Self {
463 self.add_geom(geom)
464 }
465
466 pub fn geom_path(self) -> Self {
467 self.add_geom(GeomPath::default())
468 }
469
470 pub fn geom_path_with(self, geom: GeomPath) -> Self {
471 self.add_geom(geom)
472 }
473
474 pub fn stat_ellipse(self) -> Self {
476 self.geom_path()
477 .stat(crate::stat::ellipse::StatEllipse::default())
478 }
479
480 pub fn stat_ellipse_level(self, level: f64) -> Self {
482 self.geom_path()
483 .stat(crate::stat::ellipse::StatEllipse::new(level))
484 }
485
486 #[cfg(feature = "regression")]
489 pub fn stat_quantile(mut self, taus: &[f64]) -> Self {
490 for &tau in taus {
491 self = self
492 .geom_path()
493 .stat(crate::stat::quantile::StatQuantile::new(tau));
494 }
495 self
496 }
497
498 #[cfg(feature = "regression")]
500 pub fn geom_quantile(self) -> Self {
501 self.stat_quantile(&[0.25, 0.5, 0.75])
502 }
503
504 pub fn geom_step(self) -> Self {
505 self.add_geom(GeomStep::default())
506 }
507
508 pub fn geom_step_with(self, geom: GeomStep) -> Self {
509 self.add_geom(geom)
510 }
511
512 pub fn geom_freqpoly(self) -> Self {
513 self.add_geom(GeomFreqpoly::default())
514 }
515
516 pub fn geom_freqpoly_with(self, geom: GeomFreqpoly) -> Self {
517 self.add_geom(geom)
518 }
519
520 pub fn geom_linerange(self) -> Self {
521 self.add_geom(GeomLinerange::default())
522 }
523
524 pub fn geom_linerange_with(self, geom: GeomLinerange) -> Self {
525 self.add_geom(geom)
526 }
527
528 pub fn geom_pointrange(self) -> Self {
529 self.add_geom(GeomPointrange::default())
530 }
531
532 pub fn geom_pointrange_with(self, geom: GeomPointrange) -> Self {
533 self.add_geom(geom)
534 }
535
536 pub fn geom_crossbar(self) -> Self {
537 self.add_geom(GeomCrossbar::default())
538 }
539
540 pub fn geom_crossbar_with(self, geom: GeomCrossbar) -> Self {
541 self.add_geom(geom)
542 }
543
544 pub fn geom_spoke(self) -> Self {
545 self.add_geom(GeomSpoke::default())
546 }
547
548 pub fn geom_spoke_with(self, geom: GeomSpoke) -> Self {
549 self.add_geom(geom)
550 }
551
552 pub fn geom_rect(self) -> Self {
553 self.add_geom(GeomRect::default())
554 }
555
556 pub fn geom_rect_with(self, geom: GeomRect) -> Self {
557 self.add_geom(geom)
558 }
559
560 pub fn geom_tile(self) -> Self {
561 self.add_geom(GeomTile::default())
562 }
563
564 pub fn geom_tile_with(self, geom: GeomTile) -> Self {
565 self.add_geom(geom)
566 }
567
568 pub fn geom_raster(self) -> Self {
570 self.add_geom(crate::geom::raster::GeomRaster::default())
571 }
572
573 pub fn geom_raster_with(self, geom: crate::geom::raster::GeomRaster) -> Self {
574 self.add_geom(geom)
575 }
576
577 pub fn geom_polygon(self) -> Self {
578 self.add_geom(GeomPolygon::default())
579 }
580
581 pub fn geom_polygon_with(self, geom: GeomPolygon) -> Self {
582 self.add_geom(geom)
583 }
584
585 #[cfg(feature = "sf")]
587 pub fn geom_sf(self) -> Self {
588 self.add_geom(crate::geom::sf::GeomSf::default())
589 }
590
591 #[cfg(feature = "sf")]
592 pub fn geom_sf_with(self, geom: crate::geom::sf::GeomSf) -> Self {
593 self.add_geom(geom)
594 }
595
596 pub fn geom_curve(self) -> Self {
597 self.add_geom(GeomCurve::default())
598 }
599
600 pub fn geom_curve_with(self, geom: GeomCurve) -> Self {
601 self.add_geom(geom)
602 }
603
604 pub fn geom_violin(self) -> Self {
605 self.add_geom(GeomViolin::default())
606 }
607
608 pub fn geom_violin_with(self, geom: GeomViolin) -> Self {
609 self.add_geom(geom)
610 }
611
612 pub fn geom_dotplot(self) -> Self {
613 self.add_geom(GeomDotplot::default())
614 }
615
616 pub fn geom_dotplot_with(self, geom: GeomDotplot) -> Self {
617 self.add_geom(geom)
618 }
619
620 pub fn geom_qq(self) -> Self {
621 self.add_geom(GeomQQ::default())
622 }
623
624 pub fn geom_qq_with(self, geom: GeomQQ) -> Self {
625 self.add_geom(geom)
626 }
627
628 pub fn geom_qq_line(self) -> Self {
629 self.add_geom(GeomQQLine::default())
630 }
631
632 pub fn geom_qq_line_with(self, geom: GeomQQLine) -> Self {
633 self.add_geom(geom)
634 }
635
636 pub fn geom_bin2d(self) -> Self {
637 self.add_geom(GeomBin2d::default())
638 }
639
640 pub fn geom_bin2d_with(self, geom: GeomBin2d) -> Self {
641 self.add_geom(geom)
642 }
643
644 pub fn geom_hex(self) -> Self {
645 self.add_geom(GeomHex::default())
646 }
647
648 pub fn geom_hex_with(self, geom: GeomHex) -> Self {
649 self.add_geom(geom)
650 }
651
652 pub fn geom_count(self) -> Self {
653 self.add_geom(GeomCount::default())
654 }
655
656 pub fn geom_count_with(self, geom: GeomCount) -> Self {
657 self.add_geom(geom)
658 }
659
660 pub fn geom_contour(self) -> Self {
661 self.add_geom(GeomContour::default())
662 }
663
664 pub fn geom_contour_with(self, geom: GeomContour) -> Self {
665 self.add_geom(geom)
666 }
667
668 pub fn geom_contour_filled(self) -> Self {
671 self.add_geom(GeomPolygon {
672 line_width: 0.0,
673 alpha: 1.0,
674 ..GeomPolygon::default()
675 })
676 .stat(crate::stat::contour_filled::StatContourFilled::default())
677 }
678
679 pub fn geom_density2d(self) -> Self {
680 self.add_geom(GeomDensity2d::default())
681 }
682
683 pub fn geom_density2d_with(self, geom: GeomDensity2d) -> Self {
684 self.add_geom(geom)
685 }
686
687 pub fn geom_blank(self) -> Self {
688 self.add_geom(GeomBlank)
689 }
690
691 fn add_geom(mut self, geom: impl Geom + 'static) -> Self {
692 let stat = geom.default_stat();
693 let position = geom.default_position();
694 let params = geom.default_params();
695 self.layers.push(Layer {
696 data: None,
697 mapping: Aes::default(),
698 geom: Box::new(geom),
699 stat,
700 position,
701 params,
702 show_legend: None,
703 });
704 self
705 }
706
707 pub fn stat(mut self, stat: impl Stat + 'static) -> Self {
711 if let Some(layer) = self.layers.last_mut() {
712 layer.stat = Box::new(stat);
713 }
714 self
715 }
716
717 pub fn position(mut self, pos: impl Position + 'static) -> Self {
719 if let Some(layer) = self.layers.last_mut() {
720 layer.position = Box::new(pos);
721 }
722 self
723 }
724
725 pub fn layer_data(mut self, data: impl GGData) -> Self {
727 if let Some(layer) = self.layers.last_mut() {
728 layer.data = Some(data.into_dataframe());
729 }
730 self
731 }
732
733 pub fn layer_aes(mut self, mapping: Aes) -> Self {
735 if let Some(layer) = self.layers.last_mut() {
736 layer.mapping = mapping;
737 }
738 self
739 }
740
741 pub fn show_legend(mut self, show: bool) -> Self {
744 if let Some(layer) = self.layers.last_mut() {
745 layer.show_legend = Some(show);
746 }
747 self
748 }
749
750 pub fn scale_x_continuous(mut self, s: ScaleContinuous) -> Self {
753 let s = s.for_aesthetic(crate::aes::Aesthetic::X);
754 self.scales.push(Box::new(s));
755 self
756 }
757
758 pub fn scale_y_continuous(mut self, s: ScaleContinuous) -> Self {
759 let s = s.for_aesthetic(crate::aes::Aesthetic::Y);
760 self.scales.push(Box::new(s));
761 self
762 }
763
764 pub fn scale_x_discrete(mut self, s: crate::scale::discrete::ScaleDiscrete) -> Self {
765 let s = s.for_aesthetic(crate::aes::Aesthetic::X);
766 self.scales.push(Box::new(s));
767 self
768 }
769
770 pub fn scale_y_discrete(mut self, s: crate::scale::discrete::ScaleDiscrete) -> Self {
771 let s = s.for_aesthetic(crate::aes::Aesthetic::Y);
772 self.scales.push(Box::new(s));
773 self
774 }
775
776 pub fn scale_color(mut self, s: impl Scale + 'static) -> Self {
777 self.scales.push(Box::new(s));
778 self
779 }
780
781 pub fn scale_fill(mut self, s: impl Scale + 'static) -> Self {
782 self.scales.push(Box::new(s));
783 self
784 }
785
786 pub fn scale_color_manual(self, values: Vec<(&str, crate::scale::color::RGBAColor)>) -> Self {
787 let s = crate::scale::manual::ScaleManual::new(crate::aes::Aesthetic::Color, values);
788 self.scale_color(s)
789 }
790
791 pub fn scale_fill_manual(self, values: Vec<(&str, crate::scale::color::RGBAColor)>) -> Self {
792 let s = crate::scale::manual::ScaleManual::new(crate::aes::Aesthetic::Fill, values);
793 self.scale_fill(s)
794 }
795
796 pub fn scale_color_viridis(self) -> Self {
797 use crate::scale::color::ScaleColorDiscrete;
798 use crate::scale::palettes::PaletteName;
799 let s = ScaleColorDiscrete::new(crate::aes::Aesthetic::Color)
800 .with_named_palette(&PaletteName::Viridis);
801 self.scale_color(s)
802 }
803
804 pub fn scale_color_brewer(self, name: crate::scale::palettes::PaletteName) -> Self {
805 use crate::scale::color::ScaleColorDiscrete;
806 let s = ScaleColorDiscrete::new(crate::aes::Aesthetic::Color).with_named_palette(&name);
807 self.scale_color(s)
808 }
809
810 pub fn scale_color_gradient(
811 self,
812 low: crate::scale::color::RGBAColor,
813 high: crate::scale::color::RGBAColor,
814 ) -> Self {
815 use crate::scale::color::ScaleColorContinuous;
816 let s = ScaleColorContinuous::new(crate::aes::Aesthetic::Color).with_colors(low, high);
817 self.scale_color(s)
818 }
819
820 pub fn scale_fill_gradient(
821 self,
822 low: crate::scale::color::RGBAColor,
823 high: crate::scale::color::RGBAColor,
824 ) -> Self {
825 use crate::scale::color::ScaleColorContinuous;
826 let s = ScaleColorContinuous::new(crate::aes::Aesthetic::Fill).with_colors(low, high);
827 self.scale_fill(s)
828 }
829
830 pub fn scale_color_gradient2(
831 self,
832 low: crate::scale::color::RGBAColor,
833 mid: crate::scale::color::RGBAColor,
834 high: crate::scale::color::RGBAColor,
835 ) -> Self {
836 use crate::scale::gradient::ScaleColorGradient2;
837 let s = ScaleColorGradient2::new(crate::aes::Aesthetic::Color).with_colors(low, mid, high);
838 self.scale_color(s)
839 }
840
841 pub fn scale_fill_gradient2(
842 self,
843 low: crate::scale::color::RGBAColor,
844 mid: crate::scale::color::RGBAColor,
845 high: crate::scale::color::RGBAColor,
846 ) -> Self {
847 use crate::scale::gradient::ScaleColorGradient2;
848 let s = ScaleColorGradient2::new(crate::aes::Aesthetic::Fill).with_colors(low, mid, high);
849 self.scale_fill(s)
850 }
851
852 pub fn scale_fill_viridis(self) -> Self {
853 use crate::scale::color::ScaleColorDiscrete;
854 use crate::scale::palettes::PaletteName;
855 let s = ScaleColorDiscrete::new(crate::aes::Aesthetic::Fill)
856 .with_named_palette(&PaletteName::Viridis);
857 self.scale_fill(s)
858 }
859
860 pub fn scale_color_viridis_c(self) -> Self {
862 use crate::scale::gradient_n::ScaleColorGradientN;
863 let s = ScaleColorGradientN::viridis(crate::aes::Aesthetic::Color);
864 self.scale_color(s)
865 }
866
867 pub fn scale_fill_viridis_c(self) -> Self {
869 use crate::scale::gradient_n::ScaleColorGradientN;
870 let s = ScaleColorGradientN::viridis(crate::aes::Aesthetic::Fill);
871 self.scale_fill(s)
872 }
873
874 pub fn scale_color_gradientn(self, stops: Vec<(f64, crate::scale::color::RGBAColor)>) -> Self {
876 use crate::scale::gradient_n::ScaleColorGradientN;
877 let s = ScaleColorGradientN::new(crate::aes::Aesthetic::Color, stops);
878 self.scale_color(s)
879 }
880
881 pub fn scale_fill_gradientn(self, stops: Vec<(f64, crate::scale::color::RGBAColor)>) -> Self {
883 use crate::scale::gradient_n::ScaleColorGradientN;
884 let s = ScaleColorGradientN::new(crate::aes::Aesthetic::Fill, stops);
885 self.scale_fill(s)
886 }
887
888 pub fn scale_color_steps(
891 self,
892 low: crate::scale::color::RGBAColor,
893 high: crate::scale::color::RGBAColor,
894 n_bins: usize,
895 ) -> Self {
896 let s = crate::scale::steps::ScaleColorSteps::two(
897 crate::aes::Aesthetic::Color,
898 (low.r, low.g, low.b),
899 (high.r, high.g, high.b),
900 n_bins,
901 );
902 self.scale_color(s)
903 }
904
905 pub fn scale_color_stepsn(
907 self,
908 stops: Vec<crate::scale::color::RGBAColor>,
909 n_bins: usize,
910 ) -> Self {
911 let s = crate::scale::steps::ScaleColorSteps::new(
912 crate::aes::Aesthetic::Color,
913 stops.iter().map(|c| (c.r, c.g, c.b)).collect(),
914 n_bins,
915 );
916 self.scale_color(s)
917 }
918
919 pub fn scale_color_fermenter(
921 self,
922 name: crate::scale::palettes::PaletteName,
923 n_bins: usize,
924 ) -> Self {
925 let stops = crate::scale::palettes::palette(&name)
926 .iter()
927 .map(|c| (c.r, c.g, c.b))
928 .collect();
929 let s =
930 crate::scale::steps::ScaleColorSteps::new(crate::aes::Aesthetic::Color, stops, n_bins);
931 self.scale_color(s)
932 }
933
934 pub fn scale_fill_steps(
936 self,
937 low: crate::scale::color::RGBAColor,
938 high: crate::scale::color::RGBAColor,
939 n_bins: usize,
940 ) -> Self {
941 let s = crate::scale::steps::ScaleColorSteps::two(
942 crate::aes::Aesthetic::Fill,
943 (low.r, low.g, low.b),
944 (high.r, high.g, high.b),
945 n_bins,
946 );
947 self.scale_fill(s)
948 }
949
950 pub fn scale_fill_fermenter(
952 self,
953 name: crate::scale::palettes::PaletteName,
954 n_bins: usize,
955 ) -> Self {
956 let stops = crate::scale::palettes::palette(&name)
957 .iter()
958 .map(|c| (c.r, c.g, c.b))
959 .collect();
960 let s =
961 crate::scale::steps::ScaleColorSteps::new(crate::aes::Aesthetic::Fill, stops, n_bins);
962 self.scale_fill(s)
963 }
964
965 pub fn scale_fill_brewer(self, name: crate::scale::palettes::PaletteName) -> Self {
966 use crate::scale::color::ScaleColorDiscrete;
967 let s = ScaleColorDiscrete::new(crate::aes::Aesthetic::Fill).with_named_palette(&name);
968 self.scale_fill(s)
969 }
970
971 pub fn scale_linetype_manual(
972 self,
973 values: Vec<(&str, crate::render::backend::Linetype)>,
974 ) -> Self {
975 let s = crate::scale::linetype_manual::ScaleLinetypeManual::new(values);
976 self.scale_color(s)
977 }
978
979 pub fn scale_shape_manual(
980 self,
981 values: Vec<(&str, crate::render::backend::PointShape)>,
982 ) -> Self {
983 let s = crate::scale::shape_manual::ScaleShapeManual::new(values);
984 self.scale_color(s)
985 }
986
987 pub fn scale_color_grey(self) -> Self {
988 let s = crate::scale::grey::ScaleColorGrey::new(crate::aes::Aesthetic::Color);
989 self.scale_color(s)
990 }
991
992 pub fn scale_fill_grey(self) -> Self {
993 let s = crate::scale::grey::ScaleColorGrey::new(crate::aes::Aesthetic::Fill);
994 self.scale_fill(s)
995 }
996
997 pub fn scale_color_grey_with(self, s: crate::scale::grey::ScaleColorGrey) -> Self {
998 self.scale_color(s)
999 }
1000
1001 pub fn scale_fill_grey_with(self, s: crate::scale::grey::ScaleColorGrey) -> Self {
1002 self.scale_fill(s)
1003 }
1004
1005 pub fn scale_x_reverse(self) -> Self {
1006 self.scale_x_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Reverse))
1007 }
1008
1009 pub fn scale_y_reverse(self) -> Self {
1010 self.scale_y_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Reverse))
1011 }
1012
1013 pub fn scale_x_datetime(mut self, s: crate::scale::datetime::ScaleDateTime) -> Self {
1014 let s = s.for_aesthetic(crate::aes::Aesthetic::X);
1015 self.scales.push(Box::new(s));
1016 self
1017 }
1018
1019 pub fn scale_y_datetime(mut self, s: crate::scale::datetime::ScaleDateTime) -> Self {
1020 let s = s.for_aesthetic(crate::aes::Aesthetic::Y);
1021 self.scales.push(Box::new(s));
1022 self
1023 }
1024
1025 pub fn scale_size(mut self, s: crate::scale::size::ScaleSizeContinuous) -> Self {
1026 self.scales.push(Box::new(s));
1027 self
1028 }
1029
1030 pub fn scale_alpha(mut self, s: crate::scale::alpha::ScaleAlphaContinuous) -> Self {
1031 self.scales.push(Box::new(s));
1032 self
1033 }
1034
1035 pub fn xlim(self, min: f64, max: f64) -> Self {
1036 self.scale_x_continuous(ScaleContinuous::new().with_limits(min, max))
1037 }
1038
1039 pub fn ylim(self, min: f64, max: f64) -> Self {
1040 self.scale_y_continuous(ScaleContinuous::new().with_limits(min, max))
1041 }
1042
1043 pub fn scale_x_log10(self) -> Self {
1044 self.scale_x_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Log10))
1045 }
1046
1047 pub fn scale_y_log10(self) -> Self {
1048 self.scale_y_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Log10))
1049 }
1050
1051 pub fn scale_x_sqrt(self) -> Self {
1052 self.scale_x_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Sqrt))
1053 }
1054
1055 pub fn scale_y_sqrt(self) -> Self {
1056 self.scale_y_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Sqrt))
1057 }
1058
1059 pub fn scale_x_log2(self) -> Self {
1060 self.scale_x_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Log2))
1061 }
1062
1063 pub fn scale_y_log2(self) -> Self {
1064 self.scale_y_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Log2))
1065 }
1066
1067 pub fn scale_x_ln(self) -> Self {
1068 self.scale_x_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Ln))
1069 }
1070
1071 pub fn scale_y_ln(self) -> Self {
1072 self.scale_y_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Ln))
1073 }
1074
1075 pub fn scale_x_logit(self) -> Self {
1077 self.scale_x_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Logit))
1078 }
1079
1080 pub fn scale_y_logit(self) -> Self {
1081 self.scale_y_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Logit))
1082 }
1083
1084 pub fn scale_x_probit(self) -> Self {
1086 self.scale_x_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Probit))
1087 }
1088
1089 pub fn scale_y_probit(self) -> Self {
1090 self.scale_y_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Probit))
1091 }
1092
1093 pub fn scale_x_pseudo_log(self) -> Self {
1095 self.scale_x_continuous(ScaleContinuous::new().with_transform(ScaleTransform::PseudoLog))
1096 }
1097
1098 pub fn scale_y_pseudo_log(self) -> Self {
1099 self.scale_y_continuous(ScaleContinuous::new().with_transform(ScaleTransform::PseudoLog))
1100 }
1101
1102 pub fn scale_x_reciprocal(self) -> Self {
1104 self.scale_x_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Reciprocal))
1105 }
1106
1107 pub fn scale_y_reciprocal(self) -> Self {
1108 self.scale_y_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Reciprocal))
1109 }
1110
1111 pub fn scale_x_exp(self) -> Self {
1113 self.scale_x_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Exp))
1114 }
1115
1116 pub fn scale_y_exp(self) -> Self {
1117 self.scale_y_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Exp))
1118 }
1119
1120 pub fn scale_x_boxcox(self, lambda: f64) -> Self {
1122 self.scale_x_continuous(
1123 ScaleContinuous::new().with_transform(ScaleTransform::BoxCox(lambda)),
1124 )
1125 }
1126
1127 pub fn scale_y_boxcox(self, lambda: f64) -> Self {
1128 self.scale_y_continuous(
1129 ScaleContinuous::new().with_transform(ScaleTransform::BoxCox(lambda)),
1130 )
1131 }
1132
1133 pub fn facet_wrap(mut self, var: &str, ncol: Option<usize>) -> Self {
1136 self.facet = Facet::Wrap {
1137 var: var.to_string(),
1138 ncol,
1139 scales: FacetScales::Fixed,
1140 labeller: FacetLabeller::default(),
1141 };
1142 self
1143 }
1144
1145 pub fn facet_wrap_free(mut self, var: &str, ncol: Option<usize>, scales: FacetScales) -> Self {
1146 self.facet = Facet::Wrap {
1147 var: var.to_string(),
1148 ncol,
1149 scales,
1150 labeller: FacetLabeller::default(),
1151 };
1152 self
1153 }
1154
1155 pub fn facet_wrap_labeller(
1156 mut self,
1157 var: &str,
1158 ncol: Option<usize>,
1159 labeller: FacetLabeller,
1160 ) -> Self {
1161 self.facet = Facet::Wrap {
1162 var: var.to_string(),
1163 ncol,
1164 scales: FacetScales::Fixed,
1165 labeller,
1166 };
1167 self
1168 }
1169
1170 pub fn facet_grid(mut self, row: Option<&str>, col: Option<&str>) -> Self {
1171 self.facet = Facet::Grid {
1172 row_var: row.map(String::from),
1173 col_var: col.map(String::from),
1174 scales: FacetScales::Fixed,
1175 labeller: FacetLabeller::default(),
1176 space: FacetSpace::Fixed,
1177 };
1178 self
1179 }
1180
1181 pub fn facet_grid_free(
1182 mut self,
1183 row: Option<&str>,
1184 col: Option<&str>,
1185 scales: FacetScales,
1186 ) -> Self {
1187 self.facet = Facet::Grid {
1188 row_var: row.map(String::from),
1189 col_var: col.map(String::from),
1190 scales,
1191 labeller: FacetLabeller::default(),
1192 space: FacetSpace::Fixed,
1193 };
1194 self
1195 }
1196
1197 pub fn facet_grid_multi(
1201 mut self,
1202 row: Option<&str>,
1203 cols: &[&str],
1204 scales: FacetScales,
1205 space: FacetSpace,
1206 ) -> Self {
1207 let col_var = if cols.len() > 1 {
1208 let n = self.data.nrows();
1210 let mut combined = Vec::with_capacity(n);
1211 for i in 0..n {
1212 let parts: Vec<String> = cols
1213 .iter()
1214 .map(|c| {
1215 self.data
1216 .column(c)
1217 .and_then(|col| col.get(i))
1218 .map(|v| v.to_group_key())
1219 .unwrap_or_default()
1220 })
1221 .collect();
1222 combined.push(crate::data::Value::Str(parts.join(" . ")));
1223 }
1224 let name = "__facet_cols__".to_string();
1225 self.data.add_column(name.clone(), combined);
1226 Some(name)
1227 } else {
1228 cols.first().map(|s| s.to_string())
1229 };
1230 self.facet = Facet::Grid {
1231 row_var: row.map(String::from),
1232 col_var,
1233 scales,
1234 labeller: FacetLabeller::default(),
1235 space,
1236 };
1237 self
1238 }
1239
1240 pub fn facet_grid_space(
1243 mut self,
1244 row: Option<&str>,
1245 col: Option<&str>,
1246 scales: FacetScales,
1247 space: FacetSpace,
1248 ) -> Self {
1249 self.facet = Facet::Grid {
1250 row_var: row.map(String::from),
1251 col_var: col.map(String::from),
1252 scales,
1253 labeller: FacetLabeller::default(),
1254 space,
1255 };
1256 self
1257 }
1258
1259 pub fn facet_grid_labeller(
1260 mut self,
1261 row: Option<&str>,
1262 col: Option<&str>,
1263 labeller: FacetLabeller,
1264 ) -> Self {
1265 self.facet = Facet::Grid {
1266 row_var: row.map(String::from),
1267 col_var: col.map(String::from),
1268 scales: FacetScales::Fixed,
1269 labeller,
1270 space: FacetSpace::Fixed,
1271 };
1272 self
1273 }
1274
1275 pub fn coord_flip(mut self) -> Self {
1278 self.coord = Box::new(CoordFlip);
1279 self
1280 }
1281
1282 pub fn coord_fixed(mut self, ratio: f64) -> Self {
1283 self.coord = Box::new(CoordFixed::new(ratio));
1284 self
1285 }
1286
1287 #[cfg(feature = "sf")]
1291 pub fn coord_sf(mut self) -> Self {
1292 self.coord = Box::new(crate::coord::sf::CoordSf::new());
1293 self
1294 }
1295
1296 pub fn coord_trans(mut self, x: Option<ScaleTransform>, y: Option<ScaleTransform>) -> Self {
1301 self.coord = Box::new(crate::coord::trans::CoordTrans::new(x, y));
1302 self
1303 }
1304
1305 pub fn coord_trans_y(self, y: ScaleTransform) -> Self {
1307 self.coord_trans(None, Some(y))
1308 }
1309
1310 pub fn coord_trans_x(self, x: ScaleTransform) -> Self {
1312 self.coord_trans(Some(x), None)
1313 }
1314
1315 pub fn coord_cartesian_zoom(
1317 mut self,
1318 xlim: Option<(f64, f64)>,
1319 ylim: Option<(f64, f64)>,
1320 ) -> Self {
1321 let mut c = CoordCartesian::new();
1322 if let Some((min, max)) = xlim {
1323 c = c.xlim(min, max);
1324 }
1325 if let Some((min, max)) = ylim {
1326 c = c.ylim(min, max);
1327 }
1328 self.coord = Box::new(c);
1329 self
1330 }
1331
1332 pub fn coord_polar(mut self) -> Self {
1333 self.coord = Box::new(CoordPolar::new());
1334 self
1335 }
1336
1337 pub fn coord_polar_with(mut self, coord: CoordPolar) -> Self {
1338 self.coord = Box::new(coord);
1339 self
1340 }
1341
1342 pub fn theme(mut self, theme: Theme) -> Self {
1345 self.theme = theme;
1346 self
1347 }
1348
1349 pub fn axis_text_x_angle(mut self, degrees: f64) -> Self {
1353 self.theme.axis_text_x.angle = degrees;
1354 self
1355 }
1356
1357 pub fn axis_text_y_angle(mut self, degrees: f64) -> Self {
1359 self.theme.axis_text_y.angle = degrees;
1360 self
1361 }
1362
1363 pub fn axis_text_x_dodge(mut self, n: usize) -> Self {
1366 self.theme.axis_text_x_dodge = n.max(1);
1367 self
1368 }
1369
1370 pub fn aspect_ratio(mut self, ratio: f64) -> Self {
1373 self.theme.aspect_ratio = Some(ratio);
1374 self
1375 }
1376
1377 pub fn panel_ontop(mut self) -> Self {
1379 self.theme.panel_ontop = true;
1380 self
1381 }
1382
1383 pub fn axis_minor_ticks(mut self) -> Self {
1385 self.theme.axis_minor_ticks = true;
1386 self
1387 }
1388
1389 pub fn title_position(mut self, pos: crate::theme::TitlePosition) -> Self {
1392 self.theme.title_position = pos;
1393 self
1394 }
1395
1396 pub fn tag_position(mut self, pos: crate::theme::TagPosition) -> Self {
1398 self.theme.tag_position = pos;
1399 self
1400 }
1401
1402 pub fn legend_direction(mut self, dir: crate::theme::LegendDirection) -> Self {
1404 self.theme.legend_direction = Some(dir);
1405 self
1406 }
1407
1408 pub fn legend_position_inside(mut self, x: f64, y: f64) -> Self {
1415 self.theme.legend_position = crate::theme::LegendPosition::Inside(x, y);
1416 self
1417 }
1418
1419 pub fn legend_position(mut self, pos: crate::theme::LegendPosition) -> Self {
1421 self.theme.legend_position = pos;
1422 self
1423 }
1424
1425 pub fn primary_color(mut self, color: (u8, u8, u8)) -> Self {
1426 self.theme.primary = Some(color);
1427 self
1428 }
1429
1430 pub fn theme_minimal(mut self) -> Self {
1431 self.theme = crate::theme::presets::theme_minimal();
1432 self
1433 }
1434
1435 pub fn theme_bw(mut self) -> Self {
1436 self.theme = crate::theme::presets::theme_bw();
1437 self
1438 }
1439
1440 pub fn theme_gray(mut self) -> Self {
1441 self.theme = crate::theme::presets::theme_gray();
1442 self
1443 }
1444
1445 pub fn theme_classic(mut self) -> Self {
1446 self.theme = crate::theme::presets::theme_classic();
1447 self
1448 }
1449
1450 pub fn theme_pubr(mut self) -> Self {
1452 self.theme = crate::theme::presets::theme_pubr();
1453 self
1454 }
1455
1456 pub fn theme_linedraw(mut self) -> Self {
1457 self.theme = crate::theme::presets::theme_linedraw();
1458 self
1459 }
1460
1461 pub fn theme_light(mut self) -> Self {
1462 self.theme = crate::theme::presets::theme_light();
1463 self
1464 }
1465
1466 pub fn theme_dark(mut self) -> Self {
1467 self.theme = crate::theme::presets::theme_dark();
1468 self
1469 }
1470
1471 pub fn theme_void(mut self) -> Self {
1472 self.theme = crate::theme::presets::theme_void();
1473 self
1474 }
1475
1476 pub fn theme_update(mut self, update: crate::theme::ThemeUpdate) -> Self {
1479 self.theme = self.theme.update(update);
1480 self
1481 }
1482
1483 pub fn guides(mut self, guide: crate::guide::config::GuideLegend) -> Self {
1487 self.guide_legend = guide;
1488 self
1489 }
1490
1491 pub fn labs(mut self, labels: Labels) -> Self {
1494 if labels.title.is_some() {
1495 self.labels.title = labels.title;
1496 }
1497 if labels.subtitle.is_some() {
1498 self.labels.subtitle = labels.subtitle;
1499 }
1500 if labels.x.is_some() {
1501 self.labels.x = labels.x;
1502 }
1503 if labels.y.is_some() {
1504 self.labels.y = labels.y;
1505 }
1506 if labels.caption.is_some() {
1507 self.labels.caption = labels.caption;
1508 }
1509 if labels.tag.is_some() {
1510 self.labels.tag = labels.tag;
1511 }
1512 self
1513 }
1514
1515 pub fn title(mut self, title: &str) -> Self {
1516 self.labels.title = Some(title.to_string());
1517 self
1518 }
1519
1520 pub fn tag(mut self, tag: &str) -> Self {
1523 self.labels.tag = Some(tag.to_string());
1524 self
1525 }
1526
1527 pub fn subtitle(mut self, subtitle: &str) -> Self {
1528 self.labels.subtitle = Some(subtitle.to_string());
1529 self
1530 }
1531
1532 pub fn xlab(mut self, label: &str) -> Self {
1533 self.labels.x = Some(label.to_string());
1534 self
1535 }
1536
1537 pub fn ylab(mut self, label: &str) -> Self {
1538 self.labels.y = Some(label.to_string());
1539 self
1540 }
1541
1542 pub fn caption(mut self, caption: &str) -> Self {
1543 self.labels.caption = Some(caption.to_string());
1544 self
1545 }
1546
1547 pub fn annotate(mut self, annotation: Annotation) -> Self {
1551 self.annotations.push(annotation);
1552 self
1553 }
1554
1555 pub fn annotate_text(self, label: &str, x: f64, y: f64) -> Self {
1557 self.annotate(Annotation::text(label, x, y))
1558 }
1559
1560 pub fn annotate_rect(self, xmin: f64, xmax: f64, ymin: f64, ymax: f64) -> Self {
1562 self.annotate(Annotation::rect(xmin, xmax, ymin, ymax))
1563 }
1564
1565 pub fn annotate_segment(self, x: f64, y: f64, xend: f64, yend: f64) -> Self {
1567 self.annotate(Annotation::segment(x, y, xend, yend))
1568 }
1569
1570 pub fn try_build(self) -> Result<crate::build::BuiltPlot, GGError> {
1574 PlotBuilder::build(self)
1575 }
1576
1577 pub fn build(self) -> crate::build::BuiltPlot {
1581 self.try_build().expect("plot build failed")
1582 }
1583
1584 #[cfg(not(target_arch = "wasm32"))]
1587 pub fn save(self, path: &str) -> Result<(), GGError> {
1588 self.save_with_size(path, 800, 600)
1589 }
1590
1591 #[cfg(not(target_arch = "wasm32"))]
1593 pub fn save_with_size(self, path: &str, w: u32, h: u32) -> Result<(), GGError> {
1594 let (built, layout) = self.prepare(w, h)?;
1595
1596 let ext = path.rsplit('.').next().unwrap_or("svg").to_lowercase();
1598
1599 match ext.as_str() {
1600 "svg" => {
1601 let backend = plotters::prelude::SVGBackend::new(path, (w, h));
1602 Self::render_into(backend.into_drawing_area(), &built, &layout)?;
1603 }
1604 "png" | "bmp" | "gif" | "jpeg" | "jpg" | "tiff" => {
1605 let backend = plotters::prelude::BitMapBackend::new(path, (w, h));
1606 Self::render_into(backend.into_drawing_area(), &built, &layout)?;
1607 }
1608 _ => {
1609 return Err(GGError::UnsupportedFormat(ext));
1610 }
1611 }
1612
1613 Ok(())
1614 }
1615
1616 #[cfg(not(target_arch = "wasm32"))]
1621 pub fn render_svg(self) -> Result<String, GGError> {
1622 self.render_svg_with_size(800, 600)
1623 }
1624
1625 #[cfg(not(target_arch = "wasm32"))]
1628 pub fn render_svg_with_size(self, w: u32, h: u32) -> Result<String, GGError> {
1629 let (built, layout) = self.prepare(w, h)?;
1630 let mut buf = String::new();
1631 {
1632 let backend = plotters::prelude::SVGBackend::with_string(&mut buf, (w, h));
1633 Self::render_into(backend.into_drawing_area(), &built, &layout)?;
1634 }
1635 Ok(buf)
1636 }
1637
1638 pub fn render_svg_native(self) -> Result<String, GGError> {
1642 self.render_svg_native_with_size(800, 600)
1643 }
1644
1645 pub fn render_svg_native_with_size(self, w: u32, h: u32) -> Result<String, GGError> {
1647 let (built, layout) = self.prepare(w, h)?;
1648 let mut backend =
1649 crate::render::svg_backend::SvgBackend::new(w, h, layout.plot_area.clone());
1650 PlotRenderer::render(&built, &mut backend).map_err(GGError::Render)?;
1651 Ok(backend.finish())
1652 }
1653
1654 pub fn render_svg_area_with_size(self, w: u32, h: u32) -> Result<(String, [f64; 4]), GGError> {
1658 let (built, layout) = self.prepare(w, h)?;
1659 let pa = layout.plot_area.clone();
1660 let mut backend = crate::render::svg_backend::SvgBackend::new(w, h, pa.clone());
1661 PlotRenderer::render(&built, &mut backend).map_err(GGError::Render)?;
1662 Ok((backend.finish(), [pa.x, pa.y, pa.width, pa.height]))
1663 }
1664
1665 #[cfg(feature = "canvas")]
1670 pub fn render_rgba_with_size(self, w: u32, h: u32) -> Result<(u32, u32, Vec<u8>), GGError> {
1671 let (built, layout) = self.prepare(w, h)?;
1672 let mut backend =
1673 crate::render::pixel_backend::PixelBackend::new(w, h, layout.plot_area.clone());
1674 PlotRenderer::render(&built, &mut backend).map_err(GGError::Render)?;
1675 let (ow, oh) = backend.dimensions();
1676 Ok((ow, oh, backend.into_rgba()))
1677 }
1678
1679 #[cfg(feature = "canvas")]
1683 pub fn render_rgba_area_with_size(
1684 self,
1685 w: u32,
1686 h: u32,
1687 ) -> Result<(Vec<u8>, [f64; 4]), GGError> {
1688 let (built, layout) = self.prepare(w, h)?;
1689 let pa = layout.plot_area.clone();
1690 let mut backend = crate::render::pixel_backend::PixelBackend::new(w, h, pa.clone());
1691 PlotRenderer::render(&built, &mut backend).map_err(GGError::Render)?;
1692 Ok((backend.into_rgba(), [pa.x, pa.y, pa.width, pa.height]))
1693 }
1694
1695 #[cfg(feature = "canvas")]
1699 pub fn render_png_raster_with_size(self, w: u32, h: u32) -> Result<Vec<u8>, GGError> {
1700 let (built, layout) = self.prepare(w, h)?;
1701 let mut backend =
1702 crate::render::pixel_backend::PixelBackend::new(w, h, layout.plot_area.clone());
1703 PlotRenderer::render(&built, &mut backend).map_err(GGError::Render)?;
1704 backend.into_png().map_err(GGError::Render)
1705 }
1706
1707 #[cfg(not(target_arch = "wasm32"))]
1712 pub fn render_png(self) -> Result<Vec<u8>, GGError> {
1713 self.render_png_with_size(800, 600)
1714 }
1715
1716 #[cfg(not(target_arch = "wasm32"))]
1719 pub fn render_png_with_size(self, w: u32, h: u32) -> Result<Vec<u8>, GGError> {
1720 let (built, layout) = self.prepare(w, h)?;
1721
1722 let mut rgb = vec![0u8; (w as usize) * (h as usize) * 3];
1725 {
1726 let backend = plotters::prelude::BitMapBackend::with_buffer(&mut rgb, (w, h));
1727 Self::render_into(backend.into_drawing_area(), &built, &layout)?;
1728 }
1729
1730 let img = image::RgbImage::from_raw(w, h, rgb).ok_or_else(|| {
1731 GGError::Render(RenderError::BackendError(
1732 "PNG buffer size mismatch".to_string(),
1733 ))
1734 })?;
1735 let mut out = std::io::Cursor::new(Vec::new());
1736 img.write_to(&mut out, image::ImageOutputFormat::Png)
1737 .map_err(|e| GGError::Render(RenderError::BackendError(format!("{:?}", e))))?;
1738 Ok(out.into_inner())
1739 }
1740
1741 fn prepare(self, w: u32, h: u32) -> Result<(crate::build::BuiltPlot, PlotLayout), GGError> {
1743 let plot = self;
1744
1745 let has_title = plot.labels.title.is_some();
1746 let has_subtitle = plot.labels.subtitle.is_some();
1747 let has_caption = plot.labels.caption.is_some();
1748 let has_legend = plot.has_legend_mapping();
1749 let x_label = plot.labels.x.clone();
1750 let y_label = plot.labels.y.clone();
1751
1752 let mut built = PlotBuilder::build(plot)?;
1753
1754 built.theme.resolve_inheritance();
1756
1757 if let Some(ref label) = x_label {
1759 if let Some(s) = built.scales.get_mut(&crate::aes::Aesthetic::X) {
1760 s.set_name(label);
1761 }
1762 }
1763 if let Some(ref label) = y_label {
1764 if let Some(s) = built.scales.get_mut(&crate::aes::Aesthetic::Y) {
1765 s.set_name(label);
1766 }
1767 }
1768
1769 let x_axis_top = built
1770 .scales
1771 .get(&crate::aes::Aesthetic::X)
1772 .map(|s| s.axis_position_opposite())
1773 .unwrap_or(false);
1774
1775 let layout = PlotLayout::compute_full(
1776 w as f64,
1777 h as f64,
1778 &built.theme,
1779 has_title,
1780 has_subtitle,
1781 has_caption,
1782 has_legend,
1783 x_axis_top,
1784 );
1785
1786 Ok((built, layout))
1787 }
1788
1789 #[cfg(not(target_arch = "wasm32"))]
1792 fn render_into<DB>(
1793 area: plotters::drawing::DrawingArea<DB, plotters::coord::Shift>,
1794 built: &crate::build::BuiltPlot,
1795 layout: &PlotLayout,
1796 ) -> Result<(), GGError>
1797 where
1798 DB: plotters::prelude::DrawingBackend,
1799 DB::ErrorType: 'static,
1800 {
1801 area.fill(&plotters::prelude::WHITE)
1802 .map_err(|e| GGError::Render(RenderError::BackendError(format!("{:?}", e))))?;
1803 let mut adapter = PlottersAdapter::new(&area, layout.plot_area.clone());
1804 PlotRenderer::render(built, &mut adapter).map_err(GGError::Render)?;
1805 area.present()
1806 .map_err(|e| GGError::Render(RenderError::BackendError(format!("{:?}", e))))?;
1807 Ok(())
1808 }
1809
1810 #[cfg(not(target_arch = "wasm32"))]
1812 pub fn ggsave(
1813 self,
1814 path: &str,
1815 width_inches: f64,
1816 height_inches: f64,
1817 dpi: f64,
1818 ) -> Result<(), GGError> {
1819 let w = (width_inches * dpi) as u32;
1820 let h = (height_inches * dpi) as u32;
1821 self.save_with_size(path, w, h)
1822 }
1823
1824 fn has_legend_mapping(&self) -> bool {
1825 self.mapping.mappings.iter().any(|m| {
1826 matches!(
1827 m.aesthetic,
1828 crate::aes::Aesthetic::Color
1829 | crate::aes::Aesthetic::Fill
1830 | crate::aes::Aesthetic::Shape
1831 | crate::aes::Aesthetic::Linetype
1832 | crate::aes::Aesthetic::Size
1833 | crate::aes::Aesthetic::Alpha
1834 )
1835 })
1836 }
1837}
1838
1839#[derive(Debug)]
1841pub enum GGError {
1842 Render(RenderError),
1843 UnsupportedFormat(String),
1844 Io(std::io::Error),
1845 ValidationError(String),
1846}
1847
1848impl std::fmt::Display for GGError {
1849 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1850 match self {
1851 GGError::Render(e) => write!(f, "Render error: {e}"),
1852 GGError::UnsupportedFormat(ext) => write!(f, "Unsupported output format: {ext}"),
1853 GGError::Io(e) => write!(f, "IO error: {e}"),
1854 GGError::ValidationError(msg) => write!(f, "Validation error: {msg}"),
1855 }
1856 }
1857}
1858
1859impl std::error::Error for GGError {}