Skip to content

[hist] Improve limits of THLimitsFinder. #19605

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

hageboeck
Copy link
Member

THLimitsFinder sometimes removes the first/last bin of an axis range. Here, it is ensured that the min and max of a buffered range is part of the axis range, and not removed by accident.
This fixes issues with TTree::Draw such as the one described in https://root-forum.cern.ch/t/bug-or-feature-in-ttree-draw/62862/

This supersedes #17689

@hageboeck hageboeck self-assigned this Aug 11, 2025
@hageboeck hageboeck added the skip ci Skip the full builds on the actions runners label Aug 11, 2025
Copy link

github-actions bot commented Aug 11, 2025

Test Results

    21 files      21 suites   3d 8h 58m 31s ⏱️
 3 376 tests  3 366 ✅ 0 💤  10 ❌
69 170 runs  69 038 ✅ 0 💤 132 ❌

For more details on these failures, see this check.

Results for commit e48467f.

♻️ This comment has been updated with latest results.

Copy link
Collaborator

@ferdymercury ferdymercury left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM thanks!

I would propose this test:

TTree t;
Float_t x;
t.Branch("x", &x);
x = -999;
t.Fill();
x = 0;
t.Fill();
t.Draw("x");
auto h = (TH1*)gROOT->FindObject("htemp");
ASSERT_EQ(h->GetEntries(), h->GetEffectiveEntries());

@hageboeck hageboeck removed the skip ci Skip the full builds on the actions runners label Aug 13, 2025
@hageboeck hageboeck marked this pull request as ready for review August 13, 2025 15:06
@hageboeck
Copy link
Member Author

LGTM thanks!

I would propose this test:

TTree t;
Float_t x;
t.Branch("x", &x);
x = -999;
t.Fill();
x = 0;
t.Fill();
t.Draw("x");
auto h = (TH1*)gROOT->FindObject("htemp");
ASSERT_EQ(h->GetEntries(), h->GetEffectiveEntries());

@ferdymercury good test! It's added now.

THLimitsFinder sometimes removes the first/last bin of an axis range.
Here, it is ensured that the min and max of a buffered range is part of
the axis range, and not removed by accident.
This fixes issues with TTree::Draw such as the one described in
https://root-forum.cern.ch/t/bug-or-feature-in-ttree-draw/62862/
Copy link
Collaborator

@ferdymercury ferdymercury left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Just a nitpick at the end of DrawAutoBinning:

delete h;
delete gROOT->FindObject("c1");

THLimitFinder tries to trim empty bins close to the end of an axis range,
but sometimes, the min/max was trimmed as well, so not all data would be
visible in the histogram.

Here, the case from the following post is tested:
https://root-forum.cern.ch/t/bug-or-feature-in-ttree-draw/
@hageboeck
Copy link
Member Author

Thanks! Just a nitpick at the end of DrawAutoBinning:

delete h;
delete gROOT->FindObject("c1");

👍, updated for h. The canvas isn't created in batch mode, though, so that should be be unnecessary in this test.

@ferdymercury
Copy link
Collaborator

The canvas isn't created in batch mode, though, so that should be be unnecessary in this test.

Are you sure?

root -l -b
root [0] TTree t;
root [1] Float_t x;
root [2] t.Branch("x", &x);
root [3] x = -999;
root [4] t.Fill();
root [5] x = 0;
root [6] t.Fill();
root [7] t.Draw("x");
Info in <TCanvas::MakeDefCanvas>:  created default TCanvas with name c1
root [8] gROOT->FindObject("c1")
(TObject *) 0x5c740608b9c0
root [9] delete gROOT->FindObject("c1")
root [10] gROOT->FindObject("c1")
(TObject *) nullptr

@hageboeck
Copy link
Member Author

The test failures for the graphics are real. This will require more investigation.

Comment on lines +340 to +349
if (al - BinLow >= atest && al < BinLow + BinWidth) {
// Suppress the first bin, but only if al doesn't fall into it
BinLow += BinWidth;
nbins--;
}
if (BinHigh - ah >= atest && BinHigh - BinWidth > ah) {
// Suppress the last bin, but only if ah doesn't fall into it
BinHigh -= BinWidth;
nbins--;
}
Copy link
Collaborator

@ferdymercury ferdymercury Aug 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't it be al > BinLow + BinWidth ? instead of < ?
Or maybe even easier:

Suggested change
if (al - BinLow >= atest && al < BinLow + BinWidth) {
// Suppress the first bin, but only if al doesn't fall into it
BinLow += BinWidth;
nbins--;
}
if (BinHigh - ah >= atest && BinHigh - BinWidth > ah) {
// Suppress the last bin, but only if ah doesn't fall into it
BinHigh -= BinWidth;
nbins--;
}
if (al >= BinLow + BinWidth + atest) {
// Suppress the first bin, but only if al doesn't fall into it
BinLow += BinWidth;
nbins--;
}
if (ah <= BinHigh - BinWidth - atest) {
// Suppress the last bin, but only if ah doesn't fall into it
BinHigh -= BinWidth;
nbins--;
}

auto h = (TH1 *)gROOT->FindObject("htemp");
ASSERT_NE(h, nullptr);
EXPECT_EQ(h->GetEntries(), h->GetEffectiveEntries());
delete h;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
delete h;
delete h;
delete gROOT->FindObject("c1");

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants