ATLAS Offline Software
Herwig7Utils.py
Go to the documentation of this file.
1 # Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
2 
3 
6 
7 import math, os, subprocess
8 
9 from AthenaCommon import Logging
10 athMsgLog = Logging.logging.getLogger('Herwig7Utils')
11 
12 integration_grids_precision_threshold = 0.0005 # if integration xsec below a warning is issue in debug mode and an erroro in production mode
13 
14 
15 
24 
25  def __init__(self):
26  self.commands = ""
27  self.locked = False
28 
29  def lock(self):
30  self.locked = True
31 
32  def add(self, commands):
33  if self.locked is False:
34  self.commands += commands
35  else:
36  raise RuntimeError("The commands associated to this configuration object can't be modified anymore because the Herwig7 infile has already been written to disk. Therefore, any subsequent additional modifications can't be adopted in the Herwig7 run.")
37  return(self)
38 
39  __iadd__ = add
40 
41 
42 
47 
48  def __init__(self, process_list, logger):
49  self.processes = process_list
50  self.n_initial = len(process_list)
51  self.logger = logger
52 
53  def success(self):
54  result = True
55  while len(self.processes) > 0:
56  for ID, process in enumerate(self.processes):
57  returncode = process.poll()
58  if returncode is not None:
59 
60 
61  self.processes.remove(process)
62  if returncode == 0:
63  athMsgLog.info(ansi_format_info('Process #{} finished sucessfully, {}/{} still running'.format(process.ID, len(self.processes), self.n_initial)))
64  elif returncode > 0:
65  athMsgLog.error(ansi_format_error("Process #{} finished with error code {} (please check logfile '{}'), {}/{} still running".format(process.ID, returncode, process.logfile_title, len(self.processes), self.n_initial)))
66  result = False
67  elif returncode < 0:
68  athMsgLog.error(ansi_format_error("Process #{} was terminated by signal {} (please check logfile '{}'), {}/{} still running".format(process.ID, -returncode, process.logfile_title, len(self.processes), self.n_initial)))
69  result = False
70 
71 
75  athMsgLog.info("Content of integration log file '%s':", process.logfile_title)
76  athMsgLog.info("")
77  with open(process.logfile_title, 'r') as logfile:
78  for line in logfile:
79  athMsgLog.info(' %s', line.rstrip('\n'))
80  athMsgLog.info("")
81  # self.logger.info('================================================================================')
82  # self.logger.info("End of integration log file '{}'".format(process.logfile_title))
83  # self.logger.info('================================================================================')
84 
85  return(result)
86 
87 
88 
92 class Process:
93 
94  def __init__(self, ID, command, logfile_title):
95 
96  athMsgLog.info(ansi_format_info("Starting subprocess #{} with command '{}' and logfile '{}'".format(ID, ' '.join(command), logfile_title)))
97  self.ID = ID
98  self.logfile_title = logfile_title
99  self.logfile = open(logfile_title, 'w')
100  self.process = subprocess.Popen(command, stdout=self.logfile, stderr=self.logfile)
101 
102  def poll(self):
103  return(self.process.poll())
104 
105 
106 
107 def get_cross_section(run_name, integration_jobs=1):
108 
109  athMsgLog.info("Calculating cross section after integration")
110  logfiles = [run_name+'.integrate'+str(integration_job)+'.log' for integration_job in range(integration_jobs)]
111 
112  xsec = 0.0
113  err = 0.0
114 
115  for logfile in logfiles:
116 
117  athMsgLog.info("- %s", logfile)
118 
119 
120  with open(logfile, 'r') as log: data = log.read().strip()
121 
122  with open(logfile, 'r') as log:
123 
124 
125  for line in log:
126  if 'Integrate ' in line:
127  n_subprocs = int(line.split('of')[1].replace(':',''))
128  athMsgLog.info(" found %s subprocesses", n_subprocs)
129  break
130 
131  data = data.split("Integrate ")[1:]
132 
133  for s, subproc in enumerate(data, start=1):
134  _xsec = 0.0
135  _err = 0.0
136  for line in subproc.split("\n"):
137  if 'integrated ( ' in line:
138  _xsec = float(line.split()[2])
139  _err = float(line.split()[4])
140  athMsgLog.info(" - subprocess %s: xsec = %s +/- %s nb", s, _xsec, _err)
141  xsec += _xsec
142  err += _err*_err
143 
144  err = math.sqrt(err)
145 
146  if err / xsec > integration_grids_precision_threshold:
147  threshold = '{}%'.format(integration_grids_precision_threshold*100.0)
148  if run_name == "Herwig_DEBUG":
149  athMsgLog.warn(ansi_format_warning('! The integration grids only have a low precision (worse than {}): xsec = {} +/- {} nb (accuracy: {:.3f}%)'.format(threshold, xsec, err, err/xsec*100.0)))
150  else:
151  athMsgLog.error(ansi_format_error('! The integration grids only have a low precision (worse than {}): xsec = {} +/- {} nb (accuracy: {:.3f}%)'.format(threshold, xsec, err, err/xsec*100.0)))
152  athMsgLog.warn(ansi_format_warning('! In order to speed up the event generation you should consider improving the statistics of the integration / phase space sampling stage (see the sampler_commands() function).'))
153  else:
154  athMsgLog.info(ansi_format_info('After integration the estimated cross section was found to be: xsec = {} +/- {} nb (accuracy: {:.3f}%)'.format(xsec, err, err/xsec*100.0)))
155 
156  return(xsec, err)
157 
158 
159 
160 def get_repeated_pattern(pattern, repetitions):
161 
162  return(pattern.join(['' for i in range(repetitions+1)]))
163 
164 
165 
166 def get_size(path):
167 
168  size = 0
169 
170  if os.path.isfile(path):
171  return(os.path.getsize(path))
172 
173  elif os.path.isdir(path):
174  for dirpath, dirs, files in os.walk(path):
175  for file in files:
176  file_path = os.path.join(dirpath, file)
177  # if not os.path.islink(file_path): # exclude symlinks because MadGraph has lots of broken symlinks
178  if os.path.isfile(file_path):
179  size += os.path.getsize(file_path)
180 
181  return(size)
182 
183 
184 
185 def humanize_bytes(bytes, precision=2):
186  # shamelessly stolen from
187  # http://code.activestate.com/recipes/577081-humanized-representation-of-a-number-of-bytes/
188 
189  abbrevs = (
190  (1<<50, 'PiB'),
191  (1<<40, 'TiB'),
192  (1<<30, 'GiB'),
193  (1<<20, 'MiB'),
194  (1<<10, 'KiB'),
195  (1, 'byte(s)')
196  )
197  if bytes == 1:
198  return '1 byte'
199  for factor, suffix in abbrevs:
200  if bytes >= factor:
201  break
202  return '%.*f %s' % (precision, bytes / factor, suffix)
203 
204 
205 
206 def ansi_format(text, colour='None', background_colour='None',
207  bold=False, underline=False, italics=False, marked=False, strikethrough=False):
208 
209  format_none = '\033[0m'
210  format_bold = '\033[1m'
211  format_underline = '\033[4m'
212  format_italics = '\033[3m'
213  format_marked = '\033[7m'
214  format_strikethrough = '\033[9m'
215 
216  colours = {
217  'None': '',
218  'Black': '\033[30m',
219  'Grey': '\033[90m',
220  'Red': '\033[91m', 'DarkRed': '\033[31m',
221  'Green': '\033[92m', 'DarkGreen': '\033[32m',
222  'Yellow': '\033[93m', 'Orange': '\033[33m',
223  'Blue': '\033[94m', 'DarkBlue': '\033[34m',
224  'Pink': '\033[95m', 'DarkPink': '\033[35m',
225  'Cyan': '\033[96m', 'DarkCyan': '\033[36m',
226  'White': '\033[97m', 'LightGrey': '\033[37m',
227  }
228 
229  background_colours = {
230  'None': '',
231  'Black': '\033[40m',
232  'Red': '\033[41m',
233  'Green': '\033[42m',
234  'Orange': '\033[43m',
235  'Blue': '\033[44m',
236  'Punk': '\033[45m',
237  'Cyan': '\033[46m',
238  'Grey': '\033[47m',
239  }
240 
241  if colour in colours:
242  if background_colour in background_colours:
243  return (format_none
244  + colours[colour]
245  + background_colours[background_colour]
246  + (format_bold if bold else '')
247  + (format_underline if underline else '')
248  + (format_italics if italics else '')
249  + (format_marked if marked else '')
250  + (format_strikethrough if strikethrough else '')
251  + text + format_none)
252  else:
253  raise Exception("Could not find background colour '{}'.".format(background_colour))
254  else:
255  raise Exception("Could not find colour '{}'.".format(colour))
256 
257 
258 def ansi_format_ok(text):
259  return (ansi_format(text, "Green"))
260 
261 
263  return (ansi_format(text, "Blue"))
264 
265 
267  return (ansi_format(text, "Yellow"))
268 
269 
271  return (ansi_format(text, "Red"))
272 
replace
std::string replace(std::string s, const std::string &s2, const std::string &s3)
Definition: hcg.cxx:307
Herwig7Utils.ProcessHandler.n_initial
n_initial
Definition: Herwig7Utils.py:50
Herwig7Utils.ansi_format_warning
def ansi_format_warning(text)
Yellow colouring.
Definition: Herwig7Utils.py:266
Herwig7Utils.ProcessHandler.__init__
def __init__(self, process_list, logger)
Definition: Herwig7Utils.py:48
Herwig7Utils.get_repeated_pattern
def get_repeated_pattern(pattern, repetitions)
Return a string made up of a certain number of repetitions of the same pattern.
Definition: Herwig7Utils.py:160
vtune_athena.format
format
Definition: vtune_athena.py:14
CaloCellPos2Ntuple.int
int
Definition: CaloCellPos2Ntuple.py:24
Herwig7Utils.get_size
def get_size(path)
Get size of file or folder.
Definition: Herwig7Utils.py:166
Herwig7Utils.ansi_format_error
def ansi_format_error(text)
Red colouring.
Definition: Herwig7Utils.py:270
PixelModuleFeMask_create_db.remove
string remove
Definition: PixelModuleFeMask_create_db.py:83
Herwig7Utils.ProcessHandler.success
def success(self)
Definition: Herwig7Utils.py:53
Herwig7Utils.ConfigurationCommands.add
def add(self, commands)
Definition: Herwig7Utils.py:32
Herwig7Utils.ConfigurationCommands.locked
locked
Definition: Herwig7Utils.py:27
plotBeamSpotVxVal.range
range
Definition: plotBeamSpotVxVal.py:195
Herwig7Utils.ProcessHandler
Class for handling parallel local multi-processing.
Definition: Herwig7Utils.py:46
Herwig7Utils.ansi_format_ok
def ansi_format_ok(text)
Green colouring.
Definition: Herwig7Utils.py:258
Herwig7Utils.ConfigurationCommands
Class for handling commands to modify the generator configuration.
Definition: Herwig7Utils.py:23
Herwig7Utils.Process.__init__
def __init__(self, ID, command, logfile_title)
Definition: Herwig7Utils.py:94
TCS::join
std::string join(const std::vector< std::string > &v, const char c=',')
Definition: Trigger/TrigT1/L1Topo/L1TopoCommon/Root/StringUtils.cxx:10
Herwig7Utils.get_cross_section
def get_cross_section(run_name, integration_jobs=1)
Calculate the total cross section from the integration log files.
Definition: Herwig7Utils.py:107
Herwig7Utils.ProcessHandler.logger
logger
Definition: Herwig7Utils.py:51
Trk::open
@ open
Definition: BinningType.h:40
Herwig7Utils.Process.ID
ID
Definition: Herwig7Utils.py:97
Herwig7Utils.ConfigurationCommands.lock
def lock(self)
Definition: Herwig7Utils.py:29
Herwig7Utils.Process
Class for handling a single process.
Definition: Herwig7Utils.py:92
Herwig7Utils.humanize_bytes
def humanize_bytes(bytes, precision=2)
Convert file/folder size from bytes to units with appropriate prefixes (multiples of 1000,...
Definition: Herwig7Utils.py:185
Herwig7Utils.Process.logfile
logfile
Definition: Herwig7Utils.py:99
Herwig7Utils.ProcessHandler.processes
processes
Definition: Herwig7Utils.py:49
str
Definition: BTagTrackIpAccessor.cxx:11
Herwig7Utils.Process.process
process
Definition: Herwig7Utils.py:100
Herwig7Utils.ansi_format
def ansi_format(text, colour='None', background_colour='None', bold=False, underline=False, italics=False, marked=False, strikethrough=False)
Format and colorize terminal output.
Definition: Herwig7Utils.py:206
Herwig7Utils.ConfigurationCommands.__init__
def __init__(self)
Definition: Herwig7Utils.py:25
Herwig7Utils.ansi_format_info
def ansi_format_info(text)
Blue colouring.
Definition: Herwig7Utils.py:262
Herwig7Utils.Process.logfile_title
logfile_title
Definition: Herwig7Utils.py:98
readCCLHist.float
float
Definition: readCCLHist.py:83
Herwig7Utils.Process.poll
def poll(self)
Definition: Herwig7Utils.py:102
Herwig7Utils.ConfigurationCommands.commands
commands
Definition: Herwig7Utils.py:26