Belle II Software  release-05-01-25
NeuroTriggerMLPToTextfile.cc
1 /* This program loads a set of trained MLPs from a rootfile
2  * and saves the weights to a textfile with fixed point precision.
3  *
4  * output format:
5  *
6  * isector
7  * ID0min ID0max ID1min ID1max ... ID8min ID8max
8  * sectorpattern patternmask
9  * nodes1 nodes2 ... nodesN
10  * weight1 weight2 ... weightN
11  * ... (repeated for all sectors)
12  *
13  * ID<i>min/max: ID ranges for super layer <i>
14  * sectorpattern/patternmask: for sector selection based on hit pattern
15  * nodes<i>: number of nodes in layer <i>
16  * weight<i>: numerical value of weight <i>, multiplied by 2^precision
17  *
18  * weights connect input nodes of one layer to output nodes of the next layer.
19  * order:
20  * - ordered by layer
21  * - within one layer, ordered by index of output node
22  * - for fixed output node, ordered by index of input node
23  * (last input node = bias node)
24  */
25 
26 #include <iostream>
27 #include <fstream>
28 #include <TFile.h>
29 #include <TObjArray.h>
30 #include <trg/cdc/dataobjects/CDCTriggerMLP.h>
31 #include <cmath>
32 
33 using namespace std;
34 using namespace Belle2;
35 
36 int
37 main(int argc, char* argv[])
38 {
39  // get arguments
40  if (argc < 3) {
41  cout << "Program needs at least 3 arguments:" << endl
42  << " 1: MLP rootfile" << endl
43  << " 2: precision for MLP weights" << endl
44  << " 3: output filename" << endl;
45  return -1;
46  }
47  string MLPFilename = argv[1];
48  unsigned precisionWeights = atoi(argv[2]);
49 
50  TFile MLPFile(MLPFilename.c_str(), "READ");
51  if (!MLPFile.IsOpen()) {
52  cout << "Could not open file " << MLPFilename << endl;
53  return -1;
54  }
55  TObjArray* MLPs = (TObjArray*)MLPFile.Get("MLPs");
56  if (!MLPs) {
57  MLPFile.Close();
58  cout << "File " << MLPFilename << " does not contain key MLPs" << endl;
59  return -1;
60  }
61 
62  // load MLPs and write them to file
63  ofstream weightstream(argv[3]);
64  for (int isector = 0; isector < MLPs->GetEntriesFast(); ++isector) {
65  CDCTriggerMLP* expert = dynamic_cast<CDCTriggerMLP*>(MLPs->At(isector));
66  if (!expert) {
67  cout << "Wrong type " << MLPs->At(isector)->ClassName()
68  << ", ignoring this entry." << endl;
69  continue;
70  }
71  // write sector number
72  weightstream << isector << endl;
73  // write ID ranges
74  for (unsigned isl = 0; isl < 9; ++isl) {
75  weightstream << expert->getIDRange(isl)[0] << " "
76  << expert->getIDRange(isl)[1] << " ";
77  }
78  weightstream << endl;
79  // write sector pattern
80  unsigned pattern = expert->getSLpatternUnmasked();
81  weightstream << pattern << " " << expert->getSLpatternMask() << endl;
82  // write number of nodes per network layer
83  vector<unsigned> nNodes = {};
84  for (unsigned il = 0; il < expert->nLayers(); ++il) {
85  nNodes.push_back(expert->nNodesLayer(il));
86  weightstream << nNodes.back() << " ";
87  }
88  weightstream << endl;
89  // write weights and check range
90  vector<float> weights = expert->getWeights();
91  float minWeight = 0;
92  float maxWeight = 0;
93  for (unsigned iw = 0; iw < weights.size(); ++iw) {
94  double weight = weights[iw];
95  // set weights for unused inputs to 0
96  if (iw < ((nNodes[0] + 1) * nNodes[1])) {
97  unsigned isl = (iw % (nNodes[0] + 1)) / 3;
98  if (isl < 9 && !((pattern >> isl) & 1)) weight = 0;
99  }
100  if (weight < minWeight) minWeight = weight;
101  if (weight > maxWeight) maxWeight = weight;
102  weightstream << round(weight * (1 << precisionWeights)) << " ";
103  }
104  weightstream << endl;
105  cout << weights.size() << " weights in [" << minWeight << "," << maxWeight << "]" << endl;
106  }
107  MLPs->Clear();
108  delete MLPs;
109  MLPFile.Close();
110  weightstream.close();
111 
112  return 0;
113 }
main
int main(int argc, char **argv)
Run all tests.
Definition: test_main.cc:77
Belle2
Abstract base class for different kinds of events.
Definition: MillepedeAlgorithm.h:19
Belle2::CDCTriggerMLP
Class to keep all parameters of an expert MLP for the neuro trigger.
Definition: CDCTriggerMLP.h:13