Problem / motivation
HistogramWidget plots raw counts and offers no way to normalize. refresh does:
[counts, edges] = histcounts(data, nBins);
centers = (edges(1:end-1) + edges(2:end)) / 2;
bar(obj.hAxes, centers, counts, 1);
(libs/Dashboard/HistogramWidget.m:63,67) and the public props are only
DataFcn / NumBins / ShowNormalFit / EdgeColor (:2-7) — verified
grep -ciE "normaliz|probability|pdf|density" over the file returns 1, a
doc-comment, not a normalization mode.
Two consequences:
- Distributions of different sample sizes can't be compared. Comparing the
pressure distribution before vs. after a change, two recordings of unequal length,
or two sensors sampled at different rates is a core exploratory move — but with raw
counts the taller histogram is just the longer recording, not the more concentrated
distribution.
- The existing
ShowNormalFit Gaussian is hard-scaled to counts. The overlay
already computes a density and rescales it back to the count axis —
yFit = numel(data)*binWidth*(1/(sigma*sqrt(2*pi)))*exp(...) (:75-76). On a true
density axis the fit would be a plain pdf and directly comparable across histograms.
Proposed feature
Add an opt-in Normalization property accepting 'count' (default), 'probability',
and 'pdf' ('density' alias) — the same vocabulary as MATLAB's own
histogram/histcounts, so it's instantly familiar.
'count' — raw counts (today's behavior, unchanged).
'probability' — counts ./ sum(counts) (bar heights sum to 1).
'pdf' / 'density' — counts ./ (sum(counts) .* diff(edges)) (area = 1; robust to
non-uniform bins).
Rough sketch
- Lib / class:
libs/Dashboard/HistogramWidget.m (single file).
- Public API:
Normalization = 'count' added to the public properties block.
- Render: after
histcounts, transform counts per the mode above before the
bar(...) call; adapt the ShowNormalFit scale factor to match (keep
numel(data)*binWidth for 'count', use binWidth for 'probability', drop both
for 'pdf'); set the y-label to Count / Probability / Probability density.
Computed by hand on the already-returned counts — no reliance on histcounts'
own 'Normalization' name-value, so it stays Octave-7-safe (the file already calls
histcounts, confirming availability).
- Serialize: emit
s.normalization = obj.Normalization in toStruct (:121-130)
when not 'count'; read it in fromStruct (:134-150) with default 'count' when
absent.
Value
Medium-High. Cross-sample distribution comparison is a recurring sensor-analysis need,
and raw-count histograms actively mislead when N differs. 'pdf' also turns the
ShowNormalFit overlay into a genuine density curve, making the histogram and its fit
directly comparable.
Constraints check
- Toolbox-free: ✅ plain arithmetic on
counts + bar; no toolbox calls.
- Backward-compatible: ✅ default
'count' is byte-identical to today; old
serialized dashboards have no normalization key and load as 'count'.
- Pure MATLAB/Octave: ✅ no
histcounts 'Normalization' dependency; manual
transform works on R2020b+ and Octave 7+.
- Widget contract: ✅ purely additive property on
HistogramWidget; no
DashboardWidget base-class or layout change.
Effort estimate
S–M — one property + a ~3-line counts transform + a small ShowNormalFit
scale-factor branch + a y-label + a toStruct/fromStruct round-trip. One test:
'probability' ⇒ Σ(heights) = 1; 'pdf' ⇒ Σ(height·binwidth) ≈ 1; default 'count'
unchanged; value round-trips through serialization.
Dedup
Distinct from #251 (percentile overlay lines), #256 (cumulative/CDF display — a
running-sum transform, not per-bin rescale), #253 (axis labels), #211 (threshold
overlays). gh issue list --search "histogram normalization probability pdf density"
→ 0; no open PR touches HistogramWidget.
Note (separate bug, not part of this feature)
EdgeColor is a declared, serialized HistogramWidget prop that is never applied —
the bar(...) call at :67 passes no 'EdgeColor'. A fixer touching this same bar
call could wire it at the same time, but it should be tracked/handled as a bug, not as
part of this enhancement.
AI-proposed via /feature-scout — needs a human product decision before implementation.
Problem / motivation
HistogramWidgetplots raw counts and offers no way to normalize.refreshdoes:(
libs/Dashboard/HistogramWidget.m:63,67) and the public props are onlyDataFcn / NumBins / ShowNormalFit / EdgeColor(:2-7) — verifiedgrep -ciE "normaliz|probability|pdf|density"over the file returns 1, adoc-comment, not a normalization mode.
Two consequences:
pressure distribution before vs. after a change, two recordings of unequal length,
or two sensors sampled at different rates is a core exploratory move — but with raw
counts the taller histogram is just the longer recording, not the more concentrated
distribution.
ShowNormalFitGaussian is hard-scaled to counts. The overlayalready computes a density and rescales it back to the count axis —
yFit = numel(data)*binWidth*(1/(sigma*sqrt(2*pi)))*exp(...)(:75-76). On a truedensity axis the fit would be a plain pdf and directly comparable across histograms.
Proposed feature
Add an opt-in
Normalizationproperty accepting'count'(default),'probability',and
'pdf'('density'alias) — the same vocabulary as MATLAB's ownhistogram/histcounts, so it's instantly familiar.'count'— raw counts (today's behavior, unchanged).'probability'—counts ./ sum(counts)(bar heights sum to 1).'pdf'/'density'—counts ./ (sum(counts) .* diff(edges))(area = 1; robust tonon-uniform bins).
Rough sketch
libs/Dashboard/HistogramWidget.m(single file).Normalization = 'count'added to the public properties block.histcounts, transformcountsper the mode above before thebar(...)call; adapt theShowNormalFitscale factor to match (keepnumel(data)*binWidthfor'count', usebinWidthfor'probability', drop bothfor
'pdf'); set the y-label toCount/Probability/Probability density.Computed by hand on the already-returned
counts— no reliance onhistcounts'own
'Normalization'name-value, so it stays Octave-7-safe (the file already callshistcounts, confirming availability).s.normalization = obj.NormalizationintoStruct(:121-130)when not
'count'; read it infromStruct(:134-150) with default'count'whenabsent.
Value
Medium-High. Cross-sample distribution comparison is a recurring sensor-analysis need,
and raw-count histograms actively mislead when N differs.
'pdf'also turns theShowNormalFitoverlay into a genuine density curve, making the histogram and its fitdirectly comparable.
Constraints check
counts+bar; no toolbox calls.'count'is byte-identical to today; oldserialized dashboards have no
normalizationkey and load as'count'.histcounts'Normalization'dependency; manualtransform works on R2020b+ and Octave 7+.
HistogramWidget; noDashboardWidgetbase-class or layout change.Effort estimate
S–M — one property + a ~3-line counts transform + a small
ShowNormalFitscale-factor branch + a y-label + a
toStruct/fromStructround-trip. One test:'probability'⇒ Σ(heights) = 1;'pdf'⇒ Σ(height·binwidth) ≈ 1; default'count'unchanged; value round-trips through serialization.
Dedup
Distinct from #251 (percentile overlay lines), #256 (cumulative/CDF display — a
running-sum transform, not per-bin rescale), #253 (axis labels), #211 (threshold
overlays).
gh issue list --search "histogram normalization probability pdf density"→ 0; no open PR touches HistogramWidget.
Note (separate bug, not part of this feature)
EdgeColoris a declared, serialized HistogramWidget prop that is never applied —the
bar(...)call at:67passes no'EdgeColor'. A fixer touching this samebarcall could wire it at the same time, but it should be tracked/handled as a bug, not as
part of this enhancement.
AI-proposed via /feature-scout — needs a human product decision before implementation.