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', 'etfcc' for the unpacked etf in the corresponding cc, 'etfcc_or_fastestpriority', 'etfcc_or_zero', 'etfhwin' for the recalculated time used in hw input. Last two options are only available for neurotrackinputode.",
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<unsigned> tsvector(9, 0);
186 for (
unsigned i = 0; i < hitIds.size(); ++i) {
187 tsvector[m_segmentHits[hitIds[i]]->getISuperLayer()] = m_segmentHits[hitIds[i]]->getLeftRight();
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 (m_neuroTrackInputMode) {
198 quadrant = m_tracks2D[itrack]->getQuadrant();
200 if (tphi > -1 * M_PI_4 && tphi < 1 * M_PI_4) { quadrant = 0; }
201 else if (tphi > 1 * M_PI_4 && tphi < 3 * M_PI_4) { quadrant = 1; }
202 else if (tphi > 3 * M_PI_4 || tphi < -3 * M_PI_4) { quadrant = 2; }
203 else if (tphi > -3 * M_PI_4 && tphi < -1 * M_PI_4) { quadrant = 3; }
210 m_tracksNN.appendNew(m_tracks2D[itrack]->getPhi0(),
211 m_tracks2D[itrack]->getOmega(),
212 m_tracks2D[itrack]->getChi2D(),
214 m_tracks2D[itrack]->getFoundOldTrack(),
219 m_tracks2D[itrack]->getTime(),
221 m_tracks2D[itrack]->getQualityVector()
223 std::stringstream intomega;
224 std::stringstream intphi;
225 std::stringstream intz;
226 std::stringstream inttheta;
227 intomega << std::fixed << std::setprecision(0) << NNtrack->getOmega() /
Const::speedOfLight / 1.5e-4 * 0.3 * 34.;
228 intphi << std::fixed << std::setprecision(0) << (((NNtrack->getPhi0() - M_PI / 2.*NNtrack->
getQuadrant()) - M_PI / 4.) * 2 *
231 std::vector<float> recalcsw(0.);
232 recalcsw = m_cdctriggerneuroconfig->getMLPs()[0].scaleTarget({
static_cast<float>(NNtrack->getZ0()),
static_cast<float>(NNtrack->getDirection().Theta())});
233 intz << std::fixed << std::setprecision(0) << recalcsw[0] * 4096;
234 inttheta << std::fixed << std::setprecision(0) << recalcsw[1] * 4096;
236 NNtrack->setRawOmega(std::stoi(intomega.str()));
238 NNtrack->setRawZ(std::stoi(intz.str()));
239 NNtrack->setRawTheta(std::stoi(inttheta.str()));
241 m_tracks2D[itrack]->addRelationTo(NNtrack);
242 if (m_neuroTrackInputMode) {
243 m_tracks2D[itrack]->getRelatedFrom<
CDCTriggerTrack>(m_realinputCollectionName)->addRelationTo(NNtrack);
246 for (
unsigned i = 0; i < hitIds.size(); ++i) {
247 NNtrack->addRelationTo(m_segmentHits[hitIds[i]]);
249 if (m_writeMLPinput) {
252 for (
unsigned ii = 0; ii < MLPinput.size(); ++ii) {
253 MLPinput[ii] = long(MLPinput[ii] * (1 << m_precision[3])) / float(1 << m_precision[3]);
256 auto* storeInput = m_mlpInput.appendNew(MLPinput,
unsigned(isector));
257 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.
void setRawPhi0(const int phi0)
setter and getter functions for raw track values
short getQuadrant() const
get the quadrant
static const double speedOfLight
[cm/ns]
@ 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.