Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TUnfold.h
Go to the documentation of this file.
1 // Author: Stefan Schmitt
2 // DESY, 13/10/08
3 
4 // Version 17.6, updated doxygen-style comments, add one argument for scanLCurve
5 //
6 // History:
7 // Version 17.5, fix memory leak and other bugs
8 // Version 17.4, in parallel to changes in TUnfoldBinning
9 // Version 17.3, in parallel to changes in TUnfoldBinning
10 // Version 17.2, in parallel to changes in TUnfoldBinning
11 // Version 17.1, bug fixes in GetFoldedOutput, GetOutput
12 // Version 17.0, error matrix with SetInput, store fL not fLSquared
13 // Version 16.2, in parallel to bug-fix in TUnfoldSys
14 // Version 16.1, in parallel to bug-fix in TUnfold.C
15 // Version 16.0, some cleanup, more getter functions, query version number
16 // Version 15, simplified L-curve scan, new tau definition, new eror calc.
17 // Version 14, with changes in TUnfoldSys.cxx
18 // Version 13, new methods for derived classes
19 // Version 12, with support for preconditioned matrix inversion
20 // Version 11, regularisation methods have return values
21 // Version 10, with bug-fix in TUnfold.cxx
22 // Version 9, implements method for optimized inversion of sparse matrix
23 // Version 8, replace all TMatrixSparse matrix operations by private code
24 // Version 7, fix problem with TMatrixDSparse,TMatrixD multiplication
25 // Version 6, completely remove definition of class XY
26 // Version 5, move definition of class XY from TUnfold.C to this file
27 // Version 4, with bug-fix in TUnfold.C
28 // Version 3, with bug-fix in TUnfold.C
29 // Version 2, with changed ScanLcurve() arguments
30 // Version 1, added ScanLcurve() method
31 // Version 0, stable version of basic unfolding algorithm
32 
33 
34 #ifndef ROOT_TUnfold
35 #define ROOT_TUnfold
36 
37 //////////////////////////////////////////////////////////////////////////
38 // //
39 // //
40 // TUnfold provides functionality to correct data //
41 // for migration effects. //
42 // //
43 // Citation: S.Schmitt, JINST 7 (2012) T10003 [arXiv:1205.6201] //
44 // //
45 // //
46 // TUnfold solves the inverse problem //
47 // //
48 // T -1 2 T //
49 // chi**2 = (y-Ax) Vyy (y-Ax) + tau (L(x-x0)) L(x-x0) //
50 // //
51 // Monte Carlo input //
52 // y: vector of measured quantities (dimension ny) //
53 // Vyy: covariance matrix for y (dimension ny x ny) //
54 // A: migration matrix (dimension ny x nx) //
55 // x: unknown underlying distribution (dimension nx) //
56 // Regularisation //
57 // tau: parameter, defining the regularisation strength //
58 // L: matrix of regularisation conditions (dimension nl x nx) //
59 // x0: underlying distribution bias //
60 // //
61 // where chi**2 is minimized as a function of x //
62 // //
63 // The algorithm is based on "standard" matrix inversion, with the //
64 // known limitations in numerical accuracy and computing cost for //
65 // matrices with large dimensions. //
66 // //
67 // Thus the algorithm should not used for large dimensions of x and y //
68 // dim(x) should not exceed O(100) //
69 // dim(y) should not exceed O(500) //
70 // //
71 //////////////////////////////////////////////////////////////////////////
72 
73 /*
74  This file is part of TUnfold.
75 
76  TUnfold is free software: you can redistribute it and/or modify
77  it under the terms of the GNU General Public License as published by
78  the Free Software Foundation, either version 3 of the License, or
79  (at your option) any later version.
80 
81  TUnfold is distributed in the hope that it will be useful,
82  but WITHOUT ANY WARRANTY; without even the implied warranty of
83  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
84  GNU General Public License for more details.
85 
86  You should have received a copy of the GNU General Public License
87  along with TUnfold. If not, see <http://www.gnu.org/licenses/>.
88 */
89 
90 #include <TH1D.h>
91 #include <TH2D.h>
92 #include <TObject.h>
93 #include <TArrayI.h>
94 #include <TSpline.h>
95 #include <TMatrixDSparse.h>
96 #include <TMatrixD.h>
97 #include <TObjArray.h>
98 #include <TString.h>
99 
100 #define TUnfold_VERSION "V17.6"
101 #define TUnfold_CLASS_VERSION 17
102 
103 
104 class TUnfold : public TObject {
105  private:
106  void InitTUnfold(void); // initialize all data members
107  public:
108 
109  /// type of extra constraint
110  enum EConstraint {
111 
112  /// use no extra constraint
113  kEConstraintNone =0,
114 
115  /// enforce preservation of the area
116  kEConstraintArea =1
117  };
118 
119  /// choice of regularisation scheme
120  enum ERegMode {
121 
122  /// no regularisation, or defined later by RegularizeXXX() methods
123  kRegModeNone = 0,
124 
125  /// regularise the amplitude of the output distribution
126  kRegModeSize = 1,
127 
128  /// regularize the 1st derivative of the output distribution
129  kRegModeDerivative = 2,
130 
131  /// regularize the 2nd derivative of the output distribution
132  kRegModeCurvature = 3,
133 
134 
135  /// mixed regularisation pattern
136  kRegModeMixed = 4
137  };
138 
139  /// arrangement of axes for the response matrix (TH2 histogram)
140  enum EHistMap {
141 
142  /// truth level on x-axis of the response matrix
143  kHistMapOutputHoriz = 0,
144 
145  /// truth level on y-axis of the response matrix
146  kHistMapOutputVert = 1
147  };
148 
149  protected:
150  /// response matrix A
151  TMatrixDSparse * fA;
152  /// regularisation conditions L
153  TMatrixDSparse *fL;
154  /// input (measured) data y
155  TMatrixD *fY;
156  /// covariance matrix Vyy corresponding to y
157  TMatrixDSparse *fVyy;
158  /// scale factor for the bias
159  Double_t fBiasScale;
160  /// bias vector x0
161  TMatrixD *fX0;
162  /// regularisation parameter tau squared
163  Double_t fTauSquared;
164  /// mapping of matrix indices to histogram bins
165  TArrayI fXToHist;
166  /// mapping of histogram bins to matrix indices
167  TArrayI fHistToX;
168  /// truth vector calculated from the non-normalized response matrix
169  TArrayD fSumOverY;
170  /// type of constraint to use for the unfolding
171  EConstraint fConstraint;
172  /// type of regularisation
173  ERegMode fRegMode;
174  private:
175  /// number of input bins which are dropped because they have error=0
176  Int_t fIgnoredBins;
177  /// machine accuracy used to determine matrix rank after eigenvalue analysis
178  Double_t fEpsMatrix;
179  /// unfolding result x
180  TMatrixD *fX;
181  /// covariance matrix Vxx
182  TMatrixDSparse *fVxx;
183  /// inverse of covariance matrix Vxx<sup>-1</sub>
184  TMatrixDSparse *fVxxInv;
185  /// inverse of the input covariance matrix Vyy<sup>-1</sub>
186  TMatrixDSparse *fVyyInv;
187  /// result x folded back A*x
188  TMatrixDSparse *fAx;
189  /// chi**2 contribution from (y-Ax)Vyy<sup>-1</sub>(y-Ax)
190  Double_t fChi2A;
191  /// chi**2 contribution from (x-s*x0)<sup>T</sub>L<sup>T</sub>L(x-s*x0)
192  Double_t fLXsquared;
193  /// maximum global correlation coefficient
194  Double_t fRhoMax;
195  /// average global correlation coefficient
196  Double_t fRhoAvg;
197  /// number of degrees of freedom
198  Int_t fNdf;
199  /// matrix contribution to the of derivative dx_k/dA_ij
200  TMatrixDSparse *fDXDAM[2];
201  /// vector contribution to the of derivative dx_k/dA_ij
202  TMatrixDSparse *fDXDAZ[2];
203  /// derivative of the result wrt tau squared
204  TMatrixDSparse *fDXDtauSquared;
205  /// derivative of the result wrt dx/dy
206  TMatrixDSparse *fDXDY;
207  /// matrix E^(-1)
208  TMatrixDSparse *fEinv;
209  /// matrix E
210  TMatrixDSparse *fE;
211  protected:
212  // Int_t IsNotSymmetric(TMatrixDSparse const &m) const;
213  virtual Double_t DoUnfold(void); // the unfolding algorithm
214  virtual void ClearResults(void); // clear all results
215  void ClearHistogram(TH1 *h,Double_t x=0.) const;
216  virtual TString GetOutputBinName(Int_t iBinX) const; // name a bin
217  TMatrixDSparse *MultiplyMSparseM(const TMatrixDSparse *a,const TMatrixD *b) const; // multiply sparse and non-sparse matrix
218  TMatrixDSparse *MultiplyMSparseMSparse(const TMatrixDSparse *a,const TMatrixDSparse *b) const; // multiply sparse and sparse matrix
219  TMatrixDSparse *MultiplyMSparseTranspMSparse(const TMatrixDSparse *a,const TMatrixDSparse *b) const; // multiply transposed sparse and sparse matrix
220  TMatrixDSparse *MultiplyMSparseMSparseTranspVector
221  (const TMatrixDSparse *m1,const TMatrixDSparse *m2,
222  const TMatrixTBase<Double_t> *v) const; // calculate M_ij = sum_k [m1_ik*m2_jk*v[k] ]. the pointer v may be zero (means no scaling).
223  TMatrixDSparse *InvertMSparseSymmPos(const TMatrixDSparse *A,Int_t *rank) const; // invert symmetric (semi-)positive sparse matrix
224  void AddMSparse(TMatrixDSparse *dest,Double_t f,const TMatrixDSparse *src) const; // replacement for dest += f*src
225  TMatrixDSparse *CreateSparseMatrix(Int_t nrow,Int_t ncol,Int_t nele,Int_t *row,Int_t *col,Double_t *data) const; // create a TMatrixDSparse from an array
226  /// returns internal number of output (truth) matrix rows
227  inline Int_t GetNx(void) const {
228  return fA->GetNcols();
229  }
230  /// converts truth histogram bin number to matrix row
231  inline Int_t GetRowFromBin(int ix) const { return fHistToX[ix]; }
232  /// converts matrix row to truth histogram bin number
233  inline Int_t GetBinFromRow(int ix) const { return fXToHist[ix]; }
234  /// returns the number of measurement bins
235  inline Int_t GetNy(void) const {
236  return fA->GetNrows();
237  }
238  /// vector of the unfolding result
239  inline const TMatrixD *GetX(void) const { return fX; }
240  /// covariance matrix of the result
241  inline const TMatrixDSparse *GetVxx(void) const { return fVxx; }
242  /// inverse of covariance matrix of the result
243  inline const TMatrixDSparse *GetVxxInv(void) const { return fVxxInv; }
244  /// vector of folded-back result
245  inline const TMatrixDSparse *GetAx(void) const { return fAx; }
246  /// matrix of derivatives dx/dy
247  inline const TMatrixDSparse *GetDXDY(void) const { return fDXDY; }
248  /// matrix contributions of the derivative dx/dA
249  inline const TMatrixDSparse *GetDXDAM(int i) const { return fDXDAM[i]; }
250  /// vector contributions of the derivative dx/dA
251  inline const TMatrixDSparse *GetDXDAZ(int i) const { return fDXDAZ[i]; }
252  /// matrix E<sup>-1</sup>, using internal bin counting
253  inline const TMatrixDSparse *GetEinv(void) const { return fEinv; }
254  /// matrix E, using internal bin counting
255  inline const TMatrixDSparse *GetE(void) const { return fE; }
256  /// inverse of covariance matrix of the data y
257  inline const TMatrixDSparse *GetVyyInv(void) const { return fVyyInv; }
258 
259  void ErrorMatrixToHist(TH2 *ematrix,const TMatrixDSparse *emat,const Int_t *binMap,Bool_t doClear) const; // return an error matrix as histogram
260  Double_t GetRhoIFromMatrix(TH1 *rhoi,const TMatrixDSparse *eOrig,const Int_t *binMap,TH2 *invEmat) const; // return global correlation coefficients
261  /// vector of derivative dx/dtauSquared, using internal bin counting
262  inline const TMatrixDSparse *GetDXDtauSquared(void) const { return fDXDtauSquared; }
263  /// delete matrix and invalidate pointer
264  static void DeleteMatrix(TMatrixD **m);
265  /// delete sparse matrix and invalidate pointer
266  static void DeleteMatrix(TMatrixDSparse **m);
267 
268  Bool_t AddRegularisationCondition(Int_t i0,Double_t f0,Int_t i1=-1,Double_t f1=0.,Int_t i2=-1,Double_t f2=0.); // add regularisation condition for a triplet of output bins
269  Bool_t AddRegularisationCondition(Int_t nEle,const Int_t *indices,const Double_t *rowData); // add a regularisation condition
270 public:
271  static const char*GetTUnfoldVersion(void);
272  // Set up response matrix and regularisation scheme
273  TUnfold(const TH2 *hist_A, EHistMap histmap,
274  ERegMode regmode = kRegModeSize,
275  EConstraint constraint=kEConstraintArea);
276  // for root streamer and derived classes
277  TUnfold(void);
278  virtual ~TUnfold(void);
279  // define input distribution
280  virtual Int_t SetInput(const TH1 *hist_y, Double_t scaleBias=0.0,Double_t oneOverZeroError=0.0,const TH2 *hist_vyy=0,const TH2 *hist_vyy_inv=0);
281  // Unfold with given choice of tau and input
282  virtual Double_t DoUnfold(Double_t tau);
283  Double_t DoUnfold(Double_t tau,const TH1 *hist_y, Double_t scaleBias=0.0);
284  // scan the L curve using successive calls to DoUnfold(Double_t) at various tau
285  virtual Int_t ScanLcurve(Int_t nPoint,Double_t tauMin,
286  Double_t tauMax,TGraph **lCurve,
287  TSpline **logTauX=0,TSpline **logTauY=0,
288  TSpline **logTauCurvature=0);
289 
290  // access unfolding results
291  Double_t GetTau(void) const;
292  void GetOutput(TH1 *output,const Int_t *binMap=0) const;
293  void GetEmatrix(TH2 *ematrix,const Int_t *binMap=0) const;
294  void GetRhoIJ(TH2 *rhoij,const Int_t *binMap=0) const;
295  Double_t GetRhoI(TH1 *rhoi,const Int_t *binMap=0,TH2 *invEmat=0) const;
296  void GetFoldedOutput(TH1 *folded,const Int_t *binMap=0) const;
297 
298  // access input parameters
299  void GetProbabilityMatrix(TH2 *A,EHistMap histmap) const;
300  void GetNormalisationVector(TH1 *s,const Int_t *binMap=0) const; // get the vector of normalisation factors, equivalent to the initial bias vector
301  void GetInput(TH1 *inputData,const Int_t *binMap=0) const; // get input data
302  void GetInputInverseEmatrix(TH2 *ematrix); // get input data inverse of error matrix
303  void GetBias(TH1 *bias,const Int_t *binMap=0) const; // get bias (includind biasScale)
304  Int_t GetNr(void) const; // number of regularisation conditions
305  void GetL(TH2 *l) const; // get matrix of regularisation conditions
306  void GetLsquared(TH2 *lsquared) const;
307 
308  // access various properties of the result
309  /// get maximum global correlation determined in recent unfolding
310  inline Double_t GetRhoMax(void) const { return fRhoMax; }
311  /// get average global correlation determined in recent unfolding
312  inline Double_t GetRhoAvg(void) const { return fRhoAvg; }
313  /// get &chi;<sup>2</sup><sub>A</sub> contribution determined in recent unfolding
314  inline Double_t GetChi2A(void) const { return fChi2A; }
315 
316  Double_t GetChi2L(void) const; // get &chi;<sup>2</sup><sub>L</sub> contribution determined in recent unfolding
317  virtual Double_t GetLcurveX(void) const; // get value on x axis of L curve
318  virtual Double_t GetLcurveY(void) const; // get value on y axis of L curve
319  /// get number of degrees of freedom determined in recent unfolding
320  ///
321  /// This returns the number of valid measurements minus the number
322  /// of unfolded truth bins. If the area constraint is active, one
323  /// further degree of freedom is subtracted
324  inline Int_t GetNdf(void) const { return fNdf; }
325  Int_t GetNpar(void) const; // get number of parameters
326 
327  // advanced features
328  void SetBias(const TH1 *bias); // set alternative bias
329  void SetConstraint(EConstraint constraint); // set type of constraint for the next unfolding
330  Int_t RegularizeSize(int bin, Double_t scale = 1.0); // regularise the size of one output bin
331  Int_t RegularizeDerivative(int left_bin, int right_bin, Double_t scale = 1.0); // regularize difference of two output bins (1st derivative)
332  Int_t RegularizeCurvature(int left_bin, int center_bin, int right_bin, Double_t scale_left = 1.0, Double_t scale_right = 1.0); // regularize curvature of three output bins (2nd derivative)
333  Int_t RegularizeBins(int start, int step, int nbin, ERegMode regmode); // regularize a 1-dimensional curve
334  Int_t RegularizeBins2D(int start_bin, int step1, int nbin1, int step2, int nbin2, ERegMode regmode); // regularize a 2-dimensional grid
335  /// get numerical accuracy for Eigenvalue analysis when inverting
336  /// matrices with rank problems
337  inline Double_t GetEpsMatrix(void) const { return fEpsMatrix; }
338  /// set numerical accuracy for Eigenvalue analysis when inverting
339  /// matrices with rank problems
340  void SetEpsMatrix(Double_t eps); // set accuracy for eigenvalue analysis
341 
342  ClassDef(TUnfold, TUnfold_CLASS_VERSION) //Unfolding with support for L-curve analysis
343 };
344 
345 #endif