Belle II Software development
NDFinder.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 <string>
10#include <cmath>
11#include <iostream>
12#include <set>
13#include <fstream>
14#include "framework/logging/Logger.h"
15#include "boost/iostreams/filter/gzip.hpp"
16#include "boost/iostreams/filtering_streambuf.hpp"
17#include "boost/iostreams/filtering_stream.hpp"
18#include "trg/cdc/NDFinder.h"
19#include "TMath.h"
20
21using namespace Belle2;
22
23
24void NDFinder::init(unsigned short minWeight, unsigned char minPts,
25 bool diagonal, unsigned char minSuperAxial, unsigned char minSuperStereo,
26 float thresh,
27 unsigned char minCells, bool dbscanning, unsigned short minTotalWeight, unsigned short minPeakWeight, unsigned char iterations,
28 unsigned char omegaTrim, unsigned char phiTrim, unsigned char thetaTrim,
29 bool verbose,
30 std::string& axialFile, std::string& stereoFile)
31{
32 m_params.minSuperAxial = (unsigned char) minSuperAxial;
33 m_params.minSuperStereo = (unsigned char) minSuperStereo;
34 m_params.thresh = (float) thresh;
35 m_params.minCells = (unsigned char) minCells;
36 m_params.dbscanning = (bool) dbscanning;
37 m_params.axialFile = axialFile;
38 m_params.stereoFile = stereoFile;
39 m_clustererParams.minWeight = (unsigned short) minWeight;
40 m_clustererParams.minPts = (unsigned char) minPts;
41 m_clustererParams.diagonal = diagonal;
42 m_clustererParams.minTotalWeight = (unsigned short) minTotalWeight;
43 m_clustererParams.minPeakWeight = (unsigned short) minPeakWeight;
44 m_clustererParams.iterations = (unsigned char) iterations;
45 m_clustererParams.omegaTrim = (unsigned char) omegaTrim;
46 m_clustererParams.phiTrim = (unsigned char) phiTrim;
47 m_clustererParams.thetaTrim = (unsigned char) thetaTrim;
48 m_verbose = verbose;
49
50
51 initBins();
52 B2DEBUG(25, "initialized binnings");
53
54 initHitModAxSt(*m_parrayHitMod);
55 B2DEBUG(25, "initialized HitMod, a map of tsid to (orient, relid, letter).");
56
58 loadArray(m_params.axialFile, m_compAxBins, *m_pcompAxial);
59 B2DEBUG(25, "loaded zero suppressed axial array ");
60 loadArray(m_params.stereoFile, m_compStBins, *m_pcompStereo);
61 B2DEBUG(25, "loaded zero suppressed stereo array ");
62
64 restoreZeros(m_expAxBins, m_compAxBins, *m_parrayAxialExp, *m_pcompAxial);
65 B2DEBUG(25, "restored expanded axial array (11/32 phi) ");
66 restoreZeros(m_expStBins, m_compStBins, *m_parrayStereoExp, *m_pcompStereo);
67 B2DEBUG(25, "restored expanded stereo array (11/32 phi) ");
69 B2DEBUG(25, "squeezed axial array (11/32 phi) --> (7/32 phi): ");
70 squeezeAll(m_stBins, *m_parrayStereo, *m_parrayStereoExp, m_params.parcels, m_params.parcelsExp);
71 B2DEBUG(25, "squeezed stereo array (11/32 phi) --> (7/32 phi)");
72
73 reset();
75 m_clusterer.setPlaneShape(m_planeShape);
76}
77
79{
90 m_nTS = 2336;
91 m_nSL = 9;
92 m_params.phigeo = 32;
93
94 m_nAx = 41;
95 m_nSt = 32;
96 m_nPrio = 3;
97
98 m_nOmega = 40;
99 m_nPhiFull = 384;
100 m_nTheta = 9;
101 m_nPhiOne = m_nPhiFull / m_params.phigeo; // 384/32 = 12
103 m_nPhiComp = 15;
105 m_nPhiUse = m_params.parcels * m_nPhiOne;
107 m_nPhiExp = m_params.parcelsExp * m_nPhiOne;
108
109 m_axBins.hitid = m_nAx;
110 m_stBins.hitid = m_nSt;
111 m_axBins.phi = m_nPhiUse; //84
112 m_stBins.phi = m_nPhiUse; //84
113 m_compAxBins.hitid = m_nAx;
114 m_compStBins.hitid = m_nSt;
115 m_compAxBins.phi = m_nPhiComp;
116 m_compStBins.phi = m_nPhiComp;
117 m_compAxBins.theta = 1;
118 m_expAxBins.hitid = m_nAx;
119 m_expStBins.hitid = m_nSt;
120 m_expAxBins.phi = m_nPhiExp; //132
121 m_expStBins.phi = m_nPhiExp; //132
122
123 m_fullBins.hitid = m_nTS;
124 m_fullBins.phi = m_nPhiFull;
125
126 m_pc5shapeax = {{ m_nAx, m_nPrio, m_nOmega, m_nPhiUse, m_nTheta }};
127 m_pc5shapest = {{ m_nSt, m_nPrio, m_nOmega, m_nPhiUse, m_nTheta }};
128 m_pc3shape = {{ m_nOmega, m_nPhiFull, m_nTheta }};
129 m_pc2shapeHitMod = {{ m_nTS, m_nPrio}};
130 m_pc5shapeCompAx = {{ m_nAx, m_nPrio, m_nOmega, m_nPhiComp, 1 }};
131 m_pc5shapeCompSt = {{ m_nSt, m_nPrio, m_nOmega, m_nPhiComp, m_nTheta }};
132 m_pc5shapeExpAx = {{ m_nAx, m_nPrio, m_nOmega, m_nPhiExp, m_nTheta }};
133 m_pc5shapeExpSt = {{ m_nSt, m_nPrio, m_nOmega, m_nPhiExp, m_nTheta }};
134
135 m_parrayAxial = new c5array(m_pc5shapeax);
136 m_parrayStereo = new c5array(m_pc5shapest);
137 m_phoughPlane = new c3array(m_pc3shape);
138 m_parrayHitMod = new c2array(m_pc2shapeHitMod);
139 m_pcompAxial = new c5array(m_pc5shapeCompAx);
140 m_pcompStereo = new c5array(m_pc5shapeCompSt);
141 m_parrayAxialExp = new c5array(m_pc5shapeExpAx);
142 m_parrayStereoExp = new c5array(m_pc5shapeExpSt);
143
144 m_nWires = {160, 160, 192, 224, 256, 288, 320, 352, 384};
145
146 m_planeShape = {m_nOmega, m_nPhiFull, m_nTheta}; //{40, 384, 9};
147
149 std::vector<float> omegaRange = { -5., 5.};
150 std::vector<float> phiRange = {0., 11.25};
151 std::vector<float> thetaRange = {19., 140.};
152 float ssOmega = (omegaRange[1] - omegaRange[0]) / m_nOmega; //40;
153 float ssPhi = (phiRange[1] - phiRange[0]) / m_nPhiOne; //12;
154 float ssTheta = (thetaRange[1] - thetaRange[0]) / m_nTheta; //9;
155 m_acceptRanges.push_back(omegaRange);
156 m_acceptRanges.push_back(phiRange);
157 m_acceptRanges.push_back(thetaRange);
158 m_slotSizes.push_back(ssOmega);
159 m_slotSizes.push_back(ssPhi);
160 m_slotSizes.push_back(ssTheta);
161}
162
163
164
165void NDFinder::loadArray(const std::string& filename, ndbinning bins, c5array& hitsToTracks)
166{
167 std::vector<c5elem> flatArray;
168 std::ifstream arrayFileGZ(filename, std::ios_base::in | std::ios_base::binary);
169 boost::iostreams::filtering_istream arrayStream;
170 arrayStream.push(boost::iostreams::gzip_decompressor());
171 arrayStream.push(arrayFileGZ);
172 c5elem uline;
173 if (arrayFileGZ.is_open()) {
174 while (arrayStream >> uline) {
175 flatArray.push_back(uline);
176 }
177 arrayFileGZ.close();
178 } else {
179 B2ERROR("could not open array file: " << filename);
180 }
181 B2DEBUG(25, "loaded array from file " << filename);
182 unsigned long icount = 0;
183 for (c5index ihit = 0; ihit < bins.hitid; ihit++) {
184 for (c5index iprio = 0; iprio < bins.prio; iprio++) {
185 for (c5index iomega = 0; iomega < bins.omega; iomega++) {
186 for (c5index iphi = 0; iphi < bins.phi; iphi++) {
187 for (c5index itheta = 0; itheta < bins.theta; itheta++) {
188 hitsToTracks[ihit][iprio][iomega][iphi][itheta] = flatArray[icount];
189 icount++;
190 }
191 }
192 }
193 }
194 }
195}
196
197
198void NDFinder::initHitModAxSt(c2array& hitMod)
199{
200 unsigned short phigeo = m_params.phigeo; // 32
201 std::vector<int> modSLs; //nWires per SL in 1/32 sector (9)
202 std::vector<int> toslid; //tsid to sl map (2336)
203 std::vector<int> sloffsets = {0}; // integrated number of wires in inner SLs (9);
204 std::vector<int> modoffsetsAxSt = {0, 0}; // integrated number of wires in inner SLs in 1/32 sector, separate for axial and stereo SLs (9);
205 for (int isl = 0; isl < m_nSL; isl++) {
206 modSLs.push_back(m_nWires[isl] / phigeo);
207 for (int itsrel = 0; itsrel < m_nWires[isl]; itsrel++) {
208 toslid.push_back(isl);
209 }
210 sloffsets.push_back(sloffsets[isl] + m_nWires[isl]);
211 int last = modoffsetsAxSt[isl];
212 modoffsetsAxSt.push_back(last + m_nWires[isl] / phigeo);
213 }
214 for (int its = 0; its < m_nTS; its++) { // 2336
215 int sl = toslid[its];
216 bool isAxial = (sl % 2 == 0);
217 int idInSL = its - sloffsets[sl];
218 int modSL = modSLs[sl];
219 int modId = idInSL % modSL;
220 int letter = (int) floor(idInSL / modSL);
221 int relId = (int)(modoffsetsAxSt[sl] + modId);
222 hitMod[its][0] = (int)(isAxial);
223 hitMod[its][1] = relId;
224 hitMod[its][2] = letter;
225 }
226}
227
228
229void NDFinder::squeezeOne(c5array& writeArray, c5array& readArray, int outparcels, int inparcels, c5index ihit, c5index iprio,
230 c5index itheta, c5elem nomega)
231{
232 int outnphi = (int)(12 * outparcels);
233 c5index trafstart = (c5index)((inparcels - outparcels) / 2 * 12);
234 c5index trafend = (c5index)(trafstart + outnphi);
235 for (c5index iomega = 0; iomega < nomega; iomega++) {
236 for (c5index iphi = 0; iphi < outnphi; iphi++) {
237 c5index readPhi = trafstart + iphi;
238 writeArray[ihit][iprio][iomega][iphi][itheta] = readArray[ihit][iprio][iomega][readPhi][itheta];
239 }
240 for (c5index iphi = 0; iphi < trafstart; iphi++) {
241 c5index writePhi = (c5index)(outnphi - trafstart + iphi);
242 writeArray[ihit][iprio][iomega][writePhi][itheta] += readArray[ihit][iprio][iomega][iphi][itheta];
243 }
244 for (c5index iphi = 0; iphi < trafstart; iphi++) {
245 c5index readPhi = trafend + iphi;
246 writeArray[ihit][iprio][iomega][iphi][itheta] += readArray[ihit][iprio][iomega][readPhi][itheta];
247 }
248 }
249}
250
251
252void NDFinder::squeezeAll(ndbinning writebins, c5array& writeArray, c5array& readArray, int outparcels, int inparcels)
253{
254 for (c5index ihit = 0; ihit < writebins.hitid; ihit++) {
255 for (c5index iprio = 0; iprio < writebins.prio; iprio++) {
256 for (c5index itheta = 0; itheta < writebins.theta; itheta++) {
257 squeezeOne(writeArray, readArray, outparcels, inparcels, ihit, iprio, itheta, writebins.omega);
258 }
259 }
260 }
261}
262
263
264void NDFinder::restoreZeros(ndbinning zerobins, ndbinning compbins, c5array& expArray, const c5array& compArray)
265{
266 B2DEBUG(25, "restoreZeros: zerobins.theta " << zerobins.theta << ", combins.theta " << compbins.theta);
267 for (c5index ihit = 0; ihit < compbins.hitid; ihit++) {
268 for (c5index iprio = 0; iprio < compbins.prio; iprio++) {
269 for (c5index iomega = 0; iomega < compbins.omega; iomega++) {
270 for (c5index itheta = 0; itheta < compbins.theta; itheta++) {
271 c5elem phiStart = compArray[ihit][iprio][iomega][0][itheta];
272 c5elem phiWidth = compArray[ihit][iprio][iomega][1][itheta];
273 for (c5index iphi = 0; iphi < phiWidth; iphi++) {
274 c5elem phiCur = phiStart + iphi;
275 expArray[ihit][iprio][iomega][phiCur][itheta] = compArray[ihit][iprio][iomega][iphi + 2][itheta];
276 if (compbins.theta == 1) { // case axial, expand in theta
277 for (c5index jtheta = 1; jtheta < zerobins.theta; jtheta++) {
278 expArray[ihit][iprio][iomega][phiCur][jtheta] = compArray[ihit][iprio][iomega][iphi + 2][itheta];
279 }
280 }
281 }
282 }
283 }
284 }
285 }
286}
287
288
289void NDFinder::printArray3D(c3array& hitsToTracks, ndbinning bins, ushort phiInc = 1, ushort omInc = 1, ushort divide = 4,
290 ushort minWeightShow = 1)
291{
292 ushort phistart = 0;
293 ushort phiend = bins.phi;
294 bool started = false;
295 unsigned long phiSlice = 0;
296 for (c3index iphi = 0; iphi < bins.phi; iphi++) {
297 for (c3index itheta = 0; itheta < bins.theta; itheta++) {
298 for (c3index iomega = 0; iomega < bins.omega; iomega++) {
299 phiSlice += hitsToTracks[iomega][iphi][itheta];
300 }
301 }
302 if (phiSlice == 0 and not started) {
303 phistart = iphi + 1;
304 } else if (phiSlice != 0 and not started) {
305 started = true;
306 } else if (phiSlice != 0 and started) {
307 phiend = iphi;
308 } else if (phiSlice == 0 and started) {
309 phiend = iphi;
310 break;
311 }
312 }
313
314 B2DEBUG(25, "printArray3D, phistart = " << phistart << ", phiend = " << phiend);
315 auto d3shp = hitsToTracks.shape();
316 B2DEBUG(25, "printArray shape: " << d3shp[0] << ", " << d3shp[1] << ", " << d3shp[2]);
317
318 if (phiend == phistart) {
319 return;
320 }
321 c3index itheta = 4; // only print itheta = 4
322 for (c3index iomega = 0; iomega < bins.omega; iomega += omInc) {
323 for (c3index iphi = phistart; iphi < phiend; iphi += phiInc) {
324 // reduce printed weight
325 ushort valRed = (ushort)((hitsToTracks[iomega][iphi][itheta]) / divide);
326 if (valRed <= minWeightShow) // skip small weights
327 std::cout << " ";
328 else
329 std::cout << valRed;
330 }
331 std::cout << "|" << std::endl;
332 }
333}
334
335
337void NDFinder::addLookup(unsigned short ihit)
338{
339 c2array& arrayHitMod = *m_parrayHitMod;
340
341 c2elem orient = arrayHitMod[m_hitIds[ihit]][0];
342 c2elem hitr = arrayHitMod[m_hitIds[ihit]][1];
343 c2elem letter = arrayHitMod[m_hitIds[ihit]][2];
344
345 unsigned short prio = m_prioPos[ ihit ];
346 short letterShort = (short) letter;
347
348 // Get hit contribution to cluster:
349 // 7 of 32 phi parcels: center = 3
350 short DstartShort = (letterShort - 3) % m_params.phigeo * m_nPhiOne;
351 if (DstartShort < 0) {DstartShort = m_nPhiFull + DstartShort;}
352 // Add hit to hough plane
353 // 11 of 32 phi parcels: center = 5
354 short DstartComp = (letterShort - 5) % m_params.phigeo * m_nPhiOne;
355 if (DstartComp < 0) {DstartComp = m_nPhiFull + DstartComp;}
356
357 m_vecDstart.push_back(DstartShort);
358 m_hitOrients.push_back(orient);
359
360 if (orient == 1) {
361 addC3Comp(hitr, prio, *m_pcompAxial, DstartComp, m_compAxBins);
362 } else {
363 addC3Comp(hitr, prio, *m_pcompStereo, DstartComp, m_compStBins);
364 }
365}
366
367
368void NDFinder::addC3Comp(ushort hitr,
369 ushort prio, const c5array& hitsToTracks,
370 short Dstart, ndbinning bins)
371{
372 ushort ntheta = 0;
373 c3array& houghPlane = *m_phoughPlane;
374 for (ushort itheta = 0; itheta < m_nTheta; itheta++) { //9
375 if (bins.theta > 1) { //stereo
376 ntheta = itheta;
377 }
378 for (ushort iomega = 0; iomega < m_nOmega; iomega++) { //40
379 ushort startfield = 0;
380 ushort lenfield = 1;
381 ushort xstart = hitsToTracks[hitr][prio][iomega][startfield][ntheta];
382 ushort xlen = hitsToTracks[hitr][prio][iomega][lenfield][ntheta];
383 for (ushort iphiz = 0; iphiz < xlen; iphiz++) {
384 ushort iphix = iphiz + 2;
385 ushort iphi = iphiz + xstart;
386 ushort iHoughPhi = (iphi + Dstart) % m_nPhiFull;
387 houghPlane[iomega][iHoughPhi][itheta] += hitsToTracks[hitr][prio][iomega][iphix][ntheta];
388 }
389 }
390 }
391}
392
393
395{
397 for (unsigned short ihit = 0; ihit < m_nHits; ihit++) {
398 addLookup(ihit);
399 }
400 if (m_verbose) {
401 B2DEBUG(25, "m_houghPlane, 2");
402 printArray3D(*m_phoughPlane, m_fullBins);
403 }
404 getCM();
405}
406
407
408std::vector<std::vector<unsigned short>> NDFinder::getHitsVsClusters(std::vector<SimpleCluster>& clusters)
409{
410 unsigned short nClusters = clusters.size();
411 unsigned short defaultValue = 0;
412 std::vector<unsigned short> hitElem(m_nHits, defaultValue);
413 std::vector<std::vector<unsigned short>> hitsVsClusters(nClusters, hitElem);
414
415 for (unsigned long iclus = 0; iclus < clusters.size(); iclus++) {
416 SimpleCluster cli = clusters[iclus];
417 std::vector<cell_index> entries = cli.getEntries();
418 cell_index maxid = getMax(entries);
419 for (unsigned long ihit = 0; ihit < m_hitIds.size(); ihit++) {
420 ushort contrib = hitContrib(maxid, ihit);
421 hitsVsClusters[iclus][ihit] = contrib;
422 }
423 }
424 return hitsVsClusters;
425}
426
427// New hit-to-cluster relation, replaces relateHitsToClusters
428std::vector<SimpleCluster>
429NDFinder::allHitsToClusters(std::vector<std::vector<unsigned short>>& hitsVsClusters, std::vector<SimpleCluster>& clusters)
430{
431 std::vector<SimpleCluster> useClusters;
432 if (hitsVsClusters.size() > 0) {
433 // Iteration over the number of clusters
434 for (unsigned long iclus = 0; iclus < hitsVsClusters.size(); iclus++) {
435 std::vector<std::vector<long>> superLayerNumbers;
436 // Iteration over all track segment hits
437 for (unsigned long ihit = 0; ihit < m_hitIds.size(); ihit++) {
438 unsigned short contribution = hitsVsClusters[iclus][ihit];
439 if (contribution > 0) {
440 superLayerNumbers.push_back({static_cast<long>(ihit), contribution, m_hitSLIds[ihit], m_prioTime[ihit]});
441 }
442 }
443 // Iteration over all super layers
444 for (unsigned short sl = 0; sl < 9; sl++) {
445 std::vector<std::vector<long>> oneSuperLayerContributions;
446 for (unsigned long nTS = 0; nTS < superLayerNumbers.size(); nTS++) {
447 if (superLayerNumbers[nTS][2] == sl) {
448 oneSuperLayerContributions.push_back({superLayerNumbers[nTS][0], superLayerNumbers[nTS][1], superLayerNumbers[nTS][3]});
449 }
450 }
451 // Continue if there are no hits in the current super layer
452 if (oneSuperLayerContributions.size() == 0) {
453 continue;
454 }
455 // Sorting after the drift times
456 struct sortingClass {
457 bool operator()(std::vector<long> i, std::vector<long> j) {return (i[2] < j[2]);}
458 } sortingTimes;
459 sort(oneSuperLayerContributions.begin(), oneSuperLayerContributions.end(), sortingTimes);
460 long maxHit = oneSuperLayerContributions[0][0];
461 long maxContribution = oneSuperLayerContributions[0][1];
462 // Iteration over all track segments in this super layer
463 for (size_t index = 0; index < oneSuperLayerContributions.size(); index++) {
464 // The maximum weight contribution gets identified
465 if (oneSuperLayerContributions[index][1] > maxContribution) {
466 maxContribution = oneSuperLayerContributions[index][1];
467 maxHit = oneSuperLayerContributions[index][0];
468 }
469 }
470 clusters[iclus].addHit(maxHit, maxContribution, m_hitOrients[maxHit]);
471 }
472 SimpleCluster& clu = clusters[iclus];
473 // The hits of the current cluster get extracted
474 std::vector<unsigned short> clusterHits = clu.getHits();
475 std::vector<unsigned short> clusterSLNumbers;
476 for (const auto& element : clusterHits) {
477 clusterSLNumbers.push_back(m_hitSLIds[element]);
478 }
479 // A cut on the super layer numbers is applied
480 std::set<unsigned short> uniqueSLNumbers(clusterSLNumbers.begin(), clusterSLNumbers.end());
481 size_t nSL = uniqueSLNumbers.size();
482 uniqueSLNumbers.insert({0, 2, 4, 6, 8});
483 size_t withAxialSLs = uniqueSLNumbers.size();
484 size_t axialNumber = 5 - (withAxialSLs - nSL);
485 size_t stereoNumber = nSL - axialNumber;
486 if (axialNumber >= m_params.minSuperAxial && stereoNumber >= m_params.minSuperStereo) {
487 useClusters.push_back(clusters[iclus]);
488 }
489 }
490 }
491 return useClusters;
492}
493
495{
496 c3array& houghPlane = *m_phoughPlane;
497 std::vector<SimpleCluster> allClusters;
498 std::vector<ROOT::Math::XYZVector> houghspace;
499 if (m_params.dbscanning) {
500 m_clusterer.setNewPlane(houghPlane);
501 allClusters = m_clusterer.dbscan();
502 } else {
503 c3array copiedPlane = houghPlane;
504 m_clusterer.setNewPlane(copiedPlane);
505 std::vector<SimpleCluster> fixedClusters = m_clusterer.makeClusters();
506 allClusters = fixedClusters;
507 }
508 std::vector<SimpleCluster> clusters;
509 for (SimpleCluster& clu : allClusters) {
510 if (clu.getEntries().size() > m_params.minCells) {
511 clusters.push_back(clu);
512 }
513 }
514 std::vector<std::vector<unsigned short>> hitsVsClusters = getHitsVsClusters(clusters);
515 // New hit to cluster relation
516 std::vector<SimpleCluster> useClusters = allHitsToClusters(hitsVsClusters, clusters);
517
518 for (unsigned long iclus = 0; iclus < useClusters.size(); iclus++) {
519 SimpleCluster cli = useClusters[iclus];
520 std::vector<cell_index> entries = cli.getEntries();
521 cell_index maxid = getMax(entries);
522 ushort maxval = houghPlane[maxid[0]][maxid[1]][maxid[2]];
523 float cutoff = m_params.thresh * maxval;
524 std::vector<cellweight> highWeight = getHighWeight(entries, cutoff);
525 std::vector<std::vector<long int>> flatHW;
526 for (auto cx : highWeight) {
527 flatHW.push_back({cx.index[0], cx.index[1], cx.index[2], (unsigned short int)cx.weight});
528 }
529 std::vector<double> result = getWeightedMean(highWeight);
530 std::vector<double> estimate = getBinToVal(result);
531 std::vector<double> transformed = transform(estimate);
532
533 // READOUTS, uncomment what needed:
534 std::vector<ROOT::Math::XYZVector> ndreadout;
535
536 // Readout of the peak weight
537 /* ndreadout.push_back(ROOT::Math::XYZVector(maxval, 0, 0)); */
538
539 // Readout of the total weight
540 /* unsigned long totalWeight = 0; */
541 /* for (const cell_index& cellIndex : entries) { */
542 /* totalWeight += houghPlane[cellIndex[0]][cellIndex[1]][cellIndex[2]]; */
543 /* } */
544 /* ndreadout.push_back(ROOT::Math::XYZVector(totalWeight, 0, 0)); */
545
546 // Readout of the number of cluster cells
547 /* int ncells = entries.size(); */
548 /* ndreadout.push_back(ROOT::Math::XYZVector(ncells, 0, 0)); */
549
550 // Readout of the cluster center of gravity
551 /* ndreadout.push_back(ROOT::Math::XYZVector(result[0], result[1], result[2])); */
552
553 // Readout of the cluster weights
554 /* for (const cell_index& cellIndex : entries) { */
555 /* c3elem element = houghPlane[cellIndex[0]][cellIndex[1]][cellIndex[2]]; */
556 /* ndreadout.push_back(ROOT::Math::XYZVector(element, 0, 0)); */
557 /* } */
558
559 // Readout of the cluster cell indices
560 /* for (const cell_index& cellIndex : entries) { */
561 /* ndreadout.push_back(ROOT::Math::XYZVector(cellIndex[0], cellIndex[1], cellIndex[2])); */
562 /* } */
563
564 // Readout of the complete Hough space:
565 /* for (c3index i = 0; i < static_cast<c3index>(houghPlane.shape()[0]); ++i) { */
566 /* for (c3index j = 0; j < static_cast<c3index>(houghPlane.shape()[1]); ++j) { */
567 /* for (c3index k = 0; k < static_cast<c3index>(houghPlane.shape()[2]); ++k) { */
568 /* c3elem element = houghPlane[i][j][k]; */
569 /* houghspace.push_back(ROOT::Math::XYZVector(element, 0, 0)); */
570 /* } */
571 /* } */
572 /* } */
573
574 m_NDFinderTracks.push_back(NDFinderTrack(transformed, cli, houghspace, ndreadout));
575 }
576}
577
578
579float NDFinder::transformVar(float estVal, int idx)
580{
581 if (idx == 0) { //omega
582 if (estVal == 0.) {
583 return estVal;
584 } else {
585 return - 1 / cdcTrackRadius(1. / estVal);
586 }
587 } else if (idx == 1) { // phi
588 float phiMod = estVal;
589 if (estVal > 180) {
590 phiMod -= 360.;
591 }
592 return phiMod * TMath::DegToRad();
593 } else { // theta
594 float thetRad = estVal * TMath::DegToRad();
595 return cos(thetRad) / sin(thetRad);
596 }
597}
598std::vector<double> NDFinder::transform(std::vector<double> estimate)
599{
600 std::vector<double> transformed;
601 for (int idx = 0; idx < 3; idx++) {
602 transformed.push_back(transformVar(estimate[idx], idx));
603 }
604 return transformed;
605}
606
607
608std::vector<double> NDFinder::getBinToVal(std::vector<double> thisAv)
609{
610 std::vector<double> estimate;
611 for (ushort idim = 0; idim < 3; idim++) {
612 double trafd = m_acceptRanges[idim][0] + (thisAv[idim] + 0.5) * m_slotSizes[idim];
613 estimate.push_back(trafd);
614 }
615 return estimate;
616}
617
618
619std::vector<double> NDFinder::getWeightedMean(std::vector<cellweight> highWeight)
620{
621 double axomega = 0.;
622 double axphi = 0.;
623 double axtheta = 0.;
624 long weightSum = 0;
625 for (cellweight& elem : highWeight) {
626 axomega += elem.index[0] * elem.weight;
627 axphi += elem.index[1] * elem.weight;
628 axtheta += elem.index[2] * elem.weight;
629 weightSum += elem.weight;
630 }
631 axomega /= weightSum;
632 axphi /= weightSum;
633 axtheta /= weightSum;
634 std::vector<double> result = {axomega, axphi, axtheta};
635 return result;
636}
637
638
639cell_index NDFinder::getMax(const std::vector<cell_index>& entries)
640{
641 ushort curWeight = 0;
642 cell_index curMaxIndex = {0, 0, 0};
643 const c3array& houghPlane = *m_phoughPlane;
644
645 for (const cell_index& entry : entries) {
646 if (houghPlane[entry[0]][entry[1]][entry[2]] > curWeight) {
647 curWeight = houghPlane[entry[0]][entry[1]][entry[2]];
648 curMaxIndex = entry;
649 }
650 }
651 return curMaxIndex;
652}
653
654
655std::vector<cellweight> NDFinder::getHighWeight(std::vector<cell_index> entries, float cutoff)
656{
657 std::vector<cellweight> cellsAndWeight;
658 const c3array& houghPlane = *m_phoughPlane;
659 for (cell_index& entry : entries) {
660 ushort cellWeight = houghPlane[entry[0]][entry[1]][entry[2]];
661 if (cellWeight > cutoff) {
662 cellweight curElem;
663 curElem.index = entry;
664 curElem.weight = cellWeight;
665 cellsAndWeight.push_back(curElem);
666 }
667 }
668 return cellsAndWeight;
669}
670
671
672ushort NDFinder::hitContrib(cell_index peak, ushort ihit)
673{
674 ushort contrib = 0;
675 ushort iHoughPhi = peak[1];
676 short Dstart = m_vecDstart[ihit];
677 ushort iphi = iHoughPhi - Dstart;
678 if (Dstart > iHoughPhi && Dstart > 300) {
679 iphi = m_nPhiFull - Dstart + iHoughPhi;
680 }
681 ushort iomega = peak[0];
682 ushort itheta = peak[2];
683 ushort orient = m_hitOrients[ihit];
684
685 const c2array& arrayHitMod = *m_parrayHitMod;
686 c2elem hitr = arrayHitMod[m_hitIds[ihit]][1];
687 unsigned short prio = m_prioPos[ ihit ];
688 if (Dstart > m_nPhiFull) {
689 B2ERROR("phi overflow: iHoughPhi = " << iHoughPhi << ", Dstart = " << Dstart << ", iphi=" << iphi);
690 }
691 if (iphi < m_nPhiUse) { // hit covers current phi area, get contribution
692 if (orient == 1) { // axial
693 contrib = (*m_parrayAxial)[hitr][prio][iomega][iphi][itheta];
694 } else { // stereo
695 contrib = (*m_parrayStereo)[hitr][prio][iomega][iphi][itheta];
696 }
697 }
698 return contrib;
699}
700
701
702void
704{
705 clustererParams cpa = m_clusterer.getParams();
706 B2DEBUG(25, "clustererParams minWeight=" << cpa.minWeight << ", minPts=" << cpa.minPts << ", diagonal=" << cpa.diagonal);
707 B2DEBUG(25, "ndFinderParams minSuperAxial=" << m_params.minSuperAxial <<
708 ", minSuperStereo=" << m_params.minSuperStereo << ", thresh=" << m_params.thresh <<
709 ", minCells=" << m_params.minCells << ", dbscanning=" << m_params.dbscanning << ", minTotalWeight=" << m_params.minTotalWeight <<
710 ", minPeakWeight=" << m_params.minPeakWeight <<
711 ", iterations=" << m_params.iterations << ", omegaTrim=" << m_params.omegaTrim << ", phiTrim=" << m_params.phiTrim << ", thetaTrim="
713}
Clustering module.
Definition: Clusterizend.h:125
void setNewPlane(c3array &houghmapPlain)
Next event initialization: set a new hough space for clustering and track finding.
Definition: Clusterizend.h:153
Store track parameters of found tracks.
Definition: NDFinder.h:28
double cdcTrackRadius(double pt)
Transverse momentum to radius.
Definition: NDFinder.h:316
Belle2::Clusterizend m_clusterer
Clustering module.
Definition: NDFinder.h:414
std::vector< SimpleCluster > allHitsToClusters(std::vector< std::vector< unsigned short > > &hitsVsClusters, std::vector< SimpleCluster > &clusters)
Relate all hits in a cluster to the cluster Remove small clusters with less than minsuper related hit...
Definition: NDFinder.cc:429
void initBins()
Initialize the binnings and reserve the arrays.
Definition: NDFinder.cc:78
void initHitModAxSt(c2array &hitMod)
Initialize hit modulo mappings.
Definition: NDFinder.cc:198
c5array * m_parrayAxial
Array pointers to the hit patterns.
Definition: NDFinder.h:339
void getCM()
NDFinder internal functions for track finding.
Definition: NDFinder.cc:494
void squeezeAll(ndbinning writebins, c5array &writeArray, c5array &readArray, int outparcels, int inparcels)
Loop over all hits and theta bins and squeeze all 2D (omega,phi) planes.
Definition: NDFinder.cc:252
std::vector< unsigned short > m_prioPos
Priority positon within the TS in the current event elements basf2: [0,3] first, left,...
Definition: NDFinder.h:365
void loadArray(const std::string &filename, ndbinning bins, c5array &hitsToTracks)
Load an NDFinder array of hit representations in track phase space.
Definition: NDFinder.cc:165
void restoreZeros(ndbinning zerobins, ndbinning compbins, c5array &expArray, const c5array &compArray)
Restore non-zero suppressed hit curves.
Definition: NDFinder.cc:264
std::vector< short > m_vecDstart
Phi-start of 7/32 hit representation in full track parameter space.
Definition: NDFinder.h:377
std::vector< unsigned short > m_hitOrients
Orients TS-Ids of the hits in the current event elements: [0,2335] for 2336 TS in total.
Definition: NDFinder.h:373
ushort hitContrib(cell_index peak, ushort ihit)
Determine weight contribution of a single hit to a single cell.
Definition: NDFinder.cc:672
void squeezeOne(c5array &writeArray, c5array &readArray, int outparcels, int inparcels, c5index ihit, c5index iprio, c5index itheta, c5elem nomega)
Squeeze phi-axis in a 2D (omega,phi) plane.
Definition: NDFinder.cc:229
std::vector< cellweight > getHighWeight(std::vector< cell_index > entries, float cutoff)
Candidate cells as seed for the clustering.
Definition: NDFinder.cc:655
std::vector< double > getBinToVal(std::vector< double >)
Scale the weighted center to track parameter values.
Definition: NDFinder.cc:608
unsigned short m_nHits
Counter for the number of hits in the current event.
Definition: NDFinder.h:380
boost::array< c5index, 5 > m_pc5shapeax
NDFinder.
Definition: NDFinder.h:329
void init(unsigned short minWeight, unsigned char minPts, bool diagonal, unsigned char minSuperAxial, unsigned char minSuperStereo, float thresh, unsigned char minCells, bool dbscanning, unsigned short minTotalWeight, unsigned short minPeakWeight, unsigned char iterations, unsigned char omegaTrim, unsigned char phiTrim, unsigned char thetaTrim, bool verbose, std::string &axialFile, std::string &stereoFile)
initialization
Definition: NDFinder.cc:24
void addC3Comp(ushort hitr, ushort prio, const c5array &hitsToTracks, short Dstart, ndbinning bins)
In place array addition to houghmap Comp: A = A + B.
Definition: NDFinder.cc:368
std::vector< int > m_nWires
Number of first priority wires in each super layer (TS per SL)
Definition: NDFinder.h:349
ndbinning m_axBins
Binnings in different hit pattern arrays.
Definition: NDFinder.h:386
clustererParams m_clustererParams
Configuration of the clustering module.
Definition: NDFinder.h:395
void printParams()
Debug: print configured parameters.
Definition: NDFinder.cc:703
ndparameters m_params
Configuration parameters of the 3DFinder.
Definition: NDFinder.h:383
std::vector< NDFinderTrack > m_NDFinderTracks
Result: vector of the found tracks.
Definition: NDFinder.h:352
void addLookup(unsigned short ihit)
Add a single axial or stereo hit to the houghmap.
Definition: NDFinder.cc:337
std::vector< unsigned short > m_hitIds
TS-Ids of the hits in the current event elements: [0,2335] for 2336 TS in total.
Definition: NDFinder.h:356
unsigned short m_nPhiFull
Default bins.
Definition: NDFinder.h:399
void reset()
NDFinder reset data structure to process next event.
Definition: NDFinder.h:231
void findTracks()
main function for track finding
Definition: NDFinder.cc:394
std::vector< std::vector< unsigned short > > getHitsVsClusters(std::vector< SimpleCluster > &clusters)
Create hits to clusters confusion matrix.
Definition: NDFinder.cc:408
std::vector< double > getWeightedMean(std::vector< cellweight >)
Calculate the weighted center of a cluster.
Definition: NDFinder.cc:619
std::vector< long > m_prioTime
Drift time of the priority wire.
Definition: NDFinder.h:368
float transformVar(float estVal, int idx)
Calculate physical units.
Definition: NDFinder.cc:579
void printArray3D(c3array &hitsToTracks, ndbinning bins, ushort, ushort, ushort, ushort)
Debug Tool: Print part of the houghmap.
Definition: NDFinder.cc:289
cell_index getMax(const std::vector< cell_index > &)
Peak cell in cluster.
Definition: NDFinder.cc:639
bool m_verbose
Print Hough planes and verbose output.
Definition: NDFinder.h:418
std::vector< unsigned short > m_hitSLIds
SL-Ids of the hits in the current event elements: super layer number in [0,1,...,8].
Definition: NDFinder.h:360
Type for found clusters.
Definition: Clusterizend.h:45
std::vector< unsigned short > getHits()
Get ids of related hits (indices of the TS StoreArray)
Definition: Clusterizend.h:100
std::vector< cell_index > getEntries()
Get member cells in the cluster.
Definition: Clusterizend.h:73
unsigned short c2elem
TS-Id to 1/32 phi-sector mapping is stored in a 2D array.
Definition: NDFinderDefs.h:34
unsigned short c5elem
Store hit patterns in a 5D array (hitid, prio, omega, phi, theta)
Definition: NDFinderDefs.h:23
Abstract base class for different kinds of events.
unsigned char iterations
Clustering: number of iterations for the cluster search in each Hough space.
Definition: NDFinder.h:139
std::string axialFile
Zero-Suppressed trained hit data.
Definition: NDFinder.h:113
unsigned short minTotalWeight
Clustering: minimum of the total weight in all cells of the 3d volume.
Definition: NDFinder.h:133
unsigned char minCells
Minimum number of cells in the track parameter space.
Definition: NDFinder.h:127
unsigned short phigeo
CDC symmetry: repeat wire pattern 32 times in phi.
Definition: NDFinder.h:151
unsigned char omegaTrim
Clustering: number of deleted cells in each omega direction from the maximum.
Definition: NDFinder.h:142
unsigned char minSuperAxial
Clustering options.
Definition: NDFinder.h:118
bool dbscanning
Clustering method: When true: dbscan, when false: fixed 3d volume.
Definition: NDFinder.h:130
float thresh
houghspace must have thresh x maxweight of cluster
Definition: NDFinder.h:124
unsigned short parcelsExp
CDC symmetry: phi range covered by expanded hit data [0 .
Definition: NDFinder.h:157
unsigned char thetaTrim
Clustering: number of deleted cells in each theta direction from the maximum.
Definition: NDFinder.h:148
unsigned char minSuperStereo
Required number of stereo super layers.
Definition: NDFinder.h:121
unsigned short minPeakWeight
Clustering: minimum peak cell weight.
Definition: NDFinder.h:136
unsigned short parcels
‍** CDC symmetry: phi range covered by hit data [0 .. phigeo] *‍/
Definition: NDFinder.h:154
unsigned char phiTrim
Clustering: number of deleted cells in each phi direction from the maximum.
Definition: NDFinder.h:145
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
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
Default binning in a (7/32) phi-sector.
Definition: NDFinderDefs.h:41