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 <TSystem.h>
18#include <cstdio>
19#include <cstddef>
20#include <fstream>
21#include <iostream>
22#include <memory>
23#include <fairlogger/Logger.h>
24
25using namespace o2::itsmft;
26using namespace std;
27
30
31constexpr float micron2cm = 1e-4;
32
33void AlpideSimResponse::initData(int tableNumber, std::string dataPath, const bool quiet)
34{
35 /*
36 * read grid parameters and load data
37 */
38 if (tableNumber == 0) // 0V back bias
39 {
40 const std::string newDataPath = dataPath + "Vbb-0.0V";
41 setDataPath(newDataPath); // setting the new data path
42 } else if (tableNumber == 1) // -3V back bias
43 {
44 const std::string newDataPath = dataPath + "Vbb-3.0V";
45 setDataPath(newDataPath); // setting the new data path
46 }
47
48 if (mData.size()) {
49 cout << "Object already initialized" << endl;
50 print();
51 return;
52 }
53
54 const float kTiny = 1e-6; // to check 0 values
55
56 // if needed, append path with slash
57 if (mDataPath.length() && mDataPath.back() != '/') {
58 mDataPath.push_back('/');
59 }
60 mDataPath = gSystem->ExpandPathName(mDataPath.data());
61 string inpfname = mDataPath + mGridColName;
62 std::ifstream inpGrid;
63
64 // read X grid
65 inpGrid.open(inpfname, std::ifstream::in);
66 if (inpGrid.fail()) {
67 LOG(fatal) << "Failed to open file " << inpfname;
68 }
69
70 while (inpGrid >> mStepInvCol && inpGrid.good()) {
71 mNBinCol++;
72 }
73
74 if (!mNBinCol || mStepInvCol < kTiny) {
75 LOG(fatal) << "Failed to read X(col) binning from " << inpfname;
76 }
77 mMaxBinCol = mNBinCol - 1;
78 mStepInvCol = mMaxBinCol / mStepInvCol; // inverse of the X bin width
79 inpGrid.close();
80
81 // read Y grid
82 inpfname = mDataPath + mGridRowName;
83 inpGrid.open(inpfname, std::ifstream::in);
84 if (inpGrid.fail()) {
85 LOG(fatal) << "Failed to open file " << inpfname;
86 }
87
88 while (inpGrid >> mStepInvRow && inpGrid.good()) {
89 mNBinRow++;
90 }
91 if (!mNBinRow || mStepInvRow < kTiny) {
92 LOG(fatal) << "Failed to read Y(row) binning from " << inpfname;
93 }
94 mMaxBinRow = mNBinRow - 1;
95 mStepInvRow = mMaxBinRow / mStepInvRow; // inverse of the Row bin width
96 inpGrid.close();
97
98 // load response data
99 int nz = 0;
100 size_t cnt = 0;
101 float val, gx, gy, gz;
102 int lost, untrck, dead, nele;
103 size_t dataSize = 0;
104 mDptMax = -2.e9;
105 mDptMin = 2.e9;
106 const int npix = AlpideRespSimMat::getNPix();
107
108 for (int ix = 0; ix < mNBinCol; ix++) {
109 for (int iy = 0; iy < mNBinRow; iy++) {
110 inpfname = composeDataName(ix, iy);
111 inpGrid.open(inpfname, std::ifstream::in);
112 if (inpGrid.fail()) {
113 LOG(fatal) << "Failed to open file " << inpfname;
114 }
115 inpGrid >> nz;
116 if (cnt == 0) {
117 mNBinDpt = nz;
118 dataSize = mNBinCol * mNBinRow * mNBinDpt;
119 mData.reserve(dataSize); // reserve space for data
120 } else if (nz != mNBinDpt) {
121 LOG(fatal) << "Mismatch in Nz slices of bin X(col): " << ix << " Y(row): " << iy
122 << " wrt bin 0,0. File " << inpfname;
123 }
124
125 // load data
126 for (int iz = 0; iz < nz; iz++) {
128
129 std::array<float, AlpideRespSimMat::MatSize>* arr = mat.getArray();
130 for (int ip = 0; ip < npix * npix; ip++) {
131 inpGrid >> val;
132 (*arr)[ip] = val;
133 cnt++;
134 }
135 inpGrid >> lost >> dead >> untrck >> nele >> gx >> gy >> gz;
136
137 if (inpGrid.bad()) {
138 LOG(fatal) << "Failed reading data for depth(Z) slice " << iz << " from "
139 << inpfname;
140 }
141 if (!nele) {
142 LOG(fatal) << "Wrong normalization Nele=" << nele << "for depth(Z) slice "
143 << iz << " from " << inpfname;
144 }
145
146 if (mDptMax < -1e9) {
147 mDptMax = gz;
148 }
149 if (mDptMin > gz) {
150 mDptMin = gz;
151 }
152
153 // normalize
154 float norm = 1.f / nele;
155 for (int ip = npix * npix; ip--;) {
156 (*arr)[ip] *= norm;
157 }
158 mData.push_back(mat); // store in the final container
159 } // loop over z
160
161 inpGrid.close();
162
163 } // loop over y
164 } // loop over x
165
166 // final check
167 if (dataSize != mData.size()) {
168 LOG(fatal) << "Mismatch between expected " << dataSize << " and loaded " << mData.size()
169 << " number of bins";
170 }
171
172 // normalize Dpt boundaries
173
174 mStepInvCol /= micron2cm;
175 mStepInvRow /= micron2cm;
176
177 mDptMin *= micron2cm;
178 mDptMax *= micron2cm;
179 mStepInvDpt = (mNBinDpt - 1) / (mDptMax - mDptMin);
180 mDptMin -= 0.5 / mStepInvDpt;
181 mDptMax += 0.5 / mStepInvDpt;
182 mDptShift = 0.5 * (mDptMax + mDptMin);
183 if (!quiet) {
184 print();
185 }
186}
187
188//-----------------------------------------------------
190{
191 /*
192 * print itself
193 */
194 printf("Alpide response object of %zu matrices to map chagre in xyz to %dx%d pixels\n",
195 mData.size(), getNPix(), getNPix());
196 printf("X(col) range: %+e : %+e | step: %e | Nbins: %d\n", 0.f, mColMax, 1.f / mStepInvCol, mNBinCol);
197 printf("Y(row) range: %+e : %+e | step: %e | Nbins: %d\n", 0.f, mRowMax, 1.f / mStepInvRow, mNBinRow);
198 printf("Z(dpt) range: %+e : %+e | step: %e | Nbins: %d\n", mDptMin, mDptMax, 1.f / mStepInvDpt, mNBinDpt);
199}
200
201//-----------------------------------------------------
202string AlpideSimResponse::composeDataName(int colBin, int rowBin)
203{
204 /*
205 * compose the file-name to read data for bin colBin,rowBin
206 */
207
208 // ugly but safe way to compose the file name
209 float vcol = colBin / mStepInvCol, vrow = rowBin / mStepInvRow;
210 size_t size = snprintf(nullptr, 0, mColRowDataFmt.data(), vcol, vrow) + 1;
211 unique_ptr<char[]> tmp(new char[size]);
212 snprintf(tmp.get(), size, mColRowDataFmt.data(), vcol, vrow);
213 return mDataPath + string(tmp.get(), tmp.get() + size - 1);
214}
215
216//____________________________________________________________
217bool AlpideSimResponse::getResponse(float vRow, float vCol, float vDepth, AlpideRespSimMat& dest) const
218{
219 /*
220 * get linearized NPix*NPix matrix for response at point vRow(sensor local X, along row)
221 * vCol(sensor local Z, along columns) and vDepth (sensor local Y, i.e. depth)
222 */
223 if (!mNBinDpt) {
224 LOG(fatal) << "response object is not initialized";
225 }
226 bool flipCol = false, flipRow = true;
227 if (vDepth < mDptMin || vDepth > mDptMax) {
228 return false;
229 }
230 if (vCol < 0) {
231 vCol = -vCol;
232 flipCol = true;
233 }
234 if (vCol > mColMax) {
235 return false;
236 }
237 if (vRow < 0) {
238 vRow = -vRow;
239 flipRow = false;
240 }
241 if (vRow > mRowMax) {
242 return false;
243 }
244
245 size_t bin = getDepthBin(vDepth) + mNBinDpt * (getRowBin(vRow) + mNBinRow * getColBin(vCol));
246 if (bin >= mData.size()) {
247 // this should not happen
248 LOG(fatal) << "requested bin " << bin << "row/col/depth: " << getRowBin(vRow) << ":" << getColBin(vCol)
249 << ":" << getDepthBin(vDepth) << ")"
250 << ">= maxBin " << mData.size()
251 << " for X(row)=" << vRow << " Z(col)=" << vCol << " Y(depth)=" << vDepth;
252 }
253 // printf("bin %d %d %d\n",getColBin(vCol),getRowBin(vRow),getDepthBin(vDepth));
254 // return &mData[bin];
255 dest.adopt(mData[bin], flipRow, flipCol);
256 return true;
257}
258
259//____________________________________________________________
260const AlpideRespSimMat* AlpideSimResponse::getResponse(float vRow, float vCol, float vDepth, bool& flipRow, bool& flipCol) const
261{
262 return getResponse(vRow, vCol, vDepth, flipRow, flipCol, mRowMax, mColMax);
263}
264
265//____________________________________________________________
266const AlpideRespSimMat* AlpideSimResponse::getResponse(float vRow, float vCol, float vDepth, bool& flipRow, bool& flipCol, float rowMax, float colMax) const
267{
268 /*
269 * get linearized NPix*NPix matrix for response at point vRow(sensor local X, along row)
270 * vCol(sensor local Z, along columns) and vDepth (sensor local Y, i.e. depth)
271 */
272 if (!mNBinDpt) {
273 LOG(fatal) << "response object is not initialized";
274 }
275 if (vDepth < mDptMin || vDepth > mDptMax) {
276 return nullptr;
277 }
278 if (vCol < 0) {
279 vCol = -vCol;
280 flipCol = true;
281 } else {
282 flipCol = false;
283 }
284 if (vCol > colMax) {
285 return nullptr;
286 }
287 if (vRow < 0) {
288 vRow = -vRow;
289 flipRow = false;
290 } else {
291 flipRow = true;
292 }
293 if (vRow > rowMax) {
294 return nullptr;
295 }
296
297 size_t bin = getDepthBin(vDepth) + mNBinDpt * (getRowBin(vRow) + mNBinRow * getColBin(vCol));
298 if (bin >= mData.size()) {
299 // this should not happen
300 LOG(fatal) << "requested bin " << bin << "row/col/depth: " << getRowBin(vRow) << ":" << getColBin(vCol)
301 << ":" << getDepthBin(vDepth) << ")"
302 << ">= maxBin " << mData.size()
303 << " for X(row)=" << vRow << " Z(col)=" << vCol << " Y(depth)=" << vDepth;
304 }
305 return &mData[bin];
306}
307
308//__________________________________________________
309void AlpideRespSimMat::print(bool flipRow, bool flipCol) const
310{
311 /*
312 * print the response matrix
313 */
314 for (int iRow = 0; iRow < NPix; iRow++) {
315 for (int iCol = 0; iCol < NPix; iCol++) {
316 printf("%+e ", getValue(iRow, iCol, flipRow, flipCol));
317 }
318 printf("\n");
319 }
320}
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
void setDataPath(const std::string pth)
bool getResponse(float vRow, float vCol, float cDepth, AlpideRespSimMat &dest) const
void initData(int tableNumber, std::string dataPath, const bool quiet=true)
static int constexpr getNPix()
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
Defining DataPointCompositeObject explicitly as copiable.
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"