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