Skip to content

histogram: Add frequency, probability and density types to -Z - #9229

Open
Esteban82 wants to merge 2 commits into
masterfrom
fix-9212
Open

Esteban82 wants to merge 2 commits into
masterfrom
fix-9212

Conversation

@Esteban82

Copy link
Copy Markdown
Member

Claude's comments:

First commit is a no-op refactor: consolidates the -Z→statistic conversion (duplicated in 4 places) into one helper, and fixes the y-range calculation to work for unequal bin widths.

Second commit adds the -Z types requested in #9212 after the existing 0-5: -Z6 frequency (n/w), -Z7 probability (n/N, alias proportion) and -Z8 density (n/(N·w)), computed with each bin's own width so unequal -T bins and the -N curve work too (src/pshistogram.c, longopts, docs, tests). -Q is rejected with -Z6/-Z8, since a cumulative count divided by one bin's width is not a meaningful statistic; -Z7 -Q gives the CDF.

Added test/pshistogram/density_unequal_bins.sh because -T allows bins of unequal width (a file of edges, or +l/+b for log-spaced bins), and an implementation that assumes uniform bin width would get density's per-bin math wrong precisely in that case. The test checks two things with deliberately unequal (log-spaced) bins: that the bars integrate to exactly 1, and that the automatic y-range (-I) matches the true per-bin min/max rather than a naive rescaling of the raw counts.

I haven't personally checked in detail whether the restriction on combining -Q with -Z6/-Z8 makes sense. Happy to adjust if maintainers feel differently.

Tested with:

gmt begin test png
	gmt histogram @v3206_06.txt -T-7000/0/250 -Z6 -Ra -JX5c -Baf -Ggray -W0.5p -N0+p1.5p,red 
	gmt histogram @v3206_06.txt -T-7000/0/250 -Z7 -Ra -JX5c -Baf -Ggray -W0.5p -N0+p1.5p,red -Xw+1.2c
	gmt histogram @v3206_06.txt -T-7000/0/250 -Z8 -Ra -JX5c -Baf -Ggray -W0.5p -N0+p1.5p,red -Xw+1.2c
gmt end
test

Fixes #9212

Assisted-by: Claude Opus 5 and Claude Sonnet 5, reviewed and revised with Claude Opus 5.5

Esteban82 and others added 2 commits September 24, 2026 16:55
The conversion from a raw bin count to the statistic selected by -Z was
spelled out as the same if/else chain in four places (the y-range in
pshistogram_fill_boxes, the bar height and the cpt z-value in
pshistogram_set_xy_array, and the -I dump).  Replace all four with
pshistogram_stat_value, where apply_log = false yields the linear
statistic that the cpt lookup has always used.

Also compute the y-range by walking the bins and tracking the min/max of
the statistic itself, rather than taking the min/max of the raw counts
and transforming afterwards.  That shortcut only works while the
statistic is an increasing function of the bin content, which is true for
the current -Z modes but not for the per-bin-width normalizations in
issue #9212, since -T may hand us bins of unequal width.

No change in output for any existing -Z mode, with one exception: with
+w and a negative total weight, master's y-range (reported by -I, and the
basis of an automatic -R) came out as 0/0 even though the bars and the -I
dump were positive percentages.  It now spans them.  The bars and the
-I dump themselves are unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add three new -Z statistics, appended after the existing 0-5 so no script
using the current numbering breaks:

  6 = frequency:    n / w
  7 = probability:  n / N   [alias: proportion]
  8 = density:      n / (N * w)

where n is a bin's count (or sum of weights under +w), N is the sum of n
over all bins, and w is that bin's own width -- which may differ from bin
to bin (-T accepts a list or file of edges, and +l/+b build log-spaced
arrays).  Bar heights, the -I dump, the y-axis range and the -C+b lookup
all go through pshistogram_stat_value(), the helper introduced in the
prior commit, now width-aware for these three modes.

Two things needed more than a new switch case:

- -N's normal-distribution overlay scales its curve by "area", the sum of
  (bin width x count), i.e. an average bin width times N.  That suits
  counts, percent and probability, whose bars grow with each bin's width,
  but not frequency or density, which have already divided it out: a
  frequency curve is N*phi(x) and a density curve is phi(x) itself.
  Neither uses "area", so both stay exact when the bins are unequal,
  whereas the other modes' curves are only approximate then.

- -Q (cumulative) sums raw counts before any -Z transform, so a naive
  "cumulative density" would reach 1/w instead of 1 -- not a CDF.  Reject
  -Q with -Z6/-Z8 outright; -Z7 (probability) has no such problem since
  n/N does not depend on bin width, and doubles as a real CDF under -Q.
  This is the recommended choice, not yet confirmed by the maintainer.

-D labels are unchanged: they show each bin's raw count for every -Z
type, as documented, and the docs now say so explicitly.

Also updates the longopt table (frequency, probability|proportion,
density), the -Z, -Q, -C and -D docs in histogram.rst (shared with
pshistogram.rst) and the -C usage text, and adds two tests: the l2s
long-to-short translation list now covers the three new names, and a new
numeric test checks two properties of density under deliberately unequal
(log-spaced) bins -- that the bars integrate to exactly 1, and that the
automatic y-range equals the true per-bin min/max rather than a rescaling
of the raw counts.  Modes 0-5 and the eight DVC baseline images are
unchanged (RMS 0.0000).

No new baseline image for the new modes: registering one needs a dvc push
to the DagsHub remote, for which this environment has no credentials.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Esteban82 Esteban82 added the add-changelog Add PR to the changelog label Sep 25, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

add-changelog Add PR to the changelog

Projects

None yet

Development

Successfully merging this pull request may close these issues.

histogram: Support density histograms and more

1 participant