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
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 pub explicit_style: bool,
87}
88
89pub struct GGPlot {
91 pub(crate) data: DataFrame,
92 pub(crate) mapping: Aes,
93 pub(crate) layers: Vec<Layer>,
94 pub(crate) scales: Vec<Box<dyn Scale>>,
95 pub(crate) coord: Box<dyn Coord>,
96 pub(crate) theme: Theme,
97 pub(crate) labels: Labels,
98 pub(crate) facet: Facet,
99 pub(crate) annotations: Vec<Annotation>,
100 pub(crate) guide_legend: crate::guide::config::GuideLegend,
101 pub(crate) warnings: Vec<String>,
104 pub(crate) default_aspect_ratio: Option<f64>,
107}
108
109impl GGPlot {
110 pub fn new(data: impl GGData) -> Self {
117 GGPlot {
118 data: data.into_dataframe(),
119 mapping: Aes::default(),
120 layers: Vec::new(),
121 scales: Vec::new(),
122 coord: Box::new(CoordCartesian::new()),
123 theme: Theme::default(),
124 labels: Labels::default(),
125 facet: Facet::default(),
126 annotations: Vec::new(),
127 guide_legend: crate::guide::config::GuideLegend::default(),
128 warnings: Vec::new(),
129 default_aspect_ratio: None,
130 }
131 }
132
133 pub fn aes(mut self, mapping: Aes) -> Self {
135 self.mapping = mapping;
136 self
137 }
138
139 pub fn geom_point(self) -> Self {
142 self.add_geom(GeomPoint::default())
143 }
144
145 pub fn geom_point_with(self, geom: GeomPoint) -> Self {
146 self.add_geom_with(geom)
147 }
148
149 pub fn geom_line(self) -> Self {
150 self.add_geom(GeomLine::default())
151 }
152
153 pub fn geom_line_with(self, geom: GeomLine) -> Self {
154 self.add_geom_with(geom)
155 }
156
157 pub fn geom_bar(self) -> Self {
158 self.add_geom(GeomBar::default())
159 }
160
161 pub fn geom_bar_with(self, geom: GeomBar) -> Self {
162 self.add_geom_with(geom)
163 }
164
165 pub fn geom_histogram(self) -> Self {
166 self.add_geom(GeomHistogram::default())
167 }
168
169 pub fn geom_histogram_with(self, geom: GeomHistogram) -> Self {
170 self.add_geom_with(geom)
171 }
172
173 pub fn geom_boxplot(self) -> Self {
174 self.add_geom(GeomBoxplot::default())
175 }
176
177 pub fn geom_boxplot_with(self, geom: GeomBoxplot) -> Self {
178 self.add_geom_with(geom)
179 }
180
181 pub fn geom_smooth(self) -> Self {
182 self.add_geom(GeomSmooth::default())
183 }
184
185 pub fn geom_smooth_with(self, geom: GeomSmooth) -> Self {
186 self.add_geom_with(geom)
187 }
188
189 pub fn geom_col(self) -> Self {
190 self.add_geom(GeomCol::default())
191 }
192
193 pub fn geom_col_with(self, geom: GeomCol) -> Self {
194 self.add_geom_with(geom)
195 }
196
197 pub fn geom_hline(self, yintercept: f64) -> Self {
198 self.add_geom(GeomHline::new(yintercept))
199 }
200
201 pub fn geom_hline_with(self, geom: GeomHline) -> Self {
203 self.add_geom_with(geom)
204 }
205
206 pub fn geom_vline(self, xintercept: f64) -> Self {
207 self.add_geom(GeomVline::new(xintercept))
208 }
209
210 pub fn geom_vline_with(self, geom: GeomVline) -> Self {
212 self.add_geom_with(geom)
213 }
214
215 pub fn geom_abline(self, slope: f64, intercept: f64) -> Self {
216 self.add_geom(GeomAbline::new(slope, intercept))
217 }
218
219 pub fn geom_abline_with(self, geom: GeomAbline) -> Self {
221 self.add_geom_with(geom)
222 }
223
224 pub fn geom_text(self) -> Self {
225 self.add_geom(GeomText::default())
226 }
227
228 pub fn geom_text_with(self, geom: GeomText) -> Self {
229 self.add_geom_with(geom)
230 }
231
232 #[cfg(feature = "ggpubr")]
237 pub fn stat_cor(self) -> Self {
238 self.geom_text().stat(crate::stat::cor::StatCor::default())
239 }
240
241 #[cfg(feature = "ggpubr")]
244 pub fn stat_cor_with(self, stat: crate::stat::cor::StatCor) -> Self {
245 self.geom_text().stat(stat)
246 }
247
248 #[cfg(feature = "ggpubr")]
253 pub fn stat_compare_means(self) -> Self {
254 self.geom_text()
255 .stat(crate::stat::compare_means::StatCompareMeans::default())
256 }
257
258 #[cfg(feature = "ggpubr")]
261 pub fn stat_compare_means_with(
262 self,
263 stat: crate::stat::compare_means::StatCompareMeans,
264 ) -> Self {
265 self.geom_text().stat(stat)
266 }
267
268 #[cfg(feature = "ggpubr")]
274 pub fn stat_compare_means_pairwise(self, comparisons: &[(&str, &str)]) -> Self {
275 self.stat_compare_means_pairwise_with(
276 crate::stat::compare_means::CompareMethod::Auto,
277 comparisons,
278 )
279 }
280
281 #[cfg(feature = "ggpubr")]
284 pub fn stat_compare_means_pairwise_with(
285 self,
286 method: crate::stat::compare_means::CompareMethod,
287 comparisons: &[(&str, &str)],
288 ) -> Self {
289 let col_for = |a: crate::aes::Aesthetic| {
291 self.mapping
292 .mappings
293 .iter()
294 .find(|m| m.aesthetic == a)
295 .map(|m| m.column.clone())
296 };
297 let (xcol, ycol) = match (
298 col_for(crate::aes::Aesthetic::X),
299 col_for(crate::aes::Aesthetic::Y),
300 ) {
301 (Some(x), Some(y)) => (x, y),
302 _ => return self,
303 };
304 let (xc, yc) = match (self.data.column(&xcol), self.data.column(&ycol)) {
305 (Some(x), Some(y)) => (x, y),
306 _ => return self,
307 };
308
309 let mut groups: Vec<(String, Vec<f64>)> = Vec::new();
311 let mut ymax = f64::NEG_INFINITY;
312 let mut ymin = f64::INFINITY;
313 for (xv, yv) in xc.iter().zip(yc.iter()) {
314 let y = match yv.as_f64() {
315 Some(y) if y.is_finite() => y,
316 _ => continue,
317 };
318 ymax = ymax.max(y);
319 ymin = ymin.min(y);
320 let key = xv.to_group_key();
321 if let Some(g) = groups.iter_mut().find(|(k, _)| *k == key) {
322 g.1.push(y);
323 } else {
324 groups.push((key, vec![y]));
325 }
326 }
327 if groups.len() < 2 {
328 return self;
329 }
330 let step = if ymax > ymin {
331 (ymax - ymin) * 0.12
332 } else {
333 1.0
334 };
335
336 let (mut xmin_v, mut xmax_v, mut y_v, mut label_v) =
338 (Vec::new(), Vec::new(), Vec::new(), Vec::new());
339 let mut placed = 0usize;
340 for (a, b) in comparisons {
341 let ga = groups.iter().find(|(k, _)| k == a).map(|g| &g.1);
342 let gb = groups.iter().find(|(k, _)| k == b).map(|g| &g.1);
343 let (ga, gb) = match (ga, gb) {
344 (Some(x), Some(y)) if x.len() >= 2 && y.len() >= 2 => (x, y),
345 _ => continue,
346 };
347 let p = match crate::stat::compare_means::pairwise_p(method, ga, gb) {
348 Some(p) => p,
349 None => continue,
350 };
351 xmin_v.push(Value::Str((*a).to_string()));
352 xmax_v.push(Value::Str((*b).to_string()));
353 y_v.push(Value::Float(ymax + step * (placed as f64 + 1.0)));
354 label_v.push(Value::Str(crate::stat::cor::format_p_value(p)));
355 placed += 1;
356 }
357 if xmin_v.is_empty() {
358 return self;
359 }
360
361 let data = vec![
362 ("xmin".to_string(), xmin_v),
363 ("xmax".to_string(), xmax_v),
364 ("y".to_string(), y_v),
365 ("label".to_string(), label_v),
366 ];
367 self.add_geom(crate::geom::bracket::GeomBracket::default())
368 .layer_data(data)
369 .layer_aes(Aes::new().xmin("xmin").xmax("xmax").y("y").label("label"))
370 }
371
372 pub fn geom_bracket(self, xmin: &str, xmax: &str, y: f64, label: &str) -> Self {
377 self.geom_bracket_many(
378 crate::geom::bracket::GeomBracket::default(),
379 &[(xmin, xmax, y, label)],
380 )
381 }
382
383 pub fn geom_bracket_many(
387 self,
388 geom: crate::geom::bracket::GeomBracket,
389 brackets: &[(&str, &str, f64, &str)],
390 ) -> Self {
391 let xmin = brackets
392 .iter()
393 .map(|b| Value::Str(b.0.to_string()))
394 .collect::<Vec<_>>();
395 let xmax = brackets
396 .iter()
397 .map(|b| Value::Str(b.1.to_string()))
398 .collect::<Vec<_>>();
399 let y = brackets
400 .iter()
401 .map(|b| Value::Float(b.2))
402 .collect::<Vec<_>>();
403 let label = brackets
404 .iter()
405 .map(|b| Value::Str(b.3.to_string()))
406 .collect::<Vec<_>>();
407 let data = vec![
408 ("xmin".to_string(), xmin),
409 ("xmax".to_string(), xmax),
410 ("y".to_string(), y),
411 ("label".to_string(), label),
412 ];
413 self.add_geom(geom)
414 .layer_data(data)
415 .layer_aes(Aes::new().xmin("xmin").xmax("xmax").y("y").label("label"))
416 }
417
418 pub fn geom_label(self) -> Self {
419 self.add_geom(GeomLabel::default())
420 }
421
422 pub fn geom_label_with(self, geom: GeomLabel) -> Self {
423 self.add_geom_with(geom)
424 }
425
426 pub fn geom_area(self) -> Self {
427 self.add_geom(GeomArea::default())
428 }
429
430 pub fn geom_area_with(self, geom: GeomArea) -> Self {
431 self.add_geom_with(geom)
432 }
433
434 pub fn geom_ribbon(self) -> Self {
435 self.add_geom(GeomRibbon::default())
436 }
437
438 pub fn geom_ribbon_with(self, geom: GeomRibbon) -> Self {
439 self.add_geom_with(geom)
440 }
441
442 pub fn geom_errorbar(self) -> Self {
443 self.add_geom(GeomErrorbar::default())
444 }
445
446 pub fn geom_errorbar_with(self, geom: GeomErrorbar) -> Self {
447 self.add_geom_with(geom)
448 }
449
450 pub fn geom_segment(self) -> Self {
451 self.add_geom(GeomSegment::default())
452 }
453
454 pub fn geom_segment_with(self, geom: GeomSegment) -> Self {
455 self.add_geom_with(geom)
456 }
457
458 pub fn geom_density(self) -> Self {
459 self.add_geom(GeomDensity::default())
460 }
461
462 pub fn geom_density_with(self, geom: GeomDensity) -> Self {
463 self.add_geom_with(geom)
464 }
465
466 pub fn geom_rug(self) -> Self {
467 self.add_geom(GeomRug::default())
468 }
469
470 pub fn geom_rug_with(self, geom: GeomRug) -> Self {
471 self.add_geom_with(geom)
472 }
473
474 pub fn geom_jitter(self) -> Self {
475 self.add_geom(GeomJitter::default())
476 }
477
478 pub fn geom_jitter_with(self, geom: GeomJitter) -> Self {
479 self.add_geom_with(geom)
480 }
481
482 pub fn geom_path(self) -> Self {
483 self.add_geom(GeomPath::default())
484 }
485
486 pub fn geom_path_with(self, geom: GeomPath) -> Self {
487 self.add_geom_with(geom)
488 }
489
490 pub fn stat_ellipse(self) -> Self {
492 self.geom_path()
493 .stat(crate::stat::ellipse::StatEllipse::default())
494 }
495
496 pub fn stat_ellipse_level(self, level: f64) -> Self {
498 self.geom_path()
499 .stat(crate::stat::ellipse::StatEllipse::new(level))
500 }
501
502 #[cfg(feature = "regression")]
505 pub fn stat_quantile(mut self, taus: &[f64]) -> Self {
506 for &tau in taus {
507 self = self
508 .geom_path()
509 .stat(crate::stat::quantile::StatQuantile::new(tau));
510 }
511 self
512 }
513
514 #[cfg(feature = "regression")]
516 pub fn geom_quantile(self) -> Self {
517 self.stat_quantile(&[0.25, 0.5, 0.75])
518 }
519
520 pub fn geom_step(self) -> Self {
521 self.add_geom(GeomStep::default())
522 }
523
524 pub fn geom_step_with(self, geom: GeomStep) -> Self {
525 self.add_geom_with(geom)
526 }
527
528 pub fn geom_freqpoly(self) -> Self {
529 self.add_geom(GeomFreqpoly::default())
530 }
531
532 pub fn geom_freqpoly_with(self, geom: GeomFreqpoly) -> Self {
533 self.add_geom_with(geom)
534 }
535
536 pub fn geom_linerange(self) -> Self {
537 self.add_geom(GeomLinerange::default())
538 }
539
540 pub fn geom_linerange_with(self, geom: GeomLinerange) -> Self {
541 self.add_geom_with(geom)
542 }
543
544 pub fn geom_pointrange(self) -> Self {
545 self.add_geom(GeomPointrange::default())
546 }
547
548 pub fn geom_pointrange_with(self, geom: GeomPointrange) -> Self {
549 self.add_geom_with(geom)
550 }
551
552 pub fn geom_crossbar(self) -> Self {
553 self.add_geom(GeomCrossbar::default())
554 }
555
556 pub fn geom_crossbar_with(self, geom: GeomCrossbar) -> Self {
557 self.add_geom_with(geom)
558 }
559
560 pub fn geom_spoke(self) -> Self {
561 self.add_geom(GeomSpoke::default())
562 }
563
564 pub fn geom_spoke_with(self, geom: GeomSpoke) -> Self {
565 self.add_geom_with(geom)
566 }
567
568 pub fn geom_rect(self) -> Self {
569 self.add_geom(GeomRect::default())
570 }
571
572 pub fn geom_rect_with(self, geom: GeomRect) -> Self {
573 self.add_geom_with(geom)
574 }
575
576 pub fn geom_tile(self) -> Self {
577 self.add_geom(GeomTile::default())
578 }
579
580 pub fn geom_tile_with(self, geom: GeomTile) -> Self {
581 self.add_geom_with(geom)
582 }
583
584 pub fn geom_raster(self) -> Self {
586 self.add_geom(crate::geom::raster::GeomRaster::default())
587 }
588
589 pub fn geom_raster_with(self, geom: crate::geom::raster::GeomRaster) -> Self {
590 self.add_geom_with(geom)
591 }
592
593 pub fn geom_polygon(self) -> Self {
594 self.add_geom(GeomPolygon::default())
595 }
596
597 pub fn geom_polygon_with(self, geom: GeomPolygon) -> Self {
598 self.add_geom_with(geom)
599 }
600
601 #[cfg(feature = "sf")]
603 pub fn geom_sf(self) -> Self {
604 self.add_geom(crate::geom::sf::GeomSf::default())
605 }
606
607 #[cfg(feature = "sf")]
608 pub fn geom_sf_with(self, geom: crate::geom::sf::GeomSf) -> Self {
609 self.add_geom_with(geom)
610 }
611
612 pub fn geom_curve(self) -> Self {
613 self.add_geom(GeomCurve::default())
614 }
615
616 pub fn geom_curve_with(self, geom: GeomCurve) -> Self {
617 self.add_geom_with(geom)
618 }
619
620 pub fn geom_violin(self) -> Self {
621 self.add_geom(GeomViolin::default())
622 }
623
624 pub fn geom_violin_with(self, geom: GeomViolin) -> Self {
625 self.add_geom_with(geom)
626 }
627
628 pub fn geom_dotplot(self) -> Self {
629 self.add_geom(GeomDotplot::default())
630 }
631
632 pub fn geom_dotplot_with(self, geom: GeomDotplot) -> Self {
633 self.add_geom_with(geom)
634 }
635
636 pub fn geom_qq(self) -> Self {
637 self.add_geom(GeomQQ::default())
638 }
639
640 pub fn geom_qq_with(self, geom: GeomQQ) -> Self {
641 self.add_geom_with(geom)
642 }
643
644 pub fn geom_qq_line(self) -> Self {
645 self.add_geom(GeomQQLine::default())
646 }
647
648 pub fn geom_qq_line_with(self, geom: GeomQQLine) -> Self {
649 self.add_geom_with(geom)
650 }
651
652 pub fn geom_bin2d(self) -> Self {
653 self.add_geom(GeomBin2d::default())
654 }
655
656 pub fn geom_bin2d_with(self, geom: GeomBin2d) -> Self {
657 self.add_geom_with(geom)
658 }
659
660 pub fn geom_hex(self) -> Self {
661 self.add_geom(GeomHex::default())
662 }
663
664 pub fn geom_hex_with(self, geom: GeomHex) -> Self {
665 self.add_geom_with(geom)
666 }
667
668 pub fn geom_count(self) -> Self {
669 self.add_geom(GeomCount::default())
670 }
671
672 pub fn geom_count_with(self, geom: GeomCount) -> Self {
673 self.add_geom_with(geom)
674 }
675
676 pub fn geom_contour(self) -> Self {
677 self.add_geom(GeomContour::default())
678 }
679
680 pub fn geom_contour_with(self, geom: GeomContour) -> Self {
681 self.add_geom_with(geom)
682 }
683
684 pub fn geom_contour_filled(self) -> Self {
687 self.add_geom(GeomPolygon {
688 line_width: 0.0,
689 alpha: 1.0,
690 ..GeomPolygon::default()
691 })
692 .stat(crate::stat::contour_filled::StatContourFilled::default())
693 }
694
695 pub fn geom_density2d(self) -> Self {
696 self.add_geom(GeomDensity2d::default())
697 }
698
699 pub fn geom_density2d_with(self, geom: GeomDensity2d) -> Self {
700 self.add_geom_with(geom)
701 }
702
703 pub fn geom_candlestick(self) -> Self {
706 self.add_geom(crate::geom::candlestick::GeomCandlestick::default())
707 }
708
709 pub fn geom_candlestick_with(self, geom: crate::geom::candlestick::GeomCandlestick) -> Self {
710 self.add_geom_with(geom)
711 }
712
713 pub fn geom_ohlc(self) -> Self {
716 self.add_geom(crate::geom::candlestick::GeomOhlc::default())
717 }
718
719 pub fn geom_ohlc_with(self, geom: crate::geom::candlestick::GeomOhlc) -> Self {
720 self.add_geom_with(geom)
721 }
722
723 pub fn geom_calendar(self) -> Self {
734 self.geom_calendar_with(
735 GeomTile {
736 color: (255, 255, 255),
737 line_width: 1.5,
738 ..Default::default()
739 },
740 false,
741 )
742 }
743
744 pub fn geom_calendar_with(mut self, tile: GeomTile, monday_first: bool) -> Self {
747 use crate::stat::calendar::{
748 day_number, month_boundaries, month_breaks, CalendarGrid, StatCalendar,
749 MAX_CALENDAR_YEARS,
750 };
751 let grid = self
752 .mapping
753 .get_mapping(&crate::aes::Aesthetic::X)
754 .and_then(|c| self.data.column(c))
755 .and_then(|col| {
756 CalendarGrid::from_days(col.iter().filter_map(day_number), monday_first)
757 });
758 let Some((grid, clipped)) = grid else {
759 return self.add_geom_with(tile).stat(StatCalendar {
761 grid: None,
762 monday_first,
763 });
764 };
765 if clipped {
766 self.warnings.push(format!(
767 "geom_calendar: dates more than {MAX_CALENDAR_YEARS} years before the newest were dropped"
768 ));
769 }
770 let (xb, xl) = month_breaks(&grid);
771 let (yb, yl) = if monday_first {
773 (vec![6.0, 4.0, 2.0], ["Mon", "Wed", "Fri"])
774 } else {
775 (vec![5.0, 3.0, 1.0], ["Mon", "Wed", "Fri"])
776 };
777 let segs = month_boundaries(&grid);
778 let col = |f: fn(&(f64, f64, f64, f64)) -> f64| -> Vec<Value> {
779 segs.iter().map(|s| Value::Float(f(s))).collect()
780 };
781 let boundaries = vec![
782 ("x".to_string(), col(|s| s.0)),
783 ("y".to_string(), col(|s| s.1)),
784 ("xend".to_string(), col(|s| s.2)),
785 ("yend".to_string(), col(|s| s.3)),
786 ];
787 self.default_aspect_ratio = Some(7.0 / grid.n_weeks().max(1) as f64);
788 let plot = self
789 .add_geom_with(tile)
790 .stat(StatCalendar {
791 grid: Some(grid),
792 monday_first,
793 })
794 .scale_x_continuous(
795 ScaleContinuous::new()
796 .with_breaks(xb)
797 .with_labels(xl)
798 .with_expand(0.0, 0.0),
799 )
800 .scale_y_continuous(
801 ScaleContinuous::new()
802 .with_breaks(yb)
803 .with_labels(yl.iter().map(|s| s.to_string()).collect())
804 .with_expand(0.0, 0.0),
805 );
806 if segs.is_empty() {
807 return plot;
808 }
809 plot.geom_segment_with(GeomSegment {
810 color: (120, 128, 140),
811 width: 1.2,
812 alpha: 1.0,
813 })
814 .layer_data(boundaries)
815 .layer_aes(Aes::new().x("x").y("y").xend("xend").yend("yend"))
816 .show_legend(false)
817 }
818
819 pub fn geom_blank(self) -> Self {
820 self.add_geom(GeomBlank)
821 }
822
823 fn add_geom_with(self, geom: impl Geom + 'static) -> Self {
826 let mut plot = self.add_geom(geom);
827 if let Some(layer) = plot.layers.last_mut() {
828 layer.explicit_style = true;
829 }
830 plot
831 }
832
833 fn add_geom(mut self, geom: impl Geom + 'static) -> Self {
834 let stat = geom.default_stat();
835 let position = geom.default_position();
836 let params = geom.default_params();
837 self.layers.push(Layer {
838 data: None,
839 mapping: Aes::default(),
840 geom: Box::new(geom),
841 stat,
842 position,
843 params,
844 show_legend: None,
845 explicit_style: false,
846 });
847 self
848 }
849
850 pub fn stat(mut self, stat: impl Stat + 'static) -> Self {
854 if let Some(layer) = self.layers.last_mut() {
855 layer.stat = Box::new(stat);
856 }
857 self
858 }
859
860 pub fn position(mut self, pos: impl Position + 'static) -> Self {
862 if let Some(layer) = self.layers.last_mut() {
863 layer.position = Box::new(pos);
864 }
865 self
866 }
867
868 pub fn layer_data(mut self, data: impl GGData) -> Self {
870 if let Some(layer) = self.layers.last_mut() {
871 layer.data = Some(data.into_dataframe());
872 }
873 self
874 }
875
876 pub fn layer_aes(mut self, mapping: Aes) -> Self {
878 if let Some(layer) = self.layers.last_mut() {
879 layer.mapping = mapping;
880 }
881 self
882 }
883
884 pub fn show_legend(mut self, show: bool) -> Self {
887 if let Some(layer) = self.layers.last_mut() {
888 layer.show_legend = Some(show);
889 }
890 self
891 }
892
893 pub fn scale_x_continuous(mut self, s: ScaleContinuous) -> Self {
896 let s = s.for_aesthetic(crate::aes::Aesthetic::X);
897 self.scales.push(Box::new(s));
898 self
899 }
900
901 pub fn scale_y_continuous(mut self, s: ScaleContinuous) -> Self {
902 let s = s.for_aesthetic(crate::aes::Aesthetic::Y);
903 self.scales.push(Box::new(s));
904 self
905 }
906
907 pub fn scale_x_discrete(mut self, s: crate::scale::discrete::ScaleDiscrete) -> Self {
908 let s = s.for_aesthetic(crate::aes::Aesthetic::X);
909 self.scales.push(Box::new(s));
910 self
911 }
912
913 pub fn scale_y_discrete(mut self, s: crate::scale::discrete::ScaleDiscrete) -> Self {
914 let s = s.for_aesthetic(crate::aes::Aesthetic::Y);
915 self.scales.push(Box::new(s));
916 self
917 }
918
919 pub fn scale_color(mut self, s: impl Scale + 'static) -> Self {
920 self.scales.push(Box::new(s));
921 self
922 }
923
924 pub fn scale_fill(mut self, s: impl Scale + 'static) -> Self {
925 self.scales.push(Box::new(s));
926 self
927 }
928
929 pub fn scale_color_manual(self, values: Vec<(&str, crate::scale::color::RGBAColor)>) -> Self {
930 let s = crate::scale::manual::ScaleManual::new(crate::aes::Aesthetic::Color, values);
931 self.scale_color(s)
932 }
933
934 pub fn scale_fill_manual(self, values: Vec<(&str, crate::scale::color::RGBAColor)>) -> Self {
935 let s = crate::scale::manual::ScaleManual::new(crate::aes::Aesthetic::Fill, values);
936 self.scale_fill(s)
937 }
938
939 pub fn scale_color_viridis(self) -> Self {
940 use crate::scale::color::ScaleColorDiscrete;
941 use crate::scale::palettes::PaletteName;
942 let s = ScaleColorDiscrete::new(crate::aes::Aesthetic::Color)
943 .with_named_palette(&PaletteName::Viridis);
944 self.scale_color(s)
945 }
946
947 pub fn scale_color_brewer(self, name: crate::scale::palettes::PaletteName) -> Self {
948 use crate::scale::color::ScaleColorDiscrete;
949 let s = ScaleColorDiscrete::new(crate::aes::Aesthetic::Color).with_named_palette(&name);
950 self.scale_color(s)
951 }
952
953 pub fn scale_color_gradient(
954 self,
955 low: crate::scale::color::RGBAColor,
956 high: crate::scale::color::RGBAColor,
957 ) -> Self {
958 use crate::scale::color::ScaleColorContinuous;
959 let s = ScaleColorContinuous::new(crate::aes::Aesthetic::Color).with_colors(low, high);
960 self.scale_color(s)
961 }
962
963 pub fn scale_fill_gradient(
964 self,
965 low: crate::scale::color::RGBAColor,
966 high: crate::scale::color::RGBAColor,
967 ) -> Self {
968 use crate::scale::color::ScaleColorContinuous;
969 let s = ScaleColorContinuous::new(crate::aes::Aesthetic::Fill).with_colors(low, high);
970 self.scale_fill(s)
971 }
972
973 pub fn scale_color_gradient2(
974 self,
975 low: crate::scale::color::RGBAColor,
976 mid: crate::scale::color::RGBAColor,
977 high: crate::scale::color::RGBAColor,
978 ) -> Self {
979 use crate::scale::gradient::ScaleColorGradient2;
980 let s = ScaleColorGradient2::new(crate::aes::Aesthetic::Color).with_colors(low, mid, high);
981 self.scale_color(s)
982 }
983
984 pub fn scale_fill_gradient2(
985 self,
986 low: crate::scale::color::RGBAColor,
987 mid: crate::scale::color::RGBAColor,
988 high: crate::scale::color::RGBAColor,
989 ) -> Self {
990 use crate::scale::gradient::ScaleColorGradient2;
991 let s = ScaleColorGradient2::new(crate::aes::Aesthetic::Fill).with_colors(low, mid, high);
992 self.scale_fill(s)
993 }
994
995 pub fn scale_fill_viridis(self) -> Self {
996 use crate::scale::color::ScaleColorDiscrete;
997 use crate::scale::palettes::PaletteName;
998 let s = ScaleColorDiscrete::new(crate::aes::Aesthetic::Fill)
999 .with_named_palette(&PaletteName::Viridis);
1000 self.scale_fill(s)
1001 }
1002
1003 pub fn scale_color_viridis_c(self) -> Self {
1005 use crate::scale::gradient_n::ScaleColorGradientN;
1006 let s = ScaleColorGradientN::viridis(crate::aes::Aesthetic::Color);
1007 self.scale_color(s)
1008 }
1009
1010 pub fn scale_fill_viridis_c(self) -> Self {
1012 use crate::scale::gradient_n::ScaleColorGradientN;
1013 let s = ScaleColorGradientN::viridis(crate::aes::Aesthetic::Fill);
1014 self.scale_fill(s)
1015 }
1016
1017 pub fn scale_color_gradientn(self, stops: Vec<(f64, crate::scale::color::RGBAColor)>) -> Self {
1019 use crate::scale::gradient_n::ScaleColorGradientN;
1020 let s = ScaleColorGradientN::new(crate::aes::Aesthetic::Color, stops);
1021 self.scale_color(s)
1022 }
1023
1024 pub fn scale_fill_gradientn(self, stops: Vec<(f64, crate::scale::color::RGBAColor)>) -> Self {
1026 use crate::scale::gradient_n::ScaleColorGradientN;
1027 let s = ScaleColorGradientN::new(crate::aes::Aesthetic::Fill, stops);
1028 self.scale_fill(s)
1029 }
1030
1031 pub fn scale_color_steps(
1034 self,
1035 low: crate::scale::color::RGBAColor,
1036 high: crate::scale::color::RGBAColor,
1037 n_bins: usize,
1038 ) -> Self {
1039 let s = crate::scale::steps::ScaleColorSteps::two(
1040 crate::aes::Aesthetic::Color,
1041 (low.r, low.g, low.b),
1042 (high.r, high.g, high.b),
1043 n_bins,
1044 );
1045 self.scale_color(s)
1046 }
1047
1048 pub fn scale_color_stepsn(
1050 self,
1051 stops: Vec<crate::scale::color::RGBAColor>,
1052 n_bins: usize,
1053 ) -> Self {
1054 let s = crate::scale::steps::ScaleColorSteps::new(
1055 crate::aes::Aesthetic::Color,
1056 stops.iter().map(|c| (c.r, c.g, c.b)).collect(),
1057 n_bins,
1058 );
1059 self.scale_color(s)
1060 }
1061
1062 pub fn scale_color_fermenter(
1064 self,
1065 name: crate::scale::palettes::PaletteName,
1066 n_bins: usize,
1067 ) -> Self {
1068 let stops = crate::scale::palettes::palette(&name)
1069 .iter()
1070 .map(|c| (c.r, c.g, c.b))
1071 .collect();
1072 let s =
1073 crate::scale::steps::ScaleColorSteps::new(crate::aes::Aesthetic::Color, stops, n_bins);
1074 self.scale_color(s)
1075 }
1076
1077 pub fn scale_fill_steps(
1079 self,
1080 low: crate::scale::color::RGBAColor,
1081 high: crate::scale::color::RGBAColor,
1082 n_bins: usize,
1083 ) -> Self {
1084 let s = crate::scale::steps::ScaleColorSteps::two(
1085 crate::aes::Aesthetic::Fill,
1086 (low.r, low.g, low.b),
1087 (high.r, high.g, high.b),
1088 n_bins,
1089 );
1090 self.scale_fill(s)
1091 }
1092
1093 pub fn scale_fill_fermenter(
1095 self,
1096 name: crate::scale::palettes::PaletteName,
1097 n_bins: usize,
1098 ) -> Self {
1099 let stops = crate::scale::palettes::palette(&name)
1100 .iter()
1101 .map(|c| (c.r, c.g, c.b))
1102 .collect();
1103 let s =
1104 crate::scale::steps::ScaleColorSteps::new(crate::aes::Aesthetic::Fill, stops, n_bins);
1105 self.scale_fill(s)
1106 }
1107
1108 pub fn scale_fill_discrete_sorted(self) -> Self {
1113 use crate::scale::color::ScaleColorDiscrete;
1114 self.scale_fill(ScaleColorDiscrete::new(crate::aes::Aesthetic::Fill).sorted())
1115 }
1116
1117 pub fn scale_color_discrete_sorted(self) -> Self {
1120 use crate::scale::color::ScaleColorDiscrete;
1121 self.scale_color(ScaleColorDiscrete::new(crate::aes::Aesthetic::Color).sorted())
1122 }
1123
1124 pub fn scale_fill_brewer(self, name: crate::scale::palettes::PaletteName) -> Self {
1125 use crate::scale::color::ScaleColorDiscrete;
1126 let s = ScaleColorDiscrete::new(crate::aes::Aesthetic::Fill).with_named_palette(&name);
1127 self.scale_fill(s)
1128 }
1129
1130 pub fn scale_linetype_manual(
1131 self,
1132 values: Vec<(&str, crate::render::backend::Linetype)>,
1133 ) -> Self {
1134 let s = crate::scale::linetype_manual::ScaleLinetypeManual::new(values);
1135 self.scale_color(s)
1136 }
1137
1138 pub fn scale_shape_manual(
1139 self,
1140 values: Vec<(&str, crate::render::backend::PointShape)>,
1141 ) -> Self {
1142 let s = crate::scale::shape_manual::ScaleShapeManual::new(values);
1143 self.scale_color(s)
1144 }
1145
1146 pub fn scale_color_grey(self) -> Self {
1147 let s = crate::scale::grey::ScaleColorGrey::new(crate::aes::Aesthetic::Color);
1148 self.scale_color(s)
1149 }
1150
1151 pub fn scale_fill_grey(self) -> Self {
1152 let s = crate::scale::grey::ScaleColorGrey::new(crate::aes::Aesthetic::Fill);
1153 self.scale_fill(s)
1154 }
1155
1156 pub fn scale_color_grey_with(self, s: crate::scale::grey::ScaleColorGrey) -> Self {
1157 self.scale_color(s)
1158 }
1159
1160 pub fn scale_fill_grey_with(self, s: crate::scale::grey::ScaleColorGrey) -> Self {
1161 self.scale_fill(s)
1162 }
1163
1164 pub fn scale_x_reverse(self) -> Self {
1165 self.scale_x_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Reverse))
1166 }
1167
1168 pub fn scale_y_reverse(self) -> Self {
1169 self.scale_y_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Reverse))
1170 }
1171
1172 pub fn scale_x_datetime(mut self, s: crate::scale::datetime::ScaleDateTime) -> Self {
1173 let s = s.for_aesthetic(crate::aes::Aesthetic::X);
1174 self.scales.push(Box::new(s));
1175 self
1176 }
1177
1178 pub fn scale_y_datetime(mut self, s: crate::scale::datetime::ScaleDateTime) -> Self {
1179 let s = s.for_aesthetic(crate::aes::Aesthetic::Y);
1180 self.scales.push(Box::new(s));
1181 self
1182 }
1183
1184 pub fn scale_size(mut self, s: crate::scale::size::ScaleSizeContinuous) -> Self {
1185 self.scales.push(Box::new(s));
1186 self
1187 }
1188
1189 pub fn scale_alpha(mut self, s: crate::scale::alpha::ScaleAlphaContinuous) -> Self {
1190 self.scales.push(Box::new(s));
1191 self
1192 }
1193
1194 pub fn xlim(self, min: f64, max: f64) -> Self {
1195 self.scale_x_continuous(ScaleContinuous::new().with_limits(min, max))
1196 }
1197
1198 pub fn ylim(self, min: f64, max: f64) -> Self {
1199 self.scale_y_continuous(ScaleContinuous::new().with_limits(min, max))
1200 }
1201
1202 pub fn scale_x_log10(self) -> Self {
1203 self.scale_x_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Log10))
1204 }
1205
1206 pub fn scale_y_log10(self) -> Self {
1207 self.scale_y_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Log10))
1208 }
1209
1210 pub fn scale_x_sqrt(self) -> Self {
1211 self.scale_x_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Sqrt))
1212 }
1213
1214 pub fn scale_y_sqrt(self) -> Self {
1215 self.scale_y_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Sqrt))
1216 }
1217
1218 pub fn scale_x_log2(self) -> Self {
1219 self.scale_x_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Log2))
1220 }
1221
1222 pub fn scale_y_log2(self) -> Self {
1223 self.scale_y_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Log2))
1224 }
1225
1226 pub fn scale_x_ln(self) -> Self {
1227 self.scale_x_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Ln))
1228 }
1229
1230 pub fn scale_y_ln(self) -> Self {
1231 self.scale_y_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Ln))
1232 }
1233
1234 pub fn scale_x_logit(self) -> Self {
1236 self.scale_x_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Logit))
1237 }
1238
1239 pub fn scale_y_logit(self) -> Self {
1240 self.scale_y_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Logit))
1241 }
1242
1243 pub fn scale_x_probit(self) -> Self {
1245 self.scale_x_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Probit))
1246 }
1247
1248 pub fn scale_y_probit(self) -> Self {
1249 self.scale_y_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Probit))
1250 }
1251
1252 pub fn scale_x_pseudo_log(self) -> Self {
1254 self.scale_x_continuous(ScaleContinuous::new().with_transform(ScaleTransform::PseudoLog))
1255 }
1256
1257 pub fn scale_y_pseudo_log(self) -> Self {
1258 self.scale_y_continuous(ScaleContinuous::new().with_transform(ScaleTransform::PseudoLog))
1259 }
1260
1261 pub fn scale_x_reciprocal(self) -> Self {
1263 self.scale_x_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Reciprocal))
1264 }
1265
1266 pub fn scale_y_reciprocal(self) -> Self {
1267 self.scale_y_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Reciprocal))
1268 }
1269
1270 pub fn scale_x_exp(self) -> Self {
1272 self.scale_x_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Exp))
1273 }
1274
1275 pub fn scale_y_exp(self) -> Self {
1276 self.scale_y_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Exp))
1277 }
1278
1279 pub fn scale_x_boxcox(self, lambda: f64) -> Self {
1281 self.scale_x_continuous(
1282 ScaleContinuous::new().with_transform(ScaleTransform::BoxCox(lambda)),
1283 )
1284 }
1285
1286 pub fn scale_y_boxcox(self, lambda: f64) -> Self {
1287 self.scale_y_continuous(
1288 ScaleContinuous::new().with_transform(ScaleTransform::BoxCox(lambda)),
1289 )
1290 }
1291
1292 pub fn facet_wrap(mut self, var: &str, ncol: Option<usize>) -> Self {
1295 self.facet = Facet::Wrap {
1296 var: var.to_string(),
1297 ncol,
1298 scales: FacetScales::Fixed,
1299 labeller: FacetLabeller::default(),
1300 };
1301 self
1302 }
1303
1304 pub fn facet_wrap_free(mut self, var: &str, ncol: Option<usize>, scales: FacetScales) -> Self {
1305 self.facet = Facet::Wrap {
1306 var: var.to_string(),
1307 ncol,
1308 scales,
1309 labeller: FacetLabeller::default(),
1310 };
1311 self
1312 }
1313
1314 pub fn facet_wrap_labeller(
1315 mut self,
1316 var: &str,
1317 ncol: Option<usize>,
1318 labeller: FacetLabeller,
1319 ) -> Self {
1320 self.facet = Facet::Wrap {
1321 var: var.to_string(),
1322 ncol,
1323 scales: FacetScales::Fixed,
1324 labeller,
1325 };
1326 self
1327 }
1328
1329 pub fn facet_grid(mut self, row: Option<&str>, col: Option<&str>) -> Self {
1330 self.facet = Facet::Grid {
1331 row_var: row.map(String::from),
1332 col_var: col.map(String::from),
1333 scales: FacetScales::Fixed,
1334 labeller: FacetLabeller::default(),
1335 space: FacetSpace::Fixed,
1336 };
1337 self
1338 }
1339
1340 pub fn facet_grid_free(
1341 mut self,
1342 row: Option<&str>,
1343 col: Option<&str>,
1344 scales: FacetScales,
1345 ) -> Self {
1346 self.facet = Facet::Grid {
1347 row_var: row.map(String::from),
1348 col_var: col.map(String::from),
1349 scales,
1350 labeller: FacetLabeller::default(),
1351 space: FacetSpace::Fixed,
1352 };
1353 self
1354 }
1355
1356 pub fn facet_grid_multi(
1360 mut self,
1361 row: Option<&str>,
1362 cols: &[&str],
1363 scales: FacetScales,
1364 space: FacetSpace,
1365 ) -> Self {
1366 let col_var = if cols.len() > 1 {
1367 let n = self.data.nrows();
1369 let mut combined = Vec::with_capacity(n);
1370 for i in 0..n {
1371 let parts: Vec<String> = cols
1372 .iter()
1373 .map(|c| {
1374 self.data
1375 .column(c)
1376 .and_then(|col| col.get(i))
1377 .map(|v| v.to_group_key())
1378 .unwrap_or_default()
1379 })
1380 .collect();
1381 combined.push(crate::data::Value::Str(parts.join(" . ")));
1382 }
1383 let name = "__facet_cols__".to_string();
1384 self.data.add_column(name.clone(), combined);
1385 Some(name)
1386 } else {
1387 cols.first().map(|s| s.to_string())
1388 };
1389 self.facet = Facet::Grid {
1390 row_var: row.map(String::from),
1391 col_var,
1392 scales,
1393 labeller: FacetLabeller::default(),
1394 space,
1395 };
1396 self
1397 }
1398
1399 pub fn facet_grid_space(
1402 mut self,
1403 row: Option<&str>,
1404 col: Option<&str>,
1405 scales: FacetScales,
1406 space: FacetSpace,
1407 ) -> Self {
1408 self.facet = Facet::Grid {
1409 row_var: row.map(String::from),
1410 col_var: col.map(String::from),
1411 scales,
1412 labeller: FacetLabeller::default(),
1413 space,
1414 };
1415 self
1416 }
1417
1418 pub fn facet_grid_labeller(
1419 mut self,
1420 row: Option<&str>,
1421 col: Option<&str>,
1422 labeller: FacetLabeller,
1423 ) -> Self {
1424 self.facet = Facet::Grid {
1425 row_var: row.map(String::from),
1426 col_var: col.map(String::from),
1427 scales: FacetScales::Fixed,
1428 labeller,
1429 space: FacetSpace::Fixed,
1430 };
1431 self
1432 }
1433
1434 pub fn coord_flip(mut self) -> Self {
1437 self.coord = Box::new(CoordFlip);
1438 self
1439 }
1440
1441 pub fn coord_fixed(mut self, ratio: f64) -> Self {
1442 self.coord = Box::new(CoordFixed::new(ratio));
1443 self
1444 }
1445
1446 #[cfg(feature = "sf")]
1450 pub fn coord_sf(mut self) -> Self {
1451 self.coord = Box::new(crate::coord::sf::CoordSf::new());
1452 self
1453 }
1454
1455 pub fn coord_trans(mut self, x: Option<ScaleTransform>, y: Option<ScaleTransform>) -> Self {
1460 self.coord = Box::new(crate::coord::trans::CoordTrans::new(x, y));
1461 self
1462 }
1463
1464 pub fn coord_trans_y(self, y: ScaleTransform) -> Self {
1466 self.coord_trans(None, Some(y))
1467 }
1468
1469 pub fn coord_trans_x(self, x: ScaleTransform) -> Self {
1471 self.coord_trans(Some(x), None)
1472 }
1473
1474 pub fn coord_cartesian_zoom(
1476 mut self,
1477 xlim: Option<(f64, f64)>,
1478 ylim: Option<(f64, f64)>,
1479 ) -> Self {
1480 let mut c = CoordCartesian::new();
1481 if let Some((min, max)) = xlim {
1482 c = c.xlim(min, max);
1483 }
1484 if let Some((min, max)) = ylim {
1485 c = c.ylim(min, max);
1486 }
1487 self.coord = Box::new(c);
1488 self
1489 }
1490
1491 pub fn coord_polar(mut self) -> Self {
1492 self.coord = Box::new(CoordPolar::new());
1493 self
1494 }
1495
1496 pub fn coord_radar(mut self) -> Self {
1500 self.coord = Box::new(crate::coord::radar::CoordRadar::new());
1501 self
1502 }
1503
1504 pub fn coord_radar_with(mut self, coord: crate::coord::radar::CoordRadar) -> Self {
1505 self.coord = Box::new(coord);
1506 self
1507 }
1508
1509 pub fn coord_polar_with(mut self, coord: CoordPolar) -> Self {
1510 self.coord = Box::new(coord);
1511 self
1512 }
1513
1514 pub fn theme(mut self, theme: Theme) -> Self {
1519 self.apply_preset(theme);
1520 self
1521 }
1522
1523 fn apply_preset(&mut self, theme: Theme) {
1524 let primary = self.theme.primary;
1525 self.theme = theme;
1526 if self.theme.primary.is_none() {
1527 self.theme.primary = primary;
1528 }
1529 }
1530
1531 pub fn axis_text_x_angle(mut self, degrees: f64) -> Self {
1535 self.theme.axis_text_x.angle = degrees;
1536 self
1537 }
1538
1539 pub fn axis_text_y_angle(mut self, degrees: f64) -> Self {
1541 self.theme.axis_text_y.angle = degrees;
1542 self
1543 }
1544
1545 pub fn axis_text_x_dodge(mut self, n: usize) -> Self {
1548 self.theme.axis_text_x_dodge = n.max(1);
1549 self
1550 }
1551
1552 pub fn aspect_ratio(mut self, ratio: f64) -> Self {
1555 self.theme.aspect_ratio = Some(ratio);
1556 self
1557 }
1558
1559 pub fn panel_ontop(mut self) -> Self {
1561 self.theme.panel_ontop = true;
1562 self
1563 }
1564
1565 pub fn axis_minor_ticks(mut self) -> Self {
1567 self.theme.axis_minor_ticks = true;
1568 self
1569 }
1570
1571 pub fn title_position(mut self, pos: crate::theme::TitlePosition) -> Self {
1574 self.theme.title_position = pos;
1575 self
1576 }
1577
1578 pub fn tag_position(mut self, pos: crate::theme::TagPosition) -> Self {
1580 self.theme.tag_position = pos;
1581 self
1582 }
1583
1584 pub fn legend_direction(mut self, dir: crate::theme::LegendDirection) -> Self {
1586 self.theme.legend_direction = Some(dir);
1587 self
1588 }
1589
1590 pub fn legend_position_inside(mut self, x: f64, y: f64) -> Self {
1597 self.theme.legend_position = crate::theme::LegendPosition::Inside(x, y);
1598 self
1599 }
1600
1601 pub fn legend_position(mut self, pos: crate::theme::LegendPosition) -> Self {
1603 self.theme.legend_position = pos;
1604 self
1605 }
1606
1607 pub fn primary_color(mut self, color: (u8, u8, u8)) -> Self {
1608 self.theme.primary = Some(color);
1609 self
1610 }
1611
1612 pub fn theme_minimal(mut self) -> Self {
1613 self.apply_preset(crate::theme::presets::theme_minimal());
1614 self
1615 }
1616
1617 pub fn theme_bw(mut self) -> Self {
1618 self.apply_preset(crate::theme::presets::theme_bw());
1619 self
1620 }
1621
1622 pub fn theme_gray(mut self) -> Self {
1623 self.apply_preset(crate::theme::presets::theme_gray());
1624 self
1625 }
1626
1627 pub fn theme_classic(mut self) -> Self {
1628 self.apply_preset(crate::theme::presets::theme_classic());
1629 self
1630 }
1631
1632 pub fn theme_pubr(mut self) -> Self {
1634 self.apply_preset(crate::theme::presets::theme_pubr());
1635 self
1636 }
1637
1638 pub fn theme_linedraw(mut self) -> Self {
1639 self.apply_preset(crate::theme::presets::theme_linedraw());
1640 self
1641 }
1642
1643 pub fn theme_light(mut self) -> Self {
1644 self.apply_preset(crate::theme::presets::theme_light());
1645 self
1646 }
1647
1648 pub fn theme_dark(mut self) -> Self {
1649 self.apply_preset(crate::theme::presets::theme_dark());
1650 self
1651 }
1652
1653 pub fn theme_void(mut self) -> Self {
1654 self.apply_preset(crate::theme::presets::theme_void());
1655 self
1656 }
1657
1658 pub fn theme_update(mut self, update: crate::theme::ThemeUpdate) -> Self {
1661 self.theme = self.theme.update(update);
1662 self
1663 }
1664
1665 pub fn guides(mut self, guide: crate::guide::config::GuideLegend) -> Self {
1669 self.guide_legend = guide;
1670 self
1671 }
1672
1673 pub fn labs(mut self, labels: Labels) -> Self {
1676 if labels.title.is_some() {
1677 self.labels.title = labels.title;
1678 }
1679 if labels.subtitle.is_some() {
1680 self.labels.subtitle = labels.subtitle;
1681 }
1682 if labels.x.is_some() {
1683 self.labels.x = labels.x;
1684 }
1685 if labels.y.is_some() {
1686 self.labels.y = labels.y;
1687 }
1688 if labels.caption.is_some() {
1689 self.labels.caption = labels.caption;
1690 }
1691 if labels.tag.is_some() {
1692 self.labels.tag = labels.tag;
1693 }
1694 self
1695 }
1696
1697 pub fn title(mut self, title: &str) -> Self {
1698 self.labels.title = Some(title.to_string());
1699 self
1700 }
1701
1702 pub fn tag(mut self, tag: &str) -> Self {
1705 self.labels.tag = Some(tag.to_string());
1706 self
1707 }
1708
1709 pub fn subtitle(mut self, subtitle: &str) -> Self {
1710 self.labels.subtitle = Some(subtitle.to_string());
1711 self
1712 }
1713
1714 pub fn xlab(mut self, label: &str) -> Self {
1715 self.labels.x = Some(label.to_string());
1716 self
1717 }
1718
1719 pub fn ylab(mut self, label: &str) -> Self {
1720 self.labels.y = Some(label.to_string());
1721 self
1722 }
1723
1724 pub fn caption(mut self, caption: &str) -> Self {
1725 self.labels.caption = Some(caption.to_string());
1726 self
1727 }
1728
1729 pub fn annotate(mut self, annotation: Annotation) -> Self {
1733 self.annotations.push(annotation);
1734 self
1735 }
1736
1737 pub fn annotate_text(self, label: &str, x: f64, y: f64) -> Self {
1739 self.annotate(Annotation::text(label, x, y))
1740 }
1741
1742 pub fn annotate_rect(self, xmin: f64, xmax: f64, ymin: f64, ymax: f64) -> Self {
1744 self.annotate(Annotation::rect(xmin, xmax, ymin, ymax))
1745 }
1746
1747 pub fn annotate_segment(self, x: f64, y: f64, xend: f64, yend: f64) -> Self {
1749 self.annotate(Annotation::segment(x, y, xend, yend))
1750 }
1751
1752 pub fn try_build(self) -> Result<crate::build::BuiltPlot, GGError> {
1756 PlotBuilder::build(self)
1757 }
1758
1759 pub fn build(self) -> crate::build::BuiltPlot {
1763 self.try_build().expect("plot build failed")
1764 }
1765
1766 #[cfg(all(feature = "plotters", not(target_arch = "wasm32")))]
1770 pub fn save(self, path: &str) -> Result<(), GGError> {
1771 self.save_with_size(path, 800, 600)
1772 }
1773
1774 #[cfg(all(feature = "plotters", not(target_arch = "wasm32")))]
1776 pub fn save_with_size(self, path: &str, w: u32, h: u32) -> Result<(), GGError> {
1777 let (built, layout) = self.prepare(w, h)?;
1778
1779 let ext = path.rsplit('.').next().unwrap_or("svg").to_lowercase();
1781
1782 match ext.as_str() {
1783 "svg" => {
1784 let backend = plotters::prelude::SVGBackend::new(path, (w, h));
1785 Self::render_into(backend.into_drawing_area(), &built, &layout)?;
1786 }
1787 "png" | "bmp" | "gif" | "jpeg" | "jpg" | "tiff" => {
1788 let backend = plotters::prelude::BitMapBackend::new(path, (w, h));
1789 Self::render_into(backend.into_drawing_area(), &built, &layout)?;
1790 }
1791 _ => {
1792 return Err(GGError::UnsupportedFormat(ext));
1793 }
1794 }
1795
1796 Ok(())
1797 }
1798
1799 #[cfg(all(feature = "plotters", not(target_arch = "wasm32")))]
1805 pub fn render_svg(self) -> Result<String, GGError> {
1806 self.render_svg_with_size(800, 600)
1807 }
1808
1809 #[cfg(all(feature = "plotters", not(target_arch = "wasm32")))]
1813 pub fn render_svg_with_size(self, w: u32, h: u32) -> Result<String, GGError> {
1814 let (built, layout) = self.prepare(w, h)?;
1815 let mut buf = String::new();
1816 {
1817 let backend = plotters::prelude::SVGBackend::with_string(&mut buf, (w, h));
1818 Self::render_into(backend.into_drawing_area(), &built, &layout)?;
1819 }
1820 Ok(buf)
1821 }
1822
1823 pub fn render_svg_native(self) -> Result<String, GGError> {
1827 self.render_svg_native_with_size(800, 600)
1828 }
1829
1830 pub fn render_svg_native_with_size(self, w: u32, h: u32) -> Result<String, GGError> {
1838 Ok(self.render_native(w, h)?.0.finish())
1839 }
1840
1841 pub fn render_svg_native_with_warnings(
1846 self,
1847 w: u32,
1848 h: u32,
1849 ) -> Result<(String, Vec<String>), GGError> {
1850 let (backend, warnings, _) = self.render_native(w, h)?;
1851 Ok((backend.finish(), warnings))
1852 }
1853
1854 pub fn render_svg_native_at(self, x: f64, y: f64, w: u32, h: u32) -> Result<String, GGError> {
1866 Ok(self.render_native(w, h)?.0.finish_fragment(x, y))
1867 }
1868
1869 pub fn render_svg_area_with_size(self, w: u32, h: u32) -> Result<(String, [f64; 4]), GGError> {
1873 let (backend, _, pa) = self.render_native(w, h)?;
1874 Ok((backend.finish(), [pa.x, pa.y, pa.width, pa.height]))
1875 }
1876
1877 fn render_native(
1881 self,
1882 w: u32,
1883 h: u32,
1884 ) -> Result<
1885 (
1886 crate::render::svg_backend::SvgBackend,
1887 Vec<String>,
1888 crate::render::Rect,
1889 ),
1890 GGError,
1891 > {
1892 let (built, layout) = self.prepare(w, h)?;
1893 let pa = layout.plot_area.clone();
1894 let mut backend = crate::render::svg_backend::SvgBackend::new(w, h, pa.clone());
1895 backend.set_root_attrs(crate::render::svg_backend::root_data_attrs(&built));
1896 PlotRenderer::render(&built, &mut backend).map_err(GGError::Render)?;
1897 Ok((backend, built.warnings, pa))
1898 }
1899
1900 #[cfg(feature = "canvas")]
1905 pub fn render_rgba_with_size(self, w: u32, h: u32) -> Result<(u32, u32, Vec<u8>), GGError> {
1906 let (built, layout) = self.prepare(w, h)?;
1907 let mut backend =
1908 crate::render::pixel_backend::PixelBackend::new(w, h, layout.plot_area.clone());
1909 PlotRenderer::render(&built, &mut backend).map_err(GGError::Render)?;
1910 let (ow, oh) = backend.dimensions();
1911 Ok((ow, oh, backend.into_rgba()))
1912 }
1913
1914 #[cfg(feature = "canvas")]
1918 pub fn render_rgba_area_with_size(
1919 self,
1920 w: u32,
1921 h: u32,
1922 ) -> Result<(Vec<u8>, [f64; 4]), GGError> {
1923 let (built, layout) = self.prepare(w, h)?;
1924 let pa = layout.plot_area.clone();
1925 let mut backend = crate::render::pixel_backend::PixelBackend::new(w, h, pa.clone());
1926 PlotRenderer::render(&built, &mut backend).map_err(GGError::Render)?;
1927 Ok((backend.into_rgba(), [pa.x, pa.y, pa.width, pa.height]))
1928 }
1929
1930 #[cfg(feature = "canvas")]
1934 pub fn render_png_raster_with_size(self, w: u32, h: u32) -> Result<Vec<u8>, GGError> {
1935 let (built, layout) = self.prepare(w, h)?;
1936 let mut backend =
1937 crate::render::pixel_backend::PixelBackend::new(w, h, layout.plot_area.clone());
1938 PlotRenderer::render(&built, &mut backend).map_err(GGError::Render)?;
1939 backend.into_png().map_err(GGError::Render)
1940 }
1941
1942 #[cfg(all(feature = "plotters", not(target_arch = "wasm32")))]
1949 pub fn render_png(self) -> Result<Vec<u8>, GGError> {
1950 self.render_png_with_size(800, 600)
1951 }
1952
1953 #[cfg(all(feature = "plotters", not(target_arch = "wasm32")))]
1956 pub fn render_png_with_size(self, w: u32, h: u32) -> Result<Vec<u8>, GGError> {
1957 let (built, layout) = self.prepare(w, h)?;
1958
1959 let mut rgb = vec![0u8; (w as usize) * (h as usize) * 3];
1962 {
1963 let backend = plotters::prelude::BitMapBackend::with_buffer(&mut rgb, (w, h));
1964 Self::render_into(backend.into_drawing_area(), &built, &layout)?;
1965 }
1966
1967 let img = image::RgbImage::from_raw(w, h, rgb).ok_or_else(|| {
1968 GGError::Render(RenderError::BackendError(
1969 "PNG buffer size mismatch".to_string(),
1970 ))
1971 })?;
1972 let mut out = std::io::Cursor::new(Vec::new());
1973 img.write_to(&mut out, image::ImageOutputFormat::Png)
1974 .map_err(|e| GGError::Render(RenderError::BackendError(format!("{:?}", e))))?;
1975 Ok(out.into_inner())
1976 }
1977
1978 fn prepare(self, w: u32, h: u32) -> Result<(crate::build::BuiltPlot, PlotLayout), GGError> {
1980 let plot = self;
1981
1982 let has_title = plot.labels.title.is_some();
1983 let has_subtitle = plot.labels.subtitle.is_some();
1984 let has_caption = plot.labels.caption.is_some();
1985 let has_legend = plot.has_legend_mapping();
1986 let x_label = plot.labels.x.clone();
1987 let y_label = plot.labels.y.clone();
1988
1989 let mut built = PlotBuilder::build(plot)?;
1990
1991 built.theme.resolve_inheritance();
1993
1994 if let Some(ref label) = x_label {
1996 if let Some(s) = built.scales.get_mut(&crate::aes::Aesthetic::X) {
1997 s.set_name(label);
1998 }
1999 }
2000 if let Some(ref label) = y_label {
2001 if let Some(s) = built.scales.get_mut(&crate::aes::Aesthetic::Y) {
2002 s.set_name(label);
2003 }
2004 }
2005
2006 let x_axis_top = built
2007 .scales
2008 .get(&crate::aes::Aesthetic::X)
2009 .map(|s| s.axis_position_opposite())
2010 .unwrap_or(false);
2011
2012 let flipped = built.coord.is_flipped();
2016 let h_aes = if flipped {
2017 crate::aes::Aesthetic::Y
2018 } else {
2019 crate::aes::Aesthetic::X
2020 };
2021 let v_aes = if flipped {
2022 crate::aes::Aesthetic::X
2023 } else {
2024 crate::aes::Aesthetic::Y
2025 };
2026
2027 let x_rot: Option<(f64, f64)> =
2031 if built.theme.axis_text_x.visible && built.theme.axis_text_x.angle.abs() < 1.0 {
2032 built.scales.get(&h_aes).and_then(|hs| {
2033 if !hs.is_discrete() {
2034 return None;
2035 }
2036 let breaks = hs.breaks();
2037 let n = breaks.len().max(1) as f64;
2038 let max_ch = breaks
2039 .iter()
2040 .map(|(_, l)| l.chars().count())
2041 .max()
2042 .unwrap_or(0) as f64;
2043 let font = built.theme.axis_text_x.size;
2044 let label_w = max_ch * font * 0.6; let spacing = 0.9 * w as f64 / n; if label_w <= spacing {
2047 return None; }
2049 let vertical = label_w * 0.707 > spacing;
2053 let angle = if vertical { 270.0 } else { 45.0 };
2054 let drop = if vertical { label_w } else { label_w * 0.707 };
2055 Some((angle, drop + font + 4.0))
2056 })
2057 } else {
2058 None
2059 };
2060 let x_label_height = x_rot.map(|(_, drop)| drop);
2061 if let Some((angle, _)) = x_rot {
2062 built.theme.axis_text_x.angle = angle;
2063 }
2064
2065 let y_label_width = if built.theme.axis_text_y.visible {
2069 built.scales.get(&v_aes).map(|vs| {
2070 let max_ch = vs
2071 .breaks()
2072 .iter()
2073 .map(|(_, l)| l.chars().count())
2074 .max()
2075 .unwrap_or(0);
2076 let measured = max_ch as f64 * built.theme.axis_text_y.size * 0.6 + 4.0;
2077 let default = built.theme.axis_text_y.size * 3.5 + 4.0;
2078 measured.max(default).min(0.35 * w as f64)
2079 })
2080 } else {
2081 None
2082 };
2083
2084 let layout = PlotLayout::compute_full(
2085 w as f64,
2086 h as f64,
2087 &built.theme,
2088 has_title,
2089 has_subtitle,
2090 has_caption,
2091 has_legend,
2092 x_axis_top,
2093 y_label_width,
2094 x_label_height,
2095 );
2096
2097 Ok((built, layout))
2098 }
2099
2100 #[cfg(all(feature = "plotters", not(target_arch = "wasm32")))]
2103 fn render_into<DB>(
2104 area: plotters::drawing::DrawingArea<DB, plotters::coord::Shift>,
2105 built: &crate::build::BuiltPlot,
2106 layout: &PlotLayout,
2107 ) -> Result<(), GGError>
2108 where
2109 DB: plotters::prelude::DrawingBackend,
2110 DB::ErrorType: 'static,
2111 {
2112 area.fill(&plotters::prelude::WHITE)
2113 .map_err(|e| GGError::Render(RenderError::BackendError(format!("{:?}", e))))?;
2114 let mut adapter = PlottersAdapter::new(&area, layout.plot_area.clone());
2115 PlotRenderer::render(built, &mut adapter).map_err(GGError::Render)?;
2116 area.present()
2117 .map_err(|e| GGError::Render(RenderError::BackendError(format!("{:?}", e))))?;
2118 Ok(())
2119 }
2120
2121 #[cfg(all(feature = "plotters", not(target_arch = "wasm32")))]
2124 pub fn ggsave(
2125 self,
2126 path: &str,
2127 width_inches: f64,
2128 height_inches: f64,
2129 dpi: f64,
2130 ) -> Result<(), GGError> {
2131 let w = (width_inches * dpi) as u32;
2132 let h = (height_inches * dpi) as u32;
2133 self.save_with_size(path, w, h)
2134 }
2135
2136 fn has_legend_mapping(&self) -> bool {
2137 self.mapping.mappings.iter().any(|m| {
2138 matches!(
2139 m.aesthetic,
2140 crate::aes::Aesthetic::Color
2141 | crate::aes::Aesthetic::Fill
2142 | crate::aes::Aesthetic::Shape
2143 | crate::aes::Aesthetic::Linetype
2144 | crate::aes::Aesthetic::Size
2145 | crate::aes::Aesthetic::Alpha
2146 )
2147 })
2148 }
2149}
2150
2151#[derive(Debug)]
2153pub enum GGError {
2154 Render(RenderError),
2155 UnsupportedFormat(String),
2156 Io(std::io::Error),
2157 ValidationError(String),
2158}
2159
2160impl std::fmt::Display for GGError {
2161 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2162 match self {
2163 GGError::Render(e) => write!(f, "Render error: {e}"),
2164 GGError::UnsupportedFormat(ext) => write!(f, "Unsupported output format: {ext}"),
2165 GGError::Io(e) => write!(f, "IO error: {e}"),
2166 GGError::ValidationError(msg) => write!(f, "Validation error: {msg}"),
2167 }
2168 }
2169}
2170
2171impl std::error::Error for GGError {}