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 "framework/logging/Logger.h"
10#include "trg/cdc/NDFinderDefs.h"
11#include "trg/cdc/Clusterizend.h"
12using namespace Belle2;
13
14
15bool Clusterizend::hasBefore(cell_index entry, ushort dim)
16{
17 if (entry[dim] > 0 || m_params.varCyclic[dim]) {
18 return true;
19 }
20 return false;
21}
22cell_index Clusterizend::before(cell_index entry, ushort dim)
23{
24 if (entry[dim] > 0) {
25 entry[dim] -= 1;
26 return entry;
27 } else if (m_params.varCyclic[dim]) {
28 entry[dim] = m_valMax[dim];
29 return entry;
30 } else {
31 B2ERROR("no before(), check with hasBefore");
32 return entry;
33 }
34}
35
36bool Clusterizend::hasAfter(cell_index entry, ushort dim)
37{
38 if (entry[dim] < m_valMax[dim] || m_params.varCyclic[dim]) {
39 return true;
40 }
41 return false;
42}
43cell_index Clusterizend::after(cell_index entry, ushort dim)
44{
45 if (entry[dim] < m_valMax[dim]) {
46 entry[dim] += 1;
47 return entry;
48 } else if (m_params.varCyclic[dim]) {
49 entry[dim] = 0;
50 return entry;
51 } else {
52 B2ERROR("no after(), check with hasBefore()");
53 return entry;
54 }
55}
56
57
58void Clusterizend::blockcheck(std::vector<cell_index>* neighbors, cell_index elem, ushort dim)
59{
60 if (dim > 10) {
61 B2ERROR("dim too large, dim=" << dim);
62 }
63 if (hasBefore(elem, dim)) {
64 cell_index ind = before(elem, dim);
65 ushort leftwe = (*m_houghVals)[ind[0]][ind[1]][ind[2]];
66 ushort leftvi = m_houghVisit[ind[0]][ind[1]][ind[2]];
67 if (leftwe > m_params.minWeight && leftvi == 0) {
68 neighbors->push_back(ind);
69 }
70 if (m_params.diagonal && dim > 0) {
71 blockcheck(neighbors, ind, dim - 1);
72 }
73 }
74 if (hasAfter(elem, dim)) {
75 cell_index ind = after(elem, dim);
76 ushort rightwe = (*m_houghVals)[ind[0]][ind[1]][ind[2]];
77 ushort rightvi = m_houghVisit[ind[0]][ind[1]][ind[2]];
78 if (rightwe > m_params.minWeight && rightvi == 0) {
79 neighbors->push_back(ind);
80 }
81 if (m_params.diagonal && dim > 0) {
82 blockcheck(neighbors, ind, dim - 1);
83 }
84 }
85
86 if (dim > 0) {
87 blockcheck(neighbors, elem, dim - 1);
88 }
89}
90
91std::vector<cell_index>
92Clusterizend::regionQuery(cell_index entry)
93{
94 std::vector<cell_index> neighbours;
95 blockcheck(&neighbours, entry, m_dimSize - 1);
96 return neighbours;
97}
98
99std::vector<SimpleCluster>
100Clusterizend::dbscan()
101{
102 std::vector<SimpleCluster> C;
103 std::vector<cell_index> candidates = getCandidates();
104 for (unsigned long icand = 0; icand < candidates.size(); icand++) {
105 cell_index entry = candidates[icand];
106 c3index iom = entry[0];
107 c3index iph = entry[1];
108 c3index ith = entry[2];
109
110 if (m_houghVisit[iom][iph][ith] == 0) {
111 //B2DEBUG(25, "dbscan: unvisited cell");
112 m_houghVisit[iom][iph][ith] = 1;
113 std::vector<cell_index> N = regionQuery(entry);
114 if (N.size() >= m_params.minPts) {
115 //B2DEBUG(25, "dbscan: starting cluster, neightbors = " << N.size());
116 SimpleCluster newCluster(entry);
117 expandCluster(N, newCluster);
118 C.push_back(newCluster);
119 }
120 }
121 }
122 return C;
123}
124
125void
126Clusterizend::expandCluster(std::vector<cell_index>& N, SimpleCluster& C)
127{
128 while (N.size() > 0) {
129 cell_index nextP = N.back();
130 N.pop_back();
131 ushort iom = nextP[0];
132 ushort iph = nextP[1];
133 ushort ith = nextP[2];
134 if (m_houghVisit[iom][iph][ith] == 0) {
135 m_houghVisit[iom][iph][ith] = 1;
136 if ((*m_houghVals)[iom][iph][ith] < m_params.minWeight) {
137 continue;
138 }
139 std::vector<cell_index> nextN = regionQuery(nextP);
140 if (nextN.size() >= m_params.minPts) {
141 N.insert(N.end(), nextN.begin(), nextN.end());
142 }
143 C.append(nextP);
144 }
145 }
146}
147
148std::vector<cell_index>
150{
151 std::vector<cell_index> candidates;
153 for (c3index iom = 0; iom < 40; iom++) {
154 for (c3index iph = 0; iph < 384; iph++) {
155 for (c3index ith = 0; ith < 9; ith++) {
156 if ((*m_houghVals)[iom][iph][ith] > m_params.minWeight) {
157 cell_index elem = {iom, iph, ith};
158 candidates.push_back(elem);
159 }
160 }
161 }
162 }
163 return candidates;
164}
165
166std::pair<cell_index, unsigned long> Clusterizend::getGlobalMax()
167{
168 unsigned long maxValue = 0;
169 cell_index maxIndex = {0, 0, 0};
170 for (c3index iom = 0; iom < 40; iom++) {
171 for (c3index iph = 0; iph < 384; iph++) {
172 for (c3index ith = 0; ith < 9; ith++) {
173 if ((*m_houghVals)[iom][iph][ith] > maxValue) {
174 maxValue = (*m_houghVals)[iom][iph][ith];
175 maxIndex = {iom, iph, ith};
176 }
177 }
178 }
179 }
180 return {maxIndex, maxValue};
181}
182
183void Clusterizend::deleteMax(cell_index maxIndex)
184{
185 c3index omIndex = maxIndex[0];
186 c3index phIndex = maxIndex[1];
187 c3index thIndex = maxIndex[2];
188 for (c3index ith = std::max<int>(0, thIndex - m_params.thetaTrim); ith < std::min<int>(9, thIndex + m_params.thetaTrim + 1);
189 ith++) {
190 for (c3index iom = std::max<int>(0, omIndex - m_params.omegaTrim); iom < std::min<int>(40, omIndex + m_params.omegaTrim + 1);
191 iom++) {
192 c3index phiIndex = phIndex + omIndex - iom;
193 c3index relativePhi = phiIndex - phIndex;
194 if (relativePhi > 0) {
195 for (c3index iph = phiIndex - m_params.phiTrim; iph < phiIndex + m_params.phiTrim + std::floor(2.4 * relativePhi); iph++) {
196 c3index iphMod = (iph + 384) % 384;
197 (*m_houghVals)[iom][iphMod][ith] = 0;
198 }
199 } else if (relativePhi < 0) {
200 for (c3index iph = phiIndex - m_params.phiTrim + std::ceil(2.4 * relativePhi); iph < phiIndex + m_params.phiTrim + 1; iph++) {
201 c3index iphMod = (iph + 384) % 384;
202 (*m_houghVals)[iom][iphMod][ith] = 0;
203 }
204 } else {
205 for (c3index iph = phiIndex - m_params.phiTrim; iph < phiIndex + m_params.phiTrim + 1; iph++) {
206 c3index iphMod = (iph + 384) % 384;
207 (*m_houghVals)[iom][iphMod][ith] = 0;
208 }
209 }
210 }
211 }
212}
213
214std::vector<SimpleCluster> Clusterizend::makeClusters()
215{
216 std::vector<SimpleCluster> candidates;
217 for (unsigned long iter = 0; iter < m_params.iterations; iter++) {
218 auto [globalMax, peakWeight] = getGlobalMax();
219 if (peakWeight < m_params.minPeakWeight || peakWeight == 0) {
220 break;
221 }
222 auto [newCluster, totalWeight] = createCluster(globalMax);
223 if (totalWeight >= m_params.minTotalWeight) {
224 candidates.push_back(newCluster);
225 }
226 deleteMax(globalMax);
227 }
228 return candidates;
229}
230
231std::pair<SimpleCluster, unsigned long> Clusterizend::createCluster(cell_index maxIndex)
232{
233 SimpleCluster fixedCluster;
234 c3index omIndex = maxIndex[0];
235 c3index phIndex = maxIndex[1];
236 c3index thIndex = maxIndex[2];
237 unsigned long totalClusterWeight = 0;
238
239 for (c3index ith = std::max<int>(0, thIndex - 1); ith < std::min<int>(9, thIndex + 2); ith++) {
240 for (c3index iph = phIndex - 1; iph < phIndex + 2; iph++) {
241 c3index iphMod = (iph + 384) % 384;
242 cell_index newMemberIndex = {omIndex, iphMod, ith};
243 fixedCluster.append(newMemberIndex);
244 totalClusterWeight += (*m_houghVals)[omIndex][iphMod][ith];
245 }
246 }
247 if (omIndex - 1 >= 0) {
248 for (c3index ith = std::max<int>(0, thIndex - 1); ith < std::min<int>(9, thIndex + 2); ith++) {
249 for (c3index iph = phIndex + 1; iph < phIndex + 4; iph++) {
250 c3index iphMod = (iph + 384) % 384;
251 cell_index newMemberIndex = {omIndex - 1, iphMod, ith};
252 fixedCluster.append(newMemberIndex);
253 totalClusterWeight += (*m_houghVals)[omIndex - 1][iphMod][ith];
254 }
255 }
256 }
257 if (omIndex + 1 < 40) {
258 for (c3index ith = std::max<int>(0, thIndex - 1); ith < std::min<int>(9, thIndex + 2); ith++) {
259 for (c3index iph = phIndex - 3; iph < phIndex; iph++) {
260 c3index iphMod = (iph + 384) % 384;
261 cell_index newMemberIndex = {omIndex + 1, iphMod, ith};
262 fixedCluster.append(newMemberIndex);
263 totalClusterWeight += (*m_houghVals)[omIndex + 1][iphMod][ith];
264 }
265 }
266 }
267 return {fixedCluster, totalClusterWeight};
268}
std::vector< cell_index > getCandidates()
clustererParams m_params
Clusterizend.
Definition: Clusterizend.h:212
bool hasBefore(cell_index entry, ushort dim)
Clustering logic.
Definition: Clusterizend.cc:15
Type for found clusters.
Definition: Clusterizend.h:45
void append(cell_index nextEntry)
Add a track-space cell to the cluster.
Definition: Clusterizend.h:78
Abstract base class for different kinds of events.
unsigned char iterations
Number of iterations of the cluster searching for each Hough space.
Definition: Clusterizend.h:31
unsigned char minPts
minimum number of neighbours for a cluster core cell
Definition: Clusterizend.h:23
std::vector< bool > varCyclic
Ordering of track parameters and position of cyclic variable (phi)
Definition: Clusterizend.h:39
bool diagonal
Consider diagonal adjacent cells as neighbors.
Definition: Clusterizend.h:25
unsigned short minTotalWeight
Cut on the total weight of all cells in the 3d volume.
Definition: Clusterizend.h:27
unsigned short minWeight
minimum weight for a cluster cell
Definition: Clusterizend.h:21
unsigned char omegaTrim
Number of deleted cells in omega in each direction of the maximum.
Definition: Clusterizend.h:33
unsigned char thetaTrim
Number of deleted cells in theta in each direction of the maximum.
Definition: Clusterizend.h:37
unsigned short minPeakWeight
Cut on the peak cell weight.
Definition: Clusterizend.h:29
unsigned char phiTrim
Number of deleted cells in phi in each direction of the maximum.
Definition: Clusterizend.h:35