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, keep=True, 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 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 self.exec_cmd('madanalysis5_parton --no_default', postcmd=False, printcmd=False) 2124 # shower launches pgs/delphes if needed 2125 self.exec_cmd('shower --no_default', postcmd=False, printcmd=False) 2126 self.exec_cmd('madanalysis5_hadron --no_default', postcmd=False, printcmd=False) 2127 self.store_result() 2128 2129 if self.param_card_iterator: 2130 param_card_iterator = self.param_card_iterator 2131 self.param_card_iterator = [] 2132 with misc.TMP_variable(self, 'allow_notification_center', False): 2133 param_card_iterator.store_entry(self.run_name, self.results.current['cross']) 2134 #check if the param_card defines a scan. 2135 orig_name = self.run_name 2136 for card in param_card_iterator: 2137 path = pjoin(self.me_dir,'Cards','param_card.dat') 2138 card.write(pjoin(self.me_dir,'Cards','param_card.dat')) 2139 self.check_param_card(path, dependent=True) 2140 next_name = param_card_iterator.get_next_name(self.run_name) 2141 try: 2142 self.exec_cmd("generate_events -f %s" % next_name, 2143 precmd=True, postcmd=True,errorhandling=False) 2144 except ZeroResult: 2145 param_card_iterator.store_entry(self.run_name, 0) 2146 else: 2147 param_card_iterator.store_entry(self.run_name, self.results.current['cross']) 2148 param_card_iterator.write(pjoin(self.me_dir,'Cards','param_card.dat')) 2149 name = misc.get_scan_name(orig_name, self.run_name) 2150 path = pjoin(self.me_dir, 'Events','scan_%s.txt' % name) 2151 logger.info("write all cross-section results in %s" % path ,'$MG:color:BLACK') 2152 param_card_iterator.write_summary(path) 2153 2154 2155 if self.allow_notification_center: 2156 misc.apple_notify('Run %s finished' % os.path.basename(self.me_dir), 2157 '%s: %s +- %s ' % (self.results.current['run_name'], 2158 self.results.current['cross'], 2159 self.results.current['error']))
2160
2161 - def do_initMadLoop(self,line):
2162 """Compile and run MadLoop for a certain number of PS point so as to 2163 initialize MadLoop (setup the zero helicity and loop filter.)""" 2164 2165 args = line.split() 2166 # Check argument's validity 2167 options = self.check_initMadLoop(args) 2168 2169 if not options['force']: 2170 self.ask_edit_cards(['MadLoopParams.dat'], mode='fixed', plot=False) 2171 self.exec_cmd('treatcards loop --no_MadLoopInit') 2172 2173 if options['refresh']: 2174 for filter in misc.glob('*Filter*', 2175 pjoin(self.me_dir,'SubProcesses','MadLoop5_resources')): 2176 logger.debug("Resetting filter '%s'."%os.path.basename(filter)) 2177 os.remove(filter) 2178 2179 MLCard = banner_mod.MadLoopParam(pjoin(self.me_dir, 2180 'Cards','MadLoopParams.dat')) 2181 if options['nPS'] is None: 2182 options['nPS'] = MLCard['CheckCycle']+2 2183 elif options['nPS'] < MLCard['CheckCycle']+2: 2184 new_n_PS = MLCard['CheckCycle']+2 2185 logger.debug('Hard-setting user-defined n_PS (%d) to %d, because '\ 2186 %(options['nPS'],new_n_PS)+"of the 'CheckCycle' value (%d) "%MLCard['CheckCycle']+\ 2187 "specified in the ML param card.") 2188 options['nPS'] = new_n_PS 2189 2190 MadLoopInitializer.init_MadLoop(self.me_dir,n_PS=options['nPS'], 2191 subproc_prefix='PV', MG_options=self.options, interface=self)
2192
2193 - def do_launch(self, line, *args, **opt):
2194 """Main Commands: exec generate_events for 2>N and calculate_width for 1>N""" 2195 2196 if self.ninitial == 1: 2197 logger.info("Note that since 2.3. The launch for 1>N pass in event generation\n"+ 2198 " To have the previous behavior use the calculate_decay_widths function") 2199 # self.do_calculate_decay_widths(line, *args, **opt) 2200 #else: 2201 self.do_generate_events(line, *args, **opt)
2202
2203 - def print_results_in_shell(self, data):
2204 """Have a nice results prints in the shell, 2205 data should be of type: gen_crossxhtml.OneTagResults""" 2206 2207 if not data: 2208 return 2209 2210 if data['run_statistics']: 2211 globalstat = sum_html.RunStatistics() 2212 2213 logger.info(" " ) 2214 logger.debug(" === Run statistics summary ===") 2215 for key, value in data['run_statistics'].items(): 2216 globalstat.aggregate_statistics(value) 2217 level = 5 2218 if value.has_warning(): 2219 level = 10 2220 logger.log(level, value.nice_output(str('/'.join([key[0],'G%s'%key[1]]))).\ 2221 replace(' statistics','')) 2222 logger.info(" " ) 2223 logger.debug(globalstat.nice_output('combined', no_warning=True)) 2224 if globalstat.has_warning(): 2225 logger.warning(globalstat.get_warning_text()) 2226 logger.info(" ") 2227 2228 2229 logger.info(" === Results Summary for run: %s tag: %s ===\n" % (data['run_name'],data['tag'])) 2230 2231 total_time = int(sum(_['cumulative_timing'] for _ in data['run_statistics'].values())) 2232 if total_time > 0: 2233 logger.info(" Cumulative sequential time for this run: %s"%misc.format_time(total_time)) 2234 2235 if self.ninitial == 1: 2236 logger.info(" Width : %.4g +- %.4g GeV" % (data['cross'], data['error'])) 2237 else: 2238 logger.info(" Cross-section : %.4g +- %.4g pb" % (data['cross'], data['error'])) 2239 logger.info(" Nb of events : %s" % data['nb_event'] ) 2240 2241 if data['run_mode']=='madevent': 2242 if data['cross_pythia'] and data['nb_event_pythia']: 2243 if data['cross_pythia'] == -1: 2244 path = pjoin(self.me_dir, 'Events', self.run_name, '%s_merged_xsecs.txt' % self.run_tag) 2245 cross_sections = {} 2246 if os.path.exists(path): 2247 for line in open(path): 2248 split = line.split() 2249 if len(split)!=3: 2250 continue 2251 scale, cross, error = split 2252 cross_sections[float(scale)] = (float(cross), float(error)) 2253 if len(cross_sections)>0: 2254 logger.info(' Pythia8 merged cross-sections are:') 2255 for scale in sorted(cross_sections.keys()): 2256 logger.info(' > Merging scale = %-6.4g : %-11.5g +/- %-7.2g [pb]'%\ 2257 (scale,cross_sections[scale][0],cross_sections[scale][1])) 2258 2259 else: 2260 if self.ninitial == 1: 2261 logger.info(" Matched width : %.4g +- %.4g GeV" % (data['cross_pythia'], data['error_pythia'])) 2262 else: 2263 logger.info(" Matched cross-section : %.4g +- %.4g pb" % (data['cross_pythia'], data['error_pythia'])) 2264 logger.info(" Nb of events after matching/merging : %d" % int(data['nb_event_pythia'])) 2265 if self.run_card['use_syst'] in self.true and \ 2266 (int(self.run_card['ickkw'])==1 or self.run_card['ktdurham']>0.0 2267 or self.run_card['ptlund']>0.0): 2268 logger.info(" Notice that because Systematics computation is turned on, the merging did not veto events but modified their weights instead.\n"+\ 2269 " The resulting hepmc/stdhep file should therefore be use with those weights.") 2270 else: 2271 logger.info(" Nb of events after merging : %s" % data['nb_event_pythia']) 2272 2273 logger.info(" " )
2274
2275 - def print_results_in_file(self, data, path, mode='w', format='full'):
2276 """Have a nice results prints in the shell, 2277 data should be of type: gen_crossxhtml.OneTagResults""" 2278 if not data: 2279 return 2280 2281 fsock = open(path, mode) 2282 2283 if data['run_statistics']: 2284 logger.debug(" === Run statistics summary ===") 2285 for key, value in data['run_statistics'].items(): 2286 logger.debug(value.nice_output(str('/'.join([key[0],'G%s'%key[1]]))).\ 2287 replace(' statistics','')) 2288 logger.info(" " ) 2289 2290 if format == "full": 2291 fsock.write(" === Results Summary for run: %s tag: %s process: %s ===\n" % \ 2292 (data['run_name'],data['tag'], os.path.basename(self.me_dir))) 2293 2294 if self.ninitial == 1: 2295 fsock.write(" Width : %.4g +- %.4g GeV\n" % (data['cross'], data['error'])) 2296 else: 2297 fsock.write(" Cross-section : %.4g +- %.4g pb\n" % (data['cross'], data['error'])) 2298 fsock.write(" Nb of events : %s\n" % data['nb_event'] ) 2299 if data['cross_pythia'] and data['nb_event_pythia']: 2300 if self.ninitial == 1: 2301 fsock.write(" Matched Width : %.4g +- %.4g GeV\n" % (data['cross_pythia'], data['error_pythia'])) 2302 else: 2303 fsock.write(" Matched Cross-section : %.4g +- %.4g pb\n" % (data['cross_pythia'], data['error_pythia'])) 2304 fsock.write(" Nb of events after Matching : %s\n" % data['nb_event_pythia']) 2305 fsock.write(" \n" ) 2306 elif format == "short": 2307 if mode == "w": 2308 fsock.write("# run_name tag cross error Nb_event cross_after_matching nb_event_after matching\n") 2309 2310 if data['cross_pythia'] and data['nb_event_pythia']: 2311 text = "%(run_name)s %(tag)s %(cross)s %(error)s %(nb_event)s %(cross_pythia)s %(nb_event_pythia)s\n" 2312 else: 2313 text = "%(run_name)s %(tag)s %(cross)s %(error)s %(nb_event)s\n" 2314 fsock.write(text % data)
2315 2316 ############################################################################
2317 - def do_calculate_decay_widths(self, line):
2318 """Main Commands: launch decay width calculation and automatic inclusion of 2319 calculated widths and BRs in the param_card.""" 2320 2321 args = self.split_arg(line) 2322 # Check argument's validity 2323 accuracy = self.check_calculate_decay_widths(args) 2324 self.ask_run_configuration('parton') 2325 self.banner = None 2326 if not args: 2327 # No run name assigned -> assigned one automaticaly 2328 self.set_run_name(self.find_available_run_name(self.me_dir)) 2329 else: 2330 self.set_run_name(args[0], reload_card=True) 2331 args.pop(0) 2332 2333 self.configure_directory() 2334 2335 # Running gridpack warmup 2336 opts=[('accuracy', accuracy), # default 0.01 2337 ('points', 1000), 2338 ('iterations',9)] 2339 2340 logger.info('Calculating decay widths with run name %s' % self.run_name) 2341 2342 self.exec_cmd('survey %s %s' % \ 2343 (self.run_name, 2344 " ".join(['--' + opt + '=' + str(val) for (opt,val) \ 2345 in opts])), 2346 postcmd=False) 2347 self.refine_mode = "old" # specify how to combine event 2348 self.exec_cmd('combine_events', postcmd=False) 2349 self.exec_cmd('store_events', postcmd=False) 2350 2351 self.collect_decay_widths() 2352 self.print_results_in_shell(self.results.current) 2353 self.update_status('calculate_decay_widths done', 2354 level='parton', makehtml=False)
2355 2356 2357 ############################################################################
2358 - def collect_decay_widths(self):
2359 """ Collect the decay widths and calculate BRs for all particles, and put 2360 in param_card form. 2361 """ 2362 2363 particle_dict = {} # store the results 2364 run_name = self.run_name 2365 2366 # Looping over the Subprocesses 2367 for P_path in SubProcesses.get_subP(self.me_dir): 2368 ids = SubProcesses.get_subP_ids(P_path) 2369 # due to grouping we need to compute the ratio factor for the 2370 # ungroup resutls (that we need here). Note that initial particles 2371 # grouping are not at the same stage as final particle grouping 2372 nb_output = len(ids) / (len(set([p[0] for p in ids]))) 2373 results = open(pjoin(P_path, run_name + '_results.dat')).read().split('\n')[0] 2374 result = float(results.strip().split(' ')[0]) 2375 for particles in ids: 2376 try: 2377 particle_dict[particles[0]].append([particles[1:], result/nb_output]) 2378 except KeyError: 2379 particle_dict[particles[0]] = [[particles[1:], result/nb_output]] 2380 2381 self.update_width_in_param_card(particle_dict, 2382 initial = pjoin(self.me_dir, 'Cards', 'param_card.dat'), 2383 output=pjoin(self.me_dir, 'Events', run_name, "param_card.dat"))
2384 2385 @staticmethod
2386 - def update_width_in_param_card(decay_info, initial=None, output=None):
2387 # Open the param_card.dat and insert the calculated decays and BRs 2388 2389 if not output: 2390 output = initial 2391 2392 param_card_file = open(initial) 2393 param_card = param_card_file.read().split('\n') 2394 param_card_file.close() 2395 2396 decay_lines = [] 2397 line_number = 0 2398 # Read and remove all decays from the param_card 2399 while line_number < len(param_card): 2400 line = param_card[line_number] 2401 if line.lower().startswith('decay'): 2402 # Read decay if particle in decay_info 2403 # DECAY 6 1.455100e+00 2404 line = param_card.pop(line_number) 2405 line = line.split() 2406 particle = 0 2407 if int(line[1]) not in decay_info: 2408 try: # If formatting is wrong, don't want this particle 2409 particle = int(line[1]) 2410 width = float(line[2]) 2411 except Exception: 2412 particle = 0 2413 # Read BRs for this decay 2414 line = param_card[line_number] 2415 while line.startswith('#') or line.startswith(' '): 2416 line = param_card.pop(line_number) 2417 if not particle or line.startswith('#'): 2418 line=param_card[line_number] 2419 continue 2420 # 6.668201e-01 3 5 2 -1 2421 line = line.split() 2422 try: # Remove BR if formatting is wrong 2423 partial_width = float(line[0])*width 2424 decay_products = [int(p) for p in line[2:2+int(line[1])]] 2425 except Exception: 2426 line=param_card[line_number] 2427 continue 2428 try: 2429 decay_info[particle].append([decay_products, partial_width]) 2430 except KeyError: 2431 decay_info[particle] = [[decay_products, partial_width]] 2432 if line_number == len(param_card): 2433 break 2434 line=param_card[line_number] 2435 if particle and particle not in decay_info: 2436 # No decays given, only total width 2437 decay_info[particle] = [[[], width]] 2438 else: # Not decay 2439 line_number += 1 2440 # Clean out possible remaining comments at the end of the card 2441 while not param_card[-1] or param_card[-1].startswith('#'): 2442 param_card.pop(-1) 2443 2444 # Append calculated and read decays to the param_card 2445 param_card.append("#\n#*************************") 2446 param_card.append("# Decay widths *") 2447 param_card.append("#*************************") 2448 for key in sorted(decay_info.keys()): 2449 width = sum([r for p,r in decay_info[key]]) 2450 param_card.append("#\n# PDG Width") 2451 param_card.append("DECAY %i %e" % (key, width.real)) 2452 if not width: 2453 continue 2454 if decay_info[key][0][0]: 2455 param_card.append("# BR NDA ID1 ID2 ...") 2456 brs = [[(val[1]/width).real, val[0]] for val in decay_info[key] if val[1]] 2457 for val in sorted(brs, reverse=True): 2458 param_card.append(" %e %i %s # %s" % 2459 (val[0].real, len(val[1]), 2460 " ".join([str(v) for v in val[1]]), 2461 val[0] * width 2462 )) 2463 decay_table = open(output, 'w') 2464 decay_table.write("\n".join(param_card) + "\n") 2465 decay_table.close() 2466 logger.info("Results written to %s" % output)
2467 2468 2469 ############################################################################
2470 - def do_multi_run(self, line):
2471 2472 args = self.split_arg(line) 2473 # Check argument's validity 2474 mode = self.check_multi_run(args) 2475 nb_run = args.pop(0) 2476 if nb_run == 1: 2477 logger.warn("'multi_run 1' command is not optimal. Think of using generate_events instead") 2478 self.ask_run_configuration(mode) 2479 2480 self.check_survey(args, cmd='multi_run') 2481 main_name = self.run_name 2482 # check if the param_card requires a scan over parameter. 2483 path=pjoin(self.me_dir, 'Cards', 'param_card.dat') 2484 self.check_param_card(path, run=False) 2485 #store it locally to avoid relaunch 2486 param_card_iterator, self.param_card_iterator = self.param_card_iterator, [] 2487 2488 crossoversig = 0 2489 inv_sq_err = 0 2490 nb_event = 0 2491 for i in range(nb_run): 2492 self.nb_refine = 0 2493 self.exec_cmd('generate_events %s_%s -f' % (main_name, i), postcmd=False) 2494 # Update collected value 2495 nb_event += int(self.results[self.run_name][-1]['nb_event']) 2496 self.results.add_detail('nb_event', nb_event , run=main_name) 2497 cross = self.results[self.run_name][-1]['cross'] 2498 error = self.results[self.run_name][-1]['error'] + 1e-99 2499 crossoversig+=cross/error**2 2500 inv_sq_err+=1.0/error**2 2501 self.results[main_name][-1]['cross'] = crossoversig/inv_sq_err 2502 self.results[main_name][-1]['error'] = math.sqrt(1.0/inv_sq_err) 2503 self.results.def_current(main_name) 2504 self.run_name = main_name 2505 self.update_status("Merging LHE files", level='parton') 2506 try: 2507 os.mkdir(pjoin(self.me_dir,'Events', self.run_name)) 2508 except Exception: 2509 pass 2510 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' 2511 % {'bin': self.dirbin, 'event': pjoin(self.me_dir,'Events'), 2512 'name': self.run_name}) 2513 2514 eradir = self.options['exrootanalysis_path'] 2515 if eradir and misc.is_executable(pjoin(eradir,'ExRootLHEFConverter')): 2516 self.update_status("Create Root file", level='parton') 2517 misc.gunzip('%s/%s/unweighted_events.lhe.gz' % 2518 (pjoin(self.me_dir,'Events'), self.run_name)) 2519 2520 self.create_root_file('%s/unweighted_events.lhe' % self.run_name, 2521 '%s/unweighted_events.root' % self.run_name) 2522 2523 path = pjoin(self.me_dir, "Events", self.run_name, "unweighted_events.lhe") 2524 self.create_plot('parton', path, 2525 pjoin(self.me_dir, 'HTML',self.run_name, 'plots_parton.html') 2526 ) 2527 2528 2529 if not os.path.exists('%s.gz' % path): 2530 misc.gzip(path) 2531 2532 self.update_status('', level='parton') 2533 self.print_results_in_shell(self.results.current) 2534 2535 if param_card_iterator: 2536 2537 param_card_iterator.store_entry(self.run_name, self.results.current['cross']) 2538 #check if the param_card defines a scan. 2539 orig_name=self.run_name 2540 for card in param_card_iterator: 2541 card.write(pjoin(self.me_dir,'Cards','param_card.dat')) 2542 self.exec_cmd("multi_run %s -f " % nb_run ,precmd=True, postcmd=True,errorhandling=False) 2543 param_card_iterator.store_entry(self.run_name, self.results.current['cross']) 2544 param_card_iterator.write(pjoin(self.me_dir,'Cards','param_card.dat')) 2545 scan_name = misc.get_scan_name(orig_name, self.run_name) 2546 path = pjoin(self.me_dir, 'Events','scan_%s.txt' % scan_name) 2547 logger.info("write all cross-section results in %s" % path, '$MG:color:BLACK') 2548 param_card_iterator.write_summary(path)
2549 2550 2551 ############################################################################
2552 - def do_treatcards(self, line, mode=None, opt=None):
2553 """Advanced commands: create .inc files from param_card.dat/run_card.dat""" 2554 2555 if not mode and not opt: 2556 args = self.split_arg(line) 2557 mode, opt = self.check_treatcards(args) 2558 2559 # To decide whether to refresh MadLoop's helicity filters, it is necessary 2560 # to check if the model parameters where modified or not, before doing 2561 # anything else. 2562 need_MadLoopFilterUpdate = False 2563 # Just to record what triggered the reinitialization of MadLoop for a 2564 # nice debug message. 2565 type_of_change = '' 2566 if not opt['forbid_MadLoopInit'] and self.proc_characteristics['loop_induced'] \ 2567 and mode in ['loop', 'all']: 2568 paramDat = pjoin(self.me_dir, 'Cards','param_card.dat') 2569 paramInc = pjoin(opt['output_dir'], 'param_card.inc') 2570 if (not os.path.isfile(paramDat)) or (not os.path.isfile(paramInc)) or \ 2571 (os.path.getmtime(paramDat)-os.path.getmtime(paramInc)) > 0.0: 2572 need_MadLoopFilterUpdate = True 2573 type_of_change = 'model' 2574 2575 ML_in = pjoin(self.me_dir, 'Cards', 'MadLoopParams.dat') 2576 ML_out = pjoin(self.me_dir,"SubProcesses", 2577 "MadLoop5_resources", "MadLoopParams.dat") 2578 if (not os.path.isfile(ML_in)) or (not os.path.isfile(ML_out)) or \ 2579 (os.path.getmtime(ML_in)-os.path.getmtime(ML_out)) > 0.0: 2580 need_MadLoopFilterUpdate = True 2581 type_of_change = 'MadLoop' 2582 2583 #check if no 'Auto' are present in the file 2584 self.check_param_card(pjoin(self.me_dir, 'Cards','param_card.dat')) 2585 2586 if mode in ['param', 'all']: 2587 model = self.find_model_name() 2588 tmp_model = os.path.basename(model) 2589 if tmp_model == 'mssm' or tmp_model.startswith('mssm-'): 2590 if not '--param_card=' in line: 2591 param_card = pjoin(self.me_dir, 'Cards','param_card.dat') 2592 mg5_param = pjoin(self.me_dir, 'Source', 'MODEL', 'MG5_param.dat') 2593 check_param_card.convert_to_mg5card(param_card, mg5_param) 2594 check_param_card.check_valid_param_card(mg5_param) 2595 opt['param_card'] = pjoin(self.me_dir, 'Source', 'MODEL', 'MG5_param.dat') 2596 else: 2597 check_param_card.check_valid_param_card(opt['param_card']) 2598 2599 logger.debug('write compile file for card: %s' % opt['param_card']) 2600 param_card = check_param_card.ParamCard(opt['param_card']) 2601 outfile = pjoin(opt['output_dir'], 'param_card.inc') 2602 ident_card = pjoin(self.me_dir,'Cards','ident_card.dat') 2603 if os.path.isfile(pjoin(self.me_dir,'bin','internal','ufomodel','restrict_default.dat')): 2604 default = pjoin(self.me_dir,'bin','internal','ufomodel','restrict_default.dat') 2605 elif os.path.isfile(pjoin(self.me_dir,'bin','internal','ufomodel','param_card.dat')): 2606 default = pjoin(self.me_dir,'bin','internal','ufomodel','param_card.dat') 2607 elif not os.path.exists(pjoin(self.me_dir,'bin','internal','ufomodel')): 2608 fsock = open(pjoin(self.me_dir,'Source','param_card.inc'),'w') 2609 fsock.write(' ') 2610 fsock.close() 2611 if mode == 'all': 2612 self.do_treatcards('', 'run', opt) 2613 return 2614 else: 2615 devnull = open(os.devnull,'w') 2616 subprocess.call([sys.executable, 'write_param_card.py'], 2617 cwd=pjoin(self.me_dir,'bin','internal','ufomodel'), 2618 stdout=devnull) 2619 devnull.close() 2620 default = pjoin(self.me_dir,'bin','internal','ufomodel','param_card.dat') 2621 2622 need_mp = self.proc_characteristics['loop_induced'] 2623 param_card.write_inc_file(outfile, ident_card, default, need_mp=need_mp) 2624 2625 2626 if mode in ['run', 'all']: 2627 if not hasattr(self, 'run_card'): 2628 run_card = banner_mod.RunCard(opt['run_card']) 2629 else: 2630 run_card = self.run_card 2631 if self.ninitial == 1: 2632 run_card['lpp1'] = 0 2633 run_card['lpp2'] = 0 2634 run_card['ebeam1'] = 0 2635 run_card['ebeam2'] = 0 2636 2637 # Ensure that the bias parameters has all the required input from the 2638 # run_card 2639 if run_card['bias_module'].lower() not in ['dummy','none']: 2640 # Using basename here means that the module will not be overwritten if already existing. 2641 bias_module_path = pjoin(self.me_dir,'Source','BIAS', 2642 os.path.basename(run_card['bias_module'])) 2643 if not os.path.isdir(bias_module_path): 2644 if not os.path.isdir(run_card['bias_module']): 2645 raise InvalidCmd("The bias module at '%s' cannot be found."%run_card['bias_module']) 2646 else: 2647 for mandatory_file in ['makefile','%s.f'%os.path.basename(run_card['bias_module'])]: 2648 if not os.path.isfile(pjoin(run_card['bias_module'],mandatory_file)): 2649 raise InvalidCmd("Could not find the mandatory file '%s' in bias module '%s'."%( 2650 mandatory_file,run_card['bias_module'])) 2651 shutil.copytree(run_card['bias_module'], pjoin(self.me_dir,'Source','BIAS', 2652 os.path.basename(run_card['bias_module']))) 2653 2654 #check expected parameters for the module. 2655 default_bias_parameters = {} 2656 start, last = False,False 2657 for line in open(pjoin(bias_module_path,'%s.f'%os.path.basename(bias_module_path))): 2658 if start and last: 2659 break 2660 if not start and not re.search('c\s*parameters\s*=\s*{',line, re.I): 2661 continue 2662 start = True 2663 if not line.startswith('C'): 2664 continue 2665 line = line[1:] 2666 if '{' in line: 2667 line = line.split('{')[-1] 2668 # split for } ! # 2669 split_result = re.split('(\}|!|\#)', line,1, re.M) 2670 line = split_result[0] 2671 sep = split_result[1] if len(split_result)>1 else None 2672 if sep == '}': 2673 last = True 2674 if ',' in line: 2675 for pair in line.split(','): 2676 if not pair.strip(): 2677 continue 2678 x,y =pair.split(':') 2679 x=x.strip() 2680 if x.startswith(('"',"'")) and x.endswith(x[0]): 2681 x = x[1:-1] 2682 default_bias_parameters[x] = y 2683 elif ':' in line: 2684 x,y = line.split(':') 2685 x = x.strip() 2686 if x.startswith(('"',"'")) and x.endswith(x[0]): 2687 x = x[1:-1] 2688 default_bias_parameters[x] = y 2689 for key,value in run_card['bias_parameters'].items(): 2690 if key not in default_bias_parameters: 2691 logger.warning('%s not supported by the bias module. We discard this entry.', key) 2692 else: 2693 default_bias_parameters[key] = value 2694 run_card['bias_parameters'] = default_bias_parameters 2695 2696 2697 # Finally write the include file 2698 run_card.write_include_file(opt['output_dir']) 2699 2700 2701 if self.proc_characteristics['loop_induced'] and mode in ['loop', 'all']: 2702 self.MadLoopparam = banner_mod.MadLoopParam(pjoin(self.me_dir, 2703 'Cards', 'MadLoopParams.dat')) 2704 # The writing out of MadLoop filter is potentially dangerous 2705 # when running in multi-core with a central disk. So it is turned 2706 # off here. If these filters were not initialized then they will 2707 # have to be re-computed at the beginning of each run. 2708 if 'WriteOutFilters' in self.MadLoopparam.user_set and \ 2709 self.MadLoopparam.get('WriteOutFilters'): 2710 logger.info( 2711 """You chose to have MadLoop writing out filters. 2712 Beware that this can be dangerous for local multicore runs.""") 2713 self.MadLoopparam.set('WriteOutFilters',False, changeifuserset=False) 2714 2715 # The conservative settings below for 'CTModeInit' and 'ZeroThres' 2716 # help adress issues for processes like g g > h z, and g g > h g 2717 # where there are some helicity configuration heavily suppressed 2718 # (by several orders of magnitude) so that the helicity filter 2719 # needs high numerical accuracy to correctly handle this spread in 2720 # magnitude. Also, because one cannot use the Born as a reference 2721 # scale, it is better to force quadruple precision *for the 2722 # initialization points only*. This avoids numerical accuracy issues 2723 # when setting up the helicity filters and does not significantly 2724 # slow down the run. 2725 # self.MadLoopparam.set('CTModeInit',4, changeifuserset=False) 2726 # Consequently, we can allow for a finer threshold for vanishing 2727 # helicity configuration 2728 # self.MadLoopparam.set('ZeroThres',1.0e-11, changeifuserset=False) 2729 2730 # It is a bit superficial to use the level 2 which tries to numerically 2731 # map matching helicities (because of CP symmetry typically) together. 2732 # It is useless in the context of MC over helicities and it can 2733 # potentially make the helicity double checking fail. 2734 self.MadLoopparam.set('HelicityFilterLevel',1, changeifuserset=False) 2735 2736 # To be on the safe side however, we ask for 4 consecutive matching 2737 # helicity filters. 2738 self.MadLoopparam.set('CheckCycle',4, changeifuserset=False) 2739 2740 # For now it is tricky to have each channel performing the helicity 2741 # double check. What we will end up doing is probably some kind 2742 # of new initialization round at the beginning of each launch 2743 # command, to reset the filters. 2744 self.MadLoopparam.set('DoubleCheckHelicityFilter',False, 2745 changeifuserset=False) 2746 2747 # Thanks to TIR recycling, TIR is typically much faster for Loop-induced 2748 # processes when not doing MC over helicities, so that we place OPP last. 2749 if not hasattr(self, 'run_card'): 2750 run_card = banner_mod.RunCard(opt['run_card']) 2751 else: 2752 run_card = self.run_card 2753 if run_card['nhel'] == 0: 2754 if 'MLReductionLib' in self.MadLoopparam.user_set and \ 2755 (self.MadLoopparam.get('MLReductionLib').startswith('1') or 2756 self.MadLoopparam.get('MLReductionLib').startswith('6')): 2757 logger.warning( 2758 """You chose to set the preferred reduction technique in MadLoop to be OPP (see parameter MLReductionLib). 2759 Beware that this can bring significant slowdown; the optimal choice --when not MC over helicity-- being to first start with TIR reduction.""") 2760 # We do not include GOLEM for now since it cannot recycle TIR coefs yet. 2761 self.MadLoopparam.set('MLReductionLib','7|6|1', changeifuserset=False) 2762 else: 2763 if 'MLReductionLib' in self.MadLoopparam.user_set and \ 2764 not (self.MadLoopparam.get('MLReductionLib').startswith('1') or 2765 self.MadLoopparam.get('MLReductionLib').startswith('6')): 2766 logger.warning( 2767 """You chose to set the preferred reduction technique in MadLoop to be different than OPP (see parameter MLReductionLib). 2768 Beware that this can bring significant slowdown; the optimal choice --when MC over helicity-- being to first start with OPP reduction.""") 2769 self.MadLoopparam.set('MLReductionLib','6|7|1', changeifuserset=False) 2770 2771 # Also TIR cache will only work when NRotations_DP=0 (but only matters 2772 # when not MC-ing over helicities) so it will be hard-reset by MadLoop 2773 # to zero when not MC-ing over helicities, unless the parameter 2774 # Force_ML_Helicity_Sum is set to True in the matrix<i>.f codes. 2775 if run_card['nhel'] == 0: 2776 if ('NRotations_DP' in self.MadLoopparam.user_set and \ 2777 self.MadLoopparam.get('NRotations_DP')!=0) or \ 2778 ('NRotations_QP' in self.MadLoopparam.user_set and \ 2779 self.MadLoopparam.get('NRotations_QP')!=0): 2780 logger.warning( 2781 """You chose to also use a lorentz rotation for stability tests (see parameter NRotations_[DP|QP]). 2782 Beware that, for optimization purposes, MadEvent uses manual TIR cache clearing which is not compatible 2783 with the lorentz rotation stability test. The number of these rotations to be used will be reset to 2784 zero by MadLoop. You can avoid this by changing the parameter 'FORCE_ML_HELICITY_SUM' int he matrix<i>.f 2785 files to be .TRUE. so that the sum over helicity configurations is performed within MadLoop (in which case 2786 the helicity of final state particles cannot be speicfied in the LHE file.""") 2787 self.MadLoopparam.set('NRotations_DP',0,changeifuserset=False) 2788 self.MadLoopparam.set('NRotations_QP',0,changeifuserset=False) 2789 else: 2790 # When MC-ing over helicities, the manual TIR cache clearing is 2791 # not necessary, so that one can use the lorentz check 2792 # Using NRotations_DP=1 slows down the code by close to 100% 2793 # but it is typicaly safer. 2794 # self.MadLoopparam.set('NRotations_DP',0,changeifuserset=False) 2795 # Revert to the above to be slightly less robust but twice faster. 2796 self.MadLoopparam.set('NRotations_DP',1,changeifuserset=False) 2797 self.MadLoopparam.set('NRotations_QP',0,changeifuserset=False) 2798 2799 # Finally, the stability tests are slightly less reliable for process 2800 # with less or equal than 4 final state particles because the 2801 # accessible kinematic is very limited (i.e. lorentz rotations don't 2802 # shuffle invariants numerics much). In these cases, we therefore 2803 # increase the required accuracy to 10^-7. 2804 # This is important for getting g g > z z [QCD] working with a 2805 # ptheavy cut as low as 1 GeV. 2806 if self.proc_characteristics['nexternal']<=4: 2807 if ('MLStabThres' in self.MadLoopparam.user_set and \ 2808 self.MadLoopparam.get('MLStabThres')>1.0e-7): 2809 logger.warning( 2810 """You chose to increase the default value of the MadLoop parameter 'MLStabThres' above 1.0e-7. 2811 Stability tests can be less reliable on the limited kinematic of processes with less or equal 2812 than four external legs, so this is not recommended (especially not for g g > z z).""") 2813 self.MadLoopparam.set('MLStabThres',1.0e-7,changeifuserset=False) 2814 else: 2815 self.MadLoopparam.set('MLStabThres',1.0e-4,changeifuserset=False) 2816 2817 #write the output file 2818 self.MadLoopparam.write(pjoin(self.me_dir,"SubProcesses","MadLoop5_resources", 2819 "MadLoopParams.dat")) 2820 2821 if self.proc_characteristics['loop_induced'] and mode in ['loop', 'all']: 2822 # Now Update MadLoop filters if necessary (if modifications were made to 2823 # the model parameters). 2824 if need_MadLoopFilterUpdate: 2825 logger.debug('Changes to the %s parameters'%type_of_change+\ 2826 ' have been detected. Madevent will then now reinitialize'+\ 2827 ' MadLoop filters.') 2828 self.exec_cmd('initMadLoop -r -f') 2829 # The need_MadLoopInit condition is just there so as to avoid useless 2830 # printout if there is not initialization to be performed. But even 2831 # without it, and because we call 'initMadLoop' without the '-r' option 2832 # no time would be wasted anyway, since the existing filters would not 2833 # be overwritten. 2834 elif not opt['forbid_MadLoopInit'] and \ 2835 MadLoopInitializer.need_MadLoopInit(self.me_dir): 2836 self.exec_cmd('initMadLoop -f')
2837 2838 ############################################################################
2839 - def do_survey(self, line):
2840 """Advanced commands: launch survey for the current process """ 2841 2842 2843 args = self.split_arg(line) 2844 # Check argument's validity 2845 self.check_survey(args) 2846 # initialize / remove lhapdf mode 2847 2848 if os.path.exists(pjoin(self.me_dir,'error')): 2849 os.remove(pjoin(self.me_dir,'error')) 2850 2851 self.configure_directory() 2852 # Save original random number 2853 self.random_orig = self.random 2854 logger.info("Using random number seed offset = %s" % self.random) 2855 # Update random number 2856 self.update_random() 2857 self.save_random() 2858 self.update_status('Running Survey', level=None) 2859 if self.cluster_mode: 2860 logger.info('Creating Jobs') 2861 2862 self.total_jobs = 0 2863 subproc = [l.strip() for l in open(pjoin(self.me_dir, 2864 'SubProcesses', 'subproc.mg'))] 2865 2866 P_zero_result = [] # check the number of times where they are no phase-space 2867 2868 # File for the loop (for loop induced) 2869 if os.path.exists(pjoin(self.me_dir,'SubProcesses', 2870 'MadLoop5_resources')) and cluster.need_transfer(self.options): 2871 tf=tarfile.open(pjoin(self.me_dir, 'SubProcesses', 2872 'MadLoop5_resources.tar.gz'), 'w:gz', dereference=True) 2873 tf.add(pjoin(self.me_dir,'SubProcesses','MadLoop5_resources'), 2874 arcname='MadLoop5_resources') 2875 tf.close() 2876 2877 logger.info('Working on SubProcesses') 2878 ajobcreator = gen_ximprove.gensym(self) 2879 2880 #check difficult PS case 2881 if float(self.run_card['mmjj']) > 0.01 * (float(self.run_card['ebeam1'])+float(self.run_card['ebeam2'])): 2882 self.pass_in_difficult_integration_mode() 2883 2884 jobs, P_zero_result = ajobcreator.launch() 2885 2886 # Check if all or only some fails 2887 if P_zero_result: 2888 if len(P_zero_result) == len(subproc): 2889 Pdir = pjoin(self.me_dir, 'SubProcesses',subproc[0].strip()) 2890 raise ZeroResult, '%s' % \ 2891 open(pjoin(Pdir,'ajob.no_ps.log')).read() 2892 else: 2893 logger.warning(''' %s SubProcesses doesn\'t have available phase-space. 2894 Please check mass spectrum.''' % ','.join(P_zero_result)) 2895 2896 2897 self.monitor(run_type='All jobs submitted for survey', html=True) 2898 if not self.history or 'survey' in self.history[-1] or self.ninitial ==1 or \ 2899 self.run_card['gridpack']: 2900 #will be done during the refine (more precisely in gen_ximprove) 2901 cross, error = sum_html.make_all_html_results(self) 2902 self.results.add_detail('cross', cross) 2903 self.results.add_detail('error', error) 2904 self.exec_cmd("print_results %s" % self.run_name, 2905 errorhandling=False, printcmd=False, precmd=False, postcmd=False) 2906 2907 self.results.add_detail('run_statistics', dict(ajobcreator.run_statistics)) 2908 self.update_status('End survey', 'parton', makehtml=False)
2909 2910 ############################################################################
2911 - def pass_in_difficult_integration_mode(self):
2912 """be more secure for the integration to not miss it due to strong cut""" 2913 2914 # improve survey options if default 2915 if self.opts['points'] == self._survey_options['points'][1]: 2916 self.opts['points'] = 2 * self._survey_options['points'][1] 2917 if self.opts['iterations'] == self._survey_options['iterations'][1]: 2918 self.opts['iterations'] = 1 + self._survey_options['iterations'][1] 2919 if self.opts['accuracy'] == self._survey_options['accuracy'][1]: 2920 self.opts['accuracy'] = self._survey_options['accuracy'][1]/2 2921 2922 # Modify run_config.inc in order to improve the refine 2923 #conf_path = pjoin(self.me_dir, 'Source','run_config.inc') 2924 #files.cp(conf_path, conf_path + '.bk') 2925 # 2926 #text = open(conf_path).read() 2927 #text = re.sub('''\(min_events = \d+\)''', '''(min_events = 7500 )''', text) 2928 #text = re.sub('''\(max_events = \d+\)''', '''(max_events = 20000 )''', text) 2929 #fsock = open(conf_path, 'w') 2930 #fsock.write(text) 2931 #fsock.close() 2932 2933 # Compile 2934 for name in ['../bin/internal/gen_ximprove', 'all', 2935 '../bin/internal/combine_events']: 2936 self.compile(arg=[name], cwd=os.path.join(self.me_dir, 'Source'))
2937 2938 2939 ############################################################################
2940 - def do_refine(self, line):
2941 """Advanced commands: launch survey for the current process """ 2942 devnull = open(os.devnull, 'w') 2943 self.nb_refine += 1 2944 args = self.split_arg(line) 2945 # Check argument's validity 2946 self.check_refine(args) 2947 2948 refine_opt = {'err_goal': args[0], 'split_channels': True} 2949 precision = args[0] 2950 if len(args) == 2: 2951 refine_opt['max_process']= args[1] 2952 2953 2954 # initialize / remove lhapdf mode 2955 self.configure_directory() 2956 2957 # Update random number 2958 self.update_random() 2959 self.save_random() 2960 2961 if self.cluster_mode: 2962 logger.info('Creating Jobs') 2963 self.update_status('Refine results to %s' % precision, level=None) 2964 2965 self.total_jobs = 0 2966 subproc = [l.strip() for l in open(pjoin(self.me_dir,'SubProcesses', 2967 'subproc.mg'))] 2968 2969 # cleanning the previous job 2970 for nb_proc,subdir in enumerate(subproc): 2971 subdir = subdir.strip() 2972 Pdir = pjoin(self.me_dir, 'SubProcesses', subdir) 2973 for match in misc.glob('*ajob*', Pdir): 2974 if os.path.basename(match)[:4] in ['ajob', 'wait', 'run.', 'done']: 2975 os.remove(match) 2976 2977 x_improve = gen_ximprove.gen_ximprove(self, refine_opt) 2978 # Load the run statistics from the survey 2979 survey_statistics = dict(self.results.get_detail('run_statistics')) 2980 # Printout survey statistics 2981 if __debug__ and survey_statistics: 2982 globalstat = sum_html.RunStatistics() 2983 logger.debug(" === Survey statistics summary ===") 2984 for key, value in survey_statistics.items(): 2985 globalstat.aggregate_statistics(value) 2986 level = 5 2987 if value.has_warning(): 2988 level = 10 2989 logger.log(level, 2990 value.nice_output(str('/'.join([key[0],'G%s'%key[1]]))). 2991 replace(' statistics','')) 2992 logger.debug(globalstat.nice_output('combined', no_warning=True)) 2993 2994 if survey_statistics: 2995 x_improve.run_statistics = survey_statistics 2996 2997 x_improve.launch() # create the ajob for the refinment. 2998 if not self.history or 'refine' not in self.history[-1]: 2999 cross, error = x_improve.update_html() #update html results for survey 3000 if cross == 0: 3001 return 3002 logger.info("Current estimate of cross-section: %s +- %s" % (cross, error)) 3003 3004 if isinstance(x_improve, gen_ximprove.gen_ximprove_v4): 3005 # Non splitted mode is based on writting ajob so need to track them 3006 # Splitted mode handle the cluster submition internally. 3007 for nb_proc,subdir in enumerate(subproc): 3008 subdir = subdir.strip() 3009 Pdir = pjoin(self.me_dir, 'SubProcesses',subdir) 3010 bindir = pjoin(os.path.relpath(self.dirbin, Pdir)) 3011 3012 logger.info(' %s ' % subdir) 3013 3014 if os.path.exists(pjoin(Pdir, 'ajob1')): 3015 self.compile(['madevent'], cwd=Pdir) 3016 3017 alljobs = misc.glob('ajob*', Pdir) 3018 3019 #remove associated results.dat (ensure to not mix with all data) 3020 Gre = re.compile("\s*j=(G[\d\.\w]+)") 3021 for job in alljobs: 3022 Gdirs = Gre.findall(open(job).read()) 3023 for Gdir in Gdirs: 3024 if os.path.exists(pjoin(Pdir, Gdir, 'results.dat')): 3025 os.remove(pjoin(Pdir, Gdir,'results.dat')) 3026 3027 nb_tot = len(alljobs) 3028 self.total_jobs += nb_tot 3029 for i, job in enumerate(alljobs): 3030 job = os.path.basename(job) 3031 self.launch_job('%s' % job, cwd=Pdir, remaining=(nb_tot-i-1), 3032 run_type='Refine number %s on %s (%s/%s)' % 3033 (self.nb_refine, subdir, nb_proc+1, len(subproc))) 3034 3035 self.monitor(run_type='All job submitted for refine number %s' % self.nb_refine, 3036 html=True) 3037 3038 self.update_status("Combining runs", level='parton') 3039 try: 3040 os.remove(pjoin(Pdir, 'combine_runs.log')) 3041 except Exception: 3042 pass 3043 3044 if isinstance(x_improve, gen_ximprove.gen_ximprove_v4): 3045 # the merge of the events.lhe is handle in the x_improve class 3046 # for splitted runs. (and partly in store_events). 3047 combine_runs.CombineRuns(self.me_dir) 3048 self.refine_mode = "old" 3049 else: 3050 self.refine_mode = "new" 3051 3052 cross, error = sum_html.make_all_html_results(self) 3053 self.results.add_detail('cross', cross) 3054 self.results.add_detail('error', error) 3055 3056 self.results.add_detail('run_statistics', 3057 dict(self.results.get_detail('run_statistics'))) 3058 3059 self.update_status('finish refine', 'parton', makehtml=False) 3060 devnull.close()
3061 3062 ############################################################################
3063 - def do_combine_iteration(self, line):
3064 """Not in help: Combine a given iteration combine_iteration Pdir Gdir S|R step 3065 S is for survey 3066 R is for refine 3067 step is the iteration number (not very critical)""" 3068 3069 self.set_run_name("tmp") 3070 self.configure_directory(html_opening=False) 3071 Pdir, Gdir, mode, step = self.split_arg(line) 3072 if Gdir.startswith("G"): 3073 Gdir = Gdir[1:] 3074 if "SubProcesses" not in Pdir: 3075 Pdir = pjoin(self.me_dir, "SubProcesses", Pdir) 3076 if mode == "S": 3077 self.opts = dict([(key,value[1]) for (key,value) in \ 3078 self._survey_options.items()]) 3079 gensym = gen_ximprove.gensym(self) 3080 gensym.combine_iteration(Pdir, Gdir, int(step)) 3081 elif mode == "R": 3082 refine = gen_ximprove.gen_ximprove_share(self) 3083 refine.combine_iteration(Pdir, Gdir, int(step))
3084 3085 3086 3087 3088 ############################################################################
3089 - def do_combine_events(self, line):
3090 """Advanced commands: Launch combine events""" 3091 3092 args = self.split_arg(line) 3093 # Check argument's validity 3094 self.check_combine_events(args) 3095 3096 self.update_status('Combining Events', level='parton') 3097 3098 3099 3100 if self.run_card['gridpack']: #not hasattr(self, "refine_mode") or self.refine_mode == "old": 3101 try: 3102 os.remove(pjoin(self.me_dir,'SubProcesses', 'combine.log')) 3103 except Exception: 3104 pass 3105 3106 cluster.onecore.launch_and_wait('../bin/internal/run_combine', 3107 args=[self.run_name], 3108 cwd=pjoin(self.me_dir,'SubProcesses'), 3109 stdout=pjoin(self.me_dir,'SubProcesses', 'combine.log'), 3110 required_output=[pjoin(self.me_dir,'SubProcesses', 'combine.log')]) 3111 3112 #self.cluster.launch_and_wait('../bin/internal/run_combine', 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 output = misc.mult_try_open(pjoin(self.me_dir,'SubProcesses','combine.log')).read() 3118 # Store the number of unweighted events for the results object 3119 pat = re.compile(r'''\s*Unweighting\s*selected\s*(\d+)\s*events''') 3120 try: 3121 nb_event = pat.search(output).groups()[0] 3122 except AttributeError: 3123 time.sleep(10) 3124 output = misc.mult_try_open(pjoin(self.me_dir,'SubProcesses','combine.log')).read() 3125 try: 3126 nb_event = pat.search(output).groups()[0] 3127 except AttributeError: 3128 logger.warning('Fail to read the number of unweighted events in the combine.log file') 3129 nb_event = 0 3130 3131 self.results.add_detail('nb_event', nb_event) 3132 3133 3134 # Define The Banner 3135 tag = self.run_card['run_tag'] 3136 3137 # Update the banner with the pythia card 3138 if not self.banner: 3139 self.banner = banner_mod.recover_banner(self.results, 'parton') 3140 self.banner.load_basic(self.me_dir) 3141 # Add cross-section/event information 3142 self.banner.add_generation_info(self.results.current['cross'], nb_event) 3143 if not hasattr(self, 'random_orig'): self.random_orig = 0 3144 self.banner.change_seed(self.random_orig) 3145 if not os.path.exists(pjoin(self.me_dir, 'Events', self.run_name)): 3146 os.mkdir(pjoin(self.me_dir, 'Events', self.run_name)) 3147 self.banner.write(pjoin(self.me_dir, 'Events', self.run_name, 3148 '%s_%s_banner.txt' % (self.run_name, tag))) 3149 3150 3151 self.banner.add_to_file(pjoin(self.me_dir,'Events', 'events.lhe'), 3152 out=pjoin(self.me_dir,'Events', self.run_name, 'events.lhe')) 3153 self.banner.add_to_file(pjoin(self.me_dir,'Events', 'unweighted_events.lhe'), 3154 out=pjoin(self.me_dir,'Events', self.run_name, 'unweighted_events.lhe')) 3155 3156 else: 3157 # Define The Banner 3158 tag = self.run_card['run_tag'] 3159 # Update the banner with the pythia card 3160 if not self.banner: 3161 self.banner = banner_mod.recover_banner(self.results, 'parton') 3162 self.banner.load_basic(self.me_dir) 3163 # Add cross-section/event information 3164 self.banner.add_generation_info(self.results.current['cross'], self.run_card['nevents']) 3165 if not hasattr(self, 'random_orig'): self.random_orig = 0 3166 self.banner.change_seed(self.random_orig) 3167 if not os.path.exists(pjoin(self.me_dir, 'Events', self.run_name)): 3168 os.mkdir(pjoin(self.me_dir, 'Events', self.run_name)) 3169 self.banner.write(pjoin(self.me_dir, 'Events', self.run_name, 3170 '%s_%s_banner.txt' % (self.run_name, tag))) 3171 3172 3173 get_wgt = lambda event: event.wgt 3174 AllEvent = lhe_parser.MultiEventFile() 3175 AllEvent.banner = self.banner 3176 3177 partials = 0 # if too many file make some partial unweighting 3178 sum_xsec, sum_xerru, sum_axsec = 0,[],0 3179 for Gdir,mfactor in self.get_Gdir(): 3180 if os.path.exists(pjoin(Gdir, 'events.lhe')): 3181 result = sum_html.OneResult('') 3182 result.read_results(pjoin(Gdir, 'results.dat')) 3183 AllEvent.add(pjoin(Gdir, 'events.lhe'), 3184 result.get('xsec'), 3185 result.get('xerru'), 3186 result.get('axsec') 3187 ) 3188 3189 sum_xsec += result.get('xsec') 3190 sum_xerru.append(result.get('xerru')) 3191 sum_axsec += result.get('axsec') 3192 3193 if len(AllEvent) >= 80: #perform a partial unweighting 3194 AllEvent.unweight(pjoin(self.me_dir, "Events", self.run_name, "partials%s.lhe.gz" % partials), 3195 get_wgt, log_level=5, trunc_error=1e-2, event_target=self.run_card['nevents']) 3196 AllEvent = lhe_parser.MultiEventFile() 3197 AllEvent.banner = self.banner 3198 AllEvent.add(pjoin(self.me_dir, "Events", self.run_name, "partials%s.lhe.gz" % partials), 3199 sum_xsec, 3200 math.sqrt(sum(x**2 for x in sum_xerru)), 3201 sum_axsec) 3202 partials +=1 3203 3204 nb_event = AllEvent.unweight(pjoin(self.me_dir, "Events", self.run_name, "unweighted_events.lhe.gz"), 3205 get_wgt, trunc_error=1e-2, event_target=self.run_card['nevents'], 3206 log_level=logging.DEBUG, normalization=self.run_card['event_norm']) 3207 3208 if partials: 3209 for i in range(partials): 3210 try: 3211 os.remove(pjoin(self.me_dir, "Events", self.run_name, "partials%s.lhe.gz" % i)) 3212 except Exception: 3213 os.remove(pjoin(self.me_dir, "Events", self.run_name, "partials%s.lhe" % i)) 3214 3215 self.results.add_detail('nb_event', nb_event) 3216 3217 if self.run_card['bias_module'].lower() not in ['dummy', 'none']: 3218 self.correct_bias() 3219 3220 3221 3222 self.to_store.append('event') 3223 eradir = self.options['exrootanalysis_path'] 3224 madir = self.options['madanalysis_path'] 3225 td = self.options['td_path'] 3226 if eradir and misc.is_executable(pjoin(eradir,'ExRootLHEFConverter')) and\ 3227 os.path.exists(pjoin(self.me_dir, 'Events', 'unweighted_events.lhe')): 3228 if not os.path.exists(pjoin(self.me_dir, 'Events', self.run_name)): 3229 os.mkdir(pjoin(self.me_dir, 'Events', self.run_name)) 3230 self.create_root_file(output='%s/unweighted_events.root' % \ 3231 self.run_name)
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 try: 5532 misc.call(['%s/ExRootLHEFConverter' % eradir, 5533 input, output], 5534 cwd=pjoin(self.me_dir, 'Events')) 5535 except Exception: 5536 logger.warning('fail to produce Root output [problem with ExRootAnalysis]')
5537
5538 - def run_syscalc(self, mode='parton', event_path=None, output=None):
5539 """create the syscalc output""" 5540 5541 if self.run_card['use_syst'] not in self.true: 5542 return 5543 5544 scdir = self.options['syscalc_path'] 5545 if not scdir or not os.path.exists(scdir): 5546 return 5547 5548 if self.run_card['event_norm'] != 'sum': 5549 logger.critical('SysCalc works only when event_norm is on \'sum\'.') 5550 return 5551 logger.info('running SysCalc on mode %s' % mode) 5552 5553 # Restore the old default for SysCalc+PY6 5554 if self.run_card['sys_matchscale']=='auto': 5555 self.run_card['sys_matchscale'] = "30 50" 5556 5557 # Check that all pdfset are correctly installed 5558 lhaid = [self.run_card.get_lhapdf_id()] 5559 if '&&' in self.run_card['sys_pdf']: 5560 line = ' '.join(self.run_card['sys_pdf']) 5561 sys_pdf = line.split('&&') 5562 lhaid += [l.split()[0] for l in sys_pdf] 5563 else: 5564 lhaid += [l for l in self.run_card['sys_pdf'].split() if not l.isdigit() or int(l) > 500] 5565 try: 5566 pdfsets_dir = self.get_lhapdf_pdfsetsdir() 5567 except Exception, error: 5568 logger.debug(str(error)) 5569 logger.warning('Systematic computation requires lhapdf to run. Bypass SysCalc') 5570 return 5571 5572 # Copy all the relevant PDF sets 5573 [self.copy_lhapdf_set([onelha], pdfsets_dir) for onelha in lhaid] 5574 5575 to_syscalc={'sys_scalefact': self.run_card['sys_scalefact'], 5576 'sys_alpsfact': self.run_card['sys_alpsfact'], 5577 'sys_matchscale': self.run_card['sys_matchscale'], 5578 'sys_scalecorrelation': self.run_card['sys_scalecorrelation'], 5579 'sys_pdf': self.run_card['sys_pdf']} 5580 5581 tag = self.run_card['run_tag'] 5582 card = pjoin(self.me_dir, 'bin','internal', 'syscalc_card.dat') 5583 template = open(pjoin(self.me_dir, 'bin','internal', 'syscalc_template.dat')).read() 5584 5585 if '&&' in to_syscalc['sys_pdf']: 5586 to_syscalc['sys_pdf'] = to_syscalc['sys_pdf'].split('#',1)[0].replace('&&',' \n ') 5587 else: 5588 data = to_syscalc['sys_pdf'].split() 5589 new = [] 5590 for d in data: 5591 if not d.isdigit(): 5592 new.append(d) 5593 elif int(d) > 500: 5594 new.append(d) 5595 else: 5596 new[-1] += ' %s' % d 5597 to_syscalc['sys_pdf'] = '\n'.join(new) 5598 5599 if to_syscalc['sys_pdf'].lower() in ['', 'f', 'false', 'none', '.false.']: 5600 to_syscalc['sys_pdf'] = '' 5601 if to_syscalc['sys_alpsfact'].lower() in ['', 'f', 'false', 'none','.false.']: 5602 to_syscalc['sys_alpsfact'] = '' 5603 5604 5605 5606 5607 # check if the scalecorrelation parameter is define: 5608 if not 'sys_scalecorrelation' in self.run_card: 5609 self.run_card['sys_scalecorrelation'] = -1 5610 open(card,'w').write(template % self.run_card) 5611 5612 if not os.path.exists(card): 5613 return False 5614 5615 5616 5617 event_dir = pjoin(self.me_dir, 'Events') 5618 5619 if not event_path: 5620 if mode == 'parton': 5621 event_path = pjoin(event_dir,self.run_name, 'unweighted_events.lhe') 5622 if not (os.path.exists(event_path) or os.path.exists(event_path+".gz")): 5623 event_path = pjoin(event_dir, 'unweighted_events.lhe') 5624 output = pjoin(event_dir, 'syscalc.lhe') 5625 stdout = open(pjoin(event_dir, self.run_name, '%s_systematics.log' % (mode)),'w') 5626 elif mode == 'Pythia': 5627 stdout = open(pjoin(event_dir, self.run_name, '%s_%s_syscalc.log' % (tag,mode)),'w') 5628 if 'mgpythiacard' in self.banner: 5629 pat = re.compile('''^\s*qcut\s*=\s*([\+\-\d.e]*)''', re.M+re.I) 5630 data = pat.search(self.banner['mgpythiacard']) 5631 if data: 5632 qcut = float(data.group(1)) 5633 xqcut = abs(self.run_card['xqcut']) 5634 for value in self.run_card['sys_matchscale'].split(): 5635 if float(value) < qcut: 5636 raise SysCalcError, 'qcut value for sys_matchscale lower than qcut in pythia_card. Bypass syscalc' 5637 if float(value) < xqcut: 5638 raise SysCalcError, 'qcut value for sys_matchscale lower than xqcut in run_card. Bypass syscalc' 5639 5640 5641 event_path = pjoin(event_dir,'syst.dat') 5642 output = pjoin(event_dir, 'syscalc.dat') 5643 else: 5644 raise self.InvalidCmd, 'Invalid mode %s' % mode 5645 5646 if not os.path.exists(event_path): 5647 if os.path.exists(event_path+'.gz'): 5648 misc.gunzip(event_path+'.gz') 5649 else: 5650 raise SysCalcError, 'Events file %s does not exits' % event_path 5651 5652 self.update_status('Calculating systematics for %s level' % mode, level = mode.lower()) 5653 try: 5654 proc = misc.call([os.path.join(scdir, 'sys_calc'), 5655 event_path, card, output], 5656 stdout = stdout, 5657 stderr = subprocess.STDOUT, 5658 cwd=event_dir) 5659 # Wait 5 s to make sure file is finished writing 5660 time.sleep(5) 5661 except OSError, error: 5662 logger.error('fail to run syscalc: %s. Please check that SysCalc is correctly installed.' % error) 5663 else: 5664 if not os.path.exists(output): 5665 logger.warning('SysCalc Failed. Please read the associate log to see the reason. Did you install the associate PDF set?') 5666 elif mode == 'parton': 5667 files.mv(output, event_path) 5668 5669 self.update_status('End syscalc for %s level' % mode, level = mode.lower(), 5670 makehtml=False) 5671 5672 return True
5673 5674 5675 5676 ############################################################################
5677 - def ask_run_configuration(self, mode=None, args=[]):
5678 """Ask the question when launching generate_events/multi_run""" 5679 5680 available_mode = ['0'] 5681 void = 'Not installed' 5682 switch_order = ['shower', 'detector', 'analysis', 'madspin', 'reweight'] 5683 5684 switch = dict((k, void) for k in switch_order) 5685 5686 description = {'shower': 'Choose the shower/hadronization program:', 5687 'detector': 'Choose the detector simulation program:', 5688 'madspin': 'Decay particles with the MadSpin module:', 5689 'reweight':'Add weights to events for different model hypothesis:', 5690 'analysis':'Run an analysis package on the events generated:' 5691 } 5692 5693 force_switch = {('shower', 'OFF'): {'detector': 'OFF'}, 5694 ('detector', 'PGS'): {'shower':'PYTHIA6'}, 5695 ('detector', 'DELPHES'): {'shower': ['PYTHIA8', 'PYTHIA6']}} 5696 5697 switch_assign = lambda key, value: switch.__setitem__(key, value if value \ 5698 in valid_options[key] else switch[key]) 5699 5700 valid_options = dict((k, ['OFF']) for k in switch_order) # track of all possible input for an entry 5701 options = ['auto', 'done'] 5702 options_legacy = [] 5703 5704 # Init the switch value according to the current status 5705 if self.options['pythia-pgs_path']: 5706 available_mode.append('1') 5707 available_mode.append('2') 5708 valid_options['shower'].append('PYTHIA6') 5709 valid_options['detector'].append('PGS') 5710 options_legacy += ['pythia', 'pgs', 'pythia=ON', 'pythia=OFF', 'pgs=ON', 'pgs=OFF'] 5711 if os.path.exists(pjoin(self.me_dir,'Cards','pythia_card.dat')): 5712 switch['shower'] = 'PYTHIA6' 5713 else: 5714 switch['shower'] = 'OFF' 5715 if os.path.exists(pjoin(self.me_dir,'Cards','pgs_card.dat')): 5716 switch['detector'] = 'PGS' 5717 else: 5718 switch['detector'] = 'OFF' 5719 5720 if self.options['pythia8_path']: 5721 available_mode.append('1') 5722 valid_options['shower'].append('PYTHIA8') 5723 if os.path.exists(pjoin(self.me_dir,'Cards','pythia8_card.dat')): 5724 switch['shower'] = 'PYTHIA8' 5725 elif switch['shower'] == void: 5726 switch['shower'] = 'OFF' 5727 5728 # MadAnalysis4 options 5729 if self.options['madanalysis_path']: 5730 if os.path.exists(pjoin(self.me_dir,'Cards','plot_card_default.dat')): 5731 valid_options['analysis'].insert(0,'MADANALYSIS_4') 5732 5733 if os.path.exists(pjoin(self.me_dir,'Cards','plot_card.dat')): 5734 switch['analysis'] = 'MADANALYSIS_4' 5735 5736 # MadAnalysis5 options 5737 if self.options['madanalysis5_path']: 5738 if os.path.exists(pjoin(self.me_dir,'Cards','madanalysis5_parton_card_default.dat')) or \ 5739 os.path.exists(pjoin(self.me_dir,'Cards','madanalysis5_hadron_card_default.dat')): 5740 valid_options['analysis'].append('MADANALYSIS_5') 5741 5742 parton_card_present = os.path.exists(pjoin(self.me_dir,'Cards', 5743 'madanalysis5_parton_card.dat')) 5744 hadron_card_present = os.path.exists(pjoin(self.me_dir,'Cards', 5745 'madanalysis5_hadron_card.dat')) 5746 if hadron_card_present or parton_card_present: 5747 switch['analysis'] = 'MADANALYSIS_5' 5748 5749 if len(valid_options['analysis'])>1: 5750 available_mode.append('3') 5751 if switch['analysis'] == void: 5752 switch['analysis'] = 'OFF' 5753 else: 5754 switch['analysis'] = 'No analysis tool interfaced to MG5aMC.' 5755 5756 # Need to allow Delphes only if a shower exists 5757 if self.options['delphes_path']: 5758 if valid_options['shower'] != ['OFF']: 5759 available_mode.append('2') 5760 valid_options['detector'].append('DELPHES') 5761 options += ['delphes', 'delphes=ON', 'delphes=OFF'] 5762 if os.path.exists(pjoin(self.me_dir,'Cards','delphes_card.dat')): 5763 switch['detector'] = 'DELPHES' 5764 elif switch['detector'] not in ['PGS']: 5765 switch['detector'] = 'OFF' 5766 elif valid_options['detector'] == ['OFF']: 5767 switch['detector'] = "Requires a shower" 5768 5769 # Check switch status for MS/reweight 5770 if not MADEVENT or ('mg5_path' in self.options and self.options['mg5_path']): 5771 available_mode.append('4') 5772 valid_options['madspin'] = ['ON', 'OFF'] 5773 if os.path.exists(pjoin(self.me_dir,'Cards','madspin_card.dat')): 5774 switch['madspin'] = 'ON' 5775 else: 5776 switch['madspin'] = 'OFF' 5777 if misc.has_f2py() or self.options['f2py_compiler']: 5778 available_mode.append('5') 5779 valid_options['reweight'] = ['ON', 'OFF'] 5780 if os.path.exists(pjoin(self.me_dir,'Cards','reweight_card.dat')): 5781 switch['reweight'] = 'ON' 5782 else: 5783 switch['reweight'] = 'OFF' 5784 else: 5785 switch['reweight'] = 'Not available (requires NumPy/f2py)' 5786 5787 if '-R' in args or '--reweight' in args: 5788 if switch['reweight'] == 'OFF': 5789 switch['reweight'] = 'ON' 5790 elif switch['reweight'] != 'ON': 5791 logger.critical("Cannot run reweight: %s", switch['reweight']) 5792 if '-M' in args or '--madspin' in args: 5793 if switch['madspin'] == 'OFF': 5794 switch['madspin'] = 'ON' 5795 elif switch['madspin'] != 'ON': 5796 logger.critical("Cannot run madspin: %s", switch['reweight']) 5797 5798 for id, key in enumerate(switch_order): 5799 if len(valid_options[key]) >1: 5800 options += ['%s=%s' % (key, s) for s in valid_options[key]] 5801 options.append(key) 5802 else: 5803 options.append('%s=OFF' % (key)) 5804 5805 options += ['parton'] + sorted(list(set(available_mode))) 5806 options += options_legacy 5807 #options += ['pythia=ON', 'pythia=OFF', 'delphes=ON', 'delphes=OFF', 'pgs=ON', 'pgs=OFF'] 5808 #ask the question 5809 5810 def color(switch_value): 5811 green = '\x1b[32m%s\x1b[0m' 5812 bold = '\x1b[33m%s\x1b[0m' 5813 red = '\x1b[31m%s\x1b[0m' 5814 if switch_value in ['OFF',void,'Requires a shower', 5815 'Not available (requires NumPy)', 5816 'Not available yet for this output/process']: 5817 return red%switch_value 5818 elif switch_value in ['ON','MADANALYSIS_4','MADANALYSIS_5', 5819 'PYTHIA8','PYTHIA6','PGS','DELPHES-ATLAS', 5820 'DELPHES-CMS','DELPHES']: 5821 return green%switch_value 5822 else: 5823 return bold%switch_value
5824 5825 if mode or not self.force: 5826 answer = '' 5827 while answer not in ['0', 'done', 'auto']: 5828 if mode: 5829 answer = mode 5830 else: 5831 switch_format = " \x1b[31m%i\x1b[0m. %-60s %12s = %s" 5832 question = "The following switches determine which programs are run:\n" 5833 question += '/'+'-'*98+'\\\n' 5834 for id, key in enumerate(switch_order): 5835 question += '| %-115s|\n'%(switch_format%(id+1, description[key], key, color(switch[key]))) 5836 question += '\\'+'-'*98+'/\n' 5837 question += ' Either type the switch number (1 to %s) to change its setting,\n' % (id+1) 5838 question += ' Set any switch explicitly (e.g. type \'madspin=ON\' at the prompt)\n' 5839 question += ' Type \'help\' for the list of all valid option\n' 5840 question += ' Type \'0\', \'auto\', \'done\' or just press enter when you are done.\n' 5841 answer = self.ask(question, '0', options, casesensitive=False) 5842 if (answer.isdigit() and answer != '0') or answer in ['shower', 'detector']: 5843 if answer.isdigit(): 5844 key = switch_order[int(answer) - 1] 5845 else: 5846 key = answer 5847 for i, opt in enumerate(valid_options[key]): 5848 if opt == switch[key]: 5849 break 5850 i +=1 5851 if i == len(valid_options[key]): 5852 i=0 5853 answer = '%s=%s' % (key, valid_options[key][i]) 5854 5855 if '=' in answer: 5856 key, status = answer.split('=') 5857 key, status = key.lower().strip(), status.upper().strip() 5858 5859 if key not in switch: 5860 # this means use use outdated switch. Use converter to new syntax 5861 logger.warning("Using old syntax. Please check that we run what you expect.") 5862 if key == "pythia" and status == "ON": 5863 key, status = "shower", "PYTHIA6" 5864 elif key == "pythia" and status == "OFF": 5865 key, status = "shower", "OFF" 5866 elif key == "pgs" and status == "ON": 5867 if switch["detector"] in ["OFF", "PGS"] : 5868 key, status = "detector", "PGS" 5869 else: 5870 key, status = "detector", "DELPHES+PGS" 5871 elif key == "delphes" and status == "ON": 5872 if switch["detector"] in ["OFF", "DELPHES"] : 5873 key, status = "detector", "DELPHES" 5874 else: 5875 key, status = "detector", "DELPHES+PGS" 5876 elif key == "pgs" and status == "OFF": 5877 if switch["detector"] in ["OFF", "PGS"] : 5878 key, status = "detector", "OFF" 5879 elif switch["detector"] == "DELPHES+PGS": 5880 key, status = "detector", "DELPHES" 5881 else: 5882 key, status = "detector", switch['detector'] 5883 elif key == "delphes" and status == "OFF": 5884 if switch["detector"] in ["OFF", "DELPHES"] : 5885 key, status = "detector", "OFF" 5886 elif switch["detector"] == "DELPHES+PGS": 5887 key, status = "detector", "PGS" 5888 else: 5889 key, status = "detector", switch['detector'] 5890 5891 5892 switch[key] = status 5893 if (key, status) in force_switch: 5894 for key2, status2 in force_switch[(key, status)].items(): 5895 if isinstance(status2, str): 5896 if switch[key2] not in [status2, void]: 5897 logger.info('For coherence \'%s\' is set to \'%s\'' 5898 % (key2, status2), '$MG:color:BLACK') 5899 switch[key2] = status2 5900 else: 5901 if switch[key2] not in status2 + [void]: 5902 logger.info('For coherence \'%s\' is set to \'%s\'' 5903 % (key2, status2[0]), '$MG:color:BLACK') 5904 switch[key2] = status2[0] 5905 elif answer in ['0', 'auto', 'done']: 5906 continue 5907 elif answer in ['parton', 'pythia','pgs','madspin','reweight', 'delphes']: 5908 logger.info('pass in %s only mode' % answer, '$MG:color:BLACK') 5909 switch_assign('madspin', 'OFF') 5910 switch_assign('reweight', 'OFF') 5911 if answer == 'parton': 5912 switch_assign('shower', 'OFF') 5913 switch_assign('detector', 'OFF') 5914 elif answer == 'pythia': 5915 switch_assign('shower', 'PYTHIA6') 5916 switch_assign('detector', 'OFF') 5917 elif answer == 'pgs': 5918 switch_assign('shower', 'PYTHIA6') 5919 switch_assign('detector', 'PGS') 5920 elif answer == 'delphes': 5921 switch_assign('shower', 'PYTHIA6') 5922 if switch['shower'] == 'OFF': 5923 switch_assign('shower', 'PYTHIA8') 5924 switch_assign('detector', 'DELPHES') 5925 elif answer == 'madspin': 5926 switch_assign('madspin', 'ON') 5927 switch_assign('shower', 'OFF') 5928 switch_assign('detector', 'OFF') 5929 elif answer == 'reweight': 5930 switch_assign('reweight', 'ON') 5931 switch_assign('shower', 'OFF') 5932 switch_assign('detector', 'OFF') 5933 5934 if mode: 5935 answer = '0' #mode auto didn't pass here (due to the continue) 5936 else: 5937 answer = 'auto' 5938 5939 # Now that we know in which mode we are check that all the card 5940 #exists (copy default if needed) 5941 5942 cards = ['param_card.dat', 'run_card.dat'] 5943 if switch['shower'] in ['PY6', 'PYTHIA6']: 5944 cards.append('pythia_card.dat') 5945 if switch['shower'] in ['PY8', 'PYTHIA8']: 5946 cards.append('pythia8_card.dat') 5947 if switch['detector'] in ['PGS','DELPHES+PGS']: 5948 cards.append('pgs_card.dat') 5949 if switch['detector'] in ['DELPHES', 'DELPHES+PGS']: 5950 cards.append('delphes_card.dat') 5951 delphes3 = True 5952 if os.path.exists(pjoin(self.options['delphes_path'], 'data')): 5953 delphes3 = False 5954 cards.append('delphes_trigger.dat') 5955 if switch['madspin'] == 'ON': 5956 cards.append('madspin_card.dat') 5957 if switch['reweight'] == 'ON': 5958 cards.append('reweight_card.dat') 5959 if switch['analysis'] in ['MADANALYSIS_5']: 5960 cards.append('madanalysis5_parton_card.dat') 5961 if switch['analysis'] in ['MADANALYSIS_5'] and not switch['shower']=='OFF': 5962 cards.append('madanalysis5_hadron_card.dat') 5963 if switch['analysis'] in ['MADANALYSIS_4']: 5964 cards.append('plot_card.dat') 5965 5966 self.keep_cards(cards) 5967 5968 if os.path.isfile(pjoin(self.me_dir,'Cards','MadLoopParams.dat')): 5969 cards.append('MadLoopParams.dat') 5970 5971 if self.force: 5972 self.check_param_card(pjoin(self.me_dir,'Cards','param_card.dat' )) 5973 return 5974 5975 if answer == 'auto': 5976 self.ask_edit_cards(cards, plot=False, mode='auto') 5977 else: 5978 self.ask_edit_cards(cards, plot=False) 5979 return 5980 5981 ############################################################################
5982 - def ask_pythia_run_configuration(self, mode=None, pythia_version=6):
5983 """Ask the question when launching pythia""" 5984 5985 pythia_suffix = '' if pythia_version==6 else '%d'%pythia_version 5986 5987 available_mode = ['0', '1'] 5988 if pythia_version==6: 5989 available_mode.append('2') 5990 if self.options['delphes_path']: 5991 available_mode.append('3') 5992 name = {'0': 'auto', '2':'pgs', '3':'delphes'} 5993 name['1'] = 'pythia%s'%pythia_suffix 5994 options = available_mode + [name[val] for val in available_mode] 5995 question = """Which programs do you want to run? 5996 0 / auto : running existing cards\n""" 5997 if pythia_version==6: 5998 question += """ 1. pythia : Pythia\n""" 5999 question += """ 2. pgs : Pythia + PGS\n""" 6000 else: 6001 question += """ 1. pythia8 : Pythia8\n""" 6002 6003 if '3' in available_mode: 6004 question += """ 3. delphes : Pythia%s + Delphes.\n"""%pythia_suffix 6005 6006 if not self.force: 6007 if not mode: 6008 mode = self.ask(question, '0', options) 6009 elif not mode: 6010 mode = 'auto' 6011 6012 if mode.isdigit(): 6013 mode = name[mode] 6014 6015 auto = False 6016 if mode == 'auto': 6017 auto = True 6018 if pythia_version==6 and os.path.exists(pjoin(self.me_dir, 6019 'Cards', 'pgs_card.dat')): 6020 mode = 'pgs' 6021 elif os.path.exists(pjoin(self.me_dir, 'Cards', 'delphes_card.dat')): 6022 mode = 'delphes' 6023 else: 6024 mode = 'pythia%s'%pythia_suffix 6025 logger.info('Will run in mode %s' % mode) 6026 # Now that we know in which mode we are check that all the card 6027 #exists (copy default if needed) remove pointless one 6028 cards = ['pythia%s_card.dat'%pythia_suffix] 6029 if mode == 'pgs' and pythia_version==6: 6030 cards.append('pgs_card.dat') 6031 if mode == 'delphes': 6032 cards.append('delphes_card.dat') 6033 delphes3 = True 6034 if os.path.exists(pjoin(self.options['delphes_path'], 'data')): 6035 delphes3 = False 6036 cards.append('delphes_trigger.dat') 6037 self.keep_cards(cards, ignore=['madanalysis5_parton_card.dat','madanalysis5_hadron_card.dat', 6038 'plot_card.dat']) 6039 6040 if self.force: 6041 return mode 6042 6043 if auto: 6044 self.ask_edit_cards(cards, mode='auto', plot=(pythia_version==6)) 6045 else: 6046 self.ask_edit_cards(cards, plot=(pythia_version==6)) 6047 6048 return mode
6049
6050 #=============================================================================== 6051 # MadEventCmd 6052 #=============================================================================== 6053 -class MadEventCmdShell(MadEventCmd, cmd.CmdShell):
6054 """The command line processor of MadGraph"""
6055
6056 6057 6058 #=============================================================================== 6059 # HELPING FUNCTION For Subprocesses 6060 #=============================================================================== 6061 -class SubProcesses(object):
6062 6063 name_to_pdg = {} 6064 6065 @classmethod
6066 - def clean(cls):
6067 cls.name_to_pdg = {}
6068 6069 @staticmethod
6070 - def get_subP(me_dir):
6071 """return the list of Subprocesses""" 6072 6073 out = [] 6074 for line in open(pjoin(me_dir,'SubProcesses', 'subproc.mg')): 6075 if not line: 6076 continue 6077 name = line.strip() 6078 if os.path.exists(pjoin(me_dir, 'SubProcesses', name)): 6079 out.append(pjoin(me_dir, 'SubProcesses', name)) 6080 6081 return out
6082 6083 6084 6085 @staticmethod
6086 - def get_subP_info(path):
6087 """ return the list of processes with their name""" 6088 6089 nb_sub = 0 6090 names = {} 6091 old_main = '' 6092 6093 if not os.path.exists(os.path.join(path,'processes.dat')): 6094 return SubProcesses.get_subP_info_v4(path) 6095 6096 for line in open(os.path.join(path,'processes.dat')): 6097 main = line[:8].strip() 6098 if main == 'mirror': 6099 main = old_main 6100 if line[8:].strip() == 'none': 6101 continue 6102 else: 6103 main = int(main) 6104 old_main = main 6105 6106 sub_proccess = line[8:] 6107 nb_sub += sub_proccess.count(',') + 1 6108 if main in names: 6109 names[main] += [sub_proccess.split(',')] 6110 else: 6111 names[main]= [sub_proccess.split(',')] 6112 6113 return names
6114 6115 @staticmethod
6116 - def get_subP_info_v4(path):
6117 """ return the list of processes with their name in case without grouping """ 6118 6119 nb_sub = 0 6120 names = {'':[[]]} 6121 path = os.path.join(path, 'auto_dsig.f') 6122 found = 0 6123 for line in open(path): 6124 if line.startswith('C Process:'): 6125 found += 1 6126 names[''][0].append(line[15:]) 6127 elif found >1: 6128 break 6129 return names
6130 6131 6132 @staticmethod
6133 - def get_subP_ids(path):
6134 """return the pdg codes of the particles present in the Subprocesses""" 6135 6136 all_ids = [] 6137 for line in open(pjoin(path, 'leshouche.inc')): 6138 if not 'IDUP' in line: 6139 continue 6140 particles = re.search("/([\d,-]+)/", line) 6141 all_ids.append([int(p) for p in particles.group(1).split(',')]) 6142 return all_ids
6143
6144 6145 #=============================================================================== 6146 -class GridPackCmd(MadEventCmd):
6147 """The command for the gridpack --Those are not suppose to be use interactively--""" 6148
6149 - def __init__(self, me_dir = None, nb_event=0, seed=0, *completekey, **stdin):
6150 """Initialize the command and directly run""" 6151 6152 # Initialize properly 6153 6154 MadEventCmd.__init__(self, me_dir, *completekey, **stdin) 6155 self.run_mode = 0 6156 self.random = seed 6157 self.random_orig = self.random 6158 self.options['automatic_html_opening'] = False 6159 # Now it's time to run! 6160 if me_dir and nb_event and seed: 6161 self.launch(nb_event, seed) 6162 else: 6163 raise MadGraph5Error,\ 6164 'Gridpack run failed: ' + str(me_dir) + str(nb_event) + \ 6165 str(seed)
6166
6167 - def launch(self, nb_event, seed):
6168 """ launch the generation for the grid """ 6169 6170 # 1) Restore the default data 6171 logger.info('generate %s events' % nb_event) 6172 self.set_run_name('GridRun_%s' % seed) 6173 self.update_status('restoring default data', level=None) 6174 misc.call([pjoin(self.me_dir,'bin','internal','restore_data'), 6175 'default'], 6176 cwd=self.me_dir) 6177 6178 # 2) Run the refine for the grid 6179 self.update_status('Generating Events', level=None) 6180 #misc.call([pjoin(self.me_dir,'bin','refine4grid'), 6181 # str(nb_event), '0', 'Madevent','1','GridRun_%s' % seed], 6182 # cwd=self.me_dir) 6183 self.refine4grid(nb_event) 6184 6185 # 3) Combine the events/pythia/... 6186 self.exec_cmd('combine_events') 6187 self.exec_cmd('store_events') 6188 self.print_results_in_shell(self.results.current) 6189 self.exec_cmd('decay_events -from_cards', postcmd=False)
6190
6191 - def refine4grid(self, nb_event):
6192 """Special refine for gridpack run.""" 6193 self.nb_refine += 1 6194 6195 precision = nb_event 6196 6197 # initialize / remove lhapdf mode 6198 # self.configure_directory() # All this has been done before 6199 self.cluster_mode = 0 # force single machine 6200 6201 # Store seed in randinit file, to be read by ranmar.f 6202 self.save_random() 6203 6204 self.update_status('Refine results to %s' % precision, level=None) 6205 logger.info("Using random number seed offset = %s" % self.random) 6206 6207 self.total_jobs = 0 6208 subproc = [P for P in os.listdir(pjoin(self.me_dir,'SubProcesses')) if 6209 P.startswith('P') and os.path.isdir(pjoin(self.me_dir,'SubProcesses', P))] 6210 devnull = open(os.devnull, 'w') 6211 for nb_proc,subdir in enumerate(subproc): 6212 subdir = subdir.strip() 6213 Pdir = pjoin(self.me_dir, 'SubProcesses',subdir) 6214 bindir = pjoin(os.path.relpath(self.dirbin, Pdir)) 6215 6216 logger.info(' %s ' % subdir) 6217 # clean previous run 6218 for match in misc.glob('*ajob*', Pdir): 6219 if os.path.basename(match)[:4] in ['ajob', 'wait', 'run.', 'done']: 6220 os.remove(pjoin(Pdir, match)) 6221 6222 6223 logfile = pjoin(Pdir, 'gen_ximprove.log') 6224 misc.call([pjoin(bindir, 'gen_ximprove')], 6225 stdin=subprocess.PIPE, 6226 stdout=open(logfile,'w'), 6227 cwd=Pdir) 6228 6229 if os.path.exists(pjoin(Pdir, 'ajob1')): 6230 alljobs = misc.glob('ajob*', Pdir) 6231 nb_tot = len(alljobs) 6232 self.total_jobs += nb_tot 6233 for i, job in enumerate(alljobs): 6234 job = os.path.basename(job) 6235 self.launch_job('%s' % job, cwd=Pdir, remaining=(nb_tot-i-1), 6236 run_type='Refine number %s on %s (%s/%s)' % 6237 (self.nb_refine, subdir, nb_proc+1, len(subproc))) 6238 if os.path.exists(pjoin(self.me_dir,'error')): 6239 self.monitor(html=True) 6240 raise MadEventError, \ 6241 'Error detected in dir %s: %s' % \ 6242 (Pdir, open(pjoin(self.me_dir,'error')).read()) 6243 self.monitor(run_type='All job submitted for refine number %s' % 6244 self.nb_refine) 6245 6246 self.update_status("Combining runs", level='parton') 6247 try: 6248 os.remove(pjoin(Pdir, 'combine_runs.log')) 6249 except Exception: 6250 pass 6251 6252 bindir = pjoin(os.path.relpath(self.dirbin, pjoin(self.me_dir,'SubProcesses'))) 6253 combine_runs.CombineRuns(self.me_dir) 6254 6255 #update html output 6256 cross, error = sum_html.make_all_html_results(self) 6257 self.results.add_detail('cross', cross) 6258 self.results.add_detail('error', error) 6259 6260 6261 self.update_status('finish refine', 'parton', makehtml=False) 6262 devnull.close()
6263
6264 6265 -class MadLoopInitializer(object):
6266 """ A container class for the various methods for initializing MadLoop. It is 6267 placed in MadEventInterface because it is used by Madevent for loop-induced 6268 simulations. """ 6269 6270 @staticmethod
6271 - def make_and_run(dir_name,checkRam=False):
6272 """ Compile the check program in the directory dir_name. 6273 Return the compilation and running time. """ 6274 6275 # Make sure to recreate the executable and modified source 6276 # (The time stamps are sometimes not actualized if it is too fast) 6277 if os.path.isfile(pjoin(dir_name,'check')): 6278 os.remove(pjoin(dir_name,'check')) 6279 os.remove(pjoin(dir_name,'check_sa.o')) 6280 os.remove(pjoin(dir_name,'loop_matrix.o')) 6281 # Now run make 6282 devnull = open(os.devnull, 'w') 6283 start=time.time() 6284 retcode = misc.compile(arg=['-j1','check'], cwd=dir_name, nb_core=1) 6285 compilation_time = time.time()-start 6286 if retcode != 0: 6287 logging.info("Error while executing make in %s" % dir_name) 6288 return None, None, None 6289 6290 if not checkRam: 6291 start=time.time() 6292 retcode = subprocess.call('./check', 6293 cwd=dir_name, stdout=devnull, stderr=devnull) 6294 6295 run_time = time.time()-start 6296 ram_usage = None 6297 else: 6298 ptimer = misc.ProcessTimer(['./check'], cwd=dir_name, shell=False, \ 6299 stdout=devnull, stderr=devnull, close_fds=True) 6300 try: 6301 ptimer.execute() 6302 #poll as often as possible; otherwise the subprocess might 6303 # "sneak" in some extra memory usage while you aren't looking 6304 # Accuracy of .2 seconds is enough for the timing. 6305 while ptimer.poll(): 6306 time.sleep(.2) 6307 finally: 6308 #make sure that we don't leave the process dangling. 6309 ptimer.close() 6310 # Notice that ptimer.max_vms_memory is also available if needed. 6311 ram_usage = ptimer.max_rss_memory 6312 # Unfortunately the running time is less precise than with the 6313 # above version 6314 run_time = (ptimer.t1 - ptimer.t0) 6315 retcode = ptimer.p.returncode 6316 6317 devnull.close() 6318 6319 if retcode != 0: 6320 logging.warning("Error while executing ./check in %s" % dir_name) 6321 return None, None, None 6322 6323 return compilation_time, run_time, ram_usage
6324 6325 @staticmethod
6326 - def fix_PSPoint_in_check(dir_path, read_ps = True, npoints = 1, 6327 hel_config = -1, mu_r=0.0, split_orders=-1):
6328 """Set check_sa.f to be reading PS.input assuming a working dir dir_name. 6329 if hel_config is different than -1 then check_sa.f is configured so to 6330 evaluate only the specified helicity. 6331 If mu_r > 0.0, then the renormalization constant value will be hardcoded 6332 directly in check_sa.f, if is is 0 it will be set to Sqrt(s) and if it 6333 is < 0.0 the value in the param_card.dat is used. 6334 If the split_orders target (i.e. the target squared coupling orders for 6335 the computation) is != -1, it will be changed in check_sa.f via the 6336 subroutine CALL SET_COUPLINGORDERS_TARGET(split_orders).""" 6337 6338 file_path = dir_path 6339 if not os.path.isfile(dir_path) or \ 6340 not os.path.basename(dir_path)=='check_sa.f': 6341 file_path = pjoin(dir_path,'check_sa.f') 6342 if not os.path.isfile(file_path): 6343 directories = [d for d in misc.glob('P*_*', dir_path) \ 6344 if (re.search(r'.*P\d+_\w*$', d) and os.path.isdir(d))] 6345 if len(directories)>0: 6346 file_path = pjoin(directories[0],'check_sa.f') 6347 if not os.path.isfile(file_path): 6348 raise MadGraph5Error('Could not find the location of check_sa.f'+\ 6349 ' from the specified path %s.'%str(file_path)) 6350 6351 file = open(file_path, 'r') 6352 check_sa = file.read() 6353 file.close() 6354 6355 file = open(file_path, 'w') 6356 check_sa = re.sub(r"READPS = \S+\)","READPS = %s)"%('.TRUE.' if read_ps \ 6357 else '.FALSE.'), check_sa) 6358 check_sa = re.sub(r"NPSPOINTS = \d+","NPSPOINTS = %d"%npoints, check_sa) 6359 if hel_config != -1: 6360 check_sa = re.sub(r"SLOOPMATRIX\S+\(\S+,MATELEM,", 6361 "SLOOPMATRIXHEL_THRES(P,%d,MATELEM,"%hel_config, check_sa) 6362 else: 6363 check_sa = re.sub(r"SLOOPMATRIX\S+\(\S+,MATELEM,", 6364 "SLOOPMATRIX_THRES(P,MATELEM,",check_sa) 6365 if mu_r > 0.0: 6366 check_sa = re.sub(r"MU_R=SQRTS","MU_R=%s"%\ 6367 (("%.17e"%mu_r).replace('e','d')),check_sa) 6368 elif mu_r < 0.0: 6369 check_sa = re.sub(r"MU_R=SQRTS","",check_sa) 6370 6371 if split_orders > 0: 6372 check_sa = re.sub(r"SET_COUPLINGORDERS_TARGET\(-?\d+\)", 6373 "SET_COUPLINGORDERS_TARGET(%d)"%split_orders,check_sa) 6374 6375 file.write(check_sa) 6376 file.close()
6377 6378 @staticmethod
6379 - def run_initialization(run_dir=None, SubProc_dir=None, infos=None,\ 6380 req_files = ['HelFilter.dat','LoopFilter.dat'], 6381 attempts = [4,15]):
6382 """ Run the initialization of the process in 'run_dir' with success 6383 characterized by the creation of the files req_files in this directory. 6384 The directory containing the driving source code 'check_sa.f'. 6385 The list attempt gives the successive number of PS points the 6386 initialization should be tried with before calling it failed. 6387 Returns the number of PS points which were necessary for the init. 6388 Notice at least run_dir or SubProc_dir must be provided. 6389 A negative attempt number given in input means that quadprec will be 6390 forced for initialization.""" 6391 6392 # If the user does not want detailed info, then set the dictionary 6393 # to a dummy one. 6394 if infos is None: 6395 infos={} 6396 6397 if SubProc_dir is None and run_dir is None: 6398 raise MadGraph5Error, 'At least one of [SubProc_dir,run_dir] must'+\ 6399 ' be provided in run_initialization.' 6400 6401 # If the user does not specify where is check_sa.f, then it is assumed 6402 # to be one levels above run_dir 6403 if SubProc_dir is None: 6404 SubProc_dir = os.path.abspath(pjoin(run_dir,os.pardir)) 6405 6406 if run_dir is None: 6407 directories =[ dir for dir in misc.glob('P[0-9]*', SubProc_dir) 6408 if os.path.isdir(dir) ] 6409 if directories: 6410 run_dir = directories[0] 6411 else: 6412 raise MadGraph5Error, 'Could not find a valid running directory'+\ 6413 ' in %s.'%str(SubProc_dir) 6414 6415 # Use the presence of the file born_matrix.f to decide if it is a 6416 # loop-induced process or not. It's not crucial, but just that because 6417 # of the dynamic adjustment of the ref scale used for deciding what are 6418 # the zero contributions, more points are neeeded for loop-induced. 6419 if not os.path.isfile(pjoin(run_dir,'born_matrix.f')): 6420 if len(attempts)>=1 and attempts[0]<8: 6421 attempts[0]=8 6422 if len(attempts)>=2 and attempts[1]<25: 6423 attempts[1]=25 6424 6425 to_attempt = list(attempts) 6426 to_attempt.reverse() 6427 my_req_files = list(req_files) 6428 6429 MLCardPath = pjoin(SubProc_dir,'MadLoopParams.dat') 6430 if not os.path.isfile(MLCardPath): 6431 raise MadGraph5Error, 'Could not find MadLoopParams.dat at %s.'\ 6432 %MLCardPath 6433 else: 6434 MLCard = banner_mod.MadLoopParam(MLCardPath) 6435 MLCard_orig = banner_mod.MadLoopParam(MLCard) 6436 6437 # Make sure that LoopFilter really is needed. 6438 if not MLCard['UseLoopFilter']: 6439 try: 6440 my_req_files.remove('LoopFilter.dat') 6441 except ValueError: 6442 pass 6443 6444 if MLCard['HelicityFilterLevel']==0: 6445 try: 6446 my_req_files.remove('HelFilter.dat') 6447 except ValueError: 6448 pass 6449 6450 def need_init(): 6451 """ True if init not done yet.""" 6452 proc_prefix_file = open(pjoin(run_dir,'proc_prefix.txt'),'r') 6453 proc_prefix = proc_prefix_file.read() 6454 proc_prefix_file.close() 6455 return any([not os.path.exists(pjoin(run_dir,'MadLoop5_resources', 6456 proc_prefix+fname)) for fname in my_req_files]) or \ 6457 not os.path.isfile(pjoin(run_dir,'check')) or \ 6458 not os.access(pjoin(run_dir,'check'), os.X_OK)
6459 6460 # Check if this is a process without born by checking the presence of the 6461 # file born_matrix.f 6462 is_loop_induced = os.path.exists(pjoin(run_dir,'born_matrix.f')) 6463 6464 # For loop induced processes, always attempt quadruple precision if 6465 # double precision attempts fail and the user didn't specify himself 6466 # quadruple precision initializations attempts 6467 if not any(attempt<0 for attempt in to_attempt): 6468 to_attempt = [-attempt for attempt in to_attempt] + to_attempt 6469 use_quad_prec = 1 6470 curr_attempt = 1 6471 6472 MLCard.set('WriteOutFilters',True) 6473 6474 while to_attempt!=[] and need_init(): 6475 curr_attempt = to_attempt.pop() 6476 # if the attempt is a negative number it means we must force 6477 # quadruple precision at initialization time 6478 if curr_attempt < 0: 6479 use_quad_prec = -1 6480 # In quadruple precision we can lower the ZeroThres threshold 6481 MLCard.set('CTModeInit',4) 6482 MLCard.set('ZeroThres',1e-11) 6483 else: 6484 # Restore the default double precision intialization params 6485 MLCard.set('CTModeInit',1) 6486 MLCard.set('ZeroThres',1e-9) 6487 # Plus one because the filter are written on the next PS point after 6488 curr_attempt = abs(curr_attempt+1) 6489 MLCard.set('MaxAttempts',curr_attempt) 6490 MLCard.write(pjoin(SubProc_dir,'MadLoopParams.dat')) 6491 6492 # initialization is performed. 6493 MadLoopInitializer.fix_PSPoint_in_check(run_dir, read_ps = False, 6494 npoints = curr_attempt) 6495 compile_time, run_time, ram_usage = \ 6496 MadLoopInitializer.make_and_run(run_dir) 6497 if compile_time==None: 6498 logging.error("Failed at running the process in %s."%run_dir) 6499 attempts = None 6500 return None 6501 # Only set process_compilation time for the first compilation. 6502 if 'Process_compilation' not in infos.keys() or \ 6503 infos['Process_compilation']==None: 6504 infos['Process_compilation'] = compile_time 6505 infos['Initialization'] = run_time 6506 6507 MLCard_orig.write(pjoin(SubProc_dir,'MadLoopParams.dat')) 6508 if need_init(): 6509 return None 6510 else: 6511 return use_quad_prec*(curr_attempt-1)
6512 6513 @staticmethod
6514 - def need_MadLoopInit(proc_dir, subproc_prefix='PV'):
6515 """Checks whether the necessary filters are present or not.""" 6516 6517 def need_init(ML_resources_path, proc_prefix, r_files): 6518 """ Returns true if not all required files are present. """ 6519 return any([not os.path.exists(pjoin(ML_resources_path, 6520 proc_prefix+fname)) for fname in r_files])
6521 6522 MLCardPath = pjoin(proc_dir,'SubProcesses','MadLoopParams.dat') 6523 if not os.path.isfile(MLCardPath): 6524 raise MadGraph5Error, 'Could not find MadLoopParams.dat at %s.'\ 6525 %MLCardPath 6526 MLCard = banner_mod.MadLoopParam(MLCardPath) 6527 6528 req_files = ['HelFilter.dat','LoopFilter.dat'] 6529 # Make sure that LoopFilter really is needed. 6530 if not MLCard['UseLoopFilter']: 6531 try: 6532 req_files.remove('LoopFilter.dat') 6533 except ValueError: 6534 pass 6535 if MLCard['HelicityFilterLevel']==0: 6536 try: 6537 req_files.remove('HelFilter.dat') 6538 except ValueError: 6539 pass 6540 6541 for v_folder in glob.iglob(pjoin(proc_dir,'SubProcesses', 6542 '%s*'%subproc_prefix)): 6543 # Make sure it is a valid MadLoop directory 6544 if not os.path.isdir(v_folder) or not os.path.isfile(\ 6545 pjoin(v_folder,'loop_matrix.f')): 6546 continue 6547 proc_prefix_file = open(pjoin(v_folder,'proc_prefix.txt'),'r') 6548 proc_prefix = proc_prefix_file.read() 6549 proc_prefix_file.close() 6550 if need_init(pjoin(proc_dir,'SubProcesses','MadLoop5_resources'), 6551 proc_prefix, req_files): 6552 return True 6553 6554 return False 6555 6556 @staticmethod
6557 - def init_MadLoop(proc_dir, n_PS=None, subproc_prefix='PV', MG_options=None, 6558 interface = None):
6559 """Advanced commands: Compiles and run MadLoop on RAMBO random PS points to initilize the 6560 filters.""" 6561 6562 logger.debug('Compiling Source materials necessary for MadLoop '+ 6563 'initialization.') 6564 # Initialize all the virtuals directory, so as to generate the necessary 6565 # filters (essentially Helcity filter). 6566 # Make sure that the MadLoopCard has the loop induced settings 6567 if interface is None: 6568 misc.compile(arg=['treatCardsLoopNoInit'], cwd=pjoin(proc_dir,'Source')) 6569 else: 6570 interface.do_treatcards('all --no_MadLoopInit') 6571 6572 # First make sure that IREGI and CUTTOOLS are compiled if needed 6573 if os.path.exists(pjoin(proc_dir,'Source','CutTools')): 6574 misc.compile(arg=['libcuttools'],cwd=pjoin(proc_dir,'Source')) 6575 if os.path.exists(pjoin(proc_dir,'Source','IREGI')): 6576 misc.compile(arg=['libiregi'],cwd=pjoin(proc_dir,'Source')) 6577 # Then make sure DHELAS and MODEL are compiled 6578 misc.compile(arg=['libmodel'],cwd=pjoin(proc_dir,'Source')) 6579 misc.compile(arg=['libdhelas'],cwd=pjoin(proc_dir,'Source')) 6580 6581 # Now initialize the MadLoop outputs 6582 logger.info('Initializing MadLoop loop-induced matrix elements '+\ 6583 '(this can take some time)...') 6584 6585 # Setup parallelization 6586 if MG_options: 6587 mcore = cluster.MultiCore(**MG_options) 6588 else: 6589 mcore = cluster.onecore 6590 def run_initialization_wrapper(run_dir, infos, attempts): 6591 if attempts is None: 6592 n_PS = MadLoopInitializer.run_initialization( 6593 run_dir=run_dir, infos=infos) 6594 else: 6595 n_PS = MadLoopInitializer.run_initialization( 6596 run_dir=run_dir, infos=infos, attempts=attempts) 6597 infos['nPS'] = n_PS 6598 return 0
6599 6600 def wait_monitoring(Idle, Running, Done): 6601 if Idle+Running+Done == 0: 6602 return 6603 logger.debug('MadLoop initialization jobs: %d Idle, %d Running, %d Done'\ 6604 %(Idle, Running, Done)) 6605 6606 init_info = {} 6607 # List all virtual folders while making sure they are valid MadLoop folders 6608 VirtualFolders = [f for f in glob.iglob(pjoin(proc_dir,'SubProcesses', 6609 '%s*'%subproc_prefix)) if (os.path.isdir(f) or 6610 os.path.isfile(pjoin(f,'loop_matrix.f')))] 6611 logger.debug("Now Initializing MadLoop matrix element in %d folder%s:"%\ 6612 (len(VirtualFolders),'s' if len(VirtualFolders)>1 else '')) 6613 logger.debug(', '.join("'%s'"%os.path.basename(v_folder) for v_folder in 6614 VirtualFolders)) 6615 for v_folder in VirtualFolders: 6616 init_info[v_folder] = {} 6617 6618 # We try all multiples of n_PS from 1 to max_mult, first in DP and then 6619 # in QP before giving up, or use default values if n_PS is None. 6620 max_mult = 3 6621 if n_PS is None: 6622 # Then use the default list of number of PS points to try 6623 mcore.submit(run_initialization_wrapper, 6624 [pjoin(v_folder), init_info[v_folder], None]) 6625 else: 6626 # Use specific set of PS points 6627 mcore.submit(run_initialization_wrapper, [pjoin(v_folder), 6628 init_info[v_folder], 6629 [n_PS*multiplier for multiplier in range(1,max_mult+1)]]) 6630 6631 # Wait for all jobs to finish. 6632 mcore.wait('',wait_monitoring,update_first=wait_monitoring) 6633 for v_folder in VirtualFolders: 6634 init = init_info[v_folder] 6635 if init['nPS'] is None: 6636 raise MadGraph5Error, 'Failed the initialization of'+\ 6637 " loop-induced matrix element '%s'%s."%\ 6638 (os.path.basename(v_folder),' (using default n_PS points)' if\ 6639 n_PS is None else ' (trying with a maximum of %d PS points)'\ 6640 %(max_mult*n_PS)) 6641 if init['nPS']==0: 6642 logger.debug("Nothing to be done in '%s', all filters already "%\ 6643 os.path.basename(v_folder)+\ 6644 "present (use the '-r' option to force their recomputation)") 6645 else: 6646 logger.debug("'%s' finished using "%os.path.basename(v_folder)+ 6647 '%d PS points (%s), in %.3g(compil.) + %.3g(init.) secs.'%( 6648 abs(init['nPS']),'DP' if init['nPS']>0 else 'QP', 6649 init['Process_compilation'],init['Initialization'])) 6650 6651 logger.info('MadLoop initialization finished.') 6652 6653 AskforEditCard = common_run.AskforEditCard 6654 6655 6656 if '__main__' == __name__: 6657 # Launch the interface without any check if one code is already running. 6658 # This can ONLY run a single command !! 6659 import sys 6660 if not sys.version_info[0] == 2 or sys.version_info[1] < 6: 6661 sys.exit('MadGraph/MadEvent 5 works only with python 2.6 or later (but not python 3.X).\n'+\ 6662 'Please upgrate your version of python.') 6663 6664 import os 6665 import optparse 6666 # Get the directory of the script real path (bin) 6667 # and add it to the current PYTHONPATH 6668 root_path = os.path.dirname(os.path.dirname(os.path.realpath( __file__ ))) 6669 sys.path.insert(0, root_path)
6670 6671 - class MyOptParser(optparse.OptionParser):
6672 - class InvalidOption(Exception): pass
6673 - def error(self, msg=''):
6674 raise MyOptParser.InvalidOption(msg)
6675 # Write out nice usage message if called with -h or --help 6676 usage = "usage: %prog [options] [FILE] " 6677 parser = MyOptParser(usage=usage) 6678 parser.add_option("-l", "--logging", default='INFO', 6679 help="logging level (DEBUG|INFO|WARNING|ERROR|CRITICAL) [%default]") 6680 parser.add_option("","--web", action="store_true", default=False, dest='web', \ 6681 help='force toce to be in secure mode') 6682 parser.add_option("","--debug", action="store_true", default=False, dest='debug', \ 6683 help='force to launch debug mode') 6684 parser_error = '' 6685 done = False 6686 6687 for i in range(len(sys.argv)-1): 6688 try: 6689 (options, args) = parser.parse_args(sys.argv[1:len(sys.argv)-i]) 6690 done = True 6691 except MyOptParser.InvalidOption, error: 6692 pass 6693 else: 6694 args += sys.argv[len(sys.argv)-i:] 6695 if not done: 6696 # raise correct error: 6697 try: 6698 (options, args) = parser.parse_args() 6699 except MyOptParser.InvalidOption, error: 6700 print error 6701 sys.exit(2) 6702 6703 if len(args) == 0: 6704 args = '' 6705 6706 import subprocess 6707 import logging 6708 import logging.config 6709 # Set logging level according to the logging level given by options 6710 #logging.basicConfig(level=vars(logging)[options.logging]) 6711 import internal.coloring_logging 6712 try: 6713 if __debug__ and options.logging == 'INFO': 6714 options.logging = 'DEBUG' 6715 if options.logging.isdigit(): 6716 level = int(options.logging) 6717 else: 6718 level = eval('logging.' + options.logging) 6719 print os.path.join(root_path, 'internal', 'me5_logging.conf') 6720 logging.config.fileConfig(os.path.join(root_path, 'internal', 'me5_logging.conf')) 6721 logging.root.setLevel(level) 6722 logging.getLogger('madgraph').setLevel(level) 6723 except: 6724 raise 6725 pass 6726 6727 # Call the cmd interface main loop 6728 try: 6729 if args: 6730 # a single command is provided 6731 if '--web' in args: 6732 i = args.index('--web') 6733 args.pop(i) 6734 cmd_line = MadEventCmd(force_run=True) 6735 else: 6736 cmd_line = MadEventCmdShell(force_run=True) 6737 if not hasattr(cmd_line, 'do_%s' % args[0]): 6738 if parser_error: 6739 print parser_error 6740 print 'and %s can not be interpreted as a valid command.' % args[0] 6741 else: 6742 print 'ERROR: %s not a valid command. Please retry' % args[0] 6743 else: 6744 cmd_line.use_rawinput = False 6745 cmd_line.run_cmd(' '.join(args)) 6746 cmd_line.run_cmd('quit') 6747 6748 except KeyboardInterrupt: 6749 print 'quit on KeyboardInterrupt' 6750 pass 6751