CMS 3D CMS Logo

Classes | Public Member Functions | Private Types | Private Member Functions | Private Attributes

pat::GenPlusSimParticleProducer Class Reference

Produces reco::GenParticle from SimTracks. More...

Inheritance diagram for pat::GenPlusSimParticleProducer:
edm::EDProducer edm::ProducerBase edm::ProductRegistryHelper

List of all members.

Classes

struct  LessById

Public Member Functions

 GenPlusSimParticleProducer (const edm::ParameterSet &)
 ~GenPlusSimParticleProducer ()

Private Types

typedef
StringCutObjectSelector
< reco::GenParticle
StrFilter

Private Member Functions

void addGenParticle (const SimTrack &stMom, const SimTrack &stDau, unsigned int momidx, const edm::SimTrackContainer &simtks, const edm::SimVertexContainer &simvtxs, reco::GenParticleCollection &mergedGens, const reco::GenParticleRefProd ref, std::vector< int > &genBarcodes, bool &barcodesAreSorted) const
 Try to link the GEANT particle to the generator particle it came from.
virtual void endJob ()
virtual void produce (edm::Event &, const edm::EventSetup &)

Private Attributes

std::auto_ptr< StrFilterfilter_
bool firstEvent_
edm::InputTag genParticles_
 Collection of GenParticles I need to make refs to. It must also have its associated vector<int> of barcodes, aligned with them.
std::set< int > pdgIds_
std::vector< PdtEntrypdts_
int setStatus_
edm::InputTag src_

Detailed Description

Produces reco::GenParticle from SimTracks.

The GenPlusSimParticleProducer produces GenParticles from SimTracks, so they can be used for MC matching. A copy of the original genParticle list is made and the genParticles created from the GEANT/FAMOS particles are added to the list including all ancestors and correct mother/daughter references

Sample useage in cfg.py file: process.genParticlePlusGEANT = cms.EDProducer("GenPlusSimParticleProducer", src = cms.InputTag("g4SimHits"), # use "famosSimHits" for FAMOS setStatus = cms.int32(8), # set status = 8 for GEANT GPs particleTypes = cms.vstring("pi+"), # also picks pi- (optional) filter = cms.vstring("pt > 0.0"), # just for testing genParticles = cms.InputTag("genParticles") # original genParticle list )

Author:
Jordan Tucker (original module), Keith Ulmer (generalization)

Definition at line 39 of file GenPlusSimParticleProducer.cc.


Member Typedef Documentation

Definition at line 54 of file GenPlusSimParticleProducer.cc.


Constructor & Destructor Documentation

GenPlusSimParticleProducer::GenPlusSimParticleProducer ( const edm::ParameterSet cfg) [explicit]

Definition at line 97 of file GenPlusSimParticleProducer.cc.

References edm::ParameterSet::exists(), edm::ParameterSet::existsAs(), align_tpl::filter, filter_, edm::ParameterSet::getParameter(), and pdts_.

                                                                              :
  firstEvent_(true),
  src_(cfg.getParameter<InputTag>("src")),            // source sim tracks & vertices
  setStatus_(cfg.getParameter<int32_t>("setStatus")), // set status of GenParticle to this code
  genParticles_(cfg.getParameter<InputTag>("genParticles")) // get the genParticles to add GEANT particles to
{
  // Possibly allow a list of particle types
  if (cfg.exists("particleTypes")) {
    pdts_ = cfg.getParameter<vector<PdtEntry> >("particleTypes");
  }
  
  // Possibly allow a string cut
  if (cfg.existsAs<string>("filter")) {
    string filter = cfg.getParameter<string>("filter");
    if (!filter.empty()) {
      filter_ = auto_ptr<StrFilter>(new StrFilter(filter));
    }
  }
  produces<GenParticleCollection>();
  produces<vector<int> >();
}
pat::GenPlusSimParticleProducer::~GenPlusSimParticleProducer ( ) [inline]

Definition at line 42 of file GenPlusSimParticleProducer.cc.

{}

Member Function Documentation

void GenPlusSimParticleProducer::addGenParticle ( const SimTrack stMom,
const SimTrack stDau,
unsigned int  momidx,
const edm::SimTrackContainer simtks,
const edm::SimVertexContainer simvtxs,
reco::GenParticleCollection mergedGens,
const reco::GenParticleRefProd  ref,
std::vector< int > &  genBarcodes,
bool &  barcodesAreSorted 
) const [private]

Try to link the GEANT particle to the generator particle it came from.

Arguments: -- Specific -- gp: GenParticle made from the GEANT particle st: The GEANT simTrack for which we create a genParticle

-- GEANT related -- simtks: A list of GEANT tracks, sorted by track id simvtxs: The list of GEANT vertices, in their natural order (skimtks have pointers into this vector!)

-- GenParticle related -- gens : Handle to the GenParticles, to make the ref to genBarcodes : Barcodes for each GenParticle, in a vector aligned to the GenParticleCollection. barcodesAreSorted: true if the barcodes are sorted (which means I can use binary_search on them)

Definition at line 119 of file GenPlusSimParticleProducer.cc.

References reco::CompositeRefCandidateT< D >::addDaughter(), CoreSimTrack::charge(), DeDxDiscriminatorTools::charge(), filter_, EgammaValidation_cff::genp, UserOptions_cff::idx, CoreSimTrack::momentum(), SimVertex::noParent(), SimTrack::noVertex(), p4, SimVertex::parentIndex(), setStatus_, CoreSimTrack::trackId(), CoreSimTrack::type(), and SimTrack::vertIndex().

Referenced by produce().

{
  // Make the genParticle for stDau and add it to the new collection and update the parent-child relationship
  // Make up a GenParticleCandidate from the GEANT track info.
  int charge = static_cast<int>(stDau.charge());
  Particle::LorentzVector p4 = stDau.momentum();
  Particle::Point vtx; // = (0,0,0) by default
  if (!stDau.noVertex()) vtx = simvertices[stDau.vertIndex()].position();
  GenParticle genp(charge, p4, vtx, stDau.type(), setStatus_, true);
  
  // Maybe apply filter on the particle
  if (filter_.get() != 0) {
    if (!(*filter_)(genp)) return;
  }
  
  reco::GenParticleRef parentRef(ref, momidx);
  genp.addMother(parentRef);
  mergedGens.push_back(genp);
  // get the index for the daughter just added
  unsigned int dauidx = mergedGens.size()-1;

  // update add daughter relationship
  reco::GenParticle & cand = mergedGens[ momidx ];
  cand.addDaughter( GenParticleRef( ref, dauidx) );

  //look for simtrack daughters of stDau to see if we need to recur further down the chain
  
  for (SimTrackContainer::const_iterator isimtrk = simtracksSorted.begin();
       isimtrk != simtracksSorted.end(); ++isimtrk) {
    if (!isimtrk->noVertex()) {
      // Pick the vertex (isimtrk.vertIndex() is really an index)
      const SimVertex &vtx = simvertices[isimtrk->vertIndex()];
      
      // Check if the vertex has a parent track (otherwise, we're lost)
      if (!vtx.noParent()) {
        
        // Now note that vtx.parentIndex() is NOT an index, it's a track id, so I have to search for it 
        unsigned int idx = vtx.parentIndex();
        SimTrackContainer::const_iterator it = std::lower_bound(simtracksSorted.begin(), simtracksSorted.end(), idx, LessById());
        if ((it != simtracksSorted.end()) && (it->trackId() == idx)) {
          if (it->trackId()==stDau.trackId()) {
            //need the genparticle index of stDau which is dauidx
            addGenParticle(stDau, *isimtrk, dauidx, simtracksSorted, simvertices, mergedGens, ref, genBarcodes, barcodesAreSorted);
          }
        }
      }
    }
  }
}
virtual void pat::GenPlusSimParticleProducer::endJob ( void  ) [inline, private, virtual]

Reimplemented from edm::EDProducer.

Definition at line 46 of file GenPlusSimParticleProducer.cc.

{}
void GenPlusSimParticleProducer::produce ( edm::Event event,
const edm::EventSetup iSetup 
) [private, virtual]

Implements edm::EDProducer.

Definition at line 177 of file GenPlusSimParticleProducer.cc.

References abs, reco::CompositeRefCandidateT< D >::addDaughter(), addGenParticle(), reco::CompositeRefCandidateT< D >::addMother(), reco::CompositeRefCandidateT< D >::daughterRefVector(), spr::find(), firstEvent_, genParticles_, i, edm::RefProd< C >::id(), UserOptions_cff::idx, combine::key, m, reco::CompositeRefCandidateT< D >::motherRefVector(), SimVertex::noParent(), reco::CompositeRefCandidateT< D >::numberOfDaughters(), reco::CompositeRefCandidateT< D >::numberOfMothers(), SimVertex::parentIndex(), pdgIds_, pdts_, reco::CompositeRefCandidateT< D >::resetDaughters(), reco::CompositeRefCandidateT< D >::resetMothers(), python::multivaluedict::sort(), and src_.

                                                                      {
  if (firstEvent_){
    if (!pdts_.empty()) {
      pdgIds_.clear();
      for (vector<PdtEntry>::iterator itp = pdts_.begin(), edp = pdts_.end(); itp != edp; ++itp) {
        itp->setup(iSetup); // decode string->pdgId and vice-versa                                                                                                      
        pdgIds_.insert(std::abs(itp->pdgId()));
      }
      pdts_.clear();
    }
    firstEvent_ = false;
  }

  // Simulated tracks (i.e. GEANT particles).
  Handle<SimTrackContainer> simtracks;
  event.getByLabel(src_, simtracks);
  
  // Need to check that SimTrackContainer is sorted; otherwise, copy and sort :-(
  std::auto_ptr<SimTrackContainer> simtracksTmp;
  const SimTrackContainer * simtracksSorted = &* simtracks;
  if (!__gnu_cxx::is_sorted(simtracks->begin(), simtracks->end(), LessById())) {
    simtracksTmp.reset(new SimTrackContainer(*simtracks));
    std::sort(simtracksTmp->begin(), simtracksTmp->end(), LessById());
    simtracksSorted = &* simtracksTmp;
  }
  
  // Get the associated vertices
  Handle<SimVertexContainer> simvertices;
  event.getByLabel(src_, simvertices);
  
  // Get the GenParticles and barcodes, if needed to set mother and daughter links
  Handle<GenParticleCollection> gens;
  Handle<std::vector<int> > genBarcodes;
  bool barcodesAreSorted = true;
  event.getByLabel(genParticles_, gens);
  event.getByLabel(genParticles_, genBarcodes);
  if (gens->size() != genBarcodes->size()) throw cms::Exception("Corrupt data") << "Barcodes not of the same size as GenParticles!\n";
  
  // make the output collection
  auto_ptr<GenParticleCollection> candsPtr(new GenParticleCollection);
  GenParticleCollection & cands = * candsPtr;
  
  const GenParticleRefProd ref = event.getRefBeforePut<GenParticleCollection>();
  
  // add the original genParticles to the merged output list
  for( size_t i = 0; i < gens->size(); ++ i ) {
    reco::GenParticle cand((*gens)[i]);
    cands.push_back(cand);
  }
  
  // make new barcodes vector and fill it with the original list
  auto_ptr<vector<int> > newGenBarcodes( new vector<int>() );
  for (unsigned int i = 0; i < genBarcodes->size(); ++i) {
    newGenBarcodes->push_back((*genBarcodes)[i]);
  }
  barcodesAreSorted = __gnu_cxx::is_sorted(newGenBarcodes->begin(), newGenBarcodes->end());
  
  for( size_t i = 0; i < cands.size(); ++ i ) {
    reco::GenParticle & cand = cands[ i ];
    size_t nDaus = cand.numberOfDaughters();
    GenParticleRefVector daus = cand.daughterRefVector();
    cand.resetDaughters( ref.id() );
    for ( size_t d = 0; d < nDaus; ++d) {
      cand.addDaughter( GenParticleRef( ref, daus[d].key() ) );
    }
    
    size_t nMoms = cand.numberOfMothers();
    GenParticleRefVector moms = cand.motherRefVector();
    cand.resetMothers( ref.id() );
    for ( size_t m = 0; m < nMoms; ++m) {
      cand.addMother( GenParticleRef( ref, moms[m].key() ) );
    }
  }
  
  for (SimTrackContainer::const_iterator isimtrk = simtracks->begin();
       isimtrk != simtracks->end(); ++isimtrk) {
    
    // Skip PYTHIA tracks.
    if (isimtrk->genpartIndex() != -1) continue; 
    
    // Maybe apply the PdgId filter
    if (!pdgIds_.empty()) { // if we have a filter on pdg ids
      if (pdgIds_.find(std::abs(isimtrk->type())) == pdgIds_.end()) continue;
    }
    
    // find simtrack that has a genParticle match to its parent
    // Look at the production vertex. If there is no vertex, I can do nothing...
    if (!isimtrk->noVertex()) {
      
      // Pick the vertex (isimtrk.vertIndex() is really an index)
      const SimVertex &vtx = (*simvertices)[isimtrk->vertIndex()];
      
      // Check if the vertex has a parent track (otherwise, we're lost)
      if (!vtx.noParent()) {
        
        // Now note that vtx.parentIndex() is NOT an index, it's a track id, so I have to search for it 
        unsigned int idx = vtx.parentIndex();
        SimTrackContainer::const_iterator it = std::lower_bound(simtracksSorted->begin(), simtracksSorted->end(), idx, LessById());
        if ((it != simtracksSorted->end()) && (it->trackId() == idx)) { //it is the parent sim track
          if (it->genpartIndex() != -1) {
            std::vector<int>::const_iterator itIndex;
            if (barcodesAreSorted) {
              itIndex = std::lower_bound(genBarcodes->begin(), genBarcodes->end(), it->genpartIndex());
            } else {
              itIndex = std::find(       genBarcodes->begin(), genBarcodes->end(), it->genpartIndex());
            }
            
            // Check that I found something
            // I need to check '*itIndex == it->genpartIndex()' because lower_bound just finds the right spot for an item in a sorted list, not the item
            if ((itIndex != genBarcodes->end()) && (*itIndex == it->genpartIndex())) {
              // Ok, I'll make the genParticle for st and add it to the new collection updating the map and parent-child relationship
              // pass the mother and daughter sim tracks and the mother genParticle to method to create the daughter genParticle and recur
              unsigned int momidx = itIndex - genBarcodes->begin();
              addGenParticle(*it, *isimtrk, momidx, *simtracksSorted, *simvertices, *candsPtr, ref, *newGenBarcodes, barcodesAreSorted);
            }
          }
        }
      }
    }   
  }
  
  event.put(candsPtr);
  event.put(newGenBarcodes);
}

Member Data Documentation

Definition at line 55 of file GenPlusSimParticleProducer.cc.

Referenced by addGenParticle(), and GenPlusSimParticleProducer().

Definition at line 48 of file GenPlusSimParticleProducer.cc.

Referenced by produce().

Collection of GenParticles I need to make refs to. It must also have its associated vector<int> of barcodes, aligned with them.

Definition at line 58 of file GenPlusSimParticleProducer.cc.

Referenced by produce().

Definition at line 51 of file GenPlusSimParticleProducer.cc.

Referenced by produce().

Definition at line 52 of file GenPlusSimParticleProducer.cc.

Referenced by GenPlusSimParticleProducer(), and produce().

Definition at line 50 of file GenPlusSimParticleProducer.cc.

Referenced by addGenParticle().

Definition at line 49 of file GenPlusSimParticleProducer.cc.

Referenced by produce().