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