CMS 3D CMS Logo

List of all members | Public Member Functions | Private Attributes
AngleCalculation Class Reference

#include <AngleCalculation.h>

Public Member Functions

void calculate_angles (EMTFTrack &track, const int izone) const
 
void calculate_bx (EMTFTrack &track) const
 
void configure (int verbose, int endcap, int sector, int bx, int bxWindow, int thetaWindow, int thetaWindowZone0, bool bugME11Dupes, bool bugAmbigThetaWin, bool twoStationSameBX)
 
void erase_tracks (EMTFTrackCollection &tracks) const
 
void process (emtf::zone_array< EMTFTrackCollection > &zone_tracks) const
 

Private Attributes

bool bugAmbigThetaWin_
 
bool bugME11Dupes_
 
int bx_
 
int bxWindow_
 
int endcap_
 
int sector_
 
int thetaWindow_
 
int thetaWindowZone0_
 
bool twoStationSameBX_
 
int verbose_
 

Detailed Description

Definition at line 6 of file AngleCalculation.h.

Member Function Documentation

◆ calculate_angles()

void AngleCalculation::calculate_angles ( EMTFTrack track,
const int  izone 
) const

Definition at line 79 of file AngleCalculation.cc.

References a, funct::abs(), b, l1t::EMTFPtLUT::bt_ci, l1t::EMTFPtLUT::bt_hi, l1t::EMTFPtLUT::bt_si, l1t::EMTFPtLUT::bt_vi, bugAmbigThetaWin_, bugME11Dupes_, emtf::calc_eta_from_theta_deg(), emtf::calc_phi_glob_deg(), emtf::calc_phi_loc_deg(), emtf::calc_theta_deg_from_int(), relativeConstraints::chamber, l1t::EMTFPtLUT::cpattern, l1t::EMTFPtLUT::csign, l1t::EMTFPtLUT::delta_ph, l1t::EMTFPtLUT::delta_th, emtf_assert, l1t::EMTFPtLUT::fr, mps_fire::i, L1TMuon::kGEM, ALCARECOPromptCalibProdSiPixelAli0T_cff::mode, emtf::NUM_STATION_PAIRS, emtf::NUM_STATIONS, mps_fire::result, relativeConstraints::ring, l1t::EMTFPtLUT::sign_ph, l1t::EMTFPtLUT::sign_th, l1t::EMTFPtLUT::slope, l1t::EMTFPtLUT::st1_ring2, relativeConstraints::station, hcal_dqm_sourceclient-live_cfg::subsystem, theta(), thetaWindow_, thetaWindowZone0_, HLT_2023v12_cff::track, findQualityFiles::v, and testProducerWithPsetDescEmpty_cfi::x1.

Referenced by process().

79  {
80  // Group track hits by station
81  std::array<EMTFHitCollection, emtf::NUM_STATIONS> st_conv_hits;
82 
83  for (int istation = 0; istation < emtf::NUM_STATIONS; ++istation) {
84  for (const auto& conv_hit : track.Hits()) {
85  if ((conv_hit.Station() - 1) == istation) {
86  st_conv_hits.at(istation).push_back(conv_hit);
87  }
88  }
89 
90  if (bugME11Dupes_) {
91  emtf_assert(st_conv_hits.at(istation).size() <= 4); // ambiguity in theta is max 4
92  } else {
93  emtf_assert(st_conv_hits.at(istation).size() <= 2); // ambiguity in theta is max 2
94  }
95  }
96  emtf_assert(st_conv_hits.size() == emtf::NUM_STATIONS);
97 
98  // Best theta deltas and phi deltas
99  // from 0 to 5: dtheta12, dtheta13, dtheta14, dtheta23, dtheta24, dtheta34
100  std::array<int, emtf::NUM_STATION_PAIRS>
101  best_dtheta_arr; // Best of up to 4 dTheta values per pair of stations (with duplicate thetas)
102  std::array<int, emtf::NUM_STATION_PAIRS> best_dtheta_sign_arr;
103  std::array<int, emtf::NUM_STATION_PAIRS>
104  best_dphi_arr; // Not really "best" - there is only one dPhi value per pair of stations
105  std::array<int, emtf::NUM_STATION_PAIRS> best_dphi_sign_arr;
106 
107  // Best angles
108  // from 0 to 5: ME2, ME3, ME4, ME2, ME2, ME3
109  // dtheta12, dtheta13, dtheta14, dtheta23, dtheta24, dtheta34
110  std::array<int, emtf::NUM_STATION_PAIRS> best_theta_arr;
111  std::array<int, emtf::NUM_STATION_PAIRS> best_phi_arr;
112 
113  // Keep track of which pair is valid
114  std::array<bool, emtf::NUM_STATION_PAIRS> best_dtheta_valid_arr;
115  // std::array<bool, emtf::NUM_STATION_PAIRS> best_has_rpc_arr; // Not used currently
116 
117  // Initialize
118  best_dtheta_arr.fill(invalid_dtheta);
119  best_dtheta_sign_arr.fill(1);
120  best_dphi_arr.fill(invalid_dphi);
121  best_dphi_sign_arr.fill(1);
122  best_phi_arr.fill(0);
123  best_theta_arr.fill(0);
124  best_dtheta_valid_arr.fill(false);
125  // best_has_rpc_arr .fill(false);
126 
127  auto abs_diff = [](int a, int b) { return std::abs(a - b); };
128 
129  // Calculate angles
130  int ipair = 0;
131 
132  for (int ist1 = 0; ist1 + 1 < emtf::NUM_STATIONS; ++ist1) { // station A
133  for (int ist2 = ist1 + 1; ist2 < emtf::NUM_STATIONS; ++ist2) { // station B
134  const EMTFHitCollection& conv_hitsA = st_conv_hits.at(ist1);
135  const EMTFHitCollection& conv_hitsB = st_conv_hits.at(ist2);
136 
137  // More than 1 hit per station when hit has ambigous theta
138  for (const auto& conv_hitA : conv_hitsA) {
139  for (const auto& conv_hitB : conv_hitsB) {
140  // bool has_rpc = (conv_hitA.Subsystem() == TriggerPrimitive::kRPC || conv_hitB.Subsystem() == TriggerPrimitive::kRPC);
141 
142  // Calculate theta deltas
143  int thA = conv_hitA.Theta_fp();
144  int thB = conv_hitB.Theta_fp();
145  int dth = abs_diff(thA, thB);
146  int dth_sign = (thA <= thB); // sign
147  emtf_assert(thA != 0 && thB != 0);
148  emtf_assert(dth < invalid_dtheta);
149 
150  if (best_dtheta_arr.at(ipair) >= dth) {
151  best_dtheta_arr.at(ipair) = dth;
152  best_dtheta_sign_arr.at(ipair) = dth_sign;
153  best_dtheta_valid_arr.at(ipair) = true;
154  // best_has_rpc_arr.at(ipair) = has_rpc; // FW doesn't currently check whether a segment is CSC or RPC
155 
156  // first 3 pairs, use station B
157  // last 3 pairs, use station A
158  best_theta_arr.at(ipair) = (ipair < 3) ? thB : thA;
159  }
160 
161  // Calculate phi deltas
162  int phA = conv_hitA.Phi_fp();
163  int phB = conv_hitB.Phi_fp();
164  int dph = abs_diff(phA, phB);
165  int dph_sign = (phA <= phB);
166 
167  if (best_dphi_arr.at(ipair) >= dph) {
168  best_dphi_arr.at(ipair) = dph;
169  best_dphi_sign_arr.at(ipair) = dph_sign;
170 
171  // first 3 pairs, use station B
172  // last 3 pairs, use station A
173  best_phi_arr.at(ipair) = (ipair < 3) ? phB : phA;
174  }
175  } // end loop over conv_hits in station B
176  } // end loop over conv_hits in station A
177 
178  ++ipair;
179  } // end loop over station B
180  } // end loop over station A
182 
183  // Apply cuts on dtheta
184 
185  // There is a possible bug in FW. After a dtheta pair fails the theta window
186  // cut, the valid flag of the pair is not updated. Later on, theta from
187  // this pair is used to assign the precise theta of the track.
188  std::array<bool, emtf::NUM_STATION_PAIRS> best_dtheta_valid_arr_1;
189 
190  for (int ipair = 0; ipair < emtf::NUM_STATION_PAIRS; ++ipair) {
191  if (izone == 0) // Tighter theta window for Zone 0 (Ring 1), where there are no RPCs
192  best_dtheta_valid_arr_1.at(ipair) =
193  best_dtheta_valid_arr.at(ipair) && (best_dtheta_arr.at(ipair) <= thetaWindowZone0_);
194  else
195  best_dtheta_valid_arr_1.at(ipair) =
196  best_dtheta_valid_arr.at(ipair) && (best_dtheta_arr.at(ipair) <= thetaWindow_);
197  }
198 
199  // Find valid segments
200  // vmask contains valid station mask = {ME4,ME3,ME2,ME1}. "0b" prefix for binary.
201  int vmask1 = 0, vmask2 = 0, vmask3 = 0;
202 
203  if (best_dtheta_valid_arr_1.at(0)) {
204  vmask1 |= 0b0011; // 12
205  }
206  if (best_dtheta_valid_arr_1.at(1)) {
207  vmask1 |= 0b0101; // 13
208  }
209  if (best_dtheta_valid_arr_1.at(2)) {
210  vmask1 |= 0b1001; // 14
211  }
212  if (best_dtheta_valid_arr_1.at(3)) {
213  vmask2 |= 0b0110; // 23
214  }
215  if (best_dtheta_valid_arr_1.at(4)) {
216  vmask2 |= 0b1010; // 24
217  }
218  if (best_dtheta_valid_arr_1.at(5)) {
219  vmask3 |= 0b1100; // 34
220  }
221 
222  // merge station masks only if they share bits
223  // Station 1 hits pass if any dTheta1X values pass
224  // Station 2 hits pass if any dTheta2X values pass, *EXCEPT* the following cases:
225  // Only {13, 24} pass, only {13, 24, 34} pass,
226  // Only {14, 23} pass, only {14, 23, 34} pass.
227  // Station 3 hits pass if any dTheta3X values pass, *EXCEPT* the following cases:
228  // Only {12, 34} pass, only {14, 23} pass.
229  // Station 4 hits pass if any dTheta4X values pass, *EXCEPT* the following cases:
230  // Only {12, 34} pass, only {13, 24} pass.
231  int vstat = vmask1; // valid stations based on th coordinates
232  if ((vstat & vmask2) != 0 || vstat == 0)
233  vstat |= vmask2;
234  if ((vstat & vmask3) != 0 || vstat == 0)
235  vstat |= vmask3;
236 
237  // Truth table to remove ambiguity in passing the dTheta window cut when there are
238  // two LCTs in the same station with the same phi value, but different theta values
239  static const int trk_bld[64] = {
240  0b1111, 0b0111, 0b0111, 0b0111, 0b1011, 0b0011, 0b1110, 0b0011, 0b0111, 0b0111, 0b0111, 0b0111, 0b1011,
241  0b0011, 0b0011, 0b0011, 0b1011, 0b1101, 0b0011, 0b0011, 0b1011, 0b0011, 0b0011, 0b0011, 0b1011, 0b0011,
242  0b0011, 0b0011, 0b1011, 0b0011, 0b0011, 0b0011, 0b1101, 0b1101, 0b1110, 0b0101, 0b1110, 0b1001, 0b1110,
243  0b0110, 0b0101, 0b0101, 0b0101, 0b0101, 0b1001, 0b1001, 0b0110, 0b0110, 0b1101, 0b1101, 0b0101, 0b0101,
244  0b1001, 0b1001, 0b1010, 0b1100, 0b0101, 0b0101, 0b0101, 0b0101, 0b1001, 0b1001, 0b1010, 0b0000};
245 
246  if (not bugAmbigThetaWin_) { // Fixed at the beginning of 2018
247  // construct bad delta word
248  // dth_bad = {12,23,34,13,14,24}
249  unsigned dth_bad = 0b111111; // "1" is bad. if valid, change to "0" (good)
250  if (best_dtheta_valid_arr_1.at(0)) {
251  dth_bad &= (~(1 << 5)); // 12
252  }
253  if (best_dtheta_valid_arr_1.at(1)) {
254  dth_bad &= (~(1 << 2)); // 13
255  }
256  if (best_dtheta_valid_arr_1.at(2)) {
257  dth_bad &= (~(1 << 1)); // 14
258  }
259  if (best_dtheta_valid_arr_1.at(3)) {
260  dth_bad &= (~(1 << 4)); // 23
261  }
262  if (best_dtheta_valid_arr_1.at(4)) {
263  dth_bad &= (~(1 << 0)); // 24
264  }
265  if (best_dtheta_valid_arr_1.at(5)) {
266  dth_bad &= (~(1 << 3)); // 34
267  }
268  emtf_assert(dth_bad < 64);
269 
270  // extract station mask from LUT
271  vstat = trk_bld[dth_bad];
272  }
273 
274  // remove valid flag for station if hit does not pass the dTheta mask
275  for (int istation = 0; istation < emtf::NUM_STATIONS; ++istation) {
276  if ((vstat & (1 << istation)) == 0) { // station bit not set
277  st_conv_hits.at(istation).clear();
278  }
279  }
280 
281  // assign precise phi and theta for the track
282  int phi_fp = 0;
283  int theta_fp = 0;
284  int best_pair = -1;
285 
286  if ((vstat & (1 << 1)) != 0) { // ME2 present
287  if (best_dtheta_valid_arr.at(0)) // 12
288  best_pair = 0;
289  else if (best_dtheta_valid_arr.at(3)) // 23
290  best_pair = 3;
291  else if (best_dtheta_valid_arr.at(4)) // 24
292  best_pair = 4;
293  } else if ((vstat & (1 << 2)) != 0) { // ME3 present
294  if (best_dtheta_valid_arr.at(1)) // 13
295  best_pair = 1;
296  else if (best_dtheta_valid_arr.at(5)) // 34
297  best_pair = 5;
298  } else if ((vstat & (1 << 3)) != 0) { // ME4 present
299  if (best_dtheta_valid_arr.at(2)) // 14
300  best_pair = 2;
301  }
302 
303  // // Possible logic preferring CSC LCTs for the track theta and phi assignment
304  // if ((vstat & (1<<1)) != 0) { // ME2 present
305  // if (!best_has_rpc_arr.at(0) && best_dtheta_valid_arr.at(0)) // 12, no RPC
306  // best_pair = 0;
307  // else if (!best_has_rpc_arr.at(3) && best_dtheta_valid_arr.at(3)) // 23, no RPC
308  // best_pair = 3;
309  // else if (!best_has_rpc_arr.at(4) && best_dtheta_valid_arr.at(4)) // 24, no RPC
310  // best_pair = 4;
311  // else if (best_dtheta_valid_arr.at(0)) // 12, has RPC
312  // best_pair = 0;
313  // else if (best_dtheta_valid_arr.at(3)) // 23, has RPC
314  // best_pair = 3;
315  // else if (best_dtheta_valid_arr.at(4)) // 24, has RPC
316  // best_pair = 4;
317  // } else if ((vstat & (1<<2)) != 0) { // ME3 present
318  // if (!best_has_rpc_arr.at(1) && best_dtheta_valid_arr.at(1)) // 13, no RPC
319  // best_pair = 1;
320  // else if (!best_has_rpc_arr.at(5) && best_dtheta_valid_arr.at(5)) // 34, no RPC
321  // best_pair = 5;
322  // else if (best_dtheta_valid_arr.at(1)) // 13, has RPC
323  // best_pair = 1;
324  // else if (best_dtheta_valid_arr.at(5)) // 34, has RPC
325  // best_pair = 5;
326  // } else if ((vstat & (1<<3)) != 0) { // ME4 present
327  // if (best_dtheta_valid_arr.at(2)) // 14
328  // best_pair = 2;
329  // }
330 
331  if (best_pair != -1) {
332  phi_fp = best_phi_arr.at(best_pair);
333  theta_fp = best_theta_arr.at(best_pair);
334  emtf_assert(theta_fp != 0);
335 
336  // In firmware, the track is associated to LCTs by the segment number, which
337  // identifies the best strip, but does not resolve the ambiguity in theta.
338  // In emulator, this additional logic also resolves the ambiguity in theta.
339  struct {
340  typedef EMTFHit value_type;
341  bool operator()(const value_type& lhs, const value_type& rhs) const {
342  return std::abs(lhs.Theta_fp() - theta) < std::abs(rhs.Theta_fp() - theta);
343  }
344  int theta;
345  } less_dtheta_cmp;
346  less_dtheta_cmp.theta = theta_fp; // capture
347 
348  for (int istation = 0; istation < emtf::NUM_STATIONS; ++istation) {
349  std::stable_sort(st_conv_hits.at(istation).begin(), st_conv_hits.at(istation).end(), less_dtheta_cmp);
350  if (st_conv_hits.at(istation).size() > 1)
351  st_conv_hits.at(istation).resize(1); // just the minimum in dtheta
352  }
353  }
354 
355  // update rank taking into account available stations after theta deltas
356  // keep straightness as it was
357  int old_rank = (track.Rank() << 1); // output rank is one bit longer than input rank, to accomodate ME4 separately
358  int rank = ((((old_rank >> 6) & 1) << 6) | // straightness
359  (((old_rank >> 4) & 1) << 4) | // straightness
360  (((old_rank >> 2) & 1) << 2) | // straightness
361  (((vstat >> 0) & 1) << 5) | // ME1
362  (((vstat >> 1) & 1) << 3) | // ME2
363  (((vstat >> 2) & 1) << 1) | // ME3
364  (((vstat >> 3) & 1) << 0) // ME4
365  );
366 
367  int mode = ((((vstat >> 0) & 1) << 3) | // ME1
368  (((vstat >> 1) & 1) << 2) | // ME2
369  (((vstat >> 2) & 1) << 1) | // ME3
370  (((vstat >> 3) & 1) << 0) // ME4
371  );
372 
373  int mode_inv = vstat;
374 
375  // if less than 2 segments, kill rank
376  if (vstat == 0b0001 || vstat == 0b0010 || vstat == 0b0100 || vstat == 0b1000 || vstat == 0)
377  rank = 0;
378 
379  // From RecoMuon/DetLayers/src/MuonCSCDetLayerGeometryBuilder.cc
380  auto isFront = [](int station, int ring, int chamber, int subsystem) {
381  // // RPCs are behind the CSCs in stations 1, 3, and 4; in front in 2
382  // if (subsystem == TriggerPrimitive::kRPC)
383  // return (station == 2);
384 
385  // In EMTF firmware, RPC hits are treated as if they came from the corresponding
386  // CSC chamber, so the FR bit assignment is the same as for CSCs - AWB 06.06.17
387 
388  // GEMs are in front of the CSCs
389  if (subsystem == L1TMuon::kGEM)
390  return true;
391 
392  bool result = false;
393  bool isOverlapping = !(station == 1 && ring == 3);
394  // not overlapping means back
395  if (isOverlapping) {
396  bool isEven = (chamber % 2 == 0);
397  // odd chambers are bolted to the iron, which faces
398  // forward in 1&2, backward in 3&4, so...
399  result = (station < 3) ? isEven : !isEven;
400  }
401  return result;
402  };
403 
404  // Fill ptlut_data
405  EMTFPtLUT ptlut_data = {};
406  for (int i = 0; i < emtf::NUM_STATION_PAIRS; ++i) {
407  ptlut_data.delta_ph[i] = best_dphi_arr.at(i);
408  ptlut_data.sign_ph[i] = best_dphi_sign_arr.at(i);
409  ptlut_data.delta_th[i] = best_dtheta_arr.at(i);
410  ptlut_data.sign_th[i] = best_dtheta_sign_arr.at(i);
411  }
412 
413  for (int i = 0; i < emtf::NUM_STATIONS; ++i) {
414  const auto& v = st_conv_hits.at(i);
415  ptlut_data.cpattern[i] = v.empty() ? 0 : v.front().Pattern(); // Automatically set to 0 for RPCs
416  ptlut_data.csign[i] = v.empty() ? 0 : v.front().Bend(); // Automatically set to 0 for RPCs
417  ptlut_data.slope[i] = v.empty() ? 0 : v.front().Slope(); // Automatically set to 0 for RPCs
418  ptlut_data.fr[i] =
419  v.empty() ? 0 : isFront(v.front().Station(), v.front().Ring(), v.front().Chamber(), v.front().Subsystem());
420  if (i == 0)
421  ptlut_data.st1_ring2 =
422  v.empty() ? 0 : (v.front().Station() == 1 && (v.front().Ring() == 2 || v.front().Ring() == 3));
423  }
424 
425  for (int i = 0; i < emtf::NUM_STATIONS + 1; ++i) { // 'bt' arrays use 5-station convention
426  ptlut_data.bt_vi[i] = 0;
427  ptlut_data.bt_hi[i] = 0;
428  ptlut_data.bt_ci[i] = 0;
429  ptlut_data.bt_si[i] = 0;
430  }
431 
432  for (int i = 0; i < emtf::NUM_STATIONS; ++i) {
433  const auto& v = st_conv_hits.at(i);
434  if (!v.empty()) {
435  int bt_station = v.front().BT_station();
436  emtf_assert(0 <= bt_station && bt_station <= 4);
437 
438  int bt_segment = v.front().BT_segment();
439  ptlut_data.bt_vi[bt_station] = 1;
440  ptlut_data.bt_hi[bt_station] = (bt_segment >> 5) & 0x3;
441  ptlut_data.bt_ci[bt_station] = (bt_segment >> 1) & 0xf;
442  ptlut_data.bt_si[bt_station] = (bt_segment >> 0) & 0x1;
443  }
444  }
445 
446  // ___________________________________________________________________________
447  // Output
448 
449  track.set_rank(rank);
450  track.set_mode(mode);
451  track.set_mode_inv(mode_inv);
452  track.set_phi_fp(phi_fp);
453  track.set_theta_fp(theta_fp);
454  track.set_PtLUT(ptlut_data);
455 
456  track.set_phi_loc(emtf::calc_phi_loc_deg(phi_fp));
457  track.set_phi_glob(emtf::calc_phi_glob_deg(track.Phi_loc(), track.Sector()));
458  track.set_theta(emtf::calc_theta_deg_from_int(theta_fp));
459  track.set_eta(emtf::calc_eta_from_theta_deg(track.Theta(), track.Endcap()));
460 
461  // Only keep the best segments
462  track.clear_Hits();
463 
464  EMTFHitCollection tmp_hits = track.Hits();
465  flatten_container(st_conv_hits, tmp_hits);
466  track.set_Hits(tmp_hits);
467 }
constexpr int NUM_STATION_PAIRS
Definition: Common.h:59
uint16_t bt_si[5]
Definition: EMTFTrack.h:41
uint16_t bt_ci[5]
Definition: EMTFTrack.h:40
uint16_t sign_ph[6]
Definition: EMTFTrack.h:32
uint16_t bt_vi[5]
Definition: EMTFTrack.h:38
double calc_phi_loc_deg(int bits)
Definition: TrackTools.h:180
l1t::EMTFHitCollection EMTFHitCollection
Definition: Common.h:23
uint16_t delta_ph[6]
Definition: EMTFTrack.h:30
uint16_t delta_th[6]
Definition: EMTFTrack.h:31
double calc_theta_deg_from_int(int theta_int)
Definition: TrackTools.h:132
uint16_t slope[4]
Definition: EMTFTrack.h:36
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
uint16_t cpattern[4]
Definition: EMTFTrack.h:34
double calc_phi_glob_deg(double loc, int sector)
Definition: TrackTools.h:170
uint16_t fr[4]
Definition: EMTFTrack.h:37
uint16_t sign_th[6]
Definition: EMTFTrack.h:33
uint16_t st1_ring2
Definition: EMTFTrack.h:28
#define emtf_assert(expr)
Definition: DebugTools.h:18
double b
Definition: hdecay.h:120
double calc_eta_from_theta_deg(double theta_deg, int endcap)
Definition: TrackTools.h:117
constexpr int NUM_STATIONS
Definition: Common.h:58
double a
Definition: hdecay.h:121
uint16_t csign[4]
Definition: EMTFTrack.h:35
uint16_t bt_hi[5]
Definition: EMTFTrack.h:39
Geom::Theta< T > theta() const

◆ calculate_bx()

void AngleCalculation::calculate_bx ( EMTFTrack track) const

Definition at line 469 of file AngleCalculation.cc.

References bx_, bxWindow_, counter, emtf_assert, mps_fire::i, and HLT_2023v12_cff::track.

Referenced by process().

469  {
470  const int delayBX = bxWindow_ - 1;
471  emtf_assert(delayBX >= 0);
472  std::vector<int> counter(delayBX + 1, 0);
473 
474  for (const auto& conv_hit : track.Hits()) {
475  for (int i = delayBX; i >= 0; i--) {
476  if (conv_hit.BX() <= bx_ - i)
477  counter.at(i) += 1; // Count stubs delayed by i BX or more
478  }
479  }
480 
481  int first_bx = bx_ - delayBX;
482  int second_bx = 99;
483  for (int i = delayBX; i >= 0; i--) {
484  if (counter.at(i) >= 2) { // If 2 or more stubs are delayed by i BX or more
485  second_bx = bx_ - i; // if i == delayBX, analyze immediately
486  break;
487  }
488  }
489  emtf_assert(second_bx != 99);
490 
491  // ___________________________________________________________________________
492  // Output
493 
494  track.set_first_bx(first_bx);
495  track.set_second_bx(second_bx);
496 }
#define emtf_assert(expr)
Definition: DebugTools.h:18
static std::atomic< unsigned int > counter

◆ configure()

void AngleCalculation::configure ( int  verbose,
int  endcap,
int  sector,
int  bx,
int  bxWindow,
int  thetaWindow,
int  thetaWindowZone0,
bool  bugME11Dupes,
bool  bugAmbigThetaWin,
bool  twoStationSameBX 
)

Definition at line 12 of file AngleCalculation.cc.

References bugAmbigThetaWin_, bugME11Dupes_, nano_mu_digi_cff::bx, bx_, bxWindow_, makeMuonMisalignmentScenario::endcap, endcap_, nano_mu_digi_cff::sector, sector_, thetaWindow_, thetaWindowZone0_, twoStationSameBX_, verbose, and verbose_.

Referenced by SectorProcessor::process_single_bx().

21  {
22  verbose_ = verbose;
23  endcap_ = endcap;
24  sector_ = sector;
25  bx_ = bx;
26 
27  bxWindow_ = bxWindow;
28  thetaWindow_ = thetaWindow;
29  thetaWindowZone0_ = thetaWindowZone0;
30  bugME11Dupes_ = bugME11Dupes;
31  bugAmbigThetaWin_ = bugAmbigThetaWin;
32  twoStationSameBX_ = twoStationSameBX;
33 }
bool verbose

◆ erase_tracks()

void AngleCalculation::erase_tracks ( EMTFTrackCollection tracks) const

Definition at line 498 of file AngleCalculation.cc.

References emtf_assert, emtf::NUM_STATIONS, HLT_2023v12_cff::track, pwdgSkimBPark_cfi::tracks, twoStationSameBX_, and x.

Referenced by process().

498  {
499  // Erase tracks with rank == 0
500  // using erase-remove idiom
501  struct {
502  typedef EMTFTrack value_type;
503  bool operator()(const value_type& x) const { return (x.Rank() == 0); }
504  } rank_zero_pred;
505 
506  // Erase two-station tracks with hits in different BX
507  struct {
508  typedef EMTFTrack value_type;
509  bool operator()(const value_type& x) const {
510  return (x.NumHits() == 2 && x.Hits().at(0).BX() != x.Hits().at(1).BX());
511  }
512  } two_station_mistime;
513 
514  tracks.erase(std::remove_if(tracks.begin(), tracks.end(), rank_zero_pred), tracks.end());
515 
516  if (twoStationSameBX_) { // Modified at the beginning of 2018
517  tracks.erase(std::remove_if(tracks.begin(), tracks.end(), two_station_mistime), tracks.end());
518  }
519 
520  for (const auto& track : tracks) {
521  emtf_assert(!track.Hits().empty());
522  emtf_assert(track.Hits().size() <= emtf::NUM_STATIONS);
523  }
524 }
#define emtf_assert(expr)
Definition: DebugTools.h:18
constexpr int NUM_STATIONS
Definition: Common.h:58

◆ process()

void AngleCalculation::process ( emtf::zone_array< EMTFTrackCollection > &  zone_tracks) const

Definition at line 35 of file AngleCalculation.cc.

References calculate_angles(), calculate_bx(), gather_cfg::cout, erase_tracks(), emtf::NUM_ZONES, to_hex(), HLT_2023v12_cff::track, pwdgSkimBPark_cfi::tracks, and verbose_.

Referenced by SectorProcessor::process_single_bx().

35  {
36  for (int izone = 0; izone < emtf::NUM_ZONES; ++izone) {
37  EMTFTrackCollection& tracks = zone_tracks.at(izone); // pass by reference
38 
39  EMTFTrackCollection::iterator tracks_it = tracks.begin();
40  EMTFTrackCollection::iterator tracks_end = tracks.end();
41 
42  // Calculate deltas
43  for (; tracks_it != tracks_end; ++tracks_it) {
44  calculate_angles(*tracks_it, izone);
45  }
46 
47  // Erase tracks with rank = 0
48  // Erase hits that are not selected as the best phi and theta in each station
49  // Erase two-station tracks with hits in different BX (2018)
51 
52  tracks_it = tracks.begin();
53  tracks_end = tracks.end();
54 
55  // Calculate bx
56  // (in the firmware, this happens during best track selection.)
57  for (; tracks_it != tracks_end; ++tracks_it) {
58  calculate_bx(*tracks_it);
59  }
60  } // end loop over zones
61 
62  if (verbose_ > 0) { // debug
63  for (const auto& tracks : zone_tracks) {
64  for (const auto& track : tracks) {
65  std::cout << "deltas: z: " << track.Zone() - 1 << " pat: " << track.Winner()
66  << " rank: " << to_hex(track.Rank()) << " delta_ph: " << array_as_string(track.PtLUT().delta_ph)
67  << " delta_th: " << array_as_string(track.PtLUT().delta_th)
68  << " sign_ph: " << array_as_string(track.PtLUT().sign_ph)
69  << " sign_th: " << array_as_string(track.PtLUT().sign_th) << " phi: " << track.Phi_fp()
70  << " theta: " << track.Theta_fp() << " cpat: " << array_as_string(track.PtLUT().cpattern)
71  << " v: " << array_as_string(track.PtLUT().bt_vi) << " h: " << array_as_string(track.PtLUT().bt_hi)
72  << " c: " << array_as_string(track.PtLUT().bt_ci) << " s: " << array_as_string(track.PtLUT().bt_si)
73  << std::endl;
74  }
75  }
76  }
77 }
static char to_hex(unsigned int i)
Definition: types.cc:26
l1t::EMTFTrackCollection EMTFTrackCollection
Definition: Common.h:27
constexpr int NUM_ZONES
Definition: Common.h:54
void calculate_bx(EMTFTrack &track) const
void calculate_angles(EMTFTrack &track, const int izone) const
void erase_tracks(EMTFTrackCollection &tracks) const

Member Data Documentation

◆ bugAmbigThetaWin_

bool AngleCalculation::bugAmbigThetaWin_
private

Definition at line 32 of file AngleCalculation.h.

Referenced by calculate_angles(), and configure().

◆ bugME11Dupes_

bool AngleCalculation::bugME11Dupes_
private

Definition at line 32 of file AngleCalculation.h.

Referenced by calculate_angles(), and configure().

◆ bx_

int AngleCalculation::bx_
private

Definition at line 28 of file AngleCalculation.h.

Referenced by calculate_bx(), and configure().

◆ bxWindow_

int AngleCalculation::bxWindow_
private

Definition at line 30 of file AngleCalculation.h.

Referenced by calculate_bx(), and configure().

◆ endcap_

int AngleCalculation::endcap_
private

Definition at line 28 of file AngleCalculation.h.

Referenced by configure().

◆ sector_

int AngleCalculation::sector_
private

Definition at line 28 of file AngleCalculation.h.

Referenced by configure().

◆ thetaWindow_

int AngleCalculation::thetaWindow_
private

Definition at line 31 of file AngleCalculation.h.

Referenced by calculate_angles(), and configure().

◆ thetaWindowZone0_

int AngleCalculation::thetaWindowZone0_
private

Definition at line 31 of file AngleCalculation.h.

Referenced by calculate_angles(), and configure().

◆ twoStationSameBX_

bool AngleCalculation::twoStationSameBX_
private

Definition at line 32 of file AngleCalculation.h.

Referenced by configure(), and erase_tracks().

◆ verbose_

int AngleCalculation::verbose_
private

Definition at line 28 of file AngleCalculation.h.

Referenced by configure(), and process().