File indexing completed on 2025-02-05 23:51:52
0001
0002
0003
0004
0005 #include <cmath>
0006 #include <cstdlib>
0007 #include <iostream>
0008
0009 #include "HepPDT/ParticleID.hh"
0010
0011 #include "SimTracker/TrackHistory/interface/VertexClassifier.h"
0012
0013 #define update(a, b) \
0014 do { \
0015 (a) = (a) || (b); \
0016 } while (0)
0017
0018 VertexClassifier::VertexClassifier(edm::ParameterSet const &config, edm::ConsumesCollector collector)
0019 : VertexCategories(),
0020 tracer_(config, collector),
0021 hepMCLabel_(config.getUntrackedParameter<edm::InputTag>("hepMC")),
0022 particleDataTableToken_(collector.esConsumes()) {
0023 collector.consumes<edm::HepMCProduct>(hepMCLabel_);
0024
0025 tracer_.depth(-2);
0026
0027
0028 longLivedDecayLength_ = config.getUntrackedParameter<double>("longLivedDecayLength");
0029
0030
0031 vertexClusteringDistance_ = config.getUntrackedParameter<double>("vertexClusteringDistance");
0032 }
0033
0034 void VertexClassifier::newEvent(edm::Event const &event, edm::EventSetup const &setup) {
0035
0036 tracer_.newEvent(event, setup);
0037
0038
0039 event.getByLabel(hepMCLabel_, mcInformation_);
0040
0041
0042 particleDataTable_ = setup.getHandle(particleDataTableToken_);
0043
0044
0045 genPrimaryVertices();
0046 }
0047
0048 void VertexClassifier::fillPSetDescription(edm::ParameterSetDescription &desc) {
0049 VertexHistory::fillPSetDescription(desc);
0050 desc.addUntracked<edm::InputTag>("hepMC", edm::InputTag("generatorSmeared"));
0051 desc.addUntracked<double>("longLivedDecayLength", 1e-14);
0052 desc.addUntracked<double>("vertexClusteringDistance", 0.003);
0053 }
0054
0055 VertexClassifier const &VertexClassifier::evaluate(reco::VertexBaseRef const &vertex) {
0056
0057 reset();
0058
0059
0060 if (tracer_.evaluate(vertex)) {
0061
0062 simulationInformation();
0063
0064
0065 processesAtGenerator();
0066
0067
0068 processesAtSimulation();
0069
0070
0071 vertexInformation();
0072
0073
0074 unknownVertex();
0075 } else
0076 flags_[Fake] = true;
0077
0078 return *this;
0079 }
0080
0081 VertexClassifier const &VertexClassifier::evaluate(TrackingVertexRef const &vertex) {
0082
0083 reset();
0084
0085
0086 tracer_.evaluate(vertex);
0087
0088
0089 if (tracer_.recoVertex().isNonnull())
0090 flags_[Reconstructed] = true;
0091 else
0092 flags_[Reconstructed] = false;
0093
0094
0095 simulationInformation();
0096
0097
0098 processesAtGenerator();
0099
0100
0101 processesAtSimulation();
0102
0103
0104 vertexInformation();
0105
0106
0107 unknownVertex();
0108
0109 return *this;
0110 }
0111
0112 void VertexClassifier::simulationInformation() {
0113
0114 EncodedEventId eventId = tracer_.simVertex()->eventId();
0115
0116 flags_[SignalEvent] = !eventId.bunchCrossing() && !eventId.event();
0117 }
0118
0119 void VertexClassifier::processesAtGenerator() {
0120
0121 VertexHistory::GenVertexTrail const &genVertexTrail = tracer_.genVertexTrail();
0122
0123
0124 for (VertexHistory::GenVertexTrail::const_iterator ivertex = genVertexTrail.begin(); ivertex != genVertexTrail.end();
0125 ++ivertex) {
0126
0127
0128 HepMC::GenVertex *vertex = const_cast<HepMC::GenVertex *>(*ivertex);
0129
0130
0131 for (HepMC::GenVertex::particle_iterator iparent = vertex->particles_begin(HepMC::parents);
0132 iparent != vertex->particles_end(HepMC::parents);
0133 ++iparent) {
0134
0135 int pdgid = std::abs((*iparent)->pdg_id());
0136
0137 HepPDT::ParticleID particleID(pdgid);
0138
0139
0140 if (particleID.isValid()) {
0141
0142 ParticleData const *particleData = particleDataTable_->particle(particleID);
0143
0144 if (particleData) {
0145
0146 if (particleData->lifetime() > longLivedDecayLength_) {
0147
0148 update(flags_[BWeakDecay], particleID.hasBottom());
0149 update(flags_[CWeakDecay], particleID.hasCharm());
0150 update(flags_[LongLivedDecay], true);
0151 }
0152
0153 update(flags_[TauDecay], pdgid == 15);
0154 update(flags_[KsDecay], pdgid == 310);
0155 update(flags_[LambdaDecay], pdgid == 3122);
0156 update(flags_[JpsiDecay], pdgid == 443);
0157 update(flags_[XiDecay], pdgid == 3312);
0158 update(flags_[OmegaDecay], pdgid == 3334);
0159 update(flags_[SigmaPlusDecay], pdgid == 3222);
0160 update(flags_[SigmaMinusDecay], pdgid == 3112);
0161 }
0162 }
0163 }
0164 }
0165 }
0166
0167 void VertexClassifier::processesAtSimulation() {
0168 VertexHistory::SimVertexTrail const &simVertexTrail = tracer_.simVertexTrail();
0169
0170 for (VertexHistory::SimVertexTrail::const_iterator ivertex = simVertexTrail.begin(); ivertex != simVertexTrail.end();
0171 ++ivertex) {
0172
0173 int pdgid = 0;
0174
0175
0176 bool flag = false;
0177 TrackingVertex::tp_iterator itd, its;
0178
0179 for (its = (*ivertex)->sourceTracks_begin(); its != (*ivertex)->sourceTracks_end(); ++its) {
0180 for (itd = (*ivertex)->daughterTracks_begin(); itd != (*ivertex)->daughterTracks_end(); ++itd)
0181 if (itd != its) {
0182 flag = true;
0183 break;
0184 }
0185 if (flag)
0186 break;
0187 }
0188
0189 if (its != (*ivertex)->sourceTracks_end())
0190 pdgid = std::abs((*its)->pdgId());
0191 else
0192 pdgid = 0;
0193
0194
0195
0196 unsigned int processG4 = 0;
0197
0198 if ((*ivertex)->nG4Vertices() > 0) {
0199 processG4 = (*(*ivertex)->g4Vertices_begin()).processType();
0200 }
0201
0202 unsigned int process = g4toCMSProcMap_.processId(processG4);
0203
0204
0205 update(flags_[KnownProcess], process != CMS::Undefined && process != CMS::Unknown && process != CMS::Primary);
0206
0207 update(flags_[UndefinedProcess], process == CMS::Undefined);
0208 update(flags_[UnknownProcess], process == CMS::Unknown);
0209 update(flags_[PrimaryProcess], process == CMS::Primary);
0210 update(flags_[HadronicProcess], process == CMS::Hadronic);
0211 update(flags_[DecayProcess], process == CMS::Decay);
0212 update(flags_[ComptonProcess], process == CMS::Compton);
0213 update(flags_[AnnihilationProcess], process == CMS::Annihilation);
0214 update(flags_[EIoniProcess], process == CMS::EIoni);
0215 update(flags_[HIoniProcess], process == CMS::HIoni);
0216 update(flags_[MuIoniProcess], process == CMS::MuIoni);
0217 update(flags_[PhotonProcess], process == CMS::Photon);
0218 update(flags_[MuPairProdProcess], process == CMS::MuPairProd);
0219 update(flags_[ConversionsProcess], process == CMS::Conversions);
0220 update(flags_[EBremProcess], process == CMS::EBrem);
0221 update(flags_[SynchrotronRadiationProcess], process == CMS::SynchrotronRadiation);
0222 update(flags_[MuBremProcess], process == CMS::MuBrem);
0223 update(flags_[MuNuclProcess], process == CMS::MuNucl);
0224
0225
0226 for (TrackingVertex::tp_iterator iparticle = (*ivertex)->daughterTracks_begin();
0227 iparticle != (*ivertex)->daughterTracks_end();
0228 ++iparticle) {
0229 if ((*iparticle)->numberOfTrackerLayers()) {
0230
0231 if (process == CMS::Decay) {
0232
0233 HepPDT::ParticleID particleID(pdgid);
0234
0235 if (particleID.isValid()) {
0236
0237 ParticleData const *particleData = particleDataTable_->particle(particleID);
0238
0239 if (particleData) {
0240
0241 if (particleDataTable_->particle(particleID)->lifetime() > longLivedDecayLength_) {
0242
0243 update(flags_[BWeakDecay], particleID.hasBottom());
0244 update(flags_[CWeakDecay], particleID.hasCharm());
0245 update(flags_[LongLivedDecay], true);
0246 }
0247
0248 update(flags_[TauDecay], pdgid == 15);
0249 update(flags_[KsDecay], pdgid == 310);
0250 update(flags_[LambdaDecay], pdgid == 3122);
0251 update(flags_[JpsiDecay], pdgid == 443);
0252 update(flags_[XiDecay], pdgid == 3312);
0253 update(flags_[OmegaDecay], pdgid == 3334);
0254 update(flags_[SigmaPlusDecay], pdgid == 3222);
0255 update(flags_[SigmaMinusDecay], pdgid == 3112);
0256 }
0257 }
0258 }
0259 }
0260 }
0261 }
0262 }
0263
0264 void VertexClassifier::vertexInformation() {
0265
0266 typedef std::multimap<double, HepMC::ThreeVector> Clusters;
0267 typedef std::pair<double, HepMC::ThreeVector> ClusterPair;
0268
0269 Clusters clusters;
0270
0271
0272 GeneratedPrimaryVertex const &genpv = genpvs_.back();
0273
0274
0275 const VertexHistory::GenVertexTrail &genVertexTrail = tracer_.genVertexTrail();
0276
0277
0278 double const mm = 0.1;
0279
0280
0281 for (VertexHistory::GenVertexTrail::const_iterator ivertex = genVertexTrail.begin(); ivertex != genVertexTrail.end();
0282 ++ivertex) {
0283
0284 if (*ivertex) {
0285
0286 HepMC::ThreeVector p = (*ivertex)->point3d();
0287 double distance =
0288 sqrt(pow(p.x() * mm - genpv.x, 2) + pow(p.y() * mm - genpv.y, 2) + pow(p.z() * mm - genpv.z, 2));
0289
0290
0291 if (clusters.empty()) {
0292 clusters.insert(ClusterPair(distance, HepMC::ThreeVector(p.x() * mm, p.y() * mm, p.z() * mm)));
0293 continue;
0294 }
0295
0296
0297
0298 Clusters::const_iterator icluster = clusters.lower_bound(distance - vertexClusteringDistance_);
0299
0300 if (icluster == clusters.upper_bound(distance + vertexClusteringDistance_)) {
0301 clusters.insert(ClusterPair(distance, HepMC::ThreeVector(p.x() * mm, p.y() * mm, p.z() * mm)));
0302 continue;
0303 }
0304
0305 bool cluster = false;
0306
0307
0308
0309 for (; icluster != clusters.upper_bound(distance + vertexClusteringDistance_); ++icluster) {
0310 double difference = sqrt(pow(p.x() * mm - icluster->second.x(), 2) + pow(p.y() * mm - icluster->second.y(), 2) +
0311 pow(p.z() * mm - icluster->second.z(), 2));
0312
0313 if (difference < vertexClusteringDistance_) {
0314 cluster = true;
0315 break;
0316 }
0317 }
0318
0319 if (!cluster)
0320 clusters.insert(ClusterPair(distance, HepMC::ThreeVector(p.x() * mm, p.y() * mm, p.z() * mm)));
0321 }
0322 }
0323
0324 const VertexHistory::SimVertexTrail &simVertexTrail = tracer_.simVertexTrail();
0325
0326
0327 for (VertexHistory::SimVertexTrail::const_reverse_iterator ivertex = simVertexTrail.rbegin();
0328 ivertex != simVertexTrail.rend();
0329 ++ivertex) {
0330
0331 TrackingVertex::LorentzVector p = (*ivertex)->position();
0332
0333 double distance = sqrt(pow(p.x() - genpv.x, 2) + pow(p.y() - genpv.y, 2) + pow(p.z() - genpv.z, 2));
0334
0335
0336 if (clusters.empty()) {
0337 clusters.insert(ClusterPair(distance, HepMC::ThreeVector(p.x(), p.y(), p.z())));
0338 continue;
0339 }
0340
0341
0342
0343 Clusters::const_iterator icluster = clusters.lower_bound(distance - vertexClusteringDistance_);
0344
0345 if (icluster == clusters.upper_bound(distance + vertexClusteringDistance_)) {
0346 clusters.insert(ClusterPair(distance, HepMC::ThreeVector(p.x(), p.y(), p.z())));
0347 continue;
0348 }
0349
0350 bool cluster = false;
0351
0352
0353 for (; icluster != clusters.upper_bound(distance + vertexClusteringDistance_); ++icluster) {
0354 double difference = sqrt(pow(p.x() - icluster->second.x(), 2) + pow(p.y() - icluster->second.y(), 2) +
0355 pow(p.z() - icluster->second.z(), 2));
0356
0357 if (difference < vertexClusteringDistance_) {
0358 cluster = true;
0359 break;
0360 }
0361 }
0362
0363 if (!cluster)
0364 clusters.insert(ClusterPair(distance, HepMC::ThreeVector(p.x(), p.y(), p.z())));
0365 }
0366
0367 if (clusters.size() == 1)
0368 flags_[PrimaryVertex] = true;
0369 else if (clusters.size() == 2)
0370 flags_[SecondaryVertex] = true;
0371 else
0372 flags_[TertiaryVertex] = true;
0373 }
0374
0375 bool VertexClassifier::isFinalstateParticle(const HepMC::GenParticle *p) {
0376 return !p->end_vertex() && p->status() == 1;
0377 }
0378
0379 bool VertexClassifier::isCharged(const HepMC::GenParticle *p) {
0380 const ParticleData *part = particleDataTable_->particle(p->pdg_id());
0381 if (part)
0382 return part->charge() != 0;
0383 else {
0384
0385 return particleDataTable_->particle(-p->pdg_id()) != nullptr;
0386 }
0387 }
0388
0389 void VertexClassifier::genPrimaryVertices() {
0390 genpvs_.clear();
0391
0392 const HepMC::GenEvent *event = mcInformation_->GetEvent();
0393
0394 if (event) {
0395
0396 for (HepMC::GenEvent::vertex_const_iterator ivertex = event->vertices_begin(); ivertex != event->vertices_end();
0397 ++ivertex) {
0398 bool hasParentVertex = false;
0399
0400
0401
0402 for (HepMC::GenVertex::particle_iterator iparent = (*ivertex)->particles_begin(HepMC::parents);
0403 iparent != (*ivertex)->particles_end(HepMC::parents);
0404 ++iparent)
0405 if ((*iparent)->production_vertex()) {
0406 hasParentVertex = true;
0407 break;
0408 }
0409
0410
0411 if (hasParentVertex)
0412 continue;
0413
0414
0415 HepMC::FourVector pos = (*ivertex)->position();
0416
0417 double const mm = 0.1;
0418
0419 GeneratedPrimaryVertex pv(pos.x() * mm, pos.y() * mm, pos.z() * mm);
0420
0421 std::vector<GeneratedPrimaryVertex>::iterator ientry = genpvs_.begin();
0422
0423
0424 for (; ientry != genpvs_.end(); ++ientry) {
0425 double distance = sqrt(pow(pv.x - ientry->x, 2) + pow(pv.y - ientry->y, 2) + pow(pv.z - ientry->z, 2));
0426 if (distance < vertexClusteringDistance_)
0427 break;
0428 }
0429
0430
0431 if (ientry == genpvs_.end())
0432 ientry = genpvs_.insert(ientry, pv);
0433
0434
0435 ientry->genVertex.push_back((*ivertex)->barcode());
0436
0437
0438 for (HepMC::GenVertex::particle_iterator idecendants = (*ivertex)->particles_begin(HepMC::descendants);
0439 idecendants != (*ivertex)->particles_end(HepMC::descendants);
0440 ++idecendants) {
0441 if (isFinalstateParticle(*idecendants))
0442 if (find(ientry->finalstateParticles.begin(), ientry->finalstateParticles.end(), (*idecendants)->barcode()) ==
0443 ientry->finalstateParticles.end()) {
0444 ientry->finalstateParticles.push_back((*idecendants)->barcode());
0445 HepMC::FourVector m = (*idecendants)->momentum();
0446
0447 ientry->ptot.setPx(ientry->ptot.px() + m.px());
0448 ientry->ptot.setPy(ientry->ptot.py() + m.py());
0449 ientry->ptot.setPz(ientry->ptot.pz() + m.pz());
0450 ientry->ptot.setE(ientry->ptot.e() + m.e());
0451 ientry->ptsq += m.perp() * m.perp();
0452
0453 if (m.perp() > 0.8 && std::abs(m.pseudoRapidity()) < 2.5 && isCharged(*idecendants))
0454 ientry->nGenTrk++;
0455 }
0456 }
0457 }
0458 }
0459
0460 std::sort(genpvs_.begin(), genpvs_.end());
0461 }