CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_7/src/SimTracker/TrackHistory/src/VertexClassifier.cc

Go to the documentation of this file.
00001 /*
00002  *  VertexClassifier.C
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     // Set the history depth after hadronization
00021     tracer_.depth(-2);
00022 
00023     // Set the minimum decay length for detecting long decays
00024     longLivedDecayLength_ = config.getUntrackedParameter<double>("longLivedDecayLength");
00025 
00026     // Set the distance for clustering vertices
00027     vertexClusteringDistance_ = config.getUntrackedParameter<double>("vertexClusteringDistance");
00028 }
00029 
00030 
00031 void VertexClassifier::newEvent(edm::Event const & event, edm::EventSetup const & setup)
00032 {
00033     // Get the new event information for the tracer
00034     tracer_.newEvent(event, setup);
00035 
00036     // Get hepmc of the event
00037     event.getByLabel(hepMCLabel_, mcInformation_);
00038 
00039     // Get the partivle data table
00040     setup.getData(particleDataTable_);
00041 
00042     // Create the list of primary vertices associated to the event
00043     genPrimaryVertices();
00044 }
00045 
00046 
00047 VertexClassifier const & VertexClassifier::evaluate (reco::VertexBaseRef const & vertex)
00048 {
00049     // Initializing the category vector
00050     reset();
00051 
00052     // Associate and evaluate the vertex history (check for fakes)
00053     if ( tracer_.evaluate(vertex) )
00054     {
00055         // Get all the information related to the simulation details
00056         simulationInformation();
00057 
00058         // Get all the information related to decay process
00059         processesAtGenerator();
00060 
00061         // Get information about conversion and other interactions
00062         processesAtSimulation();
00063 
00064         // Get geometrical information about the vertices
00065         vertexInformation();
00066 
00067         // Check for unkown classification
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     // Initializing the category vector
00080     reset();
00081 
00082     // Trace the history for the given TP
00083     tracer_.evaluate(vertex);
00084 
00085     // Check for a reconstructed track
00086     if ( tracer_.recoVertex().isNonnull() )
00087         flags_[Reconstructed] = true;
00088     else
00089         flags_[Reconstructed] = false;
00090 
00091     // Get all the information related to the simulation details
00092     simulationInformation();
00093 
00094     // Get all the information related to decay process
00095     processesAtGenerator();
00096 
00097     // Get information about conversion and other interactions
00098     processesAtSimulation();
00099 
00100     // Get geometrical information about the vertices
00101     vertexInformation();
00102 
00103     // Check for unkown classification
00104     unknownVertex();
00105 
00106     return *this;
00107 }
00108 
00109 
00110 void VertexClassifier::simulationInformation()
00111 {
00112     // Get the event id for the initial TP.
00113     EncodedEventId eventId = tracer_.simVertex()->eventId();
00114     // Check for signal events
00115     flags_[SignalEvent] = !eventId.bunchCrossing() && !eventId.event();
00116 }
00117 
00118 
00119 void VertexClassifier::processesAtGenerator()
00120 {
00121     // Get the generated vetices from track history
00122     VertexHistory::GenVertexTrail const & genVertexTrail = tracer_.genVertexTrail();
00123 
00124     // Loop over the generated vertices
00125     for (
00126         VertexHistory::GenVertexTrail::const_iterator ivertex = genVertexTrail.begin();
00127         ivertex != genVertexTrail.end();
00128         ++ivertex
00129     )
00130     {
00131         // Get the pointer to the vertex by removing the const-ness (no const methos in HepMC::GenVertex)
00132         HepMC::GenVertex * vertex = const_cast<HepMC::GenVertex *>(*ivertex);
00133 
00134         // Loop over the sources looking for specific decays
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             // Collect the pdgid of the parent
00142             int pdgid = std::abs((*iparent)->pdg_id());
00143             // Get particle type
00144             HepPDT::ParticleID particleID(pdgid);
00145 
00146             // Check if the particle type is valid one
00147             if (particleID.isValid())
00148             {
00149                 // Get particle data
00150                 ParticleData const * particleData = particleDataTable_->particle(particleID);
00151                 // Check if the particle exist in the table
00152                 if (particleData)
00153                 {
00154                     // Check if their life time is bigger than longLivedDecayLength_
00155                     if ( particleData->lifetime() > longLivedDecayLength_ )
00156                     {
00157                         // Check for B, C weak decays and long lived decays
00158                         update(flags_[BWeakDecay], particleID.hasBottom());
00159                         update(flags_[CWeakDecay], particleID.hasCharm());
00160                         update(flags_[LongLivedDecay], true);
00161                     }
00162                     // Check Tau, Ks and Lambda decay
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         // pdgid of the real source parent vertex
00189         int pdgid = 0;
00190 
00191         // select the original source in case of combined vertices
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         // Collect the pdgid of the original source track
00207         if ( its != (*ivertex)->sourceTracks_end() )
00208             pdgid = std::abs((*its)->pdgId());
00209         else
00210             pdgid = 0;
00211 
00212         // Loop over the simulated particles
00213         for (
00214             TrackingVertex::tp_iterator iparticle = (*ivertex)->daughterTracks_begin();
00215             iparticle != (*ivertex)->daughterTracks_end();
00216             ++iparticle
00217         )
00218         {
00219 
00220             if ( (*iparticle)->numberOfTrackerLayers() )
00221             {
00222 #warning "This file has been modified just to get it to compile without any regard as to whether it still functions as intended"
00223 #ifdef REMOVED_JUST_TO_GET_IT_TO_COMPILE__THIS_CODE_NEEDS_TO_BE_CHECKED
00224                 // Collect the G4 process of the first psimhit (it should be the same for all of them)
00225                 unsigned short process = (*iparticle)->pSimHit_begin()->processType();
00226 #else
00227                 unsigned short process = 0;
00228 #endif
00229                 // Flagging all the different processes
00230 
00231                 update(
00232                     flags_[KnownProcess],
00233                     process != G4::Undefined &&
00234                     process != G4::Unknown &&
00235                     process != G4::Primary
00236                 );
00237 
00238                 update(flags_[UndefinedProcess], process == G4::Undefined);
00239                 update(flags_[UnknownProcess], process == G4::Unknown);
00240                 update(flags_[PrimaryProcess], process == G4::Primary);
00241                 update(flags_[HadronicProcess], process == G4::Hadronic);
00242                 update(flags_[DecayProcess], process == G4::Decay);
00243                 update(flags_[ComptonProcess], process == G4::Compton);
00244                 update(flags_[AnnihilationProcess], process == G4::Annihilation);
00245                 update(flags_[EIoniProcess], process == G4::EIoni);
00246                 update(flags_[HIoniProcess], process == G4::HIoni);
00247                 update(flags_[MuIoniProcess], process == G4::MuIoni);
00248                 update(flags_[PhotonProcess], process == G4::Photon);
00249                 update(flags_[MuPairProdProcess], process == G4::MuPairProd);
00250                 update(flags_[ConversionsProcess], process == G4::Conversions);
00251                 update(flags_[EBremProcess], process == G4::EBrem);
00252                 update(flags_[SynchrotronRadiationProcess], process == G4::SynchrotronRadiation);
00253                 update(flags_[MuBremProcess], process == G4::MuBrem);
00254                 update(flags_[MuNuclProcess], process == G4::MuNucl);
00255 
00256                 // Special treatment for decays
00257                 if (process == G4::Decay)
00258                 {
00259                     // Get particle type
00260                     HepPDT::ParticleID particleID(pdgid);
00261                     // Check if the particle type is valid one
00262                     if (particleID.isValid())
00263                     {
00264                         // Get particle data
00265                         ParticleData const * particleData = particleDataTable_->particle(particleID);
00266                         // Check if the particle exist in the table
00267                         if (particleData)
00268                         {
00269                             // Check if their life time is bigger than 1e-14
00270                             if ( particleDataTable_->particle(particleID)->lifetime() > longLivedDecayLength_ )
00271                             {
00272                                 // Check for B, C weak decays and long lived decays
00273                                 update(flags_[BWeakDecay], particleID.hasBottom());
00274                                 update(flags_[CWeakDecay], particleID.hasCharm());
00275                                 update(flags_[LongLivedDecay], true);
00276                             }
00277                             // Check Tau, Ks and Lambda decay
00278                             update(flags_[TauDecay], pdgid == 15);
00279                             update(flags_[KsDecay], pdgid == 310);
00280                             update(flags_[LambdaDecay], pdgid == 3122);
00281                             update(flags_[JpsiDecay], pdgid == 443);
00282                             update(flags_[XiDecay], pdgid == 3312);
00283                             update(flags_[OmegaDecay], pdgid == 3334);
00284                             update(flags_[SigmaPlusDecay], pdgid == 3222);
00285                             update(flags_[SigmaMinusDecay], pdgid == 3112);
00286                         }
00287                     }
00288                 }
00289             }
00290         }
00291     }
00292 }
00293 
00294 
00295 void VertexClassifier::vertexInformation()
00296 {
00297     // Helper class for clusterization
00298     typedef std::multimap<double, HepMC::ThreeVector> Clusters;
00299     typedef std::pair<double, HepMC::ThreeVector> ClusterPair;
00300 
00301     Clusters clusters;
00302 
00303     // Get the main primary vertex from the list
00304     GeneratedPrimaryVertex const & genpv = genpvs_.back();
00305 
00306     // Get the generated history of the tracks
00307     VertexHistory::GenVertexTrail & genVertexTrail = const_cast<VertexHistory::GenVertexTrail &> (tracer_.genVertexTrail());
00308 
00309     // Unit transformation from mm to cm
00310     double const mm = 0.1;
00311 
00312     // Loop over the generated vertexes
00313     for (
00314         VertexHistory::GenVertexTrail::const_iterator ivertex = genVertexTrail.begin();
00315         ivertex != genVertexTrail.end();
00316         ++ivertex
00317     )
00318     {
00319         // Check vertex exist
00320         if (*ivertex)
00321         {
00322             // Measure the distance2 respecto the primary vertex
00323             HepMC::ThreeVector p = (*ivertex)->point3d();
00324             double distance = sqrt( pow(p.x() * mm - genpv.x, 2) + pow(p.y() * mm - genpv.y, 2) + pow(p.z() * mm - genpv.z, 2) );
00325 
00326             // If there is not any clusters add the first vertex.
00327             if ( clusters.empty() )
00328             {
00329                 clusters.insert( ClusterPair(distance, HepMC::ThreeVector(p.x() * mm, p.y() * mm, p.z() * mm)) );
00330                 continue;
00331             }
00332 
00333             // Check if there is already a cluster in the given distance from primary vertex
00334             Clusters::const_iterator icluster = clusters.lower_bound(distance - vertexClusteringDistance_);
00335 
00336             if ( icluster == clusters.upper_bound(distance + vertexClusteringDistance_) )
00337             {
00338                 clusters.insert ( ClusterPair(distance, HepMC::ThreeVector(p.x() * mm, p.y() * mm, p.z() * mm)) );
00339                 continue;
00340             }
00341 
00342             bool cluster = false;
00343 
00344             // Looping over the vertex clusters of a given distance from primary vertex
00345             for (;
00346                     icluster != clusters.upper_bound(distance + vertexClusteringDistance_);
00347                     ++icluster
00348                 )
00349             {
00350                 double difference = sqrt (
00351                                         pow(p.x() * mm - icluster->second.x(), 2) +
00352                                         pow(p.y() * mm - icluster->second.y(), 2) +
00353                                         pow(p.z() * mm - icluster->second.z(), 2)
00354                                     );
00355 
00356                 if ( difference < vertexClusteringDistance_ )
00357                 {
00358                     cluster = true;
00359                     break;
00360                 }
00361             }
00362 
00363             if (!cluster) clusters.insert ( ClusterPair(distance, HepMC::ThreeVector(p.x() * mm, p.y() * mm, p.z() * mm)) );
00364         }
00365     }
00366 
00367     VertexHistory::SimVertexTrail & simVertexTrail = const_cast<VertexHistory::SimVertexTrail &> (tracer_.simVertexTrail());
00368 
00369     // Loop over the generated particles
00370     for (
00371         VertexHistory::SimVertexTrail::reverse_iterator ivertex = simVertexTrail.rbegin();
00372         ivertex != simVertexTrail.rend();
00373         ++ivertex
00374     )
00375     {
00376         // Look for those with production vertex
00377         TrackingVertex::LorentzVector p = (*ivertex)->position();
00378 
00379         double distance = sqrt( pow(p.x() - genpv.x, 2) + pow(p.y() - genpv.y, 2) + pow(p.z() - genpv.z, 2) );
00380 
00381         // If there is not any clusters add the first vertex.
00382         if ( clusters.empty() )
00383         {
00384             clusters.insert( ClusterPair(distance, HepMC::ThreeVector(p.x(), p.y(), p.z())) );
00385             continue;
00386         }
00387 
00388         // Check if there is already a cluster in the given distance from primary vertex
00389         Clusters::const_iterator icluster = clusters.lower_bound(distance - vertexClusteringDistance_);
00390 
00391         if ( icluster == clusters.upper_bound(distance + vertexClusteringDistance_) )
00392         {
00393             clusters.insert ( ClusterPair(distance, HepMC::ThreeVector(p.x(), p.y(), p.z())) );
00394             continue;
00395         }
00396 
00397         bool cluster = false;
00398 
00399         // Looping over the vertex clusters of a given distance from primary vertex
00400         for (;
00401                 icluster != clusters.upper_bound(distance + vertexClusteringDistance_);
00402                 ++icluster
00403             )
00404         {
00405             double difference = sqrt (
00406                                     pow(p.x() - icluster->second.x(), 2) +
00407                                     pow(p.y() - icluster->second.y(), 2) +
00408                                     pow(p.z() - icluster->second.z(), 2)
00409                                 );
00410 
00411             if ( difference < vertexClusteringDistance_ )
00412             {
00413                 cluster = true;
00414                 break;
00415             }
00416         }
00417 
00418         if (!cluster) clusters.insert ( ClusterPair(distance, HepMC::ThreeVector(p.x(), p.y(), p.z())) );
00419     }
00420 
00421     if ( clusters.size() == 1 )
00422         flags_[PrimaryVertex] = true;
00423     else if ( clusters.size() == 2 )
00424         flags_[SecondaryVertex] = true;
00425     else
00426         flags_[TertiaryVertex] = true;
00427 }
00428 
00429 
00430 bool VertexClassifier::isFinalstateParticle(const HepMC::GenParticle * p)
00431 {
00432     return !p->end_vertex() && p->status() == 1;
00433 }
00434 
00435 
00436 bool VertexClassifier::isCharged(const HepMC::GenParticle * p)
00437 {
00438     const ParticleData * part = particleDataTable_->particle( p->pdg_id() );
00439     if (part)
00440         return part->charge()!=0;
00441     else
00442     {
00443         // the new/improved particle table doesn't know anti-particles
00444         return  particleDataTable_->particle( -p->pdg_id() ) != 0;
00445     }
00446 }
00447 
00448 
00449 void VertexClassifier::genPrimaryVertices()
00450 {
00451     genpvs_.clear();
00452 
00453     const HepMC::GenEvent * event = mcInformation_->GetEvent();
00454 
00455     if (event)
00456     {
00457         int idx = 0;
00458 
00459         // Loop over the different GenVertex
00460         for ( HepMC::GenEvent::vertex_const_iterator ivertex = event->vertices_begin(); ivertex != event->vertices_end(); ++ivertex )
00461         {
00462             bool hasParentVertex = false;
00463 
00464             // Loop over the parents looking to see if they are coming from a production vertex
00465             for (
00466                 HepMC::GenVertex::particle_iterator iparent = (*ivertex)->particles_begin(HepMC::parents);
00467                 iparent != (*ivertex)->particles_end(HepMC::parents);
00468                 ++iparent
00469             )
00470                 if ( (*iparent)->production_vertex() )
00471                 {
00472                     hasParentVertex = true;
00473                     break;
00474                 }
00475 
00476             // Reject those vertices with parent vertices
00477             if (hasParentVertex) continue;
00478 
00479             // Get the position of the vertex
00480             HepMC::FourVector pos = (*ivertex)->position();
00481 
00482             double const mm = 0.1;
00483 
00484             GeneratedPrimaryVertex pv(pos.x()*mm, pos.y()*mm, pos.z()*mm);
00485 
00486             std::vector<GeneratedPrimaryVertex>::iterator ientry = genpvs_.begin();
00487 
00488             // Search for a VERY close vertex in the list
00489             for (; ientry != genpvs_.end(); ++ientry)
00490             {
00491                 double distance = sqrt( pow(pv.x - ientry->x, 2) + pow(pv.y - ientry->y, 2) + pow(pv.z - ientry->z, 2) );
00492                 if ( distance < vertexClusteringDistance_ )
00493                     break;
00494             }
00495 
00496             // Check if there is not a VERY close vertex and added to the list
00497             if (ientry == genpvs_.end())
00498                 ientry = genpvs_.insert(ientry,pv);
00499 
00500             // Add the vertex barcodes to the new or existent vertices
00501             ientry->genVertex.push_back((*ivertex)->barcode());
00502 
00503             // Collect final state descendants
00504             for (
00505                 HepMC::GenVertex::particle_iterator idecendants  = (*ivertex)->particles_begin(HepMC::descendants);
00506                 idecendants != (*ivertex)->particles_end(HepMC::descendants);
00507                 ++idecendants
00508             )
00509             {
00510                 if (isFinalstateParticle(*idecendants))
00511                     if ( find(ientry->finalstateParticles.begin(), ientry->finalstateParticles.end(), (*idecendants)->barcode()) == ientry->finalstateParticles.end() )
00512                     {
00513                         ientry->finalstateParticles.push_back((*idecendants)->barcode());
00514                         HepMC::FourVector m = (*idecendants)->momentum();
00515 
00516                         ientry->ptot.setPx(ientry->ptot.px() + m.px());
00517                         ientry->ptot.setPy(ientry->ptot.py() + m.py());
00518                         ientry->ptot.setPz(ientry->ptot.pz() + m.pz());
00519                         ientry->ptot.setE(ientry->ptot.e() + m.e());
00520                         ientry->ptsq += m.perp() * m.perp();
00521 
00522                         if ( m.perp() > 0.8 && std::abs(m.pseudoRapidity()) < 2.5 && isCharged(*idecendants) ) ientry->nGenTrk++;
00523                     }
00524             }
00525             idx++;
00526         }
00527     }
00528 
00529     std::sort(genpvs_.begin(), genpvs_.end());
00530 }