]> git.uio.no Git - u/mrichter/AliRoot.git/blame - PWG2/FORWARD/analysis2/AliForwardUtil.cxx
Renames and new scripts
[u/mrichter/AliRoot.git] / PWG2 / FORWARD / analysis2 / AliForwardUtil.cxx
CommitLineData
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//====================================================================
22UShort_t
23AliForwardUtil::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//____________________________________________________________________
46const char*
47AliForwardUtil::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//____________________________________________________________________
68UShort_t
cc83fca2 69AliForwardUtil::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//____________________________________________________________________
95const char*
96AliForwardUtil::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//____________________________________________________________________
110Short_t
111AliForwardUtil::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//____________________________________________________________________
128const char*
129AliForwardUtil::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//====================================================================
145Int_t AliForwardUtil::fgConvolutionSteps = 100;
146Double_t AliForwardUtil::fgConvolutionNSigma = 5;
147namespace {
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//____________________________________________________________________
208Double_t
209AliForwardUtil::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//____________________________________________________________________
232Double_t
233AliForwardUtil::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//____________________________________________________________________
288Double_t
289AliForwardUtil::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//____________________________________________________________________
327Double_t
328AliForwardUtil::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//____________________________________________________________________
419Double_t
420AliForwardUtil::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 458namespace {
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//____________________________________________________________________
474TF1*
475AliForwardUtil::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//____________________________________________________________________
523TF1*
524AliForwardUtil::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//====================================================================
565AliForwardUtil::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//____________________________________________________________________
583AliForwardUtil::ELossFitter::~ELossFitter()
584{
7984e5f7 585 //
586 // Destructor
587 //
588 //
7f759bb7 589 fFitResults.Delete();
590 fFunctions.Delete();
591}
592//____________________________________________________________________
593void
594AliForwardUtil::ELossFitter::Clear()
595{
7984e5f7 596 //
597 // Clear internal arrays
598 //
599 //
7f759bb7 600 fFitResults.Clear();
601 fFunctions.Clear();
602}
603//____________________________________________________________________
604TF1*
605AliForwardUtil::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//____________________________________________________________________
663TF1*
664AliForwardUtil::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//====================================================================
735AliForwardUtil::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//____________________________________________________________________
748TH2D*
749AliForwardUtil::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//____________________________________________________________________
777void
778AliForwardUtil::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//____________________________________________________________________
793void
794AliForwardUtil::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//____________________________________________________________________
810TH2D*
811AliForwardUtil::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//====================================================================
831TList*
832AliForwardUtil::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//____________________________________________________________________
850TList*
851AliForwardUtil::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//____________________________________________________________________
868TH1*
869AliForwardUtil::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//