pub mod jointplot;
pub mod pairplot;
pub use jointplot::{
JointKind, JointPlotConfig, JointPlotLayout, MarginalHistogram, compute_marginal_histogram,
joint_plot_layout, jointplot, jointplot_with, panel_config,
};
pub use pairplot::{
DiagKind, MAX_PAIRPLOT_VARIABLES, OffDiagKind, PairPlotCell, PairPlotConfig, PairPlotLayout,
cell_variable_names, compute_pairplot_layout, pairplot, pairplot_with,
};
#[cfg(test)]
mod the_module_doc_is_true {
use super::*;
fn sample() -> (Vec<f64>, Vec<f64>) {
let x: Vec<f64> = (0..80).map(|i| i as f64 * 0.25).collect();
let y: Vec<f64> = x.iter().map(|v| v.sin()).collect();
(x, y)
}
fn loud_joint_config() -> JointPlotConfig {
JointPlotConfig::default()
.marginal_hist(false)
.marginal_kde(false)
.rugplot(true)
.bins(7)
.color(crate::render::Color::from_rgb(1, 2, 3))
}
#[test]
fn joint_plot_layout_still_depends_only_on_the_marginal_ratio() {
let quiet = joint_plot_layout(JointPlotConfig::default().marginal_ratio);
let loud = joint_plot_layout(loud_joint_config().marginal_ratio);
assert_eq!(quiet, loud);
assert_ne!(quiet.main_bounds, joint_plot_layout(0.4).main_bounds);
}
#[test]
fn the_appearance_fields_reach_the_figure() {
let (x, y) = sample();
let blank = JointPlotConfig::default()
.marginal_hist(false)
.marginal_kde(false);
assert_eq!(
jointplot_with(&x, &y, 400, 400, blank.clone())
.unwrap()
.axes_count(),
1
);
assert_eq!(
jointplot_with(&x, &y, 400, 400, blank.rugplot(true))
.unwrap()
.axes_count(),
3
);
assert_eq!(
jointplot_with(&x, &y, 400, 400, loud_joint_config())
.unwrap()
.axes_count(),
3
);
}
#[test]
fn the_kinds_without_a_renderer_say_so() {
let (x, y) = sample();
for kind in [JointKind::Reg, JointKind::Kde, JointKind::Resid] {
assert!(
jointplot_with(&x, &y, 400, 400, JointPlotConfig::default().kind(kind)).is_err(),
"{kind:?} is documented as undrawable and must not silently \
render as something else"
);
}
for kind in [OffDiagKind::Reg, OffDiagKind::Kde] {
let config = PairPlotConfig::default().off_diag_kind(kind);
assert!(pairplot_with(&[x.clone(), y.clone()], 400, 400, config).is_err());
}
}
#[test]
fn pairplot_layout_reads_only_the_three_triangle_flags() {
let base = PairPlotConfig {
vars: vec!["a".into(), "b".into(), "c".into()],
..Default::default()
};
let styled = PairPlotConfig {
diag_kind: DiagKind::Kde,
off_diag_kind: OffDiagKind::Reg,
colors: Some(vec![crate::render::Color::from_rgb(9, 9, 9)]),
scatter_size: 42.0,
scatter_alpha: 0.1,
bins: 99,
..base.clone()
};
let quiet = compute_pairplot_layout(3, &base);
let loud = compute_pairplot_layout(3, &styled);
assert_eq!(quiet.cells.len(), loud.cells.len());
for (a, b) in quiet.cells.iter().zip(&loud.cells) {
assert_eq!(a.bounds, b.bounds);
assert_eq!(a.var_indices, b.var_indices);
}
let lower_only = PairPlotConfig {
upper: false,
diag: false,
..base
};
let lower_cells = compute_pairplot_layout(3, &lower_only).cells.len();
assert!(lower_cells < quiet.cells.len());
}
#[test]
fn both_composers_return_the_same_figure_type_as_subplots() {
let (x, y) = sample();
let extended = jointplot(&x, &y, 600, 600)
.unwrap()
.suptitle("joint")
.add_axes([0.82, 0.82, 0.16, 0.16], crate::core::Plot::new())
.unwrap();
assert_eq!(extended.axes_count(), 4);
let extended = pairplot(&[x, y], 600, 600)
.unwrap()
.theme(crate::render::Theme::dark())
.add_axes([0.82, 0.82, 0.16, 0.16], crate::core::Plot::new())
.unwrap();
assert_eq!(extended.axes_count(), 5);
}
}