HPS-MC
 
Loading...
Searching...
No Matches
generators.py
Go to the documentation of this file.
1"""! @package generators
2Event generation tools."""
3
4import os
5import shutil
6import glob
7import gzip
8import logging
9
10from hpsmc.component import Component
11
12
14 """! Event generator base class."""
15
16 def __init__(self, name, command=None, **kwargs):
17 Component.__init__(self, name, command=command, description='', **kwargs)
18
20 return ['nevents']
21
22 def get_install_dir(self):
23 if os.getenv("HPSMC_DIR") is None:
24 raise Exception("HPSMC_DIR is not set!")
25 return "{}/share/generators".format(os.getenv("HPSMC_DIR", None))
26
27
29 """!
30 Run the EGS5 event generator to produce a StdHep file.
31
32 Required parameters are **seed**, **target_thickness**, **beam_energy**, **num_electrons** \n
33 Optional parameters are: **bunches**
34 """
35
36 def __init__(self, name='', **kwargs):
37
38 self.bunches = 5e5
39
40 self.target_thickness = None
41
42 self.egs5_dir = None
43
44 self.beam_energy = None
45
46 self.num_electrons = None
47 EventGenerator.__init__(self, name, "egs5_" + name, **kwargs)
48
49 def get_install_dir(self):
50 """! Get installation directory."""
51 return EventGenerator.get_install_dir(self) + "/egs5"
52
53 def setup(self):
54 """! Setup of egs5 event generator."""
55 EventGenerator.setup(self)
56
57 if self.egs5_dir is None:
59 self.logger.debug("Using EGS5 from install dir: " + self.egs5_dir)
60
61
62 self.egs5_data_dir = os.path.join(self.egs5_dir, "data")
63
64 self.egs5_config_dir = os.path.join(self.egs5_dir, "config")
65
66 self.logger.debug("egs5_data_dir=%s" % self.egs5_data_dir)
67 self.logger.debug("egs5_config_dir=%s" % self.egs5_config_dir)
68
69 if os.path.exists("data"):
70 os.unlink("data")
71 os.symlink(self.egs5_data_dir, "data")
72
73 if os.path.exists("pgs5job.pegs5inp"):
74 os.unlink("pgs5job.pegs5inp")
75 os.symlink(self.egs5_config_dir + "/src/esa.inp", "pgs5job.pegs5inp")
76
77 # Set target thickness from job parameter or use the default from run parameters
78 if self.target_thickness is not None:
80 self.logger.debug("Target thickness set from job param: {}".format(self.target_dz))
81 else:
82 raise Exception("Target thickness not set!")
83
84 ebeam = self.beam_energy
85 electrons = int(self.num_electrons * self.bunches)
86
87 # seed_data = "%d %f %f %d" % (self.seed, self.target_dz, ebeam, electrons)
88 seed_data = " ".join(str(item) for item in [self.seed, self.target_dz, ebeam, electrons])
89 self.logger.debug("Seed data (seed, target_dz, ebeam, electrons): {}".format(seed_data))
90 seed_file = open("seed.dat", 'w')
91 seed_file.write(seed_data)
92 seed_file.close()
93
94 def output_files(self):
95 """! Generate output file name.
96 @return moller.stdhep if name of generator contains moller; beam.stdhep else"""
97 # Output file for Moller generation
98 if 'moller' in self.name:
99 return ['moller.stdhep']
100 # Output file for beam generation
101 return ['beam.stdhep']
102
103 def execute(self, log_out, log_err):
104 """! Execute event generator.
105 @param log_out name of log file for output
106 @param log_err name of log file for error
107 """
108 EventGenerator.execute(self, log_out, log_err)
109 if 'moller' not in self.name:
110 src = os.path.join(self.rundir, 'brems.stdhep')
111 dest = os.path.join(self.rundir, self.output_filesoutput_files()[0])
112 self.logger.debug("Copying '%s' to '%s'" % (src, dest))
113 shutil.copy(src, dest)
114
116 """!
117 Return required parameters.
118
119 Required parameters are **seed**, **target_thickness**, **beam_energy**, **num_electrons**
120 """
121 return ['seed', 'target_thickness', 'beam_energy', 'num_electrons']
122
124 """!
125 Return optional parameters.
126
127 Optional parameters are: **bunches**
128 """
129 return ['bunches']
130
131 # def required_config(self):
132 # return ['egs5_dir']
133
134
136 """! Target processing and conversion of LHE files to StdHep using EGS5."""
137
138 def __init__(self, name="lhe_v1", **kwargs):
139 EGS5.__init__(self, name, **kwargs)
140
141 if self.namename not in ["lhe_v1", "lhe_rad", "lhe_prompt", "lhe_uniform", "lhe_exponential"]:
142 raise Exception("The name '%s' is not valid for StdHepConverter tools." % self.namename)
143
144 def config(self, parser):
145 EGS5.config(self, parser)
146
147 def setup(self):
148 """! Setup egs5 generator.
149 Throws exception if input LHE file is missing."""
150 EGS5.setup(self)
151 if not len(self.inputsinputs):
152 raise Exception("Missing required input LHE file.")
153
154 def execute(self, log_out, log_err):
155 """! Execute converter.
156 Calls egs5 generator.
157
158 @param log_out name of log file for output
159 @param log_err name of log file for error
160 @return egs5 error code
161 """
162 input_file = self.inputsinputs[0]
163 base, ext = os.path.splitext(input_file)
164 if ext == ".lhe":
165 os.symlink(input_file, "egs5job.inp")
166 elif ext == ".gz":
167 with open("egs5job.inp", 'wb') as outfile:
168 with gzip.open(self.inputsinputs[0], 'rb') as infile:
169 outfile.write(infile.read())
170 else:
171 raise Exception('Input file has an unknown extension: %s' % input_file)
172 return EGS5.execute(self, log_out, log_err)
173
174 def output_files(self):
175 """! Converts *.lhe.gz and *.lhe to *.stdhep files."""
176 return [self.input_files()[0].replace(".lhe.gz", ".stdhep").replace(".lhe", ".stdhep")]
177
178
180 """!
181 Abstract class for MadGraph generators.
182
183 Required parameters are: **nevents**, **run_params** \n
184 Optional parameters are: **seed**, **param_card**, **apmass**, **map**, **mpid**, **mrhod**
185 """
186
187 def __init__(self, name, **kwargs):
188
189
190 self.madgraph_dir = None
191
192
193 self.param_card = "param_card.dat"
194
195 # Extra parameters for param card:
196 # map = mass of the A-prime
197 # mpid = mass of the dark pion
198 # mrhod = mass of the dark rho
199
200 self.apmass = None
201
202 self.map = None
203
204 self.Map = None
205
206 self.mpid = None
207
208 self.mrhod = None
209
210 self.mchi = None
211
212 self.dmchi = None
213
214 if 'event_types' in kwargs:
215
216 self.event_types = kwargs['event_types']
217 else:
218 self.event_types = ['unweighted', 'weighted']
219
220 EventGenerator.__init__(self, name, **kwargs)
221
222 def output_files(self):
223 """! Generate output file name."""
224 o = []
225 if 'unweighted' in self.event_types:
226 o.append(self.namename + "_unweighted_events.lhe.gz")
227 if 'weighted' in self.event_types:
228 o.append(self.namename + "_events.lhe.gz")
229 return o
230
231 def set_parameters(self, params):
232 """! Set parameters."""
233 Component.set_parameters(self, params)
234 self.run_card = "run_card_" + self.run_params + ".dat"
235 self.logger.debug("Set run card to '%s'" % self.run_card)
236
238 """!
239 Return required parameters.
240
241 Required parameters are: **nevents**, **run_params**
242 """
243 return ['nevents', 'run_params']
244
246 """!
247 Return optional parameters.
248
249 Optional parameters are: **seed**, **param_card**, **apmass**, **map**, **mpid**, **mrhod**, **Map**, **mchi**, **dmchi**
250 """
251 return ['seed', 'param_card', 'apmass', 'map', 'mpid', 'mrhod', 'Map', 'mchi', 'dmchi']
252
253 # def required_config(self):
254 # return ['madgraph_dir']
255
256 def make_run_card(self, run_card):
257 """! Make run card."""
258
259 self.logger.info("Making run card '%s' with nevents=%d, seed=%d" % (run_card, self.neventsnevents, self.seedseed))
260
261 with open(run_card, 'r') as cardin:
262 data = cardin.readlines()
263
264 for i in range(0, len(data)):
265 if "= nevents" in data[i]:
266 self.logger.debug("Setting nevents=%d in run card" % self.neventsnevents)
267 data[i] = " " + str(self.neventsnevents) + " = nevents ! Number of unweighted events requested" + '\n'
268 if "= iseed" in data[i]:
269 self.logger.debug("Setting seed=%d in run card" % self.seedseed)
270 data[i] = " " + str(self.seedseed) + " = iseed ! rnd seed (0=assigned automatically=default))" + '\n'
271
272 with open(run_card, 'w') as cardout:
273 cardout.writelines(data)
274
275 def make_param_card(self, param_card):
276 """! Make parameter card."""
277
278 self.logger.debug("Making param card '%s'" % param_card)
279
280 with open(param_card, 'r') as paramin:
281 data = paramin.readlines()
282
283 for i in range(0, len(data)):
284 if "APMASS" in data[i] and self.apmass is not None:
285 data[i] = " 622 %.7fe-03 # APMASS" % (self.apmass) + '\n'
286 self.logger.debug("APMASS in param card set to %d" % self.apmass)
287 if "MAp" in data[i] and "622" in data[i] and self.apmass is not None:
288 data[i] = " 622 %.7fe-03 # MAp" % (self.apmass) + '\n'
289 if "map" in data[i] and self.map is not None:
290 data[i] = " 622 %.7fe-03 # map" % (self.map) + '\n'
291 if "mpid" in data[i] and self.mpid is not None:
292 data[i] = " 624 %.7fe-03 # mpid" % (self.mpid) + '\n'
293 if "mrhod" in data[i] and self.mrhod is not None:
294 data[i] = " 625 %.7fe-03 # mrhod" % (self.mrhod) + '\n'
295 if "Map" in data[i] and "ap :" not in data[i] and self.Map is not None:
296 data[i] = " 1 %.7e # Map\n" % (self.Map/1000)
297 if "Mchi" in data[i] and "dMchi" not in data[i] and self.mchi is not None:
298 data[i] = " 1 %.7e # Mchi\n" % (self.mchi/1000)
299 if "dMchi" in data[i] and "Mchi/2" not in data[i] and self.dmchi is not None:
300 data[i] = " 2 %.7e # dMchi" % (self.dmchi/1000)
301
302 with open(param_card, 'w') as paramout:
303 paramout.writelines(data)
304
305 def cmd_args(self):
306 """! Return command arguments."""
307 return ["0", self.namename]
308
309 def execute(self, log_out, log_err):
310 """! Execute MadGraph generator.
311 @param log_out name of log file for output
312 @param log_err name of log file for error
313 @return error code
314 """
315 os.chdir(os.path.dirname(self.commandcommand))
316 # need python3.7 for MG5, but s3df only has python3.6 for now; python2 works though
317 # if "WAB" in self.name:
318 # self.command = "python2 " + self.command
319 self.logger.debug("Executing '%s' from '%s'" % (self.namename, os.getcwd()))
320 return Component.execute(self, log_out, log_err)
321
322 def setup(self):
323 """! Setup event generator."""
324 EventGenerator.setup(self)
325
326 if self.madgraph_dir is None:
327 self.madgraph_dir = self.get_install_dir()
328 self.logger.debug("Using Madgraph from install dir: " + self.madgraph_dir)
329
330 if self.namename == 'ap' and self.apmass is None:
331 raise Exception("Missing apmass param for AP generation.")
332
333
334class MG4(MG):
335 """! Run the MadGraph 4 event generator."""
336
337
338 dir_map = {"BH": "BH/MG_mini_BH/apBH",
339 "RAD": "RAD/MG_mini_Rad/apRad",
340 "TM": "TM/MG_mini/ap",
341 "ap": "ap/MG_mini/ap",
342 "trigg": "trigg/MG_mini_Trigg/apTri",
343 "tritrig": "tritrig/MG_mini_Tri_W/apTri",
344 "wab": "wab/MG_mini_WAB/AP_6W_XSec2_HallB"}
345
346 def __init__(self, name='ap', **kwargs):
347
348 MG.__init__(self, name, **kwargs)
349
350 if self.namenamename not in MG4.dir_map:
351 raise Exception("The name '%s' is not valid for MG4." % self.namenamename)
352
354 """! Get installation directory of MadGraph4."""
355 return EventGenerator.get_install_dir(self) + "/madgraph4/src"
356
357 def setup(self):
358 """! Setup MadGraph4 generator."""
359 MG.setup(self)
360
361 proc_dirs = MG4.dir_map[self.namenamename].split(os.sep)
362 src = os.path.join(self.madgraph_dir, proc_dirs[0], proc_dirs[1])
363 dest = proc_dirs[1]
364 self.logger.debug("Copying '%s' to '%s'" % (src, dest))
365 shutil.copytree(src, dest, symlinks=True)
366
367 self.event_dir = os.path.join(self.rundir, proc_dirs[1], proc_dirs[2], "Events")
368 if not os.path.isdir(self.event_dir):
369 os.makedirs(self.event_dir)
370
371 self.commandcommandcommand = os.path.join(os.getcwd(), proc_dirs[1], proc_dirs[2], "bin", "generate_events")
372 self.logger.debug("Command set to '%s'" % self.commandcommandcommand)
373
374 run_card_src = os.path.join(self.madgraph_dir, proc_dirs[0], self.run_card)
375 run_card_dest = os.path.join(self.rundir, proc_dirs[1], proc_dirs[2], "Cards", "run_card.dat")
376 self.logger.debug("Copying run card from '%s' to '%s'" % (run_card_src, run_card_dest))
377 shutil.copyfile(run_card_src, run_card_dest)
378
379 self.make_run_card(run_card_dest)
380
381 param_card_src = os.path.join(self.madgraph_dir, proc_dirs[0], self.param_card)
382 param_card_dest = os.path.join(self.rundir, proc_dirs[1], proc_dirs[2], "Cards", "param_card.dat")
383 self.logger.debug("Copying param card from '%s' to '%s'" % (param_card_src, param_card_dest))
384 shutil.copyfile(param_card_src, param_card_dest)
385
386 self.make_param_card(param_card_dest)
387
388 def execute(self, log_out, log_err):
389 """! Execute MadGraph4 generator.
390 @param log_out name of log file for output
391 @param log_err name of log file for error
392 @return error code
393 """
394 returncode = MG.execute(self, log_out, log_err)
395 lhe_files = glob.glob(os.path.join(self.event_dir, "*.lhe.gz"))
396 for f in lhe_files:
397 dest = os.path.join(self.rundir, os.path.basename(f))
398 self.logger.debug("Copying '%s' to '%s'" % (f, dest))
399 shutil.copy(f, dest)
400 os.chdir(self.rundir)
401 return returncode
402
403
404class MG5(MG):
405 """! Run the MadGraph 5 event generator."""
406
407
408 dir_map = {"BH": "BH",
409 "RAD": "RAD",
410 "tritrig": "tritrig",
411 "simp": "simp",
412 "simp-3body": "simp-3body",
413 "idm": "idm",
414 "WAB": "WAB",
415 "ap": "ap"
416 }
417
418 def __init__(self, name='tritrig', **kwargs):
419
420 MG.__init__(self, name, **kwargs)
421
422 if self.namenamename not in MG5.dir_map:
423 raise Exception("The name '%s' is not valid for MG5." % self.namenamename)
424
426 """! Get installation directory of MadGraph5."""
427 return EventGenerator.get_install_dir(self) + "/madgraph5/src"
428
429 def setup(self):
430 """! Setup MadGraph5 generator."""
431 MG.setup(self)
432
433 self.proc_dir = MG5.dir_map[self.namenamename]
434 self.event_dir = os.path.join(self.rundir, self.proc_dir, "Events", self.proc_dir)
435
436 src = os.path.join(self.madgraph_dir, self.proc_dir)
437 dest = os.path.join(self.rundir, self.proc_dir)
438 self.logger.debug("Copying '%s' to '%s'" % (src, dest))
439 shutil.copytree(src, dest, symlinks=True)
440
441
442 """
443 input_dir = os.path.join(self.madgraph_dir, "input")
444 dest_input_dir = os.path.join(self.rundir, self.proc_dir, "input")
445 self.logger.info("Copying '%s' to '%s'" % (input_dir, dest_input_dir))
446 shutil.copytree(input_dir, dest_input_dir)
447 """
448
449 self.commandcommandcommand = os.path.join(dest, "bin", "generate_events")
450 self.logger.debug("Command set to '%s'" % self.commandcommandcommand)
451
452 run_card_src = os.path.join(src, "Cards", self.run_card)
453 run_card_dest = os.path.join(dest, "Cards", "run_card.dat")
454 self.logger.debug("Copying run card from '%s' to '%s'" % (run_card_src, run_card_dest))
455 shutil.copyfile(run_card_src, run_card_dest)
456
457 self.make_run_card(run_card_dest)
458
459 param_card_src = os.path.join(src, "Cards", self.param_card)
460 param_card_dest = os.path.join(dest, "Cards", "param_card.dat")
461 self.logger.debug("Copying param card from '%s' to '%s'" % (param_card_src, param_card_dest))
462 shutil.copyfile(param_card_src, param_card_dest)
463
464 self.make_param_card(param_card_dest)
465
466 def execute(self, log_out, log_err):
467 """! Execute MadGraph5 generator.
468 @param log_out name of log file for output
469 @param log_err name of log file for error
470 @return error code
471 """
472 os.chdir(os.path.dirname(self.commandcommandcommand))
473 # need python3.7 for MG5, but s3df only has python3.6 for now; python2 works though
474 if "WAB" or "ap" in self.namenamename:
475 self.commandcommandcommand = "python2 " + self.commandcommandcommand
476 self.logger.debug("Executing '%s' from '%s'" % (self.namenamename, os.getcwd()))
477 returncode = Component.execute(self, log_out, log_err)
478
479 # returncode = MG.execute(self, log_out, log_err)
480 lhe_files = glob.glob(os.path.join(self.event_dir, "*.lhe.gz"))
481 for f in lhe_files:
482 dest = os.path.join(self.rundir, '%s_%s' % (self.namenamename, os.path.basename(f)))
483 self.logger.debug("Copying '%s' to '%s'" % (f, dest))
484 shutil.copy(f, dest)
485 os.chdir(self.rundir)
486 return returncode
Base class for components in a job.
Definition component.py:15
output_files(self)
Return a list of output files created by this component.
Definition component.py:206
input_files(self)
Get a list of input files for this component.
Definition component.py:202
Run the EGS5 event generator to produce a StdHep file.
Definition generators.py:28
egs5_dir
egs5 installation directory
Definition generators.py:42
execute(self, log_out, log_err)
Execute event generator.
egs5_data_dir
data directory
Definition generators.py:62
output_files(self)
Generate output file name.
Definition generators.py:94
beam_energy
beam energy in MeV
Definition generators.py:44
optional_parameters(self)
Return optional parameters.
target_thickness
target thickness in $\mu$m,
Definition generators.py:40
required_parameters(self)
Return required parameters.
setup(self)
Setup of egs5 event generator.
Definition generators.py:53
egs5_config_dir
config directory
Definition generators.py:64
num_electrons
number of electrons
Definition generators.py:46
get_install_dir(self)
Get installation directory.
Definition generators.py:49
__init__(self, name='', **kwargs)
Definition generators.py:36
Event generator base class.
Definition generators.py:13
required_parameters(self)
Return a list of required parameters.
Definition generators.py:19
__init__(self, name, command=None, **kwargs)
Definition generators.py:16
Run the MadGraph 4 event generator.
execute(self, log_out, log_err)
Execute MadGraph4 generator.
setup(self)
Setup MadGraph4 generator.
__init__(self, name='ap', **kwargs)
get_install_dir(self)
Get installation directory of MadGraph4.
Run the MadGraph 5 event generator.
execute(self, log_out, log_err)
Execute MadGraph5 generator.
__init__(self, name='tritrig', **kwargs)
setup(self)
Setup MadGraph5 generator.
get_install_dir(self)
Get installation directory of MadGraph5.
Abstract class for MadGraph generators.
execute(self, log_out, log_err)
Execute MadGraph generator.
output_files(self)
Generate output file name.
make_run_card(self, run_card)
Make run card.
optional_parameters(self)
Return optional parameters.
event_types
event types: weighted or unweighted
make_param_card(self, param_card)
Make parameter card.
mpid
dark pion mass
required_parameters(self)
Return required parameters.
setup(self)
Setup event generator.
mchi
average dark fermion mass when running idm
apmass
A-prime mass.
set_parameters(self, params)
Set parameters.
param_card
Default name of param card.
map
A-prime mass.
mrhod
dark rho mass
__init__(self, name, **kwargs)
madgraph_dir
Install dir or user config will be used for this.
cmd_args(self)
Return command arguments.
dmchi
difference between dark fermion masses when running idm
Map
A-prime mass.
Target processing and conversion of LHE files to StdHep using EGS5.
execute(self, log_out, log_err)
Execute converter.
output_files(self)
Converts *.lhe.gz and *.lhe to *.stdhep files.
setup(self)
Setup egs5 generator.
config(self, parser)
Automatic configuration.
__init__(self, name="lhe_v1", **kwargs)