Belle II Software  release-05-02-19
CDCTriggerNeuroModule.cc
1 #include "trg/cdc/modules/neurotrigger/CDCTriggerNeuroModule.h"
2 
3 #include <cmath>
4 
5 using namespace Belle2;
6 using namespace std;
7 
8 //this line registers the module with the framework and actually makes it available
9 //in steering files or the the module list (basf2 -m).
10 REG_MODULE(CDCTriggerNeuro)
11 
13 {
14  setDescription(
15  "The NeuroTrigger module of the CDC trigger.\n"
16  "Takes track segments and 2D track estimates as input and estimates\n"
17  "the z-vertex for each track using a neural network.\n"
18  "Requires one or several trained networks stored in a file.\n"
19  );
20  setPropertyFlags(c_ParallelProcessingCertified);
21  // parameters for saving / loading
22  addParam("filename", m_filename,
23  "Name of the files where the NeuroTrigger parameters are saved. "
24  "When left blank, the parameters are loaded from the Conditions "
25  "Database."
26  "(compare NeuroTriggerTrainer).",
27  string(""));
28  addParam("arrayname", m_arrayname,
29  "Name of the TObjArray holding the NeuroTrigger parameters "
30  "(compare NeuroTriggerTrainer).",
31  string("MLPs"));
32  addParam("hitCollectionName", m_hitCollectionName,
33  "Name of the input StoreArray of CDCTriggerSegmentHits.",
34  string(""));
35  addParam("EventTimeName", m_EventTimeName,
36  "Name of the event time object.",
37  string(""));
38  addParam("inputCollectionName", m_inputCollectionName,
39  "Name of the StoreArray holding the 2D input tracks or Neurotracks.",
40  string("TRGCDC2DFinderTracks"));
41  addParam("realinputCollectionName", m_realinputCollectionName,
42  "Name of the StoreArray holding the 2D input tracks in case "
43  "Neurotracks were used for the inputCollectionName.",
44  string("CDCTriggerNNInput2DFinderTracks"));
45  addParam("outputCollectionName", m_outputCollectionName,
46  "Name of the StoreArray holding the output tracks with neural "
47  "network estimates.",
48  string("TRGCDCNeuroTracks"));
49  addParam("fixedPoint", m_fixedPoint,
50  "Switch to turn on fixed point arithmetic for FPGA simulation.",
51  false);
52  addParam("precision", m_precision,
53  "fixed point precision in bit after radix point (for track phi, "
54  "scaling factor, reference id, MLP nodes, MLP weights, "
55  "MLP activation function)", {12, 8, 8, 12, 10, 10});
56  addParam("et_option", m_et_option,
57  "option on how to obtain the event time. When left blank, the value "
58  "is loaded from the Conditions Database. Possibilities are: "
59  "'etf_only', 'fastestpriority', 'zero', 'etf_or_fastestpriority', "
60  "'etf_or_zero', 'etf_or_fastest2d', 'fastest2d'.",
61  string(""));
62  addParam("writeMLPinput", m_writeMLPinput,
63  "if true, the MLP input vector will be written to the datastore "
64  "(for DQM)",
65  false);
66  addParam("hardwareCompatibilityMode", m_hardwareCompatibilityMode,
67  "Switch to mimic an apparent bug in the hardware preprocessing",
68  false);
69  addParam("NeuroHWTrackInputMode", m_neuroTrackInputMode,
70  "use Neurotracks instead of 2DTracks as input",
71  false);
72 }
73 
74 
75 void
77 {
78  // Load Values from the conditions Database. The actual MLP-values are loaded
79  // in the Neurotrigger class itself to avoid bigger changes in the code.
80  if (m_et_option.size() < 1) {
81  m_et_option = m_cdctriggerneuroconfig->getUseETF() ? "etf_or_fastestpriority" : "fastestpriority";
82  B2DEBUG(2, "The firmware version of the Neurotrigger boards is: " + m_cdctriggerneuroconfig->getNNTFirmwareVersionID());
83  }
84  if (!m_NeuroTrigger.load(m_filename, m_arrayname))
85  B2ERROR("NeuroTrigger could not be loaded correctly.");
86  if (m_fixedPoint) {
87  m_NeuroTrigger.setPrecision(m_precision);
88  }
89  if (m_et_option == "") {
90  m_et_option = m_NeuroTrigger.get_et_option();
91  }
92  m_tracksNN.registerInDataStore(m_outputCollectionName);
93  m_tracks2D.isRequired(m_inputCollectionName);
94  m_segmentHits.isRequired(m_hitCollectionName);
95  m_NeuroTrigger.initializeCollections(m_hitCollectionName, m_EventTimeName, m_et_option);
96 
97  m_tracks2D.registerRelationTo(m_tracksNN);
98  m_tracks2D.requireRelationTo(m_segmentHits);
99  m_tracksNN.registerRelationTo(m_segmentHits);
100  if (m_neuroTrackInputMode) {
101  m_realtracks2D.isRequired(m_realinputCollectionName);
102  m_realtracks2D.registerRelationTo(m_tracksNN);
103  }
104  if (m_writeMLPinput) {
105  m_mlpInput.registerInDataStore(m_outputCollectionName + "Input");
106  m_tracksNN.registerRelationTo(m_mlpInput, DataStore::c_Event);
107  }
108 }
109 
111 {
112  switch (sl) {
113  case 8: return tsid + 0.12;
114  case 4: return tsid / 2;
115  case 3: return tsid - 0.12;
116  case 1: return (tsid + 0.12) / 2;
117  case 0: return tsid / 4;
118  default: return tsid;
119  }
120 }
121 
122 void
124 {
125  for (int itrack = 0; itrack < m_tracks2D.getEntries(); ++itrack) {
126  // calculate parameters that depend only on track
127  if (m_fixedPoint) {
128  m_NeuroTrigger.updateTrackFix(*m_tracks2D[itrack]);
129  } else {
130  m_NeuroTrigger.updateTrack(*m_tracks2D[itrack]);
131  }
132  // get all MLPs that match the phase space sector
133  vector<int> geoSectors =
134  m_NeuroTrigger.selectMLPs(m_tracks2D[itrack]->getPhi0(),
135  m_tracks2D[itrack]->getKappa(1.5),
136  atan2(1., m_tracks2D[itrack]->getCotTheta()));
137  if (geoSectors.size() == 0) continue;
138  // read out or determine event time
139  m_NeuroTrigger.getEventTime(geoSectors[0], *m_tracks2D[itrack], m_et_option, m_neuroTrackInputMode);
140  // get the hit pattern (depends on phase space sector)
141  unsigned long hitPattern =
142  m_NeuroTrigger.getInputPattern(geoSectors[0], *m_tracks2D[itrack], m_neuroTrackInputMode);
143  // get the MLP that matches the hit pattern
144  int isector = m_NeuroTrigger.selectMLPbyPattern(geoSectors, hitPattern, m_neuroTrackInputMode);
145  if (isector < 0) continue;
146  // get the input for the MLP
147  vector<unsigned> hitIds;
148  if (m_neuroTrackInputMode) {
149  hitIds = m_NeuroTrigger.selectHitsHWSim(isector, *m_tracks2D[itrack]);
150  } else {
151  hitIds = m_NeuroTrigger.selectHits(isector, *m_tracks2D[itrack]);
152  }
153  vector<float> MLPinput = m_NeuroTrigger.getInputVector(isector, hitIds);
154  if (m_hardwareCompatibilityMode) {
155  for (unsigned isl = 0; isl < 9; isl++) {
156  MLPinput[3 * isl] = hwInputIdShuffle(MLPinput[3 * isl], isl);
157  }
158  }
159  // run the MLP
160  vector<float> target;
161  if (m_fixedPoint) {
162  target = m_NeuroTrigger.runMLPFix(isector, MLPinput);
163  } else {
164  target = m_NeuroTrigger.runMLP(isector, MLPinput);
165  }
166  // create a new track with the MLP output values
167  int zIndex = m_NeuroTrigger[isector].zIndex();
168  double z = (zIndex >= 0) ? target[zIndex] : 0.;
169  int thetaIndex = m_NeuroTrigger[isector].thetaIndex();
170  double cot = (thetaIndex >= 0) ? cos(target[thetaIndex]) / sin(target[thetaIndex]) : 0.;
171  const CDCTriggerTrack* NNtrack =
172  m_tracksNN.appendNew(m_tracks2D[itrack]->getPhi0(),
173  m_tracks2D[itrack]->getOmega(),
174  m_tracks2D[itrack]->getChi2D(),
175  z, cot, 0.,
176  m_tracks2D[itrack]->getFoundOldTrack(),
177  m_tracks2D[itrack]->getDriftThreshold(),
178  m_tracks2D[itrack]->getValidStereoBit(),
179  m_tracks2D[itrack]->getExpert(),
180  m_tracks2D[itrack]->getTSVector(),
181  m_tracks2D[itrack]->getTime(),
182  -1 //quadrant not known in simulation
183  );
184  m_tracks2D[itrack]->addRelationTo(NNtrack);
185  if (m_neuroTrackInputMode) {
186  m_tracks2D[itrack]->getRelatedFrom<CDCTriggerTrack>(m_realinputCollectionName)->addRelationTo(NNtrack);
187  }
188  // relations to hits used in MLP
189  for (unsigned i = 0; i < hitIds.size(); ++i) {
190  NNtrack->addRelationTo(m_segmentHits[hitIds[i]]);
191  }
192  if (m_writeMLPinput) {
193  // for fixed point precision, round the inputs before saving
194  if (m_fixedPoint) {
195  for (unsigned ii = 0; ii < MLPinput.size(); ++ii) {
196  MLPinput[ii] = long(MLPinput[ii] * (1 << m_precision[3])) / float(1 << m_precision[3]);
197  }
198  }
199  auto* storeInput = m_mlpInput.appendNew(MLPinput, unsigned(isector));
200  NNtrack->addRelationTo(storeInput);
201  }
202  }
203 }
Belle2::CDCTriggerNeuroModule::event
virtual void event() override
Called once for each event.
Definition: CDCTriggerNeuroModule.cc:123
REG_MODULE
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:652
Belle2::CDCTriggerTrack
Track created by the CDC trigger.
Definition: CDCTriggerTrack.h:15
Belle2::CDCTriggerNeuroModule
The neural network module of the CDC trigger.
Definition: CDCTriggerNeuroModule.h:24
Belle2::CDCTriggerNeuroModule::hwInputIdShuffle
float hwInputIdShuffle(float tsid, int sl)
shuffle the input ids in the input vector to match the hardware
Definition: CDCTriggerNeuroModule.cc:110
Belle2::Module
Base class for Modules.
Definition: Module.h:74
Belle2
Abstract base class for different kinds of events.
Definition: MillepedeAlgorithm.h:19
Belle2::CDCTriggerNeuroModule::initialize
virtual void initialize() override
Initialize the module.
Definition: CDCTriggerNeuroModule.cc:76
Belle2::DataStore::c_Event
@ c_Event
Different object in each event, all objects/arrays are invalidated after event() function has been ca...
Definition: DataStore.h:61