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 ast 
  21  import atexit 
  22  import cmath 
  23  import cmd 
  24  import glob 
  25  import logging 
  26  import math 
  27  import optparse 
  28  import os 
  29  import pydoc 
  30  import random 
  31  import re 
  32  import shutil 
  33  import signal 
  34  import stat 
  35  import subprocess 
  36  import sys 
  37  import time 
  38  import traceback 
  39  import glob 
  40  import StringIO 
  41   
  42  try: 
  43      import readline 
  44      GNU_SPLITTING = ('GNU' in readline.__doc__) 
  45  except: 
  46      GNU_SPLITTING = True 
  47   
  48  root_path = os.path.split(os.path.dirname(os.path.realpath( __file__ )))[0] 
  49  root_path = os.path.split(root_path)[0] 
  50  sys.path.insert(0, os.path.join(root_path,'bin')) 
  51   
  52  # usefull shortcut 
  53  pjoin = os.path.join 
  54  # Special logger for the Cmd Interface 
  55  logger = logging.getLogger('madgraph.stdout') # -> stdout 
  56  logger_stderr = logging.getLogger('madgraph.stderr') # ->stderr 
  57   
  58  try: 
  59      import madgraph 
  60  except ImportError:     
  61      # import from madevent directory 
  62      import internal.extended_cmd as cmd 
  63      import internal.banner as banner_mod 
  64      import internal.shower_card as shower_card_mod 
  65      import internal.misc as misc 
  66      import internal.cluster as cluster 
  67      import internal.check_param_card as check_param_card 
  68      import internal.files as files 
  69      import internal.histograms as histograms 
  70      import internal.save_load_object as save_load_object 
  71      import internal.gen_crossxhtml as gen_crossxhtml 
  72      import internal.lhe_parser as lhe_parser 
  73      from internal import InvalidCmd, MadGraph5Error 
  74      MADEVENT=True     
  75  else: 
  76      # import from madgraph directory 
  77      import madgraph.interface.extended_cmd as cmd 
  78      import madgraph.various.banner as banner_mod 
  79      import madgraph.various.shower_card as shower_card_mod 
  80      import madgraph.various.misc as misc 
  81      import madgraph.iolibs.files as files 
  82      import madgraph.various.cluster as cluster 
  83      import madgraph.various.lhe_parser as lhe_parser 
  84      import madgraph.iolibs.save_load_object as save_load_object 
  85      import madgraph.madevent.gen_crossxhtml as gen_crossxhtml 
  86      import models.check_param_card as check_param_card 
  87      import madgraph.various.histograms as histograms 
  88       
  89      from madgraph import InvalidCmd, MadGraph5Error, MG5DIR 
  90      MADEVENT=False 
91 92 #=============================================================================== 93 # HelpToCmd 94 #=============================================================================== 95 -class HelpToCmd(object):
96 """ The Series of help routins in common between amcatnlo_run and 97 madevent interface""" 98
99 - def help_treatcards(self):
100 logger.info("syntax: treatcards [param|run] [--output_dir=] [--param_card=] [--run_card=]") 101 logger.info("-- create the .inc files containing the cards information." )
102
103 - def help_set(self):
104 logger.info("syntax: set %s argument" % "|".join(self._set_options)) 105 logger.info("-- set options") 106 logger.info(" stdout_level DEBUG|INFO|WARNING|ERROR|CRITICAL") 107 logger.info(" change the default level for printed information") 108 logger.info(" timeout VALUE") 109 logger.info(" (default 20) Seconds allowed to answer questions.") 110 logger.info(" Note that pressing tab always stops the timer.") 111 logger.info(" cluster_temp_path PATH") 112 logger.info(" (default None) Allow to perform the run in PATH directory") 113 logger.info(" This allow to not run on the central disk. This is not used") 114 logger.info(" by condor cluster (since condor has it's own way to prevent it).")
115
116 - def help_plot(self):
117 logger.info("syntax: help [RUN] [%s] [-f]" % '|'.join(self._plot_mode)) 118 logger.info("-- create the plot for the RUN (current run by default)") 119 logger.info(" at the different stage of the event generation") 120 logger.info(" Note than more than one mode can be specified in the same command.") 121 logger.info(" This require to have MadAnalysis and td require. By default") 122 logger.info(" if those programs are installed correctly, the creation") 123 logger.info(" will be performed automaticaly during the event generation.") 124 logger.info(" -f options: answer all question by default.")
125
126 - def help_compute_widths(self):
127 logger.info("syntax: compute_widths Particle [Particles] [OPTIONS]") 128 logger.info("-- Compute the widths for the particles specified.") 129 logger.info(" By default, this takes the current param_card and overwrites it.") 130 logger.info(" Precision allows to define when to include three/four/... body decays (LO).") 131 logger.info(" If this number is an integer then all N-body decay will be included.") 132 logger.info(" Various options:\n") 133 logger.info(" --body_decay=X: Parameter to control the precision of the computation") 134 logger.info(" if X is an integer, we compute all channels up to X-body decay.") 135 logger.info(" if X <1, then we stop when the estimated error is lower than X.") 136 logger.info(" if X >1 BUT not an integer, then we X = N + M, with M <1 and N an integer") 137 logger.info(" We then either stop at the N-body decay or when the estimated error is lower than M.") 138 logger.info(" default: 4.0025") 139 logger.info(" --min_br=X: All channel which are estimated below this value will not be integrated numerically.") 140 logger.info(" default: precision (decimal part of the body_decay options) divided by four") 141 logger.info(" --precision_channel=X: requested numerical precision for each channel") 142 logger.info(" default: 0.01") 143 logger.info(" --path=X: path for param_card") 144 logger.info(" default: take value from the model") 145 logger.info(" --output=X: path where to write the resulting card. ") 146 logger.info(" default: overwrite input file. If no input file, write it in the model directory") 147 logger.info(" --nlo: Compute NLO width [if the model support it]")
148
149 - def help_shower(self):
150 logger.info("syntax: shower [shower_name] [shower_options]") 151 logger.info("-- This is equivalent to running '[shower_name] [shower_options]'")
152
153 - def help_pgs(self):
154 logger.info("syntax: pgs [RUN] [--run_options]") 155 logger.info("-- run pgs on RUN (current one by default)") 156 self.run_options_help([('-f','answer all question by default'), 157 ('--tag=', 'define the tag for the pgs run'), 158 ('--no_default', 'not run if pgs_card not present')])
159
160 - def help_delphes(self):
161 logger.info("syntax: delphes [RUN] [--run_options]") 162 logger.info("-- run delphes on RUN (current one by default)") 163 self.run_options_help([('-f','answer all question by default'), 164 ('--tag=', 'define the tag for the delphes run'), 165 ('--no_default', 'not run if delphes_card not present')])
166
167 - def help_decay_events(self, skip_syntax=False):
168 if not skip_syntax: 169 logger.info("syntax: decay_events [RUN]") 170 logger.info("This functionality allows for the decay of resonances") 171 logger.info("in a .lhe file, keeping track of the spin correlation effets.") 172 logger.info("BE AWARE OF THE CURRENT LIMITATIONS:") 173 logger.info(" (1) Only a succession of 2 body decay are currently allowed")
174
175 176 177 -class CheckValidForCmd(object):
178 """ The Series of check routines in common between amcatnlo_run and 179 madevent interface""" 180
181 - def check_set(self, args):
182 """ check the validity of the line""" 183 184 185 if len(args) < 2: 186 if len(args)==1 and "=" in args[0]: 187 args[:] = args[0].split("=",1) 188 else: 189 self.help_set() 190 raise self.InvalidCmd('set needs an option and an argument') 191 192 if args[0] not in self._set_options + self.options.keys(): 193 self.help_set() 194 raise self.InvalidCmd('Possible options for set are %s' % \ 195 (self._set_options+self.options.keys())) 196 197 if args[0] in ['stdout_level']: 198 if args[1] not in ['DEBUG','INFO','WARNING','ERROR','CRITICAL'] \ 199 and not args[1].isdigit(): 200 raise self.InvalidCmd('output_level needs ' + \ 201 'a valid level') 202 203 if args[0] in ['timeout']: 204 if not args[1].isdigit(): 205 raise self.InvalidCmd('timeout values should be a integer')
206
207 - def check_compute_widths(self, args):
208 """check that the model is loadable and check that the format is of the 209 type: PART PATH --output=PATH -f --precision=N 210 return the model. 211 """ 212 213 # Check that MG5 directory is present . 214 if MADEVENT and not self.options['mg5_path']: 215 raise self.InvalidCmd, '''The automatic computations of widths requires that MG5 is installed on the system. 216 You can install it and set his path in ./Cards/me5_configuration.txt''' 217 elif MADEVENT: 218 sys.path.append(self.options['mg5_path']) 219 try: 220 import models.model_reader as model_reader 221 import models.import_ufo as import_ufo 222 except ImportError: 223 raise self.ConfigurationError, '''Can\'t load MG5. 224 The variable mg5_path should not be correctly configure.''' 225 226 227 ufo_path = pjoin(self.me_dir,'bin','internal', 'ufomodel') 228 # Import model 229 if not MADEVENT: 230 modelname = self.find_model_name() 231 #restrict_file = None 232 #if os.path.exists(pjoin(ufo_path, 'restrict_default.dat')): 233 # restrict_file = pjoin(ufo_path, 'restrict_default.dat') 234 235 force_CMS = self.mother and self.mother.options['complex_mass_scheme'] 236 model = import_ufo.import_model(modelname, decay=True, 237 restrict=True, complex_mass_scheme=force_CMS) 238 else: 239 #pattern for checking complex mass scheme. 240 has_cms = re.compile(r'''set\s+complex_mass_scheme\s*(True|T|1|true|$|;)''') 241 force_CMS = has_cms.search(open(pjoin(self.me_dir,'Cards', 242 'proc_card_mg5.dat')).read()) 243 model = import_ufo.import_model(pjoin(self.me_dir,'bin','internal', 244 'ufomodel'), decay=True, complex_mass_scheme=force_CMS) 245 246 # if not hasattr(model.get('particles')[0], 'partial_widths'): 247 # raise self.InvalidCmd, 'The UFO model does not include partial widths information. Impossible to compute widths automatically' 248 249 # check if the name are passed to default MG5 250 if '-modelname' not in open(pjoin(self.me_dir,'Cards','proc_card_mg5.dat')).read(): 251 model.pass_particles_name_in_mg_default() 252 model = model_reader.ModelReader(model) 253 particles_name = dict([(p.get('name'), p.get('pdg_code')) 254 for p in model.get('particles')]) 255 particles_name.update(dict([(p.get('antiname'), p.get('pdg_code')) 256 for p in model.get('particles')])) 257 258 output = {'model': model, 'force': False, 'output': None, 259 'path':None, 'particles': set(), 'body_decay':4.0025, 260 'min_br':None, 'precision_channel':0.01} 261 for arg in args: 262 if arg.startswith('--output='): 263 output_path = arg.split('=',1)[1] 264 if not os.path.exists(output_path): 265 raise self.InvalidCmd, 'Invalid Path for the output. Please retry.' 266 if not os.path.isfile(output_path): 267 output_path = pjoin(output_path, 'param_card.dat') 268 output['output'] = output_path 269 elif arg == '-f': 270 output['force'] = True 271 elif os.path.isfile(arg): 272 ftype = self.detect_card_type(arg) 273 if ftype != 'param_card.dat': 274 raise self.InvalidCmd , '%s is not a valid param_card.' % arg 275 output['path'] = arg 276 elif arg.startswith('--path='): 277 arg = arg.split('=',1)[1] 278 ftype = self.detect_card_type(arg) 279 if ftype != 'param_card.dat': 280 raise self.InvalidCmd , '%s is not a valid param_card.' % arg 281 output['path'] = arg 282 elif arg.startswith('--'): 283 if "=" in arg: 284 name, value = arg.split('=',1) 285 try: 286 value = float(value) 287 except Exception: 288 raise self.InvalidCmd, '--%s requires integer or a float' % name 289 output[name[2:]] = float(value) 290 elif arg == "--nlo": 291 output["nlo"] = True 292 elif arg in particles_name: 293 # should be a particles 294 output['particles'].add(particles_name[arg]) 295 elif arg.isdigit() and int(arg) in particles_name.values(): 296 output['particles'].add(ast.literal_eval(arg)) 297 elif arg == 'all': 298 output['particles'] = set(['all']) 299 else: 300 self.help_compute_widths() 301 raise self.InvalidCmd, '%s is not a valid argument for compute_widths' % arg 302 if self.force: 303 output['force'] = True 304 305 if not output['particles']: 306 raise self.InvalidCmd, '''This routines requires at least one particle in order to compute 307 the related width''' 308 309 if output['output'] is None: 310 output['output'] = output['path'] 311 312 return output
313
314 - def check_delphes(self, arg, nodefault=False):
315 """Check the argument for pythia command 316 syntax: delphes [NAME] 317 Note that other option are already remove at this point 318 """ 319 320 # If not pythia-pgs path 321 if not self.options['delphes_path']: 322 logger.info('Retry to read configuration file to find delphes path') 323 self.set_configuration() 324 325 if not self.options['delphes_path']: 326 error_msg = 'No valid Delphes path set.\n' 327 error_msg += 'Please use the set command to define the path and retry.\n' 328 error_msg += 'You can also define it in the configuration file.\n' 329 raise self.InvalidCmd(error_msg) 330 331 tag = [a for a in arg if a.startswith('--tag=')] 332 if tag: 333 arg.remove(tag[0]) 334 tag = tag[0][6:] 335 336 337 if len(arg) == 0 and not self.run_name: 338 if self.results.lastrun: 339 arg.insert(0, self.results.lastrun) 340 else: 341 raise self.InvalidCmd('No run name currently define. Please add this information.') 342 343 if len(arg) == 1 and self.run_name == arg[0]: 344 arg.pop(0) 345 346 filepath = None 347 if not len(arg): 348 prev_tag = self.set_run_name(self.run_name, tag, 'delphes') 349 paths = [pjoin(self.me_dir,'Events',self.run_name, '%(tag)s_pythia_events.hep.gz'), 350 pjoin(self.me_dir,'Events',self.run_name, '%(tag)s_pythia8_events.hepmc.gz'), 351 pjoin(self.me_dir,'Events',self.run_name, '%(tag)s_pythia_events.hep'), 352 pjoin(self.me_dir,'Events',self.run_name, '%(tag)s_pythia8_events.hepmc'), 353 pjoin(self.me_dir,'Events','pythia_events.hep'), 354 pjoin(self.me_dir,'Events','pythia_events.hepmc'), 355 pjoin(self.me_dir,'Events','pythia8_events.hep.gz'), 356 pjoin(self.me_dir,'Events','pythia8_events.hepmc.gz') 357 ] 358 for p in paths: 359 if os.path.exists(p % {'tag': prev_tag}): 360 filepath = p % {'tag': prev_tag} 361 break 362 else: 363 a = raw_input("NO INPUT") 364 if nodefault: 365 return False 366 else: 367 self.help_pgs() 368 raise self.InvalidCmd('''No file file pythia_events.* currently available 369 Please specify a valid run_name''') 370 371 if len(arg) == 1: 372 prev_tag = self.set_run_name(arg[0], tag, 'delphes') 373 if os.path.exists(pjoin(self.me_dir,'Events',self.run_name, '%s_pythia_events.hep.gz' % prev_tag)): 374 filepath = pjoin(self.me_dir,'Events',self.run_name, '%s_pythia_events.hep.gz' % prev_tag) 375 elif os.path.exists(pjoin(self.me_dir,'Events',self.run_name, '%s_pythia8_events.hepmc.gz' % prev_tag)): 376 filepath = pjoin(self.me_dir,'Events',self.run_name, '%s_pythia8_events.hepmc.gz' % prev_tag) 377 elif os.path.exists(pjoin(self.me_dir,'Events',self.run_name, '%s_pythia_events.hep' % prev_tag)): 378 filepath = pjoin(self.me_dir,'Events',self.run_name, '%s_pythia_events.hep.gz' % prev_tag) 379 elif os.path.exists(pjoin(self.me_dir,'Events',self.run_name, '%s_pythia8_events.hepmc' % prev_tag)): 380 filepath = pjoin(self.me_dir,'Events',self.run_name, '%s_pythia8_events.hepmc.gz' % prev_tag) 381 else: 382 raise self.InvalidCmd('No events file corresponding to %s run with tag %s.:%s '\ 383 % (self.run_name, prev_tag, 384 pjoin(self.me_dir,'Events',self.run_name, '%s_pythia_events.hep.gz' % prev_tag))) 385 else: 386 if tag: 387 self.run_card['run_tag'] = tag 388 self.set_run_name(self.run_name, tag, 'delphes') 389 390 return filepath
391 392 393 394 395 396 397
398 - def check_open(self, args):
399 """ check the validity of the line """ 400 401 if len(args) != 1: 402 self.help_open() 403 raise self.InvalidCmd('OPEN command requires exactly one argument') 404 405 if args[0].startswith('./'): 406 if not os.path.isfile(args[0]): 407 raise self.InvalidCmd('%s: not such file' % args[0]) 408 return True 409 410 # if special : create the path. 411 if not self.me_dir: 412 if not os.path.isfile(args[0]): 413 self.help_open() 414 raise self.InvalidCmd('No MadEvent path defined. Unable to associate this name to a file') 415 else: 416 return True 417 418 path = self.me_dir 419 if os.path.isfile(os.path.join(path,args[0])): 420 args[0] = os.path.join(path,args[0]) 421 elif os.path.isfile(os.path.join(path,'Cards',args[0])): 422 args[0] = os.path.join(path,'Cards',args[0]) 423 elif os.path.isfile(os.path.join(path,'HTML',args[0])): 424 args[0] = os.path.join(path,'HTML',args[0]) 425 # special for card with _default define: copy the default and open it 426 elif '_card.dat' in args[0]: 427 name = args[0].replace('_card.dat','_card_default.dat') 428 if os.path.isfile(os.path.join(path,'Cards', name)): 429 files.cp(os.path.join(path,'Cards', name), os.path.join(path,'Cards', args[0])) 430 args[0] = os.path.join(path,'Cards', args[0]) 431 else: 432 raise self.InvalidCmd('No default path for this file') 433 elif not os.path.isfile(args[0]): 434 raise self.InvalidCmd('No default path for this file')
435
436 - def check_treatcards(self, args):
437 """check that treatcards arguments are valid 438 [param|run|all] [--output_dir=] [--param_card=] [--run_card=] 439 """ 440 441 opt = {'output_dir':pjoin(self.me_dir,'Source'), 442 'param_card':pjoin(self.me_dir,'Cards','param_card.dat'), 443 'run_card':pjoin(self.me_dir,'Cards','run_card.dat')} 444 mode = 'all' 445 for arg in args: 446 if arg.startswith('--') and '=' in arg: 447 key,value =arg[2:].split('=',1) 448 if not key in opt: 449 self.help_treatcards() 450 raise self.InvalidCmd('Invalid option for treatcards command:%s ' \ 451 % key) 452 if key in ['param_card', 'run_card']: 453 if os.path.isfile(value): 454 card_name = self.detect_card_type(value) 455 if card_name != key: 456 raise self.InvalidCmd('Format for input file detected as %s while expecting %s' 457 % (card_name, key)) 458 opt[key] = value 459 elif os.path.isfile(pjoin(self.me_dir,value)): 460 card_name = self.detect_card_type(pjoin(self.me_dir,value)) 461 if card_name != key: 462 raise self.InvalidCmd('Format for input file detected as %s while expecting %s' 463 % (card_name, key)) 464 opt[key] = value 465 else: 466 raise self.InvalidCmd('No such file: %s ' % value) 467 elif key in ['output_dir']: 468 if os.path.isdir(value): 469 opt[key] = value 470 elif os.path.isdir(pjoin(self.me_dir,value)): 471 opt[key] = pjoin(self.me_dir, value) 472 else: 473 raise self.InvalidCmd('No such directory: %s' % value) 474 elif arg in ['MadLoop','param','run','all']: 475 mode = arg 476 else: 477 self.help_treatcards() 478 raise self.InvalidCmd('Unvalid argument %s' % arg) 479 480 return mode, opt
481
482 - def check_decay_events(self,args):
483 """Check the argument for decay_events command 484 syntax is "decay_events [NAME]" 485 Note that other option are already remove at this point 486 """ 487 488 opts = [] 489 if '-from_cards' in args: 490 args.remove('-from_cards') 491 opts.append('-from_cards') 492 493 if len(args) == 0: 494 if self.run_name: 495 args.insert(0, self.run_name) 496 elif self.results.lastrun: 497 args.insert(0, self.results.lastrun) 498 else: 499 raise self.InvalidCmd('No run name currently defined. Please add this information.') 500 return 501 502 if args[0] != self.run_name: 503 self.set_run_name(args[0]) 504 505 args[0] = self.get_events_path(args[0]) 506 507 args += opts
508
509 - def check_check_events(self,args):
510 """Check the argument for decay_events command 511 syntax is "decay_events [NAME]" 512 Note that other option are already remove at this point 513 """ 514 515 if len(args) == 0: 516 if self.run_name: 517 args.insert(0, self.run_name) 518 elif self.results.lastrun: 519 args.insert(0, self.results.lastrun) 520 else: 521 raise self.InvalidCmd('No run name currently defined. Please add this information.') 522 return 523 524 if args[0] and os.path.isfile(args[0]): 525 pass 526 else: 527 if args[0] != self.run_name: 528 self.set_run_name(args[0], allow_new_tag=False) 529 530 args[0] = self.get_events_path(args[0])
531 532
533 - def get_events_path(self, run_name):
534 """return the path to the output events 535 """ 536 537 if self.mode == 'madevent': 538 possible_path = [ 539 pjoin(self.me_dir,'Events', run_name, 'unweighted_events.lhe.gz'), 540 pjoin(self.me_dir,'Events', run_name, 'unweighted_events.lhe')] 541 else: 542 possible_path = [ 543 pjoin(self.me_dir,'Events', run_name, 'events.lhe.gz'), 544 pjoin(self.me_dir,'Events', run_name, 'events.lhe')] 545 546 for path in possible_path: 547 if os.path.exists(path): 548 correct_path = path 549 break 550 else: 551 if os.path.exists(run_name): 552 correct_path = run_name 553 else: 554 raise self.InvalidCmd('No events file corresponding to %s run. ' % run_name) 555 return correct_path
556
557 558 559 -class MadEventAlreadyRunning(InvalidCmd):
560 pass
561 -class AlreadyRunning(MadEventAlreadyRunning):
562 pass
563
564 #=============================================================================== 565 # CommonRunCmd 566 #=============================================================================== 567 -class CommonRunCmd(HelpToCmd, CheckValidForCmd, cmd.Cmd):
568 569 debug_output = 'ME5_debug' 570 helporder = ['Main Commands', 'Documented commands', 'Require MG5 directory', 571 'Advanced commands'] 572 573 # The three options categories are treated on a different footage when a 574 # set/save configuration occur. current value are kept in self.options 575 options_configuration = {'pythia8_path': './pythia8', 576 'hwpp_path': './herwigPP', 577 'thepeg_path': './thepeg', 578 'hepmc_path': './hepmc', 579 'madanalysis_path': './MadAnalysis', 580 'madanalysis5_path': './HEPTools/madanalysis5', 581 'pythia-pgs_path':'./pythia-pgs', 582 'td_path':'./td', 583 'delphes_path':'./Delphes', 584 'exrootanalysis_path':'./ExRootAnalysis', 585 'syscalc_path': './SysCalc', 586 'lhapdf': 'lhapdf-config', 587 'timeout': 60, 588 'f2py_compiler':None, 589 'web_browser':None, 590 'eps_viewer':None, 591 'text_editor':None, 592 'fortran_compiler':None, 593 'cpp_compiler': None, 594 'auto_update':7, 595 'cluster_type': 'condor', 596 'cluster_status_update': (600, 30), 597 'cluster_nb_retry':1, 598 'cluster_local_path': None, 599 'cluster_retry_wait':300} 600 601 options_madgraph= {'stdout_level':None} 602 603 options_madevent = {'automatic_html_opening':True, 604 'notification_center':True, 605 'run_mode':2, 606 'cluster_queue':None, 607 'cluster_time':None, 608 'cluster_size':100, 609 'cluster_memory':None, 610 'nb_core': None, 611 'cluster_temp_path':None} 612 613
614 - def __init__(self, me_dir, options, *args, **opts):
615 """common""" 616 617 self.force_run = False # this flag force the run even if RunWeb is present 618 if 'force_run' in opts and opts['force_run']: 619 self.force_run = True 620 del opts['force_run'] 621 622 cmd.Cmd.__init__(self, *args, **opts) 623 # Define current MadEvent directory 624 if me_dir is None and MADEVENT: 625 me_dir = root_path 626 627 if os.path.isabs(me_dir): 628 self.me_dir = me_dir 629 else: 630 self.me_dir = pjoin(os.getcwd(),me_dir) 631 632 self.options = options 633 634 self.param_card_iterator = [] #an placeholder containing a generator of paramcard for scanning 635 636 # usefull shortcut 637 self.status = pjoin(self.me_dir, 'status') 638 self.error = pjoin(self.me_dir, 'error') 639 self.dirbin = pjoin(self.me_dir, 'bin', 'internal') 640 641 # Check that the directory is not currently running_in_idle 642 if not self.force_run: 643 if os.path.exists(pjoin(me_dir,'RunWeb')): 644 message = '''Another instance of the program is currently running. 645 (for this exact same directory) Please wait that this is instance is 646 closed. If no instance is running, you can delete the file 647 %s and try again.''' % pjoin(me_dir,'RunWeb') 648 raise AlreadyRunning, message 649 else: 650 pid = os.getpid() 651 fsock = open(pjoin(me_dir,'RunWeb'),'w') 652 fsock.write(`pid`) 653 fsock.close() 654 655 misc.Popen([os.path.relpath(pjoin(self.dirbin, 'gen_cardhtml-pl'), me_dir)], 656 cwd=me_dir) 657 658 self.to_store = [] 659 self.run_name = None 660 self.run_tag = None 661 self.banner = None 662 # Load the configuration file 663 self.set_configuration() 664 self.configure_run_mode(self.options['run_mode']) 665 666 # Define self.proc_characteristics 667 self.get_characteristics() 668 669 if not self.proc_characteristics['ninitial']: 670 # Get number of initial states 671 nexternal = open(pjoin(self.me_dir,'Source','nexternal.inc')).read() 672 found = re.search("PARAMETER\s*\(NINCOMING=(\d)\)", nexternal) 673 self.ninitial = int(found.group(1)) 674 else: 675 self.ninitial = self.proc_characteristics['ninitial']
676 677 678 ############################################################################
679 - def split_arg(self, line, error=False):
680 """split argument and remove run_options""" 681 682 args = cmd.Cmd.split_arg(line) 683 for arg in args[:]: 684 if not arg.startswith('-'): 685 continue 686 elif arg == '-c': 687 self.configure_run_mode(1) 688 elif arg == '-m': 689 self.configure_run_mode(2) 690 elif arg == '-f': 691 self.force = True 692 elif not arg.startswith('--'): 693 if error: 694 raise self.InvalidCmd('%s argument cannot start with - symbol' % arg) 695 else: 696 continue 697 elif arg.startswith('--cluster'): 698 self.configure_run_mode(1) 699 elif arg.startswith('--multicore'): 700 self.configure_run_mode(2) 701 elif arg.startswith('--nb_core'): 702 self.options['nb_core'] = int(arg.split('=',1)[1]) 703 self.configure_run_mode(2) 704 elif arg.startswith('--web'): 705 self.pass_in_web_mode() 706 self.configure_run_mode(1) 707 else: 708 continue 709 args.remove(arg) 710 711 return args
712 713 714 @misc.multiple_try(nb_try=5, sleep=2)
715 - def load_results_db(self):
716 """load the current results status""" 717 718 # load the current status of the directory 719 if os.path.exists(pjoin(self.me_dir,'HTML','results.pkl')): 720 try: 721 self.results = save_load_object.load_from_file(pjoin(self.me_dir,'HTML','results.pkl')) 722 except Exception: 723 #the pickle fail -> need to recreate the library 724 model = self.find_model_name() 725 process = self.process # define in find_model_name 726 self.results = gen_crossxhtml.AllResults(model, process, self.me_dir) 727 self.results.resetall(self.me_dir) 728 else: 729 try: 730 self.results.resetall(self.me_dir) 731 except Exception, error: 732 logger.debug(error) 733 # Maybe the format was updated -> try fresh 734 model = self.find_model_name() 735 process = self.process # define in find_model_name 736 self.results = gen_crossxhtml.AllResults(model, process, self.me_dir) 737 self.results.resetall(self.me_dir) 738 self.last_mode = '' 739 try: 740 self.last_mode = self.results[self.results.lastrun][-1]['run_mode'] 741 except: 742 self.results.resetall(self.me_dir) 743 self.last_mode = '' 744 745 else: 746 model = self.find_model_name() 747 process = self.process # define in find_model_name 748 self.results = gen_crossxhtml.AllResults(model, process, self.me_dir) 749 self.results.resetall(self.me_dir) 750 self.last_mode='' 751 752 return self.results
753 754 ############################################################################
755 - def do_treatcards(self, line, amcatnlo=False):
756 """Advanced commands: create .inc files from param_card.dat/run_card.dat""" 757 758 keepwidth = False 759 if '--keepwidth' in line: 760 keepwidth = True 761 line = line.replace('--keepwidth', '') 762 args = self.split_arg(line) 763 mode, opt = self.check_treatcards(args) 764 765 if mode in ['run', 'all']: 766 if not hasattr(self, 'run_card'): 767 if amcatnlo: 768 run_card = banner_mod.RunCardNLO(opt['run_card']) 769 else: 770 run_card = banner_mod.RunCard(opt['run_card']) 771 else: 772 run_card = self.run_card 773 774 # add the conversion from the lhaid to the pdf set names 775 if amcatnlo and run_card['pdlabel']=='lhapdf': 776 pdfsetsdir=self.get_lhapdf_pdfsetsdir() 777 pdfsets=self.get_lhapdf_pdfsets_list(pdfsetsdir) 778 lhapdfsetname=[] 779 for lhaid in run_card['lhaid']: 780 if lhaid in pdfsets: 781 lhapdfsetname.append(pdfsets[lhaid]['filename']) 782 else: 783 raise MadGraph5Error("lhaid %s is not a valid PDF identification number. This can be due to the use of an outdated version of LHAPDF, or %s is not a LHAGlue number corresponding to a central PDF set (but rather one of the error sets)." % (lhaid,lhaid)) 784 run_card['lhapdfsetname']=lhapdfsetname 785 run_card.write_include_file(opt['output_dir']) 786 787 if mode in ['MadLoop', 'all']: 788 if os.path.exists(pjoin(self.me_dir, 'Cards', 'MadLoopParams.dat')): 789 self.MadLoopparam = banner_mod.MadLoopParam(pjoin(self.me_dir, 790 'Cards', 'MadLoopParams.dat')) 791 # write the output file 792 self.MadLoopparam.write(pjoin(self.me_dir,"SubProcesses", 793 "MadLoopParams.dat")) 794 795 if mode in ['param', 'all']: 796 if os.path.exists(pjoin(self.me_dir, 'Source', 'MODEL', 'mp_coupl.inc')): 797 param_card = check_param_card.ParamCardMP(opt['param_card']) 798 else: 799 param_card = check_param_card.ParamCard(opt['param_card']) 800 outfile = pjoin(opt['output_dir'], 'param_card.inc') 801 ident_card = pjoin(self.me_dir,'Cards','ident_card.dat') 802 if os.path.isfile(pjoin(self.me_dir,'bin','internal','ufomodel','restrict_default.dat')): 803 default = pjoin(self.me_dir,'bin','internal','ufomodel','restrict_default.dat') 804 elif os.path.isfile(pjoin(self.me_dir,'bin','internal','ufomodel','param_card.dat')): 805 default = pjoin(self.me_dir,'bin','internal','ufomodel','param_card.dat') 806 elif not os.path.exists(pjoin(self.me_dir,'bin','internal','ufomodel')): 807 fsock = open(pjoin(self.me_dir,'Source','param_card.inc'),'w') 808 fsock.write(' ') 809 fsock.close() 810 return 811 else: 812 subprocess.call(['python', 'write_param_card.py'], 813 cwd=pjoin(self.me_dir,'bin','internal','ufomodel')) 814 default = pjoin(self.me_dir,'bin','internal','ufomodel','param_card.dat') 815 816 817 if amcatnlo and not keepwidth: 818 # force particle in final states to have zero width 819 pids = self.get_pid_final_initial_states() 820 # check those which are charged under qcd 821 if not MADEVENT and pjoin(self.me_dir,'bin','internal') not in sys.path: 822 sys.path.insert(0,pjoin(self.me_dir,'bin','internal')) 823 824 #Ensure that the model that we are going to load is the current 825 #one. 826 to_del = [name for name in sys.modules.keys() 827 if name.startswith('internal.ufomodel') 828 or name.startswith('ufomodel')] 829 for name in to_del: 830 del(sys.modules[name]) 831 832 import ufomodel as ufomodel 833 zero = ufomodel.parameters.ZERO 834 no_width = [p for p in ufomodel.all_particles 835 if (str(p.pdg_code) in pids or str(-p.pdg_code) in pids) 836 and p.color != 1 and p.width != zero] 837 done = [] 838 for part in no_width: 839 if abs(part.pdg_code) in done: 840 continue 841 done.append(abs(part.pdg_code)) 842 param = param_card['decay'].get((part.pdg_code,)) 843 844 if param.value != 0: 845 logger.info('''For gauge cancellation, the width of \'%s\' has been set to zero.'''\ 846 % part.name,'$MG:color:BLACK') 847 param.value = 0 848 849 param_card.write_inc_file(outfile, ident_card, default)
850
851 - def get_model(self):
852 """return the model related to this process""" 853 854 if self.options['mg5_path']: 855 sys.path.append(self.options['mg5_path']) 856 import models.import_ufo as import_ufo 857 complexmass = self.proc_characteristics['complex_mass_scheme'] 858 with misc.MuteLogger(['madgraph.model'],[50]): 859 out= import_ufo.import_model(pjoin(self.me_dir,'bin','internal','ufomodel'), 860 complex_mass_scheme=complexmass) 861 return out 862 #elif self.mother: 863 # misc.sprint('Hum this is dangerous....') 864 # return self.mother._curr_model 865 else: 866 return None
867
868 - def ask_edit_cards(self, cards, mode='fixed', plot=True, first_cmd=None):
869 """ """ 870 if not self.options['madanalysis_path']: 871 plot = False 872 873 self.ask_edit_card_static(cards, mode, plot, self.options['timeout'], 874 self.ask, first_cmd=first_cmd)
875 876 @staticmethod
877 - def ask_edit_card_static(cards, mode='fixed', plot=True, 878 timeout=0, ask=None, **opt):
879 if not ask: 880 ask = CommonRunCmd.ask 881 882 def path2name(path): 883 if '_card' in path: 884 return path.split('_card')[0] 885 elif path == 'delphes_trigger.dat': 886 return 'trigger' 887 elif path == 'input.lhco': 888 return 'lhco' 889 elif path == 'MadLoopParams.dat': 890 return 'MadLoopParams' 891 else: 892 raise Exception, 'Unknow cards name %s' % path
893 894 # Ask the user if he wants to edit any of the files 895 #First create the asking text 896 question = """Do you want to edit a card (press enter to bypass editing)?\n""" 897 possible_answer = ['0', 'done'] 898 card = {0:'done'} 899 900 indent = max(len(path2name(card_name)) for card_name in cards) 901 question += '/'+'-'*60+'\\\n' 902 for i, card_name in enumerate(cards): 903 imode = path2name(card_name) 904 possible_answer.append(i+1) 905 possible_answer.append(imode) 906 question += '| %-77s|\n'%((' \x1b[31m%%s\x1b[0m. %%-%ds : \x1b[32m%%s\x1b[0m'%indent)%(i+1, imode, card_name)) 907 card[i+1] = imode 908 909 if plot and not 'plot_card.dat' in cards: 910 question += '| %-77s|\n'%((' \x1b[31m9\x1b[0m. %%-%ds : \x1b[32mplot_card.dat\x1b[0m'%indent) % 'plot') 911 possible_answer.append(9) 912 possible_answer.append('plot') 913 card[9] = 'plot' 914 915 question += '\\'+'-'*60+'/\n' 916 917 if 'param_card.dat' in cards: 918 # Add the path options 919 question += ' you can also\n' 920 question += ' - enter the path to a valid card or banner.\n' 921 question += ' - use the \'set\' command to modify a parameter directly.\n' 922 question += ' The set option works only for param_card and run_card.\n' 923 question += ' Type \'help set\' for more information on this command.\n' 924 question += ' - call an external program (ASperGE/MadWidth/...).\n' 925 question += ' Type \'help\' for the list of available command\n' 926 else: 927 question += ' you can also\n' 928 question += ' - enter the path to a valid card.\n' 929 if 'transfer_card.dat' in cards: 930 question += ' - use the \'change_tf\' command to set a transfer functions.\n' 931 932 out = 'to_run' 933 while out not in ['0', 'done']: 934 out = ask(question, '0', possible_answer, timeout=int(1.5*timeout), 935 path_msg='enter path', ask_class = AskforEditCard, 936 cards=cards, mode=mode, **opt)
937 938 @staticmethod
939 - def detect_card_type(path):
940 """detect the type of the card. Return value are 941 banner 942 param_card.dat 943 run_card.dat 944 pythia_card.dat 945 pythia8_card.dat 946 plot_card.dat 947 pgs_card.dat 948 delphes_card.dat 949 delphes_trigger.dat 950 shower_card.dat [aMCatNLO] 951 FO_analyse_card.dat [aMCatNLO] 952 madspin_card.dat [MS] 953 transfer_card.dat [MW] 954 madweight_card.dat [MW] 955 madanalysis5_hadron_card.dat 956 madanalysis5_parton_card.dat 957 958 Please update the unit-test: test_card_type_recognition when adding 959 cards. 960 """ 961 962 fulltext = open(path).read(50000) 963 if fulltext == '': 964 logger.warning('File %s is empty' % path) 965 return 'unknown' 966 967 to_search = ['<MGVersion>', # banner 968 '<mg5proccard>' 969 'ParticlePropagator', # Delphes 970 'ExecutionPath', 971 'Treewriter', 972 'CEN_max_tracker', 973 '#TRIGGER CARD', # delphes_trigger.dat 974 'parameter set name', # pgs_card 975 'muon eta coverage', 976 'req_acc_FO', 977 'MSTP', 978 'b_stable', 979 'FO_ANALYSIS_FORMAT', 980 'MSTU', 981 'Begin Minpts', 982 'gridpack', 983 'ebeam1', 984 'block\s+mw_run', 985 'BLOCK', 986 'DECAY', 987 'launch', 988 'madspin', 989 'transfer_card\.dat', 990 'set', 991 'main:numberofevents', # pythia8, 992 '@MG5aMC skip_analysis', #MA5 --both-- 993 '@MG5aMC\s*inputs\s*=\s*\*\.(?:hepmc|lhe)', #MA5 --both-- 994 '@MG5aMC\s*reconstruction_name', # MA5 hadronique 995 '@MG5aMC' # MA5 hadronique 996 ] 997 998 999 text = re.findall('(%s)' % '|'.join(to_search), fulltext, re.I) 1000 text = [t.lower() for t in text] 1001 if '<mgversion>' in text or '<mg5proccard>' in text: 1002 return 'banner' 1003 elif 'particlepropagator' in text or 'executionpath' in text or 'treewriter' in text: 1004 return 'delphes_card.dat' 1005 elif 'cen_max_tracker' in text: 1006 return 'delphes_card.dat' 1007 elif '@mg5amc' in text: 1008 ma5_flag = [f[7:].strip() for f in text if f.startswith('@mg5amc')] 1009 if any(f.startswith('reconstruction_name') for f in ma5_flag): 1010 return 'madanalysis5_hadron_card.dat' 1011 ma5_flag = [f.split('*.')[1] for f in ma5_flag if '*.' in f] 1012 if any(f.startswith('lhe') for f in ma5_flag): 1013 return 'madanalysis5_parton_card.dat' 1014 if any(f.startswith(('hepmc','hep','stdhep','lhco')) for f in ma5_flag): 1015 return 'madanalysis5_hadron_card.dat' 1016 else: 1017 return 'unknown' 1018 elif '#trigger card' in text: 1019 return 'delphes_trigger.dat' 1020 elif 'parameter set name' in text: 1021 return 'pgs_card.dat' 1022 elif 'muon eta coverage' in text: 1023 return 'pgs_card.dat' 1024 elif 'mstp' in text and not 'b_stable' in text: 1025 return 'pythia_card.dat' 1026 elif 'begin minpts' in text: 1027 return 'plot_card.dat' 1028 elif ('gridpack' in text and 'ebeam1' in text) or \ 1029 ('req_acc_fo' in text and 'ebeam1' in text): 1030 return 'run_card.dat' 1031 elif any(t.endswith('mw_run') for t in text): 1032 return 'madweight_card.dat' 1033 elif 'transfer_card.dat' in text: 1034 return 'transfer_card.dat' 1035 elif 'block' in text and 'decay' in text: 1036 return 'param_card.dat' 1037 elif 'b_stable' in text: 1038 return 'shower_card.dat' 1039 elif 'fo_analysis_format' in text: 1040 return 'FO_analyse_card.dat' 1041 elif 'main:numberofevents' in text: 1042 return 'pythia8_card.dat' 1043 elif 'launch' in text: 1044 # need to separate madspin/reweight. 1045 # decay/set can be in both... 1046 if 'madspin' in text: 1047 return 'madspin_card.dat' 1048 if 'decay' in text: 1049 # need to check if this a line like "decay w+" or "set decay" 1050 if re.search("(^|;)\s*decay", fulltext): 1051 return 'madspin_card.dat' 1052 else: 1053 return 'reweight_card.dat' 1054 else: 1055 return 'reweight_card.dat' 1056 else: 1057 return 'unknown'
1058 1059 1060 ############################################################################
1061 - def get_available_tag(self):
1062 """create automatically a tag""" 1063 1064 used_tags = [r['tag'] for r in self.results[self.run_name]] 1065 i=0 1066 while 1: 1067 i+=1 1068 if 'tag_%s' %i not in used_tags: 1069 return 'tag_%s' % i
1070 1071 1072 ############################################################################ 1073 @misc.mute_logger(names=['madgraph.various.histograms', 1074 'internal.histograms'],levels=[20,20])
1075 - def generate_Pythia8_HwU_plots(self, plot_root_path, 1076 merging_scale_name, observable_name, 1077 data_path):
1078 """Generated the HwU plots from Pythia8 driver output for a specific 1079 observable.""" 1080 1081 # Make sure that the file is present 1082 if not os.path.isfile(data_path): 1083 return False 1084 1085 # Load the HwU file. 1086 histos = histograms.HwUList(data_path, consider_reweights='ALL',run_id=0) 1087 if len(histos)==0: 1088 return False 1089 1090 # Now also plot the max vs min merging scale 1091 merging_scales_available = [label[1] for label in \ 1092 histos[0].bins.weight_labels if 1093 histograms.HwU.get_HwU_wgt_label_type(label)=='merging_scale'] 1094 if len(merging_scales_available)>=2: 1095 min_merging_scale = min(merging_scales_available) 1096 max_merging_scale = max(merging_scales_available) 1097 else: 1098 min_merging_scale = None 1099 max_merging_scale = None 1100 1101 # jet_samples_to_keep = None means that all jet_samples are kept 1102 histo_output_options = { 1103 'format':'gnuplot', 1104 'uncertainties':['scale','pdf','statistical', 1105 'merging_scale','alpsfact'], 1106 'ratio_correlations':True, 1107 'arg_string':'Automatic plotting from MG5aMC', 1108 'jet_samples_to_keep':None, 1109 'use_band':['merging_scale','alpsfact'], 1110 'auto_open':False 1111 } 1112 # alpsfact variation only applies to MLM 1113 if not (int(self.run_card['ickkw'])==1): 1114 histo_output_options['uncertainties'].pop( 1115 histo_output_options['uncertainties'].index('alpsfact')) 1116 histo_output_options['use_band'].pop( 1117 histo_output_options['use_band'].index('alpsfact')) 1118 1119 histos.output(pjoin(plot_root_path, 1120 'central_%s_%s_plots'%(merging_scale_name,observable_name)), 1121 **histo_output_options) 1122 1123 for scale in merging_scales_available: 1124 that_scale_histos = histograms.HwUList( 1125 data_path, run_id=0, merging_scale=scale) 1126 that_scale_histos.output(pjoin(plot_root_path, 1127 '%s_%.3g_%s_plots'%(merging_scale_name,scale,observable_name)), 1128 **histo_output_options) 1129 1130 # If several merging scales were specified, then it is interesting 1131 # to compare the summed jet samples for the maximum and minimum 1132 # merging scale available. 1133 if not min_merging_scale is None: 1134 min_scale_histos = histograms.HwUList(data_path, 1135 consider_reweights=[], run_id=0, 1136 merging_scale=min_merging_scale) 1137 max_scale_histos = histograms.HwUList(data_path, 1138 consider_reweights=[], run_id=0, 1139 merging_scale=max_merging_scale) 1140 1141 # Give the histos types so that the plot labels look good 1142 for histo in min_scale_histos: 1143 if histo.type is None: 1144 histo.type = '%s=%.4g'%(merging_scale_name, min_merging_scale) 1145 else: 1146 histo.type += '|%s=%.4g'%(merging_scale_name, min_merging_scale) 1147 for histo in max_scale_histos: 1148 if histo.type is None: 1149 histo.type = '%s=%.4g'%(merging_scale_name, max_merging_scale) 1150 else: 1151 histo.type += '|%s=%.4g'%(merging_scale_name, max_merging_scale) 1152 1153 # Now plot and compare against oneanother the shape for the the two scales 1154 histograms.HwUList(min_scale_histos+max_scale_histos).output( 1155 pjoin(plot_root_path,'min_max_%s_%s_comparison' 1156 %(merging_scale_name,observable_name)), 1157 format='gnuplot', 1158 uncertainties=[], 1159 ratio_correlations=True, 1160 arg_string='Automatic plotting from MG5aMC', 1161 jet_samples_to_keep=[], 1162 use_band=[], 1163 auto_open=False) 1164 return True
1165
1166 - def create_plot(self, mode='parton', event_path=None, output=None, tag=None):
1167 """create the plot""" 1168 1169 if not tag: 1170 tag = self.run_card['run_tag'] 1171 1172 if mode != 'Pythia8': 1173 madir = self.options['madanalysis_path'] 1174 td = self.options['td_path'] 1175 1176 if not madir or not td or \ 1177 not os.path.exists(pjoin(self.me_dir, 'Cards', 'plot_card.dat')): 1178 return False 1179 else: 1180 PY8_plots_root_path = pjoin(self.me_dir,'HTML', 1181 self.run_name,'%s_PY8_plots'%tag) 1182 1183 if 'ickkw' in self.run_card: 1184 if int(self.run_card['ickkw']) and mode == 'Pythia': 1185 self.update_status('Create matching plots for Pythia', level='pythia') 1186 # recover old data if none newly created 1187 if not os.path.exists(pjoin(self.me_dir,'Events','events.tree')): 1188 misc.gunzip(pjoin(self.me_dir,'Events', 1189 self.run_name, '%s_pythia_events.tree.gz' % tag), keep=True, 1190 stdout=pjoin(self.me_dir,'Events','events.tree')) 1191 files.mv(pjoin(self.me_dir,'Events',self.run_name, tag+'_pythia_xsecs.tree'), 1192 pjoin(self.me_dir,'Events','xsecs.tree')) 1193 1194 # Generate the matching plots 1195 misc.call([self.dirbin+'/create_matching_plots.sh', 1196 self.run_name, tag, madir], 1197 stdout = os.open(os.devnull, os.O_RDWR), 1198 cwd=pjoin(self.me_dir,'Events')) 1199 1200 #Clean output 1201 misc.gzip(pjoin(self.me_dir,"Events","events.tree"), 1202 stdout=pjoin(self.me_dir,'Events',self.run_name, tag + '_pythia_events.tree.gz')) 1203 files.mv(pjoin(self.me_dir,'Events','xsecs.tree'), 1204 pjoin(self.me_dir,'Events',self.run_name, tag+'_pythia_xsecs.tree')) 1205 1206 elif mode == 'Pythia8' and (int(self.run_card['ickkw'])==1 or \ 1207 self.run_card['ktdurham']>0.0 or self.run_card['ptlund']>0.0): 1208 1209 self.update_status('Create matching plots for Pythia8', 1210 level='pythia8') 1211 1212 # Create the directory if not existing at this stage 1213 if not os.path.isdir(PY8_plots_root_path): 1214 os.makedirs(PY8_plots_root_path) 1215 1216 merging_scale_name = 'qCut' if int(self.run_card['ickkw'])==1 \ 1217 else 'TMS' 1218 1219 djr_path = pjoin(self.me_dir,'Events', 1220 self.run_name, '%s_djrs.dat' % tag) 1221 pt_path = pjoin(self.me_dir,'Events', 1222 self.run_name, '%s_pts.dat' % tag) 1223 for observable_name, data_path in [('djr',djr_path), 1224 ('pt',pt_path)]: 1225 if not self.generate_Pythia8_HwU_plots( 1226 PY8_plots_root_path, merging_scale_name, 1227 observable_name,data_path): 1228 return False 1229 1230 if mode == 'Pythia8': 1231 plot_files = glob.glob(pjoin(PY8_plots_root_path,'*.gnuplot')) 1232 if not misc.which('gnuplot'): 1233 logger.warning("Install gnuplot to be able to view the plots"+\ 1234 " generated at :\n "+\ 1235 '\n '.join('%s.gnuplot'%p for p in plot_files)) 1236 return True 1237 for plot in plot_files: 1238 command = ['gnuplot',plot] 1239 try: 1240 subprocess.call(command,cwd=PY8_plots_root_path,stderr=subprocess.PIPE) 1241 except Exception as e: 1242 logger.warning("Automatic processing of the Pythia8 "+\ 1243 "merging plots with gnuplot failed. Try the"+\ 1244 " following command by hand:\n %s"%(' '.join(command))+\ 1245 "\nException was: %s"%str(e)) 1246 return False 1247 1248 plot_files = glob.glob(pjoin(PY8_plots_root_path,'*.pdf')) 1249 if len(plot_files)>0: 1250 # Add an html page 1251 html = "<html>\n<head>\n<TITLE>PLOT FOR PYTHIA8</TITLE>" 1252 html+= '<link rel=stylesheet href="../../mgstyle.css" type="text/css">\n</head>\n<body>\n' 1253 html += "<h2> Plot for Pythia8 </h2>\n" 1254 html += '<a href=../../../crossx.html>return to summary</a><br>' 1255 html += "<table>\n<tr> <td> <b>Obs.</b> </td> <td> <b>Type of plot</b> </td> <td><b> PDF</b> </td> <td><b> input file</b> </td> </tr>\n" 1256 def sorted_plots(elem): 1257 name = os.path.basename(elem[1]) 1258 if 'central' in name: 1259 return -100 1260 if 'min_max' in name: 1261 return -10 1262 merging_re = re.match(r'^.*_(\d+)_.*$',name) 1263 if not merging_re is None: 1264 return int(merging_re.group(1)) 1265 else: 1266 return 1e10
1267 djr_plot_files = sorted( 1268 (('DJR',p) for p in plot_files if '_djr_' in p), 1269 key = sorted_plots) 1270 pt_plot_files = sorted( 1271 (('Pt',p) for p in plot_files if '_pt_' in p), 1272 key = sorted_plots) 1273 last_obs = None 1274 for obs, one_plot in djr_plot_files+pt_plot_files: 1275 if obs!=last_obs: 1276 # Add a line between observables 1277 html += "<tr><td></td></tr>" 1278 last_obs = obs 1279 name = os.path.basename(one_plot).replace('.pdf','') 1280 short_name = name 1281 for dummy in ['_plots','_djr','_pt']: 1282 short_name = short_name.replace(dummy,'') 1283 short_name = short_name.replace('_',' ') 1284 if 'min max' in short_name: 1285 short_name = "%s comparison with min/max merging scale"%obs 1286 if 'central' in short_name: 1287 short_name = "Merging uncertainty band around central scale" 1288 html += "<tr><td>%(obs)s</td><td>%(sn)s</td><td> <a href=./%(n)s.pdf>PDF</a> </td><td> <a href=./%(n)s.HwU>HwU</a> <a href=./%(n)s.gnuplot>GNUPLOT</a> </td></tr>\n" %\ 1289 {'obs':obs, 'sn': short_name, 'n': name} 1290 html += '</table>\n' 1291 html += '<a href=../../../bin/internal/plot_djrs.py> Example of code to plot the above with matplotlib </a><br><br>' 1292 html+='</body>\n</html>' 1293 ff=open(pjoin(PY8_plots_root_path, 'index.html'),'w') 1294 ff.write(html) 1295 return True 1296 1297 if not event_path: 1298 if mode == 'parton': 1299 possibilities=[ 1300 pjoin(self.me_dir, 'Events', 'unweighted_events.lhe'), 1301 pjoin(self.me_dir, 'Events', 'unweighted_events.lhe.gz'), 1302 pjoin(self.me_dir, 'Events', self.run_name, 'unweighted_events.lhe'), 1303 pjoin(self.me_dir, 'Events', self.run_name, 'unweighted_events.lhe.gz')] 1304 for event_path in possibilities: 1305 if os.path.exists(event_path): 1306 break 1307 output = pjoin(self.me_dir, 'HTML',self.run_name, 'plots_parton.html') 1308 1309 elif mode == 'Pythia': 1310 event_path = pjoin(self.me_dir, 'Events','pythia_events.lhe') 1311 output = pjoin(self.me_dir, 'HTML',self.run_name, 1312 'plots_pythia_%s.html' % tag) 1313 elif mode == 'PGS': 1314 event_path = pjoin(self.me_dir, 'Events', self.run_name, 1315 '%s_pgs_events.lhco' % tag) 1316 output = pjoin(self.me_dir, 'HTML',self.run_name, 1317 'plots_pgs_%s.html' % tag) 1318 elif mode == 'Delphes': 1319 event_path = pjoin(self.me_dir, 'Events', self.run_name,'%s_delphes_events.lhco' % tag) 1320 output = pjoin(self.me_dir, 'HTML',self.run_name, 1321 'plots_delphes_%s.html' % tag) 1322 elif mode == "shower": 1323 event_path = pjoin(self.me_dir, 'Events','pythia_events.lhe') 1324 output = pjoin(self.me_dir, 'HTML',self.run_name, 1325 'plots_shower_%s.html' % tag) 1326 if not self.options['pythia-pgs_path']: 1327 return 1328 else: 1329 raise self.InvalidCmd, 'Invalid mode %s' % mode 1330 elif mode == 'reweight' and not output: 1331 output = pjoin(self.me_dir, 'HTML',self.run_name, 1332 'plots_%s.html' % tag) 1333 1334 if not os.path.exists(event_path): 1335 if os.path.exists(event_path+'.gz'): 1336 misc.gunzip('%s.gz' % event_path) 1337 else: 1338 raise self.InvalidCmd, 'Events file %s does not exist' % event_path 1339 elif event_path.endswith(".gz"): 1340 misc.gunzip(event_path) 1341 event_path = event_path[:-3] 1342 1343 1344 self.update_status('Creating Plots for %s level' % mode, level = mode.lower()) 1345 1346 mode = mode.lower() 1347 if mode not in ['parton', 'reweight']: 1348 plot_dir = pjoin(self.me_dir, 'HTML', self.run_name,'plots_%s_%s' % (mode.lower(),tag)) 1349 elif mode == 'parton': 1350 plot_dir = pjoin(self.me_dir, 'HTML', self.run_name,'plots_parton') 1351 else: 1352 plot_dir =pjoin(self.me_dir, 'HTML', self.run_name,'plots_%s' % (tag)) 1353 1354 if not os.path.isdir(plot_dir): 1355 os.makedirs(plot_dir) 1356 1357 files.ln(pjoin(self.me_dir, 'Cards','plot_card.dat'), plot_dir, 'ma_card.dat') 1358 1359 try: 1360 proc = misc.Popen([os.path.join(madir, 'plot_events')], 1361 stdout = open(pjoin(plot_dir, 'plot.log'),'w'), 1362 stderr = subprocess.STDOUT, 1363 stdin=subprocess.PIPE, 1364 cwd=plot_dir) 1365 proc.communicate('%s\n' % event_path) 1366 del proc 1367 #proc.wait() 1368 misc.call(['%s/plot' % self.dirbin, madir, td], 1369 stdout = open(pjoin(plot_dir, 'plot.log'),'a'), 1370 stderr = subprocess.STDOUT, 1371 cwd=plot_dir) 1372 1373 misc.call(['%s/plot_page-pl' % self.dirbin, 1374 os.path.basename(plot_dir), 1375 mode], 1376 stdout = open(pjoin(plot_dir, 'plot.log'),'a'), 1377 stderr = subprocess.STDOUT, 1378 cwd=pjoin(self.me_dir, 'HTML', self.run_name)) 1379 1380 shutil.move(pjoin(self.me_dir, 'HTML',self.run_name ,'plots.html'), 1381 output) 1382 1383 logger.info("Plots for %s level generated, see %s" % \ 1384 (mode, output)) 1385 except OSError, error: 1386 logger.error('fail to create plot: %s. Please check that MadAnalysis is correctly installed.' % error) 1387 1388 self.update_status('End Plots for %s level' % mode, level = mode.lower(), 1389 makehtml=False) 1390 1391 return True 1392
1393 - def run_hep2lhe(self, banner_path = None):
1394 """Run hep2lhe on the file Events/pythia_events.hep""" 1395 1396 if not self.options['pythia-pgs_path']: 1397 raise self.InvalidCmd, 'No pythia-pgs path defined' 1398 1399 pydir = pjoin(self.options['pythia-pgs_path'], 'src') 1400 eradir = self.options['exrootanalysis_path'] 1401 1402 # Creating LHE file 1403 if misc.is_executable(pjoin(pydir, 'hep2lhe')): 1404 self.update_status('Creating shower LHE File (for plot)', level='pythia') 1405 # Write the banner to the LHE file 1406 out = open(pjoin(self.me_dir,'Events','pythia_events.lhe'), 'w') 1407 #out.writelines('<LesHouchesEvents version=\"1.0\">\n') 1408 out.writelines('<!--\n') 1409 out.writelines('# Warning! Never use this file for detector studies!\n') 1410 out.writelines('-->\n<!--\n') 1411 if banner_path: 1412 out.writelines(open(banner_path).read().replace('<LesHouchesEvents version="1.0">','')) 1413 out.writelines('\n-->\n') 1414 out.close() 1415 1416 self.cluster.launch_and_wait(self.dirbin+'/run_hep2lhe', 1417 argument= [pydir], 1418 cwd=pjoin(self.me_dir,'Events'), 1419 stdout=os.devnull) 1420 1421 logger.info('Warning! Never use this lhe file for detector studies!') 1422 # Creating ROOT file 1423 if eradir and misc.is_executable(pjoin(eradir, 'ExRootLHEFConverter')): 1424 self.update_status('Creating Pythia LHE Root File', level='pythia') 1425 try: 1426 misc.call([eradir+'/ExRootLHEFConverter', 1427 'pythia_events.lhe', 1428 pjoin(self.run_name, '%s_pythia_lhe_events.root' % self.run_tag)], 1429 cwd=pjoin(self.me_dir,'Events')) 1430 except Exception, error: 1431 misc.sprint('ExRootLHEFConverter fails', str(error), 1432 log=logger) 1433 pass
1434
1435 - def store_result(self):
1436 """Dummy routine, to be overwritten by daughter classes""" 1437 1438 pass
1439 1440 ############################################################################
1441 - def help_systematics(self):
1442 """help for systematics command""" 1443 logger.info("syntax: systematics RUN_NAME [OUTPUT] [options]",'$MG:color:BLACK') 1444 logger.info("-- Run the systematics run on the RUN_NAME run.") 1445 logger.info(" RUN_NAME can be a path to a lhef file.") 1446 logger.info(" OUTPUT can be the path to the output lhe file, otherwise the input file will be overwritten") 1447 logger.info("") 1448 logger.info("options: (values written are the default)", '$MG:color:BLACK') 1449 logger.info("") 1450 logger.info(" --mur=0.5,1,2 # specify the values for renormalisation scale variation") 1451 logger.info(" --muf=0.5,1,2 # specify the values for factorisation scale variation") 1452 logger.info(" --alps=1 # specify the values for MLM emission scale variation (LO only)") 1453 logger.info(" --dyn=-1,1,2,3,4 # specify the dynamical schemes to use.") 1454 logger.info(" # -1 is the one used by the sample.") 1455 logger.info(" # > 0 correspond to options of dynamical_scale_choice of the run_card.") 1456 logger.info(" --pdf=errorset # specify the pdfs to use for pdf variation. (see below)") 1457 logger.info(" --together=mur,muf,dyn # lists the parameter that must be varied simultaneously so as to ") 1458 logger.info(" # compute the weights for all combinations of their variations.") 1459 logger.info(" --from_card # use the information from the run_card (LO only).") 1460 logger.info("") 1461 logger.info(" Allowed value for the pdf options:", '$MG:color:BLACK') 1462 logger.info(" central : Do not perform any pdf variation" ) 1463 logger.info(" errorset : runs over the all the members of the PDF set used to generate the events") 1464 logger.info(" 244800 : runs over the associated set and all its members") 1465 logger.info(" 244800@0 : runs over the central member of the associated set") 1466 # logger.info(" 244800@X : runs over the Xth set of the associated error set") 1467 logger.info(" CT10 : runs over the associated set and all its members") 1468 logger.info(" CT10@0 : runs over the central member of the associated set") 1469 logger.info(" CT10@X : runs over the Xth member of the associated PDF set") 1470 logger.info(" XX,YY,ZZ : runs over the sets for XX,YY,ZZ (those three follows above syntax)")
1471
1472 - def complete_systematics(self, text, line, begidx, endidx):
1473 """auto completion for the systematics command""" 1474 1475 args = self.split_arg(line[0:begidx], error=False) 1476 options = ['--mur=', '--muf=', '--pdf=', '--dyn=','--alps=','--together=','--from_card '] 1477 1478 if len(args) == 1 and os.path.sep not in text: 1479 #return valid run_name 1480 data = misc.glob(pjoin('*','*events.lhe*'), pjoin(self.me_dir, 'Events')) 1481 data = [n.rsplit('/',2)[1] for n in data] 1482 return self.list_completion(text, data, line) 1483 elif len(args)==1: 1484 #logger.warning('1args') 1485 return self.path_completion(text, 1486 os.path.join('.',*[a for a in args \ 1487 if a.endswith(os.path.sep)])) 1488 elif len(args)==2 and os.path.sep in args[1]: 1489 #logger.warning('2args %s', args[1]) 1490 return self.path_completion(text, '.') 1491 1492 elif not line.endswith(tuple(options)): 1493 return self.list_completion(text, options)
1494 1495 1496 ############################################################################
1497 - def do_systematics(self, line):
1498 """ syntax is 'systematics [INPUT [OUTPUT]] OPTIONS' 1499 --mur=0.5,1,2 1500 --muf=0.5,1,2 1501 --alps=1 1502 --dyn=-1 1503 --together=mur,muf #can be repeated 1504 1505 #special options 1506 --from_card= 1507 """ 1508 1509 lhapdf = misc.import_python_lhapdf(self.options['lhapdf']) 1510 if not lhapdf: 1511 logger.info('can not run systematics since can not link python to lhapdf') 1512 return 1513 1514 self.update_status('Running Systematics computation', level='parton') 1515 args = self.split_arg(line) 1516 #split arguments and option 1517 opts= [] 1518 args = [a for a in args if not a.startswith('-') or opts.append(a)] 1519 1520 #check sanity of options 1521 if any(not o.startswith(('--mur=', '--muf=', '--alps=','--dyn=','--together=','--from_card','--pdf=')) 1522 for o in opts): 1523 raise self.InvalidCmd, "command systematics called with invalid option syntax. Please retry." 1524 1525 # check that we have define the input 1526 if len(args) == 0: 1527 if self.run_name: 1528 args[0] = self.run_name 1529 else: 1530 raise self.InvalidCmd, 'no default run. Please specify the run_name' 1531 1532 if args[0] != self.run_name: 1533 self.set_run_name(args[0]) 1534 1535 # always pass to a path + get the event size 1536 result_file= sys.stdout 1537 if not os.path.isfile(args[0]) and not os.path.sep in args[0]: 1538 path = [pjoin(self.me_dir, 'Events', args[0], 'unweighted_events.lhe.gz'), 1539 pjoin(self.me_dir, 'Events', args[0], 'unweighted_events.lhe'), 1540 pjoin(self.me_dir, 'Events', args[0], 'events.lhe.gz'), 1541 pjoin(self.me_dir, 'Events', args[0], 'events.lhe')] 1542 1543 for p in path: 1544 if os.path.exists(p): 1545 nb_event = self.results[args[0]].get_current_info()['nb_event'] 1546 1547 1548 if self.run_name != args[0]: 1549 tag = self.results[args[0]].tags[0] 1550 self.set_run_name(args[0], tag,'parton', False) 1551 result_file = open(pjoin(self.me_dir,'Events', self.run_name, 'parton_systematics.log'),'w') 1552 args[0] = p 1553 break 1554 else: 1555 raise self.InvalidCmd, 'Invalid run name. Please retry' 1556 elif self.options['nb_core'] != 1: 1557 lhe = lhe_parser.EventFile(args[0]) 1558 nb_event = len(lhe) 1559 lhe.close() 1560 1561 input = args[0] 1562 if len(args)>1: 1563 output = pjoin(os.getcwd(),args[1]) 1564 else: 1565 output = input 1566 1567 lhaid = [self.run_card.get_lhapdf_id()] 1568 if 'store_rwgt_info' in self.run_card and not self.run_card['store_rwgt_info']: 1569 raise self.InvalidCmd, "The events was not generated with store_rwgt_info=True. Can not evaluate systematics error on this event file." 1570 elif 'use_syst' in self.run_card: 1571 if not self.run_card['use_syst']: 1572 raise self.InvalidCmd, "The events was not generated with use_syst=True. Can not evaluate systematics error on this event file." 1573 elif self.proc_characteristics['ninitial'] ==1: 1574 if '--from_card' in opts: 1575 logger.warning('systematics not available for decay processes. Bypass it') 1576 return 1577 else: 1578 raise self.InvalidCmd, 'systematics not available for decay processes.' 1579 1580 try: 1581 pdfsets_dir = self.get_lhapdf_pdfsetsdir() 1582 except Exception, error: 1583 logger.debug(str(error)) 1584 logger.warning('Systematic computation requires lhapdf to run. Bypass Systematics') 1585 return 1586 1587 if '--from_card' in opts: 1588 opts.remove('--from_card') 1589 opts.append('--from_card=internal') 1590 1591 # Check that all pdfset are correctly installed 1592 if 'sys_pdf' in self.run_card: 1593 if '&&' in self.run_card['sys_pdf']: 1594 line = ' '.join(self.run_card['sys_pdf']) 1595 sys_pdf = line.split('&&') 1596 lhaid += [l.split()[0] for l in sys_pdf] 1597 else: 1598 lhaid += [l for l in self.run_card['sys_pdf'].split() if not l.isdigit() or int(l) > 500] 1599 1600 else: 1601 #check that all p 1602 pdf = [a[6:] for a in opts if a.startswith('--pdf=')] 1603 lhaid += [t.split('@')[0] for p in pdf for t in p.split(',') 1604 if t not in ['errorset', 'central']] 1605 1606 # Copy all the relevant PDF sets 1607 [self.copy_lhapdf_set([onelha], pdfsets_dir) for onelha in lhaid] 1608 1609 1610 if self.options['run_mode'] ==2: 1611 nb_submit = min(self.options['nb_core'], nb_event//2500) 1612 elif self.options['run_mode'] ==1: 1613 nb_submit = min(self.options['cluster_size'], nb_event//25000) 1614 else: 1615 nb_submit =1 1616 1617 if MADEVENT: 1618 import internal.systematics as systematics 1619 else: 1620 import madgraph.various.systematics as systematics 1621 1622 #one core: 1623 if nb_submit in [0,1]: 1624 systematics.call_systematics([input, output] + opts, 1625 log=lambda x: logger.info(str(x)), 1626 result=result_file 1627 ) 1628 1629 elif self.options['run_mode'] in [1,2]: 1630 event_per_job = nb_event // nb_submit 1631 nb_job_with_plus_one = nb_event % nb_submit 1632 start_event, stop_event = 0,0 1633 for i in range(nb_submit): 1634 #computing start/stop event 1635 event_requested = event_per_job 1636 if i < nb_job_with_plus_one: 1637 event_requested += 1 1638 start_event = stop_event 1639 stop_event = start_event + event_requested 1640 1641 prog = sys.executable 1642 input_files = [os.path.basename(input)] 1643 output_files = ['./tmp_%s_%s' % (i, os.path.basename(output)), 1644 './log_sys_%s.txt' % (i)] 1645 argument = [] 1646 if not __debug__: 1647 argument.append('-O') 1648 argument += [pjoin(self.me_dir, 'bin', 'internal', 'systematics.py'), 1649 input_files[0], output_files[0]] + opts +\ 1650 ['--start_event=%i' % start_event, 1651 '--stop_event=%i' %stop_event, 1652 '--result=./log_sys_%s.txt' %i, 1653 '--lhapdf_config=%s' % self.options['lhapdf']] 1654 required_output = output_files 1655 self.cluster.cluster_submit(prog, argument, 1656 input_files=input_files, 1657 output_files=output_files, 1658 cwd=os.path.dirname(output), 1659 required_output=required_output, 1660 stdout='/dev/null' 1661 ) 1662 starttime = time.time() 1663 update_status = lambda idle, run, finish: \ 1664 self.update_status((idle, run, finish, 'running systematics'), level=None, 1665 force=False, starttime=starttime) 1666 1667 try: 1668 self.cluster.wait(os.path.dirname(output), update_status, update_first=update_status) 1669 except Exception: 1670 self.cluster.remove() 1671 old_run_mode = self.options['run_mode'] 1672 self.options['run_mode'] =0 1673 try: 1674 out = self.do_systematics(line) 1675 finally: 1676 self.options['run_mode'] = old_run_mode 1677 #collect the data 1678 all_cross = [] 1679 for i in range(nb_submit): 1680 pos=0 1681 for line in open(pjoin(os.path.dirname(output), 'log_sys_%s.txt'%i)): 1682 if line.startswith('#'): 1683 continue 1684 split = line.split() 1685 if len(split) in [0,1]: 1686 continue 1687 key = tuple(float(x) for x in split[:-1]) 1688 cross= float(split[-1]) 1689 if 'event_norm' in self.run_card and \ 1690 self.run_card['event_norm'] in ['average', 'unity']: 1691 cross *= (event_per_job+1 if i <nb_job_with_plus_one else event_per_job) 1692 if len(all_cross) > pos: 1693 all_cross[pos] += cross 1694 else: 1695 all_cross.append(cross) 1696 pos+=1 1697 1698 if 'event_norm' in self.run_card and \ 1699 self.run_card['event_norm'] in ['unity']: 1700 all_cross= [cross/nb_event for cross in all_cross] 1701 1702 sys_obj = systematics.call_systematics([input, None] + opts, 1703 log=lambda x: logger.info(str(x)), 1704 result=result_file, 1705 running=False 1706 ) 1707 sys_obj.print_cross_sections(all_cross, nb_event, result_file) 1708 1709 #concatenate the output file 1710 subprocess.call(['cat']+\ 1711 ['./tmp_%s_%s' % (i, os.path.basename(output)) for i in range(nb_submit)], 1712 stdout=open(output,'w'), 1713 cwd=os.path.dirname(output)) 1714 for i in range(nb_submit): 1715 os.remove('%s/tmp_%s_%s' %(os.path.dirname(output),i,os.path.basename(output))) 1716 # os.remove('%s/log_sys_%s.txt' % (os.path.dirname(output),i)) 1717 1718 1719 1720 1721 1722 self.update_status('End of systematics computation', level='parton', makehtml=False)
1723 1724 1725 ############################################################################
1726 - def do_reweight(self, line):
1727 """ syntax is "reweight RUN_NAME" 1728 Allow to reweight the events generated with a new choices of model 1729 parameter. Description of the methods are available here 1730 cp3.irmp.ucl.ac.be/projects/madgraph/wiki/Reweight 1731 """ 1732 1733 #### Utility function 1734 def check_multicore(self): 1735 """ determine if the cards are save for multicore use""" 1736 card = pjoin(self.me_dir, 'Cards', 'reweight_card.dat') 1737 1738 multicore = True 1739 if self.options['run_mode'] in [0,1]: 1740 multicore = False 1741 1742 lines = [l.strip() for l in open(card) if not l.strip().startswith('#')] 1743 while lines and not lines[0].startswith('launch'): 1744 line = lines.pop(0) 1745 # if not standard output mode forbid multicore mode 1746 if line.startswith('change') and line[6:].strip().startswith('output'): 1747 return False 1748 if line.startswith('change') and line[6:].strip().startswith('multicore'): 1749 split_line = line.split() 1750 if len(split_line) > 2: 1751 multicore = bool(split_line[2]) 1752 # we have reached the first launch in the card ensure that no output change 1753 #are done after that point. 1754 lines = [line[6:].strip() for line in lines if line.startswith('change')] 1755 for line in lines: 1756 if line.startswith(('process','model','output', 'rwgt_dir')): 1757 return False 1758 elif line.startswith('multicore'): 1759 split_line = line.split() 1760 if len(split_line) > 1: 1761 multicore = bool(split_line[1]) 1762 1763 return multicore
1764 1765 1766 1767 if '-from_cards' in line and not os.path.exists(pjoin(self.me_dir, 'Cards', 'reweight_card.dat')): 1768 return 1769 # option for multicore to avoid that all of them create the same directory 1770 if '--multicore=create' in line: 1771 multicore='create' 1772 elif '--multicore=wait' in line: 1773 multicore='wait' 1774 else: 1775 multicore=False 1776 1777 # Check that MG5 directory is present . 1778 if MADEVENT and not self.options['mg5_path']: 1779 raise self.InvalidCmd, '''The module reweight requires that MG5 is installed on the system. 1780 You can install it and set its path in ./Cards/me5_configuration.txt''' 1781 elif MADEVENT: 1782 sys.path.append(self.options['mg5_path']) 1783 try: 1784 import madgraph.interface.reweight_interface as reweight_interface 1785 except ImportError: 1786 raise self.ConfigurationError, '''Can\'t load Reweight module. 1787 The variable mg5_path might not be correctly configured.''' 1788 1789 1790 1791 if not '-from_cards' in line: 1792 self.keep_cards(['reweight_card.dat'], ignore=['*']) 1793 self.ask_edit_cards(['reweight_card.dat'], 'fixed', plot=False) 1794 1795 # load the name of the event file 1796 args = self.split_arg(line) 1797 1798 if not self.force_run: 1799 # forbid this function to create an empty item in results. 1800 if self.run_name and self.results.current and self.results.current['cross'] == 0: 1801 self.results.delete_run(self.run_name, self.run_tag) 1802 self.results.save() 1803 # ensure that the run_card is present 1804 if not hasattr(self, 'run_card'): 1805 self.run_card = banner_mod.RunCard(pjoin(self.me_dir, 'Cards', 'run_card.dat')) 1806 1807 # we want to run this in a separate shell to avoid hard f2py crash 1808 command = [sys.executable] 1809 if os.path.exists(pjoin(self.me_dir, 'bin', 'madevent')): 1810 command.append(pjoin(self.me_dir, 'bin', 'internal','madevent_interface.py')) 1811 else: 1812 command.append(pjoin(self.me_dir, 'bin', 'internal', 'amcatnlo_run_interface.py')) 1813 if not isinstance(self, cmd.CmdShell): 1814 command.append('--web') 1815 command.append('reweight') 1816 1817 ######### START SINGLE CORE MODE ############ 1818 if self.options['nb_core']==1 or self.run_card['nevents'] < 101 or not check_multicore(self): 1819 if self.run_name: 1820 command.append(self.run_name) 1821 else: 1822 command += args 1823 if '-from_cards' not in command: 1824 command.append('-from_cards') 1825 p = misc.Popen(command, stdout = subprocess.PIPE, stderr = subprocess.STDOUT, cwd=os.getcwd()) 1826 while p.poll() is None: 1827 line = p.stdout.readline() 1828 if any(t in line for t in ['INFO:', 'WARNING:', 'CRITICAL:', 'ERROR:', 'root:','KEEP:']) and \ 1829 not '***********' in line: 1830 print line[:-1].replace('INFO', 'REWEIGHT').replace('KEEP:','') 1831 elif __debug__ and line: 1832 logger.debug(line[:-1]) 1833 if p.returncode !=0: 1834 logger.error("Reweighting failed") 1835 return 1836 self.results = self.load_results_db() 1837 # forbid this function to create an empty item in results. 1838 try: 1839 if self.results[self.run_name][-2]['cross']==0: 1840 self.results.delete_run(self.run_name,self.results[self.run_name][-2]['tag']) 1841 except: 1842 pass 1843 try: 1844 if self.results.current['cross'] == 0 and self.run_name: 1845 self.results.delete_run(self.run_name, self.run_tag) 1846 except: 1847 pass 1848 # re-define current run 1849 try: 1850 self.results.def_current(self.run_name, self.run_tag) 1851 except Exception: 1852 pass 1853 return 1854 ########## END SINGLE CORE HANDLING ############# 1855 else: 1856 ########## START MULTI-CORE HANDLING ############# 1857 if not isinstance(self.cluster, cluster.MultiCore): 1858 mycluster = cluster.MultiCore(nb_core=self.options['nb_core']) 1859 else: 1860 mycluster = self.cluster 1861 1862 new_args=list(args) 1863 self.check_decay_events(new_args) 1864 try: 1865 os.remove(pjoin(self.me_dir,'rw_me','rwgt.pkl')) 1866 except Exception, error: 1867 pass 1868 # prepare multi-core job: 1869 import madgraph.various.lhe_parser as lhe_parser 1870 # args now alway content the path to the valid files 1871 if 'nevt_job' in self.run_card and self.run_card['nevt_job'] !=-1: 1872 nevt_job = self.run_card['nevt_job'] 1873 else: 1874 nevt_job = max(5000, self.run_card['nevents']/50) 1875 logger.info("split the event file in bunch of %s events" % nevt_job) 1876 nb_file = lhe_parser.EventFile(new_args[0]).split(nevt_job) 1877 starttime = time.time() 1878 update_status = lambda idle, run, finish: \ 1879 self.update_status((idle, run, finish, 'reweight'), level=None, 1880 force=False, starttime=starttime) 1881 1882 all_lhe = [] 1883 devnull= open(os.devnull) 1884 for i in range(nb_file): 1885 new_command = list(command) 1886 new_command.append('%s_%s.lhe' % (new_args[0],i)) 1887 all_lhe.append('%s_%s.lhe' % (new_args[0],i)) 1888 if '-from_cards' not in command: 1889 new_command.append('-from_cards') 1890 if i==0: 1891 if __debug__: 1892 stdout = None 1893 else: 1894 stdout = open(pjoin(self.me_dir,'Events', self.run_name, 'reweight.log'),'w') 1895 new_command.append('--multicore=create') 1896 else: 1897 stdout = devnull 1898 #stdout = open(pjoin(self.me_dir,'Events', self.run_name, 'reweight%s.log' % i),'w') 1899 new_command.append('--multicore=wait') 1900 mycluster.submit(prog=command[0], argument=new_command[1:], stdout=stdout, cwd=os.getcwd()) 1901 mycluster.wait(self.me_dir,update_status) 1902 devnull.close() 1903 logger.info("Collect and combine the various output file.") 1904 lhe = lhe_parser.MultiEventFile(all_lhe, parse=False) 1905 nb_event, cross_sections = lhe.write(new_args[0], get_info=True) 1906 if any(os.path.exists('%s_%s_debug.log' % (f, self.run_tag)) for f in all_lhe): 1907 for f in all_lhe: 1908 if os.path.exists('%s_%s_debug.log' % (f, self.run_tag)): 1909 raise Exception, "Some of the run failed: Please read %s_%s_debug.log" % (f, self.run_tag) 1910 1911 1912 if 'event_norm' in self.run_card and self.run_card['event_norm'] == 'average': 1913 for key, value in cross_sections.items(): 1914 cross_sections[key] = value / (nb_event+1) 1915 lhe.remove() 1916 for key in cross_sections: 1917 if key == 'orig' or key.isdigit(): 1918 continue 1919 logger.info('%s : %s pb' % (key, cross_sections[key])) 1920 return 1921 ########## END MULTI-CORE HANDLING ############# 1922 1923 1924 self.to_store.append('event') 1925 # forbid this function to create an empty item in results. 1926 if self.results.current['cross'] == 0 and self.run_name: 1927 self.results.delete_run(self.run_name, self.run_tag) 1928 1929 self.check_decay_events(args) 1930 # args now alway content the path to the valid files 1931 reweight_cmd = reweight_interface.ReweightInterface(args[0], mother=self) 1932 #reweight_cmd.use_rawinput = False 1933 #reweight_cmd.mother = self 1934 wgt_names = reweight_cmd.get_weight_names() 1935 if wgt_names == [''] and reweight_cmd.has_nlo: 1936 self.update_status('Running Reweighting (LO approximate)', level='madspin') 1937 else: 1938 self.update_status('Running Reweighting', level='madspin') 1939 1940 path = pjoin(self.me_dir, 'Cards', 'reweight_card.dat') 1941 reweight_cmd.raw_input=False 1942 reweight_cmd.me_dir = self.me_dir 1943 reweight_cmd.multicore = multicore #allow the directory creation or not 1944 print "We are in mode", multicore 1945 reweight_cmd.import_command_file(path) 1946 reweight_cmd.do_quit('') 1947 1948 logger.info("quit rwgt") 1949 1950 1951 1952 # re-define current run 1953 try: 1954 self.results.def_current(self.run_name, self.run_tag) 1955 except Exception: 1956 pass 1957 1958 ############################################################################
1959 - def do_pgs(self, line):
1960 """launch pgs""" 1961 1962 args = self.split_arg(line) 1963 # Check argument's validity 1964 if '--no_default' in args: 1965 no_default = True 1966 args.remove('--no_default') 1967 else: 1968 no_default = False 1969 1970 if no_default and not os.path.exists(pjoin(self.me_dir, 'Cards', 'pgs_card.dat')): 1971 logger.info('No pgs_card detected, so not run pgs') 1972 return 1973 1974 # Check all arguments 1975 # This might launch a gunzip in another thread. After the question 1976 # This thread need to be wait for completion. (This allow to have the 1977 # question right away and have the computer working in the same time) 1978 # if lock is define this a locker for the completion of the thread 1979 lock = self.check_pgs(args, no_default=no_default) 1980 1981 # Check that the pgs_card exists. If not copy the default 1982 if not os.path.exists(pjoin(self.me_dir, 'Cards', 'pgs_card.dat')): 1983 files.cp(pjoin(self.me_dir, 'Cards', 'pgs_card_default.dat'), 1984 pjoin(self.me_dir, 'Cards', 'pgs_card.dat')) 1985 logger.info('No pgs card found. Take the default one.') 1986 1987 if not (no_default or self.force): 1988 self.ask_edit_cards(['pgs_card.dat']) 1989 1990 self.update_status('prepare PGS run', level=None) 1991 1992 pgsdir = pjoin(self.options['pythia-pgs_path'], 'src') 1993 eradir = self.options['exrootanalysis_path'] 1994 madir = self.options['madanalysis_path'] 1995 td = self.options['td_path'] 1996 1997 # Compile pgs if not there 1998 if not misc.is_executable(pjoin(pgsdir, 'pgs')): 1999 logger.info('No PGS executable -- running make') 2000 misc.compile(cwd=pgsdir) 2001 2002 self.update_status('Running PGS', level='pgs') 2003 2004 tag = self.run_tag 2005 # Update the banner with the pgs card 2006 banner_path = pjoin(self.me_dir, 'Events', self.run_name, '%s_%s_banner.txt' % (self.run_name, self.run_tag)) 2007 if os.path.exists(pjoin(self.me_dir, 'Source', 'banner_header.txt')): 2008 self.banner.add(pjoin(self.me_dir, 'Cards','pgs_card.dat')) 2009 self.banner.write(banner_path) 2010 else: 2011 open(banner_path, 'w').close() 2012 2013 ######################################################################## 2014 # now pass the event to a detector simulator and reconstruct objects 2015 ######################################################################## 2016 if lock: 2017 lock.wait() 2018 # Prepare the output file with the banner 2019 ff = open(pjoin(self.me_dir, 'Events', 'pgs_events.lhco'), 'w') 2020 if os.path.exists(pjoin(self.me_dir, 'Source', 'banner_header.txt')): 2021 text = open(banner_path).read() 2022 text = '#%s' % text.replace('\n','\n#') 2023 dico = self.results[self.run_name].get_current_info() 2024 text +='\n## Integrated weight (pb) : %.4g' % dico['cross'] 2025 text +='\n## Number of Event : %s\n' % dico['nb_event'] 2026 ff.writelines(text) 2027 ff.close() 2028 2029 try: 2030 os.remove(pjoin(self.me_dir, 'Events', 'pgs.done')) 2031 except Exception: 2032 pass 2033 2034 pgs_log = pjoin(self.me_dir, 'Events', self.run_name, "%s_pgs.log" % tag) 2035 self.cluster.launch_and_wait('../bin/internal/run_pgs', 2036 argument=[pgsdir], cwd=pjoin(self.me_dir,'Events'), 2037 stdout=pgs_log, stderr=subprocess.STDOUT) 2038 2039 if not os.path.exists(pjoin(self.me_dir, 'Events', 'pgs.done')): 2040 logger.error('Fail to create LHCO events') 2041 return 2042 else: 2043 os.remove(pjoin(self.me_dir, 'Events', 'pgs.done')) 2044 2045 if os.path.getsize(banner_path) == os.path.getsize(pjoin(self.me_dir, 'Events','pgs_events.lhco')): 2046 misc.call(['cat pgs_uncleaned_events.lhco >> pgs_events.lhco'], 2047 cwd=pjoin(self.me_dir, 'Events')) 2048 os.remove(pjoin(self.me_dir, 'Events', 'pgs_uncleaned_events.lhco ')) 2049 2050 # Creating Root file 2051 if eradir and misc.is_executable(pjoin(eradir, 'ExRootLHCOlympicsConverter')): 2052 self.update_status('Creating PGS Root File', level='pgs') 2053 try: 2054 misc.call([eradir+'/ExRootLHCOlympicsConverter', 2055 'pgs_events.lhco',pjoin('%s/%s_pgs_events.root' % (self.run_name, tag))], 2056 cwd=pjoin(self.me_dir, 'Events')) 2057 except Exception: 2058 logger.warning('fail to produce Root output [problem with ExRootAnalysis') 2059 if os.path.exists(pjoin(self.me_dir, 'Events', 'pgs_events.lhco')): 2060 # Creating plots 2061 files.mv(pjoin(self.me_dir, 'Events', 'pgs_events.lhco'), 2062 pjoin(self.me_dir, 'Events', self.run_name, '%s_pgs_events.lhco' % tag)) 2063 self.create_plot('PGS') 2064 misc.gzip(pjoin(self.me_dir, 'Events', self.run_name, '%s_pgs_events.lhco' % tag)) 2065 2066 self.update_status('finish', level='pgs', makehtml=False)
2067 2068 ############################################################################
2069 - def do_compute_widths(self, line):
2070 """Require MG5 directory: Compute automatically the widths of a set 2071 of particles""" 2072 2073 2074 2075 args = self.split_arg(line) 2076 opts = self.check_compute_widths(args) 2077 2078 from madgraph.interface.master_interface import MasterCmd 2079 cmd = MasterCmd() 2080 self.define_child_cmd_interface(cmd, interface=False) 2081 cmd.exec_cmd('set automatic_html_opening False --no_save') 2082 if not opts['path']: 2083 opts['path'] = pjoin(self.me_dir, 'Cards', 'param_card.dat') 2084 if not opts['force'] : 2085 self.ask_edit_cards(['param_card'],[], plot=False) 2086 2087 2088 line = 'compute_widths %s %s' % \ 2089 (' '.join([str(i) for i in opts['particles']]), 2090 ' '.join('--%s=%s' % (key,value) for (key,value) in opts.items() 2091 if key not in ['model', 'force', 'particles'] and value)) 2092 cmd.exec_cmd(line, model=opts['model']) 2093 self.child = None 2094 del cmd
2095 2096 ############################################################################
2097 - def do_print_results(self, line):
2098 """Not in help:Print the cross-section/ number of events for a given run""" 2099 2100 args = self.split_arg(line) 2101 options={'path':None, 'mode':'w', 'format':'full'} 2102 for arg in list(args): 2103 if arg.startswith('--') and '=' in arg: 2104 name,value=arg.split('=',1) 2105 name = name [2:] 2106 options[name] = value 2107 args.remove(arg) 2108 2109 2110 if len(args) > 0: 2111 run_name = args[0] 2112 else: 2113 for i, run_name in enumerate(self.results.order): 2114 for j, one_result in enumerate(self.results[run_name]): 2115 if i or j: 2116 options['mode'] = "a" 2117 if options['path']: 2118 self.print_results_in_file(one_result, options['path'], options['mode'], options['format']) 2119 else: 2120 self.print_results_in_shell(one_result) 2121 return 2122 2123 if run_name not in self.results: 2124 raise self.InvalidCmd('%s is not a valid run_name or it doesn\'t have any information' \ 2125 % run_name) 2126 2127 2128 if len(args) == 2: 2129 tag = args[1] 2130 if tag.isdigit(): 2131 tag = int(tag) - 1 2132 if len(self.results[run_name]) < tag: 2133 raise self.InvalidCmd('Only %s different tag available' % \ 2134 len(self.results[run_name])) 2135 data = self.results[run_name][tag] 2136 else: 2137 data = self.results[run_name].return_tag(tag) 2138 else: 2139 data = self.results[run_name].return_tag(None) # return the last 2140 2141 if options['path']: 2142 self.print_results_in_file(data, options['path'], options['mode'], options['format']) 2143 else: 2144 self.print_results_in_shell(data)
2145
2146 - def configure_directory(self, *args, **opts):
2147 """ All action require before any type of run. Typically overloaded by 2148 daughters if need be.""" 2149 pass
2150 2151 ############################################################################ 2152 # Start of MadAnalysis5 related function 2153 ############################################################################ 2154 2155 @staticmethod
2156 - def runMA5(MA5_interpreter, MA5_cmds, MA5_runtag, logfile_path, advertise_log=True):
2157 """ Run MA5 in a controlled environnment.""" 2158 successfull_MA5_run = True 2159 2160 try: 2161 # Predefine MA5_logger as None in case we don't manage to retrieve it. 2162 MA5_logger = None 2163 MA5_logger = logging.getLogger('MA5') 2164 BackUp_MA5_handlers = MA5_logger.handlers 2165 for handler in BackUp_MA5_handlers: 2166 MA5_logger.removeHandler(handler) 2167 file_handler = logging.FileHandler(logfile_path) 2168 MA5_logger.addHandler(file_handler) 2169 if advertise_log: 2170 logger.info("Follow Madanalysis5 run with the following command in a separate terminal:") 2171 logger.info(' tail -f %s'%logfile_path) 2172 # Now the magic, finally call MA5. 2173 with misc.stdchannel_redirected(sys.stdout, os.devnull): 2174 with misc.stdchannel_redirected(sys.stderr, os.devnull): 2175 MA5_interpreter.print_banner() 2176 MA5_interpreter.load(MA5_cmds) 2177 except Exception as e: 2178 logger.warning("MadAnalysis5 failed to run the commands for task "+ 2179 "'%s'. Madanalys5 analysis will be skipped."%MA5_runtag) 2180 error=StringIO.StringIO() 2181 traceback.print_exc(file=error) 2182 logger.debug('MadAnalysis5 error was:') 2183 logger.debug('-'*60) 2184 logger.debug(error.getvalue()[:-1]) 2185 logger.debug('-'*60) 2186 successfull_MA5_run = False 2187 finally: 2188 if not MA5_logger is None: 2189 for handler in MA5_logger.handlers: 2190 MA5_logger.removeHandler(handler) 2191 for handler in BackUp_MA5_handlers: 2192 MA5_logger.addHandler(handler) 2193 2194 return successfull_MA5_run
2195 2196 #=============================================================================== 2197 # Return a Main instance of MadAnlysis5, provided its path 2198 #=============================================================================== 2199 @staticmethod
2200 - def get_MadAnalysis5_interpreter(mg5_path, ma5_path, mg5_interface=None, 2201 logstream = sys.stdout, loglevel =logging.INFO, forced = True):
2202 """ Makes sure to correctly setup paths and constructs and return an MA5 path""" 2203 2204 MA5path = os.path.normpath(pjoin(mg5_path,ma5_path)) 2205 2206 if MA5path is None or not os.path.isfile(pjoin(MA5path,'bin','ma5')): 2207 return None 2208 if MA5path not in sys.path: 2209 sys.path.insert(0, MA5path) 2210 2211 try: 2212 # We must backup the readline module attributes because they get modified 2213 # when MA5 imports root and that supersedes MG5 autocompletion 2214 import readline 2215 old_completer = readline.get_completer() 2216 old_delims = readline.get_completer_delims() 2217 old_history = [readline.get_history_item(i) for i in range(1,readline.get_current_history_length()+1)] 2218 except ImportError: 2219 old_completer, old_delims, old_history = None, None, None 2220 try: 2221 from madanalysis.interpreter.ma5_interpreter import MA5Interpreter 2222 with misc.stdchannel_redirected(sys.stdout, os.devnull): 2223 with misc.stdchannel_redirected(sys.stderr, os.devnull): 2224 MA5_interpreter = MA5Interpreter(MA5path, LoggerLevel=loglevel, 2225 LoggerStream=logstream,forced=forced) 2226 except Exception as e: 2227 logger.warning('MadAnalysis5 failed to start so that MA5 analysis will be skipped.') 2228 error=StringIO.StringIO() 2229 traceback.print_exc(file=error) 2230 logger.debug('MadAnalysis5 error was:') 2231 logger.debug('-'*60) 2232 logger.debug(error.getvalue()[:-1]) 2233 logger.debug('-'*60) 2234 MA5_interpreter = None 2235 finally: 2236 # Now restore the readline MG5 state 2237 if not old_history is None: 2238 readline.clear_history() 2239 for line in old_history: 2240 readline.add_history(line) 2241 if not old_completer is None: 2242 readline.set_completer(old_completer) 2243 if not old_delims is None: 2244 readline.set_completer_delims(old_delims) 2245 # Also restore the completion_display_matches_hook if an mg5 interface 2246 # is specified as it could also have been potentially modified 2247 if not mg5_interface is None and any(not elem is None for elem in [old_completer, old_delims, old_history]): 2248 mg5_interface.set_readline_completion_display_matches_hook() 2249 2250 return MA5_interpreter
2251
2252 - def check_madanalysis5(self, args, mode='parton'):
2253 """Check the argument for the madanalysis5 command 2254 syntax: madanalysis5_parton [NAME] 2255 """ 2256 2257 MA5_options = {'MA5_stdout_lvl':'default'} 2258 2259 stdout_level_tags = [a for a in args if a.startswith('--MA5_stdout_lvl=')] 2260 for slt in stdout_level_tags: 2261 lvl = slt.split('=')[1].strip() 2262 try: 2263 # It is likely an int 2264 MA5_options['MA5_stdout_lvl']=int(lvl) 2265 except ValueError: 2266 if lvl.startswith('logging.'): 2267 lvl = lvl[8:] 2268 try: 2269 MA5_options['MA5_stdout_lvl'] = getattr(logging, lvl) 2270 except: 2271 raise InvalidCmd("MA5 output level specification"+\ 2272 " '%s' is incorrect." % str(lvl)) 2273 args.remove(slt) 2274 2275 if mode=='parton': 2276 # We will attempt to run MA5 on the parton level output 2277 # found in the last run if not specified. 2278 MA5_options['inputs'] = '*.lhe' 2279 elif mode=='hadron': 2280 # We will run MA5 on all sources of post-partonic output we 2281 # can find if not specified. PY8 is a keyword indicating shower 2282 # piped to MA5. 2283 MA5_options['inputs'] = ['fromCard'] 2284 else: 2285 raise MadGraph5Error('Mode %s not reckognized'%mode+ 2286 ' in function check_madanalysis5.') 2287 # If not madanalysis5 path 2288 if not self.options['madanalysis5_path']: 2289 logger.info('Now trying to read the configuration file again'+ 2290 ' to find MadAnalysis5 path') 2291 self.set_configuration() 2292 2293 if not self.options['madanalysis5_path'] or not \ 2294 os.path.exists(pjoin(self.options['madanalysis5_path'],'bin','ma5')): 2295 error_msg = 'No valid MadAnalysis5 path set.\n' 2296 error_msg += 'Please use the set command to define the path and retry.\n' 2297 error_msg += 'You can also define it in the configuration file.\n' 2298 error_msg += 'Finally, it can be installed automatically using the' 2299 error_msg += ' install command.\n' 2300 raise self.InvalidCmd(error_msg) 2301 2302 # Now make sure that the corresponding default card exists 2303 if not os.path.isfile(pjoin(self.me_dir, 2304 'Cards','madanalysis5_%s_card.dat'%mode)): 2305 raise self.InvalidCmd('Your installed version of MadAnalysis5 and/or'+\ 2306 ' MadGraph5_aMCatNLO does not seem to support analysis at'+ 2307 '%s level.'%mode) 2308 2309 tag = [a for a in args if a.startswith('--tag=')] 2310 if tag: 2311 args.remove(tag[0]) 2312 tag = tag[0][6:] 2313 2314 if len(args) == 0 and not self.run_name: 2315 if self.results.lastrun: 2316 args.insert(0, self.results.lastrun) 2317 else: 2318 raise self.InvalidCmd('No run name currently defined. '+ 2319 'Please add this information.') 2320 2321 if len(args) >= 1: 2322 if mode=='parton' and args[0] != self.run_name and \ 2323 not os.path.exists(pjoin(self.me_dir,'Events',args[0], 2324 'unweighted_events.lhe.gz')) and not os.path.exists( 2325 pjoin(self.me_dir,'Events',args[0])): 2326 raise self.InvalidCmd('No events file in the %s run.'%args[0]) 2327 self.set_run_name(args[0], tag, level='madanalysis5_%s'%mode) 2328 else: 2329 if tag: 2330 self.run_card['run_tag'] = args[0] 2331 self.set_run_name(self.run_name, tag, level='madanalysis5_%s'%mode) 2332 2333 if mode=='parton': 2334 if any(t for t in args if t.startswith('--input=')): 2335 raise InvalidCmd('The option --input=<input_file> is not'+ 2336 ' available when running partonic MadAnalysis5 analysis. The'+ 2337 ' .lhe output of the selected run is used automatically.') 2338 input_file = pjoin(self.me_dir,'Events',self.run_name, 'unweighted_events.lhe') 2339 MA5_options['inputs'] = '%s.gz'%input_file 2340 if not os.path.exists('%s.gz'%input_file): 2341 if os.path.exists(input_file): 2342 misc.gzip(input_file, keep=True, stdout=output_file) 2343 else: 2344 logger.warning("LHE event file not found in \n%s\ns"%input_file+ 2345 "Parton-level MA5 analysis will be skipped.") 2346 2347 if mode=='hadron': 2348 # Make sure to store current results (like Pythia8 hep files) 2349 # so that can be found here 2350 self.store_result() 2351 2352 hadron_tag = [t for t in args if t.startswith('--input=')] 2353 if hadron_tag and hadron_tag[0][8:]: 2354 hadron_inputs = hadron_tag[0][8:].split(',') 2355 2356 # If not set above, then we must read it from the card 2357 elif MA5_options['inputs'] == ['fromCard']: 2358 hadron_inputs = banner_mod.MadAnalysis5Card(pjoin(self.me_dir, 2359 'Cards','madanalysis5_hadron_card.dat'),mode='hadron')['inputs'] 2360 2361 # Make sure the corresponding input files are present and unfold 2362 # potential wildcard while making their path absolute as well. 2363 MA5_options['inputs'] = [] 2364 special_source_tags = [] 2365 for htag in hadron_inputs: 2366 # Possible pecial tag for MA5 run inputs 2367 if htag in special_source_tags: 2368 # Special check/actions 2369 continue 2370 # Check if the specified file exists and is not a wildcard 2371 if os.path.isfile(htag) or (os.path.exists(htag) and 2372 stat.S_ISFIFO(os.stat(htag).st_mode)): 2373 MA5_options['inputs'].append(htag) 2374 continue 2375 2376 # Now select one source per tag, giving priority to unzipped 2377 # files with 'events' in their name (case-insensitive). 2378 file_candidates = misc.glob(htag, pjoin(self.me_dir,'Events',self.run_name))+\ 2379 misc.glob('%s.gz'%htag, pjoin(self.me_dir,'Events',self.run_name)) 2380 priority_files = [f for f in file_candidates if 2381 self.run_card['run_tag'] in os.path.basename(f)] 2382 priority_files = [f for f in priority_files if 2383 'EVENTS' in os.path.basename(f).upper()] 2384 # Make sure to always prefer the original partonic event file 2385 for f in file_candidates: 2386 if os.path.basename(f).startswith('unweighted_events.lhe'): 2387 priority_files.append(f) 2388 if priority_files: 2389 MA5_options['inputs'].append(priority_files[-1]) 2390 continue 2391 if file_candidates: 2392 MA5_options['inputs'].append(file_candidates[-1]) 2393 continue 2394 2395 return MA5_options
2396
2397 - def ask_madanalysis5_run_configuration(self, runtype='parton',mode=None):
2398 """Ask the question when launching madanalysis5. 2399 In the future we can ask here further question about the MA5 run, but 2400 for now we just edit the cards""" 2401 2402 cards = ['madanalysis5_%s_card.dat'%runtype] 2403 self.keep_cards(cards) 2404 2405 if self.force: 2406 return runtype 2407 2408 # This heavy-looking structure of auto is just to mimick what is done 2409 # for ask_pythia_configuration 2410 auto=False 2411 if mode=='auto': 2412 auto=True 2413 if auto: 2414 self.ask_edit_cards(cards, mode='auto', plot=False) 2415 else: 2416 self.ask_edit_cards(cards, plot=False) 2417 2418 # For now, we don't pass any further information and simply return the 2419 # input mode asked for 2420 mode = runtype 2421 return mode
2422
2423 - def complete_madanalysis5_hadron(self,text, line, begidx, endidx):
2424 "Complete the madanalysis5 command" 2425 args = self.split_arg(line[0:begidx], error=False) 2426 if len(args) == 1: 2427 #return valid run_name 2428 data = [] 2429 for name in banner_mod.MadAnalysis5Card._default_hadron_inputs: 2430 data += misc.glob(pjoin('*','%s'%name), pjoin(self.me_dir, 'Events')) 2431 data += misc.glob(pjoin('*','%s.gz'%name), pjoin(self.me_dir, 'Events')) 2432 data = [n.rsplit('/',2)[1] for n in data] 2433 tmp1 = self.list_completion(text, data) 2434 if not self.run_name: 2435 return tmp1 2436 else: 2437 tmp2 = self.list_completion(text, ['-f', 2438 '--MA5_stdout_lvl=','--input=','--no_default', '--tag='], line) 2439 return tmp1 + tmp2 2440 2441 elif '--MA5_stdout_lvl=' in line and not any(arg.startswith( 2442 '--MA5_stdout_lvl=') for arg in args): 2443 return self.list_completion(text, 2444 ['--MA5_stdout_lvl=%s'%opt for opt in 2445 ['logging.INFO','logging.DEBUG','logging.WARNING', 2446 'logging.CRITICAL','90']], line) 2447 elif '--input=' in line and not any(arg.startswith( 2448 '--input=') for arg in args): 2449 return self.list_completion(text, ['--input=%s'%opt for opt in 2450 (banner_mod.MadAnalysis5Card._default_hadron_inputs +['path'])], line) 2451 else: 2452 return self.list_completion(text, ['-f', 2453 '--MA5_stdout_lvl=','--input=','--no_default', '--tag='], line)
2454
2455 - def do_madanalysis5_hadron(self, line):
2456 """launch MadAnalysis5 at the hadron level.""" 2457 return self.run_madanalysis5(line,mode='hadron')
2458
2459 - def run_madanalysis5(self, line, mode='parton'):
2460 """launch MadAnalysis5 at the parton level or at the hadron level with 2461 a specific command line.""" 2462 2463 # Check argument's validity 2464 args = self.split_arg(line) 2465 2466 if '--no_default' in args: 2467 no_default = True 2468 args.remove('--no_default') 2469 else: 2470 no_default = False 2471 2472 if no_default: 2473 # Called issued by MG5aMC itself during a generate_event action 2474 if mode=='parton' and not os.path.exists(pjoin(self.me_dir, 'Cards', 2475 'madanalysis5_parton_card.dat')): 2476 return 2477 if mode=='hadron' and not os.path.exists(pjoin(self.me_dir, 'Cards', 2478 'madanalysis5_hadron_card.dat')): 2479 return 2480 else: 2481 # Called issued by the user itself and only MA5 will be run. 2482 # we must therefore ask wheter the user wants to edit the card 2483 self.ask_madanalysis5_run_configuration(runtype=mode) 2484 2485 if not self.options['madanalysis5_path'] or \ 2486 all(not os.path.exists(pjoin(self.me_dir, 'Cards',card)) for card in 2487 ['madanalysis5_parton_card.dat','madanalysis5_hadron_card.dat']): 2488 if no_default: 2489 return 2490 else: 2491 raise InvalidCmd('You must have MadAnalysis5 available to run'+ 2492 " this command. Consider installing it with the 'install' function.") 2493 2494 if not self.run_name: 2495 MA5_opts = self.check_madanalysis5(args, mode=mode) 2496 self.configure_directory(html_opening =False) 2497 else: 2498 # initialize / remove lhapdf mode 2499 self.configure_directory(html_opening =False) 2500 MA5_opts = self.check_madanalysis5(args, mode=mode) 2501 2502 # Now check that there is at least one input to run 2503 if MA5_opts['inputs']==[]: 2504 if no_default: 2505 logger.warning('No hadron level input found to run MadAnalysis5 on.'+ 2506 ' Skipping its hadron-level analysis.') 2507 return 2508 else: 2509 raise self.InvalidCmd('\nNo input files specified or availabled for'+ 2510 ' this MadAnalysis5 hadron-level run.\nPlease double-check the options of this'+ 2511 ' MA5 command (or card) and which output files\nare currently in the chosen'+ 2512 " run directory '%s'."%self.run_name) 2513 2514 MA5_card = banner_mod.MadAnalysis5Card(pjoin(self.me_dir, 'Cards', 2515 'madanalysis5_%s_card.dat'%mode), mode=mode) 2516 2517 if MA5_card._skip_analysis: 2518 logger.info('Madanalysis5 %s-level analysis was skipped following user request.'%mode) 2519 logger.info("To run the analysis, remove or comment the tag '%s skip_analysis' " 2520 %banner_mod.MadAnalysis5Card._MG5aMC_escape_tag+ 2521 "in\n '%s'."%pjoin(self.me_dir, 'Cards','madanalysis5_%s_card.dat'%mode)) 2522 return 2523 2524 MA5_cmds_list = MA5_card.get_MA5_cmds(MA5_opts['inputs'], 2525 pjoin(self.me_dir,'MA5_%s_ANALYSIS'%mode.upper()), 2526 run_dir_path = pjoin(self.me_dir,'Events', self.run_name), 2527 UFO_model_path=pjoin(self.me_dir,'bin','internal','ufomodel'), 2528 run_tag = self.run_tag) 2529 2530 # Here's how to print the MA5 commands generated by MG5aMC 2531 # for MA5_runtag, MA5_cmds in MA5_cmds_list: 2532 # misc.sprint('****************************************') 2533 # misc.sprint('* Commands for MA5 runtag %s:'%MA5_runtag) 2534 # misc.sprint('\n'+('\n'.join('* %s'%cmd for cmd in MA5_cmds))) 2535 # misc.sprint('****************************************') 2536 2537 self.update_status('\033[92mRunning MadAnalysis5 [arXiv:1206.1599]\033[0m', 2538 level='madanalysis5_%s'%mode) 2539 if mode=='hadron': 2540 logger.info('Hadron input files considered:') 2541 for input in MA5_opts['inputs']: 2542 logger.info(' --> %s'%input) 2543 elif mode=='parton': 2544 logger.info('Parton input file considered:') 2545 logger.info(' --> %s'%MA5_opts['inputs']) 2546 2547 # Obtain a main MA5 interpreter 2548 # Ideally we would like to do it all with a single interpreter 2549 # but we'd need a way to reset it for this. 2550 if MA5_opts['MA5_stdout_lvl']=='default': 2551 if MA5_card['stdout_lvl'] is None: 2552 MA5_lvl = self.options['stdout_level'] 2553 else: 2554 MA5_lvl = MA5_card['stdout_lvl'] 2555 else: 2556 MA5_lvl = MA5_opts['MA5_stdout_lvl'] 2557 2558 # Bypass initialization information 2559 MA5_interpreter = CommonRunCmd.get_MadAnalysis5_interpreter( 2560 self.options['mg5_path'], 2561 self.options['madanalysis5_path'], 2562 logstream=sys.stdout, 2563 loglevel=100, 2564 forced=True) 2565 2566 2567 # If failed to start MA5, then just leave 2568 if MA5_interpreter is None: 2569 return 2570 2571 # Make sure to only run over one analysis over each fifo. 2572 used_up_fifos = [] 2573 # Now loop over the different MA5_runs 2574 for MA5_runtag, MA5_cmds in MA5_cmds_list: 2575 2576 # Bypass the banner. 2577 MA5_interpreter.setLogLevel(100) 2578 # Make sure to properly initialize MA5 interpreter 2579 if mode=='hadron': 2580 MA5_interpreter.init_reco() 2581 else: 2582 MA5_interpreter.init_parton() 2583 MA5_interpreter.setLogLevel(MA5_lvl) 2584 2585 if MA5_runtag!='default': 2586 if MA5_runtag.startswith('_reco_'): 2587 logger.info("MadAnalysis5 now running the reconstruction '%s'..."% 2588 MA5_runtag[6:],'$MG:color:GREEN') 2589 elif MA5_runtag=='Recasting': 2590 logger.info("MadAnalysis5 now running the recasting...", 2591 '$MG:color:GREEN') 2592 else: 2593 logger.info("MadAnalysis5 now running the '%s' analysis..."% 2594 MA5_runtag,'$MG:color:GREEN') 2595 2596 2597 # Now the magic, let's call MA5 2598 if not CommonRunCmd.runMA5(MA5_interpreter, MA5_cmds, MA5_runtag, 2599 pjoin(self.me_dir,'Events',self.run_name,'%s_MA5_%s.log'%(self.run_tag,MA5_runtag))): 2600 # Unsuccessful MA5 run, we therefore stop here. 2601 return 2602 2603 if MA5_runtag.startswith('_reco_'): 2604 # When doing a reconstruction we must first link the event file 2605 # created with MA5 reconstruction and then directly proceed to the 2606 # next batch of instructions. There can be several output directory 2607 # if there were several input files. 2608 links_created=[] 2609 for i, input in enumerate(MA5_opts['inputs']): 2610 # Make sure it is not an lhco or root input, which would not 2611 # undergo any reconstruction of course. 2612 if not banner_mod.MadAnalysis5Card.events_can_be_reconstructed(input): 2613 continue 2614 2615 if input.endswith('.fifo'): 2616 if input in used_up_fifos: 2617 # Only run once on each fifo 2618 continue 2619 else: 2620 used_up_fifos.append(input) 2621 2622 reco_output = pjoin(self.me_dir, 2623 'MA5_%s_ANALYSIS%s_%d'%(mode.upper(),MA5_runtag,i+1)) 2624 # Look for either a root or .lhe.gz output 2625 reco_event_file = misc.glob('*.lhe.gz',pjoin(reco_output,'Output','_reco_events'))+\ 2626 misc.glob('*.root',pjoin(reco_output,'Output','_reco_events')) 2627 if len(reco_event_file)==0: 2628 raise MadGraph5Error, "MadAnalysis5 failed to produce the "+\ 2629 "reconstructed event file for reconstruction '%s'."%MA5_runtag[6:] 2630 reco_event_file = reco_event_file[0] 2631 # move the reconstruction output to the HTML directory 2632 shutil.move(reco_output,pjoin(self.me_dir,'HTML', 2633 self.run_name,'%s_MA5_%s_ANALYSIS%s_%d'% 2634 (self.run_tag,mode.upper(),MA5_runtag,i+1))) 2635 # link the reconstructed event file to the run directory 2636 links_created.append(os.path.basename(reco_event_file)) 2637 files.ln(pjoin(self.me_dir,'HTML',self.run_name, 2638 '%s_MA5_%s_ANALYSIS%s_%d'%(self.run_tag,mode.upper(), 2639 MA5_runtag,i+1),'Output','_reco_events',links_created[-1]), 2640 pjoin(self.me_dir,'Events',self.run_name)) 2641 2642 logger.info("MadAnalysis5 successfully completed the reconstruction "+ 2643 "'%s'. Links to the reconstructed event files are:"%MA5_runtag[6:]) 2644 for link in links_created: 2645 logger.info(' --> %s'%pjoin(self.me_dir,'Events',self.run_name,link)) 2646 continue 2647 2648 if MA5_runtag.upper()=='RECASTING': 2649 target = pjoin(self.me_dir,'MA5_%s_ANALYSIS_%s'\ 2650 %(mode.upper(),MA5_runtag),'Output','CLs_output_summary.dat') 2651 else: 2652 target = pjoin(self.me_dir,'MA5_%s_ANALYSIS_%s'\ 2653 %(mode.upper(),MA5_runtag),'PDF','main.pdf') 2654 if not os.path.isfile(target): 2655 raise MadGraph5Error, "MadAnalysis5 failed to produced "+\ 2656 "an output for the analysis '%s' in\n %s"%(MA5_runtag,target) 2657 2658 # Copy the PDF report or CLs in the Events/run directory. 2659 if MA5_runtag.upper()=='RECASTING': 2660 carboncopy_name = '%s_MA5_CLs.dat'%(self.run_tag) 2661 else: 2662 carboncopy_name = '%s_MA5_%s_analysis_%s.pdf'%( 2663 self.run_tag,mode,MA5_runtag) 2664 shutil.copy(target, pjoin(self.me_dir,'Events',self.run_name,carboncopy_name)) 2665 if MA5_runtag!='default': 2666 logger.info("MadAnalysis5 successfully completed the "+ 2667 "%s. Reported results are placed in:"%("analysis '%s'"%MA5_runtag 2668 if MA5_runtag.upper()!='RECASTING' else "recasting")) 2669 else: 2670 logger.info("MadAnalysis5 successfully completed the analysis."+ 2671 " Reported results are placed in:") 2672 logger.info(' --> %s'%pjoin(self.me_dir,'Events',self.run_name,carboncopy_name)) 2673 2674 # Copy the entire analysis in the HTML directory 2675 shutil.move(pjoin(self.me_dir,'MA5_%s_ANALYSIS_%s'\ 2676 %(mode.upper(),MA5_runtag)), pjoin(self.me_dir,'HTML',self.run_name, 2677 '%s_MA5_%s_ANALYSIS_%s'%(self.run_tag,mode.upper(),MA5_runtag))) 2678 2679 # Set the number of events and cross-section to the last one 2680 # (maybe do something smarter later) 2681 new_details={} 2682 for detail in ['nb_event','cross','error']: 2683 new_details[detail] = \ 2684 self.results[self.run_name].get_current_info()[detail] 2685 for detail in new_details: 2686 self.results.add_detail(detail,new_details[detail]) 2687 2688 self.update_status('Finished MA5 analyses.', level='madanalysis5_%s'%mode, 2689 makehtml=False) 2690 2691 #Update the banner 2692 self.banner.add(pjoin(self.me_dir, 'Cards', 2693 'madanalysis5_%s_card.dat'%mode)) 2694 banner_path = pjoin(self.me_dir,'Events', self.run_name, 2695 '%s_%s_banner.txt'%(self.run_name, self.run_tag)) 2696 self.banner.write(banner_path) 2697 2698 if not no_default: 2699 logger.info('Find more information about this run on the HTML local page') 2700 logger.info(' --> %s'%pjoin(self.me_dir,'index.html'))
2701 2702 ############################################################################ 2703 # End of MadAnalysis5 related function 2704 ############################################################################ 2705
2706 - def do_delphes(self, line):
2707 """ run delphes and make associate root file/plot """ 2708 2709 args = self.split_arg(line) 2710 # Check argument's validity 2711 if '--no_default' in args: 2712 no_default = True 2713 args.remove('--no_default') 2714 else: 2715 no_default = False 2716 2717 if no_default and not os.path.exists(pjoin(self.me_dir, 'Cards', 'delphes_card.dat')): 2718 logger.info('No delphes_card detected, so not run Delphes') 2719 return 2720 2721 # Check all arguments 2722 filepath = self.check_delphes(args, nodefault=no_default) 2723 if no_default and not filepath: 2724 return # no output file but nothing to do either. 2725 2726 self.update_status('prepare delphes run', level=None) 2727 2728 if os.path.exists(pjoin(self.options['delphes_path'], 'data')): 2729 delphes3 = False 2730 prog = '../bin/internal/run_delphes' 2731 if filepath and '.hepmc' in filepath[:-10]: 2732 raise self.InvalidCmd, 'delphes2 do not support hepmc' 2733 else: 2734 delphes3 = True 2735 prog = '../bin/internal/run_delphes3' 2736 2737 # Check that the delphes_card exists. If not copy the default and 2738 # ask for edition of the card. 2739 if not os.path.exists(pjoin(self.me_dir, 'Cards', 'delphes_card.dat')): 2740 if no_default: 2741 logger.info('No delphes_card detected, so not running Delphes') 2742 return 2743 files.cp(pjoin(self.me_dir, 'Cards', 'delphes_card_default.dat'), 2744 pjoin(self.me_dir, 'Cards', 'delphes_card.dat')) 2745 logger.info('No delphes card found. Take the default one.') 2746 if not delphes3 and not os.path.exists(pjoin(self.me_dir, 'Cards', 'delphes_trigger.dat')): 2747 files.cp(pjoin(self.me_dir, 'Cards', 'delphes_trigger_default.dat'), 2748 pjoin(self.me_dir, 'Cards', 'delphes_trigger.dat')) 2749 if not (no_default or self.force): 2750 if delphes3: 2751 self.ask_edit_cards(['delphes_card.dat'], args) 2752 else: 2753 self.ask_edit_cards(['delphes_card.dat', 'delphes_trigger.dat'], args) 2754 2755 self.update_status('Running Delphes', level=None) 2756 2757 delphes_dir = self.options['delphes_path'] 2758 tag = self.run_tag 2759 if os.path.exists(pjoin(self.me_dir, 'Source', 'banner_header.txt')): 2760 self.banner.add(pjoin(self.me_dir, 'Cards','delphes_card.dat')) 2761 if not delphes3: 2762 self.banner.add(pjoin(self.me_dir, 'Cards','delphes_trigger.dat')) 2763 self.banner.write(pjoin(self.me_dir, 'Events', self.run_name, '%s_%s_banner.txt' % (self.run_name, tag))) 2764 2765 cross = self.results[self.run_name].get_current_info()['cross'] 2766 2767 delphes_log = pjoin(self.me_dir, 'Events', self.run_name, "%s_delphes.log" % tag) 2768 self.cluster.launch_and_wait(prog, 2769 argument= [delphes_dir, self.run_name, tag, str(cross), filepath], 2770 stdout=delphes_log, stderr=subprocess.STDOUT, 2771 cwd=pjoin(self.me_dir,'Events')) 2772 2773 if not os.path.exists(pjoin(self.me_dir, 'Events', 2774 self.run_name, '%s_delphes_events.lhco.gz' % tag))\ 2775 and not os.path.exists(pjoin(self.me_dir, 'Events', 2776 self.run_name, '%s_delphes_events.lhco' % tag)): 2777 logger.info('If you are interested in lhco output. please run root2lhco converter.') 2778 logger.info(' or edit bin/internal/run_delphes3 to run the converter automatically.') 2779 2780 2781 #eradir = self.options['exrootanalysis_path'] 2782 madir = self.options['madanalysis_path'] 2783 td = self.options['td_path'] 2784 2785 if os.path.exists(pjoin(self.me_dir, 'Events', 2786 self.run_name, '%s_delphes_events.lhco' % tag)): 2787 # Creating plots 2788 self.create_plot('Delphes') 2789 2790 if os.path.exists(pjoin(self.me_dir, 'Events', self.run_name, '%s_delphes_events.lhco' % tag)): 2791 misc.gzip(pjoin(self.me_dir, 'Events', self.run_name, '%s_delphes_events.lhco' % tag)) 2792 2793 self.update_status('delphes done', level='delphes', makehtml=False)
2794 2795 2796 ############################################################################
2797 - def get_pid_final_initial_states(self):
2798 """Find the pid of all particles in the final and initial states""" 2799 pids = set() 2800 subproc = [l.strip() for l in open(pjoin(self.me_dir,'SubProcesses', 2801 'subproc.mg'))] 2802 nb_init = self.ninitial 2803 pat = re.compile(r'''DATA \(IDUP\(I,\d+\),I=1,\d+\)/([\+\-\d,\s]*)/''', re.I) 2804 for Pdir in subproc: 2805 text = open(pjoin(self.me_dir, 'SubProcesses', Pdir, 'born_leshouche.inc')).read() 2806 group = pat.findall(text) 2807 for particles in group: 2808 particles = particles.split(',') 2809 pids.update(set(particles)) 2810 2811 return pids
2812 2813 ############################################################################
2814 - def get_pdf_input_filename(self):
2815 """return the name of the file which is used by the pdfset""" 2816 2817 if self.options["cluster_local_path"] and \ 2818 os.path.exists(self.options["cluster_local_path"]) and \ 2819 self.options['run_mode'] ==1: 2820 # no need to transfer the pdf. 2821 return '' 2822 2823 def check_cluster(path): 2824 if not self.options["cluster_local_path"] or \ 2825 os.path.exists(self.options["cluster_local_path"]) or\ 2826 self.options['run_mode'] !=1: 2827 return path 2828 main = self.options["cluster_local_path"] 2829 if os.path.isfile(path): 2830 filename = os.path.basename(path) 2831 possible_path = [pjoin(main, filename), 2832 pjoin(main, "lhadpf", filename), 2833 pjoin(main, "Pdfdata", filename)] 2834 if any(os.path.exists(p) for p in possible_path): 2835 return " " 2836 else: 2837 return path
2838 2839 2840 if hasattr(self, 'pdffile') and self.pdffile: 2841 return self.pdffile 2842 else: 2843 for line in open(pjoin(self.me_dir,'Source','PDF','pdf_list.txt')): 2844 data = line.split() 2845 if len(data) < 4: 2846 continue 2847 if data[1].lower() == self.run_card['pdlabel'].lower(): 2848 self.pdffile = check_cluster(pjoin(self.me_dir, 'lib', 'Pdfdata', data[2])) 2849 return self.pdffile 2850 else: 2851 # possible when using lhapdf 2852 path = pjoin(self.me_dir, 'lib', 'PDFsets') 2853 if os.path.exists(path): 2854 self.pdffile = path 2855 else: 2856 self.pdffile = " " 2857 return self.pdffile 2858 2859 ############################################################################
2860 - def do_open(self, line):
2861 """Open a text file/ eps file / html file""" 2862 2863 args = self.split_arg(line) 2864 # Check Argument validity and modify argument to be the real path 2865 self.check_open(args) 2866 file_path = args[0] 2867 2868 misc.open_file(file_path)
2869 2870 ############################################################################
2871 - def do_set(self, line, log=True):
2872 """Set an option, which will be default for coming generations/outputs 2873 """ 2874 # cmd calls automaticaly post_set after this command. 2875 2876 2877 args = self.split_arg(line) 2878 # Check the validity of the arguments 2879 self.check_set(args) 2880 # Check if we need to save this in the option file 2881 if args[0] in self.options_configuration and '--no_save' not in args: 2882 self.do_save('options --auto') 2883 2884 if args[0] == "stdout_level": 2885 if args[1].isdigit(): 2886 logging.root.setLevel(int(args[1])) 2887 logging.getLogger('madgraph').setLevel(int(args[1])) 2888 else: 2889 logging.root.setLevel(eval('logging.' + args[1])) 2890 logging.getLogger('madgraph').setLevel(eval('logging.' + args[1])) 2891 if log: logger.info('set output information to level: %s' % args[1]) 2892 elif args[0] == "fortran_compiler": 2893 if args[1] == 'None': 2894 args[1] = None 2895 self.options['fortran_compiler'] = args[1] 2896 current = misc.detect_current_compiler(pjoin(self.me_dir,'Source','make_opts'), 'fortran') 2897 if current != args[1] and args[1] != None: 2898 misc.mod_compilator(self.me_dir, args[1], current, 'gfortran') 2899 elif args[0] == "cpp_compiler": 2900 if args[1] == 'None': 2901 args[1] = None 2902 self.options['cpp_compiler'] = args[1] 2903 current = misc.detect_current_compiler(pjoin(self.me_dir,'Source','make_opts'), 'cpp') 2904 if current != args[1] and args[1] != None: 2905 misc.mod_compilator(self.me_dir, args[1], current, 'cpp') 2906 elif args[0] == "run_mode": 2907 if not args[1] in [0,1,2,'0','1','2']: 2908 raise self.InvalidCmd, 'run_mode should be 0, 1 or 2.' 2909 self.cluster_mode = int(args[1]) 2910 self.options['run_mode'] = self.cluster_mode 2911 elif args[0] in ['cluster_type', 'cluster_queue', 'cluster_temp_path']: 2912 if args[1] == 'None': 2913 args[1] = None 2914 self.options[args[0]] = args[1] 2915 # cluster (re)-initialization done later 2916 # self.cluster update at the end of the routine 2917 elif args[0] in ['cluster_nb_retry', 'cluster_retry_wait', 'cluster_size']: 2918 self.options[args[0]] = int(args[1]) 2919 # self.cluster update at the end of the routine 2920 elif args[0] == 'nb_core': 2921 if args[1] == 'None': 2922 import multiprocessing 2923 self.nb_core = multiprocessing.cpu_count() 2924 self.options['nb_core'] = self.nb_core 2925 return 2926 if not args[1].isdigit(): 2927 raise self.InvalidCmd('nb_core should be a positive number') 2928 self.nb_core = int(args[1]) 2929 self.options['nb_core'] = self.nb_core 2930 elif args[0] == 'timeout': 2931 self.options[args[0]] = int(args[1]) 2932 elif args[0] == 'cluster_status_update': 2933 if '(' in args[1]: 2934 data = ' '.join([a for a in args[1:] if not a.startswith('-')]) 2935 data = data.replace('(','').replace(')','').replace(',',' ').split() 2936 first, second = data[:2] 2937 else: 2938 first, second = args[1:3] 2939 2940 self.options[args[0]] = (int(first), int(second)) 2941 elif args[0] == 'notification_center': 2942 if args[1] in ['None','True','False']: 2943 self.allow_notification_center = eval(args[1]) 2944 self.options[args[0]] = eval(args[1]) 2945 else: 2946 raise self.InvalidCmd('Not a valid value for notification_center') 2947 elif args[0] in self.options: 2948 if args[1] in ['None','True','False']: 2949 self.options[args[0]] = ast.literal_eval(args[1]) 2950 elif args[0].endswith('path'): 2951 if os.path.exists(args[1]): 2952 self.options[args[0]] = args[1] 2953 elif os.path.exists(pjoin(self.me_dir, args[1])): 2954 self.options[args[0]] = pjoin(self.me_dir, args[1]) 2955 else: 2956 raise self.InvalidCmd('Not a valid path: keep previous value: \'%s\'' % self.options[args[0]]) 2957 else: 2958 self.options[args[0]] = args[1]
2959
2960 - def post_set(self, stop, line):
2961 """Check if we need to save this in the option file""" 2962 try: 2963 args = self.split_arg(line) 2964 if 'cluster' in args[0] or args[0] == 'run_mode': 2965 self.configure_run_mode(self.options['run_mode']) 2966 2967 2968 # Check the validity of the arguments 2969 self.check_set(args) 2970 2971 if args[0] in self.options_configuration and '--no_save' not in args: 2972 self.exec_cmd('save options --auto') 2973 elif args[0] in self.options_madevent: 2974 logger.info('This option will be the default in any output that you are going to create in this session.') 2975 logger.info('In order to keep this changes permanent please run \'save options\'') 2976 return stop 2977 except self.InvalidCmd: 2978 return stop
2979
2980 - def configure_run_mode(self, run_mode):
2981 """change the way to submit job 0: single core, 1: cluster, 2: multicore""" 2982 2983 self.cluster_mode = run_mode 2984 self.options['run_mode'] = run_mode 2985 2986 if run_mode == 2: 2987 if not self.options['nb_core']: 2988 import multiprocessing 2989 self.options['nb_core'] = multiprocessing.cpu_count() 2990 nb_core = self.options['nb_core'] 2991 elif run_mode == 0: 2992 nb_core = 1 2993 2994 2995 2996 if run_mode in [0, 2]: 2997 self.cluster = cluster.MultiCore( 2998 **self.options) 2999 self.cluster.nb_core = nb_core 3000 #cluster_temp_path=self.options['cluster_temp_path'], 3001 3002 if self.cluster_mode == 1: 3003 opt = self.options 3004 cluster_name = opt['cluster_type'] 3005 if cluster_name in cluster.from_name: 3006 self.cluster = cluster.from_name[cluster_name](**opt) 3007 else: 3008 if MADEVENT and ('mg5_path' not in self.options or not self.options['mg5_path']): 3009 if not self.plugin_path: 3010 raise self.InvalidCmd('%s not native cluster type and no PLUGIN directory available') 3011 elif MADEVENT: 3012 mg5dir = self.options['mg5_path'] 3013 if mg5dir not in sys.path: 3014 sys.path.append(mg5dir) 3015 newpath = pjoin(mg5dir, 'PLUGIN') 3016 if newpath not in self.plugin_path: 3017 self.plugin_path.append(newpath) 3018 else: 3019 mg5dir = MG5DIR 3020 # Check if a plugin define this type of cluster 3021 # check for PLUGIN format 3022 for plugpath in self.plugin_path: 3023 plugindirname = os.path.basename(plugpath) 3024 for plug in os.listdir(plugpath): 3025 if os.path.exists(pjoin(plugpath, plug, '__init__.py')): 3026 try: 3027 __import__('%s.%s' % (plugindirname,plug)) 3028 except Exception: 3029 logger.critical('plugin directory %s/%s fail to be loaded. Please check it', plugindirname, plug) 3030 continue 3031 plugin = sys.modules['%s.%s' % (plugindirname,plug)] 3032 if not hasattr(plugin, 'new_cluster'): 3033 continue 3034 if not misc.is_plugin_supported(plugin): 3035 continue 3036 if cluster_name in plugin.new_cluster: 3037 logger.info("cluster handling will be done with PLUGIN: %s" % plug,'$MG:color:BLACK') 3038 self.cluster = plugin.new_cluster[cluster_name](**opt) 3039 break 3040 else: 3041 continue 3042 break 3043 else: 3044 raise self.InvalidCmd, "%s is not recognized as a supported cluster format." % cluster_name
3045 3046
3047 - def check_param_card(self, path, run=True, dependent=False):
3048 """ 3049 1) Check that no scan parameter are present 3050 2) Check that all the width are define in the param_card. 3051 - If a scan parameter is define. create the iterator and recall this fonction 3052 on the first element. 3053 - If some width are set on 'Auto', call the computation tools. 3054 3) if dependent is on True check for dependent parameter (automatic for scan)""" 3055 3056 pattern_scan = re.compile(r'''^(decay)?[\s\d]*scan''', re.I+re.M) 3057 pattern_width = re.compile(r'''decay\s+(\+?\-?\d+)\s+auto(@NLO|)''',re.I) 3058 text = open(path).read() 3059 3060 if pattern_scan.search(text): 3061 if not isinstance(self, cmd.CmdShell): 3062 # we are in web mode => forbid scan due to security risk 3063 raise Exception, "Scan are not allowed in web mode" 3064 # at least one scan parameter found. create an iterator to go trough the cards 3065 main_card = check_param_card.ParamCardIterator(text) 3066 self.param_card_iterator = main_card 3067 first_card = main_card.next(autostart=True) 3068 first_card.write(path) 3069 return self.check_param_card(path, run, dependent=True) 3070 3071 pdg_info = pattern_width.findall(text) 3072 if pdg_info: 3073 if run: 3074 logger.info('Computing the width set on auto in the param_card.dat') 3075 has_nlo = any(nlo.lower()=="@nlo" for _,nlo in pdg_info) 3076 pdg = [pdg for pdg,nlo in pdg_info] 3077 if not has_nlo: 3078 self.do_compute_widths('%s %s' % (' '.join(pdg), path)) 3079 else: 3080 self.do_compute_widths('%s %s --nlo' % (' '.join(pdg), path)) 3081 else: 3082 logger.info('''Some width are on Auto in the card. 3083 Those will be computed as soon as you have finish the edition of the cards. 3084 If you want to force the computation right now and being able to re-edit 3085 the cards afterwards, you can type \"compute_wdiths\".''') 3086 3087 if dependent: 3088 card = check_param_card.ParamCard(path) 3089 AskforEditCard.update_dependent(self, self.me_dir, card, path, timer=20) 3090 3091 return
3092
3093 - def add_error_log_in_html(self, errortype=None):
3094 """If a ME run is currently running add a link in the html output""" 3095 3096 # Be very carefull to not raise any error here (the traceback 3097 #will be modify in that case.) 3098 if hasattr(self, 'results') and hasattr(self.results, 'current') and\ 3099 self.results.current and 'run_name' in self.results.current and \ 3100 hasattr(self, 'me_dir'): 3101 name = self.results.current['run_name'] 3102 tag = self.results.current['tag'] 3103 self.debug_output = pjoin(self.me_dir, '%s_%s_debug.log' % (name,tag)) 3104 if errortype: 3105 self.results.current.debug = errortype 3106 else: 3107 self.results.current.debug = self.debug_output 3108 3109 else: 3110 #Force class default 3111 self.debug_output = CommonRunCmd.debug_output 3112 if os.path.exists('ME5_debug') and not 'ME5_debug' in self.debug_output: 3113 os.remove('ME5_debug') 3114 if not 'ME5_debug' in self.debug_output: 3115 os.system('ln -s %s ME5_debug &> /dev/null' % self.debug_output)
3116 3117
3118 - def do_quit(self, line):
3119 """Not in help: exit """ 3120 3121 if not self.force_run: 3122 try: 3123 os.remove(pjoin(self.me_dir,'RunWeb')) 3124 except Exception: 3125 pass 3126 try: 3127 self.store_result() 3128 except Exception: 3129 # If nothing runs they they are no result to update 3130 pass 3131 3132 try: 3133 self.update_status('', level=None) 3134 except Exception, error: 3135 pass 3136 devnull = open(os.devnull, 'w') 3137 try: 3138 misc.call(['./bin/internal/gen_cardhtml-pl'], cwd=self.me_dir, 3139 stdout=devnull, stderr=devnull) 3140 except Exception: 3141 pass 3142 devnull.close() 3143 3144 return super(CommonRunCmd, self).do_quit(line)
3145 3146 # Aliases 3147 do_EOF = do_quit 3148 do_exit = do_quit 3149 3150
3151 - def update_status(self, status, level, makehtml=True, force=True, 3152 error=False, starttime = None, update_results=True, 3153 print_log=True):
3154 """ update the index status """ 3155 3156 if makehtml and not force: 3157 if hasattr(self, 'next_update') and time.time() < self.next_update: 3158 return 3159 else: 3160 self.next_update = time.time() + 3 3161 3162 if print_log: 3163 if isinstance(status, str): 3164 if '<br>' not in status: 3165 logger.info(status) 3166 elif starttime: 3167 running_time = misc.format_timer(time.time()-starttime) 3168 logger.info(' Idle: %s, Running: %s, Completed: %s [ %s ]' % \ 3169 (status[0], status[1], status[2], running_time)) 3170 else: 3171 logger.info(' Idle: %s, Running: %s, Completed: %s' % status[:3]) 3172 3173 if isinstance(status, str) and status.startswith('\x1b['): 3174 status = status[status.index('m')+1:-7] 3175 if 'arXiv' in status: 3176 if '[' in status: 3177 status = status.split('[',1)[0] 3178 else: 3179 status = status.split('arXiv',1)[0] 3180 3181 if update_results: 3182 self.results.update(status, level, makehtml=makehtml, error=error)
3183 3184 ############################################################################
3185 - def keep_cards(self, need_card=[], ignore=[]):
3186 """Ask the question when launching generate_events/multi_run""" 3187 3188 check_card = ['pythia_card.dat', 'pgs_card.dat','delphes_card.dat', 3189 'delphes_trigger.dat', 'madspin_card.dat', 'shower_card.dat', 3190 'reweight_card.dat','pythia8_card.dat', 3191 'madanalysis5_parton_card.dat','madanalysis5_hadron_card.dat', 3192 'plot_card.dat'] 3193 3194 cards_path = pjoin(self.me_dir,'Cards') 3195 for card in check_card: 3196 if card in ignore or (ignore == ['*'] and card not in need_card): 3197 continue 3198 if card not in need_card: 3199 if os.path.exists(pjoin(cards_path, card)): 3200 files.mv(pjoin(cards_path, card), pjoin(cards_path, '.%s' % card)) 3201 else: 3202 if not os.path.exists(pjoin(cards_path, card)): 3203 if os.path.exists(pjoin(cards_path, '.%s' % card)): 3204 files.mv(pjoin(cards_path, '.%s' % card), pjoin(cards_path, card)) 3205 else: 3206 default = card.replace('.dat', '_default.dat') 3207 files.cp(pjoin(cards_path, default),pjoin(cards_path, card))
3208 3209 ############################################################################
3210 - def set_configuration(self, config_path=None, final=True, initdir=None, amcatnlo=False):
3211 """ assign all configuration variable from file 3212 ./Cards/mg5_configuration.txt. assign to default if not define """ 3213 3214 if not hasattr(self, 'options') or not self.options: 3215 self.options = dict(self.options_configuration) 3216 self.options.update(self.options_madgraph) 3217 self.options.update(self.options_madevent) 3218 3219 if not config_path: 3220 if os.environ.has_key('MADGRAPH_BASE'): 3221 config_path = pjoin(os.environ['MADGRAPH_BASE'],'mg5_configuration.txt') 3222 self.set_configuration(config_path=config_path, final=False) 3223 if 'HOME' in os.environ: 3224 config_path = pjoin(os.environ['HOME'],'.mg5', 3225 'mg5_configuration.txt') 3226 if os.path.exists(config_path): 3227 self.set_configuration(config_path=config_path, final=False) 3228 if amcatnlo: 3229 me5_config = pjoin(self.me_dir, 'Cards', 'amcatnlo_configuration.txt') 3230 else: 3231 me5_config = pjoin(self.me_dir, 'Cards', 'me5_configuration.txt') 3232 self.set_configuration(config_path=me5_config, final=False, initdir=self.me_dir) 3233 3234 if self.options.has_key('mg5_path') and self.options['mg5_path']: 3235 MG5DIR = self.options['mg5_path'] 3236 config_file = pjoin(MG5DIR, 'input', 'mg5_configuration.txt') 3237 self.set_configuration(config_path=config_file, final=False,initdir=MG5DIR) 3238 else: 3239 self.options['mg5_path'] = None 3240 return self.set_configuration(config_path=me5_config, final=final,initdir=self.me_dir) 3241 3242 config_file = open(config_path) 3243 3244 # read the file and extract information 3245 logger.info('load configuration from %s ' % config_file.name) 3246 for line in config_file: 3247 3248 if '#' in line: 3249 line = line.split('#',1)[0] 3250 line = line.replace('\n','').replace('\r\n','') 3251 try: 3252 name, value = line.split('=') 3253 except ValueError: 3254 pass 3255 else: 3256 name = name.strip() 3257 value = value.strip() 3258 if name.endswith('_path') and not name.startswith('cluster'): 3259 path = value 3260 if os.path.isdir(path): 3261 self.options[name] = os.path.realpath(path) 3262 continue 3263 if not initdir: 3264 continue 3265 path = pjoin(initdir, value) 3266 if os.path.isdir(path): 3267 self.options[name] = os.path.realpath(path) 3268 continue 3269 else: 3270 self.options[name] = value 3271 if value.lower() == "none": 3272 self.options[name] = None 3273 3274 if not final: 3275 return self.options # the return is usefull for unittest 3276 3277 # Treat each expected input 3278 # delphes/pythia/... path 3279 for key in self.options: 3280 # Final cross check for the path 3281 if key.endswith('path') and not key.startswith("cluster"): 3282 path = self.options[key] 3283 if path is None: 3284 continue 3285 if os.path.isdir(path): 3286 self.options[key] = os.path.realpath(path) 3287 continue 3288 path = pjoin(self.me_dir, self.options[key]) 3289 if os.path.isdir(path): 3290 self.options[key] = os.path.realpath(path) 3291 continue 3292 elif self.options.has_key('mg5_path') and self.options['mg5_path']: 3293 path = pjoin(self.options['mg5_path'], self.options[key]) 3294 if os.path.isdir(path): 3295 self.options[key] = os.path.realpath(path) 3296 continue 3297 self.options[key] = None 3298 elif key.startswith('cluster') and key != 'cluster_status_update': 3299 if key in ('cluster_nb_retry','cluster_wait_retry'): 3300 self.options[key] = int(self.options[key]) 3301 if hasattr(self,'cluster'): 3302 del self.cluster 3303 pass 3304 elif key == 'automatic_html_opening': 3305 if self.options[key] in ['False', 'True']: 3306 self.options[key] =ast.literal_eval(self.options[key]) 3307 elif key == "notification_center": 3308 if self.options[key] in ['False', 'True']: 3309 self.allow_notification_center =ast.literal_eval(self.options[key]) 3310 self.options[key] =ast.literal_eval(self.options[key]) 3311 elif key not in ['text_editor','eps_viewer','web_browser','stdout_level', 3312 'complex_mass_scheme', 'gauge', 'group_subprocesses']: 3313 # Default: try to set parameter 3314 try: 3315 self.do_set("%s %s --no_save" % (key, self.options[key]), log=False) 3316 except self.InvalidCmd: 3317 logger.warning("Option %s from config file not understood" \ 3318 % key) 3319 3320 # Configure the way to open a file: 3321 misc.open_file.configure(self.options) 3322 self.configure_run_mode(self.options['run_mode']) 3323 return self.options
3324 3325 @staticmethod
3326 - def find_available_run_name(me_dir):
3327 """ find a valid run_name for the current job """ 3328 3329 name = 'run_%02d' 3330 data = [int(s[4:j]) for s in os.listdir(pjoin(me_dir,'Events')) for 3331 j in range(4,len(s)+1) if \ 3332 s.startswith('run_') and s[4:j].isdigit()] 3333 return name % (max(data+[0])+1)
3334 3335 3336 ############################################################################
3337 - def do_decay_events(self,line):
3338 """Require MG5 directory: decay events with spin correlations 3339 """ 3340 3341 if '-from_cards' in line and not os.path.exists(pjoin(self.me_dir, 'Cards', 'madspin_card.dat')): 3342 return 3343 3344 # First need to load MadSpin 3345 3346 # Check that MG5 directory is present . 3347 if MADEVENT and not self.options['mg5_path']: 3348 raise self.InvalidCmd, '''The module decay_events requires that MG5 is installed on the system. 3349 You can install it and set its path in ./Cards/me5_configuration.txt''' 3350 elif MADEVENT: 3351 sys.path.append(self.options['mg5_path']) 3352 try: 3353 import MadSpin.decay as decay 3354 import MadSpin.interface_madspin as interface_madspin 3355 except ImportError: 3356 if __debug__: 3357 raise 3358 else: 3359 raise self.ConfigurationError, '''Can\'t load MadSpin 3360 The variable mg5_path might not be correctly configured.''' 3361 3362 self.update_status('Running MadSpin', level='madspin') 3363 if not '-from_cards' in line: 3364 self.keep_cards(['madspin_card.dat'], ignore=['*']) 3365 self.ask_edit_cards(['madspin_card.dat'], 'fixed', plot=False) 3366 self.help_decay_events(skip_syntax=True) 3367 3368 # load the name of the event file 3369 args = self.split_arg(line) 3370 self.check_decay_events(args) 3371 # args now alway content the path to the valid files 3372 madspin_cmd = interface_madspin.MadSpinInterface(args[0]) 3373 madspin_cmd.update_status = lambda *x,**opt: self.update_status(*x, level='madspin',**opt) 3374 3375 path = pjoin(self.me_dir, 'Cards', 'madspin_card.dat') 3376 3377 madspin_cmd.import_command_file(path) 3378 3379 # create a new run_name directory for this output 3380 i = 1 3381 while os.path.exists(pjoin(self.me_dir,'Events', '%s_decayed_%i' % (self.run_name,i))): 3382 i+=1 3383 new_run = '%s_decayed_%i' % (self.run_name,i) 3384 evt_dir = pjoin(self.me_dir, 'Events') 3385 3386 os.mkdir(pjoin(evt_dir, new_run)) 3387 current_file = args[0].replace('.lhe', '_decayed.lhe') 3388 new_file = pjoin(evt_dir, new_run, os.path.basename(args[0])) 3389 if not os.path.exists(current_file): 3390 if os.path.exists(current_file+'.gz'): 3391 current_file += '.gz' 3392 new_file += '.gz' 3393 else: 3394 logger.error('MadSpin fails to create any decayed file.') 3395 return 3396 3397 files.mv(current_file, new_file) 3398 logger.info("The decayed event file has been moved to the following location: ") 3399 logger.info(new_file) 3400 3401 if hasattr(self, 'results'): 3402 current = self.results.current 3403 nb_event = self.results.current['nb_event'] 3404 if not nb_event: 3405 current = self.results[self.run_name][0] 3406 nb_event = current['nb_event'] 3407 3408 cross = current['cross'] 3409 error = current['error'] 3410 self.results.add_run( new_run, self.run_card) 3411 self.results.add_detail('nb_event', int(nb_event*madspin_cmd.efficiency)) 3412 self.results.add_detail('cross', madspin_cmd.cross)#cross * madspin_cmd.branching_ratio) 3413 self.results.add_detail('error', madspin_cmd.error+ cross * madspin_cmd.err_branching_ratio) 3414 self.results.add_detail('run_mode', current['run_mode']) 3415 3416 self.run_name = new_run 3417 self.banner = madspin_cmd.banner 3418 self.banner.add(path) 3419 self.banner.write(pjoin(self.me_dir,'Events',self.run_name, '%s_%s_banner.txt' % 3420 (self.run_name, self.run_tag))) 3421 self.update_status('MadSpin Done', level='parton', makehtml=False) 3422 if 'unweighted' in os.path.basename(args[0]): 3423 self.create_plot('parton')
3424
3425 - def complete_decay_events(self, text, line, begidx, endidx):
3426 args = self.split_arg(line[0:begidx], error=False) 3427 if len(args) == 1: 3428 return self.complete_plot(text, line, begidx, endidx) 3429 else: 3430 return
3431
3432 - def complete_print_results(self,text, line, begidx, endidx):
3433 "Complete the print results command" 3434 args = self.split_arg(line[0:begidx], error=False) 3435 if len(args) == 1: 3436 #return valid run_name 3437 data = misc.glob(pjoin('*','unweighted_events.lhe.gz'), 3438 pjoin(self.me_dir, 'Events')) 3439 3440 data = [n.rsplit('/',2)[1] for n in data] 3441 tmp1 = self.list_completion(text, data) 3442 return tmp1 3443 else: 3444 data = misc.glob('*_pythia_events.hep.gz', pjoin(self.me_dir, 'Events', args[0])) 3445 data = [os.path.basename(p).rsplit('_',1)[0] for p in data] 3446 data += ["--mode=a", "--mode=w", "--path=", "--format=short"] 3447 tmp1 = self.list_completion(text, data) 3448 return tmp1
3449
3450 - def help_print_result(self):
3451 logger.info("syntax: print_result [RUN] [TAG] [options]") 3452 logger.info("-- show in text format the status of the run (cross-section/nb-event/...)") 3453 logger.info("--path= defines the path of the output file.") 3454 logger.info("--mode=a allow to add the information at the end of the file.") 3455 logger.info("--format=short (only if --path is define)") 3456 logger.info(" allows to have a multi-column output easy to parse")
3457 3458 ############################################################################
3459 - def do_check_events(self, line):
3460 """ Run some sanity check on the generated events.""" 3461 3462 # Check that MG5 directory is present . 3463 if MADEVENT and not self.options['mg5_path']: 3464 raise self.InvalidCmd, '''The module reweight requires that MG5 is installed on the system. 3465 You can install it and set its path in ./Cards/me5_configuration.txt''' 3466 elif MADEVENT: 3467 sys.path.append(self.options['mg5_path']) 3468 try: 3469 import madgraph.interface.reweight_interface as reweight_interface 3470 except ImportError: 3471 raise self.ConfigurationError, '''Can\'t load Reweight module. 3472 The variable mg5_path might not be correctly configured.''' 3473 3474 3475 # load the name of the event file 3476 args = self.split_arg(line) 3477 self.check_check_events(args) 3478 # args now alway content the path to the valid files 3479 reweight_cmd = reweight_interface.ReweightInterface(args[0], allow_madspin=True) 3480 reweight_cmd.mother = self 3481 self.update_status('Running check on events', level='check') 3482 3483 reweight_cmd.check_events()
3484 3485 ############################################################################
3486 - def complete_check_events(self, text, line, begidx, endidx):
3487 args = self.split_arg(line[0:begidx], error=False) 3488 3489 if len(args) == 1 and os.path.sep not in text: 3490 #return valid run_name 3491 data = misc.glob(pjoin('*','*events.lhe*'), pjoin(self.me_dir, 'Events')) 3492 data = [n.rsplit('/',2)[1] for n in data] 3493 return self.list_completion(text, data, line) 3494 else: 3495 return self.path_completion(text, 3496 os.path.join('.',*[a for a in args \ 3497 if a.endswith(os.path.sep)]))
3498
3499 - def complete_reweight(self,text, line, begidx, endidx):
3500 "Complete the pythia command" 3501 args = self.split_arg(line[0:begidx], error=False) 3502 3503 #return valid run_name 3504 data = misc.glob(pjoin('*','*events.lhe*'), pjoin(self.me_dir, 'Events')) 3505 data = list(set([n.rsplit('/',2)[1] for n in data])) 3506 if not '-f' in args: 3507 data.append('-f') 3508 tmp1 = self.list_completion(text, data) 3509 return tmp1
3510 3511 3512
3513 - def complete_compute_widths(self, text, line, begidx, endidx, formatting=True):
3514 "Complete the compute_widths command" 3515 3516 args = self.split_arg(line[0:begidx]) 3517 3518 if args[-1] in ['--path=', '--output=']: 3519 completion = {'path': self.path_completion(text)} 3520 elif line[begidx-1] == os.path.sep: 3521 current_dir = pjoin(*[a for a in args if a.endswith(os.path.sep)]) 3522 if current_dir.startswith('--path='): 3523 current_dir = current_dir[7:] 3524 if current_dir.startswith('--output='): 3525 current_dir = current_dir[9:] 3526 completion = {'path': self.path_completion(text, current_dir)} 3527 else: 3528 completion = {} 3529 completion['options'] = self.list_completion(text, 3530 ['--path=', '--output=', '--min_br=0.\$', '--nlo', 3531 '--precision_channel=0.\$', '--body_decay=']) 3532 3533 return self.deal_multiple_categories(completion, formatting)
3534 3535
3536 - def update_make_opts(self):
3537 """update the make_opts file writing the environmental variables 3538 stored in make_opts_var""" 3539 make_opts = os.path.join(self.me_dir, 'Source', 'make_opts') 3540 3541 # Set some environment variables common to all interfaces 3542 if not hasattr(self,'options') or not 'pythia8_path' in self.options or \ 3543 not self.options['pythia8_path'] or \ 3544 not os.path.isfile(pjoin(self.options['pythia8_path'],'bin','pythia8-config')): 3545 self.make_opts_var['PYTHIA8_PATH']='NotInstalled' 3546 else: 3547 self.make_opts_var['PYTHIA8_PATH']=self.options['pythia8_path'] 3548 3549 self.make_opts_var['MG5AMC_VERSION'] = misc.get_pkg_info()['version'] 3550 3551 return self.update_make_opts_full(make_opts, self.make_opts_var)
3552 3553 @staticmethod
3554 - def update_make_opts_full(path, def_variables, keep_old=True):
3555 """update the make_opts file writing the environmental variables 3556 of def_variables. 3557 if a value of the dictionary is None then it is not written. 3558 """ 3559 make_opts = path 3560 pattern = re.compile(r'^(\w+)\s*=\s*(.*)$',re.DOTALL) 3561 diff = False # set to True if one varible need to be updated 3562 #if on False the file is not modify 3563 3564 tag = '#end_of_make_opts_variables\n' 3565 make_opts_variable = True # flag to say if we are in edition area or not 3566 content = [] 3567 variables = dict(def_variables) 3568 need_keys = variables.keys() 3569 for line in open(make_opts): 3570 line = line.strip() 3571 if make_opts_variable: 3572 if line.startswith('#') or not line: 3573 if line.startswith('#end_of_make_opts_variables'): 3574 make_opts_variable = False 3575 continue 3576 elif pattern.search(line): 3577 key, value = pattern.search(line).groups() 3578 if key not in variables: 3579 variables[key] = value 3580 elif value != variables[key]: 3581 diff=True 3582 else: 3583 need_keys.remove(key) 3584 else: 3585 make_opts_variable = False 3586 content.append(line) 3587 else: 3588 content.append(line) 3589 3590 if need_keys: 3591 diff=True #This means that new definition are added to the file. 3592 3593 content_variables = '\n'.join('%s=%s' % (k,v) for k, v in variables.items() if v is not None) 3594 content_variables += '\n%s' % tag 3595 3596 if diff: 3597 with open(make_opts, 'w') as fsock: 3598 fsock.write(content_variables + '\n'.join(content)) 3599 return
3600 3601 3602 # lhapdf-related functions 3631 3632
3633 - def get_characteristics(self, path=None):
3634 """reads the proc_characteristics file and initialises the correspondant 3635 dictionary""" 3636 3637 if not path: 3638 path = os.path.join(self.me_dir, 'SubProcesses', 'proc_characteristics') 3639 3640 self.proc_characteristics = banner_mod.ProcCharacteristic(path) 3641 return self.proc_characteristics
3642 3643
3644 - def copy_lhapdf_set(self, lhaid_list, pdfsets_dir):
3645 """copy (if needed) the lhapdf set corresponding to the lhaid in lhaid_list 3646 into lib/PDFsets""" 3647 3648 if not hasattr(self, 'lhapdf_pdfsets'): 3649 self.lhapdf_pdfsets = self.get_lhapdf_pdfsets_list(pdfsets_dir) 3650 3651 pdfsetname=set() 3652 for lhaid in lhaid_list: 3653 if isinstance(lhaid, str) and lhaid.isdigit(): 3654 lhaid = int(lhaid) 3655 if isinstance(lhaid, (int,float)): 3656 try: 3657 if lhaid in self.lhapdf_pdfsets: 3658 pdfsetname.add(self.lhapdf_pdfsets[lhaid]['filename']) 3659 else: 3660 raise MadGraph5Error('lhaid %s not valid input number for the current lhapdf' % lhaid ) 3661 except KeyError: 3662 if self.lhapdf_version.startswith('5'): 3663 raise MadGraph5Error(\ 3664 ('invalid lhaid set in th run_card: %d .\nPlease note that some sets' % lhaid) + \ 3665 '(eg MSTW 90%CL error sets) \nare not available in aMC@NLO + LHAPDF 5.x.x') 3666 else: 3667 logger.debug('%d not found in pdfsets.index' % lhaid) 3668 else: 3669 pdfsetname.add(lhaid) 3670 3671 # check if the file exists, otherwise install it: 3672 # also check that the PDFsets dir exists, otherwise create it. 3673 # if fails, install the lhapdfset into lib/PDFsets 3674 if not os.path.isdir(pdfsets_dir): 3675 try: 3676 os.mkdir(pdfsets_dir) 3677 except OSError: 3678 pdfsets_dir = pjoin(self.me_dir, 'lib', 'PDFsets') 3679 elif os.path.exists(pjoin(self.me_dir, 'lib', 'PDFsets')): 3680 #clean previous set of pdf used 3681 for name in os.listdir(pjoin(self.me_dir, 'lib', 'PDFsets')): 3682 if name not in pdfsetname: 3683 try: 3684 if os.path.isdir(pjoin(self.me_dir, 'lib', 'PDFsets', name)): 3685 shutil.rmtree(pjoin(self.me_dir, 'lib', 'PDFsets', name)) 3686 else: 3687 os.remove(pjoin(self.me_dir, 'lib', 'PDFsets', name)) 3688 except Exception, error: 3689 logger.debug('%s', error) 3690 3691 if self.options["cluster_local_path"]: 3692 lhapdf_cluster_possibilities = [self.options["cluster_local_path"], 3693 pjoin(self.options["cluster_local_path"], "lhapdf"), 3694 pjoin(self.options["cluster_local_path"], "lhapdf", "pdfsets"), 3695 pjoin(self.options["cluster_local_path"], "..", "lhapdf"), 3696 pjoin(self.options["cluster_local_path"], "..", "lhapdf", "pdfsets"), 3697 pjoin(self.options["cluster_local_path"], "..", "lhapdf","pdfsets", "6.1") 3698 ] 3699 else: 3700 lhapdf_cluster_possibilities = [] 3701 3702 for pdfset in pdfsetname: 3703 # Check if we need to copy the pdf 3704 if self.options["cluster_local_path"] and self.options["run_mode"] == 1 and \ 3705 any((os.path.exists(pjoin(d, pdfset)) for d in lhapdf_cluster_possibilities)): 3706 3707 os.environ["LHAPATH"] = [d for d in lhapdf_cluster_possibilities if os.path.exists(pjoin(d, pdfset))][0] 3708 os.environ["CLUSTER_LHAPATH"] = os.environ["LHAPATH"] 3709 # no need to copy it 3710 if os.path.exists(pjoin(pdfsets_dir, pdfset)): 3711 try: 3712 if os.path.isdir(pjoin(pdfsets_dir, name)): 3713 shutil.rmtree(pjoin(pdfsets_dir, name)) 3714 else: 3715 os.remove(pjoin(pdfsets_dir, name)) 3716 except Exception, error: 3717 logger.debug('%s', error) 3718 3719 #check that the pdfset is not already there 3720 elif not os.path.exists(pjoin(self.me_dir, 'lib', 'PDFsets', pdfset)) and \ 3721 not os.path.isdir(pjoin(self.me_dir, 'lib', 'PDFsets', pdfset)): 3722 3723 if pdfset and not os.path.exists(pjoin(pdfsets_dir, pdfset)): 3724 self.install_lhapdf_pdfset(pdfsets_dir, pdfset) 3725 3726 if os.path.exists(pjoin(pdfsets_dir, pdfset)): 3727 files.cp(pjoin(pdfsets_dir, pdfset), pjoin(self.me_dir, 'lib', 'PDFsets')) 3728 elif os.path.exists(pjoin(os.path.dirname(pdfsets_dir), pdfset)): 3729 files.cp(pjoin(os.path.dirname(pdfsets_dir), pdfset), pjoin(self.me_dir, 'lib', 'PDFsets'))
3730
3731 - def install_lhapdf_pdfset(self, pdfsets_dir, filename):
3732 """idownloads and install the pdfset filename in the pdfsets_dir""" 3733 lhapdf_version = self.get_lhapdf_version() 3734 local_path = pjoin(self.me_dir, 'lib', 'PDFsets') 3735 return self.install_lhapdf_pdfset_static(self.options['lhapdf'], 3736 pdfsets_dir, filename, 3737 lhapdf_version=lhapdf_version, 3738 alternate_path=local_path)
3739 3740 3741 @staticmethod
3742 - def install_lhapdf_pdfset_static(lhapdf_config, pdfsets_dir, filename, 3743 lhapdf_version=None, alternate_path=None):
3744 """idownloads and install the pdfset filename in the pdfsets_dir. 3745 Version which can be used independently of the class. 3746 local path is used if the global installation fails. 3747 """ 3748 3749 if not lhapdf_version: 3750 lhapdf_version = subprocess.Popen([lhapdf_config, '--version'], 3751 stdout = subprocess.PIPE).stdout.read().strip() 3752 if not pdfsets_dir: 3753 pdfsets_dir = subprocess.Popen([lhapdf_config, '--datadir'], 3754 stdout = subprocess.PIPE).stdout.read().strip() 3755 3756 if isinstance(filename, int): 3757 pdf_info = CommonRunCmd.get_lhapdf_pdfsets_list_static(pdfsets_dir, lhapdf_version) 3758 filename = pdf_info[filename]['filename'] 3759 3760 if os.path.exists(pjoin(pdfsets_dir, filename)): 3761 logger.debug('%s is already present in %s', filename, pdfsets_dir) 3762 return 3763 3764 logger.info('Trying to download %s' % filename) 3765 3766 if lhapdf_version.startswith('5.'): 3767 3768 # use the lhapdf-getdata command, which is in the same path as 3769 # lhapdf-config 3770 getdata = lhapdf_config.replace('lhapdf-config', ('lhapdf-getdata')) 3771 misc.call([getdata, filename], cwd = pdfsets_dir) 3772 3773 elif lhapdf_version.startswith('6.'): 3774 # use the "lhapdf install xxx" command, which is in the same path as 3775 # lhapdf-config 3776 getdata = lhapdf_config.replace('lhapdf-config', ('lhapdf')) 3777 3778 misc.call([getdata, 'install', filename], cwd = pdfsets_dir) 3779 3780 else: 3781 raise MadGraph5Error('Not valid LHAPDF version: %s' % lhapdf_version) 3782 3783 # check taht the file has been installed in the global dir 3784 if os.path.exists(pjoin(pdfsets_dir, filename)) or \ 3785 os.path.isdir(pjoin(pdfsets_dir, filename)): 3786 logger.info('%s successfully downloaded and stored in %s' \ 3787 % (filename, pdfsets_dir)) 3788 #otherwise (if v5) save it locally 3789 elif lhapdf_version.startswith('5.'): 3790 logger.warning('Could not download %s into %s. Trying to save it locally' \ 3791 % (filename, pdfsets_dir)) 3792 CommonRunCmd.install_lhapdf_pdfset_static(lhapdf_config, alternate_path, filename, 3793 lhapdf_version=lhapdf_version) 3794 elif lhapdf_version.startswith('6.') and '.LHgrid' in filename: 3795 logger.info('Could not download %s: Try %s', filename, filename.replace('.LHgrid','')) 3796 return CommonRunCmd.install_lhapdf_pdfset_static(lhapdf_config, pdfsets_dir, 3797 filename.replace('.LHgrid',''), 3798 lhapdf_version, alternate_path) 3799 3800 else: 3801 raise MadGraph5Error, \ 3802 'Could not download %s into %s. Please try to install it manually.' \ 3803 % (filename, pdfsets_dir)
3804 3805 3806
3807 - def get_lhapdf_pdfsets_list(self, pdfsets_dir):
3808 """read the PDFsets.index file, which should be located in the same 3809 place as pdfsets_dir, and return a list of dictionaries with the information 3810 about each pdf set""" 3811 lhapdf_version = self.get_lhapdf_version() 3812 return self.get_lhapdf_pdfsets_list_static(pdfsets_dir, lhapdf_version)
3813 3814 @staticmethod
3815 - def get_lhapdf_pdfsets_list_static(pdfsets_dir, lhapdf_version):
3816 3817 if lhapdf_version.startswith('5.'): 3818 if os.path.exists('%s.index' % pdfsets_dir): 3819 indexfile = '%s.index' % pdfsets_dir 3820 else: 3821 raise MadGraph5Error, 'index of lhapdf file not found' 3822 pdfsets_lines = \ 3823 [l for l in open(indexfile).read().split('\n') if l.strip() and \ 3824 not '90cl' in l] 3825 lhapdf_pdfsets = dict( (int(l.split()[0]), {'lhaid': int(l.split()[0]), 3826 'pdflib_ntype': int(l.split()[1]), 3827 'pdflib_ngroup': int(l.split()[2]), 3828 'pdflib_nset': int(l.split()[3]), 3829 'filename': l.split()[4], 3830 'lhapdf_nmem': int(l.split()[5]), 3831 'q2min': float(l.split()[6]), 3832 'q2max': float(l.split()[7]), 3833 'xmin': float(l.split()[8]), 3834 'xmax': float(l.split()[9]), 3835 'description': l.split()[10]}) \ 3836 for l in pdfsets_lines) 3837 3838 elif lhapdf_version.startswith('6.'): 3839 pdfsets_lines = \ 3840 [l for l in open(pjoin(pdfsets_dir, 'pdfsets.index')).read().split('\n') if l.strip()] 3841 lhapdf_pdfsets = dict( (int(l.split()[0]), 3842 {'lhaid': int(l.split()[0]), 3843 'filename': l.split()[1]}) \ 3844 for l in pdfsets_lines) 3845 3846 else: 3847 raise MadGraph5Error('Not valid LHAPDF version: %s' % lhapdf_version) 3848 3849 return lhapdf_pdfsets
3850 3851
3852 - def get_lhapdf_version(self):
3853 """returns the lhapdf version number""" 3854 if not hasattr(self, 'lhapdfversion'): 3855 try: 3856 self.lhapdf_version = \ 3857 subprocess.Popen([self.options['lhapdf'], '--version'], 3858 stdout = subprocess.PIPE).stdout.read().strip() 3859 except OSError, error: 3860 if error.errno == 2: 3861 raise Exception, 'lhapdf executable (%s) is not found on your system. Please install it and/or indicate the path to the correct executable in input/mg5_configuration.txt' % self.options['lhapdf'] 3862 else: 3863 raise 3864 3865 # this will be removed once some issues in lhapdf6 will be fixed 3866 if self.lhapdf_version.startswith('6.0'): 3867 raise MadGraph5Error('LHAPDF 6.0.x not supported. Please use v6.1 or later') 3868 3869 return self.lhapdf_version
3870 3871
3872 - def get_lhapdf_pdfsetsdir(self):
3873 lhapdf_version = self.get_lhapdf_version() 3874 3875 # check if the LHAPDF_DATA_PATH variable is defined 3876 if 'LHAPDF_DATA_PATH' in os.environ.keys() and os.environ['LHAPDF_DATA_PATH']: 3877 datadir = os.environ['LHAPDF_DATA_PATH'] 3878 3879 elif lhapdf_version.startswith('5.'): 3880 datadir = subprocess.Popen([self.options['lhapdf'], '--pdfsets-path'], 3881 stdout = subprocess.PIPE).stdout.read().strip() 3882 3883 elif lhapdf_version.startswith('6.'): 3884 datadir = subprocess.Popen([self.options['lhapdf'], '--datadir'], 3885 stdout = subprocess.PIPE).stdout.read().strip() 3886 3887 return datadir
3888
3889 - def get_lhapdf_libdir(self):
3890 lhapdf_version = self.get_lhapdf_version() 3891 3892 if lhapdf_version.startswith('5.'): 3893 libdir = subprocess.Popen([self.options['lhapdf-config'], '--libdir'], 3894 stdout = subprocess.PIPE).stdout.read().strip() 3895 3896 elif lhapdf_version.startswith('6.'): 3897 libdir = subprocess.Popen([self.options['lhapdf'], '--libs'], 3898 stdout = subprocess.PIPE).stdout.read().strip() 3899 3900 return libdir
3901
3902 -class AskforEditCard(cmd.OneLinePathCompletion):
3903 """A class for asking a question where in addition you can have the 3904 set command define and modifying the param_card/run_card correctly""" 3905 3906 all_card_name = ['param_card', 'run_card', 'pythia_card', 'pythia8_card', 3907 'madweight_card', 'MadLoopParams', 'shower_card'] 3908 3909 special_shortcut = {'ebeam':([float],['run_card ebeam1 %(0)s', 'run_card ebeam2 %(0)s']), 3910 'lpp': ([int],['run_card lpp1 %(0)s', 'run_card lpp2 %(0)s' ]), 3911 'lhc': ([int],['run_card lpp1 1', 'run_card lpp2 1', 'run_card ebeam1 %(0)s*1000/2', 'run_card ebeam2 %(0)s*1000/2']), 3912 'lep': ([int],['run_card lpp1 0', 'run_card lpp2 0', 'run_card ebeam1 %(0)s/2', 'run_card ebeam2 %(0)s/2']), 3913 'ilc': ([int],['run_card lpp1 0', 'run_card lpp2 0', 'run_card ebeam1 %(0)s/2', 'run_card ebeam2 %(0)s/2']), 3914 'lcc': ([int],['run_card lpp1 1', 'run_card lpp2 1', 'run_card ebeam1 %(0)s*1000/2', 'run_card ebeam2 %(0)s*1000/2']), 3915 'fixed_scale': ([float],['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']), 3916 'simplepy8':([],['pythia8_card hadronlevel:all False', 3917 'pythia8_card partonlevel:mpi False', 3918 'pythia8_card BeamRemnants:primordialKT False', 3919 'pythia8_card PartonLevel:Remnants False', 3920 'pythia8_card Check:event False', 3921 'pythia8_card TimeShower:QEDshowerByQ False', 3922 'pythia8_card TimeShower:QEDshowerByL False', 3923 'pythia8_card SpaceShower:QEDshowerByQ False', 3924 'pythia8_card SpaceShower:QEDshowerByL False', 3925 'pythia8_card PartonLevel:FSRinResonances False', 3926 'pythia8_card ProcessLevel:resonanceDecays False', 3927 ]), 3928 'mpi':([bool],['pythia8_card partonlevel:mpi %(0)s']), 3929 'no_parton_cut':([],['run_card nocut T']) 3930 } 3931 3932 special_shortcut_help = { 3933 'ebeam' : 'syntax: set ebeam VALUE:\n This parameter sets the energy to both beam to the value in GeV', 3934 'lpp' : 'syntax: set ebeam VALUE:\n'+\ 3935 ' Set the type of beam to a given value for both beam\n'+\ 3936 ' 0 : means no PDF\n'+\ 3937 ' 1 : means proton PDF\n'+\ 3938 ' -1 : means antiproton PDF\n'+\ 3939 ' 2 : means PDF for elastic photon emited from a proton\n'+\ 3940 ' 3 : means PDF for elastic photon emited from an electron', 3941 'lhc' : 'syntax: set lhc VALUE:\n Set for a proton-proton collision with that given center of mass energy (in TeV)', 3942 'lep' : 'syntax: set lep VALUE:\n Set for a electron-positron collision with that given center of mass energy (in GeV)', 3943 'fixed_scale' : 'syntax: set fixed_scale VALUE:\n Set all scales to the give value (in GeV)', 3944 'simplepy8' : 'Turn off non-perturbative slow features of Pythia8.', 3945 'mpi' : 'syntax: set mpi value: allow to turn mpi in Pythia8 on/off' 3946 } 3947
3948 - def load_default(self):
3949 """ define all default variable. No load of card here. 3950 This allow to subclass this class and just change init and still have 3951 all variables defined.""" 3952 3953 self.me_dir = None 3954 self.param_card = None 3955 self.run_card = {} 3956 self.pname2block = {} 3957 self.conflict = [] 3958 self.restricted_value = {} 3959 self.mode = '' 3960 self.cards = [] 3961 self.run_set = [] 3962 self.has_mw = False 3963 self.has_ml = False 3964 self.has_shower = False 3965 self.has_PY8 = False 3966 self.paths = {}
3967 3968
3969 - def define_paths(self, **opt):
3970 # Initiation 3971 if 'pwd' in opt: 3972 self.me_dir = opt['pwd'] 3973 elif 'mother_interface' in opt: 3974 self.mother_interface = opt['mother_interface'] 3975 if not hasattr(self, 'me_dir') or not self.me_dir: 3976 self.me_dir = self.mother_interface.me_dir 3977 3978 #define paths 3979 self.paths['param'] = pjoin(self.me_dir,'Cards','param_card.dat') 3980 self.paths['param_default'] = pjoin(self.me_dir,'Cards','param_card_default.dat') 3981 self.paths['run'] = pjoin(self.me_dir,'Cards','run_card.dat') 3982 self.paths['run_default'] = pjoin(self.me_dir,'Cards','run_card_default.dat') 3983 self.paths['transfer'] =pjoin(self.me_dir,'Cards','transfer_card.dat') 3984 self.paths['MadWeight'] =pjoin(self.me_dir,'Cards','MadWeight_card.dat') 3985 self.paths['MadWeight_default'] =pjoin(self.me_dir,'Cards','MadWeight_card_default.dat') 3986 self.paths['ML'] =pjoin(self.me_dir,'Cards','MadLoopParams.dat') 3987 self.paths['shower'] = pjoin(self.me_dir,'Cards','shower_card.dat') 3988 self.paths['shower_default'] = pjoin(self.me_dir,'Cards','shower_card_default.dat') 3989 self.paths['pythia'] =pjoin(self.me_dir, 'Cards','pythia_card.dat') 3990 self.paths['PY8'] = pjoin(self.me_dir, 'Cards','pythia8_card.dat') 3991 self.paths['PY8_default'] = pjoin(self.me_dir, 'Cards','pythia8_card_default.dat') 3992 self.paths['madspin_default'] = pjoin(self.me_dir,'Cards/madspin_card_default.dat') 3993 self.paths['madspin'] = pjoin(self.me_dir,'Cards/madspin_card.dat') 3994 self.paths['reweight'] = pjoin(self.me_dir,'Cards','reweight_card.dat') 3995 self.paths['delphes'] = pjoin(self.me_dir,'Cards','delphes_card.dat') 3996 self.paths['plot'] = pjoin(self.me_dir,'Cards','plot_card.dat') 3997 self.paths['plot_default'] = pjoin(self.me_dir,'Cards','plot_card_default.dat') 3998 self.paths['madanalysis5_parton'] = pjoin(self.me_dir,'Cards','madanalysis5_parton_card.dat') 3999 self.paths['madanalysis5_hadron'] = pjoin(self.me_dir,'Cards','madanalysis5_hadron_card.dat') 4000 self.paths['madanalysis5_parton_default'] = pjoin(self.me_dir,'Cards','madanalysis5_parton_card_default.dat') 4001 self.paths['madanalysis5_hadron_default'] = pjoin(self.me_dir,'Cards','madanalysis5_hadron_card_default.dat')
4002
4003 - def __init__(self, question, cards=[], mode='auto', *args, **opt):
4004 4005 self.load_default() 4006 self.define_paths(**opt) 4007 cmd.OneLinePathCompletion.__init__(self, question, *args, **opt) 4008 4009 4010 try: 4011 self.param_card = check_param_card.ParamCard(self.paths['param']) 4012 except (check_param_card.InvalidParamCard, ValueError) as e: 4013 logger.error('Current param_card is not valid. We are going to use the default one.') 4014 logger.error('problem detected: %s' % e) 4015 files.cp(self.paths['param_default'], self.paths['param']) 4016 self.param_card = check_param_card.ParamCard(self.paths['param']) 4017 default_param = check_param_card.ParamCard(self.paths['param_default']) 4018 self.param_card_default = default_param 4019 4020 try: 4021 self.run_card = banner_mod.RunCard(self.paths['run'], consistency='warning') 4022 except IOError: 4023 self.run_card = {} 4024 try: 4025 run_card_def = banner_mod.RunCard(self.paths['run_default']) 4026 except IOError: 4027 run_card_def = {} 4028 4029 self.pname2block = {} 4030 self.conflict = [] 4031 self.restricted_value = {} 4032 self.mode = mode 4033 self.cards = cards 4034 4035 # Read the comment of the param_card_default to find name variable for 4036 # the param_card also check which value seems to be constrained in the 4037 # model. 4038 self.pname2block, self.restricted_value = \ 4039 default_param.analyze_param_card() 4040 4041 if run_card_def: 4042 self.run_set = run_card_def.keys() + self.run_card.hidden_param 4043 elif self.run_card: 4044 self.run_set = self.run_card.keys() 4045 else: 4046 self.run_set = [] 4047 # check for conflict with run_card 4048 for var in self.pname2block: 4049 if var in self.run_set: 4050 self.conflict.append(var) 4051 4052 4053 self.has_delphes = False 4054 if 'delphes_card.dat' in cards: 4055 self.has_delphes = True 4056 4057 #check if Madweight_card is present: 4058 self.has_mw = False 4059 if 'madweight_card.dat' in cards: 4060 4061 self.do_change_tf = self.mother_interface.do_define_transfer_fct 4062 self.complete_change_tf = self.mother_interface.complete_define_transfer_fct 4063 self.help_change_tf = self.mother_interface.help_define_transfer_fct 4064 if not os.path.exists(self.paths['transfer']): 4065 logger.warning('No transfer function currently define. Please use the change_tf command to define one.') 4066 4067 4068 self.has_mw = True 4069 try: 4070 import madgraph.madweight.Cards as mwcards 4071 except: 4072 import internal.madweight.Cards as mwcards 4073 self.mw_card = mwcards.Card(self.paths['MadWeight']) 4074 self.mw_card = self.mw_card.info 4075 self.mw_vars = [] 4076 for key in self.mw_card: 4077 if key == 'comment': 4078 continue 4079 for key2 in self.mw_card.info[key]: 4080 if isinstance(key2, str) and not key2.isdigit(): 4081 self.mw_vars.append(key2) 4082 4083 # check for conflict with run_card/param_card 4084 for var in self.pname2block: 4085 if var in self.mw_vars: 4086 self.conflict.append(var) 4087 for var in self.mw_vars: 4088 if var in self.run_card: 4089 self.conflict.append(var) 4090 4091 #check if MadLoopParams.dat is present: 4092 self.has_ml = False 4093 if os.path.isfile(self.paths['ML']): 4094 self.has_ml = True 4095 self.MLcard = banner_mod.MadLoopParam(self.paths['ML']) 4096 self.MLcardDefault = banner_mod.MadLoopParam() 4097 4098 self.ml_vars = [k.lower() for k in self.MLcard.keys()] 4099 # check for conflict 4100 for var in self.ml_vars: 4101 if var in self.run_card: 4102 self.conflict.append(var) 4103 if var in self.pname2block: 4104 self.conflict.append(var) 4105 if self.has_mw and var in self.mw_vars: 4106 self.conflict.append(var) 4107 4108 #check if shower_card is present: 4109 self.has_shower = False 4110 if 'shower_card.dat' in cards: 4111 self.has_shower = True 4112 try: 4113 import madgraph.various.shower_card as showercards 4114 except: 4115 import internal.shower_card as showercards 4116 self.shower_card = showercards.ShowerCard(self.paths['shower']) 4117 self.shower_vars = self.shower_card.keys() 4118 4119 # check for conflict with run_card/param_card 4120 for var in self.pname2block: 4121 if var in self.shower_vars: 4122 self.conflict.append(var) 4123 for var in self.shower_vars: 4124 if var in self.run_card: 4125 self.conflict.append(var) 4126 4127 #check if pythia8_card.dat is present: 4128 self.has_PY8 = False 4129 if 'pythia8_card.dat' in cards: 4130 self.has_PY8 = True 4131 self.PY8Card = banner_mod.PY8Card(self.paths['PY8']) 4132 self.PY8CardDefault = banner_mod.PY8Card() 4133 4134 self.py8_vars = [k.lower() for k in self.PY8Card.keys()] 4135 # check for conflict 4136 for var in self.py8_vars: 4137 if var in self.run_card: 4138 self.conflict.append(var) 4139 if var in self.pname2block: 4140 self.conflict.append(var) 4141 if self.has_mw and var in self.mw_vars: 4142 self.conflict.append(var) 4143 if self.has_ml and var in self.ml_vars: 4144 self.conflict.append(var)
4145
4146 - def do_help(self, line, conflict_raise=False, banner=True):
4147 # try: 4148 if banner: 4149 logger.info('*** HELP MESSAGE ***', '$MG:color:BLACK') 4150 4151 args = self.split_arg(line) 4152 # handle comand related help 4153 if len(args)==0 or (len(args) == 1 and hasattr(self, 'do_%s' % args[0])): 4154 out = cmd.BasicCmd.do_help(self, line) 4155 if len(args)==0: 4156 print 'Allowed Argument' 4157 print '================' 4158 print '\t'.join(self.allow_arg) 4159 print 4160 print 'Special shortcut: (type help <name>)' 4161 print '====================================' 4162 print ' syntax: set <name> <value>' 4163 print '\t'.join(self.special_shortcut) 4164 print 4165 if banner: 4166 logger.info('*** END HELP ***', '$MG:color:BLACK') 4167 return out 4168 # check for special shortcut. 4169 # special shortcut: 4170 if args[0] in self.special_shortcut: 4171 if args[0] in self.special_shortcut_help: 4172 print self.special_shortcut_help[args[0]] 4173 if banner: 4174 logger.info('*** END HELP ***', '$MG:color:BLACK') 4175 return 4176 4177 start = 0 4178 card = '' 4179 if args[0]+'_card' in self.all_card_name+ self.cards: 4180 args[0] += '_card' 4181 elif args[0]+'.dat' in self.all_card_name+ self.cards: 4182 args[0] += '.dat' 4183 elif args[0]+'_card.dat' in self.all_card_name+ self.cards: 4184 args[0] += '_card.dat' 4185 if args[0] in self.all_card_name + self.cards: 4186 start += 1 4187 card = args[0] 4188 if len(args) == 1: 4189 if args[0] == 'pythia8_card': 4190 args[0] = 'PY8Card' 4191 if args[0] == 'param_card': 4192 logger.info("Param_card information: ", '$MG:color:BLUE') 4193 print "File to define the various model parameter" 4194 logger.info("List of the Block defined:",'$MG:color:BLUE') 4195 print "\t".join(self.param_card.keys()) 4196 elif args[0].startswith('madanalysis5'): 4197 print 'This card allow to make plot with the madanalysis5 package' 4198 print 'An example card is provided. For more information about the ' 4199 print 'syntax please refer to: https://madanalysis.irmp.ucl.ac.be/' 4200 print 'or to the user manual [arXiv:1206.1599]' 4201 if args[0].startswith('madanalysis5_hadron'): 4202 print 4203 print 'This card also allow to make recasting analysis' 4204 print 'For more detail, see: arXiv:1407.3278' 4205 elif hasattr(self, args[0]): 4206 logger.info("%s information: " % args[0], '$MG:color:BLUE') 4207 print(eval('self.%s' % args[0]).__doc__) 4208 logger.info("List of parameter associated", '$MG:color:BLUE') 4209 print "\t".join(eval('self.%s' % args[0]).keys()) 4210 if banner: 4211 logger.info('*** END HELP ***', '$MG:color:BLACK') 4212 return 4213 4214 #### RUN CARD 4215 if args[start] in [l.lower() for l in self.run_card.keys()] and card in ['', 'run_card']: 4216 if args[start] not in self.run_set: 4217 args[start] = [l for l in self.run_set if l.lower() == args[start]][0] 4218 4219 if args[start] in self.conflict and not conflict_raise: 4220 conflict_raise = True 4221 logger.info('** AMBIGUOUS NAME: %s **', args[start], '$MG:color:BLACK') 4222 if card == '': 4223 logger.info('** If not explicitely speficy this parameter will modif the run_card file', '$MG:color:BLACK') 4224 4225 self.run_card.do_help(args[start]) 4226 ### PARAM_CARD WITH BLOCK NAME ----------------------------------------- 4227 elif (args[start] in self.param_card or args[start] == 'width') \ 4228 and card in ['','param_card']: 4229 if args[start] in self.conflict and not conflict_raise: 4230 conflict_raise = True 4231 logger.info('** AMBIGUOUS NAME: %s **', args[start], '$MG:color:BLACK') 4232 if card == '': 4233 logger.info('** If not explicitely speficy this parameter will modif the param_card file', '$MG:color:BLACK') 4234 4235 if args[start] == 'width': 4236 args[start] = 'decay' 4237 4238 if len(args) == start+1: 4239 self.param_card.do_help(args[start], tuple()) 4240 key = None 4241 elif args[start+1] in self.pname2block: 4242 all_var = self.pname2block[args[start+1]] 4243 key = None 4244 for bname, lhaid in all_var: 4245 if bname == args[start]: 4246 key = lhaid 4247 break 4248 else: 4249 logger.warning('%s is not part of block "%s" but "%s". please correct.' % 4250 (args[start+1], args[start], bname)) 4251 else: 4252 try: 4253 key = tuple([int(i) for i in args[start+1:]]) 4254 except ValueError: 4255 logger.warning('Failed to identify LHA information') 4256 return 4257 4258 if key in self.param_card[args[start]].param_dict: 4259 self.param_card.do_help(args[start], key, default=self.param_card_default) 4260 elif key: 4261 logger.warning('invalid information: %s not defined in the param_card' % (key,)) 4262 # PARAM_CARD NO BLOCK NAME --------------------------------------------- 4263 elif args[start] in self.pname2block and card in ['','param_card']: 4264 if args[start] in self.conflict and not conflict_raise: 4265 conflict_raise = True 4266 logger.info('** AMBIGUOUS NAME: %s **', args[start], '$MG:color:BLACK') 4267 if card == '': 4268 logger.info('** If not explicitely speficy this parameter will modif the param_card file', '$MG:color:BLACK') 4269 4270 all_var = self.pname2block[args[start]] 4271 for bname, lhaid in all_var: 4272 new_line = 'param_card %s %s %s' % (bname, 4273 ' '.join([ str(i) for i in lhaid]), ' '.join(args[start+1:])) 4274 self.do_help(new_line, conflict_raise=True, banner=False) 4275 4276 # MadLoop Parameter --------------------------------------------------- 4277 elif self.has_ml and args[start] in self.ml_vars \ 4278 and card in ['', 'MadLoop_card']: 4279 4280 if args[start] in self.conflict and not conflict_raise: 4281 conflict_raise = True 4282 logger.info('** AMBIGUOUS NAME: %s **', args[start], '$MG:color:BLACK') 4283 if card == '': 4284 logger.info('** If not explicitely speficy this parameter will modif the madloop_card file', '$MG:color:BLACK') 4285 4286 self.MLcard.do_help(args[start]) 4287 4288 # Pythia8 Parameter --------------------------------------------------- 4289 elif self.has_PY8 and args[start] in self.PY8Card: 4290 if args[start] in self.conflict and not conflict_raise: 4291 conflict_raise = True 4292 logger.info('** AMBIGUOUS NAME: %s **', args[start], '$MG:color:BLACK') 4293 if card == '': 4294 logger.info('** If not explicitely speficy this parameter will modif the pythia8_card file', '$MG:color:BLACK') 4295 4296 self.PY8Card.do_help(args[start]) 4297 elif card.startswith('madanalysis5'): 4298 print 'MA5' 4299 4300 4301 else: 4302 print "no help available" 4303 4304 if banner: 4305 logger.info('*** END HELP ***', '$MG:color:BLACK') 4306 #raw_input('press enter to quit the help') 4307 return
4308 # except Exception, error: 4309 # if __debug__: 4310 # import traceback 4311 # traceback.print_exc() 4312 # print error 4313
4314 - def complete_help(self, text, line, begidx, endidx):
4315 prev_timer = signal.alarm(0) # avoid timer if any 4316 if prev_timer: 4317 nb_back = len(line) 4318 self.stdout.write('\b'*nb_back + '[timer stopped]\n') 4319 self.stdout.write(line) 4320 self.stdout.flush() 4321 # try: 4322 possibilities = self.complete_set(text, line, begidx, endidx,formatting=False) 4323 if line[:begidx].strip() == 'help': 4324 possibilities['Defined command'] = cmd.BasicCmd.completenames(self, text, line)#, begidx, endidx) 4325 possibilities.update(self.complete_add(text, line, begidx, endidx,formatting=False)) 4326 return self.deal_multiple_categories(possibilities)
4327 # except Exception, error: 4328 # import traceback 4329 # traceback.print_exc() 4330 # print error 4331
4332 - def complete_update(self, text, line, begidx, endidx):
4333 prev_timer = signal.alarm(0) # avoid timer if any 4334 if prev_timer: 4335 nb_back = len(line) 4336 self.stdout.write('\b'*nb_back + '[timer stopped]\n') 4337 self.stdout.write(line) 4338 self.stdout.flush() 4339 4340 arg = line[:begidx].split() 4341 if len(arg) <=1: 4342 return self.list_completion(text, ['dependent', 'missing'], line)
4343 4344
4345 - def complete_set(self, text, line, begidx, endidx, formatting=True):
4346 """ Complete the set command""" 4347 4348 prev_timer = signal.alarm(0) # avoid timer if any 4349 if prev_timer: 4350 nb_back = len(line) 4351 self.stdout.write('\b'*nb_back + '[timer stopped]\n') 4352 self.stdout.write(line) 4353 self.stdout.flush() 4354 4355 possibilities = {} 4356 allowed = {} 4357 args = self.split_arg(line[0:begidx]) 4358 if args[-1] in ['Auto', 'default']: 4359 return 4360 if len(args) == 1: 4361 allowed = {'category':'', 'run_card':'', 'block':'all', 'param_card':'','shortcut':''} 4362 if self.has_mw: 4363 allowed['madweight_card'] = '' 4364 allowed['mw_block'] = 'all' 4365 if self.has_shower: 4366 allowed['shower_card'] = '' 4367 if self.has_ml: 4368 allowed['madloop_card'] = '' 4369 if self.has_PY8: 4370 allowed['pythia8_card'] = '' 4371 if self.has_delphes: 4372 allowed['delphes_card'] = '' 4373 4374 elif len(args) == 2: 4375 if args[1] == 'run_card': 4376 allowed = {'run_card':'default'} 4377 elif args[1] == 'param_card': 4378 allowed = {'block':'all', 'param_card':'default'} 4379 elif args[1] in self.param_card.keys(): 4380 allowed = {'block':args[1]} 4381 elif args[1] == 'width': 4382 allowed = {'block': 'decay'} 4383 elif args[1] == 'MadWeight_card': 4384 allowed = {'madweight_card':'default', 'mw_block': 'all'} 4385 elif args[1] == 'MadLoop_card': 4386 allowed = {'madloop_card':'default'} 4387 elif args[1] == 'pythia8_card': 4388 allowed = {'pythia8_card':'default'} 4389 elif self.has_mw and args[1] in self.mw_card.keys(): 4390 allowed = {'mw_block':args[1]} 4391 elif args[1] == 'shower_card': 4392 allowed = {'shower_card':'default'} 4393 elif args[1] == 'delphes_card': 4394 allowed = {'delphes_card':'default'} 4395 else: 4396 allowed = {'value':''} 4397 else: 4398 start = 1 4399 if args[1] in ['run_card', 'param_card', 'MadWeight_card', 'shower_card', 4400 'MadLoop_card','pythia8_card','delphes_card','plot_card', 4401 'madanalysis5_parton_card','madanalysis5_hadron_card']: 4402 start = 2 4403 if args[-1] in self.pname2block.keys(): 4404 allowed['value'] = 'default' 4405 elif args[start] in self.param_card.keys() or args[start] == 'width': 4406 if args[start] == 'width': 4407 args[start] = 'decay' 4408 4409 if args[start+1:]: 4410 allowed = {'block':(args[start], args[start+1:])} 4411 else: 4412 allowed = {'block':args[start]} 4413 elif self.has_mw and args[start] in self.mw_card.keys(): 4414 if args[start+1:]: 4415 allowed = {'mw_block':(args[start], args[start+1:])} 4416 else: 4417 allowed = {'mw_block':args[start]} 4418 #elif len(args) == start +1: 4419 # allowed['value'] = '' 4420 else: 4421 allowed['value'] = '' 4422 4423 if 'category' in allowed.keys(): 4424 categories = ['run_card', 'param_card'] 4425 if self.has_mw: 4426 categories.append('MadWeight_card') 4427 if self.has_shower: 4428 categories.append('shower_card') 4429 if self.has_ml: 4430 categories.append('MadLoop_card') 4431 if self.has_PY8: 4432 categories.append('pythia8_card') 4433 if self.has_delphes: 4434 categories.append('delphes_card') 4435 4436 possibilities['category of parameter (optional)'] = \ 4437 self.list_completion(text, categories) 4438 4439 if 'shortcut' in allowed.keys(): 4440 possibilities['special values'] = self.list_completion(text, self.special_shortcut.keys()+['qcut', 'showerkt']) 4441 4442 if 'run_card' in allowed.keys(): 4443 opts = self.run_set 4444 if allowed['run_card'] == 'default': 4445 opts.append('default') 4446 4447 possibilities['Run Card'] = self.list_completion(text, opts) 4448 4449 if 'param_card' in allowed.keys(): 4450 opts = self.pname2block.keys() 4451 if allowed['param_card'] == 'default': 4452 opts.append('default') 4453 possibilities['Param Card'] = self.list_completion(text, opts) 4454 4455 if 'madweight_card' in allowed.keys(): 4456 opts = self.mw_vars + [k for k in self.mw_card.keys() if k !='comment'] 4457 if allowed['madweight_card'] == 'default': 4458 opts.append('default') 4459 possibilities['MadWeight Card'] = self.list_completion(text, opts) 4460 4461 if 'madloop_card' in allowed.keys(): 4462 opts = self.ml_vars 4463 if allowed['madloop_card'] == 'default': 4464 opts.append('default') 4465 possibilities['MadLoop Parameter'] = self.list_completion(text, opts) 4466 4467 if 'pythia8_card' in allowed.keys(): 4468 opts = self.py8_vars 4469 if allowed['pythia8_card'] == 'default': 4470 opts.append('default') 4471 possibilities['Pythia8 Parameter'] = self.list_completion(text, opts) 4472 4473 if 'shower_card' in allowed.keys(): 4474 opts = self.shower_vars + [k for k in self.shower_card.keys() if k !='comment'] 4475 if allowed['shower_card'] == 'default': 4476 opts.append('default') 4477 possibilities['Shower Card'] = self.list_completion(text, opts) 4478 4479 if 'delphes_card' in allowed: 4480 if allowed['delphes_card'] == 'default': 4481 opts = ['default', 'atlas', 'cms'] 4482 possibilities['Delphes Card'] = self.list_completion(text, opts) 4483 4484 if 'value' in allowed.keys(): 4485 opts = ['default'] 4486 if 'decay' in args: 4487 opts.append('Auto') 4488 opts.append('Auto@NLO') 4489 elif args[-1] in self.pname2block and self.pname2block[args[-1]][0][0] == 'decay': 4490 opts.append('Auto') 4491 opts.append('Auto@NLO') 4492 possibilities['Special Value'] = self.list_completion(text, opts) 4493 4494 if 'block' in allowed.keys(): 4495 if allowed['block'] == 'all': 4496 allowed_block = [i for i in self.param_card.keys() if 'qnumbers' not in i] 4497 allowed_block.append('width') 4498 possibilities['Param Card Block' ] = \ 4499 self.list_completion(text, allowed_block) 4500 elif isinstance(allowed['block'], basestring): 4501 block = self.param_card[allowed['block']].param_dict 4502 ids = [str(i[0]) for i in block 4503 if (allowed['block'], i) not in self.restricted_value] 4504 possibilities['Param Card id' ] = self.list_completion(text, ids) 4505 varname = [name for name, all_var in self.pname2block.items() 4506 if any((bname == allowed['block'] 4507 for bname,lhaid in all_var))] 4508 possibilities['Param card variable'] = self.list_completion(text, 4509 varname) 4510 else: 4511 block = self.param_card[allowed['block'][0]].param_dict 4512 nb = len(allowed['block'][1]) 4513 ids = [str(i[nb]) for i in block if len(i) > nb and \ 4514 [str(a) for a in i[:nb]] == allowed['block'][1]] 4515 4516 if not ids: 4517 if tuple([int(i) for i in allowed['block'][1]]) in block: 4518 opts = ['default'] 4519 if allowed['block'][0] == 'decay': 4520 opts.append('Auto') 4521 opts.append('Auto@NLO') 4522 possibilities['Special value'] = self.list_completion(text, opts) 4523 possibilities['Param Card id' ] = self.list_completion(text, ids) 4524 4525 if 'mw_block' in allowed.keys(): 4526 if allowed['mw_block'] == 'all': 4527 allowed_block = [i for i in self.mw_card.keys() if 'comment' not in i] 4528 possibilities['MadWeight Block' ] = \ 4529 self.list_completion(text, allowed_block) 4530 elif isinstance(allowed['mw_block'], basestring): 4531 block = self.mw_card[allowed['mw_block']] 4532 ids = [str(i[0]) if isinstance(i, tuple) else str(i) for i in block] 4533 possibilities['MadWeight Card id' ] = self.list_completion(text, ids) 4534 else: 4535 block = self.mw_card[allowed['mw_block'][0]] 4536 nb = len(allowed['mw_block'][1]) 4537 ids = [str(i[nb]) for i in block if isinstance(i, tuple) and\ 4538 len(i) > nb and \ 4539 [str(a) for a in i[:nb]] == allowed['mw_block'][1]] 4540 4541 if not ids: 4542 if tuple([i for i in allowed['mw_block'][1]]) in block or \ 4543 allowed['mw_block'][1][0] in block.keys(): 4544 opts = ['default'] 4545 possibilities['Special value'] = self.list_completion(text, opts) 4546 possibilities['MadWeight Card id' ] = self.list_completion(text, ids) 4547 4548 return self.deal_multiple_categories(possibilities, formatting)
4549
4550 - def do_set(self, line):
4551 """ edit the value of one parameter in the card""" 4552 4553 4554 args = self.split_arg(line) 4555 if len(args) == 0: 4556 logger.warning("No argument. For help type 'help set'.") 4557 # fix some formatting problem 4558 if len(args)==1 and '=' in args[-1]: 4559 arg1, arg2 = args.pop(-1).split('=',1) 4560 args += [arg1, arg2] 4561 if '=' in args: 4562 args.remove('=') 4563 4564 args[:-1] = [ a.lower() for a in args[:-1]] 4565 # special shortcut: 4566 if args[0] in self.special_shortcut: 4567 targettypes , cmd = self.special_shortcut[args[0]] 4568 if len(args) != len(targettypes) +1: 4569 logger.warning('shortcut %s requires %s argument' % (args[0], len(targettypes))) 4570 if len(args) < len(targettypes) +1: 4571 return 4572 else: 4573 logger.warning('additional argument will be ignored') 4574 values ={} 4575 for i, argtype in enumerate(targettypes): 4576 try: 4577 values = {str(i): banner_mod.ConfigFile.format_variable(args[i+1], argtype, args[0])} 4578 except ValueError as e: 4579 logger.warning("Wrong argument: The entry #%s should be of type %s.", i+1, argtype) 4580 return 4581 #else: 4582 # logger.warning("too many argument for this command") 4583 # return 4584 for arg in cmd: 4585 try: 4586 text = arg % values 4587 except KeyError: 4588 logger.warning("This command requires one argument") 4589 return 4590 except Exception as e: 4591 logger.warning(str(e)) 4592 return 4593 else: 4594 self.do_set(arg % values) 4595 return 4596 4597 4598 start = 0 4599 if len(args) < 2: 4600 logger.warning('Invalid set command %s (need two arguments)' % line) 4601 return 4602 4603 # Special case for the qcut value 4604 if args[0].lower() == 'qcut': 4605 pythia_path = self.paths['pythia'] 4606 if os.path.exists(pythia_path): 4607 logger.info('add line QCUT = %s in pythia_card.dat' % args[1]) 4608 p_card = open(pythia_path,'r').read() 4609 p_card, n = re.subn('''^\s*QCUT\s*=\s*[\de\+\-\.]*\s*$''', 4610 ''' QCUT = %s ''' % args[1], \ 4611 p_card, flags=(re.M+re.I)) 4612 if n==0: 4613 p_card = '%s \n QCUT= %s' % (p_card, args[1]) 4614 with open(pythia_path, 'w') as fsock: 4615 fsock.write(p_card) 4616 return 4617 # Special case for the showerkt value 4618 if args[0].lower() == 'showerkt': 4619 pythia_path = self.paths['pythia'] 4620 if os.path.exists(pythia_path): 4621 logger.info('add line SHOWERKT = %s in pythia_card.dat' % args[1].upper()) 4622 p_card = open(pythia_path,'r').read() 4623 p_card, n = re.subn('''^\s*SHOWERKT\s*=\s*[default\de\+\-\.]*\s*$''', 4624 ''' SHOWERKT = %s ''' % args[1].upper(), \ 4625 p_card, flags=(re.M+re.I)) 4626 if n==0: 4627 p_card = '%s \n SHOWERKT= %s' % (p_card, args[1].upper()) 4628 with open(pythia_path, 'w') as fsock: 4629 fsock.write(p_card) 4630 return 4631 4632 card = '' #store which card need to be modify (for name conflict) 4633 if args[0] == 'madweight_card': 4634 if not self.mw_card: 4635 logger.warning('Invalid Command: No MadWeight card defined.') 4636 return 4637 args[0] = 'MadWeight_card' 4638 4639 if args[0] == 'shower_card': 4640 if not self.shower_card: 4641 logger.warning('Invalid Command: No Shower card defined.') 4642 return 4643 args[0] = 'shower_card' 4644 4645 if args[0] == "madloop_card": 4646 if not self.has_ml: 4647 logger.warning('Invalid Command: No MadLoopParam card defined.') 4648 return 4649 args[0] = 'MadLoop_card' 4650 4651 if args[0] == "pythia8_card": 4652 if not self.has_PY8: 4653 logger.warning('Invalid Command: No Pythia8 card defined.') 4654 return 4655 args[0] = 'pythia8_card' 4656 4657 if args[0] == 'delphes_card': 4658 if not self.has_delphes: 4659 logger.warning('Invalid Command: No Delphes card defined.') 4660 return 4661 if args[1] == 'atlas': 4662 logger.info("set default ATLAS configuration for Delphes", '$MG:color:BLACK') 4663 files.cp(pjoin(self.me_dir,'Cards', 'delphes_card_ATLAS.dat'), 4664 pjoin(self.me_dir,'Cards', 'delphes_card.dat')) 4665 return 4666 elif args[1] == 'cms': 4667 logger.info("set default CMS configuration for Delphes",'$MG:color:BLACK') 4668 files.cp(pjoin(self.me_dir,'Cards', 'delphes_card_CMS.dat'), 4669 pjoin(self.me_dir,'Cards', 'delphes_card.dat')) 4670 return 4671 4672 if args[0] in ['run_card', 'param_card', 'MadWeight_card', 'shower_card', 4673 'delphes_card','madanalysis5_hadron_card','madanalysis5_parton_card']: 4674 if args[1] == 'default': 4675 logger.info('replace %s by the default card' % args[0],'$MG:color:BLACK') 4676 files.cp(self.paths['%s_default' %args[0][:-5]], self.paths[args[0][:-5]]) 4677 if args[0] == 'param_card': 4678 self.param_card = check_param_card.ParamCard(self.paths['param']) 4679 elif args[0] == 'run_card': 4680 self.run_card = banner_mod.RunCard(self.paths['run']) 4681 elif args[0] == 'shower_card': 4682 self.shower_card = shower_card_mod.ShowerCard(self.paths['shower']) 4683 return 4684 else: 4685 card = args[0] 4686 start=1 4687 if len(args) < 3: 4688 logger.warning('Invalid set command: %s (not enough arguments)' % line) 4689 return 4690 4691 elif args[0] in ['MadLoop_card']: 4692 if args[1] == 'default': 4693 logger.info('replace MadLoopParams.dat by the default card','$MG:color:BLACK') 4694 self.MLcard = banner_mod.MadLoopParam(self.MLcardDefault) 4695 self.MLcard.write(self.paths['ML'], 4696 commentdefault=True) 4697 return 4698 else: 4699 card = args[0] 4700 start=1 4701 if len(args) < 3: 4702 logger.warning('Invalid set command: %s (not enough arguments)' % line) 4703 return 4704 elif args[0] in ['pythia8_card']: 4705 if args[1] == 'default': 4706 logger.info('replace pythia8_card.dat by the default card','$MG:color:BLACK') 4707 self.PY8Card = banner_mod.PY8Card(self.PY8CardDefault) 4708 self.PY8Card.write(pjoin(self.me_dir,'Cards','pythia8_card.dat'), 4709 pjoin(self.me_dir,'Cards','pythia8_card_default.dat'), 4710 print_only_visible=True) 4711 return 4712 else: 4713 card = args[0] 4714 start=1 4715 if len(args) < 3: 4716 logger.warning('Invalid set command: %s (not enough arguments)' % line) 4717 return 4718 elif args[0] in ['madspin_card']: 4719 if args[1] == 'default': 4720 logger.info('replace madspin_card.dat by the default card','$MG:color:BLACK') 4721 files.cp(self.paths['MS_default'], self.paths['madspin']) 4722 return 4723 else: 4724 logger.warning("""Command set not allowed for modifying the madspin_card. 4725 Check the command \"decay\" instead.""") 4726 return 4727 4728 #### RUN CARD 4729 if args[start] in [l.lower() for l in self.run_card.keys()] and card in ['', 'run_card']: 4730 if args[start] not in self.run_set: 4731 args[start] = [l for l in self.run_set if l.lower() == args[start]][0] 4732 4733 if args[start] in self.conflict and card == '': 4734 text = 'Ambiguous name (present in more than one card). Will assume it to be referred to run_card.\n' 4735 text += 'If this is not intended, please reset it in the run_card and specify the relevant card to \n' 4736 text += 'edit, in the format < set card parameter value >' 4737 logger.warning(text) 4738 4739 if args[start+1] == 'default': 4740 default = banner_mod.RunCard(self.paths['run_default']) 4741 if args[start] in default.keys(): 4742 self.setR(args[start],default[args[start]]) 4743 else: 4744 logger.info('remove information %s from the run_card' % args[start],'$MG:color:BLACK') 4745 del self.run_card[args[start]] 4746 else: 4747 if args[0].startswith('sys_') or \ 4748 args[0] in self.run_card.list_parameter or \ 4749 args[0] in self.run_card.dict_parameter: 4750 val = ' '.join(args[start+1:]) 4751 val = val.split('#')[0] 4752 else: 4753 val = args[start+1] 4754 self.setR(args[start], val) 4755 self.run_card.write(self.paths['run'], self.paths['run_default']) 4756 # special mode for set run_card nocut T (generated by set no_parton_cut 4757 elif card == 'run_card' and args[start] in ['nocut', 'no_cut']: 4758 logger.info("Going to remove all cuts from the run_card", '$MG:color:BLACK') 4759 self.run_card.remove_all_cut() 4760 self.run_card.write(self.paths['run'], self.paths['run_default']) 4761 ### PARAM_CARD WITH BLOCK NAME ----------------------------------------- 4762 elif (args[start] in self.param_card or args[start] == 'width') \ 4763 and card in ['','param_card']: 4764 #special treatment for scan 4765 if any(t.startswith('scan') for t in args): 4766 index = [i for i,t in enumerate(args) if t.startswith('scan')][0] 4767 args = args[:index] + [' '.join(args[index:])] 4768 4769 if args[start] in self.conflict and card == '': 4770 text = 'ambiguous name (present in more than one card). Please specify which card to edit' 4771 text += ' in the format < set card parameter value>' 4772 logger.warning(text) 4773 return 4774 4775 if args[start] == 'width': 4776 args[start] = 'decay' 4777 4778 if args[start+1] in self.pname2block: 4779 all_var = self.pname2block[args[start+1]] 4780 key = None 4781 for bname, lhaid in all_var: 4782 if bname == args[start]: 4783 key = lhaid 4784 break 4785 else: 4786 logger.warning('%s is not part of block "%s" but "%s". please correct.' % 4787 (args[start+1], args[start], bname)) 4788 return 4789 else: 4790 try: 4791 key = tuple([int(i) for i in args[start+1:-1]]) 4792 except ValueError: 4793 if args[start] == 'decay' and args[start+1:-1] == ['all']: 4794 for key in self.param_card[args[start]].param_dict: 4795 if (args[start], key) in self.restricted_value: 4796 continue 4797 else: 4798 self.setP(args[start], key, args[-1]) 4799 self.param_card.write(self.paths['param']) 4800 return 4801 logger.warning('invalid set command %s (failed to identify LHA information)' % line) 4802 return 4803 4804 if key in self.param_card[args[start]].param_dict: 4805 if (args[start], key) in self.restricted_value: 4806 text = "Note that this parameter seems to be ignore by MG.\n" 4807 text += "MG will use instead the expression: %s\n" % \ 4808 self.restricted_value[(args[start], key)] 4809 text += "You need to match this expression for external program (such pythia)." 4810 logger.warning(text) 4811 4812 if args[-1].lower() in ['default', 'auto', 'auto@nlo'] or args[-1].startswith('scan'): 4813 self.setP(args[start], key, args[-1]) 4814 else: 4815 try: 4816 value = float(args[-1]) 4817 except Exception: 4818 logger.warning('Invalid input: Expected number and not \'%s\'' \ 4819 % args[-1]) 4820 return 4821 self.setP(args[start], key, value) 4822 else: 4823 logger.warning('invalid set command %s' % line) 4824 return 4825 self.param_card.write(self.paths['param']) 4826 4827 # PARAM_CARD NO BLOCK NAME --------------------------------------------- 4828 elif args[start] in self.pname2block and card in ['','param_card']: 4829 if args[start] in self.conflict and card == '': 4830 text = 'ambiguous name (present in more than one card). Please specify which card to edit' 4831 text += ' in the format < set card parameter value>' 4832 logger.warning(text) 4833 return 4834 4835 all_var = self.pname2block[args[start]] 4836 for bname, lhaid in all_var: 4837 new_line = 'param_card %s %s %s' % (bname, 4838 ' '.join([ str(i) for i in lhaid]), ' '.join(args[start+1:])) 4839 self.do_set(new_line) 4840 if len(all_var) > 1: 4841 logger.warning('This variable correspond to more than one parameter in the param_card.') 4842 for bname, lhaid in all_var: 4843 logger.warning(' %s %s' % (bname, ' '.join([str(i) for i in lhaid]))) 4844 logger.warning('all listed variables have been modified') 4845 4846 # MadWeight_card with block name --------------------------------------- 4847 elif self.has_mw and (args[start] in self.mw_card and args[start] != 'comment') \ 4848 and card in ['','MadWeight_card']: 4849 4850 if args[start] in self.conflict and card == '': 4851 text = 'ambiguous name (present in more than one card). Please specify which card to edit' 4852 text += ' in the format < set card parameter value>' 4853 logger.warning(text) 4854 return 4855 4856 block = args[start] 4857 name = args[start+1] 4858 value = args[start+2:] 4859 self.setM(block, name, value) 4860 self.mw_card.write(self.paths['MadWeight']) 4861 4862 # MadWeight_card NO Block name ----------------------------------------- 4863 elif self.has_mw and args[start] in self.mw_vars \ 4864 and card in ['', 'MadWeight_card']: 4865 4866 if args[start] in self.conflict and card == '': 4867 text = 'ambiguous name (present in more than one card). Please specify which card to edit' 4868 text += ' in the format < set card parameter value>' 4869 logger.warning(text) 4870 return 4871 4872 block = [b for b, data in self.mw_card.items() if args[start] in data] 4873 if len(block) > 1: 4874 logger.warning('%s is define in more than one block: %s.Please specify.' 4875 % (args[start], ','.join(block))) 4876 return 4877 4878 block = block[0] 4879 name = args[start] 4880 value = args[start+1:] 4881 self.setM(block, name, value) 4882 self.mw_card.write(self.paths['MadWeight']) 4883 4884 # MadWeight_card New Block --------------------------------------------- 4885 elif self.has_mw and args[start].startswith('mw_') and len(args[start:]) == 3\ 4886 and card == 'MadWeight_card': 4887 block = args[start] 4888 name = args[start+1] 4889 value = args[start+2] 4890 self.setM(block, name, value) 4891 self.mw_card.write(self.paths['MadWeight']) 4892 4893 #### SHOWER CARD 4894 elif self.has_shower and args[start].lower() in [l.lower() for l in \ 4895 self.shower_card.keys()] and card in ['', 'shower_card']: 4896 if args[start] not in self.shower_card: 4897 args[start] = [l for l in self.shower_card if l.lower() == args[start].lower()][0] 4898 4899 if args[start] in self.conflict and card == '': 4900 text = 'ambiguous name (present in more than one card). Please specify which card to edit' 4901 text += ' in the format < set card parameter value>' 4902 logger.warning(text) 4903 return 4904 4905 if args[start+1].lower() == 'default': 4906 default = shower_card_mod.ShowerCard(self.paths['shower_default']) 4907 if args[start] in default.keys(): 4908 self.shower_card.set_param(args[start],default[args[start]], self.paths['shower']) 4909 else: 4910 logger.info('remove information %s from the shower_card' % args[start],'$MG:color:BLACK') 4911 del self.shower_card[args[start]] 4912 elif args[start+1].lower() in ['t','.true.','true']: 4913 self.shower_card.set_param(args[start],'.true.',self.paths['shower']) 4914 elif args[start+1].lower() in ['f','.false.','false']: 4915 self.shower_card.set_param(args[start],'.false.',self.paths['shower']) 4916 elif args[start] in ['analyse', 'extralibs', 'extrapaths', 'includepaths'] or\ 4917 args[start].startswith('dm_'): 4918 #case sensitive parameters 4919 args = line.split() 4920 args_str = ' '.join(str(a) for a in args[start+1:len(args)]) 4921 self.shower_card.set_param(args[start],args_str,pjoin(self.me_dir,'Cards','shower_card.dat')) 4922 else: 4923 args_str = ' '.join(str(a) for a in args[start+1:len(args)]) 4924 self.shower_card.set_param(args[start],args_str,self.paths['shower']) 4925 4926 # MadLoop Parameter --------------------------------------------------- 4927 elif self.has_ml and args[start] in self.ml_vars \ 4928 and card in ['', 'MadLoop_card']: 4929 4930 if args[start] in self.conflict and card == '': 4931 text = 'ambiguous name (present in more than one card). Please specify which card to edit' 4932 logger.warning(text) 4933 return 4934 4935 if args[start+1] == 'default': 4936 value = self.MLcardDefault[args[start]] 4937 default = True 4938 else: 4939 value = args[start+1] 4940 default = False 4941 self.setML(args[start], value, default=default) 4942 self.MLcard.write(self.paths['ML'], 4943 commentdefault=True) 4944 4945 # Pythia8 Parameter --------------------------------------------------- 4946 elif self.has_PY8 and (card == 'pythia8_card' or (card == '' and \ 4947 args[start] in self.PY8Card)): 4948 4949 if args[start] in self.conflict and card == '': 4950 text = 'ambiguous name (present in more than one card). Please specify which card to edit' 4951 logger.warning(text) 4952 return 4953 4954 if args[start+1] == 'default': 4955 value = self.PY8CardDefault[args[start]] 4956 default = True 4957 else: 4958 value = ' '.join(args[start+1:]) 4959 default = False 4960 self.setPY8(args[start], value, default=default) 4961 self.PY8Card.write(pjoin(self.me_dir,'Cards','pythia8_card.dat'), 4962 pjoin(self.me_dir,'Cards','pythia8_card_default.dat'), 4963 print_only_visible=True) 4964 4965 #INVALID -------------------------------------------------------------- 4966 else: 4967 logger.warning('invalid set command %s ' % line) 4968 arg = args[start].lower() 4969 if self.has_PY8: 4970 close_opts = [name for name in self.PY8Card if name.lower().startswith(arg[:3]) or arg in name.lower()] 4971 if close_opts: 4972 logger.info('Did you mean one of the following PY8 options:\n%s' % '\t'.join(close_opts)) 4973 if self.run_card: 4974 close_opts = [name for name in self.run_card if name.lower().startswith(arg[:3]) or arg in name.lower()] 4975 if close_opts: 4976 logger.info('Did you mean one of the following run_card options:\n%s' % '\t'.join(close_opts)) 4977 4978 return
4979
4980 - def setM(self, block, name, value):
4981 4982 if isinstance(value, list) and len(value) == 1: 4983 value = value[0] 4984 4985 if block not in self.mw_card: 4986 logger.warning('block %s was not present in the current MadWeight card. We are adding it' % block) 4987 self.mw_card[block] = {} 4988 elif name not in self.mw_card[block]: 4989 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') 4990 if value == 'default': 4991 import madgraph.madweight.Cards as mwcards 4992 mw_default = mwcards.Card(self.paths['MadWeight_default']) 4993 try: 4994 value = mw_default[block][name] 4995 except KeyError: 4996 logger.info('removing id "%s" from Block "%s" '% (name, block),'$MG:color:BLACK') 4997 if name in self.mw_card[block]: 4998 del self.mw_card[block][name] 4999 return 5000 if value: 5001 logger.info('modify madweight_card information BLOCK "%s" with id "%s" set to %s', 5002 block, name, value, '$MG:color:BLACK') 5003 else: 5004 logger.warning("Invalid command: No value. To set default value. Use \"default\" as value") 5005 return 5006 5007 self.mw_card[block][name] = value
5008
5009 - def setR(self, name, value):
5010 logger.info('modify parameter %s of the run_card.dat to %s' % (name, value),'$MG:color:BLACK') 5011 self.run_card.set(name, value, user=True)
5012
5013 - def setML(self, name, value, default=False):
5014 5015 try: 5016 self.MLcard.set(name, value, user=True) 5017 except Exception, error: 5018 logger.warning("Fail to change parameter. Please Retry. Reason: %s." % error) 5019 return 5020 logger.info('modify parameter %s of the MadLoopParam.dat to %s' % (name, value),'$MG:color:BLACK') 5021 if default and name.lower() in self.MLcard.user_set: 5022 self.MLcard.user_set.remove(name.lower())
5023
5024 - def setPY8(self, name, value, default=False):
5025 try: 5026 self.PY8Card.userSet(name, value) 5027 except Exception, error: 5028 logger.warning("Fail to change parameter. Please Retry. Reason: %s." % error) 5029 return 5030 logger.info('modify parameter %s of the pythia8_card.dat to %s' % (name, value), '$MG:color:BLACK') 5031 if default and name.lower() in self.PY8Card.user_set: 5032 self.PY8Card.user_set.remove(name.lower())
5033
5034 - def setP(self, block, lhaid, value):
5035 if isinstance(value, str): 5036 value = value.lower() 5037 if value == 'default': 5038 default = check_param_card.ParamCard(self.paths['param_default']) 5039 value = default[block].param_dict[lhaid].value 5040 5041 elif value in ['auto', 'auto@nlo']: 5042 if 'nlo' in value: 5043 value = 'Auto@NLO' 5044 else: 5045 value = 'Auto' 5046 if block != 'decay': 5047 logger.warning('Invalid input: \'Auto\' value only valid for DECAY') 5048 return 5049 elif value.startswith('scan'): 5050 if ':' not in value: 5051 logger.warning('Invalid input: \'scan\' mode requires a \':\' before the definition.') 5052 return 5053 tag = value.split(':')[0] 5054 tag = tag[4:].strip() 5055 if tag and not tag.isdigit(): 5056 logger.warning('Invalid input: scan tag need to be integer and not "%s"' % tag) 5057 return 5058 5059 5060 pass 5061 else: 5062 try: 5063 value = float(value) 5064 except ValueError: 5065 logger.warning('Invalid input: \'%s\' not valid intput.'% value) 5066 5067 logger.info('modify param_card information BLOCK %s with id %s set to %s' %\ 5068 (block, lhaid, value), '$MG:color:BLACK') 5069 self.param_card[block].param_dict[lhaid].value = value
5070
5071 - def check_card_consistency(self):
5072 """This is run on quitting the class. Apply here all the self-consistency 5073 rule that you want. Do the modification via the set command.""" 5074 5075 # if NLO reweighting is ON: ensure that we keep the rwgt information 5076 if 'reweight' in self.allow_arg and 'run' in self.allow_arg and \ 5077 isinstance(self.run_card,banner_mod.RunCardNLO) and \ 5078 not self.run_card['store_rwgt_info']: 5079 #check if a NLO reweighting is required 5080 re_pattern = re.compile(r'''^\s*change\s*mode\s* (LO\+NLO|LO|NLO)\s*(?:#|$)''', re.M+re.I) 5081 text = open(self.paths['reweight']).read() 5082 options = re_pattern.findall(text) 5083 if any(o in ['NLO', 'LO+NLO'] for o in options): 5084 logger.info('NLO reweighting is on ON. Automatically set store_rwgt_info to True', '$MG:color:BLACK' ) 5085 self.do_set('run_card store_rwgt_info True') 5086 5087 # if external computation for the systematics are asked then switch 5088 #automatically the book-keeping of the weight for NLO 5089 if 'run' in self.allow_arg and \ 5090 self.run_card['systematics_program'] == 'systematics' and \ 5091 isinstance(self.run_card,banner_mod.RunCardNLO) and \ 5092 not self.run_card['store_rwgt_info']: 5093 logger.warning('To be able to run systematics program, we set store_rwgt_info to True') 5094 self.do_set('run_card store_rwgt_info True') 5095 5096 # @LO if PY6 shower => event_norm on sum 5097 if 'pythia_card.dat' in self.cards: 5098 if self.run_card['event_norm'] != 'sum': 5099 logger.info('Pythia6 needs a specific normalisation of the events. We will change it accordingly.', '$MG:color:BLACK' ) 5100 self.do_set('run_card event_norm sum') 5101 # @LO if PY6 shower => event_norm on sum 5102 elif 'pythia8_card.dat' in self.cards: 5103 if self.run_card['event_norm'] == 'sum': 5104 logger.info('Pythia8 needs a specific normalisation of the events. We will change it accordingly.', '$MG:color:BLACK' ) 5105 self.do_set('run_card event_norm average') 5106 5107 # Check the extralibs flag. 5108 if self.has_shower and isinstance(self.run_card, banner_mod.RunCardNLO): 5109 modify_extralibs, modify_extrapaths = False,False 5110 extralibs = self.shower_card['extralibs'].split() 5111 extrapaths = self.shower_card['extrapaths'].split() 5112 # remove default stdhep/Fmcfio for recent shower 5113 if self.run_card['parton_shower'] in ['PYTHIA8', 'HERWIGPP', 'HW7']: 5114 if 'stdhep' in self.shower_card['extralibs']: 5115 extralibs.remove('stdhep') 5116 modify_extralibs = True 5117 if 'Fmcfio' in self.shower_card['extralibs']: 5118 extralibs.remove('Fmcfio') 5119 modify_extralibs = True 5120 if self.run_card['parton_shower'] == 'PYTHIA8': 5121 # First check sanity of PY8 5122 if not self.mother_interface.options['pythia8_path']: 5123 raise self.mother.InvalidCmd, 'Pythia8 is not correctly specified to MadGraph5_aMC@NLO' 5124 executable = pjoin(self.mother_interface.options['pythia8_path'], 'bin', 'pythia8-config') 5125 if not os.path.exists(executable): 5126 raise self.mother.InvalidCmd, 'Pythia8 is not correctly specified to MadGraph5_aMC@NLO' 5127 5128 # 2. take the compilation flag of PY8 from pythia8-config 5129 libs , paths = [], [] 5130 p = misc.subprocess.Popen([executable, '--libs'], stdout=subprocess.PIPE) 5131 stdout, _ = p. communicate() 5132 libs = [x[2:] for x in stdout.split() if x.startswith('-l') or paths.append(x[2:])] 5133 5134 # Add additional user-defined compilation flags 5135 p = misc.subprocess.Popen([executable, '--config'], stdout=subprocess.PIPE) 5136 stdout, _ = p. communicate() 5137 for lib in ['-ldl','-lstdc++','-lc++']: 5138 if lib in stdout: 5139 libs.append(lib[2:]) 5140 5141 # This precompiler flag is in principle useful for the analysis if it writes HEPMC 5142 # events, but there is unfortunately no way for now to specify it in the shower_card. 5143 supports_HEPMCHACK = '-DHEPMC2HACK' in stdout 5144 5145 #3. ensure that those flag are in the shower card 5146 for l in libs: 5147 if l not in extralibs: 5148 modify_extralibs = True 5149 extralibs.append(l) 5150 for L in paths: 5151 if L not in extrapaths: 5152 modify_extrapaths = True 5153 extrapaths.append(L) 5154 5155 # Apply the required modification 5156 if modify_extralibs: 5157 if extralibs: 5158 self.do_set('shower_card extralibs %s ' % ' '.join(extralibs)) 5159 else: 5160 self.do_set('shower_card extralibs None ') 5161 if modify_extrapaths: 5162 if extrapaths: 5163 self.do_set('shower_card extrapaths %s ' % ' '.join(extrapaths)) 5164 else: 5165 self.do_set('shower_card extrapaths None ')
5166
5167 - def reask(self, *args, **opt):
5168 5169 cmd.OneLinePathCompletion.reask(self,*args, **opt) 5170 if self.has_mw and not os.path.exists(pjoin(self.me_dir,'Cards','transfer_card.dat')): 5171 logger.warning('No transfer function currently define. Please use the change_tf command to define one.')
5172 5173 fail_due_to_format = 0 #parameter to avoid infinite loop
5174 - def postcmd(self, stop, line):
5175 ending_question = cmd.OneLinePathCompletion.postcmd(self,stop,line) 5176 5177 if ending_question: 5178 self.check_card_consistency() 5179 try: 5180 self.do_update('dependent', timer=20) 5181 except MadGraph5Error, error: 5182 if 'Missing block:' in str(error): 5183 self.fail_due_to_format +=1 5184 if self.fail_due_to_format == 10: 5185 missing, unknow = str(error).split('\n')[-2:] 5186 logger.warning("Invalid param_card:\n%s\n%s\n" % (missing, unknow)) 5187 logger.info("Type \"update missing\" to use default value.\n ", '$MG:color:BLACK') 5188 self.value = False # to avoid that entering a command stop the question 5189 return self.reask(True) 5190 else: 5191 raise 5192 5193 return ending_question
5194 5195 5196 5197 5198
5199 - def do_update(self, line, timer=0):
5200 """ syntax: update dependent: Change the mass/width of particles which are not free parameter for the model. 5201 update missing: add to the current param_card missing blocks/parameters.""" 5202 5203 args = self.split_arg(line) 5204 if len(args)==0: 5205 logger.warning('miss an argument (dependent or missing). Please retry') 5206 return 5207 5208 if args[0] == 'dependent': 5209 if not self.mother_interface: 5210 logger.warning('Failed to update dependent parameter. This might create trouble for external program (like MadSpin/shower/...)') 5211 5212 pattern_width = re.compile(r'''decay\s+(\+?\-?\d+)\s+auto(@NLO|)''',re.I) 5213 pattern_scan = re.compile(r'''^(decay)?[\s\d]*scan''', re.I+re.M) 5214 param_text= open(self.paths['param']).read() 5215 5216 if pattern_scan.search(param_text): 5217 #for block, key in self.restricted_value: 5218 # self.param_card[block].get(key).value = -9.999e-99 5219 # self.param_card.write(self.paths['param']) 5220 return 5221 elif pattern_width.search(param_text): 5222 self.do_compute_widths('') 5223 self.param_card = check_param_card.ParamCard(self.paths['param']) 5224 5225 # calling the routine doing the work 5226 self.update_dependent(self.mother_interface, self.me_dir, self.param_card, 5227 self.paths['param'], timer) 5228 5229 elif args[0] == 'missing': 5230 self.update_missing() 5231 return
5232 5233 5234 5235 @staticmethod
5236 - def update_dependent(mecmd, me_dir, param_card, path ,timer=0):
5237 """static method which can also be called from outside the class 5238 usefull in presence of scan. 5239 return if the param_card was updated or not 5240 """ 5241 logger.info('Update the dependent parameter of the param_card.dat') 5242 modify = True 5243 class TimeOutError(Exception): 5244 pass
5245 def handle_alarm(signum, frame): 5246 raise TimeOutError 5247 signal.signal(signal.SIGALRM, handle_alarm) 5248 if timer: 5249 signal.alarm(timer) 5250 log_level=30 5251 else: 5252 log_level=20 5253 # Try to load the model in the limited amount of time allowed 5254 try: 5255 model = mecmd.get_model() 5256 signal.alarm(0) 5257 except TimeOutError: 5258 logger.warning('The model takes too long to load so we bypass the updating of dependent parameter.\n'+\ 5259 'This might create trouble for external program (like MadSpin/shower/...)\n'+\ 5260 'The update can be forced without timer by typing \'update dependent\' at the time of the card edition') 5261 modify =False 5262 except Exception,error: 5263 logger.debug(str(error)) 5264 logger.warning('Failed to update dependent parameter. This might create trouble for external program (like MadSpin/shower/...)') 5265 signal.alarm(0) 5266 else: 5267 restrict_card = pjoin(me_dir,'Source','MODEL','param_card_rule.dat') 5268 if not os.path.exists(restrict_card): 5269 restrict_card = None 5270 #restrict_card = None 5271 if model: 5272 modify = param_card.update_dependent(model, restrict_card, log_level) 5273 if modify and path: 5274 param_card.write(path) 5275 else: 5276 logger.warning('missing MG5aMC code. Fail to update dependent parameter. This might create trouble for program like MadSpin/shower/...') 5277 5278 if log_level==20: 5279 logger.info('param_card up to date.') 5280 5281 return modify 5282 5283 5284
5285 - def update_missing(self):
5286 5287 def check_block(self, blockname): 5288 add_entry = 0 5289 if blockname.lower() not in self.param_card_default: 5290 logger.info('unknow block %s: block will be ignored', blockname) 5291 return add_entry 5292 block = self.param_card_default[blockname] 5293 for key in block.keys(): 5294 if key not in input_in_block: 5295 param = block.get(key) 5296 if blockname != 'decay': 5297 text.append('\t%s\t%s # %s\n' % (' \t'.join([`i` for i in param.lhacode]), param.value, param.comment)) 5298 else: 5299 text.append('DECAY \t%s\t%s # %s\n' % (' \t'.join([`i` for i in param.lhacode]), param.value, param.comment)) 5300 add_entry += 1 5301 if add_entry: 5302 text.append('\n') 5303 if add_entry: 5304 logger.info("Adding %s parameter(s) to block %s", add_entry, blockname) 5305 return add_entry
5306 5307 # Add to the current param_card all the missing input at default value 5308 current_block = '' 5309 input_in_block = set() 5310 defined_blocks = set() 5311 decay = set() 5312 text = [] 5313 add_entry = 0 5314 for line in open(self.paths['param']): 5315 5316 new_block = re.findall(r'^\s*(block|decay)\s*(\w*)', line, re.I) 5317 if new_block: 5318 new_block = new_block[0] 5319 defined_blocks.add(new_block[1].lower()) 5320 if current_block: 5321 add_entry += check_block(self, current_block) 5322 5323 current_block= new_block[1] 5324 input_in_block = set() 5325 if new_block[0].lower() == 'decay': 5326 decay.add((int(new_block[1]),)) 5327 current_block = '' 5328 if new_block[1].lower() == 'qnumbers': 5329 current_block = '' 5330 5331 text.append(line) 5332 if not current_block: 5333 continue 5334 5335 #normal line. 5336 #strip comment 5337 line = line.split('#',1)[0] 5338 split = line.split() 5339 if not split: 5340 continue 5341 else: 5342 try: 5343 lhacode = [int(i) for i in split[:-1]] 5344 except: 5345 continue 5346 input_in_block.add(tuple(lhacode)) 5347 5348 if current_block: 5349 add_entry += check_block(self, current_block) 5350 5351 # special check for missing block 5352 for block in self.param_card_default: 5353 5354 if block.startswith(('qnumbers', 'decay')): 5355 continue 5356 5357 if block not in defined_blocks: 5358 nb_entry = len(self.param_card_default[block]) 5359 logger.info("Block %s was missing. Adding the %s associated parameter(s)", block,nb_entry) 5360 add_entry += nb_entry 5361 text.append(str(self.param_card_default[block])) 5362 5363 # special check for the decay 5364 input_in_block = decay 5365 add_entry += check_block(self, 'decay') 5366 5367 if add_entry: 5368 logger.info('write new param_card with %s new parameter(s).', add_entry, '$MG:color:BLACK') 5369 open(self.paths['param'],'w').write(''.join(text)) 5370 self.reload_card(self.paths['param']) 5371 else: 5372 logger.info('No missing parameter detected.', '$MG:color:BLACK') 5373 5374
5375 - def check_answer_consistency(self):
5376 """function called if the code reads a file""" 5377 self.check_card_consistency() 5378 self.do_update('dependent', timer=20)
5379
5380 - def help_set(self):
5381 '''help message for set''' 5382 5383 logger.info('********************* HELP SET ***************************') 5384 logger.info("syntax: set [run_card|param_card|...] NAME [VALUE|default]") 5385 logger.info("syntax: set [param_card] BLOCK ID(s) [VALUE|default]") 5386 logger.info('') 5387 logger.info('-- Edit the param_card/run_card/... and replace the value of the') 5388 logger.info(' parameter by the value VALUE.') 5389 logger.info(' ') 5390 logger.info('-- Example:') 5391 logger.info(' set run_card ebeam1 4000') 5392 logger.info(' set ebeam2 4000') 5393 logger.info(' set lpp1 0') 5394 logger.info(' set ptj default') 5395 logger.info('') 5396 logger.info(' set param_card mass 6 175') 5397 logger.info(' set mass 25 125.3') 5398 logger.info(' set mass mh 125') 5399 logger.info(' set mh 125') 5400 logger.info(' set decay 25 0.004') 5401 logger.info(' set decay wh 0.004') 5402 logger.info(' set vmix 2 1 2.326612e-01') 5403 logger.info('') 5404 logger.info(' set param_card default #return all parameter to default') 5405 logger.info(' set run_card default') 5406 logger.info('********************* HELP SET ***************************')
5407 5408
5409 - def default(self, line):
5410 """Default action if line is not recognized""" 5411 5412 line = line.strip() 5413 args = line.split() 5414 if line == '' and self.default_value is not None: 5415 self.value = self.default_value 5416 # check if input is a file 5417 elif hasattr(self, 'do_%s' % args[0]): 5418 self.do_set(' '.join(args[1:])) 5419 elif os.path.isfile(line): 5420 self.copy_file(line) 5421 self.value = 'repeat' 5422 elif self.me_dir and os.path.exists(pjoin(self.me_dir, line)): 5423 self.copy_file(pjoin(self.me_dir,line)) 5424 self.value = 'repeat' 5425 elif line.strip() != '0' and line.strip() != 'done' and \ 5426 str(line) != 'EOF' and line.strip() in self.allow_arg: 5427 self.open_file(line) 5428 self.value = 'repeat' 5429 else: 5430 self.value = line 5431 5432 return line
5433
5434 - def do_decay(self, line):
5435 """edit the madspin_card to define the decay of the associate particle""" 5436 signal.alarm(0) # avoid timer if any 5437 path = self.paths['madspin'] 5438 5439 if 'madspin_card.dat' not in self.cards or not os.path.exists(path): 5440 logger.warning("Command decay not valid. Since MadSpin is not available.") 5441 return 5442 5443 if ">" not in line: 5444 logger.warning("invalid command for decay. Line ignored") 5445 return 5446 5447 if "-add" in line: 5448 # just to have to add the line to the end of the file 5449 particle = line.split('>')[0].strip() 5450 text = open(path).read() 5451 line = line.replace('--add', '').replace('-add','') 5452 logger.info("change madspin_card to add one decay to %s: %s" %(particle, line.strip()), '$MG:color:BLACK') 5453 5454 text = text.replace('launch', "\ndecay %s\nlaunch\n" % line,1) 5455 else: 5456 # Here we have to remove all the previous definition of the decay 5457 #first find the particle 5458 particle = line.split('>')[0].strip() 5459 logger.info("change madspin_card to define the decay of %s: %s" %(particle, line.strip()), '$MG:color:BLACK') 5460 particle = particle.replace('+','\+').replace('-','\-') 5461 decay_pattern = re.compile(r"^\s*decay\s+%s\s*>[\s\w+-~]*?$" % particle, re.I+re.M) 5462 text= open(path).read() 5463 text = decay_pattern.sub('', text) 5464 text = text.replace('launch', "\ndecay %s\nlaunch\n" % line,1) 5465 5466 with open(path,'w') as fsock: 5467 fsock.write(text)
5468 5469 5470
5471 - def do_compute_widths(self, line):
5472 signal.alarm(0) # avoid timer if any 5473 path = self.paths['param'] 5474 pattern = re.compile(r'''decay\s+(\+?\-?\d+)\s+auto(@NLO|)''',re.I) 5475 text = open(path).read() 5476 pdg_info = pattern.findall(text) 5477 has_nlo = any("@nlo"==nlo.lower() for _, nlo in pdg_info) 5478 pdg = [p for p,_ in pdg_info] 5479 5480 5481 line = '%s %s' % (line, ' '.join(pdg)) 5482 if not '--path' in line: 5483 line += ' --path=%s' % path 5484 if has_nlo: 5485 line += ' --nlo' 5486 5487 try: 5488 return self.mother_interface.do_compute_widths(line) 5489 except InvalidCmd, error: 5490 logger.error("Invalid command: %s " % error)
5491
5492 - def help_compute_widths(self):
5493 signal.alarm(0) # avoid timer if any 5494 return self.mother_interface.help_compute_widths()
5495
5496 - def help_decay(self):
5497 """help for command decay which modifies MadSpin_card""" 5498 5499 signal.alarm(0) # avoid timer if any 5500 print '--syntax: decay PROC [--add]' 5501 print ' ' 5502 print ' modify the madspin_card to modify the decay of the associate particle.' 5503 print ' and define it to PROC.' 5504 print ' if --add is present, just add a new decay for the associate particle.'
5505
5506 - def complete_compute_widths(self, *args, **opts):
5507 prev_timer = signal.alarm(0) # avoid timer if any 5508 if prev_timer: 5509 nb_back = len(line) 5510 self.stdout.write('\b'*nb_back + '[timer stopped]\n') 5511 self.stdout.write(line) 5512 self.stdout.flush() 5513 return self.mother_interface.complete_compute_widths(*args,**opts)
5514 5515
5516 - def help_add(self):
5517 """help for add command""" 5518 5519 logger.info('********************* HELP ADD ***************************') 5520 logger.info( '-- syntax: add pythia8_card NAME VALUE') 5521 logger.info( " add a definition of name in the pythia8_card with the given value") 5522 logger.info( " Do not work for the param_card" ) 5523 logger.info( '-- syntax: add filename [OPTION] line') 5524 logger.info( ' add the given LINE to the end of the associate file (all file supportedd).') 5525 logger.info( ' OPTION parameter allows to change the position where to write in the file') 5526 logger.info( ' --after_line=banner : write the line at the end of the banner') 5527 logger.info( ' --line_position=X : insert the line before line X (starts at 0)') 5528 logger.info( ' --after_line="<regular-expression>" write the line after the first line matching the regular expression') 5529 logger.info( ' --before_line="<regular-expression>" write the line before the first line matching the regular expression') 5530 logger.info( ' example: change reweight --after_line="^\s*change mode" change model heft') 5531 logger.info('********************* HELP ADD ***************************')
5532
5533 - def complete_add(self, text, line, begidx, endidx, formatting=True):
5534 """ auto-completion for add command""" 5535 5536 prev_timer = signal.alarm(0) # avoid timer if any 5537 if prev_timer: 5538 nb_back = len(line) 5539 self.stdout.write('\b'*nb_back + '[timer stopped]\n') 5540 self.stdout.write(line) 5541 self.stdout.flush() 5542 5543 split = line[:begidx].split() 5544 if len(split)==1: 5545 possibilities = {} 5546 cards = [c.rsplit('.',1)[0] for c in self.cards] 5547 possibilities['category of parameter (optional)'] = \ 5548 self.list_completion(text, cards) 5549 elif len(split) == 2: 5550 possibilities = {} 5551 options = ['--line_position=','--after_line=banner', '--after_line="','--before_line="'] 5552 possibilities['category of parameter (optional)'] = \ 5553 self.list_completion(text, options, line) 5554 else: 5555 return 5556 return self.deal_multiple_categories(possibilities, formatting)
5557
5558 - def do_add(self, line):
5559 """ syntax: add filename NAME VALUE 5560 syntax: add filename LINE""" 5561 5562 args = self.split_arg(line) 5563 if len(args) == 3 and args[0] in ['pythia8_card', 'pythia8_card.dat'] and self.has_PY8: 5564 name= args[1] 5565 value = args[2] 5566 self.PY8Card.userSet(name, value) 5567 self.PY8Card.write(pjoin(self.me_dir,'Cards','pythia8_card.dat'), 5568 pjoin(self.me_dir,'Cards','pythia8_card_default.dat'), 5569 print_only_visible=True) 5570 logger.info("add in the pythia8_card the parameter \"%s\" with value \"%s\"" % (name, value), '$MG:color:BLACK') 5571 elif len(args) > 0: 5572 if args[0] in self.cards: 5573 card = args[0] 5574 elif "%s.dat" % args[0] in self.cards: 5575 card = "%s.dat" % args[0] 5576 elif "%s_card.dat" % args[0] in self.cards: 5577 card = "%s_card.dat" % args[0] 5578 elif self.has_ml and args[0].lower() == "madloop": 5579 card = "MadLoopParams.dat" 5580 else: 5581 logger.error("unknow card %s. Please retry." % args[0]) 5582 return 5583 5584 # handling the various option on where to write the line 5585 if args[1].startswith('--line_position='): 5586 #position in file determined by user 5587 text = open(pjoin(self.me_dir,'Cards',card)).read() 5588 split = text.split('\n') 5589 pos = int(args[1].split('=',1)[1]) 5590 newline = line.split(None,2)[2] 5591 split.insert(pos, newline) 5592 ff = open(pjoin(self.me_dir,'Cards',card),'w') 5593 ff.write('\n'.join(split)) 5594 logger.info("writting at line %d of the file %s the line: \"%s\"" %(pos, card, line.split(None,1)[1] )) 5595 5596 elif args[1].startswith('--after_line=banner'): 5597 # write the line at the first not commented line 5598 text = open(pjoin(self.me_dir,'Cards',card)).read() 5599 split = text.split('\n') 5600 for posline,l in enumerate(split): 5601 if not l.startswith('#'): 5602 break 5603 split.insert(posline, line.split(None,2)[2]) 5604 ff = open(pjoin(self.me_dir,'Cards',card),'w') 5605 ff.write('\n'.join(split)) 5606 logger.info("writting at line %d of the file %s the line: \"%s\"" %(posline, card, line.split(None,1)[1] )) 5607 5608 elif args[1].startswith('--before_line='): 5609 # catch the line/regular expression and write before that line 5610 text = open(pjoin(self.me_dir,'Cards',card)).read() 5611 split = text.split('\n') 5612 search_pattern=r'''before_line=(?P<quote>["'])(?:(?=(\\?))\2.)*?\1''' 5613 pattern = re.search(search_pattern, line).group()[13:-1] 5614 for posline,l in enumerate(split): 5615 if re.search(pattern, l): 5616 break 5617 else: 5618 raise Exception, 'invalid regular expression: not found in file' 5619 split.insert(posline, re.split(search_pattern,line)[-1]) 5620 ff = open(pjoin(self.me_dir,'Cards',card),'w') 5621 ff.write('\n'.join(split)) 5622 logger.info("writting at line %d of the file %s the line: \"%s\"" %(posline, card, line.split(None,1)[1] )) 5623 5624 5625 5626 elif args[1].startswith('--after_line='): 5627 # catch the line/regular expression and write after that line 5628 text = open(pjoin(self.me_dir,'Cards',card)).read() 5629 split = text.split('\n') 5630 search_pattern = r'''after_line=(?P<quote>["'])(?:(?=(\\?))\2.)*?\1''' 5631 pattern = re.search(search_pattern, line).group()[12:-1] 5632 for posline,l in enumerate(split): 5633 if re.search(pattern, l): 5634 break 5635 else: 5636 posline=len(split) 5637 split.insert(posline+1, re.split(search_pattern,line)[-1]) 5638 ff = open(pjoin(self.me_dir,'Cards',card),'w') 5639 ff.write('\n'.join(split)) 5640 logger.info("writting at line %d of the file %s the line: \"%s\"" %(posline, card, line.split(None,1)[1] )) 5641 else: 5642 ff = open(pjoin(self.me_dir,'Cards',card),'a') 5643 ff.write("%s \n" % line.split(None,1)[1]) 5644 ff.close() 5645 logger.info("adding at the end of the file %s the line: \"%s\"" %(card, line.split(None,1)[1] )) 5646 self.reload_card(pjoin(self.me_dir,'Cards',card))
5647 5648 5649
5650 - def help_asperge(self):
5651 """Help associated to the asperge command""" 5652 signal.alarm(0) 5653 5654 print '-- syntax: asperge [options]' 5655 print ' Call ASperGe to diagonalize all mass matrices in the model.' 5656 print ' This works only if the ASperGE module is part of the UFO model (a subdirectory).' 5657 print ' If you specify some names after the command (i.e. asperge m1 m2) then ASperGe will only' 5658 print ' diagonalize the associate mass matrices (here m1 and m2).'
5659
5660 - def complete_asperge(self, text, line, begidx, endidx, formatting=True):
5661 prev_timer = signal.alarm(0) # avoid timer if any 5662 if prev_timer: 5663 nb_back = len(line) 5664 self.stdout.write('\b'*nb_back + '[timer stopped]\n') 5665 self.stdout.write(line) 5666 self.stdout.flush() 5667 blockname = self.pname2block.keys() 5668 # remove those that we know for sure are not mixing 5669 wrong = ['decay', 'mass', 'sminput'] 5670 valid = [k for k in blockname if 'mix' in k] 5671 potential = [k for k in blockname if k not in valid+wrong] 5672 output = {'Mixing matrices': self.list_completion(text, valid, line), 5673 'Other potential valid input': self.list_completion(text, potential, line)} 5674 5675 return self.deal_multiple_categories(output, formatting)
5676 5677
5678 - def do_asperge(self, line):
5679 """Running ASperGe""" 5680 signal.alarm(0) # avoid timer if any 5681 5682 path = pjoin(self.me_dir,'bin','internal','ufomodel','ASperGE') 5683 if not os.path.exists(path): 5684 logger.error('ASperge has not been detected in the current model, therefore it will not be run.') 5685 return 5686 elif not os.path.exists(pjoin(path,'ASperGe')): 5687 logger.info('ASperGe has been detected but is not compiled. Running the compilation now.') 5688 try: 5689 misc.compile(cwd=path,shell=True) 5690 except MadGraph5Error, error: 5691 logger.error('''ASperGe failed to compile. Note that gsl is needed 5692 for this compilation to go trough. More information on how to install this package on 5693 http://www.gnu.org/software/gsl/ 5694 Full compilation log is available at %s''' % pjoin(self.me_dir, 'ASperge_compilation.log')) 5695 open(pjoin(self.me_dir, 'ASperge_compilation.log'),'w').write(str(error)) 5696 return 5697 5698 opts = line.split() 5699 card = self.paths['param'] 5700 logger.info('running ASperGE') 5701 returncode = misc.call([pjoin(path,'ASperGe'), card, '%s.new' % card] + opts) 5702 if returncode: 5703 logger.error('ASperGE fails with status %s' % returncode) 5704 else: 5705 logger.info('AsPerGe creates the file succesfully') 5706 files.mv(card, '%s.beforeasperge' % card) 5707 files.mv('%s.new' % card, card)
5708 5709 5710
5711 - def copy_file(self, path):
5712 """detect the type of the file and overwritte the current file""" 5713 5714 if path.endswith('.lhco'): 5715 #logger.info('copy %s as Events/input.lhco' % (path)) 5716 #files.cp(path, pjoin(self.mother_interface.me_dir, 'Events', 'input.lhco' )) 5717 self.do_set('mw_run inputfile %s' % os.path.relpath(path, self.mother_interface.me_dir)) 5718 return 5719 elif path.endswith('.lhco.gz'): 5720 #logger.info('copy %s as Events/input.lhco.gz' % (path)) 5721 #files.cp(path, pjoin(self.mother_interface.me_dir, 'Events', 'input.lhco.gz' )) 5722 self.do_set('mw_run inputfile %s' % os.path.relpath(path, self.mother_interface.me_dir)) 5723 return 5724 else: 5725 card_name = CommonRunCmd.detect_card_type(path) 5726 5727 if card_name == 'unknown': 5728 logger.warning('Fail to determine the type of the file. Not copied') 5729 if card_name != 'banner': 5730 logger.info('copy %s as %s' % (path, card_name)) 5731 files.cp(path, self.paths[card_name.split('_',1)[0]]) 5732 self.reload_card(self.paths[card_name.split('_',1)[0]]) 5733 elif card_name == 'banner': 5734 banner_mod.split_banner(path, self.mother_interface.me_dir, proc_card=False) 5735 logger.info('Splitting the banner in it\'s component') 5736 if not self.mode == 'auto': 5737 self.mother_interface.keep_cards(self.cards) 5738 for card_name in self.cards: 5739 self.reload_card(pjoin(self.me_dir, 'Cards', card_name))
5740
5741 - def open_file(self, answer):
5742 """open the file""" 5743 try: 5744 me_dir = self.mother_interface.me_dir 5745 except: 5746 me_dir = None 5747 5748 if answer.isdigit(): 5749 if answer == '9': 5750 answer = 'plot' 5751 else: 5752 answer = self.cards[int(answer)-1] 5753 5754 if 'madweight' in answer: 5755 answer = answer.replace('madweight', 'MadWeight') 5756 elif 'MadLoopParams' in answer: 5757 answer = self.paths['ML'] 5758 elif 'pythia8_card' in answer: 5759 answer = self.paths['PY8'] 5760 if os.path.exists(answer): 5761 path = answer 5762 else: 5763 if not '.dat' in answer and not '.lhco' in answer: 5764 if answer != 'trigger': 5765 path = self.paths[answer] 5766 else: 5767 path = self.paths['delphes'] 5768 elif not '.lhco' in answer: 5769 if '_' in answer: 5770 path = self.paths['_'.join(answer.split('_')[:-1])] 5771 else: 5772 path = pjoin(me_dir, 'Cards', answer) 5773 else: 5774 path = pjoin(me_dir, self.mw_card['mw_run']['inputfile']) 5775 if not os.path.exists(path): 5776 logger.info('Path in MW_card not existing') 5777 path = pjoin(me_dir, 'Events', answer) 5778 #security 5779 path = path.replace('_card_card','_card') 5780 try: 5781 self.mother_interface.exec_cmd('open %s' % path) 5782 except InvalidCmd, error: 5783 if str(error) != 'No default path for this file': 5784 raise 5785 if answer == 'transfer_card.dat': 5786 logger.warning('You have to specify a transfer function first!') 5787 elif answer == 'input.lhco': 5788 path = pjoin(me_dir,'Events', 'input.lhco') 5789 ff = open(path,'w') 5790 ff.write('''No LHCO information imported at current time. 5791 To import a lhco file: Close this file and type the path of your file. 5792 You can also copy/paste, your event file here.''') 5793 ff.close() 5794 self.open_file(path) 5795 else: 5796 raise 5797 self.reload_card(path)
5798
5799 - def reload_card(self, path):
5800 """reload object to have it in sync""" 5801 5802 if path == self.paths['param']: 5803 try: 5804 self.param_card = check_param_card.ParamCard(path) 5805 except (check_param_card.InvalidParamCard, ValueError) as e: 5806 logger.error('Current param_card is not valid. We are going to use the default one.') 5807 logger.error('problem detected: %s' % e) 5808 logger.error('Please re-open the file and fix the problem.') 5809 logger.warning('using the \'set\' command without opening the file will discard all your manual change') 5810 elif path == self.paths['run']: 5811 self.run_card = banner_mod.RunCard(path) 5812 elif path == self.paths['ML']: 5813 self.MLcard = banner_mod.MadLoopParam(path) 5814 elif path == self.paths['PY8']: 5815 # Use the read function so that modified/new parameters are correctly 5816 # set as 'user_set' 5817 if not self.PY8Card: 5818 self.PY8Card = banner_mod.PY8Card(self.paths['PY8_default']) 5819 5820 self.PY8Card.read(self.paths['PY8'], setter='user') 5821 self.py8_vars = [k.lower() for k in self.PY8Card.keys()] 5822 elif path == self.paths['MadWeight']: 5823 try: 5824 import madgraph.madweight.Cards as mwcards 5825 except: 5826 import internal.madweight.Cards as mwcards 5827 self.mw_card = mwcards.Card(path) 5828 return path 5829
5830 -class EditParamCard(AskforEditCard):
5831 """a dedicated module for the param""" 5832 5833 special_shortcut ={} 5834
5835 - def __init__(self, question, card=[], mode='auto', *args, **opt):
5836 5837 self.load_default() 5838 cmd.OneLinePathCompletion.__init__(self, question, *args, **opt) 5839 if os.path.isfile(card[0]): 5840 self.param_card = check_param_card.ParamCard(card[0]) 5841 self.paths['param'] = card[0] 5842 if os.path.isfile(card[0].replace('.dat', '_default.dat')): 5843 self.paths['param_default'] = card[0].replace('.dat', '_default.dat') 5844 else: 5845 self.paths['param_default'] = card[0] 5846 else: 5847 raise Exception, 'path %s do not exists' % card[0] 5848 5849 self.pname2block, self.restricted_value = self.param_card.analyze_param_card() 5850 self.cards=['param']
5851
5852 - def do_asperge(self, *args, **opts):
5853 "Not available" 5854 logger.warning("asperge not available in this mode")
5855