27 return logging.getLogger(__name__)
35 """Read generated events or generate new events"""
38 description =
"Simulate events using various generator and detector setups from command line."
43 generator_module =
None
45 detector_setup =
"Default"
51 disable_deltas =
False
53 simulation_output =
None
56 """Convert command-line arguments to basf2 argument list"""
59 setup_argument_group = argument_parser.add_argument_group(
"Detector setup arguments")
60 setup_argument_group.add_argument(
63 dest=
'detector_setup',
64 default=argparse.SUPPRESS,
65 metavar=
'DETECTOR_SETUP_NAME',
67 help=(
'Name of the detector setup to be used')
70 setup_argument_group.add_argument(
75 default=argparse.SUPPRESS,
78 help=(
'Overrides the components of the detector setup')
81 generator_argument_group = argument_parser.add_argument_group(
"Generator arguments")
82 generator_argument_group.add_argument(
85 dest=
'generator_module',
86 default=argparse.SUPPRESS,
87 metavar=
'GENERATOR_NAME',
89 help=
'Name module or short name of the generator to be used.',
92 simulation_argument_group = argument_parser.add_argument_group(
"Simulation arguments")
93 simulation_argument_group.add_argument(
99 metavar=
'BACKGROUND_DIRECTORY',
100 help=
'Path to folder of files or to a file containing the background to be used. ' +
101 'Can be given multiple times.',
104 simulation_argument_group.add_argument(
107 help=
'Disable the generation of delta rays in the simulation'
110 simulation_argument_group.add_argument(
112 '--simulation-output',
116 dest=
'simulation_output',
117 help=
'Only generate and simulate the events and write them to the given output file. Skip rest of the path.'
120 return argument_parser
123 """Configure for basf2 job; disable ROOT input if simulating events"""
126 get_logger().info(
"Requested to simulation run. Deactivate input file")
131 """Run the basf2 job"""
137 path = ReadOrGenerateEventsRun.create_path(self)
141 """Create and configure the basf2 path"""
145 path.add_module(
"Gearbox")
146 path.add_module(
"Geometry", useDB=
True)
149 detector_setup_function = detector_setups_by_short_name[detector_setup]
150 components = detector_setup_function(path)
160 add_evtgen_generator(path, dec_file_path)
163 utilities.extend_path(path,
165 generators_by_short_name,
166 allow_function_import=
True)
170 bkg_file_paths = get_bkg_file_paths(self.
bkg_files)
173 components=components,
174 bkgfiles=bkg_file_paths)
177 adjustments.disable_deltas(path)
182 raise RuntimeError(
'Need at least one of root_input_file,'
183 ' generator_module or bkg_files specified.')
186 raise RuntimeError(
"Could not find file " + str(self.
root_input_file) +
". Generate it with -- -so?")
190 path.add_module(
'RootOutput',
197 """Generate events using the EvtGen generator"""
198 ## Use EvtGen for the event generator
199 generator_module = "EvtGenInput"
202# Default settings and shorthand names for generator with specific settings #
203#############################################################################
205# PDG code of an electorn
206electron_pdg_code = 11
220# PDG code of a protons
221proton_pdg_code = 2212
224def add_single_gun_generator(path):
225 """Add ParticleGun with a single muon"""
226 path.add_module("ParticleGun",
227 pdgCodes=[muon_pdg_code, -muon_pdg_code],
230 momentumGeneration='inversePt',
231 momentumParams=[0.6, 1.4],
232 thetaGeneration='uniform',
233 thetaParams=[17., 150.])
236def add_transverse_gun_generator(path):
237 """Add ParticleGun to illuminate a region of the phase space with low efficiency"""
238 path.add_module("ParticleGun",
239 pdgCodes=[muon_pdg_code, -muon_pdg_code],
242 momentumGeneration='inversePt',
243 momentumParams=[0.275, 0.276],
244 thetaGeneration='uniform',
245 thetaParams=[89., 91.])
248def add_simple_gun_generator(path):
249 """Add ParticleGun firing 10 muons at medium energy"""
250 path.add_module("ParticleGun",
251 pdgCodes=[muon_pdg_code, -muon_pdg_code],
254 momentumGeneration='inversePt',
255 momentumParams=[0.6, 1.4],
256 thetaGeneration='uniform')
259def add_low_gun_generator(path):
260 """Add ParticleGun firing 10 muons at low energy"""
261 path.add_module("ParticleGun",
262 pdgCodes=[muon_pdg_code, -muon_pdg_code],
265 momentumGeneration='inversePt',
266 momentumParams=[0.4, 0.8],
267 thetaGeneration='uniform')
270def add_gun_generator(path):
271 """Add ParticleGun firing 10 muons with wide energy range"""
272 path.add_module("ParticleGun",
273 pdgCodes=[muon_pdg_code, -muon_pdg_code],
276 momentumGeneration='inversePt',
277 thetaGeneration='uniform',
278 thetaParams=[17., 150.])
281def add_eloss_gun_generator(path):
282 """Add ParticleGun particle gun for energy loss estimations"""
283 path.add_module("ParticleGun",
288 # -electron_pdg_code,
296 momentumParams=[0.3, 2],
299 thetaGeneration='uniform',
300 # thetaParams=[17., 150.],
301 thetaParams=[89., 91],
305def add_forward_gun_generator(path):
306 """Add ParticleGun with one muon in rather forward direction"""
307 path.add_module("ParticleGun",
308 pdgCodes=[muon_pdg_code, -muon_pdg_code],
311 momentumGeneration='inversePt',
312 thetaGeneration='uniform',
313 thetaParams=[30., 31.])
316def add_evtgen_generator(path, dec_file_path=None):
317 """Add Y4S generato
r"""
318 beamparameters.add_beamparameters(path, "Y4S")
320 path.add_module("EvtGenInput", userDECFile=dec_file_path)
322 path.add_module("EvtGenInput")
325def add_cosmics_generator(path):
326 """Add simple cosmics generato
r"""
327 generators.add_cosmics_generator(path)
330def add_sector_tb_generator(path, sector=1):
331 phiBounds = (240 + 60.0 * sector % 360.0, 300 + 60.0 * sector % 360.0)
332 path.add_module("ParticleGun",
333 pdgCodes=[muon_pdg_code, -muon_pdg_code],
336 momentumGeneration='uniform',
337 momentumParams=[2.0, 4.0],
338 phiGeneration='uniform',
340 thetaGeneration='uniform',
341 thetaParams=[70., 110.])
344def add_cosmics_tb_generator(path):
345 """Add simple cosmics generator resembling the test beam setup"""
346 path.add_module("Cosmics",
354 # Do not add time of propagation in the scintilator
357 cosmics_selector = path.add_module('CDCCosmicSelector',
366 cosmics_selector.if_false(basf2.create_path())
369def add_cry_tb_generator(path):
370 """Add cry generator resembling the test beam setup"""
371 generators.add_cosmics_generator(path, accept_box=[0.7, 0.3, 0.3],
372 keep_box=[0.7, 0.3, 0.3],
373 pre_general_run_setup="normal")
376def add_no_generator(path):
377 """Add no generator for e.g. background only studies"""
378 # Nothing to do here since the background files are included in the add_simulation
381# Generator module names hashed by shorthand menomics. Includes
382# None as a special value for background only simulation
383generators_by_short_name = {
384 'single_gun': add_single_gun_generator,
385 'transverse_gun': add_transverse_gun_generator,
386 'simple_gun': add_simple_gun_generator,
387 'low_gun': add_low_gun_generator,
388 'forward_gun': add_forward_gun_generator,
389 'gun': add_gun_generator,
390 'eloss_gun': add_eloss_gun_generator,
391 'generic': add_evtgen_generator,
392 "EvtGenInput": add_evtgen_generator, # <- requires beam parameters
393 'cosmics': add_cosmics_generator,
394 'cosmics_tb': add_cosmics_tb_generator,
395 'cry_tb': add_cry_tb_generator,
396 'sector_tb': add_sector_tb_generator,
397 'bkg': add_no_generator,
398 'none': add_no_generator,
401# Names of module names and short names of the generators usable in this script.
402valid_generator_short_names = list(generators_by_short_name.keys())
405# Memorandum of geometry setups #
406# ############################# #
407def setup_default_detector(path):
411def setup_tracking_detector(path):
412 components = ["BeamPipe", "PXD", "SVD", "CDC", "MagneticField"]
414 ("/DetectorComponent[@name='MagneticField']//Component[@type='3d'][2]/ExcludeRadiusMax",
415 "4.20", "m", ) # Remove the second component which is the magnetic field outside the tracking volume.
418 adjustments.adjust_module(path, "Gearbox", override=override)
419 adjustments.adjust_module(path, "Geometry", components=components)
423def setup_tracking_detector_constant_b(path):
424 components = ["BeamPipe", "PXD", "SVD", "CDC", "MagneticFieldConstant4LimitedRCDC"]
425 adjustments.adjust_module(path, "Geometry", components=components)
429def setup_cdc_cr_test(path):
432 # Reset the top volume to accommodate cosmics that can hit all parts of the detector
433 ("/Global/length", "8.", "m"),
434 ("/Global/width", "8.", "m"),
435 ("/Global/height", "1.5", "m"),
437 # Adjustments of the CDC setup
438 ("/DetectorComponent[@name='CDC']//t0FileName", "t0.dat", ""),
439 ("/DetectorComponent[@name='CDC']//xtFileName", "xt_noB_v1.dat", ""),
440 ("/DetectorComponent[@name='CDC']//GlobalPhiRotation", "1.875", "deg"),
441 # ("/DetectorComponent[@name='CDC']//bwFileName", "badwire_CDCTOP.dat", ""),
444 adjustments.adjust_module(path, "Gearbox", override=override)
445 adjustments.adjust_module(path, "Geometry", components=components)
449def setup_cdc_top_test(path):
452 # Reset the top volume: must be larger than the generated surface and higher than the detector
453 # It is the users responsibility to ensure a full angular coverage
454 ("/Global/length", "8.", "m"),
455 ("/Global/width", "8.", "m"),
456 ("/Global/height", "1.5", "m"),
458 # Adjustments of the CDC setup
459 ("/DetectorComponent[@name='CDC']//t0FileName", "t0.dat", ""),
460 ("/DetectorComponent[@name='CDC']//xtFileName", "xt_noB_v1.dat", ""),
461 # ("/DetectorComponent[@name='CDC']//bwFileName", "badwire_CDCTOP.dat", ""),
462 ("/DetectorComponent[@name='CDC']//GlobalPhiRotation", "1.875", "deg"),
463 ("/DetectorComponent[@name='MagneticField']//Component/Z", "0", ""),
466 adjustments.adjust_module(path, "Gearbox",
468 fileName="geometry/CDCcosmicTests.xml" # <- does something mysterious to the reconstruction...
471 adjustments.adjust_module(path, "Geometry", components=components)
475detector_setups_by_short_name = {
476 "Default": setup_default_detector,
477 'TrackingDetector': setup_tracking_detector,
478 'TrackingDetectorConstB': setup_tracking_detector_constant_b,
479 'CDCCRTest': setup_cdc_cr_test,
480 'CDCTOPTest': setup_cdc_top_test,
484# Heuristic to find background files #
485# ################################## #
487def is_bkg_file(bkg_file_path):
488 """Test if a file path points to a file containing background mixins.
496 Simple test only checks if file exists and ends with ".root"
498 return os.path.isfile(bkg_file_path) and bkg_file_path.endswith('.root')
501def get_bkg_file_paths(bkg_dir_or_file_paths):
502 """Unpacks the content of a single or a list of directories and/or files filtering for
503 files containing background mixins.
507 bkg_dir_or_file_paths : string or iterable of strings
508 Single file or single directory in which background files are located or
509 a list of files and/or directories.
514 A list of paths to individual background files.
517 if isinstance(bkg_dir_or_file_paths, str):
518 bkg_dir_or_file_path = bkg_dir_or_file_paths
519 bkg_dir_or_file_paths = [bkg_dir_or_file_path]
522 for bkg_dir_or_file_path in bkg_dir_or_file_paths:
523 if is_bkg_file(bkg_dir_or_file_path):
524 bkg_file_path = bkg_dir_or_file_path
525 result.append(bkg_file_path)
526 elif os.path.isdir(bkg_dir_or_file_path):
528 bkg_dir_path = bkg_dir_or_file_path
529 bkg_dir_contents = os.listdir(bkg_dir_path)
530 for dir_or_file_name in bkg_dir_contents:
531 dir_or_file_path = os.path.join(bkg_dir_path, dir_or_file_name)
532 if is_bkg_file(dir_or_file_path):
533 bkg_file_path = dir_or_file_path
534 result.append(bkg_file_path)
configure(self, arguments)
components
By default, do specific components.
str detector_setup
By default, use the default detector setup.
bool disable_deltas
By default, do not disable delta-ray generation.
simulation_output
By default, do no store the simulation output.
create_argument_parser(self, **kwds)
generator_module
By default, do not generate events.
list bkg_files
By default, no background overlay.
add_simulation(path, components=None, bkgfiles=None, bkgOverlay=True, forceSetPXDDataReduction=False, usePXDDataReduction=True, cleanupPXDDataReduction=True, generate_2nd_cdc_hits=False, simulateT0jitter=True, isCosmics=False, FilterEvents=False, usePXDGatedMode=False, skipExperimentCheckForBG=False, save_slow_pions_in_mc=False, save_all_charged_particles_in_mc=False)