8 #include "trg/cdc/modules/neurotrigger/CDCTriggerNeuroModule.h"
22 "The NeuroTrigger module of the CDC trigger.\n"
23 "Takes track segments and 2D track estimates as input and estimates\n"
24 "the z-vertex for each track using a neural network.\n"
25 "Requires one or several trained networks stored in a file.\n"
27 setPropertyFlags(c_ParallelProcessingCertified);
29 addParam(
"filename", m_filename,
30 "Name of the files where the NeuroTrigger parameters are saved. "
31 "When left blank, the parameters are loaded from the Conditions "
33 "(compare NeuroTriggerTrainer).",
35 addParam(
"arrayname", m_arrayname,
36 "Name of the TObjArray holding the NeuroTrigger parameters "
37 "(compare NeuroTriggerTrainer).",
39 addParam(
"hitCollectionName", m_hitCollectionName,
40 "Name of the input StoreArray of CDCTriggerSegmentHits.",
42 addParam(
"EventTimeName", m_EventTimeName,
43 "Name of the event time object.",
45 addParam(
"inputCollectionName", m_inputCollectionName,
46 "Name of the StoreArray holding the 2D input tracks or Neurotracks.",
47 string(
"TRGCDC2DFinderTracks"));
48 addParam(
"realinputCollectionName", m_realinputCollectionName,
49 "Name of the StoreArray holding the 2D input tracks in case "
50 "Neurotracks were used for the inputCollectionName.",
51 string(
"CDCTriggerNNInput2DFinderTracks"));
52 addParam(
"outputCollectionName", m_outputCollectionName,
53 "Name of the StoreArray holding the output tracks with neural "
55 string(
"TRGCDCNeuroTracks"));
56 addParam(
"fixedPoint", m_fixedPoint,
57 "Switch to turn on fixed point arithmetic for FPGA simulation.",
59 addParam(
"precision", m_precision,
60 "fixed point precision in bit after radix point (for track phi, "
61 "scaling factor, reference id, MLP nodes, MLP weights, "
62 "MLP activation function)", {12, 8, 8, 12, 10, 10});
63 addParam(
"et_option", m_et_option,
64 "option on how to obtain the event time. When left blank, the value "
65 "is loaded from the Conditions Database. Possibilities are: "
66 "'etf_only', 'fastestpriority', 'zero', 'etf_or_fastestpriority', "
67 "'etf_or_zero', 'etf_or_fastest2d', 'fastest2d'.",
69 addParam(
"writeMLPinput", m_writeMLPinput,
70 "if true, the MLP input vector will be written to the datastore "
73 addParam(
"hardwareCompatibilityMode", m_hardwareCompatibilityMode,
74 "Switch to mimic an apparent bug in the hardware preprocessing",
76 addParam(
"NeuroHWTrackInputMode", m_neuroTrackInputMode,
77 "use Neurotracks instead of 2DTracks as input",
87 if (m_et_option.size() < 1) {
88 m_et_option = m_cdctriggerneuroconfig->getUseETF() ?
"etf_or_fastestpriority" :
"fastestpriority";
89 B2DEBUG(2,
"The firmware version of the Neurotrigger boards is: " + m_cdctriggerneuroconfig->getNNTFirmwareVersionID());
91 if (!m_NeuroTrigger.load(m_filename, m_arrayname))
92 B2ERROR(
"NeuroTrigger could not be loaded correctly.");
94 m_NeuroTrigger.setPrecision(m_precision);
96 if (m_et_option ==
"") {
97 m_et_option = m_NeuroTrigger.get_et_option();
99 m_tracksNN.registerInDataStore(m_outputCollectionName);
100 m_tracks2D.isRequired(m_inputCollectionName);
101 m_segmentHits.isRequired(m_hitCollectionName);
102 m_NeuroTrigger.initializeCollections(m_hitCollectionName, m_EventTimeName, m_et_option);
104 m_tracks2D.registerRelationTo(m_tracksNN);
105 m_tracks2D.requireRelationTo(m_segmentHits);
106 m_tracksNN.registerRelationTo(m_segmentHits);
107 if (m_neuroTrackInputMode) {
108 m_realtracks2D.isRequired(m_realinputCollectionName);
109 m_realtracks2D.registerRelationTo(m_tracksNN);
111 if (m_writeMLPinput) {
112 m_mlpInput.registerInDataStore(m_outputCollectionName +
"Input");
120 case 8:
return tsid + 0.12;
121 case 4:
return tsid / 2;
122 case 3:
return tsid - 0.12;
123 case 1:
return (tsid + 0.12) / 2;
124 case 0:
return tsid / 4;
125 default:
return tsid;
132 for (
int itrack = 0; itrack < m_tracks2D.getEntries(); ++itrack) {
135 m_NeuroTrigger.updateTrackFix(*m_tracks2D[itrack]);
137 m_NeuroTrigger.updateTrack(*m_tracks2D[itrack]);
140 vector<int> geoSectors =
141 m_NeuroTrigger.selectMLPs(m_tracks2D[itrack]->getPhi0(),
142 m_tracks2D[itrack]->getKappa(1.5),
143 atan2(1., m_tracks2D[itrack]->getCotTheta()));
144 if (geoSectors.size() == 0)
continue;
146 m_NeuroTrigger.getEventTime(geoSectors[0], *m_tracks2D[itrack], m_et_option, m_neuroTrackInputMode);
148 unsigned long hitPattern =
149 m_NeuroTrigger.getInputPattern(geoSectors[0], *m_tracks2D[itrack], m_neuroTrackInputMode);
151 unsigned long chitPattern =
152 m_NeuroTrigger.getCompleteHitPattern(geoSectors[0], *m_tracks2D[itrack], m_neuroTrackInputMode);
154 unsigned long puredriftth =
155 m_NeuroTrigger.getPureDriftThreshold(geoSectors[0], *m_tracks2D[itrack], m_neuroTrackInputMode);
157 int isector = m_NeuroTrigger.selectMLPbyPattern(geoSectors, hitPattern, m_neuroTrackInputMode);
158 if (isector < 0)
continue;
160 vector<unsigned> hitIds;
161 if (m_neuroTrackInputMode) {
162 hitIds = m_NeuroTrigger.selectHitsHWSim(isector, *m_tracks2D[itrack]);
164 hitIds = m_NeuroTrigger.selectHits(isector, *m_tracks2D[itrack]);
166 vector<float> MLPinput = m_NeuroTrigger.getInputVector(isector, hitIds);
167 if (m_hardwareCompatibilityMode) {
168 for (
unsigned isl = 0; isl < 9; isl++) {
169 MLPinput[3 * isl] = hwInputIdShuffle(MLPinput[3 * isl], isl);
173 vector<float> target;
175 target = m_NeuroTrigger.runMLPFix(isector, MLPinput);
177 target = m_NeuroTrigger.runMLP(isector, MLPinput);
180 int zIndex = m_NeuroTrigger[isector].zIndex();
181 double z = (zIndex >= 0) ? target[zIndex] : 0.;
182 int thetaIndex = m_NeuroTrigger[isector].thetaIndex();
183 double cot = (thetaIndex >= 0) ? cos(target[thetaIndex]) / sin(target[thetaIndex]) : 0.;
184 bool valtrack = (m_neuroTrackInputMode) ? m_tracks2D[itrack]->getValidStereoBit() :
true;
185 std::vector<bool> tsvector;
186 for (
int k = 0; k < 9; k++) {
187 tsvector.push_back(
bool ((chitPattern & (1 << k)) >> k));
189 tsvector = (m_neuroTrackInputMode) ? m_tracks2D[itrack]->getTSVector() : tsvector;
190 std::vector<bool> driftthreshold;
191 for (
int k = 8; k >= 0; k--) {
192 driftthreshold.push_back(!tsvector[k] ||
static_cast<bool>((puredriftth & (1 << k)) >> k));
194 int expert = (m_neuroTrackInputMode) ? m_tracks2D[itrack]->getExpert() : isector;
196 double tphi = m_tracks2D[itrack]->getPhi0();
197 if (tphi > -1 * M_PI_4 && tphi < 1 * M_PI_4) { quadrant = 0; }
198 else if (tphi > 1 * M_PI_4 && tphi < 3 * M_PI_4) { quadrant = 1; }
199 else if (tphi > 3 * M_PI_4 || tphi < -3 * M_PI_4) { quadrant = 2; }
200 else if (tphi > -3 * M_PI_4 && tphi < -1 * M_PI_4) { quadrant = 3; }
207 m_tracksNN.appendNew(m_tracks2D[itrack]->getPhi0(),
208 m_tracks2D[itrack]->getOmega(),
209 m_tracks2D[itrack]->getChi2D(),
211 m_tracks2D[itrack]->getFoundOldTrack(),
216 m_tracks2D[itrack]->getTime(),
219 m_tracks2D[itrack]->getQualityVector()
221 m_tracks2D[itrack]->addRelationTo(NNtrack);
222 if (m_neuroTrackInputMode) {
223 m_tracks2D[itrack]->getRelatedFrom<
CDCTriggerTrack>(m_realinputCollectionName)->addRelationTo(NNtrack);
226 for (
unsigned i = 0; i < hitIds.size(); ++i) {
227 NNtrack->addRelationTo(m_segmentHits[hitIds[i]]);
229 if (m_writeMLPinput) {
232 for (
unsigned ii = 0; ii < MLPinput.size(); ++ii) {
233 MLPinput[ii] = long(MLPinput[ii] * (1 << m_precision[3])) / float(1 << m_precision[3]);
236 auto* storeInput = m_mlpInput.appendNew(MLPinput,
unsigned(isector));
237 NNtrack->addRelationTo(storeInput);
The neural network module of the CDC trigger.
virtual void initialize() override
Initialize the module.
virtual void event() override
Called once for each event.
float hwInputIdShuffle(float tsid, int sl)
shuffle the input ids in the input vector to match the hardware
Track created by the CDC trigger.
@ c_Event
Different object in each event, all objects/arrays are invalidated after event() function has been ca...
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Abstract base class for different kinds of events.