File indexing completed on 2024-04-06 12:23:49
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include "FWCore/Framework/interface/Frameworkfwd.h"
0013 #include "FWCore/Framework/interface/stream/EDProducer.h"
0014 #include "FWCore/Framework/interface/Event.h"
0015 #include "FWCore/Framework/interface/MakerMacros.h"
0016 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0017
0018 #include "DataFormats/HepMCCandidate/interface/GenParticle.h"
0019 #include "DataFormats/HepMCCandidate/interface/GenParticleFwd.h"
0020 #include "SimDataFormats/Track/interface/SimTrackContainer.h"
0021 #include "SimDataFormats/Vertex/interface/SimVertexContainer.h"
0022
0023 #include "CommonTools/Utils/interface/StringCutObjectSelector.h"
0024 #include "SimGeneral/HepPDTRecord/interface/PdtEntry.h"
0025 #include "SimGeneral/HepPDTRecord/interface/ParticleDataTable.h"
0026
0027 #include <ext/algorithm>
0028 #include <memory>
0029
0030 namespace pat {
0031 class PATGenCandsFromSimTracksProducer : public edm::stream::EDProducer<> {
0032 public:
0033 explicit PATGenCandsFromSimTracksProducer(const edm::ParameterSet &);
0034 ~PATGenCandsFromSimTracksProducer() override {}
0035
0036 private:
0037 void produce(edm::Event &, const edm::EventSetup &) override;
0038
0039 bool firstEvent_;
0040 edm::EDGetTokenT<edm::SimTrackContainer> simTracksToken_;
0041 edm::EDGetTokenT<edm::SimVertexContainer> simVertexToken_;
0042 int setStatus_;
0043 std::set<int> pdgIds_;
0044 std::vector<PdtEntry> pdts_;
0045 std::set<int> motherPdgIds_;
0046 std::vector<PdtEntry> motherPdts_;
0047
0048 typedef StringCutObjectSelector<reco::GenParticle> StrFilter;
0049 const StrFilter filter_;
0050
0051
0052 bool makeMotherLink_;
0053
0054 bool writeAncestors_;
0055
0056
0057 edm::EDGetTokenT<reco::GenParticleCollection> genParticlesToken_;
0058 edm::EDGetTokenT<std::vector<int> > genBarcodesToken_;
0059
0060 edm::ESGetToken<HepPDT::ParticleDataTable, edm::DefaultRecord> tableToken_;
0061
0062 struct GlobalContext {
0063 GlobalContext(const edm::SimTrackContainer &simtks1,
0064 const edm::SimVertexContainer &simvtxs1,
0065 const edm::Handle<reco::GenParticleCollection> &gens1,
0066 const edm::Handle<std::vector<int> > &genBarcodes1,
0067 bool barcodesAreSorted1,
0068 reco::GenParticleCollection &output1,
0069 const edm::RefProd<reco::GenParticleCollection> &refprod1)
0070 : simtks(simtks1),
0071 simvtxs(simvtxs1),
0072 gens(gens1),
0073 genBarcodes(genBarcodes1),
0074 barcodesAreSorted(barcodesAreSorted1),
0075 output(output1),
0076 refprod(refprod1),
0077 simTksProcessed() {}
0078
0079 const edm::SimTrackContainer &simtks;
0080 const edm::SimVertexContainer &simvtxs;
0081
0082 const edm::Handle<reco::GenParticleCollection> &gens;
0083 const edm::Handle<std::vector<int> > &genBarcodes;
0084 bool barcodesAreSorted;
0085
0086 reco::GenParticleCollection &output;
0087 const edm::RefProd<reco::GenParticleCollection> &refprod;
0088
0089 std::map<unsigned int, int> simTksProcessed;
0090
0091
0092
0093 };
0094
0095
0096 const SimTrack *findGeantMother(const SimTrack &tk, const GlobalContext &g) const;
0097
0098
0099
0100
0101
0102 edm::Ref<reco::GenParticleCollection> findRef(const SimTrack &tk, GlobalContext &g) const;
0103
0104
0105 edm::Ref<reco::GenParticleCollection> generatorRef_(const SimTrack &tk, const GlobalContext &g) const;
0106
0107 reco::GenParticle makeGenParticle_(const SimTrack &tk,
0108 const edm::Ref<reco::GenParticleCollection> &mother,
0109 const GlobalContext &g) const;
0110
0111 struct LessById {
0112 bool operator()(const SimTrack &tk1, const SimTrack &tk2) const { return tk1.trackId() < tk2.trackId(); }
0113 bool operator()(const SimTrack &tk1, unsigned int id) const { return tk1.trackId() < id; }
0114 bool operator()(unsigned int id, const SimTrack &tk2) const { return id < tk2.trackId(); }
0115 };
0116 };
0117 }
0118
0119 using namespace std;
0120 using namespace edm;
0121 using namespace reco;
0122 using pat::PATGenCandsFromSimTracksProducer;
0123
0124 PATGenCandsFromSimTracksProducer::PATGenCandsFromSimTracksProducer(const ParameterSet &cfg)
0125 : firstEvent_(true),
0126 simTracksToken_(consumes<SimTrackContainer>(cfg.getParameter<InputTag>("src"))),
0127 simVertexToken_(consumes<SimVertexContainer>(cfg.getParameter<InputTag>("src"))),
0128 setStatus_(cfg.getParameter<int32_t>("setStatus")),
0129 filter_(cfg.existsAs<string>("filter") ? cfg.getParameter<string>("filter") : std::string("1 == 1")),
0130 makeMotherLink_(cfg.existsAs<bool>("makeMotherLink") ? cfg.getParameter<bool>("makeMotherLink") : false),
0131 writeAncestors_(cfg.existsAs<bool>("writeAncestors") ? cfg.getParameter<bool>("writeAncestors") : false),
0132 genParticlesToken_(mayConsume<GenParticleCollection>(cfg.getParameter<InputTag>("genParticles"))),
0133 genBarcodesToken_(mayConsume<std::vector<int> >(cfg.getParameter<InputTag>("genParticles"))),
0134 tableToken_(esConsumes()) {
0135
0136 if (cfg.exists("particleTypes")) {
0137 pdts_ = cfg.getParameter<vector<PdtEntry> >("particleTypes");
0138 }
0139 if (cfg.exists("motherTypes")) {
0140 motherPdts_ = cfg.getParameter<vector<PdtEntry> >("motherTypes");
0141 }
0142
0143 if (writeAncestors_ && !makeMotherLink_) {
0144 edm::LogWarning("Configuration")
0145 << "PATGenCandsFromSimTracksProducer: "
0146 << "you have set 'writeAncestors' to 'true' and 'makeMotherLink' to false;"
0147 << "GEANT particles with generator level (e.g.PYHIA) mothers won't have mother links.\n";
0148 }
0149 produces<GenParticleCollection>();
0150 }
0151
0152 const SimTrack *PATGenCandsFromSimTracksProducer::findGeantMother(const SimTrack &tk, const GlobalContext &g) const {
0153 assert(tk.genpartIndex() == -1);
0154 if (!tk.noVertex()) {
0155 const SimVertex &vtx = g.simvtxs[tk.vertIndex()];
0156 if (!vtx.noParent()) {
0157 unsigned int idx = vtx.parentIndex();
0158 SimTrackContainer::const_iterator it = std::lower_bound(g.simtks.begin(), g.simtks.end(), idx, LessById());
0159 if ((it != g.simtks.end()) && (it->trackId() == idx)) {
0160 return &*it;
0161 }
0162 }
0163 }
0164 return nullptr;
0165 }
0166
0167 edm::Ref<reco::GenParticleCollection> PATGenCandsFromSimTracksProducer::findRef(const SimTrack &tk,
0168 GlobalContext &g) const {
0169 if (tk.genpartIndex() != -1)
0170 return makeMotherLink_ ? generatorRef_(tk, g) : edm::Ref<reco::GenParticleCollection>();
0171 const SimTrack *simMother = findGeantMother(tk, g);
0172
0173 edm::Ref<reco::GenParticleCollection> motherRef;
0174 if (simMother != nullptr)
0175 motherRef = findRef(*simMother, g);
0176
0177 if (writeAncestors_) {
0178
0179
0180 std::map<unsigned int, int>::const_iterator it = g.simTksProcessed.find(tk.trackId());
0181 if (it != g.simTksProcessed.end()) {
0182
0183 assert(it->second > 0);
0184 return edm::Ref<reco::GenParticleCollection>(g.refprod, (it->second) - 1);
0185 } else {
0186
0187 reco::GenParticle p = makeGenParticle_(tk, motherRef, g);
0188 g.output.push_back(p);
0189 g.simTksProcessed[tk.trackId()] = g.output.size();
0190 return edm::Ref<reco::GenParticleCollection>(g.refprod, g.output.size() - 1);
0191 }
0192 } else {
0193
0194 return motherRef;
0195 }
0196 }
0197
0198 edm::Ref<reco::GenParticleCollection> PATGenCandsFromSimTracksProducer::generatorRef_(const SimTrack &st,
0199 const GlobalContext &g) const {
0200 assert(st.genpartIndex() != -1);
0201
0202 std::vector<int>::const_iterator it;
0203 if (g.barcodesAreSorted) {
0204 it = std::lower_bound(g.genBarcodes->begin(), g.genBarcodes->end(), st.genpartIndex());
0205 } else {
0206 it = std::find(g.genBarcodes->begin(), g.genBarcodes->end(), st.genpartIndex());
0207 }
0208
0209
0210
0211 if ((it != g.genBarcodes->end()) && (*it == st.genpartIndex())) {
0212 return reco::GenParticleRef(g.gens, it - g.genBarcodes->begin());
0213 } else {
0214 return reco::GenParticleRef();
0215 }
0216 }
0217
0218 reco::GenParticle PATGenCandsFromSimTracksProducer::makeGenParticle_(
0219 const SimTrack &tk, const edm::Ref<reco::GenParticleCollection> &mother, const GlobalContext &g) const {
0220
0221 int charge = static_cast<int>(tk.charge());
0222 const Particle::LorentzVector &p4 = tk.momentum();
0223 Particle::Point vtx;
0224 if (!tk.noVertex())
0225 vtx = g.simvtxs[tk.vertIndex()].position();
0226 GenParticle gp(charge, p4, vtx, tk.type(), setStatus_, true);
0227 if (mother.isNonnull())
0228 gp.addMother(mother);
0229 return gp;
0230 }
0231
0232 void PATGenCandsFromSimTracksProducer::produce(Event &event, const EventSetup &iSetup) {
0233 if (firstEvent_) {
0234 auto const &pdt = iSetup.getData(tableToken_);
0235 if (!pdts_.empty()) {
0236 pdgIds_.clear();
0237 for (vector<PdtEntry>::iterator itp = pdts_.begin(), edp = pdts_.end(); itp != edp; ++itp) {
0238 itp->setup(pdt);
0239 pdgIds_.insert(std::abs(itp->pdgId()));
0240 }
0241 pdts_.clear();
0242 }
0243 if (!motherPdts_.empty()) {
0244 motherPdgIds_.clear();
0245 for (vector<PdtEntry>::iterator itp = motherPdts_.begin(), edp = motherPdts_.end(); itp != edp; ++itp) {
0246 itp->setup(pdt);
0247 motherPdgIds_.insert(std::abs(itp->pdgId()));
0248 }
0249 motherPdts_.clear();
0250 }
0251 firstEvent_ = false;
0252 }
0253
0254
0255 Handle<SimTrackContainer> simtracks;
0256 event.getByToken(simTracksToken_, simtracks);
0257
0258
0259 std::unique_ptr<SimTrackContainer> simtracksTmp;
0260 const SimTrackContainer *simtracksSorted = &*simtracks;
0261 if (makeMotherLink_ || writeAncestors_) {
0262 if (!__gnu_cxx::is_sorted(simtracks->begin(), simtracks->end(), LessById())) {
0263 simtracksTmp = std::make_unique<SimTrackContainer>(*simtracks);
0264 std::sort(simtracksTmp->begin(), simtracksTmp->end(), LessById());
0265 simtracksSorted = &*simtracksTmp;
0266 }
0267 }
0268
0269
0270 Handle<SimVertexContainer> simvertices;
0271 event.getByToken(simVertexToken_, simvertices);
0272
0273
0274 Handle<GenParticleCollection> gens;
0275 Handle<std::vector<int> > genBarcodes;
0276 bool barcodesAreSorted = true;
0277 if (makeMotherLink_) {
0278 event.getByToken(genParticlesToken_, gens);
0279 event.getByToken(genBarcodesToken_, genBarcodes);
0280 if (gens->size() != genBarcodes->size())
0281 throw cms::Exception("Corrupt data") << "Barcodes not of the same size as GenParticles!\n";
0282 barcodesAreSorted = __gnu_cxx::is_sorted(genBarcodes->begin(), genBarcodes->end());
0283 }
0284
0285
0286 auto cands = std::make_unique<GenParticleCollection>();
0287 edm::RefProd<GenParticleCollection> refprod = event.getRefBeforePut<GenParticleCollection>();
0288
0289 GlobalContext globals(*simtracksSorted, *simvertices, gens, genBarcodes, barcodesAreSorted, *cands, refprod);
0290
0291 for (SimTrackContainer::const_iterator isimtrk = simtracks->begin(); isimtrk != simtracks->end(); ++isimtrk) {
0292
0293 if (isimtrk->genpartIndex() != -1)
0294 continue;
0295
0296
0297 if (!pdgIds_.empty()) {
0298 if (pdgIds_.find(std::abs(isimtrk->type())) == pdgIds_.end())
0299 continue;
0300 }
0301
0302 GenParticle genp = makeGenParticle_(*isimtrk, Ref<GenParticleCollection>(), globals);
0303
0304
0305 if (!(filter_(genp)))
0306 continue;
0307
0308 if (!motherPdgIds_.empty()) {
0309 const SimTrack *motherSimTk = findGeantMother(*isimtrk, globals);
0310 if (motherSimTk == nullptr)
0311 continue;
0312 if (motherPdgIds_.find(std::abs(motherSimTk->type())) == motherPdgIds_.end())
0313 continue;
0314 }
0315
0316 if (makeMotherLink_ || writeAncestors_) {
0317 Ref<GenParticleCollection> motherRef;
0318 const SimTrack *mother = findGeantMother(*isimtrk, globals);
0319 if (mother != nullptr)
0320 motherRef = findRef(*mother, globals);
0321 if (motherRef.isNonnull())
0322 genp.addMother(motherRef);
0323 }
0324
0325 cands->push_back(genp);
0326 }
0327
0328
0329 edm::OrphanHandle<reco::GenParticleCollection> orphans = event.put(std::move(cands));
0330
0331 #ifdef DEBUG_PATGenCandsFromSimTracksProducer
0332 std::cout << "Produced a list of " << orphans->size() << " genParticles." << std::endl;
0333 for (GenParticleCollection::const_iterator it = orphans->begin(), ed = orphans->end(); it != ed; ++it) {
0334 std::cout << " ";
0335 std::cout << "GenParticle #" << (it - orphans->begin()) << ": pdgId " << it->pdgId() << ", pt = " << it->pt()
0336 << ", eta = " << it->eta() << ", phi = " << it->phi() << ", rho = " << it->vertex().Rho()
0337 << ", z = " << it->vertex().Z() << std::endl;
0338 edm::Ref<GenParticleCollection> mom = it->motherRef();
0339 size_t depth = 2;
0340 while (mom.isNonnull()) {
0341 if (mom.id() == orphans.id()) {
0342
0343 mom = edm::Ref<GenParticleCollection>(orphans, mom.key());
0344 }
0345 for (size_t i = 0; i < depth; ++i)
0346 std::cout << " ";
0347 std::cout << "GenParticleRef [" << mom.id() << "/" << mom.key() << "]: pdgId " << mom->pdgId()
0348 << ", status = " << mom->status() << ", pt = " << mom->pt() << ", eta = " << mom->eta()
0349 << ", phi = " << mom->phi() << ", rho = " << mom->vertex().Rho() << ", z = " << mom->vertex().Z()
0350 << std::endl;
0351 if (mom.id() != orphans.id())
0352 break;
0353 if ((mom->motherRef().id() == mom.id()) && (mom->motherRef().key() == mom.key())) {
0354 throw cms::Exception("Corrupt Data") << "A particle is it's own mother.\n";
0355 }
0356 mom = mom->motherRef();
0357 depth++;
0358 }
0359 }
0360 std::cout << std::endl;
0361 #endif
0362 }
0363
0364 DEFINE_FWK_MODULE(PATGenCandsFromSimTracksProducer);