CMS 3D CMS Logo

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