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