Package madgraph :: Package madevent :: Module combine_runs
[hide private]
[frames] | no frames]

Source Code for Module madgraph.madevent.combine_runs

  1  ################################################################################ 
  2  # 
  3  # Copyright (c) 2012 The MadGraph5_aMC@NLO Development team and Contributors 
  4  # 
  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. 
  8  # 
  9  # It is subject to the MadGraph5_aMC@NLO license which should accompany this  
 10  # distribution. 
 11  # 
 12  # For more information, visit madgraph.phys.ucl.ac.be and amcatnlo.web.cern.ch 
 13  # 
 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. 
 18  """ 
 19  from __future__ import division 
 20  from __future__ import absolute_import 
 21  import math 
 22  import os 
 23  import re 
 24  import logging 
 25  from six.moves import range 
 26   
 27  try: 
 28      import madgraph 
 29  except ImportError: 
 30      import internal.sum_html as sum_html 
 31      import internal.misc as misc 
 32      from internal import InvalidCmd, MadGraph5Error     
 33  else: 
 34      import madgraph.madevent.sum_html as sum_html 
 35      import madgraph.various.misc as misc 
 36      from madgraph import InvalidCmd, MadGraph5Error, MG5DIR 
 37   
 38       
 39  logger = logging.getLogger('madevent.combine_run') # -> stdout 
 40   
 41  #usefull shortcut 
 42  pjoin = os.path.join 
43 44 45 -def get_inc_file(path):
46 """read the information of fortran inc files and returns 47 the definition in a dictionary format. 48 This catch PARAMETER (NAME = VALUE)""" 49 50 pat = re.compile(r'''PARAMETER\s*\((?P<name>[_\w]*)\s*=\s*(?P<value>[\+\-\ded]*)\)''', 51 re.I) 52 53 out = {} 54 for name, value in pat.findall(open(path).read()): 55 orig_value = str(value) 56 try: 57 out[name.lower()] = float(value.replace('d','e')) 58 except ValueError: 59 out[name] = orig_value 60 return out
61
62 -class CombineRuns(object):
63
64 - def __init__(self, me_dir, subproc=None):
65 66 self.me_dir = me_dir 67 68 if not subproc: 69 subproc = [l.strip() for l in open(pjoin(self.me_dir,'SubProcesses', 70 'subproc.mg'))] 71 self.subproc = subproc 72 maxpart = get_inc_file(pjoin(me_dir, 'Source', 'maxparticles.inc')) 73 self.maxparticles = maxpart['max_particles'] 74 75 76 for procname in self.subproc: 77 path = pjoin(self.me_dir,'SubProcesses', procname) 78 channels = self.get_channels(path) 79 for channel in channels: 80 self.sum_multichannel(channel)
81
82 - def sum_multichannel(self, channel):
83 """Looks in channel to see if there are multiple runs that 84 need to be combined. If so combines them into single run""" 85 86 alphabet = "abcdefghijklmnopqrstuvwxyz" 87 88 if os.path.exists(pjoin(channel, 'multijob.dat')): 89 njobs = int(open(pjoin(channel, 'multijob.dat')).read()) 90 else: 91 return 92 results = sum_html.Combine_results(channel) 93 if njobs: 94 logger.debug('find %s multijob in %s' % (njobs, channel)) 95 else: 96 return 97 for i in range(njobs): 98 if channel.endswith(os.path.pathsep): 99 path = channel[:-1] + alphabet[i % 26] + str((i+1)//26) 100 else: 101 path = channel + alphabet[i % 26] + str((i+1)//26) 102 results.add_results(name=alphabet[i % 26] + str((i+1)//26) , 103 filepath=pjoin(path, 'results.dat')) 104 105 results.compute_average() 106 if results.xsec: 107 results.write_results_dat(pjoin(channel, 'results.dat')) 108 else: 109 return 110 ### Adding information in the log file 111 fsock = open(pjoin(channel, 'log.txt'), 'a') 112 fsock.write('--------------------- Multi run with %s jobs. ---------------------\n' 113 % njobs) 114 for r in results: 115 fsock.write('job %s : %s %s +- %s %s\n' % (r.name, r.xsec, r.axsec,\ 116 r.xerru, r.nunwgt)) 117 118 #Now read in all of the events and write them 119 #back out with the appropriate scaled weight 120 fsock = open(pjoin(channel, 'events.lhe'), 'w') 121 wgt = results.axsec / results.nunwgt 122 tot_nevents, nb_file = 0, 0 123 for result in results: 124 i = result.name 125 if channel.endswith(os.path.pathsep): 126 path = channel[:-1] + i 127 else: 128 path = channel + i 129 nw = self.copy_events(fsock, pjoin(path,'events.lhe'), wgt) 130 tot_nevents += nw 131 nb_file += 1 132 logger.debug("Combined %s file generating %s events for %s " , nb_file, tot_nevents, channel)
133 134 @staticmethod
135 - def get_fortran_str(nb):
136 data = '%E' % nb 137 nb, power = data.split('E') 138 nb = abs(float(nb)) /10 139 power = int(power) + 1 140 return '%.7fE%+03i' %(nb,power)
141 142
143 - def copy_events(self, fsock, input, new_wgt):
144 """ Copy events from separate runs into one file w/ appropriate wgts""" 145 146 147 new_wgt = self.get_fortran_str(new_wgt) 148 old_line = "" 149 nb_evt =0 150 for line in open(input): 151 if old_line.startswith("<event>"): 152 nb_evt+=1 153 data = line.split() 154 if not len(data) == 6: 155 raise MadGraph5Error("Line after <event> should have 6 entries") 156 if float(data[2]) > 0: 157 sign = '' 158 else: 159 sign = '-' 160 line= ' %s %s%s %s\n' % (' '.join(data[:2]), sign, 161 new_wgt, ' '.join(data[3:])) 162 fsock.write(line) 163 old_line = line 164 return nb_evt
165 - def get_channels(self, proc_path):
166 """Opens file symfact.dat to determine all channels""" 167 sympath = os.path.join(proc_path, 'symfact.dat') 168 169 #ncode is number of digits needed for the bw coding 170 171 ncode = int(math.log10(3)*(self.maxparticles-3))+1 172 channels = [] 173 for line in open(sympath): 174 try: 175 xi, j = line.split() 176 except Exception: 177 break 178 xi, j = float(xi), int(j) 179 180 if j > 0: 181 k = int(xi) 182 npos = int(math.log10(k))+1 183 #Write with correct number of digits 184 if xi == k: 185 dirname = 'G%i' % k 186 else: 187 dirname = 'G%.{0}f'.format(ncode) % xi 188 channels.append(os.path.join(proc_path,dirname)) 189 return channels
190