-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathMuonScaRe.cc
140 lines (121 loc) · 3.89 KB
/
MuonScaRe.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#include <boost/math/special_functions/erf.hpp>
struct CrystalBall{
double pi=3.14159;
double sqrtPiOver2=sqrt(pi/2.0);
double sqrt2=sqrt(2.0);
double m;
double s;
double a;
double n;
double B;
double C;
double D;
double N;
double NA;
double Ns;
double NC;
double F;
double G;
double k;
double cdfMa;
double cdfPa;
CrystalBall():m(0),s(1),a(10),n(10){
init();
}
CrystalBall(double mean, double sigma, double alpha, double n)
:m(mean),s(sigma),a(alpha),n(n){
init();
}
void init(){
double fa = fabs(a);
double ex = exp(-fa*fa/2);
double A = pow(n/fa, n) * ex;
double C1 = n/fa/(n-1) * ex;
double D1 = 2 * sqrtPiOver2 * erf(fa/sqrt2);
B = n/fa-fa;
C = (D1+2*C1)/C1;
D = (D1+2*C1)/2;
N = 1.0/s/(D1+2*C1);
k = 1.0/(n-1);
NA = N*A;
Ns = N*s;
NC = Ns*C1;
F = 1-fa*fa/n;
G = s*n/fa;
cdfMa = cdf(m-a*s);
cdfPa = cdf(m+a*s);
}
double pdf(double x) const{
double d=(x-m)/s;
if(d<-a) return NA*pow(B-d, -n);
if(d>a) return NA*pow(B+d, -n);
return N*exp(-d*d/2);
}
double pdf(double x, double ks, double dm) const{
double d=(x-m-dm)/(s*ks);
if(d<-a) return NA/ks*pow(B-d, -n);
if(d>a) return NA/ks*pow(B+d, -n);
return N/ks*exp(-d*d/2);
}
double cdf(double x) const{
double d = (x-m)/s;
if(d<-a) return NC / pow(F-s*d/G, n-1);
if(d>a) return NC * (C - pow(F+s*d/G, 1-n) );
return Ns * (D - sqrtPiOver2 * erf(-d/sqrt2));
}
double invcdf(double u) const{
if(u<cdfMa) return m + G*(F - pow(NC/u, k));
if(u>cdfPa) return m - G*(F - pow(C-u/NC, -k) );
return m - sqrt2 * s * boost::math::erf_inv((D - u/Ns )/sqrtPiOver2);
}
};
double get_rndm(double eta, float nL) {
// obtain parameters from correctionlib
double mean = cset->at("cb_params")->evaluate({abs(eta), nL, 0});
double sigma = cset->at("cb_params")->evaluate({abs(eta), nL, 1});
double n = cset->at("cb_params")->evaluate({abs(eta), nL, 2});
double alpha = cset->at("cb_params")->evaluate({abs(eta), nL, 3});
// instantiate CB and get random number following the CB
CrystalBall cb(mean, sigma, alpha, n);
TRandom3 rnd(time(0));
double rndm = gRandom->Rndm();
return cb.invcdf(rndm);
}
double get_std(double pt, double eta, float nL) {
// obtain paramters from correctionlib
double param_0 = cset->at("poly_params")->evaluate({abs(eta), nL, 0});
double param_1 = cset->at("poly_params")->evaluate({abs(eta), nL, 1});
double param_2 = cset->at("poly_params")->evaluate({abs(eta), nL, 2});
// calculate value and return max(0, val)
double sigma = param_0 + param_1 * pt + param_2 * pt*pt;
if (sigma < 0) sigma = 0;
return sigma;
}
double get_k(double eta, string var) {
// obtain parameters from correctionlib
double k_data = cset->at("k_data")->evaluate({abs(eta), var});
double k_mc = cset->at("k_mc")->evaluate({abs(eta), var});
// calculate residual smearing factor
// return 0 if smearing in MC already larger than in data
double k = 0;
if (k_mc < k_data) k = sqrt(k_data*k_data - k_mc*k_mc);
return k;
}
double pt_resol(double pt, double eta, float nL, string var) {
// load correction values
double rndm = (double) get_rndm(eta, nL);
double std = (double) get_std(pt, eta, nL);
double k = (double) get_k(eta, var);
// calculate corrected value and return original value if a parameter is nan
double ptc = pt * ( 1 + k * std * rndm);
if (isnan(ptc)) ptc = pt;
return ptc;
}
double pt_scale(bool is_data, double pt, double eta, double phi, int charge, string var) {
// use right correction
string dtmc = "mc";
if (is_data) dtmc = "data";
double a = cset->at("a_"+dtmc)->evaluate({eta, phi, var});
double m = cset->at("m_"+dtmc)->evaluate({eta, phi, var});
return 1. / (m/pt + charge * a);
}