1pub mod align;
2pub mod arcdiagram;
3pub mod bin;
4pub mod bin2d;
5pub mod bindot;
6pub mod binhex;
7pub mod boxplot;
8pub mod calendar;
9pub mod chord;
10#[cfg(feature = "ggpubr")]
11pub mod compare_means;
12pub mod contour;
13pub mod contour_filled;
14#[cfg(feature = "ggpubr")]
15pub mod cor;
16pub mod count;
17pub mod density;
18pub mod density2d;
19pub mod dist;
20pub mod distribution;
21pub mod ecdf;
22pub mod ellipse;
23pub mod function;
24pub mod funnel;
25pub(crate) mod gam;
26pub mod heikin_ashi;
27pub mod identity;
28pub mod indicator;
29pub mod loess;
30pub mod marching_squares;
31pub mod marimekko;
32pub mod network;
33pub mod pack;
34pub mod pareto;
35pub mod partition;
36pub mod qq;
37#[cfg(feature = "regression")]
38pub mod quantile;
39pub mod renko;
40pub mod sankey;
41pub mod smooth;
42pub mod sum;
43pub mod summary;
44pub mod summary2d;
45pub mod summary_bin;
46pub mod tree;
47pub mod treemap;
48pub mod venn;
49pub mod waffle;
50pub mod waterfall;
51pub mod xdensity_ridges;
52pub mod ydensity;
53
54use crate::aes::{Aes, Aesthetic};
55use crate::data::DataFrame;
56use crate::scale::ScaleSet;
57
58pub trait Stat: Send + Sync {
60 fn compute_group(&self, data: &DataFrame, scales: &ScaleSet) -> DataFrame;
62
63 fn required_aes(&self) -> Vec<Aesthetic>;
65
66 fn default_aes(&self) -> Aes {
68 Aes::default()
69 }
70
71 fn panelwise(&self) -> bool {
76 false
77 }
78
79 fn name(&self) -> &str;
81
82 fn validate(&self, _warnings: &mut Vec<String>) {}
90}
91
92pub(crate) fn bw_nrd0(values: &[f64]) -> f64 {
96 let n = values.len();
97 if n < 2 {
98 return 1.0;
99 }
100 let nf = n as f64;
101 let mean = values.iter().sum::<f64>() / nf;
102 let sd = (values.iter().map(|x| (x - mean).powi(2)).sum::<f64>() / (nf - 1.0)).sqrt();
103 let mut sorted = values.to_vec();
104 sorted.sort_by(|a, b| a.total_cmp(b));
105 let q = |p: f64| {
106 let h = (n - 1) as f64 * p;
107 let lo = h.floor() as usize;
108 let hi = (lo + 1).min(n - 1);
109 sorted[lo] + (h - lo as f64) * (sorted[hi] - sorted[lo])
110 };
111 let iqr = q(0.75) - q(0.25);
112 let mut lo = sd.min(iqr / 1.34);
113 for fallback in [sd, values[0].abs(), 1.0] {
114 if lo > 0.0 && lo.is_finite() {
115 break;
116 }
117 lo = fallback;
118 }
119 0.9 * lo * nf.powf(-0.2)
120}