ATLAS Offline Software
Herwig7Control.py
Go to the documentation of this file.
1 # Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
2 
14 
15 import os, shutil, subprocess, sys
16 import six
17 
18 from . import Herwig7Utils as hw7Utils
19 from . import Herwig7JOChecker as JOChecker
20 # import Herwig7Defaults as HwDefaults
21 
22 from AthenaCommon import Logging
23 athMsgLog = Logging.logging.getLogger('Herwig7Control')
24 
25 
26 
32 
33  cmt_paths = os.environ.get("CMAKE_PREFIX_PATH")
34  cmt_config = os.environ.get("BINARY_TAG")
35 
36  # trying to get it from the `InstallArea`
37  for path in cmt_paths.split(':'):
38  path = os.path.join(path, "InstallArea", cmt_config, "share")
39  try:
40  filelist = os.listdir(path)
41  except Exception:
42  filelist = []
43  if "HerwigDefaults.rpo" in filelist: return(path)
44 
45  # falling back to `$HERWIG7_PATH`
46  path = os.path.join(os.environ['HERWIG7_PATH'], 'share/Herwig')
47  if os.path.isfile(os.path.join(path, 'HerwigDefaults.rpo')):
48  return(path)
49 
50  # raise exception if none of the two methods work out
51  raise RuntimeError(hw7Utils.ansi_format_error('Could not find a valid share/Herwig folder'))
52 
53 
54 # proper handling with path set in External/Herwig7/cmt/requirements
55 herwig7_path = os.environ['HERWIG7_PATH']
56 herwig7_bin_path = os.path.join(herwig7_path, 'bin')
57 herwig7_share_path = get_share_path()
58 
59 herwig7_binary = os.path.join(herwig7_bin_path, 'Herwig')
60 
61 
62 
65 def run(gen_config):
66 
67 
68  do_read(gen_config)
69 
70 
71  do_run(gen_config, cleanup_herwig_scratch=False)
72 
73 
74 
78 def matchbox_run(gen_config, integration_jobs, cleanup_herwig_scratch):
79 
80 
81  do_build_integrate_mergegrids(gen_config, integration_jobs)
82 
83 
84  do_run(gen_config, cleanup_herwig_scratch)
85 
86 
87 
91 def matchbox_run_gridpack(gen_config, integration_jobs, gridpack_name, cleanup_herwig_scratch, integrate):
92 
93 
94  log(message=start_banner())
95 
96  if not gridpack_name or integrate:
97 
98 
99  write_infile(gen_config)
100 
101 
102  xsec, err = do_build_integrate_mergegrids(gen_config, integration_jobs)
103 
104 
105  do_compress_gridpack(gen_config.run_name, gridpack_name)
106 
107 
108  log(message=exit_banner(gridpack_name, xsec, err))
109  sys.exit(0)
110 
111  else:
112 
113 
114  DSIS_dir = gen_config.runArgs.jobConfig[0]+"/"
115  do_uncompress_gridpack(DSIS_dir+gridpack_name)
116  athMsgLog.info("Finished unpacking the gridpack")
117 
118 
119  do_run(gen_config, cleanup_herwig_scratch)
120 
121 
122 
123 def do_step(step, command, logfile_name=None):
124 
125  athMsgLog.info(hw7Utils.ansi_format_info("Starting Herwig7 '{}' step with command '{}'".format(step, ' '.join(command))))
126 
127  logfile = open(logfile_name, 'w') if logfile_name else None
128  do = subprocess.Popen(command, stdout=logfile, stderr=logfile)
129  do.wait()
130  if not do.returncode == 0:
131  raise RuntimeError(hw7Utils.ansi_format_error("Some error occured during the '{}' step.".format(step)))
132 
133  if logfile:
134  athMsgLog.info("Content of %s log file '%s':", step, logfile_name)
135  athMsgLog.info("")
136  with open(logfile_name, 'r') as logfile:
137  for line in logfile:
138  athMsgLog.info(' %s', line.rstrip('\n'))
139  athMsgLog.info("")
140 
141 
142 def do_abort():
143  athMsgLog.info(hw7Utils.ansi_format_info("Doing abort"))
144  sys.exit(0)
145 
146 
147 
148 def do_read(gen_config):
149 
150 
151  log(message=start_banner())
152 
153 
154  write_infile(gen_config)
155 
156 
158 
159 
160  share_path = get_share_path()
161  do_step('read', [herwig7_binary, 'read', get_infile_name(gen_config.run_name), '-I', share_path])
162 
163 
164 def do_read_existing_infile(gen_config):
165 
166 
167  log(message=start_banner())
168 
169 
171 
172 
173  share_path = get_share_path()
174  do_step('read', [herwig7_binary, 'read', gen_config.infile_name, '-I', share_path])
175 
176 
177 
178 def do_build(gen_config, integration_jobs):
179 
180 
181  log(message=start_banner())
182 
183 
184  write_infile(gen_config)
185 
186 
188 
189 
190  share_path = get_share_path()
191  do_step('build', [herwig7_binary, 'build', get_infile_name(gen_config.run_name), '-I', share_path, '-y '+str(integration_jobs)])
192 
193 
194 
196 def do_integrate(run_name, integration_job):
197 
198  runfile_name = get_runfile_name(run_name)
199  # setupfile_name = get_setupfile_name(run_name) if setupfile else None
200 
201  integrate_log = run_name+'.integrate'+str(integration_job)+'.log'
202  integrate_command = [herwig7_binary,'integrate',runfile_name,'--jobid='+str(integration_job)]
203  # if setupfile: integrate_command.append('--setupfile='+setupfile_name)
204 
205  do_step('integrate', integrate_command, integrate_log)
206 
207 
208 
209 def do_mergegrids(run_name, integration_jobs):
210 
211  runfile_name = get_runfile_name(run_name)
212  mergegrids_command = [herwig7_binary, 'mergegrids', runfile_name]
213  # if setupfile_name: mergegrids_command.append('--setupfile='+setupfile_name)
214 
215  do_step('mergegrids', mergegrids_command)
216 
217 
218  xsec, err = hw7Utils.get_cross_section(run_name, integration_jobs)
219 
220  return(xsec, err)
221 
222 
223 
224 def do_build_integrate_mergegrids(gen_config, integration_jobs):
225 
226 
227  do_build(gen_config, integration_jobs)
228 
229 
230  runfile_name = get_runfile_name(gen_config.run_name)
231  # setupfile_name = get_setupfile_name(run_name) if setupfile else None
232  athMsgLog.info(hw7Utils.ansi_format_info('Starting integration with {} jobs'.format(integration_jobs)))
233 
234  integration_procs = []
235  for integration_job in range(integration_jobs):
236  integrate_log = gen_config.run_name+'.integrate'+str(integration_job)+'.log'
237  integrate_command = [herwig7_binary,'integrate',runfile_name,'--jobid='+str(integration_job)]
238  # if setupfile: integrate_command.append('--setupfile='+setupfile_name)
239  integration_procs.append(hw7Utils.Process(integration_job, integrate_command, integrate_log))
240 
241  integration_handler = hw7Utils.ProcessHandler(integration_procs, athMsgLog)
242  if not integration_handler.success():
243  raise RuntimeError(hw7Utils.ansi_format_error('Not all of the integration jobs finished successfully'))
244 
245  athMsgLog.info(hw7Utils.ansi_format_ok('All integration jobs finished successfully'))
246 
247 
248  xsec, err = do_mergegrids(gen_config.run_name, integration_jobs)
249 
250  return(xsec, err)
251 
252 
253 def do_compress_gridpack(run_name, gridpack_name):
254 
255  if not (gridpack_name.endswith('.tar.gz') or gridpack_name.endswith('.tgz')): gridpack_name += '.tar.gz'
256  infile_name = get_infile_name(run_name)
257  runfile_name = get_runfile_name(run_name)
258  version = herwig_version()
259  athMsgLog.debug("Scratch area, this is Herwig version '{}'".format(version))
260  if "7.1" in version or "7.0" in version:
261  do_step('compress', ['tar', 'czf', gridpack_name, infile_name, runfile_name, 'Herwig-scratch'])
262  else:
263  do_step('compress', ['tar', 'czf', gridpack_name, infile_name, runfile_name, 'Herwig-cache'])
264 
265 
266 def do_uncompress_gridpack(gridpack_name):
267 
268  athMsgLog.info("unpacking gridpack '%s'", gridpack_name)
269  do_step('uncompress', ['tar', 'xzf', gridpack_name])
270 
271 
272 
273 def do_run(gen_config, cleanup_herwig_scratch=True):
274 
275 
276  gen_config.genSeq.Herwig7.RunFile = get_runfile_name(gen_config.run_name)
277 
278 
279  JOChecker.check_file()
280 
281 
282  if gen_config.runArgs.randomSeed is None:
283  gen_config.genSeq.Herwig7.UseRandomSeedFromGeneratetf = False
284  else:
285  gen_config.genSeq.Herwig7.UseRandomSeedFromGeneratetf = True
286  gen_config.genSeq.Herwig7.RandomSeedFromGeneratetf = gen_config.runArgs.randomSeed
287 
288 
289  gen_config.genSeq.Herwig7.PDFNameME = gen_config.me_pdf_name
290 
291 
292  gen_config.genSeq.Herwig7.PDFNameMPI = gen_config.mpi_pdf_name
293 
294 
295  gen_config.genSeq.Herwig7.CleanupHerwigScratch = cleanup_herwig_scratch
296 
297 
299  athMsgLog.info(hw7Utils.ansi_format_info("Returning to the job options and starting the event generation afterwards"))
300 
301 
302 
303 def do_run_existing_runfile(gen_config):
304 
305 
306  gen_config.genSeq.Herwig7.RunFile = gen_config.runfile_name
307 
308 
309  if gen_config.runArgs.randomSeed is None:
310  gen_config.genSeq.Herwig7.UseRandomSeedFromGeneratetf = False
311  else:
312  gen_config.genSeq.Herwig7.UseRandomSeedFromGeneratetf = True
313  gen_config.genSeq.Herwig7.RandomSeedFromGeneratetf = gen_config.runArgs.randomSeed
314 
315 
317  athMsgLog.info(hw7Utils.ansi_format_info("Returning to the job options and starting the event generation afterwards"))
318 
319 
320 # utility functions -----------------------------------------------------------
321 
322 
324 
325  versions = get_software_versions()
326  return(' '.join(versions[0].split()[1:]))
327 
329 
330  versions = get_software_versions()
331  return(' '.join(versions[1].split()[1:]))
332 
334 
335  herwig_version_number = herwig_version()
336  thepeg_version_number = thepeg_version()
337  herwig_version_space = ' '.join(['' for i in range(14-len(herwig_version_number))])
338  thepeg_version_space = ' '.join(['' for i in range(14-len(thepeg_version_number))])
339 
340  banner = ''
341  banner += "#####################################\n"
342  banner += "## {} ##\n".format(hw7Utils.ansi_format_ok("---------------------------"))
343  banner += "## {} ##\n".format(hw7Utils.ansi_format_ok("Starting HERWIG 7 in ATHENA"))
344  banner += "## {} ##\n".format(hw7Utils.ansi_format_ok("---------------------------"))
345  banner += "## ##\n"
346  banner += "## with software versions: ##\n"
347  banner += "## - Herwig7: {}{} ##\n".format(herwig_version_number, herwig_version_space)
348  banner += "## - ThePEG: {}{} ##\n".format(thepeg_version_number, thepeg_version_space)
349  # banner += "## ##\n"
350  # banner += "## with depencency versions ##\n"
351  # banner += "## - GoSam\n"
352  # banner += "## - GoSam-Contrib\n"
353  # banner += "## - GoSam\n"
354  # banner += "## - HJets\n"
355  # banner += "## - MadGraph5_aMC@NLO: \n"
356  # banner += "## - NJet: \n"
357  # banner += "## - OpenLoops: \n"
358  # banner += "## - VBFNLO: \n"
359  banner += "## ##\n"
360  banner += "#####################################\n"
361  return(banner)
362 
363 
365 
366  return(six.ensure_str(subprocess.check_output([herwig7_binary,'--version'])).splitlines())
367 
368 
369 def get_infile_name(run_name="Herwig-Matchbox"):
370 
371  return('{}.in'.format(run_name))
372 
373 
374 def get_setupfile_name(run_name="Herwig-Matchbox"):
375 
376  return('{}.setupfile.in'.format(run_name))
377 
378 
379 def get_runfile_name(run_name="Herwig-Matchbox"):
380 
381  return('{}.run'.format(run_name) if not run_name.endswith('.run') else run_name)
382 
383 
384 def write_infile(gen_config, print_infile=True):
385 
386  # lock settings to prevent modification from within the job options after infile was written to disk
387  gen_config.default_commands.lock()
388  gen_config.commands.lock()
389 
390  infile_name = get_infile_name(gen_config.run_name)
391  if print_infile: athMsgLog.info("")
392  athMsgLog.info(hw7Utils.ansi_format_info("Writing infile '{}'".format(infile_name)))
393  commands = \
394  gen_config.global_pre_commands().splitlines() \
395  + gen_config.local_pre_commands().splitlines() \
396  + ["",
397  "## ================",
398  "## Default Commands",
399  "## ================"] \
400  + str(gen_config.default_commands.commands).splitlines() \
401  + ["",
402  "## ========================",
403  "## Commands from jobOptions",
404  "## ========================"] \
405  + str(gen_config.commands.commands).splitlines() \
406  + gen_config.local_post_commands().splitlines()
407  try:
408  with open(infile_name, 'w') as infile:
409  for command in commands:
410  infile.write(command+'\n')
411  except Exception:
412  raise RuntimeError('Could not write Herwig/Matchbox infile')
413 
414  if print_infile:
415  athMsgLog.info("")
416  for command in commands:
417  athMsgLog.info(' %s', command)
418  athMsgLog.info("")
419 
420 
421 def write_setupfile(run_name, commands, print_setupfile=True):
422 
423  setupfile_name = get_setupfile_name(run_name)
424 
425  if len(commands) > 0:
426  if print_setupfile: athMsgLog.info("")
427  athMsgLog.info("Writing setupfile '%s'", setupfile_name)
428  try:
429  with open(setupfile_name, 'w') as setupfile:
430  for command in commands: setupfile.write(command+'\n')
431  except Exception:
432  raise RuntimeError('Could not write Herwig/Matchbox setupfile')
433 
434  if print_setupfile:
435  athMsgLog.info("")
436  for command in commands: athMsgLog.info(' %s', command)
437  athMsgLog.info("")
438 
439  else:
440  athMsgLog.info("No setupfile commands given.")
441 
442 
443 
446 
447  shutil.copy(os.path.join(get_share_path(), 'HerwigDefaults.rpo'), 'HerwigDefaults.rpo')
448 
449 
450 def log(level='info', message=''):
451 
452  if level in ['info', 'warn', 'error']:
453  logger = getattr(athMsgLog, level)
454  for line in message.splitlines(): logger(line)
455  else:
456  raise ValueError("Unknown logging level'{}' specified. Possible values are 'info', 'warn' or 'error'".format(level))
457 
458 
459 def exit_banner(gridpack, cross_section, cross_section_error):
460 
461  size = hw7Utils.humanize_bytes(hw7Utils.get_size(gridpack))
462  space_size = hw7Utils.get_repeated_pattern(' ', 31-len(size))
463 
464  xsec = '{:f}'.format(cross_section)
465  err = '{:f}'.format(cross_section_error)
466  rel_err = '{:.2f}'.format(cross_section_error / cross_section * 100.0)
467  space_xsec = hw7Utils.get_repeated_pattern(' ', 37-len(xsec)-len(err)-len(rel_err))
468 
469  banner = ''
470  space = ' '.join(['' for i in range(70+4+1-len(gridpack))])
471  banner += "##########################################################################################\n"
472  banner += "## ------------------------------------------------------------------------------- ##\n"
473  banner += "## {} (size: {}){} ##\n".format(hw7Utils.ansi_format_ok("HERWIG 7 successfully created the gridpack"), size, space_size)
474  banner += "## ##\n"
475  banner += "## {}{} ##\n".format(hw7Utils.ansi_format_info(gridpack), space)
476  banner += "## ##\n"
477  banner += "## cross section from integration: {} +/- {} ({}%) nb {} ##\n".format(xsec, err, rel_err, space_xsec)
478 
479  if cross_section_error / cross_section > hw7Utils.integration_grids_precision_threshold:
480  threshold = '{}%'.format(hw7Utils.integration_grids_precision_threshold*100.0)
481  space_threshold = hw7Utils.get_repeated_pattern(' ', 6-len(threshold))
482  banner += "## ##\n"
483  banner += "## {} ##\n".format(hw7Utils.ansi_format_warning("! WARNING: The integration grids only have a low precision (worse than {}){}!".format(threshold, space_threshold)))
484 
485  banner += "## ##\n"
486  banner += "## ------------------------------------------------------------------------------- ##\n"
487  banner += "## ##\n"
488  banner += "## Please ignore the error ##\n"
489  banner += "## ##\n"
490  banner += "## No such file or directory: 'evgen.root' raised while stating file evgen.root ##\n"
491  banner += "## ##\n"
492  banner += "##########################################################################################\n"
493  return(banner)
494 
Herwig7Control.do_integrate
def do_integrate(run_name, integration_job)
Do the integrate step for one specific integration job.
Definition: Herwig7Control.py:196
Herwig7Control.exit_banner
def exit_banner(gridpack, cross_section, cross_section_error)
Definition: Herwig7Control.py:459
Herwig7Control.do_build
def do_build(gen_config, integration_jobs)
Do the build step.
Definition: Herwig7Control.py:178
vtune_athena.format
format
Definition: vtune_athena.py:14
Herwig7Control.do_build_integrate_mergegrids
def do_build_integrate_mergegrids(gen_config, integration_jobs)
Subsequent build, integrate and mergegrid steps.
Definition: Herwig7Control.py:224
Herwig7Control.do_mergegrids
def do_mergegrids(run_name, integration_jobs)
This function provides the mergegrids step.
Definition: Herwig7Control.py:209
Herwig7Control.matchbox_run
def matchbox_run(gen_config, integration_jobs, cleanup_herwig_scratch)
Do the build, integrate, mergegrids and run step in one go without creating a gridpack.
Definition: Herwig7Control.py:78
Herwig7Control.do_run_existing_runfile
def do_run_existing_runfile(gen_config)
Do the run step and re-use an already existing runfile.
Definition: Herwig7Control.py:303
Herwig7Control.do_abort
def do_abort()
Definition: Herwig7Control.py:142
Herwig7Control.get_default_repository
def get_default_repository()
Copy default repository HerwigDefaults.rpo to current working directory.
Definition: Herwig7Control.py:445
Herwig7Control.write_setupfile
def write_setupfile(run_name, commands, print_setupfile=True)
Definition: Herwig7Control.py:421
Herwig7Control.do_step
def do_step(step, command, logfile_name=None)
Definition: Herwig7Control.py:123
Herwig7Control.matchbox_run_gridpack
def matchbox_run_gridpack(gen_config, integration_jobs, gridpack_name, cleanup_herwig_scratch, integrate)
Either do the build, integrate and mergegrids steps and create a gridpack or extract it and generate ...
Definition: Herwig7Control.py:91
Herwig7Control.run
def run(gen_config)
Do the read/run sequence.
Definition: Herwig7Control.py:65
Herwig7Control.start_banner
def start_banner()
Definition: Herwig7Control.py:333
Herwig7Control.do_uncompress_gridpack
def do_uncompress_gridpack(gridpack_name)
Definition: Herwig7Control.py:266
plotBeamSpotVxVal.range
range
Definition: plotBeamSpotVxVal.py:195
Herwig7Control.get_infile_name
def get_infile_name(run_name="Herwig-Matchbox")
Definition: Herwig7Control.py:369
Herwig7Control.get_share_path
def get_share_path()
Get path to the share/Herwig folder.
Definition: Herwig7Control.py:31
Herwig7Control.do_read_existing_infile
def do_read_existing_infile(gen_config)
Do the read step and re-use an already existing infile.
Definition: Herwig7Control.py:164
TCS::join
std::string join(const std::vector< std::string > &v, const char c=',')
Definition: Trigger/TrigT1/L1Topo/L1TopoCommon/Root/StringUtils.cxx:10
Herwig7Control.do_read
def do_read(gen_config)
Do the read step.
Definition: Herwig7Control.py:148
Herwig7Control.do_compress_gridpack
def do_compress_gridpack(run_name, gridpack_name)
Definition: Herwig7Control.py:253
Herwig7Control.log
def log(level='info', message='')
Definition: Herwig7Control.py:450
Trk::open
@ open
Definition: BinningType.h:40
Herwig7Control.get_software_versions
def get_software_versions()
Definition: Herwig7Control.py:364
Herwig7Control.get_runfile_name
def get_runfile_name(run_name="Herwig-Matchbox")
Definition: Herwig7Control.py:379
Herwig7Control.herwig_version
def herwig_version()
Definition: Herwig7Control.py:323
str
Definition: BTagTrackIpAccessor.cxx:11
Herwig7Control.do_run
def do_run(gen_config, cleanup_herwig_scratch=True)
Definition: Herwig7Control.py:273
Trk::split
@ split
Definition: LayerMaterialProperties.h:38
python.iconfTool.gui.pad.logger
logger
Definition: pad.py:14
Herwig7Control.get_setupfile_name
def get_setupfile_name(run_name="Herwig-Matchbox")
Definition: Herwig7Control.py:374
Herwig7Control.write_infile
def write_infile(gen_config, print_infile=True)
Definition: Herwig7Control.py:384
Herwig7Control.thepeg_version
def thepeg_version()
Definition: Herwig7Control.py:328