1
################################################################################
3
# Copyright (c) 2012 The MadGraph5_aMC@NLO Development team and Contributors
5
# This file is a part of the MadGraph5_aMC@NLO project, an application which
6
# automatically generates Feynman diagrams and matrix elements for arbitrary
7
# high-energy processes in the Standard Model and beyond.
9
# It is subject to the MadGraph5_aMC@NLO license which should accompany this
12
# For more information, visit madgraph.phys.ucl.ac.be and amcatnlo.web.cern.ch
14
################################################################################
15
"""Program to combine results from channels that have been
16
split into multiple jobs. Multi-job channels are identified
17
by local file mjobs.dat in the channel directory.
19
from __future__ import division
26
import madgraph.various.sum_html as sum_html
27
from madgraph import InvalidCmd, MadGraph5Error, MG5DIR
29
import internal.sum_html as sum_html
30
from internal import InvalidCmd, MadGraph5Error
32
logger = logging.getLogger('madevent.combine_run') # -> stdout
38
def get_inc_file(path):
39
"""read the information of fortran inc files and returns
40
the definition in a dictionary format.
41
This catch PARAMETER (NAME = VALUE)"""
43
pat = re.compile(r'''PARAMETER\s*\((?P<name>[_\w]*)\s*=\s*(?P<value>[\+\-\ded]*)\)''',
47
for name, value in pat.findall(open(path).read()):
48
orig_value = str(value)
50
out[name.lower()] = float(value.replace('d','e'))
52
out[name] = orig_value
55
class CombineRuns(object):
57
def __init__(self, me_dir, subproc=None):
62
subproc = [l.strip() for l in open(pjoin(self.me_dir,'SubProcesses',
64
self.subproc = subproc
65
maxpart = get_inc_file(pjoin(me_dir, 'Source', 'maxparticles.inc'))
66
self.maxparticles = maxpart['max_particles']
69
for procname in self.subproc:
70
path = pjoin(self.me_dir,'SubProcesses', procname)
71
channels = self.get_channels(path)
72
for channel in channels:
73
self.sum_multichannel(channel)
75
def sum_multichannel(self, channel):
76
"""Looks in channel to see if there are multiple runs that
77
need to be combined. If so combines them into single run"""
79
alphabet = "abcdefghijklmnopqrstuvwxyz"
81
if os.path.exists(pjoin(channel, 'multijob.dat')):
82
njobs = int(open(pjoin(channel, 'multijob.dat')).read())
85
results = sum_html.Combine_results(channel)
87
logger.debug('find %s multijob in %s' % (njobs, channel))
90
for i in range(njobs):
91
if channel.endswith(os.path.pathsep):
92
path = channel[:-1] + alphabet[i]
94
path = channel + alphabet[i]
95
results.add_results(name=alphabet[i],
96
filepath=pjoin(path, 'results.dat'))
98
results.compute_average()
100
results.write_results_dat(pjoin(channel, 'results.dat'))
103
### Adding information in the log file
104
fsock = open(pjoin(channel, 'log.txt'), 'a')
105
fsock.write('--------------------- Multi run with %s jobs. ---------------------\n'
108
fsock.write('job %s : %s %s %s\n' % (r.name, r.xsec, r.axsec, r.nunwgt))
110
#Now read in all of the events and write them
111
#back out with the appropriate scaled weight
112
fsock = open(pjoin(channel, 'events.lhe'), 'w')
113
wgt = results.axsec / results.nunwgt
115
for result in results:
117
if channel.endswith(os.path.pathsep):
118
path = channel[:-1] + i
121
nw = self.copy_events(fsock, pjoin(path,'events.lhe'), wgt)
123
#logger.debug("Combined %s events to %s " % (tot_events, channel))
126
def copy_events(self, fsock, input, new_wgt):
127
""" Copy events from separate runs into one file w/ appropriate wgts"""
129
def get_fortran_str(nb):
131
nb, power = data.split('E')
132
nb = abs(float(nb)) /10
133
power = int(power) + 1
134
return '%.7fE%+03i' %(nb,power)
135
new_wgt = get_fortran_str(new_wgt)
137
for line in open(input):
138
if old_line.startswith("<event>"):
140
if not len(data) == 6:
141
raise MadGraph5Error, "Line after <event> should have 6 entries"
142
if float(data[2]) > 0:
147
line= ' %s %s%s %s\n' % (' '.join(data[:2]), sign,
148
new_wgt, ' '.join(data[3:]))
152
def get_channels(self, proc_path):
153
"""Opens file symfact.dat to determine all channels"""
154
sympath = os.path.join(proc_path, 'symfact.dat')
156
#ncode is number of digits needed for the bw coding
158
ncode = int(math.log10(3)*(self.maxparticles-3))+1
160
for line in open(sympath):
165
xi, j = float(xi), int(j)
169
npos = int(math.log10(k))+1
170
#Write with correct number of digits
174
dirname = 'G%.{0}f'.format(ncode) % xi
175
channels.append(os.path.join(proc_path,dirname))