9 #include <trg/cdc/modules/houghETF/CDCTriggerHoughETFModule.h>
11 #include <cdc/geometry/CDCGeometryPar.h>
12 #include <framework/logging/Logger.h>
13 #include <framework/gearbox/Const.h>
19 #include <root/TMatrix.h>
22 #define CDC_SUPER_LAYERS 9
40 setDescription(
"Hough tracking algorithm for CDC trigger.");
41 setPropertyFlags(c_ParallelProcessingCertified);
50 addParam(
"outputEventTimeName", m_EventTimeName,
51 "Name of the output StoreObjPtr.",
53 addParam(
"storeTracks", m_storeTracks,
56 addParam(
"usePriorityTiming", m_usePriorityTiming,
57 "Use priority timing instead of fastest timing.",
59 addParam(
"useHighPassTimingList", m_useHighPassTimingList,
60 "Use associated fastest timings track-by-track",
62 addParam(
"t0CalcMethod", m_t0CalcMethod,
63 "0: Nth fastest fastest time."
64 "1: median of all timings."
65 "2: median of timings in timing window.",
67 addParam(
"arrivalOrder", m_arrivalOrder,
68 "When t0CalcMethod == 0: Nth fastest ft is used as T0. (i.e. 0 is fastest)",
70 addParam(
"timeWindowBegin", m_timeWindowBegin,
71 "When t0CalcMethod == 2: start time of time window relative to median. (in ns)",
73 addParam(
"timeWindowEnd", m_timeWindowEnd,
74 "When t0CalcMethod == 2: end time of time window relative to median. (in ns)",
78 addParam(
"hitCollectionName", m_hitCollectionName,
79 "Name of the input StoreArray of CDCTriggerSegmentHits.",
81 addParam(
"outputCollectionName", m_outputCollectionName,
82 "Name of the StoreArray holding the tracks found in the Hough tracking.",
83 string(
"TRGCDCETFTracks"));
84 addParam(
"clusterCollectionName", m_clusterCollectionName,
85 "Name of the StoreArray holding the clusters formed in the Hough plane.",
87 addParam(
"nCellsPhi", m_nCellsPhi,
88 "Number of Hough cells in phi (limits: [-180, 180]). Must be an even number.",
90 addParam(
"nCellsR", m_nCellsR,
91 "Number of Hough cells in 1/r. Must be an even number.",
93 addParam(
"minPt", m_minPt,
95 "Hough plane limits in 1/r are [-1/r(minPt), 1/r(minPt)]", (
double)(0.3));
96 addParam(
"shiftPt", m_shiftPt,
97 "Shift the Hough plane by 1/4 cell size in 1/r to avoid "
98 "curvature 0 tracks (<0: shift in negative direction, "
99 "0: no shift, >0: shift in positive direction).", 0);
101 addParam(
"minHits", m_minHits,
102 "Minimum hits from different super layers required in a peak cell.",
104 addParam(
"minHitsShort", m_minHitsShort,
105 "Minimum hits required required in a peak cell for a short track"
106 " (must be in the first minHitsShort super layers).",
108 addParam(
"minCells", m_minCells,
109 "Peaks with less than minCells connected cells are ignored.",
111 addParam(
"onlyLocalMax", m_onlyLocalMax,
112 "Switch to remove cells connected to a cell with higher super layer count.",
114 addParam(
"connect", m_connect,
115 "Definition for connected cells. 4: direct (left/right/top/bottom), "
116 "6: direct + 2 diagonal (top right/bottom left), "
117 "8: direct + all diagonal (top right/top left/bottom right/bottom left)",
119 addParam(
"ignore2ndPriority", m_ignore2nd,
120 "Switch to skip second priority hits.",
false);
121 addParam(
"usePriorityPosition", m_usePriority,
122 "If true, use wire position of priority cell in track segment, "
123 "otherwise use wire position of center cell.",
true);
124 addParam(
"requireSL0", m_requireSL0,
125 "Switch to check separately for a hit in the innermost superlayer.",
false);
126 addParam(
"storeHoughPlane", m_storePlane,
127 "Switch for saving Hough plane as TMatrix in DataStore. "
128 "0: don't store anything, 1: store only peaks, 2: store full plane "
129 "(will increase runtime).", (
unsigned)(0));
130 addParam(
"clusterPattern", m_clusterPattern,
131 "use nested pattern algorithm to find clusters",
true);
132 addParam(
"clusterSizeX", m_clusterSizeX,
133 "maximum number of 2 x 2 squares in cluster for pattern algorithm",
135 addParam(
"clusterSizeY", m_clusterSizeY,
136 "maximum number of 2 x 2 squares in cluster for pattern algorithm",
138 addParam(
"hitRelationsFromCorners", m_hitRelationsFromCorners,
139 "Switch for creating relations to hits in the pattern algorithm. "
140 "If true, create relations from cluster corners, otherwise "
141 "from estimated cluster center (might not have relations).",
false);
143 addParam(
"testFilename", m_testFilename,
144 "If not empty, a file with input (hits) and output (tracks) "
145 "for each event is written (for firmware debugging).",
string(
""));
147 addParam(
"suppressClone", m_suppressClone,
148 "Switch to send only the first found track and suppress the "
149 "subsequent clones." ,
false);
153 CDCTriggerHoughETFModule::initialize()
156 m_eventTime.registerInDataStore(m_EventTimeName);
157 m_segmentHits.isRequired(m_hitCollectionName);
160 m_tracks.registerInDataStore(m_outputCollectionName);
161 m_clusters.registerInDataStore(m_clusterCollectionName);
163 m_tracks.registerRelationTo(m_segmentHits);
164 m_tracks.registerRelationTo(m_clusters);
167 if (m_storePlane > 0) m_houghPlane.registerInDataStore(
"HoughPlane");
172 for (
int iSL = 0; iSL < 9; ++iSL) {
174 nTS += cdc.nWiresInLayer(layerId);
175 TSoffset[iSL + 1] = nTS;
176 for (
int priority = 0; priority < 2; ++ priority) {
177 radius[iSL][priority] = cdc.senseWireR(layerId + priority);
179 layerId += (iSL > 0 ? 6 : 7);
182 for (
int sl = 1; sl < 9; sl++) {
183 NSecOffset[sl] = NSEC[sl - 1] + NSecOffset[sl - 1];
186 if (m_testFilename !=
"") {
187 testFile.open(m_testFilename);
190 if (m_suppressClone) {
191 B2INFO(
"2D finder will exit with the first track candidate in time.");
194 if (m_t0CalcMethod != 0 && m_t0CalcMethod != 1) B2WARNING(
"t0CalcMethod is invalid. calculate as default.");
198 CDCTriggerHoughETFModule::event()
203 associatedTSHitsList.clear();
205 if (!m_eventTime.isValid()) m_eventTime.create();
207 setReturnValue(
true);
209 if (m_testFilename !=
"") {
210 testFile << StoreObjPtr<EventMetaData>()->getEvent() <<
" "
211 << m_segmentHits.getEntries() << endl;
214 if (m_segmentHits.getEntries() == 0) {
220 for (
int iHit = 0; iHit < m_segmentHits.getEntries(); iHit++) {
221 unsigned short iSL = m_segmentHits[iHit]->getISuperLayer();
222 if (m_testFilename !=
"") {
223 testFile << iSL <<
" " << m_segmentHits[iHit]->getSegmentID() - TSoffset[iSL] <<
" "
224 << m_segmentHits[iHit]->getPriorityPosition() << endl;
226 if (iSL % 2)
continue;
227 if (m_ignore2nd && m_segmentHits[iHit]->getPriorityPosition() < 3)
continue;
228 double phi = m_segmentHits[iHit]->getSegmentID() - TSoffset[iSL];
230 phi += 0.5 * (((m_segmentHits[iHit]->getPriorityPosition() >> 1) & 1)
231 - (m_segmentHits[iHit]->getPriorityPosition() & 1));
233 phi = phi * 2. * M_PI / (TSoffset[iSL + 1] - TSoffset[iSL]);
234 double r = radius[iSL][int(m_usePriority &&
235 m_segmentHits[iHit]->getPriorityPosition() < 3)];
236 TVector2 pos(cos(phi) / r, sin(phi) / r);
237 hitMap.insert(std::make_pair(iHit, std::make_pair(iSL, pos)));
243 maxIterations = ceil(log2(max(m_nCellsPhi, m_nCellsR))) - 1;
244 nCells = pow(2, maxIterations + 1);
246 double rectX = M_PI * nCells / m_nCellsPhi;
248 maxR = 0.5 * Const::speedOfLight * 1.5e-4 / m_minPt;
249 double rectY = maxR * nCells / m_nCellsR;
252 shiftR = -maxR / 2. / m_nCellsR;
253 }
else if (m_shiftPt > 0) {
254 shiftR = maxR / 2. / m_nCellsR;
257 B2DEBUG(50,
"extending Hough plane to " << maxIterations <<
" iterations, "
258 << nCells <<
" cells: phi in ["
259 << -rectX * 180. / M_PI <<
", " << rectX * 180. / M_PI
260 <<
"] deg, 1/r in [" << -rectY + shiftR <<
", " << rectY + shiftR <<
"] /cm");
263 if (m_storePlane > 0) {
264 m_houghPlane.create();
265 m_houghPlane->ResizeTo(m_nCellsPhi, m_nCellsR);
270 if (m_suppressClone && !hitMap.empty()) {
277 typedef pair<int, cdcPair> cdcHitPair;
279 typedef vector<cdcHitPair> cdcSeqMap;
282 for (
auto hit : hitMap) {
283 seqHitMap.push_back(hit);
285 sort(seqHitMap.begin(), seqHitMap.end(), [
this](cdcHitPair i, cdcHitPair j) {
286 return m_segmentHits[i.first]->foundTime() < m_segmentHits[j.first]->foundTime();
288 auto seqHitItr = seqHitMap.begin();
290 vector<bool> layerHit(CDC_SUPER_LAYERS,
false);
293 short firstTick = m_segmentHits[(*seqHitMap.begin()).first]->foundTime() / period + 1;
294 short lastTick = m_segmentHits[(*(seqHitMap.end() - 1)).first]->foundTime() / period + 1;
296 for (
auto tick = firstTick * period; tick < lastTick * period; tick += period) {
298 for (
auto itr = seqHitItr; itr < seqHitMap.end(); ++itr) {
299 cdcHitPair currentHit = *itr;
301 if (count(layerHit.begin(), layerHit.end(),
true) >= m_minHits &&
302 m_segmentHits[currentHit.first]->foundTime() > tick) {
306 layerHit[m_segmentHits[currentHit.first]->getISuperLayer()] =
true;
308 copy_n(seqHitItr, nHitInCycle, inserter(fastHitMap, fastHitMap.end()));
309 fastInterceptFinder(fastHitMap, -rectX, rectX, -rectY + shiftR, rectY + shiftR, 0, 0, 0);
310 B2DEBUG(20,
"at tick " << tick <<
", number of candidates: " << houghCand.size());
311 if (!houghCand.empty()) {
312 B2DEBUG(10,
"found a track at clock " << tick <<
" with "
313 << fastHitMap.size() <<
"hits");
316 advance(seqHitItr, nHitInCycle);
320 fastInterceptFinder(hitMap, -rectX, rectX, -rectY + shiftR, rectY + shiftR, 0, 0, 0);
321 if (!houghCand.empty()) {
322 B2DEBUG(10,
"found a track with " << hitMap.size() <<
"hits");
327 if (m_clusterPattern) {
328 if (patternClustering(fastHitMap))
329 m_eventTime->addBinnedEventT0(calcEventTiming(), Const::CDC);
334 if (m_testFilename !=
"") {
335 testFile << m_tracks.getEntries() << endl;
336 for (
int i = 0; i < m_tracks.getEntries(); ++i) {
337 float ix = (m_tracks[i]->getPhi0() - M_PI_4) * m_nCellsPhi / 2. / M_PI - 0.5;
338 float iy = (m_tracks[i]->getOmega() / 2. + maxR - shiftR) * m_nCellsR / 2. / maxR - 0.5;
339 testFile << round(2 * ix) / 2. <<
" " << round(2 * iy) / 2. <<
" "
340 << m_tracks[i]->getChargeSign() << endl;
343 testFile << hits.size() << endl;
344 for (
unsigned ihit = 0; ihit < hits.size(); ++ihit) {
345 unsigned short iSL = hits[ihit]->getISuperLayer();
346 testFile << iSL <<
" " << hits[ihit]->getSegmentID() - TSoffset[iSL] <<
" "
347 << hits[ihit]->getPriorityPosition() <<
" "
348 << hits.weight(ihit) << endl;
355 CDCTriggerHoughETFModule::terminate()
357 if (m_testFilename !=
"") testFile.close();
Combination of several CDCHits to a track segment hit for the trigger.
The Class for CDC Geometry Parameters.
Class for type safe access to objects that are referred to in relations.
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
std::map< int, cdcPair > cdcMap
Map of <counter, cdcPair>, for hits with indices.
Abstract base class for different kinds of events.