#include "TUnfoldDensity.h"
#include <TMath.h>
#include <TVectorD.h>
#include <TObjString.h>
#include <iostream>
#include <map>
ClassImp(TUnfoldDensity)
TUnfoldDensity::TUnfoldDensity(void)
{
fConstOutputBins=0;
fConstInputBins=0;
fOwnedOutputBins=0;
fOwnedInputBins=0;
fRegularisationConditions=0;
}
TUnfoldDensity::~TUnfoldDensity(void)
{
if(fOwnedOutputBins) delete fOwnedOutputBins;
if(fOwnedInputBins) delete fOwnedInputBins;
if(fRegularisationConditions) delete fRegularisationConditions;
}
TUnfoldDensity::TUnfoldDensity
(const TH2 *hist_A, EHistMap histmap,ERegMode regmode,EConstraint constraint,
EDensityMode densityMode,const TUnfoldBinning *outputBins,
const TUnfoldBinning *inputBins,const char *regularisationDistribution,
const char *regularisationAxisSteering) :
TUnfoldSys(hist_A,histmap,kRegModeNone,constraint)
{
fRegularisationConditions=0;
fConstOutputBins = outputBins;
fOwnedOutputBins = 0;
TAxis const *genAxis,*detAxis;
if(histmap==kHistMapOutputHoriz) {
genAxis=hist_A->GetXaxis();
detAxis=hist_A->GetYaxis();
} else {
genAxis=hist_A->GetYaxis();
detAxis=hist_A->GetXaxis();
}
if(!fConstOutputBins) {
fOwnedOutputBins =
new TUnfoldBinning(*genAxis,1,1);
fConstOutputBins = fOwnedOutputBins;
}
if(fConstOutputBins->GetParentNode()) {
Error("TUnfoldDensity",
"Invalid output binning scheme (node is not the root node)");
}
fConstInputBins = inputBins;
fOwnedInputBins = 0;
if(!fConstInputBins) {
fOwnedInputBins =
new TUnfoldBinning(*detAxis,0,0);
fConstInputBins = fOwnedInputBins;
}
if(fConstInputBins->GetParentNode()) {
Error("TUnfoldDensity",
"Invalid input binning scheme (node is not the root node)");
}
Int_t nOut=genAxis->GetNbins();
Int_t nOutMapped=TMath::Abs(fConstOutputBins->GetTH1xNumberOfBins());
if(nOutMapped!= nOut) {
Error("TUnfoldDensity",
"Output binning incompatible number of bins %d!=%d",
nOutMapped, nOut);
}
Int_t nInput=detAxis->GetNbins();
Int_t nInputMapped=TMath::Abs(fConstInputBins->GetTH1xNumberOfBins());
if(nInputMapped!= nInput) {
Error("TUnfoldDensity",
"Input binning incompatible number of bins %d!=%d ",
nInputMapped, nInput);
}
for (Int_t ix = 0; ix <= nOut+1; ix++) {
if(fHistToX[ix]<0) {
Info("TUnfold","*NOT* unfolding bin %s",GetOutputBinName(ix).Data());
}
}
if(regmode !=kRegModeNone) {
RegularizeDistribution
(regmode,densityMode,regularisationDistribution,
regularisationAxisSteering);
}
}
TString TUnfoldDensity::GetOutputBinName(Int_t iBinX) const {
if(!fConstOutputBins) return TUnfold::GetOutputBinName(iBinX);
else return fConstOutputBins->GetBinName(iBinX);
}
Double_t TUnfoldDensity::GetDensityFactor
(EDensityMode densityMode,Int_t iBin) const
{
Double_t factor=1.0;
if((densityMode == kDensityModeBinWidth)||
(densityMode == kDensityModeBinWidthAndUser)) {
Double_t binSize=fConstOutputBins->GetBinSize(iBin);
if(binSize>0.0) factor /= binSize;
else factor=0.0;
}
if((densityMode == kDensityModeUser)||
(densityMode == kDensityModeBinWidthAndUser)) {
factor *= fConstOutputBins->GetBinFactor(iBin);
}
return factor;
}
void TUnfoldDensity::RegularizeDistribution
(ERegMode regmode,EDensityMode densityMode,const char *distribution,
const char *axisSteering)
{
RegularizeDistributionRecursive(GetOutputBinning(),regmode,densityMode,
distribution,axisSteering);
}
void TUnfoldDensity::RegularizeDistributionRecursive
(const TUnfoldBinning *binning,ERegMode regmode,
EDensityMode densityMode,const char *distribution,const char *axisSteering) {
if((!distribution)|| !TString(distribution).CompareTo(binning->GetName())) {
RegularizeOneDistribution(binning,regmode,densityMode,axisSteering);
}
for(const TUnfoldBinning *child=binning->GetChildNode();child;
child=child->GetNextNode()) {
RegularizeDistributionRecursive(child,regmode,densityMode,distribution,
axisSteering);
}
}
void TUnfoldDensity::RegularizeOneDistribution
(const TUnfoldBinning *binning,ERegMode regmode,
EDensityMode densityMode,const char *axisSteering)
{
if(!fRegularisationConditions)
fRegularisationConditions=new TUnfoldBinning("regularisation");
TUnfoldBinning *thisRegularisationBinning=
fRegularisationConditions->AddBinning(binning->GetName());
Int_t isOptionGiven[6] = {0};
binning->DecodeAxisSteering(axisSteering,"uUoObB",isOptionGiven);
isOptionGiven[0] |= isOptionGiven[1];
isOptionGiven[2] |= isOptionGiven[3];
isOptionGiven[4] |= isOptionGiven[5];
#ifdef DEBUG
cout<<" "<<isOptionGiven[0]
<<" "<<isOptionGiven[1]
<<" "<<isOptionGiven[2]
<<" "<<isOptionGiven[3]
<<" "<<isOptionGiven[4]
<<" "<<isOptionGiven[5]
<<"\n";
#endif
Info("RegularizeOneDistribution","regularizing %s regMode=%d"
" densityMode=%d axisSteering=%s",
binning->GetName(),(Int_t) regmode,(Int_t)densityMode,
axisSteering ? axisSteering : "");
Int_t startBin=binning->GetStartBin();
Int_t endBin=startBin+ binning->GetDistributionNumberOfBins();
std::vector<Double_t> factor(endBin-startBin);
Int_t nbin=0;
for(Int_t bin=startBin;bin<endBin;bin++) {
factor[bin-startBin]=GetDensityFactor(densityMode,bin);
if(factor[bin-startBin] !=0.0) nbin++;
}
#ifdef DEBUG
cout<<"initial number of bins "<<nbin<<"\n";
#endif
Int_t dimension=binning->GetDistributionDimension();
nbin=0;
for(Int_t bin=startBin;bin<endBin;bin++) {
Int_t uStatus,oStatus;
binning->GetBinUnderflowOverflowStatus(bin,&uStatus,&oStatus);
if(uStatus & isOptionGiven[1]) factor[bin-startBin]=0.;
if(oStatus & isOptionGiven[3]) factor[bin-startBin]=0.;
if(factor[bin-startBin] !=0.0) nbin++;
}
#ifdef DEBUG
cout<<"after underflow/overflow bin removal "<<nbin<<"\n";
#endif
if(regmode==kRegModeSize) {
Int_t nRegBins=0;
for(Int_t bin=startBin;bin<endBin;bin++) {
if(factor[bin-startBin]==0.0) continue;
if(AddRegularisationCondition(bin,factor[bin-startBin])) {
nRegBins++;
}
}
if(nRegBins) {
thisRegularisationBinning->AddBinning("size",nRegBins);
}
} else if((regmode==kRegModeDerivative)||(regmode==kRegModeCurvature)) {
for(Int_t direction=0;direction<dimension;direction++) {
Int_t nRegBins=0;
Int_t directionMask=(1<<direction);
Double_t binDistanceNormalisation=
(isOptionGiven[5] & directionMask) ?
binning->GetDistributionAverageBinSize
(direction,isOptionGiven[0] & directionMask,
isOptionGiven[2] & directionMask) : 1.0;
for(Int_t bin=startBin;bin<endBin;bin++) {
if(factor[bin-startBin]==0.0) continue;
Int_t iPrev,iNext;
Double_t distPrev,distNext;
binning->GetBinNeighbours
(bin,direction,&iPrev,&distPrev,&iNext,&distNext);
if((regmode==kRegModeDerivative)&&(iNext>=0)) {
Double_t f0 = -factor[bin-startBin];
Double_t f1 = factor[iNext-startBin];
if(isOptionGiven[4] & directionMask) {
if(distNext>0.0) {
f0 *= binDistanceNormalisation/distNext;
f1 *= binDistanceNormalisation/distNext;
} else {
f0=0.;
f1=0.;
}
}
if((f0==0.0)||(f1==0.0)) continue;
if(AddRegularisationCondition(bin,f0,iNext,f1)) {
nRegBins++;
#ifdef DEBUG
std::cout<<"Added Reg: bin "<<bin<<" "<<f0
<<" next: "<<iNext<<" "<<f1<<"\n";
#endif
}
} else if((regmode==kRegModeCurvature)&&(iPrev>=0)&&(iNext>=0)) {
Double_t f0 = factor[iPrev-startBin];
Double_t f1 = -factor[bin-startBin];
Double_t f2 = factor[iNext-startBin];
if(isOptionGiven[4] & directionMask) {
if((distPrev<0.)&&(distNext>0.)) {
distPrev= -distPrev;
Double_t f=TMath::Power(binDistanceNormalisation,2.)/
(distPrev+distNext);
f0 *= f/distPrev;
f1 *= f*(1./distPrev+1./distNext);
f2 *= f/distNext;
} else {
f0=0.;
f1=0.;
f2=0.;
}
}
if((f0==0.0)||(f1==0.0)||(f2==0.0)) continue;
if(AddRegularisationCondition(iPrev,f0,bin,f1,iNext,f2)) {
nRegBins++;
#ifdef DEBUG
std::cout<<"Added Reg: prev "<<iPrev<<" "<<f0
<<" bin: "<<bin<<" "<<f1
<<" next: "<<iNext<<" "<<f2<<"\n";
#endif
}
}
}
if(nRegBins) {
TString name;
if(regmode==kRegModeDerivative) {
name="derivative_";
} else if(regmode==kRegModeCurvature) {
name="curvature_";
}
name += binning->GetDistributionAxisLabel(direction);
thisRegularisationBinning->AddBinning(name,nRegBins);
}
}
}
#ifdef DEBUG
#endif
}
TH1 *TUnfoldDensity::GetOutput
(const char *histogramName,const char *histogramTitle,
const char *distributionName,const char *axisSteering,
Bool_t useAxisBinning) const
{
TUnfoldBinning const *binning=fConstOutputBins->FindNode(distributionName);
Int_t *binMap=0;
TH1 *r=binning->CreateHistogram
(histogramName,useAxisBinning,&binMap,histogramTitle,axisSteering);
if(r) {
TUnfoldSys::GetOutput(r,binMap);
}
if(binMap) {
delete [] binMap;
}
return r;
}
TH1 *TUnfoldDensity::GetBias
(const char *histogramName,const char *histogramTitle,
const char *distributionName,const char *axisSteering,
Bool_t useAxisBinning) const
{
TUnfoldBinning const *binning=fConstOutputBins->FindNode(distributionName);
Int_t *binMap=0;
TH1 *r=binning->CreateHistogram
(histogramName,useAxisBinning,&binMap,histogramTitle,axisSteering);
if(r) {
TUnfoldSys::GetBias(r,binMap);
}
if(binMap) delete [] binMap;
return r;
}
TH1 *TUnfoldDensity::GetFoldedOutput
(const char *histogramName,const char *histogramTitle,
const char *distributionName,const char *axisSteering,
Bool_t useAxisBinning,Bool_t addBgr) const
{
TUnfoldBinning const *binning=fConstInputBins->FindNode(distributionName);
Int_t *binMap=0;
TH1 *r=binning->CreateHistogram
(histogramName,useAxisBinning,&binMap,histogramTitle,axisSteering);
if(r) {
TUnfoldSys::GetFoldedOutput(r,binMap);
if(addBgr) {
TUnfoldSys::GetBackground(r,0,binMap,0,kFALSE);
}
}
if(binMap) delete [] binMap;
return r;
}
TH1 *TUnfoldDensity::GetBackground
(const char *histogramName,const char *bgrSource,const char *histogramTitle,
const char *distributionName,const char *axisSteering,Bool_t useAxisBinning,
Int_t includeError,Bool_t clearHist) const
{
TUnfoldBinning const *binning=fConstInputBins->FindNode(distributionName);
Int_t *binMap=0;
TH1 *r=binning->CreateHistogram
(histogramName,useAxisBinning,&binMap,histogramTitle,axisSteering);
if(r) {
TUnfoldSys::GetBackground(r,bgrSource,binMap,includeError,clearHist);
}
if(binMap) delete [] binMap;
return r;
}
TH1 *TUnfoldDensity::GetInput
(const char *histogramName,const char *histogramTitle,
const char *distributionName,const char *axisSteering,
Bool_t useAxisBinning) const
{
TUnfoldBinning const *binning=fConstInputBins->FindNode(distributionName);
Int_t *binMap=0;
TH1 *r=binning->CreateHistogram
(histogramName,useAxisBinning,&binMap,histogramTitle,axisSteering);
if(r) {
TUnfoldSys::GetInput(r,binMap);
}
if(binMap) delete [] binMap;
return r;
}
TH1 *TUnfoldDensity::GetRhoItotal
(const char *histogramName,const char *histogramTitle,
const char *distributionName,const char *axisSteering,
Bool_t useAxisBinning,TH2 **ematInv) {
TUnfoldBinning const *binning=fConstOutputBins->FindNode(distributionName);
Int_t *binMap=0;
TH1 *r=binning->CreateHistogram
(histogramName,useAxisBinning,&binMap,histogramTitle,axisSteering);
if(r) {
TH2 *invEmat=0;
if(ematInv) {
if(r->GetDimension()==1) {
TString ematName(histogramName);
ematName += "_inverseEMAT";
Int_t *binMap2D=0;
invEmat=binning->CreateErrorMatrixHistogram
(ematName,useAxisBinning,&binMap2D,histogramTitle,
axisSteering);
if(binMap2D) delete [] binMap2D;
} else {
Error("GetRhoItotal",
"can not return inverse of error matrix for this binning");
}
}
TUnfoldSys::GetRhoItotal(r,binMap,invEmat);
if(invEmat) {
*ematInv=invEmat;
}
}
if(binMap) delete [] binMap;
return r;
}
TH1 *TUnfoldDensity::GetRhoIstatbgr
(const char *histogramName,const char *histogramTitle,
const char *distributionName,const char *axisSteering,
Bool_t useAxisBinning,TH2 **ematInv) {
TUnfoldBinning const *binning=fConstOutputBins->FindNode(distributionName);
Int_t *binMap=0;
TH1 *r=binning->CreateHistogram
(histogramName,useAxisBinning,&binMap,histogramTitle,axisSteering);
if(r) {
TH2 *invEmat=0;
if(ematInv) {
if(r->GetDimension()==1) {
TString ematName(histogramName);
ematName += "_inverseEMAT";
Int_t *binMap2D=0;
invEmat=binning->CreateErrorMatrixHistogram
(ematName,useAxisBinning,&binMap2D,histogramTitle,
axisSteering);
if(binMap2D) delete [] binMap2D;
} else {
Error("GetRhoItotal",
"can not return inverse of error matrix for this binning");
}
}
TUnfoldSys::GetRhoI(r,binMap,invEmat);
if(invEmat) {
*ematInv=invEmat;
}
}
if(binMap) delete [] binMap;
return r;
}
TH1 *TUnfoldDensity::GetDeltaSysSource
(const char *source,const char *histogramName,
const char *histogramTitle,const char *distributionName,
const char *axisSteering,Bool_t useAxisBinning) {
TUnfoldBinning const *binning=fConstOutputBins->FindNode(distributionName);
Int_t *binMap=0;
TH1 *r=binning->CreateHistogram
(histogramName,useAxisBinning,&binMap,histogramTitle,axisSteering);
if(r) {
if(!TUnfoldSys::GetDeltaSysSource(r,source,binMap)) {
delete r;
r=0;
}
}
if(binMap) delete [] binMap;
return r;
}
TH1 *TUnfoldDensity::GetDeltaSysBackgroundScale
(const char *bgrSource,const char *histogramName,
const char *histogramTitle,const char *distributionName,
const char *axisSteering,Bool_t useAxisBinning) {
TUnfoldBinning const *binning=fConstOutputBins->FindNode(distributionName);
Int_t *binMap=0;
TH1 *r=binning->CreateHistogram
(histogramName,useAxisBinning,&binMap,histogramTitle,axisSteering);
if(r) {
if(!TUnfoldSys::GetDeltaSysBackgroundScale(r,bgrSource,binMap)) {
delete r;
r=0;
}
}
if(binMap) delete [] binMap;
return r;
}
TH1 *TUnfoldDensity::GetDeltaSysTau
(const char *histogramName,const char *histogramTitle,
const char *distributionName,const char *axisSteering,Bool_t useAxisBinning)
{
TUnfoldBinning const *binning=fConstOutputBins->FindNode(distributionName);
Int_t *binMap=0;
TH1 *r=binning->CreateHistogram
(histogramName,useAxisBinning,&binMap,histogramTitle,axisSteering);
if(r) {
if(!TUnfoldSys::GetDeltaSysTau(r,binMap)) {
delete r;
r=0;
}
}
if(binMap) delete [] binMap;
return r;
}
TH2 *TUnfoldDensity::GetRhoIJtotal
(const char *histogramName,const char *histogramTitle,
const char *distributionName,const char *axisSteering,
Bool_t useAxisBinning)
{
TH2 *r=GetEmatrixTotal
(histogramName,histogramTitle,distributionName,
axisSteering,useAxisBinning);
if(r) {
for(Int_t i=0;i<=r->GetNbinsX()+1;i++) {
Double_t e_i=r->GetBinContent(i,i);
if(e_i>0.0) e_i=TMath::Sqrt(e_i);
else e_i=0.0;
for(Int_t j=0;j<=r->GetNbinsY()+1;j++) {
if(i==j) continue;
Double_t e_j=r->GetBinContent(j,j);
if(e_j>0.0) e_j=TMath::Sqrt(e_j);
else e_j=0.0;
Double_t e_ij=r->GetBinContent(i,j);
if((e_i>0.0)&&(e_j>0.0)) {
r->SetBinContent(i,j,e_ij/e_i/e_j);
} else {
r->SetBinContent(i,j,0.0);
}
}
}
for(Int_t i=0;i<=r->GetNbinsX()+1;i++) {
if(r->GetBinContent(i,i)>0.0) {
r->SetBinContent(i,i,1.0);
} else {
r->SetBinContent(i,i,0.0);
}
}
}
return r;
}
TH2 *TUnfoldDensity::GetEmatrixSysUncorr
(const char *histogramName,const char *histogramTitle,
const char *distributionName,const char *axisSteering,
Bool_t useAxisBinning)
{
TUnfoldBinning const *binning=fConstOutputBins->FindNode(distributionName);
Int_t *binMap=0;
TH2 *r=binning->CreateErrorMatrixHistogram
(histogramName,useAxisBinning,&binMap,histogramTitle,axisSteering);
if(r) {
TUnfoldSys::GetEmatrixSysUncorr(r,binMap);
}
if(binMap) delete [] binMap;
return r;
}
TH2 *TUnfoldDensity::GetEmatrixSysBackgroundUncorr
(const char *bgrSource,const char *histogramName,
const char *histogramTitle,const char *distributionName,
const char *axisSteering,Bool_t useAxisBinning)
{
TUnfoldBinning const *binning=fConstOutputBins->FindNode(distributionName);
Int_t *binMap=0;
TH2 *r=binning->CreateErrorMatrixHistogram
(histogramName,useAxisBinning,&binMap,histogramTitle,axisSteering);
if(r) {
TUnfoldSys::GetEmatrixSysBackgroundUncorr(r,bgrSource,binMap,kFALSE);
}
if(binMap) delete [] binMap;
return r;
}
TH2 *TUnfoldDensity::GetEmatrixInput
(const char *histogramName,const char *histogramTitle,
const char *distributionName,const char *axisSteering,
Bool_t useAxisBinning)
{
TUnfoldBinning const *binning=fConstOutputBins->FindNode(distributionName);
Int_t *binMap=0;
TH2 *r=binning->CreateErrorMatrixHistogram
(histogramName,useAxisBinning,&binMap,histogramTitle,axisSteering);
if(r) {
TUnfoldSys::GetEmatrixInput(r,binMap);
}
if(binMap) delete [] binMap;
return r;
}
TH2 *TUnfoldDensity::GetProbabilityMatrix
(const char *histogramName,const char *histogramTitle,
Bool_t useAxisBinning) const
{
TH2 *r=TUnfoldBinning::CreateHistogramOfMigrations
(fConstOutputBins,fConstInputBins,histogramName,
useAxisBinning,useAxisBinning,histogramTitle);
TUnfold::GetProbabilityMatrix(r,kHistMapOutputHoriz);
return r;
}
TH2 *TUnfoldDensity::GetEmatrixTotal
(const char *histogramName,const char *histogramTitle,
const char *distributionName,const char *axisSteering,
Bool_t useAxisBinning)
{
TUnfoldBinning const *binning=fConstOutputBins->FindNode(distributionName);
Int_t *binMap=0;
TH2 *r=binning->CreateErrorMatrixHistogram
(histogramName,useAxisBinning,&binMap,histogramTitle,axisSteering);
if(r) {
TUnfoldSys::GetEmatrixTotal(r,binMap);
}
if(binMap) delete [] binMap;
return r;
}
TH2 *TUnfoldDensity::GetL
(const char *histogramName,const char *histogramTitle,Bool_t useAxisBinning)
{
if(fRegularisationConditions &&
(fRegularisationConditions->GetEndBin()-
fRegularisationConditions->GetStartBin()!= fL->GetNrows())) {
Warning("GetL",
"remove invalid scheme of regularisation conditions %d %d",
fRegularisationConditions->GetEndBin(),fL->GetNrows());
delete fRegularisationConditions;
fRegularisationConditions=0;
}
if(!fRegularisationConditions) {
fRegularisationConditions=new TUnfoldBinning("regularisation",fL->GetNrows());
Warning("GetL","create flat regularisation conditions scheme");
}
TH2 *r=TUnfoldBinning::CreateHistogramOfMigrations
(fConstOutputBins,fRegularisationConditions,histogramName,
useAxisBinning,useAxisBinning,histogramTitle);
TUnfold::GetL(r);
return r;
}
TH1 *TUnfoldDensity::GetLxMinusBias
(const char *histogramName,const char *histogramTitle)
{
TMatrixD dx(*GetX(), TMatrixD::kMinus, fBiasScale * (*fX0));
TMatrixDSparse *Ldx=MultiplyMSparseM(fL,&dx);
if(fRegularisationConditions &&
(fRegularisationConditions->GetEndBin()-
fRegularisationConditions->GetStartBin()!= fL->GetNrows())) {
Warning("GetLxMinusBias",
"remove invalid scheme of regularisation conditions %d %d",
fRegularisationConditions->GetEndBin(),fL->GetNrows());
delete fRegularisationConditions;
fRegularisationConditions=0;
}
if(!fRegularisationConditions) {
fRegularisationConditions=new TUnfoldBinning("regularisation",fL->GetNrows());
Warning("GetLxMinusBias","create flat regularisation conditions scheme");
}
TH1 *r=fRegularisationConditions->CreateHistogram
(histogramName,kFALSE,0,histogramTitle);
const Int_t *Ldx_rows=Ldx->GetRowIndexArray();
const Double_t *Ldx_data=Ldx->GetMatrixArray();
for(Int_t row=0;row<Ldx->GetNrows();row++) {
if(Ldx_rows[row]<Ldx_rows[row+1]) {
r->SetBinContent(row+1,Ldx_data[Ldx_rows[row]]);
}
}
delete Ldx;
return r;
}
const TUnfoldBinning *TUnfoldDensity::GetInputBinning
(const char *distributionName) const
{
return fConstInputBins->FindNode(distributionName);
}
const TUnfoldBinning *TUnfoldDensity::GetOutputBinning
(const char *distributionName) const
{
return fConstOutputBins->FindNode(distributionName);
}
Int_t TUnfoldDensity::ScanTau
(Int_t nPoint,Double_t tauMin,Double_t tauMax,TSpline **scanResult,
Int_t mode,const char *distribution,const char *axisSteering,
TGraph **lCurvePlot,TSpline **logTauXPlot,TSpline **logTauYPlot)
{
typedef std::map<Double_t,Double_t> TauScan_t;
typedef std::map<Double_t,std::pair<Double_t,Double_t> > LCurve_t;
TauScan_t curve;
LCurve_t lcurve;
if((tauMin<=0)||(tauMax<=0.0)||(tauMin>=tauMax)) {
DoUnfold(0.0);
if(GetNdf()<=0) {
Error("ScanTau","too few input bins, NDF<=0 %d",GetNdf());
}
Double_t X0=GetLcurveX();
Double_t Y0=GetLcurveY();
Double_t y0=GetScanVariable(mode,distribution,axisSteering);
Info("ScanTau","logtau=-Infinity y=%lf X=%lf Y=%lf",y0,X0,Y0);
{
Double_t logTau=
0.5*(TMath::Log10(GetChi2A()+3.*TMath::Sqrt(GetNdf()+1.0))
-GetLcurveY());
DoUnfold(TMath::Power(10.,logTau));
if((!TMath::Finite(GetLcurveX())) ||(!TMath::Finite(GetLcurveY()))) {
Fatal("ScanTau","problem (missing regularisation?) X=%f Y=%f",
GetLcurveX(),GetLcurveY());
}
Double_t y=GetScanVariable(mode,distribution,axisSteering);
curve[logTau]=y;
lcurve[logTau]=std::make_pair(GetLcurveX(),GetLcurveY());
Info("ScanTau","logtau=%lf y=%lf X=%lf Y=%lf",logTau,y,
GetLcurveX(),GetLcurveY());
}
while(((int)curve.size()<nPoint-1)&&
((TMath::Abs(GetLcurveX()-X0)>0.00432)||
(TMath::Abs(GetLcurveY()-Y0)>0.00432))) {
Double_t logTau=(*curve.begin()).first-0.5;
DoUnfold(TMath::Power(10.,logTau));
Double_t y=GetScanVariable(mode,distribution,axisSteering);
curve[logTau]=y;
lcurve[logTau]=std::make_pair(GetLcurveX(),GetLcurveY());
Info("ScanTay","logtau=%lf y=%lf X=%lf Y=%lf",logTau,y,
GetLcurveX(),GetLcurveY());
}
} else {
Double_t logTauMin=TMath::Log10(tauMin);
Double_t logTauMax=TMath::Log10(tauMax);
if(nPoint>1) {
DoUnfold(TMath::Power(10.,logTauMax));
Double_t y=GetScanVariable(mode,distribution,axisSteering);
curve[logTauMax]=y;
lcurve[logTauMax]=std::make_pair(GetLcurveX(),GetLcurveY());
Info("ScanTau","logtau=%lf y=%lf X=%lf Y=%lf",logTauMax,y,
GetLcurveX(),GetLcurveY());
}
DoUnfold(TMath::Power(10.,logTauMin));
Double_t y=GetScanVariable(mode,distribution,axisSteering);
curve[logTauMin]=y;
lcurve[logTauMin]=std::make_pair(GetLcurveX(),GetLcurveY());
Info("ScanTau","logtau=%lf y=%lf X=%lf Y=%lf",logTauMin,y,
GetLcurveX(),GetLcurveY());
}
while((int)curve.size()<nPoint-1) {
TauScan_t::const_iterator i0,i1;
i0=curve.begin();
Double_t logTauYMin=(*i0).first;
Double_t yMin=(*i0).second;
for(;i0!=curve.end();i0++) {
if((*i0).second<yMin) {
yMin=(*i0).second;
logTauYMin=(*i0).first;
}
}
i0=curve.begin();
i1=i0;
Double_t distMax=0.0;
Double_t logTau=0.0;
for(i1++;i1!=curve.end();i1++) {
Double_t dist;
dist=TMath::Abs((*i0).first-(*i1).first)
+0.25*TMath::Power(0.5*((*i0).first+(*i1).first)-logTauYMin,2.)/
((*curve.rbegin()).first-(*curve.begin()).first)/nPoint;
if((dist<=0.0)||(dist>distMax)) {
distMax=dist;
logTau=0.5*((*i0).first+(*i1).first);
}
i0=i1;
}
DoUnfold(TMath::Power(10.,logTau));
Double_t y=GetScanVariable(mode,distribution,axisSteering);
curve[logTau]=y;
lcurve[logTau]=std::make_pair(GetLcurveX(),GetLcurveY());
Info("ScanTau","logtau=%lf y=%lf X=%lf Y=%lf",logTau,y,
GetLcurveX(),GetLcurveY());
}
Double_t cTmin=0.0;
{
Double_t *cTi=new Double_t[curve.size()];
Double_t *cCi=new Double_t[curve.size()];
Int_t n=0;
for(TauScan_t::const_iterator i=curve.begin();i!=curve.end();i++) {
cTi[n]=(*i).first;
cCi[n]=(*i).second;
n++;
}
TSpline3 *splineC=new TSpline3("L curve curvature",cTi,cCi,n);
Int_t iskip=0;
if(n>3) iskip=1;
if(n>6) iskip=2;
Double_t cCmin=cCi[iskip];
cTmin=cTi[iskip];
for(Int_t i=iskip;i<n-1-iskip;i++) {
Double_t xMin=cTi[i+1];
Double_t yMin=cCi[i+1];
if(cCi[i]<yMin) {
yMin=cCi[i];
xMin=cTi[i];
}
Double_t x,y,b,c,d;
splineC->GetCoeff(i,x,y,b,c,d);
Double_t m_p_half=-c/(3.*d);
Double_t q=b/(3.*d);
Double_t discr=m_p_half*m_p_half-q;
if(discr>=0.0) {
discr=TMath::Sqrt(discr);
Double_t xx;
if(m_p_half>0.0) {
xx = m_p_half + discr;
} else {
xx = m_p_half - discr;
}
Double_t dx=cTi[i+1]-x;
if((xx>0.0)&&(xx<dx)) {
y=splineC->Eval(x+xx);
if(y<yMin) {
yMin=y;
xMin=x+xx;
}
}
if(xx !=0.0) {
xx= q/xx;
} else {
xx=0.0;
}
if((xx>0.0)&&(xx<dx)) {
y=splineC->Eval(x+xx);
if(y<yMin) {
yMin=y;
xMin=x+xx;
}
}
}
if(yMin<cCmin) {
cCmin=yMin;
cTmin=xMin;
}
}
delete splineC;
delete[] cTi;
delete[] cCi;
}
Double_t logTauFin=cTmin;
DoUnfold(TMath::Power(10.,logTauFin));
{
Double_t y=GetScanVariable(mode,distribution,axisSteering);
curve[logTauFin]=y;
lcurve[logTauFin]=std::make_pair(GetLcurveX(),GetLcurveY());
Info("ScanTau","Result logtau=%lf y=%lf X=%lf Y=%lf",logTauFin,y,
GetLcurveX(),GetLcurveY());
}
Int_t bestChoice=-1;
if(curve.size()>0) {
Double_t *y=new Double_t[curve.size()];
Double_t *logT=new Double_t[curve.size()];
int n=0;
for( TauScan_t::const_iterator i=curve.begin();i!=curve.end();i++) {
if(logTauFin==(*i).first) {
bestChoice=n;
}
y[n]=(*i).second;
logT[n]=(*i).first;
n++;
}
if(scanResult) {
TString name;
name = TString::Format("scan(%d,",mode);
if(distribution) name+= distribution;
name += ",";
if(axisSteering) name += axisSteering;
name +=")";
(*scanResult)=new TSpline3(name+"%log(tau)",logT,y,n);
}
delete[] y;
delete[] logT;
}
if(lcurve.size()) {
Double_t *logT=new Double_t[lcurve.size()];
Double_t *x=new Double_t[lcurve.size()];
Double_t *y=new Double_t[lcurve.size()];
Int_t n=0;
for(LCurve_t::const_iterator i=lcurve.begin();i!=lcurve.end();i++) {
logT[n]=(*i).first;
x[n]=(*i).second.first;
y[n]=(*i).second.second;
n++;
}
if(lCurvePlot) {
*lCurvePlot=new TGraph(n,x,y);
(*lCurvePlot)->SetTitle("L curve");
}
if(logTauXPlot)
*logTauXPlot=new TSpline3("log(chi**2)%log(tau)",logT,x,n);
if(logTauYPlot)
*logTauYPlot=new TSpline3("log(reg.cond)%log(tau)",logT,y,n);
delete [] y;
delete [] x;
delete [] logT;
}
return bestChoice;
}
Double_t TUnfoldDensity::GetScanVariable
(Int_t mode,const char *distribution,const char *axisSteering)
{
Double_t r=0.0;
TString name("GetScanVariable(");
name += TString::Format("%d,",mode);
if(distribution) name += distribution;
name += ",";
if(axisSteering) name += axisSteering;
name += ")";
TH1 *rhoi=0;
if((mode==kEScanTauRhoAvg)||(mode==kEScanTauRhoMax)||
(mode==kEScanTauRhoSquareAvg)) {
rhoi=GetRhoIstatbgr(name,0,distribution,axisSteering,kFALSE);
} else if((mode==kEScanTauRhoAvgSys)||(mode==kEScanTauRhoMaxSys)||
(mode==kEScanTauRhoSquareAvgSys)) {
rhoi=GetRhoItotal(name,0,distribution,axisSteering,kFALSE);
}
if(rhoi) {
Double_t sum=0.0;
Double_t sumSquare=0.0;
Double_t rhoMax=0.0;
Int_t n=0;
for(Int_t i=0;i<=rhoi->GetNbinsX()+1;i++) {
Double_t c=rhoi->GetBinContent(i);
if(c>=0.) {
if(c>rhoMax) rhoMax=c;
sum += c;
sumSquare += c*c;
n ++;
}
}
if((mode==kEScanTauRhoAvg)||(mode==kEScanTauRhoAvgSys)) {
r=sum/n;
} else if((mode==kEScanTauRhoSquareAvg)||
(mode==kEScanTauRhoSquareAvgSys)) {
r=sum/n;
} else {
r=rhoMax;
}
delete rhoi;
} else {
Fatal("GetScanVariable","mode %d not implemented",mode);
}
return r;
}