CMS 3D CMS Logo

CaloTruthAccumulator.cc
Go to the documentation of this file.
1 #define DEBUG false
2 #if DEBUG
3 // boost optional (used by boost graph) results in some false positives with
4 // -Wmaybe-uninitialized
5 #pragma GCC diagnostic push
6 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
7 #endif
8 
9 // BOOST GRAPH LIBRARY
10 #include <boost/graph/adjacency_list.hpp>
11 #include <boost/graph/breadth_first_search.hpp>
12 #include <boost/graph/depth_first_search.hpp>
13 #include <boost/graph/graphviz.hpp>
14 
15 #if DEBUG
16 #pragma GCC diagnostic pop
17 #endif
18 
19 #include <iterator>
20 #include <numeric> // for std::accumulate
21 #include <unordered_map>
22 
31 
38 
47 
52 
58 
59 namespace {
60  using Index_t = unsigned;
61  using Barcode_t = int;
62  const std::string messageCategoryGraph_("CaloTruthAccumulatorGraphProducer");
63 } // namespace
64 
65 using boost::add_edge;
66 using boost::adjacency_list;
67 using boost::directedS;
68 using boost::edge;
69 using boost::edge_weight;
70 using boost::edge_weight_t;
71 using boost::listS;
72 using boost::property;
73 using boost::vecS;
74 using boost::vertex;
75 using boost::vertex_name;
76 using boost::vertex_name_t;
77 
78 /* GRAPH DEFINITIONS
79 
80  The graphs represent the full decay chain.
81 
82  The parent-child relationship is the natural one, following "time".
83 
84  Each edge has a property (edge_weight_t) that holds a const pointer to the
85  SimTrack that connects the 2 vertices of the edge, the number of simHits
86  associated to that simTrack and the cumulative number of simHits of itself
87  and of all its children. Only simHits within the selected detectors are
88  taken into account. The cumulative property is filled during the dfs
89  exploration of the graph: if not explored the number is 0.
90 
91  Each vertex has a property (vertex_name_t) that holds a const pointer to the
92  SimTrack that originated that vertex and the cumulative number of simHits of
93  all its outgoing edges. The cumulative property is filled during the dfs
94  exploration of the graph: if not explored the number is 0.
95 
96  Stable particles are recovered/added in a second iterations and are linked
97  to ghost vertices with an offset starting from the highest generated vertex.
98 
99  Multiple decays of a single particle that retains its original trackId are
100  merged into one unique vertex (the first encountered) in order to avoid
101  multiple counting of its associated simHits (if any).
102 
103 */
104 struct EdgeProperty {
105  EdgeProperty(const SimTrack *t, int h, int c) : simTrack(t), simHits(h), cumulative_simHits(c) {}
107  int simHits;
109 };
110 
118 };
119 
120 using EdgeParticleClustersProperty = property<edge_weight_t, EdgeProperty>;
121 using VertexMotherParticleProperty = property<vertex_name_t, VertexProperty>;
122 using DecayChain = adjacency_list<listS, vecS, directedS, VertexMotherParticleProperty, EdgeParticleClustersProperty>;
123 
125 public:
127 
128 private:
129  void initializeEvent(const edm::Event &event, const edm::EventSetup &setup) override;
130  void accumulate(const edm::Event &event, const edm::EventSetup &setup) override;
131  void accumulate(const PileUpEventPrincipal &event, const edm::EventSetup &setup, edm::StreamID const &) override;
132  void finalizeEvent(edm::Event &event, const edm::EventSetup &setup) override;
133  void beginLuminosityBlock(edm::LuminosityBlock const &lumi, edm::EventSetup const &setup) override;
134 
136  template <class T>
137  void accumulateEvent(const T &event,
138  const edm::EventSetup &setup,
139  const edm::Handle<edm::HepMCProduct> &hepMCproduct);
140 
143  template <class T>
144  void fillSimHits(std::vector<std::pair<DetId, const PCaloHit *>> &returnValue,
145  std::unordered_map<int, std::map<int, float>> &simTrackDetIdEnergyMap,
146  const T &event,
147  const edm::EventSetup &setup);
148 
150 
151  std::unordered_map<Index_t, float> m_detIdToTotalSimEnergy; // keep track of cell normalizations
152  std::unordered_multimap<Barcode_t, Index_t> m_simHitBarcodeToIndex;
153 
159  const unsigned int maximumPreviousBunchCrossing_;
166 
171 
172  std::vector<edm::InputTag> collectionTags_;
176 
177  const double minEnergy_, maxPseudoRapidity_;
178  const bool premixStage1_;
179 
180 public:
182  std::unique_ptr<SimClusterCollection> pSimClusters;
183  std::unique_ptr<CaloParticleCollection> pCaloParticles;
184  };
185 
186  struct calo_particles {
187  std::vector<uint32_t> sc_start_;
188  std::vector<uint32_t> sc_stop_;
189 
190  void swap(calo_particles &oth) {
191  sc_start_.swap(oth.sc_start_);
192  sc_stop_.swap(oth.sc_stop_);
193  }
194 
195  void clear() {
196  sc_start_.clear();
197  sc_stop_.clear();
198  }
199  };
200 
201 private:
202  const HGCalTopology *hgtopo_[3] = {nullptr, nullptr, nullptr};
203  const HGCalDDDConstants *hgddd_[3] = {nullptr, nullptr, nullptr};
204  const HcalDDDRecConstants *hcddd_ = nullptr;
207  // geometry type (0 pre-TDR; 1 TDR)
209 };
210 
211 /* Graph utility functions */
212 
213 namespace {
214  template <typename Edge, typename Graph, typename Visitor>
215  void accumulateSimHits_edge(Edge &e, const Graph &g, Visitor *v) {
216  auto const edge_property = get(edge_weight, g, e);
217  v->total_simHits += edge_property.simHits;
218  IfLogDebug(DEBUG, messageCategoryGraph_)
219  << " Examining edges " << e << " --> particle " << edge_property.simTrack->type() << "("
220  << edge_property.simTrack->trackId() << ")"
221  << " with SimClusters: " << edge_property.simHits << " Accumulated SimClusters: " << v->total_simHits
222  << std::endl;
223  }
224  template <typename Vertex, typename Graph>
225  void print_vertex(Vertex &u, const Graph &g) {
226  auto const vertex_property = get(vertex_name, g, u);
227  IfLogDebug(DEBUG, messageCategoryGraph_) << " At " << u;
228  // The Mother of all vertices has **no** SimTrack associated.
229  if (vertex_property.simTrack)
230  IfLogDebug(DEBUG, messageCategoryGraph_) << " [" << vertex_property.simTrack->type() << "]"
231  << "(" << vertex_property.simTrack->trackId() << ")";
232  IfLogDebug(DEBUG, messageCategoryGraph_) << std::endl;
233  }
234 
235 // Graphviz output functions will only be generated in DEBUG mode
236 #if DEBUG
237  std::string graphviz_vertex(const VertexProperty &v) {
238  std::ostringstream oss;
239  oss << "{id: " << (v.simTrack ? v.simTrack->trackId() : 0) << ",\\ntype: " << (v.simTrack ? v.simTrack->type() : 0)
240  << ",\\nchits: " << v.cumulative_simHits << "}";
241  return oss.str();
242  }
243 
244  std::string graphviz_edge(const EdgeProperty &e) {
245  std::ostringstream oss;
246  oss << "[" << (e.simTrack ? e.simTrack->trackId() : 0) << "," << (e.simTrack ? e.simTrack->type() : 0) << ","
247  << e.simHits << "," << e.cumulative_simHits << "]";
248  return oss.str();
249  }
250 #endif
251 
252  class SimHitsAccumulator_dfs_visitor : public boost::default_dfs_visitor {
253  public:
254  int total_simHits = 0;
255  template <typename Edge, typename Graph>
256  void examine_edge(Edge e, const Graph &g) {
257  accumulateSimHits_edge(e, g, this);
258  }
259  template <typename Edge, typename Graph>
260  void finish_edge(Edge e, const Graph &g) {
261  auto const edge_property = get(edge_weight, g, e);
262  auto src = source(e, g);
263  auto trg = target(e, g);
264  auto cumulative = edge_property.simHits + get(vertex_name, g, trg).cumulative_simHits +
265  (get(vertex_name, g, src).simTrack ? get(vertex_name, g, src).cumulative_simHits
266  : 0); // when we hit the root vertex we have to stop
267  // adding back its contribution.
268  auto const src_vertex_property = get(vertex_name, g, src);
269  put(get(vertex_name, const_cast<Graph &>(g)), src, VertexProperty(src_vertex_property.simTrack, cumulative));
270  put(get(edge_weight, const_cast<Graph &>(g)),
271  e,
272  EdgeProperty(edge_property.simTrack, edge_property.simHits, cumulative));
273  IfLogDebug(DEBUG, messageCategoryGraph_)
274  << " Finished edge: " << e << " Track id: " << get(edge_weight, g, e).simTrack->trackId()
275  << " has accumulated " << cumulative << " hits" << std::endl;
276  IfLogDebug(DEBUG, messageCategoryGraph_) << " SrcVtx: " << src << "\t" << get(vertex_name, g, src).simTrack
277  << "\t" << get(vertex_name, g, src).cumulative_simHits << std::endl;
278  IfLogDebug(DEBUG, messageCategoryGraph_) << " TrgVtx: " << trg << "\t" << get(vertex_name, g, trg).simTrack
279  << "\t" << get(vertex_name, g, trg).cumulative_simHits << std::endl;
280  }
281  };
282 
283  using Selector = std::function<bool(EdgeProperty &)>;
284 
285  class CaloParticle_dfs_visitor : public boost::default_dfs_visitor {
286  public:
287  CaloParticle_dfs_visitor(CaloTruthAccumulator::OutputCollections &output,
289  std::unordered_multimap<Barcode_t, Index_t> &simHitBarcodeToIndex,
290  std::unordered_map<int, std::map<int, float>> &simTrackDetIdEnergyMap,
291  Selector selector)
292  : output_(output),
293  caloParticles_(caloParticles),
294  simHitBarcodeToIndex_(simHitBarcodeToIndex),
295  simTrackDetIdEnergyMap_(simTrackDetIdEnergyMap),
296  selector_(selector) {}
297  template <typename Vertex, typename Graph>
298  void discover_vertex(Vertex u, const Graph &g) {
299  // If we reach the vertex 0, it means that we are backtracking with respect
300  // to the first generation of stable particles: simply return;
301  // if (u == 0) return;
302  print_vertex(u, g);
303  auto const vertex_property = get(vertex_name, g, u);
304  if (!vertex_property.simTrack)
305  return;
306  auto trackIdx = vertex_property.simTrack->trackId();
307  IfLogDebug(DEBUG, messageCategoryGraph_)
308  << " Found " << simHitBarcodeToIndex_.count(trackIdx) << " associated simHits" << std::endl;
309  if (simHitBarcodeToIndex_.count(trackIdx)) {
310  output_.pSimClusters->emplace_back(*vertex_property.simTrack);
311  auto &simcluster = output_.pSimClusters->back();
312  std::unordered_map<uint32_t, float> acc_energy;
313  for (auto const &hit_and_energy : simTrackDetIdEnergyMap_[trackIdx]) {
314  acc_energy[hit_and_energy.first] += hit_and_energy.second;
315  }
316  for (auto const &hit_and_energy : acc_energy) {
317  simcluster.addRecHitAndFraction(hit_and_energy.first, hit_and_energy.second);
318  }
319  }
320  }
321  template <typename Edge, typename Graph>
322  void examine_edge(Edge e, const Graph &g) {
323  auto src = source(e, g);
324  auto vertex_property = get(vertex_name, g, src);
325  if (src == 0 or (vertex_property.simTrack == nullptr)) {
326  auto edge_property = get(edge_weight, g, e);
327  IfLogDebug(DEBUG, messageCategoryGraph_) << "Considering CaloParticle: " << edge_property.simTrack->trackId();
328  if (selector_(edge_property)) {
329  IfLogDebug(DEBUG, messageCategoryGraph_) << "Adding CaloParticle: " << edge_property.simTrack->trackId();
330  output_.pCaloParticles->emplace_back(*(edge_property.simTrack));
331  caloParticles_.sc_start_.push_back(output_.pSimClusters->size());
332  }
333  }
334  }
335 
336  template <typename Edge, typename Graph>
337  void finish_edge(Edge e, const Graph &g) {
338  auto src = source(e, g);
339  auto vertex_property = get(vertex_name, g, src);
340  if (src == 0 or (vertex_property.simTrack == nullptr)) {
341  auto edge_property = get(edge_weight, g, e);
342  if (selector_(edge_property)) {
343  caloParticles_.sc_stop_.push_back(output_.pSimClusters->size());
344  }
345  }
346  }
347 
348  private:
350  CaloTruthAccumulator::calo_particles &caloParticles_;
351  std::unordered_multimap<Barcode_t, Index_t> &simHitBarcodeToIndex_;
352  std::unordered_map<int, std::map<int, float>> &simTrackDetIdEnergyMap_;
353  Selector selector_;
354  };
355 } // namespace
356 
358  edm::ProducerBase &mixMod,
360  : messageCategory_("CaloTruthAccumulator"),
361  maximumPreviousBunchCrossing_(config.getParameter<unsigned int>("maximumPreviousBunchCrossing")),
362  maximumSubsequentBunchCrossing_(config.getParameter<unsigned int>("maximumSubsequentBunchCrossing")),
363  simTrackLabel_(config.getParameter<edm::InputTag>("simTrackCollection")),
364  simVertexLabel_(config.getParameter<edm::InputTag>("simVertexCollection")),
365  collectionTags_(),
366  genParticleLabel_(config.getParameter<edm::InputTag>("genParticleCollection")),
367  hepMCproductLabel_(config.getParameter<edm::InputTag>("HepMCProductLabel")),
368  minEnergy_(config.getParameter<double>("MinEnergy")),
369  maxPseudoRapidity_(config.getParameter<double>("MaxPseudoRapidity")),
370  premixStage1_(config.getParameter<bool>("premixStage1")),
371  geometryType_(-1) {
372  mixMod.produces<SimClusterCollection>("MergedCaloTruth");
373  mixMod.produces<CaloParticleCollection>("MergedCaloTruth");
374  if (premixStage1_) {
375  mixMod.produces<std::vector<std::pair<unsigned int, float>>>("MergedCaloTruth");
376  }
377 
378  iC.consumes<std::vector<SimTrack>>(simTrackLabel_);
379  iC.consumes<std::vector<SimVertex>>(simVertexLabel_);
380  iC.consumes<std::vector<reco::GenParticle>>(genParticleLabel_);
381  iC.consumes<std::vector<int>>(genParticleLabel_);
382  iC.consumes<std::vector<int>>(hepMCproductLabel_);
383 
384  // Fill the collection tags
385  const edm::ParameterSet &simHitCollectionConfig = config.getParameterSet("simHitCollections");
386  std::vector<std::string> parameterNames = simHitCollectionConfig.getParameterNames();
387 
388  for (auto const &parameterName : parameterNames) {
389  std::vector<edm::InputTag> tags = simHitCollectionConfig.getParameter<std::vector<edm::InputTag>>(parameterName);
390  collectionTags_.insert(collectionTags_.end(), tags.begin(), tags.end());
391  }
392 
393  for (auto const &collectionTag : collectionTags_) {
394  iC.consumes<std::vector<PCaloHit>>(collectionTag);
395  }
396 }
397 
400  iSetup.get<CaloGeometryRecord>().get(geom);
401  const HGCalGeometry *eegeom = nullptr, *fhgeom = nullptr, *bhgeomnew = nullptr;
402  const HcalGeometry *bhgeom = nullptr;
403 
404  eegeom = static_cast<const HGCalGeometry *>(
406  // check if it's the new geometry
407  if (eegeom) {
408  geometryType_ = 1;
409  fhgeom = static_cast<const HGCalGeometry *>(
411  bhgeomnew = static_cast<const HGCalGeometry *>(
413  } else {
414  geometryType_ = 0;
415  eegeom = static_cast<const HGCalGeometry *>(geom->getSubdetectorGeometry(DetId::Forward, HGCEE));
416  fhgeom = static_cast<const HGCalGeometry *>(geom->getSubdetectorGeometry(DetId::Forward, HGCHEF));
417  bhgeom = static_cast<const HcalGeometry *>(geom->getSubdetectorGeometry(DetId::Hcal, HcalEndcap));
418  }
419  hgtopo_[0] = &(eegeom->topology());
420  hgtopo_[1] = &(fhgeom->topology());
421  if (bhgeomnew)
422  hgtopo_[2] = &(bhgeomnew->topology());
423 
424  for (unsigned i = 0; i < 3; ++i) {
425  if (hgtopo_[i])
426  hgddd_[i] = &(hgtopo_[i]->dddConstants());
427  }
428 
429  if (bhgeom)
430  hcddd_ = bhgeom->topology().dddConstants();
431 }
432 
436 
437  m_detIdToTotalSimEnergy.clear();
438 }
439 
449  event.getByLabel(hepMCproductLabel_, hepmc);
450 
451  edm::LogInfo(messageCategory_) << " CaloTruthAccumulator::accumulate (signal)";
452  accumulateEvent(event, setup, hepmc);
453 }
454 
456  edm::EventSetup const &setup,
457  edm::StreamID const &) {
458  if (event.bunchCrossing() >= -static_cast<int>(maximumPreviousBunchCrossing_) &&
459  event.bunchCrossing() <= static_cast<int>(maximumSubsequentBunchCrossing_)) {
460  // simply create empty handle as we do not have a HepMCProduct in PU anyway
462  edm::LogInfo(messageCategory_) << " CaloTruthAccumulator::accumulate (pileup) bunchCrossing="
463  << event.bunchCrossing();
464  accumulateEvent(event, setup, hepmc);
465  } else {
466  edm::LogInfo(messageCategory_) << "Skipping pileup event for bunch crossing " << event.bunchCrossing();
467  }
468 }
469 
471  edm::LogInfo(messageCategory_) << "Adding " << output_.pSimClusters->size() << " SimParticles and "
472  << output_.pCaloParticles->size() << " CaloParticles to the event.";
473 
474  // We need to normalize the hits and energies into hits and fractions (since
475  // we have looped over all pileup events)
476  // For premixing stage1 we keep the energies, they will be normalized to
477  // fractions in stage2
478 
479  if (premixStage1_) {
480  auto totalEnergies = std::make_unique<std::vector<std::pair<unsigned int, float>>>();
481  totalEnergies->reserve(m_detIdToTotalSimEnergy.size());
482  std::copy(m_detIdToTotalSimEnergy.begin(), m_detIdToTotalSimEnergy.end(), std::back_inserter(*totalEnergies));
483  std::sort(totalEnergies->begin(), totalEnergies->end());
484  event.put(std::move(totalEnergies), "MergedCaloTruth");
485  } else {
486  for (auto &sc : *(output_.pSimClusters)) {
487  auto hitsAndEnergies = sc.hits_and_fractions();
489  for (auto &hAndE : hitsAndEnergies) {
490  const float totalenergy = m_detIdToTotalSimEnergy[hAndE.first];
491  float fraction = 0.;
492  if (totalenergy > 0)
493  fraction = hAndE.second / totalenergy;
494  else
496  << "TotalSimEnergy for hit " << hAndE.first << " is 0! The fraction for this hit cannot be computed.";
497  sc.addRecHitAndFraction(hAndE.first, fraction);
498  }
499  }
500  }
501 
502  // save the SimCluster orphan handle so we can fill the calo particles
503  auto scHandle = event.put(std::move(output_.pSimClusters), "MergedCaloTruth");
504 
505  // now fill the calo particles
506  for (unsigned i = 0; i < output_.pCaloParticles->size(); ++i) {
507  auto &cp = (*output_.pCaloParticles)[i];
508  for (unsigned j = m_caloParticles.sc_start_[i]; j < m_caloParticles.sc_stop_[i]; ++j) {
509  edm::Ref<SimClusterCollection> ref(scHandle, j);
510  cp.addSimCluster(ref);
511  }
512  }
513 
514  event.put(std::move(output_.pCaloParticles), "MergedCaloTruth");
515 
517 
518  std::unordered_map<Index_t, float>().swap(m_detIdToTotalSimEnergy);
519  std::unordered_multimap<Barcode_t, Index_t>().swap(m_simHitBarcodeToIndex);
520 }
521 
522 template <class T>
524  const edm::EventSetup &setup,
525  const edm::Handle<edm::HepMCProduct> &hepMCproduct) {
527  edm::Handle<std::vector<int>> hGenParticleIndices;
528 
529  event.getByLabel(simTrackLabel_, hSimTracks);
530  event.getByLabel(simVertexLabel_, hSimVertices);
531 
532  event.getByLabel(genParticleLabel_, hGenParticles);
533  event.getByLabel(genParticleLabel_, hGenParticleIndices);
534 
535  std::vector<std::pair<DetId, const PCaloHit *>> simHitPointers;
536  std::unordered_map<int, std::map<int, float>> simTrackDetIdEnergyMap;
537  fillSimHits(simHitPointers, simTrackDetIdEnergyMap, event, setup);
538 
539  // Clear maps from previous event fill them for this one
540  m_simHitBarcodeToIndex.clear();
541  for (unsigned int i = 0; i < simHitPointers.size(); ++i) {
542  m_simHitBarcodeToIndex.emplace(simHitPointers[i].second->geantTrackId(), i);
543  }
544 
545  auto const &tracks = *hSimTracks;
546  auto const &vertices = *hSimVertices;
547  std::unordered_map<int, int> trackid_to_track_index;
549  int idx = 0;
550 
551  IfLogDebug(DEBUG, messageCategory_) << " TRACKS" << std::endl;
552  for (auto const &t : tracks) {
553  IfLogDebug(DEBUG, messageCategory_) << " " << idx << "\t" << t.trackId() << "\t" << t << std::endl;
554  trackid_to_track_index[t.trackId()] = idx;
555  idx++;
556  }
557 
584  idx = 0;
585  std::vector<int> used_sim_tracks(tracks.size(), 0);
586  std::vector<int> collapsed_vertices(vertices.size(), 0);
587  IfLogDebug(DEBUG, messageCategory_) << " VERTICES" << std::endl;
588  for (auto const &v : vertices) {
589  IfLogDebug(DEBUG, messageCategory_) << " " << idx++ << "\t" << v << std::endl;
590  if (v.parentIndex() != -1) {
591  auto trk_idx = trackid_to_track_index[v.parentIndex()];
592  auto origin_vtx = tracks[trk_idx].vertIndex();
593  if (used_sim_tracks[trk_idx]) {
594  // collapse the vertex into the original first vertex we saw associated
595  // to this track. Omit adding the edge in order to avoid double
596  // counting of the very same particles and its associated hits.
597  collapsed_vertices[v.vertexId()] = used_sim_tracks[trk_idx];
598  continue;
599  }
600  // Perform the actual vertex collapsing, if needed.
601  if (collapsed_vertices[origin_vtx])
602  origin_vtx = collapsed_vertices[origin_vtx];
603  add_edge(origin_vtx,
604  v.vertexId(),
605  EdgeProperty(&tracks[trk_idx], simTrackDetIdEnergyMap[v.parentIndex()].size(), 0),
606  decay);
607  used_sim_tracks[trk_idx] = v.vertexId();
608  }
609  }
610  // Build the motherParticle property to each vertex
611  auto const &vertexMothersProp = get(vertex_name, decay);
612  // Now recover the particles that did not decay. Append them with an index
613  // bigger than the size of the generated vertices.
614  int offset = vertices.size();
615  for (size_t i = 0; i < tracks.size(); ++i) {
616  if (!used_sim_tracks[i]) {
617  auto origin_vtx = tracks[i].vertIndex();
618  // Perform the actual vertex collapsing, if needed.
619  if (collapsed_vertices[origin_vtx])
620  origin_vtx = collapsed_vertices[origin_vtx];
621  add_edge(
622  origin_vtx, offset, EdgeProperty(&tracks[i], simTrackDetIdEnergyMap[tracks[i].trackId()].size(), 0), decay);
623  // The properties for "fake" vertices associated to stable particles have
624  // to be set inside this loop, since they do not belong to the vertices
625  // collection and would be skipped by that loop (coming next)
626  put(vertexMothersProp, offset, VertexProperty(&tracks[i], 0));
627  offset++;
628  }
629  }
630  for (auto const &v : vertices) {
631  if (v.parentIndex() != -1) {
632  // Skip collapsed_vertices
633  if (collapsed_vertices[v.vertexId()])
634  continue;
635  put(vertexMothersProp, v.vertexId(), VertexProperty(&tracks[trackid_to_track_index[v.parentIndex()]], 0));
636  }
637  }
638  SimHitsAccumulator_dfs_visitor vis;
639  depth_first_search(decay, visitor(vis));
640  CaloParticle_dfs_visitor caloParticleCreator(
641  output_,
644  simTrackDetIdEnergyMap,
645  [&](EdgeProperty &edge_property) -> bool {
646  // Apply selection on SimTracks in order to promote them to be
647  // CaloParticles. The function returns TRUE if the particle satisfies
648  // the selection, FALSE otherwise. Therefore the correct logic to select
649  // the particle is to ask for TRUE as return value.
650  return (edge_property.cumulative_simHits != 0 and !edge_property.simTrack->noGenpart() and
651  edge_property.simTrack->momentum().E() > minEnergy_ and
652  std::abs(edge_property.simTrack->momentum().Eta()) < maxPseudoRapidity_);
653  });
654  depth_first_search(decay, visitor(caloParticleCreator));
655 
656 #if DEBUG
657  boost::write_graphviz(std::cout,
658  decay,
659  make_label_writer(make_transform_value_property_map(&graphviz_vertex, get(vertex_name, decay))),
660  make_label_writer(make_transform_value_property_map(&graphviz_edge, get(edge_weight, decay))));
661 #endif
662 }
663 
664 template <class T>
665 void CaloTruthAccumulator::fillSimHits(std::vector<std::pair<DetId, const PCaloHit *>> &returnValue,
666  std::unordered_map<int, std::map<int, float>> &simTrackDetIdEnergyMap,
667  const T &event,
668  const edm::EventSetup &setup) {
669  for (auto const &collectionTag : collectionTags_) {
671  const bool isHcal = (collectionTag.instance().find("HcalHits") != std::string::npos);
672  event.getByLabel(collectionTag, hSimHits);
673  for (auto const &simHit : *hSimHits) {
674  DetId id(0);
675  const uint32_t simId = simHit.id();
676  if (geometryType_ == 1) {
677  // no test numbering in new geometry
678  id = simId;
679  } else if (isHcal) {
681  if (hid.subdet() == HcalEndcap)
682  id = hid;
683  } else {
684  int subdet, layer, cell, sec, subsec, zp;
685  HGCalTestNumbering::unpackHexagonIndex(simId, subdet, zp, layer, sec, subsec, cell);
686  const HGCalDDDConstants *ddd = hgddd_[subdet - 3];
687  std::pair<int, int> recoLayerCell = ddd->simToReco(cell, layer, sec, hgtopo_[subdet - 3]->detectorType());
688  cell = recoLayerCell.first;
689  layer = recoLayerCell.second;
690  // skip simhits with bad barcodes or non-existant layers
691  if (layer == -1 || simHit.geantTrackId() == 0)
692  continue;
693  id = HGCalDetId((ForwardSubdetector)subdet, zp, layer, subsec, sec, cell);
694  }
695 
696  if (DetId(0) == id)
697  continue;
698 
699  uint32_t detId = id.rawId();
700  returnValue.emplace_back(id, &simHit);
701  simTrackDetIdEnergyMap[simHit.geantTrackId()][id.rawId()] += simHit.energy();
702 
703  m_detIdToTotalSimEnergy[detId] += simHit.energy();
704  }
705  } // end of loop over InputTags
706 }
707 
708 // Register with the framework
BranchAliasSetterT< ProductType > produces()
declare what type of product will make and with which optional label
size
Write out results.
EDGetTokenT< ProductType > consumes(edm::InputTag const &tag)
const CaloSubdetectorGeometry * getSubdetectorGeometry(const DetId &id) const
access the subdetector geometry for the given subdetector directly
Definition: CaloGeometry.cc:49
std::unordered_multimap< Barcode_t, Index_t > m_simHitBarcodeToIndex
const HcalDDDRecConstants * dddConstants() const
Definition: HcalTopology.h:168
edm::Handle< std::vector< SimVertex > > hSimVertices
void fillSimHits(std::vector< std::pair< DetId, const PCaloHit * >> &returnValue, std::unordered_map< int, std::map< int, float >> &simTrackDetIdEnergyMap, const T &event, const edm::EventSetup &setup)
Fills the supplied vector with pointers to the SimHits, checking for bad modules if required...
void initializeEvent(const edm::Event &event, const edm::EventSetup &setup) override
HcalSubdetector subdet() const
get the subdetector
Definition: HcalDetId.h:146
FWCore Framework interface EventSetupRecordImplementation h
Helper function to determine trigger accepts.
def copy(args, dbName)
const HGCalTopology * hgtopo_[3]
const unsigned int maximumSubsequentBunchCrossing_
#define nullptr
void beginLuminosityBlock(edm::LuminosityBlock const &lumi, edm::EventSetup const &setup) override
def setup(process, global_tag, zero_tesla=False)
Definition: GeneralSetup.py:2
std::vector< edm::InputTag > collectionTags_
Definition: config.py:1
ForwardSubdetector
EdgeProperty(const SimTrack *t, int h, int c)
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e g
Definition: Activities.doc:4
void addRecHitAndFraction(uint32_t hit, float fraction)
add rechit with fraction
Definition: SimCluster.h:175
void swap(Association< C > &lhs, Association< C > &rhs)
Definition: Association.h:116
const SimTrack * simTrack
const HcalTopology & topology() const
Definition: HcalGeometry.h:117
void put(edm::Event &evt, double value, const char *instanceName)
U second(std::pair< T, U > const &p)
const SimTrack * simTrack
edm::InputTag hepMCproductLabel_
Needed to add HepMC::GenVertex to SimVertex.
bool noGenpart() const
Definition: SimTrack.h:35
const std::string messageCategory_
std::pair< int, int > simToReco(int cell, int layer, int mod, bool half) const
void accumulate(const edm::Event &event, const edm::EventSetup &setup) override
def trg(schema, nls)
CaloTruthAccumulator(const edm::ParameterSet &config, edm::ProducerBase &mixMod, edm::ConsumesCollector &iC)
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e< void, edm::EventID const &, edm::Timestamp const & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
Definition: Activities.doc:12
const HGCalTopology & topology() const
void clearHitsAndFractions()
clear the hits and fractions list
Definition: SimCluster.h:190
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
property< edge_weight_t, EdgeProperty > EdgeParticleClustersProperty
std::unordered_map< Index_t, float > m_detIdToTotalSimEnergy
const edm::InputTag simVertexLabel_
void addSimCluster(const SimClusterRef &ref)
Definition: CaloParticle.h:60
std::vector< std::string > getParameterNames() const
Functor that operates on <T>
Definition: Selector.h:23
const HGCalDDDConstants * hgddd_[3]
VertexProperty(const VertexProperty &other)
const edm::InputTag simTrackLabel_
VertexProperty(const SimTrack *t, int c)
edm::Handle< std::vector< SimTrack > > hSimTracks
Definition: DetId.h:18
void accumulateEvent(const T &event, const edm::EventSetup &setup, const edm::Handle< edm::HepMCProduct > &hepMCproduct)
Both forms of accumulate() delegate to this templated method.
unsigned int trackId() const
Definition: CoreSimTrack.h:31
std::unique_ptr< CaloParticleCollection > pCaloParticles
const HGCalDDDConstants & dddConstants() const
ParameterSet const & getParameterSet(std::string const &) const
const HcalDDDRecConstants * hcddd_
void finalizeEvent(edm::Event &event, const edm::EventSetup &setup) override
int type() const
particle type (HEP PDT convension)
Definition: CoreSimTrack.h:22
HLT enums.
#define DEFINE_DIGI_ACCUMULATOR(type)
std::vector< CaloParticle > CaloParticleCollection
const math::XYZTLorentzVectorD & momentum() const
Definition: CoreSimTrack.h:19
T get() const
Definition: EventSetup.h:71
property< vertex_name_t, VertexProperty > VertexMotherParticleProperty
std::unique_ptr< SimClusterCollection > pSimClusters
DetId relabel(const uint32_t testId) const
std::vector< SimCluster > SimClusterCollection
Definition: SimClusterFwd.h:8
long double T
adjacency_list< listS, vecS, directedS, VertexMotherParticleProperty, EdgeParticleClustersProperty > DecayChain
static std::string const source
Definition: EdmProvDump.cc:47
static void unpackHexagonIndex(const uint32_t &idx, int &subdet, int &z, int &lay, int &wafer, int &celltyp, int &cell)
def move(src, dest)
Definition: eostools.py:511
#define IfLogDebug(cond, cat)
Definition: event.py:1
std::vector< std::pair< uint32_t, float > > hits_and_fractions() const
Returns list of rechit IDs and fractions for this SimCluster.
Definition: SimCluster.h:181
const unsigned int maximumPreviousBunchCrossing_
#define DEBUG