CMS 3D CMS Logo

MatchProcessor.cc
Go to the documentation of this file.
1 // MatchProcessor
3 //
4 // This module is the combined version of the PR+ME+MC
5 // See more in execute()
6 //
7 // Variables such as `best_ideltaphi_barrel` store the "global"
8 // best value for delta phi, r, z, and r*phi, for instances
9 // where the same tracklet has multiple stub pairs. This allows
10 // us to find the truly best match
12 
17 
22 
23 #include <filesystem>
24 
25 using namespace std;
26 using namespace trklet;
27 
28 MatchProcessor::MatchProcessor(string name, Settings const& settings, Globals* global)
29  : ProcessBase(name, settings, global),
30  phimatchcuttable_(settings),
31  zmatchcuttable_(settings),
32  rphicutPStable_(settings),
33  rphicut2Stable_(settings),
34  rcutPStable_(settings),
35  rcut2Stable_(settings),
36  alphainner_(settings),
37  alphaouter_(settings),
38  rSSinner_(settings),
39  rSSouter_(settings),
40  diskRadius_(settings),
41  fullmatches_(12),
42  rinvbendlut_(settings),
43  luttable_(settings),
44  inputProjBuffer_(3) {
45  phiregion_ = name[8] - 'A';
46 
48 
50 
53 
54  if (barrel_) {
57  } else {
60  }
61 
63 
64  nrbits_ = 5;
65  nphiderbits_ = 6;
66 
67  nrprojbits_ = 8;
68 
69  if (!barrel_) {
72  }
73 
74  nrinv_ = NRINVBITS;
75 
76  unsigned int region = getName()[8] - 'A';
78 
79  if (barrel_) {
80  phimatchcuttable_.initmatchcut(layerdisk_, TrackletLUT::MatchType::barrelphi, region);
81  zmatchcuttable_.initmatchcut(layerdisk_, TrackletLUT::MatchType::barrelz, region);
82  } else {
83  rphicutPStable_.initmatchcut(layerdisk_, TrackletLUT::MatchType::diskPSphi, region);
84  rphicut2Stable_.initmatchcut(layerdisk_, TrackletLUT::MatchType::disk2Sphi, region);
85  rcutPStable_.initmatchcut(layerdisk_, TrackletLUT::MatchType::diskPSr, region);
86  rcut2Stable_.initmatchcut(layerdisk_, TrackletLUT::MatchType::disk2Sr, region);
87  alphainner_.initmatchcut(layerdisk_, TrackletLUT::MatchType::alphainner, region);
88  alphaouter_.initmatchcut(layerdisk_, TrackletLUT::MatchType::alphaouter, region);
89  rSSinner_.initmatchcut(layerdisk_, TrackletLUT::MatchType::rSSinner, region);
90  rSSouter_.initmatchcut(layerdisk_, TrackletLUT::MatchType::rSSouter, region);
92  }
93 
94  for (unsigned int i = 0; i < N_DSS_MOD * 2; i++) {
96  (1 << (settings_.nbitsalpha() - 1)) / (settings_.rDSSinner(i) * settings_.rDSSinner(i)) /
97  settings_.kphi();
99  (1 << (settings_.nbitsalpha() - 1)) / (settings_.rDSSouter(i) * settings_.rDSSouter(i)) /
100  settings_.kphi();
101  }
102 
106 
107  nMatchEngines_ = 4;
108  for (unsigned int iME = 0; iME < nMatchEngines_; iME++) {
110  tmpME.setimeu(iME);
111  matchengines_.push_back(tmpME);
112  }
113 
114  // Pick some initial large values
115  best_ideltaphi_barrel = 0xFFFF;
116  best_ideltaz_barrel = 0xFFFF;
117  best_ideltaphi_disk = 0xFFFF;
118  best_ideltar_disk = 0xFFFF;
119  curr_tracklet = nullptr;
120  next_tracklet = nullptr;
121 }
122 
124  if (settings_.writetrace()) {
125  edm::LogVerbatim("Tracklet") << "In " << name_ << " adding output to " << memory->getName() << " to output "
126  << output;
127  }
128  if (output.find("matchout") != std::string::npos) {
129  auto* tmp = dynamic_cast<FullMatchMemory*>(memory);
130  assert(tmp != nullptr);
131  unsigned int iSeed = getISeed(tmp->getName());
132  assert(iSeed < fullmatches_.size());
133  assert(fullmatches_[iSeed] == nullptr);
134  fullmatches_[iSeed] = tmp;
135  return;
136  }
137  throw cms::Exception("BadConfig") << __FILE__ << " " << __LINE__ << " could not find output: " << output;
138 }
139 
141  if (settings_.writetrace()) {
142  edm::LogVerbatim("Tracklet") << "In " << name_ << " adding input from " << memory->getName() << " to input "
143  << input;
144  }
145  if (input == "allstubin") {
146  auto* tmp = dynamic_cast<AllStubsMemory*>(memory);
147  assert(tmp != nullptr);
148  allstubs_ = tmp;
149  return;
150  }
151  if (input == "vmstubin") {
152  auto* tmp = dynamic_cast<VMStubsMEMemory*>(memory);
153  assert(tmp != nullptr);
154  vmstubs_.push_back(tmp); //to allow more than one stub in? vmstubs_=tmp;
155  return;
156  }
157  if (input == "projin") {
158  auto* tmp = dynamic_cast<TrackletProjectionsMemory*>(memory);
159  assert(tmp != nullptr);
160  inputprojs_.push_back(tmp);
161  return;
162  }
163  throw cms::Exception("BadConfig") << __FILE__ << " " << __LINE__ << " could not find input: " << input;
164 }
165 
166 void MatchProcessor::execute(unsigned int iSector, double phimin) {
167  assert(vmstubs_.size() == 1);
168 
169  /*
170  The code is organized in three 'steps' corresponding to the PR, ME, and MC functions. The output from
171  the PR step is buffered in a 'circular' buffer, and similarly the ME output is put in a circular buffer.
172  The implementation is done in steps, emulating what can be done in firmware. On each step we do:
173 
174  1) A projection is read and if there is space it is insert into the inputProjBuffer_
175 
176  2) Process next match in the ME - if there is an idle ME the next projection is inserted
177 
178  3) Readout match from ME and send to match calculator
179 
180  However, for the pipelining to work in HLS these blocks are executed in reverse order
181 
182  */
183 
184  bool print = getName() == "MP_L3PHIC" && iSector == 3;
185  print = false;
186 
187  phimin_ = phimin;
188 
189  Tracklet* oldTracklet = nullptr;
190 
191  unsigned int countme = 0;
192  unsigned int countall = 0;
193  unsigned int countsel = 0;
194  unsigned int countinputproj = 0;
195 
196  unsigned int iprojmem = 0;
197  while (iprojmem < inputprojs_.size() && inputprojs_[iprojmem]->nTracklets() == 0) {
198  iprojmem++;
199  }
200 
201  unsigned int iproj = 0;
202 
203  inputProjBuffer_.reset();
204 
205  for (const auto& inputproj : inputprojs_) {
206  countinputproj += inputproj->nTracklets();
207  }
208 
209  for (auto& matchengine : matchengines_) {
210  matchengine.reset();
211  }
212 
213  ProjectionTemp tmpProj_, tmpProj__;
214  bool good_ = false;
215  bool good__ = false;
216 
217  for (unsigned int istep = 0; istep < settings_.maxStep("MP"); istep++) {
218  // This print statement is useful for detailed comparison with the HLS code
219  // It prints out detailed status information for each clock step
220  /*
221  if (print) {
222  cout << "istep = "<<istep<<" projBuff: "<<inputProjBuffer_.rptr()<<" "<<inputProjBuffer_.wptr()<<" "<<projBuffNearFull;
223  unsigned int iMEU = 0;
224  for (auto& matchengine : matchengines_) {
225  cout <<" MEU"<<iMEU<<": "<<matchengine.rptr()<<" "<<matchengine.wptr()
226  <<" "<<matchengine.idle()<<" "<<matchengine.empty()
227  <<" "<<matchengine.TCID();
228  iMEU++;
229  }
230  cout << std::endl;
231  }
232  */
233 
234  //First do some caching of state at the start of the clock
235 
236  bool projdone = false;
237 
238  bool projBuffNearFull = inputProjBuffer_.nearfull();
239 
240  for (unsigned int iME = 0; iME < nMatchEngines_; iME++) {
241  matchengines_[iME].setAlmostFull();
242  }
243 
244  //Step 3
245  //Check if we have candidate match to process
246 
247  unsigned int iMEbest = 0;
248  int bestTCID = matchengines_[0].TCID();
249  bool meactive = matchengines_[0].active();
250  for (unsigned int iME = 1; iME < nMatchEngines_; iME++) {
251  meactive = meactive || matchengines_[iME].active();
252  int tcid = matchengines_[iME].TCID();
253  if (tcid < bestTCID) {
254  bestTCID = tcid;
255  iMEbest = iME;
256  }
257  }
258 
259  // check if the matche engine processing the smallest tcid has match
260 
261  if (!matchengines_[iMEbest].empty()) {
262  std::pair<Tracklet*, const Stub*> candmatch = matchengines_[iMEbest].read();
263 
264  const Stub* fpgastub = candmatch.second;
265  Tracklet* tracklet = candmatch.first;
266 
267  //Consistency check
268  if (oldTracklet != nullptr) {
269  //allow equal here since we can have more than one cadidate match per tracklet projection
270  //cout << "old new : "<<oldTracklet->TCID()<<" "<<tracklet->TCID()<<" "<<iMEbest<<endl;
271  assert(oldTracklet->TCID() <= tracklet->TCID());
272  }
273  oldTracklet = tracklet;
274 
275  bool match = matchCalculator(tracklet, fpgastub, print, istep);
276 
277  if (settings_.debugTracklet() && match) {
278  edm::LogVerbatim("Tracklet") << getName() << " have match";
279  }
280 
281  countall++;
282  if (match)
283  countsel++;
284  }
285 
286  //Step 2
287  //Check if we have ME that can process projection
288 
289  bool addedProjection = false;
290  for (unsigned int iME = 0; iME < nMatchEngines_; iME++) {
291  if (!matchengines_[iME].idle())
292  countme++;
293  //if match engine empty and we have queued projections add to match engine
294  if ((!addedProjection) && matchengines_[iME].idle() && (!inputProjBuffer_.empty())) {
295  ProjectionTemp tmpProj = inputProjBuffer_.read();
296  VMStubsMEMemory* stubmem = vmstubs_[0];
297 
298  if (settings_.debugTracklet()) {
299  edm::LogVerbatim("Tracklet") << getName() << " adding projection to match engine";
300  }
301 
302  int nbins = (1 << N_RZBITS);
303  if (layerdisk_ >= N_LAYER) {
304  nbins *= 2; //twice as many bins in disks (since there are two disks)
305  }
306 
307  matchengines_[iME].init(stubmem,
308  nbins,
309  tmpProj.slot(),
310  tmpProj.iphi(),
311  tmpProj.shift(),
312  tmpProj.projrinv(),
313  tmpProj.projfinerz(),
314  tmpProj.projfinephi(),
315  tmpProj.use(0, 0),
316  tmpProj.use(0, 1),
317  tmpProj.use(1, 0),
318  tmpProj.use(1, 1),
319  tmpProj.isPSseed(),
320  tmpProj.proj());
321  meactive = true;
322  addedProjection = true;
323  } else {
324  matchengines_[iME].step();
325  }
326  matchengines_[iME].processPipeline();
327  }
328 
329  //Step 1
330  //First step here checks if we have more input projections to put into
331  //the input puffer for projections
332 
333  if (good__) {
334  inputProjBuffer_.store(tmpProj__);
335  }
336 
337  good__ = good_;
338  tmpProj__ = tmpProj_;
339 
340  good_ = false;
341 
342  if (iprojmem < inputprojs_.size()) {
343  TrackletProjectionsMemory* projMem = inputprojs_[iprojmem];
344  if (!projBuffNearFull) {
345  if (settings_.debugTracklet()) {
346  edm::LogVerbatim("Tracklet") << getName() << " have projection in memory : " << projMem->getName();
347  }
348 
349  Tracklet* proj = projMem->getTracklet(iproj);
350 
351  FPGAWord fpgaphi = proj->proj(layerdisk_).fpgaphiproj();
352 
353  unsigned int iphi = (fpgaphi.value() >> (fpgaphi.nbits() - nvmbits_)) & (nvmbins_ - 1);
354 
355  constexpr int nextrabits = 2;
356  int overlapbits = nvmbits_ + nextrabits;
357 
358  unsigned int extrabits = fpgaphi.bits(fpgaphi.nbits() - overlapbits - nextrabits, nextrabits);
359 
360  unsigned int ivmPlus = iphi;
361 
362  int shift = 0;
363 
364  if (extrabits == ((1U << nextrabits) - 1) && iphi != ((1U << settings_.nbitsvmme(layerdisk_)) - 1)) {
365  shift = 1;
366  ivmPlus++;
367  }
368  unsigned int ivmMinus = iphi;
369  if (extrabits == 0 && iphi != 0) {
370  shift = -1;
371  ivmMinus--;
372  }
373 
374  int projrinv = -1;
375  if (barrel_) {
376  FPGAWord phider = proj->proj(layerdisk_).fpgaphiprojder();
377  projrinv = (1 << (nrinv_ - 1)) - 1 - (phider.value() >> (phider.nbits() - nrinv_));
378  } else {
379  //The next lines looks up the predicted bend based on:
380  // 1 - r projections
381  // 2 - phi derivative
382  // 3 - the sign - i.e. if track is forward or backward
383 
384  int rindex =
385  (proj->proj(layerdisk_).fpgarzproj().value() >> (proj->proj(layerdisk_).fpgarzproj().nbits() - nrbits_)) &
386  ((1 << nrbits_) - 1);
387 
388  int phiprojder = proj->proj(layerdisk_).fpgaphiprojder().value();
389 
390  int phiderindex = (phiprojder >> (proj->proj(layerdisk_).fpgaphiprojder().nbits() - nphiderbits_)) &
391  ((1 << nphiderbits_) - 1);
392 
393  int signindex = proj->proj(layerdisk_).fpgarzprojder().value() < 0;
394 
395  int bendindex = (signindex << (nphiderbits_ + nrbits_)) + (rindex << (nphiderbits_)) + phiderindex;
396 
397  projrinv = rinvbendlut_.lookup(bendindex);
398 
399  proj->proj(layerdisk_).setBendIndex(projrinv);
400  }
401  assert(projrinv >= 0);
402 
403  unsigned int projfinephi =
404  (fpgaphi.value() >> (fpgaphi.nbits() - (nvmbits_ + NFINEPHIBITS))) & ((1 << NFINEPHIBITS) - 1);
405 
406  unsigned int slot;
407  bool second;
408  int projfinerz;
409 
410  if (barrel_) {
411  slot = proj->proj(layerdisk_).fpgarzbin1projvm().value();
412  second = proj->proj(layerdisk_).fpgarzbin2projvm().value();
413  projfinerz = proj->proj(layerdisk_).fpgafinerzvm().value();
414  } else {
415  //The -1 here is due to not using the full range of bits. Should be fixed.
416  unsigned int ir = proj->proj(layerdisk_).fpgarzproj().value() >>
417  (proj->proj(layerdisk_).fpgarzproj().nbits() - nrprojbits_ - 1);
418  unsigned int word = diskRadius_.lookup(ir);
419 
420  slot = (word >> 1) & ((1 << N_RZBITS) - 1);
421  if (proj->proj(layerdisk_).fpgarzprojder().value() < 0) {
422  slot += (1 << N_RZBITS);
423  }
424  second = word & 1;
425  projfinerz = word >> 4;
426  }
427 
428  bool isPSseed = proj->PSseed();
429 
430  int nbins = (1 << N_RZBITS);
431  if (layerdisk_ >= N_LAYER) {
432  nbins *= 2; //twice as many bins in disks (since there are two disks)
433  }
434 
435  VMStubsMEMemory* stubmem = vmstubs_[0];
436  bool usefirstMinus = stubmem->nStubsBin(ivmMinus * nbins + slot) != 0;
437  bool usesecondMinus = (second && (stubmem->nStubsBin(ivmMinus * nbins + slot + 1) != 0));
438  bool usefirstPlus = ivmPlus != ivmMinus && (stubmem->nStubsBin(ivmPlus * nbins + slot) != 0);
439  bool usesecondPlus = ivmPlus != ivmMinus && (second && (stubmem->nStubsBin(ivmPlus * nbins + slot + 1) != 0));
440 
441  good_ = usefirstPlus || usesecondPlus || usefirstMinus || usesecondMinus;
442 
443  if (good_) {
444  ProjectionTemp tmpProj(proj,
445  slot,
446  projrinv,
447  projfinerz,
448  projfinephi,
449  ivmMinus,
450  shift,
451  usefirstMinus,
452  usefirstPlus,
453  usesecondMinus,
454  usesecondPlus,
455  isPSseed);
456  tmpProj_ = tmpProj;
457  }
458 
459  iproj++;
460  if (iproj == projMem->nTracklets()) {
461  iproj = 0;
462  do {
463  iprojmem++;
464  } while (iprojmem < inputprojs_.size() && inputprojs_[iprojmem]->nTracklets() == 0);
465  }
466 
467  } else {
468  projdone = true && !good_ && !good__;
469  }
470  }
471 
472  //
473  // Check if done
474  //
475  //
476  //
477 
478  if ((projdone && !meactive && inputProjBuffer_.rptr() == inputProjBuffer_.wptr()) ||
479  (istep == settings_.maxStep("MP") - 1)) {
480  if (settings_.writeMonitorData("MP")) {
481  globals_->ofstream("matchprocessor.txt") << getName() << " " << istep << " " << countall << " " << countsel
482  << " " << countme << " " << countinputproj << endl;
483  }
484  break;
485  }
486  }
487 
488  if (settings_.writeMonitorData("MC")) {
489  globals_->ofstream("matchcalculator.txt") << getName() << " " << countall << " " << countsel << endl;
490  }
491 }
492 
493 bool MatchProcessor::matchCalculator(Tracklet* tracklet, const Stub* fpgastub, bool, unsigned int istep) {
494  const L1TStub* stub = fpgastub->l1tstub();
495 
496  if (layerdisk_ < N_LAYER) {
497  const Projection& proj = tracklet->proj(layerdisk_);
498  int ir = fpgastub->r().value();
499  int iphi = proj.fpgaphiproj().value();
500  int icorr = (ir * proj.fpgaphiprojder().value()) >> icorrshift_;
501  iphi += icorr;
502 
503  int iz = proj.fpgarzproj().value();
504  int izcor = (ir * proj.fpgarzprojder().value() + (1 << (icorzshift_ - 1))) >> icorzshift_;
505  iz += izcor;
506 
507  int ideltaz = fpgastub->z().value() - iz;
508  int ideltaphi = (fpgastub->phi().value() - iphi) << phishift_;
509 
510  //Floating point calculations
511 
512  double phi = stub->phi();
513  double r = stub->r();
514  double z = stub->z();
515 
516  if (settings_.useapprox()) {
517  double dphi = reco::reduceRange(phi - fpgastub->phiapprox(phimin_, 0.0));
518  assert(std::abs(dphi) < 0.001);
519  phi = fpgastub->phiapprox(phimin_, 0.0);
520  z = fpgastub->zapprox();
521  r = fpgastub->rapprox();
522  }
523 
524  if (phi < 0)
525  phi += 2 * M_PI;
526  phi -= phimin_;
527 
528  double dr = r - settings_.rmean(layerdisk_);
529  assert(std::abs(dr) < settings_.drmax());
530 
531  double dphi = reco::reduceRange(phi - (proj.phiproj() + dr * proj.phiprojder()));
532 
533  double dz = z - (proj.rzproj() + dr * proj.rzprojder());
534 
535  double dphiapprox = reco::reduceRange(phi - (proj.phiprojapprox() + dr * proj.phiprojderapprox()));
536 
537  double dzapprox = z - (proj.rzprojapprox() + dr * proj.rzprojderapprox());
538 
539  int seedindex = tracklet->getISeed();
541  next_tracklet = tracklet;
542 
543  // Do we have a new tracklet?
544  bool newtracklet = (istep == 0 || tracklet != curr_tracklet);
545  if (istep == 0)
546  best_ideltar_disk = (1 << (fpgastub->r().nbits() - 1)); // Set to the maximum possible
547  // If so, replace the "best" values with the cut tables
548  if (newtracklet) {
551  }
552 
553  assert(phimatchcuttable_.lookup(seedindex) > 0);
554  assert(zmatchcuttable_.lookup(seedindex) > 0);
555 
556  if (settings_.bookHistos()) {
557  bool truthmatch = tracklet->stubtruthmatch(stub);
558 
560  hists->FillLayerResidual(layerdisk_ + 1,
561  seedindex,
562  dphiapprox * settings_.rmean(layerdisk_),
563  ideltaphi * settings_.kphi1() * settings_.rmean(layerdisk_),
564  (ideltaz << dzshift_) * settings_.kz(),
565  dz,
566  truthmatch);
567  }
568 
569  if (settings_.writeMonitorData("Residuals")) {
570  double pt = 0.01 * settings_.c() * settings_.bfield() / std::abs(tracklet->rinv());
571 
572  globals_->ofstream("layerresiduals.txt")
573  << layerdisk_ + 1 << " " << seedindex << " " << pt << " "
574  << ideltaphi * settings_.kphi1() * settings_.rmean(layerdisk_) << " "
575  << dphiapprox * settings_.rmean(layerdisk_) << " "
576  << phimatchcuttable_.lookup(seedindex) * settings_.kphi1() * settings_.rmean(layerdisk_) << " "
577  << (ideltaz << dzshift_) * settings_.kz() << " " << dz << " "
578  << zmatchcuttable_.lookup(seedindex) * settings_.kz() << endl;
579  }
580 
581  bool imatch = (std::abs(ideltaphi) <= best_ideltaphi_barrel && (ideltaz << dzshift_ < best_ideltaz_barrel) &&
582  (ideltaz << dzshift_ >= -best_ideltaz_barrel));
583  // Update the "best" values
584  if (imatch) {
585  best_ideltaphi_barrel = std::abs(ideltaphi);
586  best_ideltaz_barrel = std::abs(ideltaz << dzshift_);
587  }
588 
589  if (settings_.debugTracklet()) {
590  edm::LogVerbatim("Tracklet") << getName() << " imatch = " << imatch << " ideltaphi cut " << ideltaphi << " "
591  << phimatchcuttable_.lookup(seedindex) << " ideltaz<<dzshift cut "
592  << (ideltaz << dzshift_) << " " << zmatchcuttable_.lookup(seedindex);
593  }
594 
595  //This would catch significant consistency problems in the configuration - helps to debug if there are problems.
596  if (std::abs(dphi) > 0.5 * settings_.dphisectorHG() || std::abs(dphiapprox) > 0.5 * settings_.dphisectorHG()) {
597  throw cms::Exception("LogicError") << "WARNING dphi and/or dphiapprox too large : " << dphi << " " << dphiapprox
598  << endl;
599  }
600 
601  bool keep = true;
602  if (!settings_.doKF() || !settings_.doMultipleMatches()) {
603  // Case of allowing only one stub per track per layer (or no KF which implies the same).
604  if (imatch && tracklet->match(layerdisk_)) {
605  // Veto match if is not the best one for this tracklet (in given layer)
606  auto res = tracklet->resid(layerdisk_);
607  keep = abs(ideltaphi) < abs(res.fpgaphiresid().value());
608  imatch = keep;
609  }
610  }
611 
612  if (imatch) {
613  tracklet->addMatch(layerdisk_,
614  ideltaphi,
615  ideltaz,
616  dphi,
617  dz,
618  dphiapprox,
619  dzapprox,
620  (phiregion_ << N_BITSMEMADDRESS) + fpgastub->stubindex().value(),
621  fpgastub);
622 
623  if (settings_.debugTracklet()) {
624  edm::LogVerbatim("Tracklet") << "Accepted full match in layer " << getName() << " " << tracklet;
625  }
626 
627  int iSeed = tracklet->getISeed();
628  assert(fullmatches_[iSeed] != nullptr);
629  fullmatches_[iSeed]->addMatch(tracklet, fpgastub);
630 
631  return true;
632  } else {
633  return false;
634  }
635  } else { //disk matches
636 
637  //check that stubs and projections in same half of detector
638  assert(stub->z() * tracklet->t() > 0.0);
639 
640  int sign = (tracklet->t() > 0.0) ? 1 : -1;
641  int disk = sign * (layerdisk_ - N_LAYER + 1);
642  assert(disk != 0);
643 
644  //Perform integer calculations here
645 
646  int iz = fpgastub->z().value();
647 
648  const Projection& proj = tracklet->proj(layerdisk_);
649 
650  int iphi = proj.fpgaphiproj().value();
651  int iphicorr = (iz * proj.fpgaphiprojder().value()) >> icorrshift_;
652 
653  iphi += iphicorr;
654 
655  int ir = proj.fpgarzproj().value();
656  int ircorr = (iz * proj.fpgarzprojder().value()) >> icorzshift_;
657  ir += ircorr;
658 
659  int ideltaphi = fpgastub->phi().value() - iphi;
660 
661  int irstub = fpgastub->r().value();
662  int ialphafact = 0;
663  if (!stub->isPSmodule()) {
664  assert(irstub < (int)N_DSS_MOD * 2);
665  if (layerdisk_ - N_LAYER <= 1) {
666  ialphafact = ialphafactinner_[irstub];
667  irstub = settings_.rDSSinner(irstub) / settings_.kr();
668  } else {
669  ialphafact = ialphafactouter_[irstub];
670  irstub = settings_.rDSSouter(irstub) / settings_.kr();
671  }
672  }
673 
674  constexpr int diff_bits = 1;
675  int ideltar = (irstub >> diff_bits) - ir;
676 
677  if (!stub->isPSmodule()) {
678  int ialpha = fpgastub->alpha().value();
679  int iphialphacor = ((ideltar * ialpha * ialphafact) >> settings_.alphashift());
680  ideltaphi += iphialphacor;
681  }
682 
683  //Perform floating point calculations here
684 
685  double phi = stub->phi();
686  double z = stub->z();
687  double r = stub->r();
688 
689  if (settings_.useapprox()) {
690  double dphi = reco::reduceRange(phi - fpgastub->phiapprox(phimin_, 0.0));
691  assert(std::abs(dphi) < 0.001);
692  phi = fpgastub->phiapprox(phimin_, 0.0);
693  z = fpgastub->zapprox();
694  r = fpgastub->rapprox();
695  }
696 
697  if (phi < 0)
698  phi += 2 * M_PI;
699  phi -= phimin_;
700 
701  double dz = z - sign * settings_.zmean(layerdisk_ - N_LAYER);
702 
703  if (std::abs(dz) > settings_.dzmax()) {
704  edm::LogProblem("Tracklet") << __FILE__ << ":" << __LINE__ << " " << name_ << " " << tracklet->getISeed();
705  edm::LogProblem("Tracklet") << "stub " << stub->z() << " disk " << disk << " " << dz;
707  }
708 
709  double phiproj = proj.phiproj() + dz * proj.phiprojder();
710  double rproj = proj.rzproj() + dz * proj.rzprojder();
711  double deltar = r - rproj;
712 
713  double dr = stub->r() - rproj;
714  double drapprox = stub->r() - (proj.rzprojapprox() + dz * proj.rzprojderapprox());
715 
716  double dphi = reco::reduceRange(phi - phiproj);
717 
718  double dphiapprox = reco::reduceRange(phi - (proj.phiprojapprox() + dz * proj.phiprojderapprox()));
719 
720  double drphi = dphi * stub->r();
721  double drphiapprox = dphiapprox * stub->r();
722 
723  if (!stub->isPSmodule()) {
724  double alphanorm = stub->alphanorm();
725  dphi += dr * alphanorm * settings_.half2SmoduleWidth() / stub->r2();
726  ;
727  dphiapprox += drapprox * alphanorm * settings_.half2SmoduleWidth() / stub->r2();
728 
729  drphi += dr * alphanorm * settings_.half2SmoduleWidth() / stub->r();
730  drphiapprox += dr * alphanorm * settings_.half2SmoduleWidth() / stub->r();
731  }
732 
733  int seedindex = tracklet->getISeed();
734 
735  int idrphicut = rphicutPStable_.lookup(seedindex);
736  int idrcut = rcutPStable_.lookup(seedindex);
737  if (!stub->isPSmodule()) {
738  idrphicut = rphicut2Stable_.lookup(seedindex);
739  idrcut = rcut2Stable_.lookup(seedindex);
740  }
741 
743  next_tracklet = tracklet;
744  // Do we have a new tracklet?
745  bool newtracklet = (istep == 0 || tracklet != curr_tracklet);
746  // If so, replace the "best" values with the cut tables
747  if (newtracklet) {
748  best_ideltaphi_disk = idrphicut;
749  best_ideltar_disk = idrcut;
750  }
751 
752  double drphicut = idrphicut * settings_.kphi() * settings_.kr();
753  double drcut = idrcut * settings_.krprojshiftdisk();
754 
755  if (settings_.writeMonitorData("Residuals")) {
756  double pt = 0.01 * settings_.c() * settings_.bfield() / std::abs(tracklet->rinv());
757 
758  globals_->ofstream("diskresiduals.txt")
759  << layerdisk_ - N_LAYER + 1 << " " << stub->isPSmodule() << " " << tracklet->layer() << " "
760  << abs(tracklet->disk()) << " " << pt << " " << ideltaphi * settings_.kphi() * stub->r() << " " << drphiapprox
761  << " " << drphicut << " " << ideltar * settings_.krprojshiftdisk() << " " << deltar << " " << drcut << " "
762  << endl;
763  }
764 
765  bool match = (std::abs(drphi) < drphicut) && (std::abs(deltar) < drcut);
766  bool imatch = (std::abs(ideltaphi * irstub) < best_ideltaphi_disk) && (std::abs(ideltar) < best_ideltar_disk);
767  // Update the "best" values
768  if (imatch) {
769  best_ideltaphi_disk = std::abs(ideltaphi) * irstub;
770  best_ideltar_disk = std::abs(ideltar);
771  }
772 
773  if (settings_.debugTracklet()) {
774  edm::LogVerbatim("Tracklet") << "imatch match disk: " << imatch << " " << match << " " << std::abs(ideltaphi)
775  << " " << drphicut / (settings_.kphi() * stub->r()) << " " << std::abs(ideltar)
776  << " " << drcut / settings_.krprojshiftdisk() << " r = " << stub->r();
777  }
778 
779  bool keep = true;
780  if (!settings_.doKF() || !settings_.doMultipleMatches()) {
781  // Case of allowing only one stub per track per layer (or no KF which implies the same).
782  if (imatch && tracklet->match(layerdisk_)) {
783  // Veto match if is not the best one for this tracklet (in given layer)
784  auto res = tracklet->resid(layerdisk_);
785  keep = abs(ideltaphi) < abs(res.fpgaphiresid().value());
786  imatch = keep;
787  }
788  }
789 
790  if (imatch) {
791  if (settings_.debugTracklet()) {
792  edm::LogVerbatim("Tracklet") << "MatchCalculator found match in disk " << getName();
793  }
794 
795  if (std::abs(dphi) >= third * settings_.dphisectorHG()) {
796  edm::LogPrint("Tracklet") << "dphi " << dphi << " ISeed " << tracklet->getISeed();
797  }
799  assert(std::abs(dphiapprox) < third * settings_.dphisectorHG());
800 
801  tracklet->addMatch(layerdisk_,
802  ideltaphi,
803  ideltar,
804  drphi / stub->r(),
805  dr,
806  drphiapprox / stub->r(),
807  drapprox,
808  (phiregion_ << N_BITSMEMADDRESS) + fpgastub->stubindex().value(),
809  fpgastub);
810 
811  if (settings_.debugTracklet()) {
812  edm::LogVerbatim("Tracklet") << "Accepted full match in disk " << getName() << " " << tracklet;
813  }
814 
815  int iSeed = tracklet->getISeed();
816  assert(fullmatches_[iSeed] != nullptr);
817  fullmatches_[iSeed]->addMatch(tracklet, fpgastub);
818 
819  return true;
820  } else {
821  return false;
822  }
823  }
824 }
Log< level::Info, true > LogVerbatim
void initBendMatch(unsigned int layerdisk)
Definition: TrackletLUT.cc:901
constexpr unsigned int N_RZBITS
Definition: Settings.h:39
double kz() const
Definition: Settings.h:342
double phi() const
Definition: L1TStub.h:65
double t() const
Definition: Tracklet.h:123
double zapprox() const
Definition: Stub.cc:166
unsigned int maxStep(std::string module) const
Definition: Settings.h:125
const FPGAWord & r() const
Definition: Stub.h:65
bool bookHistos() const
Definition: Settings.h:219
std::string name_
Definition: ProcessBase.h:38
const Residual & resid(unsigned int layerdisk)
Definition: Tracklet.h:110
unsigned int projrinv() const
int disk() const
Definition: Tracklet.cc:792
double kphi1() const
Definition: Settings.h:339
double kphiderdisk() const
Definition: Settings.h:435
void initmatchcut(unsigned int layerdisk, MatchType type, unsigned int region)
Definition: TrackletLUT.cc:190
double rDSSinner(unsigned int iBin) const
Definition: Settings.h:183
constexpr T reduceRange(T x)
Definition: deltaPhi.h:18
void addInput(MemoryBase *memory, std::string input) override
double phiapprox(double phimin, double) const
Definition: Stub.cc:185
std::vector< MatchEngineUnit > matchengines_
double kphider() const
Definition: Settings.h:434
constexpr unsigned int NRINVBITS
Definition: Settings.h:36
const FPGAWord & z() const
Definition: Stub.h:66
void initProjectionBend(double k_phider, unsigned int idisk, unsigned int nrbits, unsigned int nphiderbits)
Definition: TrackletLUT.cc:801
double dphisectorHG() const
Definition: Settings.h:320
unsigned int projfinephi() const
Projection & proj(int layerdisk)
Definition: Tracklet.h:87
Settings const & settings_
Definition: ProcessBase.h:40
TrackletLUT phimatchcuttable_
double z() const
Definition: L1TStub.h:59
Globals * globals_
Definition: ProcessBase.h:41
double krder() const
Definition: Settings.h:437
int lookup(unsigned int index) const
bool writetrace() const
Definition: Settings.h:195
std::vector< TrackletProjectionsMemory * > inputprojs_
double dzmax() const
Definition: Settings.h:138
constexpr unsigned int N_DSS_MOD
Definition: Settings.h:31
assert(be >=bs)
int TCID() const
Definition: Tracklet.h:214
Definition: Electron.h:6
constexpr double third
Definition: Settings.h:46
static std::string const input
Definition: EdmProvDump.cc:50
unsigned int isPSmodule() const
Definition: L1TStub.h:103
void addMatch(unsigned int layerdisk, int ideltaphi, int ideltarz, double dphi, double drz, double dphiapprox, double drzapprox, int stubid, const trklet::Stub *stubptr)
Definition: Tracklet.cc:303
U second(std::pair< T, U > const &p)
uint64_t word
double kzder() const
Definition: Settings.h:436
unsigned int nbitsallstubs(unsigned int layerdisk) const
Definition: Settings.h:115
double half2SmoduleWidth() const
Definition: Settings.h:140
unsigned int nzbitsstub(unsigned int layerdisk) const
Definition: Settings.h:91
unsigned int nphibitsstub(unsigned int layerdisk) const
Definition: Settings.h:92
double rmean(unsigned int iLayer) const
Definition: Settings.h:173
double rinv() const
Definition: Tracklet.h:120
int ilog2(double factor)
Definition: Util.h:121
double rDSSouter(unsigned int iBin) const
Definition: Settings.h:186
bool use(unsigned int nextrzbin, unsigned int nextiphibin) const
std::vector< FullMatchMemory * > fullmatches_
double bfield() const
Definition: Settings.h:277
void print(TMatrixD &m, const char *label=nullptr, bool mathematicaFormat=false)
Definition: Utilities.cc:47
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
IMATH_TrackletCalculator * ITC_L1L2()
Definition: Globals.h:48
int value() const
Definition: FPGAWord.h:24
bool doMultipleMatches() const
Definition: Settings.h:254
int alphashift() const
Definition: Settings.h:228
L1TStub * l1tstub()
Definition: Stub.h:83
std::string const & getName() const
Definition: MemoryBase.h:19
unsigned int nbitsvmme(unsigned int layerdisk) const
Definition: Settings.h:112
CircularBuffer< ProjectionTemp > inputProjBuffer_
bool writeMonitorData(std::string module) const
Definition: Settings.h:118
Log< level::Warning, true > LogPrint
double rapprox() const
Definition: Stub.cc:152
double zmean(unsigned int iDisk) const
Definition: Settings.h:176
void initLayerDisk(unsigned int pos, int &layer, int &disk)
Definition: ProcessBase.cc:33
const FPGAWord & stubindex() const
Definition: Stub.h:72
#define M_PI
double K() const
Definition: imath.h:247
TrackletLUT rphicutPStable_
unsigned int nallstubs(unsigned int layerdisk) const
Definition: Settings.h:116
bool debugTracklet() const
Definition: Settings.h:194
bool matchCalculator(Tracklet *tracklet, const Stub *fpgastub, bool print, unsigned int istep)
unsigned int iphi() const
TrackletLUT rphicut2Stable_
double kr() const
Definition: Settings.h:344
unsigned int slot() const
double drmax() const
Definition: Settings.h:137
double alphanorm() const
Definition: L1TStub.cc:91
int ialphafactinner_[N_DSS_MOD *2]
bool stubtruthmatch(const L1TStub *stub)
Definition: Tracklet.cc:138
int nbits() const
Definition: FPGAWord.h:25
void addOutput(MemoryBase *memory, std::string output) override
Definition: deltar.py:1
constexpr unsigned int NFINEPHIBITS
Definition: Settings.h:38
int getISeed() const
Definition: Tracklet.cc:811
double c() const
Definition: Settings.h:224
unsigned int getISeed(const std::string &name)
Definition: ProcessBase.cc:119
unsigned int nvmme(unsigned int layerdisk) const
Definition: Settings.h:113
const FPGAWord & alpha() const
Definition: Stub.h:70
double r() const
Definition: L1TStub.h:60
bool match(unsigned int layerdisk)
Definition: Tracklet.h:105
void execute(unsigned int iSector, double phimin)
Tracklet * proj() const
unsigned int nMatchEngines_
std::ofstream & ofstream(std::string fname)
Definition: Globals.cc:44
static unsigned int const shift
int nbitsalpha() const
Definition: Settings.h:229
HistBase *& histograms()
Definition: Globals.h:38
Definition: output.py:1
double krbarrel() const
Definition: Settings.h:345
double krprojshiftdisk() const
Definition: Settings.h:441
const FPGAWord & phi() const
Definition: Stub.h:68
std::vector< VMStubsMEMemory * > vmstubs_
void initProjectionDiskRadius(int nrbits)
Definition: TrackletLUT.cc:854
unsigned int nStubsBin(unsigned int bin) const
int layer() const
Definition: Tracklet.cc:783
double kphi() const
Definition: Settings.h:338
unsigned int bits(unsigned int lsb, unsigned int nbit) const
Definition: FPGAWord.cc:74
tmp
align.sh
Definition: createJobs.py:716
bool doKF() const
Definition: Settings.h:253
double r2() const
Definition: L1TStub.h:62
std::string const & getName() const
Definition: ProcessBase.h:22
AllStubsMemory * allstubs_
TrackletLUT zmatchcuttable_
int ialphafactouter_[N_DSS_MOD *2]
bool useapprox() const
Definition: Settings.h:247
constexpr unsigned int N_BITSMEMADDRESS
Definition: Settings.h:43
Log< level::Error, true > LogProblem
constexpr int N_LAYER
Definition: Settings.h:25