CMS 3D CMS Logo

CMSSW_4_4_3_patch1/src/SimGeneral/TrackingAnalysis/plugins/TrackingTruthProducer.cc

Go to the documentation of this file.
00001 
00002 #include "DataFormats/DetId/interface/DetId.h"
00003 #include "DataFormats/SiPixelDetId/interface/PXBDetId.h"
00004 #include "DataFormats/SiPixelDetId/interface/PXFDetId.h"
00005 #include "DataFormats/SiPixelDetId/interface/PixelSubdetector.h"
00006 #include "DataFormats/SiStripDetId/interface/StripSubdetector.h"
00007 #include "DataFormats/SiStripDetId/interface/TECDetId.h"
00008 #include "DataFormats/SiStripDetId/interface/TIBDetId.h"
00009 #include "DataFormats/SiStripDetId/interface/TIDDetId.h"
00010 #include "DataFormats/SiStripDetId/interface/TOBDetId.h"
00011 
00012 #include "FWCore/Framework/interface/MakerMacros.h"
00013 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00014 
00015 #include "SimDataFormats/EncodedEventId/interface/EncodedEventId.h"
00016 #include "SimDataFormats/TrackingAnalysis/interface/TrackingParticle.h"
00017 #include "SimDataFormats/TrackingAnalysis/interface/TrackingVertex.h"
00018 
00019 #include "SimGeneral/TrackingAnalysis/interface/TrackingTruthProducer.h"
00020 
00021 typedef edm::Ref<edm::HepMCProduct, HepMC::GenParticle > GenParticleRef;
00022 typedef edm::Ref<edm::HepMCProduct, HepMC::GenVertex >   GenVertexRef;
00023 typedef math::XYZTLorentzVectorD    LorentzVector;
00024 typedef math::XYZPoint Vector;
00025 
00026 TrackingTruthProducer::TrackingTruthProducer(const edm::ParameterSet & config) :
00027         pSimHitSelector_(config), pixelPSimHitSelector_(config), trackerPSimHitSelector_(config), muonPSimHitSelector_(config)
00028 {
00029     // Initialize global parameters
00030     dataLabels_             = config.getParameter<std::vector<std::string> >("HepMCDataLabels");
00031     useMultipleHepMCLabels_ = config.getParameter<bool>("useMultipleHepMCLabels");
00032 
00033     distanceCut_            = config.getParameter<double>("vertexDistanceCut");
00034     volumeRadius_           = config.getParameter<double>("volumeRadius");
00035     volumeZ_                = config.getParameter<double>("volumeZ");
00036     mergedBremsstrahlung_   = config.getParameter<bool>("mergedBremsstrahlung");
00037     removeDeadModules_      = config.getParameter<bool>("removeDeadModules");
00038     simHitLabel_            = config.getParameter<std::string>("simHitLabel");
00039 
00040     // Initialize selection for building TrackingParticles
00041     if ( config.exists("select") )
00042     {
00043         edm::ParameterSet param = config.getParameter<edm::ParameterSet>("select");
00044         selector_ = TrackingParticleSelector(
00045                         param.getParameter<double>("ptMinTP"),
00046                         param.getParameter<double>("minRapidityTP"),
00047                         param.getParameter<double>("maxRapidityTP"),
00048                         param.getParameter<double>("tipTP"),
00049                         param.getParameter<double>("lipTP"),
00050                         param.getParameter<int>("minHitTP"),
00051                         param.getParameter<bool>("signalOnlyTP"),
00052                         param.getParameter<bool>("chargedOnlyTP"),
00053                         param.getParameter<bool>("stableOnlyTP"),
00054                         param.getParameter<std::vector<int> >("pdgIdTP")
00055                     );
00056         selectorFlag_ = true;
00057     }
00058     else
00059         selectorFlag_ = false;
00060 
00061     MessageCategory_       = "TrackingTruthProducer";
00062 
00063     edm::LogInfo (MessageCategory_) << "Setting up TrackingTruthProducer";
00064     edm::LogInfo (MessageCategory_) << "Vertex distance cut set to " << distanceCut_  << " mm";
00065     edm::LogInfo (MessageCategory_) << "Volume radius set to "       << volumeRadius_ << " mm";
00066     edm::LogInfo (MessageCategory_) << "Volume Z      set to "       << volumeZ_      << " mm";
00067 
00068     if (useMultipleHepMCLabels_) edm::LogInfo (MessageCategory_) << "Collecting generator information from pileup.";
00069     if (mergedBremsstrahlung_) edm::LogInfo (MessageCategory_) << "Merging electrom bremsstralung";
00070     if (removeDeadModules_) edm::LogInfo (MessageCategory_) << "Removing psimhit from dead modules";
00071 
00072     if (!mergedBremsstrahlung_)
00073     {
00074         produces<TrackingVertexCollection>();
00075         produces<TrackingParticleCollection>();
00076     }
00077     else
00078     {
00079         produces<TrackingVertexCollection>();
00080         produces<TrackingParticleCollection>();
00081         produces<TrackingVertexCollection>("MergedTrackTruth");
00082         produces<TrackingParticleCollection>("MergedTrackTruth");
00083     }
00084 }
00085 
00086 
00087 void TrackingTruthProducer::produce(edm::Event &event, const edm::EventSetup & setup)
00088 {
00089     // Clean the list of hepmc products
00090     hepMCProducts_.clear();
00091 
00092     // Collect all the HepMCProducts
00093     edm::Handle<edm::HepMCProduct> hepMCHandle;
00094 
00095     for (std::vector<std::string>::const_iterator source = dataLabels_.begin(); source != dataLabels_.end(); ++source)
00096     {
00097         if ( event.getByLabel(*source, hepMCHandle) )
00098         {
00099             hepMCProducts_.push_back(hepMCHandle);
00100             edm::LogInfo (MessageCategory_) << "Using HepMC source " << *source;
00101             if (!useMultipleHepMCLabels_) break;
00102         }
00103     }
00104 
00105     if ( hepMCProducts_.empty() )
00106     {
00107         edm::LogWarning (MessageCategory_) << "No HepMC source found";
00108         return;
00109     }
00110     else if (hepMCProducts_.size() > 1 || useMultipleHepMCLabels_)
00111     {
00112         edm::LogInfo (MessageCategory_) << "You are using more than one HepMC source.";
00113         edm::LogInfo (MessageCategory_) << "If the labels are not in the same order as the events in the crossing frame (i.e. signal, pileup(s) ) ";
00114         edm::LogInfo (MessageCategory_) << "or there are fewer labels than events in the crossing frame";
00115         edm::LogInfo (MessageCategory_) << MessageCategory_ << " may try to access data in the wrong HepMCProduct and crash.";
00116     }
00117 
00118     // Collect all the simtracks from the crossing frame
00119     edm::Handle<CrossingFrame<SimTrack> > cfSimTracks;
00120     event.getByLabel("mix", simHitLabel_, cfSimTracks);
00121 
00122     // Create a mix collection from one simtrack collection
00123     simTracks_ = std::auto_ptr<MixCollection<SimTrack> >( new MixCollection<SimTrack>(cfSimTracks.product()) );
00124 
00125     // Collect all the simvertex from the crossing frame
00126     edm::Handle<CrossingFrame<SimVertex> > cfSimVertexes;
00127     event.getByLabel("mix", simHitLabel_, cfSimVertexes);
00128 
00129     // Create a mix collection from one simvertex collection
00130     simVertexes_ = std::auto_ptr<MixCollection<SimVertex> >( new MixCollection<SimVertex>(cfSimVertexes.product()) );
00131 
00132     // Create collections of things we will put in event
00133     trackingParticles_ = std::auto_ptr<TrackingParticleCollection>( new TrackingParticleCollection );
00134     trackingVertexes_ = std::auto_ptr<TrackingVertexCollection>( new TrackingVertexCollection );
00135 
00136     // Get references before put so we can cross reference
00137     refTrackingParticles_ = event.getRefBeforePut<TrackingParticleCollection>();
00138     refTrackingVertexes_ = event.getRefBeforePut<TrackingVertexCollection>();
00139 
00140     // Create a list of psimhits
00141     if (removeDeadModules_)
00142     {
00143         pSimHits_.clear();
00144         pixelPSimHitSelector_.select(pSimHits_, event, setup);
00145         trackerPSimHitSelector_.select(pSimHits_, event, setup);
00146         muonPSimHitSelector_.select(pSimHits_, event, setup);
00147     }
00148     else
00149     {
00150         pSimHits_.clear();
00151         pSimHitSelector_.select(pSimHits_, event, setup);
00152     }
00153 
00154     // Create a multimap between trackId and hit indices
00155     associator(pSimHits_, trackIdToHits_);
00156 
00157     // Create a map between trackId and track index
00158     associator(simTracks_, trackIdToIndex_);
00159 
00160     // Create a map between vertexId and vertex index
00161     associator(simVertexes_, vertexIdToIndex_);
00162 
00163     createTrackingTruth();
00164 
00165     if (mergedBremsstrahlung_)
00166     {
00167         // Create collections of things we will put in event,
00168         mergedTrackingParticles_ = std::auto_ptr<TrackingParticleCollection>( new TrackingParticleCollection );
00169         mergedTrackingVertexes_ = std::auto_ptr<TrackingVertexCollection>( new TrackingVertexCollection );
00170 
00171         // Get references before put so we can cross reference
00172         refMergedTrackingParticles_ = event.getRefBeforePut<TrackingParticleCollection>("MergedTrackTruth");
00173         refMergedTrackingVertexes_ = event.getRefBeforePut<TrackingVertexCollection>("MergedTrackTruth");
00174 
00175         // Merged brem electrons
00176         mergeBremsstrahlung();
00177 
00178         // Put TrackingParticles and TrackingVertices in event
00179         event.put(mergedTrackingParticles_, "MergedTrackTruth");
00180         event.put(mergedTrackingVertexes_, "MergedTrackTruth");
00181         event.put(trackingParticles_);
00182         event.put(trackingVertexes_);
00183     }
00184     else
00185     {
00186         // Put TrackingParticles and TrackingVertices in event
00187         event.put(trackingParticles_);
00188         event.put(trackingVertexes_);
00189     }
00190 }
00191 
00192 
00193 void TrackingTruthProducer::associator(
00194     std::vector<PSimHit> const & pSimHits,
00195     EncodedTruthIdToIndexes & association
00196 )
00197 {
00198     // Clear the association map
00199     association.clear();
00200 
00201     // Create a association from simtracks to overall index in the mix collection
00202     for (std::size_t i = 0; i < pSimHits.size(); ++i)
00203     {
00204         EncodedTruthIdToIndexes::key_type objectId = EncodedTruthIdToIndexes::key_type(pSimHits[i].eventId(), pSimHits[i].trackId());
00205         association.insert( std::make_pair(objectId, i) );
00206     }
00207 }
00208 
00209 
00210 void TrackingTruthProducer::associator(
00211     std::auto_ptr<MixCollection<SimTrack> > const & mixCollection,
00212     EncodedTruthIdToIndex & association
00213 )
00214 {
00215     int index = 0;
00216     // Clear the association map
00217     association.clear();
00218     // Create a association from simtracks to overall index in the mix collection
00219     for (MixCollection<SimTrack>::MixItr iterator = mixCollection->begin(); iterator != mixCollection->end(); ++iterator, ++index)
00220     {
00221         EncodedTruthId objectId = EncodedTruthId(iterator->eventId(), iterator->trackId());
00222         association.insert( std::make_pair(objectId, index) );
00223     }
00224 }
00225 
00226 
00227 void TrackingTruthProducer::associator(
00228     std::auto_ptr<MixCollection<SimVertex> > const & mixCollection,
00229     EncodedTruthIdToIndex & association
00230 )
00231 {
00232     int index = 0;
00233 
00234     // Solution to the problem of not having vertexId
00235     bool useVertexId = true;
00236     EncodedEventIdToIndex vertexId;
00237     EncodedEventId oldEventId;
00238     unsigned int oldVertexId = 0;
00239 
00240     // Loop for finding repeated vertexId (vertexId problem hack)
00241     for (MixCollection<SimVertex>::MixItr iterator = mixCollection->begin(); iterator != mixCollection->end(); ++iterator, ++index)
00242     {
00243         if (!index || iterator->eventId() != oldEventId)
00244         {
00245             oldEventId = iterator->eventId();
00246             oldVertexId = iterator->vertexId();
00247             continue;
00248         }
00249 
00250         if ( iterator->vertexId() == oldVertexId )
00251         {
00252             edm::LogWarning(MessageCategory_) << "Multiple vertexId found, no using vertexId.";
00253             useVertexId = false;
00254             break;
00255         }
00256     }
00257 
00258     // Reset the index
00259     index = 0;
00260 
00261     // Clear the association map
00262     association.clear();
00263 
00264     // Create a association from simvertexes to overall index in the mix collection
00265     for (MixCollection<SimVertex>::MixItr iterator = mixCollection->begin(); iterator != mixCollection->end(); ++iterator, ++index)
00266     {
00267         EncodedTruthId objectId;
00268         if (useVertexId)
00269             objectId = EncodedTruthId(iterator->eventId(), iterator->vertexId());
00270         else
00271             objectId = EncodedTruthId(iterator->eventId(), vertexId[iterator->eventId()]++);
00272         association.insert( std::make_pair(objectId, index) );
00273     }
00274 }
00275 
00276 
00277 void TrackingTruthProducer::mergeBremsstrahlung()
00278 {
00279     unsigned int index = 0;
00280 
00281     std::set<unsigned int> excludedTV, excludedTP;
00282 
00283     // Merge Bremsstrahlung vertexes
00284     for (TrackingVertexCollection::iterator iVC = trackingVertexes_->begin(); iVC != trackingVertexes_->end(); ++iVC, ++index)
00285     {
00286         // Check Bremsstrahlung vertex
00287         if ( isBremsstrahlungVertex(*iVC, trackingParticles_) )
00288         {
00289             // Get a pointer to the source track (A Ref<> cannot be use with a product!)
00290             TrackingParticle * track = &trackingParticles_->at(iVC->sourceTracks_begin()->key());
00291             // Get a Ref<> to the source track
00292             TrackingParticleRef trackRef = *iVC->sourceTracks_begin();
00293             // Pointer to electron daughter
00294             TrackingParticle * daughter = 0;
00295             // Ref<> to electron daughter
00296             TrackingParticleRef daughterRef;
00297 
00298             // Select the electron daughter and redirect the photon
00299             for (TrackingVertex::tp_iterator idaughter = iVC->daughterTracks_begin(); idaughter != iVC->daughterTracks_end(); ++idaughter)
00300             {
00301                 TrackingParticle * pointer = &trackingParticles_->at(idaughter->key());
00302                 if ( std::abs( pointer->pdgId() ) == 11 )
00303                 {
00304                     // Set pointer to the electron daughter
00305                     daughter = pointer;
00306                     // Set Ref<> to the electron daughter
00307                     daughterRef = *idaughter;
00308                 }
00309                 else if ( pointer->pdgId() == 22 )
00310                 {
00311                     // Delete the photon original parent vertex
00312                     pointer->clearParentVertex();
00313                     // Set the new parent vertex to the vertex of the source track
00314                     pointer->setParentVertex( track->parentVertex() );
00315                     // Get a non-const pointer to the parent vertex
00316                     TrackingVertex * vertex = &trackingVertexes_->at( track->parentVertex().key() );
00317                     // Add the photon to the doughter list of the parent vertex
00318                     vertex->addDaughterTrack( *idaughter );
00319                 }
00320             }
00321 
00322             // Add the electron segments from the electron daughter
00323             // track must not be the same particle as daughter
00324             // if (track != daughter)
00325             for (TrackingParticle::g4t_iterator isegment = daughter->g4Track_begin(); isegment != daughter->g4Track_end(); ++isegment)
00326                 track->addG4Track(*isegment);
00327 
00328             // Copy all the simhits to the new track
00329             for (std::vector<PSimHit>::const_iterator ihit = daughter->pSimHit_begin(); ihit != daughter->pSimHit_end(); ++ihit)
00330                 track->addPSimHit(*ihit);
00331 
00332             // Make a copy of the decay vertexes of the track
00333             TrackingVertexRefVector decayVertices( track->decayVertices() );
00334 
00335             // Clear the decay vertex list
00336             track->clearDecayVertices();
00337 
00338             // Add the remaining vertexes
00339             for (TrackingVertexRefVector::const_iterator idecay = decayVertices.begin(); idecay != decayVertices.end(); ++idecay)
00340                 if ( (*idecay).key() != index ) track->addDecayVertex(*idecay);
00341 
00342             // Redirect all the decay source vertexes to those in the electron daughter
00343             for (TrackingParticle::tv_iterator idecay = daughter->decayVertices_begin(); idecay != daughter->decayVertices_end(); ++idecay)
00344             {
00345                 // Add the vertexes to the decay list of the source particles
00346                 track->addDecayVertex(*idecay);
00347                 // Get a reference to decay vertex
00348                 TrackingVertex * vertex = &trackingVertexes_->at( idecay->key() );
00349                 // Copy all the source tracks from of the decay vertex
00350                 TrackingParticleRefVector sources( vertex->sourceTracks() );
00351                 // Clear the source track references
00352                 vertex->clearParentTracks();
00353                 // Add the new source tracks by excluding the one with the segment merged
00354                 for (TrackingVertex::tp_iterator isource = sources.begin(); isource != sources.end(); ++isource)
00355                     if (*isource != daughterRef)
00356                         vertex->addParentTrack(*isource);
00357                 // Add the track reference to the list of sources
00358                 vertex->addParentTrack(trackRef);
00359             }
00360 
00361             // Adding the vertex to the exlusion list
00362             excludedTV.insert(index);
00363 
00364             // Adding the electron segment tp into the exlusion list
00365             excludedTP.insert( daughterRef.key() );
00366         }
00367     }
00368 
00369     edm::LogInfo(MessageCategory_) << "Generating the merged collection." << std::endl;
00370 
00371     // Reserved the same amount of memory for the merged collections
00372     mergedTrackingParticles_->reserve(trackingParticles_->size());
00373     mergedTrackingVertexes_->reserve(trackingVertexes_->size());
00374 
00375     index = 0;
00376     std::map<unsigned int, unsigned int> vertexMap;
00377 
00378     // Copy non-excluded vertices discarding parent & child tracks
00379     for (TrackingVertexCollection::const_iterator iVC = trackingVertexes_->begin(); iVC != trackingVertexes_->end(); ++iVC, ++index)
00380     {
00381         if ( excludedTV.find(index) != excludedTV.end() ) continue;
00382         // Save the new location of the non excluded vertexes (take in consideration those were removed)
00383         vertexMap.insert( std::make_pair(index, mergedTrackingVertexes_->size()) );
00384         // Copy those vertexes are not excluded
00385         TrackingVertex newVertex = (*iVC);
00386         newVertex.clearDaughterTracks();
00387         newVertex.clearParentTracks();
00388         mergedTrackingVertexes_->push_back(newVertex);
00389     }
00390 
00391     index = 0;
00392 
00393     // Copy and cross reference the non-excluded tp to the merged collection
00394     for (TrackingParticleCollection::const_iterator iTP = trackingParticles_->begin(); iTP != trackingParticles_->end(); ++iTP, ++index)
00395     {
00396         if ( excludedTP.find(index) != excludedTP.end() ) continue;
00397 
00398         TrackingVertexRef       sourceV = iTP->parentVertex();
00399         TrackingVertexRefVector decayVs = iTP->decayVertices();
00400         TrackingParticle newTrack = *iTP;
00401 
00402         newTrack.clearParentVertex();
00403         newTrack.clearDecayVertices();
00404 
00405         // Set vertex indices for new vertex product and track references in those vertices
00406 
00407         // Index of parent vertex in vertex container
00408         unsigned int parentIndex = vertexMap[sourceV.key()];
00409         // Index of this track in track container
00410         unsigned int tIndex = mergedTrackingParticles_->size();
00411 
00412         // Add vertex to track
00413         newTrack.setParentVertex( TrackingVertexRef(refMergedTrackingVertexes_, parentIndex) );
00414         // Add track to vertex
00415         (mergedTrackingVertexes_->at(parentIndex)).addDaughterTrack(TrackingParticleRef(refMergedTrackingParticles_, tIndex));
00416 
00417         for (TrackingVertexRefVector::const_iterator iDecayV = decayVs.begin(); iDecayV != decayVs.end(); ++iDecayV)
00418         {
00419             // Index of decay vertex in vertex container
00420             unsigned int daughterIndex = vertexMap[iDecayV->key()];
00421             // Add vertex to track
00422             newTrack.addDecayVertex( TrackingVertexRef(refMergedTrackingVertexes_, daughterIndex) );
00423             // Add track to vertex
00424             (mergedTrackingVertexes_->at(daughterIndex)).addParentTrack( TrackingParticleRef(refMergedTrackingParticles_, tIndex) );
00425         }
00426 
00427         mergedTrackingParticles_->push_back(newTrack);
00428     }
00429 }
00430 
00431 
00432 bool TrackingTruthProducer::isBremsstrahlungVertex(
00433     TrackingVertex const & vertex,
00434     std::auto_ptr<TrackingParticleCollection> & tPC
00435 )
00436 {
00437     const TrackingParticleRefVector parents(vertex.sourceTracks());
00438 
00439     // Check for the basic parent conditions
00440     if ( parents.size() != 1)
00441         return false;
00442 
00443     // Check for the parent particle is a |electron| (electron or positron)
00444     if ( std::abs( tPC->at(parents.begin()->key()).pdgId() ) != 11 )
00445         return false;
00446 
00447     int nElectrons = 0;
00448     int nPhotons = 0;
00449     int nOthers = 0;
00450 
00451     // Loop over the daughter particles and counts the number of |electrons|, photons or others
00452     for ( TrackingVertex::tp_iterator it = vertex.daughterTracks_begin(); it != vertex.daughterTracks_end(); ++it )
00453     {
00454         // Stronger rejection for looping particles
00455         if ( parents[0] == *it )
00456             return false;
00457 
00458         if ( std::abs( tPC->at(it->key()).pdgId() ) == 11 )
00459             nElectrons++;
00460         else if ( tPC->at(it->key()).pdgId() == 22 )
00461             nPhotons++;
00462         else
00463             nOthers++;
00464     }
00465 
00466     // Condition to be a Bremsstrahlung Vertex
00467     if (nElectrons == 1 && nPhotons >= 0 && nOthers == 0)
00468         return true;
00469 
00470     return false;
00471 }
00472 
00473 
00474 void TrackingTruthProducer::createTrackingTruth()
00475 {
00476     // Reset the event counter (use for define vertexId)
00477     eventIdCounter_.clear();
00478 
00479     // Define a container of vetoed traks
00480     std::map<int,std::size_t> vetoedTracks;
00481 
00482     // Define map between parent simtrack and tv indexes
00483     std::map<int,std::size_t> vetoedSimVertexes;
00484 
00485     for (int simTrackIndex = 0; simTrackIndex != simTracks_->size(); ++simTrackIndex)
00486     {
00487         // Check if the simTrack is excluded (includes non traceable and recovered by history)
00488         if ( vetoedTracks.find(simTrackIndex) != vetoedTracks.end() ) continue;
00489 
00490         SimTrack const & simTrack = simTracks_->getObject(simTrackIndex);
00491 
00492         TrackingParticle trackingParticle;
00493 
00494         // Set a bare tp (only with the psimhit) with a given simtrack
00495         // the function return true if it is tracable
00496         if ( setTrackingParticle(simTrack, trackingParticle) )
00497         {
00498             // Follows the path upward recovering the history of the particle
00499             SimTrack const * currentSimTrack = & simTrack;
00500 
00501             // Initial condition for the tp and tv indexes
00502             int trackingParticleIndex = -1;
00503             int trackingVertexIndex = -1;
00504 
00505             do
00506             {
00507                 // Set a new tracking particle for the current simtrack
00508                 // and add it to the list of parent tracks of previous vertex
00509                 if (trackingParticleIndex >= 0)
00510                 {
00511                     setTrackingParticle(*currentSimTrack, trackingParticle);
00512 
00513                     // Set the tp index to its new value
00514                     trackingParticleIndex = trackingParticles_->size();
00515                     // Push the tp in to the collection
00516                     trackingParticles_->push_back(trackingParticle);
00517 
00518                     // Add the previous track to the list of decay vertexes of the new tp
00519                     trackingParticles_->at(trackingParticleIndex).addDecayVertex(
00520                         TrackingVertexRef(refTrackingVertexes_, trackingVertexIndex)
00521                     );
00522 
00523                     // Add the new tp to the list of parent tracks of the previous tv
00524                     trackingVertexes_->at(trackingVertexIndex).addParentTrack(
00525                         TrackingParticleRef(refTrackingParticles_, trackingParticleIndex)
00526                     );
00527                 }
00528                 else
00529                 {
00530                     // Set the tp index to its new value
00531                     trackingParticleIndex = trackingParticles_->size();
00532                     // Push the tp in to the collection
00533                     trackingParticles_->push_back(trackingParticle);
00534                     // Vetoed the simTrack
00535                     vetoedTracks.insert( std::make_pair(simTrackIndex, trackingParticleIndex) );
00536                 }
00537 
00538                 // Verify if the parent simVertex has a simTrack or if the source is a vetoSimVertex
00539                 if (currentSimTrack->noVertex()) break;
00540 
00541                 // Get the simTrack parent index (it is implicit should be in the same event as current)
00542                 unsigned int parentSimVertexIndex = vertexIdToIndex_[
00543                                                         EncodedTruthId(
00544                                                             currentSimTrack->eventId(),
00545                                                             currentSimTrack->vertIndex()
00546                                                         )
00547                                                     ];
00548                 // Create a new tv
00549                 TrackingVertex trackingVertex;
00550                 // Get the parent simVertex associated to the current simTrack
00551                 SimVertex const * parentSimVertex = & simVertexes_->getObject(parentSimVertexIndex);
00552 
00553                 bool vetoSimVertex = vetoedSimVertexes.find(parentSimVertexIndex) != vetoedSimVertexes.end();
00554 
00555                 // Check for a already visited parent simTrack
00556                 if ( !vetoSimVertex )
00557                 {
00558                     // Set the tv by using simvertex
00559                     trackingVertexIndex = setTrackingVertex(*parentSimVertex, trackingVertex);
00560 
00561                     // Check if a new vertex needs to be created
00562                     if (trackingVertexIndex < 0)
00563                     {
00564                         // Set the tv index ot its new value
00565                         trackingVertexIndex = trackingVertexes_->size();
00566                         // Push the new tv in to the collection
00567                         trackingVertexes_->push_back(trackingVertex);
00568                     }
00569                     else
00570                     {
00571                         // Get the postion and time of the vertex
00572                         const LorentzVector & position = trackingVertexes_->at(trackingVertexIndex).position();
00573                         Vector xyz = Vector(position.x(), position.y(), position.z());
00574                         double t = position.t();
00575                         // Set the vertex postion of the tp to the closest vertex
00576                         trackingParticles_->at(trackingParticleIndex).setVertex(xyz, t);
00577                     }
00578 
00579                     vetoedSimVertexes.insert( std::make_pair(parentSimVertexIndex, trackingVertexIndex) );
00580                 }
00581                 else
00582                     trackingVertexIndex = vetoedSimVertexes[parentSimVertexIndex];
00583 
00584                 // Set the newly created tv as parent vertex
00585                 trackingParticles_->at(trackingParticleIndex).setParentVertex(
00586                     TrackingVertexRef(refTrackingVertexes_, trackingVertexIndex)
00587                 );
00588 
00589                 // Add the newly created tp to the tv daughter list
00590                 trackingVertexes_->at(trackingVertexIndex).addDaughterTrack(
00591                     TrackingParticleRef(refTrackingParticles_, trackingParticleIndex)
00592                 );
00593 
00594                 // Verify if the parent simVertex has a simTrack or if the source is a vetoSimVertex
00595                 if (parentSimVertex->noParent() || vetoSimVertex) break;
00596 
00597                 // Get the next simTrack index (it is implicit should be in the same event as current).
00598                 unsigned int nextSimTrackIndex = trackIdToIndex_[
00599                                                      EncodedTruthId(
00600                                                          currentSimTrack->eventId(),
00601                                                          parentSimVertex->parentIndex()
00602                                                      )
00603                                                  ];
00604 
00605                 // Check if the next track exist
00606                 if ( vetoedTracks.find(nextSimTrackIndex) != vetoedTracks.end() )
00607                 {
00608                     // Add to the newly created tv the existent next simtrack in to parent list.
00609                     trackingVertexes_->at(trackingVertexIndex).addParentTrack(
00610                         TrackingParticleRef(refTrackingParticles_, vetoedTracks[nextSimTrackIndex])
00611                     );
00612                     // Add the vertex to list of decay vertexes of the new tp
00613                     trackingParticles_->at(vetoedTracks[nextSimTrackIndex]).addDecayVertex(
00614                         TrackingVertexRef(refTrackingVertexes_, trackingVertexIndex)
00615                     );
00616                     break;
00617                 }
00618 
00619                 // Vetoed the next simTrack
00620                 vetoedTracks.insert( std::make_pair(nextSimTrackIndex, trackingParticleIndex) );
00621 
00622                 // Set the current simTrack as the next simTrack
00623                 currentSimTrack = & simTracks_->getObject(nextSimTrackIndex);
00624             }
00625             while (!currentSimTrack->noVertex());
00626         }
00627     }
00628 }
00629 
00630 
00631 bool TrackingTruthProducer::setTrackingParticle(
00632     SimTrack const & simTrack,
00633     TrackingParticle & trackingParticle
00634 )
00635 {
00636     // Get the eventid associated to the track
00637     EncodedEventId trackEventId = simTrack.eventId();
00638     // Get the simtrack id
00639     EncodedTruthId simTrackId = EncodedTruthId( trackEventId, simTrack.trackId() );
00640 
00641     // Location of the parent vertex
00642     LorentzVector position;
00643     // If not parent then location is (0,0,0,0)
00644     if (simTrack.noVertex())
00645         position = LorentzVector(0, 0, 0, 0);
00646     else
00647         position = simVertexes_->getObject(simTrack.vertIndex()). position();
00648 
00649     // Define the default status and pdgid
00650     int status = -99;
00651     int pdgId = simTrack.type();
00652 
00653     int genParticleIndex = simTrack.genpartIndex();
00654     bool signalEvent = (trackEventId.event() == 0 && trackEventId.bunchCrossing() == 0);
00655 
00656     // In the case of a existing generated particle and track
00657     // event is signal redefine status a pdgId
00658 
00659     edm::Handle<edm::HepMCProduct> hepmc;
00660 
00661     if (genParticleIndex >= 0 && (signalEvent || useMultipleHepMCLabels_) )
00662     {
00663         // Get the generated particle
00664         hepmc = (useMultipleHepMCLabels_) ? hepMCProducts_.at(trackEventId.rawId()) : hepmc = hepMCProducts_.at(0);
00665 
00666         const HepMC::GenParticle * genParticle = hepmc->GetEvent()->barcode_to_particle(genParticleIndex);
00667 
00668         if (genParticle)
00669         {
00670             status = genParticle->status();
00671             pdgId  = genParticle->pdg_id();
00672         }
00673     }
00674 
00675     // Create a tp from the simtrack
00676     trackingParticle = TrackingParticle(
00677                            (char) simTrack.charge(),
00678                            simTrack.momentum(),
00679                            Vector(position.x(), position.y(), position.z()),
00680                            position.t(),
00681                            pdgId,
00682                            status,
00683                            trackEventId
00684                        );
00685 
00686     bool init = true;
00687 
00688     int processType = 0;
00689     int particleType = 0;
00690 
00691     // Counting the TP hits using the layers (as in ORCA).
00692     // Does seem to find less hits. maybe b/c layer is a number now, not a pointer
00693     int totalSimHits = 0;
00694     int oldLayer = 0;
00695     int newLayer = 0;
00696     int oldDetector = 0;
00697     int newDetector = 0;
00698 
00699     // Loop over the associated hits per track
00700     for (
00701         EncodedTruthIdToIndexes::const_iterator iEntry = trackIdToHits_.lower_bound(simTrackId);
00702         iEntry != trackIdToHits_.upper_bound(simTrackId);
00703         ++iEntry
00704     )
00705     {
00706         // Get a constant reference to the simhit
00707         PSimHit const & pSimHit = pSimHits_.at(iEntry->second);
00708 
00709         // Initial condition for consistent simhit selection
00710         if (init)
00711         {
00712             processType = pSimHit.processType();
00713             particleType = pSimHit.particleType();
00714             init = false;
00715         }
00716 
00717         // Check for delta and interaction products discards
00718         if (processType == pSimHit.processType() && particleType == pSimHit.particleType() && pdgId == pSimHit.particleType() )
00719         {
00720             trackingParticle.addPSimHit(pSimHit);
00721 
00722             unsigned int detectorIdIndex = pSimHit.detUnitId();
00723             DetId detectorId = DetId(detectorIdIndex);
00724             oldLayer = newLayer;
00725             oldDetector = newDetector;
00726             newLayer = LayerFromDetid(detectorIdIndex);
00727             newDetector = detectorId.subdetId();
00728 
00729             // Count hits using layers for glued detectors
00730             // newlayer !=0 excludes Muon layers set to 0 by LayerFromDetid
00731             if ( ( oldLayer != newLayer || (oldLayer==newLayer && oldDetector!=newDetector ) ) && newLayer != 0 ) totalSimHits++;
00732         }
00733     }
00734 
00735     // Set the number of matched simhits
00736     trackingParticle.setMatchedHit(totalSimHits);
00737 
00738     // Add the simtrack associated to the tp
00739     trackingParticle.addG4Track(simTrack);
00740 
00741     // Add the generator information
00742     if ( genParticleIndex >= 0 && (signalEvent || useMultipleHepMCLabels_) )
00743         trackingParticle.addGenParticle( GenParticleRef(hepmc, genParticleIndex) );
00744 
00745     if (selectorFlag_) return selector_(trackingParticle);
00746 
00747     return true;
00748 }
00749 
00750 
00751 int TrackingTruthProducer::setTrackingVertex(
00752     SimVertex const & simVertex,
00753     TrackingVertex & trackingVertex
00754 )
00755 {
00756     LorentzVector const & position = simVertex.position();
00757 
00758     // Look for close by vertexes
00759     for (std::size_t trackingVertexIndex = 0; trackingVertexIndex < trackingVertexes_->size(); ++trackingVertexIndex)
00760     {
00761         // Calculate the distance
00762         double distance = (position - trackingVertexes_->at(trackingVertexIndex).position()).P();
00763         // If the distance is under a given cut return the trackingVertex index (vertex merging)
00764         if (distance <= distanceCut_)
00765         {
00766             // Add simvertex to the pre existent tv
00767             trackingVertexes_->at(trackingVertexIndex).addG4Vertex(simVertex);
00768             // return tv index
00769             return trackingVertexIndex;
00770         }
00771     }
00772 
00773     // Get the event if from the simvertex
00774     EncodedEventId simVertexEventId = simVertex.eventId();
00775 
00776     // Initialize the event counter
00777     if (eventIdCounter_.find(simVertexEventId) == eventIdCounter_.end())
00778         eventIdCounter_[simVertexEventId] = 0;
00779 
00780     // Get the simVertex id
00781     EncodedTruthId simVertexId = EncodedTruthId(simVertexEventId, eventIdCounter_[simVertexEventId]);
00782 
00783     // Calculate if the vertex is in the tracker volume (it needs to be review for other detectors)
00784     bool inVolume = (position.Pt() < volumeRadius_ && std::abs(position.z()) < volumeZ_); // In or out of Tracker
00785 
00786     // Initialize the new vertex
00787     trackingVertex = TrackingVertex(position, inVolume, simVertexId);
00788 
00789     // Find the the closest GenVertexes to the created tv
00790     addCloseGenVertexes(trackingVertex);
00791 
00792     // Add the g4 vertex to the tv
00793     trackingVertex.addG4Vertex(simVertex);
00794 
00795     // Initialize the event counter
00796     eventIdCounter_[simVertexEventId]++;
00797 
00798     return -1;
00799 }
00800 
00801 
00802 void TrackingTruthProducer::addCloseGenVertexes(TrackingVertex & trackingVertex)
00803 {
00804     // Get the generated particle
00805     edm::Handle<edm::HepMCProduct> hepmc = (useMultipleHepMCLabels_) ? hepMCProducts_.at(trackingVertex.eventId().rawId()) : hepMCProducts_.at(0);
00806     const HepMC::GenEvent * genEvent = hepmc->GetEvent();
00807 
00808     // Get the postion of the tv
00809     Vector tvPosition(trackingVertex.position().x(), trackingVertex.position().y(), trackingVertex.position().z());
00810 
00811     // Find HepMC vertices, put them in a close TrackingVertex (this could conceivably add the same GenVertex to multiple TrackingVertices)
00812     for (
00813         HepMC::GenEvent::vertex_const_iterator iGenVertex = genEvent->vertices_begin();
00814         iGenVertex != genEvent->vertices_end();
00815         ++iGenVertex
00816     )
00817     {
00818         // Get the position of the genVertex
00819         HepMC::ThreeVector rawPosition = (*iGenVertex)->position();
00820 
00821         // Convert to cm
00822         Vector genPosition(rawPosition.x()/10.0, rawPosition.y()/10.0, rawPosition.z()/10.0);
00823 
00824         // Calculate the dis
00825         double distance = sqrt( (tvPosition - genPosition).mag2() );
00826 
00827         if (distance <= distanceCut_)
00828             trackingVertex.addGenVertex( GenVertexRef(hepmc, (*iGenVertex)->barcode()) );
00829     }
00830 }
00831 
00832 
00833 int TrackingTruthProducer::LayerFromDetid(const unsigned int & detid)
00834 {
00835     DetId detId = DetId(detid);
00836 
00837     if ( detId.det() != DetId::Tracker ) return 0;
00838 
00839     int layerNumber=0;
00840     unsigned int subdetId = static_cast<unsigned int>(detId.subdetId());
00841 
00842     if ( subdetId == StripSubdetector::TIB)
00843     {
00844         TIBDetId tibid(detId.rawId());
00845         layerNumber = tibid.layer();
00846     }
00847     else if ( subdetId ==  StripSubdetector::TOB )
00848     {
00849         TOBDetId tobid(detId.rawId());
00850         layerNumber = tobid.layer();
00851     }
00852     else if ( subdetId ==  StripSubdetector::TID)
00853     {
00854         TIDDetId tidid(detId.rawId());
00855         layerNumber = tidid.wheel();
00856     }
00857     else if ( subdetId ==  StripSubdetector::TEC )
00858     {
00859         TECDetId tecid(detId.rawId());
00860         layerNumber = tecid.wheel();
00861     }
00862     else if ( subdetId ==  PixelSubdetector::PixelBarrel )
00863     {
00864         PXBDetId pxbid(detId.rawId());
00865         layerNumber = pxbid.layer();
00866     }
00867     else if ( subdetId ==  PixelSubdetector::PixelEndcap )
00868     {
00869         PXFDetId pxfid(detId.rawId());
00870         layerNumber = pxfid.disk();
00871     }
00872     else
00873         edm::LogVerbatim("TrackingTruthProducer") << "Unknown subdetid: " <<  subdetId;
00874 
00875     return layerNumber;
00876 }
00877 
00878 DEFINE_FWK_MODULE(TrackingTruthProducer);