Belle II Software development
CDCTriggerNeuroIDHistModule.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 "trg/cdc/modules/neurotrigger/CDCTriggerNeuroIDHistModule.h"
10#include <framework/datastore/StoreArray.h>
11#include <mdst/dataobjects/MCParticle.h>
12#include <tracking/dataobjects/RecoTrack.h>
13#include <trg/cdc/dataobjects/CDCTriggerSegmentHit.h>
14#include <trg/cdc/dataobjects/CDCTriggerTrack.h>
15#include <framework/datastore/StoreObjPtr.h>
16#include <framework/dataobjects/EventMetaData.h>
17#include <framework/core/ModuleParam.templateDetails.h>
18
19#include <cdc/geometry/CDCGeometryPar.h>
20#include <framework/gearbox/Unit.h>
21
22#include <iostream>
23#include <fstream>
24#include <cmath>
25#include <TFile.h>
26#include "boost/iostreams/filter/gzip.hpp"
27#include "boost/iostreams/filtering_streambuf.hpp"
28#include "boost/iostreams/filtering_stream.hpp"
29#include "boost/multi_array.hpp"
30#define BOOST_MULTI_ARRAY_NO_GENERATORS
31
32namespace Belle2 {
38 REG_MODULE(CDCTriggerNeuroIDHist);
40 {
42 "description" //TODO
43 );
44 // parameters for saving / loading
45 addParam("hitCollectionName", m_hitCollectionName,
46 "Name of the input StoreArray of CDCTriggerSegmentHits.",
47 std::string(""));
48 addParam("inputCollectionName", m_inputCollectionName,
49 "Name of the StoreArray holding the 2D input tracks.",
50 std::string("TRGCDC2DFinderTracks"));
51 addParam("trainOnRecoTracks", m_trainOnRecoTracks,
52 "If true, use RecoTracks as targets instead of MCParticles.",
53 false);
54 addParam("targetCollectionName", m_targetCollectionName,
55 "Name of the MCParticle/RecoTrack collection used as target values.",
56 std::string("MCParticles"));
57 addParam("writeconfigfile", m_writeconfigFileName,
58 "Name of the config file, where all the parameters and the IDHist configuration is written.",
59 std::string(""));
60 addParam("configfile", m_configFileName,
61 "Name of the config file, where all the parameters and the IDHist configuration is read in from.",
62 std::string(""));
63 addParam("MaxEvents", m_nPrepare,
64 "amount of events used for creating the IDHist. If it is 0, "
65 "all Events are used.",
66 0);
67
68 }
69
70
72 {
78 if (m_configFileName != "") {
81 } else {
82 m_neuroParameters.saveconfigtxt("neuroconfig_example.conf");
83 B2ERROR("Configuration file is missing! Make sure to give the configuration file as a parameter. \
84 An example file neuroconfig_example.conf has been saved.");
85 }
86 m_trainSets_prepare.clear();
88 for (unsigned iMLP = 0; iMLP < m_NeuroTrigger.nSectors(); ++iMLP) {
89 // sectors means experts here; this is the old naming within the neurotrigger
90 // class which originates from times were we had different expert networks for
91 // different geometrical sectors. In future, this might come back because of
92 // the 3DFinder and its rough information about the theta angle of the tracks.
94 // layerid is the layer number where the priority hits are.
95 // for every 1st priority wire there is a corresponding track segment.
96 int layerId = 3;
97 for (int iSL = 0; iSL < 9; ++iSL) {
98
99 m_trainSets_prepare[iMLP].addCounters(cdc.nWiresInLayer(layerId));
100 // the first superlayer has 2 layers extra compared to the rest
101 layerId += (iSL > 0 ? 6 : 7);
102 }
106 targets.isRequired(m_targetCollectionName);
107 } else {
109 targets.isRequired(m_targetCollectionName);
110 }
111
112 m_NeuroTrigger.initializeCollections(m_hitCollectionName);
113
114
115
116
117 }
118 if (m_NeuroTrigger.nSectors() == 0) {
119 B2ERROR("No networks defined, please make sure to have a proper configuration file! Example file will be created here: ./neurotrigger_default.conf");
120 m_neuroParameters.saveconfigtxt("neurotrigger_default.conf");
121 }
122 }
123
124
125
126 void
128 {
129 StoreObjPtr<EventMetaData> evtmetadata;
130 for (int itrack = 0; itrack < m_tracks.getEntries(); ++itrack) {
131 // get related MCParticle/RecoTrack for target
132 // and retrieve track parameters
133
134 std::vector<float> targetvector = NeuroTrainer::getTrainTargets(m_trainOnRecoTracks, m_tracks[itrack], m_targetCollectionName);
135 if (targetvector[4] == 0) {
136 continue;
137 } // no valid representation found
138 // float phi0Target = targetvector[0]; // currently unused
139 // float invptTarget = targetvector[1]; // currently unused
140 float thetaTarget = targetvector[2];
141 float zTarget = targetvector[3];
142
143
144 // update 2D track variables
145 m_NeuroTrigger.updateTrack(*m_tracks[itrack]);
146
147 // find all matching sectors
148 float phi0 = m_tracks[itrack]->getPhi0();
149 float invpt = m_tracks[itrack]->getKappa(1.5);
150 float theta = atan2(1., m_tracks[itrack]->getCotTheta());
151 std::vector<int> sectors = m_NeuroTrigger.selectMLPsTrain(phi0, invpt, theta);
152 if (sectors.size() == 0) continue;
153 // get target values
154 std::vector<float> targetRaw = {};
155 if (m_neuroParameters.targetZ)
156 targetRaw.push_back(zTarget);
157 if (m_neuroParameters.targetTheta)
158 targetRaw.push_back(thetaTarget);
159 for (unsigned i = 0; i < sectors.size(); ++i) {
160 int isector = sectors[i];
161 std::vector<float> target = m_NeuroTrigger[isector].scaleTarget(targetRaw);
162 // skip out of range targets or rescale them
163 bool outOfRange = false;
164 for (unsigned itarget = 0; itarget < target.size(); ++itarget) {
165 if (fabs(target[itarget]) > 1.) {
166 outOfRange = true;
167 target[itarget] /= fabs(target[itarget]);
168 }
169 }
170 if (!m_neuroParameters.rescaleTarget && outOfRange) continue;
171 if (m_nPrepare == 0 || m_trainSets_prepare[isector].getTrackCounter() < m_nPrepare) {
172 // get relative ids for all hits related to the MCParticle / RecoTrack
173 // and count them to find relevant id range
174 // using only related hits suppresses background EXCEPT for curling tracks
176 RecoTrack* recoTrack =
177 m_tracks[itrack]->getRelatedTo<RecoTrack>(m_targetCollectionName);
178 for (const CDCTriggerSegmentHit& hit :
179 recoTrack->getRelationsTo<CDCTriggerSegmentHit>(m_hitCollectionName)) {
180 // get relative id
181 double relId = m_NeuroTrigger.getRelId(hit);
182 m_trainSets_prepare[isector].addHit(hit.getISuperLayer(), round(relId));
183 }
184 } else {
185 MCParticle* mcTrack =
186 m_tracks[itrack]->getRelatedTo<MCParticle>(m_targetCollectionName);
187 for (const CDCTriggerSegmentHit& hit :
188 mcTrack->getRelationsTo<CDCTriggerSegmentHit>(m_hitCollectionName)) {
189 // get relative id
190 double relId = m_NeuroTrigger.getRelId(hit);
191 m_trainSets_prepare[isector].addHit(hit.getISuperLayer(), round(relId));
192 }
193 }
194 m_trainSets_prepare[isector].countTrack();
195 }
196 }
197 }
198 bool stop = true;
199 for (unsigned isector = 0; isector < m_trainSets_prepare.size(); ++isector) {
200 if (m_nPrepare == 0 || m_trainSets_prepare[isector].getTrackCounter() < m_nPrepare) {
201 stop = false;
202 break;
203 }
204 }
205 if (stop) {
206 B2INFO("Training sample preparation for NeuroTrigger finished, stopping event loop.");
207 // if required hit number is reached, get relevant ids
208 StoreObjPtr<EventMetaData> eventMetaData;
209 eventMetaData->setEndOfData();
210 }
211 }
212
213 void
215 {
216
217 if (m_neuroParameters.IDRanges.size() > 0) {
218 if (m_neuroParameters.IDRanges[0].size() > 0) {
219 if (m_neuroParameters.IDRanges[0][0].isSet()) {
220 // the idranges are already set, print warning:
221 if (!m_neuroParameters.IDRanges[0][0].isLocked()) {
222 B2WARNING("ID ranges are already set in the config file, they will be updated now!");
223 } else {
224 B2ERROR("The ID ranges in the config file are already locked and cannot be updated!");
225 return;
226 }
227 }
228 }
229 }
230 m_neuroParameters.IDRanges.clear();
231 for (unsigned isector = 0; isector < m_trainSets_prepare.size(); ++isector) {
232 CDCTriggerMLPData::HeaderSet hset(isector, NeuroTrainer::getRelevantID(
233 m_trainSets_prepare[isector],
234 m_neuroParameters.cutSum,
235 m_neuroParameters.relevantCut));
236 std::vector<NNTParam<float>> expertline;
237 expertline.push_back(float(isector));
238 expertline.back().lock();
239 for (auto x : hset.relID) {
240 expertline.push_back(x);
241 expertline.back().lock();
242 }
243 m_neuroParameters.IDRanges.push_back(expertline);
244 B2DEBUG(15, hset);
245 }
246 // lock the variables used in this module, that are not supposed be changed
247 // further down the training chain because of the danger of implications or
248 // wrong assumptions.
249 m_neuroParameters.relevantCut.lock();
250 m_neuroParameters.cutSum.lock();
251 // the IDRanges are set here; however, they can be altered manually in the
252 // configuration file to achieve potentially better results, eg. widen
253 // the range of the axial phi acceptance. This is why they are not to be "locked".
254 m_neuroParameters.nInput.lock();
255 m_neuroParameters.nOutput.lock();
256 m_neuroParameters.nMLP.lock();
257 for (auto x : m_neuroParameters.SLpattern) {
258 x.lock();
259 }
260 for (auto x : m_neuroParameters.SLpatternMask) {
261 x.lock();
262 }
263 for (auto x : m_neuroParameters.maxHitsPerSL) {
264 x.lock();
265 }
266 m_neuroParameters.multiplyHidden.lock();
267
268 if (m_writeconfigFileName == "") {
269 m_neuroParameters.saveconfigtxt(m_configFileName);
270 } else {
272 }
273
274
275 // the *rangeTrain variables are used here, but just for obtaining the idranges.
276 // because they only have a very minor effect on those, they are not locked here.
277 //TODO: also write the config file to be directly able to start the training
278 }
279
281}
Struct for training data of a single MLP for the neuro trigger.
bool m_trainOnRecoTracks
Switch between MCParticles or RecoTracks as targets.
NeuroTriggerParameters m_neuroParameters
Parameters for the NeuroTrigger.
NeuroTrigger m_NeuroTrigger
Instance of the NeuroTrigger.
std::string m_targetCollectionName
Name of the MCParticles/RecoTracks collection used as target values.
std::string m_inputCollectionName
name of the event time StoreObjPtr
StoreArray< CDCTriggerTrack > m_tracks
List of input tracks.
std::vector< CDCTriggerMLPData > m_trainSets_prepare
dataset for all idhist prepare data
int m_nPrepare
Number of samples to prepare input ranges.
std::string m_writeconfigFileName
name for the output configuration file which holds all the parameters and the idhist tables for each ...
std::string m_configFileName
name for the input configuration file which holds all the parameters and the idhist tables for each e...
Combination of several CDCHits to a track segment hit for the trigger.
The Class for CDC Geometry Parameters.
static CDCGeometryPar & Instance(const CDCGeometry *=nullptr)
Static method to get a reference to the CDCGeometryPar instance.
A Class to store the Monte Carlo particle information.
Definition MCParticle.h:32
void setDescription(const std::string &description)
Sets the description of the module.
Definition Module.cc:214
Module()
Constructor.
Definition Module.cc:30
This is the Reconstruction Event-Data Model Track.
Definition RecoTrack.h:79
RelationVector< TO > getRelationsTo(const std::string &name="", const std::string &namedRelation="") const
Get the relations that point from this object to another store array.
Accessor to arrays stored in the data store.
Definition StoreArray.h:113
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
virtual void initialize() override
Initialize the module.
virtual void event() override
Called once for each event.
virtual void terminate() override
Do the training for all sectors.
CDCTriggerNeuroIDHistModule()
Constructor, for setting module description and parameters.
Abstract base class for different kinds of events.