#include <iostream>
#include <TUnfoldSys.h>
#include <TMap.h>
#include <TMath.h>
#include <TObjString.h>
#include <RVersion.h>
ClassImp(TUnfoldSys)
TUnfoldSys::TUnfoldSys(void) {
InitTUnfoldSys();
}
TUnfoldSys::TUnfoldSys(TH2 const *hist_A, EHistMap histmap, ERegMode regmode)
: TUnfold(hist_A,histmap,regmode) {
InitTUnfoldSys();
fAoutside = new TMatrixD(GetNx(),2);
fDAcol = new TMatrixD(GetNx(),1);
Int_t nmax=GetNx()*GetNy();
Int_t *rowDA2 = new Int_t[nmax];
Int_t *colDA2 = new Int_t[nmax];
Double_t *dataDA2 = new Double_t[nmax];
Int_t da2col_nonzero=0;
Int_t da2_nonzero=0;
for (Int_t ix = 0; ix < GetNx(); ix++) {
Int_t ibinx = fXToHist[ix];
for (Int_t ibiny = 0; ibiny <= GetNy()+1; ibiny++) {
Double_t z,dz;
if (histmap == kHistMapOutputHoriz) {
z = hist_A->GetBinContent(ibinx, ibiny);
dz = hist_A->GetBinError(ibinx, ibiny);
} else {
z = hist_A->GetBinContent(ibiny, ibinx);
dz = hist_A->GetBinError(ibiny, ibinx);
}
if(ibiny==0) {
(*fAoutside)(ix,0)=z;
if(dz>0.0) {
(*fDAcol)(ix,0) += dz*dz;
da2col_nonzero++;
}
} else if(ibiny==GetNy()+1) {
(*fAoutside)(ix,1)=z;
if(dz>0.0) {
(*fDAcol)(ix,0) += dz*dz;
da2col_nonzero++;
}
} else {
Double_t sum= fSumOverY[ix];
Double_t error =
(sum-z)/sum/sum * dz;
rowDA2[da2_nonzero]=ibiny-1;
colDA2[da2_nonzero] = ix;
dataDA2[da2_nonzero] = error*error;
if(dataDA2[da2_nonzero]>0.0) da2_nonzero++;
}
}
}
if(da2_nonzero) {
fDA2 = new TMatrixDSparse(GetNy(),GetNx());
fDA2->SetMatrixArray(da2_nonzero,rowDA2,colDA2,dataDA2);
}
if(!da2col_nonzero) {
delete fDAcol;
fDAcol=0;
} else {
for (Int_t ix = 0; ix < GetNx(); ix++) {
(*fDAcol)(ix,0) = TMath::Sqrt((*fDAcol)(ix,0))/fSumOverY[ix];
}
}
delete [] rowDA2;
delete [] colDA2;
delete [] dataDA2;
}
void TUnfoldSys::AddSysError(TH2 const *sysError,char const *name,
EHistMap histmap,ESysErrMode mode) {
if(fSysIn->FindObject(name)) {
std::cout<<"UnfoldSys::AddSysError \""<<name
<<"\" has already been added, ignoring\n";
} else {
TMatrixD aCopy(*fA);
Int_t nmax= GetNx()*GetNy();
Double_t *data=new Double_t[nmax];
Int_t *cols=new Int_t[nmax];
Int_t *rows=new Int_t[nmax];
nmax=0;
for (Int_t ix = 0; ix < GetNx(); ix++) {
Int_t ibinx = fXToHist[ix];
Double_t sum=0.0;
for(Int_t loop=0;loop<2;loop++) {
for (Int_t ibiny = 0; ibiny <= GetNy()+1; ibiny++) {
Double_t z;
if (histmap == kHistMapOutputHoriz) {
z = sysError->GetBinContent(ibinx, ibiny);
} else {
z = sysError->GetBinContent(ibiny, ibinx);
}
if(mode!=kSysErrModeMatrix) {
Double_t z0;
if((ibiny>0)&&(ibiny<=GetNy())) {
z0=aCopy(ibiny-1,ix)*fSumOverY[ix];
} else if(ibiny==0) {
z0=(*fAoutside)(ix,0);
} else {
z0=(*fAoutside)(ix,1);
}
if(mode==kSysErrModeShift) {
z += z0;
} else if(mode==kSysErrModeRelative) {
z = z0*(1.+z);
}
}
if(loop==0) {
sum += z;
} else {
if((ibiny>0)&&(ibiny<=GetNy())) {
rows[nmax]=ibiny-1;
cols[nmax]=ix;
if(sum>0.0) {
data[nmax]=z/sum-aCopy(ibiny-1,ix);
} else {
data[nmax]=0.0;
}
if(data[nmax] != 0.0) nmax++;
}
}
}
}
}
std::cout<<nmax<<" "<<GetNy()*GetNx()<<"\n";
TMatrixDSparse *dsys=new TMatrixDSparse(GetNy(),GetNx());
if(nmax==0) {
std::cout<<"UnfoldSys::AddSysError source \""<<name
<<"\" has no influence on the result.\n";
}
dsys->SetMatrixArray(nmax,rows,cols,data);
delete[] data;
delete[] rows;
delete[] cols;
fSysIn->Add(new TObjString(name),dsys);
}
}
void TUnfoldSys::InitTUnfoldSys(void) {
fDA2 = 0;
fDAcol = 0;
fAoutside = 0;
fSysIn = new TMap();
#if ROOT_VERSION_CODE >= ROOT_VERSION(5,20,00)
fSysIn->SetOwnerKeyValue();
#else
fSysIn->SetOwner();
#endif
fVYAx = 0;
fESparse = 0;
fEAtV = 0;
fErrorUncorrX = 0;
fErrorUncorrAx = 0;
fAE = 0;
fAEAtV_one = 0;
fErrorCorrX = new TMap();
fErrorCorrAx = new TMap();
#if ROOT_VERSION_CODE >= ROOT_VERSION(5,20,00)
fErrorCorrX->SetOwnerKeyValue();
fErrorCorrAx->SetOwnerKeyValue();
#else
fErrorCorrX->SetOwner();
fErrorCorrAx->SetOwner();
#endif
}
TUnfoldSys::~TUnfoldSys(void) {
DeleteMatrix(&fDA2);
delete fSysIn;
ClearResults();
delete fErrorCorrX;
delete fErrorCorrAx;
}
void TUnfoldSys::ClearResults(void) {
TUnfold::ClearResults();
DeleteMatrix(&fVYAx);
DeleteMatrix(&fESparse);
DeleteMatrix(&fEAtV);
DeleteMatrix(&fErrorUncorrX);
DeleteMatrix(&fErrorUncorrAx);
DeleteMatrix(&fAE);
DeleteMatrix(&fAEAtV_one);
fErrorCorrX->Clear();
fErrorCorrAx->Clear();
}
void TUnfoldSys::PrepareSysError(void) {
if(!fVYAx) {
TMatrixD yAx(*fY,TMatrixD::kMinus,*fAx);
fVYAx=MultiplyMSparseM(*fV,yAx);
}
if(!fESparse) {
fESparse=new TMatrixDSparse(*fE);
}
if(!fEAtV) {
fEAtV=MultiplyMSparseMSparse(*fESparse,*fAtV);
}
if(!fAE) {
fAE = MultiplyMSparseMSparse(*fA,*fESparse);
}
if(!fAEAtV_one) {
fAEAtV_one=MultiplyMSparseMSparse(*fA,*fEAtV);
Int_t *rows_cols=new Int_t[GetNy()];
Double_t *data=new Double_t[GetNy()];
for(Int_t i=0;i<GetNy();i++) {
rows_cols[i]=i;
data[i]=1.0;
}
TMatrixDSparse one(GetNy(),GetNy());
one.SetMatrixArray(GetNy(),rows_cols, rows_cols,data);
AddMSparse(*fAEAtV_one,-1.,one);
delete [] data;
delete [] rows_cols;
}
if(!fErrorUncorrX) {
fErrorUncorrX=PrepareUncorrEmat(fESparse,fEAtV);
}
if(!fErrorUncorrAx) {
fErrorUncorrAx=PrepareUncorrEmat(fAE,fAEAtV_one);
}
TMapIter sysErrIn(fSysIn);
TObjString const *key;
for(key=(TObjString const *)sysErrIn.Next();key;
key=(TObjString const *)sysErrIn.Next()) {
#if ROOT_VERSION_CODE >= ROOT_VERSION(5,20,00)
TMatrixDSparse const *dsys=
(TMatrixDSparse const *)((TPair const *)*sysErrIn)->Value();
#else
TMatrixDSparse const *dsys=
(TMatrixDSparse const *)(fSysIn->GetValue(key->GetString()));
#endif
TPair const *named_emat=(TPair const *)
fErrorCorrX->FindObject(key->GetString());
if(!named_emat) {
TMatrixD *emat=PrepareCorrEmat(fESparse,fEAtV,dsys);
fErrorCorrX->Add(new TObjString(*key),emat);
}
named_emat=(TPair const *)fErrorCorrAx->FindObject(key->GetString());
if(!named_emat) {
TMatrixD *emat=PrepareCorrEmat(fAE,fAEAtV_one,dsys);
fErrorCorrAx->Add(new TObjString(*key),emat);
}
}
}
void TUnfoldSys::GetEmatrixSysUncorr(TH2 *ematrix,Int_t const *binMap,Bool_t clearEmat) {
PrepareSysError();
ErrorMatrixToHist(ematrix,fErrorUncorrX,binMap,clearEmat);
}
TMatrixD *TUnfoldSys::PrepareUncorrEmat(TMatrixDSparse const *m1,TMatrixDSparse const *m2) {
TMatrixD *r=new TMatrixD(m1->GetNrows(),m1->GetNrows());
if(fDA2) {
const Int_t *DA2_rows=fDA2->GetRowIndexArray();
const Int_t *DA2_cols=fDA2->GetColIndexArray();
const Double_t *DA2_data=fDA2->GetMatrixArray();
const Int_t *fVYAx_rows=fVYAx->GetRowIndexArray();
const Double_t *fVYAx_data=fVYAx->GetMatrixArray();
TMatrixD DA2t_VYAx2(fDA2->GetNcols(),1);
for(Int_t i=0;i<fVYAx->GetNrows();i++) {
if(fVYAx_rows[i]==fVYAx_rows[i+1]) continue;
for(Int_t index=DA2_rows[i];index<DA2_rows[i+1];index++) {
Int_t j=DA2_cols[index];
Double_t fVYAx_j=fVYAx_data[fVYAx_rows[i]];
DA2t_VYAx2(j,0) += DA2_data[index]*fVYAx_j*fVYAx_j;
}
}
TMatrixD DA2_x2(fDA2->GetNrows(),1);
for(Int_t i=0;i<fDA2->GetNrows();i++) {
for(Int_t index=DA2_rows[i];index<DA2_rows[i+1];index++) {
Int_t j=DA2_cols[index];
DA2_x2(i,0) += DA2_data[index]*(*fX)(j,0)*(*fX)(j,0);
}
}
TMatrixDSparse mDA2_VYAx(*fDA2);
Double_t *mDA2_VYAx_data=mDA2_VYAx.GetMatrixArray();
for(Int_t i=0;i<fDA2->GetNrows();i++) {
for(Int_t index=DA2_rows[i];index<DA2_rows[i+1];index++) {
if(fVYAx_rows[i]==fVYAx_rows[i+1]) {
mDA2_VYAx_data[index]=0.0;
} else {
mDA2_VYAx_data[index] *= fVYAx_data[fVYAx_rows[i]];
}
}
}
TMatrixDSparse *m2_mDA2_VYAx = MultiplyMSparseMSparse(*m2,mDA2_VYAx);
const Int_t *m2_mDA2_VYAx_rows=m2_mDA2_VYAx->GetRowIndexArray();
const Int_t *m2_mDA2_VYAx_cols=m2_mDA2_VYAx->GetColIndexArray();
const Double_t *m2_mDA2_VYAx_data=m2_mDA2_VYAx->GetMatrixArray();
const Int_t *m1_rows=m1->GetRowIndexArray();
const Int_t *m1_cols=m1->GetColIndexArray();
const Double_t *m1_data=m1->GetMatrixArray();
const Int_t *m2_rows=m2->GetRowIndexArray();
const Int_t *m2_cols=m2->GetColIndexArray();
const Double_t *m2_data=m2->GetMatrixArray();
for(Int_t m=0;m<r->GetNrows();m++) {
for(Int_t n=0;n<r->GetNrows();n++) {
Int_t index_m=m1_rows[m];
Int_t index_n=m1_rows[n];
while((index_m<m1_rows[m+1])&&(index_n<m1_rows[n+1])) {
Int_t j=m1_cols[index_m];
Int_t delta=j-m1_cols[index_n];
if(delta<0) {
index_m++;
} else if(delta>0) {
index_n++;
} else {
(*r)(m,n) +=
m1_data[index_m]*m1_data[index_n]*DA2t_VYAx2(j,0);
index_m++;
index_n++;
}
}
index_m=m2_rows[m];
index_n=m2_rows[n];
while((index_m<m2_rows[m+1])&&(index_n<m2_rows[n+1])) {
Int_t i=m2_cols[index_m];
Int_t delta=i-m2_cols[index_n];
if(delta<0) {
index_m++;
} else if(delta>0) {
index_n++;
} else {
(*r)(m,n) +=
m2_data[index_m]*m2_data[index_n]*DA2_x2(i,0);
index_m++;
index_n++;
}
}
}
for(Int_t n=0;n<m1->GetNrows();n++) {
Int_t index_m=m2_mDA2_VYAx_rows[m];
Int_t index_n=m1_rows[n];
while((index_m<m2_mDA2_VYAx_rows[m+1])
&&(index_n<m1_rows[n+1])) {
Int_t j=m2_mDA2_VYAx_cols[index_m];
Int_t delta=j-m1_cols[index_n];
if(delta<0) {
index_m++;
} else if(delta>0) {
index_n++;
} else {
Double_t d_mn = m1_data[index_n]*m2_mDA2_VYAx_data[index_n]*
(*fX)(j,0);
(*r)(m,n) -= d_mn;
(*r)(n,m) -= d_mn;
index_m++;
index_n++;
}
}
}
}
delete m2_mDA2_VYAx;
}
if(fDAcol) {
TMatrixDSparse *delta=MultiplyMSparseMSparse(*m2,*fA);
Double_t *delta_data=delta->GetMatrixArray();
const Int_t *delta_rows=delta->GetRowIndexArray();
const Int_t *delta_cols=delta->GetColIndexArray();
for(Int_t row=0;row<delta->GetNrows();row++) {
for(Int_t index=delta_rows[row];index<delta_rows[row+1];index++) {
Int_t col=delta_cols[index];
delta_data[index] *= (*fX)(col,0);
}
}
TMatrixDSparse *AtVYAx=MultiplyMSparseTranspMSparse(*fA,*fVYAx);
const Double_t *AtVYAx_data=AtVYAx->GetMatrixArray();
const Int_t *AtVYAx_rows=AtVYAx->GetRowIndexArray();
const Int_t *m1_rows=m1->GetRowIndexArray();
const Int_t *m1_cols=m1->GetColIndexArray();
const Double_t *m1_data=m1->GetMatrixArray();
Int_t nmax= m1_rows[m1->GetNrows()];
if(nmax>0) {
Double_t *delta2_data=new Double_t[nmax];
Int_t *delta2_rows=new Int_t[nmax];
Int_t *delta2_cols=new Int_t[nmax];
nmax=0;
for(Int_t row=0;row<m1->GetNrows();row++) {
for(Int_t index=m1_rows[row];index<m1_rows[row+1];index++) {
Int_t col=m1_cols[index];
if(AtVYAx_rows[col]<AtVYAx_rows[col+1]) {
delta2_rows[nmax]=row;
delta2_cols[nmax]=col;
delta2_data[nmax]=m1_data[index]*
AtVYAx_data[AtVYAx_rows[col]];
if(delta2_data[nmax] !=0.0) nmax++;
}
}
}
if(nmax>0) {
TMatrixDSparse delta2(m1->GetNrows(),m1->GetNcols());
delta2.SetMatrixArray(nmax,delta2_rows,delta2_cols,delta2_data);
AddMSparse(*delta,-1.,delta2);
}
delete [] delta2_cols;
delete [] delta2_rows;
delete [] delta2_data;
}
delete AtVYAx;
delta_data=delta->GetMatrixArray();
delta_rows=delta->GetRowIndexArray();
delta_cols=delta->GetColIndexArray();
for(Int_t row=0;row<delta->GetNrows();row++) {
for(Int_t index=delta_rows[row];index<delta_rows[row+1];index++) {
Int_t col=delta_cols[index];
delta_data[index] *= (*fDAcol)(col,0);
}
}
for(Int_t row=0;row<delta->GetNrows();row++) {
for(Int_t col=0;col<delta->GetNrows();col++) {
Int_t index1=delta_rows[row];
Int_t index2=delta_rows[col];
while((index1<delta_rows[row+1])&&(index2<delta_rows[col+1])) {
Int_t j=delta_cols[index1];
Int_t dj=j-delta_cols[index2];
if(dj<0) {
index1++;
} else if(dj>0) {
index2++;
} else {
(*r)(row,col) += delta_data[index1]*delta_data[index2];
index1++;
index2++;
}
}
}
}
delete delta;
}
return r;
}
TMatrixD *TUnfoldSys::PrepareCorrEmat(TMatrixDSparse const *m1,TMatrixDSparse const *m2,TMatrixDSparse const *dsys) {
TMatrixD *r=new TMatrixD(m1->GetNrows(),m1->GetNrows());
TMatrixDSparse *dsysT_VYAx = MultiplyMSparseTranspMSparse(*dsys,*fVYAx);
TMatrixDSparse *delta = MultiplyMSparseMSparse(*m1,*dsysT_VYAx);
delete dsysT_VYAx;
TMatrixDSparse *dsys_X = MultiplyMSparseM(*dsys,*fX);
TMatrixDSparse *delta2 = MultiplyMSparseMSparse(*m2,*dsys_X);
delete dsys_X;
AddMSparse(*delta,-1.0,*delta2);
delete delta2;
const Double_t *delta_data=delta->GetMatrixArray();
const Int_t *delta_rows=delta->GetRowIndexArray();
for(Int_t row=0;row<delta->GetNrows();row++) {
if(delta_rows[row]>=delta_rows[row+1]) continue;
for(Int_t col=0;col<delta->GetNrows();col++) {
if(delta_rows[col]>=delta_rows[col+1]) continue;
(*r)(row,col)=
delta_data[delta_rows[row]]*delta_data[delta_rows[col]];
}
}
delete delta;
return r;
}
void TUnfoldSys::GetEmatrixSysSource(TH2 *ematrix,char const *name,
Int_t const *binMap,Bool_t clearEmat) {
PrepareSysError();
TPair const *named_emat=(TPair const *)fErrorUncorrX->FindObject(name);
TMatrixD *emat=0;
if(named_emat) {
emat=(TMatrixD *)named_emat->Value();
}
ErrorMatrixToHist(ematrix,emat,binMap,clearEmat);
}
void TUnfoldSys::GetEmatrixSysTotal(TH2 *ematrix,Int_t const *binMap,
Bool_t clearEmat) {
GetEmatrixSysUncorr(ematrix,binMap,clearEmat);
TMapIter sysErrPtr(fErrorCorrX);
TObject const *key;
for(key=sysErrPtr.Next();key;key=sysErrPtr.Next()) {
ErrorMatrixToHist
(ematrix,
(TMatrixD const *)
#if ROOT_VERSION_CODE >= ROOT_VERSION(5,20,00)
((TPair const *)*sysErrPtr)->Value()
#else
(fErrorCorrX->GetValue(((TObjString const *)key)->GetString()))
#endif
,binMap,kFALSE);
}
}
void TUnfoldSys::GetEmatrixTotal(TH2 *ematrix,Int_t const *binMap) {
GetEmatrix(ematrix,binMap);
GetEmatrixSysTotal(ematrix,binMap,kFALSE);
}
Double_t TUnfoldSys::GetChi2Sys(void) {
PrepareSysError();
TMatrixD *emat_sum_1=InvertMSparse(*fV);
TMatrixDSparse emat_sum(*emat_sum_1);
delete emat_sum_1;
AddMSparse(emat_sum,1.0,*fErrorUncorrAx);
TMapIter sysErrPtr(fErrorCorrAx);
TObject const *key;
for(key=sysErrPtr.Next();key;key=sysErrPtr.Next()) {
AddMSparse(emat_sum,1.0,
*(TMatrixD const *)
#if ROOT_VERSION_CODE >= ROOT_VERSION(5,20,00)
((TPair const *)*sysErrPtr)->Value()
#else
fErrorCorrAx->GetValue(((TObjString const *)key)
->GetString())
#endif
);
}
TMatrixD *v=InvertMSparse(emat_sum);
TMatrixD dy(*fY, TMatrixD::kMinus, *fAx);
Double_t r=MultiplyVecMSparseVec(*v,dy);
delete v;
return r;
}