10 #include <trg/cdc/modules/houghtracking/CDCTrigger2DFinderModule.h>
12 #include <framework/logging/Logger.h>
16 #include <root/TMatrix.h>
19 #define CDC_SUPER_LAYERS 9
25 CDCTrigger2DFinderModule::countSL(
bool* layer)
27 if (m_requireSL0 && !layer[0])
return 0;
28 unsigned short lcnt = 0;
29 for (
int i = 0; i < CDC_SUPER_LAYERS; ++i) {
30 if (layer[i] ==
true) ++lcnt;
36 CDCTrigger2DFinderModule::shortTrack(
bool* layer)
38 unsigned short lcnt = 0;
41 for (
int i = 0; i < CDC_SUPER_LAYERS; i += 2) {
42 if (layer[i] ==
true) ++lcnt;
45 return (lcnt >= m_minHitsShort);
58 CDCTrigger2DFinderModule::fastInterceptFinder(
cdcMap& hits,
59 double x1_s,
double x2_s,
60 double y1_s,
double y2_s,
62 unsigned ix_s,
unsigned iy_s)
65 for (
unsigned i = 0; i < iterations; ++i) indent +=
" ";
66 B2DEBUG(150, indent <<
"intercept finder iteration " << iterations
67 <<
" x1 " << x1_s * 180 / M_PI <<
" x2 " << x2_s * 180 / M_PI
68 <<
" y1 " << y1_s <<
" y2 " << y2_s
69 <<
" ix " << ix_s <<
" iy " << iy_s);
78 vector<unsigned> idx_list;
81 double x1_d, x2_d, y1_d, y2_d;
86 unitx = ((x2_s - x1_s) / 2.0);
87 unity = ((y2_s - y1_s) / 2.0);
90 for (i = 0; i < 2 ; ++i) {
92 for (j = 0; j < 2; ++j) {
93 x1_d = x1_s + i * unitx;
94 x2_d = x1_s + (i + 1) * unitx;
95 y1_d = y1_s + j * unity;
96 y2_d = y1_s + (j + 1) * unity;
102 if (x2_d <= -M_PI || x1_d >= M_PI || y2_d <= -maxR + shiftR || y1_d >= maxR + shiftR) {
103 B2DEBUG(150, indent <<
"skip Hough cell outside of plane limits");
109 if (iterations != maxIterations && unitx > M_PI / 2.) {
110 fastInterceptFinder(hits, x1_d, x2_d, y1_d, y2_d, iterations + 1, ix, iy);
115 bool layerHit[CDC_SUPER_LAYERS] = {
false};
116 for (
auto it = hits.begin(); it != hits.end(); ++it) {
123 y1 = m * sin(x1_d - 1e-10) - a * cos(x1_d - 1e-10);
124 y2 = m * sin(x2_d + 1e-10) - a * cos(x2_d + 1e-10);
126 if (iterations == maxIterations && y1 > y2)
continue;
127 if (!((y1 > y2_d && y2 > y2_d) || (y1 < y1_d && y2 < y1_d))) {
128 if (iterations == maxIterations) {
129 idx_list.push_back(iHit);
131 layerHit[iSL] =
true;
134 unsigned short nSL = countSL(layerHit);
135 B2DEBUG(150, indent <<
"i " << i <<
" j " << j
136 <<
" layerHit " <<
int(layerHit[0]) <<
int(layerHit[2])
137 <<
int(layerHit[4]) <<
int(layerHit[6]) <<
int(layerHit[8])
139 if (nSL >= m_minHits || shortTrack(layerHit)) {
140 if (iterations != maxIterations) {
141 fastInterceptFinder(hits, x1_d, x2_d, y1_d, y2_d, iterations + 1, ix, iy);
143 TVector2 v1(x1_d, y1_d);
144 TVector2 v2(x2_d, y2_d);
146 nSL, houghCand.size()));
147 if (m_storePlane > 0) {
148 (*m_houghPlane)[ix - (nCells - m_nCellsPhi) / 2][iy - (nCells - m_nCellsR) / 2] = nSL;
151 }
else if (m_storePlane > 1) {
154 for (
unsigned min = m_minHits - 1; min > 0; --min) {
156 if (iterations != maxIterations) {
157 fastInterceptFinder(hits, x1_d, x2_d, y1_d, y2_d, iterations + 1, ix, iy);
159 (*m_houghPlane)[ix - (nCells - m_nCellsPhi) / 2][iy - (nCells - m_nCellsR) / 2] = nSL;
175 CDCTrigger2DFinderModule::connectedRegions()
177 vector<vector<CDCTriggerHoughCand>> regions;
178 vector<CDCTriggerHoughCand> cpyCand = houghCand;
181 B2DEBUG(50,
"houghCand number " << cpyCand.size());
182 for (
unsigned icand = 0; icand < houghCand.size(); ++icand) {
184 B2DEBUG(100, houghCand[icand].
getID()
185 <<
" nSL " << houghCand[icand].getSLcount()
186 <<
" x1 " << coord.first.X() <<
" x2 " << coord.second.X()
187 <<
" y1 " << coord.first.Y() <<
" y2 " << coord.second.Y());
191 while (cpyCand.size() > 0) {
192 B2DEBUG(100,
"make new region");
193 vector<CDCTriggerHoughCand> region;
194 vector<CDCTriggerHoughCand> rejected;
196 cpyCand.erase(cpyCand.begin());
197 region.push_back(start);
198 addNeighbors(start, cpyCand, region, rejected, start.getSLcount());
199 regions.push_back(region);
200 for (
auto cand = cpyCand.begin(); cand != cpyCand.end();) {
201 if (inList(*cand, region) || inList(*cand, rejected))
209 for (
unsigned ir = 0; ir < regions.size(); ++ir) {
210 B2DEBUG(50,
"region " << ir <<
" (" << regions[ir].size() <<
" cells).");
212 if (regions[ir].size() < m_minCells) {
213 B2DEBUG(50,
"Skipping region with " << regions[ir].size() <<
" cells.");
216 double xfirst = regions[ir][0].getCoord().first.X();
220 vector<unsigned> mergedList;
221 int xmin = m_nCellsPhi;
223 int ymin = m_nCellsR;
225 vector<TVector2> cellIds = {};
226 for (
unsigned ir2 = 0; ir2 < regions[ir].size(); ++ir2) {
228 B2DEBUG(100,
" " << regions[ir][ir2].
getID()
229 <<
" nSL " << regions[ir][ir2].getSLcount()
230 <<
" x1 " << hc.first.X() <<
" x2 " << hc.second.X()
231 <<
" y1 " << hc.first.Y() <<
" y2 " << hc.second.Y());
232 int ix = floor((hc.first.X() + M_PI) / 2. / M_PI * m_nCellsPhi + 0.5);
233 int iy = floor((hc.first.Y() + maxR - shiftR) / 2. / maxR * m_nCellsR + 0.5);
234 x += (hc.first.X() + hc.second.X());
235 if (xfirst - hc.first.X() > M_PI) {
238 }
else if (hc.first.X() - xfirst > M_PI) {
242 y += (hc.first.Y() + hc.second.Y());
244 vector<unsigned> idList = regions[ir][ir2].getIdList();
245 mergeIdList(mergedList, mergedList, idList);
246 xmin = min(xmin, ix);
247 xmax = max(xmax, ix);
248 ymin = min(ymin, iy);
249 ymax = max(ymax, iy);
250 cellIds.push_back(TVector2(ix, iy));
258 B2DEBUG(50,
"x " << x <<
" y " << y);
261 vector<unsigned> selectedList = {};
262 vector<unsigned> unselectedList = {};
263 selectHits(mergedList, selectedList, unselectedList);
267 m_tracks.appendNew(x, 2. * y, 0.);
269 for (
unsigned i = 0; i < selectedList.size(); ++i) {
270 unsigned its = selectedList[i];
271 track->addRelationTo(m_segmentHits[its]);
274 for (
unsigned i = 0; i < unselectedList.size(); ++i) {
275 unsigned its = unselectedList[i];
276 track->addRelationTo(m_segmentHits[its], -1.);
280 m_clusters.appendNew(xmin, xmax, ymin, ymax, cellIds);
281 track->addRelationTo(cluster);
287 const vector<CDCTriggerHoughCand>& candidates,
288 vector<CDCTriggerHoughCand>& merged,
289 vector<CDCTriggerHoughCand>& rejected,
290 unsigned short nSLmax)
const
292 for (
unsigned icand = 0; icand < candidates.size(); ++icand) {
293 B2DEBUG(120,
"compare center " << center.
getID()
294 <<
" to " << candidates[icand].getID());
295 if (inList(candidates[icand], merged) || inList(candidates[icand], rejected)) {
296 B2DEBUG(120,
" " << candidates[icand].
getID() <<
" already in list");
299 bool reject = inList(center, rejected);
300 if (connected(center, candidates[icand])) {
301 if (m_onlyLocalMax && candidates[icand].getSLcount() < nSLmax) {
302 B2DEBUG(100,
" lower than highest SLcount, rejected");
303 rejected.push_back(candidates[icand]);
304 }
else if (m_onlyLocalMax && !reject && candidates[icand].getSLcount() > nSLmax) {
305 B2DEBUG(100,
" new highest SLcount, clearing list");
306 nSLmax = candidates[icand].getSLcount();
307 for (
unsigned imerged = 0; imerged < merged.size(); ++imerged) {
308 rejected.push_back(merged[imerged]);
311 merged.push_back(candidates[icand]);
312 }
else if (m_onlyLocalMax && candidates[icand].getSLcount() > center.
getSLcount()) {
313 B2DEBUG(100,
" connected to rejected cell, skip");
315 }
else if (m_onlyLocalMax && reject) {
316 B2DEBUG(100,
" connected to rejected cell, rejected");
317 rejected.push_back(candidates[icand]);
319 B2DEBUG(100,
" connected");
320 merged.push_back(candidates[icand]);
322 vector<CDCTriggerHoughCand> cpyCand = candidates;
323 cpyCand.erase(cpyCand.begin() + icand);
324 addNeighbors(candidates[icand], cpyCand, merged, rejected, nSLmax);
331 const vector<CDCTriggerHoughCand>& list)
const
333 for (
unsigned i = 0; i < list.size(); ++i) {
334 if (a == list[i])
return true;
343 double ax1 = a.getCoord().first.X();
344 double ax2 = a.getCoord().second.X();
345 double ay1 = a.getCoord().first.Y();
346 double ay2 = a.getCoord().second.Y();
347 double bx1 = b.getCoord().first.X();
348 double bx2 = b.getCoord().second.X();
349 double by1 = b.getCoord().first.Y();
350 double by2 = b.getCoord().second.Y();
352 bool direct = ((ax2 == bx1 && ay1 == by1) ||
353 (ax1 == bx2 && ay1 == by1) ||
354 (ax1 == bx1 && ay2 == by1) ||
355 (ax1 == bx1 && ay1 == by2) ||
356 (ax1 + 2. * M_PI == bx2 && ay1 == by1) ||
357 (ax2 == bx1 + 2. * M_PI && ay1 == by1));
359 bool diagRise = ((ax2 == bx1 && ay2 == by1) ||
360 (ax1 == bx2 && ay1 == by2) ||
361 (ax1 + 2. * M_PI == bx2 && ay1 == by2) ||
362 (ax2 == bx1 + 2. * M_PI && ay2 == by1));
363 bool diagFall = ((ax1 == bx2 && ay2 == by1) ||
364 (ax2 == bx1 && ay1 == by2) ||
365 (ax2 == bx1 + 2. * M_PI && ay1 == by2) ||
366 (ax1 + 2. * M_PI == bx2 && ay2 == by1));
367 if (m_connect == 4)
return direct;
368 else if (m_connect == 6)
return (direct || diagRise);
369 else if (m_connect == 8)
return (direct || diagRise || diagFall);
370 else B2WARNING(
"Unknown option for connect " << m_connect <<
", using default.");
371 return (direct || diagRise);
378 CDCTrigger2DFinderModule::mergeIdList(std::vector<unsigned>& merged,
379 std::vector<unsigned>& a,
380 std::vector<unsigned>& b)
384 for (
auto it = a.begin(); it != a.end(); ++it) {
386 for (
auto it_in = merged.begin(); it_in != merged.end(); ++it_in) {
393 merged.push_back(*it);
397 for (
auto it = b.begin(); it != b.end(); ++it) {
399 for (
auto it_in = merged.begin(); it_in != merged.end(); ++it_in) {
406 merged.push_back(*it);
412 CDCTrigger2DFinderModule::findAllCrossingHits(std::vector<unsigned>& list,
413 double x1,
double x2,
414 double y1,
double y2,
417 double m, a, y1_h, y2_h;
418 for (
int iHit = 0; iHit < m_segmentHits.getEntries(); iHit++) {
419 unsigned short iSL = m_segmentHits[iHit]->getISuperLayer();
420 if (iSL % 2)
continue;
422 if (m_suppressClone && inputMap.find(iHit) == inputMap.end())
continue;
424 vector<double> phi = {0, 0, 0};
425 phi[0] = m_segmentHits[iHit]->getSegmentID() - TSoffset[iSL];
426 phi[1] = phi[0] + 0.5;
427 phi[2] = phi[0] - 0.5;
428 vector<double> r = {radius[iSL][0], radius[iSL][1], radius[iSL][1]};
429 for (
unsigned i = 0; i < 3; ++i) {
430 phi[i] *= 2. * M_PI / (TSoffset[iSL + 1] - TSoffset[iSL]);
431 m = cos(phi[i]) / r[i];
432 a = sin(phi[i]) / r[i];
434 y1_h = m * sin(x1 - 1e-10) - a * cos(x1 - 1e-10);
435 y2_h = m * sin(x2 + 1e-10) - a * cos(x2 + 1e-10);
437 if (y1_h > y2_h)
continue;
438 if (!((y1_h > y2 && y2_h > y2) || (y1_h < y1 && y2_h < y1))) {
439 list.push_back(iHit);
450 CDCTrigger2DFinderModule::selectHits(std::vector<unsigned>& list,
451 std::vector<unsigned>& selected,
452 std::vector<unsigned>& unselected)
454 std::vector<int> bestPerSL(5, -1);
455 for (
unsigned i = 0; i < list.size(); ++i) {
456 unsigned iax = m_segmentHits[list[i]]->getISuperLayer() / 2;
457 bool firstPriority = (m_segmentHits[list[i]]->getPriorityPosition() == 3);
458 if (bestPerSL[iax] < 0) {
461 unsigned itsBest = list[bestPerSL[iax]];
462 bool firstBest = (m_segmentHits[itsBest]->getPriorityPosition() == 3);
465 if ((firstPriority && !firstBest) ||
466 (firstPriority == firstBest &&
467 m_segmentHits[list[i]]->getSegmentID() > m_segmentHits[itsBest]->getSegmentID())) {
473 for (
unsigned i = 0; i < list.size(); ++i) {
474 unsigned iax = m_segmentHits[list[i]]->getISuperLayer() / 2;
475 if (
int(i) == bestPerSL[iax]) selected.push_back(list[i]);
476 else unselected.push_back(list[i]);
484 CDCTrigger2DFinderModule::patternClustering(
const cdcMap& inputMap)
487 TMatrix plane2(m_nCellsPhi / 2, m_nCellsR / 2);
488 TMatrix planeIcand(m_nCellsPhi, m_nCellsR);
489 for (
unsigned icand = 0; icand < houghCand.size(); ++icand) {
490 double x = (houghCand[icand].getCoord().first.X() +
491 houghCand[icand].getCoord().second.X()) / 2.;
492 unsigned ix = floor((x + M_PI) / 2. / M_PI * m_nCellsPhi);
493 double y = (houghCand[icand].getCoord().first.Y() +
494 houghCand[icand].getCoord().second.Y()) / 2.;
495 unsigned iy = floor((y + maxR - shiftR) / 2. / maxR * m_nCellsR);
496 plane2[ix / 2][iy / 2] += 1 << ((ix % 2) + 2 * (iy % 2));
497 planeIcand[ix][iy] = icand;
498 B2DEBUG(100,
"candidate " << icand <<
" at ix " << ix <<
" iy " << iy);
501 unsigned nX = m_nCellsPhi / 2;
502 unsigned nY = m_nCellsR / 2;
503 unsigned rX = m_clusterSizeX;
504 unsigned rY = m_clusterSizeY;
505 for (
unsigned ix = 0; ix < nX; ++ix) {
506 for (
unsigned iy = 0; iy < nY; ++iy) {
507 if (!plane2[ix][iy])
continue;
509 unsigned ileft = (ix - 1 + nX) % nX;
510 B2DEBUG(100,
"ix " << ix <<
" iy " << iy);
511 if (connectedLR(plane2[ileft][iy], plane2[ix][iy]) ||
512 (iy > 0 && connectedUD(plane2[ix][iy - 1], plane2[ix][iy])) ||
513 (iy > 0 && connectedDiag(plane2[ileft][iy - 1], plane2[ix][iy]))) {
514 B2DEBUG(100,
"skip connected square");
518 vector<unsigned> pattern(rX * rY, 0);
519 pattern[0] = plane2[ix][iy];
520 vector<TVector2> cellIds = {TVector2(2 * ix, 2 * iy)};
521 for (
unsigned ix2 = 0; ix2 < rX; ++ix2) {
522 for (
unsigned iy2 = 0; iy2 < rY; ++iy2) {
523 if (iy + iy2 >= nY)
continue;
524 unsigned ip = ix2 + rX * iy2;
525 unsigned iright = (ix + ix2 + nX) % nX;
526 ileft = (iright - 1 + nX) % nX;
527 B2DEBUG(100,
"ix2 " << ix2 <<
" ileft " << ileft <<
" iright " << iright);
530 connectedLR(plane2[ileft][iy + iy2], plane2[iright][iy + iy2])) ||
533 connectedUD(plane2[iright][iy + iy2 - 1], plane2[iright][iy + iy2])) ||
534 (ix2 > 0 && iy2 > 0 &&
535 pattern[ip - rX - 1] &&
536 connectedDiag(plane2[ileft][iy + iy2 - 1], plane2[iright][iy + iy2]))) {
537 pattern[ip] = plane2[iright][iy + iy2];
538 B2DEBUG(100,
"connect cell " << iright <<
" " << iy + iy2);
539 cellIds.push_back(TVector2(2 * (ix + ix2), 2 * (iy + iy2)));
543 B2DEBUG(100,
"cluster starting at " << ix <<
" " << iy);
545 bool overflowRight =
false;
546 bool overflowTop =
false;
547 for (
unsigned iy2 = 0; iy2 < rY; ++iy2) {
548 unsigned ip = rX - 1 + rX * iy2;
549 if (!pattern[ip])
continue;
550 unsigned iright = (ix + rX + nX) % nX;
551 ileft = (iright - 1 + nX) % nX;
552 if (connectedLR(plane2[ileft][iy + iy2], plane2[iright][iy + iy2]) ||
553 ((iy + iy2 + 1 < nY) &&
554 connectedDiag(plane2[ileft][iy + iy2], plane2[iright][iy + iy2 + 1]))) {
555 setReturnValue(
false);
556 overflowRight =
true;
560 for (
unsigned ix2 = 0; ix2 < rX; ++ix2) {
561 unsigned ip = ix2 + rX * (rY - 1);
562 if (!pattern[ip])
continue;
563 unsigned iright = (ix + ix2 + 1 + nX) % nX;
564 ileft = (iright - 1 + nX) % nX;
565 if (connectedUD(plane2[ileft][iy + rY - 1], plane2[ileft][iy + rY]) ||
566 connectedDiag(plane2[ileft][iy + rY - 1], plane2[iright][iy + rY])) {
567 setReturnValue(
false);
572 if (overflowRight && !overflowTop) {
573 B2DEBUG(100,
"cluster extends right of " << rX <<
" x " << rY <<
" area");
574 }
else if (overflowTop && !overflowRight) {
575 B2DEBUG(100,
"cluster extends above " << rX <<
" x " << rY <<
" area");
576 }
else if (overflowRight && overflowTop) {
577 B2DEBUG(100,
"cluster extends right and above " << rX <<
" x " << rY <<
" area");
580 unsigned topRight2 = topRightSquare(pattern);
581 unsigned topRight = topRightCorner(pattern[topRight2]);
582 unsigned bottomLeft = bottomLeftCorner(pattern[0]);
583 B2DEBUG(100,
"topRight2 " << topRight2 <<
" topRight " << topRight <<
" bottomLeft " << bottomLeft);
585 unsigned ixTR = 2 * (topRight2 % m_clusterSizeX) + (topRight % 2);
586 unsigned ixBL = bottomLeft % 2;
587 unsigned iyTR = 2 * (topRight2 / m_clusterSizeX) + (topRight / 2);
588 unsigned iyBL = bottomLeft / 2;
589 B2DEBUG(100,
"ixTR " << ixTR <<
" ixBL " << ixBL <<
" iyTR " << iyTR <<
" iyBL " << iyBL);
591 if (m_minCells > 1 && ixTR == ixBL && iyTR == iyBL) {
592 B2DEBUG(100,
"skipping cluster of size 1");
595 float centerX = 2 * ix + (ixTR + ixBL) / 2.;
596 if (centerX >= m_nCellsPhi) centerX -= m_nCellsPhi;
597 float centerY = 2 * iy + (iyTR + iyBL) / 2.;
598 B2DEBUG(100,
"center at cell (" << centerX <<
", " << centerY <<
")");
600 double x = -M_PI + (centerX + 0.5) * 2. * M_PI / m_nCellsPhi;
601 double y = -maxR + shiftR + (centerY + 0.5) * 2. * maxR / m_nCellsR;
602 B2DEBUG(100,
"center coordinates (" << x <<
", " << y <<
")");
604 vector <unsigned> idList = {};
605 if (m_hitRelationsFromCorners) {
606 unsigned icandTR = planeIcand[(ixTR + 2 * ix) % m_nCellsPhi][iyTR + 2 * iy];
607 unsigned icandBL = planeIcand[ixBL + 2 * ix][iyBL + 2 * iy];
608 vector<unsigned> candIdListTR = houghCand[icandTR].getIdList();
609 vector<unsigned> candIdListBL = houghCand[icandBL].getIdList();
610 mergeIdList(idList, candIdListTR, candIdListBL);
611 B2DEBUG(100,
"merge id lists from candidates " << icandTR <<
" and " << icandBL);
613 double dx = M_PI / m_nCellsPhi;
614 double dy = maxR / m_nCellsR;
615 double x1 = (round(centerX) == centerX) ? x - dx : x - 2 * dx;
616 double x2 = (round(centerX) == centerX) ? x + dx : x + 2 * dx;
617 double y1 = (round(centerY) == centerY) ? y - dy : y - 2 * dy;
618 double y2 = (round(centerY) == centerY) ? y + dy : y + 2 * dy;
619 findAllCrossingHits(idList, x1, x2, y1, y2, inputMap);
621 if (idList.size() == 0) {
622 setReturnValue(
false);
623 B2DEBUG(100,
"id list empty");
627 vector<unsigned> selectedList = {};
628 vector<unsigned> unselectedList = {};
629 selectHits(idList, selectedList, unselectedList);
633 m_tracks.appendNew(x, 2. * y, 0.);
635 for (
unsigned i = 0; i < selectedList.size(); ++i) {
636 unsigned its = selectedList[i];
637 track->addRelationTo(m_segmentHits[its]);
640 for (
unsigned i = 0; i < unselectedList.size(); ++i) {
641 unsigned its = unselectedList[i];
642 track->addRelationTo(m_segmentHits[its], -1.);
646 m_clusters.appendNew(2 * ix, 2 * (ix + m_clusterSizeX) - 1,
647 2 * iy, 2 * (iy + m_clusterSizeY) - 1,
649 track->addRelationTo(cluster);
658 CDCTrigger2DFinderModule::connectedLR(
unsigned patternL,
unsigned patternR)
663 bool connectDirect = (((patternL >> 3) & 1) && ((patternR >> 2) & 1)) ||
664 (((patternL >> 1) & 1) && ((patternR >> 0) & 1));
668 bool connectRise = ((patternL >> 1) & 1) && ((patternR >> 2) & 1);
672 bool connectFall = ((patternL >> 3) & 1) && ((patternR >> 0) & 1);
674 if (m_connect == 4)
return connectDirect;
675 else if (m_connect == 6)
return (connectDirect || connectRise);
676 else if (m_connect == 8)
return (connectDirect || connectRise || connectFall);
677 else B2WARNING(
"Unknown option for connect " << m_connect <<
", using default.");
678 return (connectDirect || connectRise);
682 CDCTrigger2DFinderModule::connectedUD(
unsigned patternD,
unsigned patternU)
690 bool connectDirect = (((patternU >> 0) & 1) && ((patternD >> 2) & 1)) ||
691 (((patternU >> 1) & 1) && ((patternD >> 3) & 1));
698 bool connectRise = ((patternU >> 1) & 1) && ((patternD >> 2) & 1);
705 bool connectFall = ((patternU >> 0) & 1) && ((patternD >> 3) & 1);
707 if (m_connect == 4)
return connectDirect;
708 else if (m_connect == 6)
return (connectDirect || connectRise);
709 else if (m_connect == 8)
return (connectDirect || connectRise || connectFall);
710 else B2WARNING(
"Unknown option for connect " << m_connect <<
", using default.");
711 return (connectDirect || connectRise);
715 CDCTrigger2DFinderModule::connectedDiag(
unsigned patternLD,
unsigned patternRU)
717 if (m_connect == 4)
return false;
724 return (((patternRU >> 0) & 1) && ((patternLD >> 3) & 1));
728 CDCTrigger2DFinderModule::topRightSquare(vector<unsigned>& pattern)
731 for (
unsigned index = pattern.size() - 1; index > 0; --index) {
732 if (!pattern[index])
continue;
734 unsigned ix = index % m_clusterSizeX;
735 unsigned iy = index / m_clusterSizeX;
736 if (ix < m_clusterSizeX - 1 && iy > 0) {
738 for (
unsigned index2 = index - 1; index2 > 0; --index2) {
739 if (!pattern[index2])
continue;
740 unsigned ix2 = index2 % m_clusterSizeX;
741 unsigned iy2 = index2 / m_clusterSizeX;
742 if (iy2 < iy && ix2 > ix) {
748 setReturnValue(
false);
749 B2DEBUG(100,
"topRightSquare not unique");
758 CDCTrigger2DFinderModule::topRightCorner(
unsigned pattern)
763 if ((pattern >> 3) & 1)
return 3;
764 if ((pattern >> 1) & 1) {
765 if ((pattern >> 2) & 1) {
766 setReturnValue(
false);
767 B2DEBUG(100,
"topRightCorner not unique");
771 if ((pattern >> 2) & 1)
return 2;
776 CDCTrigger2DFinderModule::bottomLeftCorner(
unsigned pattern)
781 if (pattern & 1)
return 0;
782 if ((pattern >> 2) & 1) {
783 if ((pattern >> 1) & 1) {
784 setReturnValue(
false);
785 B2DEBUG(100,
"bottomLeftCorner not unique");
789 if ((pattern >> 1) & 1)
return 1;