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