Skip to content

Commit 824a75e

Browse files
committed
[hist] fine-grained autorange feature for TH2/3
allows to optimize range of only one of the 2 or 3 axes while keeping user-set (fixed) the others. Fixes https://its.cern.ch/jira/browse/ROOT-7714 See https://root-forum.cern.ch/t/automatic-axis-range-for-2d-and-3d-histograms/19962
1 parent f4346b9 commit 824a75e

File tree

4 files changed

+88
-64
lines changed

4 files changed

+88
-64
lines changed

hist/hist/inc/THLimitsFinder.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ class THLimitsFinder : public TObject {
3434
THLimitsFinder();
3535
~THLimitsFinder() override;
3636
virtual Int_t FindGoodLimits(TH1 *h, Double_t xmin, Double_t xmax);
37-
virtual Int_t FindGoodLimits(TH1 *h, Double_t xmin, Double_t xmax, Double_t ymin, Double_t ymax);
38-
virtual Int_t FindGoodLimits(TH1 *h, Double_t xmin, Double_t xmax, Double_t ymin, Double_t ymax, Double_t zmin, Double_t zmax);
37+
virtual Int_t FindGoodLimits(TH1 *h, Double_t xmin, Double_t xmax, Double_t ymin, Double_t ymax, Int_t newbinsx = 0, Int_t newbinsy = 0);
38+
virtual Int_t FindGoodLimits(TH1 *h, Double_t xmin, Double_t xmax, Double_t ymin, Double_t ymax, Double_t zmin, Double_t zmax, Int_t newbinsx = 0, Int_t newbinsy = 0, Int_t newbinsz = 0);
3939

4040
static void Optimize(Double_t A1, Double_t A2, Int_t nold
4141
,Double_t &BinLow, Double_t &BinHigh, Int_t &nbins, Double_t &BWID, Option_t *option="");

hist/hist/src/TH2.cxx

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -260,22 +260,28 @@ Int_t TH2::BufferEmpty(Int_t action)
260260
fBuffer = buffer;
261261
}
262262

263-
if (CanExtendAllAxes() || fXaxis.GetXmax() <= fXaxis.GetXmin() || fYaxis.GetXmax() <= fYaxis.GetXmin()) {
263+
const bool xbinAuto = fXaxis.GetXmax() <= fXaxis.GetXmin();
264+
const bool ybinAuto = fYaxis.GetXmax() <= fYaxis.GetXmin();
265+
if (CanExtendAllAxes() || xbinAuto || ybinAuto) {
264266
//find min, max of entries in buffer
265-
Double_t xmin = fBuffer[2];
266-
Double_t xmax = xmin;
267-
Double_t ymin = fBuffer[3];
268-
Double_t ymax = ymin;
267+
Double_t xmin = xbinAuto ? fBuffer[2] : fXaxis.GetXmin();
268+
Double_t xmax = xbinAuto ? xmin : fXaxis.GetXmax();
269+
Double_t ymin = ybinAuto ? fBuffer[3] : fYaxis.GetXmin();
270+
Double_t ymax = ybinAuto ? ymin : fYaxis.GetXmax();
269271
for (Int_t i=1;i<nbentries;i++) {
270-
Double_t x = fBuffer[3*i+2];
271-
if (x < xmin) xmin = x;
272-
if (x > xmax) xmax = x;
273-
Double_t y = fBuffer[3*i+3];
274-
if (y < ymin) ymin = y;
275-
if (y > ymax) ymax = y;
272+
if (CanExtendAllAxes() || xbinAuto) {
273+
Double_t x = fBuffer[3*i+2];
274+
if (x < xmin) xmin = x;
275+
if (x > xmax) xmax = x;
276+
}
277+
if (CanExtendAllAxes() || ybinAuto) {
278+
Double_t y = fBuffer[3*i+3];
279+
if (y < ymin) ymin = y;
280+
if (y > ymax) ymax = y;
281+
}
276282
}
277-
if (fXaxis.GetXmax() <= fXaxis.GetXmin() || fYaxis.GetXmax() <= fYaxis.GetXmin()) {
278-
THLimitsFinder::GetLimitsFinder()->FindGoodLimits(this,xmin,xmax,ymin,ymax);
283+
if (xbinAuto || ybinAuto) {
284+
THLimitsFinder::GetLimitsFinder()->FindGoodLimits(this, xmin, xmax, ymin, ymax, xbinAuto ? 0 : fXaxis.GetNbins(), ybinAuto ? 0 : fYaxis.GetNbins());
279285
} else {
280286
fBuffer = nullptr;
281287
Int_t keep = fBufferSize; fBufferSize = 0;

hist/hist/src/TH3.cxx

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -241,29 +241,36 @@ Int_t TH3::BufferEmpty(Int_t action)
241241
Reset("ICES");
242242
fBuffer = buffer;
243243
}
244-
if (CanExtendAllAxes() || fXaxis.GetXmax() <= fXaxis.GetXmin() ||
245-
fYaxis.GetXmax() <= fYaxis.GetXmin() ||
246-
fZaxis.GetXmax() <= fZaxis.GetXmin()) {
244+
const bool xbinAuto = fXaxis.GetXmax() <= fXaxis.GetXmin();
245+
const bool ybinAuto = fYaxis.GetXmax() <= fYaxis.GetXmin();
246+
const bool zbinAuto = fZaxis.GetXmax() <= fZaxis.GetXmin();
247+
if (CanExtendAllAxes() || xbinAuto || ybinAuto || zbinAuto) {
247248
//find min, max of entries in buffer
248-
Double_t xmin = fBuffer[2];
249-
Double_t xmax = xmin;
250-
Double_t ymin = fBuffer[3];
251-
Double_t ymax = ymin;
252-
Double_t zmin = fBuffer[4];
253-
Double_t zmax = zmin;
249+
Double_t xmin = xbinAuto ? fBuffer[2] : fXaxis.GetXmin();
250+
Double_t xmax = xbinAuto ? xmin : fXaxis.GetXmax();
251+
Double_t ymin = ybinAuto ? fBuffer[3] : fYaxis.GetXmin();
252+
Double_t ymax = ybinAuto ? ymin : fYaxis.GetXmax();
253+
Double_t zmin = zbinAuto ? fBuffer[4] : fZaxis.GetXmin();
254+
Double_t zmax = zbinAuto ? zmin : fZaxis.GetXmax();
254255
for (Int_t i=1;i<nbentries;i++) {
255-
Double_t x = fBuffer[4*i+2];
256-
if (x < xmin) xmin = x;
257-
if (x > xmax) xmax = x;
258-
Double_t y = fBuffer[4*i+3];
259-
if (y < ymin) ymin = y;
260-
if (y > ymax) ymax = y;
261-
Double_t z = fBuffer[4*i+4];
262-
if (z < zmin) zmin = z;
263-
if (z > zmax) zmax = z;
256+
if (CanExtendAllAxes() || xbinAuto) {
257+
Double_t x = fBuffer[4*i+2];
258+
if (x < xmin) xmin = x;
259+
if (x > xmax) xmax = x;
260+
}
261+
if (CanExtendAllAxes() || ybinAuto) {
262+
Double_t y = fBuffer[4*i+3];
263+
if (y < ymin) ymin = y;
264+
if (y > ymax) ymax = y;
265+
}
266+
if (CanExtendAllAxes() || zbinAuto) {
267+
Double_t z = fBuffer[4*i+4];
268+
if (z < zmin) zmin = z;
269+
if (z > zmax) zmax = z;
270+
}
264271
}
265-
if (fXaxis.GetXmax() <= fXaxis.GetXmin() || fYaxis.GetXmax() <= fYaxis.GetXmin() || fZaxis.GetXmax() <= fZaxis.GetXmin()) {
266-
THLimitsFinder::GetLimitsFinder()->FindGoodLimits(this,xmin,xmax,ymin,ymax,zmin,zmax);
272+
if (xbinAuto || ybinAuto || zbinAuto) {
273+
THLimitsFinder::GetLimitsFinder()->FindGoodLimits(this, xmin, xmax, ymin, ymax, zmin, zmax, xbinAuto ? 0 : fXaxis.GetNbins(), ybinAuto ? 0 : fYaxis.GetNbins(), zbinAuto ? 0 : fZaxis.GetNbins());
267274
} else {
268275
fBuffer = nullptr;
269276
Int_t keep = fBufferSize; fBufferSize = 0;

hist/hist/src/THLimitsFinder.cxx

Lines changed: 40 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -71,75 +71,86 @@ Int_t THLimitsFinder::FindGoodLimits(TH1 *h, Double_t xmin, Double_t xmax)
7171
}
7272

7373
////////////////////////////////////////////////////////////////////////////////
74-
/// Compute the best axis limits for the X and Y axis.
74+
/// Compute the best axis limits for the X and Y axis
75+
/// (if the corresponding newbins variable is set to 0 ie default).
7576
///
7677
/// If the bit kIsInteger is set, the number of channels is also recomputed.
7778
/// The axis parameters are replaced by the optimized parameters
7879

79-
Int_t THLimitsFinder::FindGoodLimits(TH1 *h, Double_t xmin, Double_t xmax, Double_t ymin, Double_t ymax)
80+
Int_t THLimitsFinder::FindGoodLimits(TH1 *h, Double_t xmin, Double_t xmax, Double_t ymin, Double_t ymax, Int_t newbinsx,
81+
Int_t newbinsy)
8082
{
81-
Int_t newbinsx,newbinsy;
8283
TAxis *xaxis = h->GetXaxis();
8384
TAxis *yaxis = h->GetYaxis();
8485

85-
if (xmin >= xmax) {
86+
const Bool_t xbinAuto = newbinsx != 0;
87+
const Bool_t ybinAuto = newbinsy != 0;
88+
89+
if (xbinAuto && xmin >= xmax) {
8690
if (xaxis->GetLabels()) {xmin = 0; xmax = xmin +xaxis->GetNbins();}
8791
else {xmin -= 1; xmax += 1;}
8892
}
89-
if (ymin >= ymax) {
93+
if (ybinAuto && ymin >= ymax) {
9094
if (yaxis->GetLabels()) {ymin = 0; ymax = ymin +yaxis->GetNbins();}
9195
else {ymin -= 1; ymax += 1;}
9296
}
9397

94-
THLimitsFinder::OptimizeLimits(xaxis->GetNbins(),
95-
newbinsx,xmin,xmax,
96-
xaxis->TestBit(TAxis::kIsInteger));
97-
98-
THLimitsFinder::OptimizeLimits(yaxis->GetNbins(),
99-
newbinsy,ymin,ymax,
100-
yaxis->TestBit(TAxis::kIsInteger));
98+
if (xbinAuto)
99+
THLimitsFinder::OptimizeLimits(xaxis->GetNbins(),
100+
newbinsx,xmin,xmax,
101+
xaxis->TestBit(TAxis::kIsInteger));
102+
if (ybinAuto)
103+
THLimitsFinder::OptimizeLimits(yaxis->GetNbins(),
104+
newbinsy,ymin,ymax,
105+
yaxis->TestBit(TAxis::kIsInteger));
101106

102107
h->SetBins(newbinsx,xmin,xmax,newbinsy,ymin,ymax);
103108
return 0;
104109
}
105110

106111
////////////////////////////////////////////////////////////////////////////////
107-
/// Compute the best axis limits for the X, Y and Z axis.
112+
/// Compute the best axis limits and bins for the X, Y and Z axis
113+
/// (if the corresponding newbins variable is set to 0 ie default).
108114
///
109115
/// If the bit kIsInteger is set, the number of channels is also recomputed.
110116
/// The axis parameters are replaced by the optimized parameters
111117

112-
Int_t THLimitsFinder::FindGoodLimits(TH1 *h, Double_t xmin, Double_t xmax, Double_t ymin, Double_t ymax, Double_t zmin, Double_t zmax)
118+
Int_t THLimitsFinder::FindGoodLimits(TH1 *h, Double_t xmin, Double_t xmax, Double_t ymin, Double_t ymax, Double_t zmin,
119+
Double_t zmax, Int_t newbinsx, Int_t newbinsy, Int_t newbinsz)
113120
{
114-
Int_t newbinsx,newbinsy,newbinsz;
115121
TAxis *xaxis = h->GetXaxis();
116122
TAxis *yaxis = h->GetYaxis();
117123
TAxis *zaxis = h->GetZaxis();
118124

119-
if (xmin >= xmax) {
125+
const Bool_t xbinAuto = newbinsx != 0;
126+
const Bool_t ybinAuto = newbinsy != 0;
127+
const Bool_t zbinAuto = newbinsz != 0;
128+
129+
if (xbinAuto && xmin >= xmax) {
120130
if (xaxis->GetLabels()) {xmin = 0; xmax = xmin +xaxis->GetNbins();}
121131
else {xmin -= 1; xmax += 1;}
122132
}
123-
if (ymin >= ymax) {
133+
if (ybinAuto && ymin >= ymax) {
124134
if (yaxis->GetLabels()) {ymin = 0; ymax = ymin +yaxis->GetNbins();}
125135
else {ymin -= 1; ymax += 1;}
126136
}
127-
if (zmin >= zmax) {
137+
if (zbinAuto && zmin >= zmax) {
128138
if (zaxis->GetLabels()) {zmin = 0; zmax = zmin +zaxis->GetNbins();}
129139
else {zmin -= 1; zmax += 1;}
130140
}
131141

132-
THLimitsFinder::OptimizeLimits(xaxis->GetNbins(),
133-
newbinsx,xmin,xmax,
134-
xaxis->TestBit(TAxis::kIsInteger));
135-
136-
THLimitsFinder::OptimizeLimits(yaxis->GetNbins(),
137-
newbinsy,ymin,ymax,
138-
yaxis->TestBit(TAxis::kIsInteger));
139-
140-
THLimitsFinder::OptimizeLimits(zaxis->GetNbins(),
141-
newbinsz,zmin,zmax,
142-
zaxis->TestBit(TAxis::kIsInteger));
142+
if (xbinAuto)
143+
THLimitsFinder::OptimizeLimits(xaxis->GetNbins(),
144+
newbinsx,xmin,xmax,
145+
xaxis->TestBit(TAxis::kIsInteger));
146+
if (ybinAuto)
147+
THLimitsFinder::OptimizeLimits(yaxis->GetNbins(),
148+
newbinsy,ymin,ymax,
149+
yaxis->TestBit(TAxis::kIsInteger));
150+
if (zbinAuto)
151+
THLimitsFinder::OptimizeLimits(zaxis->GetNbins(),
152+
newbinsz,zmin,zmax,
153+
zaxis->TestBit(TAxis::kIsInteger));
143154

144155
h->SetBins(newbinsx,xmin,xmax,newbinsy,ymin,ymax,newbinsz,zmin,zmax);
145156
return 0;

0 commit comments

Comments
 (0)