ROOT  6.07/01
Reference Guide
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
TUnfoldBinning.cxx
Go to the documentation of this file.
1 // Author: Stefan Schmitt
2 // DESY, 10/08/11
3 
4 // Version 17.1, in parallel to changes in TUnfold
5 //
6 // History:
7 // Version 17.0, initial version, numbered in parallel to TUnfold
8 
9 /** \class TUnfoldBinning
10  \ingroup Hist
11  This class serves as a container of analysis bins
12  analysis bins are specified by defining the axes of a distribution.
13  It is also possible to have unconnected analysis bins without axis.
14  Multiple TUnfoldBinning objects may be arranged in a tree,
15  such that a full tree structure of histograms and bins is supported
16 
17  If you use this software, please consider the following citation
18  S.Schmitt, JINST 7 (2012) T10003 [arXiv:1205.6201]
19 
20  More documentation and updates are available on
21  http://www.desy.de/~sschmitt
22 
23  Functionality
24 
25  The class gives access to all analysis bins numbered in sequence.
26  Such a sequence of bins may be stored in a 1-dimension histogram.
27  Correlations between two TUnfoldBinning objects may be stored in
28  a 2-dimensional histogram. This type of ordering is required for
29  the TUnfold class.
30 
31  In addition, it is possible to have root histograms, using the
32  axes as defined with the distributions. Underflow/overflow bins
33  can be included or excluded when mapping bins on root histograms.
34  In addition, it is possible to collapse one of more axes when going
35  from a N-dimensional distribution to a root histogram.
36 */
37 
38 /*
39  This file is part of TUnfold.
40 
41  TUnfold is free software: you can redistribute it and/or modify
42  it under the terms of the GNU General Public License as published by
43  the Free Software Foundation, either version 3 of the License, or
44  (at your option) any later version.
45 
46  TUnfold is distributed in the hope that it will be useful,
47  but WITHOUT ANY WARRANTY; without even the implied warranty of
48  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
49  GNU General Public License for more details.
50 
51  You should have received a copy of the GNU General Public License
52  along with TUnfold. If not, see <http://www.gnu.org/licenses/>.
53  */
54 
55 
56 #include "TUnfoldBinning.h"
57 #include <TVectorD.h>
58 #include <TAxis.h>
59 #include <TString.h>
60 #include <iostream>
61 #include <fstream>
62 #include <TMath.h>
63 #include <TF1.h>
64 #include <TH1D.h>
65 #include <TH2D.h>
66 #include <TH3D.h>
67 #include <TList.h>
68 #include <TIterator.h>
69 
70 // #define DEBUG
71 
72 using namespace std;
73 
75 
76 /********************* setup **************************/
77 
79 {
80  // initialize variables
81  parentNode=0;
82  childNode=0;
83  nextNode=0;
84  prevNode=0;
85  fAxisList=new TObjArray();
86  fAxisLabelList=new TObjArray();
87  fAxisList->SetOwner();
88  fAxisLabelList->SetOwner();
89  fHasUnderflow=0;
90  fHasOverflow=0;
91  fDistributionSize=nBins;
92  fBinFactorFunction=0;
93  fBinFactorConstant=1.0;
94 }
95 
97 {
98  // update fFirstBin and fLastBin members of this node and its children
99  // startWithRootNode: if true, start the update with the root node
100  if(startWithRootNode) {
101  return GetRootNode()->UpdateFirstLastBin(kFALSE);
102  }
103  if(GetPrevNode()) {
104  // if this is not the first node in a sequence,
105  // start with the end bin of the previous node
106  fFirstBin=GetPrevNode()->GetEndBin();
107  } else if(GetParentNode()) {
108  // if this is the first node in a sequence but has a parent,
109  // start with the end bin of the parent's distribution
110  fFirstBin=GetParentNode()->GetStartBin()+
111  GetParentNode()->GetDistributionNumberOfBins();
112  } else {
113  // if this is the top level node, the first bin number is 1
114  fFirstBin=1;
115  // ... unless the top level node is the only node
116  // ... with dimension=1
117  // ... and there are no child nodes
118  // ... and there is an underflow bin
119  if((!GetChildNode())&&(GetDistributionDimension()==1)&&
120  (fHasUnderflow==1)) {
121  fFirstBin=0;
122  }
123  }
124  fLastBin=fFirstBin+fDistributionSize;
125  // now update count for all children
126  for(TUnfoldBinning *node=childNode;node;node=node->nextNode) {
127  fLastBin=node->UpdateFirstLastBin(kFALSE);
128  }
129  return fLastBin;
130 }
131 
133 (const char *name,Int_t nBins,const char *binNames)
134 : TNamed(name ? name : "",name ? name : "")
135 {
136  // initialize a node with bins but without axis
137  // name: name of the node
138  // nBin: number of extra bins (could be zero)
139  // binNames: (optionally) names of the bins sepatared by ';'
140  Initialize(nBins);
141  if(binNames) {
142  TString nameString(binNames);
143  delete fAxisLabelList;
144  fAxisLabelList=nameString.Tokenize(";");
145  }
146  UpdateFirstLastBin();
147 }
148 
150 (const TAxis &axis,Int_t includeUnderflow,Int_t includeOverflow)
151 : TNamed(axis.GetName(),axis.GetTitle())
152 {
153  // create binning containing a distribution with one axis
154  // axis: the axis to represent
155  // includeUnderflow: include underflow bin
156  // includeOverflow: include overflow bin
157  Initialize(0);
158  AddAxis(axis,includeUnderflow,includeOverflow);
159  UpdateFirstLastBin();
160 }
161 
163 {
164  // delete all children
165  if(childNode) delete childNode;
166  // remove this node from the tree
167  if(GetParentNode() && (GetParentNode()->GetChildNode()==this)) {
168  parentNode->childNode=nextNode;
169  }
170  if(GetPrevNode()) prevNode->nextNode=nextNode;
171  if(GetNextNode()) nextNode->prevNode=prevNode;
172  delete fAxisList;
173  delete fAxisLabelList;
174 }
175 
177 (const char *name,Int_t nBins,const char *binNames)
178 {
179  // add a binning as last daughter to this tree
180  // name: name of the node
181  // nBin: number of bins not belonging to a distribution (usually zero)
182  // binNames: (optionally) names of these bins sepatared by ';'
183  return AddBinning(new TUnfoldBinning(name,nBins,binNames));
184 }
185 
187 {
188  // add a binning as last daughter to this tree
189  // binning: pointer to the new binning
190  // return value: if succeeded, return "binning"
191  // otherwise return 0
192  TUnfoldBinning *r=0;
193  if(binning->GetParentNode()) {
194  Error("binning \"%s\" already has parent \"%s\", can not be added to %s",
195  (char *)binning->GetName(),
196  (char *)binning->GetParentNode()->GetName(),
197  (char *)GetName());
198  } else if(binning->GetPrevNode()) {
199  Error("binning \"%s\" has previous node \"%s\", can not be added to %s",
200  (char *)binning->GetName(),
201  (char *)binning->GetPrevNode()->GetName(),
202  (char *)GetName());
203  } else if(binning->GetNextNode()) {
204  Error("binning \"%s\" has next node \"%s\", can not be added to %s",
205  (char *)binning->GetName(),
206  (char *)binning->GetNextNode()->GetName(),
207  (char *)GetName());
208  } else {
209  r=binning;
210  binning->parentNode=this;
211  if(childNode) {
212  TUnfoldBinning *child=childNode;
213  // find last child
214  while(child->nextNode) {
215  child=child->nextNode;
216  }
217  // add as last child
218  child->nextNode=r;
219  r->prevNode=child;
220  } else {
221  childNode=r;
222  }
223  UpdateFirstLastBin();
224  r=binning;
225  }
226  return r;
227 }
228 
230 (const char *name,Int_t nBin,Double_t xMin,Double_t xMax,
231  Bool_t hasUnderflow,Bool_t hasOverflow)
232 {
233  // add an axis with equidistant bins to the distribution
234  // name: name of the axis
235  // nBin: number of bins
236  // xMin: lower edge of the first bin
237  // xMax: upper edge of the last bin
238  // hasUnderflow: decide whether the axis has an underflow bin
239  // hasOverflow: decide whether the axis has an overflow bin
240  // return: true if the axis has been added
241  Bool_t r=kFALSE;
242  if(nBin<=0) {
243  Fatal("AddAxis","number of bins %d is not positive",
244  nBin);
245  } else if((!TMath::Finite(xMin))||(!TMath::Finite(xMax))||
246  (xMin>=xMax)) {
247  Fatal("AddAxis","xmin=%f required to be smaller than xmax=%f",
248  xMin,xMax);
249  } else {
250  Double_t *binBorders=new Double_t[nBin+1];
251  Double_t x=xMin;
252  Double_t dx=(xMax-xMin)/nBin;
253  for(Int_t i=0;i<=nBin;i++) {
254  binBorders[i]=x+i*dx;
255  }
256  r=AddAxis(name,nBin,binBorders,hasUnderflow,hasOverflow);
257  delete [] binBorders;
258  }
259  return r;
260 }
261 
263 (const TAxis &axis,Bool_t hasUnderflow,Bool_t hasOverflow)
264 {
265  // add an axis to the distribution
266  // axis: the axis
267  // hasUnderflow: decide whether the underflow bin should be included
268  // hasOverflow: decide whether the overflow bin should be included
269  // return: true if the axis has been added
270  //
271  // Note: axis labels are not imported
272  Int_t nBin=axis.GetNbins();
273  Double_t *binBorders=new Double_t[nBin+1];
274  for(Int_t i=0;i<nBin;i++) {
275  binBorders[i]=axis.GetBinLowEdge(i+1);
276  }
277  binBorders[nBin]=axis.GetBinUpEdge(nBin);
278  Bool_t r=AddAxis(axis.GetTitle(),nBin,binBorders,hasUnderflow,hasOverflow);
279  delete [] binBorders;
280  return r;
281 }
282 
284 (const char *name,Int_t nBin,const Double_t *binBorders,
285  Bool_t hasUnderflow,Bool_t hasOverflow)
286 {
287  // add an axis with the specified bin borders to the distribution
288  // name: name of the axis
289  // nBin: number of bins
290  // binBorders: array of bin borders, with nBin+1 elements
291  // hasUnderflow: decide whether the axis has an underflow bin
292  // hasOverflow: decide whether the axis has an overflow bin
293  Bool_t r=kFALSE;
294  if(HasUnconnectedBins()) {
295  Fatal("AddAxis","node already has %d bins without axis",
296  GetDistributionNumberOfBins());
297  } else if(nBin<=0) {
298  Fatal("AddAxis","number of bins %d is not positive",
299  nBin);
300  } else {
301  TVectorD *bins=new TVectorD(nBin+1);
302  r=kTRUE;
303  for(Int_t i=0;i<=nBin;i++) {
304  (*bins)(i)=binBorders[i];
305  if(!TMath::Finite((*bins)(i))) {
306  Fatal("AddAxis","bin border %d is not finite",i);
307  r=kFALSE;
308  } else if((i>0)&&((*bins)(i)<=(*bins)(i-1))) {
309  Fatal("AddAxis","bins not in order x[%d]=%f <= %f=x[%d]",
310  i,(*bins)(i),(*bins)(i-1),i-1);
311  r=kFALSE;
312  }
313  }
314  if(r) {
315  Int_t axis=fAxisList->GetEntriesFast();
316  Int_t bitMask=1<<axis;
317  Int_t nBinUO=nBin;
318  if(hasUnderflow) {
319  fHasUnderflow |= bitMask;
320  nBinUO++;
321  } else {
322  fHasUnderflow &= ~bitMask;
323  }
324  if(hasOverflow) {
325  fHasOverflow |= bitMask;
326  nBinUO++;
327  } else {
328  fHasOverflow &= ~bitMask;
329  }
330  fAxisList->AddLast(bins);
331  fAxisLabelList->AddLast(new TObjString(name));
332  if(!fDistributionSize) fDistributionSize=1;
333  fDistributionSize *= nBinUO;
334  UpdateFirstLastBin();
335  }
336  }
337  return r;
338 }
339 
341 {
342  // print some information about this binning tree
343  // out: stream to write to
344  // indent: initial indentation (sub-trees have indent+1)
345  for(Int_t i=0;i<indent;i++) out<<" ";
346  out<<"TUnfoldBinning \""<<GetName()<<"\" has ";
347  Int_t nBin=GetEndBin()-GetStartBin();
348  if(nBin==1) {
349  out<<"1 bin";
350  } else {
351  out<<nBin<<" bins";
352  }
353  out<<" ["
354  <<GetStartBin()<<","<<GetEndBin()<<"] nTH1x="
355  <<GetTH1xNumberOfBins()
356  <<"\n";
357  if(GetDistributionNumberOfBins()) {
358  for(Int_t i=0;i<indent;i++) out<<" ";
359  out<<" distribution: "<<GetDistributionNumberOfBins()<<" bins\n";
360  if(fAxisList->GetEntriesFast()) {
361  /* for(Int_t i=0;i<indent;i++) out<<" ";
362  out<<" axes:\n"; */
363  for(Int_t axis=0;axis<GetDistributionDimension();axis++) {
364  for(Int_t i=0;i<indent;i++) out<<" ";
365  out<<" \""
366  <<GetDistributionAxisLabel(axis)
367  <<"\" nbin="<<GetDistributionBinning(axis)->GetNrows()-1;
368  if(fHasUnderflow & (1<<axis)) out<<" plus underflow";
369  if(fHasOverflow & (1<<axis)) out<<" plus overflow";
370  out<<"\n";
371  }
372  } else {
373  for(Int_t i=0;i<indent;i++) out<<" ";
374  out<<" no axis\n";
375  for(Int_t i=0;i<indent;i++) out<<" ";
376  out<<" names: ";
377  for(Int_t ibin=0;(ibin<GetDistributionNumberOfBins())&&
378  (ibin<fAxisLabelList->GetEntriesFast());ibin++) {
379  if(ibin) out<<";";
380  if(GetDistributionAxisLabel(ibin)) {
381  out<<GetDistributionAxisLabel(ibin);
382  }
383  }
384  out<<"\n";
385  }
386  }
387  TUnfoldBinning const *child=GetChildNode();
388  if(child) {
389  while(child) {
390  child->PrintStream(out,indent+1);
391  child=child->GetNextNode();
392  }
393  }
394 }
395 
396 /********************* Navigation **********************/
397 
398 TUnfoldBinning const *TUnfoldBinning::FindNode(char const *name) const
399 {
400  // parse the tree and return a node with the given name
401  // name: the name of the node to find
402  TUnfoldBinning const *r=0;
403  if((!name)||(!TString(GetName()).CompareTo(name))) {
404  r=this;
405  }
406  for(TUnfoldBinning const *child=GetChildNode();
407  (!r) && child;child=child->GetNextNode()) {
408  r=child->FindNode(name);
409  }
410  return r;
411 }
412 
414 {
415  // return root node
416  TUnfoldBinning *node=this;
417  while(node->GetParentNode()) node=node->parentNode;
418  return node;
419 }
420 
422 {
423  // return root node
424  TUnfoldBinning const *node=this;
425  while(node->GetParentNode()) node=node->GetParentNode();
426  return node;
427 }
428 
429 /********************* Create THxx histograms **********/
430 
432 (const char *histogramName,const char *histogramTitle,Int_t const *axisList)
433 const
434 {
435  // build a title
436  // input:
437  // histogramTitle : if this is non-zero, use that title
438  // otherwise:
439  // title=histogramName[;x[;y[;z]]]
440  // ?Axis : -2 stop adding text to the title
441  // -1 add name of this node
442  // >=0 use name of the corresponding axis
443  TString r;
444  if(histogramTitle) {
445  r=histogramTitle;
446  } else {
447  r=histogramName;
448  Int_t iEnd;
449  for(iEnd=2;iEnd>0;iEnd--) {
450  if(axisList[iEnd]>=0) break;
451  }
452  for(Int_t i=0;i<=iEnd;i++) {
453  r += ";";
454  if(axisList[i]<0) {
455  r += GetName();
456  } else {
457  r += GetNonemptyNode()->GetDistributionAxisLabel(axisList[i]);
458  }
459  }
460  }
461  return r;
462 }
463 
465 (const char *histogramName,const char *histogramTitle,
466  Int_t xAxis,const TUnfoldBinning *yAxisBinning,Int_t yAxis) const
467 {
468  // build a title
469  // input:
470  // histogramTitle : if this is non-zero, use that title
471  // otherwise:
472  // title=histogramName;x;y
473  // xAxis : -1 no title for this axis
474  // >=0 use name of the corresponding axis
475  TString r;
476  if(histogramTitle) {
477  r=histogramTitle;
478  } else {
479  r=histogramName;
480  r += ";";
481  if(xAxis==-1) {
482  r += GetName();
483  } else if(xAxis>=0) {
484  r += GetNonemptyNode()->GetDistributionAxisLabel(xAxis);
485  }
486  r+= ";";
487  if(yAxis==-1) {
488  r += yAxisBinning->GetName();
489  } else if(yAxis>=0) {
490  r += yAxisBinning->GetNonemptyNode()->GetDistributionAxisLabel(yAxis);
491  }
492 
493  }
494  return r;
495 }
496 
498 (Bool_t originalAxisBinning,const char *axisSteering) const
499 {
500  // return the number of histogram bins required when storing
501  // this binning in a one-dimensional histogram
502  // originalAxisBinning : try to preserve the axis binning,
503  // if this binning is 1-dimensional then the
504  // underflow/overflow are stored in the
505  // corresponding bins of the TH1 and
506  // axisSteering:
507  // "pattern1;pattern2;...;patternN"
508  // patternI = axis[mode]
509  // axis = name or *
510  // mode = C|U|O
511  // C: collapse axis into one bin
512  // U: discarde underflow bin
513  // O: discarde overflow bin
514  // return: number of bins of the TH1 (underflow/overflow are not counted)
515  Int_t axisBins[3],axisList[3];
516  GetTHxxBinning(originalAxisBinning ? 1 : 0,axisBins,axisList,
517  axisSteering);
518  return axisBins[0];
519 }
520 
522 (const char *histogramName,Bool_t originalAxisBinning,Int_t **binMap,
523  const char *histogramTitle,const char *axisSteering) const
524 {
525  // create a THxx histogram capable to hold the bins of this binning
526  // scheme and its children
527  // input:
528  // histogramName: name of the histogram which is created
529  // originalAxisBinning : try to preserve the axis binning
530  // if this parameter is true, the resulting
531  // histogram has bin widths and histogram
532  // dimension (TH1D, TH2D, TH3D)
533  // in parallel to the binning scheme
534  // (if possible)
535  // binMap : mapping of global bins to histogram bins
536  // see method CreateBinMap()
537  // if(binMap==0), no binMap is created
538  // histogramTitle: if this is non-zero, it is taken as histogram title
539  // otherwise, the title is created automatically
540  // axisSteering:
541  // "pattern1;pattern2;...;patternN"
542  // patternI = axis[mode]
543  // axis = name or *
544  // mode = C|U|O
545  // C: collapse axis into one bin
546  // U: discarde underflow bin
547  // O: discarde overflow bin
548  // returns: a new histogram (TH1D, TH2D or TH3D)
549  Int_t nBin[3],axisList[3];
550  Int_t nDim=GetTHxxBinning(originalAxisBinning ? 3 : 0,nBin,axisList,
551  axisSteering);
552  const TUnfoldBinning *neNode=GetNonemptyNode();
553  TString title=BuildHistogramTitle(histogramName,histogramTitle,axisList);
554  TH1 *r=0;
555  if(nDim>0) {
556  const TVectorD *axisBinsX=
557  neNode->GetDistributionBinning(axisList[0]);
558  if(nDim>1) {
559  const TVectorD *axisBinsY=
560  neNode->GetDistributionBinning(axisList[1]);
561  if(nDim>2) {
562  const TVectorD *axisBinsZ=
563  neNode->GetDistributionBinning(axisList[2]);
564  r=new TH3D(histogramName,title,
565  nBin[0],axisBinsX->GetMatrixArray(),
566  nBin[1],axisBinsY->GetMatrixArray(),
567  nBin[2],axisBinsZ->GetMatrixArray());
568  } else {
569  r=new TH2D(histogramName,title,
570  nBin[0],axisBinsX->GetMatrixArray(),
571  nBin[1],axisBinsY->GetMatrixArray());
572  }
573  } else {
574  r=new TH1D(histogramName,title,nBin[0],axisBinsX->GetMatrixArray());
575  }
576  } else {
577  if(originalAxisBinning) {
578  Warning("CreateHistogram",
579  "Original binning can not be represented as THxx");
580  }
581  r=new TH1D(histogramName,title,nBin[0],0.5,nBin[0]+0.5);
582  nDim=0;
583  }
584  if(binMap) {
585  *binMap=CreateBinMap(r,nDim,axisList,axisSteering);
586  }
587  return r;
588 }
589 
591 (const char *histogramName,Bool_t originalAxisBinning,Int_t **binMap,
592  const char *histogramTitle,const char *axisSteering) const
593 {
594  // create a TH2D histogram capable to hold an error matrix
595  // coresponding to the bins of this binning scheme and its children
596  // input:
597  // histogramName: name of the histogram which is created
598  // originalAxisBinning : try to preserve the axis binning
599  // if this parameter is true, the resulting
600  // histogram has bin widths
601  // in parallel to this binning scheme
602  // (if possible)
603  // binMap : mapping of global bins to histogram bins
604  // see method CreateBinMap()
605  // if(binMap==0), no binMap is created
606  // histogramTitle: if this is non-zero, it is taken as histogram title
607  // otherwise, the title is created automatically
608  // axisSteering:
609  // "pattern1;pattern2;...;patternN"
610  // patternI = axis[mode]
611  // axis = name or *
612  // mode = C|U|O
613  // C: collapse axis into one bin
614  // U: discarde underflow bin
615  // O: discarde overflow bin
616  // returns: a new TH2D
617 
618  Int_t nBin[3],axisList[3];
619  Int_t nDim=GetTHxxBinning(originalAxisBinning ? 1 : 0,nBin,axisList,
620  axisSteering);
621  TString title=BuildHistogramTitle(histogramName,histogramTitle,axisList);
622  TH2D *r=0;
623  if(nDim==1) {
624  const TVectorD *axisBinsX=(TVectorD const *)
625  GetNonemptyNode()->fAxisList->At(axisList[0]);
626  r=new TH2D(histogramName,title,nBin[0],axisBinsX->GetMatrixArray(),
627  nBin[0],axisBinsX->GetMatrixArray());
628  } else {
629  if(originalAxisBinning) {
630  Info("CreateErrorMatrixHistogram",
631  "Original binning can not be represented on one axis");
632  }
633  r=new TH2D(histogramName,title,nBin[0],0.5,nBin[0]+0.5,
634  nBin[0],0.5,nBin[0]+0.5);
635  nDim=0;
636  }
637  if(binMap) {
638  *binMap=CreateBinMap(r,nDim,axisList,axisSteering);
639  }
640  return r;
641 }
642 
644 (TUnfoldBinning const *xAxis,TUnfoldBinning const *yAxis,
645  char const *histogramName,Bool_t originalXAxisBinning,
646  Bool_t originalYAxisBinning,char const *histogramTitle)
647 {
648  // create a TH2D histogram capable to hold the bins of the two
649  // input binning schemes on the x and y axes, respectively
650  // input:
651  // histogramName: name of the histogram which is created
652  // xAxis: binning scheme for the x axis
653  // yAxis: binning scheme for the y axis
654  // originalXAxisBinning: preserve x-axis bin widths if possible
655  // originalXAxisBinning: preserve y-axis bin widths if possible
656  // histogramTitle: if this is non-zero, it is taken as histogram title
657  // otherwise, the title is created automatically
658  // returns: a new TH2D
659 
660  Int_t nBinX[3],axisListX[3];
661  Int_t nDimX=
662  xAxis->GetTHxxBinning(originalXAxisBinning ? 1 : 0,nBinX,axisListX,0);
663  Int_t nBinY[3],axisListY[3];
664  Int_t nDimY=
665  yAxis->GetTHxxBinning(originalYAxisBinning ? 1 : 0,nBinY,axisListY,0);
667  (histogramName,histogramTitle,axisListX[0],yAxis,axisListY[0]);
668  if(nDimX==1) {
669  const TVectorD *axisBinsX=(TVectorD const *)
670  xAxis->fAxisList->At(axisListX[0]);
671  if(nDimY==1) {
672  const TVectorD *axisBinsY=(TVectorD const *)
673  yAxis->fAxisList->At(axisListY[0]);
674  return new TH2D(histogramName,title,
675  nBinX[0],axisBinsX->GetMatrixArray(),
676  nBinY[0],axisBinsY->GetMatrixArray());
677  } else {
678  return new TH2D(histogramName,title,
679  nBinX[0],axisBinsX->GetMatrixArray(),
680  nBinY[0],0.5,0.5+nBinY[0]);
681  }
682  } else {
683  if(nDimY==1) {
684  const TVectorD *axisBinsY=(TVectorD const *)
685  yAxis->fAxisList->At(axisListY[0]);
686  return new TH2D(histogramName,title,
687  nBinX[0],0.5,0.5+nBinX[0],
688  nBinY[0],axisBinsY->GetMatrixArray());
689  } else {
690  return new TH2D(histogramName,title,
691  nBinX[0],0.5,0.5+nBinX[0],
692  nBinY[0],0.5,0.5+nBinY[0]);
693  }
694  }
695 }
696 
698 (Int_t maxDim,Int_t *axisBins,Int_t *axisList,
699  const char *axisSteering) const
700 {
701  // calculate properties of a THxx histogram to store this binning
702  // input:
703  // maxDim : maximum dimension of the THxx (0 or 1..3)
704  // maxDim==0 is used to indicate that the histogram should be
705  // 1-dimensional with all bins mapped on one axis,
706  // bin centers equal to bin numbers
707  // axisSteering:
708  // "pattern1;pattern2;...;patternN"
709  // patternI = axis[mode]
710  // axis = name or *
711  // mode = C|U|O
712  // C: collapse axis into one bin
713  // U: discarde underflow bin
714  // O: discarde overflow bin
715  // output;
716  // axisBins[0..2] : number of bins on the THxx axes [0]:x [1]:y [2]:z
717  // axisList[0..2] : TUnfoldBinning axis number corresponding to TH1 axis
718  // [0]:x [1]:y [2]:z
719  // return value : 1-3: dimension of THxx
720  // 0 : use 1-dim THxx, binning structure is not preserved
721  for(Int_t i=0;i<3;i++) {
722  axisBins[i]=0;
723  axisList[i]=-1;
724  }
725  const TUnfoldBinning *theNode=GetNonemptyNode();
726  if(theNode) {
727  return theNode->GetTHxxBinningSingleNode
728  (maxDim,axisBins,axisList,axisSteering);
729  } else {
730  axisBins[0]=GetTHxxBinsRecursive(axisSteering);
731  return 0;
732  }
733 }
734 
736 {
737  // get the node which has non-empty distributions
738  // if there is none or if there are many, return zero
739  const TUnfoldBinning *r=GetDistributionNumberOfBins()>0 ? this : 0;
740  for(TUnfoldBinning const *child=GetChildNode();child;
741  child=child->GetNextNode()) {
742  const TUnfoldBinning *c=child->GetNonemptyNode();
743  if(!r) {
744  // new candidate found
745  r=c;
746  } else {
747  if(c) {
748  // multiple nodes found
749  r=0;
750  break;
751  }
752  }
753  }
754  return r;
755 }
756 
758 (Int_t maxDim,Int_t *axisBins,Int_t *axisList,const char *axisSteering) const
759 {
760  // get the properties of a histogram capable to hold the distribution
761  // of this node
762  // input:
763  // maxDim : maximum dimension of the THxx (0 or 1..3)
764  // maxDim==0 is used to indicate that the histogram should be
765  // 1-dimensional with all bins mapped on one axis
766  // axisSteering :
767  // "pattern1;pattern2;...;patternN"
768  // patternI = axis[mode]
769  // axis = name or *
770  // mode = C|U|O
771  // C: collapse axis into one bin
772  // U: discarde underflow bin
773  // O: discarde overflow bin
774  // input/output:
775  // axisBins[0..2] : cumulated number of bins on the THxx axes
776  // [0]:x [1]:y [2]:z
777  // axisList[0..2] : TUnfoldBinning axis number corresponding to TH1 axis
778  // [0]:x [1]:y [2]:z
779  // return value : 1-3: dimension of THxx
780  // 0 : use 1-dim THxx, binning structure is not preserved
781 
782 
783  // decode axisSteering
784  // isOptionGiven[0] ('C'): bit vector which axes to collapse
785  // isOptionGiven[1] ('U'): bit vector to discarde underflow bins
786  // isOptionGiven[2] ('U'): bit vector to discarde overflow bins
787  Int_t isOptionGiven[3] = { 0 };
788  DecodeAxisSteering(axisSteering,"CUO",isOptionGiven);
789  // count number of axes after projecting
790  Int_t numDimension=GetDistributionDimension();
791  Int_t r=0;
792  for(Int_t i=0;i<numDimension;i++) {
793  if(isOptionGiven[0] & (1<<i)) continue;
794  r++;
795  }
796  if((r>0)&&(r<=maxDim)) {
797  // 0<r<=maxDim
798  //
799  // -> preserve the original binning
800  // axisList[] and axisBins[] are overwritten
801  r=0;
802  for(Int_t i=0;i<numDimension;i++) {
803  if(isOptionGiven[0] & (1<<i)) continue;
804  axisList[r]=i;
805  axisBins[r]=GetDistributionBinning(i)->GetNrows()-1;
806  r++;
807  }
808  } else {
809  // map everything on one axis
810  // axisBins[0] is the number of bins
811  if(HasUnconnectedBins() || (GetDistributionNumberOfBins()<=0)) {
812  axisBins[0] = GetDistributionNumberOfBins();
813  } else {
814  Int_t nBin=1;
815  for(Int_t i=0;i<numDimension;i++) {
816  Int_t mask=(1<<i);
817  if(isOptionGiven[0] & mask) continue;
818  Int_t nBinI=GetDistributionBinning(i)->GetNrows()-1;
819  if((fHasUnderflow & mask)&& !(isOptionGiven[1] & mask)) nBinI++;
820  if((fHasOverflow & mask)&& !(isOptionGiven[2] & mask)) nBinI++;
821  nBin *= nBinI;
822  }
823  axisBins[0] = nBin;
824  }
825  r=0;
826  }
827  return r;
828 }
829 
830 Int_t TUnfoldBinning::GetTHxxBinsRecursive(const char *axisSteering) const
831 {
832  // input:
833  // axisSteering :
834  // "pattern1;pattern2;...;patternN"
835  // patternI = axis[mode]
836  // axis = name or *
837  // mode = C|U|O
838  // C: collapse axis into one bin
839  // U: discarde underflow bin
840  // O: discarde overflow bin
841  // output:
842  // binMap[] : map global bin numbers to histogram bins
843  // return value : number of bins
844 
845  Int_t r=0;
846  for(TUnfoldBinning const *child=GetChildNode();child;
847  child=child->GetNextNode()) {
848  r +=child->GetTHxxBinsRecursive(axisSteering);
849  }
850  // here: process distribution of this node
851  Int_t axisBins[3] = {0}, axisList[3] = {0};
852  GetTHxxBinningSingleNode(0,axisBins,axisList,axisSteering);
853  r += axisBins[0];
854  return r;
855 }
856 
858 (const TH1 *hist,Int_t nDim,const Int_t *axisList,const char *axisSteering)
859 const
860 {
861  // create mapping from global bin number to a histogram for this node
862  // global bins are the bins of the root node binning scheme
863  // when projecting them on a TH1 histogram "hRootNode" without special
864  // axis steering and without attempting to preserve the axis binnings
865  //
866  // The bin map is an array of size hRootNode->GetNbinsX()+2
867  // For each bin of the "hRootNode" histogram it holds the target bin in
868  // "hist" or the number -1 if the corresponding "hRootNode" bin is not
869  // represented in "hist"
870  //
871  // input
872  // hist : the histogram (to calculate root bin numbers)
873  // nDim : target dimension of the TUnfoldBinning
874  // if(nDim==0) all bins are mapped linearly
875  // axisSteering:
876  // "pattern1;pattern2;...;patternN"
877  // patternI = axis[mode]
878  // axis = name or *
879  // mode = C|U|O
880  // C: collapse axis into one bin
881  // U: discarde underflow bin
882  // O: discarde overflow bin
883  //
884  // input used only if nDim>0:
885  // axisList : for each THxx axis give the TUnfoldBinning axis number
886  //
887  // return value:
888  // an new array which holds the bin mapping
889  // r[0] : to which THxx bin to map global bin number 0
890  // r[1] : to which THxx bin to map global bin number 1
891  // ...
892  // r[nmax]
893  // where nmax=GetRootNode()->GetEndBin()+1
894  Int_t nMax=GetRootNode()->GetEndBin()+1;
895  Int_t *r=new Int_t[nMax];
896  for(Int_t i=0;i<nMax;i++) {
897  r[i]=-1;
898  }
899  Int_t startBin=GetRootNode()->GetStartBin();
900  if(nDim>0) {
901  const TUnfoldBinning *nonemptyNode=GetNonemptyNode();
902  if(nonemptyNode) {
903  FillBinMapSingleNode(hist,startBin,nDim,axisList,axisSteering,r);
904  } else {
905  Fatal("CreateBinMap","called with nDim=%d but GetNonemptyNode()=0",
906  nDim);
907  }
908  } else {
909  FillBinMapRecursive(startBin,axisSteering,r);
910  }
911  return r;
912 }
913 
915 (Int_t startBin,const char *axisSteering,Int_t *binMap) const
916 {
917  // fill bin map recursively
918  // input
919  // startBin : first histogram bin
920  // axisSteering : specify how to project the axes
921  // binMap : the bin mapping which is to be filled
922  //
923  // the positions
924  // binMap[GetStartBin()]
925  // ..
926  // binMap[GetEndBin()-1]
927  // are filled
928  //
929  Int_t nbin=0;
930  nbin = FillBinMapSingleNode(0,startBin,0,0,axisSteering,binMap);
931  for(TUnfoldBinning const *child=GetChildNode();child;
932  child=child->GetNextNode()) {
933  nbin += child->FillBinMapRecursive(startBin+nbin,axisSteering,binMap);
934  }
935  return nbin;
936 }
937 
939 (const TH1 *hist,Int_t startBin,Int_t nDim,const Int_t *axisList,
940  const char *axisSteering,Int_t *binMap) const
941 {
942  // fill bin map for a single node
943  // input:
944  // hist: the histogram represeinthing this node (used if nDim>0)
945  // startBin: start bin in the bin map
946  // nDim:
947  // 0: bins are mapped in linear order, ignore hist and axisList
948  // nDim=hist->GetDimension():
949  // bins are mapped to "hist" bin numbers
950  // the corresponding TUnfoldBinning axes are taken from axisList[]
951  // nDim=1 and hist->GetDimension()>1:
952  // bins are mapped to th x-axis of "hist"
953  // the corresponding TUnfoldBinning axis is taken from axisList[0]
954  // axisList[]:
955  // TUnfoldBinning axis numbers corresponding to the
956  // x[0], y[1], z[2] axes of "hist"
957  // axisSteering:
958  // "pattern1;pattern2;...;patternN"
959  // patternI = axis[mode]
960  // axis = name or *
961  // mode = C|U|O
962  // C: collapse axis into one bin
963  // U: discarde underflow bin
964  // O: discarde overflow bin
965  // binMap: the bin map to fill
966  // return value:
967  // the number of bins mapped
968  // (only relevant if nDim==0)
969  // first, decode axisSteering
970  // isOptionGiven[0] ('C'): bit vector which axes to collapse
971  // isOptionGiven[1] ('U'): bit vector to discarde underflow bins
972  // isOptionGiven[2] ('U'): bit vector to discarde overflow bins
973  Int_t isOptionGiven[3] = {0};
974  DecodeAxisSteering(axisSteering,"CUO",isOptionGiven);
975  Int_t axisBins[MAXDIM] = {0};
976  Int_t dimension=GetDistributionDimension();
977  Int_t axisNbin[MAXDIM] = {0};
978  for(Int_t i=0;i<dimension;i++) {
979  const TVectorD *binning=GetDistributionBinning(i);
980  axisNbin[i]=binning->GetNrows()-1;
981  };
982  for(Int_t i=0;i<GetDistributionNumberOfBins();i++) {
983  Int_t globalBin=GetStartBin()+i;
984  const TUnfoldBinning *dest=ToAxisBins(globalBin,axisBins);
985  if(dest!=this) {
986  if(!dest) {
987  Fatal("FillBinMapSingleNode",
988  "bin %d outside binning scheme",
989  globalBin);
990  } else {
991  Fatal("FillBinMapSingleNode",
992  "bin %d located in %s %d-%d rather than %s %d=%d",
993  i,(const char *)dest->GetName(),
994  dest->GetStartBin(),dest->GetEndBin(),
995  (const char *)GetName(),GetStartBin(),GetEndBin());
996  }
997  }
998  // check whether this bin has to be skipped (underflow/overflow excluded)
1000  for(Int_t axis=0;axis<dimension;axis++) {
1001  Int_t mask=(1<<axis);
1002  if(((axisBins[axis]<0)&&(isOptionGiven[1] & mask))||
1003  ((axisBins[axis]>=axisNbin[axis])&&(isOptionGiven[2] & mask)))
1004  skip=kTRUE;
1005  }
1006  if(skip) continue;
1007 
1008  if(nDim>0) {
1009  // get bin number from THxx function(s)
1010  if(nDim==hist->GetDimension()) {
1011  Int_t ibin[3];
1012  ibin[0]=ibin[1]=ibin[2]=0;
1013  for(Int_t hdim=0;hdim<nDim;hdim++) {
1014  Int_t axis=axisList[hdim];
1015  ibin[hdim]=axisBins[axis]+1;
1016  }
1017  binMap[globalBin]=hist->GetBin(ibin[0],ibin[1],ibin[2]);
1018  } else if(nDim==1) {
1019  // histogram has more dimensions than the binning scheme
1020  // and the binning scheme has one axis only
1021  // -> use the first valid axis only
1022  for(Int_t ii=0;ii<hist->GetDimension();ii++) {
1023  if(axisList[ii]>=0) {
1024  binMap[globalBin]=axisBins[axisList[ii]]+1;
1025  break;
1026  }
1027  }
1028  } else {
1029  Fatal("FillBinMapSingleNode","unexpected bin mapping %d %d",nDim,
1030  hist->GetDimension());
1031  }
1032  } else {
1033  // order all bins in sequence
1034  // calculation in parallel to ToGlobalBin()
1035  // but take care of
1036  // startBin,collapseAxis,discardeUnderflow,discardeOverflow
1037  if(dimension>0) {
1038  Int_t r=0;
1039  for(Int_t axis=dimension-1;axis>=0;axis--) {
1040  Int_t mask=(1<<axis);
1041  if(isOptionGiven[0] & mask) {
1042  // bins on this axis are integrated over
1043  continue;
1044  }
1045  Int_t iBin=axisBins[axis];
1046  Int_t nMax=axisNbin[axis];
1047  if((fHasUnderflow & ~isOptionGiven[1]) & mask) {
1048  nMax +=1;
1049  iBin +=1;
1050  }
1051  if((fHasOverflow & ~isOptionGiven[2]) & mask) {
1052  nMax += 1;
1053  }
1054  r = r*nMax +iBin;
1055  }
1056  binMap[globalBin] = startBin + r;
1057  } else {
1058  binMap[globalBin] = startBin + axisBins[0];
1059  }
1060  }
1061  }
1062  Int_t nbin;
1063  if(dimension>0) {
1064  nbin=1;
1065  for(Int_t axis=dimension-1;axis>=0;axis--) {
1066  Int_t mask=(1<<axis);
1067  if(isOptionGiven[0] & mask) {
1068  // bins on this axis are integrated over
1069  continue;
1070  }
1071  Int_t nMax=axisNbin[axis];
1072  if((fHasUnderflow & ~isOptionGiven[1]) & mask) {
1073  nMax +=1;
1074  }
1075  if((fHasOverflow & ~isOptionGiven[2]) & mask) {
1076  nMax += 1;
1077  }
1078  nbin = nbin*nMax;
1079  }
1080  } else {
1081  nbin=GetDistributionNumberOfBins();
1082  }
1083  return nbin;
1084 }
1085 
1087 (const char *histogramName,const TH1 *globalBins,
1088  const TH2 *globalBinsEmatrix,Bool_t originalAxisBinning,
1089  const char *axisSteering) const
1090 {
1091  // extract a distribution from the given set of global bins
1092  // input:
1093  // histogramName : name of the histogram which ic created
1094  // globalBins : histogram with all bins
1095  // globalBinsEmatrix : corresponding error matrix
1096  // if this pointer is zero, only diagonal errors
1097  // are considered
1098  // originalAxisBinning : extract histogram with proper binning
1099  // (if possible)
1100  // axisSteering
1101  // "pattern1;pattern2;...;patternN"
1102  // patternI = axis[mode]
1103  // axis = name or *
1104  // mode = C|U|O
1105  // C: collapse axis into one bin
1106  // U: discarde underflow bin
1107  // O: discarde overflow bin
1108  Int_t *binMap=0;
1109  TH1 *r=CreateHistogram(histogramName,originalAxisBinning,&binMap,0,
1110  axisSteering);
1111  TUnfoldBinning const *root=GetRootNode();
1112  Int_t nMax=0;
1113  for(Int_t iSrc=root->GetStartBin();iSrc<root->GetEndBin();iSrc++) {
1114  if(binMap[iSrc]>nMax) nMax=binMap[iSrc];
1115  }
1116  TVectorD eSquared(nMax+1);
1117  for(Int_t iSrc=root->GetStartBin();iSrc<root->GetEndBin();iSrc++) {
1118  Int_t iDest=binMap[iSrc];
1119  if(iDest>=0) {
1120  Double_t c=r->GetBinContent(iDest);
1121  r->SetBinContent(iDest,c+globalBins->GetBinContent(iSrc));
1122  if(!globalBinsEmatrix) {
1123  eSquared(iDest) += TMath::Power(globalBins->GetBinError(iSrc),2.);
1124  } else {
1125  for(Int_t jSrc=root->GetStartBin();jSrc<root->GetEndBin();jSrc++) {
1126  if(binMap[jSrc]==iDest) {
1127  eSquared(iDest) +=
1128  TMath::Power(globalBins->GetBinError(jSrc),2.);
1129  }
1130  }
1131  }
1132  }
1133  }
1134  for(Int_t i=0;i<nMax;i++) {
1135  Double_t e2=eSquared(i);
1136  if(e2>0.0) {
1137  r->SetBinError(i,TMath::Sqrt(e2));
1138  }
1139  }
1140  delete [] binMap;
1141 
1142  return r;
1143 }
1144 
1145 /********************* Calculate global bin number ******/
1146 
1148 {
1149  // locate bin on a one-dimensional distribution
1150  // input
1151  // x: coordinate to locate
1152  if(GetDistributionDimension()!=1) {
1153  Fatal("GetBinNumber",
1154  "called with 1 argument for %d dimensional distribution",
1155  GetDistributionDimension());
1156  }
1157  return GetGlobalBinNumber(&x);
1158 }
1159 
1161 {
1162  // locate bin on a two-dimensional distribution
1163  // input
1164  // x,y: coordinates to locate
1165  if(GetDistributionDimension()!=2) {
1166  Fatal("GetBinNumber",
1167  "called with 2 arguments for %d dimensional distribution",
1168  GetDistributionDimension());
1169  }
1170  Double_t xx[2];
1171  xx[0]=x;
1172  xx[1]=y;
1173  return GetGlobalBinNumber(xx);
1174 }
1175 
1178 {
1179  // locate bin on a three-dimensional distribution
1180  // input
1181  // x,y,z: coordinates to locate
1182  if(GetDistributionDimension()!=3) {
1183  Fatal("GetBinNumber",
1184  "called with 3 arguments for %d dimensional distribution",
1185  GetDistributionDimension());
1186  }
1187  Double_t xx[3];
1188  xx[0]=x;
1189  xx[1]=y;
1190  xx[2]=z;
1191  return GetGlobalBinNumber(xx);
1192 }
1193 
1195 (Double_t x0,Double_t x1,Double_t x2,Double_t x3) const
1196 {
1197  // locate bin on a four-dimensional distribution
1198  // input
1199  // x0,x1,x2,x3: coordinates to locate
1200  if(GetDistributionDimension()!=4) {
1201  Fatal("GetBinNumber",
1202  "called with 4 arguments for %d dimensional distribution",
1203  GetDistributionDimension());
1204  }
1205  Double_t xx[4];
1206  xx[0]=x0;
1207  xx[1]=x1;
1208  xx[2]=x2;
1209  xx[3]=x3;
1210  return GetGlobalBinNumber(xx);
1211 }
1212 
1214 {
1215  // locate bin on a n-dimensional distribution
1216  // input
1217  // x[]: coordinates to locate
1218  if(!GetDistributionDimension()) {
1219  Fatal("GetBinNumber",
1220  "no axes are defined for node %s",
1221  (char const *)GetName());
1222  }
1223  Int_t iAxisBins[MAXDIM] = {0};
1224  for(Int_t dim=0;dim<GetDistributionDimension();dim++) {
1225  TVectorD const *bins=(TVectorD const *) fAxisList->At(dim);
1226  Int_t i0=0;
1227  Int_t i1=bins->GetNrows()-1;
1228  Int_t iBin= 0;
1229  if(x[dim]<(*bins)[i0]) {
1230  iBin += i0-1;
1231  // underflow
1232  } else if(x[dim]>=(*bins)[i1]) {
1233  // overflow
1234  iBin += i1;
1235  } else {
1236  while(i1-i0>1) {
1237  Int_t i2=(i0+i1)/2;
1238  if(x[dim]<(*bins)[i2]) {
1239  i1=i2;
1240  } else {
1241  i0=i2;
1242  }
1243  }
1244  iBin += i0;
1245  }
1246  iAxisBins[dim]=iBin;
1247  }
1248  Int_t r=ToGlobalBin(iAxisBins);
1249  if(r<0) r=0;
1250  return r;
1251 }
1252 
1253 /********************* access by global bin number ******/
1254 
1256 {
1257  // get the name of a bin in the given tree
1258  // iBin: bin number
1259  Int_t axisBins[MAXDIM] = {0};
1260  TString r=TString::Format("#%d",iBin);
1261  TUnfoldBinning const *distribution=ToAxisBins(iBin,axisBins);
1262  if(distribution) {
1263  r +=" (";
1264  r += distribution->GetName();
1265  Int_t dimension=distribution->GetDistributionDimension();
1266  if(dimension>0) {
1267  TString axisString;
1268  for(Int_t axis=0;axis<dimension;axis++) {
1269  TString thisAxisString=
1270  distribution->GetDistributionAxisLabel(axis);
1271  TVectorD const *bins=distribution->GetDistributionBinning(axis);
1272  Int_t i=axisBins[axis];
1273  if(i<0) thisAxisString += "[ufl]";
1274  else if(i>=bins->GetNrows()-1) thisAxisString += "[ofl]";
1275  else {
1276  thisAxisString +=
1277  TString::Format("[%.3g,%.3g]",(*bins)[i],(*bins)[i+1]);
1278  }
1279  axisString = ":"+thisAxisString+axisString;
1280  }
1281  r += axisString;
1282  } else {
1283  // extra bins
1284  Int_t i=axisBins[0];
1285  if((i>=0)&&(i<distribution->fAxisLabelList->GetEntriesFast())) {
1286  r += distribution->GetDistributionAxisLabel(i);
1287  } else {
1288  r += TString::Format(" %d",i);
1289  }
1290  }
1291  r +=")";
1292  }
1293  return r;
1294 }
1295 
1297 {
1298  // get N-dimensional bin size
1299  // input:
1300  // iBin : global bin number
1301  // includeUO : include underflow/overflow bins or not
1302  Int_t axisBins[MAXDIM] = {0};
1303  TUnfoldBinning const *distribution=ToAxisBins(iBin,axisBins);
1304  Double_t r=0.0;
1305  if(distribution) {
1306  if(distribution->GetDistributionDimension()>0) r=1.0;
1307  for(Int_t axis=0;axis<distribution->GetDistributionDimension();axis++) {
1308  TVectorD const *bins=distribution->GetDistributionBinning(axis);
1309  Int_t pos=axisBins[axis];
1310  if(pos<0) {
1311  r *= distribution->GetDistributionUnderflowBinWidth(axis);
1312  } else if(pos>=bins->GetNrows()-1) {
1313  r *= distribution->GetDistributionOverflowBinWidth(axis);
1314  } else {
1315  r *= (*bins)(pos+1)-(*bins)(pos);
1316  }
1317  if(r<=0.) break;
1318  }
1319  }
1320  return r;
1321 }
1322 
1324 {
1325  // return user factor for a bin
1326  // iBin : global bin number
1327  Int_t axisBins[MAXDIM] = {0};
1328  TUnfoldBinning const *distribution=ToAxisBins(iBin,axisBins);
1329  Double_t r=distribution->fBinFactorConstant;
1330  if((r!=0.0) && distribution->fBinFactorFunction) {
1331  Double_t x[MAXDIM];
1332  Int_t dimension=distribution->GetDistributionDimension();
1333  if(dimension>0) {
1334  for(Int_t axis=0;axis<dimension;axis++) {
1335  x[axis]=distribution->GetDistributionBinCenter
1336  (axis,axisBins[axis]);
1337  }
1338  r *= distribution->fBinFactorFunction->EvalPar
1339  (x,distribution->fBinFactorFunction->GetParameters());
1340  } else {
1341  x[0]=axisBins[0];
1342  r *= distribution->fBinFactorFunction->Eval(x[0]);
1343  }
1344 
1345  }
1346  return r;
1347 }
1348 
1350 (Int_t bin,Int_t axis,Int_t *prev,Double_t *distPrev,
1351  Int_t *next,Double_t *distNext) const
1352 {
1353  // get neighbour bins along the specified axis
1354  // input:
1355  // bin,axis : bin number and axis number
1356  // output:
1357  // prev: bin number of previous bin (or -1 if not existing)
1358  // distPrev: distance to previous bin
1359  // next: bin number of next bin (or -1 if not existing)
1360  // distNext: distance to next bin
1361  Int_t axisBins[MAXDIM] = {0};
1362  TUnfoldBinning const *distribution=ToAxisBins(bin,axisBins);
1363  Int_t dimension=distribution->GetDistributionDimension();
1364  *prev=-1;
1365  *next=-1;
1366  *distPrev=0.;
1367  *distNext=0.;
1368  if((axis>=0)&&(axis<dimension)) {
1369  //TVectorD const *bins=distribution->GetDistributionBinning(axis);
1370  //Int_t nBin=bins->GetNrows()-1;
1371  Int_t centerBin= axisBins[axis];
1372  axisBins[axis] =centerBin-1;
1373  *prev=ToGlobalBin(axisBins);
1374  if(*prev>=0) {
1375  *distPrev=distribution->GetDistributionBinCenter(axis,axisBins[axis])-
1376  distribution->GetDistributionBinCenter(axis,centerBin);
1377  }
1378  axisBins[axis] =centerBin+1;
1379  *next=ToGlobalBin(axisBins);
1380  if(*next>=0) {
1381  *distNext=distribution->GetDistributionBinCenter(axis,axisBins[axis])-
1382  distribution->GetDistributionBinCenter(axis,centerBin);
1383  }
1384  }
1385 }
1386 
1388 (Int_t iBin,Int_t *uStatus,Int_t *oStatus) const
1389 {
1390  // return bit map indicating underflow and overflow status
1391  // iBin: global bin number
1392  // output
1393  // uStatus: bin map indicating whether the bin is in underflow
1394  // oStatus: bin map indicating whether the bin is in overflow
1395  Int_t axisBins[MAXDIM] = {0};
1396  TUnfoldBinning const *distribution=ToAxisBins(iBin,axisBins);
1397  Int_t dimension=distribution->GetDistributionDimension();
1398  *uStatus=0;
1399  *oStatus=0;
1400  for(Int_t axis=0;axis<dimension;axis++) {
1401  TVectorD const *bins=distribution->GetDistributionBinning(axis);
1402  Int_t nBin=bins->GetNrows()-1;
1403  if(axisBins[axis]<0) *uStatus |= (1<<axis);
1404  if(axisBins[axis]>=nBin) *oStatus |= (1<<axis);
1405  }
1406 }
1407 
1408 /********************* access by bin number, given a projection mode ******/
1410 (Int_t binTHxx,const char *axisSteering,Int_t axisBins[MAXDIM]) const
1411 {
1412  // locate the node corresponding to
1413  // a given THxx bin for a given projection mode
1414  // input:
1415  // binTHxx : bin in histogram
1416  // axisSteering :
1417  // "pattern1;pattern2;...;patternN"
1418  // patternI = axis[mode]
1419  // axis = name or *
1420  // mode = C|U|O
1421  // C: collapse axis into one bin
1422  // U: discarde underflow bin
1423  // O: discarde overflow bin
1424  // output:
1425  // axisBins[]
1426  // for each axis of the identified binning node give the bin number
1427  // -1 underflow bin
1428  // >=0 inside distribution or overflow bin
1429  // special bin numbers
1430  // -2 : axis collapsed
1431  // -3 : axis collapsed and underflow bin excluded
1432  // -4 : axis collapsed and overflow bin excluded
1433  // -5 : axis collapsed and underflow+overflow bin excluded
1434  // return value:
1435  // the binning node or 0 if not found
1436  Int_t offset=binTHxx-GetStartBin();
1437  return GetBinLocationRecursive(offset,axisSteering,axisBins);
1438 }
1439 
1441 (Int_t &offset,const char *axisSteering,Int_t axisBins[MAXDIM]) const
1442 {
1443  // recursively locate the node corresponding to
1444  // a given THxx bin for a given projection mode
1445  // input:
1446  // offset : start bin of this nodes in the histogram
1447  // axisSteering :
1448  // "pattern1;pattern2;...;patternN"
1449  // patternI = axis[mode]
1450  // axis = name or *
1451  // mode = C|U|O
1452  // C: collapse axis into one bin
1453  // U: discarde underflow bin
1454  // O: discarde overflow bin
1455  // output:
1456  // axisBins[]
1457  // for each axis of the identified binning node give the bin number
1458  // -1 underflow bin
1459  // >=0 inside distribution or overflow bin
1460  // special bin numbers
1461  // -2 : axis collapsed
1462  // -3 : axis collapsed and underflow bin excluded
1463  // -4 : axis collapsed and overflow bin excluded
1464  // -5 : axis collapsed and underflow+overflow bin excluded
1465  // return value:
1466  // the binning node or 0 if not found
1467 
1468  // decode axisSteering
1469  // isOptionGiven[0] ('C'): bit vector which axes to collapse
1470  // isOptionGiven[1] ('U'): bit vector to discarde underflow bins
1471  // isOptionGiven[2] ('U'): bit vector to discarde overflow bins
1472  Int_t isOptionGiven[3] = { 0 };
1473  DecodeAxisSteering(axisSteering,"CUO",isOptionGiven);
1474  const TUnfoldBinning *r=0;
1475  if(offset>=0) {
1476  if(GetDistributionDimension()>0) {
1477  Int_t nBinsTotal=1;
1478  Int_t i=offset;
1479  for(Int_t axis=0;axis<GetDistributionDimension();axis++) {
1480  Int_t mask=1<<axis;
1481  if(isOptionGiven[0] & mask) {
1482  axisBins[axis]=-2;
1483  if((isOptionGiven[1] & mask)&&
1484  (fHasUnderflow & mask)) axisBins[axis] -= 1;
1485  if((isOptionGiven[2] & mask)&&
1486  (fHasOverflow & mask)) axisBins[axis] -= 2;
1487  } else {
1488  Int_t nBin=GetDistributionBinning(axis)->GetNrows()-1;
1489  axisBins[axis]=0;
1490  if((fHasUnderflow & mask) && !(isOptionGiven[1] & mask)) {
1491  nBin++;
1492  axisBins[axis]=-1;
1493  }
1494  if((fHasOverflow & mask) && !(isOptionGiven[2] & mask)) {
1495  nBin++;
1496  }
1497  axisBins[axis] += i % nBin;
1498  i /= nBin;
1499  nBinsTotal *= nBin;
1500  }
1501  }
1502  offset -= nBinsTotal;
1503  if(offset<0) {
1504  r=this;
1505  }
1506  } else {
1507  axisBins[0]=offset;
1508  offset -= GetDistributionNumberOfBins();
1509  if(offset<0) r=this;
1510  }
1511  }
1512  if(!r) {
1513  for(TUnfoldBinning const *child=GetChildNode();child;
1514  child=child->GetNextNode()) {
1515  r=child->GetBinLocationRecursive(offset,axisSteering,axisBins);
1516  if(r) break;
1517  }
1518  }
1519  return r;
1520 }
1521 
1523 {
1524  // check whether there are bins but no axis
1525  return (!GetDistributionDimension())&&(GetDistributionNumberOfBins()>0);
1526 }
1527 
1529 (Int_t axis,Bool_t includeUnderflow,Bool_t includeOverflow) const
1530 {
1531  // get average bin size of the specified axis
1532  // axis : axis number
1533  // includeUnderflow : include underflow bin
1534  // includeOverflow : include overflow bin
1535  Double_t r=0.0;
1536  if((axis>=0)&&(axis<GetDistributionDimension())) {
1537  TVectorD const *bins=GetDistributionBinning(axis);
1538  Double_t d=(*bins)[bins->GetNrows()-1]-(*bins)[0];
1539  Double_t nBins=bins->GetNrows()-1;
1540  if(includeUnderflow && (fHasUnderflow & (1<<axis))) {
1541  Double_t w=GetDistributionUnderflowBinWidth(axis);
1542  if(w>0) {
1543  nBins++;
1544  d += w;
1545  }
1546  }
1547  if(includeOverflow && (fHasOverflow & (1<<axis))) {
1548  Double_t w=GetDistributionOverflowBinWidth(axis);
1549  if(w>0.0) {
1550  nBins++;
1551  d += w;
1552  }
1553  }
1554  if(nBins>0) {
1555  r=d/nBins;
1556  }
1557  } else {
1558  Error("GetDistributionAverageBinSize","axis %d does not exist",axis);
1559  }
1560  return r;
1561 }
1562 
1564 {
1565  // return width of the underflow bin
1566  // axis: axis number
1567  TVectorD const *bins=GetDistributionBinning(axis);
1568  return (*bins)[1]-(*bins)[0];
1569 }
1570 
1572 {
1573  // return width of the underflow bin
1574  // axis: axis number
1575  TVectorD const *bins=GetDistributionBinning(axis);
1576  return (*bins)[bins->GetNrows()-1]-(*bins)[bins->GetNrows()-2];
1577 }
1578 
1580 (Int_t axis,Int_t bin) const
1581 {
1582  // position of the bin center
1583  // input
1584  // axis : axis number
1585  // bin : bin number on the axis
1586  TVectorD const *bins=GetDistributionBinning(axis);
1587  Double_t r=0.0;
1588  if(bin<0) {
1589  // underflow bin
1590  r=(*bins)[0]-0.5*GetDistributionUnderflowBinWidth(axis);
1591  } else if(bin>=bins->GetNrows()-1) {
1592  // overflow bin
1593  r=(*bins)[bins->GetNrows()-1]+0.5*GetDistributionOverflowBinWidth(axis);
1594  } else {
1595  r=0.5*((*bins)[bin+1]+(*bins)[bin]);
1596  }
1597  return r;
1598 }
1599 
1601 {
1602  // get global bin number, given axis bin numbers
1603  // axisBins[]: bin numbers on each axis
1604  // return: global bin nmber or -1 if not inside distribution
1605  Int_t dimension=GetDistributionDimension();
1606  Int_t r=0;
1607  if(dimension>0) {
1608  for(Int_t axis=dimension-1;axis>=0;axis--) {
1609  Int_t nMax=GetDistributionBinning(axis)->GetNrows()-1;
1610  Int_t i=axisBins[axis];
1611  if(fHasUnderflow & (1<<axis)) {
1612  nMax +=1;
1613  i +=1;
1614  }
1615  if(fHasOverflow & (1<<axis)) nMax +=1;
1616  if((i>=0)&&(i<nMax)) {
1617  r = r*nMax +i;
1618  } else {
1619  r=-1;
1620  break;
1621  }
1622  }
1623  if(r>=0) {
1624  r += GetStartBin();
1625  }
1626  } else {
1627  if((axisBins[0]>=0)&&(axisBins[0]<GetDistributionNumberOfBins()))
1628  r=GetStartBin()+axisBins[0];
1629  }
1630  return r;
1631 }
1632 
1634 (Int_t globalBin,Int_t *axisBins) const
1635 {
1636  // return distribution in which the bin is located
1637  // and bin numbers on the corresponding axes
1638  // input
1639  // globalBin : global bin number
1640  // output
1641  // if(GetDistributionDimension()>0)
1642  // axisBin[] : bin number on the individual axes
1643  // bin numbers are starting with -1 (underflow)
1644  // else
1645  // axisBin[0] : bin number, counted from zero
1646  // return value
1647  // the distribution in which the globalBin is located
1648  // or 0 if the globalBin is outside the tree
1649  TUnfoldBinning const *r=0;
1650  if((globalBin>=GetStartBin())&&(globalBin<GetEndBin())) {
1651  TUnfoldBinning const *node;
1652  for(node=GetChildNode();node && !r; node=node->GetNextNode()) {
1653  r=node->ToAxisBins(globalBin,axisBins);
1654  }
1655  if(!r) {
1656  r=this;
1657  Int_t i=globalBin-GetStartBin();
1658  Int_t dimension=GetDistributionDimension();
1659  if(dimension>0) {
1660  for(int axis=0;axis<dimension;axis++) {
1661  Int_t nMax=GetDistributionBinning(axis)->GetNrows()-1;
1662  axisBins[axis]=0;
1663  if(fHasUnderflow & (1<<axis)) {
1664  axisBins[axis] =-1;
1665  nMax += 1;
1666  }
1667  if(fHasOverflow & (1<<axis)) nMax +=1;
1668  axisBins[axis] += i % nMax;
1669  i /= nMax;
1670  }
1671  } else {
1672  axisBins[0]=i;
1673  }
1674  }
1675  }
1676  return r;
1677 }
1678 
1680 (const char *axisSteering,const char *options,Int_t *isOptionGiven) const
1681 {
1682  // decode axis steering
1683  // input
1684  // axisSteering: the steering to decode
1685  // options: the allowed options to extract
1686  // output
1687  // isOptionGiven[] : array of decoded steering options
1688  // the dimension of isOptionGiven[] has to match the number of
1689  // characters in "option"
1690  //
1691  // the axis steering is given in the form
1692  // steering1;steering2;...;steeringN
1693  // all parts of the steering, sepatared by ';' are parsed
1694  // each part must have the form
1695  // axisName[optionlist]
1696  // where:
1697  // axisName : the name of the axis for which the optionlist is relevant
1698  // if the name is the character '*', all axes are matched
1699  // optionlist : for each option the corresonding character
1700  //
1701  // example:
1702  // imagine this node has two axes, named "xgen" and "ygen"
1703  // then
1704  // DecodeAxisSteering("*[u];xgen[c]","cuo",options);
1705  // will set the "U" option for all axes and the "C" option for the "xgen"
1706  // axis, so:
1707  // options[0]=0x1; // option 'c' is true for axis 0 (bit #0 is set)
1708  // options[1]=0x3; // option 'u' is true for both axes (bit #0,#1 are set)
1709  // options[2]=0x0; // option 'o' is not given (no bits are set)
1710  Int_t nOpt=TString(options).Length();
1711  for(Int_t i=0;i<nOpt;i++) isOptionGiven[i]=0;
1712  if(axisSteering) {
1713  TObjArray *patterns=TString(axisSteering).Tokenize(";");
1714  Int_t nPattern=patterns->GetEntries();
1715  Int_t nAxis=fAxisLabelList->GetEntries();
1716  for(Int_t i=0;i<nPattern;i++) {
1717  TString const &pattern=((TObjString * const)patterns->At(i))
1718  ->GetString();
1719  Int_t bracketBegin=pattern.Last('[');
1720  Int_t len=pattern.Length();
1721  if((bracketBegin>0)&&(pattern[len-1]==']')) {
1722  TString axisId=pattern(0,bracketBegin);
1723  Int_t mask=0;
1724  if((axisId[0]=='*')&&(axisId.Length()==1)) {
1725  // turn all bins on
1726  mask=(1<<nAxis)-1;
1727  } else {
1728  // if axis is there, turn its bit on
1729  for(Int_t j=0;j<nAxis;j++) {
1730  if(!axisId.CompareTo(GetDistributionAxisLabel(j))) {
1731  mask|= (1<<j);
1732  }
1733  }
1734  }
1735  for(Int_t o=0;o<nOpt;o++) {
1736  if(pattern.Last(options[o])>bracketBegin) {
1737  isOptionGiven[o] |= mask;
1738  }
1739  }
1740  } else {
1741  Error("DecodeAxisSteering",
1742  "steering \"%s\" does not end with [options]",
1743  (const char *)pattern);
1744  }
1745  }
1746  }
1747 }
1748 
Int_t FillBinMapRecursive(Int_t startBin, const char *axisSteering, Int_t *binMap) const
TString GetBinName(Int_t iBin) const
Ssiz_t Last(char c) const
Find last occurrence of a character c.
Definition: TString.cxx:851
An array of TObjects.
Definition: TObjArray.h:39
Int_t GetEndBin(void) const
TUnfoldBinning * parentNode
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition: TH1.cxx:4629
Ssiz_t Length() const
Definition: TString.h:390
void Fatal(const char *location, const char *msgfmt,...)
Collectable string class.
Definition: TObjString.h:32
return c
tuple offset
Definition: tree.py:93
virtual Int_t GetDimension() const
Definition: TH1.h:283
Int_t GetNrows() const
Definition: TVectorT.h:81
TString BuildHistogramTitle(const char *histogramName, const char *histogramTitle, Int_t const *axisList) const
virtual Double_t GetDistributionOverflowBinWidth(Int_t axis) const
TUnfoldBinning * nextNode
const TUnfoldBinning * GetNonemptyNode(void) const
virtual Double_t GetBinLowEdge(Int_t bin) const
Return low edge of bin.
Definition: TAxis.cxx:489
Int_t GetTHxxBinning(Int_t maxDim, Int_t *axisBins, Int_t *axisList, const char *axisSteering) const
Int_t ToGlobalBin(Int_t const *axisBins) const
Int_t GetStartBin(void) const
Basic string class.
Definition: TString.h:137
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
const Bool_t kFALSE
Definition: Rtypes.h:92
const TKDTreeBinning * bins
ClassImp(TUnfoldBinning) void TUnfoldBinning
virtual ~TUnfoldBinning(void)
LongDouble_t Power(LongDouble_t x, LongDouble_t y)
Definition: TMath.h:501
Int_t UpdateFirstLastBin(Bool_t startWithRootNode=kTRUE)
Double_t fBinFactorConstant
static const double x2[5]
const TUnfoldBinning * GetBinLocation(Int_t binTHxx, const char *axisSteering, Int_t axisBins[MAXDIM]) const
Double_t x[n]
Definition: legend1.C:17
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:2321
TH1 * ExtractHistogram(const char *histogramName, const TH1 *globalBins, const TH2 *globalBinsEmatrix=0, Bool_t originalAxisBinning=kTRUE, const char *axisSteering=0) const
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:33
TH1 * CreateHistogram(const char *histogramName, Bool_t originalAxisBinning=kFALSE, Int_t **binMap=0, const char *histogramTitle=0, const char *axisSteering=0) const
int d
Definition: tornado.py:11
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:4535
void Info(const char *location, const char *msgfmt,...)
Int_t FillBinMapSingleNode(const TH1 *hist, Int_t startBin, Int_t nDim, const Int_t *axisList, const char *axisSteering, Int_t *binMap) const
static const std::string pattern("pattern")
TF1 * fBinFactorFunction
Int_t Finite(Double_t x)
Definition: TMath.h:532
TVectorD const * GetDistributionBinning(Int_t axis) const
Float_t z[5]
Definition: Ifit.C:16
virtual void SetBinError(Int_t bin, Double_t error)
see convention for numbering bins in TH1::GetBin
Definition: TH1.cxx:8528
void Error(const char *location, const char *msgfmt,...)
TVectorT< Double_t > TVectorD
Definition: TVectorDfwd.h:24
char * out
Definition: TBase64.cxx:29
virtual Double_t GetDistributionUnderflowBinWidth(Int_t axis) const
Element * GetMatrixArray()
Definition: TVectorT.h:84
Int_t * CreateBinMap(const TH1 *hist, Int_t nDim, const Int_t *axisList, const char *axisSteering) const
Bool_t AddAxis(const char *name, Int_t nBins, const Double_t *binBorders, Bool_t hasUnderflow, Bool_t hasOverflow)
void GetBinUnderflowOverflowStatus(Int_t iBin, Int_t *uStatus, Int_t *oStatus) const
ROOT::R::TRInterface & r
Definition: Object.C:4
Service class for 2-Dim histogram classes.
Definition: TH2.h:36
Class to manage histogram axis.
Definition: TAxis.h:36
void Initialize(Bool_t useTMVAStyle=kTRUE)
Definition: tmvaglob.cxx:176
3-D histogram with a double per channel (see TH1 documentation)}
Definition: TH3.h:309
TPaveLabel title(3, 27.1, 15, 28.7,"ROOT Environment and Tools")
Int_t GetNbins() const
Definition: TAxis.h:125
virtual Double_t GetBinUpEdge(Int_t bin) const
Return up edge of bin.
Definition: TAxis.cxx:499
virtual void SetBinContent(Int_t bin, Double_t content)
Set bin content see convention for numbering bins in TH1::GetBin In case the bin number is greater th...
Definition: TH1.cxx:8543
const TUnfoldBinning * GetBinLocationRecursive(Int_t &offset, const char *axisSteering, Int_t axisBins[MAXDIM]) const
TUnfoldBinning const * GetNextNode(void) const
tuple w
Definition: qtexample.py:51
Double_t GetBinSize(Int_t iBin) const
return fString CompareTo(((TObjString *) obj) ->fString)
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:51
Int_t GetGlobalBinNumber(Double_t x) const
const char * GetTitle() const
Returns title of object.
Definition: TAxis.h:133
static void indent(ostringstream &buf, int indent_level)
void Warning(const char *location, const char *msgfmt,...)
1-D histogram with a double per channel (see TH1 documentation)}
Definition: TH1.h:613
TObjArray * Tokenize(const TString &delim) const
This function is used to isolate sequential tokens in a TString.
Definition: TString.cxx:2227
static TH2D * CreateHistogramOfMigrations(TUnfoldBinning const *xAxis, TUnfoldBinning const *yAxis, char const *histogramName, Bool_t originalXAxisBinning=kFALSE, Bool_t originalYAxisBinning=kFALSE, char const *histogramTitle=0)
TH2D * CreateErrorMatrixHistogram(const char *histogramName, Bool_t originalAxisBinning, Int_t **binMap=0, const char *histogramTitle=0, const char *axisSteering=0) const
void PrintStream(std::ostream &out, Int_t indent=0) const
This class serves as a container of analysis bins analysis bins are specified by defining the axes of...
TUnfoldBinning const * GetParentNode(void) const
static const double x1[5]
Bool_t HasUnconnectedBins(void) const
double Double_t
Definition: RtypesCore.h:55
Int_t GetDistributionDimension(void) const
TUnfoldBinning * prevNode
TString BuildHistogramTitle2D(const char *histogramName, const char *histogramTitle, Int_t xAxis, const TUnfoldBinning *yAxisBinning, Int_t yAxis) const
void GetBinNeighbours(Int_t globalBin, Int_t axis, Int_t *prev, Double_t *distPrev, Int_t *next, Double_t *distNext) const
TUnfoldBinning const * GetPrevNode(void) const
Double_t y[n]
Definition: legend1.C:17
The TH1 histogram class.
Definition: TH1.h:80
Int_t GetEntries() const
Return the number of objects in array (i.e.
Definition: TObjArray.cxx:494
TString GetDistributionAxisLabel(Int_t axis) const
typedef void((*Func_t)())
TUnfoldBinning const * FindNode(char const *name) const
Bool_t axis
Definition: geodemo.C:37
TObjArray * fAxisList
#define dest(otri, vertexptr)
Definition: triangle.c:1040
TUnfoldBinning(const char *name=0, Int_t nBins=0, const char *binNames=0)
Int_t GetTH1xNumberOfBins(Bool_t originalAxisBinning=kTRUE, const char *axisSteering=0) const
Double_t Sqrt(Double_t x)
Definition: TMath.h:464
TObject * At(Int_t idx) const
Definition: TObjArray.h:167
virtual Double_t GetBinError(Int_t bin) const
Return value of error associated to bin number bin.
Definition: TH1.cxx:8395
void DecodeAxisSteering(const char *axisSteering, const char *options, Int_t *isOptionGiven) const
const Bool_t kTRUE
Definition: Rtypes.h:91
virtual Double_t GetBinFactor(Int_t iBin) const
Int_t GetTHxxBinsRecursive(const char *axisSteering) const
TUnfoldBinning * GetRootNode(void)
TUnfoldBinning * AddBinning(TUnfoldBinning *binning)
virtual Double_t GetDistributionBinCenter(Int_t axis, Int_t bin) const
static char * skip(char **buf, const char *delimiters)
Definition: civetweb.c:1014
virtual Double_t GetDistributionAverageBinSize(Int_t axis, Bool_t includeUnderflow, Bool_t includeOverflow) const
int CompareTo(const char *cs, ECaseCompare cmp=kExact) const
Compare a string to char *cs2.
Definition: TString.cxx:372
Int_t GetTHxxBinningSingleNode(Int_t maxDim, Int_t *axisBins, Int_t *axisList, const char *axisSteering) const
static const double x3[11]
TUnfoldBinning const * ToAxisBins(Int_t globalBin, Int_t *axisBins) const
2-D histogram with a double per channel (see TH1 documentation)}
Definition: TH2.h:297
int ii
Definition: hprod.C:34