1 /* Copyright (C) 2007 Christian Holm Christensen <cholm@nbi.dk>
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public License
5 * as published by the Free Software Foundation; either version 2.1 of
6 * the License, or (at your option) any later version.
8 * This library is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19 @brief Implementation of an Resolution class */
20 //____________________________________________________________________
22 // Calculate the event plane resolution.
23 // Input is the observed phis.
24 // There's a number of implementations of this.
25 // One is based on a naive interpretation of the Voloshin paper
26 // Another is taken from aliroot/PWG2/FLOW
27 // An finally one is based on Ollitraut's article.
28 #include "flow/AliFMDFlowResolution.h"
29 #include "flow/AliFMDFlowUtil.h"
30 #include "flow/AliFMDFlowBessel.h"
31 #include <TGraphErrors.h>
38 //====================================================================
39 AliFMDFlowResolution::AliFMDFlowResolution(UShort_t n)
41 fContrib("contrib", Form("cos(%d(#Psi_{A} - #Psi_{B}))", fOrder), 100,-1,1)
43 fContrib.SetDirectory(0);
44 fContrib.SetXTitle(Form("cos(%d(#Psi_{A} - #Psi_{B}))", fOrder));
47 //____________________________________________________________________
48 AliFMDFlowResolution::AliFMDFlowResolution(const AliFMDFlowResolution& o)
55 // o Object to copy from.
56 fContrib.SetDirectory(0);
57 fContrib.SetXTitle(Form("cos(%d(#Psi_{A} - #Psi_{B}", fOrder));
59 //____________________________________________________________________
61 AliFMDFlowResolution::operator=(const AliFMDFlowResolution& o)
63 // Assignment operator
65 // o Object to assign from
67 AliFMDFlowStat::operator=(o);
71 fContrib.Add(&o.fContrib);
75 //____________________________________________________________________
77 AliFMDFlowResolution::Add(Double_t psiA, Double_t psiB)
81 // psiA A sub-event plane angle Psi_A in [0,2pi]
82 // psiB B sub-event plane angle Psi_B in [0,2pi]
83 Double_t diff = NormalizeAngle(fOrder * (psiA - psiB));
84 Double_t contrib = cos(diff);
85 AliFMDFlowStat::Add(contrib);
86 fContrib.Fill(contrib);
89 //____________________________________________________________________
91 AliFMDFlowResolution::Correction(UShort_t k) const
93 // Get the correction for harmonic strength of order @a k
94 // k The harminic strenght order to get the correction for
95 // Returns <cos(n(psi - psi_R))>
97 return Correction(k, e);
100 //____________________________________________________________________
102 AliFMDFlowResolution::Correction(UShort_t, Double_t& e2) const
104 // Get the correction for harmonic strength of order k
106 // k The harminic strenght order to get the correction for
107 // e2 The square error on the correction
108 // Returns <cos(n(psi - psi_R))>
110 return sqrt(Double_t(2)) * sqrt(fabs(fAverage));
113 //____________________________________________________________________
115 AliFMDFlowResolution::Draw(Option_t* option)
117 // Draw this corrrection function
119 // option String of options. Passed to TGraph::Draw
120 TGraph* g = new TGraph(100);
121 for (UShort_t i = 0; i < g->GetN(); i++) {
122 Double_t x = -1. + 2. / 100 * i;
123 Double_t y = sqrt(Double_t(2)) * sqrt(fabs(x));
124 g->SetPoint(i, x, y);
126 g->SetName("naive_res");
127 g->SetTitle("Naive Resolution Function");
128 g->GetHistogram()->SetXTitle("<cos(n(|#Psi_{A}-#Psi_{B}|))>");
129 g->GetHistogram()->SetYTitle("<cos(n(#Psi-#Psi_{R}))>");
130 g->GetHistogram()->SetDirectory(0);
131 g->Draw(Form("lh %s", option));
134 //____________________________________________________________________
136 AliFMDFlowResolution::Browse(TBrowser* b)
141 //====================================================================
143 AliFMDFlowResolutionStar::Correction(UShort_t k, Double_t& e2) const
145 // Get the correction for harmonic strength of order k
147 // k The harminic strenght order to get the correction for
148 // e2 The square error on the correction
149 // Returns <cos(n(psi - psi_R))>
152 Double_t chi = Chi(fAverage, k, delta);
154 Double_t res = Res(sqrt(Double_t(2)) * chi, k, dr);
155 e2 = pow(dr * delta,2);
158 //____________________________________________________________________
160 AliFMDFlowResolutionStar::Correction(UShort_t k) const
162 // Get the correction for harmonic strength of order @a k
163 // k The harminic strenght order to get the correction for
164 // Returns <cos(n(psi - psi_R))>
166 return Correction(k, e);
168 //____________________________________________________________________
170 AliFMDFlowResolutionStar::Chi(Double_t res, UShort_t k,
171 Double_t& delta) const
175 // res First shot at the resolution.
177 // delta On return, the last step size in \chi -
178 // which is taken to be delta chi
183 for (UInt_t i = 0; i < 15; i++) {
184 if (Res(chi, k, dr) < res) chi += delta;
190 //____________________________________________________________________
192 AliFMDFlowResolutionStar::Res(Double_t chi, UShort_t k, Double_t& dr) const
194 // The resolution function is
196 // sqrt(pi) x exp(-x/4) (f1(x^2/4) + f2(x^2/4))
197 // r(x) = --------------------------------------------
201 // = c x (f1(y) - f2(y))
203 // where f1 is the modified Bessel function first kind I_{(k-1)/2},
204 // and f2 is the modified Bessel function of the first kind
207 // sqrt(pi) exp(-x^2/4)
208 // c = --------------------, y = x^2/4
211 // The derivative of the resolution function is
214 // r'(y) = - (4 sqrt(y) (f1'(y) - f2'(y)) - (4 y - 2)(f1(y) - f2(y)))
218 // = - (4 sqrt(y) (f1'(y) - f2'(y))) + --------- - sqrt(y) r(y)
221 // Since dI_n(x)/dx = I_(n-1)(x) - n / x I_n(x), and substituting
222 // f3(y) = I_((k-3)/2)(y)
225 // r'(y) = - ((4 - 2 k) f1(y) - (4 y + 2 k) f2(y) + 4 y f3(y))
228 Double_t y = chi * chi / 4;
229 Double_t c = sqrt(M_PI) * exp(-y) / (2 * sqrt(Double_t(2)));
231 // i[0] = I[(k-1)/2-1], i[1] = I[(k-1)/2], i[2] = I[(k-1)/2+1]
232 Double_t i[3], di[3];
233 AliFMDFlowBessel::Inu(Double_t(k-3)/2, Double_t(k+1)/2, y, i, di);
235 Double_t r = c * chi * (i[2] + i[1]);
236 dr = c / 2 * ((4 - 2*k)*i[1] - (4*y + 2*k)*i[2] + 4*y*i[0]);
241 //____________________________________________________________________
243 AliFMDFlowResolutionStar::Draw(Option_t* option)
245 // Draw this corrrection function
247 // option String of options. Passed to TGraph::Draw
249 // chi Draw chi rather than the resolution.
252 Bool_t chi = opt.Contains("chi");
254 TH2* h = new TH2D(Form("star_%s_frame", (chi ? "chi" : "res")),
255 Form("STAR %s Function for k=(1,2,4)",
256 (chi ? "Chi" : "Resolution")),
257 100, 0, 1, 100, 0, (chi ? 3 : 1.5));
258 h->SetXTitle("<cos(n(|#Psi_{A}-#Psi_{B}|))>");
259 h->SetYTitle((chi ? "#chi" : "<cos(n(#Psi-#Psi_{R}))>"));
264 for (UShort_t k = 1; k <= 4; k++) {
265 if (k == 3) continue;
267 TGraphErrors* g = new TGraphErrors(100);
268 for (UShort_t i = 0; i < g->GetN(); i++) {
270 Double_t x = 1. / 100 * i;
272 Double_t c = Chi(x, k, e2);
276 y = Res(sqrt(Double_t(2)) * c, k, dr);
279 g->SetPoint(i, x, y);
280 g->SetPointError(i, 0, sqrt(e2));
283 g->SetName(Form("star_%s_k%d", (chi ? "chi" : "res"), k));
284 g->SetTitle(Form("STAR %s Function for k=%d",
285 (chi ? "Chi" : "Resolution"), k));
286 g->GetHistogram()->SetXTitle("<cos(n(|#Psi_{A}-#Psi_{B}|))>");
287 g->GetHistogram()->SetYTitle((chi ? "#chi" : "<cos(n(#Psi-#Psi_{R}))>"));
288 g->GetHistogram()->SetDirectory(0);
289 g->Draw(Form("l %s same", option));
293 //====================================================================
294 AliFMDFlowResolutionTDR::AliFMDFlowResolutionTDR(UShort_t n)
295 : AliFMDFlowResolution(n),
297 fNK("nk", "Number of events with (#Psi_{}A-#Psi_{B})>90^{o}", 2, 0, 2)
300 fNK.SetYTitle("# events");
301 fNK.GetXaxis()->SetBinLabel(1, "k");
302 fNK.GetXaxis()->SetBinLabel(2, "N");
305 //____________________________________________________________________
306 AliFMDFlowResolutionTDR::AliFMDFlowResolutionTDR(const
307 AliFMDFlowResolutionTDR& o)
308 : AliFMDFlowResolution(o),
313 fNK.SetYTitle("# events");
314 fNK.GetXaxis()->SetBinLabel(1, "k");
315 fNK.GetXaxis()->SetBinLabel(2, "N");
317 //____________________________________________________________________
318 AliFMDFlowResolutionTDR&
319 AliFMDFlowResolutionTDR::operator=(const AliFMDFlowResolutionTDR& o)
321 // Assignment operator
323 // o Object to assign from
325 AliFMDFlowResolution::operator=(o);
331 //____________________________________________________________________
333 AliFMDFlowResolutionTDR::Clear(Option_t*)
335 // Clear internal variables.
341 //____________________________________________________________________
343 AliFMDFlowResolutionTDR::Add(Double_t psiA, Double_t psiB)
345 // add data point. If |psi_a - psi_b| >= pi/2 increase large
348 // psiA A sub-event plane angle Psi_A in [0,2pi]
349 // psiB B sub-event plane angle Psi_B in [0,2pi]
350 AliFMDFlowResolution::Add(psiA, psiB);
351 Double_t a = fabs(psiA - psiB);
352 if (a >= .5 * M_PI) {
359 //____________________________________________________________________
361 AliFMDFlowResolutionTDR::Correction(UShort_t k, Double_t& e2) const
363 // From nucl-ex/9711003v2
366 // <cos n Delta phi> =
369 // -------- chi exp(-z) (I_((n-1)/2)(z) + I_((n+1)/2)(z))
372 // where z = chi^2 / 2
375 // std::cerr << "TDR: K = 0" << std::endl;
379 // std::cerr << "TDR: N = 0" << std::endl;
382 Double_t r = Double_t(fLarge) / fN;
384 Double_t y = Chi2Over2(r, echi2);
385 return Res(k, y, echi2, e2);
390 //____________________________________________________________________
392 AliFMDFlowResolutionTDR::Res(UShort_t k, Double_t y, Double_t echi2,
395 // The resolution function is
397 // sqrt(pi) x exp(-x/4) (f1(x^2/4) + f2(x^2/4))
398 // r(x) = --------------------------------------------
402 // = c x (f1(y) - f2(y))
404 // where f1 is the modified Bessel function first kind I_{(k-1)/2},
405 // and f2 is the modified Bessel function of the first kind
408 // sqrt(pi) exp(-x^2/4)
409 // c = --------------------, y = x^2/4
412 // The derivative of the resolution function is
415 // r'(y) = - (4 sqrt(y) (f1'(y) - f2'(y)) - (4 y - 2)(f1(y) - f2(y)))
419 // = - (4 sqrt(y) (f1'(y) - f2'(y))) + --------- - sqrt(y) r(y)
422 // Since dI_n(x)/dx = I_(n-1)(x) - n / x I_n(x), and substituting
423 // f3(y) = I_((k-3)/2)(y)
426 // r'(y) = - ((4 - 2 k) f1(y) - (4 y + 2 k) f2(y) + 4 y f3(y))
430 Double_t chi = sqrt(2 * y);
431 Double_t c = sqrt(M_PI) * exp(-y) / 2;
433 // i[0] = I[(k-1)/2-1], i[1] = I[(k-1)/2], i[2] = I[(k-1)/2+1]
434 Double_t i[3], di[3];
435 AliFMDFlowBessel::Inu(Double_t(k-3)/2, Double_t(k+1)/2, y, i, di);
437 Double_t r = c * chi * (i[2] + i[1]);
438 Double_t dr = c / 2 * ((4 - 2*k)*i[1] - (4*y + 2*k)*i[2] + 4*y*i[0]);
439 e2 = dr * dr * echi2;
443 //____________________________________________________________________
445 AliFMDFlowResolutionTDR::Correction(UShort_t k) const
447 // Get the correction for harmonic strength of order k
449 // k The harminic strenght order to get the correction for
450 // Returns <cos(n(psi - psi_R))>
452 return Correction(k, e);
454 //____________________________________________________________________
456 AliFMDFlowResolutionTDR::Chi2Over2(Double_t r, Double_t& e2) const
458 // From nucl-ex/9711003v2
460 // N equal to the total number of events, and k equal to the
461 // number of events where |Psi_A - Psi_B| > pi/2, we get
464 // - = ------------- => chi^2 / 2 = - log 2 -
468 // => chi^2 / 2 = log -- (*)
472 // => chi^2 = - 2 log ---
475 // => chi = -/+ sgrt (- 2 log (2k/N))
477 // (*) this is what is returned.
479 // The error on chi is given by
482 // d^2chi = (------)^2 d^2(k/N) = - -------------------- d^2(k/N)
483 // d(k/N) 4 (k/N)^2 log(2 k/N)
487 // (1 - 2 -) dk^2 + --- dN^2
489 // d^2(k/N) = --------------------------
493 // with dk = sqrt(k) and dN = sqrt(N), this reduces to
496 // (1 - 2 -) k + ----- N --- - 2 --- + ---
498 // d^2(k/N) = --------------------- = --------------------------
501 // k N - k^2 k (N - k) k (1 - k / N)
502 // = --------- = - ------- = - -----------
505 // Identifying r = k/N, we get
508 // d(k/N) = sqrt(r (1 - r) / N)
510 // which is the well-known result for Binomial errors.
511 // Alternatively, one could compute these error using an Baysian
512 // confidence level of say 68.3% (see for example
513 // http://home.fnal.gov/~paterno/images/effic.pdf).
515 // Our final expression for the error on chi then becomes
518 // d^2chi = - -------------------- r (1 - r) / N
522 // = - -------------- = ------------
523 // 4 r N log(2 r) 4 k log(2 r)
525 std::cerr << "TDR: Large/All = " << r << " <= 0!" << std::endl;
528 Double_t ratio = 1. / (2*r); // Double_t(fN) / (2 * fLarge);
530 std::cerr << "TDR: Large/All = " << ratio << " <= 0!" << std::endl;
533 Double_t chi2over2 = log(ratio);
535 std::cerr << "TDR: log(" << ratio << ") = " << chi2over2
536 << " < 0" << std::endl;
539 if (fLarge != 0) e2 = (r - 1) / (4 * fLarge * log(2 * r));
540 else e2 = (r - 1) / (4 * r * log(2 * r));
544 //____________________________________________________________________
546 AliFMDFlowResolutionTDR::Draw(Option_t* option)
548 // Draw this corrrection function
550 // option String of options. Passed to TGraph::Draw
552 // chi Draw chi rather than the resolution.
555 Bool_t chi = opt.Contains("chi");
557 TH2* h = new TH2D(Form("tdr_%s_frame", (chi ? "chi" : "res")),
558 Form("TDR %s Function for k=(1,2,4)",
559 (chi ? "Chi" : "Resolution")),
560 100, 0, 1, 100, 0, (chi ? 3 : 1.5));
562 h->SetYTitle((chi ? "#chi" : "<cos(n(#Psi-#Psi_{R}))>"));
567 for (UShort_t k = 1; k <= 4; k++) {
568 if (k == 3) continue;
570 TGraphErrors* g = new TGraphErrors;
572 for (Double_t x = 0.02; x < 0.5; x += 0.01) {
575 Double_t c = Chi2Over2(x, e2);
576 if (chi) y = sqrt(2 * c);
579 y = Res(k, c, e2, dr);
582 g->SetPoint(i, x, y);
583 g->SetPointError(i, 0, sqrt(fabs(e2)));
587 g->SetName(Form("tdr_%s_k%d", (chi ? "chi" : "res"), k));
588 g->SetTitle(Form("TDR %s Function for k=%d",
589 (chi ? "Chi" : "Resolution"), k));
590 g->GetHistogram()->SetXTitle("K/N");
591 g->GetHistogram()->SetYTitle((chi ? "#chi" : "<cos(n(#Psi-#Psi_{R}))>"));
592 g->GetHistogram()->SetDirectory(0);
593 g->Draw(Form("l %s %s", (k == 0 ? "h" : "same"), option));
598 //____________________________________________________________________
600 AliFMDFlowResolutionTDR::Browse(TBrowser* b)
602 AliFMDFlowResolution::Browse(b);
606 //____________________________________________________________________