]>
Commit | Line | Data |
---|---|---|
7dacdf84 | 1 | // Object holding the Energy loss fit 'correction' |
7984e5f7 | 2 | // |
3 | // These are generated from Monte-Carlo or real ESDs. | |
7dacdf84 | 4 | // |
0bd4b00f | 5 | #include "AliFMDCorrELossFit.h" |
6 | #include "AliForwardUtil.h" | |
7 | #include <TF1.h> | |
8 | #include <TBrowser.h> | |
9 | #include <TVirtualPad.h> | |
10 | #include <THStack.h> | |
11 | #include <TH1D.h> | |
12 | #include <AliLog.h> | |
7dacdf84 | 13 | #include <TMath.h> |
0bd4b00f | 14 | #include <TList.h> |
15 | #include <iostream> | |
16 | #include <iomanip> | |
17 | ||
fb3430ac | 18 | Double_t AliFMDCorrELossFit::ELossFit::fgMaxRelError = .12; |
0bd4b00f | 19 | Double_t AliFMDCorrELossFit::ELossFit::fgLeastWeight = 1e-5; |
20 | Double_t AliFMDCorrELossFit::ELossFit::fgMaxChi2nu = 20; | |
21 | ||
22 | //____________________________________________________________________ | |
23 | AliFMDCorrELossFit::ELossFit::ELossFit() | |
24 | : fN(0), | |
25 | fNu(0), | |
26 | fChi2(0), | |
27 | fC(0), | |
28 | fDelta(0), | |
29 | fXi(0), | |
30 | fSigma(0), | |
31 | fSigmaN(0), | |
32 | fA(0), | |
33 | fEC(0), | |
34 | fEDelta(0), | |
35 | fEXi(0), | |
36 | fESigma(0), | |
37 | fESigmaN(0), | |
38 | fEA(0), | |
39 | fQuality(0), | |
40 | fDet(0), | |
41 | fRing('\0'), | |
42 | fBin(0) | |
7984e5f7 | 43 | { |
44 | // | |
45 | // Default constructor | |
46 | // | |
47 | // | |
48 | } | |
0bd4b00f | 49 | //____________________________________________________________________ |
50 | AliFMDCorrELossFit::ELossFit::ELossFit(Int_t quality, const TF1& f) | |
51 | : fN(f.GetNpar() > AliForwardUtil::ELossFitter::kN ? | |
6feacd76 | 52 | Int_t(f.GetParameter(AliForwardUtil::ELossFitter::kN)) : |
0bd4b00f | 53 | 1), |
54 | fNu(f.GetNDF()), | |
55 | fChi2(f.GetChisquare()), | |
56 | fC(f.GetParameter(AliForwardUtil::ELossFitter::kC)), | |
57 | fDelta(f.GetParameter(AliForwardUtil::ELossFitter::kDelta)), | |
58 | fXi(f.GetParameter(AliForwardUtil::ELossFitter::kXi)), | |
59 | fSigma(f.GetParameter(AliForwardUtil::ELossFitter::kSigma)), | |
60 | fSigmaN(f.GetParameter(AliForwardUtil::ELossFitter::kSigmaN)), | |
61 | fA(0), | |
62 | fEC(f.GetParError(AliForwardUtil::ELossFitter::kC)), | |
63 | fEDelta(f.GetParError(AliForwardUtil::ELossFitter::kDelta)), | |
64 | fEXi(f.GetParError(AliForwardUtil::ELossFitter::kXi)), | |
65 | fESigma(f.GetParError(AliForwardUtil::ELossFitter::kSigma)), | |
66 | fESigmaN(f.GetParError(AliForwardUtil::ELossFitter::kSigmaN)), | |
67 | fEA(0), | |
68 | fQuality(quality), | |
69 | fDet(0), | |
70 | fRing('\0'), | |
71 | fBin(0) | |
72 | { | |
7984e5f7 | 73 | // |
74 | // Construct from a function | |
75 | // | |
76 | // Parameters: | |
77 | // quality Quality flag | |
78 | // f Function | |
79 | // | |
0bd4b00f | 80 | if (fN <= 0) return; |
81 | fA = new Double_t[fN]; | |
82 | fEA = new Double_t[fN]; | |
83 | for (Int_t i = 0; i < fN-1; i++) { | |
84 | fA[i] = f.GetParameter(AliForwardUtil::ELossFitter::kA+i); | |
85 | fEA[i] = f.GetParError(AliForwardUtil::ELossFitter::kA+i); | |
86 | } | |
87 | fA[fN-1] = -9999; | |
88 | fEA[fN-1] = -9999; | |
89 | } | |
90 | ||
91 | //____________________________________________________________________ | |
92 | AliFMDCorrELossFit::ELossFit::ELossFit(Int_t quality,UShort_t n, | |
93 | Double_t chi2, UShort_t nu, | |
94 | Double_t c, Double_t ec, | |
95 | Double_t delta, Double_t edelta, | |
96 | Double_t xi, Double_t exi, | |
97 | Double_t sigma, Double_t esigma, | |
98 | Double_t sigman, Double_t esigman, | |
fb3430ac | 99 | const Double_t* a,const Double_t* ea) |
0bd4b00f | 100 | : fN(n), |
101 | fNu(nu), | |
102 | fChi2(chi2), | |
103 | fC(c), | |
104 | fDelta(delta), | |
105 | fXi(xi), | |
106 | fSigma(sigma), | |
107 | fSigmaN(sigman), | |
108 | fA(0), | |
109 | fEC(ec), | |
110 | fEDelta(edelta), | |
111 | fEXi(exi), | |
112 | fESigma(esigma), | |
113 | fESigmaN(esigman), | |
114 | fEA(0), | |
115 | fQuality(quality), | |
116 | fDet(0), | |
117 | fRing('\0'), | |
118 | fBin(0) | |
119 | { | |
7984e5f7 | 120 | // |
121 | // Constructor with full parameter set | |
122 | // | |
123 | // Parameters: | |
124 | // quality Quality flag | |
125 | // n @f$ N@f$ - Number of fitted peaks | |
126 | // chi2 @f$ \chi^2 @f$ | |
127 | // nu @f$ \nu @f$ - number degrees of freedom | |
128 | // c @f$ C@f$ - scale constant | |
129 | // ec @f$ \delta C@f$ - error on @f$ C@f$ | |
130 | // delta @f$ \Delta@f$ - Most probable value | |
131 | // edelta @f$ \delta\Delta@f$ - error on @f$\Delta@f$ | |
132 | // xi @f$ \xi@f$ - width | |
133 | // exi @f$ \delta\xi@f$ - error on @f$\xi@f$ | |
134 | // sigma @f$ \sigma@f$ - Width of Gaussian | |
135 | // esigma @f$ \delta\sigma@f$ - error on @f$\sigma@f$ | |
136 | // sigman @f$ \sigma_n@f$ - Noise width | |
137 | // esigman @f$ \delta\sigma_n@f$ - error on @f$\sigma_n@f$ | |
138 | // a Array of @f$ N-1@f$ weights @f$ a_i@f$ for | |
139 | // @f$ i=2,\ldots@f$ | |
140 | // ea Array of @f$ N-1@f$ error on the weights @f$ a_i@f$ for | |
141 | // @f$ i=2,\ldots@f$ | |
142 | // | |
0bd4b00f | 143 | if (fN <= 0) return; |
144 | fA = new Double_t[fN]; | |
145 | fEA = new Double_t[fN]; | |
146 | for (Int_t i = 0; i < fN-1; i++) { | |
147 | fA[i] = a[i]; | |
148 | fEA[i] = ea[i]; | |
149 | } | |
150 | fA[fN-1] = -9999; | |
151 | fEA[fN-1] = -9999; | |
152 | } | |
153 | //____________________________________________________________________ | |
154 | AliFMDCorrELossFit::ELossFit::ELossFit(const ELossFit& o) | |
155 | : TObject(o), | |
156 | fN(o.fN), | |
157 | fNu(o.fNu), | |
158 | fChi2(o.fChi2), | |
159 | fC(o.fC), | |
160 | fDelta(o.fDelta), | |
161 | fXi(o.fXi), | |
162 | fSigma(o.fSigma), | |
163 | fSigmaN(o.fSigmaN), | |
164 | fA(0), | |
165 | fEC(o.fEC), | |
166 | fEDelta(o.fEDelta), | |
167 | fEXi(o.fEXi), | |
168 | fESigma(o.fESigma), | |
169 | fESigmaN(o.fESigmaN), | |
170 | fEA(0), | |
171 | fQuality(o.fQuality), | |
172 | fDet(o.fDet), | |
173 | fRing(o.fRing), | |
174 | fBin(o.fBin) | |
175 | { | |
7984e5f7 | 176 | // |
177 | // Copy constructor | |
178 | // | |
179 | // Parameters: | |
180 | // o Object to copy from | |
181 | // | |
0bd4b00f | 182 | if (fN <= 0) return; |
183 | fA = new Double_t[fN]; | |
184 | fEA = new Double_t[fN]; | |
185 | for (Int_t i = 0; i < fN-1; i++) { | |
186 | fA[i] = o.fA[i]; | |
187 | fEA[i] = o.fEA[i]; | |
188 | } | |
189 | fA[fN-1] = -9999; | |
190 | fEA[fN-1] = -9999; | |
191 | } | |
192 | ||
193 | //____________________________________________________________________ | |
194 | AliFMDCorrELossFit::ELossFit& | |
195 | AliFMDCorrELossFit::ELossFit::operator=(const ELossFit& o) | |
196 | { | |
7984e5f7 | 197 | // |
198 | // Assignment operator | |
199 | // | |
200 | // Parameters: | |
201 | // o Object to assign from | |
202 | // | |
203 | // Return: | |
204 | // Reference to this object | |
205 | // | |
d015ecfe | 206 | if (&o == this) return *this; |
0bd4b00f | 207 | fN = o.fN; |
208 | fNu = o.fNu; | |
209 | fChi2 = o.fChi2; | |
210 | fC = o.fC; | |
211 | fDelta = o.fDelta; | |
212 | fXi = o.fXi; | |
213 | fSigma = o.fSigma; | |
214 | fSigmaN = o.fSigmaN; | |
215 | fEC = o.fEC; | |
216 | fEDelta = o.fEDelta; | |
217 | fEXi = o.fEXi; | |
218 | fESigma = o.fESigma; | |
219 | fESigmaN = o.fESigmaN; | |
220 | fQuality = o.fQuality; | |
221 | fDet = o.fDet; | |
222 | fRing = o.fRing; | |
223 | fBin = o.fBin; | |
224 | if (fA) delete [] fA; | |
225 | if (fEA) delete [] fEA; | |
226 | fA = 0; | |
227 | fEA = 0; | |
228 | ||
229 | if (fN <= 0) return *this; | |
230 | fA = new Double_t[fN]; | |
231 | fEA = new Double_t[fN]; | |
232 | for (Int_t i = 0; i < fN; i++) { | |
233 | fA[i] = o.fA[i]; | |
234 | fEA[i] = o.fEA[i]; | |
235 | } | |
236 | ||
237 | return *this; | |
238 | } | |
239 | ||
240 | //____________________________________________________________________ | |
241 | AliFMDCorrELossFit::ELossFit::~ELossFit() | |
242 | { | |
243 | if (fA) delete[] fA; | |
244 | if (fEA) delete[] fEA; | |
245 | } | |
246 | ||
247 | ||
248 | //____________________________________________________________________ | |
249 | Int_t | |
250 | AliFMDCorrELossFit::ELossFit::FindMaxWeight(Double_t maxRelError, | |
251 | Double_t leastWeight, | |
252 | UShort_t maxN) const | |
253 | { | |
7984e5f7 | 254 | // |
255 | // Find the maximum weight to use. The maximum weight is the | |
256 | // largest i for which | |
257 | // | |
258 | // - @f$ i \leq \max{N}@f$ | |
259 | // - @f$ a_i > \min{a}@f$ | |
260 | // - @f$ \delta a_i/a_i > \delta_{max}@f$ | |
261 | // | |
262 | // Parameters: | |
263 | // maxRelError @f$ \min{a}@f$ | |
264 | // leastWeight @f$ \delta_{max}@f$ | |
265 | // maxN @f$ \max{N}@f$ | |
266 | // | |
267 | // Return: | |
268 | // The largest index @f$ i@f$ for which the above | |
269 | // conditions hold. Will never return less than 1. | |
270 | // | |
0bd4b00f | 271 | Int_t n = TMath::Min(maxN, UShort_t(fN-1)); |
272 | Int_t m = 1; | |
273 | // fN is one larger than we have data | |
274 | for (Int_t i = 0; i < n-1; i++, m++) { | |
275 | if (fA[i] < leastWeight) break; | |
276 | if (fEA[i] / fA[i] > maxRelError) break; | |
277 | } | |
278 | return m; | |
279 | } | |
280 | ||
281 | //____________________________________________________________________ | |
282 | Double_t | |
283 | AliFMDCorrELossFit::ELossFit::Evaluate(Double_t x, | |
284 | UShort_t maxN) const | |
285 | { | |
7984e5f7 | 286 | // |
287 | // Evaluate | |
288 | // @f[ | |
289 | // f_N(x;\Delta,\xi,\sigma') = | |
290 | // \sum_{i=1}^{n} a_i f(x;\Delta_i,\xi_i,\sigma_i') | |
291 | // @f] | |
292 | // | |
293 | // (see AliForwardUtil::NLandauGaus) for the maximum @f$ N @f$ | |
294 | // that fulfills the requirements | |
295 | // | |
296 | // Parameters: | |
297 | // x Where to evaluate | |
298 | // maxN @f$ \max{N}@f$ | |
299 | // | |
300 | // Return: | |
301 | // @f$ f_N(x;\Delta,\xi,\sigma')@f$ | |
302 | // | |
0bd4b00f | 303 | return AliForwardUtil::NLandauGaus(x, fDelta, fXi, fSigma, fSigmaN, |
304 | TMath::Min(maxN, UShort_t(fN)), fA); | |
305 | } | |
306 | ||
307 | //____________________________________________________________________ | |
308 | Double_t | |
309 | AliFMDCorrELossFit::ELossFit::EvaluateWeighted(Double_t x, | |
310 | UShort_t maxN) const | |
311 | { | |
7984e5f7 | 312 | // |
313 | // Evaluate | |
314 | // @f[ | |
315 | // f_W(x;\Delta,\xi,\sigma') = | |
316 | // \frac{\sum_{i=1}^{n} i a_i f_i(x;\Delta,\xi,\sigma')}{ | |
317 | // f_N(x;\Delta,\xi,\sigma')} = | |
318 | // \frac{\sum_{i=1}^{n} i a_i f(x;\Delta_i,\xi_i,\sigma_i')}{ | |
319 | // \sum_{i=1}^{n} a_i f(x;\Delta_i,\xi_i,\sigma_i')} | |
320 | // @f] | |
321 | // where @f$ n@f$ fulfills the requirements (see FindMaxWeight). | |
322 | // | |
323 | // If the denominator is zero, then 1 is returned. | |
324 | // | |
325 | // See also AliForwardUtil::ILandauGaus and AliForwardUtil::NLandauGaus | |
326 | // for more information on the evaluated functions. | |
327 | // | |
328 | // Parameters: | |
329 | // x Where to evaluate | |
330 | // maxN @f$ \max{N}@f$ | |
331 | // | |
332 | // Return: | |
333 | // @f$ f_W(x;\Delta,\xi,\sigma')@f$. | |
334 | // | |
0bd4b00f | 335 | UShort_t n = TMath::Min(maxN, UShort_t(fN-1)); |
336 | Double_t num = 0; | |
337 | Double_t den = 0; | |
338 | for (Int_t i = 1; i <= n; i++) { | |
339 | Double_t a = (i == 1 ? 1 : fA[i-1]); | |
340 | if (fA[i-1] < 0) break; | |
341 | Double_t f = AliForwardUtil::ILandauGaus(x,fDelta,fXi,fSigma,fSigmaN,i); | |
342 | num += i * a * f; | |
343 | den += a * f; | |
344 | } | |
345 | if (den <= 0) return 1; | |
346 | return num / den; | |
347 | } | |
348 | ||
349 | ||
350 | #define OUTPAR(N,V,E) \ | |
351 | std::setprecision(9) << \ | |
352 | std::setw(12) << N << ": " << \ | |
353 | std::setw(14) << V << " +/- " << \ | |
354 | std::setw(14) << E << " (" << \ | |
355 | std::setprecision(-1) << \ | |
356 | std::setw(5) << 100*(V>0?E/V:1) << "%)\n" | |
357 | ||
358 | ||
359 | //____________________________________________________________________ | |
360 | Int_t | |
361 | AliFMDCorrELossFit::ELossFit::Compare(const TObject* o) const | |
362 | { | |
7984e5f7 | 363 | // |
364 | // Compare to another ELossFit object. | |
365 | // | |
366 | // - +1, if this quality is better (larger) than other objects quality | |
367 | // - -1, if this quality is worse (smaller) than other objects quality | |
368 | // - +1, if this @f$|\chi^2/\nu-1|@f$ is smaller than the same for other | |
369 | // - -1, if this @f$|\chi^2/\nu-1|@f$ is larger than the same for other | |
370 | // - 0 otherwise | |
371 | // | |
372 | // Parameters: | |
373 | // o Other object to compare to | |
374 | // | |
0bd4b00f | 375 | const ELossFit* other = static_cast<const ELossFit*>(o); |
376 | if (this->fQuality < other->fQuality) return -1; | |
377 | if (this->fQuality > other->fQuality) return +1; | |
378 | Double_t chi2nu = (fNu == 0 ? 1000 : fChi2 / fNu); | |
379 | Double_t oChi2nu = (other->fNu == 0 ? 1000 : other->fChi2 / other->fNu); | |
380 | if (TMath::Abs(chi2nu-1) < TMath::Abs(oChi2nu-1)) return +1; | |
381 | if (TMath::Abs(chi2nu-1) > TMath::Abs(oChi2nu-1)) return -1; | |
382 | return 0; | |
383 | } | |
384 | ||
385 | //____________________________________________________________________ | |
386 | void | |
387 | AliFMDCorrELossFit::ELossFit::Print(Option_t*) const | |
388 | { | |
7984e5f7 | 389 | // |
390 | // Information to standard output | |
391 | // | |
392 | // Parameters: | |
393 | // option Not used | |
394 | // | |
0bd4b00f | 395 | std::cout << GetName() << ":\n" |
396 | << " chi^2/nu = " << fChi2 << "/" << fNu << " = " | |
397 | << (fNu == 0 ? 999 : fChi2 / fNu) << "\n" | |
398 | << " Quality: " << fQuality << "\n" | |
399 | << " NParticles: " << fN << " (" << FindMaxWeight() << ")\n" | |
400 | << OUTPAR("Delta", fDelta, fEDelta) | |
401 | << OUTPAR("xi", fXi, fEXi) | |
402 | << OUTPAR("sigma", fSigma, fESigma) | |
403 | << OUTPAR("sigma_n", fSigmaN, fESigmaN); | |
404 | for (Int_t i = 0; i < fN-1; i++) | |
405 | std::cout << OUTPAR(Form("a%d", i+2), fA[i], fEA[i]); | |
406 | std::cout << std::flush; | |
407 | } | |
408 | ||
409 | //____________________________________________________________________ | |
410 | const Char_t* | |
411 | AliFMDCorrELossFit::ELossFit::GetName() const | |
412 | { | |
7984e5f7 | 413 | // |
414 | // Get the name of this object | |
415 | // | |
416 | // | |
417 | // Return: | |
418 | // | |
419 | // | |
0bd4b00f | 420 | return Form("FMD%d%c_etabin%03d", fDet, fRing, fBin); |
421 | } | |
422 | ||
423 | //____________________________________________________________________ | |
424 | void | |
425 | AliFMDCorrELossFit::ELossFit::Browse(TBrowser* b) | |
426 | { | |
7984e5f7 | 427 | // |
428 | // Browse this object | |
429 | // | |
430 | // Parameters: | |
431 | // b Browser | |
432 | // | |
0bd4b00f | 433 | Draw(b ? b->GetDrawOption() : "comp"); |
434 | gPad->SetLogy(); | |
435 | gPad->Update(); | |
436 | } | |
437 | ||
438 | //____________________________________________________________________ | |
439 | void | |
440 | AliFMDCorrELossFit::ELossFit::Draw(Option_t* option) | |
441 | { | |
7984e5f7 | 442 | // |
443 | // Draw this fit | |
444 | // | |
445 | // Parameters: | |
446 | // option Options | |
447 | // - COMP Draw components too | |
448 | // | |
0bd4b00f | 449 | TString opt(option); |
450 | opt.ToUpper(); | |
451 | bool comp = false; | |
452 | if (opt.Contains("COMP")) { | |
453 | opt.ReplaceAll("COMP",""); | |
454 | comp = true; | |
455 | } | |
456 | if (!opt.Contains("SAME")) { | |
457 | gPad->Clear(); | |
458 | } | |
459 | ||
460 | TObjArray cleanup; | |
461 | TF1* tot = AliForwardUtil::MakeNLandauGaus(1, | |
462 | fDelta, fXi, | |
463 | fSigma, fSigmaN, | |
464 | fN, fA, | |
465 | 0.01, 10); | |
466 | tot->SetLineColor(kBlack); | |
467 | tot->SetLineWidth(2); | |
468 | tot->SetLineStyle(1); | |
469 | tot->SetTitle(GetName()); | |
470 | Double_t max = tot->GetMaximum(); | |
471 | ||
472 | if (!opt.Contains("SAME")) { | |
473 | TH1* frame = new TH1F(GetName(), | |
474 | Form("FMD%d%c, eta bin %d",fDet,fRing,fBin), | |
475 | 100, 0, 10); | |
476 | frame->SetMinimum(max/10000); | |
477 | frame->SetMaximum(max*1.4); | |
478 | frame->SetXTitle("#Delta / #Delta_{mip}"); | |
479 | frame->Draw(); | |
480 | opt.Append(" SAME"); | |
481 | } | |
482 | tot->DrawCopy(opt.Data()); | |
483 | cleanup.Add(tot); | |
484 | ||
485 | if (!comp) { | |
486 | gPad->cd(); | |
487 | return; | |
488 | } | |
489 | ||
490 | Double_t min = max; | |
491 | opt.Append(" same"); | |
492 | Int_t maxW = FindMaxWeight(); | |
493 | for (Int_t i=1; i <= fN; i++) { | |
494 | TF1* f = AliForwardUtil::MakeILandauGaus((i == 1 ? 1 : fA[i-2]), | |
495 | fDelta, fXi, | |
496 | fSigma, fSigmaN, | |
497 | i, 0.01, 10); | |
498 | f->SetLineWidth(2); | |
499 | f->SetLineStyle(i > maxW ? 2 : 1); | |
500 | min = TMath::Min(f->GetMaximum(), min); | |
501 | f->DrawCopy(opt.Data()); | |
502 | cleanup.Add(f); | |
503 | } | |
504 | min /= 100; | |
505 | tot->GetHistogram()->SetMaximum(max); | |
506 | tot->GetHistogram()->SetMinimum(min); | |
507 | tot->GetHistogram()->GetYaxis()->SetRangeUser(min, max); | |
508 | ||
509 | gPad->cd(); | |
510 | } | |
511 | ||
512 | ||
513 | //____________________________________________________________________ | |
514 | #define CHECKPAR(V,E,T) ((V > 0) && (E / V < T)) | |
515 | ||
16ac05a3 | 516 | //____________________________________________________________________ |
517 | Double_t | |
518 | AliFMDCorrELossFit::ELossFit::GetLowerBound(Double_t f) const | |
519 | { | |
520 | // | |
521 | // Return | |
522 | // Delta * f | |
523 | return f * fDelta; | |
524 | } | |
5bb5d1f6 | 525 | //____________________________________________________________________ |
526 | Double_t | |
527 | AliFMDCorrELossFit::ELossFit::GetLowerBound(Double_t f, | |
528 | Bool_t includeSigma) const | |
529 | { | |
530 | // | |
531 | // Return | |
532 | // Delta - f * (xi + sigma) | |
533 | return fDelta - f * (fXi + (includeSigma ? fSigma : 0)); | |
534 | } | |
535 | ||
0bd4b00f | 536 | //____________________________________________________________________ |
537 | void | |
538 | AliFMDCorrELossFit::ELossFit::CalculateQuality(Double_t maxChi2nu, | |
539 | Double_t maxRelError, | |
540 | Double_t leastWeight) | |
541 | { | |
7984e5f7 | 542 | // |
543 | // Calculate the quality | |
544 | // | |
0bd4b00f | 545 | Int_t qual = 0; |
546 | if (fNu > 0 && fChi2 / fNu < maxChi2nu) qual += 4;; | |
547 | if (CHECKPAR(fDelta, fEDelta, maxRelError)) qual++; | |
548 | if (CHECKPAR(fXi, fEXi, maxRelError)) qual++; | |
549 | if (CHECKPAR(fSigma, fESigma, maxRelError)) qual++; | |
550 | if (CHECKPAR(fSigmaN, fESigmaN, maxRelError)) qual++; | |
551 | qual += FindMaxWeight(1.5*maxRelError, leastWeight, fN); | |
552 | fQuality = qual; | |
553 | } | |
554 | ||
555 | //____________________________________________________________________ | |
556 | AliFMDCorrELossFit::AliFMDCorrELossFit() | |
557 | : TObject(), | |
558 | fRings(), | |
559 | fEtaAxis(0,0,0), | |
560 | fLowCut(0) | |
561 | { | |
7984e5f7 | 562 | // |
563 | // Default constructor | |
564 | // | |
0bd4b00f | 565 | fRings.SetOwner(kTRUE); |
566 | fEtaAxis.SetTitle("#eta"); | |
567 | fEtaAxis.SetName("etaAxis"); | |
568 | fRings.SetName("rings"); | |
569 | } | |
570 | ||
571 | //____________________________________________________________________ | |
572 | AliFMDCorrELossFit::AliFMDCorrELossFit(const AliFMDCorrELossFit& o) | |
573 | : TObject(o), | |
574 | fRings(o.fRings), | |
575 | fEtaAxis(o.fEtaAxis.GetNbins(),o.fEtaAxis.GetXmin(),o.fEtaAxis.GetXmax()), | |
576 | fLowCut(0) | |
577 | { | |
7984e5f7 | 578 | // |
579 | // Copy constructor | |
580 | // | |
581 | // Parameters: | |
582 | // o Object to copy from | |
583 | // | |
0bd4b00f | 584 | fEtaAxis.SetTitle("#eta"); |
585 | fEtaAxis.SetName("etaAxis"); | |
586 | } | |
587 | ||
588 | //____________________________________________________________________ | |
589 | AliFMDCorrELossFit::~AliFMDCorrELossFit() | |
590 | { | |
7984e5f7 | 591 | // |
592 | // Destructor | |
593 | // | |
0bd4b00f | 594 | fRings.Clear(); |
595 | } | |
596 | ||
597 | //____________________________________________________________________ | |
598 | AliFMDCorrELossFit& | |
599 | AliFMDCorrELossFit::operator=(const AliFMDCorrELossFit& o) | |
600 | { | |
7984e5f7 | 601 | // |
602 | // Assignment operator | |
603 | // | |
604 | // Parameters: | |
605 | // o Object to assign from | |
606 | // | |
607 | // Return: | |
608 | // Reference to this object | |
609 | // | |
d015ecfe | 610 | if (&o == this) return *this; |
0bd4b00f | 611 | fRings = o.fRings; |
612 | fLowCut = o.fLowCut; | |
613 | SetEtaAxis(o.fEtaAxis.GetNbins(), o.fEtaAxis.GetXmin(), o.fEtaAxis.GetXmax()); | |
614 | ||
615 | return *this; | |
616 | } | |
617 | //____________________________________________________________________ | |
618 | Int_t | |
619 | AliFMDCorrELossFit::FindEtaBin(Double_t eta) const | |
620 | { | |
7984e5f7 | 621 | // |
622 | // Find the eta bin corresponding to the given eta | |
623 | // | |
624 | // Parameters: | |
625 | // eta Eta value | |
626 | // | |
627 | // Return: | |
628 | // Bin (in @f$[1,N_{bins}]@f$) corresponding to the given | |
629 | // eta, or 0 if out of range. | |
630 | // | |
fb3430ac | 631 | if (TMath::Abs(fEtaAxis.GetXmin() - fEtaAxis.GetXmax()) < 1e-6 |
632 | || fEtaAxis.GetNbins() == 0) { | |
0bd4b00f | 633 | AliWarning("No eta axis defined"); |
634 | return -1; | |
635 | } | |
636 | Int_t bin = const_cast<TAxis&>(fEtaAxis).FindBin(eta); | |
637 | if (bin <= 0 || bin > fEtaAxis.GetNbins()) return 0; | |
638 | return bin; | |
639 | } | |
640 | ||
641 | //____________________________________________________________________ | |
642 | Bool_t | |
643 | AliFMDCorrELossFit::SetFit(UShort_t d, Char_t r, Int_t etaBin, ELossFit* fit) | |
644 | { | |
7984e5f7 | 645 | // |
646 | // Set the fit parameters from a function | |
647 | // | |
648 | // Parameters: | |
649 | // d Detector | |
650 | // r Ring | |
651 | // etaBin Eta (bin number, 1->nBins) | |
652 | // f ELoss fit result - note, the object will take ownership | |
653 | // | |
0bd4b00f | 654 | TObjArray* ringArray = GetOrMakeRingArray(d, r); |
655 | if (!ringArray) { | |
656 | AliError(Form("Failed to make ring array for FMD%d%c", d, r)); | |
657 | return kFALSE; | |
658 | } | |
659 | if (etaBin <= 0 || etaBin >= fEtaAxis.GetNbins()+1) { | |
660 | AliError(Form("bin=%d is out of range [%d,%d]", | |
661 | etaBin, 1, fEtaAxis.GetNbins())); | |
662 | return kFALSE; | |
663 | } | |
664 | // AliInfo(Form("Adding fit %p at %3d", fit, etaBin)); | |
665 | ringArray->AddAtAndExpand(fit, etaBin); | |
666 | return kTRUE; | |
667 | } | |
668 | ||
669 | //____________________________________________________________________ | |
670 | Bool_t | |
671 | AliFMDCorrELossFit::SetFit(UShort_t d, Char_t r, Double_t eta, ELossFit* fit) | |
672 | { | |
7984e5f7 | 673 | // |
674 | // Set the fit parameters from a function | |
675 | // | |
676 | // Parameters: | |
677 | // d Detector | |
678 | // r Ring | |
679 | // eta Eta | |
680 | // f ELoss fit result - note, the object will take ownership | |
681 | // | |
0bd4b00f | 682 | Int_t bin = FindEtaBin(eta); |
683 | if (bin <= 0) { | |
684 | AliError(Form("eta=%f is out of range [%f,%f]", | |
685 | eta, fEtaAxis.GetXmin(), fEtaAxis.GetXmax())); | |
686 | return kFALSE; | |
687 | } | |
688 | ||
689 | return SetFit(d, r, bin, fit); | |
690 | } | |
691 | //____________________________________________________________________ | |
692 | Bool_t | |
693 | AliFMDCorrELossFit::SetFit(UShort_t d, Char_t r, | |
694 | Double_t eta, | |
695 | Int_t quality,UShort_t n, | |
696 | Double_t chi2, UShort_t nu, | |
697 | Double_t c, Double_t ec, | |
698 | Double_t delta, Double_t edelta, | |
699 | Double_t xi, Double_t exi, | |
700 | Double_t sigma, Double_t esigma, | |
701 | Double_t sigman, Double_t esigman, | |
702 | Double_t* a, Double_t* ea) | |
703 | { | |
7984e5f7 | 704 | // |
705 | // Set the fit parameters from a function | |
706 | // | |
707 | // Parameters: | |
708 | // d Detector number | |
709 | // r Ring identifier | |
710 | // eta Eta value | |
711 | // quality Quality flag | |
712 | // n @f$ N@f$ - Number of fitted peaks | |
713 | // chi2 @f$ \chi^2 @f$ | |
714 | // nu @f$ \nu @f$ - number degrees of freedom | |
715 | // c @f$ C@f$ - scale constant | |
716 | // ec @f$ \delta C@f$ - error on @f$ C@f$ | |
717 | // delta @f$ \Delta@f$ - most probable value | |
718 | // edelta @f$ \delta\Delta@f$ - error on @f$\Delta@f$ | |
719 | // xi @f$ \xi@f$ - Landau width | |
720 | // exi @f$ \delta\xi@f$ - error on @f$\xi@f$ | |
721 | // sigma @f$ \sigma@f$ - Gaussian width | |
722 | // esigma @f$ \delta\sigma@f$ - error on @f$\sigma@f$ | |
723 | // sigman @f$ \sigma_n@f$ - Noise width | |
724 | // esigman @f$ \delta\sigma_n@f$ - error on @f$\sigma_n@f$ | |
725 | // a Array of @f$ N-1@f$ weights @f$ a_i@f$ for | |
726 | // @f$ i=2,\ldots@f$ | |
727 | // ea Array of @f$ N-1@f$ errors on weights @f$ a_i@f$ for | |
728 | // @f$ i=2,\ldots@f$ | |
729 | // | |
0bd4b00f | 730 | ELossFit* e = new ELossFit(quality, n, |
731 | chi2, nu, | |
732 | c, ec, | |
733 | delta, edelta, | |
734 | xi, exi, | |
735 | sigma, esigma, | |
736 | sigman, esigman, | |
737 | a, ea); | |
738 | if (!SetFit(d, r, eta, e)) { | |
739 | delete e; | |
740 | return kFALSE; | |
741 | } | |
742 | return kTRUE; | |
743 | } | |
744 | //____________________________________________________________________ | |
745 | Bool_t | |
746 | AliFMDCorrELossFit::SetFit(UShort_t d, Char_t r, Double_t eta, | |
747 | Int_t quality, const TF1& f) | |
748 | { | |
7984e5f7 | 749 | // |
750 | // Set the fit parameters from a function | |
751 | // | |
752 | // Parameters: | |
753 | // d Detector | |
754 | // r Ring | |
755 | // eta Eta | |
756 | // quality Quality flag | |
757 | // f Function from fit | |
758 | // | |
0bd4b00f | 759 | ELossFit* e = new ELossFit(quality, f); |
760 | if (!SetFit(d, r, eta, e)) { | |
761 | delete e; | |
762 | return kFALSE; | |
763 | } | |
764 | return kTRUE; | |
765 | } | |
1174780f | 766 | //____________________________________________________________________ |
767 | AliFMDCorrELossFit::ELossFit* | |
768 | AliFMDCorrELossFit::GetFit(UShort_t d, Char_t r, Int_t etabin) const | |
769 | { | |
770 | // | |
771 | // Get the fit corresponding to the specified parameters | |
772 | // | |
773 | // Parameters: | |
774 | // d Detector | |
775 | // r Ring | |
776 | // etabin Eta bin (1 based) | |
777 | // | |
778 | // Return: | |
779 | // Fit parameters or null in case of problems | |
780 | // | |
781 | TObjArray* ringArray = GetRingArray(d, r); | |
782 | if (!ringArray) return 0; | |
783 | if (etabin <= 0 || etabin >= fEtaAxis.GetNbins()) return 0; | |
784 | if (etabin > ringArray->GetEntriesFast()) return 0; | |
785 | else if (etabin >= ringArray->GetEntriesFast()) etabin--; | |
786 | else if (!ringArray->At(etabin)) etabin++; | |
787 | return static_cast<ELossFit*>(ringArray->At(etabin)); | |
788 | } | |
789 | //____________________________________________________________________ | |
790 | AliFMDCorrELossFit::ELossFit* | |
791 | AliFMDCorrELossFit::GetFit(UShort_t d, Char_t r, Double_t eta) const | |
792 | { | |
793 | // | |
794 | // Find the fit corresponding to the specified parameters | |
795 | // | |
796 | // Parameters: | |
797 | // d Detector | |
798 | // r Ring | |
799 | // eta Eta value | |
800 | // | |
801 | // Return: | |
802 | // Fit parameters or null in case of problems | |
803 | // | |
804 | Int_t etabin = FindEtaBin(eta); | |
805 | return GetFit(d, r, etabin); | |
806 | } | |
807 | ||
0bd4b00f | 808 | //____________________________________________________________________ |
809 | AliFMDCorrELossFit::ELossFit* | |
810 | AliFMDCorrELossFit::FindFit(UShort_t d, Char_t r, Int_t etabin) const | |
811 | { | |
7984e5f7 | 812 | // |
813 | // Find the fit corresponding to the specified parameters | |
814 | // | |
815 | // Parameters: | |
816 | // d Detector | |
817 | // r Ring | |
818 | // etabin Eta bin (1 based) | |
819 | // | |
820 | // Return: | |
821 | // Fit parameters or null in case of problems | |
822 | // | |
0bd4b00f | 823 | TObjArray* ringArray = GetRingArray(d, r); |
824 | if (!ringArray) { | |
825 | AliError(Form("Failed to make ring array for FMD%d%c", d, r)); | |
826 | return 0; | |
827 | } | |
828 | if (etabin <= 0 || etabin >= fEtaAxis.GetNbins()) { | |
5bb5d1f6 | 829 | // AliError(Form("Eta bin=%3d out of bounds [%d,%d] for FMD%d%c", |
830 | // etabin, 1, fEtaAxis.GetNbins(), d, r)); | |
0bd4b00f | 831 | return 0; |
832 | } | |
833 | if (etabin > ringArray->GetEntriesFast()) { | |
5bb5d1f6 | 834 | // AliError(Form("Eta bin=%3d out of bounds [%d,%d] for FMD%d%c", |
835 | // etabin, 1, ringArray->GetEntriesFast(), d, r)); | |
0bd4b00f | 836 | return 0; |
837 | } | |
838 | else if (etabin >= ringArray->GetEntriesFast()) { | |
5bb5d1f6 | 839 | // AliWarning(Form("Eta bin=%3d out of bounds by +1 [%d,%d] for FMD%d%c, " |
840 | // "trying %3d", etabin, 1, ringArray->GetEntriesFast(), d, r, | |
841 | // etabin-1)); | |
0bd4b00f | 842 | etabin--; |
843 | } | |
844 | else if (!ringArray->At(etabin)) { | |
5bb5d1f6 | 845 | // AliWarning(Form("Eta bin=%d has no fit for FMD%d%c, trying %03d", |
846 | // etabin, d, r, etabin+1)); | |
0bd4b00f | 847 | etabin++; |
848 | } | |
849 | return static_cast<ELossFit*>(ringArray->At(etabin)); | |
850 | } | |
851 | //____________________________________________________________________ | |
852 | AliFMDCorrELossFit::ELossFit* | |
853 | AliFMDCorrELossFit::FindFit(UShort_t d, Char_t r, Double_t eta) const | |
854 | { | |
7984e5f7 | 855 | // |
856 | // Find the fit corresponding to the specified parameters | |
857 | // | |
858 | // Parameters: | |
859 | // d Detector | |
860 | // r Ring | |
861 | // eta Eta value | |
862 | // | |
863 | // Return: | |
864 | // Fit parameters or null in case of problems | |
865 | // | |
0bd4b00f | 866 | Int_t etabin = FindEtaBin(eta); |
867 | return FindFit(d, r, etabin); | |
868 | } | |
869 | //____________________________________________________________________ | |
870 | TObjArray* | |
871 | AliFMDCorrELossFit::GetRingArray(UShort_t d, Char_t r) const | |
872 | { | |
7984e5f7 | 873 | // |
874 | // Get the ring array corresponding to the specified ring | |
875 | // | |
876 | // Parameters: | |
877 | // d Detector | |
878 | // r Ring | |
879 | // | |
880 | // Return: | |
881 | // Pointer to ring array, or null in case of problems | |
882 | // | |
0bd4b00f | 883 | Int_t idx = -1; |
884 | switch (d) { | |
885 | case 1: idx = 0; break; | |
886 | case 2: idx = (r == 'i' || r == 'I') ? 1 : 2; break; | |
887 | case 3: idx = (r == 'o' || r == 'I') ? 3 : 4; break; | |
888 | } | |
889 | if (idx < 0 || idx >= fRings.GetEntriesFast()) return 0; | |
890 | return static_cast<TObjArray*>(fRings.At(idx)); | |
891 | } | |
892 | //____________________________________________________________________ | |
893 | TObjArray* | |
894 | AliFMDCorrELossFit::GetOrMakeRingArray(UShort_t d, Char_t r) | |
895 | { | |
7984e5f7 | 896 | // |
897 | // Get the ring array corresponding to the specified ring | |
898 | // | |
899 | // Parameters: | |
900 | // d Detector | |
901 | // r Ring | |
902 | // | |
903 | // Return: | |
904 | // Pointer to ring array, or newly created container | |
905 | // | |
0bd4b00f | 906 | Int_t idx = -1; |
907 | switch (d) { | |
908 | case 1: idx = 0; break; | |
909 | case 2: idx = (r == 'i' || r == 'I') ? 1 : 2; break; | |
910 | case 3: idx = (r == 'o' || r == 'I') ? 3 : 4; break; | |
911 | } | |
912 | if (idx < 0) return 0; | |
913 | if (idx >= fRings.GetEntriesFast() || !fRings.At(idx)) { | |
914 | TObjArray* a = new TObjArray(0); | |
915 | // TOrdCollection* a = new TOrdCollection(fEtaAxis.GetNbins()); | |
916 | a->SetName(Form("FMD%d%c", d, r)); | |
917 | a->SetOwner(); | |
918 | fRings.AddAtAndExpand(a, idx); | |
919 | } | |
920 | return static_cast<TObjArray*>(fRings.At(idx)); | |
921 | } | |
922 | ||
16ac05a3 | 923 | //____________________________________________________________________ |
924 | Double_t | |
925 | AliFMDCorrELossFit::GetLowerBound(UShort_t d, Char_t r, Int_t etabin, | |
926 | Double_t f) const | |
927 | { | |
928 | ELossFit* fit = GetFit(d, r, etabin); | |
929 | if (!fit) return -1024; | |
930 | return fit->GetLowerBound(f); | |
931 | } | |
932 | //____________________________________________________________________ | |
933 | Double_t | |
934 | AliFMDCorrELossFit::GetLowerBound(UShort_t d, Char_t r, Double_t eta, | |
935 | Double_t f) const | |
936 | { | |
937 | Int_t bin = FindEtaBin(eta); | |
938 | if (bin <= 0) return -1024; | |
939 | return GetLowerBound(d, r, Int_t(bin), f); | |
940 | } | |
5bb5d1f6 | 941 | //____________________________________________________________________ |
942 | Double_t | |
943 | AliFMDCorrELossFit::GetLowerBound(UShort_t d, Char_t r, Int_t etabin, | |
944 | Double_t f, Bool_t showErrors, | |
945 | Bool_t includeSigma) const | |
946 | { | |
947 | ELossFit* fit = GetFit(d, r, etabin); | |
948 | if (!fit) { | |
949 | if (showErrors) { | |
950 | AliWarning(Form("No fit for FMD%d%c @ etabin=%d", d, r, etabin)); | |
951 | } | |
952 | return -1024; | |
953 | } | |
954 | return fit->GetLowerBound(f, includeSigma); | |
955 | } | |
956 | ||
957 | //____________________________________________________________________ | |
958 | Double_t | |
959 | AliFMDCorrELossFit::GetLowerBound(UShort_t d, Char_t r, Double_t eta, | |
960 | Double_t f, Bool_t showErrors, | |
961 | Bool_t includeSigma) const | |
962 | { | |
963 | Int_t bin = FindEtaBin(eta); | |
964 | if (bin <= 0) { | |
965 | if (showErrors) | |
966 | AliError(Form("eta=%f out of bounds for FMD%d%c", eta, d, r)); | |
967 | return -1024; | |
968 | } | |
969 | return GetLowerBound(d, r, bin, f, showErrors, includeSigma); | |
970 | } | |
971 | ||
972 | //____________________________________________________________________ | |
0bd4b00f | 973 | namespace { |
974 | TH1D* MakeHist(const TAxis& axis, const char* name, const char* title, | |
975 | Int_t color) | |
976 | { | |
977 | TH1D* h = new TH1D(Form("%s_%s", name, title), | |
978 | Form("%s %s", name, title), | |
979 | axis.GetNbins(), axis.GetXmin(), axis.GetXmax()); | |
980 | h->SetDirectory(0); | |
981 | h->SetMarkerStyle(20); | |
982 | h->SetMarkerColor(color); | |
983 | h->SetMarkerSize(0.5); | |
984 | h->SetFillColor(color); | |
985 | h->SetFillStyle(3001); | |
986 | h->SetLineColor(color); | |
987 | return h; | |
988 | } | |
989 | } | |
990 | ||
5bb5d1f6 | 991 | |
992 | ||
7dacdf84 | 993 | #define IDX2RING(I) (i == 0 || i == 1 || i == 3 ? 'I' : 'O') |
994 | #define IDX2DET(I) (i == 0 ? 1 : (i == 1 || i == 2 ? 2 : 3)) | |
0bd4b00f | 995 | //____________________________________________________________________ |
f7cfc454 | 996 | TList* |
997 | AliFMDCorrELossFit::GetStacks(Bool_t err, Bool_t rel, UShort_t maxN) const | |
0bd4b00f | 998 | { |
f7cfc454 | 999 | // Get a list of THStacks |
1000 | Int_t nRings = fRings.GetEntriesFast(); | |
1001 | Int_t nPad = 6+maxN-1; // 7 regular params, and maxN-1 weights | |
7dacdf84 | 1002 | |
1003 | enum { | |
1004 | kChi2nu = 0, | |
1005 | kC = 1, | |
1006 | kDelta = 2, | |
1007 | kXi = 3, | |
1008 | kSigma = 4, | |
1009 | kN = 5 | |
1010 | }; | |
0bd4b00f | 1011 | |
7dacdf84 | 1012 | THStack* sChi2nu; |
1013 | THStack* sC; | |
1014 | THStack* sDelta; | |
1015 | THStack* sXi; | |
1016 | THStack* sSigma; | |
1017 | // THStack* sigman; | |
0bd4b00f | 1018 | THStack* n; |
f7cfc454 | 1019 | TList* stacks = new TList; |
1020 | stacks->AddAt(sChi2nu= new THStack("chi2", "#chi^{2}/#nu"), kChi2nu); | |
1021 | stacks->AddAt(sC = new THStack("c", "C"), kC); | |
1022 | stacks->AddAt(sDelta = new THStack("delta", "#Delta_{mp}"), kDelta); | |
1023 | stacks->AddAt(sXi = new THStack("xi", "#xi"), kXi); | |
1024 | stacks->AddAt(sSigma = new THStack("sigma", "#sigma"), kSigma); | |
1025 | //stacks->AddAt(sigman= new THStack("sigman", "#sigma_{n}"), 5); | |
1026 | stacks->AddAt(n = new THStack("n", "N"), kN); | |
0bd4b00f | 1027 | for (Int_t i = 1; i <= maxN; i++) { |
f7cfc454 | 1028 | stacks->AddAt(new THStack(Form("a_%02d", i+1), Form("a_{%d}", i+1)), kN+i); |
0bd4b00f | 1029 | } |
f7cfc454 | 1030 | |
7dacdf84 | 1031 | TArrayD min(nPad); |
1032 | TArrayD max(nPad); | |
1033 | min.Reset(100000); | |
1034 | max.Reset(-100000); | |
1035 | ||
0bd4b00f | 1036 | for (Int_t i = 0; i < nRings; i++) { |
1037 | if (!fRings.At(i)) continue; | |
1038 | TObjArray* a = static_cast<TObjArray*>(fRings.At(i)); | |
1039 | Int_t nFits = a->GetEntriesFast(); | |
7dacdf84 | 1040 | Int_t color = AliForwardUtil::RingColor(IDX2DET(i), IDX2RING(i)); |
0bd4b00f | 1041 | |
1042 | TH1D* hChi = MakeHist(fEtaAxis,a->GetName(), "chi2", color); | |
1043 | TH1D* hC = MakeHist(fEtaAxis,a->GetName(), "c", color); | |
1044 | TH1D* hDelta = MakeHist(fEtaAxis,a->GetName(), "delta", color); | |
1045 | TH1D* hXi = MakeHist(fEtaAxis,a->GetName(), "xi", color); | |
1046 | TH1D* hSigma = MakeHist(fEtaAxis,a->GetName(), "sigma", color); | |
7dacdf84 | 1047 | // TH1D* hSigmaN = MakeHist(fEtaAxis,a->GetName(), "sigman", color); |
0bd4b00f | 1048 | TH1D* hN = MakeHist(fEtaAxis,a->GetName(), "n", color); |
1049 | TH1D* hA[maxN]; | |
1050 | const char* ho = (rel || !err ? "hist" : "e"); | |
7dacdf84 | 1051 | sChi2nu->Add(hChi, "hist"); // 0 |
1052 | sC ->Add(hC, ho); // 1 | |
1053 | sDelta ->Add(hDelta, ho); // 2 | |
1054 | sXi ->Add(hXi, ho); // 3 | |
1055 | sSigma ->Add(hSigma, ho); // 4 | |
1056 | // sigman->Add(hSigmaN,ho); // 5 | |
1057 | n ->Add(hN, "hist"); // 5 | |
0bd4b00f | 1058 | hChi->SetFillColor(color); |
1059 | hChi->SetFillStyle(3001); | |
1060 | hN->SetFillColor(color); | |
1061 | hN->SetFillStyle(3001); | |
1062 | ||
1063 | for (Int_t k = 1; k <= maxN; k++) { | |
1064 | hA[k-1] = MakeHist(fEtaAxis,a->GetName(), Form("a%02d",k+1), color); | |
f7cfc454 | 1065 | static_cast<THStack*>(stacks->At(kN+k))->Add(hA[k-1], ho); |
0bd4b00f | 1066 | } |
1067 | ||
1068 | for (Int_t j = 0; j < nFits; j++) { | |
1069 | ELossFit* f = static_cast<ELossFit*>(a->At(j)); | |
1070 | if (!f) continue; | |
1071 | ||
7dacdf84 | 1072 | Int_t b = f->fBin; |
1073 | Int_t nW = f->FindMaxWeight(); | |
1074 | Double_t vChi2nu = (f->fNu <= 0 ? 0 : f->fChi2 / f->fNu); | |
1075 | Double_t vC = (rel ? (f->fC >0 ?f->fEC /f->fC :0) | |
1076 | : f->fC); | |
1077 | Double_t vDelta = (rel ? (f->fDelta >0 ?f->fEDelta /f->fDelta :0) | |
1078 | : f->fDelta); | |
1079 | Double_t vXi = (rel ? (f->fXi >0 ?f->fEXi /f->fXi :0) | |
1080 | : f->fXi); | |
1081 | Double_t vSigma = (rel ? (f->fSigma >0 ?f->fESigma /f->fSigma :0) | |
1082 | : f->fSigma); | |
1083 | // Double_t sigman = (rel ? (f->fSigmaN>0 ?f->fESigmaN/f->fSigmaN :0) | |
1084 | // : f->SigmaN); | |
1085 | hChi ->SetBinContent(b, vChi2nu); | |
0bd4b00f | 1086 | hN ->SetBinContent(b, nW); |
7dacdf84 | 1087 | hC ->SetBinContent(b, vC); |
1088 | hDelta ->SetBinContent(b, vDelta); | |
1089 | hXi ->SetBinContent(b, vXi); | |
1090 | hSigma ->SetBinContent(b, vSigma); | |
1091 | if (vChi2nu > 1e-12) { | |
1092 | min[kChi2nu] = TMath::Min(min[kChi2nu], vChi2nu); | |
1093 | max[kChi2nu] = TMath::Max(max[kChi2nu], vChi2nu); | |
1094 | } | |
1095 | if (vC > 1e-12) { | |
1096 | min[kC] = TMath::Min(min[kC], vC); | |
1097 | max[kC] = TMath::Max(max[kC], vC); | |
1098 | } | |
1099 | if (vDelta > 1e-12) { | |
1100 | min[kDelta] = TMath::Min(min[kDelta], vDelta); | |
1101 | max[kDelta] = TMath::Max(max[kDelta], vDelta); | |
1102 | } | |
1103 | if (vXi > 1e-12) { | |
1104 | min[kXi] = TMath::Min(min[kXi], vXi); | |
1105 | max[kXi] = TMath::Max(max[kXi], vXi); | |
1106 | } | |
1107 | if (vSigma > 1e-12) { | |
1108 | min[kSigma] = TMath::Min(min[kSigma], vSigma); | |
1109 | max[kSigma] = TMath::Max(max[kSigma], vSigma); | |
0bd4b00f | 1110 | } |
7dacdf84 | 1111 | if (nW > 1e-12) { |
1112 | min[kN] = TMath::Min(min[kN], Double_t(nW)); | |
1113 | max[kN] = TMath::Max(max[kN], Double_t(nW)); | |
1114 | } | |
1115 | // hSigmaN->SetBinContent(b, sigman); | |
1116 | if (!rel) { | |
0bd4b00f | 1117 | hC ->SetBinError(b, f->fEC); |
1118 | hDelta ->SetBinError(b, f->fEDelta); | |
1119 | hXi ->SetBinError(b, f->fEXi); | |
1120 | hSigma ->SetBinError(b, f->fESigma); | |
7dacdf84 | 1121 | // hSigmaN->SetBinError(b, f->fESigmaN); |
0bd4b00f | 1122 | } |
1123 | for (Int_t k = 0; k < f->fN-1 && k < maxN; k++) { | |
7dacdf84 | 1124 | Double_t vA = (rel ? (f->fA[k] > 0 ? f->fEA[k] / f->fA[k] : 0) |
1125 | : f->fA[k]); | |
1126 | hA[k]->SetBinContent(b, vA); | |
1127 | if (!rel) hA[k]->SetBinError(b, f->fEA[k]); | |
1128 | if (vA > 1e-12) { | |
1129 | min[kN+1+k] = TMath::Min(min[kN+1+k], vA); | |
1130 | max[kN+1+k] = TMath::Max(max[kN+1+k], vA); | |
0bd4b00f | 1131 | } |
1132 | } | |
1133 | } | |
1134 | } | |
f7cfc454 | 1135 | return stacks; |
1136 | } | |
1137 | ||
1138 | //____________________________________________________________________ | |
1139 | void | |
1140 | AliFMDCorrELossFit::Draw(Option_t* option) | |
1141 | { | |
1142 | // | |
1143 | // Draw this object | |
1144 | // | |
1145 | // Parameters: | |
1146 | // option Options. Possible values are | |
1147 | // - err Plot error bars | |
1148 | // | |
1149 | TString opt(Form("nostack %s", option)); | |
1150 | opt.ToLower(); | |
1151 | Bool_t rel = (opt.Contains("relative")); | |
1152 | Bool_t err = (opt.Contains("error")); | |
1153 | if (rel) opt.ReplaceAll("relative",""); | |
1154 | if (err) opt.ReplaceAll("error",""); | |
1155 | ||
1156 | UShort_t maxN = 0; | |
1157 | Int_t nRings = fRings.GetEntriesFast(); | |
1158 | for (Int_t i = 0; i < nRings; i++) { | |
1159 | if (!fRings.At(i)) continue; | |
1160 | TObjArray* a = static_cast<TObjArray*>(fRings.At(i)); | |
1161 | Int_t nFits = a->GetEntriesFast(); | |
1162 | ||
1163 | for (Int_t j = 0; j < nFits; j++) { | |
1164 | ELossFit* fit = static_cast<ELossFit*>(a->At(j)); | |
1165 | if (!fit) continue; | |
1166 | maxN = TMath::Max(maxN, UShort_t(fit->fN)); | |
1167 | } | |
1168 | } | |
1169 | // AliInfo(Form("Maximum N is %d", maxN)); | |
1170 | Int_t nPad = 6+maxN-1; // 7 regular params, and maxN-1 weights | |
1171 | TVirtualPad* pad = gPad; | |
1172 | pad->Divide(2, (nPad+1)/2, 0.1, 0, 0); | |
1173 | ||
1174 | TList* stacks = GetStacks(err, rel, maxN); | |
1175 | ||
0bd4b00f | 1176 | Int_t nPad2 = (nPad+1) / 2; |
1177 | for (Int_t i = 0; i < nPad; i++) { | |
1178 | Int_t iPad = 1 + i/nPad2 + 2 * (i % nPad2); | |
1179 | TVirtualPad* p = pad->cd(iPad); | |
1180 | p->SetLeftMargin(.15); | |
1181 | p->SetFillColor(0); | |
1182 | p->SetFillStyle(0); | |
1183 | p->SetGridx(); | |
1184 | p->SetGridy(); | |
1185 | if (rel && i != 0 && i != 6 && i != 5 && i != 4) p->SetLogy(); | |
1186 | ||
7dacdf84 | 1187 | |
f7cfc454 | 1188 | THStack* stack = static_cast<THStack*>(stacks->At(i)); |
1189 | ||
1190 | // Double_t powMax = TMath::Log10(max[i]); | |
1191 | // Double_t powMin = min[i] <= 0 ? powMax : TMath::Log10(min[i]); | |
1192 | // if (powMax-powMin > 2. && min[i] != 0) p->SetLogy(); | |
1193 | ||
7dacdf84 | 1194 | // stack->SetMinimum(min[i]); |
1195 | // stack->SetMaximum(max[i]); | |
0bd4b00f | 1196 | stack->Draw(opt.Data()); |
1197 | ||
1198 | TString tit(stack->GetTitle()); | |
1199 | if (rel && i != 0 && i != 6) | |
1200 | tit = Form("#delta %s/%s", tit.Data(), tit.Data()); | |
1201 | TH1* hist = stack->GetHistogram(); | |
1202 | TAxis* yaxis = hist->GetYaxis(); | |
1203 | yaxis->SetTitle(tit.Data()); | |
1204 | yaxis->SetTitleSize(0.15); | |
1205 | yaxis->SetLabelSize(0.08); | |
1206 | yaxis->SetTitleOffset(0.35); | |
7dacdf84 | 1207 | yaxis->SetTitleFont(132); |
1208 | yaxis->SetLabelFont(132); | |
0bd4b00f | 1209 | yaxis->SetNdivisions(5); |
1210 | ||
7dacdf84 | 1211 | |
0bd4b00f | 1212 | TAxis* xaxis = stack->GetHistogram()->GetXaxis(); |
1213 | xaxis->SetTitle("#eta"); | |
1214 | xaxis->SetTitleSize(0.15); | |
1215 | xaxis->SetLabelSize(0.08); | |
1216 | xaxis->SetTitleOffset(0.35); | |
7dacdf84 | 1217 | xaxis->SetTitleFont(132); |
1218 | xaxis->SetLabelFont(132); | |
0bd4b00f | 1219 | xaxis->SetNdivisions(10); |
1220 | ||
7dacdf84 | 1221 | stack->Draw(opt.Data()); |
0bd4b00f | 1222 | } |
1223 | pad->cd(); | |
1224 | } | |
1225 | ||
1226 | //____________________________________________________________________ | |
1227 | void | |
1228 | AliFMDCorrELossFit::Print(Option_t* option) const | |
1229 | { | |
fb3430ac | 1230 | // |
1231 | // Print this object. | |
1232 | // | |
1233 | // Parameters: | |
1234 | // option Options | |
1235 | // - R Print recursive | |
1236 | // | |
1237 | // | |
0bd4b00f | 1238 | TString opt(option); |
1239 | opt.ToUpper(); | |
1240 | Int_t nRings = fRings.GetEntriesFast(); | |
1241 | bool recurse = opt.Contains("R"); | |
1242 | ||
1243 | std::cout << "Low cut in fit range: " << fLowCut << "\n" | |
1244 | << "Eta axis: " << fEtaAxis.GetNbins() | |
1245 | << " bins, range [" << fEtaAxis.GetXmin() << "," | |
1246 | << fEtaAxis.GetXmax() << "]" << std::endl; | |
1247 | ||
1248 | for (Int_t i = 0; i < nRings; i++) { | |
1249 | if (!fRings.At(i)) continue; | |
1250 | TObjArray* a = static_cast<TObjArray*>(fRings.At(i)); | |
1251 | Int_t nFits = a->GetEntriesFast(); | |
1252 | ||
1253 | std::cout << a->GetName() << " [" << nFits << " entries]" | |
1254 | << (recurse ? ":\n" : "\t"); | |
1255 | Int_t min = fEtaAxis.GetNbins()+1; | |
1256 | Int_t max = 0; | |
1257 | for (Int_t j = 0; j < nFits; j++) { | |
1258 | if (!a->At(j)) continue; | |
1259 | ||
1260 | min = TMath::Min(j, min); | |
1261 | max = TMath::Max(j, max); | |
1262 | ||
1263 | if (recurse) { | |
1264 | std::cout << "Bin # " << j << "\t"; | |
1265 | ELossFit* fit = static_cast<ELossFit*>(a->At(j)); | |
1266 | fit->Print(option); | |
1267 | } | |
1268 | } | |
1269 | if (!recurse) | |
1270 | std::cout << " bin range: " << std::setw(3) << min | |
1271 | << "-" << std::setw(3) << max << " " << std::setw(3) | |
1272 | << (max-min+1) << " bins" << std::endl; | |
1273 | } | |
1274 | } | |
1275 | ||
1276 | //____________________________________________________________________ | |
1277 | void | |
1278 | AliFMDCorrELossFit::Browse(TBrowser* b) | |
1279 | { | |
7984e5f7 | 1280 | // |
1281 | // Browse this object | |
1282 | // | |
1283 | // Parameters: | |
1284 | // b | |
1285 | // | |
0bd4b00f | 1286 | b->Add(&fRings); |
1287 | b->Add(&fEtaAxis); | |
1288 | } | |
1289 | ||
1290 | ||
1291 | ||
1292 | //____________________________________________________________________ | |
1293 | // | |
1294 | // EOF | |
1295 | // |