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