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