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