Belle II Software  release-08-01-10
NeuroTriggerParameters.cc
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 #include <trg/cdc/NeuroTriggerParameters.h>
9 
10 
11 #include <TFile.h>
12 #include "boost/iostreams/filter/gzip.hpp"
13 #include "boost/iostreams/filtering_streambuf.hpp"
14 #include "boost/iostreams/filtering_stream.hpp"
15 #include "boost/multi_array.hpp"
16 #include <iostream>
17 #include <fstream>
18 #include <framework/core/Module.h>
19 
20 
21 using namespace Belle2;
22 
23 NeuroTriggerParameters::NeuroTriggerParameters(std::string& filename)
24 {
26 
27 }
28 
29 void
30 NeuroTriggerParameters::loadconfigtxt(const std::string& filename)
31 {
32  // now loading confile
33  std::ifstream confile;
34  try {
35  confile.open(filename, std::ifstream::in);
36  } catch (int e) {
37  saveconfigtxt("neuroconfig_example.conf");
38  B2ERROR("Configuration file " + filename + " could not be loaded! Make sure to give the configuration file as a parameter. \
39  An example file neuroconfig_example.conf has been saved.");
40 
41  exit(EXIT_FAILURE);
42  }
43  std::string line_all;
44  if (!confile.is_open()) {
45  saveconfigtxt("neuroconfig_example.conf");
46  B2ERROR("Configuration file " + filename + " could not be loaded! Make sure to give the configuration file as a parameter. \
47  An example file neuroconfig_example.conf has been saved.");
48  exit(EXIT_FAILURE);
49  }
50  while (std::getline(confile, line_all)) {
51  // remove comments
52  std::size_t hashtag = line_all.find('#');
53  std::string line = line_all.substr(0, hashtag);
54  std::string par;
55  std::string key;
56  std::string skip;
57  if (line.length() < 3) {
58  continue;
59  // check, if line wasnt a pure comment line
60  }
61  bool locked = false; //check, if "==" was used and the variable should be registered as locked
62  if (line.find('=') == std::string::npos) {
63  continue;
64  }
65  line.erase(std::remove(line.begin(), line.end(), ' '), line.end()); // remove whitespaces in whole string
66  par = line.substr(0, line.find('='));
67  std::string l;
68  l = line.substr(line.find("=") + 1, 1);
69  if (l == "=") {
70  locked = true;
71  }
72  // now find the value that should be asigned to the "par"
73  key = (locked) ? line.substr((line.find('=') + 2), line.length() - line.find('=') - 2) : line.substr((line.find('=') + 1),
74  line.length() - line.find('=') - 1);
75  if (par == "nInput") {
76  nInput = std::stoul(key);
77  if (locked) {nInput.lock();}
78  } else if (par == "nOutput") {
79  nOutput = std::stoul(key);
80  if (locked) {nOutput.lock();}
81  } else if (par == "relevantCut") {
82  relevantCut = std::stod(key);
83  if (locked) {relevantCut.lock();}
84  } else if (par == "nMLP") {
85  nMLP = std::stoul(key);
86  if (locked) {nMLP.lock();}
87  } else if (par == "targetZ") {
88  targetZ = std::stoi(key);
89  if (locked) {targetZ.lock();}
90  } else if (par == "targetTheta") {
91  targetTheta = std::stoi(key);
92  if (locked) {targetTheta.lock();}
93  } else if (par == "multiplyHidden") {
94  multiplyHidden = std::stoi(key);
95  if (locked) {multiplyHidden.lock();}
96  } else if (par == "rescaleTarget") {
97  rescaleTarget = std::stoi(key);
98  if (locked) {rescaleTarget.lock();}
99  } else if (par == "cutSum") {
100  cutSum = std::stoi(key);
101  if (locked) {cutSum.lock();}
102  } else if (par == "tMax") {
103  tMax = std::stoul(key);
104  if (locked) {tMax.lock();}
105  } else if (par == "ETOption") {
106  ETOption = std::stoul(key);
107  if (locked) {ETOption.lock();}
108  } else if (par == "IDRanges") {
109  IDRanges = read2dArray<float>(key, locked);
110  } else if (par == "phiRangeUse") {
111  phiRangeUse = read2dArray<float>(key, locked);
112  } else if (par == "thetaRangeUse") {
113  thetaRangeUse = read2dArray<float>(key, locked);
114  } else if (par == "invptRangeUse") {
115  invptRangeUse = read2dArray<float>(key, locked);
116  } else if (par == "phiRangeTrain") {
117  phiRangeTrain = read2dArray<float>(key, locked);
118  } else if (par == "thetaRangeTrain") {
119  thetaRangeTrain = read2dArray<float>(key, locked);
120  } else if (par == "invptRangeTrain") {
121  invptRangeTrain = read2dArray<float>(key, locked);
122  } else if (par == "nHidden") {
123  nHidden = read2dArray<float>(key, locked);
124  } else if (par == "maxHitsPerSL") {
125  maxHitsPerSL = read1dArray<unsigned short>(key, locked);
126  } else if (par == "outputScale") {
127  outputScale = read2dArray<float>(key, locked);
128  } else if (par == "SLpattern") {
129  SLpattern = read1dArray<unsigned long>(key, locked);
130  } else if (par == "SLpatternMask") {
131  SLpatternMask = read1dArray<unsigned long>(key, locked);
132  } else if (par == "precision") {
133  precision = read1dArray<unsigned>(key, locked);
134  }
135  }
136 }
137 template<typename X>
138 bool NeuroTriggerParameters::checkarr(std::vector<std::vector<NNTParam<X>>> vec)
139 {
140  // check, if a vector is already set. this is done by just checking the first member of the vector.
141  if (vec.size() < 1) {return false;}
142  else if (vec[0].size() < 1) {return false;}
143  else {return vec[0][0].isSet();}
144 }
145 
146 template<typename X>
148 {
149  // check, if a vector is already set. this is done by just checking the first member of the vector.
150  if (vec.size() < 1) {return false;}
151  else {return vec[0].isSet();}
152 }
153 
154 void NeuroTriggerParameters::saveconfigtxt(const std::string& filename)
155 {
156  // save all the configuration otions in a file, which can later be used to initialize a new parameter set.
157  // only paramters, that already have been set are saved. parameters which are locked, are written wit a "==".
158  std::ofstream savestream;
159  savestream.open(filename);
160  savestream << "########################################################" << std::endl;
161  savestream << "### Neurotrigger configuration file created by basf2 ###" << std::endl;
162  savestream << "########################################################" << std::endl << std::endl;
163  savestream << "# '=' means the parameter is set and can be changed," << std::endl;
164  savestream << "# '==' means the parameter is locked and should not be changed." << std::endl << std::endl;
165 
166  savestream << "# number of input nodes " << std::endl;
167  if (nInput.isSet()) {
168  savestream << "nInput " << (nInput.isLocked() ? "== " : "= ") << nInput << std::endl;
169  savestream << std::endl;
170  } else {savestream << "nInput = 27" << std::endl;}
171  savestream << "# number of output nodes " << std::endl;
172  if (nOutput.isSet()) {
173  savestream << "nOutput " << (nOutput.isLocked() ? "== " : "= ") << nOutput << std::endl;
174  savestream << std::endl;
175  } else {savestream << "nOutput = 2" << std::endl;}
176  savestream << "# If true, relevantCut is applied to the sum over hit counters, " << std::endl;
177  savestream << "# otherwise directly on the hit counters." << std::endl;
178  if (cutSum.isSet()) {
179  savestream << "cutSum " << (cutSum.isLocked() ? "== " : "= ") << cutSum << std::endl;
180  savestream << std::endl;
181  } else {savestream << "cutSum = 0" << std::endl;}
182  savestream << "# only used in the idhist module. it defines the how much of the idrange is cut off after making the histogram " <<
183  std::endl;
184  if (relevantCut.isSet()) {
185  savestream << "relevantCut " << (relevantCut.isLocked() ? "== " : "= ") << relevantCut << std::endl;
186  savestream << std::endl;
187  } else {savestream << "relevantCut = 0.02" << std::endl;}
188  savestream << "# flag to allow for target tracks lying out of the output range to be rescaled during training. " << std::endl;
189  if (rescaleTarget.isSet()) {
190  savestream << "rescaleTarget " << (rescaleTarget.isLocked() ? "== " : "= ") << rescaleTarget << std::endl;
191  savestream << std::endl;
192  } else {savestream << "rescaleTarget = 0" << std::endl;}
193  savestream << "# Number of networks. For network specific parameters you can give " << std::endl;
194  savestream << "# either a list with values for each network, or a single value that will be used" << std::endl;
195  savestream << "# for all. The ranges are also valid if nPhi * nPt * nTheta * nPattern = nMLPs. " << std::endl;
196  if (nMLP.isSet()) {
197  savestream << "nMLP " << (nMLP.isLocked() ? "== " : "= ") << nMLP << std::endl;
198  savestream << std::endl;
199  } else {savestream << "nMLP = 5" << std::endl;}
200  savestream << "# train z as output " << std::endl;
201  if (targetZ.isSet()) {
202  savestream << "targetZ " << (targetZ.isLocked() ? "== " : "= ") << targetZ << std::endl;
203  savestream << std::endl;
204  } else {savestream << "targetZ = 1" << std::endl;}
205  savestream << "# train theta as output " << std::endl;
206  if (targetTheta.isSet()) {
207  savestream << "targetTheta " << (targetTheta.isLocked() ? "== " : "= ") << targetTheta << std::endl;
208  savestream << std::endl;
209  } else {savestream << "targetTheta = 1" << std::endl;}
210  savestream << "# If true, multiply nHidden with number of input nodes. " << std::endl;
211  if (multiplyHidden.isSet()) {
212  savestream << "multiplyHidden " << (multiplyHidden.isLocked() ? "== " : "= ") << multiplyHidden << std::endl;
213  savestream << std::endl;
214  } else {savestream << "multiplyHidden = 0" << std::endl;}
215  savestream << "# Maximal drift time, identical for all networks. " << std::endl;
216  if (tMax.isSet()) {
217  savestream << "tMax " << (tMax.isLocked() ? "== " : "= ") << tMax << std::endl;
218  savestream << std::endl;
219  } else {savestream << "tMax = 256" << std::endl;}
220  savestream << "# Determine, how the event time should be obtained. The options are:" << std::endl;
221  for (unsigned i = 0; i < 11; i++) {
222  savestream << "# " << i << ": " << to_strTiming(i) << std::endl;
223  }
224  if (ETOption.isSet()) {
225  savestream << "ETOption " << (ETOption.isLocked() ? "== " : "= ") << ETOption << std::endl;
226  savestream << std::endl;
227  } else {savestream << "ETOption = 7" << std::endl;}
228  savestream << "# Phi region for which MLP is used in degree for all networks. " << std::endl;
229  if (checkarr(phiRangeUse)) {
230  savestream << print2dArray<float>("phiRangeUse", phiRangeUse);
231  savestream << std::endl;
232  } else {savestream << "phiRangeUse = [[0, 360]]" << std::endl;}
233  savestream << "# relative ID range of the relevant wire IDs of the track segments " << std::endl;
234  savestream << "# that are taken into consideration when determining the best fitting track segments. " << std::endl;
235  if (checkarr(IDRanges)) {
236  savestream << print2dArray<float>("IDRanges", IDRanges);
237  savestream << std::endl;
238  } else {
239  savestream << "IDRanges = [[0,-1.5,1.5,-7.5,-0.5,-1.5,1.5,0.5,7.5,-1.5,1.5,-8.5,0.5,-2.5,1.5,-0.5,10.5,-3.5,2.5],";
240  savestream << "[1,-1.5,1.5,-7.5,-0.5,-1.5,1.5,0.5,7.5,-1.5,1.5,-8.5,0.5,-2.5,1.5,-0.5,10.5,-3.5,2.5],";
241  savestream << "[2,-1.5,1.5,-7.5,-0.5,-1.5,1.5,0.5,7.5,-1.5,1.5,-8.5,0.5,-2.5,1.5,-0.5,10.5,-3.5,2.5],";
242  savestream << "[3,-1.5,1.5,-7.5,-0.5,-1.5,1.5,0.5,7.5,-1.5,1.5,-8.5,0.5,-2.5,1.5,-0.5,10.5,-3.5,2.5],";
243  savestream << "[4,-1.5,1.5,-7.5,-0.5,-1.5,1.5,0.5,7.5,-1.5,1.5,-8.5,0.5,-2.5,1.5,-0.5,10.5,-3.5,2.5]]";
244  savestream << std::endl;
245  }
246  savestream << "# Theta region for which MLP is used in degree for all networks. " << std::endl;
247  if (checkarr(thetaRangeUse)) {
248  savestream << print2dArray<float>("thetaRangeUse", thetaRangeUse);
249  savestream << std::endl;
250  } else {savestream << "thetaRangeUse = [[10, 170]]" << std::endl;}
251  savestream << "# Charge / Pt region for which MLP is used in 1/GeV for all networks. " << std::endl;
252  if (checkarr(invptRangeUse)) {
253  savestream << print2dArray<float>("invptRangeUse", invptRangeUse);
254  savestream << std::endl;
255  } else {savestream << "invptRangeUse = [[-5, 5]]" << std::endl;}
256  savestream << "# Phi region for which MLP is trained in degree for all networks. " << std::endl;
257  savestream << "# Can be larger than use range to avoid edge effects. " << std::endl;
258  if (checkarr(phiRangeTrain)) {
259  savestream << print2dArray<float>("phiRangeTrain", phiRangeTrain);
260  savestream << std::endl;
261  } else {savestream << "phiRangeTrain = [[0, 360]]" << std::endl;}
262  savestream << "# Theta region for which MLP is trained in degree for all networks. " << std::endl;
263  savestream << "# Can be larger than use range to avoid edge effects. " << std::endl;
264  if (checkarr(thetaRangeTrain)) {
265  savestream << print2dArray<float>("thetaRangeTrain", thetaRangeTrain);
266  savestream << std::endl;
267  } else {savestream << "thetaRangeTrain = [[10, 170]]" << std::endl;}
268  savestream << "# charge/Pt region for which MLP is trained in degree for all networks. " << std::endl;
269  savestream << "# Can be larger than use range to avoid edge effects. " << std::endl;
270  if (checkarr(invptRangeTrain)) {
271  savestream << print2dArray<float>("invptRangeTrain", invptRangeTrain);
272  savestream << std::endl;
273  } else {savestream << "invptRangeTrain = [[-5, 5]]" << std::endl;}
274  savestream << "# Number of nodes in each hidden layer for all networks" << std::endl;
275  savestream << "# or factor to multiply with number of inputs." << std::endl;
276  savestream << "# The number of layers is derived from the shape." << std::endl;
277  if (checkarr(nHidden)) {
278  savestream << print2dArray<float>("nHidden", nHidden);
279  savestream << std::endl;
280  } else {savestream << "nHidden = [[81]]" << std::endl;}
281  savestream << "# Maximum number of hits in a single super layer for all networks. " << std::endl;
282  if (checkarr(maxHitsPerSL)) {
283  savestream << print1dArray<unsigned short>("maxHitsPerSL", maxHitsPerSL);
284  savestream << std::endl;
285  } else {savestream << "maxHitsPerSL = [1]" << std::endl;}
286  savestream << "# Output scale for all networks. " << std::endl;
287  if (checkarr(outputScale)) {
288  savestream << print2dArray<float>("outputScale", outputScale);
289  savestream << std::endl;
290  } else {savestream << "outputScale = [[-100, 100, 10, 170]]" << std::endl;}
291  savestream << "# Super layer pattern for which MLP is trained for all networks." << std::endl;
292  savestream << "# Binary pattern of 9 * maxHitsPerSL bits (on/off for each hit)." << std::endl;
293  savestream << "# 0 in bit <i>: hits from super layer <i> are not used." << std::endl;
294  savestream << "# 1 in bit <i>: hits from super layer <i> are used." << std::endl;
295  savestream << "# SLpattern = 0: use any hits present, don't check the pattern. " << std::endl;
296  if (checkarr(SLpattern)) {
297  savestream << print1dArray<unsigned long>("SLpattern", SLpattern);
298  savestream << std::endl;
299  } else {savestream << "SLpattern = [511, 383, 479, 503, 509]" << std::endl;}
300  savestream << "# Super layer pattern mask for which MLP is trained for all networks." << std::endl;
301  savestream << "# Binary pattern of 9 * maxHitsPerSL bits (on/off for each hit)." << std::endl;
302  savestream << "# 0 in bit <i>: super layer <i> may or may not have a hit." << std::endl;
303  savestream << "# 1 in bit <i>: super layer <i>" << std::endl;
304  savestream << "# - must have a hit if SLpattern bit <i> = 1" << std::endl;
305  savestream << "# - must not have a hit if SLpattenr bit <i> = 0 " << std::endl;
306  if (checkarr(SLpatternMask)) {
307  savestream << print1dArray<unsigned long>("SLpatternMask", SLpatternMask);
308  savestream << std::endl;
309  } else {savestream << "SLpatternMask = [170]" << std::endl;}
310  savestream << "# precision used for the hardware simulation " << std::endl;
311  if (checkarr(precision)) {
312  savestream << print1dArray<unsigned>("precision", precision);
313  savestream << std::endl;
314  } else {savestream << "precision = [12, 8, 8, 12, 10, 10]" << std::endl;}
315  savestream.close();
316 }
317 
318 template<typename X>
319 std::string NeuroTriggerParameters::print2dArray(const std::string& name, std::vector<std::vector<NNTParam<X>>> vecvec)
320 {
321  // this is a class for piping the output of a 2d array to a string with brackets
322  std::stringstream savestream;
323  savestream << name << " " << (vecvec[0][0].isLocked() ? "== " : "= ") << "[";
324  bool outcomma = false;
325  for (auto x : vecvec) {
326  if (outcomma) {savestream << ",";}
327  outcomma = true;
328  savestream << "[";
329  bool incomma = false;
330  for (auto y : x) {
331  if (incomma) {savestream << ",";}
332  incomma = true;
333  savestream << y;
334  }
335  savestream << "]";
336  }
337  savestream << "]" << std::endl;
338  return savestream.str();
339 }
340 template<typename X>
341 std::string NeuroTriggerParameters::print1dArray(const std::string& name, std::vector<NNTParam<X>> vecvec)
342 {
343  // this is a class for piping the output of a 1d array to a string with brackets
344  std::stringstream savestream;
345  savestream << name << " " << (vecvec[0].isLocked() ? "== " : "= ") << "[";
346  bool incomma = false;
347  for (auto y : vecvec) {
348  if (incomma) {savestream << ",";}
349  incomma = true;
350  savestream << y;
351  }
352  savestream << "]" << std::endl;
353  return savestream.str();
354 }
355 template<typename X>
356 std::vector<std::vector<NNTParam<X>>> NeuroTriggerParameters::read2dArray(std::string keyx, bool locked)
357 {
358  std::vector<std::vector<NNTParam<X>>> retarr;
359  std::string key = keyx;
360  // parse the brackets here to fill the vector: [[1,2], 3,4]]
361  key = key.substr(key.find("[") + 1, std::string::npos); // without outer brackets: [1,2], [3,4]
362  for (std::size_t ipos = 0; ipos != std::string::npos; ipos = key.find("[", ipos + 1)) {
363  std::string pairstr = key.substr(ipos + 1, key.find("]", ipos + 1) - ipos - 1); // this shopuld be 1,2 now
364  std::vector<NNTParam<X>> newpair;
365  std::size_t jpos;
366  for (jpos = 0; jpos != std::string::npos; jpos = pairstr.find(",", jpos)) {
367  if (!(jpos == 0)) {jpos++;}
368  newpair.push_back(NNTParam<X>(std::stof(pairstr.substr(jpos, pairstr.find(",") - jpos))));
369  if (locked) {newpair.back().lock();}
370  }
371  retarr.push_back(newpair);
372  }
373  return retarr;
374 }
375 
376 template<typename X>
377 std::vector<NNTParam<X>> NeuroTriggerParameters::read1dArray(std::string keyx, bool locked)
378 {
379  std::string key = keyx;
380  // parse the brackets here to fill the vector: [[1,2], 3,4]]
381  std::string pairstr = key.substr(1, key.find("]", 1) - 1); // this shopuld be 1,2 now
382  std::vector<NNTParam<X>> newpair;
383  std::size_t jpos;
384  for (jpos = 0; jpos != std::string::npos; jpos = pairstr.find(",", jpos)) {
385  if (!(jpos == 0)) {jpos++;}
386  newpair.push_back(NNTParam<X>(std::stof(pairstr.substr(jpos, pairstr.find(",") - jpos))));
387  if (locked) {newpair.back().lock();}
388  }
389  return newpair;
390 }
Class to represent a complete set to describe a Neurotrigger.
bool isLocked() const
check, if variable was already locked and is read only now
bool isSet() const
check, if variable was already initialized
void lock()
lock the variable, to make it read only
std::vector< NNTParam< unsigned short > > maxHitsPerSL
Maximum number of hits in a single super layer for all networks.
std::vector< std::vector< NNTParam< float > > > invptRangeUse
Charge / Pt region for which MLP is used in 1/GeV for all networks.
std::vector< std::vector< NNTParam< float > > > thetaRangeUse
Theta region for which MLP is used in degree for all networks.
std::vector< NNTParam< X > > read1dArray(std::string keyx, bool locked)
fill the array from a given string that looks like: [1,2,3]
NNTParam< unsigned > nMLP
Number of networks.
std::vector< NNTParam< unsigned long > > SLpatternMask
Super layer pattern mask for which MLP is trained for all networks.
std::vector< std::vector< NNTParam< float > > > nHidden
Number of nodes in each hidden layer for all networks or factor to multiply with number of inputs.
std::vector< std::vector< NNTParam< float > > > thetaRangeTrain
Theta region for which MLP is trained in degree for all networks.
std::string print1dArray(const std::string &name, std::vector< NNTParam< X >> vecvec)
this is a class for piping the output of a 1d array to a string with brackets
NNTParam< unsigned > tMax
Maximal drift time, identical for all networks.
bool checkarr(std::vector< std::vector< NNTParam< X >>> vec)
check, if a vector is already set.
std::vector< NNTParam< unsigned long > > SLpattern
Super layer pattern for which MLP is trained for all networks.
NNTParam< bool > rescaleTarget
flag to allow for target tracks lying out of the output range to be rescaled during training.
std::vector< std::vector< NNTParam< float > > > IDRanges
relative ID range of the relevant wire IDs of the track segments that are taken into consideration wh...
NNTParam< bool > multiplyHidden
If true, multiply nHidden with number of input nodes.
NNTParam< bool > targetTheta
train theta as output
NNTParam< unsigned > nOutput
number of output nodes
std::vector< std::vector< NNTParam< float > > > phiRangeUse
Phi region for which MLP is used in degree for all networks.
std::vector< std::vector< NNTParam< X > > > read2dArray(std::string keyx, bool locked)
fill the array from a given string that looks like: [[1,2],[3, 4]]
NNTParam< unsigned > ETOption
Determine, how the event time should be obtained.
NNTParam< bool > targetZ
train z as output
NNTParam< bool > cutSum
only used in the idhist module.
std::vector< std::vector< NNTParam< float > > > invptRangeTrain
Charge / Pt region for which MLP is trained in 1/GeV for all networks.
std::vector< std::vector< NNTParam< float > > > phiRangeTrain
Phi region for which MLP is trained in degree for all networks.
void loadconfigtxt(const std::string &filename)
load the configuration from a file
void saveconfigtxt(const std::string &filename)
save the configuration to a file
std::string print2dArray(const std::string &name, std::vector< std::vector< NNTParam< X >>> vecvec)
this is a class for piping the output of a 2d array to a string with brackets
NNTParam< double > relevantCut
only used in the idhist module.
NNTParam< unsigned > nInput
Network parameters.
std::vector< NNTParam< unsigned > > precision
precision used for the hardware simulation
std::vector< std::vector< NNTParam< float > > > outputScale
Output scale for all networks.
Abstract base class for different kinds of events.