Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MbdDigitization.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file MbdDigitization.cc
1 #include "MbdDigitization.h"
2 
3 #include <mbd/MbdDefs.h>
5 #include <mbd/MbdPmtHit.h>
6 
7 #include <g4main/PHG4Hit.h>
9 #include <g4main/PHG4Particle.h>
11 #include <g4main/PHG4VtxPoint.h>
12 
13 #include <fun4all/Fun4AllServer.h>
14 #include <fun4all/PHTFileServer.h>
15 
16 #include <phool/PHCompositeNode.h>
17 #include <phool/PHIODataNode.h>
18 #include <phool/PHNode.h>
19 #include <phool/PHNodeIterator.h>
20 #include <phool/PHObject.h>
21 #include <phool/PHRandomSeed.h>
22 #include <phool/getClass.h>
23 #include <phool/phool.h>
24 
25 #include <TDatabasePDG.h>
26 #include <TF1.h>
27 #include <TFile.h>
28 #include <TH1F.h>
29 #include <TH2F.h>
30 #include <TLorentzVector.h>
31 #include <TString.h>
32 #include <TSystem.h>
33 #include <TTree.h>
34 
35 #include <gsl/gsl_randist.h>
36 #include <gsl/gsl_rng.h>
37 
38 #include <cmath>
39 #include <iostream>
40 
41 //____________________________________
43  : SubsysReco(name)
44  , _tres(0.05)
45 {
46  std::fill(std::begin(f_pmtq), std::end(f_pmtq), 0.);
47  std::fill(std::begin(f_pmtt0), std::end(f_pmtt0), std::numeric_limits<float>::quiet_NaN());
48  std::fill(std::begin(f_pmtt1), std::end(f_pmtt1), std::numeric_limits<float>::quiet_NaN());
49  m_RandomGenerator = gsl_rng_alloc(gsl_rng_mt19937);
50  m_Seed = PHRandomSeed(); // fixed seed is handled in this funtcion
52 }
53 
55 {
56  gsl_rng_free(m_RandomGenerator);
57  return;
58 }
59 
60 //___________________________________
62 {
63  if ( Verbosity() ) std::cout << PHWHERE << std::endl;
64  CreateNodes(topNode);
65 
66  _pdg = new TDatabasePDG(); // database of PDG info on particles
67 
68  gaussian = new TF1("gaussian", "gaus", 0, 20);
69  gaussian->FixParameter(2, _tres); // set sigma to timing resolution
70 
71  return 0;
72 }
73 
74 //___________________________________
76 {
77  GetNodes(topNode);
78 
79  return 0;
80 }
81 
82 //__________________________________
83 // Call user instructions for every event
85 {
86  if ( Verbosity() ) std::cout << PHWHERE << std::endl;
87  //**** Initialize Variables
88 
89  // PMT data
90  float len[MbdDefs::MBD_N_PMT] = {0.};
91  float edep[MbdDefs::MBD_N_PMT] = {0.};
92  float first_time[MbdDefs::MBD_N_PMT]; // First hit time for each tube
93  std::fill_n(first_time, MbdDefs::MBD_N_PMT, 1e12);
94  std::fill_n(f_pmtt0, MbdDefs::MBD_N_PMT, 1e12);
95  std::fill_n(f_pmtt1, MbdDefs::MBD_N_PMT, 1e12);
96  std::fill_n(f_pmtq, MbdDefs::MBD_N_PMT, 0.);
97 
98  // Get True Vertex
99  // NB: Currently PrimaryVertexIndex is always 1, need to figure out how to handle collision pile-up
101  if (vtxp != nullptr)
102  {
103  f_vx = vtxp->get_x();
104  f_vy = vtxp->get_y();
105  f_vz = vtxp->get_z();
106  f_vt = vtxp->get_t();
107 
108  if (Verbosity())
109  {
110  std::cout << "VTXP "
111  << "\t" << f_vx << "\t" << f_vy << "\t" << f_vz << "\t" << f_vt << std::endl;
112  }
113  }
114 
115  // Go through BBC G4 hits
116  if ( Verbosity()>10 ) std::cout << "Processing BBC G4 Hits" << std::endl;
117 
118  TLorentzVector v4;
119  unsigned int nhits = 0;
120 
121  PHG4HitContainer::ConstRange bbc_hit_range = _bbchits->getHits();
122  for (auto hit_iter = bbc_hit_range.first; hit_iter != bbc_hit_range.second; hit_iter++)
123  {
124  PHG4Hit *this_hit = hit_iter->second;
125 
126  unsigned int ch = this_hit->get_layer(); // pmt channel
127  // int arm = ch/64;; // south=0, north=1
128 
129  int trkid = this_hit->get_trkid();
130  // if ( trkid>0 && f_evt<20 ) std::cout << "TRKID " << trkid << std::endl;
131 
132  PHG4Particle *part = _truth_container->GetParticle(trkid);
133  v4.SetPxPyPzE(part->get_px(), part->get_py(), part->get_pz(), part->get_e());
134 
135  int pid = part->get_pid();
136  TParticlePDG *partinfo = _pdg->GetParticle(pid);
137  Double_t charge = -9999.;
138  if (partinfo)
139  {
140  charge = partinfo->Charge() / 3; // PDG gives charge in 1/3 e
141  }
142  else if (part->isIon())
143  {
144  charge = part->get_IonCharge();
145  }
146 
147  // get the first time
148  if (this_hit->get_t(1) < first_time[ch])
149  {
150  if (fabs(this_hit->get_t(1)) < 106.5)
151  {
152  first_time[ch] = this_hit->get_t(1) - vtxp->get_t();
153  Float_t dt = gsl_ran_gaussian(m_RandomGenerator, _tres); // get fluctuation in time
154  first_time[ch] += dt;
155  }
156  else
157  {
158  if (Verbosity())
159  {
160  std::cout << "BAD " << ch << "\t" << this_hit->get_t(1) << std::endl;
161  }
162  }
163  }
164 
165  edep[ch] += this_hit->get_edep();
166 
167  // get summed path length for particles that can create CKOV light
168  // n.p.e. is determined from path length
169  Double_t beta = v4.Beta();
170  if (beta > MbdDefs::v_ckov && charge != 0.)
171  {
172  len[ch] += this_hit->get_path_length();
173 
174  _pids[pid] += 1;
175  }
176 
177  nhits++;
178  }
179 
180  if ( Verbosity()>10 )
181  {
182  std::cout << "Found " << nhits << " MBD hits" << std::endl;
183  std::cout << "Calculating response and storing in MbdPmtHits" << std::endl;
184  }
185 
186  for (int ipmt = 0; ipmt < MbdDefs::MBD_N_PMT; ipmt++)
187  {
188  // Fill charge and time info
189  if (len[ipmt] > 0.)
190  {
191  if (Verbosity() > 0)
192  {
193  std::cout << "ipmt " << ipmt << "\t" << len[ipmt] << "\t" << edep[ipmt] << std::endl;
194  }
195 
196  // Get charge in BBC tube
197  float npe = len[ipmt] * (120 / 3.0); // we get 120 p.e. per 3 cm
198  float dnpe = gsl_ran_gaussian(m_RandomGenerator, std::sqrt(npe)); // get fluctuation in npe
199 
200  npe += dnpe; // apply the fluctuations in npe
201  f_pmtq[ipmt] = npe;
202 
203  // Now time
204  if (first_time[ipmt] < 9999.)
205  {
206  f_pmtt0[ipmt] = first_time[ipmt] - 8.346;
207  f_pmtt1[ipmt] = first_time[ipmt] - 8.346;
208  }
209  else // should never happen
210  {
211  if (Verbosity() != 0)
212  {
213  std::cout << "ERROR, have hit but no time" << std::endl;
214  }
215  }
216 
217  _bbcpmts->get_pmt(ipmt)->set_pmt(ipmt, f_pmtq[ipmt], f_pmtt0[ipmt], f_pmtt1[ipmt]);
218 
219  if (Verbosity() > 0)
220  {
221  std::cout << "Adding " << ipmt << ", " << f_pmtq[ipmt] << ", " << f_pmtt0[ipmt] << " , " << f_pmtt1[ipmt] << std::endl;
222  }
223  }
224  else
225  {
226  // empty channel
227  _bbcpmts->get_pmt(ipmt)->set_pmt(ipmt, f_pmtq[ipmt], f_pmtt0[ipmt], f_pmtt1[ipmt]);
228  }
229  }
230 
231  return 0;
232 }
233 
235 {
236  PHNodeIterator iter(topNode);
237  PHCompositeNode *dstNode = dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "DST"));
238  if (!dstNode)
239  {
240  std::cout << PHWHERE << "DST Node missing doing nothing" << std::endl;
241  gSystem->Exit(1);
242  exit(1);
243  }
244 
245  PHCompositeNode *bbcNode = dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "MBD"));
246  if (!bbcNode)
247  {
248  bbcNode = new PHCompositeNode("MBD");
249  dstNode->addNode(bbcNode);
250  }
251 
252  //-* contains info for each pmt (nmips, time, etc)
253  _bbcpmts = findNode::getClass<MbdPmtContainer>(bbcNode, "MbdPmtContainer");
254  if (!_bbcpmts)
255  {
256  _bbcpmts = new MbdPmtContainerV1();
257  PHIODataNode<PHObject> *BbcPmtNode = new PHIODataNode<PHObject>(_bbcpmts, "MbdPmtContainer", "PHObject");
258  bbcNode->addNode(BbcPmtNode);
259  }
260 }
261 
262 //___________________________________
264 {
265  // Get the DST objects
266 
267  // Truth container
268  _truth_container = findNode::getClass<PHG4TruthInfoContainer>(topNode, "G4TruthInfo");
269  if (!_truth_container)
270  {
271  std::cout << PHWHERE << " PHG4TruthInfoContainer node not found on node tree" << std::endl;
272  gSystem->Exit(1);
273  }
274 
275  // BBC hit container
276  _bbchits = findNode::getClass<PHG4HitContainer>(topNode, "G4HIT_BBC");
277  if (!_bbchits)
278  {
279  std::cout << PHWHERE << " G4HIT_BBC node not found on node tree" << std::endl;
280  gSystem->Exit(1);
281  }
282 
285  // MbdPmtContainer
286  _bbcpmts = findNode::getClass<MbdPmtContainerV1>(topNode, "MbdPmtContainer");
287  if (!_bbcpmts)
288  {
289  std::cout << PHWHERE << " MbdPmtContainer node not found on node tree" << std::endl;
290  gSystem->Exit(1);
291  }
292 }