Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MBDStudy.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file MBDStudy.cc
1 #include "MBDStudy.h"
2 
3 #include <phool/phool.h>
4 #include <phool/getClass.h>
7 #include <g4main/PHG4Particle.h>
8 #include <g4main/PHG4Hit.h>
9 #include <g4main/PHG4VtxPoint.h>
10 #include <fun4all/PHTFileServer.h>
11 #include <fun4all/Fun4AllServer.h>
13 #include <mbd/MbdOut.h>
14 
15 #include <TFile.h>
16 #include <TTree.h>
17 #include <TH1F.h>
18 #include <TH2F.h>
19 #include <TF1.h>
20 #include <TCanvas.h>
21 #include <TString.h>
22 #include <TLorentzVector.h>
23 //#include <TMath.h>
24 #include <TDatabasePDG.h>
25 #include <TRandom3.h>
26 #include <TSystem.h>
27 
28 
29 #include <iostream>
30 #include <cmath>
31 
32 using namespace std;
33 
34 const Double_t index_refract = 1.4585;
35 const Double_t v_ckov = 1.0/index_refract; // velocity threshold for CKOV
36 const Double_t C = 29.9792458; // cm/ns
37 
38 // kludge where we have the hardcoded positions of the tubes
39 // These are the x,y for the south MBD (in cm).
40 // The north inverts the x coordinate (x -> -x)
41 const float TubeLoc[64][2] = {
42  { -12.2976, 4.26 },
43  { -12.2976, 1.42 },
44  { -9.83805, 8.52 },
45  { -9.83805, 5.68 },
46  { -9.83805, 2.84 },
47  { -7.37854, 9.94 },
48  { -7.37854, 7.1 },
49  { -7.37854, 4.26 },
50  { -7.37854, 1.42 },
51  { -4.91902, 11.36 },
52  { -4.91902, 8.52 },
53  { -4.91902, 5.68 },
54  { -2.45951, 12.78 },
55  { -2.45951, 9.94 },
56  { -2.45951, 7.1 },
57  { 0, 11.36 },
58  { 0, 8.52 },
59  { 2.45951, 12.78 },
60  { 2.45951, 9.94 },
61  { 2.45951, 7.1 },
62  { 4.91902, 11.36 },
63  { 4.91902, 8.52 },
64  { 4.91902, 5.68 },
65  { 7.37854, 9.94 },
66  { 7.37854, 7.1 },
67  { 7.37854, 4.26 },
68  { 7.37854, 1.42 },
69  { 9.83805, 8.52 },
70  { 9.83805, 5.68 },
71  { 9.83805, 2.84 },
72  { 12.2976, 4.26 },
73  { 12.2976, 1.42 },
74  { 12.2976, -4.26 },
75  { 12.2976, -1.42 },
76  { 9.83805, -8.52 },
77  { 9.83805, -5.68 },
78  { 9.83805, -2.84 },
79  { 7.37854, -9.94 },
80  { 7.37854, -7.1 },
81  { 7.37854, -4.26 },
82  { 7.37854, -1.42 },
83  { 4.91902, -11.36 },
84  { 4.91902, -8.52 },
85  { 4.91902, -5.68 },
86  { 2.45951, -12.78 },
87  { 2.45951, -9.94 },
88  { 2.45951, -7.1 },
89  { 0, -11.36 },
90  { 0, -8.52 },
91  { -2.45951, -12.78 },
92  { -2.45951, -9.94 },
93  { -2.45951, -7.1 },
94  { -4.91902, -11.36 },
95  { -4.91902, -8.52 },
96  { -4.91902, -5.68 },
97  { -7.37854, -9.94 },
98  { -7.37854, -7.1 },
99  { -7.37854, -4.26 },
100  { -7.37854, -1.42 },
101  { -9.83805, -8.52 },
102  { -9.83805, -5.68 },
103  { -9.83805, -2.84 },
104  { -12.2976, -4.26 },
105  { -12.2976, -1.42 }
106 };
107 
108 
109 
110 //____________________________________
111 MBDStudy::MBDStudy(const string &name) : SubsysReco(name),
112  _tree( 0 ),
113  f_evt( 0 ),
114  _pdg( 0 ),
115  _rndm( 0 ),
116  _tres( 0.05 ),
117  _savefname( "mbdstudy.root" ),
118  _savefile( 0 )
119 {
120 
121 }
122 
123 //___________________________________
125 {
126  cout << PHWHERE << " Saving to file " << _savefname << endl;
127  //PHTFileServer::get().open( _outfile, "RECREATE");
128  _savefile = new TFile( _savefname.c_str(), "RECREATE" );
129 
130  // Global MBD variables
131  _tree = new TTree("t","MBD Study");
132  _tree->Branch("evt",&f_evt,"evt/I");
133  _tree->Branch("bimp",&f_bimp,"bimp/F");
134  _tree->Branch("ncoll",&f_ncoll,"ncoll/I");
135  _tree->Branch("npart",&f_npart,"npart/I");
136  _tree->Branch("vx",&f_vx,"vx/F");
137  _tree->Branch("vy",&f_vy,"vy/F");
138  _tree->Branch("vz",&f_vz,"vz/F");
139  _tree->Branch("bns",&f_mbdn[0],"bns/S");
140  _tree->Branch("bnn",&f_mbdn[1],"bnn/S");
141  _tree->Branch("bqs",&f_mbdq[0],"bqs/F");
142  _tree->Branch("bqn",&f_mbdq[1],"bqn/F");
143  _tree->Branch("bts",&f_mbdt[0],"bts/F");
144  _tree->Branch("btn",&f_mbdt[1],"btn/F");
145  _tree->Branch("btes",&f_mbdte[0],"btes/F");
146  _tree->Branch("bten",&f_mbdte[1],"bten/F");
147  _tree->Branch("bz",&f_mbdz,"bz/F");
148  _tree->Branch("bt0",&f_mbdt0,"bt0/F");
149 
150  _pdg = TDatabasePDG::Instance(); // database of PDG info on particles
151  _rndm = new TRandom3(0);
152 
153  TString name, title;
154  for (int ipmt=0; ipmt<128; ipmt++)
155  {
156  name = "h_mbdq"; name += ipmt;
157  title = "mbd charge, ch "; title += ipmt;
158  h_mbdq[ipmt] = new TH1F(name,title,1200,0,120*90);
159 
160  /*
161  name = "h_tdiff_ch"; name += ipmt;
162  title = "tdiff, ch "; title += ipmt;
163  h_tdiff_ch[ipmt] = new TH1F(name,title,600,-3,3);
164  */
165  }
166 
167  for (int iarm=0; iarm<2; iarm++)
168  {
169  name = "h_mbdqtot"; name += iarm;
170  title = "mbd charge, arm "; title += iarm;
171  h_mbdqtot[iarm] = new TH1F(name,title,1200,0,120*60); // npe for 1 mip = 120, and up to 30 mips are possible
172 
173  //
174  name = "hevt_mbdt"; name += iarm;
175  title = "mbd times, arm "; title += iarm;
176  hevt_mbdt[iarm] = new TH1F(name,title,200,7.5,11.5);
177  hevt_mbdt[iarm]->SetLineColor(4);
178  }
179  h2_mbdqtot = new TH2F("h2_mbdqtot","north MBDQ vs South MBDQ",300,0,120*900,300,0,120*900);
180 
181  h_ztrue = new TH1F("h_ztrue","true z-vtx",600,-30,30);
182  h_tdiff = new TH1F("h_tdiff","dt (measured - true_time)",6000,-3,3);
183  h2_tdiff_ch = new TH2F("h2_tdiff_ch","dt (measured - true time) vs ch",128,-0.5,127.5,200,-2,2);
184 
185  gaussian = new TF1("gaussian","gaus",0,20);
186  gaussian->FixParameter(2,0.05); // set sigma to 50 ps
187 
188  c_mbdt = new TCanvas("c_mbdt","MBD Times",1200,800);
189  c_mbdt->Divide(1,2);
190 
191  return 0;
192 }
193 
194 //___________________________________
196 {
197  GetNodes(topNode);
198 
199  return 0;
200 }
201 
202 //__________________________________
203 //Call user instructions for every event
205 {
206  nprocessed++;
207 
208  //GetNodes(topNode);
209 
211  if(f_evt%1==0) cout << PHWHERE << "Event " << f_evt << "\t" << ", nprocessed = " << nprocessed << endl;
212 
213  // Initialize Variables
214  f_mbdn[0] = 0;
215  f_mbdn[1] = 0;
216  f_mbdq[0] = 0.;
217  f_mbdq[1] = 0.;
218  f_mbdt[0] = -9999.;
219  f_mbdt[1] = -9999.;
220  f_mbdte[0] = -9999.;
221  f_mbdte[1] = -9999.;
222  f_mbdz = NAN;
223  f_mbdt0 = NAN;
224  hevt_mbdt[0]->Reset();
225  hevt_mbdt[1]->Reset();
226 
227  // Get Truth Centrality Info
231 
232  // Get Primaries AND Secondaries
233  /*
234  PHG4TruthInfoContainer::ConstRange primary_range = _truth_container->GetPrimaryParticleRange();
235  int nprimaries = 0;
236 
237  for (auto part_iter = primary_range.first; part_iter != primary_range.second; ++part_iter)
238  {
239  PHG4Particle *particle = part_iter->second;
240  Float_t e = particle->get_e();
241  Float_t px = particle->get_px();
242  Float_t py = particle->get_py();
243  Float_t pz = particle->get_pz();
244  Float_t eta = 0.5*log((particle->get_e()+particle->get_pz())/ (particle->get_e()-particle->get_pz()));
245  Float_t pt = sqrt( px*px + py*py );
246  Float_t phi = atan2(particle->get_py(), particle->get_px());
247  Float_t pid = particle->get_pid();
248 
249  nprimaries++;
250  }
251  if ( f_evt < 20 )
252  {
253  cout << "Num primaries = " << nprimaries << "\t" << _truth_container->GetNumPrimaryVertexParticles() << endl;
254  }
255  */
256 
257 
258  // Get True Vertex
259  // NB: Currently PrimaryVertexIndex is always 1, need to figure out how to handle collision pile-up
261  if ( vtxp != 0 )
262  {
263  f_vx = vtxp->get_x();
264  f_vy = vtxp->get_y();
265  f_vz = vtxp->get_z();
266  f_vt = vtxp->get_t();
267 
268  if ( f_evt<20 )
269  {
270  cout << "VTXP " << "\t" << f_vx << "\t" << f_vy << "\t" << f_vz << "\t" << f_vt << endl;
271  }
272 
273  h_ztrue->Fill( f_vz );
274 
275  }
276 
277 
278  // Get All Vertices
280  unsigned int nvtx = 0;
281 
282  /*
283  for (auto vtx_iter = vtx_range.first; vtx_iter != vtx_range.second; ++vtx_iter)
284  {
285  PHG4VtxPoint *vtx = vtx_iter->second;
286  double vx = vtx->get_x();
287  double vy = vtx->get_y();
288  double vz = vtx->get_z();
289  double vt = vtx->get_t();
290 
291  // look at first few tracks
292  // What are negative track id's?
293  if ( abs(vtx->get_id()) < 8 && f_evt<20 )
294  {
295  cout << "vtx " << nvtx << "\t" << vtx->get_id() << "\t" << vt << "\t" << vx << "\t" << vy << "\t" << vz << endl;
296  }
297  nvtx++;
298  }
299  */
300 
301  if ( f_evt<20 )
302  {
303  cout << "Num Vertices = " << nvtx << "\t" << _truth_container->GetNumVertices() << endl;
304  //cout << "Primary Vertex = " << _truth_container->GetPrimaryVertexIndex() << endl;
305  }
306 
307  // Go through MBD hits to see what they look like
308 
309  float len[128] = {0.};
310  float edep[128] = {0.};
311  float first_time[128]; // First hit time for each tube
312  std::fill_n(first_time, 128, 1e12);
313 
314 
315  unsigned int nhits = 0;
316 
317  TLorentzVector v4;
318  //TLorentzVector hitpos;
319 
320  PHG4HitContainer::ConstRange mbd_hit_range = _mbdhits->getHits();
321  for (auto hit_iter = mbd_hit_range.first; hit_iter != mbd_hit_range.second; hit_iter++)
322  {
323  PHG4Hit *this_hit = hit_iter->second;
324 
325  unsigned int ch = this_hit->get_layer(); // pmt channel
326  int arm = ch/64;; // south=0, north=1
327 
328  int trkid = this_hit->get_trkid();
329  if ( trkid>0 && f_evt<20 ) cout << "TRKID " << trkid << endl;
330 
331  PHG4Particle *part = _truth_container->GetParticle( trkid );
332  v4.SetPxPyPzE( part->get_px(), part->get_py(), part->get_pz(), part->get_e() );
333 
334  int pid = part->get_pid();
335  TParticlePDG *partinfo = _pdg->GetParticle( pid );
336  Double_t charge = -9999.;
337  if ( partinfo )
338  {
339  charge = partinfo->Charge()/3; // PDG gives charge in 1/3 e
340  }
341  else if ( part->isIon() )
342  {
343  charge = part->get_IonCharge();
344  }
345 
346  Double_t beta = v4.Beta();
347 
348  // Determine time
349  //hitpos.SetXYZT( this_hit->get_x(), this_hit->get_y(), this_hit->get_z(), this_hit->get_t() );
350 
351  float xsign = 1.;
352  float zsign = -1.;
353  if ( arm == 1 )
354  {
355  xsign = -1.;
356  zsign = 1.;
357  }
358 
359  float tube_x = xsign*TubeLoc[ch%64][0];
360  float tube_y = TubeLoc[ch%64][1];
361  float tube_z = zsign*253.;
362  float flight_z = fabs(tube_z - vtxp->get_z());
363 
364  float flight_time = sqrt( tube_x*tube_x + tube_y*tube_y + flight_z*flight_z )/C;
365  float tdiff = this_hit->get_t(1) - ( vtxp->get_t() + flight_time );
366 
367  // get the first time
368  if ( this_hit->get_t(1) < first_time[ch] )
369  {
370  if ( fabs( this_hit->get_t(1) ) < 106.5 )
371  {
372  first_time[ch] = this_hit->get_t(1) - vtxp->get_t();
373  Float_t dt = static_cast<float>( _rndm->Gaus( 0, _tres ) ); // get fluctuation in time
374  first_time[ch] += dt;
375  }
376  else
377  {
378  cout << "BAD " << ch << "\t" << this_hit->get_t(1) << endl;
379  }
380  }
381 
382  if ( f_evt<10 )
383  {
384  cout << "hit " << ch << "\t" << trkid << "\t" << pid
385  //<< "\t" << v4.M()
386  << "\t" << beta
387  << "\t" << this_hit->get_path_length()
388  << "\t" << this_hit->get_edep()
389  //<< "\t" << v4.Eta()
390  //<< "\t" << v4.Pt()
391  //<< "\t" << v4.P()
392  << "\t" << this_hit->get_x(1)
393  << "\t" << this_hit->get_y(1)
394  << "\t" << this_hit->get_z(1)
395  << "\t" << this_hit->get_t(1)
396  << "\t" << tdiff
397  << endl;
398 
399  //cout << "WWW " << first_time[ch] << endl;
400  }
401 
402  edep[ch] += this_hit->get_edep();
403 
404  // get summed path length for particles that can create CKOV light
405  // n.p.e. is determined from path length
406  if ( beta > v_ckov && charge != 0. )
407  {
408  len[ch] += this_hit->get_path_length();
409 
410  if ( trkid>0 )
411  {
412  h_tdiff->Fill( tdiff );
413  h2_tdiff_ch->Fill( ch, tdiff );
414  }
415 
416  _pids[pid] += 1;
417  }
418 
419  // sanity check
420  if ( part->get_track_id() != trkid )
421  {
422  cout << "ERROR " << endl;
423  }
424 
425  nhits++;
426  }
427 
428  if ( f_evt<20 )
429  {
430  cout << "******** " << f_evt << " **************" << endl;
431  }
432 
433 
434  // process the data from each channel
435  for (int iarm=0; iarm<2; iarm++)
436  {
437  f_mbdt[iarm] = 0.;
438  }
439 
440  vector<float> hit_times[2]; // times of the hits in each [arm]
441 
442  for (int ich=0; ich<128; ich++)
443  {
444  //cout << "ZZZ " << ich << "\t" << first_time[ich] << "\t" << edep[ich] << "\t" << len[ich] << endl;
445 
446  int arm = ich/64; // ch 0-63 = south, ch 64-127 = north
447 
448  // Fill charge and time info
449  if ( len[ich]>0. )
450  {
451  if ( f_evt<20 )
452  {
453  cout << "ich " << ich << "\t" << len[ich] << "\t" << edep[ich] << endl;
454  }
455 
456  // Get charge in MBD tube
457  float npe = len[ich]*(120/3.0); // we get 120 p.e. per 3 cm
458  float dnpe = static_cast<float>( _rndm->Gaus( 0, sqrt(npe) ) ); // get fluctuation in npe
459 
460  npe += dnpe; // apply the fluctuations in npe
461 
462  f_mbdq[arm] += npe;
463 
464  h_mbdq[ich]->Fill( npe );
465  h_mbdqtot[arm]->Fill( npe );
466 
467  // Now time
468  if ( first_time[ich] < 9999. )
469  {
470  // Fill evt histogram
471  hevt_mbdt[arm]->Fill( first_time[ich] );
472  hit_times[arm].push_back( first_time[ich] );
473 
474  f_mbdt[arm] += first_time[ich];
475  //cout << "XXX " << ich << "\t" << f_mbdt[arm] << "\t" << first_time[ich] << endl;
476 
477  }
478  else // should never happen
479  {
480  cout << "ERROR, have hit but no time" << endl;
481  }
482 
483  // threshold should be > 0.
484  ++f_mbdn[arm];
485  }
486  }
487 
488  // Get best t
489  if ( f_mbdn[0]>0 && f_mbdn[1]> 0 )
490  {
491  for (int iarm=0; iarm<2; iarm++)
492  {
493  c_mbdt->cd(iarm+1);
494 
495  std::sort( hit_times[iarm].begin(), hit_times[iarm].end() );
496  float earliest = hit_times[iarm][0];
497 
498  gaussian->SetParameter(0,5);
499  gaussian->SetParameter(1, earliest);
500  gaussian->SetRange(6, earliest+ 5*0.05);
501  //gaussian->SetParameter(1,hevt_mbdt[iarm]->GetMean());
502  //gaussian->SetRange(6,hevt_mbdt[iarm]->GetMean()+0.125);
503 
504  hevt_mbdt[iarm]->Fit(gaussian,"BLR");
505  hevt_mbdt[iarm]->Draw();
506 
507  if ( f_mbdn[iarm] > 0 )
508  {
509  //f_mbdt[iarm] = f_mbdt[iarm] / f_mbdn[iarm];
510  f_mbdt[iarm] = gaussian->GetParameter(1);
511  f_mbdte[iarm] = earliest;
512  }
513  }
514 
515  // Now calculate zvtx, t0 from best times
516  f_mbdz = (f_mbdt[0] - f_mbdt[1])*C/2.0;
517  f_mbdt0 = (f_mbdt[0] + f_mbdt[1])/2.0;
518 
519  }
520 
521  c_mbdt->Modified();
522  c_mbdt->Update();
523 
524  if ( fabs(f_mbdz-f_vz)>5.0 && f_mbdn[0]>1 && f_mbdn[1]>1 )
525  {
526  string response;
527  cout << "Event " << f_evt << " ? ";
528  //cin >> response;
529  //if ( response[0] == 'q' )
530  TString name = "evt_"; name += f_evt; name += ".png";
531  c_mbdt->SaveAs( name );
532  }
533 
534  h2_mbdqtot->Fill( f_mbdq[0], f_mbdq[1] );
535 
536  _tree->Fill();
537 
538  //CheckDST(topNode);
539 
540  return 0;
541 }
542 
543 //___________________________________
545 {
546  // Get the DST objects
547 
548  // Truth container
549  _truth_container = findNode::getClass<PHG4TruthInfoContainer>(topNode, "G4TruthInfo");
550  if(!_truth_container && f_evt<10) cout << PHWHERE << " PHG4TruthInfoContainer node not found on node tree" << endl;
551 
552  // MBD hit container
553  _mbdhits = findNode::getClass<PHG4HitContainer> (topNode, "G4HIT_MBD");
554  if(!_mbdhits && f_evt<10) cout << PHWHERE << " G4HIT_MBD node not found on node tree" << endl;
555 
556  _evtheader = findNode::getClass<EventHeaderv1>(topNode, "EventHeader");
557  if (!_evtheader && f_evt<10) cout << PHWHERE << " G4HIT_MBD node not found on node tree" << endl;
558 
559 }
560 
561 //______________________________________
563 {
564  _savefile->cd();
565  _savefile->Write();
566  _savefile->Close();
567 
568  // print out list of pids that hit MBD
569  cout << "PIDs of Particles that hit MBD" << endl;
570  unsigned int ipid = 0;
571  double npart = 0;
572  for (auto & pid : _pids)
573  {
574  npart += pid.second;
575  }
576  for (auto & pid : _pids)
577  {
578  cout << pid.first << "\t" << pid.second << "\t" << pid.second/npart << endl;
579  ipid++;
580  }
581  cout << "There were " << ipid << " different particle types" << endl;
582 
583  return 0;
584 }
585 
587 {
588  // MbdOut
589  MbdOut *_mbdout = findNode::getClass<MbdOut>(topNode, "MbdOut");
590  if(!_mbdout && f_evt<10) cout << PHWHERE << " MbdOut node not found on node tree" << endl;
591 
592  Float_t mbdz = _mbdout->get_zvtx();
593  if ( f_mbdz != mbdz )
594  {
595  cout << "ERROR, f_mbdz != mbdz, " << f_mbdz << "\t" << mbdz << endl;
596  }
597 
598  for (int iarm=0; iarm<2; iarm++)
599  {
600  if ( f_mbdq[iarm] != _mbdout->get_q(iarm) )
601  {
602  cout << "ERROR, f_mbdq != mbdq, arm " << iarm << "\t" << f_mbdq[iarm] << "\t" << _mbdout->get_q(iarm) << endl;
603  }
604  }
605 
606 }