TUnfoldSys.cxx

Go to the documentation of this file.
00001 // @(#)root/hist:$Id: TUnfoldSys.cxx 37440 2010-12-09 15:13:46Z moneta $
00002 // Author: Stefan Schmitt
00003 // DESY, 23/01/09
00004 
00005 //  Version 16, parallel to changes in TUnfold
00006 //
00007 //  History:
00008 //    Version 15, fix bugs with uncorr. uncertainties, add backgnd subtraction
00009 //    Version 14, remove some print-out, do not add unused sys.errors
00010 //    Version 13, support for systematic errors
00011 
00012 ////////////////////////////////////////////////////////////////////////
00013 //
00014 // TUnfoldSys adds error propagation of systematic errors to TUnfold
00015 // Also, background sources (with errors) can be subtracted.
00016 //
00017 // The following sources of systematic error are considered:
00018 //  (a) uncorrelated errors on the input matrix histA, taken as the 
00019 //      errors provided with the histogram.
00020 //      These are typically statistical errors from finite Monte Carlo samples
00021 //
00022 //  (b) correlated shifts of the input matrix histA. These shifts are taken
00023 //      as one-sigma effects when switchig on a given error soure.
00024 //      several such error sources may be defined
00025 //
00026 //  (c) a systematic error on the regularisation parameter tau
00027 //
00028 //  (d) uncorrelated errors on background sources, taken as the errors
00029 //      provided with the background histograms
00030 //
00031 //  (e) scale errors on background sources
00032 //
00033 //
00034 // Source (a) is providede with the original histogram histA
00035 //     TUnfoldSys(histA,...)
00036 //
00037 // Sources (b) are added by calls to
00038 //     AddSysError()
00039 //
00040 // The systematic uncertainty on tau (c) is set by
00041 //     SetTauError()
00042 //
00043 // Backgound sources causing errors of type (d) and (e) are added by
00044 //     SubtractBackground()
00045 //
00046 //
00047 // NOTE:
00048 // ======
00049 //    Systematic errors (a), (b), (c) are propagated to the result
00050 //       AFTER unfolding
00051 //
00052 //    Background errors (d) and (e) are added to the data errors
00053 //       BEFORE unfolding
00054 //
00055 // For this reason:
00056 //  errors of type (d) and (e) are INCLUDED in the standard error matrix
00057 //  and other methods provided by the base class TUnfold:
00058 //      GetOutput()
00059 //      GetEmatrix()
00060 //      ...
00061 //  whereas errors of type (a), (b), (c) are NOT INCLUDED in the methods
00062 //  provided by the base class TUnfold.
00063 //
00064 // Accessing error matrices:
00065 // ===================================
00066 //  The error sources (b),(c) and (e) propagate to shifts of the result.
00067 //  These shifts may be accessed as histograms using the methods
00068 //     GetDeltaSysSource()            corresponds to (b)
00069 //     GetDeltaSysTau()               corresponds to (c)
00070 //     GetDeltaSysBackgroundScale()   corresponds to (e)
00071 //  The error sources (a) and (d) originate from many uncorrelated errors,
00072 //  which in general ar NOT uncorrelated on the result vector.
00073 //  Thus, there is no corresponding shift of the output vector, only error
00074 //  matrices are available
00075 //
00076 //  Method to get error matrix       corresponds to error sources
00077 //  ===============================================================
00078 //   GetEmatrixSysUncorr()             (a)
00079 //   GetEmatrixSysSource()             (b)
00080 //   GetEmatrixSysTau()                (c)
00081 //   GetEmatrixSysBackgroundUncorr()   (d)
00082 //   GetEmatrixSysBackgroundScale()    (e)
00083 //   GetEmatrixInput()                 (0)
00084 //   GetEmatrix()                      (0)+(d)+(e)
00085 //   GetEmatrixTotal()                 (0)+(a)+(b)+(c)+(d)+(e)
00086 //
00087 // Example:
00088 // ========
00089 //    TH2D *histA,*histAsys1,*histAsys2,*histBgr1,*histBgr2;
00090 //    TH1D *data;
00091 //  assume the above histograms are filled:
00092 //      histA: migration matrix from generator (x-axis) to detector (y-axis)
00093 //           the errors of histA are the uncorrelated systematic errors
00094 //      histAsys1: alternative migration matrix, when systematic #1 is applied
00095 //      histAsys1: alternative migration matrix, when systematic #2 is applied
00096 //      histBgr: known background to the data, with errors
00097 //
00098 //  set up the unfolding:
00099 //
00100 //    TUnfoldSys unfold(histA,TUnfold::kHistMapOutputVert);
00101 //    unfold.SetInput(input);
00102 //     // this background has 5% scale uncertainty
00103 //    unfold.SubtractBackground(histBgr1,"bgr1",1.0,0.05);
00104 //     // this background is scaled by 0.8 and has 10% scale uncertainty
00105 //    unfold.SubtractBackground(histBgr2,"bgr2",0.8,0.1);
00106 //    unfold.AddSysError(histAsys1,"syserror1",TUnfold::kHistMapOutputVert,
00107 //                       TUnfoldSys::kSysErrModeMatrix);
00108 //    unfold.AddSysError(histAsys2,"syserror2",TUnfold::kHistMapOutputVert,
00109 //                       TUnfoldSys::kSysErrModeMatrix);
00110 //
00111 //
00112 //  run the unfolding: see description of class TUnfold
00113 //    unfold.ScanLcurve( ...)
00114 //
00115 //  retrieve the output
00116 //  the errors include errors from input, from histBgr1 and from histBgr2
00117 //    unfold.GetOutput(output);
00118 //
00119 //  retreive systematic shifts corresponding to correlated error sources
00120 //  In the example, there are 4 correlated sources:
00121 //     * 5% scale error on bgr1
00122 //     * 10% scale error on bgr2
00123 //     * the systematic error  "syserror1"
00124 //     * the systematic error  "syserror2"
00125 //  These error s are returned as vectors
00126 //  (corresponding to one-sigma shifts of each source)
00127 //
00128 //   unfold.GetDeltaSysBackgroundScale(bgr1shifts,"bgr1");
00129 //   unfold.GetDeltaSysBackgroundScale(bgr2shifts,"bgr2");
00130 //   unfold.GetDeltaSysSource(sys1shifts,"syserror1");
00131 //   unfold.GetDeltaSysSource(sys2shifts,"syserror2");
00132 //
00133 //  retreive errors from uncorrelated sources
00134 //  In the example, there are four sources of uncorrelated error
00135 //     * the input vector (statistical errors of the data)
00136 //     * the input matrix histA (Monte Carlo statistical errors)
00137 //     * the errors on bgr1 (Monte Carlo statistical errors)
00138 //     * the errors on bgr2 (Monte Carlo statistical errors)
00139 //  These errors are returned as error matrices
00140 //
00141 //    unfold.GetEmatrixInput(stat_error);
00142 //    unfold.GetEmatrixSysUncorr(uncorr_sys);
00143 //    unfold.GetEmatrixSysBackgroundUncorr(bgr1uncorr,"bgr1");
00144 //    unfold.GetEmatrixSysBackgroundUncorr(bgr2uncorr,"bgr2");
00145 //
00146 //  Error matrices can be added to existing histograms.
00147 //  This is useful to retreive the sum of several error matrices.
00148 //  If the last argument of the .GetEmatrixXXX methods is set to kFALSE, the
00149 //  histogram is not cleared, but the error matrix is simply added.
00150 //  Example: add all errors from background subtraction
00151 //
00152 //     unfold.GetEmatrixSysBackgroundUncorr(bgrerror,"bgr1",0,kTRUE);   
00153 //     unfold.GetEmatrixSysBackgroundCorr(bgrerror,"bgr1",0,kFALSE);   
00154 //     unfold.GetEmatrixSysBackgroundUncorr(bgrerror,"bgr2",0,kFALSE);   
00155 //     unfold.GetEmatrixSysBackgroundCorr(bgrerror,"bgr2",0,kFALSE);   
00156 //
00157 //  There is a special function to get the total error:
00158 //    unfold.GetEmatrixTotal(err_total);
00159 //
00160 ////////////////////////////////////////////////////////////////////////
00161 
00162 #include <iostream>
00163 #include <TMap.h>
00164 #include <TMath.h>
00165 #include <TObjString.h>
00166 #include <RVersion.h>
00167 
00168 #include <TUnfoldSys.h>
00169 
00170 ClassImp(TUnfoldSys)
00171 
00172 TUnfoldSys::TUnfoldSys(void) {
00173    // set all pointers to zero
00174    InitTUnfoldSys();
00175 }
00176 
00177 TUnfoldSys::TUnfoldSys(const TH2 *hist_A, EHistMap histmap, ERegMode regmode,
00178                        EConstraint constraint) : TUnfold(hist_A,histmap,regmode,constraint) {
00179    // arguments:
00180    //    hist_A:  matrix that describes the migrations
00181    //    histmap: mapping of the histogram axes to the unfolding output 
00182    //    regmode: global regularisation mode
00183    // data members initialized to something different from zero:
00184    //    fDA2, fDAcol
00185 
00186    // initialize TUnfold
00187    InitTUnfoldSys();
00188 
00189    // svae underflow and overflow bins
00190    fAoutside = new TMatrixD(GetNx(),2);
00191    // save the romalized errors on hist_A
00192    // to the matrices fDAinRelSq and fDAinColRelSq
00193    fDAinColRelSq = new TMatrixD(GetNx(),1);
00194 
00195    Int_t nmax=GetNx()*GetNy();
00196    Int_t *rowDAinRelSq = new Int_t[nmax];
00197    Int_t *colDAinRelSq = new Int_t[nmax];
00198    Double_t *dataDAinRelSq = new Double_t[nmax];
00199 
00200    Int_t da_nonzero=0;
00201    for (Int_t ix = 0; ix < GetNx(); ix++) {
00202       Int_t ibinx = fXToHist[ix];
00203       Double_t sum_sq= fSumOverY[ix]*fSumOverY[ix];
00204       for (Int_t ibiny = 0; ibiny <= GetNy()+1; ibiny++) {
00205          Double_t dz;
00206          if (histmap == kHistMapOutputHoriz) {
00207             dz = hist_A->GetBinError(ibinx, ibiny);
00208          } else {
00209             dz = hist_A->GetBinError(ibiny, ibinx);
00210          }
00211          Double_t normerr_sq=dz*dz/sum_sq;
00212          // quadratic sum of all errors from all bins,
00213          //   including under/overflow bins
00214          (*fDAinColRelSq)(ix,0) += normerr_sq;
00215 
00216          if(ibiny==0) {
00217             // underflow bin
00218             if (histmap == kHistMapOutputHoriz) {
00219                (*fAoutside)(ix,0)=hist_A->GetBinContent(ibinx, ibiny);
00220             } else {
00221                (*fAoutside)(ix,0)=hist_A->GetBinContent(ibiny, ibinx);
00222             }
00223          } else if(ibiny==GetNy()+1) {
00224             // overflow bins
00225             if (histmap == kHistMapOutputHoriz) {
00226                (*fAoutside)(ix,1)=hist_A->GetBinContent(ibinx, ibiny);
00227             } else {
00228                (*fAoutside)(ix,1)=hist_A->GetBinContent(ibiny, ibinx);
00229             }
00230          } else {
00231             // error on this bin
00232             rowDAinRelSq[da_nonzero]=ibiny-1;
00233             colDAinRelSq[da_nonzero] = ix;
00234             dataDAinRelSq[da_nonzero] = normerr_sq;
00235             if(dataDAinRelSq[da_nonzero]>0.0) da_nonzero++;
00236          }
00237       }
00238    }
00239    if(da_nonzero) {
00240       fDAinRelSq = CreateSparseMatrix(GetNy(),GetNx(),da_nonzero,
00241                                       rowDAinRelSq,colDAinRelSq,dataDAinRelSq);
00242    } else {
00243       DeleteMatrix(&fDAinColRelSq);
00244    }
00245    delete[] rowDAinRelSq;
00246    delete[] colDAinRelSq;
00247    delete[] dataDAinRelSq;      
00248 }
00249 
00250 void TUnfoldSys::AddSysError(const TH2 *sysError,const char *name,
00251                              EHistMap histmap,ESysErrMode mode) {
00252    // add a correlated error source
00253    //    sysError: alternative matrix or matrix of absolute/relative shifts
00254    //    name: name of the error source
00255    //    histmap: mapping of the histogram axes to the unfolding output
00256    //    mode: format of the error source
00257 
00258    if(fSysIn->FindObject(name)) {
00259       Error("AddSysError","Source %s given twice, ignoring 2nd call.\n",name);
00260    } else {
00261       // a copy of fA is made. It can be accessed inside the loop
00262       // without having to take care that the sparse structure of *fA
00263       // may be accidentally destroyed by asking for an element which is zero.
00264       TMatrixD aCopy(*fA);
00265 
00266       Int_t nmax= GetNx()*GetNy();
00267       Double_t *data=new Double_t[nmax];
00268       Int_t *cols=new Int_t[nmax];
00269       Int_t *rows=new Int_t[nmax];
00270       nmax=0;
00271       for (Int_t ix = 0; ix < GetNx(); ix++) {
00272          Int_t ibinx = fXToHist[ix];
00273          Double_t sum=0.0;
00274          for(Int_t loop=0;loop<2;loop++) {
00275             for (Int_t ibiny = 0; ibiny <= GetNy()+1; ibiny++) {
00276                Double_t z;
00277                // get bin content, depending on histmap
00278                if (histmap == kHistMapOutputHoriz) {
00279                   z = sysError->GetBinContent(ibinx, ibiny);
00280                } else {
00281                   z = sysError->GetBinContent(ibiny, ibinx);
00282                }
00283                // correct to absolute numbers
00284                if(mode!=kSysErrModeMatrix) {
00285                   Double_t z0;
00286                   if((ibiny>0)&&(ibiny<=GetNy())) {
00287                      z0=aCopy(ibiny-1,ix)*fSumOverY[ix];
00288                   } else if(ibiny==0) {
00289                      z0=(*fAoutside)(ix,0);
00290                   } else {
00291                      z0=(*fAoutside)(ix,1);
00292                   }
00293                   if(mode==kSysErrModeShift) {
00294                      z += z0;
00295                   } else if(mode==kSysErrModeRelative) {
00296                      z = z0*(1.+z);
00297                   }
00298                }
00299                if(loop==0) {
00300                   // sum up all entries, including overflow bins
00301                   sum += z;
00302                } else {
00303                   if((ibiny>0)&&(ibiny<=GetNy())) {
00304                      // save normalized matrix of shifts,
00305                      // excluding overflow bins
00306                      rows[nmax]=ibiny-1;
00307                      cols[nmax]=ix;
00308                      if(sum>0.0) {
00309                         data[nmax]=z/sum-aCopy(ibiny-1,ix);
00310                      } else {
00311                         data[nmax]=0.0;
00312                      }
00313                      if(data[nmax] != 0.0) nmax++;
00314                   }
00315                }
00316             }
00317          }
00318       }
00319       if(nmax==0) {
00320          Error("AddSysError",
00321                "source %s has no influence and has not been added.\n",name);
00322       } else {
00323          TMatrixDSparse *dsys=CreateSparseMatrix(GetNy(),GetNx(),
00324                                                  nmax,rows,cols,data);
00325          fSysIn->Add(new TObjString(name),dsys);
00326       }
00327       delete[] data;
00328       delete[] rows;
00329       delete[] cols;
00330    }
00331 }
00332 
00333 void TUnfoldSys::DoBackgroundSubtraction(void) {
00334    // performs background subtraction
00335    // fY = fYData - fBgrIn
00336    // fVyy = fVyyData + fBgrErrUncorr^2 + fBgrErrCorr * fBgrErrCorr#
00337    // fVyyinv = fVyy^(-1)
00338 
00339    if(fYData) {
00340       DeleteMatrix(&fY);
00341       DeleteMatrix(&fVyy);
00342       if(fBgrIn->GetEntries()<=0) {
00343          // simple copy
00344          fY=new TMatrixD(*fYData);
00345          fVyy=new TMatrixDSparse(*fVyyData);
00346       } else {
00347          // copy of the data
00348          fY=new TMatrixD(*fYData);
00349          // subtract background from fY
00350          const TObject *key;
00351          {
00352             TMapIter bgrPtr(fBgrIn);
00353             for(key=bgrPtr.Next();key;key=bgrPtr.Next()) {
00354                const TMatrixD *bgr=(const TMatrixD *)
00355 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,20,00)
00356                   ((const TPair *)*bgrPtr)->Value()
00357 #else
00358                   fBgrIn->GetValue(((const TObjString *)key)->GetString())
00359 #endif
00360                   ;
00361                for(Int_t i=0;i<GetNy();i++) {
00362                   (*fY)(i,0) -= (*bgr)(i,0);
00363                }
00364             }
00365          }
00366          // copy original error matrix
00367          TMatrixD vyy(*fVyyData);
00368          // determine used bins
00369          Int_t ny=fVyyData->GetNrows();
00370          const Int_t *vyydata_rows=fVyyData->GetRowIndexArray();
00371          const Int_t *vyydata_cols=fVyyData->GetColIndexArray();
00372          const Double_t *vyydata_data=fVyyData->GetMatrixArray();
00373          Int_t *usedBin=new Int_t[ny];
00374          for(Int_t i=0;i<ny;i++) {
00375             usedBin[i]=0;
00376          }
00377          for(Int_t i=0;i<ny;i++) {
00378             for(Int_t k=vyydata_rows[i];k<vyydata_rows[i+1];k++) {
00379                if(vyydata_data[k]>0.0) {
00380                   usedBin[i]++;
00381                   usedBin[vyydata_cols[k]]++;
00382                }
00383             }
00384          }
00385          // add uncorrelated background errors
00386          {
00387             TMapIter bgrErrUncorrPtr(fBgrErrUncorrIn);
00388             for(key=bgrErrUncorrPtr.Next();key;key=bgrErrUncorrPtr.Next()) {
00389                const TMatrixD *bgrerruncorr=(TMatrixD const *)
00390 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,20,00)
00391                   ((const TPair *)*bgrErrUncorrPtr)->Value()
00392 #else
00393                   fBgrErrUncorrIn->GetValue(((const TObjString *)key)
00394                                             ->GetString())
00395 #endif
00396                   ;
00397                for(Int_t yi=0;yi<ny;yi++) {
00398                   if(!usedBin[yi]) continue;
00399                   vyy(yi,yi) +=(*bgrerruncorr)(yi,0)* (*bgrerruncorr)(yi,0);
00400                }
00401             }
00402          }
00403          // add correlated background errors
00404          {
00405             TMapIter bgrErrCorrPtr(fBgrErrCorrIn);
00406             for(key=bgrErrCorrPtr.Next();key;key=bgrErrCorrPtr.Next()) {
00407                const TMatrixD *bgrerrcorr=(const TMatrixD *)
00408 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,20,00)
00409                   ((const TPair *)*bgrErrCorrPtr)->Value()
00410 #else
00411                   fBgrErrCorrIn->GetValue(((const TObjString *)key)
00412                                           ->GetString())
00413 #endif
00414                   ;
00415                for(Int_t yi=0;yi<ny;yi++) {
00416                   if(!usedBin[yi]) continue;
00417                   for(Int_t yj=0;yj<ny;yj++) {
00418                      if(!usedBin[yj]) continue;
00419                      vyy(yi,yj) +=(*bgrerrcorr)(yi,0)* (*bgrerrcorr)(yj,0);
00420                   }
00421                }
00422             }
00423          }
00424          delete[] usedBin;
00425          usedBin=0;
00426 
00427          // convert to sparse matrix
00428          fVyy=new TMatrixDSparse(vyy);
00429 
00430       }
00431    } else {
00432       Fatal("TUnfoldSys::DoBackgroundSubtraction","No input vector defined");
00433    }
00434 #ifdef UNUSED
00435       // for first background source, create a copy of the original error
00436       // matrix
00437       if(!fVyy0) {
00438          if(!fVyy) {
00439             Fatal("TUnfoldSys::SubtractBackground",
00440                   "did You forget to call SetInput()?");
00441          }
00442          fVyy0=new TMatrixDSparse(*fVyy);
00443       }
00444       Int_t *rowcol=new Int_t[GetNy()];
00445       Int_t *col0=new Int_t[GetNy()];
00446       Double_t *error_uncorr=new Double_t[GetNy()];
00447       Double_t *error_uncorr_sq=new Double_t[GetNy()];
00448       Double_t *error_corr=new Double_t[GetNy()];
00449       Int_t n=0;
00450       const Int_t *vyyinv_rows=fVyyinv->GetRowIndexArray();
00451       const Int_t *vyyinv_cols=fVyyinv->GetColIndexArray();
00452       const Double_t *vyyinv_data=fVyyinv->GetMatrixArray();
00453       for(Int_t row=0;row<fVyyinv->GetNrows();row++) {
00454          Double_t y0=(*fY)(row,0);
00455          (*fY)(row,0) -= scale*bgr->GetBinContent(row+1);
00456          // loop over the existing data error matrix
00457          // only those bins which have non-zero error^-1 are considered
00458          for(Int_t index=vyyinv_rows[row];index<vyyinv_rows[row+1];index++) {
00459             if(vyyinv_cols[index]==row) {
00460                rowcol[n] = row;
00461                col0[n]=0;
00462                // uncorrelated error
00463                error_uncorr[n]=scale*bgr->GetBinError(row+1);
00464                error_uncorr_sq[n]=error_uncorr[n]*error_uncorr[n];
00465                // correlated error
00466                error_corr[n] = scale_error*bgr->GetBinContent(row+1);
00467                n++;
00468             }
00469          }
00470       }
00471       // diagonal matrix of uncorrelated errors
00472       TMatrixDSparse VYuncorr(GetNy(),GetNy());
00473       SetSparseMatrixArray(&VYuncorr,n,rowcol,rowcol,error_uncorr_sq);
00474       // add uncorrelated errors
00475       AddMSparse(fVyy,1.0,&VYuncorr);
00476       // save uncorrelated errors
00477       TMatrixDSparse *dbgr_unc=new TMatrixDSparse(GetNy(),1);
00478       SetSparseMatrixArray(dbgr_unc,n,rowcol,col0,error_uncorr);
00479       fBgrUncorrIn->Add(new TObjString(name),dbgr_unc);
00480       // save vector of correlated errors
00481       TMatrixDSparse *dbgr_corr=new TMatrixDSparse(GetNy(),1);
00482       SetSparseMatrixArray(dbgr_corr,n,rowcol,col0,error_corr);
00483       fBgrCorrIn->Add(new TObjString(name),dbgr_corr);
00484       // add correlated error
00485       TMatrixDSparse *VYcorr=MultiplyMSparseMSparseTranspVector
00486          (dbgr_corr,dbgr_corr,0);
00487       AddMSparse(fVyy,1.0,VYcorr);
00488       delete[] error_uncorr;
00489       delete[] error_uncorr_sq;
00490       delete[] error_corr;
00491       delete[] rowcol;
00492       delete[] col0;
00493       DeleteMatrix(&VYcorr);
00494       // invert covariance matrix
00495       DeleteMatrix(&fVyyinv);
00496       TMatrixD *vyyinv=InvertMSparse(fVyy);
00497       fVyyinv=new TMatrixDSparse(*vyyinv);
00498       DeleteMatrix(&vyyinv);
00499 #endif
00500 }
00501 
00502 Int_t TUnfoldSys::SetInput(const TH1 *hist_y,Double_t scaleBias,
00503                            Double_t oneOverZeroError) {
00504    // Define the input data for subsequent calls to DoUnfold(Double_t)
00505    //  input:   input distribution with errors
00506    //  scaleBias:  scale factor applied to the bias
00507    //  oneOverZeroError: for bins with zero error, this number defines 1/error.
00508    // Return value: number of bins with bad error
00509    //                 +10000*number of unconstrained output bins
00510    //         Note: return values>=10000 are fatal errors, 
00511    //               for the given input, the unfolding can not be done!
00512    // Calls the SetInput metghod of the base class, then renames the input
00513    // vectors fY and fVyy, then performs the background subtraction
00514    // Data members modified:
00515    //   fYData,fY,fVyyData,fVyy,fVyyinvData,fVyyinv
00516    // and those modified by TUnfold::SetInput()
00517    // and those modified by DoBackgroundSubtraction()
00518 
00519    Int_t r=TUnfold::SetInput(hist_y,scaleBias,oneOverZeroError);
00520    //LM: WARNING: Coverity detects here a false USE_AFTER_FREE for fY and fVyy
00521    // the objects are deleted but then re-created immediatly afterwards in 
00522    //  TUnfold::SetInput
00523    fYData=fY;
00524    fY=0;
00525    fVyyData=fVyy;
00526    fVyy=0;
00527    DoBackgroundSubtraction();
00528 
00529    return r;
00530 }
00531 
00532 void TUnfoldSys::SubtractBackground(const TH1 *bgr,const char *name,
00533                                     Double_t scale,
00534                                     Double_t scale_error) {
00535    // Store background source
00536    //   bgr:    background distribution with uncorrelated errors
00537    //   name:   name of this background source
00538    //   scale:  scale factor applied to the background
00539    //   scaleError: error on scale factor (correlated error)
00540    //
00541    // Data members modified:
00542    //   fBgrIn,fBgrErrUncorrIn,fBgrErrCorrIn
00543    // and those modified by DoBackgroundSubtraction()
00544 
00545    // save background source
00546    if(fBgrIn->FindObject(name)) {
00547       Error("SubtractBackground","Source %s given twice, ignoring 2nd call.\n",
00548             name);
00549    } else {
00550       TMatrixD *bgrScaled=new TMatrixD(GetNy(),1);
00551       TMatrixD *bgrErrUnc=new TMatrixD(GetNy(),1);
00552       TMatrixD *bgrErrCorr=new TMatrixD(GetNy(),1);
00553       for(Int_t row=0;row<GetNy();row++) {
00554          (*bgrScaled)(row,0) = scale*bgr->GetBinContent(row+1);
00555          (*bgrErrUnc)(row,0) = scale*bgr->GetBinError(row+1);
00556          (*bgrErrCorr)(row,0) = scale_error*bgr->GetBinContent(row+1);
00557       }
00558       fBgrIn->Add(new TObjString(name),bgrScaled);
00559       fBgrErrUncorrIn->Add(new TObjString(name),bgrErrUnc);
00560       fBgrErrCorrIn->Add(new TObjString(name),bgrErrCorr);
00561       if(fYData) {
00562          DoBackgroundSubtraction();
00563       } else {
00564          Info("TUnfoldSys::SubtractBackground",
00565               "Background subtraction prior to setting input data");
00566       }
00567    }
00568 }
00569 
00570 void TUnfoldSys::InitTUnfoldSys(void) {
00571    // initialize pointers and TMaps
00572 
00573    // input
00574    fDAinRelSq = 0;
00575    fDAinColRelSq = 0;
00576    fAoutside = 0;
00577    fBgrIn = new TMap();
00578    fBgrErrUncorrIn = new TMap();
00579    fBgrErrCorrIn = new TMap();
00580    fSysIn = new TMap();
00581 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,20,00)
00582    fBgrIn->SetOwnerKeyValue();
00583    fBgrErrUncorrIn->SetOwnerKeyValue();
00584    fBgrErrCorrIn->SetOwnerKeyValue();
00585    fSysIn->SetOwnerKeyValue();
00586 #else
00587    fBgrIn->SetOwner();
00588    fBgrErrUncorrIn->SetOwner();
00589    fBgrErrCorrIn->SetOwner();
00590    fSysIn->SetOwner();
00591 #endif
00592    // results
00593    fEmatUncorrX = 0;
00594    fEmatUncorrAx = 0;
00595    fDeltaCorrX = new TMap();
00596    fDeltaCorrAx = new TMap();
00597 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,20,00)
00598    fDeltaCorrX->SetOwnerKeyValue();
00599    fDeltaCorrAx->SetOwnerKeyValue();
00600 #else
00601    fDeltaCorrX->SetOwner();
00602    fDeltaCorrAx->SetOwner();
00603 #endif
00604    fDeltaSysTau = 0;
00605    fDtau=0.0;
00606    fYData=0;
00607    fVyyData=0;
00608 }
00609 
00610 TUnfoldSys::~TUnfoldSys(void) {
00611    // delete all data members
00612    DeleteMatrix(&fDAinRelSq);
00613    DeleteMatrix(&fDAinColRelSq);
00614    delete fBgrIn;
00615    delete fBgrErrUncorrIn;
00616    delete fBgrErrCorrIn;
00617    delete fSysIn;
00618    ClearResults();
00619    delete fDeltaCorrX;
00620    delete fDeltaCorrAx;
00621    DeleteMatrix(&fYData);
00622    DeleteMatrix(&fVyyData);
00623 }
00624 
00625 void TUnfoldSys::ClearResults(void) {
00626    // clear all data members which depend on the unfolding results
00627    TUnfold::ClearResults();
00628    DeleteMatrix(&fEmatUncorrX);
00629    DeleteMatrix(&fEmatUncorrAx);
00630    fDeltaCorrX->Clear();
00631    fDeltaCorrAx->Clear();
00632    DeleteMatrix(&fDeltaSysTau);
00633 }
00634 
00635 void TUnfoldSys::PrepareSysError(void) {
00636    // calculations required for syst.error
00637    // data members modified
00638    //    fEmatUncorrX, fEmatUncorrAx, fDeltaCorrX, fDeltaCorrAx
00639    if(!fEmatUncorrX) {
00640       fEmatUncorrX=PrepareUncorrEmat(GetDXDAM(0),GetDXDAM(1));
00641    }
00642    TMatrixDSparse *AM0=0,*AM1=0;
00643    if(!fEmatUncorrAx) {
00644       if(!AM0) AM0=MultiplyMSparseMSparse(fA,GetDXDAM(0));
00645       if(!AM1) {
00646          AM1=MultiplyMSparseMSparse(fA,GetDXDAM(1));
00647          Int_t *rows_cols=new Int_t[GetNy()];
00648          Double_t *data=new Double_t[GetNy()];
00649          for(Int_t i=0;i<GetNy();i++) {
00650             rows_cols[i]=i;
00651             data[i]=1.0;
00652          }
00653          TMatrixDSparse *one=CreateSparseMatrix
00654             (GetNy(),GetNy(),GetNy(),rows_cols, rows_cols,data);
00655          delete[] data;
00656          delete[] rows_cols;
00657          AddMSparse(AM1,-1.,one);
00658          DeleteMatrix(&one);
00659          fEmatUncorrAx=PrepareUncorrEmat(AM0,AM1);
00660       }
00661    }
00662    if((!fDeltaSysTau )&&(fDtau>0.0)) {
00663       fDeltaSysTau=new TMatrixDSparse(*GetDXDtauSquared());
00664       Double_t scale=2.*TMath::Sqrt(fTauSquared)*fDtau;
00665       Int_t n=fDeltaSysTau->GetRowIndexArray() [fDeltaSysTau->GetNrows()];
00666       Double_t *data=fDeltaSysTau->GetMatrixArray();
00667       for(Int_t i=0;i<n;i++) {
00668          data[i] *= scale;
00669       }
00670    }
00671 
00672    TMapIter sysErrIn(fSysIn);
00673    const TObjString *key;
00674 
00675    // calculate individual systematic errors
00676    for(key=(const TObjString *)sysErrIn.Next();key;
00677        key=(const TObjString *)sysErrIn.Next()) {
00678 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,20,00)
00679       const TMatrixDSparse *dsys=
00680          (const TMatrixDSparse *)((const TPair *)*sysErrIn)->Value();
00681 #else
00682       const TMatrixDSparse *dsys=
00683          (const TMatrixDSparse *)(fSysIn->GetValue(key->GetString()));
00684 #endif
00685       const TPair *named_emat=(const TPair *)
00686          fDeltaCorrX->FindObject(key->GetString());
00687       if(!named_emat) {
00688          TMatrixDSparse *emat=PrepareCorrEmat(GetDXDAM(0),GetDXDAM(1),dsys);
00689          fDeltaCorrX->Add(new TObjString(*key),emat);
00690       }
00691       named_emat=(const TPair *)fDeltaCorrAx->FindObject(key->GetString());
00692       if(!named_emat) {
00693          if(!AM0) AM0=MultiplyMSparseMSparse(fA,GetDXDAM(0));
00694          if(!AM1) {
00695             AM1=MultiplyMSparseMSparse(fA,GetDXDAM(1));
00696             Int_t *rows_cols=new Int_t[GetNy()];
00697             Double_t *data=new Double_t[GetNy()];
00698             for(Int_t i=0;i<GetNy();i++) {
00699                rows_cols[i]=i;
00700                data[i]=1.0;
00701             }
00702             TMatrixDSparse *one=CreateSparseMatrix
00703                (GetNy(),GetNy(),GetNy(),rows_cols, rows_cols,data);
00704             delete[] data;
00705             delete[] rows_cols;
00706             AddMSparse(AM1,-1.,one);
00707             DeleteMatrix(&one);
00708             fEmatUncorrAx=PrepareUncorrEmat(AM0,AM1);
00709          }
00710          TMatrixDSparse *emat=PrepareCorrEmat(AM0,AM1,dsys);
00711          fDeltaCorrAx->Add(new TObjString(*key),emat);
00712       }
00713    }
00714    DeleteMatrix(&AM0);
00715    DeleteMatrix(&AM1);
00716 }
00717   
00718 void TUnfoldSys::GetEmatrixSysUncorr(TH2 *ematrix,const Int_t *binMap,
00719                                      Bool_t clearEmat) {
00720    // get output error contribution from statistical fluctuations in A
00721    //   ematrix: output error matrix histogram
00722    //   binMap: see method GetEmatrix()
00723    //   clearEmat: set kTRUE to clear the histogram prior to adding the errors
00724    // data members modified:
00725    //   fVYAx, fESparse, fEAtV, fErrorAStat
00726    PrepareSysError();
00727    ErrorMatrixToHist(ematrix,fEmatUncorrX,binMap,clearEmat);
00728 }
00729 
00730 TMatrixDSparse *TUnfoldSys::PrepareUncorrEmat(const TMatrixDSparse *m_0,
00731                                               const TMatrixDSparse *m_1) {
00732    // propagate uncorrelated systematic errors to a covariance matrix
00733    //   m0,m1 : coefficients (matrices) for propagating the errors
00734    //
00735    // the error matrix is calculated by standard error propagation, where the
00736    // derivative of the result vector X wrt the matrix A is given by
00737    //
00738    //  dX_k / dA_ij  =  M0_kj * Z0_i  - M1_ki * Z1_j
00739    //
00740    // where:
00741    //   the matrices M0 and M1 are arguments to this function
00742    //   the vectors Z0, Z1 : GetDXDAZ()
00743    //
00744    // The matrix A is calculated from a matrix B as
00745    //
00746    //    A_ij = B_ij / sum_k B_kj
00747    //
00748    // where k runs over additional indices of B, not present in A.
00749    // (underflow and overflow bins, used for efficiency corrections)
00750    //
00751    // define:   Norm_j = sum_k B_kj   (data member fSumOverY)
00752    //
00753    // the derivative of A wrt this input matrix B is given by:
00754    //
00755    //   dA_ij / dB_kj = (  delta_ik - A_ij ) * 1/Norm_j 
00756    //
00757    // The covariance matrix Vxx is:
00758    //
00759    //   Vxx_mn  = sum_ijlk [   (dX_m / dA_ij) * (dA_ij / dB_kj) * DB_kj
00760    //                        * (dX_n / dA_lj) * (dA_lj / dB_kj)  ]
00761    //
00762    // where DB_kj is the error on B_kj squared
00763    // Simplify the sum over k:
00764    //
00765    //   sum_k [ (dA_ij / dB_kj) * DB_kj * (dA_lj / dB_kj) ]
00766    //      =  sum_k [  ( delta_ik - A_ij ) * 1/Norm_j * DB_kj *
00767    //                * ( delta_lk - A_lj ) * 1/Norm_j ]
00768    //      =  sum_k [ ( delta_ik*delta_lk - delta_ik*A_lj - delta_lk*A_ij
00769    //                  + A_ij * A_lj ) * DB_kj / Norm_j^2 ]
00770    //
00771    // introduce normalized errors:  Rsq_kj = DB_kj / Norm_j^2
00772    // after summing over k:
00773    //   delta_ik*delta_lk*Rsq_kj  ->    delta_il*Rsq_ij
00774    //   delta_ik*A_lj*Rsq_kj      ->    A_lj*Rsq_ij
00775    //   delta_lk*A_ij*Rsq_kj      ->    A_ij*Rsq_lj
00776    //   A_ij*A_lj*Rsq_kj          ->    A_ij*A_lj*sum_k(Rsq_kj)
00777    //
00778    // introduce sum of normalized errors squared:   SRsq_j = sum_k(Rsq_kj)
00779    //
00780    // Note: Rsq_ij is stored as  fDAinRelSq     (excludes extra indices of B)
00781    //   and SRsq_j is stored as  fDAinColRelSq  (sum includes all indices of B)
00782    //
00783    //  Vxx_nm = sum_ijl [ (dX_m / dA_ij) * (dX_n / dA_lj)
00784    //     (delta_il*Rsq_ij - A_lj*Rsq_ij - A_ij*Rsq_lj + A_ij*A_lj *SRsq_j) ]
00785    //
00786    //  Vxx_nm =    sum_j [ F_mj * F_nj * SRsq_j
00787    //            - sum_j [ G_mj * F_nj ]
00788    //            - sum_j [ F_mj * G_nj ]
00789    //            + sum_ij [  (dX_m / dA_ij) * (dX_n / dA_lj) * Rsq_ij ]
00790    //
00791    // where:
00792    //    F_mj = sum_i [ (dX_m / dA_ij) * A_ij ]
00793    //    G_mj = sum_i [ (dX_m / dA_ij) * Rsq_ij ]
00794    //
00795    // In order to avoid explicitly calculating the 3-dimensional tensor
00796    // (dX_m/dA_ij) the sums are evaluated further, using
00797    //    dX_k / dA_ij  =  M0_kj * Z0_i  - M1_ki * Z1_j
00798    //
00799    //   F_mj = M0_mj * (A# Z0)_j - (M1 A)_mj Z1_j
00800    //   G_mj = M0_mj * (Rsq# Z0)_j - (M1 Rsq)_mj Z1_j
00801    //
00802    // and
00803    //
00804    //   sum_ij [ (dX_m/dA_ij) * (dX_n/dA_ij) * Rsq_ij ] =
00805    //      sum_j [ M0_mj * M0_nj *  [ sum_i (Z0_i)^2 * Rsq_ij ] ]
00806    //    + sum_i [ M1_mi * M1_ni *  [ sum_j (Z1_j)^2 * Rsq_ij ] ]
00807    //    - sum_i [ M1_mi * H_ni + M1_ni * H_mi]
00808    // where:
00809    //   H_mi = Z0_i * sum_j [ M0_mj * Z1_j * Rsq_ij ]
00810    //
00811    // collect all contributions:
00812    //   Vxx_nm = r0 -r1 -r2 +r3 +r4 -r5 -r6
00813    //      r0 = sum_j [ F_mj * F_nj * SRsq_j ]
00814    //      r1 = sum_j [ G_mj * F_nj ]
00815    //      r2 = sum_j [ F_mj * G_nj ]
00816    //      r3 = sum_j [ M0_mj * M0_nj *  [ sum_i (Z0_i)^2 * Rsq_ij ] ]
00817    //      r4 = sum_i [ M1_mi * M1_ni *  [ sum_j (Z1_j)^2 * Rsq_ij ] ]
00818    //      r5 = sum_i [ M1_mi * H_ni ]
00819    //      r6 = sum_i [ M1_ni * H_mi ]
00820 
00821    //======================================================
00822    // calculate contributions containing matrices F and G
00823    // r0,r1,r2
00824    TMatrixDSparse *r=0;
00825    if(fDAinColRelSq && fDAinRelSq) {
00826       // calculate matrices (M1*A)_mj * Z1_j  and  (M1*Rsq)_mj * Z1_j
00827       TMatrixDSparse *M1A_Z1=MultiplyMSparseMSparse(m_1,fA);
00828       ScaleColumnsByVector(M1A_Z1,GetDXDAZ(1));
00829       TMatrixDSparse *M1Rsq_Z1=MultiplyMSparseMSparse(m_1,fDAinRelSq);
00830       ScaleColumnsByVector(M1Rsq_Z1,GetDXDAZ(1));
00831       // calculate vectors A#*Z0  and  Rsq#*Z0
00832       TMatrixDSparse *AtZ0 = MultiplyMSparseTranspMSparse(fA,GetDXDAZ(0));
00833       TMatrixDSparse *RsqZ0=
00834          MultiplyMSparseTranspMSparse(fDAinRelSq,GetDXDAZ(0));
00835       //calculate matrix F
00836       //   F_mj = M0_mj * (A# Z0)_j - (M1 A)_mj Z1_j
00837       TMatrixDSparse *F=new TMatrixDSparse(*m_0);
00838       ScaleColumnsByVector(F,AtZ0);
00839       AddMSparse(F,-1.0,M1A_Z1);
00840       //calculate matrix G
00841       //   G_mj = M0_mj * (Rsq# Z0)_j - (M1 Rsq)_mj Z1_j
00842       TMatrixDSparse *G=new TMatrixDSparse(*m_0);
00843       ScaleColumnsByVector(G,RsqZ0);
00844       AddMSparse(G,-1.0,M1Rsq_Z1);
00845       DeleteMatrix(&M1A_Z1);
00846       DeleteMatrix(&M1Rsq_Z1);
00847       DeleteMatrix(&AtZ0);
00848       DeleteMatrix(&RsqZ0);
00849       //      r0 = sum_j [ F_mj * F_nj * SRsq_j ]
00850       r=MultiplyMSparseMSparseTranspVector(F,F,fDAinColRelSq);
00851       //      r1 = sum_j [ G_mj * F_nj ]
00852       TMatrixDSparse *r1=MultiplyMSparseMSparseTranspVector(F,G,0);
00853       //      r2 = sum_j [ F_mj * G_nj ]
00854       TMatrixDSparse *r2=MultiplyMSparseMSparseTranspVector(G,F,0);
00855       // r = r0-r1-r2
00856       AddMSparse(r,-1.0,r1);
00857       AddMSparse(r,-1.0,r2);
00858       DeleteMatrix(&r1);
00859       DeleteMatrix(&r2);
00860       DeleteMatrix(&F);
00861       DeleteMatrix(&G);
00862    }
00863    //======================================================
00864    // calculate contribution
00865    //   sum_ij [ (dX_m/dA_ij) * (dX_n/dA_ij) * Rsq_ij ]
00866    //  (r3,r4,r5,r6)
00867    if(fDAinRelSq) {
00868       // (Z0_i)^2
00869       TMatrixDSparse Z0sq(*GetDXDAZ(0));
00870       const Int_t *Z0sq_rows=Z0sq.GetRowIndexArray();
00871       Double_t *Z0sq_data=Z0sq.GetMatrixArray();
00872       for(int index=0;index<Z0sq_rows[Z0sq.GetNrows()];index++) {
00873          Z0sq_data[index] *= Z0sq_data[index];
00874       }
00875       // Z0sqRsq =  sum_i (Z_i)^2 * Rsq_ij 
00876       TMatrixDSparse *Z0sqRsq=MultiplyMSparseTranspMSparse(fDAinRelSq,&Z0sq);
00877       //      r3 = sum_j [ M0_mj * M0_nj *  [ sum_i (Z0_i)^2 * Rsq_ij ] ]      
00878       TMatrixDSparse *r3=MultiplyMSparseMSparseTranspVector(m_0,m_0,Z0sqRsq);
00879       DeleteMatrix(&Z0sqRsq);
00880 
00881       // (Z1_j)^2
00882       TMatrixDSparse Z1sq(*GetDXDAZ(1));
00883       const Int_t *Z1sq_rows=Z1sq.GetRowIndexArray();
00884       Double_t *Z1sq_data=Z1sq.GetMatrixArray();
00885       for(int index=0;index<Z1sq_rows[Z1sq.GetNrows()];index++) {
00886          Z1sq_data[index] *= Z1sq_data[index];
00887       }
00888       // Z1sqRsq = sum_j (Z1_j)^2 * Rsq_ij ]
00889       TMatrixDSparse *Z1sqRsq=MultiplyMSparseMSparse(fDAinRelSq,&Z1sq);
00890       //      r4 = sum_i [ M1_mi * M1_ni *  [ sum_j (Z1_j)^2 * Rsq_ij ] ]
00891       TMatrixDSparse *r4=MultiplyMSparseMSparseTranspVector(m_1,m_1,Z1sqRsq);
00892       DeleteMatrix(&Z1sqRsq);
00893 
00894       // sum_j [ M0_mj * Z1_j * Rsq_ij ]
00895       TMatrixDSparse *H=MultiplyMSparseMSparseTranspVector
00896          (m_0,fDAinRelSq,GetDXDAZ(1));
00897       // H_mi = Z0_i * sum_j [ M0_mj * Z1_j * Rsq_ij ]
00898       ScaleColumnsByVector(H,GetDXDAZ(0));
00899       //      r5 = sum_i [ M1_mi * H_ni ]
00900       TMatrixDSparse *r5=MultiplyMSparseMSparseTranspVector(m_1,H,0);
00901       //      r6 = sum_i [ H_mi * M1_ni ]
00902       TMatrixDSparse *r6=MultiplyMSparseMSparseTranspVector(H,m_1,0);
00903       DeleteMatrix(&H);
00904       // r =  r0 -r1 -r2 +r3 +r4 +r5 +r6
00905       if(r) {
00906          AddMSparse(r,1.0,r3);
00907          DeleteMatrix(&r3);
00908       } else {
00909          r=r3;
00910          r3=0;
00911       }
00912       AddMSparse(r,1.0,r4);
00913       AddMSparse(r,-1.0,r5);
00914       AddMSparse(r,-1.0,r6);
00915       DeleteMatrix(&r4);
00916       DeleteMatrix(&r5);
00917       DeleteMatrix(&r6);
00918    }
00919    return r;
00920 }
00921 
00922 TMatrixDSparse *TUnfoldSys::PrepareCorrEmat
00923 (const TMatrixDSparse *m1,const TMatrixDSparse *m2,const TMatrixDSparse *dsys) {
00924    // propagate correlated systematic shift to output vector
00925    //   m1,m2 : coefficients for propagating the errors
00926    //   dsys : matrix of correlated shifts from this source
00927 
00928    // delta_m = 
00929    //   sum{i,j}   {
00930    //      ((*m1)(m,j) * (*fVYAx)(i) - (*m2)(m,i) * (*fX)(j))*dsys(i,j) }
00931    //   =    sum_j (*m1)(m,j)  sum_i dsys(i,j) * (*fVYAx)(i)
00932    //     -  sum_i (*m2)(m,i)  sum_j dsys(i,j) * (*fX)(j)
00933 
00934    TMatrixDSparse *dsysT_VYAx = MultiplyMSparseTranspMSparse(dsys,GetDXDAZ(0));
00935    TMatrixDSparse *delta =  MultiplyMSparseMSparse(m1,dsysT_VYAx);
00936    DeleteMatrix(&dsysT_VYAx);
00937    TMatrixDSparse *dsys_X = MultiplyMSparseMSparse(dsys,GetDXDAZ(1));
00938    TMatrixDSparse *delta2 = MultiplyMSparseMSparse(m2,dsys_X);
00939    DeleteMatrix(&dsys_X);
00940    AddMSparse(delta,-1.0,delta2);
00941    DeleteMatrix(&delta2);
00942    return delta;
00943 }
00944 
00945 void TUnfoldSys::SetTauError(Double_t delta_tau) {
00946    // set uncertainty on tau
00947    fDtau=delta_tau;
00948    DeleteMatrix(&fDeltaSysTau);
00949 }
00950 
00951 void TUnfoldSys::GetDeltaSysSource(TH1 *hist_delta,const char *name,
00952                                    const Int_t *binMap) {
00953    // calculate systematic shift from a given source
00954    //    ematrix: output
00955    //    source: name of the error source
00956    //    binMap: see method GetEmatrix()
00957    PrepareSysError();
00958    const TPair *named_emat=(const TPair *)fDeltaCorrX->FindObject(name);
00959    const TMatrixDSparse *delta=0;
00960    if(named_emat) {
00961       delta=(TMatrixDSparse *)named_emat->Value();
00962    }
00963    VectorMapToHist(hist_delta,delta,binMap);
00964 }
00965 
00966 void TUnfoldSys::GetDeltaSysBackgroundScale(TH1 *hist_delta,const char *source,
00967                                          const Int_t *binMap) {
00968    // get correlated shift induced by a background source
00969    //   delta: output shift vector histogram
00970    //   source: name of background source
00971    //   binMap: see method GetEmatrix()
00972    //   see PrepareSysError()
00973    PrepareSysError();
00974    const TPair *named_err=(const TPair *)fBgrErrCorrIn->FindObject(source);
00975    TMatrixDSparse *dx=0;
00976    if(named_err) {
00977       const TMatrixDSparse *dy=(TMatrixDSparse *)named_err->Value();
00978       dx=MultiplyMSparseMSparse(GetDXDY(),dy);
00979    }
00980    VectorMapToHist(hist_delta,dx,binMap);
00981 }
00982 
00983 void TUnfoldSys::GetDeltaSysTau(TH1 *hist_delta,const Int_t *binMap) {
00984    // calculate systematic shift from tau variation
00985    //    ematrix: output
00986    //    binMap: see method GetEmatrix()
00987    PrepareSysError();
00988    VectorMapToHist(hist_delta,fDeltaSysTau,binMap);
00989 }
00990 
00991 void TUnfoldSys::GetEmatrixSysSource(TH2 *ematrix,const char *name,
00992                                      const Int_t *binMap,Bool_t clearEmat) {
00993    // calculate systematic shift from a given source
00994    //    ematrix: output
00995    //    source: name of the error source
00996    //    binMap: see method GetEmatrix()
00997    //    clearEmat: set kTRUE to clear the histogram prior to adding the errors
00998    PrepareSysError();
00999    const TPair *named_emat=(const TPair *)fDeltaCorrX->FindObject(name);
01000    TMatrixDSparse *emat=0;
01001    if(named_emat) {
01002       const TMatrixDSparse *delta=(TMatrixDSparse *)named_emat->Value();
01003       emat=MultiplyMSparseMSparseTranspVector(delta,delta,0);
01004    }
01005    ErrorMatrixToHist(ematrix,emat,binMap,clearEmat);
01006    DeleteMatrix(&emat);
01007 }
01008 
01009 void TUnfoldSys::GetEmatrixSysBackgroundScale(TH2 *ematrix,const char *name,
01010                                               const Int_t *binMap,
01011                                               Bool_t clearEmat) {
01012    // calculate systematic shift from a given background scale error
01013    //    ematrix: output
01014    //    source: name of the error source
01015    //    binMap: see method GetEmatrix()
01016    //    clearEmat: set kTRUE to clear the histogram prior to adding the errors
01017    PrepareSysError();
01018    const TPair *named_err=(const TPair *)fBgrErrCorrIn->FindObject(name);
01019    TMatrixDSparse *emat=0;
01020    if(named_err) {
01021       const TMatrixDSparse *dy=(TMatrixDSparse *)named_err->Value();
01022       TMatrixDSparse *dx=MultiplyMSparseMSparse(GetDXDY(),dy);
01023       emat=MultiplyMSparseMSparseTranspVector(dx,dx,0);
01024       DeleteMatrix(&dx);
01025    }
01026    ErrorMatrixToHist(ematrix,emat,binMap,clearEmat);
01027    DeleteMatrix(&emat);
01028 }
01029 
01030 void TUnfoldSys::GetEmatrixSysTau(TH2 *ematrix,
01031                                   const Int_t *binMap,Bool_t clearEmat) {
01032    // calculate error matrix from error in regularisation parameter
01033    //    ematrix: output
01034    //    binMap: see method GetEmatrix()
01035    //    clearEmat: set kTRUE to clear the histogram prior to adding the errors
01036    PrepareSysError();
01037    TMatrixDSparse *emat=0;
01038    if(fDeltaSysTau) {
01039       emat=MultiplyMSparseMSparseTranspVector(fDeltaSysTau,fDeltaSysTau,0);
01040    }
01041    ErrorMatrixToHist(ematrix,emat,binMap,clearEmat);
01042    DeleteMatrix(&emat);
01043 }
01044 
01045 void TUnfoldSys::GetEmatrixInput(TH2 *ematrix,const Int_t *binMap,
01046                                      Bool_t clearEmat) {
01047    // calculate error matrix from error in input vector alone
01048    //    ematrix: output
01049    //    binMap: see method GetEmatrix()
01050    //    clearEmat: set kTRUE to clear the histogram prior to adding the errors
01051    GetEmatrixFromVyy(fVyyData,ematrix,binMap,clearEmat);
01052 }
01053 
01054 void TUnfoldSys::GetEmatrixSysBackgroundUncorr
01055 (TH2 *ematrix,const char *source,const Int_t *binMap,Bool_t clearEmat) {
01056    // calculate error matrix contribution originating from uncorrelated errors
01057    // of one background source
01058    //    ematrix: output
01059    //    source: name of the error source
01060    //    binMap: see method GetEmatrix()
01061    //    clearEmat: set kTRUE to clear the histogram prior to adding the errors
01062    const TPair *named_err=(const TPair *)fBgrErrCorrIn->FindObject(source);
01063    const TMatrixDSparse *emat=0;
01064    if(named_err) emat=(TMatrixDSparse *)named_err->Value();
01065    GetEmatrixFromVyy(emat,ematrix,binMap,clearEmat);
01066 }
01067 
01068 void TUnfoldSys::GetEmatrixFromVyy(const TMatrixDSparse *vyy,TH2 *ematrix,
01069                                    const Int_t *binMap,Bool_t clearEmat) {
01070    // propagate error matrix vyy to the result
01071    //    vyy: error matrix on input data fY
01072    //    ematrix: output
01073    //    binMap: see method GetEmatrix()
01074    //    clearEmat: set kTRUE to clear the histogram prior to adding the errors
01075    PrepareSysError();
01076    TMatrixDSparse *em=0;
01077    if(vyy) {
01078       TMatrixDSparse *dxdyVyy=MultiplyMSparseMSparse(GetDXDY(),vyy);
01079       em=MultiplyMSparseMSparseTranspVector(dxdyVyy,GetDXDY(),0);
01080       DeleteMatrix(&dxdyVyy);
01081    }
01082    ErrorMatrixToHist(ematrix,em,binMap,clearEmat);
01083    DeleteMatrix(&em);
01084 }
01085 
01086 void TUnfoldSys::GetEmatrixTotal(TH2 *ematrix,const Int_t *binMap) {
01087    // get total error including statistical error
01088    //    ematrix: output
01089    //    binMap: see method GetEmatrix()
01090    GetEmatrix(ematrix,binMap);  // (stat)+(d)+(e)
01091    GetEmatrixSysUncorr(ematrix,binMap,kFALSE); // (a)
01092    TMapIter sysErrPtr(fDeltaCorrX);
01093    const TObject *key;
01094    
01095    for(key=sysErrPtr.Next();key;key=sysErrPtr.Next()) {
01096       GetEmatrixSysSource(ematrix,
01097                           ((const TObjString *)key)->GetString(),
01098                           binMap,kFALSE); // (b)
01099    }
01100    GetEmatrixSysTau(ematrix,binMap,kFALSE); // (c)
01101 }
01102 
01103 Double_t TUnfoldSys::GetChi2Sys(void) {
01104    // calculate total chi**2 including systematic errors
01105    PrepareSysError();
01106    // errors from input vector and from background subtraction
01107    TMatrixDSparse emat_sum(*fVyy);
01108    // uncorrelated systematic error
01109    AddMSparse(&emat_sum,1.0,fEmatUncorrAx);
01110    TMapIter sysErrPtr(fDeltaCorrAx);
01111    const TObject *key;
01112    // correlated su=ystematic errors
01113    for(key=sysErrPtr.Next();key;key=sysErrPtr.Next()) {
01114       const TMatrixDSparse *delta=(TMatrixDSparse *)
01115 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,20,00)
01116                  ((const TPair *)*sysErrPtr)->Value()
01117 #else
01118          fDeltaCorrAx->GetValue(((const TObjString *)key)
01119                                 ->GetString())
01120 #endif
01121          ;
01122       TMatrixDSparse *emat=MultiplyMSparseMSparseTranspVector(delta,delta,0);
01123       AddMSparse(&emat_sum,1.0,emat);
01124       DeleteMatrix(&emat);
01125    }
01126    // error on tau
01127    if(fDeltaSysTau) {
01128       TMatrixDSparse *Adx_tau=MultiplyMSparseMSparse(fA,fDeltaSysTau);
01129       TMatrixDSparse *emat_tau=
01130          MultiplyMSparseMSparseTranspVector(Adx_tau,Adx_tau,0);
01131       DeleteMatrix(&Adx_tau);
01132       AddMSparse(&emat_sum,1.0,emat_tau);
01133       DeleteMatrix(&emat_tau);
01134    }
01135 
01136    TMatrixD *v=InvertMSparse(&emat_sum);
01137    TMatrixD dy(*fY, TMatrixD::kMinus, *GetAx());
01138    Double_t r=0.0;
01139    for(Int_t i=0;i<v->GetNrows();i++) {
01140       for(Int_t j=0;j<v->GetNcols();j++) {
01141          r += dy(i,0) * (*v)(i,j) * dy(j,0);
01142       }
01143    }
01144    DeleteMatrix(&v);
01145    return r;
01146 }
01147 
01148 void TUnfoldSys::ScaleColumnsByVector
01149 (TMatrixDSparse *m,const TMatrixTBase<Double_t> *v) const {
01150    // scale columns of m by the corresponding rows of v
01151    // input:
01152    //   m:  pointer to sparse matrix of dimension NxM
01153    //   v:  pointer to matrix of dimension Mx1
01154    if((m->GetNcols() != v->GetNrows())||(v->GetNcols()!=1)) {
01155       Fatal("ScaleColumnsByVector error",
01156             "matrix cols/vector rows %d!=%d OR vector cols %d !=1\n",
01157             m->GetNcols(),v->GetNrows(),v->GetNcols());
01158    }
01159    const Int_t *rows_m=m->GetRowIndexArray();
01160    const Int_t *cols_m=m->GetColIndexArray();
01161    Double_t *data_m=m->GetMatrixArray();
01162    const TMatrixDSparse *v_sparse=dynamic_cast<const TMatrixDSparse *>(v);
01163    if(v_sparse) {
01164       const Int_t *rows_v=v_sparse->GetRowIndexArray();
01165       const Double_t *data_v=v_sparse->GetMatrixArray();
01166       for(Int_t i=0;i<m->GetNrows();i++) {
01167          for(Int_t index_m=rows_m[i];index_m<rows_m[i+1];index_m++) {
01168             Int_t j=cols_m[index_m];
01169             Int_t index_v=rows_v[j];
01170             if(index_v<rows_v[j+1]) {
01171                data_m[index_m] *= data_v[index_v];
01172             } else {
01173                data_m[index_m] =0.0;
01174             }
01175          }
01176       }
01177    } else {
01178       for(Int_t i=0;i<m->GetNrows();i++) {
01179          for(Int_t index=rows_m[i];index<rows_m[i+1];index++) {
01180             data_m[index] *= (*v)(cols_m[index],0);
01181          }
01182       }
01183    }
01184 }
01185 
01186 void TUnfoldSys::VectorMapToHist(TH1 *hist_delta,const TMatrixDSparse *delta,
01187                                  const Int_t *binMap) {
01188    // sum over bins of *delta, as defined in binMap,fXToHist
01189    //   hist_delta: histogram to return summed vector
01190    //   delta: vector to sum and remap
01191    Int_t nbin=hist_delta->GetNbinsX();
01192    Double_t *c=new Double_t[nbin+2];
01193    for(Int_t i=0;i<nbin+2;i++) {
01194       c[i]=0.0;
01195    }
01196    if(delta) {
01197       Int_t binMapSize = fHistToX.GetSize();
01198       const Double_t *delta_data=delta->GetMatrixArray();
01199       const Int_t *delta_rows=delta->GetRowIndexArray();
01200       for(Int_t i=0;i<binMapSize;i++) {
01201          Int_t destBinI=binMap ? binMap[i] : i;
01202          Int_t srcBinI=fHistToX[i];
01203          if((destBinI>=0)&&(destBinI<nbin+2)&&(srcBinI>=0)) {
01204             Int_t index=delta_rows[srcBinI];
01205             if(index<delta_rows[srcBinI+1]) {
01206                c[destBinI]+=delta_data[index];
01207             }
01208          }
01209       }
01210    }
01211    for(Int_t i=0;i<nbin+2;i++) {
01212       hist_delta->SetBinContent(i,c[i]);
01213       hist_delta->SetBinError(i,0.0);
01214    }
01215    delete[] c;
01216 }

Generated on Tue Jul 5 14:24:23 2011 for ROOT_528-00b_version by  doxygen 1.5.1