CMS 3D CMS Logo

HoughTransform.cc
Go to the documentation of this file.
2 
3 #include <numeric>
4 #include <algorithm>
5 #include <iterator>
6 #include <deque>
7 #include <vector>
8 #include <set>
9 #include <utility>
10 #include <cmath>
11 
12 using namespace std;
13 using namespace edm;
14 using namespace tt;
15 
16 namespace trackerTFP {
17 
19  const Setup* setup,
20  const DataFormats* dataFormats,
21  int region)
22  : enableTruncation_(iConfig.getParameter<bool>("EnableTruncation")),
23  setup_(setup),
24  dataFormats_(dataFormats),
25  inv2R_(dataFormats_->format(Variable::inv2R, Process::ht)),
26  phiT_(dataFormats_->format(Variable::phiT, Process::ht)),
27  region_(region),
28  input_(dataFormats_->numChannel(Process::ht), vector<deque<StubGP*>>(dataFormats_->numChannel(Process::gp))) {}
29 
30  // read in and organize input product (fill vector input_)
33  auto validFrame = [](int sum, const FrameStub& frame) { return sum + (frame.first.isNonnull() ? 1 : 0); };
34  int nStubsGP(0);
35  for (int sector = 0; sector < dataFormats_->numChannel(Process::gp); sector++) {
37  nStubsGP += accumulate(stream.begin(), stream.end(), 0, validFrame);
38  }
39  stubsGP_.reserve(nStubsGP);
40  for (int sector = 0; sector < dataFormats_->numChannel(Process::gp); sector++) {
41  const int sectorPhi = sector % setup_->numSectorsPhi();
42  const int sectorEta = sector / setup_->numSectorsPhi();
43  for (const FrameStub& frame : streams[offset + sector]) {
44  // Store input stubs in vector, so rest of HT algo can work with pointers to them (saves CPU)
45  StubGP* stub = nullptr;
46  if (frame.first.isNonnull()) {
48  stub = &stubsGP_.back();
49  }
50  for (int binInv2R = 0; binInv2R < dataFormats_->numChannel(Process::ht); binInv2R++)
51  input_[binInv2R][sector].push_back(stub && stub->inInv2RBin(binInv2R) ? stub : nullptr);
52  }
53  }
54  // remove all gaps between end and last stub
55  for (vector<deque<StubGP*>>& input : input_)
56  for (deque<StubGP*>& stubs : input)
57  for (auto it = stubs.end(); it != stubs.begin();)
58  it = (*--it) ? stubs.begin() : stubs.erase(it);
59  auto validStub = [](int sum, StubGP* stub) { return sum + (stub ? 1 : 0); };
60  int nStubsHT(0);
61  for (const vector<deque<StubGP*>>& binInv2R : input_)
62  for (const deque<StubGP*>& sector : binInv2R)
63  nStubsHT += accumulate(sector.begin(), sector.end(), 0, validStub);
64  stubsHT_.reserve(nStubsHT);
65  }
66 
67  // fill output products
69  for (int binInv2R = 0; binInv2R < dataFormats_->numChannel(Process::ht); binInv2R++) {
70  const int inv2R = inv2R_.toSigned(binInv2R);
71  deque<StubHT*> acceptedAll;
72  deque<StubHT*> lostAll;
73  for (deque<StubGP*>& inputSector : input_[binInv2R]) {
74  const int size = inputSector.size();
75  vector<StubHT*> acceptedSector;
76  vector<StubHT*> lostSector;
77  acceptedSector.reserve(size);
78  lostSector.reserve(size);
79  // associate stubs with inv2R and phiT bins
80  fillIn(inv2R, inputSector, acceptedSector, lostSector);
81  // Process::ht collects all stubs before readout starts -> remove all gaps
82  acceptedSector.erase(remove(acceptedSector.begin(), acceptedSector.end(), nullptr), acceptedSector.end());
83  // identify tracks
84  readOut(acceptedSector, lostSector, acceptedAll, lostAll);
85  }
86  // truncate accepted stream
87  const auto limit = enableTruncation_
88  ? next(acceptedAll.begin(), min(setup_->numFrames(), (int)acceptedAll.size()))
89  : acceptedAll.end();
90  copy_if(limit, acceptedAll.end(), back_inserter(lostAll), [](StubHT* stub) { return stub; });
91  acceptedAll.erase(limit, acceptedAll.end());
92  // store found tracks
93  auto put = [](const deque<StubHT*>& stubs, StreamStub& stream) {
94  stream.reserve(stubs.size());
95  for (StubHT* stub : stubs)
96  stream.emplace_back(stub ? stub->frame() : FrameStub());
97  };
99  put(acceptedAll, accepted[offset + binInv2R]);
100  // store lost tracks
101  put(lostAll, lost[offset + binInv2R]);
102  }
103  }
104 
105  // associate stubs with phiT bins in this inv2R column
106  void HoughTransform::fillIn(int inv2R,
107  deque<StubGP*>& inputSector,
108  vector<StubHT*>& acceptedSector,
109  vector<StubHT*>& lostSector) {
110  // fifo, used to store stubs which belongs to a second possible track
111  deque<StubHT*> stack;
112  // clock accurate firmware emulation, each while trip describes one clock tick, one stub in and one stub out per tick
113  while (!inputSector.empty() || !stack.empty()) {
114  StubHT* stubHT = nullptr;
115  StubGP* stubGP = pop_front(inputSector);
116  if (stubGP) {
117  const double phiT = stubGP->phi() - inv2R_.floating(inv2R) * stubGP->r();
118  const int major = phiT_.integer(phiT);
119  if (phiT_.inRange(major)) {
120  // major candidate has pt > threshold (3 GeV)
121  // stubHT records which HT bin this stub is added to
122  stubsHT_.emplace_back(*stubGP, major, inv2R);
123  stubHT = &stubsHT_.back();
124  }
125  const double chi = phiT - phiT_.floating(major);
126  if (abs(stubGP->r() * inv2R_.base()) + 2. * abs(chi) >= phiT_.base()) {
127  // stub belongs to two candidates
128  const int minor = chi >= 0. ? major + 1 : major - 1;
129  if (phiT_.inRange(minor)) {
130  // second (minor) candidate has pt > threshold (3 GeV)
131  stubsHT_.emplace_back(*stubGP, minor, inv2R);
132  if (enableTruncation_ && (int)stack.size() == setup_->htDepthMemory() - 1)
133  // buffer overflow
134  lostSector.push_back(pop_front(stack));
135  // store minor stub in fifo
136  stack.push_back(&stubsHT_.back());
137  }
138  }
139  }
140  // take a minor stub if no major stub available
141  acceptedSector.push_back(stubHT ? stubHT : pop_front(stack));
142  }
143  // truncate to many input stubs
144  const auto limit = enableTruncation_
145  ? next(acceptedSector.begin(), min(setup_->numFrames(), (int)acceptedSector.size()))
146  : acceptedSector.end();
147  copy_if(limit, acceptedSector.end(), back_inserter(lostSector), [](StubHT* stub) { return stub; });
148  acceptedSector.erase(limit, acceptedSector.end());
149  }
150 
151  // identify tracks
152  void HoughTransform::readOut(const vector<StubHT*>& acceptedSector,
153  const vector<StubHT*>& lostSector,
154  deque<StubHT*>& acceptedAll,
155  deque<StubHT*>& lostAll) const {
156  // used to recognise in which order tracks are found
157  TTBV trkFoundPhiTs(0, setup_->htNumBinsPhiT());
158  // hitPattern for all possible tracks, used to find tracks
159  vector<TTBV> patternHits(setup_->htNumBinsPhiT(), TTBV(0, setup_->numLayers()));
160  // found unsigned phiTs, ordered in time
161  vector<int> binsPhiT;
162  // stub container for all possible tracks
163  vector<vector<StubHT*>> tracks(setup_->htNumBinsPhiT());
164  for (int binPhiT = 0; binPhiT < setup_->htNumBinsPhiT(); binPhiT++) {
165  const int phiT = phiT_.toSigned(binPhiT);
166  auto samePhiT = [phiT](int sum, StubHT* stub) { return sum + (stub->phiT() == phiT); };
167  const int numAccepted = accumulate(acceptedSector.begin(), acceptedSector.end(), 0, samePhiT);
168  const int numLost = accumulate(lostSector.begin(), lostSector.end(), 0, samePhiT);
169  tracks[binPhiT].reserve(numAccepted + numLost);
170  }
171  for (StubHT* stub : acceptedSector) {
172  const int binPhiT = phiT_.toUnsigned(stub->phiT());
173  TTBV& pattern = patternHits[binPhiT];
174  pattern.set(stub->layer());
175  tracks[binPhiT].push_back(stub);
176  if (pattern.count() >= setup_->htMinLayers() && !trkFoundPhiTs[binPhiT]) {
177  // first time track found
178  trkFoundPhiTs.set(binPhiT);
179  binsPhiT.push_back(binPhiT);
180  }
181  }
182  // read out found tracks ordered as found
183  for (int binPhiT : binsPhiT) {
184  const vector<StubHT*>& track = tracks[binPhiT];
185  acceptedAll.insert(acceptedAll.end(), track.begin(), track.end());
186  }
187  // look for lost tracks
188  for (StubHT* stub : lostSector) {
189  const int binPhiT = phiT_.toUnsigned(stub->phiT());
190  if (!trkFoundPhiTs[binPhiT])
191  tracks[binPhiT].push_back(stub);
192  }
193  for (int binPhiT : trkFoundPhiTs.ids(false)) {
194  const vector<StubHT*>& track = tracks[binPhiT];
195  set<int> layers;
196  auto toLayer = [](StubHT* stub) { return stub->layer(); };
197  transform(track.begin(), track.end(), inserter(layers, layers.begin()), toLayer);
198  if ((int)layers.size() >= setup_->htMinLayers())
199  lostAll.insert(lostAll.end(), track.begin(), track.end());
200  }
201  }
202 
203  // remove and return first element of deque, returns nullptr if empty
204  template <class T>
205  T* HoughTransform::pop_front(deque<T*>& ts) const {
206  T* t = nullptr;
207  if (!ts.empty()) {
208  t = ts.front();
209  ts.pop_front();
210  }
211  return t;
212  }
213 
214 } // namespace trackerTFP
bool inRange(double d, bool digi=false) const
Definition: DataFormats.h:106
bool inInv2RBin(int inv2RBin) const
Definition: DataFormats.h:646
double base() const
Definition: DataFormats.h:117
int numSectorsPhi() const
Definition: Setup.h:413
Bit vector used by Track Trigger emulators. Mainly used to convert integers into arbitrary (within ma...
Definition: TTBV.h:20
std::pair< TTStubRef, Frame > FrameStub
Definition: TTTypes.h:60
std::vector< StubGP > stubsGP_
Class to process and provide run-time constants used by Track Trigger emulators.
Definition: Setup.h:44
std::vector< StreamStub > StreamsStub
Definition: TTTypes.h:66
std::vector< FrameStub > StreamStub
Definition: TTTypes.h:63
int numFrames() const
Definition: Setup.h:153
void produce(tt::StreamsStub &accepted, tt::StreamsStub &lost)
uint32_t T const *__restrict__ uint32_t const *__restrict__ int32_t int Histo::index_type cudaStream_t stream
const tt::Setup * setup_
static std::string const input
Definition: EdmProvDump.cc:50
int numChannel(Process p) const
Definition: DataFormats.h:498
int integer(double d) const
Definition: DataFormats.h:96
std::vector< std::vector< std::deque< StubGP * > > > input_
Definition: TTTypes.h:54
std::vector< StubHT > stubsHT_
int htDepthMemory() const
Definition: Setup.h:445
double floating(int i) const
Definition: DataFormats.h:94
stack
Definition: svgfig.py:559
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
int htMinLayers() const
Definition: Setup.h:443
void consume(const tt::StreamsStub &streams)
void readOut(const std::vector< StubHT *> &acceptedSector, const std::vector< StubHT *> &lostSector, std::deque< StubHT *> &acceptedAll, std::deque< StubHT *> &lostAll) const
int numLayers() const
Definition: Setup.h:215
int toSigned(int i) const
Definition: DataFormats.h:100
double r() const
Definition: DataFormats.h:654
deadvectors [0] push_back({0.0175431, 0.538005, 6.80997, 13.29})
double phi() const
Definition: DataFormats.h:656
int toUnsigned(int i) const
Definition: DataFormats.h:102
int htNumBinsPhiT() const
Definition: Setup.h:441
HLT enums.
const DataFormats * dataFormats_
Class to calculate and provide dataformats used by Track Trigger emulator.
Definition: DataFormats.h:216
T * pop_front(std::deque< T *> &ts) const
long double T
void fillIn(int inv2R, std::deque< StubGP *> &inputSector, std::vector< StubHT *> &acceptedSector, std::vector< StubHT *> &lostSector)
unsigned transform(const HcalDetId &id, unsigned transformCode)