CMS 3D CMS Logo

FFTJetPFPileupCleaner.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: FFTJetProducers
4 // Class: FFTJetPFPileupCleaner
5 //
13 //
14 // Original Author: Igor Volobouev
15 // Created: Thu Jul 14 17:50:33 CDT 2011
16 //
17 //
18 #include <cmath>
19 #include <climits>
20 #include <utility>
21 #include <algorithm>
22 
23 // framework include files
30 
33 
36 
39 
40 #define init_param(type, varname) varname(ps.getParameter<type>(#varname))
41 
42 //
43 // class declaration
44 //
46 public:
48  ~FFTJetPFPileupCleaner() override;
49 
50 protected:
51  // methods
52  void beginJob() override;
53  void produce(edm::Event&, const edm::EventSetup&) override;
54  void endJob() override;
55 
56 private:
57  FFTJetPFPileupCleaner() = delete;
60 
62  void setRemovalBit(reco::PFCandidate::ParticleType ptype, bool onOff);
63  void buildRemovalMask();
64  bool isAcceptableVtx(reco::VertexCollection::const_iterator iv) const;
65 
67  const edm::Handle<reco::VertexCollection>& fakeVertices,
69  bool* fromFakeSet) const;
70 
74 
78 
79  // The following, if true, will switch to an algorithm
80  // which takes a fake primary vertex into account
82 
83  // The following, if true, will cause association of a candidate
84  // with some vertex no matter what
86 
87  // The following switch will check if the primary vertex
88  // is a neighbor (in Z) of a track and will keep the
89  // track if this is so, even if it is not directly associated
90  // with the primary vertex. This switch is meaningful only if
91  // "checkClosestZVertex" is true.
93 
94  // The following, if true, will cause removal of candidates
95  // associated with the main vertex
97 
98  // The following will tell us to remove candidates not associated
99  // with any vertex
101 
102  // Do we want to reverse the decision?
104 
105  // Flags for removing things. See PFCandidate header
106  // for particle types.
107  bool remove_X; // undefined
108  bool remove_h; // charged hadron
109  bool remove_e; // electron
110  bool remove_mu; // muon
111  bool remove_gamma; // photon
112  bool remove_h0; // neutral hadron
113  bool remove_h_HF; // HF tower identified as a hadron
114  bool remove_egamma_HF; // HF tower identified as an EM particle
115 
116  // Mask for removing things
117  unsigned removalMask;
118 
119  // Min and max eta for keeping things
120  double etaMin;
121  double etaMax;
122 
123  // Cut for the vertex Ndof
125 
126  // Cut for the vertex Z
128 
129  // Cut for the vertex rho
130  double vertexRhoCut;
131 
132  // Vector for associating tracks with Z positions of the vertices
133  mutable std::vector<std::pair<double, unsigned> > zAssoc;
134 };
135 
136 //
137 // constructors and destructor
138 //
157  removalMask(0),
158  init_param(double, etaMin),
159  init_param(double, etaMax),
160  init_param(double, vertexNdofCut),
161  init_param(double, vertexZmaxCut),
162  init_param(double, vertexRhoCut) {
164 
165  PFCandidatesToken = consumes<reco::PFCandidateCollection>(PFCandidates);
166  VerticesToken = consumes<reco::VertexCollection>(Vertices);
168  FakePrimaryVerticesToken = consumes<reco::VertexCollection>(FakePrimaryVertices);
169 
170  produces<reco::PFCandidateCollection>();
171 }
172 
174 
175 bool FFTJetPFPileupCleaner::isAcceptableVtx(reco::VertexCollection::const_iterator iv) const {
176  return !iv->isFake() && static_cast<double>(iv->ndof()) > vertexNdofCut && std::abs(iv->z()) < vertexZmaxCut &&
177  iv->position().rho() < vertexRhoCut;
178 }
179 
180 // ------------ method called to produce the data ------------
182  // get PFCandidates
183  auto pOutput = std::make_unique<reco::PFCandidateCollection>();
184 
186  iEvent.getByToken(PFCandidatesToken, pfCandidates);
187 
188  // get vertices
190  iEvent.getByToken(VerticesToken, vertices);
191 
193  if (useFakePrimaryVertex) {
194  iEvent.getByToken(FakePrimaryVerticesToken, fakeVertices);
195  if (!fakeVertices.isValid())
196  throw cms::Exception("FFTJetBadConfig") << "ERROR in FFTJetPFPileupCleaner:"
197  " could not find fake vertices"
198  << std::endl;
199  }
200 
201  const unsigned ncand = pfCandidates->size();
202  for (unsigned i = 0; i < ncand; ++i) {
203  reco::PFCandidatePtr candptr(pfCandidates, i);
204  bool remove = false;
205 
206  if (isRemovable(candptr->particleId())) {
207  bool fromFakeSet = false;
208  reco::VertexRef vertexref(findSomeVertexWFakes(vertices, fakeVertices, *candptr, &fromFakeSet));
209  if (vertexref.isNull()) {
210  // Track is not associated with any vertex
211  // in any of the vertex sets
212  remove = removeUnassociated;
213  } else if (vertexref.key() == 0 && (!useFakePrimaryVertex || fromFakeSet)) {
214  // Track is associated with the main primary vertex
215  // However, if we are using fake vertices, this only
216  // matters if the vertex comes from the fake set. If
217  // it comes from the real set, remove the track anyway
218  // because in the combined set the associated vertex
219  // would not be the main primary vertex.
220  remove = removeMainVertex;
221  } else
222  remove = true;
223  }
224 
225  // Check the eta range
226  if (!remove) {
227  const double eta = candptr->p4().Eta();
228  remove = eta < etaMin || eta > etaMax;
229  }
230 
231  // Should we remember this candidate?
233  remove = !remove;
234  if (!remove) {
235  const reco::PFCandidate& cand = (*pfCandidates)[i];
236  pOutput->push_back(cand);
237  pOutput->back().setSourceCandidatePtr(candptr);
238  }
239  }
240 
241  iEvent.put(std::move(pOutput));
242 }
243 
245  const unsigned shift = static_cast<unsigned>(ptype);
246  assert(shift < 32U);
247  return removalMask & (1U << shift);
248 }
249 
251  const unsigned shift = static_cast<unsigned>(ptype);
252  assert(shift < 32U);
253  const unsigned mask = (1U << shift);
254  if (value)
255  removalMask |= mask;
256  else
257  removalMask &= ~mask;
258 }
259 
260 // The following essentially follows the code in PFPileUp.cc,
261 // with added cut on ndof, vertex Z position, and iteration
262 // over fakes
264  const edm::Handle<reco::VertexCollection>& fakeVertices,
265  const reco::PFCandidate& pfcand,
266  bool* fromFakeSet) const {
267  typedef reco::VertexCollection::const_iterator IV;
269 
270  *fromFakeSet = false;
271  reco::TrackBaseRef trackBaseRef(pfcand.trackRef());
272 
273  size_t iVertex = 0;
274  unsigned nFoundVertex = 0;
275  const IV vertend(vertices->end());
276 
277  {
278  unsigned index = 0;
279  double bestweight = 0.0;
280  for (IV iv = vertices->begin(); iv != vertend; ++iv, ++index)
281  if (isAcceptableVtx(iv)) {
282  const reco::Vertex& vtx = *iv;
283 
284  // loop on tracks in vertices
285  IT trackend(vtx.tracks_end());
286  for (IT iTrack = vtx.tracks_begin(); iTrack != trackend; ++iTrack) {
287  const reco::TrackBaseRef& baseRef = *iTrack;
288 
289  // one of the tracks in the vertex is the same as
290  // the track considered in the function
291  if (baseRef == trackBaseRef) {
292  // select the vertex for which the track has the highest weight
293  const double w = vtx.trackWeight(baseRef);
294  if (w > bestweight) {
295  bestweight = w;
296  iVertex = index;
297  nFoundVertex++;
298  }
299  }
300  }
301  }
302  }
303 
304  if (nFoundVertex > 0) {
305  if (nFoundVertex != 1)
306  edm::LogWarning("TrackOnTwoVertex") << "a track is shared by at least two vertices. "
307  << "Used to be an assert";
308 
309  // Check if we can re-associate this track with one
310  // of the fake vertices
311  if (useFakePrimaryVertex) {
312  const double ztrack = pfcand.vertex().z();
313  double dzmin = std::abs(ztrack - ((*vertices)[iVertex]).z());
314 
315  const IV fakeEnd(fakeVertices->end());
316  unsigned index = 0;
317  for (IV iv = fakeVertices->begin(); iv != fakeEnd; ++iv, ++index)
318  if (isAcceptableVtx(iv)) {
319  const double dz = std::abs(ztrack - iv->z());
320  if (dz < dzmin) {
321  dzmin = dz;
322  iVertex = index;
323  *fromFakeSet = true;
324  }
325  }
326  }
327 
328  return reco::VertexRef(*fromFakeSet ? fakeVertices : vertices, iVertex);
329  }
330 
331  // optional: as a secondary solution, associate the closest vertex in z
332  if (checkClosestZVertex) {
333  const double ztrack = pfcand.vertex().z();
334  bool foundVertex = false;
335 
336  if (keepIfPVneighbor) {
337  // Sort all vertices according to their Z coordinate
338  zAssoc.clear();
339  unsigned index = 0;
340  for (IV iv = vertices->begin(); iv != vertend; ++iv, ++index)
341  if (isAcceptableVtx(iv))
342  zAssoc.push_back(std::pair<double, unsigned>(iv->z(), index));
343  const unsigned numRealVertices = index;
344 
345  // Mix the fake vertex collection into zAssoc.
346  // Note that we do not reset "index" before doing this.
347  if (useFakePrimaryVertex) {
348  const IV fakeEnd(fakeVertices->end());
349  for (IV iv = fakeVertices->begin(); iv != fakeEnd; ++iv, ++index)
350  if (isAcceptableVtx(iv))
351  zAssoc.push_back(std::pair<double, unsigned>(iv->z(), index));
352  }
353 
354  // Check where the track z position fits into this sequence
355  if (!zAssoc.empty()) {
356  std::sort(zAssoc.begin(), zAssoc.end());
357  std::pair<double, unsigned> tPair(ztrack, UINT_MAX);
358  const unsigned iAbove = std::upper_bound(zAssoc.begin(), zAssoc.end(), tPair) - zAssoc.begin();
359 
360  // Check whether one of the vertices with indices
361  // iAbove or (iAbove - 1) is a primary vertex.
362  // If so, return it. Otherwise return the one
363  // with closest distance to the track.
364  unsigned ich[2] = {0U, 0U};
365  unsigned nch = 1;
366  if (iAbove) {
367  ich[0] = iAbove - 1U;
368  ich[1] = iAbove;
369  if (iAbove < zAssoc.size())
370  nch = 2;
371  }
372 
373  double dzmin = 1.0e100;
374  unsigned bestVertexNum = UINT_MAX;
375  for (unsigned icheck = 0; icheck < nch; ++icheck) {
376  const unsigned zAssocIndex = ich[icheck];
377  const unsigned vertexNum = zAssoc[zAssocIndex].second;
378 
379  if (vertexNum == numRealVertices || (!useFakePrimaryVertex && vertexNum == 0U)) {
380  bestVertexNum = vertexNum;
381  break;
382  }
383 
384  const double dz = std::abs(ztrack - zAssoc[zAssocIndex].first);
385  if (dz < dzmin) {
386  dzmin = dz;
387  bestVertexNum = vertexNum;
388  }
389  }
390 
391  foundVertex = bestVertexNum < UINT_MAX;
392  if (foundVertex) {
393  iVertex = bestVertexNum;
394  if (iVertex >= numRealVertices) {
395  *fromFakeSet = true;
396  iVertex -= numRealVertices;
397  }
398  }
399  }
400  } else {
401  // This is a simple association algorithm (from PFPileUp)
402  // extended to take fake vertices into account
403  double dzmin = 1.0e100;
404  unsigned index = 0;
405  for (IV iv = vertices->begin(); iv != vertend; ++iv, ++index)
406  if (isAcceptableVtx(iv)) {
407  const double dz = std::abs(ztrack - iv->z());
408  if (dz < dzmin) {
409  dzmin = dz;
410  iVertex = index;
411  foundVertex = true;
412  }
413  }
414 
415  if (useFakePrimaryVertex) {
416  const IV fakeEnd(fakeVertices->end());
417  index = 0;
418  for (IV iv = fakeVertices->begin(); iv != fakeEnd; ++iv, ++index)
419  if (isAcceptableVtx(iv)) {
420  const double dz = std::abs(ztrack - iv->z());
421  if (dz < dzmin) {
422  dzmin = dz;
423  iVertex = index;
424  *fromFakeSet = true;
425  foundVertex = true;
426  }
427  }
428  }
429  }
430 
431  if (foundVertex)
432  return reco::VertexRef(*fromFakeSet ? fakeVertices : vertices, iVertex);
433  }
434 
435  return reco::VertexRef();
436 }
437 
447 }
448 
449 // ------------ method called once each job just before starting event loop
451 
452 // ------------ method called once each job just after ending the event loop
454 
455 //define this as a plug-in
void setRemovalBit(reco::PFCandidate::ParticleType ptype, bool onOff)
OrphanHandle< PROD > put(std::unique_ptr< PROD > product)
Put a new product.
Definition: Event.h:131
ParticleType
particle types
Definition: PFCandidate.h:43
const double w
Definition: UKUtility.cc:23
trackRef_iterator tracks_end() const
last iterator over tracks
Definition: Vertex.cc:73
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:525
edm::EDGetTokenT< reco::VertexCollection > FakePrimaryVerticesToken
key_type key() const
Accessor for product key.
Definition: Ref.h:250
reco::TrackRef trackRef() const
Definition: PFCandidate.cc:408
bool isRemovable(reco::PFCandidate::ParticleType ptype) const
const Point & vertex() const override
vertex position (overwritten by PF...)
Definition: PFCandidate.cc:602
FFTJetPFPileupCleaner & operator=(const FFTJetPFPileupCleaner &)=delete
int iEvent
Definition: GenABIO.cc:224
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
FFTJetPFPileupCleaner()=delete
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
edm::EDGetTokenT< reco::VertexCollection > VerticesToken
float trackWeight(const TREF &r) const
returns the weight with which a Track has contributed to the vertex-fit.
Definition: Vertex.h:84
Definition: value.py:1
std::vector< LinkConnSpec >::const_iterator IT
bool isValid() const
Definition: HandleBase.h:70
void produce(edm::Event &, const edm::EventSetup &) override
edm::Ref< VertexCollection > VertexRef
persistent reference to a Vertex
Definition: VertexFwd.h:13
bool isNull() const
Checks for null.
Definition: Ref.h:235
std::vector< std::pair< double, unsigned > > zAssoc
edm::EDGetTokenT< reco::PFCandidateCollection > PFCandidatesToken
#define init_param(type, varname)
Particle reconstructed by the particle flow algorithm.
Definition: PFCandidate.h:40
HLT enums.
reco::VertexRef findSomeVertexWFakes(const edm::Handle< reco::VertexCollection > &vertices, const edm::Handle< reco::VertexCollection > &fakeVertices, const reco::PFCandidate &pfcand, bool *fromFakeSet) const
static unsigned int const shift
trackRef_iterator tracks_begin() const
first iterator over tracks
Definition: Vertex.cc:71
def move(src, dest)
Definition: eostools.py:511
std::vector< TrackBaseRef >::const_iterator trackRef_iterator
The iteratator for the vector<TrackRef>
Definition: Vertex.h:37
bool isAcceptableVtx(reco::VertexCollection::const_iterator iv) const