Package madgraph :: Package interface :: Module madevent_interface
[hide private]
[frames] | no frames]

Source Code for Module madgraph.interface.madevent_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  import collections 
  21  import glob 
  22  import logging 
  23  import math 
  24  import os 
  25  import random 
  26  import re 
  27   
  28  import stat 
  29  import subprocess 
  30  import sys 
  31  import time 
  32  import tarfile 
  33  import StringIO 
  34  import shutil 
  35  import copy 
  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('madevent.stdout') # -> stdout 
  51  logger_stderr = logging.getLogger('madevent.stderr') # ->stderr 
  52    
  53  try: 
  54      import madgraph 
  55  except ImportError:  
  56      # import from madevent directory 
  57      MADEVENT = True 
  58      import internal.extended_cmd as cmd 
  59      import internal.common_run_interface as common_run 
  60      import internal.banner as banner_mod 
  61      import internal.misc as misc 
  62      from internal import InvalidCmd, MadGraph5Error, ReadWrite 
  63      import internal.files as files 
  64      import internal.gen_crossxhtml as gen_crossxhtml 
  65      import internal.gen_ximprove as gen_ximprove 
  66      import internal.save_load_object as save_load_object 
  67      import internal.cluster as cluster 
  68      import internal.check_param_card as check_param_card 
  69      import internal.sum_html as sum_html 
  70      import internal.combine_runs as combine_runs 
  71      import internal.lhe_parser as lhe_parser 
  72  #    import internal.histograms as histograms # imported later to not slow down the loading of the code 
  73      from internal.files import ln 
  74  else: 
  75      # import from madgraph directory 
  76      MADEVENT = False 
  77      import madgraph.interface.extended_cmd as cmd 
  78      import madgraph.interface.common_run_interface as common_run 
  79      import madgraph.iolibs.files as files 
  80      import madgraph.iolibs.save_load_object as save_load_object 
  81      import madgraph.madevent.gen_crossxhtml as gen_crossxhtml 
  82      import madgraph.madevent.gen_ximprove as gen_ximprove 
  83      import madgraph.madevent.sum_html as sum_html 
  84      import madgraph.various.banner as banner_mod 
  85      import madgraph.various.cluster as cluster 
  86      import madgraph.various.misc as misc 
  87      import madgraph.madevent.combine_runs as combine_runs 
  88      import madgraph.various.lhe_parser as lhe_parser 
  89  #    import madgraph.various.histograms as histograms  # imported later to not slow down the loading of the code 
  90      import models.check_param_card as check_param_card 
  91      from madgraph.iolibs.files import ln     
  92      from madgraph import InvalidCmd, MadGraph5Error, MG5DIR, ReadWrite 
93 94 95 96 -class MadEventError(Exception):
97 pass
98
99 -class ZeroResult(MadEventError):
100 pass
101
102 -class SysCalcError(InvalidCmd): pass
103 104 MadEventAlreadyRunning = common_run.MadEventAlreadyRunning
105 106 #=============================================================================== 107 # CmdExtended 108 #=============================================================================== 109 -class CmdExtended(common_run.CommonRunCmd):
110 """Particularisation of the cmd command for MadEvent""" 111 112 #suggested list of command 113 next_possibility = { 114 'start': [], 115 } 116 117 debug_output = 'ME5_debug' 118 error_debug = 'Please report this bug on https://bugs.launchpad.net/mg5amcnlo\n' 119 error_debug += 'More information is found in \'%(debug)s\'.\n' 120 error_debug += 'Please attach this file to your report.' 121 122 config_debug = 'If you need help with this issue please contact us on https://answers.launchpad.net/mg5amcnlo\n' 123 124 125 keyboard_stop_msg = """stopping all operation 126 in order to quit MadGraph5_aMC@NLO please enter exit""" 127 128 # Define the Error 129 InvalidCmd = InvalidCmd 130 ConfigurationError = MadGraph5Error 131
132 - def __init__(self, me_dir, options, *arg, **opt):
133 """Init history and line continuation""" 134 135 # Tag allowing/forbiding question 136 self.force = False 137 138 # If possible, build an info line with current version number 139 # and date, from the VERSION text file 140 info = misc.get_pkg_info() 141 info_line = "" 142 if info and info.has_key('version') and info.has_key('date'): 143 len_version = len(info['version']) 144 len_date = len(info['date']) 145 if len_version + len_date < 30: 146 info_line = "#* VERSION %s %s %s *\n" % \ 147 (info['version'], 148 (30 - len_version - len_date) * ' ', 149 info['date']) 150 else: 151 version = open(pjoin(root_path,'MGMEVersion.txt')).readline().strip() 152 info_line = "#* VERSION %s %s *\n" % \ 153 (version, (24 - len(version)) * ' ') 154 155 # Create a header for the history file. 156 # Remember to fill in time at writeout time! 157 self.history_header = \ 158 '#************************************************************\n' + \ 159 '#* MadGraph5_aMC@NLO/MadEvent *\n' + \ 160 '#* *\n' + \ 161 "#* * * *\n" + \ 162 "#* * * * * *\n" + \ 163 "#* * * * * 5 * * * * *\n" + \ 164 "#* * * * * *\n" + \ 165 "#* * * *\n" + \ 166 "#* *\n" + \ 167 "#* *\n" + \ 168 info_line + \ 169 "#* *\n" + \ 170 "#* The MadGraph5_aMC@NLO Development Team - Find us at *\n" + \ 171 "#* https://server06.fynu.ucl.ac.be/projects/madgraph *\n" + \ 172 '#* *\n' + \ 173 '#************************************************************\n' + \ 174 '#* *\n' + \ 175 '#* Command File for MadEvent *\n' + \ 176 '#* *\n' + \ 177 '#* run as ./bin/madevent.py filename *\n' + \ 178 '#* *\n' + \ 179 '#************************************************************\n' 180 181 if info_line: 182 info_line = info_line[1:] 183 184 logger.info(\ 185 "************************************************************\n" + \ 186 "* *\n" + \ 187 "* W E L C O M E to *\n" + \ 188 "* M A D G R A P H 5 _ a M C @ N L O *\n" + \ 189 "* M A D E V E N T *\n" + \ 190 "* *\n" + \ 191 "* * * *\n" + \ 192 "* * * * * *\n" + \ 193 "* * * * * 5 * * * * *\n" + \ 194 "* * * * * *\n" + \ 195 "* * * *\n" + \ 196 "* *\n" + \ 197 info_line + \ 198 "* *\n" + \ 199 "* The MadGraph5_aMC@NLO Development Team - Find us at *\n" + \ 200 "* https://server06.fynu.ucl.ac.be/projects/madgraph *\n" + \ 201 "* *\n" + \ 202 "* Type 'help' for in-line help. *\n" + \ 203 "* *\n" + \ 204 "************************************************************") 205 super(CmdExtended, self).__init__(me_dir, options, *arg, **opt)
206
207 - def get_history_header(self):
208 """return the history header""" 209 return self.history_header % misc.get_time_info()
210
211 - def stop_on_keyboard_stop(self):
212 """action to perform to close nicely on a keyboard interupt""" 213 try: 214 if hasattr(self, 'cluster'): 215 logger.info('rm jobs on queue') 216 self.cluster.remove() 217 if hasattr(self, 'results'): 218 self.update_status('Stop by the user', level=None, makehtml=False, error=True) 219 self.add_error_log_in_html(KeyboardInterrupt) 220 except: 221 pass
222
223 - def postcmd(self, stop, line):
224 """ Update the status of the run for finishing interactive command """ 225 226 stop = super(CmdExtended, self).postcmd(stop, line) 227 # relaxing the tag forbidding question 228 self.force = False 229 230 if not self.use_rawinput: 231 return stop 232 233 if self.results and not self.results.current: 234 return stop 235 236 arg = line.split() 237 if len(arg) == 0: 238 return stop 239 if isinstance(self.results.status, str) and self.results.status.startswith('Error'): 240 return stop 241 if isinstance(self.results.status, str) and self.results.status == 'Stop by the user': 242 self.update_status('%s Stop by the user' % arg[0], level=None, error=True) 243 return stop 244 elif not self.results.status: 245 return stop 246 elif str(arg[0]) in ['exit','quit','EOF']: 247 return stop 248 249 try: 250 self.update_status('Command \'%s\' done.<br> Waiting for instruction.' % arg[0], 251 level=None, error=True) 252 except Exception: 253 misc.sprint('update_status fails') 254 pass
255 256
257 - def nice_user_error(self, error, line):
258 """If a ME run is currently running add a link in the html output""" 259 260 self.add_error_log_in_html() 261 cmd.Cmd.nice_user_error(self, error, line)
262
263 - def nice_config_error(self, error, line):
264 """If a ME run is currently running add a link in the html output""" 265 266 self.add_error_log_in_html() 267 cmd.Cmd.nice_config_error(self, error, line) 268 269 270 try: 271 debug_file = open(self.debug_output, 'a') 272 debug_file.write(open(pjoin(self.me_dir,'Cards','proc_card_mg5.dat'))) 273 debug_file.close() 274 except: 275 pass
276 277
278 - def nice_error_handling(self, error, line):
279 """If a ME run is currently running add a link in the html output""" 280 281 if isinstance(error, ZeroResult): 282 self.add_error_log_in_html(error) 283 logger.warning('Zero result detected: %s' % error) 284 # create a banner if needed 285 try: 286 if not self.banner: 287 self.banner = banner_mod.Banner() 288 if 'slha' not in self.banner: 289 self.banner.add(pjoin(self.me_dir,'Cards','param_card.dat')) 290 if 'mgruncard' not in self.banner: 291 self.banner.add(pjoin(self.me_dir,'Cards','run_card.dat')) 292 if 'mg5proccard' not in self.banner: 293 proc_card = pjoin(self.me_dir,'Cards','proc_card_mg5.dat') 294 if os.path.exists(proc_card): 295 self.banner.add(proc_card) 296 297 out_dir = pjoin(self.me_dir, 'Events', self.run_name) 298 if not os.path.isdir(out_dir): 299 os.mkdir(out_dir) 300 output_path = pjoin(out_dir, '%s_%s_banner.txt' % \ 301 (self.run_name, self.run_tag)) 302 self.banner.write(output_path) 303 except Exception: 304 if __debug__: 305 raise 306 else: 307 pass 308 else: 309 self.add_error_log_in_html() 310 cmd.Cmd.nice_error_handling(self, error, line) 311 try: 312 debug_file = open(self.debug_output, 'a') 313 debug_file.write(open(pjoin(self.me_dir,'Cards','proc_card_mg5.dat'))) 314 debug_file.close() 315 except: 316 pass
317
318 319 #=============================================================================== 320 # HelpToCmd 321 #=============================================================================== 322 -class HelpToCmd(object):
323 """ The Series of help routine for the MadEventCmd""" 324
325 - def help_pythia(self):
326 logger.info("syntax: pythia [RUN] [--run_options]") 327 logger.info("-- run pythia on RUN (current one by default)") 328 self.run_options_help([('-f','answer all question by default'), 329 ('--tag=', 'define the tag for the pythia run'), 330 ('--no_default', 'not run if pythia_card not present')])
331
332 - def help_pythia8(self):
333 logger.info("syntax: pythia8 [RUN] [--run_options]") 334 logger.info("-- run pythia8 on RUN (current one by default)") 335 self.run_options_help([('-f','answer all question by default'), 336 ('--tag=', 'define the tag for the pythia8 run'), 337 ('--no_default', 'not run if pythia8_card not present')])
338
339 - def help_banner_run(self):
340 logger.info("syntax: banner_run Path|RUN [--run_options]") 341 logger.info("-- Reproduce a run following a given banner") 342 logger.info(" One of the following argument is require:") 343 logger.info(" Path should be the path of a valid banner.") 344 logger.info(" RUN should be the name of a run of the current directory") 345 self.run_options_help([('-f','answer all question by default'), 346 ('--name=X', 'Define the name associated with the new run')])
347
348 - def help_open(self):
349 logger.info("syntax: open FILE ") 350 logger.info("-- open a file with the appropriate editor.") 351 logger.info(' If FILE belongs to index.html, param_card.dat, run_card.dat') 352 logger.info(' the path to the last created/used directory is used') 353 logger.info(' The program used to open those files can be chosen in the') 354 logger.info(' configuration file ./input/mg5_configuration.txt')
355 356
357 - def run_options_help(self, data):
358 if data: 359 logger.info('-- local options:') 360 for name, info in data: 361 logger.info(' %s : %s' % (name, info)) 362 363 logger.info("-- session options:") 364 logger.info(" Note that those options will be kept for the current session") 365 logger.info(" --cluster : Submit to the cluster. Current cluster: %s" % self.options['cluster_type']) 366 logger.info(" --multicore : Run in multi-core configuration") 367 logger.info(" --nb_core=X : limit the number of core to use to X.")
368 369
370 - def help_generate_events(self):
371 logger.info("syntax: generate_events [run_name] [options]",) 372 logger.info("-- Launch the full chain of script for the generation of events") 373 logger.info(" Including possible plotting, shower and detector resolution.") 374 logger.info(" Those steps are performed if the related program are installed") 375 logger.info(" and if the related card are present in the Cards directory.") 376 self.run_options_help([('-f', 'Use default for all questions.'), 377 ('--laststep=', 'argument might be parton/pythia/pgs/delphes and indicate the last level to be run.'), 378 ('-M', 'in order to add MadSpin'), 379 ('-R', 'in order to add the reweighting module')])
380
381 - def help_initMadLoop(self):
382 logger.info("syntax: initMadLoop [options]",'$MG:color:GREEN') 383 logger.info( 384 """-- Command only useful when MadEvent simulates loop-induced processes. This command compiles and run 385 the MadLoop output for the matrix element computation so as to initialize the filter for analytically 386 zero helicity configurations and loop topologies. If you suspect that a change you made in the model 387 parameters can have affected these filters, this command allows you to automatically refresh them. """) 388 logger.info(" The available options are:",'$MG:color:BLUE') 389 logger.info(" -f : Bypass the edition of MadLoopParams.dat.",'$MG:color:BLUE') 390 logger.info(" -r : Refresh of the existing filters (erasing them if already present).",'$MG:color:BLUE') 391 logger.info(" --nPS=<int> : Specify how many phase-space points should be tried to set up the filters.",'$MG:color:BLUE')
392
393 - def help_add_time_of_flight(self):
394 logger.info("syntax: add_time_of_flight [run_name|path_to_file] [--threshold=]") 395 logger.info('-- Add in the lhe files the information') 396 logger.info(' of how long it takes to a particle to decay.') 397 logger.info(' threshold option allows to change the minimal value required to') 398 logger.info(' a non zero value for the particle (default:1e-12s)')
399
401 402 if self.ninitial != 1: 403 logger.warning("This command is only valid for processes of type A > B C.") 404 logger.warning("This command can not be run in current context.") 405 logger.warning("") 406 407 logger.info("syntax: calculate_decay_widths [run_name] [options])") 408 logger.info("-- Calculate decay widths and enter widths and BRs in param_card") 409 logger.info(" for a series of processes of type A > B C ...") 410 self.run_options_help([('-f', 'Use default for all questions.'), 411 ('--accuracy=', 'accuracy (for each partial decay width).'\ 412 + ' Default is 0.01.')])
413
414 - def help_multi_run(self):
415 logger.info("syntax: multi_run NB_RUN [run_name] [--run_options])") 416 logger.info("-- Launch the full chain of script for the generation of events") 417 logger.info(" NB_RUN times. This chains includes possible plotting, shower") 418 logger.info(" and detector resolution.") 419 self.run_options_help([('-f', 'Use default for all questions.'), 420 ('--laststep=', 'argument might be parton/pythia/pgs/delphes and indicate the last level to be run.')])
421
422 - def help_survey(self):
423 logger.info("syntax: survey [run_name] [--run_options])") 424 logger.info("-- evaluate the different channel associate to the process") 425 self.run_options_help([("--" + key,value[-1]) for (key,value) in \ 426 self._survey_options.items()])
427
428 - def help_launch(self):
429 """exec generate_events for 2>N and calculate_width for 1>N""" 430 logger.info("syntax: launch [run_name] [options])") 431 logger.info(" --alias for either generate_events/calculate_decay_widths") 432 logger.info(" depending of the number of particles in the initial state.") 433 434 if self.ninitial == 1: 435 logger.info("For this directory this is equivalent to calculate_decay_widths") 436 self.help_calculate_decay_widths() 437 else: 438 logger.info("For this directory this is equivalent to $generate_events") 439 self.help_generate_events()
440
441 - def help_refine(self):
442 logger.info("syntax: refine require_precision [max_channel] [--run_options]") 443 logger.info("-- refine the LAST run to achieve a given precision.") 444 logger.info(" require_precision: can be either the targeted number of events") 445 logger.info(' or the required relative error') 446 logger.info(' max_channel:[5] maximal number of channel per job') 447 self.run_options_help([])
448
449 - def help_combine_events(self):
450 """ """ 451 logger.info("syntax: combine_events [run_name] [--tag=tag_name] [--run_options]") 452 logger.info("-- Combine the last run in order to write the number of events") 453 logger.info(" asked in the run_card.") 454 self.run_options_help([])
455
456 - def help_store_events(self):
457 """ """ 458 logger.info("syntax: store_events [--run_options]") 459 logger.info("-- Write physically the events in the files.") 460 logger.info(" should be launch after \'combine_events\'") 461 self.run_options_help([])
462
463 - def help_create_gridpack(self):
464 """ """ 465 logger.info("syntax: create_gridpack [--run_options]") 466 logger.info("-- create the gridpack. ") 467 logger.info(" should be launch after \'store_events\'") 468 self.run_options_help([])
469
470 - def help_import(self):
471 """ """ 472 logger.info("syntax: import command PATH") 473 logger.info("-- Execute the command present in the file") 474 self.run_options_help([])
475
476 - def help_syscalc(self):
477 logger.info("syntax: syscalc [RUN] [%s] [-f | --tag=]" % '|'.join(self._plot_mode)) 478 logger.info("-- calculate systematics information for the RUN (current run by default)") 479 logger.info(" at different stages of the event generation for scale/pdf/...")
480
481 - def help_remove(self):
482 logger.info("syntax: remove RUN [all|parton|pythia|pgs|delphes|banner] [-f] [--tag=]") 483 logger.info("-- Remove all the files linked to previous run RUN") 484 logger.info(" if RUN is 'all', then all run will be cleaned.") 485 logger.info(" The optional argument precise which part should be cleaned.") 486 logger.info(" By default we clean all the related files but the banners.") 487 logger.info(" the optional '-f' allows to by-pass all security question") 488 logger.info(" The banner can be remove only if all files are removed first.")
489
490 491 492 #=============================================================================== 493 # CheckValidForCmd 494 #=============================================================================== 495 -class CheckValidForCmd(object):
496 """ The Series of check routine for the MadEventCmd""" 497
498 - def check_banner_run(self, args):
499 """check the validity of line""" 500 501 if len(args) == 0: 502 self.help_banner_run() 503 raise self.InvalidCmd('banner_run requires at least one argument.') 504 505 tag = [a[6:] for a in args if a.startswith('--tag=')] 506 507 508 if os.path.exists(args[0]): 509 type ='banner' 510 format = self.detect_card_type(args[0]) 511 if format != 'banner': 512 raise self.InvalidCmd('The file is not a valid banner.') 513 elif tag: 514 args[0] = pjoin(self.me_dir,'Events', args[0], '%s_%s_banner.txt' % \ 515 (args[0], tag)) 516 if not os.path.exists(args[0]): 517 raise self.InvalidCmd('No banner associates to this name and tag.') 518 else: 519 name = args[0] 520 type = 'run' 521 banners = misc.glob('*_banner.txt', pjoin(self.me_dir,'Events', args[0])) 522 if not banners: 523 raise self.InvalidCmd('No banner associates to this name.') 524 elif len(banners) == 1: 525 args[0] = banners[0] 526 else: 527 #list the tag and propose those to the user 528 tags = [os.path.basename(p)[len(args[0])+1:-11] for p in banners] 529 tag = self.ask('which tag do you want to use?', tags[0], tags) 530 args[0] = pjoin(self.me_dir,'Events', args[0], '%s_%s_banner.txt' % \ 531 (args[0], tag)) 532 533 run_name = [arg[7:] for arg in args if arg.startswith('--name=')] 534 if run_name: 535 try: 536 self.exec_cmd('remove %s all banner -f' % run_name) 537 except Exception: 538 pass 539 self.set_run_name(args[0], tag=None, level='parton', reload_card=True) 540 elif type == 'banner': 541 self.set_run_name(self.find_available_run_name(self.me_dir)) 542 elif type == 'run': 543 if not self.results[name].is_empty(): 544 run_name = self.find_available_run_name(self.me_dir) 545 logger.info('Run %s is not empty so will use run_name: %s' % \ 546 (name, run_name)) 547 self.set_run_name(run_name) 548 else: 549 try: 550 self.exec_cmd('remove %s all banner -f' % run_name) 551 except Exception: 552 pass 553 self.set_run_name(name)
554
555 - def check_history(self, args):
556 """check the validity of line""" 557 558 if len(args) > 1: 559 self.help_history() 560 raise self.InvalidCmd('\"history\" command takes at most one argument') 561 562 if not len(args): 563 return 564 elif args[0] != 'clean': 565 dirpath = os.path.dirname(args[0]) 566 if dirpath and not os.path.exists(dirpath) or \ 567 os.path.isdir(args[0]): 568 raise self.InvalidCmd("invalid path %s " % dirpath)
569
570 - def check_save(self, args):
571 """ check the validity of the line""" 572 573 if len(args) == 0: 574 args.append('options') 575 576 if args[0] not in self._save_opts: 577 raise self.InvalidCmd('wrong \"save\" format') 578 579 if args[0] != 'options' and len(args) != 2: 580 self.help_save() 581 raise self.InvalidCmd('wrong \"save\" format') 582 elif args[0] != 'options' and len(args) == 2: 583 basename = os.path.dirname(args[1]) 584 if not os.path.exists(basename): 585 raise self.InvalidCmd('%s is not a valid path, please retry' % \ 586 args[1]) 587 588 if args[0] == 'options': 589 has_path = None 590 for arg in args[1:]: 591 if arg in ['--auto', '--all']: 592 continue 593 elif arg.startswith('--'): 594 raise self.InvalidCmd('unknow command for \'save options\'') 595 else: 596 basename = os.path.dirname(arg) 597 if not os.path.exists(basename): 598 raise self.InvalidCmd('%s is not a valid path, please retry' % \ 599 arg) 600 elif has_path: 601 raise self.InvalidCmd('only one path is allowed') 602 else: 603 args.remove(arg) 604 args.insert(1, arg) 605 has_path = True 606 if not has_path: 607 if '--auto' in arg and self.options['mg5_path']: 608 args.insert(1, pjoin(self.options['mg5_path'],'input','mg5_configuration.txt')) 609 else: 610 args.insert(1, pjoin(self.me_dir,'Cards','me5_configuration.txt'))
611
612 - def check_set(self, args):
613 """ check the validity of the line""" 614 615 if len(args) < 2: 616 self.help_set() 617 raise self.InvalidCmd('set needs an option and an argument') 618 619 if args[0] not in self._set_options + self.options.keys(): 620 self.help_set() 621 raise self.InvalidCmd('Possible options for set are %s' % \ 622 self._set_options) 623 624 if args[0] in ['stdout_level']: 625 if args[1] not in ['DEBUG','INFO','WARNING','ERROR','CRITICAL'] \ 626 and not args[1].isdigit(): 627 raise self.InvalidCmd('output_level needs ' + \ 628 'a valid level') 629 630 if args[0] in ['timeout']: 631 if not args[1].isdigit(): 632 raise self.InvalidCmd('timeout values should be a integer')
633
634 - def check_open(self, args):
635 """ check the validity of the line """ 636 637 if len(args) != 1: 638 self.help_open() 639 raise self.InvalidCmd('OPEN command requires exactly one argument') 640 641 if args[0].startswith('./'): 642 if not os.path.isfile(args[0]): 643 raise self.InvalidCmd('%s: not such file' % args[0]) 644 return True 645 646 # if special : create the path. 647 if not self.me_dir: 648 if not os.path.isfile(args[0]): 649 self.help_open() 650 raise self.InvalidCmd('No MadEvent path defined. Unable to associate this name to a file') 651 else: 652 return True 653 654 path = self.me_dir 655 if os.path.isfile(os.path.join(path,args[0])): 656 args[0] = os.path.join(path,args[0]) 657 elif os.path.isfile(os.path.join(path,'Cards',args[0])): 658 args[0] = os.path.join(path,'Cards',args[0]) 659 elif os.path.isfile(os.path.join(path,'HTML',args[0])): 660 args[0] = os.path.join(path,'HTML',args[0]) 661 # special for card with _default define: copy the default and open it 662 elif '_card.dat' in args[0]: 663 name = args[0].replace('_card.dat','_card_default.dat') 664 if os.path.isfile(os.path.join(path,'Cards', name)): 665 files.cp(os.path.join(path,'Cards', name), os.path.join(path,'Cards', args[0])) 666 args[0] = os.path.join(path,'Cards', args[0]) 667 else: 668 raise self.InvalidCmd('No default path for this file') 669 elif not os.path.isfile(args[0]): 670 raise self.InvalidCmd('No default path for this file')
671
672 - def check_initMadLoop(self, args):
673 """ check initMadLoop command arguments are valid.""" 674 675 opt = {'refresh': False, 'nPS': None, 'force': False} 676 677 for arg in args: 678 if arg in ['-r','--refresh']: 679 opt['refresh'] = True 680 if arg in ['-f','--force']: 681 opt['force'] = True 682 elif arg.startswith('--nPS='): 683 n_attempts = arg.split('=')[1] 684 try: 685 opt['nPS'] = int(n_attempts) 686 except ValueError: 687 raise InvalidCmd("The number of attempts specified "+ 688 "'%s' is not a valid integer."%n_attempts) 689 690 return opt
691
692 - def check_treatcards(self, args):
693 """check that treatcards arguments are valid 694 [param|run|all] [--output_dir=] [--param_card=] [--run_card=] 695 """ 696 697 opt = {'output_dir':pjoin(self.me_dir,'Source'), 698 'param_card':pjoin(self.me_dir,'Cards','param_card.dat'), 699 'run_card':pjoin(self.me_dir,'Cards','run_card.dat'), 700 'forbid_MadLoopInit': False} 701 mode = 'all' 702 for arg in args: 703 if arg.startswith('--') and '=' in arg: 704 key,value =arg[2:].split('=',1) 705 if not key in opt: 706 self.help_treatcards() 707 raise self.InvalidCmd('Invalid option for treatcards command:%s ' \ 708 % key) 709 if key in ['param_card', 'run_card']: 710 if os.path.isfile(value): 711 card_name = self.detect_card_type(value) 712 if card_name != key: 713 raise self.InvalidCmd('Format for input file detected as %s while expecting %s' 714 % (card_name, key)) 715 opt[key] = value 716 elif os.path.isfile(pjoin(self.me_dir,value)): 717 card_name = self.detect_card_type(pjoin(self.me_dir,value)) 718 if card_name != key: 719 raise self.InvalidCmd('Format for input file detected as %s while expecting %s' 720 % (card_name, key)) 721 opt[key] = value 722 else: 723 raise self.InvalidCmd('No such file: %s ' % value) 724 elif key in ['output_dir']: 725 if os.path.isdir(value): 726 opt[key] = value 727 elif os.path.isdir(pjoin(self.me_dir,value)): 728 opt[key] = pjoin(self.me_dir, value) 729 else: 730 raise self.InvalidCmd('No such directory: %s' % value) 731 elif arg in ['loop','param','run','all']: 732 mode = arg 733 elif arg == '--no_MadLoopInit': 734 opt['forbid_MadLoopInit'] = True 735 else: 736 self.help_treatcards() 737 raise self.InvalidCmd('Unvalid argument %s' % arg) 738 739 return mode, opt
740 741
742 - def check_survey(self, args, cmd='survey'):
743 """check that the argument for survey are valid""" 744 745 746 self.opts = dict([(key,value[1]) for (key,value) in \ 747 self._survey_options.items()]) 748 749 # Treat any arguments starting with '--' 750 while args and args[-1].startswith('--'): 751 arg = args.pop(-1) 752 try: 753 for opt,value in self._survey_options.items(): 754 if arg.startswith('--%s=' % opt): 755 exec('self.opts[\'%s\'] = %s(arg.split(\'=\')[-1])' % \ 756 (opt, value[0])) 757 arg = "" 758 if arg != "": raise Exception 759 except Exception: 760 self.help_survey() 761 raise self.InvalidCmd('invalid %s argument'% arg) 762 763 if len(args) > 1: 764 self.help_survey() 765 raise self.InvalidCmd('Too many argument for %s command' % cmd) 766 elif not args: 767 # No run name assigned -> assigned one automaticaly 768 self.set_run_name(self.find_available_run_name(self.me_dir)) 769 else: 770 self.set_run_name(args[0], None,'parton', True) 771 args.pop(0) 772 773 return True
774
775 - def check_generate_events(self, args):
776 """check that the argument for generate_events are valid""" 777 778 run = None 779 if args and args[-1].startswith('--laststep='): 780 run = args[-1].split('=')[-1] 781 if run not in ['auto','parton', 'pythia', 'pgs', 'delphes']: 782 self.help_generate_events() 783 raise self.InvalidCmd('invalid %s argument'% args[-1]) 784 if run != 'parton' and not self.options['pythia-pgs_path']: 785 raise self.InvalidCmd('''pythia-pgs not install. Please install this package first. 786 To do so type: \'install pythia-pgs\' in the mg5 interface''') 787 if run == 'delphes' and not self.options['delphes_path']: 788 raise self.InvalidCmd('''delphes not install. Please install this package first. 789 To do so type: \'install Delphes\' in the mg5 interface''') 790 del args[-1] 791 792 793 #if len(args) > 1: 794 # self.help_generate_events() 795 # raise self.InvalidCmd('Too many argument for generate_events command: %s' % cmd) 796 797 return run
798
799 - def check_add_time_of_flight(self, args):
800 """check that the argument are correct""" 801 802 803 if len(args) >2: 804 self.help_time_of_flight() 805 raise self.InvalidCmd('Too many arguments') 806 807 # check if the threshold is define. and keep it's value 808 if args and args[-1].startswith('--threshold='): 809 try: 810 threshold = float(args[-1].split('=')[1]) 811 except ValueError: 812 raise self.InvalidCmd('threshold options require a number.') 813 args.remove(args[-1]) 814 else: 815 threshold = 1e-12 816 817 if len(args) == 1 and os.path.exists(args[0]): 818 event_path = args[0] 819 else: 820 if len(args) and self.run_name != args[0]: 821 self.set_run_name(args.pop(0)) 822 elif not self.run_name: 823 self.help_add_time_of_flight() 824 raise self.InvalidCmd('Need a run_name to process') 825 event_path = pjoin(self.me_dir, 'Events', self.run_name, 'unweighted_events.lhe.gz') 826 if not os.path.exists(event_path): 827 event_path = event_path[:-3] 828 if not os.path.exists(event_path): 829 raise self.InvalidCmd('No unweighted events associate to this run.') 830 831 832 833 #reformat the data 834 args[:] = [event_path, threshold]
835
836 - def check_calculate_decay_widths(self, args):
837 """check that the argument for calculate_decay_widths are valid""" 838 839 if self.ninitial != 1: 840 raise self.InvalidCmd('Can only calculate decay widths for decay processes A > B C ...') 841 842 accuracy = 0.01 843 run = None 844 if args and args[-1].startswith('--accuracy='): 845 try: 846 accuracy = float(args[-1].split('=')[-1]) 847 except Exception: 848 raise self.InvalidCmd('Argument error in calculate_decay_widths command') 849 del args[-1] 850 if len(args) > 1: 851 self.help_calculate_decay_widths() 852 raise self.InvalidCmd('Too many argument for calculate_decay_widths command: %s' % cmd) 853 854 return accuracy
855 856 857
858 - def check_multi_run(self, args):
859 """check that the argument for survey are valid""" 860 861 run = None 862 863 if not len(args): 864 self.help_multi_run() 865 raise self.InvalidCmd("""multi_run command requires at least one argument for 866 the number of times that it call generate_events command""") 867 868 if args[-1].startswith('--laststep='): 869 run = args[-1].split('=')[-1] 870 if run not in ['parton', 'pythia', 'pgs', 'delphes']: 871 self.help_multi_run() 872 raise self.InvalidCmd('invalid %s argument'% args[-1]) 873 if run != 'parton' and not self.options['pythia-pgs_path']: 874 raise self.InvalidCmd('''pythia-pgs not install. Please install this package first. 875 To do so type: \'install pythia-pgs\' in the mg5 interface''') 876 if run == 'delphes' and not self.options['delphes_path']: 877 raise self.InvalidCmd('''delphes not install. Please install this package first. 878 To do so type: \'install Delphes\' in the mg5 interface''') 879 del args[-1] 880 881 882 elif not args[0].isdigit(): 883 self.help_multi_run() 884 raise self.InvalidCmd("The first argument of multi_run should be a integer.") 885 #pass nb run to an integer 886 nb_run = args.pop(0) 887 args.insert(0, int(nb_run)) 888 889 890 return run
891
892 - def check_refine(self, args):
893 """check that the argument for survey are valid""" 894 895 # if last argument is not a number -> it's the run_name (Not allow anymore) 896 try: 897 float(args[-1]) 898 except ValueError: 899 self.help_refine() 900 raise self.InvalidCmd('Not valid arguments') 901 except IndexError: 902 self.help_refine() 903 raise self.InvalidCmd('require_precision argument is require for refine cmd') 904 905 906 if not self.run_name: 907 if self.results.lastrun: 908 self.set_run_name(self.results.lastrun) 909 else: 910 raise self.InvalidCmd('No run_name currently define. Unable to run refine') 911 912 if len(args) > 2: 913 self.help_refine() 914 raise self.InvalidCmd('Too many argument for refine command') 915 else: 916 try: 917 [float(arg) for arg in args] 918 except ValueError: 919 self.help_refine() 920 raise self.InvalidCmd('refine arguments are suppose to be number') 921 922 return True
923
924 - def check_combine_events(self, arg):
925 """ Check the argument for the combine events command """ 926 927 tag = [a for a in arg if a.startswith('--tag=')] 928 if tag: 929 arg.remove(tag[0]) 930 tag = tag[0][6:] 931 elif not self.run_tag: 932 tag = 'tag_1' 933 else: 934 tag = self.run_tag 935 self.run_tag = tag 936 937 if len(arg) > 1: 938 self.help_combine_events() 939 raise self.InvalidCmd('Too many argument for combine_events command') 940 941 if len(arg) == 1: 942 self.set_run_name(arg[0], self.run_tag, 'parton', True) 943 944 if not self.run_name: 945 if not self.results.lastrun: 946 raise self.InvalidCmd('No run_name currently define. Unable to run combine') 947 else: 948 self.set_run_name(self.results.lastrun) 949 950 return True
951
952 - def check_pythia(self, args):
953 """Check the argument for pythia command 954 syntax: pythia [NAME] 955 Note that other option are already removed at this point 956 """ 957 958 mode = None 959 laststep = [arg for arg in args if arg.startswith('--laststep=')] 960 if laststep and len(laststep)==1: 961 mode = laststep[0].split('=')[-1] 962 if mode not in ['auto', 'pythia', 'pgs', 'delphes']: 963 self.help_pythia() 964 raise self.InvalidCmd('invalid %s argument'% args[-1]) 965 elif laststep: 966 raise self.InvalidCmd('only one laststep argument is allowed') 967 968 if not self.options['pythia-pgs_path']: 969 logger.info('Retry to read configuration file to find pythia-pgs path') 970 self.set_configuration() 971 972 if not self.options['pythia-pgs_path'] or not \ 973 os.path.exists(pjoin(self.options['pythia-pgs_path'],'src')): 974 error_msg = 'No valid pythia-pgs path set.\n' 975 error_msg += 'Please use the set command to define the path and retry.\n' 976 error_msg += 'You can also define it in the configuration file.\n' 977 raise self.InvalidCmd(error_msg) 978 979 980 981 tag = [a for a in args if a.startswith('--tag=')] 982 if tag: 983 args.remove(tag[0]) 984 tag = tag[0][6:] 985 986 if len(args) == 0 and not self.run_name: 987 if self.results.lastrun: 988 args.insert(0, self.results.lastrun) 989 else: 990 raise self.InvalidCmd('No run name currently define. Please add this information.') 991 992 if len(args) >= 1: 993 if args[0] != self.run_name and\ 994 not os.path.exists(pjoin(self.me_dir,'Events',args[0], 'unweighted_events.lhe.gz')): 995 raise self.InvalidCmd('No events file corresponding to %s run. '% args[0]) 996 self.set_run_name(args[0], tag, 'pythia') 997 else: 998 if tag: 999 self.run_card['run_tag'] = tag 1000 self.set_run_name(self.run_name, tag, 'pythia') 1001 1002 input_file = pjoin(self.me_dir,'Events',self.run_name, 'unweighted_events.lhe') 1003 output_file = pjoin(self.me_dir, 'Events', 'unweighted_events.lhe') 1004 if not os.path.exists('%s.gz' % input_file): 1005 if not os.path.exists(input_file): 1006 raise self.InvalidCmd('No events file corresponding to %s run. '% self.run_name) 1007 files.ln(input_file, os.path.dirname(output_file)) 1008 else: 1009 misc.gunzip(input_file, keep=True, stdout=output_file) 1010 1011 args.append(mode)
1012
1013 - def check_pythia8(self, args):
1014 """Check the argument for pythia command 1015 syntax: pythia8 [NAME] 1016 Note that other option are already removed at this point 1017 """ 1018 mode = None 1019 laststep = [arg for arg in args if arg.startswith('--laststep=')] 1020 if laststep and len(laststep)==1: 1021 mode = laststep[0].split('=')[-1] 1022 if mode not in ['auto', 'pythia','pythia8','delphes']: 1023 self.help_pythia8() 1024 raise self.InvalidCmd('invalid %s argument'% args[-1]) 1025 elif laststep: 1026 raise self.InvalidCmd('only one laststep argument is allowed') 1027 1028 # If not pythia-pgs path 1029 if not self.options['pythia8_path']: 1030 logger.info('Retry reading configuration file to find pythia8 path') 1031 self.set_configuration() 1032 1033 if not self.options['pythia8_path'] or not \ 1034 os.path.exists(pjoin(self.options['pythia8_path'],'bin','pythia8-config')): 1035 error_msg = 'No valid pythia8 path set.\n' 1036 error_msg += 'Please use the set command to define the path and retry.\n' 1037 error_msg += 'You can also define it in the configuration file.\n' 1038 error_msg += 'Finally, it can be installed automatically using the' 1039 error_msg += ' install command.\n' 1040 raise self.InvalidCmd(error_msg) 1041 1042 tag = [a for a in args if a.startswith('--tag=')] 1043 if tag: 1044 args.remove(tag[0]) 1045 tag = tag[0][6:] 1046 1047 if len(args) == 0 and not self.run_name: 1048 if self.results.lastrun: 1049 args.insert(0, self.results.lastrun) 1050 else: 1051 raise self.InvalidCmd('No run name currently define. '+ 1052 'Please add this information.') 1053 1054 if len(args) >= 1: 1055 if args[0] != self.run_name and\ 1056 not os.path.exists(pjoin(self.me_dir,'Events',args[0], 1057 'unweighted_events.lhe.gz')): 1058 raise self.InvalidCmd('No events file corresponding to %s run. ' 1059 % args[0]) 1060 self.set_run_name(args[0], tag, 'pythia8') 1061 else: 1062 if tag: 1063 self.run_card['run_tag'] = tag 1064 self.set_run_name(self.run_name, tag, 'pythia8') 1065 1066 input_file = pjoin(self.me_dir,'Events',self.run_name, 'unweighted_events.lhe') 1067 if not os.path.exists('%s.gz'%input_file): 1068 if os.path.exists(input_file): 1069 misc.gzip(input_file, stdout='%s.gz'%input_file) 1070 else: 1071 raise self.InvalidCmd('No event file corresponding to %s run. ' 1072 % self.run_name) 1073 1074 args.append(mode)
1075
1076 - def check_remove(self, args):
1077 """Check that the remove command is valid""" 1078 1079 tmp_args = args[:] 1080 1081 tag = [a[6:] for a in tmp_args if a.startswith('--tag=')] 1082 if tag: 1083 tag = tag[0] 1084 tmp_args.remove('--tag=%s' % tag) 1085 1086 1087 if len(tmp_args) == 0: 1088 self.help_remove() 1089 raise self.InvalidCmd('clean command require the name of the run to clean') 1090 elif len(tmp_args) == 1: 1091 return tmp_args[0], tag, ['all'] 1092 else: 1093 for arg in tmp_args[1:]: 1094 if arg not in self._clean_mode: 1095 self.help_remove() 1096 raise self.InvalidCmd('%s is not a valid options for clean command'\ 1097 % arg) 1098 return tmp_args[0], tag, tmp_args[1:]
1099
1100 - def check_plot(self, args):
1101 """Check the argument for the plot command 1102 plot run_name modes""" 1103 1104 madir = self.options['madanalysis_path'] 1105 td = self.options['td_path'] 1106 1107 if not madir or not td: 1108 logger.info('Retry to read configuration file to find madanalysis/td') 1109 self.set_configuration() 1110 1111 madir = self.options['madanalysis_path'] 1112 td = self.options['td_path'] 1113 1114 if not madir: 1115 error_msg = 'No valid MadAnalysis path set.\n' 1116 error_msg += 'Please use the set command to define the path and retry.\n' 1117 error_msg += 'You can also define it in the configuration file.\n' 1118 raise self.InvalidCmd(error_msg) 1119 if not td: 1120 error_msg = 'No valid td path set.\n' 1121 error_msg += 'Please use the set command to define the path and retry.\n' 1122 error_msg += 'You can also define it in the configuration file.\n' 1123 raise self.InvalidCmd(error_msg) 1124 1125 if len(args) == 0: 1126 if not hasattr(self, 'run_name') or not self.run_name: 1127 self.help_plot() 1128 raise self.InvalidCmd('No run name currently define. Please add this information.') 1129 args.append('all') 1130 return 1131 1132 1133 if args[0] not in self._plot_mode: 1134 self.set_run_name(args[0], level='plot') 1135 del args[0] 1136 if len(args) == 0: 1137 args.append('all') 1138 elif not self.run_name: 1139 self.help_plot() 1140 raise self.InvalidCmd('No run name currently define. Please add this information.') 1141 1142 for arg in args: 1143 if arg not in self._plot_mode and arg != self.run_name: 1144 self.help_plot() 1145 raise self.InvalidCmd('unknown options %s' % arg)
1146
1147 - def check_syscalc(self, args):
1148 """Check the argument for the syscalc command 1149 syscalc run_name modes""" 1150 1151 scdir = self.options['syscalc_path'] 1152 1153 if not scdir: 1154 logger.info('Retry to read configuration file to find SysCalc') 1155 self.set_configuration() 1156 1157 scdir = self.options['syscalc_path'] 1158 1159 if not scdir: 1160 error_msg = 'No valid SysCalc path set.\n' 1161 error_msg += 'Please use the set command to define the path and retry.\n' 1162 error_msg += 'You can also define it in the configuration file.\n' 1163 error_msg += 'Please note that you need to compile SysCalc first.' 1164 raise self.InvalidCmd(error_msg) 1165 1166 if len(args) == 0: 1167 if not hasattr(self, 'run_name') or not self.run_name: 1168 self.help_syscalc() 1169 raise self.InvalidCmd('No run name currently defined. Please add this information.') 1170 args.append('all') 1171 return 1172 1173 #deal options 1174 tag = [a for a in args if a.startswith('--tag=')] 1175 if tag: 1176 args.remove(tag[0]) 1177 tag = tag[0][6:] 1178 1179 if args[0] not in self._syscalc_mode: 1180 self.set_run_name(args[0], tag=tag, level='syscalc') 1181 del args[0] 1182 if len(args) == 0: 1183 args.append('all') 1184 elif not self.run_name: 1185 self.help_syscalc() 1186 raise self.InvalidCmd('No run name currently defined. Please add this information.') 1187 elif tag and tag != self.run_tag: 1188 self.set_run_name(self.run_name, tag=tag, level='syscalc') 1189 1190 for arg in args: 1191 if arg not in self._syscalc_mode and arg != self.run_name: 1192 self.help_syscalc() 1193 raise self.InvalidCmd('unknown options %s' % arg) 1194 1195 if self.run_card['use_syst'] not in self.true: 1196 raise self.InvalidCmd('Run %s does not include ' % self.run_name + \ 1197 'systematics information needed for syscalc.')
1198 1199
1200 - def check_pgs(self, arg, no_default=False):
1201 """Check the argument for pythia command 1202 syntax is "pgs [NAME]" 1203 Note that other option are already remove at this point 1204 """ 1205 1206 # If not pythia-pgs path 1207 if not self.options['pythia-pgs_path']: 1208 logger.info('Retry to read configuration file to find pythia-pgs path') 1209 self.set_configuration() 1210 1211 if not self.options['pythia-pgs_path'] or not \ 1212 os.path.exists(pjoin(self.options['pythia-pgs_path'],'src')): 1213 error_msg = 'No valid pythia-pgs path set.\n' 1214 error_msg += 'Please use the set command to define the path and retry.\n' 1215 error_msg += 'You can also define it in the configuration file.\n' 1216 raise self.InvalidCmd(error_msg) 1217 1218 tag = [a for a in arg if a.startswith('--tag=')] 1219 if tag: 1220 arg.remove(tag[0]) 1221 tag = tag[0][6:] 1222 1223 1224 if len(arg) == 0 and not self.run_name: 1225 if self.results.lastrun: 1226 arg.insert(0, self.results.lastrun) 1227 else: 1228 raise self.InvalidCmd('No run name currently define. Please add this information.') 1229 1230 if len(arg) == 1 and self.run_name == arg[0]: 1231 arg.pop(0) 1232 1233 if not len(arg) and \ 1234 not os.path.exists(pjoin(self.me_dir,'Events','pythia_events.hep')): 1235 if not no_default: 1236 self.help_pgs() 1237 raise self.InvalidCmd('''No file file pythia_events.hep currently available 1238 Please specify a valid run_name''') 1239 1240 lock = None 1241 if len(arg) == 1: 1242 prev_tag = self.set_run_name(arg[0], tag, 'pgs') 1243 if not os.path.exists(pjoin(self.me_dir,'Events',self.run_name,'%s_pythia_events.hep.gz' % prev_tag)): 1244 raise self.InvalidCmd('No events file corresponding to %s run with tag %s. '% (self.run_name, prev_tag)) 1245 else: 1246 input_file = pjoin(self.me_dir,'Events', self.run_name, '%s_pythia_events.hep.gz' % prev_tag) 1247 output_file = pjoin(self.me_dir, 'Events', 'pythia_events.hep') 1248 lock = cluster.asyncrone_launch('gunzip',stdout=open(output_file,'w'), 1249 argument=['-c', input_file]) 1250 1251 else: 1252 if tag: 1253 self.run_card['run_tag'] = tag 1254 self.set_run_name(self.run_name, tag, 'pgs') 1255 1256 return lock
1257
1258 - def check_display(self, args):
1259 """check the validity of line 1260 syntax is "display XXXXX" 1261 """ 1262 1263 if len(args) < 1 or args[0] not in self._display_opts: 1264 self.help_display() 1265 raise self.InvalidCmd 1266 1267 if args[0] == 'variable' and len(args) !=2: 1268 raise self.InvalidCmd('variable need a variable name')
1269 1270 1271 1272 1273
1274 - def check_import(self, args):
1275 """check the validity of line""" 1276 1277 if not args: 1278 self.help_import() 1279 raise self.InvalidCmd('wrong \"import\" format') 1280 1281 if args[0] != 'command': 1282 args.insert(0,'command') 1283 1284 1285 if not len(args) == 2 or not os.path.exists(args[1]): 1286 raise self.InvalidCmd('PATH is mandatory for import command\n')
1287
1288 1289 #=============================================================================== 1290 # CompleteForCmd 1291 #=============================================================================== 1292 -class CompleteForCmd(CheckValidForCmd):
1293 """ The Series of help routine for the MadGraphCmd""" 1294 1295
1296 - def complete_add_time_of_flight(self, text, line, begidx, endidx):
1297 "Complete command" 1298 1299 args = self.split_arg(line[0:begidx], error=False) 1300 1301 if len(args) == 1: 1302 #return valid run_name 1303 data = misc.glob(pjoin('*','unweighted_events.lhe.gz'), pjoin(self.me_dir, 'Events')) 1304 data = [n.rsplit('/',2)[1] for n in data] 1305 return self.list_completion(text, data + ['--threshold='], line) 1306 elif args[-1].endswith(os.path.sep): 1307 return self.path_completion(text, 1308 os.path.join('.',*[a for a in args \ 1309 if a.endswith(os.path.sep)])) 1310 else: 1311 return self.list_completion(text, ['--threshold='], line)
1312
1313 - def complete_banner_run(self, text, line, begidx, endidx, formatting=True):
1314 "Complete the banner run command" 1315 try: 1316 1317 1318 args = self.split_arg(line[0:begidx], error=False) 1319 1320 if args[-1].endswith(os.path.sep): 1321 return self.path_completion(text, 1322 os.path.join('.',*[a for a in args \ 1323 if a.endswith(os.path.sep)])) 1324 1325 1326 if len(args) > 1: 1327 # only options are possible 1328 tags = misc.glob('%s_*_banner.txt' % args[1], pjoin(self.me_dir, 'Events' , args[1])) 1329 tags = ['%s' % os.path.basename(t)[len(args[1])+1:-11] for t in tags] 1330 1331 if args[-1] != '--tag=': 1332 tags = ['--tag=%s' % t for t in tags] 1333 else: 1334 return self.list_completion(text, tags) 1335 return self.list_completion(text, tags +['--name=','-f'], line) 1336 1337 # First argument 1338 possibilites = {} 1339 1340 comp = self.path_completion(text, os.path.join('.',*[a for a in args \ 1341 if a.endswith(os.path.sep)])) 1342 if os.path.sep in line: 1343 return comp 1344 else: 1345 possibilites['Path from ./'] = comp 1346 1347 run_list = misc.glob(pjoin('*','*_banner.txt'), pjoin(self.me_dir, 'Events')) 1348 run_list = [n.rsplit('/',2)[1] for n in run_list] 1349 possibilites['RUN Name'] = self.list_completion(text, run_list) 1350 1351 return self.deal_multiple_categories(possibilites, formatting) 1352 1353 1354 except Exception, error: 1355 print error
1356 1357
1358 - def complete_history(self, text, line, begidx, endidx):
1359 "Complete the history command" 1360 1361 args = self.split_arg(line[0:begidx], error=False) 1362 1363 # Directory continuation 1364 if args[-1].endswith(os.path.sep): 1365 return self.path_completion(text, 1366 os.path.join('.',*[a for a in args \ 1367 if a.endswith(os.path.sep)])) 1368 1369 if len(args) == 1: 1370 return self.path_completion(text)
1371
1372 - def complete_open(self, text, line, begidx, endidx):
1373 """ complete the open command """ 1374 1375 args = self.split_arg(line[0:begidx]) 1376 1377 # Directory continuation 1378 if os.path.sep in args[-1] + text: 1379 return self.path_completion(text, 1380 os.path.join('.',*[a for a in args if \ 1381 a.endswith(os.path.sep)])) 1382 1383 possibility = [] 1384 if self.me_dir: 1385 path = self.me_dir 1386 possibility = ['index.html'] 1387 if os.path.isfile(os.path.join(path,'README')): 1388 possibility.append('README') 1389 if os.path.isdir(os.path.join(path,'Cards')): 1390 possibility += [f for f in os.listdir(os.path.join(path,'Cards')) 1391 if f.endswith('.dat')] 1392 if os.path.isdir(os.path.join(path,'HTML')): 1393 possibility += [f for f in os.listdir(os.path.join(path,'HTML')) 1394 if f.endswith('.html') and 'default' not in f] 1395 else: 1396 possibility.extend(['./','../']) 1397 if os.path.exists('ME5_debug'): 1398 possibility.append('ME5_debug') 1399 if os.path.exists('MG5_debug'): 1400 possibility.append('MG5_debug') 1401 return self.list_completion(text, possibility)
1402
1403 - def complete_set(self, text, line, begidx, endidx):
1404 "Complete the set command" 1405 1406 args = self.split_arg(line[0:begidx]) 1407 1408 # Format 1409 if len(args) == 1: 1410 return self.list_completion(text, self._set_options + self.options.keys() ) 1411 1412 if len(args) == 2: 1413 if args[1] == 'stdout_level': 1414 return self.list_completion(text, ['DEBUG','INFO','WARNING','ERROR','CRITICAL']) 1415 else: 1416 first_set = ['None','True','False'] 1417 # directory names 1418 second_set = [name for name in self.path_completion(text, '.', only_dirs = True)] 1419 return self.list_completion(text, first_set + second_set) 1420 elif len(args) >2 and args[-1].endswith(os.path.sep): 1421 return self.path_completion(text, 1422 os.path.join('.',*[a for a in args if a.endswith(os.path.sep)]), 1423 only_dirs = True)
1424
1425 - def complete_survey(self, text, line, begidx, endidx):
1426 """ Complete the survey command """ 1427 1428 if line.endswith('nb_core=') and not text: 1429 import multiprocessing 1430 max = multiprocessing.cpu_count() 1431 return [str(i) for i in range(2,max+1)] 1432 1433 return self.list_completion(text, self._run_options, line)
1434 1435 complete_refine = complete_survey 1436 complete_combine_events = complete_survey 1437 complite_store = complete_survey 1438 complete_generate_events = complete_survey 1439 complete_create_gridpack = complete_survey 1440
1441 - def complete_generate_events(self, text, line, begidx, endidx):
1442 """ Complete the generate events""" 1443 1444 if line.endswith('nb_core=') and not text: 1445 import multiprocessing 1446 max = multiprocessing.cpu_count() 1447 return [str(i) for i in range(2,max+1)] 1448 if line.endswith('laststep=') and not text: 1449 return ['parton','pythia','pgs','delphes'] 1450 elif '--laststep=' in line.split()[-1] and line and line[-1] != ' ': 1451 return self.list_completion(text,['parton','pythia','pgs','delphes'],line) 1452 1453 opts = self._run_options + self._generate_options 1454 return self.list_completion(text, opts, line)
1455 1456
1457 - def complete_initMadLoop(self, text, line, begidx, endidx):
1458 "Complete the initMadLoop command" 1459 1460 numbers = [str(i) for i in range(10)] 1461 opts = ['-f','-r','--nPS='] 1462 1463 args = self.split_arg(line[0:begidx], error=False) 1464 if len(line) >=6 and line[begidx-6:begidx]=='--nPS=': 1465 return self.list_completion(text, numbers, line) 1466 else: 1467 return self.list_completion(text, [opt for opt in opts if not opt in 1468 line], line)
1469
1470 - def complete_launch(self, *args, **opts):
1471 1472 if self.ninitial == 1: 1473 return self.complete_calculate_decay_widths(*args, **opts) 1474 else: 1475 return self.complete_generate_events(*args, **opts)
1476
1477 - def complete_calculate_decay_widths(self, text, line, begidx, endidx):
1478 """ Complete the calculate_decay_widths command""" 1479 1480 if line.endswith('nb_core=') and not text: 1481 import multiprocessing 1482 max = multiprocessing.cpu_count() 1483 return [str(i) for i in range(2,max+1)] 1484 1485 opts = self._run_options + self._calculate_decay_options 1486 return self.list_completion(text, opts, line)
1487
1488 - def complete_display(self, text, line, begidx, endidx):
1489 """ Complete the display command""" 1490 1491 args = self.split_arg(line[0:begidx], error=False) 1492 if len(args) >= 2 and args[1] =='results': 1493 start = line.find('results') 1494 return self.complete_print_results(text, 'print_results '+line[start+7:], begidx+2+start, endidx+2+start) 1495 return super(CompleteForCmd, self).complete_display(text, line, begidx, endidx)
1496
1497 - def complete_multi_run(self, text, line, begidx, endidx):
1498 """complete multi run command""" 1499 1500 args = self.split_arg(line[0:begidx], error=False) 1501 if len(args) == 1: 1502 data = [str(i) for i in range(0,20)] 1503 return self.list_completion(text, data, line) 1504 1505 if line.endswith('run=') and not text: 1506 return ['parton','pythia','pgs','delphes'] 1507 elif '--laststep=' in line.split()[-1] and line and line[-1] != ' ': 1508 return self.list_completion(text,['parton','pythia','pgs','delphes'],line) 1509 1510 opts = self._run_options + self._generate_options 1511 return self.list_completion(text, opts, line) 1512 1513 1514 1515 if line.endswith('nb_core=') and not text: 1516 import multiprocessing 1517 max = multiprocessing.cpu_count() 1518 return [str(i) for i in range(2,max+1)] 1519 opts = self._run_options + self._generate_options 1520 return self.list_completion(text, opts, line)
1521
1522 - def complete_plot(self, text, line, begidx, endidx):
1523 """ Complete the plot command """ 1524 1525 args = self.split_arg(line[0:begidx], error=False) 1526 if len(args) > 1: 1527 return self.list_completion(text, self._plot_mode) 1528 else: 1529 return self.list_completion(text, self._plot_mode + self.results.keys())
1530
1531 - def complete_syscalc(self, text, line, begidx, endidx, formatting=True):
1532 """ Complete the syscalc command """ 1533 1534 output = {} 1535 args = self.split_arg(line[0:begidx], error=False) 1536 1537 if len(args) <=1: 1538 output['RUN_NAME'] = self.list_completion(self.results.keys()) 1539 output['MODE'] = self.list_completion(text, self._syscalc_mode) 1540 output['options'] = ['-f'] 1541 if len(args) > 1 and (text.startswith('--t')): 1542 run = args[1] 1543 if run in self.results: 1544 tags = ['--tag=%s' % tag['tag'] for tag in self.results[run]] 1545 output['options'] += tags 1546 1547 return self.deal_multiple_categories(output, formatting)
1548
1549 - def complete_remove(self, text, line, begidx, endidx):
1550 """Complete the remove command """ 1551 1552 args = self.split_arg(line[0:begidx], error=False) 1553 if len(args) > 1 and (text.startswith('--t')): 1554 run = args[1] 1555 tags = ['--tag=%s' % tag['tag'] for tag in self.results[run]] 1556 return self.list_completion(text, tags) 1557 elif len(args) > 1 and '--' == args[-1]: 1558 run = args[1] 1559 tags = ['tag=%s' % tag['tag'] for tag in self.results[run]] 1560 return self.list_completion(text, tags) 1561 elif len(args) > 1 and '--tag=' == args[-1]: 1562 run = args[1] 1563 tags = [tag['tag'] for tag in self.results[run]] 1564 return self.list_completion(text, tags) 1565 elif len(args) > 1: 1566 return self.list_completion(text, self._clean_mode + ['-f','--tag=']) 1567 else: 1568 data = misc.glob(pjoin('*','*_banner.txt'), pjoin(self.me_dir, 'Events')) 1569 data = [n.rsplit('/',2)[1] for n in data] 1570 return self.list_completion(text, ['all'] + data)
1571 1572
1573 - def complete_shower(self,text, line, begidx, endidx):
1574 "Complete the shower command" 1575 args = self.split_arg(line[0:begidx], error=False) 1576 if len(args) == 1: 1577 return self.list_completion(text, self._interfaced_showers) 1578 elif len(args)>1 and args[1] in self._interfaced_showers: 1579 return getattr(self, 'complete_%s' % text)\ 1580 (text, args[1],line.replace(args[0]+' ',''), 1581 begidx-len(args[0])-1, endidx-len(args[0])-1)
1582
1583 - def complete_pythia8(self,text, line, begidx, endidx):
1584 "Complete the pythia8 command" 1585 args = self.split_arg(line[0:begidx], error=False) 1586 if len(args) == 1: 1587 #return valid run_name 1588 data = misc.glob(pjoin('*','unweighted_events.lhe.gz'),pjoin(self.me_dir, 'Events')) 1589 data = [n.rsplit('/',2)[1] for n in data] 1590 tmp1 = self.list_completion(text, data) 1591 if not self.run_name: 1592 return tmp1 1593 else: 1594 tmp2 = self.list_completion(text, self._run_options + ['-f', 1595 '--no_default', '--tag='], line) 1596 return tmp1 + tmp2 1597 elif line[-1] != '=': 1598 return self.list_completion(text, self._run_options + ['-f', 1599 '--no_default','--tag='], line)
1600
1601 - def complete_madanalysis5_parton(self,text, line, begidx, endidx):
1602 "Complete the madanalysis5 command" 1603 args = self.split_arg(line[0:begidx], error=False) 1604 if len(args) == 1: 1605 #return valid run_name 1606 data = [] 1607 for name in ['unweighted_events.lhe']: 1608 data += misc.glob(pjoin('*','%s'%name), pjoin(self.me_dir, 'Events')) 1609 data += misc.glob(pjoin('*','%s.gz'%name), pjoin(self.me_dir, 'Events')) 1610 data = [n.rsplit('/',2)[1] for n in data] 1611 tmp1 = self.list_completion(text, data) 1612 if not self.run_name: 1613 return tmp1 1614 else: 1615 tmp2 = self.list_completion(text, ['-f', 1616 '--MA5_stdout_lvl=','--no_default','--tag='], line) 1617 return tmp1 + tmp2 1618 elif '--MA5_stdout_lvl=' in line and not any(arg.startswith( 1619 '--MA5_stdout_lvl=') for arg in args): 1620 return self.list_completion(text, 1621 ['--MA5_stdout_lvl=%s'%opt for opt in 1622 ['logging.INFO','logging.DEBUG','logging.WARNING', 1623 'logging.CRITICAL','90']], line) 1624 else: 1625 return self.list_completion(text, ['-f', 1626 '--MA5_stdout_lvl=','--no_default','--tag='], line)
1627
1628 - def complete_pythia(self,text, line, begidx, endidx):
1629 "Complete the pythia command" 1630 args = self.split_arg(line[0:begidx], error=False) 1631 1632 if len(args) == 1: 1633 #return valid run_name 1634 data = misc.glob(pjoin('*','unweighted_events.lhe.gz'), pjoin(self.me_dir, 'Events')) 1635 data = [n.rsplit('/',2)[1] for n in data] 1636 tmp1 = self.list_completion(text, data) 1637 if not self.run_name: 1638 return tmp1 1639 else: 1640 tmp2 = self.list_completion(text, self._run_options + ['-f', 1641 '--no_default', '--tag='], line) 1642 return tmp1 + tmp2 1643 elif line[-1] != '=': 1644 return self.list_completion(text, self._run_options + ['-f', 1645 '--no_default','--tag='], line)
1646
1647 - def complete_pgs(self,text, line, begidx, endidx):
1648 "Complete the pythia command" 1649 args = self.split_arg(line[0:begidx], error=False) 1650 if len(args) == 1: 1651 #return valid run_name 1652 data = misc.glob(pjoin('*', '*_pythia_events.hep.gz'), pjoin(self.me_dir, 'Events')) 1653 data = [n.rsplit('/',2)[1] for n in data] 1654 tmp1 = self.list_completion(text, data) 1655 if not self.run_name: 1656 return tmp1 1657 else: 1658 tmp2 = self.list_completion(text, self._run_options + ['-f', 1659 '--tag=' ,'--no_default'], line) 1660 return tmp1 + tmp2 1661 else: 1662 return self.list_completion(text, self._run_options + ['-f', 1663 '--tag=','--no_default'], line)
1664 1665 complete_delphes = complete_pgs 1666
1667 1668 1669 1670 1671 #=============================================================================== 1672 # MadEventCmd 1673 #=============================================================================== 1674 -class MadEventCmd(CompleteForCmd, CmdExtended, HelpToCmd, common_run.CommonRunCmd):
1675 1676 """The command line processor of Mad Graph""" 1677 1678 # Truth values 1679 true = ['T','.true.',True,'true'] 1680 # Options and formats available 1681 _run_options = ['--cluster','--multicore','--nb_core=','--nb_core=2', '-c', '-m'] 1682 _generate_options = ['-f', '--laststep=parton', '--laststep=pythia', '--laststep=pgs', '--laststep=delphes'] 1683 _calculate_decay_options = ['-f', '--accuracy=0.'] 1684 _interfaced_showers = ['pythia','pythia8'] 1685 _set_options = ['stdout_level','fortran_compiler','timeout'] 1686 _plot_mode = ['all', 'parton','pythia','pgs','delphes','channel', 'banner'] 1687 _syscalc_mode = ['all', 'parton','pythia'] 1688 _clean_mode = _plot_mode 1689 _display_opts = ['run_name', 'options', 'variable', 'results'] 1690 _save_opts = ['options'] 1691 _initMadLoop_opts = ['-f','-r','--nPS='] 1692 # survey options, dict from name to type, default value, and help text 1693 _survey_options = {'points':('int', 1000,'Number of points for first iteration'), 1694 'iterations':('int', 5, 'Number of iterations'), 1695 'accuracy':('float', 0.1, 'Required accuracy'), 1696 'gridpack':('str', '.false.', 'Gridpack generation')} 1697 # Variables to store object information 1698 true = ['T','.true.',True,'true', 1, '1'] 1699 web = False 1700 cluster_mode = 0 1701 queue = 'madgraph' 1702 nb_core = None 1703 1704 next_possibility = { 1705 'start': ['generate_events [OPTIONS]', 'multi_run [OPTIONS]', 1706 'calculate_decay_widths [OPTIONS]', 1707 'help generate_events'], 1708 'generate_events': ['generate_events [OPTIONS]', 'multi_run [OPTIONS]', 'pythia', 'pgs','delphes'], 1709 'calculate_decay_widths': ['calculate_decay_widths [OPTIONS]', 1710 'generate_events [OPTIONS]'], 1711 'multi_run': ['generate_events [OPTIONS]', 'multi_run [OPTIONS]'], 1712 'survey': ['refine'], 1713 'refine': ['combine_events'], 1714 'combine_events': ['store'], 1715 'store': ['pythia'], 1716 'pythia': ['pgs', 'delphes'], 1717 'pgs': ['generate_events [OPTIONS]', 'multi_run [OPTIONS]'], 1718 'delphes' : ['generate_events [OPTIONS]', 'multi_run [OPTIONS]'] 1719 } 1720 1721 ############################################################################
1722 - def __init__(self, me_dir = None, options={}, *completekey, **stdin):
1723 """ add information to the cmd """ 1724 1725 CmdExtended.__init__(self, me_dir, options, *completekey, **stdin) 1726 #common_run.CommonRunCmd.__init__(self, me_dir, options) 1727 1728 self.mode = 'madevent' 1729 self.nb_refine=0 1730 if self.web: 1731 os.system('touch %s' % pjoin(self.me_dir,'Online')) 1732 1733 self.load_results_db() 1734 self.results.def_web_mode(self.web) 1735 1736 self.prompt = "%s>"%os.path.basename(pjoin(self.me_dir)) 1737 self.configured = 0 # time for reading the card 1738 self._options = {} # for compatibility with extended_cmd
1739 1740
1741 - def pass_in_web_mode(self):
1742 """configure web data""" 1743 self.web = True 1744 self.results.def_web_mode(True) 1745 self.force = True 1746 if os.environ['MADGRAPH_BASE']: 1747 self.options['mg5_path'] = pjoin(os.environ['MADGRAPH_BASE'],'MG5')
1748 1749 ############################################################################
1750 - def check_output_type(self, path):
1751 """ Check that the output path is a valid madevent directory """ 1752 1753 bin_path = os.path.join(path,'bin') 1754 if os.path.isfile(os.path.join(bin_path,'generate_events')): 1755 return True 1756 else: 1757 return False
1758 1759 ############################################################################
1760 - def set_configuration(self, amcatnlo=False, final=True, **opt):
1761 """assign all configuration variable from file 1762 loop over the different config file if config_file not define """ 1763 1764 super(MadEventCmd,self).set_configuration(amcatnlo=amcatnlo, 1765 final=final, **opt) 1766 1767 if not final: 1768 return self.options # the return is usefull for unittest 1769 1770 1771 # Treat each expected input 1772 # delphes/pythia/... path 1773 # ONLY the ONE LINKED TO Madevent ONLY!!! 1774 for key in (k for k in self.options if k.endswith('path')): 1775 path = self.options[key] 1776 if path is None or key.startswith("cluster"): 1777 continue 1778 if not os.path.isdir(path): 1779 path = pjoin(self.me_dir, self.options[key]) 1780 if os.path.isdir(path): 1781 self.options[key] = None 1782 if key == "pythia-pgs_path": 1783 if not os.path.exists(pjoin(path, 'src','pythia')): 1784 logger.info("No valid pythia-pgs path found") 1785 continue 1786 elif key == "delphes_path": 1787 if not os.path.exists(pjoin(path, 'Delphes')) and not\ 1788 os.path.exists(pjoin(path, 'DelphesSTDHEP')): 1789 logger.info("No valid Delphes path found") 1790 continue 1791 elif key == "madanalysis_path": 1792 if not os.path.exists(pjoin(path, 'plot_events')): 1793 logger.info("No valid MadAnalysis path found") 1794 continue 1795 elif key == "td_path": 1796 if not os.path.exists(pjoin(path, 'td')): 1797 logger.info("No valid td path found") 1798 continue 1799 elif key == "syscalc_path": 1800 if not os.path.exists(pjoin(path, 'sys_calc')): 1801 logger.info("No valid SysCalc path found") 1802 continue 1803 # No else since the next line reinitialize the option to the 1804 #previous value anyway 1805 self.options[key] = os.path.realpath(path) 1806 continue 1807 else: 1808 self.options[key] = None 1809 1810 1811 return self.options
1812 1813 ############################################################################
1814 - def do_add_time_of_flight(self, line):
1815 1816 args = self.split_arg(line) 1817 #check the validity of the arguments and reformat args 1818 self.check_add_time_of_flight(args) 1819 1820 event_path, threshold = args 1821 #gunzip the file 1822 if event_path.endswith('.gz'): 1823 need_zip = True 1824 misc.gunzip(event_path) 1825 event_path = event_path[:-3] 1826 else: 1827 need_zip = False 1828 1829 import random 1830 try: 1831 import madgraph.various.lhe_parser as lhe_parser 1832 except: 1833 import internal.lhe_parser as lhe_parser 1834 1835 logger.info('Add time of flight information on file %s' % event_path) 1836 lhe = lhe_parser.EventFile(event_path) 1837 output = open('%s_2vertex.lhe' % event_path, 'w') 1838 #write the banner to the output file 1839 output.write(lhe.banner) 1840 1841 # get the associate param_card 1842 begin_param = lhe.banner.find('<slha>') 1843 end_param = lhe.banner.find('</slha>') 1844 param_card = lhe.banner[begin_param+6:end_param].split('\n') 1845 param_card = check_param_card.ParamCard(param_card) 1846 1847 cst = 6.58211915e-25 # hbar in GeV s 1848 c = 299792458000 # speed of light in mm/s 1849 # Loop over all events 1850 for event in lhe: 1851 for particle in event: 1852 id = particle.pid 1853 width = param_card['decay'].get((abs(id),)).value 1854 if width: 1855 vtim = c * random.expovariate(width/cst) 1856 if vtim > threshold: 1857 particle.vtim = vtim 1858 #write this modify event 1859 output.write(str(event)) 1860 output.write('</LesHouchesEvents>\n') 1861 output.close() 1862 1863 files.mv('%s_2vertex.lhe' % event_path, event_path) 1864 1865 if need_zip: 1866 misc.gzip(event_path)
1867 1868 ############################################################################
1869 - def do_banner_run(self, line):
1870 """Make a run from the banner file""" 1871 1872 args = self.split_arg(line) 1873 #check the validity of the arguments 1874 self.check_banner_run(args) 1875 1876 # Remove previous cards 1877 for name in ['delphes_trigger.dat', 'delphes_card.dat', 1878 'pgs_card.dat', 'pythia_card.dat', 'madspin_card.dat', 1879 'reweight_card.dat']: 1880 try: 1881 os.remove(pjoin(self.me_dir, 'Cards', name)) 1882 except Exception: 1883 pass 1884 1885 banner_mod.split_banner(args[0], self.me_dir, proc_card=False) 1886 1887 # Check if we want to modify the run 1888 if not self.force: 1889 ans = self.ask('Do you want to modify the Cards?', 'n', ['y','n']) 1890 if ans == 'n': 1891 self.force = True 1892 1893 # Call Generate events 1894 self.exec_cmd('generate_events %s %s' % (self.run_name, self.force and '-f' or ''))
1895 1896 1897 1898 ############################################################################
1899 - def do_display(self, line, output=sys.stdout):
1900 """Display current internal status""" 1901 1902 args = self.split_arg(line) 1903 #check the validity of the arguments 1904 self.check_display(args) 1905 1906 if args[0] == 'run_name': 1907 #return valid run_name 1908 data = misc.glob(pjoin('*','*_banner.txt'), pjoin(self.me_dir, 'Events')) 1909 data = [n.rsplit('/',2)[1:] for n in data] 1910 1911 if data: 1912 out = {} 1913 for name, tag in data: 1914 tag = tag[len(name)+1:-11] 1915 if name in out: 1916 out[name].append(tag) 1917 else: 1918 out[name] = [tag] 1919 print 'the runs available are:' 1920 for run_name, tags in out.items(): 1921 print ' run: %s' % run_name 1922 print ' tags: ', 1923 print ', '.join(tags) 1924 else: 1925 print 'No run detected.' 1926 1927 elif args[0] == 'options': 1928 outstr = " Run Options \n" 1929 outstr += " ----------- \n" 1930 for key, default in self.options_madgraph.items(): 1931 value = self.options[key] 1932 if value == default: 1933 outstr += " %25s \t:\t%s\n" % (key,value) 1934 else: 1935 outstr += " %25s \t:\t%s (user set)\n" % (key,value) 1936 outstr += "\n" 1937 outstr += " MadEvent Options \n" 1938 outstr += " ---------------- \n" 1939 for key, default in self.options_madevent.items(): 1940 if key in self.options: 1941 value = self.options[key] 1942 else: 1943 default = '' 1944 if value == default: 1945 outstr += " %25s \t:\t%s\n" % (key,value) 1946 else: 1947 outstr += " %25s \t:\t%s (user set)\n" % (key,value) 1948 outstr += "\n" 1949 outstr += " Configuration Options \n" 1950 outstr += " --------------------- \n" 1951 for key, default in self.options_configuration.items(): 1952 value = self.options[key] 1953 if value == default: 1954 outstr += " %25s \t:\t%s\n" % (key,value) 1955 else: 1956 outstr += " %25s \t:\t%s (user set)\n" % (key,value) 1957 output.write(outstr) 1958 elif args[0] == 'results': 1959 self.do_print_results(' '.join(args[1:])) 1960 else: 1961 super(MadEventCmd, self).do_display(line, output)
1962
1963 - def do_save(self, line, check=True, to_keep={}):
1964 """Not in help: Save information to file""" 1965 1966 args = self.split_arg(line) 1967 # Check argument validity 1968 if check: 1969 self.check_save(args) 1970 1971 if args[0] == 'options': 1972 # First look at options which should be put in MG5DIR/input 1973 to_define = {} 1974 for key, default in self.options_configuration.items(): 1975 if self.options[key] != self.options_configuration[key]: 1976 to_define[key] = self.options[key] 1977 1978 if not '--auto' in args: 1979 for key, default in self.options_madevent.items(): 1980 if self.options[key] != self.options_madevent[key]: 1981 to_define[key] = self.options[key] 1982 1983 if '--all' in args: 1984 for key, default in self.options_madgraph.items(): 1985 if self.options[key] != self.options_madgraph[key]: 1986 to_define[key] = self.options[key] 1987 elif not '--auto' in args: 1988 for key, default in self.options_madgraph.items(): 1989 if self.options[key] != self.options_madgraph[key]: 1990 logger.info('The option %s is modified [%s] but will not be written in the configuration files.' \ 1991 % (key,self.options_madgraph[key]) ) 1992 logger.info('If you want to make this value the default for future session, you can run \'save options --all\'') 1993 if len(args) >1 and not args[1].startswith('--'): 1994 filepath = args[1] 1995 else: 1996 filepath = pjoin(self.me_dir, 'Cards', 'me5_configuration.txt') 1997 basefile = pjoin(self.me_dir, 'Cards', 'me5_configuration.txt') 1998 basedir = self.me_dir 1999 2000 if to_keep: 2001 to_define = to_keep 2002 self.write_configuration(filepath, basefile, basedir, to_define)
2003 2004 2005 2006
2007 - def do_edit_cards(self, line):
2008 """Advanced commands: Basic edition of the cards""" 2009 args = self.split_arg(line) 2010 # Check argument's validity 2011 mode = self.check_generate_events(args) 2012 self.ask_run_configuration(mode) 2013 2014 return
2015 2016 ############################################################################ 2017 2018 ############################################################################
2019 - def do_generate_events(self, line):
2020 """Main Commands: launch the full chain """ 2021 2022 self.banner = None 2023 args = self.split_arg(line) 2024 # Check argument's validity 2025 mode = self.check_generate_events(args) 2026 switch_mode = self.ask_run_configuration(mode, args) 2027 if not args: 2028 # No run name assigned -> assigned one automaticaly 2029 self.set_run_name(self.find_available_run_name(self.me_dir), None, 'parton') 2030 else: 2031 self.set_run_name(args[0], None, 'parton', True) 2032 args.pop(0) 2033 2034 if self.proc_characteristics['loop_induced'] and self.options['run_mode']==0: 2035 # Also the single core mode is not supported for loop-induced. 2036 # We therefore emulate it with multi-core mode with one core 2037 logger.warning( 2038 """Single-core mode not supported for loop-induced processes. 2039 Beware that MG5aMC now changes your runtime options to a multi-core mode with only one active core.""") 2040 self.do_set('run_mode 2') 2041 self.do_set('nb_core 1') 2042 2043 if self.run_card['gridpack'] in self.true: 2044 # Running gridpack warmup 2045 gridpack_opts=[('accuracy', 0.01), 2046 ('points', 2000), 2047 ('iterations',8), 2048 ('gridpack','.true.')] 2049 logger.info('Generating gridpack with run name %s' % self.run_name) 2050 self.exec_cmd('survey %s %s' % \ 2051 (self.run_name, 2052 " ".join(['--' + opt + '=' + str(val) for (opt,val) \ 2053 in gridpack_opts])), 2054 postcmd=False) 2055 self.exec_cmd('combine_events', postcmd=False) 2056 self.exec_cmd('store_events', postcmd=False) 2057 self.exec_cmd('decay_events -from_cards', postcmd=False) 2058 self.exec_cmd('create_gridpack', postcmd=False) 2059 else: 2060 # Regular run mode 2061 logger.info('Generating %s events with run name %s' % 2062 (self.run_card['nevents'], self.run_name)) 2063 2064 self.exec_cmd('survey %s %s' % (self.run_name,' '.join(args)), 2065 postcmd=False) 2066 nb_event = self.run_card['nevents'] 2067 bypass_run=False 2068 self.exec_cmd('refine %s' % nb_event, postcmd=False) 2069 if not float(self.results.current['cross']): 2070 # Zero cross-section. Try to guess why 2071 text = '''Survey return zero cross section. 2072 Typical reasons are the following: 2073 1) A massive s-channel particle has a width set to zero. 2074 2) The pdf are zero for at least one of the initial state particles 2075 or you are using maxjetflavor=4 for initial state b:s. 2076 3) The cuts are too strong. 2077 Please check/correct your param_card and/or your run_card.''' 2078 logger_stderr.critical(text) 2079 if not self.param_card_iterator: 2080 raise ZeroResult('See https://cp3.irmp.ucl.ac.be/projects/madgraph/wiki/FAQ-General-14') 2081 else: 2082 bypass_run = True 2083 2084 #we can bypass the following if scan and first result is zero 2085 if not bypass_run: 2086 self.exec_cmd('refine %s' % nb_event, postcmd=False) 2087 2088 self.exec_cmd('combine_events', postcmd=False,printcmd=False) 2089 self.print_results_in_shell(self.results.current) 2090 2091 if self.run_card['use_syst']: 2092 if self.run_card['systematics_program'] == 'auto': 2093 scdir = self.options['syscalc_path'] 2094 if not scdir or not os.path.exists(scdir): 2095 to_use = 'systematics' 2096 else: 2097 to_use = 'syscalc' 2098 elif self.run_card['systematics_program'].lower() in ['systematics','syscalc', 'none']: 2099 to_use = self.run_card['systematics_program'] 2100 else: 2101 logger.critical('Unvalid options for systematics_program: bypass computation of systematics variations.') 2102 to_use = 'none' 2103 2104 if to_use == 'systematics': 2105 if self.run_card['systematics_arguments'] != ['']: 2106 self.exec_cmd('systematics %s %s ' % (self.run_name, 2107 ' '.join(self.run_card['systematics_arguments'])), 2108 postcmd=False, printcmd=False) 2109 else: 2110 self.exec_cmd('systematics %s --from_card' % self.run_name, 2111 postcmd=False,printcmd=False) 2112 elif to_use == 'syscalc': 2113 self.run_syscalc('parton') 2114 2115 2116 self.create_plot('parton') 2117 self.exec_cmd('store_events', postcmd=False) 2118 self.exec_cmd('reweight -from_cards', postcmd=False) 2119 self.exec_cmd('decay_events -from_cards', postcmd=False) 2120 if self.run_card['time_of_flight']>=0: 2121 self.exec_cmd("add_time_of_flight --threshold=%s" % self.run_card['time_of_flight'] ,postcmd=False) 2122 2123 if switch_mode['analysis'] == 'EXROOTANALYSIS': 2124 input = pjoin(self.me_dir, 'Events', self.run_name,'unweighted_events.lhe.gz') 2125 output = pjoin(self.me_dir, 'Events', self.run_name, 'unweighted_events.root') 2126 self.create_root_file(input , output) 2127 2128 self.exec_cmd('madanalysis5_parton --no_default', postcmd=False, printcmd=False) 2129 # shower launches pgs/delphes if needed 2130 self.exec_cmd('shower --no_default', postcmd=False, printcmd=False) 2131 self.exec_cmd('madanalysis5_hadron --no_default', postcmd=False, printcmd=False) 2132 self.store_result() 2133 2134 if self.param_card_iterator: 2135 param_card_iterator = self.param_card_iterator 2136 self.param_card_iterator = [] 2137 with misc.TMP_variable(self, 'allow_notification_center', False): 2138 param_card_iterator.store_entry(self.run_name, self.results.current['cross']) 2139 #check if the param_card defines a scan. 2140 orig_name = self.run_name 2141 for card in param_card_iterator: 2142 path = pjoin(self.me_dir,'Cards','param_card.dat') 2143 card.write(pjoin(self.me_dir,'Cards','param_card.dat')) 2144 self.check_param_card(path, dependent=True) 2145 next_name = param_card_iterator.get_next_name(self.run_name) 2146 try: 2147 self.exec_cmd("generate_events -f %s" % next_name, 2148 precmd=True, postcmd=True,errorhandling=False) 2149 except ZeroResult: 2150 param_card_iterator.store_entry(self.run_name, 0) 2151 else: 2152 param_card_iterator.store_entry(self.run_name, self.results.current['cross']) 2153 param_card_iterator.write(pjoin(self.me_dir,'Cards','param_card.dat')) 2154 name = misc.get_scan_name(orig_name, self.run_name) 2155 path = pjoin(self.me_dir, 'Events','scan_%s.txt' % name) 2156 logger.info("write all cross-section results in %s" % path ,'$MG:color:BLACK') 2157 param_card_iterator.write_summary(path) 2158 2159 2160 if self.allow_notification_center: 2161 misc.apple_notify('Run %s finished' % os.path.basename(self.me_dir), 2162 '%s: %s +- %s ' % (self.results.current['run_name'], 2163 self.results.current['cross'], 2164 self.results.current['error']))
2165
2166 - def do_initMadLoop(self,line):
2167 """Compile and run MadLoop for a certain number of PS point so as to 2168 initialize MadLoop (setup the zero helicity and loop filter.)""" 2169 2170 args = line.split() 2171 # Check argument's validity 2172 options = self.check_initMadLoop(args) 2173 2174 if not options['force']: 2175 self.ask_edit_cards(['MadLoopParams.dat'], mode='fixed', plot=False) 2176 self.exec_cmd('treatcards loop --no_MadLoopInit') 2177 2178 if options['refresh']: 2179 for filter in misc.glob('*Filter*', 2180 pjoin(self.me_dir,'SubProcesses','MadLoop5_resources')): 2181 logger.debug("Resetting filter '%s'."%os.path.basename(filter)) 2182 os.remove(filter) 2183 2184 MLCard = banner_mod.MadLoopParam(pjoin(self.me_dir, 2185 'Cards','MadLoopParams.dat')) 2186 if options['nPS'] is None: 2187 options['nPS'] = MLCard['CheckCycle']+2 2188 elif options['nPS'] < MLCard['CheckCycle']+2: 2189 new_n_PS = MLCard['CheckCycle']+2 2190 logger.debug('Hard-setting user-defined n_PS (%d) to %d, because '\ 2191 %(options['nPS'],new_n_PS)+"of the 'CheckCycle' value (%d) "%MLCard['CheckCycle']+\ 2192 "specified in the ML param card.") 2193 options['nPS'] = new_n_PS 2194 2195 MadLoopInitializer.init_MadLoop(self.me_dir,n_PS=options['nPS'], 2196 subproc_prefix='PV', MG_options=self.options, interface=self)
2197
2198 - def do_launch(self, line, *args, **opt):
2199 """Main Commands: exec generate_events for 2>N and calculate_width for 1>N""" 2200 2201 if self.ninitial == 1: 2202 logger.info("Note that since 2.3. The launch for 1>N pass in event generation\n"+ 2203 " To have the previous behavior use the calculate_decay_widths function") 2204 # self.do_calculate_decay_widths(line, *args, **opt) 2205 #else: 2206 self.do_generate_events(line, *args, **opt)
2207
2208 - def print_results_in_shell(self, data):
2209 """Have a nice results prints in the shell, 2210 data should be of type: gen_crossxhtml.OneTagResults""" 2211 2212 if not data: 2213 return 2214 2215 if data['run_statistics']: 2216 globalstat = sum_html.RunStatistics() 2217 2218 logger.info(" " ) 2219 logger.debug(" === Run statistics summary ===") 2220 for key, value in data['run_statistics'].items(): 2221 globalstat.aggregate_statistics(value) 2222 level = 5 2223 if value.has_warning(): 2224 level = 10 2225 logger.log(level, value.nice_output(str('/'.join([key[0],'G%s'%key[1]]))).\ 2226 replace(' statistics','')) 2227 logger.info(" " ) 2228 logger.debug(globalstat.nice_output('combined', no_warning=True)) 2229 if globalstat.has_warning(): 2230 logger.warning(globalstat.get_warning_text()) 2231 logger.info(" ") 2232 2233 2234 logger.info(" === Results Summary for run: %s tag: %s ===\n" % (data['run_name'],data['tag'])) 2235 2236 total_time = int(sum(_['cumulative_timing'] for _ in data['run_statistics'].values())) 2237 if total_time > 0: 2238 logger.info(" Cumulative sequential time for this run: %s"%misc.format_time(total_time)) 2239 2240 if self.ninitial == 1: 2241 logger.info(" Width : %.4g +- %.4g GeV" % (data['cross'], data['error'])) 2242 else: 2243 logger.info(" Cross-section : %.4g +- %.4g pb" % (data['cross'], data['error'])) 2244 logger.info(" Nb of events : %s" % data['nb_event'] ) 2245 2246 if data['run_mode']=='madevent': 2247 if data['cross_pythia'] and data['nb_event_pythia']: 2248 if data['cross_pythia'] == -1: 2249 path = pjoin(self.me_dir, 'Events', self.run_name, '%s_merged_xsecs.txt' % self.run_tag) 2250 cross_sections = {} 2251 if os.path.exists(path): 2252 for line in open(path): 2253 split = line.split() 2254 if len(split)!=3: 2255 continue 2256 scale, cross, error = split 2257 cross_sections[float(scale)] = (float(cross), float(error)) 2258 if len(cross_sections)>0: 2259 logger.info(' Pythia8 merged cross-sections are:') 2260 for scale in sorted(cross_sections.keys()): 2261 logger.info(' > Merging scale = %-6.4g : %-11.5g +/- %-7.2g [pb]'%\ 2262 (scale,cross_sections[scale][0],cross_sections[scale][1])) 2263 2264 else: 2265 if self.ninitial == 1: 2266 logger.info(" Matched width : %.4g +- %.4g GeV" % (data['cross_pythia'], data['error_pythia'])) 2267 else: 2268 logger.info(" Matched cross-section : %.4g +- %.4g pb" % (data['cross_pythia'], data['error_pythia'])) 2269 logger.info(" Nb of events after matching/merging : %d" % int(data['nb_event_pythia'])) 2270 if self.run_card['use_syst'] in self.true and \ 2271 (int(self.run_card['ickkw'])==1 or self.run_card['ktdurham']>0.0 2272 or self.run_card['ptlund']>0.0): 2273 logger.info(" Notice that because Systematics computation is turned on, the merging did not veto events but modified their weights instead.\n"+\ 2274 " The resulting hepmc/stdhep file should therefore be use with those weights.") 2275 else: 2276 logger.info(" Nb of events after merging : %s" % data['nb_event_pythia']) 2277 2278 logger.info(" " )
2279
2280 - def print_results_in_file(self, data, path, mode='w', format='full'):
2281 """Have a nice results prints in the shell, 2282 data should be of type: gen_crossxhtml.OneTagResults""" 2283 if not data: 2284 return 2285 2286 fsock = open(path, mode) 2287 2288 if data['run_statistics']: 2289 logger.debug(" === Run statistics summary ===") 2290 for key, value in data['run_statistics'].items(): 2291 logger.debug(value.nice_output(str('/'.join([key[0],'G%s'%key[1]]))).\ 2292 replace(' statistics','')) 2293 logger.info(" " ) 2294 2295 if format == "full": 2296 fsock.write(" === Results Summary for run: %s tag: %s process: %s ===\n" % \ 2297 (data['run_name'],data['tag'], os.path.basename(self.me_dir))) 2298 2299 if self.ninitial == 1: 2300 fsock.write(" Width : %.4g +- %.4g GeV\n" % (data['cross'], data['error'])) 2301 else: 2302 fsock.write(" Cross-section : %.4g +- %.4g pb\n" % (data['cross'], data['error'])) 2303 fsock.write(" Nb of events : %s\n" % data['nb_event'] ) 2304 if data['cross_pythia'] and data['nb_event_pythia']: 2305 if self.ninitial == 1: 2306 fsock.write(" Matched Width : %.4g +- %.4g GeV\n" % (data['cross_pythia'], data['error_pythia'])) 2307 else: 2308 fsock.write(" Matched Cross-section : %.4g +- %.4g pb\n" % (data['cross_pythia'], data['error_pythia'])) 2309 fsock.write(" Nb of events after Matching : %s\n" % data['nb_event_pythia']) 2310 fsock.write(" \n" ) 2311 elif format == "short": 2312 if mode == "w": 2313 fsock.write("# run_name tag cross error Nb_event cross_after_matching nb_event_after matching\n") 2314 2315 if data['cross_pythia'] and data['nb_event_pythia']: 2316 text = "%(run_name)s %(tag)s %(cross)s %(error)s %(nb_event)s %(cross_pythia)s %(nb_event_pythia)s\n" 2317 else: 2318 text = "%(run_name)s %(tag)s %(cross)s %(error)s %(nb_event)s\n" 2319 fsock.write(text % data)
2320 2321 ############################################################################
2322 - def do_calculate_decay_widths(self, line):
2323 """Main Commands: launch decay width calculation and automatic inclusion of 2324 calculated widths and BRs in the param_card.""" 2325 2326 args = self.split_arg(line) 2327 # Check argument's validity 2328 accuracy = self.check_calculate_decay_widths(args) 2329 self.ask_run_configuration('parton') 2330 self.banner = None 2331 if not args: 2332 # No run name assigned -> assigned one automaticaly 2333 self.set_run_name(self.find_available_run_name(self.me_dir)) 2334 else: 2335 self.set_run_name(args[0], reload_card=True) 2336 args.pop(0) 2337 2338 self.configure_directory() 2339 2340 # Running gridpack warmup 2341 opts=[('accuracy', accuracy), # default 0.01 2342 ('points', 1000), 2343 ('iterations',9)] 2344 2345 logger.info('Calculating decay widths with run name %s' % self.run_name) 2346 2347 self.exec_cmd('survey %s %s' % \ 2348 (self.run_name, 2349 " ".join(['--' + opt + '=' + str(val) for (opt,val) \ 2350 in opts])), 2351 postcmd=False) 2352 self.refine_mode = "old" # specify how to combine event 2353 self.exec_cmd('combine_events', postcmd=False) 2354 self.exec_cmd('store_events', postcmd=False) 2355 2356 self.collect_decay_widths() 2357 self.print_results_in_shell(self.results.current) 2358 self.update_status('calculate_decay_widths done', 2359 level='parton', makehtml=False)
2360 2361 2362 ############################################################################
2363 - def collect_decay_widths(self):
2364 """ Collect the decay widths and calculate BRs for all particles, and put 2365 in param_card form. 2366 """ 2367 2368 particle_dict = {} # store the results 2369 run_name = self.run_name 2370 2371 # Looping over the Subprocesses 2372 for P_path in SubProcesses.get_subP(self.me_dir): 2373 ids = SubProcesses.get_subP_ids(P_path) 2374 # due to grouping we need to compute the ratio factor for the 2375 # ungroup resutls (that we need here). Note that initial particles 2376 # grouping are not at the same stage as final particle grouping 2377 nb_output = len(ids) / (len(set([p[0] for p in ids]))) 2378 results = open(pjoin(P_path, run_name + '_results.dat')).read().split('\n')[0] 2379 result = float(results.strip().split(' ')[0]) 2380 for particles in ids: 2381 try: 2382 particle_dict[particles[0]].append([particles[1:], result/nb_output]) 2383 except KeyError: 2384 particle_dict[particles[0]] = [[particles[1:], result/nb_output]] 2385 2386 self.update_width_in_param_card(particle_dict, 2387 initial = pjoin(self.me_dir, 'Cards', 'param_card.dat'), 2388 output=pjoin(self.me_dir, 'Events', run_name, "param_card.dat"))
2389 2390 @staticmethod
2391 - def update_width_in_param_card(decay_info, initial=None, output=None):
2392 # Open the param_card.dat and insert the calculated decays and BRs 2393 2394 if not output: 2395 output = initial 2396 2397 param_card_file = open(initial) 2398 param_card = param_card_file.read().split('\n') 2399 param_card_file.close() 2400 2401 decay_lines = [] 2402 line_number = 0 2403 # Read and remove all decays from the param_card 2404 while line_number < len(param_card): 2405 line = param_card[line_number] 2406 if line.lower().startswith('decay'): 2407 # Read decay if particle in decay_info 2408 # DECAY 6 1.455100e+00 2409 line = param_card.pop(line_number) 2410 line = line.split() 2411 particle = 0 2412 if int(line[1]) not in decay_info: 2413 try: # If formatting is wrong, don't want this particle 2414 particle = int(line[1]) 2415 width = float(line[2]) 2416 except Exception: 2417 particle = 0 2418 # Read BRs for this decay 2419 line = param_card[line_number] 2420 while line.startswith('#') or line.startswith(' '): 2421 line = param_card.pop(line_number) 2422 if not particle or line.startswith('#'): 2423 line=param_card[line_number] 2424 continue 2425 # 6.668201e-01 3 5 2 -1 2426 line = line.split() 2427 try: # Remove BR if formatting is wrong 2428 partial_width = float(line[0])*width 2429 decay_products = [int(p) for p in line[2:2+int(line[1])]] 2430 except Exception: 2431 line=param_card[line_number] 2432 continue 2433 try: 2434 decay_info[particle].append([decay_products, partial_width]) 2435 except KeyError: 2436 decay_info[particle] = [[decay_products, partial_width]] 2437 if line_number == len(param_card): 2438 break 2439 line=param_card[line_number] 2440 if particle and particle not in decay_info: 2441 # No decays given, only total width 2442 decay_info[particle] = [[[], width]] 2443 else: # Not decay 2444 line_number += 1 2445 # Clean out possible remaining comments at the end of the card 2446 while not param_card[-1] or param_card[-1].startswith('#'): 2447 param_card.pop(-1) 2448 2449 # Append calculated and read decays to the param_card 2450 param_card.append("#\n#*************************") 2451 param_card.append("# Decay widths *") 2452 param_card.append("#*************************") 2453 for key in sorted(decay_info.keys()): 2454 width = sum([r for p,r in decay_info[key]]) 2455 param_card.append("#\n# PDG Width") 2456 param_card.append("DECAY %i %e" % (key, width.real)) 2457 if not width: 2458 continue 2459 if decay_info[key][0][0]: 2460 param_card.append("# BR NDA ID1 ID2 ...") 2461 brs = [[(val[1]/width).real, val[0]] for val in decay_info[key] if val[1]] 2462 for val in sorted(brs, reverse=True): 2463 param_card.append(" %e %i %s # %s" % 2464 (val[0].real, len(val[1]), 2465 " ".join([str(v) for v in val[1]]), 2466 val[0] * width 2467 )) 2468 decay_table = open(output, 'w') 2469 decay_table.write("\n".join(param_card) + "\n") 2470 decay_table.close() 2471 logger.info("Results written to %s" % output)
2472 2473 2474 ############################################################################
2475 - def do_multi_run(self, line):
2476 2477 args = self.split_arg(line) 2478 # Check argument's validity 2479 mode = self.check_multi_run(args) 2480 nb_run = args.pop(0) 2481 if nb_run == 1: 2482 logger.warn("'multi_run 1' command is not optimal. Think of using generate_events instead") 2483 self.ask_run_configuration(mode) 2484 2485 self.check_survey(args, cmd='multi_run') 2486 main_name = self.run_name 2487 # check if the param_card requires a scan over parameter. 2488 path=pjoin(self.me_dir, 'Cards', 'param_card.dat') 2489 self.check_param_card(path, run=False) 2490 #store it locally to avoid relaunch 2491 param_card_iterator, self.param_card_iterator = self.param_card_iterator, [] 2492 2493 crossoversig = 0 2494 inv_sq_err = 0 2495 nb_event = 0 2496 for i in range(nb_run): 2497 self.nb_refine = 0 2498 self.exec_cmd('generate_events %s_%s -f' % (main_name, i), postcmd=False) 2499 # Update collected value 2500 nb_event += int(self.results[self.run_name][-1]['nb_event']) 2501 self.results.add_detail('nb_event', nb_event , run=main_name) 2502 cross = self.results[self.run_name][-1]['cross'] 2503 error = self.results[self.run_name][-1]['error'] + 1e-99 2504 crossoversig+=cross/error**2 2505 inv_sq_err+=1.0/error**2 2506 self.results[main_name][-1]['cross'] = crossoversig/inv_sq_err 2507 self.results[main_name][-1]['error'] = math.sqrt(1.0/inv_sq_err) 2508 self.results.def_current(main_name) 2509 self.run_name = main_name 2510 self.update_status("Merging LHE files", level='parton') 2511 try: 2512 os.mkdir(pjoin(self.me_dir,'Events', self.run_name)) 2513 except Exception: 2514 pass 2515 os.system('%(bin)s/merge.pl %(event)s/%(name)s_*/unweighted_events.lhe.gz %(event)s/%(name)s/unweighted_events.lhe.gz %(event)s/%(name)s_banner.txt' 2516 % {'bin': self.dirbin, 'event': pjoin(self.me_dir,'Events'), 2517 'name': self.run_name}) 2518 2519 eradir = self.options['exrootanalysis_path'] 2520 if eradir and misc.is_executable(pjoin(eradir,'ExRootLHEFConverter')): 2521 self.update_status("Create Root file", level='parton') 2522 misc.gunzip('%s/%s/unweighted_events.lhe.gz' % 2523 (pjoin(self.me_dir,'Events'), self.run_name)) 2524 2525 self.create_root_file('%s/unweighted_events.lhe' % self.run_name, 2526 '%s/unweighted_events.root' % self.run_name) 2527 2528 path = pjoin(self.me_dir, "Events", self.run_name, "unweighted_events.lhe") 2529 self.create_plot('parton', path, 2530 pjoin(self.me_dir, 'HTML',self.run_name, 'plots_parton.html') 2531 ) 2532 2533 2534 if not os.path.exists('%s.gz' % path): 2535 misc.gzip(path) 2536 2537 self.update_status('', level='parton') 2538 self.print_results_in_shell(self.results.current) 2539 2540 if param_card_iterator: 2541 2542 param_card_iterator.store_entry(self.run_name, self.results.current['cross']) 2543 #check if the param_card defines a scan. 2544 orig_name=self.run_name 2545 for card in param_card_iterator: 2546 card.write(pjoin(self.me_dir,'Cards','param_card.dat')) 2547 self.exec_cmd("multi_run %s -f " % nb_run ,precmd=True, postcmd=True,errorhandling=False) 2548 param_card_iterator.store_entry(self.run_name, self.results.current['cross']) 2549 param_card_iterator.write(pjoin(self.me_dir,'Cards','param_card.dat')) 2550 scan_name = misc.get_scan_name(orig_name, self.run_name) 2551 path = pjoin(self.me_dir, 'Events','scan_%s.txt' % scan_name) 2552 logger.info("write all cross-section results in %s" % path, '$MG:color:BLACK') 2553 param_card_iterator.write_summary(path)
2554 2555 2556 ############################################################################
2557 - def do_treatcards(self, line, mode=None, opt=None):
2558 """Advanced commands: create .inc files from param_card.dat/run_card.dat""" 2559 2560 if not mode and not opt: 2561 args = self.split_arg(line) 2562 mode, opt = self.check_treatcards(args) 2563 2564 # To decide whether to refresh MadLoop's helicity filters, it is necessary 2565 # to check if the model parameters where modified or not, before doing 2566 # anything else. 2567 need_MadLoopFilterUpdate = False 2568 # Just to record what triggered the reinitialization of MadLoop for a 2569 # nice debug message. 2570 type_of_change = '' 2571 if not opt['forbid_MadLoopInit'] and self.proc_characteristics['loop_induced'] \ 2572 and mode in ['loop', 'all']: 2573 paramDat = pjoin(self.me_dir, 'Cards','param_card.dat') 2574 paramInc = pjoin(opt['output_dir'], 'param_card.inc') 2575 if (not os.path.isfile(paramDat)) or (not os.path.isfile(paramInc)) or \ 2576 (os.path.getmtime(paramDat)-os.path.getmtime(paramInc)) > 0.0: 2577 need_MadLoopFilterUpdate = True 2578 type_of_change = 'model' 2579 2580 ML_in = pjoin(self.me_dir, 'Cards', 'MadLoopParams.dat') 2581 ML_out = pjoin(self.me_dir,"SubProcesses", 2582 "MadLoop5_resources", "MadLoopParams.dat") 2583 if (not os.path.isfile(ML_in)) or (not os.path.isfile(ML_out)) or \ 2584 (os.path.getmtime(ML_in)-os.path.getmtime(ML_out)) > 0.0: 2585 need_MadLoopFilterUpdate = True 2586 type_of_change = 'MadLoop' 2587 2588 #check if no 'Auto' are present in the file 2589 self.check_param_card(pjoin(self.me_dir, 'Cards','param_card.dat')) 2590 2591 if mode in ['param', 'all']: 2592 model = self.find_model_name() 2593 tmp_model = os.path.basename(model) 2594 if tmp_model == 'mssm' or tmp_model.startswith('mssm-'): 2595 if not '--param_card=' in line: 2596 param_card = pjoin(self.me_dir, 'Cards','param_card.dat') 2597 mg5_param = pjoin(self.me_dir, 'Source', 'MODEL', 'MG5_param.dat') 2598 check_param_card.convert_to_mg5card(param_card, mg5_param) 2599 check_param_card.check_valid_param_card(mg5_param) 2600 opt['param_card'] = pjoin(self.me_dir, 'Source', 'MODEL', 'MG5_param.dat') 2601 else: 2602 check_param_card.check_valid_param_card(opt['param_card']) 2603 2604 logger.debug('write compile file for card: %s' % opt['param_card']) 2605 param_card = check_param_card.ParamCard(opt['param_card']) 2606 outfile = pjoin(opt['output_dir'], 'param_card.inc') 2607 ident_card = pjoin(self.me_dir,'Cards','ident_card.dat') 2608 if os.path.isfile(pjoin(self.me_dir,'bin','internal','ufomodel','restrict_default.dat')): 2609 default = pjoin(self.me_dir,'bin','internal','ufomodel','restrict_default.dat') 2610 elif os.path.isfile(pjoin(self.me_dir,'bin','internal','ufomodel','param_card.dat')): 2611 default = pjoin(self.me_dir,'bin','internal','ufomodel','param_card.dat') 2612 elif not os.path.exists(pjoin(self.me_dir,'bin','internal','ufomodel')): 2613 fsock = open(pjoin(self.me_dir,'Source','param_card.inc'),'w') 2614 fsock.write(' ') 2615 fsock.close() 2616 if mode == 'all': 2617 self.do_treatcards('', 'run', opt) 2618 return 2619 else: 2620 devnull = open(os.devnull,'w') 2621 subprocess.call([sys.executable, 'write_param_card.py'], 2622 cwd=pjoin(self.me_dir,'bin','internal','ufomodel'), 2623 stdout=devnull) 2624 devnull.close() 2625 default = pjoin(self.me_dir,'bin','internal','ufomodel','param_card.dat') 2626 2627 need_mp = self.proc_characteristics['loop_induced'] 2628 param_card.write_inc_file(outfile, ident_card, default, need_mp=need_mp) 2629 2630 2631 if mode in ['run', 'all']: 2632 if not hasattr(self, 'run_card'): 2633 run_card = banner_mod.RunCard(opt['run_card']) 2634 else: 2635 run_card = self.run_card 2636 if self.ninitial == 1: 2637 run_card['lpp1'] = 0 2638 run_card['lpp2'] = 0 2639 run_card['ebeam1'] = 0 2640 run_card['ebeam2'] = 0 2641 2642 # Ensure that the bias parameters has all the required input from the 2643 # run_card 2644 if run_card['bias_module'].lower() not in ['dummy','none']: 2645 # Using basename here means that the module will not be overwritten if already existing. 2646 bias_module_path = pjoin(self.me_dir,'Source','BIAS', 2647 os.path.basename(run_card['bias_module'])) 2648 if not os.path.isdir(bias_module_path): 2649 if not os.path.isdir(run_card['bias_module']): 2650 raise InvalidCmd("The bias module at '%s' cannot be found."%run_card['bias_module']) 2651 else: 2652 for mandatory_file in ['makefile','%s.f'%os.path.basename(run_card['bias_module'])]: 2653 if not os.path.isfile(pjoin(run_card['bias_module'],mandatory_file)): 2654 raise InvalidCmd("Could not find the mandatory file '%s' in bias module '%s'."%( 2655 mandatory_file,run_card['bias_module'])) 2656 shutil.copytree(run_card['bias_module'], pjoin(self.me_dir,'Source','BIAS', 2657 os.path.basename(run_card['bias_module']))) 2658 2659 #check expected parameters for the module. 2660 default_bias_parameters = {} 2661 start, last = False,False 2662 for line in open(pjoin(bias_module_path,'%s.f'%os.path.basename(bias_module_path))): 2663 if start and last: 2664 break 2665 if not start and not re.search('c\s*parameters\s*=\s*{',line, re.I): 2666 continue 2667 start = True 2668 if not line.startswith('C'): 2669 continue 2670 line = line[1:] 2671 if '{' in line: 2672 line = line.split('{')[-1] 2673 # split for } ! # 2674 split_result = re.split('(\}|!|\#)', line,1, re.M) 2675 line = split_result[0] 2676 sep = split_result[1] if len(split_result)>1 else None 2677 if sep == '}': 2678 last = True 2679 if ',' in line: 2680 for pair in line.split(','): 2681 if not pair.strip(): 2682 continue 2683 x,y =pair.split(':') 2684 x=x.strip() 2685 if x.startswith(('"',"'")) and x.endswith(x[0]): 2686 x = x[1:-1] 2687 default_bias_parameters[x] = y 2688 elif ':' in line: 2689 x,y = line.split(':') 2690 x = x.strip() 2691 if x.startswith(('"',"'")) and x.endswith(x[0]): 2692 x = x[1:-1] 2693 default_bias_parameters[x] = y 2694 for key,value in run_card['bias_parameters'].items(): 2695 if key not in default_bias_parameters: 2696 logger.warning('%s not supported by the bias module. We discard this entry.', key) 2697 else: 2698 default_bias_parameters[key] = value 2699 run_card['bias_parameters'] = default_bias_parameters 2700 2701 2702 # Finally write the include file 2703 run_card.write_include_file(opt['output_dir']) 2704 2705 2706 if self.proc_characteristics['loop_induced'] and mode in ['loop', 'all']: 2707 self.MadLoopparam = banner_mod.MadLoopParam(pjoin(self.me_dir, 2708 'Cards', 'MadLoopParams.dat')) 2709 # The writing out of MadLoop filter is potentially dangerous 2710 # when running in multi-core with a central disk. So it is turned 2711 # off here. If these filters were not initialized then they will 2712 # have to be re-computed at the beginning of each run. 2713 if 'WriteOutFilters' in self.MadLoopparam.user_set and \ 2714 self.MadLoopparam.get('WriteOutFilters'): 2715 logger.info( 2716 """You chose to have MadLoop writing out filters. 2717 Beware that this can be dangerous for local multicore runs.""") 2718 self.MadLoopparam.set('WriteOutFilters',False, changeifuserset=False) 2719 2720 # The conservative settings below for 'CTModeInit' and 'ZeroThres' 2721 # help adress issues for processes like g g > h z, and g g > h g 2722 # where there are some helicity configuration heavily suppressed 2723 # (by several orders of magnitude) so that the helicity filter 2724 # needs high numerical accuracy to correctly handle this spread in 2725 # magnitude. Also, because one cannot use the Born as a reference 2726 # scale, it is better to force quadruple precision *for the 2727 # initialization points only*. This avoids numerical accuracy issues 2728 # when setting up the helicity filters and does not significantly 2729 # slow down the run. 2730 # self.MadLoopparam.set('CTModeInit',4, changeifuserset=False) 2731 # Consequently, we can allow for a finer threshold for vanishing 2732 # helicity configuration 2733 # self.MadLoopparam.set('ZeroThres',1.0e-11, changeifuserset=False) 2734 2735 # It is a bit superficial to use the level 2 which tries to numerically 2736 # map matching helicities (because of CP symmetry typically) together. 2737 # It is useless in the context of MC over helicities and it can 2738 # potentially make the helicity double checking fail. 2739 self.MadLoopparam.set('HelicityFilterLevel',1, changeifuserset=False) 2740 2741 # To be on the safe side however, we ask for 4 consecutive matching 2742 # helicity filters. 2743 self.MadLoopparam.set('CheckCycle',4, changeifuserset=False) 2744 2745 # For now it is tricky to have each channel performing the helicity 2746 # double check. What we will end up doing is probably some kind 2747 # of new initialization round at the beginning of each launch 2748 # command, to reset the filters. 2749 self.MadLoopparam.set('DoubleCheckHelicityFilter',False, 2750 changeifuserset=False) 2751 2752 # Thanks to TIR recycling, TIR is typically much faster for Loop-induced 2753 # processes when not doing MC over helicities, so that we place OPP last. 2754 if not hasattr(self, 'run_card'): 2755 run_card = banner_mod.RunCard(opt['run_card']) 2756 else: 2757 run_card = self.run_card 2758 if run_card['nhel'] == 0: 2759 if 'MLReductionLib' in self.MadLoopparam.user_set and \ 2760 (self.MadLoopparam.get('MLReductionLib').startswith('1') or 2761 self.MadLoopparam.get('MLReductionLib').startswith('6')): 2762 logger.warning( 2763 """You chose to set the preferred reduction technique in MadLoop to be OPP (see parameter MLReductionLib). 2764 Beware that this can bring significant slowdown; the optimal choice --when not MC over helicity-- being to first start with TIR reduction.""") 2765 # We do not include GOLEM for now since it cannot recycle TIR coefs yet. 2766 self.MadLoopparam.set('MLReductionLib','7|6|1', changeifuserset=False) 2767 else: 2768 if 'MLReductionLib' in self.MadLoopparam.user_set and \ 2769 not (self.MadLoopparam.get('MLReductionLib').startswith('1') or 2770 self.MadLoopparam.get('MLReductionLib').startswith('6')): 2771 logger.warning( 2772 """You chose to set the preferred reduction technique in MadLoop to be different than OPP (see parameter MLReductionLib). 2773 Beware that this can bring significant slowdown; the optimal choice --when MC over helicity-- being to first start with OPP reduction.""") 2774 self.MadLoopparam.set('MLReductionLib','6|7|1', changeifuserset=False) 2775 2776 # Also TIR cache will only work when NRotations_DP=0 (but only matters 2777 # when not MC-ing over helicities) so it will be hard-reset by MadLoop 2778 # to zero when not MC-ing over helicities, unless the parameter 2779 # Force_ML_Helicity_Sum is set to True in the matrix<i>.f codes. 2780 if run_card['nhel'] == 0: 2781 if ('NRotations_DP' in self.MadLoopparam.user_set and \ 2782 self.MadLoopparam.get('NRotations_DP')!=0) or \ 2783 ('NRotations_QP' in self.MadLoopparam.user_set and \ 2784 self.MadLoopparam.get('NRotations_QP')!=0): 2785 logger.warning( 2786 """You chose to also use a lorentz rotation for stability tests (see parameter NRotations_[DP|QP]). 2787 Beware that, for optimization purposes, MadEvent uses manual TIR cache clearing which is not compatible 2788 with the lorentz rotation stability test. The number of these rotations to be used will be reset to 2789 zero by MadLoop. You can avoid this by changing the parameter 'FORCE_ML_HELICITY_SUM' int he matrix<i>.f 2790 files to be .TRUE. so that the sum over helicity configurations is performed within MadLoop (in which case 2791 the helicity of final state particles cannot be speicfied in the LHE file.""") 2792 self.MadLoopparam.set('NRotations_DP',0,changeifuserset=False) 2793 self.MadLoopparam.set('NRotations_QP',0,changeifuserset=False) 2794 else: 2795 # When MC-ing over helicities, the manual TIR cache clearing is 2796 # not necessary, so that one can use the lorentz check 2797 # Using NRotations_DP=1 slows down the code by close to 100% 2798 # but it is typicaly safer. 2799 # self.MadLoopparam.set('NRotations_DP',0,changeifuserset=False) 2800 # Revert to the above to be slightly less robust but twice faster. 2801 self.MadLoopparam.set('NRotations_DP',1,changeifuserset=False) 2802 self.MadLoopparam.set('NRotations_QP',0,changeifuserset=False) 2803 2804 # Finally, the stability tests are slightly less reliable for process 2805 # with less or equal than 4 final state particles because the 2806 # accessible kinematic is very limited (i.e. lorentz rotations don't 2807 # shuffle invariants numerics much). In these cases, we therefore 2808 # increase the required accuracy to 10^-7. 2809 # This is important for getting g g > z z [QCD] working with a 2810 # ptheavy cut as low as 1 GeV. 2811 if self.proc_characteristics['nexternal']<=4: 2812 if ('MLStabThres' in self.MadLoopparam.user_set and \ 2813 self.MadLoopparam.get('MLStabThres')>1.0e-7): 2814 logger.warning( 2815 """You chose to increase the default value of the MadLoop parameter 'MLStabThres' above 1.0e-7. 2816 Stability tests can be less reliable on the limited kinematic of processes with less or equal 2817 than four external legs, so this is not recommended (especially not for g g > z z).""") 2818 self.MadLoopparam.set('MLStabThres',1.0e-7,changeifuserset=False) 2819 else: 2820 self.MadLoopparam.set('MLStabThres',1.0e-4,changeifuserset=False) 2821 2822 #write the output file 2823 self.MadLoopparam.write(pjoin(self.me_dir,"SubProcesses","MadLoop5_resources", 2824 "MadLoopParams.dat")) 2825 2826 if self.proc_characteristics['loop_induced'] and mode in ['loop', 'all']: 2827 # Now Update MadLoop filters if necessary (if modifications were made to 2828 # the model parameters). 2829 if need_MadLoopFilterUpdate: 2830 logger.debug('Changes to the %s parameters'%type_of_change+\ 2831 ' have been detected. Madevent will then now reinitialize'+\ 2832 ' MadLoop filters.') 2833 self.exec_cmd('initMadLoop -r -f') 2834 # The need_MadLoopInit condition is just there so as to avoid useless 2835 # printout if there is not initialization to be performed. But even 2836 # without it, and because we call 'initMadLoop' without the '-r' option 2837 # no time would be wasted anyway, since the existing filters would not 2838 # be overwritten. 2839 elif not opt['forbid_MadLoopInit'] and \ 2840 MadLoopInitializer.need_MadLoopInit(self.me_dir): 2841 self.exec_cmd('initMadLoop -f')
2842 2843 ############################################################################
2844 - def do_survey(self, line):
2845 """Advanced commands: launch survey for the current process """ 2846 2847 2848 args = self.split_arg(line) 2849 # Check argument's validity 2850 self.check_survey(args) 2851 # initialize / remove lhapdf mode 2852 2853 if os.path.exists(pjoin(self.me_dir,'error')): 2854 os.remove(pjoin(self.me_dir,'error')) 2855 2856 self.configure_directory() 2857 # Save original random number 2858 self.random_orig = self.random 2859 logger.info("Using random number seed offset = %s" % self.random) 2860 # Update random number 2861 self.update_random() 2862 self.save_random() 2863 self.update_status('Running Survey', level=None) 2864 if self.cluster_mode: 2865 logger.info('Creating Jobs') 2866 2867 self.total_jobs = 0 2868 subproc = [l.strip() for l in open(pjoin(self.me_dir, 2869 'SubProcesses', 'subproc.mg'))] 2870 2871 P_zero_result = [] # check the number of times where they are no phase-space 2872 2873 # File for the loop (for loop induced) 2874 if os.path.exists(pjoin(self.me_dir,'SubProcesses', 2875 'MadLoop5_resources')) and cluster.need_transfer(self.options): 2876 tf=tarfile.open(pjoin(self.me_dir, 'SubProcesses', 2877 'MadLoop5_resources.tar.gz'), 'w:gz', dereference=True) 2878 tf.add(pjoin(self.me_dir,'SubProcesses','MadLoop5_resources'), 2879 arcname='MadLoop5_resources') 2880 tf.close() 2881 2882 logger.info('Working on SubProcesses') 2883 ajobcreator = gen_ximprove.gensym(self) 2884 2885 #check difficult PS case 2886 if float(self.run_card['mmjj']) > 0.01 * (float(self.run_card['ebeam1'])+float(self.run_card['ebeam2'])): 2887 self.pass_in_difficult_integration_mode() 2888 2889 jobs, P_zero_result = ajobcreator.launch() 2890 2891 # Check if all or only some fails 2892 if P_zero_result: 2893 if len(P_zero_result) == len(subproc): 2894 Pdir = pjoin(self.me_dir, 'SubProcesses',subproc[0].strip()) 2895 raise ZeroResult, '%s' % \ 2896 open(pjoin(Pdir,'ajob.no_ps.log')).read() 2897 else: 2898 logger.warning(''' %s SubProcesses doesn\'t have available phase-space. 2899 Please check mass spectrum.''' % ','.join(P_zero_result)) 2900 2901 2902 self.monitor(run_type='All jobs submitted for survey', html=True) 2903 if not self.history or 'survey' in self.history[-1] or self.ninitial ==1 or \ 2904 self.run_card['gridpack']: 2905 #will be done during the refine (more precisely in gen_ximprove) 2906 cross, error = sum_html.make_all_html_results(self) 2907 self.results.add_detail('cross', cross) 2908 self.results.add_detail('error', error) 2909 self.exec_cmd("print_results %s" % self.run_name, 2910 errorhandling=False, printcmd=False, precmd=False, postcmd=False) 2911 2912 self.results.add_detail('run_statistics', dict(ajobcreator.run_statistics)) 2913 self.update_status('End survey', 'parton', makehtml=False)
2914 2915 ############################################################################
2916 - def pass_in_difficult_integration_mode(self):
2917 """be more secure for the integration to not miss it due to strong cut""" 2918 2919 # improve survey options if default 2920 if self.opts['points'] == self._survey_options['points'][1]: 2921 self.opts['points'] = 2 * self._survey_options['points'][1] 2922 if self.opts['iterations'] == self._survey_options['iterations'][1]: 2923 self.opts['iterations'] = 1 + self._survey_options['iterations'][1] 2924 if self.opts['accuracy'] == self._survey_options['accuracy'][1]: 2925 self.opts['accuracy'] = self._survey_options['accuracy'][1]/2 2926 2927 # Modify run_config.inc in order to improve the refine 2928 #conf_path = pjoin(self.me_dir, 'Source','run_config.inc') 2929 #files.cp(conf_path, conf_path + '.bk') 2930 # 2931 #text = open(conf_path).read() 2932 #text = re.sub('''\(min_events = \d+\)''', '''(min_events = 7500 )''', text) 2933 #text = re.sub('''\(max_events = \d+\)''', '''(max_events = 20000 )''', text) 2934 #fsock = open(conf_path, 'w') 2935 #fsock.write(text) 2936 #fsock.close() 2937 2938 # Compile 2939 for name in ['../bin/internal/gen_ximprove', 'all', 2940 '../bin/internal/combine_events']: 2941 self.compile(arg=[name], cwd=os.path.join(self.me_dir, 'Source'))
2942 2943 2944 ############################################################################
2945 - def do_refine(self, line):
2946 """Advanced commands: launch survey for the current process """ 2947 devnull = open(os.devnull, 'w') 2948 self.nb_refine += 1 2949 args = self.split_arg(line) 2950 # Check argument's validity 2951 self.check_refine(args) 2952 2953 refine_opt = {'err_goal': args[0], 'split_channels': True} 2954 precision = args[0] 2955 if len(args) == 2: 2956 refine_opt['max_process']= args[1] 2957 2958 2959 # initialize / remove lhapdf mode 2960 self.configure_directory() 2961 2962 # Update random number 2963 self.update_random() 2964 self.save_random() 2965 2966 if self.cluster_mode: 2967 logger.info('Creating Jobs') 2968 self.update_status('Refine results to %s' % precision, level=None) 2969 2970 self.total_jobs = 0 2971 subproc = [l.strip() for l in open(pjoin(self.me_dir,'SubProcesses', 2972 'subproc.mg'))] 2973 2974 # cleanning the previous job 2975 for nb_proc,subdir in enumerate(subproc): 2976 subdir = subdir.strip() 2977 Pdir = pjoin(self.me_dir, 'SubProcesses', subdir) 2978 for match in misc.glob('*ajob*', Pdir): 2979 if os.path.basename(match)[:4] in ['ajob', 'wait', 'run.', 'done']: 2980 os.remove(match) 2981 2982 x_improve = gen_ximprove.gen_ximprove(self, refine_opt) 2983 # Load the run statistics from the survey 2984 survey_statistics = dict(self.results.get_detail('run_statistics')) 2985 # Printout survey statistics 2986 if __debug__ and survey_statistics: 2987 globalstat = sum_html.RunStatistics() 2988 logger.debug(" === Survey statistics summary ===") 2989 for key, value in survey_statistics.items(): 2990 globalstat.aggregate_statistics(value) 2991 level = 5 2992 if value.has_warning(): 2993 level = 10 2994 logger.log(level, 2995 value.nice_output(str('/'.join([key[0],'G%s'%key[1]]))). 2996 replace(' statistics','')) 2997 logger.debug(globalstat.nice_output('combined', no_warning=True)) 2998 2999 if survey_statistics: 3000 x_improve.run_statistics = survey_statistics 3001 3002 x_improve.launch() # create the ajob for the refinment. 3003 if not self.history or 'refine' not in self.history[-1]: 3004 cross, error = x_improve.update_html() #update html results for survey 3005 if cross == 0: 3006 return 3007 logger.info("Current estimate of cross-section: %s +- %s" % (cross, error)) 3008 3009 if isinstance(x_improve, gen_ximprove.gen_ximprove_v4): 3010 # Non splitted mode is based on writting ajob so need to track them 3011 # Splitted mode handle the cluster submition internally. 3012 for nb_proc,subdir in enumerate(subproc): 3013 subdir = subdir.strip() 3014 Pdir = pjoin(self.me_dir, 'SubProcesses',subdir) 3015 bindir = pjoin(os.path.relpath(self.dirbin, Pdir)) 3016 3017 logger.info(' %s ' % subdir) 3018 3019 if os.path.exists(pjoin(Pdir, 'ajob1')): 3020 self.compile(['madevent'], cwd=Pdir) 3021 3022 alljobs = misc.glob('ajob*', Pdir) 3023 3024 #remove associated results.dat (ensure to not mix with all data) 3025 Gre = re.compile("\s*j=(G[\d\.\w]+)") 3026 for job in alljobs: 3027 Gdirs = Gre.findall(open(job).read()) 3028 for Gdir in Gdirs: 3029 if os.path.exists(pjoin(Pdir, Gdir, 'results.dat')): 3030 os.remove(pjoin(Pdir, Gdir,'results.dat')) 3031 3032 nb_tot = len(alljobs) 3033 self.total_jobs += nb_tot 3034 for i, job in enumerate(alljobs): 3035 job = os.path.basename(job) 3036 self.launch_job('%s' % job, cwd=Pdir, remaining=(nb_tot-i-1), 3037 run_type='Refine number %s on %s (%s/%s)' % 3038 (self.nb_refine, subdir, nb_proc+1, len(subproc))) 3039 3040 self.monitor(run_type='All job submitted for refine number %s' % self.nb_refine, 3041 html=True) 3042 3043 self.update_status("Combining runs", level='parton') 3044 try: 3045 os.remove(pjoin(Pdir, 'combine_runs.log')) 3046 except Exception: 3047 pass 3048 3049 if isinstance(x_improve, gen_ximprove.gen_ximprove_v4): 3050 # the merge of the events.lhe is handle in the x_improve class 3051 # for splitted runs. (and partly in store_events). 3052 combine_runs.CombineRuns(self.me_dir) 3053 self.refine_mode = "old" 3054 else: 3055 self.refine_mode = "new" 3056 3057 cross, error = sum_html.make_all_html_results(self) 3058 self.results.add_detail('cross', cross) 3059 self.results.add_detail('error', error) 3060 3061 self.results.add_detail('run_statistics', 3062 dict(self.results.get_detail('run_statistics'))) 3063 3064 self.update_status('finish refine', 'parton', makehtml=False) 3065 devnull.close()
3066 3067 ############################################################################
3068 - def do_combine_iteration(self, line):
3069 """Not in help: Combine a given iteration combine_iteration Pdir Gdir S|R step 3070 S is for survey 3071 R is for refine 3072 step is the iteration number (not very critical)""" 3073 3074 self.set_run_name("tmp") 3075 self.configure_directory(html_opening=False) 3076 Pdir, Gdir, mode, step = self.split_arg(line) 3077 if Gdir.startswith("G"): 3078 Gdir = Gdir[1:] 3079 if "SubProcesses" not in Pdir: 3080 Pdir = pjoin(self.me_dir, "SubProcesses", Pdir) 3081 if mode == "S": 3082 self.opts = dict([(key,value[1]) for (key,value) in \ 3083 self._survey_options.items()]) 3084 gensym = gen_ximprove.gensym(self) 3085 gensym.combine_iteration(Pdir, Gdir, int(step)) 3086 elif mode == "R": 3087 refine = gen_ximprove.gen_ximprove_share(self) 3088 refine.combine_iteration(Pdir, Gdir, int(step))
3089 3090 3091 3092 3093 ############################################################################
3094 - def do_combine_events(self, line):
3095 """Advanced commands: Launch combine events""" 3096 3097 args = self.split_arg(line) 3098 # Check argument's validity 3099 self.check_combine_events(args) 3100 3101 self.update_status('Combining Events', level='parton') 3102 3103 3104 3105 if self.run_card['gridpack']: #not hasattr(self, "refine_mode") or self.refine_mode == "old": 3106 try: 3107 os.remove(pjoin(self.me_dir,'SubProcesses', 'combine.log')) 3108 except Exception: 3109 pass 3110 3111 cluster.onecore.launch_and_wait('../bin/internal/run_combine', 3112 args=[self.run_name], 3113 cwd=pjoin(self.me_dir,'SubProcesses'), 3114 stdout=pjoin(self.me_dir,'SubProcesses', 'combine.log'), 3115 required_output=[pjoin(self.me_dir,'SubProcesses', 'combine.log')]) 3116 3117 #self.cluster.launch_and_wait('../bin/internal/run_combine', 3118 # cwd=pjoin(self.me_dir,'SubProcesses'), 3119 # stdout=pjoin(self.me_dir,'SubProcesses', 'combine.log'), 3120 # required_output=[pjoin(self.me_dir,'SubProcesses', 'combine.log')]) 3121 3122 output = misc.mult_try_open(pjoin(self.me_dir,'SubProcesses','combine.log')).read() 3123 # Store the number of unweighted events for the results object 3124 pat = re.compile(r'''\s*Unweighting\s*selected\s*(\d+)\s*events''') 3125 try: 3126 nb_event = pat.search(output).groups()[0] 3127 except AttributeError: 3128 time.sleep(10) 3129 output = misc.mult_try_open(pjoin(self.me_dir,'SubProcesses','combine.log')).read() 3130 try: 3131 nb_event = pat.search(output).groups()[0] 3132 except AttributeError: 3133 logger.warning('Fail to read the number of unweighted events in the combine.log file') 3134 nb_event = 0 3135 3136 self.results.add_detail('nb_event', nb_event) 3137 3138 3139 # Define The Banner 3140 tag = self.run_card['run_tag'] 3141 3142 # Update the banner with the pythia card 3143 if not self.banner: 3144 self.banner = banner_mod.recover_banner(self.results, 'parton') 3145 self.banner.load_basic(self.me_dir) 3146 # Add cross-section/event information 3147 self.banner.add_generation_info(self.results.current['cross'], nb_event) 3148 if not hasattr(self, 'random_orig'): self.random_orig = 0 3149 self.banner.change_seed(self.random_orig) 3150 if not os.path.exists(pjoin(self.me_dir, 'Events', self.run_name)): 3151 os.mkdir(pjoin(self.me_dir, 'Events', self.run_name)) 3152 self.banner.write(pjoin(self.me_dir, 'Events', self.run_name, 3153 '%s_%s_banner.txt' % (self.run_name, tag))) 3154 3155 3156 self.banner.add_to_file(pjoin(self.me_dir,'Events', 'events.lhe'), 3157 out=pjoin(self.me_dir,'Events', self.run_name, 'events.lhe')) 3158 self.banner.add_to_file(pjoin(self.me_dir,'Events', 'unweighted_events.lhe'), 3159 out=pjoin(self.me_dir,'Events', self.run_name, 'unweighted_events.lhe')) 3160 3161 else: 3162 # Define The Banner 3163 tag = self.run_card['run_tag'] 3164 # Update the banner with the pythia card 3165 if not self.banner: 3166 self.banner = banner_mod.recover_banner(self.results, 'parton') 3167 self.banner.load_basic(self.me_dir) 3168 # Add cross-section/event information 3169 self.banner.add_generation_info(self.results.current['cross'], self.run_card['nevents']) 3170 if not hasattr(self, 'random_orig'): self.random_orig = 0 3171 self.banner.change_seed(self.random_orig) 3172 if not os.path.exists(pjoin(self.me_dir, 'Events', self.run_name)): 3173 os.mkdir(pjoin(self.me_dir, 'Events', self.run_name)) 3174 self.banner.write(pjoin(self.me_dir, 'Events', self.run_name, 3175 '%s_%s_banner.txt' % (self.run_name, tag))) 3176 3177 3178 get_wgt = lambda event: event.wgt 3179 AllEvent = lhe_parser.MultiEventFile() 3180 AllEvent.banner = self.banner 3181 3182 partials = 0 # if too many file make some partial unweighting 3183 sum_xsec, sum_xerru, sum_axsec = 0,[],0 3184 for Gdir,mfactor in self.get_Gdir(): 3185 if os.path.exists(pjoin(Gdir, 'events.lhe')): 3186 result = sum_html.OneResult('') 3187 result.read_results(pjoin(Gdir, 'results.dat')) 3188 AllEvent.add(pjoin(Gdir, 'events.lhe'), 3189 result.get('xsec'), 3190 result.get('xerru'), 3191 result.get('axsec') 3192 ) 3193 3194 sum_xsec += result.get('xsec') 3195 sum_xerru.append(result.get('xerru')) 3196 sum_axsec += result.get('axsec') 3197 3198 if len(AllEvent) >= 80: #perform a partial unweighting 3199 AllEvent.unweight(pjoin(self.me_dir, "Events", self.run_name, "partials%s.lhe.gz" % partials), 3200 get_wgt, log_level=5, trunc_error=1e-2, event_target=self.run_card['nevents']) 3201 AllEvent = lhe_parser.MultiEventFile() 3202 AllEvent.banner = self.banner 3203 AllEvent.add(pjoin(self.me_dir, "Events", self.run_name, "partials%s.lhe.gz" % partials), 3204 sum_xsec, 3205 math.sqrt(sum(x**2 for x in sum_xerru)), 3206 sum_axsec) 3207 partials +=1 3208 3209 if not hasattr(self,'proc_characteristic'): 3210 self.proc_characteristic = self.get_characteristics() 3211 3212 nb_event = AllEvent.unweight(pjoin(self.me_dir, "Events", self.run_name, "unweighted_events.lhe.gz"), 3213 get_wgt, trunc_error=1e-2, event_target=self.run_card['nevents'], 3214 log_level=logging.DEBUG, normalization=self.run_card['event_norm'], 3215 proc_charac=self.proc_characteristic) 3216 3217 if partials: 3218 for i in range(partials): 3219 try: 3220 os.remove(pjoin(self.me_dir, "Events", self.run_name, "partials%s.lhe.gz" % i)) 3221 except Exception: 3222 os.remove(pjoin(self.me_dir, "Events", self.run_name, "partials%s.lhe" % i)) 3223 3224 self.results.add_detail('nb_event', nb_event) 3225 3226 if self.run_card['bias_module'].lower() not in ['dummy', 'none']: 3227 self.correct_bias() 3228 3229 3230 3231 self.to_store.append('event')
3232 3233 ############################################################################
3234 - def correct_bias(self):
3235 """check the first event and correct the weight by the bias 3236 and correct the cross-section. 3237 If the event do not have the bias tag it means that the bias is 3238 one modifying the cross-section/shape so we have nothing to do 3239 """ 3240 3241 lhe = lhe_parser.EventFile(pjoin(self.me_dir, 'Events', self.run_name, 'unweighted_events.lhe.gz')) 3242 init = False 3243 cross = collections.defaultdict(float) 3244 nb_event = 0 3245 for event in lhe: 3246 rwgt_info = event.parse_reweight() 3247 if not init: 3248 if 'bias' in rwgt_info: 3249 output = lhe_parser.EventFile(pjoin(self.me_dir, 'Events', self.run_name, '.unweighted_events.lhe.tmp.gz'),'w') 3250 #output.write(lhe.banner) 3251 init = True 3252 else: 3253 return 3254 #change the weight 3255 event.wgt /= rwgt_info['bias'] 3256 #remove the bias info 3257 del event.reweight_data['bias'] 3258 # compute the new cross-section 3259 cross[event.ievent] += event.wgt 3260 nb_event +=1 3261 output.write(str(event)) 3262 output.write('</LesHouchesEvents>') 3263 output.close() 3264 lhe.close() 3265 3266 # MODIFY THE BANNER i.e. INIT BLOCK 3267 # ensure information compatible with normalisation choice 3268 total_cross = sum(cross[key] for key in cross) 3269 if 'event_norm' in self.run_card: # if not this is "sum" 3270 if self.run_card['event_norm'] == 'average': 3271 total_cross = total_cross / nb_event 3272 for key in cross: 3273 cross[key] /= nb_event 3274 elif self.run_card['event_norm'] == 'unity': 3275 total_cross = self.results.current['cross'] * total_cross / nb_event 3276 for key in cross: 3277 cross[key] *= total_cross / nb_event 3278 3279 bannerfile = lhe_parser.EventFile(pjoin(self.me_dir, 'Events', self.run_name, '.banner.tmp.gz'),'w') 3280 banner = banner_mod.Banner(lhe.banner) 3281 banner.modify_init_cross(cross) 3282 banner.write(bannerfile, close_tag=False) 3283 bannerfile.close() 3284 # replace the lhe file by the new one 3285 os.system('cat %s %s > %s' %(bannerfile.name, output.name, lhe.name)) 3286 os.remove(bannerfile.name) 3287 os.remove(output.name) 3288 3289 3290 self.results.current['cross'] = total_cross 3291 self.results.current['error'] = 0
3292 3293 ############################################################################
3294 - def do_store_events(self, line):
3295 """Advanced commands: Launch store events""" 3296 3297 args = self.split_arg(line) 3298 # Check argument's validity 3299 self.check_combine_events(args) 3300 self.update_status('Storing parton level results', level='parton') 3301 3302 run = self.run_name 3303 tag = self.run_card['run_tag'] 3304 devnull = open(os.devnull, 'w') 3305 3306 if not os.path.exists(pjoin(self.me_dir, 'Events', run)): 3307 os.mkdir(pjoin(self.me_dir, 'Events', run)) 3308 if not os.path.exists(pjoin(self.me_dir, 'HTML', run)): 3309 os.mkdir(pjoin(self.me_dir, 'HTML', run)) 3310 3311 # 1) Store overall process information 3312 #input = pjoin(self.me_dir, 'SubProcesses', 'results.dat') 3313 #output = pjoin(self.me_dir, 'SubProcesses', '%s_results.dat' % run) 3314 #files.cp(input, output) 3315 3316 3317 # 2) Treat the files present in the P directory 3318 # Ensure that the number of events is different of 0 3319 if self.results.current['nb_event'] == 0: 3320 logger.warning("No event detected. No cleaning performed! This should allow to run:\n" + 3321 " cd Subprocesses; ../bin/internal/combine_events\n"+ 3322 " to have your events if those one are missing.") 3323 else: 3324 for P_path in SubProcesses.get_subP(self.me_dir): 3325 G_dir = [G for G in os.listdir(P_path) if G.startswith('G') and 3326 os.path.isdir(pjoin(P_path,G))] 3327 for G in G_dir: 3328 G_path = pjoin(P_path,G) 3329 try: 3330 # Remove events file (if present) 3331 if os.path.exists(pjoin(G_path, 'events.lhe')): 3332 os.remove(pjoin(G_path, 'events.lhe')) 3333 except Exception: 3334 continue 3335 #try: 3336 # # Store results.dat 3337 # if os.path.exists(pjoin(G_path, 'results.dat')): 3338 # input = pjoin(G_path, 'results.dat') 3339 # output = pjoin(G_path, '%s_results.dat' % run) 3340 # files.cp(input, output) 3341 #except Exception: 3342 # continue 3343 # Store log 3344 try: 3345 if os.path.exists(pjoin(G_path, 'log.txt')): 3346 input = pjoin(G_path, 'log.txt') 3347 output = pjoin(G_path, '%s_log.txt' % run) 3348 files.mv(input, output) 3349 except Exception: 3350 continue 3351 #try: 3352 # # Grid 3353 # for name in ['ftn26']: 3354 # if os.path.exists(pjoin(G_path, name)): 3355 # if os.path.exists(pjoin(G_path, '%s_%s.gz'%(run,name))): 3356 # os.remove(pjoin(G_path, '%s_%s.gz'%(run,name))) 3357 # input = pjoin(G_path, name) 3358 # output = pjoin(G_path, '%s_%s' % (run,name)) 3359 # files.mv(input, output) 3360 # misc.gzip(pjoin(G_path, output), error=None) 3361 #except Exception: 3362 # continue 3363 # Delete ftn25 to ensure reproducible runs 3364 if os.path.exists(pjoin(G_path, 'ftn25')): 3365 os.remove(pjoin(G_path, 'ftn25')) 3366 3367 # 3) Update the index.html 3368 misc.call(['%s/gen_cardhtml-pl' % self.dirbin], 3369 cwd=pjoin(self.me_dir)) 3370 3371 3372 # 4) Move the Files present in Events directory 3373 E_path = pjoin(self.me_dir, 'Events') 3374 O_path = pjoin(self.me_dir, 'Events', run) 3375 3376 # The events file 3377 for name in ['events.lhe', 'unweighted_events.lhe']: 3378 finput = pjoin(E_path, name) 3379 foutput = pjoin(O_path, name) 3380 if os.path.exists(finput): 3381 logger.debug("File %s exists BAAAAD. Not move anymore!" % pjoin(E_path, name)) 3382 if os.path.exists(foutput): 3383 misc.gzip(foutput, stdout="%s.gz" % foutput, error=False) 3384 # if os.path.exists(pjoin(O_path, '%s.gz' % name)): 3385 # os.remove(pjoin(O_path, '%s.gz' % name)) 3386 # input = pjoin(E_path, name) 3387 ## output = pjoin(O_path, name) 3388 3389 3390 self.update_status('End Parton', level='parton', makehtml=False) 3391 devnull.close()
3392 3393 3394 ############################################################################
3395 - def do_create_gridpack(self, line):
3396 """Advanced commands: Create gridpack from present run""" 3397 3398 self.update_status('Creating gridpack', level='parton') 3399 # compile gen_ximprove 3400 misc.compile(['../bin/internal/gen_ximprove'], cwd=pjoin(self.me_dir, "Source")) 3401 args = self.split_arg(line) 3402 self.check_combine_events(args) 3403 if not self.run_tag: self.run_tag = 'tag_1' 3404 os.system("sed -i.bak \"s/ *.false.*=.*GridRun/ .true. = GridRun/g\" %s/Cards/grid_card.dat" \ 3405 % self.me_dir) 3406 misc.call(['./bin/internal/restore_data', self.run_name], 3407 cwd=self.me_dir) 3408 misc.call(['./bin/internal/store4grid', 3409 self.run_name, self.run_tag], 3410 cwd=self.me_dir) 3411 misc.call(['./bin/internal/clean'], cwd=self.me_dir) 3412 misc.call(['./bin/internal/make_gridpack'], cwd=self.me_dir) 3413 files.mv(pjoin(self.me_dir, 'gridpack.tar.gz'), 3414 pjoin(self.me_dir, '%s_gridpack.tar.gz' % self.run_name)) 3415 os.system("sed -i.bak \"s/\s*.true.*=.*GridRun/ .false. = GridRun/g\" %s/Cards/grid_card.dat" \ 3416 % self.me_dir) 3417 self.update_status('gridpack created', level='gridpack')
3418 3419 ############################################################################
3420 - def do_shower(self, line):
3421 """launch the shower""" 3422 3423 args = self.split_arg(line) 3424 if len(args)>1 and args[0] in self._interfaced_showers: 3425 chosen_showers = [args.pop(0)] 3426 elif '--no_default' in line: 3427 # If '--no_default' was specified in the arguments, then only one 3428 # shower will be run, depending on which card is present. 3429 # but we each of them are called. (each of them check if the file exists) 3430 chosen_showers = list(self._interfaced_showers) 3431 else: 3432 chosen_showers = list(self._interfaced_showers) 3433 # It is preferable to run only one shower, even if several are available and no 3434 # specific one has been selected 3435 shower_priority = ['pythia8','pythia'] 3436 chosen_showers = [sorted(chosen_showers,key=lambda sh: 3437 shower_priority.index(sh) if sh in shower_priority else len(shower_priority)+1)[0]] 3438 3439 for shower in chosen_showers: 3440 self.exec_cmd('%s %s'%(shower,' '.join(args)), 3441 postcmd=False, printcmd=False)
3442
3443 - def do_madanalysis5_parton(self, line):
3444 """launch MadAnalysis5 at the parton level.""" 3445 return self.run_madanalysis5(line,mode='parton')
3446 3447 #=============================================================================== 3448 # Return a warning (if applicable) on the consistency of the current Pythia8 3449 # and MG5_aMC version specified. It is placed here because it should be accessible 3450 # from both madgraph5_interface and madevent_interface 3451 #=============================================================================== 3452 @staticmethod
3453 - def mg5amc_py8_interface_consistency_warning(options):
3454 """ Check the consistency of the mg5amc_py8_interface installed with 3455 the current MG5 and Pythia8 versions. """ 3456 3457 # All this is only relevant is Pythia8 is interfaced to MG5 3458 if not options['pythia8_path']: 3459 return None 3460 3461 if not options['mg5amc_py8_interface_path']: 3462 return \ 3463 """ 3464 A Pythia8 path is specified via the option 'pythia8_path' but no path for option 3465 'mg5amc_py8_interface_path' is specified. This means that Pythia8 cannot be used 3466 leading order simulations with MadEvent. 3467 Consider installing the MG5_aMC-PY8 interface with the following command: 3468 MG5_aMC>install mg5amc_py8_interface 3469 """ 3470 3471 mg5amc_py8_interface_path = options['mg5amc_py8_interface_path'] 3472 py8_path = options['pythia8_path'] 3473 # If the specified interface path is relative, make it absolut w.r.t MGDIR if 3474 # avaialble. 3475 if not MADEVENT: 3476 mg5amc_py8_interface_path = pjoin(MG5DIR,mg5amc_py8_interface_path) 3477 py8_path = pjoin(MG5DIR,py8_path) 3478 3479 # Retrieve all the on-install and current versions 3480 fsock = open(pjoin(mg5amc_py8_interface_path, 'MG5AMC_VERSION_ON_INSTALL')) 3481 MG5_version_on_install = fsock.read().replace('\n','') 3482 fsock.close() 3483 if MG5_version_on_install == 'UNSPECIFIED': 3484 MG5_version_on_install = None 3485 fsock = open(pjoin(mg5amc_py8_interface_path, 'PYTHIA8_VERSION_ON_INSTALL')) 3486 PY8_version_on_install = fsock.read().replace('\n','') 3487 fsock.close() 3488 MG5_curr_version =misc.get_pkg_info()['version'] 3489 try: 3490 p = subprocess.Popen(['./get_pythia8_version.py',py8_path], 3491 stdout=subprocess.PIPE, stderr=subprocess.PIPE, 3492 cwd=mg5amc_py8_interface_path) 3493 (out, err) = p.communicate() 3494 out = out.replace('\n','') 3495 PY8_curr_version = out 3496 # In order to test that the version is correctly formed, we try to cast 3497 # it to a float 3498 float(out) 3499 except: 3500 PY8_curr_version = None 3501 3502 if not MG5_version_on_install is None and not MG5_curr_version is None: 3503 if MG5_version_on_install != MG5_curr_version: 3504 return \ 3505 """ 3506 The current version of MG5_aMC (v%s) is different than the one active when 3507 installing the 'mg5amc_py8_interface_path' (which was MG5aMC v%s). 3508 Please consider refreshing the installation of this interface with the command: 3509 MG5_aMC>install mg5amc_py8_interface 3510 """%(MG5_curr_version, MG5_version_on_install) 3511 3512 if not PY8_version_on_install is None and not PY8_curr_version is None: 3513 if PY8_version_on_install != PY8_curr_version: 3514 return \ 3515 """ 3516 The current version of Pythia8 (v%s) is different than the one active when 3517 installing the 'mg5amc_py8_interface' tool (which was Pythia8 v%s). 3518 Please consider refreshing the installation of this interface with the command: 3519 MG5_aMC>install mg5amc_py8_interface 3520 """%(PY8_curr_version,PY8_version_on_install) 3521 3522 return None
3523
3524 - def setup_Pythia8RunAndCard(self, PY8_Card, run_type):
3525 """ Setup the Pythia8 Run environment and card. In particular all the process and run specific parameters 3526 of the card are automatically set here. This function returns the path where HEPMC events will be output, 3527 if any.""" 3528 3529 HepMC_event_output = None 3530 tag = self.run_tag 3531 3532 PY8_Card.subruns[0].systemSet('Beams:LHEF',"unweighted_events.lhe.gz") 3533 3534 if PY8_Card['HEPMCoutput:file']=='auto': 3535 HepMC_event_output = pjoin(self.me_dir,'Events', self.run_name, 3536 '%s_pythia8_events.hepmc'%tag) 3537 PY8_Card.MadGraphSet('HEPMCoutput:file','%s_pythia8_events.hepmc'%tag, force=True) 3538 elif PY8_Card['HEPMCoutput:file'].startswith('fifo'): 3539 fifo_specs = PY8_Card['HEPMCoutput:file'].split('@') 3540 fifo_path = None 3541 if len(fifo_specs)<=1: 3542 fifo_path = pjoin(self.me_dir,'Events', self.run_name,'PY8.hepmc.fifo') 3543 if os.path.exists(fifo_path): 3544 os.remove(fifo_path) 3545 misc.mkfifo(fifo_path) 3546 # Use defaultSet not to overwrite the current userSet status 3547 PY8_Card.defaultSet('HEPMCoutput:file','PY8.hepmc.fifo') 3548 else: 3549 fifo_path = fifo_specs[1] 3550 if os.path.exists(fifo_path): 3551 if stat.S_ISFIFO(os.stat(fifo_path).st_mode): 3552 logger.warning('PY8 will be reusing already existing '+ 3553 'custom fifo file at:\n %s'%fifo_path) 3554 else: 3555 raise InvalidCmd( 3556 """The fifo path speficied for the PY8 parameter 'HEPMCoutput:file': 3557 %s 3558 already exists and is not a fifo file."""%fifo_path) 3559 else: 3560 misc.mkfifo(fifo_path) 3561 # Use defaultSet not to overwrite the current userSet status 3562 PY8_Card.defaultSet('HEPMCoutput:file',fifo_path) 3563 HepMC_event_output=fifo_path 3564 elif PY8_Card['HEPMCoutput:file'] in ['','/dev/null','None']: 3565 logger.warning('User disabled the HepMC output of Pythia8.') 3566 HepMC_event_output = None 3567 else: 3568 # Normalize the relative path if given as relative by the user. 3569 HepMC_event_output = pjoin(self.me_dir,'Events', self.run_name, 3570 PY8_Card['HEPMCoutput:file']) 3571 3572 # We specify by hand all necessary parameters, so that there is no 3573 # need to read parameters from the Banner. 3574 PY8_Card.MadGraphSet('JetMatching:setMad', False) 3575 if run_type=='MLM': 3576 # When running MLM make sure that we do not write out the parameter 3577 # Merging:xxx as this can interfere with the MLM merging in older 3578 # versions of the driver. 3579 PY8_Card.vetoParamWriteOut('Merging:TMS') 3580 PY8_Card.vetoParamWriteOut('Merging:Process') 3581 PY8_Card.vetoParamWriteOut('Merging:nJetMax') 3582 # MadGraphSet sets the corresponding value (in system mode) 3583 # only if it is not already user_set. 3584 if PY8_Card['JetMatching:qCut']==-1.0: 3585 PY8_Card.MadGraphSet('JetMatching:qCut',1.5*self.run_card['xqcut'], force=True) 3586 3587 if PY8_Card['JetMatching:qCut']<(1.5*self.run_card['xqcut']): 3588 logger.error( 3589 'The MLM merging qCut parameter you chose (%f) is less than '%PY8_Card['JetMatching:qCut']+ 3590 '1.5*xqcut, with xqcut your run_card parameter (=%f).\n'%self.run_card['xqcut']+ 3591 'It would be better/safer to use a larger qCut or a smaller xqcut.') 3592 3593 # Also make sure to use the shower starting scales specified in the LHE 3594 # unless the user specified it 3595 PY8_Card.systemSet('Beams:setProductionScalesFromLHEF',True) 3596 3597 # Automatically set qWeed to xqcut if not defined by the user. 3598 if PY8_Card['SysCalc:qWeed']==-1.0: 3599 PY8_Card.MadGraphSet('SysCalc:qWeed',self.run_card['xqcut'], force=True) 3600 3601 if PY8_Card['SysCalc:qCutList']=='auto': 3602 if self.run_card['use_syst']: 3603 if self.run_card['sys_matchscale']=='auto': 3604 qcut = PY8_Card['JetMatching:qCut'] 3605 value = [factor*qcut for factor in [0.5,0.75,1.0,1.5,2.0] if\ 3606 factor*qcut> 1.5*self.run_card['xqcut'] ] 3607 PY8_Card.MadGraphSet('SysCalc:qCutList', value, force=True) 3608 else: 3609 qCutList = [float(qc) for qc in self.run_card['sys_matchscale'].split()] 3610 if PY8_Card['JetMatching:qCut'] not in qCutList: 3611 qCutList.append(PY8_Card['JetMatching:qCut']) 3612 PY8_Card.MadGraphSet('SysCalc:qCutList', qCutList, force=True) 3613 3614 for scale in PY8_Card['SysCalc:qCutList']: 3615 if scale<(1.5*self.run_card['xqcut']): 3616 logger.error( 3617 'One of the MLM merging qCut parameter you chose (%f) in the variation list'%scale+\ 3618 " (either via 'SysCalc:qCutList' in the PY8 shower card or "+\ 3619 "'sys_matchscale' in the run_card) is less than 1.5*xqcut, where xqcut is"+ 3620 ' the run_card parameter (=%f)\n'%self.run_card['xqcut']+ 3621 'It would be better/safer to use a larger qCut or a smaller xqcut.') 3622 3623 # Specific MLM settings 3624 # PY8 should not implement the MLM veto since the driver should do it 3625 # if merging scale variation is turned on 3626 if self.run_card['use_syst']: 3627 # We do no force it here, but it is clear that the user should know what 3628 # he's doing if he were to force it to True. 3629 PY8_Card.MadGraphSet('JetMatching:doVeto',False) 3630 PY8_Card.MadGraphSet('JetMatching:merge',True) 3631 PY8_Card.MadGraphSet('JetMatching:scheme',1) 3632 # Use the parameter maxjetflavor for JetMatching:nQmatch which specifies 3633 # up to which parton must be matched.Merging:nQuarksMerge 3634 PY8_Card.MadGraphSet('JetMatching:nQmatch',self.run_card['maxjetflavor']) 3635 # For MLM, a cone radius of 1.0 is to be prefered. 3636 PY8_Card.MadGraphSet('JetMatching:coneRadius',1.0) 3637 # And the value of etaj_max is already infinity by default. 3638 # PY8_Card.MadGraphSet('JetMatching:etaJetMax',1000.0) 3639 if not hasattr(self,'proc_characteristic'): 3640 self.proc_characteristic = self.get_characteristics() 3641 nJetMax = self.proc_characteristic['max_n_matched_jets'] 3642 if PY8_Card['JetMatching:nJetMax'.lower()] == -1: 3643 logger.info("No user-defined value for Pythia8 parameter "+ 3644 "'JetMatching:nJetMax'. Setting it automatically to %d."%nJetMax) 3645 PY8_Card.MadGraphSet('JetMatching:nJetMax',nJetMax, force=True) 3646 # We use the positivity of 'ktdurham' cut as a CKKWl marker. 3647 elif run_type=='CKKW': 3648 3649 # Make sure the user correctly filled in the lowest order process to be considered 3650 if PY8_Card['Merging:Process']=='<set_by_user>': 3651 raise self.InvalidCmd('When running CKKWl merging, the user must'+ 3652 " specifiy the option 'Merging:Process' in pythia8_card.dat.\n"+ 3653 "Read section 'Defining the hard process' of "+\ 3654 "http://home.thep.lu.se/~torbjorn/pythia81html/CKKWLMerging.html for more information.") 3655 3656 # When running CKKWL make sure that we do not write out the parameter 3657 # JetMatching:xxx as this can interfere with the MLM merging in older 3658 # versions of the driver. 3659 PY8_Card.vetoParamWriteOut('JetMatching:qCut') 3660 PY8_Card.vetoParamWriteOut('JetMatching:doShowerKt') 3661 PY8_Card.vetoParamWriteOut('JetMatching:nJetMax') 3662 3663 CKKW_cut = None 3664 # Specific CKKW settings 3665 if self.run_card['ptlund']<=0.0 and self.run_card['ktdurham']>0.0: 3666 PY8_Card.subruns[0].MadGraphSet('Merging:doKTMerging',True) 3667 PY8_Card.subruns[0].MadGraphSet('Merging:Dparameter', 3668 self.run_card['dparameter']) 3669 CKKW_cut = 'ktdurham' 3670 elif self.run_card['ptlund']>0.0 and self.run_card['ktdurham']<=0.0: 3671 PY8_Card.subruns[0].MadGraphSet('Merging:doPTLundMerging',True) 3672 CKKW_cut = 'ptlund' 3673 else: 3674 raise InvalidCmd("*Either* the 'ptlund' or 'ktdurham' cut in "+\ 3675 " the run_card must be turned on to activate CKKW(L) merging"+ 3676 " with Pythia8, but *both* cuts cannot be turned on at the same time."+ 3677 "\n ptlund=%f, ktdurham=%f."%(self.run_card['ptlund'],self.run_card['ktdurham'])) 3678 3679 3680 # Automatically set qWeed to the CKKWL cut if not defined by the user. 3681 if PY8_Card['SysCalc:qWeed']==-1.0: 3682 PY8_Card.MadGraphSet('SysCalc:qWeed',self.run_card[CKKW_cut], force=True) 3683 3684 # MadGraphSet sets the corresponding value (in system mode) 3685 # only if it is not already user_set. 3686 if PY8_Card['Merging:TMS']==-1.0: 3687 if self.run_card[CKKW_cut]>0.0: 3688 PY8_Card.MadGraphSet('Merging:TMS',self.run_card[CKKW_cut], force=True) 3689 else: 3690 raise self.InvalidCmd('When running CKKWl merging, the user'+\ 3691 " select a '%s' cut larger than 0.0 in the run_card."%CKKW_cut) 3692 if PY8_Card['Merging:TMS']<self.run_card[CKKW_cut]: 3693 logger.error( 3694 'The CKKWl merging scale you chose (%f) is less than '%PY8_Card['Merging:TMS']+ 3695 'the %s cut specified in the run_card parameter (=%f).\n'%(CKKW_cut,self.run_card[CKKW_cut])+ 3696 'It is incorrect to use a smaller CKKWl scale than the generation-level %s cut!'%CKKW_cut) 3697 3698 PY8_Card.MadGraphSet('TimeShower:pTmaxMatch',1) 3699 PY8_Card.MadGraphSet('SpaceShower:pTmaxMatch',1) 3700 PY8_Card.MadGraphSet('SpaceShower:rapidityOrder',False) 3701 # PY8 should not implement the CKKW veto since the driver should do it. 3702 if self.run_card['use_syst']: 3703 # We do no force it here, but it is clear that the user should know what 3704 # he's doing if he were to force it to True. 3705 PY8_Card.MadGraphSet('Merging:applyVeto',False) 3706 PY8_Card.MadGraphSet('Merging:includeWeightInXsection',False) 3707 # Use the parameter maxjetflavor for Merging:nQuarksMerge which specifies 3708 # up to which parton must be matched. 3709 PY8_Card.MadGraphSet('Merging:nQuarksMerge',self.run_card['maxjetflavor']) 3710 if not hasattr(self,'proc_characteristic'): 3711 self.proc_characteristic = self.get_characteristics() 3712 nJetMax = self.proc_characteristic['max_n_matched_jets'] 3713 if PY8_Card['Merging:nJetMax'.lower()] == -1: 3714 logger.info("No user-defined value for Pythia8 parameter "+ 3715 "'Merging:nJetMax'. Setting it automatically to %d."%nJetMax) 3716 PY8_Card.MadGraphSet('Merging:nJetMax',nJetMax, force=True) 3717 if PY8_Card['SysCalc:tmsList']=='auto': 3718 if self.run_card['use_syst']: 3719 if self.run_card['sys_matchscale']=='auto': 3720 tms = PY8_Card["Merging:TMS"] 3721 value = [factor*tms for factor in [0.5,0.75,1.0,1.5,2.0] 3722 if factor*tms > self.run_card[CKKW_cut]] 3723 PY8_Card.MadGraphSet('SysCalc:tmsList', value, force=True) 3724 else: 3725 tmsList = [float(tms) for tms in self.run_card['sys_matchscale'].split()] 3726 if PY8_Card['Merging:TMS'] not in tmsList: 3727 tmsList.append(PY8_Card['Merging:TMS']) 3728 PY8_Card.MadGraphSet('SysCalc:tmsList', tmsList, force=True) 3729 3730 for scale in PY8_Card['SysCalc:tmsList']: 3731 if scale<self.run_card[CKKW_cut]: 3732 logger.error( 3733 'One of the CKKWl merging scale you chose (%f) in the variation list'%scale+\ 3734 " (either via 'SysCalc:tmsList' in the PY8 shower card or "+\ 3735 "'sys_matchscale' in the run_card) is less than %f, "%self.run_card[CKKW_cut]+ 3736 'the %s cut specified in the run_card parameter.\n'%CKKW_cut+ 3737 'It is incorrect to use a smaller CKKWl scale than the generation-level %s cut!'%CKKW_cut) 3738 else: 3739 # When not performing any merging, make sure that we do not write out the parameter 3740 # JetMatching:xxx or Merging:xxx as this can trigger undesired vetos in an unmerged 3741 # simulation. 3742 PY8_Card.vetoParamWriteOut('Merging:TMS') 3743 PY8_Card.vetoParamWriteOut('Merging:Process') 3744 PY8_Card.vetoParamWriteOut('Merging:nJetMax') 3745 PY8_Card.vetoParamWriteOut('JetMatching:qCut') 3746 PY8_Card.vetoParamWriteOut('JetMatching:doShowerKt') 3747 PY8_Card.vetoParamWriteOut('JetMatching:nJetMax') 3748 3749 return HepMC_event_output
3750
3751 - def do_pythia8(self, line):
3752 """launch pythia8""" 3753 3754 3755 try: 3756 import madgraph 3757 except ImportError: 3758 import internal.histograms as histograms 3759 else: 3760 import madgraph.various.histograms as histograms 3761 3762 # Check argument's validity 3763 args = self.split_arg(line) 3764 if '--no_default' in args: 3765 if not os.path.exists(pjoin(self.me_dir, 'Cards', 'pythia8_card.dat')): 3766 return 3767 no_default = True 3768 args.remove('--no_default') 3769 else: 3770 no_default = False 3771 3772 if not self.run_name: 3773 self.check_pythia8(args) 3774 self.configure_directory(html_opening =False) 3775 else: 3776 # initialize / remove lhapdf mode 3777 self.configure_directory(html_opening =False) 3778 self.check_pythia8(args) 3779 3780 # the args are modify and the last arg is always the mode 3781 if not no_default: 3782 self.ask_pythia_run_configuration(args[-1], pythia_version=8) 3783 3784 if self.options['automatic_html_opening']: 3785 misc.open_file(os.path.join(self.me_dir, 'crossx.html')) 3786 self.options['automatic_html_opening'] = False 3787 3788 if self.run_card['event_norm'] not in ['unit','average']: 3789 logger.critical("Pythia8 does not support normalization to the sum. Not running Pythia8") 3790 return 3791 #\n"+\ 3792 #"The normalisation of the hepmc output file will be wrong (i.e. non-standard).\n"+\ 3793 #"Please use 'event_norm = average' in the run_card to avoid this problem.") 3794 3795 # Update the banner with the pythia card 3796 if not self.banner or len(self.banner) <=1: 3797 # Here the level keyword 'pythia' must not be changed to 'pythia8'. 3798 self.banner = banner_mod.recover_banner(self.results, 'pythia') 3799 3800 if not self.options['mg5amc_py8_interface_path'] or not \ 3801 os.path.exists(pjoin(self.options['mg5amc_py8_interface_path'], 3802 'MG5aMC_PY8_interface')): 3803 raise self.InvalidCmd( 3804 """The MG5aMC_PY8_interface tool cannot be found, so that MadEvent cannot steer Pythia8 shower. 3805 Please install this tool with the following MG5_aMC command: 3806 MG5_aMC> install mg5amc_py8_interface_path""") 3807 else: 3808 pythia_main = pjoin(self.options['mg5amc_py8_interface_path'], 3809 'MG5aMC_PY8_interface') 3810 warnings = MadEventCmd.mg5amc_py8_interface_consistency_warning(self.options) 3811 if warnings: 3812 logger.warning(warnings) 3813 3814 self.results.add_detail('run_mode', 'madevent') 3815 3816 # Again here 'pythia' is just a keyword for the simulation level. 3817 self.update_status('\033[92mRunning Pythia8 [arXiv:1410.3012]\033[0m', 'pythia8') 3818 3819 tag = self.run_tag 3820 # Now write Pythia8 card 3821 # Start by reading, starting from the default one so that the 'user_set' 3822 # tag are correctly set. 3823 PY8_Card = banner_mod.PY8Card(pjoin(self.me_dir, 'Cards', 3824 'pythia8_card_default.dat')) 3825 PY8_Card.read(pjoin(self.me_dir, 'Cards', 'pythia8_card.dat'), 3826 setter='user') 3827 3828 run_type = 'default' 3829 merged_run_types = ['MLM','CKKW'] 3830 if int(self.run_card['ickkw'])==1: 3831 run_type = 'MLM' 3832 elif int(self.run_card['ickkw'])==2 or \ 3833 self.run_card['ktdurham']>0.0 or self.run_card['ptlund']>0.0: 3834 run_type = 'CKKW' 3835 3836 # Edit the card and run environment according to the run specification 3837 HepMC_event_output = self.setup_Pythia8RunAndCard(PY8_Card, run_type) 3838 3839 # Now write the card. 3840 pythia_cmd_card = pjoin(self.me_dir, 'Events', self.run_name , 3841 '%s_pythia8.cmd' % tag) 3842 cmd_card = StringIO.StringIO() 3843 PY8_Card.write(cmd_card,pjoin(self.me_dir,'Cards','pythia8_card_default.dat'), 3844 direct_pythia_input=True) 3845 3846 # Now setup the preamble to make sure that everything will use the locally 3847 # installed tools (if present) even if the user did not add it to its 3848 # environment variables. 3849 if 'heptools_install_dir' in self.options: 3850 preamble = misc.get_HEPTools_location_setter( 3851 self.options['heptools_install_dir'],'lib') 3852 else: 3853 if MADEVENT: 3854 preamble = misc.get_HEPTools_location_setter( 3855 pjoin(self.options['mg5amc_py8_interface_path'],os.pardir),'lib') 3856 else: 3857 preamble = misc.get_HEPTools_location_setter( 3858 pjoin(MG5DIR,'HEPTools'),'lib') 3859 3860 open(pythia_cmd_card,'w').write("""! 3861 ! It is possible to run this card manually with: 3862 ! %s %s 3863 ! 3864 """%(preamble+pythia_main,os.path.basename(pythia_cmd_card))+cmd_card.getvalue()) 3865 3866 # launch pythia8 3867 pythia_log = pjoin(self.me_dir , 'Events', self.run_name , 3868 '%s_pythia8.log' % tag) 3869 3870 # Write a bash wrapper to run the shower with custom environment variables 3871 wrapper_path = pjoin(self.me_dir,'Events',self.run_name,'run_shower.sh') 3872 wrapper = open(wrapper_path,'w') 3873 shell = 'bash' if misc.get_shell_type() in ['bash',None] else 'tcsh' 3874 shell_exe = None 3875 if os.path.exists('/usr/bin/env'): 3876 shell_exe = '/usr/bin/env %s'%shell 3877 else: 3878 shell_exe = misc.which(shell) 3879 if not shell_exe: 3880 self.InvalidCmd('No s hell could be found in your environment.\n'+ 3881 "Make sure that either '%s' is in your path or that the"%shell+\ 3882 " command '/usr/bin/env %s' exists and returns a valid path."%shell) 3883 3884 exe_cmd = "#!%s\n%s"%(shell_exe,' '.join( 3885 [preamble+pythia_main, 3886 os.path.basename(pythia_cmd_card)])) 3887 3888 wrapper.write(exe_cmd) 3889 wrapper.close() 3890 3891 # Set it as executable 3892 st = os.stat(wrapper_path) 3893 os.chmod(wrapper_path, st.st_mode | stat.S_IEXEC) 3894 3895 # If the target HEPMC output file is a fifo, don't hang MG5_aMC and let 3896 # it proceed. 3897 is_HepMC_output_fifo = False if not HepMC_event_output else \ 3898 ( os.path.exists(HepMC_event_output) and \ 3899 stat.S_ISFIFO(os.stat(HepMC_event_output).st_mode)) 3900 startPY8timer = time.time() 3901 3902 # Information that will be extracted from this PY8 run 3903 PY8_extracted_information={ 'sigma_m':None, 'Nacc':None, 'Ntry':None, 3904 'cross_sections':{} } 3905 3906 if is_HepMC_output_fifo: 3907 logger.info( 3908 """Pythia8 is set to output HEPMC events to to a fifo file. 3909 You can follow PY8 run with the following command (in a separate terminal): 3910 tail -f %s"""%pythia_log ) 3911 py8_log = open( pythia_log,'w') 3912 py8_bkgrd_proc = misc.Popen([wrapper_path], 3913 stdout=py8_log,stderr=py8_log, 3914 cwd=pjoin(self.me_dir,'Events',self.run_name)) 3915 # Now directly return to madevent interactive interface if we are piping PY8 3916 if not no_default: 3917 logger.info('You can now run a tool that reads the following fifo file:'+\ 3918 '\n %s\nwhere PY8 outputs HEPMC events (e.g. MadAnalysis5).' 3919 %HepMC_event_output,'$MG:color:GREEN') 3920 return 3921 else: 3922 if self.options ['run_mode']!=0: 3923 # Start a parallelization instance (stored in self.cluster) 3924 self.configure_run_mode(self.options['run_mode']) 3925 if self.options['run_mode']==1: 3926 n_cores = max(self.options['cluster_size'],1) 3927 elif self.options['run_mode']==2: 3928 n_cores = max(self.cluster.nb_core,1) 3929 3930 lhe_file_name = os.path.basename(PY8_Card.subruns[0]['Beams:LHEF']) 3931 lhe_file = lhe_parser.EventFile(pjoin(self.me_dir,'Events', 3932 self.run_name,PY8_Card.subruns[0]['Beams:LHEF'])) 3933 n_available_events = len(lhe_file) 3934 if PY8_Card['Main:numberOfEvents']==-1: 3935 n_events = n_available_events 3936 else: 3937 n_events = PY8_Card['Main:numberOfEvents'] 3938 if n_events > n_available_events: 3939 raise self.InvalidCmd, 'You specified more events (%d) in the PY8 parameter'%n_events+\ 3940 "'Main:numberOfEvents' than the total number of events available (%d)"%n_available_events+\ 3941 ' in the event file:\n %s'%pjoin(self.me_dir,'Events',self.run_name,PY8_Card.subruns[0]['Beams:LHEF']) 3942 3943 # Implement a security to insure a minimum numbe of events per job 3944 if self.options['run_mode']==2: 3945 min_n_events_per_job = 100 3946 elif self.options['run_mode']==1: 3947 min_n_events_per_job = 1000 3948 min_n_core = n_events//min_n_events_per_job 3949 n_cores = max(min(min_n_core,n_cores),1) 3950 3951 if self.options['run_mode']==0 or (self.options['run_mode']==2 and self.options['nb_core']==1): 3952 # No need for parallelization anymore 3953 self.cluster = None 3954 logger.info('Follow Pythia8 shower by running the '+ 3955 'following command (in a separate terminal):\n tail -f %s'%pythia_log) 3956 3957 if self.options['run_mode']==2 and self.options['nb_core']>1: 3958 ret_code = self.cluster.launch_and_wait(wrapper_path, 3959 argument= [], stdout= pythia_log, stderr=subprocess.STDOUT, 3960 cwd=pjoin(self.me_dir,'Events',self.run_name)) 3961 else: 3962 ret_code = misc.call(wrapper_path, stdout=open(pythia_log,'w'), stderr=subprocess.STDOUT, 3963 cwd=pjoin(self.me_dir,'Events',self.run_name)) 3964 if ret_code != 0: 3965 raise self.InvalidCmd, 'Pythia8 shower interrupted with return'+\ 3966 ' code %d.\n'%ret_code+\ 3967 'You can find more information in this log file:\n%s'%pythia_log 3968 else: 3969 if self.run_card['event_norm']=='sum': 3970 logger.error("") 3971 logger.error("Either run in single core or change event_norm to 'average'.") 3972 raise InvalidCmd("Pythia8 parallelization with event_norm set to 'sum' is not supported." 3973 "Either run in single core or change event_norm to 'average'.") 3974 3975 # Create the parallelization folder 3976 parallelization_dir = pjoin(self.me_dir,'Events',self.run_name,'PY8_parallelization') 3977 if os.path.isdir(parallelization_dir): 3978 shutil.rmtree(parallelization_dir) 3979 os.mkdir(parallelization_dir) 3980 # Copy what should be the now standalone executable for PY8 3981 shutil.copy(pythia_main,parallelization_dir) 3982 # Add a safe card in parallelization 3983 ParallelPY8Card = copy.copy(PY8_Card) 3984 # Normalize the name of the HEPMCouput and lhe input 3985 if HepMC_event_output: 3986 ParallelPY8Card['HEPMCoutput:file']='events.hepmc' 3987 else: 3988 ParallelPY8Card['HEPMCoutput:file']='/dev/null' 3989 3990 ParallelPY8Card.subruns[0].systemSet('Beams:LHEF','events.lhe.gz') 3991 ParallelPY8Card.write(pjoin(parallelization_dir,'PY8Card.dat'), 3992 pjoin(self.me_dir,'Cards','pythia8_card_default.dat'), 3993 direct_pythia_input=True) 3994 # Write the wrapper 3995 wrapper_path = pjoin(parallelization_dir,'run_PY8.sh') 3996 wrapper = open(wrapper_path,'w') 3997 if self.options['cluster_temp_path'] is None: 3998 exe_cmd = \ 3999 """#!%s 4000 ./%s PY8Card.dat >& PY8_log.txt 4001 """ 4002 else: 4003 exe_cmd = \ 4004 """#!%s 4005 ln -s ./events_$1.lhe.gz ./events.lhe.gz 4006 ./%s PY8Card_$1.dat >& PY8_log.txt 4007 mkdir split_$1 4008 if [ -f ./events.hepmc ]; 4009 then 4010 mv ./events.hepmc ./split_$1/ 4011 fi 4012 if [ -f ./pts.dat ]; 4013 then 4014 mv ./pts.dat ./split_$1/ 4015 fi 4016 if [ -f ./djrs.dat ]; 4017 then 4018 mv ./djrs.dat ./split_$1/ 4019 fi 4020 if [ -f ./PY8_log.txt ]; 4021 then 4022 mv ./PY8_log.txt ./split_$1/ 4023 fi 4024 tar -czf split_$1.tar.gz split_$1 4025 """ 4026 exe_cmd = exe_cmd%(shell_exe,os.path.basename(pythia_main)) 4027 wrapper.write(exe_cmd) 4028 wrapper.close() 4029 # Set it as executable 4030 st = os.stat(wrapper_path) 4031 os.chmod(wrapper_path, st.st_mode | stat.S_IEXEC) 4032 4033 # Split the .lhe event file, create event partition 4034 partition=[n_available_events//n_cores]*n_cores 4035 for i in range(n_available_events%n_cores): 4036 partition[i] += 1 4037 4038 # Splitting according to the total number of events requested by the user 4039 # Will be used to determine the number of events to indicate in the PY8 split cards. 4040 partition_for_PY8=[n_events//n_cores]*n_cores 4041 for i in range(n_events%n_cores): 4042 partition_for_PY8[i] += 1 4043 4044 logger.info('Splitting .lhe event file for PY8 parallelization...') 4045 n_splits = lhe_file.split(partition=partition, cwd=parallelization_dir, zip=True) 4046 4047 if n_splits!=len(partition): 4048 raise MadGraph5Error('Error during lhe file splitting. Expected %d files but obtained %d.' 4049 %(len(partition),n_splits)) 4050 # Distribute the split events 4051 split_files = [] 4052 split_dirs = [] 4053 for split_id in range(n_splits): 4054 split_files.append('events_%s.lhe.gz'%split_id) 4055 split_dirs.append(pjoin(parallelization_dir,'split_%d'%split_id)) 4056 # Add the necessary run content 4057 shutil.move(pjoin(parallelization_dir,lhe_file.name+'_%d.lhe.gz'%split_id), 4058 pjoin(parallelization_dir,split_files[-1])) 4059 4060 logger.info('Submitting Pythia8 jobs...') 4061 for i, split_file in enumerate(split_files): 4062 # We must write a PY8Card tailored for each split so as to correct the normalization 4063 # HEPMCoutput:scaling of each weight since the lhe showered will not longer contain the 4064 # same original number of events 4065 split_PY8_Card = banner_mod.PY8Card(pjoin(parallelization_dir,'PY8Card.dat')) 4066 # Make sure to sure the number of split_events determined during the splitting. 4067 split_PY8_Card.systemSet('Main:numberOfEvents',partition_for_PY8[i]) 4068 split_PY8_Card.systemSet('HEPMCoutput:scaling',split_PY8_Card['HEPMCoutput:scaling']* 4069 (float(partition_for_PY8[i])/float(n_events))) 4070 # Add_missing set to False so as to be sure not to add any additional parameter w.r.t 4071 # the ones in the original PY8 param_card copied. 4072 split_PY8_Card.write(pjoin(parallelization_dir,'PY8Card_%d.dat'%i), 4073 pjoin(parallelization_dir,'PY8Card.dat'), add_missing=False) 4074 in_files = [pjoin(parallelization_dir,os.path.basename(pythia_main)), 4075 pjoin(parallelization_dir,'PY8Card_%d.dat'%i), 4076 pjoin(parallelization_dir,split_file)] 4077 if self.options['cluster_temp_path'] is None: 4078 out_files = [] 4079 os.mkdir(pjoin(parallelization_dir,'split_%d'%i)) 4080 selected_cwd = pjoin(parallelization_dir,'split_%d'%i) 4081 for in_file in in_files+[pjoin(parallelization_dir,'run_PY8.sh')]: 4082 # Make sure to rename the split_file link from events_<x>.lhe.gz to events.lhe.gz 4083 # and similarly for PY8Card 4084 if os.path.basename(in_file)==split_file: 4085 ln(in_file,selected_cwd,name='events.lhe.gz') 4086 elif os.path.basename(in_file).startswith('PY8Card'): 4087 ln(in_file,selected_cwd,name='PY8Card.dat') 4088 else: 4089 ln(in_file,selected_cwd) 4090 in_files = [] 4091 else: 4092 out_files = ['split_%d.tar.gz'%i] 4093 selected_cwd = parallelization_dir 4094 self.cluster.submit2(wrapper_path, 4095 argument=[str(i)], cwd=selected_cwd, 4096 input_files=in_files, 4097 output_files=out_files, 4098 required_output=out_files) 4099 4100 def wait_monitoring(Idle, Running, Done): 4101 if Idle+Running+Done == 0: 4102 return 4103 logger.info('Pythia8 shower jobs: %d Idle, %d Running, %d Done [%s]'\ 4104 %(Idle, Running, Done, misc.format_time(time.time() - startPY8timer)))
4105 self.cluster.wait(parallelization_dir,wait_monitoring) 4106 4107 logger.info('Merging results from the split PY8 runs...') 4108 if self.options['cluster_temp_path']: 4109 # Decompressing the output 4110 for i, split_file in enumerate(split_files): 4111 misc.call(['tar','-xzf','split_%d.tar.gz'%i],cwd=parallelization_dir) 4112 os.remove(pjoin(parallelization_dir,'split_%d.tar.gz'%i)) 4113 4114 # Now merge logs 4115 pythia_log_file = open(pythia_log,'w') 4116 n_added = 0 4117 for split_dir in split_dirs: 4118 log_file = pjoin(split_dir,'PY8_log.txt') 4119 pythia_log_file.write('='*35+'\n') 4120 pythia_log_file.write(' -> Pythia8 log file for run %d <-'%i+'\n') 4121 pythia_log_file.write('='*35+'\n') 4122 pythia_log_file.write(open(log_file,'r').read()+'\n') 4123 if run_type in merged_run_types: 4124 sigma_m, Nacc, Ntry = self.parse_PY8_log_file(log_file) 4125 if any(elem is None for elem in [sigma_m, Nacc, Ntry]): 4126 continue 4127 n_added += 1 4128 if PY8_extracted_information['sigma_m'] is None: 4129 PY8_extracted_information['sigma_m'] = sigma_m 4130 else: 4131 PY8_extracted_information['sigma_m'] += sigma_m 4132 if PY8_extracted_information['Nacc'] is None: 4133 PY8_extracted_information['Nacc'] = Nacc 4134 else: 4135 PY8_extracted_information['Nacc'] += Nacc 4136 if PY8_extracted_information['Ntry'] is None: 4137 PY8_extracted_information['Ntry'] = Ntry 4138 else: 4139 PY8_extracted_information['Ntry'] += Ntry 4140 4141 # Normalize the values added 4142 if n_added>0: 4143 PY8_extracted_information['sigma_m'] /= float(n_added) 4144 pythia_log_file.close() 4145 4146 # djr plots 4147 djr_HwU = None 4148 n_added = 0 4149 for split_dir in split_dirs: 4150 djr_file = pjoin(split_dir,'djrs.dat') 4151 if not os.path.isfile(djr_file): 4152 continue 4153 xsecs = self.extract_cross_sections_from_DJR(djr_file) 4154 if len(xsecs)>0: 4155 n_added += 1 4156 if len(PY8_extracted_information['cross_sections'])==0: 4157 PY8_extracted_information['cross_sections'] = xsecs 4158 # Square the error term 4159 for key in PY8_extracted_information['cross_sections']: 4160 PY8_extracted_information['cross_sections'][key][1] = \ 4161 PY8_extracted_information['cross_sections'][key][1]**2 4162 else: 4163 for key, value in xsecs.items(): 4164 PY8_extracted_information['cross_sections'][key][0] += value[0] 4165 # Add error in quadrature 4166 PY8_extracted_information['cross_sections'][key][1] += value[1]**2 4167 new_djr_HwU = histograms.HwUList(djr_file,run_id=0) 4168 if djr_HwU is None: 4169 djr_HwU = new_djr_HwU 4170 else: 4171 for i, hist in enumerate(djr_HwU): 4172 djr_HwU[i] = hist + new_djr_HwU[i] 4173 4174 4175 if not djr_HwU is None: 4176 djr_HwU.output(pjoin(self.me_dir,'Events',self.run_name,'djrs'),format='HwU') 4177 shutil.move(pjoin(self.me_dir,'Events',self.run_name,'djrs.HwU'), 4178 pjoin(self.me_dir,'Events',self.run_name,'%s_djrs.dat'%tag)) 4179 4180 if n_added>0: 4181 for key in PY8_extracted_information['cross_sections']: 4182 # The cross-sections in the DJR are normalized for the original number of events, so we should not 4183 # divide by n_added anymore for the cross-section value 4184 # PY8_extracted_information['cross_sections'][key][0] /= float(n_added) 4185 PY8_extracted_information['cross_sections'][key][1] = \ 4186 math.sqrt(PY8_extracted_information['cross_sections'][key][1]) / float(n_added) 4187 4188 # pts plots 4189 pts_HwU = None 4190 for split_dir in split_dirs: 4191 pts_file = pjoin(split_dir,'pts.dat') 4192 if not os.path.isfile(pts_file): 4193 continue 4194 new_pts_HwU = histograms.HwUList(pts_file,run_id=0) 4195 if pts_HwU is None: 4196 pts_HwU = new_pts_HwU 4197 else: 4198 for i, hist in enumerate(pts_HwU): 4199 pts_HwU[i] = hist + new_pts_HwU[i] 4200 if not pts_HwU is None: 4201 pts_HwU.output(pjoin(self.me_dir,'Events',self.run_name,'pts'),format='HwU') 4202 shutil.move(pjoin(self.me_dir,'Events',self.run_name,'pts.HwU'), 4203 pjoin(self.me_dir,'Events',self.run_name,'%s_pts.dat'%tag)) 4204 4205 # HepMC events now. 4206 all_hepmc_files = [] 4207 for split_dir in split_dirs: 4208 hepmc_file = pjoin(split_dir,'events.hepmc') 4209 if not os.path.isfile(hepmc_file): 4210 continue 4211 all_hepmc_files.append(hepmc_file) 4212 4213 if len(all_hepmc_files)>0: 4214 hepmc_output = pjoin(self.me_dir,'Events',self.run_name,HepMC_event_output) 4215 with misc.TMP_directory() as tmp_dir: 4216 # Use system calls to quickly put these together 4217 header = open(pjoin(tmp_dir,'header.hepmc'),'w') 4218 n_head = 0 4219 for line in open(all_hepmc_files[0],'r'): 4220 if not line.startswith('E'): 4221 n_head += 1 4222 header.write(line) 4223 else: 4224 break 4225 header.close() 4226 tail = open(pjoin(tmp_dir,'tail.hepmc'),'w') 4227 n_tail = 0 4228 for line in misc.BackRead(all_hepmc_files[-1]): 4229 if line.startswith('HepMC::'): 4230 n_tail += 1 4231 tail.write(line) 4232 else: 4233 break 4234 tail.close() 4235 if n_tail>1: 4236 raise MadGraph5Error,'HEPMC files should only have one trailing command.' 4237 ###################################################################### 4238 # This is the most efficient way of putting together HEPMC's, *BUT* # 4239 # WARNING: NEED TO RENDER THE CODE BELOW SAFE TOWARDS INJECTION # 4240 ###################################################################### 4241 for hepmc_file in all_hepmc_files: 4242 # Remove in an efficient way the starting and trailing HEPMC tags 4243 if sys.platform == 'darwin': 4244 # sed on MAC has slightly different synthax than on 4245 os.system(' '.join(['sed','-i',"''","'%s;$d'"% 4246 (';'.join('%id'%(i+1) for i in range(n_head))),hepmc_file])) 4247 else: 4248 # other UNIX systems 4249 os.system(' '.join(['sed','-i']+["-e '%id'"%(i+1) for i in range(n_head)]+ 4250 ["-e '$d'",hepmc_file])) 4251 4252 os.system(' '.join(['cat',pjoin(tmp_dir,'header.hepmc')]+all_hepmc_files+ 4253 [pjoin(tmp_dir,'tail.hepmc'),'>',hepmc_output])) 4254 4255 # We are done with the parallelization directory. Clean it. 4256 if os.path.isdir(parallelization_dir): 4257 shutil.rmtree(parallelization_dir) 4258 4259 # Properly rename the djr and pts output if present. 4260 djr_output = pjoin(self.me_dir,'Events', self.run_name, 'djrs.dat') 4261 if os.path.isfile(djr_output): 4262 shutil.move(djr_output, pjoin(self.me_dir,'Events', 4263 self.run_name, '%s_djrs.dat' % tag)) 4264 pt_output = pjoin(self.me_dir,'Events', self.run_name, 'pts.dat') 4265 if os.path.isfile(pt_output): 4266 shutil.move(pt_output, pjoin(self.me_dir,'Events', 4267 self.run_name, '%s_pts.dat' % tag)) 4268 4269 if not os.path.isfile(pythia_log) or \ 4270 'Inclusive cross section:' not in '\n'.join(open(pythia_log,'r').readlines()[-20:]): 4271 logger.warning('Fail to produce a pythia8 output. More info in \n %s'%pythia_log) 4272 return 4273 4274 # Plot for Pythia8 4275 successful = self.create_plot('Pythia8') 4276 if not successful: 4277 logger.warning('Failed to produce Pythia8 merging plots.') 4278 4279 self.to_store.append('pythia8') 4280 4281 # Study matched cross-sections 4282 if run_type in merged_run_types: 4283 # From the log file 4284 if all(PY8_extracted_information[_] is None for _ in ['sigma_m','Nacc','Ntry']): 4285 # When parallelization is enable we shouldn't have cannot look in the log in this way 4286 if self.options ['run_mode']!=0: 4287 logger.warning('Pythia8 cross-section could not be retreived.\n'+ 4288 'Try turning parallelization off by setting the option nb_core to 1.') 4289 else: 4290 PY8_extracted_information['sigma_m'],PY8_extracted_information['Nacc'],\ 4291 PY8_extracted_information['Ntry'] = self.parse_PY8_log_file( 4292 pjoin(self.me_dir,'Events', self.run_name,'%s_pythia8.log' % tag)) 4293 4294 if not any(PY8_extracted_information[_] is None for _ in ['sigma_m','Nacc','Ntry']): 4295 self.results.add_detail('cross_pythia', PY8_extracted_information['sigma_m']) 4296 self.results.add_detail('nb_event_pythia', PY8_extracted_information['Nacc']) 4297 # Shorthands 4298 Nacc = PY8_extracted_information['Nacc'] 4299 Ntry = PY8_extracted_information['Ntry'] 4300 sigma_m = PY8_extracted_information['sigma_m'] 4301 # Compute pythia error 4302 error = self.results[self.run_name].return_tag(self.run_tag)['error'] 4303 try: 4304 error_m = math.sqrt((error * Nacc/Ntry)**2 + sigma_m**2 *(1-Nacc/Ntry)/Nacc) 4305 except ZeroDivisionError: 4306 # Cannot compute error 4307 error_m = -1.0 4308 # works both for fixed number of generated events and fixed accepted events 4309 self.results.add_detail('error_pythia', error_m) 4310 4311 if self.run_card['use_syst']: 4312 self.results.add_detail('cross_pythia', -1) 4313 self.results.add_detail('error_pythia', 0) 4314 4315 # From the djr file generated 4316 djr_output = pjoin(self.me_dir,'Events',self.run_name,'%s_djrs.dat'%tag) 4317 if os.path.isfile(djr_output) and len(PY8_extracted_information['cross_sections'])==0: 4318 # When parallelization is enable we shouldn't have cannot look in the log in this way 4319 if self.options ['run_mode']!=0: 4320 logger.warning('Pythia8 merged cross-sections could not be retreived.\n'+ 4321 'Try turning parallelization off by setting the option nb_core to 1.') 4322 PY8_extracted_information['cross_sections'] = {} 4323 else: 4324 PY8_extracted_information['cross_sections'] = self.extract_cross_sections_from_DJR(djr_output) 4325 cross_sections = PY8_extracted_information['cross_sections'] 4326 if cross_sections: 4327 # Filter the cross_sections specified an keep only the ones 4328 # with central parameters and a different merging scale 4329 a_float_re = '[\+|-]?\d+(\.\d*)?([EeDd][\+|-]?\d+)?' 4330 central_merging_re = re.compile( 4331 '^\s*Weight_MERGING\s*=\s*(?P<merging>%s)\s*$'%a_float_re, 4332 re.IGNORECASE) 4333 cross_sections = dict( 4334 (float(central_merging_re.match(xsec).group('merging')),value) 4335 for xsec, value in cross_sections.items() if not 4336 central_merging_re.match(xsec) is None) 4337 central_scale = PY8_Card['JetMatching:qCut'] if \ 4338 int(self.run_card['ickkw'])==1 else PY8_Card['Merging:TMS'] 4339 if central_scale in cross_sections: 4340 self.results.add_detail('cross_pythia8', cross_sections[central_scale][0]) 4341 self.results.add_detail('error_pythia8', cross_sections[central_scale][1]) 4342 4343 #logger.info('Pythia8 merged cross-sections are:') 4344 #for scale in sorted(cross_sections.keys()): 4345 # logger.info(' > Merging scale = %-6.4g : %-11.5g +/- %-7.2g [pb]'%\ 4346 # (scale,cross_sections[scale][0],cross_sections[scale][1])) 4347 4348 xsecs_file = open(pjoin(self.me_dir,'Events',self.run_name, 4349 '%s_merged_xsecs.txt'%tag),'w') 4350 if cross_sections: 4351 xsecs_file.write('%-20s%-20s%-20s\n'%('Merging scale', 4352 'Cross-section [pb]','MC uncertainty [pb]')) 4353 for scale in sorted(cross_sections.keys()): 4354 xsecs_file.write('%-20.4g%-20.6e%-20.2e\n'% 4355 (scale,cross_sections[scale][0],cross_sections[scale][1])) 4356 else: 4357 xsecs_file.write('Cross-sections could not be read from the'+\ 4358 "XML node 'xsection' of the .dat file produced by Pythia8.") 4359 xsecs_file.close() 4360 4361 #Update the banner 4362 # We add directly the pythia command card because it has the full 4363 # information 4364 self.banner.add(pythia_cmd_card) 4365 4366 if int(self.run_card['ickkw']): 4367 # Add the matched cross-section 4368 if 'MGGenerationInfo' in self.banner: 4369 self.banner['MGGenerationInfo'] += '# Matched Integrated weight (pb) : %s\n' % self.results.current['cross_pythia'] 4370 else: 4371 self.banner['MGGenerationInfo'] = '# Matched Integrated weight (pb) : %s\n' % self.results.current['cross_pythia'] 4372 banner_path = pjoin(self.me_dir, 'Events', self.run_name, '%s_%s_banner.txt' % (self.run_name, tag)) 4373 self.banner.write(banner_path) 4374 4375 self.update_status('Pythia8 shower finished after %s.'%misc.format_time(time.time() - startPY8timer), level='pythia8') 4376 if self.options['delphes_path']: 4377 self.exec_cmd('delphes --no_default', postcmd=False, printcmd=False) 4378 self.print_results_in_shell(self.results.current) 4379
4380 - def parse_PY8_log_file(self, log_file_path):
4381 """ Parse a log file to extract number of event and cross-section. """ 4382 pythiare = re.compile("Les Houches User Process\(es\)\s*\d+\s*\|\s*(?P<tried>\d+)\s*(?P<selected>\d+)\s*(?P<generated>\d+)\s*\|\s*(?P<xsec>[\d\.e\-\+]+)\s*(?P<xsec_error>[\d\.e\-\+]+)") 4383 pythia_xsec_re = re.compile("Inclusive cross section\s*:\s*(?P<xsec>[\d\.e\-\+]+)\s*(?P<xsec_error>[\d\.e\-\+]+)") 4384 sigma_m, Nacc, Ntry = None, None, None 4385 for line in misc.BackRead(log_file_path): 4386 info = pythiare.search(line) 4387 if not info: 4388 # Also try to obtain the cross-section and error from the final xsec line of pythia8 log 4389 # which is more reliable, in general for example when there is merging and the last event 4390 # is skipped. 4391 final_PY8_xsec = pythia_xsec_re.search(line) 4392 if not final_PY8_xsec: 4393 continue 4394 else: 4395 sigma_m = float(final_PY8_xsec.group('xsec')) *1e9 4396 continue 4397 else: 4398 try: 4399 # Pythia cross section in mb, we want pb 4400 if sigma_m is None: 4401 sigma_m = float(info.group('xsec')) *1e9 4402 if Nacc is None: 4403 Nacc = int(info.group('generated')) 4404 if Ntry is None: 4405 Ntry = int(info.group('tried')) 4406 if Nacc==0: 4407 raise self.InvalidCmd, 'Pythia8 shower failed since it'+\ 4408 ' did not accept any event from the MG5aMC event file.' 4409 return sigma_m, Nacc, Ntry 4410 except ValueError: 4411 return None,None,None 4412 4413 raise self.InvalidCmd, "Could not find cross-section and event number information "+\ 4414 "in Pythia8 log\n '%s'."%log_file_path
4415
4416 - def extract_cross_sections_from_DJR(self,djr_output):
4417 """Extract cross-sections from a djr XML output.""" 4418 import xml.dom.minidom as minidom 4419 run_nodes = minidom.parse(djr_output).getElementsByTagName("run") 4420 all_nodes = dict((int(node.getAttribute('id')),node) for 4421 node in run_nodes) 4422 try: 4423 selected_run_node = all_nodes[0] 4424 except: 4425 return {} 4426 xsections = selected_run_node.getElementsByTagName("xsection") 4427 # In the DJR, the conversion to pb is already performed 4428 return dict((xsec.getAttribute('name'), 4429 [float(xsec.childNodes[0].data.split()[0]), 4430 float(xsec.childNodes[0].data.split()[1])]) 4431 for xsec in xsections)
4432
4433 - def do_pythia(self, line):
4434 """launch pythia""" 4435 4436 4437 # Check argument's validity 4438 args = self.split_arg(line) 4439 if '--no_default' in args: 4440 if not os.path.exists(pjoin(self.me_dir, 'Cards', 'pythia_card.dat')): 4441 return 4442 no_default = True 4443 args.remove('--no_default') 4444 else: 4445 no_default = False 4446 4447 if not self.run_name: 4448 self.check_pythia(args) 4449 self.configure_directory(html_opening =False) 4450 else: 4451 # initialize / remove lhapdf mode 4452 self.configure_directory(html_opening =False) 4453 self.check_pythia(args) 4454 4455 if self.run_card['event_norm'] != 'sum': 4456 logger.error('pythia-pgs require event_norm to be on sum. Do not run pythia6') 4457 return 4458 4459 # the args are modify and the last arg is always the mode 4460 if not no_default: 4461 self.ask_pythia_run_configuration(args[-1]) 4462 if self.options['automatic_html_opening']: 4463 misc.open_file(os.path.join(self.me_dir, 'crossx.html')) 4464 self.options['automatic_html_opening'] = False 4465 4466 # Update the banner with the pythia card 4467 if not self.banner or len(self.banner) <=1: 4468 self.banner = banner_mod.recover_banner(self.results, 'pythia') 4469 4470 pythia_src = pjoin(self.options['pythia-pgs_path'],'src') 4471 4472 self.results.add_detail('run_mode', 'madevent') 4473 4474 self.update_status('Running Pythia', 'pythia') 4475 try: 4476 os.remove(pjoin(self.me_dir,'Events','pythia.done')) 4477 except Exception: 4478 pass 4479 4480 ## LAUNCHING PYTHIA 4481 # check that LHAPATH is define. 4482 if not re.search(r'^\s*LHAPATH=%s/PDFsets' % pythia_src, 4483 open(pjoin(self.me_dir,'Cards','pythia_card.dat')).read(), 4484 re.M): 4485 f = open(pjoin(self.me_dir,'Cards','pythia_card.dat'),'a') 4486 f.write('\n LHAPATH=%s/PDFsets' % pythia_src) 4487 f.close() 4488 tag = self.run_tag 4489 pythia_log = pjoin(self.me_dir, 'Events', self.run_name , '%s_pythia.log' % tag) 4490 #self.cluster.launch_and_wait('../bin/internal/run_pythia', 4491 # argument= [pythia_src], stdout= pythia_log, 4492 # stderr=subprocess.STDOUT, 4493 # cwd=pjoin(self.me_dir,'Events')) 4494 output_files = ['pythia_events.hep'] 4495 if self.run_card['use_syst']: 4496 output_files.append('syst.dat') 4497 if self.run_card['ickkw'] == 1: 4498 output_files += ['beforeveto.tree', 'xsecs.tree', 'events.tree'] 4499 4500 os.environ['PDG_MASS_TBL'] = pjoin(pythia_src,'mass_width_2004.mc') 4501 self.cluster.launch_and_wait(pjoin(pythia_src, 'pythia'), 4502 input_files=[pjoin(self.me_dir, "Events", "unweighted_events.lhe"), 4503 pjoin(self.me_dir,'Cards','pythia_card.dat'), 4504 pjoin(pythia_src,'mass_width_2004.mc')], 4505 output_files=output_files, 4506 stdout= pythia_log, 4507 stderr=subprocess.STDOUT, 4508 cwd=pjoin(self.me_dir,'Events')) 4509 4510 4511 os.remove(pjoin(self.me_dir, "Events", "unweighted_events.lhe")) 4512 4513 if not os.path.exists(pjoin(self.me_dir,'Events','pythia_events.hep')): 4514 logger.warning('Fail to produce pythia output. More info in \n %s' % pythia_log) 4515 return 4516 4517 self.to_store.append('pythia') 4518 4519 # Find the matched cross-section 4520 if int(self.run_card['ickkw']): 4521 # read the line from the bottom of the file 4522 pythia_log = misc.BackRead(pjoin(self.me_dir,'Events', self.run_name, 4523 '%s_pythia.log' % tag)) 4524 pythiare = re.compile("\s*I\s+0 All included subprocesses\s+I\s+(?P<generated>\d+)\s+(?P<tried>\d+)\s+I\s+(?P<xsec>[\d\.D\-+]+)\s+I") 4525 for line in pythia_log: 4526 info = pythiare.search(line) 4527 if not info: 4528 continue 4529 try: 4530 # Pythia cross section in mb, we want pb 4531 sigma_m = float(info.group('xsec').replace('D','E')) *1e9 4532 Nacc = int(info.group('generated')) 4533 Ntry = int(info.group('tried')) 4534 except ValueError: 4535 # xsec is not float - this should not happen 4536 self.results.add_detail('cross_pythia', 0) 4537 self.results.add_detail('nb_event_pythia', 0) 4538 self.results.add_detail('error_pythia', 0) 4539 else: 4540 self.results.add_detail('cross_pythia', sigma_m) 4541 self.results.add_detail('nb_event_pythia', Nacc) 4542 #compute pythia error 4543 error = self.results[self.run_name].return_tag(self.run_tag)['error'] 4544 if Nacc: 4545 error_m = math.sqrt((error * Nacc/Ntry)**2 + sigma_m**2 *(1-Nacc/Ntry)/Nacc) 4546 else: 4547 error_m = 10000 * sigma_m 4548 # works both for fixed number of generated events and fixed accepted events 4549 self.results.add_detail('error_pythia', error_m) 4550 break 4551 4552 pythia_log.close() 4553 4554 pydir = pjoin(self.options['pythia-pgs_path'], 'src') 4555 eradir = self.options['exrootanalysis_path'] 4556 madir = self.options['madanalysis_path'] 4557 td = self.options['td_path'] 4558 4559 #Update the banner 4560 self.banner.add(pjoin(self.me_dir, 'Cards','pythia_card.dat')) 4561 if int(self.run_card['ickkw']): 4562 # Add the matched cross-section 4563 if 'MGGenerationInfo' in self.banner: 4564 self.banner['MGGenerationInfo'] += '# Matched Integrated weight (pb) : %s\n' % self.results.current['cross_pythia'] 4565 else: 4566 self.banner['MGGenerationInfo'] = '# Matched Integrated weight (pb) : %s\n' % self.results.current['cross_pythia'] 4567 banner_path = pjoin(self.me_dir, 'Events', self.run_name, '%s_%s_banner.txt' % (self.run_name, tag)) 4568 self.banner.write(banner_path) 4569 4570 # Creating LHE file 4571 self.run_hep2lhe(banner_path) 4572 4573 if int(self.run_card['ickkw']): 4574 misc.gzip(pjoin(self.me_dir,'Events','beforeveto.tree'), 4575 stdout=pjoin(self.me_dir,'Events',self.run_name, tag+'_pythia_beforeveto.tree.gz')) 4576 4577 4578 if self.run_card['use_syst'] in self.true: 4579 # Calculate syscalc info based on syst.dat 4580 try: 4581 self.run_syscalc('Pythia') 4582 except SysCalcError, error: 4583 logger.error(str(error)) 4584 else: 4585 if os.path.exists(pjoin(self.me_dir,'Events', 'syst.dat')): 4586 # Store syst.dat 4587 misc.gzip(pjoin(self.me_dir,'Events', 'syst.dat'), 4588 stdout=pjoin(self.me_dir,'Events',self.run_name, tag + '_pythia_syst.dat.gz')) 4589 4590 # Store syscalc.dat 4591 if os.path.exists(pjoin(self.me_dir, 'Events', 'syscalc.dat')): 4592 filename = pjoin(self.me_dir, 'Events' ,self.run_name, 4593 '%s_syscalc.dat' % self.run_tag) 4594 misc.gzip(pjoin(self.me_dir, 'Events','syscalc.dat'), 4595 stdout = "%s.gz" % filename) 4596 4597 # Plot for pythia 4598 self.create_plot('Pythia') 4599 4600 if os.path.exists(pjoin(self.me_dir,'Events','pythia_events.lhe')): 4601 misc.gzip(pjoin(self.me_dir,'Events','pythia_events.lhe'), 4602 stdout=pjoin(self.me_dir,'Events', self.run_name,'%s_pythia_events.lhe.gz' % tag)) 4603 4604 self.update_status('finish', level='pythia', makehtml=False) 4605 self.exec_cmd('pgs --no_default', postcmd=False, printcmd=False) 4606 if self.options['delphes_path']: 4607 self.exec_cmd('delphes --no_default', postcmd=False, printcmd=False) 4608 self.print_results_in_shell(self.results.current)
4609 4610 4611 ################################################################################
4612 - def do_remove(self, line):
4613 """Remove one/all run or only part of it""" 4614 4615 args = self.split_arg(line) 4616 run, tag, mode = self.check_remove(args) 4617 if 'banner' in mode: 4618 mode.append('all') 4619 4620 4621 if run == 'all': 4622 # Check first if they are not a run with a name run. 4623 if os.path.exists(pjoin(self.me_dir, 'Events', 'all')): 4624 logger.warning('A run with name all exists. So we will not supress all processes.') 4625 else: 4626 for match in misc.glob(pjoin('*','*_banner.txt'), pjoin(self.me_dir, 'Events')): 4627 run = match.rsplit(os.path.sep,2)[1] 4628 if self.force: 4629 args.append('-f') 4630 try: 4631 self.exec_cmd('remove %s %s' % (run, ' '.join(args[1:]) ) ) 4632 except self.InvalidCmd, error: 4633 logger.info(error) 4634 pass # run already clear 4635 return 4636 4637 # Check that run exists 4638 if not os.path.exists(pjoin(self.me_dir, 'Events', run)): 4639 raise self.InvalidCmd('No run \'%s\' detected' % run) 4640 4641 try: 4642 self.resuls.def_current(run) 4643 self.update_status(' Cleaning %s' % run, level=None) 4644 except Exception: 4645 misc.sprint('fail to update results or html status') 4646 pass # Just ensure that html never makes crash this function 4647 4648 4649 # Found the file to delete 4650 4651 to_delete = misc.glob('*', pjoin(self.me_dir, 'Events', run)) 4652 to_delete += misc.glob('*', pjoin(self.me_dir, 'HTML', run)) 4653 # forbid the banner to be removed 4654 to_delete = [os.path.basename(f) for f in to_delete if 'banner' not in f] 4655 if tag: 4656 to_delete = [f for f in to_delete if tag in f] 4657 if 'parton' in mode or 'all' in mode: 4658 try: 4659 if self.results[run][0]['tag'] != tag: 4660 raise Exception, 'dummy' 4661 except Exception: 4662 pass 4663 else: 4664 nb_rm = len(to_delete) 4665 if os.path.exists(pjoin(self.me_dir, 'Events', run, 'events.lhe.gz')): 4666 to_delete.append('events.lhe.gz') 4667 if os.path.exists(pjoin(self.me_dir, 'Events', run, 'unweighted_events.lhe.gz')): 4668 to_delete.append('unweighted_events.lhe.gz') 4669 if os.path.exists(pjoin(self.me_dir, 'HTML', run,'plots_parton.html')): 4670 to_delete.append(pjoin(self.me_dir, 'HTML', run,'plots_parton.html')) 4671 if nb_rm != len(to_delete): 4672 logger.warning('Be carefull that partonic information are on the point to be removed.') 4673 if 'all' in mode: 4674 pass # delete everything 4675 else: 4676 if 'pythia' not in mode: 4677 to_delete = [f for f in to_delete if 'pythia' not in f] 4678 if 'pgs' not in mode: 4679 to_delete = [f for f in to_delete if 'pgs' not in f] 4680 if 'delphes' not in mode: 4681 to_delete = [f for f in to_delete if 'delphes' not in f] 4682 if 'parton' not in mode: 4683 to_delete = [f for f in to_delete if 'delphes' in f 4684 or 'pgs' in f 4685 or 'pythia' in f] 4686 if not self.force and len(to_delete): 4687 question = 'Do you want to delete the following files?\n %s' % \ 4688 '\n '.join(to_delete) 4689 ans = self.ask(question, 'y', choices=['y','n']) 4690 else: 4691 ans = 'y' 4692 4693 if ans == 'y': 4694 for file2rm in to_delete: 4695 if os.path.exists(pjoin(self.me_dir, 'Events', run, file2rm)): 4696 try: 4697 os.remove(pjoin(self.me_dir, 'Events', run, file2rm)) 4698 except Exception: 4699 shutil.rmtree(pjoin(self.me_dir, 'Events', run, file2rm)) 4700 else: 4701 try: 4702 os.remove(pjoin(self.me_dir, 'HTML', run, file2rm)) 4703 except Exception: 4704 shutil.rmtree(pjoin(self.me_dir, 'HTML', run, file2rm)) 4705 4706 4707 4708 # Remove file in SubProcess directory 4709 if 'all' in mode or 'channel' in mode: 4710 try: 4711 if tag and self.results[run][0]['tag'] != tag: 4712 raise Exception, 'dummy' 4713 except Exception: 4714 pass 4715 else: 4716 to_delete = misc.glob('%s*' % run, pjoin(self.me_dir, 'SubProcesses')) 4717 to_delete += misc.glob(pjoin('*','%s*' % run), pjoin(self.me_dir, 'SubProcesses')) 4718 to_delete += misc.glob(pjoin('*','*','%s*' % run), pjoin(self.me_dir, 'SubProcesses')) 4719 4720 if self.force or len(to_delete) == 0: 4721 ans = 'y' 4722 else: 4723 question = 'Do you want to delete the following files?\n %s' % \ 4724 '\n '.join(to_delete) 4725 ans = self.ask(question, 'y', choices=['y','n']) 4726 4727 if ans == 'y': 4728 for file2rm in to_delete: 4729 os.remove(file2rm) 4730 4731 if 'banner' in mode: 4732 to_delete = misc.glob('*', pjoin(self.me_dir, 'Events', run)) 4733 if tag: 4734 # remove banner 4735 try: 4736 os.remove(pjoin(self.me_dir, 'Events',run,'%s_%s_banner.txt' % (run,tag))) 4737 except Exception: 4738 logger.warning('fail to remove the banner') 4739 # remove the run from the html output 4740 if run in self.results: 4741 self.results.delete_run(run, tag) 4742 return 4743 elif any(['banner' not in os.path.basename(p) for p in to_delete]): 4744 if to_delete: 4745 raise MadGraph5Error, '''Some output still exists for this run. 4746 Please remove those output first. Do for example: 4747 remove %s all banner 4748 ''' % run 4749 else: 4750 shutil.rmtree(pjoin(self.me_dir, 'Events',run)) 4751 if run in self.results: 4752 self.results.delete_run(run) 4753 return 4754 else: 4755 logger.info('''The banner is not removed. In order to remove it run: 4756 remove %s all banner %s''' % (run, tag and '--tag=%s ' % tag or '')) 4757 4758 # update database. 4759 self.results.clean(mode, run, tag) 4760 self.update_status('', level='all')
4761 4762 4763 4764 ############################################################################
4765 - def do_plot(self, line):
4766 """Create the plot for a given run""" 4767 4768 # Since in principle, all plot are already done automaticaly 4769 self.store_result() 4770 args = self.split_arg(line) 4771 # Check argument's validity 4772 self.check_plot(args) 4773 logger.info('plot for run %s' % self.run_name) 4774 if not self.force: 4775 self.ask_edit_cards([], args, plot=True) 4776 4777 if any([arg in ['all','parton'] for arg in args]): 4778 filename = pjoin(self.me_dir, 'Events', self.run_name, 'unweighted_events.lhe') 4779 if os.path.exists(filename+'.gz'): 4780 misc.gunzip('%s.gz' % filename, keep=True) 4781 if os.path.exists(filename): 4782 files.ln(filename, pjoin(self.me_dir, 'Events')) 4783 self.create_plot('parton') 4784 if not os.path.exists(filename+'.gz'): 4785 misc.gzip(pjoin(self.me_dir, 'Events', 'unweighted_events.lhe'), 4786 stdout= "%s.gz" % filename) 4787 else: 4788 try: 4789 os.remove(pjoin(self.me_dir, 'Events', 'unweighted_events.lhe')) 4790 os.remove(filename) 4791 except Exception: 4792 pass 4793 else: 4794 logger.info('No valid files for partonic plot') 4795 4796 if any([arg in ['all','pythia'] for arg in args]): 4797 filename = pjoin(self.me_dir, 'Events' ,self.run_name, 4798 '%s_pythia_events.lhe' % self.run_tag) 4799 if os.path.exists(filename+'.gz'): 4800 misc.gunzip("%s.gz" % filename) 4801 if os.path.exists(filename): 4802 shutil.move(filename, pjoin(self.me_dir, 'Events','pythia_events.lhe')) 4803 self.create_plot('Pythia') 4804 misc.gzip(pjoin(self.me_dir, 'Events','pythia_events.lhe'), 4805 stdout= "%s.gz" % filename) 4806 else: 4807 logger.info('No valid files for pythia plot') 4808 4809 4810 if any([arg in ['all','pgs'] for arg in args]): 4811 filename = pjoin(self.me_dir, 'Events', self.run_name, 4812 '%s_pgs_events.lhco' % self.run_tag) 4813 if os.path.exists(filename+'.gz'): 4814 misc.gunzip("%s.gz" % filename) 4815 if os.path.exists(filename): 4816 self.create_plot('PGS') 4817 misc.gzip(filename) 4818 else: 4819 logger.info('No valid files for pgs plot') 4820 4821 if any([arg in ['all','delphes'] for arg in args]): 4822 filename = pjoin(self.me_dir, 'Events', self.run_name, 4823 '%s_delphes_events.lhco' % self.run_tag) 4824 if os.path.exists(filename+'.gz'): 4825 misc.gunzip("%s.gz" % filename) 4826 if os.path.exists(filename): 4827 self.create_plot('Delphes') 4828 misc.gzip(filename) 4829 else: 4830 logger.info('No valid files for delphes plot')
4831 4832 ############################################################################
4833 - def do_syscalc(self, line):
4834 """Evaluate systematics variation weights for a given run""" 4835 4836 # Since in principle, all systematics run are already done automaticaly 4837 self.store_result() 4838 args = self.split_arg(line) 4839 # Check argument's validity 4840 self.check_syscalc(args) 4841 if self.ninitial == 1: 4842 logger.error('SysCalc can\'t be run for decay processes') 4843 return 4844 4845 logger.info('Calculating systematics for run %s' % self.run_name) 4846 4847 self.ask_edit_cards(['run_card'], args) 4848 self.run_card = banner_mod.RunCard(pjoin(self.me_dir, 'Cards', 'run_card.dat')) 4849 if any([arg in ['all','parton'] for arg in args]): 4850 filename = pjoin(self.me_dir, 'Events', self.run_name, 'unweighted_events.lhe') 4851 if os.path.exists(filename+'.gz'): 4852 misc.gunzip("%s.gz" % filename) 4853 if os.path.exists(filename): 4854 shutil.move(filename, pjoin(self.me_dir, 'Events', 'unweighted_events.lhe')) 4855 self.run_syscalc('parton') 4856 misc.gzip(pjoin(self.me_dir, 'Events', 'unweighted_events.lhe'), 4857 stdout="%s.gz" % filename) 4858 else: 4859 logger.info('No valid files for parton level systematics run.') 4860 4861 if any([arg in ['all','pythia'] for arg in args]): 4862 filename = pjoin(self.me_dir, 'Events' ,self.run_name, 4863 '%s_pythia_syst.dat' % self.run_tag) 4864 if os.path.exists(filename+'.gz'): 4865 misc.gunzip("%s.gz" % filename) 4866 if os.path.exists(filename): 4867 shutil.move(filename, pjoin(self.me_dir, 'Events','syst.dat')) 4868 try: 4869 self.run_syscalc('Pythia') 4870 except SysCalcError, error: 4871 logger.warning(str(error)) 4872 return 4873 misc.gzip(pjoin(self.me_dir, 'Events','syst.dat'), "%s.gz" % filename) 4874 filename = pjoin(self.me_dir, 'Events' ,self.run_name, 4875 '%s_syscalc.dat' % self.run_tag) 4876 misc.gzip(pjoin(self.me_dir, 'Events','syscalc.dat'), 4877 stdout=filename) 4878 else: 4879 logger.info('No valid files for pythia level')
4880 4881
4882 - def store_result(self):
4883 """ tar the pythia results. This is done when we are quite sure that 4884 the pythia output will not be use anymore """ 4885 4886 if not self.run_name: 4887 return 4888 4889 self.results.save() 4890 4891 4892 if not self.to_store: 4893 return 4894 4895 tag = self.run_card['run_tag'] 4896 self.update_status('storing files of previous run', level=None,\ 4897 error=True) 4898 if 'event' in self.to_store: 4899 if not os.path.exists(pjoin(self.me_dir, 'Events',self.run_name, 'unweighted_events.lhe.gz')) and\ 4900 os.path.exists(pjoin(self.me_dir, 'Events',self.run_name, 'unweighted_events.lhe')): 4901 logger.info("gzipping output file: unweighted_events.lhe") 4902 misc.gzip(pjoin(self.me_dir,'Events',self.run_name,"unweighted_events.lhe")) 4903 if os.path.exists(pjoin(self.me_dir,'Events','reweight.lhe')): 4904 os.remove(pjoin(self.me_dir,'Events', 'reweight.lhe')) 4905 4906 if 'pythia' in self.to_store: 4907 self.update_status('Storing Pythia files of previous run', level='pythia', error=True) 4908 4909 p = pjoin(self.me_dir,'Events') 4910 n = self.run_name 4911 t = tag 4912 self.to_store.remove('pythia') 4913 misc.gzip(pjoin(p,'pythia_events.hep'), 4914 stdout=pjoin(p, str(n),'%s_pythia_events.hep' % t)) 4915 4916 if 'pythia8' in self.to_store: 4917 p = pjoin(self.me_dir,'Events') 4918 n = self.run_name 4919 t = tag 4920 file_path = pjoin(p, n ,'%s_pythia8_events.hepmc'%t) 4921 self.to_store.remove('pythia8') 4922 if os.path.isfile(file_path): 4923 self.update_status('Storing Pythia8 files of previous run', 4924 level='pythia', error=True) 4925 misc.gzip(file_path,stdout=file_path) 4926 4927 self.update_status('Done', level='pythia',makehtml=False,error=True) 4928 4929 self.to_store = []
4930
4931 - def launch_job(self,exe, cwd=None, stdout=None, argument = [], remaining=0, 4932 run_type='', mode=None, **opt):
4933 """ """ 4934 argument = [str(arg) for arg in argument] 4935 if mode is None: 4936 mode = self.cluster_mode 4937 4938 # ensure that exe is executable 4939 if os.path.exists(exe) and not os.access(exe, os.X_OK): 4940 os.system('chmod +x %s ' % exe) 4941 elif (cwd and os.path.exists(pjoin(cwd, exe))) and not \ 4942 os.access(pjoin(cwd, exe), os.X_OK): 4943 os.system('chmod +x %s ' % pjoin(cwd, exe)) 4944 4945 if mode == 0: 4946 self.update_status((remaining, 1, 4947 self.total_jobs - remaining -1, run_type), level=None, force=False) 4948 start = time.time() 4949 #os.system('cd %s; ./%s' % (cwd,exe)) 4950 status = misc.call([exe] + argument, cwd=cwd, stdout=stdout, **opt) 4951 logger.info('%s run in %f s' % (exe, time.time() -start)) 4952 if status: 4953 raise MadGraph5Error, '%s didn\'t stop properly. Stop all computation' % exe 4954 4955 4956 elif mode in [1,2]: 4957 exename = os.path.basename(exe) 4958 # For condor cluster, create the input/output files 4959 if 'ajob' in exename: 4960 input_files = ['madevent','input_app.txt','symfact.dat','iproc.dat','dname.mg', 4961 pjoin(self.me_dir, 'SubProcesses','randinit')] 4962 if os.path.exists(pjoin(self.me_dir,'SubProcesses', 4963 'MadLoop5_resources.tar.gz')) and cluster.need_transfer(self.options): 4964 input_files.append(pjoin(self.me_dir,'SubProcesses', 'MadLoop5_resources.tar.gz')) 4965 4966 output_files = [] 4967 required_output = [] 4968 4969 4970 #Find the correct PDF input file 4971 input_files.append(self.get_pdf_input_filename()) 4972 4973 #Find the correct ajob 4974 Gre = re.compile("\s*j=(G[\d\.\w]+)") 4975 origre = re.compile("grid_directory=(G[\d\.\w]+)") 4976 try : 4977 fsock = open(exe) 4978 except Exception: 4979 fsock = open(pjoin(cwd,exe)) 4980 text = fsock.read() 4981 output_files = Gre.findall(text) 4982 if not output_files: 4983 Ire = re.compile("for i in ([\d\.\s]*) ; do") 4984 data = Ire.findall(text) 4985 data = ' '.join(data).split() 4986 for nb in data: 4987 output_files.append('G%s' % nb) 4988 required_output.append('G%s/results.dat' % nb) 4989 else: 4990 for G in output_files: 4991 if os.path.isdir(pjoin(cwd,G)): 4992 input_files.append(G) 4993 required_output.append('%s/results.dat' % G) 4994 4995 if origre.search(text): 4996 G_grid = origre.search(text).groups()[0] 4997 input_files.append(pjoin(G_grid, 'ftn26')) 4998 4999 #submitting 5000 self.cluster.submit2(exe, stdout=stdout, cwd=cwd, 5001 input_files=input_files, output_files=output_files, 5002 required_output=required_output) 5003 elif 'survey' in exename: 5004 input_files = ['madevent','input_app.txt','symfact.dat','iproc.dat', 'dname.mg', 5005 pjoin(self.me_dir, 'SubProcesses','randinit')] 5006 if os.path.exists(pjoin(self.me_dir,'SubProcesses', 5007 'MadLoop5_resources.tar.gz')) and cluster.need_transfer(self.options): 5008 input_files.append(pjoin(self.me_dir,'SubProcesses', 5009 'MadLoop5_resources.tar.gz')) 5010 5011 #Find the correct PDF input file 5012 input_files.append(self.get_pdf_input_filename()) 5013 5014 5015 output_files = [] 5016 required_output = [] 5017 5018 #Find the correct ajob 5019 suffix = "_%s" % int(float(argument[0])) 5020 if suffix == '_0': 5021 suffix = '' 5022 output_files = ['G%s%s' % (i, suffix) for i in argument[1:]] 5023 for G in output_files: 5024 required_output.append('%s/results.dat' % G) 5025 5026 # add the grid information if needed 5027 for G in output_files: 5028 if '.' in argument[0]: 5029 offset = int(str(argument[0]).split('.')[1]) 5030 else: 5031 offset = 0 5032 5033 if offset ==0 or offset == int(float(argument[0])): 5034 if os.path.exists(pjoin(cwd, G, 'input_app.txt')): 5035 os.remove(pjoin(cwd, G, 'input_app.txt')) 5036 5037 if os.path.exists(os.path.realpath(pjoin(cwd, G, 'ftn25'))): 5038 if offset == 0 or offset == int(float(argument[0])): 5039 os.remove(pjoin(cwd, G, 'ftn25')) 5040 continue 5041 else: 5042 input_files.append(pjoin(cwd, G, 'ftn25')) 5043 input_files.remove('input_app.txt') 5044 input_files.append(pjoin(cwd, G, 'input_app.txt')) 5045 elif os.path.lexists(pjoin(cwd, G, 'ftn25')): 5046 try: 5047 os.remove(pjoin(cwd,G,'ftn25')) 5048 except: 5049 pass 5050 5051 #submitting 5052 self.cluster.cluster_submit(exe, stdout=stdout, cwd=cwd, argument=argument, 5053 input_files=input_files, output_files=output_files, 5054 required_output=required_output, **opt) 5055 elif "refine_splitted.sh" in exename: 5056 input_files = ['madevent','symfact.dat','iproc.dat', 'dname.mg', 5057 pjoin(self.me_dir, 'SubProcesses','randinit')] 5058 5059 if os.path.exists(pjoin(self.me_dir,'SubProcesses', 5060 'MadLoop5_resources.tar.gz')) and cluster.need_transfer(self.options): 5061 input_files.append(pjoin(self.me_dir,'SubProcesses', 5062 'MadLoop5_resources.tar.gz')) 5063 5064 #Find the correct PDF input file 5065 input_files.append(self.get_pdf_input_filename()) 5066 5067 5068 output_files = [argument[0]] 5069 required_output = [] 5070 for G in output_files: 5071 required_output.append('%s/results.dat' % G) 5072 input_files.append(pjoin(argument[1], "input_app.txt")) 5073 input_files.append(pjoin(argument[1], "ftn26")) 5074 5075 #submitting 5076 self.cluster.cluster_submit(exe, stdout=stdout, cwd=cwd, argument=argument, 5077 input_files=input_files, output_files=output_files, 5078 required_output=required_output, **opt) 5079 5080 5081 5082 else: 5083 self.cluster.submit(exe, argument=argument, stdout=stdout, cwd=cwd, **opt)
5084 5085 5086 ############################################################################
5087 - def find_madevent_mode(self):
5088 """Find if Madevent is in Group mode or not""" 5089 5090 # The strategy is too look in the files Source/run_configs.inc 5091 # if we found: ChanPerJob=3 then it's a group mode. 5092 file_path = pjoin(self.me_dir, 'Source', 'run_config.inc') 5093 text = open(file_path).read() 5094 if re.search(r'''s*parameter\s+\(ChanPerJob=2\)''', text, re.I+re.M): 5095 return 'group' 5096 else: 5097 return 'v4'
5098 5099 ############################################################################
5100 - def monitor(self, run_type='monitor', mode=None, html=False):
5101 """ monitor the progress of running job """ 5102 5103 5104 starttime = time.time() 5105 if mode is None: 5106 mode = self.cluster_mode 5107 if mode > 0: 5108 if html: 5109 update_status = lambda idle, run, finish: \ 5110 self.update_status((idle, run, finish, run_type), level=None, 5111 force=False, starttime=starttime) 5112 update_first = lambda idle, run, finish: \ 5113 self.update_status((idle, run, finish, run_type), level=None, 5114 force=True, starttime=starttime) 5115 else: 5116 update_status = lambda idle, run, finish: None 5117 update_first = None 5118 try: 5119 self.cluster.wait(self.me_dir, update_status, update_first=update_first) 5120 except Exception, error: 5121 logger.info(error) 5122 if not self.force: 5123 ans = self.ask('Cluster Error detected. Do you want to clean the queue? ("c"=continue the run anyway)', 5124 default = 'y', choices=['y','n', 'c']) 5125 else: 5126 ans = 'y' 5127 if ans == 'y': 5128 self.cluster.remove() 5129 elif ans == 'c': 5130 return self.monitor(run_type=run_type, mode=mode, html=html) 5131 raise 5132 except KeyboardInterrupt, error: 5133 self.cluster.remove() 5134 raise
5135 5136 5137 5138 ############################################################################
5139 - def configure_directory(self, html_opening=True):
5140 """ All action require before any type of run """ 5141 5142 # Basic check 5143 assert os.path.exists(pjoin(self.me_dir,'SubProcesses')) 5144 5145 # environmental variables to be included in make_opts 5146 self.make_opts_var = {} 5147 5148 #see when the last file was modified 5149 time_mod = max([os.path.getctime(pjoin(self.me_dir,'Cards','run_card.dat')), 5150 os.path.getctime(pjoin(self.me_dir,'Cards','param_card.dat'))]) 5151 if self.configured > time_mod and hasattr(self, 'random'): 5152 return 5153 else: 5154 self.configured = time.time() 5155 self.update_status('compile directory', level=None, update_results=True) 5156 if self.options['automatic_html_opening'] and html_opening: 5157 misc.open_file(os.path.join(self.me_dir, 'crossx.html')) 5158 self.options['automatic_html_opening'] = False 5159 #open only once the web page 5160 # Change current working directory 5161 self.launching_dir = os.getcwd() 5162 5163 # Check if we need the MSSM special treatment 5164 model = self.find_model_name() 5165 if model == 'mssm' or model.startswith('mssm-'): 5166 param_card = pjoin(self.me_dir, 'Cards','param_card.dat') 5167 mg5_param = pjoin(self.me_dir, 'Source', 'MODEL', 'MG5_param.dat') 5168 check_param_card.convert_to_mg5card(param_card, mg5_param) 5169 check_param_card.check_valid_param_card(mg5_param) 5170 5171 # limit the number of event to 100k 5172 self.check_nb_events() 5173 5174 # this is in order to avoid conflicts between runs with and without 5175 # lhapdf 5176 misc.compile(['clean4pdf'], cwd = pjoin(self.me_dir, 'Source')) 5177 5178 # set lhapdf. 5179 if self.run_card['pdlabel'] == "lhapdf": 5180 self.make_opts_var['lhapdf'] = 'True' 5181 self.link_lhapdf(pjoin(self.me_dir,'lib')) 5182 pdfsetsdir = self.get_lhapdf_pdfsetsdir() 5183 lhaid_list = [int(self.run_card['lhaid'])] 5184 self.copy_lhapdf_set(lhaid_list, pdfsetsdir) 5185 if self.run_card['pdlabel'] != "lhapdf": 5186 self.pdffile = None 5187 self.make_opts_var['lhapdf'] = "" 5188 5189 # set random number 5190 if self.run_card['iseed'] != 0: 5191 self.random = int(self.run_card['iseed']) 5192 self.run_card['iseed'] = 0 5193 # Reset seed in run_card to 0, to ensure that following runs 5194 # will be statistically independent 5195 self.run_card.write(pjoin(self.me_dir, 'Cards','run_card.dat')) 5196 self.configured = time.time() 5197 elif os.path.exists(pjoin(self.me_dir,'SubProcesses','randinit')): 5198 for line in open(pjoin(self.me_dir,'SubProcesses','randinit')): 5199 data = line.split('=') 5200 assert len(data) ==2 5201 self.random = int(data[1]) 5202 break 5203 else: 5204 self.random = random.randint(1, 30107) 5205 5206 if self.run_card['ickkw'] == 2: 5207 logger.info('Running with CKKW matching') 5208 self.treat_ckkw_matching() 5209 5210 # add the make_opts_var to make_opts 5211 self.update_make_opts() 5212 5213 # create param_card.inc and run_card.inc 5214 self.do_treatcards('') 5215 5216 logger.info("compile Source Directory") 5217 5218 # Compile 5219 for name in [ 'all', '../bin/internal/combine_events']: 5220 self.compile(arg=[name], cwd=os.path.join(self.me_dir, 'Source')) 5221 5222 bias_name = os.path.basename(self.run_card['bias_module']) 5223 if bias_name.lower()=='none': 5224 bias_name = 'dummy' 5225 5226 # Always refresh the bias dependencies file 5227 if os.path.exists(pjoin(self.me_dir, 'SubProcesses','bias_dependencies')): 5228 os.remove(pjoin(self.me_dir, 'SubProcesses','bias_dependencies')) 5229 if os.path.exists(pjoin(self.me_dir, 'Source','BIAS',bias_name,'bias_dependencies')): 5230 files.ln(pjoin(self.me_dir, 'Source','BIAS',bias_name,'bias_dependencies'), 5231 pjoin(self.me_dir, 'SubProcesses')) 5232 5233 if self.proc_characteristics['bias_module']!=bias_name and \ 5234 os.path.isfile(pjoin(self.me_dir, 'lib','libbias.a')): 5235 os.remove(pjoin(self.me_dir, 'lib','libbias.a')) 5236 5237 # Finally compile the bias module as well 5238 if self.run_card['bias_module']!='dummy': 5239 logger.debug("Compiling the bias module '%s'"%bias_name) 5240 # Verify the compatibility of the specified module 5241 bias_module_valid = misc.Popen(['make','requirements'], 5242 cwd=os.path.join(self.me_dir, 'Source','BIAS',bias_name), 5243 stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0] 5244 if 'VALID' not in bias_module_valid.upper() or \ 5245 'INVALID' in bias_module_valid.upper(): 5246 raise InvalidCmd("The bias module '%s' cannot be used because of:\n%s"% 5247 (bias_name,bias_module_valid)) 5248 5249 self.compile(arg=[], cwd=os.path.join(self.me_dir, 'Source','BIAS',bias_name)) 5250 self.proc_characteristics['bias_module']=bias_name 5251 # Update the proc_characterstics file 5252 self.proc_characteristics.write( 5253 pjoin(self.me_dir,'SubProcesses','proc_characteristics')) 5254 # Make sure that madevent will be recompiled 5255 subproc = [l.strip() for l in open(pjoin(self.me_dir,'SubProcesses', 5256 'subproc.mg'))] 5257 for nb_proc,subdir in enumerate(subproc): 5258 Pdir = pjoin(self.me_dir, 'SubProcesses',subdir.strip()) 5259 self.compile(['clean'], cwd=Pdir)
5260 5261 ############################################################################ 5262 ## HELPING ROUTINE 5263 ############################################################################ 5264 @staticmethod
5265 - def check_dir(path, default=''):
5266 """check if the directory exists. if so return the path otherwise the 5267 default""" 5268 5269 if os.path.isdir(path): 5270 return path 5271 else: 5272 return default
5273 5274 ############################################################################
5275 - def get_Pdir(self):
5276 """get the list of Pdirectory if not yet saved.""" 5277 5278 if hasattr(self, "Pdirs"): 5279 if self.me_dir in self.Pdirs[0]: 5280 return self.Pdirs 5281 self.Pdirs = [pjoin(self.me_dir, 'SubProcesses', l.strip()) 5282 for l in open(pjoin(self.me_dir,'SubProcesses', 'subproc.mg'))] 5283 return self.Pdirs
5284 5285 ############################################################################
5286 - def get_Gdir(self):
5287 """get the list of Gdirectory if not yet saved.""" 5288 5289 if hasattr(self, "Gdirs"): 5290 if self.me_dir in self.Gdirs[0]: 5291 return self.Gdirs 5292 5293 Pdirs = self.get_Pdir() 5294 Gdirs = [] 5295 for P in Pdirs: 5296 for line in open(pjoin(P, "symfact.dat")): 5297 tag, mfactor = line.split() 5298 Gdirs.append( (pjoin(P, "G%s" % tag), int(mfactor)) ) 5299 5300 5301 self.Gdirs = Gdirs 5302 return self.Gdirs
5303 5304 ############################################################################
5305 - def set_run_name(self, name, tag=None, level='parton', reload_card=False, 5306 allow_new_tag=True):
5307 """define the run name, the run_tag, the banner and the results.""" 5308 5309 def get_last_tag(self, level): 5310 # Return the tag of the previous run having the required data for this 5311 # tag/run to working wel. 5312 if level == 'parton': 5313 return 5314 elif level in ['pythia','pythia8','madanalysis5_parton','madanalysis5_hadron']: 5315 return self.results[self.run_name][0]['tag'] 5316 else: 5317 for i in range(-1,-len(self.results[self.run_name])-1,-1): 5318 tagRun = self.results[self.run_name][i] 5319 if tagRun.pythia or tagRun.shower or tagRun.pythia8 : 5320 return tagRun['tag']
5321 5322 5323 # when are we force to change the tag new_run:previous run requiring changes 5324 upgrade_tag = {'parton': ['parton','pythia','pgs','delphes','madanalysis5_hadron','madanalysis5_parton'], 5325 'pythia': ['pythia','pgs','delphes','madanalysis5_hadron'], 5326 'pythia8': ['pythia8','pgs','delphes','madanalysis5_hadron'], 5327 'pgs': ['pgs'], 5328 'delphes':['delphes'], 5329 'madanalysis5_hadron':['madanalysis5_hadron'], 5330 'madanalysis5_parton':['madanalysis5_parton'], 5331 'plot':[], 5332 'syscalc':[]} 5333 5334 if name == self.run_name: 5335 if reload_card: 5336 run_card = pjoin(self.me_dir, 'Cards','run_card.dat') 5337 self.run_card = banner_mod.RunCard(run_card) 5338 5339 #check if we need to change the tag 5340 if tag: 5341 self.run_card['run_tag'] = tag 5342 self.run_tag = tag 5343 self.results.add_run(self.run_name, self.run_card) 5344 else: 5345 for tag in upgrade_tag[level]: 5346 if getattr(self.results[self.run_name][-1], tag): 5347 tag = self.get_available_tag() 5348 self.run_card['run_tag'] = tag 5349 self.run_tag = tag 5350 self.results.add_run(self.run_name, self.run_card) 5351 break 5352 return get_last_tag(self, level) 5353 5354 5355 # save/clean previous run 5356 if self.run_name: 5357 self.store_result() 5358 # store new name 5359 self.run_name = name 5360 5361 new_tag = False 5362 # First call for this run -> set the banner 5363 self.banner = banner_mod.recover_banner(self.results, level, name) 5364 if 'mgruncard' in self.banner: 5365 self.run_card = self.banner.charge_card('run_card') 5366 else: 5367 # Read run_card 5368 run_card = pjoin(self.me_dir, 'Cards','run_card.dat') 5369 self.run_card = banner_mod.RunCard(run_card) 5370 5371 if tag: 5372 self.run_card['run_tag'] = tag 5373 new_tag = True 5374 elif not self.run_name in self.results and level =='parton': 5375 pass # No results yet, so current tag is fine 5376 elif not self.run_name in self.results: 5377 #This is only for case when you want to trick the interface 5378 logger.warning('Trying to run data on unknown run.') 5379 self.results.add_run(name, self.run_card) 5380 self.results.update('add run %s' % name, 'all', makehtml=False) 5381 else: 5382 for tag in upgrade_tag[level]: 5383 5384 if getattr(self.results[self.run_name][-1], tag): 5385 # LEVEL is already define in the last tag -> need to switch tag 5386 tag = self.get_available_tag() 5387 self.run_card['run_tag'] = tag 5388 new_tag = True 5389 break 5390 if not new_tag: 5391 # We can add the results to the current run 5392 tag = self.results[self.run_name][-1]['tag'] 5393 self.run_card['run_tag'] = tag # ensure that run_tag is correct 5394 5395 if allow_new_tag and (name in self.results and not new_tag): 5396 self.results.def_current(self.run_name) 5397 else: 5398 self.results.add_run(self.run_name, self.run_card) 5399 5400 self.run_tag = self.run_card['run_tag'] 5401 5402 return get_last_tag(self, level) 5403 5404 5405 ############################################################################
5406 - def find_model_name(self):
5407 """ return the model name """ 5408 if hasattr(self, 'model_name'): 5409 return self.model_name 5410 5411 model = 'sm' 5412 proc = [] 5413 for line in open(os.path.join(self.me_dir,'Cards','proc_card_mg5.dat')): 5414 line = line.split('#')[0] 5415 #line = line.split('=')[0] 5416 if line.startswith('import') and 'model' in line: 5417 model = line.split()[2] 5418 proc = [] 5419 elif line.startswith('generate'): 5420 proc.append(line.split(None,1)[1]) 5421 elif line.startswith('add process'): 5422 proc.append(line.split(None,2)[2]) 5423 5424 self.model = model 5425 self.process = proc 5426 return model
5427 5428 5429 ############################################################################
5430 - def check_nb_events(self):
5431 """Find the number of event in the run_card, and check that this is not 5432 too large""" 5433 5434 5435 nb_event = int(self.run_card['nevents']) 5436 if nb_event > 1000000: 5437 logger.warning("Attempting to generate more than 1M events") 5438 logger.warning("Limiting number to 1M. Use multi_run for larger statistics.") 5439 path = pjoin(self.me_dir, 'Cards', 'run_card.dat') 5440 os.system(r"""perl -p -i.bak -e "s/\d+\s*=\s*nevents/1000000 = nevents/" %s""" \ 5441 % path) 5442 self.run_card['nevents'] = 1000000 5443 5444 return
5445 5446 5447 ############################################################################
5448 - def update_random(self):
5449 """ change random number""" 5450 5451 self.random += 3 5452 if self.random > 30081*30081: # can't use too big random number 5453 raise MadGraph5Error,\ 5454 'Random seed too large ' + str(self.random) + ' > 30081*30081'
5455 5456 ############################################################################
5457 - def save_random(self):
5458 """save random number in appropirate file""" 5459 5460 fsock = open(pjoin(self.me_dir, 'SubProcesses','randinit'),'w') 5461 fsock.writelines('r=%s\n' % self.random)
5462
5463 - def do_quit(self, *args, **opts):
5464 5465 common_run.CommonRunCmd.do_quit(self, *args, **opts) 5466 return CmdExtended.do_quit(self, *args, **opts)
5467 5468 ############################################################################
5469 - def treat_CKKW_matching(self):
5470 """check for ckkw""" 5471 5472 lpp1 = self.run_card['lpp1'] 5473 lpp2 = self.run_card['lpp2'] 5474 e1 = self.run_card['ebeam1'] 5475 e2 = self.run_card['ebeam2'] 5476 pd = self.run_card['pdlabel'] 5477 lha = self.run_card['lhaid'] 5478 xq = self.run_card['xqcut'] 5479 translation = {'e1': e1, 'e2':e2, 'pd':pd, 5480 'lha':lha, 'xq':xq} 5481 5482 if lpp1 or lpp2: 5483 # Remove ':s from pd 5484 if pd.startswith("'"): 5485 pd = pd[1:] 5486 if pd.endswith("'"): 5487 pd = pd[:-1] 5488 5489 if xq >2 or xq ==2: 5490 xq = 2 5491 5492 # find data file 5493 if pd == "lhapdf": 5494 issudfile = 'lib/issudgrid-%(e1)s-%(e2)s-%(pd)s-%(lha)s-%(xq)s.dat.gz' 5495 else: 5496 issudfile = 'lib/issudgrid-%(e1)s-%(e2)s-%(pd)s-%(xq)s.dat.gz' 5497 if self.web: 5498 issudfile = pjoin(self.webbin, issudfile % translation) 5499 else: 5500 issudfile = pjoin(self.me_dir, issudfile % translation) 5501 5502 logger.info('Sudakov grid file: %s' % issudfile) 5503 5504 # check that filepath exists 5505 if os.path.exists(issudfile): 5506 path = pjoin(self.me_dir, 'lib', 'issudgrid.dat') 5507 misc.gunzip(issudfile, keep=True, stdout=path) 5508 else: 5509 msg = 'No sudakov grid file for parameter choice. Start to generate it. This might take a while' 5510 logger.info(msg) 5511 self.update_status('GENERATE SUDAKOV GRID', level='parton') 5512 5513 for i in range(-2,6): 5514 self.cluster.submit('%s/gensudgrid ' % self.dirbin, 5515 argument = ['%d'%i], 5516 cwd=self.me_dir, 5517 stdout=open(pjoin(self.me_dir, 'gensudgrid%s.log' % i),'w')) 5518 self.monitor() 5519 for i in range(-2,6): 5520 path = pjoin(self.me_dir, 'lib', 'issudgrid.dat') 5521 os.system('cat %s/gensudgrid%s.log >> %s' % (self.me_dir, path)) 5522 misc.gzip(path, stdout=issudfile)
5523 5524 ############################################################################
5525 - def create_root_file(self, input='unweighted_events.lhe', 5526 output='unweighted_events.root' ):
5527 """create the LHE root file """ 5528 self.update_status('Creating root files', level='parton') 5529 5530 eradir = self.options['exrootanalysis_path'] 5531 totar = False 5532 if input.endswith('.gz'): 5533 misc.gunzip(input, keep=True) 5534 totar = True 5535 input = input[:-3] 5536 5537 try: 5538 misc.call(['%s/ExRootLHEFConverter' % eradir, 5539 input, output], 5540 cwd=pjoin(self.me_dir, 'Events')) 5541 except Exception: 5542 logger.warning('fail to produce Root output [problem with ExRootAnalysis]') 5543 5544 if totar: 5545 if os.path.exists('%s.gz' % input): 5546 try: 5547 os.remove(input) 5548 except: 5549 pass 5550 else: 5551 misc.gzip(input,keep=False)
5552 5553
5554 - def run_syscalc(self, mode='parton', event_path=None, output=None):
5555 """create the syscalc output""" 5556 5557 if self.run_card['use_syst'] not in self.true: 5558 return 5559 5560 scdir = self.options['syscalc_path'] 5561 if not scdir or not os.path.exists(scdir): 5562 return 5563 5564 if self.run_card['event_norm'] != 'sum': 5565 logger.critical('SysCalc works only when event_norm is on \'sum\'.') 5566 return 5567 logger.info('running SysCalc on mode %s' % mode) 5568 5569 # Restore the old default for SysCalc+PY6 5570 if self.run_card['sys_matchscale']=='auto': 5571 self.run_card['sys_matchscale'] = "30 50" 5572 5573 # Check that all pdfset are correctly installed 5574 lhaid = [self.run_card.get_lhapdf_id()] 5575 if '&&' in self.run_card['sys_pdf']: 5576 line = ' '.join(self.run_card['sys_pdf']) 5577 sys_pdf = line.split('&&') 5578 lhaid += [l.split()[0] for l in sys_pdf] 5579 else: 5580 lhaid += [l for l in self.run_card['sys_pdf'].split() if not l.isdigit() or int(l) > 500] 5581 try: 5582 pdfsets_dir = self.get_lhapdf_pdfsetsdir() 5583 except Exception, error: 5584 logger.debug(str(error)) 5585 logger.warning('Systematic computation requires lhapdf to run. Bypass SysCalc') 5586 return 5587 5588 # Copy all the relevant PDF sets 5589 [self.copy_lhapdf_set([onelha], pdfsets_dir) for onelha in lhaid] 5590 5591 to_syscalc={'sys_scalefact': self.run_card['sys_scalefact'], 5592 'sys_alpsfact': self.run_card['sys_alpsfact'], 5593 'sys_matchscale': self.run_card['sys_matchscale'], 5594 'sys_scalecorrelation': self.run_card['sys_scalecorrelation'], 5595 'sys_pdf': self.run_card['sys_pdf']} 5596 5597 tag = self.run_card['run_tag'] 5598 card = pjoin(self.me_dir, 'bin','internal', 'syscalc_card.dat') 5599 template = open(pjoin(self.me_dir, 'bin','internal', 'syscalc_template.dat')).read() 5600 5601 if '&&' in to_syscalc['sys_pdf']: 5602 to_syscalc['sys_pdf'] = to_syscalc['sys_pdf'].split('#',1)[0].replace('&&',' \n ') 5603 else: 5604 data = to_syscalc['sys_pdf'].split() 5605 new = [] 5606 for d in data: 5607 if not d.isdigit(): 5608 new.append(d) 5609 elif int(d) > 500: 5610 new.append(d) 5611 else: 5612 new[-1] += ' %s' % d 5613 to_syscalc['sys_pdf'] = '\n'.join(new) 5614 5615 if to_syscalc['sys_pdf'].lower() in ['', 'f', 'false', 'none', '.false.']: 5616 to_syscalc['sys_pdf'] = '' 5617 if to_syscalc['sys_alpsfact'].lower() in ['', 'f', 'false', 'none','.false.']: 5618 to_syscalc['sys_alpsfact'] = '' 5619 5620 5621 5622 5623 # check if the scalecorrelation parameter is define: 5624 if not 'sys_scalecorrelation' in self.run_card: 5625 self.run_card['sys_scalecorrelation'] = -1 5626 open(card,'w').write(template % self.run_card) 5627 5628 if not os.path.exists(card): 5629 return False 5630 5631 5632 5633 event_dir = pjoin(self.me_dir, 'Events') 5634 5635 if not event_path: 5636 if mode == 'parton': 5637 event_path = pjoin(event_dir,self.run_name, 'unweighted_events.lhe') 5638 if not (os.path.exists(event_path) or os.path.exists(event_path+".gz")): 5639 event_path = pjoin(event_dir, 'unweighted_events.lhe') 5640 output = pjoin(event_dir, 'syscalc.lhe') 5641 stdout = open(pjoin(event_dir, self.run_name, '%s_systematics.log' % (mode)),'w') 5642 elif mode == 'Pythia': 5643 stdout = open(pjoin(event_dir, self.run_name, '%s_%s_syscalc.log' % (tag,mode)),'w') 5644 if 'mgpythiacard' in self.banner: 5645 pat = re.compile('''^\s*qcut\s*=\s*([\+\-\d.e]*)''', re.M+re.I) 5646 data = pat.search(self.banner['mgpythiacard']) 5647 if data: 5648 qcut = float(data.group(1)) 5649 xqcut = abs(self.run_card['xqcut']) 5650 for value in self.run_card['sys_matchscale'].split(): 5651 if float(value) < qcut: 5652 raise SysCalcError, 'qcut value for sys_matchscale lower than qcut in pythia_card. Bypass syscalc' 5653 if float(value) < xqcut: 5654 raise SysCalcError, 'qcut value for sys_matchscale lower than xqcut in run_card. Bypass syscalc' 5655 5656 5657 event_path = pjoin(event_dir,'syst.dat') 5658 output = pjoin(event_dir, 'syscalc.dat') 5659 else: 5660 raise self.InvalidCmd, 'Invalid mode %s' % mode 5661 5662 if not os.path.exists(event_path): 5663 if os.path.exists(event_path+'.gz'): 5664 misc.gunzip(event_path+'.gz') 5665 else: 5666 raise SysCalcError, 'Events file %s does not exits' % event_path 5667 5668 self.update_status('Calculating systematics for %s level' % mode, level = mode.lower()) 5669 try: 5670 proc = misc.call([os.path.join(scdir, 'sys_calc'), 5671 event_path, card, output], 5672 stdout = stdout, 5673 stderr = subprocess.STDOUT, 5674 cwd=event_dir) 5675 # Wait 5 s to make sure file is finished writing 5676 time.sleep(5) 5677 except OSError, error: 5678 logger.error('fail to run syscalc: %s. Please check that SysCalc is correctly installed.' % error) 5679 else: 5680 if not os.path.exists(output): 5681 logger.warning('SysCalc Failed. Please read the associate log to see the reason. Did you install the associate PDF set?') 5682 elif mode == 'parton': 5683 files.mv(output, event_path) 5684 5685 self.update_status('End syscalc for %s level' % mode, level = mode.lower(), 5686 makehtml=False) 5687 5688 return True
5689 5690 5691 5692 ############################################################################
5693 - def ask_run_configuration(self, mode=None, args=[]):
5694 """Ask the question when launching generate_events/multi_run""" 5695 5696 available_mode = ['0'] 5697 void = 'Not installed' 5698 switch_order = ['shower', 'detector', 'analysis', 'madspin', 'reweight'] 5699 5700 switch = dict((k, void) for k in switch_order) 5701 5702 description = {'shower': 'Choose the shower/hadronization program:', 5703 'detector': 'Choose the detector simulation program:', 5704 'madspin': 'Decay particles with the MadSpin module:', 5705 'reweight':'Add weights to events for different model hypothesis:', 5706 'analysis':'Run an analysis package on the events generated:' 5707 } 5708 5709 force_switch = {('shower', 'OFF'): {'detector': 'OFF'}, 5710 ('detector', 'PGS'): {'shower':'PYTHIA6'}, 5711 ('detector', 'DELPHES'): {'shower': ['PYTHIA8', 'PYTHIA6']}} 5712 5713 switch_assign = lambda key, value: switch.__setitem__(key, value if value \ 5714 in valid_options[key] else switch[key]) 5715 5716 valid_options = dict((k, ['OFF']) for k in switch_order) # track of all possible input for an entry 5717 options = ['auto', 'done'] 5718 options_legacy = [] 5719 5720 # Init the switch value according to the current status 5721 if self.options['pythia-pgs_path']: 5722 available_mode.append('1') 5723 available_mode.append('2') 5724 valid_options['shower'].append('PYTHIA6') 5725 valid_options['detector'].append('PGS') 5726 options_legacy += ['pythia', 'pgs', 'pythia=ON', 'pythia=OFF', 'pgs=ON', 'pgs=OFF'] 5727 if os.path.exists(pjoin(self.me_dir,'Cards','pythia_card.dat')): 5728 switch['shower'] = 'PYTHIA6' 5729 else: 5730 switch['shower'] = 'OFF' 5731 if os.path.exists(pjoin(self.me_dir,'Cards','pgs_card.dat')): 5732 switch['detector'] = 'PGS' 5733 else: 5734 switch['detector'] = 'OFF' 5735 5736 if self.options['pythia8_path']: 5737 available_mode.append('1') 5738 valid_options['shower'].append('PYTHIA8') 5739 if os.path.exists(pjoin(self.me_dir,'Cards','pythia8_card.dat')): 5740 switch['shower'] = 'PYTHIA8' 5741 elif switch['shower'] == void: 5742 switch['shower'] = 'OFF' 5743 5744 # MadAnalysis4 options 5745 if self.options['madanalysis_path']: 5746 if os.path.exists(pjoin(self.me_dir,'Cards','plot_card_default.dat')): 5747 valid_options['analysis'].insert(0,'MADANALYSIS_4') 5748 5749 if os.path.exists(pjoin(self.me_dir,'Cards','plot_card.dat')): 5750 switch['analysis'] = 'MADANALYSIS_4' 5751 5752 # MadAnalysis5 options 5753 if self.options['madanalysis5_path']: 5754 if os.path.exists(pjoin(self.me_dir,'Cards','madanalysis5_parton_card_default.dat')) or \ 5755 os.path.exists(pjoin(self.me_dir,'Cards','madanalysis5_hadron_card_default.dat')): 5756 valid_options['analysis'].append('MADANALYSIS_5') 5757 5758 parton_card_present = os.path.exists(pjoin(self.me_dir,'Cards', 5759 'madanalysis5_parton_card.dat')) 5760 hadron_card_present = os.path.exists(pjoin(self.me_dir,'Cards', 5761 'madanalysis5_hadron_card.dat')) 5762 if hadron_card_present or parton_card_present: 5763 switch['analysis'] = 'MADANALYSIS_5' 5764 5765 # ExRootanalysis 5766 eradir = self.options['exrootanalysis_path'] 5767 if eradir and misc.is_executable(pjoin(eradir,'ExRootLHEFConverter')): 5768 valid_options['analysis'].insert(0,'EXROOTANALYSIS') 5769 if switch['analysis'] in ['OFF', void]: 5770 switch['analysis'] = 'EXROOTANALYSIS' 5771 5772 5773 5774 if len(valid_options['analysis'])>1: 5775 available_mode.append('3') 5776 if switch['analysis'] == void: 5777 switch['analysis'] = 'OFF' 5778 else: 5779 switch['analysis'] = 'No analysis tool interfaced to MG5aMC.' 5780 5781 # Need to allow Delphes only if a shower exists 5782 if self.options['delphes_path']: 5783 if valid_options['shower'] != ['OFF']: 5784 available_mode.append('2') 5785 valid_options['detector'].append('DELPHES') 5786 options += ['delphes', 'delphes=ON', 'delphes=OFF'] 5787 if os.path.exists(pjoin(self.me_dir,'Cards','delphes_card.dat')): 5788 switch['detector'] = 'DELPHES' 5789 elif switch['detector'] not in ['PGS']: 5790 switch['detector'] = 'OFF' 5791 elif valid_options['detector'] == ['OFF']: 5792 switch['detector'] = "Requires a shower" 5793 5794 # Check switch status for MS/reweight 5795 if not MADEVENT or ('mg5_path' in self.options and self.options['mg5_path']): 5796 available_mode.append('4') 5797 valid_options['madspin'] = ['ON', 'OFF'] 5798 if os.path.exists(pjoin(self.me_dir,'Cards','madspin_card.dat')): 5799 switch['madspin'] = 'ON' 5800 else: 5801 switch['madspin'] = 'OFF' 5802 if misc.has_f2py() or self.options['f2py_compiler']: 5803 available_mode.append('5') 5804 valid_options['reweight'] = ['ON', 'OFF'] 5805 if os.path.exists(pjoin(self.me_dir,'Cards','reweight_card.dat')): 5806 switch['reweight'] = 'ON' 5807 else: 5808 switch['reweight'] = 'OFF' 5809 else: 5810 switch['reweight'] = 'Not available (requires NumPy/f2py)' 5811 5812 if '-R' in args or '--reweight' in args: 5813 if switch['reweight'] == 'OFF': 5814 switch['reweight'] = 'ON' 5815 elif switch['reweight'] != 'ON': 5816 logger.critical("Cannot run reweight: %s", switch['reweight']) 5817 if '-M' in args or '--madspin' in args: 5818 if switch['madspin'] == 'OFF': 5819 switch['madspin'] = 'ON' 5820 elif switch['madspin'] != 'ON': 5821 logger.critical("Cannot run madspin: %s", switch['reweight']) 5822 5823 for id, key in enumerate(switch_order): 5824 if len(valid_options[key]) >1: 5825 options += ['%s=%s' % (key, s) for s in valid_options[key]] 5826 options.append(key) 5827 else: 5828 options.append('%s=OFF' % (key)) 5829 5830 options += ['parton'] + sorted(list(set(available_mode))) 5831 options += options_legacy 5832 #options += ['pythia=ON', 'pythia=OFF', 'delphes=ON', 'delphes=OFF', 'pgs=ON', 'pgs=OFF'] 5833 #ask the question 5834 5835 def color(switch_value): 5836 green = '\x1b[32m%s\x1b[0m' 5837 bold = '\x1b[33m%s\x1b[0m' 5838 red = '\x1b[31m%s\x1b[0m' 5839 if switch_value in ['OFF',void,'Requires a shower', 5840 'Not available (requires NumPy)', 5841 'Not available yet for this output/process']: 5842 return red%switch_value 5843 elif switch_value in ['ON','MADANALYSIS_4','MADANALYSIS_5', 5844 'PYTHIA8','PYTHIA6','PGS','DELPHES-ATLAS', 5845 'DELPHES-CMS','DELPHES', 'EXROOTANALYSIS']: 5846 return green%switch_value 5847 else: 5848 return bold%switch_value
5849 5850 if mode or not self.force: 5851 answer = '' 5852 while answer not in ['0', 'done', 'auto']: 5853 if mode: 5854 answer = mode 5855 else: 5856 switch_format = " \x1b[31m%i\x1b[0m. %-60s %12s = %s" 5857 question = "The following switches determine which programs are run:\n" 5858 question += '/'+'-'*98+'\\\n' 5859 for id, key in enumerate(switch_order): 5860 question += '| %-115s|\n'%(switch_format%(id+1, description[key], key, color(switch[key]))) 5861 question += '\\'+'-'*98+'/\n' 5862 question += ' Either type the switch number (1 to %s) to change its setting,\n' % (id+1) 5863 question += ' Set any switch explicitly (e.g. type \'madspin=ON\' at the prompt)\n' 5864 question += ' Type \'help\' for the list of all valid option\n' 5865 question += ' Type \'0\', \'auto\', \'done\' or just press enter when you are done.\n' 5866 answer = self.ask(question, '0', options, casesensitive=False) 5867 if (answer.isdigit() and answer != '0') or answer in ['shower', 'detector']: 5868 if answer.isdigit(): 5869 key = switch_order[int(answer) - 1] 5870 else: 5871 key = answer 5872 for i, opt in enumerate(valid_options[key]): 5873 if opt == switch[key]: 5874 break 5875 i +=1 5876 if i == len(valid_options[key]): 5877 i=0 5878 answer = '%s=%s' % (key, valid_options[key][i]) 5879 5880 if '=' in answer: 5881 key, status = answer.split('=') 5882 key, status = key.lower().strip(), status.upper().strip() 5883 5884 if key not in switch: 5885 # this means use use outdated switch. Use converter to new syntax 5886 logger.warning("Using old syntax. Please check that we run what you expect.") 5887 if key == "pythia" and status == "ON": 5888 key, status = "shower", "PYTHIA6" 5889 elif key == "pythia" and status == "OFF": 5890 key, status = "shower", "OFF" 5891 elif key == "pgs" and status == "ON": 5892 if switch["detector"] in ["OFF", "PGS"] : 5893 key, status = "detector", "PGS" 5894 else: 5895 key, status = "detector", "DELPHES+PGS" 5896 elif key == "delphes" and status == "ON": 5897 if switch["detector"] in ["OFF", "DELPHES"] : 5898 key, status = "detector", "DELPHES" 5899 else: 5900 key, status = "detector", "DELPHES+PGS" 5901 elif key == "pgs" and status == "OFF": 5902 if switch["detector"] in ["OFF", "PGS"] : 5903 key, status = "detector", "OFF" 5904 elif switch["detector"] == "DELPHES+PGS": 5905 key, status = "detector", "DELPHES" 5906 else: 5907 key, status = "detector", switch['detector'] 5908 elif key == "delphes" and status == "OFF": 5909 if switch["detector"] in ["OFF", "DELPHES"] : 5910 key, status = "detector", "OFF" 5911 elif switch["detector"] == "DELPHES+PGS": 5912 key, status = "detector", "PGS" 5913 else: 5914 key, status = "detector", switch['detector'] 5915 5916 5917 switch[key] = status 5918 if (key, status) in force_switch: 5919 for key2, status2 in force_switch[(key, status)].items(): 5920 if isinstance(status2, str): 5921 if switch[key2] not in [status2, void]: 5922 logger.info('For coherence \'%s\' is set to \'%s\'' 5923 % (key2, status2), '$MG:color:BLACK') 5924 switch[key2] = status2 5925 else: 5926 if switch[key2] not in status2 + [void]: 5927 logger.info('For coherence \'%s\' is set to \'%s\'' 5928 % (key2, status2[0]), '$MG:color:BLACK') 5929 switch[key2] = status2[0] 5930 elif answer in ['0', 'auto', 'done']: 5931 continue 5932 elif answer in ['parton', 'pythia','pgs','madspin','reweight', 'delphes']: 5933 logger.info('pass in %s only mode' % answer, '$MG:color:BLACK') 5934 switch_assign('madspin', 'OFF') 5935 switch_assign('reweight', 'OFF') 5936 if answer == 'parton': 5937 switch_assign('shower', 'OFF') 5938 switch_assign('detector', 'OFF') 5939 elif answer == 'pythia': 5940 switch_assign('shower', 'PYTHIA6') 5941 switch_assign('detector', 'OFF') 5942 elif answer == 'pgs': 5943 switch_assign('shower', 'PYTHIA6') 5944 switch_assign('detector', 'PGS') 5945 elif answer == 'delphes': 5946 switch_assign('shower', 'PYTHIA6') 5947 if switch['shower'] == 'OFF': 5948 switch_assign('shower', 'PYTHIA8') 5949 switch_assign('detector', 'DELPHES') 5950 elif answer == 'madspin': 5951 switch_assign('madspin', 'ON') 5952 switch_assign('shower', 'OFF') 5953 switch_assign('detector', 'OFF') 5954 elif answer == 'reweight': 5955 switch_assign('reweight', 'ON') 5956 switch_assign('shower', 'OFF') 5957 switch_assign('detector', 'OFF') 5958 5959 if mode: 5960 answer = '0' #mode auto didn't pass here (due to the continue) 5961 else: 5962 answer = 'auto' 5963 5964 # Now that we know in which mode we are check that all the card 5965 #exists (copy default if needed) 5966 5967 cards = ['param_card.dat', 'run_card.dat'] 5968 if switch['shower'] in ['PY6', 'PYTHIA6']: 5969 cards.append('pythia_card.dat') 5970 if switch['shower'] in ['PY8', 'PYTHIA8']: 5971 cards.append('pythia8_card.dat') 5972 if switch['detector'] in ['PGS','DELPHES+PGS']: 5973 cards.append('pgs_card.dat') 5974 if switch['detector'] in ['DELPHES', 'DELPHES+PGS']: 5975 cards.append('delphes_card.dat') 5976 delphes3 = True 5977 if os.path.exists(pjoin(self.options['delphes_path'], 'data')): 5978 delphes3 = False 5979 cards.append('delphes_trigger.dat') 5980 if switch['madspin'] == 'ON': 5981 cards.append('madspin_card.dat') 5982 if switch['reweight'] == 'ON': 5983 cards.append('reweight_card.dat') 5984 if switch['analysis'] in ['MADANALYSIS_5']: 5985 cards.append('madanalysis5_parton_card.dat') 5986 if switch['analysis'] in ['MADANALYSIS_5'] and not switch['shower']=='OFF': 5987 cards.append('madanalysis5_hadron_card.dat') 5988 if switch['analysis'] in ['MADANALYSIS_4']: 5989 cards.append('plot_card.dat') 5990 5991 self.keep_cards(cards) 5992 5993 if os.path.isfile(pjoin(self.me_dir,'Cards','MadLoopParams.dat')): 5994 cards.append('MadLoopParams.dat') 5995 5996 if self.force: 5997 self.check_param_card(pjoin(self.me_dir,'Cards','param_card.dat' )) 5998 return switch 5999 6000 if answer == 'auto': 6001 self.ask_edit_cards(cards, plot=False, mode='auto') 6002 else: 6003 self.ask_edit_cards(cards, plot=False) 6004 return switch 6005 6006 ############################################################################
6007 - def ask_pythia_run_configuration(self, mode=None, pythia_version=6):
6008 """Ask the question when launching pythia""" 6009 6010 pythia_suffix = '' if pythia_version==6 else '%d'%pythia_version 6011 6012 available_mode = ['0', '1'] 6013 if pythia_version==6: 6014 available_mode.append('2') 6015 if self.options['delphes_path']: 6016 available_mode.append('3') 6017 name = {'0': 'auto', '2':'pgs', '3':'delphes'} 6018 name['1'] = 'pythia%s'%pythia_suffix 6019 options = available_mode + [name[val] for val in available_mode] 6020 question = """Which programs do you want to run? 6021 0 / auto : running existing cards\n""" 6022 if pythia_version==6: 6023 question += """ 1. pythia : Pythia\n""" 6024 question += """ 2. pgs : Pythia + PGS\n""" 6025 else: 6026 question += """ 1. pythia8 : Pythia8\n""" 6027 6028 if '3' in available_mode: 6029 question += """ 3. delphes : Pythia%s + Delphes.\n"""%pythia_suffix 6030 6031 if not self.force: 6032 if not mode: 6033 mode = self.ask(question, '0', options) 6034 elif not mode: 6035 mode = 'auto' 6036 6037 if mode.isdigit(): 6038 mode = name[mode] 6039 6040 auto = False 6041 if mode == 'auto': 6042 auto = True 6043 if pythia_version==6 and os.path.exists(pjoin(self.me_dir, 6044 'Cards', 'pgs_card.dat')): 6045 mode = 'pgs' 6046 elif os.path.exists(pjoin(self.me_dir, 'Cards', 'delphes_card.dat')): 6047 mode = 'delphes' 6048 else: 6049 mode = 'pythia%s'%pythia_suffix 6050 logger.info('Will run in mode %s' % mode) 6051 # Now that we know in which mode we are check that all the card 6052 #exists (copy default if needed) remove pointless one 6053 cards = ['pythia%s_card.dat'%pythia_suffix] 6054 if mode == 'pgs' and pythia_version==6: 6055 cards.append('pgs_card.dat') 6056 if mode == 'delphes': 6057 cards.append('delphes_card.dat') 6058 delphes3 = True 6059 if os.path.exists(pjoin(self.options['delphes_path'], 'data')): 6060 delphes3 = False 6061 cards.append('delphes_trigger.dat') 6062 self.keep_cards(cards, ignore=['madanalysis5_parton_card.dat','madanalysis5_hadron_card.dat', 6063 'plot_card.dat']) 6064 6065 if self.force: 6066 return mode 6067 6068 if auto: 6069 self.ask_edit_cards(cards, mode='auto', plot=(pythia_version==6)) 6070 else: 6071 self.ask_edit_cards(cards, plot=(pythia_version==6)) 6072 6073 return mode
6074
6075 #=============================================================================== 6076 # MadEventCmd 6077 #=============================================================================== 6078 -class MadEventCmdShell(MadEventCmd, cmd.CmdShell):
6079 """The command line processor of MadGraph"""
6080
6081 6082 6083 #=============================================================================== 6084 # HELPING FUNCTION For Subprocesses 6085 #=============================================================================== 6086 -class SubProcesses(object):
6087 6088 name_to_pdg = {} 6089 6090 @classmethod
6091 - def clean(cls):
6092 cls.name_to_pdg = {}
6093 6094 @staticmethod
6095 - def get_subP(me_dir):
6096 """return the list of Subprocesses""" 6097 6098 out = [] 6099 for line in open(pjoin(me_dir,'SubProcesses', 'subproc.mg')): 6100 if not line: 6101 continue 6102 name = line.strip() 6103 if os.path.exists(pjoin(me_dir, 'SubProcesses', name)): 6104 out.append(pjoin(me_dir, 'SubProcesses', name)) 6105 6106 return out
6107 6108 6109 6110 @staticmethod
6111 - def get_subP_info(path):
6112 """ return the list of processes with their name""" 6113 6114 nb_sub = 0 6115 names = {} 6116 old_main = '' 6117 6118 if not os.path.exists(os.path.join(path,'processes.dat')): 6119 return SubProcesses.get_subP_info_v4(path) 6120 6121 for line in open(os.path.join(path,'processes.dat')): 6122 main = line[:8].strip() 6123 if main == 'mirror': 6124 main = old_main 6125 if line[8:].strip() == 'none': 6126 continue 6127 else: 6128 main = int(main) 6129 old_main = main 6130 6131 sub_proccess = line[8:] 6132 nb_sub += sub_proccess.count(',') + 1 6133 if main in names: 6134 names[main] += [sub_proccess.split(',')] 6135 else: 6136 names[main]= [sub_proccess.split(',')] 6137 6138 return names
6139 6140 @staticmethod
6141 - def get_subP_info_v4(path):
6142 """ return the list of processes with their name in case without grouping """ 6143 6144 nb_sub = 0 6145 names = {'':[[]]} 6146 path = os.path.join(path, 'auto_dsig.f') 6147 found = 0 6148 for line in open(path): 6149 if line.startswith('C Process:'): 6150 found += 1 6151 names[''][0].append(line[15:]) 6152 elif found >1: 6153 break 6154 return names
6155 6156 6157 @staticmethod
6158 - def get_subP_ids(path):
6159 """return the pdg codes of the particles present in the Subprocesses""" 6160 6161 all_ids = [] 6162 for line in open(pjoin(path, 'leshouche.inc')): 6163 if not 'IDUP' in line: 6164 continue 6165 particles = re.search("/([\d,-]+)/", line) 6166 all_ids.append([int(p) for p in particles.group(1).split(',')]) 6167 return all_ids
6168
6169 6170 #=============================================================================== 6171 -class GridPackCmd(MadEventCmd):
6172 """The command for the gridpack --Those are not suppose to be use interactively--""" 6173
6174 - def __init__(self, me_dir = None, nb_event=0, seed=0, *completekey, **stdin):
6175 """Initialize the command and directly run""" 6176 6177 # Initialize properly 6178 6179 MadEventCmd.__init__(self, me_dir, *completekey, **stdin) 6180 self.run_mode = 0 6181 self.random = seed 6182 self.random_orig = self.random 6183 self.options['automatic_html_opening'] = False 6184 # Now it's time to run! 6185 if me_dir and nb_event and seed: 6186 self.launch(nb_event, seed) 6187 else: 6188 raise MadGraph5Error,\ 6189 'Gridpack run failed: ' + str(me_dir) + str(nb_event) + \ 6190 str(seed)
6191
6192 - def launch(self, nb_event, seed):
6193 """ launch the generation for the grid """ 6194 6195 # 1) Restore the default data 6196 logger.info('generate %s events' % nb_event) 6197 self.set_run_name('GridRun_%s' % seed) 6198 self.update_status('restoring default data', level=None) 6199 misc.call([pjoin(self.me_dir,'bin','internal','restore_data'), 6200 'default'], 6201 cwd=self.me_dir) 6202 6203 # 2) Run the refine for the grid 6204 self.update_status('Generating Events', level=None) 6205 #misc.call([pjoin(self.me_dir,'bin','refine4grid'), 6206 # str(nb_event), '0', 'Madevent','1','GridRun_%s' % seed], 6207 # cwd=self.me_dir) 6208 self.refine4grid(nb_event) 6209 6210 # 3) Combine the events/pythia/... 6211 self.exec_cmd('combine_events') 6212 self.exec_cmd('store_events') 6213 self.print_results_in_shell(self.results.current) 6214 self.exec_cmd('decay_events -from_cards', postcmd=False)
6215
6216 - def refine4grid(self, nb_event):
6217 """Special refine for gridpack run.""" 6218 self.nb_refine += 1 6219 6220 precision = nb_event 6221 6222 # initialize / remove lhapdf mode 6223 # self.configure_directory() # All this has been done before 6224 self.cluster_mode = 0 # force single machine 6225 6226 # Store seed in randinit file, to be read by ranmar.f 6227 self.save_random() 6228 6229 self.update_status('Refine results to %s' % precision, level=None) 6230 logger.info("Using random number seed offset = %s" % self.random) 6231 6232 self.total_jobs = 0 6233 subproc = [P for P in os.listdir(pjoin(self.me_dir,'SubProcesses')) if 6234 P.startswith('P') and os.path.isdir(pjoin(self.me_dir,'SubProcesses', P))] 6235 devnull = open(os.devnull, 'w') 6236 for nb_proc,subdir in enumerate(subproc): 6237 subdir = subdir.strip() 6238 Pdir = pjoin(self.me_dir, 'SubProcesses',subdir) 6239 bindir = pjoin(os.path.relpath(self.dirbin, Pdir)) 6240 6241 logger.info(' %s ' % subdir) 6242 # clean previous run 6243 for match in misc.glob('*ajob*', Pdir): 6244 if os.path.basename(match)[:4] in ['ajob', 'wait', 'run.', 'done']: 6245 os.remove(pjoin(Pdir, match)) 6246 6247 6248 logfile = pjoin(Pdir, 'gen_ximprove.log') 6249 misc.call([pjoin(bindir, 'gen_ximprove')], 6250 stdin=subprocess.PIPE, 6251 stdout=open(logfile,'w'), 6252 cwd=Pdir) 6253 6254 if os.path.exists(pjoin(Pdir, 'ajob1')): 6255 alljobs = misc.glob('ajob*', Pdir) 6256 nb_tot = len(alljobs) 6257 self.total_jobs += nb_tot 6258 for i, job in enumerate(alljobs): 6259 job = os.path.basename(job) 6260 self.launch_job('%s' % job, cwd=Pdir, remaining=(nb_tot-i-1), 6261 run_type='Refine number %s on %s (%s/%s)' % 6262 (self.nb_refine, subdir, nb_proc+1, len(subproc))) 6263 if os.path.exists(pjoin(self.me_dir,'error')): 6264 self.monitor(html=True) 6265 raise MadEventError, \ 6266 'Error detected in dir %s: %s' % \ 6267 (Pdir, open(pjoin(self.me_dir,'error')).read()) 6268 self.monitor(run_type='All job submitted for refine number %s' % 6269 self.nb_refine) 6270 6271 self.update_status("Combining runs", level='parton') 6272 try: 6273 os.remove(pjoin(Pdir, 'combine_runs.log')) 6274 except Exception: 6275 pass 6276 6277 bindir = pjoin(os.path.relpath(self.dirbin, pjoin(self.me_dir,'SubProcesses'))) 6278 combine_runs.CombineRuns(self.me_dir) 6279 6280 #update html output 6281 cross, error = sum_html.make_all_html_results(self) 6282 self.results.add_detail('cross', cross) 6283 self.results.add_detail('error', error) 6284 6285 6286 self.update_status('finish refine', 'parton', makehtml=False) 6287 devnull.close()
6288
6289 6290 -class MadLoopInitializer(object):
6291 """ A container class for the various methods for initializing MadLoop. It is 6292 placed in MadEventInterface because it is used by Madevent for loop-induced 6293 simulations. """ 6294 6295 @staticmethod
6296 - def make_and_run(dir_name,checkRam=False):
6297 """ Compile the check program in the directory dir_name. 6298 Return the compilation and running time. """ 6299 6300 # Make sure to recreate the executable and modified source 6301 # (The time stamps are sometimes not actualized if it is too fast) 6302 if os.path.isfile(pjoin(dir_name,'check')): 6303 os.remove(pjoin(dir_name,'check')) 6304 os.remove(pjoin(dir_name,'check_sa.o')) 6305 os.remove(pjoin(dir_name,'loop_matrix.o')) 6306 # Now run make 6307 devnull = open(os.devnull, 'w') 6308 start=time.time() 6309 retcode = misc.compile(arg=['-j1','check'], cwd=dir_name, nb_core=1) 6310 compilation_time = time.time()-start 6311 if retcode != 0: 6312 logging.info("Error while executing make in %s" % dir_name) 6313 return None, None, None 6314 6315 if not checkRam: 6316 start=time.time() 6317 retcode = subprocess.call('./check', 6318 cwd=dir_name, stdout=devnull, stderr=devnull) 6319 6320 run_time = time.time()-start 6321 ram_usage = None 6322 else: 6323 ptimer = misc.ProcessTimer(['./check'], cwd=dir_name, shell=False, \ 6324 stdout=devnull, stderr=devnull, close_fds=True) 6325 try: 6326 ptimer.execute() 6327 #poll as often as possible; otherwise the subprocess might 6328 # "sneak" in some extra memory usage while you aren't looking 6329 # Accuracy of .2 seconds is enough for the timing. 6330 while ptimer.poll(): 6331 time.sleep(.2) 6332 finally: 6333 #make sure that we don't leave the process dangling. 6334 ptimer.close() 6335 # Notice that ptimer.max_vms_memory is also available if needed. 6336 ram_usage = ptimer.max_rss_memory 6337 # Unfortunately the running time is less precise than with the 6338 # above version 6339 run_time = (ptimer.t1 - ptimer.t0) 6340 retcode = ptimer.p.returncode 6341 6342 devnull.close() 6343 6344 if retcode != 0: 6345 logging.warning("Error while executing ./check in %s" % dir_name) 6346 return None, None, None 6347 6348 return compilation_time, run_time, ram_usage
6349 6350 @staticmethod
6351 - def fix_PSPoint_in_check(dir_path, read_ps = True, npoints = 1, 6352 hel_config = -1, mu_r=0.0, split_orders=-1):
6353 """Set check_sa.f to be reading PS.input assuming a working dir dir_name. 6354 if hel_config is different than -1 then check_sa.f is configured so to 6355 evaluate only the specified helicity. 6356 If mu_r > 0.0, then the renormalization constant value will be hardcoded 6357 directly in check_sa.f, if is is 0 it will be set to Sqrt(s) and if it 6358 is < 0.0 the value in the param_card.dat is used. 6359 If the split_orders target (i.e. the target squared coupling orders for 6360 the computation) is != -1, it will be changed in check_sa.f via the 6361 subroutine CALL SET_COUPLINGORDERS_TARGET(split_orders).""" 6362 6363 file_path = dir_path 6364 if not os.path.isfile(dir_path) or \ 6365 not os.path.basename(dir_path)=='check_sa.f': 6366 file_path = pjoin(dir_path,'check_sa.f') 6367 if not os.path.isfile(file_path): 6368 directories = [d for d in misc.glob('P*_*', dir_path) \ 6369 if (re.search(r'.*P\d+_\w*$', d) and os.path.isdir(d))] 6370 if len(directories)>0: 6371 file_path = pjoin(directories[0],'check_sa.f') 6372 if not os.path.isfile(file_path): 6373 raise MadGraph5Error('Could not find the location of check_sa.f'+\ 6374 ' from the specified path %s.'%str(file_path)) 6375 6376 file = open(file_path, 'r') 6377 check_sa = file.read() 6378 file.close() 6379 6380 file = open(file_path, 'w') 6381 check_sa = re.sub(r"READPS = \S+\)","READPS = %s)"%('.TRUE.' if read_ps \ 6382 else '.FALSE.'), check_sa) 6383 check_sa = re.sub(r"NPSPOINTS = \d+","NPSPOINTS = %d"%npoints, check_sa) 6384 if hel_config != -1: 6385 check_sa = re.sub(r"SLOOPMATRIX\S+\(\S+,MATELEM,", 6386 "SLOOPMATRIXHEL_THRES(P,%d,MATELEM,"%hel_config, check_sa) 6387 else: 6388 check_sa = re.sub(r"SLOOPMATRIX\S+\(\S+,MATELEM,", 6389 "SLOOPMATRIX_THRES(P,MATELEM,",check_sa) 6390 if mu_r > 0.0: 6391 check_sa = re.sub(r"MU_R=SQRTS","MU_R=%s"%\ 6392 (("%.17e"%mu_r).replace('e','d')),check_sa) 6393 elif mu_r < 0.0: 6394 check_sa = re.sub(r"MU_R=SQRTS","",check_sa) 6395 6396 if split_orders > 0: 6397 check_sa = re.sub(r"SET_COUPLINGORDERS_TARGET\(-?\d+\)", 6398 "SET_COUPLINGORDERS_TARGET(%d)"%split_orders,check_sa) 6399 6400 file.write(check_sa) 6401 file.close()
6402 6403 @staticmethod
6404 - def run_initialization(run_dir=None, SubProc_dir=None, infos=None,\ 6405 req_files = ['HelFilter.dat','LoopFilter.dat'], 6406 attempts = [4,15]):
6407 """ Run the initialization of the process in 'run_dir' with success 6408 characterized by the creation of the files req_files in this directory. 6409 The directory containing the driving source code 'check_sa.f'. 6410 The list attempt gives the successive number of PS points the 6411 initialization should be tried with before calling it failed. 6412 Returns the number of PS points which were necessary for the init. 6413 Notice at least run_dir or SubProc_dir must be provided. 6414 A negative attempt number given in input means that quadprec will be 6415 forced for initialization.""" 6416 6417 # If the user does not want detailed info, then set the dictionary 6418 # to a dummy one. 6419 if infos is None: 6420 infos={} 6421 6422 if SubProc_dir is None and run_dir is None: 6423 raise MadGraph5Error, 'At least one of [SubProc_dir,run_dir] must'+\ 6424 ' be provided in run_initialization.' 6425 6426 # If the user does not specify where is check_sa.f, then it is assumed 6427 # to be one levels above run_dir 6428 if SubProc_dir is None: 6429 SubProc_dir = os.path.abspath(pjoin(run_dir,os.pardir)) 6430 6431 if run_dir is None: 6432 directories =[ dir for dir in misc.glob('P[0-9]*', SubProc_dir) 6433 if os.path.isdir(dir) ] 6434 if directories: 6435 run_dir = directories[0] 6436 else: 6437 raise MadGraph5Error, 'Could not find a valid running directory'+\ 6438 ' in %s.'%str(SubProc_dir) 6439 6440 # Use the presence of the file born_matrix.f to decide if it is a 6441 # loop-induced process or not. It's not crucial, but just that because 6442 # of the dynamic adjustment of the ref scale used for deciding what are 6443 # the zero contributions, more points are neeeded for loop-induced. 6444 if not os.path.isfile(pjoin(run_dir,'born_matrix.f')): 6445 if len(attempts)>=1 and attempts[0]<8: 6446 attempts[0]=8 6447 if len(attempts)>=2 and attempts[1]<25: 6448 attempts[1]=25 6449 6450 to_attempt = list(attempts) 6451 to_attempt.reverse() 6452 my_req_files = list(req_files) 6453 6454 MLCardPath = pjoin(SubProc_dir,'MadLoopParams.dat') 6455 if not os.path.isfile(MLCardPath): 6456 raise MadGraph5Error, 'Could not find MadLoopParams.dat at %s.'\ 6457 %MLCardPath 6458 else: 6459 MLCard = banner_mod.MadLoopParam(MLCardPath) 6460 MLCard_orig = banner_mod.MadLoopParam(MLCard) 6461 6462 # Make sure that LoopFilter really is needed. 6463 if not MLCard['UseLoopFilter']: 6464 try: 6465 my_req_files.remove('LoopFilter.dat') 6466 except ValueError: 6467 pass 6468 6469 if MLCard['HelicityFilterLevel']==0: 6470 try: 6471 my_req_files.remove('HelFilter.dat') 6472 except ValueError: 6473 pass 6474 6475 def need_init(): 6476 """ True if init not done yet.""" 6477 proc_prefix_file = open(pjoin(run_dir,'proc_prefix.txt'),'r') 6478 proc_prefix = proc_prefix_file.read() 6479 proc_prefix_file.close() 6480 return any([not os.path.exists(pjoin(run_dir,'MadLoop5_resources', 6481 proc_prefix+fname)) for fname in my_req_files]) or \ 6482 not os.path.isfile(pjoin(run_dir,'check')) or \ 6483 not os.access(pjoin(run_dir,'check'), os.X_OK)
6484 6485 # Check if this is a process without born by checking the presence of the 6486 # file born_matrix.f 6487 is_loop_induced = os.path.exists(pjoin(run_dir,'born_matrix.f')) 6488 6489 # For loop induced processes, always attempt quadruple precision if 6490 # double precision attempts fail and the user didn't specify himself 6491 # quadruple precision initializations attempts 6492 if not any(attempt<0 for attempt in to_attempt): 6493 to_attempt = [-attempt for attempt in to_attempt] + to_attempt 6494 use_quad_prec = 1 6495 curr_attempt = 1 6496 6497 MLCard.set('WriteOutFilters',True) 6498 6499 while to_attempt!=[] and need_init(): 6500 curr_attempt = to_attempt.pop() 6501 # if the attempt is a negative number it means we must force 6502 # quadruple precision at initialization time 6503 if curr_attempt < 0: 6504 use_quad_prec = -1 6505 # In quadruple precision we can lower the ZeroThres threshold 6506 MLCard.set('CTModeInit',4) 6507 MLCard.set('ZeroThres',1e-11) 6508 else: 6509 # Restore the default double precision intialization params 6510 MLCard.set('CTModeInit',1) 6511 MLCard.set('ZeroThres',1e-9) 6512 # Plus one because the filter are written on the next PS point after 6513 curr_attempt = abs(curr_attempt+1) 6514 MLCard.set('MaxAttempts',curr_attempt) 6515 MLCard.write(pjoin(SubProc_dir,'MadLoopParams.dat')) 6516 6517 # initialization is performed. 6518 MadLoopInitializer.fix_PSPoint_in_check(run_dir, read_ps = False, 6519 npoints = curr_attempt) 6520 compile_time, run_time, ram_usage = \ 6521 MadLoopInitializer.make_and_run(run_dir) 6522 if compile_time==None: 6523 logging.error("Failed at running the process in %s."%run_dir) 6524 attempts = None 6525 return None 6526 # Only set process_compilation time for the first compilation. 6527 if 'Process_compilation' not in infos.keys() or \ 6528 infos['Process_compilation']==None: 6529 infos['Process_compilation'] = compile_time 6530 infos['Initialization'] = run_time 6531 6532 MLCard_orig.write(pjoin(SubProc_dir,'MadLoopParams.dat')) 6533 if need_init(): 6534 return None 6535 else: 6536 return use_quad_prec*(curr_attempt-1)
6537 6538 @staticmethod
6539 - def need_MadLoopInit(proc_dir, subproc_prefix='PV'):
6540 """Checks whether the necessary filters are present or not.""" 6541 6542 def need_init(ML_resources_path, proc_prefix, r_files): 6543 """ Returns true if not all required files are present. """ 6544 return any([not os.path.exists(pjoin(ML_resources_path, 6545 proc_prefix+fname)) for fname in r_files])
6546 6547 MLCardPath = pjoin(proc_dir,'SubProcesses','MadLoopParams.dat') 6548 if not os.path.isfile(MLCardPath): 6549 raise MadGraph5Error, 'Could not find MadLoopParams.dat at %s.'\ 6550 %MLCardPath 6551 MLCard = banner_mod.MadLoopParam(MLCardPath) 6552 6553 req_files = ['HelFilter.dat','LoopFilter.dat'] 6554 # Make sure that LoopFilter really is needed. 6555 if not MLCard['UseLoopFilter']: 6556 try: 6557 req_files.remove('LoopFilter.dat') 6558 except ValueError: 6559 pass 6560 if MLCard['HelicityFilterLevel']==0: 6561 try: 6562 req_files.remove('HelFilter.dat') 6563 except ValueError: 6564 pass 6565 6566 for v_folder in glob.iglob(pjoin(proc_dir,'SubProcesses', 6567 '%s*'%subproc_prefix)): 6568 # Make sure it is a valid MadLoop directory 6569 if not os.path.isdir(v_folder) or not os.path.isfile(\ 6570 pjoin(v_folder,'loop_matrix.f')): 6571 continue 6572 proc_prefix_file = open(pjoin(v_folder,'proc_prefix.txt'),'r') 6573 proc_prefix = proc_prefix_file.read() 6574 proc_prefix_file.close() 6575 if need_init(pjoin(proc_dir,'SubProcesses','MadLoop5_resources'), 6576 proc_prefix, req_files): 6577 return True 6578 6579 return False 6580 6581 @staticmethod
6582 - def init_MadLoop(proc_dir, n_PS=None, subproc_prefix='PV', MG_options=None, 6583 interface = None):
6584 """Advanced commands: Compiles and run MadLoop on RAMBO random PS points to initilize the 6585 filters.""" 6586 6587 logger.debug('Compiling Source materials necessary for MadLoop '+ 6588 'initialization.') 6589 # Initialize all the virtuals directory, so as to generate the necessary 6590 # filters (essentially Helcity filter). 6591 # Make sure that the MadLoopCard has the loop induced settings 6592 if interface is None: 6593 misc.compile(arg=['treatCardsLoopNoInit'], cwd=pjoin(proc_dir,'Source')) 6594 else: 6595 interface.do_treatcards('all --no_MadLoopInit') 6596 6597 # First make sure that IREGI and CUTTOOLS are compiled if needed 6598 if os.path.exists(pjoin(proc_dir,'Source','CutTools')): 6599 misc.compile(arg=['libcuttools'],cwd=pjoin(proc_dir,'Source')) 6600 if os.path.exists(pjoin(proc_dir,'Source','IREGI')): 6601 misc.compile(arg=['libiregi'],cwd=pjoin(proc_dir,'Source')) 6602 # Then make sure DHELAS and MODEL are compiled 6603 misc.compile(arg=['libmodel'],cwd=pjoin(proc_dir,'Source')) 6604 misc.compile(arg=['libdhelas'],cwd=pjoin(proc_dir,'Source')) 6605 6606 # Now initialize the MadLoop outputs 6607 logger.info('Initializing MadLoop loop-induced matrix elements '+\ 6608 '(this can take some time)...') 6609 6610 # Setup parallelization 6611 if MG_options: 6612 mcore = cluster.MultiCore(**MG_options) 6613 else: 6614 mcore = cluster.onecore 6615 def run_initialization_wrapper(run_dir, infos, attempts): 6616 if attempts is None: 6617 n_PS = MadLoopInitializer.run_initialization( 6618 run_dir=run_dir, infos=infos) 6619 else: 6620 n_PS = MadLoopInitializer.run_initialization( 6621 run_dir=run_dir, infos=infos, attempts=attempts) 6622 infos['nPS'] = n_PS 6623 return 0
6624 6625 def wait_monitoring(Idle, Running, Done): 6626 if Idle+Running+Done == 0: 6627 return 6628 logger.debug('MadLoop initialization jobs: %d Idle, %d Running, %d Done'\ 6629 %(Idle, Running, Done)) 6630 6631 init_info = {} 6632 # List all virtual folders while making sure they are valid MadLoop folders 6633 VirtualFolders = [f for f in glob.iglob(pjoin(proc_dir,'SubProcesses', 6634 '%s*'%subproc_prefix)) if (os.path.isdir(f) or 6635 os.path.isfile(pjoin(f,'loop_matrix.f')))] 6636 logger.debug("Now Initializing MadLoop matrix element in %d folder%s:"%\ 6637 (len(VirtualFolders),'s' if len(VirtualFolders)>1 else '')) 6638 logger.debug(', '.join("'%s'"%os.path.basename(v_folder) for v_folder in 6639 VirtualFolders)) 6640 for v_folder in VirtualFolders: 6641 init_info[v_folder] = {} 6642 6643 # We try all multiples of n_PS from 1 to max_mult, first in DP and then 6644 # in QP before giving up, or use default values if n_PS is None. 6645 max_mult = 3 6646 if n_PS is None: 6647 # Then use the default list of number of PS points to try 6648 mcore.submit(run_initialization_wrapper, 6649 [pjoin(v_folder), init_info[v_folder], None]) 6650 else: 6651 # Use specific set of PS points 6652 mcore.submit(run_initialization_wrapper, [pjoin(v_folder), 6653 init_info[v_folder], 6654 [n_PS*multiplier for multiplier in range(1,max_mult+1)]]) 6655 6656 # Wait for all jobs to finish. 6657 mcore.wait('',wait_monitoring,update_first=wait_monitoring) 6658 for v_folder in VirtualFolders: 6659 init = init_info[v_folder] 6660 if init['nPS'] is None: 6661 raise MadGraph5Error, 'Failed the initialization of'+\ 6662 " loop-induced matrix element '%s'%s."%\ 6663 (os.path.basename(v_folder),' (using default n_PS points)' if\ 6664 n_PS is None else ' (trying with a maximum of %d PS points)'\ 6665 %(max_mult*n_PS)) 6666 if init['nPS']==0: 6667 logger.debug("Nothing to be done in '%s', all filters already "%\ 6668 os.path.basename(v_folder)+\ 6669 "present (use the '-r' option to force their recomputation)") 6670 else: 6671 logger.debug("'%s' finished using "%os.path.basename(v_folder)+ 6672 '%d PS points (%s), in %.3g(compil.) + %.3g(init.) secs.'%( 6673 abs(init['nPS']),'DP' if init['nPS']>0 else 'QP', 6674 init['Process_compilation'],init['Initialization'])) 6675 6676 logger.info('MadLoop initialization finished.') 6677 6678 AskforEditCard = common_run.AskforEditCard 6679 6680 6681 if '__main__' == __name__: 6682 # Launch the interface without any check if one code is already running. 6683 # This can ONLY run a single command !! 6684 import sys 6685 if not sys.version_info[0] == 2 or sys.version_info[1] < 6: 6686 sys.exit('MadGraph/MadEvent 5 works only with python 2.6 or later (but not python 3.X).\n'+\ 6687 'Please upgrate your version of python.') 6688 6689 import os 6690 import optparse 6691 # Get the directory of the script real path (bin) 6692 # and add it to the current PYTHONPATH 6693 root_path = os.path.dirname(os.path.dirname(os.path.realpath( __file__ ))) 6694 sys.path.insert(0, root_path)
6695 6696 - class MyOptParser(optparse.OptionParser):
6697 - class InvalidOption(Exception): pass
6698 - def error(self, msg=''):
6699 raise MyOptParser.InvalidOption(msg)
6700 # Write out nice usage message if called with -h or --help 6701 usage = "usage: %prog [options] [FILE] " 6702 parser = MyOptParser(usage=usage) 6703 parser.add_option("-l", "--logging", default='INFO', 6704 help="logging level (DEBUG|INFO|WARNING|ERROR|CRITICAL) [%default]") 6705 parser.add_option("","--web", action="store_true", default=False, dest='web', \ 6706 help='force toce to be in secure mode') 6707 parser.add_option("","--debug", action="store_true", default=False, dest='debug', \ 6708 help='force to launch debug mode') 6709 parser_error = '' 6710 done = False 6711 6712 for i in range(len(sys.argv)-1): 6713 try: 6714 (options, args) = parser.parse_args(sys.argv[1:len(sys.argv)-i]) 6715 done = True 6716 except MyOptParser.InvalidOption, error: 6717 pass 6718 else: 6719 args += sys.argv[len(sys.argv)-i:] 6720 if not done: 6721 # raise correct error: 6722 try: 6723 (options, args) = parser.parse_args() 6724 except MyOptParser.InvalidOption, error: 6725 print error 6726 sys.exit(2) 6727 6728 if len(args) == 0: 6729 args = '' 6730 6731 import subprocess 6732 import logging 6733 import logging.config 6734 # Set logging level according to the logging level given by options 6735 #logging.basicConfig(level=vars(logging)[options.logging]) 6736 import internal.coloring_logging 6737 try: 6738 if __debug__ and options.logging == 'INFO': 6739 options.logging = 'DEBUG' 6740 if options.logging.isdigit(): 6741 level = int(options.logging) 6742 else: 6743 level = eval('logging.' + options.logging) 6744 print os.path.join(root_path, 'internal', 'me5_logging.conf') 6745 logging.config.fileConfig(os.path.join(root_path, 'internal', 'me5_logging.conf')) 6746 logging.root.setLevel(level) 6747 logging.getLogger('madgraph').setLevel(level) 6748 except: 6749 raise 6750 pass 6751 6752 # Call the cmd interface main loop 6753 try: 6754 if args: 6755 # a single command is provided 6756 if '--web' in args: 6757 i = args.index('--web') 6758 args.pop(i) 6759 cmd_line = MadEventCmd(force_run=True) 6760 else: 6761 cmd_line = MadEventCmdShell(force_run=True) 6762 if not hasattr(cmd_line, 'do_%s' % args[0]): 6763 if parser_error: 6764 print parser_error 6765 print 'and %s can not be interpreted as a valid command.' % args[0] 6766 else: 6767 print 'ERROR: %s not a valid command. Please retry' % args[0] 6768 else: 6769 cmd_line.use_rawinput = False 6770 cmd_line.run_cmd(' '.join(args)) 6771 cmd_line.run_cmd('quit') 6772 6773 except KeyboardInterrupt: 6774 print 'quit on KeyboardInterrupt' 6775 pass 6776