00001
00002
00003
00004
00005 #include <math.h>
00006 #include <cstdlib>
00007 #include <iostream>
00008
00009 #include "HepPDT/ParticleID.hh"
00010
00011 #include "SimTracker/TrackHistory/interface/VertexClassifier.h"
00012
00013
00014 #define update(a, b) do { (a) = (a) | (b); } while(0)
00015
00016
00017 VertexClassifier::VertexClassifier(edm::ParameterSet const & config) : VertexCategories(), tracer_(config),
00018 hepMCLabel_( config.getUntrackedParameter<edm::InputTag>("hepMC") )
00019 {
00020
00021 tracer_.depth(-2);
00022
00023
00024 longLivedDecayLength_ = config.getUntrackedParameter<double>("longLivedDecayLength");
00025
00026
00027 vertexClusteringDistance_ = config.getUntrackedParameter<double>("vertexClusteringDistance");
00028 }
00029
00030
00031 void VertexClassifier::newEvent(edm::Event const & event, edm::EventSetup const & setup)
00032 {
00033
00034 tracer_.newEvent(event, setup);
00035
00036
00037 event.getByLabel(hepMCLabel_, mcInformation_);
00038
00039
00040 setup.getData(particleDataTable_);
00041
00042
00043 genPrimaryVertices();
00044 }
00045
00046
00047 VertexClassifier const & VertexClassifier::evaluate (reco::VertexBaseRef const & vertex)
00048 {
00049
00050 reset();
00051
00052
00053 if ( tracer_.evaluate(vertex) )
00054 {
00055
00056 simulationInformation();
00057
00058
00059 processesAtGenerator();
00060
00061
00062 processesAtSimulation();
00063
00064
00065 vertexInformation();
00066
00067
00068 unknownVertex();
00069 }
00070 else
00071 flags_[Fake] = true;
00072
00073 return *this;
00074 }
00075
00076
00077 VertexClassifier const & VertexClassifier::evaluate (TrackingVertexRef const & vertex)
00078 {
00079
00080 reset();
00081
00082
00083 tracer_.evaluate(vertex);
00084
00085
00086 if ( tracer_.recoVertex().isNonnull() )
00087 flags_[Reconstructed] = true;
00088 else
00089 flags_[Reconstructed] = false;
00090
00091
00092 simulationInformation();
00093
00094
00095 processesAtGenerator();
00096
00097
00098 processesAtSimulation();
00099
00100
00101 vertexInformation();
00102
00103
00104 unknownVertex();
00105
00106 return *this;
00107 }
00108
00109
00110 void VertexClassifier::simulationInformation()
00111 {
00112
00113 EncodedEventId eventId = tracer_.simVertex()->eventId();
00114
00115 flags_[SignalEvent] = !eventId.bunchCrossing() && !eventId.event();
00116 }
00117
00118
00119 void VertexClassifier::processesAtGenerator()
00120 {
00121
00122 VertexHistory::GenVertexTrail const & genVertexTrail = tracer_.genVertexTrail();
00123
00124
00125 for (
00126 VertexHistory::GenVertexTrail::const_iterator ivertex = genVertexTrail.begin();
00127 ivertex != genVertexTrail.end();
00128 ++ivertex
00129 )
00130 {
00131
00132 HepMC::GenVertex * vertex = const_cast<HepMC::GenVertex *>(*ivertex);
00133
00134
00135 for (
00136 HepMC::GenVertex::particle_iterator iparent = vertex->particles_begin(HepMC::parents);
00137 iparent != vertex->particles_end(HepMC::parents);
00138 ++iparent
00139 )
00140 {
00141
00142 int pdgid = std::abs((*iparent)->pdg_id());
00143
00144 HepPDT::ParticleID particleID(pdgid);
00145
00146
00147 if (particleID.isValid())
00148 {
00149
00150 ParticleData const * particleData = particleDataTable_->particle(particleID);
00151
00152 if (particleData)
00153 {
00154
00155 if ( particleData->lifetime() > longLivedDecayLength_ )
00156 {
00157
00158 update(flags_[BWeakDecay], particleID.hasBottom());
00159 update(flags_[CWeakDecay], particleID.hasCharm());
00160 update(flags_[LongLivedDecay], true);
00161 }
00162
00163 update(flags_[TauDecay], pdgid == 15);
00164 update(flags_[KsDecay], pdgid == 310);
00165 update(flags_[LambdaDecay], pdgid == 3122);
00166 update(flags_[JpsiDecay], pdgid == 443);
00167 update(flags_[XiDecay], pdgid == 3312);
00168 update(flags_[OmegaDecay], pdgid == 3334);
00169 update(flags_[SigmaPlusDecay], pdgid == 3222);
00170 update(flags_[SigmaMinusDecay], pdgid == 3112);
00171 }
00172 }
00173 }
00174 }
00175 }
00176
00177
00178 void VertexClassifier::processesAtSimulation()
00179 {
00180 VertexHistory::SimVertexTrail const & simVertexTrail = tracer_.simVertexTrail();
00181
00182 for (
00183 VertexHistory::SimVertexTrail::const_iterator ivertex = simVertexTrail.begin();
00184 ivertex != simVertexTrail.end();
00185 ++ivertex
00186 )
00187 {
00188
00189 int pdgid = 0;
00190
00191
00192 bool flag = false;
00193 TrackingVertex::tp_iterator itd, its;
00194
00195 for (its = (*ivertex)->sourceTracks_begin(); its != (*ivertex)->sourceTracks_end(); ++its)
00196 {
00197 for (itd = (*ivertex)->daughterTracks_begin(); itd != (*ivertex)->daughterTracks_end(); ++itd)
00198 if (itd != its)
00199 {
00200 flag = true;
00201 break;
00202 }
00203 if (flag)
00204 break;
00205 }
00206
00207 if ( its != (*ivertex)->sourceTracks_end() )
00208 pdgid = std::abs((*its)->pdgId());
00209 else
00210 pdgid = 0;
00211
00212
00213 for (
00214 TrackingVertex::tp_iterator iparticle = (*ivertex)->daughterTracks_begin();
00215 iparticle != (*ivertex)->daughterTracks_end();
00216 ++iparticle
00217 )
00218 {
00219
00220 if ( (*iparticle)->matchedHit() )
00221 {
00222
00223 unsigned short process = (*iparticle)->pSimHit_begin()->processType();
00224
00225
00226
00227 update(
00228 flags_[KnownProcess],
00229 process != G4::Undefined &&
00230 process != G4::Unknown &&
00231 process != G4::Primary
00232 );
00233
00234 update(flags_[UndefinedProcess], process == G4::Undefined);
00235 update(flags_[UnknownProcess], process == G4::Unknown);
00236 update(flags_[PrimaryProcess], process == G4::Primary);
00237 update(flags_[HadronicProcess], process == G4::Hadronic);
00238 update(flags_[DecayProcess], process == G4::Decay);
00239 update(flags_[ComptonProcess], process == G4::Compton);
00240 update(flags_[AnnihilationProcess], process == G4::Annihilation);
00241 update(flags_[EIoniProcess], process == G4::EIoni);
00242 update(flags_[HIoniProcess], process == G4::HIoni);
00243 update(flags_[MuIoniProcess], process == G4::MuIoni);
00244 update(flags_[PhotonProcess], process == G4::Photon);
00245 update(flags_[MuPairProdProcess], process == G4::MuPairProd);
00246 update(flags_[ConversionsProcess], process == G4::Conversions);
00247 update(flags_[EBremProcess], process == G4::EBrem);
00248 update(flags_[SynchrotronRadiationProcess], process == G4::SynchrotronRadiation);
00249 update(flags_[MuBremProcess], process == G4::MuBrem);
00250 update(flags_[MuNuclProcess], process == G4::MuNucl);
00251
00252
00253 if (process == G4::Decay)
00254 {
00255
00256 HepPDT::ParticleID particleID(pdgid);
00257
00258 if (particleID.isValid())
00259 {
00260
00261 ParticleData const * particleData = particleDataTable_->particle(particleID);
00262
00263 if (particleData)
00264 {
00265
00266 if ( particleDataTable_->particle(particleID)->lifetime() > longLivedDecayLength_ )
00267 {
00268
00269 update(flags_[BWeakDecay], particleID.hasBottom());
00270 update(flags_[CWeakDecay], particleID.hasCharm());
00271 update(flags_[LongLivedDecay], true);
00272 }
00273
00274 update(flags_[TauDecay], pdgid == 15);
00275 update(flags_[KsDecay], pdgid == 310);
00276 update(flags_[LambdaDecay], pdgid == 3122);
00277 update(flags_[JpsiDecay], pdgid == 443);
00278 update(flags_[XiDecay], pdgid == 3312);
00279 update(flags_[OmegaDecay], pdgid == 3334);
00280 update(flags_[SigmaPlusDecay], pdgid == 3222);
00281 update(flags_[SigmaMinusDecay], pdgid == 3112);
00282 }
00283 }
00284 }
00285 }
00286 }
00287 }
00288 }
00289
00290
00291 void VertexClassifier::vertexInformation()
00292 {
00293
00294 typedef std::multimap<double, HepMC::ThreeVector> Clusters;
00295 typedef std::pair<double, HepMC::ThreeVector> ClusterPair;
00296
00297 Clusters clusters;
00298
00299
00300 GeneratedPrimaryVertex const & genpv = genpvs_.back();
00301
00302
00303 VertexHistory::GenVertexTrail & genVertexTrail = const_cast<VertexHistory::GenVertexTrail &> (tracer_.genVertexTrail());
00304
00305
00306 double const mm = 0.1;
00307
00308
00309 for (
00310 VertexHistory::GenVertexTrail::const_iterator ivertex = genVertexTrail.begin();
00311 ivertex != genVertexTrail.end();
00312 ++ivertex
00313 )
00314 {
00315
00316 if (*ivertex)
00317 {
00318
00319 HepMC::ThreeVector p = (*ivertex)->point3d();
00320 double distance = sqrt( pow(p.x() * mm - genpv.x, 2) + pow(p.y() * mm - genpv.y, 2) + pow(p.z() * mm - genpv.z, 2) );
00321
00322
00323 if ( clusters.empty() )
00324 {
00325 clusters.insert( ClusterPair(distance, HepMC::ThreeVector(p.x() * mm, p.y() * mm, p.z() * mm)) );
00326 continue;
00327 }
00328
00329
00330 Clusters::const_iterator icluster = clusters.lower_bound(distance - vertexClusteringDistance_);
00331
00332 if ( icluster == clusters.upper_bound(distance + vertexClusteringDistance_) )
00333 {
00334 clusters.insert ( ClusterPair(distance, HepMC::ThreeVector(p.x() * mm, p.y() * mm, p.z() * mm)) );
00335 continue;
00336 }
00337
00338 bool cluster = false;
00339
00340
00341 for (;
00342 icluster != clusters.upper_bound(distance + vertexClusteringDistance_);
00343 ++icluster
00344 )
00345 {
00346 double difference = sqrt (
00347 pow(p.x() * mm - icluster->second.x(), 2) +
00348 pow(p.y() * mm - icluster->second.y(), 2) +
00349 pow(p.z() * mm - icluster->second.z(), 2)
00350 );
00351
00352 if ( difference < vertexClusteringDistance_ )
00353 {
00354 cluster = true;
00355 break;
00356 }
00357 }
00358
00359 if (!cluster) clusters.insert ( ClusterPair(distance, HepMC::ThreeVector(p.x() * mm, p.y() * mm, p.z() * mm)) );
00360 }
00361 }
00362
00363 VertexHistory::SimVertexTrail & simVertexTrail = const_cast<VertexHistory::SimVertexTrail &> (tracer_.simVertexTrail());
00364
00365
00366 for (
00367 VertexHistory::SimVertexTrail::reverse_iterator ivertex = simVertexTrail.rbegin();
00368 ivertex != simVertexTrail.rend();
00369 ++ivertex
00370 )
00371 {
00372
00373 TrackingVertex::LorentzVector p = (*ivertex)->position();
00374
00375 double distance = sqrt( pow(p.x() - genpv.x, 2) + pow(p.y() - genpv.y, 2) + pow(p.z() - genpv.z, 2) );
00376
00377
00378 if ( clusters.empty() )
00379 {
00380 clusters.insert( ClusterPair(distance, HepMC::ThreeVector(p.x(), p.y(), p.z())) );
00381 continue;
00382 }
00383
00384
00385 Clusters::const_iterator icluster = clusters.lower_bound(distance - vertexClusteringDistance_);
00386
00387 if ( icluster == clusters.upper_bound(distance + vertexClusteringDistance_) )
00388 {
00389 clusters.insert ( ClusterPair(distance, HepMC::ThreeVector(p.x(), p.y(), p.z())) );
00390 continue;
00391 }
00392
00393 bool cluster = false;
00394
00395
00396 for (;
00397 icluster != clusters.upper_bound(distance + vertexClusteringDistance_);
00398 ++icluster
00399 )
00400 {
00401 double difference = sqrt (
00402 pow(p.x() - icluster->second.x(), 2) +
00403 pow(p.y() - icluster->second.y(), 2) +
00404 pow(p.z() - icluster->second.z(), 2)
00405 );
00406
00407 if ( difference < vertexClusteringDistance_ )
00408 {
00409 cluster = true;
00410 break;
00411 }
00412 }
00413
00414 if (!cluster) clusters.insert ( ClusterPair(distance, HepMC::ThreeVector(p.x(), p.y(), p.z())) );
00415 }
00416
00417 if ( clusters.size() == 1 )
00418 flags_[PrimaryVertex] = true;
00419 else if ( clusters.size() == 2 )
00420 flags_[SecondaryVertex] = true;
00421 else
00422 flags_[TertiaryVertex] = true;
00423 }
00424
00425
00426 bool VertexClassifier::isFinalstateParticle(const HepMC::GenParticle * p)
00427 {
00428 return !p->end_vertex() && p->status() == 1;
00429 }
00430
00431
00432 bool VertexClassifier::isCharged(const HepMC::GenParticle * p)
00433 {
00434 const ParticleData * part = particleDataTable_->particle( p->pdg_id() );
00435 if (part)
00436 return part->charge()!=0;
00437 else
00438 {
00439
00440 return particleDataTable_->particle( -p->pdg_id() ) != 0;
00441 }
00442 }
00443
00444
00445 void VertexClassifier::genPrimaryVertices()
00446 {
00447 genpvs_.clear();
00448
00449 const HepMC::GenEvent * event = mcInformation_->GetEvent();
00450
00451 if (event)
00452 {
00453 int idx = 0;
00454
00455
00456 for ( HepMC::GenEvent::vertex_const_iterator ivertex = event->vertices_begin(); ivertex != event->vertices_end(); ++ivertex )
00457 {
00458 bool hasParentVertex = false;
00459
00460
00461 for (
00462 HepMC::GenVertex::particle_iterator iparent = (*ivertex)->particles_begin(HepMC::parents);
00463 iparent != (*ivertex)->particles_end(HepMC::parents);
00464 ++iparent
00465 )
00466 if ( (*iparent)->production_vertex() )
00467 {
00468 hasParentVertex = true;
00469 break;
00470 }
00471
00472
00473 if (hasParentVertex) continue;
00474
00475
00476 HepMC::FourVector pos = (*ivertex)->position();
00477
00478 double const mm = 0.1;
00479
00480 GeneratedPrimaryVertex pv(pos.x()*mm, pos.y()*mm, pos.z()*mm);
00481
00482 std::vector<GeneratedPrimaryVertex>::iterator ientry = genpvs_.begin();
00483
00484
00485 for (; ientry != genpvs_.end(); ++ientry)
00486 {
00487 double distance = sqrt( pow(pv.x - ientry->x, 2) + pow(pv.y - ientry->y, 2) + pow(pv.z - ientry->z, 2) );
00488 if ( distance < vertexClusteringDistance_ )
00489 break;
00490 }
00491
00492
00493 if (ientry == genpvs_.end())
00494 ientry = genpvs_.insert(ientry,pv);
00495
00496
00497 ientry->genVertex.push_back((*ivertex)->barcode());
00498
00499
00500 for (
00501 HepMC::GenVertex::particle_iterator idecendants = (*ivertex)->particles_begin(HepMC::descendants);
00502 idecendants != (*ivertex)->particles_end(HepMC::descendants);
00503 ++idecendants
00504 )
00505 {
00506 if (isFinalstateParticle(*idecendants))
00507 if ( find(ientry->finalstateParticles.begin(), ientry->finalstateParticles.end(), (*idecendants)->barcode()) == ientry->finalstateParticles.end() )
00508 {
00509 ientry->finalstateParticles.push_back((*idecendants)->barcode());
00510 HepMC::FourVector m = (*idecendants)->momentum();
00511
00512 ientry->ptot.setPx(ientry->ptot.px() + m.px());
00513 ientry->ptot.setPy(ientry->ptot.py() + m.py());
00514 ientry->ptot.setPz(ientry->ptot.pz() + m.pz());
00515 ientry->ptot.setE(ientry->ptot.e() + m.e());
00516 ientry->ptsq += m.perp() * m.perp();
00517
00518 if ( m.perp() > 0.8 && std::abs(m.pseudoRapidity()) < 2.5 && isCharged(*idecendants) ) ientry->nGenTrk++;
00519 }
00520 }
00521 idx++;
00522 }
00523 }
00524
00525 std::sort(genpvs_.begin(), genpvs_.end());
00526 }