File indexing completed on 2024-04-06 12:23:24
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022 #include "FWCore/Framework/interface/Frameworkfwd.h"
0023 #include "FWCore/Framework/interface/stream/EDProducer.h"
0024 #include "FWCore/Framework/interface/Event.h"
0025 #include "FWCore/Framework/interface/EventSetup.h"
0026 #include "FWCore/Framework/interface/MakerMacros.h"
0027 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0028
0029 #include "DataFormats/HepMCCandidate/interface/GenParticle.h"
0030 #include "DataFormats/HepMCCandidate/interface/GenParticleFwd.h"
0031 #include "SimDataFormats/Track/interface/SimTrackContainer.h"
0032 #include "SimDataFormats/Vertex/interface/SimVertexContainer.h"
0033
0034 #include "CommonTools/Utils/interface/StringCutObjectSelector.h"
0035 #include "SimGeneral/HepPDTRecord/interface/PdtEntry.h"
0036 #include "SimGeneral/HepPDTRecord/interface/ParticleDataTable.h"
0037
0038 #include <ext/algorithm>
0039 #include <memory>
0040
0041 namespace pat {
0042 class GenPlusSimParticleProducer : public edm::stream::EDProducer<> {
0043 public:
0044 explicit GenPlusSimParticleProducer(const edm::ParameterSet &);
0045
0046 private:
0047 void produce(edm::Event &, const edm::EventSetup &) override;
0048
0049 bool firstEvent_;
0050 edm::EDGetTokenT<edm::SimTrackContainer> simtracksToken_;
0051 edm::EDGetTokenT<edm::SimVertexContainer> simverticesToken_;
0052 int setStatus_;
0053 std::set<int> pdgIds_;
0054 std::vector<PdtEntry> pdts_;
0055
0056 typedef StringCutObjectSelector<reco::GenParticle> StrFilter;
0057 std::unique_ptr<StrFilter> filter_;
0058
0059
0060 edm::EDGetTokenT<reco::GenParticleCollection> gensToken_;
0061 edm::EDGetTokenT<std::vector<int>> genBarcodesToken_;
0062
0063 edm::ESGetToken<HepPDT::ParticleDataTable, edm::DefaultRecord> tableToken_;
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078 void addGenParticle(const SimTrack &stMom,
0079 const SimTrack &stDau,
0080 unsigned int momidx,
0081 const edm::SimTrackContainer &simtks,
0082 const edm::SimVertexContainer &simvtxs,
0083 reco::GenParticleCollection &mergedGens,
0084 const reco::GenParticleRefProd ref,
0085 std::vector<int> &genBarcodes,
0086 bool &barcodesAreSorted) const;
0087 struct LessById {
0088 bool operator()(const SimTrack &tk1, const SimTrack &tk2) const { return tk1.trackId() < tk2.trackId(); }
0089 bool operator()(const SimTrack &tk1, unsigned int id) const { return tk1.trackId() < id; }
0090 bool operator()(unsigned int id, const SimTrack &tk2) const { return id < tk2.trackId(); }
0091 };
0092 };
0093 }
0094
0095 using namespace std;
0096 using namespace edm;
0097 using namespace reco;
0098 using pat::GenPlusSimParticleProducer;
0099
0100 GenPlusSimParticleProducer::GenPlusSimParticleProducer(const ParameterSet &cfg)
0101 : firstEvent_(true),
0102 simtracksToken_(consumes<SimTrackContainer>(cfg.getParameter<InputTag>("src"))),
0103 simverticesToken_(
0104 consumes<SimVertexContainer>(cfg.getParameter<InputTag>("src"))),
0105 setStatus_(cfg.getParameter<int32_t>("setStatus")),
0106 gensToken_(consumes<GenParticleCollection>(
0107 cfg.getParameter<InputTag>("genParticles"))),
0108 genBarcodesToken_(consumes<std::vector<int>>(
0109 cfg.getParameter<InputTag>("genParticles")))
0110 {
0111
0112 if (cfg.exists("particleTypes")) {
0113 pdts_ = cfg.getParameter<vector<PdtEntry>>("particleTypes");
0114 if (!pdts_.empty()) {
0115 tableToken_ = esConsumes();
0116 }
0117 }
0118
0119
0120 if (cfg.existsAs<string>("filter")) {
0121 string filter = cfg.getParameter<string>("filter");
0122 if (!filter.empty()) {
0123 filter_ = std::make_unique<StrFilter>(filter);
0124 }
0125 }
0126 produces<GenParticleCollection>();
0127 produces<vector<int>>();
0128 }
0129
0130 void GenPlusSimParticleProducer::addGenParticle(const SimTrack &stMom,
0131 const SimTrack &stDau,
0132 unsigned int momidx,
0133 const SimTrackContainer &simtracksSorted,
0134 const SimVertexContainer &simvertices,
0135 reco::GenParticleCollection &mergedGens,
0136 const GenParticleRefProd ref,
0137 std::vector<int> &genBarcodes,
0138 bool &barcodesAreSorted) const {
0139
0140
0141 int charge = static_cast<int>(stDau.charge());
0142 const Particle::LorentzVector &p4 = stDau.momentum();
0143 Particle::Point vtx;
0144 if (!stDau.noVertex())
0145 vtx = simvertices[stDau.vertIndex()].position();
0146 GenParticle genp(charge, p4, vtx, stDau.type(), setStatus_, true);
0147
0148
0149 if (filter_.get() != nullptr) {
0150 if (!(*filter_)(genp))
0151 return;
0152 }
0153
0154 reco::GenParticleRef parentRef(ref, momidx);
0155 genp.addMother(parentRef);
0156 mergedGens.push_back(genp);
0157
0158 unsigned int dauidx = mergedGens.size() - 1;
0159
0160
0161 reco::GenParticle &cand = mergedGens[momidx];
0162 cand.addDaughter(GenParticleRef(ref, dauidx));
0163
0164
0165
0166 for (SimTrackContainer::const_iterator isimtrk = simtracksSorted.begin(); isimtrk != simtracksSorted.end();
0167 ++isimtrk) {
0168 if (!isimtrk->noVertex()) {
0169
0170 const SimVertex &vtx = simvertices[isimtrk->vertIndex()];
0171
0172
0173 if (!vtx.noParent()) {
0174
0175 unsigned int idx = vtx.parentIndex();
0176 SimTrackContainer::const_iterator it =
0177 std::lower_bound(simtracksSorted.begin(), simtracksSorted.end(), idx, LessById());
0178 if ((it != simtracksSorted.end()) && (it->trackId() == idx)) {
0179 if (it->trackId() == stDau.trackId()) {
0180
0181 addGenParticle(
0182 stDau, *isimtrk, dauidx, simtracksSorted, simvertices, mergedGens, ref, genBarcodes, barcodesAreSorted);
0183 }
0184 }
0185 }
0186 }
0187 }
0188 }
0189
0190 void GenPlusSimParticleProducer::produce(Event &event, const EventSetup &iSetup) {
0191 if (firstEvent_) {
0192 if (!pdts_.empty()) {
0193 auto const &pdt = iSetup.getData(tableToken_);
0194 pdgIds_.clear();
0195 for (vector<PdtEntry>::iterator itp = pdts_.begin(), edp = pdts_.end(); itp != edp; ++itp) {
0196 itp->setup(pdt);
0197 pdgIds_.insert(std::abs(itp->pdgId()));
0198 }
0199 pdts_.clear();
0200 }
0201 firstEvent_ = false;
0202 }
0203
0204
0205 Handle<SimTrackContainer> simtracks;
0206 event.getByToken(simtracksToken_, simtracks);
0207
0208
0209 std::unique_ptr<SimTrackContainer> simtracksTmp;
0210 const SimTrackContainer *simtracksSorted = &*simtracks;
0211 if (!__gnu_cxx::is_sorted(simtracks->begin(), simtracks->end(), LessById())) {
0212 simtracksTmp = std::make_unique<SimTrackContainer>(*simtracks);
0213 std::sort(simtracksTmp->begin(), simtracksTmp->end(), LessById());
0214 simtracksSorted = &*simtracksTmp;
0215 }
0216
0217
0218 Handle<SimVertexContainer> simvertices;
0219 event.getByToken(simverticesToken_, simvertices);
0220
0221
0222 Handle<GenParticleCollection> gens;
0223 Handle<std::vector<int>> genBarcodes;
0224 bool barcodesAreSorted = true;
0225 event.getByToken(gensToken_, gens);
0226 event.getByToken(genBarcodesToken_, genBarcodes);
0227 if (gens->size() != genBarcodes->size())
0228 throw cms::Exception("Corrupt data") << "Barcodes not of the same size as GenParticles!\n";
0229
0230
0231 auto candsPtr = std::make_unique<GenParticleCollection>();
0232 GenParticleCollection &cands = *candsPtr;
0233
0234 const GenParticleRefProd ref = event.getRefBeforePut<GenParticleCollection>();
0235
0236
0237 for (size_t i = 0; i < gens->size(); ++i) {
0238 reco::GenParticle cand((*gens)[i]);
0239 cands.push_back(cand);
0240 }
0241
0242
0243 auto newGenBarcodes = std::make_unique<vector<int>>();
0244 for (unsigned int i = 0; i < genBarcodes->size(); ++i) {
0245 newGenBarcodes->push_back((*genBarcodes)[i]);
0246 }
0247 barcodesAreSorted = __gnu_cxx::is_sorted(newGenBarcodes->begin(), newGenBarcodes->end());
0248
0249 for (size_t i = 0; i < cands.size(); ++i) {
0250 reco::GenParticle &cand = cands[i];
0251 size_t nDaus = cand.numberOfDaughters();
0252 GenParticleRefVector daus = cand.daughterRefVector();
0253 cand.resetDaughters(ref.id());
0254 for (size_t d = 0; d < nDaus; ++d) {
0255 cand.addDaughter(GenParticleRef(ref, daus[d].key()));
0256 }
0257
0258 size_t nMoms = cand.numberOfMothers();
0259 GenParticleRefVector moms = cand.motherRefVector();
0260 cand.resetMothers(ref.id());
0261 for (size_t m = 0; m < nMoms; ++m) {
0262 cand.addMother(GenParticleRef(ref, moms[m].key()));
0263 }
0264 }
0265
0266 for (SimTrackContainer::const_iterator isimtrk = simtracks->begin(); isimtrk != simtracks->end(); ++isimtrk) {
0267
0268 if (isimtrk->genpartIndex() != -1)
0269 continue;
0270
0271
0272 if (!pdgIds_.empty()) {
0273 if (pdgIds_.find(std::abs(isimtrk->type())) == pdgIds_.end())
0274 continue;
0275 }
0276
0277
0278
0279 if (!isimtrk->noVertex()) {
0280
0281 const SimVertex &vtx = (*simvertices)[isimtrk->vertIndex()];
0282
0283
0284 if (!vtx.noParent()) {
0285
0286 unsigned int idx = vtx.parentIndex();
0287 SimTrackContainer::const_iterator it =
0288 std::lower_bound(simtracksSorted->begin(), simtracksSorted->end(), idx, LessById());
0289 if ((it != simtracksSorted->end()) && (it->trackId() == idx)) {
0290 if (it->genpartIndex() != -1) {
0291 std::vector<int>::const_iterator itIndex;
0292 if (barcodesAreSorted) {
0293 itIndex = std::lower_bound(genBarcodes->begin(), genBarcodes->end(), it->genpartIndex());
0294 } else {
0295 itIndex = std::find(genBarcodes->begin(), genBarcodes->end(), it->genpartIndex());
0296 }
0297
0298
0299
0300 if ((itIndex != genBarcodes->end()) && (*itIndex == it->genpartIndex())) {
0301
0302
0303 unsigned int momidx = itIndex - genBarcodes->begin();
0304 addGenParticle(*it,
0305 *isimtrk,
0306 momidx,
0307 *simtracksSorted,
0308 *simvertices,
0309 *candsPtr,
0310 ref,
0311 *newGenBarcodes,
0312 barcodesAreSorted);
0313 }
0314 }
0315 }
0316 }
0317 }
0318 }
0319
0320 event.put(std::move(candsPtr));
0321 event.put(std::move(newGenBarcodes));
0322 }
0323
0324 DEFINE_FWK_MODULE(GenPlusSimParticleProducer);