ATLAS Offline Software
Loading...
Searching...
No Matches
CalibCscStripFitter.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7#include <cmath>
8
10
12
15
16//**********************************************************************
17
18CalibCscStripFitter::CalibCscStripFitter(const std::string& type, const std::string& aname, const IInterface* parent) :
19 AthAlgTool(type, aname, parent), m_noiseOption(rms) {
20 declareInterface<ICscStripFitter>(this);
21 declareProperty("timeError", m_terr = 5.0);
22 declareProperty("failTimeError", m_terr_fail = 50.0);
23 declareProperty("chargeCalibrationError", m_qerrprop = 0.000);
24 declareProperty("noiseOption", m_noiseOptionStr = "f001");
25 declareProperty("doCorrection", m_doCorrection = true);
26 declareProperty("chargeErrorScaler", m_chargeErrorScaler = 1.0);
27}
28
29//**********************************************************************
30
32 ATH_MSG_DEBUG("Initializing " << name());
33
34 ATH_MSG_DEBUG("Properties for " << name() << ":");
35 ATH_MSG_DEBUG(" Time error: " << m_terr);
36 ATH_MSG_DEBUG(" Fail time error: " << m_terr_fail);
37 ATH_MSG_DEBUG(" Charge calibration error: " << m_qerrprop);
38 ATH_MSG_DEBUG(" Charge Error Option is " << m_noiseOptionStr);
39 ATH_MSG_DEBUG(" Charge Error Scaler is " << m_chargeErrorScaler);
40 ATH_MSG_DEBUG(" Correction applied for para to bipolar is " << m_doCorrection);
41
42 if (m_noiseOptionStr != "rms" && m_noiseOptionStr != "sigma" && m_noiseOptionStr != "f001") {
43 ATH_MSG_DEBUG(" noiseOption is not among rms/sigma/f001. rms is used for default!!");
44 m_noiseOptionStr = "rms";
45 }
46 if (m_noiseOptionStr == "rms")
48 else if (m_noiseOptionStr == "sigma")
50 else if (m_noiseOptionStr == "f001")
52
53 // ATH_MSG_DEBUG ( " (failed) Charge error is noise(DB)*1.03588 = 4300 " << m_errorScaler );
56
57 // Retrieve the detector descriptor.
58 ATH_CHECK(m_idHelperSvc.retrieve());
59
60 return StatusCode::SUCCESS;
61}
62
63//**********************************************************************
64
65Result CalibCscStripFitter::fit(const ChargeList& chgs, double period, bool samplingPhase, Identifier& stripId) const {
66 // period ==> frequency either 50ns or 25ns
67
68 Result res;
69
70 // It has been used 4300e- as charge error so far.
71 // 3.5 ADC was noise -> 4151.06 e- (as of Mar 10, 2009)
72 // From DB, we got it as noise. error scaler is from 4300/3546.03;
73 // double errorScaler = 4300./4151.06; // 1.03588
74
75 IdentifierHash stripHash;
76 if (m_idHelperSvc->cscIdHelper().get_channel_hash(stripId, stripHash)) {
77 ATH_MSG_WARNING("Unable to get CSC striphash id "
78 << " the identifier is ");
79 stripId.show();
80 }
81
82 int zsec = m_idHelperSvc->cscIdHelper().stationEta(stripId);
83 int phisec = m_idHelperSvc->cscIdHelper().stationPhi(stripId);
84 int station = m_idHelperSvc->cscIdHelper().stationName(stripId) - 49;
85
86 int sector = zsec * (2 * phisec - station + 1);
87
88 int wlay = m_idHelperSvc->cscIdHelper().wireLayer(stripId);
89 int measphi = m_idHelperSvc->cscIdHelper().measuresPhi(stripId);
90 int istrip = m_idHelperSvc->cscIdHelper().strip(stripId);
91
92 double ped = m_cscCalibTool->stripPedestal(stripHash);
93 // Get noise information
94 double noise = 0;
95 if (m_noiseOption == rms) {
96 noise = m_cscCalibTool->stripRMS(stripHash);
97 } else if (m_noiseOption == sigma) {
98 noise = m_cscCalibTool->stripNoise(stripHash);
99 } else if (m_noiseOption == f001) { // f001 is rawADC +1
100 noise = m_cscCalibTool->stripF001(stripHash) - m_cscCalibTool->stripPedestal(stripHash);
101 noise /= 3.251;
102 }
103
104 // bool isGood = m_cscCalibTool->isGood(stripHash);
105 int stripStatusWord = m_cscCalibTool->stripStatusBit(stripHash);
106
107 bool showDetail = false;
108 if (noise <= 0.0) {
109 showDetail = true;
110 ATH_MSG_DEBUG(" Noise is zero!! DB needs to be fixed for this channel. 4151.06 (3.5ADC) is assigned.");
111 noise = 4151.06;
112 }
113
114 noise = m_chargeErrorScaler * noise;
115
116 if (ped < 1.0) {
117 showDetail = true;
118 ATH_MSG_DEBUG(" Pedestal is zero!! DB needs to be fixed for this channel. 2048*1013 (2048ADC) is assigned.");
119 // ped = 0; // 2048 ADC as a default...
120 // unrealistic.... DB should be corrupted....
121 }
122
123 if (showDetail)
124 ATH_MSG_DEBUG("noiseOption " << m_noiseOptionStr << " noise= " << noise << " pedestal= " << ped << " strIdentifier= " << stripId
125 << " strHash= " << (unsigned int)stripHash << " zsec:phisec:istation sector " << zsec << ":"
126 << phisec << ":" << station << " " << sector << " wlay:measphi:istr = " << wlay << " " << measphi
127 << " " << istrip << " Charges: " << chgs << " (Sample time: " << period << " ns)");
128
129 // Fit with calib tool.
130 res.phase = samplingPhase;
131 res.dcharge = noise;
132
133 if (m_cscCalibTool->findCharge(period, samplingPhase, chgs, res.charge, res.time)) { // success
134 res.stripStatus = Muon::CscStrStatSuccess;
135 res.status += 1;
136 } else {
138 res.status += 2;
139 }
140
141 res.charge_beforeBPCorr = res.charge;
142 res.time_beforeBPCorr = res.time;
143
144 if (samplingPhase == 1) // This is bipolar correction purpose and will be subtracted...
145 res.time = res.time + 25;
146
147 if (m_doCorrection) { // m_ denotes global variables...
148
149 bool doPositionCorrection = false;
150
151 ATH_MSG_DEBUG("Without any correction res.time = " << res.time);
152 ATH_MSG_DEBUG("Without any correction res.charge = " << res.charge);
153
154 double parabolapTime[150];
155 for (int i = 0; i < 150; ++i) { parabolapTime[i] = 0.5 + i; }
156
157 double bipolarpTime[150] = {
158 7.2767, 14.6497, 14.9118, 15.3129, 15.5765, 15.8889, 16.2474, 16.6022, 16.9897, 17.3629, 17.7400, 18.2157,
159 18.6235, 19.0662, 19.4730, 19.9940, 20.4652, 20.9776, 21.4932, 22.0852, 22.6554, 23.2433, 23.8237, 24.5097,
160 25.1759, 25.8815, 26.6378, 27.4112, 28.2157, 29.0271, 29.9248, 30.7977, 31.7510, 32.7041, 33.7583, 34.8513,
161 35.9103, 37.1485, 38.3861, 39.7035, 41.0022, 42.3003, 43.6234, 45.0080, 46.3782, 47.7918, 49.1901, 50.6580,
162 52.0537, 53.4410, 54.8608, 56.2165, 57.5229, 58.8066, 60.0287, 61.2283, 62.3879, 63.5055, 64.5241, 65.5107,
163 66.4050, 67.3491, 68.2172, 68.9896, 69.8158, 70.4611, 71.1646, 71.7663, 72.4042, 73.0496, 73.5342, 74.1307,
164 74.5450, 75.0907, 75.6212, 76.0865, 76.8541, 77.6080, 78.4420, 79.2248, 80.0880, 81.0277, 81.9300, 82.9188,
165 83.9960, 85.0072, 86.1661, 87.2706, 88.4430, 89.6940, 90.9562, 92.2918, 93.6533, 95.0087, 96.3996, 97.7745,
166 99.1749, 100.6474, 102.0441, 103.4479, 104.8626, 106.2086, 107.5305, 108.8386, 110.0599, 111.2366, 112.4078, 113.4710,
167 114.5671, 115.5359, 116.4890, 117.3761, 118.1778, 119.0282, 119.7657, 120.4136, 121.1364, 121.8754, 122.4186, 123.0246,
168 123.5694, 124.1640, 124.5444, 125.1546, 125.5514, 126.0263, 126.4062, 126.8301, 127.1727, 127.5432, 127.7796, 128.2254,
169 128.4639, 128.7937, 129.1810, 129.3844, 129.6880, 129.9609, 130.1609, 130.4174, 130.6324, 130.8404, 131.0484, 131.3148,
170 131.5413, 131.6463, 131.8371, 132.1471, 132.1629, 132.3846};
171
172 double amplCorrValue[150] = {
173 0.0011, 0.0019, 0.0028, 0.0047, 0.0077, 0.0111, 0.0145, 0.0207, 0.0261, 0.0322, 0.0412, 0.0491, 0.0576, 0.0663,
174 0.0749, 0.0830, 0.0875, 0.0912, 0.0929, 0.0931, 0.0920, 0.0901, 0.0875, 0.0841, 0.0800, 0.0756, 0.0711, 0.0663,
175 0.0609, 0.0557, 0.0506, 0.0453, 0.0402, 0.0351, 0.0299, 0.0260, 0.0216, 0.0173, 0.0141, 0.0109, 0.0076, 0.0049,
176 0.0022, 0.0003, -0.0014, -0.0021, -0.0029, -0.0029, -0.0025, -0.0023, -0.0013, 0.0004, 0.0017, 0.0043, 0.0072, 0.0104,
177 0.0141, 0.0181, 0.0232, 0.0277, 0.0338, 0.0387, 0.0451, 0.0514, 0.0582, 0.0648, 0.0720, 0.0787, 0.0855, 0.0924,
178 0.0992, 0.1064, 0.1125, 0.1187, 0.1232, 0.1079, 0.0779, 0.0672, 0.0622, 0.0570, 0.0515, 0.0463, 0.0415, 0.0362,
179 0.0314, 0.0266, 0.0221, 0.0181, 0.0143, 0.0103, 0.0073, 0.0047, 0.0021, 0.0003, -0.0010, -0.0024, -0.0027, -0.0030,
180 -0.0026, -0.0022, -0.0012, 0.0003, 0.0019, 0.0045, 0.0071, 0.0108, 0.0141, 0.0186, 0.0233, 0.0285, 0.0340, 0.0388,
181 0.0451, 0.0512, 0.0575, 0.0645, 0.0715, 0.0788, 0.0856, 0.0924, 0.0992, 0.1064, 0.1126, 0.1186, 0.1236, 0.1283,
182 0.1320, 0.1346, 0.1360, 0.1351, 0.1318, 0.1253, 0.1148, 0.1030, 0.0908, 0.0796, 0.0702, 0.0597, 0.0506, 0.0424,
183 0.0345, 0.0283, 0.0220, 0.0165, 0.0122, 0.0082, 0.0051, 0.0027, 0.0013, 0.0004};
184
185 unsigned int j;
186 for (j = 0; j < 150; j++) {
187 if (res.time < parabolapTime[j]) {
188 // with that way we keep the index, from which bin we get values from the tables
189 break;
190 }
191 }
192
193 if (j > 0 && j < 149) { // j should be at least 1 and at most 148..
194 double a = 0.;
195 double b = 0.;
196 double c = 0.;
197
198 double a1 = (bipolarpTime[j] - bipolarpTime[j - 1]);
199 // std::cout << "a1 = " << a1 << std::endl;
200 double a2 = (parabolapTime[j - 1] + parabolapTime[j]);
201 // std::cout << "a2 = " << a2 << std::endl;
202 double a3 = ((std::pow(parabolapTime[j + 1], 2) - std::pow(parabolapTime[j - 1], 2)) * (bipolarpTime[j] - bipolarpTime[j - 1]) -
203 (bipolarpTime[j + 1] - bipolarpTime[j - 1]) * (std::pow(parabolapTime[j], 2) - std::pow(parabolapTime[j - 1], 2)));
204 // std::cout << "a3 = " << a3 << std::endl;
205 double a4 = (parabolapTime[j - 1] + parabolapTime[j + 1]) *
206 ((parabolapTime[j - 1] - parabolapTime[j + 1]) * (parabolapTime[j - 1] + parabolapTime[j]) +
207 std::pow(parabolapTime[j], 2) - std::pow(parabolapTime[j - 1], 2));
208 // std::cout << "a4 = " << a4 << std::endl;
209 double a5 = std::pow(parabolapTime[j], 2) - std::pow(parabolapTime[j - 1], 2);
210 // std::cout << "a5 = " << a5 << std::endl;
211
212 // first constant
213 a = (a1 + (a2 * a3 / a4)) / a5;
214
215 // std::cout << "a = " << a << std::endl;
216 double b1 = (bipolarpTime[j + 1] - bipolarpTime[j - 1]);
217 double b2 = std::pow(parabolapTime[j], 2) - std::pow(parabolapTime[j - 1], 2);
218 double b3 = std::pow(parabolapTime[j + 1], 2) - std::pow(parabolapTime[j - 1], 2);
219 double b4 = (bipolarpTime[j] - bipolarpTime[j - 1]);
220 double b5 = (parabolapTime[j - 1] + parabolapTime[j + 1]);
221 double b6 = (parabolapTime[j - 1] - parabolapTime[j + 1]) * (parabolapTime[j - 1] + parabolapTime[j]) +
222 std::pow(parabolapTime[j], 2) - std::pow(parabolapTime[j - 1], 2);
223 // second constant
224 b = (b1 * b2 - b3 * b4) / (b5 * b6);
225 // std::cout << "b = " << b << std::endl;
226
227 // third constant
228 c = bipolarpTime[j - 1] - a * std::pow(parabolapTime[j - 1], 2) + b * parabolapTime[j - 1];
229
230 // std::cout << "c = " << c << std::endl;
231
232 double correctedTime = a * res.time * res.time + b * res.time + c;
233
234 if (correctedTime != 0.0) {
235 doPositionCorrection = true;
236
237 if (samplingPhase == 0) res.time = correctedTime;
238 if (samplingPhase == 1) res.time = correctedTime - 25;
239 }
240
241 ATH_MSG_DEBUG("After Correction time = " << res.time);
242 } // if ( j>0 && j < 149 ) {
243
244 if (doPositionCorrection) {
245 unsigned int l;
246 for (l = 0; l < 150; l++) {
247 if (res.time < parabolapTime[l]) {
248 // with that way we keep the index, from which bin we get values from the tables
249 break;
250 }
251 }
252
253 if (l > 0 && l < 149) {
254 double a_1 = (amplCorrValue[l] - amplCorrValue[l - 1]);
255 double a_2 = (parabolapTime[l - 1] + parabolapTime[l]);
256 double a_3 =
257 ((std::pow(parabolapTime[l + 1], 2) - std::pow(parabolapTime[l - 1], 2)) * (amplCorrValue[l] - amplCorrValue[l - 1]) -
258 (amplCorrValue[l + 1] - amplCorrValue[l - 1]) * (std::pow(parabolapTime[l], 2) - std::pow(parabolapTime[l - 1], 2)));
259 double a_4 = (parabolapTime[l - 1] + parabolapTime[l + 1]) *
260 ((parabolapTime[l - 1] - parabolapTime[l + 1]) * (parabolapTime[l - 1] + parabolapTime[l]) +
261 std::pow(parabolapTime[l], 2) - std::pow(parabolapTime[l - 1], 2));
262 double a_5 = std::pow(parabolapTime[l], 2) - std::pow(parabolapTime[l - 1], 2);
263 // first constant
264 double aConst = (a_1 + (a_2 * a_3 / a_4)) / a_5;
265
266 double b_1 = (amplCorrValue[l + 1] - amplCorrValue[l - 1]);
267 double b_2 = std::pow(parabolapTime[l], 2) - std::pow(parabolapTime[l - 1], 2);
268 double b_3 = std::pow(parabolapTime[l + 1], 2) - std::pow(parabolapTime[l - 1], 2);
269 double b_4 = (amplCorrValue[l] - amplCorrValue[l - 1]);
270 double b_5 = (parabolapTime[l - 1] + parabolapTime[l + 1]);
271 double b_6 = (parabolapTime[l - 1] - parabolapTime[l + 1]) * (parabolapTime[l - 1] + parabolapTime[l]) +
272 std::pow(parabolapTime[l], 2) - std::pow(parabolapTime[l - 1], 2);
273 // second constant
274 double bConst = (b_1 * b_2 - b_3 * b_4) / (b_5 * b_6);
275
276 // third constant
277 double cConst = amplCorrValue[l - 1] - aConst * std::pow(parabolapTime[l - 1], 2) + bConst * parabolapTime[l - 1];
278 double fixedValue = aConst * res.time * res.time + bConst * res.time + cConst;
279
280 res.charge = res.charge / (1 - fixedValue);
281
282 ATH_MSG_DEBUG("After Correction charge = " << res.charge);
283 }
284 } // if(doPositionCorrection)
285
287
288 res.time_beforeT0Corr = res.time;
289
290 double t0base = m_cscCalibTool->stripT0base(stripHash);
291 int t0phase = int(m_cscCalibTool->stripT0phase(stripHash));
292
293 res.time = res.time_beforeT0Corr - t0base - 12.5 * t0phase;
294 }
295
296 for (unsigned int i = 0; i < chgs.size(); ++i) {
297 if (m_cscCalibTool->numberOfElectronsToADCCount(stripHash, int(ped + chgs[i])) >= 4090) { // ADC unit
298 res.stripStatus = Muon::CscStrStatSaturated;
299 res.status += 4;
300 }
301 }
302
303 if (stripStatusWord & 0x1) {
304 res.stripStatus = Muon::CscStrStatHot;
305 res.status += 8;
306 } else if ((stripStatusWord >> 1) & 0x1) {
307 res.stripStatus = Muon::CscStrStatDead;
308 res.status += 16;
309 }
310
311 float max = -4090000;
312 // unsigned int imax =0;
313 for (unsigned int i = 0; i < chgs.size(); ++i) {
314 if (chgs[i] > max) {
315 max = chgs[i];
316 // imax = i;
317 }
318 }
319
320 if (res.stripStatus == Muon::CscStrStatSuccess || res.stripStatus == Muon::CscStrStatSaturated) {
321 res.timeStatus = Muon::CscTimeSuccess;
322 if (res.time < -500) {
323 res.timeStatus = Muon::CscTimeEarly;
324 } else if (res.time > 500) {
325 res.timeStatus = Muon::CscTimeLate;
326 }
327 } else if (res.stripStatus == Muon::CscStrStatUndefined) {
329 } else {
330 res.timeStatus = Muon::CscTimeUnavailable;
331 }
332
333 /*
334 Completed later
335
336 if (imax <= 1 && chgs[imax+1] <= chgs[imax+2] ) {
337 res.stripStatus = Muon::CscStrStatNoBipolarShape;
338 }
339 */
340
341 res.dtime = !res.stripStatus ? m_terr : m_terr_fail;
342
343 // Add an error proportional to the charge.
344 double dqprop = m_qerrprop * res.charge;
345 res.dcharge = sqrt(res.dcharge * res.dcharge + dqprop * dqprop);
346
347 // if (res.charge ==0) res.charge =40;
348
349 return res;
350}
351
352//**********************************************************************
353// for (int i=1; i<2000; i++){
354// ATH_MSG_DEBUG ( " ADC counts: " << 1.0*i
355// << " Charges: " << m_cscCalibTool->adcCountToNumberOfElectrons(i) << endl;
356// }
#define ATH_CHECK_RECOVERABLE
Evaluate an expression and check for errors.
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
ICscStripFitter::ChargeList ChargeList
std::pair< std::vector< unsigned int >, bool > res
static Double_t a
#define max(a, b)
Definition cfImp.cxx:41
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
CalibCscStripFitter(const std::string &, const std::string &, const IInterface *)
Result fit(const ChargeList &ChargeList, double samplingTime, bool samplingPhase, Identifier &sid) const
ToolHandle< ICscCalibTool > m_cscCalibTool
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
std::vector< float > ChargeList
This is a "hash" representation of an Identifier.
void show() const
Print out in hex form.
Class representing the raw data of one CSC strip (for clusters look at Muon::CscPrepData).
@ CscStrStatParabolaFailed
@ CscStrStatDead
@ CscStrStatHot
@ CscStrStatSaturated
@ CscStrStatUndefined
Undefined, should not happen, most likely indicates a problem.
@ CscStrStatSuccess
@ CscTimeSuccess
Time measurement is successful to use.
@ CscTimeStatusUndefined
Time is not assessed indicating potential bug.
@ CscTimeEarly
Not successful time measurement but samples indicates early time below -50ns in RAW time.
@ CscTimeLate
Not successful time measurement but samples indicates late time above 200ns in RAW time.
@ CscTimeUnavailable
Time information is not available due to dead/noise/stuck bit channels.