CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_6_1_2_SLHC4_patch1/src/RecoTauTag/RecoTau/plugins/RecoTauPiZeroStripPlugin2.cc

Go to the documentation of this file.
00001 /*
00002  * RecoTauPiZeroStripPlugin2
00003  *
00004  * Merges PFGammas in a PFJet into Candidate piZeros defined as
00005  * strips in eta-phi.
00006  *
00007  * Author: Michail Bachtis (University of Wisconsin)
00008  *
00009  * Code modifications: Evan Friis (UC Davis),
00010  *                     Christian Veelken (LLR)
00011  *
00012  * $Id $
00013  */
00014 #include <algorithm>
00015 #include <memory>
00016 
00017 #include "RecoTauTag/RecoTau/interface/RecoTauPiZeroPlugins.h"
00018 
00019 #include "DataFormats/ParticleFlowCandidate/interface/PFCandidateFwd.h"
00020 #include "DataFormats/ParticleFlowCandidate/interface/PFCandidate.h"
00021 #include "DataFormats/VertexReco/interface/Vertex.h"
00022 #include "DataFormats/VertexReco/interface/VertexFwd.h"
00023 #include "DataFormats/TauReco/interface/RecoTauPiZero.h"
00024 #include "DataFormats/JetReco/interface/PFJet.h"
00025 #include "CommonTools/CandUtils/interface/AddFourMomenta.h"
00026 #include "DataFormats/Math/interface/deltaPhi.h"
00027 
00028 #include "RecoTauTag/RecoTau/interface/RecoTauCommonUtilities.h"
00029 #include "RecoTauTag/RecoTau/interface/RecoTauQualityCuts.h"
00030 #include "RecoTauTag/RecoTau/interface/RecoTauVertexAssociator.h"
00031 #include "RecoTauTag/RecoTau/interface/CombinatoricGenerator.h"
00032 
00033 //-------------------------------------------------------------------------------
00034 // CV: the following headers are needed only for debug print-out
00035 #include "DataFormats/GsfTrackReco/interface/GsfTrack.h"
00036 #include "DataFormats/TrackReco/interface/Track.h"
00037 //-------------------------------------------------------------------------------
00038 
00039 namespace reco { namespace tau {
00040 
00041 namespace {
00042   // Apply a hypothesis on the mass of the strips.
00043   math::XYZTLorentzVector applyMassConstraint(
00044       const math::XYZTLorentzVector& vec,double mass) {
00045     double factor = sqrt(vec.energy()*vec.energy()-mass*mass)/vec.P();
00046     return math::XYZTLorentzVector(
00047         vec.px()*factor,vec.py()*factor,vec.pz()*factor,vec.energy());
00048   }
00049 }
00050 
00051 class RecoTauPiZeroStripPlugin2 : public RecoTauPiZeroBuilderPlugin 
00052 {
00053  public:
00054   explicit RecoTauPiZeroStripPlugin2(const edm::ParameterSet&);
00055   virtual ~RecoTauPiZeroStripPlugin2();
00056   // Return type is auto_ptr<PiZeroVector>
00057   return_type operator()(const reco::PFJet&) const;
00058   // Hook to update PV information
00059   virtual void beginEvent();
00060   
00061  private:
00062   typedef std::vector<reco::PFCandidatePtr> PFCandPtrs;
00063   void addCandsToStrip(RecoTauPiZero&, PFCandPtrs&, const std::vector<bool>&, std::set<size_t>&, bool&) const;
00064 
00065   RecoTauVertexAssociator vertexAssociator_;
00066 
00067   RecoTauQualityCuts* qcuts_;
00068   bool applyElecTrackQcuts_;
00069   double minGammaEtStripSeed_;
00070   double minGammaEtStripAdd_;
00071 
00072   double minStripEt_;
00073 
00074   std::vector<int> inputPdgIds_;  // type of candidates to clusterize
00075   double etaAssociationDistance_; // size of strip clustering window in eta direction
00076   double phiAssociationDistance_; // size of strip clustering window in phi direction
00077 
00078   bool updateStripAfterEachDaughter_;
00079   int maxStripBuildIterations_;
00080 
00081   // Parameters for build strip combinations
00082   bool combineStrips_;
00083   int maxStrips_;
00084   double combinatoricStripMassHypo_;
00085 
00086   AddFourMomenta p4Builder_;
00087 };
00088 
00089 RecoTauPiZeroStripPlugin2::RecoTauPiZeroStripPlugin2(const edm::ParameterSet& pset)
00090   : RecoTauPiZeroBuilderPlugin(pset),
00091     vertexAssociator_(pset.getParameter<edm::ParameterSet>("qualityCuts")),
00092     qcuts_(0)
00093 {
00094   LogTrace("RecoTauPiZeroStripPlugin2") << "<RecoTauPiZeroStripPlugin2::RecoTauPiZeroStripPlugin2>:" ;
00095 
00096   minGammaEtStripSeed_ = pset.getParameter<double>("minGammaEtStripSeed");
00097   LogTrace("RecoTauPiZeroStripPlugin2") << " minGammaEtStripSeed = " << minGammaEtStripSeed_ ;
00098   minGammaEtStripAdd_ = pset.getParameter<double>("minGammaEtStripAdd");
00099   LogTrace("RecoTauPiZeroStripPlugin2") << " minGammaEtStripAdd = " << minGammaEtStripAdd_ ;
00100 
00101   minStripEt_ = pset.getParameter<double>("minStripEt");
00102   LogTrace("RecoTauPiZeroStripPlugin2") << " minStripEt = " << minStripEt_ ;
00103   
00104   edm::ParameterSet qcuts_pset = pset.getParameterSet("qualityCuts").getParameterSet("signalQualityCuts");
00105 //-------------------------------------------------------------------------------
00106 // CV: disable track quality cuts for PFElectronsPFElectron
00107 //       (treat PFElectrons like PFGammas for the purpose of building eta-phi strips)
00108   applyElecTrackQcuts_ = pset.getParameter<bool>("applyElecTrackQcuts");
00109   if ( !applyElecTrackQcuts_ ) {
00110     qcuts_pset.addParameter<double>("minTrackPt", std::min(minGammaEtStripSeed_, minGammaEtStripAdd_));
00111     qcuts_pset.addParameter<double>("maxTrackChi2", 1.e+9);
00112     qcuts_pset.addParameter<double>("maxTransverseImpactParameter", 1.e+9);
00113     qcuts_pset.addParameter<double>("maxDeltaZ", 1.);
00114     qcuts_pset.addParameter<double>("minTrackVertexWeight", -1.);
00115     qcuts_pset.addParameter<unsigned>("minTrackPixelHits", 0);
00116     qcuts_pset.addParameter<unsigned>("minTrackHits", 0);
00117   }
00118 //-------------------------------------------------------------------------------
00119   qcuts_pset.addParameter<double>("minGammaEt", std::min(minGammaEtStripSeed_, minGammaEtStripAdd_));
00120   qcuts_ = new RecoTauQualityCuts(qcuts_pset);
00121 
00122   inputPdgIds_ = pset.getParameter<std::vector<int> >("stripCandidatesParticleIds");
00123   etaAssociationDistance_ = pset.getParameter<double>("stripEtaAssociationDistance");
00124   phiAssociationDistance_ = pset.getParameter<double>("stripPhiAssociationDistance");
00125 
00126   updateStripAfterEachDaughter_ = pset.getParameter<bool>("updateStripAfterEachDaughter");
00127   maxStripBuildIterations_ = pset.getParameter<int>("maxStripBuildIterations");
00128 
00129   combineStrips_ = pset.getParameter<bool>("makeCombinatoricStrips");
00130   if ( combineStrips_ ) {
00131     maxStrips_ = pset.getParameter<int>("maxInputStrips");
00132     combinatoricStripMassHypo_ = pset.getParameter<double>("stripMassWhenCombining");
00133   }
00134 }
00135   
00136 RecoTauPiZeroStripPlugin2::~RecoTauPiZeroStripPlugin2()
00137 {
00138   delete qcuts_;
00139 }
00140 
00141 // Update the primary vertex
00142 void RecoTauPiZeroStripPlugin2::beginEvent() 
00143 {
00144   vertexAssociator_.setEvent(*evt());
00145 }
00146 
00147 void RecoTauPiZeroStripPlugin2::addCandsToStrip(RecoTauPiZero& strip, PFCandPtrs& cands, const std::vector<bool>& candFlags, 
00148                                                 std::set<size_t>& candIdsCurrentStrip, bool& isCandAdded) const
00149 {
00150   size_t numCands = cands.size();
00151   for ( size_t candId = 0; candId < numCands; ++candId ) {
00152     if ( (!candFlags[candId]) && candIdsCurrentStrip.find(candId) == candIdsCurrentStrip.end() ) { // do not include same cand twice
00153       reco::PFCandidatePtr cand = cands[candId];
00154       if ( fabs(strip.eta() - cand->eta()) < etaAssociationDistance_ && // check if cand is within eta-phi window centered on strip 
00155            fabs(strip.phi() - cand->phi()) < phiAssociationDistance_ ) {
00156         LogTrace("RecoTauPiZeroStripPlugin2") << "--> candId = " << candId << " has been added." ;
00157         strip.addDaughter(cand);
00158         if ( updateStripAfterEachDaughter_ ) p4Builder_.set(strip);
00159         isCandAdded = true;
00160         candIdsCurrentStrip.insert(candId);
00161       }
00162     }
00163   }
00164 }
00165 
00166 void markCandsInStrip(std::vector<bool>& candFlags, const std::set<size_t>& candIds)
00167 {
00168   for ( std::set<size_t>::const_iterator candId = candIds.begin();
00169         candId != candIds.end(); ++candId ) {
00170     candFlags[*candId] = true;
00171   }
00172 }
00173 
00174 namespace {
00175   const reco::TrackBaseRef getTrack(const PFCandidate& cand) 
00176   {
00177     if      ( cand.trackRef().isNonnull()    ) return reco::TrackBaseRef(cand.trackRef());
00178     else if ( cand.gsfTrackRef().isNonnull() ) return reco::TrackBaseRef(cand.gsfTrackRef());
00179     else return reco::TrackBaseRef();
00180   }
00181 }
00182 
00183 RecoTauPiZeroStripPlugin2::return_type RecoTauPiZeroStripPlugin2::operator()(const reco::PFJet& jet) const 
00184 {
00185   PiZeroVector output;
00186 
00187   // Get the candidates passing our quality cuts
00188   qcuts_->setPV(vertexAssociator_.associatedVertex(jet));
00189   PFCandPtrs candsVector = qcuts_->filterRefs(pfCandidates(jet, inputPdgIds_));
00190 
00191   // Convert to stl::list to allow fast deletions
00192   PFCandPtrs seedCands;
00193   PFCandPtrs addCands;
00194   int idx = 0;
00195   for ( PFCandPtrs::iterator cand = candsVector.begin();
00196         cand != candsVector.end(); ++cand ) {
00197     LogTrace("RecoTauPiZeroStripPlugin2") << "PFGamma (" << idx << "): Et = " << (*cand)->et() << "," 
00198                 << " eta = " << (*cand)->eta() << ", phi = " << (*cand)->phi(); 
00199     if ( (*cand)->et() > minGammaEtStripSeed_ ) {
00200       LogTrace("RecoTauPiZeroStripPlugin2") << " --> assigning seedCandId = " << seedCands.size() ;
00201 #ifdef EDM_ML_DEBUG
00202         const reco::TrackBaseRef candTrack = getTrack(*cand);
00203         if ( candTrack.isNonnull() ) {
00204         LogTrace("RecoTauPiZeroStripPlugin2") << "has Track: pt = " << candTrack->pt() << " +/- " << candTrack->ptError() << "," 
00205                     << " eta = " << candTrack->eta() << ", phi = " << candTrack->phi() << ","
00206                     << " charge = " << candTrack->charge() ;
00207         LogTrace("RecoTauPiZeroStripPlugin2") << " chi2 = " << candTrack->normalizedChi2() ;
00208         LogTrace("RecoTauPiZeroStripPlugin2") << " dIP = " << std::abs(candTrack->dxy(vertexAssociator_.associatedVertex(jet)->position())) ;
00209         LogTrace("RecoTauPiZeroStripPlugin2") << " dZ = " << std::abs(candTrack->dz(vertexAssociator_.associatedVertex(jet)->position())) ;
00210         LogTrace("RecoTauPiZeroStripPlugin2") << " vtxAssocWeight = " << vertexAssociator_.associatedVertex(jet)->trackWeight(candTrack) ;
00211         LogTrace("RecoTauPiZeroStripPlugin2") << " numPxlHits = " << candTrack->hitPattern().numberOfValidPixelHits() ;
00212         LogTrace("RecoTauPiZeroStripPlugin2") << " numTrkHits = " << candTrack->hitPattern().numberOfValidHits() ;
00213         }
00214 #endif
00215       LogTrace("RecoTauPiZeroStripPlugin2") << "ECAL Et: calibrated = " << (*cand)->ecalEnergy()*sin((*cand)->theta()) << "," 
00216           << " raw = " << (*cand)->rawEcalEnergy()*sin((*cand)->theta()) ;
00217       LogTrace("RecoTauPiZeroStripPlugin2") << "HCAL Et: calibrated = " << (*cand)->hcalEnergy()*sin((*cand)->theta()) << "," 
00218           << " raw = " << (*cand)->rawHcalEnergy()*sin((*cand)->theta()) ;
00219       seedCands.push_back(*cand);
00220     } else if ( (*cand)->et() > minGammaEtStripAdd_  ) {
00221       LogTrace("RecoTauPiZeroStripPlugin2") << " --> assigning addCandId = " << addCands.size();
00222       addCands.push_back(*cand);
00223     }
00224     LogTrace("RecoTauPiZeroStripPlugin2") ;
00225     ++idx;
00226   }
00227 
00228   std::vector<bool> seedCandFlags(seedCands.size()); // true/false: seedCand is already/not yet included in strip
00229   std::vector<bool> addCandFlags(addCands.size());   // true/false: addCand  is already/not yet included in strip
00230 
00231   std::set<size_t> seedCandIdsCurrentStrip;
00232   std::set<size_t> addCandIdsCurrentStrip;
00233 
00234   size_t idxSeed = 0;
00235   while ( idxSeed < seedCands.size() ) {
00236     LogTrace("RecoTauPiZeroStripPlugin2") << "idxSeed = " << idxSeed ;
00237 
00238     seedCandIdsCurrentStrip.clear();
00239     addCandIdsCurrentStrip.clear();
00240 
00241     std::auto_ptr<RecoTauPiZero> strip(new RecoTauPiZero(*seedCands[idxSeed], RecoTauPiZero::kStrips));
00242     strip->addDaughter(seedCands[idxSeed]);
00243     seedCandIdsCurrentStrip.insert(idxSeed);
00244 
00245     bool isCandAdded;
00246     int stripBuildIteration = 0;
00247     do {
00248       isCandAdded = false;
00249 
00250       LogTrace("RecoTauPiZeroStripPlugin2") << " adding seedCands to strip..." ;
00251       addCandsToStrip(*strip, seedCands, seedCandFlags, seedCandIdsCurrentStrip, isCandAdded);
00252       LogTrace("RecoTauPiZeroStripPlugin2") << " adding addCands to strip..." ;
00253       addCandsToStrip(*strip, addCands,  addCandFlags,  addCandIdsCurrentStrip, isCandAdded);
00254 
00255       if ( !updateStripAfterEachDaughter_ ) p4Builder_.set(*strip);
00256 
00257       ++stripBuildIteration;
00258     } while ( isCandAdded && (stripBuildIteration < maxStripBuildIterations_ || maxStripBuildIterations_ == -1) );
00259 
00260     if ( strip->et() > minStripEt_ ) { // strip passed Et cuts, add it to the event
00261       LogTrace("RecoTauPiZeroStripPlugin2") << "Strip: Et = " << strip->et() << "," 
00262           << " eta = " << strip->eta() << ", phi = " << strip->phi() 
00263           << " --> building it !!" ;
00264 
00265       // Update the vertex
00266       if ( strip->daughterPtr(0).isNonnull() ) strip->setVertex(strip->daughterPtr(0)->vertex());
00267       output.push_back(strip);
00268 
00269       // Mark daughters as being part of this strip
00270       markCandsInStrip(seedCandFlags, seedCandIdsCurrentStrip);
00271       markCandsInStrip(addCandFlags,  addCandIdsCurrentStrip);
00272     } else { // strip failed Et cuts, just skip it
00273       LogTrace("RecoTauPiZeroStripPlugin2") << "Strip: Et = " << strip->et() << "," 
00274           << " eta = " << strip->eta() << ", phi = " << strip->phi() 
00275           << " --> discarding it !!" ;
00276     }
00277 
00278     ++idxSeed;
00279     while ( idxSeed < seedCands.size() && seedCandFlags[idxSeed] ) {
00280       ++idxSeed; // fast-forward to next seed cand not yet included in any strip
00281     }
00282   }
00283 
00284   // Check if we want to combine our strips
00285   if ( combineStrips_ && output.size() > 1 ) {
00286     PiZeroVector stripCombinations;
00287     // Sort the output by descending pt
00288     output.sort(output.begin(), output.end(),
00289         boost::bind(&RecoTauPiZero::pt, _1) >
00290         boost::bind(&RecoTauPiZero::pt, _2));
00291     // Get the end of interesting set of strips to try and combine
00292     PiZeroVector::const_iterator end_iter = takeNElements(
00293         output.begin(), output.end(), maxStrips_);
00294 
00295     // Look at all the combinations
00296     for ( PiZeroVector::const_iterator first = output.begin();
00297           first != end_iter-1; ++first ) {
00298       for ( PiZeroVector::const_iterator second = first+1;
00299             second != end_iter; ++second ) {
00300         Candidate::LorentzVector firstP4 = first->p4();
00301         Candidate::LorentzVector secondP4 = second->p4();
00302         // If we assume a certain mass for each strip apply it here.
00303         firstP4 = applyMassConstraint(firstP4, combinatoricStripMassHypo_);
00304         secondP4 = applyMassConstraint(secondP4, combinatoricStripMassHypo_);
00305         Candidate::LorentzVector totalP4 = firstP4 + secondP4;
00306         // Make our new combined strip
00307         std::auto_ptr<RecoTauPiZero> combinedStrips(
00308             new RecoTauPiZero(0, totalP4,
00309               Candidate::Point(0, 0, 0),
00310               //111, 10001, true, RecoTauPiZero::kCombinatoricStrips));
00311               111, 10001, true, RecoTauPiZero::kUndefined));
00312 
00313         // Now loop over the strip members
00314         BOOST_FOREACH(const RecoTauPiZero::daughters::value_type& gamma,
00315             first->daughterPtrVector()) {
00316           combinedStrips->addDaughter(gamma);
00317         }
00318         BOOST_FOREACH(const RecoTauPiZero::daughters::value_type& gamma,
00319             second->daughterPtrVector()) {
00320           combinedStrips->addDaughter(gamma);
00321         }
00322         // Update the vertex
00323         if ( combinedStrips->daughterPtr(0).isNonnull() )
00324           combinedStrips->setVertex(combinedStrips->daughterPtr(0)->vertex());
00325         // Add to our collection of combined strips
00326         stripCombinations.push_back(combinedStrips);
00327       }
00328     }
00329     // When done doing all the combinations, add the combined strips to the
00330     // output.
00331     output.transfer(output.end(), stripCombinations);
00332   }
00333 
00334   return output.release();
00335 }
00336 }} // end namespace reco::tau
00337 
00338 #include "FWCore/Framework/interface/MakerMacros.h"
00339 DEFINE_EDM_PLUGIN(RecoTauPiZeroBuilderPluginFactory,
00340     reco::tau::RecoTauPiZeroStripPlugin2, "RecoTauPiZeroStripPlugin2");