CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
TrackstersMergeProducer.cc
Go to the documentation of this file.
1 #include <memory> // unique_ptr
7 
18 
19 #include "TrackstersPCA.h"
20 
21 using namespace ticl;
22 
23 class TrackstersMergeProducer : public edm::stream::EDProducer<edm::GlobalCache<TrackstersCache>> {
24 public:
25  explicit TrackstersMergeProducer(const edm::ParameterSet &ps, const CacheBase *cache);
27  void produce(edm::Event &, const edm::EventSetup &) override;
28  static void fillDescriptions(edm::ConfigurationDescriptions &descriptions);
29 
30  // static methods for handling the global cache
31  static std::unique_ptr<TrackstersCache> initializeGlobalCache(const edm::ParameterSet &);
32  static void globalEndJob(TrackstersCache *);
33 
34 private:
36 
37  void fillTile(TICLTracksterTiles &, const std::vector<Trackster> &, TracksterIterIndex);
38 
39  void energyRegressionAndID(const std::vector<reco::CaloCluster> &layerClusters, std::vector<Trackster> &result) const;
40  void printTrackstersDebug(const std::vector<Trackster> &, const char *label) const;
41  void assignTimeToCandidates(std::vector<TICLCandidate> &resultCandidates) const;
42  void dumpTrackster(const Trackster &) const;
43 
54  const int eta_bin_window_;
55  const int phi_bin_window_;
56  const double pt_sigma_high_;
57  const double pt_sigma_low_;
58  const double halo_max_distance2_;
59  const double track_min_pt_;
60  const double track_min_eta_;
61  const double track_max_eta_;
63  const double cosangle_align_;
64  const double e_over_h_threshold_;
65  const double pt_neutral_threshold_;
66  const double resol_calo_offset_had_;
67  const double resol_calo_scale_had_;
68  const double resol_calo_offset_em_;
69  const double resol_calo_scale_em_;
70  const bool debug_;
74  const float eidMinClusterEnergy_;
75  const int eidNLayers_;
76  const int eidNClusters_;
77 
78  tensorflow::Session *eidSession_;
80 
81  static constexpr int eidNFeatures_ = 3;
82 };
83 
85  : tracksterstrkem_token_(consumes<std::vector<Trackster>>(ps.getParameter<edm::InputTag>("tracksterstrkem"))),
86  trackstersem_token_(consumes<std::vector<Trackster>>(ps.getParameter<edm::InputTag>("trackstersem"))),
87  tracksterstrk_token_(consumes<std::vector<Trackster>>(ps.getParameter<edm::InputTag>("tracksterstrk"))),
88  trackstershad_token_(consumes<std::vector<Trackster>>(ps.getParameter<edm::InputTag>("trackstershad"))),
89  seedingTrk_token_(consumes<std::vector<TICLSeedingRegion>>(ps.getParameter<edm::InputTag>("seedingTrk"))),
90  clusters_token_(consumes<std::vector<reco::CaloCluster>>(ps.getParameter<edm::InputTag>("layer_clusters"))),
91  clustersTime_token_(
92  consumes<edm::ValueMap<std::pair<float, float>>>(ps.getParameter<edm::InputTag>("layer_clustersTime"))),
93  tracks_token_(consumes<std::vector<reco::Track>>(ps.getParameter<edm::InputTag>("tracks"))),
94  geometry_token_(esConsumes<CaloGeometry, CaloGeometryRecord>()),
95  optimiseAcrossTracksters_(ps.getParameter<bool>("optimiseAcrossTracksters")),
96  eta_bin_window_(ps.getParameter<int>("eta_bin_window")),
97  phi_bin_window_(ps.getParameter<int>("phi_bin_window")),
98  pt_sigma_high_(ps.getParameter<double>("pt_sigma_high")),
99  pt_sigma_low_(ps.getParameter<double>("pt_sigma_low")),
100  halo_max_distance2_(ps.getParameter<double>("halo_max_distance2")),
101  track_min_pt_(ps.getParameter<double>("track_min_pt")),
102  track_min_eta_(ps.getParameter<double>("track_min_eta")),
103  track_max_eta_(ps.getParameter<double>("track_max_eta")),
104  track_max_missing_outerhits_(ps.getParameter<int>("track_max_missing_outerhits")),
105  cosangle_align_(ps.getParameter<double>("cosangle_align")),
106  e_over_h_threshold_(ps.getParameter<double>("e_over_h_threshold")),
107  pt_neutral_threshold_(ps.getParameter<double>("pt_neutral_threshold")),
108  resol_calo_offset_had_(ps.getParameter<double>("resol_calo_offset_had")),
109  resol_calo_scale_had_(ps.getParameter<double>("resol_calo_scale_had")),
110  resol_calo_offset_em_(ps.getParameter<double>("resol_calo_offset_em")),
111  resol_calo_scale_em_(ps.getParameter<double>("resol_calo_scale_em")),
112  debug_(ps.getParameter<bool>("debug")),
113  eidInputName_(ps.getParameter<std::string>("eid_input_name")),
114  eidOutputNameEnergy_(ps.getParameter<std::string>("eid_output_name_energy")),
115  eidOutputNameId_(ps.getParameter<std::string>("eid_output_name_id")),
116  eidMinClusterEnergy_(ps.getParameter<double>("eid_min_cluster_energy")),
117  eidNLayers_(ps.getParameter<int>("eid_n_layers")),
118  eidNClusters_(ps.getParameter<int>("eid_n_clusters")),
119  eidSession_(nullptr) {
120  // mount the tensorflow graph onto the session when set
121  const TrackstersCache *trackstersCache = dynamic_cast<const TrackstersCache *>(cache);
122  if (trackstersCache == nullptr || trackstersCache->eidGraphDef == nullptr) {
123  throw cms::Exception("MissingGraphDef")
124  << "TrackstersMergeProducer received an empty graph definition from the global cache";
125  }
127 
128  produces<std::vector<Trackster>>();
129  produces<std::vector<TICLCandidate>>();
130 }
131 
133  const std::vector<Trackster> &tracksters,
134  TracksterIterIndex tracksterIteration) {
135  int tracksterId = 0;
136  for (auto const &t : tracksters) {
137  tracksterTile.fill(tracksterIteration, t.barycenter().eta(), t.barycenter().phi(), tracksterId);
138  LogDebug("TrackstersMergeProducer") << "Adding tracksterId: " << tracksterId << " into bin [eta,phi]: [ "
139  << tracksterTile[tracksterIteration].etaBin(t.barycenter().eta()) << ", "
140  << tracksterTile[tracksterIteration].phiBin(t.barycenter().phi())
141  << "] for iteration: " << tracksterIteration << std::endl;
142 
143  tracksterId++;
144  }
145 }
146 
148  auto e_over_h = (t.raw_em_pt() / ((t.raw_pt() - t.raw_em_pt()) != 0. ? (t.raw_pt() - t.raw_em_pt()) : 1.));
149  LogDebug("TrackstersMergeProducer")
150  << "\nTrackster raw_pt: " << t.raw_pt() << " raw_em_pt: " << t.raw_em_pt() << " eoh: " << e_over_h
151  << " barycenter: " << t.barycenter() << " eta,phi (baricenter): " << t.barycenter().eta() << ", "
152  << t.barycenter().phi() << " eta,phi (eigen): " << t.eigenvectors(0).eta() << ", " << t.eigenvectors(0).phi()
153  << " pt(eigen): " << std::sqrt(t.eigenvectors(0).Unit().perp2()) * t.raw_energy() << " seedID: " << t.seedID()
154  << " seedIndex: " << t.seedIndex() << " size: " << t.vertices().size() << " average usage: "
155  << (std::accumulate(std::begin(t.vertex_multiplicity()), std::end(t.vertex_multiplicity()), 0.) /
156  (float)t.vertex_multiplicity().size())
157  << " raw_energy: " << t.raw_energy() << " regressed energy: " << t.regressed_energy()
158  << " probs(ga/e/mu/np/cp/nh/am/unk): ";
159  for (auto const &p : t.id_probabilities()) {
160  LogDebug("TrackstersMergeProducer") << std::fixed << p << " ";
161  }
162  LogDebug("TrackstersMergeProducer") << " sigmas: ";
163  for (auto const &s : t.sigmas()) {
164  LogDebug("TrackstersMergeProducer") << s << " ";
165  }
166  LogDebug("TrackstersMergeProducer") << std::endl;
167 }
168 
171  rhtools_.setGeometry(*geom);
172  auto resultTrackstersMerged = std::make_unique<std::vector<Trackster>>();
173  auto resultCandidates = std::make_unique<std::vector<TICLCandidate>>();
174 
175  TICLTracksterTiles tracksterTile;
176  std::vector<bool> usedTrackstersMerged;
177  std::vector<int> indexInMergedCollTRKEM;
178  std::vector<int> indexInMergedCollEM;
179  std::vector<int> indexInMergedCollTRK;
180  std::vector<int> indexInMergedCollHAD;
181  std::vector<bool> usedSeeds;
182 
183  // associating seed to the index of the trackster in the merged collection and the iteration that found it
184  std::map<int, std::vector<std::pair<int, TracksterIterIndex>>> seedToTracksterAssociator;
186  evt.getByToken(tracks_token_, track_h);
187  const auto &tracks = *track_h;
188 
190  evt.getByToken(clusters_token_, cluster_h);
191  const auto &layerClusters = *cluster_h;
192 
194  evt.getByToken(clustersTime_token_, clustersTime_h);
195  const auto &layerClustersTimes = *clustersTime_h;
196 
197  edm::Handle<std::vector<Trackster>> trackstersem_h;
198  evt.getByToken(trackstersem_token_, trackstersem_h);
199  const auto &trackstersEM = *trackstersem_h;
200 
201  edm::Handle<std::vector<Trackster>> tracksterstrkem_h;
202  evt.getByToken(tracksterstrkem_token_, tracksterstrkem_h);
203  const auto &trackstersTRKEM = *tracksterstrkem_h;
204 
205  edm::Handle<std::vector<Trackster>> tracksterstrk_h;
206  evt.getByToken(tracksterstrk_token_, tracksterstrk_h);
207  const auto &trackstersTRK = *tracksterstrk_h;
208 
209  edm::Handle<std::vector<Trackster>> trackstershad_h;
210  evt.getByToken(trackstershad_token_, trackstershad_h);
211  const auto &trackstersHAD = *trackstershad_h;
212 
214  evt.getByToken(seedingTrk_token_, seedingTrk_h);
215  const auto &seedingTrk = *seedingTrk_h;
216  usedSeeds.resize(tracks.size(), false);
217 
218  fillTile(tracksterTile, trackstersTRKEM, TracksterIterIndex::TRKEM);
219  fillTile(tracksterTile, trackstersEM, TracksterIterIndex::EM);
220  fillTile(tracksterTile, trackstersTRK, TracksterIterIndex::TRKHAD);
221  fillTile(tracksterTile, trackstersHAD, TracksterIterIndex::HAD);
222 
223  auto totalNumberOfTracksters =
224  trackstersTRKEM.size() + trackstersTRK.size() + trackstersEM.size() + trackstersHAD.size();
225  resultTrackstersMerged->reserve(totalNumberOfTracksters);
226  usedTrackstersMerged.resize(totalNumberOfTracksters, false);
227  indexInMergedCollTRKEM.reserve(trackstersTRKEM.size());
228  indexInMergedCollEM.reserve(trackstersEM.size());
229  indexInMergedCollTRK.reserve(trackstersTRK.size());
230  indexInMergedCollHAD.reserve(trackstersHAD.size());
231 
232  if (debug_) {
233  printTrackstersDebug(trackstersTRKEM, "tracksterTRKEM");
234  printTrackstersDebug(trackstersEM, "tracksterEM");
235  printTrackstersDebug(trackstersTRK, "tracksterTRK");
236  printTrackstersDebug(trackstersHAD, "tracksterHAD");
237  }
238 
239  for (auto const &t : trackstersTRKEM) {
240  indexInMergedCollTRKEM.push_back(resultTrackstersMerged->size());
241  seedToTracksterAssociator[t.seedIndex()].emplace_back(resultTrackstersMerged->size(), TracksterIterIndex::TRKEM);
242  resultTrackstersMerged->push_back(t);
243  }
244 
245  for (auto const &t : trackstersEM) {
246  indexInMergedCollEM.push_back(resultTrackstersMerged->size());
247  resultTrackstersMerged->push_back(t);
248  }
249 
250  for (auto const &t : trackstersTRK) {
251  indexInMergedCollTRK.push_back(resultTrackstersMerged->size());
252  seedToTracksterAssociator[t.seedIndex()].emplace_back(resultTrackstersMerged->size(), TracksterIterIndex::TRKHAD);
253  resultTrackstersMerged->push_back(t);
254  }
255 
256  for (auto const &t : trackstersHAD) {
257  indexInMergedCollHAD.push_back(resultTrackstersMerged->size());
258  resultTrackstersMerged->push_back(t);
259  }
260 
261  assignPCAtoTracksters(*resultTrackstersMerged,
262  layerClusters,
263  layerClustersTimes,
265  energyRegressionAndID(layerClusters, *resultTrackstersMerged);
266 
267  printTrackstersDebug(*resultTrackstersMerged, "TrackstersMergeProducer");
268 
269  auto trackstersMergedHandle = evt.put(std::move(resultTrackstersMerged));
270 
271  // TICL Candidate creation
272  // We start from neutrals first
273 
274  // Photons
275  for (unsigned i = 0; i < trackstersEM.size(); ++i) {
276  auto mergedIdx = indexInMergedCollEM[i];
277  usedTrackstersMerged[mergedIdx] = true;
278  const auto &t = trackstersEM[i]; //trackster
279  TICLCandidate tmpCandidate;
280  tmpCandidate.addTrackster(edm::Ptr<ticl::Trackster>(trackstersMergedHandle, mergedIdx));
281  tmpCandidate.setCharge(0);
282  tmpCandidate.setPdgId(22);
283  tmpCandidate.setRawEnergy(t.raw_energy());
284  math::XYZTLorentzVector p4(t.raw_energy() * t.barycenter().unit().x(),
285  t.raw_energy() * t.barycenter().unit().y(),
286  t.raw_energy() * t.barycenter().unit().z(),
287  t.raw_energy());
288  tmpCandidate.setP4(p4);
289  resultCandidates->push_back(tmpCandidate);
290  }
291 
292  // Neutral Hadrons
293  constexpr double mpion = 0.13957;
294  constexpr float mpion2 = mpion * mpion;
295  for (unsigned i = 0; i < trackstersHAD.size(); ++i) {
296  auto mergedIdx = indexInMergedCollHAD[i];
297  usedTrackstersMerged[mergedIdx] = true;
298  const auto &t = trackstersHAD[i]; //trackster
299  TICLCandidate tmpCandidate;
300  tmpCandidate.addTrackster(edm::Ptr<ticl::Trackster>(trackstersMergedHandle, mergedIdx));
301  tmpCandidate.setCharge(0);
302  tmpCandidate.setPdgId(130);
303  tmpCandidate.setRawEnergy(t.raw_energy());
304  float momentum = std::sqrt(t.raw_energy() * t.raw_energy() - mpion2);
305  math::XYZTLorentzVector p4(momentum * t.barycenter().unit().x(),
306  momentum * t.barycenter().unit().y(),
307  momentum * t.barycenter().unit().z(),
308  t.raw_energy());
309  tmpCandidate.setP4(p4);
310  resultCandidates->push_back(tmpCandidate);
311  }
312 
313  // Charged Particles
314  for (unsigned i = 0; i < trackstersTRKEM.size(); ++i) {
315  auto mergedIdx = indexInMergedCollTRKEM[i];
316  if (!usedTrackstersMerged[mergedIdx]) {
317  const auto &t = trackstersTRKEM[i]; //trackster
318  auto trackIdx = t.seedIndex();
319  auto const &track = tracks[trackIdx];
320  if (!usedSeeds[trackIdx] and t.raw_energy() > 0) {
321  usedSeeds[trackIdx] = true;
322  usedTrackstersMerged[mergedIdx] = true;
323 
324  std::vector<int> trackstersTRKwithSameSeed;
325  std::vector<int> trackstersTRKEMwithSameSeed;
326 
327  for (const auto &tracksterIterationPair : seedToTracksterAssociator[trackIdx]) {
328  if (tracksterIterationPair.first != mergedIdx and !usedTrackstersMerged[tracksterIterationPair.first] and
329  trackstersMergedHandle->at(tracksterIterationPair.first).raw_energy() > 0.) {
330  if (tracksterIterationPair.second == TracksterIterIndex::TRKEM) {
331  trackstersTRKEMwithSameSeed.push_back(tracksterIterationPair.first);
332  } else if (tracksterIterationPair.second == TracksterIterIndex::TRKHAD) {
333  trackstersTRKwithSameSeed.push_back(tracksterIterationPair.first);
334  }
335  }
336  }
337 
338  float tracksterTotalRawPt = t.raw_pt();
339  std::vector<int> haloTrackstersTRKIdx;
340  bool foundCompatibleTRK = false;
341 
342  for (auto otherTracksterIdx : trackstersTRKwithSameSeed) {
343  usedTrackstersMerged[otherTracksterIdx] = true;
344  tracksterTotalRawPt += trackstersMergedHandle->at(otherTracksterIdx).raw_pt();
345 
346  // Check the X,Y,Z barycenter and merge if they are very close (halo)
347  if ((t.barycenter() - trackstersMergedHandle->at(otherTracksterIdx).barycenter()).mag2() <
349  haloTrackstersTRKIdx.push_back(otherTracksterIdx);
350 
351  } else {
352  foundCompatibleTRK = true;
353  }
354  }
355 
356  //check if there is 1-to-1 relationship
357  if (trackstersTRKEMwithSameSeed.empty()) {
358  if (foundCompatibleTRK) {
359  TICLCandidate tmpCandidate;
360  tmpCandidate.addTrackster(edm::Ptr<ticl::Trackster>(trackstersMergedHandle, mergedIdx));
361  double raw_energy = t.raw_energy();
362 
363  tmpCandidate.setCharge(track.charge());
364  tmpCandidate.setTrackPtr(edm::Ptr<reco::Track>(track_h, trackIdx));
365  tmpCandidate.setPdgId(211 * track.charge());
366  for (auto otherTracksterIdx : trackstersTRKwithSameSeed) {
367  tmpCandidate.addTrackster(edm::Ptr<ticl::Trackster>(trackstersMergedHandle, otherTracksterIdx));
368  raw_energy += trackstersMergedHandle->at(otherTracksterIdx).raw_energy();
369  }
370  tmpCandidate.setRawEnergy(raw_energy);
371  math::XYZTLorentzVector p4(raw_energy * track.momentum().unit().x(),
372  raw_energy * track.momentum().unit().y(),
373  raw_energy * track.momentum().unit().z(),
374  raw_energy);
375  tmpCandidate.setP4(p4);
376  resultCandidates->push_back(tmpCandidate);
377 
378  } else {
379  TICLCandidate tmpCandidate;
380  tmpCandidate.addTrackster(edm::Ptr<ticl::Trackster>(trackstersMergedHandle, mergedIdx));
381  double raw_energy = t.raw_energy();
382  tmpCandidate.setCharge(track.charge());
383  tmpCandidate.setTrackPtr(edm::Ptr<reco::Track>(track_h, trackIdx));
384  for (auto otherTracksterIdx : trackstersTRKwithSameSeed) {
385  tmpCandidate.addTrackster(edm::Ptr<ticl::Trackster>(trackstersMergedHandle, otherTracksterIdx));
386  raw_energy += trackstersMergedHandle->at(otherTracksterIdx).raw_energy();
387  }
388  tmpCandidate.setPdgId(11 * track.charge());
389 
390  tmpCandidate.setRawEnergy(raw_energy);
391  math::XYZTLorentzVector p4(raw_energy * track.momentum().unit().x(),
392  raw_energy * track.momentum().unit().y(),
393  raw_energy * track.momentum().unit().z(),
394  raw_energy);
395  tmpCandidate.setP4(p4);
396  resultCandidates->push_back(tmpCandidate);
397  }
398 
399  } else {
400  // if 1-to-many find closest trackster in momentum
401  int closestTrackster = mergedIdx;
402  float minPtDiff = std::abs(t.raw_pt() - track.pt());
403  for (auto otherTracksterIdx : trackstersTRKEMwithSameSeed) {
404  auto thisPt = tracksterTotalRawPt + trackstersMergedHandle->at(otherTracksterIdx).raw_pt() - t.raw_pt();
405  closestTrackster = std::abs(thisPt - track.pt()) < minPtDiff ? otherTracksterIdx : closestTrackster;
406  }
407  usedTrackstersMerged[closestTrackster] = true;
408 
409  if (foundCompatibleTRK) {
410  TICLCandidate tmpCandidate;
411  tmpCandidate.addTrackster(edm::Ptr<ticl::Trackster>(trackstersMergedHandle, closestTrackster));
412  double raw_energy = trackstersMergedHandle->at(closestTrackster).raw_energy();
413 
414  tmpCandidate.setCharge(track.charge());
415  tmpCandidate.setTrackPtr(edm::Ptr<reco::Track>(track_h, trackIdx));
416  tmpCandidate.setPdgId(211 * track.charge());
417  for (auto otherTracksterIdx : trackstersTRKwithSameSeed) {
418  tmpCandidate.addTrackster(edm::Ptr<ticl::Trackster>(trackstersMergedHandle, otherTracksterIdx));
419  raw_energy += trackstersMergedHandle->at(otherTracksterIdx).raw_energy();
420  }
421  tmpCandidate.setRawEnergy(raw_energy);
422  float momentum = std::sqrt(raw_energy * raw_energy - mpion2);
423  math::XYZTLorentzVector p4(momentum * track.momentum().unit().x(),
424  momentum * track.momentum().unit().y(),
425  momentum * track.momentum().unit().z(),
426  raw_energy);
427  tmpCandidate.setP4(p4);
428  resultCandidates->push_back(tmpCandidate);
429 
430  } else {
431  TICLCandidate tmpCandidate;
432  tmpCandidate.addTrackster(edm::Ptr<ticl::Trackster>(trackstersMergedHandle, closestTrackster));
433  double raw_energy = trackstersMergedHandle->at(closestTrackster).raw_energy();
434 
435  tmpCandidate.setCharge(track.charge());
436  tmpCandidate.setTrackPtr(edm::Ptr<reco::Track>(track_h, trackIdx));
437  for (auto otherTracksterIdx : trackstersTRKwithSameSeed) {
438  tmpCandidate.addTrackster(edm::Ptr<ticl::Trackster>(trackstersMergedHandle, otherTracksterIdx));
439  raw_energy += trackstersMergedHandle->at(otherTracksterIdx).raw_energy();
440  }
441  tmpCandidate.setPdgId(11 * track.charge());
442  tmpCandidate.setRawEnergy(raw_energy);
443  math::XYZTLorentzVector p4(raw_energy * track.momentum().unit().x(),
444  raw_energy * track.momentum().unit().y(),
445  raw_energy * track.momentum().unit().z(),
446  raw_energy);
447  tmpCandidate.setP4(p4);
448  resultCandidates->push_back(tmpCandidate);
449  }
450  // Promote all other TRKEM tracksters as photons with their energy.
451  for (auto otherTracksterIdx : trackstersTRKEMwithSameSeed) {
452  auto tmpIndex = (otherTracksterIdx != closestTrackster) ? otherTracksterIdx : mergedIdx;
453  TICLCandidate photonCandidate;
454  const auto &otherTrackster = trackstersMergedHandle->at(tmpIndex);
455  auto gammaEnergy = otherTrackster.raw_energy();
456  photonCandidate.setCharge(0);
457  photonCandidate.setPdgId(22);
458  photonCandidate.setRawEnergy(gammaEnergy);
459  math::XYZTLorentzVector gammaP4(gammaEnergy * otherTrackster.barycenter().unit().x(),
460  gammaEnergy * otherTrackster.barycenter().unit().y(),
461  gammaEnergy * otherTrackster.barycenter().unit().z(),
462  gammaEnergy);
463  photonCandidate.setP4(gammaP4);
464  photonCandidate.addTrackster(edm::Ptr<ticl::Trackster>(trackstersMergedHandle, tmpIndex));
465  resultCandidates->push_back(photonCandidate);
466  }
467  }
468  }
469  }
470  } //end of loop over trackstersTRKEM
471 
472  for (unsigned i = 0; i < trackstersTRK.size(); ++i) {
473  auto mergedIdx = indexInMergedCollTRK[i];
474  const auto &t = trackstersTRK[i]; //trackster
475 
476  if (!usedTrackstersMerged[mergedIdx] and t.raw_energy() > 0) {
477  auto trackIdx = t.seedIndex();
478  auto const &track = tracks[trackIdx];
479  if (!usedSeeds[trackIdx]) {
480  usedSeeds[trackIdx] = true;
481  usedTrackstersMerged[mergedIdx] = true;
482  TICLCandidate tmpCandidate;
483  tmpCandidate.addTrackster(edm::Ptr<ticl::Trackster>(trackstersMergedHandle, mergedIdx));
484  tmpCandidate.setCharge(track.charge());
485  tmpCandidate.setTrackPtr(edm::Ptr<reco::Track>(track_h, trackIdx));
486  tmpCandidate.setPdgId(211 * track.charge());
487  tmpCandidate.setRawEnergy(t.raw_energy());
488  float momentum = std::sqrt(t.raw_energy() * t.raw_energy() - mpion2);
489  math::XYZTLorentzVector p4(momentum * track.momentum().unit().x(),
490  momentum * track.momentum().unit().y(),
491  momentum * track.momentum().unit().z(),
492  t.raw_energy());
493  tmpCandidate.setP4(p4);
494  resultCandidates->push_back(tmpCandidate);
495  }
496  }
497  }
498  // For all seeds that have 0-energy tracksters whose track is not marked as used, create a charged hadron with the track information.
499  for (auto const &s : seedingTrk) {
500  if (usedSeeds[s.index] == false) {
501  auto const &track = tracks[s.index];
502  // emit a charged hadron
503  TICLCandidate tmpCandidate;
504  tmpCandidate.setCharge(track.charge());
505  tmpCandidate.setTrackPtr(edm::Ptr<reco::Track>(track_h, s.index));
506  tmpCandidate.setPdgId(211 * track.charge());
507  float energy = std::sqrt(track.p() * track.p() + mpion2);
508  tmpCandidate.setRawEnergy(energy);
509  math::PtEtaPhiMLorentzVector p4Polar(track.pt(), track.eta(), track.phi(), mpion);
510  tmpCandidate.setP4(p4Polar);
511  resultCandidates->push_back(tmpCandidate);
512  usedSeeds[s.index] = true;
513  }
514  }
515 
516  // for all general tracks (high purity, pt > 1), check if they have been used: if not, promote them as charged hadrons
517  for (unsigned i = 0; i < tracks.size(); ++i) {
518  auto const &track = tracks[i];
519  if (track.pt() > track_min_pt_ and track.quality(reco::TrackBase::highPurity) and
520  track.missingOuterHits() < track_max_missing_outerhits_ and std::abs(track.outerEta()) > track_min_eta_ and
521  std::abs(track.outerEta()) < track_max_eta_ and usedSeeds[i] == false) {
522  // emit a charged hadron
523  TICLCandidate tmpCandidate;
524  tmpCandidate.setCharge(track.charge());
525  tmpCandidate.setTrackPtr(edm::Ptr<reco::Track>(track_h, i));
526  tmpCandidate.setPdgId(211 * track.charge());
527  float energy = std::sqrt(track.p() * track.p() + mpion2);
528  tmpCandidate.setRawEnergy(energy);
529  math::PtEtaPhiMLorentzVector p4Polar(track.pt(), track.eta(), track.phi(), mpion);
530  tmpCandidate.setP4(p4Polar);
531  resultCandidates->push_back(tmpCandidate);
532  usedSeeds[i] = true;
533  }
534  }
535 
536  // Compute timing
537  assignTimeToCandidates(*resultCandidates);
538 
539  evt.put(std::move(resultCandidates));
540 }
541 
542 void TrackstersMergeProducer::energyRegressionAndID(const std::vector<reco::CaloCluster> &layerClusters,
543  std::vector<Trackster> &tracksters) const {
544  // Energy regression and particle identification strategy:
545  //
546  // 1. Set default values for regressed energy and particle id for each trackster.
547  // 2. Store indices of tracksters whose total sum of cluster energies is above the
548  // eidMinClusterEnergy_ (GeV) treshold. Inference is not applied for soft tracksters.
549  // 3. When no trackster passes the selection, return.
550  // 4. Create input and output tensors. The batch dimension is determined by the number of
551  // selected tracksters.
552  // 5. Fill input tensors with layer cluster features. Per layer, clusters are ordered descending
553  // by energy. Given that tensor data is contiguous in memory, we can use pointer arithmetic to
554  // fill values, even with batching.
555  // 6. Zero-fill features for empty clusters in each layer.
556  // 7. Batched inference.
557  // 8. Assign the regressed energy and id probabilities to each trackster.
558  //
559  // Indices used throughout this method:
560  // i -> batch element / trackster
561  // j -> layer
562  // k -> cluster
563  // l -> feature
564 
565  // set default values per trackster, determine if the cluster energy threshold is passed,
566  // and store indices of hard tracksters
567  std::vector<int> tracksterIndices;
568  for (int i = 0; i < (int)tracksters.size(); i++) {
569  // calculate the cluster energy sum (2)
570  // note: after the loop, sumClusterEnergy might be just above the threshold
571  // which is enough to decide whether to run inference for the trackster or
572  // not
573  float sumClusterEnergy = 0.;
574  for (const unsigned int &vertex : tracksters[i].vertices()) {
575  sumClusterEnergy += (float)layerClusters[vertex].energy();
576  // there might be many clusters, so try to stop early
577  if (sumClusterEnergy >= eidMinClusterEnergy_) {
578  // set default values (1)
579  tracksters[i].setRegressedEnergy(0.f);
580  tracksters[i].zeroProbabilities();
581  tracksterIndices.push_back(i);
582  break;
583  }
584  }
585  }
586 
587  // do nothing when no trackster passes the selection (3)
588  int batchSize = (int)tracksterIndices.size();
589  if (batchSize == 0) {
590  return;
591  }
592 
593  // create input and output tensors (4)
594  tensorflow::TensorShape shape({batchSize, eidNLayers_, eidNClusters_, eidNFeatures_});
595  tensorflow::Tensor input(tensorflow::DT_FLOAT, shape);
596  tensorflow::NamedTensorList inputList = {{eidInputName_, input}};
597  static constexpr int inputDimension = 4;
598 
599  std::vector<tensorflow::Tensor> outputs;
600  std::vector<std::string> outputNames;
601  if (!eidOutputNameEnergy_.empty()) {
602  outputNames.push_back(eidOutputNameEnergy_);
603  }
604  if (!eidOutputNameId_.empty()) {
605  outputNames.push_back(eidOutputNameId_);
606  }
607 
608  // fill input tensor (5)
609  for (int i = 0; i < batchSize; i++) {
610  const Trackster &trackster = tracksters[tracksterIndices[i]];
611 
612  // per layer, we only consider the first eidNClusters_ clusters in terms of
613  // energy, so in order to avoid creating large / nested structures to do
614  // the sorting for an unknown number of total clusters, create a sorted
615  // list of layer cluster indices to keep track of the filled clusters
616  std::vector<int> clusterIndices(trackster.vertices().size());
617  for (int k = 0; k < (int)trackster.vertices().size(); k++) {
618  clusterIndices[k] = k;
619  }
620  sort(clusterIndices.begin(), clusterIndices.end(), [&layerClusters, &trackster](const int &a, const int &b) {
621  return layerClusters[trackster.vertices(a)].energy() > layerClusters[trackster.vertices(b)].energy();
622  });
623 
624  // keep track of the number of seen clusters per layer
625  std::vector<int> seenClusters(eidNLayers_);
626 
627  // loop through clusters by descending energy
628  for (const int &k : clusterIndices) {
629  // get features per layer and cluster and store the values directly in the input tensor
630  const reco::CaloCluster &cluster = layerClusters[trackster.vertices(k)];
631  int j = rhtools_.getLayerWithOffset(cluster.hitsAndFractions()[0].first) - 1;
632  if (j < eidNLayers_ && seenClusters[j] < eidNClusters_) {
633  // get the pointer to the first feature value for the current batch, layer and cluster
634  float *features = &input.tensor<float, inputDimension>()(i, j, seenClusters[j], 0);
635 
636  // fill features
637  *(features++) = float(cluster.energy() / float(trackster.vertex_multiplicity(k)));
638  *(features++) = float(std::abs(cluster.eta()));
639  *(features) = float(cluster.phi());
640 
641  // increment seen clusters
642  seenClusters[j]++;
643  }
644  }
645 
646  // zero-fill features of empty clusters in each layer (6)
647  for (int j = 0; j < eidNLayers_; j++) {
648  for (int k = seenClusters[j]; k < eidNClusters_; k++) {
649  float *features = &input.tensor<float, inputDimension>()(i, j, k, 0);
650  for (int l = 0; l < eidNFeatures_; l++) {
651  *(features++) = 0.f;
652  }
653  }
654  }
655  }
656 
657  // run the inference (7)
658  tensorflow::run(eidSession_, inputList, outputNames, &outputs);
659 
660  // store regressed energy per trackster (8)
661  if (!eidOutputNameEnergy_.empty()) {
662  // get the pointer to the energy tensor, dimension is batch x 1
663  float *energy = outputs[0].flat<float>().data();
664 
665  for (const int &i : tracksterIndices) {
666  tracksters[i].setRegressedEnergy(*(energy++));
667  }
668  }
669 
670  // store id probabilities per trackster (8)
671  if (!eidOutputNameId_.empty()) {
672  // get the pointer to the id probability tensor, dimension is batch x id_probabilities.size()
673  int probsIdx = !eidOutputNameEnergy_.empty();
674  float *probs = outputs[probsIdx].flat<float>().data();
675 
676  for (const int &i : tracksterIndices) {
677  tracksters[i].setProbabilities(probs);
678  probs += tracksters[i].id_probabilities().size();
679  }
680  }
681 }
682 
683 void TrackstersMergeProducer::assignTimeToCandidates(std::vector<TICLCandidate> &resultCandidates) const {
684  for (auto &cand : resultCandidates) {
685  if (cand.tracksters().size() > 1) { // For single-trackster candidates the timing is already set
686  float time = 0.f;
687  float timeErr = 0.f;
688  for (const auto &tr : cand.tracksters()) {
689  if (tr->timeError() > 0) {
690  auto invTimeESq = pow(tr->timeError(), -2);
691  time += tr->time() * invTimeESq;
692  timeErr += invTimeESq;
693  }
694  }
695  if (timeErr > 0) {
696  timeErr = 1. / timeErr;
697 
698  cand.setTime(time * timeErr);
699  cand.setTimeError(sqrt(timeErr));
700  }
701  }
702  }
703 }
704 
706  // this method is supposed to create, initialize and return a TrackstersCache instance
707  std::unique_ptr<TrackstersCache> cache = std::make_unique<TrackstersCache>(params);
708 
709  // load the graph def and save it
710  std::string graphPath = params.getParameter<std::string>("eid_graph_path");
711  if (!graphPath.empty()) {
712  graphPath = edm::FileInPath(graphPath).fullPath();
713  cache->eidGraphDef = tensorflow::loadGraphDef(graphPath);
714  }
715 
716  return cache;
717 }
718 
720  delete cache->eidGraphDef;
721  cache->eidGraphDef = nullptr;
722 }
723 
724 void TrackstersMergeProducer::printTrackstersDebug(const std::vector<Trackster> &tracksters, const char *label) const {
725  if (!debug_)
726  return;
727 
728  int counter = 0;
729  for (auto const &t : tracksters) {
730  LogDebug("TrackstersMergeProducer")
731  << counter++ << " TrackstersMergeProducer (" << label << ") obj barycenter: " << t.barycenter()
732  << " eta,phi (baricenter): " << t.barycenter().eta() << ", " << t.barycenter().phi()
733  << " eta,phi (eigen): " << t.eigenvectors(0).eta() << ", " << t.eigenvectors(0).phi()
734  << " pt(eigen): " << std::sqrt(t.eigenvectors(0).Unit().perp2()) * t.raw_energy() << " seedID: " << t.seedID()
735  << " seedIndex: " << t.seedIndex() << " size: " << t.vertices().size() << " average usage: "
736  << (std::accumulate(std::begin(t.vertex_multiplicity()), std::end(t.vertex_multiplicity()), 0.) /
737  (float)t.vertex_multiplicity().size())
738  << " raw_energy: " << t.raw_energy() << " regressed energy: " << t.regressed_energy()
739  << " probs(ga/e/mu/np/cp/nh/am/unk): ";
740  for (auto const &p : t.id_probabilities()) {
741  LogDebug("TrackstersMergeProducer") << std::fixed << p << " ";
742  }
743  LogDebug("TrackstersMergeProducer") << " sigmas: ";
744  for (auto const &s : t.sigmas()) {
745  LogDebug("TrackstersMergeProducer") << s << " ";
746  }
747  LogDebug("TrackstersMergeProducer") << std::endl;
748  }
749 }
750 
753  desc.add<edm::InputTag>("tracksterstrkem", edm::InputTag("ticlTrackstersTrkEM"));
754  desc.add<edm::InputTag>("trackstersem", edm::InputTag("ticlTrackstersEM"));
755  desc.add<edm::InputTag>("tracksterstrk", edm::InputTag("ticlTrackstersTrk"));
756  desc.add<edm::InputTag>("trackstershad", edm::InputTag("ticlTrackstersHAD"));
757  desc.add<edm::InputTag>("seedingTrk", edm::InputTag("ticlSeedingTrk"));
758  desc.add<edm::InputTag>("layer_clusters", edm::InputTag("hgcalLayerClusters"));
759  desc.add<edm::InputTag>("layer_clustersTime", edm::InputTag("hgcalLayerClusters", "timeLayerCluster"));
760  desc.add<edm::InputTag>("tracks", edm::InputTag("generalTracks"));
761  desc.add<bool>("optimiseAcrossTracksters", true);
762  desc.add<int>("eta_bin_window", 1);
763  desc.add<int>("phi_bin_window", 1);
764  desc.add<double>("pt_sigma_high", 2.);
765  desc.add<double>("pt_sigma_low", 2.);
766  desc.add<double>("halo_max_distance2", 4.);
767  desc.add<double>("track_min_pt", 1.);
768  desc.add<double>("track_min_eta", 1.48);
769  desc.add<double>("track_max_eta", 3.);
770  desc.add<int>("track_max_missing_outerhits", 5);
771  desc.add<double>("cosangle_align", 0.9945);
772  desc.add<double>("e_over_h_threshold", 1.);
773  desc.add<double>("pt_neutral_threshold", 2.);
774  desc.add<double>("resol_calo_offset_had", 1.5);
775  desc.add<double>("resol_calo_scale_had", 0.15);
776  desc.add<double>("resol_calo_offset_em", 1.5);
777  desc.add<double>("resol_calo_scale_em", 0.15);
778  desc.add<bool>("debug", true);
779  desc.add<std::string>("eid_graph_path", "RecoHGCal/TICL/data/tf_models/energy_id_v0.pb");
780  desc.add<std::string>("eid_input_name", "input");
781  desc.add<std::string>("eid_output_name_energy", "output/regressed_energy");
782  desc.add<std::string>("eid_output_name_id", "output/id_probabilities");
783  desc.add<double>("eid_min_cluster_energy", 1.);
784  desc.add<int>("eid_n_layers", 50);
785  desc.add<int>("eid_n_clusters", 10);
786  descriptions.add("trackstersMergeProducer", desc);
787 }
788 
ticl::Trackster::IterationIndex TracksterIterIndex
Session * createSession(SessionOptions &sessionOptions)
Definition: TensorFlow.cc:85
std::vector< NamedTensor > NamedTensorList
Definition: TensorFlow.h:30
OrphanHandle< PROD > put(std::unique_ptr< PROD > product)
Put a new product.
Definition: Event.h:133
const edm::EDGetTokenT< std::vector< Trackster > > trackstersem_token_
void fillTile(TICLTracksterTiles &, const std::vector< Trackster > &, TracksterIterIndex)
tensorflow::Session * eidSession_
const edm::EDGetTokenT< std::vector< TICLSeedingRegion > > seedingTrk_token_
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:539
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
void assignTimeToCandidates(std::vector< TICLCandidate > &resultCandidates) const
GraphDef * loadGraphDef(const std::string &pbFile)
Definition: TensorFlow.cc:68
void produce(edm::Event &, const edm::EventSetup &) override
auto const & tracks
cannot be loose
const edm::EDGetTokenT< std::vector< Trackster > > tracksterstrkem_token_
const edm::EDGetTokenT< std::vector< reco::CaloCluster > > clusters_token_
const edm::ESGetToken< CaloGeometry, CaloGeometryRecord > geometry_token_
void dumpTrackster(const Trackster &) const
double eta() const
pseudorapidity of cluster centroid
Definition: CaloCluster.h:181
void energyRegressionAndID(const std::vector< reco::CaloCluster > &layerClusters, std::vector< Trackster > &result) const
static std::string const input
Definition: EdmProvDump.cc:47
tuple result
Definition: mps_fire.py:311
PtEtaPhiMLorentzVectorD PtEtaPhiMLorentzVector
Lorentz vector with cartesian internal representation.
Definition: LorentzVector.h:25
void assignPCAtoTracksters(std::vector< Trackster > &, const std::vector< reco::CaloCluster > &, const edm::ValueMap< std::pair< float, float >> &, double, bool energyWeight=true)
void setCharge(Charge q) final
set electric charge
XYZTLorentzVectorD XYZTLorentzVector
Lorentz vector with cylindrical internal representation using pseudorapidity.
Definition: LorentzVector.h:29
char const * label
static constexpr int eidNFeatures_
const std::vector< std::pair< DetId, float > > & hitsAndFractions() const
Definition: CaloCluster.h:210
const edm::EDGetTokenT< std::vector< Trackster > > tracksterstrk_token_
void setRawEnergy(float rawEnergy)
Definition: TICLCandidate.h:40
std::vector< float > features(const reco::PreId &ecal, const reco::PreId &hcal, double rho, const reco::BeamSpot &spot, noZS::EcalClusterLazyTools &ecalTools)
static std::unique_ptr< TrackstersCache > initializeGlobalCache(const edm::ParameterSet &)
T sqrt(T t)
Definition: SSEVec.h:19
T mag2() const
The vector magnitude squared. Equivalent to vec.dot(vec)
def move
Definition: eostools.py:511
void run(Session *session, const NamedTensorList &inputs, const std::vector< std::string > &outputNames, std::vector< Tensor > *outputs, const thread::ThreadPoolOptions &threadPoolOptions)
Definition: TensorFlow.cc:213
static void globalEndJob(TrackstersCache *)
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
std::atomic< tensorflow::GraphDef * > eidGraphDef
Definition: GlobalCache.h:25
const edm::EDGetTokenT< std::vector< Trackster > > trackstershad_token_
double energy() const
cluster energy
Definition: CaloCluster.h:149
const edm::EDGetTokenT< edm::ValueMap< std::pair< float, float > > > clustersTime_token_
ParameterDescriptionBase * add(U const &iLabel, T const &value)
const edm::EDGetTokenT< std::vector< reco::Track > > tracks_token_
const std::string eidOutputNameEnergy_
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
unsigned int getLayerWithOffset(const DetId &) const
Definition: RecHitTools.cc:365
GlobalPoint getPositionLayer(int layer, bool nose=false) const
Definition: RecHitTools.cc:141
T getParameter(std::string const &) const
Definition: ParameterSet.h:303
double b
Definition: hdecay.h:118
void add(std::string const &label, ParameterSetDescription const &psetDescription)
TrackstersMergeProducer(const edm::ParameterSet &ps, const CacheBase *cache)
void setGeometry(CaloGeometry const &)
Definition: RecHitTools.cc:68
char data[epos_bytes_allocation]
Definition: EPOS_Wrapper.h:79
void addTrackster(const edm::Ptr< ticl::Trackster > &trackster)
Definition: TICLCandidate.h:45
double a
Definition: hdecay.h:119
static std::atomic< unsigned int > counter
unsigned int lastLayerEE(bool nose=false) const
Definition: RecHitTools.h:75
string end
Definition: dataset.py:937
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
std::string fullPath() const
Definition: FileInPath.cc:161
void fill(int index, double eta, double phi, unsigned int objectId)
Definition: TICLLayerTile.h:80
ESHandle< T > getHandle(const ESGetToken< T, R > &iToken) const
Definition: EventSetup.h:157
double phi() const
azimuthal angle of cluster centroid
Definition: CaloCluster.h:184
void printTrackstersDebug(const std::vector< Trackster > &, const char *label) const
void setPdgId(int pdgId) final
void setTrackPtr(const edm::Ptr< reco::Track > &trackPtr)
Definition: TICLCandidate.h:37
ESGetTokenH3DDVariant esConsumes(std::string const &Reccord, edm::ConsumesCollector &)
Definition: DeDxTools.cc:283
void setP4(const LorentzVector &p4) final
set 4-momentum
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:29
def cache
Definition: utilities.py:3
#define LogDebug(id)