Belle II Software  release-08-01-10
TpcDigitizerModule.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 
9 #include <beast/microtpc/modules/TpcDigitizerModule.h>
10 #include <beast/microtpc/dataobjects/MicrotpcSimHit.h>
11 
12 #include <mdst/dataobjects/MCParticle.h>
13 #include <framework/logging/Logger.h>
14 #include <framework/gearbox/GearDir.h>
15 #include <framework/gearbox/Const.h>
16 #include <framework/core/RandomNumbers.h>
17 
18 //c++
19 #include <cmath>
20 #include <boost/foreach.hpp>
21 #include <vector>
22 
23 using namespace Belle2;
24 using namespace microtpc;
25 
26 
27 //-----------------------------------------------------------------
28 // Register the Module
29 //-----------------------------------------------------------------
30 REG_MODULE(TpcDigitizer);
31 
32 //-----------------------------------------------------------------
33 // Implementation
34 //-----------------------------------------------------------------
35 
37 {
38  // Set module properties
39  setDescription("Microtpc digitizer module");
40 
41  //Default values are set here. New values can be in MICROTPC.xml.
42  addParam("LowerTimingCut", m_lowerTimingCut, "Lower timing cut", 0.);
43  addParam("UpperTimingCut", m_upperTimingCut, "Upper timing cut", 1000000.);
44 }
45 
46 TpcDigitizerModule::~TpcDigitizerModule()
47 {
48 }
49 
51 {
52  B2INFO("TpcDigitizer: Initializing");
53  m_microtpcHit.registerInDataStore();
54 
55  //get xml data
56  getXMLData();
57 
58  //converter: electron number to TOT part I
59  fctToT_Calib1 = new TF1("fctToT_Calib1", "[0]*(x/[3]+[1])/(x/[3]+[2])", 0., 100000.);
60  fctToT_Calib1->SetParameters(m_TOTA1, m_TOTB1, m_TOTC1, m_TOTQ1);
61  //converter: electron number to TOT part II
62  fctToT_Calib2 = new TF1("fctToT_Calib2", "[0]*(x/[3]+[1])/(x/[3]+[2])", 0., 100000.);
63  fctToT_Calib2->SetParameters(m_TOTA2, m_TOTB2, m_TOTC2, m_TOTQ2);
64  /*
65  for (int i = 0; i < m_nTPC; i++) {
66  for (int j = 0; j < 80; j++) {
67  for (int k = 0; k < 336; k++) {
68  for (int l = 0; l < MAXtSIZE; l++) {
69  m_dchip[i][j][k][l] = 0;
70  //dchip[j][k][l] = 0;
71  }
72  }
73  }
74  }
75  */
76 }
77 
79 {
80 }
81 
83 {
84  StoreArray<MCParticle> mcParticles;
85  StoreArray<MicrotpcSimHit> microtpcSimHits;
86 
87  m_dchip_map.clear();
88  m_dchip.clear();
89  m_dchip_detNb_map.clear();
90  m_dchip_pdg_map.clear();
91  m_dchip_trkID_map.clear();
92 
93  std::vector<double> T0(m_nTPC,
94  m_upperTimingCut); // TODO: why this number? Maybe pick something larger the the upperTiming cut? e.g. m_upperTimingCut + 1
95  //std::vector<bool> PixelFired(m_nTPC, false);
96 
97  for (const auto& microtpcSimHit : microtpcSimHits) {
98  const int detNb = microtpcSimHit.getdetNb();
99  const TVector3 simHitPosition = microtpcSimHit.gettkPos();
100  TVector3 chipPosition(
101  simHitPosition.X() / 100. - m_TPCCenter[detNb].X(),
102  simHitPosition.Y() / 100. - m_TPCCenter[detNb].Y(),
103  simHitPosition.Z() / 100. - m_TPCCenter[detNb].Z()
104  );
105  chipPosition.RotateZ(-m_TPCAngleZ[detNb] * TMath::DegToRad());
106  chipPosition.RotateX(-m_TPCAngleX[detNb] * TMath::DegToRad());
107  const double T = chipPosition.Z() + m_z_DG / 2.;
108  if (T < T0[detNb]) {
109  T0[detNb] = T;
110  }
111  }
112 
113  for (auto& val : T0) {
114  if (m_lowerTimingCut < val && val < m_upperTimingCut) {
115  val = val / m_v_DG;
116  } else {
117  val = -1.;
118  }
119  }
120  olddetNb = -1;
121  oldtrkID = -1;
122  //loop on all entries to store in 3D the ionization for each TPC
123  for (const auto& microtpcSimHit : microtpcSimHits) {
124 
125  const int PDGid = microtpcSimHit.gettkPDG();
126  if (m_LookAtRec == 1) {
127  if (PDGid != 1000020040 && PDGid != 1000060120 && PDGid != 1000080160 && PDGid != Const::proton.getPDGCode()) {
128  continue;
129  }
130  }
131 
132  const int detNb = microtpcSimHit.getdetNb();
133  const double edep = microtpcSimHit.getEnergyDep();
134  const double niel = microtpcSimHit.getEnergyNiel();
135  const int pdg = microtpcSimHit.gettkPDG();
136  const int trkID = microtpcSimHit.gettkID();
137 
138  const TVector3 simHitPosition = microtpcSimHit.gettkPos();
139  TVector3 chipPosition(
140  simHitPosition.X() / 100. - m_TPCCenter[detNb].X(),
141  simHitPosition.Y() / 100. - m_TPCCenter[detNb].Y(),
142  simHitPosition.Z() / 100. - m_TPCCenter[detNb].Z()
143  );
144  chipPosition.RotateZ(-m_TPCAngleZ[detNb] * TMath::DegToRad());
145  chipPosition.RotateX(-m_TPCAngleX[detNb] * TMath::DegToRad());
146 
147  TVector3 ChipPosition(0, 0, 0);
148  if (m_phase == 1) {
149  if (detNb == 0 || detNb == 3) {
150  ChipPosition.SetX(-chipPosition.Y());
151  ChipPosition.SetY(-chipPosition.X());
152  ChipPosition.SetZ(chipPosition.Z() + m_z_DG / 2.);
153  }
154  if (detNb == 1 || detNb == 2) {
155  ChipPosition.SetX(chipPosition.Y());
156  ChipPosition.SetY(chipPosition.X());
157  ChipPosition.SetZ(chipPosition.Z() + m_z_DG / 2.);
158  }
159  }
160  if (m_phase == 2) {
161  ChipPosition.SetX(chipPosition.Y());
162  ChipPosition.SetY(chipPosition.X());
163  ChipPosition.SetZ(chipPosition.Z() + m_z_DG / 2);
164  }
165 
166 
167  //If new detector filled the chip
168  if (olddetNb != detNb && m_dchip_map.size() > 0 && m_dchip.size() < 20000 && oldtrkID != trkID) {
169  Pixelization();
170  olddetNb = detNb;
171  oldtrkID = trkID;
172  m_dchip_map.clear();
173  m_dchip.clear();
174  m_dchip_detNb_map.clear();
175  m_dchip_pdg_map.clear();
176  m_dchip_trkID_map.clear();
177  }
178 
179  //check if ionization within sensitive volume
180  if ((-m_ChipColumnX < ChipPosition.X() && ChipPosition.X() < m_ChipColumnX) &&
181  (-m_ChipRowY < ChipPosition.Y() && ChipPosition.Y() < m_ChipRowY) &&
182  (0. < ChipPosition.Z() && ChipPosition.Z() < m_z_DG) &&
183  (m_lowerTimingCut < T0[detNb] && T0[detNb] < m_upperTimingCut)) {
184 
185  //ionization energy
186  //MeV -> keV
187  const double ionEn = (edep - niel) * 1e3; // TODO: Use Unit constants instead of self made magic numbers
188  // check if enough energy to ionize if not break
189  // keV -> eV
190 
191  //if ((ionEn * 1e3) < m_Workfct) continue; // TODO: Use Unit constants instead of self made magic numbers
193  // check if enough energy to ionize
194  //else if ((ionEn * 1e3) > m_Workfct) { // TODO: Use Unit constants instead of self made magic numbers
195  if ((ionEn * 1e3) > m_Workfct) { // TODO: Use Unit constants instead of self made magic numbers
196 
197  const double meanEl = ionEn * 1e3 / m_Workfct;
198  const double sigma = sqrt(m_Fanofac * meanEl);
199  const int NbEle = (int)gRandom->Gaus(meanEl, sigma);
200  const double NbEle_real = NbEle - NbEle * m_GasAbs * chipPosition.Z();
201 
202  // start loop on the number of electron-ion-pairs at each interaction point
203  for (int ie = 0; ie < (int)NbEle_real; ie++) {
204 
205  //drift ionization to GEM 1 plane
206  //const TLorentzVector driftGap(Drift(chipPosition.X(), chipPosition.Y(), chipPosition.Z(), m_Dt_DG, m_Dl_DG, m_v_DG));
207  double x_DG, y_DG, z_DG, t_DG;
208  Drift(ChipPosition.X(),
209  ChipPosition.Y(),
210  ChipPosition.Z(),
211  x_DG, y_DG, z_DG, t_DG, m_Dt_DG, m_Dl_DG, m_v_DG);
212 
213  //calculate and scale 1st GEM gain
214  const double GEM_gain1 = gRandom->Gaus(m_GEMGain1, m_GEMGain1 * m_GEMGainRMS1) / m_ScaleGain1;
215 
216  //calculate and scale 2nd GEM gain
217  const double GEM_gain2 = gRandom->Gaus(m_GEMGain2, m_GEMGain2 * m_GEMGainRMS2) / m_ScaleGain2;
218 
220  // start loop on amplification
221  for (int ig1 = 0; ig1 < (int)GEM_gain1; ig1++) {
222  //1st GEM geometrical effect
223  //const TVector2 GEM1(GEMGeo1(driftGap.X(), driftGap.Y()));
224  const TVector2 GEM1(GEMGeo1(x_DG, y_DG));
225  //drift 1st amplication to 2nd GEM
226  //const TLorentzVector transferGap(Drift(GEM1.X(), GEM1.Y(), m_z_TG, m_Dt_TG, m_Dl_TG, m_v_TG));
227  double x_TG, y_TG, z_TG, t_TG;
228  Drift(GEM1.X(), GEM1.Y(), m_z_TG, x_TG, y_TG, z_TG, t_TG, m_Dt_TG, m_Dl_TG, m_v_TG);
229 
231  // start loop on amplification
232  for (int ig2 = 0; ig2 < (int)GEM_gain2; ig2++) {
233  //2nd GEN geometrical effect
234  //const TVector2 GEM2(GEMGeo2(transferGap.X(), transferGap.Y()));
235  const TVector2 GEM2(GEMGeo2(x_TG, y_TG));
236  //drift 2nd amplification to chip
237  //const TLorentzVector collectionGap(Drift(GEM2.X(), GEM2.Y(), m_z_CG, m_Dt_CG, m_Dl_CG, m_v_CG));
238  double x_CG, y_CG, z_CG, t_CG;
239  Drift(GEM2.X(), GEM2.Y(), m_z_CG, x_CG, y_CG, z_CG, t_CG, m_Dt_CG, m_Dl_CG, m_v_CG);
240 
241  //determine col, row, and bc
242  int col = (int)((x_CG + m_ChipColumnX) / (2. * m_ChipColumnX / (double)m_ChipColumnNb));
243  int row = (int)((y_CG + m_ChipRowY) / (2. * m_ChipRowY / (double)m_ChipRowNb));
244  int pix = col + m_ChipColumnNb * row;
245  int quT = gRandom->Uniform(-1, 1);
246  int bci = (int)((t_DG + t_TG + t_CG - T0[detNb]) / (double)m_PixelTimeBin) + quT;
247  if (bci < 0)bci = 0;
248 
249  //check if amplified drifted electron are within pixel boundaries
250  if ((0 <= col && col < m_ChipColumnNb) &&
251  (0 <= row && row < m_ChipRowNb) &&
252  (0 <= pix && pix < m_ChipColumnNb * m_ChipRowNb) &&
253  (0 <= bci && bci < MAXtSIZE)) {
254  //PixelFired[detNb] = true;
255  //store info into 3D array for each TPCs
257  //m_dchip_map[std::tuple<int, int, int>(detNb, col, row)] = 1;
258  //m_dchip[std::tuple<int, int, int, int>(detNb, col, row, bci)] += (int)(m_ScaleGain1 * m_ScaleGain2);
259  m_dchip_map[std::tuple<int, int>(col, row)] = 1;
260  m_dchip_detNb_map[std::tuple<int, int>(col, row)] = detNb;
261  m_dchip_pdg_map[std::tuple<int, int>(col, row)] = pdg;
262  m_dchip_trkID_map[std::tuple<int, int>(col, row)] = trkID;
263  m_dchip[std::tuple<int, int, int>(col, row, bci)] += (int)(m_ScaleGain1 * m_ScaleGain2);
264  }
265  }
266  }
267  }
268  }
269  }
270  }
271 
272  //Pixelization of the 3D ionization cloud
273  /*for (int i = 0; i < m_nTPC; i++) {
274  if (m_lowerTimingCut < T0[i] && T0[i] < m_upperTimingCut && PixelFired[i]) {
275  Pixelization(i);
276 
277  for (int j = 0; j < 80; j++) {
278  for (int k = 0; k < 336; k++) {
279  for (int l = 0; l < MAXtSIZE; l++) {
280  m_dchip[i][j][k][l] = 0;
281  }
282  }
283  }
284 
285  }
286  }
287  */
288  if (m_dchip_map.size() > 0 && m_dchip.size() < 20000) {
289  //std::cout << " event size " << m_dchip_map.size() << " all " << m_dchip.size() << std::endl;
290  Pixelization();
291  }
292  m_dchip_map.clear();
293  m_dchip.clear();
294  m_dchip_detNb_map.clear();
295  m_dchip_pdg_map.clear();
296  m_dchip_trkID_map.clear();
297 }
298 /*
299 TLorentzVector TpcDigitizerModule::Drift(
300  double x1, double y1, double z1,
301  double st, double sl, double vd
302 )
303 {
304  double x2 = 0;
305  double y2 = 0;
306  double z2 = 0;
307  double t2 = 0;
308  if (z1 > 0.) {
309  //transverse diffusion
310  x2 = x1 + gRandom->Gaus(0., sqrt(z1) * st);
311  //transverse diffusion
312  y2 = y1 + gRandom->Gaus(0., sqrt(z1) * st);
313  //longitidinal diffusion
314  z2 = z1 + gRandom->Gaus(0., sqrt(z1) * sl);
315  //time to diffuse
316  t2 = z2 / vd;
317  } else {
318  x2 = -1000; y2 = -1000; z2 = -1000; t2 = -1000;
319  }
320  return TLorentzVector(x2, y2, z2, t2);
321 }
322 */
323 void TpcDigitizerModule::Drift(double x1, double y1, double z1, double& x2, double& y2, double& z2, double& t2, double st,
324  double sl, double vd)
325 {
326  //check if
327  if (z1 > 0.) {
328  //transverse diffusion
329  x2 = x1 + gRandom->Gaus(0., sqrt(z1) * st);
330  //transverse diffusion
331  y2 = y1 + gRandom->Gaus(0., sqrt(z1) * st);
332  //longitidinal diffusion
333  z2 = z1 + gRandom->Gaus(0., sqrt(z1) * sl);
334  //time to diffuse
335  t2 = z2 / vd;
336  } else {
337  x2 = -1000; y2 = -1000; z2 = -1000; t2 = -1000;
338  }
339 }
340 TVector2 TpcDigitizerModule::GEMGeo1(double x1, double y1)
341 {
342  static const double sqrt3o4 = std::sqrt(3. / 4.);
343  double x2 = 0;
344  double y2 = (int)(y1 / (sqrt3o4 * m_GEMpitch) + (y1 < 0 ? -0.5 : 0.5)) * sqrt3o4 * m_GEMpitch;
345  int yint = (int)(y1 / (sqrt3o4 * m_GEMpitch) + 0.5);
346  if (yint % 2) {
347  x2 = static_cast<int>(x1 / m_GEMpitch + (x1 < 0 ? -0.5 : 0.5)) * m_GEMpitch;
348  } else {
349  //everysecond row is shifted with half a pitch
350  x2 = (static_cast<int>(x1 / m_GEMpitch) + (x1 < 0 ? -0.5 : 0.5)) * m_GEMpitch;
351  }
352  return TVector2(x2, y2);
353 }
354 
355 TVector2 TpcDigitizerModule::GEMGeo2(double x1, double y1)
356 {
357  static const double sqrt3o4 = std::sqrt(3. / 4.);
358  double x2 = (int)(x1 / (sqrt3o4 * m_GEMpitch) + (x1 < 0 ? -0.5 : 0.5)) * sqrt3o4 * m_GEMpitch;
359  double y2 = 0;
360  int yint = (int)(x1 / (sqrt3o4 * m_GEMpitch) + 0.5);
361  if (yint % 2) {
362  y2 = static_cast<int>(y1 / m_GEMpitch + (y1 < 0 ? -0.5 : 0.5)) * m_GEMpitch;
363  } else {
364  //everysecond row is shifted with half a pitch
365  y2 = (static_cast<int>(y1 / m_GEMpitch) + (y1 < 0 ? -0.5 : 0.5)) * m_GEMpitch;
366  }
367  return TVector2(x2, y2);
368 }
369 
370 
371 
372 
373 
374 //bool TpcDigitizerModule::Pixelization(int detNb)
376 {
377  std::vector<int> t0;
378  std::vector<int> col;
379  std::vector<int> row;
380  std::vector<int> ToT;
381  std::vector<int> bci;
382  t0.clear();
383  col.clear();
384  row.clear();
385  ToT.clear();
386  bci.clear();
387  StoreArray<MicrotpcHit> microtpcHits;
388 
389  for (auto& keyValuePair : m_dchip_map) {
390  const auto& key = keyValuePair.first;
391  //column
392  int i = std::get<0>(key);
393  //raw
394  int j = std::get<1>(key);
395 
396  if (m_dchip_map[std::tuple<int, int>(i, j)] == 1) {
397 
398  int k0 = 1e9;
399  const int quE = gRandom->Uniform(0, 2);
400  const double thresEl = m_PixelThreshold + gRandom->Uniform(-1.*m_PixelThresholdRMS, 1.*m_PixelThresholdRMS);
401  int kcounter = 0;
402  //determined t0 ie first time above pixel threshold
403  for (auto& keyValuePair2 : m_dchip) {
404  const auto& key2 = keyValuePair2.first;
405  int k = std::get<2>(key2);
406  if (m_dchip[std::tuple<int, int, int>(i, j, k)] > thresEl) {
407  if (k0 > k)k0 = k;
408  kcounter ++;
409  }
410  }
411  //std::cout<<"kcounter " << kcounter << std::endl;
412  //determined nb of bc per pixel
413  //if good t0
414  if (k0 != 1e9) {
415  int ik = 0;
416  int NbOfEl = 0;
417  for (auto& keyValuePair2 : m_dchip) {
418  const auto& key2 = keyValuePair2.first;
419  int k = std::get<2>(key2);
420  //sum up charge with 16 cycles
421  if (ik < 16) {
422  NbOfEl += m_dchip[std::tuple<int, int, int>(i, j, k)];
423  } else {
424  //calculate ToT
425  int tot = -1;
426  if (NbOfEl > thresEl && NbOfEl <= 45.*m_TOTQ1) {
427  tot = (int)fctToT_Calib1->Eval((double)NbOfEl) + quE;
428  } else if (NbOfEl > 45.*m_TOTQ1 && NbOfEl <= 900.*m_TOTQ1) {
429  tot = (int)fctToT_Calib2->Eval((double)NbOfEl);
430  } else if (NbOfEl > 800.*m_TOTQ1) {
431  tot = 13;
432  }
433  if (tot > 12) {
434  tot = 13;
435  }
436  if (tot >= 0) {
437  ToT.push_back(tot);
438  t0.push_back(k0);
439  col.push_back(i);
440  row.push_back(j);
441  bci.push_back(k0);
442  }
443  ik = 0;
444  NbOfEl = 0;
445  }
446  ik++;
447  }
448 
449  if (kcounter < 16) {
450  //calculate ToT
451  int tot = -1;
452  if (NbOfEl > thresEl && NbOfEl <= 45.*m_TOTQ1) {
453  tot = (int)fctToT_Calib1->Eval((double)NbOfEl) + quE;
454  } else if (NbOfEl > 45.*m_TOTQ1 && NbOfEl <= 900.*m_TOTQ1) {
455  tot = (int)fctToT_Calib2->Eval((double)NbOfEl);
456  } else if (NbOfEl > 800.*m_TOTQ1) {
457  tot = 13;
458  }
459  if (tot > 12) {
460  tot = 13;
461  }
462  if (tot >= 0) {
463  ToT.push_back(tot);
464  t0.push_back(k0);
465  col.push_back(i);
466  row.push_back(j);
467  bci.push_back(k0);
468  }
469  }
470 
471  }
472  } //end loop on row
473  } // end loop on col
474 
475  //bool PixHit = false;
476  //if entry
477 
478  if (bci.size() > 0) {
479  //std::cout << " size " << bci.size() << std::endl;
480  //PixHit = true;
481  //find start time
482  sort(t0.begin(), t0.end());
483 
484  //loop on nb of hit
485  for (int j = 0; j < (int)bci.size(); j++) {
486  if ((bci[j] - t0[0]) > (m_PixelTimeBinNb - 1)) {
487  continue;
488  }
489  //create MicrotpcHit
490  microtpcHits.appendNew(MicrotpcHit(col[j] + 1, row[j] + 1, bci[j] - t0[0] + 1, ToT[j],
491  m_dchip_detNb_map[std::tuple<int, int>(col[j], row[j])],
492  m_dchip_pdg_map[std::tuple<int, int>(col[j], row[j])],
493  m_dchip_trkID_map[std::tuple<int, int>(col[j], row[j])]));
494  } //end if entry
495  }
496  //return PixHit;
497  /*
498  std::vector<int> t0[10];
499  std::vector<int> col[10];
500  std::vector<int> row[10];
501  std::vector<int> ToT[10];
502  std::vector<int> bci[10];
503 
504  StoreArray<MicrotpcHit> microtpcHits;
505 
506  for (auto& keyValuePair : m_dchip_map) {
507  const auto& key = keyValuePair.first;
508  //detector number
509  int detNb = std::get<0>(key);
510  //column
511  int i = std::get<1>(key);
512  //raw
513  int j = std::get<2>(key);
514 
515  if (m_dchip_map[std::tuple<int, int, int>(detNb, i, j)] == 1) {
516 
517  int k0 = -10;
518  const int quE = gRandom->Uniform(0, 2);
519  const double thresEl = m_PixelThreshold + gRandom->Uniform(-1.*m_PixelThresholdRMS, 1.*m_PixelThresholdRMS);
520  //determined t0 ie first time above pixel threshold
521  //for (int k = 0; k < MAXtSIZE; k++) {
522  for (auto& keyValuePair2 : m_dchip) {
523  const auto& key2 = keyValuePair2.first;
524  int k = std::get<3>(key2);
525  if (m_dchip[std::tuple<int, int, int, int>(detNb, i, j, k)] > thresEl) {
526  //if (m_dchip[detNb][i][j][k] > thresEl) {
527  k0 = k;
528  break;
529  }
530  }
531  //determined nb of bc per pixel
532 
533  //if good t0
534  if (k0 != -10) {
535  int ik = 0;
536  int NbOfEl = 0;
537  //for (int k = k0; k < MAXtSIZE; k++) {
538  for (auto& keyValuePair2 : m_dchip) {
539  const auto& key2 = keyValuePair2.first;
540  int k = std::get<3>(key2);
541  //sum up charge with 16 cycles
542  if (ik < 16) {
543  NbOfEl += m_dchip[std::tuple<int, int, int, int>(detNb, i, j, k)];
544  //NbOfEl += m_dchip[detNb][i][j][k];
545  } else {
546  //calculate ToT
547  int tot = -1;
548  if (NbOfEl > thresEl && NbOfEl <= 45.*m_TOTQ1) {
549  tot = (int)fctToT_Calib1->Eval((double)NbOfEl) + quE;
550  } else if (NbOfEl > 45.*m_TOTQ1 && NbOfEl <= 900.*m_TOTQ1) {
551  tot = (int)fctToT_Calib2->Eval((double)NbOfEl);
552  } else if (NbOfEl > 800.*m_TOTQ1) {
553  tot = 14;
554  }
555  if (tot > 13) {
556  tot = 14;
557  }
558  if (tot >= 0) {
559  ToT[detNb].push_back(tot);
560  t0[detNb].push_back(k0);
561  col[detNb].push_back(i);
562  row[detNb].push_back(j);
563  bci[detNb].push_back(k0);
564  }
565  ik = 0;
566  NbOfEl = 0;
567  }
568  ik++;
569  }
570  }
571  } //end loop on row
572  //for (int k = 0; k < MAXtSIZE; k++) m_dchip[detNb][i][j][k] = 0;
573  } // end loop on col
574 
575  //bool PixHit = false;
576  for (int i = 0; i < 10 ; i++) {
577  //if entry
578  if (bci[i].size() > 0) {
579  //PixHit = true;
580  //find start time
581  sort(t0[i].begin(), t0[i].end());
582 
583  //loop on nb of hit
584  for (int j = 0; j < (int)bci[i].size(); j++) {
585  if ((bci[i][j] - t0[i][0]) > (m_PixelTimeBinNb - 1)) {
586  continue;
587  }
588  //create MicrotpcHit
589  microtpcHits.appendNew(MicrotpcHit(col[i][j], row[i][j], bci[i][j] - t0[i][0], ToT[i][j], i));
590  } //end on loop nb of hit
591  } //end if entry
592  }
593  //return PixHit;
594  */
595 }
596 
597 /*
598 
599 bool TpcDigitizerModule::Pixelization(int detNb)
600 {
601  std::vector<int> t0;
602  std::vector<int> col;
603  std::vector<int> row;
604  std::vector<int> ToT;
605  std::vector<int> bci;
606 
607  StoreArray<MicrotpcHit> microtpcHits;
608 
609  //loop on col.
610  for (int i = 0; i < (int)m_ChipColumnNb; i++) {
611  //loop on row
612  for (int j = 0; j < (int)m_ChipRowNb; j++) {
613  int k0 = -10;
614  const int quE = gRandom->Uniform(0, 2);
615  const double thresEl = m_PixelThreshold + gRandom->Uniform(-1.*m_PixelThresholdRMS, 1.*m_PixelThresholdRMS);
616  //determined t0 ie first time above pixel threshold
617  for (int k = 0; k < MAXtSIZE; k++) {
618  //if (m_dchip[std::tuple<int, int, int, int>(detNb, i, j, k)] > thresEl) {
619  if (m_dchip[detNb][i][j][k] > thresEl) {
620  k0 = k;
621  break;
622  }
623  }
624  //determined nb of bc per pixel
625 
626  //if good t0
627  if (k0 != -10) {
628  int ik = 0;
629  int NbOfEl = 0;
630  for (int k = k0; k < MAXtSIZE; k++) {
631  //sum up charge with 16 cycles
632  if (ik < 16) {
633  //NbOfEl += m_dchip[std::tuple<int, int, int, int>(detNb, i, j, k)];
634  NbOfEl += m_dchip[detNb][i][j][k];
635  } else {
636  //calculate ToT
637  int tot = -1;
638  if (NbOfEl > thresEl && NbOfEl <= 45.*m_TOTQ1) {
639  tot = (int)fctToT_Calib1->Eval((double)NbOfEl) + quE;
640  } else if (NbOfEl > 45.*m_TOTQ1 && NbOfEl <= 900.*m_TOTQ1) {
641  tot = (int)fctToT_Calib2->Eval((double)NbOfEl);
642  } else if (NbOfEl > 800.*m_TOTQ1) {
643  tot = 14;
644  }
645  if (tot > 13) {
646  tot = 14;
647  }
648  if (tot >= 0) {
649  ToT.push_back(tot);
650  t0.push_back(k0);
651  col.push_back(i);
652  row.push_back(j);
653  bci.push_back(k0);
654  }
655  ik = 0;
656  NbOfEl = 0;
657  }
658  ik++;
659  }
660  }
661  } //end loop on row
662  } // end loop on col
663 
664  bool PixHit = false;
665  //if entry
666  if (bci.size() > 0) {
667  PixHit = true;
668  //find start time
669  sort(t0.begin(), t0.end());
670 
671  //loop on nb of hit
672  for (int i = 0; i < (int)bci.size(); i++) {
673  if ((bci[i] - t0[0]) > (m_PixelTimeBinNb - 1)) {
674  continue;
675  }
676  //create MicrotpcHit
677  microtpcHits.appendNew(MicrotpcHit(col[i], row[i], bci[i] - t0[0], ToT[i], detNb));
678  } //end on loop nb of hit
679  } //end if entry
680 
681  return PixHit;
682 }
683 */
684 //read tube centers, impulse response, and garfield drift data filename from MICROTPC.xml
686 {
687  //const GearDir& content;
688  GearDir content = GearDir("/Detector/DetectorComponent[@name=\"MICROTPC\"]/Content/");
689 
690  //get the location of the tubes
691  BOOST_FOREACH(const GearDir & activeParams, content.getNodes("Active")) {
692 
693  m_TPCCenter.push_back(TVector3(activeParams.getLength("SensVol_x"), activeParams.getLength("SensVol_y"),
694  activeParams.getLength("SensVol_z")));
695  m_TPCAngleX.push_back(activeParams.getLength("AngleX"));
696  m_TPCAngleZ.push_back(activeParams.getLength("AngleZ"));
697 
698  m_nTPC++;
699  }
700  m_phase = content.getDouble("Phase");
701  m_LookAtRec = content.getDouble("LookAtRec");
702  m_GEMGain1 = content.getDouble("GEMGain1");
703  m_GEMGain2 = content.getDouble("GEMGain2");
704  m_GEMGainRMS1 = content.getDouble("GEMGainRMS1");
705  m_GEMGainRMS2 = content.getDouble("GEMGainRMS2");
706  m_ScaleGain1 = content.getDouble("ScaleGain1");
707  m_ScaleGain2 = content.getDouble("ScaleGain2");
708  m_GEMpitch = content.getDouble("GEMpitch");
709  m_PixelThreshold = content.getInt("PixelThreshold");
710  m_PixelThresholdRMS = content.getInt("PixelThresholdRMS");
711  m_PixelTimeBinNb = content.getInt("PixelTimeBinNb");
712  m_PixelTimeBin = content.getDouble("PixelTimeBin");
713  m_ChipColumnNb = content.getInt("ChipColumnNb");
714  m_ChipRowNb = content.getInt("ChipRowNb");
715  m_ChipColumnX = content.getDouble("ChipColumnX");
716  m_ChipRowY = content.getDouble("ChipRowY");
717  m_TOTA1 = content.getDouble("TOTA1");
718  m_TOTB1 = content.getDouble("TOTB1");
719  m_TOTC1 = content.getDouble("TOTC1");
720  m_TOTQ1 = content.getDouble("TOTQ1");
721  m_TOTA2 = content.getDouble("TOTA2");
722  m_TOTB2 = content.getDouble("TOTB2");
723  m_TOTC2 = content.getDouble("TOTC2");
724  m_TOTQ2 = content.getDouble("TOTQ2");
725  m_z_DG = content.getDouble("z_DG");
726  m_z_TG = content.getDouble("z_TG");
727  m_z_CG = content.getDouble("z_CG");
728  m_Dl_DG = content.getDouble("Dl_DG");
729  m_Dl_TG = content.getDouble("Dl_TG");
730  m_Dl_CG = content.getDouble("Dl_CG");
731  m_Dt_DG = content.getDouble("Dt_DG");
732  m_Dt_TG = content.getDouble("Dt_TG");
733  m_Dt_CG = content.getDouble("Dt_CG");
734  m_v_DG = content.getDouble("v_DG");
735  m_v_TG = content.getDouble("v_TG");
736  m_v_CG = content.getDouble("v_CG");
737  m_Workfct = content.getDouble("Workfct");
738  m_Fanofac = content.getDouble("Fanofac");
739  m_GasAbs = content.getDouble("GasAbs");
740 
741  B2INFO("TpcDigitizer: Aquired tpc locations and gas parameters");
742  B2INFO(" from MICROTPC.xml. There are " << m_nTPC << " TPCs implemented");
743 
744 }
745 
747 {
748 }
749 
751 {
752 }
753 
754 
static const ChargedStable proton
proton particle
Definition: Const.h:654
GearDir is the basic class used for accessing the parameter store.
Definition: GearDir.h:31
ClassMicrotpcHit - digitization simulated hit for the Microtpc detector.
Definition: MicrotpcHit.h:26
Base class for Modules.
Definition: Module.h:72
void setDescription(const std::string &description)
Sets the description of the module.
Definition: Module.cc:214
T * appendNew()
Construct a new T object at the end of the array.
Definition: StoreArray.h:246
double getLength(const std::string &path="") const noexcept(false)
Get the parameter path as a double converted to the standard length unit.
Definition: Interface.h:259
double m_lowerTimingCut
Lower timing cut.
double m_ChipRowY
Chip row y dimension.
std::map< std::tuple< int, int >, int > m_dchip_pdg_map
chip pdg map arrays
int m_LookAtRec
Flag 0/1 only look at nuclear recoils.
double m_Dl_CG
Longitudinal diffusion in collection gap.
double m_Dl_DG
Longitudinal diffusion in drift gap.
std::map< std::tuple< int, int >, int > m_dchip_trkID_map
chip track ID map arrays
TVector2 GEMGeo1(double x1, double y1)
GEMazition of GEM1.
virtual void initialize() override
Initialize the Module.
TF1 * fctToT_Calib1
Define ToT calib 1.
virtual void event() override
This method is the core of the module.
double m_v_DG
Drift velocity in drift gap.
virtual void endRun() override
This method is called if the current run ends.
double m_ChipColumnX
Chip column x dimension.
void getXMLData()
reads data from MICROTPC.xml: tube location, drift data filename, sigma of impulse response function
TpcDigitizerModule()
Constructor: Sets the description, the properties and the parameters of the module.
virtual void terminate() override
This method is called at the end of the event processing.
double m_upperTimingCut
Upper timing cut.
std::map< std::tuple< int, int, int >, int > m_dchip
chip store arrays
TF1 * fctToT_Calib2
Define ToT calib 2.
std::map< std::tuple< int, int >, int > m_dchip_detNb_map
chip Nb map arrays
virtual void beginRun() override
Called when entering a new run.
std::vector< TVector3 > m_TPCCenter
TPC coordinate.
double m_Dt_CG
Transverse diffusion in collection gap.
std::vector< float > m_TPCAngleZ
TPC angle Z.
std::map< std::tuple< int, int >, int > m_dchip_map
chip map arrays
double m_Dt_TG
Transverse diffusion in transfer gap.
std::vector< float > m_TPCAngleX
TPC angle X.
int m_PixelTimeBinNb
Pixel time number of bin.
double m_Dt_DG
Transverse diffusion in drift gap.
void Pixelization()
Produces the pixelization.
StoreArray< MicrotpcHit > m_microtpcHit
Array for MicrotpcHit.
int m_PixelThresholdRMS
Pixel threshold RMS.
double m_v_CG
Drift velocity in collection gap.
virtual void Drift(double, double, double, double &, double &, double &, double &, double, double, double)
Drift ionization Make the ionization drifting from (x,y,z) to GEM1 top plane.
TVector2 GEMGeo2(double x1, double y1)
GEMazition of GEM2.
double m_Dl_TG
Longitudinal diffusion in transfer gap.
double m_v_TG
Drift velocity in transfer gap.
REG_MODULE(arichBtest)
Register the Module.
void addParam(const std::string &name, T &paramVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
Definition: Module.h:560
double sqrt(double a)
sqrt for double
Definition: beamHelpers.h:28
Abstract base class for different kinds of events.