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