File indexing completed on 2024-04-06 12:20:44
0001 #include <memory>
0002
0003 #include "FWCore/Framework/interface/Frameworkfwd.h"
0004 #include "FWCore/Framework/interface/stream/EDProducer.h"
0005 #include "FWCore/Framework/interface/Event.h"
0006 #include "FWCore/Framework/interface/MakerMacros.h"
0007 #include "FWCore/Framework/interface/ESHandle.h"
0008 #include "FWCore/Framework/interface/EventSetup.h"
0009 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0010 #include "FWCore/Utilities/interface/StreamID.h"
0011 #include "DataFormats/Common/interface/AssociationMap.h"
0012 #include "DataFormats/Common/interface/OneToMany.h"
0013 #include "DataFormats/Common/interface/Ref.h"
0014 #include "DataFormats/L1THGCal/interface/HGCalTriggerCell.h"
0015 #include "DataFormats/L1THGCal/interface/HGCalMulticluster.h"
0016 #include "DataFormats/ForwardDetId/interface/HGCalDetId.h"
0017 #include "SimDataFormats/CaloAnalysis/interface/CaloParticleFwd.h"
0018 #include "SimDataFormats/CaloAnalysis/interface/CaloParticle.h"
0019 #include "SimDataFormats/CaloAnalysis/interface/SimCluster.h"
0020 #include "L1Trigger/L1THGCal/interface/HGCalTriggerGeometryBase.h"
0021 #include "L1Trigger/L1THGCal/interface/backend/HGCalShowerShape.h"
0022 #include "L1Trigger/L1THGCal/interface/backend/HGCalClusteringDummyImpl.h"
0023 #include "L1Trigger/L1THGCal/interface/HGCalTriggerTools.h"
0024 #include "Geometry/Records/interface/CaloGeometryRecord.h"
0025
0026 class CaloTruthCellsProducer : public edm::stream::EDProducer<> {
0027 public:
0028 explicit CaloTruthCellsProducer(edm::ParameterSet const&);
0029 ~CaloTruthCellsProducer() override;
0030
0031 static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
0032
0033 private:
0034 void produce(edm::Event&, edm::EventSetup const&) override;
0035
0036 std::unordered_map<uint32_t, double> makeHitMap(edm::Event const&,
0037 edm::EventSetup const&,
0038 HGCalTriggerGeometryBase const&) const;
0039
0040 typedef edm::AssociationMap<edm::OneToMany<CaloParticleCollection, l1t::HGCalTriggerCellBxCollection>> CaloToCellsMap;
0041
0042 bool makeCellsCollection_;
0043 edm::EDGetTokenT<CaloParticleCollection> caloParticlesToken_;
0044 edm::EDGetTokenT<l1t::HGCalTriggerCellBxCollection> triggerCellsToken_;
0045 edm::EDGetTokenT<std::vector<PCaloHit>> simHitsTokenEE_;
0046 edm::EDGetTokenT<std::vector<PCaloHit>> simHitsTokenHEfront_;
0047 edm::EDGetTokenT<std::vector<PCaloHit>> simHitsTokenHEback_;
0048 edm::ESGetToken<HGCalTriggerGeometryBase, CaloGeometryRecord> triggerGeomToken_;
0049
0050 HGCalClusteringDummyImpl dummyClustering_;
0051 HGCalShowerShape showerShape_;
0052
0053 HGCalTriggerTools triggerTools_;
0054 };
0055
0056 CaloTruthCellsProducer::CaloTruthCellsProducer(edm::ParameterSet const& config)
0057 : makeCellsCollection_(config.getParameter<bool>("makeCellsCollection")),
0058 caloParticlesToken_(consumes<CaloParticleCollection>(config.getParameter<edm::InputTag>("caloParticles"))),
0059 triggerCellsToken_(
0060 consumes<l1t::HGCalTriggerCellBxCollection>(config.getParameter<edm::InputTag>("triggerCells"))),
0061 simHitsTokenEE_(consumes<std::vector<PCaloHit>>(config.getParameter<edm::InputTag>("simHitsEE"))),
0062 simHitsTokenHEfront_(consumes<std::vector<PCaloHit>>(config.getParameter<edm::InputTag>("simHitsHEfront"))),
0063 simHitsTokenHEback_(consumes<std::vector<PCaloHit>>(config.getParameter<edm::InputTag>("simHitsHEback"))),
0064 triggerGeomToken_(esConsumes<HGCalTriggerGeometryBase, CaloGeometryRecord, edm::Transition::BeginRun>()),
0065 dummyClustering_(config.getParameterSet("dummyClustering")) {
0066 produces<CaloToCellsMap>();
0067 produces<l1t::HGCalClusterBxCollection>();
0068 produces<l1t::HGCalMulticlusterBxCollection>();
0069 if (makeCellsCollection_)
0070 produces<l1t::HGCalTriggerCellBxCollection>();
0071 }
0072
0073 CaloTruthCellsProducer::~CaloTruthCellsProducer() {}
0074
0075 void CaloTruthCellsProducer::produce(edm::Event& event, edm::EventSetup const& setup) {
0076 auto caloParticlesHandle = event.getHandle(caloParticlesToken_);
0077 auto const& caloParticles = *caloParticlesHandle;
0078
0079 auto const& triggerCellsHandle = event.getHandle(triggerCellsToken_);
0080 auto const& triggerCells = *triggerCellsHandle;
0081
0082 auto const& geometry = setup.getData(triggerGeomToken_);
0083 ;
0084
0085 dummyClustering_.setGeometry(&geometry);
0086 showerShape_.setGeometry(&geometry);
0087 triggerTools_.setGeometry(&geometry);
0088
0089 std::unordered_map<uint32_t, CaloParticleRef> tcToCalo;
0090
0091 std::unordered_map<uint32_t, double> hitToEnergy(makeHitMap(event, setup, geometry));
0092 std::unordered_map<uint32_t, std::pair<double, double>>
0093 tcToEnergies;
0094
0095 for (auto const& he : hitToEnergy) {
0096 DetId hitId(he.first);
0097
0098 uint32_t tcId(geometry.getTriggerCellFromCell(hitId));
0099 tcToEnergies[tcId].first += he.second;
0100 }
0101
0102
0103 std::map<int, CaloParticleRef> orderedCaloRefs;
0104
0105 for (unsigned iP(0); iP != caloParticles.size(); ++iP) {
0106 auto const& caloParticle(caloParticles.at(iP));
0107 if (caloParticle.g4Tracks().at(0).eventId().event() != 0)
0108 continue;
0109
0110 CaloParticleRef ref(caloParticlesHandle, iP);
0111
0112 SimClusterRefVector const& simClusters(caloParticle.simClusters());
0113 for (auto const& simCluster : simClusters) {
0114 for (auto const& hAndF : simCluster->hits_and_fractions()) {
0115 DetId hitId(hAndF.first);
0116 uint32_t tcId;
0117 try {
0118 tcId = geometry.getTriggerCellFromCell(hitId);
0119 } catch (cms::Exception const& ex) {
0120 edm::LogError("CaloTruthCellsProducer") << ex.what();
0121 continue;
0122 }
0123
0124 tcToCalo.emplace(tcId, ref);
0125 tcToEnergies[tcId].second += hitToEnergy[hAndF.first] * hAndF.second;
0126 }
0127 }
0128
0129
0130 int genIndex(caloParticle.g4Tracks().at(0).genpartIndex() - 1);
0131 orderedCaloRefs[genIndex] = ref;
0132 }
0133
0134 auto outMap(std::make_unique<CaloToCellsMap>(caloParticlesHandle, triggerCellsHandle));
0135 std::unique_ptr<l1t::HGCalTriggerCellBxCollection> outCollection;
0136 if (makeCellsCollection_)
0137 outCollection = std::make_unique<l1t::HGCalTriggerCellBxCollection>();
0138
0139 typedef edm::Ptr<l1t::HGCalTriggerCell> TriggerCellPtr;
0140 typedef edm::Ptr<l1t::HGCalCluster> ClusterPtr;
0141
0142
0143 std::vector<TriggerCellPtr> triggerCellPtrs;
0144
0145
0146 for (int bx(triggerCells.getFirstBX()); bx <= triggerCells.getLastBX(); ++bx) {
0147 for (auto cItr(triggerCells.begin(bx)); cItr != triggerCells.end(bx); ++cItr) {
0148 auto const& cell(*cItr);
0149
0150 auto mapElem(tcToCalo.find(cell.detId()));
0151 if (mapElem == tcToCalo.end())
0152 continue;
0153
0154 outMap->insert(mapElem->second,
0155 edm::Ref<l1t::HGCalTriggerCellBxCollection>(triggerCellsHandle, triggerCells.key(cItr)));
0156
0157 if (makeCellsCollection_) {
0158 auto const& simEnergies(tcToEnergies.at(cell.detId()));
0159 if (simEnergies.first > 0.) {
0160 double eFraction(simEnergies.second / simEnergies.first);
0161
0162 outCollection->push_back(bx, cell);
0163 auto& newCell((*outCollection)[outCollection->size() - 1]);
0164
0165 newCell.setMipPt(cell.mipPt() * eFraction);
0166 newCell.setP4(cell.p4() * eFraction);
0167 }
0168 }
0169
0170 triggerCellPtrs.emplace_back(triggerCellsHandle, triggerCells.key(cItr));
0171 }
0172 }
0173
0174 event.put(std::move(outMap));
0175 if (makeCellsCollection_)
0176 event.put(std::move(outCollection));
0177
0178 auto outClusters(std::make_unique<l1t::HGCalClusterBxCollection>());
0179
0180 auto sortCellPtrs(
0181 [](TriggerCellPtr const& lhs, TriggerCellPtr const& rhs) -> bool { return lhs->mipPt() > rhs->mipPt(); });
0182
0183 std::sort(triggerCellPtrs.begin(), triggerCellPtrs.end(), sortCellPtrs);
0184 dummyClustering_.clusterizeDummy(triggerCellPtrs, *outClusters);
0185
0186 std::unordered_map<unsigned, std::vector<unsigned>> caloToClusterIndices;
0187 for (unsigned iC(0); iC != outClusters->size(); ++iC) {
0188 auto const& cluster((*outClusters)[iC]);
0189
0190 auto caloRef(tcToCalo.at(cluster.detId()));
0191 caloToClusterIndices[caloRef.key()].push_back(iC);
0192 }
0193
0194 auto clustersHandle(event.put(std::move(outClusters)));
0195
0196 auto outMulticlusters(std::make_unique<l1t::HGCalMulticlusterBxCollection>());
0197
0198 for (auto const& ocr : orderedCaloRefs) {
0199 auto const& ref(ocr.second);
0200
0201 if (ref.isNull())
0202 continue;
0203
0204 auto const& caloParticle(*ref);
0205
0206 l1t::HGCalMulticluster multicluster;
0207
0208 for (unsigned iC : caloToClusterIndices[ref.key()]) {
0209 ClusterPtr clPtr(clustersHandle, iC);
0210 multicluster.addConstituent(clPtr, true, 1.);
0211 }
0212
0213
0214 multicluster.setDetId(caloParticle.g4Tracks().at(0).genpartIndex() - 1);
0215
0216 auto const& centre(multicluster.centre());
0217 math::PtEtaPhiMLorentzVector multiclusterP4(multicluster.sumPt(), centre.eta(), centre.phi(), 0.);
0218 multicluster.setP4(multiclusterP4);
0219
0220 showerShape_.fillShapes(multicluster, geometry);
0221
0222
0223
0224
0225 multicluster.saveHOverE();
0226
0227 outMulticlusters->push_back(0, multicluster);
0228 }
0229
0230 event.put(std::move(outMulticlusters));
0231 }
0232
0233 std::unordered_map<uint32_t, double> CaloTruthCellsProducer::makeHitMap(
0234 edm::Event const& event, edm::EventSetup const& setup, HGCalTriggerGeometryBase const& geometry) const {
0235 std::unordered_map<uint32_t, double> hitMap;
0236
0237 typedef std::function<DetId(DetId const&)> DetIdMapper;
0238 typedef std::pair<edm::EDGetTokenT<std::vector<PCaloHit>> const*, DetIdMapper> SimHitSpec;
0239
0240 SimHitSpec specs[3] = {{&simHitsTokenEE_,
0241 [this, &geometry](DetId const& simId) -> DetId {
0242 return this->triggerTools_.simToReco(simId, geometry.eeTopology());
0243 }},
0244 {&simHitsTokenHEfront_,
0245 [this, &geometry](DetId const& simId) -> DetId {
0246 return this->triggerTools_.simToReco(simId, geometry.fhTopology());
0247 }},
0248 {&simHitsTokenHEback_, [this, &geometry](DetId const& simId) -> DetId {
0249 return this->triggerTools_.simToReco(simId, geometry.hscTopology());
0250 }}};
0251
0252 for (auto const& tt : specs) {
0253 edm::Handle<std::vector<PCaloHit>> handle;
0254 event.getByToken(*tt.first, handle);
0255 auto const& simhits(*handle);
0256
0257 for (auto const& simhit : simhits)
0258 hitMap.emplace(tt.second(simhit.id()), simhit.energy());
0259 }
0260
0261 return hitMap;
0262 }
0263
0264 void CaloTruthCellsProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0265
0266
0267 edm::ParameterSetDescription desc;
0268 desc.setUnknown();
0269 descriptions.addDefault(desc);
0270 }
0271
0272 DEFINE_FWK_MODULE(CaloTruthCellsProducer);