Package madgraph :: Package interface :: Module common_run_interface
[hide private]
[frames] | no frames]

Source Code for Module madgraph.interface.common_run_interface

   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  """A user friendly command line interface to access MadGraph5_aMC@NLO features. 
  16     Uses the cmd package for command interpretation and tab completion. 
  17  """ 
  18  from __future__ import division 
  19   
  20  import atexit 
  21  import cmath 
  22  import cmd 
  23  import glob 
  24  import logging 
  25  import math 
  26  import optparse 
  27  import os 
  28  import pydoc 
  29  import random 
  30  import re 
  31  import shutil 
  32  import signal 
  33  import stat 
  34  import subprocess 
  35  import sys 
  36  import time 
  37  import traceback 
  38   
  39   
  40  try: 
  41      import readline 
  42      GNU_SPLITTING = ('GNU' in readline.__doc__) 
  43  except: 
  44      GNU_SPLITTING = True 
  45   
  46  root_path = os.path.split(os.path.dirname(os.path.realpath( __file__ )))[0] 
  47  root_path = os.path.split(root_path)[0] 
  48  sys.path.insert(0, os.path.join(root_path,'bin')) 
  49   
  50  # usefull shortcut 
  51  pjoin = os.path.join 
  52  # Special logger for the Cmd Interface 
  53  logger = logging.getLogger('madgraph.stdout') # -> stdout 
  54  logger_stderr = logging.getLogger('madgraph.stderr') # ->stderr 
  55   
  56   
  57  try: 
  58      import madgraph 
  59  except ImportError:     
  60      # import from madevent directory 
  61      import internal.extended_cmd as cmd 
  62      import internal.banner as banner_mod 
  63      import internal.shower_card as shower_card_mod 
  64      import internal.misc as misc 
  65      import internal.cluster as cluster 
  66      import internal.check_param_card as check_param_card 
  67      import internal.files as files 
  68      from internal import InvalidCmd, MadGraph5Error 
  69      MADEVENT=True     
  70  else: 
  71      # import from madgraph directory 
  72      import madgraph.interface.extended_cmd as cmd 
  73      import madgraph.various.banner as banner_mod 
  74      import madgraph.various.shower_card as shower_card_mod 
  75      import madgraph.various.misc as misc 
  76      import madgraph.iolibs.files as files 
  77      import madgraph.various.cluster as cluster 
  78      import models.check_param_card as check_param_card 
  79      from madgraph import InvalidCmd, MadGraph5Error, MG5DIR 
  80      MADEVENT=False 
81 82 #=============================================================================== 83 # HelpToCmd 84 #=============================================================================== 85 -class HelpToCmd(object):
86 """ The Series of help routins in common between amcatnlo_run and 87 madevent interface""" 88
89 - def help_treatcards(self):
90 logger.info("syntax: treatcards [param|run] [--output_dir=] [--param_card=] [--run_card=]") 91 logger.info("-- create the .inc files containing the cards information." )
92
93 - def help_set(self):
94 logger.info("syntax: set %s argument" % "|".join(self._set_options)) 95 logger.info("-- set options") 96 logger.info(" stdout_level DEBUG|INFO|WARNING|ERROR|CRITICAL") 97 logger.info(" change the default level for printed information") 98 logger.info(" timeout VALUE") 99 logger.info(" (default 20) Seconds allowed to answer questions.") 100 logger.info(" Note that pressing tab always stops the timer.") 101 logger.info(" cluster_temp_path PATH") 102 logger.info(" (default None) Allow to perform the run in PATH directory") 103 logger.info(" This allow to not run on the central disk. This is not used") 104 logger.info(" by condor cluster (since condor has it's own way to prevent it).")
105
106 - def help_plot(self):
107 logger.info("syntax: help [RUN] [%s] [-f]" % '|'.join(self._plot_mode)) 108 logger.info("-- create the plot for the RUN (current run by default)") 109 logger.info(" at the different stage of the event generation") 110 logger.info(" Note than more than one mode can be specified in the same command.") 111 logger.info(" This require to have MadAnalysis and td require. By default") 112 logger.info(" if those programs are installed correctly, the creation") 113 logger.info(" will be performed automaticaly during the event generation.") 114 logger.info(" -f options: answer all question by default.")
115
116 - def help_compute_widths(self):
117 logger.info("syntax: compute_widths Particle [Particles] [OPTIONS]") 118 logger.info("-- Compute the widths for the particles specified.") 119 logger.info(" By default, this takes the current param_card and overwrites it.") 120 logger.info(" Precision allows to define when to include three/four/... body decays (LO).") 121 logger.info(" If this number is an integer then all N-body decay will be included.") 122 logger.info(" Various options:\n") 123 logger.info(" --body_decay=X: Parameter to control the precision of the computation") 124 logger.info(" if X is an integer, we compute all channels up to X-body decay.") 125 logger.info(" if X <1, then we stop when the estimated error is lower than X.") 126 logger.info(" if X >1 BUT not an integer, then we X = N + M, with M <1 and N an integer") 127 logger.info(" We then either stop at the N-body decay or when the estimated error is lower than M.") 128 logger.info(" default: 4.0025") 129 logger.info(" --min_br=X: All channel which are estimated below this value will not be integrated numerically.") 130 logger.info(" default: precision (decimal part of the body_decay options) divided by four") 131 logger.info(" --precision_channel=X: requested numerical precision for each channel") 132 logger.info(" default: 0.01") 133 logger.info(" --path=X: path for param_card") 134 logger.info(" default: take value from the model") 135 logger.info(" --output=X: path where to write the resulting card. ") 136 logger.info(" default: overwrite input file. If no input file, write it in the model directory") 137 logger.info(" --nlo: Compute NLO width [if the model support it]")
138 139
140 - def help_pythia(self):
141 logger.info("syntax: pythia [RUN] [--run_options]") 142 logger.info("-- run pythia on RUN (current one by default)") 143 self.run_options_help([('-f','answer all question by default'), 144 ('--tag=', 'define the tag for the pythia run'), 145 ('--no_default', 'not run if pythia_card not present')])
146
147 - def help_pgs(self):
148 logger.info("syntax: pgs [RUN] [--run_options]") 149 logger.info("-- run pgs on RUN (current one by default)") 150 self.run_options_help([('-f','answer all question by default'), 151 ('--tag=', 'define the tag for the pgs run'), 152 ('--no_default', 'not run if pgs_card not present')])
153
154 - def help_delphes(self):
155 logger.info("syntax: delphes [RUN] [--run_options]") 156 logger.info("-- run delphes on RUN (current one by default)") 157 self.run_options_help([('-f','answer all question by default'), 158 ('--tag=', 'define the tag for the delphes run'), 159 ('--no_default', 'not run if delphes_card not present')])
160
161 - def help_decay_events(self, skip_syntax=False):
162 if not skip_syntax: 163 logger.info("syntax: decay_events [RUN]") 164 logger.info("This functionality allows for the decay of resonances") 165 logger.info("in a .lhe file, keeping track of the spin correlation effets.") 166 logger.info("BE AWARE OF THE CURRENT LIMITATIONS:") 167 logger.info(" (1) Only a succession of 2 body decay are currently allowed")
168
169 170 171 -class CheckValidForCmd(object):
172 """ The Series of check routines in common between amcatnlo_run and 173 madevent interface""" 174
175 - def check_set(self, args):
176 """ check the validity of the line""" 177 178 if len(args) < 2: 179 self.help_set() 180 raise self.InvalidCmd('set needs an option and an argument') 181 182 if args[0] not in self._set_options + self.options.keys(): 183 self.help_set() 184 raise self.InvalidCmd('Possible options for set are %s' % \ 185 self._set_options) 186 187 if args[0] in ['stdout_level']: 188 if args[1] not in ['DEBUG','INFO','WARNING','ERROR','CRITICAL'] \ 189 and not args[1].isdigit(): 190 raise self.InvalidCmd('output_level needs ' + \ 191 'a valid level') 192 193 if args[0] in ['timeout']: 194 if not args[1].isdigit(): 195 raise self.InvalidCmd('timeout values should be a integer')
196
197 - def check_compute_widths(self, args):
198 """check that the model is loadable and check that the format is of the 199 type: PART PATH --output=PATH -f --precision=N 200 return the model. 201 """ 202 203 # Check that MG5 directory is present . 204 if MADEVENT and not self.options['mg5_path']: 205 raise self.InvalidCmd, '''The automatic computations of widths requires that MG5 is installed on the system. 206 You can install it and set his path in ./Cards/me5_configuration.txt''' 207 elif MADEVENT: 208 sys.path.append(self.options['mg5_path']) 209 try: 210 import models.model_reader as model_reader 211 import models.import_ufo as import_ufo 212 except ImportError: 213 raise self.ConfigurationError, '''Can\'t load MG5. 214 The variable mg5_path should not be correctly configure.''' 215 216 217 ufo_path = pjoin(self.me_dir,'bin','internal', 'ufomodel') 218 # Import model 219 if not MADEVENT: 220 modelname = self.find_model_name() 221 #restrict_file = None 222 #if os.path.exists(pjoin(ufo_path, 'restrict_default.dat')): 223 # restrict_file = pjoin(ufo_path, 'restrict_default.dat') 224 model = import_ufo.import_model(modelname, decay=True, 225 restrict=True) 226 if self.mother and self.mother.options['complex_mass_scheme']: 227 model.change_mass_to_complex_scheme() 228 else: 229 model = import_ufo.import_model(pjoin( 230 self.me_dir,'bin','internal', 'ufomodel'),decay=True) 231 #pattern for checking complex mass scheme. 232 has_cms = re.compile(r'''set\s+complex_mass_scheme\s*(True|T|1|true|$|;)''') 233 if has_cms.search(open(pjoin(self.me_dir,'Cards','proc_card_mg5.dat')\ 234 ).read()): 235 model.change_mass_to_complex_scheme() 236 237 238 # if not hasattr(model.get('particles')[0], 'partial_widths'): 239 # raise self.InvalidCmd, 'The UFO model does not include partial widths information. Impossible to compute widths automatically' 240 241 # check if the name are passed to default MG5 242 if '-modelname' not in open(pjoin(self.me_dir,'Cards','proc_card_mg5.dat')).read(): 243 model.pass_particles_name_in_mg_default() 244 model = model_reader.ModelReader(model) 245 particles_name = dict([(p.get('name'), p.get('pdg_code')) 246 for p in model.get('particles')]) 247 particles_name.update(dict([(p.get('antiname'), p.get('pdg_code')) 248 for p in model.get('particles')])) 249 250 output = {'model': model, 'force': False, 'output': None, 251 'path':None, 'particles': set(), 'body_decay':4.0025, 252 'min_br':None, 'precision_channel':0.01} 253 for arg in args: 254 if arg.startswith('--output='): 255 output_path = arg.split('=',1)[1] 256 if not os.path.exists(output_path): 257 raise self.InvalidCmd, 'Invalid Path for the output. Please retry.' 258 if not os.path.isfile(output_path): 259 output_path = pjoin(output_path, 'param_card.dat') 260 output['output'] = output_path 261 elif arg == '-f': 262 output['force'] = True 263 elif os.path.isfile(arg): 264 ftype = self.detect_card_type(arg) 265 if ftype != 'param_card.dat': 266 raise self.InvalidCmd , '%s is not a valid param_card.' % arg 267 output['path'] = arg 268 elif arg.startswith('--path='): 269 arg = arg.split('=',1)[1] 270 ftype = self.detect_card_type(arg) 271 if ftype != 'param_card.dat': 272 raise self.InvalidCmd , '%s is not a valid param_card.' % arg 273 output['path'] = arg 274 elif arg.startswith('--'): 275 if "=" in arg: 276 name, value = arg.split('=',1) 277 try: 278 value = float(value) 279 except Exception: 280 raise self.InvalidCmd, '--%s requires integer or a float' % name 281 output[name[2:]] = float(value) 282 elif arg == "--nlo": 283 output["nlo"] = True 284 elif arg in particles_name: 285 # should be a particles 286 output['particles'].add(particles_name[arg]) 287 elif arg.isdigit() and int(arg) in particles_name.values(): 288 output['particles'].add(eval(arg)) 289 elif arg == 'all': 290 output['particles'] = set(['all']) 291 else: 292 self.help_compute_widths() 293 raise self.InvalidCmd, '%s is not a valid argument for compute_widths' % arg 294 if self.force: 295 output['force'] = True 296 297 if not output['particles']: 298 raise self.InvalidCmd, '''This routines requires at least one particle in order to compute 299 the related width''' 300 301 if output['output'] is None: 302 output['output'] = output['path'] 303 304 return output
305
306 - def check_open(self, args):
307 """ check the validity of the line """ 308 309 if len(args) != 1: 310 self.help_open() 311 raise self.InvalidCmd('OPEN command requires exactly one argument') 312 313 if args[0].startswith('./'): 314 if not os.path.isfile(args[0]): 315 raise self.InvalidCmd('%s: not such file' % args[0]) 316 return True 317 318 # if special : create the path. 319 if not self.me_dir: 320 if not os.path.isfile(args[0]): 321 self.help_open() 322 raise self.InvalidCmd('No MadEvent path defined. Unable to associate this name to a file') 323 else: 324 return True 325 326 path = self.me_dir 327 if os.path.isfile(os.path.join(path,args[0])): 328 args[0] = os.path.join(path,args[0]) 329 elif os.path.isfile(os.path.join(path,'Cards',args[0])): 330 args[0] = os.path.join(path,'Cards',args[0]) 331 elif os.path.isfile(os.path.join(path,'HTML',args[0])): 332 args[0] = os.path.join(path,'HTML',args[0]) 333 # special for card with _default define: copy the default and open it 334 elif '_card.dat' in args[0]: 335 name = args[0].replace('_card.dat','_card_default.dat') 336 if os.path.isfile(os.path.join(path,'Cards', name)): 337 files.cp(os.path.join(path,'Cards', name), os.path.join(path,'Cards', args[0])) 338 args[0] = os.path.join(path,'Cards', args[0]) 339 else: 340 raise self.InvalidCmd('No default path for this file') 341 elif not os.path.isfile(args[0]): 342 raise self.InvalidCmd('No default path for this file')
343
344 - def check_treatcards(self, args):
345 """check that treatcards arguments are valid 346 [param|run|all] [--output_dir=] [--param_card=] [--run_card=] 347 """ 348 349 opt = {'output_dir':pjoin(self.me_dir,'Source'), 350 'param_card':pjoin(self.me_dir,'Cards','param_card.dat'), 351 'run_card':pjoin(self.me_dir,'Cards','run_card.dat')} 352 mode = 'all' 353 for arg in args: 354 if arg.startswith('--') and '=' in arg: 355 key,value =arg[2:].split('=',1) 356 if not key in opt: 357 self.help_treatcards() 358 raise self.InvalidCmd('Invalid option for treatcards command:%s ' \ 359 % key) 360 if key in ['param_card', 'run_card']: 361 if os.path.isfile(value): 362 card_name = self.detect_card_type(value) 363 if card_name != key: 364 raise self.InvalidCmd('Format for input file detected as %s while expecting %s' 365 % (card_name, key)) 366 opt[key] = value 367 elif os.path.isfile(pjoin(self.me_dir,value)): 368 card_name = self.detect_card_type(pjoin(self.me_dir,value)) 369 if card_name != key: 370 raise self.InvalidCmd('Format for input file detected as %s while expecting %s' 371 % (card_name, key)) 372 opt[key] = value 373 else: 374 raise self.InvalidCmd('No such file: %s ' % value) 375 elif key in ['output_dir']: 376 if os.path.isdir(value): 377 opt[key] = value 378 elif os.path.isdir(pjoin(self.me_dir,value)): 379 opt[key] = pjoin(self.me_dir, value) 380 else: 381 raise self.InvalidCmd('No such directory: %s' % value) 382 elif arg in ['MadLoop','param','run','all']: 383 mode = arg 384 else: 385 self.help_treatcards() 386 raise self.InvalidCmd('Unvalid argument %s' % arg) 387 388 return mode, opt
389
390 - def check_decay_events(self,args):
391 """Check the argument for decay_events command 392 syntax: decay_events [NAME] 393 Note that other option are already remove at this point 394 """ 395 396 opts = [] 397 if '-from_cards' in args: 398 args.remove('-from_cards') 399 opts.append('-from_cards') 400 401 if len(args) == 0: 402 if self.run_name: 403 args.insert(0, self.run_name) 404 elif self.results.lastrun: 405 args.insert(0, self.results.lastrun) 406 else: 407 raise self.InvalidCmd('No run name currently defined. Please add this information.') 408 return 409 410 if args[0] != self.run_name: 411 self.set_run_name(args[0]) 412 413 args[0] = self.get_events_path(args[0]) 414 415 args += opts
416
417 - def check_check_events(self,args):
418 """Check the argument for decay_events command 419 syntax: decay_events [NAME] 420 Note that other option are already remove at this point 421 """ 422 423 if len(args) == 0: 424 if self.run_name: 425 args.insert(0, self.run_name) 426 elif self.results.lastrun: 427 args.insert(0, self.results.lastrun) 428 else: 429 raise self.InvalidCmd('No run name currently defined. Please add this information.') 430 return 431 432 if args[0] and os.path.isfile(args[0]): 433 pass 434 else: 435 if args[0] != self.run_name: 436 self.set_run_name(args[0], allow_new_tag=False) 437 438 args[0] = self.get_events_path(args[0])
439 440
441 - def get_events_path(self, run_name):
442 """Check the argument for decay_events command 443 syntax: decay_events [NAME] 444 Note that other option are already remove at this point 445 """ 446 447 448 if self.mode == 'madevent': 449 possible_path = [ 450 pjoin(self.me_dir,'Events', run_name, 'unweighted_events.lhe.gz'), 451 pjoin(self.me_dir,'Events', run_name, 'unweighted_events.lhe')] 452 else: 453 possible_path = [ 454 pjoin(self.me_dir,'Events', run_name, 'events.lhe.gz'), 455 pjoin(self.me_dir,'Events', run_name, 'events.lhe')] 456 457 for path in possible_path: 458 if os.path.exists(path): 459 correct_path = path 460 break 461 else: 462 raise self.InvalidCmd('No events file corresponding to %s run. ' % run_name) 463 return correct_path
464
465 466 467 -class MadEventAlreadyRunning(InvalidCmd):
468 pass
469 -class AlreadyRunning(MadEventAlreadyRunning):
470 pass
471
472 #=============================================================================== 473 # CommonRunCmd 474 #=============================================================================== 475 -class CommonRunCmd(HelpToCmd, CheckValidForCmd, cmd.Cmd):
476 477 debug_output = 'ME5_debug' 478 helporder = ['Main Commands', 'Documented commands', 'Require MG5 directory', 479 'Advanced commands'] 480 481 # The three options categories are treated on a different footage when a 482 # set/save configuration occur. current value are kept in self.options 483 options_configuration = {'pythia8_path': './pythia8', 484 'hwpp_path': './herwigPP', 485 'thepeg_path': './thepeg', 486 'hepmc_path': './hepmc', 487 'madanalysis_path': './MadAnalysis', 488 'pythia-pgs_path':'./pythia-pgs', 489 'td_path':'./td', 490 'delphes_path':'./Delphes', 491 'exrootanalysis_path':'./ExRootAnalysis', 492 'syscalc_path': './SysCalc', 493 'lhapdf': 'lhapdf-config', 494 'timeout': 60, 495 'f2py_compiler':None, 496 'web_browser':None, 497 'eps_viewer':None, 498 'text_editor':None, 499 'fortran_compiler':None, 500 'cpp_compiler': None, 501 'auto_update':7, 502 'cluster_type': 'condor', 503 'cluster_status_update': (600, 30), 504 'cluster_nb_retry':1, 505 'cluster_local_path': "/cvmfs/cp3.uclouvain.be/madgraph/", 506 'cluster_retry_wait':300} 507 508 options_madgraph= {'stdout_level':None} 509 510 options_madevent = {'automatic_html_opening':True, 511 'run_mode':2, 512 'cluster_queue':'madgraph', 513 'cluster_time':None, 514 'cluster_size':100, 515 'cluster_memory':None, 516 'nb_core': None, 517 'cluster_temp_path':None} 518 519
520 - def __init__(self, me_dir, options, *args, **opts):
521 """common""" 522 523 cmd.Cmd.__init__(self, *args, **opts) 524 # Define current MadEvent directory 525 if me_dir is None and MADEVENT: 526 me_dir = root_path 527 528 self.me_dir = me_dir 529 self.options = options 530 531 # usefull shortcut 532 self.status = pjoin(self.me_dir, 'status') 533 self.error = pjoin(self.me_dir, 'error') 534 self.dirbin = pjoin(self.me_dir, 'bin', 'internal') 535 536 # Check that the directory is not currently running 537 if os.path.exists(pjoin(me_dir,'RunWeb')): 538 message = '''Another instance of the program is currently running. 539 (for this exact same directory) Please wait that this is instance is 540 closed. If no instance is running, you can delete the file 541 %s and try again.''' % pjoin(me_dir,'RunWeb') 542 raise AlreadyRunning, message 543 else: 544 pid = os.getpid() 545 fsock = open(pjoin(me_dir,'RunWeb'),'w') 546 fsock.write(`pid`) 547 fsock.close() 548 549 misc.Popen([os.path.relpath(pjoin(self.dirbin, 'gen_cardhtml-pl'), me_dir)], 550 cwd=me_dir) 551 552 self.to_store = [] 553 self.run_name = None 554 self.run_tag = None 555 self.banner = None 556 # Load the configuration file 557 self.set_configuration() 558 self.configure_run_mode(self.options['run_mode']) 559 560 # Define self.proc_characteristics 561 self.get_characteristics() 562 563 if not self.proc_characteristics['ninitial']: 564 # Get number of initial states 565 nexternal = open(pjoin(self.me_dir,'Source','nexternal.inc')).read() 566 found = re.search("PARAMETER\s*\(NINCOMING=(\d)\)", nexternal) 567 self.ninitial = int(found.group(1)) 568 else: 569 self.ninitial = self.proc_characteristics['ninitial']
570 571 572 ############################################################################
573 - def split_arg(self, line, error=False):
574 """split argument and remove run_options""" 575 576 args = cmd.Cmd.split_arg(line) 577 for arg in args[:]: 578 if not arg.startswith('-'): 579 continue 580 elif arg == '-c': 581 self.configure_run_mode(1) 582 elif arg == '-m': 583 self.configure_run_mode(2) 584 elif arg == '-f': 585 self.force = True 586 elif not arg.startswith('--'): 587 if error: 588 raise self.InvalidCmd('%s argument cannot start with - symbol' % arg) 589 else: 590 continue 591 elif arg.startswith('--cluster'): 592 self.configure_run_mode(1) 593 elif arg.startswith('--multicore'): 594 self.configure_run_mode(2) 595 elif arg.startswith('--nb_core'): 596 self.options['nb_core'] = int(arg.split('=',1)[1]) 597 self.configure_run_mode(2) 598 elif arg.startswith('--web'): 599 self.pass_in_web_mode() 600 self.configure_run_mode(1) 601 else: 602 continue 603 args.remove(arg) 604 605 return args
606 607 ############################################################################
608 - def do_treatcards(self, line, amcatnlo=False):
609 """Advanced commands: create .inc files from param_card.dat/run_card.dat""" 610 611 keepwidth = False 612 if '--keepwidth' in line: 613 keepwidth = True 614 line = line.replace('--keepwidth', '') 615 args = self.split_arg(line) 616 mode, opt = self.check_treatcards(args) 617 618 if mode in ['run', 'all']: 619 if not hasattr(self, 'run_card'): 620 if amcatnlo: 621 run_card = banner_mod.RunCardNLO(opt['run_card']) 622 else: 623 run_card = banner_mod.RunCard(opt['run_card']) 624 else: 625 run_card = self.run_card 626 627 run_card.write_include_file(pjoin(opt['output_dir'],'run_card.inc')) 628 629 if mode in ['MadLoop', 'all']: 630 if os.path.exists(pjoin(self.me_dir, 'Cards', 'MadLoopParams.dat')): 631 self.MadLoopparam = banner_mod.MadLoopParam(pjoin(self.me_dir, 632 'Cards', 'MadLoopParams.dat')) 633 # write the output file 634 self.MadLoopparam.write(pjoin(self.me_dir,"SubProcesses", 635 "MadLoopParams.dat")) 636 637 if mode in ['param', 'all']: 638 if os.path.exists(pjoin(self.me_dir, 'Source', 'MODEL', 'mp_coupl.inc')): 639 param_card = check_param_card.ParamCardMP(opt['param_card']) 640 else: 641 param_card = check_param_card.ParamCard(opt['param_card']) 642 outfile = pjoin(opt['output_dir'], 'param_card.inc') 643 ident_card = pjoin(self.me_dir,'Cards','ident_card.dat') 644 if os.path.isfile(pjoin(self.me_dir,'bin','internal','ufomodel','restrict_default.dat')): 645 default = pjoin(self.me_dir,'bin','internal','ufomodel','restrict_default.dat') 646 elif os.path.isfile(pjoin(self.me_dir,'bin','internal','ufomodel','param_card.dat')): 647 default = pjoin(self.me_dir,'bin','internal','ufomodel','param_card.dat') 648 elif not os.path.exists(pjoin(self.me_dir,'bin','internal','ufomodel')): 649 fsock = open(pjoin(self.me_dir,'Source','param_card.inc'),'w') 650 fsock.write(' ') 651 fsock.close() 652 return 653 else: 654 subprocess.call(['python', 'write_param_card.py'], 655 cwd=pjoin(self.me_dir,'bin','internal','ufomodel')) 656 default = pjoin(self.me_dir,'bin','internal','ufomodel','param_card.dat') 657 658 659 if amcatnlo and not keepwidth: 660 # force particle in final states to have zero width 661 pids = self.get_pid_final_states() 662 # check those which are charged under qcd 663 if not MADEVENT and pjoin(self.me_dir,'bin','internal') not in sys.path: 664 sys.path.insert(0,pjoin(self.me_dir,'bin','internal')) 665 666 #Ensure that the model that we are going to load is the current 667 #one. 668 to_del = [name for name in sys.modules.keys() 669 if name.startswith('internal.ufomodel') 670 or name.startswith('ufomodel')] 671 for name in to_del: 672 del(sys.modules[name]) 673 674 import ufomodel as ufomodel 675 zero = ufomodel.parameters.ZERO 676 no_width = [p for p in ufomodel.all_particles 677 if (str(p.pdg_code) in pids or str(-p.pdg_code) in pids) 678 and p.color != 1 and p.width != zero] 679 done = [] 680 for part in no_width: 681 if abs(part.pdg_code) in done: 682 continue 683 done.append(abs(part.pdg_code)) 684 param = param_card['decay'].get((part.pdg_code,)) 685 686 if param.value != 0: 687 logger.info('''For gauge cancellation, the width of \'%s\' has been set to zero.''' 688 % part.name,'$MG:color:BLACK') 689 param.value = 0 690 691 param_card.write_inc_file(outfile, ident_card, default)
692 693
694 - def ask_edit_cards(self, cards, mode='fixed', plot=True):
695 """ """ 696 if not self.options['madanalysis_path']: 697 plot = False 698 699 self.ask_edit_card_static(cards, mode, plot, self.options['timeout'], 700 self.ask)
701 702 @staticmethod
703 - def ask_edit_card_static(cards, mode='fixed', plot=True, 704 timeout=0, ask=None, **opt):
705 if not ask: 706 ask = CommonRunCmd.ask 707 708 def path2name(path): 709 if '_card' in path: 710 return path.split('_card')[0] 711 elif path == 'delphes_trigger.dat': 712 return 'trigger' 713 elif path == 'input.lhco': 714 return 'lhco' 715 elif path == 'MadLoopParams.dat': 716 return 'MadLoopParams' 717 else: 718 raise Exception, 'Unknow cards name %s' % path
719 720 # Ask the user if he wants to edit any of the files 721 #First create the asking text 722 question = """Do you want to edit a card (press enter to bypass editing)?\n""" 723 possible_answer = ['0', 'done'] 724 card = {0:'done'} 725 726 for i, card_name in enumerate(cards): 727 imode = path2name(card_name) 728 possible_answer.append(i+1) 729 possible_answer.append(imode) 730 question += ' %s / %-10s : %s\n' % (i+1, imode, card_name) 731 card[i+1] = imode 732 if plot: 733 question += ' 9 / %-10s : plot_card.dat\n' % 'plot' 734 possible_answer.append(9) 735 possible_answer.append('plot') 736 card[9] = 'plot' 737 738 if 'param_card.dat' in cards: 739 # Add the path options 740 question += ' you can also\n' 741 question += ' - enter the path to a valid card or banner.\n' 742 question += ' - use the \'set\' command to modify a parameter directly.\n' 743 question += ' The set option works only for param_card and run_card.\n' 744 question += ' Type \'help set\' for more information on this command.\n' 745 question += ' - call an external program (ASperGE/MadWidth/...).\n' 746 question += ' Type \'help\' for the list of available command\n' 747 else: 748 question += ' you can also\n' 749 question += ' - enter the path to a valid card.\n' 750 if 'transfer_card.dat' in cards: 751 question += ' - use the \'change_tf\' command to set a transfer functions.\n' 752 753 out = 'to_run' 754 while out not in ['0', 'done']: 755 out = ask(question, '0', possible_answer, timeout=int(1.5*timeout), 756 path_msg='enter path', ask_class = AskforEditCard, 757 cards=cards, mode=mode, **opt)
758 759 760 761 @staticmethod
762 - def detect_card_type(path):
763 """detect the type of the card. Return value are 764 banner 765 param_card.dat 766 run_card.dat 767 pythia_card.dat 768 plot_card.dat 769 pgs_card.dat 770 delphes_card.dat 771 delphes_trigger.dat 772 shower_card.dat [aMCatNLO] 773 FO_analyse_card.dat [aMCatNLO] 774 madspin_card.dat [MS] 775 transfer_card.dat [MW] 776 madweight_card.dat [MW] 777 """ 778 779 fulltext = open(path).read(50000) 780 if fulltext == '': 781 logger.warning('File %s is empty' % path) 782 return 'unknown' 783 text = re.findall('(<MGVersion>|ParticlePropagator|<mg5proccard>|CEN_max_tracker|#TRIGGER CARD|parameter set name|muon eta coverage|QES_over_ref|MSTP|b_stable|FO_ANALYSIS_FORMAT|MSTU|Begin Minpts|gridpack|ebeam1|block\s+mw_run|BLOCK|DECAY|launch|madspin|transfer_card\.dat|set)', fulltext, re.I) 784 text = [t.lower() for t in text] 785 if '<mgversion>' in text or '<mg5proccard>' in text: 786 return 'banner' 787 elif 'particlepropagator' in text: 788 return 'delphes_card.dat' 789 elif 'cen_max_tracker' in text: 790 return 'delphes_card.dat' 791 elif '#trigger card' in text: 792 return 'delphes_trigger.dat' 793 elif 'parameter set name' in text: 794 return 'pgs_card.dat' 795 elif 'muon eta coverage' in text: 796 return 'pgs_card.dat' 797 elif 'mstp' in text and not 'b_stable' in text: 798 return 'pythia_card.dat' 799 elif 'begin minpts' in text: 800 return 'plot_card.dat' 801 elif ('gridpack' in text and 'ebeam1' in text) or \ 802 ('qes_over_ref' in text and 'ebeam1' in text): 803 return 'run_card.dat' 804 elif any(t.endswith('mw_run') for t in text): 805 return 'madweight_card.dat' 806 elif 'transfer_card.dat' in text: 807 return 'transfer_card.dat' 808 elif 'block' in text and 'decay' in text: 809 return 'param_card.dat' 810 elif 'b_stable' in text: 811 return 'shower_card.dat' 812 elif 'fo_analysis_format' in text: 813 return 'FO_analyse_card.dat' 814 elif 'launch' in text: 815 # need to separate madspin/reweight. 816 # decay/set can be in both... 817 if 'madspin' in text: 818 return 'madspin_card.dat' 819 if 'decay' in text: 820 # need to check if this a line like "decay w+" or "set decay" 821 if re.search("(^|;)\s*decay", fulltext): 822 return 'madspin_card.dat' 823 else: 824 return 'reweight_card.dat' 825 else: 826 return 'reweight_card.dat' 827 else: 828 return 'unknown'
829 830 831 ############################################################################
832 - def get_available_tag(self):
833 """create automatically a tag""" 834 835 used_tags = [r['tag'] for r in self.results[self.run_name]] 836 i=0 837 while 1: 838 i+=1 839 if 'tag_%s' %i not in used_tags: 840 return 'tag_%s' % i
841 842 843 ############################################################################
844 - def create_plot(self, mode='parton', event_path=None, output=None, tag=None):
845 """create the plot""" 846 847 madir = self.options['madanalysis_path'] 848 if not tag: 849 tag = self.run_card['run_tag'] 850 td = self.options['td_path'] 851 852 if not madir or not td or \ 853 not os.path.exists(pjoin(self.me_dir, 'Cards', 'plot_card.dat')): 854 return False 855 856 if 'ickkw' in self.run_card and int(self.run_card['ickkw']) and \ 857 mode == 'Pythia': 858 self.update_status('Create matching plots for Pythia', level='pythia') 859 # recover old data if none newly created 860 if not os.path.exists(pjoin(self.me_dir,'Events','events.tree')): 861 misc.gunzip(pjoin(self.me_dir,'Events', 862 self.run_name, '%s_pythia_events.tree.gz' % tag), keep=True, 863 stdout=pjoin(self.me_dir,'Events','events.tree')) 864 files.mv(pjoin(self.me_dir,'Events',self.run_name, tag+'_pythia_xsecs.tree'), 865 pjoin(self.me_dir,'Events','xsecs.tree')) 866 867 # Generate the matching plots 868 misc.call([self.dirbin+'/create_matching_plots.sh', 869 self.run_name, tag, madir], 870 stdout = os.open(os.devnull, os.O_RDWR), 871 cwd=pjoin(self.me_dir,'Events')) 872 873 #Clean output 874 misc.gzip(pjoin(self.me_dir,"Events","events.tree"), 875 stdout=pjoin(self.me_dir,'Events',self.run_name, tag + '_pythia_events.tree.gz')) 876 files.mv(pjoin(self.me_dir,'Events','xsecs.tree'), 877 pjoin(self.me_dir,'Events',self.run_name, tag+'_pythia_xsecs.tree')) 878 879 880 if not event_path: 881 if mode == 'parton': 882 possibilities=[ 883 pjoin(self.me_dir, 'Events', 'unweighted_events.lhe'), 884 pjoin(self.me_dir, 'Events', 'unweighted_events.lhe.gz'), 885 pjoin(self.me_dir, 'Events', self.run_name, 'unweighted_events.lhe'), 886 pjoin(self.me_dir, 'Events', self.run_name, 'unweighted_events.lhe.gz')] 887 for event_path in possibilities: 888 if os.path.exists(event_path): 889 break 890 output = pjoin(self.me_dir, 'HTML',self.run_name, 'plots_parton.html') 891 892 elif mode == 'Pythia': 893 event_path = pjoin(self.me_dir, 'Events','pythia_events.lhe') 894 output = pjoin(self.me_dir, 'HTML',self.run_name, 895 'plots_pythia_%s.html' % tag) 896 elif mode == 'PGS': 897 event_path = pjoin(self.me_dir, 'Events', self.run_name, 898 '%s_pgs_events.lhco' % tag) 899 output = pjoin(self.me_dir, 'HTML',self.run_name, 900 'plots_pgs_%s.html' % tag) 901 elif mode == 'Delphes': 902 event_path = pjoin(self.me_dir, 'Events', self.run_name,'%s_delphes_events.lhco' % tag) 903 output = pjoin(self.me_dir, 'HTML',self.run_name, 904 'plots_delphes_%s.html' % tag) 905 elif mode == "shower": 906 event_path = pjoin(self.me_dir, 'Events','pythia_events.lhe') 907 output = pjoin(self.me_dir, 'HTML',self.run_name, 908 'plots_shower_%s.html' % tag) 909 if not self.options['pythia-pgs_path']: 910 return 911 else: 912 raise self.InvalidCmd, 'Invalid mode %s' % mode 913 elif mode == 'reweight' and not output: 914 output = pjoin(self.me_dir, 'HTML',self.run_name, 915 'plots_%s.html' % tag) 916 917 if not os.path.exists(event_path): 918 if os.path.exists(event_path+'.gz'): 919 misc.gunzip('%s.gz' % event_path) 920 else: 921 raise self.InvalidCmd, 'Events file %s does not exist' % event_path 922 elif event_path.endswith(".gz"): 923 misc.gunzip(event_path) 924 event_path = event_path[:-3] 925 926 927 self.update_status('Creating Plots for %s level' % mode, level = mode.lower()) 928 929 mode = mode.lower() 930 if mode not in ['parton', 'reweight']: 931 plot_dir = pjoin(self.me_dir, 'HTML', self.run_name,'plots_%s_%s' % (mode.lower(),tag)) 932 elif mode == 'parton': 933 plot_dir = pjoin(self.me_dir, 'HTML', self.run_name,'plots_parton') 934 else: 935 plot_dir =pjoin(self.me_dir, 'HTML', self.run_name,'plots_%s' % (tag)) 936 937 if not os.path.isdir(plot_dir): 938 os.makedirs(plot_dir) 939 940 files.ln(pjoin(self.me_dir, 'Cards','plot_card.dat'), plot_dir, 'ma_card.dat') 941 942 try: 943 proc = misc.Popen([os.path.join(madir, 'plot_events')], 944 stdout = open(pjoin(plot_dir, 'plot.log'),'w'), 945 stderr = subprocess.STDOUT, 946 stdin=subprocess.PIPE, 947 cwd=plot_dir) 948 proc.communicate('%s\n' % event_path) 949 del proc 950 #proc.wait() 951 misc.call(['%s/plot' % self.dirbin, madir, td], 952 stdout = open(pjoin(plot_dir, 'plot.log'),'a'), 953 stderr = subprocess.STDOUT, 954 cwd=plot_dir) 955 956 misc.call(['%s/plot_page-pl' % self.dirbin, 957 os.path.basename(plot_dir), 958 mode], 959 stdout = open(pjoin(plot_dir, 'plot.log'),'a'), 960 stderr = subprocess.STDOUT, 961 cwd=pjoin(self.me_dir, 'HTML', self.run_name)) 962 963 shutil.move(pjoin(self.me_dir, 'HTML',self.run_name ,'plots.html'), 964 output) 965 966 logger.info("Plots for %s level generated, see %s" % \ 967 (mode, output)) 968 except OSError, error: 969 logger.error('fail to create plot: %s. Please check that MadAnalysis is correctly installed.' % error) 970 971 self.update_status('End Plots for %s level' % mode, level = mode.lower(), 972 makehtml=False) 973 974 return True
975
976 - def run_hep2lhe(self, banner_path = None):
977 """Run hep2lhe on the file Events/pythia_events.hep""" 978 979 if not self.options['pythia-pgs_path']: 980 raise self.InvalidCmd, 'No pythia-pgs path defined' 981 982 pydir = pjoin(self.options['pythia-pgs_path'], 'src') 983 eradir = self.options['exrootanalysis_path'] 984 985 # Creating LHE file 986 if misc.is_executable(pjoin(pydir, 'hep2lhe')): 987 self.update_status('Creating shower LHE File (for plot)', level='pythia') 988 # Write the banner to the LHE file 989 out = open(pjoin(self.me_dir,'Events','pythia_events.lhe'), 'w') 990 #out.writelines('<LesHouchesEvents version=\"1.0\">\n') 991 out.writelines('<!--\n') 992 out.writelines('# Warning! Never use this file for detector studies!\n') 993 out.writelines('-->\n<!--\n') 994 if banner_path: 995 out.writelines(open(banner_path).read().replace('<LesHouchesEvents version="1.0">','')) 996 out.writelines('\n-->\n') 997 out.close() 998 999 self.cluster.launch_and_wait(self.dirbin+'/run_hep2lhe', 1000 argument= [pydir], 1001 cwd=pjoin(self.me_dir,'Events'), 1002 stdout=os.devnull) 1003 1004 logger.info('Warning! Never use this lhe file for detector studies!') 1005 # Creating ROOT file 1006 if eradir and misc.is_executable(pjoin(eradir, 'ExRootLHEFConverter')): 1007 self.update_status('Creating Pythia LHE Root File', level='pythia') 1008 try: 1009 misc.call([eradir+'/ExRootLHEFConverter', 1010 'pythia_events.lhe', 1011 pjoin(self.run_name, '%s_pythia_lhe_events.root' % self.run_tag)], 1012 cwd=pjoin(self.me_dir,'Events')) 1013 except Exception, error: 1014 misc.sprint('ExRootLHEFConverter fails', str(error), 1015 log=logger) 1016 pass
1017
1018 - def store_result(self):
1019 """Dummy routine, to be overwritten by daughter classes""" 1020 1021 pass
1022 ############################################################################
1023 - def do_reweight(self, line):
1024 """ Allow to reweight the events generated with a new choices of model 1025 parameter. 1026 """ 1027 1028 if '-from_cards' in line and not os.path.exists(pjoin(self.me_dir, 'Cards', 'reweight_card.dat')): 1029 return 1030 1031 # Check that MG5 directory is present . 1032 if MADEVENT and not self.options['mg5_path']: 1033 raise self.InvalidCmd, '''The module reweight requires that MG5 is installed on the system. 1034 You can install it and set its path in ./Cards/me5_configuration.txt''' 1035 elif MADEVENT: 1036 sys.path.append(self.options['mg5_path']) 1037 try: 1038 import madgraph.interface.reweight_interface as reweight_interface 1039 except ImportError: 1040 raise self.ConfigurationError, '''Can\'t load Reweight module. 1041 The variable mg5_path might not be correctly configured.''' 1042 1043 self.to_store.append('event') 1044 if not '-from_cards' in line: 1045 self.keep_cards(['reweight_card.dat']) 1046 self.ask_edit_cards(['reweight_card.dat'], 'fixed', plot=False) 1047 1048 # forbid this function to create an empty item in results. 1049 if self.results.current['cross'] == 0 and self.run_name: 1050 self.results.delete_run(self.run_name, self.run_tag) 1051 1052 # load the name of the event file 1053 args = self.split_arg(line) 1054 self.check_decay_events(args) 1055 # args now alway content the path to the valid files 1056 reweight_cmd = reweight_interface.ReweightInterface(args[0]) 1057 reweight_cmd.mother = self 1058 self.update_status('Running Reweight', level='madspin') 1059 1060 1061 path = pjoin(self.me_dir, 'Cards', 'reweight_card.dat') 1062 reweight_cmd.me_dir = self.me_dir 1063 reweight_cmd.import_command_file(path) 1064 1065 # re-define current run 1066 try: 1067 self.results.def_current(self.run_name, self.run_tag) 1068 except Exception: 1069 pass
1070 1071 ############################################################################
1072 - def do_pgs(self, line):
1073 """launch pgs""" 1074 1075 args = self.split_arg(line) 1076 # Check argument's validity 1077 if '--no_default' in args: 1078 no_default = True 1079 args.remove('--no_default') 1080 else: 1081 no_default = False 1082 1083 # Check all arguments 1084 # This might launch a gunzip in another thread. After the question 1085 # This thread need to be wait for completion. (This allow to have the 1086 # question right away and have the computer working in the same time) 1087 # if lock is define this a locker for the completion of the thread 1088 lock = self.check_pgs(args) 1089 1090 # Check that the pgs_card exists. If not copy the default 1091 if not os.path.exists(pjoin(self.me_dir, 'Cards', 'pgs_card.dat')): 1092 if no_default: 1093 logger.info('No pgs_card detected, so not run pgs') 1094 return 1095 1096 files.cp(pjoin(self.me_dir, 'Cards', 'pgs_card_default.dat'), 1097 pjoin(self.me_dir, 'Cards', 'pgs_card.dat')) 1098 logger.info('No pgs card found. Take the default one.') 1099 1100 if not (no_default or self.force): 1101 self.ask_edit_cards(['pgs_card.dat']) 1102 1103 self.update_status('prepare PGS run', level=None) 1104 1105 pgsdir = pjoin(self.options['pythia-pgs_path'], 'src') 1106 eradir = self.options['exrootanalysis_path'] 1107 madir = self.options['madanalysis_path'] 1108 td = self.options['td_path'] 1109 1110 # Compile pgs if not there 1111 if not misc.is_executable(pjoin(pgsdir, 'pgs')): 1112 logger.info('No PGS executable -- running make') 1113 misc.compile(cwd=pgsdir) 1114 1115 self.update_status('Running PGS', level='pgs') 1116 1117 tag = self.run_tag 1118 # Update the banner with the pgs card 1119 banner_path = pjoin(self.me_dir, 'Events', self.run_name, '%s_%s_banner.txt' % (self.run_name, self.run_tag)) 1120 if os.path.exists(pjoin(self.me_dir, 'Source', 'banner_header.txt')): 1121 self.banner.add(pjoin(self.me_dir, 'Cards','pgs_card.dat')) 1122 self.banner.write(banner_path) 1123 else: 1124 open(banner_path, 'w').close() 1125 1126 ######################################################################## 1127 # now pass the event to a detector simulator and reconstruct objects 1128 ######################################################################## 1129 if lock: 1130 lock.wait() 1131 # Prepare the output file with the banner 1132 ff = open(pjoin(self.me_dir, 'Events', 'pgs_events.lhco'), 'w') 1133 if os.path.exists(pjoin(self.me_dir, 'Source', 'banner_header.txt')): 1134 text = open(banner_path).read() 1135 text = '#%s' % text.replace('\n','\n#') 1136 dico = self.results[self.run_name].get_current_info() 1137 text +='\n## Integrated weight (pb) : %.4g' % dico['cross'] 1138 text +='\n## Number of Event : %s\n' % dico['nb_event'] 1139 ff.writelines(text) 1140 ff.close() 1141 1142 try: 1143 os.remove(pjoin(self.me_dir, 'Events', 'pgs.done')) 1144 except Exception: 1145 pass 1146 1147 pgs_log = pjoin(self.me_dir, 'Events', self.run_name, "%s_pgs.log" % tag) 1148 self.cluster.launch_and_wait('../bin/internal/run_pgs', 1149 argument=[pgsdir], cwd=pjoin(self.me_dir,'Events'), 1150 stdout=pgs_log, stderr=subprocess.STDOUT) 1151 1152 if not os.path.exists(pjoin(self.me_dir, 'Events', 'pgs.done')): 1153 logger.error('Fail to create LHCO events') 1154 return 1155 else: 1156 os.remove(pjoin(self.me_dir, 'Events', 'pgs.done')) 1157 1158 if os.path.getsize(banner_path) == os.path.getsize(pjoin(self.me_dir, 'Events','pgs_events.lhco')): 1159 misc.call(['cat pgs_uncleaned_events.lhco >> pgs_events.lhco'], 1160 cwd=pjoin(self.me_dir, 'Events')) 1161 os.remove(pjoin(self.me_dir, 'Events', 'pgs_uncleaned_events.lhco ')) 1162 1163 # Creating Root file 1164 if eradir and misc.is_executable(pjoin(eradir, 'ExRootLHCOlympicsConverter')): 1165 self.update_status('Creating PGS Root File', level='pgs') 1166 try: 1167 misc.call([eradir+'/ExRootLHCOlympicsConverter', 1168 'pgs_events.lhco',pjoin('%s/%s_pgs_events.root' % (self.run_name, tag))], 1169 cwd=pjoin(self.me_dir, 'Events')) 1170 except Exception: 1171 logger.warning('fail to produce Root output [problem with ExRootAnalysis') 1172 if os.path.exists(pjoin(self.me_dir, 'Events', 'pgs_events.lhco')): 1173 # Creating plots 1174 files.mv(pjoin(self.me_dir, 'Events', 'pgs_events.lhco'), 1175 pjoin(self.me_dir, 'Events', self.run_name, '%s_pgs_events.lhco' % tag)) 1176 self.create_plot('PGS') 1177 misc.gzip(pjoin(self.me_dir, 'Events', self.run_name, '%s_pgs_events.lhco' % tag)) 1178 1179 self.update_status('finish', level='pgs', makehtml=False)
1180 1181 ############################################################################
1182 - def do_compute_widths(self, line):
1183 """Require MG5 directory: Compute automatically the widths of a set 1184 of particles""" 1185 1186 1187 1188 args = self.split_arg(line) 1189 opts = self.check_compute_widths(args) 1190 1191 from madgraph.interface.master_interface import MasterCmd 1192 cmd = MasterCmd() 1193 self.define_child_cmd_interface(cmd, interface=False) 1194 cmd.exec_cmd('set automatic_html_opening False --no_save') 1195 if not opts['path']: 1196 opts['path'] = pjoin(self.me_dir, 'Cards', 'param_card.dat') 1197 if not opts['force'] : 1198 self.ask_edit_cards(['param_card'],[], plot=False) 1199 1200 1201 line = 'compute_widths %s %s' % \ 1202 (' '.join([str(i) for i in opts['particles']]), 1203 ' '.join('--%s=%s' % (key,value) for (key,value) in opts.items() 1204 if key not in ['model', 'force', 'particles'] and value)) 1205 cmd.exec_cmd(line, model=opts['model']) 1206 self.child = None 1207 del cmd
1208 1209 ############################################################################
1210 - def do_print_results(self, line):
1211 """Not in help:Print the cross-section/ number of events for a given run""" 1212 1213 args = self.split_arg(line) 1214 options={'path':None, 'mode':'w', 'format':'full'} 1215 for arg in list(args): 1216 if arg.startswith('--') and '=' in arg: 1217 name,value=arg.split('=',1) 1218 name = name [2:] 1219 options[name] = value 1220 args.remove(arg) 1221 1222 1223 if len(args) > 0: 1224 run_name = args[0] 1225 else: 1226 for i, run_name in enumerate(self.results.order): 1227 for j, one_result in enumerate(self.results[run_name]): 1228 if i or j: 1229 options['mode'] = "a" 1230 if options['path']: 1231 self.print_results_in_file(one_result, options['path'], options['mode'], options['format']) 1232 else: 1233 self.print_results_in_shell(one_result) 1234 return 1235 1236 if run_name not in self.results: 1237 raise self.InvalidCmd('%s is not a valid run_name or it doesn\'t have any information' \ 1238 % run_name) 1239 1240 1241 if len(args) == 2: 1242 tag = args[1] 1243 if tag.isdigit(): 1244 tag = int(tag) - 1 1245 if len(self.results[run_name]) < tag: 1246 raise self.InvalidCmd('Only %s different tag available' % \ 1247 len(self.results[run_name])) 1248 data = self.results[run_name][tag] 1249 else: 1250 data = self.results[run_name].return_tag(tag) 1251 else: 1252 data = self.results[run_name].return_tag(None) # return the last 1253 1254 if options['path']: 1255 self.print_results_in_file(data, options['path'], options['mode'], options['format']) 1256 else: 1257 self.print_results_in_shell(data)
1258 1259 1260 ############################################################################
1261 - def do_delphes(self, line):
1262 """ run delphes and make associate root file/plot """ 1263 1264 args = self.split_arg(line) 1265 # Check argument's validity 1266 if '--no_default' in args: 1267 no_default = True 1268 args.remove('--no_default') 1269 else: 1270 no_default = False 1271 # Check all arguments 1272 # This might launch a gunzip in another thread. After the question 1273 # This thread need to be wait for completion. (This allow to have the 1274 # question right away and have the computer working in the same time) 1275 # if lock is define this a locker for the completion of the thread 1276 lock = self.check_delphes(args) 1277 self.update_status('prepare delphes run', level=None) 1278 1279 1280 if os.path.exists(pjoin(self.options['delphes_path'], 'data')): 1281 delphes3 = False 1282 prog = '../bin/internal/run_delphes' 1283 else: 1284 delphes3 = True 1285 prog = '../bin/internal/run_delphes3' 1286 1287 # Check that the delphes_card exists. If not copy the default and 1288 # ask for edition of the card. 1289 if not os.path.exists(pjoin(self.me_dir, 'Cards', 'delphes_card.dat')): 1290 if no_default: 1291 logger.info('No delphes_card detected, so not run Delphes') 1292 return 1293 1294 files.cp(pjoin(self.me_dir, 'Cards', 'delphes_card_default.dat'), 1295 pjoin(self.me_dir, 'Cards', 'delphes_card.dat')) 1296 logger.info('No delphes card found. Take the default one.') 1297 if not delphes3 and not os.path.exists(pjoin(self.me_dir, 'Cards', 'delphes_trigger.dat')): 1298 files.cp(pjoin(self.me_dir, 'Cards', 'delphes_trigger_default.dat'), 1299 pjoin(self.me_dir, 'Cards', 'delphes_trigger.dat')) 1300 if not (no_default or self.force): 1301 if delphes3: 1302 self.ask_edit_cards(['delphes_card.dat'], args) 1303 else: 1304 self.ask_edit_cards(['delphes_card.dat', 'delphes_trigger.dat'], args) 1305 1306 self.update_status('Running Delphes', level=None) 1307 # Wait that the gunzip of the files is finished (if any) 1308 if lock: 1309 lock.wait() 1310 1311 1312 1313 delphes_dir = self.options['delphes_path'] 1314 tag = self.run_tag 1315 if os.path.exists(pjoin(self.me_dir, 'Source', 'banner_header.txt')): 1316 self.banner.add(pjoin(self.me_dir, 'Cards','delphes_card.dat')) 1317 if not delphes3: 1318 self.banner.add(pjoin(self.me_dir, 'Cards','delphes_trigger.dat')) 1319 self.banner.write(pjoin(self.me_dir, 'Events', self.run_name, '%s_%s_banner.txt' % (self.run_name, tag))) 1320 1321 cross = self.results[self.run_name].get_current_info()['cross'] 1322 1323 delphes_log = pjoin(self.me_dir, 'Events', self.run_name, "%s_delphes.log" % tag) 1324 self.cluster.launch_and_wait(prog, 1325 argument= [delphes_dir, self.run_name, tag, str(cross)], 1326 stdout=delphes_log, stderr=subprocess.STDOUT, 1327 cwd=pjoin(self.me_dir,'Events')) 1328 1329 if not os.path.exists(pjoin(self.me_dir, 'Events', 1330 self.run_name, '%s_delphes_events.lhco' % tag)): 1331 logger.error('Fail to create LHCO events from DELPHES') 1332 return 1333 1334 if os.path.exists(pjoin(self.me_dir,'Events','delphes.root')): 1335 source = pjoin(self.me_dir,'Events','delphes.root') 1336 target = pjoin(self.me_dir,'Events', self.run_name, "%s_delphes_events.root" % tag) 1337 files.mv(source, target) 1338 1339 #eradir = self.options['exrootanalysis_path'] 1340 madir = self.options['madanalysis_path'] 1341 td = self.options['td_path'] 1342 1343 # Creating plots 1344 self.create_plot('Delphes') 1345 1346 if os.path.exists(pjoin(self.me_dir, 'Events', self.run_name, '%s_delphes_events.lhco' % tag)): 1347 misc.gzip(pjoin(self.me_dir, 'Events', self.run_name, '%s_delphes_events.lhco' % tag)) 1348 1349 1350 1351 self.update_status('delphes done', level='delphes', makehtml=False)
1352 1353 ############################################################################
1354 - def get_pid_final_states(self):
1355 """Find the pid of all particles in the final states""" 1356 pids = set() 1357 subproc = [l.strip() for l in open(pjoin(self.me_dir,'SubProcesses', 1358 'subproc.mg'))] 1359 nb_init = self.ninitial 1360 pat = re.compile(r'''DATA \(IDUP\(I,\d+\),I=1,\d+\)/([\+\-\d,\s]*)/''', re.I) 1361 for Pdir in subproc: 1362 text = open(pjoin(self.me_dir, 'SubProcesses', Pdir, 'born_leshouche.inc')).read() 1363 group = pat.findall(text) 1364 for particles in group: 1365 particles = particles.split(',') 1366 pids.update(set(particles[nb_init:])) 1367 1368 return pids
1369 1370 ############################################################################
1371 - def get_pdf_input_filename(self):
1372 """return the name of the file which is used by the pdfset""" 1373 1374 if self.options["cluster_local_path"] and \ 1375 os.path.exists(self.options["cluster_local_path"]) and \ 1376 self.options['run_mode'] ==1: 1377 # no need to transfer the pdf. 1378 return '' 1379 1380 def check_cluster(path): 1381 if not self.options["cluster_local_path"] or \ 1382 os.path.exists(self.options["cluster_local_path"]) or\ 1383 self.options['run_mode'] !=1: 1384 return path 1385 main = self.options["cluster_local_path"] 1386 if os.path.isfile(path): 1387 filename = os.path.basename(path) 1388 possible_path = [pjoin(main, filename), 1389 pjoin(main, "lhadpf", filename), 1390 pjoin(main, "Pdfdata", filename)] 1391 if any(os.path.exists(p) for p in possible_path): 1392 return " " 1393 else: 1394 return path
1395 1396 1397 if hasattr(self, 'pdffile') and self.pdffile: 1398 return self.pdffile 1399 else: 1400 for line in open(pjoin(self.me_dir,'Source','PDF','pdf_list.txt')): 1401 data = line.split() 1402 if len(data) < 4: 1403 continue 1404 if data[1].lower() == self.run_card['pdlabel'].lower(): 1405 self.pdffile = check_cluster(pjoin(self.me_dir, 'lib', 'Pdfdata', data[2])) 1406 return self.pdffile 1407 else: 1408 # possible when using lhapdf 1409 path = pjoin(self.me_dir, 'lib', 'PDFsets') 1410 if os.path.exists(path): 1411 self.pdffile = path 1412 else: 1413 self.pdffile = " " 1414 return self.pdffile 1415
1416 - def do_quit(self, line):
1417 """Not in help: exit """ 1418 1419 1420 try: 1421 os.remove(pjoin(self.me_dir,'RunWeb')) 1422 except Exception, error: 1423 pass 1424 1425 try: 1426 self.store_result() 1427 except Exception: 1428 # If nothing runs they they are no result to update 1429 pass 1430 1431 try: 1432 self.update_status('', level=None) 1433 except Exception, error: 1434 pass 1435 try: 1436 devnull = open(os.devnull, 'w') 1437 misc.call(['./bin/internal/gen_cardhtml-pl'], cwd=self.me_dir, 1438 stdout=devnull, stderr=devnull) 1439 except Exception: 1440 pass 1441 try: 1442 devnull.close() 1443 except Exception: 1444 pass 1445 1446 return super(CommonRunCmd, self).do_quit(line)
1447 1448 1449 # Aliases 1450 do_EOF = do_quit 1451 do_exit = do_quit 1452 1453 ############################################################################
1454 - def do_open(self, line):
1455 """Open a text file/ eps file / html file""" 1456 1457 args = self.split_arg(line) 1458 # Check Argument validity and modify argument to be the real path 1459 self.check_open(args) 1460 file_path = args[0] 1461 1462 misc.open_file(file_path)
1463 1464 ############################################################################
1465 - def do_set(self, line, log=True):
1466 """Set an option, which will be default for coming generations/outputs 1467 """ 1468 # cmd calls automaticaly post_set after this command. 1469 1470 1471 args = self.split_arg(line) 1472 # Check the validity of the arguments 1473 self.check_set(args) 1474 # Check if we need to save this in the option file 1475 if args[0] in self.options_configuration and '--no_save' not in args: 1476 self.do_save('options --auto') 1477 1478 if args[0] == "stdout_level": 1479 if args[1].isdigit(): 1480 logging.root.setLevel(int(args[1])) 1481 logging.getLogger('madgraph').setLevel(int(args[1])) 1482 else: 1483 logging.root.setLevel(eval('logging.' + args[1])) 1484 logging.getLogger('madgraph').setLevel(eval('logging.' + args[1])) 1485 if log: logger.info('set output information to level: %s' % args[1]) 1486 elif args[0] == "fortran_compiler": 1487 if args[1] == 'None': 1488 args[1] = None 1489 self.options['fortran_compiler'] = args[1] 1490 current = misc.detect_current_compiler(pjoin(self.me_dir,'Source','make_opts'), 'fortran') 1491 if current != args[1] and args[1] != None: 1492 misc.mod_compilator(self.me_dir, args[1], current, 'gfortran') 1493 elif args[0] == "cpp_compiler": 1494 if args[1] == 'None': 1495 args[1] = None 1496 self.options['cpp_compiler'] = args[1] 1497 current = misc.detect_current_compiler(pjoin(self.me_dir,'Source','make_opts'), 'cpp') 1498 if current != args[1] and args[1] != None: 1499 misc.mod_compilator(self.me_dir, args[1], current, 'cpp') 1500 elif args[0] == "run_mode": 1501 if not args[1] in [0,1,2,'0','1','2']: 1502 raise self.InvalidCmd, 'run_mode should be 0, 1 or 2.' 1503 self.cluster_mode = int(args[1]) 1504 self.options['run_mode'] = self.cluster_mode 1505 elif args[0] in ['cluster_type', 'cluster_queue', 'cluster_temp_path']: 1506 if args[1] == 'None': 1507 args[1] = None 1508 self.options[args[0]] = args[1] 1509 # cluster (re)-initialization done later 1510 # self.cluster update at the end of the routine 1511 elif args[0] in ['cluster_nb_retry', 'cluster_retry_wait', 'cluster_size']: 1512 self.options[args[0]] = int(args[1]) 1513 # self.cluster update at the end of the routine 1514 elif args[0] == 'nb_core': 1515 if args[1] == 'None': 1516 import multiprocessing 1517 self.nb_core = multiprocessing.cpu_count() 1518 self.options['nb_core'] = self.nb_core 1519 return 1520 if not args[1].isdigit(): 1521 raise self.InvalidCmd('nb_core should be a positive number') 1522 self.nb_core = int(args[1]) 1523 self.options['nb_core'] = self.nb_core 1524 elif args[0] == 'timeout': 1525 self.options[args[0]] = int(args[1]) 1526 elif args[0] == 'cluster_status_update': 1527 if '(' in args[1]: 1528 data = ' '.join([a for a in args[1:] if not a.startswith('-')]) 1529 data = data.replace('(','').replace(')','').replace(',',' ').split() 1530 first, second = data[:2] 1531 else: 1532 first, second = args[1:3] 1533 1534 self.options[args[0]] = (int(first), int(second)) 1535 elif args[0] in self.options: 1536 if args[1] in ['None','True','False']: 1537 self.options[args[0]] = eval(args[1]) 1538 elif args[0].endswith('path'): 1539 if os.path.exists(args[1]): 1540 self.options[args[0]] = args[1] 1541 elif os.path.exists(pjoin(self.me_dir, args[1])): 1542 self.options[args[0]] = pjoin(self.me_dir, args[1]) 1543 else: 1544 raise self.InvalidCmd('Not a valid path: keep previous value: \'%s\'' % self.options[args[0]]) 1545 else: 1546 self.options[args[0]] = args[1]
1547
1548 - def post_set(self, stop, line):
1549 """Check if we need to save this in the option file""" 1550 try: 1551 args = self.split_arg(line) 1552 if 'cluster' in args[0] or args[0] == 'run_mode': 1553 self.configure_run_mode(self.options['run_mode']) 1554 1555 1556 # Check the validity of the arguments 1557 self.check_set(args) 1558 1559 if args[0] in self.options_configuration and '--no_save' not in args: 1560 self.exec_cmd('save options --auto') 1561 elif args[0] in self.options_madevent: 1562 logger.info('This option will be the default in any output that you are going to create in this session.') 1563 logger.info('In order to keep this changes permanent please run \'save options\'') 1564 return stop 1565 except self.InvalidCmd: 1566 return stop
1567
1568 - def configure_run_mode(self, run_mode):
1569 """change the way to submit job 0: single core, 1: cluster, 2: multicore""" 1570 1571 self.cluster_mode = run_mode 1572 self.options['run_mode'] = run_mode 1573 1574 if run_mode == 2: 1575 if not self.options['nb_core']: 1576 import multiprocessing 1577 self.options['nb_core'] = multiprocessing.cpu_count() 1578 nb_core = self.options['nb_core'] 1579 elif run_mode == 0: 1580 nb_core = 1 1581 1582 1583 1584 if run_mode in [0, 2]: 1585 self.cluster = cluster.MultiCore( 1586 **self.options) 1587 self.cluster.nb_core = nb_core 1588 #cluster_temp_path=self.options['cluster_temp_path'], 1589 1590 if self.cluster_mode == 1: 1591 opt = self.options 1592 cluster_name = opt['cluster_type'] 1593 self.cluster = cluster.from_name[cluster_name](**opt)
1594 1595
1596 - def check_param_card(self, path, run=True):
1597 """Check that all the width are define in the param_card. 1598 If some width are set on 'Auto', call the computation tools.""" 1599 1600 pattern = re.compile(r'''decay\s+(\+?\-?\d+)\s+auto(@NLO|)''',re.I) 1601 text = open(path).read() 1602 pdg_info = pattern.findall(text) 1603 if pdg_info: 1604 if run: 1605 logger.info('Computing the width set on auto in the param_card.dat') 1606 has_nlo = any(nlo.lower()=="@nlo" for _,nlo in pdg_info) 1607 pdg = [pdg for pdg,nlo in pdg_info] 1608 if not has_nlo: 1609 self.do_compute_widths('%s %s' % (' '.join(pdg), path)) 1610 else: 1611 self.do_compute_widths('%s %s --nlo' % (' '.join(pdg), path)) 1612 else: 1613 logger.info('''Some width are on Auto in the card. 1614 Those will be computed as soon as you have finish the edition of the cards. 1615 If you want to force the computation right now and being able to re-edit 1616 the cards afterwards, you can type \"compute_wdiths\".''')
1617 1618
1619 - def add_error_log_in_html(self, errortype=None):
1620 """If a ME run is currently running add a link in the html output""" 1621 1622 # Be very carefull to not raise any error here (the traceback 1623 #will be modify in that case.) 1624 if hasattr(self, 'results') and hasattr(self.results, 'current') and\ 1625 self.results.current and 'run_name' in self.results.current and \ 1626 hasattr(self, 'me_dir'): 1627 name = self.results.current['run_name'] 1628 tag = self.results.current['tag'] 1629 self.debug_output = pjoin(self.me_dir, '%s_%s_debug.log' % (name,tag)) 1630 if errortype: 1631 self.results.current.debug = errortype 1632 else: 1633 self.results.current.debug = self.debug_output 1634 1635 else: 1636 #Force class default 1637 self.debug_output = CommonRunCmd.debug_output 1638 if os.path.exists('ME5_debug') and not 'ME5_debug' in self.debug_output: 1639 os.remove('ME5_debug') 1640 if not 'ME5_debug' in self.debug_output: 1641 os.system('ln -s %s ME5_debug &> /dev/null' % self.debug_output)
1642 1643
1644 - def do_quit(self, line):
1645 """Not in help: exit """ 1646 1647 try: 1648 os.remove(pjoin(self.me_dir,'RunWeb')) 1649 except Exception: 1650 pass 1651 try: 1652 self.store_result() 1653 except Exception: 1654 # If nothing runs they they are no result to update 1655 pass 1656 1657 try: 1658 self.update_status('', level=None) 1659 except Exception, error: 1660 pass 1661 devnull = open(os.devnull, 'w') 1662 try: 1663 misc.call(['./bin/internal/gen_cardhtml-pl'], cwd=self.me_dir, 1664 stdout=devnull, stderr=devnull) 1665 except Exception: 1666 pass 1667 devnull.close() 1668 1669 return super(CommonRunCmd, self).do_quit(line)
1670 1671 # Aliases 1672 do_EOF = do_quit 1673 do_exit = do_quit 1674 1675
1676 - def update_status(self, status, level, makehtml=True, force=True, 1677 error=False, starttime = None, update_results=True, 1678 print_log=True):
1679 """ update the index status """ 1680 1681 if makehtml and not force: 1682 if hasattr(self, 'next_update') and time.time() < self.next_update: 1683 return 1684 else: 1685 self.next_update = time.time() + 3 1686 1687 if print_log: 1688 if isinstance(status, str): 1689 if '<br>' not in status: 1690 logger.info(status) 1691 elif starttime: 1692 running_time = misc.format_timer(time.time()-starttime) 1693 logger.info(' Idle: %s, Running: %s, Completed: %s [ %s ]' % \ 1694 (status[0], status[1], status[2], running_time)) 1695 else: 1696 logger.info(' Idle: %s, Running: %s, Completed: %s' % status[:3]) 1697 1698 if update_results: 1699 self.results.update(status, level, makehtml=makehtml, error=error)
1700 1701 1702 ############################################################################
1703 - def keep_cards(self, need_card=[], ignore=[]):
1704 """Ask the question when launching generate_events/multi_run""" 1705 1706 check_card = ['pythia_card.dat', 'pgs_card.dat','delphes_card.dat', 1707 'delphes_trigger.dat', 'madspin_card.dat', 'shower_card.dat', 1708 'reweight_card.dat'] 1709 1710 cards_path = pjoin(self.me_dir,'Cards') 1711 for card in check_card: 1712 if card in ignore: 1713 continue 1714 if card not in need_card: 1715 if os.path.exists(pjoin(cards_path, card)): 1716 os.remove(pjoin(cards_path, card)) 1717 else: 1718 if not os.path.exists(pjoin(cards_path, card)): 1719 default = card.replace('.dat', '_default.dat') 1720 files.cp(pjoin(cards_path, default),pjoin(cards_path, card))
1721 1722 ############################################################################
1723 - def set_configuration(self, config_path=None, final=True, initdir=None, amcatnlo=False):
1724 """ assign all configuration variable from file 1725 ./Cards/mg5_configuration.txt. assign to default if not define """ 1726 1727 if not hasattr(self, 'options') or not self.options: 1728 self.options = dict(self.options_configuration) 1729 self.options.update(self.options_madgraph) 1730 self.options.update(self.options_madevent) 1731 1732 if not config_path: 1733 if os.environ.has_key('MADGRAPH_BASE'): 1734 config_path = pjoin(os.environ['MADGRAPH_BASE'],'mg5_configuration.txt') 1735 self.set_configuration(config_path=config_path, final=final) 1736 return 1737 if 'HOME' in os.environ: 1738 config_path = pjoin(os.environ['HOME'],'.mg5', 1739 'mg5_configuration.txt') 1740 if os.path.exists(config_path): 1741 self.set_configuration(config_path=config_path, final=False) 1742 if amcatnlo: 1743 me5_config = pjoin(self.me_dir, 'Cards', 'amcatnlo_configuration.txt') 1744 else: 1745 me5_config = pjoin(self.me_dir, 'Cards', 'me5_configuration.txt') 1746 self.set_configuration(config_path=me5_config, final=False, initdir=self.me_dir) 1747 1748 if self.options.has_key('mg5_path') and self.options['mg5_path']: 1749 MG5DIR = self.options['mg5_path'] 1750 config_file = pjoin(MG5DIR, 'input', 'mg5_configuration.txt') 1751 self.set_configuration(config_path=config_file, final=False,initdir=MG5DIR) 1752 else: 1753 self.options['mg5_path'] = None 1754 return self.set_configuration(config_path=me5_config, final=final,initdir=self.me_dir) 1755 1756 config_file = open(config_path) 1757 1758 # read the file and extract information 1759 logger.info('load configuration from %s ' % config_file.name) 1760 for line in config_file: 1761 1762 if '#' in line: 1763 line = line.split('#',1)[0] 1764 line = line.replace('\n','').replace('\r\n','') 1765 try: 1766 name, value = line.split('=') 1767 except ValueError: 1768 pass 1769 else: 1770 name = name.strip() 1771 value = value.strip() 1772 if name.endswith('_path') and not name.startswith('cluster'): 1773 path = value 1774 if os.path.isdir(path): 1775 self.options[name] = os.path.realpath(path) 1776 continue 1777 if not initdir: 1778 continue 1779 path = pjoin(initdir, value) 1780 if os.path.isdir(path): 1781 self.options[name] = os.path.realpath(path) 1782 continue 1783 else: 1784 self.options[name] = value 1785 if value.lower() == "none": 1786 self.options[name] = None 1787 1788 if not final: 1789 return self.options # the return is usefull for unittest 1790 1791 # Treat each expected input 1792 # delphes/pythia/... path 1793 for key in self.options: 1794 # Final cross check for the path 1795 if key.endswith('path') and not key.startswith("cluster"): 1796 path = self.options[key] 1797 if path is None: 1798 continue 1799 if os.path.isdir(path): 1800 self.options[key] = os.path.realpath(path) 1801 continue 1802 path = pjoin(self.me_dir, self.options[key]) 1803 if os.path.isdir(path): 1804 self.options[key] = os.path.realpath(path) 1805 continue 1806 elif self.options.has_key('mg5_path') and self.options['mg5_path']: 1807 path = pjoin(self.options['mg5_path'], self.options[key]) 1808 if os.path.isdir(path): 1809 self.options[key] = os.path.realpath(path) 1810 continue 1811 self.options[key] = None 1812 elif key.startswith('cluster') and key != 'cluster_status_update': 1813 if key in ('cluster_nb_retry','cluster_wait_retry'): 1814 self.options[key] = int(self.options[key]) 1815 if hasattr(self,'cluster'): 1816 del self.cluster 1817 pass 1818 elif key == 'automatic_html_opening': 1819 if self.options[key] in ['False', 'True']: 1820 self.options[key] =eval(self.options[key]) 1821 elif key not in ['text_editor','eps_viewer','web_browser','stdout_level', 1822 'complex_mass_scheme', 'gauge', 'group_subprocesses']: 1823 # Default: try to set parameter 1824 try: 1825 self.do_set("%s %s --no_save" % (key, self.options[key]), log=False) 1826 except self.InvalidCmd: 1827 logger.warning("Option %s from config file not understood" \ 1828 % key) 1829 1830 # Configure the way to open a file: 1831 misc.open_file.configure(self.options) 1832 self.configure_run_mode(self.options['run_mode']) 1833 return self.options
1834 1835 @staticmethod
1836 - def find_available_run_name(me_dir):
1837 """ find a valid run_name for the current job """ 1838 1839 name = 'run_%02d' 1840 data = [int(s[4:j]) for s in os.listdir(pjoin(me_dir,'Events')) for 1841 j in range(4,len(s)+1) if \ 1842 s.startswith('run_') and s[4:j].isdigit()] 1843 return name % (max(data+[0])+1)
1844 1845 1846 ############################################################################
1847 - def do_decay_events(self,line):
1848 """Require MG5 directory: decay events with spin correlations 1849 """ 1850 1851 if '-from_cards' in line and not os.path.exists(pjoin(self.me_dir, 'Cards', 'madspin_card.dat')): 1852 return 1853 1854 # First need to load MadSpin 1855 1856 # Check that MG5 directory is present . 1857 if MADEVENT and not self.options['mg5_path']: 1858 raise self.InvalidCmd, '''The module decay_events requires that MG5 is installed on the system. 1859 You can install it and set its path in ./Cards/me5_configuration.txt''' 1860 elif MADEVENT: 1861 sys.path.append(self.options['mg5_path']) 1862 try: 1863 import MadSpin.decay as decay 1864 import MadSpin.interface_madspin as interface_madspin 1865 except ImportError: 1866 if __debug__: 1867 raise 1868 else: 1869 raise self.ConfigurationError, '''Can\'t load MadSpin 1870 The variable mg5_path might not be correctly configured.''' 1871 1872 self.update_status('Running MadSpin', level='madspin') 1873 if not '-from_cards' in line: 1874 self.keep_cards(['madspin_card.dat']) 1875 self.ask_edit_cards(['madspin_card.dat'], 'fixed', plot=False) 1876 self.help_decay_events(skip_syntax=True) 1877 1878 # load the name of the event file 1879 args = self.split_arg(line) 1880 self.check_decay_events(args) 1881 # args now alway content the path to the valid files 1882 madspin_cmd = interface_madspin.MadSpinInterface(args[0]) 1883 madspin_cmd.update_status = lambda *x,**opt: self.update_status(*x, level='madspin',**opt) 1884 1885 path = pjoin(self.me_dir, 'Cards', 'madspin_card.dat') 1886 1887 madspin_cmd.import_command_file(path) 1888 1889 # create a new run_name directory for this output 1890 i = 1 1891 while os.path.exists(pjoin(self.me_dir,'Events', '%s_decayed_%i' % (self.run_name,i))): 1892 i+=1 1893 new_run = '%s_decayed_%i' % (self.run_name,i) 1894 evt_dir = pjoin(self.me_dir, 'Events') 1895 1896 os.mkdir(pjoin(evt_dir, new_run)) 1897 current_file = args[0].replace('.lhe', '_decayed.lhe') 1898 new_file = pjoin(evt_dir, new_run, os.path.basename(args[0])) 1899 if not os.path.exists(current_file): 1900 if os.path.exists(current_file+'.gz'): 1901 current_file += '.gz' 1902 new_file += '.gz' 1903 else: 1904 logger.error('MadSpin fails to create any decayed file.') 1905 return 1906 1907 files.mv(current_file, new_file) 1908 logger.info("The decayed event file has been moved to the following location: ") 1909 logger.info(new_file) 1910 1911 if hasattr(self, 'results'): 1912 current = self.results.current 1913 nb_event = self.results.current['nb_event'] 1914 if not nb_event: 1915 current = self.results[self.run_name][0] 1916 nb_event = current['nb_event'] 1917 1918 cross = current['cross'] 1919 error = current['error'] 1920 self.results.add_run( new_run, self.run_card) 1921 self.results.add_detail('nb_event', nb_event) 1922 self.results.add_detail('cross', cross * madspin_cmd.branching_ratio) 1923 self.results.add_detail('error', error * madspin_cmd.branching_ratio + cross * madspin_cmd.err_branching_ratio) 1924 self.results.add_detail('run_mode', current['run_mode']) 1925 1926 self.run_name = new_run 1927 self.banner = madspin_cmd.banner 1928 self.banner.add(path) 1929 self.banner.write(pjoin(self.me_dir,'Events',self.run_name, '%s_%s_banner.txt' % 1930 (self.run_name, self.run_tag))) 1931 self.update_status('MadSpin Done', level='parton', makehtml=False) 1932 if 'unweighted' in os.path.basename(args[0]): 1933 self.create_plot('parton')
1934
1935 - def complete_decay_events(self, text, line, begidx, endidx):
1936 args = self.split_arg(line[0:begidx], error=False) 1937 if len(args) == 1: 1938 return self.complete_plot(text, line, begidx, endidx) 1939 else: 1940 return
1941
1942 - def complete_print_results(self,text, line, begidx, endidx):
1943 "Complete the print results command" 1944 args = self.split_arg(line[0:begidx], error=False) 1945 if len(args) == 1: 1946 #return valid run_name 1947 data = glob.glob(pjoin(self.me_dir, 'Events', '*','unweighted_events.lhe.gz')) 1948 data = [n.rsplit('/',2)[1] for n in data] 1949 tmp1 = self.list_completion(text, data) 1950 return tmp1 1951 else: 1952 data = glob.glob(pjoin(self.me_dir, 'Events', args[0], '*_pythia_events.hep.gz')) 1953 data = [os.path.basename(p).rsplit('_',1)[0] for p in data] 1954 data += ["--mode=a", "--mode=w", "--path=", "--format=short"] 1955 tmp1 = self.list_completion(text, data) 1956 return tmp1
1957
1958 - def help_print_result(self):
1959 logger.info("syntax: print_result [RUN] [TAG] [options]") 1960 logger.info("-- show in text format the status of the run (cross-section/nb-event/...)") 1961 logger.info("--path= defines the path of the output file.") 1962 logger.info("--mode=a allow to add the information at the end of the file.") 1963 logger.info("--format=short (only if --path is define)") 1964 logger.info(" allows to have a multi-column output easy to parse")
1965 1966 ############################################################################
1967 - def do_check_events(self, line):
1968 """ Run some sanity check on the generated events.""" 1969 1970 # Check that MG5 directory is present . 1971 if MADEVENT and not self.options['mg5_path']: 1972 raise self.InvalidCmd, '''The module reweight requires that MG5 is installed on the system. 1973 You can install it and set its path in ./Cards/me5_configuration.txt''' 1974 elif MADEVENT: 1975 sys.path.append(self.options['mg5_path']) 1976 try: 1977 import madgraph.interface.reweight_interface as reweight_interface 1978 except ImportError: 1979 raise self.ConfigurationError, '''Can\'t load Reweight module. 1980 The variable mg5_path might not be correctly configured.''' 1981 1982 1983 # load the name of the event file 1984 args = self.split_arg(line) 1985 self.check_check_events(args) 1986 # args now alway content the path to the valid files 1987 reweight_cmd = reweight_interface.ReweightInterface(args[0], allow_madspin=True) 1988 reweight_cmd.mother = self 1989 self.update_status('Running check on events', level='check') 1990 1991 reweight_cmd.check_events()
1992 1993 ############################################################################
1994 - def complete_check_events(self, text, line, begidx, endidx):
1995 args = self.split_arg(line[0:begidx], error=False) 1996 1997 if len(args) == 1 and os.path.sep not in text: 1998 #return valid run_name 1999 data = glob.glob(pjoin(self.me_dir, 'Events', '*','*events.lhe*')) 2000 data = [n.rsplit('/',2)[1] for n in data] 2001 return self.list_completion(text, data, line) 2002 else: 2003 return self.path_completion(text, 2004 os.path.join('.',*[a for a in args \ 2005 if a.endswith(os.path.sep)]))
2006
2007 - def complete_compute_widths(self, text, line, begidx, endidx):
2008 "Complete the compute_widths command" 2009 2010 args = self.split_arg(line[0:begidx]) 2011 2012 if args[-1] in ['--path=', '--output=']: 2013 completion = {'path': self.path_completion(text)} 2014 elif line[begidx-1] == os.path.sep: 2015 current_dir = pjoin(*[a for a in args if a.endswith(os.path.sep)]) 2016 if current_dir.startswith('--path='): 2017 current_dir = current_dir[7:] 2018 if current_dir.startswith('--output='): 2019 current_dir = current_dir[9:] 2020 completion = {'path': self.path_completion(text, current_dir)} 2021 else: 2022 completion = {} 2023 completion['options'] = self.list_completion(text, 2024 ['--path=', '--output=', '--min_br=0.\$', '--nlo', 2025 '--precision_channel=0.\$', '--body_decay=']) 2026 2027 return self.deal_multiple_categories(completion)
2028 2029 2030 # lhapdf-related functions 2058 2059
2060 - def get_characteristics(self, path=None):
2061 """reads the proc_characteristics file and initialises the correspondant 2062 dictionary""" 2063 2064 if not path: 2065 path = os.path.join(self.me_dir, 'SubProcesses', 'proc_characteristics') 2066 2067 self.proc_characteristics = banner_mod.ProcCharacteristic(path) 2068 return self.proc_characteristics
2069 2070
2071 - def copy_lhapdf_set(self, lhaid_list, pdfsets_dir):
2072 """copy (if needed) the lhapdf set corresponding to the lhaid in lhaid_list 2073 into lib/PDFsets""" 2074 2075 pdfsetname = '' 2076 for lhaid in lhaid_list: 2077 try: 2078 if not pdfsetname: 2079 if lhaid in self.lhapdf_pdfsets: 2080 pdfsetname = self.lhapdf_pdfsets[lhaid]['filename'] 2081 else: 2082 raise MadGraph5Error('lhaid %s not valid input number for the current lhapdf' % lhaid ) 2083 # just check the other ids refer to the same pdfsetname 2084 elif not \ 2085 self.lhapdf_pdfsets[lhaid]['filename'] == pdfsetname: 2086 raise MadGraph5Error(\ 2087 'lhaid and PDF_set_min/max in the run_card do not correspond to the' + \ 2088 'same PDF set. Please check the run_card.') 2089 except KeyError: 2090 if self.lhapdf_version.startswith('5'): 2091 raise MadGraph5Error(\ 2092 ('invalid lhaid set in th run_card: %d .\nPlease note that some sets' % lhaid) + \ 2093 '(eg MSTW 90%CL error sets) \nare not available in aMC@NLO + LHAPDF 5.x.x') 2094 else: 2095 logger.debug('%d not found in pdfsets.index' % lhaid) 2096 2097 2098 # check if the file exists, otherwise install it: 2099 # also check that the PDFsets dir exists, otherwise create it. 2100 # if fails, install the lhapdfset into lib/PDFsets 2101 if not os.path.isdir(pdfsets_dir): 2102 try: 2103 os.mkdir(pdfsets_dir) 2104 except OSError: 2105 pdfsets_dir = pjoin(self.me_dir, 'lib', 'PDFsets') 2106 else: 2107 #clean previous set of pdf used 2108 for name in os.listdir(pjoin(self.me_dir, 'lib', 'PDFsets')): 2109 if name != pdfsetname: 2110 try: 2111 if os.path.isdir(pjoin(self.me_dir, 'lib', 'PDFsets', name)): 2112 shutil.rmtree(pjoin(self.me_dir, 'lib', 'PDFsets', name)) 2113 else: 2114 os.remove(pjoin(self.me_dir, 'lib', 'PDFsets', name)) 2115 except Exception, error: 2116 logger.debug('%s', error) 2117 2118 if self.options["cluster_local_path"]: 2119 lhapdf_cluster_possibilities = [self.options["cluster_local_path"], 2120 pjoin(self.options["cluster_local_path"], "lhapdf"), 2121 pjoin(self.options["cluster_local_path"], "lhapdf", "pdfsets"), 2122 pjoin(self.options["cluster_local_path"], "..", "lhapdf"), 2123 pjoin(self.options["cluster_local_path"], "..", "lhapdf", "pdfsets"), 2124 pjoin(self.options["cluster_local_path"], "..", "lhapdf","pdfsets", "6.1") 2125 ] 2126 else: 2127 lhapdf_cluster_possibilities = [] 2128 2129 # Check if we need to copy the pdf 2130 if self.options["cluster_local_path"] and self.options["run_mode"] == 1 and \ 2131 any((os.path.exists(pjoin(d, pdfsetname)) for d in lhapdf_cluster_possibilities)): 2132 2133 os.environ["LHAPATH"] = [d for d in lhapdf_cluster_possibilities if os.path.exists(pjoin(d, pdfsetname))][0] 2134 os.environ["CLUSTER_LHAPATH"] = os.environ["LHAPATH"] 2135 # no need to copy it 2136 if os.path.exists(pjoin(pdfsets_dir, pdfsetname)): 2137 try: 2138 if os.path.isdir(pjoin(pdfsets_dir, name)): 2139 shutil.rmtree(pjoin(pdfsets_dir, name)) 2140 else: 2141 os.remove(pjoin(pdfsets_dir, name)) 2142 except Exception, error: 2143 logger.debug('%s', error) 2144 2145 #check that the pdfset is not already there 2146 elif not os.path.exists(pjoin(self.me_dir, 'lib', 'PDFsets', pdfsetname)) and \ 2147 not os.path.isdir(pjoin(self.me_dir, 'lib', 'PDFsets', pdfsetname)): 2148 2149 if pdfsetname and not os.path.exists(pjoin(pdfsets_dir, pdfsetname)): 2150 self.install_lhapdf_pdfset(pdfsets_dir, pdfsetname) 2151 2152 if os.path.exists(pjoin(pdfsets_dir, pdfsetname)): 2153 files.cp(pjoin(pdfsets_dir, pdfsetname), pjoin(self.me_dir, 'lib', 'PDFsets')) 2154 elif os.path.exists(pjoin(os.path.dirname(pdfsets_dir), pdfsetname)): 2155 files.cp(pjoin(os.path.dirname(pdfsets_dir), pdfsetname), pjoin(self.me_dir, 'lib', 'PDFsets'))
2156
2157 - def install_lhapdf_pdfset(self, pdfsets_dir, filename):
2158 """idownloads and install the pdfset filename in the pdfsets_dir""" 2159 lhapdf_version = self.get_lhapdf_version() 2160 logger.info('Trying to download %s' % filename) 2161 2162 if lhapdf_version.startswith('5.'): 2163 # use the lhapdf-getdata command, which is in the same path as 2164 # lhapdf-config 2165 getdata = self.options['lhapdf'].replace('lhapdf-config', ('lhapdf-getdata')) 2166 misc.call([getdata, filename], cwd = pdfsets_dir) 2167 2168 elif lhapdf_version.startswith('6.'): 2169 # use the "lhapdf install xxx" command, which is in the same path as 2170 # lhapdf-config 2171 getdata = self.options['lhapdf'].replace('lhapdf-config', ('lhapdf')) 2172 2173 misc.call([getdata, 'install', filename], cwd = pdfsets_dir) 2174 2175 else: 2176 raise MadGraph5Error('Not valid LHAPDF version: %s' % lhapdf_version) 2177 2178 # check taht the file has been installed in the global dir 2179 if os.path.exists(pjoin(pdfsets_dir, filename)) or \ 2180 os.path.isdir(pjoin(pdfsets_dir, filename)): 2181 logger.info('%s successfully downloaded and stored in %s' \ 2182 % (filename, pdfsets_dir)) 2183 #otherwise (if v5) save it locally 2184 elif lhapdf_version.startswith('5.'): 2185 logger.warning('Could not download %s into %s. Trying to save it locally' \ 2186 % (filename, pdfsets_dir)) 2187 self.install_lhapdf_pdfset(pjoin(self.me_dir, 'lib', 'PDFsets'), filename) 2188 else: 2189 raise MadGraph5Error, \ 2190 'Could not download %s into %s. Please try to install it manually.' \ 2191 % (filename, pdfsets_dir)
2192 2193
2194 - def get_lhapdf_pdfsets_list(self, pdfsets_dir):
2195 """read the PDFsets.index file, which should be located in the same 2196 place as pdfsets_dir, and return a list of dictionaries with the information 2197 about each pdf set""" 2198 lhapdf_version = self.get_lhapdf_version() 2199 2200 if lhapdf_version.startswith('5.'): 2201 if os.path.exists('%s.index' % pdfsets_dir): 2202 indexfile = '%s.index' % pdfsets_dir 2203 else: 2204 raise MadGraph5Error, 'index of lhapdf file not found' 2205 pdfsets_lines = \ 2206 [l for l in open(indexfile).read().split('\n') if l.strip() and \ 2207 not '90cl' in l] 2208 lhapdf_pdfsets = dict( (int(l.split()[0]), {'lhaid': int(l.split()[0]), 2209 'pdflib_ntype': int(l.split()[1]), 2210 'pdflib_ngroup': int(l.split()[2]), 2211 'pdflib_nset': int(l.split()[3]), 2212 'filename': l.split()[4], 2213 'lhapdf_nmem': int(l.split()[5]), 2214 'q2min': float(l.split()[6]), 2215 'q2max': float(l.split()[7]), 2216 'xmin': float(l.split()[8]), 2217 'xmax': float(l.split()[9]), 2218 'description': l.split()[10]}) \ 2219 for l in pdfsets_lines) 2220 2221 elif lhapdf_version.startswith('6.'): 2222 pdfsets_lines = \ 2223 [l for l in open(pjoin(pdfsets_dir, 'pdfsets.index')).read().split('\n') if l.strip()] 2224 lhapdf_pdfsets = dict( (int(l.split()[0]), 2225 {'lhaid': int(l.split()[0]), 2226 'filename': l.split()[1]}) \ 2227 for l in pdfsets_lines) 2228 2229 else: 2230 raise MadGraph5Error('Not valid LHAPDF version: %s' % lhapdf_version) 2231 2232 return lhapdf_pdfsets
2233 2234
2235 - def get_lhapdf_version(self):
2236 """returns the lhapdf version number""" 2237 if not hasattr(self, 'lhapdfversion'): 2238 self.lhapdf_version = \ 2239 subprocess.Popen([self.options['lhapdf'], '--version'], 2240 stdout = subprocess.PIPE).stdout.read().strip() 2241 2242 # this will be removed once some issues in lhapdf6 will be fixed 2243 if self.lhapdf_version.startswith('6.0'): 2244 raise MadGraph5Error('LHAPDF 6.0.x not supported. Please use v6.1 or later') 2245 2246 return self.lhapdf_version
2247 2248
2249 - def get_lhapdf_pdfsetsdir(self):
2250 lhapdf_version = self.get_lhapdf_version() 2251 2252 # check if the LHAPDF_DATA_PATH variable is defined 2253 if 'LHAPDF_DATA_PATH' in os.environ.keys() and os.environ['LHAPDF_DATA_PATH']: 2254 datadir = os.environ['LHAPDF_DATA_PATH'] 2255 2256 elif lhapdf_version.startswith('5.'): 2257 datadir = subprocess.Popen([self.options['lhapdf'], '--pdfsets-path'], 2258 stdout = subprocess.PIPE).stdout.read().strip() 2259 2260 elif lhapdf_version.startswith('6.'): 2261 datadir = subprocess.Popen([self.options['lhapdf'], '--datadir'], 2262 stdout = subprocess.PIPE).stdout.read().strip() 2263 2264 return datadir
2265
2266 -class AskforEditCard(cmd.OneLinePathCompletion):
2267 """A class for asking a question where in addition you can have the 2268 set command define and modifying the param_card/run_card correctly""" 2269 2270 special_shortcut = {'ebeam':['run_card ebeam1 %(0)s', 'run_card ebeam2 %(0)s'], 2271 'lpp': ['run_card lpp1 %(0)s', 'run_card lpp2 %(0)s' ], 2272 'lhc': ['run_card lpp1 1', 'run_card lpp2 1', 'run_card ebeam1 %(0)s*1000/2', 'run_card ebeam2 %(0)s*1000/2'], 2273 'lep': ['run_card lpp1 0', 'run_card lpp2 0', 'run_card ebeam1 %(0)s/2', 'run_card ebeam2 %(0)s/2'], 2274 'ilc': ['run_card lpp1 0', 'run_card lpp2 0', 'run_card ebeam1 %(0)s/2', 'run_card ebeam2 %(0)s/2'], 2275 'lcc':['run_card lpp1 1', 'run_card lpp2 1', 'run_card ebeam1 %(0)s*1000/2', 'run_card ebeam2 %(0)s*1000/2'], 2276 'fixed_scale': ['run_card fixed_fac_scale T', 'run_card fixed_ren_scale T', 'run_card scale %(0)s', 'run_card dsqrt_q2fact1 %(0)s' ,'run_card dsqrt_q2fact2 %(0)s'], 2277 } 2278
2279 - def __init__(self, question, cards=[], mode='auto', *args, **opt):
2280 2281 # Initiation 2282 if 'pwd' in opt: 2283 self.me_dir = opt['pwd'] 2284 del opt['pwd'] 2285 2286 cmd.OneLinePathCompletion.__init__(self, question, *args, **opt) 2287 2288 if not hasattr(self, 'me_dir') or not self.me_dir: 2289 self.me_dir = self.mother_interface.me_dir 2290 2291 # read the card 2292 2293 2294 try: 2295 self.param_card = check_param_card.ParamCard(pjoin(self.me_dir,'Cards','param_card.dat')) 2296 except (check_param_card.InvalidParamCard, ValueError) as e: 2297 logger.error('Current param_card is not valid. We are going to use the default one.') 2298 logger.error('problem detected: %s' % e) 2299 files.cp(pjoin(self.me_dir,'Cards','param_card_default.dat'), 2300 pjoin(self.me_dir,'Cards','param_card.dat')) 2301 self.param_card = check_param_card.ParamCard(pjoin(self.me_dir,'Cards','param_card.dat')) 2302 default_param = check_param_card.ParamCard(pjoin(self.me_dir,'Cards','param_card_default.dat')) 2303 2304 2305 try: 2306 self.run_card = banner_mod.RunCard(pjoin(self.me_dir,'Cards','run_card.dat')) 2307 except IOError: 2308 self.run_card = {} 2309 try: 2310 run_card_def = banner_mod.RunCard(pjoin(self.me_dir,'Cards','run_card_default.dat')) 2311 except IOError: 2312 run_card_def = {} 2313 2314 self.pname2block = {} 2315 self.conflict = [] 2316 self.restricted_value = {} 2317 self.mode = mode 2318 self.cards = cards 2319 2320 # Read the comment of the param_card_default to find name variable for 2321 # the param_card also check which value seems to be constrained in the 2322 # model. 2323 for bname, block in default_param.items(): 2324 for lha_id, param in block.param_dict.items(): 2325 all_var = [] 2326 comment = param.comment 2327 # treat merge parameter 2328 if comment.strip().startswith('set of param :'): 2329 all_var = list(re.findall(r'''[^-]1\*(\w*)\b''', comment)) 2330 # just the variable name as comment 2331 elif len(comment.split()) == 1: 2332 all_var = [comment.strip().lower()] 2333 # either contraction or not formatted 2334 else: 2335 split = comment.split() 2336 if len(split) >2 and split[1] == ':': 2337 # NO VAR associated 2338 self.restricted_value[(bname, lha_id)] = ' '.join(split[1:]) 2339 elif len(split) == 2: 2340 if re.search(r'''\[[A-Z]\]eV\^''', split[1]): 2341 all_var = [comment.strip().lower()] 2342 elif len(split) >=2 and split[1].startswith('('): 2343 all_var = [split[0].strip().lower()] 2344 else: 2345 if not bname.startswith('qnumbers'): 2346 logger.debug("not recognize information for %s %s : %s", 2347 bname, lha_id, comment) 2348 # not recognized format 2349 continue 2350 2351 for var in all_var: 2352 var = var.lower() 2353 if var in self.pname2block: 2354 self.pname2block[var].append((bname, lha_id)) 2355 else: 2356 self.pname2block[var] = [(bname, lha_id)] 2357 2358 if run_card_def: 2359 self.run_set = run_card_def.keys() + self.run_card.hidden_param 2360 elif self.run_card: 2361 self.run_set = self.run_card.keys() 2362 else: 2363 self.run_set = [] 2364 # check for conflict with run_card 2365 for var in self.pname2block: 2366 if var in self.run_set: 2367 self.conflict.append(var) 2368 2369 2370 #check if Madweight_card is present: 2371 self.has_mw = False 2372 if 'madweight_card.dat' in cards: 2373 2374 self.do_change_tf = self.mother_interface.do_define_transfer_fct 2375 self.complete_change_tf = self.mother_interface.complete_define_transfer_fct 2376 self.help_change_tf = self.mother_interface.help_define_transfer_fct 2377 if not os.path.exists(pjoin(self.me_dir,'Cards','transfer_card.dat')): 2378 logger.warning('No transfer function currently define. Please use the change_tf command to define one.') 2379 2380 2381 self.has_mw = True 2382 try: 2383 import madgraph.madweight.Cards as mwcards 2384 except: 2385 import internal.madweight.Cards as mwcards 2386 self.mw_card = mwcards.Card(pjoin(self.me_dir,'Cards','MadWeight_card.dat')) 2387 self.mw_card = self.mw_card.info 2388 self.mw_vars = [] 2389 for key in self.mw_card: 2390 if key == 'comment': 2391 continue 2392 for key2 in self.mw_card.info[key]: 2393 if isinstance(key2, str) and not key2.isdigit(): 2394 self.mw_vars.append(key2) 2395 2396 # check for conflict with run_card/param_card 2397 for var in self.pname2block: 2398 if var in self.mw_vars: 2399 self.conflict.append(var) 2400 for var in self.mw_vars: 2401 if var in self.run_card: 2402 self.conflict.append(var) 2403 2404 #check if MadLoopParams.dat is present: 2405 self.has_ml = False 2406 if os.path.isfile(pjoin(self.me_dir,'Cards','MadLoopParams.dat')): 2407 self.has_ml = True 2408 self.MLcard = banner_mod.MadLoopParam(pjoin(self.me_dir,'Cards','MadLoopParams.dat')) 2409 self.MLcardDefault = banner_mod.MadLoopParam() 2410 2411 self.ml_vars = [k.lower() for k in self.MLcard.keys()] 2412 # check for conflict 2413 for var in self.MLcard: 2414 if var in self.run_card: 2415 self.conflict.append(var) 2416 if var in self.pname2block: 2417 self.conflict.append(var) 2418 if self.has_mw and var in self.mw_vars: 2419 self.conflict.append(var) 2420 2421 #check if shower_card is present: 2422 self.has_shower = False 2423 if 'shower_card.dat' in cards: 2424 self.has_shower = True 2425 try: 2426 import madgraph.various.shower_card as showercards 2427 except: 2428 import internal.shower_card as showercards 2429 self.shower_card = showercards.ShowerCard(pjoin(self.me_dir,'Cards','shower_card.dat')) 2430 self.shower_vars = self.shower_card.keys() 2431 2432 # check for conflict with run_card/param_card 2433 for var in self.pname2block: 2434 if var in self.shower_vars: 2435 self.conflict.append(var) 2436 for var in self.shower_vars: 2437 if var in self.run_card: 2438 self.conflict.append(var)
2439 2440
2441 - def complete_set(self, text, line, begidx, endidx):
2442 """ Complete the set command""" 2443 2444 prev_timer = signal.alarm(0) # avoid timer if any 2445 if prev_timer: 2446 nb_back = len(line) 2447 self.stdout.write('\b'*nb_back + '[timer stopped]\n') 2448 self.stdout.write(line) 2449 self.stdout.flush() 2450 2451 possibilities = {} 2452 allowed = {} 2453 args = self.split_arg(line[0:begidx]) 2454 if args[-1] in ['Auto', 'default']: 2455 return 2456 if len(args) == 1: 2457 allowed = {'category':'', 'run_card':'', 'block':'all', 'param_card':'','shortcut':''} 2458 if self.has_mw: 2459 allowed['madweight_card'] = '' 2460 allowed['mw_block'] = 'all' 2461 if self.has_shower: 2462 allowed['shower_card'] = '' 2463 if self.has_ml: 2464 allowed['madloop_card'] = '' 2465 elif len(args) == 2: 2466 if args[1] == 'run_card': 2467 allowed = {'run_card':'default'} 2468 elif args[1] == 'param_card': 2469 allowed = {'block':'all', 'param_card':'default'} 2470 elif args[1] in self.param_card.keys(): 2471 allowed = {'block':args[1]} 2472 elif args[1] == 'width': 2473 allowed = {'block': 'decay'} 2474 elif args[1] == 'MadWeight_card': 2475 allowed = {'madweight_card':'default', 'mw_block': 'all'} 2476 elif args[1] == 'MadLoop_card': 2477 allowed = {'madloop_card':'default'} 2478 elif self.has_mw and args[1] in self.mw_card.keys(): 2479 allowed = {'mw_block':args[1]} 2480 elif args[1] == 'shower_card': 2481 allowed = {'shower_card':'default'} 2482 else: 2483 allowed = {'value':''} 2484 else: 2485 start = 1 2486 if args[1] in ['run_card', 'param_card', 'MadWeight_card', 'shower_card', 'MadLoop_card']: 2487 start = 2 2488 if args[-1] in self.pname2block.keys(): 2489 allowed['value'] = 'default' 2490 elif args[start] in self.param_card.keys() or args[start] == 'width': 2491 if args[start] == 'width': 2492 args[start] = 'decay' 2493 2494 if args[start+1:]: 2495 allowed = {'block':(args[start], args[start+1:])} 2496 else: 2497 allowed = {'block':args[start]} 2498 elif self.has_mw and args[start] in self.mw_card.keys(): 2499 if args[start+1:]: 2500 allowed = {'mw_block':(args[start], args[start+1:])} 2501 else: 2502 allowed = {'mw_block':args[start]} 2503 #elif len(args) == start +1: 2504 # allowed['value'] = '' 2505 else: 2506 allowed['value'] = '' 2507 2508 if 'category' in allowed.keys(): 2509 categories = ['run_card', 'param_card'] 2510 if self.has_mw: 2511 categories.append('MadWeight_card') 2512 if self.has_shower: 2513 categories.append('shower_card') 2514 if self.has_ml: 2515 categories.append('MadLoop_card') 2516 2517 possibilities['category of parameter (optional)'] = \ 2518 self.list_completion(text, categories) 2519 2520 if 'shortcut' in allowed.keys(): 2521 possibilities['special values'] = self.list_completion(text, self.special_shortcut.keys()+['qcut', 'showerkt']) 2522 2523 if 'run_card' in allowed.keys(): 2524 opts = self.run_set 2525 if allowed['run_card'] == 'default': 2526 opts.append('default') 2527 2528 possibilities['Run Card'] = self.list_completion(text, opts) 2529 2530 if 'param_card' in allowed.keys(): 2531 opts = self.pname2block.keys() 2532 if allowed['param_card'] == 'default': 2533 opts.append('default') 2534 possibilities['Param Card'] = self.list_completion(text, opts) 2535 2536 if 'madweight_card' in allowed.keys(): 2537 opts = self.mw_vars + [k for k in self.mw_card.keys() if k !='comment'] 2538 if allowed['madweight_card'] == 'default': 2539 opts.append('default') 2540 possibilities['MadWeight Card'] = self.list_completion(text, opts) 2541 2542 if 'madloop_card' in allowed.keys(): 2543 opts = self.ml_vars 2544 if allowed['madloop_card'] == 'default': 2545 opts.append('default') 2546 2547 possibilities['MadLoop Parameter'] = self.list_completion(text, opts) 2548 2549 if 'shower_card' in allowed.keys(): 2550 opts = self.shower_vars + [k for k in self.shower_card.keys() if k !='comment'] 2551 if allowed['shower_card'] == 'default': 2552 opts.append('default') 2553 possibilities['Shower Card'] = self.list_completion(text, opts) 2554 2555 if 'value' in allowed.keys(): 2556 opts = ['default'] 2557 if 'decay' in args: 2558 opts.append('Auto') 2559 opts.append('Auto@NLO') 2560 elif args[-1] in self.pname2block and self.pname2block[args[-1]][0][0] == 'decay': 2561 opts.append('Auto') 2562 opts.append('Auto@NLO') 2563 possibilities['Special Value'] = self.list_completion(text, opts) 2564 2565 if 'block' in allowed.keys(): 2566 if allowed['block'] == 'all': 2567 allowed_block = [i for i in self.param_card.keys() if 'qnumbers' not in i] 2568 allowed_block.append('width') 2569 possibilities['Param Card Block' ] = \ 2570 self.list_completion(text, allowed_block) 2571 elif isinstance(allowed['block'], basestring): 2572 block = self.param_card[allowed['block']].param_dict 2573 ids = [str(i[0]) for i in block 2574 if (allowed['block'], i) not in self.restricted_value] 2575 possibilities['Param Card id' ] = self.list_completion(text, ids) 2576 varname = [name for name, all_var in self.pname2block.items() 2577 if any((bname == allowed['block'] 2578 for bname,lhaid in all_var))] 2579 possibilities['Param card variable'] = self.list_completion(text, 2580 varname) 2581 else: 2582 block = self.param_card[allowed['block'][0]].param_dict 2583 nb = len(allowed['block'][1]) 2584 ids = [str(i[nb]) for i in block if len(i) > nb and \ 2585 [str(a) for a in i[:nb]] == allowed['block'][1]] 2586 2587 if not ids: 2588 if tuple([int(i) for i in allowed['block'][1]]) in block: 2589 opts = ['default'] 2590 if allowed['block'][0] == 'decay': 2591 opts.append('Auto') 2592 opts.append('Auto@NLO') 2593 possibilities['Special value'] = self.list_completion(text, opts) 2594 possibilities['Param Card id' ] = self.list_completion(text, ids) 2595 2596 if 'mw_block' in allowed.keys(): 2597 if allowed['mw_block'] == 'all': 2598 allowed_block = [i for i in self.mw_card.keys() if 'comment' not in i] 2599 possibilities['MadWeight Block' ] = \ 2600 self.list_completion(text, allowed_block) 2601 elif isinstance(allowed['mw_block'], basestring): 2602 block = self.mw_card[allowed['mw_block']] 2603 ids = [str(i[0]) if isinstance(i, tuple) else str(i) for i in block] 2604 possibilities['MadWeight Card id' ] = self.list_completion(text, ids) 2605 else: 2606 block = self.mw_card[allowed['mw_block'][0]] 2607 nb = len(allowed['mw_block'][1]) 2608 ids = [str(i[nb]) for i in block if isinstance(i, tuple) and\ 2609 len(i) > nb and \ 2610 [str(a) for a in i[:nb]] == allowed['mw_block'][1]] 2611 2612 if not ids: 2613 if tuple([i for i in allowed['mw_block'][1]]) in block or \ 2614 allowed['mw_block'][1][0] in block.keys(): 2615 opts = ['default'] 2616 possibilities['Special value'] = self.list_completion(text, opts) 2617 possibilities['MadWeight Card id' ] = self.list_completion(text, ids) 2618 2619 return self.deal_multiple_categories(possibilities)
2620
2621 - def do_set(self, line):
2622 """ edit the value of one parameter in the card""" 2623 2624 args = self.split_arg(line) 2625 if '=' in args[-1]: 2626 arg1, arg2 = args.pop(-1).split('=') 2627 args += [arg1, arg2] 2628 if '=' in args: 2629 args.remove('=') 2630 args[:-1] = [ a.lower() for a in args[:-1]] 2631 # special shortcut: 2632 if args[0] in self.special_shortcut: 2633 if len(args) == 1: 2634 values = {} 2635 elif len(args) == 2: 2636 targettype = float 2637 if args[1].strip().isdigit(): 2638 targettype = int 2639 2640 try: 2641 values = {'0': targettype(args[1])} 2642 except ValueError as e: 2643 logger.warning("Wrong argument: The last entry should be a number.") 2644 return 2645 else: 2646 logger.warning("too many argument for this command") 2647 return 2648 2649 for arg in self.special_shortcut[args[0]]: 2650 try: 2651 text = arg % values 2652 except KeyError: 2653 logger.warning("This command requires one argument") 2654 return 2655 except Exception as e: 2656 logger.warning(str(e)) 2657 return 2658 else: 2659 self.do_set(arg % values) 2660 return 2661 2662 2663 start = 0 2664 if len(args) < 2: 2665 logger.warning('Invalid set command %s (need two arguments)' % line) 2666 return 2667 2668 # Special case for the qcut value 2669 if args[0].lower() == 'qcut': 2670 pythia_path = pjoin(self.me_dir, 'Cards','pythia_card.dat') 2671 if os.path.exists(pythia_path): 2672 logger.info('add line QCUT = %s in pythia_card.dat' % args[1]) 2673 p_card = open(pythia_path,'r').read() 2674 p_card, n = re.subn('''^\s*QCUT\s*=\s*[\de\+\-\.]*\s*$''', 2675 ''' QCUT = %s ''' % args[1], \ 2676 p_card, flags=(re.M+re.I)) 2677 if n==0: 2678 p_card = '%s \n QCUT= %s' % (p_card, args[1]) 2679 open(pythia_path, 'w').write(p_card) 2680 return 2681 # Special case for the showerkt value 2682 if args[0].lower() == 'showerkt': 2683 pythia_path = pjoin(self.me_dir, 'Cards','pythia_card.dat') 2684 if os.path.exists(pythia_path): 2685 logger.info('add line SHOWERKT = %s in pythia_card.dat' % args[1].upper()) 2686 p_card = open(pythia_path,'r').read() 2687 p_card, n = re.subn('''^\s*SHOWERKT\s*=\s*[default\de\+\-\.]*\s*$''', 2688 ''' SHOWERKT = %s ''' % args[1].upper(), \ 2689 p_card, flags=(re.M+re.I)) 2690 if n==0: 2691 p_card = '%s \n SHOWERKT= %s' % (p_card, args[1].upper()) 2692 open(pythia_path, 'w').write(p_card) 2693 return 2694 2695 2696 card = '' #store which card need to be modify (for name conflict) 2697 if args[0] == 'madweight_card': 2698 if not self.mw_card: 2699 logger.warning('Invalid Command: No MadWeight card defined.') 2700 return 2701 args[0] = 'MadWeight_card' 2702 2703 if args[0] == 'shower_card': 2704 if not self.shower_card: 2705 logger.warning('Invalid Command: No Shower card defined.') 2706 return 2707 args[0] = 'shower_card' 2708 2709 if args[0] == "madloop_card": 2710 if not self.has_ml: 2711 logger.warning('Invalid Command: No MadLoopParam card defined.') 2712 return 2713 args[0] = 'MadLoop_card' 2714 2715 if args[0] in ['run_card', 'param_card', 'MadWeight_card', 'shower_card']: 2716 if args[1] == 'default': 2717 logging.info('replace %s by the default card' % args[0]) 2718 files.cp(pjoin(self.me_dir,'Cards','%s_default.dat' % args[0]), 2719 pjoin(self.me_dir,'Cards','%s.dat'% args[0])) 2720 if args[0] == 'param_card': 2721 self.param_card = check_param_card.ParamCard(pjoin(self.me_dir,'Cards','param_card.dat')) 2722 elif args[0] == 'run_card': 2723 self.run_card = banner_mod.RunCard(pjoin(self.me_dir,'Cards','run_card.dat')) 2724 elif args[0] == 'shower_card': 2725 self.shower_card = shower_card_mod.ShowerCard(pjoin(self.me_dir,'Cards','shower_card.dat')) 2726 return 2727 else: 2728 card = args[0] 2729 start=1 2730 if len(args) < 3: 2731 logger.warning('Invalid set command: %s (not enough arguments)' % line) 2732 return 2733 2734 elif args[0] in ['MadLoop_card']: 2735 if args[1] == 'default': 2736 logging.info('replace MadLoopParams.dat by the default card') 2737 self.MLcard = banner_mod.MadLoopParam(self.MLcardDefault) 2738 self.MLcard.write(pjoin(self.me_dir,'Cards','MadLoopParams.dat'), 2739 commentdefault=True) 2740 return 2741 else: 2742 card = args[0] 2743 start=1 2744 if len(args) < 3: 2745 logger.warning('Invalid set command: %s (not enough arguments)' % line) 2746 return 2747 elif args[0] in ['madspin_card']: 2748 if args[1] == 'default': 2749 logging.info('replace madspin_card.dat by the default card') 2750 files.cp(pjoin(self.me_dir,'Cards/madspin_card_default.dat'), 2751 pjoin(self.me_dir,'Cards/madspin_card.dat')) 2752 return 2753 else: 2754 logger.warning("""Command set not allowed for modifying the madspin_card. 2755 Check the command \"decay\" instead.""") 2756 return 2757 2758 #### RUN CARD 2759 if args[start] in [l.lower() for l in self.run_card.keys()] and card in ['', 'run_card']: 2760 if args[start] not in self.run_set: 2761 args[start] = [l for l in self.run_set if l.lower() == args[start]][0] 2762 2763 if args[start] in self.conflict and card == '': 2764 text = 'Ambiguous name (present in more than one card). Will assume it to be referred to run_card.\n' 2765 text += 'If this is not intended, please reset it in the run_card and specify the relevant card to \n' 2766 text += 'edit, in the format < set card parameter value >' 2767 logger.warning(text) 2768 2769 if args[start+1] == 'default': 2770 default = banner_mod.RunCard(pjoin(self.me_dir,'Cards','run_card_default.dat')) 2771 if args[start] in default.keys(): 2772 self.setR(args[start],default[args[start]]) 2773 else: 2774 logger.info('remove information %s from the run_card' % args[start]) 2775 del self.run_card[args[start]] 2776 elif args[start+1].lower() in ['t','.true.','true']: 2777 self.setR(args[start], '.true.') 2778 elif args[start+1].lower() in ['f','.false.','false']: 2779 self.setR(args[start], '.false.') 2780 else: 2781 if args[0].startswith('sys_'): 2782 val = ' '.join(args[start+1:]) 2783 val = val.split('#')[0] 2784 else: 2785 try: 2786 val = eval(args[start+1]) 2787 except NameError: 2788 val = args[start+1] 2789 self.setR(args[start], val) 2790 self.run_card.write(pjoin(self.me_dir,'Cards','run_card.dat'), 2791 pjoin(self.me_dir,'Cards','run_card_default.dat')) 2792 2793 ### PARAM_CARD WITH BLOCK NAME ----------------------------------------- 2794 elif (args[start] in self.param_card or args[start] == 'width') \ 2795 and card in ['','param_card']: 2796 if args[start] in self.conflict and card == '': 2797 text = 'ambiguous name (present in more than one card). Please specify which card to edit' 2798 text += ' in the format < set card parameter value>' 2799 logger.warning(text) 2800 return 2801 2802 if args[start] == 'width': 2803 args[start] = 'decay' 2804 2805 if args[start+1] in self.pname2block: 2806 all_var = self.pname2block[args[start+1]] 2807 key = None 2808 for bname, lhaid in all_var: 2809 if bname == args[start]: 2810 key = lhaid 2811 break 2812 else: 2813 logger.warning('%s is not part of block "%s" but "%s". please correct.' % 2814 (args[start+1], args[start], bname)) 2815 return 2816 else: 2817 try: 2818 key = tuple([int(i) for i in args[start+1:-1]]) 2819 except ValueError: 2820 if args[start] == 'decay' and args[start+1:-1] == ['all']: 2821 for key in self.param_card[args[start]].param_dict: 2822 if (args[start], key) in self.restricted_value: 2823 continue 2824 else: 2825 self.setP(args[start], key, args[-1]) 2826 self.param_card.write(pjoin(self.me_dir,'Cards','param_card.dat')) 2827 return 2828 logger.warning('invalid set command %s (failed to identify LHA information)' % line) 2829 return 2830 2831 if key in self.param_card[args[start]].param_dict: 2832 if (args[start], key) in self.restricted_value: 2833 text = "Note that this parameter seems to be ignore by MG.\n" 2834 text += "MG will use instead the expression: %s\n" % \ 2835 self.restricted_value[(args[start], key)] 2836 text += "You need to match this expression for external program (such pythia)." 2837 logger.warning(text) 2838 2839 if args[-1].lower() in ['default', 'auto', 'auto@nlo']: 2840 self.setP(args[start], key, args[-1]) 2841 else: 2842 try: 2843 value = float(args[-1]) 2844 except Exception: 2845 logger.warning('Invalid input: Expected number and not \'%s\'' \ 2846 % args[-1]) 2847 return 2848 self.setP(args[start], key, value) 2849 else: 2850 logger.warning('invalid set command %s' % line) 2851 return 2852 self.param_card.write(pjoin(self.me_dir,'Cards','param_card.dat')) 2853 2854 # PARAM_CARD NO BLOCK NAME --------------------------------------------- 2855 elif args[start] in self.pname2block and card != 'run_card': 2856 if args[start] in self.conflict and card == '': 2857 text = 'ambiguous name (present in more than one card). Please specify which card to edit' 2858 text += ' in the format < set card parameter value>' 2859 logger.warning(text) 2860 return 2861 2862 all_var = self.pname2block[args[start]] 2863 for bname, lhaid in all_var: 2864 new_line = 'param_card %s %s %s' % (bname, 2865 ' '.join([ str(i) for i in lhaid]), ' '.join(args[start+1:])) 2866 self.do_set(new_line) 2867 if len(all_var) > 1: 2868 logger.warning('This variable correspond to more than one parameter in the param_card.') 2869 for bname, lhaid in all_var: 2870 logger.warning(' %s %s' % (bname, ' '.join([str(i) for i in lhaid]))) 2871 logger.warning('all listed variables have been modified') 2872 2873 # MadWeight_card with block name --------------------------------------- 2874 elif self.has_mw and (args[start] in self.mw_card and args[start] != 'comment') \ 2875 and card in ['','MadWeight_card']: 2876 2877 if args[start] in self.conflict and card == '': 2878 text = 'ambiguous name (present in more than one card). Please specify which card to edit' 2879 text += ' in the format < set card parameter value>' 2880 logger.warning(text) 2881 return 2882 2883 block = args[start] 2884 name = args[start+1] 2885 value = args[start+2:] 2886 self.setM(block, name, value) 2887 self.mw_card.write(pjoin(self.me_dir,'Cards','MadWeight_card.dat')) 2888 2889 # MadWeight_card NO Block name ----------------------------------------- 2890 elif self.has_mw and args[start] in self.mw_vars \ 2891 and card in ['', 'MadWeight_card']: 2892 2893 if args[start] in self.conflict and card == '': 2894 text = 'ambiguous name (present in more than one card). Please specify which card to edit' 2895 text += ' in the format < set card parameter value>' 2896 logger.warning(text) 2897 return 2898 2899 block = [b for b, data in self.mw_card.items() if args[start] in data] 2900 if len(block) > 1: 2901 logger.warning('%s is define in more than one block: %s.Please specify.' 2902 % (args[start], ','.join(block))) 2903 return 2904 2905 block = block[0] 2906 name = args[start] 2907 value = args[start+1:] 2908 self.setM(block, name, value) 2909 self.mw_card.write(pjoin(self.me_dir,'Cards','MadWeight_card.dat')) 2910 2911 # MadWeight_card New Block --------------------------------------------- 2912 elif self.has_mw and args[start].startswith('mw_') and len(args[start:]) == 3\ 2913 and card == 'MadWeight_card': 2914 block = args[start] 2915 name = args[start+1] 2916 value = args[start+2] 2917 self.setM(block, name, value) 2918 self.mw_card.write(pjoin(self.me_dir,'Cards','MadWeight_card.dat')) 2919 2920 #### SHOWER CARD 2921 elif self.has_shower and args[start] in [l.lower() for l in \ 2922 self.shower_card.keys()] and card in ['', 'shower_card']: 2923 if args[start] not in self.shower_card: 2924 args[start] = [l for l in self.shower_card if l.lower() == args[start]][0] 2925 2926 if args[start] in self.conflict and card == '': 2927 text = 'ambiguous name (present in more than one card). Please specify which card to edit' 2928 text += ' in the format < set card parameter value>' 2929 logger.warning(text) 2930 return 2931 2932 if args[start+1].lower() == 'default': 2933 default = shower_card_mod.ShowerCard(pjoin(self.me_dir,'Cards','shower_card_default.dat')) 2934 if args[start] in default.keys(): 2935 self.shower_card.set_param(args[start],default[args[start]],pjoin(self.me_dir,'Cards','shower_card.dat')) 2936 else: 2937 logger.info('remove information %s from the shower_card' % args[start]) 2938 del self.shower_card[args[start]] 2939 elif args[start+1].lower() in ['t','.true.','true']: 2940 self.shower_card.set_param(args[start],'.true.',pjoin(self.me_dir,'Cards','shower_card.dat')) 2941 elif args[start+1].lower() in ['f','.false.','false']: 2942 self.shower_card.set_param(args[start],'.false.',pjoin(self.me_dir,'Cards','shower_card.dat')) 2943 else: 2944 args_str = ' '.join(str(a) for a in args[start+1:len(args)]) 2945 self.shower_card.set_param(args[start],args_str,pjoin(self.me_dir,'Cards','shower_card.dat')) 2946 2947 # MadLoop Parameter --------------------------------------------------- 2948 elif self.has_ml and args[start] in self.ml_vars \ 2949 and card in ['', 'MadLoop_card']: 2950 2951 if args[start] in self.conflict and card == '': 2952 text = 'ambiguous name (present in more than one card). Please specify which card to edit' 2953 logger.warning(text) 2954 return 2955 2956 if args[start+1] == 'default': 2957 value = self.MLcardDefault[args[start]] 2958 default = True 2959 else: 2960 value = args[start+1] 2961 default = False 2962 self.setML(args[start], value, default=default) 2963 self.MLcard.write(pjoin(self.me_dir,'Cards','MadLoopParams.dat'), 2964 commentdefault=True) 2965 2966 #INVALID -------------------------------------------------------------- 2967 else: 2968 logger.warning('invalid set command %s ' % line) 2969 return
2970
2971 - def setM(self, block, name, value):
2972 2973 if isinstance(value, list) and len(value) == 1: 2974 value = value[0] 2975 2976 if block not in self.mw_card: 2977 logger.warning('block %s was not present in the current MadWeight card. We are adding it' % block) 2978 self.mw_card[block] = {} 2979 elif name not in self.mw_card[block]: 2980 logger.info('name %s was not present in the block %s for the current MadWeight card. We are adding it' % (name,block),'$MG:color:BLACK') 2981 if value == 'default': 2982 import madgraph.madweight.Cards as mwcards 2983 mw_default = mwcards.Card(pjoin(self.me_dir,'Cards','MadWeight_card_default.dat')) 2984 try: 2985 value = mw_default[block][name] 2986 except KeyError: 2987 logger.info('removing id "%s" from Block "%s" '% (name, block)) 2988 if name in self.mw_card[block]: 2989 del self.mw_card[block][name] 2990 return 2991 if value: 2992 logger.info('modify madweight_card information BLOCK "%s" with id "%s" set to %s' %\ 2993 (block, name, value), '$MG:color:BLACK') 2994 else: 2995 logger.value("Invalid command: No value. To set default value. Use \"default\" as value") 2996 return 2997 2998 self.mw_card[block][name] = value
2999
3000 - def setR(self, name, value):
3001 logger.info('modify parameter %s of the run_card.dat to %s' % (name, value)) 3002 self.run_card.set(name, value, user=True)
3003
3004 - def setML(self, name, value, default=False):
3005 3006 try: 3007 self.MLcard.set(name, value, user=True) 3008 except Exception, error: 3009 logger.warning("Fail to change parameter. Please Retry. Reason: %s." % error) 3010 return 3011 logger.info('modify parameter %s of the MadLoopParam.dat to %s' % (name, value)) 3012 if default and name.lower() in self.MLcard.user_set: 3013 self.MLcard.user_set.remove(name.lower())
3014
3015 - def setP(self, block, lhaid, value):
3016 if isinstance(value, str): 3017 value = value.lower() 3018 if value == 'default': 3019 default = check_param_card.ParamCard(pjoin(self.me_dir,'Cards','param_card_default.dat')) 3020 value = default[block].param_dict[lhaid].value 3021 3022 elif value in ['auto', 'auto@nlo']: 3023 if 'nlo' in value: 3024 value = 'Auto@NLO' 3025 else: 3026 value = 'Auto' 3027 if block != 'decay': 3028 logger.warning('Invalid input: \'Auto\' value only valid for DECAY') 3029 return 3030 else: 3031 try: 3032 value = float(value) 3033 except ValueError: 3034 logger.warning('Invalid input: \'%s\' not valid intput.'% value) 3035 3036 logger.info('modify param_card information BLOCK %s with id %s set to %s' %\ 3037 (block, lhaid, value), '$MG:color:BLACK') 3038 self.param_card[block].param_dict[lhaid].value = value
3039
3040 - def reask(self, *args, **opt):
3041 3042 cmd.OneLinePathCompletion.reask(self,*args, **opt) 3043 if self.has_mw and not os.path.exists(pjoin(self.me_dir,'Cards','transfer_card.dat')): 3044 logger.warning('No transfer function currently define. Please use the change_tf command to define one.')
3045 3046
3047 - def help_set(self):
3048 '''help message for set''' 3049 3050 logger.info('********************* HELP SET ***************************') 3051 logger.info("syntax: set [run_card|param_card] NAME [VALUE|default]") 3052 logger.info("syntax: set [param_card] BLOCK ID(s) [VALUE|default]") 3053 logger.info('') 3054 logger.info('-- Edit the param_card/run_card and replace the value of the') 3055 logger.info(' parameter by the value VALUE.') 3056 logger.info(' ') 3057 logger.info('-- Example:') 3058 logger.info(' set run_card ebeam1 4000') 3059 logger.info(' set ebeam2 4000') 3060 logger.info(' set lpp1 0') 3061 logger.info(' set ptj default') 3062 logger.info('') 3063 logger.info(' set param_card mass 6 175') 3064 logger.info(' set mass 25 125.3') 3065 logger.info(' set mass mh 125') 3066 logger.info(' set mh 125') 3067 logger.info(' set decay 25 0.004') 3068 logger.info(' set decay wh 0.004') 3069 logger.info(' set vmix 2 1 2.326612e-01') 3070 logger.info('') 3071 logger.info(' set param_card default #return all parameter to default') 3072 logger.info(' set run_card default') 3073 logger.info('********************* HELP SET ***************************')
3074 3075
3076 - def default(self, line):
3077 """Default action if line is not recognized""" 3078 3079 line = line.strip() 3080 args = line.split() 3081 if line == '' and self.default_value is not None: 3082 self.value = self.default_value 3083 # check if input is a file 3084 elif hasattr(self, 'do_%s' % args[0]): 3085 self.do_set(' '.join(args[1:])) 3086 elif os.path.isfile(line): 3087 self.copy_file(line) 3088 self.value = 'repeat' 3089 elif os.path.exists(pjoin(self.me_dir, line)): 3090 self.copy_file(pjoin(self.me_dir,line)) 3091 self.value = 'repeat' 3092 elif line.strip() != '0' and line.strip() != 'done' and \ 3093 str(line) != 'EOF' and line.strip() in self.allow_arg: 3094 self.open_file(line) 3095 self.value = 'repeat' 3096 else: 3097 self.value = line 3098 3099 return line
3100
3101 - def do_decay(self, line):
3102 """edit the madspin_card to define the decay of the associate particle""" 3103 signal.alarm(0) # avoid timer if any 3104 path = pjoin(self.me_dir,'Cards','madspin_card.dat') 3105 3106 if 'madspin_card.dat' not in self.cards or not os.path.exists(path): 3107 logger.warning("Command decay not valid. Since MadSpin is not available.") 3108 return 3109 3110 if ">" not in line: 3111 logger.warning("invalid command for decay. Line ignored") 3112 return 3113 3114 misc.sprint( line, "-add" in line) 3115 if "-add" in line: 3116 # just to have to add the line to the end of the file 3117 particle = line.split('>')[0].strip() 3118 text = open(path).read() 3119 line = line.replace('--add', '').replace('-add','') 3120 logger.info("change madspin_card to add one decay to %s: %s" %(particle, line.strip()), '$MG:color:BLACK') 3121 3122 text = text.replace('launch', "\ndecay %s\nlaunch\n" % line,1) 3123 open(path,'w').write(text) 3124 else: 3125 # Here we have to remove all the previous definition of the decay 3126 #first find the particle 3127 particle = line.split('>')[0].strip() 3128 logger.info("change madspin_card to define the decay of %s: %s" %(particle, line.strip()), '$MG:color:BLACK') 3129 particle = particle.replace('+','\+').replace('-','\-') 3130 decay_pattern = re.compile(r"^\s*decay\s+%s\s*>[\s\w+-~]*?$" % particle, re.I+re.M) 3131 text= open(path).read() 3132 text = decay_pattern.sub('', text) 3133 text = text.replace('launch', "\ndecay %s\nlaunch\n" % line,1) 3134 open(path,'w').write(text)
3135 3136 3137
3138 - def do_compute_widths(self, line):
3139 signal.alarm(0) # avoid timer if any 3140 path = pjoin(self.me_dir,'Cards','param_card.dat') 3141 pattern = re.compile(r'''decay\s+(\+?\-?\d+)\s+auto(@NLO|)''',re.I) 3142 text = open(path).read() 3143 pdg_info = pattern.findall(text) 3144 has_nlo = any("@nlo"==nlo.lower() for _, nlo in pdg_info) 3145 pdg = [p for p,_ in pdg_info] 3146 3147 3148 line = '%s %s' % (line, ' '.join(pdg)) 3149 if not '--path' in line: 3150 line += ' --path=%s' % path 3151 if has_nlo: 3152 line += ' --nlo' 3153 3154 try: 3155 return self.mother_interface.do_compute_widths(line) 3156 except InvalidCmd, error: 3157 logger.error("Invalid command: %s " % error)
3158
3159 - def help_compute_widths(self):
3160 signal.alarm(0) # avoid timer if any 3161 return self.mother_interface.help_compute_widths()
3162
3163 - def help_decay(self):
3164 """help for command decay which modifies MadSpin_card""" 3165 3166 signal.alarm(0) # avoid timer if any 3167 print '--syntax: decay PROC [--add]' 3168 print ' ' 3169 print ' modify the madspin_card to modify the decay of the associate particle.' 3170 print ' and define it to PROC.' 3171 print ' if --add is present, just add a new decay for the associate particle.'
3172
3173 - def complete_compute_widths(self, *args, **opts):
3174 signal.alarm(0) # avoid timer if any 3175 return self.mother_interface.complete_compute_widths(*args,**opts)
3176 3177 3178
3179 - def help_asperge(self):
3180 """Help associated to the asperge command""" 3181 signal.alarm(0) 3182 3183 print '-- syntax: asperge [options]' 3184 print ' Call ASperGe to diagonalize all mass matrices in the model.' 3185 print ' This works only if the ASperGE module is part of the UFO model (a subdirectory).' 3186 print ' If you specify some names after the command (i.e. asperge m1 m2) then ASperGe will only' 3187 print ' diagonalize the associate mass matrices (here m1 and m2).'
3188
3189 - def complete_asperge(self, text, line, begidx, endidx):
3190 signal.alarm(0) # avoid timer if any 3191 3192 blockname = self.pname2block.keys() 3193 # remove those that we know for sure are not mixing 3194 wrong = ['decay', 'mass', 'sminput'] 3195 valid = [k for k in blockname if 'mix' in k] 3196 potential = [k for k in blockname if k not in valid+wrong] 3197 output = {'Mixing matrices': self.list_completion(text, valid, line), 3198 'Other potential valid input': self.list_completion(text, potential, line)} 3199 3200 return self.deal_multiple_categories(output)
3201 3202
3203 - def do_asperge(self, line):
3204 """Running ASperGe""" 3205 signal.alarm(0) # avoid timer if any 3206 3207 path = pjoin(self.me_dir,'bin','internal','ufomodel','ASperGE') 3208 if not os.path.exists(path): 3209 logger.error('ASperge has not been detected in the current model, therefore it will not be run.') 3210 return 3211 elif not os.path.exists(pjoin(path,'ASperGe')): 3212 logger.info('ASperGe has been detected but is not compiled. Running the compilation now.') 3213 try: 3214 misc.compile(cwd=path,shell=True) 3215 except MadGraph5Error, error: 3216 logger.error('''ASperGe failed to compile. Note that gsl is needed 3217 for this compilation to go trough. More information on how to install this package on 3218 http://www.gnu.org/software/gsl/ 3219 Full compilation log is available at %s''' % pjoin(self.me_dir, 'ASperge_compilation.log')) 3220 open(pjoin(self.me_dir, 'ASperge_compilation.log'),'w').write(str(error)) 3221 return 3222 3223 opts = line.split() 3224 card = pjoin(self.me_dir,'Cards', 'param_card.dat') 3225 logger.info('running ASperGE') 3226 returncode = misc.call([pjoin(path,'ASperGe'), card, '%s.new' % card] + opts) 3227 if returncode: 3228 logger.error('ASperGE fails with status %s' % returncode) 3229 else: 3230 logger.info('AsPerGe creates the file succesfully') 3231 files.mv(card, '%s.beforeasperge' % card) 3232 files.mv('%s.new' % card, card)
3233 3234 3235
3236 - def copy_file(self, path):
3237 """detect the type of the file and overwritte the current file""" 3238 3239 if path.endswith('.lhco'): 3240 #logger.info('copy %s as Events/input.lhco' % (path)) 3241 #files.cp(path, pjoin(self.mother_interface.me_dir, 'Events', 'input.lhco' )) 3242 self.do_set('mw_run inputfile %s' % os.path.relpath(path, self.mother_interface.me_dir)) 3243 return 3244 elif path.endswith('.lhco.gz'): 3245 #logger.info('copy %s as Events/input.lhco.gz' % (path)) 3246 #files.cp(path, pjoin(self.mother_interface.me_dir, 'Events', 'input.lhco.gz' )) 3247 self.do_set('mw_run inputfile %s' % os.path.relpath(path, self.mother_interface.me_dir)) 3248 return 3249 else: 3250 card_name = CommonRunCmd.detect_card_type(path) 3251 3252 if card_name == 'unknown': 3253 logger.warning('Fail to determine the type of the file. Not copied') 3254 if card_name != 'banner': 3255 logger.info('copy %s as %s' % (path, card_name)) 3256 files.cp(path, pjoin(self.me_dir, 'Cards', card_name)) 3257 elif card_name == 'banner': 3258 banner_mod.split_banner(path, self.mother_interface.me_dir, proc_card=False) 3259 logger.info('Splitting the banner in it\'s component') 3260 if not self.mode == 'auto': 3261 self.mother_interface.keep_cards(self.cards)
3262
3263 - def open_file(self, answer):
3264 """open the file""" 3265 me_dir = self.mother_interface.me_dir 3266 if answer.isdigit(): 3267 if answer == '9': 3268 answer = 'plot' 3269 else: 3270 answer = self.cards[int(answer)-1] 3271 if 'madweight' in answer: 3272 answer = answer.replace('madweight', 'MadWeight') 3273 3274 if 'MadLoopParams' in answer: 3275 answer = pjoin(me_dir,'Cards','MadLoopParams.dat') 3276 if not '.dat' in answer and not '.lhco' in answer: 3277 if answer != 'trigger': 3278 path = pjoin(me_dir,'Cards','%s_card.dat' % answer) 3279 else: 3280 path = pjoin(me_dir,'Cards','delphes_trigger.dat') 3281 elif not '.lhco' in answer: 3282 path = pjoin(me_dir, 'Cards', answer) 3283 else: 3284 path = pjoin(me_dir, self.mw_card['mw_run']['inputfile']) 3285 if not os.path.exists(path): 3286 logger.info('Path in MW_card not existing') 3287 path = pjoin(me_dir, 'Events', answer) 3288 #security 3289 path = path.replace('_card_card','_card') 3290 try: 3291 self.mother_interface.exec_cmd('open %s' % path) 3292 except InvalidCmd, error: 3293 if str(error) != 'No default path for this file': 3294 raise 3295 if answer == 'transfer_card.dat': 3296 logger.warning('You have to specify a transfer function first!') 3297 elif answer == 'input.lhco': 3298 path = pjoin(me_dir,'Events', 'input.lhco') 3299 ff = open(path,'w') 3300 ff.write('''No LHCO information imported at current time. 3301 To import a lhco file: Close this file and type the path of your file. 3302 You can also copy/paste, your event file here.''') 3303 ff.close() 3304 self.open_file(path) 3305 else: 3306 raise 3307 3308 # reload object to have it in sync 3309 if path == pjoin(self.me_dir,'Cards','param_card.dat'): 3310 try: 3311 self.param_card = check_param_card.ParamCard(path) 3312 except (check_param_card.InvalidParamCard, ValueError) as e: 3313 logger.error('Current param_card is not valid. We are going to use the default one.') 3314 logger.error('problem detected: %s' % e) 3315 logger.error('Please re-open the file and fix the problem.') 3316 logger.warning('using the \'set\' command without opening the file will discard all your manual change') 3317 elif path == pjoin(self.me_dir,'Cards','run_card.dat'): 3318 self.run_card = banner_mod.RunCard(pjoin(self.me_dir,'Cards','run_card.dat')) 3319 elif path == pjoin(self.me_dir,'Cards','MadLoopParams.dat'): 3320 self.MLcard = banner_mod.MadLoopParam(pjoin(self.me_dir,'Cards','MadLoopParams.dat')) 3321 elif path == pjoin(self.me_dir,'Cards','MadWeight_card.dat'): 3322 try: 3323 import madgraph.madweight.Cards as mwcards 3324 except: 3325 import internal.madweight.Cards as mwcards 3326 self.mw_card = mwcards.Card(pjoin(self.me_dir,'Cards','MadWeight_card.dat'))
3327