ATLAS Offline Software
Loading...
Searching...
No Matches
TileCalibDrawerFlt.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3*/
4
7#include <iostream>
8#include <algorithm>
9
10//
11//_____________________________________________________________
13TileCalibDrawerFlt::getInstance(const coral::Blob& blob)
14{
15 //=== const Blob needs to be correctly formated
16 if(blob.size()<static_cast<long>(m_hdrSize32)){
17 throw TileCalib::InvalidBlob("TileCalibDrawerFlt::getInstance");
18 }
19 return (new TileCalibDrawerFlt(blob));
20}
21
22//
23//_____________________________________________________________
26 const DefType& def,
27 uint16_t nChans,
28 uint16_t objVers,
29 const std::string& author,
30 const std::string& comment,
31 uint64_t timeStamp)
32{
33 TileCalibDrawerFlt* calibDrawer = new TileCalibDrawerFlt(blob);
34 calibDrawer->init(def,nChans,objVers,author,comment,timeStamp);
35 return calibDrawer;
36}
37
38//
39//_______________________________________________________________
40TileCalibDrawerFlt::TileCalibDrawerFlt(const coral::Blob& blob) :
41 TileCalibDrawerDat<float>(blob)
42{
43 if(getBlobSize()){
45 throw TileCalib::TypeConflict("TileCalibDrawerFlt::Ctor",getObjType(),TileCalibDrawerFlt::getType());
46 }
47 }
48}
49
50//
51//_______________________________________________________________
53 TileCalibDrawerDat<float>(blob)
54{
55 if(getBlobSize()){
57 throw TileCalib::TypeConflict("TileCalibDrawerFlt::Ctor",getObjType(),TileCalibDrawerFlt::getType());
58 }
59 }
60}
61
62//
63//______________________________________________________________
64float
65TileCalibDrawerFlt::getCalib(unsigned int channel, unsigned int adc, float energy, bool invert) const
66{
67 //=== interpretation of data depends on the objVersion
68 if(getObjVersion()==1){
69
70 //=== Application of a single slope
71 float slope = TileCalibDrawerFlt::getData(channel,adc,0);
72 if(invert)
73 {
74 energy *= slope;
75 }
76 else
77 {
78 if(slope==0.) throw TileCalib::InvalidValue("TileCalibDrawerFlt::getCalib(), SLOPE",slope);
79 energy /= slope;
80 }
81 return energy;
82
83 }
84 else if(getObjVersion()==100){
85
86 //============================================================================
87 //=== Look up table (LUT)
88 //=== Values are stored in one x and one y column
89 //=== Note: when filling the vector for the sqlite input file
90 //=== first insert all x-values and then all y-values
91 //=== Linear interpolation is done between two x-value entries
92 //=== Under- and overflows return the input value (convenient for CIS LUT)
93 //=== The return value is the LUT value!
94 //============================================================================
95
96 //NGO need to do something if "invert" is requested
97
98 //NGO change LUT format to slope and residual? Makes it more consistent with rest
99 //NGO and easier for visualization??
100
101 //=== need at least 2 (x,y) pairs,
102 //=== return unit function as default
103 if(getObjSizeUint32()<4){
104 return energy;
105 }
106
107 //=== Tile Default Policy has to be enforced here again,
108 //=== since getAddress() below assumes valid channel & adc
109
110 if(channel >= getNChans()) {
111 if (channel <= TileCalibUtils::MAX_CHAN) {
112 channel = 0;
113 } else {
114 channel = channel % TileCalibUtils::MAX_CHAN;
115 if (channel >= getNChans()) channel = 0;
116 }
117 }
118
119 if(adc >= getNGains()) {adc = 0;}
120
121 //=== determine position in table
122 const float* xBeg = getAddress(channel,adc);
123 const float* xEnd = xBeg + getObjSizeUint32()/2;
124 const float* iX = std::upper_bound(xBeg,xEnd,energy);
125 unsigned int offset = iX-xBeg;
126 float y(0.);
127 //=== boundary values
128 if(iX==xBeg || iX==xEnd){
129 y = energy;
130 }
131 //=== linear interpolation
132 else{
133 float x1 = *(iX );
134 float x0 = *(iX-1);
135 float y1 = *(xEnd+offset );
136 float y0 = *(xEnd+offset-1);
137 y = y0+(energy-x0)*(y1-y0)/(x1-x0);
138 }
139 return y;
140 }
141
142 //=== did not recognize the blob version
143 throw TileCalib::VersionConflict("TileCalibDrawerFlt::getCalib",getObjVersion());
144}
145
146//
147//______________________________________________________________
148bool
149TileCalibDrawerFlt::getYDY(unsigned int channel, unsigned int adc, float x,
150 float& y, float& dy) const
151{
152 //=== need to have a "function" blob version
153 if(getObjVersion()!=200){
154 throw TileCalib::VersionConflict("TileCalibDrawerFlt::getYDY",getObjVersion());
155 }
156
157 //=== require minimum pulse shape
158 if(getObjSizeUint32()<4){
159 return false;
160 }
161
162 //=== Tile Default Policy has to be enforced here again,
163 //=== since getAddress() below assumes valid channel & adc
164
165 if(channel >= getNChans()) {
166 if (channel <= TileCalibUtils::MAX_CHAN) {
167 channel = 0;
168 } else {
169 channel = channel % TileCalibUtils::MAX_CHAN;
170 if (channel >= getNChans()) channel = 0;
171 }
172 }
173
174 if( adc >= getNGains()) {adc = 0;}
175
176 //=== determine position in table
177 const float* xBeg = getAddress(channel,adc);
178 const float* xEnd = xBeg + getObjSizeUint32()/2;
179 const float* iX = std::upper_bound(xBeg,xEnd,x);
180 unsigned int offset = iX-xBeg;
181
182 //=== under-/overflow: return boundary y and dy==0
183 //=== offset delta is to avoid float comparison troubles
184 const float delta = 1.0e-3;
185 if(iX==xBeg) {
186 y = *(xEnd+offset);
187 dy = 0.;
188 if (x < (*(xBeg) - delta)) return false;
189 }
190 else if(iX==xEnd) {
191 y = *(xEnd+offset-1);
192 dy = 0.;
193 if (x > (*(xEnd-1) + delta)) return false;
194 }
195
196 //=== linear interpolation to determine y
197 else{
198 float x1 = *(iX );
199 float x0 = *(iX-1);
200 float y1 = *(xEnd+offset );
201 float y0 = *(xEnd+offset-1);
202 float slope = (y1-y0)/(x1-x0);
203 y = y0+(x-x0)*slope;
204
205 //=== determine dy from secant near [x,y]
206 float dx = x1 - x0;
207 float xs1 = x + 0.5 * dx;
208 float xs0 = x - 0.5 * dx;
209 dy = (getY(channel, adc, xs1) - getY(channel, adc, xs0)) / dx;
210 }
211 return true;
212}
213
214//
215//______________________________________________________________
216float
217TileCalibDrawerFlt::getY(unsigned int channel, unsigned int adc, float x) const
218{
219 float y(-9999.);
220 //=== need to have a "function" blob version
221 if(getObjVersion()!=200){
222 throw TileCalib::VersionConflict("TileCalibDrawerFlt::getY",getObjVersion());
223 }
224
225 //=== require minimum pulse shape
226 if(getObjSizeUint32()<4){
227 return false;
228 }
229
230 //=== Tile Default Policy has to be enforced here again,
231 //=== since getAddress() below assumes valid channel & adc
232
233 if(channel >= getNChans()) {
234 if (channel <= TileCalibUtils::MAX_CHAN) {
235 channel = 0;
236 } else {
237 channel = channel % TileCalibUtils::MAX_CHAN;
238 if (channel >= getNChans()) channel = 0;
239 }
240 }
241
242 if(adc >= getNGains()) {adc = 0;}
243
244 //=== determine position in table
245 const float* xBeg = getAddress(channel,adc);
246 const float* xEnd = xBeg + getObjSizeUint32()/2;
247 const float* iX = std::upper_bound(xBeg,xEnd,x);
248 unsigned int offset = iX-xBeg;
249
250 //=== under-/overflow: return boundary y
251 if(iX==xBeg){
252 y = *(xEnd+offset);
253 return y;
254 }
255 else if(iX==xEnd){
256 y = *(xEnd+offset-1);
257 return y;
258 }
259
260 //=== linear interpolation to determine y
261 else{
262 float x1 = *(iX );
263 float x0 = *(iX-1);
264 float y1 = *(xEnd+offset );
265 float y0 = *(xEnd+offset-1);
266 float slope = (y1-y0)/(x1-x0);
267 y = y0+(x-x0)*slope;
268 }
269 return y;
270}
271
272//
273//______________________________________________________________
274float
275TileCalibDrawerFlt::getDY(unsigned int channel, unsigned int adc, float x) const
276{
277 float y(-9999.), dy(-9999.);
278 (void)getYDY(channel,adc,x,y,dy);
279 return dy;
280}
281
#define y
#define x
uint16_t getNChans() const
uint16_t getObjType() const
uint16_t getNGains() const
static const unsigned int m_hdrSize32
uint16_t getObjVersion() const
uint32_t getObjSizeUint32() const
TileCalibDrawerDat(const coral::Blob &blob)
std::vector< std::vector< float > > DefType
float getData(unsigned int channel, unsigned int adc, unsigned int idx) const
const float * getAddress(unsigned int channel, unsigned int adc) const
Generic class for storing a number of floats (Flt) for each channel or ADC.
static const TileCalibDrawerFlt * getInstance(const coral::Blob &blob)
Returns a pointer to a const TileCalibDrawerFlt.
virtual uint16_t getType() const
Returns TileCalibType::FLT.
float getDY(unsigned int channel, unsigned int adc, float x) const
Returns y for a given x for function blob of type 200.
float getY(unsigned int channel, unsigned int adc, float x) const
Returns y for a given x for function blob of type 200.
bool getYDY(unsigned int channel, unsigned int adc, float x, float &y, float &dy) const
Returns y and derivative dy for a given x for function blob of type 200.
TileCalibDrawerFlt(const coral::Blob &blob)
Ctor (const).
float getCalib(unsigned int channel, unsigned int adc, float energy, bool invert=false) const
Returns the calibrated energy for a given channel/ADC and input energy.
static const unsigned int MAX_CHAN
Number of channels in drawer.
Thrown if coral::Blob does not conform with expected structure.
Thrown if object type in BLOB does not agree with class type.
Thrown if object version in BLOB does not agree with class.