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