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 797 # perform the scanning 798 if param_card_iterator: 799 for i,card in enumerate(param_card_iterator): 800 if self.options['rwgt_name']: 801 self.options['rwgt_name'] = '%s_%s' % (self.options['rwgt_name'].rsplit('_',1)[0], i+1) 802 card.write(pjoin(rw_dir, 'Cards', 'param_card.dat')) 803 self.exec_cmd("launch --keep_card", printcmd=False, precmd=True) 804 805 self.options['rwgt_name'] = None
806
807 - def do_set(self, line):
808 "Not in help" 809 810 logger.warning("Invalid Syntax. The command 'set' should be placed after the 'launch' one. Continuing by adding automatically 'launch'") 811 self.stored_line = "set %s" % line 812 return self.exec_cmd("launch")
813
814 - def default(self, line, log=True):
815 """Default action if line is not recognized""" 816 817 if os.path.isfile(line): 818 if log: 819 logger.warning("Invalid Syntax. The path to a param_card' should be placed after the 'launch' command. Continuing by adding automatically 'launch'") 820 self.stored_line = line 821 return self.exec_cmd("launch") 822 else: 823 return super(ReweightInterface,self).default(line, log=log)
824
825 - def write_reweighted_event(self, event, tag_name, **opt):
826 """a function for running in multicore""" 827 828 if not hasattr(opt['thread_space'], "calculator"): 829 opt['thread_space'].calculator = {} 830 opt['thread_space'].calculator_nbcall = {} 831 opt['thread_space'].cross = 0 832 opt['thread_space'].output = open( self.lhe_input.name +'rw.%s' % opt['thread_id'], 'w') 833 if self.mother: 834 out_path = pjoin(self.mother.me_dir, 'Events', 'reweight.lhe.%s' % opt['thread_id']) 835 opt['thread_space'].output2 = open(out_path, 'w') 836 837 weight = self.calculate_weight(event, space=opt['thread_space']) 838 opt['thread_space'].cross += weight 839 if self.output_type == "default": 840 event.reweight_data[tag_name] = weight 841 #write this event with weight 842 opt['thread_space'].output.write(str(event)) 843 if self.mother: 844 event.wgt = weight 845 event.reweight_data = {} 846 opt['thread_space'].output2.write(str(event)) 847 else: 848 event.wgt = weight 849 event.reweight_data = {} 850 if self.mother: 851 opt['thread_space'].output2.write(str(event)) 852 else: 853 opt['thread_space'].output.write(str(event)) 854 855 return 0
856
857 - def calculate_weight(self, event, space=None):
858 """space defines where to find the calculator (in multicore)""" 859 860 if self.has_nlo and self.rwgt_mode != "LO": 861 return self.calculate_nlo_weight(event, space) 862 863 if not space: 864 space = self 865 event.parse_reweight() 866 867 # LO reweighting 868 w_orig = self.calculate_matrix_element(event, 0, space) 869 w_new = self.calculate_matrix_element(event, 1, space) 870 871 if w_orig == 0: 872 tag, order = event.get_tag_and_order() 873 orig_order, Pdir, hel_dict = self.id_to_path[tag] 874 misc.sprint(w_orig, w_new) 875 misc.sprint(event) 876 raise Exception, "Invalid matrix element for original computation (weight=0)" 877 878 return {'orig': event.wgt, '': w_new/w_orig*event.wgt}
879
880 - def calculate_nlo_weight(self, event, space=None):
881 882 883 type_nlo = self.get_weight_names() 884 final_weight = {'orig': event.wgt} 885 886 if not space: 887 space = self #for multicore: not use so far 888 889 event.parse_reweight() 890 event.parse_nlo_weight() 891 892 #initialise the input to the function which recompute the weight 893 scales2 = [] 894 pdg = [] 895 bjx = [] 896 wgt_tree = [] # reweight for loop-improved type 897 wgt_virt = [] #reweight b+v together 898 base_wgt = [] 899 gs=[] 900 qcdpower = [] 901 ref_wgts = [] #for debugging 902 903 orig_wgt = 0 904 for cevent in event.nloweight.cevents: 905 #check if we need to compute the virtual for that cevent 906 need_V = False # the real is nothing else than the born for a N+1 config 907 all_ctype = [w.type for w in cevent.wgts] 908 if '_nlo' in type_nlo and any(c in all_ctype for c in [2,14,15]): 909 need_V =True 910 911 w_orig = self.calculate_matrix_element(cevent, 0, space) 912 w_new = self.calculate_matrix_element(cevent, 1, space) 913 ratio_T = w_new/w_orig 914 if need_V: 915 scale2 = cevent.wgts[0].scales2[0] 916 #for scale2 in set(c.scales2[1] for c in cevent.wgts): 917 w_origV = self.calculate_matrix_element(cevent, 'V0', space, scale2=scale2) 918 w_newV = self.calculate_matrix_element(cevent, 'V1', space, scale2=scale2) 919 ratio_BV = (w_newV + w_new) / (w_origV + w_orig) 920 ratio_V = w_newV/w_origV 921 else: 922 ratio_V = "should not be used" 923 ratio_BV = "should not be used" 924 925 for c_wgt in cevent.wgts: 926 orig_wgt += c_wgt.ref_wgt 927 #add the information to the input 928 scales2.append(c_wgt.scales2) 929 pdg.append(c_wgt.pdgs[:2]) 930 931 bjx.append(c_wgt.bjks) 932 qcdpower.append(c_wgt.qcdpower) 933 gs.append(c_wgt.gs) 934 ref_wgts.append(c_wgt.ref_wgt) 935 936 if '_nlo' in type_nlo: 937 if c_wgt.type in [2,14,15]: 938 R = ratio_BV 939 else: 940 R = ratio_T 941 942 new_wgt = [c_wgt.pwgt[0] * R, 943 c_wgt.pwgt[1] * ratio_T, 944 c_wgt.pwgt[2] * ratio_T] 945 wgt_virt.append(new_wgt) 946 947 if '_tree' in type_nlo: 948 new_wgt = [c_wgt.pwgt[0] * ratio_T, 949 c_wgt.pwgt[1] * ratio_T, 950 c_wgt.pwgt[2] * ratio_T] 951 wgt_tree.append(new_wgt) 952 base_wgt.append(c_wgt.pwgt[:3]) 953 954 #change the ordering to the fortran one: 955 scales2 = self.invert_momenta(scales2) 956 pdg = self.invert_momenta(pdg) 957 bjx = self.invert_momenta(bjx) 958 # re-compute original weight to reduce numerical inacurracy 959 base_wgt = self.invert_momenta(base_wgt) 960 961 orig_wgt_check, partial_check = self.combine_wgt(scales2, pdg, bjx, base_wgt, gs, qcdpower, 1., 1.) 962 963 if '_nlo' in type_nlo: 964 wgt = self.invert_momenta(wgt_virt) 965 with misc.stdchannel_redirected(sys.stdout, os.devnull): 966 new_out, partial = self.combine_wgt(scales2, pdg, bjx, wgt, gs, qcdpower, 1., 1.) 967 # try to correct for precision issue 968 avg = [partial_check[i]/ref_wgts[i] for i in range(len(ref_wgts))] 969 out = sum(partial[i]/avg[i] if 0.85<avg[i]<1.15 else 0 \ 970 for i in range(len(avg))) 971 final_weight['_nlo'] = out/orig_wgt*event.wgt 972 973 974 if '_tree' in type_nlo: 975 wgt = self.invert_momenta(wgt_tree) 976 with misc.stdchannel_redirected(sys.stdout, os.devnull): 977 out, partial = self.combine_wgt(scales2, pdg, bjx, wgt, gs, qcdpower, 1., 1.) 978 # try to correct for precision issue 979 avg = [partial_check[i]/ref_wgts[i] for i in range(len(ref_wgts))] 980 new_out = sum(partial[i]/avg[i] if 0.85<avg[i]<1.15 else partial[i] \ 981 for i in range(len(avg))) 982 final_weight['_tree'] = new_out/orig_wgt*event.wgt 983 984 if '_lo' in type_nlo: 985 w_orig = self.calculate_matrix_element(event, 0, space) 986 w_new = self.calculate_matrix_element(event, 1, space) 987 final_weight['_lo'] = w_new/w_orig*event.wgt 988 989 return final_weight
990 991 992 @staticmethod
993 - def invert_momenta(p):
994 """ fortran/C-python do not order table in the same order""" 995 new_p = [] 996 for i in range(len(p[0])): new_p.append([0]*len(p)) 997 for i, onep in enumerate(p): 998 for j, x in enumerate(onep): 999 new_p[j][i] = x 1000 return new_p
1001 1002 @staticmethod
1003 - def rename_f2py_lib(Pdir, tag):
1004 if tag == 2: 1005 return 1006 if os.path.exists(pjoin(Pdir, 'matrix%spy.so' % tag)): 1007 return 1008 else: 1009 open(pjoin(Pdir, 'matrix%spy.so' % tag),'w').write(open(pjoin(Pdir, 'matrix2py.so') 1010 ).read().replace('matrix2py', 'matrix%spy' % tag))
1011
1012 - def calculate_matrix_element(self, event, hypp_id, space, scale2=0):
1013 """routine to return the matrix element""" 1014 1015 tag, order = event.get_tag_and_order() 1016 if isinstance(hypp_id, str) and hypp_id.startswith('V'): 1017 tag = (tag,'V') 1018 hypp_id = int(hypp_id[1:]) 1019 base = "rw_mevirt" 1020 else: 1021 base = "rw_me" 1022 1023 if (not self.second_model and not self.second_process) or hypp_id==0: 1024 orig_order, Pdir, hel_dict = self.id_to_path[tag] 1025 else: 1026 orig_order, Pdir, hel_dict = self.id_to_path_second[tag] 1027 1028 1029 run_id = (tag, hypp_id) 1030 1031 assert space == self 1032 start = False 1033 if run_id in space.calculator: 1034 external = space.calculator[run_id] 1035 # mod = space.calculator[(run_id,'module')] 1036 # #with misc.chdir(Pdir): 1037 # # if hypp_id==0: 1038 # # mod.initialise('param_card_orig.dat') 1039 # # else: 1040 # # mod.initialise('param_card.dat') 1041 elif (not self.second_model and not self.second_process) or hypp_id==0: 1042 # create the executable for this param_card 1043 subdir = pjoin(self.me_dir, base, 'SubProcesses') 1044 if self.me_dir not in sys.path: 1045 sys.path.insert(0,self.me_dir) 1046 if self.rwgt_dir and self.rwgt_dir not in sys.path: 1047 sys.path.insert(0,self.rwgt_dir) 1048 Pname = os.path.basename(Pdir) 1049 if hypp_id == 0: 1050 if (Pdir, 0) not in dir_to_f2py_free_mod: 1051 metag = 1 1052 dir_to_f2py_free_mod[(Pdir,0)] = (metag, nb_f2py_module) 1053 else: 1054 metag, old_module = dir_to_f2py_free_mod[(Pdir,0)] 1055 if old_module != nb_f2py_module: 1056 metag += 1 1057 dir_to_f2py_free_mod[(Pdir,0)] = (metag, nb_f2py_module) 1058 os.environ['MENUM'] = '2' 1059 if not self.rwgt_dir or not os.path.exists(pjoin(Pdir, 'matrix2py.so')): 1060 misc.compile(['matrix2py.so'], cwd=Pdir) 1061 self.rename_f2py_lib(Pdir, 2*metag) 1062 try: 1063 mymod = __import__('%s.SubProcesses.%s.matrix%spy' % (base, Pname, 2*metag), globals(), locals(), [],-1) 1064 except: 1065 import platform 1066 if platform.system() == 'Darwin': 1067 os.system('install_name_tool -change libMadLoop.dylib %s/libMadLoop.dylib matrix%spy.so' % (Pdir,2*metag)) 1068 mymod = __import__('%s.SubProcesses.%s.matrix%spy' % (base, Pname, 2*metag), globals(), locals(), [],-1) 1069 else: 1070 misc.sprint("fail compilation") 1071 raise 1072 S = mymod.SubProcesses 1073 P = getattr(S, Pname) 1074 mymod = getattr(P, 'matrix%spy' % (2*metag)) 1075 with misc.chdir(Pdir): 1076 with misc.stdchannel_redirected(sys.stdout, os.devnull): 1077 mymod.initialise('param_card_orig.dat') 1078 1079 1080 if hypp_id == 1: 1081 #incorrect line 1082 metag = dir_to_f2py_free_mod[(Pdir,0)][0] 1083 newtag = 2*metag+1 1084 self.rename_f2py_lib(Pdir, newtag) 1085 try: 1086 mymod = __import__('%s.SubProcesses.%s.matrix%spy' % (base, Pname, newtag), globals(), locals(), [],-1) 1087 except Exception, error: 1088 os.remove(pjoin(Pdir, 'matrix%spy.so' % newtag)) 1089 newtag = "L%s" % newtag 1090 os.environ['MENUM'] = newtag 1091 misc.compile(['matrix%spy.so' % newtag], cwd=Pdir) 1092 mymod = __import__('%s.SubProcesses.%s.matrix%spy' % (base, Pname, newtag), globals(), locals(), [],-1) 1093 1094 S = mymod.SubProcesses 1095 P = getattr(S, Pname) 1096 mymod = getattr(P, 'matrix%spy' % newtag) 1097 with misc.chdir(Pdir): 1098 with misc.stdchannel_redirected(sys.stdout, os.devnull): 1099 mymod.initialise('param_card.dat') 1100 1101 space.calculator[run_id] = mymod.get_me 1102 space.calculator[(run_id,'module')] = mymod 1103 external = space.calculator[run_id] 1104 else: 1105 subdir = pjoin(self.me_dir,'%s_second' % base, 'SubProcesses') 1106 if self.me_dir not in sys.path: 1107 sys.path.append(self.me_dir) 1108 1109 assert hypp_id == 1 1110 Pname = os.path.basename(Pdir) 1111 os.environ['MENUM'] = '2' 1112 if not self.rwgt_dir or not os.path.exists(pjoin(Pdir, 'matrix2py.so')): 1113 misc.compile(['matrix2py.so'], cwd=pjoin(subdir, Pdir)) 1114 if (Pdir, 1) not in dir_to_f2py_free_mod: 1115 metag = 1 1116 dir_to_f2py_free_mod[(Pdir,1)] = (metag, nb_f2py_module) 1117 else: 1118 metag, old_module = dir_to_f2py_free_mod[(Pdir,1)] 1119 if old_module != nb_f2py_module: 1120 metag += 1 1121 dir_to_f2py_free_mod[(Pdir,1)] = (metag, nb_f2py_module) 1122 self.rename_f2py_lib(Pdir, metag) 1123 try: 1124 mymod = __import__("%s_second.SubProcesses.%s.matrix%spy" % (base, Pname, metag)) 1125 except ImportError: 1126 os.remove(pjoin(Pdir, 'matrix%spy.so' % metag )) 1127 metag = "L%s" % metag 1128 os.environ['MENUM'] = str(metag) 1129 misc.compile(['matrix%spy.so' % metag], cwd=pjoin(subdir, Pdir)) 1130 mymod = __import__("%s_second.SubProcesses.%s.matrix%spy" % (base, Pname, metag)) 1131 1132 reload(mymod) 1133 S = mymod.SubProcesses 1134 P = getattr(S, Pname) 1135 mymod = getattr(P, 'matrix%spy' % metag) 1136 with misc.chdir(Pdir): 1137 with misc.stdchannel_redirected(sys.stdout, os.devnull): 1138 mymod.initialise('param_card.dat') 1139 space.calculator[run_id] = mymod.get_me 1140 space.calculator[(run_id,'module')] = mymod 1141 external = space.calculator[run_id] 1142 1143 p = self.invert_momenta(event.get_momenta(orig_order)) 1144 1145 1146 # add helicity information 1147 1148 hel_order = event.get_helicity(orig_order) 1149 if self.helicity_reweighting and 9 not in hel_order: 1150 nhel = hel_dict[tuple(hel_order)] 1151 else: 1152 nhel = 0 1153 1154 with misc.chdir(Pdir): 1155 with misc.stdchannel_redirected(sys.stdout, os.devnull): 1156 if 'V' in tag or \ 1157 (hypp_id ==1 and self.second_process and any('sqrvirt' in l for l in self.second_process)): 1158 me_value = external(p,event.aqcd, math.sqrt(scale2), nhel) 1159 else: 1160 try: 1161 me_value = external(p,event.aqcd, nhel) 1162 except TypeError: 1163 me_value = external(p,event.aqcd, math.sqrt(scale2), nhel) 1164 1165 # for NLO we have also the stability status code 1166 if isinstance(me_value, tuple): 1167 me_value, code = me_value 1168 #if code points unstability -> returns 0 1169 hundred_value = (code % 1000) //100 1170 if hundred_value in [4]: 1171 me_value = 0. 1172 1173 return me_value
1174
1175 - def terminate_fortran_executables(self, new_card_only=False):
1176 """routine to terminate all fortran executables""" 1177 1178 for (mode, production) in dict(self.calculator): 1179 1180 if new_card_only and production == 0: 1181 continue 1182 del self.calculator[(mode, production)]
1183
1184 - def do_quit(self, line):
1185 if self.exitted: 1186 return 1187 self.exitted = True 1188 1189 if 'init' in self.banner: 1190 cross = 0 1191 error = 0 1192 for line in self.banner['init'].split('\n'): 1193 split = line.split() 1194 if len(split) == 4: 1195 cross, error = float(split[0]), float(split[1]) 1196 if 'orig' not in self.all_cross_section: 1197 logger.info('Original cross-section: %s +- %s pb' % (cross, error)) 1198 else: 1199 logger.info('Original cross-section: %s +- %s pb (cross-section from sum of weights: %s)' % (cross, error, self.all_cross_section['orig'][0])) 1200 logger.info('Computed cross-section:') 1201 keys = self.all_cross_section.keys() 1202 keys.sort() 1203 for key in keys: 1204 if key == 'orig': 1205 continue 1206 logger.info('%s : %s +- %s pb' % (key[0] if not key[1] else '%s%s' % key, 1207 self.all_cross_section[key][0],self.all_cross_section[key][1] )) 1208 self.terminate_fortran_executables() 1209 1210 if self.rwgt_dir: 1211 self.save_to_pickle() 1212 1213 with misc.stdchannel_redirected(sys.stdout, os.devnull): 1214 for run_id in self.calculator: 1215 del self.calculator[run_id] 1216 del self.calculator
1217 1218
1219 - def __del__(self):
1220 self.do_quit('')
1221 1222
1223 - def adding_me(self, matrix_elements, path):
1224 """Adding one element to the list based on the matrix element"""
1225 1226 1227 @misc.mute_logger()
1228 - def create_standalone_directory(self, second=False):
1229 """generate the various directory for the weight evaluation""" 1230 1231 data={} 1232 if not second: 1233 data['paths'] = ['rw_me', 'rw_mevirt'] 1234 # model 1235 info = self.banner.get('proc_card', 'full_model_line') 1236 if '-modelname' in info: 1237 data['mg_names'] = False 1238 else: 1239 data['mg_names'] = True 1240 data['model_name'] = self.banner.get('proc_card', 'model') 1241 #processes 1242 data['processes'] = [line[9:].strip() for line in self.banner.proc_card 1243 if line.startswith('generate')] 1244 data['processes'] += [' '.join(line.split()[2:]) for line in self.banner.proc_card 1245 if re.search('^\s*add\s+process', line)] 1246 #object_collector 1247 self.id_to_path = {} 1248 data['id2path'] = self.id_to_path 1249 else: 1250 data['paths'] = ['rw_me_second', 'rw_mevirt_second'] 1251 # model 1252 if self.second_model: 1253 data['mg_names'] = True 1254 if ' ' in self.second_model: 1255 args = self.second_model.split() 1256 if '--modelname' in args: 1257 data['mg_names'] = False 1258 data['model_name'] = args[0] 1259 else: 1260 data['model_name'] = self.second_model 1261 else: 1262 data['model_name'] = None 1263 #processes 1264 if self.second_process: 1265 data['processes'] = self.second_process 1266 else: 1267 data['processes'] = [line[9:].strip() for line in self.banner.proc_card 1268 if line.startswith('generate')] 1269 data['processes'] += [' '.join(line.split()[2:]) 1270 for line in self.banner.proc_card 1271 if re.search('^\s*add\s+process', line)] 1272 #object_collector 1273 self.id_to_path_second = {} 1274 data['id2path'] = self.id_to_path_second 1275 1276 # 0. clean previous run ------------------------------------------------ 1277 if not self.rwgt_dir: 1278 path_me = self.me_dir 1279 else: 1280 path_me = self.rwgt_dir 1281 try: 1282 shutil.rmtree(pjoin(path_me,data['paths'][0])) 1283 except Exception: 1284 pass 1285 try: 1286 shutil.rmtree(pjoin(path_me, data['paths'][1])) 1287 except Exception: 1288 pass 1289 1290 # 1. prepare the interface---------------------------------------------- 1291 mgcmd = self.mg5cmd 1292 complex_mass = False 1293 has_cms = re.compile(r'''set\s+complex_mass_scheme\s*(True|T|1|true|$|;)''') 1294 for line in self.banner.proc_card: 1295 if line.startswith('set'): 1296 mgcmd.exec_cmd(line, printcmd=False, precmd=False, postcmd=False) 1297 if has_cms.search(line): 1298 complex_mass = True 1299 elif line.startswith('define'): 1300 try: 1301 mgcmd.exec_cmd(line, printcmd=False, precmd=False, postcmd=False) 1302 except Exception: 1303 pass 1304 1305 # 1. Load model--------------------------------------------------------- 1306 if not data['model_name'] and not second: 1307 raise self.InvalidCmd('Only UFO model can be loaded in this module.') 1308 elif data['model_name']: 1309 self.load_model(data['model_name'], data['mg_names'], complex_mass) 1310 modelpath = self.model.get('modelpath') 1311 if os.path.basename(modelpath) != mgcmd._curr_model['name']: 1312 name, restrict = mgcmd._curr_model['name'].rsplit('-',1) 1313 if os.path.exists(pjoin(os.path.dirname(modelpath),name, 'restrict_%s.dat' % restrict)): 1314 modelpath = pjoin(os.path.dirname(modelpath), mgcmd._curr_model['name']) 1315 1316 commandline="import model %s " % modelpath 1317 if not data['mg_names']: 1318 commandline += ' -modelname ' 1319 mgcmd.exec_cmd(commandline) 1320 1321 #multiparticles 1322 for name, content in self.banner.get('proc_card', 'multiparticles'): 1323 mgcmd.exec_cmd("define %s = %s" % (name, content)) 1324 1325 # 2. compute the production matrix element ----------------------------- 1326 has_nlo = False 1327 mgcmd.exec_cmd("set group_subprocesses False") 1328 1329 if not second: 1330 logger.info('generating the square matrix element for reweighting') 1331 else: 1332 logger.info('generating the square matrix element for reweighting (second model and/or processes)') 1333 start = time.time() 1334 commandline='' 1335 for proc in data['processes']: 1336 if '[' not in proc: 1337 commandline += "add process %s ;" % proc 1338 else: 1339 has_nlo = True 1340 commandline += self.get_LO_definition_from_NLO(proc) 1341 1342 commandline = commandline.replace('add process', 'generate',1) 1343 logger.info(commandline) 1344 try: 1345 mgcmd.exec_cmd(commandline, precmd=True, errorhandling=False) 1346 except diagram_generation.NoDiagramException: 1347 commandline='' 1348 for proc in data['processes']: 1349 if '[' not in proc: 1350 raise 1351 commandline += "add process %s ;" % proc 1352 commandline = commandline.replace('add process', 'generate',1) 1353 logger.info("RETRY with %s", commandline) 1354 mgcmd.exec_cmd(commandline, precmd=True) 1355 has_nlo = False 1356 except Exception, error: 1357 raise 1358 1359 commandline = 'output standalone_rw %s' % pjoin(path_me,data['paths'][0]) 1360 mgcmd.exec_cmd(commandline, precmd=True) 1361 logger.info('Done %.4g' % (time.time()-start)) 1362 self.has_standalone_dir = True 1363 1364 1365 # 3. Store id to directory information --------------------------------- 1366 matrix_elements = mgcmd._curr_matrix_elements.get_matrix_elements() 1367 1368 to_check = [] # list of tag that do not have a Pdir at creation time. 1369 for me in matrix_elements: 1370 for proc in me.get('processes'): 1371 initial = [] #filled in the next line 1372 final = [l.get('id') for l in proc.get('legs')\ 1373 if l.get('state') or initial.append(l.get('id'))] 1374 order = (initial, final) 1375 tag = proc.get_initial_final_ids() 1376 decay_finals = proc.get_final_ids_after_decay() 1377 1378 if tag[1] != decay_finals: 1379 order = (initial, list(decay_finals)) 1380 decay_finals.sort() 1381 tag = (tag[0], tuple(decay_finals)) 1382 Pdir = pjoin(path_me, data['paths'][0], 'SubProcesses', 1383 'P%s' % me.get('processes')[0].shell_string()) 1384 1385 if not os.path.exists(Pdir): 1386 to_check.append(tag) 1387 continue 1388 if tag in data['id2path']: 1389 if not Pdir == data['id2path'][tag][1]: 1390 misc.sprint(tag, Pdir, data['id2path'][tag][1]) 1391 raise self.InvalidCmd, '2 different process have the same final states. This module can not handle such situation' 1392 else: 1393 continue 1394 # build the helicity dictionary 1395 hel_nb = 0 1396 hel_dict = {9:0} # unknown helicity -> use full ME 1397 for helicities in me.get_helicity_matrix(): 1398 hel_nb +=1 #fortran starts at 1 1399 hel_dict[tuple(helicities)] = hel_nb 1400 1401 data['id2path'][tag] = [order, Pdir, hel_dict] 1402 1403 for tag in to_check: 1404 if tag not in self.id_to_path: 1405 logger.warning("no valid path for %s" % (tag,)) 1406 #raise self.InvalidCmd, "no valid path for %s" % (tag,) 1407 1408 # 4. Check MadLoopParam for Loop induced 1409 if os.path.exists(pjoin(path_me, data['paths'][0], 'Cards', 'MadLoopParams.dat')): 1410 MLCard = banner.MadLoopParam(pjoin(path_me, data['paths'][0], 'Cards', 'MadLoopParams.dat')) 1411 MLCard.set('WriteOutFilters', False) 1412 MLCard.set('UseLoopFilter', False) 1413 MLCard.set("DoubleCheckHelicityFilter", False) 1414 MLCard.set("HelicityFilterLevel", 0) 1415 MLCard.write(pjoin(path_me, data['paths'][0], 'SubProcesses', 'MadLoopParams.dat'), 1416 pjoin(path_me, data['paths'][0], 'Cards', 'MadLoopParams.dat'), 1417 commentdefault=False) 1418 1419 # 5. create the virtual for NLO reweighting --------------------------- 1420 if has_nlo and 'NLO' in self.rwgt_mode: 1421 # Do not pass here for LO/NLO_tree 1422 start = time.time() 1423 commandline='' 1424 for proc in data['processes']: 1425 if '[' not in proc: 1426 pass 1427 else: 1428 proc = proc.replace('[', '[ virt=') 1429 commandline += "add process %s ;" % proc 1430 # deactivate golem since it creates troubles 1431 old_options = dict(mgcmd.options) 1432 if mgcmd.options['golem'] or mgcmd.options['pjfry']: 1433 logger.info(" When doing NLO reweighting, MG5aMC cannot use the loop reduction algorithms Golem and/or PJFry++") 1434 mgcmd.options['golem'] = None 1435 mgcmd.options['pjfry'] = None 1436 commandline = commandline.replace('add process', 'generate',1) 1437 logger.info(commandline) 1438 mgcmd.exec_cmd(commandline, precmd=True) 1439 commandline = 'output standalone_rw %s -f' % pjoin(path_me, data['paths'][1]) 1440 mgcmd.exec_cmd(commandline, precmd=True) 1441 1442 #put back golem to original value 1443 mgcmd.options['golem'] = old_options['golem'] 1444 mgcmd.options['pjfry'] = old_options['pjfry'] 1445 # update make_opts 1446 m_opts = {} 1447 if mgcmd.options['lhapdf']: 1448 #lhapdfversion = subprocess.Popen([mgcmd.options['lhapdf'], '--version'], 1449 # stdout = subprocess.PIPE).stdout.read().strip()[0] 1450 m_opts['lhapdf'] = True 1451 m_opts['f2pymode'] = True 1452 m_opts['lhapdfversion'] = 5 # 6 always fail on my computer since 5 is compatible but slower always use 5 1453 m_opts['llhapdf'] = self.mother.get_lhapdf_libdir() 1454 else: 1455 raise Exception, "NLO reweighting requires LHAPDF to work correctly" 1456 1457 path = pjoin(path_me,data['paths'][1], 'Source', 'make_opts') 1458 common_run_interface.CommonRunCmd.update_make_opts_full(path, m_opts) 1459 logger.info('Done %.4g' % (time.time()-start)) 1460 1461 1462 # Download LHAPDF SET 1463 common_run_interface.CommonRunCmd.install_lhapdf_pdfset_static(\ 1464 mgcmd.options['lhapdf'], None, self.banner.run_card.get_lhapdf_id()) 1465 1466 # now store the id information 1467 matrix_elements = mgcmd._curr_matrix_elements.get_matrix_elements() 1468 for me in matrix_elements: 1469 for proc in me.get('processes'): 1470 initial = [] #filled in the next line 1471 final = [l.get('id') for l in proc.get('legs')\ 1472 if l.get('state') or initial.append(l.get('id'))] 1473 order = (initial, final) 1474 tag = proc.get_initial_final_ids() 1475 decay_finals = proc.get_final_ids_after_decay() 1476 1477 if tag[1] != decay_finals: 1478 order = (initial, list(decay_finals)) 1479 decay_finals.sort() 1480 tag = (tag[0], tuple(decay_finals)) 1481 Pdir = pjoin(path_me, data['paths'][1], 'SubProcesses', 1482 'P%s' % me.get('processes')[0].shell_string()) 1483 assert os.path.exists(Pdir), "Pdir %s do not exists" % Pdir 1484 if (tag,'V') in data['id2path']: 1485 if not Pdir == data['id2path'][(tag,'V')][1]: 1486 misc.sprint(tag, Pdir, self.id_to_path[(tag,'V')][1]) 1487 raise self.InvalidCmd, '2 different process have the same final states. This module can not handle such situation' 1488 else: 1489 continue 1490 # build the helicity dictionary 1491 hel_nb = 0 1492 hel_dict = {9:0} # unknown helicity -> use full ME 1493 for helicities in me.get_helicity_matrix(): 1494 hel_nb +=1 #fortran starts at 1 1495 hel_dict[tuple(helicities)] = hel_nb 1496 1497 data['id2path'][(tag,'V')] = [order, Pdir, hel_dict] 1498 1499 #compile the module to combine the weight 1500 misc.compile(cwd=pjoin(path_me, data['paths'][1], 'Source')) 1501 #link it 1502 with misc.chdir(pjoin(path_me)): 1503 if path_me not in sys.path: 1504 sys.path.insert(0, path_me) 1505 mymod = __import__('%s.Source.rwgt2py' % data['paths'][1], globals(), locals(), [],-1) 1506 mymod = mymod.Source.rwgt2py 1507 with misc.stdchannel_redirected(sys.stdout, os.devnull): 1508 mymod.initialise([self.banner.run_card['lpp1'], 1509 self.banner.run_card['lpp2']], 1510 self.banner.run_card.get_lhapdf_id()) 1511 self.combine_wgt = mymod.get_wgt 1512 1513 elif has_nlo and not second and self.rwgt_mode == ['NLO_tree']: 1514 # We do not have any virtual reweighting to do but we still have to 1515 #combine the weights. 1516 #Idea:create a fake directory. 1517 start = time.time() 1518 commandline='import model loop_sm;generate g g > e+ ve [virt=QCD]' 1519 # deactivate golem since it creates troubles 1520 old_options = dict(mgcmd.options) 1521 mgcmd.options['golem'] = None 1522 mgcmd.options['pjfry'] = None 1523 commandline = commandline.replace('add process', 'generate',1) 1524 logger.info(commandline) 1525 mgcmd.exec_cmd(commandline, precmd=True) 1526 commandline = 'output standalone_rw %s -f' % pjoin(path_me, data['paths'][1]) 1527 mgcmd.exec_cmd(commandline, precmd=True) 1528 #put back golem to original value 1529 mgcmd.options['golem'] = old_options['golem'] 1530 mgcmd.options['pjfry'] = old_options['pjfry'] 1531 # update make_opts 1532 m_opts = {} 1533 if mgcmd.options['lhapdf']: 1534 #lhapdfversion = subprocess.Popen([mgcmd.options['lhapdf'], '--version'], 1535 # stdout = subprocess.PIPE).stdout.read().strip()[0] 1536 m_opts['lhapdf'] = True 1537 m_opts['f2pymode'] = True 1538 m_opts['lhapdfversion'] = 5 # 6 always fail on my computer since 5 is compatible but slower always use 5 1539 m_opts['llhapdf'] = self.mother.get_lhapdf_libdir() 1540 else: 1541 raise Exception, "NLO_tree reweighting requires LHAPDF to work correctly" 1542 1543 path = pjoin(path_me,data['paths'][1], 'Source', 'make_opts') 1544 common_run_interface.CommonRunCmd.update_make_opts_full(path, m_opts) 1545 logger.info('Done %.4g' % (time.time()-start)) 1546 1547 # Download LHAPDF SET 1548 common_run_interface.CommonRunCmd.install_lhapdf_pdfset_static(\ 1549 mgcmd.options['lhapdf'], None, self.banner.run_card.get_lhapdf_id()) 1550 1551 #compile the module to combine the weight 1552 misc.compile(cwd=pjoin(path_me, data['paths'][1], 'Source')) 1553 #link it 1554 with misc.chdir(pjoin(path_me)): 1555 if path_me not in sys.path: 1556 sys.path.insert(0, path_me) 1557 mymod = __import__('%s.Source.rwgt2py' % data['paths'][1], globals(), locals(), [],-1) 1558 mymod = mymod.Source.rwgt2py 1559 with misc.stdchannel_redirected(sys.stdout, os.devnull): 1560 mymod.initialise([self.banner.run_card['lpp1'], 1561 self.banner.run_card['lpp2']], 1562 self.banner.run_card.get_lhapdf_id()) 1563 self.combine_wgt = mymod.get_wgt 1564 1565 1566 # 6. If we need a new model/process------------------------------------- 1567 if (self.second_model or self.second_process) and not second: 1568 self.create_standalone_directory(second=True) 1569 1570 if not second: 1571 self.has_nlo = has_nlo
1572 1573 1574 1575
1576 - def load_model(self, name, use_mg_default, complex_mass=False):
1577 """load the model""" 1578 1579 loop = False 1580 1581 logger.info('detected model: %s. Loading...' % name) 1582 model_path = name 1583 1584 # Import model 1585 base_model = import_ufo.import_model(name, decay=False, 1586 complex_mass_scheme=complex_mass) 1587 1588 if use_mg_default: 1589 base_model.pass_particles_name_in_mg_default() 1590 1591 self.model = base_model 1592 self.mg5cmd._curr_model = self.model 1593 self.mg5cmd.process_model()
1594 1595
1596 - def save_to_pickle(self):
1597 import madgraph.iolibs.save_load_object as save_load_object 1598 1599 to_save = {} 1600 to_save['id_to_path'] = self.id_to_path 1601 if hasattr(self, 'id_to_path_second'): 1602 to_save['id_to_path_second'] = self.id_to_path_second 1603 else: 1604 to_save['id_to_path_second'] = {} 1605 to_save['all_cross_section'] = self.all_cross_section 1606 to_save['processes'] = self.processes 1607 to_save['second_process'] = self.second_process 1608 if self.second_model: 1609 to_save['second_model'] =True 1610 else: 1611 to_save['second_model'] = None 1612 to_save['rwgt_dir'] = self.rwgt_dir 1613 to_save['has_nlo'] = self.has_nlo 1614 to_save['rwgt_mode'] = self.rwgt_mode 1615 1616 name = pjoin(self.rwgt_dir, 'rw_me', 'rwgt.pkl') 1617 save_load_object.save_to_file(name, to_save)
1618
1619 - def load_from_pickle(self):
1620 import madgraph.iolibs.save_load_object as save_load_object 1621 1622 obj = save_load_object.load_from_file( pjoin(self.rwgt_dir, 'rw_me', 'rwgt.pkl')) 1623 1624 self.has_standalone_dir = True 1625 self.options = {'curr_dir': os.path.realpath(os.getcwd()), 1626 'rewgt_name': None} 1627 1628 old_rwgt = obj['rwgt_dir'] 1629 1630 # path to fortran executable 1631 self.id_to_path = {} 1632 for key , (order, Pdir, hel_dict) in obj['id_to_path'].items(): 1633 new_P = Pdir.replace(old_rwgt, self.rwgt_dir) 1634 self.id_to_path[key] = [order, new_P, hel_dict] 1635 1636 # path to fortran executable (for second directory) 1637 self.id_to_path_second = {} 1638 for key , (order, Pdir, hel_dict) in obj['id_to_path_second'].items(): 1639 new_P = Pdir.replace(old_rwgt, self.rwgt_dir) 1640 self.id_to_path_second[key] = [order, new_P, hel_dict] 1641 1642 self.all_cross_section = obj['all_cross_section'] 1643 self.processes = obj['processes'] 1644 self.second_process = obj['second_process'] 1645 self.second_model = obj['second_model'] 1646 self.has_nlo = obj['has_nlo'] 1647 if not self.rwgt_mode: 1648 self.rwgt_mode = obj['rwgt_mode'] 1649 logger.info("mode set to %s" % self.rwgt_mode) 1650 if self.has_nlo: 1651 path = pjoin(obj['rwgt_dir'], 'rw_mevirt','Source') 1652 sys.path.insert(0, path) 1653 mymod = __import__('rwgt2py', globals(), locals()) 1654 with misc.stdchannel_redirected(sys.stdout, os.devnull): 1655 mymod.initialise([self.banner.run_card['lpp1'], 1656 self.banner.run_card['lpp2']], 1657 self.banner.run_card.get_lhapdf_id()) 1658 self.combine_wgt = mymod.get_wgt
1659