Belle II Software development
NDFinder.h
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#pragma once
10
11#include <string>
12#include <vector>
13#include <array>
14#include <utility>
15#include <boost/multi_array.hpp>
16#include <cstdint>
17
18#include "trg/cdc/NDFinderPeakFinder.h"
19#include "trg/cdc/dataobjects/CDCTriggerNDFinderLUTs.h"
20#include "framework/database/DBObjPtr.h"
21
22#define BOOST_MULTI_ARRAY_NO_GENERATORS
23
24namespace Belle2 {
29
30 // Typedefs for the LUT tables and the Hough space
31 typedef boost::multi_array<unsigned short, 2> c2array;
32 typedef boost::multi_array<unsigned short, 3> c3array;
33 typedef boost::multi_array<unsigned short, 4> c4array;
34 typedef c3array::index c3index;
35 typedef c4array::index c4index;
36 typedef std::array<c3index, 3> cell_index;
37
38 // Struct of NDFinder parameters
40 // Required number of axial super layers
41 unsigned short minSuperAxial;
42 // Required number of stereo super layers
43 unsigned short minSuperStereo;
44 // Peak finding: Number of iterations for the peak search in each Hough space quadrant
45 unsigned short iterations;
46 // Peak finding: Number of deleted cells in each omega direction from the maximum
47 unsigned short omegaTrim;
48 // Peak finding: Number of deleted cells in each phi direction from the maximum
49 unsigned short phiTrim;
50 // Switch for saving the full Hough space
51 bool storeHoughSpace;
52 // Axial and stereo hit representations that should be used
53 std::string axialFile;
54 std::string stereoFile;
55 };
56
57 // Struct containing the track segment (hit) information from the Track Segment Finder (TSF)
58 struct HitInfo {
59 unsigned short hitID;
60 unsigned short hitSLID;
61 short hitPrioTime;
62 };
63
64 // Struct for a found NDFinder track
65 struct RawFinderTrack {
66 double omega{};
67 double phi{};
68 double cot{};
69 HoughPeak peak;
70 std::vector<uint8_t> houghSpace;
71
72 RawFinderTrack(std::array<double, 3> estimatedParameters,
73 HoughPeak&& houghPeak,
74 std::vector<uint8_t>&& readoutHoughSpace)
75 : omega{estimatedParameters[0]},
76 phi{estimatedParameters[1]},
77 cot{estimatedParameters[2]},
78 peak{std::move(houghPeak)},
79 houghSpace{std::move(readoutHoughSpace)} {}
80 };
81
82 // Class to represent the CDC NDFinder.
83 class NDFinder {
84 public:
85 // Data type to collect a binning
87 unsigned short omega;
88 unsigned short phi;
89 unsigned short cot;
90 unsigned short nHitIDs;
91 };
92
93 // Collection of the hit contribution information needed for the hit to peak relations
95 unsigned short hitIndex;
96 unsigned short contribution;
97 unsigned short superLayer;
98 short priorityTime;
99 };
100
101 // Default constructor
102 NDFinder() = default;
103
104 // Destructor
105 ~NDFinder() { delete m_houghSpace; }
106
107 // Initialization of the NDFinder (parameters and lookup tables)
108 void init(const NDFinderParameters& ndFinderParameters);
109 // Reset the NDFinder data structure to process next event
110 void reset();
111 // Add the hit info of a single track segment to the NDFinder
112 void addHit(const HitInfo& hitInfo);
113 // Main function for track finding
114 void findTracks();
115 // Retreive the results
116 std::vector<RawFinderTrack>* getFinderTracks() { return &m_rawFinderTracks; }
117
118 private:
119 // NDFinder: Internal functions for track finding
120 // Fills the m_hitToSectorIDs (see below) array with the hit to orientation/sectorWire/sectorID relations
121 void initHitToSectorMap();
122 // Fills the m_compAxialHitReps/m_compStereoHitReps (see below) arrays with the hit representations (hits to weights)
123 void fillCompressedHitReps(const std::vector<unsigned short>& flatArray, const SectorBinning& compBins,
124 c4array& compHitsToWeights) const;
125 // Loads the hit representations from a plain text file if the ConditionsDB is not used
126 std::vector<unsigned short> loadFromFile(const std::string& fileName) const;
127 // Fills the m_expAxialHitReps/m_expStereoHitReps (see below) arrays with the expanded hit representations (hits to weights)
128 void fillExpandedHitReps(const SectorBinning& compBins, const c4array& compHitsToWeights, c4array& expHitsToWeights) const;
129 // Process a single axial or stereo hit for the Hough space
130 void processHitForHoughSpace(const unsigned short hitIdx);
131 // Write (add) a single hit (Hough curve) to the Hough space
132 void writeHitToHoughSpace(const unsigned short relativeWireID, const unsigned short phiSectorStart,
133 const c4array& expHitsToWeights);
134 // Core track finding logic in the constructed Hough space
135 void runTrackFinding();
136 // Relate the hits in the peak cell of the peak. Applies a cut on the found peaks.
137 std::vector<HoughPeak> relateHitsToPeaks(std::vector<HoughPeak>& peaks) const;
138 // Create hits to peaks confusion matrix
139 std::vector<std::vector<unsigned short>> getHitsVsPeaksTable(const std::vector<HoughPeak>& peaks) const;
140 // Returns the hit contribution of a TS at a certain cell (= peak/maximum cell)
141 unsigned short getHitContribution(const cell_index& peakCell, const unsigned short hitIdx) const;
142 // Extract relevant hit information (hitIdx, contribution, super layer, drift time)
143 std::vector<ContributionInfo> extractContributionInfos(const std::vector<unsigned short>& peakHits) const;
144 // Find the hit with the maximum contribution in a given super layer
145 int getMaximumHitInSuperLayer(const std::vector<ContributionInfo>& contributionInfos, unsigned short superLayer) const;
146 // Cut on the number of hit axial/stereo super layers
147 bool checkHitSuperLayers(const HoughPeak& peak) const;
148 // Transform the center of gravity (cells) into the estimated track parameters
149 std::array<double, 3> getTrackParameterEstimate(const cell_index& peakCell) const;
150 // Transform to physical units
151 std::array<double, 3> transformTrackParameters(const std::array<double, 3>& estimatedParameters) const;
152 // Transverse momentum (which is 1/omega, in GeV/c) to radius (in cm)
153 static inline double getTrackRadius(double transverseMomentum) { return transverseMomentum * 1e11 / (3e8 * 1.5); }
154
155 // NDFinder: Member data stores
156 // Result: Vector of the found tracks
157 std::vector<RawFinderTrack> m_rawFinderTracks;
158 // TS-IDs of the hits in the current event: Elements = [0,2335] for 2336 TS in total
159 std::vector<unsigned short> m_hitIDs;
160 // SL-IDs of the hits in the current event: Elements = Super layer number in [0,1,...,8]
161 std::vector<unsigned short> m_hitSLIDs;
162 // Drift time of the priority wire.
163 std::vector<short> m_priorityWireTime;
164 // Counter for the number of hits in the current event
165 unsigned short m_nHits{0};
166 // Configuration parameters of the 3DFinder
167 NDFinderParameters m_ndFinderParams;
168 // Peak finding module
169 NDFinderPeakFinder m_peakFinder;
170 // LUTs from the conditions database
171 DBObjPtr<CDCTriggerNDFinderLUTs> m_LUTsConditionsDB;
172
173 /*
174 Since the CDC wire pattern is repeated 32 times, the hit IDs are stored for 1/32 of the CDC only.
175 The total number of 2336 TS corresponds to (41 axial + 32 stereo) * 32.
176 The number of track bins is (for example): (omega, phi, cot) = (40, 384, 9)
177 Note: The omega dimension here represents just sign(q)/(p_T[GeV/c]) (0.25 -> inf -> -inf -> -0.25 for 0 -> 19.5 -> 39)
178 */
179
180 // Track segments
181 static constexpr unsigned short m_nTS = 2336; // Number of track segments
182 static constexpr unsigned short m_nSL = 9; // Number of super layers
183 static constexpr unsigned short m_nAxial = 41; // Number of unique axial track segments
184 static constexpr unsigned short m_nStereo = 32; // Number of unique stereo track segments
185
186 // Full Hough space bins
187 static constexpr unsigned short m_nOmega = 40; // Bins in the phi dimension
188 static constexpr unsigned short m_nPhi = 384; // Bins in the omega dimension
189 static constexpr unsigned short m_nCot = 9; // Bins in the cot dimension
190
191 // CDC symmetry in phi
192 static constexpr unsigned short m_phiGeo = 32; // Repetition of the wire pattern
193
194 // Phi sectors in the CDC
195 static constexpr unsigned short m_nPhiSector = m_nPhi / m_phiGeo; // Bins of one phi sector (12)
196
197 // Data structure/binning of the compressed hit pattern files (.txt LUT files)
198 static constexpr unsigned short m_nPhiComp = 15; // Bins of compressed phi: phi_start, phi_width, phi_0, ..., phi_12
199 static constexpr SectorBinning m_compAxialBins = {m_nOmega, m_nPhiComp, 1, m_nAxial}; // 40, 15, 1, 41
200 static constexpr SectorBinning m_compStereoBins = {m_nOmega, m_nPhiComp, m_nCot, m_nStereo}; // 40, 15, 9, 32
201
202 // Acceptance ranges + slot sizes to convert bins to track parameters (for getBinToVal method)
203 static constexpr std::array<double, 2> m_omegaRange = {-4., 4.}; // 1/4 = 0.25 GeV (minimum transverse momentum)
204 static constexpr std::array<double, 2> m_phiRange = {0., 11.25}; // One phi sector (360/32)
205 // These are optimized for minSuperAxial = 3 and minSuperStereo = 2
206 static constexpr std::array<double, 2> m_cotRange = {2.3849627654510415, -1.0061730449796316}; // => theta in [22.75, 135.18]
207 static constexpr double m_binSizeOmega = (m_omegaRange[1] - m_omegaRange[0]) / m_nOmega; // 0.2
208 static constexpr double m_binSizePhi = (m_phiRange[1] - m_phiRange[0]) / m_nPhiSector; // 0.9375
209 static constexpr double m_binSizeCot = (m_cotRange[1] - m_cotRange[0]) / m_nCot; // -0.377
210 static constexpr std::array<std::array<double, 2>, 3> m_acceptanceRanges = {m_omegaRange, m_phiRange, m_cotRange};
211 static constexpr std::array<double, 3> m_binSizes = {m_binSizeOmega, m_binSizePhi, m_binSizeCot};
212
213 // Arrays of the hit representations and pointer to the Hough space
214 /*
215 m_hitToSectorIDs: 2D array mapping TS-ID ([0, 2335]) to:
216
217 - [0]: Orientation (1 = axial, 0 = stereo)
218 - [1]: Relative wire ID in the sector ([0, 40] for axials, [0, 31] for stereos)
219 - [2]: Relative phi-sector ID in the super layer ([0, 31] in each SL)
220 */
221 c2array m_hitToSectorIDs{boost::extents[m_nTS][3]};
222 /*
223 m_compAxialHitReps/m_compStereoHitReps (~ Compressed in phi (width, start, values)) 4D array mapping:
224
225 1. [hitID]: Relative hit number of the track segment (axial [0, 40], stereo [0, 31])
226 2. [omegaIdx]: Omega index of the Hough space ([0, m_nOmega - 1])
227 3. [phiIdx]: Phi start value, number of phi bins, phi values (0, 1, [2, 14])
228 4. [cotIdx]: Cot index of the Hough space (0 for axial TS, [0, m_nCot - 1] for stereo TS)
229
230 to the Hough space weight contribution at the corresponding bin (int, [0, 7])
231 */
232 c4array m_compAxialHitReps{boost::extents[m_nAxial][m_nOmega][m_nPhiComp][1]};
233 c4array m_compStereoHitReps{boost::extents[m_nStereo][m_nOmega][m_nPhiComp][m_nCot]};
234 /*
235 m_expAxialHitReps/m_expStereoHitReps (~ expansion of the compressed representations) 4D array mapping:
236
237 1. [hitID]: Relative hit number of the track segment (axial [0, 40], stereo [0, 31])
238 2. [omegaIdx]: Omega index of the Hough space ([0, m_nOmega - 1])
239 3. [phiIdx]: Phi index of the Hough space ([0, m_nPhi - 1])
240 4. [cotIdx]: Cot index of the Hough space ([0, m_nCot - 1] for both axial and stereo!)
241
242 to the Hough space weight contribution at the corresponding bin (int, [0, 7])
243 */
244 c4array m_expAxialHitReps{boost::extents[m_nAxial][m_nOmega][m_nPhi][m_nCot]};
245 c4array m_expStereoHitReps{boost::extents[m_nStereo][m_nOmega][m_nPhi][m_nCot]};
246
247 // The complete Hough space with the size [m_nOmega, m_nPhi, m_nCot]
248 c3array* m_houghSpace = nullptr;
249 };
250
251}
Abstract base class for different kinds of events.