Belle II Software development
generators.py
1
8
9'''
10This module contains convenience functions to setup most commonly used physics
11generators correctly with their default settings. More information can be found
12in `BELLE2-NOTE-PH-2015-006`_
13
14.. _BELLE2-NOTE-PH-2015-006: https://docs.belle2.org/record/282
15'''
16
17import basf2 as b2
18import pdg
19
20
21def get_default_decayfile():
22 """Return the default DECAY.dec for Belle2"""
23 return b2.find_file("decfiles/dec/DECAY_BELLE2.DEC")
24
25
26def add_generator_preselection(
27 path,
28 emptypath,
29 nChargedMin=0,
30 nChargedMax=999,
31 MinChargedP=-1.0,
32 MinChargedPt=-1.0,
33 MinChargedTheta=0.0,
34 MaxChargedTheta=180.0,
35 nPhotonMin=0,
36 nPhotonMax=999,
37 MinPhotonEnergy=-1,
38 MinPhotonTheta=0.0,
39 MaxPhotonTheta=180.0,
40 applyInCMS=False,
41 stableParticles=False):
42 """
43 Adds generator preselection.
44 Should be added to the path after the generator.add_abc_generator but before simulation.add_simulation modules
45 It uses all particles from the event generator (i.e. primary, non-virtual, non-initial particles).
46 It checks if the required conditions are fulfilled.
47 If not, the events are given to the emptypath.
48 The main use case is a reduction of simulation time.
49 Note that you have to multiply the generated cross section by the retention fraction of the preselection.
50
51 Parameters:
52 path (basf2.Path): path where the generator should be added
53 emptypath (basf2.Path): path where the skipped events are given to
54 nChargedMin (int): minimum number of charged particles
55 nChargedMax (int): maximum number of charged particles
56 MinChargedP (float): minimum charged momentum [GeV]
57 MinChargedPt (float): minimum charged transverse momentum (pt) [GeV]
58 MinChargedTheta (float): minimum polar angle of charged particle [deg]
59 MaxChargedTheta (float): maximum polar angle of charged particle [deg]
60 nPhotonMin (int): minimum number of photons
61 nPhotonMax (int): maximum number of photons
62 MinPhotonEnergy (float): minimum photon energy [GeV]
63 MinPhotonTheta (float): minimum polar angle of photon [deg]
64 MaxPhotonTheta (float): maximum polar angle of photon [deg]
65 applyInCMS (bool): if true apply the P,Pt,theta, and energy cuts in the center of mass frame
66 stableParticles (bool): if true apply the selection criteria for stable particles in the generator
67 """
68
69 generatorpreselection = path.add_module('GeneratorPreselection',
70 nChargedMin=nChargedMin,
71 nChargedMax=nChargedMax,
72 MinChargedP=MinChargedP,
73 MinChargedPt=MinChargedPt,
74 MinChargedTheta=MinChargedTheta,
75 MaxChargedTheta=MaxChargedTheta,
76 nPhotonMin=nPhotonMin,
77 nPhotonMax=nPhotonMax,
78 MinPhotonEnergy=MinPhotonEnergy,
79 MinPhotonTheta=MinPhotonTheta,
80 MaxPhotonTheta=MaxPhotonTheta,
81 applyInCMS=applyInCMS,
82 stableParticles=stableParticles
83 )
84
85 # empty path for unwanted events
86 generatorpreselection.if_value('<11', emptypath)
87
88
89def add_aafh_generator(
90 path,
91 finalstate='',
92 preselection=False,
93 enableTauDecays=True,
94 minmass=0.5,
95 subweights=[],
96 maxsubweight=1,
97 maxfinalweight=3.0,
98 eventType=''):
99 """
100 Add the default two photon generator for four fermion final states
101
102 Parameters:
103 path (basf2.Path): path where the generator should be added
104 finalstate (str): either "e+e-e+e-", "e+e-mu+mu-", "e+e-tau+tau-", "mu+mu-mu+mu-" or "mu+mu-tau+tau-"
105 preselection (bool): if True, select events with at least one medium pt particle in the CDC acceptance
106 enableTauDecays (bool): if True, allow tau leptons to decay (using EvtGen)
107 minmass (float): minimum invariant mass
108 subweights (list(float)): list of four or eight values (first four are interpreted as WAP, rest as WBP)
109 which specify the relative weights for each of the four sub generators
110 maxsubweight (float): maximum expected subgenerator weight for rejection scheme
111 maxfinalweight (float): maximum expected final weight for rejection scheme
112 eventType (str) : event type information
113 """
114
115 if finalstate == 'e+e-e+e-':
116 aafh_mode = 5
117 if not subweights: # default subweights are for minmass=0.5
118 aafh_subgeneratorWeights = [1.0, 7.986e+01, 5.798e+04, 3.898e+05, 1.0, 1.664e+00, 2.812e+00, 7.321e-01]
119 else:
120 aafh_subgeneratorWeights = subweights
121 if abs(minmass - 0.5) > 0.01 and not subweights:
122 b2.B2WARNING("add_aafh_generator: non default invariant mass cut without updated subweights requested!")
123 elif finalstate == 'e+e-mu+mu-':
124 aafh_mode = 3
125 if not subweights: # default subweights are for minmass=0.5
126 aafh_subgeneratorWeights = [1.000e+00, 1.520e+01, 3.106e+03, 6.374e+03, 1.000e+00, 1.778e+00, 6.075e+00, 6.512e+00]
127 else:
128 aafh_subgeneratorWeights = subweights
129 if abs(minmass - 0.5) > 0.01 and not subweights:
130 b2.B2WARNING("add_aafh_generator: non default invariant mass cut without updated subweights requested!")
131 elif finalstate == 'e+e-tau+tau-':
132 aafh_mode = 4
133 minmass = 0
134 if not subweights:
135 aafh_subgeneratorWeights = [1.000e+00, 2.214e+00, 1.202e+01, 1.536e+01, 1.000e+00, 1.664e+00, 1.680e+01, 6.934e+00]
136 else:
137 aafh_subgeneratorWeights = subweights
138 if preselection:
139 b2.B2WARNING(
140 f"You requested a generator preselection for the final state {finalstate}: "
141 "please consider to remove it, since the cross section is small.")
142 elif finalstate == 'mu+mu-mu+mu-':
143 aafh_mode = 2
144 minmass = 0
145 maxsubweight = 3
146 if not subweights:
147 aafh_subgeneratorWeights = [0.000e+00, 0.000e+00, 1.000e+00, 3.726e+00, 1.000e+00, 1.778e+00, 1.000e+00, 1.094e+00]
148 else:
149 aafh_subgeneratorWeights = subweights
150 if preselection:
151 b2.B2WARNING(
152 f"You requested a generator preselection for the final state {finalstate}: "
153 "please consider to remove it, since the cross section is small.")
154 elif finalstate == 'mu+mu-tau+tau-':
155 aafh_mode = 1
156 minmass = 0
157 maxsubweight = 3
158 if not subweights:
159 aafh_subgeneratorWeights = [0.000e+00, 0.000e+00, 1.000e+00, 1.715e+00, 1.000e+00, 1.778e+00, 1.000e+00, 6.257e-01]
160 else:
161 aafh_subgeneratorWeights = subweights
162 if preselection:
163 b2.B2WARNING(
164 f"You requested a generator preselection for the final state {finalstate}: "
165 "please consider to remove it, since the cross section is small.")
166 elif finalstate == 'tau+tau-tau+tau-':
167 b2.B2FATAL(f"AAFH is not able to generate the {finalstate} final state. Please use KoralW instead.")
168 else:
169 b2.B2FATAL(f"add_aafh_generator final state not supported: {finalstate}")
170
171 aafh_maxSubgeneratorWeight = maxsubweight
172 aafh_maxFinalWeight = maxfinalweight
173
174 path.add_module(
175 'AafhInput',
176 mode=aafh_mode,
177 rejection=2,
178 maxSubgeneratorWeight=aafh_maxSubgeneratorWeight,
179 maxFinalWeight=aafh_maxFinalWeight,
180 subgeneratorWeights=aafh_subgeneratorWeights,
181 suppressionLimits=[1e100] * 4,
182 minMass=minmass,
183 eventType=eventType,
184 )
185
186 if preselection:
187 generator_emptypath = b2.create_path()
188 add_generator_preselection(
189 path=path,
190 emptypath=generator_emptypath,
191 nChargedMin=1,
192 MinChargedPt=0.1,
193 MinChargedTheta=17.0,
194 MaxChargedTheta=150.0)
195
196 if 'tau+tau-' in finalstate:
197 if enableTauDecays:
198 path.add_module('EvtGenDecay')
199 else:
200 b2.B2WARNING("The tau decays will not be generated.")
201
202
203def add_kkmc_generator(path, finalstate='', signalconfigfile='', useTauolaBelle=False, tauinputfile='', eventType=''):
204 """
205 Add the default muon pair and tau pair generator KKMC.
206 For tau decays, TauolaBelle and TauolaBelle2 are available.
207 Signal events can be produced setting a configuration file. Please notice that the configuration files for
208 TauolaBelle and TauolaBelle2 has a very different structure (see the examples below generators/examples).
209
210 Parameters:
211 path (basf2.Path): path where the generator should be added
212 finalstate(str): either "mu-mu+" or "tau-tau+"
213 signalconfigfile(str): File with configuration of the signal event to generate. It doesn't affect mu-mu+ decays. useTauolaBelle(bool): If true, tau decay is driven by TauolaBelle. Otherwise TauolaBelle2 is used.
214 It doesn't affect mu-mu+ decays.
215 tauinputfile(str) : File to override KK2f_defaults. Only [sometimes] needed when tau decay is driven by TauolaBelle.
216 eventType (str) : event type information
217 """
218
219
220 kkmc_inputfile = b2.find_file('data/generators/kkmc/tauola_bbb.input.dat')
221
222
223 kkmc_logfile = 'kkmc_tautau.txt'
224
225
226 kkmc_config = b2.find_file('data/generators/kkmc/KK2f_defaults.dat')
227
228
229 kkmc_tauconfigfile = ''
230
231 if finalstate == 'tau+tau-':
232 b2.B2WARNING("add_kkmc_generator: please set finalstate as 'tau-tau+'. 'tau+tau-' will be deprecated in the future"
233 " for consistency in the configuration files.")
234 finalstate = 'tau-tau+'
235 if finalstate == 'mu+mu-':
236 b2.B2WARNING("add_kkmc_generator: please set finalstate as 'mu-mu+'. 'mu+mu-' will be deprecated in the future for"
237 " consistency in the configuration files.")
238 finalstate = 'mu-mu+'
239
240 if finalstate == 'tau-tau+':
241 if useTauolaBelle:
242 b2.B2INFO("Generating tau pair events with TauolaBelle")
243
244 kkmc_inputfile = b2.find_file('data/generators/kkmc/tau.input.dat')
245 kkmc_tauconfigfile = b2.find_file('data/generators/kkmc/tau_decaytable.dat')
246
247 if not signalconfigfile == '':
248 b2.B2INFO(f"Using config file defined by user: {signalconfigfile}")
249 if useTauolaBelle:
250 kkmc_tauconfigfile = b2.find_file(signalconfigfile)
251 else:
252 kkmc_inputfile = b2.find_file(signalconfigfile)
253
254 if not tauinputfile == '':
255 kkmc_inputfile = b2.find_file(tauinputfile)
256
257 elif finalstate == 'mu-mu+':
258 kkmc_inputfile = b2.find_file('data/generators/kkmc/mu.input.dat')
259 kkmc_logfile = 'kkmc_mumu.txt'
260
261 else:
262 b2.B2FATAL("add_kkmc_generator final state not supported: {}".format(finalstate))
263
264 # use KKMC to generate lepton pairs
265 path.add_module(
266 'KKGenInput',
267 tauinputFile=kkmc_inputfile,
268 KKdefaultFile=kkmc_config,
269 taudecaytableFile=kkmc_tauconfigfile,
270 kkmcoutputfilename=kkmc_logfile,
271 eventType=eventType,
272 )
273
274
275def add_evtgen_generator(path, finalstate='', signaldecfile=None, coherentMixing=True, parentParticle='Upsilon(4S)', eventType=''): """
276 Add EvtGen for mixed and charged BB
277
278 Parameters:
279 path (basf2.Path): path where the generator should be added
280 finalstate (str): Either "charged" for generation of generic B+/B-, "mixed" for generic B0/anti-B0, or "signal" for
281 generation of user-defined signal mode
282 signaldecfile (str): path to decfile which defines the signal decay to be generated
283 (only needed if ``finalstate`` set to "signal")
284 coherentMixing: Either True or False. Switches on or off the coherent decay of the B0-B0bar pair.
285 It should always be True, unless you are generating Y(5,6S) -> BBar. In the latter case,
286 setting it False solves the internal limitation of Evtgen that allows to make a
287 coherent decay only starting from the Y(4S).
288 parentParticle (str): initial state (used only if it is not Upsilon(4S).
289 eventType (str) : event type information
290 """
291 evtgen_userdecfile = b2.find_file('data/generators/evtgen/charged.dec')
292
293 if parentParticle != 'Upsilon(3S)' and parentParticle != 'Upsilon(4S)'\
294 and parentParticle != 'Upsilon(5S)' and parentParticle != 'Upsilon(6S)':
295 b2.B2FATAL("add_evtgen_generator initial state not supported: {}".format(parentParticle))
296
297 if finalstate == 'charged':
298 pass
299 elif finalstate == 'mixed':
300 evtgen_userdecfile = b2.find_file('data/generators/evtgen/mixed.dec')
301 elif finalstate == 'signal':
302 evtgen_userdecfile = signaldecfile
303 else:
304 b2.B2FATAL("add_evtgen_generator final state not supported: {}".format(finalstate))
305
306 if signaldecfile and finalstate in ['charged', 'mixed']:
307 b2.B2WARNING("ignoring decfile: {}".format(signaldecfile))
308
309 # use EvtGen
310 if parentParticle == 'Upsilon(3S)':
311 if finalstate != 'signal':
312 b2.B2FATAL("add_evtgen_generator initial state {} is supported only with 'signal' final state".format(parentParticle))
313 if coherentMixing:
314 coherentMixing = False
315 b2.B2WARNING("add_evtgen_generator initial state {} has no BB mixing, now switching coherentMixing OFF"
316 .format(parentParticle))
317
318 if parentParticle == 'Upsilon(5S)':
319 if finalstate != 'signal':
320 b2.B2FATAL("add_evtgen_generator initial state {} is supported only with 'signal' final state".format(parentParticle))
321 if coherentMixing:
322 coherentMixing = False
323 b2.B2WARNING(
324 "add_evtgen_generator initial state {} is supported only with false coherentMixing, now switching it OFF"
325 .format(parentParticle))
326 pdg.load(b2.find_file('decfiles/dec/Y5S.pdl'))
327
328 if parentParticle == 'Upsilon(6S)':
329 if finalstate != 'signal':
330 b2.B2FATAL("add_evtgen_generator initial state {} is supported only with 'signal' final state".format(parentParticle))
331 if coherentMixing:
332 coherentMixing = False
333 b2.B2WARNING(
334 "add_evtgen_generator initial state {} is supported only with false coherentMixing, now switching it OFF"
335 .format(parentParticle))
336 pdg.load(b2.find_file('decfiles/dec/Y6S.pdl'))
337
338 path.add_module(
339 'EvtGenInput',
340 userDECFile=evtgen_userdecfile,
341 CoherentMixing=coherentMixing,
342 ParentParticle=parentParticle,
343 eventType=eventType,
344 )
345
346
347def add_continuum_generator(path, finalstate, userdecfile='', *, skip_on_failure=True, eventType=''):
348 """
349 Add the default continuum generators KKMC + PYTHIA including their default decfiles and PYTHIA settings
350
351 See Also:
352 `add_inclusive_continuum_generator()` to add continuum generation with preselected particles
353
354 Parameters:
355 path (basf2.Path): path where the generator should be added
356 finalstate (str): uubar, ddbar, ssbar, ccbar
357 userdecfile (str): EvtGen decfile used for particle decays
358 skip_on_failure (bool): If True stop event processing right after
359 fragmentation fails. Otherwise continue normally
360 eventType (str) : event type information
361 """
362
363
364 kkmc_inputfile = b2.find_file('data/generators/kkmc/uubar_nohadronization.input.dat')
365
366
367 kkmc_logfile = 'kkmc_uubar.txt'
368
369
370 pythia_config = b2.find_file('data/generators/modules/fragmentation/pythia_belle2.dat')
371
372
373 decay_user = b2.find_file('data/generators/modules/fragmentation/dec_belle2_qqbar.dec')
374 if userdecfile == '':
375 pass
376 else:
377 b2.B2INFO('Replacing default user decfile: {}'.format(userdecfile))
378 decay_user = userdecfile
379
380
381 kkmc_config = b2.find_file('data/generators/kkmc/KK2f_defaults.dat')
382
383
384 decay_file = get_default_decayfile()
385
386 if finalstate == 'uubar':
387 pass
388 elif finalstate == 'ddbar':
389 kkmc_inputfile = b2.find_file('data/generators/kkmc/ddbar_nohadronization.input.dat')
390 kkmc_logfile = 'kkmc_ddbar.txt'
391 elif finalstate == 'ssbar':
392 kkmc_inputfile = b2.find_file('data/generators/kkmc/ssbar_nohadronization.input.dat')
393 kkmc_logfile = 'kkmc_ssbar.txt'
394 elif finalstate == 'ccbar':
395 kkmc_inputfile = b2.find_file('data/generators/kkmc/ccbar_nohadronization.input.dat')
396 pythia_config = b2.find_file('data/generators/modules/fragmentation/pythia_belle2_charm.dat')
397 kkmc_logfile = 'kkmc_ccbar.txt'
398 else:
399 b2.B2FATAL("add_continuum_generator final state not supported: {}".format(finalstate))
400
401 # use KKMC to generate qqbar events (no fragmentation at this stage)
402 path.add_module(
403 'KKGenInput',
404 tauinputFile=kkmc_inputfile,
405 KKdefaultFile=kkmc_config,
406 taudecaytableFile='',
407 kkmcoutputfilename=kkmc_logfile,
408 eventType=eventType,
409 )
410
411 # add the fragmentation module to fragment the generated quarks into hadrons
412 # using PYTHIA8
413 fragmentation = path.add_module(
414 'Fragmentation',
415 ParameterFile=pythia_config,
416 ListPYTHIAEvent=0,
417 UseEvtGen=1,
418 DecFile=decay_file,
419 UserDecFile=decay_user,
420 )
421
422 if skip_on_failure:
423 # branch to an empty path if PYTHIA failed, this will change the number of events
424 # but the file meta data will contain the total number of generated events
425 generator_emptypath = b2.create_path()
426 fragmentation.if_value('<1', generator_emptypath)
427
428
429def add_inclusive_continuum_generator(path, finalstate, particles, userdecfile='',
430 *, include_conjugates=True, max_iterations=100000, eventType=''):
431 """
432 Add continuum generation but require at least one of the given particles be
433 present in the event.
434
435 For example to only generate ccbar events which contain a "D*+" or an
436 electron one could would use
437
438 >>> add_inclusive_continuum_generator(path, "ccbar", ["D*+", 11])
439
440 If you are unsure how the particles are named in Belle II please have a look
441 at the ``b2help-particles`` executable or the `pdg` python module.
442
443 See Also:
444 `add_continuum_generator()` to add continuum generation without preselection
445
446 Parameters:
447 path (basf2.Path): path to which the generator should be added
448 finalstate (str): uubar, ddbar, ssbar, ccbar
449 particles (list): A list of particle names or pdg codes. An event is
450 only accepted if at lease one of those particles appears in the event.
451 userdecfile (str): EvtGen decfile used for particle decays
452 include_conjugates (bool): If True (default) accept the event also if a
453 charge conjugate of the given particles is found
454 max_iterations (int): maximum tries per event to generate the requested
455 particle. If exceeded processing will be stopped with a
456 `FATAL <LogLevel.FATAL>` error so for rare particles one might need a
457 larger number.
458 eventType (str) : event type information
459 """
460 loop_path = b2.create_path()
461 # we might run this more than once so make sure we remove any particles
462 # before generating new ones
463 loop_path.add_module("PruneDataStore", keepMatchedEntries=False, matchEntries=["MCParticles", "EventExtraInfo"])
464 # add the generator but make sure it doesn't stop processing on
465 # fragmentation failure as is this currently not supported by do_while
466 add_continuum_generator(loop_path, finalstate, userdecfile, skip_on_failure=False, eventType=eventType)
467 # check for the particles we want
468 loop_path.add_module("InclusiveParticleChecker", particles=particles, includeConjugates=include_conjugates)
469 # Done, add this to the path and iterate it until we found our particle
470 path.do_while(loop_path, max_iterations=max_iterations)
471
472
473def add_bhwide_generator(path, minangle=0.5):
474 """
475 Add the high precision QED generator BHWIDE to the path. Settings are the default L1/HLT study settings
476 with a cross section of about 124000 nb (!)
477
478 Parameters:
479 path (basf2.Path): path where the generator should be added
480 minangle (float): minimum angle of the outgoing electron/positron in the CMS in degrees
481 """
482
483 if minangle < 0.0 or minangle > 180.0:
484 b2.B2FATAL("add_bhwide_generator minimum angle too small (<0.0) or too large (>180): {}".format(minangle))
485
486 bhwide = path.add_module("BHWideInput")
487 bhwide.param('ScatteringAngleRangePositron', [minangle, 180.0 - minangle])
488 bhwide.param('ScatteringAngleRangeElectron', [minangle, 180.0 - minangle])
489 bhwide.param('MaxAcollinearity', 180.0)
490 bhwide.param('MinEnergy', 0.10)
491 bhwide.param('VacuumPolarization', 'burkhardt')
492 bhwide.param('WeakCorrections', True)
493 bhwide.param('WtMax', 3.0)
494
495
496def add_babayaganlo_generator(
497 path,
498 finalstate='',
499 minenergy=0.01,
500 minangle=10.0,
501 fmax=-1.0,
502 generateInECLAcceptance=False,
503 eventType=''):
504 '''
505 Add the high precision QED generator BabaYaga@NLO to the path.
506
507 Parameters:
508 path (basf2.Path): path where the generator should be added.
509 finalstate (str): ee (e+e-), mm(mu+mu-) or gg (gammagamma).
510 minenergy (float): minimum particle (leptons for 'ee' or 'mm', photons for 'gg') energy in GeV.
511 minangle (float): angular range from minangle to 180-minangle for primary particles (in degrees).
512 fmax (float): maximum of differential cross section weight. This parameter should be set only by experts.
513 generateInECLAcceptance (bool): if True, the GeneratorPreselection module is used to select only events
514 with both the primary particles within the ECL acceptance.
515 eventType (str) : event type information
516 '''
517
518 if finalstate != 'ee' and finalstate != 'gg' and finalstate != 'mm':
519 b2.B2FATAL(f'add_babayaganlo_generator final state not supported: {finalstate}')
520
521 if not (fmax == -1.0):
522 b2.B2WARNING(f'The BabayagaNLOInput parameter "FMax" will be set to {fmax} instead to the default value (-1.0). '
523 'Please do not do this, unless you are extremely sure about this choice.')
524
525 path.add_module(
526 'BabayagaNLOInput',
527 eventType=eventType,
528 FinalState=finalstate,
529 ScatteringAngleRange=[minangle, 180.0 - minangle],
530 MinEnergy=minenergy,
531 FMax=fmax
532 )
533
534 if generateInECLAcceptance:
535 b2.B2INFO(f'The final state {finalstate} is preselected requiring both primary particles within the ECL acceptance.')
536 emptypath = b2.Path()
537 add_generator_preselection(path=path,
538 emptypath=emptypath,
539 applyInCMS=False)
540
541 if finalstate == 'ee' or finalstate == 'mm':
542 b2.set_module_parameters(path=path,
543 name='GeneratorPreselection',
544 nChargedMin=2,
545 MinChargedTheta=12.4,
546 MaxChargedTheta=155.1,)
547
548 elif finalstate == 'gg':
549 b2.set_module_parameters(path=path,
550 name='GeneratorPreselection',
551 nPhotonMin=2,
552 MinPhotonTheta=12.4,
553 MaxPhotonTheta=155.1)
554
555
556def add_phokhara_generator(path, finalstate='', eventType=''):
557 """
558 Add the high precision QED generator PHOKHARA to the path. Almost full
559 acceptance settings for photons and hadrons/muons.
560
561 Parameters:
562 path (basf2.Path): path where the generator should be added
563 finalstate (str): One of the following final states: "mu+mu-", "pi+pi-", "pi+pi-pi0", "pi+pi-pi+pi-" (or "2(pi+pi-)"),
564 "pi+pi-pi0pi0" or ("pi+pi-2pi0"), "pi+pi-eta", "K+K-", "K0K0bar", "ppbar", "n0n0bar" or "Lambda0Lambda0bar"
565 eventType (str) : event type information
566 """
567
568 if finalstate == 'mu+mu-':
569 path.add_module(
570 'PhokharaInput',
571 FinalState=0, # mu+mu-
572 LO=0, NLO=1, QED=0, # use full two loop corrections
573 MinInvMassHadrons=0.,
574 eventType=eventType,
575 ).set_name('PHOKHARA_mumuISR')
576
577 elif finalstate == 'pi+pi-':
578 path.add_module(
579 'PhokharaInput',
580 FinalState=1, # pi+pi-
581 LO=0, NLO=1, QED=0, # use full two loop corrections
582 MinInvMassHadrons=0.,
583 eventType=eventType,
584 ).set_name('PHOKHARA_pipiISR')
585
586 elif finalstate == 'pi+pi-pi0':
587 path.add_module(
588 'PhokharaInput',
589 FinalState=8, # pi+pi-pi0
590 LO=0, NLO=1, QED=0, # use full two loop corrections
591 MinInvMassHadrons=0.,
592 eventType=eventType,
593 ).set_name('PHOKHARA_pipipi0ISR')
594
595 elif finalstate == 'pi+pi-pi+pi-' or finalstate == '2(pi+pi-)':
596 path.add_module(
597 'PhokharaInput',
598 FinalState=3, # 2(pi+pi-)
599 LO=0, NLO=1, QED=0, # use full two loop corrections
600 MinInvMassHadrons=0.,
601 eventType=eventType,
602 ).set_name('PHOKHARA_pipipipiISR')
603
604 elif finalstate == 'pi+pi-pi0pi0' or finalstate == 'pi+pi-2pi0':
605 path.add_module(
606 'PhokharaInput',
607 FinalState=2, # pi+pi-2pi0
608 LO=0, NLO=1, QED=0, # use full two loop corrections
609 MinInvMassHadrons=0.,
610 eventType=eventType,
611 ).set_name('PHOKHARA_pipipi0pi0ISR')
612
613 elif finalstate == 'pi+pi-eta':
614 path.add_module(
615 'PhokharaInput',
616 FinalState=10, # pi+pi-eta
617 LO=0, NLO=1, QED=0, # use full two loop corrections
618 MinInvMassHadrons=0.,
619 eventType=eventType,
620 ).set_name('PHOKHARA_pipietaISR')
621
622 elif finalstate == 'K+K-':
623 path.add_module(
624 'PhokharaInput',
625 FinalState=6, # K+K-
626 LO=0, NLO=1, QED=0, # use full two loop corrections
627 MinInvMassHadrons=0.,
628 eventType=eventType,
629 ).set_name('PHOKHARA_KKISR')
630
631 elif finalstate == 'K0K0bar':
632 path.add_module(
633 'PhokharaInput',
634 FinalState=7, # K0K0bar
635 LO=0, NLO=1, QED=0, # use full two loop corrections
636 MinInvMassHadrons=0.,
637 eventType=eventType,
638 ).set_name('PHOKHARA_K0K0barISR')
639
640 elif finalstate == 'ppbar':
641 path.add_module(
642 'PhokharaInput',
643 FinalState=4, # ppbar
644 LO=0, NLO=1, QED=0, # use full two loop corrections
645 MinInvMassHadrons=0.,
646 eventType=eventType,
647 ).set_name('PHOKHARA_ppbarISR')
648
649 elif finalstate == 'n0n0bar':
650 path.add_module(
651 'PhokharaInput',
652 FinalState=5, # n0n0bar
653 LO=0, NLO=1, QED=0, # use full two loop corrections
654 MinInvMassHadrons=0.,
655 eventType=eventType,
656 ).set_name('PHOKHARA_n0n0barISR')
657
658 elif finalstate == 'Lambda0Lambda0bar':
659 path.add_module(
660 'PhokharaInput',
661 FinalState=9, # Lambda0Lambda0bar
662 LO=0, NLO=1, QED=0, # use full two loop corrections
663 MinInvMassHadrons=0.,
664 eventType=eventType,
665 ).set_name('PHOKHARA_Lambda0Lambda0barISR')
666
667 else:
668 b2.B2FATAL(f"add_phokhara_generator final state not supported: {finalstate}")
669
670
671def add_phokhara_evtgen_combination(
672 path, final_state_particles, user_decay_file,
673 beam_energy_spread=True, isr_events=False, min_inv_mass_vpho=0.0,
674 max_inv_mass_vpho=0.0, eventType=''):
675 """
676 Add combination of PHOKHARA and EvtGen to the path. Phokhara is
677 acting as ISR generator by generating e+ e- -> mu+ mu-, the muon pair is
678 then replaced by a virtual photon. Finally, the virtual photon is
679 decayed by EvtGen.
680
681 Parameters:
682 path (basf2.Path): Path where the generator should be added.
683 final_state_particles (list): List of final-state particles of
684 the virtual-photon decay. It is necessary to define the correct
685 mass threshold in PHOKHARA. For example, for the process
686 e+ e- -> J/psi eta_c, the list should be ['J/psi', 'eta_c'];
687 it does not depend on subsequent J/psi or eta_c decays.
688 user_decay_file (str): Name of EvtGen user decay file. The initial
689 particle must be the virtual photon (vpho).
690 beam_energy_spread (bool): Whether beam-energy spread should be
691 simulated
692 isr_events (bool): If true, then PHOKHARA is used with ph0 (LO in
693 basf2) = 0, i.e. generation of processes with one photon.
694 min_inv_mass_hadrons(float): Minimum invariant mass of the virtual
695 photon. This parameter is used only if isr_events is true,
696 otherwise the minimum mass is computed from the masses of
697 the final-state particles.
698 max_inv_mass_hadrons(float): Maximum invariant mass of the virtual
699 photon. This parameter is used only if isr_events is true,
700 otherwise the maximum mass is not restricted.
701 eventType (str) : event type information
702 """
703
704 import pdg
705
706 phokhara = path.add_module('PhokharaInput')
707 phokhara.param('eventType', eventType)
708
709 # Generate muons and replace them by a virtual photon.
710 phokhara.param('FinalState', 0)
711 phokhara.param('ReplaceMuonsByVirtualPhoton', True)
712
713 # Simulate beam-energy spread. This performs initialization for every
714 # event, and, thus, very slow, but usually necessary except for testing.
715 phokhara.param('BeamEnergySpread', beam_energy_spread)
716
717 # Soft photon cutoff.
718 phokhara.param('Epsilon', 0.0001)
719
720 # Maximum search.
721 phokhara.param('SearchMax', 5000)
722
723 # Number of generation attempts for event.
724 phokhara.param('nMaxTrials', 25000)
725
726 # Use NNLO.
727 if isr_events:
728 phokhara.param('LO', 0)
729 else:
730 phokhara.param('LO', 1)
731 phokhara.param('NLO', 1)
732
733 # Use ISR only.
734 phokhara.param('QED', 0)
735
736 # No interference.
737 phokhara.param('IFSNLO', 0)
738
739 # Vacuum polarization by Fred Jegerlehner.
740 phokhara.param('Alpha', 1)
741
742 # Do not include narrow resonances.
743 phokhara.param('NarrowRes', 0)
744
745 # Angular ragnes.
746 phokhara.param('ScatteringAngleRangePhoton', [0., 180.])
747 phokhara.param('ScatteringAngleRangeFinalStates', [0., 180.])
748
749 # Minimal invariant mass of the muons and tagged photon combination.
750 phokhara.param('MinInvMassHadronsGamma', 0.)
751
752 if isr_events:
753 # Minimum squared invariant mass of muons (final state).
754 phokhara.param('MinInvMassHadrons',
755 min_inv_mass_vpho * min_inv_mass_vpho)
756 # Maximum squared invariant mass of muons (final state).
757 phokhara.param('MaxInvMassHadrons',
758 max_inv_mass_vpho * max_inv_mass_vpho)
759 else:
760 # Minimum squared invariant mass of muons (final state).
761 # Force application of this cut.
762 mass = 0
763 for particle in final_state_particles:
764 p = pdg.get(particle)
765 mass = mass + p.Mass()
766 phokhara.param('MinInvMassHadrons', mass * mass)
767 phokhara.param('ForceMinInvMassHadronsCut', True)
768 # Maximum squared invariant mass of muons (final state).
769 # It is set to a large value, resulting in unrestricted mass.
770 phokhara.param('MaxInvMassHadrons', 200.0)
771
772 # Minimal photon energy.
773 phokhara.param('MinEnergyGamma', 0.01)
774
775 # EvtGen.
776 evtgen_decay = path.add_module('EvtGenDecay')
777 evtgen_decay.param('UserDecFile', user_decay_file)
778
779
780def add_koralw_generator(path, finalstate='', enableTauDecays=True, eventType=''):
781 """
782 Add KoralW generator for radiative four fermion final states (only four leptons final states are currently supported).
783
784 Parameters:
785 path (basf2.Path): path where the generator should be added
786 finalstate (str): either 'e+e-e+e-', 'e+e-mu+mu-', 'e+e-tau+tau-', 'mu+mu-mu+mu-', 'mu+mu-tau+tau-' or 'tau+tau-tau+tau-'
787 enableTauDecays (bool): if True, allow tau leptons to decay (using EvtGen)
788 eventType (str) : event type information
789 """
790
791 decayFile = ''
792 if finalstate == 'e+e-e+e-':
793 decayFile = b2.find_file('data/generators/koralw/KoralW_eeee.data')
794 elif finalstate == 'e+e-mu+mu-':
795 decayFile = b2.find_file('data/generators/koralw/KoralW_eeMuMu.data')
796 elif finalstate == 'e+e-tau+tau-':
797 decayFile = b2.find_file('data/generators/koralw/KoralW_eeTauTau.data')
798 elif finalstate == 'mu+mu-mu+mu-':
799 decayFile = b2.find_file('data/generators/koralw/KoralW_MuMuMuMu.data')
800 elif finalstate == 'mu+mu-tau+tau-':
801 decayFile = b2.find_file('data/generators/koralw/KoralW_MuMuTauTau.data')
802 elif finalstate == 'tau+tau-tau+tau-':
803 decayFile = b2.find_file('data/generators/koralw/KoralW_TauTauTauTau.data')
804 else:
805 b2.B2FATAL(f'add_koralw_generator final state not supported: {finalstate}')
806
807 path.add_module('KoralWInput',
808 UserDataFile=decayFile,
809 eventType=eventType)
810
811 if 'tau+tau-' in finalstate:
812 if enableTauDecays:
813 path.add_module('EvtGenDecay')
814 else:
815 b2.B2WARNING('The tau decays will not be generated.')
816
817
818def add_cosmics_generator(path, components=None,
819 global_box_size=None, accept_box=None, keep_box=None,
820 geometry_xml_file='geometry/Beast2_phase2.xml',
821 cosmics_data_dir='data/generators/modules/cryinput/',
822 setup_file='generators/scripts/cry.setup',
823 data_taking_period='gcr2017', top_in_counter=False):
824 """
825 Add the cosmics generator CRY with the default parameters to the path.
826
827 Warning:
828 Please remember to also change the reconstruction accordingly, if you
829 set "special" parameters here!
830
831 Parameters:
832 path (basf2.Path): path where the generator should be added
833 components (list(str)): list of geometry components to add in the
834 geometry module, or None for all components.
835 global_box_size (tuple(float, float, float)): sets global length, width
836 and height (in meters) in which to generate.
837 Default is ``[100, 100, 100]``
838 accept_box (tuple(float, float, float)): sets the size of the accept box in meter.
839 As a default it is set to ``[8.0, 8.0, 8.0]`` (the Belle II detector size).
840 keep_box (tuple(float, float, float)): sets the size of the keep box (keep box >= accept box).
841 geometry_xml_file (str): Name of the xml file to use for the geometry.
842 cosmics_data_dir (str): parameter CosmicDataDir for the cry module (absolute or relative to the basf2 repo).
843 setup_file (str): location of the cry.setup file (absolute or relative to the basf2 repo)
844 data_taking_period (str): The cosmics generation will be added using the
845 parameters, that where used in this period of data taking. The
846 periods can be found in ``cdc/cr/__init__.py``.
847 top_in_counter (bool): time of propagation from the hit point to the PMT in the trigger counter is subtracted
848 (assuming PMT is put at -z of the counter).
849 """
850
851 b2.B2FATAL('''The function "add_cosmics_generator()" is outdated and it is currently not working: please replace
852
853 add_cosmics_generator(path=path)
854
855with
856
857 path.add_module('CRYInput')
858
859in your steering file (the module parameter "acceptance" has to be set, see the module docummentation).''')
860
861 import cdc.cr as cosmics_setup
862
863 if global_box_size is None:
864 global_box_size = [100, 100, 100]
865 if accept_box is None:
866 accept_box = [8, 8, 8]
867 if keep_box is None:
868 keep_box = [8, 8, 8]
869
870 cosmics_setup.set_cdc_cr_parameters(data_taking_period)
871
872 if cosmics_setup.cosmics_period == "201607":
873 b2.B2FATAL("The data taking period 201607 is very special (geometry setup, PMTs etc). This is not handled "
874 "by this script! Please ask the CDC group, if you want to simulate this.")
875
876 if 'Gearbox' not in path:
877 override = [("/Global/length", str(global_box_size[0]), "m"),
878 ("/Global/width", str(global_box_size[1]), "m"),
879 ("/Global/height", str(global_box_size[2]), "m")]
880
881 if cosmics_setup.globalPhi:
882 override += [("/DetectorComponent[@name='CDC']//GlobalPhiRotation", str(cosmics_setup.globalPhi), "deg")]
883
884 path.add_module('Gearbox', override=override, fileName=geometry_xml_file,)
885
886 # detector geometry
887 if 'Geometry' not in path:
888 geometry = path.add_module('Geometry')
889 if components:
890 geometry.param('components', components)
891
892 cry = path.add_module('CRYInput')
893
894 # cosmic data input
895 cry.param('CosmicDataDir', b2.find_file(cosmics_data_dir))
896
897 # user input file
898 cry.param('SetupFile', b2.find_file(setup_file))
899
900 # acceptance half-lengths - at least one particle has to enter that box to use that event
901 cry.param('acceptLength', accept_box[0])
902 cry.param('acceptWidth', accept_box[1])
903 cry.param('acceptHeight', accept_box[2])
904 cry.param('maxTrials', 100000)
905
906 # keep half-lengths - all particles that do not enter the box are removed (keep box >= accept box)
907 # default was 6.0
908 cry.param('keepLength', keep_box[0])
909 cry.param('keepWidth', keep_box[1])
910 cry.param('keepHeight', keep_box[2])
911
912 # minimal kinetic energy - all particles below that energy are ignored
913 cry.param('kineticEnergyThreshold', 0.01)
914
915 # TODO: I still do not fully understand, when the cosmics selector is needed and when not
916 if cosmics_setup.cosmics_period not in ["normal", "gcr2017"]:
917 # Selector module.
918 cosmics_selector = b2.register_module('CDCCosmicSelector',
919 lOfCounter=cosmics_setup.lengthOfCounter,
920 wOfCounter=cosmics_setup.widthOfCounter,
921 xOfCounter=cosmics_setup.triggerPos[0],
922 yOfCounter=cosmics_setup.triggerPos[1],
923 zOfCounter=cosmics_setup.triggerPos[2],
924 phiOfCounter=0.,
925 TOP=top_in_counter,
926 propSpeed=cosmics_setup.lightPropSpeed,
927 TOF=1,
928 cryGenerator=True
929 )
930
931 path.add_module(cosmics_selector)
932
933 empty_path = b2.create_path()
934 cosmics_selector.if_false(empty_path)
935
936
937def add_treps_generator(path, finalstate='', useDiscreteAndSortedW=False, eventType=''):
938 """
939 Add TREPS generator to produce hadronic two-photon processes.
940
941 Parameters:
942 path (basf2.Path): path where the generator should be added
943 finalstate(str): "e+e-pi+pi-", "e+e-K+K-" or "e+e-ppbar"
944 useDiscreteAndSortedW(bool): if True, wListTableFile is used for discrete and sorted W. evtNumList must be set proper value.
945 eventType (str) : event type information
946 """
947
948 if finalstate == 'e+e-pi+pi-':
949 parameterFile = b2.find_file('generators/treps/data/parameterFiles/treps_par_pipi.dat')
950 differentialCrossSectionFile = b2.find_file('generators/treps/data/differentialCrossSectionFiles/pipidcs.dat')
951 wListTableFile = b2.find_file('generators/treps/data/wListFiles/wlist_table_pipi.dat')
952 elif finalstate == 'e+e-K+K-':
953 parameterFile = b2.find_file('generators/treps/data/parameterFiles/treps_par_kk.dat')
954 differentialCrossSectionFile = b2.find_file('generators/treps/data/differentialCrossSectionFiles/kkdcs.dat')
955 wListTableFile = b2.find_file('generators/treps/data/wListFiles/wlist_table_kk.dat')
956 elif finalstate == 'e+e-ppbar':
957 parameterFile = b2.find_file('generators/treps/data/parameterFiles/treps_par_ppbar.dat')
958 differentialCrossSectionFile = b2.find_file('generators/treps/data/differentialCrossSectionFiles/ppbardcs.dat')
959 wListTableFile = b2.find_file('generators/treps/data/wListFiles/wlist_table_ppbar.dat')
960 else:
961 b2.B2FATAL("add_treps_generator final state not supported: {}".format(finalstate))
962
963 # use TREPS to generate two-photon events.
964 path.add_module(
965 'TrepsInput',
966 ParameterFile=parameterFile,
967 DifferentialCrossSectionFile=differentialCrossSectionFile,
968 WListTableFile=wListTableFile,
969 UseDiscreteAndSortedW=useDiscreteAndSortedW,
970 MaximalQ2=1.0,
971 MaximalAbsCosTheta=1.01,
972 ApplyCosThetaCutCharged=True,
973 MinimalTransverseMomentum=0,
974 ApplyTransverseMomentumCutCharged=True,
975 eventType=eventType,
976 )
977
def load(filename)
Definition: pdg.py:122
def get(name)
Definition: pdg.py:48