File indexing completed on 2024-04-06 12:31:59
0001
0002
0003
0004
0005
0006 #include "FWCore/Framework/interface/Frameworkfwd.h"
0007 #include "FWCore/Framework/interface/one/EDAnalyzer.h"
0008 #include "FWCore/Framework/interface/Event.h"
0009 #include "FWCore/Framework/interface/MakerMacros.h"
0010 #include "FWCore/Framework/interface/EventSetup.h"
0011 #include "FWCore/Framework/interface/ESHandle.h"
0012
0013 #include "DataFormats/CTPPSDetId/interface/CTPPSDetId.h"
0014
0015 #include "CondTools/RunInfo/interface/LHCInfoCombined.h"
0016
0017 #include "SimDataFormats/GeneratorProducts/interface/HepMCProduct.h"
0018
0019 #include "DataFormats/ProtonReco/interface/ForwardProton.h"
0020 #include "DataFormats/ProtonReco/interface/ForwardProtonFwd.h"
0021 #include "DataFormats/CTPPSReco/interface/CTPPSLocalTrackLite.h"
0022 #include "DataFormats/CTPPSReco/interface/CTPPSLocalTrackLiteFwd.h"
0023 #include "DataFormats/Common/interface/DetSetVector.h"
0024 #include "DataFormats/CTPPSReco/interface/TotemRPRecHit.h"
0025 #include "DataFormats/CTPPSReco/interface/CTPPSPixelRecHit.h"
0026
0027 #include "TFile.h"
0028 #include "TH1D.h"
0029 #include "TH2D.h"
0030 #include "TProfile.h"
0031 #include "TGraphErrors.h"
0032
0033 #include <map>
0034 #include <string>
0035
0036
0037
0038 class CTPPSProtonReconstructionEfficiencyEstimatorMC : public edm::one::EDAnalyzer<> {
0039 public:
0040 explicit CTPPSProtonReconstructionEfficiencyEstimatorMC(const edm::ParameterSet &);
0041
0042 static void fillDescriptions(edm::ConfigurationDescriptions &descriptions);
0043
0044 private:
0045 void analyze(const edm::Event &, const edm::EventSetup &) override;
0046 void endJob() override;
0047
0048 edm::EDGetTokenT<edm::HepMCProduct> tokenHepMCAfterSmearing_;
0049
0050 edm::EDGetTokenT<std::map<int, edm::DetSetVector<TotemRPRecHit>>> tokenStripRecHitsPerParticle_;
0051 edm::EDGetTokenT<std::map<int, edm::DetSetVector<CTPPSPixelRecHit>>> tokenPixelRecHitsPerParticle_;
0052
0053 edm::EDGetTokenT<CTPPSLocalTrackLiteCollection> tracksToken_;
0054
0055 edm::EDGetTokenT<reco::ForwardProtonCollection> tokenRecoProtonsMultiRP_;
0056
0057 const edm::ESGetToken<LHCInfo, LHCInfoRcd> lhcInfoToken_;
0058 const edm::ESGetToken<LHCInfoPerLS, LHCInfoPerLSRcd> lhcInfoPerLSToken_;
0059 const edm::ESGetToken<LHCInfoPerFill, LHCInfoPerFillRcd> lhcInfoPerFillToken_;
0060 const bool useNewLHCInfo_;
0061
0062 unsigned int rpId_45_N_, rpId_45_F_;
0063 unsigned int rpId_56_N_, rpId_56_F_;
0064
0065 std::map<unsigned int, unsigned int> rpDecId_near_, rpDecId_far_;
0066
0067 std::string outputFile_;
0068
0069 unsigned int verbosity_;
0070
0071 struct PlotGroup {
0072 std::unique_ptr<TProfile> p_eff_vs_xi;
0073
0074 std::unique_ptr<TH1D> h_n_part_acc_nr, h_n_part_acc_fr;
0075
0076 PlotGroup()
0077 : p_eff_vs_xi(new TProfile("", ";#xi_{simu};efficiency", 19, 0.015, 0.205)),
0078 h_n_part_acc_nr(new TH1D("", ";n particles in acceptance", 6, -0.5, +5.5)),
0079 h_n_part_acc_fr(new TH1D("", ";n particles in acceptance", 6, -0.5, +5.5)) {}
0080
0081 void write() const {
0082 p_eff_vs_xi->Write("p_eff_vs_xi");
0083 h_n_part_acc_nr->Write("h_n_part_acc_nr");
0084 h_n_part_acc_fr->Write("h_n_part_acc_fr");
0085 }
0086 };
0087
0088 std::map<unsigned int, std::map<unsigned int, PlotGroup>> plots_;
0089 };
0090
0091
0092
0093 using namespace std;
0094 using namespace edm;
0095 using namespace HepMC;
0096
0097
0098
0099 CTPPSProtonReconstructionEfficiencyEstimatorMC::CTPPSProtonReconstructionEfficiencyEstimatorMC(
0100 const edm::ParameterSet &iConfig)
0101 : tokenHepMCAfterSmearing_(
0102 consumes<edm::HepMCProduct>(iConfig.getParameter<edm::InputTag>("tagHepMCAfterSmearing"))),
0103 tokenStripRecHitsPerParticle_(consumes<std::map<int, edm::DetSetVector<TotemRPRecHit>>>(
0104 iConfig.getParameter<edm::InputTag>("tagStripRecHitsPerParticle"))),
0105 tokenPixelRecHitsPerParticle_(consumes<std::map<int, edm::DetSetVector<CTPPSPixelRecHit>>>(
0106 iConfig.getParameter<edm::InputTag>("tagPixelRecHitsPerParticle"))),
0107 tracksToken_(consumes<CTPPSLocalTrackLiteCollection>(iConfig.getParameter<edm::InputTag>("tagTracks"))),
0108 tokenRecoProtonsMultiRP_(
0109 consumes<reco::ForwardProtonCollection>(iConfig.getParameter<InputTag>("tagRecoProtonsMultiRP"))),
0110
0111 lhcInfoToken_(esConsumes(ESInputTag("", iConfig.getParameter<std::string>("lhcInfoLabel")))),
0112 lhcInfoPerLSToken_(esConsumes(ESInputTag("", iConfig.getParameter<std::string>("lhcInfoPerLSLabel")))),
0113 lhcInfoPerFillToken_(esConsumes(ESInputTag("", iConfig.getParameter<std::string>("lhcInfoPerFillLabel")))),
0114 useNewLHCInfo_(iConfig.getParameter<bool>("useNewLHCInfo")),
0115
0116 rpId_45_N_(iConfig.getParameter<unsigned int>("rpId_45_N")),
0117 rpId_45_F_(iConfig.getParameter<unsigned int>("rpId_45_F")),
0118 rpId_56_N_(iConfig.getParameter<unsigned int>("rpId_56_N")),
0119 rpId_56_F_(iConfig.getParameter<unsigned int>("rpId_56_F")),
0120
0121 outputFile_(iConfig.getParameter<string>("outputFile")),
0122
0123 verbosity_(iConfig.getUntrackedParameter<unsigned int>("verbosity", 0)) {
0124 rpDecId_near_[0] = rpId_45_N_;
0125 rpDecId_far_[0] = rpId_45_F_;
0126
0127 rpDecId_near_[1] = rpId_56_N_;
0128 rpDecId_far_[1] = rpId_56_F_;
0129
0130
0131 for (unsigned int arm = 0; arm < 2; ++arm) {
0132 for (unsigned int np = 1; np <= 5; ++np)
0133 plots_[arm][np] = PlotGroup();
0134 }
0135 }
0136
0137
0138
0139 void CTPPSProtonReconstructionEfficiencyEstimatorMC::fillDescriptions(edm::ConfigurationDescriptions &descriptions) {
0140 edm::ParameterSetDescription desc;
0141
0142 desc.add<edm::InputTag>("tagTracks", edm::InputTag())->setComment("input tag for local lite tracks");
0143 desc.add<edm::InputTag>("tagRecoProtonsMultiRP", edm::InputTag())->setComment("input tag for multi-RP reco protons");
0144
0145 desc.add<std::string>("lhcInfoLabel", "")->setComment("label of the LHCInfo record");
0146 desc.add<std::string>("lhcInfoPerLSLabel", "")->setComment("label of the LHCInfoPerLS record");
0147 desc.add<std::string>("lhcInfoPerFillLabel", "")->setComment("label of the LHCInfoPerFill record");
0148 desc.add<bool>("useNewLHCInfo", false)->setComment("flag whether to use new LHCInfoPer* records or old LHCInfo");
0149
0150 desc.add<unsigned int>("rpId_45_N", 0)->setComment("decimal RP id for 45 near");
0151 desc.add<unsigned int>("rpId_45_F", 0)->setComment("decimal RP id for 45 far");
0152 desc.add<unsigned int>("rpId_56_N", 0)->setComment("decimal RP id for 56 near");
0153 desc.add<unsigned int>("rpId_56_F", 0)->setComment("decimal RP id for 56 far");
0154
0155 desc.add<std::string>("outputFile", "output.root")->setComment("output file name");
0156
0157 desc.addUntracked<unsigned int>("verbosity", 0)->setComment("verbosity level");
0158
0159 descriptions.add("ctppsProtonReconstructionEfficiencyEstimatorMCDefault", desc);
0160 }
0161
0162
0163
0164 void CTPPSProtonReconstructionEfficiencyEstimatorMC::analyze(const edm::Event &iEvent, const edm::EventSetup &iSetup) {
0165 std::ostringstream os;
0166
0167
0168 const LHCInfoCombined lhcInfoCombined(
0169 iSetup, lhcInfoPerLSToken_, lhcInfoPerFillToken_, lhcInfoToken_, useNewLHCInfo_);
0170
0171
0172 edm::Handle<edm::HepMCProduct> hHepMCAfterSmearing;
0173 iEvent.getByToken(tokenHepMCAfterSmearing_, hHepMCAfterSmearing);
0174 HepMC::GenEvent *hepMCEventAfterSmearing = (HepMC::GenEvent *)hHepMCAfterSmearing->GetEvent();
0175
0176 edm::Handle<std::map<int, edm::DetSetVector<TotemRPRecHit>>> hStripRecHitsPerParticle;
0177 iEvent.getByToken(tokenStripRecHitsPerParticle_, hStripRecHitsPerParticle);
0178
0179 edm::Handle<std::map<int, edm::DetSetVector<CTPPSPixelRecHit>>> hPixelRecHitsPerParticle;
0180 iEvent.getByToken(tokenPixelRecHitsPerParticle_, hPixelRecHitsPerParticle);
0181
0182 edm::Handle<CTPPSLocalTrackLiteCollection> tracks;
0183 iEvent.getByToken(tracksToken_, tracks);
0184
0185 Handle<reco::ForwardProtonCollection> hRecoProtonsMultiRP;
0186 iEvent.getByToken(tokenRecoProtonsMultiRP_, hRecoProtonsMultiRP);
0187
0188
0189 struct ParticleInfo {
0190 unsigned int arm = 2;
0191 double xi = 0.;
0192 std::map<unsigned int, unsigned int> recHitsPerRP;
0193 bool inAcceptanceNear = false, inAcceptanceFar = false, inAcceptance = false;
0194 };
0195
0196 std::map<int, ParticleInfo> particleInfo;
0197
0198
0199 for (auto it = hepMCEventAfterSmearing->particles_begin(); it != hepMCEventAfterSmearing->particles_end(); ++it) {
0200 const auto &part = *it;
0201
0202
0203 if (part->pdg_id() != 2212)
0204 continue;
0205
0206 if (part->status() != 1)
0207 continue;
0208
0209 if (part->is_beam())
0210 continue;
0211
0212 const auto &mom = part->momentum();
0213
0214 if (mom.e() < 4500.)
0215 continue;
0216
0217 ParticleInfo info;
0218
0219 info.arm = (mom.z() > 0.) ? 0 : 1;
0220
0221 const double p_nom = lhcInfoCombined.energy;
0222 info.xi = (p_nom - mom.rho()) / p_nom;
0223
0224 particleInfo[part->barcode()] = std::move(info);
0225 }
0226
0227
0228 for (const auto &pp : *hStripRecHitsPerParticle) {
0229 const auto barcode = pp.first;
0230
0231 for (const auto &ds : pp.second) {
0232 CTPPSDetId detId(ds.detId());
0233 CTPPSDetId rpId = detId.rpId();
0234 particleInfo[barcode].recHitsPerRP[rpId] += ds.size();
0235 }
0236 }
0237
0238 for (const auto &pp : *hPixelRecHitsPerParticle) {
0239 const auto barcode = pp.first;
0240
0241 for (const auto &ds : pp.second) {
0242 CTPPSDetId detId(ds.detId());
0243 CTPPSDetId rpId = detId.rpId();
0244 particleInfo[barcode].recHitsPerRP[rpId] += ds.size();
0245 }
0246 }
0247
0248 std::map<unsigned int, bool> isStripRPNear, isStripRPFar;
0249
0250 for (auto &pp : particleInfo) {
0251 if (verbosity_)
0252 os << "* barcode=" << pp.first << ", arm=" << pp.second.arm << ", xi=" << pp.second.xi << std::endl;
0253
0254 for (const auto &rpp : pp.second.recHitsPerRP) {
0255 CTPPSDetId rpId(rpp.first);
0256 unsigned int needed_rec_hits = 1000;
0257 if (rpId.subdetId() == CTPPSDetId::sdTrackingStrip)
0258 needed_rec_hits = 6;
0259 if (rpId.subdetId() == CTPPSDetId::sdTrackingPixel)
0260 needed_rec_hits = 3;
0261
0262 unsigned int rpDecId = rpId.arm() * 100 + rpId.station() * 10 + rpId.rp();
0263
0264 if (rpId.subdetId() == CTPPSDetId::sdTrackingStrip) {
0265 if (rpDecId == rpDecId_near_[rpId.arm()])
0266 isStripRPNear[rpId.arm()] = true;
0267 if (rpDecId == rpDecId_far_[rpId.arm()])
0268 isStripRPFar[rpId.arm()] = true;
0269 }
0270
0271 if (rpp.second >= needed_rec_hits) {
0272 if (rpDecId == rpDecId_near_[rpId.arm()])
0273 pp.second.inAcceptanceNear = true;
0274 if (rpDecId == rpDecId_far_[rpId.arm()])
0275 pp.second.inAcceptanceFar = true;
0276 }
0277
0278 if (verbosity_)
0279 os << " RP " << rpDecId << ": " << rpp.second << " hits" << std::endl;
0280 }
0281
0282 pp.second.inAcceptance = pp.second.inAcceptanceNear && pp.second.inAcceptanceFar;
0283
0284 if (verbosity_)
0285 os << " inAcceptance: near=" << pp.second.inAcceptanceNear << ", far=" << pp.second.inAcceptanceFar
0286 << ", global=" << pp.second.inAcceptance << std::endl;
0287 }
0288
0289
0290 struct ArmCounter {
0291 unsigned int near = 0, far = 0, global = 0;
0292 };
0293 std::map<unsigned int, ArmCounter> nParticlesInAcceptance;
0294 for (auto &pp : particleInfo) {
0295 auto &counter = nParticlesInAcceptance[pp.second.arm];
0296 if (pp.second.inAcceptanceNear)
0297 counter.near++;
0298 if (pp.second.inAcceptanceFar)
0299 counter.far++;
0300 if (pp.second.inAcceptance)
0301 counter.global++;
0302 }
0303
0304
0305 std::map<unsigned int, ArmCounter> nReconstructedTracks;
0306 for (const auto &tr : *tracks) {
0307 CTPPSDetId rpId(tr.rpId());
0308 unsigned int rpDecId = rpId.arm() * 100 + rpId.station() * 10 + rpId.rp();
0309
0310 if (rpDecId == rpDecId_near_[rpId.arm()])
0311 nReconstructedTracks[rpId.arm()].near++;
0312 if (rpDecId == rpDecId_far_[rpId.arm()])
0313 nReconstructedTracks[rpId.arm()].far++;
0314 }
0315
0316
0317 std::map<unsigned int, unsigned int> nReconstructedProtons;
0318 for (const auto &pr : *hRecoProtonsMultiRP) {
0319 if (!pr.validFit())
0320 continue;
0321
0322 unsigned int arm = 2;
0323 if (pr.lhcSector() == reco::ForwardProton::LHCSector::sector45)
0324 arm = 0;
0325 if (pr.lhcSector() == reco::ForwardProton::LHCSector::sector56)
0326 arm = 1;
0327
0328 nReconstructedProtons[arm]++;
0329 }
0330
0331
0332 for (unsigned int arm = 0; arm < 2; arm++) {
0333 const auto &npa = nParticlesInAcceptance[arm];
0334 const auto &nrt = nReconstructedTracks[arm];
0335
0336 if (verbosity_)
0337 os << "* arm " << arm << ": nRecoProtons=" << nReconstructedProtons[arm]
0338 << " (tracks near=" << nReconstructedTracks[arm].near << ", far=" << nReconstructedTracks[arm].far
0339 << "), nAcc=" << npa.global << " (near=" << npa.near << ", far=" << npa.far << ")" << std::endl;
0340
0341
0342 if (npa.global < 1)
0343 continue;
0344
0345 const auto &p = plots_[arm][npa.global];
0346
0347 p.h_n_part_acc_nr->Fill(npa.near);
0348 p.h_n_part_acc_fr->Fill(npa.far);
0349
0350
0351 if (nrt.near != npa.near || nrt.far != npa.far)
0352 continue;
0353
0354 const double eff = double(nReconstructedProtons[arm]) / npa.global;
0355
0356 if (verbosity_)
0357 os << " eff=" << eff << std::endl;
0358
0359 for (auto &pp : particleInfo) {
0360 if (pp.second.arm != arm || !pp.second.inAcceptance)
0361 continue;
0362
0363 p.p_eff_vs_xi->Fill(pp.second.xi, eff);
0364 }
0365 }
0366
0367 if (verbosity_)
0368 edm::LogInfo("CTPPSProtonReconstructionEfficiencyEstimatorMC") << os.str();
0369 }
0370
0371
0372
0373 void CTPPSProtonReconstructionEfficiencyEstimatorMC::endJob() {
0374 auto f_out = std::make_unique<TFile>(outputFile_.c_str(), "recreate");
0375
0376 for (const auto &ait : plots_) {
0377 char buf[100];
0378 sprintf(buf, "arm%u", ait.first);
0379 TDirectory *d_arm = f_out->mkdir(buf);
0380
0381 for (const auto &npit : ait.second) {
0382 sprintf(buf, "%u", npit.first);
0383 TDirectory *d_np = d_arm->mkdir(buf);
0384 gDirectory = d_np;
0385
0386 npit.second.write();
0387 }
0388 }
0389 }
0390
0391
0392
0393 DEFINE_FWK_MODULE(CTPPSProtonReconstructionEfficiencyEstimatorMC);