HPS-MC
generators.py
Go to the documentation of this file.
1 """! @package generators
2 Event generation tools."""
3 
4 import os
5 import shutil
6 import glob
7 import gzip
8 import logging
9 
10 from 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.bunchesbunches = 5e5
39 
40  self.target_thicknesstarget_thickness = None
41 
42  self.egs5_diregs5_dir = None
43 
44  self.beam_energybeam_energy = None
45 
46  self.num_electronsnum_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_diregs5_dir is None:
58  self.egs5_diregs5_dir = self.get_install_dirget_install_dirget_install_dir()
59  self.loggerlogger.debug("Using EGS5 from install dir: " + self.egs5_diregs5_dir)
60 
61 
62  self.egs5_data_diregs5_data_dir = os.path.join(self.egs5_diregs5_dir, "data")
63 
64  self.egs5_config_diregs5_config_dir = os.path.join(self.egs5_diregs5_dir, "config")
65 
66  self.loggerlogger.debug("egs5_data_dir=%s" % self.egs5_data_diregs5_data_dir)
67  self.loggerlogger.debug("egs5_config_dir=%s" % self.egs5_config_diregs5_config_dir)
68 
69  if os.path.exists("data"):
70  os.unlink("data")
71  os.symlink(self.egs5_data_diregs5_data_dir, "data")
72 
73  if os.path.exists("pgs5job.pegs5inp"):
74  os.unlink("pgs5job.pegs5inp")
75  os.symlink(self.egs5_config_diregs5_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_thicknesstarget_thickness is not None:
79  self.target_dztarget_dz = self.target_thicknesstarget_thickness
80  self.loggerlogger.debug("Target thickness set from job param: {}".format(self.target_dztarget_dz))
81  else:
82  raise Exception("Target thickness not set!")
83 
84  ebeam = self.beam_energybeam_energy
85  electrons = int(self.num_electronsnum_electrons * self.bunchesbunches)
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.seedseed, self.target_dztarget_dz, ebeam, electrons])
89  self.loggerlogger.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.namename:
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.namename:
110  src = os.path.join(self.rundir, 'brems.stdhep')
111  dest = os.path.join(self.rundir, self.output_filesoutput_filesoutput_files()[0])
112  self.loggerlogger.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  """! Convert 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_filesinput_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_dirmadgraph_dir = None
191 
192 
193  self.param_cardparam_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.apmassapmass = None
201 
202  self.mapmap = None
203 
204  self.MapMap = None
205 
206  self.mpidmpid = None
207 
208  self.mrhodmrhod = None
209 
210  self.mchimchi = None
211 
212  self.dmchidmchi = None
213 
214  if 'event_types' in kwargs:
215 
216  self.event_typesevent_types = kwargs['event_types']
217  else:
218  self.event_typesevent_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_typesevent_types:
226  o.append(self.namenamename + "_unweighted_events.lhe.gz")
227  if 'weighted' in self.event_typesevent_types:
228  o.append(self.namenamename + "_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_cardrun_card = "run_card_" + self.run_params + ".dat"
235  self.loggerlogger.debug("Set run card to '%s'" % self.run_cardrun_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.loggerlogger.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.loggerlogger.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.loggerlogger.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.loggerlogger.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.apmassapmass is not None:
285  data[i] = " 622 %.7fe-03 # APMASS" % (self.apmassapmass) + '\n'
286  self.loggerlogger.debug("APMASS in param card set to %d" % self.apmassapmass)
287  if "map" in data[i] and self.mapmap is not None:
288  data[i] = " 622 %.7fe-03 # map" % (self.mapmap) + '\n'
289  if "mpid" in data[i] and self.mpidmpid is not None:
290  data[i] = " 624 %.7fe-03 # mpid" % (self.mpidmpid) + '\n'
291  if "mrhod" in data[i] and self.mrhodmrhod is not None:
292  data[i] = " 625 %.7fe-03 # mrhod" % (self.mrhodmrhod) + '\n'
293  if "Map" in data[i] and "ap :" not in data[i] and self.MapMap is not None:
294  data[i] = " 1 %.7e # Map\n" % (self.MapMap/1000)
295  if "Mchi" in data[i] and "dMchi" not in data[i] and self.mchimchi is not None:
296  data[i] = " 1 %.7e # Mchi\n" % (self.mchimchi/1000)
297  if "dMchi" in data[i] and "Mchi/2" not in data[i] and self.dmchidmchi is not None:
298  data[i] = " 2 %.7e # dMchi" % (self.dmchidmchi/1000)
299 
300  with open(param_card, 'w') as paramout:
301  paramout.writelines(data)
302 
303  def cmd_args(self):
304  """! Return command arguments."""
305  return ["0", self.namenamename]
306 
307  def execute(self, log_out, log_err):
308  """! Execute MadGraph generator.
309  @param log_out name of log file for output
310  @param log_err name of log file for error
311  @return error code
312  """
313  os.chdir(os.path.dirname(self.commandcommand))
314  self.loggerlogger.debug("Executing '%s' from '%s'" % (self.namenamename, os.getcwd()))
315  return Component.execute(self, log_out, log_err)
316 
317  def setup(self):
318  """! Setup event generator."""
319  EventGenerator.setup(self)
320 
321  if self.madgraph_dirmadgraph_dir is None:
322  self.madgraph_dirmadgraph_dir = self.get_install_dirget_install_dir()
323  self.loggerlogger.debug("Using Madgraph from install dir: " + self.madgraph_dirmadgraph_dir)
324 
325  if self.namenamename == 'ap' and self.apmassapmass is None:
326  raise Exception("Missing apmass param for AP generation.")
327 
328 
329 class MG4(MG):
330  """! Run the MadGraph 4 event generator."""
331 
332 
333  dir_map = {"BH": "BH/MG_mini_BH/apBH",
334  "RAD": "RAD/MG_mini_Rad/apRad",
335  "TM": "TM/MG_mini/ap",
336  "ap": "ap/MG_mini/ap",
337  "trigg": "trigg/MG_mini_Trigg/apTri",
338  "tritrig": "tritrig/MG_mini_Tri_W/apTri",
339  "wab": "wab/MG_mini_WAB/AP_6W_XSec2_HallB"}
340 
341  def __init__(self, name='ap', **kwargs):
342 
343  MG.__init__(self, name, **kwargs)
344 
345  if self.namenamename not in MG4.dir_map:
346  raise Exception("The name '%s' is not valid for MG4." % self.namenamename)
347 
348  def get_install_dir(self):
349  """! Get installation directory of MadGraph4."""
350  return EventGenerator.get_install_dir(self) + "/madgraph4/src"
351 
352  def setup(self):
353  """! Setup MadGraph4 generator."""
354  MG.setup(self)
355 
356  proc_dirs = MG4.dir_map[self.namenamename].split(os.sep)
357  src = os.path.join(self.madgraph_dirmadgraph_dir, proc_dirs[0], proc_dirs[1])
358  dest = proc_dirs[1]
359  self.loggerlogger.debug("Copying '%s' to '%s'" % (src, dest))
360  shutil.copytree(src, dest, symlinks=True)
361 
362  self.event_direvent_dir = os.path.join(self.rundir, proc_dirs[1], proc_dirs[2], "Events")
363  if not os.path.isdir(self.event_direvent_dir):
364  os.makedirs(self.event_direvent_dir)
365 
366  self.commandcommandcommand = os.path.join(os.getcwd(), proc_dirs[1], proc_dirs[2], "bin", "generate_events")
367  self.loggerlogger.debug("Command set to '%s'" % self.commandcommandcommand)
368 
369  run_card_src = os.path.join(self.madgraph_dirmadgraph_dir, proc_dirs[0], self.run_cardrun_card)
370  run_card_dest = os.path.join(self.rundir, proc_dirs[1], proc_dirs[2], "Cards", "run_card.dat")
371  self.loggerlogger.debug("Copying run card from '%s' to '%s'" % (run_card_src, run_card_dest))
372  shutil.copyfile(run_card_src, run_card_dest)
373 
374  self.make_run_cardmake_run_card(run_card_dest)
375 
376  param_card_src = os.path.join(self.madgraph_dirmadgraph_dir, proc_dirs[0], self.param_cardparam_card)
377  param_card_dest = os.path.join(self.rundir, proc_dirs[1], proc_dirs[2], "Cards", "param_card.dat")
378  self.loggerlogger.debug("Copying param card from '%s' to '%s'" % (param_card_src, param_card_dest))
379  shutil.copyfile(param_card_src, param_card_dest)
380 
381  self.make_param_cardmake_param_card(param_card_dest)
382 
383  def execute(self, log_out, log_err):
384  """! Execute MadGraph4 generator.
385  @param log_out name of log file for output
386  @param log_err name of log file for error
387  @return error code
388  """
389  returncode = MG.execute(self, log_out, log_err)
390  lhe_files = glob.glob(os.path.join(self.event_direvent_dir, "*.lhe.gz"))
391  for f in lhe_files:
392  dest = os.path.join(self.rundir, os.path.basename(f))
393  self.loggerlogger.debug("Copying '%s' to '%s'" % (f, dest))
394  shutil.copy(f, dest)
395  os.chdir(self.rundir)
396  return returncode
397 
398 
399 class MG5(MG):
400  """! Run the MadGraph 5 event generator."""
401 
402 
403  dir_map = {"BH": "BH",
404  "RAD": "RAD",
405  "tritrig": "tritrig",
406  "simp": "simp",
407  "simp-3body": "simp-3body",
408  "idm": "idm",
409  }
410 
411  def __init__(self, name='tritrig', **kwargs):
412 
413  MG.__init__(self, name, **kwargs)
414 
415  if self.namenamename not in MG5.dir_map:
416  raise Exception("The name '%s' is not valid for MG5." % self.namenamename)
417 
418  def get_install_dir(self):
419  """! Get installation directory of MadGraph5."""
420  return EventGenerator.get_install_dir(self) + "/madgraph5/src"
421 
422  def setup(self):
423  """! Setup MadGraph5 generator."""
424  MG.setup(self)
425 
426  self.proc_dirproc_dir = MG5.dir_map[self.namenamename]
427  self.event_direvent_dir = os.path.join(self.rundir, self.proc_dirproc_dir, "Events", self.proc_dirproc_dir)
428 
429  src = os.path.join(self.madgraph_dirmadgraph_dir, self.proc_dirproc_dir)
430  dest = os.path.join(self.rundir, self.proc_dirproc_dir)
431  self.loggerlogger.debug("Copying '%s' to '%s'" % (src, dest))
432  shutil.copytree(src, dest, symlinks=True)
433 
434 
435  """
436  input_dir = os.path.join(self.madgraph_dir, "input")
437  dest_input_dir = os.path.join(self.rundir, self.proc_dir, "input")
438  self.logger.info("Copying '%s' to '%s'" % (input_dir, dest_input_dir))
439  shutil.copytree(input_dir, dest_input_dir)
440  """
441 
442  self.commandcommandcommand = os.path.join(dest, "bin", "generate_events")
443  self.loggerlogger.debug("Command set to '%s'" % self.commandcommandcommand)
444 
445  run_card_src = os.path.join(src, "Cards", self.run_cardrun_card)
446  run_card_dest = os.path.join(dest, "Cards", "run_card.dat")
447  self.loggerlogger.debug("Copying run card from '%s' to '%s'" % (run_card_src, run_card_dest))
448  shutil.copyfile(run_card_src, run_card_dest)
449 
450  self.make_run_cardmake_run_card(run_card_dest)
451 
452  param_card_src = os.path.join(src, "Cards", self.param_cardparam_card)
453  param_card_dest = os.path.join(dest, "Cards", "param_card.dat")
454  self.loggerlogger.debug("Copying param card from '%s' to '%s'" % (param_card_src, param_card_dest))
455  shutil.copyfile(param_card_src, param_card_dest)
456 
457  self.make_param_cardmake_param_card(param_card_dest)
458 
459  def execute(self, log_out, log_err):
460  """! Execute MadGraph5 generator.
461  @param log_out name of log file for output
462  @param log_err name of log file for error
463  @return error code
464  """
465  returncode = MG.execute(self, log_out, log_err)
466  lhe_files = glob.glob(os.path.join(self.event_direvent_dir, "*.lhe.gz"))
467  for f in lhe_files:
468  dest = os.path.join(self.rundir, '%s_%s' % (self.namenamename, os.path.basename(f)))
469  self.loggerlogger.debug("Copying '%s' to '%s'" % (f, dest))
470  shutil.copy(f, dest)
471  os.chdir(self.rundir)
472  return returncode
Base class for components in a job.
Definition: component.py:15
def output_files(self)
Return a list of output files created by this component.
Definition: component.py:206
def 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
egs5_data_dir
data directory
Definition: generators.py:62
beam_energy
beam energy in MeV
Definition: generators.py:44
target_thickness
target thickness in $\mu$m,
Definition: generators.py:40
def execute(self, log_out, log_err)
Execute event generator.
Definition: generators.py:103
def required_parameters(self)
Return required parameters.
Definition: generators.py:115
egs5_config_dir
config directory
Definition: generators.py:64
def output_files(self)
Generate output file name.
Definition: generators.py:94
def optional_parameters(self)
Return optional parameters.
Definition: generators.py:123
num_electrons
number of electrons
Definition: generators.py:46
def __init__(self, name='', **kwargs)
Definition: generators.py:36
def get_install_dir(self)
Get installation directory.
Definition: generators.py:49
def setup(self)
Setup of egs5 event generator.
Definition: generators.py:53
Event generator base class.
Definition: generators.py:13
def __init__(self, name, command=None, **kwargs)
Definition: generators.py:16
def required_parameters(self)
Return a list of required parameters.
Definition: generators.py:19
Run the MadGraph 4 event generator.
Definition: generators.py:329
def __init__(self, name='ap', **kwargs)
Definition: generators.py:341
def execute(self, log_out, log_err)
Execute MadGraph4 generator.
Definition: generators.py:383
def get_install_dir(self)
Get installation directory of MadGraph4.
Definition: generators.py:348
def setup(self)
Setup MadGraph4 generator.
Definition: generators.py:352
Run the MadGraph 5 event generator.
Definition: generators.py:399
def execute(self, log_out, log_err)
Execute MadGraph5 generator.
Definition: generators.py:459
def __init__(self, name='tritrig', **kwargs)
Definition: generators.py:411
def get_install_dir(self)
Get installation directory of MadGraph5.
Definition: generators.py:418
def setup(self)
Setup MadGraph5 generator.
Definition: generators.py:422
Abstract class for MadGraph generators.
Definition: generators.py:179
event_types
event types: weighted or unweighted
Definition: generators.py:216
mpid
dark pion mass
Definition: generators.py:206
mchi
average dark fermion mass when running idm
Definition: generators.py:210
apmass
A-prime mass.
Definition: generators.py:200
def __init__(self, name, **kwargs)
Definition: generators.py:187
def execute(self, log_out, log_err)
Execute MadGraph generator.
Definition: generators.py:307
def required_parameters(self)
Return required parameters.
Definition: generators.py:237
def output_files(self)
Generate output file name.
Definition: generators.py:222
param_card
Default name of param card.
Definition: generators.py:193
map
A-prime mass.
Definition: generators.py:202
def optional_parameters(self)
Return optional parameters.
Definition: generators.py:245
def make_param_card(self, param_card)
Make parameter card.
Definition: generators.py:275
mrhod
dark rho mass
Definition: generators.py:208
def make_run_card(self, run_card)
Make run card.
Definition: generators.py:256
madgraph_dir
Install dir or user config will be used for this.
Definition: generators.py:190
dmchi
difference between dark fermion masses when running idm
Definition: generators.py:212
def setup(self)
Setup event generator.
Definition: generators.py:317
def set_parameters(self, params)
Set parameters.
Definition: generators.py:231
def cmd_args(self)
Return command arguments.
Definition: generators.py:303
Map
A-prime mass.
Definition: generators.py:204
Convert LHE files to StdHep using EGS5.
Definition: generators.py:135
def config(self, parser)
Automatic configuration.
Definition: generators.py:144
def execute(self, log_out, log_err)
Execute converter.
Definition: generators.py:154
def output_files(self)
Converts *.lhe.gz and *.lhe to *.stdhep files.
Definition: generators.py:174
def setup(self)
Setup egs5 generator.
Definition: generators.py:147
def __init__(self, name="lhe_v1", **kwargs)
Definition: generators.py:138