00001
00002 #include <math.h>
00003 #include <cstdlib>
00004 #include <iostream>
00005
00006 #include "HepPDT/ParticleID.hh"
00007
00008 #include "SimTracker/TrackHistory/interface/TrackClassifier.h"
00009
00010 #define update(a, b) do { (a) = (a) | (b); } while(0)
00011
00012 TrackClassifier::TrackClassifier(edm::ParameterSet const & config) : TrackCategories(),
00013 hepMCLabel_( config.getUntrackedParameter<edm::InputTag>("hepMC") ),
00014 beamSpotLabel_( config.getUntrackedParameter<edm::InputTag>("beamSpot") ),
00015 tracer_(config),
00016 quality_(config)
00017 {
00018
00019 tracer_.depth(-2);
00020
00021
00022 badPull_ = config.getUntrackedParameter<double>("badPull");
00023
00024
00025 longLivedDecayLength_ = config.getUntrackedParameter<double>("longLivedDecayLength");
00026
00027
00028 float vertexClusteringDistance = config.getUntrackedParameter<double>("vertexClusteringDistance");
00029 vertexClusteringSqDistance_ = vertexClusteringDistance * vertexClusteringDistance;
00030
00031
00032 numberOfInnerLayers_ = config.getUntrackedParameter<unsigned int>("numberOfInnerLayers");
00033
00034
00035 minTrackerSimHits_ = config.getUntrackedParameter<unsigned int>("minTrackerSimHits");
00036 }
00037
00038
00039 void TrackClassifier::newEvent ( edm::Event const & event, edm::EventSetup const & setup )
00040 {
00041
00042 tracer_.newEvent(event, setup);
00043
00044
00045 quality_.newEvent(event, setup);
00046
00047
00048 event.getByLabel(hepMCLabel_, mcInformation_);
00049
00050
00051 setup.get<IdealMagneticFieldRecord>().get(magneticField_);
00052
00053
00054 setup.getData(particleDataTable_);
00055
00056
00057 event.getByLabel(beamSpotLabel_, beamSpot_);
00058
00059
00060 setup.get<TransientTrackRecord>().get("TransientTrackBuilder", transientTrackBuilder_);
00061
00062
00063 genPrimaryVertices();
00064 }
00065
00066
00067 TrackClassifier const & TrackClassifier::evaluate (reco::TrackBaseRef const & track)
00068 {
00069
00070 reset();
00071
00072
00073 if ( tracer_.evaluate(track) )
00074 {
00075
00076 reconstructionInformation(track);
00077
00078
00079 simulationInformation();
00080
00081
00082 qualityInformation(track);
00083
00084
00085 hadronFlavor();
00086
00087
00088 processesAtGenerator();
00089
00090
00091 processesAtSimulation();
00092
00093
00094 vertexInformation();
00095
00096
00097 unknownTrack();
00098 }
00099 else
00100 flags_[Fake] = true;
00101
00102 return *this;
00103 }
00104
00105
00106 TrackClassifier const & TrackClassifier::evaluate (TrackingParticleRef const & track)
00107 {
00108
00109 reset();
00110
00111
00112 tracer_.evaluate(track);
00113
00114
00115 const reco::TrackBaseRef & recotrack = tracer_.recoTrack();
00116
00117
00118 if ( recotrack.isNonnull() )
00119 {
00120 flags_[Reconstructed] = true;
00121
00122 reconstructionInformation(recotrack);
00123
00124 qualityInformation(recotrack);
00125 }
00126 else
00127 flags_[Reconstructed] = false;
00128
00129
00130 simulationInformation();
00131
00132
00133 hadronFlavor();
00134
00135
00136 processesAtGenerator();
00137
00138
00139 processesAtSimulation();
00140
00141
00142 vertexInformation();
00143
00144
00145 unknownTrack();
00146
00147 return *this;
00148 }
00149
00150
00151 void TrackClassifier::reconstructionInformation(reco::TrackBaseRef const & track)
00152 {
00153 TrackingParticleRef tpr = tracer_.simParticle();
00154
00155
00156
00157 const SimTrack * assocTrack = &(*tpr->g4Track_begin());
00158
00159 FreeTrajectoryState ftsAtProduction(
00160 GlobalPoint(
00161 tpr->vertex().x(),
00162 tpr->vertex().y(),
00163 tpr->vertex().z()
00164 ),
00165 GlobalVector(
00166 assocTrack->momentum().x(),
00167 assocTrack->momentum().y(),
00168 assocTrack->momentum().z()
00169 ),
00170 TrackCharge(track->charge()),
00171 magneticField_.product()
00172 );
00173
00174 try
00175 {
00176 TSCPBuilderNoMaterial tscpBuilder;
00177 TrajectoryStateClosestToPoint tsAtClosestApproach = tscpBuilder(
00178 ftsAtProduction,
00179 GlobalPoint(beamSpot_->x0(), beamSpot_->y0(), beamSpot_->z0())
00180 );
00181
00182 GlobalVector v = tsAtClosestApproach.theState().position()
00183 - GlobalPoint(beamSpot_->x0(), beamSpot_->y0(), beamSpot_->z0());
00184 GlobalVector p = tsAtClosestApproach.theState().momentum();
00185
00186
00187 double dxySim = -v.x()*sin(p.phi()) + v.y()*cos(p.phi());
00188
00189
00190 double dzSim = v.z() - (v.x()*p.x() + v.y()*p.y())*p.z()/p.perp2();
00191
00192
00193 double dxyPull = std::abs(
00194 track->dxy( reco::TrackBase::Point(beamSpot_->x0(), beamSpot_->y0(), beamSpot_->z0()) ) - dxySim
00195 ) / track->dxyError();
00196
00197
00198 double dzPull = std::abs(
00199 track->dz( reco::TrackBase::Point(beamSpot_->x0(), beamSpot_->y0(), beamSpot_->z0()) ) - dzSim
00200 ) / track->dzError();
00201
00202
00203 flags_[Bad] = (dxyPull > badPull_ || dzPull > badPull_);
00204
00205 }
00206 catch (cms::Exception exception)
00207 {
00208 flags_[Bad] = true;
00209 }
00210 }
00211
00212
00213 void TrackClassifier::simulationInformation()
00214 {
00215
00216 EncodedEventId eventId = tracer_.simParticle()->eventId();
00217
00218 flags_[SignalEvent] = !eventId.bunchCrossing() && !eventId.event();
00219
00220 flags_[Muon] = (abs(tracer_.simParticle()->pdgId()) == 13);
00221
00222 flags_[TrackerSimHits] = tracer_.simParticle()->matchedHit() >= (int)minTrackerSimHits_;
00223 }
00224
00225
00226 void TrackClassifier::qualityInformation(reco::TrackBaseRef const & track)
00227 {
00228
00229 quality_.evaluate(tracer_.simParticleTrail(), track);
00230
00231 unsigned int maxLayers = std::min(numberOfInnerLayers_, quality_.numberOfLayers());
00232
00233
00234 for (unsigned int i = 0; i < maxLayers; i++)
00235 {
00236 const TrackQuality::Layer &layer = quality_.layer(i);
00237
00238
00239 for (unsigned int j = 0; j < layer.hits.size(); j++)
00240 {
00241 const TrackQuality::Layer::Hit &hit = layer.hits[j];
00242
00243
00244 if (hit.state == TrackQuality::Layer::Noise ||
00245 hit.state == TrackQuality::Layer::Misassoc)
00246 flags_[BadInnerHits] = true;
00247 else if (hit.state == TrackQuality::Layer::Shared)
00248 flags_[SharedInnerHits] = true;
00249 }
00250 }
00251 }
00252
00253
00254 void TrackClassifier::hadronFlavor()
00255 {
00256
00257 const HepMC::GenParticle * particle = tracer_.genParticle();
00258
00259
00260 if (particle)
00261 {
00262 HepPDT::ParticleID pid(particle->pdg_id());
00263 flags_[Bottom] = pid.hasBottom();
00264 flags_[Charm] = pid.hasCharm();
00265 flags_[Light] = !pid.hasCharm() && !pid.hasBottom();
00266 }
00267 }
00268
00269
00270 void TrackClassifier::processesAtGenerator()
00271 {
00272
00273 int pdgid = 0;
00274
00275
00276 TrackHistory::GenParticleTrail const & genParticleTrail = tracer_.genParticleTrail();
00277
00278
00279 for (TrackHistory::GenParticleTrail::const_iterator iparticle = genParticleTrail.begin(); iparticle != genParticleTrail.end(); ++iparticle)
00280 {
00281
00282 HepMC::GenVertex * productionVertex = (*iparticle)->production_vertex();
00283
00284
00285
00286
00287
00288 if (productionVertex)
00289 {
00290
00291 if ( productionVertex->particles_in_size() == 1 )
00292 {
00293
00294 pdgid = std::abs((*productionVertex->particles_in_const_begin())->pdg_id());
00295
00296 HepPDT::ParticleID particleID(pdgid);
00297
00298
00299 if (particleID.isValid())
00300 {
00301
00302 ParticleData const * particleData = particleDataTable_->particle(particleID);
00303
00304 if (particleData)
00305 {
00306
00307 if ( particleData->lifetime() > longLivedDecayLength_ )
00308 update(flags_[LongLivedDecay], true);
00309
00310 update(flags_[BWeakDecay], particleID.hasBottom());
00311 update(flags_[CWeakDecay], particleID.hasCharm());
00312
00313 int daughterId = abs((*iparticle)->pdg_id());
00314 update(flags_[FromBWeakDecayMuon], particleID.hasBottom() && daughterId == 13);
00315 update(flags_[FromCWeakDecayMuon], particleID.hasCharm() && daughterId == 13);
00316 }
00317
00318 update(flags_[ChargePionDecay], pdgid == 211);
00319 update(flags_[ChargeKaonDecay], pdgid == 321);
00320 update(flags_[TauDecay], pdgid == 15);
00321 update(flags_[KsDecay], pdgid == 310);
00322 update(flags_[LambdaDecay], pdgid == 3122);
00323 update(flags_[JpsiDecay], pdgid == 443);
00324 update(flags_[XiDecay], pdgid == 3312);
00325 update(flags_[SigmaPlusDecay], pdgid == 3222);
00326 update(flags_[SigmaMinusDecay], pdgid == 3112);
00327 }
00328 }
00329 }
00330 }
00331
00332 update(flags_[FromChargePionMuon], flags_[Muon] && flags_[ChargePionDecay]);
00333 update(flags_[FromChargeKaonMuon], flags_[Muon] && flags_[ChargeKaonDecay]);
00334 update(flags_[DecayOnFlightMuon], (flags_[FromChargePionMuon] || flags_[FromChargeKaonMuon]));
00335 }
00336
00337
00338 void TrackClassifier::processesAtSimulation()
00339 {
00340 TrackHistory::SimParticleTrail const & simParticleTrail = tracer_.simParticleTrail();
00341
00342
00343 for (
00344 TrackHistory::SimParticleTrail::const_iterator iparticle = simParticleTrail.begin();
00345 iparticle != simParticleTrail.end();
00346 ++iparticle
00347 )
00348 {
00349
00350 int pdgid = 0;
00351
00352
00353 TrackingVertexRef const & parentVertex = (*iparticle)->parentVertex();
00354
00355
00356 if ( parentVertex.isNonnull() )
00357 {
00358
00359 bool flag = false;
00360 TrackingVertex::tp_iterator itd, its;
00361
00362 for (its = parentVertex->sourceTracks_begin(); its != parentVertex->sourceTracks_end(); ++its)
00363 {
00364 for (itd = parentVertex->daughterTracks_begin(); itd != parentVertex->daughterTracks_end(); ++itd)
00365 if (itd != its)
00366 {
00367 flag = true;
00368 break;
00369 }
00370 if (flag)
00371 break;
00372 }
00373
00374
00375 if ( its != parentVertex->sourceTracks_end() )
00376 pdgid = std::abs((*its)->pdgId());
00377 else
00378 pdgid = 0;
00379 }
00380
00381
00382 if ((*iparticle)->trackPSimHit().empty()) continue;
00383
00384
00385 unsigned short process = (*iparticle)->pSimHit_begin()->processType();
00386
00387
00388
00389 update(
00390 flags_[KnownProcess],
00391 process != G4::Undefined &&
00392 process != G4::Unknown &&
00393 process != G4::Primary
00394 );
00395
00396 update(flags_[UndefinedProcess], process == G4::Undefined);
00397 update(flags_[UnknownProcess], process == G4::Unknown);
00398 update(flags_[PrimaryProcess], process == G4::Primary);
00399 update(flags_[HadronicProcess], process == G4::Hadronic);
00400 update(flags_[DecayProcess], process == G4::Decay);
00401 update(flags_[ComptonProcess], process == G4::Compton);
00402 update(flags_[AnnihilationProcess], process == G4::Annihilation);
00403 update(flags_[EIoniProcess], process == G4::EIoni);
00404 update(flags_[HIoniProcess], process == G4::HIoni);
00405 update(flags_[MuIoniProcess], process == G4::MuIoni);
00406 update(flags_[PhotonProcess], process == G4::Photon);
00407 update(flags_[MuPairProdProcess], process == G4::MuPairProd);
00408 update(flags_[ConversionsProcess], process == G4::Conversions);
00409 update(flags_[EBremProcess], process == G4::EBrem);
00410 update(flags_[SynchrotronRadiationProcess], process == G4::SynchrotronRadiation);
00411 update(flags_[MuBremProcess], process == G4::MuBrem);
00412 update(flags_[MuNuclProcess], process == G4::MuNucl);
00413
00414
00415 HepPDT::ParticleID particleID(pdgid);
00416
00417
00418 if (particleID.isValid())
00419 {
00420
00421 ParticleData const * particleData = particleDataTable_->particle(particleID);
00422
00423 if (process == G4::Decay)
00424 {
00425
00426 if (particleData)
00427 {
00428
00429 if ( particleDataTable_->particle(particleID)->lifetime() > longLivedDecayLength_ )
00430 update(flags_[LongLivedDecay], true);
00431
00432
00433 update(flags_[BWeakDecay], particleID.hasBottom());
00434 update(flags_[CWeakDecay], particleID.hasCharm());
00435
00436
00437 int daughtId = abs((*iparticle)->pdgId());
00438 update(flags_[FromBWeakDecayMuon], particleID.hasBottom() && daughtId == 13);
00439 update(flags_[FromCWeakDecayMuon], particleID.hasCharm() && daughtId == 13);
00440 }
00441
00442 update(flags_[ChargePionDecay], pdgid == 211);
00443 update(flags_[ChargeKaonDecay], pdgid == 321);
00444 update(flags_[TauDecay], pdgid == 15);
00445 update(flags_[KsDecay], pdgid == 310);
00446 update(flags_[LambdaDecay], pdgid == 3122);
00447 update(flags_[JpsiDecay], pdgid == 443);
00448 update(flags_[XiDecay], pdgid == 3312);
00449 update(flags_[OmegaDecay], pdgid == 3334);
00450 update(flags_[SigmaPlusDecay], pdgid == 3222);
00451 update(flags_[SigmaMinusDecay], pdgid == 3112);
00452 }
00453 }
00454 }
00455
00456 update(flags_[FromChargePionMuon], flags_[Muon] && flags_[ChargePionDecay]);
00457 update(flags_[FromChargeKaonMuon], flags_[Muon] && flags_[ChargeKaonDecay]);
00458 update(flags_[DecayOnFlightMuon], flags_[FromChargePionMuon] || flags_[FromChargeKaonMuon]);
00459 }
00460
00461
00462 void TrackClassifier::vertexInformation()
00463 {
00464
00465 GeneratedPrimaryVertex const & genpv = genpvs_.back();
00466
00467
00468 TrackHistory::GenParticleTrail & genParticleTrail = const_cast<TrackHistory::GenParticleTrail &> (tracer_.genParticleTrail());
00469
00470
00471 int counter = 0;
00472
00473
00474 double const mm = 0.1;
00475
00476 double oldX = genpv.x;
00477 double oldY = genpv.y;
00478 double oldZ = genpv.z;
00479
00480
00481 for (
00482 TrackHistory::GenParticleTrail::reverse_iterator iparticle = genParticleTrail.rbegin();
00483 iparticle != genParticleTrail.rend();
00484 ++iparticle
00485 )
00486 {
00487
00488 HepMC::GenVertex * parent = (*iparticle)->production_vertex();
00489 if (parent)
00490 {
00491 HepMC::ThreeVector p = parent->point3d();
00492
00493 double distance2 = pow(p.x() * mm - genpv.x, 2) + pow(p.y() * mm - genpv.y, 2) + pow(p.z() * mm - genpv.z, 2);
00494 double difference2 = pow(p.x() * mm - oldX, 2) + pow(p.y() * mm - oldY, 2) + pow(p.z() * mm - oldZ, 2);
00495
00496
00497
00498
00499 if ( difference2 > vertexClusteringSqDistance_ )
00500 {
00501 if ( distance2 > vertexClusteringSqDistance_ ) counter++;
00502 oldX = p.x() * mm;
00503 oldY = p.y() * mm;
00504 oldZ = p.z() * mm;
00505 }
00506 }
00507 }
00508
00509 TrackHistory::SimParticleTrail & simParticleTrail = const_cast<TrackHistory::SimParticleTrail &> (tracer_.simParticleTrail());
00510
00511
00512 for (
00513 TrackHistory::SimParticleTrail::reverse_iterator iparticle = simParticleTrail.rbegin();
00514 iparticle != simParticleTrail.rend();
00515 ++iparticle
00516 )
00517 {
00518
00519 TrackingParticle::Point p = (*iparticle)->vertex();
00520
00521 double distance2 = pow(p.x() - genpv.x, 2) + pow(p.y() - genpv.y, 2) + pow(p.z() - genpv.z, 2);
00522 double difference2 = pow(p.x() - oldX, 2) + pow(p.y() - oldY, 2) + pow(p.z() - oldZ, 2);
00523
00524
00525
00526
00527 if ( difference2 > vertexClusteringSqDistance_ )
00528 {
00529 if ( distance2 > vertexClusteringSqDistance_ ) counter++;
00530 oldX = p.x();
00531 oldY = p.y();
00532 oldZ = p.z();
00533 }
00534 }
00535
00536 if ( !counter )
00537 flags_[PrimaryVertex] = true;
00538 else if ( counter == 1 )
00539 flags_[SecondaryVertex] = true;
00540 else
00541 flags_[TertiaryVertex] = true;
00542 }
00543
00544
00545 bool TrackClassifier::isFinalstateParticle(const HepMC::GenParticle * p)
00546 {
00547 return !p->end_vertex() && p->status() == 1;
00548 }
00549
00550
00551 bool TrackClassifier::isCharged(const HepMC::GenParticle * p)
00552 {
00553 const ParticleData * part = particleDataTable_->particle( p->pdg_id() );
00554 if (part)
00555 return part->charge()!=0;
00556 else
00557 {
00558
00559 return particleDataTable_->particle( -p->pdg_id() ) != 0;
00560 }
00561 }
00562
00563
00564 void TrackClassifier::genPrimaryVertices()
00565 {
00566 genpvs_.clear();
00567
00568 const HepMC::GenEvent * event = mcInformation_->GetEvent();
00569
00570 if (event)
00571 {
00572 int idx = 0;
00573
00574
00575 for ( HepMC::GenEvent::vertex_const_iterator ivertex = event->vertices_begin(); ivertex != event->vertices_end(); ++ivertex )
00576 {
00577 bool hasParentVertex = false;
00578
00579
00580 for (
00581 HepMC::GenVertex::particle_iterator iparent = (*ivertex)->particles_begin(HepMC::parents);
00582 iparent != (*ivertex)->particles_end(HepMC::parents);
00583 ++iparent
00584 )
00585 if ( (*iparent)->production_vertex() )
00586 {
00587 hasParentVertex = true;
00588 break;
00589 }
00590
00591
00592 if (hasParentVertex) continue;
00593
00594
00595 HepMC::FourVector pos = (*ivertex)->position();
00596
00597 double const mm = 0.1;
00598
00599 GeneratedPrimaryVertex pv(pos.x()*mm, pos.y()*mm, pos.z()*mm);
00600
00601 std::vector<GeneratedPrimaryVertex>::iterator ientry = genpvs_.begin();
00602
00603
00604 for (; ientry != genpvs_.end(); ++ientry)
00605 {
00606 double distance2 = pow(pv.x - ientry->x, 2) + pow(pv.y - ientry->y, 2) + pow(pv.z - ientry->z, 2);
00607 if ( distance2 < vertexClusteringSqDistance_ )
00608 break;
00609 }
00610
00611
00612 if (ientry == genpvs_.end())
00613 ientry = genpvs_.insert(ientry,pv);
00614
00615
00616 ientry->genVertex.push_back((*ivertex)->barcode());
00617
00618
00619 for (
00620 HepMC::GenVertex::particle_iterator idecendants = (*ivertex)->particles_begin(HepMC::descendants);
00621 idecendants != (*ivertex)->particles_end(HepMC::descendants);
00622 ++idecendants
00623 )
00624 {
00625 if (isFinalstateParticle(*idecendants))
00626 if ( find(ientry->finalstateParticles.begin(), ientry->finalstateParticles.end(), (*idecendants)->barcode()) == ientry->finalstateParticles.end() )
00627 {
00628 ientry->finalstateParticles.push_back((*idecendants)->barcode());
00629 HepMC::FourVector m = (*idecendants)->momentum();
00630
00631 ientry->ptot.setPx(ientry->ptot.px() + m.px());
00632 ientry->ptot.setPy(ientry->ptot.py() + m.py());
00633 ientry->ptot.setPz(ientry->ptot.pz() + m.pz());
00634 ientry->ptot.setE(ientry->ptot.e() + m.e());
00635 ientry->ptsq += m.perp() * m.perp();
00636
00637 if ( m.perp() > 0.8 && std::abs(m.pseudoRapidity()) < 2.5 && isCharged(*idecendants) ) ientry->nGenTrk++;
00638 }
00639 }
00640 idx++;
00641 }
00642 }
00643
00644 std::sort(genpvs_.begin(), genpvs_.end());
00645 }