ATLAS Offline Software
Loading...
Searching...
No Matches
CalibCscStripFitter.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 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 \n" << stripId);
79 }
80
81 int zsec = m_idHelperSvc->cscIdHelper().stationEta(stripId);
82 int phisec = m_idHelperSvc->cscIdHelper().stationPhi(stripId);
83 int station = m_idHelperSvc->cscIdHelper().stationName(stripId) - 49;
84
85 int sector = zsec * (2 * phisec - station + 1);
86
87 int wlay = m_idHelperSvc->cscIdHelper().wireLayer(stripId);
88 int measphi = m_idHelperSvc->cscIdHelper().measuresPhi(stripId);
89 int istrip = m_idHelperSvc->cscIdHelper().strip(stripId);
90
91 double ped = m_cscCalibTool->stripPedestal(stripHash);
92 // Get noise information
93 double noise = 0;
94 if (m_noiseOption == rms) {
95 noise = m_cscCalibTool->stripRMS(stripHash);
96 } else if (m_noiseOption == sigma) {
97 noise = m_cscCalibTool->stripNoise(stripHash);
98 } else if (m_noiseOption == f001) { // f001 is rawADC +1
99 noise = m_cscCalibTool->stripF001(stripHash) - m_cscCalibTool->stripPedestal(stripHash);
100 noise /= 3.251;
101 }
102
103 // bool isGood = m_cscCalibTool->isGood(stripHash);
104 int stripStatusWord = m_cscCalibTool->stripStatusBit(stripHash);
105
106 bool showDetail = false;
107 if (noise <= 0.0) {
108 showDetail = true;
109 ATH_MSG_DEBUG(" Noise is zero!! DB needs to be fixed for this channel. 4151.06 (3.5ADC) is assigned.");
110 noise = 4151.06;
111 }
112
113 noise = m_chargeErrorScaler * noise;
114
115 if (ped < 1.0) {
116 showDetail = true;
117 ATH_MSG_DEBUG(" Pedestal is zero!! DB needs to be fixed for this channel. 2048*1013 (2048ADC) is assigned.");
118 // ped = 0; // 2048 ADC as a default...
119 // unrealistic.... DB should be corrupted....
120 }
121
122 if (showDetail)
123 ATH_MSG_DEBUG("noiseOption " << m_noiseOptionStr << " noise= " << noise << " pedestal= " << ped << " strIdentifier= " << stripId
124 << " strHash= " << (unsigned int)stripHash << " zsec:phisec:istation sector " << zsec << ":"
125 << phisec << ":" << station << " " << sector << " wlay:measphi:istr = " << wlay << " " << measphi
126 << " " << istrip << " Charges: " << chgs << " (Sample time: " << period << " ns)");
127
128 // Fit with calib tool.
129 res.phase = samplingPhase;
130 res.dcharge = noise;
131
132 if (m_cscCalibTool->findCharge(period, samplingPhase, chgs, res.charge, res.time)) { // success
133 res.stripStatus = Muon::CscStrStatSuccess;
134 res.status += 1;
135 } else {
137 res.status += 2;
138 }
139
140 res.charge_beforeBPCorr = res.charge;
141 res.time_beforeBPCorr = res.time;
142
143 if (samplingPhase == 1) // This is bipolar correction purpose and will be subtracted...
144 res.time = res.time + 25;
145
146 if (m_doCorrection) { // m_ denotes global variables...
147
148 bool doPositionCorrection = false;
149
150 ATH_MSG_DEBUG("Without any correction res.time = " << res.time);
151 ATH_MSG_DEBUG("Without any correction res.charge = " << res.charge);
152
153 double parabolapTime[150];
154 for (int i = 0; i < 150; ++i) { parabolapTime[i] = 0.5 + i; }
155
156 double bipolarpTime[150] = {
157 7.2767, 14.6497, 14.9118, 15.3129, 15.5765, 15.8889, 16.2474, 16.6022, 16.9897, 17.3629, 17.7400, 18.2157,
158 18.6235, 19.0662, 19.4730, 19.9940, 20.4652, 20.9776, 21.4932, 22.0852, 22.6554, 23.2433, 23.8237, 24.5097,
159 25.1759, 25.8815, 26.6378, 27.4112, 28.2157, 29.0271, 29.9248, 30.7977, 31.7510, 32.7041, 33.7583, 34.8513,
160 35.9103, 37.1485, 38.3861, 39.7035, 41.0022, 42.3003, 43.6234, 45.0080, 46.3782, 47.7918, 49.1901, 50.6580,
161 52.0537, 53.4410, 54.8608, 56.2165, 57.5229, 58.8066, 60.0287, 61.2283, 62.3879, 63.5055, 64.5241, 65.5107,
162 66.4050, 67.3491, 68.2172, 68.9896, 69.8158, 70.4611, 71.1646, 71.7663, 72.4042, 73.0496, 73.5342, 74.1307,
163 74.5450, 75.0907, 75.6212, 76.0865, 76.8541, 77.6080, 78.4420, 79.2248, 80.0880, 81.0277, 81.9300, 82.9188,
164 83.9960, 85.0072, 86.1661, 87.2706, 88.4430, 89.6940, 90.9562, 92.2918, 93.6533, 95.0087, 96.3996, 97.7745,
165 99.1749, 100.6474, 102.0441, 103.4479, 104.8626, 106.2086, 107.5305, 108.8386, 110.0599, 111.2366, 112.4078, 113.4710,
166 114.5671, 115.5359, 116.4890, 117.3761, 118.1778, 119.0282, 119.7657, 120.4136, 121.1364, 121.8754, 122.4186, 123.0246,
167 123.5694, 124.1640, 124.5444, 125.1546, 125.5514, 126.0263, 126.4062, 126.8301, 127.1727, 127.5432, 127.7796, 128.2254,
168 128.4639, 128.7937, 129.1810, 129.3844, 129.6880, 129.9609, 130.1609, 130.4174, 130.6324, 130.8404, 131.0484, 131.3148,
169 131.5413, 131.6463, 131.8371, 132.1471, 132.1629, 132.3846};
170
171 double amplCorrValue[150] = {
172 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,
173 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,
174 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,
175 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,
176 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,
177 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,
178 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,
179 -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,
180 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,
181 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,
182 0.0345, 0.0283, 0.0220, 0.0165, 0.0122, 0.0082, 0.0051, 0.0027, 0.0013, 0.0004};
183
184 unsigned int j;
185 for (j = 0; j < 150; j++) {
186 if (res.time < parabolapTime[j]) {
187 // with that way we keep the index, from which bin we get values from the tables
188 break;
189 }
190 }
191
192 if (j > 0 && j < 149) { // j should be at least 1 and at most 148..
193 double a = 0.;
194 double b = 0.;
195 double c = 0.;
196
197 double a1 = (bipolarpTime[j] - bipolarpTime[j - 1]);
198 // std::cout << "a1 = " << a1 << std::endl;
199 double a2 = (parabolapTime[j - 1] + parabolapTime[j]);
200 // std::cout << "a2 = " << a2 << std::endl;
201 double a3 = ((std::pow(parabolapTime[j + 1], 2) - std::pow(parabolapTime[j - 1], 2)) * (bipolarpTime[j] - bipolarpTime[j - 1]) -
202 (bipolarpTime[j + 1] - bipolarpTime[j - 1]) * (std::pow(parabolapTime[j], 2) - std::pow(parabolapTime[j - 1], 2)));
203 // std::cout << "a3 = " << a3 << std::endl;
204 double a4 = (parabolapTime[j - 1] + parabolapTime[j + 1]) *
205 ((parabolapTime[j - 1] - parabolapTime[j + 1]) * (parabolapTime[j - 1] + parabolapTime[j]) +
206 std::pow(parabolapTime[j], 2) - std::pow(parabolapTime[j - 1], 2));
207 // std::cout << "a4 = " << a4 << std::endl;
208 double a5 = std::pow(parabolapTime[j], 2) - std::pow(parabolapTime[j - 1], 2);
209 // std::cout << "a5 = " << a5 << std::endl;
210
211 // first constant
212 a = (a1 + (a2 * a3 / a4)) / a5;
213
214 // std::cout << "a = " << a << std::endl;
215 double b1 = (bipolarpTime[j + 1] - bipolarpTime[j - 1]);
216 double b2 = std::pow(parabolapTime[j], 2) - std::pow(parabolapTime[j - 1], 2);
217 double b3 = std::pow(parabolapTime[j + 1], 2) - std::pow(parabolapTime[j - 1], 2);
218 double b4 = (bipolarpTime[j] - bipolarpTime[j - 1]);
219 double b5 = (parabolapTime[j - 1] + parabolapTime[j + 1]);
220 double b6 = (parabolapTime[j - 1] - parabolapTime[j + 1]) * (parabolapTime[j - 1] + parabolapTime[j]) +
221 std::pow(parabolapTime[j], 2) - std::pow(parabolapTime[j - 1], 2);
222 // second constant
223 b = (b1 * b2 - b3 * b4) / (b5 * b6);
224 // std::cout << "b = " << b << std::endl;
225
226 // third constant
227 c = bipolarpTime[j - 1] - a * std::pow(parabolapTime[j - 1], 2) + b * parabolapTime[j - 1];
228
229 // std::cout << "c = " << c << std::endl;
230
231 double correctedTime = a * res.time * res.time + b * res.time + c;
232
233 if (correctedTime != 0.0) {
234 doPositionCorrection = true;
235
236 if (samplingPhase == 0) res.time = correctedTime;
237 if (samplingPhase == 1) res.time = correctedTime - 25;
238 }
239
240 ATH_MSG_DEBUG("After Correction time = " << res.time);
241 } // if ( j>0 && j < 149 ) {
242
243 if (doPositionCorrection) {
244 unsigned int l;
245 for (l = 0; l < 150; l++) {
246 if (res.time < parabolapTime[l]) {
247 // with that way we keep the index, from which bin we get values from the tables
248 break;
249 }
250 }
251
252 if (l > 0 && l < 149) {
253 double a_1 = (amplCorrValue[l] - amplCorrValue[l - 1]);
254 double a_2 = (parabolapTime[l - 1] + parabolapTime[l]);
255 double a_3 =
256 ((std::pow(parabolapTime[l + 1], 2) - std::pow(parabolapTime[l - 1], 2)) * (amplCorrValue[l] - amplCorrValue[l - 1]) -
257 (amplCorrValue[l + 1] - amplCorrValue[l - 1]) * (std::pow(parabolapTime[l], 2) - std::pow(parabolapTime[l - 1], 2)));
258 double a_4 = (parabolapTime[l - 1] + parabolapTime[l + 1]) *
259 ((parabolapTime[l - 1] - parabolapTime[l + 1]) * (parabolapTime[l - 1] + parabolapTime[l]) +
260 std::pow(parabolapTime[l], 2) - std::pow(parabolapTime[l - 1], 2));
261 double a_5 = std::pow(parabolapTime[l], 2) - std::pow(parabolapTime[l - 1], 2);
262 // first constant
263 double aConst = (a_1 + (a_2 * a_3 / a_4)) / a_5;
264
265 double b_1 = (amplCorrValue[l + 1] - amplCorrValue[l - 1]);
266 double b_2 = std::pow(parabolapTime[l], 2) - std::pow(parabolapTime[l - 1], 2);
267 double b_3 = std::pow(parabolapTime[l + 1], 2) - std::pow(parabolapTime[l - 1], 2);
268 double b_4 = (amplCorrValue[l] - amplCorrValue[l - 1]);
269 double b_5 = (parabolapTime[l - 1] + parabolapTime[l + 1]);
270 double b_6 = (parabolapTime[l - 1] - parabolapTime[l + 1]) * (parabolapTime[l - 1] + parabolapTime[l]) +
271 std::pow(parabolapTime[l], 2) - std::pow(parabolapTime[l - 1], 2);
272 // second constant
273 double bConst = (b_1 * b_2 - b_3 * b_4) / (b_5 * b_6);
274
275 // third constant
276 double cConst = amplCorrValue[l - 1] - aConst * std::pow(parabolapTime[l - 1], 2) + bConst * parabolapTime[l - 1];
277 double fixedValue = aConst * res.time * res.time + bConst * res.time + cConst;
278
279 res.charge = res.charge / (1 - fixedValue);
280
281 ATH_MSG_DEBUG("After Correction charge = " << res.charge);
282 }
283 } // if(doPositionCorrection)
284
286
287 res.time_beforeT0Corr = res.time;
288
289 double t0base = m_cscCalibTool->stripT0base(stripHash);
290 int t0phase = int(m_cscCalibTool->stripT0phase(stripHash));
291
292 res.time = res.time_beforeT0Corr - t0base - 12.5 * t0phase;
293 }
294
295 for (unsigned int i = 0; i < chgs.size(); ++i) {
296 if (m_cscCalibTool->numberOfElectronsToADCCount(stripHash, int(ped + chgs[i])) >= 4090) { // ADC unit
297 res.stripStatus = Muon::CscStrStatSaturated;
298 res.status += 4;
299 }
300 }
301
302 if (stripStatusWord & 0x1) {
303 res.stripStatus = Muon::CscStrStatHot;
304 res.status += 8;
305 } else if ((stripStatusWord >> 1) & 0x1) {
306 res.stripStatus = Muon::CscStrStatDead;
307 res.status += 16;
308 }
309
310 float max = -4090000;
311 // unsigned int imax =0;
312 for (unsigned int i = 0; i < chgs.size(); ++i) {
313 if (chgs[i] > max) {
314 max = chgs[i];
315 // imax = i;
316 }
317 }
318
319 if (res.stripStatus == Muon::CscStrStatSuccess || res.stripStatus == Muon::CscStrStatSaturated) {
320 res.timeStatus = Muon::CscTimeSuccess;
321 if (res.time < -500) {
322 res.timeStatus = Muon::CscTimeEarly;
323 } else if (res.time > 500) {
324 res.timeStatus = Muon::CscTimeLate;
325 }
326 } else if (res.stripStatus == Muon::CscStrStatUndefined) {
328 } else {
329 res.timeStatus = Muon::CscTimeUnavailable;
330 }
331
332 /*
333 Completed later
334
335 if (imax <= 1 && chgs[imax+1] <= chgs[imax+2] ) {
336 res.stripStatus = Muon::CscStrStatNoBipolarShape;
337 }
338 */
339
340 res.dtime = !res.stripStatus ? m_terr : m_terr_fail;
341
342 // Add an error proportional to the charge.
343 double dqprop = m_qerrprop * res.charge;
344 res.dcharge = sqrt(res.dcharge * res.dcharge + dqprop * dqprop);
345
346 // if (res.charge ==0) res.charge =40;
347
348 return res;
349}
350
351//**********************************************************************
352// for (int i=1; i<2000; i++){
353// ATH_MSG_DEBUG ( " ADC counts: " << 1.0*i
354// << " Charges: " << m_cscCalibTool->adcCountToNumberOfElectrons(i) << endl;
355// }
#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.
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.