File indexing completed on 2024-04-06 12:31:22
0001 #include "FWCore/Framework/interface/Event.h"
0002 #include "FWCore/Framework/interface/stream/EDProducer.h"
0003 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0004
0005 #include "PhysicsTools/JetMCUtils/interface/combination.h"
0006 #include "AnalysisDataFormats/TopObjects/interface/TtSemiLepEvtPartons.h"
0007 #include "TopQuarkAnalysis/TopKinFitter/interface/TtSemiLepKinFitter.h"
0008
0009 template <typename LeptonCollection>
0010 class TtSemiLepKinFitProducer : public edm::stream::EDProducer<> {
0011 public:
0012 explicit TtSemiLepKinFitProducer(const edm::ParameterSet&);
0013
0014 private:
0015
0016 void produce(edm::Event&, const edm::EventSetup&) override;
0017
0018
0019 TtSemiLepKinFitter::Param param(unsigned);
0020
0021 TtSemiLepKinFitter::Constraint constraint(unsigned);
0022
0023 std::vector<TtSemiLepKinFitter::Constraint> constraints(std::vector<unsigned>&);
0024
0025 bool doBTagging(bool& useBTag_,
0026 const edm::Handle<std::vector<pat::Jet>>& jets,
0027 const std::vector<int>& combi,
0028 std::string& bTagAlgo_,
0029 double& minBTagValueBJets_,
0030 double& maxBTagValueNonBJets_);
0031
0032 edm::EDGetTokenT<std::vector<pat::Jet>> jetsToken_;
0033 edm::EDGetTokenT<LeptonCollection> lepsToken_;
0034 edm::EDGetTokenT<std::vector<pat::MET>> metsToken_;
0035
0036 edm::EDGetTokenT<std::vector<std::vector<int>>> matchToken_;
0037
0038 bool useOnlyMatch_;
0039
0040 std::string bTagAlgo_;
0041
0042 double minBTagValueBJet_;
0043
0044 double maxBTagValueNonBJet_;
0045
0046 bool useBTag_;
0047
0048 int maxNJets_;
0049
0050 int maxNComb_;
0051
0052
0053 unsigned int maxNrIter_;
0054
0055 double maxDeltaS_;
0056
0057 double maxF_;
0058 unsigned int jetParam_;
0059 unsigned int lepParam_;
0060 unsigned int metParam_;
0061
0062 std::vector<unsigned> constraints_;
0063 double mW_;
0064 double mTop_;
0065
0066 std::vector<double> jetEnergyResolutionScaleFactors_;
0067 std::vector<double> jetEnergyResolutionEtaBinning_;
0068
0069 std::vector<edm::ParameterSet> udscResolutions_;
0070 std::vector<edm::ParameterSet> bResolutions_;
0071 std::vector<edm::ParameterSet> lepResolutions_;
0072 std::vector<edm::ParameterSet> metResolutions_;
0073
0074 std::unique_ptr<TtSemiLepKinFitter> fitter;
0075
0076 struct KinFitResult {
0077 int Status;
0078 double Chi2;
0079 double Prob;
0080 pat::Particle HadB;
0081 pat::Particle HadP;
0082 pat::Particle HadQ;
0083 pat::Particle LepB;
0084 pat::Particle LepL;
0085 pat::Particle LepN;
0086 std::vector<int> JetCombi;
0087 bool operator<(const KinFitResult& rhs) { return Chi2 < rhs.Chi2; };
0088 };
0089 };
0090
0091 template <typename LeptonCollection>
0092 TtSemiLepKinFitProducer<LeptonCollection>::TtSemiLepKinFitProducer(const edm::ParameterSet& cfg)
0093 : jetsToken_(consumes<std::vector<pat::Jet>>(cfg.getParameter<edm::InputTag>("jets"))),
0094 lepsToken_(consumes<LeptonCollection>(cfg.getParameter<edm::InputTag>("leps"))),
0095 metsToken_(consumes<std::vector<pat::MET>>(cfg.getParameter<edm::InputTag>("mets"))),
0096 matchToken_(mayConsume<std::vector<std::vector<int>>>(cfg.getParameter<edm::InputTag>("match"))),
0097 useOnlyMatch_(cfg.getParameter<bool>("useOnlyMatch")),
0098 bTagAlgo_(cfg.getParameter<std::string>("bTagAlgo")),
0099 minBTagValueBJet_(cfg.getParameter<double>("minBDiscBJets")),
0100 maxBTagValueNonBJet_(cfg.getParameter<double>("maxBDiscLightJets")),
0101 useBTag_(cfg.getParameter<bool>("useBTagging")),
0102 maxNJets_(cfg.getParameter<int>("maxNJets")),
0103 maxNComb_(cfg.getParameter<int>("maxNComb")),
0104 maxNrIter_(cfg.getParameter<unsigned>("maxNrIter")),
0105 maxDeltaS_(cfg.getParameter<double>("maxDeltaS")),
0106 maxF_(cfg.getParameter<double>("maxF")),
0107 jetParam_(cfg.getParameter<unsigned>("jetParametrisation")),
0108 lepParam_(cfg.getParameter<unsigned>("lepParametrisation")),
0109 metParam_(cfg.getParameter<unsigned>("metParametrisation")),
0110 constraints_(cfg.getParameter<std::vector<unsigned>>("constraints")),
0111 mW_(cfg.getParameter<double>("mW")),
0112 mTop_(cfg.getParameter<double>("mTop")),
0113 jetEnergyResolutionScaleFactors_(cfg.getParameter<std::vector<double>>("jetEnergyResolutionScaleFactors")),
0114 jetEnergyResolutionEtaBinning_(cfg.getParameter<std::vector<double>>("jetEnergyResolutionEtaBinning")),
0115 udscResolutions_(0),
0116 bResolutions_(0),
0117 lepResolutions_(0),
0118 metResolutions_(0) {
0119 if (cfg.exists("udscResolutions") && cfg.exists("bResolutions") && cfg.exists("lepResolutions") &&
0120 cfg.exists("metResolutions")) {
0121 udscResolutions_ = cfg.getParameter<std::vector<edm::ParameterSet>>("udscResolutions");
0122 bResolutions_ = cfg.getParameter<std::vector<edm::ParameterSet>>("bResolutions");
0123 lepResolutions_ = cfg.getParameter<std::vector<edm::ParameterSet>>("lepResolutions");
0124 metResolutions_ = cfg.getParameter<std::vector<edm::ParameterSet>>("metResolutions");
0125 } else if (cfg.exists("udscResolutions") || cfg.exists("bResolutions") || cfg.exists("lepResolutions") ||
0126 cfg.exists("metResolutions")) {
0127 throw cms::Exception("Configuration") << "Parameters 'udscResolutions', 'bResolutions', 'lepResolutions', "
0128 "'metResolutions' should be used together.\n";
0129 }
0130
0131 fitter = std::make_unique<TtSemiLepKinFitter>(param(jetParam_),
0132 param(lepParam_),
0133 param(metParam_),
0134 maxNrIter_,
0135 maxDeltaS_,
0136 maxF_,
0137 constraints(constraints_),
0138 mW_,
0139 mTop_,
0140 &udscResolutions_,
0141 &bResolutions_,
0142 &lepResolutions_,
0143 &metResolutions_,
0144 &jetEnergyResolutionScaleFactors_,
0145 &jetEnergyResolutionEtaBinning_);
0146
0147 produces<std::vector<pat::Particle>>("PartonsHadP");
0148 produces<std::vector<pat::Particle>>("PartonsHadQ");
0149 produces<std::vector<pat::Particle>>("PartonsHadB");
0150 produces<std::vector<pat::Particle>>("PartonsLepB");
0151 produces<std::vector<pat::Particle>>("Leptons");
0152 produces<std::vector<pat::Particle>>("Neutrinos");
0153
0154 produces<std::vector<std::vector<int>>>();
0155 produces<std::vector<double>>("Chi2");
0156 produces<std::vector<double>>("Prob");
0157 produces<std::vector<int>>("Status");
0158
0159 produces<int>("NumberOfConsideredJets");
0160 }
0161
0162 template <typename LeptonCollection>
0163 bool TtSemiLepKinFitProducer<LeptonCollection>::doBTagging(bool& useBTag_,
0164 const edm::Handle<std::vector<pat::Jet>>& jets,
0165 const std::vector<int>& combi,
0166 std::string& bTagAlgo_,
0167 double& minBTagValueBJet_,
0168 double& maxBTagValueNonBJet_) {
0169 if (!useBTag_) {
0170 return true;
0171 }
0172 if (useBTag_ && (*jets)[combi[TtSemiLepEvtPartons::HadB]].bDiscriminator(bTagAlgo_) >= minBTagValueBJet_ &&
0173 (*jets)[combi[TtSemiLepEvtPartons::LepB]].bDiscriminator(bTagAlgo_) >= minBTagValueBJet_ &&
0174 (*jets)[combi[TtSemiLepEvtPartons::LightQ]].bDiscriminator(bTagAlgo_) < maxBTagValueNonBJet_ &&
0175 (*jets)[combi[TtSemiLepEvtPartons::LightQBar]].bDiscriminator(bTagAlgo_) < maxBTagValueNonBJet_) {
0176 return true;
0177 } else {
0178 return false;
0179 }
0180 }
0181
0182 template <typename LeptonCollection>
0183 void TtSemiLepKinFitProducer<LeptonCollection>::produce(edm::Event& evt, const edm::EventSetup& setup) {
0184 std::unique_ptr<std::vector<pat::Particle>> pPartonsHadP(new std::vector<pat::Particle>);
0185 std::unique_ptr<std::vector<pat::Particle>> pPartonsHadQ(new std::vector<pat::Particle>);
0186 std::unique_ptr<std::vector<pat::Particle>> pPartonsHadB(new std::vector<pat::Particle>);
0187 std::unique_ptr<std::vector<pat::Particle>> pPartonsLepB(new std::vector<pat::Particle>);
0188 std::unique_ptr<std::vector<pat::Particle>> pLeptons(new std::vector<pat::Particle>);
0189 std::unique_ptr<std::vector<pat::Particle>> pNeutrinos(new std::vector<pat::Particle>);
0190
0191 std::unique_ptr<std::vector<std::vector<int>>> pCombi(new std::vector<std::vector<int>>);
0192 std::unique_ptr<std::vector<double>> pChi2(new std::vector<double>);
0193 std::unique_ptr<std::vector<double>> pProb(new std::vector<double>);
0194 std::unique_ptr<std::vector<int>> pStatus(new std::vector<int>);
0195
0196 std::unique_ptr<int> pJetsConsidered(new int);
0197
0198 const edm::Handle<std::vector<pat::Jet>>& jets = evt.getHandle(jetsToken_);
0199
0200 const edm::Handle<std::vector<pat::MET>>& mets = evt.getHandle(metsToken_);
0201
0202 const edm::Handle<LeptonCollection>& leps = evt.getHandle(lepsToken_);
0203
0204 const unsigned int nPartons = 4;
0205
0206 std::vector<int> match;
0207 bool invalidMatch = false;
0208 if (useOnlyMatch_) {
0209 *pJetsConsidered = nPartons;
0210 const edm::Handle<std::vector<std::vector<int>>>& matchHandle = evt.getHandle(matchToken_);
0211 match = *(matchHandle->begin());
0212
0213 if (match.size() != nPartons)
0214 invalidMatch = true;
0215 else {
0216 for (unsigned int idx = 0; idx < match.size(); ++idx) {
0217 if (match[idx] < 0 || match[idx] >= (int)jets->size()) {
0218 invalidMatch = true;
0219 break;
0220 }
0221 }
0222 }
0223 }
0224
0225
0226
0227
0228
0229
0230 if (leps->empty() || mets->empty() || jets->size() < nPartons || invalidMatch) {
0231
0232 pPartonsHadP->push_back(fitter->fittedHadP());
0233 pPartonsHadQ->push_back(fitter->fittedHadQ());
0234 pPartonsHadB->push_back(fitter->fittedHadB());
0235 pPartonsLepB->push_back(fitter->fittedLepB());
0236 pLeptons->push_back(fitter->fittedLepton());
0237 pNeutrinos->push_back(fitter->fittedNeutrino());
0238
0239 std::vector<int> invalidCombi;
0240 for (unsigned int i = 0; i < nPartons; ++i)
0241 invalidCombi.push_back(-1);
0242 pCombi->push_back(invalidCombi);
0243
0244 pChi2->push_back(-1.);
0245
0246 pProb->push_back(-1.);
0247
0248 pStatus->push_back(-1);
0249
0250 *pJetsConsidered = jets->size();
0251
0252 evt.put(std::move(pCombi));
0253 evt.put(std::move(pPartonsHadP), "PartonsHadP");
0254 evt.put(std::move(pPartonsHadQ), "PartonsHadQ");
0255 evt.put(std::move(pPartonsHadB), "PartonsHadB");
0256 evt.put(std::move(pPartonsLepB), "PartonsLepB");
0257 evt.put(std::move(pLeptons), "Leptons");
0258 evt.put(std::move(pNeutrinos), "Neutrinos");
0259 evt.put(std::move(pChi2), "Chi2");
0260 evt.put(std::move(pProb), "Prob");
0261 evt.put(std::move(pStatus), "Status");
0262 evt.put(std::move(pJetsConsidered), "NumberOfConsideredJets");
0263 return;
0264 }
0265
0266
0267
0268
0269
0270
0271 std::vector<int> jetIndices;
0272 if (!useOnlyMatch_) {
0273 for (unsigned int i = 0; i < jets->size(); ++i) {
0274 if (maxNJets_ >= (int)nPartons && maxNJets_ == (int)i) {
0275 *pJetsConsidered = i;
0276 break;
0277 }
0278 jetIndices.push_back(i);
0279 }
0280 }
0281
0282 std::vector<int> combi;
0283 for (unsigned int i = 0; i < nPartons; ++i) {
0284 if (useOnlyMatch_)
0285 combi.push_back(match[i]);
0286 else
0287 combi.push_back(i);
0288 }
0289
0290 std::list<KinFitResult> FitResultList;
0291
0292 do {
0293 for (int cnt = 0; cnt < TMath::Factorial(combi.size()); ++cnt) {
0294
0295
0296 if ((combi[TtSemiLepEvtPartons::LightQ] < combi[TtSemiLepEvtPartons::LightQBar] || useOnlyMatch_) &&
0297 doBTagging(useBTag_, jets, combi, bTagAlgo_, minBTagValueBJet_, maxBTagValueNonBJet_)) {
0298 std::vector<pat::Jet> jetCombi;
0299 jetCombi.resize(nPartons);
0300 jetCombi[TtSemiLepEvtPartons::LightQ] = (*jets)[combi[TtSemiLepEvtPartons::LightQ]];
0301 jetCombi[TtSemiLepEvtPartons::LightQBar] = (*jets)[combi[TtSemiLepEvtPartons::LightQBar]];
0302 jetCombi[TtSemiLepEvtPartons::HadB] = (*jets)[combi[TtSemiLepEvtPartons::HadB]];
0303 jetCombi[TtSemiLepEvtPartons::LepB] = (*jets)[combi[TtSemiLepEvtPartons::LepB]];
0304
0305
0306 const int status = fitter->fit(jetCombi, (*leps)[0], (*mets)[0]);
0307
0308 if (status == 0) {
0309 KinFitResult result;
0310 result.Status = status;
0311 result.Chi2 = fitter->fitS();
0312 result.Prob = fitter->fitProb();
0313 result.HadB = fitter->fittedHadB();
0314 result.HadP = fitter->fittedHadP();
0315 result.HadQ = fitter->fittedHadQ();
0316 result.LepB = fitter->fittedLepB();
0317 result.LepL = fitter->fittedLepton();
0318 result.LepN = fitter->fittedNeutrino();
0319 result.JetCombi = combi;
0320
0321 FitResultList.push_back(result);
0322 }
0323 }
0324 if (useOnlyMatch_)
0325 break;
0326 next_permutation(combi.begin(), combi.end());
0327 }
0328 if (useOnlyMatch_)
0329 break;
0330 } while (stdcomb::next_combination(jetIndices.begin(), jetIndices.end(), combi.begin(), combi.end()));
0331
0332
0333 FitResultList.sort();
0334
0335
0336
0337
0338
0339
0340 if ((unsigned)FitResultList.size() < 1) {
0341 pPartonsHadP->push_back(fitter->fittedHadP());
0342 pPartonsHadQ->push_back(fitter->fittedHadQ());
0343 pPartonsHadB->push_back(fitter->fittedHadB());
0344 pPartonsLepB->push_back(fitter->fittedLepB());
0345 pLeptons->push_back(fitter->fittedLepton());
0346 pNeutrinos->push_back(fitter->fittedNeutrino());
0347
0348 std::vector<int> invalidCombi;
0349 for (unsigned int i = 0; i < nPartons; ++i)
0350 invalidCombi.push_back(-1);
0351 pCombi->push_back(invalidCombi);
0352
0353 pChi2->push_back(-1.);
0354
0355 pProb->push_back(-1.);
0356
0357 pStatus->push_back(-1);
0358 } else {
0359 unsigned int iComb = 0;
0360 for (typename std::list<KinFitResult>::const_iterator result = FitResultList.begin(); result != FitResultList.end();
0361 ++result) {
0362 if (maxNComb_ >= 1 && iComb == (unsigned int)maxNComb_)
0363 break;
0364 iComb++;
0365
0366 pPartonsHadP->push_back(result->HadP);
0367 pPartonsHadQ->push_back(result->HadQ);
0368 pPartonsHadB->push_back(result->HadB);
0369 pPartonsLepB->push_back(result->LepB);
0370
0371 pLeptons->push_back(result->LepL);
0372
0373 pNeutrinos->push_back(result->LepN);
0374
0375 pCombi->push_back(result->JetCombi);
0376
0377 pChi2->push_back(result->Chi2);
0378
0379 pProb->push_back(result->Prob);
0380
0381 pStatus->push_back(result->Status);
0382 }
0383 }
0384 evt.put(std::move(pCombi));
0385 evt.put(std::move(pPartonsHadP), "PartonsHadP");
0386 evt.put(std::move(pPartonsHadQ), "PartonsHadQ");
0387 evt.put(std::move(pPartonsHadB), "PartonsHadB");
0388 evt.put(std::move(pPartonsLepB), "PartonsLepB");
0389 evt.put(std::move(pLeptons), "Leptons");
0390 evt.put(std::move(pNeutrinos), "Neutrinos");
0391 evt.put(std::move(pChi2), "Chi2");
0392 evt.put(std::move(pProb), "Prob");
0393 evt.put(std::move(pStatus), "Status");
0394 evt.put(std::move(pJetsConsidered), "NumberOfConsideredJets");
0395 }
0396
0397 template <typename LeptonCollection>
0398 TtSemiLepKinFitter::Param TtSemiLepKinFitProducer<LeptonCollection>::param(unsigned val) {
0399 TtSemiLepKinFitter::Param result;
0400 switch (val) {
0401 case TtSemiLepKinFitter::kEMom:
0402 result = TtSemiLepKinFitter::kEMom;
0403 break;
0404 case TtSemiLepKinFitter::kEtEtaPhi:
0405 result = TtSemiLepKinFitter::kEtEtaPhi;
0406 break;
0407 case TtSemiLepKinFitter::kEtThetaPhi:
0408 result = TtSemiLepKinFitter::kEtThetaPhi;
0409 break;
0410 default:
0411 throw cms::Exception("Configuration") << "Chosen jet parametrization is not supported: " << val << "\n";
0412 break;
0413 }
0414 return result;
0415 }
0416
0417 template <typename LeptonCollection>
0418 TtSemiLepKinFitter::Constraint TtSemiLepKinFitProducer<LeptonCollection>::constraint(unsigned val) {
0419 TtSemiLepKinFitter::Constraint result;
0420 switch (val) {
0421 case TtSemiLepKinFitter::kWHadMass:
0422 result = TtSemiLepKinFitter::kWHadMass;
0423 break;
0424 case TtSemiLepKinFitter::kWLepMass:
0425 result = TtSemiLepKinFitter::kWLepMass;
0426 break;
0427 case TtSemiLepKinFitter::kTopHadMass:
0428 result = TtSemiLepKinFitter::kTopHadMass;
0429 break;
0430 case TtSemiLepKinFitter::kTopLepMass:
0431 result = TtSemiLepKinFitter::kTopLepMass;
0432 break;
0433 case TtSemiLepKinFitter::kNeutrinoMass:
0434 result = TtSemiLepKinFitter::kNeutrinoMass;
0435 break;
0436 case TtSemiLepKinFitter::kEqualTopMasses:
0437 result = TtSemiLepKinFitter::kEqualTopMasses;
0438 break;
0439 case TtSemiLepKinFitter::kSumPt:
0440 result = TtSemiLepKinFitter::kSumPt;
0441 break;
0442 default:
0443 throw cms::Exception("Configuration") << "Chosen fit constraint is not supported: " << val << "\n";
0444 break;
0445 }
0446 return result;
0447 }
0448
0449 template <typename LeptonCollection>
0450 std::vector<TtSemiLepKinFitter::Constraint> TtSemiLepKinFitProducer<LeptonCollection>::constraints(
0451 std::vector<unsigned>& val) {
0452 std::vector<TtSemiLepKinFitter::Constraint> result;
0453 for (unsigned i = 0; i < val.size(); ++i) {
0454 result.push_back(constraint(val[i]));
0455 }
0456 return result;
0457 }
0458
0459 #include "DataFormats/PatCandidates/interface/Muon.h"
0460 #include "DataFormats/PatCandidates/interface/Electron.h"
0461 using TtSemiLepKinFitProducerMuon = TtSemiLepKinFitProducer<std::vector<pat::Muon>>;
0462 using TtSemiLepKinFitProducerElectron = TtSemiLepKinFitProducer<std::vector<pat::Electron>>;
0463
0464 #include "FWCore/Framework/interface/MakerMacros.h"
0465 DEFINE_FWK_MODULE(TtSemiLepKinFitProducerMuon);
0466 DEFINE_FWK_MODULE(TtSemiLepKinFitProducerElectron);