Belle II Software development
Clusterizend.cc
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8
9#include <vector>
10#include <utility>
11#include <array>
12#include <cmath>
13#include "trg/cdc/NDFinderDefs.h"
14#include "trg/cdc/Clusterizend.h"
15
16using namespace Belle2;
17
18// Create all the clusters in the Hough space
19std::vector<SimpleCluster> Clusterizend::makeClusters()
20{
21 std::vector<SimpleCluster> candidateClusters;
22 c3array houghSpaceBackup = *m_houghSpace;
23 for (unsigned short quadrant = 0; quadrant < 4; ++quadrant) {
24 for (unsigned short section = 0; section < 4; ++section) {
25 std::array<c3index, 2> sectionBounds = getSectionBounds(quadrant, section);
26 iterateOverSection(sectionBounds, candidateClusters);
27 if (m_clustererParams.iterations > 1) *m_houghSpace = houghSpaceBackup;
28 }
29 }
30 return candidateClusters;
31}
32
33// Get the phi bounds of one quadrant section
34std::array<c3index, 2> Clusterizend::getSectionBounds(const unsigned short quadrant, const unsigned section)
35{
36 c3index quadrantSize = m_clustererParams.nPhi / 4;
37 c3index quadrantOffset = m_clustererParams.nPhi / 8;
38 c3index sectionSize = quadrantSize / 4;
39
40 c3index quadrantStart = quadrant * quadrantSize + quadrantOffset;
41 c3index sectionStart = quadrantStart + section * sectionSize;
42 c3index sectionEnd = sectionStart + sectionSize;
43
44 return {sectionStart, sectionEnd};
45}
46
47// Iterate m_clustererParams.iterations times over one section
48void Clusterizend::iterateOverSection(const std::array<c3index, 2>& sectionBounds, std::vector<SimpleCluster>& candidateClusters)
49{
50 for (unsigned short _ = 0; _ < m_clustererParams.iterations; ++_) {
51 auto [sectionPeak, peakWeight] = getSectionPeak(sectionBounds);
52 // Ignore the cluster if the peak weight is below 10 (reduces processing)
53 if (peakWeight < 10) {
54 break;
55 }
56 SimpleCluster newCluster = createCluster(sectionPeak);
57 newCluster.setPeakCell(sectionPeak);
58 newCluster.setPeakWeight(peakWeight);
59 candidateClusters.push_back(newCluster);
60 if (m_clustererParams.iterations > 1) deletePeakSurroundings(sectionPeak);
61 }
62}
63
64// Returns the global section peak index and weight
65std::pair<cell_index, unsigned int> Clusterizend::getSectionPeak(const std::array<c3index, 2>& sectionBounds)
66{
67 unsigned int peakValue = 0;
68 cell_index peakCell = {0, 0, 0};
69 for (c3index omegaIdx = 0; omegaIdx < m_clustererParams.nOmega; ++omegaIdx) {
70 for (c3index phiIdx = sectionBounds[0]; phiIdx < sectionBounds[1]; ++phiIdx) {
71 c3index phiIdxMod = phiIdx % m_clustererParams.nPhi;
72 for (c3index cotIdx = 0; cotIdx < m_clustererParams.nCot; ++cotIdx) {
73 if ((*m_houghSpace)[omegaIdx][phiIdxMod][cotIdx] > peakValue) {
74 peakValue = (*m_houghSpace)[omegaIdx][phiIdxMod][cotIdx];
75 peakCell = {omegaIdx, phiIdxMod, cotIdx};
76 }
77 }
78 }
79 }
80 return {peakCell, peakValue};
81}
82
83// Creates the surrounding cluster (fixed shape) around the section peak index
85{
86 c3index omegaPeak = peakCell[0];
87 c3index phiPeak = peakCell[1];
88 c3index cotPeak = peakCell[2];
89
90 c3index cotLower = cotPeak - 1;
91 c3index cotUpper = cotPeak + 1;
92
93 c3index phiLeft = (phiPeak - 1 + m_clustererParams.nPhi) % m_clustererParams.nPhi;
94 c3index phiRight = (phiPeak + 1 + m_clustererParams.nPhi) % m_clustererParams.nPhi;
95
96 c3index omegaUpperRight = omegaPeak - 1;
97 c3index omegaLowerLeft = omegaPeak + 1;
98
99 // Add in-bound cells to the cluster:
100 SimpleCluster fixedCluster;
101 fixedCluster.appendCell(peakCell);
102 fixedCluster.appendCell({omegaPeak, phiLeft, cotPeak});
103 fixedCluster.appendCell({omegaPeak, phiRight, cotPeak});
104 if (cotLower >= 0) {
105 fixedCluster.appendCell({omegaPeak, phiPeak, cotLower});
106 }
107 if (cotUpper < m_clustererParams.nCot) {
108 fixedCluster.appendCell({omegaPeak, phiPeak, cotUpper});
109 }
110 if (omegaUpperRight >= 0) {
111 fixedCluster.appendCell({omegaUpperRight, phiRight, cotPeak});
112 }
113 if (omegaLowerLeft < m_clustererParams.nOmega) {
114 fixedCluster.appendCell({omegaLowerLeft, phiLeft, cotPeak});
115 }
116 return fixedCluster;
117}
118
119// Deletes the surroundings of the peak index with a butterfly cutout
121{
122 c3index omegaPeak = peakCell[0];
123 c3index phiPeak = peakCell[1];
124
125 c3index omegaLowerBound = std::max<unsigned short>(0, omegaPeak - m_clustererParams.omegaTrim);
126 c3index omegaUpperBound = std::min<unsigned short>(m_clustererParams.nOmega, omegaPeak + m_clustererParams.omegaTrim + 1);
127
128 for (c3index cotIdx = 0; cotIdx < m_clustererParams.nCot; ++cotIdx) {
129 for (c3index omegaIdx = omegaLowerBound; omegaIdx < omegaUpperBound; ++omegaIdx) {
130 c3index phiCell = phiPeak + omegaPeak - omegaIdx;
131 c3index relativePhi = phiCell - phiPeak;
132
133 if (relativePhi > 0) {
134 DeletionBounds firstBounds = {
135 phiCell - m_clustererParams.phiTrim,
136 static_cast<c3index>(phiCell + m_clustererParams.phiTrim + std::floor(2.4 * relativePhi)),
137 omegaIdx,
138 cotIdx
139 };
140 clearHoughSpaceRow(firstBounds);
141 } else if (relativePhi < 0) {
142 DeletionBounds secondBounds = {
143 static_cast<c3index>(phiCell - m_clustererParams.phiTrim + std::ceil(2.4 * relativePhi)),
144 phiCell + m_clustererParams.phiTrim + 1,
145 omegaIdx,
146 cotIdx
147 };
148 clearHoughSpaceRow(secondBounds);
149 } else {
150 DeletionBounds thirdBounds = {
151 phiCell - m_clustererParams.phiTrim,
152 phiCell + m_clustererParams.phiTrim + 1,
153 omegaIdx,
154 cotIdx
155 };
156 clearHoughSpaceRow(thirdBounds);
157 }
158 }
159 }
160}
161
162// Clears a single omega row
164{
165 for (c3index phiIdx = bounds.phiLowerBound; phiIdx < bounds.phiUpperBound; ++phiIdx) {
166 c3index phiIdxMod = (phiIdx + m_clustererParams.nPhi) % m_clustererParams.nPhi;
167 (*m_houghSpace)[bounds.omega][phiIdxMod][bounds.cot] = 0;
168 }
169}
SimpleCluster createCluster(const cell_index &peakCell)
Creates the surrounding cluster (fixed shape) around the section peak index.
std::vector< SimpleCluster > makeClusters()
Create all the clusters in the Hough space.
std::pair< cell_index, unsigned int > getSectionPeak(const std::array< c3index, 2 > &sectionBounds)
Returns the global section peak index and weight.
ClustererParameters m_clustererParams
The struct holding the cluster parameters.
void deletePeakSurroundings(const cell_index &peakCell)
Deletes the surroundings of such a cluster.
void clearHoughSpaceRow(const DeletionBounds &bounds)
Method to delete a omega row for the cluster deletion in deletePeakSurroundings method.
c3array * m_houghSpace
Pointer to the Hough space.
std::array< c3index, 2 > getSectionBounds(const unsigned short quadrant, const unsigned section)
Get the phi bounds of one quadrant section.
void iterateOverSection(const std::array< c3index, 2 > &sectionBounds, std::vector< SimpleCluster > &candidateClusters)
Iterate m_clustererParams.iterations times over one section.
Type for found clusters.
void setPeakCell(const cell_index &peakCell)
Set the peak index (found as the section peak) of the cluster.
void setPeakWeight(const unsigned int peakWeight)
Set the weight of the peak cluster cell.
void appendCell(const cell_index &newClusterCell)
Add a track-space cell to the cluster.
c3array::index c3index
index of Hough space 3D array
boost::multi_array< unsigned short, 3 > c3array
The Hough space is a 3D array (omega, phi, cot)
std::array< c3index, 3 > cell_index
The cell index of one Hough space bin.
Abstract base class for different kinds of events.
Struct containing the deletion bounds of a omega row.