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