Belle II Software development
FANGSDigitizerModule.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/fangs/modules/FANGSDigitizerModule.h>
10#include <beast/fangs/dataobjects/FANGSSimHit.h>
11
12#include <mdst/dataobjects/MCParticle.h>
13#include <framework/logging/Logger.h>
14#include <framework/gearbox/GearDir.h>
15#include <framework/core/RandomNumbers.h>
16
17//c++
18#include <cmath>
19#include <vector>
20
21using namespace Belle2;
22using namespace fangs;
23
24
25//-----------------------------------------------------------------
26// Register the Module
27//-----------------------------------------------------------------
28REG_MODULE(FANGSDigitizer);
29
30//-----------------------------------------------------------------
31// Implementation
32//-----------------------------------------------------------------
33
35{
36 // Set module properties
37 setDescription("FANGS digitizer module");
38
39 //Default values are set here. New values can be in FANGS.xml.
40 addParam("LowerTimingCut", m_lowerTimingCut, "Lower timing cut", 0.);
41 addParam("UpperTimingCut", m_upperTimingCut, "Upper timing cut", 1000000.);
42}
43
44FANGSDigitizerModule::~FANGSDigitizerModule()
45{
46}
47
49{
50 B2INFO("FANGSDigitizer: Initializing");
51 m_fangsHit.registerInDataStore();
52
53 //get xml data
54 getXMLData();
55
56 //converter: electron number to TOT part I
57 fctToT_Calib1 = new TF1("fctToT_Calib1", "[0]*(x/[3]+[1])/(x/[3]+[2])", 0., 100000.);
58 fctToT_Calib1->SetParameters(m_TOTA1, m_TOTB1, m_TOTC1, m_TOTQ1);
59 //converter: electron number to TOT part II
60 fctToT_Calib2 = new TF1("fctToT_Calib2", "[0]*(x/[3]+[1])/(x/[3]+[2])", 0., 100000.);
61 fctToT_Calib2->SetParameters(m_TOTA2, m_TOTB2, m_TOTC2, m_TOTQ2);
62}
63
65{
66}
67
69{
70 StoreArray<FANGSSimHit> FANGSSimHits;
71 m_nFANGS = 15;
72 std::vector<double> T0(m_nFANGS,
74
75 //Find the start time
76 for (const auto& FANGSSimHit : FANGSSimHits) {
77 const int lad = FANGSSimHit.getLadder();
78 const int sen = FANGSSimHit.getSensor();
79 const int detNb = (lad - 1) * 5 + sen - 1;
80 const ROOT::Math::XYZVector trackPosition = FANGSSimHit.getLocalPosEntry();
81 const double z = trackPosition.Y() + m_sensor_width / 2.; //cm
82 if (z < T0[detNb]) {
83 T0[detNb] = z;
84 }
85 }
86
87 for (auto& val : T0) {
88 if (m_lowerTimingCut < val && val < m_upperTimingCut) {
89 val = val / m_v_sensor; //cm / (cm / ns) = ns
90 } else {
91 val = -1.;
92 }
93 }
94
95 //loop on all entries to store in 3D the ionization for each FANGS
96 for (const auto& FANGSSimHit : FANGSSimHits) {
97
98 const int lad = FANGSSimHit.getLadder();
99 const int sen = FANGSSimHit.getSensor();
100 const int detNb = (lad - 1) * 5 + sen - 1;
101 const ROOT::Math::XYZVector simHitPosition = FANGSSimHit.getLocalPosEntry();
102 const double edep = FANGSSimHit.getEnergyDep() * 1e9; //GeV to eV
103
104 const ROOT::Math::XYZVector chipPosition(//cm
105 simHitPosition.X(),
106 simHitPosition.Z(),
107 simHitPosition.Y() + m_sensor_width / 2.);
108
109 //If new detector filled the chip
110 if (olddetNb != detNb && m_dchip_map.size() > 0) {
111 Pixelization();
112 olddetNb = detNb;
113 m_dchip_map.clear();
114 m_dchip.clear();
115 m_dchip_detNb_map.clear();
116 m_dchip_pdg_map.clear();
117 m_dchip_trkID_map.clear();
118 }
119
120 // There is some issue with these cuts! please check, remove for now!
121 //check if ionization within sensitive volume
122 /*if ((-m_ChipColumnX < chipPosition.X() && chipPosition.X() < m_ChipColumnX) &&
123 (-m_ChipRowY < chipPosition.Y() && chipPosition.Y() < m_ChipRowY) &&
124 (0. < chipPosition.Z() && chipPosition.Z() < m_sensor_width) &&
125 (m_lowerTimingCut < T0[detNb] && T0[detNb] < m_upperTimingCut)) {*/
126 if (1) {
127
128 if (edep < m_Workfct) break;
130 // check if enough energy to ionize
131 else if (edep > m_Workfct) {
132
133 const double meanEl = edep / m_Workfct;
134 const double sigma = sqrt(m_Fanofac * meanEl);
135 const int NbEle = (int)gRandom->Gaus(meanEl, sigma);
136
137 int col = (int)((chipPosition.X() + m_ChipColumnX) / (2. * m_ChipColumnX / (double)m_ChipColumnNb));
138 int row = (int)((chipPosition.Y() + m_ChipRowY) / (2. * m_ChipRowY / (double)m_ChipRowNb));
139 int pix = col + m_ChipColumnNb * row;
140 int quT = gRandom->Uniform(-1, 1);
141 int bci = (int)((chipPosition.Z() / m_v_sensor - T0[detNb]) / (double)m_PixelTimeBin) + quT;
142 if (bci < 0)bci = 0;
143
144 //check if amplified drifted electron are within pixel boundaries
145 if ((0 <= col && col < m_ChipColumnNb) &&
146 (0 <= row && row < m_ChipRowNb) &&
147 (0 <= pix && pix < m_ChipColumnNb * m_ChipRowNb) &&
148 (0 <= bci && bci < MAXtSIZE)) {
149 //store info into 3D array for each FANGSs
150 m_dchip_map[std::tuple<int, int>(col, row)] = 1;
151 m_dchip_detNb_map[std::tuple<int, int>(col, row)] = detNb;
152 m_dchip_pdg_map[std::tuple<int, int>(col, row)] = FANGSSimHit.getPDG();
153 m_dchip_trkID_map[std::tuple<int, int>(col, row)] = FANGSSimHit.gettrkID();
154 m_dchip[std::tuple<int, int, int>(col, row, bci)] += (int)(NbEle);
155 }
156 }
157 }
158 }
159
160 if (m_dchip_map.size() > 0) Pixelization();
161 m_dchip_map.clear();
162 m_dchip.clear();
163 m_dchip_detNb_map.clear();
164 m_dchip_pdg_map.clear();
165 m_dchip_trkID_map.clear();
166}
167
169{
170 std::vector<int> t0;
171 std::vector<int> col;
172 std::vector<int> row;
173 std::vector<int> ToT;
174 std::vector<int> bci;
175
176 StoreArray<FANGSHit> FANGSHits;
177
178 for (auto& keyValuePair : m_dchip_map) {
179 const auto& key = keyValuePair.first;
180 //column
181 int i = std::get<0>(key);
182 //raw
183 int j = std::get<1>(key);
184
185 if (m_dchip_map[std::tuple<int, int>(i, j)] == 1) {
186
187 int k0 = 1e9;
188 const int quE = gRandom->Uniform(0, 2);
189 const double thresEl = m_PixelThreshold + gRandom->Uniform(-1.*m_PixelThresholdRMS, 1.*m_PixelThresholdRMS);
190 int kcounter = 0;
191 //determined t0 ie first time above pixel threshold
192 for (auto& keyValuePair2 : m_dchip) {
193 const auto& key2 = keyValuePair2.first;
194 int k = std::get<2>(key2);
195 if (m_dchip[std::tuple<int, int, int>(i, j, k)] > thresEl) {
196 if (k0 > k)k0 = k;
197 kcounter ++;
198 }
199 }
200 //determined nb of bc per pixel
201 //if good t0
202 if (k0 != 1e9) {
203 int ik = 0;
204 int NbOfEl = 0;
205 for (auto& keyValuePair2 : m_dchip) {
206 const auto& key2 = keyValuePair2.first;
207 int k = std::get<2>(key2);
208 //sum up charge with 16 cycles
209 if (ik < 16) {
210 NbOfEl += m_dchip[std::tuple<int, int, int>(i, j, k)];
211 } else {
212 //calculate ToT
213 int tot = -1;
214 if (NbOfEl > thresEl && NbOfEl <= 45.*m_TOTQ1) {
215 tot = (int)fctToT_Calib1->Eval((double)NbOfEl) + quE;
216 } else if (NbOfEl > 45.*m_TOTQ1 && NbOfEl <= 900.*m_TOTQ1) {
217 tot = (int)fctToT_Calib2->Eval((double)NbOfEl);
218 } else if (NbOfEl > 800.*m_TOTQ1) {
219 tot = 14;
220 }
221 if (tot > 13) {
222 tot = 14;
223 }
224 if (tot >= 0) {
225 ToT.push_back(tot);
226 t0.push_back(k0);
227 col.push_back(i);
228 row.push_back(j);
229 bci.push_back(k0);
230 }
231 ik = 0;
232 NbOfEl = 0;
233 }
234 ik++;
235 }
236
237 if (kcounter < 16) {
238 //calculate ToT
239 int tot = -1;
240 if (NbOfEl > thresEl && NbOfEl <= 45.*m_TOTQ1) {
241 tot = (int)fctToT_Calib1->Eval((double)NbOfEl) + quE;
242 } else if (NbOfEl > 45.*m_TOTQ1 && NbOfEl <= 900.*m_TOTQ1) {
243 tot = (int)fctToT_Calib2->Eval((double)NbOfEl);
244 } else if (NbOfEl > 800.*m_TOTQ1) {
245 tot = 14;
246 }
247 if (tot > 13) {
248 tot = 14;
249 }
250 if (tot >= 0) {
251 ToT.push_back(tot);
252 t0.push_back(k0);
253 col.push_back(i);
254 row.push_back(j);
255 bci.push_back(k0);
256 }
257 }
258
259 }
260 } //end loop on row
261 } // end loop on col
262
263 //bool PixHit = false;
264 //if entry
265 if (bci.size() > 0) {
266 //PixHit = true;
267 //find start time
268 sort(t0.begin(), t0.end());
269
270 //loop on nb of hit
271 for (int j = 0; j < (int)bci.size(); j++) {
272 if ((bci[j] - t0[0]) > (m_PixelTimeBinNb - 1)) {
273 continue;
274 }
275 //create FANGSHit
276 FANGSHits.appendNew(FANGSHit(col[j], row[j], bci[j] - t0[0], ToT[j],
277 m_dchip_detNb_map[std::tuple<int, int>(col[j], row[j])],
278 m_dchip_pdg_map[std::tuple<int, int>(col[j], row[j])],
279 m_dchip_trkID_map[std::tuple<int, int>(col[j], row[j])]));
280 } //end if entry
281 }
282 //return PixHit;
283}
284//read tube centers, impulse response, and garfield drift data filename from FANGS.xml
286{
287 //const GearDir& content;
288 GearDir content = GearDir("/Detector/DetectorComponent[@name=\"FANGS\"]/Content/");
289
290 //get the location of the tubes
291
292 m_PixelThreshold = content.getInt("PixelThreshold");
293 m_PixelThresholdRMS = content.getInt("PixelThresholdRMS");
294 m_PixelTimeBinNb = content.getInt("PixelTimeBinNb");
295 m_PixelTimeBin = content.getDouble("PixelTimeBin");
296 m_ChipColumnNb = content.getInt("ChipColumnNb");
297 m_ChipRowNb = content.getInt("ChipRowNb");
298 m_ChipColumnX = content.getDouble("ChipColumnX");
299 m_ChipRowY = content.getDouble("ChipRowY");
300 m_TOTA1 = content.getDouble("TOTA1");
301 m_TOTB1 = content.getDouble("TOTB1");
302 m_TOTC1 = content.getDouble("TOTC1");
303 m_TOTQ1 = content.getDouble("TOTQ1");
304 m_TOTA2 = content.getDouble("TOTA2");
305 m_TOTB2 = content.getDouble("TOTB2");
306 m_TOTC2 = content.getDouble("TOTC2");
307 m_TOTQ2 = content.getDouble("TOTQ2");
308 m_v_sensor = content.getDouble("v_sensor");
309 m_sensor_width = content.getDouble("sensor_width");
310 m_Workfct = content.getDouble("Workfct");
311 m_Fanofac = content.getDouble("Fanofac");
312
313 B2INFO("FANGSDigitizer: Aquired FANGS locations and gas parameters");
314 B2INFO(" from FANGS.xml. There are " << m_nFANGS << " FANGSs implemented");
315
316}
317
319{
320}
321
323{
324}
325
326
ClassFANGSHit - digitization simulated hit for the FANGS detector.
Definition: FANGSHit.h:26
Class FANGSSimHit - Geant4 simulated hit for the FANGS detector.
Definition: FANGSSimHit.h:28
float getEnergyDep() const
Return the energy deposition in electrons.
Definition: FANGSSimHit.h:76
int getLadder() const
Return the Ladder number (starting at 1, increasing with phi)
Definition: FANGSSimHit.h:68
int getSensor() const
Return the Sensor number (starting at 1, increasing with decreasing z)
Definition: FANGSSimHit.h:70
int getPDG() const
Return the PDG number of the track.
Definition: FANGSSimHit.h:72
ROOT::Math::XYZVector getLocalPosEntry() const
Return the local entry track position.
Definition: FANGSSimHit.h:80
int gettrkID() const
Return track ID.
Definition: FANGSSimHit.h:66
GearDir is the basic class used for accessing the parameter store.
Definition: GearDir.h:31
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 m_ChipRowY
Chip row y dimension.
std::map< std::tuple< int, int >, int > m_dchip_pdg_map
chip pdg map arrays
std::map< std::tuple< int, int >, int > m_dchip_trkID_map
chip track ID map arrays
virtual void initialize() override
Initialize the Module.
TF1 * fctToT_Calib1
Define ToT calib 1.
StoreArray< FANGSHit > m_fangsHit
array for FANGSHit
virtual void event() override
This method is the core of the module.
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 MICROFANGS.xml: tube location, drift data filename, sigma of impulse response functio...
virtual void terminate() override
This method is called at the end of the event processing.
double m_v_sensor
Drift velocity in sensor.
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::map< std::tuple< int, int >, int > m_dchip_map
chip map arrays
int m_PixelTimeBinNb
Pixel time number of bin.
void Pixelization()
Produces the pixelization.
int m_PixelThresholdRMS
Pixel threshold RMS.
FANGSDigitizerModule()
Constructor: Sets the description, the properties and the parameters of 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
#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.