CMS 3D CMS Logo

RecoTauPiZeroStripPlugin3.cc
Go to the documentation of this file.
1 /*
2  * RecoTauPiZeroStripPlugin3
3  *
4  * Merges PFGammas in a PFJet into Candidate piZeros defined as
5  * strips in eta-phi.
6  *
7  * Author: Michail Bachtis (University of Wisconsin)
8  *
9  * Code modifications: Evan Friis (UC Davis),
10  * Christian Veelken (LLR)
11  *
12  */
13 
14 #include <algorithm>
15 #include <functional>
16 #include <memory>
17 
19 
29 
34 
35 //-------------------------------------------------------------------------------
36 // CV: the following headers are needed only for debug print-out
39 //-------------------------------------------------------------------------------
40 
41 #include "TString.h"
42 #include "TFormula.h"
43 
44 namespace reco {
45  namespace tau {
46 
47  namespace {
48  // Apply a hypothesis on the mass of the strips.
49  math::XYZTLorentzVector applyMassConstraint(const math::XYZTLorentzVector& vec, double mass) {
50  double factor = sqrt(vec.energy() * vec.energy() - mass * mass) / vec.P();
51  return math::XYZTLorentzVector(vec.px() * factor, vec.py() * factor, vec.pz() * factor, vec.energy());
52  }
53  } // namespace
54 
56  public:
58  ~RecoTauPiZeroStripPlugin3() override;
59  // Return type is unique_ptr<PiZeroVector>
60  return_type operator()(const reco::Jet&) const override;
61  // Hook to update PV information
62  void beginEvent() override;
63 
64  private:
65  typedef std::vector<reco::CandidatePtr> CandPtrs;
66  void addCandsToStrip(RecoTauPiZero&, CandPtrs&, const std::vector<bool>&, std::set<size_t>&, bool&) const;
67 
69 
70  std::unique_ptr<RecoTauQualityCuts> qcuts_;
74 
75  double minStripEt_;
76 
77  std::vector<int> inputParticleIds_; // type of candidates to clusterize
78  std::unique_ptr<const TFormula> etaAssociationDistance_; // size of strip clustering window in eta direction
79  std::unique_ptr<const TFormula> phiAssociationDistance_; // size of strip clustering window in phi direction
80 
83 
84  // Parameters for build strip combinations
88 
90 
92  };
93 
94  namespace {
95  std::unique_ptr<TFormula> makeFunction(const std::string& functionName, const edm::ParameterSet& pset) {
96  TString formula = pset.getParameter<std::string>("function");
97  formula = formula.ReplaceAll("pT", "x");
98  std::unique_ptr<TFormula> function(new TFormula(functionName.data(), formula.Data()));
99  int numParameter = function->GetNpar();
100  for (int idxParameter = 0; idxParameter < numParameter; ++idxParameter) {
101  std::string parameterName = Form("par%i", idxParameter);
102  double parameter = pset.getParameter<double>(parameterName);
103  function->SetParameter(idxParameter, parameter);
104  }
105  return function;
106  }
107  } // namespace
108 
111  vertexAssociator_(pset.getParameter<edm::ParameterSet>("qualityCuts"), std::move(iC)),
112  qcuts_(nullptr),
113  etaAssociationDistance_(nullptr),
114  phiAssociationDistance_(nullptr) {
115  minGammaEtStripSeed_ = pset.getParameter<double>("minGammaEtStripSeed");
116  minGammaEtStripAdd_ = pset.getParameter<double>("minGammaEtStripAdd");
117 
118  minStripEt_ = pset.getParameter<double>("minStripEt");
119 
120  edm::ParameterSet qcuts_pset = pset.getParameterSet("qualityCuts").getParameterSet("signalQualityCuts");
121  //-------------------------------------------------------------------------------
122  // CV: disable track quality cuts for PFElectronsPFElectron
123  // (treat PFElectrons like PFGammas for the purpose of building eta-phi strips)
124  applyElecTrackQcuts_ = pset.getParameter<bool>("applyElecTrackQcuts");
125  if (!applyElecTrackQcuts_) {
126  qcuts_pset.addParameter<double>("minTrackPt", std::min(minGammaEtStripSeed_, minGammaEtStripAdd_));
127  qcuts_pset.addParameter<double>("maxTrackChi2", 1.e+9);
128  qcuts_pset.addParameter<double>("maxTransverseImpactParameter", 1.e+9);
129  qcuts_pset.addParameter<double>("maxDeltaZ", 1.e+9);
130  qcuts_pset.addParameter<double>("minTrackVertexWeight", -1.);
131  qcuts_pset.addParameter<unsigned>("minTrackPixelHits", 0);
132  qcuts_pset.addParameter<unsigned>("minTrackHits", 0);
133  }
134  //-------------------------------------------------------------------------------
135  qcuts_pset.addParameter<double>("minGammaEt", std::min(minGammaEtStripSeed_, minGammaEtStripAdd_));
136  //qcuts_ = new RecoTauQualityCuts(qcuts_pset);
137  //std::unique_ptr<RecoTauQualityCuts> qcuts_(new RecoTauQualityCuts(qcuts_pset));
138 
139  qcuts_ = std::make_unique<RecoTauQualityCuts>(qcuts_pset);
140 
141  inputParticleIds_ = pset.getParameter<std::vector<int> >("stripCandidatesParticleIds");
142  const edm::ParameterSet& stripSize_eta_pset = pset.getParameterSet("stripEtaAssociationDistanceFunc");
143  etaAssociationDistance_ = makeFunction("etaAssociationDistance", stripSize_eta_pset);
144  const edm::ParameterSet& stripSize_phi_pset = pset.getParameterSet("stripPhiAssociationDistanceFunc");
145  phiAssociationDistance_ = makeFunction("phiAssociationDistance", stripSize_phi_pset);
146 
147  updateStripAfterEachDaughter_ = pset.getParameter<bool>("updateStripAfterEachDaughter");
148  maxStripBuildIterations_ = pset.getParameter<int>("maxStripBuildIterations");
149 
150  combineStrips_ = pset.getParameter<bool>("makeCombinatoricStrips");
151  if (combineStrips_) {
152  maxStrips_ = pset.getParameter<int>("maxInputStrips");
153  combinatoricStripMassHypo_ = pset.getParameter<double>("stripMassWhenCombining");
154  }
155 
156  verbosity_ = pset.getParameter<int>("verbosity");
157  }
159 
160  // Update the primary vertex
162 
164  CandPtrs& cands,
165  const std::vector<bool>& candFlags,
166  std::set<size_t>& candIdsCurrentStrip,
167  bool& isCandAdded) const {
168  if (verbosity_ >= 1) {
169  edm::LogPrint("RecoTauPiZeroStripPlugin3") << "<RecoTauPiZeroStripPlugin3::addCandsToStrip>:";
170  }
171  size_t numCands = cands.size();
172  for (size_t candId = 0; candId < numCands; ++candId) {
173  if ((!candFlags[candId]) &&
174  candIdsCurrentStrip.find(candId) == candIdsCurrentStrip.end()) { // do not include same cand twice
175  reco::CandidatePtr cand = cands[candId];
176  double etaAssociationDistance_value =
177  etaAssociationDistance_->Eval(strip.pt()) + etaAssociationDistance_->Eval(cand->pt());
178  double phiAssociationDistance_value =
179  phiAssociationDistance_->Eval(strip.pt()) + phiAssociationDistance_->Eval(cand->pt());
180  if (fabs(strip.eta() - cand->eta()) <
181  etaAssociationDistance_value && // check if cand is within eta-phi window centered on strip
182  reco::deltaPhi(strip.phi(), cand->phi()) < phiAssociationDistance_value) {
183  if (verbosity_ >= 2) {
184  edm::LogPrint("RecoTauPiZeroStripPlugin3")
185  << "--> adding PFCand #" << candId << " (" << cand.id() << ":" << cand.key()
186  << "): Et = " << cand->et() << ", eta = " << cand->eta() << ", phi = " << cand->phi();
187  }
188  strip.addDaughter(cand);
191  isCandAdded = true;
192  candIdsCurrentStrip.insert(candId);
193  }
194  }
195  }
196  }
197 
198  namespace {
199  void markCandsInStrip(std::vector<bool>& candFlags, const std::set<size_t>& candIds) {
200  for (std::set<size_t>::const_iterator candId = candIds.begin(); candId != candIds.end(); ++candId) {
201  candFlags[*candId] = true;
202  }
203  }
204 
205  // The following method has not been adapted to work with PackedCandidates,
206  // however, it is only used for printing/debugging and can be adapted when
207  // needed.
208  inline const reco::TrackBaseRef getTrack(const Candidate& cand) {
209  const PFCandidate* pfCandPtr = dynamic_cast<const PFCandidate*>(&cand);
210  if (pfCandPtr) {
211  if (pfCandPtr->trackRef().isNonnull())
212  return reco::TrackBaseRef(pfCandPtr->trackRef());
213  else if (pfCandPtr->gsfTrackRef().isNonnull())
214  return reco::TrackBaseRef(pfCandPtr->gsfTrackRef());
215  else
216  return reco::TrackBaseRef();
217  }
218 
219  return reco::TrackBaseRef();
220  }
221  } // namespace
222 
224  if (verbosity_ >= 1) {
225  edm::LogPrint("RecoTauPiZeroStripPlugin3") << "<RecoTauPiZeroStripPlugin3::operator()>:";
226  edm::LogPrint("RecoTauPiZeroStripPlugin3") << " minGammaEtStripSeed = " << minGammaEtStripSeed_;
227  edm::LogPrint("RecoTauPiZeroStripPlugin3") << " minGammaEtStripAdd = " << minGammaEtStripAdd_;
228  edm::LogPrint("RecoTauPiZeroStripPlugin3") << " minStripEt = " << minStripEt_;
229  }
230 
232 
233  // Get the candidates passing our quality cuts
235  CandPtrs candsVector = qcuts_->filterCandRefs(pfCandidates(jet, inputParticleIds_));
236 
237  // Convert to stl::list to allow fast deletions
238  CandPtrs seedCands;
239  CandPtrs addCands;
240  int idx = 0;
241  for (CandPtrs::iterator cand = candsVector.begin(); cand != candsVector.end(); ++cand) {
242  if (verbosity_ >= 1) {
243  edm::LogPrint("RecoTauPiZeroStripPlugin3")
244  << "PFGamma #" << idx << " (" << cand->id() << ":" << cand->key() << "): Et = " << (*cand)->et()
245  << ", eta = " << (*cand)->eta() << ", phi = " << (*cand)->phi();
246  }
247  if ((*cand)->et() > minGammaEtStripSeed_) {
248  if (verbosity_ >= 2) {
249  edm::LogPrint("RecoTauPiZeroStripPlugin3") << "--> assigning seedCandId = " << seedCands.size();
250  const reco::TrackBaseRef candTrack = getTrack(**cand);
251  if (candTrack.isNonnull()) {
252  edm::LogPrint("RecoTauPiZeroStripPlugin3")
253  << "track: Pt = " << candTrack->pt() << " eta = " << candTrack->eta()
254  << ", phi = " << candTrack->phi() << ", charge = " << candTrack->charge();
255  edm::LogPrint("RecoTauPiZeroStripPlugin3")
256  << " (dZ = " << candTrack->dz(vertexAssociator_.associatedVertex(jet)->position())
257  << ", dXY = " << candTrack->dxy(vertexAssociator_.associatedVertex(jet)->position()) << ","
258  << " numHits = " << candTrack->hitPattern().numberOfValidTrackerHits()
259  << ", numPxlHits = " << candTrack->hitPattern().numberOfValidPixelHits() << ","
260  << " chi2 = " << candTrack->normalizedChi2()
261  << ", dPt/Pt = " << (candTrack->ptError() / candTrack->pt()) << ")";
262  }
263  }
264  seedCands.push_back(*cand);
265  } else if ((*cand)->et() > minGammaEtStripAdd_) {
266  if (verbosity_ >= 2) {
267  edm::LogPrint("RecoTauPiZeroStripPlugin3") << "--> assigning addCandId = " << addCands.size();
268  }
269  addCands.push_back(*cand);
270  }
271  ++idx;
272  }
273 
274  std::vector<bool> seedCandFlags(seedCands.size()); // true/false: seedCand is already/not yet included in strip
275  std::vector<bool> addCandFlags(addCands.size()); // true/false: addCand is already/not yet included in strip
276 
277  std::set<size_t> seedCandIdsCurrentStrip;
278  std::set<size_t> addCandIdsCurrentStrip;
279 
280  size_t idxSeed = 0;
281  while (idxSeed < seedCands.size()) {
282  if (verbosity_ >= 2)
283  edm::LogPrint("RecoTauPiZeroStripPlugin3") << "processing seed #" << idxSeed;
284 
285  seedCandIdsCurrentStrip.clear();
286  addCandIdsCurrentStrip.clear();
287 
288  std::unique_ptr<RecoTauPiZero> strip(new RecoTauPiZero(*seedCands[idxSeed], RecoTauPiZero::kStrips));
289  strip->addDaughter(seedCands[idxSeed]);
290  seedCandIdsCurrentStrip.insert(idxSeed);
291 
292  bool isCandAdded;
293  int stripBuildIteration = 0;
294  do {
295  isCandAdded = false;
296 
297  //if ( verbosity_ >= 2 ) edm::LogPrint("RecoTauPiZeroStripPlugin3") << " adding seedCands to strip..." ;
298  addCandsToStrip(*strip, seedCands, seedCandFlags, seedCandIdsCurrentStrip, isCandAdded);
299  //if ( verbosity_ >= 2 ) edm::LogPrint("RecoTauPiZeroStripPlugin3") << " adding addCands to strip..." ;
300  addCandsToStrip(*strip, addCands, addCandFlags, addCandIdsCurrentStrip, isCandAdded);
301 
303  p4Builder_.set(*strip);
304 
305  ++stripBuildIteration;
306  } while (isCandAdded && (stripBuildIteration < maxStripBuildIterations_ || maxStripBuildIterations_ == -1));
307 
308  if (strip->et() > minStripEt_) { // strip passed Et cuts, add it to the event
309  if (verbosity_ >= 2)
310  edm::LogPrint("RecoTauPiZeroStripPlugin3")
311  << "Building strip: Et = " << strip->et() << ", eta = " << strip->eta() << ", phi = " << strip->phi();
312 
313  // Update the vertex
314  if (strip->daughterPtr(0).isNonnull())
315  strip->setVertex(strip->daughterPtr(0)->vertex());
316  output.push_back(std::move(strip));
317 
318  // Mark daughters as being part of this strip
319  markCandsInStrip(seedCandFlags, seedCandIdsCurrentStrip);
320  markCandsInStrip(addCandFlags, addCandIdsCurrentStrip);
321  } else { // strip failed Et cuts, just skip it
322  if (verbosity_ >= 2)
323  edm::LogPrint("RecoTauPiZeroStripPlugin3")
324  << "Discarding strip: Et = " << strip->et() << ", eta = " << strip->eta() << ", phi = " << strip->phi();
325  }
326 
327  ++idxSeed;
328  while (idxSeed < seedCands.size() && seedCandFlags[idxSeed]) {
329  ++idxSeed; // fast-forward to next seed cand not yet included in any strip
330  }
331  }
332 
333  // Check if we want to combine our strips
334  if (combineStrips_ && output.size() > 1) {
335  PiZeroVector stripCombinations;
336  // Sort the output by descending pt
337  std::sort(output.begin(), output.end(), [&](auto& arg1, auto& arg2) { return arg1->pt() > arg2->pt(); });
338  // Get the end of interesting set of strips to try and combine
339  PiZeroVector::const_iterator end_iter = takeNElements(output.begin(), output.end(), maxStrips_);
340 
341  // Look at all the combinations
342  for (PiZeroVector::const_iterator firstIter = output.begin(); firstIter != end_iter - 1; ++firstIter) {
343  for (PiZeroVector::const_iterator secondIter = firstIter + 1; secondIter != end_iter; ++secondIter) {
344  auto const& first = *firstIter;
345  auto const& second = *secondIter;
346  Candidate::LorentzVector firstP4 = first->p4();
347  Candidate::LorentzVector secondP4 = second->p4();
348  // If we assume a certain mass for each strip apply it here.
349  firstP4 = applyMassConstraint(firstP4, combinatoricStripMassHypo_);
350  secondP4 = applyMassConstraint(secondP4, combinatoricStripMassHypo_);
351  Candidate::LorentzVector totalP4 = firstP4 + secondP4;
352  // Make our new combined strip
353  auto combinedStrips =
354  std::make_unique<RecoTauPiZero>(0,
355  totalP4,
356  Candidate::Point(0, 0, 0),
357  //111, 10001, true, RecoTauPiZero::kCombinatoricStrips));
358  111,
359  10001,
360  true,
362 
363  // Now loop over the strip members
364  for (auto const& gamma : first->daughterPtrVector()) {
365  combinedStrips->addDaughter(gamma);
366  }
367  for (auto const& gamma : second->daughterPtrVector()) {
368  combinedStrips->addDaughter(gamma);
369  }
370  // Update the vertex
371  if (combinedStrips->daughterPtr(0).isNonnull()) {
372  combinedStrips->setVertex(combinedStrips->daughterPtr(0)->vertex());
373  }
374 
375  // Add to our collection of combined strips
376  stripCombinations.push_back(std::move(combinedStrips));
377  }
378  }
379  // When done doing all the combinations, add the combined strips to the
380  // output.
381  std::move(stripCombinations.begin(), stripCombinations.end(), std::back_inserter(output));
382  }
383 
384  // Compute correction to account for spread of photon energy in eta and phi
385  // in case charged pions make nuclear interactions or photons convert within the tracking detector
386  for (auto const& strip : output) {
387  double bendCorrEta = 0.;
388  double bendCorrPhi = 0.;
389  double energySum = 0.;
390  for (auto const& gamma : strip->daughterPtrVector()) {
391  bendCorrEta += (gamma->energy() * etaAssociationDistance_->Eval(gamma->pt()));
392  bendCorrPhi += (gamma->energy() * phiAssociationDistance_->Eval(gamma->pt()));
393  energySum += gamma->energy();
394  }
395  if (energySum > 1.e-2) {
396  bendCorrEta /= energySum;
397  bendCorrPhi /= energySum;
398  }
399  //std::cout << "stripPt = " << strip->pt() << ": bendCorrEta = " << bendCorrEta << ", bendCorrPhi = " << bendCorrPhi << std::endl;
400  strip->setBendCorrEta(bendCorrEta);
401  strip->setBendCorrPhi(bendCorrPhi);
402  }
403 
404  return output;
405  }
406  } // namespace tau
407 } // namespace reco
408 
int numberOfValidPixelHits() const
Definition: HitPattern.h:831
constexpr double deltaPhi(double phi1, double phi2)
Definition: deltaPhi.h:26
std::vector< CandidatePtr > pfCandidates(const Jet &jet, int particleId, bool sort=true)
InputIterator takeNElements(const InputIterator &begin, const InputIterator &end, size_t N)
void set(reco::Candidate &c) const
set up a candidate
double ptError() const
error on Pt (set to 1000 TeV if charge==0 for safety)
Definition: TrackBase.h:754
bool isNonnull() const
Checks for non-null.
Definition: RefToBase.h:303
Base class for all types of Jets.
Definition: Jet.h:20
void addCandsToStrip(RecoTauPiZero &, CandPtrs &, const std::vector< bool > &, std::set< size_t > &, bool &) const
void setEvent(const edm::Event &evt)
Load the vertices from the event.
return_type operator()(const reco::Jet &) const override
Build a collection of piZeros from objects in the input jet.
reco::VertexRef associatedVertex(const Jet &jet) const
U second(std::pair< T, U > const &p)
XYZTLorentzVectorD XYZTLorentzVector
Lorentz vector with cylindrical internal representation using pseudorapidity.
Definition: LorentzVector.h:29
double pt() const
track transverse momentum
Definition: TrackBase.h:637
int charge() const
track electric charge
Definition: TrackBase.h:596
double dz() const
dz parameter (= dsz/cos(lambda)). This is the track z0 w.r.t (0,0,0) only if the refPoint is close to...
Definition: TrackBase.h:622
edm::RefToBase< reco::Track > TrackBaseRef
persistent reference to a Track, using views
Definition: TrackFwd.h:35
T sqrt(T t)
Definition: SSEVec.h:19
double phi() const
azimuthal angle of momentum vector
Definition: TrackBase.h:649
std::vector< reco::CandidatePtr > CandPtrs
void beginEvent() override
Hook called at the beginning of the event.
std::unique_ptr< const TFormula > etaAssociationDistance_
Log< level::Warning, true > LogPrint
std::unique_ptr< RecoTauQualityCuts > qcuts_
static const TrackGhostTrackState * getTrack(const BasicGhostTrackState *basic)
double eta() const
pseudorapidity of momentum vector
Definition: TrackBase.h:652
const HitPattern & hitPattern() const
Access the hit pattern, indicating in which Tracker layers the track has hits.
Definition: TrackBase.h:504
double normalizedChi2() const
chi-squared divided by n.d.o.f. (or chi-squared * 1e6 if n.d.o.f. is zero)
Definition: TrackBase.h:593
std::vector< std::unique_ptr< RecoTauPiZero > > PiZeroVector
math::XYZTLorentzVector LorentzVector
Lorentz vector.
Definition: Candidate.h:36
fixed size matrix
RecoTauPiZeroStripPlugin3(const edm::ParameterSet &, edm::ConsumesCollector &&iC)
HLT enums.
std::unique_ptr< const TFormula > phiAssociationDistance_
math::XYZPoint Point
point in the space
Definition: Candidate.h:40
#define DEFINE_EDM_PLUGIN(factory, type, name)
Definition: output.py:1
double energySum(const DataFrame &df, int fs, int ls)
int numberOfValidTrackerHits() const
Definition: HitPattern.h:819
def move(src, dest)
Definition: eostools.py:511
double dxy() const
dxy parameter. (This is the transverse impact parameter w.r.t. to (0,0,0) ONLY if refPoint is close t...
Definition: TrackBase.h:608