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