Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TUnfoldBinning.cxx
Go to the documentation of this file.
1// Author: Stefan Schmitt
2// DESY, 10/08/11
3
4// Version 17.9, parallel to changes in TUnfold
5//
6// History:
7// Version 17.8, bug fix in GetNonemptyNode() and non-const access of tree
8// Version 17.7, bug fix in ExtractHistogram
9// Version 17.6, bug fix to avoid possible crash in method
10// CreateHistogramOfMigrations(). Bug fix with NaN in GetGlobalBinNumber()
11// Version 17.5, in parallel to changes in TUnfold
12// Version 17.4, bug fix with error handling
13// Version 17.3, bug fix with underflow/overflow bins
14// Version 17.2, with XML support, bug fix with bin map creation,
15// isPeriodic option for neighbour bins
16// Version 17.1, in parallel to changes in TUnfold
17// Version 17.0, initial version, numbered in parallel to TUnfold
18
19/** \class TUnfoldBinning
20Binning schemes for use with the unfolding algorithm TUnfoldDensity.
21
22Binning schemes are used to map analysis bins on a single histogram
23axis and back. The analysis bins may include unconnected bins (e.g
24nuisances for background normalisation) or various multidimensional
25histograms (signal bins, differential background normalisation bins, etc).
26<br/>
27If you use this software, please consider the following citation
28<br/>
29<b>S.Schmitt, JINST 7 (2012) T10003 [arXiv:1205.6201]</b>
30<br/>
31Detailed documentation and updates are available on
32http://www.desy.de/~sschmitt
33
34<h3>Functionality</h3>
35
36The TUnfoldBinning objects are connected by a tree-like structure.
37The structure does not hold any data, but is only responsible for
38arranging the analysis bins in the proper order.
39Each node of the tree is responsible for a group of bins. That group
40may consist of
41<ul>
42<li> several unconnected bins, each with a dedicated name.</li>
43<li> bins organized in a multidimensional distribution, defined by a
44set of axes. The axes are defined by a number of bins N and by (N+1)
45bin borders. In addition to the N bins inside there may be an underflow and an
46overflow bin</li>
47</ul>
48Each bin has a "global" bin number, which can be found using the
49GetGlobalBinNumber() methods. The global bin number 0 is reserved and
50corresponds to the case where no bin is found in the
51TUnfoldBinning tree.
52
53<h3>Use in the analysis</h3>
54Booking histograms:
55<ul>
56<li>Define binning schemes on detector level and on truth level. This
57can be done using the XML language, use the class TUnfoldBinningXML to
58read the binning scheme. The TUnfoldBinning objects can be written to
59a root file, preferentially together with the corresponding histograms.</li>
60<li>For Monte Carlo, book histograms for the response matrix (detector
61vs truth level) using the
62method CreateHistogramOfMigrations()</li>
63<li>For data and background, book histograms using the
64"detector level" binning scheme and the method CreateHistogram()</li>
65<li>(if required) for the data covarianve matrix, book a histogram using the
66"detector level" binning scheme and the method CreateErrorMatrixHistogram()</li>
67<li>For truth histograms, book histograms using the
68"truth level" binning scheme and the method CreateHistogram()</li>
69</ul>
70The histograms which are booked have all analysis bins arranged on one
71axis (global bin number). TUnfoldBinning provides methods to locate
72the global bin number:
73<ul>
74<li>Use the method FindNode() to locate a group of bins (e.g. signal,
75control distribution, etc) by their name, then:</li>
76<li>Use the method GetGlobalBinNumber() to locate a bin in a
77distribution, then:</li>
78<li>Use the TH1::Fill() method and the bin number to fill the
79appropriate bin in one of the histograms booked above.</li>
80</ul>
81Unfolding: Specify the response matrix and the binning schemes when
82constructing a TUnfoldDensity object. Tell TUnfoldDensity about the
83data, bakcground, systematic error histograms using the corresponding
84methods of class TUnfoldDensity. Then run the unfolding. Use the
85GetXXX() methods to retreive the unfolding results into properly
86binned multidimensional histograms.
87*/
88
89/*
90 This file is part of TUnfold.
91
92 TUnfold is free software: you can redistribute it and/or modify
93 it under the terms of the GNU General Public License as published by
94 the Free Software Foundation, either version 3 of the License, or
95 (at your option) any later version.
96
97 TUnfold is distributed in the hope that it will be useful,
98 but WITHOUT ANY WARRANTY; without even the implied warranty of
99 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
100 GNU General Public License for more details.
101
102 You should have received a copy of the GNU General Public License
103 along with TUnfold. If not, see <http://www.gnu.org/licenses/>.
104*/
105
106
107#include "TUnfoldBinningXML.h"
108#include <TVectorD.h>
109#include <TAxis.h>
110#include <TString.h>
111#include <TMath.h>
112#include <TF1.h>
113#include <TH1D.h>
114#include <TH2D.h>
115#include <TH3D.h>
116#include <TIterator.h>
117#include <iomanip>
118
119// #define DEBUG
120
121using std::ostream;
122
123
124////////////////////////////////////////////////////////////////////////
126{
127 // delete all children
128 while(childNode) delete childNode;
129 // remove this node from the tree
130 if(GetParentNode() && (GetParentNode()->GetChildNode()==this)) {
132 }
135 delete fAxisList;
136 delete fAxisLabelList;
138 if(!dynamic_cast<TF1 *>(fBinFactorFunction))
139 delete fBinFactorFunction;
140 }
141}
142
143/********************* setup **************************/
144
145////////////////////////////////////////////////////////////////////////
146/// initialize variables for a given number of bins
148{
149 parentNode=nullptr;
150 childNode=nullptr;
151 nextNode=nullptr;
152 prevNode=nullptr;
153 fAxisList=new TObjArray();
158 fHasOverflow=0;
159 fDistributionSize=nBins;
160 fBinFactorFunction=nullptr;
162}
163
164////////////////////////////////////////////////////////////////////////
165/// update fFirstBin and fLastBin members of this node and its children
166///
167/// \param[in] startWithRootNode if true, start the update with the root node
169{
172 }
173 if(GetPrevNode()) {
174 // if this is not the first node in a sequence,
175 // start with the end bin of the previous node
177 } else if(GetParentNode()) {
178 // if this is the first node in a sequence but has a parent,
179 // start with the end bin of the parent's distribution
182 } else {
183 // if this is the top level node, the first bin number is 1
184 fFirstBin=1;
185 // ... unless the top level node is the only node
186 // ... with dimension=1
187 // ... and there are no child nodes
188 // ... and there is an underflow bin
189 if((!GetChildNode())&&(GetDistributionDimension()==1)&&
190 (fHasUnderflow==1)) {
191 fFirstBin=0;
192 }
193 }
195 // now update count for all children
196 for(TUnfoldBinning *node=childNode;node;node=node->nextNode) {
197 fLastBin=node->UpdateFirstLastBin(kFALSE);
198 }
199 return fLastBin;
200}
201
202////////////////////////////////////////////////////////////////////////
203/// create a new node without axis
204///
205/// \param[in] name identifier of the node
206/// \param[in] nBin number of unconnected bins (could be zero)
207/// \param[in] binNames (optional) names of the bins separated by ';'
209(const char *name,Int_t nBins,const char *binNames)
210 : TNamed(name ? name : "",name ? name : "")
211{
212 Initialize(nBins);
213 if(binNames) {
215 delete fAxisLabelList;
216 fAxisLabelList=nameString.Tokenize(";");
217 }
219}
220
221////////////////////////////////////////////////////////////////////////
222/// create a new node containing a distribution with one axis
223///
224/// \param[in] axis the axis to represent
225/// \param[in] includeUnderflow true if underflow bin should be included
226/// \param[in] includeOverflow true if overflow bin should be included
229 : TNamed(axis.GetName(),axis.GetTitle())
230{
231 Initialize(0);
234}
235
236////////////////////////////////////////////////////////////////////////
237/// add a new binning node as last last child of this node
238///
239/// \param[in] name name of the node
240/// \param[in] nBin number of extra bins
241/// \param[in] binNames (optional) names of the bins sepatared by ';'
242///
243/// this is a shortcut for AddBinning(new TUnfoldBinning(name,nBins,binNames))
245(const char *name,Int_t nBins,const char *binNames)
246{
247 return AddBinning(new TUnfoldBinning(name,nBins,binNames));
248}
249
250////////////////////////////////////////////////////////////////////////
251/// add a TUnfoldBinning as the last child of this node
252///
253/// \param[in] binning the new binning to be added
254///
255/// return value: if succeeded, return "binning"
256/// otherwise return 0
258{
259 TUnfoldBinning *r=nullptr;
260 if(binning->GetParentNode()) {
261 Error("AddBinning",
262 "binning \"%s\" already has parent \"%s\", can not be added to %s",
263 (char *)binning->GetName(),
264 (char *)binning->GetParentNode()->GetName(),
265 (char *)GetName());
266 } else if(binning->GetPrevNode()) {
267 Error("AddBinning",
268 "binning \"%s\" has previous node \"%s\", can not be added to %s",
269 (char *)binning->GetName(),
270 (char *)binning->GetPrevNode()->GetName(),
271 (char *)GetName());
272 } else if(binning->GetNextNode()) {
273 Error("AddBinning",
274 "binning \"%s\" has next node \"%s\", can not be added to %s",
275 (char *)binning->GetName(),
276 (char *)binning->GetNextNode()->GetName(),
277 (char *)GetName());
278 } else {
279 r=binning;
280 binning->parentNode=this;
281 if(childNode) {
283 // find last child
284 while(child->nextNode) {
285 child=child->nextNode;
286 }
287 // add as last child
288 child->nextNode=r;
289 r->prevNode=child;
290 } else {
291 childNode=r;
292 }
294 r=binning;
295 }
296 return r;
297}
298
299////////////////////////////////////////////////////////////////////////
300/// add an axis with equidistant bins
301///
302/// \param[in] name name of the axis
303/// \param[in] nBin number of bins
304/// \param[in] xMin lower edge of the first bin
305/// \param[in] xMax upper edge of the last bin
306/// \param[in] hasUnderflow decide whether the axis has an underflow bin
307/// \param[in] hasOverflow decide whether the axis has an overflow bin
308///
309/// returns true if the axis has been added
313{
315 if(nBin<=0) {
316 Fatal("AddAxis","number of bins %d is not positive",
317 nBin);
318 } else if((!TMath::Finite(xMin))||(!TMath::Finite(xMax))||
319 (xMin>=xMax)) {
320 Fatal("AddAxis","xmin=%f required to be smaller than xmax=%f",
321 xMin,xMax);
322 } else {
326 for(Int_t i=0;i<=nBin;i++) {
327 binBorders[i]=x+i*dx;
328 }
330 delete [] binBorders;
331 }
332 return r;
333}
334
335////////////////////////////////////////////////////////////////////////
336/// add an axis to the distribution, using the TAxis as blueprint
337///
338/// \param[in] axis blueprint of the axis
339/// \param[in] hasUnderflow decide whether the underflow bin should be included
340/// \param[in] hasOverflow decide whether the overflow bin should be included
341///
342/// returns true if the axis has been added
343/// </br/>
344/// Note: axis labels are not imported
347{
348 Int_t nBin=axis.GetNbins();
350 for(Int_t i=0;i<nBin;i++) {
351 binBorders[i]=axis.GetBinLowEdge(i+1);
352 }
355 delete [] binBorders;
356 return r;
357}
358
359////////////////////////////////////////////////////////////////////////
360/// add an axis with the specified bin borders
361///
362/// \param[in] name name of the axis
363/// \param[in] nBin number of bins
364/// \param[in] binBorders array of bin borders, with nBin+1 elements
365/// \param[in] hasUnderflow decide whether the axis has an underflow bin
366/// \param[in] hasOverflow decide whether the axis has an overflow bin
367///
368/// returns true if the axis has been added
369
371(const char *name,Int_t nBin,const Double_t *binBorders,
373{
375 if(HasUnconnectedBins()) {
376 Fatal("AddAxis","node already has %d bins without axis",
378 } else if(nBin<=0) {
379 Fatal("AddAxis","number of bins %d is not positive",
380 nBin);
381 } else {
382 TVectorD *bins=new TVectorD(nBin+1);
383 r=kTRUE;
384 for(Int_t i=0;i<=nBin;i++) {
385 (*bins)(i)=binBorders[i];
386 if(!TMath::Finite((*bins)(i))) {
387 Fatal("AddAxis","bin border %d is not finite",i);
388 r=kFALSE;
389 } else if((i>0)&&((*bins)(i)<=(*bins)(i-1))) {
390 Fatal("AddAxis","bins not in order x[%d]=%f <= %f=x[%d]",
391 i,(*bins)(i),(*bins)(i-1),i-1);
392 r=kFALSE;
393 }
394 }
395 if(r) {
397 Int_t bitMask=1<<axis;
399 if(hasUnderflow) {
401 nBinUO++;
402 } else {
404 }
405 if(hasOverflow) {
407 nBinUO++;
408 } else {
410 }
411 fAxisList->AddLast(bins);
416 }
417 }
418 return r;
419}
420
421////////////////////////////////////////////////////////////////////////
422/// print some information about this binning tree
423///
424/// \param[out] out stream to write to
425/// \param[in] indent initial indentation (sub-trees have indent+1)
426/// \param[in] debug if debug&gt;0 print more information
427
429 const {
430 for(Int_t i=0;i<indent;i++) out<<" ";
431 out<<"TUnfoldBinning \""<<GetName()<<"\" has ";
433 if(nBin==1) {
434 out<<"1 bin";
435 } else {
436 out<<nBin<<" bins";
437 }
438 out<<" ["
439 <<GetStartBin()<<","<<GetEndBin()<<"] nTH1x="
441 <<"\n";
443 for(Int_t i=0;i<indent;i++) out<<" ";
444 out<<" distribution: "<<GetDistributionNumberOfBins()<<" bins\n";
446 /* for(Int_t i=nullptr;i<indent;i++) out<<" ";
447 out<<" axes:\n"; */
448 for(Int_t axis=0;axis<GetDistributionDimension();axis++) {
449 for(Int_t i=0;i<indent;i++) out<<" ";
450 out<<" \""
452 <<"\" nbin="<<GetDistributionBinning(axis)->GetNrows()-1;
453 if(HasUnderflow(axis)) out<<" plus underflow";
454 if(HasOverflow(axis)) out<<" plus overflow";
455 out<<"\n";
456 }
457 } else {
458 for(Int_t i=0;i<indent;i++) out<<" ";
459 out<<" no axis\n";
460 for(Int_t i=0;i<indent;i++) out<<" ";
461 out<<" names: ";
463 (ibin<fAxisLabelList->GetEntriesFast());ibin++) {
464 if(ibin) out<<";";
467 }
468 }
469 out<<"\n";
470 }
471 if(debug>0) {
472 // print all bins with full name, size, status, user factor
473 for(int iBin=GetStartBin();iBin<GetEndBin();iBin++) {
474 for(Int_t i=0;i<indent;i++) out<<" ";
475 out<<GetBinName(iBin)
476 <<" size="<<GetBinSize(iBin)
477 <<" factor="<<GetBinFactor(iBin);
478 out<<"\n";
479 }
480 }
481 }
483 if(child) {
484 while(child) {
485 child->PrintStream(out,indent+1,debug);
486 child=child->GetNextNode();
487 }
488 }
489}
490
491////////////////////////////////////////////////////////////////////////
492/// set normalisation factors which are used in calls to GetBinFactor()
493///
494/// \param[in] normalisation normalisation factor
495/// \param[in] binfactor object which defines a factor for each bin
496///
497/// IN the presnet implementation, <b>binfactor</b> can be a TF1 or a
498/// TVectorD. The TF1 is evaluated a the bin centes of the
499/// relevant axes. The TVectorD is indexed by the global bin number
500/// minus the start bin number of this node.
510
511////////////////////////////////////////////////////////////////////////
512/// set normalisation factor and function which are used in calls to GetBinFactor()
513///
514/// \param[in] normalisation normalisation factor
515/// \param[in] userFunc function evaluated at the (multi-dimensional)
516/// bin centres
521
522/********************* Navigation **********************/
523
524////////////////////////////////////////////////////////////////////////
525/// traverse the tree and return the first node which matches the given name
526///
527/// \param[in] name the identifier of the node to find (zero matches
528/// the first node)
529///
530/// returns the node found or zero
532{
533 TUnfoldBinning const *r=nullptr;
534 if((!name)||(!TString(GetName()).CompareTo(name))) {
535 r=this;
536 }
537 for(TUnfoldBinning const *child=GetChildNode();
538 (!r) && child;child=child->GetNextNode()) {
539 r=child->FindNode(name);
540 }
541 return r;
542}
543
544////////////////////////////////////////////////////////////////////////
546{
547 // return root node
548 TUnfoldBinning *node=this;
549 while(node->GetParentNode()) node=node->parentNode;
550 return node;
551}
552
553////////////////////////////////////////////////////////////////////////
555{
556 // return root node
557 TUnfoldBinning const *node=this;
558 while(node->GetParentNode()) node=node->GetParentNode();
559 return node;
560}
561
562/********************* Create THxx histograms **********/
563
564////////////////////////////////////////////////////////////////////////
565/// construct a title
566///
567/// \param[in] histogramName distribution name
568/// \param[in] histogramTitle default title
569/// \param[in] axisList array indicating wqhich axis of this node is
570/// mapped to which histogram axis
571///
572/// if histogramTitle!=nullptr thsi title is used. Otherwise, the title is
573/// composed as:
574/// histogramName;axisname[axisList[0]];axisname[axisList[1]];...
576(const char *histogramName,const char *histogramTitle,Int_t const *axisList)
577 const
578{
579 TString r;
580 if(histogramTitle) {
582 } else {
584 Int_t iEnd;
585 for(iEnd=2;iEnd>0;iEnd--) {
586 if(axisList[iEnd]>=0) break;
587 }
588 for(Int_t i=0;i<=iEnd;i++) {
589 r += ";";
590 if(axisList[i]<0) {
591 r += GetName();
592 } else {
593 r += GetNonemptyNode()->GetDistributionAxisLabel(axisList[i]);
594 }
595 }
596 }
597 return r;
598}
599
600////////////////////////////////////////////////////////////////////////
601/// construct a histogram title for a 2D histogram with different
602/// binning schemes on x and y axis
603///
604/// \param[in] histogramName distribution name
605/// \param[in] histogramTitle default title
606/// \param[in] xAxis indicates which x-axis name to use
607/// \param[in] yAxisBinning binning scheme for y-axis
608/// \param[in] yAxis indicates which y-axis name to use
609///
611(const char *histogramName,const char *histogramTitle,
613{
614 // build a title
615 // input:
616 // histogramTitle : if this is non-zero, use that title
617 // otherwise:
618 // title=histogramName;x;y
619 // xAxis : -1 no title for this axis
620 // >=nullptr use name of the corresponding axis
621 TString r;
622 if(histogramTitle) {
624 } else {
626 r += ";";
627 if(xAxis==-1) {
628 r += GetName();
629 } else if(xAxis>=0) {
630 r += GetNonemptyNode()->GetDistributionAxisLabel(xAxis);
631 }
632 r+= ";";
633 if(yAxis==-1) {
634 r += yAxisBinning->GetName();
635 } else if(yAxis>=0) {
636 r += yAxisBinning->GetNonemptyNode()->GetDistributionAxisLabel(yAxis);
637 }
638
639 }
640 return r;
641}
642
643////////////////////////////////////////////////////////////////////////
644/// return the number of histogram bins required when storing
645/// this binning in a one-dimensional histogram
646///
647/// \param[in] originalAxisBinning if true, try to have the histogram
648/// axis reflect precisely the relevant axis of the binnnig scheme
649/// \param[in] axisSteering steering to integrate over axis and/or
650/// skip underflow and overflow bins
651///
652/// returns the number of bins of the TH1, where the underflow/overflow
653/// are not used, unless the distribution has only one axis and
654/// originalAxisBinning=true)
655/// <br/>
656/// axisSteering is a string as follows:
657/// "axis[options];axis[options];..."
658/// where: axis = name or * is an identifier of an axis (* matches all)
659/// and: options is any combination of the letters C,U,O (other
660/// letters are ignored).
661/// <br>
662/// The letter C means that the corresponding axis is collapsed into
663/// one bin, i.e. one dimension is removed from the counting.
664/// The letters U,O remove for the matching axis the underflow.overflow
665/// bins from the counting
674
675////////////////////////////////////////////////////////////////////////
676/// create a THxx histogram capable to hold the bins of this binning
677/// node and its children
678///
679/// \param[in] histogramName name of the histogram which is created
680/// \param[in] originalAxisBinning if true, try to preserve the axis binning
681/// \param[out] (default=nullptr) binMap mapping of global bins to histogram bins.
682/// if(binMap==nullptr), no binMap is created
683/// \param[in] (default=nullptr) histogramTitle title o fthe histogram. If zero, a title
684/// is selected automatically
685/// \param[in] (default=nullptr) axisSteering steer the handling of underflow/overflow
686/// and projections
687///
688/// returns a new histogram (TH1D, TH2D or TH3D)
689/// <br>
690/// if the parameter <b>originalAxisBinning</b> parameter is true, the
691/// resulting histogram has bin widths and histogram dimension (TH1D,
692/// TH2D, TH3D) in parallel to this binning node, if possible.
693/// <br/>
694/// The <b>binMap</b> is an array which translates global bin numbers to bin
695/// numbers in the histogram returned by this method. The global bin
696/// numbers correspond to the bin numbers in a histogram created by
697/// calling GetRootNode()->CreateHistogram(name,false,0,0,0)
698/// <br/>
699/// The <b>axisSteering</b> is a string to steer whether underflow and
700/// overflow bins are included in the bin map. Furthermore, it is
701/// possible to "collapse" axes, such that their content is summed and
702/// the axis does not show up in the created histogram.
703/// <br/>
704/// The string looks like this: "axis[options];axis[options];..." where
705/// <ul>
706/// <li>axis is the name of an axis or equal to *, the latter matches
707/// all axes</li>
708/// <li>options is a combination of characters chosen from
709/// OUC0123456789
710/// <ul>
711/// <li>if O is included, the overflow bin of that axis is discarded</li>
712/// <li>if U is included, the underflow bin of that axis is discarded</li>
713/// <li>if C is included, the bins on that axes are collapsed,
714/// i.e. the corresponding histogram axis is not present in the output.
715/// The corrsponding bin contents are added up
716/// (projected onto the remaining axes). Using the characters O and U
717/// one can decide to exclude underflow or overflow from the
718/// projection. Using a selection of the characters 0123456789 one can
719/// restrict the sum further to only include the corresponding
720/// bins. In this counting, the first non-underflow bin corresponds to
721/// the character 0. This obviously only works for up to ten
722/// bins.</li>
723/// </ul>
724/// </li>
725/// </ul>
728 const char *histogramTitle,const char *axisSteering) const
729{
730 Int_t nBin[3],axisList[3];
735 TH1 *r=nullptr;
736 if(nDim>0) {
737 const TVectorD *axisBinsX=
738 neNode->GetDistributionBinning(axisList[0]);
739 if(nDim>1) {
740 const TVectorD *axisBinsY=
741 neNode->GetDistributionBinning(axisList[1]);
742 if(nDim>2) {
743 const TVectorD *axisBinsZ=
744 neNode->GetDistributionBinning(axisList[2]);
745 r=new TH3D(histogramName,title,
746 nBin[0],axisBinsX->GetMatrixArray(),
747 nBin[1],axisBinsY->GetMatrixArray(),
748 nBin[2],axisBinsZ->GetMatrixArray());
749 } else {
750 r=new TH2D(histogramName,title,
751 nBin[0],axisBinsX->GetMatrixArray(),
752 nBin[1],axisBinsY->GetMatrixArray());
753 }
754 } else {
755 r=new TH1D(histogramName,title,nBin[0],axisBinsX->GetMatrixArray());
756 }
757 } else {
759 Warning("CreateHistogram",
760 "Original binning can not be represented as THxx");
761 }
762 r=new TH1D(histogramName,title,nBin[0],0.5,nBin[0]+0.5);
763 nDim=0;
764 }
765 if(binMap) {
767 }
768 return r;
769}
770
771////////////////////////////////////////////////////////////////////////
772/// create a TH2D histogram capable to hold a covariance matrix
773///
774///
775/// \param[in] histogramName name of the histogram which is created
776/// \param[in] originalAxisBinning if true, try to preserve the axis binning
777/// \param[out] (default=nullptr) binMap mapping of global bins to histogram bins.
778/// if(binMap==nullptr), no binMap is created
779/// \param[in] (default=nullptr) histogramTitle title o fthe histogram. If zero, a title
780/// is selected automatically
781/// \param[in] (default=nullptr) axisSteering steer the handling of underflow/overflow
782/// and projections
783///
784/// returns a new TH2D. The options are described in greater detail
785/// with the CreateHistogram() method.
786
789 const char *histogramTitle,const char *axisSteering) const
790{
791 Int_t nBin[3],axisList[3];
795 TH2D *r=nullptr;
796 if(nDim==1) {
797 const TVectorD *axisBinsX=(TVectorD const *)
798 GetNonemptyNode()->fAxisList->At(axisList[0]);
799 r=new TH2D(histogramName,title,nBin[0],axisBinsX->GetMatrixArray(),
800 nBin[0],axisBinsX->GetMatrixArray());
801 } else {
803 Info("CreateErrorMatrixHistogram",
804 "Original binning can not be represented on one axis");
805 }
806 r=new TH2D(histogramName,title,nBin[0],0.5,nBin[0]+0.5,
807 nBin[0],0.5,nBin[0]+0.5);
808 nDim=0;
809 }
810 if(binMap) {
812 }
813 return r;
814}
815
816////////////////////////////////////////////////////////////////////////
817/// create a TH2D histogram capable to hold the bins of the two
818/// input binning schemes on the x and y axes, respectively
819///
820/// \paran[in] xAxis binning scheme for the x axis
821/// \param[in] yAxis binning scheme for the y axis
822/// \param[in] histogramName name of the histogram which is created
823/// \param[in] originalXAxisBinning preserve x-axis bin widths if possible
824/// \param[in] originalXAxisBinning preserve y-axis bin widths if possible
825/// \param[in] histogramTitle if is non-zero, it is taken as histogram title
826/// otherwise, the title is created automatically
827///
828/// returns a new TH2D.
829
834{
835 Int_t nBinX[3],axisListX[3];
836 Int_t nDimX=
837 xAxis->GetTHxxBinning(originalXAxisBinning ? 1 : 0,nBinX,axisListX,nullptr);
838 const TUnfoldBinning *neNodeX=xAxis->GetNonemptyNode();
839 Int_t nBinY[3],axisListY[3];
840 Int_t nDimY=
841 yAxis->GetTHxxBinning(originalYAxisBinning ? 1 : 0,nBinY,axisListY,nullptr);
842 const TUnfoldBinning *neNodeY=yAxis->GetNonemptyNode();
843 TString title=xAxis->BuildHistogramTitle2D
845 if(nDimX==1) {
846 const TVectorD *axisBinsX=(TVectorD const *)
847 neNodeX->fAxisList->At(axisListX[0]);
848 if(nDimY==1) {
849 const TVectorD *axisBinsY=(TVectorD const *)
850 neNodeY->fAxisList->At(axisListY[0]);
851 return new TH2D(histogramName,title,
852 nBinX[0],axisBinsX->GetMatrixArray(),
853 nBinY[0],axisBinsY->GetMatrixArray());
854 } else {
855 return new TH2D(histogramName,title,
856 nBinX[0],axisBinsX->GetMatrixArray(),
857 nBinY[0],0.5,0.5+nBinY[0]);
858 }
859 } else {
860 if(nDimY==1) {
861 const TVectorD *axisBinsY=(TVectorD const *)
862 neNodeY->fAxisList->At(axisListY[0]);
863 return new TH2D(histogramName,title,
864 nBinX[0],0.5,0.5+nBinX[0],
865 nBinY[0],axisBinsY->GetMatrixArray());
866 } else {
867 return new TH2D(histogramName,title,
868 nBinX[0],0.5,0.5+nBinX[0],
869 nBinY[0],0.5,0.5+nBinY[0]);
870 }
871 }
872}
873
874////////////////////////////////////////////////////////////////////////
875/// calculate properties of a THxx histogram to store this binning
876///
877/// \param[in] maxDim maximum dimension of the THxx (0 or 1..3)
878/// maxDim==nullptr is used to indicate that the histogram should be
879/// dimensional with all bins mapped on one axis,
880/// bin centers equal to bin numbers
881/// \param[in] axisSteering see method CreateHistogram()
882/// \param[out] axisBins[3] number of bins on the THxx axes
883/// \param[out] axisList[3] TUnfoldBinning axis number corresponding
884/// to the THxx axis
885///
886/// returns 1-3 dimension of THxx or 0 for 1-dim THxx with equidistant bins
889 const char *axisSteering) const
890{
891 for(Int_t i=0;i<3;i++) {
892 axisBins[i]=0;
893 axisList[i]=-1;
894 }
896 if(theNode) {
897 Int_t r=theNode->GetTHxxBinningSingleNode
899 /* cout<<"GetTHxxBinning single node "<<r
900 <<" "<<axisBins[0]
901 <<" "<<axisBins[1]
902 <<" "<<axisBins[2]
903 <<"\n"; */
904 return r;
905 } else {
907 //cout<<"GetTHxxBinning recursive "<<axisBins[0]<<"\n";
908 return 0;
909 }
910}
911
912////////////////////////////////////////////////////////////////////////
913/// find a node which has non-empty distributions
914/// if there is none or if there are many, return zero
916{
917 int count=0;
918 const TUnfoldBinning *r=GetNonemptyNode_r(count);
919 if(count!=1) r=nullptr;
920 return r;
921}
922
924{
925 const TUnfoldBinning *r=nullptr;
927 r=this;
928 count++;
929 }
931 child=child->GetNextNode()) {
932 const TUnfoldBinning *c=child->GetNonemptyNode_r(count);
933 if(!r) r=c;
934 }
935 return r;
936}
937
938////////////////////////////////////////////////////////////////////////
939/// get the properties of a histogram capable to hold the distribution
940/// attached to this node
941///
942/// \param[in] maxDim maximum dimension of the THxx (0 or 1..3)
943/// maxDim==nullptr is used to indicate that the histogram should
944/// 1-dimensional with all bins mapped on one axis
945/// \param[out] axisBins[3] number of bins on the THxx axes
946/// \param[out] axisList[3] TUnfoldBinning axis numbers
947/// corresponding to the THxx axis
948/// \param[in] axisSteering see method CreateHistogram()
949/// and projection
950///
951/// returns 1-3 dimension of THxx or use 1-dim THxx, binning structure
952/// is not preserved
955{
956 // decode axisSteering
957 // isOptionGiven[0] ('C'): bit vector which axes to collapse
958 // isOptionGiven[1] ('U'): bit vector to discard underflow bins
959 // isOptionGiven[2] ('O'): bit vector to discard overflow bins
962 // count number of axes after projecting
964 Int_t r=0;
965 for(Int_t i=0;i<numDimension;i++) {
966 if(isOptionGiven[0] & (1<<i)) continue;
967 r++;
968 }
969 if((r>0)&&(r<=maxDim)) {
970 // 0<r<=maxDim
971 //
972 // -> preserve the original binning
973 // axisList[] and axisBins[] are overwritten
974 r=0;
975 for(Int_t i=0;i<numDimension;i++) {
976 if(isOptionGiven[0] & (1<<i)) continue;
977 axisList[r]=i;
979 r++;
980 }
981 } else {
982 // map everything on one axis
983 // axisBins[0] is the number of bins
986 } else {
987 Int_t nBin=1;
988 for(Int_t i=0;i<numDimension;i++) {
989 Int_t mask=(1<<i);
990 if(isOptionGiven[0] & mask) continue;
992 if((fHasUnderflow & mask)&& !(isOptionGiven[1] & mask)) nBinI++;
993 if((fHasOverflow & mask)&& !(isOptionGiven[2] & mask)) nBinI++;
994 nBin *= nBinI;
995 }
996 axisBins[0] = nBin;
997 }
998 r=0;
999 }
1000 return r;
1001}
1002
1003////////////////////////////////////////////////////////////////////////
1004/// calculate number of bins required to store this binning with teh
1005/// given axisSteering
1006///
1007/// \param[in] axisSteering see method CreateHistogram()
1008///
1009/// returns the number of bins
1011{
1012
1013 Int_t r=0;
1015 child=child->GetNextNode()) {
1016 r +=child->GetTHxxBinsRecursive(axisSteering);
1017 }
1018 // here: process distribution of this node
1019 Int_t axisBins[3],axisList[3];
1021 r += axisBins[0];
1022 // cout<<"GetTHxxBinsRecursive returns "<<r<<"\n";
1023 return r;
1024}
1025
1026////////////////////////////////////////////////////////////////////////
1027/// create an empty bin map, useful together with the getter methods of
1028/// class TUnfold and TUnfoldSys
1029///
1030/// returns: a new Int array of the proper size, all eleemnts set to -1
1032 // create empty bin map which can be manipulated by
1033 // MapGlobalBin()
1035 Int_t *r=new Int_t[nMax];
1036 for(Int_t i=0;i<nMax;i++) {
1037 r[i]=-1;
1038 }
1039 return r;
1040}
1041
1042////////////////////////////////////////////////////////////////////////
1043/// set one entry in a bin map
1044///
1045/// \param[out] binMap to be used with TUnfoldSys::GetOutput() etc
1046/// \param[in] source bin, global bin number in this binning scheme
1047/// \param[in] destination bin in the output histogram
1048///
1049
1053 if((globalBin<0)||(globalBin>=nMax)) {
1054 Error("SetBinMapEntry","global bin number %d outside range (max=%d)",
1055 globalBin,nMax);
1056 } else {
1058 }
1059}
1060
1061////////////////////////////////////////////////////////////////////////
1062/// map all global bins referenced by this node to the one-dimensional
1063/// histogram destHist, starting with bin firstBinX
1064///
1065/// \param[out] binMap to be used with TUnfoldSys::GetOutput() etc
1066/// \param[in] axisSteering steering for underflow/overflow/projections
1067/// \param[in] firstBinX first bin of destination histogram to be filled
1068///
1069/// returns: highest bin number in destibation histogram plus 1
1070/// <br/>The parameter <b>axisSteering</b> is explained with the
1071/// method CreateHistogram()
1073(Int_t *binMap,const char *axisSteering,Int_t firstBinX) const {
1075 Int_t axisBins[3],axisList[3];
1077 if((nDim==1)|| !GetDistributionDimension()) {
1078 r+=FillBinMapSingleNode(nullptr,r,0,nullptr,axisSteering,binMap);
1079 } else {
1080 Error("FillBinMap1D","distribution %s with steering=%s is not 1D",
1081 (char *)GetName(),axisSteering);
1082 }
1084 child=child->GetNextNode()) {
1085 r =child->FillBinMap1D(binMap,axisSteering,r);
1086 }
1087 return r;
1088}
1089
1090////////////////////////////////////////////////////////////////////////
1091/// create mapping from global bin number to a histogram for this node
1092///
1093/// \param[in] hist destination histogram
1094/// \param[in] nDim target dimension
1095/// \param[in] axisList map axes in the binning scheme to histogram axes
1096/// \param[in] axisSteering steering for underflow/overflow/projections
1097///
1098/// The <b>axisSteering</b> is explained with the method CreateHistogram()
1100(const TH1 *hist,Int_t nDim,const Int_t *axisList,const char *axisSteering)
1101 const
1102{
1103 // create mapping from global bin number to a histogram for this node
1104 // global bins are the bins of the root node binning scheme
1105 // when projecting them on a TH1 histogram "hRootNode" without special
1106 // axis steering and without attempting to preserve the axis binnings
1107 //
1108 // The bin map is an array of size hRootNode->GetNbinsX()+2
1109 // For each bin of the "hRootNode" histogram it holds the target bin in
1110 // "hist" or the number -1 if the corresponding "hRootNode" bin is not
1111 // represented in "hist"
1112 //
1113 // input
1114 // hist : the histogram (to calculate root bin numbers)
1115 // nDim : target dimension of the TUnfoldBinning
1116 // if(nDim==nullptr) all bins are mapped linearly
1117 // axisSteering:
1118 // "pattern1;pattern2;...;patternN"
1119 // patternI = axis[mode]
1120 // axis = name or *
1121 // mode = C|U|O
1122 // C: collapse axis into one bin
1123 // U: discard underflow bin
1124 // O: discard overflow bin
1125 //
1126 // input used only if nDim>0:
1127 // axisList : for each THxx axis give the TUnfoldBinning axis number
1128 //
1129 // return value:
1130 // an new array which holds the bin mapping
1131 // r[0] : to which THxx bin to map global bin number 0
1132 // r[1] : to which THxx bin to map global bin number 1
1133 // ...
1134 // r[nmax]
1135 // where nmax=GetRootNode()->GetEndBin()+1
1138 if(nDim>0) {
1140 if(nonemptyNode) {
1141 nonemptyNode->
1143 } else {
1144 Fatal("CreateBinMap","called with nDim=%d but GetNonemptyNode()=nullptr",
1145 nDim);
1146 }
1147 } else {
1149 }
1150 return r;
1151}
1152
1153////////////////////////////////////////////////////////////////////////
1154/// recursively fill bin map
1155///
1156/// \param[in] startBin first histogram bin
1157/// \param[in] axisSteering see CreateHistogram() method
1158/// \param[out] binMap the bin mapping which is to be filled
1159///
1160/// the positions
1161/// binMap[GetStartBin()]...binMap[GetEndBin()-1]
1162/// are filled
1164(Int_t startBin,const char *axisSteering,Int_t *binMap) const
1165{
1166 Int_t nbin=0;
1169 child=child->GetNextNode()) {
1170 nbin += child->FillBinMapRecursive(startBin+nbin,axisSteering,binMap);
1171 }
1172 return nbin;
1173}
1174
1175////////////////////////////////////////////////////////////////////////
1176/// fill bin map for a single node
1177///
1178/// \param[in] hist the histogram representing this node (used if nDim>0)
1179/// \param[in] startBin start bin in the bin map
1180/// \param[in] nDim number of dimensions to resolve
1181/// \param[in] axisList[3] TUnfoldBinning axis numbers corresponding
1182/// to the axes of <b>hist</b>
1183/// \param[in] axisSteering see documentation of CreateHistogram()
1184/// \param[out] binMap the bin map to fill
1185///
1186/// returns the number of bins mapped.
1187/// <br>
1188/// The result depends on the parameter <b>nDim</b> as follows
1189/// <ul>
1190/// <li> nDim==nullptr: bins are mapped in linear order, ignore hist and
1191/// axisList</li>
1192/// <li> nDim==hist->GetDimension():
1193/// bins are mapped to "hist" bin numbers
1194/// the corresponding TUnfoldBinning axes are taken from
1195/// axisList[]</li>
1196/// <li>nDim=1 and hist->GetDimension()>1:
1197/// bins are mapped to the x-axis of "hist"
1198/// the corresponding TUnfoldBinning axis is taken from
1199/// axisList[0]</li>
1200/// </ul>
1202(const TH1 *hist,Int_t startBin,Int_t nDim,const Int_t *axisList,
1203 const char *axisSteering,Int_t *binMap) const
1204{
1205 // first, decode axisSteering
1206 // isOptionGiven[0] ('C'): bit vector which axes to collapse
1207 // isOptionGiven[1] ('U'): bit vector to discard underflow bins
1208 // isOptionGiven[2] ('O'): bit vector to discard overflow bins
1209 Int_t isOptionGiven[3+10];
1212 for(Int_t i=3;i<3+10;i++) {
1214 }
1215
1217 Int_t dimension=GetDistributionDimension();
1219 for(Int_t i=0;i<dimension;i++) {
1220 const TVectorD *binning=GetDistributionBinning(i);
1221 axisNbin[i]=binning->GetNrows()-1;
1222 };
1223 for(Int_t i=0;i<GetDistributionNumberOfBins();i++) {
1226 if(dest!=this) {
1227 if(!dest) {
1228 Fatal("FillBinMapSingleNode",
1229 "bin %d outside binning scheme",
1230 globalBin);
1231 } else {
1232 Fatal("FillBinMapSingleNode",
1233 "bin %d located in %s %d-%d rather than %s %d=%d",
1234 i,(const char *)dest->GetName(),
1235 dest->GetStartBin(),dest->GetEndBin(),
1236 (const char *)GetName(),GetStartBin(),GetEndBin());
1237 }
1238 }
1239 // check whether this bin has to be skipped
1241 for(Int_t axis=0;axis<dimension;axis++) {
1242 Int_t mask=(1<<axis);
1243 // underflow/overflow excluded by steering
1244 if(((axisBins[axis]<0)&&(isOptionGiven[1] & mask))||
1245 ((axisBins[axis]>=axisNbin[axis])&&(isOptionGiven[2] & mask)))
1246 skip=kTRUE;
1247 // only certain bins selected by steering
1248 if((axisBins[axis]>=0)&&(axisBins[axis]<axisNbin[axis])&&
1249 (haveSelectedBin & mask)) {
1250 if(!(isOptionGiven[3+axisBins[axis]] & mask)) skip=kTRUE;
1251 }
1252 }
1253 if(skip) {
1254 continue;
1255 }
1256
1257 if(nDim>0) {
1258 // get bin number from THxx function(s)
1259 if(nDim==hist->GetDimension()) {
1260 Int_t ibin[3];
1261 ibin[0]=ibin[1]=ibin[2]=0;
1262 for(Int_t hdim=0;hdim<nDim;hdim++) {
1263 Int_t axis=axisList[hdim];
1264 ibin[hdim]=axisBins[axis]+1;
1265 }
1266 binMap[globalBin]=hist->GetBin(ibin[0],ibin[1],ibin[2]);
1267 //cout<<globalBin<<"->"<<binMap[globalBin]
1268 // <<" ("<<ibin[0]<<","<<ibin[1]<<","<<ibin[2]<<")\n";
1269 } else if(nDim==1) {
1270 // histogram has more dimensions than the binning scheme
1271 // and the binning scheme has one axis only
1272 //
1273 // special case: error histogram is 2-d
1274 // create nor error if ndim==1 && hist->GetDimension()==2
1275 if((nDim!=1)||( hist->GetDimension()!=2)) {
1276 // -> use the first valid axis only
1277 Error("FillBinMapSingleNode","inconsistent dimensions %d %d",nDim,
1278 hist->GetDimension());
1279 }
1280 for(Int_t ii=0;ii<hist->GetDimension();ii++) {
1281 if(axisList[ii]>=0) {
1283 break;
1284 }
1285 }
1286 } else {
1287 Fatal("FillBinMapSingleNode","inconsistent dimensions %d %d",nDim,
1288 hist->GetDimension());
1289 }
1290 } else {
1291 // order all bins in sequence
1292 // calculation in parallel to ToGlobalBin()
1293 // but take care of
1294 // startBin,collapseAxis,discardeUnderflow,discardeOverflow
1295 if(dimension>0) {
1296 Int_t r=0;
1297 for(Int_t axis=dimension-1;axis>=0;axis--) {
1298 Int_t mask=(1<<axis);
1299 if(isOptionGiven[0] & mask) {
1300 // bins on this axis are integrated over
1301 continue;
1302 }
1303 Int_t iBin=axisBins[axis];
1304 Int_t nMax=axisNbin[axis];
1305 if((fHasUnderflow & ~isOptionGiven[1]) & mask) {
1306 nMax +=1;
1307 iBin +=1;
1308 }
1309 if((fHasOverflow & ~isOptionGiven[2]) & mask) {
1310 nMax += 1;
1311 }
1312 r = r*nMax +iBin;
1313 }
1315 } else {
1317 }
1318 }
1319 }
1320 Int_t nbin;
1321 if(dimension>0) {
1322 nbin=1;
1323 for(Int_t axis=dimension-1;axis>=0;axis--) {
1324 Int_t mask=(1<<axis);
1325 if(isOptionGiven[0] & mask) {
1326 // bins on this axis are integrated over
1327 continue;
1328 }
1329 Int_t nMax=axisNbin[axis];
1330 if((fHasUnderflow & ~isOptionGiven[1]) & mask) {
1331 nMax +=1;
1332 }
1333 if((fHasOverflow & ~isOptionGiven[2]) & mask) {
1334 nMax += 1;
1335 }
1336 nbin = nbin*nMax;
1337 }
1338 } else {
1340 }
1341 return nbin;
1342}
1343
1344////////////////////////////////////////////////////////////////////////
1346(const char *histogramName,const TH1 *globalBins,
1348 const char *axisSteering) const
1349{
1350 // extract a distribution from the given set of global bins
1351 // input:
1352 // histogramName : name of the histogram which is created
1353 // globalBins : histogram with all bins
1354 // globalBinsEmatrix : corresponding error matrix
1355 // if this pointer is zero, only diagonal errors
1356 // are considered
1357 // originalAxisBinning : extract histogram with proper binning
1358 // (if possible)
1359 // axisSteering
1360 // "pattern1;pattern2;...;patternN"
1361 // patternI = axis[mode]
1362 // axis = name or *
1363 // mode = C|U|O
1364 // C: collapse axis into one bin
1365 // U: discard underflow bin
1366 // O: discard overflow bin
1367 Int_t *binMap=nullptr;
1369 axisSteering);
1370 if(!r) return nullptr;
1371 TUnfoldBinning const *root=GetRootNode();
1372 Int_t nMax=-1;
1373 for(Int_t iSrc=root->GetStartBin();iSrc<root->GetEndBin();iSrc++) {
1375 }
1376 if(nMax<0) {
1377 delete r;
1378 r=nullptr;
1379 } else {
1381 for(Int_t iSrc=root->GetStartBin();iSrc<root->GetEndBin();iSrc++) {
1383 if(iDest>=0) {
1384 Double_t c=r->GetBinContent(iDest);
1385 r->SetBinContent(iDest,c+globalBins->GetBinContent(iSrc));
1386 if(!globalBinsEmatrix) {
1387 eSquared(iDest)+=TMath::Power(globalBins->GetBinError(iSrc),2.);
1388 } else {
1389 for(Int_t jSrc=root->GetStartBin();jSrc<root->GetEndBin();
1390 jSrc++) {
1391 if(binMap[jSrc]==iDest) {
1392 eSquared(iDest) +=
1393 globalBinsEmatrix->GetBinContent(iSrc,jSrc);
1394 }
1395 }
1396 }
1397 }
1398 }
1399 for(Int_t i=0;i<=nMax;i++) {
1400 Double_t e2=eSquared(i);
1401 if(e2>0.0) {
1402 r->SetBinError(i,TMath::Sqrt(e2));
1403 }
1404 }
1405 }
1406 delete binMap;
1407 return r;
1408}
1409
1410/********************* Calculate global bin number ******/
1411
1412////////////////////////////////////////////////////////////////////////
1413/// locate a bin in a one-dimensional distribution
1414///
1415/// \param[in] x coordinate
1416///
1417/// returns the global bin number within the distribution attached to
1418/// this node. THe global bin number is valid for the root node of the
1419/// binning scheme
1421{
1422 if(GetDistributionDimension()!=1) {
1423 Fatal("GetBinNumber",
1424 "called with 1 argument for %d dimensional distribution",
1426 }
1427 return GetGlobalBinNumber(&x);
1428}
1429
1430////////////////////////////////////////////////////////////////////////
1431/// locate a bin in a two-dimensional distribution
1432///
1433/// \param[in] x coordinate on first axis
1434/// \param[in] y coordinate on second axis
1435///
1436/// returns the global bin number within the distribution attached to
1437/// this node. The global bin number is valid for the root node of the
1438/// binning scheme
1440{
1441 if(GetDistributionDimension()!=2) {
1442 Fatal("GetBinNumber",
1443 "called with 2 arguments for %d dimensional distribution",
1445 }
1446 Double_t xx[2];
1447 xx[0]=x;
1448 xx[1]=y;
1449 return GetGlobalBinNumber(xx);
1450}
1451
1452////////////////////////////////////////////////////////////////////////
1453/// locate a bin in a three-dimensional distribution
1454///
1455/// \param[in] x coordinate on first axis
1456/// \param[in] y coordinate on second axis
1457/// \param[in] z coordinate on third axis
1458///
1459/// returns the global bin number within the distribution attached to
1460/// this node. The global bin number is valid for the root node of the
1461/// binning scheme
1463(Double_t x,Double_t y,Double_t z) const
1464{
1465 // locate bin on a three-dimensional distribution
1466 // input
1467 // x,y,z: coordinates to locate
1468 if(GetDistributionDimension()!=3) {
1469 Fatal("GetBinNumber",
1470 "called with 3 arguments for %d dimensional distribution",
1472 }
1473 Double_t xx[3];
1474 xx[0]=x;
1475 xx[1]=y;
1476 xx[2]=z;
1477 return GetGlobalBinNumber(xx);
1478}
1479
1480////////////////////////////////////////////////////////////////////////
1481/// locate a bin in a four-dimensional distribution
1482///
1483/// \param[in] x0 coordinate on first axis
1484/// \param[in] x1 coordinate on second axis
1485/// \param[in] x2 coordinate on third axis
1486/// \param[in] x3 coordinate on fourth axis
1487///
1488/// returns the global bin number within the distribution attached to
1489/// this node. The global bin number is valid for the root node of the
1490/// binning scheme
1493{
1494 // locate bin on a four-dimensional distribution
1495 // input
1496 // x0,x1,x2,x3: coordinates to locate
1497 if(GetDistributionDimension()!=4) {
1498 Fatal("GetBinNumber",
1499 "called with 4 arguments for %d dimensional distribution",
1501 }
1502 Double_t xx[4];
1503 xx[0]=x0;
1504 xx[1]=x1;
1505 xx[2]=x2;
1506 xx[3]=x3;
1507 return GetGlobalBinNumber(xx);
1508}
1509
1510////////////////////////////////////////////////////////////////////////
1511/// locate a bin in a five-dimensional distribution
1512///
1513/// \param[in] x0 coordinate on first axis
1514/// \param[in] x1 coordinate on second axis
1515/// \param[in] x2 coordinate on third axis
1516/// \param[in] x3 coordinate on fourth axis
1517/// \param[in] x4 coordinate on fifth axis
1518///
1519/// returns the global bin number within the distribution attached to
1520/// this node. The global bin number is valid for the root node of the
1521/// binning scheme
1524{
1525 // locate bin on a five-dimensional distribution
1526 // input
1527 // x0,x1,x2,x3,x4: coordinates to locate
1528 if(GetDistributionDimension()!=5) {
1529 Fatal("GetBinNumber",
1530 "called with 5 arguments for %d dimensional distribution",
1532 }
1533 Double_t xx[5];
1534 xx[0]=x0;
1535 xx[1]=x1;
1536 xx[2]=x2;
1537 xx[3]=x3;
1538 xx[4]=x4;
1539 return GetGlobalBinNumber(xx);
1540}
1541
1542////////////////////////////////////////////////////////////////////////
1543/// locate a bin in a six-dimensional distribution
1544///
1545/// \param[in] x0 coordinate on first axis
1546/// \param[in] x1 coordinate on second axis
1547/// \param[in] x2 coordinate on third axis
1548/// \param[in] x3 coordinate on fourth axis
1549/// \param[in] x4 coordinate on fifth axis
1550/// \param[in] x5 coordinate on sixth axis
1551///
1552/// returns the global bin number within the distribution attached to
1553/// this node. The global bin number is valid for the root node of the
1554/// binning scheme
1557{
1558 // locate bin on a five-dimensional distribution
1559 // input
1560 // x0,x1,x2,x3,x4,x5: coordinates to locate
1561 if(GetDistributionDimension()!=6) {
1562 Fatal("GetBinNumber",
1563 "called with 6 arguments for %d dimensional distribution",
1565 }
1566 Double_t xx[6];
1567 xx[0]=x0;
1568 xx[1]=x1;
1569 xx[2]=x2;
1570 xx[3]=x3;
1571 xx[4]=x4;
1572 xx[5]=x5;
1573 return GetGlobalBinNumber(xx);
1574}
1575
1576////////////////////////////////////////////////////////////////////////
1577/// locate a bin in an N-dimensional distribution
1578///
1579/// \param[in] x array of coordinates
1580/// \param[out] isBelow pointer to an integer (bit vector) to indicate
1581/// coordinates which do not fit in the binning scheme
1582/// \param[out] isAbove pointer to an integer (bit vector) to indicate
1583/// coordinates which do not fit in the binning scheme
1584///
1585/// returns the global bin number within the distribution attached to
1586/// this node. The global bin number is valid for the root node of the
1587/// binning scheme. If some coordinates do not fit, zero is returned.
1588/// The integers pointed to by isBelow and isAbove are set to zero.
1589/// However, if coordinate i is below
1590/// the lowest bin border and there is no underflow bin, the bin i is
1591/// set in (*isBelow). Overflows are handled in a similar manner with
1592/// (*isAbove).
1593/// <br>
1594/// If a coordinate is NaN, the result is undefined for TUnfold
1595/// Version<17.6. As of version 17.6, NaN is expected to end up in the
1596/// underflow or by setting the corresponding bit in (*isBelow).
1597
1599(const Double_t *x,Int_t *isBelow,Int_t *isAbove) const
1600{
1601 // locate bin on a n-dimensional distribution
1602 // input
1603 // x[]: coordinates to locate
1604 // output:
1605 // isBelow,isAbove: bit vectors,
1606 // indicating which cut on which axis failed
1608 Fatal("GetBinNumber",
1609 "no axes are defined for node %s",
1610 (char const *)GetName());
1611 }
1613 for(Int_t dim=0;dim<GetDistributionDimension();dim++) {
1614 TVectorD const *bins=(TVectorD const *) fAxisList->At(dim);
1615 Int_t i0=0;
1616 Int_t i1=bins->GetNrows()-1;
1617 Int_t iBin= 0;
1618 if(!(x[dim]>=(*bins)[i0])) {
1619 // underflow or NaN
1620 iBin += i0-1;
1621 } else if(!(x[dim]<(*bins)[i1])) {
1622 // overflow
1623 iBin += i1;
1624 } else {
1625 while(i1-i0>1) {
1626 Int_t i2=(i0+i1)/2;
1627 if(x[dim]<(*bins)[i2]) {
1628 i1=i2;
1629 } else {
1630 i0=i2;
1631 }
1632 }
1633 iBin += i0;
1634 }
1635 iAxisBins[dim]=iBin;
1636 }
1638 if(r<0) r=0;
1639 return r;
1640}
1641
1642/********************* access by global bin number ******/
1643
1644////////////////////////////////////////////////////////////////////////
1645/// get the name of a bin
1646///
1647/// \param[in] iBin global bin number
1648///
1649/// returns a string describing the bin
1651{
1652 // get the name of a bin in the given tree
1653 // iBin: bin number
1657 if(distribution) {
1658 r +=" (";
1659 r += distribution->GetName();
1660 Int_t dimension=distribution->GetDistributionDimension();
1661 if(dimension>0) {
1663 for(Int_t axis=0;axis<dimension;axis++) {
1665 distribution->GetDistributionAxisLabel(axis);
1666 TVectorD const *bins=distribution->GetDistributionBinning(axis);
1667 Int_t i=axisBins[axis];
1668 if(i<0) thisAxisString += "[ufl]";
1669 else if(i>=bins->GetNrows()-1) thisAxisString += "[ofl]";
1670 else {
1672 TString::Format("[%.3g,%.3g]",(*bins)[i],(*bins)[i+1]);
1673 }
1675 }
1676 r += axisString;
1677 } else {
1678 // extra bins
1679 Int_t i=axisBins[0];
1681 r += distribution->GetDistributionAxisLabel(i);
1682 } else {
1683 r += TString::Format(" %d",i);
1684 }
1685 }
1686 r +=")";
1687 }
1688 return r;
1689}
1690
1691////////////////////////////////////////////////////////////////////////
1692/// get N-dimensional bin size
1693///
1694/// \param[in] iBin global bin number
1696{
1697 // includeUO : include underflow/overflow bins or not
1700 Double_t r=0.0;
1701 if(distribution) {
1702 if(distribution->GetDistributionDimension()>0) r=1.0;
1703 for(Int_t axis=0;axis<distribution->GetDistributionDimension();axis++) {
1704 TVectorD const *bins=distribution->GetDistributionBinning(axis);
1705 Int_t pos=axisBins[axis];
1706 if(pos<0) {
1707 r *= distribution->GetDistributionUnderflowBinWidth(axis);
1708 } else if(pos>=bins->GetNrows()-1) {
1709 r *= distribution->GetDistributionOverflowBinWidth(axis);
1710 } else {
1711 r *= (*bins)(pos+1)-(*bins)(pos);
1712 }
1713 if(r<=0.) break;
1714 }
1715 }
1716 return r;
1717}
1718
1719////////////////////////////////////////////////////////////////////////
1720/// check whether there is only a global scaling factor for this node
1724
1725////////////////////////////////////////////////////////////////////////
1726/// return global scaling factor for this node
1730
1731////////////////////////////////////////////////////////////////////////
1732/// return scaling factor for the given global bin number
1733///
1734/// \param[in] iBin global bin number
1735///
1736/// returns the scaling factor for this bin.
1737/// The scaling factors can be set using the method SetBinFactorFunction()
1739{
1740 // return user factor for a bin
1741 // iBin : global bin number
1744 Double_t r=distribution->fBinFactorConstant;
1745 if((r!=0.0) && distribution->fBinFactorFunction) {
1746 TF1 *function=dynamic_cast<TF1 *>(distribution->fBinFactorFunction);
1747 if(function) {
1748 Double_t x[MAXDIM];
1749 Int_t dimension=distribution->GetDistributionDimension();
1750 if(dimension>0) {
1751 for(Int_t axis=0;axis<dimension;axis++) {
1752 x[axis]=distribution->GetDistributionBinCenter
1753 (axis,axisBins[axis]);
1754 }
1755 r *= function->EvalPar(x,function->GetParameters());
1756 } else {
1757 x[0]=axisBins[0];
1758 r *= function->Eval(x[0]);
1759 }
1760 } else {
1761 TVectorD *vect=dynamic_cast<TVectorD *>
1762 (distribution->fBinFactorFunction);
1763 if(vect) {
1764 r=(*vect)[iBin-GetStartBin()];
1765 } else {
1766 Error("GetBinFactor",
1767 "internal error: user function is neiter TF1 or TVectorD");
1768 }
1769 }
1770 }
1771 return r;
1772}
1773
1774////////////////////////////////////////////////////////////////////////
1775/// get neighbour bins along the specified axis
1776///
1777/// \param[in] bin global bin number
1778/// \param[in] axis axis number of interest
1779/// \param[out] prev bin number of previous bin or -1 if not existing
1780/// \param[out] distPrev distance between bin centres
1781/// \param[out] next bin number of next bin or -1 if not existing
1782/// \param[out] distNext distance between bin centres
1783/// \param[in] isPeriodic (default=false) if true, the first bin is counted as neighbour of the last bin
1784///
1785/// return code
1786/// <ul>
1787/// <li>0 everything is fine</li>
1788/// <li>1,2,3 isPeriodic option was reset to false, because underflow/overflow
1789/// bins are present
1790/// <ul>
1791/// <li>+1 invalid isPeriodic option was specified with underflow bin</li>
1792/// <li>+2 invalid isPeriodic option was specified with overflow bin</li>
1793/// </ul>
1794/// </li>
1795/// </ul>
1796
1798(Int_t bin,Int_t axis,Int_t *prev,Double_t *distPrev,
1800{
1803 Int_t dimension=distribution->GetDistributionDimension();
1804 *prev=-1;
1805 *next=-1;
1806 *distPrev=0.;
1807 *distNext=0.;
1808 Int_t r=0;
1809 if((axis>=0)&&(axis<dimension)) {
1810 //TVectorD const *bins=distribution->GetDistributionBinning(axis);
1811 //Int_t nBin=bins->GetNrows()-1;
1813 Int_t centerBin= axisBins[axis];
1814 axisBins[axis] =centerBin-1;
1815 if(isPeriodic) {
1816 if(HasUnderflow(axis)) {
1817 r +=1;
1818 } else if((axisBins[axis]<0)&&(nMax>=3)) {
1819 axisBins[axis]=nMax-1;
1820 }
1821 }
1822 *prev=ToGlobalBin(axisBins);
1823 if(*prev>=0) {
1824 *distPrev=distribution->GetDistributionBinCenter(axis,axisBins[axis])-
1825 distribution->GetDistributionBinCenter(axis,centerBin);
1826 }
1827 axisBins[axis] =centerBin+1;
1828 if(isPeriodic) {
1829 if(HasOverflow(axis)) {
1830 r +=2;
1831 } else if((axisBins[axis]==nMax)&&(nMax>=3)) {
1832 axisBins[axis]=0;
1833 }
1834 }
1835 *next=ToGlobalBin(axisBins);
1836 if(*next>=0) {
1837 *distNext=distribution->GetDistributionBinCenter(axis,axisBins[axis])-
1838 distribution->GetDistributionBinCenter(axis,centerBin);
1839 }
1840 }
1841 return r;
1842}
1843
1844////////////////////////////////////////////////////////////////////////
1845/// return bit maps indicating underflow and overflow status
1846///
1847/// \param[in] iBin global bin number
1848/// \param[out] uStatus bit map indicating whether the bin is underflow
1849/// \param[out] oStatus bit map indicating whether the bin is overflow
1852{
1855 Int_t dimension=distribution->GetDistributionDimension();
1856 *uStatus=0;
1857 *oStatus=0;
1858 for(Int_t axis=0;axis<dimension;axis++) {
1859 TVectorD const *bins=distribution->GetDistributionBinning(axis);
1860 Int_t nBin=bins->GetNrows()-1;
1861 if(axisBins[axis]<0) *uStatus |= (1<<axis);
1862 if(axisBins[axis]>=nBin) *oStatus |= (1<<axis);
1863 }
1864}
1865
1866////////////////////////////////////////////////////////////////////////
1867/// check whether there are bins but no axis
1872
1873////////////////////////////////////////////////////////////////////////
1874/// return the bin names of unconnected bins
1875///
1876/// \param[in] bin local bin number
1878 TObjString const *r = nullptr;
1879 if(HasUnconnectedBins()) {
1880 if(bin<fAxisLabelList->GetEntriesFast()) {
1881 r = ((TObjString const *)fAxisLabelList->At(bin));
1882 }
1883 }
1884 return r;
1885}
1886
1887
1888////////////////////////////////////////////////////////////////////////
1890/// get average bin size on the specified axis
1891///
1892/// \param[in] axis axis number
1893/// \param[in] includeUnderflow whether to include the underflow bin
1894/// \param[in] includeOverflow whether to include the overflow bin
1896{
1897 Double_t r=0.0;
1898 if((axis>=0)&&(axis<GetDistributionDimension())) {
1899 TVectorD const *bins=GetDistributionBinning(axis);
1900 Double_t d=(*bins)[bins->GetNrows()-1]-(*bins)[0];
1901 Double_t nBins=bins->GetNrows()-1;
1902 if(includeUnderflow && HasUnderflow(axis)) {
1903 Double_t w=GetDistributionUnderflowBinWidth(axis);
1904 if(w>0) {
1905 nBins++;
1906 d += w;
1907 }
1908 }
1909 if(includeOverflow && HasOverflow(axis)) {
1910 Double_t w=GetDistributionOverflowBinWidth(axis);
1911 if(w>0.0) {
1912 nBins++;
1913 d += w;
1914 }
1915 }
1916 if(nBins>0) {
1917 r=d/nBins;
1918 }
1919 } else {
1920 Error("GetDistributionAverageBinSize","axis %d does not exist",axis);
1921 }
1922 return r;
1923}
1924
1925////////////////////////////////////////////////////////////////////////
1926/// return bin width assigned to the underflow bin
1927///
1928/// \param[in] axis axis number
1929///
1930/// the bin width of the first bin is returned.
1931/// The method is virtual, so this behaviour can be adjusted.
1933{
1934 // return width of the underflow bin
1935 // axis: axis number
1936 TVectorD const *bins=GetDistributionBinning(axis);
1937 return (*bins)[1]-(*bins)[0];
1938}
1939
1940////////////////////////////////////////////////////////////////////////
1941/// return bin width assigned to the overflow bin
1942///
1943/// \param[in] axis axis number
1944///
1945/// the bin width of the last bin is returned.
1946/// The method is virtual, so this behaviour can be adjusted.
1948{
1949 // return width of the underflow bin
1950 // axis: axis number
1951 TVectorD const *bins=GetDistributionBinning(axis);
1952 return (*bins)[bins->GetNrows()-1]-(*bins)[bins->GetNrows()-2];
1953}
1954
1955////////////////////////////////////////////////////////////////////////
1956/// return bin center for a given axis and bin number
1957///
1958/// \param[in] axis axis number
1959/// \param[in] bin local bin number on the specified axis
1960///
1961/// returns the geometrical bin center.
1962/// for underflow and overflow, the calculation is using the
1963/// GetDistributionUnderflowBinWidth() and
1964/// GetDistributionOverflowBinWidth() methods.
1966(Int_t axis,Int_t bin) const
1967{
1968 // position of the bin center
1969 // input
1970 // axis : axis number
1971 // bin : bin number on the axis
1972 TVectorD const *bins=GetDistributionBinning(axis);
1973 Double_t r=0.0;
1974 if(bin<0) {
1975 // underflow bin
1976 r=(*bins)[0]-0.5*GetDistributionUnderflowBinWidth(axis);
1977 } else if(bin>=bins->GetNrows()-1) {
1978 // overflow bin
1979 r=(*bins)[bins->GetNrows()-1]+0.5*GetDistributionOverflowBinWidth(axis);
1980 } else {
1981 r=0.5*((*bins)[bin+1]+(*bins)[bin]);
1982 }
1983 return r;
1984}
1985
1986////////////////////////////////////////////////////////////////////////
1987/// get global bin number, given axis bin numbers
1988///
1989/// \param[in] axisBins[] bin numbers on each axis
1990/// \param[out] isBelow indicates bins are in underflow but there is
1991/// no undeflow bin
1992/// \param[out] isAbove indicates bins are in overflow but there is
1993/// no overflow bin
1994///
1995/// return: global bin nuber or -1 if not matched.
1997(Int_t const *axisBins,Int_t *isBelow,Int_t *isAbove) const
1998{
1999 Int_t dimension=GetDistributionDimension();
2000 Int_t r=0;
2001 if(isBelow) *isBelow=0;
2002 if(isAbove) *isAbove=0;
2003 if(dimension>0) {
2004 for(Int_t axis=dimension-1;axis>=0;axis--) {
2006 Int_t i=axisBins[axis];
2007 if(HasUnderflow(axis)) {
2008 nMax +=1;
2009 i +=1;
2010 }
2011 if(HasOverflow(axis)) nMax +=1;
2012 if((i>=0)&&(i<nMax)) {
2013 if(r>=0) r = r*nMax +i;
2014 } else {
2015 r=-1;
2016 if((i<0)&&(isBelow)) *isBelow |= 1<<axis;
2017 if((i>=nMax)&&(isAbove)) *isAbove |= 1<<axis;
2018 }
2019 }
2020 if(r>=0) {
2021 r += GetStartBin();
2022 }
2023 } else {
2025 r=GetStartBin()+axisBins[0];
2026 else
2027 Fatal("ToGlobalBin","bad input %d for dimensionless binning %s %d",
2028 axisBins[0],(const char *)GetName(),
2030 }
2031 return r;
2032}
2033
2034////////////////////////////////////////////////////////////////////////
2035/// return distribution in which the bin is located
2036/// and bin numbers on the corresponding axes
2037///
2038/// \param[in] globalBin global bin number
2039/// \param[out] local bin numbers of the distribution's axes
2040///
2041/// returns the distribution in which the globalBin is located
2042/// or 0 if the globalBin is outside this node and its children
2045{
2046 TUnfoldBinning const *r=nullptr;
2048 TUnfoldBinning const *node;
2049 for(node=GetChildNode();node && !r; node=node->GetNextNode()) {
2051 }
2052 if(!r) {
2053 r=this;
2055 Int_t dimension=GetDistributionDimension();
2056 if(dimension>0) {
2057 for(int axis=0;axis<dimension;axis++) {
2059 axisBins[axis]=0;
2060 if(HasUnderflow(axis)) {
2061 axisBins[axis] =-1;
2062 nMax += 1;
2063 }
2064 if(HasOverflow(axis)) nMax +=1;
2065 axisBins[axis] += i % nMax;
2066 i /= nMax;
2067 }
2068 } else {
2069 axisBins[0]=i;
2070 }
2071 }
2072 }
2073 return r;
2074}
2075
2076////////////////////////////////////////////////////////////////////////
2077/// decode axis steering
2078///
2079/// \param[in] axisSteering the steering to decode
2080/// \param[in] options the allowed options to extract
2081/// \param[out] isOptionGiven array of decoded steering options,
2082/// the dimension equal to the number of
2083/// characters in <b>options</b>
2084///
2085/// the axis steering is given in the form
2086/// "axis[option];axis[option];..."
2087/// <br/> axis : the name of the axis for which the optionlist is relevant
2088/// the character * matches all axes
2089/// <br/>option : a list of characters taken from <b>options</b>
2090/// <br/>for each match the corresponding bit number corresponding to
2091/// the axis number is set in
2092/// <b>isOptionGiven</b>[i], where i is the position of the matching option
2093/// character in <b>options</b>
2095(const char *axisSteering,const char *options,Int_t *isOptionGiven) const
2096{
2097 Int_t nOpt=TString(options).Length();
2098 for(Int_t i=0;i<nOpt;i++) isOptionGiven[i]=0;
2099 if(axisSteering) {
2101 Int_t nPattern=patterns->GetEntries();
2103 for(Int_t i=0;i<nPattern;i++) {
2104 TString const &pattern=((TObjString const *)patterns->At(i))
2105 ->GetString();
2106 Int_t bracketBegin=pattern.Last('[');
2107 Int_t len=pattern.Length();
2108 if((bracketBegin>0)&&(pattern[len-1]==']')) {
2109 TString axisId=pattern(0,bracketBegin);
2110 Int_t mask=0;
2111 if((axisId[0]=='*')&&(axisId.Length()==1)) {
2112 // turn all bins on
2113 mask=(1<<nAxis)-1;
2114 } else {
2115 // if axis is there, turn its bit on
2116 for(Int_t j=0;j<nAxis;j++) {
2117 if(!axisId.CompareTo(GetDistributionAxisLabel(j))) {
2118 mask|= (1<<j);
2119 }
2120 }
2121 }
2122 for(Int_t o=0;o<nOpt;o++) {
2123 if(pattern.Last(options[o])>bracketBegin) {
2124 isOptionGiven[o] |= mask;
2125 }
2126 }
2127 } else {
2128 Error("DecodeAxisSteering",
2129 "steering \"%s\" does not end with [options]",
2130 (const char *)pattern);
2131 }
2132 }
2133 }
2134}
2135
#define d(i)
Definition RSha256.hxx:102
#define c(i)
Definition RSha256.hxx:101
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
static void indent(ostringstream &buf, int indent_level)
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:208
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 mask
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t dest
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 r
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 child
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 winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t UChar_t len
Option_t Option_t TPoint TPoint const char x2
Option_t Option_t TPoint TPoint const char x1
char name[80]
Definition TGX11.cxx:110
TVectorT< Double_t > TVectorD
Definition TVectorDfwd.h:23
Class to manage histogram axis.
Definition TAxis.h:32
const char * GetTitle() const override
Returns title of object.
Definition TAxis.h:137
virtual Double_t GetBinLowEdge(Int_t bin) const
Return low edge of bin.
Definition TAxis.cxx:521
Int_t GetNbins() const
Definition TAxis.h:127
virtual Double_t GetBinUpEdge(Int_t bin) const
Return up edge of bin.
Definition TAxis.cxx:531
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
1-Dim function class
Definition TF1.h:182
1-D histogram with a double per channel (see TH1 documentation)
Definition TH1.h:927
TH1 is the base class of all histogram classes in ROOT.
Definition TH1.h:109
virtual Int_t GetDimension() const
Definition TH1.h:528
virtual Int_t GetBin(Int_t binx, Int_t biny=0, Int_t binz=0) const
Return Global bin number corresponding to binx,y,z.
Definition TH1.cxx:4974
2-D histogram with a double per channel (see TH1 documentation)
Definition TH2.h:356
Service class for 2-D histogram classes.
Definition TH2.h:30
3-D histogram with a double per channel (see TH1 documentation)
Definition TH3.h:371
The TNamed class is the base class for all named ROOT classes.
Definition TNamed.h:29
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
An array of TObjects.
Definition TObjArray.h:31
Int_t GetEntriesFast() const
Definition TObjArray.h:58
Int_t GetEntries() const override
Return the number of objects in array (i.e.
TObject * At(Int_t idx) const override
Definition TObjArray.h:164
void AddLast(TObject *obj) override
Add object in the next empty slot in the array.
Collectable string class.
Definition TObjString.h:28
Mother of all ROOT objects.
Definition TObject.h:41
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1057
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1071
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition TObject.cxx:1099
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:1045
Basic string class.
Definition TString.h:138
Ssiz_t Length() const
Definition TString.h:425
Ssiz_t Last(char c) const
Find last occurrence of a character c.
Definition TString.cxx:938
TObjArray * Tokenize(const TString &delim) const
This function is used to isolate sequential tokens in a TString.
Definition TString.cxx:2270
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:2384
Binning schemes for use with the unfolding algorithm TUnfoldDensity.
void PrintStream(std::ostream &out, Int_t indent=0, int debug=0) const
print some information about this binning tree
Int_t ToGlobalBin(Int_t const *axisBins, Int_t *isBelow=nullptr, Int_t *isAbove=nullptr) const
get global bin number, given axis bin numbers
Bool_t HasOverflow(int axis) const
check whether the axis has an overflow bin
~TUnfoldBinning(void) override
TH1 * CreateHistogram(const char *histogramName, Bool_t originalAxisBinning=kFALSE, Int_t **binMap=nullptr, const char *histogramTitle=nullptr, const char *axisSteering=nullptr) const
create a THxx histogram capable to hold the bins of this binning node and its children
Int_t FillBinMapSingleNode(const TH1 *hist, Int_t startBin, Int_t nDim, const Int_t *axisList, const char *axisSteering, Int_t *binMap) const
fill bin map for a single node
virtual Double_t GetDistributionOverflowBinWidth(Int_t axis) const
return bin width assigned to the overflow bin
Int_t fFirstBin
global bin number of the first bin
void SetBinFactorFunction(Double_t normalisation, TF1 *userFunc=nullptr)
set normalisation factor and function which are used in calls to GetBinFactor()
TH1 * ExtractHistogram(const char *histogramName, const TH1 *globalBins, const TH2 *globalBinsEmatrix=nullptr, Bool_t originalAxisBinning=kTRUE, const char *axisSteering=nullptr) const
Int_t UpdateFirstLastBin(Bool_t startWithRootNode=kTRUE)
update fFirstBin and fLastBin members of this node and its children
TString BuildHistogramTitle(const char *histogramName, const char *histogramTitle, Int_t const *axisList) const
construct a title
Int_t FillBinMapRecursive(Int_t startBin, const char *axisSteering, Int_t *binMap) const
recursively fill bin map
Int_t FillBinMap1D(Int_t *binMap, const char *axisSteering, Int_t firstBinX) const
map all global bins referenced by this node to the one-dimensional histogram destHist,...
TUnfoldBinning * parentNode
mother node
Int_t GetDistributionDimension(void) const
query dimension of this node's distribution
TUnfoldBinning const * GetPrevNode(void) const
previous sister node
void SetBinFactor(Double_t normalisation, TObject *factors)
set normalisation factors which are used in calls to GetBinFactor()
TUnfoldBinning * childNode
first daughter node
TString GetBinName(Int_t iBin) const
get the name of a bin
Int_t GetTH1xNumberOfBins(Bool_t originalAxisBinning=kTRUE, const char *axisSteering=nullptr) const
return the number of histogram bins required when storing this binning in a one-dimensional histogram
virtual Double_t GetDistributionUnderflowBinWidth(Int_t axis) const
return bin width assigned to the underflow bin
Double_t GetBinSize(Int_t iBin) const
get N-dimensional bin size
Int_t GetDistributionNumberOfBins(void) const
number of bins in the distribution possibly including under/overflow
Double_t GetGlobalFactor(void) const
return global scaling factor for this node
Int_t GetGlobalBinNumber(Double_t x) const
locate a bin in a one-dimensional distribution
Bool_t HasUnconnectedBins(void) const
check whether there are bins but no axis
virtual Double_t GetBinFactor(Int_t iBin) const
return scaling factor for the given global bin number
TUnfoldBinning * nextNode
next sister
TObject * fBinFactorFunction
function to calculate a scale factor from bin centres (may be a TF1 or a TVectorD
Int_t GetTHxxBinning(Int_t maxDim, Int_t *axisBins, Int_t *axisList, const char *axisSteering) const
calculate properties of a THxx histogram to store this binning
const TUnfoldBinning * GetNonemptyNode_r(int &count) const
Int_t fHasUnderflow
bit fields indicating whether there are underflow bins on the axes
Int_t GetEndBin(void) const
last+1 bin of this node (includes children)
TObjArray * fAxisLabelList
for each axis its name (TObjString), or names of unconnected bins
Double_t fBinFactorConstant
common scale factor for all bins of this node
TUnfoldBinning const * GetNextNode(void) const
next sister node
Bool_t HasUnderflow(int axis) const
check whether an axis has an underflow bin
Int_t * CreateEmptyBinMap(void) const
create an empty bin map, useful together with the getter methods of class TUnfold and TUnfoldSys
TUnfoldBinning const * GetParentNode(void) const
mother node
@ MAXDIM
maximum numner of axes per distribution
static TH2D * CreateHistogramOfMigrations(TUnfoldBinning const *xAxis, TUnfoldBinning const *yAxis, char const *histogramName, Bool_t originalXAxisBinning=kFALSE, Bool_t originalYAxisBinning=kFALSE, char const *histogramTitle=nullptr)
create a TH2D histogram capable to hold the bins of the two input binning schemes on the x and y axes...
TObjArray * fAxisList
for each axis the bin borders (TVectorD)
Int_t fLastBin
global bin number of the last(+1) bin, including daughters
void GetBinUnderflowOverflowStatus(Int_t iBin, Int_t *uStatus, Int_t *oStatus) const
return bit maps indicating underflow and overflow status
virtual Double_t GetDistributionBinCenter(Int_t axis, Int_t bin) const
return bin center for a given axis and bin number
Int_t fDistributionSize
number of bins in this node's distribution
Int_t fHasOverflow
bit fields indicating whether there are overflow bins on the axes
const TUnfoldBinning * GetNonemptyNode(void) const
find a node which has non-empty distributions if there is none or if there are many,...
void Initialize(Int_t nBins)
initialize variables for a given number of bins
void SetBinMapEntry(Int_t *binMap, Int_t globalBin, Int_t destBin) const
set one entry in a bin map
virtual Double_t GetDistributionAverageBinSize(Int_t axis, Bool_t includeUnderflow, Bool_t includeOverflow) const
get average bin size on the specified axis
void DecodeAxisSteering(const char *axisSteering, const char *options, Int_t *isOptionGiven) const
decode axis steering
virtual Bool_t IsBinFactorGlobal(void) const
check whether there is only a global scaling factor for this node
TString GetDistributionAxisLabel(Int_t axis) const
get name of an axis
TUnfoldBinning * AddBinning(TUnfoldBinning *binning)
add a TUnfoldBinning as the last child of this node
const TObjString * GetUnconnectedBinName(Int_t bin) const
return the bin names of unconnected bins
Int_t GetBinNeighbours(Int_t globalBin, Int_t axis, Int_t *prev, Double_t *distPrev, Int_t *next, Double_t *distNext, Bool_t isPeriodic=kFALSE) const
get neighbour bins along the specified axis
TVectorD const * GetDistributionBinning(Int_t axis) const
get vector of bin borders for one axis
Int_t * CreateBinMap(const TH1 *hist, Int_t nDim, const Int_t *axisList, const char *axisSteering) const
create mapping from global bin number to a histogram for this node
TH2D * CreateErrorMatrixHistogram(const char *histogramName, Bool_t originalAxisBinning, Int_t **binMap=nullptr, const char *histogramTitle=nullptr, const char *axisSteering=nullptr) const
create a TH2D histogram capable to hold a covariance matrix
Bool_t AddAxis(const char *name, Int_t nBins, const Double_t *binBorders, Bool_t hasUnderflow, Bool_t hasOverflow)
add an axis with the specified bin borders
TUnfoldBinning * prevNode
previous sister
TUnfoldBinning const * GetRootNode(void) const
return root node of the binnig scheme
Int_t GetStartBin(void) const
first bin of this node
TUnfoldBinning const * ToAxisBins(Int_t globalBin, Int_t *axisBins) const
return distribution in which the bin is located and bin numbers on the corresponding axes
TUnfoldBinning const * FindNode(char const *name) const
traverse the tree and return the first node which matches the given name
TUnfoldBinning(const char *name=nullptr, Int_t nBins=0, const char *binNames=nullptr)
create a new node without axis
Int_t GetTHxxBinsRecursive(const char *axisSteering) const
calculate number of bins required to store this binning with teh given axisSteering
TUnfoldBinning const * GetChildNode(void) const
first daughter node
Int_t GetTHxxBinningSingleNode(Int_t maxDim, Int_t *axisBins, Int_t *axisList, const char *axisSteering) const
get the properties of a histogram capable to hold the distribution attached to this node
TString BuildHistogramTitle2D(const char *histogramName, const char *histogramTitle, Int_t xAxis, const TUnfoldBinning *yAxisBinning, Int_t yAxis) const
construct a histogram title for a 2D histogram with different binning schemes on x and y axis
Int_t GetNrows() const
Definition TVectorT.h:75
Double_t y[n]
Definition legend1.C:17
Double_t x[n]
Definition legend1.C:17
Int_t Finite(Double_t x)
Check if it is finite with a mask in order to be consistent in presence of fast math.
Definition TMath.h:781
Double_t Sqrt(Double_t x)
Returns the square root of x.
Definition TMath.h:673
LongDouble_t Power(LongDouble_t x, LongDouble_t y)
Returns x raised to the power y.
Definition TMath.h:732