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