00001
00023 #include "SimGeneral/TrackingAnalysis/interface/TrackingTruthAccumulator.h"
00024
00025 #include <SimGeneral/MixingModule/interface/DigiAccumulatorMixModFactory.h>
00026 #include <FWCore/MessageLogger/interface/MessageLogger.h>
00027 #include <FWCore/Framework/interface/Event.h>
00028 #include <FWCore/Framework/interface/EventSetup.h>
00029 #include <FWCore/ParameterSet/interface/ParameterSet.h>
00030 #include <SimGeneral/MixingModule/interface/PileUpEventPrincipal.h>
00031 #include "FWCore/Framework/interface/EDProducer.h"
00032 #include "SimGeneral/TrackingAnalysis/interface/EncodedTruthId.h"
00033 #include "SimDataFormats/GeneratorProducts/interface/HepMCProduct.h"
00034 #include "SimDataFormats/TrackingAnalysis/interface/TrackingParticle.h"
00035 #include "SimDataFormats/TrackingAnalysis/interface/TrackingVertex.h"
00036 #include "SimDataFormats/TrackingHit/interface/PSimHit.h"
00037 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00038
00039 #include "DataFormats/SiPixelDetId/interface/PixelSubdetector.h"
00040 #include "DataFormats/SiStripDetId/interface/StripSubdetector.h"
00041 #include "DataFormats/SiPixelDetId/interface/PXBDetId.h"
00042 #include "DataFormats/SiPixelDetId/interface/PXFDetId.h"
00043 #include "DataFormats/SiStripDetId/interface/TECDetId.h"
00044 #include "DataFormats/SiStripDetId/interface/TIBDetId.h"
00045 #include "DataFormats/SiStripDetId/interface/TIDDetId.h"
00046 #include "DataFormats/SiStripDetId/interface/TOBDetId.h"
00047 #include "DataFormats/HepMCCandidate/interface/GenParticle.h"
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 namespace
00064 {
00069 struct DecayChainTrack
00070 {
00071 int simTrackIndex;
00072 struct DecayChainVertex* pParentVertex;
00073
00074 std::vector<struct DecayChainVertex*> daughterVertices;
00075 DecayChainTrack* pMergedBremSource;
00076 DecayChainTrack() : simTrackIndex(-1), pParentVertex(NULL), pMergedBremSource(NULL) {}
00077 DecayChainTrack( int newSimTrackIndex ) : simTrackIndex(newSimTrackIndex), pParentVertex(NULL), pMergedBremSource() {}
00078 };
00079
00084 struct DecayChainVertex
00085 {
00086 int simVertexIndex;
00087 DecayChainTrack* pParentTrack;
00088 std::vector<DecayChainTrack*> daughterTracks;
00089 DecayChainVertex* pMergedBremSource;
00090 DecayChainVertex() : simVertexIndex(-1), pParentTrack(NULL), pMergedBremSource(NULL) {}
00091 DecayChainVertex( int newIndex ) : simVertexIndex(newIndex), pParentTrack(NULL), pMergedBremSource(NULL) {}
00092 };
00093
00104 struct DecayChain
00105 {
00106 public:
00107 DecayChain( const std::vector<SimTrack>& trackCollection, const std::vector<SimVertex>& vertexCollection );
00108 const size_t decayTracksSize;
00109 const size_t decayVerticesSize;
00110
00115 void integrityCheck();
00116 const SimTrack& getSimTrack( const ::DecayChainTrack* pDecayTrack ) const { return simTrackCollection_.at( pDecayTrack->simTrackIndex ); }
00117 const SimVertex& getSimVertex( const ::DecayChainVertex* pDecayVertex ) const { return simVertexCollection_.at( pDecayVertex->simVertexIndex ); }
00118 private:
00119 void findBrem( const std::vector<SimTrack>& trackCollection, const std::vector<SimVertex>& vertexCollection );
00120 std::unique_ptr< ::DecayChainTrack[]> decayTracks_;
00121 std::unique_ptr< ::DecayChainVertex[]> decayVertices_;
00122
00124 std::vector< ::DecayChainVertex*> rootVertices_;
00125
00126
00127 const std::vector<SimTrack>& simTrackCollection_;
00128 const std::vector<SimVertex>& simVertexCollection_;
00129 public:
00130 const std::unique_ptr< ::DecayChainTrack[]>& decayTracks;
00131 const std::unique_ptr< ::DecayChainVertex[]>& decayVertices;
00132 const std::vector< ::DecayChainVertex*>& rootVertices;
00133 };
00134
00139 class TrackingParticleFactory
00140 {
00141 public:
00142 TrackingParticleFactory( const ::DecayChain& decayChain, const edm::Handle< std::vector<reco::GenParticle> >& hGenParticles,
00143 const edm::Handle< std::vector<int> >& hHepMCGenParticleIndices, const std::vector<const PSimHit*>& simHits,
00144 double volumeRadius, double volumeZ, bool allowDifferentProcessTypes );
00145 TrackingParticle createTrackingParticle( const DecayChainTrack* pTrack ) const;
00146 TrackingVertex createTrackingVertex( const DecayChainVertex* pVertex ) const;
00147 bool vectorIsInsideVolume( const math::XYZTLorentzVectorD& vector ) const;
00148 private:
00149 const ::DecayChain& decayChain_;
00150 const edm::Handle< std::vector<reco::GenParticle> >& hGenParticles_;
00151 std::vector<int> genParticleIndices_;
00152 const std::vector<const PSimHit*>& simHits_;
00153 const double volumeRadius_;
00154 const double volumeZ_;
00155 std::multimap<unsigned int, size_t> trackIdToHitIndex_;
00156 bool allowDifferentProcessTypeForDifferentDetectors_;
00157 };
00158
00163 class OutputCollectionWrapper
00164 {
00165 public:
00166 OutputCollectionWrapper( const DecayChain& decayChain, TrackingTruthAccumulator::OutputCollections& outputCollections );
00167 TrackingParticle* addTrackingParticle( const ::DecayChainTrack* pDecayTrack, const TrackingParticle& trackingParticle );
00168 TrackingVertex* addTrackingVertex( const ::DecayChainVertex* pDecayVertex, const TrackingVertex& trackingVertex );
00169 TrackingParticle* getTrackingParticle( const ::DecayChainTrack* pDecayTrack );
00171 void setProxy( const ::DecayChainTrack* pOriginalTrack, const ::DecayChainTrack* pProxyTrack );
00172 void setProxy( const ::DecayChainVertex* pOriginalVertex, const ::DecayChainVertex* pProxyVertex );
00173 TrackingVertex* getTrackingVertex( const ::DecayChainVertex* pDecayVertex );
00174 TrackingParticleRef getRef( const ::DecayChainTrack* pDecayTrack );
00175 TrackingVertexRef getRef( const ::DecayChainVertex* pDecayVertex );
00176 private:
00177 void associateToExistingObjects( const ::DecayChainVertex* pChainVertex );
00178 void associateToExistingObjects( const ::DecayChainTrack* pChainTrack );
00179 TrackingTruthAccumulator::OutputCollections& output_;
00180 std::vector<int> trackingParticleIndices_;
00181 std::vector<int> trackingVertexIndices_;
00182 };
00183
00186 int LayerFromDetid( const DetId& detid );
00187
00192 TrackingParticle* addTrackAndParentVertex( ::DecayChainTrack* pDecayTrack, const TrackingParticle& trackingParticle, ::OutputCollectionWrapper* pOutput );
00193
00198 void addTrack( ::DecayChainTrack* pDecayChainTrack, const TrackingParticleSelector* pSelector, ::OutputCollectionWrapper* pUnmergedOutput, ::OutputCollectionWrapper* pMergedOutput, const ::TrackingParticleFactory& objectFactory, bool addAncestors );
00199
00200 }
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216 TrackingTruthAccumulator::TrackingTruthAccumulator( const edm::ParameterSet & config, edm::EDProducer& mixMod ) :
00217 messageCategory_("TrackingTruthAccumulator"),
00218 volumeRadius_( config.getParameter<double>("volumeRadius") ),
00219 volumeZ_( config.getParameter<double>("volumeZ") ),
00220 ignoreTracksOutsideVolume_( config.getParameter<bool>("ignoreTracksOutsideVolume") ),
00221 maximumPreviousBunchCrossing_( config.getParameter<unsigned int>("maximumPreviousBunchCrossing") ),
00222 maximumSubsequentBunchCrossing_( config.getParameter<unsigned int>("maximumSubsequentBunchCrossing") ),
00223 createUnmergedCollection_( config.getParameter<bool>("createUnmergedCollection") ),
00224 createMergedCollection_(config.getParameter<bool>("createMergedBremsstrahlung") ),
00225 addAncestors_( config.getParameter<bool>("alwaysAddAncestors") ),
00226 removeDeadModules_( config.getParameter<bool>("removeDeadModules") ),
00227 simTrackLabel_( config.getParameter<edm::InputTag>("simTrackCollection") ),
00228 simVertexLabel_( config.getParameter<edm::InputTag>("simVertexCollection") ),
00229 simHitCollectionConfig_( config.getParameter<edm::ParameterSet>("simHitCollections") ),
00230 genParticleLabel_( config.getParameter<edm::InputTag>("genParticleCollection") ),
00231 allowDifferentProcessTypeForDifferentDetectors_( config.getParameter<bool>("allowDifferentSimHitProcesses") )
00232 {
00233
00234
00235
00236
00237 if( !createUnmergedCollection_ && !createMergedCollection_ )
00238 edm::LogError(messageCategory_) << "Both \"createUnmergedCollection\" and \"createMergedBremsstrahlung\" have been"
00239 << "set to false, which means no collections will be created";
00240
00241
00242
00243
00244
00245 if( config.exists( "select" ) )
00246 {
00247 edm::ParameterSet param=config.getParameter<edm::ParameterSet>("select");
00248 selector_=TrackingParticleSelector( param.getParameter<double>( "ptMinTP" ),
00249 param.getParameter<double>( "minRapidityTP" ),
00250 param.getParameter<double>( "maxRapidityTP" ),
00251 param.getParameter<double>( "tipTP" ),
00252 param.getParameter<double>( "lipTP" ),
00253 param.getParameter<int>( "minHitTP" ),
00254 param.getParameter<bool>( "signalOnlyTP" ),
00255 param.getParameter<bool>( "chargedOnlyTP" ),
00256 param.getParameter<bool>( "stableOnlyTP" ),
00257 param.getParameter<std::vector<int> >("pdgIdTP") );
00258 selectorFlag_=true;
00259
00260
00261
00262 chargedOnly_=param.getParameter<bool>( "chargedOnlyTP" );
00263 signalOnly_=param.getParameter<bool>( "signalOnlyTP" );
00264 }
00265 else
00266 {
00267 selectorFlag_=false;
00268 chargedOnly_=false;
00269 signalOnly_=false;
00270 }
00271
00272
00273
00274
00275
00276
00277 if( createUnmergedCollection_ )
00278 {
00279 mixMod.produces<TrackingVertexCollection>();
00280 mixMod.produces<TrackingParticleCollection>();
00281 }
00282
00283 if( createMergedCollection_ )
00284 {
00285 mixMod.produces<TrackingParticleCollection>("MergedTrackTruth");
00286 mixMod.produces<TrackingVertexCollection>("MergedTrackTruth");
00287 }
00288 }
00289
00290 void TrackingTruthAccumulator::initializeEvent( edm::Event const& event, edm::EventSetup const& setup )
00291 {
00292 if( createUnmergedCollection_ )
00293 {
00294 unmergedOutput_.pTrackingParticles.reset( new TrackingParticleCollection );
00295 unmergedOutput_.pTrackingVertices.reset( new TrackingVertexCollection );
00296 unmergedOutput_.refTrackingParticles=const_cast<edm::Event&>( event ).getRefBeforePut<TrackingParticleCollection>();
00297 unmergedOutput_.refTrackingVertexes=const_cast<edm::Event&>( event ).getRefBeforePut<TrackingVertexCollection>();
00298 }
00299
00300 if( createMergedCollection_ )
00301 {
00302 mergedOutput_.pTrackingParticles.reset( new TrackingParticleCollection );
00303 mergedOutput_.pTrackingVertices.reset( new TrackingVertexCollection );
00304 mergedOutput_.refTrackingParticles=const_cast<edm::Event&>( event ).getRefBeforePut<TrackingParticleCollection>("MergedTrackTruth");
00305 mergedOutput_.refTrackingVertexes=const_cast<edm::Event&>( event ).getRefBeforePut<TrackingVertexCollection>("MergedTrackTruth");
00306 }
00307 }
00308
00309 void TrackingTruthAccumulator::accumulate( edm::Event const& event, edm::EventSetup const& setup )
00310 {
00311
00312 accumulateEvent( event, setup );
00313 }
00314
00315 void TrackingTruthAccumulator::accumulate( PileUpEventPrincipal const& event, edm::EventSetup const& setup )
00316 {
00317
00318 if( event.bunchCrossing()>=-static_cast<int>(maximumPreviousBunchCrossing_) && event.bunchCrossing()<=static_cast<int>(maximumSubsequentBunchCrossing_) )
00319 {
00320
00321 accumulateEvent( event, setup );
00322 }
00323 else edm::LogInfo(messageCategory_) << "Skipping pileup event for bunch crossing " << event.bunchCrossing();
00324 }
00325
00326 void TrackingTruthAccumulator::finalizeEvent( edm::Event& event, edm::EventSetup const& setup )
00327 {
00328
00329 if( createUnmergedCollection_ )
00330 {
00331 edm::LogInfo("TrackingTruthAccumulator") << "Adding " << unmergedOutput_.pTrackingParticles->size() << " TrackingParticles and " << unmergedOutput_.pTrackingVertices->size()
00332 << " TrackingVertexs to the event.";
00333
00334 event.put( unmergedOutput_.pTrackingParticles );
00335 event.put( unmergedOutput_.pTrackingVertices );
00336 }
00337
00338 if( createMergedCollection_ )
00339 {
00340 edm::LogInfo("TrackingTruthAccumulator") << "Adding " << mergedOutput_.pTrackingParticles->size() << " merged TrackingParticles and " << mergedOutput_.pTrackingVertices->size()
00341 << " merged TrackingVertexs to the event.";
00342
00343 event.put( mergedOutput_.pTrackingParticles, "MergedTrackTruth" );
00344 event.put( mergedOutput_.pTrackingVertices, "MergedTrackTruth" );
00345 }
00346
00347 }
00348
00349 template<class T> void TrackingTruthAccumulator::accumulateEvent( const T& event, const edm::EventSetup& setup )
00350 {
00351
00352
00353
00354 edm::Handle<std::vector<SimTrack> > hSimTracks;
00355 edm::Handle<std::vector<SimVertex> > hSimVertices;
00356 edm::Handle< std::vector<reco::GenParticle> > hGenParticles;
00357 edm::Handle< std::vector<int> > hGenParticleIndices;
00358
00359 event.getByLabel( simTrackLabel_, hSimTracks );
00360 event.getByLabel( simVertexLabel_, hSimVertices );
00361
00362 try
00363 {
00364 event.getByLabel( genParticleLabel_, hGenParticles );
00365 event.getByLabel( genParticleLabel_, hGenParticleIndices );
00366 }
00367 catch( cms::Exception& exception )
00368 {
00369
00370
00371
00372
00373
00374
00375
00376 }
00377
00378
00379
00380
00381
00382
00383 DecayChain decayChain( *hSimTracks, *hSimVertices );
00384
00385
00386 std::auto_ptr< ::OutputCollectionWrapper> pUnmergedCollectionWrapper;
00387 std::auto_ptr< ::OutputCollectionWrapper> pMergedCollectionWrapper;
00388 if( createUnmergedCollection_ ) pUnmergedCollectionWrapper.reset( new ::OutputCollectionWrapper( decayChain, unmergedOutput_ ) );
00389 if( createMergedCollection_ ) pMergedCollectionWrapper.reset( new ::OutputCollectionWrapper( decayChain, mergedOutput_ ) );
00390
00391 std::vector<const PSimHit*> simHitPointers;
00392 fillSimHits( simHitPointers, event, setup );
00393 TrackingParticleFactory objectFactory( decayChain, hGenParticles, hGenParticleIndices, simHitPointers, volumeRadius_, volumeZ_, allowDifferentProcessTypeForDifferentDetectors_ );
00394
00395
00396
00397
00398
00399 TrackingParticleSelector* pSelector=NULL;
00400 if( selectorFlag_ ) pSelector=&selector_;
00401
00402
00403
00404
00405
00406
00407 for( size_t index=0; index<decayChain.decayTracksSize; ++index )
00408 {
00409 ::DecayChainTrack* pDecayTrack=&decayChain.decayTracks[index];
00410 const SimTrack& simTrack=hSimTracks->at(pDecayTrack->simTrackIndex);
00411
00412
00413
00414
00415
00416
00417 if( chargedOnly_ && simTrack.charge()==0 ) continue;
00418 if( signalOnly_ && (simTrack.eventId().bunchCrossing()!=0 || simTrack.eventId().event()!=0) ) continue;
00419
00420
00421 if( ignoreTracksOutsideVolume_ )
00422 {
00423 const SimVertex& simVertex=hSimVertices->at( pDecayTrack->pParentVertex->simVertexIndex );
00424 if( !objectFactory.vectorIsInsideVolume( simVertex.position() ) ) continue;
00425 }
00426
00427
00428
00429
00430
00431 ::addTrack( pDecayTrack, pSelector, pUnmergedCollectionWrapper.get(), pMergedCollectionWrapper.get(), objectFactory, addAncestors_ );
00432 }
00433 }
00434
00435 template<class T> void TrackingTruthAccumulator::fillSimHits( std::vector<const PSimHit*>& returnValue, const T& event, const edm::EventSetup& setup )
00436 {
00437 std::vector<std::string> parameterNames=simHitCollectionConfig_.getParameterNames();
00438
00439
00440
00441 for( const auto& parameterName : parameterNames )
00442 {
00443 std::vector<edm::InputTag> collectionTags=simHitCollectionConfig_.getParameter<std::vector<edm::InputTag> >(parameterName);
00444
00445 for( const auto& collectionTag : collectionTags )
00446 {
00447 edm::Handle< std::vector<PSimHit> > hSimHits;
00448 event.getByLabel( collectionTag, hSimHits );
00449
00450
00451 for( const auto& simHit : *hSimHits )
00452 {
00453 returnValue.push_back( &simHit );
00454 }
00455
00456 }
00457 }
00458 }
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475 namespace
00476 {
00477
00478
00479
00480
00481
00482
00483 ::TrackingParticleFactory::TrackingParticleFactory( const ::DecayChain& decayChain, const edm::Handle< std::vector<reco::GenParticle> >& hGenParticles,
00484 const edm::Handle< std::vector<int> >& hHepMCGenParticleIndices, const std::vector<const PSimHit*>& simHits,
00485 double volumeRadius, double volumeZ, bool allowDifferentProcessTypes )
00486 : decayChain_(decayChain), hGenParticles_(hGenParticles), simHits_(simHits), volumeRadius_(volumeRadius),
00487 volumeZ_(volumeZ), allowDifferentProcessTypeForDifferentDetectors_(allowDifferentProcessTypes)
00488 {
00489
00490
00491 for( size_t index=0; index<simHits_.size(); ++index )
00492 {
00493 trackIdToHitIndex_.insert( std::make_pair( simHits_[index]->trackId(), index ) );
00494 }
00495
00496 if( hHepMCGenParticleIndices.isValid() )
00497 {
00498 genParticleIndices_.resize( hHepMCGenParticleIndices->size()+1 );
00499
00500
00501
00502 for( size_t recoGenParticleIndex=0; recoGenParticleIndex<hHepMCGenParticleIndices->size(); ++recoGenParticleIndex )
00503 {
00504 size_t hepMCGenParticleIndex=(*hHepMCGenParticleIndices)[recoGenParticleIndex];
00505
00506
00507 if( genParticleIndices_.size()<hepMCGenParticleIndex ) genParticleIndices_.resize(hepMCGenParticleIndex);
00508
00509 genParticleIndices_[ hepMCGenParticleIndex ]=recoGenParticleIndex;
00510 }
00511 }
00512 }
00513
00514 TrackingParticle TrackingParticleFactory::createTrackingParticle( const ::DecayChainTrack* pChainTrack ) const
00515 {
00516 typedef math::XYZTLorentzVectorD LorentzVector;
00517 typedef math::XYZPoint Vector;
00518
00519 const SimTrack& simTrack=decayChain_.getSimTrack( pChainTrack );
00520 const SimVertex& parentSimVertex=decayChain_.getSimVertex( pChainTrack->pParentVertex );
00521
00522 LorentzVector position( 0, 0, 0, 0 );
00523 if( !simTrack.noVertex() ) position=parentSimVertex.position();
00524
00525 int pdgId=simTrack.type();
00526
00527 TrackingParticle returnValue;
00528
00529
00530
00531
00532
00533
00534
00535
00536 if( simTrack.eventId().event()==0 && simTrack.eventId().bunchCrossing()==0 )
00537 {
00538 int hepMCGenParticleIndex=simTrack.genpartIndex();
00539 if( hepMCGenParticleIndex>=0 && hGenParticles_.isValid() )
00540 {
00541 int recoGenParticleIndex=genParticleIndices_[hepMCGenParticleIndex];
00542 reco::GenParticleRef generatorParticleRef( hGenParticles_, recoGenParticleIndex );
00543 pdgId=generatorParticleRef->pdgId();
00544 returnValue.addGenParticle( generatorParticleRef );
00545 }
00546 }
00547
00548 returnValue.addG4Track( simTrack );
00549
00550
00551
00552
00553 size_t matchedHits=0;
00554 size_t numberOfHits=0;
00555 size_t numberOfTrackerHits=0;
00556
00557 bool init=true;
00558 int processType=0;
00559 int particleType=0;
00560 int oldLayer = 0;
00561 int newLayer = 0;
00562 DetId oldDetector;
00563 DetId newDetector;
00564
00565 for( std::multimap<unsigned int,size_t>::const_iterator iHitIndex=trackIdToHitIndex_.lower_bound( simTrack.trackId() );
00566 iHitIndex!=trackIdToHitIndex_.upper_bound( simTrack.trackId() );
00567 ++iHitIndex )
00568 {
00569 const auto& pSimHit=simHits_[ iHitIndex->second ];
00570
00571
00572 if( init )
00573 {
00574 processType=pSimHit->processType();
00575 particleType=pSimHit->particleType();
00576 newDetector=DetId( pSimHit->detUnitId() );
00577 init=false;
00578 }
00579
00580 oldDetector=newDetector;
00581 newDetector=DetId( pSimHit->detUnitId() );
00582
00583
00584
00585 if( allowDifferentProcessTypeForDifferentDetectors_ && newDetector.det()!=oldDetector.det() ) processType=pSimHit->processType();
00586
00587
00588 if( processType==pSimHit->processType() && particleType==pSimHit->particleType() && pdgId==pSimHit->particleType() )
00589 {
00590 ++numberOfHits;
00591 if( newDetector.det() == DetId::Tracker ) ++numberOfTrackerHits;
00592
00593 oldLayer=newLayer;
00594 newLayer=LayerFromDetid( newDetector );
00595
00596
00597
00598 if( (oldLayer!=newLayer || (oldLayer==newLayer && oldDetector.subdetId()!=newDetector.subdetId())) && newLayer!=0 ) ++matchedHits;
00599 }
00600 }
00601
00602 returnValue.setNumberOfTrackerLayers( matchedHits );
00603 returnValue.setNumberOfHits( numberOfHits );
00604 returnValue.setNumberOfTrackerHits( numberOfTrackerHits );
00605
00606 return returnValue;
00607 }
00608
00609 TrackingVertex TrackingParticleFactory::createTrackingVertex( const ::DecayChainVertex* pChainVertex ) const
00610 {
00611 const SimVertex& simVertex=decayChain_.getSimVertex( pChainVertex );
00612
00613 bool isInVolume=this->vectorIsInsideVolume( simVertex.position() );
00614
00615
00616
00617 TrackingVertex returnValue( simVertex.position(), isInVolume, EncodedTruthId( simVertex.eventId(), 0 ) );
00618 return returnValue;
00619 }
00620
00621 bool ::TrackingParticleFactory::vectorIsInsideVolume( const math::XYZTLorentzVectorD& vector ) const
00622 {
00623 return ( vector.Pt()<volumeRadius_ && vector.z()<volumeZ_ );
00624 }
00625
00626
00627
00628
00629
00630
00631
00632 ::DecayChain::DecayChain( const std::vector<SimTrack>& trackCollection, const std::vector<SimVertex>& vertexCollection )
00633 : decayTracksSize( trackCollection.size() ),
00634 decayVerticesSize( vertexCollection.size() ),
00635 decayTracks_( new DecayChainTrack[decayTracksSize] ),
00636 decayVertices_( new DecayChainVertex[decayVerticesSize] ),
00637 simTrackCollection_( trackCollection ),
00638 simVertexCollection_( vertexCollection ),
00639 decayTracks( decayTracks_ ),
00640 decayVertices( decayVertices_ ),
00641 rootVertices( rootVertices_ )
00642 {
00643
00644 std::map<int,::DecayChainTrack*> trackIdToDecayTrack;
00645 std::map<int,::DecayChainVertex*> vertexIdToDecayVertex;
00646
00647
00648
00649
00650
00651 size_t decayVertexIndex=0;
00652 for( size_t index=0; index<trackCollection.size(); ++index )
00653 {
00654 ::DecayChainTrack* pDecayTrack=&decayTracks_[index];
00655
00656
00657
00658
00659 pDecayTrack->simTrackIndex=index;
00660
00661 trackIdToDecayTrack[ trackCollection[index].trackId() ]=pDecayTrack;
00662
00663 int parentVertexIndex=trackCollection[index].vertIndex();
00664 if( parentVertexIndex>=0 )
00665 {
00666
00667 ::DecayChainVertex*& pParentVertex=vertexIdToDecayVertex[parentVertexIndex];
00668 if( pParentVertex==NULL )
00669 {
00670
00671 pParentVertex=&decayVertices_[decayVertexIndex];
00672 ++decayVertexIndex;
00673 pParentVertex->simVertexIndex=parentVertexIndex;
00674 }
00675 pParentVertex->daughterTracks.push_back(pDecayTrack);
00676 pDecayTrack->pParentVertex=pParentVertex;
00677 }
00678 else throw std::runtime_error( "TrackingTruthAccumulator: Found a track with an invalid parent vertex index." );
00679 }
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690 for( auto& decayVertexMapPair : vertexIdToDecayVertex )
00691 {
00692 ::DecayChainVertex* pDecayVertex=decayVertexMapPair.second;
00693 int parentTrackIndex=vertexCollection[pDecayVertex->simVertexIndex].parentIndex();
00694 if( parentTrackIndex!=-1 )
00695 {
00696 std::map<int,::DecayChainTrack*>::iterator iParentTrackMapPair=trackIdToDecayTrack.find(parentTrackIndex);
00697 if( iParentTrackMapPair==trackIdToDecayTrack.end() )
00698 {
00699 std::stringstream errorStream;
00700 errorStream << "TrackingTruthAccumulator: Something has gone wrong with the indexing. Parent track index is " << parentTrackIndex << ".";
00701 throw std::runtime_error( errorStream.str() );
00702 }
00703
00704 ::DecayChainTrack* pParentTrackHierarchy=iParentTrackMapPair->second;
00705
00706 pParentTrackHierarchy->daughterVertices.push_back( pDecayVertex );
00707 pDecayVertex->pParentTrack=pParentTrackHierarchy;
00708 }
00709 else rootVertices_.push_back(pDecayVertex);
00710 }
00711
00712 findBrem( trackCollection, vertexCollection );
00713
00714 }
00715
00716
00717 void ::DecayChain::integrityCheck()
00718 {
00719
00720
00721
00722 for( size_t index=0; index<decayTracksSize; ++index )
00723 {
00724 const auto& decayTrack=decayTracks[index];
00725
00726
00727
00728 if( decayTrack.pParentVertex==NULL ) throw std::runtime_error( "TrackingTruthAccumulator.cc integrityCheck(): Found DecayChainTrack with no parent vertex." );
00729
00730
00731
00732
00733 size_t numberOfTimesListed=0;
00734 for( const auto pSiblingTrack : decayTrack.pParentVertex->daughterTracks )
00735 {
00736 if( pSiblingTrack==&decayTrack ) ++numberOfTimesListed;
00737 }
00738 if( numberOfTimesListed!=1 ) throw std::runtime_error( "TrackingTruthAccumulator.cc integrityCheck(): Found DecayChainTrack whose parent does not have it listed once and only once as a child." );
00739
00740
00741
00742
00743 for( const auto pDaughterVertex : decayTrack.daughterVertices )
00744 {
00745 if( pDaughterVertex->pParentTrack!=&decayTrack ) throw std::runtime_error( "TrackingTruthAccumulator.cc integrityCheck(): Found DecayChainTrack whose child does not have it listed as the parent." );
00746 }
00747
00748
00749
00750
00751 const DecayChainVertex* pAncestorVertex=decayTrack.pParentVertex;
00752 while( pAncestorVertex->pParentTrack!=NULL )
00753 {
00754 if( pAncestorVertex->pParentTrack->pParentVertex==NULL ) throw std::runtime_error( "TrackingTruthAccumulator.cc integrityCheck(): Found DecayChainTrack with no parent vertex higher in the decay chain." );
00755 pAncestorVertex=pAncestorVertex->pParentTrack->pParentVertex;
00756 }
00757 if( std::find( rootVertices.begin(), rootVertices.end(), pAncestorVertex )==rootVertices.end() )
00758 {
00759 throw std::runtime_error( "TrackingTruthAccumulator.cc integrityCheck(): Found DecayChainTrack whose root vertex is not recorded anywhere." );
00760 }
00761 }
00762
00763
00764
00765
00766 for( size_t index=0; index<decayVerticesSize; ++index )
00767 {
00768 const auto& decayVertex=decayVertices[index];
00769
00770
00771
00772
00773 const DecayChainVertex* pAncestorVertex=&decayVertex;
00774 while( pAncestorVertex->pParentTrack!=NULL )
00775 {
00776 if( pAncestorVertex->pParentTrack->pParentVertex==NULL ) throw std::runtime_error( "TrackingTruthAccumulator.cc integrityCheck(): Found DecayChainTrack with no parent vertex higher in the vertex decay chain." );
00777 pAncestorVertex=pAncestorVertex->pParentTrack->pParentVertex;
00778 }
00779 if( std::find( rootVertices.begin(), rootVertices.end(), pAncestorVertex )==rootVertices.end() )
00780 {
00781 throw std::runtime_error( "TrackingTruthAccumulator.cc integrityCheck(): Found DecayChainTrack whose root vertex is not recorded anywhere." );
00782 }
00783
00784
00785
00786
00787 if( decayVertex.pParentTrack!=NULL )
00788 {
00789 size_t numberOfTimesListed=0;
00790 for( const auto pSibling : decayVertex.pParentTrack->daughterVertices )
00791 {
00792 if( pSibling==&decayVertex ) ++numberOfTimesListed;
00793 }
00794 if( numberOfTimesListed!=1 ) throw std::runtime_error( "TrackingTruthAccumulator.cc integrityCheck(): Found DecayChainVertex whose parent does not have it listed once and only once as a child." );
00795 }
00796
00797
00798
00799
00800 for( const auto pDaughter : decayVertex.daughterTracks )
00801 {
00802 if( pDaughter->pParentVertex!=&decayVertex ) throw std::runtime_error( "TrackingTruthAccumulator.cc integrityCheck(): Found DecayChainVertex whose child does not have it listed as the parent." );
00803 }
00804 }
00805
00806 std::cout << "TrackingTruthAccumulator.cc integrityCheck() completed successfully" << std::endl;
00807 }
00808
00809 void ::DecayChain::findBrem( const std::vector<SimTrack>& trackCollection, const std::vector<SimVertex>& vertexCollection )
00810 {
00811 for( size_t index=0; index<decayVerticesSize; ++index )
00812 {
00813 auto& vertex=decayVertices_[index];
00814
00815
00816 if( vertex.pParentTrack==NULL ) continue;
00817 int parentTrackPDG=trackCollection[vertex.pParentTrack->simTrackIndex].type();
00818 if( std::abs( parentTrackPDG )!=11 ) continue;
00819
00820 size_t numberOfElectrons=0;
00821 size_t numberOfNonElectronsOrPhotons=0;
00822 for( auto& pDaughterTrack : vertex.daughterTracks )
00823 {
00824 const auto& simTrack=trackCollection[pDaughterTrack->simTrackIndex];
00825 if( simTrack.type()==11 || simTrack.type()==-11 ) ++numberOfElectrons;
00826 else if( simTrack.type()!=22 ) ++numberOfNonElectronsOrPhotons;
00827 }
00828 if( numberOfElectrons==1 && numberOfNonElectronsOrPhotons==0 )
00829 {
00830
00831
00832 for( auto& pDaughterTrack : vertex.daughterTracks ) pDaughterTrack->pMergedBremSource=vertex.pParentTrack;
00833 vertex.pMergedBremSource=vertex.pParentTrack->pParentVertex;
00834 }
00835 }
00836 }
00837
00838
00839
00840
00841
00842
00843
00844
00845 ::OutputCollectionWrapper::OutputCollectionWrapper( const ::DecayChain& decayChain, TrackingTruthAccumulator::OutputCollections& outputCollections )
00846 : output_(outputCollections),
00847 trackingParticleIndices_(decayChain.decayTracksSize,-1),
00848 trackingVertexIndices_(decayChain.decayVerticesSize,-1)
00849 {
00850
00851 }
00852
00853 TrackingParticle* ::OutputCollectionWrapper::addTrackingParticle( const ::DecayChainTrack* pDecayTrack, const TrackingParticle& trackingParticle )
00854 {
00855 if( trackingParticleIndices_[pDecayTrack->simTrackIndex]!=-1 ) throw std::runtime_error( "OutputCollectionWrapper::addTrackingParticle - trying to add a particle twice" );
00856
00857 trackingParticleIndices_[pDecayTrack->simTrackIndex]=output_.pTrackingParticles->size();
00858 output_.pTrackingParticles->push_back( trackingParticle );
00859
00860
00861 output_.pTrackingParticles->back().clearDecayVertices();
00862 output_.pTrackingParticles->back().clearParentVertex();
00863
00864
00865 associateToExistingObjects( pDecayTrack );
00866
00867 return &output_.pTrackingParticles->back();
00868 }
00869
00870 TrackingVertex* ::OutputCollectionWrapper::addTrackingVertex( const ::DecayChainVertex* pDecayVertex, const TrackingVertex& trackingVertex )
00871 {
00872 if( trackingVertexIndices_[pDecayVertex->simVertexIndex]!=-1 ) throw std::runtime_error( "OutputCollectionWrapper::addTrackingVertex - trying to add a vertex twice" );
00873
00874 trackingVertexIndices_[pDecayVertex->simVertexIndex]=output_.pTrackingVertices->size();
00875 output_.pTrackingVertices->push_back( trackingVertex );
00876
00877
00878 associateToExistingObjects( pDecayVertex );
00879
00880 return &output_.pTrackingVertices->back();
00881 }
00882
00883 TrackingParticle* ::OutputCollectionWrapper::getTrackingParticle( const ::DecayChainTrack* pDecayTrack )
00884 {
00885 const int index=trackingParticleIndices_[pDecayTrack->simTrackIndex];
00886 if( index==-1 ) return NULL;
00887 else return &(*output_.pTrackingParticles)[index];
00888 }
00889
00890 TrackingVertex* ::OutputCollectionWrapper::getTrackingVertex( const ::DecayChainVertex* pDecayVertex )
00891 {
00892 const int index=trackingVertexIndices_[pDecayVertex->simVertexIndex];
00893 if( index==-1 ) return NULL;
00894 else return &(*output_.pTrackingVertices)[index];
00895 }
00896
00897 TrackingParticleRef OutputCollectionWrapper::getRef( const ::DecayChainTrack* pDecayTrack )
00898 {
00899 const int index=trackingParticleIndices_[pDecayTrack->simTrackIndex];
00900 if( index==-1 ) throw std::runtime_error( "OutputCollectionWrapper::getRefTrackingParticle - ref requested for a non existent TrackingParticle" );
00901 else return TrackingParticleRef( output_.refTrackingParticles, index );
00902 }
00903
00904 TrackingVertexRef OutputCollectionWrapper::getRef( const ::DecayChainVertex* pDecayVertex )
00905 {
00906 const int index=trackingVertexIndices_[pDecayVertex->simVertexIndex];
00907 if( index==-1 ) throw std::runtime_error( "OutputCollectionWrapper::getRefTrackingParticle - ref requested for a non existent TrackingVertex" );
00908 else return TrackingVertexRef( output_.refTrackingVertexes, index );
00909 }
00910
00911 void ::OutputCollectionWrapper::setProxy( const ::DecayChainTrack* pOriginalTrack, const ::DecayChainTrack* pProxyTrack )
00912 {
00913 int& index=trackingParticleIndices_[pOriginalTrack->simTrackIndex];
00914 if( index!=-1 ) throw std::runtime_error( "OutputCollectionWrapper::setProxy() was called for a TrackingParticle that has already been created" );
00915
00916 index=trackingParticleIndices_[pProxyTrack->simTrackIndex];
00917 }
00918
00919 void ::OutputCollectionWrapper::setProxy( const ::DecayChainVertex* pOriginalVertex, const ::DecayChainVertex* pProxyVertex )
00920 {
00921 int& index=trackingVertexIndices_[pOriginalVertex->simVertexIndex];
00922 const int newIndex=trackingVertexIndices_[pProxyVertex->simVertexIndex];
00923
00924 if( index!=-1 && index!=newIndex ) throw std::runtime_error( "OutputCollectionWrapper::setProxy() was called for a TrackingVertex that has already been created" );
00925
00926
00927 index=newIndex;
00928 }
00929
00930 void ::OutputCollectionWrapper::associateToExistingObjects( const ::DecayChainVertex* pChainVertex )
00931 {
00932
00933 TrackingVertex* pTrackingVertex=getTrackingVertex( pChainVertex );
00934 if( pTrackingVertex==NULL ) throw std::runtime_error( "associateToExistingObjects was passed a non existent TrackingVertex" );
00935
00936
00937
00938
00939 ::DecayChainTrack* pParentChainTrack=pChainVertex->pParentTrack;
00940 if( pParentChainTrack!=NULL )
00941 {
00942
00943 TrackingParticle* pParentTrackingParticle=getTrackingParticle(pParentChainTrack);
00944 if( pParentTrackingParticle!=NULL )
00945 {
00946 pParentTrackingParticle->addDecayVertex( getRef(pChainVertex) );
00947 pTrackingVertex->addParentTrack( getRef(pParentChainTrack) );
00948 }
00949
00950
00951
00952 }
00953
00954
00955
00956
00957
00958
00959 }
00960
00961 void ::OutputCollectionWrapper::associateToExistingObjects( const ::DecayChainTrack* pChainTrack )
00962 {
00963
00964
00965
00966 TrackingParticle* pTrackingParticle=getTrackingParticle( pChainTrack );
00967 if( pTrackingParticle==NULL ) throw std::runtime_error( "associateToExistingObjects was passed a non existent TrackingParticle" );
00968
00969
00970
00971 ::DecayChainVertex* pParentChainVertex=pChainTrack->pParentVertex;
00972 TrackingVertex* pParentTrackingVertex=getTrackingVertex( pParentChainVertex );
00973
00974
00975
00976
00977 pTrackingParticle->setParentVertex( getRef(pParentChainVertex) );
00978 pParentTrackingVertex->addDaughterTrack( getRef(pChainTrack) );
00979
00980
00981
00982
00983
00984 for( auto pDaughterChainVertex : pChainTrack->daughterVertices )
00985 {
00986 TrackingVertex* pDaughterTrackingVertex=getTrackingVertex( pDaughterChainVertex );
00987 if( pDaughterTrackingVertex!=NULL )
00988 {
00989 pTrackingParticle->addDecayVertex( getRef(pDaughterChainVertex) );
00990 pDaughterTrackingVertex->addParentTrack( getRef(pChainTrack) );
00991 }
00992 }
00993 }
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003 int LayerFromDetid( const DetId& detId )
01004 {
01005 if( detId.det()!=DetId::Tracker ) return 0;
01006
01007 int layerNumber=0;
01008 unsigned int subdetId=static_cast<unsigned int>( detId.subdetId() );
01009
01010 if( subdetId==StripSubdetector::TIB )
01011 {
01012 TIBDetId tibid( detId.rawId() );
01013 layerNumber=tibid.layer();
01014 }
01015 else if( subdetId==StripSubdetector::TOB )
01016 {
01017 TOBDetId tobid( detId.rawId() );
01018 layerNumber=tobid.layer();
01019 }
01020 else if( subdetId==StripSubdetector::TID )
01021 {
01022 TIDDetId tidid( detId.rawId() );
01023 layerNumber=tidid.wheel();
01024 }
01025 else if( subdetId==StripSubdetector::TEC )
01026 {
01027 TECDetId tecid( detId.rawId() );
01028 layerNumber=tecid.wheel();
01029 }
01030 else if( subdetId==PixelSubdetector::PixelBarrel )
01031 {
01032 PXBDetId pxbid( detId.rawId() );
01033 layerNumber=pxbid.layer();
01034 }
01035 else if( subdetId==PixelSubdetector::PixelEndcap )
01036 {
01037 PXFDetId pxfid( detId.rawId() );
01038 layerNumber=pxfid.disk();
01039 }
01040 else edm::LogVerbatim( "TrackingTruthAccumulator" )<<"Unknown subdetid: "<<subdetId;
01041
01042 return layerNumber;
01043 }
01044
01045 TrackingParticle* addTrackAndParentVertex( ::DecayChainTrack* pDecayTrack, const TrackingParticle& trackingParticle, ::OutputCollectionWrapper* pOutput )
01046 {
01047
01048
01049 TrackingParticle* pTrackingParticle=pOutput->getTrackingParticle( pDecayTrack );
01050 if( pTrackingParticle==NULL )
01051 {
01052
01053 TrackingVertex* pProductionVertex=pOutput->getTrackingVertex( pDecayTrack->pParentVertex );
01054 if( pProductionVertex==NULL )
01055 {
01056
01057
01058
01059
01060
01061 pProductionVertex=pOutput->addTrackingVertex( pDecayTrack->pParentVertex, *trackingParticle.parentVertex() );
01062 }
01063
01064
01065 pTrackingParticle=pOutput->addTrackingParticle( pDecayTrack, trackingParticle );
01066 }
01067
01068 return pTrackingParticle;
01069 }
01070
01071 void addTrack( ::DecayChainTrack* pDecayChainTrack, const TrackingParticleSelector* pSelector, ::OutputCollectionWrapper* pUnmergedOutput, ::OutputCollectionWrapper* pMergedOutput, const ::TrackingParticleFactory& objectFactory, bool addAncestors )
01072 {
01073 if( pDecayChainTrack==NULL ) return;
01074
01075
01076
01077
01078 {
01079 bool alreadyProcessed=true;
01080 if( pUnmergedOutput!=NULL )
01081 {
01082 if( pUnmergedOutput->getTrackingParticle( pDecayChainTrack )==NULL ) alreadyProcessed=false;
01083 }
01084 if( pMergedOutput!=NULL )
01085 {
01086 if( pMergedOutput->getTrackingParticle( pDecayChainTrack )==NULL ) alreadyProcessed=false;
01087 }
01088 if( alreadyProcessed ) return;
01089 }
01090
01091
01092 TrackingParticle newTrackingParticle=objectFactory.createTrackingParticle( pDecayChainTrack );
01093
01094
01095
01096
01097
01098
01099
01100
01101 TrackingVertexCollection dummyCollection;
01102 dummyCollection.push_back( objectFactory.createTrackingVertex( pDecayChainTrack->pParentVertex ) );
01103 TrackingVertexRef temporaryRef( &dummyCollection, 0 );
01104 newTrackingParticle.setParentVertex( temporaryRef );
01105
01106
01107 if( pSelector )
01108 {
01109 if( !(*pSelector)( newTrackingParticle ) ) return;
01110 }
01111
01112
01113
01114
01115
01116 if( addAncestors ) addTrack( pDecayChainTrack->pParentVertex->pParentTrack, NULL, pUnmergedOutput, pMergedOutput, objectFactory, addAncestors );
01117
01118
01119
01120 if( pUnmergedOutput!=NULL ) addTrackAndParentVertex( pDecayChainTrack, newTrackingParticle, pUnmergedOutput );
01121
01122
01123
01124 if( pMergedOutput!=NULL )
01125 {
01126 ::DecayChainTrack* pBremParentChainTrack=pDecayChainTrack;
01127 while( pBremParentChainTrack->pMergedBremSource!=NULL ) pBremParentChainTrack=pBremParentChainTrack->pMergedBremSource;
01128
01129 if( pBremParentChainTrack!=pDecayChainTrack )
01130 {
01131 TrackingParticle* pBremParentTrackingParticle=addTrackAndParentVertex( pBremParentChainTrack, newTrackingParticle, pMergedOutput );
01132
01133
01134
01135
01136
01137 if( std::abs( newTrackingParticle.pdgId() ) == 22 )
01138 {
01139
01140
01141
01142
01143
01144 pMergedOutput->setProxy( pDecayChainTrack->pParentVertex, pBremParentChainTrack->pParentVertex );
01145
01146
01147
01148
01149 addTrackAndParentVertex( pDecayChainTrack, newTrackingParticle, pMergedOutput );
01150 }
01151 else if( std::abs( newTrackingParticle.pdgId() ) == 11 )
01152 {
01153
01154 for( const auto& trackSegment : newTrackingParticle.g4Tracks() )
01155 {
01156 pBremParentTrackingParticle->addG4Track( trackSegment );
01157 }
01158
01159
01160 for( const auto& genParticleRef : newTrackingParticle.genParticles() )
01161 {
01162 pBremParentTrackingParticle->addGenParticle( genParticleRef );
01163 }
01164
01165 pBremParentTrackingParticle->setNumberOfHits(pBremParentTrackingParticle->numberOfHits()+newTrackingParticle.numberOfHits());
01166 pBremParentTrackingParticle->setNumberOfTrackerHits(pBremParentTrackingParticle->numberOfTrackerHits()+newTrackingParticle.numberOfTrackerHits());
01167 pBremParentTrackingParticle->setNumberOfTrackerLayers(pBremParentTrackingParticle->numberOfTrackerLayers()+newTrackingParticle.numberOfTrackerLayers());
01168
01169
01170
01171 pMergedOutput->setProxy( pDecayChainTrack, pBremParentChainTrack );
01172 }
01173 }
01174 else
01175 {
01176
01177 addTrackAndParentVertex( pDecayChainTrack, newTrackingParticle, pMergedOutput );
01178 }
01179 }
01180
01181 }
01182
01183 }
01184
01185
01186 DEFINE_DIGI_ACCUMULATOR (TrackingTruthAccumulator);