Logo ROOT  
Reference Guide
RHistDrawable.cxx
Go to the documentation of this file.
1/// \file RHistDrawable.cxx
2/// \ingroup HistDrawV7
3/// \author Axel Naumann <axel@cern.ch>
4/// \date 2015-09-11
5/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
6/// is welcome!
7
8/*************************************************************************
9 * Copyright (C) 1995-2015, Rene Brun and Fons Rademakers. *
10 * All rights reserved. *
11 * *
12 * For the licensing terms see $ROOTSYS/LICENSE. *
13 * For the list of contributors see $ROOTSYS/README/CREDITS. *
14 *************************************************************************/
15
17
19#include "ROOT/RFrame.hxx"
20#include "ROOT/RPadBase.hxx"
21#include "ROOT/RAxis.hxx"
22
23#include <algorithm> // for std::min
24
25using namespace ROOT::Experimental;
26
27
28std::unique_ptr<RDisplayItem> RHist1Drawable::CreateHistDisplay(const RDisplayContext &ctxt)
29{
30 auto item = std::make_unique<RHistDisplayItem>(*this);
31
32 auto frame = ctxt.GetPad()->GetFrame();
34 if (frame) frame->GetClientRanges(ctxt.GetConnId(), ranges);
35
36 auto himpl = fHistImpl.get();
37
38 if (himpl) {
39
40 int nbinsx = himpl->GetAxis(0).GetNBinsNoOver();
41
42 int i1 = 0, i2 = nbinsx, stepi = 1;
43
44 if (ranges.HasMin(0) && ranges.HasMax(0) && (ranges.GetMin(0) != ranges.GetMax(0))) {
45 i1 = himpl->GetAxis(0).FindBin(ranges.GetMin(0));
46 i2 = himpl->GetAxis(0).FindBin(ranges.GetMax(0));
47 if (i1 <= 1) i1 = 0; else i1--; // include extra left bin
48 if ((i2 <= 0) || (i2 >= nbinsx)) i2 = nbinsx; else i2++; // include extra right bin
49 }
50
51 if (i1 >= i2) {
52 // fatal, fallback to full content
53 i1 = 0; i2 = nbinsx;
54 }
55
56 // make approx 200 bins visible in each direction
57 static const int NumVisibleBins = 5000;
58
59 // with minmax approach 2*n bins replaced by 2 bins with min and max value inside the range
60 // this let display histogram showing dynamic values range properly
61 // configured when more than 3 bins should be merged
62
63 bool needrebin = false, produce_minmax = false;
64
65 if (i2 - i1 > NumVisibleBins) {
66 stepi = (i2 - i1) / NumVisibleBins;
67 if (stepi < 2) stepi = 2;
68 if (stepi > 3) {
69 produce_minmax = true;
70 if (stepi % 2 == 1) stepi++; // ensure even number of stepi
71 }
72 i1 = (i1 / stepi) * stepi;
73 if (i2 % stepi > 0) i2 = (i2/stepi + 1) * stepi;
74 needrebin = true;
75 }
76
77 // be aware, right indicies i2 or j2 can be larger then axes index range.
78 // In this case axis rebin is special
79
80 auto &bins = item->GetBinContent();
81 if (needrebin) {
82 bins.resize((i2 - i1) / stepi * (produce_minmax ? 2 : 1));
83 } else {
84 bins.resize(i2 - i1);
85 }
86
87 double min{0}, minpos{0}, max{0};
88
89 min = max = himpl->GetBinContentAsDouble(1);
90 if (max > 0) minpos = max;
91
92 /// found histogram min/max values
93 /// TODO: make search only when histogram is really changed
94 for (int i = 0; i < nbinsx; ++i) {
95 double val = himpl->GetBinContentAsDouble(i + 1);
96 if (val < min) min = val; else
97 if (val > max) max = val;
98 if ((val > 0.) && (val < minpos)) minpos = val;
99 if (!needrebin && (i>=i1) && (i<i2)) {
100 int indx = (i-i1);
101 bins[indx] = val;
102 }
103 }
104
105 // provide simple rebin with average values
106 // TODO: provide methods in histogram classes
107 if (needrebin)
108 for (int i = i1; i < i2; i += stepi) {
109 int ir = std::min(i+stepi, nbinsx);
110 double vmin = himpl->GetBinContentAsDouble(i + 1);
111 if (produce_minmax) {
112 double vmax = vmin;
113 int imin = i;
114 int imax = i;
115 for(int ii = i+1; ii < ir; ++ii) {
116 double val = himpl->GetBinContentAsDouble(ii + 1);
117 if (val < vmin) { vmin = val; imin = ii; }
118 if (val > vmax) { vmax = val; imax = ii; }
119 }
120 int indx = (i-i1)/stepi*2;
121 bins[indx] = (imin<imax) ? vmin : vmax;
122 bins[indx+1] = (imin<imax) ? vmax : vmin;
123 } else {
124 int indx = (i-i1)/stepi;
125 bins[indx] = vmin;
126 }
127 }
128
129 item->SetContentMinMax(min, minpos, max);
130 item->AddAxis(&himpl->GetAxis(0), i1, i2, !needrebin ? 1 : stepi / (produce_minmax ? 2 : 1));
131 }
132
133 return item;
134}
135
136std::unique_ptr<RDisplayItem> RHist2Drawable::CreateHistDisplay(const RDisplayContext &ctxt)
137{
138 auto item = std::make_unique<RHistDisplayItem>(*this);
139
140 auto frame = ctxt.GetPad()->GetFrame();
141 RFrame::RUserRanges ranges;
142 if (frame) frame->GetClientRanges(ctxt.GetConnId(), ranges);
143
144 auto himpl = fHistImpl.get();
145
146 if (himpl) {
147
148 int nbinsx = himpl->GetAxis(0).GetNBinsNoOver();
149 int nbinsy = himpl->GetAxis(1).GetNBinsNoOver();
150
151 int i1 = 0, i2 = nbinsx, j1 = 0, j2 = nbinsy, stepi = 1, stepj = 1;
152
153 if (ranges.HasMin(0) && ranges.HasMax(0) && (ranges.GetMin(0) != ranges.GetMax(0))) {
154 i1 = himpl->GetAxis(0).FindBin(ranges.GetMin(0));
155 i2 = himpl->GetAxis(0).FindBin(ranges.GetMax(0));
156 if (i1 <= 1) i1 = 0; else i1--; // include extra left bin
157 if ((i2 <= 0) || (i2 >= nbinsx)) i2 = nbinsx; else i2++; // include extra right bin
158 }
159
160 if (ranges.HasMin(1) && ranges.HasMax(1) && (ranges.GetMin(1) != ranges.GetMax(1))) {
161 j1 = himpl->GetAxis(1).FindBin(ranges.GetMin(1));
162 j2 = himpl->GetAxis(1).FindBin(ranges.GetMax(1));
163 if (j1 <= 1) j1 = 0; else j1--; // include extra left bin
164 if ((j2 <= 0) || (j2 >= nbinsy)) j2 = nbinsy; else j2++; // include extra right bin
165 }
166
167 if ((i1 >= i2) || (j1 >= j2)) {
168 // FATAL, fallback to full content
169 i1 = 0; i2 = nbinsx;
170 j1 = 0; j2 = nbinsy;
171 }
172
173 // make approx 200 bins visible in each direction
174 static const int NumVisibleBins = 200;
175
176 bool needrebin = false;
177
178 if (i2 - i1 > NumVisibleBins) {
179 stepi = (i2 - i1) / NumVisibleBins;
180 if (stepi < 2) stepi = 2;
181 i1 = (i1 / stepi) * stepi;
182 if (i2 % stepi > 0) i2 = (i2/stepi + 1) * stepi;
183 needrebin = true;
184 }
185
186 if (j2 - j1 > NumVisibleBins) {
187 stepj = (j2 - j1) / NumVisibleBins;
188 if (stepj < 2) stepj = 2;
189 j1 = (j1 / stepj) * stepj;
190 if (j2 % stepj > 0) j2 = (j2/stepj + 1) * stepj;
191 needrebin = true;
192 }
193
194 // be aware, right indicies i2 or j2 can be larger then axes index range.
195 // In this case axis rebin is special
196
197 auto &bins = item->GetBinContent();
198 bins.resize((i2 - i1) / stepi * (j2 - j1) / stepj);
199
200 double min{0}, minpos{0}, max{0};
201
202 min = max = himpl->GetBinContentAsDouble(1);
203 if (max > 0) minpos = max;
204
205 /// found histogram min/max values
206 for (int j = 0; j < nbinsy; ++j)
207 for (int i = 0; i < nbinsx; ++i) {
208 double val = himpl->GetBinContentAsDouble(j*nbinsx + i + 1);
209 if (val < min) min = val; else
210 if (val > max) max = val;
211 if ((val > 0.) && (val < minpos)) minpos = val;
212 if (!needrebin && (i>=i1) && (i<i2) && (j>=j1) && (j<j2)) {
213 int indx = (j-j1)*(i2-i1) + (i-i1);
214 bins[indx] = val;
215 }
216 }
217
218 // provide simple rebin with average values
219 // TODO: provide methods in histogram classes
220 if (needrebin)
221 for (int j = j1; j < j2; j += stepj) {
222 int jr = std::min(j+stepj, nbinsy);
223 for (int i = i1; i < i2; i += stepi) {
224 double sum = 0.;
225 int ir = std::min(i+stepi, nbinsx);
226 int cnt = 0;
227 for(int jj = j; jj < jr; ++jj)
228 for(int ii = i; ii < ir; ++ii) {
229 sum += himpl->GetBinContentAsDouble(jj*nbinsx + ii + 1);
230 cnt++;
231 }
232
233 int indx = (j-j1)/stepj * (i2-i1)/stepi + (i-i1)/stepi;
234 bins[indx] = sum/cnt;
235 }
236 }
237
238 item->SetContentMinMax(min, minpos, max);
239 item->AddAxis(&himpl->GetAxis(0), i1, i2, stepi);
240 item->AddAxis(&himpl->GetAxis(1), j1, j2, stepj);
241 }
242
243 return item;
244}
245
246
247std::unique_ptr<RDisplayItem> RHist3Drawable::CreateHistDisplay(const RDisplayContext &ctxt)
248{
249 auto item = std::make_unique<RHistDisplayItem>(*this);
250
251 auto frame = ctxt.GetPad()->GetFrame();
252 RFrame::RUserRanges ranges;
253 if (frame) frame->GetClientRanges(ctxt.GetConnId(), ranges);
254
255 auto himpl = fHistImpl.get();
256
257 if (himpl) {
258
259 int nbinsx = himpl->GetAxis(0).GetNBinsNoOver();
260 int nbinsy = himpl->GetAxis(1).GetNBinsNoOver();
261 int nbinsz = himpl->GetAxis(2).GetNBinsNoOver();
262
263 int i1 = 0, i2 = nbinsx, stepi = 1,
264 j1 = 0, j2 = nbinsy, stepj = 1,
265 k1 = 0, k2 = nbinsz, stepk = 1;
266
267 if (ranges.HasMin(0) && ranges.HasMax(0) && (ranges.GetMin(0) != ranges.GetMax(0))) {
268 i1 = himpl->GetAxis(0).FindBin(ranges.GetMin(0));
269 i2 = himpl->GetAxis(0).FindBin(ranges.GetMax(0));
270 if (i1 <= 1) i1 = 0; else i1--; // include extra left bin
271 if ((i2 <= 0) || (i2 >= nbinsx)) i2 = nbinsx; else i2++; // include extra right bin
272 }
273
274 if (ranges.HasMin(1) && ranges.HasMax(1) && (ranges.GetMin(1) != ranges.GetMax(1))) {
275 j1 = himpl->GetAxis(1).FindBin(ranges.GetMin(1));
276 j2 = himpl->GetAxis(1).FindBin(ranges.GetMax(1));
277 if (j1 <= 1) j1 = 0; else j1--; // include extra left bin
278 if ((j2 <= 0) || (j2 >= nbinsy)) j2 = nbinsy; else j2++; // include extra right bin
279 }
280
281 if (ranges.HasMin(2) && ranges.HasMax(2) && (ranges.GetMin(2) != ranges.GetMax(2))) {
282 k1 = himpl->GetAxis(2).FindBin(ranges.GetMin(2));
283 k2 = himpl->GetAxis(2).FindBin(ranges.GetMax(2));
284 if (k1 <= 1) k1 = 0; else k1--; // include extra left bin
285 if ((k2 <= 0) || (k2 >= nbinsz)) k2 = nbinsz; else k2++; // include extra right bin
286 }
287
288 if ((i1 >= i2) || (j1 >= j2) || (k1 >= k2)) {
289 // FATAL, fallback to full content
290 i1 = 0; i2 = nbinsx;
291 j1 = 0; j2 = nbinsy;
292 k1 = 0; k2 = nbinsz;
293 }
294
295 // make approx 25 bins visible in each direction
296 static const int NumVisibleBins = 25;
297
298 bool needrebin = false;
299
300 if (i2 - i1 > NumVisibleBins) {
301 stepi = (i2 - i1) / NumVisibleBins;
302 if (stepi < 2) stepi = 2;
303 i1 = (i1 / stepi) * stepi;
304 if (i2 % stepi > 0) i2 = (i2/stepi + 1) * stepi;
305 needrebin = true;
306 }
307
308 if (j2 - j1 > NumVisibleBins) {
309 stepj = (j2 - j1) / NumVisibleBins;
310 if (stepj < 2) stepj = 2;
311 j1 = (j1 / stepj) * stepj;
312 if (j2 % stepj > 0) j2 = (j2/stepj + 1) * stepj;
313 needrebin = true;
314 }
315
316 if (k2 - k1 > NumVisibleBins) {
317 stepk = (k2 - k1) / NumVisibleBins;
318 if (stepk < 2) stepk = 2;
319 k1 = (k1 / stepk) * stepk;
320 if (k2 % stepk > 0) k2 = (k2/stepk + 1) * stepk;
321 needrebin = true;
322 }
323
324 // be aware, right indicies i2 or j2 can be larger then axes index range.
325 // In this case axis rebin is special
326
327 auto &bins = item->GetBinContent();
328 bins.resize((i2 - i1) / stepi * (j2 - j1) / stepj * (k2 - k1) / stepk);
329
330 double min{0}, minpos{0}, max{0};
331
332 min = max = himpl->GetBinContentAsDouble(1);
333 if (max > 0) minpos = max;
334
335 /// found histogram min/max values
336 for (int k = 0; k < nbinsz; ++k)
337 for (int j = 0; j < nbinsy; ++j)
338 for (int i = 0; i < nbinsx; ++i) {
339 double val = himpl->GetBinContentAsDouble(k*nbinsx*nbinsy + j*nbinsx + i + 1);
340 if (val < min) min = val; else
341 if (val > max) max = val;
342 if ((val > 0.) && (val < minpos)) minpos = val;
343 if (!needrebin && (i>=i1) && (i<i2) && (j>=j1) && (j<j2) && (k>=k1) && (k<k2)) {
344 int indx = (k-k1)*(j2-j1)*(i2-i1) + (j-j1)*(i2-i1) + (i-i1);
345 bins[indx] = val;
346 }
347 }
348
349 // provide simple rebin with average values
350 // TODO: provide methods in histogram classes
351 if (needrebin)
352 for (int k = k1; k < k2; k += stepk) {
353 int kr = std::min(k+stepk, nbinsz);
354 for (int j = j1; j < j2; j += stepj) {
355 int jr = std::min(j+stepj, nbinsy);
356 for (int i = i1; i < i2; i += stepi) {
357 double sum = 0.;
358 int ir = std::min(i+stepi, nbinsx);
359 int cnt = 0;
360 for(int kk = k; kk < kr; ++kk)
361 for(int jj = j; jj < jr; ++jj)
362 for(int ii = i; ii < ir; ++ii) {
363 sum += himpl->GetBinContentAsDouble(kk*nbinsx*nbinsy + jj*nbinsx + ii + 1);
364 cnt++;
365 }
366
367 int indx = (k-k1)/stepk * (j2-j1)/stepj * (i2-i1)/stepi + (j-j1)/stepj * (i2-i1)/stepi + (i-i1)/stepi;
368 bins[indx] = sum/cnt;
369 }
370 }
371 }
372
373 item->SetContentMinMax(min, minpos, max);
374 item->AddAxis(&himpl->GetAxis(0), i1, i2, stepi);
375 item->AddAxis(&himpl->GetAxis(1), j1, j2, stepj);
376 item->AddAxis(&himpl->GetAxis(2), k1, k2, stepk);
377 }
378
379 return item;
380}
bool HasMin(unsigned ndim) const
Definition: RFrame.hxx:89
bool HasMax(unsigned ndim) const
Definition: RFrame.hxx:100
double GetMax(unsigned ndim) const
Definition: RFrame.hxx:101
double GetMin(unsigned ndim) const
Definition: RFrame.hxx:90
std::unique_ptr< RDisplayItem > CreateHistDisplay(const RDisplayContext &) override
std::unique_ptr< RDisplayItem > CreateHistDisplay(const RDisplayContext &) override
Internal::RIOShared< HistImpl_t > fHistImpl
I/O capable reference on histogram.
std::shared_ptr< RFrame > GetFrame()
Get a frame object if exists.
Definition: RPadBase.cxx:214
const char * cnt
Definition: TXMLSetup.cxx:75