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