Skip to content

Commit ef4cbca

Browse files
jqnatividadclaude
andcommitted
fix(histogram2d): document z as 1D aggregation data, not a matrix
histogram2d `z` is a data_array ("aggregation data") aligned 1:1 with the `x`/`y` samples and aggregated per bin via `hist_func` — not a pre-binned 2D matrix like `heatmap.z`. Reword the struct and `new_xyz` docs accordingly (directing pre-computed matrices to `HeatMap`), and replace the matrix round-trip test with an aligned 1D aggregation example using `hist_func(Sum)`. Addresses roborev review job 3598. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent c62820d commit ef4cbca

1 file changed

Lines changed: 29 additions & 16 deletions

File tree

plotly/src/traces/histogram2d.rs

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,16 @@ use crate::{
1717
/// Construct a 2D histogram trace.
1818
///
1919
/// A `Histogram2d` bins raw `x`/`y` samples into a 2D grid and renders the
20-
/// counts as a heatmap. Provide raw `x`/`y` data (and let Plotly.js bin it via
21-
/// `hist_func`/`n_bins_x`/`n_bins_y`/`x_bins`/`y_bins`), or supply a
22-
/// pre-computed `z` matrix.
20+
/// binned counts as a heatmap. Provide raw `x`/`y` data and let Plotly.js bin
21+
/// it via `hist_func`/`n_bins_x`/`n_bins_y`/`x_bins`/`y_bins`. Optionally
22+
/// supply per-sample aggregation values via `z` (a 1D array aligned with
23+
/// `x`/`y`) and a `hist_func` such as [`HistFunc::Sum`] or
24+
/// [`HistFunc::Average`] to aggregate those values within each bin instead of
25+
/// counting samples.
26+
///
27+
/// Note: unlike [`HeatMap`](crate::HeatMap), `z` here is per-sample aggregation
28+
/// data aligned with `x`/`y`, not a pre-binned 2D matrix. For a pre-computed
29+
/// matrix, use [`HeatMap`](crate::HeatMap).
2330
///
2431
/// # Examples
2532
///
@@ -177,8 +184,10 @@ where
177184
Y: Serialize + Clone,
178185
Z: Serialize + Clone,
179186
{
180-
/// Build a new 2D histogram from a pre-computed `z` matrix, with `x`/`y`
181-
/// coordinates.
187+
/// Build a new 2D histogram from raw `x`/`y` samples plus per-sample
188+
/// aggregation values `z`. All three vectors are aligned (one entry per
189+
/// sample); combine with a `hist_func` such as [`HistFunc::Sum`] to
190+
/// aggregate the `z` values within each `x`/`y` bin.
182191
pub fn new_xyz(x: Vec<X>, y: Vec<Y>, z: Vec<Z>) -> Box<Self> {
183192
Box::new(Self {
184193
x: Some(x),
@@ -251,29 +260,33 @@ mod tests {
251260
}
252261

253262
#[test]
254-
fn serialize_histogram2d_z_matrix() {
263+
fn serialize_histogram2d_aggregation() {
264+
// `z` is per-sample aggregation data aligned with `x`/`y` (not a
265+
// pre-binned matrix); `hist_func` aggregates it within each bin.
255266
let trace = Histogram2d::new_xyz(
256-
vec![0.0, 1.0],
257-
vec![2.0, 3.0],
258-
vec![vec![4.0, 5.0], vec![6.0, 7.0]],
267+
vec![1.0, 2.0, 2.0],
268+
vec![1.0, 1.0, 3.0],
269+
vec![10.0, 20.0, 30.0],
259270
)
271+
.hist_func(HistFunc::Sum)
260272
.zauto(true)
261273
.zmin(0.0)
262-
.zmax(10.0)
263-
.zmid(5.0)
274+
.zmax(60.0)
275+
.zmid(30.0)
264276
.zsmooth(Smoothing::Best)
265277
.x_gap(1.0)
266278
.y_gap("10");
267279

268280
let expected = json!({
269281
"type": "histogram2d",
270-
"x": [0.0, 1.0],
271-
"y": [2.0, 3.0],
272-
"z": [[4.0, 5.0], [6.0, 7.0]],
282+
"x": [1.0, 2.0, 2.0],
283+
"y": [1.0, 1.0, 3.0],
284+
"z": [10.0, 20.0, 30.0],
285+
"histfunc": "sum",
273286
"zauto": true,
274287
"zmin": 0.0,
275-
"zmax": 10.0,
276-
"zmid": 5.0,
288+
"zmax": 60.0,
289+
"zmid": 30.0,
277290
"zsmooth": "best",
278291
"xgap": 1.0,
279292
"ygap": "10",

0 commit comments

Comments
 (0)