Belle II Software development
NeuroTrigger3DH.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 <cstdint>
15#include <cmath>
16
17#include "trg/cdc/dataobjects/CDCTriggerHoughMLP.h"
18#include "trg/cdc/dataobjects/CDCTriggerSegmentHit.h"
19#include "trg/cdc/dataobjects/CDCTrigger3DHTrack.h"
20#include "framework/datastore/StoreArray.h"
21
22namespace Belle2 {
27
28 // Represents the neuro trigger using a single MLP with 3DHough Finder (NDFinder) input
29 class NeuroTrigger3DH {
30 public:
31
32 // Default constructor
33 NeuroTrigger3DH() = default;
34
35 // Default destructor
36 virtual ~NeuroTrigger3DH() = default;
37
38 // Initialize CDC geometry
39 void initialize();
40 // Initialize the track segment hit collections
41 void initializeCollections(std::string hitCollectionName);
42 // Create the integer weights for the fixed point precision
43 void createIntWeights();
44 // Calculate the crossing angles (m_alpha) and reference IDs (m_referenceID) for each super layer
45 void calculateTrackParameters(const CDCTrigger3DHTrack& track);
46 // Calculate the same track parameters but with fixed floating point accuracy
47 void calculateTrackParametersFixedPrecision(const CDCTrigger3DHTrack& track);
48 // Set the event time based on the 3DFinder track segment hits
49 void setEventTime(const CDCTrigger3DHTrack& track);
50 // Load the 3DFinder track segment hits
51 std::vector<size_t> load3DHits(const CDCTrigger3DHTrack& track) const;
52 // Calculate the input vector for the MLP
53 std::vector<float> getInputVector(const std::vector<size_t>& hitIds) const;
54 // Run the neural network (MLP) with the input vector
55 std::vector<float> runMLP(const std::vector<float>& input) const;
56 // Run the MLP with fixed point arithmetic
57 std::vector<float> runMLPFixedPrecision(const std::vector<float>& input) const;
58 // Scale target value from [-1, 1] to outputScale
59 std::vector<float> unscaleTarget(const std::vector<float>& target) const;
60 // Scale target value from outputScale to [-1, 1]
61 std::vector<float> scaleTarget(const std::vector<float>& target) const;
62
63 // Get the full precision of the weights of the fixed point (integer) network
64 int getWeightBits() const { return m_precisionWeights; }
65 // Get the fractional weight bits of the fixed point (integer) network
66 int getFractionalWeightBits() const { return m_fractionalWeightBits; }
67 // Get the integerized weights of the fixed point network
68 const std::vector<int32_t>& getIntWeights() const { return m_intWeights; }
69 // Get the event time
70 int getEventTime() const { return m_T0; };
71 // Set the network parameters
72 void setNeuroParameters(const NeuroParametersHough& neuroParameters3DH) { m_neuroParameters3DH = neuroParameters3DH; };
73 // Set the MLP (includes the neuro parameters)
74 void setMLP(const CDCTrigger3DHMLP& mlp);
75 // Get the MLP
76 const CDCTrigger3DHMLP& getMLP() const { return m_MLP; };
77
78 private:
79 // Get the lowest priority time from the track segment hits
80 int getLowestTime(const RelationVector<CDCTriggerSegmentHit>& trackSegmentHits) const;
81 // Calculate the scaled drift time of a track segment hit for the network input
82 float getScaledDriftTime(const CDCTriggerSegmentHit& trackSegmentHit, const unsigned short maxTime) const;
83 // Calculates the relative wire ID difference between the 3DFinder track and the priority hit
84 double getRelativeID(const CDCTriggerSegmentHit& hit) const;
85 // Scale relative TS ID from relevant range to approximately [-1, 1]
86 float scaleRelativeID(const double relativeID, const unsigned superLayerIdx) const;
87
88 // One instance of the MLP (network)
89 CDCTrigger3DHMLP m_MLP;
90 // Integer weights for fixed point precision
91 std::vector<int32_t> m_intWeights;
92 // Fractional weight bits of the network
93 int m_fractionalWeightBits;
94 // Settings loaded from the root file
95 NeuroParametersHough m_neuroParameters3DH;
96 // StoreArray containing the input track segment hits
98 // Name of the StoreArray containing the input track segment hits
99 std::string m_hitCollectionName;
100
101 // Number of super layers
102 static constexpr unsigned int m_nSL = 9;
103 // The priority wire radius of each super layer (first and second priorities)
104 std::array<std::array<double, 2>, m_nSL> m_radiusWireLayer{};
105 // The cumulative priority wires (i.e., track segments) in each super layer
106 std::array < unsigned short, m_nSL + 1 > m_cumulativeWires{};
107 // The number of wires in each super layer
108 std::array<unsigned short, m_nSL> m_nWires{};
109 // referenceID = (phiTrack - alpha) * wiresInLayer / (2 * pi)
110 double m_referenceID[m_nSL][2] = {};
111 // 2D crossing angle of current track
112 double m_alpha[m_nSL][2] = {};
113 // Event time of current event/track
114 int m_T0 = 0;
115 // Flag to show if stored event time is valid
116 bool m_hasT0 = false;
117
118 // Number of supported input nodes for standard and extended input of the neural network
119 static constexpr unsigned int m_nStandardInputNodes = 27;
120 static constexpr unsigned int m_nExtendedInputNodes = 126;
121
122 // The integer bit precisions for the fixed point parameter calculation
123 static constexpr int m_precisionPhi = 12;
124 static constexpr int m_precisionAlpha = 12;
125 static constexpr int m_precisionScaleFactor = 8;
126 static constexpr int m_precisionReferenceID = 8;
127
128 // The integer bit precisions for the fixed point network calculation
129 static constexpr int m_precisionInputs = 13;
130 static constexpr int m_precisionWeights = 17;
131
132 // Tanh activation function LUT (hardware)
133 struct TanhLUT {
134 // How many entries the LUT has
135 static constexpr int LUT_INDEX_BITS = 12;
136 static constexpr std::size_t LUT_SIZE = 1 << LUT_INDEX_BITS;
137
138 // Quantization of the outputs
139 static constexpr int LUT_FRAC_BITS = 12;
140 static constexpr int LUT_SCALE = 1 << LUT_FRAC_BITS;
141
142 // Function domain limit (saturation limit)
143 static constexpr int MAX_FLOAT_SHIFT = 2;
144 static constexpr int MAX_FLOAT = 1 << MAX_FLOAT_SHIFT;
145 static constexpr int LUT_SATURATION = 1 << (LUT_FRAC_BITS + MAX_FLOAT_SHIFT);
146
147 // Headroom for the DSP cut window (high bit cutoff to ensure full representation):
148 // Using MAX_OBSERVED = 10.439 (in simulation of > 50 mio tracks)
149 // With HEADROOM_BITS = std::ceil(std::log2(MAX_OBSERVED / MAX_FLOAT)) + 1
150 static constexpr int HEADROOM_BITS = 3;
151
152 inline static const std::array<int32_t, LUT_SIZE> table = []()
153 {
154 std::array<int32_t, LUT_SIZE> lut{};
155 for (std::size_t i = 0; i < LUT_SIZE; ++i) {
156 double input = MAX_FLOAT * static_cast<double>(i) / LUT_SIZE;
157 double val = std::tanh(input) * LUT_SCALE;
158 int32_t qval = static_cast<int32_t>(std::round(val));
159 // Clamp to maximum bit range [0, LUT_SCALE - 1] (maps LUT_SCALE -> LUT_SCALE - 1)
160 qval = std::min<int32_t>(qval, (LUT_SCALE - 1));
161 lut[i] = qval;
162 }
163 return lut;
164 }();
165
166 static int32_t get(std::size_t idx) { return table[idx]; }
167 };
168
169 // Cut a bit window from signed int (hardware truncation)
170 static constexpr int32_t extractBits(int64_t value, int high, int low)
171 {
172 int width = high - low + 1;
173 int64_t shifted = value >> low;
174 int32_t mask = (1 << width) - 1;
175 int32_t result = static_cast<int32_t>(shifted & mask);
176 if (result & (1 << (width - 1))) {
177 result |= ~mask;
178 }
179 return result;
180 }
181 };
182
183}
Combination of several CDCHits to a track segment hit for the trigger.
Class for type safe access to objects that are referred to in relations.
Accessor to arrays stored in the data store.
Definition StoreArray.h:113
Abstract base class for different kinds of events.