EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SmearePHENIX_0_0.cxx
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file SmearePHENIX_0_0.cxx
1 
10 /*
11  Example smearing script for the ePHENIX detector.
12 
13  It defines:
14  - EPhenixMomentum: a special smearing class for the ePHENIX momentum
15  performance
16  - BuildDetector: a function to generate the full ePHENIX detector description
17 
18  This script must be compiled in ROOT before running.
19  Therefore, you must first make sure that
20  (1) libeicsmear is loaded, via
21  gSystem->Load("libeicsmear");
22  (2) the eicsmear headers are accessible, by doing e.g.
23  gSystem->AddIncludePath(" -I/path/to/eic-smear/include");
24  You can then compile it in a ROOT session via
25  .L ePHENIXDetector.cpp+g
26 */
27 
28 #include <algorithm> // For std::max
29 #include <cmath>
30 #include <list>
31 
32 #include <TCollection.h> // For TIter
33 #include <TGraph.h>
34 #include <TList.h>
35 #include <TLorentzVector.h>
36 #include <TMultiGraph.h>
37 #include <TPad.h>
38 #include <TRandom.h>
39 
42 #include "eicsmear/smear/Device.h"
44 #include "eicsmear/smear/Smearer.h"
47 
48 
59 public:
63  virtual ~EPhenixMomentum();
71  EPhenixMomentum(bool multipleScattering = true);
78  void Initialise();
84  TMultiGraph* Graphs();
88  virtual EPhenixMomentum* Clone(const char* /* unused */) const;
92  virtual void Smear(const erhic::VirtualParticle& particle,
93  Smear::ParticleMCS& smeared);
99  virtual double computeMultipleScattering(
100  const erhic::VirtualParticle& particle) const;
104  virtual void Draw(Option_t* option = "ac");
105 
111  static double etaToTheta(double eta) {
112  return 2. * std::atan(std::exp(-eta));
113  }
114 
115 
116 private:
117  TMultiGraph* mGraphDrawer;
119  // ClassDef(EPhenixMomentum, 1)
120 };
121 
122 EPhenixMomentum::EPhenixMomentum(bool multipleScattering)
123  : mGraphDrawer(nullptr), mMultipleScattering(multipleScattering) {
124  // Only use charged particles, as this is a tracker
126 }
127 
129  if (mGraphDrawer) {
130  delete mGraphDrawer;
131  mGraphDrawer = NULL;
132  } // if
133 }
134 
136  // Pseudorapidity values
137  const double eta[75] = {
138  -3.0, -2.9, -2.8, -2.7, -2.6, -2.5, -2.4, -2.3, -2.2, -2.1, -2.0, -2.0,
139  -1.9, -1.8, -1.7, -1.6, -1.5, -1.5, -1.4, -1.3, -1.2, -1.1, -1.0, -0.9,
140  -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1, 0.0, 0.1, 0.2, 0.3,
141  0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.0, 1.1, 1.2, 1.3, 1.4,
142  1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.5,
143  2.6, 2.7, 2.8, 2.9, 3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7,
144  3.8, 3.9, 4.0
145  };
146  // sigma(1/p) values at each value of eta
147  const double sigma[75] = {
148  0.010500, 0.009820, 0.009140, 0.008460, 0.007780, 0.007100, 0.006520,
149  0.005940, 0.005360, 0.004780, 0.004200, 0.009811, 0.008759, 0.007479,
150  0.006242, 0.005436, 0.004524, 0.006887, 0.005374, 0.004485, 0.003822,
151  0.003164, 0.002592, 0.002791, 0.002991, 0.003187, 0.003374, 0.003547,
152  0.003700, 0.003827, 0.003921, 0.003980, 0.004000, 0.003980, 0.003921,
153  0.003827, 0.003700, 0.003547, 0.003374, 0.003187, 0.002991, 0.002791,
154  0.002592, 0.001200, 0.001280, 0.001360, 0.001440, 0.001520, 0.001600,
155  0.001840, 0.002080, 0.002320, 0.002560, 0.002800, 0.003160, 0.003520,
156  0.003880, 0.004240, 0.004600, 0.002300, 0.002620, 0.002940, 0.003260,
157  0.003580, 0.003900, 0.004400, 0.004900, 0.005400, 0.005900, 0.006400,
158  0.007220, 0.008040, 0.008860, 0.009680, 0.010500
159  };
160  mGraphDrawer = new TMultiGraph;
161  mGraphDrawer->SetTitle(";#eta;Momentum Resolution, #delta(1/p) (1/GeV)");
162  // Use different graphs for each region to avoid problems at discontinuities
163  // both with the calculated values and with drawing
164  int points[5] = {11, 6, 26, 16, 16}; // Number of points in each graph
165  int colours[5] = {kBlue, kMagenta, kRed, kGreen + 3, kGreen - 2};
166  int position(0); // Tracks cumulative array index
167  for (int i(0); i < 5; ++i) {
168  TGraph* graph = new TGraph(points[i], eta + position, sigma + position);
169  TString name("graph");
170  name += i; // Append graph number to name
171  graph->SetName(name);
172  // Apply formatting
173  graph->SetLineWidth(3);
174  graph->SetLineColor(colours[i]);
175  graph->SetMarkerColor(colours[i]);
176  mGraphDrawer->Add(graph);
177  position += points[i]; // Update total array index
178  } // for
179 }
180 
181 TMultiGraph* EPhenixMomentum::Graphs() {
182  if (!mGraphDrawer) {
183  Initialise();
184  } // if
185  return mGraphDrawer;
186 }
187 
189  EPhenixMomentum* clone = new EPhenixMomentum(*this);
190  // We need to "de-initialise" the clone so it doesn't retain the
191  // same graphs as this instance.
192  clone->mGraphDrawer = NULL;
193  return clone;
194 }
195 
197  Smear::ParticleMCS& smeared) {
198  TGraph* graph(NULL);
199  TGraph* iterGraph(NULL); // For iterator position
200  TIter iter(Graphs()->GetListOfGraphs());
201  // Loop through graphs for each eta range until we find the one for
202  // the eta of this particle
203  while ((iterGraph = static_cast<TGraph*>(iter()))) {
204  // Array of eta points in the graph
205  double* eta = iterGraph->GetX();
206  if (particle.GetEta() > eta[0] &&
207  particle.GetEta() < eta[iterGraph->GetN() - 1] ) {
208  graph = iterGraph;
209  break;
210  } // if
211  } // while
212  if (graph) {
213  // Stored values are sigma(1/p).
214  // We want to get sigma(p), which is equivalent to sigma(1/p) * p^2.
215  double sigmaP = graph->Eval(particle.GetEta()) // sigma(1/p)
216  * std::pow(particle.GetP(), 2.);
217  // Add multiple scattering in quadrature with the linear term if requested
218  if (mMultipleScattering) {
219  sigmaP = std::sqrt(std::pow(sigmaP, 2.) +
220  std::pow(computeMultipleScattering(particle), 2.));
221  } // if
222  double sigma = gRandom->Gaus(particle.GetP(), sigmaP);
223  smeared.SetP(std::max(sigma, 0.)); // Store p, must not be negative
224  } // if
225 }
226 
228  const erhic::VirtualParticle& particle) const {
229  // Here is a duplicate of the relevant information from Sasha's email:
230  // "As for multiple scattering term, what has been simulated so far is eta
231  // ranges 2-3 and 3-4. Numbers keep changing after inclusion of different
232  // material (associated with detectors and read-out). The current very
233  // conservative advice is to use 3% for eta=2-3; in eta=3-4, log of this
234  // term changes ~linearly from 3% at eta=3 to ~15% at eta=4."
235  // Note that the 3% etc is sigma(P) / P.
236  const double eta = particle.GetEta();
237  if (eta > 2. && eta <= 3.) {
238  return 0.03 * particle.GetP(); // Flat sigma(P)/P = 3% in this range
239  } else if (eta > 3. && eta <= 4.) {
240  // The behaviour Sasha describes is (I think!)
241  // log(M.S.) ~= log(3%) + (log(15%) - log(3%)) * (eta - 3) [3 < eta < 4]
242  double logSigmaP = std::log(0.03) +
243  (std::log(0.15) - std::log(0.03)) * (eta - 3);
244  // Remember to multiply by momentum, as the 3-15% is sigma(P)/P and we
245  // want sigma(P)
246  return std::exp(logSigmaP) * particle.GetP();
247  } // if
248  return 0.; // Outside 2 < eta < 4
249 }
250 
251 void EPhenixMomentum::Draw(Option_t* option) {
252  Graphs()->Draw(option);
253  if (gPad) {
254  gPad->SetLogy(1);
255  } // if
256 }
257 
272 Smear::Detector BuildePHENIX_0_0(bool multipleScattering) {
273  EPhenixMomentum momentum(multipleScattering);
274  // Define acceptance zones for different ePHENIX regions:
275  // - electron-going: -4 < eta < -1
276  // - barrel: -1 < eta < 1
277  // - hadron-going: 1 < eta < 4
278  // As the same calorimeter performance is used in the barrel and hadron-going
279  // directions we define them as a single zone
280  // Note etamin -> thetamax, etamax -> thetamin
283 
284  // Electron-going electromagnetic calorimeter
285  Smear::Device electronEcal("E", "0.015*sqrt(E) + 0.01*E",
287  electronEcal.Accept.AddZone(electronDirection);
288  // Barrel and hadron-going electromagnetic calorimeter
289  Smear::Device barrelAndHadronEcal("E", "0.12*sqrt(E) + 0.02*E",
291  barrelAndHadronEcal.Accept.AddZone(barrelAndHadronDirection);
292  // Barrel and hadron-going hadronic calorimeter
293  Smear::Device barrelAndHadronHcal("E", "sqrt(E)", Smear::kHadronic);
294  barrelAndHadronHcal.Accept.AddZone(barrelAndHadronDirection);
295  // Assume perfect theta and phi performance i.e. momentum resolution
296  // dominates over angular resolution
297  Smear::Device theta("theta", "0");
298  Smear::Device phi("phi", "0");
299  // PID performance is unparameterised as of now
301  // Combine the devices into a detector.
302  Smear::Detector ephenix;
303  ephenix.AddDevice(momentum);
304  ephenix.AddDevice(electronEcal);
305  ephenix.AddDevice(barrelAndHadronEcal);
306  ephenix.AddDevice(barrelAndHadronHcal);
307  ephenix.AddDevice(theta);
308  ephenix.AddDevice(phi);
309  ephenix.AddDevice(pid);
310  ephenix.SetEventKinematicsCalculator("NM JB DA");
311  return ephenix;
312 }
313 
314 /*
315  Here is the email from Sasha giving the calorimeter performances used above:
316 
317  From: Alexander Bazilevsky <shura@bnl.gov>
318  Subject: Re: a favour
319  Date: 26 December, 2013 1:47:19 PM EST
320  To: elke-caroline aschenauer <elke@bnl.gov>, Thomas P Burton <tpb@bnl.gov>
321 
322  Hello Elke, Thomas,
323 
324  Of course numbers are still drifting, but for now what you could use is roughly the following:
325 
326  EMCal sigma_E/E:
327  e-going direction: 1.5%/sqrt(E) \oplus 1%
328  h-going direction and barrel: 12%/sqrt(E) \oplus 2%
329 
330  HCal sigma_E/E:
331  h-going direction and barrel: 100%/sqrt(E)
332 
333  Tracking sigma_p/p:
334  is quite complicated: the linear term is in attached plot; we also calculated constant (multiple scattering) term from Geant, which appeared to vary from under 1% at eta~1 to 3% at eta~3 and to larger values (~10%) towards eta~4. I'll give you numerical parametrization one of the following days, as soon as I get them from the author of these calculations (Jin Huang).
335 
336  Regards,
337 
338  Sasha.
339 
340  --------------------------------------------------------------------------------
341 
342  Here is the email from Sasha giving the momentum resolution points used above:
343 
344  From: Alexander Bazilevsky <shura@bnl.gov>
345  Subject: Re: a favour
346  Date: 2 January, 2014 11:01:39 AM EST
347  To: elke-caroline aschenauer <elke@bnl.gov>, Thomas P Burton <tpb@bnl.gov>
348 
349  Hello Elke, Thomas,
350 
351  Ok, the linear term in momentum resolution (as in the plot I sent you before):
352 
353  eta d(1/p) in (1/GeV)
354  -3.0 0.010500
355  -2.9 0.009820
356  -2.8 0.009140
357  -2.7 0.008460
358  -2.6 0.007780
359  -2.5 0.007100
360  -2.4 0.006520
361  -2.3 0.005940
362  -2.2 0.005360
363  -2.1 0.004780
364  -2.0 0.004200
365 
366  -2.0 0.009811
367  -1.9 0.008759
368  -1.8 0.007479
369  -1.7 0.006242
370  -1.6 0.005436
371  -1.5 0.004524
372 
373  -1.5 0.006887
374  -1.4 0.005374
375  -1.3 0.004485
376  -1.2 0.003822
377  -1.1 0.003164
378  -1.0 0.002592
379  -0.9 0.002791
380  -0.8 0.002991
381  -0.7 0.003187
382  -0.6 0.003374
383  -0.5 0.003547
384  -0.4 0.003700
385  -0.3 0.003827
386  -0.2 0.003921
387  -0.1 0.003980
388  0.0 0.004000
389  0.1 0.003980
390  0.2 0.003921
391  0.3 0.003827
392  0.4 0.003700
393  0.5 0.003547
394  0.6 0.003374
395  0.7 0.003187
396  0.8 0.002991
397  0.9 0.002791
398  1.0 0.002592
399 
400  1.0 0.001200
401  1.1 0.001280
402  1.2 0.001360
403  1.3 0.001440
404  1.4 0.001520
405  1.5 0.001600
406  1.6 0.001840
407  1.7 0.002080
408  1.8 0.002320
409  1.9 0.002560
410  2.0 0.002800
411  2.1 0.003160
412  2.2 0.003520
413  2.3 0.003880
414  2.4 0.004240
415  2.5 0.004600
416 
417  2.5 0.002300
418  2.6 0.002620
419  2.7 0.002940
420  2.8 0.003260
421  2.9 0.003580
422  3.0 0.003900
423  3.1 0.004400
424  3.2 0.004900
425  3.3 0.005400
426  3.4 0.005900
427  3.5 0.006400
428  3.6 0.007220
429  3.7 0.008040
430  3.8 0.008860
431  3.9 0.009680
432  4.0 0.010500
433 
434  As for multiple scattering term, what has been simulated so far is eta ranges 2-3 and 3-4. Numbers keep changing after inclusion of different material (associated with detectors and read-out). The current very conservative advice is to use 3% for eta=2-3; in eta=3-4, log of this term changes ~linearly from 3% at eta=3 to ~15% at eta=4.
435 
436  That's what we have for now.
437 
438  Regards,
439 
440  Sasha.
441 */