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.
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"