00001 #include "CommonTools/CandUtils/interface/AddFourMomenta.h"
00002 #include "AnalysisDataFormats/TopObjects/interface/TtSemiLepEvtPartons.h"
00003 #include "DataFormats/PatCandidates/interface/Electron.h"
00004 #include "DataFormats/PatCandidates/interface/Muon.h"
00005 #include "TopQuarkAnalysis/TopTools/interface/MEzCalculator.h"
00006
00007 #include "TopQuarkAnalysis/TopJetCombination/interface/TtSemiLepHypothesis.h"
00008
00010 TtSemiLepHypothesis::TtSemiLepHypothesis(const edm::ParameterSet& cfg):
00011 jets_(cfg.getParameter<edm::InputTag>("jets")),
00012 leps_(cfg.getParameter<edm::InputTag>("leps")),
00013 mets_(cfg.getParameter<edm::InputTag>("mets")),
00014 nJetsConsidered_(cfg.getParameter<edm::InputTag>("nJetsConsidered")),
00015 numberOfRealNeutrinoSolutions_(-1),
00016 lightQ_(0), lightQBar_(0), hadronicB_(0),
00017 leptonicB_(0), neutrino_(0), lepton_(0)
00018 {
00019 getMatch_ = false;
00020 if( cfg.exists("match") ) {
00021 getMatch_ = true;
00022 match_ = cfg.getParameter<edm::InputTag>("match");
00023 }
00024 if( cfg.exists("neutrinoSolutionType") )
00025 neutrinoSolutionType_ = cfg.getParameter<int>("neutrinoSolutionType");
00026 else
00027 neutrinoSolutionType_ = -1;
00028 if( cfg.exists("jetCorrectionLevel") ) {
00029 jetCorrectionLevel_ = cfg.getParameter<std::string>("jetCorrectionLevel");
00030 }
00031 produces<std::vector<std::pair<reco::CompositeCandidate, std::vector<int> > > >();
00032 produces<int>("Key");
00033 produces<int>("NumberOfRealNeutrinoSolutions");
00034 produces<int>("NumberOfConsideredJets");
00035 }
00036
00038 TtSemiLepHypothesis::~TtSemiLepHypothesis()
00039 {
00040 if( lightQ_ ) delete lightQ_;
00041 if( lightQBar_ ) delete lightQBar_;
00042 if( hadronicB_ ) delete hadronicB_;
00043 if( leptonicB_ ) delete leptonicB_;
00044 if( neutrino_ ) delete neutrino_;
00045 if( lepton_ ) delete lepton_;
00046 }
00047
00049 void
00050 TtSemiLepHypothesis::produce(edm::Event& evt, const edm::EventSetup& setup)
00051 {
00052 edm::Handle<std::vector<pat::Jet> > jets;
00053 evt.getByLabel(jets_, jets);
00054
00055 edm::Handle<edm::View<reco::RecoCandidate> > leps;
00056 evt.getByLabel(leps_, leps);
00057
00058 edm::Handle<std::vector<pat::MET> > mets;
00059 evt.getByLabel(mets_, mets);
00060
00061 edm::Handle<int> nJetsConsidered;
00062 evt.getByLabel(nJetsConsidered_, nJetsConsidered);
00063
00064 std::vector<std::vector<int> > matchVec;
00065 if( getMatch_ ) {
00066 edm::Handle<std::vector<std::vector<int> > > matchHandle;
00067 evt.getByLabel(match_, matchHandle);
00068 matchVec = *matchHandle;
00069 }
00070 else {
00071 std::vector<int> dummyMatch;
00072 for(unsigned int i = 0; i < 4; ++i)
00073 dummyMatch.push_back( -1 );
00074 matchVec.push_back( dummyMatch );
00075 }
00076
00077
00078 std::auto_ptr<std::vector<std::pair<reco::CompositeCandidate, std::vector<int> > > >
00079 pOut( new std::vector<std::pair<reco::CompositeCandidate, std::vector<int> > > );
00080 std::auto_ptr<int> pKey(new int);
00081 std::auto_ptr<int> pNeutrinoSolutions(new int);
00082 std::auto_ptr<int> pJetsConsidered(new int);
00083
00084
00085 unsigned int idMatch = 0;
00086 typedef std::vector<std::vector<int> >::iterator MatchVecIterator;
00087 for(MatchVecIterator match = matchVec.begin(); match != matchVec.end(); ++match) {
00088
00089 resetCandidates();
00090
00091 buildHypo(evt, leps, mets, jets, *match, idMatch++);
00092 pOut->push_back( std::make_pair(hypo(), *match) );
00093 }
00094
00095 evt.put(pOut);
00096
00097
00098 buildKey();
00099 *pKey=key();
00100 evt.put(pKey, "Key");
00101
00102
00103 *pNeutrinoSolutions=numberOfRealNeutrinoSolutions_;
00104 evt.put(pNeutrinoSolutions, "NumberOfRealNeutrinoSolutions");
00105
00106
00107 *pJetsConsidered=*nJetsConsidered;
00108 evt.put(pJetsConsidered, "NumberOfConsideredJets");
00109 }
00110
00112 void
00113 TtSemiLepHypothesis::resetCandidates()
00114 {
00115 numberOfRealNeutrinoSolutions_ = -1;
00116 lightQ_ = 0;
00117 lightQBar_ = 0;
00118 hadronicB_ = 0;
00119 leptonicB_ = 0;
00120 neutrino_ = 0;
00121 lepton_ = 0;
00122 }
00123
00125 reco::CompositeCandidate
00126 TtSemiLepHypothesis::hypo()
00127 {
00128
00129 if( !lightQ_ || !lightQBar_ || !hadronicB_ ||
00130 !leptonicB_ || !neutrino_ || !lepton_ )
00131 return reco::CompositeCandidate();
00132
00133
00134 reco::CompositeCandidate hyp, hadTop, hadW, lepTop, lepW;
00135
00136 AddFourMomenta addFourMomenta;
00137
00138 lepW .addDaughter(*lepton_, TtSemiLepDaughter::Lep );
00139 lepW .addDaughter(*neutrino_, TtSemiLepDaughter::Nu );
00140 addFourMomenta.set( lepW );
00141 lepTop.addDaughter( lepW, TtSemiLepDaughter::LepW );
00142 lepTop.addDaughter(*leptonicB_,TtSemiLepDaughter::LepB );
00143 addFourMomenta.set( lepTop );
00144
00145
00146 hadW .addDaughter(*lightQ_, TtSemiLepDaughter::HadP );
00147 hadW .addDaughter(*lightQBar_,TtSemiLepDaughter::HadQ );
00148 addFourMomenta.set( hadW );
00149 hadTop.addDaughter( hadW, TtSemiLepDaughter::HadW );
00150 hadTop.addDaughter(*hadronicB_,TtSemiLepDaughter::HadB );
00151 addFourMomenta.set( hadTop );
00152
00153
00154 hyp.addDaughter( lepTop, TtSemiLepDaughter::LepTop );
00155 hyp.addDaughter( hadTop, TtSemiLepDaughter::HadTop );
00156 addFourMomenta.set( hyp );
00157
00158 return hyp;
00159 }
00160
00162 WDecay::LeptonType
00163 TtSemiLepHypothesis::leptonType(const reco::RecoCandidate* cand)
00164 {
00165
00166 WDecay::LeptonType type = WDecay::kNone;
00167 if( dynamic_cast<const reco::Muon*>(cand) ){
00168 type = WDecay::kMuon;
00169 }
00170 else if( dynamic_cast<const reco::GsfElectron*>(cand) ){
00171 type = WDecay::kElec;
00172 }
00173 return type;
00174 }
00175
00177 std::string
00178 TtSemiLepHypothesis::jetCorrectionLevel(const std::string& quarkType)
00179 {
00180
00181 if(jetCorrectionLevel_.empty())
00182 throw cms::Exception("Configuration")
00183 << "Unconfigured jetCorrectionLevel. Please use an appropriate, non-empty string.\n";
00184
00185
00186 if( !(quarkType=="wQuarkMix" ||
00187 quarkType=="udsQuark" ||
00188 quarkType=="cQuark" ||
00189 quarkType=="bQuark") )
00190 throw cms::Exception("Configuration")
00191 << quarkType << " is unknown as a quarkType for the jetCorrectionLevel.\n";
00192
00193
00194
00195
00196
00197 std::string level=jetCorrectionLevel_+":";
00198 if( level=="L5Flavor:" || level=="L6UE:" || level=="L7Parton:" ){
00199 if(quarkType=="wQuarkMix"){level+="wMix";}
00200 if(quarkType=="udsQuark" ){level+="uds";}
00201 if(quarkType=="cQuark" ){level+="charm";}
00202 if(quarkType=="bQuark" ){level+="bottom";}
00203 }
00204 else{
00205 level+="none";
00206 }
00207 return level;
00208 }
00209
00211 void
00212 TtSemiLepHypothesis::setCandidate(const edm::Handle<std::vector<pat::Jet> >& handle, const int& idx,
00213 reco::ShallowClonePtrCandidate*& clone, const std::string& correctionLevel)
00214 {
00215 edm::Ptr<pat::Jet> ptr = edm::Ptr<pat::Jet>(handle, idx);
00216
00217
00218 std::string step = correctionLevel.substr(0,correctionLevel.find(":"));
00219 std::string flavor = correctionLevel.substr(1+correctionLevel.find(":"));
00220 float corrFactor = 1.;
00221 if(flavor=="wMix")
00222 corrFactor = 0.75*ptr->jecFactor(step, "uds") + 0.25*ptr->jecFactor(step, "charm");
00223 else
00224 corrFactor = ptr->jecFactor(step, flavor);
00225 clone = new reco::ShallowClonePtrCandidate( ptr, ptr->charge(), ptr->p4()*corrFactor, ptr->vertex() );
00226 }
00227
00229 void TtSemiLepHypothesis::setNeutrino(const edm::Handle<std::vector<pat::MET> >& met,
00230 const edm::Handle<edm::View<reco::RecoCandidate> >& leps, const int& idx, const int& type)
00231 {
00232 edm::Ptr<pat::MET> ptr = edm::Ptr<pat::MET>(met, 0);
00233 MEzCalculator mez;
00234 mez.SetMET( *(met->begin()) );
00235 if( leptonType( &(leps->front()) ) == WDecay::kMuon )
00236 mez.SetLepton( (*leps)[idx], true );
00237 else if( leptonType( &(leps->front()) ) == WDecay::kElec )
00238 mez.SetLepton( (*leps)[idx], false );
00239 else
00240 throw cms::Exception("UnimplementedFeature") << "Type of lepton given together with MET for solving neutrino kinematics is neither muon nor electron.\n";
00241 double pz = mez.Calculate(type);
00242 numberOfRealNeutrinoSolutions_ = mez.IsComplex() ? 0 : 2;
00243 const math::XYZTLorentzVector p4( ptr->px(), ptr->py(), pz, sqrt(ptr->px()*ptr->px() + ptr->py()*ptr->py() + pz*pz) );
00244 neutrino_ = new reco::ShallowClonePtrCandidate( ptr, ptr->charge(), p4, ptr->vertex() );
00245 }
00246
00248 void
00249 TtSemiLepHypothesis::buildHypo(const edm::Handle<edm::View<reco::RecoCandidate> >& leps,
00250 const edm::Handle<std::vector<pat::MET> >& mets,
00251 const edm::Handle<std::vector<pat::Jet> >& jets,
00252 std::vector<int>& match)
00253 {
00254
00255
00256
00257 for(unsigned idx=0; idx<match.size(); ++idx){
00258 if( isValid(match[idx], jets) ){
00259 switch(idx){
00260 case TtSemiLepEvtPartons::LightQ:
00261 setCandidate(jets, match[idx], lightQ_, jetCorrectionLevel("wQuarkMix")); break;
00262 case TtSemiLepEvtPartons::LightQBar:
00263 setCandidate(jets, match[idx], lightQBar_, jetCorrectionLevel("wQuarkMix")); break;
00264 case TtSemiLepEvtPartons::HadB:
00265 setCandidate(jets, match[idx], hadronicB_, jetCorrectionLevel("bQuark")); break;
00266 case TtSemiLepEvtPartons::LepB:
00267 setCandidate(jets, match[idx], leptonicB_, jetCorrectionLevel("bQuark")); break;
00268 }
00269 }
00270 }
00271
00272
00273
00274
00275 if( leps->empty() )
00276 return;
00277 setCandidate(leps, 0, lepton_);
00278 match.push_back( 0 );
00279
00280
00281
00282
00283 if( mets->empty() )
00284 return;
00285 if(neutrinoSolutionType_ == -1)
00286 setCandidate(mets, 0, neutrino_);
00287 else
00288 setNeutrino(mets, leps, 0, neutrinoSolutionType_);
00289 }
00290