00001 #ifndef TtSemiLepKinFitProducer_h
00002 #define TtSemiLepKinFitProducer_h
00003
00004 #include "FWCore/Framework/interface/Event.h"
00005 #include "FWCore/Framework/interface/EDProducer.h"
00006 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00007
00008 #include "PhysicsTools/JetMCUtils/interface/combination.h"
00009 #include "AnalysisDataFormats/TopObjects/interface/TtSemiLepEvtPartons.h"
00010 #include "TopQuarkAnalysis/TopKinFitter/interface/TtSemiLepKinFitter.h"
00011
00012 template <typename LeptonCollection>
00013 class TtSemiLepKinFitProducer : public edm::EDProducer {
00014
00015 public:
00016
00017 explicit TtSemiLepKinFitProducer(const edm::ParameterSet&);
00018 ~TtSemiLepKinFitProducer();
00019
00020 private:
00021
00022 virtual void produce(edm::Event&, const edm::EventSetup&);
00023
00024
00025 TtSemiLepKinFitter::Param param(unsigned);
00026
00027 TtSemiLepKinFitter::Constraint constraint(unsigned);
00028
00029 std::vector<TtSemiLepKinFitter::Constraint> constraints(std::vector<unsigned>&);
00030
00031 bool doBTagging(bool& useBTag_, edm::Handle<std::vector<pat::Jet> >& jets, std::vector<int>& combi,
00032 std::string& bTagAlgo_, double& minBTagValueBJets_, double& maxBTagValueNonBJets_);
00033
00034 edm::InputTag jets_;
00035 edm::InputTag leps_;
00036 edm::InputTag mets_;
00037
00038 edm::InputTag match_;
00040 bool useOnlyMatch_;
00042 std::string bTagAlgo_;
00044 double minBTagValueBJet_;
00046 double maxBTagValueNonBJet_;
00048 bool useBTag_;
00050 int maxNJets_;
00052 int maxNComb_;
00053
00055 unsigned int maxNrIter_;
00057 double maxDeltaS_;
00059 double maxF_;
00060 unsigned int jetParam_;
00061 unsigned int lepParam_;
00062 unsigned int metParam_;
00063
00064 std::vector<unsigned> constraints_;
00065 double mW_;
00066 double mTop_;
00067
00068 TtSemiLepKinFitter* fitter;
00069
00070 struct KinFitResult {
00071 int Status;
00072 double Chi2;
00073 double Prob;
00074 pat::Particle HadB;
00075 pat::Particle HadP;
00076 pat::Particle HadQ;
00077 pat::Particle LepB;
00078 pat::Particle LepL;
00079 pat::Particle LepN;
00080 std::vector<int> JetCombi;
00081 bool operator< (const KinFitResult& rhs) { return Chi2 < rhs.Chi2; };
00082 };
00083 };
00084
00085 template<typename LeptonCollection>
00086 TtSemiLepKinFitProducer<LeptonCollection>::TtSemiLepKinFitProducer(const edm::ParameterSet& cfg):
00087 jets_ (cfg.getParameter<edm::InputTag>("jets")),
00088 leps_ (cfg.getParameter<edm::InputTag>("leps")),
00089 mets_ (cfg.getParameter<edm::InputTag>("mets")),
00090 match_ (cfg.getParameter<edm::InputTag>("match")),
00091 useOnlyMatch_ (cfg.getParameter<bool> ("useOnlyMatch" )),
00092 bTagAlgo_ (cfg.getParameter<std::string> ("bTagAlgo" )),
00093 minBTagValueBJet_ (cfg.getParameter<double> ("minBDiscBJets" )),
00094 maxBTagValueNonBJet_(cfg.getParameter<double> ("maxBDiscLightJets" )),
00095 useBTag_ (cfg.getParameter<bool> ("useBTagging" )),
00096 maxNJets_ (cfg.getParameter<int> ("maxNJets" )),
00097 maxNComb_ (cfg.getParameter<int> ("maxNComb" )),
00098 maxNrIter_ (cfg.getParameter<unsigned> ("maxNrIter" )),
00099 maxDeltaS_ (cfg.getParameter<double> ("maxDeltaS" )),
00100 maxF_ (cfg.getParameter<double> ("maxF" )),
00101 jetParam_ (cfg.getParameter<unsigned> ("jetParametrisation")),
00102 lepParam_ (cfg.getParameter<unsigned> ("lepParametrisation")),
00103 metParam_ (cfg.getParameter<unsigned> ("metParametrisation")),
00104 constraints_ (cfg.getParameter<std::vector<unsigned> >("constraints")),
00105 mW_ (cfg.getParameter<double> ("mW" )),
00106 mTop_ (cfg.getParameter<double> ("mTop" ))
00107 {
00108 fitter = new TtSemiLepKinFitter(param(jetParam_), param(lepParam_), param(metParam_), maxNrIter_, maxDeltaS_, maxF_,
00109 constraints(constraints_), mW_, mTop_);
00110
00111 produces< std::vector<pat::Particle> >("PartonsHadP");
00112 produces< std::vector<pat::Particle> >("PartonsHadQ");
00113 produces< std::vector<pat::Particle> >("PartonsHadB");
00114 produces< std::vector<pat::Particle> >("PartonsLepB");
00115 produces< std::vector<pat::Particle> >("Leptons");
00116 produces< std::vector<pat::Particle> >("Neutrinos");
00117
00118 produces< std::vector<std::vector<int> > >();
00119 produces< std::vector<double> >("Chi2");
00120 produces< std::vector<double> >("Prob");
00121 produces< std::vector<int> >("Status");
00122 }
00123
00124 template<typename LeptonCollection>
00125 TtSemiLepKinFitProducer<LeptonCollection>::~TtSemiLepKinFitProducer()
00126 {
00127 delete fitter;
00128 }
00129
00130 template<typename LeptonCollection>
00131 bool TtSemiLepKinFitProducer<LeptonCollection>::doBTagging(bool& useBTag_, edm::Handle<std::vector<pat::Jet> >& jets, std::vector<int>& combi,
00132 std::string& bTagAlgo_, double& minBTagValueBJet_, double& maxBTagValueNonBJet_){
00133
00134 if( !useBTag_ ) {
00135 return true;
00136 }
00137 if( useBTag_ &&
00138 (*jets)[combi[TtSemiLepEvtPartons::HadB ]].bDiscriminator(bTagAlgo_) >= minBTagValueBJet_ &&
00139 (*jets)[combi[TtSemiLepEvtPartons::LepB ]].bDiscriminator(bTagAlgo_) >= minBTagValueBJet_ &&
00140 (*jets)[combi[TtSemiLepEvtPartons::LightQ ]].bDiscriminator(bTagAlgo_) < maxBTagValueNonBJet_ &&
00141 (*jets)[combi[TtSemiLepEvtPartons::LightQBar]].bDiscriminator(bTagAlgo_) < maxBTagValueNonBJet_ ) {
00142 return true;
00143 }
00144 else{
00145 return false;
00146 }
00147 }
00148
00149 template<typename LeptonCollection>
00150 void TtSemiLepKinFitProducer<LeptonCollection>::produce(edm::Event& evt, const edm::EventSetup& setup)
00151 {
00152 std::auto_ptr< std::vector<pat::Particle> > pPartonsHadP( new std::vector<pat::Particle> );
00153 std::auto_ptr< std::vector<pat::Particle> > pPartonsHadQ( new std::vector<pat::Particle> );
00154 std::auto_ptr< std::vector<pat::Particle> > pPartonsHadB( new std::vector<pat::Particle> );
00155 std::auto_ptr< std::vector<pat::Particle> > pPartonsLepB( new std::vector<pat::Particle> );
00156 std::auto_ptr< std::vector<pat::Particle> > pLeptons ( new std::vector<pat::Particle> );
00157 std::auto_ptr< std::vector<pat::Particle> > pNeutrinos ( new std::vector<pat::Particle> );
00158
00159 std::auto_ptr< std::vector<std::vector<int> > > pCombi ( new std::vector<std::vector<int> > );
00160 std::auto_ptr< std::vector<double> > pChi2 ( new std::vector<double> );
00161 std::auto_ptr< std::vector<double> > pProb ( new std::vector<double> );
00162 std::auto_ptr< std::vector<int> > pStatus( new std::vector<int> );
00163
00164 edm::Handle<std::vector<pat::Jet> > jets;
00165 evt.getByLabel(jets_, jets);
00166
00167 edm::Handle<std::vector<pat::MET> > mets;
00168 evt.getByLabel(mets_, mets);
00169
00170 edm::Handle<LeptonCollection> leps;
00171 evt.getByLabel(leps_, leps);
00172
00173 unsigned int nPartons = 4;
00174
00175 std::vector<int> match;
00176 bool invalidMatch = false;
00177 if(useOnlyMatch_) {
00178 edm::Handle<std::vector<std::vector<int> > > matchHandle;
00179 evt.getByLabel(match_, matchHandle);
00180 match = *(matchHandle->begin());
00181
00182 if(match.size()!=nPartons) invalidMatch=true;
00183 else {
00184 for(unsigned int idx=0; idx<match.size(); ++idx) {
00185 if(match[idx]<0 || match[idx]>=(int)jets->size()) {
00186 invalidMatch=true;
00187 break;
00188 }
00189 }
00190 }
00191 }
00192
00193
00194
00195
00196
00197
00198 if( leps->empty() || mets->empty() || jets->size()<nPartons || invalidMatch ) {
00199
00200 pPartonsHadP->push_back( fitter->fittedHadP() );
00201 pPartonsHadQ->push_back( fitter->fittedHadQ() );
00202 pPartonsHadB->push_back( fitter->fittedHadB() );
00203 pPartonsLepB->push_back( fitter->fittedLepB() );
00204 pLeptons ->push_back( fitter->fittedLepton() );
00205 pNeutrinos ->push_back( fitter->fittedNeutrino() );
00206
00207 std::vector<int> invalidCombi;
00208 for(unsigned int i = 0; i < nPartons; ++i)
00209 invalidCombi.push_back( -1 );
00210 pCombi->push_back( invalidCombi );
00211
00212 pChi2->push_back( -1. );
00213
00214 pProb->push_back( -1. );
00215
00216 pStatus->push_back( -1 );
00217
00218 evt.put(pCombi);
00219 evt.put(pPartonsHadP, "PartonsHadP");
00220 evt.put(pPartonsHadQ, "PartonsHadQ");
00221 evt.put(pPartonsHadB, "PartonsHadB");
00222 evt.put(pPartonsLepB, "PartonsLepB");
00223 evt.put(pLeptons , "Leptons" );
00224 evt.put(pNeutrinos , "Neutrinos" );
00225 evt.put(pChi2 , "Chi2" );
00226 evt.put(pProb , "Prob" );
00227 evt.put(pStatus , "Status" );
00228 return;
00229 }
00230
00231
00232
00233
00234
00235
00236 std::vector<int> jetIndices;
00237 if(!useOnlyMatch_) {
00238 for(unsigned int i=0; i<jets->size(); ++i){
00239 if(maxNJets_ >= (int) nPartons && maxNJets_ == (int) i) break;
00240 jetIndices.push_back(i);
00241 }
00242 }
00243
00244 std::vector<int> combi;
00245 for(unsigned int i=0; i<nPartons; ++i) {
00246 if(useOnlyMatch_) combi.push_back( match[i] );
00247 else combi.push_back(i);
00248 }
00249
00250 std::list<KinFitResult> FitResultList;
00251
00252 do{
00253 for(int cnt = 0; cnt < TMath::Factorial( combi.size() ); ++cnt){
00254
00255
00256 if( (combi[TtSemiLepEvtPartons::LightQ] < combi[TtSemiLepEvtPartons::LightQBar]
00257 || useOnlyMatch_ ) && doBTagging(useBTag_, jets, combi, bTagAlgo_, minBTagValueBJet_, maxBTagValueNonBJet_) ){
00258
00259 std::vector<pat::Jet> jetCombi;
00260 jetCombi.resize(nPartons);
00261 jetCombi[TtSemiLepEvtPartons::LightQ ] = (*jets)[combi[TtSemiLepEvtPartons::LightQ ]];
00262 jetCombi[TtSemiLepEvtPartons::LightQBar] = (*jets)[combi[TtSemiLepEvtPartons::LightQBar]];
00263 jetCombi[TtSemiLepEvtPartons::HadB ] = (*jets)[combi[TtSemiLepEvtPartons::HadB ]];
00264 jetCombi[TtSemiLepEvtPartons::LepB ] = (*jets)[combi[TtSemiLepEvtPartons::LepB ]];
00265
00266
00267 int status = fitter->fit(jetCombi, (*leps)[0], (*mets)[0]);
00268
00269 if( status == 0 ) {
00270 KinFitResult result;
00271 result.Status = status;
00272 result.Chi2 = fitter->fitS();
00273 result.Prob = fitter->fitProb();
00274 result.HadB = fitter->fittedHadB();
00275 result.HadP = fitter->fittedHadP();
00276 result.HadQ = fitter->fittedHadQ();
00277 result.LepB = fitter->fittedLepB();
00278 result.LepL = fitter->fittedLepton();
00279 result.LepN = fitter->fittedNeutrino();
00280 result.JetCombi = combi;
00281
00282 FitResultList.push_back(result);
00283 }
00284
00285 }
00286 if(useOnlyMatch_) break;
00287 next_permutation( combi.begin(), combi.end() );
00288 }
00289 if(useOnlyMatch_) break;
00290 }
00291 while(stdcomb::next_combination( jetIndices.begin(), jetIndices.end(), combi.begin(), combi.end() ));
00292
00293
00294 FitResultList.sort();
00295
00296
00297
00298
00299
00300
00301 if( FitResultList.size() < 1 ) {
00302 pPartonsHadP->push_back( fitter->fittedHadP() );
00303 pPartonsHadQ->push_back( fitter->fittedHadQ() );
00304 pPartonsHadB->push_back( fitter->fittedHadB() );
00305 pPartonsLepB->push_back( fitter->fittedLepB() );
00306 pLeptons ->push_back( fitter->fittedLepton() );
00307 pNeutrinos ->push_back( fitter->fittedNeutrino() );
00308
00309 std::vector<int> invalidCombi;
00310 for(unsigned int i = 0; i < nPartons; ++i)
00311 invalidCombi.push_back( -1 );
00312 pCombi->push_back( invalidCombi );
00313
00314 pChi2->push_back( -1. );
00315
00316 pProb->push_back( -1. );
00317
00318 pStatus->push_back( -1 );
00319 }
00320 else {
00321 unsigned int iComb = 0;
00322 for(typename std::list<KinFitResult>::const_iterator result = FitResultList.begin(); result != FitResultList.end(); ++result) {
00323 if(maxNComb_ >= 1 && iComb == (unsigned int) maxNComb_) break;
00324 iComb++;
00325
00326 pPartonsHadP->push_back( result->HadP );
00327 pPartonsHadQ->push_back( result->HadQ );
00328 pPartonsHadB->push_back( result->HadB );
00329 pPartonsLepB->push_back( result->LepB );
00330
00331 pLeptons->push_back( result->LepL );
00332
00333 pNeutrinos->push_back( result->LepN );
00334
00335 pCombi->push_back( result->JetCombi );
00336
00337 pChi2->push_back( result->Chi2 );
00338
00339 pProb->push_back( result->Prob );
00340
00341 pStatus->push_back( result->Status );
00342 }
00343 }
00344 evt.put(pCombi);
00345 evt.put(pPartonsHadP, "PartonsHadP");
00346 evt.put(pPartonsHadQ, "PartonsHadQ");
00347 evt.put(pPartonsHadB, "PartonsHadB");
00348 evt.put(pPartonsLepB, "PartonsLepB");
00349 evt.put(pLeptons , "Leptons" );
00350 evt.put(pNeutrinos , "Neutrinos" );
00351 evt.put(pChi2 , "Chi2" );
00352 evt.put(pProb , "Prob" );
00353 evt.put(pStatus , "Status" );
00354 }
00355
00356 template<typename LeptonCollection>
00357 TtSemiLepKinFitter::Param TtSemiLepKinFitProducer<LeptonCollection>::param(unsigned val)
00358 {
00359 TtSemiLepKinFitter::Param result;
00360 switch(val){
00361 case TtSemiLepKinFitter::kEMom : result=TtSemiLepKinFitter::kEMom; break;
00362 case TtSemiLepKinFitter::kEtEtaPhi : result=TtSemiLepKinFitter::kEtEtaPhi; break;
00363 case TtSemiLepKinFitter::kEtThetaPhi : result=TtSemiLepKinFitter::kEtThetaPhi; break;
00364 default:
00365 throw cms::Exception("WrongConfig")
00366 << "Chosen jet parametrization is not supported: " << val << "\n";
00367 break;
00368 }
00369 return result;
00370 }
00371
00372 template<typename LeptonCollection>
00373 TtSemiLepKinFitter::Constraint TtSemiLepKinFitProducer<LeptonCollection>::constraint(unsigned val)
00374 {
00375 TtSemiLepKinFitter::Constraint result;
00376 switch(val){
00377 case TtSemiLepKinFitter::kWHadMass : result=TtSemiLepKinFitter::kWHadMass; break;
00378 case TtSemiLepKinFitter::kWLepMass : result=TtSemiLepKinFitter::kWLepMass; break;
00379 case TtSemiLepKinFitter::kTopHadMass : result=TtSemiLepKinFitter::kTopHadMass; break;
00380 case TtSemiLepKinFitter::kTopLepMass : result=TtSemiLepKinFitter::kTopLepMass; break;
00381 case TtSemiLepKinFitter::kNeutrinoMass : result=TtSemiLepKinFitter::kNeutrinoMass; break;
00382 case TtSemiLepKinFitter::kEqualTopMasses : result=TtSemiLepKinFitter::kEqualTopMasses; break;
00383 default:
00384 throw cms::Exception("WrongConfig")
00385 << "Chosen fit constraint is not supported: " << val << "\n";
00386 break;
00387 }
00388 return result;
00389 }
00390
00391 template<typename LeptonCollection>
00392 std::vector<TtSemiLepKinFitter::Constraint> TtSemiLepKinFitProducer<LeptonCollection>::constraints(std::vector<unsigned>& val)
00393 {
00394 std::vector<TtSemiLepKinFitter::Constraint> result;
00395 for(unsigned i=0; i<val.size(); ++i){
00396 result.push_back(constraint(val[i]));
00397 }
00398 return result;
00399 }
00400
00401 #endif