Belle II Software development
SectorMapBootstrapModule.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 <iostream>
10
11#include <tracking/trackFindingVXD/filterMap/map/FiltersContainer.h>
12#include "tracking/trackFindingVXD/environment/VXDTFFilters.h"
13#include "tracking/modules/vxdtfRedesign/SectorMapBootstrapModule.h"
14//#include "tracking/dataobjects/VXDTFSecMap.h"
15#include "tracking/dataobjects/SectorMapConfig.h"
16#include <tracking/spacePointCreation/SpacePoint.h>
17
18// needed for complicated parameter types to not get an undefined reference error
19#include <framework/core/ModuleParam.templateDetails.h>
20
21#include <vxd/geometry/GeoCache.h>
22#include <vxd/geometry/SensorInfoBase.h>
23
24#include <TString.h>
25#include <TFile.h>
26#include <TTree.h>
27
28#include <algorithm>
29#include <fstream>
30
31
32using namespace Belle2;
33
34REG_MODULE(SectorMapBootstrap);
35
37{
38
40
41 setDescription("Create the VXDTF SectorMap for the following modules."
42 );
43
44 addParam("SectorMapsInputFile", m_sectorMapsInputFile,
45 "File from which the SectorMaps will be retrieved if\
46 ReadSectorMap is set to true", m_sectorMapsInputFile);
47
48 addParam("SectorMapsOutputFile", m_sectorMapsOutputFile,
49 "File into which the SectorMaps will be written if\
50 WriteSectorMap is set to true", m_sectorMapsOutputFile);
51
52 addParam("ReadSectorMap", m_readSectorMap, "If set to true \
53retrieve the SectorMaps from SectorMapsInputFile during initialize.", m_readSectorMap);
54
55 addParam("WriteSectorMap", m_writeSectorMap, "If set to true \
56at endRun write the SectorMaps to SectorMapsOutputFile.", m_writeSectorMap);
57
58 addParam("SetupToRead", m_setupToRead, "If non empty only the setup with the given name will be read"
59 " from the from the root file. All other will be ignored. If empty \"\" (default) all setups are read. Will "
60 "only used if sectormap is retrieved from root file. Case will be ignored!",
61 std::string(""));
62
63 addParam("ReadSecMapFromDB", m_readSecMapFromDB, "If set to true the sector map will be read from the Data Base. NOTE: this will "
64 "override the parameter ReadSectorMap (reading sector map from file)!!!", m_readSecMapFromDB);
65
66
67 // dummy vector needed to get the current structure of the filter
68 std::vector< std::pair<char, void*> > dummyVector = {};
69
71 // the structure is the same for all specializations of the template
72 std::string structure2HitFilter = empty2HitFilter.getNameAndReference(&dummyVector);
73 dummyVector.clear();
74 addParam("twoHitFilterAdjustFunctions", m_twoHitFilterAdjustFunctions,
75 "Vector of vectors containing expressions used to "
76 "alter the 2-hit filters. The inner vector should contain exactly two strings. The first entry is interpreted as index (integer). "
77 "The second entry is interpreted as function used to create a TF1. The variable to be altered will be assumed to be called \"x\" "
78 "and in addition one can use \"[0]\" can be used which will be interpreted as FullSecID of the static sector the filter is attached to. "
79 "No other parameter is allowed. The structure of the 2-hit filter is as follows: " + structure2HitFilter +
80 " Example: [(1, \"12\"), (3, \"sin(x)\"), (4, \"x + [0]\")] PS: use this feature only if you know what you are doing!",
82
84 // the structure is the same for all specializations of the template
85 std::string structure3HitFilter = empty3HitFilter.getNameAndReference(&dummyVector);
86 dummyVector.clear();
87 addParam("threeHitFilterAdjustFunctions", m_threeHitFilterAdjustFunctions,
88 "Vector of vectors containing expressions used to "
89 "alter the 3-hit filters. The inner vector should contain exactly two strings. The first entry is interpreted as index (integer). "
90 "The second entry is interpreted as function used to create a TF1. The variable to be altered will be assumed to be called \"x\" "
91 "and in addition \"[0]\" can be used which will be interpreted as FullSecID of the static sector the filter is attached to. No other "
92 "parameter is allowed. The structure of the 2-hit filter is as follows: " + structure3HitFilter +
93 " Example: [(1, \"12\"), (3, \"sin(x)\"), (4, \"x + [0]\")] PS: use this feature only if you know what you are doing!",
95}
96
97void
99{
100
101 // in case sector map is read from the DB one needs to set the DB pointer
102 if (m_readSecMapFromDB) {
103 B2DEBUG(29, "SectorMapBootstrapModule: Retrieving sectormap from DB. Filename: " << m_sectorMapsInputFile);
105 if (m_ptrDBObjPtr == nullptr) B2FATAL("SectorMapBootstrapModule: the DBObjPtr is not initialized");
106 // add a callback function so that the sectormap is updated each time the DBObj changes
108 }
109 // retrieve the SectorMap or create an empty one
112 else
114
115 // security measurement: test if output file exists so that existing sector maps are not overwritten
116 if (m_writeSectorMap) {
117 if (std::ifstream(m_sectorMapsOutputFile.c_str())) {
118 B2FATAL("Detected existing output file! Please delete or move before proceeding! File name: " << m_sectorMapsOutputFile);
119 } else {
120 B2DEBUG(29, "Checked that output file does not exist!");
121 }
122 }
123
124
125
126}
127
128
129
130
131void
133{
134
135
136 // TODO: Most of the information is not used at all.
137 // It seems to me (EP) that only the SectorDividers are used.
138
139 // TODO: find a better way to put the configs into the framework
140
141 // WARNING: chose the names of the configs in that way that they are not contained in each other!
142 // E.g. having two configs with names "BobTheGreat" and "Bob" is not allowed as it will cause problems in some modules!
143
144
145 // for now declare this as default config for SVD only tracking!
146 SectorMapConfig config1;
147// config1.pTmin = 0.02;
148// config1.pTmax = 0.08;
149 config1.pTmin = 0.02; // minimal relevant version
150 config1.pTmax = 6.0; // minimal relevant version // Feb18-onePass-Test
151 config1.pTSmear = 0.;
152 config1.allowedLayers = {0, 3, 4, 5, 6};
153// config1.uSectorDivider = { .15, .5, .85, 1.};
154// config1.vSectorDivider = { .1, .3, .5, .7, .9, 1.};
155 config1.uSectorDivider = {.25, .5, .75, 1.}; // standard relevant version
156 config1.vSectorDivider = {.25, .5, .75, 1.}; // standard relevant version
157// config1.uSectorDivider = { .5, 1.}; // small relevant version
158// config1.vSectorDivider = { .5, 1.}; // small relevant version
159// config1.uSectorDivider = { 1.}; // minimal relevant version
160// config1.vSectorDivider = { 1.}; // minimal relevant version
161 config1.pdgCodesAllowed = {};
162 config1.seedMaxDist2IPXY = 23.5;
163 config1.seedMaxDist2IPZ = 23.5;
164 config1.nHitsMin = 3;
165 config1.vIP = B2Vector3D(0, 0, 0);
166 config1.secMapName = "SVDOnlyDefault"; // has been: "lowTestRedesign";
167 config1.mField = 1.5;
168 config1.rarenessThreshold = 0.; //0.001;
169 config1.quantiles = {0., 1.}; //{0.005, 1. - 0.005};
170 // TODO: still missing: minimal sample-size, quantiles for smaller samplesizes, threshshold small <-> big sampleSize.
171 bootstrapSectorMap(config1);
172
173
174 // 11th Oct. 2023: removed to prevent that corresponding training samples are generated. Still want to keep it to not forget how it is done.
175 /*
176 // same as config1 but allows the PXD layers
177 // default for VXD tracking (SVD+PXD)
178 SectorMapConfig config1point1;
179 config1point1.pTmin = 0.02; // minimal relevant version
180 config1point1.pTmax = 6.0; // minimal relevant version // Feb18-onePass-Test
181 config1point1.pTSmear = 0.;
182 config1point1.allowedLayers = {0, 1, 2, 3, 4, 5, 6};
183 config1point1.uSectorDivider = { .3, .7, 1.}; // standard relevant version
184 config1point1.vSectorDivider = { .3, .7, 1.}; // standard relevant version
185 config1point1.pdgCodesAllowed = {};
186 config1point1.seedMaxDist2IPXY = 23.5;
187 config1point1.seedMaxDist2IPZ = 23.5;
188 config1point1.nHitsMin = 3;
189 config1point1.vIP = B2Vector3D(0, 0, 0);
190 config1point1.secMapName = "SVDPXDDefault"; // has been: "lowTestSVDPXD";
191 config1point1.mField = 1.5;
192 config1point1.rarenessThreshold = 0.; //0.001;
193 config1point1.quantiles = {0., 1.}; //{0.005, 1. - 0.005};
194 bootstrapSectorMap(config1point1);
195 */
196}
197
198void
204
205void
207{
208
209 // TODO: change naming! This is poor naming as these include also Triplet filters!
211 segmentFilters->setConfig(config);
212
213 // TO DO: The whole information must be retrieved from the geometry
214
215 std::vector< double > uDividersMinusLastOne = config.uSectorDivider;
216 uDividersMinusLastOne.pop_back();
217 std::vector< double > vDividersMinusLastOne = config.vSectorDivider;
218 vDividersMinusLastOne.pop_back();
219
220
221 std::vector< std::vector< FullSecID > > sectors;
222
223 sectors.resize(config.uSectorDivider.size());
224 unsigned nSectorsInU = config.uSectorDivider.size(),
225 nSectorsInV = config.vSectorDivider.size();
226
227 // retrieve the full list of sensors from the geometry
229 std::vector<VxdID> listOfSensors = geometry.getListOfSensors();
230 for (VxdID aSensorId : listOfSensors) {
231
232 // filter only those sensors on layers which are specified in the config
233 if (std::find(config.allowedLayers.begin(), config.allowedLayers.end(),
234 aSensorId.getLayerNumber()) == config.allowedLayers.end()) continue;
235
236 // for testbeams there might be other sensors in the geometry so filter for SVD and PXD only, as the CompactSecID dont like those!
237 VXD::SensorInfoBase::SensorType type = geometry.getSensorInfo(aSensorId).getType();
238 if (type != VXD::SensorInfoBase::SVD && type != VXD::SensorInfoBase::PXD) {
239 B2WARNING("Found sensor which is not PXD or SVD with VxdID: " << aSensorId << " ! Will skip that sensor ");
240 continue;
241 }
242
243 int counter = 0;
244 for (unsigned int i = 0; i < nSectorsInU; i++) {
245 sectors.at(i).resize(nSectorsInV);
246 for (unsigned int j = 0; j < nSectorsInV ; j++) {
247 sectors.at(i).at(j) = FullSecID(aSensorId, false, counter);
248 counter ++;
249 }
250 }
251 segmentFilters->addSectorsOnSensor(uDividersMinusLastOne,
252 vDividersMinusLastOne,
253 sectors) ;
254 }//end loop over sensors
255
256
257 // if layer 0 is specified in the config then the virtual IP is added
258 if (std::find(config.allowedLayers.begin(), config.allowedLayers.end(), 0) != config.allowedLayers.end()) {
259 std::vector<double> uCuts4vIP = {}, vCuts4vIP = {};
260 sectors.clear();
261 sectors = {{ FullSecID(0) }};
262 segmentFilters->addSectorsOnSensor(uCuts4vIP, vCuts4vIP, sectors);
263 }
264
265 // put config into the container
266 FiltersContainer<SpacePoint>::getInstance().assignFilters(config.secMapName, segmentFilters);
267
268}
269
270
272void
274{
275
276 // the "CREATE" option results in the root file not being opened if it already exists (to prevent overwriting existing sectormaps)
277 TFile rootFile(m_sectorMapsOutputFile.c_str(), "CREATE");
278 if (!rootFile.IsOpen()) B2FATAL("Unable to open rootfile! This could be caused by an already existing file of the same name: "
279 << m_sectorMapsOutputFile.c_str());
280
281 TTree* tree = new TTree(c_setupKeyNameTTreeName.c_str(),
283
284 TString setupKeyName;
285
286 tree->Branch(c_setupKeyNameBranchName.c_str(),
287 & setupKeyName);
288
290 for (auto singleSetupFilters : allSetupsFilters) {
291
292 setupKeyName = TString(singleSetupFilters.first.c_str());
293
294 tree->Fill();
295
296 rootFile.mkdir(setupKeyName, setupKeyName);
297 rootFile.cd(setupKeyName);
298
299 singleSetupFilters.second->persistOnRootFile();
300
301 rootFile.cd("..");
302
303 }
304
305 rootFile.Write();
306 rootFile.Close();
307
308
309}
310
311
313void
315{
316
317 std::string rootFileName = m_sectorMapsInputFile;
318 // if reading from the DB get the root file name from the DB object ptr
319 if (m_readSecMapFromDB) {
320 if (m_ptrDBObjPtr == nullptr) B2FATAL("SectorMapBootstrapModule: the pointer to the DB payload is not set!");
321 if (!(*m_ptrDBObjPtr).isValid()) B2FATAL("SectorMapBootstrapModule the DB object is not valid!");
322
323 rootFileName = (*m_ptrDBObjPtr)->getFileName();
324 }
325
326 B2DEBUG(29, "SectorMapBootstrapModule: retrieving new SectorMap. New file name: " << rootFileName);
327 TFile rootFile(rootFileName.c_str());
328
329 // some cross check that the file is open
330 if (!rootFile.IsOpen()) B2FATAL("The root file: " << rootFileName << " was not found.");
331
332 TTree* tree = nullptr;
333 rootFile.GetObject(c_setupKeyNameTTreeName.c_str(), tree);
334 if (tree == nullptr) B2FATAL("SectorMapBootstrapModule: tree not found! tree name: " << c_setupKeyNameTTreeName.c_str());
335
336 TString* setupKeyName = nullptr;
337 tree->SetBranchAddress(c_setupKeyNameBranchName.c_str(),
338 & setupKeyName);
339 if (setupKeyName == nullptr) B2FATAL("SectorMapBootstrapModule: setupKeyName not found");
340
341 // ignore case, so only upper case
342 TString setupToRead_upper = m_setupToRead;
343 setupToRead_upper.ToUpper();
344
345 // to monitor if anything was read from the root files
346 bool read_something = false;
347
349 auto nEntries = tree->GetEntriesFast();
350 for (int i = 0; i < nEntries ; i++) {
351 tree->GetEntry(i);
352
353 // if a setup name is specified only read that one
354 if (setupToRead_upper != "") {
355 TString buff = setupKeyName->Data();
356 buff.ToUpper();
357 if (buff != setupToRead_upper) continue;
358 }
359
360 rootFile.cd(setupKeyName->Data());
361
362 B2DEBUG(29, "Retrieving SectorMap with name " << setupKeyName->Data());
363
365
366 std::string setupKeyNameStd = std::string(setupKeyName->Data());
367 segmentFilters->retrieveFromRootFile(setupKeyName);
368
369 // if the m_twoHitFilterAdjustFunctions m_threeHitFilterAdjustFunctions are non empty filters will be altered
370 if (m_twoHitFilterAdjustFunctions.size() > 0) {
371 B2WARNING("The 2-hit filters will be altered from the default!");
372 B2INFO("The following set of indizes and functions will be used to alter the 2-hit filters:");
373 for (auto& entry : m_twoHitFilterAdjustFunctions) {
374 B2INFO("index=" << std::get<0>(entry) << " function=" << std::get<1>(entry));
375 }
377 }
378 if (m_threeHitFilterAdjustFunctions.size() > 0) {
379 B2WARNING("The 3-hit filters will be altered from the default!");
380 B2INFO("The following set of indizes and functions will be used to alter the 3-hit filters:");
381 for (auto& entry : m_threeHitFilterAdjustFunctions) {
382 B2INFO("index=" << std::get<0>(entry) << " function=" << std::get<1>(entry));
383 }
385 }
386
387 // locks all functions that can modify the filters
388 segmentFilters->lockFilters();
389
390 B2DEBUG(29, "Retrieved map with name: " << setupKeyNameStd << " from rootfie.");
391 filtersContainer.assignFilters(setupKeyNameStd, segmentFilters);
392
393 rootFile.cd("..");
394
395 setupKeyName->Clear();
396
397 read_something = true;
398 }
399
400 if (!read_something) B2FATAL("SectorMapBootstrapModule: No setup was read from the root file! " <<
401 "The requested setup name was: " << m_setupToRead);
402
403 rootFile.Close();
404
405 // delete the TString which was allocated by ROOT but not cleaned up
406 if (setupKeyName != nullptr) {
407 delete setupKeyName;
408 }
409
410}
411
412
Class for accessing objects in the database.
Definition DBObjPtr.h:21
This class contains everything needed by the VXDTF that is not going to change during a RUN,...
static FiltersContainer & getInstance()
one and only way to access the singleton object
void assignFilters(const std::string &setupName, VXDTFFilters< point_t > *filters)
assigns filters.
const setupNameToFilters_t & getAllSetups(void)
returns all the available setups.
Class to identify a sector inside of the VXD.
Definition FullSecID.h:33
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
bool m_readSecMapFromDB
if true the sector map will be read from the DB. NOTE: this will override m_readSectorMap (read from ...
std::string m_sectorMapsInputFile
the name of the input root file the sectormaps are read from
void endRun() override
This method is called if the current run ends.
std::vector< std::tuple< int, std::string > > m_twoHitFilterAdjustFunctions
vector of tuple<int, string> specifying how 2-hit filters are altered.
static void bootstrapSectorMap(void)
puts several empty sectormaps into the framework
bool m_readSectorMap
if true a sectormap will be read from a file. NOTE: this will be overridden by m_readSecMapFromDB!
DBObjPtr< PayloadFile > * m_ptrDBObjPtr
pointer to the DBObjPtr for the payloadfile from which the sectormap is read
const std::string c_setupKeyNameBranchName
the name of the branch the setupt are stored in the tree
std::vector< std::tuple< int, std::string > > m_threeHitFilterAdjustFunctions
vector of tuple<int, string> specifying how 3-hit filters are altered.
const std::string c_setupKeyNameTTreeName
the name of the tree the setups are stored in in the root file
std::string m_setupToRead
if specified (non "") ONLY the setup with this name will be read. Else all setups in the root file wi...
std::string m_sectorMapsOutputFile
the name of the output root file the sectormaps are written to
void persistSectorMap(void)
writes a sectormap to a root file
void retrieveSectorMap(void)
retrieves SectorMap from file or from the DB
bool m_writeSectorMap
if true the sectormap will be written to an output file
Class that contains all the static sectors to which the filters are attached.
int addSectorsOnSensor(const std::vector< double > &normalizedUsup, const std::vector< double > &normalizedVsup, const std::vector< std::vector< FullSecID > > &sectorIds)
To add an array of sectors on a sensor.
bool retrieveFromRootFile(const TString *dirName)
Retrieves from the current TDirectory all the VXDTFFilters.
decltype((0.<=DistanceInTimeUside< point_t >()<=0. &&0.<=DistanceInTimeVside< point_t >()<=0. &&0.<=Distance3DSquared< point_t >()<=0.&&0.<=Distance2DXYSquared< point_t >()<=0.&&0.<=Distance1DZ< point_t >()<=0.&&0.<=SlopeRZ< point_t >()<=0.&&0.<=Distance3DNormed< point_t >()<=0.)) twoHitFilter_t
minimal working 2-hits-example used for redesign of VXDTF.
void modify2SPFilters(const std::vector< std::tuple< int, std::string > > &adjustFunctions)
modifies the 2SP-filters according to the functions given
void lockFilters()
This function should be called only AFTER all adjustments to the filters have been performed.
void setConfig(const SectorMapConfig &config)
set the configuration which is used to create this filter
decltype((0.<=DistanceInTime< point_t >()<=0. &&0.<=Angle3DSimple< point_t >()<=0.&&0.<=CosAngleXY< point_t >()<=0.&&0.<=AngleRZSimple< point_t >()<=0.&&CircleDist2IP< point_t >()<=0.&&0.<=DeltaSlopeRZ< point_t >()<=0.&&0.<=DeltaSlopeZoverS< point_t >()<=0.&&0.<=DeltaSoverZ< point_t >()<=0.&&0.<=HelixParameterFit< point_t >()<=0.&&0.<=Pt< point_t >()<=0.&&0.<=CircleRadius< point_t >()<=0.)) threeHitFilter_t
minimal working example for 3-hits:
void modify3SPFilters(const std::vector< std::tuple< int, std::string > > &adjustFunctions)
modifies the 3SP-filters according to the functions given
Class to facilitate easy access to sensor information of the VXD like coordinate transformations or p...
Definition GeoCache.h:38
static GeoCache & getInstance()
Return a reference to the singleton instance.
Definition GeoCache.cc:214
SensorType
Enum specifying the type of sensor the SensorInfo represents.
Class to uniquely identify a any structure of the PXD and SVD.
Definition VxdID.h:32
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
B2Vector3< double > B2Vector3D
typedef for common usage with double
Definition B2Vector3.h:522
Common code concerning the geometry representation of the detector.
Definition CreatorBase.h:25
Abstract base class for different kinds of events.
simple struct containing all the configuration data needed for the SecMapTrainer.
double pTmin
stores pTCuts for min pT allowed for this .
std::vector< double > vSectorDivider
Defines the sectors boundaries in normalized v coordinates (i.e.
double pTSmear
allows smearing of the cuts.
std::vector< int > pdgCodesAllowed
Stores all the pdgCodes which are allowed to be used by the SecMap.
double mField
Magnetic field value to be set for the filters.
double seedMaxDist2IPXY
Stores a cut for maximum distance of the seed in xy of the given virtual IP.
std::pair< double, double > quantiles
the quantiles to be chosen in the end for determining the cuts first is quantile, second is 1-quantil...
std::vector< double > uSectorDivider
Defines the sectors boundaries in normalized u coordinates (i.e.
double rarenessThreshold
defined 1 == 100%, if relative frequency of sec-combi to the outer-sector is less than threshold,...
std::string secMapName
Sets the human readable proto-name of the sectorMap.
B2Vector3D vIP
Stores the position of the assumed position of the interaction point - The virtual IP.
double seedMaxDist2IPZ
Stores a cut for maximum distance of the seed in z of the given virtual IP.
double pTmax
stores pTCuts for min (.first) and max (.second) ptCut.
unsigned nHitsMin
Stores the minimal number of hits a TC must have to be accepted as TC (vIP-Hits are ignored).
std::vector< int > allowedLayers
stores allowed layers to be used (including virtual IP with layer 0).