]>
Commit | Line | Data |
---|---|---|
7984e5f7 | 1 | // |
2 | // Utilities used in the forward multiplcity analysis | |
3 | // | |
4 | // | |
7e4038b5 | 5 | #include "AliForwardUtil.h" |
9d99b0dd | 6 | #include <AliAnalysisManager.h> |
7 | #include "AliAODForwardMult.h" | |
8 | #include <AliLog.h> | |
9 | #include <AliInputEventHandler.h> | |
10 | #include <AliESDEvent.h> | |
11 | #include <AliPhysicsSelection.h> | |
12 | #include <AliTriggerAnalysis.h> | |
13 | #include <AliMultiplicity.h> | |
7e4038b5 | 14 | #include <TH2D.h> |
9d99b0dd | 15 | #include <TH1I.h> |
7f759bb7 | 16 | #include <TF1.h> |
17 | #include <TFitResult.h> | |
7e4038b5 | 18 | #include <TMath.h> |
7f759bb7 | 19 | #include <TError.h> |
20 | ||
0bd4b00f | 21 | //==================================================================== |
22 | UShort_t | |
23 | AliForwardUtil::ParseCollisionSystem(const char* sys) | |
24 | { | |
7984e5f7 | 25 | // |
26 | // Parse a collision system spec given in a string. Known values are | |
27 | // | |
28 | // - "pp", "p-p" which returns kPP | |
29 | // - "PbPb", "Pb-Pb", "A-A", which returns kPbPb | |
30 | // - Everything else gives kUnknown | |
31 | // | |
32 | // Parameters: | |
33 | // sys Collision system spec | |
34 | // | |
35 | // Return: | |
36 | // Collision system id | |
37 | // | |
0bd4b00f | 38 | TString s(sys); |
39 | s.ToLower(); | |
40 | if (s.Contains("p-p") || s.Contains("pp")) return AliForwardUtil::kPP; | |
41 | if (s.Contains("pb-pb") || s.Contains("pbpb")) return AliForwardUtil::kPbPb; | |
42 | if (s.Contains("a-a") || s.Contains("aa")) return AliForwardUtil::kPbPb; | |
43 | return AliForwardUtil::kUnknown; | |
44 | } | |
45 | //____________________________________________________________________ | |
46 | const char* | |
47 | AliForwardUtil::CollisionSystemString(UShort_t sys) | |
48 | { | |
7984e5f7 | 49 | // |
50 | // Get a string representation of the collision system | |
51 | // | |
52 | // Parameters: | |
53 | // sys Collision system | |
54 | // - kPP -> "pp" | |
55 | // - kPbPb -> "PbPb" | |
56 | // - anything else gives "unknown" | |
57 | // | |
58 | // Return: | |
59 | // String representation of the collision system | |
60 | // | |
0bd4b00f | 61 | switch (sys) { |
62 | case AliForwardUtil::kPP: return "pp"; | |
63 | case AliForwardUtil::kPbPb: return "PbPb"; | |
64 | } | |
65 | return "unknown"; | |
66 | } | |
67 | //____________________________________________________________________ | |
68 | UShort_t | |
cc83fca2 | 69 | AliForwardUtil::ParseCenterOfMassEnergy(UShort_t /* sys */, Float_t v) |
0bd4b00f | 70 | { |
7984e5f7 | 71 | // |
72 | // Parse the center of mass energy given as a float and return known | |
73 | // values as a unsigned integer | |
74 | // | |
75 | // Parameters: | |
76 | // sys Collision system (needed for AA) | |
77 | // cms Center of mass energy * total charge | |
78 | // | |
79 | // Return: | |
80 | // Center of mass energy per nucleon | |
81 | // | |
0bd4b00f | 82 | Float_t energy = v; |
cc83fca2 | 83 | // Below no longer needed apparently |
84 | // if (sys == AliForwardUtil::kPbPb) energy = energy / 208 * 82; | |
0bd4b00f | 85 | if (TMath::Abs(energy - 900.) < 10) return 900; |
86 | if (TMath::Abs(energy - 2400.) < 10) return 2400; | |
87 | if (TMath::Abs(energy - 2750.) < 10) return 2750; | |
88 | if (TMath::Abs(energy - 5500.) < 40) return 5500; | |
89 | if (TMath::Abs(energy - 7000.) < 10) return 7000; | |
90 | if (TMath::Abs(energy - 10000.) < 10) return 10000; | |
91 | if (TMath::Abs(energy - 14000.) < 10) return 14000; | |
92 | return 0; | |
93 | } | |
94 | //____________________________________________________________________ | |
95 | const char* | |
96 | AliForwardUtil::CenterOfMassEnergyString(UShort_t cms) | |
97 | { | |
7984e5f7 | 98 | // |
99 | // Get a string representation of the center of mass energy per nuclean | |
100 | // | |
101 | // Parameters: | |
102 | // cms Center of mass energy per nucleon | |
103 | // | |
104 | // Return: | |
105 | // String representation of the center of mass energy per nuclean | |
106 | // | |
0bd4b00f | 107 | return Form("%04dGeV", cms); |
108 | } | |
109 | //____________________________________________________________________ | |
110 | Short_t | |
111 | AliForwardUtil::ParseMagneticField(Float_t v) | |
112 | { | |
7984e5f7 | 113 | // |
114 | // Parse the magnetic field (in kG) as given by a floating point number | |
115 | // | |
116 | // Parameters: | |
117 | // field Magnetic field in kG | |
118 | // | |
119 | // Return: | |
120 | // Short integer value of magnetic field in kG | |
121 | // | |
0bd4b00f | 122 | if (TMath::Abs(v - 5.) < 1 ) return +5; |
123 | if (TMath::Abs(v + 5.) < 1 ) return -5; | |
124 | if (TMath::Abs(v) < 1) return 0; | |
125 | return 999; | |
126 | } | |
127 | //____________________________________________________________________ | |
128 | const char* | |
129 | AliForwardUtil::MagneticFieldString(Short_t f) | |
130 | { | |
7984e5f7 | 131 | // |
132 | // Get a string representation of the magnetic field | |
133 | // | |
134 | // Parameters: | |
135 | // field Magnetic field in kG | |
136 | // | |
137 | // Return: | |
138 | // String representation of the magnetic field | |
139 | // | |
0bd4b00f | 140 | return Form("%01dkG", f); |
141 | } | |
142 | ||
143 | ||
7f759bb7 | 144 | //==================================================================== |
145 | Int_t AliForwardUtil::fgConvolutionSteps = 100; | |
146 | Double_t AliForwardUtil::fgConvolutionNSigma = 5; | |
147 | namespace { | |
7984e5f7 | 148 | // |
149 | // The shift of the most probable value for the ROOT function TMath::Landau | |
150 | // | |
7f759bb7 | 151 | const Double_t mpshift = -0.22278298; |
7984e5f7 | 152 | // |
153 | // Integration normalisation | |
154 | // | |
7f759bb7 | 155 | const Double_t invSq2pi = 1. / TMath::Sqrt(2*TMath::Pi()); |
156 | ||
7984e5f7 | 157 | // |
158 | // Utility function to use in TF1 defintition | |
159 | // | |
7f759bb7 | 160 | Double_t landauGaus1(Double_t* xp, Double_t* pp) |
161 | { | |
162 | Double_t x = xp[0]; | |
c389303e | 163 | Double_t constant = pp[AliForwardUtil::ELossFitter::kC]; |
164 | Double_t delta = pp[AliForwardUtil::ELossFitter::kDelta]; | |
165 | Double_t xi = pp[AliForwardUtil::ELossFitter::kXi]; | |
166 | Double_t sigma = pp[AliForwardUtil::ELossFitter::kSigma]; | |
1174780f | 167 | Double_t sigmaN = pp[AliForwardUtil::ELossFitter::kSigmaN]; |
7f759bb7 | 168 | |
1174780f | 169 | return constant * AliForwardUtil::LandauGaus(x, delta, xi, sigma, sigmaN); |
7f759bb7 | 170 | } |
171 | ||
7984e5f7 | 172 | // |
173 | // Utility function to use in TF1 defintition | |
174 | // | |
7f759bb7 | 175 | Double_t landauGausN(Double_t* xp, Double_t* pp) |
176 | { | |
177 | Double_t x = xp[0]; | |
c389303e | 178 | Double_t constant = pp[AliForwardUtil::ELossFitter::kC]; |
179 | Double_t delta = pp[AliForwardUtil::ELossFitter::kDelta]; | |
180 | Double_t xi = pp[AliForwardUtil::ELossFitter::kXi]; | |
181 | Double_t sigma = pp[AliForwardUtil::ELossFitter::kSigma]; | |
1174780f | 182 | Double_t sigmaN = pp[AliForwardUtil::ELossFitter::kSigmaN]; |
c389303e | 183 | Int_t n = Int_t(pp[AliForwardUtil::ELossFitter::kN]); |
184 | Double_t* a = &(pp[AliForwardUtil::ELossFitter::kA]); | |
7f759bb7 | 185 | |
1174780f | 186 | return constant * AliForwardUtil::NLandauGaus(x, delta, xi, sigma, sigmaN, |
7f759bb7 | 187 | n, a); |
188 | } | |
7984e5f7 | 189 | // |
190 | // Utility function to use in TF1 defintition | |
191 | // | |
0bd4b00f | 192 | Double_t landauGausI(Double_t* xp, Double_t* pp) |
193 | { | |
194 | Double_t x = xp[0]; | |
195 | Double_t constant = pp[AliForwardUtil::ELossFitter::kC]; | |
196 | Double_t delta = pp[AliForwardUtil::ELossFitter::kDelta]; | |
197 | Double_t xi = pp[AliForwardUtil::ELossFitter::kXi]; | |
198 | Double_t sigma = pp[AliForwardUtil::ELossFitter::kSigma]; | |
1174780f | 199 | Double_t sigmaN = pp[AliForwardUtil::ELossFitter::kSigmaN]; |
0bd4b00f | 200 | Int_t i = Int_t(pp[AliForwardUtil::ELossFitter::kN]); |
201 | ||
1174780f | 202 | return constant * AliForwardUtil::ILandauGaus(x,delta,xi,sigma,sigmaN,i); |
0bd4b00f | 203 | } |
7f759bb7 | 204 | |
205 | ||
206 | } | |
207 | //____________________________________________________________________ | |
208 | Double_t | |
209 | AliForwardUtil::Landau(Double_t x, Double_t delta, Double_t xi) | |
210 | { | |
7984e5f7 | 211 | // |
212 | // Calculate the shifted Landau | |
213 | // @f[ | |
214 | // f'_{L}(x;\Delta,\xi) = f_L(x;\Delta+0.22278298\xi) | |
215 | // @f] | |
216 | // | |
217 | // where @f$ f_{L}@f$ is the ROOT implementation of the Landau | |
218 | // distribution (known to have @f$ \Delta_{p}=-0.22278298@f$ for | |
219 | // @f$\Delta=0,\xi=1@f$. | |
220 | // | |
221 | // Parameters: | |
222 | // x Where to evaluate @f$ f'_{L}@f$ | |
223 | // delta Most probable value | |
224 | // xi The 'width' of the distribution | |
225 | // | |
226 | // Return: | |
227 | // @f$ f'_{L}(x;\Delta,\xi) @f$ | |
228 | // | |
7f759bb7 | 229 | return TMath::Landau(x, delta - xi * mpshift, xi); |
230 | } | |
231 | //____________________________________________________________________ | |
232 | Double_t | |
233 | AliForwardUtil::LandauGaus(Double_t x, Double_t delta, Double_t xi, | |
1174780f | 234 | Double_t sigma, Double_t sigmaN) |
7f759bb7 | 235 | { |
7984e5f7 | 236 | // |
237 | // Calculate the value of a Landau convolved with a Gaussian | |
238 | // | |
239 | // @f[ | |
240 | // f(x;\Delta,\xi,\sigma') = \frac{1}{\sigma' \sqrt{2 \pi}} | |
241 | // \int_{-\infty}^{+\infty} d\Delta' f'_{L}(x;\Delta',\xi) | |
242 | // \exp{-\frac{(\Delta-\Delta')^2}{2\sigma'^2}} | |
243 | // @f] | |
244 | // | |
245 | // where @f$ f'_{L}@f$ is the Landau distribution, @f$ \Delta@f$ the | |
246 | // energy loss, @f$ \xi@f$ the width of the Landau, and | |
247 | // @f$ \sigma'^2=\sigma^2-\sigma_n^2 @f$. Here, @f$\sigma@f$ is the | |
248 | // variance of the Gaussian, and @f$\sigma_n@f$ is a parameter modelling | |
249 | // noise in the detector. | |
250 | // | |
251 | // Note that this function uses the constants fgConvolutionSteps and | |
252 | // fgConvolutionNSigma | |
253 | // | |
254 | // References: | |
255 | // - <a href="http://dx.doi.org/10.1016/0168-583X(84)90472-5">Nucl.Instrum.Meth.B1:16</a> | |
256 | // - <a href="http://dx.doi.org/10.1103/PhysRevA.28.615">Phys.Rev.A28:615</a> | |
257 | // - <a href="http://root.cern.ch/root/htmldoc/tutorials/fit/langaus.C.html">ROOT implementation</a> | |
258 | // | |
259 | // Parameters: | |
260 | // x where to evaluate @f$ f@f$ | |
261 | // delta @f$ \Delta@f$ of @f$ f(x;\Delta,\xi,\sigma')@f$ | |
262 | // xi @f$ \xi@f$ of @f$ f(x;\Delta,\xi,\sigma')@f$ | |
263 | // sigma @f$ \sigma@f$ of @f$\sigma'^2=\sigma^2-\sigma_n^2 @f$ | |
264 | // sigma_n @f$ \sigma_n@f$ of @f$\sigma'^2=\sigma^2-\sigma_n^2 @f$ | |
265 | // | |
266 | // Return: | |
267 | // @f$ f@f$ evaluated at @f$ x@f$. | |
268 | // | |
7f759bb7 | 269 | Double_t deltap = delta - xi * mpshift; |
1174780f | 270 | Double_t sigma2 = sigmaN*sigmaN + sigma*sigma; |
271 | Double_t sigma1 = sigmaN == 0 ? sigma : TMath::Sqrt(sigma2); | |
7f759bb7 | 272 | Double_t xlow = x - fgConvolutionNSigma * sigma1; |
c389303e | 273 | Double_t xhigh = x + fgConvolutionNSigma * sigma1; |
7f759bb7 | 274 | Double_t step = (xhigh - xlow) / fgConvolutionSteps; |
275 | Double_t sum = 0; | |
276 | ||
277 | for (Int_t i = 0; i <= fgConvolutionSteps/2; i++) { | |
c389303e | 278 | Double_t x1 = xlow + (i - .5) * step; |
279 | Double_t x2 = xhigh - (i - .5) * step; | |
7f759bb7 | 280 | |
281 | sum += TMath::Landau(x1, deltap, xi, kTRUE) * TMath::Gaus(x, x1, sigma1); | |
282 | sum += TMath::Landau(x2, deltap, xi, kTRUE) * TMath::Gaus(x, x2, sigma1); | |
283 | } | |
284 | return step * sum * invSq2pi / sigma1; | |
285 | } | |
286 | ||
0bd4b00f | 287 | //____________________________________________________________________ |
288 | Double_t | |
289 | AliForwardUtil::ILandauGaus(Double_t x, Double_t delta, Double_t xi, | |
1174780f | 290 | Double_t sigma, Double_t sigmaN, Int_t i) |
0bd4b00f | 291 | { |
7984e5f7 | 292 | // |
293 | // Evaluate | |
294 | // @f[ | |
295 | // f_i(x;\Delta,\xi,\sigma') = f(x;\Delta_i,\xi_i,\sigma_i') | |
296 | // @f] | |
297 | // corresponding to @f$ i@f$ particles i.e., with the substitutions | |
298 | // @f{eqnarray*}{ | |
299 | // \Delta \rightarrow \Delta_i &=& i(\Delta + \xi\log(i)) | |
300 | // \xi \rightarrow \xi_i &=& i \xi | |
301 | // \sigma \rightarrow \sigma_i &=& \sqrt{i}\sigma | |
302 | // \sigma'^2 \rightarrow \sigma_i'^2 &=& \sigma_n^2 + \sigma_i^2 | |
303 | // @f} | |
304 | // | |
305 | // Parameters: | |
306 | // x Where to evaluate | |
307 | // delta @f$ \Delta@f$ | |
308 | // xi @f$ \xi@f$ | |
309 | // sigma @f$ \sigma@f$ | |
310 | // sigma_n @f$ \sigma_n@f$ | |
311 | // i @f$ i @f$ | |
312 | // | |
313 | // Return: | |
314 | // @f$ f_i @f$ evaluated | |
315 | // | |
1174780f | 316 | Double_t deltaI = (i == 1 ? delta : i * (delta + xi * TMath::Log(i))); |
317 | Double_t xiI = i * xi; | |
318 | Double_t sigmaI = (i == 1 ? sigma : TMath::Sqrt(Double_t(i))*sigma); | |
319 | if (sigmaI < 1e-10) { | |
0bd4b00f | 320 | // Fall back to landau |
1174780f | 321 | return AliForwardUtil::Landau(x, deltaI, xiI); |
0bd4b00f | 322 | } |
1174780f | 323 | return AliForwardUtil::LandauGaus(x, deltaI, xiI, sigmaI, sigmaN); |
0bd4b00f | 324 | } |
325 | ||
326 | //____________________________________________________________________ | |
327 | Double_t | |
328 | AliForwardUtil::IdLandauGausdPar(Double_t x, | |
329 | UShort_t par, Double_t dPar, | |
330 | Double_t delta, Double_t xi, | |
1174780f | 331 | Double_t sigma, Double_t sigmaN, |
0bd4b00f | 332 | Int_t i) |
333 | { | |
7984e5f7 | 334 | // |
335 | // Numerically evaluate | |
336 | // @f[ | |
337 | // \left.\frac{\partial f_i}{\partial p_i}\right|_{x} | |
338 | // @f] | |
339 | // where @f$ p_i@f$ is the @f$ i^{\mbox{th}}@f$ parameter. The mapping | |
340 | // of the parameters is given by | |
341 | // | |
342 | // - 0: @f$\Delta@f$ | |
343 | // - 1: @f$\xi@f$ | |
344 | // - 2: @f$\sigma@f$ | |
345 | // - 3: @f$\sigma_n@f$ | |
346 | // | |
347 | // This is the partial derivative with respect to the parameter of | |
348 | // the response function corresponding to @f$ i@f$ particles i.e., | |
349 | // with the substitutions | |
350 | // @f[ | |
351 | // \Delta \rightarrow \Delta_i = i(\Delta + \xi\log(i)) | |
352 | // \xi \rightarrow \xi_i = i \xi | |
353 | // \sigma \rightarrow \sigma_i = \sqrt{i}\sigma | |
354 | // \sigma'^2 \rightarrow \sigma_i'^2 = \sigma_n^2 + \sigma_i^2 | |
355 | // @f] | |
356 | // | |
357 | // Parameters: | |
358 | // x Where to evaluate | |
359 | // ipar Parameter number | |
360 | // dp @f$ \epsilon\delta p_i@f$ for some value of @f$\epsilon@f$ | |
361 | // delta @f$ \Delta@f$ | |
362 | // xi @f$ \xi@f$ | |
363 | // sigma @f$ \sigma@f$ | |
364 | // sigma_n @f$ \sigma_n@f$ | |
365 | // i @f$ i@f$ | |
366 | // | |
367 | // Return: | |
368 | // @f$ f_i@f$ evaluated | |
369 | // | |
0bd4b00f | 370 | if (dPar == 0) return 0; |
371 | Double_t dp = dPar; | |
372 | Double_t d2 = dPar / 2; | |
1174780f | 373 | Double_t deltaI = i * (delta + xi * TMath::Log(i)); |
374 | Double_t xiI = i * xi; | |
0bd4b00f | 375 | Double_t si = TMath::Sqrt(Double_t(i)); |
1174780f | 376 | Double_t sigmaI = si*sigma; |
0bd4b00f | 377 | Double_t y1 = 0; |
378 | Double_t y2 = 0; | |
379 | Double_t y3 = 0; | |
380 | Double_t y4 = 0; | |
381 | switch (par) { | |
382 | case 0: | |
1174780f | 383 | y1 = ILandauGaus(x, deltaI+i*dp, xiI, sigmaI, sigmaN, i); |
384 | y2 = ILandauGaus(x, deltaI+i*d2, xiI, sigmaI, sigmaN, i); | |
385 | y3 = ILandauGaus(x, deltaI-i*d2, xiI, sigmaI, sigmaN, i); | |
386 | y4 = ILandauGaus(x, deltaI-i*dp, xiI, sigmaI, sigmaN, i); | |
0bd4b00f | 387 | break; |
388 | case 1: | |
1174780f | 389 | y1 = ILandauGaus(x, deltaI, xiI+i*dp, sigmaI, sigmaN, i); |
390 | y2 = ILandauGaus(x, deltaI, xiI+i*d2, sigmaI, sigmaN, i); | |
391 | y3 = ILandauGaus(x, deltaI, xiI-i*d2, sigmaI, sigmaN, i); | |
392 | y4 = ILandauGaus(x, deltaI, xiI-i*dp, sigmaI, sigmaN, i); | |
0bd4b00f | 393 | break; |
394 | case 2: | |
1174780f | 395 | y1 = ILandauGaus(x, deltaI, xiI, sigmaI+si*dp, sigmaN, i); |
396 | y2 = ILandauGaus(x, deltaI, xiI, sigmaI+si*d2, sigmaN, i); | |
397 | y3 = ILandauGaus(x, deltaI, xiI, sigmaI-si*d2, sigmaN, i); | |
398 | y4 = ILandauGaus(x, deltaI, xiI, sigmaI-si*dp, sigmaN, i); | |
0bd4b00f | 399 | break; |
400 | case 3: | |
1174780f | 401 | y1 = ILandauGaus(x, deltaI, xiI, sigmaI, sigmaN+dp, i); |
402 | y2 = ILandauGaus(x, deltaI, xiI, sigmaI, sigmaN+d2, i); | |
403 | y3 = ILandauGaus(x, deltaI, xiI, sigmaI, sigmaN-d2, i); | |
404 | y4 = ILandauGaus(x, deltaI, xiI, sigmaI, sigmaN-dp, i); | |
0bd4b00f | 405 | break; |
406 | default: | |
407 | return 0; | |
408 | } | |
409 | ||
410 | Double_t d0 = y1 - y4; | |
411 | Double_t d1 = 2 * (y2 - y3); | |
412 | ||
413 | Double_t g = 1/(2*dp) * (4*d1 - d0) / 3; | |
414 | ||
415 | return g; | |
416 | } | |
417 | ||
7f759bb7 | 418 | //____________________________________________________________________ |
419 | Double_t | |
420 | AliForwardUtil::NLandauGaus(Double_t x, Double_t delta, Double_t xi, | |
1174780f | 421 | Double_t sigma, Double_t sigmaN, Int_t n, |
7f759bb7 | 422 | Double_t* a) |
423 | { | |
7984e5f7 | 424 | // |
425 | // Evaluate | |
426 | // @f[ | |
427 | // f_N(x;\Delta,\xi,\sigma') = \sum_{i=1}^N a_i f_i(x;\Delta,\xi,\sigma'a) | |
428 | // @f] | |
429 | // | |
430 | // where @f$ f(x;\Delta,\xi,\sigma')@f$ is the convolution of a | |
431 | // Landau with a Gaussian (see LandauGaus). Note that | |
432 | // @f$ a_1 = 1@f$, @f$\Delta_i = i(\Delta_1 + \xi\log(i))@f$, | |
433 | // @f$\xi_i=i\xi_1@f$, and @f$\sigma_i'^2 = \sigma_n^2 + i\sigma_1^2@f$. | |
434 | // | |
435 | // References: | |
436 | // - <a href="http://dx.doi.org/10.1016/0168-583X(84)90472-5">Nucl.Instrum.Meth.B1:16</a> | |
437 | // - <a href="http://dx.doi.org/10.1103/PhysRevA.28.615">Phys.Rev.A28:615</a> | |
438 | // - <a href="http://root.cern.ch/root/htmldoc/tutorials/fit/langaus.C.html">ROOT implementation</a> | |
439 | // | |
440 | // Parameters: | |
441 | // x Where to evaluate @f$ f_N@f$ | |
442 | // delta @f$ \Delta_1@f$ | |
443 | // xi @f$ \xi_1@f$ | |
444 | // sigma @f$ \sigma_1@f$ | |
445 | // sigma_n @f$ \sigma_n@f$ | |
446 | // n @f$ N@f$ in the sum above. | |
447 | // a Array of size @f$ N-1@f$ of the weights @f$ a_i@f$ for | |
448 | // @f$ i > 1@f$ | |
449 | // | |
450 | // Return: | |
451 | // @f$ f_N(x;\Delta,\xi,\sigma')@f$ | |
452 | // | |
1174780f | 453 | Double_t result = ILandauGaus(x, delta, xi, sigma, sigmaN, 1); |
0bd4b00f | 454 | for (Int_t i = 2; i <= n; i++) |
1174780f | 455 | result += a[i-2] * AliForwardUtil::ILandauGaus(x,delta,xi,sigma,sigmaN,i); |
7f759bb7 | 456 | return result; |
457 | } | |
0bd4b00f | 458 | namespace { |
459 | const Int_t kColors[] = { kRed+1, | |
460 | kPink+3, | |
461 | kMagenta+2, | |
462 | kViolet+2, | |
463 | kBlue+1, | |
464 | kAzure+3, | |
465 | kCyan+1, | |
466 | kTeal+2, | |
467 | kGreen+2, | |
468 | kSpring+3, | |
469 | kYellow+2, | |
470 | kOrange+2 }; | |
471 | } | |
472 | ||
473 | //____________________________________________________________________ | |
474 | TF1* | |
475 | AliForwardUtil::MakeNLandauGaus(Double_t c, | |
476 | Double_t delta, Double_t xi, | |
1174780f | 477 | Double_t sigma, Double_t sigmaN, Int_t n, |
0bd4b00f | 478 | Double_t* a, |
479 | Double_t xmin, Double_t xmax) | |
480 | { | |
7984e5f7 | 481 | // |
482 | // Generate a TF1 object of @f$ f_N@f$ | |
483 | // | |
484 | // Parameters: | |
485 | // c Constant | |
486 | // delta @f$ \Delta@f$ | |
487 | // xi @f$ \xi_1@f$ | |
488 | // sigma @f$ \sigma_1@f$ | |
489 | // sigma_n @f$ \sigma_n@f$ | |
490 | // n @f$ N@f$ - how many particles to sum to | |
491 | // a Array of size @f$ N-1@f$ of the weights @f$ a_i@f$ for | |
492 | // @f$ i > 1@f$ | |
493 | // xmin Least value of range | |
494 | // xmax Largest value of range | |
495 | // | |
496 | // Return: | |
497 | // Newly allocated TF1 object | |
498 | // | |
0bd4b00f | 499 | Int_t npar = AliForwardUtil::ELossFitter::kN+n; |
500 | TF1* landaun = new TF1(Form("nlandau%d", n), &landauGausN,xmin,xmax,npar); | |
501 | // landaun->SetLineStyle(((n-2) % 10)+2); // start at dashed | |
502 | landaun->SetLineColor(kColors[((n-1) % 12)]); // start at red | |
503 | landaun->SetLineWidth(2); | |
504 | landaun->SetNpx(500); | |
505 | landaun->SetParNames("C","#Delta_{p}","#xi", "#sigma", "#sigma_{n}", "N"); | |
506 | ||
507 | // Set the initial parameters from the seed fit | |
508 | landaun->SetParameter(AliForwardUtil::ELossFitter::kC, c); | |
509 | landaun->SetParameter(AliForwardUtil::ELossFitter::kDelta, delta); | |
510 | landaun->SetParameter(AliForwardUtil::ELossFitter::kXi, xi); | |
511 | landaun->SetParameter(AliForwardUtil::ELossFitter::kSigma, sigma); | |
1174780f | 512 | landaun->SetParameter(AliForwardUtil::ELossFitter::kSigmaN, sigmaN); |
0bd4b00f | 513 | landaun->FixParameter(AliForwardUtil::ELossFitter::kN, n); |
514 | ||
515 | // Set the range and name of the scale parameters | |
516 | for (UShort_t i = 2; i <= n; i++) {// Take parameters from last fit | |
517 | landaun->SetParameter(AliForwardUtil::ELossFitter::kA+i-2, a[i-2]); | |
518 | landaun->SetParName(AliForwardUtil::ELossFitter::kA+i-2, Form("a_{%d}", i)); | |
519 | } | |
520 | return landaun; | |
521 | } | |
522 | //____________________________________________________________________ | |
523 | TF1* | |
524 | AliForwardUtil::MakeILandauGaus(Double_t c, | |
525 | Double_t delta, Double_t xi, | |
1174780f | 526 | Double_t sigma, Double_t sigmaN, Int_t i, |
0bd4b00f | 527 | Double_t xmin, Double_t xmax) |
528 | { | |
7984e5f7 | 529 | // |
530 | // Generate a TF1 object of @f$ f_I@f$ | |
531 | // | |
532 | // Parameters: | |
533 | // c Constant | |
534 | // delta @f$ \Delta@f$ | |
535 | // xi @f$ \xi_1@f$ | |
536 | // sigma @f$ \sigma_1@f$ | |
537 | // sigma_n @f$ \sigma_n@f$ | |
538 | // i @f$ i@f$ - the number of particles | |
539 | // xmin Least value of range | |
540 | // xmax Largest value of range | |
541 | // | |
542 | // Return: | |
543 | // Newly allocated TF1 object | |
544 | // | |
0bd4b00f | 545 | Int_t npar = AliForwardUtil::ELossFitter::kN+1; |
546 | TF1* landaui = new TF1(Form("ilandau%d", i), &landauGausI,xmin,xmax,npar); | |
547 | // landaui->SetLineStyle(((i-2) % 10)+2); // start at dashed | |
548 | landaui->SetLineColor(kColors[((i-1) % 12)]); // start at red | |
549 | landaui->SetLineWidth(1); | |
550 | landaui->SetNpx(500); | |
551 | landaui->SetParNames("C","#Delta_{p}","#xi", "#sigma", "#sigma_{n}", "i"); | |
552 | ||
553 | // Set the initial parameters from the seed fit | |
554 | landaui->SetParameter(AliForwardUtil::ELossFitter::kC, c); | |
555 | landaui->SetParameter(AliForwardUtil::ELossFitter::kDelta, delta); | |
556 | landaui->SetParameter(AliForwardUtil::ELossFitter::kXi, xi); | |
557 | landaui->SetParameter(AliForwardUtil::ELossFitter::kSigma, sigma); | |
1174780f | 558 | landaui->SetParameter(AliForwardUtil::ELossFitter::kSigmaN, sigmaN); |
0bd4b00f | 559 | landaui->FixParameter(AliForwardUtil::ELossFitter::kN, i); |
560 | ||
561 | return landaui; | |
562 | } | |
7f759bb7 | 563 | |
564 | //==================================================================== | |
565 | AliForwardUtil::ELossFitter::ELossFitter(Double_t lowCut, | |
566 | Double_t maxRange, | |
567 | UShort_t minusBins) | |
568 | : fLowCut(lowCut), fMaxRange(maxRange), fMinusBins(minusBins), | |
569 | fFitResults(0), fFunctions(0) | |
570 | { | |
7984e5f7 | 571 | // |
572 | // Constructor | |
573 | // | |
574 | // Parameters: | |
575 | // lowCut Lower cut of spectrum - data below this cuts is ignored | |
576 | // maxRange Maximum range to fit to | |
577 | // minusBins The number of bins below maximum to use | |
578 | // | |
7f759bb7 | 579 | fFitResults.SetOwner(); |
580 | fFunctions.SetOwner(); | |
581 | } | |
582 | //____________________________________________________________________ | |
583 | AliForwardUtil::ELossFitter::~ELossFitter() | |
584 | { | |
7984e5f7 | 585 | // |
586 | // Destructor | |
587 | // | |
588 | // | |
7f759bb7 | 589 | fFitResults.Delete(); |
590 | fFunctions.Delete(); | |
591 | } | |
592 | //____________________________________________________________________ | |
593 | void | |
594 | AliForwardUtil::ELossFitter::Clear() | |
595 | { | |
7984e5f7 | 596 | // |
597 | // Clear internal arrays | |
598 | // | |
599 | // | |
7f759bb7 | 600 | fFitResults.Clear(); |
601 | fFunctions.Clear(); | |
602 | } | |
603 | //____________________________________________________________________ | |
604 | TF1* | |
605 | AliForwardUtil::ELossFitter::Fit1Particle(TH1* dist, Double_t sigman) | |
606 | { | |
7984e5f7 | 607 | // |
608 | // Fit a 1-particle signal to the passed energy loss distribution | |
609 | // | |
610 | // Note that this function clears the internal arrays first | |
611 | // | |
612 | // Parameters: | |
613 | // dist Data to fit the function to | |
614 | // sigman If larger than zero, the initial guess of the | |
615 | // detector induced noise. If zero or less, then this | |
616 | // parameter is ignored in the fit (fixed at 0) | |
617 | // | |
618 | // Return: | |
619 | // The function fitted to the data | |
620 | // | |
621 | ||
7f759bb7 | 622 | // Clear the cache |
623 | Clear(); | |
624 | ||
625 | // Find the fit range | |
626 | dist->GetXaxis()->SetRangeUser(fLowCut, fMaxRange); | |
627 | ||
7f759bb7 | 628 | // Get the bin with maximum |
629 | Int_t maxBin = dist->GetMaximumBin(); | |
630 | Double_t maxE = dist->GetBinLowEdge(maxBin); | |
631 | ||
632 | // Get the low edge | |
633 | dist->GetXaxis()->SetRangeUser(fLowCut, maxE); | |
634 | Int_t minBin = maxBin - fMinusBins; // dist->GetMinimumBin(); | |
635 | Double_t minE = TMath::Max(dist->GetBinCenter(minBin),fLowCut); | |
636 | Double_t maxEE = dist->GetBinCenter(maxBin+2*fMinusBins); | |
637 | ||
638 | // Restore the range | |
639 | dist->GetXaxis()->SetRangeUser(0, fMaxRange); | |
640 | ||
641 | // Define the function to fit | |
0bd4b00f | 642 | TF1* landau1 = new TF1("landau1", landauGaus1, minE,maxEE,kSigmaN+1); |
7f759bb7 | 643 | |
644 | // Set initial guesses, parameter names, and limits | |
c389303e | 645 | landau1->SetParameters(1,0.5,0.07,0.1,sigman); |
7f759bb7 | 646 | landau1->SetParNames("C","#Delta_{p}","#xi", "#sigma", "#sigma_{n}"); |
c389303e | 647 | landau1->SetNpx(500); |
648 | landau1->SetParLimits(kDelta, minE, fMaxRange); | |
649 | landau1->SetParLimits(kXi, 0.00, fMaxRange); | |
650 | landau1->SetParLimits(kSigma, 0.01, 0.1); | |
651 | if (sigman <= 0) landau1->FixParameter(kSigmaN, 0); | |
652 | else landau1->SetParLimits(kSigmaN, 0, fMaxRange); | |
7f759bb7 | 653 | |
654 | // Do the fit, getting the result object | |
655 | TFitResultPtr r = dist->Fit(landau1, "RNQS", "", minE, maxEE); | |
c389303e | 656 | landau1->SetRange(minE, fMaxRange); |
7f759bb7 | 657 | fFitResults.AddAtAndExpand(new TFitResult(*r), 0); |
658 | fFunctions.AddAtAndExpand(landau1, 0); | |
659 | ||
660 | return landau1; | |
661 | } | |
662 | //____________________________________________________________________ | |
663 | TF1* | |
664 | AliForwardUtil::ELossFitter::FitNParticle(TH1* dist, UShort_t n, | |
665 | Double_t sigman) | |
666 | { | |
7984e5f7 | 667 | // |
668 | // Fit a N-particle signal to the passed energy loss distribution | |
669 | // | |
670 | // If there's no 1-particle fit present, it does that first | |
671 | // | |
672 | // Parameters: | |
673 | // dist Data to fit the function to | |
674 | // n Number of particle signals to fit | |
675 | // sigman If larger than zero, the initial guess of the | |
676 | // detector induced noise. If zero or less, then this | |
677 | // parameter is ignored in the fit (fixed at 0) | |
678 | // | |
679 | // Return: | |
680 | // The function fitted to the data | |
681 | // | |
682 | ||
7f759bb7 | 683 | // Get the seed fit result |
684 | TFitResult* r = static_cast<TFitResult*>(fFitResults.At(0)); | |
685 | TF1* f = static_cast<TF1*>(fFunctions.At(0)); | |
686 | if (!r || !f) { | |
687 | f = Fit1Particle(dist, sigman); | |
688 | r = static_cast<TFitResult*>(fFitResults.At(0)); | |
689 | if (!r || !f) { | |
690 | ::Warning("FitNLandau", "No first shot at landau fit"); | |
691 | return 0; | |
692 | } | |
693 | } | |
694 | ||
695 | // Get some parameters from seed fit | |
c389303e | 696 | Double_t delta1 = r->Parameter(kDelta); |
697 | Double_t xi1 = r->Parameter(kXi); | |
7f759bb7 | 698 | Double_t maxEi = n * (delta1 + xi1 * TMath::Log(n)) + 2 * n * xi1; |
699 | Double_t minE = f->GetXmin(); | |
700 | ||
0bd4b00f | 701 | // Array of weights |
702 | TArrayD a(n-1); | |
703 | for (UShort_t i = 2; i <= n; i++) | |
704 | a.fArray[i-2] = (n == 2 ? 0.05 : 0.000001); | |
7f759bb7 | 705 | // Make the fit function |
0bd4b00f | 706 | TF1* landaun = MakeNLandauGaus(r->Parameter(kC), |
707 | r->Parameter(kDelta), | |
708 | r->Parameter(kXi), | |
709 | r->Parameter(kSigma), | |
710 | r->Parameter(kSigmaN), | |
711 | n,a.fArray,minE,maxEi); | |
c389303e | 712 | landaun->SetParLimits(kDelta, minE, fMaxRange); // Delta |
713 | landaun->SetParLimits(kXi, 0.00, fMaxRange); // xi | |
714 | landaun->SetParLimits(kSigma, 0.01, 1); // sigma | |
715 | // Check if we're using the noise sigma | |
716 | if (sigman <= 0) landaun->FixParameter(kSigmaN, 0); | |
717 | else landaun->SetParLimits(kSigmaN, 0, fMaxRange); | |
7f759bb7 | 718 | |
719 | // Set the range and name of the scale parameters | |
720 | for (UShort_t i = 2; i <= n; i++) {// Take parameters from last fit | |
c389303e | 721 | landaun->SetParLimits(kA+i-2, 0,1); |
7f759bb7 | 722 | } |
723 | ||
724 | // Do the fit | |
725 | TFitResultPtr tr = dist->Fit(landaun, "RSQN", "", minE, maxEi); | |
726 | ||
c389303e | 727 | landaun->SetRange(minE, fMaxRange); |
7f759bb7 | 728 | fFitResults.AddAtAndExpand(new TFitResult(*tr), n-1); |
729 | fFunctions.AddAtAndExpand(landaun, n-1); | |
730 | ||
731 | return landaun; | |
732 | } | |
7e4038b5 | 733 | |
734 | //==================================================================== | |
735 | AliForwardUtil::Histos::~Histos() | |
736 | { | |
7984e5f7 | 737 | // |
738 | // Destructor | |
739 | // | |
7e4038b5 | 740 | if (fFMD1i) delete fFMD1i; |
741 | if (fFMD2i) delete fFMD2i; | |
742 | if (fFMD2o) delete fFMD2o; | |
743 | if (fFMD3i) delete fFMD3i; | |
744 | if (fFMD3o) delete fFMD3o; | |
745 | } | |
746 | ||
747 | //____________________________________________________________________ | |
748 | TH2D* | |
749 | AliForwardUtil::Histos::Make(UShort_t d, Char_t r, | |
750 | const TAxis& etaAxis) const | |
751 | { | |
7984e5f7 | 752 | // |
753 | // Make a histogram | |
754 | // | |
755 | // Parameters: | |
756 | // d Detector | |
757 | // r Ring | |
758 | // etaAxis Eta axis to use | |
759 | // | |
760 | // Return: | |
761 | // Newly allocated histogram | |
762 | // | |
7e4038b5 | 763 | Int_t ns = (r == 'I' || r == 'i') ? 20 : 40; |
764 | TH2D* hist = new TH2D(Form("FMD%d%c_cache", d, r), | |
765 | Form("FMD%d%c cache", d, r), | |
766 | etaAxis.GetNbins(), etaAxis.GetXmin(), | |
767 | etaAxis.GetXmax(), ns, 0, 2*TMath::Pi()); | |
768 | hist->SetXTitle("#eta"); | |
769 | hist->SetYTitle("#phi [radians]"); | |
770 | hist->SetZTitle("d^{2}N_{ch}/d#etad#phi"); | |
771 | hist->Sumw2(); | |
772 | hist->SetDirectory(0); | |
773 | ||
774 | return hist; | |
775 | } | |
776 | //____________________________________________________________________ | |
777 | void | |
778 | AliForwardUtil::Histos::Init(const TAxis& etaAxis) | |
779 | { | |
7984e5f7 | 780 | // |
781 | // Initialize the object | |
782 | // | |
783 | // Parameters: | |
784 | // etaAxis Eta axis to use | |
785 | // | |
7e4038b5 | 786 | fFMD1i = Make(1, 'I', etaAxis); |
787 | fFMD2i = Make(2, 'I', etaAxis); | |
788 | fFMD2o = Make(2, 'O', etaAxis); | |
789 | fFMD3i = Make(3, 'I', etaAxis); | |
790 | fFMD3o = Make(3, 'O', etaAxis); | |
791 | } | |
792 | //____________________________________________________________________ | |
793 | void | |
794 | AliForwardUtil::Histos::Clear(Option_t* option) | |
795 | { | |
7984e5f7 | 796 | // |
797 | // Clear data | |
798 | // | |
799 | // Parameters: | |
800 | // option Not used | |
801 | // | |
7e4038b5 | 802 | fFMD1i->Reset(option); |
803 | fFMD2i->Reset(option); | |
804 | fFMD2o->Reset(option); | |
805 | fFMD3i->Reset(option); | |
806 | fFMD3o->Reset(option); | |
807 | } | |
808 | ||
809 | //____________________________________________________________________ | |
810 | TH2D* | |
811 | AliForwardUtil::Histos::Get(UShort_t d, Char_t r) const | |
812 | { | |
7984e5f7 | 813 | // |
814 | // Get the histogram for a particular detector,ring | |
815 | // | |
816 | // Parameters: | |
817 | // d Detector | |
818 | // r Ring | |
819 | // | |
820 | // Return: | |
821 | // Histogram for detector,ring or nul | |
822 | // | |
7e4038b5 | 823 | switch (d) { |
824 | case 1: return fFMD1i; | |
825 | case 2: return (r == 'I' || r == 'i' ? fFMD2i : fFMD2o); | |
826 | case 3: return (r == 'I' || r == 'i' ? fFMD3i : fFMD3o); | |
827 | } | |
828 | return 0; | |
829 | } | |
9d99b0dd | 830 | //==================================================================== |
831 | TList* | |
832 | AliForwardUtil::RingHistos::DefineOutputList(TList* d) const | |
833 | { | |
7984e5f7 | 834 | // |
835 | // Define the outout list in @a d | |
836 | // | |
837 | // Parameters: | |
838 | // d Where to put the output list | |
839 | // | |
840 | // Return: | |
841 | // Newly allocated TList object or null | |
842 | // | |
9d99b0dd | 843 | if (!d) return 0; |
844 | TList* list = new TList; | |
845 | list->SetName(fName.Data()); | |
846 | d->Add(list); | |
847 | return list; | |
848 | } | |
849 | //____________________________________________________________________ | |
850 | TList* | |
851 | AliForwardUtil::RingHistos::GetOutputList(TList* d) const | |
852 | { | |
7984e5f7 | 853 | // |
854 | // Get our output list from the container @a d | |
855 | // | |
856 | // Parameters: | |
857 | // d where to get the output list from | |
858 | // | |
859 | // Return: | |
860 | // The found TList or null | |
861 | // | |
9d99b0dd | 862 | if (!d) return 0; |
863 | TList* list = static_cast<TList*>(d->FindObject(fName.Data())); | |
864 | return list; | |
865 | } | |
866 | ||
867 | //____________________________________________________________________ | |
868 | TH1* | |
869 | AliForwardUtil::RingHistos::GetOutputHist(TList* d, const char* name) const | |
870 | { | |
7984e5f7 | 871 | // |
872 | // Find a specific histogram in the source list @a d | |
873 | // | |
874 | // Parameters: | |
875 | // d (top)-container | |
876 | // name Name of histogram | |
877 | // | |
878 | // Return: | |
879 | // Found histogram or null | |
880 | // | |
9d99b0dd | 881 | return static_cast<TH1*>(d->FindObject(name)); |
882 | } | |
883 | ||
7e4038b5 | 884 | // |
885 | // EOF | |
886 | // |