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