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