ATLAS Offline Software
Loading...
Searching...
No Matches
OnlineLumiCalibrator.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7#include "CoralBase/Attribute.h"
8#include "CoralBase/Blob.h"
9#include "CoolKernel/StorageType.h"
10
11#include <cmath>
12#include <iostream>
13
14#ifdef __linux__
15#include <endian.h>
16static_assert (__FLOAT_WORD_ORDER == __LITTLE_ENDIAN,
17 "OnlineLumiCalibrator assumes little-endian byte ordering.");
18#endif
19
20//--------------------------------------------------
22 m_nPar(0),
23 m_fType(""),
24 m_muToLumi(-1.) // Nonsensical intialization value
25{
26 m_parVec.clear();
27}
28
30 : m_nPar (other.m_nPar),
31 m_fType (std::move (other.m_fType)),
32 m_muToLumi (other.m_muToLumi),
33 m_parVec (std::move (other.m_parVec))
34{
35}
36
37
40{
41 if (this != &other) {
42 m_nPar = other.m_nPar;
43 m_fType = std::move (other.m_fType);
44 m_muToLumi = other.m_muToLumi;
45 m_parVec = std::move (other.m_parVec);
46 }
47 return *this;
48}
49
50
51// Return false on error
52bool
53OnlineLumiCalibrator::setCalibration(const coral::AttributeList& attrList)
54{
55 if (attrList["NumOfParameters"].isNull()) return false;
56 m_nPar = attrList["NumOfParameters"].data<uint32_t>();
57
58 if (attrList["Function"].isNull()) return false;
59 m_fType = attrList["Function"].data<std::string>();
60
61 if (attrList["MuToLumi"].isNull()) return false;
62 m_muToLumi = attrList["MuToLumi"].data<float>();
63
64 if (attrList["Parameters"].isNull()) return false;
65 const coral::Blob& blob = attrList["Parameters"].data<coral::Blob>();
66
67
68 // Verify length
69 if ( static_cast<uint32_t>( blob.size() ) != 4*m_nPar) return false;
70
71 // Read calibration parameters
72 const float* p = static_cast<const float*>(blob.startingAddress());
73 for (unsigned int i=0; i<m_nPar; i++, p++)
74 m_parVec.push_back(*p);
75
76 return true;
77}
78
79float
84
85// Return False on error
86bool
87OnlineLumiCalibrator::calibrateLumi(const std::vector<float>& rawLumi, std::vector<float>& calLumi) const
88{
89 calLumi.clear();
90 bool error = false;
91 float calValue;
92 for (float val : rawLumi) {
93 calValue = 0;
94 if (!calibrateLumi(val, calValue)) {
95 error = true;
96 calLumi.push_back(0.);
97 } else {
98 calLumi.push_back(calValue);
99 }
100 }
101 return error;
102}
103
104// Return False on error
105bool
106OnlineLumiCalibrator::calibrateMu(const std::vector<float>& rawLumi, std::vector<float>& calMu) const
107{
108 calMu.clear();
109 bool error = false;
110 float calValue;
111 for (float val : rawLumi) {
112 calValue = 0;
113 if (!calibrateMu(val, calValue)) {
114 error = true;
115 calMu.push_back(0.);
116 } else {
117 calMu.push_back(calValue);
118 }
119 }
120 return error;
121}
122
123// Return False on error
124bool
125OnlineLumiCalibrator::calibrateLumi(float rawLumi, float& calLumi) const
126{
127 calLumi = 0;
128 float calMu = 0.;
129 if (!calibrateMu(rawLumi, calMu)) return false;
130 calLumi = calMu * m_muToLumi;
131 return true;
132}
133
134// Return False on error
135bool
136OnlineLumiCalibrator::calibrateMu(float rawLumi, float& calMu) const
137{
138 calMu = 0.;
139
140 if (m_fType == "Polynomial") {
141
142 // Check parameter length
143 if (m_parVec.size() < 1) return false;
144
145 unsigned int nrange = m_parVec[0];
146
147 // Check parameter size again
148 if (m_parVec.size() < (8*nrange + 1)) return false;
149
150 for (unsigned int i=0; i<nrange; i++) {
151 float rmin = m_parVec[8*i+1];
152 float rmax = m_parVec[8*i+2];
153 if (rawLumi < rmax and rawLumi >= rmin) {
154 calMu += m_parVec[8*i+3] * pow(rawLumi, 0);
155 calMu += m_parVec[8*i+4] * pow(rawLumi, 1);
156 calMu += m_parVec[8*i+5] * pow(rawLumi, 2);
157 calMu += m_parVec[8*i+6] * pow(rawLumi, 3);
158 calMu += m_parVec[8*i+7] * pow(rawLumi, 4);
159 calMu += m_parVec[8*i+8] * pow(rawLumi, 5);
160 break;
161 }
162 }
163 return true;
164 }
165
166 if (m_fType == "Logarithm") {
167
168 // Check parameter length
169 if (m_parVec.size() != 1) return false;
170
171 // Check input for physically allowed range
172 if ((1.-rawLumi) <= 0.) return false;
173
174 // Convert negative luminosity to zero
175 if (rawLumi < 0.) return false;
176
177 calMu = -m_parVec[0] * log(1.-rawLumi);
178 return true;
179 }
180
181 if (m_fType == "HitLogarithm") {
182
183 // Check parameter length
184 if (m_parVec.size() != 4) return false;
185
186 // Channel count must be > 0
187 if (m_parVec[1] <= 0.) return false;
188
189 // Check input value for physically allowed range
190 if ((1.-rawLumi/m_parVec[1]) <= 0.) return false;
191
192 // Convert negative luminosity to zero
193 if (rawLumi < 0.) return false;
194
195 calMu = -m_parVec[0] * log(1.-rawLumi/m_parVec[1])/(1.-m_parVec[2]);
196 return true;
197 }
198
199 if (m_fType == "LookupTable_EventAND_Lin") {
200
201 // Check parameter size
202 if (m_parVec.size() != 6) return false;
203
204 if (rawLumi < 0.) return false;
205
206 float sigo = m_parVec[0];
207 float siga = m_parVec[1];
208 calMu = m_parVec[5] * getMuVis(rawLumi, sigo, siga);
209
210 if (calMu < 0.) { // Indicates an error, try again
211 calMu = m_parVec[5] * getMuVis2(rawLumi, sigo, siga);
212 }
213
214 if (calMu < 0.) { // Indicates an error
215 calMu = 0.;
216 return false;
217 }
218
219 return true;
220 }
221
222 if (m_fType == "LookupTable_EventAND_Log") {
223
224 // Check parameter size
225 if (m_parVec.size() != 8) return false;
226
227 if (rawLumi < 0.) return false;
228
229 float sigo = m_parVec[0];
230 float siga = m_parVec[1];
231 calMu = m_parVec[7] * getMuVis(rawLumi, sigo, siga);
232
233 if (calMu < 0.) { // Indicates an error, try again
234 calMu = m_parVec[7] * getMuVis2(rawLumi, sigo, siga);
235 }
236
237 if (calMu < 0.) { // Indicates an error
238 calMu = 0.;
239 return false;
240 }
241
242 return true;
243 }
244
245 // Unknown type
246 return false;
247}
248
249// Vincent's Newton-Rhapson method
250float
251OnlineLumiCalibrator::getMuVis(float rawPerBX, float sigo, float siga) const
252{
253
254 //std::cout << "getMuVis("<<rawPerBX<<","<<sigo<<","<<siga<<")"<<std::endl;
255
256 float mu, y, dy;
257 float munew = 0.01;
258 float a = (sigo/siga + 1) / 2.;
259 float b = sigo/siga;
260
261 // Set a fixed number of cycles, but break if we converge faster
262 for (int i=0; i<30; i++) {
263 mu = munew;
264 y = rawPerBX - 1. - exp(-b * mu) + 2. * exp(-a * mu);
265 dy = b * exp(-b * mu) - 2. * a * exp(-a * mu);
266 munew = mu-y/dy;
267
268 //std::cout << i <<" - munew: " << munew << " mu:" << mu << " diff:"
269 // << fabs(munew-mu) << std::endl;
270
271 // Protect against unphysical values
272 if (munew <= 0.) return -1.;
273 if (fabs(munew-mu)/munew < 1.E-5) break;
274 }
275
276 return munew;
277}
278
279// Mika's original brute-force method
280float rpbx(float sr, float mu) {
281 return 1. - 2.*exp(-(1+sr)*mu/2.) + exp(-sr*mu);
282}
283
284float
285OnlineLumiCalibrator::getMuVis2(float rawPerBX, float sigo, float siga) const
286{
287 float muvl=1e-10;
288 float muvu=100.;
289 float muvm=10.;
290 float sr=sigo/siga;
291 float rbxl=rpbx(sr,muvl);
292 float rbxu=rpbx(sr,muvu);
293 float rbxm=rpbx(sr,muvm);
294
295 // Check that starting value is in the valid range
296 if (rawPerBX < rbxl || rawPerBX > rbxu) return -1.;
297
298 int i=0;
299 while (++i <= 50) {
300 if (rbxl<rawPerBX && rbxm>rawPerBX) {
301 rbxu=rbxm;
302 muvu=muvm;
303 muvm=0.5*(muvu+muvl);
304 } else {
305 rbxl=rbxm;
306 muvl=muvm;
307 muvm=0.5*(muvu+muvl);
308 }
309
310 rbxm = rpbx(sr, muvm);
311 //std::cout << i <<" - munew: " << muvu << " mu:" << muvl << " diff:" << fabs(muvu-muvl) << std::endl;
312
313 if ((muvu-muvl)/muvl < 1e-5) return muvm;
314 }
315
316 // Didn't converge
317 return -1.;
318}
319
320// Dump out parameters
321MsgStream&
322OnlineLumiCalibrator::dump(MsgStream &stream) const {
323 stream << m_fType << " Npar = " << m_nPar << " MuToLumi = " << m_muToLumi << " ParVec: " << m_parVec;
324 return stream;
325}
static Double_t a
float rpbx(float sr, float mu)
#define y
constexpr int pow(int base, int exp) noexcept
Utility class to apply calibrations from /TDAQ/OLC/CALIBRATIONS folder.
float getMuVis2(float rawPerBX, float sigo, float siga) const
float getMuVis(float rawPerBX, float sigo, float siga) const
bool calibrateLumi(float rawLumi, float &calLumi) const
bool calibrateMu(float rawLumi, float &calMu) const
std::vector< float > m_parVec
MsgStream & dump(MsgStream &) const
OnlineLumiCalibrator & operator=(const OnlineLumiCalibrator &)=default
bool setCalibration(const coral::AttributeList &attrList)
STL namespace.