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': "/cvmfs/cp3.uclouvain.be/madgraph/", 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.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) 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 sys_pdf = self.run_card['sys_pdf'].split('&&') 1594 lhaid += [l.split()[0] for l in sys_pdf] 1595 1596 else: 1597 #check that all p 1598 pdf = [a[6:] for a in opts if a.startswith('--pdf=')] 1599 lhaid += [t.split('@')[0] for p in pdf for t in p.split(',') 1600 if t not in ['errorset', 'central']] 1601 1602 # Copy all the relevant PDF sets 1603 [self.copy_lhapdf_set([onelha], pdfsets_dir) for onelha in lhaid] 1604 1605 1606 if self.options['run_mode'] ==2: 1607 nb_submit = min(self.options['nb_core'], nb_event//2500) 1608 elif self.options['run_mode'] ==1: 1609 nb_submit = min(self.options['cluster_size'], nb_event//25000) 1610 else: 1611 nb_submit =1 1612 1613 if MADEVENT: 1614 import internal.systematics as systematics 1615 else: 1616 import madgraph.various.systematics as systematics 1617 1618 #one core: 1619 if nb_submit in [0,1]: 1620 systematics.call_systematics([input, output] + opts, 1621 log=lambda x: logger.info(str(x)), 1622 result=result_file 1623 ) 1624 1625 elif self.options['run_mode'] in [1,2]: 1626 event_per_job = nb_event // nb_submit 1627 nb_job_with_plus_one = nb_event % nb_submit 1628 start_event, stop_event = 0,0 1629 for i in range(nb_submit): 1630 #computing start/stop event 1631 event_requested = event_per_job 1632 if i < nb_job_with_plus_one: 1633 event_requested += 1 1634 start_event = stop_event 1635 stop_event = start_event + event_requested 1636 1637 prog = sys.executable 1638 input_files = [os.path.basename(input)] 1639 output_files = ['./tmp_%s_%s' % (i, os.path.basename(output)), 1640 './log_sys_%s.txt' % (i)] 1641 argument = [] 1642 if not __debug__: 1643 argument.append('-O') 1644 argument += [pjoin(self.me_dir, 'bin', 'internal', 'systematics.py'), 1645 input_files[0], output_files[0]] + opts +\ 1646 ['--start_event=%i' % start_event, 1647 '--stop_event=%i' %stop_event, 1648 '--result=./log_sys_%s.txt' %i, 1649 '--lhapdf_config=%s' % self.options['lhapdf']] 1650 required_output = output_files 1651 self.cluster.cluster_submit(prog, argument, 1652 input_files=input_files, 1653 output_files=output_files, 1654 cwd=os.path.dirname(output), 1655 required_output=required_output, 1656 stdout='/dev/null' 1657 ) 1658 starttime = time.time() 1659 update_status = lambda idle, run, finish: \ 1660 self.update_status((idle, run, finish, 'running systematics'), level=None, 1661 force=False, starttime=starttime) 1662 1663 try: 1664 self.cluster.wait(os.path.dirname(output), update_status, update_first=update_status) 1665 except Exception: 1666 self.cluster.remove() 1667 old_run_mode = self.options['run_mode'] 1668 self.options['run_mode'] =0 1669 try: 1670 out = self.do_systematics(line) 1671 finally: 1672 self.options['run_mode'] = old_run_mode 1673 #collect the data 1674 all_cross = [] 1675 for i in range(nb_submit): 1676 pos=0 1677 for line in open(pjoin(os.path.dirname(output), 'log_sys_%s.txt'%i)): 1678 if line.startswith('#'): 1679 continue 1680 split = line.split() 1681 if len(split) in [0,1]: 1682 continue 1683 key = tuple(float(x) for x in split[:-1]) 1684 cross= float(split[-1]) 1685 if 'event_norm' in self.run_card and \ 1686 self.run_card['event_norm'] in ['average', 'unity']: 1687 cross *= (event_per_job+1 if i <nb_job_with_plus_one else event_per_job) 1688 if len(all_cross) > pos: 1689 all_cross[pos] += cross 1690 else: 1691 all_cross.append(cross) 1692 pos+=1 1693 1694 if 'event_norm' in self.run_card and \ 1695 self.run_card['event_norm'] in ['unity']: 1696 all_cross= [cross/nb_event for cross in all_cross] 1697 1698 sys_obj = systematics.call_systematics([input, None] + opts, 1699 log=lambda x: logger.info(str(x)), 1700 result=result_file, 1701 running=False 1702 ) 1703 sys_obj.print_cross_sections(all_cross, nb_event, result_file) 1704 1705 #concatenate the output file 1706 subprocess.call(['cat']+\ 1707 ['./tmp_%s_%s' % (i, os.path.basename(output)) for i in range(nb_submit)], 1708 stdout=open(output,'w'), 1709 cwd=os.path.dirname(output)) 1710 for i in range(nb_submit): 1711 os.remove('%s/tmp_%s_%s' %(os.path.dirname(output),i,os.path.basename(output))) 1712 # os.remove('%s/log_sys_%s.txt' % (os.path.dirname(output),i)) 1713 1714 1715 1716 1717 1718 self.update_status('End of systematics computation', level='parton', makehtml=False)
1719 1720 1721 ############################################################################
1722 - def do_reweight(self, line):
1723 """ syntax is "reweight RUN_NAME" 1724 Allow to reweight the events generated with a new choices of model 1725 parameter. Description of the methods are available here 1726 cp3.irmp.ucl.ac.be/projects/madgraph/wiki/Reweight 1727 """ 1728 1729 #### Utility function 1730 def check_multicore(self): 1731 """ determine if the cards are save for multicore use""" 1732 card = pjoin(self.me_dir, 'Cards', 'reweight_card.dat') 1733 1734 multicore = True 1735 if self.options['run_mode'] in [0,1]: 1736 multicore = False 1737 1738 lines = [l.strip() for l in open(card) if not l.strip().startswith('#')] 1739 while lines and not lines[0].startswith('launch'): 1740 line = lines.pop(0) 1741 # if not standard output mode forbid multicore mode 1742 if line.startswith('change') and line[6:].strip().startswith('output'): 1743 return False 1744 if line.startswith('change') and line[6:].strip().startswith('multicore'): 1745 split_line = line.split() 1746 if len(split_line) > 2: 1747 multicore = bool(split_line[2]) 1748 # we have reached the first launch in the card ensure that no output change 1749 #are done after that point. 1750 lines = [line[6:].strip() for line in lines if line.startswith('change')] 1751 for line in lines: 1752 if line.startswith(('process','model','output', 'rwgt_dir')): 1753 return False 1754 elif line.startswith('multicore'): 1755 split_line = line.split() 1756 if len(split_line) > 1: 1757 multicore = bool(split_line[1]) 1758 1759 return multicore
1760 1761 1762 1763 if '-from_cards' in line and not os.path.exists(pjoin(self.me_dir, 'Cards', 'reweight_card.dat')): 1764 return 1765 # option for multicore to avoid that all of them create the same directory 1766 if '--multicore=create' in line: 1767 multicore='create' 1768 elif '--multicore=wait' in line: 1769 multicore='wait' 1770 else: 1771 multicore=False 1772 1773 # Check that MG5 directory is present . 1774 if MADEVENT and not self.options['mg5_path']: 1775 raise self.InvalidCmd, '''The module reweight requires that MG5 is installed on the system. 1776 You can install it and set its path in ./Cards/me5_configuration.txt''' 1777 elif MADEVENT: 1778 sys.path.append(self.options['mg5_path']) 1779 try: 1780 import madgraph.interface.reweight_interface as reweight_interface 1781 except ImportError: 1782 raise self.ConfigurationError, '''Can\'t load Reweight module. 1783 The variable mg5_path might not be correctly configured.''' 1784 1785 1786 1787 if not '-from_cards' in line: 1788 self.keep_cards(['reweight_card.dat'], ignore=['*']) 1789 self.ask_edit_cards(['reweight_card.dat'], 'fixed', plot=False) 1790 1791 # load the name of the event file 1792 args = self.split_arg(line) 1793 1794 if not self.force_run: 1795 # forbid this function to create an empty item in results. 1796 if self.run_name and self.results.current and self.results.current['cross'] == 0: 1797 self.results.delete_run(self.run_name, self.run_tag) 1798 self.results.save() 1799 # ensure that the run_card is present 1800 if not hasattr(self, 'run_card'): 1801 self.run_card = banner_mod.RunCard(pjoin(self.me_dir, 'Cards', 'run_card.dat')) 1802 1803 # we want to run this in a separate shell to avoid hard f2py crash 1804 command = [sys.executable] 1805 if os.path.exists(pjoin(self.me_dir, 'bin', 'madevent')): 1806 command.append(pjoin(self.me_dir, 'bin', 'internal','madevent_interface.py')) 1807 else: 1808 command.append(pjoin(self.me_dir, 'bin', 'internal', 'amcatnlo_run_interface.py')) 1809 if not isinstance(self, cmd.CmdShell): 1810 command.append('--web') 1811 command.append('reweight') 1812 1813 ######### START SINGLE CORE MODE ############ 1814 if self.options['nb_core']==1 or self.run_card['nevents'] < 101 or not check_multicore(self): 1815 if self.run_name: 1816 command.append(self.run_name) 1817 else: 1818 command += args 1819 if '-from_cards' not in command: 1820 command.append('-from_cards') 1821 p = misc.Popen(command, stdout = subprocess.PIPE, stderr = subprocess.STDOUT, cwd=os.getcwd()) 1822 while p.poll() is None: 1823 line = p.stdout.readline() 1824 if any(t in line for t in ['INFO:', 'WARNING:', 'CRITICAL:', 'ERROR:', 'root:','KEEP:']) and \ 1825 not '***********' in line: 1826 print line[:-1].replace('INFO', 'REWEIGHT').replace('KEEP:','') 1827 elif __debug__ and line: 1828 logger.debug(line[:-1]) 1829 if p.returncode !=0: 1830 logger.error("Reweighting failed") 1831 return 1832 self.results = self.load_results_db() 1833 # forbid this function to create an empty item in results. 1834 try: 1835 if self.results[self.run_name][-2]['cross']==0: 1836 self.results.delete_run(self.run_name,self.results[self.run_name][-2]['tag']) 1837 except: 1838 pass 1839 try: 1840 if self.results.current['cross'] == 0 and self.run_name: 1841 self.results.delete_run(self.run_name, self.run_tag) 1842 except: 1843 pass 1844 # re-define current run 1845 try: 1846 self.results.def_current(self.run_name, self.run_tag) 1847 except Exception: 1848 pass 1849 return 1850 ########## END SINGLE CORE HANDLING ############# 1851 else: 1852 ########## START MULTI-CORE HANDLING ############# 1853 if not isinstance(self.cluster, cluster.MultiCore): 1854 mycluster = cluster.MultiCore(nb_core=self.options['nb_core']) 1855 else: 1856 mycluster = self.cluster 1857 1858 new_args=list(args) 1859 self.check_decay_events(new_args) 1860 try: 1861 os.remove(pjoin(self.me_dir,'rw_me','rwgt.pkl')) 1862 except Exception, error: 1863 pass 1864 # prepare multi-core job: 1865 import madgraph.various.lhe_parser as lhe_parser 1866 # args now alway content the path to the valid files 1867 if 'nevt_job' in self.run_card and self.run_card['nevt_job'] !=-1: 1868 nevt_job = self.run_card['nevt_job'] 1869 else: 1870 nevt_job = max(5000, self.run_card['nevents']/50) 1871 logger.info("split the event file in bunch of %s events" % nevt_job) 1872 nb_file = lhe_parser.EventFile(new_args[0]).split(nevt_job) 1873 starttime = time.time() 1874 update_status = lambda idle, run, finish: \ 1875 self.update_status((idle, run, finish, 'reweight'), level=None, 1876 force=False, starttime=starttime) 1877 1878 all_lhe = [] 1879 devnull= open(os.devnull) 1880 for i in range(nb_file): 1881 new_command = list(command) 1882 new_command.append('%s_%s.lhe' % (new_args[0],i)) 1883 all_lhe.append('%s_%s.lhe' % (new_args[0],i)) 1884 if '-from_cards' not in command: 1885 new_command.append('-from_cards') 1886 if i==0: 1887 if __debug__: 1888 stdout = None 1889 else: 1890 stdout = open(pjoin(self.me_dir,'Events', self.run_name, 'reweight.log'),'w') 1891 new_command.append('--multicore=create') 1892 else: 1893 stdout = devnull 1894 #stdout = open(pjoin(self.me_dir,'Events', self.run_name, 'reweight%s.log' % i),'w') 1895 new_command.append('--multicore=wait') 1896 mycluster.submit(prog=command[0], argument=new_command[1:], stdout=stdout, cwd=os.getcwd()) 1897 mycluster.wait(self.me_dir,update_status) 1898 devnull.close() 1899 logger.info("Collect and combine the various output file.") 1900 lhe = lhe_parser.MultiEventFile(all_lhe, parse=False) 1901 nb_event, cross_sections = lhe.write(new_args[0], get_info=True) 1902 if any(os.path.exists('%s_%s_debug.log' % (f, self.run_tag)) for f in all_lhe): 1903 for f in all_lhe: 1904 if os.path.exists('%s_%s_debug.log' % (f, self.run_tag)): 1905 raise Exception, "Some of the run failed: Please read %s_%s_debug.log" % (f, self.run_tag) 1906 1907 1908 if 'event_norm' in self.run_card and self.run_card['event_norm'] == 'average': 1909 for key, value in cross_sections.items(): 1910 cross_sections[key] = value / (nb_event+1) 1911 lhe.remove() 1912 for key in cross_sections: 1913 if key == 'orig' or key.isdigit(): 1914 continue 1915 logger.info('%s : %s pb' % (key, cross_sections[key])) 1916 return 1917 ########## END MULTI-CORE HANDLING ############# 1918 1919 1920 self.to_store.append('event') 1921 # forbid this function to create an empty item in results. 1922 if self.results.current['cross'] == 0 and self.run_name: 1923 self.results.delete_run(self.run_name, self.run_tag) 1924 1925 self.check_decay_events(args) 1926 # args now alway content the path to the valid files 1927 reweight_cmd = reweight_interface.ReweightInterface(args[0], mother=self) 1928 #reweight_cmd.use_rawinput = False 1929 #reweight_cmd.mother = self 1930 wgt_names = reweight_cmd.get_weight_names() 1931 if wgt_names == [''] and reweight_cmd.has_nlo: 1932 self.update_status('Running Reweighting (LO approximate)', level='madspin') 1933 else: 1934 self.update_status('Running Reweighting', level='madspin') 1935 1936 path = pjoin(self.me_dir, 'Cards', 'reweight_card.dat') 1937 reweight_cmd.raw_input=False 1938 reweight_cmd.me_dir = self.me_dir 1939 reweight_cmd.multicore = multicore #allow the directory creation or not 1940 print "We are in mode", multicore 1941 reweight_cmd.import_command_file(path) 1942 reweight_cmd.do_quit('') 1943 1944 logger.info("quit rwgt") 1945 1946 1947 1948 # re-define current run 1949 try: 1950 self.results.def_current(self.run_name, self.run_tag) 1951 except Exception: 1952 pass 1953 1954 ############################################################################
1955 - def do_pgs(self, line):
1956 """launch pgs""" 1957 1958 args = self.split_arg(line) 1959 # Check argument's validity 1960 if '--no_default' in args: 1961 no_default = True 1962 args.remove('--no_default') 1963 else: 1964 no_default = False 1965 1966 if no_default and not os.path.exists(pjoin(self.me_dir, 'Cards', 'pgs_card.dat')): 1967 logger.info('No pgs_card detected, so not run pgs') 1968 return 1969 1970 # Check all arguments 1971 # This might launch a gunzip in another thread. After the question 1972 # This thread need to be wait for completion. (This allow to have the 1973 # question right away and have the computer working in the same time) 1974 # if lock is define this a locker for the completion of the thread 1975 lock = self.check_pgs(args, no_default=no_default) 1976 1977 # Check that the pgs_card exists. If not copy the default 1978 if not os.path.exists(pjoin(self.me_dir, 'Cards', 'pgs_card.dat')): 1979 files.cp(pjoin(self.me_dir, 'Cards', 'pgs_card_default.dat'), 1980 pjoin(self.me_dir, 'Cards', 'pgs_card.dat')) 1981 logger.info('No pgs card found. Take the default one.') 1982 1983 if not (no_default or self.force): 1984 self.ask_edit_cards(['pgs_card.dat']) 1985 1986 self.update_status('prepare PGS run', level=None) 1987 1988 pgsdir = pjoin(self.options['pythia-pgs_path'], 'src') 1989 eradir = self.options['exrootanalysis_path'] 1990 madir = self.options['madanalysis_path'] 1991 td = self.options['td_path'] 1992 1993 # Compile pgs if not there 1994 if not misc.is_executable(pjoin(pgsdir, 'pgs')): 1995 logger.info('No PGS executable -- running make') 1996 misc.compile(cwd=pgsdir) 1997 1998 self.update_status('Running PGS', level='pgs') 1999 2000 tag = self.run_tag 2001 # Update the banner with the pgs card 2002 banner_path = pjoin(self.me_dir, 'Events', self.run_name, '%s_%s_banner.txt' % (self.run_name, self.run_tag)) 2003 if os.path.exists(pjoin(self.me_dir, 'Source', 'banner_header.txt')): 2004 self.banner.add(pjoin(self.me_dir, 'Cards','pgs_card.dat')) 2005 self.banner.write(banner_path) 2006 else: 2007 open(banner_path, 'w').close() 2008 2009 ######################################################################## 2010 # now pass the event to a detector simulator and reconstruct objects 2011 ######################################################################## 2012 if lock: 2013 lock.wait() 2014 # Prepare the output file with the banner 2015 ff = open(pjoin(self.me_dir, 'Events', 'pgs_events.lhco'), 'w') 2016 if os.path.exists(pjoin(self.me_dir, 'Source', 'banner_header.txt')): 2017 text = open(banner_path).read() 2018 text = '#%s' % text.replace('\n','\n#') 2019 dico = self.results[self.run_name].get_current_info() 2020 text +='\n## Integrated weight (pb) : %.4g' % dico['cross'] 2021 text +='\n## Number of Event : %s\n' % dico['nb_event'] 2022 ff.writelines(text) 2023 ff.close() 2024 2025 try: 2026 os.remove(pjoin(self.me_dir, 'Events', 'pgs.done')) 2027 except Exception: 2028 pass 2029 2030 pgs_log = pjoin(self.me_dir, 'Events', self.run_name, "%s_pgs.log" % tag) 2031 self.cluster.launch_and_wait('../bin/internal/run_pgs', 2032 argument=[pgsdir], cwd=pjoin(self.me_dir,'Events'), 2033 stdout=pgs_log, stderr=subprocess.STDOUT) 2034 2035 if not os.path.exists(pjoin(self.me_dir, 'Events', 'pgs.done')): 2036 logger.error('Fail to create LHCO events') 2037 return 2038 else: 2039 os.remove(pjoin(self.me_dir, 'Events', 'pgs.done')) 2040 2041 if os.path.getsize(banner_path) == os.path.getsize(pjoin(self.me_dir, 'Events','pgs_events.lhco')): 2042 misc.call(['cat pgs_uncleaned_events.lhco >> pgs_events.lhco'], 2043 cwd=pjoin(self.me_dir, 'Events')) 2044 os.remove(pjoin(self.me_dir, 'Events', 'pgs_uncleaned_events.lhco ')) 2045 2046 # Creating Root file 2047 if eradir and misc.is_executable(pjoin(eradir, 'ExRootLHCOlympicsConverter')): 2048 self.update_status('Creating PGS Root File', level='pgs') 2049 try: 2050 misc.call([eradir+'/ExRootLHCOlympicsConverter', 2051 'pgs_events.lhco',pjoin('%s/%s_pgs_events.root' % (self.run_name, tag))], 2052 cwd=pjoin(self.me_dir, 'Events')) 2053 except Exception: 2054 logger.warning('fail to produce Root output [problem with ExRootAnalysis') 2055 if os.path.exists(pjoin(self.me_dir, 'Events', 'pgs_events.lhco')): 2056 # Creating plots 2057 files.mv(pjoin(self.me_dir, 'Events', 'pgs_events.lhco'), 2058 pjoin(self.me_dir, 'Events', self.run_name, '%s_pgs_events.lhco' % tag)) 2059 self.create_plot('PGS') 2060 misc.gzip(pjoin(self.me_dir, 'Events', self.run_name, '%s_pgs_events.lhco' % tag)) 2061 2062 self.update_status('finish', level='pgs', makehtml=False)
2063 2064 ############################################################################
2065 - def do_compute_widths(self, line):
2066 """Require MG5 directory: Compute automatically the widths of a set 2067 of particles""" 2068 2069 2070 2071 args = self.split_arg(line) 2072 opts = self.check_compute_widths(args) 2073 2074 from madgraph.interface.master_interface import MasterCmd 2075 cmd = MasterCmd() 2076 self.define_child_cmd_interface(cmd, interface=False) 2077 cmd.exec_cmd('set automatic_html_opening False --no_save') 2078 if not opts['path']: 2079 opts['path'] = pjoin(self.me_dir, 'Cards', 'param_card.dat') 2080 if not opts['force'] : 2081 self.ask_edit_cards(['param_card'],[], plot=False) 2082 2083 2084 line = 'compute_widths %s %s' % \ 2085 (' '.join([str(i) for i in opts['particles']]), 2086 ' '.join('--%s=%s' % (key,value) for (key,value) in opts.items() 2087 if key not in ['model', 'force', 'particles'] and value)) 2088 cmd.exec_cmd(line, model=opts['model']) 2089 self.child = None 2090 del cmd
2091 2092 ############################################################################
2093 - def do_print_results(self, line):
2094 """Not in help:Print the cross-section/ number of events for a given run""" 2095 2096 args = self.split_arg(line) 2097 options={'path':None, 'mode':'w', 'format':'full'} 2098 for arg in list(args): 2099 if arg.startswith('--') and '=' in arg: 2100 name,value=arg.split('=',1) 2101 name = name [2:] 2102 options[name] = value 2103 args.remove(arg) 2104 2105 2106 if len(args) > 0: 2107 run_name = args[0] 2108 else: 2109 for i, run_name in enumerate(self.results.order): 2110 for j, one_result in enumerate(self.results[run_name]): 2111 if i or j: 2112 options['mode'] = "a" 2113 if options['path']: 2114 self.print_results_in_file(one_result, options['path'], options['mode'], options['format']) 2115 else: 2116 self.print_results_in_shell(one_result) 2117 return 2118 2119 if run_name not in self.results: 2120 raise self.InvalidCmd('%s is not a valid run_name or it doesn\'t have any information' \ 2121 % run_name) 2122 2123 2124 if len(args) == 2: 2125 tag = args[1] 2126 if tag.isdigit(): 2127 tag = int(tag) - 1 2128 if len(self.results[run_name]) < tag: 2129 raise self.InvalidCmd('Only %s different tag available' % \ 2130 len(self.results[run_name])) 2131 data = self.results[run_name][tag] 2132 else: 2133 data = self.results[run_name].return_tag(tag) 2134 else: 2135 data = self.results[run_name].return_tag(None) # return the last 2136 2137 if options['path']: 2138 self.print_results_in_file(data, options['path'], options['mode'], options['format']) 2139 else: 2140 self.print_results_in_shell(data)
2141
2142 - def configure_directory(self, *args, **opts):
2143 """ All action require before any type of run. Typically overloaded by 2144 daughters if need be.""" 2145 pass
2146 2147 ############################################################################ 2148 # Start of MadAnalysis5 related function 2149 ############################################################################ 2150 2151 @staticmethod
2152 - def runMA5(MA5_interpreter, MA5_cmds, MA5_runtag, logfile_path, advertise_log=True):
2153 """ Run MA5 in a controlled environnment.""" 2154 successfull_MA5_run = True 2155 2156 try: 2157 # Predefine MA5_logger as None in case we don't manage to retrieve it. 2158 MA5_logger = None 2159 MA5_logger = logging.getLogger('MA5') 2160 BackUp_MA5_handlers = MA5_logger.handlers 2161 for handler in BackUp_MA5_handlers: 2162 MA5_logger.removeHandler(handler) 2163 file_handler = logging.FileHandler(logfile_path) 2164 MA5_logger.addHandler(file_handler) 2165 if advertise_log: 2166 logger.info("Follow Madanalysis5 run with the following command in a separate terminal:") 2167 logger.info(' tail -f %s'%logfile_path) 2168 # Now the magic, finally call MA5. 2169 with misc.stdchannel_redirected(sys.stdout, os.devnull): 2170 with misc.stdchannel_redirected(sys.stderr, os.devnull): 2171 MA5_interpreter.print_banner() 2172 MA5_interpreter.load(MA5_cmds) 2173 except Exception as e: 2174 logger.warning("MadAnalysis5 failed to run the commands for task "+ 2175 "'%s'. Madanalys5 analysis will be skipped."%MA5_runtag) 2176 error=StringIO.StringIO() 2177 traceback.print_exc(file=error) 2178 logger.debug('MadAnalysis5 error was:') 2179 logger.debug('-'*60) 2180 logger.debug(error.getvalue()[:-1]) 2181 logger.debug('-'*60) 2182 successfull_MA5_run = False 2183 finally: 2184 if not MA5_logger is None: 2185 for handler in MA5_logger.handlers: 2186 MA5_logger.removeHandler(handler) 2187 for handler in BackUp_MA5_handlers: 2188 MA5_logger.addHandler(handler) 2189 2190 return successfull_MA5_run
2191 2192 #=============================================================================== 2193 # Return a Main instance of MadAnlysis5, provided its path 2194 #=============================================================================== 2195 @staticmethod
2196 - def get_MadAnalysis5_interpreter(mg5_path, ma5_path, mg5_interface=None, 2197 logstream = sys.stdout, loglevel =logging.INFO, forced = True):
2198 """ Makes sure to correctly setup paths and constructs and return an MA5 path""" 2199 2200 MA5path = os.path.normpath(pjoin(mg5_path,ma5_path)) 2201 2202 if MA5path is None or not os.path.isfile(pjoin(MA5path,'bin','ma5')): 2203 return None 2204 if MA5path not in sys.path: 2205 sys.path.insert(0, MA5path) 2206 2207 try: 2208 # We must backup the readline module attributes because they get modified 2209 # when MA5 imports root and that supersedes MG5 autocompletion 2210 import readline 2211 old_completer = readline.get_completer() 2212 old_delims = readline.get_completer_delims() 2213 old_history = [readline.get_history_item(i) for i in range(1,readline.get_current_history_length()+1)] 2214 except ImportError: 2215 old_completer, old_delims, old_history = None, None, None 2216 try: 2217 from madanalysis.interpreter.ma5_interpreter import MA5Interpreter 2218 with misc.stdchannel_redirected(sys.stdout, os.devnull): 2219 with misc.stdchannel_redirected(sys.stderr, os.devnull): 2220 MA5_interpreter = MA5Interpreter(MA5path, LoggerLevel=loglevel, 2221 LoggerStream=logstream,forced=forced) 2222 except Exception as e: 2223 logger.warning('MadAnalysis5 failed to start so that MA5 analysis will be skipped.') 2224 error=StringIO.StringIO() 2225 traceback.print_exc(file=error) 2226 logger.debug('MadAnalysis5 error was:') 2227 logger.debug('-'*60) 2228 logger.debug(error.getvalue()[:-1]) 2229 logger.debug('-'*60) 2230 MA5_interpreter = None 2231 finally: 2232 # Now restore the readline MG5 state 2233 if not old_history is None: 2234 readline.clear_history() 2235 for line in old_history: 2236 readline.add_history(line) 2237 if not old_completer is None: 2238 readline.set_completer(old_completer) 2239 if not old_delims is None: 2240 readline.set_completer_delims(old_delims) 2241 # Also restore the completion_display_matches_hook if an mg5 interface 2242 # is specified as it could also have been potentially modified 2243 if not mg5_interface is None and any(not elem is None for elem in [old_completer, old_delims, old_history]): 2244 mg5_interface.set_readline_completion_display_matches_hook() 2245 2246 return MA5_interpreter
2247
2248 - def check_madanalysis5(self, args, mode='parton'):
2249 """Check the argument for the madanalysis5 command 2250 syntax: madanalysis5_parton [NAME] 2251 """ 2252 2253 MA5_options = {'MA5_stdout_lvl':'default'} 2254 2255 stdout_level_tags = [a for a in args if a.startswith('--MA5_stdout_lvl=')] 2256 for slt in stdout_level_tags: 2257 lvl = slt.split('=')[1].strip() 2258 try: 2259 # It is likely an int 2260 MA5_options['MA5_stdout_lvl']=int(lvl) 2261 except ValueError: 2262 if lvl.startswith('logging.'): 2263 lvl = lvl[8:] 2264 try: 2265 MA5_options['MA5_stdout_lvl'] = getattr(logging, lvl) 2266 except: 2267 raise InvalidCmd("MA5 output level specification"+\ 2268 " '%s' is incorrect." % str(lvl)) 2269 args.remove(slt) 2270 2271 if mode=='parton': 2272 # We will attempt to run MA5 on the parton level output 2273 # found in the last run if not specified. 2274 MA5_options['inputs'] = '*.lhe' 2275 elif mode=='hadron': 2276 # We will run MA5 on all sources of post-partonic output we 2277 # can find if not specified. PY8 is a keyword indicating shower 2278 # piped to MA5. 2279 MA5_options['inputs'] = ['fromCard'] 2280 else: 2281 raise MadGraph5Error('Mode %s not reckognized'%mode+ 2282 ' in function check_madanalysis5.') 2283 # If not madanalysis5 path 2284 if not self.options['madanalysis5_path']: 2285 logger.info('Now trying to read the configuration file again'+ 2286 ' to find MadAnalysis5 path') 2287 self.set_configuration() 2288 2289 if not self.options['madanalysis5_path'] or not \ 2290 os.path.exists(pjoin(self.options['madanalysis5_path'],'bin','ma5')): 2291 error_msg = 'No valid MadAnalysis5 path set.\n' 2292 error_msg += 'Please use the set command to define the path and retry.\n' 2293 error_msg += 'You can also define it in the configuration file.\n' 2294 error_msg += 'Finally, it can be installed automatically using the' 2295 error_msg += ' install command.\n' 2296 raise self.InvalidCmd(error_msg) 2297 2298 # Now make sure that the corresponding default card exists 2299 if not os.path.isfile(pjoin(self.me_dir, 2300 'Cards','madanalysis5_%s_card.dat'%mode)): 2301 raise self.InvalidCmd('Your installed version of MadAnalysis5 and/or'+\ 2302 ' MadGraph5_aMCatNLO does not seem to support analysis at'+ 2303 '%s level.'%mode) 2304 2305 tag = [a for a in args if a.startswith('--tag=')] 2306 if tag: 2307 args.remove(tag[0]) 2308 tag = tag[0][6:] 2309 2310 if len(args) == 0 and not self.run_name: 2311 if self.results.lastrun: 2312 args.insert(0, self.results.lastrun) 2313 else: 2314 raise self.InvalidCmd('No run name currently defined. '+ 2315 'Please add this information.') 2316 2317 if len(args) >= 1: 2318 if mode=='parton' and args[0] != self.run_name and \ 2319 not os.path.exists(pjoin(self.me_dir,'Events',args[0], 2320 'unweighted_events.lhe.gz')) and not os.path.exists( 2321 pjoin(self.me_dir,'Events',args[0])): 2322 raise self.InvalidCmd('No events file in the %s run.'%args[0]) 2323 self.set_run_name(args[0], tag, level='madanalysis5_%s'%mode) 2324 else: 2325 if tag: 2326 self.run_card['run_tag'] = args[0] 2327 self.set_run_name(self.run_name, tag, level='madanalysis5_%s'%mode) 2328 2329 if mode=='parton': 2330 if any(t for t in args if t.startswith('--input=')): 2331 raise InvalidCmd('The option --input=<input_file> is not'+ 2332 ' available when running partonic MadAnalysis5 analysis. The'+ 2333 ' .lhe output of the selected run is used automatically.') 2334 input_file = pjoin(self.me_dir,'Events',self.run_name, 'unweighted_events.lhe') 2335 MA5_options['inputs'] = '%s.gz'%input_file 2336 if not os.path.exists('%s.gz'%input_file): 2337 if os.path.exists(input_file): 2338 misc.gzip(input_file, keep=True, stdout=output_file) 2339 else: 2340 logger.warning("LHE event file not found in \n%s\ns"%input_file+ 2341 "Parton-level MA5 analysis will be skipped.") 2342 2343 if mode=='hadron': 2344 # Make sure to store current results (like Pythia8 hep files) 2345 # so that can be found here 2346 self.store_result() 2347 2348 hadron_tag = [t for t in args if t.startswith('--input=')] 2349 if hadron_tag and hadron_tag[0][8:]: 2350 hadron_inputs = hadron_tag[0][8:].split(',') 2351 2352 # If not set above, then we must read it from the card 2353 elif MA5_options['inputs'] == ['fromCard']: 2354 hadron_inputs = banner_mod.MadAnalysis5Card(pjoin(self.me_dir, 2355 'Cards','madanalysis5_hadron_card.dat'),mode='hadron')['inputs'] 2356 2357 # Make sure the corresponding input files are present and unfold 2358 # potential wildcard while making their path absolute as well. 2359 MA5_options['inputs'] = [] 2360 special_source_tags = [] 2361 for htag in hadron_inputs: 2362 # Possible pecial tag for MA5 run inputs 2363 if htag in special_source_tags: 2364 # Special check/actions 2365 continue 2366 # Check if the specified file exists and is not a wildcard 2367 if os.path.isfile(htag) or (os.path.exists(htag) and 2368 stat.S_ISFIFO(os.stat(htag).st_mode)): 2369 MA5_options['inputs'].append(htag) 2370 continue 2371 2372 # Now select one source per tag, giving priority to unzipped 2373 # files with 'events' in their name (case-insensitive). 2374 file_candidates = misc.glob(htag, pjoin(self.me_dir,'Events',self.run_name))+\ 2375 misc.glob('%s.gz'%htag, pjoin(self.me_dir,'Events',self.run_name)) 2376 priority_files = [f for f in file_candidates if 2377 self.run_card['run_tag'] in os.path.basename(f)] 2378 priority_files = [f for f in priority_files if 2379 'EVENTS' in os.path.basename(f).upper()] 2380 # Make sure to always prefer the original partonic event file 2381 for f in file_candidates: 2382 if os.path.basename(f).startswith('unweighted_events.lhe'): 2383 priority_files.append(f) 2384 if priority_files: 2385 MA5_options['inputs'].append(priority_files[-1]) 2386 continue 2387 if file_candidates: 2388 MA5_options['inputs'].append(file_candidates[-1]) 2389 continue 2390 2391 return MA5_options
2392
2393 - def ask_madanalysis5_run_configuration(self, runtype='parton',mode=None):
2394 """Ask the question when launching madanalysis5. 2395 In the future we can ask here further question about the MA5 run, but 2396 for now we just edit the cards""" 2397 2398 cards = ['madanalysis5_%s_card.dat'%runtype] 2399 self.keep_cards(cards) 2400 2401 if self.force: 2402 return runtype 2403 2404 # This heavy-looking structure of auto is just to mimick what is done 2405 # for ask_pythia_configuration 2406 auto=False 2407 if mode=='auto': 2408 auto=True 2409 if auto: 2410 self.ask_edit_cards(cards, mode='auto', plot=False) 2411 else: 2412 self.ask_edit_cards(cards, plot=False) 2413 2414 # For now, we don't pass any further information and simply return the 2415 # input mode asked for 2416 mode = runtype 2417 return mode
2418
2419 - def complete_madanalysis5_hadron(self,text, line, begidx, endidx):
2420 "Complete the madanalysis5 command" 2421 args = self.split_arg(line[0:begidx], error=False) 2422 if len(args) == 1: 2423 #return valid run_name 2424 data = [] 2425 for name in banner_mod.MadAnalysis5Card._default_hadron_inputs: 2426 data += misc.glob(pjoin('*','%s'%name), pjoin(self.me_dir, 'Events')) 2427 data += misc.glob(pjoin('*','%s.gz'%name), pjoin(self.me_dir, 'Events')) 2428 data = [n.rsplit('/',2)[1] for n in data] 2429 tmp1 = self.list_completion(text, data) 2430 if not self.run_name: 2431 return tmp1 2432 else: 2433 tmp2 = self.list_completion(text, ['-f', 2434 '--MA5_stdout_lvl=','--input=','--no_default', '--tag='], line) 2435 return tmp1 + tmp2 2436 2437 elif '--MA5_stdout_lvl=' in line and not any(arg.startswith( 2438 '--MA5_stdout_lvl=') for arg in args): 2439 return self.list_completion(text, 2440 ['--MA5_stdout_lvl=%s'%opt for opt in 2441 ['logging.INFO','logging.DEBUG','logging.WARNING', 2442 'logging.CRITICAL','90']], line) 2443 elif '--input=' in line and not any(arg.startswith( 2444 '--input=') for arg in args): 2445 return self.list_completion(text, ['--input=%s'%opt for opt in 2446 (banner_mod.MadAnalysis5Card._default_hadron_inputs +['path'])], line) 2447 else: 2448 return self.list_completion(text, ['-f', 2449 '--MA5_stdout_lvl=','--input=','--no_default', '--tag='], line)
2450
2451 - def do_madanalysis5_hadron(self, line):
2452 """launch MadAnalysis5 at the hadron level.""" 2453 return self.run_madanalysis5(line,mode='hadron')
2454
2455 - def run_madanalysis5(self, line, mode='parton'):
2456 """launch MadAnalysis5 at the parton level or at the hadron level with 2457 a specific command line.""" 2458 2459 # Check argument's validity 2460 args = self.split_arg(line) 2461 2462 if '--no_default' in args: 2463 no_default = True 2464 args.remove('--no_default') 2465 else: 2466 no_default = False 2467 2468 if no_default: 2469 # Called issued by MG5aMC itself during a generate_event action 2470 if mode=='parton' and not os.path.exists(pjoin(self.me_dir, 'Cards', 2471 'madanalysis5_parton_card.dat')): 2472 return 2473 if mode=='hadron' and not os.path.exists(pjoin(self.me_dir, 'Cards', 2474 'madanalysis5_hadron_card.dat')): 2475 return 2476 else: 2477 # Called issued by the user itself and only MA5 will be run. 2478 # we must therefore ask wheter the user wants to edit the card 2479 self.ask_madanalysis5_run_configuration(runtype=mode) 2480 2481 if not self.options['madanalysis5_path'] or \ 2482 all(not os.path.exists(pjoin(self.me_dir, 'Cards',card)) for card in 2483 ['madanalysis5_parton_card.dat','madanalysis5_hadron_card.dat']): 2484 if no_default: 2485 return 2486 else: 2487 raise InvalidCmd('You must have MadAnalysis5 available to run'+ 2488 " this command. Consider installing it with the 'install' function.") 2489 2490 if not self.run_name: 2491 MA5_opts = self.check_madanalysis5(args, mode=mode) 2492 self.configure_directory(html_opening =False) 2493 else: 2494 # initialize / remove lhapdf mode 2495 self.configure_directory(html_opening =False) 2496 MA5_opts = self.check_madanalysis5(args, mode=mode) 2497 2498 # Now check that there is at least one input to run 2499 if MA5_opts['inputs']==[]: 2500 if no_default: 2501 logger.warning('No hadron level input found to run MadAnalysis5 on.'+ 2502 ' Skipping its hadron-level analysis.') 2503 return 2504 else: 2505 raise self.InvalidCmd('\nNo input files specified or availabled for'+ 2506 ' this MadAnalysis5 hadron-level run.\nPlease double-check the options of this'+ 2507 ' MA5 command (or card) and which output files\nare currently in the chosen'+ 2508 " run directory '%s'."%self.run_name) 2509 2510 MA5_card = banner_mod.MadAnalysis5Card(pjoin(self.me_dir, 'Cards', 2511 'madanalysis5_%s_card.dat'%mode), mode=mode) 2512 2513 if MA5_card._skip_analysis: 2514 logger.info('Madanalysis5 %s-level analysis was skipped following user request.'%mode) 2515 logger.info("To run the analysis, remove or comment the tag '%s skip_analysis' " 2516 %banner_mod.MadAnalysis5Card._MG5aMC_escape_tag+ 2517 "in\n '%s'."%pjoin(self.me_dir, 'Cards','madanalysis5_%s_card.dat'%mode)) 2518 return 2519 2520 MA5_cmds_list = MA5_card.get_MA5_cmds(MA5_opts['inputs'], 2521 pjoin(self.me_dir,'MA5_%s_ANALYSIS'%mode.upper()), 2522 run_dir_path = pjoin(self.me_dir,'Events', self.run_name), 2523 UFO_model_path=pjoin(self.me_dir,'bin','internal','ufomodel'), 2524 run_tag = self.run_tag) 2525 2526 # Here's how to print the MA5 commands generated by MG5aMC 2527 # for MA5_runtag, MA5_cmds in MA5_cmds_list: 2528 # misc.sprint('****************************************') 2529 # misc.sprint('* Commands for MA5 runtag %s:'%MA5_runtag) 2530 # misc.sprint('\n'+('\n'.join('* %s'%cmd for cmd in MA5_cmds))) 2531 # misc.sprint('****************************************') 2532 2533 self.update_status('\033[92mRunning MadAnalysis5 [arXiv:1206.1599]\033[0m', 2534 level='madanalysis5_%s'%mode) 2535 if mode=='hadron': 2536 logger.info('Hadron input files considered:') 2537 for input in MA5_opts['inputs']: 2538 logger.info(' --> %s'%input) 2539 elif mode=='parton': 2540 logger.info('Parton input file considered:') 2541 logger.info(' --> %s'%MA5_opts['inputs']) 2542 2543 # Obtain a main MA5 interpreter 2544 # Ideally we would like to do it all with a single interpreter 2545 # but we'd need a way to reset it for this. 2546 if MA5_opts['MA5_stdout_lvl']=='default': 2547 if MA5_card['stdout_lvl'] is None: 2548 MA5_lvl = self.options['stdout_level'] 2549 else: 2550 MA5_lvl = MA5_card['stdout_lvl'] 2551 else: 2552 MA5_lvl = MA5_opts['MA5_stdout_lvl'] 2553 2554 # Bypass initialization information 2555 MA5_interpreter = CommonRunCmd.get_MadAnalysis5_interpreter( 2556 self.options['mg5_path'], 2557 self.options['madanalysis5_path'], 2558 logstream=sys.stdout, 2559 loglevel=100, 2560 forced=True) 2561 2562 2563 # If failed to start MA5, then just leave 2564 if MA5_interpreter is None: 2565 return 2566 2567 # Make sure to only run over one analysis over each fifo. 2568 used_up_fifos = [] 2569 # Now loop over the different MA5_runs 2570 for MA5_runtag, MA5_cmds in MA5_cmds_list: 2571 2572 # Bypass the banner. 2573 MA5_interpreter.setLogLevel(100) 2574 # Make sure to properly initialize MA5 interpreter 2575 if mode=='hadron': 2576 MA5_interpreter.init_reco() 2577 else: 2578 MA5_interpreter.init_parton() 2579 MA5_interpreter.setLogLevel(MA5_lvl) 2580 2581 if MA5_runtag!='default': 2582 if MA5_runtag.startswith('_reco_'): 2583 logger.info("MadAnalysis5 now running the reconstruction '%s'..."% 2584 MA5_runtag[6:],'$MG:color:GREEN') 2585 elif MA5_runtag=='Recasting': 2586 logger.info("MadAnalysis5 now running the recasting...", 2587 '$MG:color:GREEN') 2588 else: 2589 logger.info("MadAnalysis5 now running the '%s' analysis..."% 2590 MA5_runtag,'$MG:color:GREEN') 2591 2592 2593 # Now the magic, let's call MA5 2594 if not CommonRunCmd.runMA5(MA5_interpreter, MA5_cmds, MA5_runtag, 2595 pjoin(self.me_dir,'Events',self.run_name,'%s_MA5_%s.log'%(self.run_tag,MA5_runtag))): 2596 # Unsuccessful MA5 run, we therefore stop here. 2597 return 2598 2599 if MA5_runtag.startswith('_reco_'): 2600 # When doing a reconstruction we must first link the event file 2601 # created with MA5 reconstruction and then directly proceed to the 2602 # next batch of instructions. There can be several output directory 2603 # if there were several input files. 2604 links_created=[] 2605 for i, input in enumerate(MA5_opts['inputs']): 2606 # Make sure it is not an lhco or root input, which would not 2607 # undergo any reconstruction of course. 2608 if not banner_mod.MadAnalysis5Card.events_can_be_reconstructed(input): 2609 continue 2610 2611 if input.endswith('.fifo'): 2612 if input in used_up_fifos: 2613 # Only run once on each fifo 2614 continue 2615 else: 2616 used_up_fifos.append(input) 2617 2618 reco_output = pjoin(self.me_dir, 2619 'MA5_%s_ANALYSIS%s_%d'%(mode.upper(),MA5_runtag,i+1)) 2620 # Look for either a root or .lhe.gz output 2621 reco_event_file = misc.glob('*.lhe.gz',pjoin(reco_output,'Output','_reco_events'))+\ 2622 misc.glob('*.root',pjoin(reco_output,'Output','_reco_events')) 2623 if len(reco_event_file)==0: 2624 raise MadGraph5Error, "MadAnalysis5 failed to produce the "+\ 2625 "reconstructed event file for reconstruction '%s'."%MA5_runtag[6:] 2626 reco_event_file = reco_event_file[0] 2627 # move the reconstruction output to the HTML directory 2628 shutil.move(reco_output,pjoin(self.me_dir,'HTML', 2629 self.run_name,'%s_MA5_%s_ANALYSIS%s_%d'% 2630 (self.run_tag,mode.upper(),MA5_runtag,i+1))) 2631 # link the reconstructed event file to the run directory 2632 links_created.append(os.path.basename(reco_event_file)) 2633 files.ln(pjoin(self.me_dir,'HTML',self.run_name, 2634 '%s_MA5_%s_ANALYSIS%s_%d'%(self.run_tag,mode.upper(), 2635 MA5_runtag,i+1),'Output','_reco_events',links_created[-1]), 2636 pjoin(self.me_dir,'Events',self.run_name)) 2637 2638 logger.info("MadAnalysis5 successfully completed the reconstruction "+ 2639 "'%s'. Links to the reconstructed event files are:"%MA5_runtag[6:]) 2640 for link in links_created: 2641 logger.info(' --> %s'%pjoin(self.me_dir,'Events',self.run_name,link)) 2642 continue 2643 2644 if MA5_runtag.upper()=='RECASTING': 2645 target = pjoin(self.me_dir,'MA5_%s_ANALYSIS_%s'\ 2646 %(mode.upper(),MA5_runtag),'Output','CLs_output_summary.dat') 2647 else: 2648 target = pjoin(self.me_dir,'MA5_%s_ANALYSIS_%s'\ 2649 %(mode.upper(),MA5_runtag),'PDF','main.pdf') 2650 if not os.path.isfile(target): 2651 raise MadGraph5Error, "MadAnalysis5 failed to produced "+\ 2652 "an output for the analysis '%s' in\n %s"%(MA5_runtag,target) 2653 2654 # Copy the PDF report or CLs in the Events/run directory. 2655 if MA5_runtag.upper()=='RECASTING': 2656 carboncopy_name = '%s_MA5_CLs.dat'%(self.run_tag) 2657 else: 2658 carboncopy_name = '%s_MA5_%s_analysis_%s.pdf'%( 2659 self.run_tag,mode,MA5_runtag) 2660 shutil.copy(target, pjoin(self.me_dir,'Events',self.run_name,carboncopy_name)) 2661 if MA5_runtag!='default': 2662 logger.info("MadAnalysis5 successfully completed the "+ 2663 "%s. Reported results are placed in:"%("analysis '%s'"%MA5_runtag 2664 if MA5_runtag.upper()!='RECASTING' else "recasting")) 2665 else: 2666 logger.info("MadAnalysis5 successfully completed the analysis."+ 2667 " Reported results are placed in:") 2668 logger.info(' --> %s'%pjoin(self.me_dir,'Events',self.run_name,carboncopy_name)) 2669 2670 # Copy the entire analysis in the HTML directory 2671 shutil.move(pjoin(self.me_dir,'MA5_%s_ANALYSIS_%s'\ 2672 %(mode.upper(),MA5_runtag)), pjoin(self.me_dir,'HTML',self.run_name, 2673 '%s_MA5_%s_ANALYSIS_%s'%(self.run_tag,mode.upper(),MA5_runtag))) 2674 2675 # Set the number of events and cross-section to the last one 2676 # (maybe do something smarter later) 2677 new_details={} 2678 for detail in ['nb_event','cross','error']: 2679 new_details[detail] = \ 2680 self.results[self.run_name].get_current_info()[detail] 2681 for detail in new_details: 2682 self.results.add_detail(detail,new_details[detail]) 2683 2684 self.update_status('Finished MA5 analyses.', level='madanalysis5_%s'%mode, 2685 makehtml=False) 2686 2687 #Update the banner 2688 self.banner.add(pjoin(self.me_dir, 'Cards', 2689 'madanalysis5_%s_card.dat'%mode)) 2690 banner_path = pjoin(self.me_dir,'Events', self.run_name, 2691 '%s_%s_banner.txt'%(self.run_name, self.run_tag)) 2692 self.banner.write(banner_path) 2693 2694 if not no_default: 2695 logger.info('Find more information about this run on the HTML local page') 2696 logger.info(' --> %s'%pjoin(self.me_dir,'index.html'))
2697 2698 ############################################################################ 2699 # End of MadAnalysis5 related function 2700 ############################################################################ 2701
2702 - def do_delphes(self, line):
2703 """ run delphes and make associate root file/plot """ 2704 2705 args = self.split_arg(line) 2706 # Check argument's validity 2707 if '--no_default' in args: 2708 no_default = True 2709 args.remove('--no_default') 2710 else: 2711 no_default = False 2712 2713 if no_default and not os.path.exists(pjoin(self.me_dir, 'Cards', 'delphes_card.dat')): 2714 logger.info('No delphes_card detected, so not run Delphes') 2715 return 2716 2717 # Check all arguments 2718 filepath = self.check_delphes(args, nodefault=no_default) 2719 if no_default and not filepath: 2720 return # no output file but nothing to do either. 2721 2722 self.update_status('prepare delphes run', level=None) 2723 2724 if os.path.exists(pjoin(self.options['delphes_path'], 'data')): 2725 delphes3 = False 2726 prog = '../bin/internal/run_delphes' 2727 if filepath and '.hepmc' in filepath[:-10]: 2728 raise self.InvalidCmd, 'delphes2 do not support hepmc' 2729 else: 2730 delphes3 = True 2731 prog = '../bin/internal/run_delphes3' 2732 2733 # Check that the delphes_card exists. If not copy the default and 2734 # ask for edition of the card. 2735 if not os.path.exists(pjoin(self.me_dir, 'Cards', 'delphes_card.dat')): 2736 if no_default: 2737 logger.info('No delphes_card detected, so not running Delphes') 2738 return 2739 files.cp(pjoin(self.me_dir, 'Cards', 'delphes_card_default.dat'), 2740 pjoin(self.me_dir, 'Cards', 'delphes_card.dat')) 2741 logger.info('No delphes card found. Take the default one.') 2742 if not delphes3 and not os.path.exists(pjoin(self.me_dir, 'Cards', 'delphes_trigger.dat')): 2743 files.cp(pjoin(self.me_dir, 'Cards', 'delphes_trigger_default.dat'), 2744 pjoin(self.me_dir, 'Cards', 'delphes_trigger.dat')) 2745 if not (no_default or self.force): 2746 if delphes3: 2747 self.ask_edit_cards(['delphes_card.dat'], args) 2748 else: 2749 self.ask_edit_cards(['delphes_card.dat', 'delphes_trigger.dat'], args) 2750 2751 self.update_status('Running Delphes', level=None) 2752 2753 delphes_dir = self.options['delphes_path'] 2754 tag = self.run_tag 2755 if os.path.exists(pjoin(self.me_dir, 'Source', 'banner_header.txt')): 2756 self.banner.add(pjoin(self.me_dir, 'Cards','delphes_card.dat')) 2757 if not delphes3: 2758 self.banner.add(pjoin(self.me_dir, 'Cards','delphes_trigger.dat')) 2759 self.banner.write(pjoin(self.me_dir, 'Events', self.run_name, '%s_%s_banner.txt' % (self.run_name, tag))) 2760 2761 cross = self.results[self.run_name].get_current_info()['cross'] 2762 2763 delphes_log = pjoin(self.me_dir, 'Events', self.run_name, "%s_delphes.log" % tag) 2764 self.cluster.launch_and_wait(prog, 2765 argument= [delphes_dir, self.run_name, tag, str(cross), filepath], 2766 stdout=delphes_log, stderr=subprocess.STDOUT, 2767 cwd=pjoin(self.me_dir,'Events')) 2768 2769 if not os.path.exists(pjoin(self.me_dir, 'Events', 2770 self.run_name, '%s_delphes_events.lhco.gz' % tag))\ 2771 and not os.path.exists(pjoin(self.me_dir, 'Events', 2772 self.run_name, '%s_delphes_events.lhco' % tag)): 2773 logger.info('If you are interested in lhco output. please run root2lhco converter.') 2774 logger.info(' or edit bin/internal/run_delphes3 to run the converter automatically.') 2775 2776 2777 #eradir = self.options['exrootanalysis_path'] 2778 madir = self.options['madanalysis_path'] 2779 td = self.options['td_path'] 2780 2781 if os.path.exists(pjoin(self.me_dir, 'Events', 2782 self.run_name, '%s_delphes_events.lhco' % tag)): 2783 # Creating plots 2784 self.create_plot('Delphes') 2785 2786 if os.path.exists(pjoin(self.me_dir, 'Events', self.run_name, '%s_delphes_events.lhco' % tag)): 2787 misc.gzip(pjoin(self.me_dir, 'Events', self.run_name, '%s_delphes_events.lhco' % tag)) 2788 2789 self.update_status('delphes done', level='delphes', makehtml=False)
2790 2791 2792 ############################################################################
2793 - def get_pid_final_initial_states(self):
2794 """Find the pid of all particles in the final and initial states""" 2795 pids = set() 2796 subproc = [l.strip() for l in open(pjoin(self.me_dir,'SubProcesses', 2797 'subproc.mg'))] 2798 nb_init = self.ninitial 2799 pat = re.compile(r'''DATA \(IDUP\(I,\d+\),I=1,\d+\)/([\+\-\d,\s]*)/''', re.I) 2800 for Pdir in subproc: 2801 text = open(pjoin(self.me_dir, 'SubProcesses', Pdir, 'born_leshouche.inc')).read() 2802 group = pat.findall(text) 2803 for particles in group: 2804 particles = particles.split(',') 2805 pids.update(set(particles)) 2806 2807 return pids
2808 2809 ############################################################################
2810 - def get_pdf_input_filename(self):
2811 """return the name of the file which is used by the pdfset""" 2812 2813 if self.options["cluster_local_path"] and \ 2814 os.path.exists(self.options["cluster_local_path"]) and \ 2815 self.options['run_mode'] ==1: 2816 # no need to transfer the pdf. 2817 return '' 2818 2819 def check_cluster(path): 2820 if not self.options["cluster_local_path"] or \ 2821 os.path.exists(self.options["cluster_local_path"]) or\ 2822 self.options['run_mode'] !=1: 2823 return path 2824 main = self.options["cluster_local_path"] 2825 if os.path.isfile(path): 2826 filename = os.path.basename(path) 2827 possible_path = [pjoin(main, filename), 2828 pjoin(main, "lhadpf", filename), 2829 pjoin(main, "Pdfdata", filename)] 2830 if any(os.path.exists(p) for p in possible_path): 2831 return " " 2832 else: 2833 return path
2834 2835 2836 if hasattr(self, 'pdffile') and self.pdffile: 2837 return self.pdffile 2838 else: 2839 for line in open(pjoin(self.me_dir,'Source','PDF','pdf_list.txt')): 2840 data = line.split() 2841 if len(data) < 4: 2842 continue 2843 if data[1].lower() == self.run_card['pdlabel'].lower(): 2844 self.pdffile = check_cluster(pjoin(self.me_dir, 'lib', 'Pdfdata', data[2])) 2845 return self.pdffile 2846 else: 2847 # possible when using lhapdf 2848 path = pjoin(self.me_dir, 'lib', 'PDFsets') 2849 if os.path.exists(path): 2850 self.pdffile = path 2851 else: 2852 self.pdffile = " " 2853 return self.pdffile 2854 2855 ############################################################################
2856 - def do_open(self, line):
2857 """Open a text file/ eps file / html file""" 2858 2859 args = self.split_arg(line) 2860 # Check Argument validity and modify argument to be the real path 2861 self.check_open(args) 2862 file_path = args[0] 2863 2864 misc.open_file(file_path)
2865 2866 ############################################################################
2867 - def do_set(self, line, log=True):
2868 """Set an option, which will be default for coming generations/outputs 2869 """ 2870 # cmd calls automaticaly post_set after this command. 2871 2872 2873 args = self.split_arg(line) 2874 # Check the validity of the arguments 2875 self.check_set(args) 2876 # Check if we need to save this in the option file 2877 if args[0] in self.options_configuration and '--no_save' not in args: 2878 self.do_save('options --auto') 2879 2880 if args[0] == "stdout_level": 2881 if args[1].isdigit(): 2882 logging.root.setLevel(int(args[1])) 2883 logging.getLogger('madgraph').setLevel(int(args[1])) 2884 else: 2885 logging.root.setLevel(eval('logging.' + args[1])) 2886 logging.getLogger('madgraph').setLevel(eval('logging.' + args[1])) 2887 if log: logger.info('set output information to level: %s' % args[1]) 2888 elif args[0] == "fortran_compiler": 2889 if args[1] == 'None': 2890 args[1] = None 2891 self.options['fortran_compiler'] = args[1] 2892 current = misc.detect_current_compiler(pjoin(self.me_dir,'Source','make_opts'), 'fortran') 2893 if current != args[1] and args[1] != None: 2894 misc.mod_compilator(self.me_dir, args[1], current, 'gfortran') 2895 elif args[0] == "cpp_compiler": 2896 if args[1] == 'None': 2897 args[1] = None 2898 self.options['cpp_compiler'] = args[1] 2899 current = misc.detect_current_compiler(pjoin(self.me_dir,'Source','make_opts'), 'cpp') 2900 if current != args[1] and args[1] != None: 2901 misc.mod_compilator(self.me_dir, args[1], current, 'cpp') 2902 elif args[0] == "run_mode": 2903 if not args[1] in [0,1,2,'0','1','2']: 2904 raise self.InvalidCmd, 'run_mode should be 0, 1 or 2.' 2905 self.cluster_mode = int(args[1]) 2906 self.options['run_mode'] = self.cluster_mode 2907 elif args[0] in ['cluster_type', 'cluster_queue', 'cluster_temp_path']: 2908 if args[1] == 'None': 2909 args[1] = None 2910 self.options[args[0]] = args[1] 2911 # cluster (re)-initialization done later 2912 # self.cluster update at the end of the routine 2913 elif args[0] in ['cluster_nb_retry', 'cluster_retry_wait', 'cluster_size']: 2914 self.options[args[0]] = int(args[1]) 2915 # self.cluster update at the end of the routine 2916 elif args[0] == 'nb_core': 2917 if args[1] == 'None': 2918 import multiprocessing 2919 self.nb_core = multiprocessing.cpu_count() 2920 self.options['nb_core'] = self.nb_core 2921 return 2922 if not args[1].isdigit(): 2923 raise self.InvalidCmd('nb_core should be a positive number') 2924 self.nb_core = int(args[1]) 2925 self.options['nb_core'] = self.nb_core 2926 elif args[0] == 'timeout': 2927 self.options[args[0]] = int(args[1]) 2928 elif args[0] == 'cluster_status_update': 2929 if '(' in args[1]: 2930 data = ' '.join([a for a in args[1:] if not a.startswith('-')]) 2931 data = data.replace('(','').replace(')','').replace(',',' ').split() 2932 first, second = data[:2] 2933 else: 2934 first, second = args[1:3] 2935 2936 self.options[args[0]] = (int(first), int(second)) 2937 elif args[0] == 'notification_center': 2938 if args[1] in ['None','True','False']: 2939 self.allow_notification_center = eval(args[1]) 2940 self.options[args[0]] = eval(args[1]) 2941 else: 2942 raise self.InvalidCmd('Not a valid value for notification_center') 2943 elif args[0] in self.options: 2944 if args[1] in ['None','True','False']: 2945 self.options[args[0]] = ast.literal_eval(args[1]) 2946 elif args[0].endswith('path'): 2947 if os.path.exists(args[1]): 2948 self.options[args[0]] = args[1] 2949 elif os.path.exists(pjoin(self.me_dir, args[1])): 2950 self.options[args[0]] = pjoin(self.me_dir, args[1]) 2951 else: 2952 raise self.InvalidCmd('Not a valid path: keep previous value: \'%s\'' % self.options[args[0]]) 2953 else: 2954 self.options[args[0]] = args[1]
2955
2956 - def post_set(self, stop, line):
2957 """Check if we need to save this in the option file""" 2958 try: 2959 args = self.split_arg(line) 2960 if 'cluster' in args[0] or args[0] == 'run_mode': 2961 self.configure_run_mode(self.options['run_mode']) 2962 2963 2964 # Check the validity of the arguments 2965 self.check_set(args) 2966 2967 if args[0] in self.options_configuration and '--no_save' not in args: 2968 self.exec_cmd('save options --auto') 2969 elif args[0] in self.options_madevent: 2970 logger.info('This option will be the default in any output that you are going to create in this session.') 2971 logger.info('In order to keep this changes permanent please run \'save options\'') 2972 return stop 2973 except self.InvalidCmd: 2974 return stop
2975
2976 - def configure_run_mode(self, run_mode):
2977 """change the way to submit job 0: single core, 1: cluster, 2: multicore""" 2978 2979 self.cluster_mode = run_mode 2980 self.options['run_mode'] = run_mode 2981 2982 if run_mode == 2: 2983 if not self.options['nb_core']: 2984 import multiprocessing 2985 self.options['nb_core'] = multiprocessing.cpu_count() 2986 nb_core = self.options['nb_core'] 2987 elif run_mode == 0: 2988 nb_core = 1 2989 2990 2991 2992 if run_mode in [0, 2]: 2993 self.cluster = cluster.MultiCore( 2994 **self.options) 2995 self.cluster.nb_core = nb_core 2996 #cluster_temp_path=self.options['cluster_temp_path'], 2997 2998 if self.cluster_mode == 1: 2999 opt = self.options 3000 cluster_name = opt['cluster_type'] 3001 if cluster_name in cluster.from_name: 3002 self.cluster = cluster.from_name[cluster_name](**opt) 3003 else: 3004 if MADEVENT and ('mg5_path' not in self.options or not self.options['mg5_path']): 3005 if not self.plugin_path: 3006 raise self.InvalidCmd('%s not native cluster type and no PLUGIN directory available') 3007 elif MADEVENT: 3008 mg5dir = self.options['mg5_path'] 3009 if mg5dir not in sys.path: 3010 sys.path.append(mg5dir) 3011 newpath = pjoin(mg5dir, 'PLUGIN') 3012 if newpath not in self.plugin_path: 3013 self.plugin_path.append(newpath) 3014 else: 3015 mg5dir = MG5DIR 3016 # Check if a plugin define this type of cluster 3017 # check for PLUGIN format 3018 for plugpath in self.plugin_path: 3019 plugindirname = os.path.basename(plugpath) 3020 for plug in os.listdir(plugpath): 3021 if os.path.exists(pjoin(plugpath, plug, '__init__.py')): 3022 try: 3023 __import__('%s.%s' % (plugindirname,plug)) 3024 except Exception: 3025 logger.critical('plugin directory %s/%s fail to be loaded. Please check it', plugindirname, plug) 3026 continue 3027 plugin = sys.modules['%s.%s' % (plugindirname,plug)] 3028 if not hasattr(plugin, 'new_cluster'): 3029 continue 3030 if not misc.is_plugin_supported(plugin): 3031 continue 3032 if cluster_name in plugin.new_cluster: 3033 logger.info("cluster handling will be done with PLUGIN: %s" % plug,'$MG:color:BLACK') 3034 self.cluster = plugin.new_cluster[cluster_name](**opt) 3035 break 3036 else: 3037 continue 3038 break 3039 else: 3040 raise self.InvalidCmd, "%s is not recognized as a supported cluster format." % cluster_name
3041 3042
3043 - def check_param_card(self, path, run=True, dependent=False):
3044 """ 3045 1) Check that no scan parameter are present 3046 2) Check that all the width are define in the param_card. 3047 - If a scan parameter is define. create the iterator and recall this fonction 3048 on the first element. 3049 - If some width are set on 'Auto', call the computation tools. 3050 3) if dependent is on True check for dependent parameter (automatic for scan)""" 3051 3052 pattern_scan = re.compile(r'''^(decay)?[\s\d]*scan''', re.I+re.M) 3053 pattern_width = re.compile(r'''decay\s+(\+?\-?\d+)\s+auto(@NLO|)''',re.I) 3054 text = open(path).read() 3055 3056 if pattern_scan.search(text): 3057 if not isinstance(self, cmd.CmdShell): 3058 # we are in web mode => forbid scan due to security risk 3059 raise Exception, "Scan are not allowed in web mode" 3060 # at least one scan parameter found. create an iterator to go trough the cards 3061 main_card = check_param_card.ParamCardIterator(text) 3062 self.param_card_iterator = main_card 3063 first_card = main_card.next(autostart=True) 3064 first_card.write(path) 3065 return self.check_param_card(path, run, dependent=True) 3066 3067 pdg_info = pattern_width.findall(text) 3068 if pdg_info: 3069 if run: 3070 logger.info('Computing the width set on auto in the param_card.dat') 3071 has_nlo = any(nlo.lower()=="@nlo" for _,nlo in pdg_info) 3072 pdg = [pdg for pdg,nlo in pdg_info] 3073 if not has_nlo: 3074 self.do_compute_widths('%s %s' % (' '.join(pdg), path)) 3075 else: 3076 self.do_compute_widths('%s %s --nlo' % (' '.join(pdg), path)) 3077 else: 3078 logger.info('''Some width are on Auto in the card. 3079 Those will be computed as soon as you have finish the edition of the cards. 3080 If you want to force the computation right now and being able to re-edit 3081 the cards afterwards, you can type \"compute_wdiths\".''') 3082 3083 if dependent: 3084 card = check_param_card.ParamCard(path) 3085 AskforEditCard.update_dependent(self, self.me_dir, card, path, timer=20) 3086 3087 return
3088
3089 - def add_error_log_in_html(self, errortype=None):
3090 """If a ME run is currently running add a link in the html output""" 3091 3092 # Be very carefull to not raise any error here (the traceback 3093 #will be modify in that case.) 3094 if hasattr(self, 'results') and hasattr(self.results, 'current') and\ 3095 self.results.current and 'run_name' in self.results.current and \ 3096 hasattr(self, 'me_dir'): 3097 name = self.results.current['run_name'] 3098 tag = self.results.current['tag'] 3099 self.debug_output = pjoin(self.me_dir, '%s_%s_debug.log' % (name,tag)) 3100 if errortype: 3101 self.results.current.debug = errortype 3102 else: 3103 self.results.current.debug = self.debug_output 3104 3105 else: 3106 #Force class default 3107 self.debug_output = CommonRunCmd.debug_output 3108 if os.path.exists('ME5_debug') and not 'ME5_debug' in self.debug_output: 3109 os.remove('ME5_debug') 3110 if not 'ME5_debug' in self.debug_output: 3111 os.system('ln -s %s ME5_debug &> /dev/null' % self.debug_output)
3112 3113
3114 - def do_quit(self, line):
3115 """Not in help: exit """ 3116 3117 if not self.force_run: 3118 try: 3119 os.remove(pjoin(self.me_dir,'RunWeb')) 3120 except Exception: 3121 pass 3122 try: 3123 self.store_result() 3124 except Exception: 3125 # If nothing runs they they are no result to update 3126 pass 3127 3128 try: 3129 self.update_status('', level=None) 3130 except Exception, error: 3131 pass 3132 devnull = open(os.devnull, 'w') 3133 try: 3134 misc.call(['./bin/internal/gen_cardhtml-pl'], cwd=self.me_dir, 3135 stdout=devnull, stderr=devnull) 3136 except Exception: 3137 pass 3138 devnull.close() 3139 3140 return super(CommonRunCmd, self).do_quit(line)
3141 3142 # Aliases 3143 do_EOF = do_quit 3144 do_exit = do_quit 3145 3146
3147 - def update_status(self, status, level, makehtml=True, force=True, 3148 error=False, starttime = None, update_results=True, 3149 print_log=True):
3150 """ update the index status """ 3151 3152 if makehtml and not force: 3153 if hasattr(self, 'next_update') and time.time() < self.next_update: 3154 return 3155 else: 3156 self.next_update = time.time() + 3 3157 3158 if print_log: 3159 if isinstance(status, str): 3160 if '<br>' not in status: 3161 logger.info(status) 3162 elif starttime: 3163 running_time = misc.format_timer(time.time()-starttime) 3164 logger.info(' Idle: %s, Running: %s, Completed: %s [ %s ]' % \ 3165 (status[0], status[1], status[2], running_time)) 3166 else: 3167 logger.info(' Idle: %s, Running: %s, Completed: %s' % status[:3]) 3168 3169 if isinstance(status, str) and status.startswith('\x1b['): 3170 status = status[status.index('m')+1:-7] 3171 if 'arXiv' in status: 3172 if '[' in status: 3173 status = status.split('[',1)[0] 3174 else: 3175 status = status.split('arXiv',1)[0] 3176 3177 if update_results: 3178 self.results.update(status, level, makehtml=makehtml, error=error)
3179 3180 ############################################################################
3181 - def keep_cards(self, need_card=[], ignore=[]):
3182 """Ask the question when launching generate_events/multi_run""" 3183 3184 check_card = ['pythia_card.dat', 'pgs_card.dat','delphes_card.dat', 3185 'delphes_trigger.dat', 'madspin_card.dat', 'shower_card.dat', 3186 'reweight_card.dat','pythia8_card.dat', 3187 'madanalysis5_parton_card.dat','madanalysis5_hadron_card.dat', 3188 'plot_card.dat'] 3189 3190 cards_path = pjoin(self.me_dir,'Cards') 3191 for card in check_card: 3192 if card in ignore or (ignore == ['*'] and card not in need_card): 3193 continue 3194 if card not in need_card: 3195 if os.path.exists(pjoin(cards_path, card)): 3196 files.mv(pjoin(cards_path, card), pjoin(cards_path, '.%s' % card)) 3197 else: 3198 if not os.path.exists(pjoin(cards_path, card)): 3199 if os.path.exists(pjoin(cards_path, '.%s' % card)): 3200 files.mv(pjoin(cards_path, '.%s' % card), pjoin(cards_path, card)) 3201 else: 3202 default = card.replace('.dat', '_default.dat') 3203 files.cp(pjoin(cards_path, default),pjoin(cards_path, card))
3204 3205 ############################################################################
3206 - def set_configuration(self, config_path=None, final=True, initdir=None, amcatnlo=False):
3207 """ assign all configuration variable from file 3208 ./Cards/mg5_configuration.txt. assign to default if not define """ 3209 3210 if not hasattr(self, 'options') or not self.options: 3211 self.options = dict(self.options_configuration) 3212 self.options.update(self.options_madgraph) 3213 self.options.update(self.options_madevent) 3214 3215 if not config_path: 3216 if os.environ.has_key('MADGRAPH_BASE'): 3217 config_path = pjoin(os.environ['MADGRAPH_BASE'],'mg5_configuration.txt') 3218 self.set_configuration(config_path=config_path, final=False) 3219 if 'HOME' in os.environ: 3220 config_path = pjoin(os.environ['HOME'],'.mg5', 3221 'mg5_configuration.txt') 3222 if os.path.exists(config_path): 3223 self.set_configuration(config_path=config_path, final=False) 3224 if amcatnlo: 3225 me5_config = pjoin(self.me_dir, 'Cards', 'amcatnlo_configuration.txt') 3226 else: 3227 me5_config = pjoin(self.me_dir, 'Cards', 'me5_configuration.txt') 3228 self.set_configuration(config_path=me5_config, final=False, initdir=self.me_dir) 3229 3230 if self.options.has_key('mg5_path') and self.options['mg5_path']: 3231 MG5DIR = self.options['mg5_path'] 3232 config_file = pjoin(MG5DIR, 'input', 'mg5_configuration.txt') 3233 self.set_configuration(config_path=config_file, final=False,initdir=MG5DIR) 3234 else: 3235 self.options['mg5_path'] = None 3236 return self.set_configuration(config_path=me5_config, final=final,initdir=self.me_dir) 3237 3238 config_file = open(config_path) 3239 3240 # read the file and extract information 3241 logger.info('load configuration from %s ' % config_file.name) 3242 for line in config_file: 3243 3244 if '#' in line: 3245 line = line.split('#',1)[0] 3246 line = line.replace('\n','').replace('\r\n','') 3247 try: 3248 name, value = line.split('=') 3249 except ValueError: 3250 pass 3251 else: 3252 name = name.strip() 3253 value = value.strip() 3254 if name.endswith('_path') and not name.startswith('cluster'): 3255 path = value 3256 if os.path.isdir(path): 3257 self.options[name] = os.path.realpath(path) 3258 continue 3259 if not initdir: 3260 continue 3261 path = pjoin(initdir, value) 3262 if os.path.isdir(path): 3263 self.options[name] = os.path.realpath(path) 3264 continue 3265 else: 3266 self.options[name] = value 3267 if value.lower() == "none": 3268 self.options[name] = None 3269 3270 if not final: 3271 return self.options # the return is usefull for unittest 3272 3273 # Treat each expected input 3274 # delphes/pythia/... path 3275 for key in self.options: 3276 # Final cross check for the path 3277 if key.endswith('path') and not key.startswith("cluster"): 3278 path = self.options[key] 3279 if path is None: 3280 continue 3281 if os.path.isdir(path): 3282 self.options[key] = os.path.realpath(path) 3283 continue 3284 path = pjoin(self.me_dir, self.options[key]) 3285 if os.path.isdir(path): 3286 self.options[key] = os.path.realpath(path) 3287 continue 3288 elif self.options.has_key('mg5_path') and self.options['mg5_path']: 3289 path = pjoin(self.options['mg5_path'], self.options[key]) 3290 if os.path.isdir(path): 3291 self.options[key] = os.path.realpath(path) 3292 continue 3293 self.options[key] = None 3294 elif key.startswith('cluster') and key != 'cluster_status_update': 3295 if key in ('cluster_nb_retry','cluster_wait_retry'): 3296 self.options[key] = int(self.options[key]) 3297 if hasattr(self,'cluster'): 3298 del self.cluster 3299 pass 3300 elif key == 'automatic_html_opening': 3301 if self.options[key] in ['False', 'True']: 3302 self.options[key] =ast.literal_eval(self.options[key]) 3303 elif key == "notification_center": 3304 if self.options[key] in ['False', 'True']: 3305 self.allow_notification_center =ast.literal_eval(self.options[key]) 3306 self.options[key] =ast.literal_eval(self.options[key]) 3307 elif key not in ['text_editor','eps_viewer','web_browser','stdout_level', 3308 'complex_mass_scheme', 'gauge', 'group_subprocesses']: 3309 # Default: try to set parameter 3310 try: 3311 self.do_set("%s %s --no_save" % (key, self.options[key]), log=False) 3312 except self.InvalidCmd: 3313 logger.warning("Option %s from config file not understood" \ 3314 % key) 3315 3316 # Configure the way to open a file: 3317 misc.open_file.configure(self.options) 3318 self.configure_run_mode(self.options['run_mode']) 3319 return self.options
3320 3321 @staticmethod
3322 - def find_available_run_name(me_dir):
3323 """ find a valid run_name for the current job """ 3324 3325 name = 'run_%02d' 3326 data = [int(s[4:j]) for s in os.listdir(pjoin(me_dir,'Events')) for 3327 j in range(4,len(s)+1) if \ 3328 s.startswith('run_') and s[4:j].isdigit()] 3329 return name % (max(data+[0])+1)
3330 3331 3332 ############################################################################
3333 - def do_decay_events(self,line):
3334 """Require MG5 directory: decay events with spin correlations 3335 """ 3336 3337 if '-from_cards' in line and not os.path.exists(pjoin(self.me_dir, 'Cards', 'madspin_card.dat')): 3338 return 3339 3340 # First need to load MadSpin 3341 3342 # Check that MG5 directory is present . 3343 if MADEVENT and not self.options['mg5_path']: 3344 raise self.InvalidCmd, '''The module decay_events requires that MG5 is installed on the system. 3345 You can install it and set its path in ./Cards/me5_configuration.txt''' 3346 elif MADEVENT: 3347 sys.path.append(self.options['mg5_path']) 3348 try: 3349 import MadSpin.decay as decay 3350 import MadSpin.interface_madspin as interface_madspin 3351 except ImportError: 3352 if __debug__: 3353 raise 3354 else: 3355 raise self.ConfigurationError, '''Can\'t load MadSpin 3356 The variable mg5_path might not be correctly configured.''' 3357 3358 self.update_status('Running MadSpin', level='madspin') 3359 if not '-from_cards' in line: 3360 self.keep_cards(['madspin_card.dat'], ignore=['*']) 3361 self.ask_edit_cards(['madspin_card.dat'], 'fixed', plot=False) 3362 self.help_decay_events(skip_syntax=True) 3363 3364 # load the name of the event file 3365 args = self.split_arg(line) 3366 self.check_decay_events(args) 3367 # args now alway content the path to the valid files 3368 madspin_cmd = interface_madspin.MadSpinInterface(args[0]) 3369 madspin_cmd.update_status = lambda *x,**opt: self.update_status(*x, level='madspin',**opt) 3370 3371 path = pjoin(self.me_dir, 'Cards', 'madspin_card.dat') 3372 3373 madspin_cmd.import_command_file(path) 3374 3375 # create a new run_name directory for this output 3376 i = 1 3377 while os.path.exists(pjoin(self.me_dir,'Events', '%s_decayed_%i' % (self.run_name,i))): 3378 i+=1 3379 new_run = '%s_decayed_%i' % (self.run_name,i) 3380 evt_dir = pjoin(self.me_dir, 'Events') 3381 3382 os.mkdir(pjoin(evt_dir, new_run)) 3383 current_file = args[0].replace('.lhe', '_decayed.lhe') 3384 new_file = pjoin(evt_dir, new_run, os.path.basename(args[0])) 3385 if not os.path.exists(current_file): 3386 if os.path.exists(current_file+'.gz'): 3387 current_file += '.gz' 3388 new_file += '.gz' 3389 else: 3390 logger.error('MadSpin fails to create any decayed file.') 3391 return 3392 3393 files.mv(current_file, new_file) 3394 logger.info("The decayed event file has been moved to the following location: ") 3395 logger.info(new_file) 3396 3397 if hasattr(self, 'results'): 3398 current = self.results.current 3399 nb_event = self.results.current['nb_event'] 3400 if not nb_event: 3401 current = self.results[self.run_name][0] 3402 nb_event = current['nb_event'] 3403 3404 cross = current['cross'] 3405 error = current['error'] 3406 self.results.add_run( new_run, self.run_card) 3407 self.results.add_detail('nb_event', int(nb_event*madspin_cmd.efficiency)) 3408 self.results.add_detail('cross', madspin_cmd.cross)#cross * madspin_cmd.branching_ratio) 3409 self.results.add_detail('error', madspin_cmd.error+ cross * madspin_cmd.err_branching_ratio) 3410 self.results.add_detail('run_mode', current['run_mode']) 3411 3412 self.run_name = new_run 3413 self.banner = madspin_cmd.banner 3414 self.banner.add(path) 3415 self.banner.write(pjoin(self.me_dir,'Events',self.run_name, '%s_%s_banner.txt' % 3416 (self.run_name, self.run_tag))) 3417 self.update_status('MadSpin Done', level='parton', makehtml=False) 3418 if 'unweighted' in os.path.basename(args[0]): 3419 self.create_plot('parton')
3420
3421 - def complete_decay_events(self, text, line, begidx, endidx):
3422 args = self.split_arg(line[0:begidx], error=False) 3423 if len(args) == 1: 3424 return self.complete_plot(text, line, begidx, endidx) 3425 else: 3426 return
3427
3428 - def complete_print_results(self,text, line, begidx, endidx):
3429 "Complete the print results command" 3430 args = self.split_arg(line[0:begidx], error=False) 3431 if len(args) == 1: 3432 #return valid run_name 3433 data = misc.glob(pjoin('*','unweighted_events.lhe.gz'), 3434 pjoin(self.me_dir, 'Events')) 3435 3436 data = [n.rsplit('/',2)[1] for n in data] 3437 tmp1 = self.list_completion(text, data) 3438 return tmp1 3439 else: 3440 data = misc.glob('*_pythia_events.hep.gz', pjoin(self.me_dir, 'Events', args[0])) 3441 data = [os.path.basename(p).rsplit('_',1)[0] for p in data] 3442 data += ["--mode=a", "--mode=w", "--path=", "--format=short"] 3443 tmp1 = self.list_completion(text, data) 3444 return tmp1
3445
3446 - def help_print_result(self):
3447 logger.info("syntax: print_result [RUN] [TAG] [options]") 3448 logger.info("-- show in text format the status of the run (cross-section/nb-event/...)") 3449 logger.info("--path= defines the path of the output file.") 3450 logger.info("--mode=a allow to add the information at the end of the file.") 3451 logger.info("--format=short (only if --path is define)") 3452 logger.info(" allows to have a multi-column output easy to parse")
3453 3454 ############################################################################
3455 - def do_check_events(self, line):
3456 """ Run some sanity check on the generated events.""" 3457 3458 # Check that MG5 directory is present . 3459 if MADEVENT and not self.options['mg5_path']: 3460 raise self.InvalidCmd, '''The module reweight requires that MG5 is installed on the system. 3461 You can install it and set its path in ./Cards/me5_configuration.txt''' 3462 elif MADEVENT: 3463 sys.path.append(self.options['mg5_path']) 3464 try: 3465 import madgraph.interface.reweight_interface as reweight_interface 3466 except ImportError: 3467 raise self.ConfigurationError, '''Can\'t load Reweight module. 3468 The variable mg5_path might not be correctly configured.''' 3469 3470 3471 # load the name of the event file 3472 args = self.split_arg(line) 3473 self.check_check_events(args) 3474 # args now alway content the path to the valid files 3475 reweight_cmd = reweight_interface.ReweightInterface(args[0], allow_madspin=True) 3476 reweight_cmd.mother = self 3477 self.update_status('Running check on events', level='check') 3478 3479 reweight_cmd.check_events()
3480 3481 ############################################################################
3482 - def complete_check_events(self, text, line, begidx, endidx):
3483 args = self.split_arg(line[0:begidx], error=False) 3484 3485 if len(args) == 1 and os.path.sep not in text: 3486 #return valid run_name 3487 data = misc.glob(pjoin('*','*events.lhe*'), pjoin(self.me_dir, 'Events')) 3488 data = [n.rsplit('/',2)[1] for n in data] 3489 return self.list_completion(text, data, line) 3490 else: 3491 return self.path_completion(text, 3492 os.path.join('.',*[a for a in args \ 3493 if a.endswith(os.path.sep)]))
3494
3495 - def complete_reweight(self,text, line, begidx, endidx):
3496 "Complete the pythia command" 3497 args = self.split_arg(line[0:begidx], error=False) 3498 3499 #return valid run_name 3500 data = misc.glob(pjoin('*','*events.lhe*'), pjoin(self.me_dir, 'Events')) 3501 data = list(set([n.rsplit('/',2)[1] for n in data])) 3502 if not '-f' in args: 3503 data.append('-f') 3504 tmp1 = self.list_completion(text, data) 3505 return tmp1
3506 3507 3508
3509 - def complete_compute_widths(self, text, line, begidx, endidx, formatting=True):
3510 "Complete the compute_widths command" 3511 3512 args = self.split_arg(line[0:begidx]) 3513 3514 if args[-1] in ['--path=', '--output=']: 3515 completion = {'path': self.path_completion(text)} 3516 elif line[begidx-1] == os.path.sep: 3517 current_dir = pjoin(*[a for a in args if a.endswith(os.path.sep)]) 3518 if current_dir.startswith('--path='): 3519 current_dir = current_dir[7:] 3520 if current_dir.startswith('--output='): 3521 current_dir = current_dir[9:] 3522 completion = {'path': self.path_completion(text, current_dir)} 3523 else: 3524 completion = {} 3525 completion['options'] = self.list_completion(text, 3526 ['--path=', '--output=', '--min_br=0.\$', '--nlo', 3527 '--precision_channel=0.\$', '--body_decay=']) 3528 3529 return self.deal_multiple_categories(completion, formatting)
3530 3531
3532 - def update_make_opts(self):
3533 """update the make_opts file writing the environmental variables 3534 stored in make_opts_var""" 3535 make_opts = os.path.join(self.me_dir, 'Source', 'make_opts') 3536 3537 # Set some environment variables common to all interfaces 3538 if not hasattr(self,'options') or not 'pythia8_path' in self.options or \ 3539 not self.options['pythia8_path'] or \ 3540 not os.path.isfile(pjoin(self.options['pythia8_path'],'bin','pythia8-config')): 3541 self.make_opts_var['PYTHIA8_PATH']='NotInstalled' 3542 else: 3543 self.make_opts_var['PYTHIA8_PATH']=self.options['pythia8_path'] 3544 3545 self.make_opts_var['MG5AMC_VERSION'] = misc.get_pkg_info()['version'] 3546 3547 return self.update_make_opts_full(make_opts, self.make_opts_var)
3548 3549 @staticmethod
3550 - def update_make_opts_full(path, def_variables, keep_old=True):
3551 """update the make_opts file writing the environmental variables 3552 of def_variables. 3553 if a value of the dictionary is None then it is not written. 3554 """ 3555 make_opts = path 3556 pattern = re.compile(r'^(\w+)\s*=\s*(.*)$',re.DOTALL) 3557 diff = False # set to True if one varible need to be updated 3558 #if on False the file is not modify 3559 3560 tag = '#end_of_make_opts_variables\n' 3561 make_opts_variable = True # flag to say if we are in edition area or not 3562 content = [] 3563 variables = dict(def_variables) 3564 need_keys = variables.keys() 3565 for line in open(make_opts): 3566 line = line.strip() 3567 if make_opts_variable: 3568 if line.startswith('#') or not line: 3569 if line.startswith('#end_of_make_opts_variables'): 3570 make_opts_variable = False 3571 continue 3572 elif pattern.search(line): 3573 key, value = pattern.search(line).groups() 3574 if key not in variables: 3575 variables[key] = value 3576 elif value != variables[key]: 3577 diff=True 3578 else: 3579 need_keys.remove(key) 3580 else: 3581 make_opts_variable = False 3582 content.append(line) 3583 else: 3584 content.append(line) 3585 3586 if need_keys: 3587 diff=True #This means that new definition are added to the file. 3588 3589 content_variables = '\n'.join('%s=%s' % (k,v) for k, v in variables.items() if v is not None) 3590 content_variables += '\n%s' % tag 3591 3592 if diff: 3593 with open(make_opts, 'w') as fsock: 3594 fsock.write(content_variables + '\n'.join(content)) 3595 return
3596 3597 3598 # lhapdf-related functions 3627 3628
3629 - def get_characteristics(self, path=None):
3630 """reads the proc_characteristics file and initialises the correspondant 3631 dictionary""" 3632 3633 if not path: 3634 path = os.path.join(self.me_dir, 'SubProcesses', 'proc_characteristics') 3635 3636 self.proc_characteristics = banner_mod.ProcCharacteristic(path) 3637 return self.proc_characteristics
3638 3639
3640 - def copy_lhapdf_set(self, lhaid_list, pdfsets_dir):
3641 """copy (if needed) the lhapdf set corresponding to the lhaid in lhaid_list 3642 into lib/PDFsets""" 3643 3644 if not hasattr(self, 'lhapdf_pdfsets'): 3645 self.lhapdf_pdfsets = self.get_lhapdf_pdfsets_list(pdfsets_dir) 3646 3647 pdfsetname=set() 3648 for lhaid in lhaid_list: 3649 if isinstance(lhaid, str) and lhaid.isdigit(): 3650 lhaid = int(lhaid) 3651 if isinstance(lhaid, (int,float)): 3652 try: 3653 if lhaid in self.lhapdf_pdfsets: 3654 pdfsetname.add(self.lhapdf_pdfsets[lhaid]['filename']) 3655 else: 3656 raise MadGraph5Error('lhaid %s not valid input number for the current lhapdf' % lhaid ) 3657 except KeyError: 3658 if self.lhapdf_version.startswith('5'): 3659 raise MadGraph5Error(\ 3660 ('invalid lhaid set in th run_card: %d .\nPlease note that some sets' % lhaid) + \ 3661 '(eg MSTW 90%CL error sets) \nare not available in aMC@NLO + LHAPDF 5.x.x') 3662 else: 3663 logger.debug('%d not found in pdfsets.index' % lhaid) 3664 else: 3665 pdfsetname.add(lhaid) 3666 3667 # check if the file exists, otherwise install it: 3668 # also check that the PDFsets dir exists, otherwise create it. 3669 # if fails, install the lhapdfset into lib/PDFsets 3670 if not os.path.isdir(pdfsets_dir): 3671 try: 3672 os.mkdir(pdfsets_dir) 3673 except OSError: 3674 pdfsets_dir = pjoin(self.me_dir, 'lib', 'PDFsets') 3675 elif os.path.exists(pjoin(self.me_dir, 'lib', 'PDFsets')): 3676 #clean previous set of pdf used 3677 for name in os.listdir(pjoin(self.me_dir, 'lib', 'PDFsets')): 3678 if name not in pdfsetname: 3679 try: 3680 if os.path.isdir(pjoin(self.me_dir, 'lib', 'PDFsets', name)): 3681 shutil.rmtree(pjoin(self.me_dir, 'lib', 'PDFsets', name)) 3682 else: 3683 os.remove(pjoin(self.me_dir, 'lib', 'PDFsets', name)) 3684 except Exception, error: 3685 logger.debug('%s', error) 3686 3687 if self.options["cluster_local_path"]: 3688 lhapdf_cluster_possibilities = [self.options["cluster_local_path"], 3689 pjoin(self.options["cluster_local_path"], "lhapdf"), 3690 pjoin(self.options["cluster_local_path"], "lhapdf", "pdfsets"), 3691 pjoin(self.options["cluster_local_path"], "..", "lhapdf"), 3692 pjoin(self.options["cluster_local_path"], "..", "lhapdf", "pdfsets"), 3693 pjoin(self.options["cluster_local_path"], "..", "lhapdf","pdfsets", "6.1") 3694 ] 3695 else: 3696 lhapdf_cluster_possibilities = [] 3697 3698 for pdfset in pdfsetname: 3699 # Check if we need to copy the pdf 3700 if self.options["cluster_local_path"] and self.options["run_mode"] == 1 and \ 3701 any((os.path.exists(pjoin(d, pdfset)) for d in lhapdf_cluster_possibilities)): 3702 3703 os.environ["LHAPATH"] = [d for d in lhapdf_cluster_possibilities if os.path.exists(pjoin(d, pdfset))][0] 3704 os.environ["CLUSTER_LHAPATH"] = os.environ["LHAPATH"] 3705 # no need to copy it 3706 if os.path.exists(pjoin(pdfsets_dir, pdfset)): 3707 try: 3708 if os.path.isdir(pjoin(pdfsets_dir, name)): 3709 shutil.rmtree(pjoin(pdfsets_dir, name)) 3710 else: 3711 os.remove(pjoin(pdfsets_dir, name)) 3712 except Exception, error: 3713 logger.debug('%s', error) 3714 3715 #check that the pdfset is not already there 3716 elif not os.path.exists(pjoin(self.me_dir, 'lib', 'PDFsets', pdfset)) and \ 3717 not os.path.isdir(pjoin(self.me_dir, 'lib', 'PDFsets', pdfset)): 3718 3719 if pdfset and not os.path.exists(pjoin(pdfsets_dir, pdfset)): 3720 self.install_lhapdf_pdfset(pdfsets_dir, pdfset) 3721 3722 if os.path.exists(pjoin(pdfsets_dir, pdfset)): 3723 files.cp(pjoin(pdfsets_dir, pdfset), pjoin(self.me_dir, 'lib', 'PDFsets')) 3724 elif os.path.exists(pjoin(os.path.dirname(pdfsets_dir), pdfset)): 3725 files.cp(pjoin(os.path.dirname(pdfsets_dir), pdfset), pjoin(self.me_dir, 'lib', 'PDFsets'))
3726
3727 - def install_lhapdf_pdfset(self, pdfsets_dir, filename):
3728 """idownloads and install the pdfset filename in the pdfsets_dir""" 3729 lhapdf_version = self.get_lhapdf_version() 3730 local_path = pjoin(self.me_dir, 'lib', 'PDFsets') 3731 return self.install_lhapdf_pdfset_static(self.options['lhapdf'], 3732 pdfsets_dir, filename, 3733 lhapdf_version=lhapdf_version, 3734 alternate_path=local_path)
3735 3736 3737 @staticmethod
3738 - def install_lhapdf_pdfset_static(lhapdf_config, pdfsets_dir, filename, 3739 lhapdf_version=None, alternate_path=None):
3740 """idownloads and install the pdfset filename in the pdfsets_dir. 3741 Version which can be used independently of the class. 3742 local path is used if the global installation fails. 3743 """ 3744 3745 if not lhapdf_version: 3746 lhapdf_version = subprocess.Popen([lhapdf_config, '--version'], 3747 stdout = subprocess.PIPE).stdout.read().strip() 3748 if not pdfsets_dir: 3749 pdfsets_dir = subprocess.Popen([lhapdf_config, '--datadir'], 3750 stdout = subprocess.PIPE).stdout.read().strip() 3751 3752 if isinstance(filename, int): 3753 pdf_info = CommonRunCmd.get_lhapdf_pdfsets_list_static(pdfsets_dir, lhapdf_version) 3754 filename = pdf_info[filename]['filename'] 3755 3756 if os.path.exists(pjoin(pdfsets_dir, filename)): 3757 logger.debug('%s is already present in %s', filename, pdfsets_dir) 3758 return 3759 3760 logger.info('Trying to download %s' % filename) 3761 3762 if lhapdf_version.startswith('5.'): 3763 3764 # use the lhapdf-getdata command, which is in the same path as 3765 # lhapdf-config 3766 getdata = lhapdf_config.replace('lhapdf-config', ('lhapdf-getdata')) 3767 misc.call([getdata, filename], cwd = pdfsets_dir) 3768 3769 elif lhapdf_version.startswith('6.'): 3770 # use the "lhapdf install xxx" command, which is in the same path as 3771 # lhapdf-config 3772 getdata = lhapdf_config.replace('lhapdf-config', ('lhapdf')) 3773 3774 misc.call([getdata, 'install', filename], cwd = pdfsets_dir) 3775 3776 else: 3777 raise MadGraph5Error('Not valid LHAPDF version: %s' % lhapdf_version) 3778 3779 # check taht the file has been installed in the global dir 3780 if os.path.exists(pjoin(pdfsets_dir, filename)) or \ 3781 os.path.isdir(pjoin(pdfsets_dir, filename)): 3782 logger.info('%s successfully downloaded and stored in %s' \ 3783 % (filename, pdfsets_dir)) 3784 #otherwise (if v5) save it locally 3785 elif lhapdf_version.startswith('5.'): 3786 logger.warning('Could not download %s into %s. Trying to save it locally' \ 3787 % (filename, pdfsets_dir)) 3788 CommonRunCmd.install_lhapdf_pdfset_static(lhapdf_config, alternate_path, filename, 3789 lhapdf_version=lhapdf_version) 3790 elif lhapdf_version.startswith('6.') and '.LHgrid' in filename: 3791 logger.info('Could not download %s: Try %s', filename, filename.replace('.LHgrid','')) 3792 return CommonRunCmd.install_lhapdf_pdfset_static(lhapdf_config, pdfsets_dir, 3793 filename.replace('.LHgrid',''), 3794 lhapdf_version, alternate_path) 3795 3796 else: 3797 raise MadGraph5Error, \ 3798 'Could not download %s into %s. Please try to install it manually.' \ 3799 % (filename, pdfsets_dir)
3800 3801 3802
3803 - def get_lhapdf_pdfsets_list(self, pdfsets_dir):
3804 """read the PDFsets.index file, which should be located in the same 3805 place as pdfsets_dir, and return a list of dictionaries with the information 3806 about each pdf set""" 3807 lhapdf_version = self.get_lhapdf_version() 3808 return self.get_lhapdf_pdfsets_list_static(pdfsets_dir, lhapdf_version)
3809 3810 @staticmethod
3811 - def get_lhapdf_pdfsets_list_static(pdfsets_dir, lhapdf_version):
3812 3813 if lhapdf_version.startswith('5.'): 3814 if os.path.exists('%s.index' % pdfsets_dir): 3815 indexfile = '%s.index' % pdfsets_dir 3816 else: 3817 raise MadGraph5Error, 'index of lhapdf file not found' 3818 pdfsets_lines = \ 3819 [l for l in open(indexfile).read().split('\n') if l.strip() and \ 3820 not '90cl' in l] 3821 lhapdf_pdfsets = dict( (int(l.split()[0]), {'lhaid': int(l.split()[0]), 3822 'pdflib_ntype': int(l.split()[1]), 3823 'pdflib_ngroup': int(l.split()[2]), 3824 'pdflib_nset': int(l.split()[3]), 3825 'filename': l.split()[4], 3826 'lhapdf_nmem': int(l.split()[5]), 3827 'q2min': float(l.split()[6]), 3828 'q2max': float(l.split()[7]), 3829 'xmin': float(l.split()[8]), 3830 'xmax': float(l.split()[9]), 3831 'description': l.split()[10]}) \ 3832 for l in pdfsets_lines) 3833 3834 elif lhapdf_version.startswith('6.'): 3835 pdfsets_lines = \ 3836 [l for l in open(pjoin(pdfsets_dir, 'pdfsets.index')).read().split('\n') if l.strip()] 3837 lhapdf_pdfsets = dict( (int(l.split()[0]), 3838 {'lhaid': int(l.split()[0]), 3839 'filename': l.split()[1]}) \ 3840 for l in pdfsets_lines) 3841 3842 else: 3843 raise MadGraph5Error('Not valid LHAPDF version: %s' % lhapdf_version) 3844 3845 return lhapdf_pdfsets
3846 3847
3848 - def get_lhapdf_version(self):
3849 """returns the lhapdf version number""" 3850 if not hasattr(self, 'lhapdfversion'): 3851 try: 3852 self.lhapdf_version = \ 3853 subprocess.Popen([self.options['lhapdf'], '--version'], 3854 stdout = subprocess.PIPE).stdout.read().strip() 3855 except OSError, error: 3856 if error.errno == 2: 3857 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'] 3858 else: 3859 raise 3860 3861 # this will be removed once some issues in lhapdf6 will be fixed 3862 if self.lhapdf_version.startswith('6.0'): 3863 raise MadGraph5Error('LHAPDF 6.0.x not supported. Please use v6.1 or later') 3864 3865 return self.lhapdf_version
3866 3867
3868 - def get_lhapdf_pdfsetsdir(self):
3869 lhapdf_version = self.get_lhapdf_version() 3870 3871 # check if the LHAPDF_DATA_PATH variable is defined 3872 if 'LHAPDF_DATA_PATH' in os.environ.keys() and os.environ['LHAPDF_DATA_PATH']: 3873 datadir = os.environ['LHAPDF_DATA_PATH'] 3874 3875 elif lhapdf_version.startswith('5.'): 3876 datadir = subprocess.Popen([self.options['lhapdf'], '--pdfsets-path'], 3877 stdout = subprocess.PIPE).stdout.read().strip() 3878 3879 elif lhapdf_version.startswith('6.'): 3880 datadir = subprocess.Popen([self.options['lhapdf'], '--datadir'], 3881 stdout = subprocess.PIPE).stdout.read().strip() 3882 3883 return datadir
3884
3885 - def get_lhapdf_libdir(self):
3886 lhapdf_version = self.get_lhapdf_version() 3887 3888 if lhapdf_version.startswith('5.'): 3889 libdir = subprocess.Popen([self.options['lhapdf-config'], '--libdir'], 3890 stdout = subprocess.PIPE).stdout.read().strip() 3891 3892 elif lhapdf_version.startswith('6.'): 3893 libdir = subprocess.Popen([self.options['lhapdf'], '--libs'], 3894 stdout = subprocess.PIPE).stdout.read().strip() 3895 3896 return libdir
3897
3898 -class AskforEditCard(cmd.OneLinePathCompletion):
3899 """A class for asking a question where in addition you can have the 3900 set command define and modifying the param_card/run_card correctly""" 3901 3902 all_card_name = ['param_card', 'run_card', 'pythia_card', 'pythia8_card', 3903 'madweight_card', 'MadLoopParams', 'shower_card'] 3904 3905 special_shortcut = {'ebeam':([float],['run_card ebeam1 %(0)s', 'run_card ebeam2 %(0)s']), 3906 'lpp': ([int],['run_card lpp1 %(0)s', 'run_card lpp2 %(0)s' ]), 3907 'lhc': ([int],['run_card lpp1 1', 'run_card lpp2 1', 'run_card ebeam1 %(0)s*1000/2', 'run_card ebeam2 %(0)s*1000/2']), 3908 'lep': ([int],['run_card lpp1 0', 'run_card lpp2 0', 'run_card ebeam1 %(0)s/2', 'run_card ebeam2 %(0)s/2']), 3909 'ilc': ([int],['run_card lpp1 0', 'run_card lpp2 0', 'run_card ebeam1 %(0)s/2', 'run_card ebeam2 %(0)s/2']), 3910 'lcc': ([int],['run_card lpp1 1', 'run_card lpp2 1', 'run_card ebeam1 %(0)s*1000/2', 'run_card ebeam2 %(0)s*1000/2']), 3911 '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']), 3912 'simplepy8':([],['pythia8_card hadronlevel:all False', 3913 'pythia8_card partonlevel:mpi False', 3914 'pythia8_card BeamRemnants:primordialKT False', 3915 'pythia8_card PartonLevel:Remnants False', 3916 'pythia8_card Check:event False', 3917 'pythia8_card TimeShower:QEDshowerByQ False', 3918 'pythia8_card TimeShower:QEDshowerByL False', 3919 'pythia8_card SpaceShower:QEDshowerByQ False', 3920 'pythia8_card SpaceShower:QEDshowerByL False', 3921 'pythia8_card PartonLevel:FSRinResonances False', 3922 'pythia8_card ProcessLevel:resonanceDecays False', 3923 ]), 3924 'mpi':([bool],['pythia8_card partonlevel:mpi %(0)s']) 3925 } 3926 3927 special_shortcut_help = { 3928 'ebeam' : 'syntax: set ebeam VALUE:\n This parameter sets the energy to both beam to the value in GeV', 3929 'lpp' : 'syntax: set ebeam VALUE:\n'+\ 3930 ' Set the type of beam to a given value for both beam\n'+\ 3931 ' 0 : means no PDF\n'+\ 3932 ' 1 : means proton PDF\n'+\ 3933 ' -1 : means antiproton PDF\n'+\ 3934 ' 2 : means PDF for elastic photon emited from a proton\n'+\ 3935 ' 3 : means PDF for elastic photon emited from an electron', 3936 'lhc' : 'syntax: set lhc VALUE:\n Set for a proton-proton collision with that given center of mass energy (in TeV)', 3937 'lep' : 'syntax: set lep VALUE:\n Set for a electron-positron collision with that given center of mass energy (in GeV)', 3938 'fixed_scale' : 'syntax: set fixed_scale VALUE:\n Set all scales to the give value (in GeV)', 3939 'simplepy8' : 'Turn off non-perturbative slow features of Pythia8.', 3940 'mpi' : 'syntax: set mpi value: allow to turn mpi in Pythia8 on/off' 3941 } 3942
3943 - def load_default(self):
3944 """ define all default variable. No load of card here. 3945 This allow to subclass this class and just change init and still have 3946 all variables defined.""" 3947 3948 self.me_dir = None 3949 self.param_card = None 3950 self.run_card = {} 3951 self.pname2block = {} 3952 self.conflict = [] 3953 self.restricted_value = {} 3954 self.mode = '' 3955 self.cards = [] 3956 self.run_set = [] 3957 self.has_mw = False 3958 self.has_ml = False 3959 self.has_shower = False 3960 self.has_PY8 = False 3961 self.paths = {}
3962 3963
3964 - def define_paths(self, **opt):
3965 # Initiation 3966 if 'pwd' in opt: 3967 self.me_dir = opt['pwd'] 3968 elif 'mother_interface' in opt: 3969 self.mother_interface = opt['mother_interface'] 3970 if not hasattr(self, 'me_dir') or not self.me_dir: 3971 self.me_dir = self.mother_interface.me_dir 3972 3973 #define paths 3974 self.paths['param'] = pjoin(self.me_dir,'Cards','param_card.dat') 3975 self.paths['param_default'] = pjoin(self.me_dir,'Cards','param_card_default.dat') 3976 self.paths['run'] = pjoin(self.me_dir,'Cards','run_card.dat') 3977 self.paths['run_default'] = pjoin(self.me_dir,'Cards','run_card_default.dat') 3978 self.paths['transfer'] =pjoin(self.me_dir,'Cards','transfer_card.dat') 3979 self.paths['MadWeight'] =pjoin(self.me_dir,'Cards','MadWeight_card.dat') 3980 self.paths['MadWeight_default'] =pjoin(self.me_dir,'Cards','MadWeight_card_default.dat') 3981 self.paths['ML'] =pjoin(self.me_dir,'Cards','MadLoopParams.dat') 3982 self.paths['shower'] = pjoin(self.me_dir,'Cards','shower_card.dat') 3983 self.paths['shower_default'] = pjoin(self.me_dir,'Cards','shower_card_default.dat') 3984 self.paths['pythia'] =pjoin(self.me_dir, 'Cards','pythia_card.dat') 3985 self.paths['PY8'] = pjoin(self.me_dir, 'Cards','pythia8_card.dat') 3986 self.paths['PY8_default'] = pjoin(self.me_dir, 'Cards','pythia8_card_default.dat') 3987 self.paths['madspin_default'] = pjoin(self.me_dir,'Cards/madspin_card_default.dat') 3988 self.paths['madspin'] = pjoin(self.me_dir,'Cards/madspin_card.dat') 3989 self.paths['reweight'] = pjoin(self.me_dir,'Cards','reweight_card.dat') 3990 self.paths['delphes'] = pjoin(self.me_dir,'Cards','delphes_card.dat') 3991 self.paths['plot'] = pjoin(self.me_dir,'Cards','plot_card.dat') 3992 self.paths['plot_default'] = pjoin(self.me_dir,'Cards','plot_card_default.dat') 3993 self.paths['madanalysis5_parton'] = pjoin(self.me_dir,'Cards','madanalysis5_parton_card.dat') 3994 self.paths['madanalysis5_hadron'] = pjoin(self.me_dir,'Cards','madanalysis5_hadron_card.dat') 3995 self.paths['madanalysis5_parton_default'] = pjoin(self.me_dir,'Cards','madanalysis5_parton_card_default.dat') 3996 self.paths['madanalysis5_hadron_default'] = pjoin(self.me_dir,'Cards','madanalysis5_hadron_card_default.dat')
3997
3998 - def __init__(self, question, cards=[], mode='auto', *args, **opt):
3999 4000 self.load_default() 4001 self.define_paths(**opt) 4002 cmd.OneLinePathCompletion.__init__(self, question, *args, **opt) 4003 4004 4005 try: 4006 self.param_card = check_param_card.ParamCard(self.paths['param']) 4007 except (check_param_card.InvalidParamCard, ValueError) as e: 4008 logger.error('Current param_card is not valid. We are going to use the default one.') 4009 logger.error('problem detected: %s' % e) 4010 files.cp(self.paths['param_default'], self.paths['param']) 4011 self.param_card = check_param_card.ParamCard(self.paths['param']) 4012 default_param = check_param_card.ParamCard(self.paths['param_default']) 4013 self.param_card_default = default_param 4014 4015 try: 4016 self.run_card = banner_mod.RunCard(self.paths['run'], consistency='warning') 4017 except IOError: 4018 self.run_card = {} 4019 try: 4020 run_card_def = banner_mod.RunCard(self.paths['run_default']) 4021 except IOError: 4022 run_card_def = {} 4023 4024 self.pname2block = {} 4025 self.conflict = [] 4026 self.restricted_value = {} 4027 self.mode = mode 4028 self.cards = cards 4029 4030 # Read the comment of the param_card_default to find name variable for 4031 # the param_card also check which value seems to be constrained in the 4032 # model. 4033 self.pname2block, self.restricted_value = \ 4034 default_param.analyze_param_card() 4035 4036 if run_card_def: 4037 self.run_set = run_card_def.keys() + self.run_card.hidden_param 4038 elif self.run_card: 4039 self.run_set = self.run_card.keys() 4040 else: 4041 self.run_set = [] 4042 # check for conflict with run_card 4043 for var in self.pname2block: 4044 if var in self.run_set: 4045 self.conflict.append(var) 4046 4047 4048 self.has_delphes = False 4049 if 'delphes_card.dat' in cards: 4050 self.has_delphes = True 4051 4052 #check if Madweight_card is present: 4053 self.has_mw = False 4054 if 'madweight_card.dat' in cards: 4055 4056 self.do_change_tf = self.mother_interface.do_define_transfer_fct 4057 self.complete_change_tf = self.mother_interface.complete_define_transfer_fct 4058 self.help_change_tf = self.mother_interface.help_define_transfer_fct 4059 if not os.path.exists(self.paths['transfer']): 4060 logger.warning('No transfer function currently define. Please use the change_tf command to define one.') 4061 4062 4063 self.has_mw = True 4064 try: 4065 import madgraph.madweight.Cards as mwcards 4066 except: 4067 import internal.madweight.Cards as mwcards 4068 self.mw_card = mwcards.Card(self.paths['MadWeight']) 4069 self.mw_card = self.mw_card.info 4070 self.mw_vars = [] 4071 for key in self.mw_card: 4072 if key == 'comment': 4073 continue 4074 for key2 in self.mw_card.info[key]: 4075 if isinstance(key2, str) and not key2.isdigit(): 4076 self.mw_vars.append(key2) 4077 4078 # check for conflict with run_card/param_card 4079 for var in self.pname2block: 4080 if var in self.mw_vars: 4081 self.conflict.append(var) 4082 for var in self.mw_vars: 4083 if var in self.run_card: 4084 self.conflict.append(var) 4085 4086 #check if MadLoopParams.dat is present: 4087 self.has_ml = False 4088 if os.path.isfile(self.paths['ML']): 4089 self.has_ml = True 4090 self.MLcard = banner_mod.MadLoopParam(self.paths['ML']) 4091 self.MLcardDefault = banner_mod.MadLoopParam() 4092 4093 self.ml_vars = [k.lower() for k in self.MLcard.keys()] 4094 # check for conflict 4095 for var in self.ml_vars: 4096 if var in self.run_card: 4097 self.conflict.append(var) 4098 if var in self.pname2block: 4099 self.conflict.append(var) 4100 if self.has_mw and var in self.mw_vars: 4101 self.conflict.append(var) 4102 4103 #check if shower_card is present: 4104 self.has_shower = False 4105 if 'shower_card.dat' in cards: 4106 self.has_shower = True 4107 try: 4108 import madgraph.various.shower_card as showercards 4109 except: 4110 import internal.shower_card as showercards 4111 self.shower_card = showercards.ShowerCard(self.paths['shower']) 4112 self.shower_vars = self.shower_card.keys() 4113 4114 # check for conflict with run_card/param_card 4115 for var in self.pname2block: 4116 if var in self.shower_vars: 4117 self.conflict.append(var) 4118 for var in self.shower_vars: 4119 if var in self.run_card: 4120 self.conflict.append(var) 4121 4122 #check if pythia8_card.dat is present: 4123 self.has_PY8 = False 4124 if 'pythia8_card.dat' in cards: 4125 self.has_PY8 = True 4126 self.PY8Card = banner_mod.PY8Card(self.paths['PY8']) 4127 self.PY8CardDefault = banner_mod.PY8Card() 4128 4129 self.py8_vars = [k.lower() for k in self.PY8Card.keys()] 4130 # check for conflict 4131 for var in self.py8_vars: 4132 if var in self.run_card: 4133 self.conflict.append(var) 4134 if var in self.pname2block: 4135 self.conflict.append(var) 4136 if self.has_mw and var in self.mw_vars: 4137 self.conflict.append(var) 4138 if self.has_ml and var in self.ml_vars: 4139 self.conflict.append(var)
4140
4141 - def do_help(self, line, conflict_raise=False, banner=True):
4142 # try: 4143 if banner: 4144 logger.info('*** HELP MESSAGE ***', '$MG:color:BLACK') 4145 4146 args = self.split_arg(line) 4147 # handle comand related help 4148 if len(args)==0 or (len(args) == 1 and hasattr(self, 'do_%s' % args[0])): 4149 out = cmd.BasicCmd.do_help(self, line) 4150 if len(args)==0: 4151 print 'Allowed Argument' 4152 print '================' 4153 print '\t'.join(self.allow_arg) 4154 print 4155 print 'Special shortcut: (type help <name>)' 4156 print '====================================' 4157 print ' syntax: set <name> <value>' 4158 print '\t'.join(self.special_shortcut) 4159 print 4160 if banner: 4161 logger.info('*** END HELP ***', '$MG:color:BLACK') 4162 return out 4163 # check for special shortcut. 4164 # special shortcut: 4165 if args[0] in self.special_shortcut: 4166 if args[0] in self.special_shortcut_help: 4167 print self.special_shortcut_help[args[0]] 4168 if banner: 4169 logger.info('*** END HELP ***', '$MG:color:BLACK') 4170 return 4171 4172 start = 0 4173 card = '' 4174 if args[0]+'_card' in self.all_card_name+ self.cards: 4175 args[0] += '_card' 4176 elif args[0]+'.dat' in self.all_card_name+ self.cards: 4177 args[0] += '.dat' 4178 elif args[0]+'_card.dat' in self.all_card_name+ self.cards: 4179 args[0] += '_card.dat' 4180 if args[0] in self.all_card_name + self.cards: 4181 start += 1 4182 card = args[0] 4183 if len(args) == 1: 4184 if args[0] == 'pythia8_card': 4185 args[0] = 'PY8Card' 4186 if args[0] == 'param_card': 4187 logger.info("Param_card information: ", '$MG:color:BLUE') 4188 print "File to define the various model parameter" 4189 logger.info("List of the Block defined:",'$MG:color:BLUE') 4190 print "\t".join(self.param_card.keys()) 4191 elif args[0].startswith('madanalysis5'): 4192 print 'This card allow to make plot with the madanalysis5 package' 4193 print 'An example card is provided. For more information about the ' 4194 print 'syntax please refer to: https://madanalysis.irmp.ucl.ac.be/' 4195 print 'or to the user manual [arXiv:1206.1599]' 4196 if args[0].startswith('madanalysis5_hadron'): 4197 print 4198 print 'This card also allow to make recasting analysis' 4199 print 'For more detail, see: arXiv:1407.3278' 4200 elif hasattr(self, args[0]): 4201 logger.info("%s information: " % args[0], '$MG:color:BLUE') 4202 print(eval('self.%s' % args[0]).__doc__) 4203 logger.info("List of parameter associated", '$MG:color:BLUE') 4204 print "\t".join(eval('self.%s' % args[0]).keys()) 4205 if banner: 4206 logger.info('*** END HELP ***', '$MG:color:BLACK') 4207 return 4208 4209 #### RUN CARD 4210 if args[start] in [l.lower() for l in self.run_card.keys()] and card in ['', 'run_card']: 4211 if args[start] not in self.run_set: 4212 args[start] = [l for l in self.run_set if l.lower() == args[start]][0] 4213 4214 if args[start] in self.conflict and not conflict_raise: 4215 conflict_raise = True 4216 logger.info('** AMBIGUOUS NAME: %s **', args[start], '$MG:color:BLACK') 4217 if card == '': 4218 logger.info('** If not explicitely speficy this parameter will modif the run_card file', '$MG:color:BLACK') 4219 4220 self.run_card.do_help(args[start]) 4221 ### PARAM_CARD WITH BLOCK NAME ----------------------------------------- 4222 elif (args[start] in self.param_card or args[start] == 'width') \ 4223 and card in ['','param_card']: 4224 if args[start] in self.conflict and not conflict_raise: 4225 conflict_raise = True 4226 logger.info('** AMBIGUOUS NAME: %s **', args[start], '$MG:color:BLACK') 4227 if card == '': 4228 logger.info('** If not explicitely speficy this parameter will modif the param_card file', '$MG:color:BLACK') 4229 4230 if args[start] == 'width': 4231 args[start] = 'decay' 4232 4233 if len(args) == start+1: 4234 self.param_card.do_help(args[start], tuple()) 4235 key = None 4236 elif args[start+1] in self.pname2block: 4237 all_var = self.pname2block[args[start+1]] 4238 key = None 4239 for bname, lhaid in all_var: 4240 if bname == args[start]: 4241 key = lhaid 4242 break 4243 else: 4244 logger.warning('%s is not part of block "%s" but "%s". please correct.' % 4245 (args[start+1], args[start], bname)) 4246 else: 4247 try: 4248 key = tuple([int(i) for i in args[start+1:]]) 4249 except ValueError: 4250 logger.warning('Failed to identify LHA information') 4251 return 4252 4253 if key in self.param_card[args[start]].param_dict: 4254 self.param_card.do_help(args[start], key, default=self.param_card_default) 4255 elif key: 4256 logger.warning('invalid information: %s not defined in the param_card' % (key,)) 4257 # PARAM_CARD NO BLOCK NAME --------------------------------------------- 4258 elif args[start] in self.pname2block and card in ['','param_card']: 4259 if args[start] in self.conflict and not conflict_raise: 4260 conflict_raise = True 4261 logger.info('** AMBIGUOUS NAME: %s **', args[start], '$MG:color:BLACK') 4262 if card == '': 4263 logger.info('** If not explicitely speficy this parameter will modif the param_card file', '$MG:color:BLACK') 4264 4265 all_var = self.pname2block[args[start]] 4266 for bname, lhaid in all_var: 4267 new_line = 'param_card %s %s %s' % (bname, 4268 ' '.join([ str(i) for i in lhaid]), ' '.join(args[start+1:])) 4269 self.do_help(new_line, conflict_raise=True, banner=False) 4270 4271 # MadLoop Parameter --------------------------------------------------- 4272 elif self.has_ml and args[start] in self.ml_vars \ 4273 and card in ['', 'MadLoop_card']: 4274 4275 if args[start] in self.conflict and not conflict_raise: 4276 conflict_raise = True 4277 logger.info('** AMBIGUOUS NAME: %s **', args[start], '$MG:color:BLACK') 4278 if card == '': 4279 logger.info('** If not explicitely speficy this parameter will modif the madloop_card file', '$MG:color:BLACK') 4280 4281 self.MLcard.do_help(args[start]) 4282 4283 # Pythia8 Parameter --------------------------------------------------- 4284 elif self.has_PY8 and args[start] in self.PY8Card: 4285 if args[start] in self.conflict and not conflict_raise: 4286 conflict_raise = True 4287 logger.info('** AMBIGUOUS NAME: %s **', args[start], '$MG:color:BLACK') 4288 if card == '': 4289 logger.info('** If not explicitely speficy this parameter will modif the pythia8_card file', '$MG:color:BLACK') 4290 4291 self.PY8Card.do_help(args[start]) 4292 elif card.startswith('madanalysis5'): 4293 print 'MA5' 4294 4295 4296 else: 4297 print "no help available" 4298 4299 if banner: 4300 logger.info('*** END HELP ***', '$MG:color:BLACK') 4301 #raw_input('press enter to quit the help') 4302 return
4303 # except Exception, error: 4304 # if __debug__: 4305 # import traceback 4306 # traceback.print_exc() 4307 # print error 4308
4309 - def complete_help(self, text, line, begidx, endidx):
4310 prev_timer = signal.alarm(0) # avoid timer if any 4311 if prev_timer: 4312 nb_back = len(line) 4313 self.stdout.write('\b'*nb_back + '[timer stopped]\n') 4314 self.stdout.write(line) 4315 self.stdout.flush() 4316 # try: 4317 possibilities = self.complete_set(text, line, begidx, endidx,formatting=False) 4318 if line[:begidx].strip() == 'help': 4319 possibilities['Defined command'] = cmd.BasicCmd.completenames(self, text, line)#, begidx, endidx) 4320 possibilities.update(self.complete_add(text, line, begidx, endidx,formatting=False)) 4321 return self.deal_multiple_categories(possibilities)
4322 # except Exception, error: 4323 # import traceback 4324 # traceback.print_exc() 4325 # print error 4326
4327 - def complete_update(self, text, line, begidx, endidx):
4328 prev_timer = signal.alarm(0) # avoid timer if any 4329 if prev_timer: 4330 nb_back = len(line) 4331 self.stdout.write('\b'*nb_back + '[timer stopped]\n') 4332 self.stdout.write(line) 4333 self.stdout.flush() 4334 4335 arg = line[:begidx].split() 4336 if len(arg) <=1: 4337 return self.list_completion(text, ['dependent', 'missing'], line)
4338 4339
4340 - def complete_set(self, text, line, begidx, endidx, formatting=True):
4341 """ Complete the set command""" 4342 4343 prev_timer = signal.alarm(0) # avoid timer if any 4344 if prev_timer: 4345 nb_back = len(line) 4346 self.stdout.write('\b'*nb_back + '[timer stopped]\n') 4347 self.stdout.write(line) 4348 self.stdout.flush() 4349 4350 possibilities = {} 4351 allowed = {} 4352 args = self.split_arg(line[0:begidx]) 4353 if args[-1] in ['Auto', 'default']: 4354 return 4355 if len(args) == 1: 4356 allowed = {'category':'', 'run_card':'', 'block':'all', 'param_card':'','shortcut':''} 4357 if self.has_mw: 4358 allowed['madweight_card'] = '' 4359 allowed['mw_block'] = 'all' 4360 if self.has_shower: 4361 allowed['shower_card'] = '' 4362 if self.has_ml: 4363 allowed['madloop_card'] = '' 4364 if self.has_PY8: 4365 allowed['pythia8_card'] = '' 4366 if self.has_delphes: 4367 allowed['delphes_card'] = '' 4368 4369 elif len(args) == 2: 4370 if args[1] == 'run_card': 4371 allowed = {'run_card':'default'} 4372 elif args[1] == 'param_card': 4373 allowed = {'block':'all', 'param_card':'default'} 4374 elif args[1] in self.param_card.keys(): 4375 allowed = {'block':args[1]} 4376 elif args[1] == 'width': 4377 allowed = {'block': 'decay'} 4378 elif args[1] == 'MadWeight_card': 4379 allowed = {'madweight_card':'default', 'mw_block': 'all'} 4380 elif args[1] == 'MadLoop_card': 4381 allowed = {'madloop_card':'default'} 4382 elif args[1] == 'pythia8_card': 4383 allowed = {'pythia8_card':'default'} 4384 elif self.has_mw and args[1] in self.mw_card.keys(): 4385 allowed = {'mw_block':args[1]} 4386 elif args[1] == 'shower_card': 4387 allowed = {'shower_card':'default'} 4388 elif args[1] == 'delphes_card': 4389 allowed = {'delphes_card':'default'} 4390 else: 4391 allowed = {'value':''} 4392 else: 4393 start = 1 4394 if args[1] in ['run_card', 'param_card', 'MadWeight_card', 'shower_card', 4395 'MadLoop_card','pythia8_card','delphes_card','plot_card', 4396 'madanalysis5_parton_card','madanalysis5_hadron_card']: 4397 start = 2 4398 if args[-1] in self.pname2block.keys(): 4399 allowed['value'] = 'default' 4400 elif args[start] in self.param_card.keys() or args[start] == 'width': 4401 if args[start] == 'width': 4402 args[start] = 'decay' 4403 4404 if args[start+1:]: 4405 allowed = {'block':(args[start], args[start+1:])} 4406 else: 4407 allowed = {'block':args[start]} 4408 elif self.has_mw and args[start] in self.mw_card.keys(): 4409 if args[start+1:]: 4410 allowed = {'mw_block':(args[start], args[start+1:])} 4411 else: 4412 allowed = {'mw_block':args[start]} 4413 #elif len(args) == start +1: 4414 # allowed['value'] = '' 4415 else: 4416 allowed['value'] = '' 4417 4418 if 'category' in allowed.keys(): 4419 categories = ['run_card', 'param_card'] 4420 if self.has_mw: 4421 categories.append('MadWeight_card') 4422 if self.has_shower: 4423 categories.append('shower_card') 4424 if self.has_ml: 4425 categories.append('MadLoop_card') 4426 if self.has_PY8: 4427 categories.append('pythia8_card') 4428 if self.has_delphes: 4429 categories.append('delphes_card') 4430 4431 possibilities['category of parameter (optional)'] = \ 4432 self.list_completion(text, categories) 4433 4434 if 'shortcut' in allowed.keys(): 4435 possibilities['special values'] = self.list_completion(text, self.special_shortcut.keys()+['qcut', 'showerkt']) 4436 4437 if 'run_card' in allowed.keys(): 4438 opts = self.run_set 4439 if allowed['run_card'] == 'default': 4440 opts.append('default') 4441 4442 possibilities['Run Card'] = self.list_completion(text, opts) 4443 4444 if 'param_card' in allowed.keys(): 4445 opts = self.pname2block.keys() 4446 if allowed['param_card'] == 'default': 4447 opts.append('default') 4448 possibilities['Param Card'] = self.list_completion(text, opts) 4449 4450 if 'madweight_card' in allowed.keys(): 4451 opts = self.mw_vars + [k for k in self.mw_card.keys() if k !='comment'] 4452 if allowed['madweight_card'] == 'default': 4453 opts.append('default') 4454 possibilities['MadWeight Card'] = self.list_completion(text, opts) 4455 4456 if 'madloop_card' in allowed.keys(): 4457 opts = self.ml_vars 4458 if allowed['madloop_card'] == 'default': 4459 opts.append('default') 4460 possibilities['MadLoop Parameter'] = self.list_completion(text, opts) 4461 4462 if 'pythia8_card' in allowed.keys(): 4463 opts = self.py8_vars 4464 if allowed['pythia8_card'] == 'default': 4465 opts.append('default') 4466 possibilities['Pythia8 Parameter'] = self.list_completion(text, opts) 4467 4468 if 'shower_card' in allowed.keys(): 4469 opts = self.shower_vars + [k for k in self.shower_card.keys() if k !='comment'] 4470 if allowed['shower_card'] == 'default': 4471 opts.append('default') 4472 possibilities['Shower Card'] = self.list_completion(text, opts) 4473 4474 if 'delphes_card' in allowed: 4475 if allowed['delphes_card'] == 'default': 4476 opts = ['default', 'atlas', 'cms'] 4477 possibilities['Delphes Card'] = self.list_completion(text, opts) 4478 4479 if 'value' in allowed.keys(): 4480 opts = ['default'] 4481 if 'decay' in args: 4482 opts.append('Auto') 4483 opts.append('Auto@NLO') 4484 elif args[-1] in self.pname2block and self.pname2block[args[-1]][0][0] == 'decay': 4485 opts.append('Auto') 4486 opts.append('Auto@NLO') 4487 possibilities['Special Value'] = self.list_completion(text, opts) 4488 4489 if 'block' in allowed.keys(): 4490 if allowed['block'] == 'all': 4491 allowed_block = [i for i in self.param_card.keys() if 'qnumbers' not in i] 4492 allowed_block.append('width') 4493 possibilities['Param Card Block' ] = \ 4494 self.list_completion(text, allowed_block) 4495 elif isinstance(allowed['block'], basestring): 4496 block = self.param_card[allowed['block']].param_dict 4497 ids = [str(i[0]) for i in block 4498 if (allowed['block'], i) not in self.restricted_value] 4499 possibilities['Param Card id' ] = self.list_completion(text, ids) 4500 varname = [name for name, all_var in self.pname2block.items() 4501 if any((bname == allowed['block'] 4502 for bname,lhaid in all_var))] 4503 possibilities['Param card variable'] = self.list_completion(text, 4504 varname) 4505 else: 4506 block = self.param_card[allowed['block'][0]].param_dict 4507 nb = len(allowed['block'][1]) 4508 ids = [str(i[nb]) for i in block if len(i) > nb and \ 4509 [str(a) for a in i[:nb]] == allowed['block'][1]] 4510 4511 if not ids: 4512 if tuple([int(i) for i in allowed['block'][1]]) in block: 4513 opts = ['default'] 4514 if allowed['block'][0] == 'decay': 4515 opts.append('Auto') 4516 opts.append('Auto@NLO') 4517 possibilities['Special value'] = self.list_completion(text, opts) 4518 possibilities['Param Card id' ] = self.list_completion(text, ids) 4519 4520 if 'mw_block' in allowed.keys(): 4521 if allowed['mw_block'] == 'all': 4522 allowed_block = [i for i in self.mw_card.keys() if 'comment' not in i] 4523 possibilities['MadWeight Block' ] = \ 4524 self.list_completion(text, allowed_block) 4525 elif isinstance(allowed['mw_block'], basestring): 4526 block = self.mw_card[allowed['mw_block']] 4527 ids = [str(i[0]) if isinstance(i, tuple) else str(i) for i in block] 4528 possibilities['MadWeight Card id' ] = self.list_completion(text, ids) 4529 else: 4530 block = self.mw_card[allowed['mw_block'][0]] 4531 nb = len(allowed['mw_block'][1]) 4532 ids = [str(i[nb]) for i in block if isinstance(i, tuple) and\ 4533 len(i) > nb and \ 4534 [str(a) for a in i[:nb]] == allowed['mw_block'][1]] 4535 4536 if not ids: 4537 if tuple([i for i in allowed['mw_block'][1]]) in block or \ 4538 allowed['mw_block'][1][0] in block.keys(): 4539 opts = ['default'] 4540 possibilities['Special value'] = self.list_completion(text, opts) 4541 possibilities['MadWeight Card id' ] = self.list_completion(text, ids) 4542 4543 return self.deal_multiple_categories(possibilities, formatting)
4544
4545 - def do_set(self, line):
4546 """ edit the value of one parameter in the card""" 4547 4548 4549 args = self.split_arg(line) 4550 if len(args) == 0: 4551 logger.warning("No argument. For help type 'help set'.") 4552 # fix some formatting problem 4553 if len(args)==1 and '=' in args[-1]: 4554 arg1, arg2 = args.pop(-1).split('=',1) 4555 args += [arg1, arg2] 4556 if '=' in args: 4557 args.remove('=') 4558 4559 args[:-1] = [ a.lower() for a in args[:-1]] 4560 # special shortcut: 4561 if args[0] in self.special_shortcut: 4562 targettypes , cmd = self.special_shortcut[args[0]] 4563 if len(args) != len(targettypes) +1: 4564 logger.warning('shortcut %s requires %s argument' % (args[0], len(targettypes))) 4565 if len(args) < len(targettypes) +1: 4566 return 4567 else: 4568 logger.warning('additional argument will be ignored') 4569 values ={} 4570 for i, argtype in enumerate(targettypes): 4571 try: 4572 values = {str(i): banner_mod.ConfigFile.format_variable(args[i+1], argtype, args[0])} 4573 except ValueError as e: 4574 logger.warning("Wrong argument: The entry #%s should be of type %s.", i+1, argtype) 4575 return 4576 #else: 4577 # logger.warning("too many argument for this command") 4578 # return 4579 4580 for arg in cmd: 4581 try: 4582 text = arg % values 4583 except KeyError: 4584 logger.warning("This command requires one argument") 4585 return 4586 except Exception as e: 4587 logger.warning(str(e)) 4588 return 4589 else: 4590 self.do_set(arg % values) 4591 return 4592 4593 4594 start = 0 4595 if len(args) < 2: 4596 logger.warning('Invalid set command %s (need two arguments)' % line) 4597 return 4598 4599 # Special case for the qcut value 4600 if args[0].lower() == 'qcut': 4601 pythia_path = self.paths['pythia'] 4602 if os.path.exists(pythia_path): 4603 logger.info('add line QCUT = %s in pythia_card.dat' % args[1]) 4604 p_card = open(pythia_path,'r').read() 4605 p_card, n = re.subn('''^\s*QCUT\s*=\s*[\de\+\-\.]*\s*$''', 4606 ''' QCUT = %s ''' % args[1], \ 4607 p_card, flags=(re.M+re.I)) 4608 if n==0: 4609 p_card = '%s \n QCUT= %s' % (p_card, args[1]) 4610 with open(pythia_path, 'w') as fsock: 4611 fsock.write(p_card) 4612 return 4613 # Special case for the showerkt value 4614 if args[0].lower() == 'showerkt': 4615 pythia_path = self.paths['pythia'] 4616 if os.path.exists(pythia_path): 4617 logger.info('add line SHOWERKT = %s in pythia_card.dat' % args[1].upper()) 4618 p_card = open(pythia_path,'r').read() 4619 p_card, n = re.subn('''^\s*SHOWERKT\s*=\s*[default\de\+\-\.]*\s*$''', 4620 ''' SHOWERKT = %s ''' % args[1].upper(), \ 4621 p_card, flags=(re.M+re.I)) 4622 if n==0: 4623 p_card = '%s \n SHOWERKT= %s' % (p_card, args[1].upper()) 4624 with open(pythia_path, 'w') as fsock: 4625 fsock.write(p_card) 4626 return 4627 4628 4629 card = '' #store which card need to be modify (for name conflict) 4630 if args[0] == 'madweight_card': 4631 if not self.mw_card: 4632 logger.warning('Invalid Command: No MadWeight card defined.') 4633 return 4634 args[0] = 'MadWeight_card' 4635 4636 if args[0] == 'shower_card': 4637 if not self.shower_card: 4638 logger.warning('Invalid Command: No Shower card defined.') 4639 return 4640 args[0] = 'shower_card' 4641 4642 if args[0] == "madloop_card": 4643 if not self.has_ml: 4644 logger.warning('Invalid Command: No MadLoopParam card defined.') 4645 return 4646 args[0] = 'MadLoop_card' 4647 4648 if args[0] == "pythia8_card": 4649 if not self.has_PY8: 4650 logger.warning('Invalid Command: No Pythia8 card defined.') 4651 return 4652 args[0] = 'pythia8_card' 4653 4654 if args[0] == 'delphes_card': 4655 if not self.has_delphes: 4656 logger.warning('Invalid Command: No Delphes card defined.') 4657 return 4658 if args[1] == 'atlas': 4659 logger.info("set default ATLAS configuration for Delphes", '$MG:color:BLACK') 4660 files.cp(pjoin(self.me_dir,'Cards', 'delphes_card_ATLAS.dat'), 4661 pjoin(self.me_dir,'Cards', 'delphes_card.dat')) 4662 return 4663 elif args[1] == 'cms': 4664 logger.info("set default CMS configuration for Delphes",'$MG:color:BLACK') 4665 files.cp(pjoin(self.me_dir,'Cards', 'delphes_card_CMS.dat'), 4666 pjoin(self.me_dir,'Cards', 'delphes_card.dat')) 4667 return 4668 4669 4670 if args[0] in ['run_card', 'param_card', 'MadWeight_card', 'shower_card', 4671 'delphes_card','madanalysis5_hadron_card','madanalysis5_parton_card']: 4672 if args[1] == 'default': 4673 logger.info('replace %s by the default card' % args[0],'$MG:color:BLACK') 4674 files.cp(self.paths['%s_default' %args[0][:-5]], self.paths[args[0][:-5]]) 4675 if args[0] == 'param_card': 4676 self.param_card = check_param_card.ParamCard(self.paths['param']) 4677 elif args[0] == 'run_card': 4678 self.run_card = banner_mod.RunCard(self.paths['run']) 4679 elif args[0] == 'shower_card': 4680 self.shower_card = shower_card_mod.ShowerCard(self.paths['shower']) 4681 return 4682 else: 4683 card = args[0] 4684 start=1 4685 if len(args) < 3: 4686 logger.warning('Invalid set command: %s (not enough arguments)' % line) 4687 return 4688 4689 elif args[0] in ['MadLoop_card']: 4690 if args[1] == 'default': 4691 logger.info('replace MadLoopParams.dat by the default card','$MG:color:BLACK') 4692 self.MLcard = banner_mod.MadLoopParam(self.MLcardDefault) 4693 self.MLcard.write(self.paths['ML'], 4694 commentdefault=True) 4695 return 4696 else: 4697 card = args[0] 4698 start=1 4699 if len(args) < 3: 4700 logger.warning('Invalid set command: %s (not enough arguments)' % line) 4701 return 4702 elif args[0] in ['pythia8_card']: 4703 if args[1] == 'default': 4704 logger.info('replace pythia8_card.dat by the default card','$MG:color:BLACK') 4705 self.PY8Card = banner_mod.PY8Card(self.PY8CardDefault) 4706 self.PY8Card.write(pjoin(self.me_dir,'Cards','pythia8_card.dat'), 4707 pjoin(self.me_dir,'Cards','pythia8_card_default.dat'), 4708 print_only_visible=True) 4709 return 4710 else: 4711 card = args[0] 4712 start=1 4713 if len(args) < 3: 4714 logger.warning('Invalid set command: %s (not enough arguments)' % line) 4715 return 4716 elif args[0] in ['madspin_card']: 4717 if args[1] == 'default': 4718 logger.info('replace madspin_card.dat by the default card','$MG:color:BLACK') 4719 files.cp(self.paths['MS_default'], self.paths['madspin']) 4720 return 4721 else: 4722 logger.warning("""Command set not allowed for modifying the madspin_card. 4723 Check the command \"decay\" instead.""") 4724 return 4725 4726 #### RUN CARD 4727 if args[start] in [l.lower() for l in self.run_card.keys()] and card in ['', 'run_card']: 4728 if args[start] not in self.run_set: 4729 args[start] = [l for l in self.run_set if l.lower() == args[start]][0] 4730 4731 if args[start] in self.conflict and card == '': 4732 text = 'Ambiguous name (present in more than one card). Will assume it to be referred to run_card.\n' 4733 text += 'If this is not intended, please reset it in the run_card and specify the relevant card to \n' 4734 text += 'edit, in the format < set card parameter value >' 4735 logger.warning(text) 4736 4737 if args[start+1] == 'default': 4738 default = banner_mod.RunCard(self.paths['run_default']) 4739 if args[start] in default.keys(): 4740 self.setR(args[start],default[args[start]]) 4741 else: 4742 logger.info('remove information %s from the run_card' % args[start],'$MG:color:BLACK') 4743 del self.run_card[args[start]] 4744 else: 4745 if args[0].startswith('sys_') or \ 4746 args[0] in self.run_card.list_parameter or \ 4747 args[0] in self.run_card.dict_parameter: 4748 val = ' '.join(args[start+1:]) 4749 val = val.split('#')[0] 4750 else: 4751 val = args[start+1] 4752 self.setR(args[start], val) 4753 self.run_card.write(self.paths['run'], self.paths['run_default']) 4754 4755 ### PARAM_CARD WITH BLOCK NAME ----------------------------------------- 4756 elif (args[start] in self.param_card or args[start] == 'width') \ 4757 and card in ['','param_card']: 4758 #special treatment for scan 4759 if any(t.startswith('scan') for t in args): 4760 index = [i for i,t in enumerate(args) if t.startswith('scan')][0] 4761 args = args[:index] + [' '.join(args[index:])] 4762 4763 if args[start] in self.conflict and card == '': 4764 text = 'ambiguous name (present in more than one card). Please specify which card to edit' 4765 text += ' in the format < set card parameter value>' 4766 logger.warning(text) 4767 return 4768 4769 if args[start] == 'width': 4770 args[start] = 'decay' 4771 4772 if args[start+1] in self.pname2block: 4773 all_var = self.pname2block[args[start+1]] 4774 key = None 4775 for bname, lhaid in all_var: 4776 if bname == args[start]: 4777 key = lhaid 4778 break 4779 else: 4780 logger.warning('%s is not part of block "%s" but "%s". please correct.' % 4781 (args[start+1], args[start], bname)) 4782 return 4783 else: 4784 try: 4785 key = tuple([int(i) for i in args[start+1:-1]]) 4786 except ValueError: 4787 if args[start] == 'decay' and args[start+1:-1] == ['all']: 4788 for key in self.param_card[args[start]].param_dict: 4789 if (args[start], key) in self.restricted_value: 4790 continue 4791 else: 4792 self.setP(args[start], key, args[-1]) 4793 self.param_card.write(self.paths['param']) 4794 return 4795 logger.warning('invalid set command %s (failed to identify LHA information)' % line) 4796 return 4797 4798 if key in self.param_card[args[start]].param_dict: 4799 if (args[start], key) in self.restricted_value: 4800 text = "Note that this parameter seems to be ignore by MG.\n" 4801 text += "MG will use instead the expression: %s\n" % \ 4802 self.restricted_value[(args[start], key)] 4803 text += "You need to match this expression for external program (such pythia)." 4804 logger.warning(text) 4805 4806 if args[-1].lower() in ['default', 'auto', 'auto@nlo'] or args[-1].startswith('scan'): 4807 self.setP(args[start], key, args[-1]) 4808 else: 4809 try: 4810 value = float(args[-1]) 4811 except Exception: 4812 logger.warning('Invalid input: Expected number and not \'%s\'' \ 4813 % args[-1]) 4814 return 4815 self.setP(args[start], key, value) 4816 else: 4817 logger.warning('invalid set command %s' % line) 4818 return 4819 self.param_card.write(self.paths['param']) 4820 4821 # PARAM_CARD NO BLOCK NAME --------------------------------------------- 4822 elif args[start] in self.pname2block and card in ['','param_card']: 4823 if args[start] in self.conflict and card == '': 4824 text = 'ambiguous name (present in more than one card). Please specify which card to edit' 4825 text += ' in the format < set card parameter value>' 4826 logger.warning(text) 4827 return 4828 4829 all_var = self.pname2block[args[start]] 4830 for bname, lhaid in all_var: 4831 new_line = 'param_card %s %s %s' % (bname, 4832 ' '.join([ str(i) for i in lhaid]), ' '.join(args[start+1:])) 4833 self.do_set(new_line) 4834 if len(all_var) > 1: 4835 logger.warning('This variable correspond to more than one parameter in the param_card.') 4836 for bname, lhaid in all_var: 4837 logger.warning(' %s %s' % (bname, ' '.join([str(i) for i in lhaid]))) 4838 logger.warning('all listed variables have been modified') 4839 4840 # MadWeight_card with block name --------------------------------------- 4841 elif self.has_mw and (args[start] in self.mw_card and args[start] != 'comment') \ 4842 and card in ['','MadWeight_card']: 4843 4844 if args[start] in self.conflict and card == '': 4845 text = 'ambiguous name (present in more than one card). Please specify which card to edit' 4846 text += ' in the format < set card parameter value>' 4847 logger.warning(text) 4848 return 4849 4850 block = args[start] 4851 name = args[start+1] 4852 value = args[start+2:] 4853 self.setM(block, name, value) 4854 self.mw_card.write(self.paths['MadWeight']) 4855 4856 # MadWeight_card NO Block name ----------------------------------------- 4857 elif self.has_mw and args[start] in self.mw_vars \ 4858 and card in ['', 'MadWeight_card']: 4859 4860 if args[start] in self.conflict and card == '': 4861 text = 'ambiguous name (present in more than one card). Please specify which card to edit' 4862 text += ' in the format < set card parameter value>' 4863 logger.warning(text) 4864 return 4865 4866 block = [b for b, data in self.mw_card.items() if args[start] in data] 4867 if len(block) > 1: 4868 logger.warning('%s is define in more than one block: %s.Please specify.' 4869 % (args[start], ','.join(block))) 4870 return 4871 4872 block = block[0] 4873 name = args[start] 4874 value = args[start+1:] 4875 self.setM(block, name, value) 4876 self.mw_card.write(self.paths['MadWeight']) 4877 4878 # MadWeight_card New Block --------------------------------------------- 4879 elif self.has_mw and args[start].startswith('mw_') and len(args[start:]) == 3\ 4880 and card == 'MadWeight_card': 4881 block = args[start] 4882 name = args[start+1] 4883 value = args[start+2] 4884 self.setM(block, name, value) 4885 self.mw_card.write(self.paths['MadWeight']) 4886 4887 #### SHOWER CARD 4888 elif self.has_shower and args[start].lower() in [l.lower() for l in \ 4889 self.shower_card.keys()] and card in ['', 'shower_card']: 4890 if args[start] not in self.shower_card: 4891 args[start] = [l for l in self.shower_card if l.lower() == args[start].lower()][0] 4892 4893 if args[start] in self.conflict and card == '': 4894 text = 'ambiguous name (present in more than one card). Please specify which card to edit' 4895 text += ' in the format < set card parameter value>' 4896 logger.warning(text) 4897 return 4898 4899 if args[start+1].lower() == 'default': 4900 default = shower_card_mod.ShowerCard(self.paths['shower_default']) 4901 if args[start] in default.keys(): 4902 self.shower_card.set_param(args[start],default[args[start]], self.paths['shower']) 4903 else: 4904 logger.info('remove information %s from the shower_card' % args[start],'$MG:color:BLACK') 4905 del self.shower_card[args[start]] 4906 elif args[start+1].lower() in ['t','.true.','true']: 4907 self.shower_card.set_param(args[start],'.true.',self.paths['shower']) 4908 elif args[start+1].lower() in ['f','.false.','false']: 4909 self.shower_card.set_param(args[start],'.false.',self.paths['shower']) 4910 elif args[start] in ['analyse', 'extralibs', 'extrapaths', 'includepaths'] or\ 4911 args[start].startswith('dm_'): 4912 #case sensitive parameters 4913 args = line.split() 4914 args_str = ' '.join(str(a) for a in args[start+1:len(args)]) 4915 self.shower_card.set_param(args[start],args_str,pjoin(self.me_dir,'Cards','shower_card.dat')) 4916 else: 4917 args_str = ' '.join(str(a) for a in args[start+1:len(args)]) 4918 self.shower_card.set_param(args[start],args_str,self.paths['shower']) 4919 4920 # MadLoop Parameter --------------------------------------------------- 4921 elif self.has_ml and args[start] in self.ml_vars \ 4922 and card in ['', 'MadLoop_card']: 4923 4924 if args[start] in self.conflict and card == '': 4925 text = 'ambiguous name (present in more than one card). Please specify which card to edit' 4926 logger.warning(text) 4927 return 4928 4929 if args[start+1] == 'default': 4930 value = self.MLcardDefault[args[start]] 4931 default = True 4932 else: 4933 value = args[start+1] 4934 default = False 4935 self.setML(args[start], value, default=default) 4936 self.MLcard.write(self.paths['ML'], 4937 commentdefault=True) 4938 4939 # Pythia8 Parameter --------------------------------------------------- 4940 elif self.has_PY8 and (card == 'pythia8_card' or (card == '' and \ 4941 args[start] in self.PY8Card)): 4942 4943 if args[start] in self.conflict and card == '': 4944 text = 'ambiguous name (present in more than one card). Please specify which card to edit' 4945 logger.warning(text) 4946 return 4947 4948 if args[start+1] == 'default': 4949 value = self.PY8CardDefault[args[start]] 4950 default = True 4951 else: 4952 value = ' '.join(args[start+1:]) 4953 default = False 4954 self.setPY8(args[start], value, default=default) 4955 self.PY8Card.write(pjoin(self.me_dir,'Cards','pythia8_card.dat'), 4956 pjoin(self.me_dir,'Cards','pythia8_card_default.dat'), 4957 print_only_visible=True) 4958 4959 #INVALID -------------------------------------------------------------- 4960 else: 4961 logger.warning('invalid set command %s ' % line) 4962 arg = args[start].lower() 4963 if self.has_PY8: 4964 close_opts = [name for name in self.PY8Card if name.lower().startswith(arg[:3]) or arg in name.lower()] 4965 if close_opts: 4966 logger.info('Did you mean one of the following PY8 options:\n%s' % '\t'.join(close_opts)) 4967 if self.run_card: 4968 close_opts = [name for name in self.run_card if name.lower().startswith(arg[:3]) or arg in name.lower()] 4969 if close_opts: 4970 logger.info('Did you mean one of the following run_card options:\n%s' % '\t'.join(close_opts)) 4971 4972 return
4973
4974 - def setM(self, block, name, value):
4975 4976 if isinstance(value, list) and len(value) == 1: 4977 value = value[0] 4978 4979 if block not in self.mw_card: 4980 logger.warning('block %s was not present in the current MadWeight card. We are adding it' % block) 4981 self.mw_card[block] = {} 4982 elif name not in self.mw_card[block]: 4983 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') 4984 if value == 'default': 4985 import madgraph.madweight.Cards as mwcards 4986 mw_default = mwcards.Card(self.paths['MadWeight_default']) 4987 try: 4988 value = mw_default[block][name] 4989 except KeyError: 4990 logger.info('removing id "%s" from Block "%s" '% (name, block),'$MG:color:BLACK') 4991 if name in self.mw_card[block]: 4992 del self.mw_card[block][name] 4993 return 4994 if value: 4995 logger.info('modify madweight_card information BLOCK "%s" with id "%s" set to %s', 4996 block, name, value, '$MG:color:BLACK') 4997 else: 4998 logger.warning("Invalid command: No value. To set default value. Use \"default\" as value") 4999 return 5000 5001 self.mw_card[block][name] = value
5002
5003 - def setR(self, name, value):
5004 logger.info('modify parameter %s of the run_card.dat to %s' % (name, value),'$MG:color:BLACK') 5005 self.run_card.set(name, value, user=True)
5006
5007 - def setML(self, name, value, default=False):
5008 5009 try: 5010 self.MLcard.set(name, value, user=True) 5011 except Exception, error: 5012 logger.warning("Fail to change parameter. Please Retry. Reason: %s." % error) 5013 return 5014 logger.info('modify parameter %s of the MadLoopParam.dat to %s' % (name, value),'$MG:color:BLACK') 5015 if default and name.lower() in self.MLcard.user_set: 5016 self.MLcard.user_set.remove(name.lower())
5017
5018 - def setPY8(self, name, value, default=False):
5019 try: 5020 self.PY8Card.userSet(name, value) 5021 except Exception, error: 5022 logger.warning("Fail to change parameter. Please Retry. Reason: %s." % error) 5023 return 5024 logger.info('modify parameter %s of the pythia8_card.dat to %s' % (name, value), '$MG:color:BLACK') 5025 if default and name.lower() in self.PY8Card.user_set: 5026 self.PY8Card.user_set.remove(name.lower())
5027
5028 - def setP(self, block, lhaid, value):
5029 if isinstance(value, str): 5030 value = value.lower() 5031 if value == 'default': 5032 default = check_param_card.ParamCard(self.paths['param_default']) 5033 value = default[block].param_dict[lhaid].value 5034 5035 elif value in ['auto', 'auto@nlo']: 5036 if 'nlo' in value: 5037 value = 'Auto@NLO' 5038 else: 5039 value = 'Auto' 5040 if block != 'decay': 5041 logger.warning('Invalid input: \'Auto\' value only valid for DECAY') 5042 return 5043 elif value.startswith('scan'): 5044 if ':' not in value: 5045 logger.warning('Invalid input: \'scan\' mode requires a \':\' before the definition.') 5046 return 5047 tag = value.split(':')[0] 5048 tag = tag[4:].strip() 5049 if tag and not tag.isdigit(): 5050 logger.warning('Invalid input: scan tag need to be integer and not "%s"' % tag) 5051 return 5052 5053 5054 pass 5055 else: 5056 try: 5057 value = float(value) 5058 except ValueError: 5059 logger.warning('Invalid input: \'%s\' not valid intput.'% value) 5060 5061 logger.info('modify param_card information BLOCK %s with id %s set to %s' %\ 5062 (block, lhaid, value), '$MG:color:BLACK') 5063 self.param_card[block].param_dict[lhaid].value = value
5064
5065 - def check_card_consistency(self):
5066 """This is run on quitting the class. Apply here all the self-consistency 5067 rule that you want. Do the modification via the set command.""" 5068 5069 # if NLO reweighting is ON: ensure that we keep the rwgt information 5070 if 'reweight' in self.allow_arg and 'run' in self.allow_arg and \ 5071 isinstance(self.run_card,banner_mod.RunCardNLO) and \ 5072 not self.run_card['store_rwgt_info']: 5073 #check if a NLO reweighting is required 5074 re_pattern = re.compile(r'''^\s*change\s*mode\s* (LO\+NLO|LO|NLO)\s*(?:#|$)''', re.M+re.I) 5075 text = open(self.paths['reweight']).read() 5076 options = re_pattern.findall(text) 5077 if any(o in ['NLO', 'LO+NLO'] for o in options): 5078 logger.info('NLO reweighting is on ON. Automatically set store_rwgt_info to True', '$MG:color:BLACK' ) 5079 self.do_set('run_card store_rwgt_info True') 5080 5081 # if external computation for the systematics are asked then switch 5082 #automatically the book-keeping of the weight for NLO 5083 if 'run' in self.allow_arg and \ 5084 self.run_card['systematics_program'] == 'systematics' and \ 5085 isinstance(self.run_card,banner_mod.RunCardNLO) and \ 5086 not self.run_card['store_rwgt_info']: 5087 logger.warning('To be able to run systematics program, we set store_rwgt_info to True') 5088 self.do_set('run_card store_rwgt_info True') 5089 5090 # @LO if PY6 shower => event_norm on sum 5091 if 'pythia_card.dat' in self.cards: 5092 if self.run_card['event_norm'] != 'sum': 5093 logger.info('Pythia6 needs a specific normalisation of the events. We will change it accordingly.', '$MG:color:BLACK' ) 5094 self.do_set('run_card event_norm sum') 5095 # @LO if PY6 shower => event_norm on sum 5096 elif 'pythia8_card.dat' in self.cards: 5097 if self.run_card['event_norm'] == 'sum': 5098 logger.info('Pythia8 needs a specific normalisation of the events. We will change it accordingly.', '$MG:color:BLACK' ) 5099 self.do_set('run_card event_norm average') 5100 5101 # Check the extralibs flag. 5102 if self.has_shower and isinstance(self.run_card, banner_mod.RunCardNLO): 5103 modify_extralibs, modify_extrapaths = False,False 5104 extralibs = self.shower_card['extralibs'].split() 5105 extrapaths = self.shower_card['extrapaths'].split() 5106 # remove default stdhep/Fmcfio for recent shower 5107 if self.run_card['parton_shower'] in ['PYTHIA8', 'HERWIGPP', 'HW7']: 5108 if 'stdhep' in self.shower_card['extralibs']: 5109 extralibs.remove('stdhep') 5110 modify_extralibs = True 5111 if 'Fmcfio' in self.shower_card['extralibs']: 5112 extralibs.remove('Fmcfio') 5113 modify_extralibs = True 5114 if self.run_card['parton_shower'] == 'PYTHIA8': 5115 # First check sanity of PY8 5116 if not self.mother_interface.options['pythia8_path']: 5117 raise self.mother.InvalidCmd, 'Pythia8 is not correctly specified to MadGraph5_aMC@NLO' 5118 executable = pjoin(self.mother_interface.options['pythia8_path'], 'bin', 'pythia8-config') 5119 if not os.path.exists(executable): 5120 raise self.mother.InvalidCmd, 'Pythia8 is not correctly specified to MadGraph5_aMC@NLO' 5121 5122 # 2. take the compilation flag of PY8 from pythia8-config 5123 libs , paths = [], [] 5124 p = misc.subprocess.Popen([executable, '--libs'], stdout=subprocess.PIPE) 5125 stdout, _ = p. communicate() 5126 libs = [x[2:] for x in stdout.split() if x.startswith('-l') or paths.append(x[2:])] 5127 5128 # Add additional user-defined compilation flags 5129 p = misc.subprocess.Popen([executable, '--config'], stdout=subprocess.PIPE) 5130 stdout, _ = p. communicate() 5131 for lib in ['-ldl','-lstdc++','-lc++']: 5132 if lib in stdout: 5133 libs.append(lib[2:]) 5134 5135 # This precompiler flag is in principle useful for the analysis if it writes HEPMC 5136 # events, but there is unfortunately no way for now to specify it in the shower_card. 5137 supports_HEPMCHACK = '-DHEPMC2HACK' in stdout 5138 5139 #3. ensure that those flag are in the shower card 5140 for l in libs: 5141 if l not in extralibs: 5142 modify_extralibs = True 5143 extralibs.append(l) 5144 for L in paths: 5145 if L not in extrapaths: 5146 modify_extrapaths = True 5147 extrapaths.append(L) 5148 5149 # Apply the required modification 5150 if modify_extralibs: 5151 if extralibs: 5152 self.do_set('shower_card extralibs %s ' % ' '.join(extralibs)) 5153 else: 5154 self.do_set('shower_card extralibs None ') 5155 if modify_extrapaths: 5156 if extrapaths: 5157 self.do_set('shower_card extrapaths %s ' % ' '.join(extrapaths)) 5158 else: 5159 self.do_set('shower_card extrapaths None ')
5160
5161 - def reask(self, *args, **opt):
5162 5163 cmd.OneLinePathCompletion.reask(self,*args, **opt) 5164 if self.has_mw and not os.path.exists(pjoin(self.me_dir,'Cards','transfer_card.dat')): 5165 logger.warning('No transfer function currently define. Please use the change_tf command to define one.')
5166 5167 fail_due_to_format = 0 #parameter to avoid infinite loop
5168 - def postcmd(self, stop, line):
5169 ending_question = cmd.OneLinePathCompletion.postcmd(self,stop,line) 5170 5171 if ending_question: 5172 self.check_card_consistency() 5173 try: 5174 self.do_update('dependent', timer=20) 5175 except MadGraph5Error, error: 5176 if 'Missing block:' in str(error): 5177 self.fail_due_to_format +=1 5178 if self.fail_due_to_format == 10: 5179 missing, unknow = str(error).split('\n')[-2:] 5180 logger.warning("Invalid param_card:\n%s\n%s\n" % (missing, unknow)) 5181 logger.info("Type \"update missing\" to use default value.\n ", '$MG:color:BLACK') 5182 self.value = False # to avoid that entering a command stop the question 5183 return self.reask(True) 5184 else: 5185 raise 5186 5187 return ending_question
5188 5189 5190 5191 5192
5193 - def do_update(self, line, timer=0):
5194 """ syntax: update dependent: Change the mass/width of particles which are not free parameter for the model. 5195 update missing: add to the current param_card missing blocks/parameters.""" 5196 5197 args = self.split_arg(line) 5198 if len(args)==0: 5199 logger.warning('miss an argument (dependent or missing). Please retry') 5200 return 5201 5202 if args[0] == 'dependent': 5203 if not self.mother_interface: 5204 logger.warning('Failed to update dependent parameter. This might create trouble for external program (like MadSpin/shower/...)') 5205 5206 pattern_width = re.compile(r'''decay\s+(\+?\-?\d+)\s+auto(@NLO|)''',re.I) 5207 pattern_scan = re.compile(r'''^(decay)?[\s\d]*scan''', re.I+re.M) 5208 param_text= open(self.paths['param']).read() 5209 5210 if pattern_scan.search(param_text): 5211 #for block, key in self.restricted_value: 5212 # self.param_card[block].get(key).value = -9.999e-99 5213 # self.param_card.write(self.paths['param']) 5214 return 5215 elif pattern_width.search(param_text): 5216 self.do_compute_widths('') 5217 self.param_card = check_param_card.ParamCard(self.paths['param']) 5218 5219 # calling the routine doing the work 5220 self.update_dependent(self.mother_interface, self.me_dir, self.param_card, 5221 self.paths['param'], timer) 5222 5223 elif args[0] == 'missing': 5224 self.update_missing() 5225 return
5226 5227 5228 5229 @staticmethod
5230 - def update_dependent(mecmd, me_dir, param_card, path ,timer=0):
5231 """static method which can also be called from outside the class 5232 usefull in presence of scan. 5233 return if the param_card was updated or not 5234 """ 5235 logger.info('Update the dependent parameter of the param_card.dat') 5236 modify = True 5237 class TimeOutError(Exception): 5238 pass
5239 def handle_alarm(signum, frame): 5240 raise TimeOutError 5241 signal.signal(signal.SIGALRM, handle_alarm) 5242 if timer: 5243 signal.alarm(timer) 5244 log_level=30 5245 else: 5246 log_level=20 5247 # Try to load the model in the limited amount of time allowed 5248 try: 5249 model = mecmd.get_model() 5250 signal.alarm(0) 5251 except TimeOutError: 5252 logger.warning('The model takes too long to load so we bypass the updating of dependent parameter.\n'+\ 5253 'This might create trouble for external program (like MadSpin/shower/...)\n'+\ 5254 'The update can be forced without timer by typing \'update dependent\' at the time of the card edition') 5255 modify =False 5256 except Exception,error: 5257 logger.debug(str(error)) 5258 logger.warning('Failed to update dependent parameter. This might create trouble for external program (like MadSpin/shower/...)') 5259 signal.alarm(0) 5260 else: 5261 restrict_card = pjoin(me_dir,'Source','MODEL','param_card_rule.dat') 5262 if not os.path.exists(restrict_card): 5263 restrict_card = None 5264 #restrict_card = None 5265 if model: 5266 modify = param_card.update_dependent(model, restrict_card, log_level) 5267 if modify and path: 5268 param_card.write(path) 5269 else: 5270 logger.warning('missing MG5aMC code. Fail to update dependent parameter. This might create trouble for program like MadSpin/shower/...') 5271 5272 if log_level==20: 5273 logger.info('param_card up to date.') 5274 5275 return modify 5276 5277 5278
5279 - def update_missing(self):
5280 5281 def check_block(self, blockname): 5282 add_entry = 0 5283 block = self.param_card_default[blockname] 5284 for key in block.keys(): 5285 if key not in input_in_block: 5286 param = block.get(key) 5287 if blockname != 'decay': 5288 text.append('\t%s\t%s # %s\n' % (' \t'.join([`i` for i in param.lhacode]), param.value, param.comment)) 5289 else: 5290 text.append('DECAY \t%s\t%s # %s\n' % (' \t'.join([`i` for i in param.lhacode]), param.value, param.comment)) 5291 add_entry += 1 5292 if add_entry: 5293 text.append('\n') 5294 return add_entry
5295 5296 # Add to the current param_card all the missing input at default value 5297 current_block = '' 5298 input_in_block = set() 5299 defined_blocks = set() 5300 decay = set() 5301 text = [] 5302 add_entry = 0 5303 for line in open(self.paths['param']): 5304 5305 new_block = re.findall(r'^\s*(block|decay)\s*(\w*)', line, re.I) 5306 if new_block: 5307 new_block = new_block[0] 5308 defined_blocks.add(new_block[1].lower()) 5309 if current_block: 5310 add_entry += check_block(self, current_block) 5311 5312 current_block= new_block[1] 5313 input_in_block = set() 5314 if new_block[0].lower() == 'decay': 5315 decay.add((int(new_block[1]),)) 5316 current_block = '' 5317 if new_block[1].lower() == 'qnumbers': 5318 current_block = '' 5319 5320 text.append(line) 5321 if not current_block: 5322 continue 5323 5324 #normal line. 5325 #strip comment 5326 line = line.split('#',1)[0] 5327 split = line.split() 5328 if not split: 5329 continue 5330 else: 5331 try: 5332 lhacode = [int(i) for i in split[:-1]] 5333 except: 5334 continue 5335 input_in_block.add(tuple(lhacode)) 5336 5337 if current_block: 5338 add_entry += check_block(self, current_block) 5339 5340 # special check for missing block 5341 for block in self.param_card_default: 5342 5343 if block.startswith(('qnumbers', 'decay')): 5344 continue 5345 5346 if block not in defined_blocks: 5347 add_entry += len(self.param_card_default[block]) 5348 text.append(str(self.param_card_default[block])) 5349 5350 # special check for the decay 5351 input_in_block = decay 5352 add_entry += check_block(self, 'decay') 5353 5354 if add_entry: 5355 logger.info('write new param_card with %s new parameter(s).', add_entry, '$MG:color:BLACK') 5356 open(self.paths['param'],'w').write(''.join(text)) 5357 self.reload_card(self.paths['param']) 5358 else: 5359 logger.info('No missing parameter detected.', '$MG:color:BLACK') 5360 5361
5362 - def check_answer_consistency(self):
5363 """function called if the code reads a file""" 5364 self.check_card_consistency() 5365 self.do_update('dependent', timer=20)
5366
5367 - def help_set(self):
5368 '''help message for set''' 5369 5370 logger.info('********************* HELP SET ***************************') 5371 logger.info("syntax: set [run_card|param_card|...] NAME [VALUE|default]") 5372 logger.info("syntax: set [param_card] BLOCK ID(s) [VALUE|default]") 5373 logger.info('') 5374 logger.info('-- Edit the param_card/run_card/... and replace the value of the') 5375 logger.info(' parameter by the value VALUE.') 5376 logger.info(' ') 5377 logger.info('-- Example:') 5378 logger.info(' set run_card ebeam1 4000') 5379 logger.info(' set ebeam2 4000') 5380 logger.info(' set lpp1 0') 5381 logger.info(' set ptj default') 5382 logger.info('') 5383 logger.info(' set param_card mass 6 175') 5384 logger.info(' set mass 25 125.3') 5385 logger.info(' set mass mh 125') 5386 logger.info(' set mh 125') 5387 logger.info(' set decay 25 0.004') 5388 logger.info(' set decay wh 0.004') 5389 logger.info(' set vmix 2 1 2.326612e-01') 5390 logger.info('') 5391 logger.info(' set param_card default #return all parameter to default') 5392 logger.info(' set run_card default') 5393 logger.info('********************* HELP SET ***************************')
5394 5395
5396 - def default(self, line):
5397 """Default action if line is not recognized""" 5398 5399 line = line.strip() 5400 args = line.split() 5401 if line == '' and self.default_value is not None: 5402 self.value = self.default_value 5403 # check if input is a file 5404 elif hasattr(self, 'do_%s' % args[0]): 5405 self.do_set(' '.join(args[1:])) 5406 elif os.path.isfile(line): 5407 self.copy_file(line) 5408 self.value = 'repeat' 5409 elif self.me_dir and os.path.exists(pjoin(self.me_dir, line)): 5410 self.copy_file(pjoin(self.me_dir,line)) 5411 self.value = 'repeat' 5412 elif line.strip() != '0' and line.strip() != 'done' and \ 5413 str(line) != 'EOF' and line.strip() in self.allow_arg: 5414 self.open_file(line) 5415 self.value = 'repeat' 5416 else: 5417 self.value = line 5418 5419 return line
5420
5421 - def do_decay(self, line):
5422 """edit the madspin_card to define the decay of the associate particle""" 5423 signal.alarm(0) # avoid timer if any 5424 path = self.paths['madspin'] 5425 5426 if 'madspin_card.dat' not in self.cards or not os.path.exists(path): 5427 logger.warning("Command decay not valid. Since MadSpin is not available.") 5428 return 5429 5430 if ">" not in line: 5431 logger.warning("invalid command for decay. Line ignored") 5432 return 5433 5434 if "-add" in line: 5435 # just to have to add the line to the end of the file 5436 particle = line.split('>')[0].strip() 5437 text = open(path).read() 5438 line = line.replace('--add', '').replace('-add','') 5439 logger.info("change madspin_card to add one decay to %s: %s" %(particle, line.strip()), '$MG:color:BLACK') 5440 5441 text = text.replace('launch', "\ndecay %s\nlaunch\n" % line,1) 5442 else: 5443 # Here we have to remove all the previous definition of the decay 5444 #first find the particle 5445 particle = line.split('>')[0].strip() 5446 logger.info("change madspin_card to define the decay of %s: %s" %(particle, line.strip()), '$MG:color:BLACK') 5447 particle = particle.replace('+','\+').replace('-','\-') 5448 decay_pattern = re.compile(r"^\s*decay\s+%s\s*>[\s\w+-~]*?$" % particle, re.I+re.M) 5449 text= open(path).read() 5450 text = decay_pattern.sub('', text) 5451 text = text.replace('launch', "\ndecay %s\nlaunch\n" % line,1) 5452 5453 with open(path,'w') as fsock: 5454 fsock.write(text)
5455 5456 5457
5458 - def do_compute_widths(self, line):
5459 signal.alarm(0) # avoid timer if any 5460 path = self.paths['param'] 5461 pattern = re.compile(r'''decay\s+(\+?\-?\d+)\s+auto(@NLO|)''',re.I) 5462 text = open(path).read() 5463 pdg_info = pattern.findall(text) 5464 has_nlo = any("@nlo"==nlo.lower() for _, nlo in pdg_info) 5465 pdg = [p for p,_ in pdg_info] 5466 5467 5468 line = '%s %s' % (line, ' '.join(pdg)) 5469 if not '--path' in line: 5470 line += ' --path=%s' % path 5471 if has_nlo: 5472 line += ' --nlo' 5473 5474 try: 5475 return self.mother_interface.do_compute_widths(line) 5476 except InvalidCmd, error: 5477 logger.error("Invalid command: %s " % error)
5478
5479 - def help_compute_widths(self):
5480 signal.alarm(0) # avoid timer if any 5481 return self.mother_interface.help_compute_widths()
5482
5483 - def help_decay(self):
5484 """help for command decay which modifies MadSpin_card""" 5485 5486 signal.alarm(0) # avoid timer if any 5487 print '--syntax: decay PROC [--add]' 5488 print ' ' 5489 print ' modify the madspin_card to modify the decay of the associate particle.' 5490 print ' and define it to PROC.' 5491 print ' if --add is present, just add a new decay for the associate particle.'
5492
5493 - def complete_compute_widths(self, *args, **opts):
5494 prev_timer = signal.alarm(0) # avoid timer if any 5495 if prev_timer: 5496 nb_back = len(line) 5497 self.stdout.write('\b'*nb_back + '[timer stopped]\n') 5498 self.stdout.write(line) 5499 self.stdout.flush() 5500 return self.mother_interface.complete_compute_widths(*args,**opts)
5501 5502
5503 - def help_add(self):
5504 """help for add command""" 5505 5506 logger.info('********************* HELP ADD ***************************') 5507 logger.info( '-- syntax: add pythia8_card NAME VALUE') 5508 logger.info( " add a definition of name in the pythia8_card with the given value") 5509 logger.info( " Do not work for the param_card" ) 5510 logger.info( '-- syntax: add filename [OPTION] line') 5511 logger.info( ' add the given LINE to the end of the associate file (all file supportedd).') 5512 logger.info( ' OPTION parameter allows to change the position where to write in the file') 5513 logger.info( ' --after_line=banner : write the line at the end of the banner') 5514 logger.info( ' --line_position=X : insert the line before line X (starts at 0)') 5515 logger.info( ' --after_line="<regular-expression>" write the line after the first line matching the regular expression') 5516 logger.info( ' --before_line="<regular-expression>" write the line before the first line matching the regular expression') 5517 logger.info( ' example: change reweight --after_line="^\s*change mode" change model heft') 5518 logger.info('********************* HELP ADD ***************************')
5519
5520 - def complete_add(self, text, line, begidx, endidx, formatting=True):
5521 """ auto-completion for add command""" 5522 5523 prev_timer = signal.alarm(0) # avoid timer if any 5524 if prev_timer: 5525 nb_back = len(line) 5526 self.stdout.write('\b'*nb_back + '[timer stopped]\n') 5527 self.stdout.write(line) 5528 self.stdout.flush() 5529 5530 split = line[:begidx].split() 5531 if len(split)==1: 5532 possibilities = {} 5533 cards = [c.rsplit('.',1)[0] for c in self.cards] 5534 possibilities['category of parameter (optional)'] = \ 5535 self.list_completion(text, cards) 5536 elif len(split) == 2: 5537 possibilities = {} 5538 options = ['--line_position=','--after_line=banner', '--after_line="','--before_line="'] 5539 possibilities['category of parameter (optional)'] = \ 5540 self.list_completion(text, options, line) 5541 else: 5542 return 5543 return self.deal_multiple_categories(possibilities, formatting)
5544
5545 - def do_add(self, line):
5546 """ syntax: add filename NAME VALUE 5547 syntax: add filename LINE""" 5548 5549 args = self.split_arg(line) 5550 if len(args) == 3 and args[0] in ['pythia8_card', 'pythia8_card.dat'] and self.has_PY8: 5551 name= args[1] 5552 value = args[2] 5553 self.PY8Card.userSet(name, value) 5554 self.PY8Card.write(pjoin(self.me_dir,'Cards','pythia8_card.dat'), 5555 pjoin(self.me_dir,'Cards','pythia8_card_default.dat'), 5556 print_only_visible=True) 5557 logger.info("add in the pythia8_card the parameter \"%s\" with value \"%s\"" % (name, value), '$MG:color:BLACK') 5558 elif len(args) > 0: 5559 if args[0] in self.cards: 5560 card = args[0] 5561 elif "%s.dat" % args[0] in self.cards: 5562 card = "%s.dat" % args[0] 5563 elif "%s_card.dat" % args[0] in self.cards: 5564 card = "%s_card.dat" % args[0] 5565 elif self.has_ml and args[0].lower() == "madloop": 5566 card = "MadLoopParams.dat" 5567 else: 5568 logger.error("unknow card %s. Please retry." % args[0]) 5569 return 5570 5571 # handling the various option on where to write the line 5572 if args[1].startswith('--line_position='): 5573 #position in file determined by user 5574 text = open(pjoin(self.me_dir,'Cards',card)).read() 5575 split = text.split('\n') 5576 pos = int(args[1].split('=',1)[1]) 5577 newline = line.split(None,2)[2] 5578 split.insert(pos, newline) 5579 ff = open(pjoin(self.me_dir,'Cards',card),'w') 5580 ff.write('\n'.join(split)) 5581 logger.info("writting at line %d of the file %s the line: \"%s\"" %(pos, card, line.split(None,1)[1] )) 5582 5583 elif args[1].startswith('--after_line=banner'): 5584 # write the line at the first not commented line 5585 text = open(pjoin(self.me_dir,'Cards',card)).read() 5586 split = text.split('\n') 5587 for posline,l in enumerate(split): 5588 if not l.startswith('#'): 5589 break 5590 split.insert(posline, line.split(None,2)[2]) 5591 ff = open(pjoin(self.me_dir,'Cards',card),'w') 5592 ff.write('\n'.join(split)) 5593 logger.info("writting at line %d of the file %s the line: \"%s\"" %(posline, card, line.split(None,1)[1] )) 5594 5595 elif args[1].startswith('--before_line='): 5596 # catch the line/regular expression and write before that line 5597 text = open(pjoin(self.me_dir,'Cards',card)).read() 5598 split = text.split('\n') 5599 search_pattern=r'''before_line=(?P<quote>["'])(?:(?=(\\?))\2.)*?\1''' 5600 pattern = re.search(search_pattern, line).group()[13:-1] 5601 for posline,l in enumerate(split): 5602 if re.search(pattern, l): 5603 break 5604 else: 5605 raise Exception, 'invalid regular expression: not found in file' 5606 split.insert(posline, re.split(search_pattern,line)[-1]) 5607 ff = open(pjoin(self.me_dir,'Cards',card),'w') 5608 ff.write('\n'.join(split)) 5609 logger.info("writting at line %d of the file %s the line: \"%s\"" %(posline, card, line.split(None,1)[1] )) 5610 5611 5612 5613 elif args[1].startswith('--after_line='): 5614 # catch the line/regular expression and write after that line 5615 text = open(pjoin(self.me_dir,'Cards',card)).read() 5616 split = text.split('\n') 5617 search_pattern = r'''after_line=(?P<quote>["'])(?:(?=(\\?))\2.)*?\1''' 5618 pattern = re.search(search_pattern, line).group()[12:-1] 5619 for posline,l in enumerate(split): 5620 if re.search(pattern, l): 5621 break 5622 else: 5623 posline=len(split) 5624 split.insert(posline+1, re.split(search_pattern,line)[-1]) 5625 ff = open(pjoin(self.me_dir,'Cards',card),'w') 5626 ff.write('\n'.join(split)) 5627 logger.info("writting at line %d of the file %s the line: \"%s\"" %(posline, card, line.split(None,1)[1] )) 5628 else: 5629 ff = open(pjoin(self.me_dir,'Cards',card),'a') 5630 ff.write("%s \n" % line.split(None,1)[1]) 5631 ff.close() 5632 logger.info("adding at the end of the file %s the line: \"%s\"" %(card, line.split(None,1)[1] )) 5633 self.reload_card(pjoin(self.me_dir,'Cards',card))
5634 5635 5636
5637 - def help_asperge(self):
5638 """Help associated to the asperge command""" 5639 signal.alarm(0) 5640 5641 print '-- syntax: asperge [options]' 5642 print ' Call ASperGe to diagonalize all mass matrices in the model.' 5643 print ' This works only if the ASperGE module is part of the UFO model (a subdirectory).' 5644 print ' If you specify some names after the command (i.e. asperge m1 m2) then ASperGe will only' 5645 print ' diagonalize the associate mass matrices (here m1 and m2).'
5646
5647 - def complete_asperge(self, text, line, begidx, endidx, formatting=True):
5648 prev_timer = signal.alarm(0) # avoid timer if any 5649 if prev_timer: 5650 nb_back = len(line) 5651 self.stdout.write('\b'*nb_back + '[timer stopped]\n') 5652 self.stdout.write(line) 5653 self.stdout.flush() 5654 blockname = self.pname2block.keys() 5655 # remove those that we know for sure are not mixing 5656 wrong = ['decay', 'mass', 'sminput'] 5657 valid = [k for k in blockname if 'mix' in k] 5658 potential = [k for k in blockname if k not in valid+wrong] 5659 output = {'Mixing matrices': self.list_completion(text, valid, line), 5660 'Other potential valid input': self.list_completion(text, potential, line)} 5661 5662 return self.deal_multiple_categories(output, formatting)
5663 5664
5665 - def do_asperge(self, line):
5666 """Running ASperGe""" 5667 signal.alarm(0) # avoid timer if any 5668 5669 path = pjoin(self.me_dir,'bin','internal','ufomodel','ASperGE') 5670 if not os.path.exists(path): 5671 logger.error('ASperge has not been detected in the current model, therefore it will not be run.') 5672 return 5673 elif not os.path.exists(pjoin(path,'ASperGe')): 5674 logger.info('ASperGe has been detected but is not compiled. Running the compilation now.') 5675 try: 5676 misc.compile(cwd=path,shell=True) 5677 except MadGraph5Error, error: 5678 logger.error('''ASperGe failed to compile. Note that gsl is needed 5679 for this compilation to go trough. More information on how to install this package on 5680 http://www.gnu.org/software/gsl/ 5681 Full compilation log is available at %s''' % pjoin(self.me_dir, 'ASperge_compilation.log')) 5682 open(pjoin(self.me_dir, 'ASperge_compilation.log'),'w').write(str(error)) 5683 return 5684 5685 opts = line.split() 5686 card = self.paths['param'] 5687 logger.info('running ASperGE') 5688 returncode = misc.call([pjoin(path,'ASperGe'), card, '%s.new' % card] + opts) 5689 if returncode: 5690 logger.error('ASperGE fails with status %s' % returncode) 5691 else: 5692 logger.info('AsPerGe creates the file succesfully') 5693 files.mv(card, '%s.beforeasperge' % card) 5694 files.mv('%s.new' % card, card)
5695 5696 5697
5698 - def copy_file(self, path):
5699 """detect the type of the file and overwritte the current file""" 5700 5701 if path.endswith('.lhco'): 5702 #logger.info('copy %s as Events/input.lhco' % (path)) 5703 #files.cp(path, pjoin(self.mother_interface.me_dir, 'Events', 'input.lhco' )) 5704 self.do_set('mw_run inputfile %s' % os.path.relpath(path, self.mother_interface.me_dir)) 5705 return 5706 elif path.endswith('.lhco.gz'): 5707 #logger.info('copy %s as Events/input.lhco.gz' % (path)) 5708 #files.cp(path, pjoin(self.mother_interface.me_dir, 'Events', 'input.lhco.gz' )) 5709 self.do_set('mw_run inputfile %s' % os.path.relpath(path, self.mother_interface.me_dir)) 5710 return 5711 else: 5712 card_name = CommonRunCmd.detect_card_type(path) 5713 5714 if card_name == 'unknown': 5715 logger.warning('Fail to determine the type of the file. Not copied') 5716 if card_name != 'banner': 5717 logger.info('copy %s as %s' % (path, card_name)) 5718 files.cp(path, self.paths[card_name.split('_',1)[0]]) 5719 self.reload_card(self.paths[card_name.split('_',1)[0]]) 5720 elif card_name == 'banner': 5721 banner_mod.split_banner(path, self.mother_interface.me_dir, proc_card=False) 5722 logger.info('Splitting the banner in it\'s component') 5723 if not self.mode == 'auto': 5724 self.mother_interface.keep_cards(self.cards) 5725 for card_name in self.cards: 5726 self.reload_card(pjoin(self.me_dir, 'Cards', card_name))
5727
5728 - def open_file(self, answer):
5729 """open the file""" 5730 try: 5731 me_dir = self.mother_interface.me_dir 5732 except: 5733 me_dir = None 5734 5735 if answer.isdigit(): 5736 if answer == '9': 5737 answer = 'plot' 5738 else: 5739 answer = self.cards[int(answer)-1] 5740 5741 if 'madweight' in answer: 5742 answer = answer.replace('madweight', 'MadWeight') 5743 elif 'MadLoopParams' in answer: 5744 answer = self.paths['ML'] 5745 elif 'pythia8_card' in answer: 5746 answer = self.paths['PY8'] 5747 if os.path.exists(answer): 5748 path = answer 5749 else: 5750 if not '.dat' in answer and not '.lhco' in answer: 5751 if answer != 'trigger': 5752 path = self.paths[answer] 5753 else: 5754 path = self.paths['delphes'] 5755 elif not '.lhco' in answer: 5756 if '_' in answer: 5757 path = self.paths['_'.join(answer.split('_')[:-1])] 5758 else: 5759 path = pjoin(me_dir, 'Cards', answer) 5760 else: 5761 path = pjoin(me_dir, self.mw_card['mw_run']['inputfile']) 5762 if not os.path.exists(path): 5763 logger.info('Path in MW_card not existing') 5764 path = pjoin(me_dir, 'Events', answer) 5765 #security 5766 path = path.replace('_card_card','_card') 5767 try: 5768 self.mother_interface.exec_cmd('open %s' % path) 5769 except InvalidCmd, error: 5770 if str(error) != 'No default path for this file': 5771 raise 5772 if answer == 'transfer_card.dat': 5773 logger.warning('You have to specify a transfer function first!') 5774 elif answer == 'input.lhco': 5775 path = pjoin(me_dir,'Events', 'input.lhco') 5776 ff = open(path,'w') 5777 ff.write('''No LHCO information imported at current time. 5778 To import a lhco file: Close this file and type the path of your file. 5779 You can also copy/paste, your event file here.''') 5780 ff.close() 5781 self.open_file(path) 5782 else: 5783 raise 5784 self.reload_card(path)
5785
5786 - def reload_card(self, path):
5787 """reload object to have it in sync""" 5788 5789 if path == self.paths['param']: 5790 try: 5791 self.param_card = check_param_card.ParamCard(path) 5792 except (check_param_card.InvalidParamCard, ValueError) as e: 5793 logger.error('Current param_card is not valid. We are going to use the default one.') 5794 logger.error('problem detected: %s' % e) 5795 logger.error('Please re-open the file and fix the problem.') 5796 logger.warning('using the \'set\' command without opening the file will discard all your manual change') 5797 elif path == self.paths['run']: 5798 self.run_card = banner_mod.RunCard(path) 5799 elif path == self.paths['ML']: 5800 self.MLcard = banner_mod.MadLoopParam(path) 5801 elif path == self.paths['PY8']: 5802 # Use the read function so that modified/new parameters are correctly 5803 # set as 'user_set' 5804 if not self.PY8Card: 5805 self.PY8Card = banner_mod.PY8Card(self.paths['PY8_default']) 5806 5807 self.PY8Card.read(self.paths['PY8'], setter='user') 5808 self.py8_vars = [k.lower() for k in self.PY8Card.keys()] 5809 elif path == self.paths['MadWeight']: 5810 try: 5811 import madgraph.madweight.Cards as mwcards 5812 except: 5813 import internal.madweight.Cards as mwcards 5814 self.mw_card = mwcards.Card(path) 5815 return path 5816
5817 -class EditParamCard(AskforEditCard):
5818 """a dedicated module for the param""" 5819 5820 special_shortcut ={} 5821
5822 - def __init__(self, question, card=[], mode='auto', *args, **opt):
5823 5824 self.load_default() 5825 cmd.OneLinePathCompletion.__init__(self, question, *args, **opt) 5826 if os.path.isfile(card[0]): 5827 self.param_card = check_param_card.ParamCard(card[0]) 5828 self.paths['param'] = card[0] 5829 if os.path.isfile(card[0].replace('.dat', '_default.dat')): 5830 self.paths['param_default'] = card[0].replace('.dat', '_default.dat') 5831 else: 5832 self.paths['param_default'] = card[0] 5833 else: 5834 raise Exception, 'path %s do not exists' % card[0] 5835 5836 self.pname2block, self.restricted_value = self.param_card.analyze_param_card() 5837 self.cards=['param']
5838
5839 - def do_asperge(self, *args, **opts):
5840 "Not available" 5841 logger.warning("asperge not available in this mode")
5842