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