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 self.add_param('splitting_types',[], typelist=str) 1439 self.add_param('perturbation_order', [], typelist=str)
1440
1441 - def read(self, finput):
1442 """Read the input file, this can be a path to a file, 1443 a file object, a str with the content of the file.""" 1444 1445 if isinstance(finput, str): 1446 if "\n" in finput: 1447 finput = finput.split('\n') 1448 elif os.path.isfile(finput): 1449 finput = open(finput) 1450 else: 1451 raise Exception, "No such file %s" % finput 1452 1453 for line in finput: 1454 if '#' in line: 1455 line = line.split('#',1)[0] 1456 if not line: 1457 continue 1458 1459 if '=' in line: 1460 key, value = line.split('=',1) 1461 self[key.strip()] = value
1462
1463 - def write(self, outputpath):
1464 """write the file""" 1465 1466 template ="# Information about the process #\n" 1467 template +="#########################################\n" 1468 1469 fsock = open(outputpath, 'w') 1470 fsock.write(template) 1471 1472 for key, value in self.items(): 1473 fsock.write(" %s = %s \n" % (key, value)) 1474 1475 fsock.close()
1476
1477 1478 1479 1480 -class GridpackCard(ConfigFile):
1481 """an object for the GridpackCard""" 1482
1483 - def default_setup(self):
1484 """default value for the GridpackCard""" 1485 1486 self.add_param("GridRun", True) 1487 self.add_param("gevents", 2500) 1488 self.add_param("gseed", 1) 1489 self.add_param("ngran", -1)
1490
1491 - def read(self, finput):
1492 """Read the input file, this can be a path to a file, 1493 a file object, a str with the content of the file.""" 1494 1495 if isinstance(finput, str): 1496 if "\n" in finput: 1497 finput = finput.split('\n') 1498 elif os.path.isfile(finput): 1499 finput = open(finput) 1500 else: 1501 raise Exception, "No such file %s" % finput 1502 1503 for line in finput: 1504 line = line.split('#')[0] 1505 line = line.split('!')[0] 1506 line = line.split('=',1) 1507 if len(line) != 2: 1508 continue 1509 self[line[1].strip()] = line[0].replace('\'','').strip()
1510
1511 - def write(self, output_file, template=None):
1512 """Write the run_card in output_file according to template 1513 (a path to a valid run_card)""" 1514 1515 if not template: 1516 if not MADEVENT: 1517 template = pjoin(MG5DIR, 'Template', 'LO', 'Cards', 1518 'grid_card_default.dat') 1519 else: 1520 template = pjoin(MEDIR, 'Cards', 'grid_card_default.dat') 1521 1522 1523 text = "" 1524 for line in file(template,'r'): 1525 nline = line.split('#')[0] 1526 nline = nline.split('!')[0] 1527 comment = line[len(nline):] 1528 nline = nline.split('=') 1529 if len(nline) != 2: 1530 text += line 1531 elif nline[1].strip() in self: 1532 text += ' %s\t= %s %s' % (self[nline[1].strip()],nline[1], comment) 1533 else: 1534 logger.info('Adding missing parameter %s to current run_card (with default value)' % nline[1].strip()) 1535 text += line 1536 1537 if isinstance(output_file, str): 1538 fsock = open(output_file,'w') 1539 else: 1540 fsock = output_file 1541 1542 fsock.write(text) 1543 fsock.close()
1544
1545 -class PY8Card(ConfigFile):
1546 """ Implements the Pythia8 card.""" 1547
1548 - def add_default_subruns(self, type):
1549 """ Placeholder function to allow overwriting in the PY8SubRun daughter. 1550 The initialization of the self.subruns attribute should of course not 1551 be performed in PY8SubRun.""" 1552 if type == 'parameters': 1553 if "LHEFInputs:nSubruns" not in self: 1554 self.add_param("LHEFInputs:nSubruns", 1, 1555 hidden='ALWAYS_WRITTEN', 1556 comment=""" 1557 ==================== 1558 Subrun definitions 1559 ==================== 1560 """) 1561 if type == 'attributes': 1562 if not(hasattr(self,'subruns')): 1563 first_subrun = PY8SubRun(subrun_id=0) 1564 self.subruns = dict([(first_subrun['Main:subrun'],first_subrun)])
1565
1566 - def default_setup(self):
1567 """ Sets up the list of available PY8 parameters.""" 1568 1569 # Visible parameters 1570 # ================== 1571 self.add_param("Main:numberOfEvents", -1) 1572 # for MLM merging 1573 # -1.0 means that it will be set automatically by MadGraph5_aMC@NLO 1574 self.add_param("JetMatching:qCut", -1.0, always_write_to_card=False) 1575 self.add_param("JetMatching:doShowerKt",False,always_write_to_card=False) 1576 # -1 means that it is automatically set. 1577 self.add_param("JetMatching:nJetMax", -1, always_write_to_card=False) 1578 # for CKKWL merging 1579 self.add_param("Merging:TMS", -1.0, always_write_to_card=False) 1580 self.add_param("Merging:Process", '<set_by_user>', always_write_to_card=False) 1581 # -1 means that it is automatically set. 1582 self.add_param("Merging:nJetMax", -1, always_write_to_card=False) 1583 # for both merging, chose whether to also consider different merging 1584 # scale values for the extra weights related to scale and PDF variations. 1585 self.add_param("SysCalc:fullCutVariation", False) 1586 # Select the HepMC output. The user can prepend 'fifo:<optional_fifo_path>' 1587 # to indicate that he wants to pipe the output. Or /dev/null to turn the 1588 # output off. 1589 self.add_param("HEPMCoutput:file", 'auto') 1590 1591 # Hidden parameters always written out 1592 # ==================================== 1593 self.add_param("Beams:frameType", 4, 1594 hidden=True, 1595 comment='Tell Pythia8 that an LHEF input is used.') 1596 self.add_param("HEPMCoutput:scaling", 1.0e9, 1597 hidden=True, 1598 comment='1.0 corresponds to HEPMC weight given in [mb]. We choose here the [pb] normalization.') 1599 self.add_param("Check:epTolErr", 1e-2, 1600 hidden=True, 1601 comment='Be more forgiving with momentum mismatches.') 1602 # By default it is important to disable any cut on the rapidity of the showered jets 1603 # during MLML merging and by default it is set to 2.5 1604 self.add_param("JetMatching:etaJetMax", 1000.0, hidden=True, always_write_to_card=True) 1605 1606 # Hidden parameters written out only if user_set or system_set 1607 # ============================================================ 1608 self.add_param("PDF:pSet", 'LHAPDF5:CT10.LHgrid', hidden=True, always_write_to_card=False, 1609 comment='Reminder: Parameter below is shower tune dependent.') 1610 self.add_param("SpaceShower:alphaSvalue", 0.118, hidden=True, always_write_to_card=False, 1611 comment='Reminder: Parameter below is shower tune dependent.') 1612 self.add_param("TimeShower:alphaSvalue", 0.118, hidden=True, always_write_to_card=False, 1613 comment='Reminder: Parameter below is shower tune dependent.') 1614 self.add_param("hadronlevel:all", True, hidden=True, always_write_to_card=False, 1615 comment='This allows to turn on/off hadronization alltogether.') 1616 self.add_param("partonlevel:mpi", True, hidden=True, always_write_to_card=False, 1617 comment='This allows to turn on/off MPI alltogether.') 1618 self.add_param("Beams:setProductionScalesFromLHEF", False, hidden=True, 1619 always_write_to_card=False, 1620 comment='This parameter is automatically set to True by MG5aMC when doing MLM merging with PY8.') 1621 1622 # for MLM merging 1623 self.add_param("JetMatching:merge", False, hidden=True, always_write_to_card=False, 1624 comment='Specifiy if we are merging sample of different multiplicity.') 1625 self.add_param("SysCalc:qCutList", [10.0,20.0], hidden=True, always_write_to_card=False) 1626 self['SysCalc:qCutList'] = 'auto' 1627 self.add_param("SysCalc:qWeed",-1.0,hidden=True, always_write_to_card=False, 1628 comment='Value of the merging scale below which one does not even write the HepMC event.') 1629 self.add_param("JetMatching:doVeto", False, hidden=True, always_write_to_card=False, 1630 comment='Do veto externally (e.g. in SysCalc).') 1631 self.add_param("JetMatching:scheme", 1, hidden=True, always_write_to_card=False) 1632 self.add_param("JetMatching:setMad", False, hidden=True, always_write_to_card=False, 1633 comment='Specify one must read inputs from the MadGraph banner.') 1634 self.add_param("JetMatching:coneRadius", 1.0, hidden=True, always_write_to_card=False) 1635 self.add_param("JetMatching:nQmatch",4,hidden=True, always_write_to_card=False) 1636 # for CKKWL merging (common with UMEPS, UNLOPS) 1637 self.add_param("TimeShower:pTmaxMatch", 2, hidden=True, always_write_to_card=False) 1638 self.add_param("SpaceShower:pTmaxMatch", 1, hidden=True, always_write_to_card=False) 1639 self.add_param("SysCalc:tmsList", [10.0,20.0], hidden=True, always_write_to_card=False) 1640 self['SysCalc:tmsList'] = 'auto' 1641 self.add_param("Merging:muFac", 91.188, hidden=True, always_write_to_card=False, 1642 comment='Set factorisation scales of the 2->2 process.') 1643 self.add_param("Merging:applyVeto", False, hidden=True, always_write_to_card=False, 1644 comment='Do veto externally (e.g. in SysCalc).') 1645 self.add_param("Merging:includeWeightInXsection", True, hidden=True, always_write_to_card=False, 1646 comment='If turned off, then the option belows forces PY8 to keep the original weight.') 1647 self.add_param("Merging:muRen", 91.188, hidden=True, always_write_to_card=False, 1648 comment='Set renormalization scales of the 2->2 process.') 1649 self.add_param("Merging:muFacInME", 91.188, hidden=True, always_write_to_card=False, 1650 comment='Set factorisation scales of the 2->2 Matrix Element.') 1651 self.add_param("Merging:muRenInME", 91.188, hidden=True, always_write_to_card=False, 1652 comment='Set renormalization scales of the 2->2 Matrix Element.') 1653 self.add_param("SpaceShower:rapidityOrder", False, hidden=True, always_write_to_card=False) 1654 self.add_param("Merging:nQuarksMerge",4,hidden=True, always_write_to_card=False) 1655 # To be added in subruns for CKKWL 1656 self.add_param("Merging:mayRemoveDecayProducts", False, hidden=True, always_write_to_card=False) 1657 self.add_param("Merging:doKTMerging", False, hidden=True, always_write_to_card=False) 1658 self.add_param("Merging:Dparameter", 0.4, hidden=True, always_write_to_card=False) 1659 self.add_param("Merging:doPTLundMerging", False, hidden=True, always_write_to_card=False) 1660 1661 # Special Pythia8 paremeters useful to simplify the shower. 1662 self.add_param("BeamRemnants:primordialKT", True, hidden=True, always_write_to_card=False, comment="see http://home.thep.lu.se/~torbjorn/pythia82html/BeamRemnants.html") 1663 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") 1664 self.add_param("Check:event", True, hidden=True, always_write_to_card=False, comment="check physical sanity of the events") 1665 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") 1666 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") 1667 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") 1668 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") 1669 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") 1670 self.add_param("ProcessLevel:resonanceDecays", True, hidden=True, always_write_to_card=False, comment="Do not allow unstable particle to decay.") 1671 1672 # Add parameters controlling the subruns execution flow. 1673 # These parameters should not be part of PY8SubRun daughter. 1674 self.add_default_subruns('parameters')
1675
1676 - def __init__(self, *args, **opts):
1677 # Parameters which are not printed in the card unless they are 1678 # 'user_set' or 'system_set' or part of the 1679 # self.hidden_params_to_always_print set. 1680 self.hidden_param = [] 1681 self.hidden_params_to_always_write = set() 1682 self.visible_params_to_always_write = set() 1683 # List of parameters that should never be written out given the current context. 1684 self.params_to_never_write = set() 1685 1686 # Parameters which have been set by the system (i.e. MG5 itself during 1687 # the regular course of the shower interface) 1688 self.system_set = set() 1689 1690 # Add attributes controlling the subruns execution flow. 1691 # These attributes should not be part of PY8SubRun daughter. 1692 self.add_default_subruns('attributes') 1693 1694 # Parameters which have been set by the 1695 super(PY8Card, self).__init__(*args, **opts)
1696
1697 - def add_param(self, name, value, hidden=False, always_write_to_card=True, 1698 comment=None):
1699 """ add a parameter to the card. value is the default value and 1700 defines the type (int/float/bool/str) of the input. 1701 The option 'hidden' decides whether the parameter should be visible to the user. 1702 The option 'always_write_to_card' decides whether it should 1703 always be printed or only when it is system_set or user_set. 1704 The option 'comment' can be used to specify a comment to write above 1705 hidden parameters. 1706 """ 1707 super(PY8Card, self).add_param(name, value, comment=comment) 1708 name = name.lower() 1709 if hidden: 1710 self.hidden_param.append(name) 1711 if always_write_to_card: 1712 self.hidden_params_to_always_write.add(name) 1713 else: 1714 if always_write_to_card: 1715 self.visible_params_to_always_write.add(name) 1716 if not comment is None: 1717 if not isinstance(comment, str): 1718 raise MadGraph5Error("Option 'comment' must be a string, not"+\ 1719 " '%s'."%str(comment))
1720
1721 - def add_subrun(self, py8_subrun):
1722 """Add a subrun to this PY8 Card.""" 1723 assert(isinstance(py8_subrun,PY8SubRun)) 1724 if py8_subrun['Main:subrun']==-1: 1725 raise MadGraph5Error, "Make sure to correctly set the subrun ID"+\ 1726 " 'Main:subrun' *before* adding it to the PY8 Card." 1727 if py8_subrun['Main:subrun'] in self.subruns: 1728 raise MadGraph5Error, "A subrun with ID '%s'"%py8_subrun['Main:subrun']+\ 1729 " is already present in this PY8 card. Remove it first, or "+\ 1730 " access it directly." 1731 self.subruns[py8_subrun['Main:subrun']] = py8_subrun 1732 if not 'LHEFInputs:nSubruns' in self.user_set: 1733 self['LHEFInputs:nSubruns'] = max(self.subruns.keys())
1734
1735 - def userSet(self, name, value, **opts):
1736 """Set an attribute of this card, following a user_request""" 1737 self.__setitem__(name, value, change_userdefine=True, **opts) 1738 if name.lower() in self.system_set: 1739 self.system_set.remove(name.lower())
1740
1741 - def vetoParamWriteOut(self, name):
1742 """ Forbid the writeout of a specific parameter of this card when the 1743 "write" function will be invoked.""" 1744 self.params_to_never_write.add(name.lower())
1745
1746 - def systemSet(self, name, value, **opts):
1747 """Set an attribute of this card, independently of a specific user 1748 request and only if not already user_set.""" 1749 try: 1750 force = opts.pop('force') 1751 except KeyError: 1752 force = False 1753 if force or name.lower() not in self.user_set: 1754 self.__setitem__(name, value, change_userdefine=False, **opts) 1755 self.system_set.add(name.lower())
1756
1757 - def MadGraphSet(self, name, value, **opts):
1758 """ Sets a card attribute, but only if it is absent or not already 1759 user_set.""" 1760 try: 1761 force = opts.pop('force') 1762 except KeyError: 1763 force = False 1764 if name.lower() not in self or (force or name.lower() not in self.user_set): 1765 self.__setitem__(name, value, change_userdefine=False, **opts) 1766 self.system_set.add(name.lower())
1767
1768 - def defaultSet(self, name, value, **opts):
1769 self.__setitem__(name, value, change_userdefine=False, **opts)
1770 1771 @staticmethod
1772 - def pythia8_formatting(value, formatv=None):
1773 """format the variable into pythia8 card convention. 1774 The type is detected by default""" 1775 if not formatv: 1776 if isinstance(value,UnknownType): 1777 formatv = 'unknown' 1778 elif isinstance(value, bool): 1779 formatv = 'bool' 1780 elif isinstance(value, int): 1781 formatv = 'int' 1782 elif isinstance(value, float): 1783 formatv = 'float' 1784 elif isinstance(value, str): 1785 formatv = 'str' 1786 elif isinstance(value, list): 1787 formatv = 'list' 1788 else: 1789 logger.debug("unknow format for pythia8_formatting: %s" , value) 1790 formatv = 'str' 1791 else: 1792 assert formatv 1793 1794 if formatv == 'unknown': 1795 # No formatting then 1796 return str(value) 1797 if formatv == 'bool': 1798 if str(value) in ['1','T','.true.','True','on']: 1799 return 'on' 1800 else: 1801 return 'off' 1802 elif formatv == 'int': 1803 try: 1804 return str(int(value)) 1805 except ValueError: 1806 fl = float(value) 1807 if int(fl) == fl: 1808 return str(int(fl)) 1809 else: 1810 raise 1811 elif formatv == 'float': 1812 return '%.10e' % float(value) 1813 elif formatv == 'shortfloat': 1814 return '%.3f' % float(value) 1815 elif formatv == 'str': 1816 return "%s" % value 1817 elif formatv == 'list': 1818 if len(value) and isinstance(value[0],float): 1819 return ','.join([PY8Card.pythia8_formatting(arg, 'shortfloat') for arg in value]) 1820 else: 1821 return ','.join([PY8Card.pythia8_formatting(arg) for arg in value])
1822 1823
1824 - def write(self, output_file, template, read_subrun=False, 1825 print_only_visible=False, direct_pythia_input=False, add_missing=True):
1826 """ Write the card to output_file using a specific template. 1827 > 'print_only_visible' specifies whether or not the hidden parameters 1828 should be written out if they are in the hidden_params_to_always_write 1829 list and system_set. 1830 > If 'direct_pythia_input' is true, then visible parameters which are not 1831 in the self.visible_params_to_always_write list and are not user_set 1832 or system_set are commented. 1833 > If 'add_missing' is False then parameters that should be written_out but are absent 1834 from the template will not be written out.""" 1835 1836 # First list the visible parameters 1837 visible_param = [p for p in self if p.lower() not in self.hidden_param 1838 or p.lower() in self.user_set] 1839 # Filter against list of parameters vetoed for write-out 1840 visible_param = [p for p in visible_param if p.lower() not in self.params_to_never_write] 1841 1842 # Now the hidden param which must be written out 1843 if print_only_visible: 1844 hidden_output_param = [] 1845 else: 1846 hidden_output_param = [p for p in self if p.lower() in self.hidden_param and 1847 not p.lower() in self.user_set and 1848 (p.lower() in self.hidden_params_to_always_write or 1849 p.lower() in self.system_set)] 1850 # Filter against list of parameters vetoed for write-out 1851 hidden_output_param = [p for p in hidden_output_param if p not in self.params_to_never_write] 1852 1853 if print_only_visible: 1854 subruns = [] 1855 else: 1856 if not read_subrun: 1857 subruns = sorted(self.subruns.keys()) 1858 1859 # Store the subruns to write in a dictionary, with its ID in key 1860 # and the corresponding stringstream in value 1861 subruns_to_write = {} 1862 1863 # Sort these parameters nicely so as to put together parameters 1864 # belonging to the same group (i.e. prefix before the ':' in their name). 1865 def group_params(params): 1866 if len(params)==0: 1867 return [] 1868 groups = {} 1869 for p in params: 1870 try: 1871 groups[':'.join(p.split(':')[:-1])].append(p) 1872 except KeyError: 1873 groups[':'.join(p.split(':')[:-1])] = [p,] 1874 res = sum(groups.values(),[]) 1875 # Make sure 'Main:subrun' appears first 1876 if 'Main:subrun' in res: 1877 res.insert(0,res.pop(res.index('Main:subrun'))) 1878 # Make sure 'LHEFInputs:nSubruns' appears last 1879 if 'LHEFInputs:nSubruns' in res: 1880 res.append(res.pop(res.index('LHEFInputs:nSubruns'))) 1881 return res
1882 1883 visible_param = group_params(visible_param) 1884 hidden_output_param = group_params(hidden_output_param) 1885 1886 # First dump in a temporary_output (might need to have a second pass 1887 # at the very end to update 'LHEFInputs:nSubruns') 1888 output = StringIO.StringIO() 1889 1890 # Setup template from which to read 1891 if isinstance(template, str): 1892 if os.path.isfile(template): 1893 tmpl = open(template, 'r') 1894 elif '\n' in template: 1895 tmpl = StringIO.StringIO(template) 1896 else: 1897 raise Exception, "File input '%s' not found." % file_input 1898 elif template is None: 1899 # Then use a dummy empty StringIO, hence skipping the reading 1900 tmpl = StringIO.StringIO() 1901 elif isinstance(template, (StringIO.StringIO, file)): 1902 tmpl = template 1903 else: 1904 raise MadGraph5Error("Incorrect type for argument 'template': %s"% 1905 template.__class__.__name__) 1906 1907 # Read the template 1908 last_pos = tmpl.tell() 1909 line = tmpl.readline() 1910 started_subrun_reading = False 1911 while line!='': 1912 # Skip comments 1913 if line.strip().startswith('!') or \ 1914 line.strip().startswith('\n') or\ 1915 line.strip() == '': 1916 output.write(line) 1917 # Proceed to next line 1918 last_pos = tmpl.tell() 1919 line = tmpl.readline() 1920 continue 1921 # Read parameter 1922 try: 1923 param_entry, value_entry = line.split('=') 1924 param = param_entry.strip() 1925 value = value_entry.strip() 1926 except ValueError: 1927 line = line.replace('\n','') 1928 raise MadGraph5Error, "Could not read line '%s' of Pythia8 card."%\ 1929 line 1930 # Read a subrun if detected: 1931 if param=='Main:subrun': 1932 if read_subrun: 1933 if not started_subrun_reading: 1934 # Record that the subrun reading has started and proceed 1935 started_subrun_reading = True 1936 else: 1937 # We encountered the next subrun. rewind last line and exit 1938 tmpl.seek(last_pos) 1939 break 1940 else: 1941 # Start the reading of this subrun 1942 tmpl.seek(last_pos) 1943 subruns_to_write[int(value)] = StringIO.StringIO() 1944 if int(value) in subruns: 1945 self.subruns[int(value)].write(subruns_to_write[int(value)], 1946 tmpl,read_subrun=True) 1947 # Remove this subrun ID from the list 1948 subruns.pop(subruns.index(int(value))) 1949 else: 1950 # Unknow subrun, create a dummy one 1951 DummySubrun=PY8SubRun() 1952 # Remove all of its variables (so that nothing is overwritten) 1953 DummySubrun.clear() 1954 DummySubrun.write(subruns_to_write[int(value)], 1955 tmpl, read_subrun=True, 1956 print_only_visible=print_only_visible, 1957 direct_pythia_input=direct_pythia_input) 1958 1959 logger.info('Adding new unknown subrun with ID %d.'% 1960 int(value)) 1961 # Proceed to next line 1962 last_pos = tmpl.tell() 1963 line = tmpl.readline() 1964 continue 1965 1966 # Change parameters which must be output 1967 if param in visible_param: 1968 new_value = PY8Card.pythia8_formatting(self[param]) 1969 visible_param.pop(visible_param.index(param)) 1970 elif param in hidden_output_param: 1971 new_value = PY8Card.pythia8_formatting(self[param]) 1972 hidden_output_param.pop(hidden_output_param.index(param)) 1973 else: 1974 # Just copy parameters which don't need to be specified 1975 if param.lower() not in self.params_to_never_write: 1976 output.write(line) 1977 else: 1978 output.write('! The following parameter was forced to be commented out by MG5aMC.\n') 1979 output.write('! %s'%line) 1980 # Proceed to next line 1981 last_pos = tmpl.tell() 1982 line = tmpl.readline() 1983 continue 1984 1985 # Substitute the value. 1986 # If it is directly the pytia input, then don't write the param if it 1987 # is not in the list of visible_params_to_always_write and was 1988 # not user_set or system_set 1989 if ((not direct_pythia_input) or 1990 (param.lower() in self.visible_params_to_always_write) or 1991 (param.lower() in self.user_set) or 1992 (param.lower() in self.system_set)): 1993 template = '%s=%s' 1994 else: 1995 # These are parameters that the user can edit in AskEditCards 1996 # but if neither the user nor the system edited them, 1997 # then they shouldn't be passed to Pythia 1998 template = '!%s=%s' 1999 2000 output.write(template%(param_entry, 2001 value_entry.replace(value,new_value))) 2002 2003 # Proceed to next line 2004 last_pos = tmpl.tell() 2005 line = tmpl.readline() 2006 2007 # If add_missing is False, make sure to empty the list of remaining parameters 2008 if not add_missing: 2009 visible_param = [] 2010 hidden_output_param = [] 2011 2012 # Now output the missing parameters. Warn about visible ones. 2013 if len(visible_param)>0 and not template is None: 2014 output.write( 2015 """! 2016 ! Additional general parameters%s. 2017 ! 2018 """%(' for subrun %d'%self['Main:subrun'] if 'Main:subrun' in self else '')) 2019 for param in visible_param: 2020 value = PY8Card.pythia8_formatting(self[param]) 2021 output.write('%s=%s\n'%(param,value)) 2022 if template is None: 2023 if param=='Main:subrun': 2024 output.write( 2025 """! 2026 ! Definition of subrun %d 2027 ! 2028 """%self['Main:subrun']) 2029 elif param.lower() not in self.hidden_param: 2030 logger.debug('Adding parameter %s (missing in the template) to current '+\ 2031 'pythia8 card (with value %s)',param, value) 2032 2033 if len(hidden_output_param)>0 and not template is None: 2034 output.write( 2035 """! 2036 ! Additional technical parameters%s set by MG5_aMC. 2037 ! 2038 """%(' for subrun %d'%self['Main:subrun'] if 'Main:subrun' in self else '')) 2039 for param in hidden_output_param: 2040 if param.lower() in self.comments: 2041 comment = '\n'.join('! %s'%c for c in 2042 self.comments[param.lower()].split('\n')) 2043 output.write(comment+'\n') 2044 output.write('%s=%s\n'%(param,PY8Card.pythia8_formatting(self[param]))) 2045 2046 # Don't close the file if we were reading a subrun, but simply write 2047 # output and return now 2048 if read_subrun: 2049 output_file.write(output.getvalue()) 2050 return 2051 2052 # Now add subruns not present in the template 2053 for subrunID in subruns: 2054 new_subrun = StringIO.StringIO() 2055 self.subruns[subrunID].write(new_subrun,None,read_subrun=True) 2056 subruns_to_write[subrunID] = new_subrun 2057 2058 # Add all subruns to the output, in the right order 2059 for subrunID in sorted(subruns_to_write): 2060 output.write(subruns_to_write[subrunID].getvalue()) 2061 2062 # If 'LHEFInputs:nSubruns' is not user_set, then make sure it is 2063 # updated at least larger or equal to the maximum SubRunID 2064 if 'LHEFInputs:nSubruns'.lower() not in self.user_set and \ 2065 len(subruns_to_write)>0 and 'LHEFInputs:nSubruns' in self\ 2066 and self['LHEFInputs:nSubruns']<max(subruns_to_write.keys()): 2067 logger.info("Updating PY8 parameter 'LHEFInputs:nSubruns' to "+ 2068 "%d so as to cover all defined subruns."%max(subruns_to_write.keys())) 2069 self['LHEFInputs:nSubruns'] = max(subruns_to_write.keys()) 2070 output = StringIO.StringIO() 2071 self.write(output,template,print_only_visible=print_only_visible) 2072 2073 # Write output 2074 if isinstance(output_file, str): 2075 out = open(output_file,'w') 2076 out.write(output.getvalue()) 2077 out.close() 2078 else: 2079 output_file.write(output.getvalue())
2080
2081 - def read(self, file_input, read_subrun=False, setter='default'):
2082 """Read the input file, this can be a path to a file, 2083 a file object, a str with the content of the file. 2084 The setter option choses the authority that sets potential 2085 modified/new parameters. It can be either: 2086 'default' or 'user' or 'system'""" 2087 if isinstance(file_input, str): 2088 if "\n" in file_input: 2089 finput = StringIO.StringIO(file_input) 2090 elif os.path.isfile(file_input): 2091 finput = open(file_input) 2092 else: 2093 raise Exception, "File input '%s' not found." % file_input 2094 elif isinstance(file_input, (StringIO.StringIO, file)): 2095 finput = file_input 2096 else: 2097 raise MadGraph5Error("Incorrect type for argument 'file_input': %s"% 2098 file_input.__class__.__name__) 2099 2100 # Read the template 2101 last_pos = finput.tell() 2102 line = finput.readline() 2103 started_subrun_reading = False 2104 while line!='': 2105 # Skip comments 2106 if line.strip().startswith('!') or line.strip()=='': 2107 # proceed to next line 2108 last_pos = finput.tell() 2109 line = finput.readline() 2110 continue 2111 # Read parameter 2112 try: 2113 param, value = line.split('=',1) 2114 param = param.strip() 2115 value = value.strip() 2116 except ValueError: 2117 line = line.replace('\n','') 2118 raise MadGraph5Error, "Could not read line '%s' of Pythia8 card."%\ 2119 line 2120 if '!' in value: 2121 value,_ = value.split('!',1) 2122 2123 # Read a subrun if detected: 2124 if param=='Main:subrun': 2125 if read_subrun: 2126 if not started_subrun_reading: 2127 # Record that the subrun reading has started and proceed 2128 started_subrun_reading = True 2129 else: 2130 # We encountered the next subrun. rewind last line and exit 2131 finput.seek(last_pos) 2132 return 2133 else: 2134 # Start the reading of this subrun 2135 finput.seek(last_pos) 2136 if int(value) in self.subruns: 2137 self.subruns[int(value)].read(finput,read_subrun=True, 2138 setter=setter) 2139 else: 2140 # Unknow subrun, create a dummy one 2141 NewSubrun=PY8SubRun() 2142 NewSubrun.read(finput,read_subrun=True, setter=setter) 2143 self.add_subrun(NewSubrun) 2144 2145 # proceed to next line 2146 last_pos = finput.tell() 2147 line = finput.readline() 2148 continue 2149 2150 # Read parameter. The case of a parameter not defined in the card is 2151 # handled directly in ConfigFile. 2152 2153 # Use the appropriate authority to set the new/changed variable 2154 if setter == 'user': 2155 self.userSet(param,value) 2156 elif setter == 'system': 2157 self.systemSet(param,value) 2158 else: 2159 self.defaultSet(param,value) 2160 2161 # proceed to next line 2162 last_pos = finput.tell() 2163 line = finput.readline()
2164
2165 -class PY8SubRun(PY8Card):
2166 """ Class to characterize a specific PY8 card subrun section. """ 2167
2168 - def add_default_subruns(self, type):
2169 """ Overloading of the homonym function called in the __init__ of PY8Card. 2170 The initialization of the self.subruns attribute should of course not 2171 be performed in PY8SubRun.""" 2172 pass
2173
2174 - def __init__(self, *args, **opts):
2175 """ Initialize a subrun """ 2176 2177 # Force user to set it manually. 2178 subrunID = -1 2179 if 'subrun_id' in opts: 2180 subrunID = opts.pop('subrun_id') 2181 2182 super(PY8SubRun, self).__init__(*args, **opts) 2183 self['Main:subrun']=subrunID
2184
2185 - def default_setup(self):
2186 """Sets up the list of available PY8SubRun parameters.""" 2187 2188 # Add all default PY8Card parameters 2189 super(PY8SubRun, self).default_setup() 2190 # Make sure they are all hidden 2191 self.hidden_param = [k.lower() for k in self.keys()] 2192 self.hidden_params_to_always_write = set() 2193 self.visible_params_to_always_write = set() 2194 2195 # Now add Main:subrun and Beams:LHEF. They are not hidden. 2196 self.add_param("Main:subrun", -1) 2197 self.add_param("Beams:LHEF", "events.lhe.gz")
2198 2199 2200 2201 runblock = collections.namedtuple('block', ('name', 'fields', 'template_on', 'template_off'))
2202 -class RunCard(ConfigFile):
2203 2204 filename = 'run_card' 2205 blocks = [] 2206
2207 - def __new__(cls, finput=None, **opt):
2208 if cls is RunCard: 2209 if not finput: 2210 target_class = RunCardLO 2211 elif isinstance(finput, cls): 2212 target_class = finput.__class__ 2213 elif isinstance(finput, str): 2214 if '\n' not in finput: 2215 finput = open(finput).read() 2216 if 'req_acc_FO' in finput: 2217 target_class = RunCardNLO 2218 else: 2219 target_class = RunCardLO 2220 else: 2221 return None 2222 return super(RunCard, cls).__new__(target_class, finput, **opt) 2223 else: 2224 return super(RunCard, cls).__new__(cls, finput, **opt)
2225
2226 - def __init__(self, *args, **opts):
2227 2228 # The following parameter are updated in the defaultsetup stage. 2229 2230 #parameter for which no warning should be raised if not define 2231 self.hidden_param = [] 2232 # in which include file the parameer should be written 2233 self.includepath = collections.defaultdict(list) 2234 #some parameter have different name in fortran code 2235 self.fortran_name = {} 2236 #parameter which are not supported anymore. (no action on the code) 2237 self.legacy_parameter = {} 2238 #a list with all the cuts variable 2239 self.cuts_parameter = [] 2240 # parameter added where legacy requires an older value. 2241 self.system_default = {} 2242 2243 self.display_block = [] # set some block to be displayed 2244 self.warned=False 2245 2246 2247 super(RunCard, self).__init__(*args, **opts)
2248
2249 - def add_param(self, name, value, fortran_name=None, include=True, 2250 hidden=False, legacy=False, cut=False, system=False, sys_default=None, 2251 **opts):
2252 """ add a parameter to the card. value is the default value and 2253 defines the type (int/float/bool/str) of the input. 2254 fortran_name defines what is the associate name in the f77 code 2255 include defines if we have to put the value in the include file 2256 hidden defines if the parameter is expected to be define by the user. 2257 legacy:Parameter which is not used anymore (raise a warning if not default) 2258 cut: defines the list of cut parameter to allow to set them all to off. 2259 sys_default: default used if the parameter is not in the card 2260 2261 options of **opts: 2262 - allowed: list of valid options. '*' means anything else should be allowed. 2263 empty list means anything possible as well. 2264 - comment: add comment for writing/help 2265 - typelist: type of the list if default is empty 2266 """ 2267 2268 super(RunCard, self).add_param(name, value, system=system,**opts) 2269 name = name.lower() 2270 if fortran_name: 2271 self.fortran_name[name] = fortran_name 2272 if legacy: 2273 self.legacy_parameter[name] = value 2274 include = False 2275 self.includepath[include].append(name) 2276 if hidden or system: 2277 self.hidden_param.append(name) 2278 if cut: 2279 self.cuts_parameter.append(name) 2280 if sys_default is not None: 2281 self.system_default[name] = sys_default
2282 2283 2284
2285 - def read(self, finput, consistency=True):
2286 """Read the input file, this can be a path to a file, 2287 a file object, a str with the content of the file.""" 2288 2289 if isinstance(finput, str): 2290 if "\n" in finput: 2291 finput = finput.split('\n') 2292 elif os.path.isfile(finput): 2293 finput = open(finput) 2294 else: 2295 raise Exception, "No such file %s" % finput 2296 2297 for line in finput: 2298 line = line.split('#')[0] 2299 line = line.split('!')[0] 2300 line = line.rsplit('=',1) 2301 if len(line) != 2: 2302 continue 2303 value, name = line 2304 name = name.lower().strip() 2305 if name not in self and ('min' in name or 'max' in name): 2306 #looks like an entry added by one user -> add it nicely 2307 self.add_param(name, float(value), hidden=True, cut=True) 2308 else: 2309 self.set( name, value, user=True) 2310 # parameter not set in the run_card can be set to compatiblity value 2311 if consistency: 2312 try: 2313 self.check_validity() 2314 except InvalidRunCard, error: 2315 if consistency == 'warning': 2316 logger.warning(str(error)) 2317 else: 2318 raise
2319 2320
2321 - def write(self, output_file, template=None, python_template=False, 2322 write_hidden=False):
2323 """Write the run_card in output_file according to template 2324 (a path to a valid run_card)""" 2325 2326 to_write = set(self.user_set) 2327 written = set() 2328 if not template: 2329 raise Exception 2330 2331 # check which optional block to write: 2332 write_block= [] 2333 for b in self.blocks: 2334 name = b.name 2335 # check if the block has to be written 2336 if name not in self.display_block and \ 2337 not any(f in self.user_set for f in b.fields): 2338 continue 2339 write_block.append(b.name) 2340 2341 if python_template and not to_write: 2342 import string 2343 text = file(template,'r').read() 2344 if self.blocks: 2345 text = string.Template(text) 2346 mapping = {} 2347 for b in self.blocks: 2348 if b.name in write_block: 2349 mapping[b.name] = b.template_on 2350 else: 2351 mapping[b.name] = b.template_off 2352 text = text.substitute(mapping) 2353 2354 if not self.list_parameter: 2355 text = text % self 2356 else: 2357 data = dict(self) 2358 for name in self.list_parameter: 2359 if self.list_parameter[name] != str: 2360 data[name] = ', '.join(str(v) for v in data[name]) 2361 else: 2362 data[name] = "['%s']" % "', '".join(str(v) for v in data[name]) 2363 text = text % data 2364 else: 2365 text = "" 2366 for line in file(template,'r'): 2367 nline = line.split('#')[0] 2368 nline = nline.split('!')[0] 2369 comment = line[len(nline):] 2370 nline = nline.split('=') 2371 if python_template and nline[0].startswith('$'): 2372 block_name = nline[0][1:] 2373 this_group = [b for b in self.blocks if b.name == block_name] 2374 if not this_group: 2375 logger.debug("block %s not defined", block_name) 2376 continue 2377 else: 2378 this_group = this_group[0] 2379 if block_name in write_block: 2380 text += this_group.template_on % self 2381 for name in this_group.fields: 2382 written.add(name) 2383 if name in to_write: 2384 to_write.remove(name) 2385 else: 2386 text += this_group.template_off % self 2387 2388 elif len(nline) != 2: 2389 text += line 2390 elif nline[1].strip() in self: 2391 name = nline[1].strip().lower() 2392 value = self[name] 2393 if name in self.list_parameter: 2394 if self.list_parameter[name] != str: 2395 value = ', '.join([str(v) for v in value]) 2396 else: 2397 value = "['%s']" % "', '".join(str(v) for v in value) 2398 if python_template: 2399 text += line % {nline[1].strip():value, name:value} 2400 written.add(name) 2401 else: 2402 if not comment or comment[-1]!='\n': 2403 endline = '\n' 2404 else: 2405 endline = '' 2406 text += ' %s\t= %s %s%s' % (value, name, comment, endline) 2407 written.add(name) 2408 2409 if name in to_write: 2410 to_write.remove(name) 2411 else: 2412 logger.info('Adding missing parameter %s to current %s (with default value)', 2413 (name, self.filename)) 2414 written.add(name) 2415 text += line 2416 2417 for b in self.blocks: 2418 if b.name not in write_block: 2419 continue 2420 # check if all attribute of the block have been written already 2421 if all(f in written for f in b.fields): 2422 continue 2423 2424 to_add = [] 2425 for line in b.template_on.split('\n'): 2426 nline = line.split('#')[0] 2427 nline = nline.split('!')[0] 2428 nline = nline.split('=') 2429 if len(nline) != 2: 2430 to_add.append(line) 2431 elif nline[1].strip() in self: 2432 name = nline[1].strip().lower() 2433 value = self[name] 2434 if name in self.list_parameter: 2435 value = ', '.join([str(v) for v in value]) 2436 if name in written: 2437 continue #already include before 2438 else: 2439 to_add.append(line % {nline[1].strip():value, name:value}) 2440 written.add(name) 2441 2442 if name in to_write: 2443 to_write.remove(name) 2444 else: 2445 raise Exception 2446 2447 if b.template_off in text: 2448 text = text.replace(b.template_off, '\n'.join(to_add)) 2449 else: 2450 text += '\n'.join(to_add) 2451 2452 if to_write or write_hidden: 2453 text+="""#********************************************************************* 2454 # Additional hidden parameters 2455 #********************************************************************* 2456 """ 2457 if write_hidden: 2458 # 2459 # do not write hidden parameter not hidden for this template 2460 # 2461 if python_template: 2462 written = written.union(set(re.findall('\%\((\w*)\)s', file(template,'r').read(), re.M))) 2463 to_write = to_write.union(set(self.hidden_param)) 2464 to_write = to_write.difference(written) 2465 2466 for key in to_write: 2467 if key in self.system_only: 2468 continue 2469 2470 comment = self.comments.get(key,'hidden_parameter').replace('\n','\n#') 2471 text += ' %s\t= %s # %s\n' % (self[key], key, comment) 2472 2473 if isinstance(output_file, str): 2474 fsock = open(output_file,'w') 2475 fsock.write(text) 2476 fsock.close() 2477 else: 2478 output_file.write(text)
2479 2480
2481 - def get_default(self, name, default=None, log_level=None):
2482 """return self[name] if exist otherwise default. log control if we 2483 put a warning or not if we use the default value""" 2484 2485 lower_name = name.lower() 2486 if lower_name not in self.user_set: 2487 if log_level is None: 2488 if lower_name in self.system_only: 2489 log_level = 5 2490 elif lower_name in self.auto_set: 2491 log_level = 5 2492 elif lower_name in self.hidden_param: 2493 log_level = 10 2494 else: 2495 log_level = 20 2496 if not default: 2497 default = dict.__getitem__(self, name.lower()) 2498 2499 logger.log(log_level, '%s missed argument %s. Takes default: %s' 2500 % (self.filename, name, default)) 2501 self[name] = default 2502 return default 2503 else: 2504 return self[name]
2505 2506 2507 @staticmethod
2508 - def f77_formatting(value, formatv=None):
2509 """format the variable into fortran. The type is detected by default""" 2510 2511 if not formatv: 2512 if isinstance(value, bool): 2513 formatv = 'bool' 2514 elif isinstance(value, int): 2515 formatv = 'int' 2516 elif isinstance(value, float): 2517 formatv = 'float' 2518 elif isinstance(value, str): 2519 formatv = 'str' 2520 else: 2521 logger.debug("unknow format for f77_formatting: %s" , str(value)) 2522 formatv = 'str' 2523 else: 2524 assert formatv 2525 2526 if formatv == 'bool': 2527 if str(value) in ['1','T','.true.','True']: 2528 return '.true.' 2529 else: 2530 return '.false.' 2531 2532 elif formatv == 'int': 2533 try: 2534 return str(int(value)) 2535 except ValueError: 2536 fl = float(value) 2537 if int(fl) == fl: 2538 return str(int(fl)) 2539 else: 2540 raise 2541 2542 elif formatv == 'float': 2543 if isinstance(value, str): 2544 value = value.replace('d','e') 2545 return ('%.10e' % float(value)).replace('e','d') 2546 2547 elif formatv == 'str': 2548 # Check if it is a list 2549 if value.strip().startswith('[') and value.strip().endswith(']'): 2550 elements = (value.strip()[1:-1]).split() 2551 return ['_length = %d'%len(elements)]+\ 2552 ['(%d) = %s'%(i+1, elem.strip()) for i, elem in \ 2553 enumerate(elements)] 2554 else: 2555 return "'%s'" % value
2556 2557 2558
2559 - def check_validity(self, log_level=30):
2560 """check that parameter missing in the card are set to the expected value""" 2561 2562 for name, value in self.system_default.items(): 2563 self.set(name, value, changeifuserset=False) 2564 2565 2566 for name in self.includepath[False]: 2567 to_bypass = self.hidden_param + self.legacy_parameter.keys() 2568 if name not in to_bypass: 2569 self.get_default(name, log_level=log_level) 2570 2571 for name in self.legacy_parameter: 2572 if self[name] != self.legacy_parameter[name]: 2573 logger.warning("The parameter %s is not supported anymore this parameter will be ignored." % name)
2574 2575 default_include_file = 'run_card.inc' 2576
2578 """update hidden system only parameter for the correct writtin in the 2579 include""" 2580 return
2581
2582 - def write_include_file(self, output_dir):
2583 """Write the various include file in output_dir. 2584 The entry True of self.includepath will be written in run_card.inc 2585 The entry False will not be written anywhere""" 2586 2587 # ensure that all parameter are coherent and fix those if needed 2588 self.check_validity() 2589 2590 #ensusre that system only parameter are correctly set 2591 self.update_system_parameter_for_include() 2592 2593 for incname in self.includepath: 2594 if incname is True: 2595 pathinc = self.default_include_file 2596 elif incname is False: 2597 continue 2598 else: 2599 pathinc = incname 2600 2601 fsock = file_writers.FortranWriter(pjoin(output_dir,pathinc)) 2602 for key in self.includepath[incname]: 2603 #define the fortran name 2604 if key in self.fortran_name: 2605 fortran_name = self.fortran_name[key] 2606 else: 2607 fortran_name = key 2608 2609 #get the value with warning if the user didn't set it 2610 value = self.get_default(key) 2611 # Special treatment for strings containing a list of 2612 # strings. Convert it to a list of strings 2613 if isinstance(value, list): 2614 # in case of a list, add the length of the list as 0th 2615 # element in fortran. Only in case of integer or float 2616 # list (not for bool nor string) 2617 targettype = self.list_parameter[key] 2618 if targettype is bool: 2619 pass 2620 elif targettype is int: 2621 line = '%s(%s) = %s \n' % (fortran_name, 0, self.f77_formatting(len(value))) 2622 fsock.writelines(line) 2623 elif targettype is float: 2624 line = '%s(%s) = %s \n' % (fortran_name, 0, self.f77_formatting(float(len(value)))) 2625 fsock.writelines(line) 2626 # output the rest of the list in fortran 2627 for i,v in enumerate(value): 2628 line = '%s(%s) = %s \n' % (fortran_name, i+1, self.f77_formatting(v)) 2629 fsock.writelines(line) 2630 elif isinstance(value, dict): 2631 for fortran_name, onevalue in value.items(): 2632 line = '%s = %s \n' % (fortran_name, self.f77_formatting(onevalue)) 2633 fsock.writelines(line) 2634 else: 2635 line = '%s = %s \n' % (fortran_name, self.f77_formatting(value)) 2636 fsock.writelines(line) 2637 fsock.close()
2638 2639 @staticmethod
2640 - def get_idbmup(lpp):
2641 """return the particle colliding pdg code""" 2642 if lpp in (1,2, -1,-2): 2643 return math.copysign(2212, lpp) 2644 elif lpp in (3,-3): 2645 return math.copysign(11, lpp) 2646 elif lpp == 0: 2647 #logger.critical("Fail to write correct idbmup in the lhe file. Please correct those by hand") 2648 return 0 2649 else: 2650 return lpp
2651
2653 """return a dictionary with the information needed to write 2654 the first line of the <init> block of the lhe file.""" 2655 2656 output = {} 2657 output["idbmup1"] = self.get_idbmup(self['lpp1']) 2658 output["idbmup2"] = self.get_idbmup(self['lpp2']) 2659 output["ebmup1"] = self["ebeam1"] 2660 output["ebmup2"] = self["ebeam2"] 2661 output["pdfgup1"] = 0 2662 output["pdfgup2"] = 0 2663 output["pdfsup1"] = self.get_pdf_id(self["pdlabel"]) 2664 output["pdfsup2"] = self.get_pdf_id(self["pdlabel"]) 2665 return output
2666
2667 - def get_pdf_id(self, pdf):
2668 if pdf == "lhapdf": 2669 lhaid = self["lhaid"] 2670 if isinstance(lhaid, list): 2671 return lhaid[0] 2672 else: 2673 return lhaid 2674 else: 2675 return {'none': 0, 2676 'cteq6_m':10000,'cteq6_l':10041,'cteq6l1':10042, 2677 'nn23lo':246800,'nn23lo1':247000,'nn23nlo':244800 2678 }[pdf]
2679
2680 - def get_lhapdf_id(self):
2681 return self.get_pdf_id(self['pdlabel'])
2682
2683 - def remove_all_cut(self):
2684 """remove all the cut""" 2685 2686 for name in self.cuts_parameter: 2687 targettype = type(self[name]) 2688 if targettype == bool: 2689 self[name] = False 2690 elif 'min' in name: 2691 self[name] = 0 2692 elif 'max' in name: 2693 self[name] = -1 2694 elif 'eta' in name: 2695 self[name] = -1 2696 else: 2697 self[name] = 0
2698
2699 -class RunCardLO(RunCard):
2700 """an object to handle in a nice way the run_card information""" 2701 2702 blocks = [ 2703 # HEAVY ION OPTIONAL BLOCK 2704 runblock(name='ion_pdf', fields=('nb_neutron1', 'nb_neutron2','nb_proton1','nb_proton2','mass_ion1', 'mass_ion2'), 2705 template_on=\ 2706 """#********************************************************************* 2707 # Heavy ion PDF / rescaling of PDF * 2708 #********************************************************************* 2709 %(nb_proton1)s = nb_proton1 # number of proton for the first beam 2710 %(nb_neutron1)s = nb_neutron1 # number of neutron for the first beam 2711 %(mass_ion1)s = mass_ion1 # mass of the heavy ion (first beam) 2712 # Note that seting differently the two beams only work if you use 2713 # group_subprocess=False when generating your matrix-element 2714 %(nb_proton2)s = nb_proton2 # number of proton for the second beam 2715 %(nb_neutron2)s = nb_neutron2 # number of neutron for the second beam 2716 %(mass_ion2)s = mass_ion2 # mass of the heavy ion (second beam) 2717 """, 2718 template_off='# To see heavy ion options: type "update ion_pdf"'), 2719 2720 2721 # BEAM POLARIZATION OPTIONAL BLOCK 2722 runblock(name='beam_pol', fields=('polbeam1','polbeam2'), 2723 template_on=\ 2724 """#********************************************************************* 2725 # Beam polarization from -100 (left-handed) to 100 (right-handed) * 2726 #********************************************************************* 2727 %(polbeam1)s = polbeam1 ! beam polarization for beam 1 2728 %(polbeam2)s = polbeam2 ! beam polarization for beam 2 2729 """, 2730 template_off='# To see polarised beam options: type "update beam_pol"'), 2731 2732 # SYSCALC OPTIONAL BLOCK 2733 runblock(name='syscalc', fields=('sys_scalefact', 'sys_alpsfact','sys_matchscale','sys_pdf'), 2734 template_on=\ 2735 """#************************************** 2736 # Parameter below of the systematics study 2737 # will be used by SysCalc (if installed) 2738 #************************************** 2739 # 2740 %(sys_scalefact)s = sys_scalefact # factorization/renormalization scale factor 2741 %(sys_alpsfact)s = sys_alpsfact # \alpha_s emission scale factors 2742 %(sys_matchscale)s = sys_matchscale # variation of merging scale 2743 # PDF sets and number of members (0 or none for all members). 2744 %(sys_pdf)s = sys_pdf # list of pdf sets. (errorset not valid for syscalc) 2745 # MSTW2008nlo68cl.LHgrid 1 = sys_pdf 2746 # 2747 """, 2748 template_off= '# Syscalc is deprecated but to see the associate options type\'update syscalc\''), 2749 ] 2750 2751 2752
2753 - def default_setup(self):
2754 """default value for the run_card.dat""" 2755 2756 self.add_param("run_tag", "tag_1", include=False) 2757 self.add_param("gridpack", False) 2758 self.add_param("time_of_flight", -1.0, include=False) 2759 self.add_param("nevents", 10000) 2760 self.add_param("iseed", 0) 2761 self.add_param("python_seed", -1, 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") 2762 self.add_param("lpp1", 1, fortran_name="lpp(1)", allowed=[-1,1,0,2,3,9, -2,-3], 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("lpp2", 1, fortran_name="lpp(2)", allowed=[-1,1,0,2,3,9], 2765 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') 2766 self.add_param("ebeam1", 6500.0, fortran_name="ebeam(1)") 2767 self.add_param("ebeam2", 6500.0, fortran_name="ebeam(2)") 2768 self.add_param("polbeam1", 0.0, fortran_name="pb1", hidden=True, 2769 comment="Beam polarization from -100 (left-handed) to 100 (right-handed) --use lpp=0 for this parameter--") 2770 self.add_param("polbeam2", 0.0, fortran_name="pb2", hidden=True, 2771 comment="Beam polarization from -100 (left-handed) to 100 (right-handed) --use lpp=0 for this parameter--") 2772 self.add_param('nb_proton1', 1, hidden=True, allowed=[1,0, 82 , '*'],fortran_name="nb_proton(1)", 2773 comment='For heavy ion physics nb of proton in the ion (for both beam but if group_subprocess was False)') 2774 self.add_param('nb_proton2', 1, hidden=True, allowed=[1,0, 82 , '*'],fortran_name="nb_proton(2)", 2775 comment='For heavy ion physics nb of proton in the ion (used for beam 2 if group_subprocess was False)') 2776 self.add_param('nb_neutron1', 0, hidden=True, allowed=[1,0, 126 , '*'],fortran_name="nb_neutron(1)", 2777 comment='For heavy ion physics nb of neutron in the ion (for both beam but if group_subprocess was False)') 2778 self.add_param('nb_neutron2', 0, hidden=True, allowed=[1,0, 126 , '*'],fortran_name="nb_neutron(2)", 2779 comment='For heavy ion physics nb of neutron in the ion (of beam 2 if group_subprocess was False )') 2780 self.add_param('mass_ion1', -1.0, hidden=True, fortran_name="mass_ion(1)", 2781 allowed=[-1,0, 0.938, 207.9766521*0.938, 0.000511, 0.105, '*'], 2782 comment='For heavy ion physics mass in GeV of the ion (of beam 1)') 2783 self.add_param('mass_ion2', -1.0, hidden=True, fortran_name="mass_ion(2)", 2784 allowed=[-1,0, 0.938, 207.9766521*0.938, 0.000511, 0.105, '*'], 2785 comment='For heavy ion physics mass in GeV of the ion (of beam 2)') 2786 2787 self.add_param("pdlabel", "nn23lo1", allowed=['lhapdf', 'cteq6_m','cteq6_l', 'cteq6l1','nn23lo', 'nn23lo1', 'nn23nlo']), 2788 self.add_param("lhaid", 230000, hidden=True) 2789 self.add_param("fixed_ren_scale", False) 2790 self.add_param("fixed_fac_scale", False) 2791 self.add_param("scale", 91.1880) 2792 self.add_param("dsqrt_q2fact1", 91.1880, fortran_name="sf1") 2793 self.add_param("dsqrt_q2fact2", 91.1880, fortran_name="sf2") 2794 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", 2795 allowed=[-1,0,1,2,3,4]) 2796 2797 # Bias module options 2798 self.add_param("bias_module", 'None', include=False) 2799 self.add_param('bias_parameters', {'__type__':1.0}, include='BIAS/bias.inc') 2800 2801 #matching 2802 self.add_param("scalefact", 1.0) 2803 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.") 2804 self.add_param("highestmult", 1, fortran_name="nhmult", hidden=True) 2805 self.add_param("ktscheme", 1, hidden=True) 2806 self.add_param("alpsfact", 1.0) 2807 self.add_param("chcluster", False, hidden=True) 2808 self.add_param("pdfwgt", True, hidden=True) 2809 self.add_param("asrwgtflavor", 5, comment = 'highest quark flavor for a_s reweighting in MLM') 2810 self.add_param("clusinfo", True) 2811 self.add_param("lhe_version", 3.0) 2812 self.add_param("event_norm", "average", allowed=['sum','average', 'unity'], 2813 include=False, sys_default='sum') 2814 #cut 2815 self.add_param("auto_ptj_mjj", False) 2816 self.add_param("bwcutoff", 15.0) 2817 self.add_param("cut_decays", False) 2818 self.add_param("nhel", 0, include=False) 2819 #pt cut 2820 self.add_param("ptj", 20.0, cut=True) 2821 self.add_param("ptb", 0.0, cut=True) 2822 self.add_param("pta", 10.0, cut=True) 2823 self.add_param("ptl", 10.0, cut=True) 2824 self.add_param("misset", 0.0, cut=True) 2825 self.add_param("ptheavy", 0.0, cut=True, comment='this cut apply on particle heavier than 10 GeV') 2826 self.add_param("ptonium", 1.0, legacy=True) 2827 self.add_param("ptjmax", -1.0, cut=True) 2828 self.add_param("ptbmax", -1.0, cut=True) 2829 self.add_param("ptamax", -1.0, cut=True) 2830 self.add_param("ptlmax", -1.0, cut=True) 2831 self.add_param("missetmax", -1.0, cut=True) 2832 # E cut 2833 self.add_param("ej", 0.0, cut=True) 2834 self.add_param("eb", 0.0, cut=True) 2835 self.add_param("ea", 0.0, cut=True) 2836 self.add_param("el", 0.0, cut=True) 2837 self.add_param("ejmax", -1.0, cut=True) 2838 self.add_param("ebmax", -1.0, cut=True) 2839 self.add_param("eamax", -1.0, cut=True) 2840 self.add_param("elmax", -1.0, cut=True) 2841 # Eta cut 2842 self.add_param("etaj", 5.0, cut=True) 2843 self.add_param("etab", -1.0, cut=True) 2844 self.add_param("etaa", 2.5, cut=True) 2845 self.add_param("etal", 2.5, cut=True) 2846 self.add_param("etaonium", 0.6, legacy=True) 2847 self.add_param("etajmin", 0.0, cut=True) 2848 self.add_param("etabmin", 0.0, cut=True) 2849 self.add_param("etaamin", 0.0, cut=True) 2850 self.add_param("etalmin", 0.0, cut=True) 2851 # DRJJ 2852 self.add_param("drjj", 0.4, cut=True) 2853 self.add_param("drbb", 0.0, cut=True) 2854 self.add_param("drll", 0.4, cut=True) 2855 self.add_param("draa", 0.4, cut=True) 2856 self.add_param("drbj", 0.0, cut=True) 2857 self.add_param("draj", 0.4, cut=True) 2858 self.add_param("drjl", 0.4, cut=True) 2859 self.add_param("drab", 0.0, cut=True) 2860 self.add_param("drbl", 0.0, cut=True) 2861 self.add_param("dral", 0.4, cut=True) 2862 self.add_param("drjjmax", -1.0, cut=True) 2863 self.add_param("drbbmax", -1.0, cut=True) 2864 self.add_param("drllmax", -1.0, cut=True) 2865 self.add_param("draamax", -1.0, cut=True) 2866 self.add_param("drbjmax", -1.0, cut=True) 2867 self.add_param("drajmax", -1.0, cut=True) 2868 self.add_param("drjlmax", -1.0, cut=True) 2869 self.add_param("drabmax", -1.0, cut=True) 2870 self.add_param("drblmax", -1.0, cut=True) 2871 self.add_param("dralmax", -1.0, cut=True) 2872 # invariant mass 2873 self.add_param("mmjj", 0.0, cut=True) 2874 self.add_param("mmbb", 0.0, cut=True) 2875 self.add_param("mmaa", 0.0, cut=True) 2876 self.add_param("mmll", 0.0, cut=True) 2877 self.add_param("mmjjmax", -1.0, cut=True) 2878 self.add_param("mmbbmax", -1.0, cut=True) 2879 self.add_param("mmaamax", -1.0, cut=True) 2880 self.add_param("mmllmax", -1.0, cut=True) 2881 self.add_param("mmnl", 0.0, cut=True) 2882 self.add_param("mmnlmax", -1.0, cut=True) 2883 #minimum/max pt for sum of leptons 2884 self.add_param("ptllmin", 0.0, cut=True) 2885 self.add_param("ptllmax", -1.0, cut=True) 2886 self.add_param("xptj", 0.0, cut=True) 2887 self.add_param("xptb", 0.0, cut=True) 2888 self.add_param("xpta", 0.0, cut=True) 2889 self.add_param("xptl", 0.0, cut=True) 2890 # ordered pt jet 2891 self.add_param("ptj1min", 0.0, cut=True) 2892 self.add_param("ptj1max", -1.0, cut=True) 2893 self.add_param("ptj2min", 0.0, cut=True) 2894 self.add_param("ptj2max", -1.0, cut=True) 2895 self.add_param("ptj3min", 0.0, cut=True) 2896 self.add_param("ptj3max", -1.0, cut=True) 2897 self.add_param("ptj4min", 0.0, cut=True) 2898 self.add_param("ptj4max", -1.0, cut=True) 2899 self.add_param("cutuse", 0, cut=True) 2900 # ordered pt lepton 2901 self.add_param("ptl1min", 0.0, cut=True) 2902 self.add_param("ptl1max", -1.0, cut=True) 2903 self.add_param("ptl2min", 0.0, cut=True) 2904 self.add_param("ptl2max", -1.0, cut=True) 2905 self.add_param("ptl3min", 0.0, cut=True) 2906 self.add_param("ptl3max", -1.0, cut=True) 2907 self.add_param("ptl4min", 0.0, cut=True) 2908 self.add_param("ptl4max", -1.0, cut=True) 2909 # Ht sum of jets 2910 self.add_param("htjmin", 0.0, cut=True) 2911 self.add_param("htjmax", -1.0, cut=True) 2912 self.add_param("ihtmin", 0.0, cut=True) 2913 self.add_param("ihtmax", -1.0, cut=True) 2914 self.add_param("ht2min", 0.0, cut=True) 2915 self.add_param("ht3min", 0.0, cut=True) 2916 self.add_param("ht4min", 0.0, cut=True) 2917 self.add_param("ht2max", -1.0, cut=True) 2918 self.add_param("ht3max", -1.0, cut=True) 2919 self.add_param("ht4max", -1.0, cut=True) 2920 # photon isolation 2921 self.add_param("ptgmin", 0.0, cut=True) 2922 self.add_param("r0gamma", 0.4) 2923 self.add_param("xn", 1.0) 2924 self.add_param("epsgamma", 1.0) 2925 self.add_param("isoem", True) 2926 self.add_param("xetamin", 0.0, cut=True) 2927 self.add_param("deltaeta", 0.0, cut=True) 2928 self.add_param("ktdurham", -1.0, fortran_name="kt_durham", cut=True) 2929 self.add_param("dparameter", 0.4, fortran_name="d_parameter", cut=True) 2930 self.add_param("ptlund", -1.0, fortran_name="pt_lund", cut=True) 2931 self.add_param("pdgs_for_merging_cut", [21, 1, 2, 3, 4, 5, 6]) 2932 self.add_param("maxjetflavor", 4) 2933 self.add_param("xqcut", 0.0, cut=True) 2934 self.add_param("use_syst", True) 2935 self.add_param('systematics_program', 'systematics', include=False, hidden=True, comment='Choose which program to use for systematics computation: none, systematics, syscalc') 2936 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.') 2937 2938 self.add_param("sys_scalefact", "0.5 1 2", include=False, hidden=True) 2939 self.add_param("sys_alpsfact", "None", include=False, hidden=True) 2940 self.add_param("sys_matchscale", "auto", include=False, hidden=True) 2941 self.add_param("sys_pdf", "errorset", include=False, hidden=True) 2942 self.add_param("sys_scalecorrelation", -1, include=False, hidden=True) 2943 2944 #parameter not in the run_card by default 2945 self.add_param('gridrun', False, hidden=True) 2946 self.add_param('fixed_couplings', True, hidden=True) 2947 self.add_param('mc_grouped_subproc', True, hidden=True) 2948 self.add_param('xmtcentral', 0.0, hidden=True, fortran_name="xmtc") 2949 self.add_param('d', 1.0, hidden=True) 2950 self.add_param('gseed', 0, hidden=True, include=False) 2951 self.add_param('issgridfile', '', hidden=True) 2952 #job handling of the survey/ refine 2953 self.add_param('job_strategy', 0, hidden=True, include=False, allowed=[0,1,2], comment='see appendix of 1507.00020 (page 26)') 2954 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.") 2955 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") 2956 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)") 2957 2958 # parameter allowing to define simple cut via the pdg 2959 # Special syntax are related to those. (can not be edit directly) 2960 self.add_param('pt_min_pdg',{'__type__':0.}, include=False) 2961 self.add_param('pt_max_pdg',{'__type__':0.}, include=False) 2962 self.add_param('E_min_pdg',{'__type__':0.}, include=False) 2963 self.add_param('E_max_pdg',{'__type__':0.}, include=False) 2964 self.add_param('eta_min_pdg',{'__type__':0.}, include=False) 2965 self.add_param('eta_max_pdg',{'__type__':0.}, include=False) 2966 self.add_param('mxx_min_pdg',{'__type__':0.}, include=False) 2967 self.add_param('mxx_only_part_antipart', {'default':False}, include=False) 2968 2969 self.add_param('pdg_cut',[0], system=True) # store which PDG are tracked 2970 self.add_param('ptmin4pdg',[0.], system=True) # store pt min 2971 self.add_param('ptmax4pdg',[-1.], system=True) 2972 self.add_param('Emin4pdg',[0.], system=True) # store pt min 2973 self.add_param('Emax4pdg',[-1.], system=True) 2974 self.add_param('etamin4pdg',[0.], system=True) # store pt min 2975 self.add_param('etamax4pdg',[-1.], system=True) 2976 self.add_param('mxxmin4pdg',[-1.], system=True) 2977 self.add_param('mxxpart_antipart', [False], system=True)
2978 2979
2980 - def check_validity(self):
2981 """ """ 2982 2983 super(RunCardLO, self).check_validity() 2984 2985 #Make sure that nhel is only either 0 (i.e. no MC over hel) or 2986 #1 (MC over hel with importance sampling). In particular, it can 2987 #no longer be > 1. 2988 if 'nhel' not in self.user_set: 2989 raise InvalidRunCard, "Parameter nhel is not defined in the run_card." 2990 if self['nhel'] not in [1,0]: 2991 raise InvalidRunCard, "Parameter nhel can only be '0' or '1', "+\ 2992 "not %s." % self['nhel'] 2993 if int(self['maxjetflavor']) > 6: 2994 raise InvalidRunCard, 'maxjetflavor should be lower than 5! (6 is partly supported)' 2995 2996 if len(self['pdgs_for_merging_cut']) > 1000: 2997 raise InvalidRunCard, "The number of elements in "+\ 2998 "'pdgs_for_merging_cut' should not exceed 1000." 2999 3000 # some cut need to be deactivated in presence of isolation 3001 if self['ptgmin'] > 0: 3002 if self['pta'] > 0: 3003 logger.warning('pta cut discarded since photon isolation is used') 3004 self['pta'] = 0.0 3005 if self['draj'] > 0: 3006 logger.warning('draj cut discarded since photon isolation is used') 3007 self['draj'] = 0.0 3008 3009 # special treatment for gridpack use the gseed instead of the iseed 3010 if self['gridrun']: 3011 self['iseed'] = self['gseed'] 3012 3013 #Some parameter need to be fixed when using syscalc 3014 if self['use_syst']: 3015 if self['scalefact'] != 1.0: 3016 logger.warning('Since use_syst=T, We change the value of \'scalefact\' to 1') 3017 self['scalefact'] = 1.0 3018 3019 # CKKW Treatment 3020 if self['ickkw'] > 0: 3021 if self['ickkw'] != 1: 3022 logger.critical('ickkw >1 is pure alpha and only partly implemented.') 3023 import madgraph.interface.extended_cmd as basic_cmd 3024 answer = basic_cmd.smart_input('Do you really want to continue', allow_arg=['y','n'], default='n') 3025 if answer !='y': 3026 raise InvalidRunCard, 'ickkw>1 is still in alpha' 3027 if self['use_syst']: 3028 # some additional parameter need to be fixed for Syscalc + matching 3029 if self['alpsfact'] != 1.0: 3030 logger.warning('Since use_syst=T, We change the value of \'alpsfact\' to 1') 3031 self['alpsfact'] =1.0 3032 if self['maxjetflavor'] == 6: 3033 raise InvalidRunCard, 'maxjetflavor at 6 is NOT supported for matching!' 3034 if self['ickkw'] == 2: 3035 # add warning if ckkw selected but the associate parameter are empty 3036 self.get_default('highestmult', log_level=20) 3037 self.get_default('issgridfile', 'issudgrid.dat', log_level=20) 3038 if self['xqcut'] > 0: 3039 if self['ickkw'] == 0: 3040 logger.error('xqcut>0 but ickkw=0. Potentially not fully consistent setup. Be carefull') 3041 import time 3042 time.sleep(5) 3043 if self['drjj'] != 0: 3044 logger.warning('Since icckw>0, We change the value of \'drjj\' to 0') 3045 self['drjj'] = 0 3046 if self['drjl'] != 0: 3047 logger.warning('Since icckw>0, We change the value of \'drjl\' to 0') 3048 self['drjl'] = 0 3049 if not self['auto_ptj_mjj']: 3050 if self['mmjj'] > self['xqcut']: 3051 logger.warning('mmjj > xqcut (and auto_ptj_mjj = F). MMJJ set to 0') 3052 self['mmjj'] = 0.0 3053 3054 # check validity of the pdf set 3055 if self['pdlabel'] == 'lhapdf': 3056 #add warning if lhaid not define 3057 self.get_default('lhaid', log_level=20)
3058
3060 3061 # set the pdg_for_cut fortran parameter 3062 pdg_to_cut = set(self['pt_min_pdg'].keys() +self['pt_max_pdg'].keys() + 3063 self['e_min_pdg'].keys() +self['e_max_pdg'].keys() + 3064 self['eta_min_pdg'].keys() +self['eta_max_pdg'].keys()+ 3065 self['mxx_min_pdg'].keys() + self['mxx_only_part_antipart'].keys()) 3066 pdg_to_cut.discard('__type__') 3067 pdg_to_cut.discard('default') 3068 if len(pdg_to_cut)>25: 3069 raise Exception, "Maximum 25 different pdgs are allowed for pdg specific cut" 3070 3071 if any(int(pdg)<0 for pdg in pdg_to_cut): 3072 logger.warning('PDG specific cuts are always applied symmetrically on particle/anti-particle. Always use positve PDG codes') 3073 raise MadGraph5Error, 'Some PDG specific cuts are defined with negative pdg code' 3074 3075 3076 if any(pdg in pdg_to_cut for pdg in [1,2,3,4,5,21,22,11,13,15]): 3077 raise Exception, "Can not use PDG related cut for light quark/b quark/lepton/gluon/photon" 3078 3079 if pdg_to_cut: 3080 self['pdg_cut'] = list(pdg_to_cut) 3081 self['ptmin4pdg'] = [] 3082 self['Emin4pdg'] = [] 3083 self['etamin4pdg'] =[] 3084 self['ptmax4pdg'] = [] 3085 self['Emax4pdg'] = [] 3086 self['etamax4pdg'] =[] 3087 self['mxxmin4pdg'] =[] 3088 self['mxxpart_antipart'] = [] 3089 for pdg in self['pdg_cut']: 3090 for var in ['pt','e','eta', 'Mxx']: 3091 for minmax in ['min', 'max']: 3092 if var in ['Mxx'] and minmax =='max': 3093 continue 3094 new_var = '%s%s4pdg' % (var, minmax) 3095 old_var = '%s_%s_pdg' % (var, minmax) 3096 default = 0. if minmax=='min' else -1. 3097 self[new_var].append(self[old_var][str(pdg)] if str(pdg) in self[old_var] else default) 3098 #special for mxx_part_antipart 3099 old_var = 'mxx_only_part_antipart' 3100 new_var = 'mxxpart_antipart' 3101 if 'default' in self[old_var]: 3102 default = self[old_var]['default'] 3103 self[new_var].append(self[old_var][str(pdg)] if str(pdg) in self[old_var] else default) 3104 else: 3105 if str(pdg) not in self[old_var]: 3106 raise Exception("no default value defined for %s and no value defined for pdg %s" % (old_var, pdg)) 3107 self[new_var].append(self[old_var][str(pdg)]) 3108 else: 3109 self['pdg_cut'] = [0] 3110 self['ptmin4pdg'] = [0.] 3111 self['Emin4pdg'] = [0.] 3112 self['etamin4pdg'] =[0.] 3113 self['ptmax4pdg'] = [-1.] 3114 self['Emax4pdg'] = [-1.] 3115 self['etamax4pdg'] =[-1.] 3116 self['mxxmin4pdg'] =[0.] 3117 self['mxxpart_antipart'] = [False]
3118 3119 3120
3121 - def create_default_for_process(self, proc_characteristic, history, proc_def):
3122 """Rules 3123 process 1->N all cut set on off. 3124 loop_induced -> MC over helicity 3125 e+ e- beam -> lpp:0 ebeam:500 3126 p p beam -> set maxjetflavor automatically 3127 more than one multiplicity: ickkw=1 xqcut=30 use_syst=F 3128 """ 3129 3130 if proc_characteristic['loop_induced']: 3131 self['nhel'] = 1 3132 self['pdgs_for_merging_cut'] = proc_characteristic['colored_pdgs'] 3133 3134 if proc_characteristic['ninitial'] == 1: 3135 #remove all cut 3136 self.remove_all_cut() 3137 self['use_syst'] = False 3138 else: 3139 # check for beam_id 3140 beam_id = set() 3141 for proc in proc_def: 3142 for oneproc in proc: 3143 for leg in oneproc['legs']: 3144 if not leg['state']: 3145 beam_id.add(leg['id']) 3146 if any(i in beam_id for i in [1,-1,2,-2,3,-3,4,-4,5,-5,21,22]): 3147 maxjetflavor = max([4]+[abs(i) for i in beam_id if -7< i < 7]) 3148 self['maxjetflavor'] = maxjetflavor 3149 self['asrwgtflavor'] = maxjetflavor 3150 pass 3151 elif 11 in beam_id or -11 in beam_id: 3152 self['lpp1'] = 0 3153 self['lpp2'] = 0 3154 self['ebeam1'] = 500 3155 self['ebeam2'] = 500 3156 self['use_syst'] = False 3157 else: 3158 self['lpp1'] = 0 3159 self['lpp2'] = 0 3160 self['use_syst'] = False 3161 3162 # Check if need matching 3163 min_particle = 99 3164 max_particle = 0 3165 for proc in proc_def: 3166 min_particle = min(len(proc[0]['legs']), min_particle) 3167 max_particle = max(len(proc[0]['legs']), max_particle) 3168 if min_particle != max_particle: 3169 #take one of the process with min_particle 3170 for procmin in proc_def: 3171 if len(procmin[0]['legs']) != min_particle: 3172 continue 3173 else: 3174 idsmin = [l['id'] for l in procmin[0]['legs']] 3175 break 3176 matching = False 3177 for procmax in proc_def: 3178 if len(procmax[0]['legs']) != max_particle: 3179 continue 3180 idsmax = [l['id'] for l in procmax[0]['legs']] 3181 for i in idsmin: 3182 if i not in idsmax: 3183 continue 3184 else: 3185 idsmax.remove(i) 3186 for j in idsmax: 3187 if j not in [1,-1,2,-2,3,-3,4,-4,5,-5,21]: 3188 break 3189 else: 3190 # all are jet => matching is ON 3191 matching=True 3192 break 3193 3194 if matching: 3195 self['ickkw'] = 1 3196 self['xqcut'] = 30 3197 #self['use_syst'] = False 3198 self['drjj'] = 0 3199 self['drjl'] = 0 3200 self['sys_alpsfact'] = "0.5 1 2" 3201 3202 # For interference module, the systematics are wrong. 3203 # automatically set use_syst=F and set systematics_program=none 3204 no_systematics = False 3205 for proc in proc_def: 3206 for oneproc in proc: 3207 if '^2' in oneproc.nice_string(): 3208 no_systematics = True 3209 break 3210 else: 3211 continue 3212 break 3213 if no_systematics: 3214 self['use_syst'] = False 3215 self['systematics_program'] = 'none'
3216
3217 - def write(self, output_file, template=None, python_template=False, 3218 **opt):
3219 """Write the run_card in output_file according to template 3220 (a path to a valid run_card)""" 3221 3222 if not template: 3223 if not MADEVENT: 3224 template = pjoin(MG5DIR, 'Template', 'LO', 'Cards', 3225 'run_card.dat') 3226 python_template = True 3227 else: 3228 template = pjoin(MEDIR, 'Cards', 'run_card_default.dat') 3229 python_template = False 3230 3231 super(RunCardLO, self).write(output_file, template=template, 3232 python_template=python_template, **opt)
3233
3234 3235 -class InvalidMadAnalysis5Card(InvalidCmd):
3236 pass
3237
3238 -class MadAnalysis5Card(dict):
3239 """ A class to store a MadAnalysis5 card. Very basic since it is basically 3240 free format.""" 3241 3242 _MG5aMC_escape_tag = '@MG5aMC' 3243 3244 _default_hadron_inputs = ['*.hepmc', '*.hep', '*.stdhep', '*.lhco','*.root'] 3245 _default_parton_inputs = ['*.lhe'] 3246 _skip_analysis = False 3247 3248 @classmethod
3249 - def events_can_be_reconstructed(cls, file_path):
3250 """ Checks from the type of an event file whether it can be reconstructed or not.""" 3251 return not (file_path.endswith('.lhco') or file_path.endswith('.lhco.gz') or \ 3252 file_path.endswith('.root') or file_path.endswith('.root.gz'))
3253 3254 @classmethod
3255 - def empty_analysis(cls):
3256 """ A method returning the structure of an empty analysis """ 3257 return {'commands':[], 3258 'reconstructions':[]}
3259 3260 @classmethod
3261 - def empty_reconstruction(cls):
3262 """ A method returning the structure of an empty reconstruction """ 3263 return {'commands':[], 3264 'reco_output':'lhe'}
3265
3266 - def default_setup(self):
3267 """define the default value""" 3268 self['mode'] = 'parton' 3269 self['inputs'] = [] 3270 # None is the default stdout level, it will be set automatically by MG5aMC 3271 self['stdout_lvl'] = None 3272 # These two dictionaries are formated as follows: 3273 # {'analysis_name': 3274 # {'reconstructions' : ['associated_reconstructions_name']} 3275 # {'commands':['analysis command lines here']} } 3276 # with values being of the form of the empty_analysis() attribute 3277 # of this class and some other property could be added to this dictionary 3278 # in the future. 3279 self['analyses'] = {} 3280 # The recasting structure contains on set of commands and one set of 3281 # card lines. 3282 self['recasting'] = {'commands':[],'card':[]} 3283 # Add the default trivial reconstruction to use an lhco input 3284 # This is just for the structure 3285 self['reconstruction'] = {'lhco_input': 3286 MadAnalysis5Card.empty_reconstruction(), 3287 'root_input': 3288 MadAnalysis5Card.empty_reconstruction()} 3289 self['reconstruction']['lhco_input']['reco_output']='lhco' 3290 self['reconstruction']['root_input']['reco_output']='root' 3291 3292 # Specify in which order the analysis/recasting were specified 3293 self['order'] = []
3294
3295 - def __init__(self, finput=None,mode=None):
3296 if isinstance(finput, self.__class__): 3297 dict.__init__(self, finput) 3298 assert finput.__dict__.keys() 3299 for key in finput.__dict__: 3300 setattr(self, key, copy.copy(getattr(finput, key)) ) 3301 return 3302 else: 3303 dict.__init__(self) 3304 3305 # Initialize it with all the default value 3306 self.default_setup() 3307 if not mode is None: 3308 self['mode']=mode 3309 3310 # if input is define read that input 3311 if isinstance(finput, (file, str, StringIO.StringIO)): 3312 self.read(finput, mode=mode)
3313
3314 - def read(self, input, mode=None):
3315 """ Read an MA5 card""" 3316 3317 if mode not in [None,'parton','hadron']: 3318 raise MadGraph5Error('A MadAnalysis5Card can be read online the modes'+ 3319 "'parton' or 'hadron'") 3320 card_mode = mode 3321 3322 if isinstance(input, (file, StringIO.StringIO)): 3323 input_stream = input 3324 elif isinstance(input, str): 3325 if not os.path.isfile(input): 3326 raise InvalidMadAnalysis5Card("Cannot read the MadAnalysis5 card."+\ 3327 "File '%s' not found."%input) 3328 if mode is None and 'hadron' in input: 3329 card_mode = 'hadron' 3330 input_stream = open(input,'r') 3331 else: 3332 raise MadGraph5Error('Incorrect input for the read function of'+\ 3333 ' the MadAnalysis5Card card. Received argument type is: %s'%str(type(input))) 3334 3335 # Reinstate default values 3336 self.__init__() 3337 current_name = 'default' 3338 current_type = 'analyses' 3339 for line in input_stream: 3340 # Skip comments for now 3341 if line.startswith('#'): 3342 continue 3343 if line.endswith('\n'): 3344 line = line[:-1] 3345 if line.strip()=='': 3346 continue 3347 if line.startswith(self._MG5aMC_escape_tag): 3348 try: 3349 option,value = line[len(self._MG5aMC_escape_tag):].split('=') 3350 value = value.strip() 3351 except ValueError: 3352 option = line[len(self._MG5aMC_escape_tag):] 3353 option = option.strip() 3354 3355 if option=='inputs': 3356 self['inputs'].extend([v.strip() for v in value.split(',')]) 3357 3358 elif option == 'skip_analysis': 3359 self._skip_analysis = True 3360 3361 elif option=='stdout_lvl': 3362 try: # It is likely an int 3363 self['stdout_lvl']=int(value) 3364 except ValueError: 3365 try: # Maybe the user used something like 'logging.INFO' 3366 self['stdout_lvl']=eval(value) 3367 except: 3368 try: 3369 self['stdout_lvl']=eval('logging.%s'%value) 3370 except: 3371 raise InvalidMadAnalysis5Card( 3372 "MA5 output level specification '%s' is incorrect."%str(value)) 3373 3374 elif option=='analysis_name': 3375 current_type = 'analyses' 3376 current_name = value 3377 if current_name in self[current_type]: 3378 raise InvalidMadAnalysis5Card( 3379 "Analysis '%s' already defined in MadAnalysis5 card"%current_name) 3380 else: 3381 self[current_type][current_name] = MadAnalysis5Card.empty_analysis() 3382 3383 elif option=='set_reconstructions': 3384 try: 3385 reconstructions = eval(value) 3386 if not isinstance(reconstructions, list): 3387 raise 3388 except: 3389 raise InvalidMadAnalysis5Card("List of reconstructions"+\ 3390 " '%s' could not be parsed in MadAnalysis5 card."%value) 3391 if current_type!='analyses' and current_name not in self[current_type]: 3392 raise InvalidMadAnalysis5Card("A list of reconstructions"+\ 3393 "can only be defined in the context of an "+\ 3394 "analysis in a MadAnalysis5 card.") 3395 self[current_type][current_name]['reconstructions']=reconstructions 3396 continue 3397 3398 elif option=='reconstruction_name': 3399 current_type = 'reconstruction' 3400 current_name = value 3401 if current_name in self[current_type]: 3402 raise InvalidMadAnalysis5Card( 3403 "Reconstruction '%s' already defined in MadAnalysis5 hadron card"%current_name) 3404 else: 3405 self[current_type][current_name] = MadAnalysis5Card.empty_reconstruction() 3406 3407 elif option=='reco_output': 3408 if current_type!='reconstruction' or current_name not in \ 3409 self['reconstruction']: 3410 raise InvalidMadAnalysis5Card( 3411 "Option '%s' is only available within the definition of a reconstruction"%option) 3412 if not value.lower() in ['lhe','root']: 3413 raise InvalidMadAnalysis5Card( 3414 "Option '%s' can only take the values 'lhe' or 'root'"%option) 3415 self['reconstruction'][current_name]['reco_output'] = value.lower() 3416 3417 elif option.startswith('recasting'): 3418 current_type = 'recasting' 3419 try: 3420 current_name = option.split('_')[1] 3421 except: 3422 raise InvalidMadAnalysis5Card('Malformed MA5 recasting option %s.'%option) 3423 if len(self['recasting'][current_name])>0: 3424 raise InvalidMadAnalysis5Card( 3425 "Only one recasting can be defined in MadAnalysis5 hadron card") 3426 3427 else: 3428 raise InvalidMadAnalysis5Card( 3429 "Unreckognized MG5aMC instruction in MadAnalysis5 card: '%s'"%option) 3430 3431 if option in ['analysis_name','reconstruction_name'] or \ 3432 option.startswith('recasting'): 3433 self['order'].append((current_type,current_name)) 3434 continue 3435 3436 # Add the default analysis if needed since the user does not need 3437 # to specify it. 3438 if current_name == 'default' and current_type == 'analyses' and\ 3439 'default' not in self['analyses']: 3440 self['analyses']['default'] = MadAnalysis5Card.empty_analysis() 3441 self['order'].append(('analyses','default')) 3442 3443 if current_type in ['recasting']: 3444 self[current_type][current_name].append(line) 3445 elif current_type in ['reconstruction']: 3446 self[current_type][current_name]['commands'].append(line) 3447 elif current_type in ['analyses']: 3448 self[current_type][current_name]['commands'].append(line) 3449 3450 if 'reconstruction' in self['analyses'] or len(self['recasting']['card'])>0: 3451 if mode=='parton': 3452 raise InvalidMadAnalysis5Card( 3453 "A parton MadAnalysis5 card cannot specify a recombination or recasting.") 3454 card_mode = 'hadron' 3455 elif mode is None: 3456 card_mode = 'parton' 3457 3458 self['mode'] = card_mode 3459 if self['inputs'] == []: 3460 if self['mode']=='hadron': 3461 self['inputs'] = self._default_hadron_inputs 3462 else: 3463 self['inputs'] = self._default_parton_inputs 3464 3465 # Make sure at least one reconstruction is specified for each hadron 3466 # level analysis and that it exists. 3467 if self['mode']=='hadron': 3468 for analysis_name, analysis in self['analyses'].items(): 3469 if len(analysis['reconstructions'])==0: 3470 raise InvalidMadAnalysis5Card('Hadron-level analysis '+\ 3471 "'%s' is not specified any reconstruction(s)."%analysis_name) 3472 if any(reco not in self['reconstruction'] for reco in \ 3473 analysis['reconstructions']): 3474 raise InvalidMadAnalysis5Card('A reconstructions specified in'+\ 3475 " analysis '%s' is not defined."%analysis_name)
3476
3477 - def write(self, output):
3478 """ Write an MA5 card.""" 3479 3480 if isinstance(output, (file, StringIO.StringIO)): 3481 output_stream = output 3482 elif isinstance(output, str): 3483 output_stream = open(output,'w') 3484 else: 3485 raise MadGraph5Error('Incorrect input for the write function of'+\ 3486 ' the MadAnalysis5Card card. Received argument type is: %s'%str(type(output))) 3487 3488 output_lines = [] 3489 if self._skip_analysis: 3490 output_lines.append('%s skip_analysis'%self._MG5aMC_escape_tag) 3491 output_lines.append('%s inputs = %s'%(self._MG5aMC_escape_tag,','.join(self['inputs']))) 3492 if not self['stdout_lvl'] is None: 3493 output_lines.append('%s stdout_lvl=%s'%(self._MG5aMC_escape_tag,self['stdout_lvl'])) 3494 for definition_type, name in self['order']: 3495 3496 if definition_type=='analyses': 3497 output_lines.append('%s analysis_name = %s'%(self._MG5aMC_escape_tag,name)) 3498 output_lines.append('%s set_reconstructions = %s'%(self._MG5aMC_escape_tag, 3499 str(self['analyses'][name]['reconstructions']))) 3500 elif definition_type=='reconstruction': 3501 output_lines.append('%s reconstruction_name = %s'%(self._MG5aMC_escape_tag,name)) 3502 elif definition_type=='recasting': 3503 output_lines.append('%s recasting_%s'%(self._MG5aMC_escape_tag,name)) 3504 3505 if definition_type in ['recasting']: 3506 output_lines.extend(self[definition_type][name]) 3507 elif definition_type in ['reconstruction']: 3508 output_lines.append('%s reco_output = %s'%(self._MG5aMC_escape_tag, 3509 self[definition_type][name]['reco_output'])) 3510 output_lines.extend(self[definition_type][name]['commands']) 3511 elif definition_type in ['analyses']: 3512 output_lines.extend(self[definition_type][name]['commands']) 3513 3514 output_stream.write('\n'.join(output_lines)) 3515 3516 return
3517
3518 - def get_MA5_cmds(self, inputs_arg, submit_folder, run_dir_path=None, 3519 UFO_model_path=None, run_tag=''):
3520 """ Returns a list of tuples ('AnalysisTag',['commands']) specifying 3521 the commands of the MadAnalysis runs required from this card. 3522 At parton-level, the number of such commands is the number of analysis 3523 asked for. In the future, the idea is that the entire card can be 3524 processed in one go from MA5 directly.""" 3525 3526 if isinstance(inputs_arg, list): 3527 inputs = inputs_arg 3528 elif isinstance(inputs_arg, str): 3529 inputs = [inputs_arg] 3530 else: 3531 raise MadGraph5Error("The function 'get_MA5_cmds' can only take "+\ 3532 " a string or a list for the argument 'inputs_arg'") 3533 3534 if len(inputs)==0: 3535 raise MadGraph5Error("The function 'get_MA5_cmds' must have "+\ 3536 " at least one input specified'") 3537 3538 if run_dir_path is None: 3539 run_dir_path = os.path.dirname(inputs_arg) 3540 3541 cmds_list = [] 3542 3543 UFO_load = [] 3544 # first import the UFO if provided 3545 if UFO_model_path: 3546 UFO_load.append('import %s'%UFO_model_path) 3547 3548 def get_import(input, type=None): 3549 """ Generates the MA5 import commands for that event file. """ 3550 dataset_name = os.path.basename(input).split('.')[0] 3551 res = ['import %s as %s'%(input, dataset_name)] 3552 if not type is None: 3553 res.append('set %s.type = %s'%(dataset_name, type)) 3554 return res
3555 3556 fifo_status = {'warned_fifo':False,'fifo_used_up':False} 3557 def warn_fifo(input): 3558 if not input.endswith('.fifo'): 3559 return False 3560 if not fifo_status['fifo_used_up']: 3561 fifo_status['fifo_used_up'] = True 3562 return False 3563 else: 3564 if not fifo_status['warned_fifo']: 3565 logger.warning('Only the first MA5 analysis/reconstructions can be run on a fifo. Subsequent runs will skip fifo inputs.') 3566 fifo_status['warned_fifo'] = True 3567 return True
3568 3569 # Then the event file(s) input(s) 3570 inputs_load = [] 3571 for input in inputs: 3572 inputs_load.extend(get_import(input)) 3573 3574 submit_command = 'submit %s'%submit_folder+'_%s' 3575 3576 # Keep track of the reconstruction outpus in the MA5 workflow 3577 # Keys are reconstruction names and values are .lhe.gz reco file paths. 3578 # We put by default already the lhco/root ones present 3579 reconstruction_outputs = { 3580 'lhco_input':[f for f in inputs if 3581 f.endswith('.lhco') or f.endswith('.lhco.gz')], 3582 'root_input':[f for f in inputs if 3583 f.endswith('.root') or f.endswith('.root.gz')]} 3584 3585 # If a recasting card has to be written out, chose here its path 3586 recasting_card_path = pjoin(run_dir_path, 3587 '_'.join([run_tag,os.path.basename(submit_folder),'recasting_card.dat'])) 3588 3589 # Make sure to only run over one analysis over each fifo. 3590 for definition_type, name in self['order']: 3591 if definition_type == 'reconstruction': 3592 analysis_cmds = list(self['reconstruction'][name]['commands']) 3593 reco_outputs = [] 3594 for i_input, input in enumerate(inputs): 3595 # Skip lhco/root as they must not be reconstructed 3596 if not MadAnalysis5Card.events_can_be_reconstructed(input): 3597 continue 3598 # Make sure the input is not a used up fifo. 3599 if warn_fifo(input): 3600 continue 3601 analysis_cmds.append('import %s as reco_events'%input) 3602 if self['reconstruction'][name]['reco_output']=='lhe': 3603 reco_outputs.append('%s_%s.lhe.gz'%(os.path.basename( 3604 input).replace('_events','').split('.')[0],name)) 3605 analysis_cmds.append('set main.outputfile=%s'%reco_outputs[-1]) 3606 elif self['reconstruction'][name]['reco_output']=='root': 3607 reco_outputs.append('%s_%s.root'%(os.path.basename( 3608 input).replace('_events','').split('.')[0],name)) 3609 analysis_cmds.append('set main.fastsim.rootfile=%s'%reco_outputs[-1]) 3610 analysis_cmds.append( 3611 submit_command%('reco_%s_%d'%(name,i_input+1))) 3612 analysis_cmds.append('remove reco_events') 3613 3614 reconstruction_outputs[name]= [pjoin(run_dir_path,rec_out) 3615 for rec_out in reco_outputs] 3616 if len(reco_outputs)>0: 3617 cmds_list.append(('_reco_%s'%name,analysis_cmds)) 3618 3619 elif definition_type == 'analyses': 3620 if self['mode']=='parton': 3621 cmds_list.append( (name, UFO_load+inputs_load+ 3622 self['analyses'][name]['commands']+[submit_command%name]) ) 3623 elif self['mode']=='hadron': 3624 # Also run on the already reconstructed root/lhco files if found. 3625 for reco in self['analyses'][name]['reconstructions']+\ 3626 ['lhco_input','root_input']: 3627 if len(reconstruction_outputs[reco])==0: 3628 continue 3629 if self['reconstruction'][reco]['reco_output']=='lhe': 3630 # For the reconstructed lhe output we must be in parton mode 3631 analysis_cmds = ['set main.mode = parton'] 3632 else: 3633 analysis_cmds = [] 3634 analysis_cmds.extend(sum([get_import(rec_out) for 3635 rec_out in reconstruction_outputs[reco]],[])) 3636 analysis_cmds.extend(self['analyses'][name]['commands']) 3637 analysis_cmds.append(submit_command%('%s_%s'%(name,reco))) 3638 cmds_list.append( ('%s_%s'%(name,reco),analysis_cmds) ) 3639 3640 elif definition_type == 'recasting': 3641 if len(self['recasting']['card'])==0: 3642 continue 3643 if name == 'card': 3644 # Create the card here 3645 open(recasting_card_path,'w').write('\n'.join(self['recasting']['card'])) 3646 if name == 'commands': 3647 recasting_cmds = list(self['recasting']['commands']) 3648 # Exclude LHCO files here of course 3649 n_inputs = 0 3650 for input in inputs: 3651 if not MadAnalysis5Card.events_can_be_reconstructed(input): 3652 continue 3653 # Make sure the input is not a used up fifo. 3654 if warn_fifo(input): 3655 continue 3656 recasting_cmds.extend(get_import(input,'signal')) 3657 n_inputs += 1 3658 3659 recasting_cmds.append('set main.recast.card_path=%s'%recasting_card_path) 3660 recasting_cmds.append(submit_command%'Recasting') 3661 if n_inputs>0: 3662 cmds_list.append( ('Recasting',recasting_cmds)) 3663 3664 return cmds_list 3665
3666 -class RunCardNLO(RunCard):
3667 """A class object for the run_card for a (aMC@)NLO pocess""" 3668
3669 - def default_setup(self):
3670 """define the default value""" 3671 3672 self.add_param('run_tag', 'tag_1', include=False) 3673 self.add_param('nevents', 10000) 3674 self.add_param('req_acc', -1.0, include=False) 3675 self.add_param('nevt_job', -1, include=False) 3676 self.add_param('event_norm', 'average') 3677 #FO parameter 3678 self.add_param('req_acc_fo', 0.01, include=False) 3679 self.add_param('npoints_fo_grid', 5000, include=False) 3680 self.add_param('niters_fo_grid', 4, include=False) 3681 self.add_param('npoints_fo', 10000, include=False) 3682 self.add_param('niters_fo', 6, include=False) 3683 #seed and collider 3684 self.add_param('iseed', 0) 3685 self.add_param('lpp1', 1, fortran_name='lpp(1)') 3686 self.add_param('lpp2', 1, fortran_name='lpp(2)') 3687 self.add_param('ebeam1', 6500.0, fortran_name='ebeam(1)') 3688 self.add_param('ebeam2', 6500.0, fortran_name='ebeam(2)') 3689 self.add_param('pdlabel', 'nn23nlo', allowed=['lhapdf', 'cteq6_m','cteq6_d','cteq6_l','cteq6l1', 'nn23lo','nn23lo1','nn23nlo','ct14q00','ct14q07','ct14q14','ct14q21']) 3690 self.add_param('lhaid', [244600],fortran_name='lhaPDFid') 3691 self.add_param('lhapdfsetname', ['internal_use_only'], system=True) 3692 #shower and scale 3693 self.add_param('parton_shower', 'HERWIG6', fortran_name='shower_mc') 3694 self.add_param('shower_scale_factor',1.0) 3695 self.add_param('fixed_ren_scale', False) 3696 self.add_param('fixed_fac_scale', False) 3697 self.add_param('mur_ref_fixed', 91.118) 3698 self.add_param('muf1_ref_fixed', -1.0, hidden=True) 3699 self.add_param('muf_ref_fixed', 91.118) 3700 self.add_param('muf2_ref_fixed', -1.0, hidden=True) 3701 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") 3702 self.add_param('fixed_qes_scale', False, hidden=True) 3703 self.add_param('qes_ref_fixed', -1.0, hidden=True) 3704 self.add_param('mur_over_ref', 1.0) 3705 self.add_param('muf_over_ref', 1.0) 3706 self.add_param('muf1_over_ref', -1.0, hidden=True) 3707 self.add_param('muf2_over_ref', -1.0, hidden=True) 3708 self.add_param('qes_over_ref', -1.0, hidden=True) 3709 self.add_param('reweight_scale', [True], fortran_name='lscalevar') 3710 self.add_param('rw_rscale_down', -1.0, hidden=True) 3711 self.add_param('rw_rscale_up', -1.0, hidden=True) 3712 self.add_param('rw_fscale_down', -1.0, hidden=True) 3713 self.add_param('rw_fscale_up', -1.0, hidden=True) 3714 self.add_param('rw_rscale', [1.0,2.0,0.5], fortran_name='scalevarR') 3715 self.add_param('rw_fscale', [1.0,2.0,0.5], fortran_name='scalevarF') 3716 self.add_param('reweight_pdf', [False], fortran_name='lpdfvar') 3717 self.add_param('pdf_set_min', 244601, hidden=True) 3718 self.add_param('pdf_set_max', 244700, hidden=True) 3719 self.add_param('store_rwgt_info', False) 3720 self.add_param('systematics_program', 'none', include=False, hidden=True, comment='Choose which program to use for systematics computation: none, systematics') 3721 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.') 3722 3723 #merging 3724 self.add_param('ickkw', 0) 3725 self.add_param('bwcutoff', 15.0) 3726 #cuts 3727 self.add_param('jetalgo', 1.0) 3728 self.add_param('jetradius', 0.7) 3729 self.add_param('ptj', 10.0 , cut=True) 3730 self.add_param('etaj', -1.0, cut=True) 3731 self.add_param('gamma_is_j', 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('rphreco', 0.1) 3739 self.add_param('etaphreco', -1.0) 3740 self.add_param('lepphreco', True) 3741 self.add_param('quarkphreco', True) 3742 self.add_param('ptgmin', 20.0, cut=True) 3743 self.add_param('etagamma', -1.0) 3744 self.add_param('r0gamma', 0.4) 3745 self.add_param('xn', 1.0) 3746 self.add_param('epsgamma', 1.0) 3747 self.add_param('isoem', True) 3748 self.add_param('maxjetflavor', 4, hidden=True) 3749 self.add_param('iappl', 0) 3750 self.add_param('lhe_version', 3, hidden=True, include=False) 3751 3752 #internal variable related to FO_analyse_card 3753 self.add_param('FO_LHE_weight_ratio',1e-3, hidden=True, system=True) 3754 self.add_param('FO_LHE_postprocessing',['grouping','random'], 3755 hidden=True, system=True, include=False) 3756 3757 # parameter allowing to define simple cut via the pdg 3758 self.add_param('pt_min_pdg',{'__type__':0.}, include=False) 3759 self.add_param('pt_max_pdg',{'__type__':0.}, include=False) 3760 self.add_param('mxx_min_pdg',{'__type__':0.}, include=False) 3761 self.add_param('mxx_only_part_antipart', {'default':False}, include=False, hidden=True) 3762 3763 #hidden parameter that are transfer to the fortran code 3764 self.add_param('pdg_cut',[0], hidden=True, system=True) # store which PDG are tracked 3765 self.add_param('ptmin4pdg',[0.], hidden=True, system=True) # store pt min 3766 self.add_param('ptmax4pdg',[-1.], hidden=True, system=True) 3767 self.add_param('mxxmin4pdg',[0.], hidden=True, system=True) 3768 self.add_param('mxxpart_antipart', [False], hidden=True, system=True)
3769
3770 - def check_validity(self):
3771 """check the validity of the various input""" 3772 3773 super(RunCardNLO, self).check_validity() 3774 3775 # for lepton-lepton collisions, ignore 'pdlabel' and 'lhaid' 3776 if self['lpp1']==0 and self['lpp2']==0: 3777 if self['pdlabel']!='nn23nlo' or self['reweight_pdf']: 3778 self['pdlabel']='nn23nlo' 3779 self['reweight_pdf']=[False] 3780 logger.info('''Lepton-lepton collisions: ignoring PDF related parameters in the run_card.dat (pdlabel, lhaid, reweight_pdf, ...)''') 3781 3782 # For FxFx merging, make sure that the following parameters are set correctly: 3783 if self['ickkw'] == 3: 3784 # 1. Renormalization and factorization (and ellis-sexton scales) are not fixed 3785 scales=['fixed_ren_scale','fixed_fac_scale','fixed_QES_scale'] 3786 for scale in scales: 3787 if self[scale]: 3788 logger.warning('''For consistency in the FxFx merging, \'%s\' has been set to false''' 3789 % scale,'$MG:BOLD') 3790 self[scale]= False 3791 #and left to default dynamical scale 3792 if len(self["dynamical_scale_choice"]) > 1 or self["dynamical_scale_choice"][0] != -1: 3793 self["dynamical_scale_choice"] = [-1] 3794 self["reweight_scale"]=[self["reweight_scale"][0]] 3795 logger.warning('''For consistency in the FxFx merging, dynamical_scale_choice has been set to -1 (default)''' 3796 ,'$MG:BOLD') 3797 3798 # 2. Use kT algorithm for jets with pseudo-code size R=1.0 3799 jetparams=['jetradius','jetalgo'] 3800 for jetparam in jetparams: 3801 if float(self[jetparam]) != 1.0: 3802 logger.info('''For consistency in the FxFx merging, \'%s\' has been set to 1.0''' 3803 % jetparam ,'$MG:BOLD') 3804 self[jetparam] = 1.0 3805 elif self['ickkw'] == -1 and (self["dynamical_scale_choice"][0] != -1 or 3806 len(self["dynamical_scale_choice"]) > 1): 3807 self["dynamical_scale_choice"] = [-1] 3808 self["reweight_scale"]=[self["reweight_scale"][0]] 3809 logger.warning('''For consistency with the jet veto, the scale which will be used is ptj. dynamical_scale_choice will be set at -1.''' 3810 ,'$MG:BOLD') 3811 3812 # For interface to APPLGRID, need to use LHAPDF and reweighting to get scale uncertainties 3813 if self['iappl'] != 0 and self['pdlabel'].lower() != 'lhapdf': 3814 raise InvalidRunCard('APPLgrid generation only possible with the use of LHAPDF') 3815 if self['iappl'] != 0 and not self['reweight_scale']: 3816 raise InvalidRunCard('APPLgrid generation only possible with including' +\ 3817 ' the reweighting to get scale dependence') 3818 3819 # Hidden values check 3820 if self['qes_ref_fixed'] == -1.0: 3821 self['qes_ref_fixed']=self['mur_ref_fixed'] 3822 if self['qes_over_ref'] == -1.0: 3823 self['qes_over_ref']=self['mur_over_ref'] 3824 if self['muf1_over_ref'] != -1.0 and self['muf1_over_ref'] == self['muf2_over_ref']: 3825 self['muf_over_ref']=self['muf1_over_ref'] 3826 if self['muf1_over_ref'] == -1.0: 3827 self['muf1_over_ref']=self['muf_over_ref'] 3828 if self['muf2_over_ref'] == -1.0: 3829 self['muf2_over_ref']=self['muf_over_ref'] 3830 if self['muf1_ref_fixed'] != -1.0 and self['muf1_ref_fixed'] == self['muf2_ref_fixed']: 3831 self['muf_ref_fixed']=self['muf1_ref_fixed'] 3832 if self['muf1_ref_fixed'] == -1.0: 3833 self['muf1_ref_fixed']=self['muf_ref_fixed'] 3834 if self['muf2_ref_fixed'] == -1.0: 3835 self['muf2_ref_fixed']=self['muf_ref_fixed'] 3836 # overwrite rw_rscale and rw_fscale when rw_(r/f)scale_(down/up) are explicitly given in the run_card for backward compatibility. 3837 if (self['rw_rscale_down'] != -1.0 and ['rw_rscale_down'] not in self['rw_rscale']) or\ 3838 (self['rw_rscale_up'] != -1.0 and ['rw_rscale_up'] not in self['rw_rscale']): 3839 self['rw_rscale']=[1.0,self['rw_rscale_up'],self['rw_rscale_down']] 3840 if (self['rw_fscale_down'] != -1.0 and ['rw_fscale_down'] not in self['rw_fscale']) or\ 3841 (self['rw_fscale_up'] != -1.0 and ['rw_fscale_up'] not in self['rw_fscale']): 3842 self['rw_fscale']=[1.0,self['rw_fscale_up'],self['rw_fscale_down']] 3843 3844 # PDF reweighting check 3845 if any(self['reweight_pdf']): 3846 # check that we use lhapdf if reweighting is ON 3847 if self['pdlabel'] != "lhapdf": 3848 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.' 3849 3850 # make sure set have reweight_pdf and lhaid of length 1 when not including lhapdf 3851 if self['pdlabel'] != "lhapdf": 3852 self['reweight_pdf']=[self['reweight_pdf'][0]] 3853 self['lhaid']=[self['lhaid'][0]] 3854 3855 # make sure set have reweight_scale and dyn_scale_choice of length 1 when fixed scales: 3856 if self['fixed_ren_scale'] and self['fixed_fac_scale']: 3857 self['reweight_scale']=[self['reweight_scale'][0]] 3858 self['dynamical_scale_choice']=[0] 3859 3860 # If there is only one reweight_pdf/reweight_scale, but 3861 # lhaid/dynamical_scale_choice are longer, expand the 3862 # reweight_pdf/reweight_scale list to have the same length 3863 if len(self['reweight_pdf']) == 1 and len(self['lhaid']) != 1: 3864 self['reweight_pdf']=self['reweight_pdf']*len(self['lhaid']) 3865 logger.warning("Setting 'reweight_pdf' for all 'lhaid' to %s" % self['reweight_pdf'][0]) 3866 if len(self['reweight_scale']) == 1 and len(self['dynamical_scale_choice']) != 1: 3867 self['reweight_scale']=self['reweight_scale']*len(self['dynamical_scale_choice']) 3868 logger.warning("Setting 'reweight_scale' for all 'dynamical_scale_choice' to %s" % self['reweight_pdf'][0]) 3869 3870 # Check that there are no identical elements in lhaid or dynamical_scale_choice 3871 if len(self['lhaid']) != len(set(self['lhaid'])): 3872 raise InvalidRunCard, "'lhaid' has two or more identical entries. They have to be all different for the code to work correctly." 3873 if len(self['dynamical_scale_choice']) != len(set(self['dynamical_scale_choice'])): 3874 raise InvalidRunCard, "'dynamical_scale_choice' has two or more identical entries. They have to be all different for the code to work correctly." 3875 3876 # Check that lenght of lists are consistent 3877 if len(self['reweight_pdf']) != len(self['lhaid']): 3878 raise InvalidRunCard, "'reweight_pdf' and 'lhaid' lists should have the same length" 3879 if len(self['reweight_scale']) != len(self['dynamical_scale_choice']): 3880 raise InvalidRunCard, "'reweight_scale' and 'dynamical_scale_choice' lists should have the same length" 3881 if len(self['dynamical_scale_choice']) > 10 : 3882 raise InvalidRunCard, "Length of list for 'dynamical_scale_choice' too long: max is 10." 3883 if len(self['lhaid']) > 25 : 3884 raise InvalidRunCard, "Length of list for 'lhaid' too long: max is 25." 3885 if len(self['rw_rscale']) > 9 : 3886 raise InvalidRunCard, "Length of list for 'rw_rscale' too long: max is 9." 3887 if len(self['rw_fscale']) > 9 : 3888 raise InvalidRunCard, "Length of list for 'rw_fscale' too long: max is 9." 3889 # make sure that the first element of rw_rscale and rw_fscale is the 1.0 3890 if 1.0 not in self['rw_rscale']: 3891 logger.warning("'1.0' has to be part of 'rw_rscale', adding it") 3892 self['rw_rscale'].insert(0,1.0) 3893 if 1.0 not in self['rw_fscale']: 3894 logger.warning("'1.0' has to be part of 'rw_fscale', adding it") 3895 self['rw_fscale'].insert(0,1.0) 3896 if self['rw_rscale'][0] != 1.0 and 1.0 in self['rw_rscale']: 3897 a=self['rw_rscale'].index(1.0) 3898 self['rw_rscale'][0],self['rw_rscale'][a]=self['rw_rscale'][a],self['rw_rscale'][0] 3899 if self['rw_fscale'][0] != 1.0 and 1.0 in self['rw_fscale']: 3900 a=self['rw_fscale'].index(1.0) 3901 self['rw_fscale'][0],self['rw_fscale'][a]=self['rw_fscale'][a],self['rw_fscale'][0] 3902 # check that all elements of rw_rscale and rw_fscale are diffent. 3903 if len(self['rw_rscale']) != len(set(self['rw_rscale'])): 3904 raise InvalidRunCard, "'rw_rscale' has two or more identical entries. They have to be all different for the code to work correctly." 3905 if len(self['rw_fscale']) != len(set(self['rw_fscale'])): 3906 raise InvalidRunCard, "'rw_fscale' has two or more identical entries. They have to be all different for the code to work correctly."
3907 3908
3910 3911 # set the pdg_for_cut fortran parameter 3912 pdg_to_cut = set(self['pt_min_pdg'].keys() +self['pt_max_pdg'].keys()+ 3913 self['mxx_min_pdg'].keys()+ self['mxx_only_part_antipart'].keys()) 3914 pdg_to_cut.discard('__type__') 3915 pdg_to_cut.discard('default') 3916 if len(pdg_to_cut)>25: 3917 raise Exception, "Maximum 25 different PDGs are allowed for PDG specific cut" 3918 3919 if any(int(pdg)<0 for pdg in pdg_to_cut): 3920 logger.warning('PDG specific cuts are always applied symmetrically on particle/anti-particle. Always use positve PDG codes') 3921 raise MadGraph5Error, 'Some PDG specific cuts are defined with negative PDG codes' 3922 3923 3924 if any(pdg in pdg_to_cut for pdg in [21,22,11,13,15]+ range(self['maxjetflavor']+1)): 3925 # Note that this will double check in the fortran code 3926 raise Exception, "Can not use PDG related cuts for massless SM particles/leptons" 3927 if pdg_to_cut: 3928 self['pdg_cut'] = list(pdg_to_cut) 3929 self['ptmin4pdg'] = [] 3930 self['ptmax4pdg'] = [] 3931 self['mxxmin4pdg'] = [] 3932 self['mxxpart_antipart'] = [] 3933 for pdg in self['pdg_cut']: 3934 for var in ['pt','mxx']: 3935 for minmax in ['min', 'max']: 3936 if var == 'mxx' and minmax == 'max': 3937 continue 3938 new_var = '%s%s4pdg' % (var, minmax) 3939 old_var = '%s_%s_pdg' % (var, minmax) 3940 default = 0. if minmax=='min' else -1. 3941 self[new_var].append(self[old_var][str(pdg)] if str(pdg) in self[old_var] else default) 3942 #special for mxx_part_antipart 3943 old_var = 'mxx_only_part_antipart' 3944 new_var = 'mxxpart_antipart' 3945 if 'default' in self[old_var]: 3946 default = self[old_var]['default'] 3947 self[new_var].append(self[old_var][str(pdg)] if str(pdg) in self[old_var] else default) 3948 else: 3949 if str(pdg) not in self[old_var]: 3950 raise Exception("no default value defined for %s and no value defined for pdg %s" % (old_var, pdg)) 3951 self[new_var].append(self[old_var][str(pdg)]) 3952 else: 3953 self['pdg_cut'] = [0] 3954 self['ptmin4pdg'] = [0.] 3955 self['ptmax4pdg'] = [-1.] 3956 self['mxxmin4pdg'] = [0.] 3957 self['mxxpart_antipart'] = [False]
3958
3959 - def write(self, output_file, template=None, python_template=False, **opt):
3960 """Write the run_card in output_file according to template 3961 (a path to a valid run_card)""" 3962 3963 if not template: 3964 if not MADEVENT: 3965 template = pjoin(MG5DIR, 'Template', 'NLO', 'Cards', 3966 'run_card.dat') 3967 python_template = True 3968 else: 3969 template = pjoin(MEDIR, 'Cards', 'run_card_default.dat') 3970 python_template = False 3971 3972 super(RunCardNLO, self).write(output_file, template=template, 3973 python_template=python_template, **opt)
3974 3975
3976 - def create_default_for_process(self, proc_characteristic, history, proc_def):
3977 """Rules 3978 e+ e- beam -> lpp:0 ebeam:500 3979 p p beam -> set maxjetflavor automatically 3980 """ 3981 3982 # check for beam_id 3983 beam_id = set() 3984 for proc in proc_def: 3985 for leg in proc['legs']: 3986 if not leg['state']: 3987 beam_id.add(leg['id']) 3988 if any(i in beam_id for i in [1,-1,2,-2,3,-3,4,-4,5,-5,21,22]): 3989 maxjetflavor = max([4]+[abs(i) for i in beam_id if -7< i < 7]) 3990 self['maxjetflavor'] = maxjetflavor 3991 pass 3992 elif 11 in beam_id or -11 in beam_id: 3993 self['lpp1'] = 0 3994 self['lpp2'] = 0 3995 self['ebeam1'] = 500 3996 self['ebeam2'] = 500 3997 else: 3998 self['lpp1'] = 0 3999 self['lpp2'] = 0 4000 4001 if proc_characteristic['ninitial'] == 1: 4002 #remove all cut 4003 self.remove_all_cut()
4004
4005 4006 4007 -class MadLoopParam(ConfigFile):
4008 """ a class for storing/dealing with the file MadLoopParam.dat 4009 contains a parser to read it, facilities to write a new file,... 4010 """ 4011 4012 _ID_reduction_tool_map = {1:'CutTools', 4013 2:'PJFry++', 4014 3:'IREGI', 4015 4:'Golem95', 4016 5:'Samurai', 4017 6:'Ninja', 4018 7:'COLLIER'} 4019
4020 - def default_setup(self):
4021 """initialize the directory to the default value""" 4022 4023 self.add_param("MLReductionLib", "6|7|1") 4024 self.add_param("IREGIMODE", 2) 4025 self.add_param("IREGIRECY", True) 4026 self.add_param("CTModeRun", -1) 4027 self.add_param("MLStabThres", 1e-3) 4028 self.add_param("NRotations_DP", 0) 4029 self.add_param("NRotations_QP", 0) 4030 self.add_param("ImprovePSPoint", 2) 4031 self.add_param("CTLoopLibrary", 2) 4032 self.add_param("CTStabThres", 1e-2) 4033 self.add_param("CTModeInit", 1) 4034 self.add_param("CheckCycle", 3) 4035 self.add_param("MaxAttempts", 10) 4036 self.add_param("ZeroThres", 1e-9) 4037 self.add_param("OSThres", 1.0e-8) 4038 self.add_param("DoubleCheckHelicityFilter", True) 4039 self.add_param("WriteOutFilters", True) 4040 self.add_param("UseLoopFilter", False) 4041 self.add_param("HelicityFilterLevel", 2) 4042 self.add_param("LoopInitStartOver", False) 4043 self.add_param("HelInitStartOver", False) 4044 self.add_param("UseQPIntegrandForNinja", True) 4045 self.add_param("UseQPIntegrandForCutTools", True) 4046 self.add_param("COLLIERMode", 1) 4047 self.add_param("COLLIERComputeUVpoles", True) 4048 self.add_param("COLLIERComputeIRpoles", True) 4049 self.add_param("COLLIERRequiredAccuracy", 1.0e-8) 4050 self.add_param("COLLIERCanOutput",False) 4051 self.add_param("COLLIERGlobalCache",-1) 4052 self.add_param("COLLIERUseCacheForPoles",False) 4053 self.add_param("COLLIERUseInternalStabilityTest",True)
4054
4055 - def read(self, finput):
4056 """Read the input file, this can be a path to a file, 4057 a file object, a str with the content of the file.""" 4058 4059 if isinstance(finput, str): 4060 if "\n" in finput: 4061 finput = finput.split('\n') 4062 elif os.path.isfile(finput): 4063 finput = open(finput) 4064 else: 4065 raise Exception, "No such file %s" % input 4066 4067 previous_line= '' 4068 for line in finput: 4069 if previous_line.startswith('#'): 4070 name = previous_line[1:].split()[0] 4071 value = line.strip() 4072 if len(value) and value[0] not in ['#', '!']: 4073 self.__setitem__(name, value, change_userdefine=True) 4074 previous_line = line
4075 4076
4077 - def write(self, outputpath, template=None,commentdefault=False):
4078 4079 if not template: 4080 if not MADEVENT: 4081 template = pjoin(MG5DIR, 'Template', 'loop_material', 'StandAlone', 4082 'Cards', 'MadLoopParams.dat') 4083 else: 4084 template = pjoin(MEDIR, 'Cards', 'MadLoopParams_default.dat') 4085 fsock = open(template, 'r') 4086 template = fsock.readlines() 4087 fsock.close() 4088 4089 if isinstance(outputpath, str): 4090 output = open(outputpath, 'w') 4091 else: 4092 output = outputpath 4093 4094 def f77format(value): 4095 if isinstance(value, bool): 4096 if value: 4097 return '.true.' 4098 else: 4099 return '.false.' 4100 elif isinstance(value, int): 4101 return value 4102 elif isinstance(value, float): 4103 tmp ='%e' % value 4104 return tmp.replace('e','d') 4105 elif isinstance(value, str): 4106 return value 4107 else: 4108 raise Exception, "Can not format input %s" % type(value)
4109 4110 name = '' 4111 done = set() 4112 for line in template: 4113 if name: 4114 done.add(name) 4115 if commentdefault and name.lower() not in self.user_set : 4116 output.write('!%s\n' % f77format(self[name])) 4117 else: 4118 output.write('%s\n' % f77format(self[name])) 4119 name='' 4120 continue 4121 elif line.startswith('#'): 4122 name = line[1:].split()[0] 4123 output.write(line)
4124