CMS 3D CMS Logo

PFRecoTauChargedHadronFromPFCandidatePlugin.cc
Go to the documentation of this file.
1 /*
2  * PFRecoTauChargedHadronFromPFCandidatePlugin
3  *
4  * Build PFRecoTauChargedHadron objects
5  * using charged PFCandidates and/or PFNeutralHadrons as input
6  *
7  * Author: Christian Veelken, LLR
8  *
9  */
10 
12 
27 
31 
36 
37 
38 #include <memory>
39 
40 namespace reco
41 {
42 
43 namespace tau
44 {
45 
47 {
48  public:
51  // Return type is auto_ptr<ChargedHadronVector>
52  return_type operator()(const reco::Jet&) const override;
53  // Hook to update PV information
54  void beginEvent() override;
55 
56  private:
57  typedef std::vector<reco::CandidatePtr> CandPtrs;
58 
60 
62 
63  std::vector<int> inputParticleIds_; // type of candidates to clusterize
64 
80 
81  double bField_;
82 
84 };
85 
88  vertexAssociator_(pset.getParameter<edm::ParameterSet>("qualityCuts"),std::move(iC)),
90 {
91  edm::ParameterSet qcuts_pset = pset.getParameterSet("qualityCuts").getParameterSet("signalQualityCuts");
92  qcuts_ = new RecoTauQualityCuts(qcuts_pset);
93 
94  inputParticleIds_ = pset.getParameter<std::vector<int> >("chargedHadronCandidatesParticleIds");
95 
96  dRmergeNeutralHadronWrtChargedHadron_ = pset.getParameter<double>("dRmergeNeutralHadronWrtChargedHadron");
97  dRmergeNeutralHadronWrtNeutralHadron_ = pset.getParameter<double>("dRmergeNeutralHadronWrtNeutralHadron");
98  dRmergeNeutralHadronWrtElectron_ = pset.getParameter<double>("dRmergeNeutralHadronWrtElectron");
99  dRmergeNeutralHadronWrtOther_ = pset.getParameter<double>("dRmergeNeutralHadronWrtOther");
100  minBlockElementMatchesNeutralHadron_ = pset.getParameter<int>("minBlockElementMatchesNeutralHadron");
101  maxUnmatchedBlockElementsNeutralHadron_ = pset.getParameter<int>("maxUnmatchedBlockElementsNeutralHadron");
102  dRmergePhotonWrtChargedHadron_ = pset.getParameter<double>("dRmergePhotonWrtChargedHadron");
103  dRmergePhotonWrtNeutralHadron_ = pset.getParameter<double>("dRmergePhotonWrtNeutralHadron");
104  dRmergePhotonWrtElectron_ = pset.getParameter<double>("dRmergePhotonWrtElectron");
105  dRmergePhotonWrtOther_ = pset.getParameter<double>("dRmergePhotonWrtOther");
106  minBlockElementMatchesPhoton_ = pset.getParameter<int>("minBlockElementMatchesPhoton");
107  maxUnmatchedBlockElementsPhoton_ = pset.getParameter<int>("maxUnmatchedBlockElementsPhoton");
108  minMergeNeutralHadronEt_ = pset.getParameter<double>("minMergeNeutralHadronEt");
109  minMergeGammaEt_ = pset.getParameter<double>("minMergeGammaEt");
110  minMergeChargedHadronPt_ = pset.getParameter<double>("minMergeChargedHadronPt");
111 
112  verbosity_ = pset.getParameter<int>("verbosity");
113 }
114 
116 {
117  delete qcuts_;
118 }
119 
120 // Update the primary vertex
122 {
124 
126  evtSetup()->get<IdealMagneticFieldRecord>().get(pSetup);
127  bField_ = pSetup->inTesla(GlobalPoint(0,0,0)).z();
128 }
129 
130 namespace
131 {
132  bool isMatchedByBlockElement(const reco::PFCandidate& pfCandidate1, const reco::PFCandidate& pfCandidate2, int minMatches1, int minMatches2, int maxUnmatchedBlockElements1plus2)
133  {
134  reco::PFCandidate::ElementsInBlocks blockElements1 = pfCandidate1.elementsInBlocks();
135  int numBlocks1 = blockElements1.size();
136  reco::PFCandidate::ElementsInBlocks blockElements2 = pfCandidate2.elementsInBlocks();
137  int numBlocks2 = blockElements2.size();
138  int numBlocks_matched = 0;
139  for ( reco::PFCandidate::ElementsInBlocks::const_iterator blockElement1 = blockElements1.begin();
140  blockElement1 != blockElements1.end(); ++blockElement1 ) {
141  bool isMatched = false;
142  for ( reco::PFCandidate::ElementsInBlocks::const_iterator blockElement2 = blockElements2.begin();
143  blockElement2 != blockElements2.end(); ++blockElement2 ) {
144  if ( blockElement1->first.id() == blockElement2->first.id() &&
145  blockElement1->first.key() == blockElement2->first.key() &&
146  blockElement1->second == blockElement2->second ) {
147  isMatched = true;
148  }
149  }
150  if ( isMatched ) ++numBlocks_matched;
151  }
152  assert(numBlocks_matched <= numBlocks1);
153  assert(numBlocks_matched <= numBlocks2);
154  if ( numBlocks_matched >= minMatches1 && numBlocks_matched >= minMatches2 &&
155  ((numBlocks1 - numBlocks_matched) + (numBlocks2 - numBlocks_matched)) <= maxUnmatchedBlockElements1plus2 ) {
156  return true;
157  } else {
158  return false;
159  }
160  }
161 }
162 
164 {
165  if ( verbosity_ ) {
166  edm::LogPrint("TauChHadronFromPF") << "<PFRecoTauChargedHadronFromPFCandidatePlugin::operator()>:";
167  edm::LogPrint("TauChHadronFromPF") << " pluginName = " << name() ;
168  }
169 
171 
172  // Get the candidates passing our quality cuts
175 
176  for ( CandPtrs::iterator cand = candsVector.begin();
177  cand != candsVector.end(); ++cand ) {
178  if ( verbosity_ ) {
179  edm::LogPrint("TauChHadronFromPF") << "processing PFCandidate: Pt = " << (*cand)->pt() << ", eta = " << (*cand)->eta() << ", phi = " << (*cand)->phi()
180  << " (pdgId = " << (*cand)->pdgId() << ", charge = " << (*cand)->charge() << ")" ;
181  }
182 
184  if ( std::abs((*cand)->charge()) > 0.5 ) algo = PFRecoTauChargedHadron::kChargedPFCandidate;
186  std::auto_ptr<PFRecoTauChargedHadron> chargedHadron(new PFRecoTauChargedHadron(**cand, algo));
187 
188  const reco::PFCandidate* pfCand = dynamic_cast<const reco::PFCandidate*>(&**cand);
189  if (pfCand) {
190  if ( pfCand->trackRef().isNonnull() ) chargedHadron->track_ = edm::refToPtr(pfCand->trackRef());
191  else if ( pfCand->muonRef().isNonnull() && pfCand->muonRef()->innerTrack().isNonnull() ) chargedHadron->track_ = edm::refToPtr(pfCand->muonRef()->innerTrack());
192  else if ( pfCand->muonRef().isNonnull() && pfCand->muonRef()->globalTrack().isNonnull() ) chargedHadron->track_ = edm::refToPtr(pfCand->muonRef()->globalTrack());
193  else if ( pfCand->muonRef().isNonnull() && pfCand->muonRef()->outerTrack().isNonnull() ) chargedHadron->track_ = edm::refToPtr(pfCand->muonRef()->outerTrack());
194  else if ( pfCand->gsfTrackRef().isNonnull() ) chargedHadron->track_ = edm::refToPtr(pfCand->gsfTrackRef());
195  } // TauReco@MiniAOD: Tracks only available dynamically, so no possiblity to save ref here; checked by code downstream
196 
197  chargedHadron->positionAtECALEntrance_ = atECALEntrance(&**cand, bField_);
198  chargedHadron->chargedPFCandidate_ = (*cand);
199  chargedHadron->addDaughter(*cand);
200 
201  int pdgId = std::abs(chargedHadron->chargedPFCandidate_->pdgId());
202 
203  if ( chargedHadron->pt() > minMergeChargedHadronPt_ ) {
204  for (const auto& jetConstituent : jet.daughterPtrVector()) {
205  // CV: take care of not double-counting energy in case "charged" PFCandidate is in fact a PFNeutralHadron
206  if ( jetConstituent == chargedHadron->chargedPFCandidate_ ) continue;
207 
208  int jetConstituentPdgId = std::abs(jetConstituent->pdgId());
209  if ( !(jetConstituentPdgId == 130 || jetConstituentPdgId == 22) ) continue;
210 
211  double dR = deltaR(atECALEntrance(jetConstituent.get(), bField_), atECALEntrance(chargedHadron->chargedPFCandidate_.get(), bField_));
212  double dRmerge = -1.;
213  int minBlockElementMatches = 1000;
214  int maxUnmatchedBlockElements = 0;
215  double minMergeEt = 1.e+6;
216  if ( jetConstituentPdgId == 130 ) {
217  if ( pdgId == 211 ) dRmerge = dRmergeNeutralHadronWrtChargedHadron_;
218  else if ( pdgId == 130 ) dRmerge = dRmergeNeutralHadronWrtNeutralHadron_;
219  else if ( pdgId == 11 ) dRmerge = dRmergeNeutralHadronWrtElectron_;
220  else dRmerge = dRmergeNeutralHadronWrtOther_;
221  minBlockElementMatches = minBlockElementMatchesNeutralHadron_;
222  maxUnmatchedBlockElements = maxUnmatchedBlockElementsNeutralHadron_;
223  minMergeEt = minMergeNeutralHadronEt_;
224  } else if ( jetConstituentPdgId == 22 ) {
225  if ( pdgId == 211 ) dRmerge = dRmergePhotonWrtChargedHadron_;
226  else if ( pdgId == 130 ) dRmerge = dRmergePhotonWrtNeutralHadron_;
227  else if ( pdgId == 11 ) dRmerge = dRmergePhotonWrtElectron_;
228  else dRmerge = dRmergePhotonWrtOther_;
229  minBlockElementMatches = minBlockElementMatchesPhoton_;
230  maxUnmatchedBlockElements = maxUnmatchedBlockElementsPhoton_;
231  minMergeEt = minMergeGammaEt_;
232  }
233 
234  if (jetConstituent->et() > minMergeEt) {
235  if (dR < dRmerge) {
236  chargedHadron->neutralPFCandidates_.push_back(jetConstituent);
237  chargedHadron->addDaughter(jetConstituent);
238  }
239  else {
240  // TauReco@MiniAOD: No access to PF blocks at MiniAOD level, but the code below seems to have very minor impact
241  const reco::PFCandidate* pfJetConstituent = dynamic_cast<const reco::PFCandidate*>(jetConstituent.get());
242  if (pfCand != nullptr && pfJetConstituent != nullptr) {
243  if (isMatchedByBlockElement(*pfJetConstituent, *pfCand, minBlockElementMatches, minBlockElementMatches, maxUnmatchedBlockElements)) {
244  chargedHadron->neutralPFCandidates_.push_back(jetConstituent);
245  chargedHadron->addDaughter(jetConstituent);
246  }
247  }
248  }
249  }
250  }
251  }
252 
253  setChargedHadronP4(*chargedHadron);
254 
255  if ( verbosity_ ) {
256  edm::LogPrint("TauChHadronFromPF") << *chargedHadron;
257  }
258  // Update the vertex
259  if ( chargedHadron->daughterPtr(0).isNonnull() ) chargedHadron->setVertex(chargedHadron->daughterPtr(0)->vertex());
260  output.push_back(chargedHadron);
261  }
262 
263  return output.release();
264 }
265 
266 }} // end namespace reco::tau
267 
269 
std::vector< CandidatePtr > pfCandidates(const Jet &jet, int particleId, bool sort=true)
T getParameter(std::string const &) const
math::XYZPointF atECALEntrance(const reco::Candidate *part, double bField)
bool isNonnull() const
Checks for non-null.
Definition: Ref.h:251
Ptr< typename C::value_type > refToPtr(Ref< C, typename C::value_type, refhelper::FindUsingAdvance< C, typename C::value_type > > const &ref)
Definition: RefToPtr.h:18
Coll filterCandRefs(const Coll &refcoll, bool invert=false) const
Filter a ref vector of Candidates.
Base class for all types of Jets.
Definition: Jet.h:20
#define nullptr
PFRecoTauChargedHadronFromPFCandidatePlugin(const edm::ParameterSet &, edm::ConsumesCollector &&iC)
Global3DPoint GlobalPoint
Definition: GlobalPoint.h:10
void setEvent(const edm::Event &evt)
Load the vertices from the event.
boost::ptr_vector< PFRecoTauChargedHadron > ChargedHadronVector
std::vector< ElementInBlock > ElementsInBlocks
Definition: PFCandidate.h:387
virtual const daughters & daughterPtrVector() const
references to daughtes
reco::TrackRef trackRef() const
Definition: PFCandidate.cc:442
void setPV(const reco::VertexRef &vtx) const
Update the primary vertex.
T z() const
Definition: PV3DBase.h:64
return_type operator()(const reco::Jet &) const override
Build a collection of chargedHadrons from objects in the input jet.
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
bool isMatched(TrackingRecHit const &hit)
const edm::EventSetup * evtSetup() const
virtual GlobalVector inTesla(const GlobalPoint &gp) const =0
Field value ad specified global point, in Tesla.
void addDaughter(const Candidate &, const std::string &s="")
add a clone of the passed candidate as daughter
reco::MuonRef muonRef() const
Definition: PFCandidate.cc:459
constexpr auto deltaR(const T1 &t1, const T2 &t2) -> decltype(t1.eta())
Definition: deltaR.h:28
ParameterSet const & getParameterSet(std::string const &) const
Particle reconstructed by the particle flow algorithm.
Definition: PFCandidate.h:40
fixed size matrix
HLT enums.
reco::VertexRef associatedVertex(const Jet &jet) const
T get() const
Definition: EventSetup.h:71
reco::GsfTrackRef gsfTrackRef() const
Definition: PFCandidate.cc:480
#define DEFINE_EDM_PLUGIN(factory, type, name)
const std::string & name() const
void setChargedHadronP4(reco::PFRecoTauChargedHadron &chargedHadron, double scaleFactor_neutralPFCands=1.0)
const ElementsInBlocks & elementsInBlocks() const
Definition: PFCandidate.cc:691
void beginEvent() override
Hook called at the beginning of the event.
def move(src, dest)
Definition: eostools.py:511