Belle II Software prerelease-11-00-00a
GRLNeuroModule.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
9#include <fstream>
10#include <sstream>
11#include <string>
12#include <unordered_map>
13#include <cstdlib>
14#include <iomanip>
15#include <cmath>
16#include <TFile.h>
17
18#include <framework/datastore/StoreArray.h>
19#include <framework/datastore/StoreObjPtr.h>
20#include <framework/dataobjects/EventMetaData.h>
21#include <framework/core/ModuleParam.templateDetails.h>
22#include <framework/gearbox/Unit.h>
23#include <framework/utilities/FileSystem.h>
24#include <analysis/utility/PCmsLabTransform.h>
25#include <trg/ecl/TrgEclMapping.h>
26#include <trg/ecl/dataobjects/TRGECLCluster.h>
27#include <trg/grl/dataobjects/GRLMLPData.h>
28#include <trg/grl/dataobjects/TRGGRLInfo.h>
29#include "trg/grl/dataobjects/TRGGRLUnpackerStore.h"
30#include "trg/grl/modules/trggrlneuralnet/GRLNeuroModule.h"
31
32
33using namespace Belle2;
34using namespace std;
35
36//-----------------------------------------------------------------
37// Register the Module
38//-----------------------------------------------------------------
40
41//-----------------------------------------------------------------
42// Implementation
43//-----------------------------------------------------------------
44//
46{
48 "The NeuroTrigger module of the GRL.\n"
49 "Takes CDC track and ECL cluster to prepare input data\n"
50 "for the training of a neural network.\n"
51 "Networks are trained after the event loop and saved."
52 );
54 // parameters for saving / loading
55 addParam("TrgGrlInformation", m_TrgGrlInformationName,
56 "Name of the StoreArray holding the information of tracks and clusters from cdc ecl klm.",
57 string("TRGGRLObjects"));
58 addParam("HistFileName", m_HistFileName,
59 "Name of the root file saving the output histogram.",
60 string("hist.root"));
61 addParam("SaveHist", m_saveHist,
62 "Save the output histogram to root file.",
63 false);
64 addParam("nMLP", m_parameters.nMLP,
65 "Number of expert MLPs.", 1u);
66 addParam("n_cdc_sector", m_parameters.n_cdc_sector,
67 "Number of expert CDC MLPs.", 0u);
68 addParam("n_ecl_sector", m_parameters.n_ecl_sector,
69 "Number of expert ECL MLPs.", 1u);
70 addParam("i_cdc_sector", m_parameters.i_cdc_sector,
71 "#cdc track of expert MLPs.", {0});
72 addParam("i_ecl_sector", m_parameters.i_ecl_sector,
73 "#ecl cluster of expert MLPs.", {24});
74 addParam("nHidden", m_parameters.nHidden,
75 "Number of nodes in each hidden layer for all networks "
76 "or factor to multiply with number of inputs (1 list or nMLP lists). "
77 "The number of layers is derived from the shape.",
78 {{24, 24, 24}});
79 addParam("multiplyHidden", m_parameters.multiplyHidden,
80 "If true, multiply nHidden with number of input nodes.", false);
81
82 addParam("csvThetaPhiFile", m_csvThetaPhiFile,
83 "CSV file for theta/phi correction per tcid.",
84 {FileSystem::findFile("/data/trg/grl/tcid_correct_theta_phi.csv", true)});
85
86 addParam("TRGECLClusters", m_TrgECLClusterName,
87 "Name of the StoreArray holding the information of trigger ecl clusters ",
88 string("TRGECLClusters"));
89 addParam("MVACut", m_parameters.nn_thres,
90 "Cut value applied to the MLP output",
91 {{0}});
92 addParam("useDB", m_useDB,
93 "Flag to use database to set config", true);
94
95 // // TRGGRLInfo must exist for this module
96 // addRequired<TRGGRLInfo>(m_TrgGrlInformationName);
97
98}
99
100
101void
103{
104
105 std::string csvPath = FileSystem::findFile(m_csvThetaPhiFile, true);
106 if (csvPath.empty()) {
107 B2ERROR("Cannot find tcid_correct_theta_phi.csv");
108 return;
109 }
110
111 std::ifstream infile(csvPath);
112 if (!infile.is_open()) {
113 B2ERROR(("Failed to open " + csvPath).c_str());
114 return;
115 }
116
117 std::string line;
118 bool isFirstLine = true;
119 while (std::getline(infile, line)) {
120 if (isFirstLine) {
121 isFirstLine = false;
122 continue;
123 }
124
125 std::stringstream ss(line);
126 std::string tc_str, theta_str, phi_str;
127 std::getline(ss, tc_str, ',');
128 std::getline(ss, theta_str, ',');
129 std::getline(ss, phi_str, ',');
130
131 if (tc_str.empty() || theta_str.empty() || phi_str.empty()) continue;
132
133 int tc = std::stoi(tc_str);
134 if (tc == 0) continue;
135 double theta = std::stod(theta_str) * TMath::RadToDeg();
136 double phi = std::stod(phi_str) * TMath::RadToDeg();
137
138 thetaMap[tc] = theta;
139 phiMap[tc] = phi;
140 }
141
142 infile.close();
143
144 TCThetaLab.clear();
145 TCPhiLab.clear();
146 TCThetaLab.reserve(576);
147 TCPhiLab.reserve(576);
148
149 for (int tc = 1; tc <= 576; ++tc) {
150 if (thetaMap.count(tc)) {
151 TCThetaLab.push_back(thetaMap[tc]);
152 TCPhiLab.push_back(phiMap[tc]);
153 } else {
154
155 TCThetaLab.push_back(0.0);
156 TCPhiLab.push_back(0.0);
157 }
158 }
159
160
161 B2INFO("Loaded TC geometry (theta/phi) from tcid_correct_theta_phi.csv");
162 B2INFO(Form("Example: TC 1 => theta = %.3f deg, phi = %.3f deg", TCThetaLab[0], TCPhiLab[0]));
163
164
165}
166
167
168void
170{
171 if (m_useDB) {
172 if (not m_db_trggrlconfig.isValid()) {
173 StoreObjPtr<EventMetaData> evtMetaData;
174 B2FATAL("No database for TRG GRL config. exp " << evtMetaData->getExperiment() << " run "
175 << evtMetaData->getRun());
176 } else {
177 m_parameters.nMLP = m_db_trggrlconfig->get_ecltaunn_nMLP();
178 m_parameters.multiplyHidden = m_db_trggrlconfig->get_ecltaunn_multiplyHidden();
179 m_parameters.nHidden = m_db_trggrlconfig->get_ecltaunn_nHidden();
180 m_parameters.nOutput = m_db_trggrlconfig->get_ecltaunn_nOutput();
181 m_parameters.n_cdc_sector = m_db_trggrlconfig->get_ecltaunn_n_cdc_sector();
182 m_parameters.n_ecl_sector = m_db_trggrlconfig->get_ecltaunn_n_ecl_sector();
183 m_parameters.i_cdc_sector = m_db_trggrlconfig->get_ecltaunn_i_cdc_sector();
184 m_parameters.i_ecl_sector = m_db_trggrlconfig->get_ecltaunn_i_ecl_sector();
185 m_parameters.nn_thres = m_db_trggrlconfig->get_ecltaunn_threshold();
186 m_parameters.total_bit_bias = m_db_trggrlconfig->get_ecltaunn_total_bit_bias();
187 m_parameters.int_bit_bias = m_db_trggrlconfig->get_ecltaunn_int_bit_bias();
188 m_parameters.is_signed_bias = m_db_trggrlconfig->get_ecltaunn_is_signed_bias();
189 m_parameters.rounding_bias = m_db_trggrlconfig->get_ecltaunn_rounding_bias();
190 m_parameters.saturation_bias = m_db_trggrlconfig->get_ecltaunn_saturation_bias();
191 m_parameters.total_bit_accum = m_db_trggrlconfig->get_ecltaunn_total_bit_accum();
192 m_parameters.int_bit_accum = m_db_trggrlconfig->get_ecltaunn_int_bit_accum();
193 m_parameters.is_signed_accum = m_db_trggrlconfig->get_ecltaunn_is_signed_accum();
194 m_parameters.rounding_accum = m_db_trggrlconfig->get_ecltaunn_rounding_accum();
195 m_parameters.saturation_accum = m_db_trggrlconfig->get_ecltaunn_saturation_accum();
196 m_parameters.total_bit_weight = m_db_trggrlconfig->get_ecltaunn_total_bit_weight();
197 m_parameters.int_bit_weight = m_db_trggrlconfig->get_ecltaunn_int_bit_weight();
198 m_parameters.is_signed_weight = m_db_trggrlconfig->get_ecltaunn_is_signed_weight();
199 m_parameters.rounding_weight = m_db_trggrlconfig->get_ecltaunn_rounding_weight();
200 m_parameters.saturation_weight = m_db_trggrlconfig->get_ecltaunn_saturation_weight();
201 m_parameters.total_bit_relu = m_db_trggrlconfig->get_ecltaunn_total_bit_relu();
202 m_parameters.int_bit_relu = m_db_trggrlconfig->get_ecltaunn_int_bit_relu();
203 m_parameters.is_signed_relu = m_db_trggrlconfig->get_ecltaunn_is_signed_relu();
204 m_parameters.rounding_relu = m_db_trggrlconfig->get_ecltaunn_rounding_relu();
205 m_parameters.saturation_relu = m_db_trggrlconfig->get_ecltaunn_saturation_relu();
206 m_parameters.total_bit = m_db_trggrlconfig->get_ecltaunn_total_bit();
207 m_parameters.int_bit = m_db_trggrlconfig->get_ecltaunn_int_bit();
208 m_parameters.is_signed = m_db_trggrlconfig->get_ecltaunn_is_signed();
209 m_parameters.rounding = m_db_trggrlconfig->get_ecltaunn_rounding();
210 m_parameters.saturation = m_db_trggrlconfig->get_ecltaunn_saturation();
211 m_parameters.W_input = m_db_trggrlconfig->get_ecltaunn_W_input();
212 m_parameters.I_input = m_db_trggrlconfig->get_ecltaunn_I_input();
213
214 B2INFO("DB GRLConfig: nMLP=" << m_db_trggrlconfig->get_ecltaunn_nMLP()
215 << " weight=" << m_db_trggrlconfig->get_ecltaunn_weight().size()
216 << " bias=" << m_db_trggrlconfig->get_ecltaunn_bias().size()
217 << " total_bit_bias=" << m_db_trggrlconfig->get_ecltaunn_total_bit_bias().size());
218
219
220 m_GRLNeuro.initialize(m_parameters);
221
222 for (unsigned int isector = 0; isector < m_parameters.nMLP; isector++) {
223 if (!m_GRLNeuro.load(isector, m_db_trggrlconfig->get_ecltaunn_weight()[isector], m_db_trggrlconfig->get_ecltaunn_bias()[isector])) {
224 B2ERROR("weight of GRL ecltaunn could not be loaded correctly.");
225 }
226 }
227 }
228 }
229
230 if (m_saveHist) {
231 for (unsigned int isector = 0; isector < m_parameters.nMLP; isector++) {
232 h_target.push_back(new TH1D(("h_target_" + to_string(isector)).c_str(),
233 ("h_target_" + to_string(isector)).c_str(), 100, -40.0, 40.0));
234 }
235 }
236}
237
239{
240
241 //StoreArray<TRGECLTrg> trgArray;
243 // if (!trgInfo.isValid()) {
244 // std::cout << "[WARNING] TRGGRLObjects not found in this event!" << std::endl;
245 // return;
246 // }
247
249 int necl = eclTrgClusterArray.getEntries();
250
251 std::vector<std::tuple<float, float, float, float, int>> eclClusters; // TC id
252 eclClusters.reserve(necl);
253
254 for (int ic = 0; ic < necl; ic++) {
255 auto* eclCluster = eclTrgClusterArray[ic];
256 int TC = eclCluster->getMaxTCId();
257
258 //float energy = eclCluster->getEnergyDep() ; // data
259 float energy = eclTrgClusterArray[ic]->getEnergyDep() * 1000.0;//MC
260 float time = eclCluster->getTimeAve();
261 float theta = TCThetaLab[TC - 1 ];
262 float phi = TCPhiLab[TC - 1 ] + 180;
263 float thetaComp = theta;
264
265 eclClusters.emplace_back(energy, thetaComp, phi, time, TC);
266
267 }
268
269
270 std::sort(eclClusters.begin(), eclClusters.end(),
271 [](const std::tuple<float, float, float, float, int>& a,
272 const std::tuple<float, float, float, float, int>& b) {
273 return std::get<0>(a) > std::get<0>(b);
274 });
275 // ====quantization
276 std::vector<float> MLPinput(24, 0.0f);
277 for (size_t i = 0; i < eclClusters.size() && i < 6; i++) {
278 float energy, theta, phi, time;
279 int TC;
280 std::tie(energy, theta, phi, time, TC) = eclClusters[i];
281 MLPinput[i] = energy;
282 MLPinput[i + 6] = theta;
283 MLPinput[i + 12] = phi;
284 MLPinput[i + 18] = time;
285 }
286
287
288 float LSB_ADC = 1 / 5.25;
289 float LSB_angle = 1 / 1.40625;
290 std::for_each(MLPinput.begin() + 0, MLPinput.begin() + 6, [LSB_ADC](float & x) { x = std::ceil(x * LSB_ADC); });
291 std::for_each(MLPinput.begin() + 6, MLPinput.begin() + 12, [LSB_angle](float & x) { x = std::ceil(x * LSB_angle); });
292 std::for_each(MLPinput.begin() + 12, MLPinput.begin() + 18, [LSB_angle](float & x) { x = std::ceil(x * LSB_angle); });
293
294 for (size_t i = 0; i < eclClusters.size() && i < 6; i++) {
295 float energy, theta, phi, time;
296 int TC;
297 std::tie(energy, theta, phi, time, TC) = eclClusters[i];
298
299 }
300
301 // Run MLP
302 for (unsigned int isector = 0; isector < m_parameters.nMLP; isector++) {
303 std::vector<float> target = m_GRLNeuro.runMLP(isector, MLPinput);
304 unsigned num_target = target.size();
305 std::vector<float> nn_thres = m_parameters.nn_thres[isector];
306
307 //if one of output exceed threshold, put true
308 bool target_output = false;
309 for (unsigned io = 0; io < num_target; io++) {
310 if (target[io] > nn_thres[io]) {
311 target_output = true;
312 break;
313 }
314 }
315 trgInfo->setTauNN(isector, target_output);
316 }
317}
318
319
320
321void
323{
324 if (m_saveHist) {
325 TFile* file = new TFile(TString(m_HistFileName), "recreate");
326 for (unsigned int isector = 0; isector < m_parameters.nMLP; isector++) {
327 h_target[isector]->Write();
328 }
329 file->Write();
330 file->Close();
331 }
332
333}
static std::string findFile(const std::string &path, bool silent=false)
Search for given file or directory in local or central release directory, and return absolute path if...
std::vector< double > TCThetaLab
Polar angle of a given TRGcluster.
DBObjPtr< TRGGRLConfig > m_db_trggrlconfig
dbobject to store grl config
std::vector< double > TCPhiLab
Azimuthal angle of a given TRGcluster.
std::string m_HistFileName
Name of root file to save the histogram.
virtual void initialize() override
Initialize the module.
std::string m_TrgECLClusterName
Name of the StoreArray containing the ECL clusters.
GRLNeuro m_GRLNeuro
Instance of the NeuroTrigger.
virtual void event() override
Called once for each event.
GRLNeuro::Parameters m_parameters
Parameters for the NeuroTrigger.
GRLNeuroModule()
Constructor, for setting module description and parameters.
virtual void terminate() override
This method is called at the end of the event processing.
virtual void beginRun() override
Register run-dependent DataStore arrays.
std::string m_TrgGrlInformationName
name of TRG GRL information object
bool m_saveHist
save the output histogram
std::vector< TH1D * > h_target
Histograms to save the NN classifiers.
bool m_useDB
save the ThetaPhi
Class to represent the GRL Neuro.
Definition GRLNeuro.h:34
void setDescription(const std::string &description)
Sets the description of the module.
Definition Module.cc:214
void setPropertyFlags(unsigned int propertyFlags)
Sets the flags for the module properties.
Definition Module.cc:208
Module()
Constructor.
Definition Module.cc:30
@ c_ParallelProcessingCertified
This module can be run in parallel processing mode safely (All I/O must be done through the data stor...
Definition Module.h:80
Accessor to arrays stored in the data store.
Definition StoreArray.h:113
int getEntries() const
Get the number of objects in the array.
Definition StoreArray.h:216
Type-safe access to single objects in the data store.
Definition StoreObjPtr.h:96
void addParam(const std::string &name, T &paramVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
Definition Module.h:559
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition Module.h:649
Abstract base class for different kinds of events.
STL namespace.