File indexing completed on 2024-04-06 12:30:32
0001
0002
0003
0004 #define DEBUG false
0005 #define PRINT_DEBUG true
0006
0007 #if DEBUG
0008 #pragma GCC diagnostic pop
0009 #endif
0010
0011 #include <algorithm>
0012 #include <iterator>
0013 #include <exception>
0014 #include <memory>
0015
0016 #include <numeric> // for std::accumulate
0017 #include <unordered_map>
0018
0019 #include "FWCore/Framework/interface/ConsumesCollector.h"
0020 #include "FWCore/Framework/interface/ESWatcher.h"
0021 #include "FWCore/Framework/interface/Event.h"
0022 #include "FWCore/Framework/interface/EventSetup.h"
0023 #include "FWCore/Framework/interface/ProducesCollector.h"
0024 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0025 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0026 #include "FWCore/Utilities/interface/InputTag.h"
0027
0028 #include "DataFormats/ForwardDetId/interface/BTLDetId.h"
0029 #include "DataFormats/ForwardDetId/interface/ETLDetId.h"
0030 #include "DataFormats/HepMCCandidate/interface/GenParticle.h"
0031 #include "DataFormats/Math/interface/GeantUnits.h"
0032 #include "DataFormats/SiPixelDetId/interface/PixelSubdetector.h"
0033 #include "DataFormats/SiStripDetId/interface/StripSubdetector.h"
0034
0035 #include "SimDataFormats/CaloAnalysis/interface/MtdCaloParticle.h"
0036 #include "SimDataFormats/CaloAnalysis/interface/MtdCaloParticleFwd.h"
0037 #include "SimDataFormats/CaloAnalysis/interface/MtdSimCluster.h"
0038 #include "SimDataFormats/CaloAnalysis/interface/MtdSimClusterFwd.h"
0039 #include "SimDataFormats/CaloAnalysis/interface/MtdSimLayerCluster.h"
0040 #include "SimDataFormats/CaloAnalysis/interface/MtdSimLayerClusterFwd.h"
0041 #include "SimDataFormats/CaloAnalysis/interface/MtdSimTrackster.h"
0042 #include "SimDataFormats/CaloAnalysis/interface/MtdSimTracksterFwd.h"
0043 #include "SimDataFormats/GeneratorProducts/interface/HepMCProduct.h"
0044 #include "SimDataFormats/TrackingHit/interface/PSimHit.h"
0045 #include "SimDataFormats/Vertex/interface/SimVertex.h"
0046
0047 #include "SimGeneral/MixingModule/interface/DecayGraph.h"
0048 #include "SimGeneral/MixingModule/interface/DigiAccumulatorMixMod.h"
0049 #include "SimGeneral/MixingModule/interface/DigiAccumulatorMixModFactory.h"
0050 #include "SimGeneral/MixingModule/interface/PileUpEventPrincipal.h"
0051 #include "SimGeneral/TrackingAnalysis/interface/EncodedTruthId.h"
0052
0053 #include "Geometry/MTDCommonData/interface/MTDTopologyMode.h"
0054 #include "Geometry/Records/interface/MTDDigiGeometryRecord.h"
0055 #include "Geometry/MTDGeometryBuilder/interface/MTDGeometry.h"
0056 #include "Geometry/MTDGeometryBuilder/interface/MTDGeomUtil.h"
0057 #include "Geometry/MTDNumberingBuilder/interface/MTDTopology.h"
0058 #include "Geometry/MTDGeometryBuilder/interface/ProxyMTDTopology.h"
0059 #include "Geometry/MTDGeometryBuilder/interface/RectangularMTDTopology.h"
0060
0061 namespace {
0062 using Index_t = unsigned;
0063 using Barcode_t = int;
0064 const std::string messageCategoryGraph_("MtdTruthAccumulatorGraphProducer");
0065 }
0066
0067 class MtdTruthAccumulator : public DigiAccumulatorMixMod {
0068 public:
0069 explicit MtdTruthAccumulator(const edm::ParameterSet &config, edm::ProducesCollector, edm::ConsumesCollector &iC);
0070
0071 private:
0072 void initializeEvent(const edm::Event &event, const edm::EventSetup &setup) override;
0073 void accumulate(const edm::Event &event, const edm::EventSetup &setup) override;
0074 void accumulate(const PileUpEventPrincipal &event, const edm::EventSetup &setup, edm::StreamID const &) override;
0075 void finalizeEvent(edm::Event &event, const edm::EventSetup &setup) override;
0076
0077
0078 template <class T>
0079 void accumulateEvent(const T &event,
0080 const edm::EventSetup &setup,
0081 const edm::Handle<edm::HepMCProduct> &hepMCproduct);
0082
0083
0084
0085 template <class T>
0086 void fillSimHits(std::vector<std::pair<uint64_t, const PSimHit *>> &returnValue,
0087 std::unordered_map<int, std::map<uint64_t, std::tuple<float, float, LocalPoint>>> &simTrackDetIdMap,
0088 const T &event,
0089 const edm::EventSetup &setup);
0090
0091 const std::string messageCategory_;
0092
0093 std::unordered_map<uint64_t, float> m_detIdToTotalSimEnergy;
0094 std::unordered_multimap<Barcode_t, Index_t> m_simHitBarcodeToIndex;
0095
0096
0097
0098
0099
0100
0101 const unsigned int maximumPreviousBunchCrossing_;
0102
0103
0104
0105
0106
0107 const unsigned int maximumSubsequentBunchCrossing_;
0108
0109 const unsigned int bunchSpacing_;
0110
0111 const edm::InputTag simTrackLabel_;
0112 const edm::InputTag simVertexLabel_;
0113 edm::Handle<std::vector<SimTrack>> hSimTracks;
0114 edm::Handle<std::vector<SimVertex>> hSimVertices;
0115
0116 std::vector<edm::InputTag> collectionTags_;
0117 edm::InputTag genParticleLabel_;
0118
0119 edm::InputTag hepMCproductLabel_;
0120 const edm::ESGetToken<MTDGeometry, MTDDigiGeometryRecord> geomToken_;
0121 const edm::ESGetToken<MTDTopology, MTDTopologyRcd> mtdtopoToken_;
0122
0123
0124 mtd::MTDGeomUtil geomTools_;
0125
0126 const double minEnergy_, maxPseudoRapidity_;
0127 const bool premixStage1_;
0128
0129 bool isEtl_;
0130
0131 public:
0132 struct OutputCollections {
0133 std::unique_ptr<MtdSimClusterCollection> pSimClusters;
0134 std::unique_ptr<MtdCaloParticleCollection> pCaloParticles;
0135 std::unique_ptr<MtdSimLayerClusterCollection> pMtdSimLayerClusters;
0136 std::unique_ptr<MtdSimTracksterCollection> pMtdSimTracksters;
0137 };
0138
0139 struct calo_particles {
0140 std::vector<uint32_t> sc_start_;
0141 std::vector<uint32_t> sc_stop_;
0142
0143 void swap(calo_particles &oth) {
0144 sc_start_.swap(oth.sc_start_);
0145 sc_stop_.swap(oth.sc_stop_);
0146 }
0147
0148 void clear() {
0149 sc_start_.clear();
0150 sc_stop_.clear();
0151 }
0152 };
0153
0154 private:
0155 const MTDGeometry *geom = nullptr;
0156 const MTDTopology *topology = nullptr;
0157 OutputCollections output_;
0158 calo_particles m_caloParticles;
0159 };
0160
0161
0162
0163 namespace {
0164 class CaloParticle_dfs_visitor : public boost::default_dfs_visitor {
0165 public:
0166 CaloParticle_dfs_visitor(
0167 MtdTruthAccumulator::OutputCollections &output,
0168 MtdTruthAccumulator::calo_particles &caloParticles,
0169 std::unordered_multimap<Barcode_t, Index_t> &simHitBarcodeToIndex,
0170 std::unordered_map<int, std::map<uint64_t, std::tuple<float, float, LocalPoint>>> &simTrackDetIdMap,
0171 std::unordered_map<uint32_t, float> &vertex_time_map,
0172 Selector selector)
0173 : output_(output),
0174 caloParticles_(caloParticles),
0175 simHitBarcodeToIndex_(simHitBarcodeToIndex),
0176 simTrackDetIdMap_(simTrackDetIdMap),
0177 vertex_time_map_(vertex_time_map),
0178 selector_(selector) {}
0179 template <typename Vertex, typename Graph>
0180 void discover_vertex(Vertex u, const Graph &g) {
0181
0182
0183
0184 print_vertex(u, g);
0185 auto const vertex_property = get(vertex_name, g, u);
0186 if (!vertex_property.simTrack)
0187 return;
0188
0189 for (unsigned int offset = 0; offset < 4; offset++) {
0190 auto trackIdx = vertex_property.simTrack->trackId();
0191 trackIdx += offset * (static_cast<int>(PSimHit::k_tidOffset));
0192 IfLogDebug(DEBUG, messageCategoryGraph_)
0193 << " Found " << simHitBarcodeToIndex_.count(trackIdx) << " associated simHits" << std::endl;
0194 if (simHitBarcodeToIndex_.count(trackIdx)) {
0195 output_.pSimClusters->emplace_back(*vertex_property.simTrack);
0196 auto &simcluster = output_.pSimClusters->back();
0197 std::unordered_map<uint64_t, float> acc_energy;
0198 for (auto const &hit_and_energy : simTrackDetIdMap_[trackIdx]) {
0199 acc_energy[hit_and_energy.first] += std::get<0>(hit_and_energy.second);
0200 }
0201 for (auto const &hit_and_energy : acc_energy) {
0202 simcluster.addHitAndFraction(hit_and_energy.first, hit_and_energy.second);
0203 simcluster.addHitEnergy(hit_and_energy.second);
0204 simcluster.addHitTime(std::get<1>(
0205 simTrackDetIdMap_[simcluster.g4Tracks()[0].trackId() +
0206 offset * (static_cast<int>(PSimHit::k_tidOffset))][hit_and_energy.first]));
0207 simcluster.addHitPosition(std::get<2>(
0208 simTrackDetIdMap_[simcluster.g4Tracks()[0].trackId() +
0209 offset * (static_cast<int>(PSimHit::k_tidOffset))][hit_and_energy.first]));
0210 simcluster.setTrackIdOffset(offset);
0211 }
0212 }
0213 }
0214 }
0215
0216 template <typename Edge, typename Graph>
0217 void examine_edge(Edge e, const Graph &g) {
0218 auto src = source(e, g);
0219 auto vertex_property = get(vertex_name, g, src);
0220 if (src == 0 or (vertex_property.simTrack == nullptr)) {
0221 auto edge_property = get(edge_weight, g, e);
0222 IfLogDebug(DEBUG, messageCategoryGraph_) << "Considering CaloParticle: " << edge_property.simTrack->trackId();
0223 if (selector_(edge_property)) {
0224 IfLogDebug(DEBUG, messageCategoryGraph_) << "Adding CaloParticle: " << edge_property.simTrack->trackId();
0225 output_.pCaloParticles->emplace_back(*(edge_property.simTrack));
0226 output_.pCaloParticles->back().addSimTime(vertex_time_map_[(edge_property.simTrack)->vertIndex()]);
0227 caloParticles_.sc_start_.push_back(output_.pSimClusters->size());
0228 }
0229 }
0230 }
0231
0232 template <typename Edge, typename Graph>
0233 void finish_edge(Edge e, const Graph &g) {
0234 auto src = source(e, g);
0235 auto vertex_property = get(vertex_name, g, src);
0236 if (src == 0 or (vertex_property.simTrack == nullptr)) {
0237 auto edge_property = get(edge_weight, g, e);
0238 if (selector_(edge_property)) {
0239 caloParticles_.sc_stop_.push_back(output_.pSimClusters->size());
0240 }
0241 }
0242 }
0243
0244 private:
0245 MtdTruthAccumulator::OutputCollections &output_;
0246 MtdTruthAccumulator::calo_particles &caloParticles_;
0247 std::unordered_multimap<Barcode_t, Index_t> &simHitBarcodeToIndex_;
0248 std::unordered_map<int, std::map<uint64_t, std::tuple<float, float, LocalPoint>>> &simTrackDetIdMap_;
0249 std::unordered_map<uint32_t, float> &vertex_time_map_;
0250 Selector selector_;
0251 };
0252 }
0253
0254 MtdTruthAccumulator::MtdTruthAccumulator(const edm::ParameterSet &config,
0255 edm::ProducesCollector producesCollector,
0256 edm::ConsumesCollector &iC)
0257 : messageCategory_("MtdTruthAccumulator"),
0258 maximumPreviousBunchCrossing_(config.getParameter<unsigned int>("maximumPreviousBunchCrossing")),
0259 maximumSubsequentBunchCrossing_(config.getParameter<unsigned int>("maximumSubsequentBunchCrossing")),
0260 bunchSpacing_(config.getParameter<unsigned int>("bunchspace")),
0261 simTrackLabel_(config.getParameter<edm::InputTag>("simTrackCollection")),
0262 simVertexLabel_(config.getParameter<edm::InputTag>("simVertexCollection")),
0263 collectionTags_(),
0264 genParticleLabel_(config.getParameter<edm::InputTag>("genParticleCollection")),
0265 hepMCproductLabel_(config.getParameter<edm::InputTag>("HepMCProductLabel")),
0266 geomToken_(iC.esConsumes<MTDGeometry, MTDDigiGeometryRecord>()),
0267 mtdtopoToken_(iC.esConsumes<MTDTopology, MTDTopologyRcd>()),
0268 minEnergy_(config.getParameter<double>("MinEnergy")),
0269 maxPseudoRapidity_(config.getParameter<double>("MaxPseudoRapidity")),
0270 premixStage1_(config.getParameter<bool>("premixStage1")) {
0271 iC.consumes<std::vector<SimTrack>>(simTrackLabel_);
0272 iC.consumes<std::vector<SimVertex>>(simVertexLabel_);
0273 iC.consumes<std::vector<reco::GenParticle>>(genParticleLabel_);
0274 iC.consumes<std::vector<int>>(genParticleLabel_);
0275 iC.consumes<std::vector<int>>(hepMCproductLabel_);
0276
0277
0278 const edm::ParameterSet &simHitCollectionConfig = config.getParameterSet("simHitCollections");
0279 std::vector<std::string> parameterNames = simHitCollectionConfig.getParameterNames();
0280
0281 for (auto const ¶meterName : parameterNames) {
0282 std::vector<edm::InputTag> tags = simHitCollectionConfig.getParameter<std::vector<edm::InputTag>>(parameterName);
0283 collectionTags_.insert(collectionTags_.end(), tags.begin(), tags.end());
0284 }
0285
0286 for (auto const &collectionTag : collectionTags_) {
0287 iC.consumes<std::vector<PSimHit>>(collectionTag);
0288 isEtl_ = (collectionTag.instance().find("FastTimerHitsEndcap") != std::string::npos);
0289 }
0290
0291 producesCollector.produces<MtdSimClusterCollection>("MergedMtdTruth");
0292 producesCollector.produces<MtdSimLayerClusterCollection>("MergedMtdTruthLC");
0293 producesCollector.produces<MtdSimTracksterCollection>("MergedMtdTruthST");
0294 producesCollector.produces<MtdCaloParticleCollection>("MergedMtdTruth");
0295 if (premixStage1_) {
0296 producesCollector.produces<std::vector<std::pair<uint64_t, float>>>("MergedMtdTruth");
0297 }
0298 }
0299
0300 void MtdTruthAccumulator::initializeEvent(edm::Event const &event, edm::EventSetup const &setup) {
0301 output_.pSimClusters = std::make_unique<MtdSimClusterCollection>();
0302 output_.pCaloParticles = std::make_unique<MtdCaloParticleCollection>();
0303
0304 output_.pMtdSimLayerClusters = std::make_unique<MtdSimLayerClusterCollection>();
0305 output_.pMtdSimTracksters = std::make_unique<MtdSimTracksterCollection>();
0306
0307 m_detIdToTotalSimEnergy.clear();
0308
0309 auto geometryHandle = setup.getTransientHandle(geomToken_);
0310 geom = geometryHandle.product();
0311
0312 auto topologyHandle = setup.getTransientHandle(mtdtopoToken_);
0313 topology = topologyHandle.product();
0314
0315 geomTools_.setGeometry(geom);
0316 geomTools_.setTopology(topology);
0317 }
0318
0319
0320
0321
0322
0323
0324
0325
0326 void MtdTruthAccumulator::accumulate(edm::Event const &event, edm::EventSetup const &setup) {
0327 edm::Handle<edm::HepMCProduct> hepmc;
0328 event.getByLabel(hepMCproductLabel_, hepmc);
0329
0330 edm::LogInfo(messageCategory_) << " MtdTruthAccumulator::accumulate (signal)";
0331 accumulateEvent(event, setup, hepmc);
0332 }
0333
0334 void MtdTruthAccumulator::accumulate(PileUpEventPrincipal const &event,
0335 edm::EventSetup const &setup,
0336 edm::StreamID const &) {
0337 if (event.bunchCrossing() >= -static_cast<int>(maximumPreviousBunchCrossing_) &&
0338 event.bunchCrossing() <= static_cast<int>(maximumSubsequentBunchCrossing_)) {
0339
0340 edm::Handle<edm::HepMCProduct> hepmc;
0341 edm::LogInfo(messageCategory_) << " MtdTruthAccumulator::accumulate (pileup) bunchCrossing="
0342 << event.bunchCrossing();
0343 accumulateEvent(event, setup, hepmc);
0344 } else {
0345 edm::LogInfo(messageCategory_) << "Skipping pileup event for bunch crossing " << event.bunchCrossing();
0346 }
0347 }
0348
0349 void MtdTruthAccumulator::finalizeEvent(edm::Event &event, edm::EventSetup const &setup) {
0350 using namespace geant_units::operators;
0351
0352 edm::LogInfo(messageCategory_) << "Adding " << output_.pSimClusters->size() << " SimParticles and "
0353 << output_.pCaloParticles->size() << " CaloParticles to the event.";
0354
0355
0356
0357
0358
0359
0360 if (premixStage1_) {
0361 auto totalEnergies = std::make_unique<std::vector<std::pair<uint64_t, float>>>();
0362 totalEnergies->reserve(m_detIdToTotalSimEnergy.size());
0363 std::copy(m_detIdToTotalSimEnergy.begin(), m_detIdToTotalSimEnergy.end(), std::back_inserter(*totalEnergies));
0364 std::sort(totalEnergies->begin(), totalEnergies->end());
0365 event.put(std::move(totalEnergies), "MergedMtdTruth");
0366 } else {
0367 for (auto &sc : *(output_.pSimClusters)) {
0368 auto hitsAndEnergies = sc.hits_and_fractions();
0369 sc.clearHitsAndFractions();
0370 sc.clearHitsEnergy();
0371 for (auto &hAndE : hitsAndEnergies) {
0372 const float totalenergy = m_detIdToTotalSimEnergy[hAndE.first];
0373 float fraction = 0.;
0374 if (totalenergy > 0)
0375 fraction = hAndE.second / totalenergy;
0376 else
0377 edm::LogWarning(messageCategory_)
0378 << "TotalSimEnergy for hit " << hAndE.first << " is 0! The fraction for this hit cannot be computed.";
0379 sc.addHitAndFraction(hAndE.first, fraction);
0380 sc.addHitEnergy(hAndE.second);
0381 }
0382 }
0383 }
0384
0385 #ifdef PRINT_DEBUG
0386 IfLogDebug(DEBUG, messageCategory_) << "SIMCLUSTERS LIST:" << std::endl;
0387 for (const auto &sc : *(output_.pSimClusters)) {
0388 IfLogDebug(DEBUG, messageCategory_) << std::fixed << std::setprecision(3) << "SimCluster from CP with:"
0389 << "\n charge " << sc.charge() << "\n pdgId " << sc.pdgId() << "\n energy "
0390 << sc.energy() << " GeV\n eta " << sc.eta() << "\n phi " << sc.phi()
0391 << "\n number of cells = " << sc.hits_and_fractions().size() << std::endl;
0392 for (unsigned int i = 0; i < sc.hits_and_fractions().size(); ++i) {
0393 DetId id(sc.detIds_and_rows()[i].first);
0394 IfLogDebug(DEBUG, messageCategory_)
0395 << std::fixed << std::setprecision(3) << " hit " << id.rawId() << " on layer " << geomTools_.layer(id)
0396 << " module " << geomTools_.module(id) << " row " << (unsigned int)(sc.detIds_and_rows()[i].second).first
0397 << " col " << (unsigned int)(sc.detIds_and_rows()[i].second).second << " at time "
0398 << sc.hits_and_times()[i].second << " ns" << std::endl;
0399 }
0400 IfLogDebug(DEBUG, messageCategory_) << "--------------\n";
0401 }
0402 IfLogDebug(DEBUG, messageCategory_) << std::endl;
0403 #endif
0404
0405
0406 auto scHandle = event.put(std::move(output_.pSimClusters), "MergedMtdTruth");
0407
0408
0409 output_.pMtdSimLayerClusters->reserve(scHandle->size());
0410 output_.pMtdSimTracksters->reserve(scHandle->size());
0411
0412 uint32_t SC_index = 0;
0413 uint32_t LC_index = 0;
0414 for (const auto &sc : *scHandle) {
0415 auto const &hAndF = sc.hits_and_fractions();
0416 auto const &hAndE = sc.hits_and_energies();
0417 auto const &hAndT = sc.hits_and_times();
0418 auto const &hAndP = sc.hits_and_positions();
0419 auto const &hAndR = sc.detIds_and_rows();
0420
0421 std::vector<int> indices(hAndF.size());
0422 std::iota(indices.begin(), indices.end(), 0);
0423
0424 std::sort(indices.begin(), indices.end(), [&](int a, int b) { return hAndF[a].first < hAndF[b].first; });
0425
0426
0427
0428
0429
0430 std::vector<uint32_t> LC_indices;
0431 MtdSimLayerCluster tmpLC(sc.g4Tracks()[0]);
0432 int prev = indices[0];
0433 DetId prevId(hAndR[prev].first);
0434
0435 float SimLCenergy = 0.;
0436 float SimLCx = 0., SimLCy = 0., SimLCz = 0.;
0437
0438 auto push_back_hit = [&](const int &ind) {
0439 tmpLC.addHitAndFraction(hAndF[ind].first, hAndF[ind].second);
0440 tmpLC.addHitEnergy(hAndE[ind].second);
0441 tmpLC.addHitTime(hAndT[ind].second);
0442 tmpLC.addHitPosition(hAndP[ind].second);
0443 };
0444
0445 auto update_clu_info = [&](const int &ind) {
0446 double energy = hAndE[ind].second;
0447 auto position = hAndP[ind].second;
0448 if (geomTools_.isBTL((DetId)hAndR[ind].first)) {
0449 BTLDetId detId{(DetId)hAndR[ind].first};
0450 DetId geoId = detId.geographicalId(MTDTopologyMode::crysLayoutFromTopoMode(topology->getMTDTopologyMode()));
0451 const MTDGeomDet *thedet = geom->idToDet(geoId);
0452 const ProxyMTDTopology &topoproxy = static_cast<const ProxyMTDTopology &>(thedet->topology());
0453 const RectangularMTDTopology &topo = static_cast<const RectangularMTDTopology &>(topoproxy.specificTopology());
0454 position =
0455 topo.pixelToModuleLocalPoint(hAndP[ind].second, (hAndR[ind].second).first, (hAndR[ind].second).second);
0456 }
0457 SimLCenergy += energy;
0458 SimLCx += position.x() * energy;
0459 SimLCy += position.y() * energy;
0460 SimLCz += position.z() * energy;
0461 };
0462
0463 auto push_back_clu = [&](const uint32_t &SC_index, uint32_t &LC_index) {
0464 tmpLC.addCluEnergy(SimLCenergy);
0465 LocalPoint SimLCpos(SimLCx / SimLCenergy, SimLCy / SimLCenergy, SimLCz / SimLCenergy);
0466 tmpLC.addCluLocalPos(SimLCpos);
0467 SimLCenergy = 0.;
0468 SimLCx = 0.;
0469 SimLCy = 0.;
0470 SimLCz = 0.;
0471 tmpLC.addCluIndex(SC_index);
0472 tmpLC.computeClusterTime();
0473 tmpLC.setTrackIdOffset(sc.trackIdOffset());
0474 output_.pMtdSimLayerClusters->push_back(tmpLC);
0475 LC_indices.push_back(LC_index);
0476 LC_index++;
0477 tmpLC.clear();
0478 };
0479
0480
0481 push_back_hit(prev);
0482 update_clu_info(prev);
0483 for (const auto &ind : indices) {
0484 if (ind == indices[0])
0485 continue;
0486 DetId id(hAndR[ind].first);
0487 if (geomTools_.isETL(id) != geomTools_.isETL(prevId) or geomTools_.layer(id) != geomTools_.layer(prevId) or
0488 geomTools_.module(id) != geomTools_.module(prevId) or
0489 ((hAndR[ind].second).first == (hAndR[prev].second).first and
0490 (hAndR[ind].second).second != (hAndR[prev].second).second + 1) or
0491 ((hAndR[ind].second).second == (hAndR[prev].second).second and
0492 (hAndR[ind].second).first != (hAndR[prev].second).first + 1)) {
0493
0494
0495 push_back_clu(SC_index, LC_index);
0496 }
0497
0498 push_back_hit(ind);
0499 update_clu_info(ind);
0500 prev = ind;
0501 DetId newId(hAndR[prev].first);
0502 prevId = newId;
0503 }
0504
0505 push_back_clu(SC_index, LC_index);
0506
0507
0508
0509
0510 float timeAtEntrance = 99.;
0511 uint32_t idAtEntrance = 0;
0512 for (uint32_t i = 0; i < (uint32_t)hAndT.size(); i++) {
0513 if (hAndT[i].second < timeAtEntrance) {
0514 timeAtEntrance = hAndT[i].second;
0515 idAtEntrance = i;
0516 }
0517 }
0518
0519
0520 auto &MtdSimLayerClusters = output_.pMtdSimLayerClusters;
0521 std::sort(LC_indices.begin(), LC_indices.end(), [&MtdSimLayerClusters](int i, int j) {
0522 return (*MtdSimLayerClusters)[i].simLCTime() < (*MtdSimLayerClusters)[j].simLCTime();
0523 });
0524
0525 GlobalPoint posAtEntrance = geomTools_
0526 .position((DetId)hAndR[idAtEntrance].first,
0527 (hAndR[idAtEntrance].second).first,
0528 (hAndR[idAtEntrance].second).second)
0529 .second;
0530 output_.pMtdSimTracksters->emplace_back(sc, LC_indices, timeAtEntrance, posAtEntrance);
0531 SC_index++;
0532 }
0533
0534 #ifdef PRINT_DEBUG
0535 IfLogDebug(DEBUG, messageCategory_) << "SIMLAYERCLUSTERS LIST: \n";
0536 for (auto &sc : *output_.pMtdSimLayerClusters) {
0537 IfLogDebug(DEBUG, messageCategory_) << std::fixed << std::setprecision(3) << "SimLayerCluster with:"
0538 << "\n CP charge " << sc.charge() << "\n CP pdgId " << sc.pdgId()
0539 << "\n CP energy " << sc.energy() << " GeV\n CP eta " << sc.eta()
0540 << "\n CP phi " << sc.phi()
0541 << "\n number of cells = " << sc.hits_and_fractions().size() << std::endl;
0542 for (unsigned int i = 0; i < sc.hits_and_fractions().size(); ++i) {
0543 DetId id(sc.detIds_and_rows()[i].first);
0544 IfLogDebug(DEBUG, messageCategory_)
0545 << std::fixed << std::setprecision(3) << " hit " << sc.detIds_and_rows()[i].first << " on layer "
0546 << geomTools_.layer(id) << " at time " << sc.hits_and_times()[i].second << " ns" << std::endl;
0547 }
0548 IfLogDebug(DEBUG, messageCategory_) << std::fixed << std::setprecision(3) << " Cluster time " << sc.simLCTime()
0549 << " ns \n Cluster pos" << sc.simLCPos() << " cm\n"
0550 << std::fixed << std::setprecision(6) << " Cluster energy "
0551 << convertUnitsTo(0.001_MeV, sc.simLCEnergy()) << " MeV" << std::endl;
0552 IfLogDebug(DEBUG, messageCategory_) << "--------------\n";
0553 }
0554 IfLogDebug(DEBUG, messageCategory_) << std::endl;
0555
0556 IfLogDebug(DEBUG, messageCategory_) << "SIMTRACKSTERS LIST: \n";
0557 for (auto &sc : *output_.pMtdSimTracksters) {
0558 IfLogDebug(DEBUG, messageCategory_) << std::fixed << std::setprecision(3) << "SimTrackster with:"
0559 << "\n CP charge " << sc.charge() << "\n CP pdgId " << sc.pdgId()
0560 << "\n CP energy " << sc.energy() << " GeV\n CP eta " << sc.eta()
0561 << "\n CP phi " << sc.phi()
0562 << "\n number of layer clusters = " << sc.numberOfClusters()
0563 << "\n time of first simhit " << sc.time() << " ns\n position of first simhit"
0564 << sc.position() << "cm" << std::endl;
0565 IfLogDebug(DEBUG, messageCategory_) << " LCs indices: ";
0566 for (const auto &lc : sc.clusters())
0567 IfLogDebug(DEBUG, messageCategory_) << lc << ", ";
0568 IfLogDebug(DEBUG, messageCategory_) << "\n--------------\n";
0569 }
0570 IfLogDebug(DEBUG, messageCategory_) << std::endl;
0571 #endif
0572
0573 event.put(std::move(output_.pMtdSimLayerClusters), "MergedMtdTruthLC");
0574 event.put(std::move(output_.pMtdSimTracksters), "MergedMtdTruthST");
0575
0576
0577 for (unsigned i = 0; i < output_.pCaloParticles->size(); ++i) {
0578 auto &cp = (*output_.pCaloParticles)[i];
0579 for (unsigned j = m_caloParticles.sc_start_[i]; j < m_caloParticles.sc_stop_[i]; ++j) {
0580 edm::Ref<MtdSimClusterCollection> ref(scHandle, j);
0581 cp.addSimCluster(ref);
0582 }
0583 }
0584 event.put(std::move(output_.pCaloParticles), "MergedMtdTruth");
0585
0586 calo_particles().swap(m_caloParticles);
0587
0588 std::unordered_map<uint64_t, float>().swap(m_detIdToTotalSimEnergy);
0589 std::unordered_multimap<Barcode_t, Index_t>().swap(m_simHitBarcodeToIndex);
0590 }
0591
0592 template <class T>
0593 void MtdTruthAccumulator::accumulateEvent(const T &event,
0594 const edm::EventSetup &setup,
0595 const edm::Handle<edm::HepMCProduct> &hepMCproduct) {
0596 edm::Handle<std::vector<reco::GenParticle>> hGenParticles;
0597 edm::Handle<std::vector<int>> hGenParticleIndices;
0598
0599 event.getByLabel(simTrackLabel_, hSimTracks);
0600 event.getByLabel(simVertexLabel_, hSimVertices);
0601
0602 event.getByLabel(genParticleLabel_, hGenParticles);
0603 event.getByLabel(genParticleLabel_, hGenParticleIndices);
0604
0605 std::vector<std::pair<uint64_t, const PSimHit *>> simHitPointers;
0606 std::unordered_map<int, std::map<uint64_t, std::tuple<float, float, LocalPoint>>> simTrackDetIdMap;
0607 fillSimHits(simHitPointers, simTrackDetIdMap, event, setup);
0608
0609
0610 m_simHitBarcodeToIndex.clear();
0611 for (unsigned int i = 0; i < simHitPointers.size(); ++i) {
0612 m_simHitBarcodeToIndex.emplace(simHitPointers[i].second->trackId(), i);
0613 }
0614
0615 auto const &tracks = *hSimTracks;
0616 auto const &vertices = *hSimVertices;
0617 std::unordered_map<int, int> trackid_to_track_index;
0618 std::unordered_map<uint32_t, float> vertex_time_map;
0619 DecayChain decay;
0620
0621 for (uint32_t i = 0; i < vertices.size(); i++) {
0622 vertex_time_map[i] = vertices[i].position().t() * 1e9 + event.bunchCrossing() * static_cast<int>(bunchSpacing_);
0623 }
0624
0625 IfLogDebug(DEBUG, messageCategory_) << " TRACKS" << std::endl;
0626 int idx = 0;
0627 for (auto const &t : tracks) {
0628 IfLogDebug(DEBUG, messageCategory_) << " " << idx << "\t" << t.trackId() << "\t" << t << std::endl;
0629 trackid_to_track_index[t.trackId()] = idx;
0630 idx++;
0631 }
0632
0633
0634
0635
0636
0637
0638
0639
0640
0641
0642
0643
0644
0645
0646
0647
0648
0649
0650
0651
0652
0653
0654
0655
0656
0657
0658
0659 idx = 0;
0660 std::vector<int> used_sim_tracks(tracks.size(), 0);
0661 std::vector<int> collapsed_vertices(vertices.size(), 0);
0662 IfLogDebug(DEBUG, messageCategory_) << " VERTICES" << std::endl;
0663 for (auto const &v : vertices) {
0664 IfLogDebug(DEBUG, messageCategory_) << " " << idx++ << "\t" << v << std::endl;
0665 if (v.parentIndex() != -1) {
0666 auto const trk_idx = trackid_to_track_index[v.parentIndex()];
0667 auto origin_vtx = tracks[trk_idx].vertIndex();
0668 if (used_sim_tracks[trk_idx]) {
0669
0670
0671
0672 collapsed_vertices[v.vertexId()] = used_sim_tracks[trk_idx];
0673 continue;
0674 }
0675
0676 if (collapsed_vertices[origin_vtx])
0677 origin_vtx = collapsed_vertices[origin_vtx];
0678 add_edge(
0679 origin_vtx, v.vertexId(), EdgeProperty(&tracks[trk_idx], simTrackDetIdMap[v.parentIndex()].size(), 0), decay);
0680 used_sim_tracks[trk_idx] = v.vertexId();
0681 }
0682 }
0683
0684 auto const &vertexMothersProp = get(vertex_name, decay);
0685
0686
0687 int offset = vertices.size();
0688 for (size_t i = 0; i < tracks.size(); ++i) {
0689 if (!used_sim_tracks[i]) {
0690 auto origin_vtx = tracks[i].vertIndex();
0691
0692 if (collapsed_vertices[origin_vtx])
0693 origin_vtx = collapsed_vertices[origin_vtx];
0694 add_edge(origin_vtx, offset, EdgeProperty(&tracks[i], simTrackDetIdMap[tracks[i].trackId()].size(), 0), decay);
0695
0696
0697
0698 put(vertexMothersProp, offset, VertexProperty(&tracks[i], 0));
0699 offset++;
0700 }
0701 }
0702 for (auto const &v : vertices) {
0703 if (v.parentIndex() != -1) {
0704
0705 if (collapsed_vertices[v.vertexId()])
0706 continue;
0707 put(vertexMothersProp, v.vertexId(), VertexProperty(&tracks[trackid_to_track_index[v.parentIndex()]], 0));
0708 }
0709 }
0710 SimHitsAccumulator_dfs_visitor vis;
0711 depth_first_search(decay, visitor(vis));
0712 CaloParticle_dfs_visitor caloParticleCreator(
0713 output_,
0714 m_caloParticles,
0715 m_simHitBarcodeToIndex,
0716 simTrackDetIdMap,
0717 vertex_time_map,
0718 [&](EdgeProperty &edge_property) -> bool {
0719
0720
0721
0722
0723 return (edge_property.cumulative_simHits != 0 and !edge_property.simTrack->noGenpart() and
0724 edge_property.simTrack->momentum().E() > minEnergy_ and
0725 std::abs(edge_property.simTrack->momentum().Eta()) < maxPseudoRapidity_);
0726 });
0727 depth_first_search(decay, visitor(caloParticleCreator));
0728
0729 #if DEBUG
0730 boost::write_graphviz(std::cout,
0731 decay,
0732 make_label_writer(make_transform_value_property_map(&graphviz_vertex, get(vertex_name, decay))),
0733 make_label_writer(make_transform_value_property_map(&graphviz_edge, get(edge_weight, decay))));
0734 #endif
0735 }
0736
0737 template <class T>
0738 void MtdTruthAccumulator::fillSimHits(
0739 std::vector<std::pair<uint64_t, const PSimHit *>> &returnValue,
0740 std::unordered_map<int, std::map<uint64_t, std::tuple<float, float, LocalPoint>>> &simTrackDetIdMap,
0741 const T &event,
0742 const edm::EventSetup &setup) {
0743 using namespace geant_units::operators;
0744 using namespace angle_units::operators;
0745 for (auto const &collectionTag : collectionTags_) {
0746 edm::Handle<std::vector<PSimHit>> hSimHits;
0747 event.getByLabel(collectionTag, hSimHits);
0748
0749 for (auto const &simHit : *hSimHits) {
0750 DetId id(0);
0751
0752
0753 if (simHit.tof() < 0 || simHit.tof() > 25.)
0754 continue;
0755
0756 id = simHit.detUnitId();
0757
0758 if (id == DetId(0)) {
0759 edm::LogWarning(messageCategory_) << "Invalid DetId for the current simHit!";
0760 continue;
0761 }
0762
0763 if (simHit.trackId() == 0) {
0764 continue;
0765 }
0766
0767 returnValue.emplace_back(id, &simHit);
0768
0769
0770
0771
0772 const auto &position = simHit.localPosition();
0773
0774 LocalPoint simscaled(convertMmToCm(position.x()), convertMmToCm(position.y()), convertMmToCm(position.z()));
0775 std::pair<uint8_t, uint8_t> pixel = geomTools_.pixelInModule(id, simscaled);
0776
0777 uint64_t uniqueId = static_cast<uint64_t>(id.rawId()) << 32;
0778 uniqueId |= pixel.first << 16;
0779 uniqueId |= pixel.second;
0780
0781 std::get<0>(simTrackDetIdMap[simHit.trackId()][uniqueId]) += simHit.energyLoss();
0782 m_detIdToTotalSimEnergy[uniqueId] += simHit.energyLoss();
0783
0784 if (std::get<1>(simTrackDetIdMap[simHit.trackId()][uniqueId]) == 0. ||
0785 simHit.tof() < std::get<1>(simTrackDetIdMap[simHit.trackId()][uniqueId])) {
0786 std::get<1>(simTrackDetIdMap[simHit.trackId()][uniqueId]) = simHit.tof();
0787 }
0788
0789 float xSim = std::get<2>(simTrackDetIdMap[simHit.trackId()][uniqueId]).x() + simscaled.x() * simHit.energyLoss();
0790 float ySim = std::get<2>(simTrackDetIdMap[simHit.trackId()][uniqueId]).y() + simscaled.y() * simHit.energyLoss();
0791 float zSim = std::get<2>(simTrackDetIdMap[simHit.trackId()][uniqueId]).z() + simscaled.z() * simHit.energyLoss();
0792 LocalPoint posSim(xSim, ySim, zSim);
0793 std::get<2>(simTrackDetIdMap[simHit.trackId()][uniqueId]) = posSim;
0794
0795 #ifdef PRINT_DEBUG
0796 IfLogDebug(DEBUG, messageCategory_)
0797 << "hitId " << id.rawId() << " from track " << simHit.trackId() << " in layer " << geomTools_.layer(id)
0798 << ", module " << geomTools_.module(id) << ", pixel ( " << (int)geomTools_.pixelInModule(id, simscaled).first
0799 << ", " << (int)geomTools_.pixelInModule(id, simscaled).second << " )\n global pos(cm) "
0800 << geomTools_.globalPosition(id, simscaled) << ", time(ns) " << simHit.tof() << ", energy(MeV) "
0801 << convertUnitsTo(0.001_MeV, simHit.energyLoss()) << std::endl;
0802 #endif
0803 }
0804
0805 }
0806
0807 for (auto &tkIt : simTrackDetIdMap) {
0808 for (auto &uIt : tkIt.second) {
0809 float accEnergy = std::get<0>(uIt.second);
0810 float xSim = std::get<2>(uIt.second).x() / accEnergy;
0811 float ySim = std::get<2>(uIt.second).y() / accEnergy;
0812 float zSim = std::get<2>(uIt.second).z() / accEnergy;
0813 LocalPoint posSim(xSim, ySim, zSim);
0814 std::get<2>(uIt.second) = posSim;
0815 }
0816 }
0817 }
0818
0819
0820 DEFINE_DIGI_ACCUMULATOR(MtdTruthAccumulator);