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