00001
00002
00003
00004
00005
00013
00014
00015
00016
00017
00018
00019 #include <cmath>
00020 #include <climits>
00021 #include <utility>
00022 #include <algorithm>
00023
00024
00025 #include "FWCore/Framework/interface/Frameworkfwd.h"
00026 #include "FWCore/Framework/interface/EDProducer.h"
00027 #include "FWCore/Framework/interface/Event.h"
00028 #include "FWCore/Framework/interface/MakerMacros.h"
00029 #include "FWCore/Utilities/interface/Exception.h"
00030 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00031
00032 #include "DataFormats/Common/interface/View.h"
00033 #include "DataFormats/Common/interface/Handle.h"
00034
00035 #include "DataFormats/ParticleFlowCandidate/interface/PFCandidate.h"
00036 #include "DataFormats/ParticleFlowCandidate/interface/PFCandidateFwd.h"
00037
00038 #include "DataFormats/VertexReco/interface/Vertex.h"
00039 #include "DataFormats/VertexReco/interface/VertexFwd.h"
00040
00041 #define init_param(type, varname) varname (ps.getParameter< type >( #varname ))
00042
00043
00044
00045
00046 class FFTJetPFPileupCleaner : public edm::EDProducer
00047 {
00048 public:
00049 explicit FFTJetPFPileupCleaner(const edm::ParameterSet&);
00050 ~FFTJetPFPileupCleaner();
00051
00052 protected:
00053
00054 void beginJob();
00055 void produce(edm::Event&, const edm::EventSetup&);
00056 void endJob();
00057
00058 private:
00059 FFTJetPFPileupCleaner();
00060 FFTJetPFPileupCleaner(const FFTJetPFPileupCleaner&);
00061 FFTJetPFPileupCleaner& operator=(const FFTJetPFPileupCleaner&);
00062
00063 bool isRemovable(reco::PFCandidate::ParticleType ptype) const;
00064 void setRemovalBit(reco::PFCandidate::ParticleType ptype, bool onOff);
00065 void buildRemovalMask();
00066 bool isAcceptableVtx(reco::VertexCollection::const_iterator iv) const;
00067
00068 reco::VertexRef findSomeVertexWFakes(
00069 const edm::Handle<reco::VertexCollection>& vertices,
00070 const edm::Handle<reco::VertexCollection>& fakeVertices,
00071 const reco::PFCandidate& pfcand, bool* fromFakeSet) const;
00072
00073 edm::InputTag PFCandidates;
00074 edm::InputTag Vertices;
00075 edm::InputTag FakePrimaryVertices;
00076
00077
00078
00079 bool useFakePrimaryVertex;
00080
00081
00082
00083 bool checkClosestZVertex;
00084
00085
00086
00087
00088
00089
00090 bool keepIfPVneighbor;
00091
00092
00093
00094 bool removeMainVertex;
00095
00096
00097
00098 bool removeUnassociated;
00099
00100
00101 bool reverseRemovalDecision;
00102
00103
00104
00105 bool remove_X;
00106 bool remove_h;
00107 bool remove_e;
00108 bool remove_mu;
00109 bool remove_gamma;
00110 bool remove_h0;
00111 bool remove_h_HF;
00112 bool remove_egamma_HF;
00113
00114
00115 unsigned removalMask;
00116
00117
00118 double etaMin;
00119 double etaMax;
00120
00121
00122 double vertexNdofCut;
00123
00124
00125 double vertexZmaxCut;
00126
00127
00128 mutable std::vector<std::pair<double, unsigned> > zAssoc;
00129 };
00130
00131
00132
00133
00134 FFTJetPFPileupCleaner::FFTJetPFPileupCleaner(const edm::ParameterSet& ps)
00135 : init_param(edm::InputTag, PFCandidates),
00136 init_param(edm::InputTag, Vertices),
00137 init_param(edm::InputTag, FakePrimaryVertices),
00138 init_param(bool, useFakePrimaryVertex),
00139 init_param(bool, checkClosestZVertex),
00140 init_param(bool, keepIfPVneighbor),
00141 init_param(bool, removeMainVertex),
00142 init_param(bool, removeUnassociated),
00143 init_param(bool, reverseRemovalDecision),
00144 init_param(bool, remove_X ),
00145 init_param(bool, remove_h ),
00146 init_param(bool, remove_e ),
00147 init_param(bool, remove_mu ),
00148 init_param(bool, remove_gamma ),
00149 init_param(bool, remove_h0 ),
00150 init_param(bool, remove_h_HF ),
00151 init_param(bool, remove_egamma_HF),
00152 removalMask(0),
00153 init_param(double, etaMin),
00154 init_param(double, etaMax),
00155 init_param(double, vertexNdofCut),
00156 init_param(double, vertexZmaxCut)
00157 {
00158 buildRemovalMask();
00159 produces<reco::PFCandidateCollection>();
00160 }
00161
00162
00163 FFTJetPFPileupCleaner::~FFTJetPFPileupCleaner()
00164 {
00165 }
00166
00167
00168 bool FFTJetPFPileupCleaner::isAcceptableVtx(
00169 reco::VertexCollection::const_iterator iv) const
00170 {
00171 return !iv->isFake() &&
00172 static_cast<double>(iv->ndof()) > vertexNdofCut &&
00173 std::abs(iv->z()) < vertexZmaxCut;
00174 }
00175
00176
00177
00178 void FFTJetPFPileupCleaner::produce(
00179 edm::Event& iEvent, const edm::EventSetup& iSetup)
00180 {
00181
00182 std::auto_ptr<reco::PFCandidateCollection>
00183 pOutput(new reco::PFCandidateCollection);
00184
00185 edm::Handle<reco::PFCandidateCollection> pfCandidates;
00186 iEvent.getByLabel(PFCandidates, pfCandidates);
00187
00188
00189 edm::Handle<reco::VertexCollection> vertices;
00190 iEvent.getByLabel(Vertices, vertices);
00191
00192 edm::Handle<reco::VertexCollection> fakeVertices;
00193 if (useFakePrimaryVertex)
00194 {
00195 iEvent.getByLabel(FakePrimaryVertices, fakeVertices);
00196 if (!fakeVertices.isValid())
00197 throw cms::Exception("FFTJetBadConfig")
00198 << "ERROR in FFTJetPFPileupCleaner:"
00199 " could not find fake vertices"
00200 << std::endl;
00201 }
00202
00203 const unsigned ncand = pfCandidates->size();
00204 for (unsigned i=0; i<ncand; ++i)
00205 {
00206 reco::PFCandidatePtr candptr(pfCandidates, i);
00207 bool remove = false;
00208
00209 if (isRemovable(candptr->particleId()))
00210 {
00211 bool fromFakeSet = false;
00212 reco::VertexRef vertexref(findSomeVertexWFakes(vertices, fakeVertices,
00213 *candptr, &fromFakeSet));
00214 if (vertexref.isNull())
00215 {
00216
00217
00218 remove = removeUnassociated;
00219 }
00220 else if (vertexref.key() == 0 &&
00221 (!useFakePrimaryVertex || fromFakeSet))
00222 {
00223
00224
00225
00226
00227
00228
00229 remove = removeMainVertex;
00230 }
00231 else
00232 remove = true;
00233 }
00234
00235
00236 if (!remove)
00237 {
00238 const double eta = candptr->p4().Eta();
00239 remove = eta < etaMin || eta > etaMax;
00240 }
00241
00242
00243 if (reverseRemovalDecision)
00244 remove = !remove;
00245 if (!remove)
00246 {
00247 const reco::PFCandidate& cand = (*pfCandidates)[i];
00248 pOutput->push_back(cand);
00249 pOutput->back().setSourceCandidatePtr(candptr);
00250 }
00251 }
00252
00253 iEvent.put(pOutput);
00254 }
00255
00256
00257 bool FFTJetPFPileupCleaner::isRemovable(
00258 const reco::PFCandidate::ParticleType ptype) const
00259 {
00260 const unsigned shift = static_cast<unsigned>(ptype);
00261 assert(shift < 32U);
00262 return removalMask & (1U << shift);
00263 }
00264
00265
00266 void FFTJetPFPileupCleaner::setRemovalBit(
00267 const reco::PFCandidate::ParticleType ptype, const bool value)
00268 {
00269 const unsigned shift = static_cast<unsigned>(ptype);
00270 assert(shift < 32U);
00271 const unsigned mask = (1U << shift);
00272 if (value)
00273 removalMask |= mask;
00274 else
00275 removalMask &= ~mask;
00276 }
00277
00278
00279
00280
00281
00282 reco::VertexRef FFTJetPFPileupCleaner::findSomeVertexWFakes(
00283 const edm::Handle<reco::VertexCollection>& vertices,
00284 const edm::Handle<reco::VertexCollection>& fakeVertices,
00285 const reco::PFCandidate& pfcand, bool* fromFakeSet) const
00286 {
00287 typedef reco::VertexCollection::const_iterator IV;
00288 typedef reco::Vertex::trackRef_iterator IT;
00289
00290 *fromFakeSet = false;
00291 reco::TrackBaseRef trackBaseRef(pfcand.trackRef());
00292
00293 size_t iVertex = 0;
00294 unsigned nFoundVertex = 0;
00295 const IV vertend(vertices->end());
00296
00297 {
00298 unsigned index = 0;
00299 double bestweight = 0.0;
00300 for (IV iv=vertices->begin(); iv!=vertend; ++iv, ++index)
00301 if (isAcceptableVtx(iv))
00302 {
00303 const reco::Vertex& vtx = *iv;
00304
00305
00306 IT trackend(vtx.tracks_end());
00307 for (IT iTrack=vtx.tracks_begin(); iTrack!=trackend; ++iTrack)
00308 {
00309 const reco::TrackBaseRef& baseRef = *iTrack;
00310
00311
00312
00313 if (baseRef == trackBaseRef)
00314 {
00315
00316 const double w = vtx.trackWeight(baseRef);
00317 if (w > bestweight)
00318 {
00319 bestweight=w;
00320 iVertex=index;
00321 nFoundVertex++;
00322 }
00323 }
00324 }
00325 }
00326 }
00327
00328 if (nFoundVertex > 0)
00329 {
00330 if (nFoundVertex != 1)
00331 edm::LogWarning("TrackOnTwoVertex")
00332 << "a track is shared by at least two vertices. "
00333 << "Used to be an assert";
00334
00335
00336
00337 if (useFakePrimaryVertex)
00338 {
00339 const double ztrack = pfcand.vertex().z();
00340 double dzmin = std::abs(ztrack - ((*vertices)[iVertex]).z());
00341
00342 const IV fakeEnd(fakeVertices->end());
00343 unsigned index = 0;
00344 for (IV iv=fakeVertices->begin(); iv!=fakeEnd; ++iv, ++index)
00345 if (isAcceptableVtx(iv))
00346 {
00347 const double dz = std::abs(ztrack - iv->z());
00348 if (dz < dzmin)
00349 {
00350 dzmin = dz;
00351 iVertex = index;
00352 *fromFakeSet = true;
00353 }
00354 }
00355 }
00356
00357 return reco::VertexRef(*fromFakeSet ? fakeVertices : vertices, iVertex);
00358 }
00359
00360
00361 if (checkClosestZVertex)
00362 {
00363 const double ztrack = pfcand.vertex().z();
00364 bool foundVertex = false;
00365
00366 if (keepIfPVneighbor)
00367 {
00368
00369 zAssoc.clear();
00370 unsigned index = 0;
00371 for (IV iv=vertices->begin(); iv!=vertend; ++iv, ++index)
00372 if (isAcceptableVtx(iv))
00373 zAssoc.push_back(std::pair<double,unsigned>(iv->z(), index));
00374 const unsigned numRealVertices = index;
00375
00376
00377
00378 if (useFakePrimaryVertex)
00379 {
00380 const IV fakeEnd(fakeVertices->end());
00381 for (IV iv=fakeVertices->begin(); iv!=fakeEnd; ++iv, ++index)
00382 if (isAcceptableVtx(iv))
00383 zAssoc.push_back(std::pair<double,unsigned>(iv->z(), index));
00384 }
00385
00386
00387 if (!zAssoc.empty())
00388 {
00389 std::sort(zAssoc.begin(), zAssoc.end());
00390 std::pair<double,unsigned> tPair(ztrack, UINT_MAX);
00391 const unsigned iAbove = std::upper_bound(
00392 zAssoc.begin(), zAssoc.end(), tPair) - zAssoc.begin();
00393
00394
00395
00396
00397
00398 unsigned ich[2] = {0U, 0U};
00399 unsigned nch = 1;
00400 if (iAbove)
00401 {
00402 ich[0] = iAbove - 1U;
00403 ich[1] = iAbove;
00404 if (iAbove < zAssoc.size())
00405 nch = 2;
00406 }
00407
00408 double dzmin = 1.0e100;
00409 unsigned bestVertexNum = UINT_MAX;
00410 for (unsigned icheck=0; icheck<nch; ++icheck)
00411 {
00412 const unsigned zAssocIndex = ich[icheck];
00413 const unsigned vertexNum = zAssoc[zAssocIndex].second;
00414
00415 if (vertexNum == numRealVertices ||
00416 (!useFakePrimaryVertex && vertexNum == 0U))
00417 {
00418 bestVertexNum = vertexNum;
00419 break;
00420 }
00421
00422 const double dz = std::abs(ztrack - zAssoc[zAssocIndex].first);
00423 if (dz < dzmin)
00424 {
00425 dzmin = dz;
00426 bestVertexNum = vertexNum;
00427 }
00428 }
00429
00430 foundVertex = bestVertexNum < UINT_MAX;
00431 if (foundVertex)
00432 {
00433 iVertex = bestVertexNum;
00434 if (iVertex >= numRealVertices)
00435 {
00436 *fromFakeSet = true;
00437 iVertex -= numRealVertices;
00438 }
00439 }
00440 }
00441 }
00442 else
00443 {
00444
00445
00446 double dzmin = 1.0e100;
00447 unsigned index = 0;
00448 for (IV iv=vertices->begin(); iv!=vertend; ++iv, ++index)
00449 if (isAcceptableVtx(iv))
00450 {
00451 const double dz = std::abs(ztrack - iv->z());
00452 if (dz < dzmin)
00453 {
00454 dzmin = dz;
00455 iVertex = index;
00456 foundVertex = true;
00457 }
00458 }
00459
00460 if (useFakePrimaryVertex)
00461 {
00462 const IV fakeEnd(fakeVertices->end());
00463 index = 0;
00464 for (IV iv=fakeVertices->begin(); iv!=fakeEnd; ++iv, ++index)
00465 if (isAcceptableVtx(iv))
00466 {
00467 const double dz = std::abs(ztrack - iv->z());
00468 if (dz < dzmin)
00469 {
00470 dzmin = dz;
00471 iVertex = index;
00472 *fromFakeSet = true;
00473 foundVertex = true;
00474 }
00475 }
00476 }
00477 }
00478
00479 if (foundVertex)
00480 return reco::VertexRef(*fromFakeSet ? fakeVertices : vertices, iVertex);
00481 }
00482
00483 return reco::VertexRef();
00484 }
00485
00486
00487 void FFTJetPFPileupCleaner::buildRemovalMask()
00488 {
00489 setRemovalBit(reco::PFCandidate::X, remove_X );
00490 setRemovalBit(reco::PFCandidate::h, remove_h );
00491 setRemovalBit(reco::PFCandidate::e, remove_e );
00492 setRemovalBit(reco::PFCandidate::mu, remove_mu );
00493 setRemovalBit(reco::PFCandidate::gamma, remove_gamma );
00494 setRemovalBit(reco::PFCandidate::h0, remove_h0 );
00495 setRemovalBit(reco::PFCandidate::h_HF, remove_h_HF );
00496 setRemovalBit(reco::PFCandidate::egamma_HF, remove_egamma_HF);
00497 }
00498
00499
00500
00501 void FFTJetPFPileupCleaner::beginJob()
00502 {
00503 }
00504
00505
00506
00507 void FFTJetPFPileupCleaner::endJob()
00508 {
00509 }
00510
00511
00512
00513 DEFINE_FWK_MODULE(FFTJetPFPileupCleaner);