120 ClassImp(TUnfoldBinning);
 
  125 TUnfoldBinning::~TUnfoldBinning(
void)
 
  128    while(childNode) 
delete childNode;
 
  130    if(GetParentNode() && (GetParentNode()->GetChildNode()==
this)) {
 
  131       parentNode->childNode=nextNode;
 
  133    if(GetPrevNode()) prevNode->nextNode=nextNode;
 
  134    if(GetNextNode()) nextNode->prevNode=prevNode;
 
  136    delete fAxisLabelList;
 
  137    if(fBinFactorFunction) {
 
  138       if(!dynamic_cast<TF1 *>(fBinFactorFunction))
 
  139          delete fBinFactorFunction;
 
  148 void TUnfoldBinning::Initialize(Int_t nBins)
 
  154    fAxisList=
new TObjArray();
 
  155    fAxisLabelList=
new TObjArray();
 
  156    fAxisList->SetOwner();
 
  157    fAxisLabelList->SetOwner();
 
  160    fDistributionSize=nBins;
 
  161    fBinFactorFunction=0;
 
  162    fBinFactorConstant=1.0;
 
  170 Int_t TUnfoldBinning::UpdateFirstLastBin(Bool_t startWithRootNode)
 
  172    if(startWithRootNode) {
 
  173       return GetRootNode()->UpdateFirstLastBin(kFALSE);
 
  178       fFirstBin=GetPrevNode()->GetEndBin();
 
  179    } 
else if(GetParentNode()) {
 
  182       fFirstBin=GetParentNode()->GetStartBin()+
 
  183          GetParentNode()->GetDistributionNumberOfBins();
 
  191      if((!GetChildNode())&&(GetDistributionDimension()==1)&&
 
  192         (fHasUnderflow==1)) {
 
  196    fLastBin=fFirstBin+fDistributionSize;
 
  198    for(TUnfoldBinning *node=childNode;node;node=node->nextNode) {
 
  199       fLastBin=node->UpdateFirstLastBin(kFALSE);
 
  211 TUnfoldBinning::TUnfoldBinning
 
  212 (
const char *name,Int_t nBins,
const char *binNames)
 
  213    : TNamed(name ? name : 
"",name ? name : 
"")
 
  217       TString nameString(binNames);
 
  218       delete fAxisLabelList;
 
  219       fAxisLabelList=nameString.Tokenize(
";");
 
  221    UpdateFirstLastBin();
 
  231 TUnfoldBinning::TUnfoldBinning
 
  232 (
const TAxis &axis,Int_t includeUnderflow,Int_t includeOverflow)
 
  233    : TNamed(axis.GetName(),axis.GetTitle())
 
  236    AddAxis(axis,includeUnderflow,includeOverflow);
 
  237    UpdateFirstLastBin();
 
  249 TUnfoldBinning *TUnfoldBinning::AddBinning
 
  250 (
const char *name,Int_t nBins,
const char *binNames)
 
  252   return AddBinning(
new TUnfoldBinning(name,nBins,binNames));
 
  263 TUnfoldBinning *TUnfoldBinning::AddBinning(TUnfoldBinning *binning)
 
  266   if(binning->GetParentNode()) {
 
  268            "binning \"%s\" already has parent \"%s\", can not be added to %s",
 
  269      (
char *)binning->GetName(),
 
  270      (
char *)binning->GetParentNode()->GetName(),
 
  272   } 
else if(binning->GetPrevNode()) {
 
  274           "binning \"%s\" has previous node \"%s\", can not be added to %s",
 
  275      (
char *)binning->GetName(),
 
  276      (
char *)binning->GetPrevNode()->GetName(),
 
  278   } 
else if(binning->GetNextNode()) {
 
  280           "binning \"%s\" has next node \"%s\", can not be added to %s",
 
  281      (
char *)binning->GetName(),
 
  282      (
char *)binning->GetNextNode()->GetName(),
 
  286     binning->parentNode=
this;
 
  288       TUnfoldBinning *child=childNode;
 
  290       while(child->nextNode) {
 
  291    child=child->nextNode;
 
  299     UpdateFirstLastBin();
 
  317 Bool_t TUnfoldBinning::AddAxis
 
  318 (
const char *name,Int_t nBin,Double_t xMin,Double_t xMax,
 
  319  Bool_t hasUnderflow,Bool_t hasOverflow)
 
  323       Fatal(
"AddAxis",
"number of bins %d is not positive",
 
  325    } 
else if((!TMath::Finite(xMin))||(!TMath::Finite(xMax))||
 
  327       Fatal(
"AddAxis",
"xmin=%f required to be smaller than xmax=%f",
 
  330      Double_t *binBorders=
new Double_t[nBin+1];
 
  332      Double_t dx=(xMax-xMin)/nBin;
 
  333      for(Int_t i=0;i<=nBin;i++) {
 
  334        binBorders[i]=x+i*dx;
 
  336      r=AddAxis(name,nBin,binBorders,hasUnderflow,hasOverflow);
 
  337      delete [] binBorders;
 
  353 Bool_t TUnfoldBinning::AddAxis
 
  354 (
const TAxis &axis,Bool_t hasUnderflow,Bool_t hasOverflow)
 
  356   Int_t nBin=axis.GetNbins();
 
  357   Double_t *binBorders=
new Double_t[nBin+1];
 
  358   for(Int_t i=0;i<nBin;i++) {
 
  359     binBorders[i]=axis.GetBinLowEdge(i+1);
 
  361   binBorders[nBin]=axis.GetBinUpEdge(nBin);
 
  362   Bool_t r=AddAxis(axis.GetTitle(),nBin,binBorders,hasUnderflow,hasOverflow);
 
  363   delete [] binBorders;
 
  378 Bool_t TUnfoldBinning::AddAxis
 
  379 (
const char *name,Int_t nBin,
const Double_t *binBorders,
 
  380  Bool_t hasUnderflow,Bool_t hasOverflow)
 
  383   if(HasUnconnectedBins()) {
 
  384     Fatal(
"AddAxis",
"node already has %d bins without axis",
 
  385      GetDistributionNumberOfBins());
 
  387     Fatal(
"AddAxis",
"number of bins %d is not positive",
 
  390     TVectorD *bins=
new TVectorD(nBin+1);
 
  392     for(Int_t i=0;i<=nBin;i++) {
 
  393       (*bins)(i)=binBorders[i];
 
  394       if(!TMath::Finite((*bins)(i))) {
 
  395    Fatal(
"AddAxis",
"bin border %d is not finite",i);
 
  397       } 
else if((i>0)&&((*bins)(i)<=(*bins)(i-1))) {
 
  398    Fatal(
"AddAxis",
"bins not in order x[%d]=%f <= %f=x[%d]",
 
  399          i,(*bins)(i),(*bins)(i-1),i-1);
 
  404       Int_t axis=fAxisList->GetEntriesFast();
 
  405       Int_t bitMask=1<<axis;
 
  408    fHasUnderflow |= bitMask;
 
  411    fHasUnderflow &= ~bitMask;
 
  414    fHasOverflow |= bitMask;
 
  417    fHasOverflow &= ~bitMask;
 
  419       fAxisList->AddLast(bins);
 
  420       fAxisLabelList->AddLast(
new TObjString(name));
 
  421       if(!fDistributionSize) fDistributionSize=1;
 
  422       fDistributionSize *= nBinUO;
 
  423       UpdateFirstLastBin();
 
  436 void TUnfoldBinning::PrintStream(ostream &out,Int_t indent,
int debug)
 
  438    for(Int_t i=0;i<indent;i++) out<<
"  ";
 
  439    out<<
"TUnfoldBinning \""<<GetName()<<
"\" has ";
 
  440    Int_t nBin=GetEndBin()-GetStartBin();
 
  447       <<GetStartBin()<<
","<<GetEndBin()<<
"] nTH1x=" 
  448       <<GetTH1xNumberOfBins()
 
  450    if(GetDistributionNumberOfBins()) {
 
  451       for(Int_t i=0;i<indent;i++) out<<
"  ";
 
  452       out<<
" distribution: "<<GetDistributionNumberOfBins()<<
" bins\n";
 
  453       if(fAxisList->GetEntriesFast()) {
 
  456           for(Int_t axis=0;axis<GetDistributionDimension();axis++) {
 
  457              for(Int_t i=0;i<indent;i++) out<<
"  ";
 
  459                  <<GetDistributionAxisLabel(axis)
 
  460                  <<
"\" nbin="<<GetDistributionBinning(axis)->GetNrows()-1;
 
  461              if(HasUnderflow(axis)) out<<
" plus underflow";
 
  462              if(HasOverflow(axis)) out<<
" plus overflow";
 
  466          for(Int_t i=0;i<indent;i++) out<<
"  ";
 
  468          for(Int_t i=0;i<indent;i++) out<<
"  ";
 
  470          for(Int_t ibin=0;(ibin<GetDistributionNumberOfBins())&&
 
  471                 (ibin<fAxisLabelList->GetEntriesFast());ibin++) {
 
  473             if(GetDistributionAxisLabel(ibin)) {
 
  474                out<<GetDistributionAxisLabel(ibin);
 
  481          for(
int iBin=GetStartBin();iBin<GetEndBin();iBin++) {
 
  482             for(Int_t i=0;i<indent;i++) out<<
"  ";
 
  483             out<<GetBinName(iBin)
 
  484                <<
" size="<<GetBinSize(iBin)
 
  485                <<
" factor="<<GetBinFactor(iBin);
 
  490    TUnfoldBinning 
const *child=GetChildNode();
 
  493          child->PrintStream(out,indent+1,debug);
 
  494          child=child->GetNextNode();
 
  510 void TUnfoldBinning::SetBinFactor
 
  511 (Double_t normalisation,TObject *binfactor) {
 
  512    fBinFactorConstant=normalisation;
 
  513    if(fBinFactorFunction) {
 
  514       if(!dynamic_cast<TF1 *>(fBinFactorFunction))
 
  515          delete fBinFactorFunction;
 
  517    fBinFactorFunction=binfactor;
 
  527 void TUnfoldBinning::SetBinFactorFunction
 
  528 (Double_t normalisation,TF1 *userFunc) {
 
  529    SetBinFactor(normalisation,userFunc);
 
  542 TUnfoldBinning 
const *TUnfoldBinning::FindNode(
char const *name)
 const 
  544    TUnfoldBinning 
const *r=0;
 
  545    if((!name)||(!TString(GetName()).CompareTo(name))) {
 
  548    for(TUnfoldBinning 
const *child=GetChildNode();
 
  549        (!r) && child;child=child->GetNextNode()) {
 
  550       r=child->FindNode(name);
 
  558 TUnfoldBinning *TUnfoldBinning::GetRootNode(
void)
 
  560    TUnfoldBinning *node=
this;
 
  561    while(node->GetParentNode()) node=node->parentNode;
 
  568 TUnfoldBinning 
const *TUnfoldBinning::GetRootNode(
void)
 const 
  570    TUnfoldBinning 
const *node=
this;
 
  571    while(node->GetParentNode()) node=node->GetParentNode();
 
  589 TString TUnfoldBinning::BuildHistogramTitle
 
  590 (
const char *histogramName,
const char *histogramTitle,Int_t 
const *axisList)
 
  599       for(iEnd=2;iEnd>0;iEnd--) {
 
  600          if(axisList[iEnd]>=0) 
break;
 
  602       for(Int_t i=0;i<=iEnd;i++) {
 
  607             r += GetNonemptyNode()->GetDistributionAxisLabel(axisList[i]);
 
  633 TString TUnfoldBinning::BuildHistogramTitle2D
 
  634 (
const char *histogramName,
const char *histogramTitle,
 
  635  Int_t xAxis,
const TUnfoldBinning *yAxisBinning,Int_t yAxis)
 const 
  645       } 
else if(xAxis>=0) {
 
  646          r += GetNonemptyNode()->GetDistributionAxisLabel(xAxis);
 
  650          r += yAxisBinning->GetName();
 
  651       } 
else if(yAxis>=0) {
 
  652          r += yAxisBinning->GetNonemptyNode()->GetDistributionAxisLabel(yAxis);
 
  683 Int_t TUnfoldBinning::GetTH1xNumberOfBins
 
  684 (Bool_t originalAxisBinning,
const char *axisSteering)
 const 
  686    Int_t axisBins[3],axisList[3];
 
  687    GetTHxxBinning(originalAxisBinning ? 1 : 0,axisBins,axisList,
 
  741 TH1 *TUnfoldBinning::CreateHistogram
 
  742 (
const char *histogramName,Bool_t originalAxisBinning,Int_t **binMap,
 
  743  const char *histogramTitle,
const char *axisSteering)
 const 
  745    Int_t nBin[3],axisList[3];
 
  746    Int_t nDim=GetTHxxBinning(originalAxisBinning ? 3 : 0,nBin,axisList,
 
  748    const TUnfoldBinning *neNode=GetNonemptyNode();
 
  749    TString title=BuildHistogramTitle(histogramName,histogramTitle,axisList);
 
  752       const TVectorD *axisBinsX=
 
  753          neNode->GetDistributionBinning(axisList[0]);
 
  755          const TVectorD *axisBinsY=
 
  756             neNode->GetDistributionBinning(axisList[1]);
 
  758             const TVectorD *axisBinsZ=
 
  759                neNode->GetDistributionBinning(axisList[2]);
 
  760             r=
new TH3D(histogramName,title,
 
  761                        nBin[0],axisBinsX->GetMatrixArray(),
 
  762                        nBin[1],axisBinsY->GetMatrixArray(),
 
  763                        nBin[2],axisBinsZ->GetMatrixArray());
 
  765             r=
new TH2D(histogramName,title,
 
  766                        nBin[0],axisBinsX->GetMatrixArray(),
 
  767                        nBin[1],axisBinsY->GetMatrixArray());
 
  770          r=
new TH1D(histogramName,title,nBin[0],axisBinsX->GetMatrixArray());
 
  773       if(originalAxisBinning) {
 
  774          Warning(
"CreateHistogram",
 
  775        "Original binning can not be represented as THxx");
 
  777       r=
new TH1D(histogramName,title,nBin[0],0.5,nBin[0]+0.5);
 
  781       *binMap=CreateBinMap(r,nDim,axisList,axisSteering);
 
  802 TH2D *TUnfoldBinning::CreateErrorMatrixHistogram
 
  803 (
const char *histogramName,Bool_t originalAxisBinning,Int_t **binMap,
 
  804  const char *histogramTitle,
const char *axisSteering)
 const 
  806    Int_t nBin[3],axisList[3];
 
  807    Int_t nDim=GetTHxxBinning(originalAxisBinning ? 1 : 0,nBin,axisList,
 
  809    TString title=BuildHistogramTitle(histogramName,histogramTitle,axisList);
 
  812       const TVectorD *axisBinsX=(TVectorD 
const *)
 
  813          GetNonemptyNode()->fAxisList->At(axisList[0]);
 
  814       r=
new TH2D(histogramName,title,nBin[0],axisBinsX->GetMatrixArray(),
 
  815                  nBin[0],axisBinsX->GetMatrixArray());
 
  817       if(originalAxisBinning) {
 
  818          Info(
"CreateErrorMatrixHistogram",
 
  819               "Original binning can not be represented on one axis");
 
  821       r=
new TH2D(histogramName,title,nBin[0],0.5,nBin[0]+0.5,
 
  822                  nBin[0],0.5,nBin[0]+0.5);
 
  826       *binMap=CreateBinMap(r,nDim,axisList,axisSteering);
 
  845 TH2D *TUnfoldBinning::CreateHistogramOfMigrations
 
  846 (TUnfoldBinning 
const *xAxis,TUnfoldBinning 
const *yAxis,
 
  847  char const *histogramName,Bool_t originalXAxisBinning,
 
  848  Bool_t originalYAxisBinning,
char const *histogramTitle)
 
  850    Int_t nBinX[3],axisListX[3];
 
  852       xAxis->GetTHxxBinning(originalXAxisBinning ? 1 : 0,nBinX,axisListX,0);
 
  853    const TUnfoldBinning *neNodeX=xAxis->GetNonemptyNode();
 
  854    Int_t nBinY[3],axisListY[3];
 
  856       yAxis->GetTHxxBinning(originalYAxisBinning ? 1 : 0,nBinY,axisListY,0);
 
  857    const TUnfoldBinning *neNodeY=yAxis->GetNonemptyNode();
 
  858    TString title=xAxis->BuildHistogramTitle2D
 
  859       (histogramName,histogramTitle,axisListX[0],yAxis,axisListY[0]);
 
  861       const TVectorD *axisBinsX=(TVectorD 
const *)
 
  862             neNodeX->fAxisList->At(axisListX[0]);
 
  864          const TVectorD *axisBinsY=(TVectorD 
const *)
 
  865             neNodeY->fAxisList->At(axisListY[0]);
 
  866          return new TH2D(histogramName,title,
 
  867                          nBinX[0],axisBinsX->GetMatrixArray(),
 
  868                          nBinY[0],axisBinsY->GetMatrixArray());
 
  870          return new TH2D(histogramName,title,
 
  871                          nBinX[0],axisBinsX->GetMatrixArray(),
 
  872                          nBinY[0],0.5,0.5+nBinY[0]);
 
  876          const TVectorD *axisBinsY=(TVectorD 
const *)
 
  877              neNodeY->fAxisList->At(axisListY[0]);
 
  878          return new TH2D(histogramName,title,
 
  879                          nBinX[0],0.5,0.5+nBinX[0],
 
  880                          nBinY[0],axisBinsY->GetMatrixArray());
 
  882          return new TH2D(histogramName,title,
 
  883                          nBinX[0],0.5,0.5+nBinX[0],
 
  884                          nBinY[0],0.5,0.5+nBinY[0]);
 
  903 Int_t TUnfoldBinning::GetTHxxBinning
 
  904 (Int_t maxDim,Int_t *axisBins,Int_t *axisList,
 
  905  const char *axisSteering)
 const 
  907    for(Int_t i=0;i<3;i++) {
 
  911    const TUnfoldBinning *theNode=GetNonemptyNode();
 
  913       Int_t r=theNode->GetTHxxBinningSingleNode
 
  914          (maxDim,axisBins,axisList,axisSteering);
 
  917       axisBins[0]=GetTHxxBinsRecursive(axisSteering);
 
  926 const TUnfoldBinning *TUnfoldBinning::GetNonemptyNode(
void)
 const 
  928    const TUnfoldBinning *r=GetDistributionNumberOfBins()>0 ? 
this : 0;
 
  929    for(TUnfoldBinning 
const *child=GetChildNode();child;
 
  930        child=child->GetNextNode()) {
 
  931       const TUnfoldBinning *c=child->GetNonemptyNode();
 
  962 Int_t TUnfoldBinning::GetTHxxBinningSingleNode
 
  963 (Int_t maxDim,Int_t *axisBins,Int_t *axisList,
const char *axisSteering)
 const 
  969    Int_t isOptionGiven[3];
 
  970    DecodeAxisSteering(axisSteering,
"CUO",isOptionGiven);
 
  972    Int_t numDimension=GetDistributionDimension();
 
  974    for(Int_t i=0;i<numDimension;i++) {
 
  975       if(isOptionGiven[0] & (1<<i)) 
continue;
 
  978    if((r>0)&&(r<=maxDim)) {
 
  984       for(Int_t i=0;i<numDimension;i++) {
 
  985          if(isOptionGiven[0] & (1<<i)) 
continue;
 
  987          axisBins[r]=GetDistributionBinning(i)->GetNrows()-1;
 
  993       if(HasUnconnectedBins() || (GetDistributionNumberOfBins()<=0)) {
 
  994          axisBins[0] = GetDistributionNumberOfBins();
 
  997          for(Int_t i=0;i<numDimension;i++) {
 
  999             if(isOptionGiven[0] & mask) 
continue;
 
 1000             Int_t nBinI=GetDistributionBinning(i)->GetNrows()-1;
 
 1001             if((fHasUnderflow & mask)&& !(isOptionGiven[1] & mask)) nBinI++;
 
 1002             if((fHasOverflow & mask)&& !(isOptionGiven[2] & mask)) nBinI++;
 
 1020 Int_t TUnfoldBinning::GetTHxxBinsRecursive(
const char *axisSteering)
 const 
 1024    for(TUnfoldBinning 
const *child=GetChildNode();child;
 
 1025        child=child->GetNextNode()) {
 
 1026       r +=child->GetTHxxBinsRecursive(axisSteering);
 
 1029    Int_t axisBins[3],axisList[3];
 
 1030    GetTHxxBinningSingleNode(0,axisBins,axisList,axisSteering);
 
 1041 Int_t *TUnfoldBinning::CreateEmptyBinMap(
void)
 const {
 
 1044    Int_t nMax=GetRootNode()->GetEndBin()+1;
 
 1045    Int_t *r=
new Int_t[nMax];
 
 1046    for(Int_t i=0;i<nMax;i++) {
 
 1059 void TUnfoldBinning::SetBinMapEntry
 
 1060 (Int_t *binMap,Int_t globalBin,Int_t destBin)
 const {
 
 1061    Int_t nMax=GetRootNode()->GetEndBin()+1;
 
 1062    if((globalBin<0)||(globalBin>=nMax)) {
 
 1063       Error(
"SetBinMapEntry",
"global bin number %d outside range (max=%d)",
 
 1066       binMap[globalBin]=destBin;
 
 1082 Int_t TUnfoldBinning::FillBinMap1D
 
 1083 (Int_t *binMap,
const char *axisSteering,Int_t firstBinX)
 const {
 
 1085    Int_t axisBins[3],axisList[3];
 
 1086    Int_t nDim=GetTHxxBinningSingleNode(3,axisBins,axisList,axisSteering);
 
 1087    if((nDim==1)|| !GetDistributionDimension()) {
 
 1088       r+=FillBinMapSingleNode(0,r,0,0,axisSteering,binMap);
 
 1090       Error(
"FillBinMap1D",
"distribution %s with steering=%s is not 1D",
 
 1091             (
char *)GetName(),axisSteering);
 
 1093    for(TUnfoldBinning 
const *child=GetChildNode();child;
 
 1094        child=child->GetNextNode()) {
 
 1095       r =child->FillBinMap1D(binMap,axisSteering,r);
 
 1143 Int_t *TUnfoldBinning::CreateBinMap
 
 1144 (
const TH1 *hist,Int_t nDim,
const Int_t *axisList,
const char *axisSteering)
 
 1147    Int_t *r=CreateEmptyBinMap();
 
 1148    Int_t startBin=GetRootNode()->GetStartBin();
 
 1150      const TUnfoldBinning *nonemptyNode=GetNonemptyNode();
 
 1153           FillBinMapSingleNode(hist,startBin,nDim,axisList,axisSteering,r);
 
 1155        Fatal(
"CreateBinMap",
"called with nDim=%d but GetNonemptyNode()=0",
 
 1159      FillBinMapRecursive(startBin,axisSteering,r);
 
 1175 Int_t TUnfoldBinning::FillBinMapRecursive
 
 1176 (Int_t startBin,
const char *axisSteering,Int_t *binMap)
 const 
 1179    nbin = FillBinMapSingleNode(0,startBin,0,0,axisSteering,binMap);
 
 1180    for(TUnfoldBinning 
const *child=GetChildNode();child;
 
 1181        child=child->GetNextNode()) {
 
 1182       nbin += child->FillBinMapRecursive(startBin+nbin,axisSteering,binMap);
 
 1213 Int_t TUnfoldBinning::FillBinMapSingleNode
 
 1214 (
const TH1 *hist,Int_t startBin,Int_t nDim,
const Int_t *axisList,
 
 1215  const char *axisSteering,Int_t *binMap)
 const 
 1221    Int_t isOptionGiven[3+10];
 
 1222    DecodeAxisSteering(axisSteering,
"CUO0123456789",isOptionGiven);
 
 1223    Int_t haveSelectedBin=0;
 
 1224    for(Int_t i=3;i<3+10;i++) {
 
 1225       haveSelectedBin |= isOptionGiven[i];
 
 1228    Int_t axisBins[MAXDIM];
 
 1229    Int_t dimension=GetDistributionDimension();
 
 1230    Int_t axisNbin[MAXDIM];
 
 1231    for(Int_t i=0;i<dimension;i++) {
 
 1232       const TVectorD *binning=GetDistributionBinning(i);
 
 1233       axisNbin[i]=binning->GetNrows()-1;
 
 1235    for(Int_t i=0;i<GetDistributionNumberOfBins();i++) {
 
 1236       Int_t globalBin=GetStartBin()+i;
 
 1237       const TUnfoldBinning *dest=ToAxisBins(globalBin,axisBins);
 
 1240             Fatal(
"FillBinMapSingleNode",
 
 1241                   "bin %d outside binning scheme",
 
 1244             Fatal(
"FillBinMapSingleNode",
 
 1245                   "bin %d located in %s %d-%d rather than %s %d=%d",
 
 1246                   i,(
const char *)dest->GetName(),
 
 1247                   dest->GetStartBin(),dest->GetEndBin(),
 
 1248                   (
const char *)GetName(),GetStartBin(),GetEndBin());
 
 1253       for(Int_t axis=0;axis<dimension;axis++) {
 
 1254          Int_t mask=(1<<axis);
 
 1256          if(((axisBins[axis]<0)&&(isOptionGiven[1] & mask))||
 
 1257             ((axisBins[axis]>=axisNbin[axis])&&(isOptionGiven[2] & mask)))
 
 1260          if((axisBins[axis]>=0)&&(axisBins[axis]<axisNbin[axis])&&
 
 1261             (haveSelectedBin & mask)) {
 
 1262             if(!(isOptionGiven[3+axisBins[axis]] & mask)) skip=kTRUE;
 
 1271          if(nDim==hist->GetDimension()) {
 
 1273             ibin[0]=ibin[1]=ibin[2]=0;
 
 1274             for(Int_t hdim=0;hdim<nDim;hdim++) {
 
 1275                Int_t axis=axisList[hdim];
 
 1276                ibin[hdim]=axisBins[axis]+1;
 
 1278             binMap[globalBin]=hist->GetBin(ibin[0],ibin[1],ibin[2]);
 
 1279          } 
else if(nDim==1) {
 
 1285             if((nDim!=1)||( hist->GetDimension()!=2)) {
 
 1287                Error(
"FillBinMapSingleNode",
"inconsistent dimensions %d %d",nDim,
 
 1288                      hist->GetDimension());
 
 1290             for(Int_t ii=0;ii<hist->GetDimension();ii++) {
 
 1291                if(axisList[ii]>=0) {
 
 1292                   binMap[globalBin]=axisBins[axisList[ii]]+1;
 
 1297             Fatal(
"FillBinMapSingleNode",
"inconsistent dimensions %d %d",nDim,
 
 1298                   hist->GetDimension());
 
 1307             for(Int_t axis=dimension-1;axis>=0;axis--) {
 
 1308                Int_t mask=(1<<axis);
 
 1309                if(isOptionGiven[0] & mask) {
 
 1313                Int_t iBin=axisBins[axis];
 
 1314                Int_t nMax=axisNbin[axis];
 
 1315                if((fHasUnderflow & ~isOptionGiven[1]) & mask) {
 
 1319                if((fHasOverflow & ~isOptionGiven[2]) & mask) {
 
 1324             binMap[globalBin] = startBin + r;
 
 1326       binMap[globalBin] = startBin + axisBins[0];
 
 1333      for(Int_t axis=dimension-1;axis>=0;axis--) {
 
 1334        Int_t mask=(1<<axis);
 
 1335        if(isOptionGiven[0] & mask) {
 
 1339        Int_t nMax=axisNbin[axis];
 
 1340        if((fHasUnderflow & ~isOptionGiven[1]) & mask) {
 
 1343        if((fHasOverflow & ~isOptionGiven[2]) & mask) {
 
 1349      nbin=GetDistributionNumberOfBins();
 
 1374 TH1 *TUnfoldBinning::ExtractHistogram
 
 1375 (
const char *histogramName,
const TH1 *globalBins,
 
 1376  const TH2 *globalBinsEmatrix,Bool_t originalAxisBinning,
 
 1377  const char *axisSteering)
 const 
 1380    TH1 *r=CreateHistogram(histogramName,originalAxisBinning,&binMap,0,
 
 1383    TUnfoldBinning 
const *root=GetRootNode();
 
 1385    for(Int_t iSrc=root->GetStartBin();iSrc<root->GetEndBin();iSrc++) {
 
 1386       if(binMap[iSrc]>nMax) nMax=binMap[iSrc];
 
 1392       TVectorD eSquared(nMax+1);
 
 1393       for(Int_t iSrc=root->GetStartBin();iSrc<root->GetEndBin();iSrc++) {
 
 1394          Int_t iDest=binMap[iSrc];
 
 1396             Double_t c=r->GetBinContent(iDest);
 
 1397             r->SetBinContent(iDest,c+globalBins->GetBinContent(iSrc));
 
 1398             if(!globalBinsEmatrix) {
 
 1399                eSquared(iDest)+=TMath::Power(globalBins->GetBinError(iSrc),2.);
 
 1401                for(Int_t jSrc=root->GetStartBin();jSrc<root->GetEndBin();
 
 1403                   if(binMap[jSrc]==iDest) {
 
 1405                         TMath::Power(globalBins->GetBinError(jSrc),2.);
 
 1411       for(Int_t i=0;i<nMax;i++) {
 
 1412          Double_t e2=eSquared(i);
 
 1414             r->SetBinError(i,TMath::Sqrt(e2));
 
 1433 Int_t TUnfoldBinning::GetGlobalBinNumber(Double_t x)
 const 
 1435    if(GetDistributionDimension()!=1) {
 
 1436       Fatal(
"GetBinNumber",
 
 1437             "called with 1 argument for %d dimensional distribution",
 
 1438             GetDistributionDimension());
 
 1440    return GetGlobalBinNumber(&x);
 
 1453 Int_t TUnfoldBinning::GetGlobalBinNumber(Double_t x,Double_t y)
 const 
 1455    if(GetDistributionDimension()!=2) {
 
 1456       Fatal(
"GetBinNumber",
 
 1457             "called with 2 arguments for %d dimensional distribution",
 
 1458             GetDistributionDimension());
 
 1463    return GetGlobalBinNumber(xx);
 
 1481 Int_t TUnfoldBinning::GetGlobalBinNumber
 
 1482 (Double_t x,Double_t y,Double_t z)
 const 
 1484    if(GetDistributionDimension()!=3) {
 
 1485       Fatal(
"GetBinNumber",
 
 1486             "called with 3 arguments for %d dimensional distribution",
 
 1487             GetDistributionDimension());
 
 1493    return GetGlobalBinNumber(xx);
 
 1512 Int_t TUnfoldBinning::GetGlobalBinNumber
 
 1513 (Double_t x0,Double_t x1,Double_t x2,Double_t x3)
 const 
 1515    if(GetDistributionDimension()!=4) {
 
 1516       Fatal(
"GetBinNumber",
 
 1517             "called with 4 arguments for %d dimensional distribution",
 
 1518             GetDistributionDimension());
 
 1525    return GetGlobalBinNumber(xx);
 
 1545 Int_t TUnfoldBinning::GetGlobalBinNumber
 
 1546 (Double_t x0,Double_t x1,Double_t x2,Double_t x3,Double_t x4)
 const 
 1548    if(GetDistributionDimension()!=5) {
 
 1549       Fatal(
"GetBinNumber",
 
 1550             "called with 5 arguments for %d dimensional distribution",
 
 1551             GetDistributionDimension());
 
 1559    return GetGlobalBinNumber(xx);
 
 1580 Int_t TUnfoldBinning::GetGlobalBinNumber
 
 1581 (Double_t x0,Double_t x1,Double_t x2,Double_t x3,Double_t x4,Double_t x5)
 const 
 1583    if(GetDistributionDimension()!=6) {
 
 1584       Fatal(
"GetBinNumber",
 
 1585             "called with 6 arguments for %d dimensional distribution",
 
 1586             GetDistributionDimension());
 
 1595    return GetGlobalBinNumber(xx);
 
 1627 Int_t TUnfoldBinning::GetGlobalBinNumber
 
 1628 (
const Double_t *x,Int_t *isBelow,Int_t *isAbove)
 const 
 1630    if(!GetDistributionDimension()) {
 
 1631       Fatal(
"GetBinNumber",
 
 1632             "no axes are defined for node %s",
 
 1633             (
char const *)GetName());
 
 1635    Int_t iAxisBins[MAXDIM] = {0};
 
 1636    for(Int_t dim=0;dim<GetDistributionDimension();dim++) {
 
 1637       TVectorD 
const *bins=(TVectorD 
const *) fAxisList->At(dim);
 
 1639       Int_t i1=bins->GetNrows()-1;
 
 1641       if(!(x[dim]>=(*bins)[i0])) {
 
 1644       } 
else if(!(x[dim]<(*bins)[i1])) {
 
 1650             if(x[dim]<(*bins)[i2]) {
 
 1658       iAxisBins[dim]=iBin;
 
 1660    Int_t r=ToGlobalBin(iAxisBins,isBelow,isAbove);
 
 1677 TString TUnfoldBinning::GetBinName(Int_t iBin)
 const 
 1679    Int_t axisBins[MAXDIM];
 
 1680    TString r=TString::Format(
"#%d",iBin);
 
 1681    TUnfoldBinning 
const *distribution=ToAxisBins(iBin,axisBins);
 
 1684       r += distribution->GetName();
 
 1685       Int_t dimension=distribution->GetDistributionDimension();
 
 1688          for(Int_t axis=0;axis<dimension;axis++) {
 
 1689             TString thisAxisString=
 
 1690                distribution->GetDistributionAxisLabel(axis);
 
 1691             TVectorD 
const *bins=distribution->GetDistributionBinning(axis);
 
 1692             Int_t i=axisBins[axis];
 
 1693             if(i<0) thisAxisString += 
"[ufl]";
 
 1694             else if(i>=bins->GetNrows()-1) thisAxisString += 
"[ofl]";
 
 1697                   TString::Format(
"[%.3g,%.3g]",(*bins)[i],(*bins)[i+1]);
 
 1699             axisString = 
":"+thisAxisString+axisString;
 
 1704          Int_t i=axisBins[0];
 
 1705          if((i>=0)&&(i<distribution->fAxisLabelList->GetEntriesFast())) {
 
 1706             r += distribution->GetDistributionAxisLabel(i);
 
 1708             r += TString::Format(
" %d",i);
 
 1723 Double_t TUnfoldBinning::GetBinSize(Int_t iBin)
 const 
 1725    Int_t axisBins[MAXDIM];
 
 1726    TUnfoldBinning 
const *distribution=ToAxisBins(iBin,axisBins);
 
 1729       if(distribution->GetDistributionDimension()>0) r=1.0;
 
 1730       for(Int_t axis=0;axis<distribution->GetDistributionDimension();axis++) {
 
 1731          TVectorD 
const *bins=distribution->GetDistributionBinning(axis);
 
 1732          Int_t pos=axisBins[axis];
 
 1734        r *= distribution->GetDistributionUnderflowBinWidth(axis);
 
 1735          } 
else if(pos>=bins->GetNrows()-1) {
 
 1736        r *= distribution->GetDistributionOverflowBinWidth(axis);
 
 1738             r *= (*bins)(pos+1)-(*bins)(pos);
 
 1749 Bool_t TUnfoldBinning::IsBinFactorGlobal(
void)
 const {
 
 1750    return fBinFactorFunction ? kFALSE : kTRUE;
 
 1756 Double_t TUnfoldBinning::GetGlobalFactor(
void)
 const {
 
 1757    return fBinFactorConstant;
 
 1771 Double_t TUnfoldBinning::GetBinFactor(Int_t iBin)
 const 
 1773    Int_t axisBins[MAXDIM];
 
 1774    TUnfoldBinning 
const *distribution=ToAxisBins(iBin,axisBins);
 
 1775    Double_t r=distribution->fBinFactorConstant;
 
 1776    if((r!=0.0) && distribution->fBinFactorFunction) {
 
 1777       TF1 *
function=
dynamic_cast<TF1 *
>(distribution->fBinFactorFunction);
 
 1780          Int_t dimension=distribution->GetDistributionDimension();
 
 1782             for(Int_t  axis=0;axis<dimension;axis++) {
 
 1783                x[axis]=distribution->GetDistributionBinCenter
 
 1784                   (axis,axisBins[axis]);
 
 1786             r *= 
function->EvalPar(x,function->GetParameters());
 
 1789             r *= 
function->Eval(x[0]);
 
 1792          TVectorD *vect=
dynamic_cast<TVectorD *
> 
 1793             (distribution->fBinFactorFunction);
 
 1795             r=(*vect)[iBin-GetStartBin()];
 
 1797             Error(
"GetBinFactor",
 
 1798                   "internal error: user function is neither TF1 or TVectorD");
 
 1825 Int_t TUnfoldBinning::GetBinNeighbours
 
 1826 (Int_t bin,Int_t axis,Int_t *prev,Double_t *distPrev,
 
 1827  Int_t *next,Double_t *distNext,Bool_t isPeriodic)
 const 
 1829    Int_t axisBins[MAXDIM];
 
 1830    TUnfoldBinning 
const *distribution=ToAxisBins(bin,axisBins);
 
 1831    Int_t dimension=distribution->GetDistributionDimension();
 
 1837    if((axis>=0)&&(axis<dimension)) {
 
 1840       Int_t nMax=GetDistributionBinning(axis)->GetNrows()-1;
 
 1841       Int_t centerBin= axisBins[axis];
 
 1842       axisBins[axis] =centerBin-1;
 
 1844          if(HasUnderflow(axis)) {
 
 1846          } 
else if((axisBins[axis]<0)&&(nMax>=3)) {
 
 1847             axisBins[axis]=nMax-1;
 
 1850       *prev=ToGlobalBin(axisBins);
 
 1852    *distPrev=distribution->GetDistributionBinCenter(axis,axisBins[axis])-
 
 1853      distribution->GetDistributionBinCenter(axis,centerBin);
 
 1855       axisBins[axis] =centerBin+1;
 
 1857          if(HasOverflow(axis)) {
 
 1859          } 
else if((axisBins[axis]==nMax)&&(nMax>=3)) {
 
 1863       *next=ToGlobalBin(axisBins);
 
 1865    *distNext=distribution->GetDistributionBinCenter(axis,axisBins[axis])-
 
 1866      distribution->GetDistributionBinCenter(axis,centerBin);
 
 1879 void TUnfoldBinning::GetBinUnderflowOverflowStatus
 
 1880 (Int_t iBin,Int_t *uStatus,Int_t *oStatus)
 const 
 1882   Int_t axisBins[MAXDIM];
 
 1883   TUnfoldBinning 
const *distribution=ToAxisBins(iBin,axisBins);
 
 1884   Int_t dimension=distribution->GetDistributionDimension();
 
 1887   for(Int_t axis=0;axis<dimension;axis++) {
 
 1888     TVectorD 
const *bins=distribution->GetDistributionBinning(axis);
 
 1889     Int_t nBin=bins->GetNrows()-1;
 
 1890     if(axisBins[axis]<0) *uStatus |= (1<<axis);
 
 1891     if(axisBins[axis]>=nBin) *oStatus |= (1<<axis);
 
 1898 Bool_t TUnfoldBinning::HasUnconnectedBins(
void)
 const 
 1900    return (!GetDistributionDimension())&&(GetDistributionNumberOfBins()>0);
 
 1908 const TObjString *TUnfoldBinning::GetUnconnectedBinName(Int_t bin)
 const {
 
 1909    TObjString 
const *r = 
nullptr;
 
 1910    if(HasUnconnectedBins()) {
 
 1911       if(bin<fAxisLabelList->GetEntriesFast()) {
 
 1912          r = ((TObjString 
const *)fAxisLabelList->At(bin));
 
 1926 Double_t TUnfoldBinning::GetDistributionAverageBinSize
 
 1927 (Int_t axis,Bool_t includeUnderflow,Bool_t includeOverflow)
 const 
 1930    if((axis>=0)&&(axis<GetDistributionDimension())) {
 
 1931       TVectorD 
const *bins=GetDistributionBinning(axis);
 
 1932       Double_t d=(*bins)[bins->GetNrows()-1]-(*bins)[0];
 
 1933       Double_t nBins=bins->GetNrows()-1;
 
 1934       if(includeUnderflow && HasUnderflow(axis)) {
 
 1935          Double_t w=GetDistributionUnderflowBinWidth(axis);
 
 1941       if(includeOverflow && HasOverflow(axis)) {
 
 1942          Double_t w=GetDistributionOverflowBinWidth(axis);
 
 1952       Error(
"GetDistributionAverageBinSize",
"axis %d does not exist",axis);
 
 1968 Double_t TUnfoldBinning::GetDistributionUnderflowBinWidth(Int_t axis)
 const 
 1970    TVectorD 
const *bins=GetDistributionBinning(axis);
 
 1971    return (*bins)[1]-(*bins)[0];
 
 1985 Double_t TUnfoldBinning::GetDistributionOverflowBinWidth(Int_t axis)
 const 
 1987    TVectorD 
const *bins=GetDistributionBinning(axis);
 
 1988    return (*bins)[bins->GetNrows()-1]-(*bins)[bins->GetNrows()-2];
 
 2007 Double_t TUnfoldBinning::GetDistributionBinCenter
 
 2008 (Int_t axis,Int_t bin)
 const 
 2010    TVectorD 
const *bins=GetDistributionBinning(axis);
 
 2014       r=(*bins)[0]-0.5*GetDistributionUnderflowBinWidth(axis);
 
 2015    } 
else if(bin>=bins->GetNrows()-1) {
 
 2017       r=(*bins)[bins->GetNrows()-1]+0.5*GetDistributionOverflowBinWidth(axis);
 
 2019       r=0.5*((*bins)[bin+1]+(*bins)[bin]);
 
 2035 Int_t TUnfoldBinning::ToGlobalBin
 
 2036 (Int_t 
const *axisBins,Int_t *isBelow,Int_t *isAbove)
 const 
 2038   Int_t dimension=GetDistributionDimension();
 
 2040   if(isBelow) *isBelow=0;
 
 2041   if(isAbove) *isAbove=0;
 
 2043     for(Int_t axis=dimension-1;axis>=0;axis--) {
 
 2044       Int_t nMax=GetDistributionBinning(axis)->GetNrows()-1;
 
 2045       Int_t i=axisBins[axis];
 
 2046       if(HasUnderflow(axis)) {
 
 2050       if(HasOverflow(axis)) nMax +=1;
 
 2051       if((i>=0)&&(i<nMax)) {
 
 2052          if(r>=0) r = r*nMax +i;
 
 2055          if((i<0)&&(isBelow)) *isBelow |= 1<<axis;
 
 2056          if((i>=nMax)&&(isAbove)) *isAbove |= 1<<axis;
 
 2063     if((axisBins[0]>=0)&&(axisBins[0]<GetDistributionNumberOfBins()))
 
 2064       r=GetStartBin()+axisBins[0];
 
 2066        Fatal(
"ToGlobalBin",
"bad input %d for dimensionless binning %s %d",
 
 2067              axisBins[0],(
const char *)GetName(),
 
 2068              GetDistributionNumberOfBins());
 
 2083 TUnfoldBinning 
const *TUnfoldBinning::ToAxisBins
 
 2084 (Int_t globalBin,Int_t *axisBins)
 const 
 2086    TUnfoldBinning 
const *r=0;
 
 2087    if((globalBin>=GetStartBin())&&(globalBin<GetEndBin())) {
 
 2088       TUnfoldBinning 
const *node;
 
 2089       for(node=GetChildNode();node && !r; node=node->GetNextNode()) {
 
 2090          r=node->ToAxisBins(globalBin,axisBins);
 
 2094          Int_t i=globalBin-GetStartBin();
 
 2095          Int_t dimension=GetDistributionDimension();
 
 2097             for(
int axis=0;axis<dimension;axis++) {
 
 2098                Int_t nMax=GetDistributionBinning(axis)->GetNrows()-1;
 
 2100                if(HasUnderflow(axis)) {
 
 2104                if(HasOverflow(axis)) nMax +=1;
 
 2105                axisBins[axis] += i % nMax;
 
 2135 void TUnfoldBinning::DecodeAxisSteering
 
 2136 (
const char *axisSteering,
const char *options,Int_t *isOptionGiven)
 const 
 2138   Int_t nOpt=TString(options).Length();
 
 2139   for(Int_t i=0;i<nOpt;i++) isOptionGiven[i]=0;
 
 2141      TObjArray *patterns=TString(axisSteering).Tokenize(
";");
 
 2142      Int_t nPattern=patterns->GetEntries();
 
 2143      Int_t nAxis=fAxisLabelList->GetEntries();
 
 2144      for(Int_t i=0;i<nPattern;i++) {
 
 2145         TString 
const &pattern=((TObjString 
const *)patterns->At(i))
 
 2147         Int_t bracketBegin=pattern.Last(
'[');
 
 2148         Int_t len=pattern.Length();
 
 2149         if((bracketBegin>0)&&(pattern[len-1]==
']')) {
 
 2150      TString axisId=pattern(0,bracketBegin);
 
 2152      if((axisId[0]==
'*')&&(axisId.Length()==1)) {
 
 2157        for(Int_t j=0;j<nAxis;j++) {
 
 2158          if(!axisId.CompareTo(GetDistributionAxisLabel(j))) {
 
 2163      for(Int_t o=0;o<nOpt;o++) {
 
 2164        if(pattern.Last(options[o])>bracketBegin) {
 
 2165          isOptionGiven[o] |= mask;
 
 2169            Error(
"DecodeAxisSteering",
 
 2170                  "steering \"%s\" does not end with [options]",
 
 2171        (
const char *)pattern);