CMS 3D CMS Logo

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