Project
Loading...
Searching...
No Matches
AlpideSimResponse.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
14
17#include <TString.h>
18#include <TSystem.h>
19#include <cstdio>
20#include <cstddef>
21#include <fstream>
22#include <iostream>
23#include <memory>
24#include <fairlogger/Logger.h>
25
26using namespace o2::itsmft;
27using namespace std;
28
31
32constexpr float micron2cm = 1e-4;
33
34void AlpideSimResponse::initData(int tableNumber, std::string dataPath, const bool quiet)
35{
36 /*
37 * read grid parameters and load data
38 */
39 if (tableNumber == 0) // 0V back bias
40 {
41 const std::string newDataPath = dataPath + "Vbb-0.0V";
42 setDataPath(newDataPath); // setting the new data path
43 } else if (tableNumber == 1) // -3V back bias
44 {
45 const std::string newDataPath = dataPath + "Vbb-3.0V";
46 setDataPath(newDataPath); // setting the new data path
47 }
48
49 if (mData.size()) {
50 cout << "Object already initialized" << endl;
51 print();
52 return;
53 }
54
55 const float kTiny = 1e-6; // to check 0 values
56
57 // if needed, append path with slash
58 if (mDataPath.length() && mDataPath.back() != '/') {
59 mDataPath.push_back('/');
60 }
61 TString expandedDataPath = mDataPath;
62 gSystem->ExpandPathName(expandedDataPath);
63 mDataPath = expandedDataPath.Data();
64 string inpfname = mDataPath + mGridColName;
65 std::ifstream inpGrid;
66
67 // read X grid
68 inpGrid.open(inpfname, std::ifstream::in);
69 if (inpGrid.fail()) {
70 LOG(fatal) << "Failed to open file " << inpfname;
71 }
72
73 while (inpGrid >> mStepInvCol && inpGrid.good()) {
74 mNBinCol++;
75 }
76
77 if (!mNBinCol || mStepInvCol < kTiny) {
78 LOG(fatal) << "Failed to read X(col) binning from " << inpfname;
79 }
80 mMaxBinCol = mNBinCol - 1;
81 mStepInvCol = mMaxBinCol / mStepInvCol; // inverse of the X bin width
82 inpGrid.close();
83
84 // read Y grid
85 inpfname = mDataPath + mGridRowName;
86 inpGrid.open(inpfname, std::ifstream::in);
87 if (inpGrid.fail()) {
88 LOG(fatal) << "Failed to open file " << inpfname;
89 }
90
91 while (inpGrid >> mStepInvRow && inpGrid.good()) {
92 mNBinRow++;
93 }
94 if (!mNBinRow || mStepInvRow < kTiny) {
95 LOG(fatal) << "Failed to read Y(row) binning from " << inpfname;
96 }
97 mMaxBinRow = mNBinRow - 1;
98 mStepInvRow = mMaxBinRow / mStepInvRow; // inverse of the Row bin width
99 inpGrid.close();
100
101 // load response data
102 int nz = 0;
103 size_t cnt = 0;
104 float val, gx, gy, gz;
105 int lost, untrck, dead, nele;
106 size_t dataSize = 0;
107 mDptMax = -2.e9;
108 mDptMin = 2.e9;
109 const int npix = AlpideRespSimMat::getNPix();
110
111 for (int ix = 0; ix < mNBinCol; ix++) {
112 for (int iy = 0; iy < mNBinRow; iy++) {
113 inpfname = composeDataName(ix, iy);
114 inpGrid.open(inpfname, std::ifstream::in);
115 if (inpGrid.fail()) {
116 LOG(fatal) << "Failed to open file " << inpfname;
117 }
118 inpGrid >> nz;
119 if (cnt == 0) {
120 mNBinDpt = nz;
122 mData.reserve(dataSize); // reserve space for data
123 } else if (nz != mNBinDpt) {
124 LOG(fatal) << "Mismatch in Nz slices of bin X(col): " << ix << " Y(row): " << iy
125 << " wrt bin 0,0. File " << inpfname;
126 }
127
128 // load data
129 for (int iz = 0; iz < nz; iz++) {
131
132 std::array<float, AlpideRespSimMat::MatSize>* arr = mat.getArray();
133 for (int ip = 0; ip < npix * npix; ip++) {
134 inpGrid >> val;
135 (*arr)[ip] = val;
136 cnt++;
137 }
138 inpGrid >> lost >> dead >> untrck >> nele >> gx >> gy >> gz;
139
140 if (inpGrid.bad()) {
141 LOG(fatal) << "Failed reading data for depth(Z) slice " << iz << " from "
142 << inpfname;
143 }
144 if (!nele) {
145 LOG(fatal) << "Wrong normalization Nele=" << nele << "for depth(Z) slice "
146 << iz << " from " << inpfname;
147 }
148
149 if (mDptMax < -1e9) {
150 mDptMax = gz;
151 }
152 if (mDptMin > gz) {
153 mDptMin = gz;
154 }
155
156 // normalize
157 float norm = 1.f / nele;
158 for (int ip = npix * npix; ip--;) {
159 (*arr)[ip] *= norm;
160 }
161 mData.push_back(mat); // store in the final container
162 } // loop over z
163
164 inpGrid.close();
165
166 } // loop over y
167 } // loop over x
168
169 // final check
170 if (dataSize != mData.size()) {
171 LOG(fatal) << "Mismatch between expected " << dataSize << " and loaded " << mData.size()
172 << " number of bins";
173 }
174
175 // normalize Dpt boundaries
176
179
182 mStepInvDpt = (mNBinDpt - 1) / (mDptMax - mDptMin);
183 mDptMin -= 0.5 / mStepInvDpt;
184 mDptMax += 0.5 / mStepInvDpt;
185 mDptShift = 0.5 * (mDptMax + mDptMin);
186 if (!quiet) {
187 print();
188 }
189}
190
191//-----------------------------------------------------
193{
194 /*
195 * print itself
196 */
197 printf("Alpide response object of %zu matrices to map chagre in xyz to %dx%d pixels\n",
198 mData.size(), getNPix(), getNPix());
199 printf("X(col) range: %+e : %+e | step: %e | Nbins: %d\n", 0.f, mColMax, 1.f / mStepInvCol, mNBinCol);
200 printf("Y(row) range: %+e : %+e | step: %e | Nbins: %d\n", 0.f, mRowMax, 1.f / mStepInvRow, mNBinRow);
201 printf("Z(dpt) range: %+e : %+e | step: %e | Nbins: %d\n", mDptMin, mDptMax, 1.f / mStepInvDpt, mNBinDpt);
202}
203
204//-----------------------------------------------------
205string AlpideSimResponse::composeDataName(int colBin, int rowBin)
206{
207 /*
208 * compose the file-name to read data for bin colBin,rowBin
209 */
210
211 // ugly but safe way to compose the file name
212 float vcol = colBin / mStepInvCol, vrow = rowBin / mStepInvRow;
213 size_t size = snprintf(nullptr, 0, mColRowDataFmt.data(), vcol, vrow) + 1;
214 unique_ptr<char[]> tmp(new char[size]);
215 snprintf(tmp.get(), size, mColRowDataFmt.data(), vcol, vrow);
216 return mDataPath + string(tmp.get(), tmp.get() + size - 1);
217}
218
219//____________________________________________________________
220bool AlpideSimResponse::getResponse(float vRow, float vCol, float vDepth, AlpideRespSimMat& dest) const
221{
222 /*
223 * get linearized NPix*NPix matrix for response at point vRow(sensor local X, along row)
224 * vCol(sensor local Z, along columns) and vDepth (sensor local Y, i.e. depth)
225 */
226 if (!mNBinDpt) {
227 LOG(fatal) << "response object is not initialized";
228 }
229 bool flipCol = false, flipRow = true;
230 if (vDepth < mDptMin || vDepth > mDptMax) {
231 return false;
232 }
233 if (vCol < 0) {
234 vCol = -vCol;
235 flipCol = true;
236 }
237 if (vCol > mColMax) {
238 return false;
239 }
240 if (vRow < 0) {
241 vRow = -vRow;
242 flipRow = false;
243 }
244 if (vRow > mRowMax) {
245 return false;
246 }
247
248 size_t bin = getDepthBin(vDepth) + mNBinDpt * (getRowBin(vRow) + mNBinRow * getColBin(vCol));
249 if (bin >= mData.size()) {
250 // this should not happen
251 LOG(fatal) << "requested bin " << bin << "row/col/depth: " << getRowBin(vRow) << ":" << getColBin(vCol)
252 << ":" << getDepthBin(vDepth) << ")"
253 << ">= maxBin " << mData.size()
254 << " for X(row)=" << vRow << " Z(col)=" << vCol << " Y(depth)=" << vDepth;
255 }
256 // printf("bin %d %d %d\n",getColBin(vCol),getRowBin(vRow),getDepthBin(vDepth));
257 // return &mData[bin];
258 dest.adopt(mData[bin], flipRow, flipCol);
259 return true;
260}
261
262//____________________________________________________________
263const AlpideRespSimMat* AlpideSimResponse::getResponse(float vRow, float vCol, float vDepth, bool& flipRow, bool& flipCol) const
264{
265 return getResponse(vRow, vCol, vDepth, flipRow, flipCol, mRowMax, mColMax);
266}
267
268//____________________________________________________________
269const AlpideRespSimMat* AlpideSimResponse::getResponse(float vRow, float vCol, float vDepth, bool& flipRow, bool& flipCol, float rowMax, float colMax) const
270{
271 /*
272 * get linearized NPix*NPix matrix for response at point vRow(sensor local X, along row)
273 * vCol(sensor local Z, along columns) and vDepth (sensor local Y, i.e. depth)
274 */
275 if (!mNBinDpt) {
276 LOG(fatal) << "response object is not initialized";
277 }
278 if (vDepth < mDptMin || vDepth > mDptMax) {
279 return nullptr;
280 }
281 if (vCol < 0) {
282 vCol = -vCol;
283 flipCol = true;
284 } else {
285 flipCol = false;
286 }
287 if (vCol > colMax) {
288 return nullptr;
289 }
290 if (vRow < 0) {
291 vRow = -vRow;
292 flipRow = false;
293 } else {
294 flipRow = true;
295 }
296 if (vRow > rowMax) {
297 return nullptr;
298 }
299
300 size_t bin = getDepthBin(vDepth) + mNBinDpt * (getRowBin(vRow) + mNBinRow * getColBin(vCol));
301 if (bin >= mData.size()) {
302 // this should not happen
303 LOG(fatal) << "requested bin " << bin << "row/col/depth: " << getRowBin(vRow) << ":" << getColBin(vCol)
304 << ":" << getDepthBin(vDepth) << ")"
305 << ">= maxBin " << mData.size()
306 << " for X(row)=" << vRow << " Z(col)=" << vCol << " Y(depth)=" << vDepth;
307 }
308 return &mData[bin];
309}
310
311//__________________________________________________
312void AlpideRespSimMat::print(bool flipRow, bool flipCol) const
313{
314 /*
315 * print the response matrix
316 */
317 for (int iRow = 0; iRow < NPix; iRow++) {
318 for (int iCol = 0; iCol < NPix; iCol++) {
319 printf("%+e ", getValue(iRow, iCol, flipRow, flipCol));
320 }
321 printf("\n");
322 }
323}
ClassImp(o2::itsmft::AlpideSimResponse)
constexpr float micron2cm
Definition of the ITSMFT Alpide simulated response parametrization.
Timeframe settings Average distance in cm of events merged into Randomize distance around average distance of merged events Simulate correct bunch interactions instead of placing only the average number of events A value[n] sets TFlen for[n] collisions in Number of bunches per trainsort Number of bunch trains Instantaneous interaction rate Do not simulate border Total number of collisions to be placed in the interior of all time Do not select random but walk over array of events in stride steps h Event generator settings h configStandalone Use CPU for GPU Force usage of the specified GPU device no CPU fallback Continue processing after an error First event to Number of events to Number of iterations to Number of iterations to Number of initial iterations excluded from const char e
static int constexpr getNPix()
number of pixels in the quadrant
void adopt(const AlpideRespSimMat &src, bool flipRow=false, bool flipCol=false)
void print(bool flipRow=false, bool flipCol=false) const
print values
float getValue(int iRow, int iCol) const
probability to find an electron in pixel ix,iy,iz
std::array< float, MatSize > * getArray()
pointer on underlying array
int mMaxBinRow
max allowed Xb (to avoid subtraction)
float mDptShift
upper boundary of Dpt
float mStepInvCol
shift of the depth center wrt 0
int mNBinDpt
number of bins in Y(row direction)
void setDataPath(const std::string pth)
std::vector< AlpideRespSimMat > mData
inverse step of the Dpt grid
float mRowMax
upper boundary of Col
int mMaxBinCol
number of bins in Z(sensor dept)
bool getResponse(float vRow, float vCol, float cDepth, AlpideRespSimMat &dest) const
std::string mGridRowName
name of the file with grid in Col
std::string mColRowDataFmt
name of the file with grid in Row
float mColMax
max allowed Yb (to avoid subtraction)
float mDptMin
upper boundary of Row
void initData(int tableNumber, std::string dataPath, const bool quiet=true)
float mStepInvDpt
inverse step of the Row grid
float mDptMax
lower boundary of Dpt
float mStepInvRow
inverse step of the Col grid
std::string mDataPath
path to look for data file
static int constexpr getNPix()
int mNBinRow
number of bins in X(col direction)
GLsizei const GLchar *const * string
Definition glcorearb.h:809
GLsizeiptr size
Definition glcorearb.h:659
GLenum GLsizei dataSize
Definition glcorearb.h:3994
GLuint GLfloat * val
Definition glcorearb.h:1582
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"