Belle II Software development
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 addParam("outputScale", m_parameters.outputScale,
82 "Output scale for all networks (1 value list or nMLP value lists). "
83 "Output[i] of the MLP is scaled from [-1, 1] "
84 "to [outputScale[2*i], outputScale[2*i+1]]. "
85 "(units: z[cm] / theta[degree])",
86 {{ -1., 1., -1., 1., -1., 1., -1., 1., -1., 1., -1., 1., -1., 1., -1., 1., -1., 1., -1., 1.}});
87 addParam("csvThetaPhiFile", m_csvThetaPhiFile,
88 "CSV file for theta/phi correction per tcid.",
89 {FileSystem::findFile("/data/trg/grl/tcid_correct_theta_phi.csv", true)});
90
91 addParam("TRGECLClusters", m_TrgECLClusterName,
92 "Name of the StoreArray holding the information of trigger ecl clusters ",
93 string("TRGECLClusters"));
94 addParam("MVACut", m_nn_thres,
95 "Cut values applied to the 10 MLP outputs", {
96 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
97 });
98 addParam("useDB", m_useDB,
99 "Flag to use database to set config", true);
100
101 // // TRGGRLInfo must exist for this module
102 // addRequired<TRGGRLInfo>(m_TrgGrlInformationName);
103
104}
105
106
107void
109{
110
111 std::string csvPath = FileSystem::findFile(m_csvThetaPhiFile, true);
112 if (csvPath.empty()) {
113 B2ERROR("Cannot find tcid_correct_theta_phi.csv");
114 return;
115 }
116
117 std::ifstream infile(csvPath);
118 if (!infile.is_open()) {
119 B2ERROR(("Failed to open " + csvPath).c_str());
120 return;
121 }
122
123 std::string line;
124 bool isFirstLine = true;
125 while (std::getline(infile, line)) {
126 if (isFirstLine) {
127 isFirstLine = false;
128 continue;
129 }
130
131 std::stringstream ss(line);
132 std::string tc_str, theta_str, phi_str;
133 std::getline(ss, tc_str, ',');
134 std::getline(ss, theta_str, ',');
135 std::getline(ss, phi_str, ',');
136
137 if (tc_str.empty() || theta_str.empty() || phi_str.empty()) continue;
138
139 int tc = std::stoi(tc_str);
140 if (tc == 0) continue;
141 double theta = std::stod(theta_str) * TMath::RadToDeg();
142 double phi = std::stod(phi_str) * TMath::RadToDeg();
143
144 thetaMap[tc] = theta;
145 phiMap[tc] = phi;
146 }
147
148 infile.close();
149
150 TCThetaLab.clear();
151 TCPhiLab.clear();
152 TCThetaLab.reserve(576);
153 TCPhiLab.reserve(576);
154
155 for (int tc = 1; tc <= 576; ++tc) {
156 if (thetaMap.count(tc)) {
157 TCThetaLab.push_back(thetaMap[tc]);
158 TCPhiLab.push_back(phiMap[tc]);
159 } else {
160
161 TCThetaLab.push_back(0.0);
162 TCPhiLab.push_back(0.0);
163 }
164 }
165
166
167 B2INFO("Loaded TC geometry (theta/phi) from tcid_correct_theta_phi.csv");
168 B2INFO(Form("Example: TC 1 => theta = %.3f deg, phi = %.3f deg", TCThetaLab.at(0), TCPhiLab.at(0)));
169
170
171}
172
173
174void
176{
177 if (m_useDB) {
178 if (not m_db_trggrlconfig.isValid()) {
179 StoreObjPtr<EventMetaData> evtMetaData;
180 B2FATAL("No database for TRG GRL config. exp " << evtMetaData->getExperiment() << " run "
181 << evtMetaData->getRun());
182 } else {
183 m_parameters.nMLP = m_db_trggrlconfig->get_ecltaunn_nMLP();
184 m_parameters.multiplyHidden = m_db_trggrlconfig->get_ecltaunn_multiplyHidden();
185 m_parameters.nHidden = m_db_trggrlconfig->get_ecltaunn_nHidden();
186 m_parameters.nOutput = m_db_trggrlconfig->get_ecltaunn_nOutput();
187 m_parameters.n_cdc_sector = m_db_trggrlconfig->get_ecltaunn_n_cdc_sector();
188 m_parameters.n_ecl_sector = m_db_trggrlconfig->get_ecltaunn_n_ecl_sector();
189 m_parameters.i_cdc_sector = m_db_trggrlconfig->get_ecltaunn_i_cdc_sector();
190 m_parameters.i_ecl_sector = m_db_trggrlconfig->get_ecltaunn_i_ecl_sector();
191 m_nn_thres = m_db_trggrlconfig->get_ecltaunn_threshold();
192 m_parameters.total_bit_bias = m_db_trggrlconfig->get_ecltaunn_total_bit_bias();
193 m_parameters.int_bit_bias = m_db_trggrlconfig->get_ecltaunn_int_bit_bias();
194 m_parameters.is_signed_bias = m_db_trggrlconfig->get_ecltaunn_is_signed_bias();
195 m_parameters.rounding_bias = m_db_trggrlconfig->get_ecltaunn_rounding_bias();
196 m_parameters.saturation_bias = m_db_trggrlconfig->get_ecltaunn_saturation_bias();
197 m_parameters.total_bit_accum = m_db_trggrlconfig->get_ecltaunn_total_bit_accum();
198 m_parameters.int_bit_accum = m_db_trggrlconfig->get_ecltaunn_int_bit_accum();
199 m_parameters.is_signed_accum = m_db_trggrlconfig->get_ecltaunn_is_signed_accum();
200 m_parameters.rounding_accum = m_db_trggrlconfig->get_ecltaunn_rounding_accum();
201 m_parameters.saturation_accum = m_db_trggrlconfig->get_ecltaunn_saturation_accum();
202 m_parameters.total_bit_weight = m_db_trggrlconfig->get_ecltaunn_total_bit_weight();
203 m_parameters.int_bit_weight = m_db_trggrlconfig->get_ecltaunn_int_bit_weight();
204 m_parameters.is_signed_weight = m_db_trggrlconfig->get_ecltaunn_is_signed_weight();
205 m_parameters.rounding_weight = m_db_trggrlconfig->get_ecltaunn_rounding_weight();
206 m_parameters.saturation_weight = m_db_trggrlconfig->get_ecltaunn_saturation_weight();
207 m_parameters.total_bit_relu = m_db_trggrlconfig->get_ecltaunn_total_bit_relu();
208 m_parameters.int_bit_relu = m_db_trggrlconfig->get_ecltaunn_int_bit_relu();
209 m_parameters.is_signed_relu = m_db_trggrlconfig->get_ecltaunn_is_signed_relu();
210 m_parameters.rounding_relu = m_db_trggrlconfig->get_ecltaunn_rounding_relu();
211 m_parameters.saturation_relu = m_db_trggrlconfig->get_ecltaunn_saturation_relu();
212 m_parameters.total_bit = m_db_trggrlconfig->get_ecltaunn_total_bit();
213 m_parameters.int_bit = m_db_trggrlconfig->get_ecltaunn_int_bit();
214 m_parameters.is_signed = m_db_trggrlconfig->get_ecltaunn_is_signed();
215 m_parameters.rounding = m_db_trggrlconfig->get_ecltaunn_rounding();
216 m_parameters.saturation = m_db_trggrlconfig->get_ecltaunn_saturation();
217 m_parameters.W_input = m_db_trggrlconfig->get_ecltaunn_W_input();
218 m_parameters.I_input = m_db_trggrlconfig->get_ecltaunn_I_input();
219 // Wrap 2D database values into 3D for Parameters (nMLP x layer x input)
220 m_parameters.W_input_layer = { m_db_trggrlconfig->get_ecltaunn_W_input_layer() };
221 m_parameters.I_input_layer = { m_db_trggrlconfig->get_ecltaunn_I_input_layer() };
222
223 B2INFO("DB GRLConfig: nMLP=" << m_db_trggrlconfig->get_ecltaunn_nMLP()
224 << " weight=" << m_db_trggrlconfig->get_ecltaunn_weight().size()
225 << " bias=" << m_db_trggrlconfig->get_ecltaunn_bias().size()
226 << " total_bit_bias=" << m_db_trggrlconfig->get_ecltaunn_total_bit_bias().size());
227
228
229 m_GRLNeuro.initialize(m_parameters);
230
231 for (unsigned int isector = 0; isector < m_parameters.nMLP; isector++) {
232 if (!m_GRLNeuro.load(isector, m_db_trggrlconfig->get_ecltaunn_weight().at(isector),
233 m_db_trggrlconfig->get_ecltaunn_bias().at(isector))) {
234 B2ERROR("weight of GRL ecltaunn could not be loaded correctly.");
235 }
236 }
237 }
238 }
239
240 if (m_saveHist) {
241 for (unsigned int isector = 0; isector < m_parameters.nMLP; isector++) {
242 h_target.push_back(new TH1D(("h_target_" + to_string(isector)).c_str(),
243 ("h_target_" + to_string(isector)).c_str(), 100, -40.0, 40.0));
244 }
245 }
246}
247
249{
250
251 //StoreArray<TRGECLTrg> trgArray;
253 // if (!trgInfo.isValid()) {
254 // std::cout << "[WARNING] TRGGRLObjects not found in this event!" << std::endl;
255 // return;
256 // }
257
259 int necl = eclTrgClusterArray.getEntries();
260
261 std::vector<std::tuple<float, float, float, float, int>> eclClusters; // TC id
262 eclClusters.reserve(necl);
263
264 for (int ic = 0; ic < necl; ic++) {
265 auto* eclCluster = eclTrgClusterArray[ic];
266 int TC = eclCluster->getMaxTCId();
267
268 //float energy = eclCluster->getEnergyDep() ; // data
269 float energy = eclTrgClusterArray[ic]->getEnergyDep() * 1000.0;//MC
270 float time = eclCluster->getTimeAve();
271 float theta = TCThetaLab.at(TC - 1);
272 float phi = TCPhiLab.at(TC - 1) + 180;
273 float thetaComp = theta;
274
275 eclClusters.emplace_back(energy, thetaComp, phi, time, TC);
276
277 }
278
279
280 std::sort(eclClusters.begin(), eclClusters.end(),
281 [](const std::tuple<float, float, float, float, int>& a,
282 const std::tuple<float, float, float, float, int>& b) {
283 return std::get<0>(a) > std::get<0>(b);
284 });
285 // ====quantization
286 std::vector<float> MLPinput(24, 0.0f);
287 for (size_t i = 0; i < eclClusters.size() && i < 6; i++) {
288 float energy, theta, phi, time;
289 int TC;
290 std::tie(energy, theta, phi, time, TC) = eclClusters.at(i);
291 MLPinput.at(i) = energy;
292 MLPinput.at(i + 6) = theta;
293 MLPinput.at(i + 12) = phi;
294 MLPinput.at(i + 18) = time;
295 }
296
297
298 float LSB_ADC = 1 / 5.25;
299 float LSB_angle = 1 / 1.40625;
300 std::for_each(MLPinput.begin() + 0, MLPinput.begin() + 6, [LSB_ADC](float & x) { x = std::ceil(x * LSB_ADC); });
301 std::for_each(MLPinput.begin() + 6, MLPinput.begin() + 12, [LSB_angle](float & x) { x = std::ceil(x * LSB_angle); });
302 std::for_each(MLPinput.begin() + 12, MLPinput.begin() + 18, [LSB_angle](float & x) { x = std::ceil(x * LSB_angle); });
303
304 // Run MLP - returns 10 outputs
305 std::vector<float> outputs = m_GRLNeuro.runMLP(0, MLPinput);
306 if (m_saveHist) {
307 for (int i = 0; i < 10; i++) {
308 h_target.at(0)->Fill(outputs.at(i));
309 }
310 }
311 bool tauNN = false;
312 for (int i = 0; i < 10 && i < (int)m_nn_thres.size(); i++) {
313 if (outputs.at(i) > m_nn_thres.at(i)) {
314 tauNN = true;
315 break;
316 }
317 }
318 trgInfo->setTauNN(tauNN);
319}
320
321
322
323void
325{
326 if (m_saveHist) {
327 TFile* file = new TFile(TString(m_HistFileName), "recreate");
328 for (unsigned int isector = 0; isector < m_parameters.nMLP; isector++) {
329 h_target.at(isector)->Write();
330 }
331 file->Write();
332 file->Close();
333 }
334
335}
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< float > m_nn_thres
cut on MVA to separate signal
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.