Package madgraph :: Package interface :: Module reweight_interface
[hide private]
[frames] | no frames]

Source Code for Module madgraph.interface.reweight_interface

   1  ################################################################################ 
   2  # 
   3  # Copyright (c) 2009 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  """ Command interface for MadSpin """ 
  16  from __future__ import division 
  17  import difflib 
  18  import logging 
  19  import math 
  20  import os 
  21  import re 
  22  import shutil 
  23  import sys 
  24  import tempfile 
  25  import time 
  26  import subprocess 
  27  from subprocess import Popen, PIPE, STDOUT 
  28   
  29   
  30  pjoin = os.path.join 
  31   
  32  import madgraph.interface.extended_cmd as extended_cmd 
  33  import madgraph.interface.madgraph_interface as mg_interface 
  34  import madgraph.interface.master_interface as master_interface 
  35  import madgraph.interface.common_run_interface as common_run_interface 
  36  import madgraph.interface.madevent_interface as madevent_interface 
  37  import madgraph.iolibs.files as files 
  38  import MadSpin.interface_madspin as madspin_interface 
  39  import madgraph.various.misc as misc 
  40  import madgraph.various.banner as banner 
  41  import madgraph.various.lhe_parser as lhe_parser 
  42  import madgraph.various.combine_plots as combine_plots 
  43  import madgraph.various.cluster as cluster 
  44  import madgraph.fks.fks_common as fks_common 
  45  import madgraph.core.diagram_generation as diagram_generation 
  46   
  47  import models.import_ufo as import_ufo 
  48  import models.check_param_card as check_param_card  
  49  import MadSpin.decay as madspin 
  50   
  51   
  52  logger = logging.getLogger('decay.stdout') # -> stdout 
  53  logger_stderr = logging.getLogger('decay.stderr') # ->stderr 
  54  cmd_logger = logging.getLogger('cmdprint2') # -> print 
  55   
  56  # global to check which f2py module have been already loaded. (to avoid border effect) 
  57  dir_to_f2py_free_mod = {} 
  58  nb_f2py_module = 0 # each time the process/model is changed this number is modified to  
59 # forced the python module to re-create an executable 60 61 62 63 64 -class ReweightInterface(extended_cmd.Cmd):
65 """Basic interface for reweighting operation""" 66 67 prompt = 'Reweight>' 68 debug_output = 'Reweight_debug' 69 70 @misc.mute_logger()
71 - def __init__(self, event_path=None, allow_madspin=False, mother=None, *completekey, **stdin):
72 """initialize the interface with potentially an event_path""" 73 74 if not event_path: 75 cmd_logger.info('************************************************************') 76 cmd_logger.info('* *') 77 cmd_logger.info('* Welcome to Reweight Module *') 78 cmd_logger.info('* *') 79 cmd_logger.info('************************************************************') 80 extended_cmd.Cmd.__init__(self, *completekey, **stdin) 81 82 self.model = None 83 self.has_standalone_dir = False 84 self.mother= mother # calling interface 85 86 87 self.options = {'curr_dir': os.path.realpath(os.getcwd()), 88 'rwgt_name':None} 89 90 self.events_file = None 91 self.processes = {} 92 self.second_model = None 93 self.second_process = None 94 self.mg5cmd = master_interface.MasterCmd() 95 self.seed = None 96 self.output_type = "default" 97 self.helicity_reweighting = True 98 self.rwgt_mode = '' # can be LO, NLO, NLO_tree, '' is default 99 self.has_nlo = False 100 self.rwgt_dir = None 101 self.exitted = False # Flag to know if do_quit was already called. 102 103 if event_path: 104 logger.info("Extracting the banner ...") 105 self.do_import(event_path, allow_madspin=allow_madspin) 106 107 # dictionary to fortan evaluator 108 self.calculator = {} 109 self.calculator_nbcall = {} 110 111 #all the cross-section for convenience 112 self.all_cross_section = {}
113
114 - def do_import(self, inputfile, allow_madspin=False):
115 """import the event file""" 116 117 args = self.split_arg(inputfile) 118 if not args: 119 return self.InvalidCmd, 'import requires arguments' 120 121 # change directory where to write the output 122 self.options['curr_dir'] = os.path.realpath(os.path.dirname(inputfile)) 123 if os.path.basename(os.path.dirname(os.path.dirname(inputfile))) == 'Events': 124 self.options['curr_dir'] = pjoin(self.options['curr_dir'], 125 os.path.pardir, os.pardir) 126 127 128 if not os.path.exists(inputfile): 129 if inputfile.endswith('.gz'): 130 if not os.path.exists(inputfile[:-3]): 131 raise self.InvalidCmd('No such file or directory : %s' % inputfile) 132 else: 133 inputfile = inputfile[:-3] 134 elif os.path.exists(inputfile + '.gz'): 135 inputfile = inputfile + '.gz' 136 else: 137 raise self.InvalidCmd('No such file or directory : %s' % inputfile) 138 139 if inputfile.endswith('.gz'): 140 misc.gunzip(inputfile) 141 inputfile = inputfile[:-3] 142 143 # Read the banner of the inputfile 144 self.lhe_input = lhe_parser.EventFile(os.path.realpath(inputfile)) 145 if not self.lhe_input.banner: 146 value = self.ask("What is the path to banner", 0, [0], "please enter a path", timeout=0) 147 self.lhe_input.banner = open(value).read() 148 self.banner = self.lhe_input.get_banner() 149 150 #get original cross-section/error 151 if 'init' not in self.banner: 152 self.orig_cross = (0,0) 153 #raise self.InvalidCmd('Event file does not contain init information') 154 else: 155 for line in self.banner['init'].split('\n'): 156 split = line.split() 157 if len(split) == 4: 158 cross, error = float(split[0]), float(split[1]) 159 self.orig_cross = (cross, error) 160 161 162 163 # Check the validity of the banner: 164 if 'slha' not in self.banner: 165 self.events_file = None 166 raise self.InvalidCmd('Event file does not contain model information') 167 elif 'mg5proccard' not in self.banner: 168 self.events_file = None 169 raise self.InvalidCmd('Event file does not contain generation information') 170 171 if 'madspin' in self.banner and not allow_madspin: 172 raise self.InvalidCmd('Reweight should be done before running MadSpin') 173 174 175 # load information 176 process = self.banner.get_detail('proc_card', 'generate') 177 if '[' in process: 178 if not self.banner.get_detail('run_card', 'store_rwgt_info'): 179 logger.warning("The information to perform a proper NLO reweighting is not present in the event file.") 180 logger.warning(" We will perform a LO reweighting instead. This does not guarantee NLO precision.") 181 self.rwgt_mode = 'LO' 182 183 if 'OLP' in self.mother.options: 184 if self.mother.options['OLP'].lower() != 'madloop': 185 logger.warning("Accurate NLO mode only works for OLP=MadLoop not for OLP=%s. An approximate (LO) reweighting will be performed instead") 186 self.rwgt_mode = 'LO' 187 188 if 'lhapdf' in self.mother.options and not self.mother.options['lhapdf']: 189 logger.warning('NLO accurate reweighting requires lhapdf to be installed. Pass in approximate LO mode.') 190 self.rwgt_mode = 'LO' 191 else: 192 self.rwgt_mode = 'LO' 193 194 if not process: 195 msg = 'Invalid proc_card information in the file (no generate line):\n %s' % self.banner['mg5proccard'] 196 raise Exception, msg 197 process, option = mg_interface.MadGraphCmd.split_process_line(process) 198 self.proc_option = option 199 200 logger.info("process: %s" % process) 201 logger.info("options: %s" % option)
202 203
204 - def get_LO_definition_from_NLO(self, proc):
205 """return the LO definitions of the process corresponding to the born/real""" 206 207 # split the line definition with the part before and after the NLO tag 208 process, order, final = re.split('\[\s*(.*)\s*\]', proc) 209 # add the part without any additional jet. 210 commandline="add process %s %s --no_warning=duplicate;" % (process, final) 211 if not order: 212 #NO NLO tag => nothing to do actually return input 213 return proc 214 elif not order.startswith(('virt','loonly','noborn')): 215 # OK this a standard NLO process 216 if '=' in order: 217 # get the type NLO QCD/QED/... 218 order = order.split('=',1)[1] 219 220 # define the list of particles that are needed for the radiation 221 pert = fks_common.find_pert_particles_interactions(self.model, 222 pert_order = order)['soft_particles'] 223 commandline += "define pert_%s = %s;" % (order.replace(' ',''), ' '.join(map(str,pert)) ) 224 225 # check if we have to increase by one the born order 226 if '%s=' % order in process: 227 result=re.split(' ',process) 228 process='' 229 for r in result: 230 if '%s=' % order in r: 231 ior=re.split('=',r) 232 r='QCD=%i' % (int(ior[1])+1) 233 process=process+r+' ' 234 #handle special tag $ | / @ 235 result = re.split('([/$@]|\w+(?:^2)?(?:=|<=|>)?\w+)', process, 1) 236 if len(result) ==3: 237 process, split, rest = result 238 commandline+="add process %s pert_%s %s%s %s --no_warning=duplicate;" % (process, order.replace(' ','') ,split, rest, final) 239 else: 240 commandline +='add process %s pert_%s %s --no_warning=duplicate;' % (process,order.replace(' ',''), final) 241 elif order.startswith(('noborn=')): 242 # pass in sqrvirt= 243 return "add process %s ;" % proc.replace('noborn=', 'sqrvirt=') 244 245 else: 246 #just return the input. since this Madloop. 247 return "add process %s ;" % proc 248 return commandline
249 250
251 - def check_events(self):
252 """Check some basic property of the events file""" 253 254 sum_of_weight = 0 255 sum_of_abs_weight = 0 256 negative_event = 0 257 positive_event = 0 258 259 start = time.time() 260 for event_nb,event in enumerate(self.lhe_input): 261 #control logger 262 if (event_nb % max(int(10**int(math.log10(float(event_nb)+1))),10)==0): 263 running_time = misc.format_timer(time.time()-start) 264 logger.info('Event nb %s %s' % (event_nb, running_time)) 265 if (event_nb==10001): logger.info('reducing number of print status. Next status update in 10000 events') 266 267 try: 268 event.check() #check 4 momenta/... 269 except Exception, error: 270 print event 271 raise error 272 sum_of_weight += event.wgt 273 sum_of_abs_weight += abs(event.wgt) 274 if event.wgt < 0 : 275 negative_event +=1 276 else: 277 positive_event +=1 278 279 logger.info("total cross-section: %s" % sum_of_weight) 280 logger.info("total abs cross-section: %s" % sum_of_abs_weight) 281 logger.info("fraction of negative event %s", negative_event/(negative_event+positive_event)) 282 logger.info("total number of events %s", (negative_event+positive_event)) 283 logger.info("negative event %s", negative_event)
284 285 286 287 288 @extended_cmd.debug()
289 - def complete_import(self, text, line, begidx, endidx):
290 "Complete the import command" 291 292 args=self.split_arg(line[0:begidx]) 293 294 if len(args) == 1: 295 base_dir = '.' 296 else: 297 base_dir = args[1] 298 299 return self.path_completion(text, base_dir) 300 301 # Directory continuation 302 if os.path.sep in args[-1] + text: 303 return self.path_completion(text, 304 pjoin(*[a for a in args if \ 305 a.endswith(os.path.sep)]))
306
307 - def help_change(self):
308 """help for change command""" 309 310 print "change model X :use model X for the reweighting" 311 print "change process p p > e+ e-: use a new process for the reweighting" 312 print "change process p p > mu+ mu- --add : add one new process to existing ones"
313
314 - def do_change(self, line):
315 """allow to define a second model/processes""" 316 317 global nb_f2py_module 318 319 args = self.split_arg(line) 320 if len(args)<2: 321 logger.critical("not enough argument (need at least two). Discard line") 322 if args[0] == "model": 323 nb_f2py_module += 1 # tag to force the f2py to reload 324 self.second_model = " ".join(args[1:]) 325 if self.has_standalone_dir: 326 self.terminate_fortran_executables() 327 self.has_standalone_dir = False 328 elif args[0] == "process": 329 nb_f2py_module += 1 330 if self.has_standalone_dir: 331 self.terminate_fortran_executables() 332 self.has_standalone_dir = False 333 if args[-1] == "--add": 334 self.second_process.append(" ".join(args[1:-1])) 335 else: 336 self.second_process = [" ".join(args[1:])] 337 elif args[0] == "output": 338 if args[1] in ['default', '2.0', 'unweight']: 339 self.output_type = args[1] 340 elif args[0] == "helicity": 341 self.helicity_reweighting = banner.ConfigFile.format_variable(args[1], bool, "helicity") 342 elif args[0] == "mode": 343 if args[1] != 'LO': 344 if 'OLP' in self.mother.options and self.mother.options['OLP'].lower() != 'madloop': 345 logger.warning("Only LO reweighting is allowed for OLP!=MadLoop. Keeping the mode to LO.") 346 self.rwgt_mode = 'LO' 347 elif not self.banner.get_detail('run_card','store_rwgt_info', default=False): 348 logger.warning("Missing information for NLO type of reweighting. Keeping the mode to LO.") 349 self.rwgt_mode = 'LO' 350 elif 'lhapdf' in self.mother.options and not self.mother.options['lhapdf']: 351 logger.warning('NLO accurate reweighting requires lhapdf to be installed. Pass in approximate LO mode.') 352 self.rwgt_mode = 'LO' 353 else: 354 self.rwgt_mode = args[1] 355 else: 356 self.rwgt_mode = args[1] 357 elif args[0] == "rwgt_dir": 358 self.rwgt_dir = args[1] 359 if not os.path.exists(self.rwgt_dir): 360 os.mkdir(self.rwgt_dir) 361 else: 362 logger.critical("unknown option! %s. Discard line." % args[0])
363 364
365 - def check_launch(self, args):
366 """check the validity of the launch command""" 367 368 if not self.lhe_input: 369 if isinstance(self.lhe_input, lhe_parser.EventFile): 370 self.lhe_input = lhe_parser.EventFile(self.lhe_input.name) 371 else: 372 raise self.InvalidCmd("No events files defined.") 373 374 opts = {'rwgt_name':None} 375 if any(a.startswith('--') for a in args): 376 for a in args[:]: 377 if a.startswith('--') and '=' in a: 378 key,value = a[2:].split('=') 379 opts[key] = value .replace("'","") .replace('"','') 380 return opts
381
382 - def help_launch(self):
383 """help for the launch command""" 384 385 logger.info('''Add to the loaded events a weight associated to a 386 new param_card (to be define). The weight returned is the ratio of the 387 square matrix element by the squared matrix element of production. 388 All scale are kept fix for this re-weighting.''')
389 390
391 - def get_weight_names(self):
392 """ return the various name for the computed weights """ 393 394 if self.rwgt_mode == 'LO': 395 return [''] 396 elif self.rwgt_mode == 'NLO': 397 return ['_nlo'] 398 elif self.rwgt_mode == 'LO+NLO': 399 return ['_lo', '_nlo'] 400 elif self.rwgt_mode == 'NLO_tree': 401 return ['_tree'] 402 elif not self.rwgt_mode and self.has_nlo : 403 return ['_nlo'] 404 else: 405 return ['']
406 407 @misc.mute_logger()
408 - def do_launch(self, line):
409 """end of the configuration launched the code""" 410 411 args = self.split_arg(line) 412 opts = self.check_launch(args) 413 if opts['rwgt_name']: 414 self.options['rwgt_name'] = opts['rwgt_name'] 415 416 model_line = self.banner.get('proc_card', 'full_model_line') 417 418 if not self.has_standalone_dir: 419 if self.rwgt_dir and os.path.exists(pjoin(self.rwgt_dir,'rw_me','rwgt.pkl')): 420 self.load_from_pickle() 421 self.me_dir = self.rwgt_dir 422 else: 423 self.create_standalone_directory() 424 425 if self.rwgt_dir: 426 path_me =self.rwgt_dir 427 else: 428 path_me = self.me_dir 429 430 if self.second_model or self.second_process: 431 rw_dir = pjoin(path_me, 'rw_me_second') 432 else: 433 rw_dir = pjoin(path_me, 'rw_me') 434 435 if not '--keep_card' in args: 436 ff = open(pjoin(rw_dir,'Cards', 'param_card.dat'), 'w') 437 ff.write(self.banner['slha']) 438 ff.close() 439 if self.has_nlo and self.rwgt_mode != "LO": 440 rwdir_virt = rw_dir.replace('rw_me', 'rw_mevirt') 441 files.ln(ff.name, starting_dir=pjoin(rwdir_virt, 'Cards')) 442 ff = open(pjoin(path_me, 'rw_me','Cards', 'param_card_orig.dat'), 'w') 443 ff.write(self.banner['slha']) 444 ff.close() 445 if self.has_nlo and self.rwgt_mode != "LO": 446 files.ln(ff.name, starting_dir=pjoin(path_me, 'rw_mevirt', 'Cards')) 447 cmd = common_run_interface.CommonRunCmd.ask_edit_card_static(cards=['param_card.dat'], 448 ask=self.ask, pwd=rw_dir, first_cmd=self.stored_line) 449 self.stored_line = None 450 451 # get the names of type of reweighting requested 452 type_rwgt = self.get_weight_names() 453 454 # check for potential scan in the new card 455 new_card = open(pjoin(rw_dir, 'Cards', 'param_card.dat')).read() 456 pattern_scan = re.compile(r'''^[\s\d]*scan''', re.I+re.M) 457 param_card_iterator = [] 458 if pattern_scan.search(new_card): 459 try: 460 import internal.extended_cmd as extended_internal 461 Shell_internal = extended_internal.CmdShell 462 except: 463 Shell_internal = None 464 import madgraph.interface.extended_cmd as extended_cmd 465 if not isinstance(self.mother, (extended_cmd.CmdShell, Shell_internal)): 466 raise Exception, "scan are not allowed on the Web" 467 # at least one scan parameter found. create an iterator to go trough the cards 468 main_card = check_param_card.ParamCardIterator(new_card) 469 if self.options['rwgt_name']: 470 self.options['rwgt_name'] = '%s_0' % self.options['rwgt_name'] 471 472 param_card_iterator = main_card 473 first_card = param_card_iterator.next(autostart=True) 474 new_card = first_card.write() 475 first_card.write(pjoin(rw_dir, 'Cards', 'param_card.dat')) 476 # check if "Auto" is present for a width parameter 477 if "auto" in new_card.lower(): 478 self.mother.check_param_card(pjoin(rw_dir, 'Cards', 'param_card.dat')) 479 new_card = open(pjoin(rw_dir, 'Cards', 'param_card.dat')).read() 480 481 482 # Find new tag in the banner and add information if needed 483 if 'initrwgt' in self.banner: 484 if 'name=\'mg_reweighting\'' in self.banner['initrwgt']: 485 blockpat = re.compile(r'''<weightgroup name=\'mg_reweighting\'\s*>(?P<text>.*?)</weightgroup>''', re.I+re.M+re.S) 486 before, content, after = blockpat.split(self.banner['initrwgt']) 487 header_rwgt_other = before + after 488 pattern = re.compile('<weight id=\'(?:rwgt_(?P<id>\d+)|(?P<id2>[_\w]+))(?P<rwgttype>\s*|_\w+)\'>(?P<info>.*?)</weight>', re.S+re.I+re.M) 489 mg_rwgt_info = pattern.findall(content) 490 491 maxid = 0 492 for k,(i, fulltag, nlotype, diff) in enumerate(mg_rwgt_info): 493 if i: 494 if int(i) > maxid: 495 maxid = int(i) 496 mg_rwgt_info[k] = (i, nlotype, diff) # remove the pointless fulltag tag 497 else: 498 mg_rwgt_info[k] = (fulltag, nlotype, diff) # remove the pointless id tag 499 500 maxid += 1 501 rewgtid = maxid 502 if self.options['rwgt_name']: 503 #ensure that the entry is not already define if so overwrites it 504 misc.sprint(mg_rwgt_info) 505 for (i, nlotype, diff) in mg_rwgt_info[:]: 506 for flag in type_rwgt: 507 if 'rwgt_%s' % i == '%s%s' %(self.options['rwgt_name'],flag) or \ 508 i == '%s%s' % (self.options['rwgt_name'], flag): 509 logger.warning("tag %s%s already defines, will replace it", self.options['rwgt_name'],flag) 510 mg_rwgt_info.remove((i, nlotype, diff)) 511 512 else: 513 header_rwgt_other = self.banner['initrwgt'] 514 mg_rwgt_info = [] 515 rewgtid = 1 516 else: 517 self.banner['initrwgt'] = '' 518 header_rwgt_other = '' 519 mg_rwgt_info = [] 520 rewgtid = 1 521 522 # add the reweighting in the banner information: 523 #starts by computing the difference in the cards. 524 s_orig = self.banner['slha'] 525 s_new = new_card 526 527 #define tag for the run 528 if self.options['rwgt_name']: 529 tag = self.options['rwgt_name'] 530 else: 531 tag = str(rewgtid) 532 533 if not self.second_model: 534 old_param = check_param_card.ParamCard(s_orig.splitlines()) 535 new_param = check_param_card.ParamCard(s_new.splitlines()) 536 card_diff = old_param.create_diff(new_param) 537 if card_diff == '' and not self.second_process: 538 if not __debug__: 539 logger.warning(' REWEIGHTING: original card and new card are identical. Bypass this run') 540 return 541 else: 542 logger.warning(' REWEIGHTING: original card and new card are identical. Run it due to debug mode') 543 #raise self.InvalidCmd, 'original card and new card are identical' 544 try: 545 if old_param['sminputs'].get(3)- new_param['sminputs'].get(3) > 1e-3 * new_param['sminputs'].get(3): 546 logger.warning("We found different value of alpha_s. Note that the value of alpha_s used is the one associate with the event and not the one from the cards.") 547 except Exception, error: 548 logger.debug("error in check of alphas: %s" % str(error)) 549 pass #this is a security 550 if not self.second_process: 551 for name in type_rwgt: 552 mg_rwgt_info.append((tag, name, card_diff)) 553 else: 554 str_proc = "\n change process ".join([""]+self.second_process) 555 for name in type_rwgt: 556 mg_rwgt_info.append((tag, name, str_proc + '\n'+ card_diff)) 557 else: 558 str_info = "change model %s" % self.second_model 559 if self.second_process: 560 str_info += "\n change process ".join([""]+self.second_process) 561 card_diff = str_info 562 str_info += '\n' + s_new 563 for name in type_rwgt: 564 mg_rwgt_info.append((tag, name, str_info)) 565 # re-create the banner. 566 self.banner['initrwgt'] = header_rwgt_other 567 self.banner['initrwgt'] += '\n<weightgroup name=\'mg_reweighting\'>\n' 568 for tag, rwgttype, diff in mg_rwgt_info: 569 if tag.isdigit(): 570 self.banner['initrwgt'] += '<weight id=\'rwgt_%s%s\'>%s</weight>\n' % \ 571 (tag, rwgttype, diff) 572 else: 573 self.banner['initrwgt'] += '<weight id=\'%s%s\'>%s</weight>\n' % \ 574 (tag, rwgttype, diff) 575 self.banner['initrwgt'] += '\n</weightgroup>\n' 576 self.banner['initrwgt'] = self.banner['initrwgt'].replace('\n\n', '\n') 577 578 579 start = time.time() 580 cross, ratio, ratio_square,error = {},{},{}, {} 581 for name in type_rwgt + ['orig']: 582 cross[name], error[name] = 0.,0. 583 ratio[name],ratio_square[name] = 0., 0.# to compute the variance and associate error 584 585 if self.output_type == "default": 586 output = open( self.lhe_input.name +'rw', 'w') 587 #write the banner to the output file 588 self.banner.write(output, close_tag=False) 589 else: 590 output = {} 591 for name in type_rwgt: 592 output[name] = open( self.lhe_input.name +'rw'+name, 'w') 593 #write the banner to the output file 594 self.banner.write(output[name], close_tag=False) 595 596 logger.info('starts to compute weight for events with the following modification to the param_card:') 597 logger.info(card_diff.replace('\n','\nKEEP:')) 598 # prepare the output file for the weight plot 599 if self.mother: 600 out_path = pjoin(self.mother.me_dir, 'Events', 'reweight.lhe') 601 output2 = open(out_path, 'w') 602 lha_strategy = self.banner.get_lha_strategy() 603 self.banner.set_lha_strategy(4*lha_strategy/abs(lha_strategy)) 604 self.banner.write(output2, close_tag=False) 605 self.banner.set_lha_strategy(lha_strategy) 606 new_banner = banner.Banner(self.banner) 607 if not hasattr(self, 'run_card'): 608 self.run_card = new_banner.charge_card('run_card') 609 self.run_card['run_tag'] = 'reweight_%s' % rewgtid 610 new_banner['slha'] = s_new 611 del new_banner['initrwgt'] 612 assert 'initrwgt' in self.banner 613 ff = open(pjoin(self.mother.me_dir,'Events',self.mother.run_name, '%s_%s_banner.txt' % \ 614 (self.mother.run_name, self.run_card['run_tag'])),'w') 615 new_banner.write(ff) 616 ff.close() 617 618 # Loop over all events 619 if self.options['rwgt_name']: 620 tag_name = self.options['rwgt_name'] 621 else: 622 tag_name = 'rwgt_%s' % rewgtid 623 624 os.environ['GFORTRAN_UNBUFFERED_ALL'] = 'y' 625 if self.lhe_input.closed: 626 self.lhe_input = lhe_parser.EventFile(self.lhe_input.name) 627 628 # Multicore option not really stable -> not use it 629 nb_core = 1 630 # if nb_core >1: 631 # multicore = cluster.MultiCore(nb_core) 632 633 self.lhe_input.seek(0) 634 for event_nb,event in enumerate(self.lhe_input): 635 #control logger 636 if (event_nb % max(int(10**int(math.log10(float(event_nb)+1))),10)==0): 637 running_time = misc.format_timer(time.time()-start) 638 logger.info('Event nb %s %s' % (event_nb, running_time)) 639 if (event_nb==10001): logger.info('reducing number of print status. Next status update in 10000 events') 640 641 if nb_core > 1: 642 # Multicore option not really stable -> not use it 643 while 1: 644 if multicore.queue.qsize() < 100 * nb_core: 645 multicore.submit(self.write_reweighted_event, argument=[event, tag_name]) 646 break 647 #else: 648 # time.sleep(0.001) 649 continue 650 else: 651 weight = self.calculate_weight(event) 652 if not isinstance(weight, dict): 653 weight = {'':weight} 654 655 for name in weight: 656 cross[name] += weight[name] 657 ratio[name] += weight[name]/event.wgt 658 ratio_square[name] += (weight[name]/event.wgt)**2 659 660 # ensure to have a consistent order of the weights. new one are put 661 # at the back, remove old position if already defines 662 for tag in type_rwgt: 663 try: 664 event.reweight_order.remove('%s%s' % (tag_name,tag)) 665 except ValueError: 666 continue 667 668 event.reweight_order += ['%s%s' % (tag_name,name) for name in type_rwgt] 669 if self.output_type == "default": 670 for name in weight: 671 if 'orig' in name: 672 continue 673 event.reweight_data['%s%s' % (tag_name,name)] = weight[name] 674 #write this event with weight 675 output.write(str(event)) 676 if self.mother: 677 event.wgt = weight[type_rwgt[0]] 678 event.reweight_data = {} 679 output2.write(str(event)) 680 else: 681 for i,name in enumerate(weight): 682 event.wgt = weight[name] 683 event.reweight_data = {} 684 if self.mother and len(weight)==1: 685 output2.write(str(event)) 686 elif self.mother and i == 0: 687 output[name].write(str(event)) 688 output2.write(str(event)) 689 else: 690 output[name].write(str(event)) 691 692 # check normalisation of the events: 693 if 'event_norm' in self.run_card: 694 if self.run_card['event_norm'] == 'average': 695 for key, value in cross.items(): 696 cross[key] = value / (event_nb+1) 697 698 699 running_time = misc.format_timer(time.time()-start) 700 logger.info('All event done (nb_event: %s) %s' % (event_nb+1, running_time)) 701 702 703 if self.output_type == "default": 704 output.write('</LesHouchesEvents>\n') 705 output.close() 706 else: 707 for key in output: 708 output[key].write('</LesHouchesEvents>\n') 709 output.close() 710 711 os.environ['GFORTRAN_UNBUFFERED_ALL'] = 'n' 712 713 if self.mother: 714 output2.write('</LesHouchesEvents>\n') 715 output2.close() 716 # add output information 717 if hasattr(self.mother, 'results'): 718 run_name = self.mother.run_name 719 results = self.mother.results 720 results.add_run(run_name, self.run_card, current=True) 721 results.add_detail('nb_event', event_nb+1) 722 name = type_rwgt[0] 723 results.add_detail('cross', cross[name]) 724 event_nb +=1 725 for name in type_rwgt: 726 variance = ratio_square[name]/event_nb - (ratio[name]/event_nb)**2 727 orig_cross, orig_error = self.orig_cross 728 error[name] = variance/math.sqrt(event_nb) * orig_cross + ratio[name]/event_nb * orig_error 729 results.add_detail('error', error[type_rwgt[0]]) 730 import madgraph.interface.madevent_interface as ME_interface 731 if isinstance(self.mother, ME_interface.MadEventCmd): 732 self.mother.create_plot(mode='reweight', event_path=output2.name, 733 tag=self.run_card['run_tag']) 734 #modify the html output to add the original run 735 if 'plot' in results.current.reweight: 736 html_dir = pjoin(self.mother.me_dir, 'HTML', run_name) 737 td = pjoin(self.mother.options['td_path'], 'td') 738 MA = pjoin(self.mother.options['madanalysis_path']) 739 path1 = pjoin(html_dir, 'plots_parton') 740 path2 = pjoin(html_dir, 'plots_%s' % self.run_card['run_tag']) 741 outputplot = path2 742 combine_plots.merge_all_plots(path2, path1, outputplot, td, MA) 743 #results.update_status(level='reweight') 744 #results.update(status, level, makehtml=True, error=False) 745 746 #old_name = self.mother.results.current['run_name'] 747 #new_run = '%s_rw_%s' % (old_name, rewgtid) 748 #self.mother.results.add_run( new_run, self.run_card) 749 #self.mother.results.add_detail('nb_event', event_nb+1) 750 #self.mother.results.add_detail('cross', cross) 751 #self.mother.results.add_detail('error', 'nan') 752 #self.mother.do_plot('%s -f' % new_run) 753 #self.mother.update_status('Reweight %s done' % rewgtid, 'madspin') 754 #self.mother.results.def_current(old_name) 755 #self.run_card['run_tag'] = self.run_card['run_tag'][9:] 756 #self.mother.run_name = old_name 757 self.lhe_input.close() 758 if not self.mother or self.output_type != "default" : 759 target = pjoin(self.mother.me_dir, 'Events', run_name, 'events.lhe') 760 else: 761 target = self.lhe_input.name 762 763 if self.output_type == "default": 764 files.mv(output.name, target) 765 logger.info('Event %s have now the additional weight' % self.lhe_input.name) 766 elif self.output_type == "unweight": 767 output2.close() 768 lhe = lhe_parser.EventFile(output2.name) 769 nb_event = lhe.unweight(target) 770 if self.mother and hasattr(self.mother, 'results'): 771 results = self.mother.results 772 results.add_detail('nb_event', nb_event) 773 results.current.parton.append('lhe') 774 logger.info('Event %s is now unweighted under the new theory' % output2.name) 775 else: 776 files.mv(output2.name, self.lhe_input.name) 777 if self.mother and hasattr(self.mother, 'results'): 778 results = self.mother.results 779 results.current.parton.append('lhe') 780 logger.info('Event %s is now created with new central weight' % output2.name) 781 782 for name in cross: 783 if name == 'orig': 784 continue 785 logger.info('new cross-section is %s: %g pb (indicative error: %g pb)' %\ 786 ('(%s)' %name if name else '',cross[name], error[name])) 787 788 self.terminate_fortran_executables(new_card_only=True) 789 #store result 790 for name in cross: 791 if name == 'orig': 792 self.all_cross_section[name] = (cross[name], error[name]) 793 else: 794 self.all_cross_section[(tag_name,name)] = (cross[name], error[name]) 795 796 # perform the scanning 797 if param_card_iterator: 798 for i,card in enumerate(param_card_iterator): 799 if self.options['rwgt_name']: 800 self.options['rwgt_name'] = '%s_%s' % (self.options['rwgt_name'].rsplit('_',1)[0], i+1) 801 card.write(pjoin(rw_dir, 'Cards', 'param_card.dat')) 802 self.exec_cmd("launch --keep_card", printcmd=False, precmd=True) 803 804 self.options['rwgt_name'] = None
805
806 - def do_set(self, line):
807 "Not in help" 808 809 logger.warning("Invalid Syntax. The command 'set' should be placed after the 'launch' one. Continuing by adding automatically 'launch'") 810 self.stored_line = "set %s" % line 811 return self.exec_cmd("launch")
812
813 - def default(self, line, log=True):
814 """Default action if line is not recognized""" 815 816 if os.path.isfile(line): 817 if log: 818 logger.warning("Invalid Syntax. The path to a param_card' should be placed after the 'launch' command. Continuing by adding automatically 'launch'") 819 self.stored_line = line 820 return self.exec_cmd("launch") 821 else: 822 return super(ReweightInterface,self).default(line, log=log)
823
824 - def write_reweighted_event(self, event, tag_name, **opt):
825 """a function for running in multicore""" 826 827 if not hasattr(opt['thread_space'], "calculator"): 828 opt['thread_space'].calculator = {} 829 opt['thread_space'].calculator_nbcall = {} 830 opt['thread_space'].cross = 0 831 opt['thread_space'].output = open( self.lhe_input.name +'rw.%s' % opt['thread_id'], 'w') 832 if self.mother: 833 out_path = pjoin(self.mother.me_dir, 'Events', 'reweight.lhe.%s' % opt['thread_id']) 834 opt['thread_space'].output2 = open(out_path, 'w') 835 836 weight = self.calculate_weight(event, space=opt['thread_space']) 837 opt['thread_space'].cross += weight 838 if self.output_type == "default": 839 event.reweight_data[tag_name] = weight 840 #write this event with weight 841 opt['thread_space'].output.write(str(event)) 842 if self.mother: 843 event.wgt = weight 844 event.reweight_data = {} 845 opt['thread_space'].output2.write(str(event)) 846 else: 847 event.wgt = weight 848 event.reweight_data = {} 849 if self.mother: 850 opt['thread_space'].output2.write(str(event)) 851 else: 852 opt['thread_space'].output.write(str(event)) 853 854 return 0
855
856 - def calculate_weight(self, event, space=None):
857 """space defines where to find the calculator (in multicore)""" 858 859 if self.has_nlo and self.rwgt_mode != "LO": 860 return self.calculate_nlo_weight(event, space) 861 862 if not space: 863 space = self 864 event.parse_reweight() 865 866 # LO reweighting 867 w_orig = self.calculate_matrix_element(event, 0, space) 868 w_new = self.calculate_matrix_element(event, 1, space) 869 870 if w_orig == 0: 871 tag, order = event.get_tag_and_order() 872 orig_order, Pdir, hel_dict = self.id_to_path[tag] 873 misc.sprint(w_orig, w_new) 874 misc.sprint(event) 875 misc.sprint(self.invert_momenta(event.get_momenta(orig_order))) 876 misc.sprint(event.get_momenta(orig_order)) 877 misc.sprint(event.aqcd) 878 hel_order = event.get_helicity(orig_order) 879 if self.helicity_reweighting and 9 not in hel_order: 880 nhel = hel_dict[tuple(hel_order)] 881 else: 882 nhel = 0 883 misc.sprint(nhel, Pdir, hel_dict) 884 raise Exception, "Invalid matrix element for original computation (weight=0)" 885 886 return {'orig': event.wgt, '': w_new/w_orig*event.wgt}
887
888 - def calculate_nlo_weight(self, event, space=None):
889 890 891 type_nlo = self.get_weight_names() 892 final_weight = {'orig': event.wgt} 893 894 if not space: 895 space = self #for multicore: not use so far 896 897 event.parse_reweight() 898 event.parse_nlo_weight() 899 900 #initialise the input to the function which recompute the weight 901 scales2 = [] 902 pdg = [] 903 bjx = [] 904 wgt_tree = [] # reweight for loop-improved type 905 wgt_virt = [] #reweight b+v together 906 base_wgt = [] 907 gs=[] 908 qcdpower = [] 909 ref_wgts = [] #for debugging 910 911 orig_wgt = 0 912 for cevent in event.nloweight.cevents: 913 #check if we need to compute the virtual for that cevent 914 need_V = False # the real is nothing else than the born for a N+1 config 915 all_ctype = [w.type for w in cevent.wgts] 916 if '_nlo' in type_nlo and any(c in all_ctype for c in [2,14,15]): 917 need_V =True 918 919 w_orig = self.calculate_matrix_element(cevent, 0, space) 920 w_new = self.calculate_matrix_element(cevent, 1, space) 921 ratio_T = w_new/w_orig 922 if need_V: 923 scale2 = cevent.wgts[0].scales2[0] 924 #for scale2 in set(c.scales2[1] for c in cevent.wgts): 925 w_origV = self.calculate_matrix_element(cevent, 'V0', space, scale2=scale2) 926 w_newV = self.calculate_matrix_element(cevent, 'V1', space, scale2=scale2) 927 ratio_BV = (w_newV + w_new) / (w_origV + w_orig) 928 ratio_V = w_newV/w_origV 929 else: 930 ratio_V = "should not be used" 931 ratio_BV = "should not be used" 932 933 for c_wgt in cevent.wgts: 934 orig_wgt += c_wgt.ref_wgt 935 #add the information to the input 936 scales2.append(c_wgt.scales2) 937 pdg.append(c_wgt.pdgs[:2]) 938 939 bjx.append(c_wgt.bjks) 940 qcdpower.append(c_wgt.qcdpower) 941 gs.append(c_wgt.gs) 942 ref_wgts.append(c_wgt.ref_wgt) 943 944 if '_nlo' in type_nlo: 945 if c_wgt.type in [2,14,15]: 946 R = ratio_BV 947 else: 948 R = ratio_T 949 950 new_wgt = [c_wgt.pwgt[0] * R, 951 c_wgt.pwgt[1] * ratio_T, 952 c_wgt.pwgt[2] * ratio_T] 953 wgt_virt.append(new_wgt) 954 955 if '_tree' in type_nlo: 956 new_wgt = [c_wgt.pwgt[0] * ratio_T, 957 c_wgt.pwgt[1] * ratio_T, 958 c_wgt.pwgt[2] * ratio_T] 959 wgt_tree.append(new_wgt) 960 base_wgt.append(c_wgt.pwgt[:3]) 961 962 #change the ordering to the fortran one: 963 scales2 = self.invert_momenta(scales2) 964 pdg = self.invert_momenta(pdg) 965 bjx = self.invert_momenta(bjx) 966 # re-compute original weight to reduce numerical inacurracy 967 base_wgt = self.invert_momenta(base_wgt) 968 969 orig_wgt_check, partial_check = self.combine_wgt(scales2, pdg, bjx, base_wgt, gs, qcdpower, 1., 1.) 970 971 if '_nlo' in type_nlo: 972 wgt = self.invert_momenta(wgt_virt) 973 with misc.stdchannel_redirected(sys.stdout, os.devnull): 974 new_out, partial = self.combine_wgt(scales2, pdg, bjx, wgt, gs, qcdpower, 1., 1.) 975 # try to correct for precision issue 976 avg = [partial_check[i]/ref_wgts[i] for i in range(len(ref_wgts))] 977 out = sum(partial[i]/avg[i] if 0.85<avg[i]<1.15 else 0 \ 978 for i in range(len(avg))) 979 final_weight['_nlo'] = out/orig_wgt*event.wgt 980 981 982 if '_tree' in type_nlo: 983 wgt = self.invert_momenta(wgt_tree) 984 with misc.stdchannel_redirected(sys.stdout, os.devnull): 985 out, partial = self.combine_wgt(scales2, pdg, bjx, wgt, gs, qcdpower, 1., 1.) 986 # try to correct for precision issue 987 avg = [partial_check[i]/ref_wgts[i] for i in range(len(ref_wgts))] 988 new_out = sum(partial[i]/avg[i] if 0.85<avg[i]<1.15 else partial[i] \ 989 for i in range(len(avg))) 990 final_weight['_tree'] = new_out/orig_wgt*event.wgt 991 992 if '_lo' in type_nlo: 993 w_orig = self.calculate_matrix_element(event, 0, space) 994 w_new = self.calculate_matrix_element(event, 1, space) 995 final_weight['_lo'] = w_new/w_orig*event.wgt 996 997 return final_weight
998 999 1000 @staticmethod
1001 - def invert_momenta(p):
1002 """ fortran/C-python do not order table in the same order""" 1003 new_p = [] 1004 for i in range(len(p[0])): new_p.append([0]*len(p)) 1005 for i, onep in enumerate(p): 1006 for j, x in enumerate(onep): 1007 new_p[j][i] = x 1008 return new_p
1009 1010 @staticmethod
1011 - def rename_f2py_lib(Pdir, tag):
1012 if tag == 2: 1013 return 1014 if os.path.exists(pjoin(Pdir, 'matrix%spy.so' % tag)): 1015 return 1016 else: 1017 open(pjoin(Pdir, 'matrix%spy.so' % tag),'w').write(open(pjoin(Pdir, 'matrix2py.so') 1018 ).read().replace('matrix2py', 'matrix%spy' % tag))
1019
1020 - def calculate_matrix_element(self, event, hypp_id, space, scale2=0):
1021 """routine to return the matrix element""" 1022 1023 tag, order = event.get_tag_and_order() 1024 if isinstance(hypp_id, str) and hypp_id.startswith('V'): 1025 tag = (tag,'V') 1026 hypp_id = int(hypp_id[1:]) 1027 base = "rw_mevirt" 1028 else: 1029 base = "rw_me" 1030 1031 if (not self.second_model and not self.second_process) or hypp_id==0: 1032 orig_order, Pdir, hel_dict = self.id_to_path[tag] 1033 else: 1034 orig_order, Pdir, hel_dict = self.id_to_path_second[tag] 1035 1036 1037 run_id = (tag, hypp_id) 1038 1039 assert space == self 1040 start = False 1041 if run_id in space.calculator: 1042 external = space.calculator[run_id] 1043 # mod = space.calculator[(run_id,'module')] 1044 # #with misc.chdir(Pdir): 1045 # # if hypp_id==0: 1046 # # mod.initialise('param_card_orig.dat') 1047 # # else: 1048 # # mod.initialise('param_card.dat') 1049 elif (not self.second_model and not self.second_process) or hypp_id==0: 1050 # create the executable for this param_card 1051 subdir = pjoin(self.me_dir, base, 'SubProcesses') 1052 if self.me_dir not in sys.path: 1053 sys.path.insert(0,self.me_dir) 1054 if self.rwgt_dir and self.rwgt_dir not in sys.path: 1055 sys.path.insert(0,self.rwgt_dir) 1056 Pname = os.path.basename(Pdir) 1057 if hypp_id == 0: 1058 if (Pdir, 0) not in dir_to_f2py_free_mod: 1059 metag = 1 1060 dir_to_f2py_free_mod[(Pdir,0)] = (metag, nb_f2py_module) 1061 else: 1062 metag, old_module = dir_to_f2py_free_mod[(Pdir,0)] 1063 if old_module != nb_f2py_module: 1064 metag += 1 1065 dir_to_f2py_free_mod[(Pdir,0)] = (metag, nb_f2py_module) 1066 os.environ['MENUM'] = '2' 1067 if not self.rwgt_dir or not os.path.exists(pjoin(Pdir, 'matrix2py.so')): 1068 misc.compile(['matrix2py.so'], cwd=Pdir) 1069 self.rename_f2py_lib(Pdir, 2*metag) 1070 try: 1071 mymod = __import__('%s.SubProcesses.%s.matrix%spy' % (base, Pname, 2*metag), globals(), locals(), [],-1) 1072 except: 1073 import platform 1074 if platform.system() == 'Darwin': 1075 os.system('install_name_tool -change libMadLoop.dylib %s/libMadLoop.dylib matrix%spy.so' % (Pdir,2*metag)) 1076 mymod = __import__('%s.SubProcesses.%s.matrix%spy' % (base, Pname, 2*metag), globals(), locals(), [],-1) 1077 else: 1078 misc.sprint("fail compilation") 1079 raise 1080 S = mymod.SubProcesses 1081 P = getattr(S, Pname) 1082 mymod = getattr(P, 'matrix%spy' % (2*metag)) 1083 with misc.chdir(Pdir): 1084 with misc.stdchannel_redirected(sys.stdout, os.devnull): 1085 mymod.initialise('param_card_orig.dat') 1086 1087 1088 if hypp_id == 1: 1089 #incorrect line 1090 metag = dir_to_f2py_free_mod[(Pdir,0)][0] 1091 newtag = 2*metag+1 1092 self.rename_f2py_lib(Pdir, newtag) 1093 try: 1094 mymod = __import__('%s.SubProcesses.%s.matrix%spy' % (base, Pname, newtag), globals(), locals(), [],-1) 1095 except Exception, error: 1096 os.remove(pjoin(Pdir, 'matrix%spy.so' % newtag)) 1097 newtag = "L%s" % newtag 1098 os.environ['MENUM'] = newtag 1099 misc.compile(['matrix%spy.so' % newtag], cwd=Pdir) 1100 mymod = __import__('%s.SubProcesses.%s.matrix%spy' % (base, Pname, newtag), globals(), locals(), [],-1) 1101 1102 S = mymod.SubProcesses 1103 P = getattr(S, Pname) 1104 mymod = getattr(P, 'matrix%spy' % newtag) 1105 with misc.chdir(Pdir): 1106 with misc.stdchannel_redirected(sys.stdout, os.devnull): 1107 mymod.initialise('param_card.dat') 1108 1109 space.calculator[run_id] = mymod.get_me 1110 space.calculator[(run_id,'module')] = mymod 1111 external = space.calculator[run_id] 1112 else: 1113 subdir = pjoin(self.me_dir,'%s_second' % base, 'SubProcesses') 1114 if self.me_dir not in sys.path: 1115 sys.path.append(self.me_dir) 1116 1117 assert hypp_id == 1 1118 Pname = os.path.basename(Pdir) 1119 os.environ['MENUM'] = '2' 1120 if not self.rwgt_dir or not os.path.exists(pjoin(Pdir, 'matrix2py.so')): 1121 misc.compile(['matrix2py.so'], cwd=pjoin(subdir, Pdir)) 1122 if (Pdir, 1) not in dir_to_f2py_free_mod: 1123 metag = 1 1124 dir_to_f2py_free_mod[(Pdir,1)] = (metag, nb_f2py_module) 1125 else: 1126 metag, old_module = dir_to_f2py_free_mod[(Pdir,1)] 1127 if old_module != nb_f2py_module: 1128 metag += 1 1129 dir_to_f2py_free_mod[(Pdir,1)] = (metag, nb_f2py_module) 1130 self.rename_f2py_lib(Pdir, metag) 1131 try: 1132 mymod = __import__("%s_second.SubProcesses.%s.matrix%spy" % (base, Pname, metag)) 1133 except ImportError: 1134 os.remove(pjoin(Pdir, 'matrix%spy.so' % metag )) 1135 metag = "L%s" % metag 1136 os.environ['MENUM'] = str(metag) 1137 misc.compile(['matrix%spy.so' % metag], cwd=pjoin(subdir, Pdir)) 1138 mymod = __import__("%s_second.SubProcesses.%s.matrix%spy" % (base, Pname, metag)) 1139 1140 reload(mymod) 1141 S = mymod.SubProcesses 1142 P = getattr(S, Pname) 1143 mymod = getattr(P, 'matrix%spy' % metag) 1144 with misc.chdir(Pdir): 1145 with misc.stdchannel_redirected(sys.stdout, os.devnull): 1146 mymod.initialise('param_card.dat') 1147 space.calculator[run_id] = mymod.get_me 1148 space.calculator[(run_id,'module')] = mymod 1149 external = space.calculator[run_id] 1150 1151 1152 1153 p = event.get_momenta(orig_order) 1154 # add helicity information 1155 1156 hel_order = event.get_helicity(orig_order) 1157 if self.helicity_reweighting and 9 not in hel_order: 1158 nhel = hel_dict[tuple(hel_order)] 1159 if event[1].status == -1: #check if this is a 2 >N processes 1160 # need to pass to the rest-frame 1161 pboost = lhe_parser.FourMomentum(p[0]) + lhe_parser.FourMomentum(p[1]) 1162 for i,thisp in enumerate(p): 1163 p[i] = lhe_parser.FourMomentum(thisp).zboost(pboost).get_tuple() 1164 else: 1165 nhel = 0 1166 1167 p = self.invert_momenta(p) 1168 1169 with misc.chdir(Pdir): 1170 with misc.stdchannel_redirected(sys.stdout, os.devnull): 1171 if 'V' in tag or \ 1172 (hypp_id ==1 and self.second_process and any('sqrvirt' in l for l in self.second_process)): 1173 me_value = external(p,event.aqcd, math.sqrt(scale2), nhel) 1174 else: 1175 try: 1176 me_value = external(p,event.aqcd, nhel) 1177 except TypeError: 1178 me_value = external(p,event.aqcd, math.sqrt(scale2), nhel) 1179 1180 # for NLO we have also the stability status code 1181 if isinstance(me_value, tuple): 1182 me_value, code = me_value 1183 #if code points unstability -> returns 0 1184 hundred_value = (code % 1000) //100 1185 if hundred_value in [4]: 1186 me_value = 0. 1187 1188 return me_value
1189
1190 - def terminate_fortran_executables(self, new_card_only=False):
1191 """routine to terminate all fortran executables""" 1192 1193 for (mode, production) in dict(self.calculator): 1194 1195 if new_card_only and production == 0: 1196 continue 1197 del self.calculator[(mode, production)]
1198
1199 - def do_quit(self, line):
1200 if self.exitted: 1201 return 1202 self.exitted = True 1203 1204 if 'init' in self.banner: 1205 cross = 0 1206 error = 0 1207 for line in self.banner['init'].split('\n'): 1208 split = line.split() 1209 if len(split) == 4: 1210 cross, error = float(split[0]), float(split[1]) 1211 if 'orig' not in self.all_cross_section: 1212 logger.info('Original cross-section: %s +- %s pb' % (cross, error)) 1213 else: 1214 logger.info('Original cross-section: %s +- %s pb (cross-section from sum of weights: %s)' % (cross, error, self.all_cross_section['orig'][0])) 1215 logger.info('Computed cross-section:') 1216 keys = self.all_cross_section.keys() 1217 keys.sort() 1218 for key in keys: 1219 if key == 'orig': 1220 continue 1221 logger.info('%s : %s +- %s pb' % (key[0] if not key[1] else '%s%s' % key, 1222 self.all_cross_section[key][0],self.all_cross_section[key][1] )) 1223 self.terminate_fortran_executables() 1224 1225 if self.rwgt_dir: 1226 self.save_to_pickle() 1227 1228 with misc.stdchannel_redirected(sys.stdout, os.devnull): 1229 for run_id in self.calculator: 1230 del self.calculator[run_id] 1231 del self.calculator
1232 1233
1234 - def __del__(self):
1235 self.do_quit('')
1236 1237
1238 - def adding_me(self, matrix_elements, path):
1239 """Adding one element to the list based on the matrix element"""
1240 1241 1242 @misc.mute_logger()
1243 - def create_standalone_directory(self, second=False):
1244 """generate the various directory for the weight evaluation""" 1245 1246 data={} 1247 if not second: 1248 data['paths'] = ['rw_me', 'rw_mevirt'] 1249 # model 1250 info = self.banner.get('proc_card', 'full_model_line') 1251 if '-modelname' in info: 1252 data['mg_names'] = False 1253 else: 1254 data['mg_names'] = True 1255 data['model_name'] = self.banner.get('proc_card', 'model') 1256 #processes 1257 data['processes'] = [line[9:].strip() for line in self.banner.proc_card 1258 if line.startswith('generate')] 1259 data['processes'] += [' '.join(line.split()[2:]) for line in self.banner.proc_card 1260 if re.search('^\s*add\s+process', line)] 1261 #object_collector 1262 self.id_to_path = {} 1263 data['id2path'] = self.id_to_path 1264 else: 1265 data['paths'] = ['rw_me_second', 'rw_mevirt_second'] 1266 # model 1267 if self.second_model: 1268 data['mg_names'] = True 1269 if ' ' in self.second_model: 1270 args = self.second_model.split() 1271 if '--modelname' in args: 1272 data['mg_names'] = False 1273 data['model_name'] = args[0] 1274 else: 1275 data['model_name'] = self.second_model 1276 else: 1277 data['model_name'] = None 1278 #processes 1279 if self.second_process: 1280 data['processes'] = self.second_process 1281 else: 1282 data['processes'] = [line[9:].strip() for line in self.banner.proc_card 1283 if line.startswith('generate')] 1284 data['processes'] += [' '.join(line.split()[2:]) 1285 for line in self.banner.proc_card 1286 if re.search('^\s*add\s+process', line)] 1287 #object_collector 1288 self.id_to_path_second = {} 1289 data['id2path'] = self.id_to_path_second 1290 1291 # 0. clean previous run ------------------------------------------------ 1292 if not self.rwgt_dir: 1293 path_me = self.me_dir 1294 else: 1295 path_me = self.rwgt_dir 1296 try: 1297 shutil.rmtree(pjoin(path_me,data['paths'][0])) 1298 except Exception: 1299 pass 1300 try: 1301 shutil.rmtree(pjoin(path_me, data['paths'][1])) 1302 except Exception: 1303 pass 1304 1305 # 1. prepare the interface---------------------------------------------- 1306 mgcmd = self.mg5cmd 1307 complex_mass = False 1308 has_cms = re.compile(r'''set\s+complex_mass_scheme\s*(True|T|1|true|$|;)''') 1309 for line in self.banner.proc_card: 1310 if line.startswith('set'): 1311 mgcmd.exec_cmd(line, printcmd=False, precmd=False, postcmd=False) 1312 if has_cms.search(line): 1313 complex_mass = True 1314 elif line.startswith('define'): 1315 try: 1316 mgcmd.exec_cmd(line, printcmd=False, precmd=False, postcmd=False) 1317 except Exception: 1318 pass 1319 1320 # 1. Load model--------------------------------------------------------- 1321 if not data['model_name'] and not second: 1322 raise self.InvalidCmd('Only UFO model can be loaded in this module.') 1323 elif data['model_name']: 1324 self.load_model(data['model_name'], data['mg_names'], complex_mass) 1325 modelpath = self.model.get('modelpath') 1326 if os.path.basename(modelpath) != mgcmd._curr_model['name']: 1327 name, restrict = mgcmd._curr_model['name'].rsplit('-',1) 1328 if os.path.exists(pjoin(os.path.dirname(modelpath),name, 'restrict_%s.dat' % restrict)): 1329 modelpath = pjoin(os.path.dirname(modelpath), mgcmd._curr_model['name']) 1330 1331 commandline="import model %s " % modelpath 1332 if not data['mg_names']: 1333 commandline += ' -modelname ' 1334 mgcmd.exec_cmd(commandline) 1335 1336 #multiparticles 1337 for name, content in self.banner.get('proc_card', 'multiparticles'): 1338 mgcmd.exec_cmd("define %s = %s" % (name, content)) 1339 1340 # 2. compute the production matrix element ----------------------------- 1341 has_nlo = False 1342 mgcmd.exec_cmd("set group_subprocesses False") 1343 1344 if not second: 1345 logger.info('generating the square matrix element for reweighting') 1346 else: 1347 logger.info('generating the square matrix element for reweighting (second model and/or processes)') 1348 start = time.time() 1349 commandline='' 1350 for proc in data['processes']: 1351 if '[' not in proc: 1352 commandline += "add process %s ;" % proc 1353 else: 1354 has_nlo = True 1355 commandline += self.get_LO_definition_from_NLO(proc) 1356 1357 commandline = commandline.replace('add process', 'generate',1) 1358 logger.info(commandline) 1359 try: 1360 mgcmd.exec_cmd(commandline, precmd=True, errorhandling=False) 1361 except diagram_generation.NoDiagramException: 1362 commandline='' 1363 for proc in data['processes']: 1364 if '[' not in proc: 1365 raise 1366 commandline += "add process %s ;" % proc 1367 commandline = commandline.replace('add process', 'generate',1) 1368 logger.info("RETRY with %s", commandline) 1369 mgcmd.exec_cmd(commandline, precmd=True) 1370 has_nlo = False 1371 except Exception, error: 1372 raise 1373 1374 commandline = 'output standalone_rw %s' % pjoin(path_me,data['paths'][0]) 1375 mgcmd.exec_cmd(commandline, precmd=True) 1376 logger.info('Done %.4g' % (time.time()-start)) 1377 self.has_standalone_dir = True 1378 1379 1380 # 3. Store id to directory information --------------------------------- 1381 matrix_elements = mgcmd._curr_matrix_elements.get_matrix_elements() 1382 1383 to_check = [] # list of tag that do not have a Pdir at creation time. 1384 for me in matrix_elements: 1385 for proc in me.get('processes'): 1386 initial = [] #filled in the next line 1387 final = [l.get('id') for l in proc.get('legs')\ 1388 if l.get('state') or initial.append(l.get('id'))] 1389 order = (initial, final) 1390 tag = proc.get_initial_final_ids() 1391 decay_finals = proc.get_final_ids_after_decay() 1392 1393 if tag[1] != decay_finals: 1394 order = (initial, list(decay_finals)) 1395 decay_finals.sort() 1396 tag = (tag[0], tuple(decay_finals)) 1397 Pdir = pjoin(path_me, data['paths'][0], 'SubProcesses', 1398 'P%s' % me.get('processes')[0].shell_string()) 1399 1400 if not os.path.exists(Pdir): 1401 to_check.append(tag) 1402 continue 1403 if tag in data['id2path']: 1404 if not Pdir == data['id2path'][tag][1]: 1405 misc.sprint(tag, Pdir, data['id2path'][tag][1]) 1406 raise self.InvalidCmd, '2 different process have the same final states. This module can not handle such situation' 1407 else: 1408 continue 1409 # build the helicity dictionary 1410 hel_nb = 0 1411 hel_dict = {9:0} # unknown helicity -> use full ME 1412 for helicities in me.get_helicity_matrix(): 1413 hel_nb +=1 #fortran starts at 1 1414 hel_dict[tuple(helicities)] = hel_nb 1415 1416 data['id2path'][tag] = [order, Pdir, hel_dict] 1417 1418 for tag in to_check: 1419 if tag not in self.id_to_path: 1420 logger.warning("no valid path for %s" % (tag,)) 1421 #raise self.InvalidCmd, "no valid path for %s" % (tag,) 1422 1423 # 4. Check MadLoopParam for Loop induced 1424 if os.path.exists(pjoin(path_me, data['paths'][0], 'Cards', 'MadLoopParams.dat')): 1425 MLCard = banner.MadLoopParam(pjoin(path_me, data['paths'][0], 'Cards', 'MadLoopParams.dat')) 1426 MLCard.set('WriteOutFilters', False) 1427 MLCard.set('UseLoopFilter', False) 1428 MLCard.set("DoubleCheckHelicityFilter", False) 1429 MLCard.set("HelicityFilterLevel", 0) 1430 MLCard.write(pjoin(path_me, data['paths'][0], 'SubProcesses', 'MadLoopParams.dat'), 1431 pjoin(path_me, data['paths'][0], 'Cards', 'MadLoopParams.dat'), 1432 commentdefault=False) 1433 1434 # 5. create the virtual for NLO reweighting --------------------------- 1435 if has_nlo and 'NLO' in self.rwgt_mode: 1436 # Do not pass here for LO/NLO_tree 1437 start = time.time() 1438 commandline='' 1439 for proc in data['processes']: 1440 if '[' not in proc: 1441 pass 1442 else: 1443 proc = proc.replace('[', '[ virt=') 1444 commandline += "add process %s ;" % proc 1445 # deactivate golem since it creates troubles 1446 old_options = dict(mgcmd.options) 1447 if mgcmd.options['golem'] or mgcmd.options['pjfry']: 1448 logger.info(" When doing NLO reweighting, MG5aMC cannot use the loop reduction algorithms Golem and/or PJFry++") 1449 mgcmd.options['golem'] = None 1450 mgcmd.options['pjfry'] = None 1451 commandline = commandline.replace('add process', 'generate',1) 1452 logger.info(commandline) 1453 mgcmd.exec_cmd(commandline, precmd=True) 1454 commandline = 'output standalone_rw %s -f' % pjoin(path_me, data['paths'][1]) 1455 mgcmd.exec_cmd(commandline, precmd=True) 1456 1457 #put back golem to original value 1458 mgcmd.options['golem'] = old_options['golem'] 1459 mgcmd.options['pjfry'] = old_options['pjfry'] 1460 # update make_opts 1461 m_opts = {} 1462 if mgcmd.options['lhapdf']: 1463 #lhapdfversion = subprocess.Popen([mgcmd.options['lhapdf'], '--version'], 1464 # stdout = subprocess.PIPE).stdout.read().strip()[0] 1465 m_opts['lhapdf'] = True 1466 m_opts['f2pymode'] = True 1467 m_opts['lhapdfversion'] = 5 # 6 always fail on my computer since 5 is compatible but slower always use 5 1468 m_opts['llhapdf'] = self.mother.get_lhapdf_libdir() 1469 else: 1470 raise Exception, "NLO reweighting requires LHAPDF to work correctly" 1471 1472 path = pjoin(path_me,data['paths'][1], 'Source', 'make_opts') 1473 common_run_interface.CommonRunCmd.update_make_opts_full(path, m_opts) 1474 logger.info('Done %.4g' % (time.time()-start)) 1475 1476 1477 # Download LHAPDF SET 1478 common_run_interface.CommonRunCmd.install_lhapdf_pdfset_static(\ 1479 mgcmd.options['lhapdf'], None, self.banner.run_card.get_lhapdf_id()) 1480 1481 # now store the id information 1482 matrix_elements = mgcmd._curr_matrix_elements.get_matrix_elements() 1483 for me in matrix_elements: 1484 for proc in me.get('processes'): 1485 initial = [] #filled in the next line 1486 final = [l.get('id') for l in proc.get('legs')\ 1487 if l.get('state') or initial.append(l.get('id'))] 1488 order = (initial, final) 1489 tag = proc.get_initial_final_ids() 1490 decay_finals = proc.get_final_ids_after_decay() 1491 1492 if tag[1] != decay_finals: 1493 order = (initial, list(decay_finals)) 1494 decay_finals.sort() 1495 tag = (tag[0], tuple(decay_finals)) 1496 Pdir = pjoin(path_me, data['paths'][1], 'SubProcesses', 1497 'P%s' % me.get('processes')[0].shell_string()) 1498 assert os.path.exists(Pdir), "Pdir %s do not exists" % Pdir 1499 if (tag,'V') in data['id2path']: 1500 if not Pdir == data['id2path'][(tag,'V')][1]: 1501 misc.sprint(tag, Pdir, self.id_to_path[(tag,'V')][1]) 1502 raise self.InvalidCmd, '2 different process have the same final states. This module can not handle such situation' 1503 else: 1504 continue 1505 # build the helicity dictionary 1506 hel_nb = 0 1507 hel_dict = {9:0} # unknown helicity -> use full ME 1508 for helicities in me.get_helicity_matrix(): 1509 hel_nb +=1 #fortran starts at 1 1510 hel_dict[tuple(helicities)] = hel_nb 1511 1512 data['id2path'][(tag,'V')] = [order, Pdir, hel_dict] 1513 1514 #compile the module to combine the weight 1515 misc.compile(cwd=pjoin(path_me, data['paths'][1], 'Source')) 1516 #link it 1517 with misc.chdir(pjoin(path_me)): 1518 if path_me not in sys.path: 1519 sys.path.insert(0, path_me) 1520 mymod = __import__('%s.Source.rwgt2py' % data['paths'][1], globals(), locals(), [],-1) 1521 mymod = mymod.Source.rwgt2py 1522 with misc.stdchannel_redirected(sys.stdout, os.devnull): 1523 mymod.initialise([self.banner.run_card['lpp1'], 1524 self.banner.run_card['lpp2']], 1525 self.banner.run_card.get_lhapdf_id()) 1526 self.combine_wgt = mymod.get_wgt 1527 1528 elif has_nlo and not second and self.rwgt_mode == ['NLO_tree']: 1529 # We do not have any virtual reweighting to do but we still have to 1530 #combine the weights. 1531 #Idea:create a fake directory. 1532 start = time.time() 1533 commandline='import model loop_sm;generate g g > e+ ve [virt=QCD]' 1534 # deactivate golem since it creates troubles 1535 old_options = dict(mgcmd.options) 1536 mgcmd.options['golem'] = None 1537 mgcmd.options['pjfry'] = None 1538 commandline = commandline.replace('add process', 'generate',1) 1539 logger.info(commandline) 1540 mgcmd.exec_cmd(commandline, precmd=True) 1541 commandline = 'output standalone_rw %s -f' % pjoin(path_me, data['paths'][1]) 1542 mgcmd.exec_cmd(commandline, precmd=True) 1543 #put back golem to original value 1544 mgcmd.options['golem'] = old_options['golem'] 1545 mgcmd.options['pjfry'] = old_options['pjfry'] 1546 # update make_opts 1547 m_opts = {} 1548 if mgcmd.options['lhapdf']: 1549 #lhapdfversion = subprocess.Popen([mgcmd.options['lhapdf'], '--version'], 1550 # stdout = subprocess.PIPE).stdout.read().strip()[0] 1551 m_opts['lhapdf'] = True 1552 m_opts['f2pymode'] = True 1553 m_opts['lhapdfversion'] = 5 # 6 always fail on my computer since 5 is compatible but slower always use 5 1554 m_opts['llhapdf'] = self.mother.get_lhapdf_libdir() 1555 else: 1556 raise Exception, "NLO_tree reweighting requires LHAPDF to work correctly" 1557 1558 path = pjoin(path_me,data['paths'][1], 'Source', 'make_opts') 1559 common_run_interface.CommonRunCmd.update_make_opts_full(path, m_opts) 1560 logger.info('Done %.4g' % (time.time()-start)) 1561 1562 # Download LHAPDF SET 1563 common_run_interface.CommonRunCmd.install_lhapdf_pdfset_static(\ 1564 mgcmd.options['lhapdf'], None, self.banner.run_card.get_lhapdf_id()) 1565 1566 #compile the module to combine the weight 1567 misc.compile(cwd=pjoin(path_me, data['paths'][1], 'Source')) 1568 #link it 1569 with misc.chdir(pjoin(path_me)): 1570 if path_me not in sys.path: 1571 sys.path.insert(0, path_me) 1572 mymod = __import__('%s.Source.rwgt2py' % data['paths'][1], globals(), locals(), [],-1) 1573 mymod = mymod.Source.rwgt2py 1574 with misc.stdchannel_redirected(sys.stdout, os.devnull): 1575 mymod.initialise([self.banner.run_card['lpp1'], 1576 self.banner.run_card['lpp2']], 1577 self.banner.run_card.get_lhapdf_id()) 1578 self.combine_wgt = mymod.get_wgt 1579 1580 1581 # 6. If we need a new model/process------------------------------------- 1582 if (self.second_model or self.second_process) and not second: 1583 self.create_standalone_directory(second=True) 1584 1585 if not second: 1586 self.has_nlo = has_nlo
1587 1588 1589 1590
1591 - def load_model(self, name, use_mg_default, complex_mass=False):
1592 """load the model""" 1593 1594 loop = False 1595 1596 logger.info('detected model: %s. Loading...' % name) 1597 model_path = name 1598 1599 # Import model 1600 base_model = import_ufo.import_model(name, decay=False, 1601 complex_mass_scheme=complex_mass) 1602 1603 if use_mg_default: 1604 base_model.pass_particles_name_in_mg_default() 1605 1606 self.model = base_model 1607 self.mg5cmd._curr_model = self.model 1608 self.mg5cmd.process_model()
1609 1610
1611 - def save_to_pickle(self):
1612 import madgraph.iolibs.save_load_object as save_load_object 1613 1614 to_save = {} 1615 to_save['id_to_path'] = self.id_to_path 1616 if hasattr(self, 'id_to_path_second'): 1617 to_save['id_to_path_second'] = self.id_to_path_second 1618 else: 1619 to_save['id_to_path_second'] = {} 1620 to_save['all_cross_section'] = self.all_cross_section 1621 to_save['processes'] = self.processes 1622 to_save['second_process'] = self.second_process 1623 if self.second_model: 1624 to_save['second_model'] =True 1625 else: 1626 to_save['second_model'] = None 1627 to_save['rwgt_dir'] = self.rwgt_dir 1628 to_save['has_nlo'] = self.has_nlo 1629 to_save['rwgt_mode'] = self.rwgt_mode 1630 1631 name = pjoin(self.rwgt_dir, 'rw_me', 'rwgt.pkl') 1632 save_load_object.save_to_file(name, to_save)
1633
1634 - def load_from_pickle(self):
1635 import madgraph.iolibs.save_load_object as save_load_object 1636 1637 obj = save_load_object.load_from_file( pjoin(self.rwgt_dir, 'rw_me', 'rwgt.pkl')) 1638 1639 self.has_standalone_dir = True 1640 self.options = {'curr_dir': os.path.realpath(os.getcwd()), 1641 'rewgt_name': None} 1642 1643 old_rwgt = obj['rwgt_dir'] 1644 1645 # path to fortran executable 1646 self.id_to_path = {} 1647 for key , (order, Pdir, hel_dict) in obj['id_to_path'].items(): 1648 new_P = Pdir.replace(old_rwgt, self.rwgt_dir) 1649 self.id_to_path[key] = [order, new_P, hel_dict] 1650 1651 # path to fortran executable (for second directory) 1652 self.id_to_path_second = {} 1653 for key , (order, Pdir, hel_dict) in obj['id_to_path_second'].items(): 1654 new_P = Pdir.replace(old_rwgt, self.rwgt_dir) 1655 self.id_to_path_second[key] = [order, new_P, hel_dict] 1656 1657 self.all_cross_section = obj['all_cross_section'] 1658 self.processes = obj['processes'] 1659 self.second_process = obj['second_process'] 1660 self.second_model = obj['second_model'] 1661 self.has_nlo = obj['has_nlo'] 1662 if not self.rwgt_mode: 1663 self.rwgt_mode = obj['rwgt_mode'] 1664 logger.info("mode set to %s" % self.rwgt_mode) 1665 if self.has_nlo: 1666 path = pjoin(obj['rwgt_dir'], 'rw_mevirt','Source') 1667 sys.path.insert(0, path) 1668 mymod = __import__('rwgt2py', globals(), locals()) 1669 with misc.stdchannel_redirected(sys.stdout, os.devnull): 1670 mymod.initialise([self.banner.run_card['lpp1'], 1671 self.banner.run_card['lpp2']], 1672 self.banner.run_card.get_lhapdf_id()) 1673 self.combine_wgt = mymod.get_wgt
1674