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