CMS 3D CMS Logo

GeneralInterpretationAlgo.cc
Go to the documentation of this file.
5 
6 using namespace ticl;
7 
9 
11 
14  del_tk_ts_layer1_(conf.getParameter<double>("delta_tk_ts_layer1")),
15  del_tk_ts_int_(conf.getParameter<double>("delta_tk_ts_interface")),
16  timing_quality_threshold_(conf.getParameter<double>("timing_quality_threshold")) {}
17 
19  const hgcal::RecHitTools rhtools,
20  const edm::ESHandle<MagneticField> bfieldH,
21  const edm::ESHandle<Propagator> propH) {
22  hgcons_ = hgcons;
23  rhtools_ = rhtools;
24  buildLayers();
25 
26  bfield_ = bfieldH;
27  propagator_ = propH;
28 }
29 
31  // build disks at HGCal front & EM-Had interface for track propagation
32 
33  float zVal = hgcons_->waferZ(1, true);
34  std::pair<float, float> rMinMax = hgcons_->rangeR(zVal, true);
35 
36  float zVal_interface = rhtools_.getPositionLayer(rhtools_.lastLayerEE()).z();
37  std::pair<float, float> rMinMax_interface = hgcons_->rangeR(zVal_interface, true);
38 
39  for (int iSide = 0; iSide < 2; ++iSide) {
40  float zSide = (iSide == 0) ? (-1. * zVal) : zVal;
41  firstDisk_[iSide] =
42  std::make_unique<GeomDet>(Disk::build(Disk::PositionType(0, 0, zSide),
44  SimpleDiskBounds(rMinMax.first, rMinMax.second, zSide - 0.5, zSide + 0.5))
45  .get());
46 
47  zSide = (iSide == 0) ? (-1. * zVal_interface) : zVal_interface;
48  interfaceDisk_[iSide] = std::make_unique<GeomDet>(
49  Disk::build(Disk::PositionType(0, 0, zSide),
51  SimpleDiskBounds(rMinMax_interface.first, rMinMax_interface.second, zSide - 0.5, zSide + 0.5))
52  .get());
53  }
54 }
56  const unsigned idx,
57  float zVal,
58  std::array<TICLLayerTile, 2> &tracksterTiles) {
59  // needs only the positive Z co-ordinate of the surface to propagate to
60  // the correct sign is calculated inside according to the barycenter of trackster
61  Vector const &baryc = t.barycenter();
62  Vector directnv = t.eigenvectors(0);
63 
64  // barycenter as direction for tracksters w/ poor PCA
65  // propagation still done to get the cartesian coords
66  // which are anyway converted to eta, phi in linking
67  // -> can be simplified later
68 
69  //FP: disable PCA propagation for the moment and fallback to barycenter position
70  // if (t.eigenvalues()[0] / t.eigenvalues()[1] < 20)
71  directnv = baryc.unit();
72  zVal *= (baryc.Z() > 0) ? 1 : -1;
73  float par = (zVal - baryc.Z()) / directnv.Z();
74  float xOnSurface = par * directnv.X() + baryc.X();
75  float yOnSurface = par * directnv.Y() + baryc.Y();
76  Vector tPoint(xOnSurface, yOnSurface, zVal);
77  if (tPoint.Eta() > 0) {
78  tracksterTiles[1].fill(tPoint.Eta(), tPoint.Phi(), idx);
79  } else if (tPoint.Eta() < 0) {
80  tracksterTiles[0].fill(tPoint.Eta(), tPoint.Phi(), idx);
81  }
82 
83  return tPoint;
84 }
85 
87  const std::vector<std::pair<Vector, unsigned>> &seedingCollection,
88  const std::array<TICLLayerTile, 2> &tracksterTiles,
89  const std::vector<Vector> &tracksterPropPoints,
90  const float delta,
91  unsigned trackstersSize,
92  std::vector<std::vector<unsigned>> &resultCollection,
93  bool useMask = false) {
94  // Finds tracksters in tracksterTiles within an eta-phi window
95  // (given by delta) of the objects (track/trackster) in the seedingCollection.
96  // Element i in resultCollection is the vector of trackster
97  // indices found close to the i-th object in the seedingCollection.
98  // If specified, Tracksters are masked once found as close to an object.
99  std::vector<int> mask(trackstersSize, 0);
100  const float delta2 = delta * delta;
101 
102  for (auto &i : seedingCollection) {
103  float seed_eta = i.first.Eta();
104  float seed_phi = i.first.Phi();
105  unsigned seedId = i.second;
106  auto sideZ = seed_eta > 0; //forward or backward region
107  const TICLLayerTile &tile = tracksterTiles[sideZ];
108  float eta_min = std::max(std::fabs(seed_eta) - delta, (float)TileConstants::minEta);
109  float eta_max = std::min(std::fabs(seed_eta) + delta, (float)TileConstants::maxEta);
110 
111  // get range of bins touched by delta
112  std::array<int, 4> search_box = tile.searchBoxEtaPhi(eta_min, eta_max, seed_phi - delta, seed_phi + delta);
113 
114  std::vector<unsigned> in_delta;
115  // std::vector<float> distances2;
116  std::vector<float> energies;
117  for (int eta_i = search_box[0]; eta_i <= search_box[1]; ++eta_i) {
118  for (int phi_i = search_box[2]; phi_i <= search_box[3]; ++phi_i) {
119  const auto &in_tile = tile[tile.globalBin(eta_i, (phi_i % TileConstants::nPhiBins))];
120  for (const unsigned &t_i : in_tile) {
121  // calculate actual distances of tracksters to the seed for a more accurate cut
122  auto sep2 = (tracksterPropPoints[t_i].Eta() - seed_eta) * (tracksterPropPoints[t_i].Eta() - seed_eta) +
123  (tracksterPropPoints[t_i].Phi() - seed_phi) * (tracksterPropPoints[t_i].Phi() - seed_phi);
124  if (sep2 < delta2) {
125  in_delta.push_back(t_i);
126  // distances2.push_back(sep2);
127  energies.push_back(tracksters[t_i].raw_energy());
128  }
129  }
130  }
131  }
132 
133  // sort tracksters found in ascending order of their distances from the seed
134  std::vector<unsigned> indices(in_delta.size());
135  std::iota(indices.begin(), indices.end(), 0);
136  std::sort(indices.begin(), indices.end(), [&](unsigned i, unsigned j) { return energies[i] > energies[j]; });
137 
138  // push back sorted tracksters in the result collection
139  for (const unsigned &index : indices) {
140  const auto &t_i = in_delta[index];
141  if (!mask[t_i]) {
142  resultCollection[seedId].push_back(t_i);
143  if (useMask)
144  mask[t_i] = 1;
145  }
146  }
147 
148  } // seeding collection loop
149 }
150 
152  const reco::Track &track,
153  const Trackster &trackster,
154  const float &tkT,
155  const float &tkTErr,
156  const float &tkQual,
157  const float &tkBeta,
158  const GlobalPoint &tkMtdPos,
159  bool useMTDTiming) {
160  float threshold = std::min(0.2 * trackster.raw_energy(), 10.0);
161  bool energyCompatible = (total_raw_energy + trackster.raw_energy() < track.p() + threshold);
162 
163  if (!useMTDTiming)
164  return energyCompatible;
165 
166  // compatible if trackster time is within 3sigma of
167  // track time; compatible if either: no time assigned
168  // to trackster or track
169 
170  float tsT = trackster.time();
171  float tsTErr = trackster.timeError();
172 
173  bool timeCompatible = false;
174  if (tsT == -99. or tkTErr == -1 or tkQual < timing_quality_threshold_)
175  timeCompatible = true;
176  else {
177  const auto &barycenter = trackster.barycenter();
178 
179  const auto deltaSoverV = std::sqrt((barycenter.x() - tkMtdPos.x()) * (barycenter.x() - tkMtdPos.x()) +
180  (barycenter.y() - tkMtdPos.y()) * (barycenter.y() - tkMtdPos.y()) +
181  (barycenter.z() - tkMtdPos.z()) * (barycenter.z() - tkMtdPos.z())) /
182  (tkBeta * 29.9792458);
183 
184  const auto deltaT = tsT - tkT;
185 
186  // timeCompatible = (std::abs(deltaSoverV - deltaT) < maxDeltaT_ * sqrt(tsTErr * tsTErr + tkTErr * tkTErr));
187  // use sqrt(2) * error on the track for the total error, because the time of the trackster is too small
188  timeCompatible = std::abs(deltaSoverV - deltaT) < maxDeltaT_ * std::sqrt(tsTErr * tsTErr + tkTErr * tkTErr);
189  }
190 
192  if (!(energyCompatible))
193  LogDebug("GeneralInterpretationAlgo")
194  << "energy incompatible : track p " << track.p() << " trackster energy " << trackster.raw_energy() << "\n"
195  << " total_raw_energy " << total_raw_energy << " greater than track p + threshold "
196  << track.p() + threshold << "\n";
197  if (!(timeCompatible))
198  LogDebug("GeneralInterpretationAlgo") << "time incompatible : track time " << tkT << " +/- " << tkTErr
199  << " trackster time " << tsT << " +/- " << tsTErr << "\n";
200  }
201 
202  return energyCompatible && timeCompatible;
203 }
204 
206  edm::Handle<MtdHostCollection> inputTiming_h,
207  std::vector<Trackster> &resultTracksters,
208  std::vector<int> &resultCandidate) {
209  bool useMTDTiming = inputTiming_h.isValid();
210  const auto tkH = input.tracksHandle;
211  const auto maskTracks = input.maskedTracks;
212  const auto &tracks = *tkH;
213  const auto &tracksters = input.tracksters;
214 
215  auto bFieldProd = bfield_.product();
216  const Propagator &prop = (*propagator_);
217 
218  // propagated point collections
219  // elements in the propagated points collecions are used
220  // to look for potential linkages in the appropriate tiles
221  std::vector<std::pair<Vector, unsigned>> trackPColl; // propagated track points and index of track in collection
222  std::vector<std::pair<Vector, unsigned>> tkPropIntColl; // tracks propagated to lastLayerEE
223 
224  trackPColl.reserve(tracks.size());
225  tkPropIntColl.reserve(tracks.size());
226 
227  std::array<TICLLayerTile, 2> tracksterPropTiles = {}; // all Tracksters, propagated to layer 1
228  std::array<TICLLayerTile, 2> tsPropIntTiles = {}; // all Tracksters, propagated to lastLayerEE
229 
231  LogDebug("GeneralInterpretationAlgo") << "------- Geometric Linking ------- \n";
232 
233  // Propagate tracks
234  std::vector<unsigned> candidateTrackIds;
235  candidateTrackIds.reserve(tracks.size());
236  for (unsigned i = 0; i < tracks.size(); ++i) {
237  if (!maskTracks[i])
238  continue;
239  candidateTrackIds.push_back(i);
240  }
241 
242  std::sort(candidateTrackIds.begin(), candidateTrackIds.end(), [&](unsigned i, unsigned j) {
243  return tracks[i].p() > tracks[j].p();
244  });
245 
246  for (auto const i : candidateTrackIds) {
247  const auto &tk = tracks[i];
248  int iSide = int(tk.eta() > 0);
249  const auto &fts = trajectoryStateTransform::outerFreeState((tk), bFieldProd);
250  // to the HGCal front
251  const auto &tsos = prop.propagate(fts, firstDisk_[iSide]->surface());
252  if (tsos.isValid()) {
253  Vector trackP(tsos.globalPosition().x(), tsos.globalPosition().y(), tsos.globalPosition().z());
254  trackPColl.emplace_back(trackP, i);
255  }
256  // to lastLayerEE
257  const auto &tsos_int = prop.propagate(fts, interfaceDisk_[iSide]->surface());
258  if (tsos_int.isValid()) {
259  Vector trackP(tsos_int.globalPosition().x(), tsos_int.globalPosition().y(), tsos_int.globalPosition().z());
260  tkPropIntColl.emplace_back(trackP, i);
261  }
262  } // Tracks
263  tkPropIntColl.shrink_to_fit();
264  trackPColl.shrink_to_fit();
265  candidateTrackIds.shrink_to_fit();
266 
267  // Propagate tracksters
268 
269  // Record postions of all tracksters propagated to layer 1 and lastLayerEE,
270  // to be used later for distance calculation in the link finding stage
271  // indexed by trackster index in event collection
272  std::vector<Vector> tsAllProp;
273  std::vector<Vector> tsAllPropInt;
274  tsAllProp.reserve(tracksters.size());
275  tsAllPropInt.reserve(tracksters.size());
276  // Propagate tracksters
277 
278  for (unsigned i = 0; i < tracksters.size(); ++i) {
279  const auto &t = tracksters[i];
281  LogDebug("GeneralInterpretationAlgo")
282  << "trackster " << i << " - eta " << t.barycenter().eta() << " phi " << t.barycenter().phi() << " time "
283  << t.time() << " energy " << t.raw_energy() << "\n";
284 
285  // to HGCal front
286  float zVal = hgcons_->waferZ(1, true);
287  auto tsP = propagateTrackster(t, i, zVal, tracksterPropTiles);
288  tsAllProp.emplace_back(tsP);
289 
290  // to lastLayerEE
292  tsP = propagateTrackster(t, i, zVal, tsPropIntTiles);
293  tsAllPropInt.emplace_back(tsP);
294 
295  } // TS
296 
297  // step 1: tracks -> all tracksters, at firstLayerEE
298  std::vector<std::vector<unsigned>> tsNearTk(tracks.size());
300  tracksters, trackPColl, tracksterPropTiles, tsAllProp, del_tk_ts_layer1_, tracksters.size(), tsNearTk);
301 
302  // step 2: tracks -> all tracksters, at lastLayerEE
303  std::vector<std::vector<unsigned>> tsNearTkAtInt(tracks.size());
305  tracksters, tkPropIntColl, tsPropIntTiles, tsAllPropInt, del_tk_ts_int_, tracksters.size(), tsNearTkAtInt);
306 
307  std::vector<unsigned int> chargedHadronsFromTk;
308  std::vector<std::vector<unsigned int>> trackstersInTrackIndices;
309  trackstersInTrackIndices.resize(tracks.size());
310 
311  std::vector<bool> chargedMask(tracksters.size(), true);
312  for (unsigned &i : candidateTrackIds) {
313  if (tsNearTk[i].empty() && tsNearTkAtInt[i].empty()) { // nothing linked to track, make charged hadrons
314  continue;
315  }
316 
317  std::vector<unsigned int> chargedCandidate;
318  float total_raw_energy = 0.f;
319 
320  float track_time = 0.f;
321  float track_timeErr = 0.f;
322  float track_quality = 0.f;
323  float track_beta = 0.f;
324  GlobalPoint track_MtdPos{0.f, 0.f, 0.f};
325  if (useMTDTiming) {
326  auto const &inputTimingView = (*inputTiming_h).const_view();
327  track_time = inputTimingView.time()[i];
328  track_timeErr = inputTimingView.timeErr()[i];
329  track_quality = inputTimingView.MVAquality()[i];
330  track_beta = inputTimingView.beta()[i];
331  track_MtdPos = {
332  inputTimingView.posInMTD_x()[i], inputTimingView.posInMTD_y()[i], inputTimingView.posInMTD_z()[i]};
333  }
334 
335  for (auto const tsIdx : tsNearTk[i]) {
336  if (chargedMask[tsIdx] && timeAndEnergyCompatible(total_raw_energy,
337  tracks[i],
338  tracksters[tsIdx],
339  track_time,
340  track_timeErr,
342  track_beta,
343  track_MtdPos,
344  useMTDTiming)) {
345  chargedCandidate.push_back(tsIdx);
346  chargedMask[tsIdx] = false;
347  total_raw_energy += tracksters[tsIdx].raw_energy();
348  }
349  }
350  for (const unsigned tsIdx : tsNearTkAtInt[i]) { // do the same for tk -> ts links at the interface
351  if (chargedMask[tsIdx] && timeAndEnergyCompatible(total_raw_energy,
352  tracks[i],
353  tracksters[tsIdx],
354  track_time,
355  track_timeErr,
357  track_beta,
358  track_MtdPos,
359  useMTDTiming)) {
360  chargedCandidate.push_back(tsIdx);
361  chargedMask[tsIdx] = false;
362  total_raw_energy += tracksters[tsIdx].raw_energy();
363  }
364  }
365  trackstersInTrackIndices[i] = chargedCandidate;
366  }
367 
368  for (size_t iTrack = 0; iTrack < trackstersInTrackIndices.size(); iTrack++) {
369  if (!trackstersInTrackIndices[iTrack].empty()) {
370  if (trackstersInTrackIndices[iTrack].size() == 1) {
371  auto tracksterId = trackstersInTrackIndices[iTrack][0];
372  resultCandidate[iTrack] = resultTracksters.size();
373  resultTracksters.push_back(input.tracksters[tracksterId]);
374  } else {
375  // in this case mergeTracksters() clears the pid probabilities and the regressed energy is not set
376  // TODO: fix probabilities when CNN will be splitted
377  Trackster outTrackster;
378  float regr_en = 0.f;
379  bool isHadron = false;
380  for (auto const tracksterId : trackstersInTrackIndices[iTrack]) {
381  //maskTracksters[tracksterId] = 0;
382  outTrackster.mergeTracksters(input.tracksters[tracksterId]);
383  regr_en += input.tracksters[tracksterId].regressed_energy();
384  if (input.tracksters[tracksterId].isHadronic())
385  isHadron = true;
386  }
387  resultCandidate[iTrack] = resultTracksters.size();
388  resultTracksters.push_back(outTrackster);
389  resultTracksters.back().setRegressedEnergy(regr_en);
390  // since a track has been linked it can only be electron or charged hadron
391  if (isHadron)
392  resultTracksters.back().setIdProbability(ticl::Trackster::ParticleType::charged_hadron, 1.f);
393  else
394  resultTracksters.back().setIdProbability(ticl::Trackster::ParticleType::electron, 1.f);
395  }
396  }
397  }
398 
399  for (size_t iTrackster = 0; iTrackster < input.tracksters.size(); iTrackster++) {
400  if (chargedMask[iTrackster]) {
401  resultTracksters.push_back(input.tracksters[iTrackster]);
402  }
403  }
404 };
405 
407  desc.add<std::string>("cutTk",
408  "1.48 < abs(eta) < 3.0 && pt > 1. && quality(\"highPurity\") && "
409  "hitPattern().numberOfLostHits(\"MISSING_OUTER_HITS\") < 5");
410  desc.add<double>("delta_tk_ts_layer1", 0.02);
411  desc.add<double>("delta_tk_ts_interface", 0.03);
412  desc.add<double>("timing_quality_threshold", 0.5);
414 }
double waferZ(int layer, bool reco) const
static DiskPointer build(Args &&... args)
Definition: BoundDisk.h:38
void initialize(const HGCalDDDConstants *hgcons, const hgcal::RecHitTools rhtools, const edm::ESHandle< MagneticField > bfieldH, const edm::ESHandle< Propagator > propH) override
edm::ESHandle< MagneticField > bfield_
bool timeAndEnergyCompatible(float &total_raw_energy, const reco::Track &track, const Trackster &trackster, const float &tkTime, const float &tkTimeErr, const float &tkQual, const float &tkBeta, const GlobalPoint &tkMtdPos, bool useMTDTiming)
static void fillPSetDescription(edm::ParameterSetDescription &iDesc)
T z() const
Definition: PV3DBase.h:61
math::XYZVectorF Vector
Definition: Trackster.h:21
uint32_t cc[maxCellsPerHit]
Definition: gpuFishbone.h:49
static constexpr int nPhiBins
Definition: Common.h:15
std::unique_ptr< GeomDet > firstDisk_[2]
const Vector & barycenter() const
Definition: Trackster.h:159
std::unique_ptr< GeomDet > interfaceDisk_[2]
static constexpr float maxEta
Definition: Common.h:13
TrajectoryStateOnSurface propagate(STA const &state, SUR const &surface) const
Definition: Propagator.h:50
const float timeError() const
Definition: Trackster.h:152
static std::string const input
Definition: EdmProvDump.cc:50
T x() const
Definition: PV3DBase.h:59
T y() const
Definition: PV3DBase.h:60
T const * product() const
Definition: ESHandle.h:86
void mergeTracksters(const Trackster &other)
Definition: Trackster.h:81
edm::ESHandle< Propagator > propagator_
const float raw_energy() const
Definition: Trackster.h:154
T sqrt(T t)
Definition: SSEVec.h:23
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e< void, edm::EventID const &, edm::Timestamp const & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
Definition: Activities.doc:12
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
double f[11][100]
static constexpr float minEta
Definition: Common.h:12
static void fillPSetDescription(edm::ParameterSetDescription &desc)
std::pair< double, double > rangeR(double z, bool reco) const
void findTrackstersInWindow(const MultiVectorManager< Trackster > &tracksters, const std::vector< std::pair< Vector, unsigned >> &seedingCollection, const std::array< TICLLayerTile, 2 > &tracksterTiles, const std::vector< Vector > &tracksterPropPoints, float delta, unsigned trackstersSize, std::vector< std::vector< unsigned >> &resultCollection, bool useMask)
GlobalPoint getPositionLayer(int layer, bool nose=false) const
Definition: RecHitTools.cc:152
bool isValid() const
Definition: HandleBase.h:70
Vector propagateTrackster(const Trackster &t, const unsigned idx, float zVal, std::array< TICLLayerTile, 2 > &tracksterTiles)
math::XYZVectorF Vector
Definition: Common.h:42
const float time() const
Definition: Trackster.h:151
Definition: Common.h:10
FreeTrajectoryState outerFreeState(const reco::Track &tk, const MagneticField *field, bool withErr=true)
void makeCandidates(const Inputs &input, edm::Handle< MtdHostCollection > inputTiming_h, std::vector< Trackster > &resultTracksters, std::vector< int > &resultCandidate) override
unsigned int lastLayerEE(bool nose=false) const
Definition: RecHitTools.h:76
GeneralInterpretationAlgo(const edm::ParameterSet &conf, edm::ConsumesCollector iC)
#define LogDebug(id)