CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
TrackingTruthAccumulator.cc
Go to the documentation of this file.
1 
32 
47 
54 
55 
56 
57 
58 //---------------------------------------------------------------------------------
59 //---------------------------------------------------------------------------------
60 //---------------------------------------------------------------------------------
61 //------ ------
62 //------ Declarations for utility classes and functions in the unnamed ------
63 //------ namespace. The definitions are right at the bottom of the file. ------
64 //------ ------
65 //---------------------------------------------------------------------------------
66 //---------------------------------------------------------------------------------
67 //---------------------------------------------------------------------------------
68 
69 namespace
70 {
75  struct DecayChainTrack
76  {
77  int simTrackIndex;
78  struct DecayChainVertex* pParentVertex;
79  // Some things have multiple decay vertices. Not sure how that works but it seems to be mostly electrons and some photons.
80  std::vector<struct DecayChainVertex*> daughterVertices;
81  DecayChainTrack* pMergedBremSource;
82  DecayChainTrack() : simTrackIndex(-1), pParentVertex(NULL), pMergedBremSource(NULL) {}
83  DecayChainTrack( int newSimTrackIndex ) : simTrackIndex(newSimTrackIndex), pParentVertex(NULL), pMergedBremSource() {}
84  };
85 
90  struct DecayChainVertex
91  {
92  int simVertexIndex;
93  DecayChainTrack* pParentTrack;
94  std::vector<DecayChainTrack*> daughterTracks;
95  DecayChainVertex* pMergedBremSource;
96  DecayChainVertex() : simVertexIndex(-1), pParentTrack(NULL), pMergedBremSource(NULL) {}
97  DecayChainVertex( int newIndex ) : simVertexIndex(newIndex), pParentTrack(NULL), pMergedBremSource(NULL) {}
98  };
99 
110  struct DecayChain
111  {
112  public:
113  DecayChain( const std::vector<SimTrack>& trackCollection, const std::vector<SimVertex>& vertexCollection );
114  const size_t decayTracksSize;
115  const size_t decayVerticesSize;
116 
121  void integrityCheck();
122  const SimTrack& getSimTrack( const ::DecayChainTrack* pDecayTrack ) const { return simTrackCollection_.at( pDecayTrack->simTrackIndex ); }
123  const SimVertex& getSimVertex( const ::DecayChainVertex* pDecayVertex ) const { return simVertexCollection_.at( pDecayVertex->simVertexIndex ); }
124  private:
125  void findBrem( const std::vector<SimTrack>& trackCollection, const std::vector<SimVertex>& vertexCollection );
126  std::unique_ptr< ::DecayChainTrack[]> decayTracks_;
127  std::unique_ptr< ::DecayChainVertex[]> decayVertices_;
128 
130  std::vector< ::DecayChainVertex*> rootVertices_;
131 
132  // Keep a record of the constructor parameters
133  const std::vector<SimTrack>& simTrackCollection_;
134  const std::vector<SimVertex>& simVertexCollection_;
135  public:
136  const std::unique_ptr< ::DecayChainTrack[]>& decayTracks;
137  const std::unique_ptr< ::DecayChainVertex[]>& decayVertices;
138  const std::vector< ::DecayChainVertex*>& rootVertices;
139  };
140 
145  class TrackingParticleFactory
146  {
147  public:
148  TrackingParticleFactory( const ::DecayChain& decayChain, const edm::Handle< std::vector<reco::GenParticle> >& hGenParticles,
149  const edm::Handle< edm::HepMCProduct >& hepMCproduct, const edm::Handle< std::vector<int> >& hHepMCGenParticleIndices,
150  const std::vector<const PSimHit*>& simHits, double volumeRadius, double volumeZ, double vertexDistanceCut, bool allowDifferentProcessTypes );
151  TrackingParticle createTrackingParticle( const DecayChainTrack* pTrack, const TrackerTopology *tTopo ) const;
152  TrackingVertex createTrackingVertex( const DecayChainVertex* pVertex) const;
153  bool vectorIsInsideVolume( const math::XYZTLorentzVectorD& vector ) const;
154  private:
155  const ::DecayChain& decayChain_;
156  const edm::Handle< std::vector<reco::GenParticle> >& hGenParticles_;
157  const edm::Handle< edm::HepMCProduct >& hepMCproduct_;
158  std::vector<int> genParticleIndices_;
159  const std::vector<const PSimHit*>& simHits_;
160  const double volumeRadius_;
161  const double volumeZ_;
162  const double vertexDistanceCut2_; // distance based on which HepMC::GenVertexs are added to SimVertexs
163  std::multimap<unsigned int, size_t> trackIdToHitIndex_;
164  bool allowDifferentProcessTypeForDifferentDetectors_;
165  };
166 
171  class OutputCollectionWrapper
172  {
173  public:
174  OutputCollectionWrapper( const DecayChain& decayChain, TrackingTruthAccumulator::OutputCollections& outputCollections );
175  TrackingParticle* addTrackingParticle( const ::DecayChainTrack* pDecayTrack, const TrackingParticle& trackingParticle );
176  TrackingVertex* addTrackingVertex( const ::DecayChainVertex* pDecayVertex, const TrackingVertex& trackingVertex );
177  TrackingParticle* getTrackingParticle( const ::DecayChainTrack* pDecayTrack );
179  void setProxy( const ::DecayChainTrack* pOriginalTrack, const ::DecayChainTrack* pProxyTrack );
180  void setProxy( const ::DecayChainVertex* pOriginalVertex, const ::DecayChainVertex* pProxyVertex );
181  TrackingVertex* getTrackingVertex( const ::DecayChainVertex* pDecayVertex );
182  TrackingParticleRef getRef( const ::DecayChainTrack* pDecayTrack );
183  TrackingVertexRef getRef( const ::DecayChainVertex* pDecayVertex );
184  private:
185  void associateToExistingObjects( const ::DecayChainVertex* pChainVertex );
186  void associateToExistingObjects( const ::DecayChainTrack* pChainTrack );
188  std::vector<int> trackingParticleIndices_;
189  std::vector<int> trackingVertexIndices_;
190  };
191 
196  TrackingParticle* addTrackAndParentVertex( ::DecayChainTrack* pDecayTrack, const TrackingParticle& trackingParticle, ::OutputCollectionWrapper* pOutput );
197 
202  void addTrack( ::DecayChainTrack* pDecayChainTrack, const TrackingParticleSelector* pSelector, ::OutputCollectionWrapper* pUnmergedOutput, ::OutputCollectionWrapper* pMergedOutput, const ::TrackingParticleFactory& objectFactory, bool addAncestors, const TrackerTopology *tTopo);
203 
204 } // end of the unnamed namespace
205 
206 
207 
208 
209 //---------------------------------------------------------------------------------
210 //---------------------------------------------------------------------------------
211 //---------------------------------------------------------------------------------
212 //------ ------
213 //------ Definitions for the TrackingTruthAccumulator methods ------
214 //------ are below. ------
215 //------ ------
216 //---------------------------------------------------------------------------------
217 //---------------------------------------------------------------------------------
218 //---------------------------------------------------------------------------------
219 
221  messageCategory_("TrackingTruthAccumulator"),
222  volumeRadius_( config.getParameter<double>("volumeRadius") ),
223  volumeZ_( config.getParameter<double>("volumeZ") ),
224  vertexDistanceCut_( config.getParameter<double>("vertexDistanceCut") ),
225  ignoreTracksOutsideVolume_( config.getParameter<bool>("ignoreTracksOutsideVolume") ),
226  maximumPreviousBunchCrossing_( config.getParameter<unsigned int>("maximumPreviousBunchCrossing") ),
227  maximumSubsequentBunchCrossing_( config.getParameter<unsigned int>("maximumSubsequentBunchCrossing") ),
228  createUnmergedCollection_( config.getParameter<bool>("createUnmergedCollection") ),
229  createMergedCollection_(config.getParameter<bool>("createMergedBremsstrahlung") ),
230  createInitialVertexCollection_(config.getParameter<bool>("createInitialVertexCollection") ),
231  addAncestors_( config.getParameter<bool>("alwaysAddAncestors") ),
232  removeDeadModules_( config.getParameter<bool>("removeDeadModules") ),
233  simTrackLabel_( config.getParameter<edm::InputTag>("simTrackCollection") ),
234  simVertexLabel_( config.getParameter<edm::InputTag>("simVertexCollection") ),
235  collectionTags_( ),
236  genParticleLabel_( config.getParameter<edm::InputTag>("genParticleCollection") ),
237  hepMCproductLabel_( config.getParameter<edm::InputTag>("HepMCProductLabel") ),
238  allowDifferentProcessTypeForDifferentDetectors_( config.getParameter<bool>("allowDifferentSimHitProcesses") )
239 {
240  //
241  // Make sure at least one of the merged and unmerged collections have been set
242  // to be created.
243  //
245  edm::LogError(messageCategory_) << "Both \"createUnmergedCollection\" and \"createMergedBremsstrahlung\" have been"
246  << "set to false, which means no collections will be created";
247 
248  // Initialize selection for building TrackingParticles
249  //
250  if( config.exists( "select" ) )
251  {
252  edm::ParameterSet param=config.getParameter<edm::ParameterSet>("select");
253  selector_=TrackingParticleSelector( param.getParameter<double>( "ptMinTP" ),
254  param.getParameter<double>( "minRapidityTP" ),
255  param.getParameter<double>( "maxRapidityTP" ),
256  param.getParameter<double>( "tipTP" ),
257  param.getParameter<double>( "lipTP" ),
258  param.getParameter<int>( "minHitTP" ),
259  param.getParameter<bool>( "signalOnlyTP" ),
260  param.getParameter<bool>( "intimeOnlyTP" ),
261  param.getParameter<bool>( "chargedOnlyTP" ),
262  param.getParameter<bool>( "stableOnlyTP" ),
263  param.getParameter<std::vector<int> >("pdgIdTP") );
264  selectorFlag_=true;
265 
266  // Also set these two variables, which are used to drop out early if the SimTrack doesn't conform.
267  // The selector_ requires a full TrackingParticle object, but these two variables can veto things early.
268  chargedOnly_=param.getParameter<bool>( "chargedOnlyTP" );
269  signalOnly_=param.getParameter<bool>( "signalOnlyTP" );
270  }
271  else
272  {
273  selectorFlag_=false;
274  chargedOnly_=false;
275  signalOnly_=false;
276  }
277 
278  //
279  // Need to state what collections are going to be added to the event. This
280  // depends on which of the merged and unmerged collections have been configured
281  // to be created.
282  //
284  {
285  mixMod.produces<TrackingVertexCollection>();
286  mixMod.produces<TrackingParticleCollection>();
287  }
288 
290  {
291  mixMod.produces<TrackingParticleCollection>("MergedTrackTruth");
292  mixMod.produces<TrackingVertexCollection>("MergedTrackTruth");
293  }
294 
296  {
297  mixMod.produces<TrackingVertexCollection>("InitialVertices");
298  }
299 
300  iC.consumes<std::vector<SimTrack> >(simTrackLabel_);
301  iC.consumes<std::vector<SimVertex> >(simVertexLabel_);
302  iC.consumes<std::vector<reco::GenParticle> >(genParticleLabel_);
303  iC.consumes<std::vector<int> >(genParticleLabel_);
304  iC.consumes<std::vector<int> >(hepMCproductLabel_);
305 
306  // Fill the collection tags
307  const edm::ParameterSet& simHitCollectionConfig=config.getParameterSet("simHitCollections");
308  std::vector<std::string> parameterNames=simHitCollectionConfig.getParameterNames();
309 
310  for( const auto& parameterName : parameterNames )
311  {
312  std::vector<edm::InputTag> tags=simHitCollectionConfig.getParameter<std::vector<edm::InputTag> >(parameterName);
313  collectionTags_.insert(collectionTags_.end(), tags.begin(), tags.end());
314  }
315 
316  for( const auto& collectionTag : collectionTags_ ) {
317  iC.consumes<std::vector<PSimHit> >(collectionTag);
318  }
319 
320 }
321 
323 {
325  {
328  unmergedOutput_.refTrackingParticles=const_cast<edm::Event&>( event ).getRefBeforePut<TrackingParticleCollection>();
329  unmergedOutput_.refTrackingVertexes=const_cast<edm::Event&>( event ).getRefBeforePut<TrackingVertexCollection>();
330  }
331 
333  {
336  mergedOutput_.refTrackingParticles=const_cast<edm::Event&>( event ).getRefBeforePut<TrackingParticleCollection>("MergedTrackTruth");
337  mergedOutput_.refTrackingVertexes=const_cast<edm::Event&>( event ).getRefBeforePut<TrackingVertexCollection>("MergedTrackTruth");
338  }
339 
341  {
343  }
344 }
345 
350 
352 {
353  // Call the templated version that does the same for both signal and pileup events
354 
356  event.getByLabel(hepMCproductLabel_, hepmc);
357 
358  accumulateEvent( event, setup, hepmc );
359 }
360 
362 {
363  // If this bunch crossing is outside the user configured limit, don't do anything.
364  if( event.bunchCrossing()>=-static_cast<int>(maximumPreviousBunchCrossing_) && event.bunchCrossing()<=static_cast<int>(maximumSubsequentBunchCrossing_) )
365  {
366  //edm::LogInfo(messageCategory_) << "Analysing pileup event for bunch crossing " << event.bunchCrossing();
367 
368  //simply create empty handle as we do not have a HepMCProduct in PU anyway
370  accumulateEvent( event, setup, hepmc );
371  }
372  else edm::LogInfo(messageCategory_) << "Skipping pileup event for bunch crossing " << event.bunchCrossing();
373 }
374 
376 {
377 
379  {
380  edm::LogInfo("TrackingTruthAccumulator") << "Adding " << unmergedOutput_.pTrackingParticles->size() << " TrackingParticles and " << unmergedOutput_.pTrackingVertices->size()
381  << " TrackingVertexs to the event.";
382 
383  event.put( unmergedOutput_.pTrackingParticles );
384  event.put( unmergedOutput_.pTrackingVertices );
385  }
386 
388  {
389  edm::LogInfo("TrackingTruthAccumulator") << "Adding " << mergedOutput_.pTrackingParticles->size() << " merged TrackingParticles and " << mergedOutput_.pTrackingVertices->size()
390  << " merged TrackingVertexs to the event.";
391 
392  event.put( mergedOutput_.pTrackingParticles, "MergedTrackTruth" );
393  event.put( mergedOutput_.pTrackingVertices, "MergedTrackTruth" );
394  }
395 
397  {
398  edm::LogInfo("TrackingTruthAccumulator") << "Adding " << pInitialVertices_->size() << " initial TrackingVertexs to the event.";
399 
400  event.put( pInitialVertices_, "InitialVertices" );
401  }
402 }
403 
405 {
406  //
407  // Get the collections
408  //
410  edm::Handle<std::vector<SimVertex> > hSimVertices;
412  edm::Handle< std::vector<int> > hGenParticleIndices;
413 
414  event.getByLabel( simTrackLabel_, hSimTracks );
415  event.getByLabel( simVertexLabel_, hSimVertices );
416 
417  try
418  {
419  event.getByLabel( genParticleLabel_, hGenParticles );
420  event.getByLabel( genParticleLabel_, hGenParticleIndices );
421  }
422  catch( cms::Exception& exception )
423  {
424  //
425  // The Monte Carlo is not always available, e.g. for pileup events. The information
426  // is only used if it's available, but for some reason the PileUpEventPrincipal
427  // wrapper throws an exception here rather than waiting to see if the handle is
428  // used (as is the case for edm::Event). So I just want to catch this exception
429  // and use the normal handle checking later on.
430  //
431  }
432 
433  //Retrieve tracker topology from geometry
434  edm::ESHandle<TrackerTopology> tTopoHandle;
435  setup.get<TrackerTopologyRcd>().get(tTopoHandle);
436  const TrackerTopology* const tTopo = tTopoHandle.product();
437 
438 
439  // Run through the collections and work out the decay chain of each track/vertex. The
440  // information in SimTrack and SimVertex only allows traversing upwards, but this will
441  // allow traversal in both directions. This is required for things like grouping electrons
442  // that bremsstrahlung as one TrackingParticle if "mergedBremsstrahlung" is set in the
443  // config file.
444  DecayChain decayChain( *hSimTracks, *hSimVertices );
445 
446  // I only want to create these collections if they're actually required
447  std::auto_ptr< ::OutputCollectionWrapper> pUnmergedCollectionWrapper;
448  std::auto_ptr< ::OutputCollectionWrapper> pMergedCollectionWrapper;
449  if( createUnmergedCollection_ ) pUnmergedCollectionWrapper.reset( new ::OutputCollectionWrapper( decayChain, unmergedOutput_ ) );
450  if( createMergedCollection_ ) pMergedCollectionWrapper.reset( new ::OutputCollectionWrapper( decayChain, mergedOutput_ ) );
451 
452  std::vector<const PSimHit*> simHitPointers;
453  fillSimHits( simHitPointers, event, setup );
454  TrackingParticleFactory objectFactory( decayChain, hGenParticles, hepMCproduct, hGenParticleIndices, simHitPointers, volumeRadius_, volumeZ_, vertexDistanceCut_, allowDifferentProcessTypeForDifferentDetectors_ );
455 
456  // While I'm testing, perform some checks.
457  // TODO - drop this call once I'm happy it works in all situations.
458  //decayChain.integrityCheck();
459 
460  TrackingParticleSelector* pSelector=NULL;
461  if( selectorFlag_ ) pSelector=&selector_;
462 
463  // Run over all of the SimTracks, but because I'm interested in the decay hierarchy
464  // do it through the DecayChainTrack objects. These are looped over in sequence here
465  // but they have the hierarchy information for the functions called to traverse the
466  // decay chain.
467 
468  for( size_t index=0; index<decayChain.decayTracksSize; ++index )
469  {
470  ::DecayChainTrack* pDecayTrack=&decayChain.decayTracks[index];
471  const SimTrack& simTrack=hSimTracks->at(pDecayTrack->simTrackIndex);
472 
473 
474  // Perform some quick checks to see if we can drop out early. Note that these are
475  // a subset of the cuts in the selector_ so the created TrackingParticle could still
476  // fail. The selector_ requires the full TrackingParticle to be made however, which
477  // can be computationally expensive.
478  if( chargedOnly_ && simTrack.charge()==0 ) continue;
479  if( signalOnly_ && (simTrack.eventId().bunchCrossing()!=0 || simTrack.eventId().event()!=0) ) continue;
480 
481  // Also perform a check to see if the production vertex is inside the tracker volume (if required).
483  {
484  const SimVertex& simVertex=hSimVertices->at( pDecayTrack->pParentVertex->simVertexIndex );
485  if( !objectFactory.vectorIsInsideVolume( simVertex.position() ) ) continue;
486  }
487 
488 
489  // This function creates the TrackinParticle and adds it to the collection if it
490  // passes the selection criteria specified in the configuration. If the config
491  // specifies adding ancestors, the function is called recursively to do that.
492  ::addTrack( pDecayTrack, pSelector, pUnmergedCollectionWrapper.get(), pMergedCollectionWrapper.get(), objectFactory, addAncestors_, tTopo );
493  }
494 
495  // If configured to create a collection of initial vertices, add them from this bunch
496  // crossing. No selection is applied on this collection, but it also has no links to
497  // the TrackingParticle decay products.
498  // There are a lot of "initial vertices", I'm not entirely sure what they all are
499  // (nuclear interactions in the detector maybe?), but the one for the main event is
500  // the one with vertexId==0.
502  {
503  // Pretty sure the one with vertexId==0 is always the first one, but doesn't hurt to check
504  for( const auto& pRootVertex : decayChain.rootVertices )
505  {
506  const SimVertex& vertex=hSimVertices->at(decayChain.rootVertices[0]->simVertexIndex);
507  if( vertex.vertexId()!=0 ) continue;
508 
509  pInitialVertices_->push_back( objectFactory.createTrackingVertex(pRootVertex) );
510  break;
511  }
512  }
513 }
514 
515 template<class T> void TrackingTruthAccumulator::fillSimHits( std::vector<const PSimHit*>& returnValue, const T& event, const edm::EventSetup& setup )
516 {
517  // loop over the collections
518  for( const auto& collectionTag : collectionTags_ )
519  {
521  event.getByLabel( collectionTag, hSimHits );
522 
523  // TODO - implement removing the dead modules
524  for( const auto& simHit : *hSimHits )
525  {
526  returnValue.push_back( &simHit );
527  }
528 
529  } // end of loop over InputTags
530 }
531 
532 
533 //---------------------------------------------------------------------------------
534 //---------------------------------------------------------------------------------
535 //---------------------------------------------------------------------------------
536 //------ ------
537 //------ End of the definitions for the TrackingTruthAccumulator methods. ------
538 //------ Definitions for the functions and classes declared in the unnamed ------
539 //------ namespace are below. Documentation for those is above, where ------
540 //------ they're declared. ------
541 //------ ------
542 //---------------------------------------------------------------------------------
543 //---------------------------------------------------------------------------------
544 //---------------------------------------------------------------------------------
545 
546 
547 namespace // Unnamed namespace for things only used in this file
548 {
549  //---------------------------------------------------------------------------------
550  //---------------------------------------------------------------------------------
551  //---- TrackingParticleFactory methods ----------------------------------------
552  //---------------------------------------------------------------------------------
553  //---------------------------------------------------------------------------------
554 
555  ::TrackingParticleFactory::TrackingParticleFactory( const ::DecayChain& decayChain, const edm::Handle< std::vector<reco::GenParticle> >& hGenParticles,
556  const edm::Handle< edm::HepMCProduct >& hepMCproduct, const edm::Handle< std::vector<int> >& hHepMCGenParticleIndices, const std::vector<const PSimHit*>& simHits,
557  double volumeRadius, double volumeZ, double vertexDistanceCut, bool allowDifferentProcessTypes )
558  : decayChain_(decayChain), hGenParticles_(hGenParticles), hepMCproduct_(hepMCproduct), simHits_(simHits), volumeRadius_(volumeRadius),
559  volumeZ_(volumeZ), vertexDistanceCut2_(vertexDistanceCut*vertexDistanceCut), allowDifferentProcessTypeForDifferentDetectors_(allowDifferentProcessTypes)
560  {
561  // Need to create a multimap to get from a SimTrackId to all of the hits in it. The SimTrackId
562  // is an unsigned int.
563  for( size_t index=0; index<simHits_.size(); ++index )
564  {
565  trackIdToHitIndex_.insert( std::make_pair( simHits_[index]->trackId(), index ) );
566  }
567 
568  if( hHepMCGenParticleIndices.isValid() ) // Monte Carlo might not be available for the pileup events
569  {
570  genParticleIndices_.resize( hHepMCGenParticleIndices->size()+1 );
571 
572  // What I need is the reverse mapping of this vector. The sizes are already equivalent because I set
573  // the size in the initialiser list.
574  for( size_t recoGenParticleIndex=0; recoGenParticleIndex<hHepMCGenParticleIndices->size(); ++recoGenParticleIndex )
575  {
576  size_t hepMCGenParticleIndex=(*hHepMCGenParticleIndices)[recoGenParticleIndex];
577 
578  // They should be the same size, give or take a fencepost error, so this should never happen - but just in case
579  if( genParticleIndices_.size()<=hepMCGenParticleIndex ) genParticleIndices_.resize(hepMCGenParticleIndex+1);
580 
581  genParticleIndices_[ hepMCGenParticleIndex ]=recoGenParticleIndex;
582  }
583  }
584  }
585 
586  TrackingParticle TrackingParticleFactory::createTrackingParticle( const ::DecayChainTrack* pChainTrack, const TrackerTopology *tTopo ) const
587  {
589  typedef math::XYZPoint Vector;
590 
591  const SimTrack& simTrack=decayChain_.getSimTrack( pChainTrack );
592  const SimVertex& parentSimVertex=decayChain_.getSimVertex( pChainTrack->pParentVertex );
593 
594  LorentzVector position( 0, 0, 0, 0 );
595  if( !simTrack.noVertex() ) position=parentSimVertex.position();
596 
597  int pdgId=simTrack.type();
598 
599  TrackingParticle returnValue;
600  // N.B. The sim track is added a few lines below, the parent and decay vertices are added in
601  // another function later on.
602 
603  //
604  // If there is some valid Monte Carlo for this track, take some information from that.
605  // Only do so if it is from the signal event however. Not sure why but that's what the
606  // old code did.
607  //
608  if( simTrack.eventId().event()==0 && simTrack.eventId().bunchCrossing()==0 ) // if this is a track in the signal event
609  {
610  int hepMCGenParticleIndex=simTrack.genpartIndex();
611  if( hepMCGenParticleIndex>=0 && hepMCGenParticleIndex<static_cast<int>(genParticleIndices_.size()) && hGenParticles_.isValid() )
612  {
613  int recoGenParticleIndex=genParticleIndices_[hepMCGenParticleIndex];
614  reco::GenParticleRef generatorParticleRef( hGenParticles_, recoGenParticleIndex );
615  pdgId=generatorParticleRef->pdgId();
616  returnValue.addGenParticle( generatorParticleRef );
617  }
618  }
619 
620  returnValue.addG4Track( simTrack );
621 
622  // I need to run over the sim hits and count up the different types of hits. To be honest
623  // I don't fully understand this next section of code, I copied it from the old TrackingTruthProducer
624  // to provide the same results. The different types of hits that I need to count are:
625  size_t matchedHits=0; // As far as I can tell, this is the number of tracker layers with hits on them, i.e. taking account of overlaps.
626  size_t numberOfHits=0; // The total number of hits not taking account of overlaps.
627  size_t numberOfTrackerHits=0; // The number of tracker hits not taking account of overlaps.
628 
629  bool init=true;
630  int processType=0;
631  int particleType=0;
632  int oldLayer = 0;
633  int newLayer = 0;
634  DetId oldDetector;
635  DetId newDetector;
636 
637  for( std::multimap<unsigned int,size_t>::const_iterator iHitIndex=trackIdToHitIndex_.lower_bound( simTrack.trackId() );
638  iHitIndex!=trackIdToHitIndex_.upper_bound( simTrack.trackId() );
639  ++iHitIndex )
640  {
641  const auto& pSimHit=simHits_[ iHitIndex->second ];
642 
643  // Initial condition for consistent simhit selection
644  if( init )
645  {
646  processType=pSimHit->processType();
647  particleType=pSimHit->particleType();
648  newDetector=DetId( pSimHit->detUnitId() );
649  init=false;
650  }
651 
652  oldDetector=newDetector;
653  newDetector=DetId( pSimHit->detUnitId() );
654 
655  // Fast sim seems to have different processType between tracker and muons, so if this flag
656  // has been set allow the processType to change if the detector changes.
657  if( allowDifferentProcessTypeForDifferentDetectors_ && newDetector.det()!=oldDetector.det() ) processType=pSimHit->processType();
658 
659  // Check for delta and interaction products discards
660  if( processType==pSimHit->processType() && particleType==pSimHit->particleType() && pdgId==pSimHit->particleType() )
661  {
662  ++numberOfHits;
663  oldLayer=newLayer;
664  newLayer=0;
665  if( newDetector.det() == DetId::Tracker ) {
666  ++numberOfTrackerHits;
667 
668  newLayer=tTopo->layer( newDetector );
669 
670  // Count hits using layers for glued detectors
671  if( (oldLayer!=newLayer || (oldLayer==newLayer && oldDetector.subdetId()!=newDetector.subdetId())) ) ++matchedHits;
672  }
673  }
674  } // end of loop over the sim hits for this sim track
675 
676  returnValue.setNumberOfTrackerLayers( matchedHits );
677  returnValue.setNumberOfHits( numberOfHits );
678  returnValue.setNumberOfTrackerHits( numberOfTrackerHits );
679 
680  return returnValue;
681  }
682 
683  TrackingVertex TrackingParticleFactory::createTrackingVertex( const ::DecayChainVertex* pChainVertex) const
684  {
685 
687  typedef math::XYZPoint Vector;
689 
690  const SimVertex& simVertex=decayChain_.getSimVertex( pChainVertex );
691 
692  bool isInVolume=this->vectorIsInsideVolume( simVertex.position() );
693 
694  TrackingVertex returnValue( simVertex.position(), isInVolume, simVertex.eventId() );
695 
696  // add the SimVertex to the TrackingVertex
697  returnValue.addG4Vertex(simVertex);
698 
699  // also add refs to nearby HepMC::GenVertexs; the way this is done (i.e. based on the position) is transcribed over from the old TrackingTruthProducer
700  if( simVertex.eventId().event()==0 && simVertex.eventId().bunchCrossing()==0 && hepMCproduct_.isValid()) // if this is a track in the signal event
701  {
702  const HepMC::GenEvent* genEvent = hepMCproduct_->GetEvent();
703 
704  if (genEvent != NULL)
705  {
706  Vector tvPosition(returnValue.position().x(), returnValue.position().y(), returnValue.position().z());
707 
708  for (HepMC::GenEvent::vertex_const_iterator iGenVertex = genEvent->vertices_begin(); iGenVertex != genEvent->vertices_end(); ++iGenVertex)
709  {
710  HepMC::ThreeVector rawPosition = (*iGenVertex)->position();
711 
712  Vector genPosition(rawPosition.x()*0.1, rawPosition.y()*0.1, rawPosition.z()*0.1);
713 
714  auto distance2 = (tvPosition - genPosition).mag2();
715 
716  if (distance2 < vertexDistanceCut2_)
717  returnValue.addGenVertex( GenVertexRef(hepMCproduct_, (*iGenVertex)->barcode()) );
718  }
719  }
720  }
721 
722  return returnValue;
723  }
724 
725  bool ::TrackingParticleFactory::vectorIsInsideVolume( const math::XYZTLorentzVectorD& vector ) const
726  {
727  return ( vector.Pt()<volumeRadius_ && std::abs( vector.z() )<volumeZ_ );
728  }
729 
730  //---------------------------------------------------------------------------------
731  //---------------------------------------------------------------------------------
732  //---- DecayChain methods -----------------------------------------------------
733  //---------------------------------------------------------------------------------
734  //---------------------------------------------------------------------------------
735 
736  ::DecayChain::DecayChain( const std::vector<SimTrack>& trackCollection, const std::vector<SimVertex>& vertexCollection )
737  : decayTracksSize( trackCollection.size() ),
738  decayVerticesSize( vertexCollection.size() ),
739  decayTracks_( new DecayChainTrack[decayTracksSize] ),
740  decayVertices_( new DecayChainVertex[decayVerticesSize] ),
741  simTrackCollection_( trackCollection ),
742  simVertexCollection_( vertexCollection ),
743  decayTracks( decayTracks_ ), // These const references map onto the actual members for public const access
744  decayVertices( decayVertices_ ),
745  rootVertices( rootVertices_ )
746  {
747  // I need some maps to be able to get object pointers from the track/vertex ID
748  std::map<int,::DecayChainTrack*> trackIdToDecayTrack;
749  std::map<int,::DecayChainVertex*> vertexIdToDecayVertex;
750 
751  // First create a DecayChainTrack for every SimTrack and make a note of the
752  // trackIds in the map. Also add a pointer to the daughter list of the parent
753  // DecayChainVertex, which might include creating the vertex object if it
754  // doesn't already exist.
755  size_t decayVertexIndex=0; // The index of the next free slot in the DecayChainVertex array.
756  for( size_t index=0; index<trackCollection.size(); ++index )
757  {
758  ::DecayChainTrack* pDecayTrack=&decayTracks_[index]; // Get a pointer for ease of use
759 
760  // This is the array index of the SimTrack that this DecayChainTrack corresponds to. At
761  // the moment this is a 1 to 1 relationship with the DecayChainTrack index, but they won't
762  // necessarily be accessed through the array later so it's still required to store it.
763  pDecayTrack->simTrackIndex=index;
764 
765  trackIdToDecayTrack[ trackCollection[index].trackId() ]=pDecayTrack;
766 
767  int parentVertexIndex=trackCollection[index].vertIndex();
768  if( parentVertexIndex>=0 )
769  {
770  // Get the DecayChainVertex corresponding to this SimVertex, or initialise it if it hasn't been done already.
771  ::DecayChainVertex*& pParentVertex=vertexIdToDecayVertex[parentVertexIndex];
772  if( pParentVertex==NULL )
773  {
774  // Note that I'm using a reference, so changing pParentVertex will change the entry in the map too.
775  pParentVertex=&decayVertices_[decayVertexIndex];
776  ++decayVertexIndex;
777  pParentVertex->simVertexIndex=parentVertexIndex;
778  }
779  pParentVertex->daughterTracks.push_back(pDecayTrack);
780  pDecayTrack->pParentVertex=pParentVertex;
781  }
782  else throw std::runtime_error( "TrackingTruthAccumulator: Found a track with an invalid parent vertex index." );
783  }
784 
785  // This assert was originally in to check the internal consistency of the decay chain. Fast sim
786  // pileup seems to have a load of vertices with no tracks pointing to them though, so fast sim fails
787  // this assert if pileup is added. I don't think the problem is vital however, so if the assert is
788  // taken out these extra vertices are ignored.
789  //assert( vertexIdToDecayVertex.size()==vertexCollection.size() && vertexCollection.size()==decayVertexIndex );
790 
791  // I still need to set DecayChainTrack::daughterVertices and DecayChainVertex::pParentTrack.
792  // The information to do this comes from SimVertex::parentIndex. I couldn't do this before
793  // because I need all of the DecayChainTracks initialised.
794  for( auto& decayVertexMapPair : vertexIdToDecayVertex )
795  {
796  ::DecayChainVertex* pDecayVertex=decayVertexMapPair.second;
797  int parentTrackIndex=vertexCollection[pDecayVertex->simVertexIndex].parentIndex();
798  if( parentTrackIndex!=-1 )
799  {
800  std::map<int,::DecayChainTrack*>::iterator iParentTrackMapPair=trackIdToDecayTrack.find(parentTrackIndex);
801  if( iParentTrackMapPair==trackIdToDecayTrack.end() )
802  {
803  std::stringstream errorStream;
804  errorStream << "TrackingTruthAccumulator: Something has gone wrong with the indexing. Parent track index is " << parentTrackIndex << ".";
805  throw std::runtime_error( errorStream.str() );
806  }
807 
808  ::DecayChainTrack* pParentTrackHierarchy=iParentTrackMapPair->second;
809 
810  pParentTrackHierarchy->daughterVertices.push_back( pDecayVertex );
811  pDecayVertex->pParentTrack=pParentTrackHierarchy;
812  }
813  else rootVertices_.push_back(pDecayVertex); // Has no parent so is at the top of the decay chain.
814  } // end of loop over the vertexIdToDecayVertex map
815 
816  findBrem( trackCollection, vertexCollection );
817 
818  } // end of ::DecayChain constructor
819 
820  // Function documentation is with the declaration above. This function is only used for testing.
821  void ::DecayChain::integrityCheck()
822  {
823  //
824  // Start off checking the tracks
825  //
826  for( size_t index=0; index<decayTracksSize; ++index )
827  {
828  const auto& decayTrack=decayTracks[index];
829  //
830  // Tracks should always have a production vertex
831  //
832  if( decayTrack.pParentVertex==NULL ) throw std::runtime_error( "TrackingTruthAccumulator.cc integrityCheck(): Found DecayChainTrack with no parent vertex." );
833 
834  //
835  // Make sure the parent has this as a child. Also make sure it's only listed once.
836  //
837  size_t numberOfTimesListed=0;
838  for( const auto pSiblingTrack : decayTrack.pParentVertex->daughterTracks )
839  {
840  if( pSiblingTrack==&decayTrack ) ++numberOfTimesListed;
841  }
842  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." );
843 
844  //
845  // Make sure all of the children have this listed as a parent.
846  //
847  for( const auto pDaughterVertex : decayTrack.daughterVertices )
848  {
849  if( pDaughterVertex->pParentTrack!=&decayTrack ) throw std::runtime_error( "TrackingTruthAccumulator.cc integrityCheck(): Found DecayChainTrack whose child does not have it listed as the parent." );
850  }
851 
852  //
853  // Follow the chain up to the root vertex, and make sure that is listed in rootVertices
854  //
855  const DecayChainVertex* pAncestorVertex=decayTrack.pParentVertex;
856  while( pAncestorVertex->pParentTrack!=NULL )
857  {
858  if( pAncestorVertex->pParentTrack->pParentVertex==NULL ) throw std::runtime_error( "TrackingTruthAccumulator.cc integrityCheck(): Found DecayChainTrack with no parent vertex higher in the decay chain." );
859  pAncestorVertex=pAncestorVertex->pParentTrack->pParentVertex;
860  }
861  if( std::find( rootVertices.begin(), rootVertices.end(), pAncestorVertex )==rootVertices.end() )
862  {
863  throw std::runtime_error( "TrackingTruthAccumulator.cc integrityCheck(): Found DecayChainTrack whose root vertex is not recorded anywhere." );
864  }
865  } // end of loop over decayTracks
866 
867  //
868  // Now check the vertices
869  //
870  for( size_t index=0; index<decayVerticesSize; ++index )
871  {
872  const auto& decayVertex=decayVertices[index];
873 
874  //
875  // Make sure this, or a vertex higher in the chain, is in the list of root vertices.
876  //
877  const DecayChainVertex* pAncestorVertex=&decayVertex;
878  while( pAncestorVertex->pParentTrack!=NULL )
879  {
880  if( pAncestorVertex->pParentTrack->pParentVertex==NULL ) throw std::runtime_error( "TrackingTruthAccumulator.cc integrityCheck(): Found DecayChainTrack with no parent vertex higher in the vertex decay chain." );
881  pAncestorVertex=pAncestorVertex->pParentTrack->pParentVertex;
882  }
883  if( std::find( rootVertices.begin(), rootVertices.end(), pAncestorVertex )==rootVertices.end() )
884  {
885  throw std::runtime_error( "TrackingTruthAccumulator.cc integrityCheck(): Found DecayChainTrack whose root vertex is not recorded anywhere." );
886  }
887 
888  //
889  // Make sure the parent has this listed in its daughters once and only once.
890  //
891  if( decayVertex.pParentTrack!=NULL )
892  {
893  size_t numberOfTimesListed=0;
894  for( const auto pSibling : decayVertex.pParentTrack->daughterVertices )
895  {
896  if( pSibling==&decayVertex ) ++numberOfTimesListed;
897  }
898  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." );
899  }
900 
901  //
902  // Make sure all of the children have this listed as the parent
903  //
904  for( const auto pDaughter : decayVertex.daughterTracks )
905  {
906  if( pDaughter->pParentVertex!=&decayVertex ) throw std::runtime_error( "TrackingTruthAccumulator.cc integrityCheck(): Found DecayChainVertex whose child does not have it listed as the parent." );
907  }
908  } // end of loop over decay vertices
909 
910  std::cout << "TrackingTruthAccumulator.cc integrityCheck() completed successfully" << std::endl;
911  } // end of ::DecayChain::integrityCheck()
912 
913  void ::DecayChain::findBrem( const std::vector<SimTrack>& trackCollection, const std::vector<SimVertex>& vertexCollection )
914  {
915  for( size_t index=0; index<decayVerticesSize; ++index )
916  {
917  auto& vertex=decayVertices_[index];
918 
919  // Make sure parent is an electron
920  if( vertex.pParentTrack==NULL ) continue;
921  int parentTrackPDG=trackCollection[vertex.pParentTrack->simTrackIndex].type();
922  if( std::abs( parentTrackPDG )!=11 ) continue;
923 
924  size_t numberOfElectrons=0;
925  size_t numberOfNonElectronsOrPhotons=0;
926  for( auto& pDaughterTrack : vertex.daughterTracks )
927  {
928  const auto& simTrack=trackCollection[pDaughterTrack->simTrackIndex];
929  if( simTrack.type()==11 || simTrack.type()==-11 ) ++numberOfElectrons;
930  else if( simTrack.type()!=22 ) ++numberOfNonElectronsOrPhotons;
931  }
932  if( numberOfElectrons==1 && numberOfNonElectronsOrPhotons==0 )
933  {
934  // This is a valid brem, run through and tell all daughters to use the parent
935  // as the brem
936  for( auto& pDaughterTrack : vertex.daughterTracks ) pDaughterTrack->pMergedBremSource=vertex.pParentTrack;
937  vertex.pMergedBremSource=vertex.pParentTrack->pParentVertex;
938  }
939  }
940  } // end of ::DecayChain::findBrem()
941 
942 
943  //---------------------------------------------------------------------------------
944  //---------------------------------------------------------------------------------
945  //---- OutputCollectionWrapper methods ----------------------------------------
946  //---------------------------------------------------------------------------------
947  //---------------------------------------------------------------------------------
948 
949  ::OutputCollectionWrapper::OutputCollectionWrapper( const ::DecayChain& decayChain, TrackingTruthAccumulator::OutputCollections& outputCollections )
950  : output_(outputCollections),
951  trackingParticleIndices_(decayChain.decayTracksSize,-1),
952  trackingVertexIndices_(decayChain.decayVerticesSize,-1)
953  {
954  // No operation besides the initialiser list
955  }
956 
957  TrackingParticle* ::OutputCollectionWrapper::addTrackingParticle( const ::DecayChainTrack* pDecayTrack, const TrackingParticle& trackingParticle )
958  {
959  if( trackingParticleIndices_[pDecayTrack->simTrackIndex]!=-1 ) throw std::runtime_error( "OutputCollectionWrapper::addTrackingParticle - trying to add a particle twice" );
960 
961  trackingParticleIndices_[pDecayTrack->simTrackIndex]=output_.pTrackingParticles->size();
962  output_.pTrackingParticles->push_back( trackingParticle );
963 
964  // Clear any associations in case there were any beforehand
965  output_.pTrackingParticles->back().clearDecayVertices();
966  output_.pTrackingParticles->back().clearParentVertex();
967 
968  // Associate to the objects that are already in the output collections
969  associateToExistingObjects( pDecayTrack );
970 
971  return &output_.pTrackingParticles->back();
972  }
973 
974  TrackingVertex* ::OutputCollectionWrapper::addTrackingVertex( const ::DecayChainVertex* pDecayVertex, const TrackingVertex& trackingVertex )
975  {
976  if( trackingVertexIndices_[pDecayVertex->simVertexIndex]!=-1 ) throw std::runtime_error( "OutputCollectionWrapper::addTrackingVertex - trying to add a vertex twice" );
977 
978  trackingVertexIndices_[pDecayVertex->simVertexIndex]=output_.pTrackingVertices->size();
979  output_.pTrackingVertices->push_back( trackingVertex );
980 
981  // Associate the new vertex to any parents or children that are already in the output collections
982  associateToExistingObjects( pDecayVertex );
983 
984  return &output_.pTrackingVertices->back();
985  }
986 
987  TrackingParticle* ::OutputCollectionWrapper::getTrackingParticle( const ::DecayChainTrack* pDecayTrack )
988  {
989  const int index=trackingParticleIndices_[pDecayTrack->simTrackIndex];
990  if( index==-1 ) return NULL;
991  else return &(*output_.pTrackingParticles)[index];
992  }
993 
994  TrackingVertex* ::OutputCollectionWrapper::getTrackingVertex( const ::DecayChainVertex* pDecayVertex )
995  {
996  const int index=trackingVertexIndices_[pDecayVertex->simVertexIndex];
997  if( index==-1 ) return NULL;
998  else return &(*output_.pTrackingVertices)[index];
999  }
1000 
1001  TrackingParticleRef OutputCollectionWrapper::getRef( const ::DecayChainTrack* pDecayTrack )
1002  {
1003  const int index=trackingParticleIndices_[pDecayTrack->simTrackIndex];
1004  if( index==-1 ) throw std::runtime_error( "OutputCollectionWrapper::getRefTrackingParticle - ref requested for a non existent TrackingParticle" );
1005  else return TrackingParticleRef( output_.refTrackingParticles, index );
1006  }
1007 
1008  TrackingVertexRef OutputCollectionWrapper::getRef( const ::DecayChainVertex* pDecayVertex )
1009  {
1010  const int index=trackingVertexIndices_[pDecayVertex->simVertexIndex];
1011  if( index==-1 ) throw std::runtime_error( "OutputCollectionWrapper::getRefTrackingParticle - ref requested for a non existent TrackingVertex" );
1012  else return TrackingVertexRef( output_.refTrackingVertexes, index );
1013  }
1014 
1015  void ::OutputCollectionWrapper::setProxy( const ::DecayChainTrack* pOriginalTrack, const ::DecayChainTrack* pProxyTrack )
1016  {
1017  int& index=trackingParticleIndices_[pOriginalTrack->simTrackIndex];
1018  if( index!=-1 ) throw std::runtime_error( "OutputCollectionWrapper::setProxy() was called for a TrackingParticle that has already been created" );
1019  // Note that index is a reference so this call changes the value in the vector too
1020  index=trackingParticleIndices_[pProxyTrack->simTrackIndex];
1021  }
1022 
1023  void ::OutputCollectionWrapper::setProxy( const ::DecayChainVertex* pOriginalVertex, const ::DecayChainVertex* pProxyVertex )
1024  {
1025  int& index=trackingVertexIndices_[pOriginalVertex->simVertexIndex];
1026  const int newIndex=trackingVertexIndices_[pProxyVertex->simVertexIndex];
1027 
1028  if( index!=-1 && index!=newIndex ) throw std::runtime_error( "OutputCollectionWrapper::setProxy() was called for a TrackingVertex that has already been created" );
1029 
1030  // Note that index is a reference so this call changes the value in the vector too
1031  index=newIndex;
1032  }
1033 
1034  void ::OutputCollectionWrapper::associateToExistingObjects( const ::DecayChainVertex* pChainVertex )
1035  {
1036  // First make sure the DecayChainVertex supplied has been turned into a TrackingVertex
1037  TrackingVertex* pTrackingVertex=getTrackingVertex( pChainVertex );
1038  if( pTrackingVertex==NULL ) throw std::runtime_error( "associateToExistingObjects was passed a non existent TrackingVertex" );
1039 
1040  //
1041  // Associate to the parent track (if there is one)
1042  //
1043  ::DecayChainTrack* pParentChainTrack=pChainVertex->pParentTrack;
1044  if( pParentChainTrack!=NULL ) // Make sure there is a parent track first
1045  {
1046  // There is a parent track, but it might not have been turned into a TrackingParticle yet
1047  TrackingParticle* pParentTrackingParticle=getTrackingParticle(pParentChainTrack);
1048  if( pParentTrackingParticle!=NULL )
1049  {
1050  pParentTrackingParticle->addDecayVertex( getRef(pChainVertex) );
1051  pTrackingVertex->addParentTrack( getRef(pParentChainTrack) );
1052  }
1053  // Don't worry about the "else" case - the parent track might not necessarily get added
1054  // to the output collection at all. A check is done on daughter vertices when tracks
1055  // are added, so the association will be picked up then.
1056  }
1057 
1058  //
1059  // A parent TrackingVertex is always associated to a daughter TrackingParticle when
1060  // the TrackingParticle is created. Hence there is no need to check the list of
1061  // daughter tracks.
1062  //
1063  }
1064 
1065  void ::OutputCollectionWrapper::associateToExistingObjects( const ::DecayChainTrack* pChainTrack )
1066  {
1067  //
1068  // First make sure this DecayChainTrack has been turned into a TrackingParticle
1069  //
1070  TrackingParticle* pTrackingParticle=getTrackingParticle( pChainTrack );
1071  if( pTrackingParticle==NULL ) throw std::runtime_error( "associateToExistingObjects was passed a non existent TrackingParticle" );
1072 
1073  // Get the parent vertex. This should always already have been turned into a TrackingVertex, and
1074  // there should always be a parent DecayChainVertex.
1075  ::DecayChainVertex* pParentChainVertex=pChainTrack->pParentVertex;
1076  TrackingVertex* pParentTrackingVertex=getTrackingVertex( pParentChainVertex );
1077 
1078  //
1079  // First associate to the parent vertex.
1080  //
1081  pTrackingParticle->setParentVertex( getRef(pParentChainVertex) );
1082  pParentTrackingVertex->addDaughterTrack( getRef(pChainTrack) );
1083 
1084  // If there are any daughter vertices that have already been made into a TrackingVertex
1085  // make sure they know about each other. If the daughter vertices haven't been made into
1086  // TrackingVertexs yet, I won't do anything and create the association when the vertex is
1087  // made.
1088  for( auto pDaughterChainVertex : pChainTrack->daughterVertices )
1089  {
1090  TrackingVertex* pDaughterTrackingVertex=getTrackingVertex( pDaughterChainVertex );
1091  if( pDaughterTrackingVertex!=NULL )
1092  {
1093  pTrackingParticle->addDecayVertex( getRef(pDaughterChainVertex) );
1094  pDaughterTrackingVertex->addParentTrack( getRef(pChainTrack) );
1095  }
1096  }
1097  }
1098 
1099 
1100  TrackingParticle* addTrackAndParentVertex( ::DecayChainTrack* pDecayTrack, const TrackingParticle& trackingParticle, ::OutputCollectionWrapper* pOutput )
1101  {
1102  // See if this TrackingParticle has already been created (could be if the DecayChainTracks are
1103  // looped over in a funny order). If it has then there's no need to do anything.
1104  TrackingParticle* pTrackingParticle=pOutput->getTrackingParticle( pDecayTrack );
1105  if( pTrackingParticle==NULL )
1106  {
1107  // Need to make sure the production vertex has been created first
1108  if( pOutput->getTrackingVertex( pDecayTrack->pParentVertex ) == nullptr )
1109  {
1110  // TrackingVertex doesn't exist in the output collection yet. However, it's already been
1111  // created in the addTrack() function and a temporary reference to it set in the TrackingParticle.
1112  // I'll use that reference to create a copy in the output collection. When the TrackingParticle
1113  // is added to the output collection a few lines below the temporary reference to the parent
1114  // vertex will be cleared, and the correct one referring to the output collection will be set.
1115  pOutput->addTrackingVertex( pDecayTrack->pParentVertex, *trackingParticle.parentVertex() );
1116  }
1117 
1118 
1119  pTrackingParticle=pOutput->addTrackingParticle( pDecayTrack, trackingParticle );
1120  }
1121 
1122  return pTrackingParticle;
1123  }
1124 
1125  void addTrack( ::DecayChainTrack* pDecayChainTrack, const TrackingParticleSelector* pSelector, ::OutputCollectionWrapper* pUnmergedOutput, ::OutputCollectionWrapper* pMergedOutput, const ::TrackingParticleFactory& objectFactory, bool addAncestors, const TrackerTopology *tTopo )
1126  {
1127  if( pDecayChainTrack==NULL ) return; // This is required for when the addAncestors_ recursive call reaches the top of the chain
1128 
1129  // Check to see if this particle has already been processed while traversing up the parents
1130  // of another split in the decay chain. The check in the line above only stops when the top
1131  // of the chain is reached, whereas this will stop when a previously traversed split is reached.
1132  { // block to limit the scope of temporary variables
1133  bool alreadyProcessed=true;
1134  if( pUnmergedOutput!=NULL )
1135  {
1136  if( pUnmergedOutput->getTrackingParticle( pDecayChainTrack )==NULL ) alreadyProcessed=false;
1137  }
1138  if( pMergedOutput!=NULL )
1139  {
1140  if( pMergedOutput->getTrackingParticle( pDecayChainTrack )==NULL ) alreadyProcessed=false;
1141  }
1142  if( alreadyProcessed ) return;
1143  }
1144 
1145  // Create a TrackingParticle.
1146  TrackingParticle newTrackingParticle=objectFactory.createTrackingParticle( pDecayChainTrack, tTopo );
1147 
1148  // The selector checks the impact parameters from the vertex, so I need to have a valid reference
1149  // to the parent vertex in the TrackingParticle before that can be called. TrackingParticle needs
1150  // an edm::Ref for the parent TrackingVertex though. I still don't know if this is going to be
1151  // added to the collection so I can't take it from there, so I need to create a temporary one.
1152  // When the addTrackAndParentVertex() is called (assuming it passes selection) it will use the
1153  // temporary reference to create a copy of the parent vertex, put that in the output collection,
1154  // and then set the reference in the TrackingParticle properly.
1155  TrackingVertexCollection dummyCollection; // Only needed to create an edm::Ref
1156  dummyCollection.push_back( objectFactory.createTrackingVertex( pDecayChainTrack->pParentVertex) );
1157  TrackingVertexRef temporaryRef( &dummyCollection, 0 );
1158  newTrackingParticle.setParentVertex( temporaryRef );
1159 
1160  // If a selector has been supplied apply it on the new TrackingParticle and return if it fails.
1161  if( pSelector )
1162  {
1163  if( !(*pSelector)( newTrackingParticle ) ) return; // Return if the TrackingParticle fails selection
1164  }
1165 
1166  // Add the ancestors first (if required) so that the collection has some kind of chronological
1167  // order. I don't know how important that is but other code might assume chronological order.
1168  // If adding ancestors, no selection is applied. Note that I've already checked that all
1169  // DecayChainTracks have a pParentVertex.
1170  if( addAncestors ) addTrack( pDecayChainTrack->pParentVertex->pParentTrack, NULL, pUnmergedOutput, pMergedOutput, objectFactory, addAncestors, tTopo );
1171 
1172  // If creation of the unmerged collection has been turned off in the config this pointer
1173  // will be null.
1174  if( pUnmergedOutput!=NULL ) addTrackAndParentVertex( pDecayChainTrack, newTrackingParticle, pUnmergedOutput );
1175 
1176  // If creation of the merged collection has been turned off in the config this pointer
1177  // will be null.
1178  if( pMergedOutput!=NULL )
1179  {
1180  ::DecayChainTrack* pBremParentChainTrack=pDecayChainTrack;
1181  while( pBremParentChainTrack->pMergedBremSource!=NULL ) pBremParentChainTrack=pBremParentChainTrack->pMergedBremSource;
1182 
1183  if( pBremParentChainTrack!=pDecayChainTrack )
1184  {
1185  TrackingParticle* pBremParentTrackingParticle=addTrackAndParentVertex( pBremParentChainTrack, newTrackingParticle, pMergedOutput );
1186  // The original particle in the bremsstrahlung decay chain has been
1187  // created (or retrieved if it already existed), now copy in the
1188  // extra information.
1189  // TODO - copy extra information.
1190 
1191  if( std::abs( newTrackingParticle.pdgId() ) == 22 )
1192  {
1193  // Photons are added as separate TrackingParticles, but with the production
1194  // vertex changed to be the production vertex of the original electron.
1195 
1196  // Set up a proxy, so that all requests for the parent TrackingVertex get
1197  // redirected to the brem parent's TrackingVertex.
1198  pMergedOutput->setProxy( pDecayChainTrack->pParentVertex, pBremParentChainTrack->pParentVertex );
1199 
1200  // Now that pMergedOutput thinks the parent vertex is the brem parent's vertex I can
1201  // call this and it will set the TrackingParticle parent vertex correctly to the brem
1202  // parent vertex.
1203  addTrackAndParentVertex( pDecayChainTrack, newTrackingParticle, pMergedOutput );
1204  }
1205  else if( std::abs( newTrackingParticle.pdgId() ) == 11 )
1206  {
1207  // Electrons have their G4 tracks and SimHits copied to the parent TrackingParticle.
1208  for( const auto& trackSegment : newTrackingParticle.g4Tracks() )
1209  {
1210  pBremParentTrackingParticle->addG4Track( trackSegment );
1211  }
1212 
1213  // Also copy the generator particle references
1214  for( const auto& genParticleRef : newTrackingParticle.genParticles() )
1215  {
1216  pBremParentTrackingParticle->addGenParticle( genParticleRef );
1217  }
1218 
1219  pBremParentTrackingParticle->setNumberOfHits(pBremParentTrackingParticle->numberOfHits()+newTrackingParticle.numberOfHits());
1220  pBremParentTrackingParticle->setNumberOfTrackerHits(pBremParentTrackingParticle->numberOfTrackerHits()+newTrackingParticle.numberOfTrackerHits());
1221  pBremParentTrackingParticle->setNumberOfTrackerLayers(pBremParentTrackingParticle->numberOfTrackerLayers()+newTrackingParticle.numberOfTrackerLayers());
1222 
1223  // Set a proxy in the output collection wrapper so that any attempt to get objects for
1224  // this DecayChainTrack again get redirected to the brem parent.
1225  pMergedOutput->setProxy( pDecayChainTrack, pBremParentChainTrack );
1226  }
1227  }
1228  else
1229  {
1230  // This is not the result of bremsstrahlung so add to the collection as normal.
1231  addTrackAndParentVertex( pDecayChainTrack, newTrackingParticle, pMergedOutput );
1232  }
1233  } // end of "if( pMergedOutput!=NULL )", i.e. end of "if bremsstrahlung merging is turned on"
1234 
1235  } // end of addTrack function
1236 
1237 } // end of the unnamed namespace
1238 
1239 // Register with the framework
helper::MatcherGetRef< C >::ref_type getRef(const Handle< C > &c, size_t k)
Definition: getRef.h:28
EDGetTokenT< ProductType > consumes(edm::InputTag const &tag)
T getParameter(std::string const &) const
EncodedEventId eventId() const
Definition: CoreSimTrack.h:31
int event() const
get the contents of the subdetector field (should be protected?)
const std::vector< SimTrack > & g4Tracks() const
ROOT::Math::LorentzVector< ROOT::Math::PxPyPzE4D< double > > XYZTLorentzVectorD
Lorentz vector with cylindrical internal representation using pseudorapidity.
Definition: LorentzVector.h:14
virtual void initializeEvent(const edm::Event &event, const edm::EventSetup &setup)
std::vector< TrackingParticle > TrackingParticleCollection
const reco::GenParticleRefVector & genParticles() const
ROOT::Math::Plane3D::Vector Vector
Definition: EcalHitMaker.cc:29
int pdgId() const
PDG ID.
const bool addAncestors_
Whether or not to add the full parentage of any TrackingParticle that is inserted in the collection...
int init
Definition: HydjetWrapper.h:67
bool exists(std::string const &parameterName) const
checks if a parameter exists
void addDaughterTrack(const TrackingParticleRef &)
const double vertexDistanceCut_
maximum distance for HepMC::GenVertex to be added to SimVertex
#define NULL
Definition: scimark2.h:8
#define nullptr
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:7
void addParentTrack(const TrackingParticleRef &)
float charge() const
charge
Definition: CoreSimTrack.cc:18
tuple vertexCollection
bool signalOnly_
Uses the same config as selector_, but can be used to drop out early since selector_ requires the Tra...
void fillSimHits(std::vector< const PSimHit * > &returnValue, const T &event, const edm::EventSetup &setup)
Fills the supplied vector with pointers to the SimHits, checking for bad modules if required...
const unsigned int maximumSubsequentBunchCrossing_
void setParentVertex(const TrackingVertexRef &ref)
void addGenParticle(const reco::GenParticleRef &ref)
SingleObjectSelector< TrackingParticleCollection,::TrackingParticleSelector > TrackingParticleSelector
void accumulateEvent(const T &event, const edm::EventSetup &setup, const edm::Handle< edm::HepMCProduct > &hepMCproduct)
Both forms of accumulate() delegate to this templated method.
double y() const
Same as rapidity().
int bunchCrossing() const
get the detector field from this detid
void addG4Track(const SimTrack &t)
int genpartIndex() const
index of the corresponding Generator particle in the Event container (-1 if no Genpart) ...
Definition: SimTrack.h:33
int numberOfTrackerLayers() const
The number of tracker layers with a hit.
virtual void finalizeEvent(edm::Event &event, const edm::EventSetup &setup)
T mag2() const
The vector magnitude squared. Equivalent to vec.dot(vec)
const std::string messageCategory_
The message category used to send messages to MessageLogger.
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
bool noVertex() const
Definition: SimTrack.h:30
tuple genEvent
Definition: MCTruth.py:33
const math::XYZTLorentzVectorD & position() const
Definition: CoreSimVertex.h:26
unsigned int vertexId() const
Definition: SimVertex.h:37
std::vector< std::string > getParameterNames() const
How EventSelector::AcceptEvent() decides whether to accept an event for output otherwise it is excluding the probing of A single or multiple positive and the trigger will pass if any such matching triggers are PASS or EXCEPTION[A criterion thatmatches no triggers at all is detected and causes a throw.] A single negative with an expectation of appropriate bit checking in the decision and the trigger will pass if any such matching triggers are FAIL or EXCEPTION A wildcarded negative criterion that matches more than one trigger in the trigger but the state exists so we define the behavior If all triggers are the negative crieriion will lead to accepting the event(this again matches the behavior of"!*"before the partial wildcard feature was incorporated).The per-event"cost"of each negative criterion with multiple relevant triggers is about the same as!*was in the past
int subdetId() const
get the contents of the subdetector field (not cast into any detector&#39;s numbering enum) ...
Definition: DetId.h:37
const TrackingVertexRef & parentVertex() const
bool allowDifferentProcessTypeForDifferentDetectors_
When counting hits, allows hits in different detectors to have a different process type...
std::auto_ptr< TrackingParticleCollection > pTrackingParticles
virtual void accumulate(const edm::Event &event, const edm::EventSetup &setup)
tuple tags
Definition: o2o.py:248
edm::Ref< TrackingVertexCollection > TrackingVertexRef
Definition: DetId.h:18
edm::Ref< edm::HepMCProduct, HepMC::GenVertex > GenVertexRef
std::auto_ptr< TrackingVertexCollection > pInitialVertices_
unsigned int trackId() const
Definition: CoreSimTrack.h:34
const bool createInitialVertexCollection_
Whether or not to create a separate collection for just the initial interaction vertices.
ParameterSet const & getParameterSet(std::string const &) const
std::auto_ptr< TrackingVertexCollection > pTrackingVertices
XYZPointD XYZPoint
point in space with cartesian internal representation
Definition: Point3D.h:12
void addDecayVertex(const TrackingVertexRef &ref)
std::vector< TrackingVertex > TrackingVertexCollection
const T & get() const
Definition: EventSetup.h:56
T const * product() const
Definition: ESHandle.h:86
tuple simHits
Definition: trackerHits.py:16
int numberOfHits() const
Gives the total number of hits, including muon hits. Hits on overlaps in the same layer count separat...
const unsigned int maximumPreviousBunchCrossing_
unsigned int layer(const DetId &id) const
void setNumberOfTrackerHits(int numberOfTrackerHits)
int type() const
particle type (HEP PDT convension)
Definition: CoreSimTrack.h:25
EncodedEventId eventId() const
Definition: CoreSimVertex.h:30
#define DEFINE_DIGI_ACCUMULATOR(type)
static int position[264][3]
Definition: ReadPGInfo.cc:509
bool chargedOnly_
Uses the same config as selector_, but can be used to drop out early since selector_ requires the Tra...
const bool createUnmergedCollection_
If bremsstrahlung merging, whether to also add the unmerged collection to the event or not...
TrackingParticleSelector selector_
Monte Carlo truth information used for tracking validation.
tuple cout
Definition: gather_cfg.py:145
TrackingTruthAccumulator(const edm::ParameterSet &config, edm::stream::EDProducerBase &mixMod, edm::ConsumesCollector &iC)
int numberOfTrackerHits() const
The number of hits in the tracker. Hits on overlaps in the same layer count separately.
void setNumberOfTrackerLayers(const int numberOfTrackerLayers)
Replacement for TrackingTruthProducer in the new pileup mixing setup.
Detector det() const
get the detector field from this detid
Definition: DetId.h:35
long double T
tuple size
Write out results.
edm::Ref< TrackingParticleCollection > TrackingParticleRef
edm::InputTag hepMCproductLabel_
Needed to add HepMC::GenVertex to SimVertex.
math::PtEtaPhiELorentzVectorF LorentzVector
void setNumberOfHits(int numberOfHits)
std::vector< edm::InputTag > collectionTags_