11 from .
import utilities
12 from .minimal
import MinimalRun
20 return logging.getLogger(__name__)
27 """Read generated events or generate new events"""
30 description =
"Simulate events using various generator and detector setups from command line."
35 generator_module =
None
37 detector_setup =
"Default"
43 disable_deltas =
False
45 simulation_output =
None
48 """Convert command-line arguments to basf2 argument list"""
51 setup_argument_group = argument_parser.add_argument_group(
"Detector setup arguments")
52 setup_argument_group.add_argument(
55 dest=
'detector_setup',
56 default=argparse.SUPPRESS,
57 metavar=
'DETECTOR_SETUP_NAME',
59 help=(
'Name of the detector setup to be used')
62 setup_argument_group.add_argument(
67 default=argparse.SUPPRESS,
70 help=(
'Overrides the components of the detector setup')
73 generator_argument_group = argument_parser.add_argument_group(
"Generator arguments")
74 generator_argument_group.add_argument(
77 dest=
'generator_module',
78 default=argparse.SUPPRESS,
79 metavar=
'GENERATOR_NAME',
81 help=
'Name module or short name of the generator to be used.',
84 simulation_argument_group = argument_parser.add_argument_group(
"Simulation arguments")
85 simulation_argument_group.add_argument(
91 metavar=
'BACKGROUND_DIRECTORY',
92 help=
'Path to folder of files or to a file containing the background to be used. ' +
93 'Can be given multiple times.',
96 simulation_argument_group.add_argument(
99 help=
'Disable the generation of delta rays in the simulation'
102 simulation_argument_group.add_argument(
104 '--simulation-output',
108 dest=
'simulation_output',
109 help=
'Only generate and simulate the events and write them to the given output file. Skip rest of the path.'
112 return argument_parser
115 """Configure for basf2 job; disable ROOT input if simulating events"""
118 get_logger().info(
"Requested to simulation run. Deactivate input file")
123 """Run the basf2 job"""
129 path = ReadOrGenerateEventsRun.create_path(self)
133 """Create and configure the basf2 path"""
137 path.add_module(
"Gearbox")
138 path.add_module(
"Geometry", useDB=
True)
141 detector_setup_function = detector_setups_by_short_name[detector_setup]
142 components = detector_setup_function(path)
152 add_evtgen_generator(path, dec_file_path)
155 utilities.extend_path(path,
157 generators_by_short_name,
158 allow_function_import=
True)
162 bkg_file_paths = get_bkg_file_paths(self.
bkg_files)
165 components=components,
166 bkgfiles=bkg_file_paths)
169 adjustments.disable_deltas(path)
174 raise RuntimeError(
'Need at least one of root_input_file,'
175 ' generator_module or bkg_files specified.')
178 raise RuntimeError(
"Could not find file " + str(self.
root_input_file) +
". Generate it with -- -so?")
182 root_output_module = path.add_module(
'RootOutput',
189 """Generate events using the EvtGen generator"""
191 generator_module =
"EvtGenInput"
198 electron_pdg_code = 11
213 proton_pdg_code = 2212
216 def add_single_gun_generator(path):
217 """Add ParticleGun with a single muon"""
218 path.add_module(
"ParticleGun",
219 pdgCodes=[muon_pdg_code, -muon_pdg_code],
222 momentumGeneration=
'inversePt',
223 momentumParams=[0.6, 1.4],
224 thetaGeneration=
'uniform',
225 thetaParams=[17., 150.])
228 def add_transverse_gun_generator(path):
229 """Add ParticleGun to illuminate a region of the phase space with low efficiency"""
230 path.add_module(
"ParticleGun",
231 pdgCodes=[muon_pdg_code, -muon_pdg_code],
234 momentumGeneration=
'inversePt',
235 momentumParams=[0.275, 0.276],
236 thetaGeneration=
'uniform',
237 thetaParams=[89., 91.])
240 def add_simple_gun_generator(path):
241 """Add ParticleGun firing 10 muons at medium energy"""
242 path.add_module(
"ParticleGun",
243 pdgCodes=[muon_pdg_code, -muon_pdg_code],
246 momentumGeneration=
'inversePt',
247 momentumParams=[0.6, 1.4],
248 thetaGeneration=
'uniform')
251 def add_low_gun_generator(path):
252 """Add ParticleGun firing 10 muons at low energy"""
253 path.add_module(
"ParticleGun",
254 pdgCodes=[muon_pdg_code, -muon_pdg_code],
257 momentumGeneration=
'inversePt',
258 momentumParams=[0.4, 0.8],
259 thetaGeneration=
'uniform')
262 def add_gun_generator(path):
263 """Add ParticleGun firing 10 muons with wide energy range"""
264 path.add_module(
"ParticleGun",
265 pdgCodes=[muon_pdg_code, -muon_pdg_code],
268 momentumGeneration=
'inversePt',
269 thetaGeneration=
'uniform',
270 thetaParams=[17., 150.])
273 def add_eloss_gun_generator(path):
274 """Add ParticleGun particle gun for energy loss estimations"""
275 path.add_module(
"ParticleGun",
288 momentumParams=[0.3, 2],
291 thetaGeneration=
'uniform',
293 thetaParams=[89., 91],
297 def add_forward_gun_generator(path):
298 """Add ParticleGun with one muon in rather forward direction"""
299 path.add_module(
"ParticleGun",
300 pdgCodes=[muon_pdg_code, -muon_pdg_code],
303 momentumGeneration=
'inversePt',
304 thetaGeneration=
'uniform',
305 thetaParams=[30., 31.])
308 def add_evtgen_generator(path, dec_file_path=None):
309 """Add Y4S generator"""
312 path.add_module(
"EvtGenInput", userDECFile=dec_file_path)
314 path.add_module(
"EvtGenInput")
317 def add_cosmics_generator(path):
318 """Add simple cosmics generator"""
322 def add_sector_tb_generator(path, sector=1):
323 phiBounds = (240 + 60.0 * sector % 360.0, 300 + 60.0 * sector % 360.0)
324 path.add_module(
"ParticleGun",
325 pdgCodes=[muon_pdg_code, -muon_pdg_code],
328 momentumGeneration=
'uniform',
329 momentumParams=[2.0, 4.0],
330 phiGeneration=
'uniform',
332 thetaGeneration=
'uniform',
333 thetaParams=[70., 110.])
336 def add_cosmics_tb_generator(path):
337 """Add simple cosmics generator resembling the test beam setup"""
338 path.add_module(
"Cosmics",
349 cosmics_selector = path.add_module(
'CDCCosmicSelector',
358 cosmics_selector.if_false(basf2.create_path())
361 def add_cry_tb_generator(path):
362 """Add cry generator resembling the test beam setup"""
364 keep_box=[0.7, 0.3, 0.3],
365 pre_general_run_setup=
"normal")
368 def add_no_generator(path):
369 """Add no generator for e.g. background only studies"""
375 generators_by_short_name = {
376 'single_gun': add_single_gun_generator,
377 'transverse_gun': add_transverse_gun_generator,
378 'simple_gun': add_simple_gun_generator,
379 'low_gun': add_low_gun_generator,
380 'forward_gun': add_forward_gun_generator,
381 'gun': add_gun_generator,
382 'eloss_gun': add_eloss_gun_generator,
383 'generic': add_evtgen_generator,
384 "EvtGenInput": add_evtgen_generator,
385 'cosmics': add_cosmics_generator,
386 'cosmics_tb': add_cosmics_tb_generator,
387 'cry_tb': add_cry_tb_generator,
388 'sector_tb': add_sector_tb_generator,
389 'bkg': add_no_generator,
390 'none': add_no_generator,
394 valid_generator_short_names = list(generators_by_short_name.keys())
399 def setup_default_detector(path):
403 def setup_tracking_detector(path):
404 components = [
"BeamPipe",
"PXD",
"SVD",
"CDC",
"MagneticField"]
406 (
"/DetectorComponent[@name='MagneticField']//Component[@type='3d'][2]/ExcludeRadiusMax",
410 adjustments.adjust_module(path,
"Gearbox", override=override)
411 adjustments.adjust_module(path,
"Geometry", components=components)
415 def setup_tracking_detector_constant_b(path):
416 components = [
"BeamPipe",
"PXD",
"SVD",
"CDC",
"MagneticFieldConstant4LimitedRCDC"]
417 adjustments.adjust_module(path,
"Geometry", components=components)
421 def setup_cdc_cr_test(path):
425 (
"/Global/length",
"8.",
"m"),
426 (
"/Global/width",
"8.",
"m"),
427 (
"/Global/height",
"1.5",
"m"),
430 (
"/DetectorComponent[@name='CDC']//t0FileName",
"t0.dat",
""),
431 (
"/DetectorComponent[@name='CDC']//xtFileName",
"xt_noB_v1.dat",
""),
432 (
"/DetectorComponent[@name='CDC']//GlobalPhiRotation",
"1.875",
"deg"),
436 adjustments.adjust_module(path,
"Gearbox", override=override)
437 adjustments.adjust_module(path,
"Geometry", components=components)
441 def setup_cdc_top_test(path):
446 (
"/Global/length",
"8.",
"m"),
447 (
"/Global/width",
"8.",
"m"),
448 (
"/Global/height",
"1.5",
"m"),
451 (
"/DetectorComponent[@name='CDC']//t0FileName",
"t0.dat",
""),
452 (
"/DetectorComponent[@name='CDC']//xtFileName",
"xt_noB_v1.dat",
""),
454 (
"/DetectorComponent[@name='CDC']//GlobalPhiRotation",
"1.875",
"deg"),
455 (
"/DetectorComponent[@name='MagneticField']//Component/Z",
"0",
""),
458 adjustments.adjust_module(path,
"Gearbox",
460 fileName=
"geometry/CDCcosmicTests.xml"
463 adjustments.adjust_module(path,
"Geometry", components=components)
466 detector_setups_by_short_name = {
467 "Default": setup_default_detector,
468 'TrackingDetector': setup_tracking_detector,
469 'TrackingDetectorConstB': setup_tracking_detector_constant_b,
470 'CDCCRTest': setup_cdc_cr_test,
471 'CDCTOPTest': setup_cdc_top_test,
478 def is_bkg_file(bkg_file_path):
479 """Test if a file path points to a file containing background mixins.
487 Simple test only checks if file exists and ends with ".root"
489 return os.path.isfile(bkg_file_path)
and bkg_file_path.endswith(
'.root')
492 def get_bkg_file_paths(bkg_dir_or_file_paths):
493 """Unpacks the content of a single or a list of directories and/or files filtering for
494 files containing background mixins.
498 bkg_dir_or_file_paths : string or iterable of strings
499 Single file or single directory in which background files are located or
500 a list of files and/or directories.
505 A list of paths to individual background files.
508 if isinstance(bkg_dir_or_file_paths, str):
509 bkg_dir_or_file_path = bkg_dir_or_file_paths
510 bkg_dir_or_file_paths = [bkg_dir_or_file_path]
513 for bkg_dir_or_file_path
in bkg_dir_or_file_paths:
514 if is_bkg_file(bkg_dir_or_file_path):
515 bkg_file_path = bkg_dir_or_file_path
516 result.append(bkg_file_path)
517 elif os.path.isdir(bkg_dir_or_file_path):
519 bkg_dir_path = bkg_dir_or_file_path
520 bkg_dir_contents = os.listdir(bkg_dir_path)
521 for dir_or_file_name
in bkg_dir_contents:
522 dir_or_file_path = os.path.join(bkg_dir_path, dir_or_file_name)
523 if is_bkg_file(dir_or_file_path):
524 bkg_file_path = dir_or_file_path
525 result.append(bkg_file_path)