File indexing completed on 2024-04-06 12:31:21
0001 #include "CommonTools/CandUtils/interface/AddFourMomenta.h"
0002 #include "AnalysisDataFormats/TopObjects/interface/TtSemiLepEvtPartons.h"
0003 #include "DataFormats/PatCandidates/interface/Electron.h"
0004 #include "DataFormats/PatCandidates/interface/Muon.h"
0005 #include "TopQuarkAnalysis/TopTools/interface/MEzCalculator.h"
0006
0007 #include "TopQuarkAnalysis/TopJetCombination/interface/TtSemiLepHypothesis.h"
0008
0009
0010 TtSemiLepHypothesis::TtSemiLepHypothesis(const edm::ParameterSet& cfg)
0011 : jetsToken_(consumes<std::vector<pat::Jet> >(cfg.getParameter<edm::InputTag>("jets"))),
0012 lepsToken_(consumes<edm::View<reco::RecoCandidate> >(cfg.getParameter<edm::InputTag>("leps"))),
0013 metsToken_(consumes<std::vector<pat::MET> >(cfg.getParameter<edm::InputTag>("mets"))),
0014 nJetsConsideredToken_(consumes<int>(cfg.getParameter<edm::InputTag>("nJetsConsidered"))),
0015 numberOfRealNeutrinoSolutions_(-1) {
0016 getMatch_ = false;
0017 if (cfg.exists("match")) {
0018 getMatch_ = true;
0019 matchToken_ = consumes<std::vector<std::vector<int> > >(cfg.getParameter<edm::InputTag>("match"));
0020 }
0021 if (cfg.exists("neutrinoSolutionType"))
0022 neutrinoSolutionType_ = cfg.getParameter<int>("neutrinoSolutionType");
0023 else
0024 neutrinoSolutionType_ = -1;
0025 if (cfg.exists("jetCorrectionLevel")) {
0026 jetCorrectionLevel_ = cfg.getParameter<std::string>("jetCorrectionLevel");
0027 }
0028 produces<std::vector<std::pair<reco::CompositeCandidate, std::vector<int> > > >();
0029 produces<int>("Key");
0030 produces<int>("NumberOfRealNeutrinoSolutions");
0031 produces<int>("NumberOfConsideredJets");
0032 }
0033
0034
0035 void TtSemiLepHypothesis::produce(edm::Event& evt, const edm::EventSetup& setup) {
0036 edm::Handle<std::vector<pat::Jet> > jets;
0037 evt.getByToken(jetsToken_, jets);
0038
0039 edm::Handle<edm::View<reco::RecoCandidate> > leps;
0040 evt.getByToken(lepsToken_, leps);
0041
0042 edm::Handle<std::vector<pat::MET> > mets;
0043 evt.getByToken(metsToken_, mets);
0044
0045 edm::Handle<int> nJetsConsidered;
0046 evt.getByToken(nJetsConsideredToken_, nJetsConsidered);
0047
0048 std::vector<std::vector<int> > matchVec;
0049 if (getMatch_) {
0050 edm::Handle<std::vector<std::vector<int> > > matchHandle;
0051 evt.getByToken(matchToken_, matchHandle);
0052 matchVec = *matchHandle;
0053 } else {
0054 std::vector<int> dummyMatch;
0055 for (unsigned int i = 0; i < 4; ++i)
0056 dummyMatch.push_back(-1);
0057 matchVec.push_back(dummyMatch);
0058 }
0059
0060
0061 std::unique_ptr<std::vector<std::pair<reco::CompositeCandidate, std::vector<int> > > > pOut(
0062 new std::vector<std::pair<reco::CompositeCandidate, std::vector<int> > >);
0063 std::unique_ptr<int> pKey(new int);
0064 std::unique_ptr<int> pNeutrinoSolutions(new int);
0065 std::unique_ptr<int> pJetsConsidered(new int);
0066
0067
0068 unsigned int idMatch = 0;
0069 typedef std::vector<std::vector<int> >::iterator MatchVecIterator;
0070 for (MatchVecIterator match = matchVec.begin(); match != matchVec.end(); ++match) {
0071
0072 resetCandidates();
0073
0074 buildHypo(evt, leps, mets, jets, *match, idMatch++);
0075 pOut->push_back(std::make_pair(hypo(), *match));
0076 }
0077
0078 evt.put(std::move(pOut));
0079
0080
0081 buildKey();
0082 *pKey = key();
0083 evt.put(std::move(pKey), "Key");
0084
0085
0086 *pNeutrinoSolutions = numberOfRealNeutrinoSolutions_;
0087 evt.put(std::move(pNeutrinoSolutions), "NumberOfRealNeutrinoSolutions");
0088
0089
0090 *pJetsConsidered = *nJetsConsidered;
0091 evt.put(std::move(pJetsConsidered), "NumberOfConsideredJets");
0092 }
0093
0094
0095 void TtSemiLepHypothesis::resetCandidates() {
0096 numberOfRealNeutrinoSolutions_ = -1;
0097 lightQ_.reset();
0098 lightQBar_.reset();
0099 hadronicB_.reset();
0100 leptonicB_.reset();
0101 neutrino_.reset();
0102 lepton_.reset();
0103 }
0104
0105
0106 reco::CompositeCandidate TtSemiLepHypothesis::hypo() {
0107
0108 if (!lightQ_ || !lightQBar_ || !hadronicB_ || !leptonicB_ || !neutrino_ || !lepton_)
0109 return reco::CompositeCandidate();
0110
0111
0112 reco::CompositeCandidate hyp, hadTop, hadW, lepTop, lepW;
0113
0114 AddFourMomenta addFourMomenta;
0115
0116 lepW.addDaughter(std::move(lepton_), TtSemiLepDaughter::Lep);
0117 lepW.addDaughter(std::move(neutrino_), TtSemiLepDaughter::Nu);
0118 addFourMomenta.set(lepW);
0119 lepTop.addDaughter(lepW, TtSemiLepDaughter::LepW);
0120 lepTop.addDaughter(std::move(leptonicB_), TtSemiLepDaughter::LepB);
0121 addFourMomenta.set(lepTop);
0122
0123
0124 hadW.addDaughter(std::move(lightQ_), TtSemiLepDaughter::HadP);
0125 hadW.addDaughter(std::move(lightQBar_), TtSemiLepDaughter::HadQ);
0126 addFourMomenta.set(hadW);
0127 hadTop.addDaughter(hadW, TtSemiLepDaughter::HadW);
0128 hadTop.addDaughter(std::move(hadronicB_), TtSemiLepDaughter::HadB);
0129 addFourMomenta.set(hadTop);
0130
0131
0132 hyp.addDaughter(lepTop, TtSemiLepDaughter::LepTop);
0133 hyp.addDaughter(hadTop, TtSemiLepDaughter::HadTop);
0134 addFourMomenta.set(hyp);
0135
0136 return hyp;
0137 }
0138
0139
0140 WDecay::LeptonType TtSemiLepHypothesis::leptonType(const reco::RecoCandidate* cand) {
0141
0142 WDecay::LeptonType type = WDecay::kNone;
0143 if (dynamic_cast<const reco::Muon*>(cand)) {
0144 type = WDecay::kMuon;
0145 } else if (dynamic_cast<const reco::GsfElectron*>(cand)) {
0146 type = WDecay::kElec;
0147 }
0148 return type;
0149 }
0150
0151
0152 std::string TtSemiLepHypothesis::jetCorrectionLevel(const std::string& quarkType) {
0153
0154 if (jetCorrectionLevel_.empty())
0155 throw cms::Exception("Configuration")
0156 << "Unconfigured jetCorrectionLevel. Please use an appropriate, non-empty string.\n";
0157
0158
0159 if (!(quarkType == "wQuarkMix" || quarkType == "udsQuark" || quarkType == "cQuark" || quarkType == "bQuark"))
0160 throw cms::Exception("Configuration") << quarkType << " is unknown as a quarkType for the jetCorrectionLevel.\n";
0161
0162
0163
0164
0165
0166 std::string level = jetCorrectionLevel_ + ":";
0167 if (level == "L5Flavor:" || level == "L6UE:" || level == "L7Parton:") {
0168 if (quarkType == "wQuarkMix") {
0169 level += "wMix";
0170 }
0171 if (quarkType == "udsQuark") {
0172 level += "uds";
0173 }
0174 if (quarkType == "cQuark") {
0175 level += "charm";
0176 }
0177 if (quarkType == "bQuark") {
0178 level += "bottom";
0179 }
0180 } else {
0181 level += "none";
0182 }
0183 return level;
0184 }
0185
0186
0187 std::unique_ptr<reco::ShallowClonePtrCandidate> TtSemiLepHypothesis::makeCandidate(
0188 const edm::Handle<std::vector<pat::Jet> >& handle, const int& idx, const std::string& correctionLevel) {
0189 edm::Ptr<pat::Jet> ptr = edm::Ptr<pat::Jet>(handle, idx);
0190
0191
0192 std::string step = correctionLevel.substr(0, correctionLevel.find(':'));
0193 std::string flavor = correctionLevel.substr(1 + correctionLevel.find(':'));
0194 float corrFactor = 1.;
0195 if (flavor == "wMix")
0196 corrFactor = 0.75 * ptr->jecFactor(step, "uds") + 0.25 * ptr->jecFactor(step, "charm");
0197 else
0198 corrFactor = ptr->jecFactor(step, flavor);
0199 return std::make_unique<reco::ShallowClonePtrCandidate>(ptr, ptr->charge(), ptr->p4() * corrFactor, ptr->vertex());
0200 }
0201
0202
0203 void TtSemiLepHypothesis::setNeutrino(const edm::Handle<std::vector<pat::MET> >& met,
0204 const edm::Handle<edm::View<reco::RecoCandidate> >& leps,
0205 const int& idx,
0206 const int& type) {
0207 edm::Ptr<pat::MET> ptr = edm::Ptr<pat::MET>(met, 0);
0208 MEzCalculator mez;
0209 mez.SetMET(*(met->begin()));
0210 if (leptonType(&(leps->front())) == WDecay::kMuon)
0211 mez.SetLepton((*leps)[idx], true);
0212 else if (leptonType(&(leps->front())) == WDecay::kElec)
0213 mez.SetLepton((*leps)[idx], false);
0214 else
0215 throw cms::Exception("UnimplementedFeature")
0216 << "Type of lepton given together with MET for solving neutrino kinematics is neither muon nor electron.\n";
0217 double pz = mez.Calculate(type);
0218 numberOfRealNeutrinoSolutions_ = mez.IsComplex() ? 0 : 2;
0219 const math::XYZTLorentzVector p4(
0220 ptr->px(), ptr->py(), pz, sqrt(ptr->px() * ptr->px() + ptr->py() * ptr->py() + pz * pz));
0221 neutrino_ = std::make_unique<reco::ShallowClonePtrCandidate>(ptr, ptr->charge(), p4, ptr->vertex());
0222 }
0223
0224
0225 void TtSemiLepHypothesis::buildHypo(const edm::Handle<edm::View<reco::RecoCandidate> >& leps,
0226 const edm::Handle<std::vector<pat::MET> >& mets,
0227 const edm::Handle<std::vector<pat::Jet> >& jets,
0228 std::vector<int>& match) {
0229
0230
0231
0232 for (unsigned idx = 0; idx < match.size(); ++idx) {
0233 if (isValid(match[idx], jets)) {
0234 switch (idx) {
0235 case TtSemiLepEvtPartons::LightQ:
0236 lightQ_ = makeCandidate(jets, match[idx], jetCorrectionLevel("wQuarkMix"));
0237 break;
0238 case TtSemiLepEvtPartons::LightQBar:
0239 lightQBar_ = makeCandidate(jets, match[idx], jetCorrectionLevel("wQuarkMix"));
0240 break;
0241 case TtSemiLepEvtPartons::HadB:
0242 hadronicB_ = makeCandidate(jets, match[idx], jetCorrectionLevel("bQuark"));
0243 break;
0244 case TtSemiLepEvtPartons::LepB:
0245 leptonicB_ = makeCandidate(jets, match[idx], jetCorrectionLevel("bQuark"));
0246 break;
0247 }
0248 }
0249 }
0250
0251
0252
0253
0254 if (leps->empty())
0255 return;
0256 lepton_ = makeCandidate(leps, 0);
0257 match.push_back(0);
0258
0259
0260
0261
0262 if (mets->empty())
0263 return;
0264 if (neutrinoSolutionType_ == -1)
0265 neutrino_ = makeCandidate(mets, 0);
0266 else
0267 setNeutrino(mets, leps, 0, neutrinoSolutionType_);
0268 }