]>
Commit | Line | Data |
---|---|---|
c0b10ad4 | 1 | /************************************************************************** |
2 | * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * | |
3 | * * | |
4 | * Author: The ALICE Off-line Project. * | |
5 | * Contributors are mentioned in the code where appropriate. * | |
6 | * * | |
7 | * Permission to use, copy, modify and distribute this software and its * | |
8 | * documentation strictly for non-commercial purposes is hereby granted * | |
9 | * without fee, provided that the above copyright notice appears in all * | |
10 | * copies and that both the copyright notice and this permission notice * | |
11 | * appear in the supporting documentation. The authors make no claims * | |
12 | * about the suitability of this software for any purpose. It is * | |
13 | * provided "as is" without express or implied warranty. * | |
14 | **************************************************************************/ | |
15 | ||
7bc6a013 | 16 | //---------------------------------------------------------------------// |
17 | // // | |
18 | // AliCFUnfolding Class // | |
19 | // Class to handle general unfolding procedure // | |
20 | // For the moment only bayesian unfolding is supported // | |
21 | // The next steps are to add chi2 minimisation and weighting methods // | |
22 | // // | |
23 | // // | |
24 | // // | |
25 | // Use : // | |
26 | // ------- // | |
27 | // The Bayesian unfolding consists of several iterations. // | |
28 | // At each iteration, an inverse response matrix is calculated, given // | |
29 | // the measured spectrum, the a priori (guessed) spectrum, // | |
30 | // the efficiency spectrum and the response matrix. // | |
c7f196bd | 31 | // // |
32 | // Then at each iteration, the unfolded spectrum is calculated using // | |
7bc6a013 | 33 | // the inverse response : the goal is to get an unfolded spectrum // |
34 | // similar (according to some criterion) to the a priori one. // | |
35 | // If the difference is too big, another iteration is performed : // | |
36 | // the a priori spectrum is updated to the unfolded one from the // | |
37 | // previous iteration, and so on so forth, until the maximum number // | |
38 | // of iterations or the similarity criterion is reached. // | |
39 | // // | |
769f5114 | 40 | // Chi2 calculation became absolute with the correlated error // |
41 | // calculation. // | |
42 | // Errors on the unfolded distribution are not known until the end // | |
43 | // Use the convergence criterion instead // | |
7bc6a013 | 44 | // // |
45 | // Currently the user has to define the max. number of iterations // | |
46 | // (::SetMaxNumberOfIterations) // | |
769f5114 | 47 | // and // |
48 | // - the chi2 below which the procedure will stop // | |
49 | // (::SetMaxChi2 or ::SetMaxChi2PerDOF) (OBSOLETE) // | |
50 | // - the convergence criterion below which the procedure will stop // | |
51 | // SetMaxConvergencePerDOF(Double_t val); // | |
52 | // // | |
53 | // Correlated error calculation can be activated by using: // | |
54 | // SetUseCorrelatedErrors(Bool_t b) in combination with convergence // | |
55 | // criterion // | |
56 | // Documentation about correlated error calculation method can be // | |
57 | // found in AliCFUnfolding::CalculateCorrelatedErrors() // | |
58 | // Author: marta.verweij@cern.ch // | |
7bc6a013 | 59 | // // |
60 | // An optional possibility is to smooth the unfolded spectrum at the // | |
61 | // end of each iteration, either using a fit function // | |
62 | // (only if #dimensions <=3) // | |
63 | // or a simple averaging using the neighbouring bins values. // | |
64 | // This is possible calling the function ::UseSmoothing // | |
65 | // If no argument is passed to this function, then the second option // | |
66 | // is used. // | |
67 | // // | |
c7f196bd | 68 | // IMPORTANT: // |
69 | //----------- // | |
70 | // With this approach, the efficiency map must be calculated // | |
71 | // with *simulated* values only, otherwise the method won't work. // | |
72 | // // | |
73 | // ex: efficiency(bin_pt) = number_rec(bin_pt) / number_sim(bin_pt) // | |
74 | // // | |
75 | // the pt bin "bin_pt" must always be the same in both the efficiency // | |
76 | // numerator and denominator. // | |
77 | // This is why the efficiency map has to be created by a method // | |
78 | // from which both reconstructed and simulated values are accessible // | |
79 | // simultaneously. // | |
80 | // // | |
81 | // // | |
7bc6a013 | 82 | //---------------------------------------------------------------------// |
83 | // Author : renaud.vernet@cern.ch // | |
84 | //---------------------------------------------------------------------// | |
c0b10ad4 | 85 | |
86 | ||
87 | #include "AliCFUnfolding.h" | |
88 | #include "TMath.h" | |
89 | #include "TAxis.h" | |
85b6bda9 | 90 | #include "TF1.h" |
91 | #include "TH1D.h" | |
92 | #include "TH2D.h" | |
93 | #include "TH3D.h" | |
769f5114 | 94 | #include "TRandom3.h" |
c0b10ad4 | 95 | |
96 | ClassImp(AliCFUnfolding) | |
97 | ||
98 | //______________________________________________________________ | |
99 | ||
100 | AliCFUnfolding::AliCFUnfolding() : | |
101 | TNamed(), | |
5a575436 | 102 | fResponseOrig(0x0), |
103 | fPriorOrig(0x0), | |
104 | fEfficiencyOrig(0x0), | |
769f5114 | 105 | fMeasuredOrig(0x0), |
a9500e70 | 106 | fMaxNumIterations(0), |
c0b10ad4 | 107 | fNVariables(0), |
c0b10ad4 | 108 | fUseSmoothing(kFALSE), |
85b6bda9 | 109 | fSmoothFunction(0x0), |
a9500e70 | 110 | fSmoothOption("iremn"), |
769f5114 | 111 | fMaxConvergence(0), |
a9500e70 | 112 | fNRandomIterations(0), |
5a575436 | 113 | fResponse(0x0), |
114 | fPrior(0x0), | |
115 | fEfficiency(0x0), | |
116 | fMeasured(0x0), | |
c0b10ad4 | 117 | fInverseResponse(0x0), |
118 | fMeasuredEstimate(0x0), | |
119 | fConditional(0x0), | |
c0b10ad4 | 120 | fUnfolded(0x0), |
a9500e70 | 121 | fUnfoldedFinal(0x0), |
c0b10ad4 | 122 | fCoordinates2N(0x0), |
123 | fCoordinatesN_M(0x0), | |
769f5114 | 124 | fCoordinatesN_T(0x0), |
5a575436 | 125 | fRandomResponse(0x0), |
126 | fRandomEfficiency(0x0), | |
127 | fRandomMeasured(0x0), | |
769f5114 | 128 | fRandom3(0x0), |
769f5114 | 129 | fDeltaUnfoldedP(0x0), |
a9500e70 | 130 | fDeltaUnfoldedN(0x0), |
769f5114 | 131 | fNCalcCorrErrors(0), |
132 | fRandomSeed(0) | |
c0b10ad4 | 133 | { |
134 | // | |
135 | // default constructor | |
136 | // | |
137 | } | |
138 | ||
139 | //______________________________________________________________ | |
140 | ||
141 | AliCFUnfolding::AliCFUnfolding(const Char_t* name, const Char_t* title, const Int_t nVar, | |
a9500e70 | 142 | const THnSparse* response, const THnSparse* efficiency, const THnSparse* measured, const THnSparse* prior , |
143 | Double_t maxConvergencePerDOF, UInt_t randomSeed, Int_t maxNumIterations | |
144 | ) : | |
c0b10ad4 | 145 | TNamed(name,title), |
5a575436 | 146 | fResponseOrig((THnSparse*)response->Clone()), |
147 | fPriorOrig(0x0), | |
148 | fEfficiencyOrig((THnSparse*)efficiency->Clone()), | |
769f5114 | 149 | fMeasuredOrig((THnSparse*)measured->Clone()), |
a9500e70 | 150 | fMaxNumIterations(maxNumIterations), |
c0b10ad4 | 151 | fNVariables(nVar), |
c0b10ad4 | 152 | fUseSmoothing(kFALSE), |
85b6bda9 | 153 | fSmoothFunction(0x0), |
a9500e70 | 154 | fSmoothOption("iremn"), |
769f5114 | 155 | fMaxConvergence(0), |
a9500e70 | 156 | fNRandomIterations(maxNumIterations), |
5a575436 | 157 | fResponse((THnSparse*)response->Clone()), |
158 | fPrior(0x0), | |
159 | fEfficiency((THnSparse*)efficiency->Clone()), | |
160 | fMeasured((THnSparse*)measured->Clone()), | |
c0b10ad4 | 161 | fInverseResponse(0x0), |
162 | fMeasuredEstimate(0x0), | |
163 | fConditional(0x0), | |
c0b10ad4 | 164 | fUnfolded(0x0), |
a9500e70 | 165 | fUnfoldedFinal(0x0), |
c0b10ad4 | 166 | fCoordinates2N(0x0), |
167 | fCoordinatesN_M(0x0), | |
769f5114 | 168 | fCoordinatesN_T(0x0), |
5a575436 | 169 | fRandomResponse((THnSparse*)response->Clone()), |
170 | fRandomEfficiency((THnSparse*)efficiency->Clone()), | |
171 | fRandomMeasured((THnSparse*)measured->Clone()), | |
769f5114 | 172 | fRandom3(0x0), |
769f5114 | 173 | fDeltaUnfoldedP(0x0), |
a9500e70 | 174 | fDeltaUnfoldedN(0x0), |
769f5114 | 175 | fNCalcCorrErrors(0), |
a9500e70 | 176 | fRandomSeed(randomSeed) |
c0b10ad4 | 177 | { |
178 | // | |
179 | // named constructor | |
180 | // | |
181 | ||
182 | AliInfo(Form("\n\n--------------------------\nCreating an unfolder :\n--------------------------\nresponse matrix has %d dimension(s)",fResponse->GetNdimensions())); | |
a9500e70 | 183 | |
c0b10ad4 | 184 | if (!prior) CreateFlatPrior(); // if no prior distribution declared, simply use a flat distribution |
185 | else { | |
186 | fPrior = (THnSparse*) prior->Clone(); | |
5a575436 | 187 | fPriorOrig = (THnSparse*)fPrior->Clone(); |
85b6bda9 | 188 | if (fPrior->GetNdimensions() != fNVariables) |
189 | AliFatal(Form("The prior matrix should have %d dimensions, and it has actually %d",fNVariables,fPrior->GetNdimensions())); | |
c0b10ad4 | 190 | } |
85b6bda9 | 191 | |
192 | if (fEfficiency->GetNdimensions() != fNVariables) | |
193 | AliFatal(Form("The efficiency matrix should have %d dimensions, and it has actually %d",fNVariables,fEfficiency->GetNdimensions())); | |
194 | if (fMeasured->GetNdimensions() != fNVariables) | |
195 | AliFatal(Form("The measured matrix should have %d dimensions, and it has actually %d",fNVariables,fMeasured->GetNdimensions())); | |
196 | if (fResponse->GetNdimensions() != 2*fNVariables) | |
197 | AliFatal(Form("The response matrix should have %d dimensions, and it has actually %d",2*fNVariables,fResponse->GetNdimensions())); | |
c0b10ad4 | 198 | |
85b6bda9 | 199 | |
c0b10ad4 | 200 | for (Int_t iVar=0; iVar<fNVariables; iVar++) { |
201 | AliInfo(Form("prior matrix has %d bins in dimension %d",fPrior ->GetAxis(iVar)->GetNbins(),iVar)); | |
202 | AliInfo(Form("efficiency matrix has %d bins in dimension %d",fEfficiency->GetAxis(iVar)->GetNbins(),iVar)); | |
203 | AliInfo(Form("measured matrix has %d bins in dimension %d",fMeasured ->GetAxis(iVar)->GetNbins(),iVar)); | |
204 | } | |
769f5114 | 205 | |
5a575436 | 206 | fRandomResponse ->SetTitle("Randomized response matrix"); |
207 | fRandomEfficiency->SetTitle("Randomized efficiency"); | |
208 | fRandomMeasured ->SetTitle("Randomized measured"); | |
a9500e70 | 209 | SetMaxConvergencePerDOF(maxConvergencePerDOF) ; |
c0b10ad4 | 210 | Init(); |
211 | } | |
212 | ||
213 | ||
214 | //______________________________________________________________ | |
215 | ||
216 | AliCFUnfolding::AliCFUnfolding(const AliCFUnfolding& c) : | |
217 | TNamed(c), | |
5a575436 | 218 | fResponseOrig((THnSparse*)c.fResponseOrig->Clone()), |
219 | fPriorOrig((THnSparse*)c.fPriorOrig->Clone()), | |
220 | fEfficiencyOrig((THnSparse*)c.fEfficiencyOrig->Clone()), | |
769f5114 | 221 | fMeasuredOrig((THnSparse*)c.fMeasuredOrig->Clone()), |
c0b10ad4 | 222 | fMaxNumIterations(c.fMaxNumIterations), |
223 | fNVariables(c.fNVariables), | |
c0b10ad4 | 224 | fUseSmoothing(c.fUseSmoothing), |
85b6bda9 | 225 | fSmoothFunction((TF1*)c.fSmoothFunction->Clone()), |
7c5606f9 | 226 | fSmoothOption(c.fSmoothOption), |
769f5114 | 227 | fMaxConvergence(c.fMaxConvergence), |
769f5114 | 228 | fNRandomIterations(c.fNRandomIterations), |
5a575436 | 229 | fResponse((THnSparse*)c.fResponse->Clone()), |
230 | fPrior((THnSparse*)c.fPrior->Clone()), | |
231 | fEfficiency((THnSparse*)c.fEfficiency->Clone()), | |
232 | fMeasured((THnSparse*)c.fMeasured->Clone()), | |
c0b10ad4 | 233 | fInverseResponse((THnSparse*)c.fInverseResponse->Clone()), |
234 | fMeasuredEstimate((THnSparse*)fMeasuredEstimate->Clone()), | |
235 | fConditional((THnSparse*)c.fConditional->Clone()), | |
c0b10ad4 | 236 | fUnfolded((THnSparse*)c.fUnfolded->Clone()), |
a9500e70 | 237 | fUnfoldedFinal((THnSparse*)c.fUnfoldedFinal->Clone()), |
c0b10ad4 | 238 | fCoordinates2N(new Int_t(*c.fCoordinates2N)), |
239 | fCoordinatesN_M(new Int_t(*c.fCoordinatesN_M)), | |
769f5114 | 240 | fCoordinatesN_T(new Int_t(*c.fCoordinatesN_T)), |
5a575436 | 241 | fRandomResponse((THnSparse*)c.fRandomResponse->Clone()), |
242 | fRandomEfficiency((THnSparse*)c.fRandomEfficiency->Clone()), | |
243 | fRandomMeasured((THnSparse*)c.fRandomMeasured->Clone()), | |
769f5114 | 244 | fRandom3((TRandom3*)c.fRandom3->Clone()), |
a9500e70 | 245 | fDeltaUnfoldedP((THnSparse*)c.fDeltaUnfoldedP), |
246 | fDeltaUnfoldedN((THnSparse*)c.fDeltaUnfoldedN), | |
769f5114 | 247 | fNCalcCorrErrors(c.fNCalcCorrErrors), |
248 | fRandomSeed(c.fRandomSeed) | |
c0b10ad4 | 249 | { |
250 | // | |
251 | // copy constructor | |
252 | // | |
253 | } | |
254 | ||
255 | //______________________________________________________________ | |
256 | ||
257 | AliCFUnfolding& AliCFUnfolding::operator=(const AliCFUnfolding& c) { | |
258 | // | |
259 | // assignment operator | |
260 | // | |
261 | ||
262 | if (this!=&c) { | |
263 | TNamed::operator=(c); | |
5a575436 | 264 | fResponseOrig = (THnSparse*)c.fResponseOrig->Clone() ; |
265 | fPriorOrig = (THnSparse*)c.fPriorOrig->Clone() ; | |
266 | fEfficiencyOrig = (THnSparse*)c.fEfficiencyOrig->Clone() ; | |
267 | fMeasuredOrig = (THnSparse*)c.fMeasuredOrig->Clone() ; | |
c0b10ad4 | 268 | fMaxNumIterations = c.fMaxNumIterations ; |
269 | fNVariables = c.fNVariables ; | |
c0b10ad4 | 270 | fUseSmoothing = c.fUseSmoothing ; |
5a575436 | 271 | fSmoothFunction = (TF1*)c.fSmoothFunction->Clone() ; |
85b6bda9 | 272 | fSmoothOption = c.fSmoothOption ; |
5a575436 | 273 | fMaxConvergence = c.fMaxConvergence ; |
274 | fNRandomIterations = c.fNRandomIterations ; | |
275 | fResponse = (THnSparse*)c.fResponse->Clone() ; | |
276 | fPrior = (THnSparse*)c.fPrior->Clone() ; | |
277 | fEfficiency = (THnSparse*)c.fEfficiency->Clone() ; | |
278 | fMeasured = (THnSparse*)c.fMeasured->Clone() ; | |
c0b10ad4 | 279 | fInverseResponse = (THnSparse*)c.fInverseResponse->Clone() ; |
280 | fMeasuredEstimate = (THnSparse*)fMeasuredEstimate->Clone() ; | |
5a575436 | 281 | fConditional = (THnSparse*)fConditional->Clone() ; |
c0b10ad4 | 282 | fUnfolded = (THnSparse*)c.fUnfolded->Clone() ; |
a9500e70 | 283 | fUnfoldedFinal = (THnSparse*)c.fUnfoldedFinal->Clone() ; |
c0b10ad4 | 284 | fCoordinates2N = new Int_t(*c.fCoordinates2N) ; |
285 | fCoordinatesN_M = new Int_t(*c.fCoordinatesN_M) ; | |
286 | fCoordinatesN_T = new Int_t(*c.fCoordinatesN_T) ; | |
5a575436 | 287 | fRandomResponse = (THnSparse*)c.fRandomResponse->Clone() ; |
288 | fRandomEfficiency = (THnSparse*)c.fRandomEfficiency->Clone() ; | |
289 | fRandomMeasured = (THnSparse*)c.fRandomMeasured->Clone() ; | |
290 | fRandom3 = (TRandom3*)c.fRandom3->Clone() ; | |
291 | fDeltaUnfoldedP = (THnSparse*)c.fDeltaUnfoldedP->Clone() ; | |
292 | fDeltaUnfoldedN = (THnSparse*)c.fDeltaUnfoldedN->Clone() ; | |
a9500e70 | 293 | fNCalcCorrErrors = c.fNCalcCorrErrors ; |
769f5114 | 294 | fRandomSeed = c.fRandomSeed ; |
c0b10ad4 | 295 | } |
296 | return *this; | |
297 | } | |
298 | ||
299 | //______________________________________________________________ | |
300 | ||
301 | AliCFUnfolding::~AliCFUnfolding() { | |
302 | // | |
303 | // destructor | |
304 | // | |
305 | if (fResponse) delete fResponse; | |
306 | if (fPrior) delete fPrior; | |
c0b10ad4 | 307 | if (fEfficiency) delete fEfficiency; |
5a575436 | 308 | if (fEfficiencyOrig) delete fEfficiencyOrig; |
c0b10ad4 | 309 | if (fMeasured) delete fMeasured; |
769f5114 | 310 | if (fMeasuredOrig) delete fMeasuredOrig; |
85b6bda9 | 311 | if (fSmoothFunction) delete fSmoothFunction; |
5a575436 | 312 | if (fPriorOrig) delete fPriorOrig; |
c0b10ad4 | 313 | if (fInverseResponse) delete fInverseResponse; |
314 | if (fMeasuredEstimate) delete fMeasuredEstimate; | |
315 | if (fConditional) delete fConditional; | |
a9500e70 | 316 | if (fUnfolded) delete fUnfolded; |
317 | if (fUnfoldedFinal) delete fUnfoldedFinal; | |
c0b10ad4 | 318 | if (fCoordinates2N) delete [] fCoordinates2N; |
319 | if (fCoordinatesN_M) delete [] fCoordinatesN_M; | |
320 | if (fCoordinatesN_T) delete [] fCoordinatesN_T; | |
5a575436 | 321 | if (fRandomResponse) delete fRandomResponse; |
322 | if (fRandomEfficiency) delete fRandomEfficiency; | |
323 | if (fRandomMeasured) delete fRandomMeasured; | |
769f5114 | 324 | if (fRandom3) delete fRandom3; |
769f5114 | 325 | if (fDeltaUnfoldedP) delete fDeltaUnfoldedP; |
a9500e70 | 326 | if (fDeltaUnfoldedN) delete fDeltaUnfoldedN; |
c0b10ad4 | 327 | } |
328 | ||
329 | //______________________________________________________________ | |
330 | ||
331 | void AliCFUnfolding::Init() { | |
332 | // | |
333 | // initialisation function : creates internal settings | |
334 | // | |
335 | ||
769f5114 | 336 | fRandom3 = new TRandom3(fRandomSeed); |
337 | ||
c0b10ad4 | 338 | fCoordinates2N = new Int_t[2*fNVariables]; |
339 | fCoordinatesN_M = new Int_t[fNVariables]; | |
340 | fCoordinatesN_T = new Int_t[fNVariables]; | |
341 | ||
342 | // create the matrix of conditional probabilities P(M|T) | |
a9500e70 | 343 | CreateConditional(); //done only once at initialization |
c0b10ad4 | 344 | |
345 | // create the frame of the inverse response matrix | |
346 | fInverseResponse = (THnSparse*) fResponse->Clone(); | |
347 | // create the frame of the unfolded spectrum | |
348 | fUnfolded = (THnSparse*) fPrior->Clone(); | |
a9500e70 | 349 | fUnfolded->SetTitle("Unfolded"); |
c0b10ad4 | 350 | // create the frame of the measurement estimate spectrum |
351 | fMeasuredEstimate = (THnSparse*) fMeasured->Clone(); | |
a9500e70 | 352 | |
5a575436 | 353 | // create the frame of the delta profiles |
a9500e70 | 354 | fDeltaUnfoldedP = (THnSparse*)fPrior->Clone(); |
355 | fDeltaUnfoldedP->SetTitle("#Delta unfolded"); | |
356 | fDeltaUnfoldedP->Reset(); | |
357 | fDeltaUnfoldedN = (THnSparse*)fPrior->Clone(); | |
5a575436 | 358 | fDeltaUnfoldedN->SetTitle(""); |
a9500e70 | 359 | fDeltaUnfoldedN->Reset(); |
c0b10ad4 | 360 | } |
361 | ||
a9500e70 | 362 | |
c0b10ad4 | 363 | //______________________________________________________________ |
364 | ||
365 | void AliCFUnfolding::CreateEstMeasured() { | |
366 | // | |
367 | // This function creates a estimate (M) of the reconstructed spectrum | |
7bc6a013 | 368 | // given the a priori distribution (T), the efficiency (E) and the conditional matrix (COND) |
c0b10ad4 | 369 | // |
370 | // --> P(M) = SUM { P(M|T) * P(T) } | |
7bc6a013 | 371 | // --> M(i) = SUM_k { COND(i,k) * T(k) * E (k)} |
c0b10ad4 | 372 | // |
373 | // This is needed to calculate the inverse response matrix | |
374 | // | |
375 | ||
376 | ||
377 | // clean the measured estimate spectrum | |
85f9f9e1 | 378 | fMeasuredEstimate->Reset(); |
379 | ||
85b6bda9 | 380 | THnSparse* priorTimesEff = (THnSparse*) fPrior->Clone(); |
381 | priorTimesEff->Multiply(fEfficiency); | |
382 | ||
c0b10ad4 | 383 | // fill it |
7bc6a013 | 384 | for (Long_t iBin=0; iBin<fConditional->GetNbins(); iBin++) { |
c0b10ad4 | 385 | Double_t conditionalValue = fConditional->GetBinContent(iBin,fCoordinates2N); |
386 | GetCoordinates(); | |
85b6bda9 | 387 | Double_t priorTimesEffValue = priorTimesEff->GetBinContent(fCoordinatesN_T); |
85b6bda9 | 388 | Double_t fill = conditionalValue * priorTimesEffValue ; |
389 | ||
390 | if (fill>0.) { | |
12e419d5 | 391 | fMeasuredEstimate->AddBinContent(fCoordinatesN_M,fill); |
769f5114 | 392 | fMeasuredEstimate->SetBinError(fCoordinatesN_M,0.); |
85b6bda9 | 393 | } |
c0b10ad4 | 394 | } |
85b6bda9 | 395 | delete priorTimesEff ; |
c0b10ad4 | 396 | } |
397 | ||
398 | //______________________________________________________________ | |
399 | ||
400 | void AliCFUnfolding::CreateInvResponse() { | |
401 | // | |
402 | // Creates the inverse response matrix (INV) with Bayesian method | |
403 | // : uses the conditional matrix (COND), the prior probabilities (T) and the efficiency map (E) | |
404 | // | |
405 | // --> P(T|M) = P(M|T) * P(T) * eff(T) / SUM { P(M|T) * P(T) } | |
406 | // --> INV(i,j) = COND(i,j) * T(j) * E(j) / SUM_k { COND(i,k) * T(k) } | |
407 | // | |
408 | ||
85b6bda9 | 409 | THnSparse* priorTimesEff = (THnSparse*) fPrior->Clone(); |
410 | priorTimesEff->Multiply(fEfficiency); | |
411 | ||
7bc6a013 | 412 | for (Long_t iBin=0; iBin<fConditional->GetNbins(); iBin++) { |
c0b10ad4 | 413 | Double_t conditionalValue = fConditional->GetBinContent(iBin,fCoordinates2N); |
414 | GetCoordinates(); | |
85b6bda9 | 415 | Double_t estMeasuredValue = fMeasuredEstimate->GetBinContent(fCoordinatesN_M); |
85b6bda9 | 416 | Double_t priorTimesEffValue = priorTimesEff ->GetBinContent(fCoordinatesN_T); |
85b6bda9 | 417 | Double_t fill = (estMeasuredValue>0. ? conditionalValue * priorTimesEffValue / estMeasuredValue : 0. ) ; |
85b6bda9 | 418 | if (fill>0. || fInverseResponse->GetBinContent(fCoordinates2N)>0.) { |
419 | fInverseResponse->SetBinContent(fCoordinates2N,fill); | |
769f5114 | 420 | fInverseResponse->SetBinError (fCoordinates2N,0.); |
85b6bda9 | 421 | } |
422 | } | |
423 | delete priorTimesEff ; | |
c0b10ad4 | 424 | } |
425 | ||
426 | //______________________________________________________________ | |
427 | ||
428 | void AliCFUnfolding::Unfold() { | |
429 | // | |
430 | // Main routine called by the user : | |
769f5114 | 431 | // it calculates the unfolded spectrum from the response matrix, measured spectrum and efficiency |
432 | // several iterations are performed until a reasonable chi2 or convergence criterion is reached | |
c0b10ad4 | 433 | // |
434 | ||
769f5114 | 435 | Int_t iIterBayes = 0 ; |
436 | Double_t convergence = 0.; | |
c0b10ad4 | 437 | |
438 | for (iIterBayes=0; iIterBayes<fMaxNumIterations; iIterBayes++) { // bayes iterations | |
a9500e70 | 439 | |
440 | CreateEstMeasured(); // create measured estimate from prior | |
441 | CreateInvResponse(); // create inverse response from prior | |
442 | CreateUnfolded(); // create unfoled spectrum from measured and inverse response | |
443 | ||
444 | convergence = GetConvergence(); | |
445 | AliDebug(0,Form("convergence at iteration %d is %e",iIterBayes,convergence)); | |
446 | ||
447 | if (fMaxConvergence>0. && convergence<fMaxConvergence && fNCalcCorrErrors == 0) { | |
448 | fNRandomIterations = iIterBayes; | |
449 | AliDebug(0,Form("convergence is met at iteration %d",iIterBayes)); | |
c0b10ad4 | 450 | break; |
451 | } | |
769f5114 | 452 | |
85b6bda9 | 453 | if (fUseSmoothing) { |
454 | if (Smooth()) { | |
455 | AliError("Couldn't smooth the unfolded spectrum!!"); | |
a9500e70 | 456 | if (fNCalcCorrErrors>0) { |
457 | AliInfo(Form("=======================\nUnfold of randomized distribution finished at iteration %d with convergence %e \n",iIterBayes,convergence)); | |
458 | } | |
459 | else { | |
460 | AliInfo(Form("\n\n=======================\nFinish at iteration %d : convergence is %e and you required it to be < %e\n=======================\n\n",iIterBayes,convergence,fMaxConvergence)); | |
769f5114 | 461 | } |
85b6bda9 | 462 | return; |
463 | } | |
464 | } | |
769f5114 | 465 | |
a9500e70 | 466 | // update the prior distribution |
467 | if (fPrior) delete fPrior ; | |
468 | fPrior = (THnSparse*)fUnfolded->Clone() ; | |
469 | fPrior->SetTitle("Prior"); | |
470 | ||
471 | } // end bayes iteration | |
472 | ||
473 | if (fNCalcCorrErrors==0) fUnfoldedFinal = (THnSparse*) fUnfolded->Clone() ; | |
474 | ||
475 | // | |
476 | //for (Long_t iBin=0; iBin<fUnfoldedFinal->GetNbins(); iBin++) AliDebug(2,Form("%e\n",fUnfoldedFinal->GetBinError(iBin))); | |
477 | // | |
478 | ||
479 | if (fNCalcCorrErrors == 0) { | |
480 | AliInfo("\n================================================\nFinished bayes iteration, now calculating errors...\n================================================\n"); | |
481 | fNCalcCorrErrors = 1; | |
769f5114 | 482 | CalculateCorrelatedErrors(); |
483 | } | |
484 | ||
a9500e70 | 485 | if (fNCalcCorrErrors >1 ) { |
486 | AliInfo(Form("\n\n=======================\nFinished at iteration %d : convergence is %e and you required it to be < %e\n=======================\n\n",iIterBayes,convergence,fMaxConvergence)); | |
487 | } | |
488 | else if(fNCalcCorrErrors>0) { | |
489 | AliInfo(Form("=======================\nUnfolding of randomized distribution finished at iteration %d with convergence %e \n",iIterBayes,convergence)); | |
c0b10ad4 | 490 | } |
c0b10ad4 | 491 | } |
492 | ||
493 | //______________________________________________________________ | |
494 | ||
495 | void AliCFUnfolding::CreateUnfolded() { | |
496 | // | |
497 | // Creates the unfolded (T) spectrum from the measured spectrum (M) and the inverse response matrix (INV) | |
498 | // We have P(T) = SUM { P(T|M) * P(M) } | |
499 | // --> T(i) = SUM_k { INV(i,k) * M(k) } | |
500 | // | |
501 | ||
502 | ||
503 | // clear the unfolded spectrum | |
a9500e70 | 504 | // if in the process of error calculation, the random unfolded spectrum is created |
505 | // otherwise the normal unfolded spectrum is created | |
506 | ||
507 | fUnfolded->Reset(); | |
c0b10ad4 | 508 | |
7bc6a013 | 509 | for (Long_t iBin=0; iBin<fInverseResponse->GetNbins(); iBin++) { |
c0b10ad4 | 510 | Double_t invResponseValue = fInverseResponse->GetBinContent(iBin,fCoordinates2N); |
511 | GetCoordinates(); | |
85b6bda9 | 512 | Double_t effValue = fEfficiency->GetBinContent(fCoordinatesN_T); |
85b6bda9 | 513 | Double_t measuredValue = fMeasured ->GetBinContent(fCoordinatesN_M); |
85b6bda9 | 514 | Double_t fill = (effValue>0. ? invResponseValue * measuredValue / effValue : 0.) ; |
769f5114 | 515 | |
85b6bda9 | 516 | if (fill>0.) { |
a9500e70 | 517 | // set errors to zero |
518 | // true errors will be filled afterwards | |
769f5114 | 519 | Double_t err = 0.; |
a9500e70 | 520 | fUnfolded->SetBinError (fCoordinatesN_T,err); |
521 | fUnfolded->AddBinContent(fCoordinatesN_T,fill); | |
85b6bda9 | 522 | } |
c0b10ad4 | 523 | } |
524 | } | |
769f5114 | 525 | |
526 | //______________________________________________________________ | |
527 | ||
528 | void AliCFUnfolding::CalculateCorrelatedErrors() { | |
529 | ||
5a575436 | 530 | // Step 1: Create randomized distribution (fRandomXXXX) of each bin of |
a9500e70 | 531 | // the measured spectrum to calculate correlated errors. |
532 | // Poisson statistics: mean = measured value of bin | |
769f5114 | 533 | // Step 2: Unfold randomized distribution |
a9500e70 | 534 | // Step 3: Store difference of unfolded spectrum from measured distribution and |
535 | // unfolded distribution from randomized distribution | |
536 | // -> fDeltaUnfoldedP (TProfile with option "S") | |
769f5114 | 537 | // Step 4: Repeat Step 1-3 several times (fNRandomIterations) |
538 | // Step 5: The spread of fDeltaUnfoldedP for each bin is the error on the unfolded spectrum of that specific bin | |
539 | ||
769f5114 | 540 | |
a9500e70 | 541 | //Do fNRandomIterations = bayes iterations performed |
542 | for (int i=0; i<fNRandomIterations; i++) { | |
543 | ||
544 | // reset prior to original one | |
545 | if (fPrior) delete fPrior ; | |
5a575436 | 546 | fPrior = (THnSparse*) fPriorOrig->Clone(); |
a9500e70 | 547 | |
548 | // create randomized distribution and stick measured spectrum to it | |
549 | CreateRandomizedDist(); | |
5a575436 | 550 | |
551 | if (fResponse) delete fResponse ; | |
552 | fResponse = (THnSparse*) fRandomResponse->Clone(); | |
553 | fResponse->SetTitle("Response"); | |
554 | ||
555 | if (fEfficiency) delete fEfficiency ; | |
556 | fEfficiency = (THnSparse*) fRandomEfficiency->Clone(); | |
557 | fEfficiency->SetTitle("Efficiency"); | |
558 | ||
559 | if (fMeasured) delete fMeasured ; | |
560 | fMeasured = (THnSparse*) fRandomMeasured->Clone(); | |
a9500e70 | 561 | fMeasured->SetTitle("Measured"); |
562 | ||
5a575436 | 563 | //unfold with randomized distributions |
a9500e70 | 564 | Unfold(); |
565 | FillDeltaUnfoldedProfile(); | |
566 | } | |
769f5114 | 567 | |
a9500e70 | 568 | // Get statistical errors for final unfolded spectrum |
569 | // ie. spread of each pt bin in fDeltaUnfoldedP | |
570 | Double_t sigma = 0.; | |
571 | Double_t dummy = 0.; | |
572 | for (Long_t iBin=0; iBin<fUnfoldedFinal->GetNbins(); iBin++) { | |
573 | dummy = fUnfoldedFinal->GetBinContent(iBin,fCoordinatesN_M); | |
574 | sigma = fDeltaUnfoldedP->GetBinError(fCoordinatesN_M); | |
575 | //AliDebug(2,Form("filling error %e\n",sigma)); | |
576 | fUnfoldedFinal->SetBinError(fCoordinatesN_M,sigma); | |
769f5114 | 577 | } |
a9500e70 | 578 | |
579 | // now errors are calculated | |
580 | fNCalcCorrErrors = 2; | |
769f5114 | 581 | } |
a9500e70 | 582 | |
769f5114 | 583 | //______________________________________________________________ |
584 | void AliCFUnfolding::CreateRandomizedDist() { | |
585 | // | |
a9500e70 | 586 | // Create randomized dist from original measured distribution |
587 | // This distribution is created several times, each time with a different random number | |
769f5114 | 588 | // |
589 | ||
5a575436 | 590 | for (Long_t iBin=0; iBin<fResponseOrig->GetNbins(); iBin++) { |
591 | Double_t val = fResponseOrig->GetBinContent(iBin,fCoordinatesN_M); //used as mean | |
592 | Double_t err = fResponseOrig->GetBinError(fCoordinatesN_M); //used as sigma | |
593 | Double_t ran = fRandom3->Gaus(val,err); | |
594 | // random = fRandom3->PoissonD(measuredValue); //doesn't work for normalized spectra, use Gaus (assuming raw counts in bin is large >10) | |
595 | fRandomResponse->SetBinContent(iBin,ran); | |
596 | } | |
597 | for (Long_t iBin=0; iBin<fEfficiencyOrig->GetNbins(); iBin++) { | |
598 | Double_t val = fEfficiencyOrig->GetBinContent(iBin,fCoordinatesN_M); //used as mean | |
599 | Double_t err = fEfficiencyOrig->GetBinError(fCoordinatesN_M); //used as sigma | |
600 | Double_t ran = fRandom3->Gaus(val,err); | |
601 | // random = fRandom3->PoissonD(measuredValue); //doesn't work for normalized spectra, use Gaus (assuming raw counts in bin is large >10) | |
602 | fRandomEfficiency->SetBinContent(iBin,ran); | |
603 | } | |
604 | for (Long_t iBin=0; iBin<fMeasuredOrig->GetNbins(); iBin++) { | |
605 | Double_t val = fMeasuredOrig->GetBinContent(iBin,fCoordinatesN_M); //used as mean | |
606 | Double_t err = fMeasuredOrig->GetBinError(fCoordinatesN_M); //used as sigma | |
607 | Double_t ran = fRandom3->Gaus(val,err); | |
769f5114 | 608 | // random = fRandom3->PoissonD(measuredValue); //doesn't work for normalized spectra, use Gaus (assuming raw counts in bin is large >10) |
5a575436 | 609 | fRandomMeasured->SetBinContent(iBin,ran); |
769f5114 | 610 | } |
611 | } | |
612 | ||
613 | //______________________________________________________________ | |
614 | void AliCFUnfolding::FillDeltaUnfoldedProfile() { | |
615 | // | |
a9500e70 | 616 | // Store difference of unfolded spectrum from measured distribution and unfolded spectrum from randomized distribution |
617 | // The delta profile has been set to a THnSparse to handle N dimension | |
618 | // The THnSparse contains in each bin the mean value and spread of the difference | |
619 | // This function updates the profile wrt to its previous mean and error | |
620 | // The relation between iterations (n+1) and n is as follows : | |
621 | // mean_{n+1} = (n*mean_n + value_{n+1}) / (n+1) | |
622 | // sigma_{n+1} = sqrt { 1/(n+1) * [ n*sigma_n^2 + (n^2+n)*(mean_{n+1}-mean_n)^2 ] } (can this be optimized?) | |
623 | ||
624 | for (Long_t iBin=0; iBin<fUnfolded->GetNbins(); iBin++) { | |
625 | Double_t deltaInBin = fUnfoldedFinal->GetBinContent(iBin,fCoordinatesN_M) - fUnfolded->GetBinContent(iBin); | |
626 | Double_t entriesInBin = fDeltaUnfoldedN->GetBinContent(fCoordinatesN_M); | |
627 | //AliDebug(2,Form("%e %e ==> delta = %e\n",fUnfoldedFinal->GetBinContent(iBin,fCoordinatesN_M),fUnfolded->GetBinContent(iBin),deltaInBin)); | |
628 | ||
629 | Double_t mean_n = fDeltaUnfoldedP->GetBinContent(fCoordinatesN_M) ; | |
630 | Double_t mean_nplus1 = mean_n ; | |
631 | mean_nplus1 *= entriesInBin ; | |
632 | mean_nplus1 += deltaInBin ; | |
633 | mean_nplus1 /= (entriesInBin+1) ; | |
634 | ||
635 | Double_t sigma = fDeltaUnfoldedP->GetBinContent(fCoordinatesN_M) ; | |
636 | sigma *= sigma ; | |
637 | sigma *= entriesInBin ; | |
638 | sigma += ( (entriesInBin*entriesInBin+entriesInBin) * TMath::Power(mean_nplus1 - mean_n,2) ) ; | |
639 | sigma /= (entriesInBin+1) ; | |
640 | sigma = TMath::Sqrt(sigma) ; | |
641 | ||
642 | //AliDebug(2,Form("sigma = %e\n",sigma)); | |
643 | ||
644 | fDeltaUnfoldedP->SetBinContent(fCoordinatesN_M,mean_nplus1) ; | |
645 | fDeltaUnfoldedP->SetBinError (fCoordinatesN_M,sigma) ; | |
646 | fDeltaUnfoldedN->SetBinContent(fCoordinatesN_M,entriesInBin+1); | |
769f5114 | 647 | } |
648 | } | |
649 | ||
85b6bda9 | 650 | //______________________________________________________________ |
651 | ||
c0b10ad4 | 652 | void AliCFUnfolding::GetCoordinates() { |
653 | // | |
654 | // assign coordinates in Measured and True spaces (dim=N) from coordinates in global space (dim=2N) | |
655 | // | |
656 | for (Int_t i = 0; i<fNVariables ; i++) { | |
657 | fCoordinatesN_M[i] = fCoordinates2N[i]; | |
658 | fCoordinatesN_T[i] = fCoordinates2N[i+fNVariables]; | |
659 | } | |
660 | } | |
661 | ||
662 | //______________________________________________________________ | |
663 | ||
664 | void AliCFUnfolding::CreateConditional() { | |
665 | // | |
666 | // creates the conditional probability matrix (R*) holding the P(M|T), given the reponse matrix R | |
667 | // | |
668 | // --> R*(i,j) = R(i,j) / SUM_k{ R(k,j) } | |
669 | // | |
670 | ||
5a575436 | 671 | fConditional = (THnSparse*) fResponse->Clone(); // output of this function |
a9500e70 | 672 | |
85b6bda9 | 673 | Int_t* dim = new Int_t [fNVariables]; |
674 | for (Int_t iDim=0; iDim<fNVariables; iDim++) dim[iDim] = fNVariables+iDim ; //dimensions corresponding to TRUE values (i.e. from N to 2N-1) | |
a9500e70 | 675 | |
676 | THnSparse* responseInT = fConditional->Projection(fNVariables,dim,"E"); // output denominator : | |
677 | // projection of the response matrix on the TRUE axis | |
85b6bda9 | 678 | delete [] dim; |
769f5114 | 679 | |
c0b10ad4 | 680 | // fill the conditional probability matrix |
7bc6a013 | 681 | for (Long_t iBin=0; iBin<fResponse->GetNbins(); iBin++) { |
c0b10ad4 | 682 | Double_t responseValue = fResponse->GetBinContent(iBin,fCoordinates2N); |
683 | GetCoordinates(); | |
a9500e70 | 684 | Double_t projValue = responseInT->GetBinContent(fCoordinatesN_T); |
769f5114 | 685 | |
85b6bda9 | 686 | Double_t fill = responseValue / projValue ; |
687 | if (fill>0. || fConditional->GetBinContent(fCoordinates2N)>0.) { | |
688 | fConditional->SetBinContent(fCoordinates2N,fill); | |
769f5114 | 689 | Double_t err = 0.; |
85b6bda9 | 690 | fConditional->SetBinError (fCoordinates2N,err); |
691 | } | |
c0b10ad4 | 692 | } |
a9500e70 | 693 | delete responseInT ; |
c0b10ad4 | 694 | } |
769f5114 | 695 | //______________________________________________________________ |
696 | ||
697 | Int_t AliCFUnfolding::GetDOF() { | |
698 | // | |
699 | // number of dof = number of bins | |
700 | // | |
701 | ||
702 | Int_t nDOF = 1 ; | |
703 | for (Int_t iDim=0; iDim<fNVariables; iDim++) { | |
704 | nDOF *= fPrior->GetAxis(iDim)->GetNbins(); | |
705 | } | |
706 | AliDebug(0,Form("Number of degrees of freedom = %d",nDOF)); | |
707 | return nDOF; | |
708 | } | |
c0b10ad4 | 709 | |
710 | //______________________________________________________________ | |
711 | ||
712 | Double_t AliCFUnfolding::GetChi2() { | |
713 | // | |
714 | // Returns the chi2 between unfolded and a priori spectrum | |
769f5114 | 715 | // This function became absolute with the correlated error calculation. |
716 | // Errors on the unfolded distribution are not known until the end | |
717 | // Use the convergence criterion instead | |
c0b10ad4 | 718 | // |
719 | ||
769f5114 | 720 | Double_t chi2 = 0. ; |
721 | Double_t error_unf = 0.; | |
7bc6a013 | 722 | for (Long_t iBin=0; iBin<fPrior->GetNbins(); iBin++) { |
85f9f9e1 | 723 | Double_t priorValue = fPrior->GetBinContent(iBin,fCoordinatesN_T); |
769f5114 | 724 | error_unf = fUnfolded->GetBinError(fCoordinatesN_T); |
85f9f9e1 | 725 | chi2 += (error_unf > 0. ? TMath::Power((fUnfolded->GetBinContent(fCoordinatesN_T) - priorValue)/error_unf,2) / priorValue : 0.) ; |
c0b10ad4 | 726 | } |
727 | return chi2; | |
728 | } | |
729 | ||
730 | //______________________________________________________________ | |
731 | ||
769f5114 | 732 | Double_t AliCFUnfolding::GetConvergence() { |
733 | // | |
734 | // Returns convergence criterion = \sum_t ((U_t^{n-1}-U_t^n)/U_t^{n-1})^2 | |
735 | // U is unfolded spectrum, t is the bin, n = current, n-1 = previous | |
736 | // | |
737 | Double_t convergence = 0.; | |
738 | Double_t priorValue = 0.; | |
739 | Double_t currentValue = 0.; | |
740 | for (Long_t iBin=0; iBin < fPrior->GetNbins(); iBin++) { | |
741 | priorValue = fPrior->GetBinContent(iBin,fCoordinatesN_T); | |
a9500e70 | 742 | currentValue = fUnfolded->GetBinContent(fCoordinatesN_T); |
769f5114 | 743 | |
744 | if (priorValue > 0.) | |
745 | convergence += ((priorValue-currentValue)/priorValue)*((priorValue-currentValue)/priorValue); | |
a9500e70 | 746 | else |
769f5114 | 747 | AliWarning(Form("priorValue = %f. Adding 0 to convergence criterion.",priorValue)); |
769f5114 | 748 | } |
749 | return convergence; | |
750 | } | |
751 | ||
752 | //______________________________________________________________ | |
753 | ||
754 | void AliCFUnfolding::SetMaxConvergencePerDOF(Double_t val) { | |
c0b10ad4 | 755 | // |
769f5114 | 756 | // Max. convergence criterion per degree of freedom : user setting |
757 | // convergence criterion = DOF*val; DOF = number of bins | |
758 | // In Jan-Fiete's multiplicity note: Convergence criterion = DOF*0.001^2 | |
c0b10ad4 | 759 | // |
760 | ||
769f5114 | 761 | Int_t nDOF = GetDOF() ; |
762 | fMaxConvergence = val * nDOF ; | |
763 | AliInfo(Form("MaxConvergence = %e. Number of degrees of freedom = %d",fMaxConvergence,nDOF)); | |
c0b10ad4 | 764 | } |
765 | ||
766 | //______________________________________________________________ | |
767 | ||
85b6bda9 | 768 | Short_t AliCFUnfolding::Smooth() { |
c0b10ad4 | 769 | // |
770 | // Smoothes the unfolded spectrum | |
85b6bda9 | 771 | // |
772 | // By default each cell content is replaced by the average with the neighbouring bins (but not diagonally-neighbouring bins) | |
773 | // However, if a specific function fcn has been defined in UseSmoothing(fcn), the unfolded will be fit and updated using fcn | |
c0b10ad4 | 774 | // |
775 | ||
85b6bda9 | 776 | if (fSmoothFunction) { |
7bc6a013 | 777 | AliDebug(2,Form("Smoothing spectrum with fit function %p",fSmoothFunction)); |
85b6bda9 | 778 | return SmoothUsingFunction(); |
779 | } | |
7036630f | 780 | else return SmoothUsingNeighbours(fUnfolded); |
85b6bda9 | 781 | } |
782 | ||
783 | //______________________________________________________________ | |
784 | ||
7036630f | 785 | Short_t AliCFUnfolding::SmoothUsingNeighbours(THnSparse* hist) { |
85b6bda9 | 786 | // |
787 | // Smoothes the unfolded spectrum using neighouring bins | |
788 | // | |
789 | ||
7036630f | 790 | Int_t const nDimensions = hist->GetNdimensions() ; |
791 | Int_t* coordinates = new Int_t[nDimensions]; | |
792 | ||
793 | Int_t* numBins = new Int_t[nDimensions]; | |
794 | for (Int_t iVar=0; iVar<nDimensions; iVar++) numBins[iVar] = hist->GetAxis(iVar)->GetNbins(); | |
c0b10ad4 | 795 | |
7036630f | 796 | //need a copy because hist will be updated during the loop, and this creates problems |
797 | THnSparse* copy = (THnSparse*)hist->Clone(); | |
c0b10ad4 | 798 | |
7bc6a013 | 799 | for (Long_t iBin=0; iBin<copy->GetNbins(); iBin++) { //loop on non-empty bins |
7036630f | 800 | Double_t content = copy->GetBinContent(iBin,coordinates); |
7bc6a013 | 801 | Double_t error2 = TMath::Power(copy->GetBinError(iBin),2); |
c0b10ad4 | 802 | |
803 | // skip the under/overflow bins... | |
804 | Bool_t isOutside = kFALSE ; | |
7036630f | 805 | for (Int_t iVar=0; iVar<nDimensions; iVar++) { |
806 | if (coordinates[iVar]<1 || coordinates[iVar]>numBins[iVar]) { | |
c0b10ad4 | 807 | isOutside=kTRUE; |
808 | break; | |
809 | } | |
810 | } | |
811 | if (isOutside) continue; | |
812 | ||
813 | Int_t neighbours = 0; // number of neighbours to average with | |
814 | ||
7036630f | 815 | for (Int_t iVar=0; iVar<nDimensions; iVar++) { |
816 | if (coordinates[iVar] > 1) { // must not be on low edge border | |
817 | coordinates[iVar]-- ; //get lower neighbouring bin | |
818 | content += copy->GetBinContent(coordinates); | |
819 | error2 += TMath::Power(copy->GetBinError(coordinates),2); | |
c0b10ad4 | 820 | neighbours++; |
7036630f | 821 | coordinates[iVar]++ ; //back to initial coordinate |
c0b10ad4 | 822 | } |
7036630f | 823 | if (coordinates[iVar] < numBins[iVar]) { // must not be on up edge border |
824 | coordinates[iVar]++ ; //get upper neighbouring bin | |
825 | content += copy->GetBinContent(coordinates); | |
826 | error2 += TMath::Power(copy->GetBinError(coordinates),2); | |
c0b10ad4 | 827 | neighbours++; |
7036630f | 828 | coordinates[iVar]-- ; //back to initial coordinate |
c0b10ad4 | 829 | } |
830 | } | |
85b6bda9 | 831 | // make an average |
7036630f | 832 | hist->SetBinContent(coordinates,content/(1.+neighbours)); |
833 | hist->SetBinError (coordinates,TMath::Sqrt(error2)/(1.+neighbours)); | |
c0b10ad4 | 834 | } |
835 | delete [] numBins; | |
7036630f | 836 | delete [] coordinates ; |
c0b10ad4 | 837 | delete copy; |
85b6bda9 | 838 | return 0; |
c0b10ad4 | 839 | } |
840 | ||
85b6bda9 | 841 | //______________________________________________________________ |
842 | ||
843 | Short_t AliCFUnfolding::SmoothUsingFunction() { | |
844 | // | |
845 | // Fits the unfolded spectrum using the function fSmoothFunction | |
846 | // | |
847 | ||
7bc6a013 | 848 | AliDebug(0,Form("Smooth function is a %s with option \"%s\" and has %d parameters : ",fSmoothFunction->ClassName(),fSmoothOption,fSmoothFunction->GetNpar())); |
85b6bda9 | 849 | |
7bc6a013 | 850 | for (Int_t iPar=0; iPar<fSmoothFunction->GetNpar(); iPar++) AliDebug(0,Form("par[%d]=%e",iPar,fSmoothFunction->GetParameter(iPar))); |
851 | ||
852 | Int_t fitResult = 0; | |
85b6bda9 | 853 | |
854 | switch (fNVariables) { | |
7bc6a013 | 855 | case 1 : fitResult = fUnfolded->Projection(0) ->Fit(fSmoothFunction,fSmoothOption); break; |
856 | case 2 : fitResult = fUnfolded->Projection(1,0) ->Fit(fSmoothFunction,fSmoothOption); break; // (1,0) instead of (0,1) -> TAxis issue | |
857 | case 3 : fitResult = fUnfolded->Projection(0,1,2)->Fit(fSmoothFunction,fSmoothOption); break; | |
858 | default: AliFatal(Form("Cannot handle such fit in %d dimensions",fNVariables)) ; return 1; | |
859 | } | |
860 | ||
861 | if (fitResult != 0) { | |
862 | AliWarning(Form("Fit failed with status %d, stopping the loop",fitResult)); | |
863 | return 1; | |
85b6bda9 | 864 | } |
865 | ||
866 | Int_t nDim = fNVariables; | |
867 | Int_t* bins = new Int_t[nDim]; // number of bins for each variable | |
868 | Long_t nBins = 1; // used to calculate the total number of bins in the THnSparse | |
869 | ||
870 | for (Int_t iVar=0; iVar<nDim; iVar++) { | |
871 | bins[iVar] = fUnfolded->GetAxis(iVar)->GetNbins(); | |
872 | nBins *= bins[iVar]; | |
873 | } | |
874 | ||
875 | Int_t *bin = new Int_t[nDim]; // bin to fill the THnSparse (holding the bin coordinates) | |
876 | Double_t x[3] = {0,0,0} ; // value in bin center (max dimension is 3 (TF3)) | |
877 | ||
878 | // loop on the bins and update of fUnfolded | |
879 | // THnSparse::Multiply(TF1*) doesn't exist, so let's do it bin by bin | |
880 | for (Long_t iBin=0; iBin<nBins; iBin++) { | |
881 | Long_t bin_tmp = iBin ; | |
882 | for (Int_t iVar=0; iVar<nDim; iVar++) { | |
883 | bin[iVar] = 1 + bin_tmp % bins[iVar] ; | |
884 | bin_tmp /= bins[iVar] ; | |
885 | x[iVar] = fUnfolded->GetAxis(iVar)->GetBinCenter(bin[iVar]); | |
886 | } | |
887 | Double_t functionValue = fSmoothFunction->Eval(x[0],x[1],x[2]) ; | |
12e419d5 | 888 | fUnfolded->SetBinError (bin,fUnfolded->GetBinError(bin)*functionValue/fUnfolded->GetBinContent(bin)); |
85b6bda9 | 889 | fUnfolded->SetBinContent(bin,functionValue); |
85b6bda9 | 890 | } |
700a1189 | 891 | delete [] bins; |
892 | delete [] bin ; | |
85b6bda9 | 893 | return 0; |
894 | } | |
c0b10ad4 | 895 | |
896 | //______________________________________________________________ | |
897 | ||
898 | void AliCFUnfolding::CreateFlatPrior() { | |
899 | // | |
900 | // Creates a flat prior distribution | |
901 | // | |
902 | ||
903 | AliInfo("Creating a flat a priori distribution"); | |
904 | ||
905 | // create the frame of the THnSparse given (for example) the one from the efficiency map | |
906 | fPrior = (THnSparse*) fEfficiency->Clone(); | |
a9500e70 | 907 | fPrior->SetTitle("Prior"); |
c0b10ad4 | 908 | |
85b6bda9 | 909 | if (fNVariables != fPrior->GetNdimensions()) |
910 | AliFatal(Form("The prior matrix should have %d dimensions, and it has actually %d",fNVariables,fPrior->GetNdimensions())); | |
911 | ||
c0b10ad4 | 912 | Int_t nDim = fNVariables; |
913 | Int_t* bins = new Int_t[nDim]; // number of bins for each variable | |
914 | Long_t nBins = 1; // used to calculate the total number of bins in the THnSparse | |
915 | ||
916 | for (Int_t iVar=0; iVar<nDim; iVar++) { | |
917 | bins[iVar] = fPrior->GetAxis(iVar)->GetNbins(); | |
918 | nBins *= bins[iVar]; | |
919 | } | |
920 | ||
921 | Int_t *bin = new Int_t[nDim]; // bin to fill the THnSparse (holding the bin coordinates) | |
922 | ||
923 | // loop that sets 1 in each bin | |
924 | for (Long_t iBin=0; iBin<nBins; iBin++) { | |
925 | Long_t bin_tmp = iBin ; | |
926 | for (Int_t iVar=0; iVar<nDim; iVar++) { | |
927 | bin[iVar] = 1 + bin_tmp % bins[iVar] ; | |
928 | bin_tmp /= bins[iVar] ; | |
929 | } | |
930 | fPrior->SetBinContent(bin,1.); // put 1 everywhere | |
85b6bda9 | 931 | fPrior->SetBinError (bin,0.); // put 0 everywhere |
c0b10ad4 | 932 | } |
933 | ||
5a575436 | 934 | fPriorOrig = (THnSparse*)fPrior->Clone(); |
c0b10ad4 | 935 | |
936 | delete [] bin; | |
937 | delete [] bins; | |
938 | } |