Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -96,6 +96,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 @@ -436,6 +436,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 @@ -550,10 +552,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, Option_t *option = "") 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
121 changes: 121 additions & 0 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 @@ -1343,6 +1344,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::AutoZoomAll","Cannot AutoZoomAll 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
198 changes: 191 additions & 7 deletions hist/hist/src/TH1.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -743,6 +743,54 @@ Bool_t TH1::AddDirectoryStatus()
return fgAddDirectory;
}

////////////////////////////////////////////////////////////////////////////////
/// Autozoom histogram in all their axes
/// \see TAxis::AutoZoom

void TH1::AutoZoom()
{
const auto ndims = GetDimension();
if (ndims < 1 || ndims > 3)
return;
// First apply autozoom in pure coordinate axis
if (ndims >= 1)
GetXaxis()->AutoZoom();
if (ndims >= 2)
GetYaxis()->AutoZoom();
if (ndims >= 3)
GetZaxis()->AutoZoom();
// Now apply autozoom in the bin content axis if it's a TH1 or TH2
if (ndims == 1)
GetYaxis()->AutoZoom();
else if (ndims == 2)
GetZaxis()->AutoZoom();
// For 3D, there is no UnZoom or AutoZoom implemented for TPaletteAxis
}

////////////////////////////////////////////////////////////////////////////////
/// Unzoom histogram in all their axes
/// \see TAxis::UnZoom

void TH1::UnZoom()
{
const auto ndims = GetDimension();
if (ndims < 1 || ndims > 3)
return;
// First apply Unzoom in pure coordinate axis
if (ndims >= 1)
GetXaxis()->UnZoom();
if (ndims >= 2)
GetYaxis()->UnZoom();
if (ndims >= 3)
GetZaxis()->UnZoom();
// Now apply unzoom in the bin content axis if it's a TH1 or TH2
if (ndims == 1)
GetYaxis()->UnZoom();
else if (ndims == 2)
GetZaxis()->UnZoom();
// For 3D, there is no UnZoom or AutoZoom implemented for TPaletteAxis
}

////////////////////////////////////////////////////////////////////////////////
/// Browse the Histogram object.

Expand Down Expand Up @@ -7959,22 +8007,158 @@ void TH1::ResetStats()
if (fSumw2.fN > 0 && fTsumw > 0 && stats[1] > 0 ) fEntries = stats[0]*stats[0]/ stats[1];
}

////////////////////////////////////////////////////////////////////////////////
/// Get the range of the histogram that is filled with non-empty contents (i.e.
/// non-zero content and non-zero error).
/// \param dim 0 for the x-axis, 1 for the y-axis, 2 for the z-axis, must be <= GetDimension()
/// \param first where the first non-empty bin index will be stored (minus margin)
/// \param last where the last non-empty bin index will be stored (plus margin)
/// \param margin number of bins to enlarge each side of the range, to leave some room
/// \param includeUnderOverflow when searching for non-empty bins, set to true to include the under/overflow bins

void TH1::GetRangeOfFilledWeights(const Int_t dim, Int_t& first, Int_t& last, const Int_t margin, const bool includeUnderOverflow) const
{
if (fBuffer) const_cast<TH1*>(this)->BufferEmpty();

const auto ndims = GetDimension();
const Int_t startX = (includeUnderOverflow ? 0 : 1);
const Int_t startY = ndims < 2 ? 1 : startX;
const Int_t startZ = ndims < 3 ? 1 : startX;
const Int_t lastX = fXaxis.GetNbins() + (includeUnderOverflow ? 1 : 0);
const Int_t lastY = ndims < 2 ? 1 : fYaxis.GetNbins() + (includeUnderOverflow ? 1 : 0);
const Int_t lastZ = ndims < 3 ? 1 : fZaxis.GetNbins() + (includeUnderOverflow ? 1 : 0);

R__ASSERT(dim == 0 || dim == 1 || dim == 2);
if (ndims == 1) {
R__ASSERT(dim == 0);
} else if (ndims == 2) {
R__ASSERT(dim == 0 || dim == 1);
} else if (ndims == 3) {
R__ASSERT(dim == 0 || dim == 1 || dim == 2);
}

if (dim == 0) {
first = startX;
for(Int_t binx = startX; binx <= lastX; binx++) {
for(auto biny = startY; biny <= lastY; biny++) {
for(auto binz = startZ; binz <= lastZ; binz++) {
auto bin = GetBin(binx, biny, binz);
if (RetrieveBinContent(bin) != 0 || GetBinError(bin) != 0)
{
first = binx;
// Break:
binx = lastX;
biny = lastY;
binz = lastZ;
}
}
}
}
last = lastX;
for(Int_t binx = lastX; binx >= startX; binx--) {
for(auto biny = startY; biny <= lastY; biny++) {
for(auto binz = startZ; binz <= lastZ; binz++) {
auto bin = GetBin(binx, biny, binz);
if (RetrieveBinContent(bin) != 0 || GetBinError(bin) != 0)
{
last = binx;
// Break:
binx = startX;
biny = lastY;
binz = lastZ;
}
}
}
}
} else if (dim == 1) {
first = startY;
for(auto biny = startY; biny <= lastY; biny++) {
for(Int_t binx = startX; binx <= lastX; binx++) {
for(auto binz = startZ; binz <= lastZ; binz++) {
auto bin = GetBin(binx, biny, binz);
if (RetrieveBinContent(bin) != 0 || GetBinError(bin) != 0)
{
first = biny;
// Break:
binx = lastX;
biny = lastY;
binz = lastZ;
}
}
}
}
last = lastY;
for(Int_t biny = lastY; biny >= startY; biny--) {
for(auto binx = startX; binx <= lastX; binx++) {
for(auto binz = startZ; binz <= lastZ; binz++) {
auto bin = GetBin(binx, biny, binz);
if (RetrieveBinContent(bin) != 0 || GetBinError(bin) != 0)
{
last = biny;
// Break:
binx = lastX;
biny = startY;
binz = lastZ;
}
}
}
}
} else if (dim == 2) {
first = startZ;
for(auto binz = startZ; binz <= lastZ; binz++) {
for(Int_t binx = startX; binx <= lastX; binx++) {
for(auto biny = startY; biny <= lastY; biny++) {
auto bin = GetBin(binx, biny, binz);
if (RetrieveBinContent(bin) != 0 || GetBinError(bin) != 0)
{
first = biny;
// Break:
binx = lastX;
biny = lastY;
binz = lastZ;
}
}
}
}
last = lastZ;
for(Int_t binz = lastZ; binz >= startZ; binz--) {
for(auto binx = startX; binx <= lastX; binx++) {
for(auto biny = startY; biny <= lastY; biny++) {
auto bin = GetBin(binx, biny, binz);
if (RetrieveBinContent(bin) != 0 || GetBinError(bin) != 0)
{
last = binz;
// Break:
binx = lastX;
biny = lastY;
binz = startZ;
}
}
}
}
}
// Apply some margins
first = std::max(dim == 0 ? startX : dim == 1 ? startY : startZ, first - margin);
last = std::min(dim == 0 ? lastX : dim == 1 ? lastY : lastZ, last + margin);
}

////////////////////////////////////////////////////////////////////////////////
/// Return the sum of all weights
/// \param includeOverflow true to include under/overflows bins, false to exclude those.
/// \note Different from TH1::GetSumOfWeights, that always excludes those

Double_t TH1::GetSumOfAllWeights(const bool includeOverflow) const
Double_t TH1::GetSumOfAllWeights(const bool includeUnderOverflow) const
{
if (fBuffer) const_cast<TH1*>(this)->BufferEmpty();

const Int_t start = (includeOverflow ? 0 : 1);
const Int_t lastX = fXaxis.GetNbins() + (includeOverflow ? 1 : 0);
const Int_t lastY = fYaxis.GetNbins() + (includeOverflow ? 1 : 0);
const Int_t lastZ = fZaxis.GetNbins() + (includeOverflow ? 1 : 0);
const auto ndims = GetDimension();
const Int_t start = (includeUnderOverflow ? 0 : 1);
const Int_t lastX = fXaxis.GetNbins() + (includeUnderOverflow ? 1 : 0);
const Int_t lastY = ndims < 2 ? 1 : fYaxis.GetNbins() + (includeUnderOverflow ? 1 : 0);
const Int_t lastZ = ndims < 3 ? 1 : fZaxis.GetNbins() + (includeUnderOverflow ? 1 : 0);
Double_t sum =0;
for(auto binz = start; binz <= lastZ; binz++) {
for(auto biny = start; biny <= lastY; biny++) {
for(auto binz = ndims < 3 ? 1 : start; binz <= lastZ; binz++) {
for(auto biny = ndims < 2 ? 1 : start; biny <= lastY; biny++) {
for(auto binx = start; binx <= lastX; binx++) {
const auto bin = GetBin(binx, biny, binz);
sum += RetrieveBinContent(bin);
Expand Down
Loading
Loading