Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
eic_sphenix_fill_xq2.C
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file eic_sphenix_fill_xq2.C
1 /* STL includes */
2 #include <iostream>
3 
4 /* ROOT includes */
5 #include <TROOT.h>
6 //#include <gSystem.h>
7 #include <TFile.h>
8 #include <TKey.h>
9 #include <TTree.h>
10 #include <TH2F.h>
11 #include <THnSparse.h>
12 
13 /* eicsmear includes */
14 #include <eicsmear/smear/EventSmear.h>
15 #include <eicsmear/erhic/EventPythia.h>
16 #include <eicsmear/erhic/ParticleMC.h>
17 
18 using namespace std;
19 
20 int
21 eic_sphenix_fill_xq2( TString filename_output,
22  TString filename_mc,
23  TString filename_mc_smeared,
24  bool debug = false )
25 {
26  /* Uncomment this line when running without compilation */
27  // gSystem->Load("libeicsmear");
28 
29  /* Selection cuts for scattered electron (after smearing) */
30  /* Minimum momentum: this makes sure the momentum was smeared, i.e. is within tracking acceptance */
31  double electron_pmin = 0.01; // GeV
32 
33  /* Minimumenergy: Acceptance cut for good electron/pion separation */
34  double electron_emin = 3.0; // GeV
35 
36  /* Open input files. */
37  TFile *file_mc = new TFile(filename_mc, "OPEN");
38  TFile *file_mc_smeared = new TFile(filename_mc_smeared, "OPEN");
39 
40  /* Get trees from files. */
41  TTree *tree = (TTree*)file_mc->Get("EICTree");
42  TTree *tree_smeared = (TTree*)file_mc_smeared->Get("Smeared");
43 
44 
45  /* Get event generator parameters (cross section, number of events, ...) from file. */
46  /* Input file may include multiple cross sections because it was merged from multiple files, so loop over all crossSection
47  objects and calculate average; same for sum of nEvents. */
48  double xsec = 0;
49  unsigned nxsec = 0;
50  int nevent = 0;
51  TIter next(file_mc->GetListOfKeys());
52  TKey *key;
53  while ((key = (TKey*)next()))
54  {
55  if ( TString(key->GetName()) == "crossSection" )
56  {
57  xsec += (TString(((TObjString*)key->ReadObj())->GetName())).Atof();
58  nxsec++;
59  continue;
60  }
61 
62  if ( TString(key->GetName()) == "nEvents" )
63  {
64  nevent += (TString(((TObjString*)key->ReadObj())->GetName())).Atof();
65  continue;
66  }
67  }
68 
69  /* Get average cross section per file */
70  if ( nxsec > 0 )
71  xsec /= nxsec;
72 
73  TObjString* gen_crossSection = (TObjString*)file_mc->Get("crossSection");
74  TObjString* gen_nEvents = (TObjString*)file_mc->Get("nEvents");
75 
76  /* Update strings with total values */
77  gen_crossSection->SetString( TString::Format("%f", xsec) );
78  gen_nEvents->SetString( TString::Format("%d", nevent) );
79 
80  /* Convert cross section from microbarn (10^-6) to femtobarn (10^-15) */
81  float xsec_fb = xsec * 1e9;
82 
83  /* Calculate integrated luminosity (inverse femtobarn) */
84  float lumi_ifb = (float)nevent / (float)xsec_fb;
85 
86  /* Add Luminosity strings */
87  TObjString* gen_lumi_ifb = new TObjString();
88  gen_lumi_ifb->SetString( TString::Format("%f", lumi_ifb) );
89 
90  /* Print parameters */
91  cout << "crossSection: " << gen_crossSection->GetName() << endl;
92  cout << "nEvents: " << gen_nEvents->GetName() << endl;
93  cout << "luminosity: " << gen_lumi_ifb->GetName() << endl;
94 
95  /* Output file. */
96  TFile *file_out = new TFile(filename_output, "RECREATE");
97 
98  /* Add friend to match branches in trees. */
99  tree->AddFriend(tree_smeared);
100 
101  erhic::EventPythia *event = NULL;
102  Smear::Event *eventS = NULL;
103 
104  tree->SetBranchAddress("event", &event);
105  tree->SetBranchAddress("eventS", &eventS);
106 
107  /* Create histogram for eta of particles to check acceptance of detectors. */
108  TH1F* h_eta = new TH1F("h_eta", ";#eta;dN/d#eta", 100, -5, 5);
109  TH1F* h_eta_accept = (TH1F*)h_eta->Clone("h_eta_accept");
110  h_eta_accept->SetLineColor(kGreen);
111 
112  /* Create n-dimensional histogram to collect statistic for DIS and SIDIS events in kinematics bins:
113  *
114  * Event properties:
115  * - x
116  * - Q2
117  *
118  * Particle properties:
119  * - z
120  * - pT
121  */
122 
123  /* Define bin ranges for DIS and SIDIS histograms */
124 
125  /* x */
126  const int nbins_x = 25; // 5 per decade
127 
128  double min_x = -5;
129  double max_x = 0;
130  double width_x = (max_x - min_x) / nbins_x;
131  double bins_x[nbins_x+1];
132  for( int i =0; i <= nbins_x; i++)
133  {
134  //cout << TMath::Power( 10, min_x + i*width_x) << endl;
135  bins_x[i] = TMath::Power( 10, min_x + i*width_x);
136  }
137 
138  /* Q2 */
139  const int nbins_Q2 = 20; // 4 per decade
140 
141  double min_Q2 = -1;
142  double max_Q2 = 4;
143  double width_Q2 = (max_Q2 - min_Q2) / nbins_Q2;
144  double bins_Q2[nbins_Q2+1];
145  for( int i =0; i <= nbins_Q2; i++)
146  bins_Q2[i] = TMath::Power( 10, min_Q2 + i*width_Q2);
147 
148  /* z */
149  const int nbins_z = 20;
150 
151  double min_z = 0.0;
152  double max_z = 1.0;
153  double width_z = (max_z - min_z) / nbins_z;
154  double bins_z[nbins_z+1];
155  for( int i =0; i <= nbins_z; i++)
156  {
157  //cout << min_z + i*width_z << endl;
158  bins_z[i] = min_z + i*width_z;
159  }
160 
161  /* pT */
162  const int nbins_pT1 = 5;
163  const int nbins_pT2 = 4;
164  const int nbins_pT = nbins_pT1 + nbins_pT2;
165 
166  double min_pT = 0.0;
167  double width_pT1 = 0.2;
168  double width_pT2 = 1.0;
169 
170  double bins_pT[nbins_pT+1];
171  for( int i =0; i <= nbins_pT1; i++)
172  {
173  //cout << min_pT + i*width_pT1 << endl;
174  bins_pT[i] = min_pT + i*width_pT1;
175  }
176  for( int i =1; i <= nbins_pT2; i++)
177  {
178  //cout << min_pT + nbins_pT1*width_pT1 + i*width_pT2<< endl;
179  bins_pT[nbins_pT1 + i] = min_pT + nbins_pT1*width_pT1 + i*width_pT2;
180  }
181 
182 
183  /* Create DIS histogram- one entry per event */
184  const int hn_dis_ndim = 2;
185  int hn_dis_nbins[] = { nbins_x,
186  nbins_Q2 };
187  double hn_dis_xmin[] = {0., 0. };
188  double hn_dis_xmax[] = {0., 0. };
189 
190  THnSparse* hn_dis = new THnSparseF("hn_dis_electron",
191  "DIS Kinematis Per Event (Electron); x; Q2;",
192  hn_dis_ndim,
193  hn_dis_nbins,
194  hn_dis_xmin,
195  hn_dis_xmax );
196 
197  hn_dis->GetAxis(0)->SetName("x");
198  hn_dis->GetAxis(1)->SetName("Q2");
199 
200  hn_dis->SetBinEdges(0,bins_x);
201  hn_dis->SetBinEdges(1,bins_Q2);
202 
203  /* clone histogram for ACCEPTED events */
204  THnSparse* hn_dis_accept = (THnSparse*)hn_dis->Clone("hn_dis_electron_accept");
205  hn_dis_accept->SetTitle("DIS Kinematis Per Event (Accepted)");
206 
207  /* Create SIDIS histogram- one entry per particle */
208  const int hn_sidis_ndim = 4;
209  int hn_sidis_nbins[] = { nbins_x,
210  nbins_Q2,
211  nbins_z,
212  nbins_pT };
213  double hn_sidis_xmin[] = {0., 0., 0., 0. };
214  double hn_sidis_xmax[] = {0., 0., 0., 0. };
215 
216  THnSparse* hn_sidis_pion_plus = new THnSparseF("hn_sidis_pion_plus",
217  "SIDIS Kinematis Per Particle (Postitively Charged Pion);x;Q2;z;pT;",
218  hn_sidis_ndim,
219  hn_sidis_nbins,
220  hn_sidis_xmin,
221  hn_sidis_xmax );
222 
223  hn_sidis_pion_plus->GetAxis(0)->SetName("x");
224  hn_sidis_pion_plus->GetAxis(1)->SetName("Q2");
225  hn_sidis_pion_plus->GetAxis(2)->SetName("z");
226  hn_sidis_pion_plus->GetAxis(3)->SetName("pT");
227 
228  /* Set logarithmic bin ranges. */
229  hn_sidis_pion_plus->SetBinEdges(0,bins_x);
230  hn_sidis_pion_plus->SetBinEdges(1,bins_Q2);
231  hn_sidis_pion_plus->SetBinEdges(2,bins_z);
232  hn_sidis_pion_plus->SetBinEdges(3,bins_pT);
233 
234  /* clone SIDIS histogram for other particle identities */
235  THnSparse* hn_sidis_pion_minus = (THnSparseF*)hn_sidis_pion_plus->Clone("hn_sidis_pion_minus");
236  hn_sidis_pion_minus->SetTitle("SIDIS Kinematis Per Particle (Negatively Charged Pion)");
237 
238  THnSparse* hn_sidis_kaon_plus = (THnSparseF*)hn_sidis_pion_plus->Clone("hn_sidis_kaon_plus");
239  hn_sidis_kaon_plus->SetTitle("SIDIS Kinematis Per Particle (Positively Charged Kaon)");
240 
241  THnSparse* hn_sidis_kaon_minus = (THnSparseF*)hn_sidis_pion_plus->Clone("hn_sidis_kaon_minus");
242  hn_sidis_kaon_minus->SetTitle("SIDIS Kinematis Per Particle (Negatively Charged Kaon)");
243 
244  /* clone histogram for ACCEPTED events */
245  THnSparse* hn_sidis_pion_plus_accept = (THnSparse*)hn_sidis_pion_plus->Clone("hn_sidis_pion_plus_accept");
246  hn_sidis_pion_plus_accept->SetTitle("SIDIS Kinematis Per Particle (Positively Charged Pion, Accepted)");
247 
248  THnSparse* hn_sidis_pion_minus_accept = (THnSparseF*)hn_sidis_pion_plus->Clone("hn_sidis_pion_minus_accept");
249  hn_sidis_pion_minus_accept->SetTitle("SIDIS Kinematis Per Particle (Negatively Charged Pion, Accepted)");
250 
251  THnSparse* hn_sidis_kaon_plus_accept = (THnSparseF*)hn_sidis_pion_plus->Clone("hn_sidis_kaon_plus_accept");
252  hn_sidis_kaon_plus_accept->SetTitle("SIDIS Kinematis Per Particle (Positively Charged Kaon, Accepted)");
253 
254  THnSparse* hn_sidis_kaon_minus_accept = (THnSparseF*)hn_sidis_pion_plus->Clone("hn_sidis_kaon_minus_accept");
255  hn_sidis_kaon_minus_accept->SetTitle("SIDIS Kinematis Per Particle (Negatively Charged Kaon, Accepted)");
256 
257  /* print all bin centers for x bins */
258  TH2F* hxQ2 = (TH2F*)hn_dis->Projection(1,0);
259 
260  /* Two alternative to determine bin center- which one is the CORRECT on a log scale axis?? */
261  //for ( int bin_x = 1; bin_x <= hxQ2->GetNbinsX(); bin_x++ )
262  // {
263  // /* Option 1 matches eRHIC high energy document Fig 11 */
264  // fprintf( stdout, "xC = %.2e\n",
265  // hxQ2->GetXaxis()->GetBinCenter(bin_x) );
266  // }
267 
268  /* Option 2 matches HERA table */
269  if ( debug )
270  {
271  for ( int bin_x = 1; bin_x <= hxQ2->GetNbinsX(); bin_x++ )
272  {
273  fprintf( stdout, "x = %.2e\n",
274  TMath::Power(10, 0.5 * ( ( TMath::Log10( hxQ2->GetXaxis()->GetBinLowEdge(bin_x) ) )
275  + ( TMath::Log10( hxQ2->GetXaxis()->GetBinLowEdge(bin_x) + hxQ2->GetXaxis()->GetBinWidth(bin_x) ) ) ) ) );
276  }
277  }
278 
279  /* print bin centers for Q2 bins */
280  if ( debug )
281  {
282  for ( int bin_Q2 = 1; bin_Q2 <= hxQ2->GetNbinsY(); bin_Q2++ )
283  {
284 
285  fprintf( stdout, "Q2 = %.2e\n",
286  TMath::Power(10, 0.5 * ( ( TMath::Log10( hxQ2->GetYaxis()->GetBinLowEdge(bin_Q2) ) )
287  + ( TMath::Log10( hxQ2->GetYaxis()->GetBinLowEdge(bin_Q2) + hxQ2->GetYaxis()->GetBinWidth(bin_Q2) ) ) ) ) );
288  }
289  }
290 
291  /* Loop over all events in tree. */
292  unsigned max_event = tree->GetEntries();
293 
294  if ( debug )
295  max_event = 10000;
296 
297  for ( unsigned ievent = 0; ievent < max_event; ievent++ )
298  {
299  if ( ievent%1000 == 0 )
300  cout << "Processing event " << ievent << endl;
301 
302  /* load event */
303  tree->GetEntry(ievent);
304 
305  /* Cut on EVENT kinematics */
306  float y = event->GetTrueY();
307  if ( y > 0.95 || y < 0.01 )
308  continue;
309 
310  float x = event->GetTrueX();
311  float Q2 = event->GetTrueQ2();
312 
313  double fill_hn_dis[] = {x, Q2};
314  hn_dis->Fill( fill_hn_dis );
315 
316  /* Scattered lepton found within acceptance of traacking system (= valid smeared momentum P)? */
317  bool electron_detected = false;
318  if ( eventS->ScatteredLepton() && eventS->ScatteredLepton()->GetP() > electron_pmin && eventS->ScatteredLepton()->GetE() > electron_emin )
319  electron_detected = true;
320 
321  /* Continue if electron not detected */
322  if ( !electron_detected )
323  continue;
324 
325  /* execute the part below only if scattered electron within acceptance */
326  hn_dis_accept->Fill( fill_hn_dis );
327 
328 
329  /* For SIDIS: Loop over all final state particles in this event */
330  unsigned ntracks = event->GetNTracks();
331 
332  for ( unsigned itrack = 0; itrack < ntracks; itrack++ )
333  {
334  erhic::ParticleMC * iparticle = event->GetTrack( itrack );
335  Smear::ParticleMCS * ismeared = eventS->GetTrack( itrack );
336 
337  /* Check status */
338  if ( iparticle->GetStatus() != 1 )
339  continue;
340 
341  /* Get z of particle */
342  float z = iparticle->GetZ();
343 
344  /* skip low z paricles- soft physics and beam remnants */
345  if ( z <= 0.15 )
346  continue;
347 
348  /* skip particles outside +/- 4 pseudorapidity */
349  if ( iparticle->GetEta() < -4 || iparticle->GetEta() > 4 )
350  continue;
351 
352  /* Get pT of particle w.r.t. exchange boson of interaction */
353  float pT = iparticle->GetPtVsGamma();
354 
355  /* Prepare array to fill histogram */
356  double fill_hn_sidis[] = {x, Q2, z, pT};
357 
358  /* get TRUE pid */
359  int pid = iparticle->Id().Code();
360  //TParticlePDG *pid_pdg = iparticle->Id().Info();
361 
362  /* Use true PID to choose which histogram to fill */
363  /* Pi+ */
364  if ( pid == 211 )
365  {
366  hn_sidis_pion_plus->Fill( fill_hn_sidis );
367 
368  if ( ismeared->GetP() > 0.1 && ismeared->Id().Code() == 211 )
369  hn_sidis_pion_plus_accept->Fill( fill_hn_sidis );
370  }
371 
372  /* Pi - */
373  else if ( pid == -211 )
374  {
375  hn_sidis_pion_minus->Fill( fill_hn_sidis );
376 
377  if ( ismeared->GetP() > 0.1 && ismeared->Id().Code() == -211 )
378  hn_sidis_pion_minus_accept->Fill( fill_hn_sidis );
379  }
380 
381  /* K+ */
382  else if ( pid == 321 )
383  {
384  hn_sidis_kaon_plus->Fill( fill_hn_sidis );
385 
386  if ( ismeared->GetP() > 0.1 && ismeared->Id().Code() == 321 )
387  hn_sidis_kaon_plus_accept->Fill( fill_hn_sidis );
388  }
389 
390  /* K- */
391  else if ( pid == -321 )
392  {
393  hn_sidis_kaon_minus->Fill( fill_hn_sidis );
394 
395  if ( ismeared->GetP() > 0.1 && ismeared->Id().Code() == -321 )
396  hn_sidis_kaon_minus_accept->Fill( fill_hn_sidis );
397  }
398  } // end loop over particles
399 
400  } // end loop over events
401 
402  /* Write histogram. */
403  hn_dis->Write();
404 
405  hn_dis_accept->Write();
406 
407  hn_sidis_pion_plus->Write();
408  hn_sidis_pion_minus->Write();
409  hn_sidis_kaon_plus->Write();
410  hn_sidis_kaon_minus->Write();
411 
412  hn_sidis_pion_plus_accept->Write();
413  hn_sidis_pion_minus_accept->Write();
414  hn_sidis_kaon_plus_accept->Write();
415  hn_sidis_kaon_minus_accept->Write();
416 
417  h_eta->Write();
418  h_eta_accept->Write();
419 
420  gen_crossSection->Write("crossSection");
421  gen_nEvents->Write("nEvents");
422  //gen_nTrials->Write("nTrials");
423  gen_lumi_ifb->Write("luminosity");
424 
425  /* Close output file. */
426  file_out->Close();
427 
428  return 0;
429 }
430 
431 
432 /* MAIN function */
433 int main( int argc , char* argv[] )
434 {
435  if ( argc < 4 || argc > 5 )
436  {
437  cout << "Usage: " << argv[0] << " <filename_output> <filename_EICTree> <filename_EICTree_smeared> <optional: 'debug' for debug mode" << endl;
438  return 1;
439  }
440 
441  cout << "Running eic_sphenix_fill_xq2 with: \n" << endl;
442  cout << " - Output file: " << argv[1] << endl;
443  cout << " - EICTree input file: " << argv[2] << endl;
444 
445  if ( argc == 4 )
446  {
447  cout << " - EICTree (smeared) file: " << argv[3] << endl;
448  eic_sphenix_fill_xq2( argv[1], argv[2], argv[3] );
449  }
450  else if ( argc == 5 )
451  {
452  cout << " - EICTree (smeared) file: " << argv[3] << endl;
453  cout << " ==== DEBUG MODE ==== " << endl;
454  eic_sphenix_fill_xq2( argv[1], argv[2], argv[3], true );
455  }
456 
457  return 0;
458 }