File indexing completed on 2024-12-21 03:54:28
0001 #include "CommonTools/PileupAlgos/interface/PuppiContainer.h"
0002 #include "DataFormats/Math/interface/deltaR.h"
0003 #include "Math/ProbFunc.h"
0004 #include "TMath.h"
0005 #include <iostream>
0006 #include <cmath>
0007 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0008 #include "FWCore/Utilities/interface/isFinite.h"
0009
0010 using namespace std;
0011
0012 PuppiContainer::PuppiContainer(const edm::ParameterSet &iConfig) {
0013 fPuppiDiagnostics = iConfig.getParameter<bool>("puppiDiagnostics");
0014 fApplyCHS = iConfig.getParameter<bool>("applyCHS");
0015 fInvert = iConfig.getParameter<bool>("invertPuppi");
0016 fUseExp = iConfig.getParameter<bool>("useExp");
0017 fPuppiWeightCut = iConfig.getParameter<double>("MinPuppiWeight");
0018 fPtMaxPhotons = iConfig.getParameter<double>("PtMaxPhotons");
0019 fEtaMaxPhotons = iConfig.getParameter<double>("EtaMaxPhotons");
0020 fPtMaxNeutrals = iConfig.getParameter<double>("PtMaxNeutrals");
0021 fPtMaxNeutralsStartSlope = iConfig.getParameter<double>("PtMaxNeutralsStartSlope");
0022 std::vector<edm::ParameterSet> lAlgos = iConfig.getParameter<std::vector<edm::ParameterSet> >("algos");
0023 fPuppiAlgo.reserve(lAlgos.size());
0024 for (auto const &algos : lAlgos) {
0025 fPuppiAlgo.emplace_back(algos);
0026 }
0027 }
0028
0029 void PuppiContainer::initialize(const std::vector<RecoObj> &iRecoObjects,
0030 std::vector<PuppiCandidate> &pfParticles,
0031 std::vector<PuppiCandidate> &pfParticlesForVar,
0032 std::vector<PuppiCandidate> &pfParticlesForVarChargedPV) const {
0033 pfParticles.reserve(iRecoObjects.size());
0034 pfParticlesForVar.reserve(iRecoObjects.size());
0035 pfParticlesForVarChargedPV.reserve(iRecoObjects.size());
0036 for (auto const &rParticle : iRecoObjects) {
0037 PuppiCandidate pCand;
0038 pCand.id = rParticle.id;
0039 if (edm::isFinite(rParticle.rapidity)) {
0040 pCand.pt = rParticle.pt;
0041 pCand.eta = rParticle.eta;
0042 pCand.rapidity = rParticle.rapidity;
0043 pCand.phi = rParticle.phi;
0044 pCand.m = rParticle.m;
0045 } else {
0046 pCand.pt = 0.;
0047 pCand.eta = 99.;
0048 pCand.rapidity = 99.;
0049 pCand.phi = 0.;
0050 pCand.m = 0.;
0051 }
0052
0053 pfParticles.push_back(pCand);
0054
0055
0056
0057 if (std::abs(rParticle.id) == 3)
0058 continue;
0059
0060 pfParticlesForVar.push_back(pCand);
0061
0062 if (std::abs(rParticle.id) == 1)
0063 pfParticlesForVarChargedPV.push_back(pCand);
0064 }
0065 }
0066
0067 double PuppiContainer::goodVar(PuppiCandidate const &iPart,
0068 std::vector<PuppiCandidate> const &iParts,
0069 int iOpt,
0070 const double iRCone) const {
0071 return var_within_R(iOpt, iParts, iPart, iRCone);
0072 }
0073
0074 double PuppiContainer::var_within_R(int iId,
0075 const vector<PuppiCandidate> &particles,
0076 const PuppiCandidate ¢re,
0077 const double R) const {
0078 if (iId == -1)
0079 return 1.;
0080
0081 double const r2 = R * R;
0082 double var = 0.;
0083
0084 for (auto const &cand : particles) {
0085 if (std::abs(cand.rapidity - centre.rapidity) < R) {
0086 auto const dr2y = reco::deltaR2(cand.rapidity, cand.phi, centre.rapidity, centre.phi);
0087 if (dr2y < r2) {
0088 auto const dr2 = reco::deltaR2(cand.eta, cand.phi, centre.eta, centre.phi);
0089 if (dr2 < 0.0001)
0090 continue;
0091 auto const pt = cand.pt;
0092 switch (iId) {
0093 case 5:
0094 var += (pt * pt / dr2);
0095 break;
0096 case 4:
0097 var += pt;
0098 break;
0099 case 3:
0100 var += (1. / dr2);
0101 break;
0102 case 2:
0103 var += (1. / dr2);
0104 break;
0105 case 1:
0106 var += pt;
0107 break;
0108 case 0:
0109 var += (pt / dr2);
0110 break;
0111 }
0112 }
0113 }
0114 }
0115
0116 if ((var != 0.) and ((iId == 0) or (iId == 3) or (iId == 5)))
0117 var = log(var);
0118 else if (iId == 1)
0119 var += centre.pt;
0120
0121 return var;
0122 }
0123
0124
0125 void PuppiContainer::getRMSAvg(int iOpt,
0126 std::vector<PuppiCandidate> const &iConstits,
0127 std::vector<PuppiCandidate> const &iParticles,
0128 std::vector<PuppiCandidate> const &iChargedParticles,
0129 std::vector<double> &oVals) {
0130 for (unsigned int i0 = 0; i0 < iConstits.size(); i0++) {
0131
0132 int pPupId = getPuppiId(iConstits[i0].pt, iConstits[i0].eta);
0133 if (pPupId == -1 || fPuppiAlgo[pPupId].numAlgos() <= iOpt) {
0134 oVals.push_back(-1);
0135 continue;
0136 }
0137
0138 int pAlgo = fPuppiAlgo[pPupId].algoId(iOpt);
0139 bool pCharged = fPuppiAlgo[pPupId].isCharged(iOpt);
0140 double pCone = fPuppiAlgo[pPupId].coneSize(iOpt);
0141
0142
0143
0144 double pVal = -1;
0145 bool const getsDefaultWgtIfApplyCHS = iConstits[i0].id == 1 or iConstits[i0].id == 2;
0146 if (not((fApplyCHS and getsDefaultWgtIfApplyCHS) or iConstits[i0].id == 3) or
0147 (std::abs(iConstits[i0].eta) < fPuppiAlgo[pPupId].etaMaxExtrap() and getsDefaultWgtIfApplyCHS)) {
0148 pVal = goodVar(iConstits[i0], pCharged ? iChargedParticles : iParticles, pAlgo, pCone);
0149 }
0150 oVals.push_back(pVal);
0151
0152 if (!edm::isFinite(pVal)) {
0153 LogDebug("NotFound") << "====> Value is Nan " << pVal << " == " << iConstits[i0].pt << " -- " << iConstits[i0].eta
0154 << endl;
0155 continue;
0156 }
0157
0158
0159 int count = 0;
0160 for (auto &algo : fPuppiAlgo) {
0161 int index = count++;
0162
0163 if (not(std::abs(iConstits[i0].eta) < algo.etaMaxExtrap() and getsDefaultWgtIfApplyCHS))
0164 continue;
0165
0166 auto curVal = pVal;
0167
0168 if (index != pPupId) {
0169 pAlgo = algo.algoId(iOpt);
0170 pCharged = algo.isCharged(iOpt);
0171 pCone = algo.coneSize(iOpt);
0172 curVal = goodVar(iConstits[i0], pCharged ? iChargedParticles : iParticles, pAlgo, pCone);
0173 }
0174
0175 algo.add(iConstits[i0], curVal, iOpt);
0176 }
0177 }
0178
0179 for (auto &algo : fPuppiAlgo)
0180 algo.computeMedRMS(iOpt);
0181 }
0182
0183
0184 std::vector<double> PuppiContainer::getRawAlphas(int iOpt,
0185 std::vector<PuppiCandidate> const &iConstits,
0186 std::vector<PuppiCandidate> const &iParticles,
0187 std::vector<PuppiCandidate> const &iChargedParticles) const {
0188 std::vector<double> oRawAlphas;
0189 oRawAlphas.reserve(fPuppiAlgo.size() * iConstits.size());
0190 for (auto &algo : fPuppiAlgo) {
0191 for (auto const &constit : iConstits) {
0192
0193 int pAlgo = algo.algoId(iOpt);
0194 bool pCharged = algo.isCharged(iOpt);
0195 double pCone = algo.coneSize(iOpt);
0196
0197 double const pVal = goodVar(constit, pCharged ? iChargedParticles : iParticles, pAlgo, pCone);
0198 oRawAlphas.push_back(pVal);
0199 if (!edm::isFinite(pVal)) {
0200 LogDebug("NotFound") << "====> Value is Nan " << pVal << " == " << constit.pt << " -- " << constit.eta << endl;
0201 continue;
0202 }
0203 }
0204 }
0205 return oRawAlphas;
0206 }
0207
0208 int PuppiContainer::getPuppiId(float iPt, float iEta) {
0209 int lId = -1;
0210 int count = 0;
0211 for (auto &algo : fPuppiAlgo) {
0212 int index = count++;
0213 int nEtaBinsPerAlgo = algo.etaBins();
0214 for (int i1 = 0; i1 < nEtaBinsPerAlgo; i1++) {
0215 if ((std::abs(iEta) >= algo.etaMin(i1)) && (std::abs(iEta) < algo.etaMax(i1))) {
0216 algo.fixAlgoEtaBin(i1);
0217 if (iPt > algo.ptMin()) {
0218 lId = index;
0219 break;
0220 }
0221 }
0222 }
0223 }
0224
0225 return lId;
0226 }
0227 double PuppiContainer::getChi2FromdZ(double iDZ) const {
0228
0229
0230
0231
0232 double lProbLV = ROOT::Math::normal_cdf_c(std::abs(iDZ), 1.) * 2.;
0233 double lProbPU = 1 - lProbLV;
0234 if (lProbPU <= 0)
0235 lProbPU = 1e-16;
0236 if (lProbPU >= 0)
0237 lProbPU = 1 - 1e-16;
0238 double lChi2PU = TMath::ChisquareQuantile(lProbPU, 1);
0239 lChi2PU *= lChi2PU;
0240 return lChi2PU;
0241 }
0242 PuppiContainer::Weights PuppiContainer::calculatePuppiWeights(const std::vector<RecoObj> &iRecoObjects,
0243 double iPUProxy) {
0244 std::vector<PuppiCandidate> pfParticles;
0245 std::vector<PuppiCandidate> pfParticlesForVar;
0246 std::vector<PuppiCandidate> pfParticlesForVarChargedPV;
0247
0248 initialize(iRecoObjects, pfParticles, pfParticlesForVar, pfParticlesForVarChargedPV);
0249
0250 int lNParticles = iRecoObjects.size();
0251
0252 Weights returnValue;
0253 returnValue.weights.reserve(lNParticles);
0254 returnValue.puppiAlphas.reserve(lNParticles);
0255
0256
0257 auto doReset = [this](void *) {
0258 for (auto &algo : fPuppiAlgo)
0259 algo.reset();
0260 };
0261 std::unique_ptr<decltype(fPuppiAlgo), decltype(doReset)> guard(&fPuppiAlgo, doReset);
0262
0263 int lNMaxAlgo = 1;
0264 for (auto &algo : fPuppiAlgo)
0265 lNMaxAlgo = std::max(algo.numAlgos(), lNMaxAlgo);
0266
0267 for (int i0 = 0; i0 < lNMaxAlgo; i0++) {
0268 getRMSAvg(i0, pfParticles, pfParticlesForVar, pfParticlesForVarChargedPV, returnValue.puppiAlphas);
0269 }
0270 if (fPuppiDiagnostics)
0271 returnValue.puppiRawAlphas = getRawAlphas(0, pfParticles, pfParticlesForVar, pfParticlesForVarChargedPV);
0272
0273 std::vector<double> pVals;
0274 pVals.reserve(lNParticles);
0275 for (int i0 = 0; i0 < lNParticles; i0++) {
0276
0277 pVals.clear();
0278
0279 const auto &rParticle = iRecoObjects[i0];
0280 int pPupId = getPuppiId(rParticle.pt, rParticle.eta);
0281 if (pPupId == -1) {
0282 returnValue.weights.push_back(0);
0283 returnValue.puppiAlphasMed.push_back(-10);
0284 returnValue.puppiAlphasRMS.push_back(-10);
0285 continue;
0286 }
0287
0288
0289 double pChi2 = 0;
0290 if (fUseExp) {
0291
0292 pChi2 = getChi2FromdZ(rParticle.dZ);
0293
0294 if ((std::abs(rParticle.pdgId) == 22) || (std::abs(rParticle.pdgId) == 130))
0295 pChi2 = 0;
0296 }
0297
0298 int lNAlgos = fPuppiAlgo[pPupId].numAlgos();
0299 for (int i1 = 0; i1 < lNAlgos; i1++)
0300 pVals.push_back(returnValue.puppiAlphas[lNParticles * i1 + i0]);
0301
0302 double pWeight = fPuppiAlgo[pPupId].compute(pVals, pChi2);
0303
0304 if (rParticle.id == 1 && fApplyCHS)
0305 pWeight = 1;
0306 if (rParticle.id == 2 && fApplyCHS)
0307 pWeight = 0;
0308
0309 if (rParticle.id == 3)
0310 pWeight = 1;
0311
0312 if (!edm::isFinite(pWeight)) {
0313 pWeight = 0.0;
0314 LogDebug("PuppiWeightError") << "====> Weight is nan : " << pWeight << " : pt " << rParticle.pt
0315 << " -- eta : " << rParticle.eta << " -- Value" << returnValue.puppiAlphas[i0]
0316 << " -- id : " << rParticle.id << " -- NAlgos: " << lNAlgos << std::endl;
0317 }
0318
0319 if (pWeight * pfParticles[i0].pt < fPuppiAlgo[pPupId].neutralPt(iPUProxy) && rParticle.id == 0)
0320 pWeight = 0;
0321
0322 if (fPtMaxPhotons > 0 && rParticle.pdgId == 22 && std::abs(pfParticles[i0].eta) < fEtaMaxPhotons &&
0323 pfParticles[i0].pt > fPtMaxPhotons)
0324 pWeight = 1.;
0325
0326 else if ((fPtMaxNeutrals > 0) && (rParticle.id == 0))
0327 pWeight = std::clamp(
0328 (pfParticles[i0].pt - fPtMaxNeutralsStartSlope) / (fPtMaxNeutrals - fPtMaxNeutralsStartSlope), pWeight, 1.);
0329 if (pWeight < fPuppiWeightCut)
0330 pWeight = 0;
0331 if (fInvert)
0332 pWeight = 1. - pWeight;
0333
0334
0335 returnValue.weights.push_back(pWeight);
0336 returnValue.puppiAlphasMed.push_back(fPuppiAlgo[pPupId].median());
0337 returnValue.puppiAlphasRMS.push_back(fPuppiAlgo[pPupId].rms());
0338
0339
0340
0341
0342
0343 }
0344 return returnValue;
0345 }