132 TUnfold::~TUnfold(
void)
141 DeleteMatrix(&fVyyInv);
149 void TUnfold::InitTUnfold(
void)
162 fConstraint = kEConstraintNone;
163 fRegMode = kRegModeNone;
195 void TUnfold::DeleteMatrix(TMatrixD **m)
209 void TUnfold::DeleteMatrix(TMatrixDSparse **m)
218 void TUnfold::ClearResults(
void)
230 for(Int_t i=0;i<2;i++) {
231 DeleteMatrix(fDXDAM+i);
232 DeleteMatrix(fDXDAZ+i);
234 DeleteMatrix(&fDXDtauSquared);
235 DeleteMatrix(&fDXDY);
236 DeleteMatrix(&fEinv);
238 DeleteMatrix(&fVxxInv);
248 TUnfold::TUnfold(
void)
290 Double_t TUnfold::DoUnfold(
void)
296 GetInputInverseEmatrix(0);
297 if(fConstraint != kEConstraintNone) {
306 TMatrixDSparse *AtVyyinv=MultiplyMSparseTranspMSparse(fA,fVyyInv);
312 TMatrixDSparse *rhs=MultiplyMSparseM(AtVyyinv,fY);
313 TMatrixDSparse *lSquared=MultiplyMSparseTranspMSparse(fL,fL);
314 if (fBiasScale != 0.0) {
315 TMatrixDSparse *rhs2=MultiplyMSparseM(lSquared,fX0);
316 AddMSparse(rhs, fTauSquared * fBiasScale ,rhs2);
324 fEinv=MultiplyMSparseMSparse(AtVyyinv,fA);
325 AddMSparse(fEinv,fTauSquared,lSquared);
333 fE = InvertMSparseSymmPos(fEinv,&rank);
334 if(rank != GetNx()) {
335 Warning(
"DoUnfold",
"rank of matrix E %d expect %d",rank,GetNx());
342 TMatrixDSparse *xSparse=MultiplyMSparseMSparse(fE,rhs);
343 fX =
new TMatrixD(*xSparse);
345 DeleteMatrix(&xSparse);
348 Double_t lambda_half=0.0;
349 Double_t one_over_epsEeps=0.0;
350 TMatrixDSparse *epsilon=0;
351 TMatrixDSparse *Eepsilon=0;
352 if(fConstraint != kEConstraintNone) {
354 const Int_t *A_rows=fA->GetRowIndexArray();
355 const Int_t *A_cols=fA->GetColIndexArray();
356 const Double_t *A_data=fA->GetMatrixArray();
357 TMatrixD epsilonNosparse(fA->GetNcols(),1);
358 for(Int_t i=0;i<A_rows[fA->GetNrows()];i++) {
359 epsilonNosparse(A_cols[i],0) += A_data[i];
361 epsilon=
new TMatrixDSparse(epsilonNosparse);
363 Eepsilon=MultiplyMSparseMSparse(fE,epsilon);
365 TMatrixDSparse *epsilonEepsilon=MultiplyMSparseTranspMSparse(epsilon,
368 if(epsilonEepsilon->GetRowIndexArray()[1]==1) {
369 one_over_epsEeps=1./epsilonEepsilon->GetMatrixArray()[0];
371 Fatal(
"Unfold",
"epsilon#Eepsilon has dimension %d != 1",
372 epsilonEepsilon->GetRowIndexArray()[1]);
374 DeleteMatrix(&epsilonEepsilon);
376 Double_t y_minus_epsx=0.0;
377 for(Int_t iy=0;iy<fY->GetNrows();iy++) {
378 y_minus_epsx += (*fY)(iy,0);
381 for(Int_t ix=0;ix<epsilonNosparse.GetNrows();ix++) {
382 y_minus_epsx -= epsilonNosparse(ix,0) * (*fX)(ix,0);
385 lambda_half=y_minus_epsx*one_over_epsEeps;
387 const Int_t *EEpsilon_rows=Eepsilon->GetRowIndexArray();
388 const Double_t *EEpsilon_data=Eepsilon->GetMatrixArray();
389 for(Int_t ix=0;ix<Eepsilon->GetNrows();ix++) {
390 if(EEpsilon_rows[ix]<EEpsilon_rows[ix+1]) {
391 (*fX)(ix,0) += lambda_half * EEpsilon_data[EEpsilon_rows[ix]];
399 fDXDY = MultiplyMSparseMSparse(fE,AtVyyinv);
402 if(fConstraint != kEConstraintNone) {
404 Int_t *rows=
new Int_t[GetNy()];
405 Int_t *cols=
new Int_t[GetNy()];
406 Double_t *data=
new Double_t[GetNy()];
407 for(Int_t i=0;i<GetNy();i++) {
410 data[i]=one_over_epsEeps;
412 TMatrixDSparse *temp=CreateSparseMatrix
413 (1,GetNy(),GetNy(),rows,cols,data);
418 TMatrixDSparse *epsilonB=MultiplyMSparseTranspMSparse(epsilon,fDXDY);
420 AddMSparse(temp, -one_over_epsEeps, epsilonB);
421 DeleteMatrix(&epsilonB);
423 TMatrixDSparse *corr=MultiplyMSparseMSparse(Eepsilon,temp);
426 AddMSparse(fDXDY,1.0,corr);
430 DeleteMatrix(&AtVyyinv);
435 TMatrixDSparse *fDXDYVyy = MultiplyMSparseMSparse(fDXDY,fVyy);
436 fVxx = MultiplyMSparseMSparseTranspVector(fDXDYVyy,fDXDY,0);
438 DeleteMatrix(&fDXDYVyy);
444 fAx = MultiplyMSparseM(fA,fX);
450 TMatrixD dy(*fY, TMatrixD::kMinus, *fAx);
451 TMatrixDSparse *VyyinvDy=MultiplyMSparseM(fVyyInv,&dy);
453 const Int_t *VyyinvDy_rows=VyyinvDy->GetRowIndexArray();
454 const Double_t *VyyinvDy_data=VyyinvDy->GetMatrixArray();
456 for(Int_t iy=0;iy<VyyinvDy->GetNrows();iy++) {
457 if(VyyinvDy_rows[iy]<VyyinvDy_rows[iy+1]) {
458 fChi2A += VyyinvDy_data[VyyinvDy_rows[iy]]*dy(iy,0);
461 TMatrixD dx( fBiasScale * (*fX0), TMatrixD::kMinus,(*fX));
462 TMatrixDSparse *LsquaredDx=MultiplyMSparseM(lSquared,&dx);
463 const Int_t *LsquaredDx_rows=LsquaredDx->GetRowIndexArray();
464 const Double_t *LsquaredDx_data=LsquaredDx->GetMatrixArray();
466 for(Int_t ix=0;ix<LsquaredDx->GetNrows();ix++) {
467 if(LsquaredDx_rows[ix]<LsquaredDx_rows[ix+1]) {
468 fLXsquared += LsquaredDx_data[LsquaredDx_rows[ix]]*dx(ix,0);
474 fDXDtauSquared=MultiplyMSparseMSparse(fE,LsquaredDx);
476 if(fConstraint != kEConstraintNone) {
477 TMatrixDSparse *temp=MultiplyMSparseTranspMSparse(epsilon,fDXDtauSquared);
479 if(temp->GetRowIndexArray()[1]==1) {
480 f=temp->GetMatrixArray()[0]*one_over_epsEeps;
481 }
else if(temp->GetRowIndexArray()[1]>1) {
483 "epsilon#fDXDtauSquared has dimension %d != 1",
484 temp->GetRowIndexArray()[1]);
487 AddMSparse(fDXDtauSquared, -f,Eepsilon);
491 DeleteMatrix(&epsilon);
493 DeleteMatrix(&LsquaredDx);
494 DeleteMatrix(&lSquared);
497 fDXDAM[0]=
new TMatrixDSparse(*fE);
498 fDXDAM[1]=
new TMatrixDSparse(*fDXDY);
501 fDXDAZ[1]=
new TMatrixDSparse(*fX);
503 if(fConstraint != kEConstraintNone) {
505 TMatrixDSparse *temp1=MultiplyMSparseMSparseTranspVector
506 (Eepsilon,Eepsilon,0);
507 AddMSparse(fDXDAM[0], -one_over_epsEeps,temp1);
508 DeleteMatrix(&temp1);
510 Int_t *rows=
new Int_t[GetNy()];
511 Int_t *cols=
new Int_t[GetNy()];
512 Double_t *data=
new Double_t[GetNy()];
513 for(Int_t i=0;i<GetNy();i++) {
518 TMatrixDSparse *temp2=CreateSparseMatrix
519 (GetNy(),1,GetNy(),rows,cols,data);
523 AddMSparse(fDXDAZ[0],1.0,temp2);
524 DeleteMatrix(&temp2);
527 DeleteMatrix(&Eepsilon);
530 fVxxInv = InvertMSparseSymmPos(fVxx,&rank);
531 if(rank != GetNx()) {
532 Warning(
"DoUnfold",
"rank of output covariance is %d expect %d",
536 TVectorD VxxInvDiag(fVxxInv->GetNrows());
537 const Int_t *VxxInv_rows=fVxxInv->GetRowIndexArray();
538 const Int_t *VxxInv_cols=fVxxInv->GetColIndexArray();
539 const Double_t *VxxInv_data=fVxxInv->GetMatrixArray();
540 for (
int ix = 0; ix < fVxxInv->GetNrows(); ix++) {
541 for(
int ik=VxxInv_rows[ix];ik<VxxInv_rows[ix+1];ik++) {
542 if(ix==VxxInv_cols[ik]) {
543 VxxInvDiag(ix)=VxxInv_data[ik];
549 const Int_t *Vxx_rows=fVxx->GetRowIndexArray();
550 const Int_t *Vxx_cols=fVxx->GetColIndexArray();
551 const Double_t *Vxx_data=fVxx->GetMatrixArray();
553 Double_t rho_squared_max = 0.0;
554 Double_t rho_sum = 0.0;
556 for (
int ix = 0; ix < fVxx->GetNrows(); ix++) {
557 for(
int ik=Vxx_rows[ix];ik<Vxx_rows[ix+1];ik++) {
558 if(ix==Vxx_cols[ik]) {
559 Double_t rho_squared =
560 1. - 1. / (VxxInvDiag(ix) * Vxx_data[ik]);
561 if (rho_squared > rho_squared_max)
562 rho_squared_max = rho_squared;
563 if(rho_squared>0.0) {
564 rho_sum += TMath::Sqrt(rho_squared);
571 fRhoMax = TMath::Sqrt(rho_squared_max);
572 fRhoAvg = (n_rho>0) ? (rho_sum/n_rho) : -1.0;
591 TMatrixDSparse *TUnfold::CreateSparseMatrix
592 (Int_t nrow,Int_t ncol,Int_t nel,Int_t *row,Int_t *col,Double_t *data)
const
598 TMatrixDSparse *A=
new TMatrixDSparse(nrow,ncol);
600 A->SetMatrixArray(nel,row,col,data);
617 TMatrixDSparse *TUnfold::MultiplyMSparseMSparse(
const TMatrixDSparse *a,
618 const TMatrixDSparse *b)
const
620 if(a->GetNcols()!=b->GetNrows()) {
621 Fatal(
"MultiplyMSparseMSparse",
622 "inconsistent matrix col/ matrix row %d !=%d",
623 a->GetNcols(),b->GetNrows());
626 TMatrixDSparse *r=
new TMatrixDSparse(a->GetNrows(),b->GetNcols());
627 const Int_t *a_rows=a->GetRowIndexArray();
628 const Int_t *a_cols=a->GetColIndexArray();
629 const Double_t *a_data=a->GetMatrixArray();
630 const Int_t *b_rows=b->GetRowIndexArray();
631 const Int_t *b_cols=b->GetColIndexArray();
632 const Double_t *b_data=b->GetMatrixArray();
635 for (Int_t irow = 0; irow < a->GetNrows(); irow++) {
636 if(a_rows[irow+1]>a_rows[irow]) nMax += b->GetNcols();
638 if((nMax>0)&&(a_cols)&&(b_cols)) {
639 Int_t *r_rows=
new Int_t[nMax];
640 Int_t *r_cols=
new Int_t[nMax];
641 Double_t *r_data=
new Double_t[nMax];
642 Double_t *row_data=
new Double_t[b->GetNcols()];
644 for (Int_t irow = 0; irow < a->GetNrows(); irow++) {
645 if(a_rows[irow+1]<=a_rows[irow])
continue;
647 for(Int_t icol=0;icol<b->GetNcols();icol++) {
651 for(Int_t ia=a_rows[irow];ia<a_rows[irow+1];ia++) {
654 for(Int_t ib=b_rows[k];ib<b_rows[k+1];ib++) {
655 row_data[b_cols[ib]] += a_data[ia]*b_data[ib];
659 for(Int_t icol=0;icol<b->GetNcols();icol++) {
660 if(row_data[icol] != 0.0) {
663 r_data[n]=row_data[icol];
669 r->SetMatrixArray(n,r_rows,r_cols,r_data);
692 TMatrixDSparse *TUnfold::MultiplyMSparseTranspMSparse
693 (
const TMatrixDSparse *a,
const TMatrixDSparse *b)
const
695 if(a->GetNrows() != b->GetNrows()) {
696 Fatal(
"MultiplyMSparseTranspMSparse",
697 "inconsistent matrix row numbers %d!=%d",
698 a->GetNrows(),b->GetNrows());
701 TMatrixDSparse *r=
new TMatrixDSparse(a->GetNcols(),b->GetNcols());
702 const Int_t *a_rows=a->GetRowIndexArray();
703 const Int_t *a_cols=a->GetColIndexArray();
704 const Double_t *a_data=a->GetMatrixArray();
705 const Int_t *b_rows=b->GetRowIndexArray();
706 const Int_t *b_cols=b->GetColIndexArray();
707 const Double_t *b_data=b->GetMatrixArray();
711 typedef std::map<Int_t,Double_t> MMatrixRow_t;
712 typedef std::map<Int_t, MMatrixRow_t > MMatrix_t;
715 for(Int_t iRowAB=0;iRowAB<a->GetNrows();iRowAB++) {
716 for(Int_t ia=a_rows[iRowAB];ia<a_rows[iRowAB+1];ia++) {
717 for(Int_t ib=b_rows[iRowAB];ib<b_rows[iRowAB+1];ib++) {
719 MMatrixRow_t &row=matrix[a_cols[ia]];
720 MMatrixRow_t::iterator icol=row.find(b_cols[ib]);
721 if(icol!=row.end()) {
723 (*icol).second += a_data[ia]*b_data[ib];
726 row[b_cols[ib]] = a_data[ia]*b_data[ib];
733 for (MMatrix_t::const_iterator irow = matrix.begin(); irow != matrix.end(); ++irow) {
734 n += (*irow).second.size();
738 Int_t *r_rows=
new Int_t[n];
739 Int_t *r_cols=
new Int_t[n];
740 Double_t *r_data=
new Double_t[n];
742 for (MMatrix_t::const_iterator irow = matrix.begin(); irow != matrix.end(); ++irow) {
743 for (MMatrixRow_t::const_iterator icol = (*irow).second.begin(); icol != (*irow).second.end(); ++icol) {
744 r_rows[n]=(*irow).first;
745 r_cols[n]=(*icol).first;
746 r_data[n]=(*icol).second;
752 r->SetMatrixArray(n,r_rows,r_cols,r_data);
773 TMatrixDSparse *TUnfold::MultiplyMSparseM(
const TMatrixDSparse *a,
774 const TMatrixD *b)
const
776 if(a->GetNcols()!=b->GetNrows()) {
777 Fatal(
"MultiplyMSparseM",
"inconsistent matrix col /matrix row %d!=%d",
778 a->GetNcols(),b->GetNrows());
781 TMatrixDSparse *r=
new TMatrixDSparse(a->GetNrows(),b->GetNcols());
782 const Int_t *a_rows=a->GetRowIndexArray();
783 const Int_t *a_cols=a->GetColIndexArray();
784 const Double_t *a_data=a->GetMatrixArray();
787 for (Int_t irow = 0; irow < a->GetNrows(); irow++) {
788 if(a_rows[irow+1]-a_rows[irow]>0) nMax += b->GetNcols();
791 Int_t *r_rows=
new Int_t[nMax];
792 Int_t *r_cols=
new Int_t[nMax];
793 Double_t *r_data=
new Double_t[nMax];
797 for (Int_t irow = 0; irow < a->GetNrows(); irow++) {
798 if(a_rows[irow+1]-a_rows[irow]<=0)
continue;
799 for(Int_t icol=0;icol<b->GetNcols();icol++) {
803 for(Int_t i=a_rows[irow];i<a_rows[irow+1];i++) {
805 r_data[n] += a_data[i]*(*b)(j,icol);
807 if(r_data[n]!=0.0) n++;
811 r->SetMatrixArray(n,r_rows,r_cols,r_data);
832 TMatrixDSparse *TUnfold::MultiplyMSparseMSparseTranspVector
833 (
const TMatrixDSparse *m1,
const TMatrixDSparse *m2,
834 const TMatrixTBase<Double_t> *v)
const
836 if((m1->GetNcols() != m2->GetNcols())||
837 (v && ((m1->GetNcols()!=v->GetNrows())||(v->GetNcols()!=1)))) {
839 Fatal(
"MultiplyMSparseMSparseTranspVector",
840 "matrix cols/vector rows %d!=%d!=%d or vector rows %d!=1\n",
841 m1->GetNcols(),m2->GetNcols(),v->GetNrows(),v->GetNcols());
843 Fatal(
"MultiplyMSparseMSparseTranspVector",
844 "matrix cols %d!=%d\n",m1->GetNcols(),m2->GetNcols());
847 const Int_t *rows_m1=m1->GetRowIndexArray();
848 const Int_t *cols_m1=m1->GetColIndexArray();
849 const Double_t *data_m1=m1->GetMatrixArray();
851 for(Int_t i=0;i<m1->GetNrows();i++) {
852 if(rows_m1[i]<rows_m1[i+1]) num_m1++;
854 const Int_t *rows_m2=m2->GetRowIndexArray();
855 const Int_t *cols_m2=m2->GetColIndexArray();
856 const Double_t *data_m2=m2->GetMatrixArray();
858 for(Int_t j=0;j<m2->GetNrows();j++) {
859 if(rows_m2[j]<rows_m2[j+1]) num_m2++;
861 const TMatrixDSparse *v_sparse=
dynamic_cast<const TMatrixDSparse *
>(v);
862 const Int_t *v_rows=0;
863 const Double_t *v_data=0;
865 v_rows=v_sparse->GetRowIndexArray();
866 v_data=v_sparse->GetMatrixArray();
868 Int_t num_r=num_m1*num_m2+1;
869 Int_t *row_r=
new Int_t[num_r];
870 Int_t *col_r=
new Int_t[num_r];
871 Double_t *data_r=
new Double_t[num_r];
873 for(Int_t i=0;i<m1->GetNrows();i++) {
874 for(Int_t j=0;j<m2->GetNrows();j++) {
876 Int_t index_m1=rows_m1[i];
877 Int_t index_m2=rows_m2[j];
878 while((index_m1<rows_m1[i+1])&&(index_m2<rows_m2[j+1])) {
879 Int_t k1=cols_m1[index_m1];
880 Int_t k2=cols_m2[index_m2];
887 Int_t v_index=v_rows[k1];
888 if(v_index<v_rows[k1+1]) {
889 data_r[num_r] += data_m1[index_m1] * data_m2[index_m2]
893 data_r[num_r] += data_m1[index_m1] * data_m2[index_m2]
896 data_r[num_r] += data_m1[index_m1] * data_m2[index_m2];
902 if(data_r[num_r] !=0.0) {
909 TMatrixDSparse *r=CreateSparseMatrix(m1->GetNrows(),m2->GetNrows(),
910 num_r,row_r,col_r,data_r);
930 void TUnfold::AddMSparse(TMatrixDSparse *dest,Double_t f,
931 const TMatrixDSparse *src)
const
933 const Int_t *dest_rows=dest->GetRowIndexArray();
934 const Int_t *dest_cols=dest->GetColIndexArray();
935 const Double_t *dest_data=dest->GetMatrixArray();
936 const Int_t *src_rows=src->GetRowIndexArray();
937 const Int_t *src_cols=src->GetColIndexArray();
938 const Double_t *src_data=src->GetMatrixArray();
940 if((dest->GetNrows()!=src->GetNrows())||
941 (dest->GetNcols()!=src->GetNcols())) {
942 Fatal(
"AddMSparse",
"inconsistent matrix rows %d!=%d OR cols %d!=%d",
943 src->GetNrows(),dest->GetNrows(),src->GetNcols(),dest->GetNcols());
945 Int_t nmax=dest->GetNrows()*dest->GetNcols();
946 Double_t *result_data=
new Double_t[nmax];
947 Int_t *result_rows=
new Int_t[nmax];
948 Int_t *result_cols=
new Int_t[nmax];
950 for(Int_t row=0;row<dest->GetNrows();row++) {
951 Int_t i_dest=dest_rows[row];
952 Int_t i_src=src_rows[row];
953 while((i_dest<dest_rows[row+1])||(i_src<src_rows[row+1])) {
954 Int_t col_dest=(i_dest<dest_rows[row+1]) ?
955 dest_cols[i_dest] : dest->GetNcols();
956 Int_t col_src =(i_src <src_rows[row+1] ) ?
957 src_cols [i_src] : src->GetNcols();
959 if(col_dest<col_src) {
960 result_cols[n]=col_dest;
961 result_data[n]=dest_data[i_dest++];
962 }
else if(col_dest>col_src) {
963 result_cols[n]=col_src;
964 result_data[n]=f*src_data[i_src++];
966 result_cols[n]=col_dest;
967 result_data[n]=dest_data[i_dest++]+f*src_data[i_src++];
969 if(result_data[n] !=0.0) {
970 if(!TMath::Finite(result_data[n])) {
971 Fatal(
"AddMSparse",
"Nan detected %d %d %d",
984 dest->SetMatrixArray(n,result_rows,result_cols,result_data);
985 delete[] result_data;
986 delete[] result_rows;
987 delete[] result_cols;
1007 TMatrixDSparse *TUnfold::InvertMSparseSymmPos
1008 (
const TMatrixDSparse *A,Int_t *rankPtr)
const
1011 if(A->GetNcols()!=A->GetNrows()) {
1012 Fatal(
"InvertMSparseSymmPos",
"inconsistent matrix row/col %d!=%d",
1013 A->GetNcols(),A->GetNrows());
1016 Bool_t *isZero=
new Bool_t[A->GetNrows()];
1017 const Int_t *a_rows=A->GetRowIndexArray();
1018 const Int_t *a_cols=A->GetColIndexArray();
1019 const Double_t *a_data=A->GetMatrixArray();
1024 Int_t iBlock=A->GetNrows();
1025 Bool_t isDiagonal=kTRUE;
1026 TVectorD aII(A->GetNrows());
1028 for(Int_t iA=0;iA<A->GetNrows();iA++) {
1029 for(Int_t indexA=a_rows[iA];indexA<a_rows[iA+1];indexA++) {
1030 Int_t jA=a_cols[indexA];
1032 if(!(a_data[indexA]>=0.0)) nError++;
1033 aII(iA)=a_data[indexA];
1038 Fatal(
"InvertMSparseSymmPos",
1039 "Matrix has %d negative elements on the diagonal", nError);
1053 Int_t *swap=
new Int_t[A->GetNrows()];
1054 for(Int_t j=0;j<A->GetNrows();j++) swap[j]=j;
1055 for(Int_t iStart=0;iStart<iBlock;iStart++) {
1057 for(Int_t i=iStart;i<iBlock;i++) {
1059 Int_t n=A->GetNrows()-(a_rows[iA+1]-a_rows[iA]);
1061 Int_t tmp=swap[iStart];
1062 swap[iStart]=swap[i];
1067 for(Int_t i=0;i<A->GetNrows();i++) isZero[i]=kTRUE;
1068 Int_t iA=swap[iStart];
1069 for(Int_t indexA=a_rows[iA];indexA<a_rows[iA+1];indexA++) {
1070 Int_t jA=a_cols[indexA];
1079 for(Int_t i=iStart+1;i<iBlock;) {
1080 if(isZero[swap[i]]) {
1084 Int_t tmp=swap[iBlock];
1085 swap[iBlock]=swap[i];
1097 #ifdef CONDITION_BLOCK_PART
1098 Int_t nn=A->GetNrows()-iBlock;
1099 for(
int inc=(nn+1)/2;inc;inc /= 2) {
1100 for(
int i=inc;i<nn;i++) {
1101 int itmp=swap[i+iBlock];
1103 for(j=i;(j>=inc)&&(aII(swap[j-inc+iBlock])<aII(itmp));j -=inc) {
1104 swap[j+iBlock]=swap[j-inc+iBlock];
1106 swap[j+iBlock]=itmp;
1111 Int_t *swapBack=
new Int_t[A->GetNrows()];
1112 for(Int_t i=0;i<A->GetNrows();i++) {
1113 swapBack[swap[i]]=i;
1116 for(Int_t i=0;i<A->GetNrows();i++) {
1117 std::cout<<
" "<<i<<
" "<<swap[i]<<
" "<<swapBack[i]<<
"\n";
1119 std::cout<<
"after sorting\n";
1120 for(Int_t i=0;i<A->GetNrows();i++) {
1121 if(i==iDiagonal) std::cout<<
"iDiagonal="<<i<<
"\n";
1122 if(i==iBlock) std::cout<<
"iBlock="<<i<<
"\n";
1123 std::cout<<
" "<<swap[i]<<
" "<<aII(swap[i])<<
"\n";
1135 for(Int_t i=0;i<A->GetNrows();i++) {
1137 for(Int_t indexA=a_rows[row];indexA<a_rows[row+1];indexA++) {
1138 Int_t j=swapBack[a_cols[indexA]];
1140 else if((i<iDiagonal)||(j<iDiagonal)) nError1++;
1141 else if((i<iBlock)&&(j<iBlock)) nError2++;
1142 else if((i<iBlock)||(j<iBlock)) nBlock++;
1146 if(nError1+nError2>0) {
1147 Fatal(
"InvertMSparseSymmPos",
"sparse matrix analysis failed %d %d %d %d %d",
1148 iDiagonal,iBlock,A->GetNrows(),nError1,nError2);
1153 Info(
"InvertMSparseSymmPos",
"iDiagonal=%d iBlock=%d nRow=%d",
1154 iDiagonal,iBlock,A->GetNrows());
1205 Double_t *rEl_data=
new Double_t[A->GetNrows()*A->GetNrows()];
1206 Int_t *rEl_col=
new Int_t[A->GetNrows()*A->GetNrows()];
1207 Int_t *rEl_row=
new Int_t[A->GetNrows()*A->GetNrows()];
1213 for(Int_t i=0;i<iDiagonal;++i) {
1218 rEl_data[rNumEl]=1./aII(iA);
1223 if((!rankPtr)&&(rankD1!=iDiagonal)) {
1224 Fatal(
"InvertMSparseSymmPos",
1225 "diagonal part 1 has rank %d != %d, matrix can not be inverted",
1233 Int_t nD2=iBlock-iDiagonal;
1234 TMatrixDSparse *D2inv=0;
1235 if((rNumEl>=0)&&(nD2>0)) {
1236 Double_t *D2inv_data=
new Double_t[nD2];
1237 Int_t *D2inv_col=
new Int_t[nD2];
1238 Int_t *D2inv_row=
new Int_t[nD2];
1240 for(Int_t i=0;i<nD2;++i) {
1241 Int_t iA=swap[i+iDiagonal];
1243 D2inv_col[D2invNumEl]=i;
1244 D2inv_row[D2invNumEl]=i;
1245 D2inv_data[D2invNumEl]=1./aII(iA);
1249 if(D2invNumEl==nD2) {
1250 D2inv=CreateSparseMatrix(nD2,nD2,D2invNumEl,D2inv_row,D2inv_col,
1252 }
else if(!rankPtr) {
1253 Fatal(
"InvertMSparseSymmPos",
1254 "diagonal part 2 has rank %d != %d, matrix can not be inverted",
1258 delete [] D2inv_data;
1259 delete [] D2inv_col;
1260 delete [] D2inv_row;
1266 Int_t nF=A->GetNrows()-iBlock;
1267 TMatrixDSparse *Finv=0;
1268 TMatrixDSparse *B=0;
1269 TMatrixDSparse *minusBD2inv=0;
1270 if((rNumEl>=0)&&(nF>0)&&((nD2==0)||D2inv)) {
1273 Double_t epsilonF2=fEpsMatrix;
1274 Double_t *F_data=
new Double_t[nFmax];
1275 Int_t *F_col=
new Int_t[nFmax];
1276 Int_t *F_row=
new Int_t[nFmax];
1279 Int_t nBmax=nF*(nD2+1);
1280 Double_t *B_data=
new Double_t[nBmax];
1281 Int_t *B_col=
new Int_t[nBmax];
1282 Int_t *B_row=
new Int_t[nBmax];
1285 for(Int_t i=0;i<nF;i++) {
1286 Int_t iA=swap[i+iBlock];
1287 for(Int_t indexA=a_rows[iA];indexA<a_rows[iA+1];indexA++) {
1288 Int_t jA=a_cols[indexA];
1289 Int_t j0=swapBack[jA];
1294 F_data[FnumEl]=a_data[indexA];
1296 }
else if(j0>=iDiagonal) {
1297 Int_t j=j0-iDiagonal;
1300 B_data[BnumEl]=a_data[indexA];
1305 TMatrixDSparse *F=0;
1307 #ifndef FORCE_EIGENVALUE_DECOMPOSITION
1308 F=CreateSparseMatrix(nF,nF,FnumEl,F_row,F_col,F_data);
1315 B=CreateSparseMatrix(nF,nD2,BnumEl,B_row,B_col,B_data);
1322 minusBD2inv=MultiplyMSparseMSparse(B,D2inv);
1324 Int_t mbd2_nMax=minusBD2inv->GetRowIndexArray()
1325 [minusBD2inv->GetNrows()];
1326 Double_t *mbd2_data=minusBD2inv->GetMatrixArray();
1327 for(Int_t i=0;i<mbd2_nMax;i++) {
1328 mbd2_data[i] = - mbd2_data[i];
1332 if(minusBD2inv && F) {
1333 TMatrixDSparse *minusBD2invBt=
1334 MultiplyMSparseMSparseTranspVector(minusBD2inv,B,0);
1335 AddMSparse(F,1.,minusBD2invBt);
1336 DeleteMatrix(&minusBD2invBt);
1341 const Int_t *f_rows=F->GetRowIndexArray();
1342 const Int_t *f_cols=F->GetColIndexArray();
1343 const Double_t *f_data=F->GetMatrixArray();
1347 for(Int_t i=0;i<nF;i++) {
1348 for(Int_t indexF=f_rows[i];indexF<f_rows[i+1];indexF++) {
1349 if(f_cols[indexF]>=i) c(f_cols[indexF],i)=f_data[indexF];
1352 Double_t c_ii=c(i,i);
1353 for(Int_t j=0;j<i;j++) {
1354 Double_t c_ij=c(i,j);
1361 c_ii=TMath::Sqrt(c_ii);
1364 for(Int_t j=i+1;j<nF;j++) {
1365 Double_t c_ji=c(j,i);
1366 for(Int_t k=0;k<i;k++) {
1367 c_ji -= c(i,k)*c(j,k);
1374 Double_t dmin=c(0,0);
1376 for(Int_t i=1;i<nF;i++) {
1377 dmin=TMath::Min(dmin,c(i,i));
1378 dmax=TMath::Max(dmax,c(i,i));
1381 std::cout<<
"dmin,dmax: "<<dmin<<
" "<<dmax<<
"\n";
1383 if(dmin/dmax<epsilonF2*nF) nErrorF=2;
1388 TMatrixD cinv(nF,nF);
1389 for(Int_t i=0;i<nF;i++) {
1390 cinv(i,i)=1./c(i,i);
1392 for(Int_t i=0;i<nF;i++) {
1393 for(Int_t j=i+1;j<nF;j++) {
1394 Double_t tmp=-c(j,i)*cinv(i,i);
1395 for(Int_t k=i+1;k<j;k++) {
1396 tmp -= cinv(k,i)*c(j,k);
1398 cinv(j,i)=tmp*cinv(j,j);
1401 TMatrixDSparse cInvSparse(cinv);
1402 Finv=MultiplyMSparseTranspMSparse
1403 (&cInvSparse,&cInvSparse);
1414 Int_t rankD2Block=0;
1416 if( ((nD2==0)||D2inv) && ((nF==0)||Finv) ) {
1425 TMatrixDSparse *G=0;
1426 if(Finv && minusBD2inv) {
1427 G=MultiplyMSparseMSparse(Finv,minusBD2inv);
1429 TMatrixDSparse *E=0;
1430 if(D2inv) E=
new TMatrixDSparse(*D2inv);
1431 if(G && minusBD2inv) {
1432 TMatrixDSparse *minusBD2invTransG=
1433 MultiplyMSparseTranspMSparse(minusBD2inv,G);
1435 AddMSparse(E,1.,minusBD2invTransG);
1436 DeleteMatrix(&minusBD2invTransG);
1438 E=minusBD2invTransG;
1443 const Int_t *e_rows=E->GetRowIndexArray();
1444 const Int_t *e_cols=E->GetColIndexArray();
1445 const Double_t *e_data=E->GetMatrixArray();
1446 for(Int_t iE=0;iE<E->GetNrows();iE++) {
1447 Int_t iA=swap[iE+iDiagonal];
1448 for(Int_t indexE=e_rows[iE];indexE<e_rows[iE+1];++indexE) {
1449 Int_t jE=e_cols[indexE];
1450 Int_t jA=swap[jE+iDiagonal];
1453 rEl_data[rNumEl]=e_data[indexE];
1461 const Int_t *g_rows=G->GetRowIndexArray();
1462 const Int_t *g_cols=G->GetColIndexArray();
1463 const Double_t *g_data=G->GetMatrixArray();
1464 for(Int_t iG=0;iG<G->GetNrows();iG++) {
1465 Int_t iA=swap[iG+iBlock];
1466 for(Int_t indexG=g_rows[iG];indexG<g_rows[iG+1];++indexG) {
1467 Int_t jG=g_cols[indexG];
1468 Int_t jA=swap[jG+iDiagonal];
1472 rEl_data[rNumEl]=g_data[indexG];
1477 rEl_data[rNumEl]=g_data[indexG];
1485 const Int_t *finv_rows=Finv->GetRowIndexArray();
1486 const Int_t *finv_cols=Finv->GetColIndexArray();
1487 const Double_t *finv_data=Finv->GetMatrixArray();
1488 for(Int_t iF=0;iF<Finv->GetNrows();iF++) {
1489 Int_t iA=swap[iF+iBlock];
1490 for(Int_t indexF=finv_rows[iF];indexF<finv_rows[iF+1];++indexF) {
1491 Int_t jF=finv_cols[indexF];
1492 Int_t jA=swap[jF+iBlock];
1495 rEl_data[rNumEl]=finv_data[indexF];
1501 }
else if(!rankPtr) {
1503 Fatal(
"InvertMSparseSymmPos",
1504 "non-trivial part has rank < %d, matrix can not be inverted",
1510 Double_t epsilonEV2=fEpsMatrix ;
1511 Info(
"InvertMSparseSymmPos",
1512 "cholesky-decomposition failed, try eigenvalue analysis");
1514 std::cout<<
"nEV="<<nEV<<
" iDiagonal="<<iDiagonal<<
"\n";
1516 TMatrixDSym EV(nEV);
1517 for(Int_t i=0;i<nEV;i++) {
1518 Int_t iA=swap[i+iDiagonal];
1519 for(Int_t indexA=a_rows[iA];indexA<a_rows[iA+1];indexA++) {
1520 Int_t jA=a_cols[indexA];
1521 Int_t j0=swapBack[jA];
1523 Int_t j=j0-iDiagonal;
1525 if((i<0)||(j<0)||(i>=nEV)||(j>=nEV)) {
1526 std::cout<<
" error "<<nEV<<
" "<<i<<
" "<<j<<
"\n";
1529 if(!TMath::Finite(a_data[indexA])) {
1530 Fatal(
"InvertMSparseSymmPos",
1531 "non-finite number detected element %d %d\n",
1534 EV(i,j)=a_data[indexA];
1539 TMatrixDSymEigen Eigen(EV);
1541 std::cout<<
"Eigenvalues\n";
1545 Double_t condition=1.0;
1546 if(Eigen.GetEigenValues()(0)<0.0) {
1548 }
else if(Eigen.GetEigenValues()(0)>0.0) {
1549 condition=Eigen.GetEigenValues()(nEV-1)/Eigen.GetEigenValues()(0);
1551 if(condition<-epsilonEV2) {
1556 Error(
"InvertMSparseSymmPos",
1557 "Largest Eigenvalue is negative %f",
1558 Eigen.GetEigenValues()(0));
1560 Error(
"InvertMSparseSymmPos",
1561 "Some Eigenvalues are negative (EV%d/EV0=%g epsilon=%g)",
1563 Eigen.GetEigenValues()(nEV-1)/Eigen.GetEigenValues()(0),
1569 Double_t setToZero=epsilonEV2*Eigen.GetEigenValues()(0);
1570 TMatrixD inverseEV(nEV,1);
1571 for(Int_t i=0;i<nEV;i++) {
1572 Double_t x=Eigen.GetEigenValues()(i);
1574 inverseEV(i,0)=1./x;
1578 TMatrixDSparse V(Eigen.GetEigenVectors());
1579 TMatrixDSparse *VDVt=MultiplyMSparseMSparseTranspVector
1583 const Int_t *vdvt_rows=VDVt->GetRowIndexArray();
1584 const Int_t *vdvt_cols=VDVt->GetColIndexArray();
1585 const Double_t *vdvt_data=VDVt->GetMatrixArray();
1586 for(Int_t iVDVt=0;iVDVt<VDVt->GetNrows();iVDVt++) {
1587 Int_t iA=swap[iVDVt+iDiagonal];
1588 for(Int_t indexVDVt=vdvt_rows[iVDVt];
1589 indexVDVt<vdvt_rows[iVDVt+1];++indexVDVt) {
1590 Int_t jVDVt=vdvt_cols[indexVDVt];
1591 Int_t jA=swap[jVDVt+iDiagonal];
1594 rEl_data[rNumEl]=vdvt_data[indexVDVt];
1598 DeleteMatrix(&VDVt);
1602 *rankPtr=rankD1+rankD2Block;
1606 DeleteMatrix(&D2inv);
1607 DeleteMatrix(&Finv);
1609 DeleteMatrix(&minusBD2inv);
1615 TMatrixDSparse *r=(rNumEl>=0) ?
1616 CreateSparseMatrix(A->GetNrows(),A->GetNrows(),rNumEl,
1617 rEl_row,rEl_col,rEl_data) : 0;
1625 TMatrixDSparse *Ar=MultiplyMSparseMSparse(A,r);
1626 TMatrixDSparse *ArA=MultiplyMSparseMSparse(Ar,A);
1627 TMatrixDSparse *rAr=MultiplyMSparseMSparse(r,Ar);
1639 Double_t epsilonA2=fEpsMatrix ;
1640 for(Int_t i=0;i<a.GetNrows();i++) {
1641 for(Int_t j=0;j<a.GetNcols();j++) {
1643 if(TMath::Abs(ar(i,j)-ar(j,i))>
1644 epsilonA2*(TMath::Abs(ar(i,j))+TMath::Abs(ar(j,i)))) {
1645 std::cout<<
"Ar is not symmetric Ar("<<i<<
","<<j<<
")="<<ar(i,j)
1646 <<
" Ar("<<j<<
","<<i<<
")="<<ar(j,i)<<
"\n";
1649 if(TMath::Abs(ara(i,j)-a(i,j))>
1650 epsilonA2*(TMath::Abs(ara(i,j))+TMath::Abs(a(i,j)))) {
1651 std::cout<<
"ArA is not equal A ArA("<<i<<
","<<j<<
")="<<ara(i,j)
1652 <<
" A("<<i<<
","<<j<<
")="<<a(i,j)<<
"\n";
1655 if(TMath::Abs(rar(i,j)-R(i,j))>
1656 epsilonA2*(TMath::Abs(rar(i,j))+TMath::Abs(R(i,j)))) {
1657 std::cout<<
"rAr is not equal r rAr("<<i<<
","<<j<<
")="<<rar(i,j)
1658 <<
" r("<<i<<
","<<j<<
")="<<R(i,j)<<
"\n";
1662 if(rankPtr) std::cout<<
"rank="<<*rankPtr<<
"\n";
1664 std::cout<<
"Matrix is not positive\n";
1684 TString TUnfold::GetOutputBinName(Int_t iBinX)
const
1686 return TString::Format(
"#%d",iBinX);
1715 TUnfold::TUnfold(
const TH2 *hist_A, EHistMap histmap, ERegMode regmode,
1716 EConstraint constraint)
1724 SetConstraint(constraint);
1726 if (histmap == kHistMapOutputHoriz) {
1728 nx0 = hist_A->GetNbinsX()+2;
1729 ny = hist_A->GetNbinsY();
1732 nx0 = hist_A->GetNbinsY()+2;
1733 ny = hist_A->GetNbinsX();
1754 for (Int_t ix = 0; ix < nx0; ix++) {
1759 for (Int_t iy = 0; iy < ny; iy++) {
1761 if (histmap == kHistMapOutputHoriz) {
1762 z = hist_A->GetBinContent(ix, iy + 1);
1764 z = hist_A->GetBinContent(iy + 1, ix);
1780 fSumOverY[nx] = sum;
1781 if (histmap == kHistMapOutputHoriz) {
1783 hist_A->GetBinContent(ix, 0) +
1784 hist_A->GetBinContent(ix, ny + 1);
1787 hist_A->GetBinContent(0, ix) +
1788 hist_A->GetBinContent(ny + 1, ix);
1797 Int_t underflowBin=0,overflowBin=0;
1798 for (Int_t ix = 0; ix < nx; ix++) {
1799 Int_t ibinx = fXToHist[ix];
1800 if(ibinx<1) underflowBin=1;
1801 if (histmap == kHistMapOutputHoriz) {
1802 if(ibinx>hist_A->GetNbinsX()) overflowBin=1;
1804 if(ibinx>hist_A->GetNbinsY()) overflowBin=1;
1809 Int_t ixfirst=-1,ixlast=-1;
1811 int nDisconnected=0;
1812 for (Int_t ix = 0; ix < nx0; ix++) {
1813 if(fHistToX[ix]<0) {
1823 if(((fHistToX[ix]>=0)&&(ixlast>=0))||
1824 (nprint==nskipped)) {
1825 if(ixlast>ixfirst) {
1832 if(nprint==nskipped) {
1836 if(nskipped==(2-underflowBin-overflowBin)) {
1837 Info(
"TUnfold",
"underflow and overflow bin "
1838 "do not depend on the input data");
1840 Warning(
"TUnfold",
"%d output bins "
1841 "do not depend on the input data %s",nDisconnected,
1842 static_cast<const char *>(binlist));
1846 fX0 =
new TMatrixD(nx, 1, fSumOverY.GetArray());
1849 Int_t *rowA =
new Int_t[nonzeroA];
1850 Int_t *colA =
new Int_t[nonzeroA];
1851 Double_t *dataA =
new Double_t[nonzeroA];
1853 for (Int_t iy = 0; iy < ny; iy++) {
1854 for (Int_t ix = 0; ix < nx; ix++) {
1855 Int_t ibinx = fXToHist[ix];
1857 if (histmap == kHistMapOutputHoriz) {
1858 z = hist_A->GetBinContent(ibinx, iy + 1);
1860 z = hist_A->GetBinContent(iy + 1, ibinx);
1865 dataA[index] = z / fSumOverY[ix];
1870 if(underflowBin && overflowBin) {
1871 Info(
"TUnfold",
"%d input bins and %d output bins (includes 2 underflow/overflow bins)",ny,nx);
1872 }
else if(underflowBin) {
1873 Info(
"TUnfold",
"%d input bins and %d output bins (includes 1 underflow bin)",ny,nx);
1874 }
else if(overflowBin) {
1875 Info(
"TUnfold",
"%d input bins and %d output bins (includes 1 overflow bin)",ny,nx);
1877 Info(
"TUnfold",
"%d input bins and %d output bins",ny,nx);
1879 fA = CreateSparseMatrix(ny,nx,index,rowA,colA,dataA);
1881 Error(
"TUnfold",
"too few (ny=%d) input bins for nx=%d output bins",ny,nx);
1883 Warning(
"TUnfold",
"too few (ny=%d) input bins for nx=%d output bins",ny,nx);
1889 fL =
new TMatrixDSparse(1, GetNx());
1890 if (regmode != kRegModeNone) {
1891 Int_t nError=RegularizeBins(0, 1, nx0, regmode);
1895 "%d regularisation conditions have been skipped",nError);
1898 "One regularisation condition has been skipped");
1912 void TUnfold::SetBias(
const TH1 *bias)
1915 fX0 =
new TMatrixD(GetNx(), 1);
1916 for (Int_t i = 0; i < GetNx(); i++) {
1917 (*fX0) (i, 0) = bias->GetBinContent(fXToHist[i]);
1935 Bool_t TUnfold::AddRegularisationCondition
1936 (Int_t i0,Double_t f0,Int_t i1,Double_t f1,Int_t i2,Double_t f2)
1957 return AddRegularisationCondition(nEle,indices,data);
1973 Bool_t TUnfold::AddRegularisationCondition
1974 (Int_t nEle,
const Int_t *indices,
const Double_t *rowData)
1977 const Int_t *l0_rows=fL->GetRowIndexArray();
1978 const Int_t *l0_cols=fL->GetColIndexArray();
1979 const Double_t *l0_data=fL->GetMatrixArray();
1981 Int_t nF=l0_rows[fL->GetNrows()]+nEle;
1982 Int_t *l_row=
new Int_t[nF];
1983 Int_t *l_col=
new Int_t[nF];
1984 Double_t *l_data=
new Double_t[nF];
1987 for(Int_t row=0;row<fL->GetNrows();row++) {
1988 for(Int_t k=l0_rows[row];k<l0_rows[row+1];k++) {
1990 l_col[nF]=l0_cols[k];
1991 l_data[nF]=l0_data[k];
1999 rowMax=fL->GetNrows();
2003 for(Int_t i=0;i<nEle;i++) {
2004 Int_t col=fHistToX[indices[i]];
2011 l_data[nF]=rowData[i];
2018 fL=CreateSparseMatrix(rowMax+1,GetNx(),nF,l_row,l_col,l_data);
2044 Int_t TUnfold::RegularizeSize(
int bin, Double_t scale)
2052 if(fRegMode==kRegModeNone) fRegMode=kRegModeSize;
2053 if(fRegMode!=kRegModeSize) fRegMode=kRegModeMixed;
2055 return AddRegularisationCondition(bin,scale) ? 0 : 1;
2078 Int_t TUnfold::RegularizeDerivative(
int left_bin,
int right_bin,
2088 if(fRegMode==kRegModeNone) fRegMode=kRegModeDerivative;
2089 if(fRegMode!=kRegModeDerivative) fRegMode=kRegModeMixed;
2091 return AddRegularisationCondition(left_bin,-scale,right_bin,scale) ? 0 : 1;
2117 Int_t TUnfold::RegularizeCurvature(
int left_bin,
int center_bin,
2119 Double_t scale_left,
2120 Double_t scale_right)
2131 if(fRegMode==kRegModeNone) fRegMode=kRegModeCurvature;
2132 if(fRegMode!=kRegModeCurvature) fRegMode=kRegModeMixed;
2134 return AddRegularisationCondition
2135 (left_bin,-scale_left,
2136 center_bin,scale_left+scale_right,
2137 right_bin,-scale_right)
2161 Int_t TUnfold::RegularizeBins(
int start,
int step,
int nbin,
2179 if (regmode == kRegModeDerivative) {
2181 }
else if (regmode == kRegModeCurvature) {
2183 }
else if(regmode != kRegModeSize) {
2184 Error(
"RegularizeBins",
"regmode = %d is not valid",regmode);
2186 for (Int_t i = nSkip; i < nbin; i++) {
2187 if (regmode == kRegModeSize) {
2188 nError += RegularizeSize(i0);
2189 }
else if (regmode == kRegModeDerivative) {
2190 nError += RegularizeDerivative(i0, i1);
2191 }
else if (regmode == kRegModeCurvature) {
2192 nError += RegularizeCurvature(i0, i1, i2);
2222 Int_t TUnfold::RegularizeBins2D(
int start_bin,
int step1,
int nbin1,
2223 int step2,
int nbin2, ERegMode regmode)
2236 for (Int_t i1 = 0; i1 < nbin1; i1++) {
2237 nError += RegularizeBins(start_bin + step1 * i1, step2, nbin2, regmode);
2239 for (Int_t i2 = 0; i2 < nbin2; i2++) {
2240 nError += RegularizeBins(start_bin + step2 * i2, step1, nbin1, regmode);
2265 Double_t TUnfold::DoUnfold(Double_t tau_reg,
const TH1 *input,
2269 SetInput(input,scaleBias);
2270 return DoUnfold(tau_reg);
2300 Int_t TUnfold::SetInput(
const TH1 *input, Double_t scaleBias,
2301 Double_t oneOverZeroError,
const TH2 *hist_vyy,
2302 const TH2 *hist_vyy_inv)
2304 DeleteMatrix(&fVyyInv);
2307 fBiasScale = scaleBias;
2315 Int_t *rowVyyN=
new Int_t[GetNy()*GetNy()+1];
2316 Int_t *colVyyN=
new Int_t[GetNy()*GetNy()+1];
2317 Double_t *dataVyyN=
new Double_t[GetNy()*GetNy()+1];
2319 Int_t *rowVyy1=
new Int_t[GetNy()];
2320 Int_t *colVyy1=
new Int_t[GetNy()];
2321 Double_t *dataVyy1=
new Double_t[GetNy()];
2322 Double_t *dataVyyDiag=
new Double_t[GetNy()];
2324 Int_t nVarianceZero=0;
2325 Int_t nVarianceForced=0;
2328 for (Int_t iy = 0; iy < GetNy(); iy++) {
2332 Double_t dy = input->GetBinError(iy + 1);
2335 if(oneOverZeroError>0.0) {
2336 dy2 = 1./ ( oneOverZeroError*oneOverZeroError);
2343 dy2 = hist_vyy->GetBinContent(iy+1,iy+1);
2348 rowVyyN[nVyyN] = iy;
2349 colVyyN[nVyyN] = iy;
2350 rowVyy1[nVyy1] = iy;
2352 dataVyyDiag[iy] = dy2;
2354 dataVyyN[nVyyN++] = dy2;
2355 dataVyy1[nVyy1++] = dy2;
2360 Int_t nOffDiagNonzero=0;
2361 for (Int_t iy = 0; iy < GetNy(); iy++) {
2363 if(dataVyyDiag[iy]<=0.0) {
2364 for (Int_t jy = 0; jy < GetNy(); jy++) {
2365 if(hist_vyy->GetBinContent(iy+1,jy+1)!=0.0) {
2371 for (Int_t jy = 0; jy < GetNy(); jy++) {
2373 if(iy==jy)
continue;
2375 if(dataVyyDiag[jy]<=0.0)
continue;
2377 rowVyyN[nVyyN] = iy;
2378 colVyyN[nVyyN] = jy;
2379 dataVyyN[nVyyN]= hist_vyy->GetBinContent(iy+1,jy+1);
2380 if(dataVyyN[nVyyN] == 0.0)
continue;
2386 "inverse of input covariance is taken from user input");
2387 Int_t *rowVyyInv=
new Int_t[GetNy()*GetNy()+1];
2388 Int_t *colVyyInv=
new Int_t[GetNy()*GetNy()+1];
2389 Double_t *dataVyyInv=
new Double_t[GetNy()*GetNy()+1];
2391 for (Int_t iy = 0; iy < GetNy(); iy++) {
2392 for (Int_t jy = 0; jy < GetNy(); jy++) {
2393 rowVyyInv[nVyyInv] = iy;
2394 colVyyInv[nVyyInv] = jy;
2395 dataVyyInv[nVyyInv]= hist_vyy_inv->GetBinContent(iy+1,jy+1);
2396 if(dataVyyInv[nVyyInv] == 0.0)
continue;
2400 fVyyInv=CreateSparseMatrix
2401 (GetNy(),GetNy(),nVyyInv,rowVyyInv,colVyyInv,dataVyyInv);
2402 delete [] rowVyyInv;
2403 delete [] colVyyInv;
2404 delete [] dataVyyInv;
2406 if(nOffDiagNonzero) {
2408 "input covariance has elements C(X,Y)!=0 where V(X)==0");
2412 DeleteMatrix(&fVyy);
2413 fVyy = CreateSparseMatrix
2414 (GetNy(),GetNy(),nVyyN,rowVyyN,colVyyN,dataVyyN);
2420 TMatrixDSparse *vecV=CreateSparseMatrix
2421 (GetNy(),1,nVyy1,rowVyy1,colVyy1, dataVyy1);
2430 fY =
new TMatrixD(GetNy(), 1);
2431 for (Int_t i = 0; i < GetNy(); i++) {
2432 (*fY) (i, 0) = input->GetBinContent(i + 1);
2435 TMatrixDSparse *mAtV=MultiplyMSparseTranspMSparse(fA,vecV);
2436 DeleteMatrix(&vecV);
2438 for (Int_t i = 0; i <mAtV->GetNrows();i++) {
2439 if(mAtV->GetRowIndexArray()[i]==
2440 mAtV->GetRowIndexArray()[i+1]) {
2444 if(nVarianceForced) {
2445 if(nVarianceForced>1) {
2446 Warning(
"SetInput",
"%d/%d input bins have zero error,"
2447 " 1/error set to %lf.",
2448 nVarianceForced,GetNy(),oneOverZeroError);
2450 Warning(
"SetInput",
"One input bin has zero error,"
2451 " 1/error set to %lf.",oneOverZeroError);
2455 if(nVarianceZero>1) {
2456 Warning(
"SetInput",
"%d/%d input bins have zero error,"
2457 " and are ignored.",nVarianceZero,GetNy());
2459 Warning(
"SetInput",
"One input bin has zero error,"
2460 " and is ignored.");
2462 fIgnoredBins=nVarianceZero;
2466 if(oneOverZeroError<=0.0) {
2469 for (Int_t col = 0; col <mAtV->GetNrows();col++) {
2470 if(mAtV->GetRowIndexArray()[col]==
2471 mAtV->GetRowIndexArray()[col+1]) {
2472 TString binlist(
"no data to constrain output bin ");
2473 binlist += GetOutputBinName(fXToHist[col]);
2483 Warning(
"SetInput",
"%s",(
char const *)binlist);
2488 Error(
"SetInput",
"%d/%d output bins are not constrained by any data.",
2489 nError2,mAtV->GetNrows());
2491 Error(
"SetInput",
"One output bins is not constrained by any data.");
2494 DeleteMatrix(&mAtV);
2496 delete[] dataVyyDiag;
2498 return nVarianceForced+nVarianceZero+10000*nError2;
2517 Double_t TUnfold::DoUnfold(Double_t tau)
2519 fTauSquared=tau*tau;
2548 Int_t TUnfold::ScanLcurve(Int_t nPoint,
2549 Double_t tauMin,Double_t tauMax,
2550 TGraph **lCurve,TSpline **logTauX,
2551 TSpline **logTauY,TSpline **logTauCurvature)
2553 typedef std::map<Double_t,std::pair<Double_t,Double_t> > XYtau_t;
2578 if((tauMin<=0)||(tauMax<=0.0)||(tauMin>=tauMax)) {
2588 Error(
"ScanLcurve",
"too few input bins, NDF<=0 %d",GetNdf());
2591 Double_t x0=GetLcurveX();
2592 Double_t y0=GetLcurveY();
2593 Info(
"ScanLcurve",
"logtau=-Infinity X=%lf Y=%lf",x0,y0);
2594 if(!TMath::Finite(x0)) {
2595 Fatal(
"ScanLcurve",
"problem (too few input bins?) X=%f",x0);
2597 if(!TMath::Finite(y0)) {
2598 Fatal(
"ScanLcurve",
"problem (missing regularisation?) Y=%f",y0);
2603 0.5*(TMath::Log10(fChi2A+3.*TMath::Sqrt(GetNdf()+1.0))
2605 DoUnfold(TMath::Power(10.,logTau));
2606 if((!TMath::Finite(GetLcurveX())) ||(!TMath::Finite(GetLcurveY()))) {
2607 Fatal(
"ScanLcurve",
"problem (missing regularisation?) X=%f Y=%f",
2608 GetLcurveX(),GetLcurveY());
2610 curve[logTau]=std::make_pair(GetLcurveX(),GetLcurveY());
2611 Info(
"ScanLcurve",
"logtau=%lf X=%lf Y=%lf",
2612 logTau,GetLcurveX(),GetLcurveY());
2614 if((*curve.begin()).second.first<x0) {
2623 Double_t logTau=(*curve.begin()).first-0.5;
2624 DoUnfold(TMath::Power(10.,logTau));
2625 if((!TMath::Finite(GetLcurveX())) ||(!TMath::Finite(GetLcurveY()))) {
2626 Fatal(
"ScanLcurve",
"problem (missing regularisation?) X=%f Y=%f",
2627 GetLcurveX(),GetLcurveY());
2629 curve[logTau]=std::make_pair(GetLcurveX(),GetLcurveY());
2630 Info(
"ScanLcurve",
"logtau=%lf X=%lf Y=%lf",
2631 logTau,GetLcurveX(),GetLcurveY());
2633 while(((
int)curve.size()<(nPoint-1)/2)&&
2634 ((*curve.begin()).second.first<x0));
2641 while(((
int)curve.size()<nPoint-1)&&
2642 (((*curve.begin()).second.first-x0>0.00432)||
2643 ((*curve.begin()).second.second-y0>0.00432)||
2644 (curve.size()<2))) {
2645 Double_t logTau=(*curve.begin()).first-0.5;
2646 DoUnfold(TMath::Power(10.,logTau));
2647 if((!TMath::Finite(GetLcurveX())) ||(!TMath::Finite(GetLcurveY()))) {
2648 Fatal(
"ScanLcurve",
"problem (missing regularisation?) X=%f Y=%f",
2649 GetLcurveX(),GetLcurveY());
2651 curve[logTau]=std::make_pair(GetLcurveX(),GetLcurveY());
2652 Info(
"ScanLcurve",
"logtau=%lf X=%lf Y=%lf",
2653 logTau,GetLcurveX(),GetLcurveY());
2657 Double_t logTauMin=TMath::Log10(tauMin);
2658 Double_t logTauMax=TMath::Log10(tauMax);
2661 DoUnfold(TMath::Power(10.,logTauMax));
2662 if((!TMath::Finite(GetLcurveX())) ||(!TMath::Finite(GetLcurveY()))) {
2663 Fatal(
"ScanLcurve",
"problem (missing regularisation?) X=%f Y=%f",
2664 GetLcurveX(),GetLcurveY());
2666 Info(
"ScanLcurve",
"logtau=%lf X=%lf Y=%lf",
2667 logTauMax,GetLcurveX(),GetLcurveY());
2668 curve[logTauMax]=std::make_pair(GetLcurveX(),GetLcurveY());
2671 DoUnfold(TMath::Power(10.,logTauMin));
2672 if((!TMath::Finite(GetLcurveX())) ||(!TMath::Finite(GetLcurveY()))) {
2673 Fatal(
"ScanLcurve",
"problem (missing regularisation?) X=%f Y=%f",
2674 GetLcurveX(),GetLcurveY());
2676 Info(
"ScanLcurve",
"logtau=%lf X=%lf Y=%lf",
2677 logTauMin,GetLcurveX(),GetLcurveY());
2678 curve[logTauMin]=std::make_pair(GetLcurveX(),GetLcurveY());
2686 while(
int(curve.size())<nPoint-1) {
2689 XYtau_t::const_iterator i0,i1;
2692 Double_t logTau=(*i0).first;
2693 Double_t distMax=0.0;
2694 for (++i1; i1 != curve.end(); ++i1) {
2695 const std::pair<Double_t, Double_t> &xy0 = (*i0).second;
2696 const std::pair<Double_t, Double_t> &xy1 = (*i1).second;
2697 Double_t dx = xy1.first - xy0.first;
2698 Double_t dy = xy1.second - xy0.second;
2699 Double_t d = TMath::Sqrt(dx * dx + dy * dy);
2702 logTau = 0.5 * ((*i0).first + (*i1).first);
2706 DoUnfold(TMath::Power(10.,logTau));
2707 if((!TMath::Finite(GetLcurveX())) ||(!TMath::Finite(GetLcurveY()))) {
2708 Fatal(
"ScanLcurve",
"problem (missing regularisation?) X=%f Y=%f",
2709 GetLcurveX(),GetLcurveY());
2711 Info(
"ScanLcurve",
"logtau=%lf X=%lf Y=%lf",logTau,GetLcurveX(),GetLcurveY());
2712 curve[logTau]=std::make_pair(GetLcurveX(),GetLcurveY());
2720 XYtau_t::const_iterator i0,i1;
2724 Double_t logTauFin=(*i0).first;
2725 if( ((
int)curve.size())<nPoint) {
2727 Double_t *cTi=
new Double_t[curve.size()-1]();
2728 Double_t *cCi=
new Double_t[curve.size()-1]();
2731 Double_t *lXi=
new Double_t[curve.size()]();
2732 Double_t *lYi=
new Double_t[curve.size()]();
2733 Double_t *lTi=
new Double_t[curve.size()]();
2734 for (XYtau_t::const_iterator i = curve.begin(); i != curve.end(); ++i) {
2735 lXi[n] = (*i).second.first;
2736 lYi[n] = (*i).second.second;
2737 lTi[n] = (*i).first;
2740 TSpline3 *splineX=
new TSpline3(
"x vs tau",lTi,lXi,n);
2741 TSpline3 *splineY=
new TSpline3(
"y vs tau",lTi,lYi,n);
2744 for(Int_t i=0;i<n-1;i++) {
2745 Double_t ltau,xy,bi,ci,di;
2746 splineX->GetCoeff(i,ltau,xy,bi,ci,di);
2747 Double_t tauBar=0.5*(lTi[i]+lTi[i+1]);
2748 Double_t dTau=0.5*(lTi[i+1]-lTi[i]);
2749 Double_t dx1=bi+dTau*(2.*ci+3.*di*dTau);
2750 Double_t dx2=2.*ci+6.*di*dTau;
2751 splineY->GetCoeff(i,ltau,xy,bi,ci,di);
2752 Double_t dy1=bi+dTau*(2.*ci+3.*di*dTau);
2753 Double_t dy2=2.*ci+6.*di*dTau;
2755 cCi[i]=(dy2*dx1-dy1*dx2)/TMath::Power(dx1*dx1+dy1*dy1,1.5);
2764 TSpline3 *splineC=
new TSpline3(
"L curve curvature",cTi,cCi,n-1);
2773 Double_t cCmax=cCi[iskip];
2774 Double_t cTmax=cTi[iskip];
2775 for(Int_t i=iskip;i<n-2-iskip;i++) {
2778 Double_t xMax=cTi[i+1];
2779 Double_t yMax=cCi[i+1];
2788 splineC->GetCoeff(i,x,y,b,c,d);
2790 Double_t m_p_half=-c/(3.*d);
2791 Double_t q=b/(3.*d);
2792 Double_t discr=m_p_half*m_p_half-q;
2795 discr=TMath::Sqrt(discr);
2798 xx = m_p_half + discr;
2800 xx = m_p_half - discr;
2802 Double_t dx=cTi[i+1]-x;
2804 if((xx>0.0)&&(xx<dx)) {
2805 y=splineC->Eval(x+xx);
2818 if((xx>0.0)&&(xx<dx)) {
2819 y=splineC->Eval(x+xx);
2832 if(logTauCurvature) {
2833 *logTauCurvature=splineC;
2840 DoUnfold(TMath::Power(10.,logTauFin));
2841 if((!TMath::Finite(GetLcurveX())) ||(!TMath::Finite(GetLcurveY()))) {
2842 Fatal(
"ScanLcurve",
"problem (missing regularisation?) X=%f Y=%f",
2843 GetLcurveX(),GetLcurveY());
2845 Info(
"ScanLcurve",
"Result logtau=%lf X=%lf Y=%lf",
2846 logTauFin,GetLcurveX(),GetLcurveY());
2847 curve[logTauFin]=std::make_pair(GetLcurveX(),GetLcurveY());
2855 Int_t bestChoice=-1;
2856 if(curve.size()>0) {
2857 Double_t *x=
new Double_t[curve.size()]();
2858 Double_t *y=
new Double_t[curve.size()]();
2859 Double_t *logT=
new Double_t[curve.size()]();
2861 for (XYtau_t::const_iterator i = curve.begin(); i != curve.end(); ++i) {
2862 if (logTauFin == (*i).first) {
2865 x[n] = (*i).second.first;
2866 y[n] = (*i).second.second;
2867 logT[n] = (*i).first;
2871 (*lCurve)=
new TGraph(n,x,y);
2872 (*lCurve)->SetTitle(
"L curve");
2874 if(logTauX) (*logTauX)=
new TSpline3(
"log(chi**2)%log(tau)",logT,x,n);
2875 if(logTauY) (*logTauY)=
new TSpline3(
"log(reg.cond)%log(tau)",logT,y,n);
2898 void TUnfold::GetNormalisationVector(TH1 *out,
const Int_t *binMap)
const
2901 ClearHistogram(out);
2902 for (Int_t i = 0; i < GetNx(); i++) {
2903 int dest=binMap ? binMap[fXToHist[i]] : fXToHist[i];
2905 out->SetBinContent(dest, fSumOverY[i] + out->GetBinContent(dest));
2922 void TUnfold::GetBias(TH1 *out,
const Int_t *binMap)
const
2925 ClearHistogram(out);
2926 for (Int_t i = 0; i < GetNx(); i++) {
2927 int dest=binMap ? binMap[fXToHist[i]] : fXToHist[i];
2929 out->SetBinContent(dest, fBiasScale*(*fX0) (i, 0) +
2930 out->GetBinContent(dest));
2948 void TUnfold::GetFoldedOutput(TH1 *out,
const Int_t *binMap)
const
2950 ClearHistogram(out);
2952 TMatrixDSparse *AVxx=MultiplyMSparseMSparse(fA,fVxx);
2954 const Int_t *rows_A=fA->GetRowIndexArray();
2955 const Int_t *cols_A=fA->GetColIndexArray();
2956 const Double_t *data_A=fA->GetMatrixArray();
2957 const Int_t *rows_AVxx=AVxx->GetRowIndexArray();
2958 const Int_t *cols_AVxx=AVxx->GetColIndexArray();
2959 const Double_t *data_AVxx=AVxx->GetMatrixArray();
2961 for (Int_t i = 0; i < GetNy(); i++) {
2962 Int_t destI = binMap ? binMap[i+1] : i+1;
2963 if(destI<0)
continue;
2965 out->SetBinContent(destI, (*fAx) (i, 0)+ out->GetBinContent(destI));
2967 Int_t index_a=rows_A[i];
2968 Int_t index_av=rows_AVxx[i];
2969 while((index_a<rows_A[i+1])&&(index_av<rows_AVxx[i+1])) {
2970 Int_t j_a=cols_A[index_a];
2971 Int_t j_av=cols_AVxx[index_av];
2974 }
else if(j_a>j_av) {
2977 e2 += data_AVxx[index_av] * data_A[index_a];
2982 out->SetBinError(destI,TMath::Sqrt(e2));
2984 DeleteMatrix(&AVxx);
2996 void TUnfold::GetProbabilityMatrix(TH2 *A,EHistMap histmap)
const
3001 const Int_t *rows_A=fA->GetRowIndexArray();
3002 const Int_t *cols_A=fA->GetColIndexArray();
3003 const Double_t *data_A=fA->GetMatrixArray();
3004 for (Int_t iy = 0; iy <fA->GetNrows(); iy++) {
3005 for(Int_t indexA=rows_A[iy];indexA<rows_A[iy+1];indexA++) {
3006 Int_t ix = cols_A[indexA];
3007 Int_t ih=fXToHist[ix];
3008 if (histmap == kHistMapOutputHoriz) {
3009 A->SetBinContent(ih, iy+1,data_A[indexA]);
3011 A->SetBinContent(iy+1, ih,data_A[indexA]);
3031 void TUnfold::GetInput(TH1 *out,
const Int_t *binMap)
const
3033 ClearHistogram(out);
3035 const Int_t *rows_Vyy=fVyy->GetRowIndexArray();
3036 const Int_t *cols_Vyy=fVyy->GetColIndexArray();
3037 const Double_t *data_Vyy=fVyy->GetMatrixArray();
3039 for (Int_t i = 0; i < GetNy(); i++) {
3040 Int_t destI=binMap ? binMap[i+1] : i+1;
3041 if(destI<0)
continue;
3043 out->SetBinContent(destI, (*fY) (i, 0)+out->GetBinContent(destI));
3046 for(
int index=rows_Vyy[i];index<rows_Vyy[i+1];index++) {
3047 if(cols_Vyy[index]==i) {
3048 e=TMath::Sqrt(data_Vyy[index]);
3051 out->SetBinError(destI, e);
3060 void TUnfold::GetInputInverseEmatrix(TH2 *out)
3066 fVyyInv=InvertMSparseSymmPos(fVyy,&rank);
3068 fNdf = rank-GetNpar();
3070 if(rank<GetNy()-fIgnoredBins) {
3071 Warning(
"GetInputInverseEmatrix",
"input covariance matrix has rank %d expect %d",
3075 Error(
"GetInputInverseEmatrix",
"number of parameters %d > %d (rank of input covariance). Problem can not be solved",GetNpar(),rank);
3076 }
else if(fNdf==0) {
3077 Warning(
"GetInputInverseEmatrix",
"number of parameters %d = input rank %d. Problem is ill posed",GetNpar(),rank);
3082 const Int_t *rows_VyyInv=fVyyInv->GetRowIndexArray();
3083 const Int_t *cols_VyyInv=fVyyInv->GetColIndexArray();
3084 const Double_t *data_VyyInv=fVyyInv->GetMatrixArray();
3086 for(
int i=0;i<=out->GetNbinsX()+1;i++) {
3087 for(
int j=0;j<=out->GetNbinsY()+1;j++) {
3088 out->SetBinContent(i,j,0.);
3092 for (Int_t i = 0; i < fVyyInv->GetNrows(); i++) {
3093 for(
int index=rows_VyyInv[i];index<rows_VyyInv[i+1];index++) {
3094 Int_t j=cols_VyyInv[index];
3095 out->SetBinContent(i+1,j+1,data_VyyInv[index]);
3113 void TUnfold::GetLsquared(TH2 *out)
const
3118 TMatrixDSparse *lSquared=MultiplyMSparseTranspMSparse(fL,fL);
3120 const Int_t *rows=lSquared->GetRowIndexArray();
3121 const Int_t *cols=lSquared->GetColIndexArray();
3122 const Double_t *data=lSquared->GetMatrixArray();
3123 for (Int_t i = 0; i < GetNx(); i++) {
3124 for (Int_t cindex = rows[i]; cindex < rows[i+1]; cindex++) {
3125 Int_t j=cols[cindex];
3126 out->SetBinContent(fXToHist[i], fXToHist[j],data[cindex]);
3129 DeleteMatrix(&lSquared);
3138 Int_t TUnfold::GetNr(
void)
const {
3139 return fL->GetNrows();
3153 void TUnfold::GetL(TH2 *out)
const
3156 const Int_t *rows=fL->GetRowIndexArray();
3157 const Int_t *cols=fL->GetColIndexArray();
3158 const Double_t *data=fL->GetMatrixArray();
3159 for (Int_t row = 0; row < GetNr(); row++) {
3160 for (Int_t cindex = rows[row]; cindex < rows[row+1]; cindex++) {
3161 Int_t col=cols[cindex];
3162 Int_t indexH=fXToHist[col];
3163 out->SetBinContent(indexH,row+1,data[cindex]);
3173 void TUnfold::SetConstraint(EConstraint constraint)
3176 if(fConstraint !=constraint) ClearResults();
3177 fConstraint=constraint;
3178 Info(
"SetConstraint",
"fConstraint=%d",fConstraint);
3185 Double_t TUnfold::GetTau(
void)
const
3188 return TMath::Sqrt(fTauSquared);
3194 Double_t TUnfold::GetChi2L(
void)
const
3197 return fLXsquared*fTauSquared;
3206 Int_t TUnfold::GetNpar(
void)
const
3216 Double_t TUnfold::GetLcurveX(
void)
const
3218 return TMath::Log10(fChi2A);
3226 Double_t TUnfold::GetLcurveY(
void)
const
3228 return TMath::Log10(fLXsquared);
3263 void TUnfold::GetOutput(TH1 *output,
const Int_t *binMap)
const
3265 ClearHistogram(output);
3274 std::map<Int_t,Double_t> e2;
3276 const Int_t *rows_Vxx=fVxx->GetRowIndexArray();
3277 const Int_t *cols_Vxx=fVxx->GetColIndexArray();
3278 const Double_t *data_Vxx=fVxx->GetMatrixArray();
3280 Int_t binMapSize = fHistToX.GetSize();
3281 for(Int_t i=0;i<binMapSize;i++) {
3282 Int_t destBinI=binMap ? binMap[i] : i;
3283 Int_t srcBinI=fHistToX[i];
3284 if((destBinI>=0)&&(srcBinI>=0)) {
3285 output->SetBinContent
3286 (destBinI, (*fX)(srcBinI,0)+ output->GetBinContent(destBinI));
3292 Int_t index_vxx=rows_Vxx[srcBinI];
3294 while((j<binMapSize)&&(index_vxx<rows_Vxx[srcBinI+1])) {
3295 Int_t destBinJ=binMap ? binMap[j] : j;
3296 if(destBinI!=destBinJ) {
3300 Int_t srcBinJ=fHistToX[j];
3305 if(cols_Vxx[index_vxx]<srcBinJ) {
3308 }
else if(cols_Vxx[index_vxx]>srcBinJ) {
3313 e2[destBinI] += data_Vxx[index_vxx];
3323 for (std::map<Int_t, Double_t>::const_iterator i = e2.begin(); i != e2.end(); ++i) {
3325 output->SetBinError((*i).first,TMath::Sqrt((*i).second));
3343 void TUnfold::ErrorMatrixToHist(TH2 *ematrix,
const TMatrixDSparse *emat,
3344 const Int_t *binMap,Bool_t doClear)
const
3346 Int_t nbin=ematrix->GetNbinsX();
3348 for(Int_t i=0;i<nbin+2;i++) {
3349 for(Int_t j=0;j<nbin+2;j++) {
3350 ematrix->SetBinContent(i,j,0.0);
3351 ematrix->SetBinError(i,j,0.0);
3357 const Int_t *rows_emat=emat->GetRowIndexArray();
3358 const Int_t *cols_emat=emat->GetColIndexArray();
3359 const Double_t *data_emat=emat->GetMatrixArray();
3361 Int_t binMapSize = fHistToX.GetSize();
3362 for(Int_t i=0;i<binMapSize;i++) {
3363 Int_t destBinI=binMap ? binMap[i] : i;
3364 Int_t srcBinI=fHistToX[i];
3365 if((destBinI>=0)&&(destBinI<nbin+2)&&(srcBinI>=0)) {
3371 Int_t index_vxx=rows_emat[srcBinI];
3372 while((j<binMapSize)&&(index_vxx<rows_emat[srcBinI+1])) {
3373 Int_t destBinJ=binMap ? binMap[j] : j;
3374 Int_t srcBinJ=fHistToX[j];
3375 if((destBinJ<0)||(destBinJ>=nbin+2)||(srcBinJ<0)) {
3379 if(cols_emat[index_vxx]<srcBinJ) {
3382 }
else if(cols_emat[index_vxx]>srcBinJ) {
3387 Double_t e2= ematrix->GetBinContent(destBinI,destBinJ)
3388 + data_emat[index_vxx];
3389 ematrix->SetBinContent(destBinI,destBinJ,e2);
3410 void TUnfold::GetEmatrix(TH2 *ematrix,
const Int_t *binMap)
const
3412 ErrorMatrixToHist(ematrix,fVxx,binMap,kTRUE);
3425 void TUnfold::GetRhoIJ(TH2 *rhoij,
const Int_t *binMap)
const
3427 GetEmatrix(rhoij,binMap);
3428 Int_t nbin=rhoij->GetNbinsX();
3429 Double_t *e=
new Double_t[nbin+2];
3430 for(Int_t i=0;i<nbin+2;i++) {
3431 e[i]=TMath::Sqrt(rhoij->GetBinContent(i,i));
3433 for(Int_t i=0;i<nbin+2;i++) {
3434 for(Int_t j=0;j<nbin+2;j++) {
3435 if((e[i]>0.0)&&(e[j]>0.0)) {
3436 rhoij->SetBinContent(i,j,rhoij->GetBinContent(i,j)/e[i]/e[j]);
3438 rhoij->SetBinContent(i,j,0.0);
3466 Double_t TUnfold::GetRhoI(TH1 *rhoi,
const Int_t *binMap,TH2 *invEmat)
const
3468 ClearHistogram(rhoi,-1.);
3474 return GetRhoIFromMatrix(rhoi,fVxx,binMap,invEmat);
3476 Double_t rhoMax=0.0;
3478 const Int_t *rows_Vxx=fVxx->GetRowIndexArray();
3479 const Int_t *cols_Vxx=fVxx->GetColIndexArray();
3480 const Double_t *data_Vxx=fVxx->GetMatrixArray();
3482 const Int_t *rows_VxxInv=fVxxInv->GetRowIndexArray();
3483 const Int_t *cols_VxxInv=fVxxInv->GetColIndexArray();
3484 const Double_t *data_VxxInv=fVxxInv->GetMatrixArray();
3486 for(Int_t i=0;i<GetNx();i++) {
3487 Int_t destI=fXToHist[i];
3488 Double_t e_ii=0.0,einv_ii=0.0;
3489 for(
int index_vxx=rows_Vxx[i];index_vxx<rows_Vxx[i+1];index_vxx++) {
3490 if(cols_Vxx[index_vxx]==i) {
3491 e_ii=data_Vxx[index_vxx];
3495 for(
int index_vxxinv=rows_VxxInv[i];index_vxxinv<rows_VxxInv[i+1];
3497 if(cols_VxxInv[index_vxxinv]==i) {
3498 einv_ii=data_VxxInv[index_vxxinv];
3503 if((einv_ii>0.0)&&(e_ii>0.0)) rho=1.-1./(einv_ii*e_ii);
3504 if(rho>=0.0) rho=TMath::Sqrt(rho);
3505 else rho=-TMath::Sqrt(-rho);
3509 rhoi->SetBinContent(destI,rho);
3528 Double_t TUnfold::GetRhoIFromMatrix(TH1 *rhoi,
const TMatrixDSparse *eOrig,
3529 const Int_t *binMap,TH2 *invEmat)
const
3536 Int_t binMapSize = fHistToX.GetSize();
3541 std::map<int,int> histToLocalBin;
3543 for(Int_t i=0;i<binMapSize;i++) {
3544 Int_t mapped_i=binMap ? binMap[i] : i;
3546 if(histToLocalBin.find(mapped_i)==histToLocalBin.end()) {
3547 histToLocalBin[mapped_i]=nBin;
3556 Int_t *localBinToHist=
new Int_t[nBin];
3557 for (std::map<int, int>::const_iterator i = histToLocalBin.begin(); i != histToLocalBin.end(); ++i) {
3558 localBinToHist[(*i).second]=(*i).first;
3561 const Int_t *rows_eOrig=eOrig->GetRowIndexArray();
3562 const Int_t *cols_eOrig=eOrig->GetColIndexArray();
3563 const Double_t *data_eOrig=eOrig->GetMatrixArray();
3569 TMatrixD eRemap(nBin,nBin);
3571 for(Int_t i=0;i<GetNx();i++) {
3573 Int_t origI=fXToHist[i];
3575 Int_t destI=binMap ? binMap[origI] : origI;
3576 if(destI<0)
continue;
3577 Int_t ematBinI=histToLocalBin[destI];
3578 for(
int index_eOrig=rows_eOrig[i];index_eOrig<rows_eOrig[i+1];
3581 Int_t j=cols_eOrig[index_eOrig];
3583 Int_t origJ=fXToHist[j];
3585 Int_t destJ=binMap ? binMap[origJ] : origJ;
3586 if(destJ<0)
continue;
3587 Int_t ematBinJ=histToLocalBin[destJ];
3588 eRemap(ematBinI,ematBinJ) += data_eOrig[index_eOrig];
3592 TMatrixDSparse eSparse(eRemap);
3594 TMatrixDSparse *einvSparse=InvertMSparseSymmPos(&eSparse,&rank);
3595 if(rank!=einvSparse->GetNrows()) {
3596 Warning(
"GetRhoIFormMatrix",
"Covariance matrix has rank %d expect %d",
3597 rank,einvSparse->GetNrows());
3600 const Int_t *rows_eInv=einvSparse->GetRowIndexArray();
3601 const Int_t *cols_eInv=einvSparse->GetColIndexArray();
3602 const Double_t *data_eInv=einvSparse->GetMatrixArray();
3604 for(Int_t i=0;i<einvSparse->GetNrows();i++) {
3605 Double_t e_ii=eRemap(i,i);
3606 Double_t einv_ii=0.0;
3607 for(Int_t index_einv=rows_eInv[i];index_einv<rows_eInv[i+1];
3609 Int_t j=cols_eInv[index_einv];
3611 einv_ii=data_eInv[index_einv];
3614 invEmat->SetBinContent(localBinToHist[i],localBinToHist[j],
3615 data_eInv[index_einv]);
3619 if((einv_ii>0.0)&&(e_ii>0.0)) rho=1.-1./(einv_ii*e_ii);
3620 if(rho>=0.0) rho=TMath::Sqrt(rho);
3621 else rho=-TMath::Sqrt(-rho);
3626 rhoi->SetBinContent(localBinToHist[i],rho);
3629 DeleteMatrix(&einvSparse);
3630 delete [] localBinToHist;
3643 void TUnfold::ClearHistogram(TH1 *h,Double_t x)
const
3646 nxyz[0]=h->GetNbinsX()+1;
3647 nxyz[1]=h->GetNbinsY()+1;
3648 nxyz[2]=h->GetNbinsZ()+1;
3649 for(
int i=h->GetDimension();i<3;i++) nxyz[i]=0;
3651 for(
int i=0;i<3;i++) ixyz[i]=0;
3652 while((ixyz[0]<=nxyz[0])&&
3653 (ixyz[1]<=nxyz[1])&&
3654 (ixyz[2]<=nxyz[2])){
3655 Int_t ibin=h->GetBin(ixyz[0],ixyz[1],ixyz[2]);
3656 h->SetBinContent(ibin,x);
3657 h->SetBinError(ibin,0.0);
3658 for(Int_t i=0;i<3;i++) {
3660 if(ixyz[i]<=nxyz[i])
break;
3666 void TUnfold::SetEpsMatrix(Double_t eps) {
3668 if((eps>0.0)&&(eps<1.0)) fEpsMatrix=eps;
3680 const char *TUnfold::GetTUnfoldVersion(
void)
3682 return TUnfold_VERSION;