Package madgraph :: Package various :: Module banner
[hide private]
[frames] | no frames]

Source Code for Module madgraph.various.banner

   1  ################################################################################ 
   2  # 
   3  # Copyright (c) 2011 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   
  16  from __future__ import division 
  17  import collections 
  18  import copy 
  19  import logging 
  20  import numbers 
  21  import os 
  22  import sys 
  23  import re 
  24  import math 
  25  import StringIO 
  26   
  27  pjoin = os.path.join 
  28   
  29  try: 
  30      import madgraph 
  31  except ImportError: 
  32      MADEVENT = True 
  33      from internal import MadGraph5Error, InvalidCmd 
  34      import internal.file_writers as file_writers 
  35      import internal.files as files 
  36      import internal.check_param_card as param_card_reader 
  37      import internal.misc as misc 
  38      MEDIR = os.path.split(os.path.dirname(os.path.realpath( __file__ )))[0] 
  39      MEDIR = os.path.split(MEDIR)[0] 
  40  else: 
  41      MADEVENT = False 
  42      import madgraph.various.misc as misc 
  43      import madgraph.iolibs.file_writers as file_writers 
  44      import madgraph.iolibs.files as files  
  45      import models.check_param_card as param_card_reader 
  46      from madgraph import MG5DIR, MadGraph5Error, InvalidCmd 
  47   
  48   
  49  logger = logging.getLogger('madevent.cards') 
50 51 # A placeholder class to store unknown parameters with undecided format 52 -class UnknownType(str):
53 pass
54 163
164 - def __getattribute__(self, attr):
165 """allow auto-build for the run_card/param_card/... """ 166 try: 167 return super(Banner, self).__getattribute__(attr) 168 except: 169 if attr not in ['run_card', 'param_card', 'slha', 'mgruncard', 'mg5proccard', 'mgshowercard', 'foanalyse']: 170 raise 171 return self.charge_card(attr)
172 173 174
175 - def change_lhe_version(self, version):
176 """change the lhe version associate to the banner""" 177 178 version = float(version) 179 if version < 3: 180 version = 1 181 elif version > 3: 182 raise Exception, "Not Supported version" 183 self.lhe_version = version
184
185 - def get_cross(self, witherror=False):
186 """return the cross-section of the file""" 187 188 if "init" not in self: 189 misc.sprint(self.keys()) 190 raise Exception 191 192 text = self["init"].split('\n') 193 cross = 0 194 error = 0 195 for line in text: 196 s = line.split() 197 if len(s)==4: 198 cross += float(s[0]) 199 if witherror: 200 error += float(s[1])**2 201 if not witherror: 202 return cross 203 else: 204 return cross, math.sqrt(error)
205 206
207 - def scale_init_cross(self, ratio):
208 """modify the init information with the associate scale""" 209 210 assert "init" in self 211 212 all_lines = self["init"].split('\n') 213 new_data = [] 214 new_data.append(all_lines[0]) 215 for i in range(1, len(all_lines)): 216 line = all_lines[i] 217 split = line.split() 218 if len(split) == 4: 219 xsec, xerr, xmax, pid = split 220 else: 221 new_data += all_lines[i:] 222 break 223 pid = int(pid) 224 225 line = " %+13.7e %+13.7e %+13.7e %i" % \ 226 (ratio*float(xsec), ratio* float(xerr), ratio*float(xmax), pid) 227 new_data.append(line) 228 self['init'] = '\n'.join(new_data)
229
230 - def get_pdg_beam(self):
231 """return the pdg of each beam""" 232 233 assert "init" in self 234 235 all_lines = self["init"].split('\n') 236 pdg1,pdg2,_ = all_lines[0].split(None, 2) 237 return int(pdg1), int(pdg2)
238
239 - def load_basic(self, medir):
240 """ Load the proc_card /param_card and run_card """ 241 242 self.add(pjoin(medir,'Cards', 'param_card.dat')) 243 self.add(pjoin(medir,'Cards', 'run_card.dat')) 244 if os.path.exists(pjoin(medir, 'SubProcesses', 'procdef_mg5.dat')): 245 self.add(pjoin(medir,'SubProcesses', 'procdef_mg5.dat')) 246 self.add(pjoin(medir,'Cards', 'proc_card_mg5.dat')) 247 else: 248 self.add(pjoin(medir,'Cards', 'proc_card.dat'))
249
250 - def change_seed(self, seed):
251 """Change the seed value in the banner""" 252 # 0 = iseed 253 p = re.compile(r'''^\s*\d+\s*=\s*iseed''', re.M) 254 new_seed_str = " %s = iseed" % seed 255 self['mgruncard'] = p.sub(new_seed_str, self['mgruncard'])
256
257 - def add_generation_info(self, cross, nb_event):
258 """add info on MGGeneration""" 259 260 text = """ 261 # Number of Events : %s 262 # Integrated weight (pb) : %s 263 """ % (nb_event, cross) 264 self['MGGenerationInfo'] = text
265 266 ############################################################################ 267 # SPLIT BANNER 268 ############################################################################
269 - def split(self, me_dir, proc_card=True):
270 """write the banner in the Cards directory. 271 proc_card argument is present to avoid the overwrite of proc_card 272 information""" 273 274 for tag, text in self.items(): 275 if tag == 'mgversion': 276 continue 277 if not proc_card and tag in ['mg5proccard','mgproccard']: 278 continue 279 if not self.tag_to_file[tag]: 280 continue 281 ff = open(pjoin(me_dir, 'Cards', self.tag_to_file[tag]), 'w') 282 ff.write(text) 283 ff.close()
284 285 286 ############################################################################ 287 # WRITE BANNER 288 ############################################################################
289 - def check_pid(self, pid2label):
290 """special routine removing width/mass of particles not present in the model 291 This is usefull in case of loop model card, when we want to use the non 292 loop model.""" 293 294 if not hasattr(self, 'param_card'): 295 self.charge_card('slha') 296 297 for tag in ['mass', 'decay']: 298 block = self.param_card.get(tag) 299 for data in block: 300 pid = data.lhacode[0] 301 if pid not in pid2label.keys(): 302 block.remove((pid,))
303
304 - def get_lha_strategy(self):
305 """get the lha_strategy: how the weight have to be handle by the shower""" 306 307 if not self["init"]: 308 raise Exception, "No init block define" 309 310 data = self["init"].split('\n')[0].split() 311 if len(data) != 10: 312 misc.sprint(len(data), self['init']) 313 raise Exception, "init block has a wrong format" 314 return int(float(data[-2]))
315
316 - def set_lha_strategy(self, value):
317 """set the lha_strategy: how the weight have to be handle by the shower""" 318 319 if not (-4 <= int(value) <= 4): 320 raise Exception, "wrong value for lha_strategy", value 321 if not self["init"]: 322 raise Exception, "No init block define" 323 324 all_lines = self["init"].split('\n') 325 data = all_lines[0].split() 326 if len(data) != 10: 327 misc.sprint(len(data), self['init']) 328 raise Exception, "init block has a wrong format" 329 data[-2] = '%s' % value 330 all_lines[0] = ' '.join(data) 331 self['init'] = '\n'.join(all_lines)
332 333
334 - def modify_init_cross(self, cross):
335 """modify the init information with the associate cross-section""" 336 337 assert isinstance(cross, dict) 338 # assert "all" in cross 339 assert "init" in self 340 341 all_lines = self["init"].split('\n') 342 new_data = [] 343 new_data.append(all_lines[0]) 344 for i in range(1, len(all_lines)): 345 line = all_lines[i] 346 split = line.split() 347 if len(split) == 4: 348 xsec, xerr, xmax, pid = split 349 else: 350 new_data += all_lines[i:] 351 break 352 if int(pid) not in cross: 353 raise Exception 354 pid = int(pid) 355 ratio = cross[pid]/float(xsec) 356 line = " %+13.7e %+13.7e %+13.7e %i" % \ 357 (float(cross[pid]), ratio* float(xerr), ratio*float(xmax), pid) 358 new_data.append(line) 359 self['init'] = '\n'.join(new_data)
360 361 ############################################################################ 362 # WRITE BANNER 363 ############################################################################
364 - def write(self, output_path, close_tag=True, exclude=[]):
365 """write the banner""" 366 367 if isinstance(output_path, str): 368 ff = open(output_path, 'w') 369 else: 370 ff = output_path 371 372 if MADEVENT: 373 header = open(pjoin(MEDIR, 'Source', 'banner_header.txt')).read() 374 else: 375 header = open(pjoin(MG5DIR,'Template', 'LO', 'Source', 'banner_header.txt')).read() 376 377 if not self.lhe_version: 378 self.lhe_version = self.get('run_card', 'lhe_version', default=1.0) 379 if float(self.lhe_version) < 3: 380 self.lhe_version = 1.0 381 382 ff.write(header % { 'version':float(self.lhe_version)}) 383 384 385 for tag in [t for t in self.ordered_items if t in self.keys()]: 386 if tag in exclude: 387 continue 388 capitalized_tag = self.capitalized_items[tag] if tag in self.capitalized_items else tag 389 ff.write('<%(tag)s>\n%(text)s\n</%(tag)s>\n' % \ 390 {'tag':capitalized_tag, 'text':self[tag].strip()}) 391 for tag in [t for t in self.keys() if t not in self.ordered_items]: 392 if tag in ['init'] or tag in exclude: 393 continue 394 capitalized_tag = self.capitalized_items[tag] if tag in self.capitalized_items else tag 395 ff.write('<%(tag)s>\n%(text)s\n</%(tag)s>\n' % \ 396 {'tag':capitalized_tag, 'text':self[tag].strip()}) 397 398 if not '/header' in exclude: 399 ff.write('</header>\n') 400 401 if 'init' in self and not 'init' in exclude: 402 text = self['init'] 403 ff.write('<%(tag)s>\n%(text)s\n</%(tag)s>\n' % \ 404 {'tag':'init', 'text':text.strip()}) 405 if close_tag: 406 ff.write('</LesHouchesEvents>\n') 407 return ff
408 409 410 ############################################################################ 411 # BANNER 412 ############################################################################
413 - def add(self, path, tag=None):
414 """Add the content of the file to the banner""" 415 416 if not tag: 417 card_name = os.path.basename(path) 418 if 'param_card' in card_name: 419 tag = 'slha' 420 elif 'run_card' in card_name: 421 tag = 'MGRunCard' 422 elif 'pythia_card' in card_name: 423 tag = 'MGPythiaCard' 424 elif 'pythia8_card' in card_name or 'pythia8.cmd' in card_name: 425 tag = 'MGPythiaCard' 426 elif 'pgs_card' in card_name: 427 tag = 'MGPGSCard' 428 elif 'delphes_card' in card_name: 429 tag = 'MGDelphesCard' 430 elif 'delphes_trigger' in card_name: 431 tag = 'MGDelphesTrigger' 432 elif 'proc_card_mg5' in card_name: 433 tag = 'MG5ProcCard' 434 elif 'proc_card' in card_name: 435 tag = 'MGProcCard' 436 elif 'procdef_mg5' in card_name: 437 tag = 'MGProcCard' 438 elif 'shower_card' in card_name: 439 tag = 'MGShowerCard' 440 elif 'madspin_card' in card_name: 441 tag = 'madspin' 442 elif 'FO_analyse_card' in card_name: 443 tag = 'foanalyse' 444 elif 'reweight_card' in card_name: 445 tag='reweight_card' 446 elif 'madanalysis5_parton_card' in card_name: 447 tag='MA5Card_parton' 448 elif 'madanalysis5_hadron_card' in card_name: 449 tag='MA5Card_hadron' 450 else: 451 raise Exception, 'Impossible to know the type of the card' 452 453 self.add_text(tag.lower(), open(path).read())
454
455 - def add_text(self, tag, text):
456 """Add the content of the file to the banner""" 457 458 if tag == 'param_card': 459 tag = 'slha' 460 elif tag == 'run_card': 461 tag = 'mgruncard' 462 elif tag == 'proc_card': 463 tag = 'mg5proccard' 464 elif tag == 'shower_card': 465 tag = 'mgshowercard' 466 elif tag == 'FO_analyse_card': 467 tag = 'foanalyse' 468 469 self[tag.lower()] = text
470 471
472 - def charge_card(self, tag):
473 """Build the python object associated to the card""" 474 475 if tag == 'param_card': 476 tag = 'slha' 477 elif tag == 'run_card': 478 tag = 'mgruncard' 479 elif tag == 'proc_card': 480 tag = 'mg5proccard' 481 elif tag == 'shower_card': 482 tag = 'mgshowercard' 483 elif tag == 'FO_analyse_card': 484 tag = 'foanalyse' 485 486 assert tag in ['slha', 'mgruncard', 'mg5proccard', 'mgshowercard', 'foanalyse'], 'invalid card %s' % tag 487 488 if tag == 'slha': 489 param_card = self[tag].split('\n') 490 self.param_card = param_card_reader.ParamCard(param_card) 491 return self.param_card 492 elif tag == 'mgruncard': 493 self.run_card = RunCard(self[tag]) 494 return self.run_card 495 elif tag == 'mg5proccard': 496 proc_card = self[tag].split('\n') 497 self.proc_card = ProcCard(proc_card) 498 return self.proc_card 499 elif tag =='mgshowercard': 500 shower_content = self[tag] 501 if MADEVENT: 502 import internal.shower_card as shower_card 503 else: 504 import madgraph.various.shower_card as shower_card 505 self.shower_card = shower_card.ShowerCard(shower_content, True) 506 # set testing to false (testing = true allow to init using 507 # the card content instead of the card path" 508 self.shower_card.testing = False 509 return self.shower_card 510 elif tag =='foanalyse': 511 analyse_content = self[tag] 512 if MADEVENT: 513 import internal.FO_analyse_card as FO_analyse_card 514 else: 515 import madgraph.various.FO_analyse_card as FO_analyse_card 516 # set testing to false (testing = true allow to init using 517 # the card content instead of the card path" 518 self.FOanalyse_card = FO_analyse_card.FOAnalyseCard(analyse_content, True) 519 self.FOanalyse_card.testing = False 520 return self.FOanalyse_card
521 522
523 - def get_detail(self, tag, *arg, **opt):
524 """return a specific """ 525 526 if tag in ['param_card', 'param']: 527 tag = 'slha' 528 attr_tag = 'param_card' 529 elif tag in ['run_card', 'run']: 530 tag = 'mgruncard' 531 attr_tag = 'run_card' 532 elif tag == 'proc_card': 533 tag = 'mg5proccard' 534 attr_tag = 'proc_card' 535 elif tag == 'model': 536 tag = 'mg5proccard' 537 attr_tag = 'proc_card' 538 arg = ('model',) 539 elif tag == 'generate': 540 tag = 'mg5proccard' 541 attr_tag = 'proc_card' 542 arg = ('generate',) 543 elif tag == 'shower_card': 544 tag = 'mgshowercard' 545 attr_tag = 'shower_card' 546 assert tag in ['slha', 'mgruncard', 'mg5proccard', 'shower_card'], '%s not recognized' % tag 547 548 if not hasattr(self, attr_tag): 549 self.charge_card(attr_tag) 550 551 card = getattr(self, attr_tag) 552 if len(arg) == 0: 553 return card 554 elif len(arg) == 1: 555 if tag == 'mg5proccard': 556 try: 557 return card.get(arg[0]) 558 except KeyError, error: 559 if 'default' in opt: 560 return opt['default'] 561 else: 562 raise 563 try: 564 return card[arg[0]] 565 except KeyError: 566 if 'default' in opt: 567 return opt['default'] 568 else: 569 raise 570 elif len(arg) == 2 and tag == 'slha': 571 try: 572 return card[arg[0]].get(arg[1:]) 573 except KeyError: 574 if 'default' in opt: 575 return opt['default'] 576 else: 577 raise 578 elif len(arg) == 0: 579 return card 580 else: 581 raise Exception, "Unknow command"
582 583 #convenient alias 584 get = get_detail 585
586 - def set(self, card, *args):
587 """modify one of the cards""" 588 589 if tag == 'param_card': 590 tag = 'slha' 591 attr_tag = 'param_card' 592 elif tag == 'run_card': 593 tag = 'mgruncard' 594 attr_tag = 'run_card' 595 elif tag == 'proc_card': 596 tag = 'mg5proccard' 597 attr_tag = 'proc_card' 598 elif tag == 'model': 599 tag = 'mg5proccard' 600 attr_tag = 'proc_card' 601 arg = ('model',) 602 elif tag == 'generate': 603 tag = 'mg5proccard' 604 attr_tag = 'proc_card' 605 arg = ('generate',) 606 elif tag == 'shower_card': 607 tag = 'mgshowercard' 608 attr_tag = 'shower_card' 609 assert tag in ['slha', 'mgruncard', 'mg5proccard', 'shower_card'], 'not recognized' 610 611 if not hasattr(self, attr_tag): 612 self.charge_card(attr_tag) 613 614 card = getattr(self, attr_tag) 615 if len(args) ==2: 616 if tag == 'mg5proccard': 617 card.info[args[0]] = args[-1] 618 else: 619 card[args[0]] = args[1] 620 else: 621 card[args[:-1]] = args[-1]
622 623 624 @misc.multiple_try()
625 - def add_to_file(self, path, seed=None, out=None):
626 """Add the banner to a file and change the associate seed in the banner""" 627 628 if seed is not None: 629 self.set("run_card", "iseed", seed) 630 631 if not out: 632 path_out = "%s.tmp" % path 633 else: 634 path_out = out 635 636 ff = self.write(path_out, close_tag=False, 637 exclude=['MGGenerationInfo', '/header', 'init']) 638 ff.write("## END BANNER##\n") 639 if self.lhe_version >= 3: 640 #add the original content 641 [ff.write(line) if not line.startswith("<generator name='MadGraph5_aMC@NLO'") 642 else ff.write("<generator name='MadGraph5_aMC@NLO' version='%s'>" % self['mgversion'][:-1]) 643 for line in open(path)] 644 else: 645 [ff.write(line) for line in open(path)] 646 ff.write("</LesHouchesEvents>\n") 647 ff.close() 648 if out: 649 os.remove(path) 650 else: 651 files.mv(path_out, path)
652
653 654 655 -def split_banner(banner_path, me_dir, proc_card=True):
656 """a simple way to split a banner""" 657 658 banner = Banner(banner_path) 659 banner.split(me_dir, proc_card)
660
661 -def recover_banner(results_object, level, run=None, tag=None):
662 """as input we receive a gen_crossxhtml.AllResults object. 663 This define the current banner and load it 664 """ 665 666 if not run: 667 try: 668 _run = results_object.current['run_name'] 669 _tag = results_object.current['tag'] 670 except Exception: 671 return Banner() 672 else: 673 _run = run 674 if not tag: 675 try: 676 _tag = results_object[run].tags[-1] 677 except Exception,error: 678 return Banner() 679 else: 680 _tag = tag 681 682 path = results_object.path 683 banner_path = pjoin(path,'Events',run,'%s_%s_banner.txt' % (run, tag)) 684 685 if not os.path.exists(banner_path): 686 if level != "parton" and tag != _tag: 687 return recover_banner(results_object, level, _run, results_object[_run].tags[0]) 688 elif level == 'parton': 689 paths = [pjoin(path,'Events',run, 'unweighted_events.lhe.gz'), 690 pjoin(path,'Events',run, 'unweighted_events.lhe'), 691 pjoin(path,'Events',run, 'events.lhe.gz'), 692 pjoin(path,'Events',run, 'events.lhe')] 693 for p in paths: 694 if os.path.exists(p): 695 if MADEVENT: 696 import internal.lhe_parser as lhe_parser 697 else: 698 import madgraph.various.lhe_parser as lhe_parser 699 lhe = lhe_parser.EventFile(p) 700 return Banner(lhe.banner) 701 702 # security if the banner was remove (or program canceled before created it) 703 return Banner() 704 banner = Banner(banner_path) 705 706 707 708 if level == 'pythia': 709 if 'mgpythiacard' in banner: 710 del banner['mgpythiacard'] 711 if level in ['pythia','pgs','delphes']: 712 for tag in ['mgpgscard', 'mgdelphescard', 'mgdelphestrigger']: 713 if tag in banner: 714 del banner[tag] 715 return banner
716
717 -class InvalidRunCard(InvalidCmd):
718 pass
719
720 -class ProcCard(list):
721 """Basic Proccard object""" 722 723 history_header = \ 724 '#************************************************************\n' + \ 725 '#* MadGraph5_aMC@NLO *\n' + \ 726 '#* *\n' + \ 727 "#* * * *\n" + \ 728 "#* * * * * *\n" + \ 729 "#* * * * * 5 * * * * *\n" + \ 730 "#* * * * * *\n" + \ 731 "#* * * *\n" + \ 732 "#* *\n" + \ 733 "#* *\n" + \ 734 "%(info_line)s" +\ 735 "#* *\n" + \ 736 "#* The MadGraph5_aMC@NLO Development Team - Find us at *\n" + \ 737 "#* https://server06.fynu.ucl.ac.be/projects/madgraph *\n" + \ 738 '#* *\n' + \ 739 '#************************************************************\n' + \ 740 '#* *\n' + \ 741 '#* Command File for MadGraph5_aMC@NLO *\n' + \ 742 '#* *\n' + \ 743 '#* run as ./bin/mg5_aMC filename *\n' + \ 744 '#* *\n' + \ 745 '#************************************************************\n' 746 747 748 749
750 - def __init__(self, init=None):
751 """ initialize a basic proc_card""" 752 self.info = {'model': 'sm', 'generate':None, 753 'full_model_line':'import model sm'} 754 list.__init__(self) 755 if init: 756 self.read(init)
757 758
759 - def read(self, init):
760 """read the proc_card and save the information""" 761 762 if isinstance(init, str): #path to file 763 init = file(init, 'r') 764 765 store_line = '' 766 for line in init: 767 line = line.rstrip() 768 if line.endswith('\\'): 769 store_line += line[:-1] 770 else: 771 tmp = store_line + line 772 self.append(tmp.strip()) 773 store_line = "" 774 if store_line: 775 raise Exception, "WRONG CARD FORMAT"
776 777
778 - def move_to_last(self, cmd):
779 """move an element to the last history.""" 780 for line in self[:]: 781 if line.startswith(cmd): 782 self.remove(line) 783 list.append(self, line)
784
785 - def append(self, line):
786 """"add a line in the proc_card perform automatically cleaning""" 787 788 line = line.strip() 789 cmds = line.split() 790 if len(cmds) == 0: 791 return 792 793 list.append(self, line) 794 795 # command type: 796 cmd = cmds[0] 797 798 if cmd == 'output': 799 # Remove previous outputs from history 800 self.clean(allow_for_removal = ['output'], keep_switch=True, 801 remove_bef_last='output') 802 elif cmd == 'generate': 803 # Remove previous generations from history 804 self.clean(remove_bef_last='generate', keep_switch=True, 805 allow_for_removal= ['generate', 'add process', 'output']) 806 self.info['generate'] = ' '.join(cmds[1:]) 807 elif cmd == 'add' and cmds[1] == 'process' and not self.info['generate']: 808 self.info['generate'] = ' '.join(cmds[2:]) 809 elif cmd == 'import': 810 if len(cmds) < 2: 811 return 812 if cmds[1].startswith('model'): 813 self.info['full_model_line'] = line 814 self.clean(remove_bef_last='import', keep_switch=True, 815 allow_for_removal=['generate', 'add process', 'add model', 'output']) 816 if cmds[1] == 'model': 817 self.info['model'] = cmds[2] 818 else: 819 self.info['model'] = None # not UFO model 820 elif cmds[1] == 'proc_v4': 821 #full cleaning 822 self[:] = []
823 824
825 - def clean(self, to_keep=['set','add','load'], 826 remove_bef_last=None, 827 to_remove=['open','display','launch', 'check','history'], 828 allow_for_removal=None, 829 keep_switch=False):
830 """Remove command in arguments from history. 831 All command before the last occurrence of 'remove_bef_last' 832 (including it) will be removed (but if another options tells the opposite). 833 'to_keep' is a set of line to always keep. 834 'to_remove' is a set of line to always remove (don't care about remove_bef_ 835 status but keep_switch acts.). 836 if 'allow_for_removal' is define only the command in that list can be 837 remove of the history for older command that remove_bef_lb1. all parameter 838 present in to_remove are always remove even if they are not part of this 839 list. 840 keep_switch force to keep the statement remove_bef_??? which changes starts 841 the removal mode. 842 """ 843 844 #check consistency 845 if __debug__ and allow_for_removal: 846 for arg in to_keep: 847 assert arg not in allow_for_removal 848 849 850 nline = -1 851 removal = False 852 #looping backward 853 while nline > -len(self): 854 switch = False # set in True when removal pass in True 855 856 #check if we need to pass in removal mode 857 if not removal and remove_bef_last: 858 if self[nline].startswith(remove_bef_last): 859 removal = True 860 switch = True 861 862 # if this is the switch and is protected pass to the next element 863 if switch and keep_switch: 864 nline -= 1 865 continue 866 867 # remove command in to_remove (whatever the status of removal) 868 if any([self[nline].startswith(arg) for arg in to_remove]): 869 self.pop(nline) 870 continue 871 872 # Only if removal mode is active! 873 if removal: 874 if allow_for_removal: 875 # Only a subset of command can be removed 876 if any([self[nline].startswith(arg) 877 for arg in allow_for_removal]): 878 self.pop(nline) 879 continue 880 elif not any([self[nline].startswith(arg) for arg in to_keep]): 881 # All command have to be remove but protected 882 self.pop(nline) 883 continue 884 885 # update the counter to pass to the next element 886 nline -= 1
887
888 - def get(self, tag, default=None):
889 if isinstance(tag, int): 890 list.__getattr__(self, tag) 891 elif tag == 'info' or tag == "__setstate__": 892 return default #for pickle 893 elif tag == "multiparticles": 894 out = [] 895 for line in self: 896 if line.startswith('define'): 897 name, content = line[7:].split('=',1) 898 out.append((name, content)) 899 return out 900 else: 901 return self.info[tag]
902
903 - def write(self, path):
904 """write the proc_card to a given path""" 905 906 fsock = open(path, 'w') 907 fsock.write(self.history_header) 908 for line in self: 909 while len(line) > 70: 910 sub, line = line[:70]+"\\" , line[70:] 911 fsock.write(sub+"\n") 912 else: 913 fsock.write(line+"\n")
914
915 916 -class ConfigFile(dict):
917 """ a class for storing/dealing with input file. 918 """ 919
920 - def __init__(self, finput=None, **opt):
921 """initialize a new instance. input can be an instance of MadLoopParam, 922 a file, a path to a file, or simply Nothing""" 923 924 if isinstance(finput, self.__class__): 925 dict.__init__(self, finput) 926 assert finput.__dict__.keys() 927 for key in finput.__dict__: 928 setattr(self, key, copy.copy(getattr(finput, key)) ) 929 return 930 else: 931 dict.__init__(self) 932 933 # Initialize it with all the default value 934 self.user_set = set() 935 self.auto_set = set() 936 self.system_only = set() 937 self.lower_to_case = {} 938 self.list_parameter = set() 939 self.dict_parameter = {} 940 self.comments = {} # comment associated to parameters. can be display via help message 941 942 self.default_setup() 943 944 945 # if input is define read that input 946 if isinstance(finput, (file, str, StringIO.StringIO)): 947 self.read(finput, **opt)
948
949 - def default_setup(self):
950 pass
951
952 - def __copy__(self):
953 return self.__class__(self)
954
955 - def __add__(self, other):
956 """define the sum""" 957 assert isinstance(other, dict) 958 base = self.__class__(self) 959 #base = copy.copy(self) 960 base.update((key.lower(),value) for key, value in other.items()) 961 return base
962
963 - def __radd__(self, other):
964 """define the sum""" 965 new = copy.copy(other) 966 new.update((key, value) for key, value in self.items()) 967 return new
968
969 - def __contains__(self, key):
970 return dict.__contains__(self, key.lower())
971
972 - def __iter__(self):
973 iter = super(ConfigFile, self).__iter__() 974 return (self.lower_to_case[name] for name in iter)
975
976 - def keys(self):
977 return [name for name in self]
978
979 - def items(self):
980 return [(name,self[name]) for name in self]
981 982
983 - def __setitem__(self, name, value, change_userdefine=False):
984 """set the attribute and set correctly the type if the value is a string. 985 change_userdefine on True if we have to add the parameter in user_set 986 """ 987 if not len(self): 988 #Should never happen but when deepcopy/pickle 989 self.__init__() 990 991 992 name = name.strip() 993 lower_name = name.lower() 994 # 0. check if this parameter is a system only one 995 if change_userdefine and lower_name in self.system_only: 996 logger.critical('%s is a private entry which can not be modify by the user. Keep value at %s' % (name,self[name])) 997 return 998 999 #1. check if the parameter is set to auto -> pass it to special 1000 if lower_name in self: 1001 targettype = type(dict.__getitem__(self, lower_name)) 1002 if targettype != str and isinstance(value, str) and value.lower() == 'auto': 1003 self.auto_set.add(lower_name) 1004 if lower_name in self.user_set: 1005 self.user_set.remove(lower_name) 1006 #keep old value. 1007 return 1008 elif lower_name in self.auto_set: 1009 self.auto_set.remove(lower_name) 1010 1011 # 2. Find the type of the attribute that we want 1012 if lower_name in self.list_parameter: 1013 if isinstance(self[name], list): 1014 targettype = type(self[name][0]) 1015 else: 1016 #should not happen but better save than sorry 1017 targettype = type(dict.__getitem__(self,name)) 1018 if isinstance(value, str): 1019 # split for each comma/space 1020 value = value.strip() 1021 if value.startswith('[') and value.endswith(']'): 1022 value = value[1:-1] 1023 #do not perform split within a " or ' block 1024 data = re.split(r"((?<![\\])['\"])((?:.(?!(?<![\\])\1))*.?)\1", str(value)) 1025 new_value = [] 1026 i = 0 1027 while len(data) > i: 1028 current = filter(None, re.split(r'(?:(?<!\\)\s)|,', data[i], re.VERBOSE)) 1029 i+=1 1030 if len(data) > i+1: 1031 if current: 1032 current[-1] += '{0}{1}{0}'.format(data[i], data[i+1]) 1033 else: 1034 current = ['{0}{1}{0}'.format(data[i], data[i+1])] 1035 i+=2 1036 new_value += current 1037 1038 1039 1040 value = new_value 1041 1042 elif not hasattr(value, '__iter__'): 1043 value = [value] 1044 elif isinstance(value, dict): 1045 raise Exception, "not being able to handle dictionary in card entry" 1046 #format each entry 1047 values =[self.format_variable(v, targettype, name=name) 1048 for v in value] 1049 dict.__setitem__(self, lower_name, values) 1050 if change_userdefine: 1051 self.user_set.add(lower_name) 1052 return 1053 elif lower_name in self.dict_parameter: 1054 targettype = self.dict_parameter[lower_name] 1055 full_reset = True #check if we just update the current dict or not 1056 1057 if isinstance(value, str): 1058 value = value.strip() 1059 # allowed entry: 1060 # name : value => just add the entry 1061 # name , value => just add the entry 1062 # name value => just add the entry 1063 # {name1:value1, name2:value2} => full reset 1064 1065 # split for each comma/space 1066 if value.startswith('{') and value.endswith('}'): 1067 new_value = {} 1068 for pair in value[1:-1].split(','): 1069 if not pair.strip(): 1070 break 1071 x, y = pair.split(':') 1072 x, y = x.strip(), y.strip() 1073 if x.startswith(('"',"'")) and x.endswith(x[0]): 1074 x = x[1:-1] 1075 new_value[x] = y 1076 value = new_value 1077 elif ',' in value: 1078 x,y = value.split(',') 1079 value = {x.strip():y.strip()} 1080 full_reset = False 1081 1082 elif ':' in value: 1083 x,y = value.split(':') 1084 value = {x.strip():y.strip()} 1085 full_reset = False 1086 else: 1087 x,y = value.split() 1088 value = {x:y} 1089 full_reset = False 1090 1091 if isinstance(value, dict): 1092 for key in value: 1093 value[key] = self.format_variable(value[key], targettype, name=name) 1094 if full_reset: 1095 dict.__setitem__(self, lower_name, value) 1096 else: 1097 dict.__getitem__(self, lower_name).update(value) 1098 else: 1099 raise Exception, '%s should be of dict type'% lower_name 1100 if change_userdefine: 1101 self.user_set.add(lower_name) 1102 return 1103 elif name in self: 1104 targettype = type(self[name]) 1105 else: 1106 logger.debug('Trying to add argument %s in %s. ' % (name, self.__class__.__name__) +\ 1107 'This argument is not defined by default. Please consider adding it.') 1108 suggestions = [k for k in self.keys() if k.startswith(name[0].lower())] 1109 if len(suggestions)>0: 1110 logger.debug("Did you mean one of the following: %s"%suggestions) 1111 self.add_param(lower_name, self.format_variable(UnknownType(value), 1112 UnknownType, name)) 1113 self.lower_to_case[lower_name] = name 1114 if change_userdefine: 1115 self.user_set.add(lower_name) 1116 return 1117 1118 value = self.format_variable(value, targettype, name=name) 1119 dict.__setitem__(self, lower_name, value) 1120 if change_userdefine: 1121 self.user_set.add(lower_name)
1122
1123 - def add_param(self, name, value, system=False, comment=False):
1124 """add a default parameter to the class""" 1125 1126 lower_name = name.lower() 1127 if __debug__: 1128 if lower_name in self: 1129 raise Exception("Duplicate case for %s in %s" % (name,self.__class__)) 1130 1131 dict.__setitem__(self, lower_name, value) 1132 self.lower_to_case[lower_name] = name 1133 if isinstance(value, list): 1134 if any([type(value[0]) != type(v) for v in value]): 1135 raise Exception, "All entry should have the same type" 1136 self.list_parameter.add(lower_name) 1137 elif isinstance(value, dict): 1138 allvalues = value.values() 1139 if any([type(allvalues[0]) != type(v) for v in allvalues]): 1140 raise Exception, "All entry should have the same type" 1141 self.dict_parameter[lower_name] = type(allvalues[0]) 1142 if '__type__' in value: 1143 del value['__type__'] 1144 dict.__setitem__(self, lower_name, value) 1145 1146 1147 if system: 1148 self.system_only.add(lower_name) 1149 if comment: 1150 self.comments[lower_name] = comment
1151
1152 - def do_help(self, name):
1153 """return a minimal help for the parameter""" 1154 1155 out = "## Information on parameter %s from class %s\n" % (name, self.__class__.__name__) 1156 if name.lower() in self: 1157 out += "## current value: %s (parameter should be of type %s)\n" % (self[name], type(self[name])) 1158 if name.lower() in self.comments: 1159 out += '## %s\n' % self.comments[name.lower()].replace('\n', '\n## ') 1160 else: 1161 out += "## Unknown for this class\n" 1162 if name.lower() in self.user_set: 1163 out += "## This value is considered as been set by the user\n" 1164 else: 1165 out += "## This value is considered as been set by the system\n" 1166 logger.info(out)
1167 1168 @staticmethod
1169 - def format_variable(value, targettype, name="unknown"):
1170 """assign the value to the attribute for the given format""" 1171 1172 if not isinstance(value, str): 1173 # just have to check that we have the correct format 1174 if isinstance(value, targettype): 1175 pass # assignement at the end 1176 elif isinstance(value, numbers.Number) and issubclass(targettype, numbers.Number): 1177 try: 1178 new_value = targettype(value) 1179 except TypeError: 1180 if value.imag/value.real<1e-12: 1181 new_value = targettype(value.real) 1182 else: 1183 raise 1184 if new_value == value: 1185 value = new_value 1186 else: 1187 raise Exception, "Wrong input type for %s found %s and expecting %s for value %s" %\ 1188 (name, type(value), targettype, value) 1189 else: 1190 raise Exception, "Wrong input type for %s found %s and expecting %s for value %s" %\ 1191 (name, type(value), targettype, value) 1192 else: 1193 # We have a string we have to format the attribute from the string 1194 if targettype == UnknownType: 1195 # No formatting 1196 pass 1197 elif targettype == bool: 1198 value = value.strip() 1199 if value.lower() in ['0', '.false.', 'f', 'false', 'off']: 1200 value = False 1201 elif value.lower() in ['1', '.true.', 't', 'true', 'on']: 1202 value = True 1203 else: 1204 raise Exception, "%s can not be mapped to True/False for %s" % (repr(value),name) 1205 elif targettype == str: 1206 value = value.strip() 1207 if value.startswith('\'') and value.endswith('\''): 1208 value = value[1:-1] 1209 elif value.startswith('"') and value.endswith('"'): 1210 value = value[1:-1] 1211 elif targettype == int: 1212 if value.isdigit(): 1213 value = int(value) 1214 elif value[1:].isdigit() and value[0] == '-': 1215 value = int(value) 1216 else: 1217 try: 1218 value = float(value.replace('d','e')) 1219 except ValueError: 1220 raise Exception, "%s can not be mapped to an integer" % value 1221 try: 1222 new_value = int(value) 1223 except ValueError: 1224 raise Exception, "%s can not be mapped to an integer" % value 1225 else: 1226 if value == new_value: 1227 value = new_value 1228 else: 1229 raise Exception, "incorect input: %s need an integer for %s" % (value,name) 1230 elif targettype == float: 1231 value = value.replace('d','e') # pass from Fortran formatting 1232 try: 1233 value = float(value) 1234 except ValueError: 1235 try: 1236 split = re.split('(\*|/)',value) 1237 v = float(split[0]) 1238 for i in range((len(split)//2)): 1239 if split[2*i+1] == '*': 1240 v *= float(split[2*i+2]) 1241 else: 1242 v /= float(split[2*i+2]) 1243 except: 1244 v=0 1245 raise Exception, "%s can not be mapped to a float" % value 1246 finally: 1247 value = v 1248 else: 1249 raise Exception, "type %s is not handle by the card" % targettype 1250 1251 return value
1252 1253 1254
1255 - def __getitem__(self, name):
1256 1257 lower_name = name.lower() 1258 if __debug__: 1259 if lower_name not in self: 1260 if lower_name in [key.lower() for key in self] : 1261 raise Exception, "Some key are not lower case %s. Invalid use of the class!"\ 1262 % [key for key in self if key.lower() != key] 1263 1264 if lower_name in self.auto_set: 1265 return 'auto' 1266 1267 return dict.__getitem__(self, name.lower())
1268 1269
1270 - def set(self, name, value, changeifuserset=True, user=False):
1271 """convenient way to change attribute. 1272 changeifuserset=False means that the value is NOT change is the value is not on default. 1273 user=True, means that the value will be marked as modified by the user 1274 (potentially preventing future change to the value) 1275 """ 1276 1277 # changeifuserset=False -> we need to check if the user force a value. 1278 if not changeifuserset: 1279 if name.lower() in self.user_set: 1280 #value modified by the user -> do nothing 1281 return 1282 1283 self.__setitem__(name, value, change_userdefine=user)
1284
1285 1286 1287 -class ProcCharacteristic(ConfigFile):
1288 """A class to handle information which are passed from MadGraph to the madevent 1289 interface.""" 1290
1291 - def default_setup(self):
1292 """initialize the directory to the default value""" 1293 1294 self.add_param('loop_induced', False) 1295 self.add_param('has_isr', False) 1296 self.add_param('has_fsr', False) 1297 self.add_param('nb_channel', 0) 1298 self.add_param('nexternal', 0) 1299 self.add_param('ninitial', 0) 1300 self.add_param('grouped_matrix', True) 1301 self.add_param('has_loops', False) 1302 self.add_param('bias_module','None') 1303 self.add_param('max_n_matched_jets', 0) 1304 self.add_param('colored_pdgs', [1,2,3,4,5]) 1305 self.add_param('complex_mass_scheme', False)
1306
1307 - def read(self, finput):
1308 """Read the input file, this can be a path to a file, 1309 a file object, a str with the content of the file.""" 1310 1311 if isinstance(finput, str): 1312 if "\n" in finput: 1313 finput = finput.split('\n') 1314 elif os.path.isfile(finput): 1315 finput = open(finput) 1316 else: 1317 raise Exception, "No such file %s" % finput 1318 1319 for line in finput: 1320 if '#' in line: 1321 line = line.split('#',1)[0] 1322 if not line: 1323 continue 1324 1325 if '=' in line: 1326 key, value = line.split('=',1) 1327 self[key.strip()] = value
1328
1329 - def write(self, outputpath):
1330 """write the file""" 1331 1332 template ="# Information about the process #\n" 1333 template +="#########################################\n" 1334 1335 fsock = open(outputpath, 'w') 1336 fsock.write(template) 1337 1338 for key, value in self.items(): 1339 fsock.write(" %s = %s \n" % (key, value)) 1340 1341 fsock.close()
1342
1343 1344 1345 1346 -class GridpackCard(ConfigFile):
1347 """an object for the GridpackCard""" 1348
1349 - def default_setup(self):
1350 """default value for the GridpackCard""" 1351 1352 self.add_param("GridRun", True) 1353 self.add_param("gevents", 2500) 1354 self.add_param("gseed", 1) 1355 self.add_param("ngran", -1)
1356
1357 - def read(self, finput):
1358 """Read the input file, this can be a path to a file, 1359 a file object, a str with the content of the file.""" 1360 1361 if isinstance(finput, str): 1362 if "\n" in finput: 1363 finput = finput.split('\n') 1364 elif os.path.isfile(finput): 1365 finput = open(finput) 1366 else: 1367 raise Exception, "No such file %s" % finput 1368 1369 for line in finput: 1370 line = line.split('#')[0] 1371 line = line.split('!')[0] 1372 line = line.split('=',1) 1373 if len(line) != 2: 1374 continue 1375 self[line[1].strip()] = line[0].replace('\'','').strip()
1376
1377 - def write(self, output_file, template=None):
1378 """Write the run_card in output_file according to template 1379 (a path to a valid run_card)""" 1380 1381 if not template: 1382 if not MADEVENT: 1383 template = pjoin(MG5DIR, 'Template', 'LO', 'Cards', 1384 'grid_card_default.dat') 1385 else: 1386 template = pjoin(MEDIR, 'Cards', 'grid_card_default.dat') 1387 1388 1389 text = "" 1390 for line in file(template,'r'): 1391 nline = line.split('#')[0] 1392 nline = nline.split('!')[0] 1393 comment = line[len(nline):] 1394 nline = nline.split('=') 1395 if len(nline) != 2: 1396 text += line 1397 elif nline[1].strip() in self: 1398 text += ' %s\t= %s %s' % (self[nline[1].strip()],nline[1], comment) 1399 else: 1400 logger.info('Adding missing parameter %s to current run_card (with default value)' % nline[1].strip()) 1401 text += line 1402 1403 fsock = open(output_file,'w') 1404 fsock.write(text) 1405 fsock.close()
1406
1407 -class PY8Card(ConfigFile):
1408 """ Implements the Pythia8 card.""" 1409
1410 - def add_default_subruns(self, type):
1411 """ Placeholder function to allow overwriting in the PY8SubRun daughter. 1412 The initialization of the self.subruns attribute should of course not 1413 be performed in PY8SubRun.""" 1414 if type == 'parameters': 1415 if "LHEFInputs:nSubruns" not in self: 1416 self.add_param("LHEFInputs:nSubruns", 1, 1417 hidden='ALWAYS_WRITTEN', 1418 comment=""" 1419 ==================== 1420 Subrun definitions 1421 ==================== 1422 """) 1423 if type == 'attributes': 1424 if not(hasattr(self,'subruns')): 1425 first_subrun = PY8SubRun(subrun_id=0) 1426 self.subruns = dict([(first_subrun['Main:subrun'],first_subrun)])
1427
1428 - def default_setup(self):
1429 """ Sets up the list of available PY8 parameters.""" 1430 1431 # Visible parameters 1432 # ================== 1433 self.add_param("Main:numberOfEvents", -1) 1434 # for MLM merging 1435 # -1.0 means that it will be set automatically by MadGraph5_aMC@NLO 1436 self.add_param("JetMatching:qCut", -1.0, always_write_to_card=False) 1437 self.add_param("JetMatching:doShowerKt",False,always_write_to_card=False) 1438 # -1 means that it is automatically set. 1439 self.add_param("JetMatching:nJetMax", -1, always_write_to_card=False) 1440 # for CKKWL merging 1441 self.add_param("Merging:TMS", -1.0, always_write_to_card=False) 1442 self.add_param("Merging:Process", '<set_by_user>', always_write_to_card=False) 1443 # -1 means that it is automatically set. 1444 self.add_param("Merging:nJetMax", -1, always_write_to_card=False) 1445 # for both merging, chose whether to also consider different merging 1446 # scale values for the extra weights related to scale and PDF variations. 1447 self.add_param("SysCalc:fullCutVariation", False) 1448 # Select the HepMC output. The user can prepend 'fifo:<optional_fifo_path>' 1449 # to indicate that he wants to pipe the output. Or /dev/null to turn the 1450 # output off. 1451 self.add_param("HEPMCoutput:file", 'auto') 1452 1453 # Hidden parameters always written out 1454 # ==================================== 1455 self.add_param("Beams:frameType", 4, 1456 hidden=True, 1457 comment='Tell Pythia8 that an LHEF input is used.') 1458 self.add_param("HEPMCoutput:scaling", 1.0e9, 1459 hidden=True, 1460 comment='1.0 corresponds to HEPMC weight given in [mb]. We choose here the [pb] normalization.') 1461 self.add_param("Check:epTolErr", 1e-2, 1462 hidden=True, 1463 comment='Be more forgiving with momentum mismatches.') 1464 # By default it is important to disable any cut on the rapidity of the showered jets 1465 # during MLML merging and by default it is set to 2.5 1466 self.add_param("JetMatching:etaJetMax", 1000.0, hidden=True, always_write_to_card=True) 1467 1468 # Hidden parameters written out only if user_set or system_set 1469 # ============================================================ 1470 self.add_param("PDF:pSet", 'LHAPDF5:CT10.LHgrid', hidden=True, always_write_to_card=False, 1471 comment='Reminder: Parameter below is shower tune dependent.') 1472 self.add_param("SpaceShower:alphaSvalue", 0.118, hidden=True, always_write_to_card=False, 1473 comment='Reminder: Parameter below is shower tune dependent.') 1474 self.add_param("TimeShower:alphaSvalue", 0.118, hidden=True, always_write_to_card=False, 1475 comment='Reminder: Parameter below is shower tune dependent.') 1476 self.add_param("hadronlevel:all", True, hidden=True, always_write_to_card=False, 1477 comment='This allows to turn on/off hadronization alltogether.') 1478 self.add_param("partonlevel:mpi", True, hidden=True, always_write_to_card=False, 1479 comment='This allows to turn on/off MPI alltogether.') 1480 self.add_param("Beams:setProductionScalesFromLHEF", False, hidden=True, 1481 always_write_to_card=False, 1482 comment='This parameter is automatically set to True by MG5aMC when doing MLM merging with PY8.') 1483 1484 # for MLM merging 1485 self.add_param("JetMatching:merge", False, hidden=True, always_write_to_card=False, 1486 comment='Specifiy if we are merging sample of different multiplicity.') 1487 self.add_param("SysCalc:qCutList", [10.0,20.0], hidden=True, always_write_to_card=False) 1488 self['SysCalc:qCutList'] = 'auto' 1489 self.add_param("SysCalc:qWeed",-1.0,hidden=True, always_write_to_card=False, 1490 comment='Value of the merging scale below which one does not even write the HepMC event.') 1491 self.add_param("JetMatching:doVeto", False, hidden=True, always_write_to_card=False, 1492 comment='Do veto externally (e.g. in SysCalc).') 1493 self.add_param("JetMatching:scheme", 1, hidden=True, always_write_to_card=False) 1494 self.add_param("JetMatching:setMad", False, hidden=True, always_write_to_card=False, 1495 comment='Specify one must read inputs from the MadGraph banner.') 1496 self.add_param("JetMatching:coneRadius", 1.0, hidden=True, always_write_to_card=False) 1497 self.add_param("JetMatching:nQmatch",4,hidden=True, always_write_to_card=False) 1498 # for CKKWL merging (common with UMEPS, UNLOPS) 1499 self.add_param("TimeShower:pTmaxMatch", 2, hidden=True, always_write_to_card=False) 1500 self.add_param("SpaceShower:pTmaxMatch", 1, hidden=True, always_write_to_card=False) 1501 self.add_param("SysCalc:tmsList", [10.0,20.0], hidden=True, always_write_to_card=False) 1502 self['SysCalc:tmsList'] = 'auto' 1503 self.add_param("Merging:muFac", 91.188, hidden=True, always_write_to_card=False, 1504 comment='Set factorisation scales of the 2->2 process.') 1505 self.add_param("Merging:applyVeto", False, hidden=True, always_write_to_card=False, 1506 comment='Do veto externally (e.g. in SysCalc).') 1507 self.add_param("Merging:includeWeightInXsection", True, hidden=True, always_write_to_card=False, 1508 comment='If turned off, then the option belows forces PY8 to keep the original weight.') 1509 self.add_param("Merging:muRen", 91.188, hidden=True, always_write_to_card=False, 1510 comment='Set renormalization scales of the 2->2 process.') 1511 self.add_param("Merging:muFacInME", 91.188, hidden=True, always_write_to_card=False, 1512 comment='Set factorisation scales of the 2->2 Matrix Element.') 1513 self.add_param("Merging:muRenInME", 91.188, hidden=True, always_write_to_card=False, 1514 comment='Set renormalization scales of the 2->2 Matrix Element.') 1515 self.add_param("SpaceShower:rapidityOrder", False, hidden=True, always_write_to_card=False) 1516 self.add_param("Merging:nQuarksMerge",4,hidden=True, always_write_to_card=False) 1517 # To be added in subruns for CKKWL 1518 self.add_param("Merging:mayRemoveDecayProducts", False, hidden=True, always_write_to_card=False) 1519 self.add_param("Merging:doKTMerging", False, hidden=True, always_write_to_card=False) 1520 self.add_param("Merging:Dparameter", 0.4, hidden=True, always_write_to_card=False) 1521 self.add_param("Merging:doPTLundMerging", False, hidden=True, always_write_to_card=False) 1522 1523 # Special Pythia8 paremeters useful to simplify the shower. 1524 self.add_param("BeamRemnants:primordialKT", True, hidden=True, always_write_to_card=False, comment="see http://home.thep.lu.se/~torbjorn/pythia82html/BeamRemnants.html") 1525 self.add_param("PartonLevel:Remnants", True, hidden=True, always_write_to_card=False, comment="Master switch for addition of beam remnants. Cannot be used to generate complete events") 1526 self.add_param("Check:event", True, hidden=True, always_write_to_card=False, comment="check physical sanity of the events") 1527 self.add_param("TimeShower:QEDshowerByQ", True, hidden=True, always_write_to_card=False, comment="Allow quarks to radiate photons for FSR, i.e. branchings q -> q gamma") 1528 self.add_param("TimeShower:QEDshowerByL", True, hidden=True, always_write_to_card=False, comment="Allow leptons to radiate photons for FSR, i.e. branchings l -> l gamma") 1529 self.add_param("SpaceShower:QEDshowerByQ", True, hidden=True, always_write_to_card=False, comment="Allow quarks to radiate photons for ISR, i.e. branchings q -> q gamma") 1530 self.add_param("SpaceShower:QEDshowerByL", True, hidden=True, always_write_to_card=False, comment="Allow leptons to radiate photonsfor ISR, i.e. branchings l -> l gamma") 1531 self.add_param("PartonLevel:FSRinResonances", True, hidden=True, always_write_to_card=False, comment="Do not allow shower to run from decay product of unstable particle") 1532 self.add_param("ProcessLevel:resonanceDecays", True, hidden=True, always_write_to_card=False, comment="Do not allow unstable particle to decay.") 1533 1534 # Add parameters controlling the subruns execution flow. 1535 # These parameters should not be part of PY8SubRun daughter. 1536 self.add_default_subruns('parameters')
1537
1538 - def __init__(self, *args, **opts):
1539 # Parameters which are not printed in the card unless they are 1540 # 'user_set' or 'system_set' or part of the 1541 # self.hidden_params_to_always_print set. 1542 self.hidden_param = [] 1543 self.hidden_params_to_always_write = set() 1544 self.visible_params_to_always_write = set() 1545 # List of parameters that should never be written out given the current context. 1546 self.params_to_never_write = set() 1547 1548 # Parameters which have been set by the system (i.e. MG5 itself during 1549 # the regular course of the shower interface) 1550 self.system_set = set() 1551 1552 # Add attributes controlling the subruns execution flow. 1553 # These attributes should not be part of PY8SubRun daughter. 1554 self.add_default_subruns('attributes') 1555 1556 # Parameters which have been set by the 1557 super(PY8Card, self).__init__(*args, **opts)
1558
1559 - def add_param(self, name, value, hidden=False, always_write_to_card=True, 1560 comment=None):
1561 """ add a parameter to the card. value is the default value and 1562 defines the type (int/float/bool/str) of the input. 1563 The option 'hidden' decides whether the parameter should be visible to the user. 1564 The option 'always_write_to_card' decides whether it should 1565 always be printed or only when it is system_set or user_set. 1566 The option 'comment' can be used to specify a comment to write above 1567 hidden parameters. 1568 """ 1569 super(PY8Card, self).add_param(name, value, comment=comment) 1570 name = name.lower() 1571 if hidden: 1572 self.hidden_param.append(name) 1573 if always_write_to_card: 1574 self.hidden_params_to_always_write.add(name) 1575 else: 1576 if always_write_to_card: 1577 self.visible_params_to_always_write.add(name) 1578 if not comment is None: 1579 if not isinstance(comment, str): 1580 raise MadGraph5Error("Option 'comment' must be a string, not"+\ 1581 " '%s'."%str(comment))
1582
1583 - def add_subrun(self, py8_subrun):
1584 """Add a subrun to this PY8 Card.""" 1585 assert(isinstance(py8_subrun,PY8SubRun)) 1586 if py8_subrun['Main:subrun']==-1: 1587 raise MadGraph5Error, "Make sure to correctly set the subrun ID"+\ 1588 " 'Main:subrun' *before* adding it to the PY8 Card." 1589 if py8_subrun['Main:subrun'] in self.subruns: 1590 raise MadGraph5Error, "A subrun with ID '%s'"%py8_subrun['Main:subrun']+\ 1591 " is already present in this PY8 card. Remove it first, or "+\ 1592 " access it directly." 1593 self.subruns[py8_subrun['Main:subrun']] = py8_subrun 1594 if not 'LHEFInputs:nSubruns' in self.user_set: 1595 self['LHEFInputs:nSubruns'] = max(self.subruns.keys())
1596
1597 - def userSet(self, name, value, **opts):
1598 """Set an attribute of this card, following a user_request""" 1599 self.__setitem__(name, value, change_userdefine=True, **opts) 1600 if name.lower() in self.system_set: 1601 self.system_set.remove(name.lower())
1602
1603 - def vetoParamWriteOut(self, name):
1604 """ Forbid the writeout of a specific parameter of this card when the 1605 "write" function will be invoked.""" 1606 self.params_to_never_write.add(name.lower())
1607
1608 - def systemSet(self, name, value, **opts):
1609 """Set an attribute of this card, independently of a specific user 1610 request and only if not already user_set.""" 1611 if name.lower() not in self.user_set: 1612 self.__setitem__(name, value, change_userdefine=False, **opts) 1613 self.system_set.add(name.lower())
1614
1615 - def MadGraphSet(self, name, value, **opts):
1616 """ Sets a card attribute, but only if it is absent or not already 1617 user_set.""" 1618 if name.lower() not in self or name.lower() not in self.user_set: 1619 self.__setitem__(name, value, change_userdefine=False, **opts) 1620 self.system_set.add(name.lower())
1621
1622 - def defaultSet(self, name, value, **opts):
1623 self.__setitem__(name, value, change_userdefine=False, **opts)
1624 1625 @staticmethod
1626 - def pythia8_formatting(value, formatv=None):
1627 """format the variable into pythia8 card convention. 1628 The type is detected by default""" 1629 if not formatv: 1630 if isinstance(value,UnknownType): 1631 formatv = 'unknown' 1632 elif isinstance(value, bool): 1633 formatv = 'bool' 1634 elif isinstance(value, int): 1635 formatv = 'int' 1636 elif isinstance(value, float): 1637 formatv = 'float' 1638 elif isinstance(value, str): 1639 formatv = 'str' 1640 elif isinstance(value, list): 1641 formatv = 'list' 1642 else: 1643 logger.debug("unknow format for pythia8_formatting: %s" , value) 1644 formatv = 'str' 1645 else: 1646 assert formatv 1647 1648 if formatv == 'unknown': 1649 # No formatting then 1650 return str(value) 1651 if formatv == 'bool': 1652 if str(value) in ['1','T','.true.','True','on']: 1653 return 'on' 1654 else: 1655 return 'off' 1656 elif formatv == 'int': 1657 try: 1658 return str(int(value)) 1659 except ValueError: 1660 fl = float(value) 1661 if int(fl) == fl: 1662 return str(int(fl)) 1663 else: 1664 raise 1665 elif formatv == 'float': 1666 return '%.10e' % float(value) 1667 elif formatv == 'shortfloat': 1668 return '%.3f' % float(value) 1669 elif formatv == 'str': 1670 return "%s" % value 1671 elif formatv == 'list': 1672 if len(value) and isinstance(value[0],float): 1673 return ','.join([PY8Card.pythia8_formatting(arg, 'shortfloat') for arg in value]) 1674 else: 1675 return ','.join([PY8Card.pythia8_formatting(arg) for arg in value])
1676 1677
1678 - def write(self, output_file, template, read_subrun=False, 1679 print_only_visible=False, direct_pythia_input=False, add_missing=True):
1680 """ Write the card to output_file using a specific template. 1681 > 'print_only_visible' specifies whether or not the hidden parameters 1682 should be written out if they are in the hidden_params_to_always_write 1683 list and system_set. 1684 > If 'direct_pythia_input' is true, then visible parameters which are not 1685 in the self.visible_params_to_always_write list and are not user_set 1686 or system_set are commented. 1687 > If 'add_missing' is False then parameters that should be written_out but are absent 1688 from the template will not be written out.""" 1689 1690 # First list the visible parameters 1691 visible_param = [p for p in self if p.lower() not in self.hidden_param 1692 or p.lower() in self.user_set] 1693 # Filter against list of parameters vetoed for write-out 1694 visible_param = [p for p in visible_param if p.lower() not in self.params_to_never_write] 1695 1696 # Now the hidden param which must be written out 1697 if print_only_visible: 1698 hidden_output_param = [] 1699 else: 1700 hidden_output_param = [p for p in self if p.lower() in self.hidden_param and 1701 not p.lower() in self.user_set and 1702 (p.lower() in self.hidden_params_to_always_write or 1703 p.lower() in self.system_set)] 1704 # Filter against list of parameters vetoed for write-out 1705 hidden_output_param = [p for p in hidden_output_param if p not in self.params_to_never_write] 1706 1707 if print_only_visible: 1708 subruns = [] 1709 else: 1710 if not read_subrun: 1711 subruns = sorted(self.subruns.keys()) 1712 1713 # Store the subruns to write in a dictionary, with its ID in key 1714 # and the corresponding stringstream in value 1715 subruns_to_write = {} 1716 1717 # Sort these parameters nicely so as to put together parameters 1718 # belonging to the same group (i.e. prefix before the ':' in their name). 1719 def group_params(params): 1720 if len(params)==0: 1721 return [] 1722 groups = {} 1723 for p in params: 1724 try: 1725 groups[':'.join(p.split(':')[:-1])].append(p) 1726 except KeyError: 1727 groups[':'.join(p.split(':')[:-1])] = [p,] 1728 res = sum(groups.values(),[]) 1729 # Make sure 'Main:subrun' appears first 1730 if 'Main:subrun' in res: 1731 res.insert(0,res.pop(res.index('Main:subrun'))) 1732 # Make sure 'LHEFInputs:nSubruns' appears last 1733 if 'LHEFInputs:nSubruns' in res: 1734 res.append(res.pop(res.index('LHEFInputs:nSubruns'))) 1735 return res
1736 1737 visible_param = group_params(visible_param) 1738 hidden_output_param = group_params(hidden_output_param) 1739 1740 # First dump in a temporary_output (might need to have a second pass 1741 # at the very end to update 'LHEFInputs:nSubruns') 1742 output = StringIO.StringIO() 1743 1744 # Setup template from which to read 1745 if isinstance(template, str): 1746 if os.path.isfile(template): 1747 tmpl = open(template, 'r') 1748 elif '\n' in template: 1749 tmpl = StringIO.StringIO(template) 1750 else: 1751 raise Exception, "File input '%s' not found." % file_input 1752 elif template is None: 1753 # Then use a dummy empty StringIO, hence skipping the reading 1754 tmpl = StringIO.StringIO() 1755 elif isinstance(template, (StringIO.StringIO, file)): 1756 tmpl = template 1757 else: 1758 raise MadGraph5Error("Incorrect type for argument 'template': %s"% 1759 template.__class__.__name__) 1760 1761 # Read the template 1762 last_pos = tmpl.tell() 1763 line = tmpl.readline() 1764 started_subrun_reading = False 1765 while line!='': 1766 # Skip comments 1767 if line.strip().startswith('!') or line.strip().startswith('\n'): 1768 output.write(line) 1769 # Proceed to next line 1770 last_pos = tmpl.tell() 1771 line = tmpl.readline() 1772 continue 1773 # Read parameter 1774 try: 1775 param_entry, value_entry = line.split('=') 1776 param = param_entry.strip() 1777 value = value_entry.strip() 1778 except ValueError: 1779 line = line.replace('\n','') 1780 raise MadGraph5Error, "Could not read line '%s' of Pythia8 card."%\ 1781 line 1782 # Read a subrun if detected: 1783 if param=='Main:subrun': 1784 if read_subrun: 1785 if not started_subrun_reading: 1786 # Record that the subrun reading has started and proceed 1787 started_subrun_reading = True 1788 else: 1789 # We encountered the next subrun. rewind last line and exit 1790 tmpl.seek(last_pos) 1791 break 1792 else: 1793 # Start the reading of this subrun 1794 tmpl.seek(last_pos) 1795 subruns_to_write[int(value)] = StringIO.StringIO() 1796 if int(value) in subruns: 1797 self.subruns[int(value)].write(subruns_to_write[int(value)], 1798 tmpl,read_subrun=True) 1799 # Remove this subrun ID from the list 1800 subruns.pop(subruns.index(int(value))) 1801 else: 1802 # Unknow subrun, create a dummy one 1803 DummySubrun=PY8SubRun() 1804 # Remove all of its variables (so that nothing is overwritten) 1805 DummySubrun.clear() 1806 DummySubrun.write(subruns_to_write[int(value)], 1807 tmpl, read_subrun=True, 1808 print_only_visible=print_only_visible, 1809 direct_pythia_input=direct_pythia_input) 1810 1811 logger.info('Adding new unknown subrun with ID %d.'% 1812 int(value)) 1813 # Proceed to next line 1814 last_pos = tmpl.tell() 1815 line = tmpl.readline() 1816 continue 1817 1818 # Change parameters which must be output 1819 if param in visible_param: 1820 new_value = PY8Card.pythia8_formatting(self[param]) 1821 visible_param.pop(visible_param.index(param)) 1822 elif param in hidden_output_param: 1823 new_value = PY8Card.pythia8_formatting(self[param]) 1824 hidden_output_param.pop(hidden_output_param.index(param)) 1825 else: 1826 # Just copy parameters which don't need to be specified 1827 if param.lower() not in self.params_to_never_write: 1828 output.write(line) 1829 else: 1830 output.write('! The following parameter was forced to be commented out by MG5aMC.\n') 1831 output.write('! %s'%line) 1832 # Proceed to next line 1833 last_pos = tmpl.tell() 1834 line = tmpl.readline() 1835 continue 1836 1837 # Substitute the value. 1838 # If it is directly the pytia input, then don't write the param if it 1839 # is not in the list of visible_params_to_always_write and was 1840 # not user_set or system_set 1841 if ((not direct_pythia_input) or 1842 (param.lower() in self.visible_params_to_always_write) or 1843 (param.lower() in self.user_set) or 1844 (param.lower() in self.system_set)): 1845 template = '%s=%s' 1846 else: 1847 # These are parameters that the user can edit in AskEditCards 1848 # but if neither the user nor the system edited them, 1849 # then they shouldn't be passed to Pythia 1850 template = '!%s=%s' 1851 1852 output.write(template%(param_entry, 1853 value_entry.replace(value,new_value))) 1854 1855 # Proceed to next line 1856 last_pos = tmpl.tell() 1857 line = tmpl.readline() 1858 1859 # If add_missing is False, make sure to empty the list of remaining parameters 1860 if not add_missing: 1861 visible_param = [] 1862 hidden_output_param = [] 1863 1864 # Now output the missing parameters. Warn about visible ones. 1865 if len(visible_param)>0 and not template is None: 1866 output.write( 1867 """! 1868 ! Additional general parameters%s. 1869 ! 1870 """%(' for subrun %d'%self['Main:subrun'] if 'Main:subrun' in self else '')) 1871 for param in visible_param: 1872 value = PY8Card.pythia8_formatting(self[param]) 1873 output.write('%s=%s\n'%(param,value)) 1874 if template is None: 1875 if param=='Main:subrun': 1876 output.write( 1877 """! 1878 ! Definition of subrun %d 1879 ! 1880 """%self['Main:subrun']) 1881 elif param.lower() not in self.hidden_param: 1882 logger.debug('Adding parameter %s (missing in the template) to current '+\ 1883 'pythia8 card (with value %s)',param, value) 1884 1885 if len(hidden_output_param)>0 and not template is None: 1886 output.write( 1887 """! 1888 ! Additional technical parameters%s set by MG5_aMC. 1889 ! 1890 """%(' for subrun %d'%self['Main:subrun'] if 'Main:subrun' in self else '')) 1891 for param in hidden_output_param: 1892 if param.lower() in self.comments: 1893 comment = '\n'.join('! %s'%c for c in 1894 self.comments[param.lower()].split('\n')) 1895 output.write(comment+'\n') 1896 output.write('%s=%s\n'%(param,PY8Card.pythia8_formatting(self[param]))) 1897 1898 # Don't close the file if we were reading a subrun, but simply write 1899 # output and return now 1900 if read_subrun: 1901 output_file.write(output.getvalue()) 1902 return 1903 1904 # Now add subruns not present in the template 1905 for subrunID in subruns: 1906 new_subrun = StringIO.StringIO() 1907 self.subruns[subrunID].write(new_subrun,None,read_subrun=True) 1908 subruns_to_write[subrunID] = new_subrun 1909 1910 # Add all subruns to the output, in the right order 1911 for subrunID in sorted(subruns_to_write): 1912 output.write(subruns_to_write[subrunID].getvalue()) 1913 1914 # If 'LHEFInputs:nSubruns' is not user_set, then make sure it is 1915 # updated at least larger or equal to the maximum SubRunID 1916 if 'LHEFInputs:nSubruns'.lower() not in self.user_set and \ 1917 len(subruns_to_write)>0 and self['LHEFInputs:nSubruns']<\ 1918 max(subruns_to_write.keys()): 1919 logger.info("Updating PY8 parameter 'LHEFInputs:nSubruns' to "+ 1920 "%d so as to cover all defined subruns."%max(subruns_to_write.keys())) 1921 self['LHEFInputs:nSubruns'] = max(subruns_to_write.keys()) 1922 output = StringIO.StringIO() 1923 self.write(output,template,print_only_visible=print_only_visible) 1924 1925 # Write output 1926 if isinstance(output_file, str): 1927 out = open(output_file,'w') 1928 out.write(output.getvalue()) 1929 out.close() 1930 else: 1931 output_file.write(output.getvalue())
1932
1933 - def read(self, file_input, read_subrun=False, setter='default'):
1934 """Read the input file, this can be a path to a file, 1935 a file object, a str with the content of the file. 1936 The setter option choses the authority that sets potential 1937 modified/new parameters. It can be either: 1938 'default' or 'user' or 'system'""" 1939 if isinstance(file_input, str): 1940 if "\n" in file_input: 1941 finput = StringIO.StringIO(file_input) 1942 elif os.path.isfile(file_input): 1943 finput = open(file_input) 1944 else: 1945 raise Exception, "File input '%s' not found." % file_input 1946 elif isinstance(file_input, (StringIO.StringIO, file)): 1947 finput = file_input 1948 else: 1949 raise MadGraph5Error("Incorrect type for argument 'file_input': %s"% 1950 file_inp .__class__.__name__) 1951 1952 # Read the template 1953 last_pos = finput.tell() 1954 line = finput.readline() 1955 started_subrun_reading = False 1956 while line!='': 1957 # Skip comments 1958 if line.strip().startswith('!') or line.strip()=='': 1959 # proceed to next line 1960 last_pos = finput.tell() 1961 line = finput.readline() 1962 continue 1963 # Read parameter 1964 try: 1965 param, value = line.split('=',1) 1966 param = param.strip() 1967 value = value.strip() 1968 except ValueError: 1969 line = line.replace('\n','') 1970 raise MadGraph5Error, "Could not read line '%s' of Pythia8 card."%\ 1971 line 1972 # Read a subrun if detected: 1973 if param=='Main:subrun': 1974 if read_subrun: 1975 if not started_subrun_reading: 1976 # Record that the subrun reading has started and proceed 1977 started_subrun_reading = True 1978 else: 1979 # We encountered the next subrun. rewind last line and exit 1980 finput.seek(last_pos) 1981 return 1982 else: 1983 # Start the reading of this subrun 1984 finput.seek(last_pos) 1985 if int(value) in self.subruns: 1986 self.subruns[int(value)].read(finput,read_subrun=True, 1987 setter=setter) 1988 else: 1989 # Unknow subrun, create a dummy one 1990 NewSubrun=PY8SubRun() 1991 NewSubrun.read(finput,read_subrun=True, setter=setter) 1992 self.add_subrun(NewSubrun) 1993 1994 # proceed to next line 1995 last_pos = finput.tell() 1996 line = finput.readline() 1997 continue 1998 1999 # Read parameter. The case of a parameter not defined in the card is 2000 # handled directly in ConfigFile. 2001 2002 # Use the appropriate authority to set the new/changed variable 2003 if setter == 'user': 2004 self.userSet(param,value) 2005 elif setter == 'system': 2006 self.systemSet(param,value) 2007 else: 2008 self.defaultSet(param,value) 2009 2010 # proceed to next line 2011 last_pos = finput.tell() 2012 line = finput.readline()
2013
2014 -class PY8SubRun(PY8Card):
2015 """ Class to characterize a specific PY8 card subrun section. """ 2016
2017 - def add_default_subruns(self, type):
2018 """ Overloading of the homonym function called in the __init__ of PY8Card. 2019 The initialization of the self.subruns attribute should of course not 2020 be performed in PY8SubRun.""" 2021 pass
2022
2023 - def __init__(self, *args, **opts):
2024 """ Initialize a subrun """ 2025 2026 # Force user to set it manually. 2027 subrunID = -1 2028 if 'subrun_id' in opts: 2029 subrunID = opts.pop('subrun_id') 2030 2031 super(PY8SubRun, self).__init__(*args, **opts) 2032 self['Main:subrun']=subrunID
2033
2034 - def default_setup(self):
2035 """Sets up the list of available PY8SubRun parameters.""" 2036 2037 # Add all default PY8Card parameters 2038 super(PY8SubRun, self).default_setup() 2039 # Make sure they are all hidden 2040 self.hidden_param = [k.lower() for k in self.keys()] 2041 self.hidden_params_to_always_write = set() 2042 self.visible_params_to_always_write = set() 2043 2044 # Now add Main:subrun and Beams:LHEF. They are not hidden. 2045 self.add_param("Main:subrun", -1) 2046 self.add_param("Beams:LHEF", "events.lhe.gz")
2047
2048 -class RunCard(ConfigFile):
2049 2050 filename = 'run_card' 2051
2052 - def __new__(cls, finput=None, **opt):
2053 if cls is RunCard: 2054 if not finput: 2055 target_class = RunCardLO 2056 elif isinstance(finput, cls): 2057 target_class = finput.__class__ 2058 elif isinstance(finput, str): 2059 if '\n' not in finput: 2060 finput = open(finput).read() 2061 if 'req_acc_FO' in finput: 2062 target_class = RunCardNLO 2063 else: 2064 target_class = RunCardLO 2065 else: 2066 return None 2067 return super(RunCard, cls).__new__(target_class, finput, **opt) 2068 else: 2069 return super(RunCard, cls).__new__(cls, finput, **opt)
2070
2071 - def __init__(self, *args, **opts):
2072 2073 # The following parameter are updated in the defaultsetup stage. 2074 2075 #parameter for which no warning should be raised if not define 2076 self.hidden_param = [] 2077 # in which include file the parameer should be written 2078 self.includepath = collections.defaultdict(list) 2079 #some parameter have different name in fortran code 2080 self.fortran_name = {} 2081 #parameter which are not supported anymore. (no action on the code) 2082 self.legacy_parameter = {} 2083 #a list with all the cuts variable 2084 self.cuts_parameter = [] 2085 # parameter added where legacy requires an older value. 2086 self.system_default = {} 2087 2088 2089 2090 2091 super(RunCard, self).__init__(*args, **opts)
2092
2093 - def add_param(self, name, value, fortran_name=None, include=True, 2094 hidden=False, legacy=False, cut=False, system=False, sys_default=None, 2095 **opts):
2096 """ add a parameter to the card. value is the default value and 2097 defines the type (int/float/bool/str) of the input. 2098 fortran_name defines what is the associate name in the f77 code 2099 include defines if we have to put the value in the include file 2100 hidden defines if the parameter is expected to be define by the user. 2101 legacy:Parameter which is not used anymore (raise a warning if not default) 2102 cut: defines the list of cut parameter to allow to set them all to off. 2103 sys_default: default used if the parameter is not in the card 2104 """ 2105 2106 super(RunCard, self).add_param(name, value, system=system,**opts) 2107 name = name.lower() 2108 if fortran_name: 2109 self.fortran_name[name] = fortran_name 2110 if legacy: 2111 self.legacy_parameter[name] = value 2112 include = False 2113 if include is True: 2114 self.includepath[True].append(name) 2115 elif include: 2116 self.includepath[include].append(name) 2117 if hidden or system: 2118 self.hidden_param.append(name) 2119 if cut: 2120 self.cuts_parameter.append(name) 2121 if sys_default is not None: 2122 self.system_default[name] = sys_default
2123 2124 2125
2126 - def read(self, finput, consistency=True):
2127 """Read the input file, this can be a path to a file, 2128 a file object, a str with the content of the file.""" 2129 2130 if isinstance(finput, str): 2131 if "\n" in finput: 2132 finput = finput.split('\n') 2133 elif os.path.isfile(finput): 2134 finput = open(finput) 2135 else: 2136 raise Exception, "No such file %s" % finput 2137 2138 for line in finput: 2139 line = line.split('#')[0] 2140 line = line.split('!')[0] 2141 line = line.rsplit('=',1) 2142 if len(line) != 2: 2143 continue 2144 value, name = line 2145 name = name.lower().strip() 2146 if name not in self and ('min' in name or 'max' in name): 2147 #looks like an entry added by one user -> add it nicely 2148 self.add_param(name, float(value), hidden=True, cut=True) 2149 else: 2150 self.set( name, value, user=True) 2151 # parameter not set in the run_card can be set to compatiblity value 2152 if consistency: 2153 try: 2154 self.check_validity() 2155 except InvalidRunCard, error: 2156 if consistency == 'warning': 2157 logger.warning(str(error)) 2158 else: 2159 raise
2160 2161
2162 - def write(self, output_file, template=None, python_template=False):
2163 """Write the run_card in output_file according to template 2164 (a path to a valid run_card)""" 2165 2166 to_write = set(self.user_set) 2167 if not template: 2168 raise Exception 2169 2170 if python_template and not to_write: 2171 if not self.list_parameter: 2172 text = file(template,'r').read() % self 2173 else: 2174 data = dict(self) 2175 for name in self.list_parameter: 2176 data[name] = ', '.join(str(v) for v in data[name]) 2177 text = file(template,'r').read() % data 2178 else: 2179 text = "" 2180 for line in file(template,'r'): 2181 nline = line.split('#')[0] 2182 nline = nline.split('!')[0] 2183 comment = line[len(nline):] 2184 nline = nline.split('=') 2185 if len(nline) != 2: 2186 text += line 2187 elif nline[1].strip() in self: 2188 name = nline[1].strip().lower() 2189 value = self[name] 2190 if name in self.list_parameter: 2191 value = ', '.join([str(v) for v in value]) 2192 if python_template: 2193 text += line % {nline[1].strip():value, name:value} 2194 else: 2195 if not comment or comment[-1]!='\n': 2196 endline = '\n' 2197 else: 2198 endline = '' 2199 text += ' %s\t= %s %s%s' % (value, name, comment, endline) 2200 2201 if name.lower() in to_write: 2202 to_write.remove(nline[1].strip().lower()) 2203 else: 2204 logger.info('Adding missing parameter %s to current %s (with default value)', 2205 (name, self.filename)) 2206 text += line 2207 2208 if to_write: 2209 text+="""#********************************************************************* 2210 # Additional parameter 2211 #********************************************************************* 2212 """ 2213 2214 for key in to_write: 2215 text += ' %s\t= %s # %s\n' % (self[key], key, 'hidden parameter') 2216 2217 if isinstance(output_file, str): 2218 fsock = open(output_file,'w') 2219 fsock.write(text) 2220 fsock.close() 2221 else: 2222 output_file.write(text)
2223 2224
2225 - def get_default(self, name, default=None, log_level=None):
2226 """return self[name] if exist otherwise default. log control if we 2227 put a warning or not if we use the default value""" 2228 2229 lower_name = name.lower() 2230 if lower_name not in self.user_set: 2231 if log_level is None: 2232 if lower_name in self.system_only: 2233 log_level = 5 2234 elif lower_name in self.auto_set: 2235 log_level = 5 2236 elif lower_name in self.hidden_param: 2237 log_level = 10 2238 else: 2239 log_level = 20 2240 if not default: 2241 default = dict.__getitem__(self, name.lower()) 2242 logger.log(log_level, '%s missed argument %s. Takes default: %s' 2243 % (self.filename, name, default)) 2244 self[name] = default 2245 return default 2246 else: 2247 return self[name]
2248 2249 @staticmethod
2250 - def format(formatv, value):
2251 """for retro compatibility""" 2252 2253 logger.debug("please use f77_formatting instead of format") 2254 return self.f77_formatting(value, formatv=formatv)
2255 2256 @staticmethod
2257 - def f77_formatting(value, formatv=None):
2258 """format the variable into fortran. The type is detected by default""" 2259 2260 if not formatv: 2261 if isinstance(value, bool): 2262 formatv = 'bool' 2263 elif isinstance(value, int): 2264 formatv = 'int' 2265 elif isinstance(value, float): 2266 formatv = 'float' 2267 elif isinstance(value, str): 2268 formatv = 'str' 2269 else: 2270 logger.debug("unknow format for f77_formatting: %s" , str(value)) 2271 formatv = 'str' 2272 else: 2273 assert formatv 2274 2275 if formatv == 'bool': 2276 if str(value) in ['1','T','.true.','True']: 2277 return '.true.' 2278 else: 2279 return '.false.' 2280 2281 elif formatv == 'int': 2282 try: 2283 return str(int(value)) 2284 except ValueError: 2285 fl = float(value) 2286 if int(fl) == fl: 2287 return str(int(fl)) 2288 else: 2289 raise 2290 2291 elif formatv == 'float': 2292 if isinstance(value, str): 2293 value = value.replace('d','e') 2294 return ('%.10e' % float(value)).replace('e','d') 2295 2296 elif formatv == 'str': 2297 # Check if it is a list 2298 if value.strip().startswith('[') and value.strip().endswith(']'): 2299 elements = (value.strip()[1:-1]).split() 2300 return ['_length = %d'%len(elements)]+\ 2301 ['(%d) = %s'%(i+1, elem.strip()) for i, elem in \ 2302 enumerate(elements)] 2303 else: 2304 return "'%s'" % value
2305 2306
2307 - def check_validity(self):
2308 """check that parameter missing in the card are set to the expected value""" 2309 2310 for name, value in self.system_default.items(): 2311 self.set(name, value, changeifuserset=False)
2312 2313 default_include_file = 'run_card.inc' 2314
2315 - def write_include_file(self, output_dir):
2316 """Write the various include file in output_dir. 2317 The entry True of self.includepath will be written in run_card.inc 2318 The entry False will not be written anywhere""" 2319 2320 # ensure that all parameter are coherent and fix those if needed 2321 self.check_validity() 2322 2323 for incname in self.includepath: 2324 if incname is True: 2325 pathinc = self.default_include_file 2326 else: 2327 pathinc = incname 2328 2329 fsock = file_writers.FortranWriter(pjoin(output_dir,pathinc)) 2330 for key in self.includepath[incname]: 2331 #define the fortran name 2332 if key in self.fortran_name: 2333 fortran_name = self.fortran_name[key] 2334 else: 2335 fortran_name = key 2336 2337 #get the value with warning if the user didn't set it 2338 value = self.get_default(key) 2339 # Special treatment for strings containing a list of 2340 # strings. Convert it to a list of strings 2341 if isinstance(value, list): 2342 # in case of a list, add the length of the list as 0th 2343 # element in fortran. Only in case of integer or float 2344 # list (not for bool nor string) 2345 if isinstance(value[0], bool): 2346 pass 2347 elif isinstance(value[0], int): 2348 line = '%s(%s) = %s \n' % (fortran_name, 0, self.f77_formatting(len(value))) 2349 fsock.writelines(line) 2350 elif isinstance(value[0], float): 2351 line = '%s(%s) = %s \n' % (fortran_name, 0, self.f77_formatting(float(len(value)))) 2352 fsock.writelines(line) 2353 # output the rest of the list in fortran 2354 for i,v in enumerate(value): 2355 line = '%s(%s) = %s \n' % (fortran_name, i+1, self.f77_formatting(v)) 2356 fsock.writelines(line) 2357 elif isinstance(value, dict): 2358 for fortran_name, onevalue in value.items(): 2359 line = '%s = %s \n' % (fortran_name, self.f77_formatting(onevalue)) 2360 fsock.writelines(line) 2361 else: 2362 line = '%s = %s \n' % (fortran_name, self.f77_formatting(value)) 2363 fsock.writelines(line) 2364 fsock.close()
2365 2366
2368 """return a dictionary with the information needed to write 2369 the first line of the <init> block of the lhe file.""" 2370 2371 output = {} 2372 2373 def get_idbmup(lpp): 2374 """return the particle colliding pdg code""" 2375 if lpp in (1,2, -1,-2): 2376 return math.copysign(2212, lpp) 2377 elif lpp in (3,-3): 2378 return math.copysign(11, lpp) 2379 elif lpp == 0: 2380 #logger.critical("Fail to write correct idbmup in the lhe file. Please correct those by hand") 2381 return 0 2382 else: 2383 return lpp
2384 2385 2386 output["idbmup1"] = get_idbmup(self['lpp1']) 2387 output["idbmup2"] = get_idbmup(self['lpp2']) 2388 output["ebmup1"] = self["ebeam1"] 2389 output["ebmup2"] = self["ebeam2"] 2390 output["pdfgup1"] = 0 2391 output["pdfgup2"] = 0 2392 output["pdfsup1"] = self.get_pdf_id(self["pdlabel"]) 2393 output["pdfsup2"] = self.get_pdf_id(self["pdlabel"]) 2394 return output
2395
2396 - def get_pdf_id(self, pdf):
2397 if pdf == "lhapdf": 2398 lhaid = self["lhaid"] 2399 if isinstance(lhaid, list): 2400 return lhaid[0] 2401 else: 2402 return lhaid 2403 else: 2404 return {'none': 0, 'mrs02nl':20250, 'mrs02nn':20270, 'cteq4_m': 19150, 2405 'cteq4_l':19170, 'cteq4_d':19160, 'cteq5_m':19050, 2406 'cteq5_d':19060,'cteq5_l':19070,'cteq5m1':19051, 2407 'cteq6_m':10000,'cteq6_l':10041,'cteq6l1':10042, 2408 'nn23lo':246800,'nn23lo1':247000,'nn23nlo':244800 2409 }[pdf]
2410
2411 - def get_lhapdf_id(self):
2412 return self.get_pdf_id(self['pdlabel'])
2413
2414 - def remove_all_cut(self):
2415 """remove all the cut""" 2416 2417 for name in self.cuts_parameter: 2418 targettype = type(self[name]) 2419 if targettype == bool: 2420 self[name] = False 2421 elif 'min' in name: 2422 self[name] = 0 2423 elif 'max' in name: 2424 self[name] = -1 2425 elif 'eta' in name: 2426 self[name] = -1 2427 else: 2428 self[name] = 0 2429
2430 -class RunCardLO(RunCard):
2431 """an object to handle in a nice way the run_card information""" 2432
2433 - def default_setup(self):
2434 """default value for the run_card.dat""" 2435 2436 self.add_param("run_tag", "tag_1", include=False) 2437 self.add_param("gridpack", False) 2438 self.add_param("time_of_flight", -1.0, include=False, hidden=True) 2439 self.add_param("nevents", 10000) 2440 self.add_param("iseed", 0) 2441 self.add_param("lpp1", 1, fortran_name="lpp(1)") 2442 self.add_param("lpp2", 1, fortran_name="lpp(2)") 2443 self.add_param("ebeam1", 6500.0, fortran_name="ebeam(1)") 2444 self.add_param("ebeam2", 6500.0, fortran_name="ebeam(2)") 2445 self.add_param("polbeam1", 0.0, fortran_name="pb1") 2446 self.add_param("polbeam2", 0.0, fortran_name="pb2") 2447 self.add_param("pdlabel", "nn23lo1") 2448 self.add_param("lhaid", 230000, hidden=True) 2449 self.add_param("fixed_ren_scale", False) 2450 self.add_param("fixed_fac_scale", False) 2451 self.add_param("scale", 91.1880) 2452 self.add_param("dsqrt_q2fact1", 91.1880, fortran_name="sf1") 2453 self.add_param("dsqrt_q2fact2", 91.1880, fortran_name="sf2") 2454 self.add_param("dynamical_scale_choice", -1) 2455 2456 # Bias module options 2457 self.add_param("bias_module", 'None', include=False) 2458 self.add_param('bias_parameters', {'__type__':1.0}, include='BIAS/bias.inc') 2459 2460 #matching 2461 self.add_param("scalefact", 1.0) 2462 self.add_param("ickkw", 0, comment="\'0\' for standard fixed order computation.\n\'1\' for MLM merging activates alphas and pdf re-weighting according to a kt clustering of the QCD radiation.") 2463 self.add_param("highestmult", 1, fortran_name="nhmult", hidden=True) 2464 self.add_param("ktscheme", 1, hidden=True) 2465 self.add_param("alpsfact", 1.0) 2466 self.add_param("chcluster", False, hidden=True) 2467 self.add_param("pdfwgt", True, hidden=True) 2468 self.add_param("asrwgtflavor", 5) 2469 self.add_param("clusinfo", True) 2470 self.add_param("lhe_version", 3.0) 2471 self.add_param("event_norm", "average", include=False, sys_default='sum') 2472 #cut 2473 self.add_param("auto_ptj_mjj", False) 2474 self.add_param("bwcutoff", 15.0) 2475 self.add_param("cut_decays", False) 2476 self.add_param("nhel", 0, include=False) 2477 #pt cut 2478 self.add_param("ptj", 20.0, cut=True) 2479 self.add_param("ptb", 0.0, cut=True) 2480 self.add_param("pta", 10.0, cut=True) 2481 self.add_param("ptl", 10.0, cut=True) 2482 self.add_param("misset", 0.0, cut=True) 2483 self.add_param("ptheavy", 0.0, cut=True, comment='this cut apply on particle heavier than 10 GeV') 2484 self.add_param("ptonium", 1.0, legacy=True) 2485 self.add_param("ptjmax", -1.0, cut=True) 2486 self.add_param("ptbmax", -1.0, cut=True) 2487 self.add_param("ptamax", -1.0, cut=True) 2488 self.add_param("ptlmax", -1.0, cut=True) 2489 self.add_param("missetmax", -1.0, cut=True) 2490 # E cut 2491 self.add_param("ej", 0.0, cut=True) 2492 self.add_param("eb", 0.0, cut=True) 2493 self.add_param("ea", 0.0, cut=True) 2494 self.add_param("el", 0.0, cut=True) 2495 self.add_param("ejmax", -1.0, cut=True) 2496 self.add_param("ebmax", -1.0, cut=True) 2497 self.add_param("eamax", -1.0, cut=True) 2498 self.add_param("elmax", -1.0, cut=True) 2499 # Eta cut 2500 self.add_param("etaj", 5.0, cut=True) 2501 self.add_param("etab", -1.0, cut=True) 2502 self.add_param("etaa", 2.5, cut=True) 2503 self.add_param("etal", 2.5, cut=True) 2504 self.add_param("etaonium", 0.6, legacy=True) 2505 self.add_param("etajmin", 0.0, cut=True) 2506 self.add_param("etabmin", 0.0, cut=True) 2507 self.add_param("etaamin", 0.0, cut=True) 2508 self.add_param("etalmin", 0.0, cut=True) 2509 # DRJJ 2510 self.add_param("drjj", 0.4, cut=True) 2511 self.add_param("drbb", 0.0, cut=True) 2512 self.add_param("drll", 0.4, cut=True) 2513 self.add_param("draa", 0.4, cut=True) 2514 self.add_param("drbj", 0.0, cut=True) 2515 self.add_param("draj", 0.4, cut=True) 2516 self.add_param("drjl", 0.4, cut=True) 2517 self.add_param("drab", 0.0, cut=True) 2518 self.add_param("drbl", 0.0, cut=True) 2519 self.add_param("dral", 0.4, cut=True) 2520 self.add_param("drjjmax", -1.0, cut=True) 2521 self.add_param("drbbmax", -1.0, cut=True) 2522 self.add_param("drllmax", -1.0, cut=True) 2523 self.add_param("draamax", -1.0, cut=True) 2524 self.add_param("drbjmax", -1.0, cut=True) 2525 self.add_param("drajmax", -1.0, cut=True) 2526 self.add_param("drjlmax", -1.0, cut=True) 2527 self.add_param("drabmax", -1.0, cut=True) 2528 self.add_param("drblmax", -1.0, cut=True) 2529 self.add_param("dralmax", -1.0, cut=True) 2530 # invariant mass 2531 self.add_param("mmjj", 0.0, cut=True) 2532 self.add_param("mmbb", 0.0, cut=True) 2533 self.add_param("mmaa", 0.0, cut=True) 2534 self.add_param("mmll", 0.0, cut=True) 2535 self.add_param("mmjjmax", -1.0, cut=True) 2536 self.add_param("mmbbmax", -1.0, cut=True) 2537 self.add_param("mmaamax", -1.0, cut=True) 2538 self.add_param("mmllmax", -1.0, cut=True) 2539 self.add_param("mmnl", 0.0, cut=True) 2540 self.add_param("mmnlmax", -1.0, cut=True) 2541 #minimum/max pt for sum of leptons 2542 self.add_param("ptllmin", 0.0, cut=True) 2543 self.add_param("ptllmax", -1.0, cut=True) 2544 self.add_param("xptj", 0.0, cut=True) 2545 self.add_param("xptb", 0.0, cut=True) 2546 self.add_param("xpta", 0.0, cut=True) 2547 self.add_param("xptl", 0.0, cut=True) 2548 # ordered pt jet 2549 self.add_param("ptj1min", 0.0, cut=True) 2550 self.add_param("ptj1max", -1.0, cut=True) 2551 self.add_param("ptj2min", 0.0, cut=True) 2552 self.add_param("ptj2max", -1.0, cut=True) 2553 self.add_param("ptj3min", 0.0, cut=True) 2554 self.add_param("ptj3max", -1.0, cut=True) 2555 self.add_param("ptj4min", 0.0, cut=True) 2556 self.add_param("ptj4max", -1.0, cut=True) 2557 self.add_param("cutuse", 0, cut=True) 2558 # ordered pt lepton 2559 self.add_param("ptl1min", 0.0, cut=True) 2560 self.add_param("ptl1max", -1.0, cut=True) 2561 self.add_param("ptl2min", 0.0, cut=True) 2562 self.add_param("ptl2max", -1.0, cut=True) 2563 self.add_param("ptl3min", 0.0, cut=True) 2564 self.add_param("ptl3max", -1.0, cut=True) 2565 self.add_param("ptl4min", 0.0, cut=True) 2566 self.add_param("ptl4max", -1.0, cut=True) 2567 # Ht sum of jets 2568 self.add_param("htjmin", 0.0, cut=True) 2569 self.add_param("htjmax", -1.0, cut=True) 2570 self.add_param("ihtmin", 0.0, cut=True) 2571 self.add_param("ihtmax", -1.0, cut=True) 2572 self.add_param("ht2min", 0.0, cut=True) 2573 self.add_param("ht3min", 0.0, cut=True) 2574 self.add_param("ht4min", 0.0, cut=True) 2575 self.add_param("ht2max", -1.0, cut=True) 2576 self.add_param("ht3max", -1.0, cut=True) 2577 self.add_param("ht4max", -1.0, cut=True) 2578 # photon isolation 2579 self.add_param("ptgmin", 0.0, cut=True) 2580 self.add_param("r0gamma", 0.4) 2581 self.add_param("xn", 1.0) 2582 self.add_param("epsgamma", 1.0) 2583 self.add_param("isoem", True) 2584 self.add_param("xetamin", 0.0, cut=True) 2585 self.add_param("deltaeta", 0.0, cut=True) 2586 self.add_param("ktdurham", -1.0, fortran_name="kt_durham", cut=True) 2587 self.add_param("dparameter", 0.4, fortran_name="d_parameter", cut=True) 2588 self.add_param("ptlund", -1.0, fortran_name="pt_lund", cut=True) 2589 self.add_param("pdgs_for_merging_cut", [21, 1, 2, 3, 4, 5, 6]) 2590 self.add_param("maxjetflavor", 4) 2591 self.add_param("xqcut", 0.0, cut=True) 2592 self.add_param("use_syst", True) 2593 self.add_param('systematics_program', 'auto', include=False, hidden=True, comment='Choose which program to use for systematics computation: none, systematics, syscalc') 2594 self.add_param('systematics_arguments', [''], include=False, hidden=True, comment='Choose the argment to pass to the systematics command. like --mur=0.25,1,4. Look at the help of the systematics function for more details.') 2595 2596 self.add_param("sys_scalefact", "0.5 1 2", include=False) 2597 self.add_param("sys_alpsfact", "None", include=False) 2598 self.add_param("sys_matchscale", "auto", include=False) 2599 self.add_param("sys_pdf", "NNPDF23_lo_as_0130_qed", include=False) 2600 self.add_param("sys_scalecorrelation", -1, include=False) 2601 2602 #parameter not in the run_card by default 2603 self.add_param('gridrun', False, hidden=True) 2604 self.add_param('fixed_couplings', True, hidden=True) 2605 self.add_param('mc_grouped_subproc', True, hidden=True) 2606 self.add_param('xmtcentral', 0.0, hidden=True, fortran_name="xmtc") 2607 self.add_param('d', 1.0, hidden=True) 2608 self.add_param('gseed', 0, hidden=True, include=False) 2609 self.add_param('issgridfile', '', hidden=True) 2610 #job handling of the survey/ refine 2611 self.add_param('job_strategy', 0, hidden=True, include=False) 2612 self.add_param('survey_splitting', -1, hidden=True, include=False) 2613 self.add_param('refine_evt_by_job', -1, hidden=True, include=False)
2614 # Specify what particle IDs to use for the CKKWL merging cut ktdurham 2615
2616 - def check_validity(self):
2617 """ """ 2618 2619 super(RunCardLO, self).check_validity() 2620 2621 #Make sure that nhel is only either 0 (i.e. no MC over hel) or 2622 #1 (MC over hel with importance sampling). In particular, it can 2623 #no longer be > 1. 2624 if 'nhel' not in self.user_set: 2625 raise InvalidRunCard, "Parameter nhel is not defined in the run_card." 2626 if self['nhel'] not in [1,0]: 2627 raise InvalidRunCard, "Parameter nhel can only be '0' or '1', "+\ 2628 "not %s." % self['nhel'] 2629 if int(self['maxjetflavor']) > 6: 2630 raise InvalidRunCard, 'maxjetflavor should be lower than 5! (6 is partly supported)' 2631 2632 if len(self['pdgs_for_merging_cut']) > 1000: 2633 raise InvalidRunCard, "The number of elements in "+\ 2634 "'pdgs_for_merging_cut' should not exceed 1000." 2635 2636 # some cut need to be deactivated in presence of isolation 2637 if self['ptgmin'] > 0: 2638 if self['pta'] > 0: 2639 logger.warning('pta cut discarded since photon isolation is used') 2640 self['pta'] = 0.0 2641 if self['draj'] > 0: 2642 logger.warning('draj cut discarded since photon isolation is used') 2643 self['draj'] = 0.0 2644 2645 # special treatment for gridpack use the gseed instead of the iseed 2646 if self['gridrun']: 2647 self['iseed'] = self['gseed'] 2648 2649 #Some parameter need to be fixed when using syscalc 2650 if self['use_syst']: 2651 if self['scalefact'] != 1.0: 2652 logger.warning('Since use_syst=T, We change the value of \'scalefact\' to 1') 2653 self['scalefact'] = 1.0 2654 2655 # CKKW Treatment 2656 if self['ickkw'] > 0: 2657 if self['ickkw'] != 1: 2658 logger.critical('ickkw >1 is pure alpha and only partly implemented.') 2659 import madgraph.interface.extended_cmd as basic_cmd 2660 answer = basic_cmd.smart_input('Do you really want to continue', allow_arg=['y','n'], default='n') 2661 if answer !='y': 2662 raise InvalidRunCard, 'ickkw>1 is still in alpha' 2663 if self['use_syst']: 2664 # some additional parameter need to be fixed for Syscalc + matching 2665 if self['alpsfact'] != 1.0: 2666 logger.warning('Since use_syst=T, We change the value of \'alpsfact\' to 1') 2667 self['alpsfact'] =1.0 2668 if self['maxjetflavor'] == 6: 2669 raise InvalidRunCard, 'maxjetflavor at 6 is NOT supported for matching!' 2670 if self['ickkw'] == 2: 2671 # add warning if ckkw selected but the associate parameter are empty 2672 self.get_default('highestmult', log_level=20) 2673 self.get_default('issgridfile', 'issudgrid.dat', log_level=20) 2674 if self['xqcut'] > 0: 2675 if self['ickkw'] == 0: 2676 logger.error('xqcut>0 but ickkw=0. Potentially not fully consistent setup. Be carefull') 2677 import time 2678 time.sleep(5) 2679 if self['drjj'] != 0: 2680 logger.warning('Since icckw>0, We change the value of \'drjj\' to 0') 2681 self['drjj'] = 0 2682 if self['drjl'] != 0: 2683 logger.warning('Since icckw>0, We change the value of \'drjl\' to 0') 2684 self['drjl'] = 0 2685 if not self['auto_ptj_mjj']: 2686 if self['mmjj'] > self['xqcut']: 2687 logger.warning('mmjj > xqcut (and auto_ptj_mjj = F). MMJJ set to 0') 2688 self['mmjj'] = 0.0 2689 2690 2691 2692 # check validity of the pdf set 2693 possible_set = ['lhapdf', 'mrs02nl','mrs02nn', 2694 'cteq4_m', 'cteq4_l','cteq4_d', 2695 'cteq5_m','cteq5_d','cteq5_l','cteq5m1', 2696 'cteq6_m','cteq6_l', 'cteq6l1', 2697 'nn23lo', 'nn23lo1', 'nn23nlo'] 2698 2699 2700 if self['pdlabel'] not in possible_set: 2701 raise InvalidRunCard, 'Invalid PDF set (argument of pdlabel): %s. Possible choice are:\n %s' % (self['pdlabel'], ', '.join(possible_set)) 2702 if self['pdlabel'] == 'lhapdf': 2703 #add warning if lhaid not define 2704 self.get_default('lhaid', log_level=20) 2705 2706 for name in self.legacy_parameter: 2707 if self[name] != self.legacy_parameter[name]: 2708 logger.warning("The parameter %s is not supported anymore this parameter will be ignored." % name)
2709 2710 2711 2712
2713 - def create_default_for_process(self, proc_characteristic, history, proc_def):
2714 """Rules 2715 process 1->N all cut set on off. 2716 loop_induced -> MC over helicity 2717 e+ e- beam -> lpp:0 ebeam:500 2718 p p beam -> set maxjetflavor automatically 2719 more than one multiplicity: ickkw=1 xqcut=30 use_syst=F 2720 """ 2721 2722 if proc_characteristic['loop_induced']: 2723 self['nhel'] = 1 2724 self['pdgs_for_merging_cut'] = proc_characteristic['colored_pdgs'] 2725 2726 if proc_characteristic['ninitial'] == 1: 2727 #remove all cut 2728 self.remove_all_cut() 2729 self['use_syst'] = False 2730 else: 2731 # check for beam_id 2732 beam_id = set() 2733 for proc in proc_def: 2734 for oneproc in proc: 2735 for leg in oneproc['legs']: 2736 if not leg['state']: 2737 beam_id.add(leg['id']) 2738 if any(i in beam_id for i in [1,-1,2,-2,3,-3,4,-4,5,-5,21,22]): 2739 maxjetflavor = max([4]+[abs(i) for i in beam_id if -7< i < 7]) 2740 self['maxjetflavor'] = maxjetflavor 2741 self['asrwgtflavor'] = maxjetflavor 2742 pass 2743 elif 11 in beam_id or -11 in beam_id: 2744 self['lpp1'] = 0 2745 self['lpp2'] = 0 2746 self['ebeam1'] = 500 2747 self['ebeam2'] = 500 2748 else: 2749 self['lpp1'] = 0 2750 self['lpp2'] = 0 2751 2752 # Check if need matching 2753 min_particle = 99 2754 max_particle = 0 2755 for proc in proc_def: 2756 min_particle = min(len(proc[0]['legs']), min_particle) 2757 max_particle = max(len(proc[0]['legs']), max_particle) 2758 if min_particle != max_particle: 2759 #take one of the process with min_particle 2760 for procmin in proc_def: 2761 if len(procmin[0]['legs']) != min_particle: 2762 continue 2763 else: 2764 idsmin = [l['id'] for l in procmin[0]['legs']] 2765 break 2766 matching = False 2767 for procmax in proc_def: 2768 if len(procmax[0]['legs']) != max_particle: 2769 continue 2770 idsmax = [l['id'] for l in procmax[0]['legs']] 2771 for i in idsmin: 2772 if i not in idsmax: 2773 continue 2774 else: 2775 idsmax.remove(i) 2776 for j in idsmax: 2777 if j not in [1,-1,2,-2,3,-3,4,-4,5,-5,21]: 2778 break 2779 else: 2780 # all are jet => matching is ON 2781 matching=True 2782 break 2783 2784 if matching: 2785 self['ickkw'] = 1 2786 self['xqcut'] = 30 2787 #self['use_syst'] = False 2788 self['drjj'] = 0 2789 self['drjl'] = 0 2790 self['sys_alpsfact'] = "0.5 1 2" 2791 2792 # For interference module, the systematics are wrong. 2793 # automatically set use_syst=F and set systematics_program=none 2794 no_systematics = False 2795 for proc in proc_def: 2796 for oneproc in proc: 2797 if '^2' in oneproc.nice_string(): 2798 no_systematics = True 2799 break 2800 else: 2801 continue 2802 break 2803 if no_systematics: 2804 self['use_syst'] = False 2805 self['systematics_program'] = 'none'
2806
2807 - def write(self, output_file, template=None, python_template=False):
2808 """Write the run_card in output_file according to template 2809 (a path to a valid run_card)""" 2810 2811 if not template: 2812 if not MADEVENT: 2813 template = pjoin(MG5DIR, 'Template', 'LO', 'Cards', 2814 'run_card.dat') 2815 python_template = True 2816 else: 2817 template = pjoin(MEDIR, 'Cards', 'run_card_default.dat') 2818 python_template = False 2819 2820 super(RunCardLO, self).write(output_file, template=template, 2821 python_template=python_template)
2822
2823 2824 -class InvalidMadAnalysis5Card(InvalidCmd):
2825 pass
2826
2827 -class MadAnalysis5Card(dict):
2828 """ A class to store a MadAnalysis5 card. Very basic since it is basically 2829 free format.""" 2830 2831 _MG5aMC_escape_tag = '@MG5aMC' 2832 2833 _default_hadron_inputs = ['*.hepmc', '*.hep', '*.stdhep', '*.lhco','*.root'] 2834 _default_parton_inputs = ['*.lhe'] 2835 _skip_analysis = False 2836 2837 @classmethod
2838 - def events_can_be_reconstructed(cls, file_path):
2839 """ Checks from the type of an event file whether it can be reconstructed or not.""" 2840 return not (file_path.endswith('.lhco') or file_path.endswith('.lhco.gz') or \ 2841 file_path.endswith('.root') or file_path.endswith('.root.gz'))
2842 2843 @classmethod
2844 - def empty_analysis(cls):
2845 """ A method returning the structure of an empty analysis """ 2846 return {'commands':[], 2847 'reconstructions':[]}
2848 2849 @classmethod
2850 - def empty_reconstruction(cls):
2851 """ A method returning the structure of an empty reconstruction """ 2852 return {'commands':[], 2853 'reco_output':'lhe'}
2854
2855 - def default_setup(self):
2856 """define the default value""" 2857 self['mode'] = 'parton' 2858 self['inputs'] = [] 2859 # None is the default stdout level, it will be set automatically by MG5aMC 2860 self['stdout_lvl'] = None 2861 # These two dictionaries are formated as follows: 2862 # {'analysis_name': 2863 # {'reconstructions' : ['associated_reconstructions_name']} 2864 # {'commands':['analysis command lines here']} } 2865 # with values being of the form of the empty_analysis() attribute 2866 # of this class and some other property could be added to this dictionary 2867 # in the future. 2868 self['analyses'] = {} 2869 # The recasting structure contains on set of commands and one set of 2870 # card lines. 2871 self['recasting'] = {'commands':[],'card':[]} 2872 # Add the default trivial reconstruction to use an lhco input 2873 # This is just for the structure 2874 self['reconstruction'] = {'lhco_input': 2875 MadAnalysis5Card.empty_reconstruction(), 2876 'root_input': 2877 MadAnalysis5Card.empty_reconstruction()} 2878 self['reconstruction']['lhco_input']['reco_output']='lhco' 2879 self['reconstruction']['root_input']['reco_output']='root' 2880 2881 # Specify in which order the analysis/recasting were specified 2882 self['order'] = []
2883
2884 - def __init__(self, finput=None,mode=None):
2885 if isinstance(finput, self.__class__): 2886 dict.__init__(self, finput) 2887 assert finput.__dict__.keys() 2888 for key in finput.__dict__: 2889 setattr(self, key, copy.copy(getattr(finput, key)) ) 2890 return 2891 else: 2892 dict.__init__(self) 2893 2894 # Initialize it with all the default value 2895 self.default_setup() 2896 if not mode is None: 2897 self['mode']=mode 2898 2899 # if input is define read that input 2900 if isinstance(finput, (file, str, StringIO.StringIO)): 2901 self.read(finput, mode=mode)
2902
2903 - def read(self, input, mode=None):
2904 """ Read an MA5 card""" 2905 2906 if mode not in [None,'parton','hadron']: 2907 raise MadGraph5Error('A MadAnalysis5Card can be read online the modes'+ 2908 "'parton' or 'hadron'") 2909 card_mode = mode 2910 2911 if isinstance(input, (file, StringIO.StringIO)): 2912 input_stream = input 2913 elif isinstance(input, str): 2914 if not os.path.isfile(input): 2915 raise InvalidMadAnalysis5Card("Cannot read the MadAnalysis5 card."+\ 2916 "File '%s' not found."%input) 2917 if mode is None and 'hadron' in input: 2918 card_mode = 'hadron' 2919 input_stream = open(input,'r') 2920 else: 2921 raise MadGraph5Error('Incorrect input for the read function of'+\ 2922 ' the MadAnalysis5Card card. Received argument type is: %s'%str(type(input))) 2923 2924 # Reinstate default values 2925 self.__init__() 2926 current_name = 'default' 2927 current_type = 'analyses' 2928 for line in input_stream: 2929 # Skip comments for now 2930 if line.startswith('#'): 2931 continue 2932 if line.endswith('\n'): 2933 line = line[:-1] 2934 if line.strip()=='': 2935 continue 2936 if line.startswith(self._MG5aMC_escape_tag): 2937 try: 2938 option,value = line[len(self._MG5aMC_escape_tag):].split('=') 2939 value = value.strip() 2940 except ValueError: 2941 option = line[len(self._MG5aMC_escape_tag):] 2942 option = option.strip() 2943 2944 if option=='inputs': 2945 self['inputs'].extend([v.strip() for v in value.split(',')]) 2946 2947 elif option == 'skip_analysis': 2948 self._skip_analysis = True 2949 2950 elif option=='stdout_lvl': 2951 try: # It is likely an int 2952 self['stdout_lvl']=int(value) 2953 except ValueError: 2954 try: # Maybe the user used something like 'logging.INFO' 2955 self['stdout_lvl']=eval(value) 2956 except: 2957 try: 2958 self['stdout_lvl']=eval('logging.%s'%value) 2959 except: 2960 raise InvalidMadAnalysis5Card( 2961 "MA5 output level specification '%s' is incorrect."%str(value)) 2962 2963 elif option=='analysis_name': 2964 current_type = 'analyses' 2965 current_name = value 2966 if current_name in self[current_type]: 2967 raise InvalidMadAnalysis5Card( 2968 "Analysis '%s' already defined in MadAnalysis5 card"%current_name) 2969 else: 2970 self[current_type][current_name] = MadAnalysis5Card.empty_analysis() 2971 2972 elif option=='set_reconstructions': 2973 try: 2974 reconstructions = eval(value) 2975 if not isinstance(reconstructions, list): 2976 raise 2977 except: 2978 raise InvalidMadAnalysis5Card("List of reconstructions"+\ 2979 " '%s' could not be parsed in MadAnalysis5 card."%value) 2980 if current_type!='analyses' and current_name not in self[current_type]: 2981 raise InvalidMadAnalysis5Card("A list of reconstructions"+\ 2982 "can only be defined in the context of an "+\ 2983 "analysis in a MadAnalysis5 card.") 2984 self[current_type][current_name]['reconstructions']=reconstructions 2985 continue 2986 2987 elif option=='reconstruction_name': 2988 current_type = 'reconstruction' 2989 current_name = value 2990 if current_name in self[current_type]: 2991 raise InvalidMadAnalysis5Card( 2992 "Reconstruction '%s' already defined in MadAnalysis5 hadron card"%current_name) 2993 else: 2994 self[current_type][current_name] = MadAnalysis5Card.empty_reconstruction() 2995 2996 elif option=='reco_output': 2997 if current_type!='reconstruction' or current_name not in \ 2998 self['reconstruction']: 2999 raise InvalidMadAnalysis5Card( 3000 "Option '%s' is only available within the definition of a reconstruction"%option) 3001 if not value.lower() in ['lhe','root']: 3002 raise InvalidMadAnalysis5Card( 3003 "Option '%s' can only take the values 'lhe' or 'root'"%option) 3004 self['reconstruction'][current_name]['reco_output'] = value.lower() 3005 3006 elif option.startswith('recasting'): 3007 current_type = 'recasting' 3008 try: 3009 current_name = option.split('_')[1] 3010 except: 3011 raise InvalidMadAnalysis5Card('Malformed MA5 recasting option %s.'%option) 3012 if len(self['recasting'][current_name])>0: 3013 raise InvalidMadAnalysis5Card( 3014 "Only one recasting can be defined in MadAnalysis5 hadron card") 3015 3016 else: 3017 raise InvalidMadAnalysis5Card( 3018 "Unreckognized MG5aMC instruction in MadAnalysis5 card: '%s'"%option) 3019 3020 if option in ['analysis_name','reconstruction_name'] or \ 3021 option.startswith('recasting'): 3022 self['order'].append((current_type,current_name)) 3023 continue 3024 3025 # Add the default analysis if needed since the user does not need 3026 # to specify it. 3027 if current_name == 'default' and current_type == 'analyses' and\ 3028 'default' not in self['analyses']: 3029 self['analyses']['default'] = MadAnalysis5Card.empty_analysis() 3030 self['order'].append(('analyses','default')) 3031 3032 if current_type in ['recasting']: 3033 self[current_type][current_name].append(line) 3034 elif current_type in ['reconstruction']: 3035 self[current_type][current_name]['commands'].append(line) 3036 elif current_type in ['analyses']: 3037 self[current_type][current_name]['commands'].append(line) 3038 3039 if 'reconstruction' in self['analyses'] or len(self['recasting']['card'])>0: 3040 if mode=='parton': 3041 raise InvalidMadAnalysis5Card( 3042 "A parton MadAnalysis5 card cannot specify a recombination or recasting.") 3043 card_mode = 'hadron' 3044 elif mode is None: 3045 card_mode = 'parton' 3046 3047 self['mode'] = card_mode 3048 if self['inputs'] == []: 3049 if self['mode']=='hadron': 3050 self['inputs'] = self._default_hadron_inputs 3051 else: 3052 self['inputs'] = self._default_parton_inputs 3053 3054 # Make sure at least one reconstruction is specified for each hadron 3055 # level analysis and that it exists. 3056 if self['mode']=='hadron': 3057 for analysis_name, analysis in self['analyses'].items(): 3058 if len(analysis['reconstructions'])==0: 3059 raise InvalidMadAnalysis5Card('Hadron-level analysis '+\ 3060 "'%s' is not specified any reconstruction(s)."%analysis_name) 3061 if any(reco not in self['reconstruction'] for reco in \ 3062 analysis['reconstructions']): 3063 raise InvalidMadAnalysis5Card('A reconstructions specified in'+\ 3064 " analysis '%s' is not defined."%analysis_name)
3065
3066 - def write(self, output):
3067 """ Write an MA5 card.""" 3068 3069 if isinstance(output, (file, StringIO.StringIO)): 3070 output_stream = output 3071 elif isinstance(output, str): 3072 output_stream = open(output,'w') 3073 else: 3074 raise MadGraph5Error('Incorrect input for the write function of'+\ 3075 ' the MadAnalysis5Card card. Received argument type is: %s'%str(type(output))) 3076 3077 output_lines = [] 3078 if self._skip_analysis: 3079 output_lines.append('%s skip_analysis'%self._MG5aMC_escape_tag) 3080 output_lines.append('%s inputs = %s'%(self._MG5aMC_escape_tag,','.join(self['inputs']))) 3081 if not self['stdout_lvl'] is None: 3082 output_lines.append('%s stdout_lvl=%s'%(self._MG5aMC_escape_tag,self['stdout_lvl'])) 3083 for definition_type, name in self['order']: 3084 3085 if definition_type=='analyses': 3086 output_lines.append('%s analysis_name = %s'%(self._MG5aMC_escape_tag,name)) 3087 output_lines.append('%s set_reconstructions = %s'%(self._MG5aMC_escape_tag, 3088 str(self['analyses'][name]['reconstructions']))) 3089 elif definition_type=='reconstruction': 3090 output_lines.append('%s reconstruction_name = %s'%(self._MG5aMC_escape_tag,name)) 3091 elif definition_type=='recasting': 3092 output_lines.append('%s recasting_%s'%(self._MG5aMC_escape_tag,name)) 3093 3094 if definition_type in ['recasting']: 3095 output_lines.extend(self[definition_type][name]) 3096 elif definition_type in ['reconstruction']: 3097 output_lines.append('%s reco_output = %s'%(self._MG5aMC_escape_tag, 3098 self[definition_type][name]['reco_output'])) 3099 output_lines.extend(self[definition_type][name]['commands']) 3100 elif definition_type in ['analyses']: 3101 output_lines.extend(self[definition_type][name]['commands']) 3102 3103 output_stream.write('\n'.join(output_lines)) 3104 3105 return
3106
3107 - def get_MA5_cmds(self, inputs_arg, submit_folder, run_dir_path=None, 3108 UFO_model_path=None, run_tag=''):
3109 """ Returns a list of tuples ('AnalysisTag',['commands']) specifying 3110 the commands of the MadAnalysis runs required from this card. 3111 At parton-level, the number of such commands is the number of analysis 3112 asked for. In the future, the idea is that the entire card can be 3113 processed in one go from MA5 directly.""" 3114 3115 if isinstance(inputs_arg, list): 3116 inputs = inputs_arg 3117 elif isinstance(inputs_arg, str): 3118 inputs = [inputs_arg] 3119 else: 3120 raise MadGraph5Error("The function 'get_MA5_cmds' can only take "+\ 3121 " a string or a list for the argument 'inputs_arg'") 3122 3123 if len(inputs)==0: 3124 raise MadGraph5Error("The function 'get_MA5_cmds' must have "+\ 3125 " at least one input specified'") 3126 3127 if run_dir_path is None: 3128 run_dir_path = os.path.dirname(inputs_arg) 3129 3130 cmds_list = [] 3131 3132 UFO_load = [] 3133 # first import the UFO if provided 3134 if UFO_model_path: 3135 UFO_load.append('import %s'%UFO_model_path) 3136 3137 def get_import(input, type=None): 3138 """ Generates the MA5 import commands for that event file. """ 3139 dataset_name = os.path.basename(input).split('.')[0] 3140 res = ['import %s as %s'%(input, dataset_name)] 3141 if not type is None: 3142 res.append('set %s.type = %s'%(dataset_name, type)) 3143 return res
3144 3145 fifo_status = {'warned_fifo':False,'fifo_used_up':False} 3146 def warn_fifo(input): 3147 if not input.endswith('.fifo'): 3148 return False 3149 if not fifo_status['fifo_used_up']: 3150 fifo_status['fifo_used_up'] = True 3151 return False 3152 else: 3153 if not fifo_status['warned_fifo']: 3154 logger.warning('Only the first MA5 analysis/reconstructions can be run on a fifo. Subsequent runs will skip fifo inputs.') 3155 fifo_status['warned_fifo'] = True 3156 return True
3157 3158 # Then the event file(s) input(s) 3159 inputs_load = [] 3160 for input in inputs: 3161 inputs_load.extend(get_import(input)) 3162 3163 submit_command = 'submit %s'%submit_folder+'_%s' 3164 3165 # Keep track of the reconstruction outpus in the MA5 workflow 3166 # Keys are reconstruction names and values are .lhe.gz reco file paths. 3167 # We put by default already the lhco/root ones present 3168 reconstruction_outputs = { 3169 'lhco_input':[f for f in inputs if 3170 f.endswith('.lhco') or f.endswith('.lhco.gz')], 3171 'root_input':[f for f in inputs if 3172 f.endswith('.root') or f.endswith('.root.gz')]} 3173 3174 # If a recasting card has to be written out, chose here its path 3175 recasting_card_path = pjoin(run_dir_path, 3176 '_'.join([run_tag,os.path.basename(submit_folder),'recasting_card.dat'])) 3177 3178 # Make sure to only run over one analysis over each fifo. 3179 for definition_type, name in self['order']: 3180 if definition_type == 'reconstruction': 3181 analysis_cmds = list(self['reconstruction'][name]['commands']) 3182 reco_outputs = [] 3183 for i_input, input in enumerate(inputs): 3184 # Skip lhco/root as they must not be reconstructed 3185 if not MadAnalysis5Card.events_can_be_reconstructed(input): 3186 continue 3187 # Make sure the input is not a used up fifo. 3188 if warn_fifo(input): 3189 continue 3190 analysis_cmds.append('import %s as reco_events'%input) 3191 if self['reconstruction'][name]['reco_output']=='lhe': 3192 reco_outputs.append('%s_%s.lhe.gz'%(os.path.basename( 3193 input).replace('_events','').split('.')[0],name)) 3194 analysis_cmds.append('set main.outputfile=%s'%reco_outputs[-1]) 3195 elif self['reconstruction'][name]['reco_output']=='root': 3196 reco_outputs.append('%s_%s.root'%(os.path.basename( 3197 input).replace('_events','').split('.')[0],name)) 3198 analysis_cmds.append('set main.fastsim.rootfile=%s'%reco_outputs[-1]) 3199 analysis_cmds.append( 3200 submit_command%('reco_%s_%d'%(name,i_input+1))) 3201 analysis_cmds.append('remove reco_events') 3202 3203 reconstruction_outputs[name]= [pjoin(run_dir_path,rec_out) 3204 for rec_out in reco_outputs] 3205 if len(reco_outputs)>0: 3206 cmds_list.append(('_reco_%s'%name,analysis_cmds)) 3207 3208 elif definition_type == 'analyses': 3209 if self['mode']=='parton': 3210 cmds_list.append( (name, UFO_load+inputs_load+ 3211 self['analyses'][name]['commands']+[submit_command%name]) ) 3212 elif self['mode']=='hadron': 3213 # Also run on the already reconstructed root/lhco files if found. 3214 for reco in self['analyses'][name]['reconstructions']+\ 3215 ['lhco_input','root_input']: 3216 if len(reconstruction_outputs[reco])==0: 3217 continue 3218 if self['reconstruction'][reco]['reco_output']=='lhe': 3219 # For the reconstructed lhe output we must be in parton mode 3220 analysis_cmds = ['set main.mode = parton'] 3221 else: 3222 analysis_cmds = [] 3223 analysis_cmds.extend(sum([get_import(rec_out) for 3224 rec_out in reconstruction_outputs[reco]],[])) 3225 analysis_cmds.extend(self['analyses'][name]['commands']) 3226 analysis_cmds.append(submit_command%('%s_%s'%(name,reco))) 3227 cmds_list.append( ('%s_%s'%(name,reco),analysis_cmds) ) 3228 3229 elif definition_type == 'recasting': 3230 if len(self['recasting']['card'])==0: 3231 continue 3232 if name == 'card': 3233 # Create the card here 3234 open(recasting_card_path,'w').write('\n'.join(self['recasting']['card'])) 3235 if name == 'commands': 3236 recasting_cmds = list(self['recasting']['commands']) 3237 # Exclude LHCO files here of course 3238 n_inputs = 0 3239 for input in inputs: 3240 if not MadAnalysis5Card.events_can_be_reconstructed(input): 3241 continue 3242 # Make sure the input is not a used up fifo. 3243 if warn_fifo(input): 3244 continue 3245 recasting_cmds.extend(get_import(input,'signal')) 3246 n_inputs += 1 3247 3248 recasting_cmds.append('set main.recast.card_path=%s'%recasting_card_path) 3249 recasting_cmds.append(submit_command%'Recasting') 3250 if n_inputs>0: 3251 cmds_list.append( ('Recasting',recasting_cmds)) 3252 3253 return cmds_list 3254
3255 -class RunCardNLO(RunCard):
3256 """A class object for the run_card for a (aMC@)NLO pocess""" 3257
3258 - def default_setup(self):
3259 """define the default value""" 3260 3261 self.add_param('run_tag', 'tag_1', include=False) 3262 self.add_param('nevents', 10000) 3263 self.add_param('req_acc', -1.0, include=False) 3264 self.add_param('nevt_job', -1, include=False) 3265 self.add_param('event_norm', 'average') 3266 #FO parameter 3267 self.add_param('req_acc_fo', 0.01, include=False) 3268 self.add_param('npoints_fo_grid', 5000, include=False) 3269 self.add_param('niters_fo_grid', 4, include=False) 3270 self.add_param('npoints_fo', 10000, include=False) 3271 self.add_param('niters_fo', 6, include=False) 3272 #seed and collider 3273 self.add_param('iseed', 0) 3274 self.add_param('lpp1', 1, fortran_name='lpp(1)') 3275 self.add_param('lpp2', 1, fortran_name='lpp(2)') 3276 self.add_param('ebeam1', 6500.0, fortran_name='ebeam(1)') 3277 self.add_param('ebeam2', 6500.0, fortran_name='ebeam(2)') 3278 self.add_param('pdlabel', 'nn23nlo') 3279 self.add_param('lhaid', [244600],fortran_name='lhaPDFid') 3280 self.add_param('lhapdfsetname', ['internal_use_only'], system=True) 3281 #shower and scale 3282 self.add_param('parton_shower', 'HERWIG6', fortran_name='shower_mc') 3283 self.add_param('shower_scale_factor',1.0) 3284 self.add_param('fixed_ren_scale', False) 3285 self.add_param('fixed_fac_scale', False) 3286 self.add_param('mur_ref_fixed', 91.118) 3287 self.add_param('muf1_ref_fixed', -1.0, hidden=True) 3288 self.add_param('muf_ref_fixed', 91.118) 3289 self.add_param('muf2_ref_fixed', -1.0, hidden=True) 3290 self.add_param("dynamical_scale_choice", [-1],fortran_name='dyn_scale') 3291 self.add_param('fixed_qes_scale', False, hidden=True) 3292 self.add_param('qes_ref_fixed', -1.0, hidden=True) 3293 self.add_param('mur_over_ref', 1.0) 3294 self.add_param('muf_over_ref', 1.0) 3295 self.add_param('muf1_over_ref', -1.0, hidden=True) 3296 self.add_param('muf2_over_ref', -1.0, hidden=True) 3297 self.add_param('qes_over_ref', -1.0, hidden=True) 3298 self.add_param('reweight_scale', [True], fortran_name='lscalevar') 3299 self.add_param('rw_rscale_down', -1.0, hidden=True) 3300 self.add_param('rw_rscale_up', -1.0, hidden=True) 3301 self.add_param('rw_fscale_down', -1.0, hidden=True) 3302 self.add_param('rw_fscale_up', -1.0, hidden=True) 3303 self.add_param('rw_rscale', [1.0,2.0,0.5], fortran_name='scalevarR') 3304 self.add_param('rw_fscale', [1.0,2.0,0.5], fortran_name='scalevarF') 3305 self.add_param('reweight_pdf', [False], fortran_name='lpdfvar') 3306 self.add_param('pdf_set_min', 244601, hidden=True) 3307 self.add_param('pdf_set_max', 244700, hidden=True) 3308 self.add_param('store_rwgt_info', False) 3309 self.add_param('systematics_program', 'none', include=False, hidden=True, comment='Choose which program to use for systematics computation: none, systematics') 3310 self.add_param('systematics_arguments', [''], include=False, hidden=True, comment='Choose the argment to pass to the systematics command. like --mur=0.25,1,4. Look at the help of the systematics function for more details.') 3311 3312 #merging 3313 self.add_param('ickkw', 0) 3314 self.add_param('bwcutoff', 15.0) 3315 #cuts 3316 self.add_param('jetalgo', 1.0) 3317 self.add_param('jetradius', 0.7) 3318 self.add_param('ptj', 10.0 , cut=True) 3319 self.add_param('etaj', -1.0, cut=True) 3320 self.add_param('ptl', 0.0, cut=True) 3321 self.add_param('etal', -1.0, cut=True) 3322 self.add_param('drll', 0.0, cut=True) 3323 self.add_param('drll_sf', 0.0, cut=True) 3324 self.add_param('mll', 0.0, cut=True) 3325 self.add_param('mll_sf', 30.0, cut=True) 3326 self.add_param('ptgmin', 20.0, cut=True) 3327 self.add_param('etagamma', -1.0) 3328 self.add_param('r0gamma', 0.4) 3329 self.add_param('xn', 1.0) 3330 self.add_param('epsgamma', 1.0) 3331 self.add_param('isoem', True) 3332 self.add_param('maxjetflavor', 4, hidden=True) 3333 self.add_param('iappl', 0) 3334 self.add_param('lhe_version', 3, hidden=True, include=False)
3335
3336 - def check_validity(self):
3337 """check the validity of the various input""" 3338 3339 super(RunCardNLO, self).check_validity() 3340 3341 # For FxFx merging, make sure that the following parameters are set correctly: 3342 if self['ickkw'] == 3: 3343 # 1. Renormalization and factorization (and ellis-sexton scales) are not fixed 3344 scales=['fixed_ren_scale','fixed_fac_scale','fixed_QES_scale'] 3345 for scale in scales: 3346 if self[scale]: 3347 logger.warning('''For consistency in the FxFx merging, \'%s\' has been set to false''' 3348 % scale,'$MG:color:BLACK') 3349 self[scale]= False 3350 #and left to default dynamical scale 3351 if len(self["dynamical_scale_choice"]) > 1 or self["dynamical_scale_choice"][0] != -1: 3352 self["dynamical_scale_choice"] = [-1] 3353 self["reweight_scale"]=[self["reweight_scale"][0]] 3354 logger.warning('''For consistency in the FxFx merging, dynamical_scale_choice has been set to -1 (default)''' 3355 ,'$MG:color:BLACK') 3356 3357 # 2. Use kT algorithm for jets with pseudo-code size R=1.0 3358 jetparams=['jetradius','jetalgo'] 3359 for jetparam in jetparams: 3360 if float(self[jetparam]) != 1.0: 3361 logger.info('''For consistency in the FxFx merging, \'%s\' has been set to 1.0''' 3362 % jetparam ,'$MG:color:BLACK') 3363 self[jetparam] = 1.0 3364 elif self['ickkw'] == -1 and (self["dynamical_scale_choice"][0] != -1 or 3365 len(self["dynamical_scale_choice"]) > 1): 3366 self["dynamical_scale_choice"] = [-1] 3367 self["reweight_scale"]=[self["reweight_scale"][0]] 3368 logger.warning('''For consistency with the jet veto, the scale which will be used is ptj. dynamical_scale_choice will be set at -1.''' 3369 ,'$MG:color:BLACK') 3370 3371 # For interface to APPLGRID, need to use LHAPDF and reweighting to get scale uncertainties 3372 if self['iappl'] != 0 and self['pdlabel'].lower() != 'lhapdf': 3373 raise InvalidRunCard('APPLgrid generation only possible with the use of LHAPDF') 3374 if self['iappl'] != 0 and not self['reweight_scale']: 3375 raise InvalidRunCard('APPLgrid generation only possible with including' +\ 3376 ' the reweighting to get scale dependence') 3377 3378 # check that the pdf is set correctly 3379 possible_set = ['lhapdf','mrs02nl','mrs02nn', 'mrs0119','mrs0117','mrs0121','mrs01_j', 'mrs99_1','mrs99_2','mrs99_3','mrs99_4','mrs99_5','mrs99_6', 'mrs99_7','mrs99_8','mrs99_9','mrs9910','mrs9911','mrs9912', 'mrs98z1','mrs98z2','mrs98z3','mrs98z4','mrs98z5','mrs98ht', 'mrs98l1','mrs98l2','mrs98l3','mrs98l4','mrs98l5', 'cteq3_m','cteq3_l','cteq3_d', 'cteq4_m','cteq4_d','cteq4_l','cteq4a1','cteq4a2', 'cteq4a3','cteq4a4','cteq4a5','cteq4hj','cteq4lq', 'cteq5_m','cteq5_d','cteq5_l','cteq5hj','cteq5hq', 'cteq5f3','cteq5f4','cteq5m1','ctq5hq1','cteq5l1', 'cteq6_m','cteq6_d','cteq6_l','cteq6l1', 'nn23lo','nn23lo1','nn23nlo'] 3380 if self['pdlabel'] not in possible_set: 3381 raise InvalidRunCard, 'Invalid PDF set (argument of pdlabel) possible choice are:\n %s' % ','.join(possible_set) 3382 3383 # Hidden values check 3384 if self['qes_ref_fixed'] == -1.0: 3385 self['qes_ref_fixed']=self['mur_ref_fixed'] 3386 if self['qes_over_ref'] == -1.0: 3387 self['qes_over_ref']=self['mur_over_ref'] 3388 if self['muf1_over_ref'] != -1.0 and self['muf1_over_ref'] == self['muf2_over_ref']: 3389 self['muf_over_ref']=self['muf1_over_ref'] 3390 if self['muf1_over_ref'] == -1.0: 3391 self['muf1_over_ref']=self['muf_over_ref'] 3392 if self['muf2_over_ref'] == -1.0: 3393 self['muf2_over_ref']=self['muf_over_ref'] 3394 if self['muf1_ref_fixed'] != -1.0 and self['muf1_ref_fixed'] == self['muf2_ref_fixed']: 3395 self['muf_ref_fixed']=self['muf1_ref_fixed'] 3396 if self['muf1_ref_fixed'] == -1.0: 3397 self['muf1_ref_fixed']=self['muf_ref_fixed'] 3398 if self['muf2_ref_fixed'] == -1.0: 3399 self['muf2_ref_fixed']=self['muf_ref_fixed'] 3400 # overwrite rw_rscale and rw_fscale when rw_(r/f)scale_(down/up) are explicitly given in the run_card for backward compatibility. 3401 if (self['rw_rscale_down'] != -1.0 and ['rw_rscale_down'] not in self['rw_rscale']) or\ 3402 (self['rw_rscale_up'] != -1.0 and ['rw_rscale_up'] not in self['rw_rscale']): 3403 self['rw_rscale']=[1.0,self['rw_rscale_up'],self['rw_rscale_down']] 3404 if (self['rw_fscale_down'] != -1.0 and ['rw_fscale_down'] not in self['rw_fscale']) or\ 3405 (self['rw_fscale_up'] != -1.0 and ['rw_fscale_up'] not in self['rw_fscale']): 3406 self['rw_fscale']=[1.0,self['rw_fscale_up'],self['rw_fscale_down']] 3407 3408 # PDF reweighting check 3409 if any(self['reweight_pdf']): 3410 # check that we use lhapdf if reweighting is ON 3411 if self['pdlabel'] != "lhapdf": 3412 raise InvalidRunCard, 'Reweight PDF option requires to use pdf sets associated to lhapdf. Please either change the pdlabel to use LHAPDF or set reweight_pdf to False.' 3413 3414 # make sure set have reweight_pdf and lhaid of length 1 when not including lhapdf 3415 if self['pdlabel'] != "lhapdf": 3416 self['reweight_pdf']=[self['reweight_pdf'][0]] 3417 self['lhaid']=[self['lhaid'][0]] 3418 3419 # make sure set have reweight_scale and dyn_scale_choice of length 1 when fixed scales: 3420 if self['fixed_ren_scale'] and self['fixed_fac_scale']: 3421 self['reweight_scale']=[self['reweight_scale'][0]] 3422 self['dynamical_scale_choice']=[0] 3423 3424 # If there is only one reweight_pdf/reweight_scale, but 3425 # lhaid/dynamical_scale_choice are longer, expand the 3426 # reweight_pdf/reweight_scale list to have the same length 3427 if len(self['reweight_pdf']) == 1 and len(self['lhaid']) != 1: 3428 self['reweight_pdf']=self['reweight_pdf']*len(self['lhaid']) 3429 logger.warning("Setting 'reweight_pdf' for all 'lhaid' to %s" % self['reweight_pdf'][0]) 3430 if len(self['reweight_scale']) == 1 and len(self['dynamical_scale_choice']) != 1: 3431 self['reweight_scale']=self['reweight_scale']*len(self['dynamical_scale_choice']) 3432 logger.warning("Setting 'reweight_scale' for all 'dynamical_scale_choice' to %s" % self['reweight_pdf'][0]) 3433 3434 # Check that there are no identical elements in lhaid or dynamical_scale_choice 3435 if len(self['lhaid']) != len(set(self['lhaid'])): 3436 raise InvalidRunCard, "'lhaid' has two or more identical entries. They have to be all different for the code to work correctly." 3437 if len(self['dynamical_scale_choice']) != len(set(self['dynamical_scale_choice'])): 3438 raise InvalidRunCard, "'dynamical_scale_choice' has two or more identical entries. They have to be all different for the code to work correctly." 3439 3440 # Check that lenght of lists are consistent 3441 if len(self['reweight_pdf']) != len(self['lhaid']): 3442 raise InvalidRunCard, "'reweight_pdf' and 'lhaid' lists should have the same length" 3443 if len(self['reweight_scale']) != len(self['dynamical_scale_choice']): 3444 raise InvalidRunCard, "'reweight_scale' and 'dynamical_scale_choice' lists should have the same length" 3445 if len(self['dynamical_scale_choice']) > 10 : 3446 raise InvalidRunCard, "Length of list for 'dynamical_scale_choice' too long: max is 10." 3447 if len(self['lhaid']) > 25 : 3448 raise InvalidRunCard, "Length of list for 'lhaid' too long: max is 25." 3449 if len(self['rw_rscale']) > 9 : 3450 raise InvalidRunCard, "Length of list for 'rw_rscale' too long: max is 9." 3451 if len(self['rw_fscale']) > 9 : 3452 raise InvalidRunCard, "Length of list for 'rw_fscale' too long: max is 9." 3453 # make sure that the first element of rw_rscale and rw_fscale is the 1.0 3454 if 1.0 not in self['rw_rscale']: 3455 logger.warning("'1.0' has to be part of 'rw_rscale', adding it") 3456 self['rw_rscale'].insert(0,1.0) 3457 if 1.0 not in self['rw_fscale']: 3458 logger.warning("'1.0' has to be part of 'rw_fscale', adding it") 3459 self['rw_fscale'].insert(0,1.0) 3460 if self['rw_rscale'][0] != 1.0 and 1.0 in self['rw_rscale']: 3461 a=self['rw_rscale'].index(1.0) 3462 self['rw_rscale'][0],self['rw_rscale'][a]=self['rw_rscale'][a],self['rw_rscale'][0] 3463 if self['rw_fscale'][0] != 1.0 and 1.0 in self['rw_fscale']: 3464 a=self['rw_fscale'].index(1.0) 3465 self['rw_fscale'][0],self['rw_fscale'][a]=self['rw_fscale'][a],self['rw_fscale'][0] 3466 # check that all elements of rw_rscale and rw_fscale are diffent. 3467 if len(self['rw_rscale']) != len(set(self['rw_rscale'])): 3468 raise InvalidRunCard, "'rw_rscale' has two or more identical entries. They have to be all different for the code to work correctly." 3469 if len(self['rw_fscale']) != len(set(self['rw_fscale'])): 3470 raise InvalidRunCard, "'rw_fscale' has two or more identical entries. They have to be all different for the code to work correctly."
3471 3472
3473 - def write(self, output_file, template=None, python_template=False):
3474 """Write the run_card in output_file according to template 3475 (a path to a valid run_card)""" 3476 3477 if not template: 3478 if not MADEVENT: 3479 template = pjoin(MG5DIR, 'Template', 'NLO', 'Cards', 3480 'run_card.dat') 3481 python_template = True 3482 else: 3483 template = pjoin(MEDIR, 'Cards', 'run_card_default.dat') 3484 python_template = False 3485 3486 super(RunCardNLO, self).write(output_file, template=template, 3487 python_template=python_template)
3488 3489
3490 - def create_default_for_process(self, proc_characteristic, history, proc_def):
3491 """Rules 3492 e+ e- beam -> lpp:0 ebeam:500 3493 p p beam -> set maxjetflavor automatically 3494 """ 3495 3496 # check for beam_id 3497 beam_id = set() 3498 for proc in proc_def: 3499 for leg in proc['legs']: 3500 if not leg['state']: 3501 beam_id.add(leg['id']) 3502 if any(i in beam_id for i in [1,-1,2,-2,3,-3,4,-4,5,-5,21,22]): 3503 maxjetflavor = max([4]+[abs(i) for i in beam_id if -7< i < 7]) 3504 self['maxjetflavor'] = maxjetflavor 3505 pass 3506 elif 11 in beam_id or -11 in beam_id: 3507 self['lpp1'] = 0 3508 self['lpp2'] = 0 3509 self['ebeam1'] = 500 3510 self['ebeam2'] = 500 3511 else: 3512 self['lpp1'] = 0 3513 self['lpp2'] = 0 3514 3515 if proc_characteristic['ninitial'] == 1: 3516 #remove all cut 3517 self.remove_all_cut()
3518
3519 -class MadLoopParam(ConfigFile):
3520 """ a class for storing/dealing with the file MadLoopParam.dat 3521 contains a parser to read it, facilities to write a new file,... 3522 """ 3523 3524 _ID_reduction_tool_map = {1:'CutTools', 3525 2:'PJFry++', 3526 3:'IREGI', 3527 4:'Golem95', 3528 5:'Samurai', 3529 6:'Ninja', 3530 7:'COLLIER'} 3531
3532 - def default_setup(self):
3533 """initialize the directory to the default value""" 3534 3535 self.add_param("MLReductionLib", "6|7|1") 3536 self.add_param("IREGIMODE", 2) 3537 self.add_param("IREGIRECY", True) 3538 self.add_param("CTModeRun", -1) 3539 self.add_param("MLStabThres", 1e-3) 3540 self.add_param("NRotations_DP", 0) 3541 self.add_param("NRotations_QP", 0) 3542 self.add_param("ImprovePSPoint", 2) 3543 self.add_param("CTLoopLibrary", 2) 3544 self.add_param("CTStabThres", 1e-2) 3545 self.add_param("CTModeInit", 1) 3546 self.add_param("CheckCycle", 3) 3547 self.add_param("MaxAttempts", 10) 3548 self.add_param("ZeroThres", 1e-9) 3549 self.add_param("OSThres", 1.0e-8) 3550 self.add_param("DoubleCheckHelicityFilter", True) 3551 self.add_param("WriteOutFilters", True) 3552 self.add_param("UseLoopFilter", False) 3553 self.add_param("HelicityFilterLevel", 2) 3554 self.add_param("LoopInitStartOver", False) 3555 self.add_param("HelInitStartOver", False) 3556 self.add_param("UseQPIntegrandForNinja", True) 3557 self.add_param("UseQPIntegrandForCutTools", True) 3558 self.add_param("COLLIERMode", 1) 3559 self.add_param("COLLIERComputeUVpoles", True) 3560 self.add_param("COLLIERComputeIRpoles", True) 3561 self.add_param("COLLIERRequiredAccuracy", 1.0e-8) 3562 self.add_param("COLLIERCanOutput",False) 3563 self.add_param("COLLIERGlobalCache",-1) 3564 self.add_param("COLLIERUseCacheForPoles",False) 3565 self.add_param("COLLIERUseInternalStabilityTest",True)
3566
3567 - def read(self, finput):
3568 """Read the input file, this can be a path to a file, 3569 a file object, a str with the content of the file.""" 3570 3571 if isinstance(finput, str): 3572 if "\n" in finput: 3573 finput = finput.split('\n') 3574 elif os.path.isfile(finput): 3575 finput = open(finput) 3576 else: 3577 raise Exception, "No such file %s" % input 3578 3579 previous_line= '' 3580 for line in finput: 3581 if previous_line.startswith('#'): 3582 name = previous_line[1:].split()[0] 3583 value = line.strip() 3584 if len(value) and value[0] not in ['#', '!']: 3585 self.__setitem__(name, value, change_userdefine=True) 3586 previous_line = line
3587 3588
3589 - def write(self, outputpath, template=None,commentdefault=False):
3590 3591 if not template: 3592 if not MADEVENT: 3593 template = pjoin(MG5DIR, 'Template', 'loop_material', 'StandAlone', 3594 'Cards', 'MadLoopParams.dat') 3595 else: 3596 template = pjoin(MEDIR, 'Cards', 'MadLoopParams_default.dat') 3597 fsock = open(template, 'r') 3598 template = fsock.readlines() 3599 fsock.close() 3600 3601 if isinstance(outputpath, str): 3602 output = open(outputpath, 'w') 3603 else: 3604 output = outputpath 3605 3606 def f77format(value): 3607 if isinstance(value, bool): 3608 if value: 3609 return '.true.' 3610 else: 3611 return '.false.' 3612 elif isinstance(value, int): 3613 return value 3614 elif isinstance(value, float): 3615 tmp ='%e' % value 3616 return tmp.replace('e','d') 3617 elif isinstance(value, str): 3618 return value 3619 else: 3620 raise Exception, "Can not format input %s" % type(value)
3621 3622 name = '' 3623 done = set() 3624 for line in template: 3625 if name: 3626 done.add(name) 3627 if commentdefault and name.lower() not in self.user_set : 3628 output.write('!%s\n' % f77format(self[name])) 3629 else: 3630 output.write('%s\n' % f77format(self[name])) 3631 name='' 3632 continue 3633 elif line.startswith('#'): 3634 name = line[1:].split()[0] 3635 output.write(line)
3636