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