#include <iostream>
#include <TMatrixD.h>
#include <TMatrixDSparse.h>
#include <TMatrixDSym.h>
#include <TMath.h>
#include <TDecompBK.h>
#include <TUnfold.h>
#include <map>
#include <vector>
#define SCHUR_COMPLEMENT_MATRIX_INVERSION
#define INVERT_WITH_CONDITIONING
#ifdef DEBUG_LCURVE
#include <TCanvas.h>
#endif
ClassImp(TUnfold)
void TUnfold::InitTUnfold(void)
{
fXToHist.Set(0);
fHistToX.Set(0);
fSumOverY.Set(0);
fA = 0;
fLsquared = 0;
fV = 0;
fY = 0;
fX0 = 0;
fTau = 0.0;
fBiasScale = 0.0;
fAtV = 0;
fEinv = 0;
fE = 0;
fX = 0;
fAx = 0;
fChi2A = 0.0;
fChi2L = 0.0;
fRhoMax = 999.0;
fRhoAvg = -1.0;
}
void TUnfold::DeleteMatrix(TMatrixD **m) {
if(*m) delete *m;
*m=0;
}
void TUnfold::DeleteMatrix(TMatrixDSparse **m) {
if(*m) delete *m;
*m=0;
}
void TUnfold::ClearResults(void) {
DeleteMatrix(&fAtV);
DeleteMatrix(&fEinv);
DeleteMatrix(&fE);
DeleteMatrix(&fX);
DeleteMatrix(&fAx);
fChi2A = 0.0;
fChi2L = 0.0;
fRhoMax = 999.0;
fRhoAvg = -1.0;
}
TUnfold::TUnfold(void)
{
InitTUnfold();
}
Double_t TUnfold::DoUnfold(void)
{
ClearResults();
fAtV=MultiplyMSparseTranspMSparse(*fA,*fV);
TMatrixDSparse *rhs=MultiplyMSparseM(*fAtV,*fY);
if (fBiasScale != 0.0) {
TMatrixDSparse *rhs2=MultiplyMSparseM(*fLsquared,*fX0);
AddMSparse(*rhs,(fTau * fBiasScale),(*rhs2));
delete rhs2;
}
fEinv=MultiplyMSparseMSparse(*fAtV,*fA);
AddMSparse(*fEinv,fTau,*fLsquared);
fE = InvertMSparse(*fEinv);
fX = new TMatrixD(*fE, TMatrixD::kMult, *rhs);
fAx = MultiplyMSparseM(*fA,*fX);
delete rhs;
CalculateChi2Rho();
return fRhoMax;
}
void TUnfold::CalculateChi2Rho(void)
{
TMatrixD dy(*fY, TMatrixD::kMinus, *fAx);
fChi2A = MultiplyVecMSparseVec(*fV,dy);
TMatrixD dx(*fX, TMatrixD::kMinus, fBiasScale * (*fX0));
fChi2L = fTau*MultiplyVecMSparseVec(*fLsquared,dx);
Double_t rho_squared_max = 0.0;
Double_t rho_sum = 0.0;
Int_t n_rho=0;
for (int ix = 0; ix < GetNx(); ix++) {
Double_t rho_squared =
1. - 1. / ((*fE) (ix, ix) * (*fEinv) (ix, ix));
if (rho_squared > rho_squared_max)
rho_squared_max = rho_squared;
if(rho_squared>0.0) {
rho_sum += TMath::Sqrt(rho_squared);
n_rho++;
}
}
fRhoMax = TMath::Sqrt(rho_squared_max);
fRhoAvg = (n_rho>0) ? (rho_sum/n_rho) : -1.0;
}
Double_t TUnfold::MultiplyVecMSparseVec(TMatrixDSparse const &a,TMatrixD const &v)
{
Double_t r=0.0;
if((a.GetNrows()!=a.GetNcols())||
(v.GetNrows()!=a.GetNrows())||
(v.GetNcols()!=1)) {
std::cout<<"TUnfold::MultiplyVecMSparseVec inconsistent row/col numbers "
<<" a("<<a.GetNrows()<<","<<a.GetNcols()
<<") v("<<v.GetNrows()<<","<<v.GetNcols()<<")\n";
}
const Int_t *a_rows=a.GetRowIndexArray();
const Int_t *a_cols=a.GetColIndexArray();
const Double_t *a_data=a.GetMatrixArray();
for (Int_t irow = 0; irow < a.GetNrows(); irow++) {
for(Int_t i=a_rows[irow];i<a_rows[irow+1];i++) {
r += v(irow,0) * a_data[i] * v(a_cols[i],0);
}
}
return r;
}
TMatrixDSparse *TUnfold::MultiplyMSparseMSparse(TMatrixDSparse const &a,TMatrixDSparse const &b)
{
if(a.GetNcols()!=b.GetNrows()) {
std::cout<<"TUnfold::MultiplyMSparseMSparse inconsistent row/col number "
<<a.GetNcols()<<" "<<b.GetNrows()<<"\n";
}
TMatrixDSparse *r=new TMatrixDSparse(a.GetNrows(),b.GetNcols());
const Int_t *a_rows=a.GetRowIndexArray();
const Int_t *a_cols=a.GetColIndexArray();
const Double_t *a_data=a.GetMatrixArray();
const Int_t *b_rows=b.GetRowIndexArray();
const Int_t *b_cols=b.GetColIndexArray();
const Double_t *b_data=b.GetMatrixArray();
int nMax=0;
for (Int_t irow = 0; irow < a.GetNrows(); irow++) {
if(a_rows[irow+1]>a_rows[irow]) nMax += b.GetNcols();
}
if(nMax>0) {
Int_t *r_rows=new Int_t[nMax];
Int_t *r_cols=new Int_t[nMax];
Double_t *r_data=new Double_t[nMax];
Double_t *row_data=new Double_t[b.GetNcols()];
Int_t n=0;
for (Int_t irow = 0; irow < a.GetNrows(); irow++) {
if(a_rows[irow+1]<=a_rows[irow]) continue;
for(Int_t icol=0;icol<b.GetNcols();icol++) {
row_data[icol]=0.0;
}
for(Int_t ia=a_rows[irow];ia<a_rows[irow+1];ia++) {
Int_t k=a_cols[ia];
for(Int_t ib=b_rows[k];ib<b_rows[k+1];ib++) {
row_data[b_cols[ib]] += a_data[ia]*b_data[ib];
}
}
for(Int_t icol=0;icol<b.GetNcols();icol++) {
if(row_data[icol] != 0.0) {
r_rows[n]=irow;
r_cols[n]=icol;
r_data[n]=row_data[icol];
n++;
}
}
}
r->SetMatrixArray(n,r_rows,r_cols,r_data);
delete [] r_rows;
delete [] r_cols;
delete [] r_data;
delete [] row_data;
}
return r;
}
TMatrixDSparse *TUnfold::MultiplyMSparseTranspMSparse(TMatrixDSparse const &a,TMatrixDSparse const &b)
{
if(a.GetNrows() != b.GetNrows()) {
std::cout<<"TUnfold::MultiplyMSparseTranspMSparse "
<<"inconsistent row numbers "
<<a.GetNrows()<<" "<<b.GetNrows()<<"\n";
}
TMatrixDSparse *r=new TMatrixDSparse(a.GetNcols(),b.GetNcols());
const Int_t *a_rows=a.GetRowIndexArray();
const Int_t *a_cols=a.GetColIndexArray();
const Double_t *a_data=a.GetMatrixArray();
const Int_t *b_rows=b.GetRowIndexArray();
const Int_t *b_cols=b.GetColIndexArray();
const Double_t *b_data=b.GetMatrixArray();
typedef std::map<Int_t,Double_t> MMatrixRow_t;
typedef std::map<Int_t, MMatrixRow_t > MMatrix_t;
MMatrix_t matrix;
for(Int_t iRowAB=0;iRowAB<a.GetNrows();iRowAB++) {
for(Int_t ia=a_rows[iRowAB];ia<a_rows[iRowAB+1];ia++) {
for(Int_t ib=b_rows[iRowAB];ib<b_rows[iRowAB+1];ib++) {
MMatrixRow_t &row=matrix[a_cols[ia]];
MMatrixRow_t::iterator icol=row.find(b_cols[ib]);
if(icol!=row.end()) {
(*icol).second += a_data[ia]*b_data[ib];
} else {
row[b_cols[ib]] = a_data[ia]*b_data[ib];
}
}
}
}
Int_t n=0;
for(MMatrix_t::const_iterator irow=matrix.begin();
irow!=matrix.end();irow++) {
n += (*irow).second.size();
}
if(n>0) {
Int_t *r_rows=new Int_t[n];
Int_t *r_cols=new Int_t[n];
Double_t *r_data=new Double_t[n];
n=0;
for(MMatrix_t::const_iterator irow=matrix.begin();
irow!=matrix.end();irow++) {
for(MMatrixRow_t::const_iterator icol=(*irow).second.begin();
icol!=(*irow).second.end();icol++) {
r_rows[n]=(*irow).first;
r_cols[n]=(*icol).first;
r_data[n]=(*icol).second;
n++;
}
}
r->SetMatrixArray(n,r_rows,r_cols,r_data);
delete [] r_rows;
delete [] r_cols;
delete [] r_data;
}
return r;
}
TMatrixDSparse *TUnfold::MultiplyMSparseM(TMatrixDSparse const &a,TMatrixD const &b)
{
if(a.GetNcols()!=b.GetNrows()) {
std::cout<<"TUnfold::MultiplyMSparseM inconsistent row/col number "
<<a.GetNcols()<<" "<<b.GetNrows()<<"\n";
}
TMatrixDSparse *r=new TMatrixDSparse(a.GetNrows(),b.GetNcols());
const Int_t *a_rows=a.GetRowIndexArray();
const Int_t *a_cols=a.GetColIndexArray();
const Double_t *a_data=a.GetMatrixArray();
int nMax=0;
for (Int_t irow = 0; irow < a.GetNrows(); irow++) {
if(a_rows[irow+1]-a_rows[irow]>0) nMax += b.GetNcols();
}
if(nMax>0) {
Int_t *r_rows=new Int_t[nMax];
Int_t *r_cols=new Int_t[nMax];
Double_t *r_data=new Double_t[nMax];
Int_t n=0;
for (Int_t irow = 0; irow < a.GetNrows(); irow++) {
if(a_rows[irow+1]-a_rows[irow]<=0) continue;
for(Int_t icol=0;icol<b.GetNcols();icol++) {
r_rows[n]=irow;
r_cols[n]=icol;
r_data[n]=0.0;
for(Int_t i=a_rows[irow];i<a_rows[irow+1];i++) {
Int_t j=a_cols[i];
r_data[n] += a_data[i]*b(j,icol);
}
if(r_data[n]!=0.0) n++;
}
}
r->SetMatrixArray(n,r_rows,r_cols,r_data);
delete [] r_rows;
delete [] r_cols;
delete [] r_data;
}
return r;
}
void TUnfold::AddMSparse(TMatrixDSparse &dest,Double_t const &f,TMatrixDSparse const &src) {
const Int_t *dest_rows=dest.GetRowIndexArray();
const Int_t *dest_cols=dest.GetColIndexArray();
const Double_t *dest_data=dest.GetMatrixArray();
const Int_t *src_rows=src.GetRowIndexArray();
const Int_t *src_cols=src.GetColIndexArray();
const Double_t *src_data=src.GetMatrixArray();
if((dest.GetNrows()!=src.GetNrows())||
(dest.GetNcols()!=src.GetNcols())) {
std::cout<<"TUnfold::AddMSparse inconsistent row/col number"
<<" "<<src.GetNrows()<<" "<<dest.GetNrows()
<<" "<<src.GetNcols()<<" "<<dest.GetNcols()
<<"\n";
}
Int_t nmax=dest.GetNrows()*dest.GetNcols();
Double_t *result_data=new Double_t[nmax];
Int_t *result_rows=new Int_t[nmax];
Int_t *result_cols=new Int_t[nmax];
Int_t n=0;
for(Int_t row=0;row<dest.GetNrows();row++) {
Int_t i_dest=dest_rows[row];
Int_t i_src=src_rows[row];
while((i_dest<dest_rows[row+1])||(i_src<src_rows[row+1])) {
Int_t col_dest=(i_dest<dest_rows[row+1]) ?
dest_cols[i_dest] : dest.GetNcols();
Int_t col_src =(i_src <src_rows[row+1] ) ?
src_cols [i_src] : src.GetNcols();
result_rows[n]=row;
if(col_dest<col_src) {
result_cols[n]=col_dest;
result_data[n]=dest_data[i_dest++];
} else if(col_dest>col_src) {
result_cols[n]=col_src;
result_data[n]=f*src_data[i_src++];
} else {
result_cols[n]=col_dest;
result_data[n]=dest_data[i_dest++]+f*src_data[i_src++];
}
if(result_data[n] !=0.0) n++;
}
}
dest.SetMatrixArray(n,result_rows,result_cols,result_data);
delete [] result_data;
delete [] result_rows;
delete [] result_cols;
}
TMatrixD *TUnfold::InvertMSparse(TMatrixDSparse const &A) {
if(A.GetNcols()!=A.GetNrows()) {
std::cout<<"TUnfold::InvertMSparse inconsistent row/col number "
<<A.GetNcols()<<" "<<A.GetNrows()<<"\n";
}
#ifdef SCHUR_COMPLEMENT_MATRIX_INVERSION
const Int_t *a_rows=A.GetRowIndexArray();
const Int_t *a_cols=A.GetColIndexArray();
const Double_t *a_data=A.GetMatrixArray();
Int_t nmin=0,nmax=0;
for(Int_t imin=0;imin<A.GetNrows();imin++) {
Int_t imax=A.GetNrows();
for(Int_t i2=imin;i2<imax;i2++) {
for(Int_t i=a_rows[i2];i<a_rows[i2+1];i++) {
if(a_data[i]==0.0) continue;
Int_t icol=a_cols[i];
if(icol<imin) continue;
if(icol==i2) continue;
if(icol<i2) {
imax=i2;
break;
} else {
imax=icol;
break;
}
}
}
if(imax-imin>nmax-nmin) {
nmin=imin;
nmax=imax;
}
}
if(nmin>=nmax-1) {
TMatrixD *r=new TMatrixD(A);
if(!InvertMConditioned(*r)) {
std::cout<<"TUnfold::InvertMSparse inversion failed at (1)\n";
}
return r;
} else if((nmin==0)&&(nmax==A.GetNrows())) {
TMatrixD *r=new TMatrixD(A.GetNrows(),A.GetNcols());
Int_t error=0;
for(Int_t irow=nmin;irow<nmax;irow++) {
for(Int_t i=a_rows[irow];i<a_rows[irow+1];i++) {
if(a_cols[i]==irow) {
if(a_data[i] !=0.0) (*r)(irow,irow)=1./a_data[i];
else error++;
}
}
}
if(error) {
std::cout<<"TUnfold::InvertMSparse inversion failed at (2)\n";
}
return r;
}
std::vector<Double_t> Dinv;
Dinv.resize(nmax-nmin);
for(Int_t irow=nmin;irow<nmax;irow++) {
for(Int_t i=a_rows[irow];i<a_rows[irow+1];i++) {
if(a_cols[i]==irow) {
if(a_data[i]!=0.0) {
Dinv[irow-nmin]=1./a_data[i];
} else {
Dinv[irow-nmin]=0.0;
}
break;
}
}
}
Int_t nBDinv=0,nC=0;
for(Int_t irow_a=0;irow_a<A.GetNrows();irow_a++) {
if((irow_a<nmin)||(irow_a>=nmax)) {
for(Int_t i=a_rows[irow_a];i<a_rows[irow_a+1];i++) {
Int_t icol=a_cols[i];
if((icol>=nmin)&&(icol<nmax)) nBDinv++;
}
} else {
for(Int_t i=a_rows[irow_a];i<a_rows[irow_a+1];i++) {
Int_t icol = a_cols[i];
if((icol<nmin)||(icol>=nmax)) nC++;
}
}
}
Int_t *row_BDinv=new Int_t[nBDinv+1];
Int_t *col_BDinv=new Int_t[nBDinv+1];
Double_t *data_BDinv=new Double_t[nBDinv+1];
Int_t *row_C=new Int_t[nC+1];
Int_t *col_C=new Int_t[nC+1];
Double_t *data_C=new Double_t[nC+1];
TMatrixD Aschur(A.GetNrows()-(nmax-nmin),A.GetNcols()-(nmax-nmin));
nBDinv=0;
nC=0;
for(Int_t irow_a=0;irow_a<A.GetNrows();irow_a++) {
if((irow_a<nmin)||(irow_a>=nmax)) {
Int_t row=(irow_a<nmin) ? irow_a : (irow_a-(nmax-nmin));
for(Int_t i=a_rows[irow_a];i<a_rows[irow_a+1];i++) {
Int_t icol_a=a_cols[i];
if(icol_a<nmin) {
Aschur(row,icol_a)=a_data[i];
} else if(icol_a>=nmax) {
Aschur(row,icol_a-(nmax-nmin))=a_data[i];
} else {
row_BDinv[nBDinv]=row;
col_BDinv[nBDinv]=icol_a-nmin;
data_BDinv[nBDinv]=a_data[i]*Dinv[icol_a-nmin];
nBDinv++;
}
}
} else {
for(Int_t i=a_rows[irow_a];i<a_rows[irow_a+1];i++) {
Int_t icol_a=a_cols[i];
if(icol_a<nmin) {
row_C[nC]=irow_a-nmin;
col_C[nC]=icol_a;
data_C[nC]=a_data[i];
nC++;
} else if(icol_a>=nmax) {
row_C[nC]=irow_a-nmin;
col_C[nC]=icol_a-(nmax-nmin);
data_C[nC]=a_data[i];
nC++;
}
}
}
}
TMatrixDSparse BDinv(A.GetNrows()-(nmax-nmin),nmax-nmin);
BDinv.SetMatrixArray(nBDinv,row_BDinv,col_BDinv,data_BDinv);
delete[] row_BDinv;
delete[] col_BDinv;
delete[] data_BDinv;
TMatrixDSparse C(nmax-nmin,A.GetNcols()-(nmax-nmin));
C.SetMatrixArray(nC,row_C,col_C,data_C);
delete[] row_C;
delete[] col_C;
delete[] data_C;
TMatrixDSparse *BDinvC=MultiplyMSparseMSparse(BDinv,C);
Aschur -= *BDinvC;
if(!InvertMConditioned(Aschur)) {
std::cout<<"TUnfold::InvertMSparse inversion failed at 3\n";
}
delete BDinvC;
TMatrixD *r=new TMatrixD(A.GetNrows(),A.GetNcols());
for(Int_t row_a=0;row_a<Aschur.GetNrows();row_a++) {
for(Int_t col_a=0;col_a<Aschur.GetNcols();col_a++) {
(*r)((row_a<nmin) ? row_a : (row_a+nmax-nmin),
(col_a<nmin) ? col_a : (col_a+nmax-nmin))=Aschur(row_a,col_a);
}
}
TMatrixDSparse *CAschur=MultiplyMSparseM(C,Aschur);
TMatrixDSparse *CAschurBDinv=MultiplyMSparseMSparse(*CAschur,BDinv);
const Int_t *CAschurBDinv_row=CAschurBDinv->GetRowIndexArray();
const Int_t *CAschurBDinv_col=CAschurBDinv->GetColIndexArray();
const Double_t *CAschurBDinv_data=CAschurBDinv->GetMatrixArray();
for(Int_t row=0;row<CAschurBDinv->GetNrows();row++) {
for(Int_t i=CAschurBDinv_row[row];i<CAschurBDinv_row[row+1];i++) {
Int_t col=CAschurBDinv_col[i];
(*r)(row+nmin,col+nmin)=CAschurBDinv_data[i]*Dinv[row];
}
(*r)(row+nmin,row+nmin) += Dinv[row];
}
delete CAschurBDinv;
const Int_t *CAschur_row=CAschur->GetRowIndexArray();
const Int_t *CAschur_col=CAschur->GetColIndexArray();
const Double_t *CAschur_data=CAschur->GetMatrixArray();
for(Int_t row=0;row<CAschur->GetNrows();row++) {
for(Int_t i=CAschur_row[row];i<CAschur_row[row+1];i++) {
Int_t col=CAschur_col[i];
(*r)(row+nmin,
(col<nmin) ? col : (col+nmax-nmin))= -CAschur_data[i]*Dinv[row];
}
}
delete CAschur;
const Int_t *BDinv_row=BDinv.GetRowIndexArray();
const Int_t *BDinv_col=BDinv.GetColIndexArray();
const Double_t *BDinv_data=BDinv.GetMatrixArray();
for(Int_t row_aschur=0;row_aschur<Aschur.GetNrows();row_aschur++) {
Int_t row=(row_aschur<nmin) ? row_aschur : (row_aschur+nmax-nmin);
for(Int_t row_bdinv=0;row_bdinv<BDinv.GetNrows();row_bdinv++) {
for(Int_t i=BDinv_row[row_bdinv];i<BDinv_row[row_bdinv+1];i++) {
(*r)(row,BDinv_col[i]+nmin) -= Aschur(row_aschur,row_bdinv)*
BDinv_data[i];
}
}
}
return r;
#else
TMatrixD *r=new TMatrixD(A);
if(!InvertMConditioned(*r)) {
std::cout<<"TUnfold::InvertMSparse inversion failed\n";
}
return r;
#endif
}
Bool_t TUnfold::InvertMConditioned(TMatrixD &A) {
#ifdef INVERT_WITH_CONDITIONING
Double_t *A_diagonals=new Double_t[A.GetNrows()];
for(Int_t i=0;i<A.GetNrows();i++) {
A_diagonals[i]=TMath::Sqrt(TMath::Abs(A(i,i)));
if(A_diagonals[i]>0.0) A_diagonals[i]=1./A_diagonals[i];
else A_diagonals[i]=1.0;
}
for(Int_t i=0;i<A.GetNrows();i++) {
for(Int_t j=0;j<A.GetNcols();j++) {
A(i,j) *= A_diagonals[i]*A_diagonals[j];
}
}
#endif
Double_t det=0.0;
A.Invert(&det);
#ifdef INVERT_WITH_CONDITIONING
for(Int_t i=0;i<A.GetNrows();i++) {
for(Int_t j=0;j<A.GetNcols();j++) {
A(i,j) *= A_diagonals[i]*A_diagonals[j];
}
}
delete [] A_diagonals;
#endif
return (det !=0.0);
}
TUnfold::TUnfold(TH2 const *hist_A, EHistMap histmap, ERegMode regmode)
{
InitTUnfold();
Int_t nx0, nx, ny;
if (histmap == kHistMapOutputHoriz) {
nx0 = hist_A->GetNbinsX()+2;
ny = hist_A->GetNbinsY();
} else {
nx0 = hist_A->GetNbinsY()+2;
ny = hist_A->GetNbinsX();
}
nx = 0;
fSumOverY.Set(nx0);
fXToHist.Set(nx0);
fHistToX.Set(nx0);
Int_t nonzeroA=0;
Int_t nskipped=0;
for (Int_t ix = 0; ix < nx0; ix++) {
Double_t sum = 0.0;
for (Int_t iy = 0; iy < ny; iy++) {
Double_t z;
if (histmap == kHistMapOutputHoriz) {
z = hist_A->GetBinContent(ix, iy + 1);
} else {
z = hist_A->GetBinContent(iy + 1, ix);
}
if (z > 0.0) {
nonzeroA++;
sum += z;
}
}
if (sum > 0.0) {
fXToHist[nx] = ix;
fHistToX[ix] = nx;
fSumOverY[nx] = sum;
if (histmap == kHistMapOutputHoriz) {
fSumOverY[nx] +=
hist_A->GetBinContent(ix, 0) +
hist_A->GetBinContent(ix, ny + 1);
} else {
fSumOverY[nx] +=
hist_A->GetBinContent(0, ix) +
hist_A->GetBinContent(ny + 1, ix);
}
nx++;
} else {
nskipped++;
fHistToX[ix] = -1;
}
}
if(nskipped) {
std::cout << "TUnfold: the following output bins "
<<"are not connected to the input side\n";
Int_t nprint=0;
Int_t ixfirst=-1,ixlast=-1;
for (Int_t ix = 0; ix < nx0; ix++) {
if(fHistToX[ix]<0) {
nprint++;
if(ixlast<0) {
std::cout<<" "<<ix;
ixfirst=ix;
}
ixlast=ix;
}
if(((fHistToX[ix]>=0)&&(ixlast>=0))||
(nprint==nskipped)) {
if(ixlast>ixfirst) std::cout<<"-"<<ixlast;
ixfirst=-1;
ixlast=-1;
}
if(nprint==nskipped) {
std::cout<<"\n";
break;
}
}
}
fX0 = new TMatrixD(nx, 1, fSumOverY.GetArray());
Int_t *rowA = new Int_t[nonzeroA];
Int_t *colA = new Int_t[nonzeroA];
Double_t *dataA = new Double_t[nonzeroA];
Int_t index=0;
for (Int_t iy = 0; iy < ny; iy++) {
for (Int_t ix = 0; ix < nx; ix++) {
Int_t ibinx = fXToHist[ix];
Double_t z;
if (histmap == kHistMapOutputHoriz) {
z = hist_A->GetBinContent(ibinx, iy + 1);
} else {
z = hist_A->GetBinContent(iy + 1, ibinx);
}
if (z > 0.0) {
rowA[index]=iy;
colA[index] = ix;
dataA[index] = z / fSumOverY[ix];
index++;
}
}
}
fA = new TMatrixDSparse(ny,nx);
fA->SetMatrixArray(index,rowA,colA,dataA);
delete[] rowA;
delete[] colA;
delete[] dataA;
fLsquared = new TMatrixDSparse(GetNx(), GetNx());
if (regmode != kRegModeNone) {
Int_t nError=RegularizeBins(0, 1, nx0, regmode);
if(nError>0) {
if(nError>1) {
std::cout<<"TUnfold: "<<nError<<" regularisation conditions have been skipped\n";
} else {
std::cout<<"TUnfold: "<<nError<<" regularisation condition has been skipped\n";
}
}
}
}
TUnfold::~TUnfold(void)
{
DeleteMatrix(&fA);
DeleteMatrix(&fLsquared);
DeleteMatrix(&fV);
DeleteMatrix(&fY);
DeleteMatrix(&fX0);
ClearResults();
}
void TUnfold::SetBias(TH1 const *bias)
{
DeleteMatrix(&fX0);
fX0 = new TMatrixD(GetNx(), 1);
for (Int_t i = 0; i < GetNx(); i++) {
(*fX0) (i, 0) = bias->GetBinContent(fXToHist[i]);
}
}
Int_t TUnfold::RegularizeSize(int bin, Double_t const &scale)
{
Int_t i = fHistToX[bin];
if (i < 0) {
return 1;
}
(*fLsquared) (i, i) = scale * scale;
return 0;
}
Int_t TUnfold::RegularizeDerivative(int left_bin, int right_bin,
Double_t const &scale)
{
Int_t il = fHistToX[left_bin];
Int_t ir = fHistToX[right_bin];
if ((il < 0) || (ir < 0)) {
return 1;
}
Double_t scale_squared = scale * scale;
(*fLsquared) (il, il) += scale_squared;
(*fLsquared) (il, ir) -= scale_squared;
(*fLsquared) (ir, il) -= scale_squared;
(*fLsquared) (ir, ir) += scale_squared;
return 0;
}
Int_t TUnfold::RegularizeCurvature(int left_bin, int center_bin,
int right_bin,
Double_t const &scale_left,
Double_t const &scale_right)
{
Int_t il, ic, ir;
il = fHistToX[left_bin];
ic = fHistToX[center_bin];
ir = fHistToX[right_bin];
if ((il < 0) || (ic < 0) || (ir < 0)) {
return 1;
}
Double_t r[3];
r[0] = -scale_left;
r[2] = -scale_right;
r[1] = -r[0] - r[2];
(*fLsquared) (il, il) += r[0] * r[0];
(*fLsquared) (il, ic) += r[0] * r[1];
(*fLsquared) (il, ir) += r[0] * r[2];
(*fLsquared) (ic, il) += r[1] * r[0];
(*fLsquared) (ic, ic) += r[1] * r[1];
(*fLsquared) (ic, ir) += r[1] * r[2];
(*fLsquared) (ir, il) += r[2] * r[0];
(*fLsquared) (ir, ic) += r[2] * r[1];
(*fLsquared) (ir, ir) += r[2] * r[2];
return 0;
}
Int_t TUnfold::RegularizeBins(int start, int step, int nbin,
ERegMode regmode)
{
Int_t i0, i1, i2;
i0 = start;
i1 = i0 + step;
i2 = i1 + step;
Int_t nSkip = 0;
Int_t nError= 0;
if (regmode == kRegModeDerivative)
nSkip = 1;
else if (regmode == kRegModeCurvature)
nSkip = 2;
for (Int_t i = nSkip; i < nbin; i++) {
if (regmode == kRegModeSize) {
nError += RegularizeSize(i0);
} else if (regmode == kRegModeDerivative) {
nError += RegularizeDerivative(i0, i1);
} else if (regmode == kRegModeCurvature) {
nError += RegularizeCurvature(i0, i1, i2);
}
i0 = i1;
i1 = i2;
i2 += step;
}
return nError;
}
Int_t TUnfold::RegularizeBins2D(int start_bin, int step1, int nbin1,
int step2, int nbin2, ERegMode regmode)
{
Int_t nError = 0;
for (Int_t i1 = 0; i1 < nbin1; i1++) {
nError += RegularizeBins(start_bin + step1 * i1, step2, nbin2, regmode);
}
for (Int_t i2 = 0; i2 < nbin2; i2++) {
nError += RegularizeBins(start_bin + step2 * i2, step1, nbin1, regmode);
}
return nError;
}
Double_t TUnfold::DoUnfold(Double_t const &tau_reg, TH1 const *input,
Double_t const &scaleBias)
{
SetInput(input,scaleBias);
return DoUnfold(tau_reg);
}
Int_t TUnfold::SetInput(TH1 const *input, Double_t const &scaleBias,
Double_t oneOverZeroError) {
fBiasScale = scaleBias;
ClearResults();
fNdf = -GetNpar();
Int_t *rowColV=new Int_t[GetNy()];
Int_t *col1V=new Int_t[GetNy()];
Double_t *dataV=new Double_t[GetNy()];
Int_t nError=0;
for (Int_t iy = 0; iy < GetNy(); iy++) {
Double_t dy = input->GetBinError(iy + 1);
rowColV[iy] = iy;
col1V[iy] = 0;
if (dy <= 0.0) {
nError++;
dataV[iy] = oneOverZeroError*oneOverZeroError;
} else {
dataV[iy] = 1. / dy / dy;
}
if( dataV[iy]>0.0) fNdf ++;
}
DeleteMatrix(&fV);
fV = new TMatrixDSparse(GetNy(),GetNy());
fV->SetMatrixArray(GetNy(),rowColV,rowColV, dataV);
TMatrixDSparse vecV(GetNy(),1);
vecV.SetMatrixArray(GetNy(),rowColV,col1V, dataV);
delete[] rowColV;
delete[] col1V;
delete[] dataV;
DeleteMatrix(&fY);
fY = new TMatrixD(GetNy(), 1);
for (Int_t i = 0; i < GetNy(); i++) {
(*fY) (i, 0) = input->GetBinContent(i + 1);
}
TMatrixDSparse *mAtV=MultiplyMSparseTranspMSparse(*fA,vecV);
Int_t nError2=0;
for (Int_t i = 0; i <mAtV->GetNrows();i++) {
if(mAtV->GetRowIndexArray()[i]==
mAtV->GetRowIndexArray()[i+1]) {
nError2 ++;
}
}
if(nError>0) {
if(nError>1) {
std::cout
<<"TUnfold::SetInput "<<nError<<" input bins have zero error. ";
} else {
std::cout
<<"TUnfold::SetInput "<<nError<<" input bin has zero error. ";
}
if(oneOverZeroError !=0.0) {
std::cout<<"1/error is set to "<<oneOverZeroError<<"\n";
} else {
if(nError>1) {
std::cout
<<"These bins are ignored.\n";
} else {
std::cout
<<"This bin is ignored.\n";
}
}
}
if(nError2>0) {
if(nError2>1) {
std::cout
<<"TUnfold::SetInput "<<nError2<<" output bins are not constrained by any data.\n";
} else {
std::cout
<<"TUnfold::SetInput "<<nError2<<" output bin is not constrained by any data.\n";
}
if(oneOverZeroError<=0.0) {
const Int_t *a_rows=fA->GetRowIndexArray();
const Int_t *a_cols=fA->GetColIndexArray();
for (Int_t col = 0; col <mAtV->GetNrows();col++) {
if(mAtV->GetRowIndexArray()[col]==
mAtV->GetRowIndexArray()[col+1]) {
std::cout<<" output bin "<<fXToHist[col]
<<" depends on ignored input bins ";
for(Int_t row=0;row<fA->GetNrows();row++) {
if(input->GetBinError(row + 1)>0.0) continue;
for(Int_t i=a_rows[row];i<a_rows[row+1];i++) {
if(a_cols[i]!=col) continue;
std::cout<<" "<<row;
}
}
std::cout<<"\n";
}
}
}
}
delete mAtV;
return nError+10000*nError2;
}
Double_t TUnfold::DoUnfold(Double_t const &tau) {
fTau=tau;
return DoUnfold();
}
Int_t TUnfold::ScanLcurve(Int_t nPoint,
Double_t const &tauMin,Double_t const &tauMax,
TGraph **lCurve,TSpline **logTauX,
TSpline **logTauY) {
typedef std::map<Double_t,std::pair<Double_t,Double_t> > XYtau_t;
Int_t bestChoice=-1;
XYtau_t curve;
Double_t logTauMin=-10.;
Double_t logTauMax=0.0;
Double_t logTau=logTauMin;
if(tauMin>0.0) logTauMin=TMath::Log10(tauMin);
if(tauMax>0.0) logTauMax=TMath::Log10(tauMax);
if(logTauMax<=logTauMin) logTauMax=logTauMin+10.;
if(nPoint>0) {
if(nPoint>1) {
DoUnfold(TMath::Power(10.,logTauMax));
curve[logTauMax]=std::make_pair(GetLcurveX(),GetLcurveY());
}
DoUnfold(TMath::Power(10.,logTauMin));
curve[logTauMin]=std::make_pair(GetLcurveX(),GetLcurveY());
}
while(int(curve.size())<nPoint-1) {
XYtau_t::const_iterator i0,i1;
i0=curve.begin();
i1=i0;
Double_t distMax=0.0;
for(i1++;i1!=curve.end();i1++) {
std::pair<Double_t,Double_t> const &xy0=(*i0).second;
std::pair<Double_t,Double_t> const &xy1=(*i1).second;
Double_t dx=xy1.first-xy0.first;
Double_t dy=xy1.second-xy0.second;
Double_t d=TMath::Sqrt(dx*dx+dy*dy);
if(d>=distMax) {
distMax=d;
logTau=0.5*((*i0).first+(*i1).first);
}
i0=i1;
}
DoUnfold(TMath::Power(10.,logTau));
curve[logTau]=std::make_pair(GetLcurveX(),GetLcurveY());
}
XYtau_t::const_iterator i0,i1;
i0=curve.begin();
i1=i0;
i1++;
if(curve.size()>2) {
Double_t *cTi=new Double_t[curve.size()-1];
Double_t *cCi=new Double_t[curve.size()-1];
Int_t n=0;
{
Double_t *lXi=new Double_t[curve.size()];
Double_t *lYi=new Double_t[curve.size()];
Double_t *lTi=new Double_t[curve.size()];
for( XYtau_t::const_iterator i=curve.begin();i!=curve.end();i++) {
lXi[n]=(*i).second.first;
lYi[n]=(*i).second.second;
lTi[n]=(*i).first;
n++;
}
TSpline3 *splineX=new TSpline3("x vs tau",lTi,lXi,n);
TSpline3 *splineY=new TSpline3("y vs tau",lTi,lYi,n);
for(Int_t i=0;i<n-1;i++) {
Double_t ltau,xy,bi,ci,di;
splineX->GetCoeff(i,ltau,xy,bi,ci,di);
Double_t tauBar=0.5*(lTi[i]+lTi[i+1]);
Double_t dTau=0.5*(lTi[i+1]-lTi[i]);
Double_t dx1=bi+dTau*(2.*ci+3.*di*dTau);
Double_t dx2=2.*ci+6.*di*dTau;
splineY->GetCoeff(i,ltau,xy,bi,ci,di);
Double_t dy1=bi+dTau*(2.*ci+3.*di*dTau);
Double_t dy2=2.*ci+6.*di*dTau;
cTi[i]=tauBar;
cCi[i]=(dy2*dx1-dy1*dx2)/TMath::Power(dx1*dx1+dy1*dy1,1.5);
}
delete splineX;
delete splineY;
delete[] lXi;
delete[] lYi;
delete[] lTi;
}
TSpline3 *splineC=new TSpline3("L curve curvature",cTi,cCi,n-1);
Int_t iskip=0;
if(n>4) iskip=1;
if(n>7) iskip=2;
Double_t cCmax=cCi[iskip];
Double_t cTmax=cTi[iskip];
for(Int_t i=iskip;i<n-2-iskip;i++) {
Double_t xMax=cTi[i+1];
Double_t yMax=cCi[i+1];
if(cCi[i]>yMax) {
yMax=cCi[i];
xMax=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>yMax) {
yMax=y;
xMax=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>yMax) {
yMax=y;
xMax=x+xx;
}
}
}
if(yMax>cCmax) {
cCmax=yMax;
cTmax=xMax;
}
}
#ifdef DEBUG_LCURVE
{
TCanvas lcc;
lcc.Divide(1,1);
lcc.cd(1);
splineC->Draw();
lcc.SaveAs("splinec.ps");
}
#endif
delete splineC;
delete[] cTi;
delete[] cCi;
logTau=cTmax;
DoUnfold(TMath::Power(10.,logTau));
curve[logTau]=std::make_pair(GetLcurveX(),GetLcurveY());
}
if(curve.size()>0) {
Double_t *x=new Double_t[curve.size()];
Double_t *y=new Double_t[curve.size()];
Double_t *logT=new Double_t[curve.size()];
int n=0;
for( XYtau_t::const_iterator i=curve.begin();i!=curve.end();i++) {
if(logTau==(*i).first) {
bestChoice=n;
}
x[n]=(*i).second.first;
y[n]=(*i).second.second;
logT[n]=(*i).first;
n++;
}
if(lCurve) (*lCurve)=new TGraph(n,x,y);
if(logTauX) (*logTauX)=new TSpline3("log(chi**2)%log(tau)",logT,x,n);
if(logTauY) (*logTauY)=new TSpline3("L curve",logT,y,n);
delete[] x;
delete[] y;
delete[] logT;
}
return bestChoice;
}
TH1D *TUnfold::GetOutput(char const *name, char const *title,
Double_t xmin, Double_t xmax) const
{
int nbins = fHistToX.GetSize() - 2;
if (xmin >= xmax) {
xmin = 0.0;
xmax = nbins;
}
TH1D *out = new TH1D(name, title, nbins, xmin, xmax);
GetOutput(out);
return out;
}
TH1D *TUnfold::GetBias(char const *name, char const *title,
Double_t xmin, Double_t xmax) const
{
int nbins = fHistToX.GetSize() - 2;
if (xmin >= xmax) {
xmin = 0.0;
xmax = nbins;
}
TH1D *out = new TH1D(name, title, nbins, xmin, xmax);
for (Int_t i = 0; i < GetNx(); i++) {
out->SetBinContent(fXToHist[i], (*fX0) (i, 0));
}
return out;
}
TH1D *TUnfold::GetFoldedOutput(char const *name, char const *title,
Double_t y0, Double_t y1) const
{
if (y0 >= y1) {
y0 = 0.0;
y1 = GetNy();
}
TH1D *out = new TH1D(name, title, GetNy(), y0, y1);
Int_t const *rows=fA->GetRowIndexArray();
Int_t const *cols=fA->GetColIndexArray();
Double_t const *data=fA->GetMatrixArray();
for (Int_t i = 0; i < GetNy(); i++) {
out->SetBinContent(i + 1, (*fAx) (i, 0));
Double_t e2=0.0;
for( Int_t cindex1=rows[i];cindex1<rows[i+1];cindex1++) {
for( Int_t cindex2=rows[i];cindex2<rows[i+1];cindex2++) {
e2 += data[cindex1]*(*fE)(cols[cindex1],cols[cindex2])*data[cindex2];
}
}
out->SetBinError(i + 1,TMath::Sqrt(e2));
}
return out;
}
TH1D *TUnfold::GetInput(char const *name, char const *title,
Double_t y0, Double_t y1) const
{
if (y0 >= y1) {
y0 = 0.0;
y1 = GetNy();
}
TH1D *out = new TH1D(name, title, GetNy(), y0, y1);
TMatrixD *Vinv=InvertMSparse(*fV);
for (Int_t i = 0; i < GetNy(); i++) {
out->SetBinContent(i + 1, (*fY) (i, 0));
out->SetBinError(i + 1, TMath::Sqrt((*Vinv)(i, i)));
}
delete Vinv;
return out;
}
TH2D *TUnfold::GetRhoIJ(char const *name, char const *title,
Double_t xmin, Double_t xmax) const
{
int nbins = fHistToX.GetSize() - 2;
if (xmin >= xmax) {
xmin = 0.0;
xmax = nbins;
}
TH2D *out = new TH2D(name, title, nbins, xmin, xmax, nbins, xmin, xmax);
GetRhoIJ(out);
return out;
}
TH2D *TUnfold::GetEmatrix(char const *name, char const *title,
Double_t xmin, Double_t xmax) const
{
int nbins = fHistToX.GetSize() - 2;
if (xmin >= xmax) {
xmin = 0.0;
xmax = nbins;
}
TH2D *out = new TH2D(name, title, nbins, xmin, xmax, nbins, xmin, xmax);
GetEmatrix(out);
return out;
}
TH1D *TUnfold::GetRhoI(char const *name, char const *title,
Double_t xmin, Double_t xmax) const
{
int nbins = fHistToX.GetSize() - 2;
if (xmin >= xmax) {
xmin = 0.0;
xmax = nbins;
}
TH1D *out = new TH1D(name, title, nbins, xmin, xmax);
GetRhoI(out);
return out;
}
TH2D *TUnfold::GetLsquared(char const *name, char const *title,
Double_t xmin, Double_t xmax) const
{
int nbins = fHistToX.GetSize() - 2;
if (xmin >= xmax) {
xmin = 0.0;
xmax = nbins;
}
TH2D *out = new TH2D(name, title, nbins, xmin, xmax, nbins, xmin, xmax);
out->SetOption("BOX");
Int_t const *rows=fLsquared->GetRowIndexArray();
Int_t const *cols=fLsquared->GetColIndexArray();
Double_t const *data=fLsquared->GetMatrixArray();
for (Int_t i = 0; i < GetNx(); i++) {
for (Int_t cindex = rows[i]; cindex < rows[i+1]; cindex++) {
Int_t j=cols[cindex];
out->SetBinContent(fXToHist[i], fXToHist[j], fTau * data[cindex]);
}
}
return out;
}
Double_t const &TUnfold::GetTau(void) const
{
return fTau;
}
Double_t const &TUnfold::GetRhoMax(void) const
{
return fRhoMax;
}
Double_t const &TUnfold::GetRhoAvg(void) const
{
return fRhoAvg;
}
Double_t const &TUnfold::GetChi2A(void) const
{
return fChi2A;
}
Double_t const &TUnfold::GetChi2L(void) const
{
return fChi2L;
}
Int_t TUnfold::GetNdf(void) const
{
return fNdf;
}
Int_t TUnfold::GetNpar(void) const
{
return GetNx();
}
Double_t TUnfold::GetLcurveX(void) const {
return TMath::Log10(fChi2A);
}
Double_t TUnfold::GetLcurveY(void) const {
return TMath::Log10(fChi2L/fTau);
}
void TUnfold::GetOutput(TH1 *output,Int_t const *binMap) const {
Int_t nbin=output->GetNbinsX();
Double_t *c=new Double_t[nbin+2];
Double_t *e2=new Double_t[nbin+2];
for(Int_t i=0;i<nbin+2;i++) {
c[i]=0.0;
e2[i]=0.0;
}
Int_t binMapSize = fHistToX.GetSize();
for(Int_t i=0;i<binMapSize;i++) {
Int_t destBinI=binMap ? binMap[i] : i;
Int_t srcBinI=fHistToX[i];
if((destBinI>=0)&&(destBinI<nbin+2)&&(srcBinI>=0)) {
c[destBinI]+=(*fX)(srcBinI,0);
for(Int_t j=0;j<binMapSize;j++) {
Int_t destBinJ=binMap ? binMap[j] : j;
if(destBinI!=destBinJ) continue;
Int_t srcBinJ=fHistToX[j];
if(srcBinJ>=0) e2[destBinI]+= (*fE)(srcBinI,srcBinJ);
}
}
}
for(Int_t i=0;i<nbin+2;i++) {
output->SetBinContent(i,c[i]);
output->SetBinError(i,TMath::Sqrt(e2[i]));
}
delete[] c;
delete[] e2;
}
void TUnfold::ErrorMatrixToHist(TH2 *ematrix,TMatrixD const *emat,Int_t const *binMap,Bool_t doClear) const {
Int_t nbin=ematrix->GetNbinsX();
if(doClear) {
for(Int_t i=0;i<nbin+2;i++) {
for(Int_t j=0;j<nbin+2;j++) {
ematrix->SetBinContent(i,j,0.0);
ematrix->SetBinError(i,j,0.0);
}
}
}
if(emat) {
Int_t binMapSize = fHistToX.GetSize();
for(Int_t i=0;i<binMapSize;i++) {
Int_t destBinI=binMap ? binMap[i] : i;
Int_t srcBinI=fHistToX[i];
if((destBinI>=0)&&(destBinI<nbin+2)&&(srcBinI>=0)) {
for(Int_t j=0;j<binMapSize;j++) {
Int_t destBinJ=binMap ? binMap[j] : j;
Int_t srcBinJ=fHistToX[j];
if((destBinJ>=0)&&(destBinJ<nbin+2)&&(srcBinJ>=0)) {
Double_t e2=ematrix->GetBinContent(destBinI,destBinJ);
e2 += (*emat)(srcBinI,srcBinJ);
ematrix->SetBinContent(destBinI,destBinJ,e2);
}
}
}
}
}
}
void TUnfold::GetEmatrix(TH2 *ematrix,Int_t const *binMap) const {
ErrorMatrixToHist(ematrix,fE,binMap,kTRUE);
}
Double_t TUnfold::GetRhoI(TH1 *rhoi,TH2 *ematrixinv,Int_t const *binMap) const {
Int_t nbin=rhoi->GetNbinsX();
Int_t *nz=new Int_t[nbin+2];
for(Int_t i=0;i<nbin+2;i++) nz[i]=0;
Int_t binMapSize = fHistToX.GetSize();
for(Int_t i=0;i<binMapSize;i++) {
Int_t destBinI=binMap ? binMap[i] : i;
Int_t srcBinI=fHistToX[i];
if((destBinI>=0)&&(destBinI<nbin+2)&&(srcBinI>=0)) {
nz[destBinI]++;
}
}
Int_t n=0;
Int_t *destBin=new Int_t[nbin+2];
Int_t *matrixBin=new Int_t[nbin+2];
for(Int_t i=0;i<nbin+2;i++) {
if(nz[i]>0) {
matrixBin[i]=n;
destBin[n]=i;
n++;
} else {
matrixBin[i]=-1;
}
}
TMatrixD e(n,n);
for(Int_t i=0;i<binMapSize;i++) {
Int_t destBinI=binMap ? binMap[i] : i;
Int_t srcBinI=fHistToX[i];
if((destBinI>=0)&&(destBinI<nbin+2)&&(srcBinI>=0)) {
Int_t matrixBinI=matrixBin[destBinI];
for(Int_t j=0;j<binMapSize;j++) {
Int_t destBinJ=binMap ? binMap[j] : j;
Int_t srcBinJ=fHistToX[j];
if((destBinJ>=0)&&(destBinJ<nbin+2)&&(srcBinJ>=0)) {
Int_t matrixBinJ=matrixBin[destBinJ];
e(matrixBinI,matrixBinJ) += (*fE)(srcBinI,srcBinJ);
}
}
}
}
TMatrixD einv(e);
InvertMConditioned(einv);
Double_t rhoMax=0.0;
for(Int_t i=0;i<n;i++) {
Int_t destBinI=destBin[i];
Double_t rho=1.-1./(einv(i,i)*e(i,i));
if(rho>=0.0) rho=TMath::Sqrt(rho);
else rho=-TMath::Sqrt(-rho);
if(rho>rhoMax) {
rhoMax = rho;
}
rhoi->SetBinContent(destBinI,rho);
if(ematrixinv) {
for(Int_t j=0;j<n;j++) {
ematrixinv->SetBinContent(destBinI,destBin[j],einv(i,j));
}
}
}
delete[] nz;
delete[] destBin;
delete[] matrixBin;
return rhoMax;
}
void TUnfold::GetRhoIJ(TH2 *rhoij,Int_t const *binMap) const {
GetEmatrix(rhoij,binMap);
Int_t nbin=rhoij->GetNbinsX();
Double_t *e=new Double_t[nbin+2];
for(Int_t i=0;i<nbin+2;i++) {
e[i]=TMath::Sqrt(rhoij->GetBinContent(i,i));
}
for(Int_t i=0;i<nbin+2;i++) {
for(Int_t j=0;j<nbin+2;j++) {
if((e[i]>0.0)&&(e[j]>0.0)) {
rhoij->SetBinContent(i,j,rhoij->GetBinContent(i,j)/e[i]/e[j]);
} else {
rhoij->SetBinContent(i,j,0.0);
}
}
}
delete[] e;
}