Repository navigation
[Python][UHI] Fix bugs and inconsistencies with the UHI specification for TH1* - #24081
Open
siliataider wants to merge 17 commits into
Open
siliataider wants to merge 17 commits into
siliataider wants to merge 17 commits into
Conversation
siliataider
marked this pull request as draft
November 10, 2026 13:12
Test Results 22 files 22 suites 3d 12h 22m 46s ⏱️ For more details on these failures, see this check. Results for commit 6f41876. ♻️ This comment has been updated with latest results. |
The UHI sum action is the builtin `sum` but only `ROOT.uhi.sum` was normalized to `slice(None, None, sum)` in `_compute_uhi_index`.
h2 = TH2D with 2x2 bins [[1, 2], [3, 4]]
Before After
h2[sum, 0:1] TypeError: Unsupported index type: float [4]
h2[::sum, 0:1] [4] [4]
Assisted-by: Claude Opus 5.5
The integral bounds were read from the `stop` of the raw user index, which is not a slice for `h[sum]`, tuple or dict indices.
h = TH1D with 3 bins [1, 2, 3]
Before After
h[::sum] 6 6
h[sum] AttributeError: no attribute 'stop' 6
h[(slice(None, None, sum),)] AttributeError: no attribute 'stop' 6
h[{0: slice(None, None, sum)}] AttributeError: no attribute 'stop' 6
Assisted-by: Claude Opus 5.5
…d 3D histograms
The sum over all axes of 2D and 3D histograms called `Integral()` without bounds, which excludes the flow bins.
h = TH2D with 3x3 bins, filled at (1.5, 1.5), (-1, 1.5) in the x underflow and (1.5, 5) in the y overflow
Before After
h[::sum, ::sum] 1 3
h[0:len:sum, 0:len:sum] 1 1
h[1, ::sum] 1 2
Assisted-by: Claude Opus 5.5
… the sum action
`ProjectionX` reuses and refills the histogram with the same name (`h_px`) found in `gDirectory`, so each projection overwrote the previous one.
h = TH2D with 4x2 bins [[1, 2], [3, 4], [5, 6], [7, 8]], px = h[:, ::sum], then px_part = h[1:3, ::sum]
Before After
px [3 7 11 15] [3 7 11 15]
px_part [7 11] [7 11]
px after px_part [7 11] [3 7 11 15]
Assisted-by: Claude Opus 5.5
…or their base class
Once `Slice<TH1D>` exists, cppyy uses it for a `TProfile` too, and copying a `TProfile` into a `TH1D` is fatal.
h = TH1D, p = TProfile
Before After
p[1:3] TProfile TProfile
h[1:3], then p[1:3] Fatal in <TProfile::Copy>: Cannot copy a TProfile in a TH1D TProfile
Assisted-by: Claude Opus 5.5
…histograms
Each cut bin should land in the flow bin of the axis it was cut from. Before, they all piled into two corner cells.
Below the result of h[1:2, :]
original slicing BEFORE slicing AFTER
of | 1 | 1 1 1 | 1 of | 0 | 0 | 11 of | 2 | 1 | 2
3 | 1 | 1 1 1 | 1 3 | 0 | 1 | 0 3 | 2 | 1 | 2
2 | 1 | 1 1 1 | 1 2 | 0 | 1 | 0 2 | 2 | 1 | 2
1 | 1 | 1 1 1 | 1 1 | 0 | 1 | 0 1 | 2 | 1 | 2
uf | 1 | 1 1 1 | 1 uf | 11 | 0 | 0 uf | 2 | 1 | 2
uf | 1 2 3 | of uf | 1 | of uf | 1 | of
Assisted-by: Claude Opus 5.5
The Sumw2 array was not sliced, `SetBins` only truncated it to the size of the slice, which keeps the first bins.
h = TH1D with 4 bins and Sumw2, one entry of weight 1, 2, 3, 4 in each bin
Before After
h.variances() [1 4 9 16] [1 4 9 16]
h[1:3].variances() [1 4] [4 9]
Assisted-by: Claude Opus 5.5
Only -1 was mapped to the last bin, other negative indices were passed to ROOT as negative bin numbers.
h = TH1D with 5 bins [10, 11, 12, 13, 14]
Before After
h[-1] 14 14
h[-2] 0 13
h[-5] 0 10
h[-6] 0 IndexError
Assisted-by: Claude Opus 5.5
`loc` changed `self` and returned it, so every `loc` call registers offsets: Expression Before After h[x] 2 2 h[x + 1] 3 3 h[x] again 3, and x.offset is now 1 2 Assisted-by: Claude Opus 5.5
`FindBin` grows the axis if the histogram is extendable, `FindFixBin` is a simple lookup.
Before After
Histogram before reading [0, 10], [0 1 2 3 4 5 6 7 8 9] same
h[loc(100)] 0.0 0.0 (the overflow bin)
Histogram after reading [0, 160], [45 0 0 0 0 0 0 0 0 0] [0, 10], [0 1 2 3 4 5 6 7 8 9]
Assisted-by: Claude Opus 5.5
The counts were computed as values^2 / Sumw2, but the Sumw2 array of a profile holds the sum of w*y^2 of each bin.
p = TProfile with 2 bins, filled with y = (1, 3) in bin 0 and y = (2, 2, 5) in bin 1
Before After
p.values() [2 3] [2 3]
p.counts() [0.4 0.27] [2 3]
Assisted-by: Claude Opus 5.5
…files
The variances were the Sumw2 array, which holds the sum of w*y^2 of each bin for a profile.
p = TProfile with 2 bins, filled with y = (1, 3) in bin 0 and y = (2, 2, 5) in bin 1
Before After
p.values() [2 3] [2 3]
p.variances() [10 33] [1 1]
Assisted-by: Claude Opus 5.5
…ontents
The bin entries of profiles were not sliced, so the sliced bin contents were divided by the entries of the first bins.
p = TProfile with 4 bins, filled with y = 1 in bin 0, y = (2, 4) in bin 1, y = 6 in bin 2 and y = 8 in bin 3
Before After
p.values() [1 3 6 8] [1 3 6 8]
p[1:3].values() [6 3] [3 6]
p[1:3].counts() [1 2] [2 1]
Assisted-by: Claude Opus 5.5
`lower` and `upper` were the edges of the range selected with `SetRange`, while `bins` was the number of bins of the whole axis.
h = TH1D with 10 bins in [0, 10], h.GetXaxis().SetRange(3, 5)
Before After
axes[0] lower 2, upper 5, bins 10 lower 0, upper 10, bins 10
Assisted-by: Claude Opus 5.5
Axes with variable bin sizes were serialized as regular axes between their first and last edges.
h = TH1D with 3 bins of edges [0, 1, 5, 10]
Before After
axes[0] regular, lower 0, upper 10, bins 3 variable, edges [0, 1, 5, 10]
Assisted-by: Claude Opus 5.5
The values were serialized with the flow bins, but the variances without.
h = TH1D with 2 bins and Sumw2, filled with weight 2 in the underflow and weight 3 in bin 0
Before After
storage["values"] [2 3 0 0] [2 3 0 0]
storage["variances"] [9 0] [4 9 0 0]
Assisted-by: Claude Opus 5.5
A profile always has a Sumw2 array (the sum of w*y^2), so every profile was serialized as a `weighted_mean` storage.
p = TProfile with 2 bins, filled with y = (1, 3) in bin 0 and y = (2, 2, 5) in bin 1
Before After
type weighted_mean mean
variances [nan 1 1 nan] [0 2 3 0]
counts - [0 2 3 0]
sum_of_weights [2 3] (the means) -
sum_of_weights_squared [0 10 33 0] (sum of y^2) -
Assisted-by: Claude Opus 5.5
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This Pull request:
Changes:
Fixes bugs and inconsistencies with the UHI specification in the UHI pythonizations of
TH1and derived classes, to keep them consistent with the upcoming UHI support for the new ROOT histograms.Each commit fixes one bug and adds a test that fails without it. Each commit message shows a small before/after example.