2D Histogram

A 2D histogram (density map) bins scatter points (x, y) into a rectangular grid and colors each cell by its count. The colorbar labeled "Count" is added to the right margin automatically. Use it to visualize the joint distribution of two continuous variables.

Import path: kuva::plot::Histogram2D, kuva::plot::histogram2d::ColorMap


Basic usage

Pass (x, y) scatter points along with explicit axis ranges and bin counts to .with_data(). Points outside the specified ranges are silently discarded.

#![allow(unused)]
fn main() {
use kuva::plot::Histogram2D;
use kuva::backend::svg::SvgBackend;
use kuva::render::render::render_multiple;
use kuva::render::layout::Layout;
use kuva::render::plots::Plot;

// (x, y) scatter points — e.g. from a 2D measurement
let data: Vec<(f64, f64)> = vec![];  // ...your data here

let hist = Histogram2D::new()
    .with_data(data, (0.0, 30.0), (0.0, 30.0), 30, 30);

let plots = vec![Plot::Histogram2d(hist)];
let layout = Layout::auto_from_plots(&plots)
    .with_title("2D Histogram — Viridis")
    .with_x_label("X")
    .with_y_label("Y");

let svg = SvgBackend.render_scene(&render_multiple(plots, layout));
std::fs::write("hist2d.svg", svg).unwrap();
}
2D histogram — single Gaussian cluster, Viridis colormap

A single bivariate Gaussian cluster binned into a 30×30 grid. The Viridis colorbar on the right shows the count scale from zero (dark blue) to the maximum (yellow).


Correlation annotation

.with_correlation() computes the Pearson r coefficient from the raw scatter points and prints it in the top-right corner.

#![allow(unused)]
fn main() {
use kuva::plot::Histogram2D;
use kuva::render::plots::Plot;
let hist = Histogram2D::new()
    .with_data(data, (0.0, 20.0), (0.0, 20.0), 25, 25)
    .with_correlation();
}
2D histogram with Pearson r = 0.85 annotation

The diagonal density ridge reflects a strong positive correlation (r ≈ 0.85). The coefficient is computed from all input points, including those clipped outside the plot range.


Bimodal data — Inferno colormap

ColorMap::Inferno maps low counts to near-black and high counts to bright yellow. It is effective for high-contrast visualization of structured or multi-modal data.

#![allow(unused)]
fn main() {
use kuva::plot::Histogram2D;
use kuva::plot::histogram2d::ColorMap;
use kuva::render::plots::Plot;

let hist = Histogram2D::new()
    .with_data(data, (0.0, 30.0), (0.0, 30.0), 30, 30)
    .with_color_map(ColorMap::Inferno);
}
2D histogram — bimodal distribution, Inferno colormap

Two Gaussian clusters in opposite corners of the grid, visible as bright islands against the dark background. Empty bins are not drawn, preserving the black background of Inferno.


Bin resolution

Bin count controls the trade-off between noise and detail.

ColorMap::Grayscale maps zero to white and the maximum to black — useful for printing or publication figures.

2D histogram — 10×10 coarse bins, Grayscale

10×10 bins smooth the distribution and make the Gaussian shape immediately obvious, but lose fine-grained density structure.

ColorMap::Viridis (the default) uses a perceptually uniform blue → green → yellow scale, making density gradients easy to read at high resolution.

2D histogram — 50×50 fine bins, Viridis

50×50 bins reveal the internal shape of the distribution, though individual cells become noisier at lower sample counts.


Range convention

The axis is calibrated directly to the physical x_range / y_range values you supply, so tick labels always show real data units regardless of bin count. Any (min, max) pair works.

Rangebins_xBin width
(0.0, 30.0)301.0
(0.0, 20.0)250.8
(5.0, 25.0)201.0

Log color scale

When a small number of bins dominate the count (a dense core surrounded by sparse tails), the linear color scale washes out low-density structure. .with_log_count() compresses the dynamic range via ln(count + 1), keeping both the core and the halo visible. The colorbar label updates to "log(Count)" automatically.

#![allow(unused)]
fn main() {
use kuva::plot::Histogram2D;
use kuva::plot::histogram2d::ColorMap;
use kuva::render::plots::Plot;
let hist = Histogram2D::new()
    .with_data(data, (0.0, 30.0), (0.0, 30.0), 30, 30)
    .with_color_map(ColorMap::Inferno)
    .with_log_count();
}

Linear — the dense core saturates the colormap; the surrounding halo is invisible.

2D histogram — linear color scale, halo invisible

Log — the same data with with_log_count(). The halo structure is now visible alongside the core.

2D histogram — log color scale, halo visible

Colorbar tick format

By default (TickFormat::Auto) colorbar tick labels render as plain integers and switch to scientific notation automatically when counts reach 10 000 or more. You can override this with Layout::with_colorbar_tick_format().

#![allow(unused)]
fn main() {
use kuva::plot::Histogram2D;
use kuva::render::plots::Plot;
use kuva::render::layout::{Layout, TickFormat};

let plots = vec![Plot::Histogram2d(hist)];
let layout = Layout::auto_from_plots(&plots)
    .with_colorbar_tick_format(TickFormat::Sci);   // always scientific notation
}

Auto — on a 50 000-point dataset the max bin count exceeds 10 000, so Auto switches to scientific notation automatically.

2D histogram — colorbar with auto tick format, sci notation for large counts

Sci — forces scientific notation at all magnitudes.

2D histogram — colorbar with explicit sci tick format
TickFormat variantColorbar label appearance
Auto (default)Integer counts as-is; sci notation when count ≥ 10 000
SciAlways 1.23e4 style
IntegerRounded to nearest integer
Fixed(n)Exactly n decimal places

Colormaps

ColorMap variantDescription
ColorMap::ViridisBlue → green → yellow. Perceptually uniform, colorblind-safe. (default)
ColorMap::InfernoBlack → orange → yellow. High contrast.
ColorMap::GrayscaleWhite → black. Print-friendly.
ColorMap::TurboBlue → green → red. High contrast over a wide range.
ColorMap::Custom(f)User-supplied Arc<dyn Fn(f64) -> String>.

API reference

MethodDescription
Histogram2D::new()Create with defaults (10×10 bins, Viridis)
.with_data(data, x_range, y_range, bins_x, bins_y)Load (x, y) points and bin them
.with_color_map(cmap)Set the colormap (default ColorMap::Viridis)
.with_correlation()Print Pearson r in the top-right corner
.with_log_count()Log-scale color mapping via ln(count+1); colorbar label → "log(Count)"
Layout::with_colorbar_tick_format(fmt)Control colorbar tick label format (default TickFormat::Auto)