From 49bd482b4e7cce1d631c2ad77560739d8e3e466e Mon Sep 17 00:00:00 2001 From: Lukasz Kreczko Date: Tue, 20 Jan 2015 09:59:51 +0000 Subject: [PATCH 01/13] first version of tau unfolding --- include/TauSVDUnfold.h | 43 +++++++ src/TauSVDUnfold.cxx | 255 +++++++++++++++++++++++++++++++++++++ test/TauSVDUnfoldTests.cpp | 14 ++ 3 files changed, 312 insertions(+) create mode 100644 include/TauSVDUnfold.h create mode 100644 src/TauSVDUnfold.cxx create mode 100644 test/TauSVDUnfoldTests.cpp diff --git a/include/TauSVDUnfold.h b/include/TauSVDUnfold.h new file mode 100644 index 0000000..061efac --- /dev/null +++ b/include/TauSVDUnfold.h @@ -0,0 +1,43 @@ +/* + * TauSVDUnfold.h + * + * Created on: 31 Dec 2014 + * Author: phxlk + */ + +#ifndef TAUSVDUNFOLD_H_ +#define TAUSVDUNFOLD_H_ +#include "TSVDUnfold_local.h" + +class TauSVDUnfold: public TSVDUnfold_local { +public: + TauSVDUnfold(const TH1D* bdat, const TH1D* bini, const TH1D* xini, const TH2D* Adet); + TauSVDUnfold(const TH1D* bdat, TH2D* Bcov, const TH1D* bini, const TH1D* xini, const TH2D* Adet); + TauSVDUnfold(const TauSVDUnfold& other); + virtual ~TauSVDUnfold(); + + void SetTau(double tau); + double GetTau() const; + + // Get Curvature of last unfolding run + double GetCurv() const; + + // Get Histo of Weights of LAST Unfolding run + TH1D* GetWeights() const; + + // Do the unfolding + // "tau" - number of singular values used (regularisation) + TH1D* Unfold(double tau); + + double kToTau(int kreg) const; + +protected: + double fTau; + double fCurv; + TH1D* fWeights; + TVectorD fASV; + + ClassDef( TauSVDUnfold, 0 ); +}; + +#endif /* TAUSVDUNFOLD_H_ */ diff --git a/src/TauSVDUnfold.cxx b/src/TauSVDUnfold.cxx new file mode 100644 index 0000000..0c1d8a0 --- /dev/null +++ b/src/TauSVDUnfold.cxx @@ -0,0 +1,255 @@ +/* + * TauSVDUnfold.cxx + * + * Created on: 31 Dec 2014 + * Author: kreczko + */ + +#include "../include/TauSVDUnfold.h" +#include "TDecompSVD.h" +#include "TMath.h" +#include "TH1D.h" + +TauSVDUnfold::TauSVDUnfold(const TH1D* bdat, const TH1D* bini, const TH1D* xini, const TH2D* Adet) : + TSVDUnfold_local(bdat, bini, xini, Adet), + fTau(0.), + fCurv(-1.), + fWeights(), + fASV() { +} + +TauSVDUnfold::TauSVDUnfold(const TH1D* bdat, TH2D* Bcov, const TH1D* bini, const TH1D* xini, const TH2D* Adet) : + TSVDUnfold_local(bdat, Bcov, bini, xini, Adet), + fTau(0.), + fCurv(-1.), + fWeights(), + fASV() { + +} +TauSVDUnfold::TauSVDUnfold(const TauSVDUnfold& other) : + TSVDUnfold_local(other), + fTau(other.GetTau()), + fCurv(other.GetCurv()), + fWeights(other.GetWeights()), + fASV() { + +} + +TH1D* TauSVDUnfold::GetWeights() const { + return fWeights; +} + +double TauSVDUnfold::GetTau() const { + return fTau; +} + +void TauSVDUnfold::SetTau(double tau) { + fTau = tau; +} + +double TauSVDUnfold::GetCurv() const { + return fCurv; +} + +TauSVDUnfold::~TauSVDUnfold() { +} + +TH1D* TauSVDUnfold::Unfold(double tau) { + fTau = tau; + // Make the histos + if (!fToyMode && !fMatToyMode) + InitHistos(); + + // Create vectors and matrices + TVectorD vb(fNdim), vbini(fNdim), vxini(fNdim), vberr(fNdim); + TMatrixD mB(fNdim, fNdim), mA(fNdim, fNdim), mCurv(fNdim, fNdim), mC(fNdim, fNdim); + + Double_t eps = 1e-12; + Double_t sreg; + + // Copy histogams entries into vector + if (fToyMode) { + H2V(fToyhisto, vb); + H2Verr(fToyhisto, vberr); + } else { + H2V(fBdat, vb); + H2Verr(fBdat, vberr); + } + + H2M(fBcov, mB); + H2V(fBini, vbini); + H2V(fXini, vxini); + if (fMatToyMode) + H2M(fToymat, mA); + else + H2M(fAdet, mA); + + // Fill and invert the second derivative matrix + FillCurvatureMatrix(mCurv, mC); + + // Inversion of mC by help of SVD + TDecompSVD CSVD(mC); + TMatrixD CUort = CSVD.GetU(); + TMatrixD CVort = CSVD.GetV(); + TVectorD CSV = CSVD.GetSig(); + + TMatrixD CSVM(fNdim, fNdim); + for (Int_t i = 0; i < fNdim; i++) + CSVM(i, i) = 1 / CSV(i); + + CUort.Transpose(CUort); + TMatrixD mCinv = (CVort * CSVM) * CUort; + + // // Rescale matrix and vectors by error of data vector. Replaced by using full covmat now + // vbini = VecDiv ( vbini, vberr ); + // vb = VecDiv ( vb, vberr, 1 ); + // mA = MatDivVec( mA, vberr, 1 ); + // vberr = VecDiv ( vberr, vberr, 1 ); + + //Rescale using the data covariance matrix + TDecompSVD BSVD(mB); + TMatrixD QT = BSVD.GetU(); + QT.Transpose(QT); + TVectorD B2SV = BSVD.GetSig(); + TVectorD BSV(B2SV); + + for (int i = 0; i < fNdim; i++) { + BSV(i) = TMath::Sqrt(B2SV(i)); + } + TMatrixD mAtmp(fNdim, fNdim); + TVectorD vbtmp(fNdim); + mAtmp *= 0; + vbtmp *= 0; + for (int i = 0; i < fNdim; i++) { + for (int j = 0; j < fNdim; j++) { + if (BSV(i)) { + vbtmp(i) += QT(i, j) * vb(j) / BSV(i); + } + for (int m = 0; m < fNdim; m++) { + if (BSV(i)) { + mAtmp(i, j) += QT(i, m) * mA(m, j) / BSV(i); + } + } + } + } + mA = mAtmp; + vb = vbtmp; + + // Singular value decomposition and matrix operations + TDecompSVD ASVD(mA * mCinv); + TMatrixD Uort = ASVD.GetU(); + TMatrixD Vort = ASVD.GetV(); + TVectorD ASV = ASVD.GetSig(); + fASV = ASV; + + if (!fToyMode && !fMatToyMode) { + V2H(ASV, *fSVHist); + } + + TMatrixD Vreg = mCinv * Vort; + + Uort.Transpose(Uort); + TVectorD vd = Uort * vb; + + if (!fToyMode && !fMatToyMode) { + V2H(vd, *fDHist); + } + + Int_t k = GetKReg() - 1; + + TVectorD vx(fNdim); // Return variable + + // Damping factors + TVectorD vdz(fNdim); + TMatrixD Z(fNdim, fNdim); + for (Int_t i = 0; i < fNdim; i++) { + if (ASV(i) < ASV(0) * eps) + sreg = ASV(0) * eps; + else + sreg = ASV(i); + + vdz(i) = sreg / (sreg * sreg + fTau * fTau); + Z(i, i) = vdz(i) * vdz(i); + } + + TVectorD vz = CompProd(vd, vdz); + + TMatrixD VortT(Vort); + VortT.Transpose(VortT); + TMatrixD W = mCinv * Vort * Z * VortT * mCinv; + + TMatrixD Xtau(fNdim, fNdim); + TMatrixD Xinv(fNdim, fNdim); + Xtau *= 0; + Xinv *= 0; + for (Int_t i = 0; i < fNdim; i++) { + for (Int_t j = 0; j < fNdim; j++) { + Xtau(i, j) = vxini(i) * vxini(j) * W(i, j); + + double a = 0; + for (Int_t m = 0; m < fNdim; m++) { + a += mA(m, i) * mA(m, j); + } + if (vxini(i) * vxini(j)) + Xinv(i, j) = a / vxini(i) / vxini(j); + } + } + + // Compute the weights + TVectorD vw = Vreg * vz; + + // DAVID + vx = CompProd(vw, vxini); + + if (fNormalize) { // Scale result to unit area + Double_t scale = vx.Sum(); + if (scale > 0) { + vx *= 1.0 / scale; + Xtau *= 1. / scale / scale; + Xinv *= scale * scale; + } + } + + if (!fToyMode && !fMatToyMode) { + M2H(Xtau, *fXtau); + M2H(Xinv, *fXinv); + } + + // DAVID + // Speichere die Kruemmung ab! + fCurv = GetCurvature(vw, mCurv); + + // Get Curvature and also chi2 in case of MC unfolding + if (!fToyMode && !fMatToyMode) { + Info("Unfold", "Unfolding param: %i", k + 1); + Info("Unfold", "Curvature of weight distribution: %f", fCurv); + } + + TH1D* h = (TH1D*) fBdat->Clone("unfoldingresult"); + for (int i = 1; i <= fNdim; i++) { + h->SetBinContent(i, 0.); + h->SetBinError(i, 0.); + } + V2H(vx, *h); + + // DAVID + // Save the weights + // but only if this is not a "Toy"-Run + if (!fToyMode && !fMatToyMode) { + if (fWeights != NULL) { + delete fWeights; + fWeights = NULL; + } + fWeights = (TH1D*) fBdat->Clone("Weights"); + V2H(vw, *fWeights); + } + + return h; +} + +double TauSVDUnfold::kToTau(int kreg) const { + double tau(0.); + if (fASV.NonZeros() == 0 && kreg > 0) + tau = fASV(kreg); + return tau; +} diff --git a/test/TauSVDUnfoldTests.cpp b/test/TauSVDUnfoldTests.cpp new file mode 100644 index 0000000..b221502 --- /dev/null +++ b/test/TauSVDUnfoldTests.cpp @@ -0,0 +1,14 @@ +/* + * File: TauSVDUnfoldTests.cpp + * Author: ale + * + * Created on August 13, 2014, 6:49 PM + */ +#include + +BOOST_AUTO_TEST_SUITE (TauSVDUnfoldTestSuite) +BOOST_AUTO_TEST_CASE(Test1) { + +} + +BOOST_AUTO_TEST_SUITE_END() From b2812fbea9e5428872d1478ccddaca717d3cecbb Mon Sep 17 00:00:00 2001 From: kreczko Date: Mon, 16 Feb 2015 10:41:26 +0000 Subject: [PATCH 02/13] updated header location and added LinkDef --- include/RooUnfold_LinkDef.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/RooUnfold_LinkDef.h b/include/RooUnfold_LinkDef.h index 97bc25c..4474cfa 100644 --- a/include/RooUnfold_LinkDef.h +++ b/include/RooUnfold_LinkDef.h @@ -15,6 +15,7 @@ #pragma link C++ class RooUnfoldParms+; #pragma link C++ class RooUnfoldInvert+; #pragma link C++ class RooUnfoldTUnfold+; +#pragma link C++ class TauSVDUnfold+; //#pragma link C++ class RooUnfoldDagostini+; #endif From f4f2a90ca5aca570503f1a96a7b5c1eed602354f Mon Sep 17 00:00:00 2001 From: kreczko Date: Mon, 16 Feb 2015 13:55:23 +0000 Subject: [PATCH 03/13] added local version of TSVDUnfold --- include/RooUnfoldSvd.h | 9 +- include/RooUnfold_LinkDef.h | 1 + include/TSVDUnfold_local.h | 162 +++++++ src/RooUnfoldSvd.cxx | 34 +- src/TSVDUnfold_local.cxx | 880 ++++++++++++++++++++++++++++++++++++ 5 files changed, 1073 insertions(+), 13 deletions(-) create mode 100644 include/TSVDUnfold_local.h create mode 100644 src/TSVDUnfold_local.cxx diff --git a/include/RooUnfoldSvd.h b/include/RooUnfoldSvd.h index 89d63ae..5910e08 100644 --- a/include/RooUnfoldSvd.h +++ b/include/RooUnfoldSvd.h @@ -18,7 +18,7 @@ class RooUnfoldResponse; class TH1; class TH1D; class TH2D; -class TSVDUnfold; +class TSVDUnfold_local; class RooUnfoldSvd : public RooUnfold { @@ -38,6 +38,8 @@ class RooUnfoldSvd : public RooUnfold { RooUnfoldSvd (const RooUnfoldResponse* res, const TH1* meas, Int_t kreg= 0, Int_t ntoyssvd= 1000, const char* name= 0, const char* title= 0); + RooUnfoldSvd (const RooUnfoldResponse* res, const TH1* meas, double taureg, Int_t ntoyssvd= 1000, + const char* name= 0, const char* title= 0); void SetKterm (Int_t kreg); void SetNtoysSVD (Int_t ntoyssvd); @@ -47,7 +49,7 @@ class RooUnfoldSvd : public RooUnfold { virtual void SetRegParm (Double_t parm); virtual Double_t GetRegParm() const; virtual void Reset(); - TSVDUnfold* Impl(); + TSVDUnfold_local* Impl(); protected: void Assign (const RooUnfoldSvd& rhs); // implementation of assignment operator @@ -62,8 +64,9 @@ class RooUnfoldSvd : public RooUnfold { protected: // instance variables - TSVDUnfold* _svd; //! Implementation in TSVDUnfold object (no streamer) + TSVDUnfold_local* _svd; //! Implementation in TSVDUnfold object (no streamer) Int_t _kreg; + double _taureg; Int_t _nb; Int_t _ntoyssvd; diff --git a/include/RooUnfold_LinkDef.h b/include/RooUnfold_LinkDef.h index 4474cfa..52e1636 100644 --- a/include/RooUnfold_LinkDef.h +++ b/include/RooUnfold_LinkDef.h @@ -16,6 +16,7 @@ #pragma link C++ class RooUnfoldInvert+; #pragma link C++ class RooUnfoldTUnfold+; #pragma link C++ class TauSVDUnfold+; +#pragma link C++ class TSVDUnfold_local+; //#pragma link C++ class RooUnfoldDagostini+; #endif diff --git a/include/TSVDUnfold_local.h b/include/TSVDUnfold_local.h new file mode 100644 index 0000000..d81bc14 --- /dev/null +++ b/include/TSVDUnfold_local.h @@ -0,0 +1,162 @@ +// Author: Kerstin Tackmann, Andreas Hoecker, Heiko Lacker + +/********************************************************************************** + * * + * Project: TSVDUnfold_local - data unfolding based on Singular Value Decomposition * + * Package: ROOT * + * Class : TSVDUnfold_local * + * * + * Description: * + * Single class implementation of SVD data unfolding based on: * + * A. Hoecker, V. Kartvelishvili, * + * "SVD approach to data unfolding" * + * NIM A372, 469 (1996) [hep-ph/9509307] * + * * + * Authors: * + * Kerstin Tackmann - CERN, Switzerland * + * Andreas Hoecker - CERN, Switzerland * + * Heiko Lacker - Humboldt U, Germany * + * * + * Copyright (c) 2010: * + * CERN, Switzerland * + * Humboldt University, Germany * + * * + **********************************************************************************/ + +////////////////////////////////////////////////////////////////////////// +// // +// TSVDUnfold_local // +// // +// Data unfolding using Singular Value Decomposition (hep-ph/9509307) // +// Authors: Kerstin Tackmann, Andreas Hoecker, Heiko Lacker // +// // +////////////////////////////////////////////////////////////////////////// + +#ifndef TSVDUNFOLD_LOCAL_H +#define TSVDUNFOLD_LOCAL_H + +#ifndef ROOT_TObject +#include "TObject.h" +#endif +#ifndef ROOT_TMatrixD +#include "TMatrixD.h" +#endif +#ifndef ROOT_TVectorD +#include "TVectorD.h" +#endif +#ifndef ROOT_TMatrixDSym +#include "TMatrixDSym.h" +#endif + +class TH1D; +class TH2D; + +class TSVDUnfold_local : public TObject { + +public: + + // Constructor + // Initialisation of unfolding + // "bdat" - measured data distribution (number of events) + // "Bcov" - covariance matrix for measured data distribution + // "bini" - reconstructed MC distribution (number of events) + // "xini" - truth MC distribution (number of events) + // "Adet" - detector response matrix (number of events) + TSVDUnfold_local( const TH1D* bdat, const TH1D* bini, const TH1D* xini, const TH2D* Adet ); + TSVDUnfold_local( const TH1D* bdat, TH2D* Bcov, const TH1D* bini, const TH1D* xini, const TH2D* Adet ); + TSVDUnfold_local( const TSVDUnfold_local& other ); + + // Destructor + virtual ~TSVDUnfold_local(); + + // Set option to normalize unfolded spectrum to unit area + // "normalize" - switch + void SetNormalize ( Bool_t normalize ) { fNormalize = normalize; } + + // Do the unfolding + // "kreg" - number of singular values used (regularisation) + TH1D* Unfold ( Int_t kreg ); + + // Determine for given input error matrix covariance matrix of unfolded + // spectrum from toy simulation + // "cov" - covariance matrix on the measured spectrum, to be propagated + // "ntoys" - number of pseudo experiments used for the propagation + // "seed" - seed for pseudo experiments + TH2D* GetUnfoldCovMatrix( const TH2D* cov, Int_t ntoys, Int_t seed = 1 ); + + // Determine covariance matrix of unfolded spectrum from finite statistics in + // response matrix + // "ntoys" - number of pseudo experiments used for the propagation + // "seed" - seed for pseudo experiments + TH2D* GetAdetCovMatrix( Int_t ntoys, Int_t seed=1 ); + + // Regularisation parameter + Int_t GetKReg() const { return fKReg; } + + // Obtain the distribution of |d| (for determining the regularization) + TH1D* GetD() const; + + // Obtain the distribution of singular values + TH1D* GetSV() const; + + // Obtain the computed regularized covariance matrix + TH2D* GetXtau() const; + + // Obtain the computed inverse of the covariance matrix + TH2D* GetXinv() const; + + //Obtain the covariance matrix on the data + TH2D* GetBCov() const; + + // Helper functions + Double_t ComputeChiSquared( const TH1D& truspec, const TH1D& unfspec ); + +// only difference to TSVDUnfold in ROOT +protected: + + // Helper functions for vector and matrix operations + void FillCurvatureMatrix( TMatrixD& tCurv, TMatrixD& tC ) const; + static Double_t GetCurvature ( const TVectorD& vec, const TMatrixD& curv ); + + void InitHistos ( ); + + // Helper functions + static void H2V ( const TH1D* histo, TVectorD& vec ); + static void H2Verr ( const TH1D* histo, TVectorD& vec ); + static void V2H ( const TVectorD& vec, TH1D& histo ); + static void H2M ( const TH2D* histo, TMatrixD& mat ); + static void M2H ( const TMatrixD& mat, TH2D& histo ); + static TMatrixD MatDivVec( const TMatrixD& mat, const TVectorD& vec, Int_t zero=0 ); + static TVectorD CompProd ( const TVectorD& vec1, const TVectorD& vec2 ); + + static TVectorD VecDiv ( const TVectorD& vec1, const TVectorD& vec2, Int_t zero = 0 ); + static void RegularisedSymMatInvert( TMatrixDSym& mat, Double_t eps = 1e-3 ); + + // Class members + Int_t fNdim; //! Truth and reconstructed dimensions + Int_t fDdim; //! Derivative for curvature matrix + Bool_t fNormalize; //! Normalize unfolded spectrum to 1 + Int_t fKReg; //! Regularisation parameter + TH1D* fDHist; //! Distribution of d (for checking regularization) + TH1D* fSVHist; //! Distribution of singular values + TH2D* fXtau; //! Computed regularized covariance matrix + TH2D* fXinv; //! Computed inverse of covariance matrix + + // Input histos + const TH1D* fBdat; // measured distribution (data) + TH2D* fBcov; // covariance matrix of measured distribution (data) + const TH1D* fBini; // reconstructed distribution (MC) + const TH1D* fXini; // truth distribution (MC) + const TH2D* fAdet; // Detector response matrix + + // Evaluation of covariance matrices + TH1D* fToyhisto; //! Toy MC histogram + TH2D* fToymat; //! Toy MC detector response matrix + Bool_t fToyMode; //! Internal switch for covariance matrix propagation + Bool_t fMatToyMode; //! Internal switch for evaluation of statistical uncertainties from response matrix + + + ClassDef( TSVDUnfold_local, 0 ) // Data unfolding using Singular Value Decomposition (hep-ph/9509307) +}; + +#endif diff --git a/src/RooUnfoldSvd.cxx b/src/RooUnfoldSvd.cxx index 648ece9..71c7304 100644 --- a/src/RooUnfoldSvd.cxx +++ b/src/RooUnfoldSvd.cxx @@ -34,7 +34,7 @@ END_HTML */ #include "TH2.h" #include "TVectorD.h" #include "TMatrixD.h" -#include "TSVDUnfold.h" +#include "../include/TauSVDUnfold.h" #include "../include/RooUnfoldResponse.h" @@ -52,13 +52,26 @@ RooUnfoldSvd::RooUnfoldSvd (const RooUnfoldSvd& rhs) CopyData (rhs); } -RooUnfoldSvd::RooUnfoldSvd (const RooUnfoldResponse* res, const TH1* meas, Int_t kreg, Int_t ntoyssvd, - const char* name, const char* title) - : RooUnfold (res, meas, name, title), _kreg(kreg ? kreg : res->GetNbinsTruth()/2), _ntoyssvd(ntoyssvd) -{ - // Constructor with response matrix object and measured unfolding input histogram. - // The regularisation parameter is kreg. - Init(); +RooUnfoldSvd::RooUnfoldSvd(const RooUnfoldResponse* res, const TH1* meas, Int_t kreg, Int_t ntoyssvd, const char* name, + const char* title) : + RooUnfold(res, meas, name, title), + _kreg(kreg ? kreg : res->GetNbinsTruth() / 2), + _taureg(-1.), + _ntoyssvd(ntoyssvd) { + // Constructor with response matrix object and measured unfolding input histogram. + // The regularisation parameter is kreg. + Init(); +} + +RooUnfoldSvd::RooUnfoldSvd(const RooUnfoldResponse* res, const TH1* meas, double taureg, Int_t ntoyssvd, const char* name, + const char* title) : + RooUnfold(res, meas, name, title), + _kreg(-1), + _taureg(taureg ? taureg: 0.), + _ntoyssvd(ntoyssvd) { + // Constructor with response matrix object and measured unfolding input histogram. + // The regularisation parameter is kreg. + Init(); } RooUnfoldSvd* @@ -107,10 +120,11 @@ void RooUnfoldSvd::CopyData (const RooUnfoldSvd& rhs) { _kreg= rhs._kreg; + _taureg = rhs._kreg; _ntoyssvd= rhs._ntoyssvd; } -TSVDUnfold* +TSVDUnfold_local* RooUnfoldSvd::Impl() { return _svd; @@ -159,7 +173,7 @@ RooUnfoldSvd::Unfold() if (_verbose>=1) cout << "SVD init " << _reshist->GetNbinsX() << " x " << _reshist->GetNbinsY() << " bins, kreg=" << _kreg << endl; - _svd= new TSVDUnfold (_meas1d, _train1d, _truth1d, _reshist); + _svd= new TauSVDUnfold (_meas1d, _train1d, _truth1d, _reshist); TH1D* rechist= _svd->Unfold (_kreg); diff --git a/src/TSVDUnfold_local.cxx b/src/TSVDUnfold_local.cxx new file mode 100644 index 0000000..dedb9ff --- /dev/null +++ b/src/TSVDUnfold_local.cxx @@ -0,0 +1,880 @@ +// Author: Kerstin Tackmann, Andreas Hoecker, Heiko Lacker + +/********************************************************************************** + * * + * Project: TSVDUnfold_local - data unfolding based on Singular Value Decomposition * + * Package: ROOT * + * Class : TSVDUnfold_local * + * * + * Description: * + * Single class implementation of SVD data unfolding based on: * + * A. Hoecker, V. Kartvelishvili, * + * "SVD approach to data unfolding" * + * NIM A372, 469 (1996) [hep-ph/9509307] * + * * + * Authors: * + * Kerstin Tackmann - CERN, Switzerland * + * Andreas Hoecker - CERN, Switzerland * + * Heiko Lacker - Humboldt U, Germany * + * * + * Copyright (c) 2010: * + * CERN, Switzerland * + * Humboldt University, Germany * + * * + **********************************************************************************/ + +//_______________________________________________________________________ +/* Begin_Html +

SVD Approach to Data Unfolding

+

+ Reference: Nucl. Instrum. Meth. A372, 469 (1996) [hep-ph/9509307] +

+ TSVDUnfold_local implements the singular value decomposition based unfolding method (see reference). Currently, the unfolding of one-dimensional histograms is supported, with the same number of bins for the measured and the unfolded spectrum. +

+ The unfolding procedure is based on singular value decomposition of the response matrix. The regularisation of the unfolding is implemented via a discrete minimum-curvature condition. +

+ Monte Carlo inputs: +

    +
  • xini: true underlying spectrum (TH1D, n bins) +
  • bini: reconstructed spectrum (TH1D, n bins) +
  • Adet: response matrix (TH2D, nxn bins) +
+ Consider the unfolding of a measured spectrum bdat with covariance matrix Bcov (if not passed explicitly, a diagonal covariance will be built given the errors of bdat). The corresponding spectrum in the Monte Carlo is given by bini, with the true underlying spectrum given by xini. The detector response is described by Adet, with Adet filled with events (not probabilities) with the true observable on the y-axis and the reconstructed observable on the x-axis. +

+ The measured distribution can be unfolded for any combination of resolution, efficiency and acceptance effects, provided an appropriate definition of xini and Adet.

+

+ The unfolding can be performed by +

    +
    + TSVDUnfold_local *tsvdunf = new TSVDUnfold_local( bdat, Bcov, bini, xini, Adet );
    + TH1D* unfresult = tsvdunf->Unfold( kreg );
    + 
    +
+ where kreg determines the regularisation of the unfolding. In general, overregularisation (too small kreg) will bias the unfolded spectrum towards the Monte Carlo input, while underregularisation (too large kreg) will lead to large fluctuations in the unfolded spectrum. The optimal regularisation can be determined following guidelines in Nucl. Instrum. Meth. A372, 469 (1996) [hep-ph/9509307] using the distribution of the |d_i|<\tt> that can be obtained by tsvdunf->GetD() and/or using pseudo-experiments. +

+ Covariance matrices on the measured spectrum (for either the total uncertainties or individual sources of uncertainties) can be propagated to covariance matrices using the GetUnfoldCovMatrix method, which uses pseudo experiments for the propagation. In addition, GetAdetCovMatrix allows for the propagation of the statistical uncertainties on the response matrix using pseudo experiments. The covariance matrix corresponding to Bcov is also computed as described in Nucl. Instrum. Meth. A372, 469 (1996) [hep-ph/9509307] and can be obtained from tsvdunf->GetXtau() and its (regularisation independent) inverse from tsvdunf->GetXinv(). The distribution of singular values can be retrieved using tsvdunf->GetSV(). +

+ See also the tutorial for a toy example. + End_Html */ +//_______________________________________________________________________ + + +#include + +#include "../include/TSVDUnfold_local.h" +#include "TH1D.h" +#include "TH2D.h" +#include "TDecompSVD.h" +#include "TRandom3.h" +#include "TMath.h" + +ClassImp(TSVDUnfold_local) + +using namespace std; + +//_______________________________________________________________________ +TSVDUnfold_local::TSVDUnfold_local( const TH1D *bdat, const TH1D *bini, const TH1D *xini, const TH2D *Adet ) +: TObject (), +fNdim (0), +fDdim (2), +fNormalize (kFALSE), +fKReg (-1), +fDHist (NULL), +fSVHist (NULL), +fXtau (NULL), +fXinv (NULL), +fBdat (bdat), +fBini (bini), +fXini (xini), +fAdet (Adet), +fToyhisto (NULL), +fToymat (NULL), +fToyMode (kFALSE), +fMatToyMode (kFALSE) +{ + // Alternative constructor + // User provides data and MC test spectra, as well as detector response matrix, diagonal covariance matrix of measured spectrum built from the uncertainties on measured spectrum + if (bdat->GetNbinsX() != bini->GetNbinsX() || + bdat->GetNbinsX() != xini->GetNbinsX() || + bdat->GetNbinsX() != Adet->GetNbinsX() || + bdat->GetNbinsX() != Adet->GetNbinsY()) { + TString msg = "All histograms must have equal dimension.\n"; + msg += Form( " Found: dim(bdat)=%i\n", bdat->GetNbinsX() ); + msg += Form( " Found: dim(bini)=%i\n", bini->GetNbinsX() ); + msg += Form( " Found: dim(xini)=%i\n", xini->GetNbinsX() ); + msg += Form( " Found: dim(Adet)=%i,%i\n", Adet->GetNbinsX(), Adet->GetNbinsY() ); + msg += "Please start again!"; + + Fatal( "Init", msg, "%s" ); + } + + fBcov = (TH2D*)fAdet->Clone("bcov"); + + for(int i=1; i<=fBdat->GetNbinsX(); i++){ + fBcov->SetBinContent(i, i, fBdat->GetBinError(i)*fBdat->GetBinError(i)); + for(int j=1; j<=fBdat->GetNbinsX(); j++){ + if(i==j) continue; + fBcov->SetBinContent(i,j,0.); + } + } + // Get the input histos + fNdim = bdat->GetNbinsX(); + fDdim = 2; // This is the derivative used to compute the curvature matrix +} + + +//_______________________________________________________________________ +TSVDUnfold_local::TSVDUnfold_local( const TH1D *bdat, TH2D* Bcov, const TH1D *bini, const TH1D *xini, const TH2D *Adet ) +: TObject (), +fNdim (0), +fDdim (2), +fNormalize (kFALSE), +fKReg (-1), +fDHist (NULL), +fSVHist (NULL), +fXtau (NULL), +fXinv (NULL), +fBdat (bdat), +fBcov (Bcov), +fBini (bini), +fXini (xini), +fAdet (Adet), +fToyhisto (NULL), +fToymat (NULL), +fToyMode (kFALSE), +fMatToyMode (kFALSE) +{ + // Default constructor + // Initialisation of TSVDUnfold_local + // User provides data and MC test spectra, as well as detector response matrix and the covariance matrix of the measured distribution + if (bdat->GetNbinsX() != bini->GetNbinsX() || + bdat->GetNbinsX() != xini->GetNbinsX() || + bdat->GetNbinsX() != Bcov->GetNbinsX() || + bdat->GetNbinsX() != Bcov->GetNbinsY() || + bdat->GetNbinsX() != Adet->GetNbinsX() || + bdat->GetNbinsX() != Adet->GetNbinsY()) { + TString msg = "All histograms must have equal dimension.\n"; + msg += Form( " Found: dim(bdat)=%i\n", bdat->GetNbinsX() ); + msg += Form( " Found: dim(Bcov)=%i,%i\n", Bcov->GetNbinsX(), Bcov->GetNbinsY() ); + msg += Form( " Found: dim(bini)=%i\n", bini->GetNbinsX() ); + msg += Form( " Found: dim(xini)=%i\n", xini->GetNbinsX() ); + msg += Form( " Found: dim(Adet)=%i,%i\n", Adet->GetNbinsX(), Adet->GetNbinsY() ); + msg += "Please start again!"; + + Fatal( "Init", msg, "%s" ); + } + + // Get the input histos + fNdim = bdat->GetNbinsX(); + fDdim = 2; // This is the derivative used to compute the curvature matrix +} + +//_______________________________________________________________________ +TSVDUnfold_local::TSVDUnfold_local( const TSVDUnfold_local& other ) +: TObject ( other ), +fNdim (other.fNdim), +fDdim (other.fDdim), +fNormalize (other.fNormalize), +fKReg (other.fKReg), +fDHist (other.fDHist), +fSVHist (other.fSVHist), +fXtau (other.fXtau), +fXinv (other.fXinv), +fBdat (other.fBdat), +fBcov (other.fBcov), +fBini (other.fBini), +fXini (other.fXini), +fAdet (other.fAdet), +fToyhisto (other.fToyhisto), +fToymat (other.fToymat), +fToyMode (other.fToyMode), +fMatToyMode (other.fMatToyMode) +{ + // Copy constructor +} + +//_______________________________________________________________________ +TSVDUnfold_local::~TSVDUnfold_local() +{ + // Destructor + if(fToyhisto){ + delete fToyhisto; + fToyhisto = 0; + } + + if(fToymat){ + delete fToymat; + fToymat = 0; + } + + if(fDHist){ + delete fDHist; + fDHist = 0; + } + + if(fSVHist){ + delete fSVHist; + fSVHist = 0; + } + + if(fXtau){ + delete fXtau; + fXtau = 0; + } + + if(fXinv){ + delete fXinv; + fXinv = 0; + } + + if(fBcov){ + delete fBcov; + fBcov = 0; + } +} + +//_______________________________________________________________________ +TH1D* TSVDUnfold_local::Unfold( Int_t kreg ) +{ + // Perform the unfolding with regularisation parameter kreg + fKReg = kreg; + + // Make the histos + if (!fToyMode && !fMatToyMode) InitHistos( ); + + // Create vectors and matrices + TVectorD vb(fNdim), vbini(fNdim), vxini(fNdim), vberr(fNdim); + TMatrixD mB(fNdim, fNdim), mA(fNdim, fNdim), mCurv(fNdim, fNdim), mC(fNdim, fNdim); + + Double_t eps = 1e-12; + Double_t sreg; + + // Copy histogams entries into vector + if (fToyMode) { H2V( fToyhisto, vb ); H2Verr( fToyhisto, vberr ); } + else { H2V( fBdat, vb ); H2Verr( fBdat, vberr ); } + + H2M( fBcov, mB); + H2V( fBini, vbini ); + H2V( fXini, vxini ); + if (fMatToyMode) H2M( fToymat, mA ); + else H2M( fAdet, mA ); + + // Fill and invert the second derivative matrix + FillCurvatureMatrix( mCurv, mC ); + + // Inversion of mC by help of SVD + TDecompSVD CSVD(mC); + TMatrixD CUort = CSVD.GetU(); + TMatrixD CVort = CSVD.GetV(); + TVectorD CSV = CSVD.GetSig(); + + TMatrixD CSVM(fNdim, fNdim); + for (Int_t i=0; i 0){ + vx *= 1.0/scale; + Xtau *= 1./scale/scale; + Xinv *= scale*scale; + } + } + + if (!fToyMode && !fMatToyMode) { + M2H(Xtau, *fXtau); + M2H(Xinv, *fXinv); + } + + // Get Curvature and also chi2 in case of MC unfolding + if (!fToyMode && !fMatToyMode) { + Info( "Unfold", "Unfolding param: %i",k+1 ); + Info( "Unfold", "Curvature of weight distribution: %f", GetCurvature( vw, mCurv ) ); + } + + TH1D* h = (TH1D*)fBdat->Clone("unfoldingresult"); + for(int i=1; i<=fNdim; i++){ + h->SetBinContent(i,0.); + h->SetBinError(i,0.); + } + V2H( vx, *h ); + + return h; +} + +//_______________________________________________________________________ +TH2D* TSVDUnfold_local::GetUnfoldCovMatrix( const TH2D* cov, Int_t ntoys, Int_t seed ) +{ + // Determine for given input error matrix covariance matrix of unfolded + // spectrum from toy simulation given the passed covariance matrix on measured spectrum + // "cov" - covariance matrix on the measured spectrum, to be propagated + // "ntoys" - number of pseudo experiments used for the propagation + // "seed" - seed for pseudo experiments + // Note that this covariance matrix will contain effects of forced normalisation if spectrum is normalised to unit area. + + fToyMode = true; + TH1D* unfres = 0; + TH2D* unfcov = (TH2D*)fAdet->Clone("unfcovmat"); + unfcov->SetTitle("Toy covariance matrix"); + for(int i=1; i<=fNdim; i++) + for(int j=1; j<=fNdim; j++) + unfcov->SetBinContent(i,j,0.); + + // Code for generation of toys (taken from RooResult and modified) + // Calculate the elements of the upper-triangular matrix L that + // gives Lt*L = C, where Lt is the transpose of L (the "square-root method") + TMatrixD L(fNdim,fNdim); L *= 0; + + for (Int_t iPar= 0; iPar < fNdim; iPar++) { + + // Calculate the diagonal term first + L(iPar,iPar) = cov->GetBinContent(iPar+1,iPar+1); + for (Int_t k=0; k 0.0) L(iPar,iPar) = TMath::Sqrt(L(iPar,iPar)); + else L(iPar,iPar) = 0.0; + + // ...then the off-diagonal terms + for (Int_t jPar=iPar+1; jParGetBinContent(iPar+1,jPar+1); + for (Int_t k=0; kClone("toyhisto"); + TH1D *toymean = (TH1D*)fBdat->Clone("toymean"); + for (Int_t j=1; j<=fNdim; j++) toymean->SetBinContent(j,0.); + + // Get the mean of the toys first + for (int i=1; i<=ntoys; i++) { + + // create a vector of unit Gaussian variables + TVectorD g(fNdim); + for (Int_t k= 0; k < fNdim; k++) g(k) = random.Gaus(0.,1.); + + // Multiply this vector by Lt to introduce the appropriate correlations + g *= (*Lt); + + // Add the mean value offsets and store the results + for (int j=1; j<=fNdim; j++) { + fToyhisto->SetBinContent(j,fBdat->GetBinContent(j)+g(j-1)); + fToyhisto->SetBinError(j,fBdat->GetBinError(j)); + } + + unfres = Unfold(GetKReg()); + + for (Int_t j=1; j<=fNdim; j++) { + toymean->SetBinContent(j, toymean->GetBinContent(j) + unfres->GetBinContent(j)/ntoys); + } + delete unfres; + unfres = 0; + } + + // Reset the random seed + random.SetSeed(seed); + + //Now the toys for the covariance matrix + for (int i=1; i<=ntoys; i++) { + + // Create a vector of unit Gaussian variables + TVectorD g(fNdim); + for (Int_t k= 0; k < fNdim; k++) g(k) = random.Gaus(0.,1.); + + // Multiply this vector by Lt to introduce the appropriate correlations + g *= (*Lt); + + // Add the mean value offsets and store the results + for (int j=1; j<=fNdim; j++) { + fToyhisto->SetBinContent( j, fBdat->GetBinContent(j)+g(j-1) ); + fToyhisto->SetBinError ( j, fBdat->GetBinError(j) ); + } + unfres = Unfold(GetKReg()); + + for (Int_t j=1; j<=fNdim; j++) { + for (Int_t k=1; k<=fNdim; k++) { + unfcov->SetBinContent(j,k,unfcov->GetBinContent(j,k) + ( (unfres->GetBinContent(j) - toymean->GetBinContent(j))* (unfres->GetBinContent(k) - toymean->GetBinContent(k))/(ntoys-1)) ); + } + } + delete unfres; + unfres = 0; + } + delete Lt; + delete toymean; + fToyMode = kFALSE; + + return unfcov; +} + +//_______________________________________________________________________ +TH2D* TSVDUnfold_local::GetAdetCovMatrix( Int_t ntoys, Int_t seed ) +{ + // Determine covariance matrix of unfolded spectrum from finite statistics in + // response matrix using pseudo experiments + // "ntoys" - number of pseudo experiments used for the propagation + // "seed" - seed for pseudo experiments + + fMatToyMode = true; + TH1D* unfres = 0; + TH2D* unfcov = (TH2D*)fAdet->Clone("unfcovmat"); + unfcov->SetTitle("Toy covariance matrix"); + for(int i=1; i<=fNdim; i++) + for(int j=1; j<=fNdim; j++) + unfcov->SetBinContent(i,j,0.); + + //Now the toys for the detector response matrix + TRandom3 random(seed); + + fToymat = (TH2D*)fAdet->Clone("toymat"); + TH1D *toymean = (TH1D*)fXini->Clone("toymean"); + for (Int_t j=1; j<=fNdim; j++) toymean->SetBinContent(j,0.); + + for (int i=1; i<=ntoys; i++) { + for (Int_t k=1; k<=fNdim; k++) { + for (Int_t m=1; m<=fNdim; m++) { + if (fAdet->GetBinContent(k,m)) { + fToymat->SetBinContent(k, m, random.Poisson(fAdet->GetBinContent(k,m))); + } + } + } + + unfres = Unfold(GetKReg()); + + for (Int_t j=1; j<=fNdim; j++) { + toymean->SetBinContent(j, toymean->GetBinContent(j) + unfres->GetBinContent(j)/ntoys); + } + delete unfres; + unfres = 0; + } + + // Reset the random seed + random.SetSeed(seed); + + for (int i=1; i<=ntoys; i++) { + for (Int_t k=1; k<=fNdim; k++) { + for (Int_t m=1; m<=fNdim; m++) { + if (fAdet->GetBinContent(k,m)) + fToymat->SetBinContent(k, m, random.Poisson(fAdet->GetBinContent(k,m))); + } + } + + unfres = Unfold(GetKReg()); + + for (Int_t j=1; j<=fNdim; j++) { + for (Int_t k=1; k<=fNdim; k++) { + unfcov->SetBinContent(j,k,unfcov->GetBinContent(j,k) + ( (unfres->GetBinContent(j) - toymean->GetBinContent(j))*(unfres->GetBinContent(k) - toymean->GetBinContent(k))/(ntoys-1)) ); + } + } + delete unfres; + unfres = 0; + } + delete toymean; + fMatToyMode = kFALSE; + + return unfcov; +} + +//_______________________________________________________________________ +TH1D* TSVDUnfold_local::GetD() const +{ + // Returns d vector (for choosing appropriate regularisation) + for (int i=1; i<=fDHist->GetNbinsX(); i++) { + if (fDHist->GetBinContent(i)<0.) fDHist->SetBinContent(i, TMath::Abs(fDHist->GetBinContent(i))); + } + return fDHist; +} + +//_______________________________________________________________________ +TH1D* TSVDUnfold_local::GetSV() const +{ + // Returns singular values vector + return fSVHist; +} + +//_______________________________________________________________________ +TH2D* TSVDUnfold_local::GetXtau() const +{ + // Returns the computed regularized covariance matrix corresponding to total uncertainties on measured spectrum as passed in the constructor. + // Note that this covariance matrix will not contain the effects of forced normalization if spectrum is normalized to unit area. + return fXtau; +} + +//_______________________________________________________________________ +TH2D* TSVDUnfold_local::GetXinv() const +{ + // Returns the computed inverse of the covariance matrix + return fXinv; +} + +//_______________________________________________________________________ +TH2D* TSVDUnfold_local::GetBCov() const +{ + // Returns the covariance matrix + return fBcov; +} + +//_______________________________________________________________________ +void TSVDUnfold_local::H2V( const TH1D* histo, TVectorD& vec ) +{ + // Fill 1D histogram into vector + for (Int_t i=0; iGetNbinsX(); i++) vec(i) = histo->GetBinContent(i+1); +} + +//_______________________________________________________________________ +void TSVDUnfold_local::H2Verr( const TH1D* histo, TVectorD& vec ) +{ + // Fill 1D histogram errors into vector + for (Int_t i=0; iGetNbinsX(); i++) vec(i) = histo->GetBinError(i+1); +} + +//_______________________________________________________________________ +void TSVDUnfold_local::V2H( const TVectorD& vec, TH1D& histo ) +{ + // Fill vector into 1D histogram + for(Int_t i=0; iGetNbinsX(); j++) { + for (Int_t i=0; iGetNbinsY(); i++) { + mat(i,j) = histo->GetBinContent(i+1,j+1); + } + } +} + +//_______________________________________________________________________ +void TSVDUnfold_local::M2H( const TMatrixD& mat, TH2D& histo ) +{ + // Fill 2D histogram into matrix + for (Int_t j=0; j 0) tC(i,i-1) = 1.0; + if (i < ndim-1) tC(i,i+1) = 1.0; + tC(i,i) = -2.0; + } + tC(0,0) = -1.0; + tC(ndim-1,ndim-1) = -1.0; + } + else if (fDdim == 3) { + for (Int_t i=1; i 0) tC(i,i-1) = -4.0; + if (i < ndim-1) tC(i,i+1) = -4.0; + if (i > 1) tC(i,i-2) = 1.0; + if (i < ndim-2) tC(i,i+2) = 1.0; + tC(i,i) = 6.0; + } + tC(0,0) = 2.0; + tC(ndim-1,ndim-1) = 2.0; + tC(0,1) = -3.0; + tC(ndim-2,ndim-1) = -3.0; + tC(1,0) = -3.0; + tC(ndim-1,ndim-2) = -3.0; + tC(1,1) = 6.0; + tC(ndim-2,ndim-2) = 6.0; + } + else if (fDdim == 5) { + for (Int_t i=2; i < ndim-3; i++) { + tC(i,i-2) = 1.0; + tC(i,i-1) = -5.0; + tC(i,i) = 10.0; + tC(i,i+1) = -10.0; + tC(i,i+2) = 5.0; + tC(i,i+3) = -1.0; + } + } + else if (fDdim == 6) { + for (Int_t i = 3; i < ndim - 3; i++) { + tC(i,i-3) = 1.0; + tC(i,i-2) = -6.0; + tC(i,i-1) = 15.0; + tC(i,i) = -20.0; + tC(i,i+1) = 15.0; + tC(i,i+2) = -6.0; + tC(i,i+3) = 1.0; + } + } + + // Add epsilon to avoid singularities + for (Int_t i=0; iSumw2(); + + fSVHist = new TH1D( "sv", "Singular values of AC^-1", fNdim, 0, fNdim ); + fSVHist->Sumw2(); + + fXtau = (TH2D*)fAdet->Clone("Xtau"); + fXtau->SetTitle("Regularized covariance matrix"); + fXtau->Sumw2(); + + fXinv = (TH2D*)fAdet->Clone("Xinv"); + fXinv->SetTitle("Inverse covariance matrix"); + fXinv->Sumw2(); +} + +//_______________________________________________________________________ +void TSVDUnfold_local::RegularisedSymMatInvert( TMatrixDSym& mat, Double_t eps ) +{ + // naive regularised inversion cuts off small elements + + // init reduced matrix + const UInt_t n = mat.GetNrows(); + UInt_t nn = 0; + + UInt_t *ipos = new UInt_t[n]; + // UInt_t ipos[n]; + + // find max diagonal entries + Double_t ymax = 0; + for (UInt_t i=0; i ymax) ymax = TMath::Abs(mat[i][i]); + + for (UInt_t i=0; i eps) ipos[nn++] = i; + } + + // effective matrix + TMatrixDSym matwork( nn ); + for (UInt_t in=0; inGetBinContent(i+1,j+1) ); + } + } + + return chi2; +} + From 674db2ff7309ec01e459fd72edb9c2baceef8565 Mon Sep 17 00:00:00 2001 From: kreczko Date: Mon, 23 Feb 2015 13:43:45 +0000 Subject: [PATCH 04/13] enabled tau unfolding --- include/RooUnfoldSvd.h | 8 +- include/TauSVDUnfold.h | 42 +++++++- src/RooUnfoldSvd.cxx | 33 ++++-- src/TauSVDUnfold.cxx | 212 ++++++++++++++++++++++++++++++++++--- test/TauSVDUnfoldTests.cpp | 140 +++++++++++++++++++++++- test/TestRooUnfoldSvd.cpp | 179 +++++++++++++++++++++++++++++++ test/simpletest.cpp | 11 -- 7 files changed, 587 insertions(+), 38 deletions(-) create mode 100644 test/TestRooUnfoldSvd.cpp delete mode 100755 test/simpletest.cpp diff --git a/include/RooUnfoldSvd.h b/include/RooUnfoldSvd.h index 5910e08..719d456 100644 --- a/include/RooUnfoldSvd.h +++ b/include/RooUnfoldSvd.h @@ -42,8 +42,10 @@ class RooUnfoldSvd : public RooUnfold { const char* name= 0, const char* title= 0); void SetKterm (Int_t kreg); + void SetTauTerm (double taureg); void SetNtoysSVD (Int_t ntoyssvd); Int_t GetKterm() const; + double GetTauTerm() const; Int_t GetNtoysSVD() const; virtual void SetRegParm (Double_t parm); @@ -67,6 +69,7 @@ class RooUnfoldSvd : public RooUnfold { TSVDUnfold_local* _svd; //! Implementation in TSVDUnfold object (no streamer) Int_t _kreg; double _taureg; + bool _use_tau_unfolding; Int_t _nb; Int_t _ntoyssvd; @@ -158,7 +161,10 @@ inline Double_t RooUnfoldSvd::GetRegParm() const { // Return regularisation parameter - return GetKterm(); + if (_use_tau_unfolding) + return _taureg; + else + return _kreg; } #endif diff --git a/include/TauSVDUnfold.h b/include/TauSVDUnfold.h index 061efac..41289a6 100644 --- a/include/TauSVDUnfold.h +++ b/include/TauSVDUnfold.h @@ -1,16 +1,25 @@ /* * TauSVDUnfold.h * - * Created on: 31 Dec 2014 + * original: + * https://github.com/eschliec/TopAnalysis/tree/master/Configuration/analysis/unfolding + * + * Modified on: 31 Dec 2014 * Author: phxlk */ #ifndef TAUSVDUNFOLD_H_ #define TAUSVDUNFOLD_H_ #include "TSVDUnfold_local.h" +#include "TGraph.h" +#include "TH1D.h" +#include "TH2D.h" class TauSVDUnfold: public TSVDUnfold_local { public: + /** + * For documentation on constructors see TSVDUnfold::TSVDUnfold + */ TauSVDUnfold(const TH1D* bdat, const TH1D* bini, const TH1D* xini, const TH2D* Adet); TauSVDUnfold(const TH1D* bdat, TH2D* Bcov, const TH1D* bini, const TH1D* xini, const TH2D* Adet); TauSVDUnfold(const TauSVDUnfold& other); @@ -31,13 +40,42 @@ class TauSVDUnfold: public TSVDUnfold_local { double kToTau(int kreg) const; + TGraph* ScanLCurve(unsigned int n_point, double tau_min, double tau_max); + double GetLcurveX() const; + double GetLcurveY() const; + + /** + * Added by Joern: adapted from TSVDUnfold::GetUnfoldCovMatrix to include + * the normalisation in the procedure + * Determine for given input error matrix covariance matrix of unfolded + * spectrum from toy simulation given the passed covariance matrix on measured spectrum + * "cov" - covariance matrix on the measured spectrum, to be propagated + * "ntoys" - number of pseudo experiments used for the propagation + * "seed" - seed for pseudo experiments + * "normType" - set type of normalisation (1=extrinsic, 2=intrinsic) + * Note that this covariance matrix will contain effects of forced normalisation if spectrum is normalised to unit area. + */ +// TH2D* GetUnfoldCovMatrixNorm(const TH2D* cov, Int_t ntoys, Int_t seed = 1, Int_t normType = 2, Int_t verbose = 0); +// static TH1D* IntNormalizeSVDDistribution(TH1D* inputHist); + /** + * Calculates the covariance matrix (dispersion matrix) + * Takes a 1D histogram and returns a diagonal 2D histogram with entries + * cov(i,i) = error(i)^2 + */ + static TH2D* get_data_covariance_matrix(const TH1D* data_histogram); + + static double get_global_correlation(const TH1D* data_histogram); + + static TH1D* get_global_correlation_hist(const TH1D* data_histogram); + protected: double fTau; double fCurv; TH1D* fWeights; TVectorD fASV; - ClassDef( TauSVDUnfold, 0 ); +ClassDef( TauSVDUnfold, 0 ) + ; }; #endif /* TAUSVDUNFOLD_H_ */ diff --git a/src/RooUnfoldSvd.cxx b/src/RooUnfoldSvd.cxx index 71c7304..192c984 100644 --- a/src/RooUnfoldSvd.cxx +++ b/src/RooUnfoldSvd.cxx @@ -57,6 +57,7 @@ RooUnfoldSvd::RooUnfoldSvd(const RooUnfoldResponse* res, const TH1* meas, Int_t RooUnfold(res, meas, name, title), _kreg(kreg ? kreg : res->GetNbinsTruth() / 2), _taureg(-1.), + _use_tau_unfolding(false), _ntoyssvd(ntoyssvd) { // Constructor with response matrix object and measured unfolding input histogram. // The regularisation parameter is kreg. @@ -68,6 +69,7 @@ RooUnfoldSvd::RooUnfoldSvd(const RooUnfoldResponse* res, const TH1* meas, double RooUnfold(res, meas, name, title), _kreg(-1), _taureg(taureg ? taureg: 0.), + _use_tau_unfolding(true), _ntoyssvd(ntoyssvd) { // Constructor with response matrix object and measured unfolding input histogram. // The regularisation parameter is kreg. @@ -120,7 +122,8 @@ void RooUnfoldSvd::CopyData (const RooUnfoldSvd& rhs) { _kreg= rhs._kreg; - _taureg = rhs._kreg; + _taureg = rhs._taureg; + _use_tau_unfolding = rhs._use_tau_unfolding; _ntoyssvd= rhs._ntoyssvd; } @@ -136,8 +139,11 @@ RooUnfoldSvd::Unfold() if (_res->GetDimensionTruth() != 1 || _res->GetDimensionMeasured() != 1) { cerr << "RooUnfoldSvd may not work very well for multi-dimensional distributions" << endl; } - if (_kreg < 0) { - cerr << "RooUnfoldSvd invalid kreg: " << _kreg << endl; + if ((_kreg < 0 && !_use_tau_unfolding) || (_taureg < 0 && _use_tau_unfolding)) { + if (_use_tau_unfolding) + cerr << "RooUnfoldSvd invalid taureg: " << _taureg << endl; + else + cerr << "RooUnfoldSvd invalid kreg: " << _kreg << endl; return; } @@ -171,12 +177,15 @@ RooUnfoldSvd::Unfold() _truth1d->SetBinContent(_nt+1,nfakes); } - if (_verbose>=1) cout << "SVD init " << _reshist->GetNbinsX() << " x " << _reshist->GetNbinsY() - << " bins, kreg=" << _kreg << endl; + if (_verbose >= 1) + cout << "SVD init " << _reshist->GetNbinsX() << " x " << _reshist->GetNbinsY() << " bins, kreg=" << _kreg + << " taureg=" << _taureg << endl; _svd= new TauSVDUnfold (_meas1d, _train1d, _truth1d, _reshist); - - TH1D* rechist= _svd->Unfold (_kreg); - + TH1D* rechist = 0; + if (_use_tau_unfolding) + rechist = ((TauSVDUnfold*) _svd)->Unfold(_taureg); + else + rechist = _svd->Unfold (_kreg); _rec.ResizeTo (_nt); for (Int_t i= 0; i<_nt; i++) { _rec[i]= rechist->GetBinContent(i+1); @@ -243,3 +252,11 @@ void RooUnfoldSvd::Streamer (TBuffer &R__b) RooUnfoldSvd::Class()->WriteBuffer (R__b, this); } } + +void RooUnfoldSvd::SetTauTerm(double taureg) { + _taureg = taureg; +} + +double RooUnfoldSvd::GetTauTerm() const { + return _taureg; +} diff --git a/src/TauSVDUnfold.cxx b/src/TauSVDUnfold.cxx index 0c1d8a0..058649c 100644 --- a/src/TauSVDUnfold.cxx +++ b/src/TauSVDUnfold.cxx @@ -9,6 +9,10 @@ #include "TDecompSVD.h" #include "TMath.h" #include "TH1D.h" +#include +#include + +using namespace std; TauSVDUnfold::TauSVDUnfold(const TH1D* bdat, const TH1D* bini, const TH1D* xini, const TH2D* Adet) : TSVDUnfold_local(bdat, bini, xini, Adet), @@ -66,7 +70,6 @@ TH1D* TauSVDUnfold::Unfold(double tau) { Double_t eps = 1e-12; Double_t sreg; - // Copy histogams entries into vector if (fToyMode) { H2V(fToyhisto, vb); @@ -75,7 +78,6 @@ TH1D* TauSVDUnfold::Unfold(double tau) { H2V(fBdat, vb); H2Verr(fBdat, vberr); } - H2M(fBcov, mB); H2V(fBini, vbini); H2V(fXini, vxini); @@ -86,7 +88,6 @@ TH1D* TauSVDUnfold::Unfold(double tau) { // Fill and invert the second derivative matrix FillCurvatureMatrix(mCurv, mC); - // Inversion of mC by help of SVD TDecompSVD CSVD(mC); TMatrixD CUort = CSVD.GetU(); @@ -99,7 +100,6 @@ TH1D* TauSVDUnfold::Unfold(double tau) { CUort.Transpose(CUort); TMatrixD mCinv = (CVort * CSVM) * CUort; - // // Rescale matrix and vectors by error of data vector. Replaced by using full covmat now // vbini = VecDiv ( vbini, vberr ); // vb = VecDiv ( vb, vberr, 1 ); @@ -112,7 +112,6 @@ TH1D* TauSVDUnfold::Unfold(double tau) { QT.Transpose(QT); TVectorD B2SV = BSVD.GetSig(); TVectorD BSV(B2SV); - for (int i = 0; i < fNdim; i++) { BSV(i) = TMath::Sqrt(B2SV(i)); } @@ -134,20 +133,18 @@ TH1D* TauSVDUnfold::Unfold(double tau) { } mA = mAtmp; vb = vbtmp; - // Singular value decomposition and matrix operations TDecompSVD ASVD(mA * mCinv); TMatrixD Uort = ASVD.GetU(); TMatrixD Vort = ASVD.GetV(); + // TODO: This part is failing for tau unfolding TVectorD ASV = ASVD.GetSig(); fASV = ASV; - if (!fToyMode && !fMatToyMode) { V2H(ASV, *fSVHist); } TMatrixD Vreg = mCinv * Vort; - Uort.Transpose(Uort); TVectorD vd = Uort * vb; @@ -156,7 +153,6 @@ TH1D* TauSVDUnfold::Unfold(double tau) { } Int_t k = GetKReg() - 1; - TVectorD vx(fNdim); // Return variable // Damping factors @@ -171,8 +167,7 @@ TH1D* TauSVDUnfold::Unfold(double tau) { vdz(i) = sreg / (sreg * sreg + fTau * fTau); Z(i, i) = vdz(i) * vdz(i); } - - TVectorD vz = CompProd(vd, vdz); + TVectorD vz = TSVDUnfold_local::CompProd(vd, vdz); TMatrixD VortT(Vort); VortT.Transpose(VortT); @@ -194,12 +189,11 @@ TH1D* TauSVDUnfold::Unfold(double tau) { Xinv(i, j) = a / vxini(i) / vxini(j); } } - // Compute the weights TVectorD vw = Vreg * vz; // DAVID - vx = CompProd(vw, vxini); + vx = TSVDUnfold_local::CompProd(vw, vxini); if (fNormalize) { // Scale result to unit area Double_t scale = vx.Sum(); @@ -218,7 +212,6 @@ TH1D* TauSVDUnfold::Unfold(double tau) { // DAVID // Speichere die Kruemmung ab! fCurv = GetCurvature(vw, mCurv); - // Get Curvature and also chi2 in case of MC unfolding if (!fToyMode && !fMatToyMode) { Info("Unfold", "Unfolding param: %i", k + 1); @@ -231,7 +224,6 @@ TH1D* TauSVDUnfold::Unfold(double tau) { h->SetBinError(i, 0.); } V2H(vx, *h); - // DAVID // Save the weights // but only if this is not a "Toy"-Run @@ -253,3 +245,193 @@ double TauSVDUnfold::kToTau(int kreg) const { tau = fASV(kreg); return tau; } + + +TH2D* TauSVDUnfold::get_data_covariance_matrix(const TH1D* data_histogram) { + // get bins from data_histogram + unsigned int n_bins = data_histogram->GetNbinsX(); + vector bin_edges; + for (unsigned int i = 1; i <= n_bins; ++i) { + double low_edge = data_histogram->GetBinLowEdge(i); + double bin_width = data_histogram->GetBinWidth(i); + bin_edges.push_back(low_edge); + bin_edges.push_back(low_edge + bin_width); + } + + // create 2D histogram + TH2D * data_covariance_matrix = new TH2D("data_covariance_matrix", "data_covariance_matrix", n_bins, &bin_edges[0], + n_bins, &bin_edges[0]); + + // fill it + for (unsigned int i = 1; i <= n_bins; ++i) { + double variance = pow(data_histogram->GetBinError(i), 2.); + data_covariance_matrix->SetBinContent(i, i, variance); + } + + return data_covariance_matrix; +} + +TH1D* TauSVDUnfold::get_global_correlation_hist(const TH1D* data_histogram) { + TH2D* covariance_hist = (TH2D*) TauSVDUnfold::get_data_covariance_matrix(data_histogram)->Clone(); + + unsigned int n_bins = data_histogram->GetNbinsX(); + vector bin_map; + bin_map.resize(n_bins); + + unsigned int number_of_bins_to_skip(0); + unsigned int bin_counter(0); + + // all bins except underflow (0) and overflow (nbins + 1) + for (auto i = 1; i <= n_bins; ++i) { + double data = data_histogram->GetBinContent(i); + if (data <= 0.) { + // Through out bin with no data + bin_map[i - 1] = -1; + ++number_of_bins_to_skip; + } else { + // Search for bins with empty rows/columns + bool skip_bin = true; + for (auto j = 1; j <= n_bins; ++j) { + double value = covariance_hist->GetBinContent(i, j); + if (value != 0.) { + skip_bin = false; + } + } + // Through out bins with empty rows/columns + if (skip_bin == true) { + bin_map[i - 1] = -1; + ++number_of_bins_to_skip; + } else { + bin_map[i - 1] = bin_counter; + bin_counter++; + } + } + } + + unsigned int matrix_dimension = n_bins - number_of_bins_to_skip; + TMatrixDSym covariance_matrix(matrix_dimension); + + // New Matrix + // Beware the side bins of the problem + // AND the side bins of the TH2D object + for (unsigned int i = 1; i <= n_bins; i++) { + for (unsigned int j = 1; j <= n_bins; j++) { + + // Is this bin to be skipped? + bool skip_bin = false; + if (bin_map[i - 1] == -1) + skip_bin = true; + if (bin_map[j - 1] == -1) + skip_bin = true; + // Set Element + if (skip_bin == false) { + double value = covariance_hist->GetBinContent(i, j); + int bin_nr_i = bin_map[i - 1]; + int bin_nr_j = bin_map[j - 1]; + covariance_matrix[bin_nr_i][bin_nr_j] = value; + } + } + } + + // Determinant + double *det_covariance_matrix = new double(0.); + + // Invert the whole thing + TMatrixDSym covariance_matrix_invers = covariance_matrix; + covariance_matrix_invers.Invert(det_covariance_matrix); + + // Check Invertibility + bool is_invertible = *det_covariance_matrix != 0.; + if (is_invertible == false) { + cout << "Error in TauSVDUnfold::get_global_correlation_hist() " << endl; + cout << "Covariance Matrix cannot be inverted." << endl; + cout << "Check the reason for this now." << endl; + exit(1); + } + + // Create new Histo for global correlation + TH1D* global_correlation_hist = new TH1D(); + global_correlation_hist->SetNameTitle("global_correlation_hist", "global_correlation_hist"); + if (covariance_hist->GetXaxis()->IsVariableBinSize() == true) { + const TArrayD* xbins = covariance_hist->GetXaxis()->GetXbins(); + global_correlation_hist->SetBins(n_bins, xbins->GetArray()); + } else { + double xmin = covariance_hist->GetXaxis()->GetXmin(); + double xmax = covariance_hist->GetXaxis()->GetXmax(); + global_correlation_hist->SetBins(n_bins, xmin, xmax); + } + + // Fill the histo you just created + for (unsigned int i = 1; i <= n_bins; i++) { + double global_correlation = 0.; + + // Find out the "true" bin number + int binnr = bin_map[i - 1]; + + // Skip bad bins + bool skipThis = false; + if (binnr == -1) + skipThis = true; + + // Run over good bins + if (skipThis == false) { + double cov = covariance_matrix[binnr][binnr]; + double covinv = covariance_matrix_invers[binnr][binnr]; + // The product cov*covinv should be greater than zero + double cov_prod = cov * covinv; + double var(0.); + if (cov_prod > 0) + var = 1. / cov_prod; + double global_correlation_squared = 0.; +// cout << "cov: " << cov << endl; +// cout << "covinv: " << covinv << endl; +// cout << "cov_prod: " << cov_prod << endl; +// cout << "var: " << var << endl; + if (var > 0.) + global_correlation_squared = 1. - var; + + if (global_correlation_squared > 0) { + global_correlation = 100. * sqrt(global_correlation_squared); + } else { + global_correlation = 0.; + } + } else { + global_correlation = 0.; + } + + // Set the value + global_correlation_hist->SetBinContent(i, global_correlation); + global_correlation_hist->SetBinError(i, 0.); + } + delete covariance_hist; + + return global_correlation_hist; +} + +double TauSVDUnfold::get_global_correlation(const TH1D* data_histogram) { + TH1D * global_correlation_hist = TauSVDUnfold::get_global_correlation_hist(data_histogram); + + double sum = 0.; + double average = 0.; + int bincounter = 0; + unsigned int n_bins = global_correlation_hist->GetNbinsX(); + + for (unsigned int i = 1; i <= n_bins; i++) { + if (i == 1) + continue; + if (i == n_bins) + continue; + double globcorr = global_correlation_hist->GetBinContent(i); + sum += globcorr; + bincounter++; + } + + // Averaging + if (bincounter > 0) { + average = sum / ((double) bincounter); + } + + delete global_correlation_hist; + + return average; +} diff --git a/test/TauSVDUnfoldTests.cpp b/test/TauSVDUnfoldTests.cpp index b221502..08b9ca7 100644 --- a/test/TauSVDUnfoldTests.cpp +++ b/test/TauSVDUnfoldTests.cpp @@ -5,10 +5,148 @@ * Created on August 13, 2014, 6:49 PM */ #include +#include "../include/TauSVDUnfold.h" +#include "../include/RooUnfoldSvd.h" +#include "../include/RooUnfoldResponse.h" +#include +#include "TROOT.h" + +using namespace std; + +struct TauSVDUnfoldSetup { + TauSVDUnfoldSetup() : + nbins(6), + n_toy(100), + kreg(3), + taureg(1), + data(new TH1D("data", "data", nbins, 0, nbins)), + gen_var(new TH1D("gen_var", "gen_var", nbins, 0, nbins)), + reco_var(new TH1D("reco_var", "reco_var", nbins, 0, nbins)), + gen_vs_reco(new TH2D("gen_vs_reco", "gen_vs_reco", nbins, 0, nbins, nbins, 0, nbins)), + roo_response(), + roounfold_svd_k(), + roounfold_svd_tau(){ + gROOT->SetBatch(1); + gROOT->ProcessLine("gErrorIgnoreLevel = 1001;"); + // from toy MC 1 + data->SetBinContent(1, 365); + data->SetBinContent(2, 578); + data->SetBinContent(3, 531); + data->SetBinContent(4, 198); + data->SetBinContent(5, 58); + data->SetBinContent(6, 31); + set_sqrt_N_error(data); + + // from toy MC 2 + reco_var->SetBinContent(1, 367); + reco_var->SetBinContent(2, 586); + reco_var->SetBinContent(3, 523); + reco_var->SetBinContent(4, 195); + reco_var->SetBinContent(5, 61); + reco_var->SetBinContent(6, 29); + set_sqrt_N_error (reco_var); + + gen_var->SetBinContent(1, 3441); + gen_var->SetBinContent(2, 5181); + gen_var->SetBinContent(3, 4050); + gen_var->SetBinContent(4, 1546); + gen_var->SetBinContent(5, 449); + gen_var->SetBinContent(6, 149); + set_sqrt_N_error(gen_var); + + gen_vs_reco->SetBinContent(1, 1, 236); + gen_vs_reco->SetBinContent(1, 2, 92); + gen_vs_reco->SetBinContent(1, 3, 4); + + gen_vs_reco->SetBinContent(2, 1, 163); + gen_vs_reco->SetBinContent(2, 2, 297); + gen_vs_reco->SetBinContent(2, 3, 61); + gen_vs_reco->SetBinContent(2, 4, 1); + + gen_vs_reco->SetBinContent(3, 1, 24); + gen_vs_reco->SetBinContent(3, 2, 167); + gen_vs_reco->SetBinContent(3, 3, 216); + gen_vs_reco->SetBinContent(3, 3, 23); + + gen_vs_reco->SetBinContent(4, 1, 2); + gen_vs_reco->SetBinContent(4, 2, 4); + gen_vs_reco->SetBinContent(4, 3, 61); + gen_vs_reco->SetBinContent(4, 4, 74); + gen_vs_reco->SetBinContent(4, 5, 5); + + gen_vs_reco->SetBinContent(5, 4, 12); + gen_vs_reco->SetBinContent(5, 5, 26); + gen_vs_reco->SetBinContent(5, 6, 3); + + gen_vs_reco->SetBinContent(6, 4, 1); + gen_vs_reco->SetBinContent(6, 5, 5); + gen_vs_reco->SetBinContent(6, 6, 11); + set_sqrt_N_error(gen_vs_reco); + + roo_response = new RooUnfoldResponse(reco_var, gen_var, gen_vs_reco); + roounfold_svd_k = new RooUnfoldSvd(roo_response, data, kreg, n_toy); + roounfold_svd_tau = new RooUnfoldSvd(roo_response, data, taureg, n_toy); + + } + ~TauSVDUnfoldSetup() { + delete data; + delete gen_var; + delete reco_var; + delete gen_vs_reco; + delete roo_response; +// delete tau_svd_unfold; + delete roounfold_svd_k; + delete roounfold_svd_tau; + } + + void set_sqrt_N_error(TH1D* hist) { + for (auto i = 1; i <= hist->GetNbinsX(); ++i) { + hist->SetBinError(i, sqrt(hist->GetBinContent(i))); + } + } + + void set_sqrt_N_error(TH2D* hist) { + for (auto i = 1; i <= hist->GetNbinsX(); ++i) { + for (auto j = 1; j <= hist->GetNbinsY(); ++j) { + hist->SetBinError(i, j, sqrt(hist->GetBinContent(i, j))); + } + } + } + + unsigned int nbins; + unsigned int n_toy; + int kreg; + double taureg; + TH1D* data, *gen_var, *reco_var; + TH2D* gen_vs_reco; + RooUnfoldResponse* roo_response; +// TauSVDUnfold* tau_svd_unfold; + RooUnfoldSvd* roounfold_svd_k; + RooUnfoldSvd* roounfold_svd_tau; + +}; BOOST_AUTO_TEST_SUITE (TauSVDUnfoldTestSuite) -BOOST_AUTO_TEST_CASE(Test1) { +BOOST_FIXTURE_TEST_CASE(test_get_data_covariance_matrix, TauSVDUnfoldSetup) { + TH2D* cov = TauSVDUnfold::get_data_covariance_matrix(data); + for (auto i = 1; i <= nbins; ++i) { + double data_error = data->GetBinError(i); + BOOST_CHECK_EQUAL(cov->GetBinContent(i, i), data_error * data_error); + } + delete cov; +} + +BOOST_FIXTURE_TEST_CASE(test_get_global_correlation, TauSVDUnfoldSetup) { + double corr = TauSVDUnfold::get_global_correlation(data); + BOOST_CHECK_EQUAL(corr, -1.); +} +BOOST_FIXTURE_TEST_CASE(test_get_global_correlation_hist, TauSVDUnfoldSetup) { + TH1D* corr_hist = TauSVDUnfold::get_global_correlation_hist(data); + for (auto i = 1; i <= nbins; ++i) { + BOOST_CHECK_EQUAL(corr_hist->GetBinContent(i), i * i); + } + delete corr_hist; } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/TestRooUnfoldSvd.cpp b/test/TestRooUnfoldSvd.cpp new file mode 100644 index 0000000..4b2a82f --- /dev/null +++ b/test/TestRooUnfoldSvd.cpp @@ -0,0 +1,179 @@ +/* + * TestUtils.cpp + * + * Created on: 24 Feb 2015 + * Author: kreczko + */ + +#include +#include "../include/RooUnfold.h" +#include "../include/RooUnfoldSvd.h" +#include +#include "TH2D.h" +#include "TROOT.h" +#include + +using namespace std; + +struct RooUnfoldSvdSetup { + RooUnfoldSvdSetup() : + nbins(6), + n_toy(100), + kreg(3), + taureg(40), + data(new TH1D("data", "data", nbins, 0, nbins)), + gen_var(new TH1D("gen_var", "gen_var", nbins, 0, nbins)), + reco_var(new TH1D("reco_var", "reco_var", nbins, 0, nbins)), + gen_vs_reco(new TH2D("gen_vs_reco", "gen_vs_reco", nbins, 0, nbins, nbins, 0, nbins)), + roo_response(), + roounfold_svd_k(), + roounfold_svd_tau() { + gROOT->SetBatch(1); +// gROOT->ProcessLine("gErrorIgnoreLevel = 1001;"); + // from toy MC 1 + data->SetBinContent(1, 365); + data->SetBinContent(2, 578); + data->SetBinContent(3, 531); + data->SetBinContent(4, 198); + data->SetBinContent(5, 58); + data->SetBinContent(6, 31); + set_sqrt_N_error(data); + + // from toy MC 2 + reco_var->SetBinContent(1, 367); + reco_var->SetBinContent(2, 586); + reco_var->SetBinContent(3, 523); + reco_var->SetBinContent(4, 195); + reco_var->SetBinContent(5, 61); + reco_var->SetBinContent(6, 29); + set_sqrt_N_error(reco_var); + + gen_var->SetBinContent(1, 3441); + gen_var->SetBinContent(2, 5181); + gen_var->SetBinContent(3, 4050); + gen_var->SetBinContent(4, 1546); + gen_var->SetBinContent(5, 449); + gen_var->SetBinContent(6, 149); + set_sqrt_N_error(gen_var); + + gen_vs_reco->SetBinContent(1, 1, 236); + gen_vs_reco->SetBinContent(1, 2, 92); + gen_vs_reco->SetBinContent(1, 3, 4); + + gen_vs_reco->SetBinContent(2, 1, 163); + gen_vs_reco->SetBinContent(2, 2, 297); + gen_vs_reco->SetBinContent(2, 3, 61); + gen_vs_reco->SetBinContent(2, 4, 1); + + gen_vs_reco->SetBinContent(3, 1, 24); + gen_vs_reco->SetBinContent(3, 2, 167); + gen_vs_reco->SetBinContent(3, 3, 216); + gen_vs_reco->SetBinContent(3, 3, 23); + + gen_vs_reco->SetBinContent(4, 1, 2); + gen_vs_reco->SetBinContent(4, 2, 4); + gen_vs_reco->SetBinContent(4, 3, 61); + gen_vs_reco->SetBinContent(4, 4, 74); + gen_vs_reco->SetBinContent(4, 5, 5); + + gen_vs_reco->SetBinContent(5, 4, 12); + gen_vs_reco->SetBinContent(5, 5, 26); + gen_vs_reco->SetBinContent(5, 6, 3); + + gen_vs_reco->SetBinContent(6, 4, 1); + gen_vs_reco->SetBinContent(6, 5, 5); + gen_vs_reco->SetBinContent(6, 6, 11); + set_sqrt_N_error(gen_vs_reco); + + roo_response = new RooUnfoldResponse(reco_var, gen_var, gen_vs_reco); + roounfold_svd_k = new RooUnfoldSvd(roo_response, data, kreg, n_toy); + roounfold_svd_tau = new RooUnfoldSvd(roo_response, data, taureg, n_toy); + + } + ~RooUnfoldSvdSetup() { + delete data; + delete gen_var; + delete reco_var; + delete gen_vs_reco; + delete roo_response; + delete roounfold_svd_k; + delete roounfold_svd_tau; + } + + void set_sqrt_N_error(TH1D* hist) { + for (auto i = 1; i <= hist->GetNbinsX(); ++i) { + hist->SetBinError(i, sqrt(hist->GetBinContent(i))); + } + } + + void set_sqrt_N_error(TH2D* hist) { + for (auto i = 1; i <= hist->GetNbinsX(); ++i) { + for (auto j = 1; j <= hist->GetNbinsY(); ++j) { + hist->SetBinError(i, j, sqrt(hist->GetBinContent(i, j))); + } + } + } + + unsigned int nbins; + unsigned int n_toy; + int kreg; + double taureg; + TH1D* data, *gen_var, *reco_var; + TH2D* gen_vs_reco; + RooUnfoldResponse* roo_response; + RooUnfoldSvd* roounfold_svd_k; + RooUnfoldSvd* roounfold_svd_tau; + +}; + +BOOST_AUTO_TEST_SUITE (TestRooUnfoldSvd) + +BOOST_AUTO_TEST_CASE(test_set_and_get_tau) { + + RooUnfoldSvd r = RooUnfoldSvd(); + r.SetTauTerm(0.1); + BOOST_CHECK_EQUAL(r.GetTauTerm(), 0.1); +} + +BOOST_FIXTURE_TEST_CASE(test_get_tau_from_constructor, RooUnfoldSvdSetup) { + BOOST_CHECK_EQUAL(roounfold_svd_tau->GetTauTerm(), taureg); +} + +BOOST_FIXTURE_TEST_CASE(test_get_k_from_constructor, RooUnfoldSvdSetup) { + BOOST_CHECK_EQUAL(roounfold_svd_k->GetKterm(), kreg); +} + +BOOST_FIXTURE_TEST_CASE(test_k_unfold, RooUnfoldSvdSetup) { + TH1D* unfolded_data = (TH1D*) roounfold_svd_k->Hreco(RooUnfold::kCovToy); + for (auto i = 1; i <= unfolded_data->GetNbinsX(); ++i) { + BOOST_CHECK_CLOSE(unfolded_data->GetBinContent(i), gen_var->GetBinContent(i), unfolded_data->GetBinError(i)); + cout << unfolded_data->GetBinContent(i) << " +-" << unfolded_data->GetBinError(i) << endl; + } + delete unfolded_data; +} + +BOOST_FIXTURE_TEST_CASE(test_tau_unfold, RooUnfoldSvdSetup) { + // this gives Error in ::operator=(const TVectorT &)>: vectors not compatible + roounfold_svd_tau->SetKterm(3); + TH1D* unfolded_data = (TH1D*) roounfold_svd_tau->Hreco(RooUnfold::kCovToy); + // this gives Request index(-2) outside vector range of 0 - 7 +// TH1D* unfolded_data = (TH1D*) roounfold_svd_tau->Hreco(); + for (auto i = 1; i <= unfolded_data->GetNbinsX(); ++i) { + BOOST_CHECK_CLOSE(unfolded_data->GetBinContent(i), gen_var->GetBinContent(i), unfolded_data->GetBinError(i)); + cout << unfolded_data->GetBinContent(i) << " +-" << unfolded_data->GetBinError(i) << endl; + } + +// BOOST_CHECK_CLOSE(unfolded_data->GetBinContent(1), gen_var->GetBinContent(1), unfolded_data->GetBinError(1)); + delete unfolded_data; +} + +BOOST_FIXTURE_TEST_CASE(test_get_reg_parm_k, RooUnfoldSvdSetup) { + BOOST_CHECK_EQUAL(roounfold_svd_k->GetRegParm(), kreg); +} + +BOOST_FIXTURE_TEST_CASE(test_get_reg_parm_tau, RooUnfoldSvdSetup) { + BOOST_CHECK_EQUAL(roounfold_svd_tau->GetRegParm(), taureg); +} + +BOOST_AUTO_TEST_SUITE_END() + diff --git a/test/simpletest.cpp b/test/simpletest.cpp deleted file mode 100755 index ae29869..0000000 --- a/test/simpletest.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#define BOOST_TEST_MODULE SimpleTest -#include -int add(int i, int j) { - return i + j; -} - -BOOST_AUTO_TEST_SUITE(SimpleTest) -BOOST_AUTO_TEST_CASE( one_and_one ) { - BOOST_REQUIRE(add(1, 1) == 2); -} -BOOST_AUTO_TEST_SUITE_END( ) From 3fa74937fb79535831a1714255026223423c62aa Mon Sep 17 00:00:00 2001 From: kreczko Date: Thu, 26 Feb 2015 10:52:53 +0000 Subject: [PATCH 05/13] updating include path for examples --- examples/RooUnfoldDagostini.h | 2 +- examples/RooUnfoldExample.cxx | 4 ++-- examples/RooUnfoldTestHarness.h | 2 +- examples/RooUnfoldTestHarness.icc | 10 +++++----- examples/RooUnfoldTestHarness2D.icc | 2 +- examples/RooUnfoldTestHarness3D.icc | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/examples/RooUnfoldDagostini.h b/examples/RooUnfoldDagostini.h index a8eac89..53f5356 100644 --- a/examples/RooUnfoldDagostini.h +++ b/examples/RooUnfoldDagostini.h @@ -13,7 +13,7 @@ #ifndef ROOUNFOLDDAGOSTINI_H_ #define ROOUNFOLDDAGOSTINI_H_ -#include "RooUnfold.h" +#include "../include/RooUnfold.h" class RooUnfoldResponse; class TH1; diff --git a/examples/RooUnfoldExample.cxx b/examples/RooUnfoldExample.cxx index 81f5266..802d9c2 100644 --- a/examples/RooUnfoldExample.cxx +++ b/examples/RooUnfoldExample.cxx @@ -17,8 +17,8 @@ using std::endl; #include "TRandom.h" #include "TH1D.h" -#include "RooUnfoldResponse.h" -#include "RooUnfoldBayes.h" +#include "../include/RooUnfoldResponse.h" +#include "../include/RooUnfoldBayes.h" //#include "RooUnfoldSvd.h" //#include "RooUnfoldTUnfold.h" #endif diff --git a/examples/RooUnfoldTestHarness.h b/examples/RooUnfoldTestHarness.h index 29bb730..9ee21e1 100644 --- a/examples/RooUnfoldTestHarness.h +++ b/examples/RooUnfoldTestHarness.h @@ -16,7 +16,7 @@ #if !defined(__CINT__) || defined(__MAKECINT__) #include "TNamed.h" #include "TString.h" -#include "RooUnfold.h" +#include "../include/RooUnfold.h" #if ROOT_VERSION_CODE >= ROOT_VERSION(5,0,0) #include "TVectorDfwd.h" #include "TMatrixDfwd.h" diff --git a/examples/RooUnfoldTestHarness.icc b/examples/RooUnfoldTestHarness.icc index 14967cc..4d06812 100644 --- a/examples/RooUnfoldTestHarness.icc +++ b/examples/RooUnfoldTestHarness.icc @@ -37,11 +37,11 @@ #include "TLine.h" #include "TNtuple.h" #include "TProfile.h" -#include "RooUnfoldErrors.h" -#include "RooUnfoldParms.h" -#include "RooUnfoldResponse.h" -#include "RooUnfold.h" -#include "RooUnfoldSvd.h" +#include "../include/RooUnfoldErrors.h" +#include "../include/RooUnfoldParms.h" +#include "../include/RooUnfoldResponse.h" +#include "../include/RooUnfold.h" +#include "../include/RooUnfoldSvd.h" #ifdef USE_TUNFOLD_H #include "RooUnfoldTUnfold.h" #endif diff --git a/examples/RooUnfoldTestHarness2D.icc b/examples/RooUnfoldTestHarness2D.icc index 91a8721..f01f088 100644 --- a/examples/RooUnfoldTestHarness2D.icc +++ b/examples/RooUnfoldTestHarness2D.icc @@ -29,7 +29,7 @@ #include "TVectorD.h" #include "TLine.h" -#include "RooUnfoldResponse.h" +#include "../include/RooUnfoldResponse.h" #endif #include "ArgVars.h" diff --git a/examples/RooUnfoldTestHarness3D.icc b/examples/RooUnfoldTestHarness3D.icc index d4937e5..c887e4a 100644 --- a/examples/RooUnfoldTestHarness3D.icc +++ b/examples/RooUnfoldTestHarness3D.icc @@ -27,7 +27,7 @@ #include "TVectorD.h" #include "TLine.h" -#include "RooUnfoldResponse.h" +#include "../include/RooUnfoldResponse.h" #endif #include "ArgVars.h" From 3e1a27dd1c19b78e122c06a6e41a13d7299d488f Mon Sep 17 00:00:00 2001 From: kreczko Date: Thu, 26 Feb 2015 10:54:06 +0000 Subject: [PATCH 06/13] added Utils package --- include/RooUnfoldUtils.h | 24 ++++++++++++++++++++++++ include/RooUnfold_LinkDef.h | 1 + src/RooUnfoldUtils.cxx | 28 ++++++++++++++++++++++++++++ test/TestUtils.cpp | 27 +++++++++++++++++++++++++++ test/test_pyroot.py | 8 ++++++++ 5 files changed, 88 insertions(+) create mode 100644 include/RooUnfoldUtils.h create mode 100644 src/RooUnfoldUtils.cxx create mode 100644 test/TestUtils.cpp create mode 100644 test/test_pyroot.py diff --git a/include/RooUnfoldUtils.h b/include/RooUnfoldUtils.h new file mode 100644 index 0000000..edfa4c5 --- /dev/null +++ b/include/RooUnfoldUtils.h @@ -0,0 +1,24 @@ +/* + * RooUnfoldUtils.h + * + * Created on: 24 Feb 2015 + * Author: kreczko + */ + +#ifndef INCLUDE_ROOUNFOLDUTILS_H +#define INCLUDE_ROOUNFOLDUTILS_H + +#include "TVectorD.h" +namespace RooUnfoldUtils { + +/** + * Calculates equidistant points on a logarithmic scale + * + * parameters: + * - tau_min: minimal tau value (> 0) + * - tau_max: maximal tau value + * - n_points: number of points (> 3) + */ +TVectorD* calculate_tau_scan_points(double tau_min, double tau_max, unsigned int n_points); +} +#endif /* INCLUDE_ROOUNFOLDUTILS_H */ diff --git a/include/RooUnfold_LinkDef.h b/include/RooUnfold_LinkDef.h index 52e1636..93f7414 100644 --- a/include/RooUnfold_LinkDef.h +++ b/include/RooUnfold_LinkDef.h @@ -17,6 +17,7 @@ #pragma link C++ class RooUnfoldTUnfold+; #pragma link C++ class TauSVDUnfold+; #pragma link C++ class TSVDUnfold_local+; +#pragma link C++ class RooUnfoldUtils+; //#pragma link C++ class RooUnfoldDagostini+; #endif diff --git a/src/RooUnfoldUtils.cxx b/src/RooUnfoldUtils.cxx new file mode 100644 index 0000000..3bea7ba --- /dev/null +++ b/src/RooUnfoldUtils.cxx @@ -0,0 +1,28 @@ +/* + * RooUnfoldUtils.cxx + * + * Created on: 24 Feb 2015 + * Author: kreczko + */ +#include "../include/RooUnfoldUtils.h" +#include +namespace RooUnfoldUtils { +TVectorD* calculate_tau_scan_points(double tau_min, double tau_max, unsigned int n_points) { + // Use 3 scan points minimum + if (n_points < 3) + n_points = 3; + + // Setup Vector + TVectorD* points = new TVectorD(n_points); + + // Find the scan points + // Use equidistant steps on a logarithmic scale + double steplog = (log10(tau_max) - log10(tau_min)) / ((double) (n_points - 1)); + for (auto i = 0; i < n_points; i++) { + double posScanPoint = pow(10., (log10(tau_min) + ((double) i) * steplog)); + (*points)[i] = posScanPoint; + } + + return points; +} +} diff --git a/test/TestUtils.cpp b/test/TestUtils.cpp new file mode 100644 index 0000000..67be3ea --- /dev/null +++ b/test/TestUtils.cpp @@ -0,0 +1,27 @@ +/* + * TestUtils.cpp + * + * Created on: 24 Feb 2015 + * Author: kreczko + */ + +#include +#include "../include/RooUnfoldUtils.h" +#include + +BOOST_AUTO_TEST_SUITE (TestUtils) + +BOOST_AUTO_TEST_CASE(test_calculate_tau_scan_points) { + + TVectorD* points = RooUnfoldUtils::calculate_tau_scan_points(0.1, 1000, 4); + BOOST_CHECK_EQUAL(points->GetNrows(), 4); //right size + double step_size = (log10(1000) - log10(0.1)) / 3; + + for (auto i = 0; i < points->GetNrows(); ++i){ + BOOST_CHECK_EQUAL((*points)[i], pow(10, log10(0.1) + i* step_size)); + } +} + +BOOST_AUTO_TEST_SUITE_END() + + diff --git a/test/test_pyroot.py b/test/test_pyroot.py new file mode 100644 index 0000000..35238f6 --- /dev/null +++ b/test/test_pyroot.py @@ -0,0 +1,8 @@ +from ROOT import gSystem +gSystem.Load('libRooUnfold.so') +from ROOT import RooUnfold, RooUnfoldSvd, RooUnfoldResponse +from ROOT import RooUnfoldBayes, RooUnfoldBinByBin, RooUnfoldErrors +from ROOT import RooUnfoldInvert, RooUnfoldParms, RooUnfoldTUnfold +from ROOT import TauSVDUnfold +from ROOT import RooUnfoldUtils +assert 'calculate_tau_scan_points' in dir(RooUnfoldUtils) \ No newline at end of file From 5a30e7feb4f04b70094c16b5a6448c5a32dab22a Mon Sep 17 00:00:00 2001 From: kreczko Date: Thu, 26 Feb 2015 11:42:17 +0000 Subject: [PATCH 07/13] overloaded GetAdetCovMatrix & GetUnfoldCovMatrix to work with tau unfolding --- include/TSVDUnfold_local.h | 4 +- include/TauSVDUnfold.h | 3 +- src/TauSVDUnfold.cxx | 194 +++++++++++++++++- ...VDUnfoldTests.cpp => TestTauSVDUnfold.cpp} | 3 +- 4 files changed, 197 insertions(+), 7 deletions(-) rename test/{TauSVDUnfoldTests.cpp => TestTauSVDUnfold.cpp} (97%) diff --git a/include/TSVDUnfold_local.h b/include/TSVDUnfold_local.h index d81bc14..22f62ad 100644 --- a/include/TSVDUnfold_local.h +++ b/include/TSVDUnfold_local.h @@ -82,13 +82,13 @@ class TSVDUnfold_local : public TObject { // "cov" - covariance matrix on the measured spectrum, to be propagated // "ntoys" - number of pseudo experiments used for the propagation // "seed" - seed for pseudo experiments - TH2D* GetUnfoldCovMatrix( const TH2D* cov, Int_t ntoys, Int_t seed = 1 ); + virtual TH2D* GetUnfoldCovMatrix( const TH2D* cov, Int_t ntoys, Int_t seed = 1 ); // Determine covariance matrix of unfolded spectrum from finite statistics in // response matrix // "ntoys" - number of pseudo experiments used for the propagation // "seed" - seed for pseudo experiments - TH2D* GetAdetCovMatrix( Int_t ntoys, Int_t seed=1 ); + virtual TH2D* GetAdetCovMatrix( Int_t ntoys, Int_t seed=1 ); // Regularisation parameter Int_t GetKReg() const { return fKReg; } diff --git a/include/TauSVDUnfold.h b/include/TauSVDUnfold.h index 41289a6..cefd518 100644 --- a/include/TauSVDUnfold.h +++ b/include/TauSVDUnfold.h @@ -43,7 +43,8 @@ class TauSVDUnfold: public TSVDUnfold_local { TGraph* ScanLCurve(unsigned int n_point, double tau_min, double tau_max); double GetLcurveX() const; double GetLcurveY() const; - + virtual TH2D* GetUnfoldCovMatrix( const TH2D* cov, Int_t ntoys, Int_t seed ); + virtual TH2D* GetAdetCovMatrix( Int_t ntoys, Int_t seed ); /** * Added by Joern: adapted from TSVDUnfold::GetUnfoldCovMatrix to include * the normalisation in the procedure diff --git a/src/TauSVDUnfold.cxx b/src/TauSVDUnfold.cxx index 058649c..73c5afe 100644 --- a/src/TauSVDUnfold.cxx +++ b/src/TauSVDUnfold.cxx @@ -9,6 +9,7 @@ #include "TDecompSVD.h" #include "TMath.h" #include "TH1D.h" +#include "TRandom3.h" #include #include @@ -139,7 +140,7 @@ TH1D* TauSVDUnfold::Unfold(double tau) { TMatrixD Vort = ASVD.GetV(); // TODO: This part is failing for tau unfolding TVectorD ASV = ASVD.GetSig(); - fASV = ASV; +// fASV = TVectorD(ASV); if (!fToyMode && !fMatToyMode) { V2H(ASV, *fSVHist); } @@ -246,7 +247,6 @@ double TauSVDUnfold::kToTau(int kreg) const { return tau; } - TH2D* TauSVDUnfold::get_data_covariance_matrix(const TH1D* data_histogram) { // get bins from data_histogram unsigned int n_bins = data_histogram->GetNbinsX(); @@ -272,7 +272,7 @@ TH2D* TauSVDUnfold::get_data_covariance_matrix(const TH1D* data_histogram) { } TH1D* TauSVDUnfold::get_global_correlation_hist(const TH1D* data_histogram) { - TH2D* covariance_hist = (TH2D*) TauSVDUnfold::get_data_covariance_matrix(data_histogram)->Clone(); + TH2D* covariance_hist = (TH2D*) TauSVDUnfold::get_data_covariance_matrix(data_histogram); unsigned int n_bins = data_histogram->GetNbinsX(); vector bin_map; @@ -435,3 +435,191 @@ double TauSVDUnfold::get_global_correlation(const TH1D* data_histogram) { return average; } + +TH2D* TauSVDUnfold::GetUnfoldCovMatrix(const TH2D* cov, Int_t ntoys, Int_t seed) { + // Determine for given input error matrix covariance matrix of unfolded + // spectrum from toy simulation given the passed covariance matrix on measured spectrum + // "cov" - covariance matrix on the measured spectrum, to be propagated + // "ntoys" - number of pseudo experiments used for the propagation + // "seed" - seed for pseudo experiments + // Note that this covariance matrix will contain effects of forced normalisation if spectrum is normalised to unit area. + + fToyMode = true; + TH1D* unfres = 0; + TH2D* unfcov = (TH2D*) fAdet->Clone("unfcovmat"); + unfcov->SetTitle("Toy covariance matrix"); + for (int i = 1; i <= fNdim; i++) + for (int j = 1; j <= fNdim; j++) + unfcov->SetBinContent(i, j, 0.); + + // Code for generation of toys (taken from RooResult and modified) + // Calculate the elements of the upper-triangular matrix L that + // gives Lt*L = C, where Lt is the transpose of L (the "square-root method") + TMatrixD L(fNdim, fNdim); + L *= 0; + + for (Int_t iPar = 0; iPar < fNdim; iPar++) { + + // Calculate the diagonal term first + L(iPar, iPar) = cov->GetBinContent(iPar + 1, iPar + 1); + for (Int_t k = 0; k < iPar; k++) + L(iPar, iPar) -= TMath::Power(L(k, iPar), 2); + if (L(iPar, iPar) > 0.0) + L(iPar, iPar) = TMath::Sqrt(L(iPar, iPar)); + else + L(iPar, iPar) = 0.0; + + // ...then the off-diagonal terms + for (Int_t jPar = iPar + 1; jPar < fNdim; jPar++) { + L(iPar, jPar) = cov->GetBinContent(iPar + 1, jPar + 1); + for (Int_t k = 0; k < iPar; k++) + L(iPar, jPar) -= L(k, iPar) * L(k, jPar); + if (L(iPar, iPar) != 0.) + L(iPar, jPar) /= L(iPar, iPar); + else + L(iPar, jPar) = 0; + } + } + + // Remember it + TMatrixD *Lt = new TMatrixD(TMatrixD::kTransposed, L); + TRandom3 random(seed); + + fToyhisto = (TH1D*) fBdat->Clone("toyhisto"); + TH1D *toymean = (TH1D*) fBdat->Clone("toymean"); + for (Int_t j = 1; j <= fNdim; j++) + toymean->SetBinContent(j, 0.); + + // Get the mean of the toys first + for (int i = 1; i <= ntoys; i++) { + + // create a vector of unit Gaussian variables + TVectorD g(fNdim); + for (Int_t k = 0; k < fNdim; k++) + g(k) = random.Gaus(0., 1.); + + // Multiply this vector by Lt to introduce the appropriate correlations + g *= (*Lt); + + // Add the mean value offsets and store the results + for (int j = 1; j <= fNdim; j++) { + fToyhisto->SetBinContent(j, fBdat->GetBinContent(j) + g(j - 1)); + fToyhisto->SetBinError(j, fBdat->GetBinError(j)); + } + unfres = Unfold(GetTau()); + + for (Int_t j = 1; j <= fNdim; j++) { + toymean->SetBinContent(j, toymean->GetBinContent(j) + unfres->GetBinContent(j) / ntoys); + } + delete unfres; + unfres = 0; + } + + // Reset the random seed + random.SetSeed(seed); + + //Now the toys for the covariance matrix + for (int i = 1; i <= ntoys; i++) { + + // Create a vector of unit Gaussian variables + TVectorD g(fNdim); + for (Int_t k = 0; k < fNdim; k++) + g(k) = random.Gaus(0., 1.); + + // Multiply this vector by Lt to introduce the appropriate correlations + g *= (*Lt); + + // Add the mean value offsets and store the results + for (int j = 1; j <= fNdim; j++) { + fToyhisto->SetBinContent(j, fBdat->GetBinContent(j) + g(j - 1)); + fToyhisto->SetBinError(j, fBdat->GetBinError(j)); + } + unfres = Unfold(GetTau()); + + for (Int_t j = 1; j <= fNdim; j++) { + for (Int_t k = 1; k <= fNdim; k++) { + unfcov->SetBinContent(j, k, + unfcov->GetBinContent(j, k) + + ((unfres->GetBinContent(j) - toymean->GetBinContent(j)) + * (unfres->GetBinContent(k) - toymean->GetBinContent(k)) / (ntoys - 1))); + } + } + delete unfres; + unfres = 0; + } + delete Lt; + delete toymean; + fToyMode = kFALSE; + + return unfcov; +} + +TH2D* TauSVDUnfold::GetAdetCovMatrix(Int_t ntoys, Int_t seed = 1) { + // Determine covariance matrix of unfolded spectrum from finite statistics in + // response matrix using pseudo experiments + // "ntoys" - number of pseudo experiments used for the propagation + // "seed" - seed for pseudo experiments + + fMatToyMode = true; + TH1D* unfres = 0; + TH2D* unfcov = (TH2D*) fAdet->Clone("unfcovmat"); + unfcov->SetTitle("Toy covariance matrix"); + for (int i = 1; i <= fNdim; i++) + for (int j = 1; j <= fNdim; j++) + unfcov->SetBinContent(i, j, 0.); + + //Now the toys for the detector response matrix + TRandom3 random(seed); + + fToymat = (TH2D*) fAdet->Clone("toymat"); + TH1D *toymean = (TH1D*) fXini->Clone("toymean"); + for (Int_t j = 1; j <= fNdim; j++) + toymean->SetBinContent(j, 0.); + + for (int i = 1; i <= ntoys; i++) { + for (Int_t k = 1; k <= fNdim; k++) { + for (Int_t m = 1; m <= fNdim; m++) { + if (fAdet->GetBinContent(k, m)) { + fToymat->SetBinContent(k, m, random.Poisson(fAdet->GetBinContent(k, m))); + } + } + } + + unfres = Unfold(GetTau()); + + for (Int_t j = 1; j <= fNdim; j++) { + toymean->SetBinContent(j, toymean->GetBinContent(j) + unfres->GetBinContent(j) / ntoys); + } + delete unfres; + unfres = 0; + } + + // Reset the random seed + random.SetSeed(seed); + + for (int i = 1; i <= ntoys; i++) { + for (Int_t k = 1; k <= fNdim; k++) { + for (Int_t m = 1; m <= fNdim; m++) { + if (fAdet->GetBinContent(k, m)) + fToymat->SetBinContent(k, m, random.Poisson(fAdet->GetBinContent(k, m))); + } + } + + unfres = Unfold(GetTau()); + + for (Int_t j = 1; j <= fNdim; j++) { + for (Int_t k = 1; k <= fNdim; k++) { + unfcov->SetBinContent(j, k, + unfcov->GetBinContent(j, k) + + ((unfres->GetBinContent(j) - toymean->GetBinContent(j)) + * (unfres->GetBinContent(k) - toymean->GetBinContent(k)) / (ntoys - 1))); + } + } + delete unfres; + unfres = 0; + } + delete toymean; + fMatToyMode = kFALSE; + + return unfcov; +} diff --git a/test/TauSVDUnfoldTests.cpp b/test/TestTauSVDUnfold.cpp similarity index 97% rename from test/TauSVDUnfoldTests.cpp rename to test/TestTauSVDUnfold.cpp index 08b9ca7..a481fdb 100644 --- a/test/TauSVDUnfoldTests.cpp +++ b/test/TestTauSVDUnfold.cpp @@ -27,7 +27,8 @@ struct TauSVDUnfoldSetup { roounfold_svd_k(), roounfold_svd_tau(){ gROOT->SetBatch(1); - gROOT->ProcessLine("gErrorIgnoreLevel = 1001;"); +// gROOT->ProcessLine("gErrorIgnoreLevel = 1001;"); + gROOT->ProcessLine("gErrorAbortLevel = 1001;"); // from toy MC 1 data->SetBinContent(1, 365); data->SetBinContent(2, 578); From ba3fe064d0fddab8d6244115857b723b25b6b5c8 Mon Sep 17 00:00:00 2001 From: kreczko Date: Thu, 26 Feb 2015 16:04:47 +0000 Subject: [PATCH 08/13] setting default verbosity to 0 --- src/RooUnfold.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/RooUnfold.cxx b/src/RooUnfold.cxx index 633f460..951018a 100644 --- a/src/RooUnfold.cxx +++ b/src/RooUnfold.cxx @@ -225,7 +225,7 @@ void RooUnfold::Init() _covMes= _covL= 0; _meas= _measmine= 0; _nm= _nt= 0; - _verbose= 1; + _verbose= 0; _overflow= 0; _unfolded= _haveCov= _haveCovMes= _fail= _have_err_mat= _haveErrors= false; _NToys=50; From b569bd8c6a02319b549d3a84dd2368ff0adf04db Mon Sep 17 00:00:00 2001 From: kreczko Date: Sun, 1 Mar 2015 12:31:25 +0000 Subject: [PATCH 09/13] added more RooUnfoldSvd tests --- test/TestRooUnfoldSvd.cpp | 70 ++++++++++++++++++++++++++++++--------- 1 file changed, 54 insertions(+), 16 deletions(-) diff --git a/test/TestRooUnfoldSvd.cpp b/test/TestRooUnfoldSvd.cpp index 4b2a82f..85aa3a8 100644 --- a/test/TestRooUnfoldSvd.cpp +++ b/test/TestRooUnfoldSvd.cpp @@ -29,7 +29,9 @@ struct RooUnfoldSvdSetup { roounfold_svd_k(), roounfold_svd_tau() { gROOT->SetBatch(1); -// gROOT->ProcessLine("gErrorIgnoreLevel = 1001;"); + gROOT->ProcessLine("gErrorIgnoreLevel = 1001;"); + // crash on ROOT::Error + gROOT->ProcessLine("gErrorAbortLevel = 2001;"); // from toy MC 1 data->SetBinContent(1, 365); data->SetBinContent(2, 578); @@ -114,6 +116,14 @@ struct RooUnfoldSvdSetup { } } + void check_unfolded_data_against_truth(const TH1D* unfolded_data, bool use_sqrt_N = false) { + for (auto i = 1; i <= unfolded_data->GetNbinsX(); ++i) { + double error = use_sqrt_N ? sqrt(unfolded_data->GetBinContent(i)) : unfolded_data->GetBinError(i); + BOOST_CHECK_CLOSE(unfolded_data->GetBinContent(i), gen_var->GetBinContent(i), error); +// cout << unfolded_data->GetBinContent(i) << " +-" << error << endl; + } + } + unsigned int nbins; unsigned int n_toy; int kreg; @@ -145,28 +155,56 @@ BOOST_FIXTURE_TEST_CASE(test_get_k_from_constructor, RooUnfoldSvdSetup) { BOOST_FIXTURE_TEST_CASE(test_k_unfold, RooUnfoldSvdSetup) { TH1D* unfolded_data = (TH1D*) roounfold_svd_k->Hreco(RooUnfold::kCovToy); - for (auto i = 1; i <= unfolded_data->GetNbinsX(); ++i) { - BOOST_CHECK_CLOSE(unfolded_data->GetBinContent(i), gen_var->GetBinContent(i), unfolded_data->GetBinError(i)); - cout << unfolded_data->GetBinContent(i) << " +-" << unfolded_data->GetBinError(i) << endl; - } + check_unfolded_data_against_truth(unfolded_data); delete unfolded_data; } -BOOST_FIXTURE_TEST_CASE(test_tau_unfold, RooUnfoldSvdSetup) { - // this gives Error in ::operator=(const TVectorT &)>: vectors not compatible - roounfold_svd_tau->SetKterm(3); - TH1D* unfolded_data = (TH1D*) roounfold_svd_tau->Hreco(RooUnfold::kCovToy); - // this gives Request index(-2) outside vector range of 0 - 7 -// TH1D* unfolded_data = (TH1D*) roounfold_svd_tau->Hreco(); - for (auto i = 1; i <= unfolded_data->GetNbinsX(); ++i) { - BOOST_CHECK_CLOSE(unfolded_data->GetBinContent(i), gen_var->GetBinContent(i), unfolded_data->GetBinError(i)); - cout << unfolded_data->GetBinContent(i) << " +-" << unfolded_data->GetBinError(i) << endl; - } +BOOST_FIXTURE_TEST_CASE(test_k_unfold_kNoError_errors, RooUnfoldSvdSetup) { + TH1D* unfolded_data = (TH1D*) roounfold_svd_k->Hreco(RooUnfold::kNoError); + check_unfolded_data_against_truth(unfolded_data, true); + delete unfolded_data; +} + +BOOST_FIXTURE_TEST_CASE(test_k_unfold_kErrors_errors, RooUnfoldSvdSetup) { + TH1D* unfolded_data = (TH1D*) roounfold_svd_k->Hreco(RooUnfold::kErrors); + check_unfolded_data_against_truth(unfolded_data); + delete unfolded_data; +} -// BOOST_CHECK_CLOSE(unfolded_data->GetBinContent(1), gen_var->GetBinContent(1), unfolded_data->GetBinError(1)); +BOOST_FIXTURE_TEST_CASE(test_k_unfold_kCovariance_errors, RooUnfoldSvdSetup) { + TH1D* unfolded_data = (TH1D*) roounfold_svd_k->Hreco(RooUnfold::kCovariance); + check_unfolded_data_against_truth(unfolded_data); delete unfolded_data; } +BOOST_FIXTURE_TEST_CASE(test_tau_unfold_kNoError_errors, RooUnfoldSvdSetup) { + // FIXME: Hreco has errors == 0 + TH1D* unfolded_data = (TH1D*) roounfold_svd_tau->Hreco(RooUnfold::kNoError); + // the bug can be seen with + // check_unfolded_data_against_truth(unfolded_data); + check_unfolded_data_against_truth(unfolded_data, true); + delete unfolded_data; +} + +BOOST_FIXTURE_TEST_CASE(test_tau_unfold_kErrors_errors, RooUnfoldSvdSetup) { + TH1D* unfolded_data = (TH1D*) roounfold_svd_tau->Hreco(RooUnfold::kErrors); + check_unfolded_data_against_truth(unfolded_data); + delete unfolded_data; +} + +BOOST_FIXTURE_TEST_CASE(test_tau_unfold_kCovariance_errors, RooUnfoldSvdSetup) { + TH1D* unfolded_data = (TH1D*) roounfold_svd_tau->Hreco(RooUnfold::kCovariance); + check_unfolded_data_against_truth(unfolded_data); + delete unfolded_data; +} + +BOOST_FIXTURE_TEST_CASE(test_tau_unfold_kCovToy_errors, RooUnfoldSvdSetup) { + TH1D* unfolded_data = (TH1D*) roounfold_svd_tau->Hreco(RooUnfold::kCovToy); + check_unfolded_data_against_truth(unfolded_data); + delete unfolded_data; +} + + BOOST_FIXTURE_TEST_CASE(test_get_reg_parm_k, RooUnfoldSvdSetup) { BOOST_CHECK_EQUAL(roounfold_svd_k->GetRegParm(), kreg); } From ae847f3764e041ea0bca437fb118803452ad8279 Mon Sep 17 00:00:00 2001 From: kreczko Date: Sun, 1 Mar 2015 12:41:45 +0000 Subject: [PATCH 10/13] fixing gitignore --- .gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 2d3f533..5cd612f 100644 --- a/.gitignore +++ b/.gitignore @@ -16,4 +16,6 @@ Makefile *~ *Dict.cxx *Dict_rdict.pcm -Test* +Test/* +/Test/ +*.pyc From 1f07eded354db357f8baf54300bacbb1e28d205f Mon Sep 17 00:00:00 2001 From: kreczko Date: Sun, 1 Mar 2015 12:42:14 +0000 Subject: [PATCH 11/13] adding new BOOST test main --- test/TestRooUnfoldSvd.cpp | 5 ----- test/boost_test.cpp | 18 ++++++++++++++++++ 2 files changed, 18 insertions(+), 5 deletions(-) create mode 100644 test/boost_test.cpp diff --git a/test/TestRooUnfoldSvd.cpp b/test/TestRooUnfoldSvd.cpp index 85aa3a8..44e20b1 100644 --- a/test/TestRooUnfoldSvd.cpp +++ b/test/TestRooUnfoldSvd.cpp @@ -10,7 +10,6 @@ #include "../include/RooUnfoldSvd.h" #include #include "TH2D.h" -#include "TROOT.h" #include using namespace std; @@ -28,10 +27,6 @@ struct RooUnfoldSvdSetup { roo_response(), roounfold_svd_k(), roounfold_svd_tau() { - gROOT->SetBatch(1); - gROOT->ProcessLine("gErrorIgnoreLevel = 1001;"); - // crash on ROOT::Error - gROOT->ProcessLine("gErrorAbortLevel = 2001;"); // from toy MC 1 data->SetBinContent(1, 365); data->SetBinContent(2, 578); diff --git a/test/boost_test.cpp b/test/boost_test.cpp new file mode 100644 index 0000000..b012654 --- /dev/null +++ b/test/boost_test.cpp @@ -0,0 +1,18 @@ +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE RooUnfoldTests +#include +#include "TH1.h" +#include "TROOT.h" + +struct GlobalSetup { + GlobalSetup() { + TH1::AddDirectory(false); + gROOT->SetBatch(1); + gROOT->ProcessLine("gErrorIgnoreLevel = 1001;"); + gROOT->ProcessLine("gErrorAbortLevel = 1001;"); + } + ~GlobalSetup() { + } +}; + +BOOST_GLOBAL_FIXTURE(GlobalSetup); From a08d3bb500df7485d812e48591d7cf7cab400961 Mon Sep 17 00:00:00 2001 From: kreczko Date: Sun, 1 Mar 2015 16:54:13 +0000 Subject: [PATCH 12/13] added TVector test for understanding --- test/TestTVectorD.cpp | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 test/TestTVectorD.cpp diff --git a/test/TestTVectorD.cpp b/test/TestTVectorD.cpp new file mode 100644 index 0000000..3ede3c8 --- /dev/null +++ b/test/TestTVectorD.cpp @@ -0,0 +1,34 @@ +/* + * File: TauSVDUnfoldTests.cpp + * Author: ale + * + * Created on August 13, 2014, 6:49 PM + */ +#include +#include +#include "TVectorD.h" +#include + +using namespace std; + +BOOST_AUTO_TEST_SUITE (TVectorDTestSuite) +BOOST_AUTO_TEST_CASE(test_assign) { + uint32_t n(3); + double elements[n] = { 1., 2., 3. }; + TVectorD vector = TVectorD(n, elements); + BOOST_CHECK_EQUAL(vector.GetNoElements(), n); + + // initialise vector with default constructor + TVectorD copy = TVectorD(); + copy.Clear(); + // does not work without resize + copy.ResizeTo(n); + // this returns "vectors not compatible" without copy.ResizeTo(n); + copy = vector; + BOOST_CHECK_EQUAL(copy.GetNoElements(), n); + BOOST_CHECK_EQUAL(copy[0], 1.); + BOOST_CHECK_EQUAL(copy[1], 2.); + BOOST_CHECK_EQUAL(copy[2], 3.); +} + +BOOST_AUTO_TEST_SUITE_END() From 35f41bdaa71404f2aaff42664b15b19d5ad93420 Mon Sep 17 00:00:00 2001 From: kreczko Date: Sun, 1 Mar 2015 16:56:54 +0000 Subject: [PATCH 13/13] added k->tau --- ci/test.sh | 4 +-- include/TauSVDUnfold.h | 5 ++-- src/TauSVDUnfold.cxx | 46 ++++++++++++++++++++----------- test/TestTVectorD.cpp | 13 ++++----- test/TestTauSVDUnfold.cpp | 58 ++++++++++++++++++++++++++++----------- 5 files changed, 83 insertions(+), 43 deletions(-) diff --git a/ci/test.sh b/ci/test.sh index f9225a5..e1affe5 100644 --- a/ci/test.sh +++ b/ci/test.sh @@ -11,8 +11,8 @@ echo "Checking PyROOT installation" time python -c 'import ROOT; ROOT.TBrowser()' # Check that RooUnfold can be imported -echo "Checking RooUnfold library" +echo "Checking RooUnfold library in PyROOT" time python -c 'from ROOT import gSystem; gSystem.Load("libRooUnfold.so");from ROOT import RooUnfoldResponse' - +time python test/test_pyroot.py echo "Executing unit tests" make test diff --git a/include/TauSVDUnfold.h b/include/TauSVDUnfold.h index cefd518..80efec6 100644 --- a/include/TauSVDUnfold.h +++ b/include/TauSVDUnfold.h @@ -65,10 +65,11 @@ class TauSVDUnfold: public TSVDUnfold_local { */ static TH2D* get_data_covariance_matrix(const TH1D* data_histogram); - static double get_global_correlation(const TH1D* data_histogram); + static double get_global_correlation(const TH2D* stat_cov_hist, const TH1D* data_histogram); - static TH1D* get_global_correlation_hist(const TH1D* data_histogram); + static TH1D* get_global_correlation_hist(const TH2D* covariance_hist, const TH1D* data_histogram); + TVectorD getASV() const; protected: double fTau; double fCurv; diff --git a/src/TauSVDUnfold.cxx b/src/TauSVDUnfold.cxx index 73c5afe..7f92a07 100644 --- a/src/TauSVDUnfold.cxx +++ b/src/TauSVDUnfold.cxx @@ -138,9 +138,11 @@ TH1D* TauSVDUnfold::Unfold(double tau) { TDecompSVD ASVD(mA * mCinv); TMatrixD Uort = ASVD.GetU(); TMatrixD Vort = ASVD.GetV(); - // TODO: This part is failing for tau unfolding + // A = fU fSig fV^T TVectorD ASV = ASVD.GetSig(); -// fASV = TVectorD(ASV); + fASV.Clear(); + fASV.ResizeTo(ASV.GetNoElements()); + fASV = ASV; if (!fToyMode && !fMatToyMode) { V2H(ASV, *fSVHist); } @@ -242,7 +244,7 @@ TH1D* TauSVDUnfold::Unfold(double tau) { double TauSVDUnfold::kToTau(int kreg) const { double tau(0.); - if (fASV.NonZeros() == 0 && kreg > 0) + if (fASV.NonZeros() > 0 && kreg > 0) tau = fASV(kreg); return tau; } @@ -271,10 +273,8 @@ TH2D* TauSVDUnfold::get_data_covariance_matrix(const TH1D* data_histogram) { return data_covariance_matrix; } -TH1D* TauSVDUnfold::get_global_correlation_hist(const TH1D* data_histogram) { - TH2D* covariance_hist = (TH2D*) TauSVDUnfold::get_data_covariance_matrix(data_histogram); - - unsigned int n_bins = data_histogram->GetNbinsX(); +TH1D* TauSVDUnfold::get_global_correlation_hist(const TH2D* covariance_hist, const TH1D* data_histogram) { + uint32_t n_bins = data_histogram->GetNbinsX(); vector bin_map; bin_map.resize(n_bins); @@ -282,7 +282,7 @@ TH1D* TauSVDUnfold::get_global_correlation_hist(const TH1D* data_histogram) { unsigned int bin_counter(0); // all bins except underflow (0) and overflow (nbins + 1) - for (auto i = 1; i <= n_bins; ++i) { + for (uint32_t i = 1; i <= n_bins; ++i) { double data = data_histogram->GetBinContent(i); if (data <= 0.) { // Through out bin with no data @@ -291,7 +291,7 @@ TH1D* TauSVDUnfold::get_global_correlation_hist(const TH1D* data_histogram) { } else { // Search for bins with empty rows/columns bool skip_bin = true; - for (auto j = 1; j <= n_bins; ++j) { + for (uint32_t j = 1; j <= n_bins; ++j) { double value = covariance_hist->GetBinContent(i, j); if (value != 0.) { skip_bin = false; @@ -383,10 +383,6 @@ TH1D* TauSVDUnfold::get_global_correlation_hist(const TH1D* data_histogram) { if (cov_prod > 0) var = 1. / cov_prod; double global_correlation_squared = 0.; -// cout << "cov: " << cov << endl; -// cout << "covinv: " << covinv << endl; -// cout << "cov_prod: " << cov_prod << endl; -// cout << "var: " << var << endl; if (var > 0.) global_correlation_squared = 1. - var; @@ -403,13 +399,13 @@ TH1D* TauSVDUnfold::get_global_correlation_hist(const TH1D* data_histogram) { global_correlation_hist->SetBinContent(i, global_correlation); global_correlation_hist->SetBinError(i, 0.); } - delete covariance_hist; return global_correlation_hist; } -double TauSVDUnfold::get_global_correlation(const TH1D* data_histogram) { - TH1D * global_correlation_hist = TauSVDUnfold::get_global_correlation_hist(data_histogram); +double TauSVDUnfold::get_global_correlation(const TH2D* covariance_hist, const TH1D* data_histogram) { + + TH1D * global_correlation_hist = TauSVDUnfold::get_global_correlation_hist(covariance_hist, data_histogram); double sum = 0.; double average = 0.; @@ -623,3 +619,21 @@ TH2D* TauSVDUnfold::GetAdetCovMatrix(Int_t ntoys, Int_t seed = 1) { return unfcov; } + +double TauSVDUnfold::GetLcurveX() const { + return 0; +} + +double TauSVDUnfold::GetLcurveY() const { + return 0; +} + +TGraph* TauSVDUnfold::ScanLCurve(unsigned int n_point, double tau_min, double tau_max){ + return 0; +} + +TVectorD TauSVDUnfold::getASV() const { + return fASV; +} + + diff --git a/test/TestTVectorD.cpp b/test/TestTVectorD.cpp index 3ede3c8..9f4663e 100644 --- a/test/TestTVectorD.cpp +++ b/test/TestTVectorD.cpp @@ -8,24 +8,23 @@ #include #include "TVectorD.h" #include - +#define N 3 using namespace std; BOOST_AUTO_TEST_SUITE (TVectorDTestSuite) BOOST_AUTO_TEST_CASE(test_assign) { - uint32_t n(3); - double elements[n] = { 1., 2., 3. }; - TVectorD vector = TVectorD(n, elements); - BOOST_CHECK_EQUAL(vector.GetNoElements(), n); + double elements[N] = { 1., 2., 3. }; + TVectorD vector = TVectorD(N, elements); + BOOST_CHECK_EQUAL(vector.GetNoElements(), N); // initialise vector with default constructor TVectorD copy = TVectorD(); copy.Clear(); // does not work without resize - copy.ResizeTo(n); + copy.ResizeTo(N); // this returns "vectors not compatible" without copy.ResizeTo(n); copy = vector; - BOOST_CHECK_EQUAL(copy.GetNoElements(), n); + BOOST_CHECK_EQUAL(copy.GetNoElements(), N); BOOST_CHECK_EQUAL(copy[0], 1.); BOOST_CHECK_EQUAL(copy[1], 2.); BOOST_CHECK_EQUAL(copy[2], 3.); diff --git a/test/TestTauSVDUnfold.cpp b/test/TestTauSVDUnfold.cpp index a481fdb..163aa68 100644 --- a/test/TestTauSVDUnfold.cpp +++ b/test/TestTauSVDUnfold.cpp @@ -9,7 +9,6 @@ #include "../include/RooUnfoldSvd.h" #include "../include/RooUnfoldResponse.h" #include -#include "TROOT.h" using namespace std; @@ -23,12 +22,10 @@ struct TauSVDUnfoldSetup { gen_var(new TH1D("gen_var", "gen_var", nbins, 0, nbins)), reco_var(new TH1D("reco_var", "reco_var", nbins, 0, nbins)), gen_vs_reco(new TH2D("gen_vs_reco", "gen_vs_reco", nbins, 0, nbins, nbins, 0, nbins)), + cov_hist(), roo_response(), roounfold_svd_k(), - roounfold_svd_tau(){ - gROOT->SetBatch(1); -// gROOT->ProcessLine("gErrorIgnoreLevel = 1001;"); - gROOT->ProcessLine("gErrorAbortLevel = 1001;"); + roounfold_svd_tau() { // from toy MC 1 data->SetBinContent(1, 365); data->SetBinContent(2, 578); @@ -45,7 +42,7 @@ struct TauSVDUnfoldSetup { reco_var->SetBinContent(4, 195); reco_var->SetBinContent(5, 61); reco_var->SetBinContent(6, 29); - set_sqrt_N_error (reco_var); + set_sqrt_N_error(reco_var); gen_var->SetBinContent(1, 3441); gen_var->SetBinContent(2, 5181); @@ -88,15 +85,18 @@ struct TauSVDUnfoldSetup { roounfold_svd_k = new RooUnfoldSvd(roo_response, data, kreg, n_toy); roounfold_svd_tau = new RooUnfoldSvd(roo_response, data, taureg, n_toy); + roounfold_svd_tau->Hreco(RooUnfold::kNoError); + TH2D* cov = TauSVDUnfold::get_data_covariance_matrix(data); + cov_hist = roounfold_svd_tau->Impl()->GetUnfoldCovMatrix(cov, n_toy); + delete cov; } ~TauSVDUnfoldSetup() { delete data; delete gen_var; delete reco_var; delete gen_vs_reco; + delete cov_hist; delete roo_response; -// delete tau_svd_unfold; - delete roounfold_svd_k; delete roounfold_svd_tau; } @@ -114,14 +114,14 @@ struct TauSVDUnfoldSetup { } } - unsigned int nbins; + uint32_t nbins; unsigned int n_toy; int kreg; double taureg; TH1D* data, *gen_var, *reco_var; TH2D* gen_vs_reco; + TH2D* cov_hist; RooUnfoldResponse* roo_response; -// TauSVDUnfold* tau_svd_unfold; RooUnfoldSvd* roounfold_svd_k; RooUnfoldSvd* roounfold_svd_tau; @@ -130,7 +130,7 @@ struct TauSVDUnfoldSetup { BOOST_AUTO_TEST_SUITE (TauSVDUnfoldTestSuite) BOOST_FIXTURE_TEST_CASE(test_get_data_covariance_matrix, TauSVDUnfoldSetup) { TH2D* cov = TauSVDUnfold::get_data_covariance_matrix(data); - for (auto i = 1; i <= nbins; ++i) { + for (uint32_t i = 1; i <= nbins; ++i) { double data_error = data->GetBinError(i); BOOST_CHECK_EQUAL(cov->GetBinContent(i, i), data_error * data_error); } @@ -138,16 +138,42 @@ BOOST_FIXTURE_TEST_CASE(test_get_data_covariance_matrix, TauSVDUnfoldSetup) { } BOOST_FIXTURE_TEST_CASE(test_get_global_correlation, TauSVDUnfoldSetup) { - double corr = TauSVDUnfold::get_global_correlation(data); - BOOST_CHECK_EQUAL(corr, -1.); + double corr = TauSVDUnfold::get_global_correlation(cov_hist, data); + BOOST_CHECK_CLOSE(corr, 99, 1); } BOOST_FIXTURE_TEST_CASE(test_get_global_correlation_hist, TauSVDUnfoldSetup) { - TH1D* corr_hist = TauSVDUnfold::get_global_correlation_hist(data); - for (auto i = 1; i <= nbins; ++i) { - BOOST_CHECK_EQUAL(corr_hist->GetBinContent(i), i * i); + TH1D* corr_hist = TauSVDUnfold::get_global_correlation_hist(cov_hist, data); + // for the above example, the first bin should be around 95 % + BOOST_CHECK_CLOSE(corr_hist->GetBinContent(1), 95, 1); + // for all others it should be between 99 and 100 % + for (uint32_t i = 2; i <= nbins; ++i) { + BOOST_CHECK_CLOSE(corr_hist->GetBinContent(i), 99, 1); } delete corr_hist; } +BOOST_FIXTURE_TEST_CASE(test_k_to_tau, TauSVDUnfoldSetup) { + const TauSVDUnfold* tau_svd = (TauSVDUnfold*) roounfold_svd_tau->Impl(); + double tau = tau_svd->GetTau(); + BOOST_CHECK_EQUAL(tau, taureg); + TVectorD ASV = tau_svd->getASV(); + uint32_t n_elements = ASV.GetNoElements(); + BOOST_CHECK_EQUAL(n_elements, nbins + 1); + tau = tau_svd->kToTau(kreg); + BOOST_CHECK_CLOSE(tau, 3.83, 0.1); +} + +BOOST_FIXTURE_TEST_CASE(test_get_tau, TauSVDUnfoldSetup) { + double tau = ((TauSVDUnfold*) roounfold_svd_tau->Impl())->GetTau(); + BOOST_CHECK_EQUAL(tau, taureg); +} + +BOOST_FIXTURE_TEST_CASE(test_get_ASV, TauSVDUnfoldSetup) { + const TauSVDUnfold* tau_svd = (TauSVDUnfold*) roounfold_svd_tau->Impl(); + TVectorD ASV = tau_svd->getASV(); + uint32_t n_elements = ASV.GetNoElements(); + BOOST_CHECK_EQUAL(n_elements, nbins + 1); + BOOST_CHECK(ASV.NonZeros() > 0); +} BOOST_AUTO_TEST_SUITE_END()