Skip to content

[hist] Implement AutoZoom of TH1/TH2/TH3/TAxis to filled range #18459

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 20 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
74dee97
[hist] Implement AutoZoom of TH1/TH2/TH3/TAxis to filled range
ferdymercury Apr 22, 2025
e38a65d
[hist] remove irrelevant return
ferdymercury Apr 22, 2025
ffce7dd
[hist] prevent spurious looping on dimensions not belonging to the
ferdymercury Apr 22, 2025
01052a7
[skip-ci] clarifying note on when this part of code is called
ferdymercury Apr 22, 2025
539fd11
[hist] Split: 1 autozooms parent histogram, 1 autozooms all hists on pad
ferdymercury Apr 22, 2025
8d20f37
[test] adapt roottests to new menu functions
ferdymercury Apr 23, 2025
844b558
[roottest] adapt again
ferdymercury Apr 23, 2025
4e56fa0
[test] give more informative error output on stress failure
ferdymercury Apr 23, 2025
cb159c3
[test] fix spacing
ferdymercury Apr 23, 2025
4503010
[test] add some extra bytes
ferdymercury Apr 23, 2025
ace3e20
[hist] fix bug in max starting value and reset iterator before reusing
ferdymercury Apr 23, 2025
50fc50c
[hist] allow specifying a margin in GetRangeOfFilledWeights
ferdymercury Apr 23, 2025
e523e5d
[hist] adapt calls to new margin signature and add a margin of 1 bin
ferdymercury Apr 23, 2025
343011b
[hist] add safety check for static_cast
ferdymercury Apr 23, 2025
8145622
[hist] support THStack Autozoom
ferdymercury Apr 23, 2025
18f5411
[test] undo test changes
ferdymercury Apr 24, 2025
96856bd
[hist] restore original class comment in order not to change streamer…
ferdymercury Apr 24, 2025
43ff9d6
[hist] Unzoom: add sanity check before casting
ferdymercury Apr 25, 2025
3e1c376
[hist] fix nullptr access
ferdymercury Apr 25, 2025
d4400a6
[hist] prevent Unzoom from Zooming in
ferdymercury Apr 25, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions core/base/inc/TVirtualPad.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ class TVirtualPad : public TObject, public TAttLine, public TAttFill,
virtual void DrawClassObject(const TObject *obj, Option_t *option="") = 0;
virtual TH1F *DrawFrame(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax, const char *title="") = 0;
virtual void ExecuteEventAxis(Int_t event, Int_t px, Int_t py, TAxis *axis) = 0;
virtual void AutoZoomed() { Emit("AutoZoomed()"); } // *SIGNAL*
virtual void UnZoomed() { Emit("UnZoomed()"); } // *SIGNAL*
virtual Short_t GetBorderMode() const = 0;
virtual Short_t GetBorderSize() const = 0;
Expand Down
2 changes: 2 additions & 0 deletions hist/hist/inc/TAxis.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,8 @@ class TAxis : public TNamed, public TAttAxis {
virtual void SetTimeDisplay(Int_t value) {fTimeDisplay = (value != 0);} // *TOGGLE*
virtual void SetTimeFormat(const char *format=""); // *MENU*
virtual void SetTimeOffset(Double_t toffset, Option_t *option="local");
virtual void AutoZoom(); // *MENU*
virtual void AutoZoomAll(); // *MENU*
virtual void UnZoom(); // *MENU*
virtual void ZoomOut(Double_t factor=0, Double_t offset=0); // *MENU*

Expand Down
5 changes: 4 additions & 1 deletion hist/hist/inc/TH1.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@ class TH1 : public TNamed, public TAttLine, public TAttFill, public TAttMarker {
virtual void AddBinContent(Int_t bin, Double_t w) = 0;
static void AddDirectory(Bool_t add=kTRUE);
static Bool_t AddDirectoryStatus();
virtual void AutoZoom(); // *MENU*
virtual void UnZoom(); // *MENU*
void Browse(TBrowser *b) override;
virtual Bool_t CanExtendAllAxes() const;
virtual Double_t Chi2Test(const TH1* h2, Option_t *option = "UU", Double_t *res = nullptr) const;
Expand Down Expand Up @@ -323,10 +325,11 @@ class TH1 : public TNamed, public TAttLine, public TAttFill, public TAttMarker {

virtual Int_t GetQuantiles(Int_t n, Double_t *xp, const Double_t *p = nullptr);
virtual Double_t GetRandom(TRandom * rng = nullptr) const;
void GetRangeOfFilledWeights(const Int_t dim, Int_t& first, Int_t& last, const Int_t margin, const bool includeUnderOverflow) const;
virtual void GetStats(Double_t *stats) const;
virtual Double_t GetStdDev(Int_t axis=1) const;
virtual Double_t GetStdDevError(Int_t axis=1) const;
Double_t GetSumOfAllWeights(const bool includeOverflow) const;
Double_t GetSumOfAllWeights(const bool includeUnderOverflow) const;
/// Return the sum of weights across all bins excluding under/overflows.
/// \see TH1::GetSumOfAllWeights()
virtual Double_t GetSumOfWeights() const { return GetSumOfAllWeights(false); }
Expand Down
125 changes: 123 additions & 2 deletions hist/hist/src/TAxis.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "TList.h"
#include "TAxisModLab.h"
#include "TH1.h"
#include "THStack.h"
#include "TObjString.h"
#include "TDatime.h"
#include "TTimeStamp.h"
Expand Down Expand Up @@ -1269,7 +1270,7 @@ void TAxis::UnZoom()

//unzoom object owning this axis
SetRange(0,0);
TH1 *hobj1 = (TH1*)GetParent();
TH1 *hobj1 = GetParent() && GetParent()->InheritsFrom(TH1::Class()) ? static_cast<TH1*>(GetParent()) : nullptr;
if (!strstr(GetName(),"xaxis")) {
if (!hobj1) return;
if (hobj1->GetDimension() == 2) {
Expand All @@ -1284,7 +1285,7 @@ void TAxis::UnZoom()
hobj1->SetMinimum(fXmin);
hobj1->SetMaximum(fXmax);
} else {
if (fXmin==hobj1->GetMinimum() && fXmax==hobj1->GetMaximum()) {
if (fXmin==hobj1->GetMinimumStored() && fXmax==hobj1->GetMaximumStored()) {
hobj1->SetMinimum(fXmin);
hobj1->SetMaximum(fXmax);
} else {
Expand Down Expand Up @@ -1328,6 +1329,126 @@ void TAxis::UnZoom()
gPad->UnZoomed();
}

////////////////////////////////////////////////////////////////////////////////
/// Automatically zoom the current axis to the range of the parent histogram
/// filled with non-zero contents (weights or errors)
/// \note For the bin content axis (yaxis) of a TH1 or (zaxis) of a TH2,
/// UnZoom is called instead. TH3, the PaletteAxis does not implement AutoZoom nor UnZoom

void TAxis::AutoZoom()
{
if (!GetParent()) {
Warning("TAxis::AutoZoom","Cannot AutoZoom if parent does not exist. Did you mean to draw the TAxis first?");
return;
}
if (!GetParent()->InheritsFrom(TH1::Class())) {
Warning("TAxis::AutoZoom","Cannot AutoZoom if axis parent (of type `%s`) does not derive from TH1.", GetParent()->ClassName());
return;
}
auto dim = strstr(GetName(), "xaxis") ? 0 : strstr(GetName(), "yaxis") ? 1 : strstr(GetName(), "zaxis") ? 2 : -1;
TH1 *hobj1 = static_cast<TH1 *>(GetParent());
Int_t first = -1, last = -1;

auto ndims = hobj1->GetDimension();
// Sanity checks
if (dim == 0) {
if (ndims != 1 && ndims != 2 && ndims != 3) {
Warning("TAxis::AutoZoom","Cannot AutoZoom xaxis if TH has %d dimension(s)", ndims);
return;
}
} else if (dim == 1) {
if (ndims == 1) {
UnZoom(); // For a TH1, it acts as an AutoZoom of the yaxis (bin content axis)
return;
}
if (ndims != 2 && ndims != 3) {
Warning("TAxis::AutoZoom","Cannot AutoZoom yaxis if TH has %d dimension(s)", ndims);
return;
}
} else if (dim == 2) {
if (ndims == 2) {
UnZoom(); // For a TH2, it acts as an AutoZoom of the zaxis (bin content axis)
return;
}
if (ndims != 3) {
Warning("TAxis::AutoZoom","Cannot AutoZoom zaxis if TH has %d dimension(s)", ndims);
return;
}
}

hobj1->GetRangeOfFilledWeights(dim, first, last, 1, false);
SetRange(first, last);

if (gPad)
gPad->AutoZoomed();
}

////////////////////////////////////////////////////////////////////////////////
/// Automatically zoom the current axis to the range of all histograms overlaid
/// in this pad and detect shared range filled with non-zero contents (weights or errors)
/// \note For the bin content axis (yaxis) of a TH1 or (zaxis) of a TH2,
/// UnZoom is called instead. TH3, the PaletteAxis does not implement AutoZoom nor UnZoom

void TAxis::AutoZoomAll()
{
if (!gPad) {
Warning("TAxis::AutoZoom","Cannot AutoZoom if gPad does not exist. Did you mean to draw the TAxis first?");
return;
}
gPad->SetView();
auto dim = strstr(GetName(), "xaxis") ? 0 : strstr(GetName(), "yaxis") ? 1 : strstr(GetName(), "zaxis") ? 2 : -1;
Int_t first = -1, last = -1;

Double_t globalMin = DBL_MAX;
Double_t globalMax = -DBL_MAX;
TIter next(gPad->GetListOfPrimitives());
while (TObject *obj= next()) {
if (!obj)
continue;
if (obj->InheritsFrom(TH1::Class())) {
TH1 *hobj = static_cast<TH1*>(obj);
if (dim > hobj->GetDimension())
continue;
hobj->GetRangeOfFilledWeights(dim, first, last, 1, false);
TAxis *ax = (dim == 0) ? hobj->GetXaxis() : (dim == 1) ? hobj->GetYaxis() : (dim == 2) ? hobj->GetZaxis() : nullptr;
if (ax) {
globalMin = std::min(globalMin, ax->GetBinLowEdge(first));
globalMax = std::max(globalMax, ax->GetBinUpEdge(last));
}
} else if (obj->InheritsFrom(THStack::Class())) {
THStack *hs = static_cast<THStack*>(obj);
TIter hsnext(hs->begin());
while (TObject *hsobj= hsnext()) {
if (!hsobj)
continue;
TH1 *hobj = static_cast<TH1*>(hsobj);
if (dim > hobj->GetDimension())
continue;
hobj->GetRangeOfFilledWeights(dim, first, last, 1, false);
TAxis *ax = (dim == 0) ? hobj->GetXaxis() : (dim == 1) ? hobj->GetYaxis() : (dim == 2) ? hobj->GetZaxis() : nullptr;
if (ax) {
globalMin = std::min(globalMin, ax->GetBinLowEdge(first));
globalMax = std::max(globalMax, ax->GetBinUpEdge(last));
}
}
}
}
next.Reset();
while (TObject *obj = next()) {
if (!obj || (!obj->InheritsFrom(TH1::Class()) && !obj->InheritsFrom(THStack::Class())))
continue;
TH1 *hobj = obj->InheritsFrom(TH1::Class()) ? static_cast<TH1 *>(obj) : static_cast<THStack *>(obj)->GetHistogram();
if (dim > hobj->GetDimension())
continue;
TAxis *ax = (dim == 0) ? hobj->GetXaxis() : (dim == 1) ? hobj->GetYaxis() : (dim == 2) ? hobj->GetZaxis() : nullptr;
if (ax) {
ax->SetRangeUser(globalMin, globalMax);
}
}

gPad->AutoZoomed();
}

////////////////////////////////////////////////////////////////////////////////
/// Zoom out by a factor of 'factor' (default =2)
/// uses previous zoom factor by default
Expand Down
Loading
Loading