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