Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TSelectorDraw.cxx
Go to the documentation of this file.
1// @(#)root/treeplayer:$Id$
2// Author: Rene Brun 08/01/2003
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12/** \class TSelectorDraw
13A specialized TSelector for TTree::Draw.
14*/
15
16#include "TSelectorDraw.h"
17#include "TROOT.h"
18#include "TH2.h"
19#include "TH3.h"
20#include "TView.h"
21#include "TGraph.h"
22#include "TPolyMarker3D.h"
23#include "TDirectory.h"
24#include "TVirtualPad.h"
25#include "TProfile.h"
26#include "TProfile2D.h"
27#include "TTreeFormulaManager.h"
28#include "TEnv.h"
29#include "TTree.h"
30#include "TCut.h"
31#include "TEntryList.h"
32#include "TEventList.h"
33#include "TEntryListArray.h"
34#include "THLimitsFinder.h"
35#include "TStyle.h"
36#include "TClass.h"
37#include "TColor.h"
38
39#include <string>
40
42
43////////////////////////////////////////////////////////////////////////////////
44/// Default selector constructor.
45
47{
48 fTree = nullptr;
49 fW = nullptr;
50 fValSize = 4;
51 fVal = new Double_t*[fValSize];
52 fVmin = new Double_t[fValSize];
53 fVmax = new Double_t[fValSize];
54 fNbins = new Int_t[fValSize];
55 fVarMultiple = new bool[fValSize];
57 for (Int_t i = 0; i < fValSize; ++i) {
58 fVal[i] = nullptr;
59 fVar[i] = nullptr;
60 }
61 fManager = nullptr;
62 fMultiplicity = 0;
63 fSelect = nullptr;
64 fSelectedRows = 0;
65 fDraw = 0;
66 fObject = nullptr;
67 fOldHistogram = nullptr;
68 fObjEval = false;
69 fSelectMultiple = false;
70 fCleanElist = false;
71 fTreeElist = nullptr;
72 fAction = 0;
73 fNfill = 0;
74 fDimension = 0;
75 fOldEstimate = 0;
76 fForceRead = 0;
77 fWeight = 1;
79 fTreeElistArray = nullptr;
80}
81
82////////////////////////////////////////////////////////////////////////////////
83/// Selector destructor.
84
86{
88 delete [] fVar;
89 if (fVal) {
90 for (Int_t i = 0; i < fValSize; ++i)
91 delete [] fVal[i];
92 delete [] fVal;
93 }
94 if (fVmin) delete [] fVmin;
95 if (fVmax) delete [] fVmax;
96 if (fNbins) delete [] fNbins;
97 if (fVarMultiple) delete [] fVarMultiple;
98 if (fW) delete [] fW;
99}
100
101////////////////////////////////////////////////////////////////////////////////
102/// Called every time a loop on the tree(s) starts.
103
105{
106 SetStatus(0);
107 ResetAbort();
109 fSelectedRows = 0;
110 fTree = tree;
111 fDimension = 0;
112 fAction = 0;
113
114 TObject *obj = fInput->FindObject("varexp");
115 const char *varexp0 = obj ? obj->GetTitle() : "";
116 obj = fInput->FindObject("selection");
117 const char *selection = obj ? obj->GetTitle() : "";
118 const char *option = GetOption();
119
120 TString opt, abrt;
121 char *hdefault = (char *)"htemp";
122 std::string varexp;
123 Int_t i, j, hkeep;
124 opt = option;
125 opt.ToLower();
126 fOldHistogram = nullptr;
127 TEntryList *enlist = nullptr;
128 TEventList *evlist = nullptr;
130 bool profile = false;
131 bool optSame = false;
132 bool optEnlist = false;
133 bool optEnlistArray = false;
134 bool optpara = false;
135 bool optcandle = false;
136 bool opt5d = false;
137 if (opt.Contains("same")) {
138 optSame = true;
139 opt.ReplaceAll("same", "");
140 }
141 if (opt.Contains("entrylist")) {
142 optEnlist = true;
143 if (opt.Contains("entrylistarray")) {
144 optEnlistArray = true;
145 opt.ReplaceAll("entrylistarray", "");
146 } else {
147 opt.ReplaceAll("entrylist", "");
148 }
149 }
150 if (opt.Contains("para")) {
151 optpara = true;
152 opt.ReplaceAll("para", "");
153 }
154 if (opt.Contains("candle")) {
155 optcandle = true;
156 opt.ReplaceAll("candle", "");
157 }
158 if (opt.Contains("gl5d")) {
159 opt5d = true;
160 opt.ReplaceAll("gl5d", "");
161 }
163 //input list - only TEntryList
166 if (evlist && inElist) {
167 //this is needed because the input entry list was created
168 //by the fTree from the input TEventList and is owned by the fTree.
169 //Calling GetEntryList function changes ownership and here
170 //we want fTree to still delete this entry list
171
172 inElist->SetBit(kCanDelete, true);
173 }
174 fCleanElist = false;
176
177 fTreeElistArray = inElist ? dynamic_cast<TEntryListArray*>(fTreeElist) : nullptr;
178
179
180 if (inElist && inElist->GetReapplyCut()) {
181 realSelection *= inElist->GetTitle();
182 }
183
184 // what each variable should contain:
185 // varexp0 - original expression eg "a:b>>htest"
186 // hname - name of new or old histogram
187 // hkeep - flag if to keep new histogram
188 // hnameplus - flag if to add to current histo
189 // i - length of variable expression stripped of everything including/after ">>"
190 // varexp - variable expression stripped of everything including/after ">>"
191 // fOldHistogram - pointer to hist hname
192 // elist - pointer to selection list of hname
193
194 bool canExtend = true;
195 if (optSame) canExtend = false;
196
197 Int_t nbinsx = 0, nbinsy = 0, nbinsz = 0;
198 Double_t xmin = 0, xmax = 0, ymin = 0, ymax = 0, zmin = 0, zmax = 0;
199
200 fObject = nullptr;
201 char *hname = nullptr;
203 i = 0;
204 if (varexp0 && strlen(varexp0)) {
205 for (UInt_t k = strlen(varexp0) - 1; k > 0; k--) {
206 if (varexp0[k] == '>' && varexp0[k-1] == '>') {
207 i = (int)(&(varexp0[k-1]) - varexp0); // length of varexp0 before ">>"
208 hnamealloc = &(varexp0[k+1]); // use TString to copy value of the
209 hname = (char *) hnamealloc.Data();
210 break;
211 }
212 }
213 }
214 // char *hname = (char*)strstr(varexp0,">>");
215 if (hname) {
216 hkeep = 1;
217 bool hnameplus = false;
218 while (*hname == ' ') hname++;
219 if (*hname == '+') {
220 hnameplus = true;
221 hname++;
222 while (*hname == ' ') hname++; //skip ' '
223 }
224 j = strlen(hname) - 1; // skip ' ' at the end
225 while (j) {
226 if (hname[j] != ' ') break;
227 hname[j] = 0;
228 j--;
229 }
230
231 if (i) {
232 varexp = std::string(varexp0, i); // everything before ">>"
233
234 Int_t mustdelete = 0;
236
237 // parse things that follow the name of the histo between '(' and ')'.
238 // At this point hname contains the name of the specified histogram.
239 // Now the syntax is extended to handle an hname of the following format
240 // hname(nBIN [[,[xlow]][,xhigh]],...)
241 // so enclosed in brackets is the binning information, xlow, xhigh, and
242 // the same for the other dimensions
243
244 char *pstart; // pointer to '('
245 char *pend; // pointer to ')'
246 char *cdummy; // dummy pointer
247 int ncomma; // number of commas between '(' and ')', later number of arguments
248 int ncols; // number of columns in varexpr
249 Double_t value; // parsed value (by sscanf)
250
251 const Int_t maxvalues = 9;
252
253 pstart = strchr(hname, '(');
254 pend = strchr(hname, ')');
255 if (pstart != nullptr) { // found the bracket
256
257 mustdelete = 1;
258
259 // check that there is only one open and close bracket
260 if (pstart == strrchr(hname, '(') && pend == strrchr(hname, ')')) {
261
262 // count number of ',' between '(' and ')'
263 ncomma = 0;
264 cdummy = pstart;
265 cdummy = strchr(&cdummy[1], ',');
266 while (cdummy != nullptr) {
267 cdummy = strchr(&cdummy[1], ',');
268 ncomma++;
269 }
270
271 if (ncomma + 1 > maxvalues) {
272 Error("DrawSelect", "ncomma+1>maxvalues, ncomma=%d, maxvalues=%d", ncomma, maxvalues);
273 ncomma = maxvalues - 1;
274 }
275
276 ncomma++; // number of arguments
277 cdummy = pstart;
278
279 // number of columns
280 ncols = 1;
281 for (j = 0; j < i; j++) {
282 if (varexp[j] == ':'
283 && !((j > 0 && varexp[j-1] == ':') || varexp[j+1] == ':')
284 ) {
285 ncols++;
286 } else if (varexp[j] == '?') {
287 ncols--;
288 // We substract to compensate the later `:` of the ternary operator
289 }
290 }
291 if (ncols > 3) { // max 3 columns
292 Error("DrawSelect", "ncols > 3, ncols=%d", ncols);
293 ncols = 0;
294 }
295
296 // check dimensions before and after ">>"
297 if (ncols * 3 < ncomma) {
298 Error("DrawSelect", "ncols*3 < ncomma ncols=%d, ncomma=%d", ncols, ncomma);
299 ncomma = ncols * 3;
300 }
301
302 // scan the values one after the other
303 for (j = 0; j < ncomma; j++) {
304 cdummy++; // skip '(' or ','
305 if (sscanf(cdummy, " %lf ", &value) == 1) {
306 cdummy = strchr(&cdummy[1], ',');
307
308 switch (j) { // do certain settings depending on position of argument
309 case 0: // binning x-axis
310 nbinsx = (Int_t)value;
311 if (ncols < 2) {
312 gEnv->SetValue("Hist.Binning.1D.x", nbinsx);
313 } else if (ncols < 3) {
314 gEnv->SetValue("Hist.Binning.2D.x", nbinsx);
315 gEnv->SetValue("Hist.Binning.2D.Prof", nbinsx);
316 } else {
317 gEnv->SetValue("Hist.Binning.3D.x", nbinsx);
318 gEnv->SetValue("Hist.Binning.3D.Profx", nbinsx);
319 }
320
321 break;
322 case 1: // lower limit x-axis
323 xmin = value;
324 break;
325 case 2: // upper limit x-axis
326 xmax = value;
327 break;
328 case 3: // binning y-axis
329 nbinsy = (Int_t)value;
330 if (ncols < 3) gEnv->SetValue("Hist.Binning.2D.y", nbinsy);
331 else {
332 gEnv->SetValue("Hist.Binning.3D.y", nbinsy);
333 gEnv->SetValue("Hist.Binning.3D.Profy", nbinsy);
334 }
335 break;
336 case 4: // lower limit y-axis
337 ymin = value;
338 break;
339 case 5: // upper limit y-axis
340 ymax = value;
341 break;
342 case 6: // binning z-axis
343 nbinsz = (Int_t)value;
344 gEnv->SetValue("Hist.Binning.3D.z", nbinsz);
345 break;
346 case 7: // lower limit z-axis
347 zmin = value;
348 break;
349 case 8: // upper limit z-axis
350 zmax = value;
351 break;
352 default:
353 Error("DrawSelect", "j>8");
354 break;
355 }
356 } // if sscanf == 1
357 } // for j=0;j<ncomma;j++
358 } else {
359 Error("Begin", "Two open or close brackets found, hname=%s", hname);
360 }
361
362 // fix up hname
363 pstart[0] = '\0'; // removes things after (and including) '('
364 } // if '(' is found
365
366 j = strlen(hname) - 1; // skip ' ' at the end
367 while (j > 0) {
368 if (hname[j] != ' ') break; // skip ' ' at the end
369 hname[j] = 0;
370 j--;
371 }
372
373 TObject *oldObject = gDirectory->Get(hname); // if hname contains '(...)' the return values is NULL, which is what we want
374 fOldHistogram = oldObject ? dynamic_cast<TH1*>(oldObject) : nullptr;
375
376 if (!fOldHistogram && oldObject && !oldObject->InheritsFrom(TH1::Class())) {
377 abrt.Form("An object of type '%s' has the same name as the requested histo (%s)", oldObject->IsA()->GetName(), hname);
378 Abort(abrt);
379 return;
380 }
381 if (!fOldHistogram && hnameplus) {
382 Warning("TSelectorDraw",
383 "TTree::Draw was asked to fill the histogram '%s', but it was not found in the current directory."
384 "Did you forget to call histogram->SetDirectory(gDirectory) or similar?",
385 hname);
386 }
387 if (fOldHistogram && !hnameplus) fOldHistogram->Reset(); // reset unless adding is wanted
388
389 if (mustdelete) {
390 if (gDebug) {
391 Warning("Begin", "Deleting old histogram, since (possibly new) limits and binnings have been given");
392 }
393 delete fOldHistogram; fOldHistogram=nullptr;
394 }
395
396 } else {
397 // make selection list (i.e. varexp0 starts with ">>")
399 if (optEnlist) {
400 //write into a TEntryList
401 enlist = oldObject ? dynamic_cast<TEntryList*>(oldObject) : nullptr;
402
403 if (!enlist && oldObject) {
404 abrt.Form("An object of type '%s' has the same name as the requested event list (%s)",
405 oldObject->IsA()->GetName(), hname);
406 Abort(abrt);
407 return;
408 }
409 if (!enlist) {
410 if (hnameplus) {
411 Warning(
412 "TSelectorDraw",
413 "TTree::Draw was asked to append to TEntryList '%s', but it was not found in the current "
414 "directory."
415 "Did you forget to call entryList->SetDirectory(gDirectory) or similar? Creating a new list now.",
416 hname);
417 }
418 if (optEnlistArray) {
419 enlist = new TEntryListArray(hname, realSelection.GetTitle());
420 } else {
421 enlist = new TEntryList(hname, realSelection.GetTitle());
422 }
423 enlist->SetDirectory(gDirectory); // TTree::Draw documentation promises it shows up in gDirectory
424 }
425 if (enlist) {
426 if (!hnameplus) {
427 if (enlist == inElist) {
428 // We have been asked to reset the input list!!
429 // Let's set it aside for now ...
430 if (optEnlistArray) {
432 } else {
433 inElist = new TEntryList(*enlist);
434 }
435 inElist->SetDirectory(gDirectory); // TTree::Draw documentation promises it shows up in gDirectory
436 fCleanElist = true;
438 }
439 enlist->Reset();
440 enlist->SetTitle(realSelection.GetTitle());
441 } else {
442 TCut old = enlist->GetTitle();
443 TCut upd = old || realSelection.GetTitle();
444 enlist->SetTitle(upd.GetTitle());
445 }
446 }
447 } else {
448 //write into a TEventList
449 evlist = oldObject ? dynamic_cast<TEventList*>(oldObject) : nullptr;
450
451 if (!evlist && oldObject) {
452 abrt.Form("An object of type '%s' has the same name as the requested event list (%s)",
453 oldObject->IsA()->GetName(), hname);
454 Abort(abrt);
455 return;
456 }
457 if (!evlist) {
458 if (hnameplus) {
459 Warning(
460 "TSelectorDraw",
461 "TTree::Draw was asked to append to TEventList '%s', but it was not found in the current "
462 "directory."
463 "Did you forget to call eventList->SetDirectory(gDirectory) or similar? Creating a new list now.",
464 hname);
465 }
466 evlist = new TEventList(hname, realSelection.GetTitle(), 1000, 0);
467 evlist->SetDirectory(gDirectory); // TTree::Draw documentation promises it shows up in gDirectory
468 }
469 if (evlist) {
470 if (!hnameplus) {
471 if (evlist == fTree->GetEventList()) {
472 // We have been asked to reset the input list!!
473 // Let's set it aside for now ...
474 Abort("Input and output lists are the same!");
475 return;
476 }
477 evlist->Reset();
478 evlist->SetTitle(realSelection.GetTitle());
479 } else {
480 TCut old = evlist->GetTitle();
481 TCut upd = old || realSelection.GetTitle();
482 evlist->SetTitle(upd.GetTitle());
483 }
484 }
485 }
486
487 } // if (i)
488 } else { // if (hname)
489 hname = hdefault;
490 hkeep = 0;
491 varexp = varexp0;
492 if (gDirectory) {
494 if (fOldHistogram) { fOldHistogram->Delete(); fOldHistogram = nullptr;}
495 }
496 }
497
498 // Decode varexp and selection
499 if (!CompileVariables(varexp.c_str(), realSelection.GetTitle())) {
500 abrt.Form("Variable compilation failed: {%s,%s}", varexp.c_str(), realSelection.GetTitle());
501 Abort(abrt);
502 return;
503 }
504 if (fDimension > 4 && !(optpara || optcandle || opt5d || opt.Contains("goff"))) {
505 Abort("Too many variables. Use the option \"para\", \"gl5d\" or \"candle\" to display more than 4 variables.");
506 return;
507 }
508 if (fDimension < 2 && (optpara || optcandle)) {
509 Abort("The options \"para\" and \"candle\" require at least 2 variables.");
510 return;
511 }
512
513 // In case fOldHistogram exists, check dimensionality
515 if (nsel > 1) {
516 htitle.Form("%s {%s}", varexp.c_str(), selection);
517 } else {
518 htitle = varexp;
519 }
520 if (fOldHistogram) {
522 Int_t mustdelete = 0;
524 profile = true;
525 olddim = 2;
526 }
528 profile = true;
529 olddim = 3;
530 }
531 if (opt.Contains("prof") && fDimension > 1) {
532 // ignore "prof" for 1D.
533 if (!profile || olddim != fDimension) mustdelete = 1;
534 } else if (opt.Contains("col") && fDimension>2) {
535 if (olddim+1 != fDimension) mustdelete = 1;
536 } else {
537 if (olddim != fDimension) mustdelete = 1;
538 }
539 if (mustdelete) {
540 Warning("Begin", "Deleting old histogram with different dimensions");
541 delete fOldHistogram;
542 fOldHistogram = nullptr;
543 }
544 }
545
546 // Create a default canvas if none exists
547 fDraw = 0;
548 if (!gPad && !opt.Contains("goff") && fDimension > 0) {
549 gROOT->MakeDefCanvas();
550 if (!gPad) {
551 Abort("Creation of default canvas failed");
552 return;
553 }
554 }
555
556 // 1-D distribution
557 TH1 *hist;
558 if (fDimension == 1) {
559 fAction = 1;
560 if (!fOldHistogram) {
561 fNbins[0] = gEnv->GetValue("Hist.Binning.1D.x", 100);
562 if (gPad && optSame) {
563 TListIter np(gPad->GetListOfPrimitives());
564 TObject *op;
565 TH1 *oldhtemp = nullptr;
566 while ((op = np()) && !oldhtemp) {
567 if (op->InheritsFrom(TH1::Class())) oldhtemp = (TH1 *)op;
568 }
569 if (oldhtemp) {
570 fNbins[0] = oldhtemp->GetXaxis()->GetNbins();
571 fVmin[0] = oldhtemp->GetXaxis()->GetXmin();
572 fVmax[0] = oldhtemp->GetXaxis()->GetXmax();
573 } else {
574 fVmin[0] = gPad->GetUxmin();
575 fVmax[0] = gPad->GetUxmax();
576 }
577 } else {
578 fAction = -1;
579 fVmin[0] = xmin;
580 fVmax[0] = xmax;
581 if (xmin < xmax) canExtend = false;
582 }
583 }
584 if (fOldHistogram) {
585 hist = fOldHistogram;
586 fNbins[0] = hist->GetXaxis()->GetNbins();
587 } else {
588 TString precision = gEnv->GetValue("Hist.Precision.1D", "float");
589 if (precision.Contains("float")) {
590 hist = new TH1F(hname, htitle.Data(), fNbins[0], fVmin[0], fVmax[0]);
591 } else {
592 hist = new TH1D(hname, htitle.Data(), fNbins[0], fVmin[0], fVmax[0]);
593 }
604 if (!hkeep) {
605 hist->GetXaxis()->SetTitle(fVar[0]->GetTitle());
606 hist->SetBit(kCanDelete);
607 if (!opt.Contains("goff")) hist->SetDirectory(nullptr);
608 }
609 if (opt.Length() && opt.Contains("e")) hist->Sumw2();
610 }
611 fVar[0]->SetAxis(hist->GetXaxis());
612 fObject = hist;
613
614 // 2-D distribution
615 } else if (fDimension == 2 && !(optpara || optcandle)) {
616 fAction = 2;
617 if (!fOldHistogram || !optSame) {
618 fNbins[0] = gEnv->GetValue("Hist.Binning.2D.y", 40);
619 fNbins[1] = gEnv->GetValue("Hist.Binning.2D.x", 40);
620 if (opt.Contains("prof")) fNbins[1] = gEnv->GetValue("Hist.Binning.2D.Prof", 100);
621 if (optSame) {
622 TH1 *oldhtemp = (TH1*)gPad->FindObject(hdefault);
623 if (oldhtemp) {
624 fNbins[1] = oldhtemp->GetXaxis()->GetNbins();
625 fVmin[1] = oldhtemp->GetXaxis()->GetXmin();
626 fVmax[1] = oldhtemp->GetXaxis()->GetXmax();
627 fNbins[0] = oldhtemp->GetYaxis()->GetNbins();
628 fVmin[0] = oldhtemp->GetYaxis()->GetXmin();
629 fVmax[0] = oldhtemp->GetYaxis()->GetXmax();
630 } else {
631 fNbins[1] = gEnv->GetValue("Hist.Binning.2D.x", 40);
632 fVmin[1] = gPad->GetUxmin();
633 fVmax[1] = gPad->GetUxmax();
634 fNbins[0] = gEnv->GetValue("Hist.Binning.2D.y", 40);
635 fVmin[0] = gPad->GetUymin();
636 fVmax[0] = gPad->GetUymax();
637 }
638 } else {
639 if (!fOldHistogram) fAction = -2;
640 fVmin[1] = xmin;
641 fVmax[1] = xmax;
642 fVmin[0] = ymin;
643 fVmax[0] = ymax;
644 if (xmin < xmax && ymin < ymax) canExtend = false;
645 }
646 }
647 if (profile || opt.Contains("prof")) {
648 TProfile *hp;
649 if (fOldHistogram) {
650 fAction = 4;
652 } else {
653 if (fAction < 0) {
654 fAction = -4;
655 fVmin[1] = xmin;
656 fVmax[1] = xmax;
657 if (xmin < xmax) canExtend = false;
658 }
659 if (fAction == 2) {
660 //we come here when option = "same prof"
661 fAction = -4;
662 TH1 *oldhtemp = (TH1*)gPad->FindObject(hdefault);
663 if (oldhtemp) {
664 fNbins[1] = oldhtemp->GetXaxis()->GetNbins();
665 fVmin[1] = oldhtemp->GetXaxis()->GetXmin();
666 fVmax[1] = oldhtemp->GetXaxis()->GetXmax();
667 }
668 }
669 if (opt.Contains("profs")) {
670 hp = new TProfile(hname, htitle.Data(), fNbins[1], fVmin[1], fVmax[1], "s");
671 } else if (opt.Contains("profi")) {
672 hp = new TProfile(hname, htitle.Data(), fNbins[1], fVmin[1], fVmax[1], "i");
673 } else if (opt.Contains("profg")) {
674 hp = new TProfile(hname, htitle.Data(), fNbins[1], fVmin[1], fVmax[1], "g");
675 } else {
676 hp = new TProfile(hname, htitle.Data(), fNbins[1], fVmin[1], fVmax[1], "");
677 }
678 hp->SetDirectory(gDirectory);
679 if (!hkeep) {
680 hp->SetBit(kCanDelete);
681 if (!opt.Contains("goff")) hp->SetDirectory(nullptr);
682 }
683 hp->SetLineColor(fTree->GetLineColor());
684 hp->SetLineWidth(fTree->GetLineWidth());
685 hp->SetLineStyle(fTree->GetLineStyle());
686 hp->SetFillColor(fTree->GetFillColor());
687 hp->SetFillStyle(fTree->GetFillStyle());
688 hp->SetMarkerStyle(fTree->GetMarkerStyle());
689 hp->SetMarkerColor(fTree->GetMarkerColor());
690 hp->SetMarkerSize(fTree->GetMarkerSize());
691 if (canExtend) hp->SetCanExtend(TH1::kAllAxes);
692 }
693 fVar[1]->SetAxis(hp->GetXaxis());
694 fObject = hp;
695
696 } else {
697 TH2 *h2;
698 if (fOldHistogram) {
699 h2 = (TH2F*)fOldHistogram;
700 } else {
701 TString precision = gEnv->GetValue("Hist.Precision.2D", "float");
702 if (precision.Contains("float")) {
703 h2 = new TH2F(hname, htitle.Data(), fNbins[1], fVmin[1], fVmax[1], fNbins[0], fVmin[0], fVmax[0]);
704 } else {
705 h2 = new TH2D(hname, htitle.Data(), fNbins[1], fVmin[1], fVmax[1], fNbins[0], fVmin[0], fVmax[0]);
706 }
717 if (!hkeep) {
718 h2->GetXaxis()->SetTitle(fVar[1]->GetTitle());
719 h2->GetYaxis()->SetTitle(fVar[0]->GetTitle());
721 h2->SetBit(kCanDelete);
722 if (!opt.Contains("goff")) h2->SetDirectory(nullptr);
723 }
724 }
725 fVar[0]->SetAxis(h2->GetYaxis());
726 fVar[1]->SetAxis(h2->GetXaxis());
727 bool graph = false;
728 Int_t l = opt.Length();
729 if (l == 0 || optSame) graph = true;
730 if (opt.Contains("p") || opt.Contains("*") || opt.Contains("l")) graph = true;
731 if (opt.Contains("surf") || opt.Contains("lego") || opt.Contains("cont")) graph = false;
732 if (opt.Contains("col") || opt.Contains("hist") || opt.Contains("scat")) graph = false;
733 if (opt.Contains("box")) graph = false;
734 fObject = h2;
735 if (graph) {
736 fAction = 12;
737 if (!fOldHistogram && !optSame) fAction = -12;
738 }
739 }
740
741 // 3-D distribution
742 } else if ((fDimension == 3 || fDimension == 4) && !(optpara || optcandle)) {
743 fAction = 3;
744 if (fDimension == 4) fAction = 40;
745 if (!fOldHistogram || !optSame) {
746 fNbins[0] = gEnv->GetValue("Hist.Binning.3D.z", 20);
747 fNbins[1] = gEnv->GetValue("Hist.Binning.3D.y", 20);
748 fNbins[2] = gEnv->GetValue("Hist.Binning.3D.x", 20);
749 if (fDimension == 3 && opt.Contains("prof")) {
750 fNbins[1] = gEnv->GetValue("Hist.Binning.3D.Profy", 20);
751 fNbins[2] = gEnv->GetValue("Hist.Binning.3D.Profx", 20);
752 } else if (fDimension == 3 && opt.Contains("col")) {
753 fNbins[0] = gEnv->GetValue("Hist.Binning.2D.y", 40);
754 fNbins[1] = gEnv->GetValue("Hist.Binning.2D.x", 40);
755 }
756 if (optSame) {
757 TH1 *oldhtemp = (TH1*)gPad->FindObject(hdefault);
758 if (oldhtemp) {
759 fNbins[2] = oldhtemp->GetXaxis()->GetNbins();
760 fVmin[2] = oldhtemp->GetXaxis()->GetXmin();
761 fVmax[2] = oldhtemp->GetXaxis()->GetXmax();
762 fNbins[1] = oldhtemp->GetYaxis()->GetNbins();
763 fVmin[1] = oldhtemp->GetYaxis()->GetXmin();
764 fVmax[1] = oldhtemp->GetYaxis()->GetXmax();
765 fNbins[0] = oldhtemp->GetZaxis()->GetNbins();
766 fVmin[0] = oldhtemp->GetZaxis()->GetXmin();
767 fVmax[0] = oldhtemp->GetZaxis()->GetXmax();
768 } else {
769 TView *view = gPad->GetView();
770 if (!view) {
771 Error("Begin", "You cannot use option same when no 3D view exists");
772 fVmin[0] = fVmin[1] = fVmin[2] = -1;
773 fVmax[0] = fVmax[1] = fVmax[2] = 1;
774 view = TView::CreateView(1, fVmin, fVmax);
775 }
776 Double_t *rmin = view->GetRmin();
777 Double_t *rmax = view->GetRmax();
778 fNbins[2] = gEnv->GetValue("Hist.Binning.3D.z", 20);
779 fVmin[2] = rmin[0];
780 fVmax[2] = rmax[0];
781 fNbins[1] = gEnv->GetValue("Hist.Binning.3D.y", 20);
782 fVmin[1] = rmin[1];
783 fVmax[1] = rmax[1];
784 fNbins[0] = gEnv->GetValue("Hist.Binning.3D.x", 20);
785 fVmin[0] = rmin[2];
786 fVmax[0] = rmax[2];
787 }
788 } else {
789 if (!fOldHistogram && fDimension == 3) fAction = -3;
790 fVmin[2] = xmin;
791 fVmax[2] = xmax;
792 fVmin[1] = ymin;
793 fVmax[1] = ymax;
794 fVmin[0] = zmin;
795 fVmax[0] = zmax;
796 if (xmin < xmax && ymin < ymax && zmin < zmax) canExtend = false;
797 }
798 }
799 if ((fDimension == 3) && (profile || opt.Contains("prof"))) {
800 TProfile2D *hp;
801 if (fOldHistogram) {
802 fAction = 23;
804 } else {
805 if (fAction < 0) {
806 fAction = -23;
807 fVmin[2] = xmin;
808 fVmax[2] = xmax;
809 fVmin[1] = ymin;
810 fVmax[1] = ymax;
811 if (xmin < xmax && ymin < ymax) canExtend = false;
812 }
813 if (opt.Contains("profs")) {
814 hp = new TProfile2D(hname, htitle.Data(), fNbins[2], fVmin[2], fVmax[2], fNbins[1], fVmin[1], fVmax[1], "s");
815 } else if (opt.Contains("profi")) {
816 hp = new TProfile2D(hname, htitle.Data(), fNbins[2], fVmin[2], fVmax[2], fNbins[1], fVmin[1], fVmax[1], "i");
817 } else if (opt.Contains("profg")) {
818 hp = new TProfile2D(hname, htitle.Data(), fNbins[2], fVmin[2], fVmax[2], fNbins[1], fVmin[1], fVmax[1], "g");
819 } else {
820 hp = new TProfile2D(hname, htitle.Data(), fNbins[2], fVmin[2], fVmax[2], fNbins[1], fVmin[1], fVmax[1], "");
821 }
822 hp->SetDirectory(gDirectory);
823 if (!hkeep) {
824 hp->SetBit(kCanDelete);
825 if (!opt.Contains("goff")) hp->SetDirectory(nullptr);
826 }
827 hp->SetLineColor(fTree->GetLineColor());
828 hp->SetLineWidth(fTree->GetLineWidth());
829 hp->SetLineStyle(fTree->GetLineStyle());
830 hp->SetFillColor(fTree->GetFillColor());
831 hp->SetFillStyle(fTree->GetFillStyle());
832 hp->SetMarkerStyle(fTree->GetMarkerStyle());
833 hp->SetMarkerColor(fTree->GetMarkerColor());
834 hp->SetMarkerSize(fTree->GetMarkerSize());
835 if (canExtend) hp->SetCanExtend(TH1::kAllAxes);
836 }
837 fVar[1]->SetAxis(hp->GetYaxis());
838 fVar[2]->SetAxis(hp->GetXaxis());
839 fObject = hp;
840 } else if (fDimension == 3 && opt.Contains("col")) {
841 TH2F *h2;
842 if (fOldHistogram) {
843 h2 = (TH2F*)fOldHistogram;
844 } else {
845 h2 = new TH2F(hname, htitle.Data(), fNbins[1], fVmin[1], fVmax[1], fNbins[0], fVmin[0], fVmax[0]);
856 if (!hkeep) {
857 h2->GetXaxis()->SetTitle(fVar[1]->GetTitle());
858 h2->GetYaxis()->SetTitle(fVar[0]->GetTitle());
859 h2->GetZaxis()->SetTitle(fVar[2]->GetTitle());
861 h2->SetBit(kCanDelete);
862 if (!opt.Contains("goff")) h2->SetDirectory(nullptr);
863 }
864 }
865 fVar[0]->SetAxis(h2->GetYaxis());
866 fVar[1]->SetAxis(h2->GetXaxis());
867 fObject = h2;
868 fAction = 33;
869 } else {
870 TH3 *h3;
871 if (fOldHistogram) {
873 } else {
874 TString precision = gEnv->GetValue("Hist.Precision.3D", "float");
875 if (precision.Contains("float")) {
876 h3 = new TH3F(hname, htitle.Data(), fNbins[2], fVmin[2], fVmax[2], fNbins[1], fVmin[1], fVmax[1], fNbins[0], fVmin[0], fVmax[0]);
877 } else {
878 h3 = new TH3D(hname, htitle.Data(), fNbins[2], fVmin[2], fVmax[2], fNbins[1], fVmin[1], fVmax[1], fNbins[0], fVmin[0], fVmax[0]);
879 }
880 h3->SetDirectory(gDirectory);
881 h3->SetLineColor(fTree->GetLineColor());
882 h3->SetLineWidth(fTree->GetLineWidth());
883 h3->SetLineStyle(fTree->GetLineStyle());
884 h3->SetFillColor(fTree->GetFillColor());
885 h3->SetFillStyle(fTree->GetFillStyle());
886 h3->SetMarkerStyle(fTree->GetMarkerStyle());
887 h3->SetMarkerColor(fTree->GetMarkerColor());
888 h3->SetMarkerSize(fTree->GetMarkerSize());
889 if (canExtend) h3->SetCanExtend(TH1::kAllAxes);
890 if (!hkeep) {
891 //small correction for the title offsets in x,y to take into account the angles
892 Double_t xoffset = h3->GetXaxis()->GetTitleOffset();
893 Double_t yoffset = h3->GetYaxis()->GetTitleOffset();
894 h3->GetXaxis()->SetTitleOffset(1.2 * xoffset);
895 h3->GetYaxis()->SetTitleOffset(1.2 * yoffset);
896 h3->GetXaxis()->SetTitle(fVar[2]->GetTitle());
897 h3->GetYaxis()->SetTitle(fVar[1]->GetTitle());
898 h3->GetZaxis()->SetTitle(fVar[0]->GetTitle());
899 h3->SetBit(kCanDelete);
900 h3->SetBit(TH1::kNoStats);
901 if (!opt.Contains("goff")) h3->SetDirectory(nullptr);
902 }
903 }
904 fVar[0]->SetAxis(h3->GetZaxis());
905 fVar[1]->SetAxis(h3->GetYaxis());
906 fVar[2]->SetAxis(h3->GetXaxis());
907 fObject = h3;
909 if (optSame) noscat -= 4;
910 if (!noscat && fDimension == 3) {
911 fAction = 13;
912 if (!fOldHistogram && !optSame) fAction = -13;
913 }
914 }
915 // An Event List
916 } else if (enlist) {
917 fAction = 5;
919 fTree->SetEstimate(1);
920 fObject = enlist;
921 } else if (evlist) {
922 fAction = 5;
924 fTree->SetEstimate(1);
925 fObject = evlist;
926 } else if (optcandle || optpara || opt5d) {
927 if (optcandle) fAction = 7;
928 else if (opt5d) fAction = 8;
929 else fAction = 6;
930 }
931 for (i = 0; i < fValSize; ++i)
932 fVarMultiple[i] = false;
933 fSelectMultiple = false;
934 for (i = 0; i < fDimension; ++i) {
935 if (fVar[i] && fVar[i]->GetMultiplicity()) fVarMultiple[i] = true;
936 }
937
939
942 fNfill = 0;
943
944 for (i = 0; i < fDimension; ++i) {
945 if (!fVal[i] && fVar[i]) {
946 fVal[i] = new Double_t[(Int_t)fTree->GetEstimate()];
947 }
948 }
949
950 if (!fW) fW = new Double_t[(Int_t)fTree->GetEstimate()];
951
952 for (i = 0; i < fValSize; ++i) {
953 fVmin[i] = DBL_MAX;
954 fVmax[i] = -DBL_MAX;
955 }
956}
957
958////////////////////////////////////////////////////////////////////////////////
959/// Delete internal buffers.
960
962{
964 for (Int_t i = 0; i < fValSize; ++i) {
965 delete fVar[i];
966 fVar[i] = nullptr;
967 }
968 delete fSelect; fSelect = nullptr;
969 fManager = nullptr;
970 fMultiplicity = 0;
971}
972
973////////////////////////////////////////////////////////////////////////////////
974/// Compile input variables and selection expression.
975///
976/// varexp is an expression of the general form e1:e2:e3
977/// where e1,etc is a formula referencing a combination of the columns
978///
979/// Example:
980///
981/// varexp = x simplest case: draw a 1-Dim distribution of column named x
982/// = sqrt(x) : draw distribution of sqrt(x)
983/// = x*y/z
984/// = y:sqrt(x) 2-Dim distribution of y versus sqrt(x)
985///
986/// selection is an expression with a combination of the columns
987///
988/// Example:
989///
990/// selection = "x<y && sqrt(z)>3.2"
991///
992/// in a selection all the C++ operators are authorized
993///
994/// Return false if any of the variable is not compilable.
995
997{
998 Int_t i, nch, ncols;
999
1000 // Compile selection expression if there is one
1001 fDimension = 0;
1002 ClearFormula();
1003 fMultiplicity = 0;
1004 fObjEval = false;
1005
1006 if (strlen(selection)) {
1007 fSelect = new TTreeFormula("Selection", selection, fTree);
1008 fSelect->SetQuickLoad(true);
1009 if (!fSelect->GetNdim()) {
1010 delete fSelect;
1011 fSelect = nullptr;
1012 return false;
1013 }
1014 }
1015
1016 // if varexp is empty, take first column by default
1017 nch = strlen(varexp);
1018 if (nch == 0) {
1019 fDimension = 0;
1020 if (fSelect) {
1022 }
1024
1025 if (fManager) {
1026 fManager->Sync();
1027
1030 }
1031
1032 return true;
1033 }
1034
1035 // otherwise select only the specified columns
1036 std::vector<TString> varnames;
1038
1040
1042 if (fSelect) fManager->Add(fSelect);
1044 for (i = 0; i < ncols; ++i) {
1045 fVar[i] = new TTreeFormula(TString::Format("Var%i", i + 1), varnames[i].Data(), fTree);
1046 fVar[i]->SetQuickLoad(true);
1047 if(!fVar[i]->GetNdim()) { ClearFormula(); return false; }
1048 fManager->Add(fVar[i]);
1049 }
1050 fManager->Sync();
1051
1054
1055 fDimension = ncols;
1056
1057 if (ncols == 1) {
1058 TClass *cl = fVar[0]->EvalClass();
1059 if (cl) {
1060 fObjEval = true;
1061 }
1062 }
1063 return true;
1064}
1065
1066////////////////////////////////////////////////////////////////////////////////
1067/// Return the last values corresponding to the i-th component
1068/// of the formula being processed (where the component are ':' separated).
1069/// The actual number of entries is:
1070///
1071/// GetSelectedRows() % tree->GetEstimate()
1072///
1073/// Note GetSelectedRows currently returns the actual number of values plotted
1074/// and thus if the formula contains arrays, this number might be greater than
1075/// the number of entries in the trees.
1076///
1077/// By default TTree::Draw creates the arrays obtained
1078/// with all GetVal and GetW with a length corresponding to the
1079/// parameter fEstimate. By default fEstimate=10000 and can be modified
1080/// via TTree::SetEstimate. A possible recipe is to do
1081///
1082/// tree->SetEstimate(tree->GetEntries());
1083///
1084/// You must call SetEstimate if the expected number of selected rows
1085/// is greater than 10000.
1086///
1087/// See TTree::Draw for additional details.
1088
1090{
1092 return nullptr;
1093 else
1094 return fVal[i];
1095}
1096
1097////////////////////////////////////////////////////////////////////////////////
1098/// Return the TTreeFormula corresponding to the i-th component
1099/// of the request formula (where the component are ':' separated).
1100
1102{
1104 return nullptr;
1105 else
1106 return fVar[i];
1107}
1108
1109////////////////////////////////////////////////////////////////////////////////
1110/// Initialization of the primitive type arrays if the new size is bigger than the available space.
1111
1113{
1114 if (newsize > fValSize) {
1116 while (fValSize < newsize)
1117 fValSize *= 2; // Double the available space until it matches the new size.
1118 if (fNbins) delete [] fNbins;
1119 if (fVmin) delete [] fVmin;
1120 if (fVmax) delete [] fVmax;
1121 if (fVarMultiple) delete [] fVarMultiple;
1122
1123 fNbins = new Int_t[fValSize];
1124 fVmin = new Double_t[fValSize];
1125 fVmax = new Double_t[fValSize];
1126 fVarMultiple = new bool[fValSize];
1127
1128 for (Int_t i = 0; i < oldsize; ++i)
1129 delete [] fVal[i];
1130 delete [] fVal;
1131 delete [] fVar;
1132 fVal = new Double_t*[fValSize];
1133 fVar = new TTreeFormula*[fValSize];
1134 for (Int_t i = 0; i < fValSize; ++i) {
1135 fVal[i] = nullptr;
1136 fVar[i] = nullptr;
1137 }
1138 }
1139}
1140
1141////////////////////////////////////////////////////////////////////////////////
1142/// Build Index array for names in varexp.
1143/// This will allocated a C style array of TString and Ints
1144
1145UInt_t TSelectorDraw::SplitNames(const TString &varexp, std::vector<TString> &names)
1146{
1147 names.clear();
1148
1149 bool ternary = false;
1150 Int_t prev = 0;
1151 for (Int_t i = 0; i < varexp.Length(); i++) {
1152 if (varexp[i] == ':'
1153 && !((i > 0 && varexp[i-1] == ':') || varexp[i+1] == ':')
1154 ) {
1155 if (ternary) {
1156 ternary = false;
1157 } else {
1158 names.push_back(varexp(prev, i - prev));
1159 prev = i + 1;
1160 }
1161 }
1162 if (varexp[i] == '?') {
1163 ternary = true;
1164 }
1165 }
1166 names.push_back(varexp(prev, varexp.Length() - prev));
1167 return names.size();
1168}
1169
1170
1171////////////////////////////////////////////////////////////////////////////////
1172/// This function is called at the first entry of a new tree in a chain.
1173
1175{
1176 if (fTree) fWeight = fTree->GetWeight();
1177 if (fVar) {
1178 for (Int_t i = 0; i < fDimension; ++i) {
1179 if (fVar[i]) fVar[i]->UpdateFormulaLeaves();
1180 }
1181 }
1183 return true;
1184}
1185
1186////////////////////////////////////////////////////////////////////////////////
1187/// Called in the entry loop for all entries accepted by Select.
1188
1190{
1191 if (fObjEval) {
1193 return;
1194 }
1195
1196 if (fMultiplicity) {
1198 return;
1199 }
1200
1201 if (fNfill >= fTree->GetEstimate())
1202 fNfill = 0;
1203
1204 // simple case with no multiplicity
1205 if (fForceRead && fManager->GetNdata() <= 0) return;
1206
1207 if (fSelect) {
1209 if (!fW[fNfill]) return;
1210 } else fW[fNfill] = fWeight;
1211 if (fVal) {
1212 for (Int_t i = 0; i < fDimension; ++i) {
1213 if (fVar[i]) fVal[i][fNfill] = fVar[i]->EvalInstance(0);
1214 }
1215 }
1216 fNfill++;
1217 if (fNfill >= fTree->GetEstimate()) {
1218 TakeAction();
1219 }
1220}
1221
1222////////////////////////////////////////////////////////////////////////////////
1223/// Called in the entry loop for all entries accepted by Select.
1224/// Complex case with multiplicity.
1225
1227{
1228 if (fNfill >= fTree->GetEstimate())
1229 fNfill = 0;
1230
1231 // Grab the array size of the formulas for this entry
1233
1234 // No data at all, let's move on to the next entry.
1235 if (!ndata) return;
1236
1237 // If the entry list is a TEntryListArray, get the selected subentries for this entry
1238 TEntryList *subList = nullptr;
1239 if (fTreeElistArray) {
1241 }
1242
1244
1245 // Calculate the first values
1246 if (fSelect) {
1247 // coverity[var_deref_model] fSelectMultiple==true => fSelect != 0
1249 if (!fW[fNfill] && !fSelectMultiple) return;
1250 } else fW[fNfill] = fWeight;
1251
1252 // Always call EvalInstance(0) to insure the loading
1253 // of the branches.
1254 if (fW[fNfill] && (!subList || subList->Contains(0))) {
1255 if (fDimension == 0 && fSelectMultiple) fCurrentSubEntry = (Long64_t) 0; // to fill TEntryListArray
1256 for (Int_t i = 0; i < fDimension; ++i) {
1257 if (fVar[i]) fVal[i][fNfill] = fVar[i]->EvalInstance(0);
1258 }
1259 fNfill++;
1260 if (fNfill >= fTree->GetEstimate()) {
1261 TakeAction();
1262 }
1263 } else {
1264 for (Int_t i = 0; i < fDimension; ++i) {
1265 if (fVar[i]) fVar[i]->ResetLoading();
1266 }
1267 }
1268 Double_t ww = fW[nfill0];
1269
1270 for (Int_t i = 1; i < ndata; i++) {
1271 if (fNfill >= fTree->GetEstimate())
1272 fNfill = 0;
1273 if (subList && !subList->Contains(i))
1274 continue;
1275 if (fSelectMultiple) {
1276 // coverity[var_deref_model] fSelectMultiple==true => fSelect != 0
1277 ww = fWeight * fSelect->EvalInstance(i);
1278 if (ww == 0) continue;
1279 if (fNfill == nfill0) {
1280 for (Int_t k = 0; k < fDimension; ++k) {
1281 if (!fVarMultiple[k]) fVal[k][fNfill] = fVar[k]->EvalInstance(0);
1282 }
1283 }
1284 if (fDimension == 0) fCurrentSubEntry = (Long64_t) i; // to fill TEntryListArray
1285 }
1286 for (Int_t k = 0; k < fDimension; ++k) {
1287 if (fVarMultiple[k]) fVal[k][fNfill] = fVar[k]->EvalInstance(i);
1288 else fVal[k][fNfill] = fVal[k][nfill0];
1289 }
1290 fW[fNfill] = ww;
1291
1292 fNfill++;
1293 if (fNfill >= fTree->GetEstimate()) {
1294 TakeAction();
1295 }
1296 }
1297}
1298
1299////////////////////////////////////////////////////////////////////////////////
1300/// Called in the entry loop for all entries accepted by Select.
1301/// Case where the only variable returns an object (or pointer to).
1302
1304{
1305 // Complex case with multiplicity.
1306
1307 if (fNfill >= fTree->GetEstimate())
1308 fNfill = 0;
1309
1310 // Grab the array size of the formulas for this entry
1312
1313 // No data at all, let's move on to the next entry.
1314 if (!ndata) return;
1315
1317 Double_t ww = 0;
1318
1319 for (Int_t i = 0; i < ndata; i++) {
1320 if (i == 0) {
1321 if (fSelect) {
1323 if (!fW[fNfill] && !fSelectMultiple) return;
1324 } else fW[fNfill] = fWeight;
1325 ww = fW[nfill0];
1326 } else if (fSelectMultiple) {
1327 ww = fWeight * fSelect->EvalInstance(i);
1328 if (ww == 0) continue;
1329 }
1330 if (fDimension >= 1 && fVar[0]) {
1331 TClass *cl = fVar[0]->EvalClass();
1332 if (cl == TBits::Class()) {
1333
1334 void *obj = fVar[0]->EvalObject(i);
1335
1336 if (obj) {
1337 TBits *bits = (TBits*)obj;
1338 Int_t nbits = bits->GetNbits();
1339
1340 Int_t nextbit = -1;
1341 while (true) {
1342 nextbit = bits->FirstSetBit(nextbit + 1);
1343 if (nextbit >= nbits) break;
1344 fVal[0][fNfill] = nextbit;
1345 fW[fNfill] = ww;
1346 fNfill++;
1347 }
1348 }
1349
1350 } else {
1351
1352 if (!TestBit(kWarn)) {
1353 Warning("ProcessFillObject",
1354 "Not implemented for %s",
1355 cl ? cl->GetName() : "unknown class");
1356 SetBit(kWarn);
1357 }
1358
1359 }
1360 }
1361 if (fNfill >= fTree->GetEstimate()) {
1362 TakeAction();
1363 }
1364 }
1365
1366}
1367
1368////////////////////////////////////////////////////////////////////////////////
1369/// Set number of entries to estimate variable limits.
1370
1372{
1373 if (fVal) {
1374 for (Int_t i = 0; i < fValSize; ++i) {
1375 delete [] fVal[i];
1376 fVal[i] = nullptr;
1377 }
1378 }
1379 delete [] fW; fW = nullptr;
1380}
1381
1382////////////////////////////////////////////////////////////////////////////////
1383/// Execute action for object obj fNfill times.
1384
1386{
1387 Int_t i;
1388 //__________________________1-D histogram_______________________
1389 if (fAction == 1)((TH1*)fObject)->FillN(fNfill, fVal[0], fW);
1390 //__________________________2-D histogram_______________________
1391 else if (fAction == 2) {
1392 TH2 *h2 = (TH2*)fObject;
1393 for (i = 0; i < fNfill; i++) h2->Fill(fVal[1][i], fVal[0][i], fW[i]);
1394 }
1395 //__________________________Profile histogram_______________________
1396 else if (fAction == 4)((TProfile*)fObject)->FillN(fNfill, fVal[1], fVal[0], fW);
1397 //__________________________Event List______________________________
1398 else if (fAction == 5) {
1401 Long64_t enumb = fTree->GetTree()->GetReadEntry();
1402 enlistarray->Enter(enumb, nullptr, fCurrentSubEntry);
1403 } else if (fObject->InheritsFrom(TEntryList::Class())) {
1405 Long64_t enumb = fTree->GetTree()->GetReadEntry();
1406 enlist->Enter(enumb);
1407 } else {
1409 Long64_t enumb = fTree->GetChainOffset() + fTree->GetTree()->GetReadEntry();
1410 if (evlist->GetIndex(enumb) < 0) evlist->Enter(enumb);
1411 }
1412 }
1413 //__________________________2D scatter plot_______________________
1414 else if (fAction == 12) {
1415 TH2 *h2 = (TH2*)fObject;
1416 if (h2->CanExtendAllAxes() && h2->TestBit(kCanDelete)) {
1417 for (i = 0; i < fNfill; i++) {
1418 if (fVmin[0] > fVal[0][i]) fVmin[0] = fVal[0][i];
1419 if (fVmax[0] < fVal[0][i]) fVmax[0] = fVal[0][i];
1420 if (fVmin[1] > fVal[1][i]) fVmin[1] = fVal[1][i];
1421 if (fVmax[1] < fVal[1][i]) fVmax[1] = fVal[1][i];
1422 }
1423 THLimitsFinder::GetLimitsFinder()->FindGoodLimitsXY(h2, fVmin[1], fVmax[1], fVmin[0], fVmax[0]);
1424 }
1425 TGraph *pm = new TGraph(fNfill, fVal[1], fVal[0]);
1426 pm->SetEditable(false);
1427 pm->SetBit(kCanDelete);
1428 pm->SetMarkerStyle(fTree->GetMarkerStyle());
1429 pm->SetMarkerColor(fTree->GetMarkerColor());
1430 pm->SetMarkerSize(fTree->GetMarkerSize());
1431 pm->SetLineColor(fTree->GetLineColor());
1432 pm->SetLineWidth(fTree->GetLineWidth());
1433 pm->SetLineStyle(fTree->GetLineStyle());
1434 pm->SetFillColor(fTree->GetFillColor());
1435 pm->SetFillStyle(fTree->GetFillStyle());
1436
1437 if (!fDraw && !strstr(fOption.Data(), "goff")) {
1438 if (fOption.Length() == 0 || strcasecmp(fOption.Data(), "same") == 0) pm->Draw("p");
1439 else pm->Draw(fOption.Data());
1440 }
1441 if (!h2->TestBit(kCanDelete)) {
1442 for (i = 0; i < fNfill; i++) h2->Fill(fVal[1][i], fVal[0][i], fW[i]);
1443 }
1444 }
1445 //__________________________3D scatter plot_______________________
1446 else if (fAction == 3) {
1447 TH3 *h3 = (TH3*)fObject;
1448 if (!h3->TestBit(kCanDelete)) {
1449 for (i = 0; i < fNfill; i++) h3->Fill(fVal[2][i], fVal[1][i], fVal[0][i], fW[i]);
1450 }
1451 } else if (fAction == 13) {
1453 pm3d->SetMarkerStyle(fTree->GetMarkerStyle());
1454 pm3d->SetMarkerColor(fTree->GetMarkerColor());
1455 pm3d->SetMarkerSize(fTree->GetMarkerSize());
1456 for (i = 0; i < fNfill; i++) {
1457 pm3d->SetPoint(i, fVal[2][i], fVal[1][i], fVal[0][i]);
1458 }
1459 pm3d->Draw();
1460 TH3 *h3 = (TH3*)fObject;
1461 if (!h3->TestBit(kCanDelete)) {
1462 for (i = 0; i < fNfill; i++) h3->Fill(fVal[2][i], fVal[1][i], fVal[0][i], fW[i]);
1463 }
1464 }
1465 //__________________________3D scatter plot (3rd variable = col)__
1466 else if (fAction == 33) {
1467 TH2 *h2 = (TH2*)fObject;
1468 TakeEstimate();
1470 TObjArray *grs = (TObjArray*)h2->GetListOfFunctions()->FindObject("graphs");
1471 Int_t col;
1472 TGraph *gr;
1473 if (!grs) {
1474 grs = new TObjArray(ncolors);
1475 grs->SetOwner();
1476 grs->SetName("graphs");
1477 h2->GetListOfFunctions()->Add(grs, "P");
1478 for (col = 0; col < ncolors; col++) {
1479 gr = new TGraph();
1483 grs->AddAt(gr, col);
1484 }
1485 }
1486 h2->SetEntries(fNfill);
1487 h2->SetMinimum(fVmin[2]);
1488 h2->SetMaximum(fVmax[2]);
1489 // Fill the graphs according to the color
1490 for (i = 0; i < fNfill; i++) {
1491 col = Int_t(ncolors * ((fVal[2][i] - fVmin[2]) / (fVmax[2] - fVmin[2])));
1492 if (col < 0) col = 0;
1493 if (col > ncolors - 1) col = ncolors - 1;
1494 gr = (TGraph*)grs->UncheckedAt(col);
1495 if (gr) gr->SetPoint(gr->GetN(), fVal[1][i], fVal[0][i]);
1496 }
1497 // Remove potential empty graphs
1498 for (col = 0; col < ncolors; col++) {
1499 gr = (TGraph*)grs->At(col);
1500 if (gr && gr->GetN() <= 0) grs->Remove(gr);
1501 }
1502 }
1503 //__________________________2D Profile Histogram__________________
1504 else if (fAction == 23) {
1506 for (i = 0; i < fNfill; i++) hp2->Fill(fVal[2][i], fVal[1][i], fVal[0][i], fW[i]);
1507 }
1508 //__________________________4D scatter plot_______________________
1509 else if (fAction == 40) {
1510 TakeEstimate();
1511 TH3 *h3 = (TH3*)fObject;
1513 if (ncolors == 0) {
1516 }
1517 TObjArray *pms = (TObjArray*)h3->GetListOfFunctions()->FindObject("polymarkers");
1518 Int_t col;
1520 if (!pms) {
1521 pms = new TObjArray(ncolors);
1522 pms->SetOwner();
1523 pms->SetName("polymarkers");
1524 h3->GetListOfFunctions()->Add(pms);
1525 for (col = 0; col < ncolors; col++) {
1526 pm3d = new TPolyMarker3D();
1527 pm3d->SetMarkerColor(gStyle->GetColorPalette(col));
1528 pm3d->SetMarkerStyle(fTree->GetMarkerStyle());
1529 pm3d->SetMarkerSize(fTree->GetMarkerSize());
1530 pms->AddAt(pm3d, col);
1531 }
1532 }
1533 h3->SetEntries(fNfill);
1534 h3->SetMinimum(fVmin[3]);
1535 h3->SetMaximum(fVmax[3]);
1536 for (i = 0; i < fNfill; i++) {
1537 col = Int_t(ncolors * ((fVal[3][i] - fVmin[3]) / (fVmax[3] - fVmin[3])));
1538 if (col > ncolors-1) col = ncolors-1;
1539 if (col < 0) col = 0;
1540 pm3d = (TPolyMarker3D*)pms->UncheckedAt(col);
1541 pm3d->SetPoint(pm3d->GetLastPoint() + 1, fVal[2][i], fVal[1][i], fVal[0][i]);
1542 }
1543 }
1544 //__________________________Parallel coordinates / candle chart_______________________
1545 else if (fAction == 6 || fAction == 7) {
1546 TakeEstimate();
1547 bool candle = (fAction == 7);
1548 // Using Interpreter to avoid a dependency in TParallelCoord
1549 if (!fOption.Contains("goff"))
1550 gROOT->ProcessLine(TString::Format("TParallelCoord::BuildParallelCoord((TSelectorDraw*)0x%zx,0x%zx)",
1551 (size_t)this, (size_t)candle));
1552 } else if (fAction == 8) {
1553 //gROOT->ProcessLineFast(TString::Format("(new TGL5DDataSet((TTree *)0x%1x))->Draw(\"%s\");", fTree, fOption.Data()));
1554 }
1555 //__________________________something else_______________________
1556 else if (fAction < 0) {
1557 fAction = -fAction;
1558 TakeEstimate();
1559 }
1560
1561 // Do we need to update screen?
1563 if (!fTree->GetUpdate()) return;
1564 if (fSelectedRows > fDraw + fTree->GetUpdate()) {
1565 if (fDraw) gPad->Modified();
1566 else fObject->Draw(fOption.Data());
1567 gPad->Update();
1569 }
1570}
1571
1572////////////////////////////////////////////////////////////////////////////////
1573/// Estimate limits for 1-D, 2-D or 3-D objects.
1574
1576{
1577 Int_t i;
1578 Double_t rmin[3], rmax[3];
1579 Double_t vminOld[4], vmaxOld[4];
1580 for (i = 0; i < fValSize && i < 4; i++) {
1581 vminOld[i] = fVmin[i];
1582 vmaxOld[i] = fVmax[i];
1583 }
1584 for (i = 0; i < fValSize; ++i) {
1585 fVmin[i] = DBL_MAX;
1586 fVmax[i] = - DBL_MAX;
1587 }
1588 //__________________________1-D histogram_______________________
1589 if (fAction == 1) {
1590 TH1 *h1 = (TH1*)fObject;
1591 if (h1->CanExtendAllAxes()) {
1592 for (i = 0; i < fNfill; i++) {
1593 if (fVmin[0] > fVal[0][i]) fVmin[0] = fVal[0][i];
1594 if (fVmax[0] < fVal[0][i]) fVmax[0] = fVal[0][i];
1595 }
1596 THLimitsFinder::GetLimitsFinder()->FindGoodLimits(h1, fVmin[0], fVmax[0]);
1597 }
1598 h1->FillN(fNfill, fVal[0], fW);
1599 //__________________________2-D histogram_______________________
1600 } else if (fAction == 2) {
1601 TH2 *h2 = (TH2*)fObject;
1602 if (h2->CanExtendAllAxes()) {
1603 for (i = 0; i < fNfill; i++) {
1604 if (fVmin[0] > fVal[0][i]) fVmin[0] = fVal[0][i];
1605 if (fVmax[0] < fVal[0][i]) fVmax[0] = fVal[0][i];
1606 if (fVmin[1] > fVal[1][i]) fVmin[1] = fVal[1][i];
1607 if (fVmax[1] < fVal[1][i]) fVmax[1] = fVal[1][i];
1608 }
1609 THLimitsFinder::GetLimitsFinder()->FindGoodLimitsXY(h2, fVmin[1], fVmax[1], fVmin[0], fVmax[0]);
1610 }
1611 for (i = 0; i < fNfill; i++) h2->Fill(fVal[1][i], fVal[0][i], fW[i]);
1612 //__________________________Profile histogram_______________________
1613 } else if (fAction == 4) {
1615 if (hp->CanExtendAllAxes()) {
1616 for (i = 0; i < fNfill; i++) {
1617 if (fVmin[0] > fVal[0][i]) fVmin[0] = fVal[0][i];
1618 if (fVmax[0] < fVal[0][i]) fVmax[0] = fVal[0][i];
1619 if (fVmin[1] > fVal[1][i]) fVmin[1] = fVal[1][i];
1620 if (fVmax[1] < fVal[1][i]) fVmax[1] = fVal[1][i];
1621 }
1622 THLimitsFinder::GetLimitsFinder()->FindGoodLimits(hp, fVmin[1], fVmax[1]);
1623 }
1624 hp->FillN(fNfill, fVal[1], fVal[0], fW);
1625 //__________________________2D scatter plot_______________________
1626 } else if (fAction == 12) {
1627 TH2 *h2 = (TH2*)fObject;
1628 if (h2->CanExtendAllAxes()) {
1629 for (i = 0; i < fNfill; i++) {
1630 if (fVmin[0] > fVal[0][i]) fVmin[0] = fVal[0][i];
1631 if (fVmax[0] < fVal[0][i]) fVmax[0] = fVal[0][i];
1632 if (fVmin[1] > fVal[1][i]) fVmin[1] = fVal[1][i];
1633 if (fVmax[1] < fVal[1][i]) fVmax[1] = fVal[1][i];
1634 }
1635 THLimitsFinder::GetLimitsFinder()->FindGoodLimitsXY(h2, fVmin[1], fVmax[1], fVmin[0], fVmax[0]);
1636 // In case the new lower limits of h2 axis are 0, it is better to set them to the minimum of
1637 // the data set (which should be >0) to avoid data cut when plotting in log scale.
1638 TAxis *aX = h2->GetXaxis();
1639 TAxis *aY = h2->GetYaxis();
1640 Double_t xmin = aX->GetXmin();
1641 Double_t ymin = aY->GetXmin();
1642 if (xmin == 0 || ymin == 0) {
1643 if (aX->GetBinUpEdge(aX->FindFixBin(0.01*aX->GetBinWidth(aX->GetFirst()))) > fVmin[1]) xmin = fVmin[1];
1644 if (aY->GetBinUpEdge(aY->FindFixBin(0.01*aY->GetBinWidth(aY->GetFirst()))) > fVmin[0]) ymin = fVmin[0];
1645 h2->SetBins(aX->GetNbins(), xmin, aX->GetXmax(), aY->GetNbins(), ymin, aY->GetXmax());
1646 }
1647 }
1648
1649 if (!strstr(fOption.Data(), "same") && !strstr(fOption.Data(), "goff")) {
1650 if (!h2->TestBit(kCanDelete)) {
1651 // case like: T.Draw("y:x>>myhist")
1652 // we must draw a copy before filling the histogram h2=myhist
1653 // because h2 will be filled below and we do not want to show
1654 // the binned scatter-plot, the TGraph being better.
1655 TH1 *h2c = h2->DrawCopy(fOption.Data(),"");
1656 if (h2c) h2c->SetStats(false);
1657 } else {
1658 // case like: T.Draw("y:x")
1659 // h2 is a temporary histogram (htemp). This histogram
1660 // will be automatically deleted by TPad::Clear
1661 h2->Draw();
1662 }
1663 gPad->Update();
1664 }
1665 TGraph *pm = new TGraph(fNfill, fVal[1], fVal[0]);
1666 pm->SetEditable(false);
1667 pm->SetBit(kCanDelete);
1668 pm->SetMarkerStyle(fTree->GetMarkerStyle());
1669 pm->SetMarkerColor(fTree->GetMarkerColor());
1670 pm->SetMarkerSize(fTree->GetMarkerSize());
1671 pm->SetLineColor(fTree->GetLineColor());
1672 pm->SetLineWidth(fTree->GetLineWidth());
1673 pm->SetLineStyle(fTree->GetLineStyle());
1674 pm->SetFillColor(fTree->GetFillColor());
1675 pm->SetFillStyle(fTree->GetFillStyle());
1676 if (!fDraw && !strstr(fOption.Data(),"goff")) {
1677 if (fOption.Length() == 0 || strcasecmp(fOption.Data(),"same")==0) {
1678 pm->Draw("p");
1679 }
1680 else {
1681 TString opt = fOption;
1682 opt.ToLower();
1683 if (opt.Contains("a")) {
1684 TString temp(opt);
1685 temp.ReplaceAll("same","");
1686 if (temp.Contains("a")) {
1687 if (h2->TestBit(kCanDelete)) {
1688 // h2 will be deleted, the axis setting is delegated to only
1689 // the TGraph.
1690 h2 = nullptr;
1691 fObject = pm->GetHistogram();
1692 }
1693 }
1694 }
1695 pm->Draw(fOption.Data());
1696 }
1697 }
1698 if (h2 && !h2->TestBit(kCanDelete)) {
1699 for (i = 0; i < fNfill; i++) h2->Fill(fVal[1][i], fVal[0][i], fW[i]);
1700 }
1701 //__________________________3D scatter plot with option col_______________________
1702 } else if (fAction == 33) {
1703 TH2 *h2 = (TH2*)fObject;
1704 bool process2 = false;
1705 if (h2->CanExtendAllAxes()) {
1706 if (vminOld[2] == DBL_MAX)
1707 process2 = true;
1708 for (i = 0; i < fValSize && i < 4; i++) {
1709 fVmin[i] = vminOld[i];
1710 fVmax[i] = vmaxOld[i];
1711 }
1712 for (i = 0; i < fNfill; i++) {
1713 if (fVmin[0] > fVal[0][i]) fVmin[0] = fVal[0][i];
1714 if (fVmax[0] < fVal[0][i]) fVmax[0] = fVal[0][i];
1715 if (fVmin[1] > fVal[1][i]) fVmin[1] = fVal[1][i];
1716 if (fVmax[1] < fVal[1][i]) fVmax[1] = fVal[1][i];
1717 if (process2) {
1718 if (fVmin[2] > fVal[2][i]) fVmin[2] = fVal[2][i];
1719 if (fVmax[2] < fVal[2][i]) fVmax[2] = fVal[2][i];
1720 }
1721 }
1722 THLimitsFinder::GetLimitsFinder()->FindGoodLimitsXY(h2, fVmin[1], fVmax[1], fVmin[0], fVmax[0]);
1723 // In case the new lower limits of h2 axis are 0, it is better to set them to the minimum of
1724 // the data set (which should be >0) to avoid data cut when plotting in log scale.
1725 TAxis *aX = h2->GetXaxis();
1726 TAxis *aY = h2->GetYaxis();
1727 Double_t xmin = aX->GetXmin();
1728 Double_t ymin = aY->GetXmin();
1729 if (xmin == 0 || ymin == 0) {
1730 if (aX->GetBinUpEdge(aX->FindFixBin(0.01*aX->GetBinWidth(aX->GetFirst()))) > fVmin[1]) xmin = fVmin[1];
1731 if (aY->GetBinUpEdge(aY->FindFixBin(0.01*aY->GetBinWidth(aY->GetFirst()))) > fVmin[0]) ymin = fVmin[0];
1732 h2->SetBins(aX->GetNbins(), xmin, aX->GetXmax(), aY->GetNbins(), ymin, aY->GetXmax());
1733 }
1734 } else {
1735 for (i = 0; i < fNfill; i++) {
1736 if (fVmin[2] > fVal[2][i]) fVmin[2] = fVal[2][i];
1737 if (fVmax[2] < fVal[2][i]) fVmax[2] = fVal[2][i];
1738 }
1739 }
1740 //__________________________3D scatter plot_______________________
1741 } else if (fAction == 3 || fAction == 13) {
1742 TH3 *h3 = (TH3*)fObject;
1743 if (h3->CanExtendAllAxes()) {
1744 for (i = 0; i < fNfill; i++) {
1745 if (fVmin[0] > fVal[0][i]) fVmin[0] = fVal[0][i];
1746 if (fVmax[0] < fVal[0][i]) fVmax[0] = fVal[0][i];
1747 if (fVmin[1] > fVal[1][i]) fVmin[1] = fVal[1][i];
1748 if (fVmax[1] < fVal[1][i]) fVmax[1] = fVal[1][i];
1749 if (fVmin[2] > fVal[2][i]) fVmin[2] = fVal[2][i];
1750 if (fVmax[2] < fVal[2][i]) fVmax[2] = fVal[2][i];
1751 }
1752 THLimitsFinder::GetLimitsFinder()->FindGoodLimitsXYZ(h3, fVmin[2], fVmax[2], fVmin[1], fVmax[1], fVmin[0],
1753 fVmax[0]);
1754 }
1755 if (fAction == 3) {
1756 for (i = 0; i < fNfill; i++) h3->Fill(fVal[2][i], fVal[1][i], fVal[0][i], fW[i]);
1757 return;
1758 }
1759 if (!strstr(fOption.Data(), "same") && !strstr(fOption.Data(), "goff")) {
1760 if (!h3->TestBit(kCanDelete)) {
1761 // case like: T.Draw("y:x>>myhist")
1762 // we must draw a copy before filling the histogram h3=myhist
1763 // because h3 will be filled below and we do not want to show
1764 // the binned scatter-plot, the TGraph being better.
1765 TH1 *h3c = h3->DrawCopy(fOption.Data(),"");
1766 if (h3c) h3c->SetStats(false);
1767 } else {
1768 // case like: T.Draw("y:x")
1769 // h3 is a temporary histogram (htemp). This histogram
1770 // will be automatically deleted by TPad::Clear
1771 h3->Draw(fOption.Data());
1772 }
1773 gPad->Update();
1774 } else {
1775 rmin[0] = fVmin[2]; rmin[1] = fVmin[1]; rmin[2] = fVmin[0];
1776 rmax[0] = fVmax[2]; rmax[1] = fVmax[1]; rmax[2] = fVmax[0];
1777 gPad->Clear();
1778 gPad->Range(-1, -1, 1, 1);
1780 }
1782 pm3d->SetMarkerStyle(fTree->GetMarkerStyle());
1783 pm3d->SetMarkerColor(fTree->GetMarkerColor());
1784 pm3d->SetMarkerSize(fTree->GetMarkerSize());
1785 for (i = 0; i < fNfill; i++) {
1786 pm3d->SetPoint(i, fVal[2][i], fVal[1][i], fVal[0][i]);
1787 }
1788 if (!fDraw && !strstr(fOption.Data(), "goff")) pm3d->Draw();
1789 if (!h3->TestBit(kCanDelete)) {
1790 for (i = 0; i < fNfill; i++) h3->Fill(fVal[2][i], fVal[1][i], fVal[0][i], fW[i]);
1791 }
1792
1793 //__________________________2D Profile Histogram__________________
1794 } else if (fAction == 23) {
1796 if (hp->CanExtendAllAxes()) {
1797 for (i = 0; i < fNfill; i++) {
1798 if (fVmin[0] > fVal[0][i]) fVmin[0] = fVal[0][i];
1799 if (fVmax[0] < fVal[0][i]) fVmax[0] = fVal[0][i];
1800 if (fVmin[1] > fVal[1][i]) fVmin[1] = fVal[1][i];
1801 if (fVmax[1] < fVal[1][i]) fVmax[1] = fVal[1][i];
1802 if (fVmin[2] > fVal[2][i]) fVmin[2] = fVal[2][i];
1803 if (fVmax[2] < fVal[2][i]) fVmax[2] = fVal[2][i];
1804 }
1805 THLimitsFinder::GetLimitsFinder()->FindGoodLimitsXY(hp, fVmin[2], fVmax[2], fVmin[1], fVmax[1]);
1806 }
1807 for (i = 0; i < fNfill; i++) hp->Fill(fVal[2][i], fVal[1][i], fVal[0][i], fW[i]);
1808 //__________________________4D scatter plot_______________________
1809 } else if (fAction == 40) {
1810 TH3 *h3 = (TH3*)fObject;
1811 if (h3->CanExtendAllAxes()) {
1812 for (i = 0; i < fValSize && i < 4; i++) {
1813 fVmin[i] = vminOld[i];
1814 fVmax[i] = vmaxOld[i];
1815 }
1816 for (i = 0; i < fNfill; i++) {
1817 if (fVmin[0] > fVal[0][i]) fVmin[0] = fVal[0][i];
1818 if (fVmax[0] < fVal[0][i]) fVmax[0] = fVal[0][i];
1819 if (fVmin[1] > fVal[1][i]) fVmin[1] = fVal[1][i];
1820 if (fVmax[1] < fVal[1][i]) fVmax[1] = fVal[1][i];
1821 if (fVmin[2] > fVal[2][i]) fVmin[2] = fVal[2][i];
1822 if (fVmax[2] < fVal[2][i]) fVmax[2] = fVal[2][i];
1823 if (fVmin[3] > fVal[3][i]) fVmin[3] = fVal[3][i];
1824 if (fVmax[3] < fVal[3][i]) fVmax[3] = fVal[3][i];
1825 }
1826 THLimitsFinder::GetLimitsFinder()->FindGoodLimitsXYZ(h3, fVmin[2], fVmax[2], fVmin[1], fVmax[1], fVmin[0],
1827 fVmax[0]);
1828 } else {
1829 for (i = 0; i < fNfill; i++) {
1830 if (fVmin[3] > fVal[3][i]) fVmin[3] = fVal[3][i];
1831 if (fVmax[3] < fVal[3][i]) fVmax[3] = fVal[3][i];
1832 }
1833 }
1834 }
1835 //__________________________Parallel coordinates plot / candle chart_______________________
1836 else if (fAction == 6 || fAction == 7) {
1837 for (i = 0; i < fDimension; ++i) {
1838 for (Long64_t entry = 0; entry < fNfill; entry++) {
1839 if (fVmin[i] > fVal[i][entry]) fVmin[i] = fVal[i][entry];
1840 if (fVmax[i] < fVal[i][entry]) fVmax[i] = fVal[i][entry];
1841 }
1842 }
1843 }
1844}
1845
1846////////////////////////////////////////////////////////////////////////////////
1847/// Called at the end of a loop on a TTree.
1848
1850{
1851 // We take action (in Process) when we reach GetEstimate but
1852 // we reset at the beginning of Process, so
1853 // if fNfill == GetEstimate(), we just took action.
1854 if (fNfill && fNfill < fTree->GetEstimate())
1855 TakeAction();
1856
1857 if ((fSelectedRows == 0) && (TestBit(kCustomHistogram) == 0)) fDraw = 1; // do not draw
1858
1860}
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:60
long long Long64_t
Portable signed long integer 8 bytes.
Definition RtypesCore.h:84
#define BIT(n)
Definition Rtypes.h:91
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
#define gDirectory
Definition TDirectory.h:385
R__EXTERN TEnv * gEnv
Definition TEnv.h:126
Option_t Option_t option
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t np
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
float xmin
float ymin
float xmax
float ymax
Int_t gDebug
Global variable setting the debug level. Set to 0 to disable, increase it in steps of 1 to increase t...
Definition TROOT.cxx:777
#define gROOT
Definition TROOT.h:417
const Int_t kCustomHistogram
R__EXTERN TStyle * gStyle
Definition TStyle.h:442
#define gPad
virtual Int_t GetNdim() const
Definition TFormula.h:238
virtual Color_t GetFillColor() const
Return the fill area color.
Definition TAttFill.h:32
virtual Style_t GetFillStyle() const
Return the fill area style.
Definition TAttFill.h:33
virtual void SetFillColor(Color_t fcolor)
Set the fill area color.
Definition TAttFill.h:40
virtual void SetFillStyle(Style_t fstyle)
Set the fill area style.
Definition TAttFill.h:42
virtual Color_t GetLineColor() const
Return the line color.
Definition TAttLine.h:36
virtual void SetLineStyle(Style_t lstyle)
Set the line style.
Definition TAttLine.h:46
virtual Width_t GetLineWidth() const
Return the line width.
Definition TAttLine.h:38
virtual void SetLineWidth(Width_t lwidth)
Set the line width.
Definition TAttLine.h:47
virtual void SetLineColor(Color_t lcolor)
Set the line color.
Definition TAttLine.h:44
virtual Style_t GetLineStyle() const
Return the line style.
Definition TAttLine.h:37
virtual Style_t GetMarkerStyle() const
Return the marker style.
Definition TAttMarker.h:34
virtual void SetMarkerColor(Color_t mcolor=1)
Set the marker color.
Definition TAttMarker.h:41
virtual Color_t GetMarkerColor() const
Return the marker color.
Definition TAttMarker.h:33
virtual Size_t GetMarkerSize() const
Return the marker size.
Definition TAttMarker.h:35
virtual void SetMarkerStyle(Style_t mstyle=1)
Set the marker style.
Definition TAttMarker.h:43
virtual void SetMarkerSize(Size_t msize=1)
Set the marker size.
Definition TAttMarker.h:48
Class to manage histogram axis.
Definition TAxis.h:32
Int_t GetNbins() const
Definition TAxis.h:127
Container of bits.
Definition TBits.h:26
UInt_t GetNbits() const
Definition TBits.h:134
UInt_t FirstSetBit(UInt_t startBit=0) const
Return position of first non null bit (starting from position 0 and up)
Definition TBits.cxx:358
static TClass * Class()
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:84
static void InitializeColors()
Initialize colors used by the TCanvas based graphics (via TColor objects).
Definition TColor.cxx:1172
A specialized string object used for TTree selections.
Definition TCut.h:25
A list of entries and subentries in a TTree or TChain.
virtual TEntryListArray * GetSubListForEntry(Long64_t entry, TTree *tree=nullptr)
Return the list holding the subentries for the given entry or 0.
static TClass * Class()
A List of entry numbers in a TTree or TChain.
Definition TEntryList.h:26
static TClass * Class()
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition TEnv.cxx:511
virtual void SetValue(const char *name, const char *value, EEnvLevel level=kEnvChange, const char *type=nullptr)
Set the value of a resource or create a new resource.
Definition TEnv.cxx:752
<div class="legacybox"><h2>Legacy Code</h2> TEventList is a legacy interface: there will be no bug fi...
Definition TEventList.h:31
A TGraph is an object made of two arrays X and Y with npoints each.
Definition TGraph.h:41
virtual void SetPoint(Int_t i, Double_t x, Double_t y)
Set x and y values for point number i.
Definition TGraph.cxx:2389
Int_t GetN() const
Definition TGraph.h:131
1-D histogram with a double per channel (see TH1 documentation)
Definition TH1.h:926
1-D histogram with a float per channel (see TH1 documentation)
Definition TH1.h:878
TH1 is the base class of all histogram classes in ROOT.
Definition TH1.h:109
virtual void SetDirectory(TDirectory *dir)
By default, when a histogram is created, it is added to the list of histogram objects in the current ...
Definition TH1.cxx:9170
TAxis * GetZaxis()
Definition TH1.h:573
static TClass * Class()
virtual Int_t GetDimension() const
Definition TH1.h:527
@ kNoStats
Don't draw stats box.
Definition TH1.h:403
virtual Bool_t CanExtendAllAxes() const
Returns true if all axes are extendable.
Definition TH1.cxx:6847
virtual void Reset(Option_t *option="")
Reset this histogram: contents, errors, etc.
Definition TH1.cxx:7324
TAxis * GetXaxis()
Definition TH1.h:571
virtual void SetMaximum(Double_t maximum=-1111)
Definition TH1.h:652
TAxis * GetYaxis()
Definition TH1.h:572
void Draw(Option_t *option="") override
Draw this histogram with options.
Definition TH1.cxx:3193
virtual void SetMinimum(Double_t minimum=-1111)
Definition TH1.h:653
@ kAllAxes
Definition TH1.h:126
virtual UInt_t SetCanExtend(UInt_t extendBitMask)
Make the histogram axes extendable / not extendable according to the bit mask returns the previous bi...
Definition TH1.cxx:6860
TList * GetListOfFunctions() const
Definition TH1.h:488
virtual TH1 * DrawCopy(Option_t *option="", const char *name_postfix="_copy") const
Copy this histogram and Draw in the current pad.
Definition TH1.cxx:3258
virtual void FillN(Int_t ntimes, const Double_t *x, const Double_t *w, Int_t stride=1)
Fill this histogram with an array x and weights w.
Definition TH1.cxx:3592
virtual void SetBins(Int_t nx, Double_t xmin, Double_t xmax)
Redefine x axis parameters.
Definition TH1.cxx:9000
virtual void Sumw2(Bool_t flag=kTRUE)
Create structure to store sum of squares of weights.
Definition TH1.cxx:9253
virtual void SetEntries(Double_t n)
Definition TH1.h:639
2-D histogram with a double per channel (see TH1 documentation)
Definition TH2.h:400
2-D histogram with a float per channel (see TH1 documentation)
Definition TH2.h:345
Service class for 2-D histogram classes.
Definition TH2.h:30
Int_t Fill(Double_t) override
Invalid Fill method.
Definition TH2.cxx:364
3-D histogram with a double per channel (see TH1 documentation)
Definition TH3.h:424
3-D histogram with a float per channel (see TH1 documentation)
Definition TH3.h:369
The 3-D histogram classes derived from the 1-D histogram classes.
Definition TH3.h:45
static THLimitsFinder * GetLimitsFinder()
Return pointer to the current finder.
Iterator of linked list.
Definition TList.h:196
TObject * FindObject(const char *name) const override
Find an object in this list using its name.
Definition TList.cxx:708
void Add(TObject *obj) override
Definition TList.h:81
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition TNamed.cxx:173
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
An array of TObjects.
Definition TObjArray.h:31
Mother of all ROOT objects.
Definition TObject.h:42
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:204
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1082
virtual void Delete(Option_t *option="")
Delete this object.
Definition TObject.cxx:267
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:886
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:548
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1096
virtual const char * GetTitle() const
Returns title of object.
Definition TObject.cxx:506
virtual void Draw(Option_t *option="")
Default Draw method for all objects.
Definition TObject.cxx:292
void ResetBit(UInt_t f)
Definition TObject.h:203
@ kCanDelete
if object in a list can be deleted
Definition TObject.h:71
A 3D polymarker.
Profile2D histograms are used to display the mean value of Z and its error for each cell in X,...
Definition TProfile2D.h:27
static TClass * Class()
Profile Histogram.
Definition TProfile.h:32
static TClass * Class()
void ProcessFill(Long64_t entry) override
Called in the entry loop for all entries accepted by Select.
TEntryListArray * fTreeElistArray
! Pointer to Tree Event list array
virtual void SetEstimate(Long64_t n)
Set number of entries to estimate variable limits.
virtual void InitArrays(Int_t newsize)
Initialization of the primitive type arrays if the new size is bigger than the available space.
void Terminate() override
Called at the end of a loop on a TTree.
Int_t fAction
! Action type
Int_t GetMultiplicity() const
TTreeFormulaManager * fManager
Pointer to the formula manager.
TTreeFormula * GetVar(Int_t i) const
Return the TTreeFormula corresponding to the i-th component of the request formula (where the compone...
bool * fVarMultiple
![fDimension] True if fVar[i] has a variable index
~TSelectorDraw() override
Selector destructor.
TSelectorDraw()
Default selector constructor.
Double_t * fW
![fSelectedRows]Local buffer for weights
virtual UInt_t SplitNames(const TString &varexp, std::vector< TString > &names)
Build Index array for names in varexp.
Long64_t fCurrentSubEntry
Current subentry when fSelectMultiple is true. Used to fill TEntryListArray.
TTreeFormula * fSelect
Pointer to selection formula.
Long64_t fSelectedRows
Number of selected entries.
Int_t fForceRead
Force Read flag.
virtual void ClearFormula()
Delete internal buffers.
virtual void TakeAction()
Execute action for object obj fNfill times.
Long64_t fOldEstimate
Value of Tree fEstimate when selector is called.
Double_t fWeight
Tree weight (see TTree::SetWeight)
Int_t fNfill
! Total number of histogram fills
TH1 * fOldHistogram
! Pointer to previously used histogram
virtual bool CompileVariables(const char *varexp="", const char *selection="")
Compile input variables and selection expression.
Double_t * fVmax
![fDimension] Maxima of varexp columns
Int_t fMultiplicity
Indicator of the variability of the size of entries.
TTreeFormula ** fVar
![fDimension] Array of pointers to variables formula
virtual void ProcessFillMultiple(Long64_t entry)
Called in the entry loop for all entries accepted by Select.
bool fSelectMultiple
True if selection has a variable index.
TTree * fTree
Pointer to current Tree.
Int_t fDimension
Dimension of the current expression.
TObject * fTreeElist
Pointer to Tree Event list.
virtual Double_t * GetVal(Int_t i) const
Return the last values corresponding to the i-th component of the formula being processed (where the ...
Int_t * fNbins
![fDimension] Number of bins per dimension
Double_t ** fVal
![fSelectedRows][fDimension] Local buffer for the variables
Long64_t fDraw
! Last entry loop number when object was drawn
virtual void TakeEstimate()
Estimate limits for 1-D, 2-D or 3-D objects.
bool Notify() override
This function is called at the first entry of a new tree in a chain.
bool fCleanElist
True if original Tree elist must be saved.
bool fObjEval
True if fVar1 returns an object (or pointer to).
void Begin(TTree *tree) override
Called every time a loop on the tree(s) starts.
virtual void ProcessFillObject(Long64_t entry)
Called in the entry loop for all entries accepted by Select.
Double_t * fVmin
![fDimension] Minima of varexp columns
virtual void SetStatus(Long64_t status)
Definition TSelector.h:67
TList * fInput
List of objects available during processing.
Definition TSelector.h:41
TString fOption
Option given to TTree::Process.
Definition TSelector.h:39
virtual void Abort(const char *why, EAbort what=kAbortProcess)
Abort processing.
const char * GetOption() const override
Definition TSelector.h:57
TObject * fObject
! Current object if processing object (vs. TTree)
Definition TSelector.h:40
virtual void ResetAbort()
Definition TSelector.h:74
Basic string class.
Definition TString.h:138
Ssiz_t Length() const
Definition TString.h:427
void ToLower()
Change string to lower-case.
Definition TString.cxx:1189
const char * Data() const
Definition TString.h:386
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition TString.h:715
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2459
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:643
Int_t GetColorPalette(Int_t i) const
Return color number i in current palette.
Definition TStyle.cxx:1102
Int_t GetNumberOfColors() const
Return number of colors in the color palette.
Definition TStyle.cxx:1176
Used to coordinate one or more TTreeFormula objects.
virtual Int_t GetNdata(bool forceLoadDim=false)
Return number of available instances in the formulas.
virtual void Add(TTreeFormula *)
Add a new formula to the list of formulas managed The manager of the formula will be changed and the ...
virtual bool Sync()
Synchronize all the formulae.
virtual Int_t GetMultiplicity() const
Used to pass a selection expression to the Tree drawing routine.
virtual void ResetLoading()
Tell the formula that we are going to request a new entry.
TTreeFormulaManager * GetManager() const
virtual Int_t GetMultiplicity() const
T EvalInstance(Int_t i=0, const char *stringStack[]=nullptr)
Evaluate this treeformula.
void SetQuickLoad(bool quick)
virtual void UpdateFormulaLeaves()
This function is called TTreePlayer::UpdateFormulaLeaves, itself called by TChain::LoadTree when a ne...
virtual void * EvalObject(Int_t i=0)
Evaluate this treeformula.
virtual void SetAxis(TAxis *axis=nullptr)
Set the axis (in particular get the type).
virtual TClass * EvalClass(Int_t oper) const
Evaluate the class of the operation oper.
A TTree represents a columnar dataset.
Definition TTree.h:89
virtual Long64_t GetEstimate() const
Definition TTree.h:554
virtual Double_t GetWeight() const
Definition TTree.h:631
virtual TEntryList * GetEntryList()
Returns the entry list assigned to this tree.
Definition TTree.cxx:5934
virtual void SetEstimate(Long64_t nentries=1000000)
Set number of entries to estimate variable limits.
Definition TTree.cxx:9364
virtual TTree * GetTree() const
Definition TTree.h:604
virtual void SetEntryList(TEntryList *list, Option_t *opt="")
Set an EntryList.
Definition TTree.cxx:9300
TEventList * GetEventList() const
Definition TTree.h:560
@ kForceRead
Definition TTree.h:295
virtual Int_t GetUpdate() const
Definition TTree.h:608
virtual Long64_t GetChainOffset() const
Definition TTree.h:503
See TView3D.
Definition TView.h:25
virtual Double_t * GetRmax()=0
virtual Double_t * GetRmin()=0
static TView * CreateView(Int_t system=1, const Double_t *rmin=nullptr, const Double_t *rmax=nullptr)
Create a concrete default 3-d view via the plug-in manager.
Definition TView.cxx:26
TGraphErrors * gr
Definition legend1.C:25
TH1F * h1
Definition legend1.C:5
TLine l
Definition textangle.C:4