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);