File indexing completed on 2025-04-19 09:06:51
0001
0002 #ifndef RIVET_ExptSmearingFunctions_HH
0003 #define RIVET_ExptSmearingFunctions_HH
0004
0005 #include "Rivet/Tools/MomentumSmearingFunctions.hh"
0006 #include "Rivet/Tools/ParticleSmearingFunctions.hh"
0007 #include "Rivet/Tools/JetSmearingFunctions.hh"
0008
0009 namespace Rivet {
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020 inline double ELECTRON_RECOEFF_ATLAS_RUN1(const Particle& e) {
0021 if (e.abspid() != PID::ELECTRON) return 0;
0022 if (e.abseta() > 2.5) return 0;
0023 if (e.pT() < 10*GeV) return 0;
0024 return (e.abseta() < 1.5) ? 0.95 : 0.85;
0025 }
0026
0027
0028
0029
0030 inline double ELECTRON_RECOEFF_ATLAS_RUN2(const Particle& e) {
0031 if (e.abspid() != PID::ELECTRON) return 0;
0032 const double et = e.Et();
0033 if (e.abseta() > 2.5 || e.Et() < 2*GeV) return 0;
0034 if (et > 25*GeV) return 0.97;
0035 if (et > 10*GeV) return 0.92 + (et/GeV-10)/15.*0.05;
0036 if (et > 6*GeV) return 0.85 + (et/GeV-6)/4.*0.07;
0037 if (et > 5*GeV) return 0.70 + (et/GeV-5)/1.*0.15;
0038 if (et > 2*GeV) return 0.00 + (et/GeV-2)/3.*0.70;
0039 return 0;
0040 }
0041
0042
0043
0044
0045
0046
0047 inline double ELECTRON_EFF_ATLAS_RUN2_LOOSE(const Particle& e) {
0048 if (e.abspid() != PID::ELECTRON) return 0;
0049
0050
0051 const static vector<double> edges_eta = { 0.0, 0.1, 0.8, 1.37, 1.52, 2.01, 2.37, 2.47 };
0052 const static vector<double> effs_eta = { 0.950, 0.965, 0.955, 0.885, 0.950, 0.935, 0.90 };
0053
0054 const static vector<double> edges_et = { 0, 10, 20, 25, 30, 35, 40, 45, 50, 60, 80 };
0055 const static vector<double> effs_et = { 0.0, 0.90, 0.91, 0.92, 0.94, 0.95, 0.955, 0.965, 0.97, 0.98, 0.98 };
0056
0057 if (e.abseta() > 2.47) return 0.0;
0058
0059 const int i_eta = binIndex(e.abseta(), edges_eta);
0060 const int i_et = binIndex(e.Et()/GeV, edges_et, true);
0061 const double eff = effs_et[i_et] * effs_eta[i_eta] / 0.95;
0062 return min(eff, 1.0) * ELECTRON_RECOEFF_ATLAS_RUN2(e);
0063 }
0064
0065
0066
0067 inline double ELECTRON_EFF_ATLAS_RUN1_MEDIUM(const Particle& e) {
0068 if (e.abspid() != PID::ELECTRON) return 0;
0069
0070 const static vector<double> eta_edges_10 = {0.000, 0.049, 0.454, 1.107, 1.46, 1.790, 2.277, 2.500};
0071 const static vector<double> eta_vals_10 = {0.730, 0.757, 0.780, 0.771, 0.77, 0.777, 0.778};
0072
0073 const static vector<double> eta_edges_15 = {0.000, 0.053, 0.456, 1.102, 1.463, 1.783, 2.263, 2.500};
0074 const static vector<double> eta_vals_15 = {0.780, 0.800, 0.819, 0.759, 0.749, 0.813, 0.829};
0075
0076 const static vector<double> eta_edges_20 = {0.000, 0.065, 0.362, 0.719, 0.980, 1.289, 1.455, 1.681, 1.942, 2.239, 2.452, 2.500};
0077 const static vector<double> eta_vals_20 = {0.794, 0.806, 0.816, 0.806, 0.797, 0.774, 0.764, 0.788, 0.793, 0.806, 0.825};
0078
0079 const static vector<double> eta_edges_25 = {0.000, 0.077, 0.338, 0.742, 1.004, 1.265, 1.467, 1.692, 1.940, 2.227, 2.452, 2.500};
0080 const static vector<double> eta_vals_25 = {0.833, 0.843, 0.853, 0.845, 0.839, 0.804, 0.790, 0.825, 0.830, 0.833, 0.839};
0081
0082 const static vector<double> eta_edges_30 = {0.000, 0.077, 0.350, 0.707, 0.980, 1.289, 1.479, 1.681, 1.942, 2.239, 2.441, 2.500};
0083 const static vector<double> eta_vals_30 = {0.863, 0.872, 0.881, 0.874, 0.870, 0.824, 0.808, 0.847, 0.845, 0.840, 0.842};
0084
0085 const static vector<double> eta_edges_35 = {0.000, 0.058, 0.344, 0.700, 1.009, 1.270, 1.458, 1.685, 1.935, 2.231, 2.468, 2.500};
0086 const static vector<double> eta_vals_35 = {0.878, 0.889, 0.901, 0.895, 0.893, 0.849, 0.835, 0.868, 0.863, 0.845, 0.832};
0087
0088 const static vector<double> eta_edges_40 = {0.000, 0.047, 0.355, 0.699, 0.983, 1.280, 1.446, 1.694, 1.943, 2.227, 2.441, 2.500};
0089 const static vector<double> eta_vals_40 = {0.894, 0.901, 0.909, 0.905, 0.904, 0.875, 0.868, 0.889, 0.876, 0.848, 0.827};
0090
0091 const static vector<double> eta_edges_45 = {0.000, 0.058, 0.356, 0.712, 0.997, 1.282, 1.459, 1.686, 1.935, 2.220, 2.444, 2.500};
0092 const static vector<double> eta_vals_45 = {0.900, 0.911, 0.923, 0.918, 0.917, 0.897, 0.891, 0.904, 0.894, 0.843, 0.796};
0093
0094 const static vector<double> eta_edges_50 = {0.000, 0.059, 0.355, 0.711, 0.983, 1.280, 1.469, 1.682, 1.919, 2.227, 2.441, 2.500};
0095 const static vector<double> eta_vals_50 = {0.903, 0.913, 0.923, 0.922, 0.923, 0.903, 0.898, 0.908, 0.895, 0.831, 0.774};
0096
0097 const static vector<double> eta_edges_60 = {0.000, 0.053, 0.351, 0.720, 1.006, 1.291, 1.469, 1.696, 1.946, 2.243, 2.455, 2.500};
0098 const static vector<double> eta_vals_60 = {0.903, 0.917, 0.928, 0.924, 0.927, 0.915, 0.911, 0.915, 0.899, 0.827, 0.760};
0099
0100 const static vector<double> eta_edges_80 = {0.000, 0.053, 0.351, 0.720, 0.994, 1.292, 1.482, 1.708, 1.934, 2.220, 2.458, 2.500};
0101 const static vector<double> eta_vals_80 = {0.936, 0.942, 0.952, 0.956, 0.956, 0.934, 0.931, 0.944, 0.933, 0.940, 0.948};
0102
0103 const static vector<double> et_edges = { 10, 15, 20, 25, 30, 35, 40, 45, 50, 60, 80 };
0104 const static vector< vector<double> > et_eta_edges = { eta_edges_10, eta_edges_15, eta_edges_20, eta_edges_25, eta_edges_30, eta_edges_35, eta_edges_40, eta_edges_45, eta_edges_50, eta_edges_60, eta_edges_80 };
0105 const static vector< vector<double> > et_eta_vals = { eta_vals_10, eta_vals_15, eta_vals_20, eta_vals_25, eta_vals_30, eta_vals_35, eta_vals_40, eta_vals_45, eta_vals_50, eta_vals_60, eta_vals_80 };
0106
0107 if (e.abseta() > 2.5 || e.Et() < 10*GeV) return 0.0;
0108 const int i_et = binIndex(e.Et()/GeV, et_edges, true);
0109 const int i_eta = binIndex(e.abseta(), et_eta_edges[i_et]);
0110 return et_eta_vals[i_et][i_eta] * ELECTRON_RECOEFF_ATLAS_RUN1(e);
0111 }
0112
0113
0114
0115
0116 inline double ELECTRON_EFF_ATLAS_RUN2_MEDIUM(const Particle& e) {
0117 if (e.abspid() != PID::ELECTRON) return 0;
0118 return 1.01 * ELECTRON_EFF_ATLAS_RUN1_MEDIUM(e);
0119 }
0120
0121
0122
0123 inline double ELECTRON_EFF_ATLAS_RUN1_TIGHT(const Particle& e) {
0124 if (e.abspid() != PID::ELECTRON) return 0;
0125
0126 const static vector<double> eta_edges_10 = {0.000, 0.049, 0.459, 1.100, 1.461, 1.789, 2.270, 2.500};
0127 const static vector<double> eta_vals_10 = {0.581, 0.632, 0.668, 0.558, 0.548, 0.662, 0.690};
0128
0129 const static vector<double> eta_edges_15 = {0.000, 0.053, 0.450, 1.096, 1.463, 1.783, 2.269, 2.500};
0130 const static vector<double> eta_vals_15 = {0.630, 0.678, 0.714, 0.633, 0.616, 0.700, 0.733};
0131
0132 const static vector<double> eta_edges_20 = {0.000, 0.065, 0.362, 0.719, 0.992, 1.277, 1.479, 1.692, 1.930, 2.227, 2.464, 2.500};
0133 const static vector<double> eta_vals_20 = {0.653, 0.695, 0.735, 0.714, 0.688, 0.635, 0.625, 0.655, 0.680, 0.691, 0.674};
0134
0135 const static vector<double> eta_edges_25 = {0.000, 0.077, 0.362, 0.719, 0.992, 1.300, 1.479, 1.692, 1.942, 2.227, 2.464, 2.500};
0136 const static vector<double> eta_vals_25 = {0.692, 0.732, 0.768, 0.750, 0.726, 0.677, 0.667, 0.692, 0.710, 0.706, 0.679};
0137
0138 const static vector<double> eta_edges_30 = {0.000, 0.053, 0.362, 0.719, 1.004, 1.277, 1.467, 1.681, 1.954, 2.239, 2.452, 2.500};
0139 const static vector<double> eta_vals_30 = {0.724, 0.763, 0.804, 0.789, 0.762, 0.702, 0.690, 0.720, 0.731, 0.714, 0.681};
0140
0141 const static vector<double> eta_edges_35 = {0.000, 0.044, 0.342, 0.711, 0.971, 1.280, 1.456, 1.683, 1.944, 2.218, 2.442, 2.500};
0142 const static vector<double> eta_vals_35 = {0.736, 0.778, 0.824, 0.811, 0.784, 0.730, 0.718, 0.739, 0.743, 0.718, 0.678};
0143
0144 const static vector<double> eta_edges_40 = {0.000, 0.047, 0.355, 0.699, 0.983, 1.268, 1.457, 1.671, 1.931, 2.204, 2.453, 2.500};
0145 const static vector<double> eta_vals_40 = {0.741, 0.774, 0.823, 0.823, 0.802, 0.764, 0.756, 0.771, 0.771, 0.734, 0.684};
0146
0147 const static vector<double> eta_edges_45 = {0.000, 0.056, 0.354, 0.711, 0.984, 1.280, 1.458, 1.684, 1.945, 2.207, 2.442, 2.500};
0148 const static vector<double> eta_vals_45 = {0.758, 0.792, 0.841, 0.841, 0.823, 0.792, 0.786, 0.796, 0.794, 0.734, 0.663};
0149
0150 const static vector<double> eta_edges_50 = {0.000, 0.059, 0.355, 0.699, 0.983, 1.268, 1.446, 1.682, 1.943, 2.216, 2.453, 2.500};
0151 const static vector<double> eta_vals_50 = {0.771, 0.806, 0.855, 0.858, 0.843, 0.810, 0.800, 0.808, 0.802, 0.730, 0.653};
0152
0153 const static vector<double> eta_edges_60 = {0.000, 0.050, 0.350, 0.707, 0.981, 1.278, 1.468, 1.694, 1.944, 2.242, 2.453, 2.500};
0154 const static vector<double> eta_vals_60 = {0.773, 0.816, 0.866, 0.865, 0.853, 0.820, 0.812, 0.817, 0.804, 0.726, 0.645};
0155
0156 const static vector<double> eta_edges_80 = {0.000, 0.051, 0.374, 0.720, 0.981, 1.279, 1.468, 1.707, 1.945, 2.207, 2.457, 2.500};
0157 const static vector<double> eta_vals_80 = {0.819, 0.855, 0.899, 0.906, 0.900, 0.869, 0.865, 0.873, 0.869, 0.868, 0.859};
0158
0159 const static vector<double> et_edges = { 10, 15, 20, 25, 30, 35, 40, 45, 50, 60, 80 };
0160 const static vector< vector<double> > et_eta_edges = { eta_edges_10, eta_edges_15, eta_edges_20, eta_edges_25, eta_edges_30, eta_edges_35, eta_edges_40, eta_edges_45, eta_edges_50, eta_edges_60, eta_edges_80 };
0161 const static vector< vector<double> > et_eta_vals = { eta_vals_10, eta_vals_15, eta_vals_20, eta_vals_25, eta_vals_30, eta_vals_35, eta_vals_40, eta_vals_45, eta_vals_50, eta_vals_60, eta_vals_80 };
0162
0163 if (e.abseta() > 2.5 || e.Et() < 10*GeV) return 0.0;
0164 const int i_et = binIndex(e.Et()/GeV, et_edges, true);
0165 const int i_eta = binIndex(e.abseta(), et_eta_edges[i_et]);
0166 return et_eta_vals[i_et][i_eta] * ELECTRON_RECOEFF_ATLAS_RUN1(e);
0167 }
0168
0169
0170
0171
0172 inline double ELECTRON_EFF_ATLAS_RUN2_TIGHT(const Particle& e) {
0173 if (e.abspid() != PID::ELECTRON) return 0;
0174 const static vector<double> et_edges = { 20, 25, 30, 35, 40, 45, 50, 60, 80 };
0175 const static vector<double> et_effs = { 0.785, 0.805, 0.820, 0.830, 0.840, 0.850, 0.875, 0.910, 0.910 };
0176 const static vector<double> eta_edges = {0.000, 0.051, 0.374, 0.720, 0.981, 1.279, 1.468, 1.707, 1.945, 2.207, 2.457, 2.500};
0177 const static vector<double> eta_refs = {0.819, 0.855, 0.899, 0.906, 0.900, 0.869, 0.865, 0.873, 0.869, 0.868, 0.859};
0178 if (e.abseta() > 2.5 || e.Et() < 20*GeV) return 0.0;
0179 const int i_et = binIndex(e.Et()/GeV, et_edges, true);
0180 const int i_eta = binIndex(e.abseta(), eta_edges);
0181 const double eff_et = et_effs[i_et];
0182
0183 const double eff = eff_et * (eta_refs[i_eta]/0.85) * ELECTRON_RECOEFF_ATLAS_RUN2(e);
0184
0185 return eff;
0186 }
0187
0188
0189
0190
0191 inline Particle ELECTRON_SMEAR_ATLAS_RUN1(const Particle& e) {
0192 static const vector<double> edges_eta = {0., 2.5, 3.};
0193 static const vector<double> edges_pt = {0., 0.1, 25.};
0194 static const vector<double> e2s = {0.000, 0.015, 0.005,
0195 0.005, 0.005, 0.005,
0196 0.107, 0.107, 0.107};
0197 static const vector<double> es = {0.00, 0.00, 0.05,
0198 0.05, 0.05, 0.05,
0199 2.08, 2.08, 2.08};
0200 static const vector<double> cs = {0.00, 0.00, 0.25,
0201 0.25, 0.25, 0.25,
0202 0.00, 0.00, 0.00};
0203
0204 const int i_eta = binIndex(e.abseta(), edges_eta, true);
0205 const int i_pt = binIndex(e.pT()/GeV, edges_pt, true);
0206 const int i = i_eta*edges_pt.size() + i_pt;
0207
0208
0209 const double c1 = sqr(e2s[i]), c2 = sqr(es[i]), c3 = sqr(cs[i]);
0210 const double resolution = sqrt(c1*e.E2() + c2*e.E() + c3) * GeV;
0211
0212
0213
0214
0215
0216 return Particle(e.pid(), P4_SMEAR_E_GAUSS(e, resolution));
0217 }
0218
0219
0220
0221
0222 inline Particle ELECTRON_SMEAR_ATLAS_RUN2(const Particle& e) {
0223 return ELECTRON_SMEAR_ATLAS_RUN1(e);
0224 }
0225
0226
0227
0228
0229
0230
0231
0232 inline double ELECTRON_EFF_CMS_RUN1(const Particle& e) {
0233 if (e.abspid() != PID::ELECTRON) return 0;
0234 if (e.abseta() > 2.5) return 0;
0235 if (e.pT() < 10*GeV) return 0;
0236 return (e.abseta() < 1.5) ? 0.95 : 0.85;
0237 }
0238
0239
0240
0241
0242 inline double ELECTRON_EFF_CMS_RUN2(const Particle& e) {
0243 if (e.abspid() != PID::ELECTRON) return 0;
0244 return ELECTRON_EFF_CMS_RUN1(e);
0245 }
0246
0247
0248
0249
0250
0251
0252
0253
0254 inline Particle ELECTRON_SMEAR_CMS_RUN1(const Particle& e) {
0255
0256 double resolution = 0;
0257 const double abseta = e.abseta();
0258 if (e.pT() > 0.1*GeV && abseta < 2.5) {
0259 if (abseta < 0.5) {
0260 resolution = add_quad(0.06, 1.3e-3 * e.pT()/GeV) * GeV;
0261 } else if (abseta < 1.5) {
0262 resolution = add_quad(0.10, 1.7e-3 * e.pT()/GeV) * GeV;
0263 } else {
0264 resolution = add_quad(0.25, 3.1e-3 * e.pT()/GeV) * GeV;
0265 }
0266 }
0267
0268
0269
0270
0271
0272 return Particle(e.pid(), P4_SMEAR_E_GAUSS(e, resolution));
0273 }
0274
0275
0276
0277 inline Particle ELECTRON_SMEAR_CMS_RUN2(const Particle& e) {
0278 return ELECTRON_SMEAR_CMS_RUN1(e);
0279 }
0280
0281
0282
0283
0284
0285
0286
0287
0288
0289
0290
0291 inline double PHOTON_EFF_ATLAS_RUN1(const Particle& y) {
0292 if (y.abspid() != PID::PHOTON) return 0;
0293
0294 if (y.pT() < 10*GeV) return 0;
0295 if (inRange(y.abseta(), 1.37, 1.52) || y.abseta() > 2.37) return 0;
0296
0297 static const vector<double> edges_eta = {0., 0.6, 1.37, 1.52, 1.81, 2.37};
0298 static const vector<double> edges_pt = {10., 15., 20., 25., 30., 35., 40., 45.,
0299 50., 60., 80., 100., 125., 150., 175., 250.};
0300 static const vector<double> effs = {0.53, 0.65, 0.73, 0.83, 0.86, 0.93, 0.94, 0.96,
0301 0.97, 0.98, 0.98, 0.98, 0.98, 0.98, 0.98, 0.98,
0302 0.45, 0.57, 0.67, 0.74, 0.84, 0.87, 0.93, 0.94,
0303 0.95, 0.96, 0.97, 0.98, 0.98, 0.99, 0.99, 0.99,
0304 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00,
0305 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00,
0306 0.48, 0.56, 0.68, 0.76, 0.86, 0.90, 0.93, 0.95,
0307 0.96, 0.97, 0.98, 0.99, 0.99, 1.00, 1.00, 1.00,
0308 0.50, 0.61, 0.74, 0.82, 0.88, 0.92, 0.94, 0.95,
0309 0.96, 0.97, 0.98, 0.98, 0.98, 0.98, 0.99, 0.99};
0310
0311 const int i_eta = binIndex(y.abseta(), edges_eta);
0312 const int i_pt = binIndex(y.pT()/GeV, edges_pt, true);
0313 const int i = i_eta*edges_pt.size() + i_pt;
0314 const double eff = effs[i];
0315 return eff;
0316 }
0317
0318
0319
0320
0321 inline double PHOTON_EFF_ATLAS_RUN2(const Particle& y) {
0322 if (y.abspid() != PID::PHOTON) return 0;
0323
0324 if (y.pT() < 10*GeV) return 0;
0325 if (inRange(y.abseta(), 1.37, 1.52) || y.abseta() > 2.37) return 0;
0326
0327 static const vector<double> edges_eta = {0., 0.6, 1.37, 1.52, 1.81, 2.37};
0328 static const vector<double> edges_pt = {10., 15., 20., 25., 30., 35., 40., 45.,
0329 50., 60., 80., 100., 125., 150., 175., 250.};
0330 static const vector<double> effs = {0.55, 0.70, 0.85, 0.89, 0.93, 0.95, 0.96, 0.96,
0331 0.97, 0.97, 0.98, 0.97, 0.97, 0.97, 0.97, 0.97,
0332 0.47, 0.66, 0.79, 0.86, 0.89, 0.94, 0.96, 0.97,
0333 0.97, 0.98, 0.97, 0.98, 0.98, 0.98, 0.98, 0.98,
0334 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00,
0335 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00,
0336 0.54, 0.71, 0.84, 0.88, 0.92, 0.93, 0.94, 0.95,
0337 0.96, 0.96, 0.96, 0.96, 0.96, 0.96, 0.96, 0.96,
0338 0.61, 0.74, 0.83, 0.88, 0.91, 0.94, 0.95, 0.96,
0339 0.97, 0.98, 0.98, 0.98, 0.98, 0.98, 0.98, 0.98};
0340
0341 const int i_eta = binIndex(y.abseta(), edges_eta);
0342 const int i_pt = binIndex(y.pT()/GeV, edges_pt, true);
0343 const int i = i_eta*edges_pt.size() + i_pt;
0344 const double eff = effs[i];
0345 return eff;
0346 }
0347
0348
0349
0350 inline double PHOTON_EFF_CMS_RUN1(const Particle& y) {
0351 if (y.abspid() != PID::PHOTON) return 0;
0352 if (y.pT() < 10*GeV || y.abseta() > 2.5) return 0;
0353 return (y.abseta() < 1.5) ? 0.95 : 0.85;
0354 }
0355
0356
0357
0358 inline double PHOTON_EFF_CMS_RUN2(const Particle& y) {
0359 if (y.abspid() != PID::PHOTON) return 0;
0360 return PHOTON_EFF_CMS_RUN1(y);
0361 }
0362
0363
0364
0365 inline Particle PHOTON_SMEAR_ATLAS_RUN1(const Particle& y) { return y; }
0366 inline Particle PHOTON_SMEAR_ATLAS_RUN2(const Particle& y) { return y; }
0367 inline Particle PHOTON_SMEAR_CMS_RUN1(const Particle& y) { return y; }
0368 inline Particle PHOTON_SMEAR_CMS_RUN2(const Particle& y) { return y; }
0369
0370
0371
0372
0373
0374
0375
0376
0377
0378 inline double MUON_EFF_ATLAS_RUN1(const Particle& m) {
0379 if (m.abspid() != PID::MUON) return 0;
0380 if (m.abseta() > 2.7) return 0;
0381 if (m.pT() < 10*GeV) return 0;
0382 return (m.abseta() < 1.5) ? 0.95 : 0.85;
0383 }
0384
0385
0386
0387
0388 inline double MUON_RECOEFF_ATLAS_RUN2(const Particle& m) {
0389 if (m.abspid() != PID::MUON) return 0;
0390 if (m.abseta() > 2.5) return 0;
0391 if (m.abseta() < 0.1) return 0.61;
0392
0393 return (m.abseta() < 1) ? 0.98 : 0.99;
0394 }
0395
0396
0397
0398
0399
0400 inline double MUON_EFF_ATLAS_RUN2(const Particle& m) {
0401 if (m.abspid() != PID::MUON) return 0;
0402 if (m.abseta() > 2.7) return 0;
0403 static const vector<double> edges_pt = {0., 3.5, 4., 5., 6., 7., 8., 10.};
0404 static const vector<double> effs = {0.00, 0.76, 0.94, 0.97, 0.98, 0.98, 0.98, 0.99};
0405 const int i_pt = binIndex(m.pT()/GeV, edges_pt, true);
0406 const double eff = effs[i_pt] * MUON_RECOEFF_ATLAS_RUN2(m);
0407 return eff;
0408 }
0409
0410
0411
0412
0413
0414
0415 inline Particle MUON_SMEAR_ATLAS_RUN1(const Particle& m) {
0416 static const vector<double> edges_eta = {0, 1.5, 2.5};
0417 static const vector<double> edges_pt = {0, 0.1, 1.0, 10., 200.};
0418 static const vector<double> res = {0., 0.03, 0.02, 0.03, 0.05,
0419 0., 0.04, 0.03, 0.04, 0.05};
0420
0421 const int i_eta = binIndex(m.abseta(), edges_eta);
0422 const int i_pt = binIndex(m.pT()/GeV, edges_pt, true);
0423 const int i = i_eta*edges_pt.size() + i_pt;
0424
0425 const double resolution = res[i];
0426
0427
0428
0429
0430
0431
0432 return Particle(m.pid(), P4_SMEAR_PT_GAUSS(m, resolution*m.pT()));
0433 }
0434
0435
0436
0437 inline Particle MUON_SMEAR_ATLAS_RUN2(const Particle& m) {
0438 double mres_pt = 0.015;
0439 if (m.pT() > 50*GeV) mres_pt = 0.014 + 0.01*(m.pT()/GeV-50)/50;
0440 if (m.pT() > 100*GeV) mres_pt = 0.025;
0441 const double ptres_pt = SQRT2 * mres_pt;
0442 const double resolution = (m.abseta() < 1.5 ? 1.0 : 1.25) * ptres_pt;
0443 return Particle(m.pid(), P4_SMEAR_PT_GAUSS(m, resolution*m.pT()));
0444 }
0445
0446
0447
0448
0449 inline double MUON_EFF_CMS_RUN1(const Particle& m) {
0450 if (m.abspid() != PID::MUON) return 0;
0451 if (m.abseta() > 2.4) return 0;
0452 if (m.pT() < 10*GeV) return 0;
0453 return 0.95 * (m.abseta() < 1.5 ? 1 : exp(0.5 - 5e-4*m.pT()/GeV));
0454 }
0455
0456
0457
0458 inline double MUON_EFF_CMS_RUN2(const Particle& m) {
0459 if (m.abspid() != PID::MUON) return 0;
0460 return MUON_EFF_CMS_RUN1(m);
0461 }
0462
0463
0464
0465 inline Particle MUON_SMEAR_CMS_RUN1(const Particle& m) {
0466
0467
0468
0469
0470 double resolution = 0;
0471 const double abseta = m.abseta();
0472 if (m.pT() > 0.1*GeV && abseta < 2.5) {
0473 if (abseta < 0.5) {
0474 resolution = add_quad(0.01, 2.0e-4 * m.pT()/GeV);
0475 } else if (abseta < 1.5) {
0476 resolution = add_quad(0.02, 3.0e-4 * m.pT()/GeV);
0477 } else {
0478 resolution = add_quad(0.05, 2.6e-4 * m.pT()/GeV);
0479 }
0480 }
0481
0482
0483
0484
0485
0486
0487 return Particle(m.pid(), P4_SMEAR_PT_GAUSS(m, resolution*m.pT()));
0488 }
0489
0490
0491
0492 inline Particle MUON_SMEAR_CMS_RUN2(const Particle& m) {
0493 return MUON_SMEAR_CMS_RUN1(m);
0494 }
0495
0496
0497
0498
0499
0500
0501
0502
0503
0504
0505
0506
0507
0508
0509
0510 inline double TAU_EFF_ATLAS_RUN1(const Particle& t) {
0511 if (t.abseta() > 2.5) return 0;
0512 if (inRange(t.abseta(), 1.37, 1.52)) return 0;
0513 double pThadvis = 0;
0514 Particles chargedhadrons;
0515 for (const Particle& p : t.children()) {
0516 if (p.isHadron()) {
0517 pThadvis += p.pT();
0518 if (p.charge3() != 0 && p.abseta() < 2.5 && p.pT() > 1*GeV) chargedhadrons += p;
0519 }
0520 }
0521 if (chargedhadrons.empty()) return 0;
0522 if (pThadvis < 20*GeV) return 0;
0523 if (pThadvis < 40*GeV) {
0524 if (chargedhadrons.size() == 1) return (t.abspid() == PID::TAU) ? 0.56 : 0;
0525 if (chargedhadrons.size() == 3) return (t.abspid() == PID::TAU) ? 0.38 : 0;
0526 } else {
0527 if (chargedhadrons.size() == 1) return (t.abspid() == PID::TAU) ? 0.56 : 0;
0528 if (chargedhadrons.size() == 3) return (t.abspid() == PID::TAU) ? 0.38 : 0;
0529 }
0530 return 0;
0531 }
0532
0533
0534
0535
0536
0537
0538
0539
0540 inline double TAUJET_EFF_ATLAS_RUN1(const Jet& j) {
0541 if (j.abseta() > 2.5) return 0;
0542 if (inRange(j.abseta(), 1.37, 1.52)) return 0;
0543 double pThadvis = 0;
0544 Particles chargedhadrons;
0545 for (const Particle& p : j.particles()) {
0546 if (p.isHadron()) {
0547 pThadvis += p.pT();
0548 if (p.charge3() != 0 && p.abseta() < 2.5 && p.pT() > 1*GeV) chargedhadrons += p;
0549 }
0550 }
0551
0552 if (chargedhadrons.empty()) return 0;
0553 if (pThadvis < 20*GeV) return 0;
0554
0555 const Particles ttags = j.tauTags(Cuts::pT > 10*GeV);
0556
0557 if (ttags.empty()) {
0558 if (pThadvis < 40*GeV)
0559 return chargedhadrons.size() == 1 ? 1/20. : chargedhadrons.size() == 3 ? 1/100. : 0;
0560 else
0561 return chargedhadrons.size() == 1 ? 1/25. : chargedhadrons.size() == 3 ? 1/400. : 0;
0562 }
0563
0564 const Particles prongs = ttags[0].stableDescendants(Cuts::charge3 > 0 && Cuts::pT > 1*GeV && Cuts::abseta < 2.5);
0565 return prongs.size() == 1 ? 0.56 : 0.38;
0566 }
0567
0568
0569
0570
0571
0572
0573
0574 inline double TAU_EFF_ATLAS_RUN2(const Particle& t) {
0575 if (t.abspid() != PID::TAU) return 0;
0576 if (t.abseta() > 2.5) return 0;
0577 if (inRange(t.abseta(), 1.37, 1.52)) return 0;
0578 double pThadvis = 0;
0579 Particles chargedhadrons;
0580 for (const Particle& p : t.children()) {
0581 if (p.isHadron()) {
0582 pThadvis += p.pT();
0583 if (p.charge3() != 0 && p.abseta() < 2.5 && p.pT() > 1*GeV) chargedhadrons += p;
0584 }
0585 }
0586 if (chargedhadrons.empty()) return 0;
0587 if (pThadvis < 20*GeV) return 0;
0588 if (chargedhadrons.size() == 1) return (t.abspid() == PID::TAU) ? 0.55 : 0;
0589 if (chargedhadrons.size() == 3) return (t.abspid() == PID::TAU) ? 0.40 : 0;
0590 return 0;
0591 }
0592
0593
0594
0595
0596
0597
0598 inline double TAUJET_EFF_ATLAS_RUN2(const Jet& j) {
0599 if (j.abseta() > 2.5) return 0;
0600 if (inRange(j.abseta(), 1.37, 1.52)) return 0;
0601 double pThadvis = 0;
0602 Particles chargedhadrons;
0603 for (const Particle& p : j.particles()) {
0604 if (p.isHadron()) {
0605 pThadvis += p.pT();
0606 if (p.charge3() != 0 && p.abseta() < 2.5 && p.pT() > 1*GeV) chargedhadrons += p;
0607 }
0608 }
0609 if (chargedhadrons.empty()) return 0;
0610 if (pThadvis < 20*GeV) return 0;
0611 const Particles ttags = j.tauTags(Cuts::pT > 10*GeV);
0612
0613
0614
0615
0616
0617
0618 if (ttags.empty()) return chargedhadrons.size() == 1 ? 1/50. : chargedhadrons.size() == 3 ? 1/110. : 0;
0619 const Particles prongs = ttags[0].stableDescendants(Cuts::charge3 > 0 && Cuts::pT > 1*GeV && Cuts::abseta < 2.5);
0620 return prongs.size() == 1 ? 0.55 : 0.40;
0621 }
0622
0623
0624
0625
0626 inline Particle TAU_SMEAR_ATLAS_RUN1(const Particle& t) {
0627
0628
0629
0630
0631
0632
0633
0634
0635
0636
0637
0638
0639
0640
0641 static const vector<double> binedges_pt = {0., 50., 70., 100., 150., 200., 1000., 10000.};
0642 static const vector<double> jer = {0.145, 0.115, 0.095, 0.075, 0.07, 0.05, 0.04, 0.04};
0643 const int ipt = binIndex(t.pT()/GeV, binedges_pt, true);
0644 if (ipt < 0) return t;
0645 const double resolution = jer.at(ipt);
0646
0647
0648
0649 const double fsmear = max(randnorm(1., resolution), 0.);
0650 const double mass = t.mass2() > 0 ? t.mass() : 0;
0651 Particle rtn(PID::TAU, FourMomentum::mkXYZM(t.px()*fsmear, t.py()*fsmear, t.pz()*fsmear, mass));
0652
0653 return rtn;
0654 }
0655
0656
0657
0658
0659 inline Particle TAU_SMEAR_ATLAS_RUN2(const Particle& t) {
0660 return TAU_SMEAR_ATLAS_RUN1(t);
0661 }
0662
0663
0664
0665
0666
0667 inline double TAU_EFF_CMS_RUN1(const Particle& t) {
0668 if (t.abspid() != PID::TAU) return 0;
0669 return (t.abspid() == PID::TAU) ? 0.6 : 0;
0670 }
0671
0672
0673
0674
0675 inline double TAU_EFF_CMS_RUN2(const Particle& t) {
0676 if (t.abspid() != PID::TAU) return 0;
0677 return (t.abspid() == PID::TAU) ? 0.6 : 0;
0678 }
0679
0680
0681
0682
0683 inline Particle TAU_SMEAR_CMS_RUN1(const Particle& t) {
0684 return TAU_SMEAR_ATLAS_RUN1(t);
0685 }
0686
0687
0688
0689
0690 inline Particle TAU_SMEAR_CMS_RUN2(const Particle& t) {
0691 return TAU_SMEAR_CMS_RUN1(t);
0692 }
0693
0694
0695
0696
0697
0698
0699
0700
0701
0702 inline double JET_BTAG_ATLAS_RUN1(const Jet& j) {
0703
0704 if (j.abseta() > 2.5) return 0;
0705 const auto ftagsel = [&](const Particle& p){ return p.pT() > 5*GeV && deltaR(p,j) < 0.3; };
0706 if (j.bTagged(ftagsel)) return 0.80*tanh(0.003*j.pT()/GeV)*(30/(1+0.0860*j.pT()/GeV));
0707 if (j.cTagged(ftagsel)) return 0.20*tanh(0.020*j.pT()/GeV)*( 1/(1+0.0034*j.pT()/GeV));
0708 return 0.002 + 7.3e-6*j.pT()/GeV;
0709 }
0710
0711
0712 inline double JET_BTAG_ATLAS_RUN2_MV2C20(const Jet& j) {
0713 if (j.abseta() > 2.5) return 0;
0714 if (j.bTagged(Cuts::pT > 5*GeV)) return 0.77;
0715 if (j.cTagged(Cuts::pT > 5*GeV)) return 1/4.5;
0716 return 1/140.;
0717 }
0718
0719
0720 inline double JET_BTAG_ATLAS_RUN2_MV2C10(const Jet& j) {
0721 if (j.abseta() > 2.5) return 0;
0722 if (j.bTagged(Cuts::pT > 5*GeV)) return 0.77;
0723 if (j.cTagged(Cuts::pT > 5*GeV)) return 1/6.0;
0724 return 1/134.;
0725 }
0726
0727
0728
0729 inline Jet JET_SMEAR_ATLAS_RUN1(const Jet& j) {
0730
0731
0732
0733
0734
0735 static const vector<double> binedges_pt = {0., 50., 70., 100., 150., 200., 1000., 10000.};
0736 static const vector<double> jer = {0.145, 0.115, 0.095, 0.075, 0.07, 0.05, 0.04, 0.04};
0737 const int ipt = binIndex(j.pT()/GeV, binedges_pt, true);
0738 if (ipt < 0) return j;
0739 const double resolution = jer.at(ipt);
0740
0741
0742
0743 const double fsmear = max(randnorm(1., resolution), 0.);
0744 const double mass = j.mass2() > 0 ? j.mass() : 0;
0745 Jet rtn(FourMomentum::mkXYZM(j.px()*fsmear, j.py()*fsmear, j.pz()*fsmear, mass));
0746
0747 return rtn;
0748 }
0749
0750
0751
0752 inline Jet JET_SMEAR_ATLAS_RUN2(const Jet& j) {
0753 return JET_SMEAR_ATLAS_RUN1(j);
0754 }
0755
0756
0757
0758 inline Jet JET_SMEAR_CMS_RUN1(const Jet& j) {
0759 return JET_SMEAR_ATLAS_RUN1(j);
0760 }
0761
0762
0763
0764 inline Jet JET_SMEAR_CMS_RUN2(const Jet& j) {
0765 return JET_SMEAR_CMS_RUN1(j);
0766 }
0767
0768
0769
0770
0771
0772
0773
0774 inline Vector3 MET_SMEAR_IDENTITY(const Vector3& met, double) { return met; }
0775
0776
0777
0778
0779 inline Vector3 MET_SMEAR_ATLAS_RUN1(const Vector3& met, double set) {
0780 Vector3 smeared_met = met;
0781
0782
0783 if (met.mod() < 25*GeV) smeared_met *= 1.05;
0784 else if (met.mod() < 40*GeV) smeared_met *= (1.05 - (0.04/15)*(met.mod()/GeV - 25));
0785 else smeared_met *= 1.01;
0786
0787
0788 const double resolution = 0.45 * sqrt(set/GeV) * GeV;
0789
0790 const double metsmear = fabs(randnorm(smeared_met.mod(), resolution));
0791 smeared_met = metsmear * smeared_met.unit();
0792
0793 return smeared_met;
0794 }
0795
0796
0797
0798
0799 inline Vector3 MET_SMEAR_ATLAS_RUN2(const Vector3& met, double set) {
0800 Vector3 smeared_met = met;
0801
0802
0803 if (met.mod() < 25*GeV) smeared_met *= 1.5;
0804 else smeared_met *= (1 + exp(-(met.mod() - 25*GeV)/(10*GeV)) - 0.02);
0805
0806
0807
0808 const double resolution1 = (set < 180*GeV ? set/180. : 1) * 0.45 * sqrt(max(set/GeV, 180)) * GeV;
0809
0810
0811
0812 const double resolution2 = 15*GeV + 0.5*sqrt(met.mod()/GeV)*GeV;
0813
0814
0815
0816 const double resolution = min(resolution1, resolution2);
0817
0818 const double metsmear = fabs(randnorm(smeared_met.mod(), resolution));
0819 smeared_met = metsmear * smeared_met.unit();
0820
0821 return smeared_met;
0822 }
0823
0824
0825
0826 inline Vector3 MET_SMEAR_CMS_RUN1(const Vector3& met, double set) {
0827 Vector3 smeared_met = met;
0828
0829
0830 const double resolution_x = (1.1 + 0.6*sqrt(set/GeV)) * GeV;
0831 const double resolution_y = (1.4 + 0.6*sqrt(set/GeV)) * GeV;
0832 const double resolution = sqrt(sqr(resolution_x) + sqr(resolution_y));
0833
0834
0835
0836 const double metsmear = fabs(randnorm(smeared_met.mod(), resolution));
0837 smeared_met = metsmear * smeared_met.unit();
0838
0839 return smeared_met;
0840 }
0841
0842
0843
0844 inline Vector3 MET_SMEAR_CMS_RUN2(const Vector3& met, double set) {
0845 Vector3 smeared_met = met;
0846
0847
0848 const double resolution_para = ( 2.0 + 0.64*sqrt(set/GeV)) * GeV;
0849 const double resolution_perp = (-1.5 + 0.68*sqrt(set/GeV)) * GeV;
0850 const double resolution = sqrt(sqr(resolution_para) + sqr(resolution_perp));
0851
0852
0853
0854 const double metsmear = fabs(randnorm(smeared_met.mod(), resolution));
0855 smeared_met = metsmear * smeared_met.unit();
0856
0857 return smeared_met;
0858 }
0859
0860
0861
0862
0863
0864
0865
0866
0867 inline double TRK_EFF_ATLAS_RUN1(const Particle& p) {
0868 if (p.charge3() == 0) return 0;
0869 if (p.abseta() > 2.5) return 0;
0870 if (p.pT() < 0.1*GeV) return 0;
0871
0872 if (p.abspid() == PID::ELECTRON) {
0873 if (p.abseta() < 1.5) {
0874 if (p.pT() < 1*GeV) return 0.73;
0875 if (p.pT() < 100*GeV) return 0.95;
0876 return 0.99;
0877 } else {
0878 if (p.pT() < 1*GeV) return 0.50;
0879 if (p.pT() < 100*GeV) return 0.83;
0880 else return 0.90;
0881 }
0882 } else if (p.abspid() == PID::MUON) {
0883 if (p.abseta() < 1.5) {
0884 return (p.pT() < 1*GeV) ? 0.75 : 0.99;
0885 } else {
0886 return (p.pT() < 1*GeV) ? 0.70 : 0.98;
0887 }
0888 } else {
0889 if (p.abseta() < 1.5) {
0890 return (p.pT() < 1*GeV) ? 0.70 : 0.95;
0891 } else {
0892 return (p.pT() < 1*GeV) ? 0.60 : 0.85;
0893 }
0894 }
0895 }
0896
0897
0898
0899 inline double TRK_EFF_ATLAS_RUN2(const Particle& p) {
0900 return TRK_EFF_ATLAS_RUN1(p);
0901 }
0902
0903
0904
0905 inline double TRK_EFF_CMS_RUN1(const Particle& p) {
0906 if (p.charge3() == 0) return 0;
0907 if (p.abseta() > 2.5) return 0;
0908 if (p.pT() < 0.1*GeV) return 0;
0909
0910 if (p.abspid() == PID::ELECTRON) {
0911 if (p.abseta() < 1.5) {
0912 if (p.pT() < 1*GeV) return 0.73;
0913 if (p.pT() < 100*GeV) return 0.95;
0914 return 0.99;
0915 } else {
0916 if (p.pT() < 1*GeV) return 0.50;
0917 if (p.pT() < 100*GeV) return 0.83;
0918 else return 0.90;
0919 }
0920 } else if (p.abspid() == PID::MUON) {
0921 if (p.abseta() < 1.5) {
0922 return (p.pT() < 1*GeV) ? 0.75 : 0.99;
0923 } else {
0924 return (p.pT() < 1*GeV) ? 0.70 : 0.98;
0925 }
0926 } else {
0927 if (p.abseta() < 1.5) {
0928 return (p.pT() < 1*GeV) ? 0.70 : 0.95;
0929 } else {
0930 return (p.pT() < 1*GeV) ? 0.60 : 0.85;
0931 }
0932 }
0933 }
0934
0935
0936
0937 inline double TRK_EFF_CMS_RUN2(const Particle& p) {
0938 return TRK_EFF_CMS_RUN1(p);
0939 }
0940
0941
0942
0943
0944
0945
0946
0947
0948 inline double ATLAS_JVT_EFF_LOOSE(const Jet & j){
0949 if (j.abseta() > 2.4) return 1.0;
0950
0951 if (j.pt() <= 20*GeV || j.pt() >= 60*GeV) return 1.0;
0952
0953 const static vector<double> binedges_pt = {20*GeV,25*GeV,30*GeV,35*GeV,40*GeV,45*GeV,50*GeV,55*GeV,60*GeV};
0954 const static vector<double> binvals = {0.9, 0.93, 0.94, 0.95, 0.96, 0.96, 0.97, 0.97};
0955
0956 const size_t bini = binIndex(j.pt(), binedges_pt);
0957 return binvals[bini];
0958 }
0959
0960
0961
0962
0963
0964
0965
0966
0967 inline double ATLAS_JVT_EFF_MEDIUM(const Jet & j){
0968 if (j.abseta() > 2.4) return 1.0;
0969
0970 if (j.pt() <= 20*GeV || j.pt() >= 60*GeV) return 1.0;
0971
0972 const static vector<double> binedges_pt = {20*GeV,25*GeV,30*GeV,35*GeV,40*GeV,45*GeV,50*GeV,55*GeV,60*GeV};
0973 const static vector<double> binvals = {0.86, 0.9, 0.92, 0.93, 0.94, 0.95, 0.95, 0.96};
0974
0975 const size_t bini = binIndex(j.pt(), binedges_pt);
0976 return binvals[bini];
0977 }
0978
0979
0980
0981
0982
0983
0984
0985
0986 inline double ATLAS_JVT_EFF_TIGHT(const Jet & j){
0987 if (j.abseta() > 2.4) return 1.0;
0988
0989 if (j.pt() <= 20*GeV || j.pt() >= 60*GeV) return 1.0;
0990
0991 const static vector<double> binedges_pt = {20*GeV,25*GeV,30*GeV,35*GeV,40*GeV,45*GeV,50*GeV,55*GeV,60*GeV};
0992 const static vector<double> binvals = {0.81, 0.84, 0.87, 0.90, 0.91, 0.92, 0.93, 0.94};
0993
0994 const size_t bini = binIndex(j.pt(), binedges_pt);
0995 return binvals[bini];
0996 }
0997
0998
0999
1000
1001
1002
1003 }
1004
1005 #endif