Belle II Software development
SectorMapTrainingUtils.py
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3
4
11
12'''
13This file contains several utility functions used during the SectorMapTraining.
14'''
15
16from simulation import add_simulation
17from pxd import add_pxd_reconstruction
18from svd import add_svd_reconstruction
19from beamparameters import add_beamparameters
20import basf2 as b2
21import random
22from ROOT import Belle2
23from generators import add_babayaganlo_generator
24
25
26def add_event_generation(path, randomSeed, eventType, expNumber):
27 ''' Adds the event generator and needed modules to the path. The IP is randomized so a random seed has to be provided.
28 @param path: the path the modules will be added to
29 @param randomSeed: a random seed to set up the random generator which randomizes the IP position.
30 @param eventType: the allowed event types are
31 "BBbar" which will generate BBbar events plus extra ParticleGun tracks.
32 "BhaBha" which will generate radiative BhaBha events
33 @param expNumber: the experiment number 0 or 1004 for full geometry, 1003 for partial PXD geometry (early phase 3).
34 For training SVD only SectorMaps this setting does not matter, as SVD does not change between exp 0, 1004 and 1003.
35 '''
36 if (expNumber not in (0, 1003, 1004)):
37 b2.B2FATAL("Specified experiment experiment number " + str(expNumber) + " not valid! Allowed numbers are 0, 1003, 1004.")
38
39 # set the exp number
40 eventinfosetter = b2.register_module('EventInfoSetter')
41 eventinfosetter.param("expList", [expNumber])
42 path.add_module(eventinfosetter)
43
44 # get some debugging output
45 eventinfoprinter = b2.register_module('EventInfoPrinter')
46 path.add_module(eventinfoprinter)
47
48 # randomize the vertex position (flatly distributed) to make the sectormap more robust wrt. changing beam position
49 # minima and maxima of the beam position given in cm
50 random.seed(randomSeed)
51 vertex_x_min = -0.1
52 vertex_x_max = 0.1
53 vertex_y_min = -0.1
54 vertex_y_max = 0.1
55 vertex_z_min = -0.5
56 vertex_z_max = 0.5
57
58 vertex_x = random.uniform(vertex_x_min, vertex_x_max)
59 vertex_y = random.uniform(vertex_y_min, vertex_y_max)
60 vertex_z = random.uniform(vertex_z_min, vertex_z_max)
61
62 b2.B2WARNING("Setting non-default beam vertex at x= " + str(vertex_x) + " y= " + str(vertex_y) + " z= " + str(vertex_z))
63
64 # Beam parameters
65 beamparameters = add_beamparameters(path, "Y4S")
66 beamparameters.param("vertex", [vertex_x, vertex_y, vertex_z])
67
68 # additional flatly smear the muon vertex between +/- this value
69 vertex_delta = 0.005 # in cm
70
71 # Particle Gun:
72 # One can add more particle gun modules if wanted.
73 # allways put the particle gun
74 particlegun = b2.register_module('ParticleGun')
75 particlegun.logging.log_level = b2.LogLevel.WARNING
76 param_pGun = {
77 'pdgCodes': [13, -13], # 13 = muon --> negatively charged!
78 'nTracks': 2,
79 'momentumGeneration': 'uniform',
80 'momentumParams': [0.05, 4],
81 'vertexGeneration': 'uniform',
82 'xVertexParams': [vertex_x - vertex_delta, vertex_x + vertex_delta], # in cm...
83 'yVertexParams': [vertex_y - vertex_delta, vertex_y + vertex_delta],
84 'zVertexParams': [vertex_z - vertex_delta, vertex_z + vertex_delta]
85 }
86 particlegun.param(param_pGun)
87 path.add_module(particlegun)
88
89 # adding event generators according to settings
90 if eventType == "BBbar":
91 # EvtGen Simulation:
92 evtgenInput = b2.register_module('EvtGenInput')
93 evtgenInput.logging.log_level = b2.LogLevel.WARNING
94 path.add_module(evtgenInput)
95 elif eventType == "BhaBha":
96 # generate some Bhabha
97 add_babayaganlo_generator(path=path, finalstate='ee')
98 else:
99 b2.B2FATAL("eventType: " + eventType + " is not recognized")
100
101
102def add_simulation_and_reconstruction_modules(path, usePXD=False):
103 '''
104 Adds the required modules to the path for simulate and reconstruct events (not event generation) needed for the
105 SectorMap training.
106 @param path: the path the modules should be added to
107 @param usePXD: If True allows to collect PXD data for SectorMap training.
108 '''
109 # Detector Simulation:
110 add_simulation(path=path,
111 forceSetPXDDataReduction=True, # needs to be true to override the DB settings
112 usePXDDataReduction=False, # for training one does not want the data reduction
113 components=None) # dont specify components because else not the whole geometry will be loaded!
114
115 # needed for fitting
116 path.add_module('SetupGenfitExtrapolation')
117
118 # this adds the clusters for PXD and SVD which are needed in the next steps
119 if usePXD:
120 add_pxd_reconstruction(path=path)
121 add_svd_reconstruction(path=path)
122
123 # Setting up the MC based track finder.
124 mctrackfinder = b2.register_module('TrackFinderMCTruthRecoTracks')
125 mctrackfinder.param('UseCDCHits', False)
126 mctrackfinder.param('UseSVDHits', True)
127 mctrackfinder.param('UsePXDHits', usePXD)
128 mctrackfinder.param('Smearing', False)
129 mctrackfinder.param('MinimalNDF', 6)
130 mctrackfinder.param('WhichParticles', ['primary'])
131 mctrackfinder.param('RecoTracksStoreArrayName', 'MCRecoTracks')
132 # set up the track finder to only use the first half loop of the track and discard all other hits
133 mctrackfinder.param('UseNLoops', 0.5)
134 mctrackfinder.param('discardAuxiliaryHits', True)
135 path.add_module(mctrackfinder)
136
137 # include a track fit into the chain (sequence adopted from the tracking scripts)
138 # Correct time seed: Do I need it for VXD only tracks ????
139 path.add_module("IPTrackTimeEstimator", recoTracksStoreArrayName="MCRecoTracks", useFittedInformation=False)
140 # track fitting
141 daffitter = b2.register_module("DAFRecoFitter")
142 daffitter.param('recoTracksStoreArrayName', "MCRecoTracks")
143 path.add_module(daffitter)
144 # also used in the tracking sequence (multi hypothesis)
145 # may be overkill
146 path.add_module('TrackCreator', recoTrackColName="MCRecoTracks", pdgCodes=[211, 321, 2212])
147
148
149def add_rootoutput(path, outputFileName):
150 ''' Adds the RootOutput module to the path. All branches not needed for the SectorMap training will be excluded.
151 @param: path the path the modules should be added.
152 @param: outputFileName the name of the file the root output will be stored.
153 '''
154 # Root output. Default filename can be overriden with '-o' basf2 option.
155 rootOutput = b2.register_module('RootOutput')
156 rootOutput.param('outputFileName', outputFileName)
157 # to save some space exclude everything except stuff needed for tracking
158 rootOutput.param('excludeBranchNames', ["ARICHAeroHits",
159 "ARICHDigits",
160 "ARICHSimHits",
161 "KLMDigits",
162 "KLMSimHits",
163 "CDCHits",
164 "CDCHits4Trg",
165 "CDCSimHits",
166 "CDCSimHitsToCDCHits4Trg",
167 "ECLDigits",
168 "ECLDsps",
169 "ECLHits",
170 "ECLSimHits",
171 "ECLTrigs",
172 "ECLDiodeHits",
173 "EKLMDigits",
174 "EKLMSimHits",
175 "TOPBarHits",
176 "TOPDigits",
177 "TOPRawDigits",
178 "TOPSimHits"
179 ])
180 path.add_module(rootOutput)
181
182
183def setup_RTCtoSPTCConverters(
184 path=0,
185 SVDSPscollection='SVDSpacePoints',
186 PXDSPscollection='PXDSpacePoints',
187 RTCinput='mcRecoTracks',
188 sptcOutput='checkedSPTCs',
189 usePXD=False,
190 logLevel=b2.LogLevel.INFO,
191 debugVal=1,
192 useNoKick=False,
193 useOnlyFittedTracks=False):
194 """This function adds the modules needed to convert Reco-TCs to SpacePointTCs to given path.
195
196 @param path if set to 0 (standard) the created modules will not be added, but returned. Else
197 modules will be added to this path.
198
199 @param SVDSPscollection the name of the storeArray containing SPs of SVD.
200
201 @param PXDSPscollection the name of the storeArray containing SPs of PXD.
202
203 @param RTCinput defines the name of input-Reco-TCs.
204
205 @param sptcOutput defines the name of output-SPTCs.
206
207 @param usePXD If False pxdClusters are ignored.
208
209 @param logLevel set to logLevel level of your choice.
210
211 @param debugVal set to debugLevel of choice - will be ignored if logLevel is not set to LogLevel.DEBUG
212
213 @param useNoKick enable the training sample selection based on track parameters (and produce a TFile of its effect)
214
215 @param useOnlyFittedTracks: if True only fitted RecoTracks will be transformed to SpacePointTrackCands
216 """
217 print("setup RTCtoSPTCConverters...")
218
219 spacePointNames = []
220 detectorTypes = []
221 trueHitNames = []
222 clusterNames = []
223 if usePXD:
224 detectorTypes.append('PXD')
225 # PXD SpacePoints and SVD SpacePoints are assumed to be in the same StoreArray
226 spacePointNames.append(PXDSPscollection)
227 trueHitNames.append('')
228 clusterNames.append('')
229 # PXD SpacePoints and SVD SpacePoints are assumed to be in the same StoreArray
230 spacePointNames.append(SVDSPscollection)
231 detectorTypes.append('SVD')
232 trueHitNames.append('')
233 clusterNames.append('')
234
235 # module to create relations between SpacePoints and TrueHits -> some of
236 # the following modules will be utilizing these relations!
237 sp2thConnector = b2.register_module('SpacePoint2TrueHitConnector')
238 sp2thConnector.logging.log_level = logLevel
239 sp2thConnector.param('DetectorTypes', detectorTypes)
240 sp2thConnector.param('TrueHitNames', trueHitNames)
241 sp2thConnector.param('ClusterNames', clusterNames)
242 sp2thConnector.param('SpacePointNames', spacePointNames)
243 sp2thConnector.param('outputSuffix', '_relTH')
244 sp2thConnector.param('storeSeperate', False)
245 sp2thConnector.param('registerAll', False)
246 sp2thConnector.param('maxGlobalPosDiff', 0.05)
247 sp2thConnector.param('maxPosSigma', 5)
248 sp2thConnector.param('minWeight', 0)
249 sp2thConnector.param('requirePrimary', True)
250 sp2thConnector.param('positionAnalysis', False)
251
252 # TCConverter, RecoTrack -> SPTC
253 recoTrackCandConverter = b2.register_module('RT2SPTCConverter')
254 recoTrackCandConverter.logging.log_level = logLevel
255 recoTrackCandConverter.param('RecoTracksName', RTCinput)
256 recoTrackCandConverter.param('SpacePointTCName', 'SPTracks')
257 recoTrackCandConverter.param('SVDSpacePointStoreArrayName', SVDSPscollection)
258 recoTrackCandConverter.param('PXDSpacePointStoreArrayName', None)
259 if usePXD:
260 recoTrackCandConverter.param('PXDSpacePointStoreArrayName', PXDSPscollection)
261 recoTrackCandConverter.param('useTrueHits', True)
262 recoTrackCandConverter.param('ignorePXDHits', not usePXD) # if True PXD hits will be ignored
263 recoTrackCandConverter.param('useSingleClusterSP', False)
264 recoTrackCandConverter.param('minSP', 3)
265 recoTrackCandConverter.param('skipProblematicCluster', False)
266 recoTrackCandConverter.param('convertFittedOnly', useOnlyFittedTracks)
267
268 NoKickCuts = Belle2.FileSystem.findFile("data/tracking/NoKickCuts.root")
269
270 if useNoKick:
271 recoTrackCandConverter.param('noKickCutsFile', NoKickCuts) # NoKickCuts applied
272 recoTrackCandConverter.param('noKickOutput', True) # produce output TFile of NoKickCuts
273 else:
274 recoTrackCandConverter.param('noKickCutsFile', "") # NoKickCuts not applied
275
276 # SpacePointTrackCand referee
277 sptcReferee = b2.register_module('SPTCReferee')
278 sptcReferee.logging.log_level = logLevel
279 sptcReferee.param('sptcName', 'SPTracks')
280 sptcReferee.param('newArrayName', sptcOutput)
281 sptcReferee.param('storeNewArray', True)
282 sptcReferee.param('checkCurling', True)
283 sptcReferee.param('splitCurlers', True)
284 sptcReferee.param('keepOnlyFirstPart', True)
285 sptcReferee.param('kickSpacePoint', True)
286 sptcReferee.param('checkSameSensor', True)
287 sptcReferee.param('useMCInfo', True)
288 # sptcReferee.logging.log_level = LogLevel.DEBUG
289
290 if path == 0:
291 return [sp2thConnector, recoTrackCandConverter, sptcReferee]
292 else:
293 path.add_module(sp2thConnector)
294 path.add_module(recoTrackCandConverter)
295 path.add_module(sptcReferee)
296 return None
297
298
299def add_training_data_collector(path, usePXD=False, nameTag='', outputDir='./', use_noKick=False):
300 ''' Adds the modules which extract and collect the actual training data from simulated events.
301 @param path: The basf2 path to add the modules
302 @param usePXD: If False PXD hits will be ignored
303 @param nameTag: Output file names are generated automatically. With this name tag can be set to have a unique
304 output file name. It will be added at the end of output file name.
305 @param outputDir: The output file will be written to that directory.
306 @param use_noKick: Activates alternative trainings method. Note: This trainings method is experimental and not maintained
307 anymore. So if you dont know what you do, keep it set to False!'''
308
309 # puts the geometry and gearbox in the path
310 if 'Gearbox' not in path:
311 gearbox = b2.register_module('Gearbox')
312 path.add_module(gearbox)
313 # the geometry is loaded from the DB by default now! The correct geometry
314 # should be pickked according to exp number for the generated events.
315 if 'Geometry' not in path:
316 geometry = b2.register_module('Geometry')
317 path.add_module(geometry)
318
319 # Converts RecoTrack candidates and checks them, with respect to the SecMap settings
320 # Produces SpacePoint track candidates which are used in the VXDTFTrainingDataCollector.
321 setup_RTCtoSPTCConverters(path=path,
322 SVDSPscollection='SVDSpacePoints',
323 PXDSPscollection='PXDSpacePoints',
324 RTCinput='MCRecoTracks',
325 sptcOutput='checkedSPTCs',
326 usePXD=usePXD,
327 logLevel=b2.LogLevel.ERROR,
328 useNoKick=use_noKick,
329 useOnlyFittedTracks=True) # train on fitted tracks only
330
331 # SecMap BootStrap
332 # Module to fetch SecMap Config and store or load SecMap Training.
333 # Config is defined in /tracking/modules/vxdtfRedesing/src/SectorMapBootstrapModule.cc
334 # and must be available for the training of the SecMap
335 # Double False for "ReadSectorMap" and "WriteSectorMap" only fetches config.
336 secMapBootStrap = b2.register_module('SectorMapBootstrap')
337 secMapBootStrap.param('ReadSectorMap', False)
338 secMapBootStrap.param('WriteSectorMap', False)
339 path.add_module(secMapBootStrap)
340
341 # Module for generation of train sample for SecMap Training
342 if usePXD:
343 nameTag += 'VXD'
344 else:
345 nameTag += 'SVDOnly'
346
347 SecMapTrainerBase = b2.register_module('VXDTFTrainingDataCollector')
348 SecMapTrainerBase.param('outputDir', outputDir)
349 SecMapTrainerBase.param('NameTag', nameTag)
350 SecMapTrainerBase.param('SpacePointTrackCandsName', 'checkedSPTCs')
351 path.add_module(SecMapTrainerBase)
352
353
354def create_unique_random_numbers(n=500, random_seed=12345, n_min=9999, n_max=9999999):
355 ''' Creates randomly a unique set of random numbers of size n. WARNING: if n is close or equal to the
356 specified range this will take very long!
357 @param n number of random numbers
358 @param random_seed random seed to initialize the random generator which generates the random numbers
359 @patam n_min minimum value for the generated random numbers
360 @param n_max maximum value for the generated random numbers
361 '''
362
363 # you cannot create more random numbers than numbers in range.
364 if (n_max - n_min + 1) < n or n_min > n_max:
365 b2.B2ERROR(
366 "Range (" +
367 str(n_min) +
368 "," +
369 str(n_max) +
370 ") not well defined or not great enough for that many random numbers (n=" +
371 str(n) +
372 ")")
373 return []
374
375 random.seed(random_seed)
376
377 # as there is no "do while" in python
378 while True:
379 my_list = [random.randint(n_min, n_max) for i in range(0, n)]
380 if (len(my_list) == len(set(my_list))):
381 return my_list
382
383
384def remove_timing_cuts_from_SectorMap(sectorMapFile, setupToRead="SVDOnlyDefault"):
385 '''
386 Simple function to remove the timing cuts from a given SectorMap and stores the
387 new SectorMap to a file
388 @param sectorMapFile Name (including path) of the SectorMap to be altered.
389 @param setupToRead SectorMap files can store different setups. This parameter specifies the name
390 of the setup which should be read.
391 Currently in use should only be the name given as default.
392 NOTE: This script should only be used by experts!
393 '''
394
395 import basf2 as b2
396
397 # Using the SectorMapBootstrap module to read the sectormap from file
398 SMBSM1 = b2.register_module("SectorMapBootstrap")
399 SMBSM1.param("ReadSecMapFromDB", False)
400 SMBSM1.param("ReadSectorMap", True)
401 SMBSM1.param("SectorMapsInputFile", sectorMapFile)
402 SMBSM1.param("SetupToRead", setupToRead)
403
404 if not sectorMapFile.endswith(".root"):
405 b2.B2FATAL("SectorMaps are supposed to be root - files! Provided name does not end on \".root\"")
406
407 # assumes it is a root file so replace the last 5 letters
408 outputMapFile = sectorMapFile[:-5] + '_timingRemoved.root'
409 # the following setting will make the module write the altered sectormap to a root file
410 SMBSM1.param("SectorMapsOutputFile", outputMapFile)
411 SMBSM1.param("WriteSectorMap", True)
412
413
416
417 # NOTE: the indizes in the example below may have changed if the code changed! So you have to cross check!
418
419 # three hit filter
420 # (#19 <= DistanceInTime <= #20)
421 SMBSM1.param('threeHitFilterAdjustFunctions', [(19, "-TMath::Infinity()"), (20, "TMath::Infinity()")])
422 # two hit filters:
423 # (#12 <= DistanceInTimeUside <= #13)
424 # (#10 <= DistanceInTimeVside <= #11)
425 SMBSM1.param('twoHitFilterAdjustFunctions', [(12, "-TMath::Infinity()"), (13, "TMath::Infinity()"),
426 (10, "-TMath::Infinity()"), (11, "TMath::Infinity()")])
427
428 # this will, in addition to other debbugging output, print the original filter ("BEFORE")
429 # and the altered filter ("AFTER") to the screen.
430 # NOTE: there are order of 10th of thousends of filters both for 2-hits and 3-hits. So expect lots of output.
431 # SMBSM1.logging.log_level = LogLevel.DEBUG
432
433 # create path
434 main = b2.create_path()
435 # EventInfoSetter needed else basf2 complains as it is afraid of having no EventMetaData
436 main.add_module('EventInfoSetter')
437 main.add_module(SMBSM1)
438 b2.print_path(main)
439 # run path
440 b2.process(main)
441 print(b2.statistics)
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...
Definition: FileSystem.cc:151