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