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 self.exec_cmd('reweight -from_cards', postcmd=False) 2562 self.exec_cmd('decay_events -from_cards', postcmd=False) 2563 if self.run_card['time_of_flight']>=0: 2564 self.exec_cmd("add_time_of_flight --threshold=%s" % self.run_card['time_of_flight'] ,postcmd=False) 2565 2566 if switch_mode['analysis'] == 'EXROOTANALYSIS': 2567 input = pjoin(self.me_dir, 'Events', self.run_name,'unweighted_events.lhe.gz') 2568 output = pjoin(self.me_dir, 'Events', self.run_name, 'unweighted_events.root') 2569 self.create_root_file(input , output) 2570 2571 self.exec_cmd('madanalysis5_parton --no_default', postcmd=False, printcmd=False) 2572 # shower launches pgs/delphes if needed 2573 self.exec_cmd('shower --no_default', postcmd=False, printcmd=False) 2574 self.exec_cmd('madanalysis5_hadron --no_default', postcmd=False, printcmd=False) 2575 self.store_result() 2576 2577 if self.allow_notification_center: 2578 misc.apple_notify('Run %s finished' % os.path.basename(self.me_dir), 2579 '%s: %s +- %s ' % (self.results.current['run_name'], 2580 self.results.current['cross'], 2581 self.results.current['error']))
2582
2583 - def do_initMadLoop(self,line):
2584 """Compile and run MadLoop for a certain number of PS point so as to 2585 initialize MadLoop (setup the zero helicity and loop filter.)""" 2586 2587 args = line.split() 2588 # Check argument's validity 2589 options = self.check_initMadLoop(args) 2590 2591 if not options['force']: 2592 self.ask_edit_cards(['MadLoopParams.dat'], mode='fixed', plot=False) 2593 self.exec_cmd('treatcards loop --no_MadLoopInit') 2594 2595 if options['refresh']: 2596 for filter in misc.glob('*Filter*', 2597 pjoin(self.me_dir,'SubProcesses','MadLoop5_resources')): 2598 logger.debug("Resetting filter '%s'."%os.path.basename(filter)) 2599 os.remove(filter) 2600 2601 MLCard = banner_mod.MadLoopParam(pjoin(self.me_dir, 2602 'Cards','MadLoopParams.dat')) 2603 if options['nPS'] is None: 2604 options['nPS'] = MLCard['CheckCycle']+2 2605 elif options['nPS'] < MLCard['CheckCycle']+2: 2606 new_n_PS = MLCard['CheckCycle']+2 2607 logger.debug('Hard-setting user-defined n_PS (%d) to %d, because '\ 2608 %(options['nPS'],new_n_PS)+"of the 'CheckCycle' value (%d) "%MLCard['CheckCycle']+\ 2609 "specified in the ML param card.") 2610 options['nPS'] = new_n_PS 2611 2612 MadLoopInitializer.init_MadLoop(self.me_dir,n_PS=options['nPS'], 2613 subproc_prefix='PV', MG_options=self.options, interface=self)
2614
2615 - def do_launch(self, line, *args, **opt):
2616 """Main Commands: exec generate_events for 2>N and calculate_width for 1>N""" 2617 2618 if self.ninitial == 1: 2619 logger.info("Note that since 2.3. The launch for 1>N pass in event generation\n"+ 2620 " To have the previous behavior use the calculate_decay_widths function") 2621 # self.do_calculate_decay_widths(line, *args, **opt) 2622 #else: 2623 self.do_generate_events(line, *args, **opt)
2624
2625 - def print_results_in_shell(self, data):
2626 """Have a nice results prints in the shell, 2627 data should be of type: gen_crossxhtml.OneTagResults""" 2628 2629 if not data: 2630 return 2631 2632 if data['run_statistics']: 2633 globalstat = sum_html.RunStatistics() 2634 2635 logger.info(" " ) 2636 logger.debug(" === Run statistics summary ===") 2637 for key, value in data['run_statistics'].items(): 2638 globalstat.aggregate_statistics(value) 2639 level = 5 2640 if value.has_warning(): 2641 level = 10 2642 logger.log(level, value.nice_output(str('/'.join([key[0],'G%s'%key[1]]))).\ 2643 replace(' statistics','')) 2644 logger.info(" " ) 2645 logger.debug(globalstat.nice_output('combined', no_warning=True)) 2646 if globalstat.has_warning(): 2647 logger.warning(globalstat.get_warning_text()) 2648 logger.info(" ") 2649 2650 2651 logger.info(" === Results Summary for run: %s tag: %s ===\n" % (data['run_name'],data['tag'])) 2652 2653 total_time = int(sum(_['cumulative_timing'] for _ in data['run_statistics'].values())) 2654 if total_time > 0: 2655 logger.info(" Cumulative sequential time for this run: %s"%misc.format_time(total_time)) 2656 2657 if self.ninitial == 1: 2658 logger.info(" Width : %.4g +- %.4g GeV" % (data['cross'], data['error'])) 2659 else: 2660 logger.info(" Cross-section : %.4g +- %.4g pb" % (data['cross'], data['error'])) 2661 logger.info(" Nb of events : %s" % data['nb_event'] ) 2662 2663 if data['run_mode']=='madevent': 2664 if data['cross_pythia'] and data['nb_event_pythia']: 2665 if data['cross_pythia'] == -1: 2666 path = pjoin(self.me_dir, 'Events', self.run_name, '%s_merged_xsecs.txt' % self.run_tag) 2667 cross_sections = {} 2668 if os.path.exists(path): 2669 for line in open(path): 2670 split = line.split() 2671 if len(split)!=3: 2672 continue 2673 scale, cross, error = split 2674 cross_sections[float(scale)] = (float(cross), float(error)) 2675 if len(cross_sections)>0: 2676 logger.info(' Pythia8 merged cross-sections are:') 2677 for scale in sorted(cross_sections.keys()): 2678 logger.info(' > Merging scale = %-6.4g : %-11.5g +/- %-7.2g [pb]'%\ 2679 (scale,cross_sections[scale][0],cross_sections[scale][1])) 2680 2681 else: 2682 if self.ninitial == 1: 2683 logger.info(" Matched width : %.4g +- %.4g GeV" % (data['cross_pythia'], data['error_pythia'])) 2684 else: 2685 logger.info(" Matched cross-section : %.4g +- %.4g pb" % (data['cross_pythia'], data['error_pythia'])) 2686 logger.info(" Nb of events after matching/merging : %d" % int(data['nb_event_pythia'])) 2687 if self.run_card['use_syst'] in self.true and \ 2688 (int(self.run_card['ickkw'])==1 or self.run_card['ktdurham']>0.0 2689 or self.run_card['ptlund']>0.0): 2690 logger.info(" Notice that because Systematics computation is turned on, the merging did not veto events but modified their weights instead.\n"+\ 2691 " The resulting hepmc/stdhep file should therefore be use with those weights.") 2692 else: 2693 logger.info(" Nb of events after merging : %s" % data['nb_event_pythia']) 2694 2695 logger.info(" " )
2696
2697 - def print_results_in_file(self, data, path, mode='w', format='full'):
2698 """Have a nice results prints in the shell, 2699 data should be of type: gen_crossxhtml.OneTagResults""" 2700 if not data: 2701 return 2702 2703 fsock = open(path, mode) 2704 2705 if data['run_statistics']: 2706 logger.debug(" === Run statistics summary ===") 2707 for key, value in data['run_statistics'].items(): 2708 logger.debug(value.nice_output(str('/'.join([key[0],'G%s'%key[1]]))).\ 2709 replace(' statistics','')) 2710 logger.info(" " ) 2711 2712 if format == "full": 2713 fsock.write(" === Results Summary for run: %s tag: %s process: %s ===\n" % \ 2714 (data['run_name'],data['tag'], os.path.basename(self.me_dir))) 2715 2716 if self.ninitial == 1: 2717 fsock.write(" Width : %.4g +- %.4g GeV\n" % (data['cross'], data['error'])) 2718 else: 2719 fsock.write(" Cross-section : %.4g +- %.4g pb\n" % (data['cross'], data['error'])) 2720 fsock.write(" Nb of events : %s\n" % data['nb_event'] ) 2721 if data['cross_pythia'] and data['nb_event_pythia']: 2722 if self.ninitial == 1: 2723 fsock.write(" Matched Width : %.4g +- %.4g GeV\n" % (data['cross_pythia'], data['error_pythia'])) 2724 else: 2725 fsock.write(" Matched Cross-section : %.4g +- %.4g pb\n" % (data['cross_pythia'], data['error_pythia'])) 2726 fsock.write(" Nb of events after Matching : %s\n" % data['nb_event_pythia']) 2727 fsock.write(" \n" ) 2728 elif format == "short": 2729 if mode == "w": 2730 fsock.write("# run_name tag cross error Nb_event cross_after_matching nb_event_after matching\n") 2731 2732 if data['cross_pythia'] and data['nb_event_pythia']: 2733 text = "%(run_name)s %(tag)s %(cross)s %(error)s %(nb_event)s %(cross_pythia)s %(nb_event_pythia)s\n" 2734 else: 2735 text = "%(run_name)s %(tag)s %(cross)s %(error)s %(nb_event)s\n" 2736 fsock.write(text % data)
2737 2738 ############################################################################
2739 - def do_calculate_decay_widths(self, line):
2740 """Main Commands: launch decay width calculation and automatic inclusion of 2741 calculated widths and BRs in the param_card.""" 2742 2743 args = self.split_arg(line) 2744 # Check argument's validity 2745 accuracy = self.check_calculate_decay_widths(args) 2746 self.ask_run_configuration('parton') 2747 self.banner = None 2748 self.Gdirs = None 2749 if not args: 2750 # No run name assigned -> assigned one automaticaly 2751 self.set_run_name(self.find_available_run_name(self.me_dir)) 2752 else: 2753 self.set_run_name(args[0], reload_card=True) 2754 args.pop(0) 2755 2756 self.configure_directory() 2757 2758 # Running gridpack warmup 2759 opts=[('accuracy', accuracy), # default 0.01 2760 ('points', 1000), 2761 ('iterations',9)] 2762 2763 logger.info('Calculating decay widths with run name %s' % self.run_name) 2764 2765 self.exec_cmd('survey %s %s' % \ 2766 (self.run_name, 2767 " ".join(['--' + opt + '=' + str(val) for (opt,val) \ 2768 in opts])), 2769 postcmd=False) 2770 self.refine_mode = "old" # specify how to combine event 2771 self.exec_cmd('combine_events', postcmd=False) 2772 self.exec_cmd('store_events', postcmd=False) 2773 2774 self.collect_decay_widths() 2775 self.print_results_in_shell(self.results.current) 2776 self.update_status('calculate_decay_widths done', 2777 level='parton', makehtml=False)
2778 2779 2780 ############################################################################
2781 - def collect_decay_widths(self):
2782 """ Collect the decay widths and calculate BRs for all particles, and put 2783 in param_card form. 2784 """ 2785 2786 particle_dict = {} # store the results 2787 run_name = self.run_name 2788 2789 # Looping over the Subprocesses 2790 for P_path in SubProcesses.get_subP(self.me_dir): 2791 ids = SubProcesses.get_subP_ids(P_path) 2792 # due to grouping we need to compute the ratio factor for the 2793 # ungroup resutls (that we need here). Note that initial particles 2794 # grouping are not at the same stage as final particle grouping 2795 nb_output = len(ids) / (len(set([p[0] for p in ids]))) 2796 results = open(pjoin(P_path, run_name + '_results.dat')).read().split('\n')[0] 2797 result = float(results.strip().split(' ')[0]) 2798 for particles in ids: 2799 try: 2800 particle_dict[particles[0]].append([particles[1:], result/nb_output]) 2801 except KeyError: 2802 particle_dict[particles[0]] = [[particles[1:], result/nb_output]] 2803 2804 self.update_width_in_param_card(particle_dict, 2805 initial = pjoin(self.me_dir, 'Cards', 'param_card.dat'), 2806 output=pjoin(self.me_dir, 'Events', run_name, "param_card.dat"))
2807 2808 @staticmethod
2809 - def update_width_in_param_card(decay_info, initial=None, output=None):
2810 # Open the param_card.dat and insert the calculated decays and BRs 2811 2812 if not output: 2813 output = initial 2814 2815 param_card_file = open(initial) 2816 param_card = param_card_file.read().split('\n') 2817 param_card_file.close() 2818 2819 decay_lines = [] 2820 line_number = 0 2821 # Read and remove all decays from the param_card 2822 while line_number < len(param_card): 2823 line = param_card[line_number] 2824 if line.lower().startswith('decay'): 2825 # Read decay if particle in decay_info 2826 # DECAY 6 1.455100e+00 2827 line = param_card.pop(line_number) 2828 line = line.split() 2829 particle = 0 2830 if int(line[1]) not in decay_info: 2831 try: # If formatting is wrong, don't want this particle 2832 particle = int(line[1]) 2833 width = float(line[2]) 2834 except Exception: 2835 particle = 0 2836 # Read BRs for this decay 2837 line = param_card[line_number] 2838 while line.startswith('#') or line.startswith(' '): 2839 line = param_card.pop(line_number) 2840 if not particle or line.startswith('#'): 2841 line=param_card[line_number] 2842 continue 2843 # 6.668201e-01 3 5 2 -1 2844 line = line.split() 2845 try: # Remove BR if formatting is wrong 2846 partial_width = float(line[0])*width 2847 decay_products = [int(p) for p in line[2:2+int(line[1])]] 2848 except Exception: 2849 line=param_card[line_number] 2850 continue 2851 try: 2852 decay_info[particle].append([decay_products, partial_width]) 2853 except KeyError: 2854 decay_info[particle] = [[decay_products, partial_width]] 2855 if line_number == len(param_card): 2856 break 2857 line=param_card[line_number] 2858 if particle and particle not in decay_info: 2859 # No decays given, only total width 2860 decay_info[particle] = [[[], width]] 2861 else: # Not decay 2862 line_number += 1 2863 # Clean out possible remaining comments at the end of the card 2864 while not param_card[-1] or param_card[-1].startswith('#'): 2865 param_card.pop(-1) 2866 2867 # Append calculated and read decays to the param_card 2868 param_card.append("#\n#*************************") 2869 param_card.append("# Decay widths *") 2870 param_card.append("#*************************") 2871 for key in sorted(decay_info.keys()): 2872 width = sum([r for p,r in decay_info[key]]) 2873 param_card.append("#\n# PDG Width") 2874 param_card.append("DECAY %i %e" % (key, width.real)) 2875 if not width: 2876 continue 2877 if decay_info[key][0][0]: 2878 param_card.append("# BR NDA ID1 ID2 ...") 2879 brs = [[(val[1]/width).real, val[0]] for val in decay_info[key] if val[1]] 2880 for val in sorted(brs, reverse=True): 2881 param_card.append(" %e %i %s # %s" % 2882 (val[0].real, len(val[1]), 2883 " ".join([str(v) for v in val[1]]), 2884 val[0] * width 2885 )) 2886 decay_table = open(output, 'w') 2887 decay_table.write("\n".join(param_card) + "\n") 2888 decay_table.close() 2889 logger.info("Results written to %s" % output)
2890 2891 2892 ############################################################################
2893 - def do_multi_run(self, line):
2894 2895 args = self.split_arg(line) 2896 # Check argument's validity 2897 mode = self.check_multi_run(args) 2898 nb_run = args.pop(0) 2899 if nb_run == 1: 2900 logger.warn("'multi_run 1' command is not optimal. Think of using generate_events instead") 2901 self.ask_run_configuration(mode) 2902 2903 self.check_survey(args, cmd='multi_run') 2904 main_name = self.run_name 2905 # check if the param_card requires a scan over parameter. 2906 path=pjoin(self.me_dir, 'Cards', 'param_card.dat') 2907 self.check_param_card(path, run=False) 2908 #store it locally to avoid relaunch 2909 param_card_iterator, self.param_card_iterator = self.param_card_iterator, [] 2910 2911 crossoversig = 0 2912 inv_sq_err = 0 2913 nb_event = 0 2914 for i in range(nb_run): 2915 self.nb_refine = 0 2916 self.exec_cmd('generate_events %s_%s -f' % (main_name, i), postcmd=False) 2917 # Update collected value 2918 nb_event += int(self.results[self.run_name][-1]['nb_event']) 2919 self.results.add_detail('nb_event', nb_event , run=main_name) 2920 cross = self.results[self.run_name][-1]['cross'] 2921 error = self.results[self.run_name][-1]['error'] + 1e-99 2922 crossoversig+=cross/error**2 2923 inv_sq_err+=1.0/error**2 2924 self.results[main_name][-1]['cross'] = crossoversig/inv_sq_err 2925 self.results[main_name][-1]['error'] = math.sqrt(1.0/inv_sq_err) 2926 self.results.def_current(main_name) 2927 self.run_name = main_name 2928 self.update_status("Merging LHE files", level='parton') 2929 try: 2930 os.mkdir(pjoin(self.me_dir,'Events', self.run_name)) 2931 except Exception: 2932 pass 2933 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' 2934 % {'bin': self.dirbin, 'event': pjoin(self.me_dir,'Events'), 2935 'name': self.run_name}) 2936 2937 eradir = self.options['exrootanalysis_path'] 2938 if eradir and misc.is_executable(pjoin(eradir,'ExRootLHEFConverter')): 2939 self.update_status("Create Root file", level='parton') 2940 misc.gunzip('%s/%s/unweighted_events.lhe.gz' % 2941 (pjoin(self.me_dir,'Events'), self.run_name)) 2942 2943 self.create_root_file('%s/unweighted_events.lhe' % self.run_name, 2944 '%s/unweighted_events.root' % self.run_name) 2945 2946 path = pjoin(self.me_dir, "Events", self.run_name, "unweighted_events.lhe") 2947 self.create_plot('parton', path, 2948 pjoin(self.me_dir, 'HTML',self.run_name, 'plots_parton.html') 2949 ) 2950 2951 2952 if not os.path.exists('%s.gz' % path): 2953 misc.gzip(path) 2954 2955 self.update_status('', level='parton') 2956 self.print_results_in_shell(self.results.current) 2957 2958 cpath = pjoin(self.me_dir,'Cards','param_card.dat') 2959 if param_card_iterator: 2960 2961 param_card_iterator.store_entry(self.run_name, self.results.current['cross'],param_card_path=cpath) 2962 #check if the param_card defines a scan. 2963 orig_name=self.run_name 2964 for card in param_card_iterator: 2965 card.write(cpath) 2966 self.exec_cmd("multi_run %s -f " % nb_run ,precmd=True, postcmd=True,errorhandling=False) 2967 param_card_iterator.store_entry(self.run_name, self.results.current['cross'], param_card_path=cpath) 2968 param_card_iterator.write(pjoin(self.me_dir,'Cards','param_card.dat')) 2969 scan_name = misc.get_scan_name(orig_name, self.run_name) 2970 path = pjoin(self.me_dir, 'Events','scan_%s.txt' % scan_name) 2971 logger.info("write all cross-section results in %s" % path, '$MG:BOLD') 2972 param_card_iterator.write_summary(path)
2973 2974 2975 ############################################################################
2976 - def do_treatcards(self, line, mode=None, opt=None):
2977 """Advanced commands: create .inc files from param_card.dat/run_card.dat""" 2978 2979 if not mode and not opt: 2980 args = self.split_arg(line) 2981 mode, opt = self.check_treatcards(args) 2982 2983 # To decide whether to refresh MadLoop's helicity filters, it is necessary 2984 # to check if the model parameters where modified or not, before doing 2985 # anything else. 2986 need_MadLoopFilterUpdate = False 2987 # Just to record what triggered the reinitialization of MadLoop for a 2988 # nice debug message. 2989 type_of_change = '' 2990 if not opt['forbid_MadLoopInit'] and self.proc_characteristics['loop_induced'] \ 2991 and mode in ['loop', 'all']: 2992 paramDat = pjoin(self.me_dir, 'Cards','param_card.dat') 2993 paramInc = pjoin(opt['output_dir'], 'param_card.inc') 2994 if (not os.path.isfile(paramDat)) or (not os.path.isfile(paramInc)) or \ 2995 (os.path.getmtime(paramDat)-os.path.getmtime(paramInc)) > 0.0: 2996 need_MadLoopFilterUpdate = True 2997 type_of_change = 'model' 2998 2999 ML_in = pjoin(self.me_dir, 'Cards', 'MadLoopParams.dat') 3000 ML_out = pjoin(self.me_dir,"SubProcesses", 3001 "MadLoop5_resources", "MadLoopParams.dat") 3002 if (not os.path.isfile(ML_in)) or (not os.path.isfile(ML_out)) or \ 3003 (os.path.getmtime(ML_in)-os.path.getmtime(ML_out)) > 0.0: 3004 need_MadLoopFilterUpdate = True 3005 type_of_change = 'MadLoop' 3006 3007 #check if no 'Auto' are present in the file 3008 self.check_param_card(pjoin(self.me_dir, 'Cards','param_card.dat')) 3009 3010 if mode in ['param', 'all']: 3011 model = self.find_model_name() 3012 tmp_model = os.path.basename(model) 3013 if tmp_model == 'mssm' or tmp_model.startswith('mssm-'): 3014 if not '--param_card=' in line: 3015 param_card = pjoin(self.me_dir, 'Cards','param_card.dat') 3016 mg5_param = pjoin(self.me_dir, 'Source', 'MODEL', 'MG5_param.dat') 3017 check_param_card.convert_to_mg5card(param_card, mg5_param) 3018 check_param_card.check_valid_param_card(mg5_param) 3019 opt['param_card'] = pjoin(self.me_dir, 'Source', 'MODEL', 'MG5_param.dat') 3020 else: 3021 check_param_card.check_valid_param_card(opt['param_card']) 3022 3023 logger.debug('write compile file for card: %s' % opt['param_card']) 3024 param_card = check_param_card.ParamCard(opt['param_card']) 3025 outfile = pjoin(opt['output_dir'], 'param_card.inc') 3026 ident_card = pjoin(self.me_dir,'Cards','ident_card.dat') 3027 if os.path.isfile(pjoin(self.me_dir,'bin','internal','ufomodel','restrict_default.dat')): 3028 default = pjoin(self.me_dir,'bin','internal','ufomodel','restrict_default.dat') 3029 elif os.path.isfile(pjoin(self.me_dir,'bin','internal','ufomodel','param_card.dat')): 3030 default = pjoin(self.me_dir,'bin','internal','ufomodel','param_card.dat') 3031 elif not os.path.exists(pjoin(self.me_dir,'bin','internal','ufomodel')): 3032 fsock = open(pjoin(self.me_dir,'Source','param_card.inc'),'w') 3033 fsock.write(' ') 3034 fsock.close() 3035 if mode == 'all': 3036 self.do_treatcards('', 'run', opt) 3037 return 3038 else: 3039 devnull = open(os.devnull,'w') 3040 subprocess.call([sys.executable, 'write_param_card.py'], 3041 cwd=pjoin(self.me_dir,'bin','internal','ufomodel'), 3042 stdout=devnull) 3043 devnull.close() 3044 default = pjoin(self.me_dir,'bin','internal','ufomodel','param_card.dat') 3045 3046 need_mp = self.proc_characteristics['loop_induced'] 3047 param_card.write_inc_file(outfile, ident_card, default, need_mp=need_mp) 3048 3049 3050 if mode in ['run', 'all']: 3051 if not hasattr(self, 'run_card'): 3052 run_card = banner_mod.RunCard(opt['run_card']) 3053 else: 3054 run_card = self.run_card 3055 self.run_card = run_card 3056 self.cluster.modify_interface(self) 3057 if self.ninitial == 1: 3058 run_card['lpp1'] = 0 3059 run_card['lpp2'] = 0 3060 run_card['ebeam1'] = 0 3061 run_card['ebeam2'] = 0 3062 3063 # Ensure that the bias parameters has all the required input from the 3064 # run_card 3065 if run_card['bias_module'].lower() not in ['dummy','none']: 3066 # Using basename here means that the module will not be overwritten if already existing. 3067 bias_module_path = pjoin(self.me_dir,'Source','BIAS', 3068 os.path.basename(run_card['bias_module'])) 3069 if not os.path.isdir(bias_module_path): 3070 if not os.path.isdir(run_card['bias_module']): 3071 raise InvalidCmd("The bias module at '%s' cannot be found."%run_card['bias_module']) 3072 else: 3073 for mandatory_file in ['makefile','%s.f'%os.path.basename(run_card['bias_module'])]: 3074 if not os.path.isfile(pjoin(run_card['bias_module'],mandatory_file)): 3075 raise InvalidCmd("Could not find the mandatory file '%s' in bias module '%s'."%( 3076 mandatory_file,run_card['bias_module'])) 3077 shutil.copytree(run_card['bias_module'], pjoin(self.me_dir,'Source','BIAS', 3078 os.path.basename(run_card['bias_module']))) 3079 3080 #check expected parameters for the module. 3081 default_bias_parameters = {} 3082 start, last = False,False 3083 for line in open(pjoin(bias_module_path,'%s.f'%os.path.basename(bias_module_path))): 3084 if start and last: 3085 break 3086 if not start and not re.search('c\s*parameters\s*=\s*{',line, re.I): 3087 continue 3088 start = True 3089 if not line.startswith('C'): 3090 continue 3091 line = line[1:] 3092 if '{' in line: 3093 line = line.split('{')[-1] 3094 # split for } ! # 3095 split_result = re.split('(\}|!|\#)', line,1, re.M) 3096 line = split_result[0] 3097 sep = split_result[1] if len(split_result)>1 else None 3098 if sep == '}': 3099 last = True 3100 if ',' in line: 3101 for pair in line.split(','): 3102 if not pair.strip(): 3103 continue 3104 x,y =pair.split(':') 3105 x=x.strip() 3106 if x.startswith(('"',"'")) and x.endswith(x[0]): 3107 x = x[1:-1] 3108 default_bias_parameters[x] = y 3109 elif ':' in line: 3110 x,y = line.split(':') 3111 x = x.strip() 3112 if x.startswith(('"',"'")) and x.endswith(x[0]): 3113 x = x[1:-1] 3114 default_bias_parameters[x] = y 3115 for key,value in run_card['bias_parameters'].items(): 3116 if key not in default_bias_parameters: 3117 logger.warning('%s not supported by the bias module. We discard this entry.', key) 3118 else: 3119 default_bias_parameters[key] = value 3120 run_card['bias_parameters'] = default_bias_parameters 3121 3122 3123 # Finally write the include file 3124 run_card.write_include_file(opt['output_dir']) 3125 3126 3127 if self.proc_characteristics['loop_induced'] and mode in ['loop', 'all']: 3128 self.MadLoopparam = banner_mod.MadLoopParam(pjoin(self.me_dir, 3129 'Cards', 'MadLoopParams.dat')) 3130 # The writing out of MadLoop filter is potentially dangerous 3131 # when running in multi-core with a central disk. So it is turned 3132 # off here. If these filters were not initialized then they will 3133 # have to be re-computed at the beginning of each run. 3134 if 'WriteOutFilters' in self.MadLoopparam.user_set and \ 3135 self.MadLoopparam.get('WriteOutFilters'): 3136 logger.info( 3137 """You chose to have MadLoop writing out filters. 3138 Beware that this can be dangerous for local multicore runs.""") 3139 self.MadLoopparam.set('WriteOutFilters',False, changeifuserset=False) 3140 3141 # The conservative settings below for 'CTModeInit' and 'ZeroThres' 3142 # help adress issues for processes like g g > h z, and g g > h g 3143 # where there are some helicity configuration heavily suppressed 3144 # (by several orders of magnitude) so that the helicity filter 3145 # needs high numerical accuracy to correctly handle this spread in 3146 # magnitude. Also, because one cannot use the Born as a reference 3147 # scale, it is better to force quadruple precision *for the 3148 # initialization points only*. This avoids numerical accuracy issues 3149 # when setting up the helicity filters and does not significantly 3150 # slow down the run. 3151 # self.MadLoopparam.set('CTModeInit',4, changeifuserset=False) 3152 # Consequently, we can allow for a finer threshold for vanishing 3153 # helicity configuration 3154 # self.MadLoopparam.set('ZeroThres',1.0e-11, changeifuserset=False) 3155 3156 # It is a bit superficial to use the level 2 which tries to numerically 3157 # map matching helicities (because of CP symmetry typically) together. 3158 # It is useless in the context of MC over helicities and it can 3159 # potentially make the helicity double checking fail. 3160 self.MadLoopparam.set('HelicityFilterLevel',1, changeifuserset=False) 3161 3162 # To be on the safe side however, we ask for 4 consecutive matching 3163 # helicity filters. 3164 self.MadLoopparam.set('CheckCycle',4, changeifuserset=False) 3165 3166 # For now it is tricky to have each channel performing the helicity 3167 # double check. What we will end up doing is probably some kind 3168 # of new initialization round at the beginning of each launch 3169 # command, to reset the filters. 3170 self.MadLoopparam.set('DoubleCheckHelicityFilter',False, 3171 changeifuserset=False) 3172 3173 # Thanks to TIR recycling, TIR is typically much faster for Loop-induced 3174 # processes when not doing MC over helicities, so that we place OPP last. 3175 if not hasattr(self, 'run_card'): 3176 run_card = banner_mod.RunCard(opt['run_card']) 3177 else: 3178 run_card = self.run_card 3179 if run_card['nhel'] == 0: 3180 if 'MLReductionLib' in self.MadLoopparam.user_set and \ 3181 (self.MadLoopparam.get('MLReductionLib').startswith('1') or 3182 self.MadLoopparam.get('MLReductionLib').startswith('6')): 3183 logger.warning( 3184 """You chose to set the preferred reduction technique in MadLoop to be OPP (see parameter MLReductionLib). 3185 Beware that this can bring significant slowdown; the optimal choice --when not MC over helicity-- being to first start with TIR reduction.""") 3186 # We do not include GOLEM for now since it cannot recycle TIR coefs yet. 3187 self.MadLoopparam.set('MLReductionLib','7|6|1', changeifuserset=False) 3188 else: 3189 if 'MLReductionLib' in self.MadLoopparam.user_set and \ 3190 not (self.MadLoopparam.get('MLReductionLib').startswith('1') or 3191 self.MadLoopparam.get('MLReductionLib').startswith('6')): 3192 logger.warning( 3193 """You chose to set the preferred reduction technique in MadLoop to be different than OPP (see parameter MLReductionLib). 3194 Beware that this can bring significant slowdown; the optimal choice --when MC over helicity-- being to first start with OPP reduction.""") 3195 self.MadLoopparam.set('MLReductionLib','6|7|1', changeifuserset=False) 3196 3197 # Also TIR cache will only work when NRotations_DP=0 (but only matters 3198 # when not MC-ing over helicities) so it will be hard-reset by MadLoop 3199 # to zero when not MC-ing over helicities, unless the parameter 3200 # Force_ML_Helicity_Sum is set to True in the matrix<i>.f codes. 3201 if run_card['nhel'] == 0: 3202 if ('NRotations_DP' in self.MadLoopparam.user_set and \ 3203 self.MadLoopparam.get('NRotations_DP')!=0) or \ 3204 ('NRotations_QP' in self.MadLoopparam.user_set and \ 3205 self.MadLoopparam.get('NRotations_QP')!=0): 3206 logger.warning( 3207 """You chose to also use a lorentz rotation for stability tests (see parameter NRotations_[DP|QP]). 3208 Beware that, for optimization purposes, MadEvent uses manual TIR cache clearing which is not compatible 3209 with the lorentz rotation stability test. The number of these rotations to be used will be reset to 3210 zero by MadLoop. You can avoid this by changing the parameter 'FORCE_ML_HELICITY_SUM' int he matrix<i>.f 3211 files to be .TRUE. so that the sum over helicity configurations is performed within MadLoop (in which case 3212 the helicity of final state particles cannot be speicfied in the LHE file.""") 3213 self.MadLoopparam.set('NRotations_DP',0,changeifuserset=False) 3214 self.MadLoopparam.set('NRotations_QP',0,changeifuserset=False) 3215 else: 3216 # When MC-ing over helicities, the manual TIR cache clearing is 3217 # not necessary, so that one can use the lorentz check 3218 # Using NRotations_DP=1 slows down the code by close to 100% 3219 # but it is typicaly safer. 3220 # self.MadLoopparam.set('NRotations_DP',0,changeifuserset=False) 3221 # Revert to the above to be slightly less robust but twice faster. 3222 self.MadLoopparam.set('NRotations_DP',1,changeifuserset=False) 3223 self.MadLoopparam.set('NRotations_QP',0,changeifuserset=False) 3224 3225 # Finally, the stability tests are slightly less reliable for process 3226 # with less or equal than 4 final state particles because the 3227 # accessible kinematic is very limited (i.e. lorentz rotations don't 3228 # shuffle invariants numerics much). In these cases, we therefore 3229 # increase the required accuracy to 10^-7. 3230 # This is important for getting g g > z z [QCD] working with a 3231 # ptheavy cut as low as 1 GeV. 3232 if self.proc_characteristics['nexternal']<=4: 3233 if ('MLStabThres' in self.MadLoopparam.user_set and \ 3234 self.MadLoopparam.get('MLStabThres')>1.0e-7): 3235 logger.warning( 3236 """You chose to increase the default value of the MadLoop parameter 'MLStabThres' above 1.0e-7. 3237 Stability tests can be less reliable on the limited kinematic of processes with less or equal 3238 than four external legs, so this is not recommended (especially not for g g > z z).""") 3239 self.MadLoopparam.set('MLStabThres',1.0e-7,changeifuserset=False) 3240 else: 3241 self.MadLoopparam.set('MLStabThres',1.0e-4,changeifuserset=False) 3242 3243 #write the output file 3244 self.MadLoopparam.write(pjoin(self.me_dir,"SubProcesses","MadLoop5_resources", 3245 "MadLoopParams.dat")) 3246 3247 if self.proc_characteristics['loop_induced'] and mode in ['loop', 'all']: 3248 # Now Update MadLoop filters if necessary (if modifications were made to 3249 # the model parameters). 3250 if need_MadLoopFilterUpdate: 3251 logger.debug('Changes to the %s parameters'%type_of_change+\ 3252 ' have been detected. Madevent will then now reinitialize'+\ 3253 ' MadLoop filters.') 3254 self.exec_cmd('initMadLoop -r -f') 3255 # The need_MadLoopInit condition is just there so as to avoid useless 3256 # printout if there is not initialization to be performed. But even 3257 # without it, and because we call 'initMadLoop' without the '-r' option 3258 # no time would be wasted anyway, since the existing filters would not 3259 # be overwritten. 3260 elif not opt['forbid_MadLoopInit'] and \ 3261 MadLoopInitializer.need_MadLoopInit(self.me_dir): 3262 self.exec_cmd('initMadLoop -f')
3263 3264 ############################################################################
3265 - def do_survey(self, line):
3266 """Advanced commands: launch survey for the current process """ 3267 3268 3269 args = self.split_arg(line) 3270 # Check argument's validity 3271 self.check_survey(args) 3272 # initialize / remove lhapdf mode 3273 3274 if os.path.exists(pjoin(self.me_dir,'error')): 3275 os.remove(pjoin(self.me_dir,'error')) 3276 3277 self.configure_directory() 3278 # Save original random number 3279 self.random_orig = self.random 3280 logger.info("Using random number seed offset = %s" % self.random) 3281 # Update random number 3282 self.update_random() 3283 self.save_random() 3284 self.update_status('Running Survey', level=None) 3285 if self.cluster_mode: 3286 logger.info('Creating Jobs') 3287 3288 self.total_jobs = 0 3289 subproc = [l.strip() for l in open(pjoin(self.me_dir, 3290 'SubProcesses', 'subproc.mg'))] 3291 3292 P_zero_result = [] # check the number of times where they are no phase-space 3293 3294 # File for the loop (for loop induced) 3295 if os.path.exists(pjoin(self.me_dir,'SubProcesses', 3296 'MadLoop5_resources')) and cluster.need_transfer(self.options): 3297 tf=tarfile.open(pjoin(self.me_dir, 'SubProcesses', 3298 'MadLoop5_resources.tar.gz'), 'w:gz', dereference=True) 3299 tf.add(pjoin(self.me_dir,'SubProcesses','MadLoop5_resources'), 3300 arcname='MadLoop5_resources') 3301 tf.close() 3302 3303 logger.info('Working on SubProcesses') 3304 ajobcreator = gen_ximprove.gensym(self) 3305 3306 #check difficult PS case 3307 if float(self.run_card['mmjj']) > 0.01 * (float(self.run_card['ebeam1'])+float(self.run_card['ebeam2'])): 3308 self.pass_in_difficult_integration_mode() 3309 3310 jobs, P_zero_result = ajobcreator.launch() 3311 # Check if all or only some fails 3312 if P_zero_result: 3313 if len(P_zero_result) == len(subproc): 3314 Pdir = pjoin(self.me_dir, 'SubProcesses',subproc[0].strip()) 3315 raise ZeroResult, '%s' % \ 3316 open(pjoin(Pdir,'ajob.no_ps.log')).read() 3317 else: 3318 logger.warning(''' %s SubProcesses doesn\'t have available phase-space. 3319 Please check mass spectrum.''' % ','.join(P_zero_result)) 3320 3321 3322 self.monitor(run_type='All jobs submitted for survey', html=True) 3323 if not self.history or 'survey' in self.history[-1] or self.ninitial ==1 or \ 3324 self.run_card['gridpack']: 3325 #will be done during the refine (more precisely in gen_ximprove) 3326 cross, error = self.make_make_all_html_results() 3327 self.results.add_detail('cross', cross) 3328 self.results.add_detail('error', error) 3329 self.exec_cmd("print_results %s" % self.run_name, 3330 errorhandling=False, printcmd=False, precmd=False, postcmd=False) 3331 3332 self.results.add_detail('run_statistics', dict(ajobcreator.run_statistics)) 3333 self.update_status('End survey', 'parton', makehtml=False)
3334 3335 ############################################################################
3336 - def pass_in_difficult_integration_mode(self):
3337 """be more secure for the integration to not miss it due to strong cut""" 3338 3339 # improve survey options if default 3340 if self.opts['points'] == self._survey_options['points'][1]: 3341 self.opts['points'] = 2 * self._survey_options['points'][1] 3342 if self.opts['iterations'] == self._survey_options['iterations'][1]: 3343 self.opts['iterations'] = 1 + self._survey_options['iterations'][1] 3344 if self.opts['accuracy'] == self._survey_options['accuracy'][1]: 3345 self.opts['accuracy'] = self._survey_options['accuracy'][1]/2 3346 3347 # Modify run_config.inc in order to improve the refine 3348 #conf_path = pjoin(self.me_dir, 'Source','run_config.inc') 3349 #files.cp(conf_path, conf_path + '.bk') 3350 # 3351 #text = open(conf_path).read() 3352 #text = re.sub('''\(min_events = \d+\)''', '''(min_events = 7500 )''', text) 3353 #text = re.sub('''\(max_events = \d+\)''', '''(max_events = 20000 )''', text) 3354 #fsock = open(conf_path, 'w') 3355 #fsock.write(text) 3356 #fsock.close() 3357 3358 # Compile 3359 for name in ['../bin/internal/gen_ximprove', 'all', 3360 '../bin/internal/combine_events']: 3361 self.compile(arg=[name], cwd=os.path.join(self.me_dir, 'Source'))
3362 3363 3364 ############################################################################
3365 - def do_refine(self, line):
3366 """Advanced commands: launch survey for the current process """ 3367 devnull = open(os.devnull, 'w') 3368 self.nb_refine += 1 3369 args = self.split_arg(line) 3370 # Check argument's validity 3371 self.check_refine(args) 3372 3373 refine_opt = {'err_goal': args[0], 'split_channels': True} 3374 precision = args[0] 3375 if len(args) == 2: 3376 refine_opt['max_process']= args[1] 3377 3378 # initialize / remove lhapdf mode 3379 self.configure_directory() 3380 3381 # Update random number 3382 self.update_random() 3383 self.save_random() 3384 3385 if self.cluster_mode: 3386 logger.info('Creating Jobs') 3387 self.update_status('Refine results to %s' % precision, level=None) 3388 3389 self.total_jobs = 0 3390 subproc = [l.strip() for l in open(pjoin(self.me_dir,'SubProcesses', 3391 'subproc.mg'))] 3392 3393 # cleanning the previous job 3394 for nb_proc,subdir in enumerate(subproc): 3395 subdir = subdir.strip() 3396 Pdir = pjoin(self.me_dir, 'SubProcesses', subdir) 3397 for match in misc.glob('*ajob*', Pdir): 3398 if os.path.basename(match)[:4] in ['ajob', 'wait', 'run.', 'done']: 3399 os.remove(match) 3400 3401 x_improve = gen_ximprove.gen_ximprove(self, refine_opt) 3402 # Load the run statistics from the survey 3403 survey_statistics = dict(self.results.get_detail('run_statistics')) 3404 # Printout survey statistics 3405 if __debug__ and survey_statistics: 3406 globalstat = sum_html.RunStatistics() 3407 logger.debug(" === Survey statistics summary ===") 3408 for key, value in survey_statistics.items(): 3409 globalstat.aggregate_statistics(value) 3410 level = 5 3411 if value.has_warning(): 3412 level = 10 3413 logger.log(level, 3414 value.nice_output(str('/'.join([key[0],'G%s'%key[1]]))). 3415 replace(' statistics','')) 3416 logger.debug(globalstat.nice_output('combined', no_warning=True)) 3417 3418 if survey_statistics: 3419 x_improve.run_statistics = survey_statistics 3420 3421 x_improve.launch() # create the ajob for the refinment. 3422 if not self.history or 'refine' not in self.history[-1]: 3423 cross, error = x_improve.update_html() #update html results for survey 3424 if cross == 0: 3425 return 3426 logger.info("Current estimate of cross-section: %s +- %s" % (cross, error)) 3427 3428 if isinstance(x_improve, gen_ximprove.gen_ximprove_v4): 3429 # Non splitted mode is based on writting ajob so need to track them 3430 # Splitted mode handle the cluster submition internally. 3431 for nb_proc,subdir in enumerate(subproc): 3432 subdir = subdir.strip() 3433 Pdir = pjoin(self.me_dir, 'SubProcesses',subdir) 3434 bindir = pjoin(os.path.relpath(self.dirbin, Pdir)) 3435 3436 logger.info(' %s ' % subdir) 3437 3438 if os.path.exists(pjoin(Pdir, 'ajob1')): 3439 self.compile(['madevent'], cwd=Pdir) 3440 3441 alljobs = misc.glob('ajob*', Pdir) 3442 3443 #remove associated results.dat (ensure to not mix with all data) 3444 Gre = re.compile("\s*j=(G[\d\.\w]+)") 3445 for job in alljobs: 3446 Gdirs = Gre.findall(open(job).read()) 3447 for Gdir in Gdirs: 3448 if os.path.exists(pjoin(Pdir, Gdir, 'results.dat')): 3449 os.remove(pjoin(Pdir, Gdir,'results.dat')) 3450 3451 nb_tot = len(alljobs) 3452 self.total_jobs += nb_tot 3453 for i, job in enumerate(alljobs): 3454 job = os.path.basename(job) 3455 self.launch_job('%s' % job, cwd=Pdir, remaining=(nb_tot-i-1), 3456 run_type='Refine number %s on %s (%s/%s)' % 3457 (self.nb_refine, subdir, nb_proc+1, len(subproc))) 3458 3459 self.monitor(run_type='All job submitted for refine number %s' % self.nb_refine, 3460 html=True) 3461 3462 self.update_status("Combining runs", level='parton') 3463 try: 3464 os.remove(pjoin(Pdir, 'combine_runs.log')) 3465 except Exception: 3466 pass 3467 3468 if isinstance(x_improve, gen_ximprove.gen_ximprove_v4): 3469 # the merge of the events.lhe is handle in the x_improve class 3470 # for splitted runs. (and partly in store_events). 3471 combine_runs.CombineRuns(self.me_dir) 3472 self.refine_mode = "old" 3473 else: 3474 self.refine_mode = "new" 3475 3476 cross, error = self.make_make_all_html_results() 3477 self.results.add_detail('cross', cross) 3478 self.results.add_detail('error', error) 3479 3480 self.results.add_detail('run_statistics', 3481 dict(self.results.get_detail('run_statistics'))) 3482 3483 self.update_status('finish refine', 'parton', makehtml=False) 3484 devnull.close()
3485 3486 ############################################################################
3487 - def do_combine_iteration(self, line):
3488 """Not in help: Combine a given iteration combine_iteration Pdir Gdir S|R step 3489 S is for survey 3490 R is for refine 3491 step is the iteration number (not very critical)""" 3492 3493 self.set_run_name("tmp") 3494 self.configure_directory(html_opening=False) 3495 Pdir, Gdir, mode, step = self.split_arg(line) 3496 if Gdir.startswith("G"): 3497 Gdir = Gdir[1:] 3498 if "SubProcesses" not in Pdir: 3499 Pdir = pjoin(self.me_dir, "SubProcesses", Pdir) 3500 if mode == "S": 3501 self.opts = dict([(key,value[1]) for (key,value) in \ 3502 self._survey_options.items()]) 3503 gensym = gen_ximprove.gensym(self) 3504 gensym.combine_iteration(Pdir, Gdir, int(step)) 3505 elif mode == "R": 3506 refine = gen_ximprove.gen_ximprove_share(self) 3507 refine.combine_iteration(Pdir, Gdir, int(step))
3508 3509 3510 3511 3512 ############################################################################
3513 - def do_combine_events(self, line):
3514 """Advanced commands: Launch combine events""" 3515 3516 args = self.split_arg(line) 3517 # Check argument's validity 3518 self.check_combine_events(args) 3519 3520 self.update_status('Combining Events', level='parton') 3521 3522 3523 3524 if self.run_card['gridpack'] and isinstance(self, GridPackCmd): 3525 return GridPackCmd.do_combine_events(self, line) 3526 3527 # Define The Banner 3528 tag = self.run_card['run_tag'] 3529 # Update the banner with the pythia card 3530 if not self.banner: 3531 self.banner = banner_mod.recover_banner(self.results, 'parton') 3532 self.banner.load_basic(self.me_dir) 3533 # Add cross-section/event information 3534 self.banner.add_generation_info(self.results.current['cross'], self.run_card['nevents']) 3535 if not hasattr(self, 'random_orig'): self.random_orig = 0 3536 self.banner.change_seed(self.random_orig) 3537 if not os.path.exists(pjoin(self.me_dir, 'Events', self.run_name)): 3538 os.mkdir(pjoin(self.me_dir, 'Events', self.run_name)) 3539 self.banner.write(pjoin(self.me_dir, 'Events', self.run_name, 3540 '%s_%s_banner.txt' % (self.run_name, tag))) 3541 3542 3543 get_wgt = lambda event: event.wgt 3544 AllEvent = lhe_parser.MultiEventFile() 3545 AllEvent.banner = self.banner 3546 3547 partials = 0 # if too many file make some partial unweighting 3548 sum_xsec, sum_xerru, sum_axsec = 0,[],0 3549 for Gdir in self.get_Gdir(): 3550 if os.path.exists(pjoin(Gdir, 'events.lhe')): 3551 result = sum_html.OneResult('') 3552 result.read_results(pjoin(Gdir, 'results.dat')) 3553 AllEvent.add(pjoin(Gdir, 'events.lhe'), 3554 result.get('xsec'), 3555 result.get('xerru'), 3556 result.get('axsec') 3557 ) 3558 3559 sum_xsec += result.get('xsec') 3560 sum_xerru.append(result.get('xerru')) 3561 sum_axsec += result.get('axsec') 3562 3563 if len(AllEvent) >= 80: #perform a partial unweighting 3564 AllEvent.unweight(pjoin(self.me_dir, "Events", self.run_name, "partials%s.lhe.gz" % partials), 3565 get_wgt, log_level=5, trunc_error=1e-2, event_target=self.run_card['nevents']) 3566 AllEvent = lhe_parser.MultiEventFile() 3567 AllEvent.banner = self.banner 3568 AllEvent.add(pjoin(self.me_dir, "Events", self.run_name, "partials%s.lhe.gz" % partials), 3569 sum_xsec, 3570 math.sqrt(sum(x**2 for x in sum_xerru)), 3571 sum_axsec) 3572 partials +=1 3573 3574 if not hasattr(self,'proc_characteristic'): 3575 self.proc_characteristic = self.get_characteristics() 3576 if len(AllEvent) == 0: 3577 nb_event = 0 3578 else: 3579 nb_event = AllEvent.unweight(pjoin(self.me_dir, "Events", self.run_name, "unweighted_events.lhe.gz"), 3580 get_wgt, trunc_error=1e-2, event_target=self.run_card['nevents'], 3581 log_level=logging.DEBUG, normalization=self.run_card['event_norm'], 3582 proc_charac=self.proc_characteristic) 3583 3584 if partials: 3585 for i in range(partials): 3586 try: 3587 os.remove(pjoin(self.me_dir, "Events", self.run_name, "partials%s.lhe.gz" % i)) 3588 except Exception: 3589 os.remove(pjoin(self.me_dir, "Events", self.run_name, "partials%s.lhe" % i)) 3590 3591 self.results.add_detail('nb_event', nb_event) 3592 3593 if self.run_card['bias_module'].lower() not in ['dummy', 'none']: 3594 self.correct_bias() 3595 3596 3597 3598 self.to_store.append('event')
3599 3600 ############################################################################
3601 - def correct_bias(self):
3602 """check the first event and correct the weight by the bias 3603 and correct the cross-section. 3604 If the event do not have the bias tag it means that the bias is 3605 one modifying the cross-section/shape so we have nothing to do 3606 """ 3607 3608 lhe = lhe_parser.EventFile(pjoin(self.me_dir, 'Events', self.run_name, 'unweighted_events.lhe.gz')) 3609 init = False 3610 cross = collections.defaultdict(float) 3611 nb_event = 0 3612 for event in lhe: 3613 rwgt_info = event.parse_reweight() 3614 if not init: 3615 if 'bias' in rwgt_info: 3616 output = lhe_parser.EventFile(pjoin(self.me_dir, 'Events', self.run_name, '.unweighted_events.lhe.tmp.gz'),'w') 3617 #output.write(lhe.banner) 3618 init = True 3619 else: 3620 return 3621 #change the weight 3622 event.wgt /= rwgt_info['bias'] 3623 #remove the bias info 3624 del event.reweight_data['bias'] 3625 # compute the new cross-section 3626 cross[event.ievent] += event.wgt 3627 nb_event +=1 3628 output.write(str(event)) 3629 output.write('</LesHouchesEvents>') 3630 output.close() 3631 lhe.close() 3632 3633 # MODIFY THE BANNER i.e. INIT BLOCK 3634 # ensure information compatible with normalisation choice 3635 total_cross = sum(cross[key] for key in cross) 3636 if 'event_norm' in self.run_card: # if not this is "sum" 3637 if self.run_card['event_norm'] == 'average': 3638 total_cross = total_cross / nb_event 3639 for key in cross: 3640 cross[key] /= nb_event 3641 elif self.run_card['event_norm'] == 'unity': 3642 total_cross = self.results.current['cross'] * total_cross / nb_event 3643 for key in cross: 3644 cross[key] *= total_cross / nb_event 3645 3646 bannerfile = lhe_parser.EventFile(pjoin(self.me_dir, 'Events', self.run_name, '.banner.tmp.gz'),'w') 3647 banner = banner_mod.Banner(lhe.banner) 3648 banner.modify_init_cross(cross) 3649 banner.set_lha_strategy(-4) 3650 banner.write(bannerfile, close_tag=False) 3651 bannerfile.close() 3652 # replace the lhe file by the new one 3653 if lhe.name.endswith('.gz'): 3654 os.system('cat %s %s > %s' %(bannerfile.name, output.name, lhe.name)) 3655 else: 3656 os.system('cat %s %s > %s.gz' %(bannerfile.name, output.name, lhe.name)) 3657 os.remove(lhe.name) 3658 os.remove(bannerfile.name) 3659 os.remove(output.name) 3660 3661 3662 self.results.current['cross'] = total_cross 3663 self.results.current['error'] = 0
3664 3665 ############################################################################
3666 - def do_store_events(self, line):
3667 """Advanced commands: Launch store events""" 3668 3669 args = self.split_arg(line) 3670 # Check argument's validity 3671 self.check_combine_events(args) 3672 self.update_status('Storing parton level results', level='parton') 3673 3674 run = self.run_name 3675 tag = self.run_card['run_tag'] 3676 devnull = open(os.devnull, 'w') 3677 3678 if not os.path.exists(pjoin(self.me_dir, 'Events', run)): 3679 os.mkdir(pjoin(self.me_dir, 'Events', run)) 3680 if not os.path.exists(pjoin(self.me_dir, 'HTML', run)): 3681 os.mkdir(pjoin(self.me_dir, 'HTML', run)) 3682 3683 # 1) Store overall process information 3684 #input = pjoin(self.me_dir, 'SubProcesses', 'results.dat') 3685 #output = pjoin(self.me_dir, 'SubProcesses', '%s_results.dat' % run) 3686 #files.cp(input, output) 3687 3688 3689 # 2) Treat the files present in the P directory 3690 # Ensure that the number of events is different of 0 3691 if self.results.current['nb_event'] == 0 and not self.run_card['gridpack']: 3692 logger.warning("No event detected. No cleaning performed! This should allow to run:\n" + 3693 " cd Subprocesses; ../bin/internal/combine_events\n"+ 3694 " to have your events if those one are missing.") 3695 else: 3696 for G_path in self.get_Gdir(): 3697 try: 3698 # Remove events file (if present) 3699 if os.path.exists(pjoin(G_path, 'events.lhe')): 3700 os.remove(pjoin(G_path, 'events.lhe')) 3701 except Exception: 3702 continue 3703 #try: 3704 # # Store results.dat 3705 # if os.path.exists(pjoin(G_path, 'results.dat')): 3706 # input = pjoin(G_path, 'results.dat') 3707 # output = pjoin(G_path, '%s_results.dat' % run) 3708 # files.cp(input, output) 3709 #except Exception: 3710 # continue 3711 # Store log 3712 try: 3713 if os.path.exists(pjoin(G_path, 'log.txt')): 3714 input = pjoin(G_path, 'log.txt') 3715 output = pjoin(G_path, '%s_log.txt' % run) 3716 files.mv(input, output) 3717 except Exception: 3718 continue 3719 #try: 3720 # # Grid 3721 # for name in ['ftn26']: 3722 # if os.path.exists(pjoin(G_path, name)): 3723 # if os.path.exists(pjoin(G_path, '%s_%s.gz'%(run,name))): 3724 # os.remove(pjoin(G_path, '%s_%s.gz'%(run,name))) 3725 # input = pjoin(G_path, name) 3726 # output = pjoin(G_path, '%s_%s' % (run,name)) 3727 # files.mv(input, output) 3728 # misc.gzip(pjoin(G_path, output), error=None) 3729 #except Exception: 3730 # continue 3731 # Delete ftn25 to ensure reproducible runs 3732 if os.path.exists(pjoin(G_path, 'ftn25')): 3733 os.remove(pjoin(G_path, 'ftn25')) 3734 3735 # 3) Update the index.html 3736 self.gen_card_html() 3737 3738 3739 # 4) Move the Files present in Events directory 3740 E_path = pjoin(self.me_dir, 'Events') 3741 O_path = pjoin(self.me_dir, 'Events', run) 3742 3743 # The events file 3744 for name in ['events.lhe', 'unweighted_events.lhe']: 3745 finput = pjoin(E_path, name) 3746 foutput = pjoin(O_path, name) 3747 if os.path.exists(finput): 3748 logger.debug("File %s exists BAAAAD. Not move anymore!" % pjoin(E_path, name)) 3749 if os.path.exists(foutput): 3750 misc.gzip(foutput, stdout="%s.gz" % foutput, error=False) 3751 # if os.path.exists(pjoin(O_path, '%s.gz' % name)): 3752 # os.remove(pjoin(O_path, '%s.gz' % name)) 3753 # input = pjoin(E_path, name) 3754 ## output = pjoin(O_path, name) 3755 3756 3757 self.update_status('End Parton', level='parton', makehtml=False) 3758 devnull.close()
3759 3760 3761 ############################################################################
3762 - def do_create_gridpack(self, line):
3763 """Advanced commands: Create gridpack from present run""" 3764 3765 self.update_status('Creating gridpack', level='parton') 3766 # compile gen_ximprove 3767 misc.compile(['../bin/internal/gen_ximprove'], cwd=pjoin(self.me_dir, "Source")) 3768 args = self.split_arg(line) 3769 self.check_combine_events(args) 3770 if not self.run_tag: self.run_tag = 'tag_1' 3771 os.system("sed -i.bak \"s/ *.false.*=.*GridRun/ .true. = GridRun/g\" %s/Cards/grid_card.dat" \ 3772 % self.me_dir) 3773 misc.call(['./bin/internal/restore_data', self.run_name], 3774 cwd=self.me_dir) 3775 misc.call(['./bin/internal/store4grid', 3776 self.run_name, self.run_tag], 3777 cwd=self.me_dir) 3778 misc.call(['./bin/internal/clean'], cwd=self.me_dir) 3779 misc.call(['./bin/internal/make_gridpack'], cwd=self.me_dir) 3780 files.mv(pjoin(self.me_dir, 'gridpack.tar.gz'), 3781 pjoin(self.me_dir, '%s_gridpack.tar.gz' % self.run_name)) 3782 os.system("sed -i.bak \"s/\s*.true.*=.*GridRun/ .false. = GridRun/g\" %s/Cards/grid_card.dat" \ 3783 % self.me_dir) 3784 self.update_status('gridpack created', level='gridpack')
3785 3786 ############################################################################
3787 - def do_shower(self, line):
3788 """launch the shower""" 3789 3790 args = self.split_arg(line) 3791 if len(args)>1 and args[0] in self._interfaced_showers: 3792 chosen_showers = [args.pop(0)] 3793 elif '--no_default' in line: 3794 # If '--no_default' was specified in the arguments, then only one 3795 # shower will be run, depending on which card is present. 3796 # but we each of them are called. (each of them check if the file exists) 3797 chosen_showers = list(self._interfaced_showers) 3798 else: 3799 chosen_showers = list(self._interfaced_showers) 3800 # It is preferable to run only one shower, even if several are available and no 3801 # specific one has been selected 3802 shower_priority = ['pythia8','pythia'] 3803 chosen_showers = [sorted(chosen_showers,key=lambda sh: 3804 shower_priority.index(sh) if sh in shower_priority else len(shower_priority)+1)[0]] 3805 3806 for shower in chosen_showers: 3807 self.exec_cmd('%s %s'%(shower,' '.join(args)), 3808 postcmd=False, printcmd=False)
3809
3810 - def do_madanalysis5_parton(self, line):
3811 """launch MadAnalysis5 at the parton level.""" 3812 return self.run_madanalysis5(line,mode='parton')
3813 3814 #=============================================================================== 3815 # Return a warning (if applicable) on the consistency of the current Pythia8 3816 # and MG5_aMC version specified. It is placed here because it should be accessible 3817 # from both madgraph5_interface and madevent_interface 3818 #=============================================================================== 3819 @staticmethod
3820 - def mg5amc_py8_interface_consistency_warning(options):
3821 """ Check the consistency of the mg5amc_py8_interface installed with 3822 the current MG5 and Pythia8 versions. """ 3823 3824 # All this is only relevant is Pythia8 is interfaced to MG5 3825 if not options['pythia8_path']: 3826 return None 3827 3828 if not options['mg5amc_py8_interface_path']: 3829 return \ 3830 """ 3831 A Pythia8 path is specified via the option 'pythia8_path' but no path for option 3832 'mg5amc_py8_interface_path' is specified. This means that Pythia8 cannot be used 3833 leading order simulations with MadEvent. 3834 Consider installing the MG5_aMC-PY8 interface with the following command: 3835 MG5_aMC>install mg5amc_py8_interface 3836 """ 3837 3838 mg5amc_py8_interface_path = options['mg5amc_py8_interface_path'] 3839 py8_path = options['pythia8_path'] 3840 # If the specified interface path is relative, make it absolut w.r.t MGDIR if 3841 # avaialble. 3842 if not MADEVENT: 3843 mg5amc_py8_interface_path = pjoin(MG5DIR,mg5amc_py8_interface_path) 3844 py8_path = pjoin(MG5DIR,py8_path) 3845 3846 # Retrieve all the on-install and current versions 3847 fsock = open(pjoin(mg5amc_py8_interface_path, 'MG5AMC_VERSION_ON_INSTALL')) 3848 MG5_version_on_install = fsock.read().replace('\n','') 3849 fsock.close() 3850 if MG5_version_on_install == 'UNSPECIFIED': 3851 MG5_version_on_install = None 3852 fsock = open(pjoin(mg5amc_py8_interface_path, 'PYTHIA8_VERSION_ON_INSTALL')) 3853 PY8_version_on_install = fsock.read().replace('\n','') 3854 fsock.close() 3855 MG5_curr_version =misc.get_pkg_info()['version'] 3856 try: 3857 p = subprocess.Popen(['./get_pythia8_version.py',py8_path], 3858 stdout=subprocess.PIPE, stderr=subprocess.PIPE, 3859 cwd=mg5amc_py8_interface_path) 3860 (out, err) = p.communicate() 3861 out = out.replace('\n','') 3862 PY8_curr_version = out 3863 # In order to test that the version is correctly formed, we try to cast 3864 # it to a float 3865 float(out) 3866 except: 3867 PY8_curr_version = None 3868 3869 if not MG5_version_on_install is None and not MG5_curr_version is None: 3870 if MG5_version_on_install != MG5_curr_version: 3871 return \ 3872 """ 3873 The current version of MG5_aMC (v%s) is different than the one active when 3874 installing the 'mg5amc_py8_interface_path' (which was MG5aMC v%s). 3875 Please consider refreshing the installation of this interface with the command: 3876 MG5_aMC>install mg5amc_py8_interface 3877 """%(MG5_curr_version, MG5_version_on_install) 3878 3879 if not PY8_version_on_install is None and not PY8_curr_version is None: 3880 if PY8_version_on_install != PY8_curr_version: 3881 return \ 3882 """ 3883 The current version of Pythia8 (v%s) is different than the one active when 3884 installing the 'mg5amc_py8_interface' tool (which was Pythia8 v%s). 3885 Please consider refreshing the installation of this interface with the command: 3886 MG5_aMC>install mg5amc_py8_interface 3887 """%(PY8_curr_version,PY8_version_on_install) 3888 3889 return None
3890
3891 - def setup_Pythia8RunAndCard(self, PY8_Card, run_type):
3892 """ Setup the Pythia8 Run environment and card. In particular all the process and run specific parameters 3893 of the card are automatically set here. This function returns the path where HEPMC events will be output, 3894 if any.""" 3895 3896 HepMC_event_output = None 3897 tag = self.run_tag 3898 3899 PY8_Card.subruns[0].systemSet('Beams:LHEF',"unweighted_events.lhe.gz") 3900 3901 if PY8_Card['HEPMCoutput:file']=='auto': 3902 HepMC_event_output = pjoin(self.me_dir,'Events', self.run_name, 3903 '%s_pythia8_events.hepmc'%tag) 3904 PY8_Card.MadGraphSet('HEPMCoutput:file','%s_pythia8_events.hepmc'%tag, force=True) 3905 elif PY8_Card['HEPMCoutput:file'].startswith('fifo'): 3906 fifo_specs = PY8_Card['HEPMCoutput:file'].split('@') 3907 fifo_path = None 3908 if len(fifo_specs)<=1: 3909 fifo_path = pjoin(self.me_dir,'Events', self.run_name,'PY8.hepmc.fifo') 3910 if os.path.exists(fifo_path): 3911 os.remove(fifo_path) 3912 misc.mkfifo(fifo_path) 3913 # Use defaultSet not to overwrite the current userSet status 3914 PY8_Card.defaultSet('HEPMCoutput:file','PY8.hepmc.fifo') 3915 else: 3916 fifo_path = fifo_specs[1] 3917 if os.path.exists(fifo_path): 3918 if stat.S_ISFIFO(os.stat(fifo_path).st_mode): 3919 logger.warning('PY8 will be reusing already existing '+ 3920 'custom fifo file at:\n %s'%fifo_path) 3921 else: 3922 raise InvalidCmd( 3923 """The fifo path speficied for the PY8 parameter 'HEPMCoutput:file': 3924 %s 3925 already exists and is not a fifo file."""%fifo_path) 3926 else: 3927 misc.mkfifo(fifo_path) 3928 # Use defaultSet not to overwrite the current userSet status 3929 PY8_Card.defaultSet('HEPMCoutput:file',fifo_path) 3930 HepMC_event_output=fifo_path 3931 elif PY8_Card['HEPMCoutput:file'] in ['','/dev/null','None']: 3932 logger.warning('User disabled the HepMC output of Pythia8.') 3933 HepMC_event_output = None 3934 else: 3935 # Normalize the relative path if given as relative by the user. 3936 HepMC_event_output = pjoin(self.me_dir,'Events', self.run_name, 3937 PY8_Card['HEPMCoutput:file']) 3938 3939 # We specify by hand all necessary parameters, so that there is no 3940 # need to read parameters from the Banner. 3941 PY8_Card.MadGraphSet('JetMatching:setMad', False) 3942 if run_type=='MLM': 3943 # When running MLM make sure that we do not write out the parameter 3944 # Merging:xxx as this can interfere with the MLM merging in older 3945 # versions of the driver. 3946 PY8_Card.vetoParamWriteOut('Merging:TMS') 3947 PY8_Card.vetoParamWriteOut('Merging:Process') 3948 PY8_Card.vetoParamWriteOut('Merging:nJetMax') 3949 # MadGraphSet sets the corresponding value (in system mode) 3950 # only if it is not already user_set. 3951 if PY8_Card['JetMatching:qCut']==-1.0: 3952 PY8_Card.MadGraphSet('JetMatching:qCut',1.5*self.run_card['xqcut'], force=True) 3953 3954 if PY8_Card['JetMatching:qCut']<(1.5*self.run_card['xqcut']): 3955 logger.error( 3956 'The MLM merging qCut parameter you chose (%f) is less than '%PY8_Card['JetMatching:qCut']+ 3957 '1.5*xqcut, with xqcut your run_card parameter (=%f).\n'%self.run_card['xqcut']+ 3958 'It would be better/safer to use a larger qCut or a smaller xqcut.') 3959 3960 # Also make sure to use the shower starting scales specified in the LHE 3961 # unless the user specified it 3962 PY8_Card.systemSet('Beams:setProductionScalesFromLHEF',True) 3963 3964 # Automatically set qWeed to xqcut if not defined by the user. 3965 if PY8_Card['SysCalc:qWeed']==-1.0: 3966 PY8_Card.MadGraphSet('SysCalc:qWeed',self.run_card['xqcut'], force=True) 3967 3968 if PY8_Card['SysCalc:qCutList']=='auto': 3969 if self.run_card['use_syst']: 3970 if self.run_card['sys_matchscale']=='auto': 3971 qcut = PY8_Card['JetMatching:qCut'] 3972 value = [factor*qcut for factor in [0.5,0.75,1.0,1.5,2.0] if\ 3973 factor*qcut> 1.5*self.run_card['xqcut'] ] 3974 PY8_Card.MadGraphSet('SysCalc:qCutList', value, force=True) 3975 else: 3976 qCutList = [float(qc) for qc in self.run_card['sys_matchscale'].split()] 3977 if PY8_Card['JetMatching:qCut'] not in qCutList: 3978 qCutList.append(PY8_Card['JetMatching:qCut']) 3979 PY8_Card.MadGraphSet('SysCalc:qCutList', qCutList, force=True) 3980 3981 for scale in PY8_Card['SysCalc:qCutList']: 3982 if scale<(1.5*self.run_card['xqcut']): 3983 logger.error( 3984 'One of the MLM merging qCut parameter you chose (%f) in the variation list'%scale+\ 3985 " (either via 'SysCalc:qCutList' in the PY8 shower card or "+\ 3986 "'sys_matchscale' in the run_card) is less than 1.5*xqcut, where xqcut is"+ 3987 ' the run_card parameter (=%f)\n'%self.run_card['xqcut']+ 3988 'It would be better/safer to use a larger qCut or a smaller xqcut.') 3989 3990 # Specific MLM settings 3991 # PY8 should not implement the MLM veto since the driver should do it 3992 # if merging scale variation is turned on 3993 if self.run_card['use_syst']: 3994 # We do no force it here, but it is clear that the user should know what 3995 # he's doing if he were to force it to True. 3996 PY8_Card.MadGraphSet('JetMatching:doVeto',False) 3997 PY8_Card.MadGraphSet('JetMatching:merge',True) 3998 PY8_Card.MadGraphSet('JetMatching:scheme',1) 3999 # Use the parameter maxjetflavor for JetMatching:nQmatch which specifies 4000 # up to which parton must be matched.Merging:nQuarksMerge 4001 PY8_Card.MadGraphSet('JetMatching:nQmatch',self.run_card['maxjetflavor']) 4002 # For MLM, a cone radius of 1.0 is to be prefered. 4003 PY8_Card.MadGraphSet('JetMatching:coneRadius',1.0) 4004 # And the value of etaj_max is already infinity by default. 4005 # PY8_Card.MadGraphSet('JetMatching:etaJetMax',1000.0) 4006 if not hasattr(self,'proc_characteristic'): 4007 self.proc_characteristic = self.get_characteristics() 4008 nJetMax = self.proc_characteristic['max_n_matched_jets'] 4009 if PY8_Card['JetMatching:nJetMax'.lower()] == -1: 4010 logger.info("No user-defined value for Pythia8 parameter "+ 4011 "'JetMatching:nJetMax'. Setting it automatically to %d."%nJetMax) 4012 PY8_Card.MadGraphSet('JetMatching:nJetMax',nJetMax, force=True) 4013 # We use the positivity of 'ktdurham' cut as a CKKWl marker. 4014 elif run_type=='CKKW': 4015 4016 # Make sure the user correctly filled in the lowest order process to be considered 4017 if PY8_Card['Merging:Process']=='<set_by_user>': 4018 raise self.InvalidCmd('When running CKKWl merging, the user must'+ 4019 " specifiy the option 'Merging:Process' in pythia8_card.dat.\n"+ 4020 "Read section 'Defining the hard process' of "+\ 4021 "http://home.thep.lu.se/~torbjorn/pythia81html/CKKWLMerging.html for more information.") 4022 4023 # When running CKKWL make sure that we do not write out the parameter 4024 # JetMatching:xxx as this can interfere with the MLM merging in older 4025 # versions of the driver. 4026 PY8_Card.vetoParamWriteOut('JetMatching:qCut') 4027 PY8_Card.vetoParamWriteOut('JetMatching:doShowerKt') 4028 PY8_Card.vetoParamWriteOut('JetMatching:nJetMax') 4029 4030 CKKW_cut = None 4031 # Specific CKKW settings 4032 if self.run_card['ptlund']<=0.0 and self.run_card['ktdurham']>0.0: 4033 PY8_Card.subruns[0].MadGraphSet('Merging:doKTMerging',True) 4034 PY8_Card.subruns[0].MadGraphSet('Merging:Dparameter', 4035 self.run_card['dparameter']) 4036 CKKW_cut = 'ktdurham' 4037 elif self.run_card['ptlund']>0.0 and self.run_card['ktdurham']<=0.0: 4038 PY8_Card.subruns[0].MadGraphSet('Merging:doPTLundMerging',True) 4039 CKKW_cut = 'ptlund' 4040 else: 4041 raise InvalidCmd("*Either* the 'ptlund' or 'ktdurham' cut in "+\ 4042 " the run_card must be turned on to activate CKKW(L) merging"+ 4043 " with Pythia8, but *both* cuts cannot be turned on at the same time."+ 4044 "\n ptlund=%f, ktdurham=%f."%(self.run_card['ptlund'],self.run_card['ktdurham'])) 4045 4046 4047 # Automatically set qWeed to the CKKWL cut if not defined by the user. 4048 if PY8_Card['SysCalc:qWeed']==-1.0: 4049 PY8_Card.MadGraphSet('SysCalc:qWeed',self.run_card[CKKW_cut], force=True) 4050 4051 # MadGraphSet sets the corresponding value (in system mode) 4052 # only if it is not already user_set. 4053 if PY8_Card['Merging:TMS']==-1.0: 4054 if self.run_card[CKKW_cut]>0.0: 4055 PY8_Card.MadGraphSet('Merging:TMS',self.run_card[CKKW_cut], force=True) 4056 else: 4057 raise self.InvalidCmd('When running CKKWl merging, the user'+\ 4058 " select a '%s' cut larger than 0.0 in the run_card."%CKKW_cut) 4059 if PY8_Card['Merging:TMS']<self.run_card[CKKW_cut]: 4060 logger.error( 4061 'The CKKWl merging scale you chose (%f) is less than '%PY8_Card['Merging:TMS']+ 4062 'the %s cut specified in the run_card parameter (=%f).\n'%(CKKW_cut,self.run_card[CKKW_cut])+ 4063 'It is incorrect to use a smaller CKKWl scale than the generation-level %s cut!'%CKKW_cut) 4064 4065 PY8_Card.MadGraphSet('TimeShower:pTmaxMatch',1) 4066 PY8_Card.MadGraphSet('SpaceShower:pTmaxMatch',1) 4067 PY8_Card.MadGraphSet('SpaceShower:rapidityOrder',False) 4068 # PY8 should not implement the CKKW veto since the driver should do it. 4069 if self.run_card['use_syst']: 4070 # We do no force it here, but it is clear that the user should know what 4071 # he's doing if he were to force it to True. 4072 PY8_Card.MadGraphSet('Merging:applyVeto',False) 4073 PY8_Card.MadGraphSet('Merging:includeWeightInXsection',False) 4074 # Use the parameter maxjetflavor for Merging:nQuarksMerge which specifies 4075 # up to which parton must be matched. 4076 PY8_Card.MadGraphSet('Merging:nQuarksMerge',self.run_card['maxjetflavor']) 4077 if not hasattr(self,'proc_characteristic'): 4078 self.proc_characteristic = self.get_characteristics() 4079 nJetMax = self.proc_characteristic['max_n_matched_jets'] 4080 if PY8_Card['Merging:nJetMax'.lower()] == -1: 4081 logger.info("No user-defined value for Pythia8 parameter "+ 4082 "'Merging:nJetMax'. Setting it automatically to %d."%nJetMax) 4083 PY8_Card.MadGraphSet('Merging:nJetMax',nJetMax, force=True) 4084 if PY8_Card['SysCalc:tmsList']=='auto': 4085 if self.run_card['use_syst']: 4086 if self.run_card['sys_matchscale']=='auto': 4087 tms = PY8_Card["Merging:TMS"] 4088 value = [factor*tms for factor in [0.5,0.75,1.0,1.5,2.0] 4089 if factor*tms > self.run_card[CKKW_cut]] 4090 PY8_Card.MadGraphSet('SysCalc:tmsList', value, force=True) 4091 else: 4092 tmsList = [float(tms) for tms in self.run_card['sys_matchscale'].split()] 4093 if PY8_Card['Merging:TMS'] not in tmsList: 4094 tmsList.append(PY8_Card['Merging:TMS']) 4095 PY8_Card.MadGraphSet('SysCalc:tmsList', tmsList, force=True) 4096 4097 for scale in PY8_Card['SysCalc:tmsList']: 4098 if scale<self.run_card[CKKW_cut]: 4099 logger.error( 4100 'One of the CKKWl merging scale you chose (%f) in the variation list'%scale+\ 4101 " (either via 'SysCalc:tmsList' in the PY8 shower card or "+\ 4102 "'sys_matchscale' in the run_card) is less than %f, "%self.run_card[CKKW_cut]+ 4103 'the %s cut specified in the run_card parameter.\n'%CKKW_cut+ 4104 'It is incorrect to use a smaller CKKWl scale than the generation-level %s cut!'%CKKW_cut) 4105 else: 4106 # When not performing any merging, make sure that we do not write out the parameter 4107 # JetMatching:xxx or Merging:xxx as this can trigger undesired vetos in an unmerged 4108 # simulation. 4109 PY8_Card.vetoParamWriteOut('Merging:TMS') 4110 PY8_Card.vetoParamWriteOut('Merging:Process') 4111 PY8_Card.vetoParamWriteOut('Merging:nJetMax') 4112 PY8_Card.vetoParamWriteOut('JetMatching:qCut') 4113 PY8_Card.vetoParamWriteOut('JetMatching:doShowerKt') 4114 PY8_Card.vetoParamWriteOut('JetMatching:nJetMax') 4115 4116 return HepMC_event_output
4117
4118 - def do_pythia8(self, line):
4119 """launch pythia8""" 4120 4121 4122 try: 4123 import madgraph 4124 except ImportError: 4125 import internal.histograms as histograms 4126 else: 4127 import madgraph.various.histograms as histograms 4128 4129 # Check argument's validity 4130 args = self.split_arg(line) 4131 if '--no_default' in args: 4132 if not os.path.exists(pjoin(self.me_dir, 'Cards', 'pythia8_card.dat')): 4133 return 4134 no_default = True 4135 args.remove('--no_default') 4136 else: 4137 no_default = False 4138 4139 if not self.run_name: 4140 self.check_pythia8(args) 4141 self.configure_directory(html_opening =False) 4142 else: 4143 # initialize / remove lhapdf mode 4144 self.configure_directory(html_opening =False) 4145 self.check_pythia8(args) 4146 4147 # Update the banner with the pythia card 4148 if not self.banner or len(self.banner) <=1: 4149 # Here the level keyword 'pythia' must not be changed to 'pythia8'. 4150 self.banner = banner_mod.recover_banner(self.results, 'pythia') 4151 4152 # the args are modify and the last arg is always the mode 4153 if not no_default: 4154 self.ask_pythia_run_configuration(args[-1], pythia_version=8, banner=self.banner) 4155 4156 if self.options['automatic_html_opening']: 4157 misc.open_file(os.path.join(self.me_dir, 'crossx.html')) 4158 self.options['automatic_html_opening'] = False 4159 4160 if self.run_card['event_norm'] not in ['unit','average']: 4161 logger.critical("Pythia8 does not support normalization to the sum. Not running Pythia8") 4162 return 4163 #\n"+\ 4164 #"The normalisation of the hepmc output file will be wrong (i.e. non-standard).\n"+\ 4165 #"Please use 'event_norm = average' in the run_card to avoid this problem.") 4166 4167 4168 4169 if not self.options['mg5amc_py8_interface_path'] or not \ 4170 os.path.exists(pjoin(self.options['mg5amc_py8_interface_path'], 4171 'MG5aMC_PY8_interface')): 4172 raise self.InvalidCmd( 4173 """The MG5aMC_PY8_interface tool cannot be found, so that MadEvent cannot steer Pythia8 shower. 4174 Please install this tool with the following MG5_aMC command: 4175 MG5_aMC> install mg5amc_py8_interface_path""") 4176 else: 4177 pythia_main = pjoin(self.options['mg5amc_py8_interface_path'], 4178 'MG5aMC_PY8_interface') 4179 warnings = MadEventCmd.mg5amc_py8_interface_consistency_warning(self.options) 4180 if warnings: 4181 logger.warning(warnings) 4182 4183 self.results.add_detail('run_mode', 'madevent') 4184 4185 # Again here 'pythia' is just a keyword for the simulation level. 4186 self.update_status('\033[92mRunning Pythia8 [arXiv:1410.3012]\033[0m', 'pythia8') 4187 4188 tag = self.run_tag 4189 # Now write Pythia8 card 4190 # Start by reading, starting from the default one so that the 'user_set' 4191 # tag are correctly set. 4192 PY8_Card = banner_mod.PY8Card(pjoin(self.me_dir, 'Cards', 4193 'pythia8_card_default.dat')) 4194 PY8_Card.read(pjoin(self.me_dir, 'Cards', 'pythia8_card.dat'), 4195 setter='user') 4196 4197 run_type = 'default' 4198 merged_run_types = ['MLM','CKKW'] 4199 if int(self.run_card['ickkw'])==1: 4200 run_type = 'MLM' 4201 elif int(self.run_card['ickkw'])==2 or \ 4202 self.run_card['ktdurham']>0.0 or self.run_card['ptlund']>0.0: 4203 run_type = 'CKKW' 4204 4205 # Edit the card and run environment according to the run specification 4206 HepMC_event_output = self.setup_Pythia8RunAndCard(PY8_Card, run_type) 4207 4208 # Now write the card. 4209 pythia_cmd_card = pjoin(self.me_dir, 'Events', self.run_name , 4210 '%s_pythia8.cmd' % tag) 4211 cmd_card = StringIO.StringIO() 4212 PY8_Card.write(cmd_card,pjoin(self.me_dir,'Cards','pythia8_card_default.dat'), 4213 direct_pythia_input=True) 4214 4215 # Now setup the preamble to make sure that everything will use the locally 4216 # installed tools (if present) even if the user did not add it to its 4217 # environment variables. 4218 if 'heptools_install_dir' in self.options: 4219 preamble = misc.get_HEPTools_location_setter( 4220 self.options['heptools_install_dir'],'lib') 4221 else: 4222 if MADEVENT: 4223 preamble = misc.get_HEPTools_location_setter( 4224 pjoin(self.options['mg5amc_py8_interface_path'],os.pardir),'lib') 4225 else: 4226 preamble = misc.get_HEPTools_location_setter( 4227 pjoin(MG5DIR,'HEPTools'),'lib') 4228 4229 open(pythia_cmd_card,'w').write("""! 4230 ! It is possible to run this card manually with: 4231 ! %s %s 4232 ! 4233 """%(preamble+pythia_main,os.path.basename(pythia_cmd_card))+cmd_card.getvalue()) 4234 4235 # launch pythia8 4236 pythia_log = pjoin(self.me_dir , 'Events', self.run_name , 4237 '%s_pythia8.log' % tag) 4238 4239 # Write a bash wrapper to run the shower with custom environment variables 4240 wrapper_path = pjoin(self.me_dir,'Events',self.run_name,'run_shower.sh') 4241 wrapper = open(wrapper_path,'w') 4242 shell = 'bash' if misc.get_shell_type() in ['bash',None] else 'tcsh' 4243 shell_exe = None 4244 if os.path.exists('/usr/bin/env'): 4245 shell_exe = '/usr/bin/env %s'%shell 4246 else: 4247 shell_exe = misc.which(shell) 4248 if not shell_exe: 4249 raise self.InvalidCmd('No s hell could be found in your environment.\n'+ 4250 "Make sure that either '%s' is in your path or that the"%shell+\ 4251 " command '/usr/bin/env %s' exists and returns a valid path."%shell) 4252 4253 exe_cmd = "#!%s\n%s"%(shell_exe,' '.join( 4254 [preamble+pythia_main, 4255 os.path.basename(pythia_cmd_card)])) 4256 4257 wrapper.write(exe_cmd) 4258 wrapper.close() 4259 4260 # Set it as executable 4261 st = os.stat(wrapper_path) 4262 os.chmod(wrapper_path, st.st_mode | stat.S_IEXEC) 4263 4264 # If the target HEPMC output file is a fifo, don't hang MG5_aMC and let 4265 # it proceed. 4266 is_HepMC_output_fifo = False if not HepMC_event_output else \ 4267 ( os.path.exists(HepMC_event_output) and \ 4268 stat.S_ISFIFO(os.stat(HepMC_event_output).st_mode)) 4269 startPY8timer = time.time() 4270 4271 # Information that will be extracted from this PY8 run 4272 PY8_extracted_information={ 'sigma_m':None, 'Nacc':None, 'Ntry':None, 4273 'cross_sections':{} } 4274 4275 if is_HepMC_output_fifo: 4276 logger.info( 4277 """Pythia8 is set to output HEPMC events to to a fifo file. 4278 You can follow PY8 run with the following command (in a separate terminal): 4279 tail -f %s"""%pythia_log ) 4280 py8_log = open( pythia_log,'w') 4281 py8_bkgrd_proc = misc.Popen([wrapper_path], 4282 stdout=py8_log,stderr=py8_log, 4283 cwd=pjoin(self.me_dir,'Events',self.run_name)) 4284 # Now directly return to madevent interactive interface if we are piping PY8 4285 if not no_default: 4286 logger.info('You can now run a tool that reads the following fifo file:'+\ 4287 '\n %s\nwhere PY8 outputs HEPMC events (e.g. MadAnalysis5).' 4288 %HepMC_event_output,'$MG:color:GREEN') 4289 return 4290 else: 4291 if self.options ['run_mode']!=0: 4292 # Start a parallelization instance (stored in self.cluster) 4293 self.configure_run_mode(self.options['run_mode']) 4294 if self.options['run_mode']==1: 4295 n_cores = max(self.options['cluster_size'],1) 4296 elif self.options['run_mode']==2: 4297 n_cores = max(self.cluster.nb_core,1) 4298 4299 lhe_file_name = os.path.basename(PY8_Card.subruns[0]['Beams:LHEF']) 4300 lhe_file = lhe_parser.EventFile(pjoin(self.me_dir,'Events', 4301 self.run_name,PY8_Card.subruns[0]['Beams:LHEF'])) 4302 n_available_events = len(lhe_file) 4303 if PY8_Card['Main:numberOfEvents']==-1: 4304 n_events = n_available_events 4305 else: 4306 n_events = PY8_Card['Main:numberOfEvents'] 4307 if n_events > n_available_events: 4308 raise self.InvalidCmd, 'You specified more events (%d) in the PY8 parameter'%n_events+\ 4309 "'Main:numberOfEvents' than the total number of events available (%d)"%n_available_events+\ 4310 ' in the event file:\n %s'%pjoin(self.me_dir,'Events',self.run_name,PY8_Card.subruns[0]['Beams:LHEF']) 4311 4312 # Implement a security to insure a minimum numbe of events per job 4313 if self.options['run_mode']==2: 4314 min_n_events_per_job = 100 4315 elif self.options['run_mode']==1: 4316 min_n_events_per_job = 1000 4317 min_n_core = n_events//min_n_events_per_job 4318 n_cores = max(min(min_n_core,n_cores),1) 4319 4320 if self.options['run_mode']==0 or (self.options['run_mode']==2 and self.options['nb_core']==1): 4321 # No need for parallelization anymore 4322 self.cluster = None 4323 logger.info('Follow Pythia8 shower by running the '+ 4324 'following command (in a separate terminal):\n tail -f %s'%pythia_log) 4325 4326 if self.options['run_mode']==2 and self.options['nb_core']>1: 4327 ret_code = self.cluster.launch_and_wait(wrapper_path, 4328 argument= [], stdout= pythia_log, stderr=subprocess.STDOUT, 4329 cwd=pjoin(self.me_dir,'Events',self.run_name)) 4330 else: 4331 stdout = open(pythia_log,'w') 4332 ret_code = misc.call(wrapper_path, stdout=stdout, stderr=subprocess.STDOUT, 4333 cwd=pjoin(self.me_dir,'Events',self.run_name)) 4334 stdout.close() 4335 if ret_code != 0: 4336 raise self.InvalidCmd, 'Pythia8 shower interrupted with return'+\ 4337 ' code %d.\n'%ret_code+\ 4338 'You can find more information in this log file:\n%s'%pythia_log 4339 else: 4340 if self.run_card['event_norm']=='sum': 4341 logger.error("") 4342 logger.error("Either run in single core or change event_norm to 'average'.") 4343 raise InvalidCmd("Pythia8 parallelization with event_norm set to 'sum' is not supported." 4344 "Either run in single core or change event_norm to 'average'.") 4345 4346 # Create the parallelization folder 4347 parallelization_dir = pjoin(self.me_dir,'Events',self.run_name,'PY8_parallelization') 4348 if os.path.isdir(parallelization_dir): 4349 shutil.rmtree(parallelization_dir) 4350 os.mkdir(parallelization_dir) 4351 # Copy what should be the now standalone executable for PY8 4352 shutil.copy(pythia_main,parallelization_dir) 4353 # Add a safe card in parallelization 4354 ParallelPY8Card = copy.copy(PY8_Card) 4355 # Normalize the name of the HEPMCouput and lhe input 4356 if HepMC_event_output: 4357 ParallelPY8Card['HEPMCoutput:file']='events.hepmc' 4358 else: 4359 ParallelPY8Card['HEPMCoutput:file']='/dev/null' 4360 4361 ParallelPY8Card.subruns[0].systemSet('Beams:LHEF','events.lhe.gz') 4362 ParallelPY8Card.write(pjoin(parallelization_dir,'PY8Card.dat'), 4363 pjoin(self.me_dir,'Cards','pythia8_card_default.dat'), 4364 direct_pythia_input=True) 4365 # Write the wrapper 4366 wrapper_path = pjoin(parallelization_dir,'run_PY8.sh') 4367 wrapper = open(wrapper_path,'w') 4368 if self.options['cluster_temp_path'] is None: 4369 exe_cmd = \ 4370 """#!%s 4371 ./%s PY8Card.dat >& PY8_log.txt 4372 """ 4373 else: 4374 exe_cmd = \ 4375 """#!%s 4376 ln -s ./events_$1.lhe.gz ./events.lhe.gz 4377 ./%s PY8Card_$1.dat >& PY8_log.txt 4378 mkdir split_$1 4379 if [ -f ./events.hepmc ]; 4380 then 4381 mv ./events.hepmc ./split_$1/ 4382 fi 4383 if [ -f ./pts.dat ]; 4384 then 4385 mv ./pts.dat ./split_$1/ 4386 fi 4387 if [ -f ./djrs.dat ]; 4388 then 4389 mv ./djrs.dat ./split_$1/ 4390 fi 4391 if [ -f ./PY8_log.txt ]; 4392 then 4393 mv ./PY8_log.txt ./split_$1/ 4394 fi 4395 tar -czf split_$1.tar.gz split_$1 4396 """ 4397 exe_cmd = exe_cmd%(shell_exe,os.path.basename(pythia_main)) 4398 wrapper.write(exe_cmd) 4399 wrapper.close() 4400 # Set it as executable 4401 st = os.stat(wrapper_path) 4402 os.chmod(wrapper_path, st.st_mode | stat.S_IEXEC) 4403 4404 # Split the .lhe event file, create event partition 4405 partition=[n_available_events//n_cores]*n_cores 4406 for i in range(n_available_events%n_cores): 4407 partition[i] += 1 4408 4409 # Splitting according to the total number of events requested by the user 4410 # Will be used to determine the number of events to indicate in the PY8 split cards. 4411 partition_for_PY8=[n_events//n_cores]*n_cores 4412 for i in range(n_events%n_cores): 4413 partition_for_PY8[i] += 1 4414 4415 logger.info('Splitting .lhe event file for PY8 parallelization...') 4416 n_splits = lhe_file.split(partition=partition, cwd=parallelization_dir, zip=True) 4417 4418 if n_splits!=len(partition): 4419 raise MadGraph5Error('Error during lhe file splitting. Expected %d files but obtained %d.' 4420 %(len(partition),n_splits)) 4421 # Distribute the split events 4422 split_files = [] 4423 split_dirs = [] 4424 for split_id in range(n_splits): 4425 split_files.append('events_%s.lhe.gz'%split_id) 4426 split_dirs.append(pjoin(parallelization_dir,'split_%d'%split_id)) 4427 # Add the necessary run content 4428 shutil.move(pjoin(parallelization_dir,lhe_file.name+'_%d.lhe.gz'%split_id), 4429 pjoin(parallelization_dir,split_files[-1])) 4430 4431 logger.info('Submitting Pythia8 jobs...') 4432 for i, split_file in enumerate(split_files): 4433 # We must write a PY8Card tailored for each split so as to correct the normalization 4434 # HEPMCoutput:scaling of each weight since the lhe showered will not longer contain the 4435 # same original number of events 4436 split_PY8_Card = banner_mod.PY8Card(pjoin(parallelization_dir,'PY8Card.dat')) 4437 # Make sure to sure the number of split_events determined during the splitting. 4438 split_PY8_Card.systemSet('Main:numberOfEvents',partition_for_PY8[i]) 4439 split_PY8_Card.systemSet('HEPMCoutput:scaling',split_PY8_Card['HEPMCoutput:scaling']* 4440 (float(partition_for_PY8[i])/float(n_events))) 4441 # Add_missing set to False so as to be sure not to add any additional parameter w.r.t 4442 # the ones in the original PY8 param_card copied. 4443 split_PY8_Card.write(pjoin(parallelization_dir,'PY8Card_%d.dat'%i), 4444 pjoin(parallelization_dir,'PY8Card.dat'), add_missing=False) 4445 in_files = [pjoin(parallelization_dir,os.path.basename(pythia_main)), 4446 pjoin(parallelization_dir,'PY8Card_%d.dat'%i), 4447 pjoin(parallelization_dir,split_file)] 4448 if self.options['cluster_temp_path'] is None: 4449 out_files = [] 4450 os.mkdir(pjoin(parallelization_dir,'split_%d'%i)) 4451 selected_cwd = pjoin(parallelization_dir,'split_%d'%i) 4452 for in_file in in_files+[pjoin(parallelization_dir,'run_PY8.sh')]: 4453 # Make sure to rename the split_file link from events_<x>.lhe.gz to events.lhe.gz 4454 # and similarly for PY8Card 4455 if os.path.basename(in_file)==split_file: 4456 ln(in_file,selected_cwd,name='events.lhe.gz') 4457 elif os.path.basename(in_file).startswith('PY8Card'): 4458 ln(in_file,selected_cwd,name='PY8Card.dat') 4459 else: 4460 ln(in_file,selected_cwd) 4461 in_files = [] 4462 else: 4463 out_files = ['split_%d.tar.gz'%i] 4464 selected_cwd = parallelization_dir 4465 self.cluster.submit2(wrapper_path, 4466 argument=[str(i)], cwd=selected_cwd, 4467 input_files=in_files, 4468 output_files=out_files, 4469 required_output=out_files) 4470 4471 def wait_monitoring(Idle, Running, Done): 4472 if Idle+Running+Done == 0: 4473 return 4474 logger.info('Pythia8 shower jobs: %d Idle, %d Running, %d Done [%s]'\ 4475 %(Idle, Running, Done, misc.format_time(time.time() - startPY8timer)))
4476 self.cluster.wait(parallelization_dir,wait_monitoring) 4477 4478 logger.info('Merging results from the split PY8 runs...') 4479 if self.options['cluster_temp_path']: 4480 # Decompressing the output 4481 for i, split_file in enumerate(split_files): 4482 misc.call(['tar','-xzf','split_%d.tar.gz'%i],cwd=parallelization_dir) 4483 os.remove(pjoin(parallelization_dir,'split_%d.tar.gz'%i)) 4484 4485 # Now merge logs 4486 pythia_log_file = open(pythia_log,'w') 4487 n_added = 0 4488 for split_dir in split_dirs: 4489 log_file = pjoin(split_dir,'PY8_log.txt') 4490 pythia_log_file.write('='*35+'\n') 4491 pythia_log_file.write(' -> Pythia8 log file for run %d <-'%i+'\n') 4492 pythia_log_file.write('='*35+'\n') 4493 pythia_log_file.write(open(log_file,'r').read()+'\n') 4494 if run_type in merged_run_types: 4495 sigma_m, Nacc, Ntry = self.parse_PY8_log_file(log_file) 4496 if any(elem is None for elem in [sigma_m, Nacc, Ntry]): 4497 continue 4498 n_added += 1 4499 if PY8_extracted_information['sigma_m'] is None: 4500 PY8_extracted_information['sigma_m'] = sigma_m 4501 else: 4502 PY8_extracted_information['sigma_m'] += sigma_m 4503 if PY8_extracted_information['Nacc'] is None: 4504 PY8_extracted_information['Nacc'] = Nacc 4505 else: 4506 PY8_extracted_information['Nacc'] += Nacc 4507 if PY8_extracted_information['Ntry'] is None: 4508 PY8_extracted_information['Ntry'] = Ntry 4509 else: 4510 PY8_extracted_information['Ntry'] += Ntry 4511 4512 # Normalize the values added 4513 if n_added>0: 4514 PY8_extracted_information['sigma_m'] /= float(n_added) 4515 pythia_log_file.close() 4516 4517 # djr plots 4518 djr_HwU = None 4519 n_added = 0 4520 for split_dir in split_dirs: 4521 djr_file = pjoin(split_dir,'djrs.dat') 4522 if not os.path.isfile(djr_file): 4523 continue 4524 xsecs = self.extract_cross_sections_from_DJR(djr_file) 4525 if len(xsecs)>0: 4526 n_added += 1 4527 if len(PY8_extracted_information['cross_sections'])==0: 4528 PY8_extracted_information['cross_sections'] = xsecs 4529 # Square the error term 4530 for key in PY8_extracted_information['cross_sections']: 4531 PY8_extracted_information['cross_sections'][key][1] = \ 4532 PY8_extracted_information['cross_sections'][key][1]**2 4533 else: 4534 for key, value in xsecs.items(): 4535 PY8_extracted_information['cross_sections'][key][0] += value[0] 4536 # Add error in quadrature 4537 PY8_extracted_information['cross_sections'][key][1] += value[1]**2 4538 new_djr_HwU = histograms.HwUList(djr_file,run_id=0) 4539 if djr_HwU is None: 4540 djr_HwU = new_djr_HwU 4541 else: 4542 for i, hist in enumerate(djr_HwU): 4543 djr_HwU[i] = hist + new_djr_HwU[i] 4544 4545 4546 if not djr_HwU is None: 4547 djr_HwU.output(pjoin(self.me_dir,'Events',self.run_name,'djrs'),format='HwU') 4548 shutil.move(pjoin(self.me_dir,'Events',self.run_name,'djrs.HwU'), 4549 pjoin(self.me_dir,'Events',self.run_name,'%s_djrs.dat'%tag)) 4550 4551 if n_added>0: 4552 for key in PY8_extracted_information['cross_sections']: 4553 # The cross-sections in the DJR are normalized for the original number of events, so we should not 4554 # divide by n_added anymore for the cross-section value 4555 # PY8_extracted_information['cross_sections'][key][0] /= float(n_added) 4556 PY8_extracted_information['cross_sections'][key][1] = \ 4557 math.sqrt(PY8_extracted_information['cross_sections'][key][1]) / float(n_added) 4558 4559 # pts plots 4560 pts_HwU = None 4561 for split_dir in split_dirs: 4562 pts_file = pjoin(split_dir,'pts.dat') 4563 if not os.path.isfile(pts_file): 4564 continue 4565 new_pts_HwU = histograms.HwUList(pts_file,run_id=0) 4566 if pts_HwU is None: 4567 pts_HwU = new_pts_HwU 4568 else: 4569 for i, hist in enumerate(pts_HwU): 4570 pts_HwU[i] = hist + new_pts_HwU[i] 4571 if not pts_HwU is None: 4572 pts_HwU.output(pjoin(self.me_dir,'Events',self.run_name,'pts'),format='HwU') 4573 shutil.move(pjoin(self.me_dir,'Events',self.run_name,'pts.HwU'), 4574 pjoin(self.me_dir,'Events',self.run_name,'%s_pts.dat'%tag)) 4575 4576 # HepMC events now. 4577 all_hepmc_files = [] 4578 for split_dir in split_dirs: 4579 hepmc_file = pjoin(split_dir,'events.hepmc') 4580 if not os.path.isfile(hepmc_file): 4581 continue 4582 all_hepmc_files.append(hepmc_file) 4583 4584 if len(all_hepmc_files)>0: 4585 hepmc_output = pjoin(self.me_dir,'Events',self.run_name,HepMC_event_output) 4586 with misc.TMP_directory() as tmp_dir: 4587 # Use system calls to quickly put these together 4588 header = open(pjoin(tmp_dir,'header.hepmc'),'w') 4589 n_head = 0 4590 for line in open(all_hepmc_files[0],'r'): 4591 if not line.startswith('E'): 4592 n_head += 1 4593 header.write(line) 4594 else: 4595 break 4596 header.close() 4597 tail = open(pjoin(tmp_dir,'tail.hepmc'),'w') 4598 n_tail = 0 4599 for line in misc.BackRead(all_hepmc_files[-1]): 4600 if line.startswith('HepMC::'): 4601 n_tail += 1 4602 tail.write(line) 4603 else: 4604 break 4605 tail.close() 4606 if n_tail>1: 4607 raise MadGraph5Error,'HEPMC files should only have one trailing command.' 4608 ###################################################################### 4609 # This is the most efficient way of putting together HEPMC's, *BUT* # 4610 # WARNING: NEED TO RENDER THE CODE BELOW SAFE TOWARDS INJECTION # 4611 ###################################################################### 4612 for hepmc_file in all_hepmc_files: 4613 # Remove in an efficient way the starting and trailing HEPMC tags 4614 if sys.platform == 'darwin': 4615 # sed on MAC has slightly different synthax than on 4616 os.system(' '.join(['sed','-i',"''","'%s;$d'"% 4617 (';'.join('%id'%(i+1) for i in range(n_head))),hepmc_file])) 4618 else: 4619 # other UNIX systems 4620 os.system(' '.join(['sed','-i']+["-e '%id'"%(i+1) for i in range(n_head)]+ 4621 ["-e '$d'",hepmc_file])) 4622 4623 os.system(' '.join(['cat',pjoin(tmp_dir,'header.hepmc')]+all_hepmc_files+ 4624 [pjoin(tmp_dir,'tail.hepmc'),'>',hepmc_output])) 4625 4626 # We are done with the parallelization directory. Clean it. 4627 if os.path.isdir(parallelization_dir): 4628 shutil.rmtree(parallelization_dir) 4629 4630 # Properly rename the djr and pts output if present. 4631 djr_output = pjoin(self.me_dir,'Events', self.run_name, 'djrs.dat') 4632 if os.path.isfile(djr_output): 4633 shutil.move(djr_output, pjoin(self.me_dir,'Events', 4634 self.run_name, '%s_djrs.dat' % tag)) 4635 pt_output = pjoin(self.me_dir,'Events', self.run_name, 'pts.dat') 4636 if os.path.isfile(pt_output): 4637 shutil.move(pt_output, pjoin(self.me_dir,'Events', 4638 self.run_name, '%s_pts.dat' % tag)) 4639 4640 if not os.path.isfile(pythia_log) or \ 4641 'Inclusive cross section:' not in '\n'.join(open(pythia_log,'r').readlines()[-20:]): 4642 logger.warning('Fail to produce a pythia8 output. More info in \n %s'%pythia_log) 4643 return 4644 4645 # Plot for Pythia8 4646 successful = self.create_plot('Pythia8') 4647 if not successful: 4648 logger.warning('Failed to produce Pythia8 merging plots.') 4649 4650 self.to_store.append('pythia8') 4651 4652 # Study matched cross-sections 4653 if run_type in merged_run_types: 4654 # From the log file 4655 if all(PY8_extracted_information[_] is None for _ in ['sigma_m','Nacc','Ntry']): 4656 # When parallelization is enable we shouldn't have cannot look in the log in this way 4657 if self.options['run_mode']==0 or (self.options['run_mode']==2 and self.options['nb_core']==1): 4658 PY8_extracted_information['sigma_m'],PY8_extracted_information['Nacc'],\ 4659 PY8_extracted_information['Ntry'] = self.parse_PY8_log_file( 4660 pjoin(self.me_dir,'Events', self.run_name,'%s_pythia8.log' % tag)) 4661 else: 4662 logger.warning('Pythia8 cross-section could not be retreived.\n'+ 4663 'Try turning parallelization off by setting the option nb_core to 1. YYYYY') 4664 4665 if not any(PY8_extracted_information[_] is None for _ in ['sigma_m','Nacc','Ntry']): 4666 self.results.add_detail('cross_pythia', PY8_extracted_information['sigma_m']) 4667 self.results.add_detail('nb_event_pythia', PY8_extracted_information['Nacc']) 4668 # Shorthands 4669 Nacc = PY8_extracted_information['Nacc'] 4670 Ntry = PY8_extracted_information['Ntry'] 4671 sigma_m = PY8_extracted_information['sigma_m'] 4672 # Compute pythia error 4673 error = self.results[self.run_name].return_tag(self.run_tag)['error'] 4674 try: 4675 error_m = math.sqrt((error * Nacc/Ntry)**2 + sigma_m**2 *(1-Nacc/Ntry)/Nacc) 4676 except ZeroDivisionError: 4677 # Cannot compute error 4678 error_m = -1.0 4679 # works both for fixed number of generated events and fixed accepted events 4680 self.results.add_detail('error_pythia', error_m) 4681 4682 if self.run_card['use_syst']: 4683 self.results.add_detail('cross_pythia', -1) 4684 self.results.add_detail('error_pythia', 0) 4685 4686 # From the djr file generated 4687 djr_output = pjoin(self.me_dir,'Events',self.run_name,'%s_djrs.dat'%tag) 4688 if os.path.isfile(djr_output) and len(PY8_extracted_information['cross_sections'])==0: 4689 # When parallelization is enable we shouldn't have cannot look in the log in this way 4690 if self.options['run_mode']==0 or (self.options['run_mode']==2 and self.options['nb_core']==1): 4691 PY8_extracted_information['cross_sections'] = self.extract_cross_sections_from_DJR(djr_output) 4692 else: 4693 logger.warning('Pythia8 merged cross-sections could not be retreived.\n'+ 4694 'Try turning parallelization off by setting the option nb_core to 1.XXXXX') 4695 PY8_extracted_information['cross_sections'] = {} 4696 4697 cross_sections = PY8_extracted_information['cross_sections'] 4698 if cross_sections: 4699 # Filter the cross_sections specified an keep only the ones 4700 # with central parameters and a different merging scale 4701 a_float_re = '[\+|-]?\d+(\.\d*)?([EeDd][\+|-]?\d+)?' 4702 central_merging_re = re.compile( 4703 '^\s*Weight_MERGING\s*=\s*(?P<merging>%s)\s*$'%a_float_re, 4704 re.IGNORECASE) 4705 cross_sections = dict( 4706 (float(central_merging_re.match(xsec).group('merging')),value) 4707 for xsec, value in cross_sections.items() if not 4708 central_merging_re.match(xsec) is None) 4709 central_scale = PY8_Card['JetMatching:qCut'] if \ 4710 int(self.run_card['ickkw'])==1 else PY8_Card['Merging:TMS'] 4711 if central_scale in cross_sections: 4712 self.results.add_detail('cross_pythia8', cross_sections[central_scale][0]) 4713 self.results.add_detail('error_pythia8', cross_sections[central_scale][1]) 4714 4715 #logger.info('Pythia8 merged cross-sections are:') 4716 #for scale in sorted(cross_sections.keys()): 4717 # logger.info(' > Merging scale = %-6.4g : %-11.5g +/- %-7.2g [pb]'%\ 4718 # (scale,cross_sections[scale][0],cross_sections[scale][1])) 4719 4720 xsecs_file = open(pjoin(self.me_dir,'Events',self.run_name, 4721 '%s_merged_xsecs.txt'%tag),'w') 4722 if cross_sections: 4723 xsecs_file.write('%-20s%-20s%-20s\n'%('Merging scale', 4724 'Cross-section [pb]','MC uncertainty [pb]')) 4725 for scale in sorted(cross_sections.keys()): 4726 xsecs_file.write('%-20.4g%-20.6e%-20.2e\n'% 4727 (scale,cross_sections[scale][0],cross_sections[scale][1])) 4728 else: 4729 xsecs_file.write('Cross-sections could not be read from the'+\ 4730 "XML node 'xsection' of the .dat file produced by Pythia8.") 4731 xsecs_file.close() 4732 4733 #Update the banner 4734 # We add directly the pythia command card because it has the full 4735 # information 4736 self.banner.add(pythia_cmd_card) 4737 4738 if int(self.run_card['ickkw']): 4739 # Add the matched cross-section 4740 if 'MGGenerationInfo' in self.banner: 4741 self.banner['MGGenerationInfo'] += '# Matched Integrated weight (pb) : %s\n' % self.results.current['cross_pythia'] 4742 else: 4743 self.banner['MGGenerationInfo'] = '# Matched Integrated weight (pb) : %s\n' % self.results.current['cross_pythia'] 4744 banner_path = pjoin(self.me_dir, 'Events', self.run_name, '%s_%s_banner.txt' % (self.run_name, tag)) 4745 self.banner.write(banner_path) 4746 4747 self.update_status('Pythia8 shower finished after %s.'%misc.format_time(time.time() - startPY8timer), level='pythia8') 4748 if self.options['delphes_path']: 4749 self.exec_cmd('delphes --no_default', postcmd=False, printcmd=False) 4750 self.print_results_in_shell(self.results.current) 4751
4752 - def parse_PY8_log_file(self, log_file_path):
4753 """ Parse a log file to extract number of event and cross-section. """ 4754 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\-\+]+)") 4755 pythia_xsec_re = re.compile("Inclusive cross section\s*:\s*(?P<xsec>[\d\.e\-\+]+)\s*(?P<xsec_error>[\d\.e\-\+]+)") 4756 sigma_m, Nacc, Ntry = None, None, None 4757 for line in misc.BackRead(log_file_path): 4758 info = pythiare.search(line) 4759 if not info: 4760 # Also try to obtain the cross-section and error from the final xsec line of pythia8 log 4761 # which is more reliable, in general for example when there is merging and the last event 4762 # is skipped. 4763 final_PY8_xsec = pythia_xsec_re.search(line) 4764 if not final_PY8_xsec: 4765 continue 4766 else: 4767 sigma_m = float(final_PY8_xsec.group('xsec')) *1e9 4768 continue 4769 else: 4770 try: 4771 # Pythia cross section in mb, we want pb 4772 if sigma_m is None: 4773 sigma_m = float(info.group('xsec')) *1e9 4774 if Nacc is None: 4775 Nacc = int(info.group('generated')) 4776 if Ntry is None: 4777 Ntry = int(info.group('tried')) 4778 if Nacc==0: 4779 raise self.InvalidCmd, 'Pythia8 shower failed since it'+\ 4780 ' did not accept any event from the MG5aMC event file.' 4781 return sigma_m, Nacc, Ntry 4782 except ValueError: 4783 return None,None,None 4784 4785 raise self.InvalidCmd, "Could not find cross-section and event number information "+\ 4786 "in Pythia8 log\n '%s'."%log_file_path
4787
4788 - def extract_cross_sections_from_DJR(self,djr_output):
4789 """Extract cross-sections from a djr XML output.""" 4790 import xml.dom.minidom as minidom 4791 run_nodes = minidom.parse(djr_output).getElementsByTagName("run") 4792 all_nodes = dict((int(node.getAttribute('id')),node) for 4793 node in run_nodes) 4794 try: 4795 selected_run_node = all_nodes[0] 4796 except: 4797 return {} 4798 xsections = selected_run_node.getElementsByTagName("xsection") 4799 # In the DJR, the conversion to pb is already performed 4800 return dict((xsec.getAttribute('name'), 4801 [float(xsec.childNodes[0].data.split()[0]), 4802 float(xsec.childNodes[0].data.split()[1])]) 4803 for xsec in xsections)
4804
4805 - def do_pythia(self, line):
4806 """launch pythia""" 4807 4808 4809 # Check argument's validity 4810 args = self.split_arg(line) 4811 if '--no_default' in args: 4812 if not os.path.exists(pjoin(self.me_dir, 'Cards', 'pythia_card.dat')): 4813 return 4814 no_default = True 4815 args.remove('--no_default') 4816 else: 4817 no_default = False 4818 4819 if not self.run_name: 4820 self.check_pythia(args) 4821 self.configure_directory(html_opening =False) 4822 else: 4823 # initialize / remove lhapdf mode 4824 self.configure_directory(html_opening =False) 4825 self.check_pythia(args) 4826 4827 if self.run_card['event_norm'] != 'sum': 4828 logger.error('pythia-pgs require event_norm to be on sum. Do not run pythia6') 4829 return 4830 4831 # the args are modify and the last arg is always the mode 4832 if not no_default: 4833 self.ask_pythia_run_configuration(args[-1]) 4834 if self.options['automatic_html_opening']: 4835 misc.open_file(os.path.join(self.me_dir, 'crossx.html')) 4836 self.options['automatic_html_opening'] = False 4837 4838 # Update the banner with the pythia card 4839 if not self.banner or len(self.banner) <=1: 4840 self.banner = banner_mod.recover_banner(self.results, 'pythia') 4841 4842 pythia_src = pjoin(self.options['pythia-pgs_path'],'src') 4843 4844 self.results.add_detail('run_mode', 'madevent') 4845 4846 self.update_status('Running Pythia', 'pythia') 4847 try: 4848 os.remove(pjoin(self.me_dir,'Events','pythia.done')) 4849 except Exception: 4850 pass 4851 4852 ## LAUNCHING PYTHIA 4853 # check that LHAPATH is define. 4854 if not re.search(r'^\s*LHAPATH=%s/PDFsets' % pythia_src, 4855 open(pjoin(self.me_dir,'Cards','pythia_card.dat')).read(), 4856 re.M): 4857 f = open(pjoin(self.me_dir,'Cards','pythia_card.dat'),'a') 4858 f.write('\n LHAPATH=%s/PDFsets' % pythia_src) 4859 f.close() 4860 tag = self.run_tag 4861 pythia_log = pjoin(self.me_dir, 'Events', self.run_name , '%s_pythia.log' % tag) 4862 #self.cluster.launch_and_wait('../bin/internal/run_pythia', 4863 # argument= [pythia_src], stdout= pythia_log, 4864 # stderr=subprocess.STDOUT, 4865 # cwd=pjoin(self.me_dir,'Events')) 4866 output_files = ['pythia_events.hep'] 4867 if self.run_card['use_syst']: 4868 output_files.append('syst.dat') 4869 if self.run_card['ickkw'] == 1: 4870 output_files += ['beforeveto.tree', 'xsecs.tree', 'events.tree'] 4871 4872 os.environ['PDG_MASS_TBL'] = pjoin(pythia_src,'mass_width_2004.mc') 4873 self.cluster.launch_and_wait(pjoin(pythia_src, 'pythia'), 4874 input_files=[pjoin(self.me_dir, "Events", "unweighted_events.lhe"), 4875 pjoin(self.me_dir,'Cards','pythia_card.dat'), 4876 pjoin(pythia_src,'mass_width_2004.mc')], 4877 output_files=output_files, 4878 stdout= pythia_log, 4879 stderr=subprocess.STDOUT, 4880 cwd=pjoin(self.me_dir,'Events')) 4881 4882 4883 os.remove(pjoin(self.me_dir, "Events", "unweighted_events.lhe")) 4884 4885 if not os.path.exists(pjoin(self.me_dir,'Events','pythia_events.hep')): 4886 logger.warning('Fail to produce pythia output. More info in \n %s' % pythia_log) 4887 return 4888 4889 self.to_store.append('pythia') 4890 4891 # Find the matched cross-section 4892 if int(self.run_card['ickkw']): 4893 # read the line from the bottom of the file 4894 pythia_log = misc.BackRead(pjoin(self.me_dir,'Events', self.run_name, 4895 '%s_pythia.log' % tag)) 4896 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") 4897 for line in pythia_log: 4898 info = pythiare.search(line) 4899 if not info: 4900 continue 4901 try: 4902 # Pythia cross section in mb, we want pb 4903 sigma_m = float(info.group('xsec').replace('D','E')) *1e9 4904 Nacc = int(info.group('generated')) 4905 Ntry = int(info.group('tried')) 4906 except ValueError: 4907 # xsec is not float - this should not happen 4908 self.results.add_detail('cross_pythia', 0) 4909 self.results.add_detail('nb_event_pythia', 0) 4910 self.results.add_detail('error_pythia', 0) 4911 else: 4912 self.results.add_detail('cross_pythia', sigma_m) 4913 self.results.add_detail('nb_event_pythia', Nacc) 4914 #compute pythia error 4915 error = self.results[self.run_name].return_tag(self.run_tag)['error'] 4916 if Nacc: 4917 error_m = math.sqrt((error * Nacc/Ntry)**2 + sigma_m**2 *(1-Nacc/Ntry)/Nacc) 4918 else: 4919 error_m = 10000 * sigma_m 4920 # works both for fixed number of generated events and fixed accepted events 4921 self.results.add_detail('error_pythia', error_m) 4922 break 4923 4924 pythia_log.close() 4925 4926 pydir = pjoin(self.options['pythia-pgs_path'], 'src') 4927 eradir = self.options['exrootanalysis_path'] 4928 madir = self.options['madanalysis_path'] 4929 td = self.options['td_path'] 4930 4931 #Update the banner 4932 self.banner.add(pjoin(self.me_dir, 'Cards','pythia_card.dat')) 4933 if int(self.run_card['ickkw']): 4934 # Add the matched cross-section 4935 if 'MGGenerationInfo' in self.banner: 4936 self.banner['MGGenerationInfo'] += '# Matched Integrated weight (pb) : %s\n' % self.results.current['cross_pythia'] 4937 else: 4938 self.banner['MGGenerationInfo'] = '# Matched Integrated weight (pb) : %s\n' % self.results.current['cross_pythia'] 4939 banner_path = pjoin(self.me_dir, 'Events', self.run_name, '%s_%s_banner.txt' % (self.run_name, tag)) 4940 self.banner.write(banner_path) 4941 4942 # Creating LHE file 4943 self.run_hep2lhe(banner_path) 4944 4945 if int(self.run_card['ickkw']): 4946 misc.gzip(pjoin(self.me_dir,'Events','beforeveto.tree'), 4947 stdout=pjoin(self.me_dir,'Events',self.run_name, tag+'_pythia_beforeveto.tree.gz')) 4948 4949 4950 if self.run_card['use_syst'] in self.true: 4951 # Calculate syscalc info based on syst.dat 4952 try: 4953 self.run_syscalc('Pythia') 4954 except SysCalcError, error: 4955 logger.error(str(error)) 4956 else: 4957 if os.path.exists(pjoin(self.me_dir,'Events', 'syst.dat')): 4958 # Store syst.dat 4959 misc.gzip(pjoin(self.me_dir,'Events', 'syst.dat'), 4960 stdout=pjoin(self.me_dir,'Events',self.run_name, tag + '_pythia_syst.dat.gz')) 4961 4962 # Store syscalc.dat 4963 if os.path.exists(pjoin(self.me_dir, 'Events', 'syscalc.dat')): 4964 filename = pjoin(self.me_dir, 'Events' ,self.run_name, 4965 '%s_syscalc.dat' % self.run_tag) 4966 misc.gzip(pjoin(self.me_dir, 'Events','syscalc.dat'), 4967 stdout = "%s.gz" % filename) 4968 4969 # Plot for pythia 4970 self.create_plot('Pythia') 4971 4972 if os.path.exists(pjoin(self.me_dir,'Events','pythia_events.lhe')): 4973 misc.gzip(pjoin(self.me_dir,'Events','pythia_events.lhe'), 4974 stdout=pjoin(self.me_dir,'Events', self.run_name,'%s_pythia_events.lhe.gz' % tag)) 4975 4976 self.update_status('finish', level='pythia', makehtml=False) 4977 self.exec_cmd('pgs --no_default', postcmd=False, printcmd=False) 4978 if self.options['delphes_path']: 4979 self.exec_cmd('delphes --no_default', postcmd=False, printcmd=False) 4980 self.print_results_in_shell(self.results.current)
4981 4982 4983 ################################################################################
4984 - def do_remove(self, line):
4985 """Remove one/all run or only part of it""" 4986 4987 args = self.split_arg(line) 4988 run, tag, mode = self.check_remove(args) 4989 if 'banner' in mode: 4990 mode.append('all') 4991 4992 4993 if run == 'all': 4994 # Check first if they are not a run with a name run. 4995 if os.path.exists(pjoin(self.me_dir, 'Events', 'all')): 4996 logger.warning('A run with name all exists. So we will not supress all processes.') 4997 else: 4998 for match in misc.glob(pjoin('*','*_banner.txt'), pjoin(self.me_dir, 'Events')): 4999 run = match.rsplit(os.path.sep,2)[1] 5000 if self.force: 5001 args.append('-f') 5002 try: 5003 self.exec_cmd('remove %s %s' % (run, ' '.join(args[1:]) ) ) 5004 except self.InvalidCmd, error: 5005 logger.info(error) 5006 pass # run already clear 5007 return 5008 5009 # Check that run exists 5010 if not os.path.exists(pjoin(self.me_dir, 'Events', run)): 5011 raise self.InvalidCmd('No run \'%s\' detected' % run) 5012 5013 try: 5014 self.resuls.def_current(run) 5015 self.update_status(' Cleaning %s' % run, level=None) 5016 except Exception: 5017 misc.sprint('fail to update results or html status') 5018 pass # Just ensure that html never makes crash this function 5019 5020 5021 # Found the file to delete 5022 5023 to_delete = misc.glob('*', pjoin(self.me_dir, 'Events', run)) 5024 to_delete += misc.glob('*', pjoin(self.me_dir, 'HTML', run)) 5025 # forbid the banner to be removed 5026 to_delete = [os.path.basename(f) for f in to_delete if 'banner' not in f] 5027 if tag: 5028 to_delete = [f for f in to_delete if tag in f] 5029 if 'parton' in mode or 'all' in mode: 5030 try: 5031 if self.results[run][0]['tag'] != tag: 5032 raise Exception, 'dummy' 5033 except Exception: 5034 pass 5035 else: 5036 nb_rm = len(to_delete) 5037 if os.path.exists(pjoin(self.me_dir, 'Events', run, 'events.lhe.gz')): 5038 to_delete.append('events.lhe.gz') 5039 if os.path.exists(pjoin(self.me_dir, 'Events', run, 'unweighted_events.lhe.gz')): 5040 to_delete.append('unweighted_events.lhe.gz') 5041 if os.path.exists(pjoin(self.me_dir, 'HTML', run,'plots_parton.html')): 5042 to_delete.append(pjoin(self.me_dir, 'HTML', run,'plots_parton.html')) 5043 if nb_rm != len(to_delete): 5044 logger.warning('Be carefull that partonic information are on the point to be removed.') 5045 if 'all' in mode: 5046 pass # delete everything 5047 else: 5048 if 'pythia' not in mode: 5049 to_delete = [f for f in to_delete if 'pythia' not in f] 5050 if 'pgs' not in mode: 5051 to_delete = [f for f in to_delete if 'pgs' not in f] 5052 if 'delphes' not in mode: 5053 to_delete = [f for f in to_delete if 'delphes' not in f] 5054 if 'parton' not in mode: 5055 to_delete = [f for f in to_delete if 'delphes' in f 5056 or 'pgs' in f 5057 or 'pythia' in f] 5058 if not self.force and len(to_delete): 5059 question = 'Do you want to delete the following files?\n %s' % \ 5060 '\n '.join(to_delete) 5061 ans = self.ask(question, 'y', choices=['y','n']) 5062 else: 5063 ans = 'y' 5064 5065 if ans == 'y': 5066 for file2rm in to_delete: 5067 if os.path.exists(pjoin(self.me_dir, 'Events', run, file2rm)): 5068 try: 5069 os.remove(pjoin(self.me_dir, 'Events', run, file2rm)) 5070 except Exception: 5071 shutil.rmtree(pjoin(self.me_dir, 'Events', run, file2rm)) 5072 else: 5073 try: 5074 os.remove(pjoin(self.me_dir, 'HTML', run, file2rm)) 5075 except Exception: 5076 shutil.rmtree(pjoin(self.me_dir, 'HTML', run, file2rm)) 5077 5078 5079 5080 # Remove file in SubProcess directory 5081 if 'all' in mode or 'channel' in mode: 5082 try: 5083 if tag and self.results[run][0]['tag'] != tag: 5084 raise Exception, 'dummy' 5085 except Exception: 5086 pass 5087 else: 5088 to_delete = misc.glob('%s*' % run, pjoin(self.me_dir, 'SubProcesses')) 5089 to_delete += misc.glob(pjoin('*','%s*' % run), pjoin(self.me_dir, 'SubProcesses')) 5090 to_delete += misc.glob(pjoin('*','*','%s*' % run), pjoin(self.me_dir, 'SubProcesses')) 5091 5092 if self.force or len(to_delete) == 0: 5093 ans = 'y' 5094 else: 5095 question = 'Do you want to delete the following files?\n %s' % \ 5096 '\n '.join(to_delete) 5097 ans = self.ask(question, 'y', choices=['y','n']) 5098 5099 if ans == 'y': 5100 for file2rm in to_delete: 5101 os.remove(file2rm) 5102 5103 if 'banner' in mode: 5104 to_delete = misc.glob('*', pjoin(self.me_dir, 'Events', run)) 5105 if tag: 5106 # remove banner 5107 try: 5108 os.remove(pjoin(self.me_dir, 'Events',run,'%s_%s_banner.txt' % (run,tag))) 5109 except Exception: 5110 logger.warning('fail to remove the banner') 5111 # remove the run from the html output 5112 if run in self.results: 5113 self.results.delete_run(run, tag) 5114 return 5115 elif any(['banner' not in os.path.basename(p) for p in to_delete]): 5116 if to_delete: 5117 raise MadGraph5Error, '''Some output still exists for this run. 5118 Please remove those output first. Do for example: 5119 remove %s all banner 5120 ''' % run 5121 else: 5122 shutil.rmtree(pjoin(self.me_dir, 'Events',run)) 5123 if run in self.results: 5124 self.results.delete_run(run) 5125 return 5126 else: 5127 logger.info('''The banner is not removed. In order to remove it run: 5128 remove %s all banner %s''' % (run, tag and '--tag=%s ' % tag or '')) 5129 5130 # update database. 5131 self.results.clean(mode, run, tag) 5132 self.update_status('', level='all')
5133 5134 5135 5136 ############################################################################
5137 - def do_plot(self, line):
5138 """Create the plot for a given run""" 5139 5140 # Since in principle, all plot are already done automaticaly 5141 self.store_result() 5142 args = self.split_arg(line) 5143 # Check argument's validity 5144 self.check_plot(args) 5145 logger.info('plot for run %s' % self.run_name) 5146 if not self.force: 5147 self.ask_edit_cards(['plot_card.dat'], args, plot=True) 5148 5149 if any([arg in ['all','parton'] for arg in args]): 5150 filename = pjoin(self.me_dir, 'Events', self.run_name, 'unweighted_events.lhe') 5151 if os.path.exists(filename+'.gz'): 5152 misc.gunzip('%s.gz' % filename, keep=True) 5153 if os.path.exists(filename): 5154 files.ln(filename, pjoin(self.me_dir, 'Events')) 5155 self.create_plot('parton') 5156 if not os.path.exists(filename+'.gz'): 5157 misc.gzip(pjoin(self.me_dir, 'Events', 'unweighted_events.lhe'), 5158 stdout= "%s.gz" % filename) 5159 else: 5160 try: 5161 os.remove(pjoin(self.me_dir, 'Events', 'unweighted_events.lhe')) 5162 os.remove(filename) 5163 except Exception: 5164 pass 5165 else: 5166 logger.info('No valid files for partonic plot') 5167 5168 if any([arg in ['all','pythia'] for arg in args]): 5169 filename = pjoin(self.me_dir, 'Events' ,self.run_name, 5170 '%s_pythia_events.lhe' % self.run_tag) 5171 if os.path.exists(filename+'.gz'): 5172 misc.gunzip("%s.gz" % filename) 5173 if os.path.exists(filename): 5174 shutil.move(filename, pjoin(self.me_dir, 'Events','pythia_events.lhe')) 5175 self.create_plot('Pythia') 5176 misc.gzip(pjoin(self.me_dir, 'Events','pythia_events.lhe'), 5177 stdout= "%s.gz" % filename) 5178 else: 5179 logger.info('No valid files for pythia plot') 5180 5181 5182 if any([arg in ['all','pgs'] for arg in args]): 5183 filename = pjoin(self.me_dir, 'Events', self.run_name, 5184 '%s_pgs_events.lhco' % self.run_tag) 5185 if os.path.exists(filename+'.gz'): 5186 misc.gunzip("%s.gz" % filename) 5187 if os.path.exists(filename): 5188 self.create_plot('PGS') 5189 misc.gzip(filename) 5190 else: 5191 logger.info('No valid files for pgs plot') 5192 5193 if any([arg in ['all','delphes'] for arg in args]): 5194 filename = pjoin(self.me_dir, 'Events', self.run_name, 5195 '%s_delphes_events.lhco' % self.run_tag) 5196 if os.path.exists(filename+'.gz'): 5197 misc.gunzip("%s.gz" % filename) 5198 if os.path.exists(filename): 5199 self.create_plot('Delphes') 5200 misc.gzip(filename) 5201 else: 5202 logger.info('No valid files for delphes plot')
5203 5204 ############################################################################
5205 - def do_syscalc(self, line):
5206 """Evaluate systematics variation weights for a given run""" 5207 5208 # Since in principle, all systematics run are already done automaticaly 5209 self.store_result() 5210 args = self.split_arg(line) 5211 # Check argument's validity 5212 self.check_syscalc(args) 5213 if self.ninitial == 1: 5214 logger.error('SysCalc can\'t be run for decay processes') 5215 return 5216 5217 logger.info('Calculating systematics for run %s' % self.run_name) 5218 5219 self.ask_edit_cards(['run_card.dat'], args, plot=False) 5220 self.run_card = banner_mod.RunCard(pjoin(self.me_dir, 'Cards', 'run_card.dat')) 5221 if any([arg in ['all','parton'] for arg in args]): 5222 filename = pjoin(self.me_dir, 'Events', self.run_name, 'unweighted_events.lhe') 5223 if os.path.exists(filename+'.gz'): 5224 misc.gunzip("%s.gz" % filename) 5225 if os.path.exists(filename): 5226 shutil.move(filename, pjoin(self.me_dir, 'Events', 'unweighted_events.lhe')) 5227 self.run_syscalc('parton') 5228 misc.gzip(pjoin(self.me_dir, 'Events', 'unweighted_events.lhe'), 5229 stdout="%s.gz" % filename) 5230 else: 5231 logger.info('No valid files for parton level systematics run.') 5232 5233 if any([arg in ['all','pythia'] for arg in args]): 5234 filename = pjoin(self.me_dir, 'Events' ,self.run_name, 5235 '%s_pythia_syst.dat' % self.run_tag) 5236 if os.path.exists(filename+'.gz'): 5237 misc.gunzip("%s.gz" % filename) 5238 if os.path.exists(filename): 5239 shutil.move(filename, pjoin(self.me_dir, 'Events','syst.dat')) 5240 try: 5241 self.run_syscalc('Pythia') 5242 except SysCalcError, error: 5243 logger.warning(str(error)) 5244 return 5245 misc.gzip(pjoin(self.me_dir, 'Events','syst.dat'), "%s.gz" % filename) 5246 filename = pjoin(self.me_dir, 'Events' ,self.run_name, 5247 '%s_syscalc.dat' % self.run_tag) 5248 misc.gzip(pjoin(self.me_dir, 'Events','syscalc.dat'), 5249 stdout=filename) 5250 else: 5251 logger.info('No valid files for pythia level')
5252 5253
5254 - def store_result(self):
5255 """ tar the pythia results. This is done when we are quite sure that 5256 the pythia output will not be use anymore """ 5257 5258 if not self.run_name: 5259 return 5260 5261 5262 5263 if not self.to_store: 5264 return 5265 5266 tag = self.run_card['run_tag'] 5267 self.update_status('storing files of previous run', level=None,\ 5268 error=True) 5269 if 'event' in self.to_store: 5270 if not os.path.exists(pjoin(self.me_dir, 'Events',self.run_name, 'unweighted_events.lhe.gz')) and\ 5271 os.path.exists(pjoin(self.me_dir, 'Events',self.run_name, 'unweighted_events.lhe')): 5272 logger.info("gzipping output file: unweighted_events.lhe") 5273 misc.gzip(pjoin(self.me_dir,'Events',self.run_name,"unweighted_events.lhe")) 5274 if os.path.exists(pjoin(self.me_dir,'Events','reweight.lhe')): 5275 os.remove(pjoin(self.me_dir,'Events', 'reweight.lhe')) 5276 5277 if 'pythia' in self.to_store: 5278 self.update_status('Storing Pythia files of previous run', level='pythia', error=True) 5279 p = pjoin(self.me_dir,'Events') 5280 n = self.run_name 5281 t = tag 5282 self.to_store.remove('pythia') 5283 misc.gzip(pjoin(p,'pythia_events.hep'), 5284 stdout=pjoin(p, str(n),'%s_pythia_events.hep' % t)) 5285 5286 if 'pythia8' in self.to_store: 5287 p = pjoin(self.me_dir,'Events') 5288 n = self.run_name 5289 t = tag 5290 file_path = pjoin(p, n ,'%s_pythia8_events.hepmc'%t) 5291 self.to_store.remove('pythia8') 5292 if os.path.isfile(file_path): 5293 self.update_status('Storing Pythia8 files of previous run', 5294 level='pythia', error=True) 5295 misc.gzip(file_path,stdout=file_path) 5296 5297 self.update_status('Done', level='pythia',makehtml=False,error=True) 5298 self.results.save() 5299 5300 self.to_store = []
5301
5302 - def launch_job(self,exe, cwd=None, stdout=None, argument = [], remaining=0, 5303 run_type='', mode=None, **opt):
5304 """ """ 5305 argument = [str(arg) for arg in argument] 5306 if mode is None: 5307 mode = self.cluster_mode 5308 5309 # ensure that exe is executable 5310 if os.path.exists(exe) and not os.access(exe, os.X_OK): 5311 os.system('chmod +x %s ' % exe) 5312 elif (cwd and os.path.exists(pjoin(cwd, exe))) and not \ 5313 os.access(pjoin(cwd, exe), os.X_OK): 5314 os.system('chmod +x %s ' % pjoin(cwd, exe)) 5315 5316 if mode == 0: 5317 self.update_status((remaining, 1, 5318 self.total_jobs - remaining -1, run_type), level=None, force=False) 5319 start = time.time() 5320 #os.system('cd %s; ./%s' % (cwd,exe)) 5321 status = misc.call([exe] + argument, cwd=cwd, stdout=stdout, **opt) 5322 logger.info('%s run in %f s' % (exe, time.time() -start)) 5323 if status: 5324 raise MadGraph5Error, '%s didn\'t stop properly. Stop all computation' % exe 5325 5326 5327 elif mode in [1,2]: 5328 exename = os.path.basename(exe) 5329 # For condor cluster, create the input/output files 5330 if 'ajob' in exename: 5331 input_files = ['madevent','input_app.txt','symfact.dat','iproc.dat','dname.mg', 5332 pjoin(self.me_dir, 'SubProcesses','randinit')] 5333 if os.path.exists(pjoin(self.me_dir,'SubProcesses', 5334 'MadLoop5_resources.tar.gz')) and cluster.need_transfer(self.options): 5335 input_files.append(pjoin(self.me_dir,'SubProcesses', 'MadLoop5_resources.tar.gz')) 5336 5337 output_files = [] 5338 required_output = [] 5339 5340 5341 #Find the correct PDF input file 5342 input_files.append(self.get_pdf_input_filename()) 5343 5344 #Find the correct ajob 5345 Gre = re.compile("\s*j=(G[\d\.\w]+)") 5346 origre = re.compile("grid_directory=(G[\d\.\w]+)") 5347 try : 5348 fsock = open(exe) 5349 except Exception: 5350 fsock = open(pjoin(cwd,exe)) 5351 text = fsock.read() 5352 output_files = Gre.findall(text) 5353 if not output_files: 5354 Ire = re.compile("for i in ([\d\.\s]*) ; do") 5355 data = Ire.findall(text) 5356 data = ' '.join(data).split() 5357 for nb in data: 5358 output_files.append('G%s' % nb) 5359 required_output.append('G%s/results.dat' % nb) 5360 else: 5361 for G in output_files: 5362 if os.path.isdir(pjoin(cwd,G)): 5363 input_files.append(G) 5364 required_output.append('%s/results.dat' % G) 5365 5366 if origre.search(text): 5367 G_grid = origre.search(text).groups()[0] 5368 input_files.append(pjoin(G_grid, 'ftn26')) 5369 5370 #submitting 5371 self.cluster.submit2(exe, stdout=stdout, cwd=cwd, 5372 input_files=input_files, output_files=output_files, 5373 required_output=required_output) 5374 elif 'survey' in exename: 5375 input_files = ['madevent','input_app.txt','symfact.dat','iproc.dat', 'dname.mg', 5376 pjoin(self.me_dir, 'SubProcesses','randinit')] 5377 if os.path.exists(pjoin(self.me_dir,'SubProcesses', 5378 'MadLoop5_resources.tar.gz')) and cluster.need_transfer(self.options): 5379 input_files.append(pjoin(self.me_dir,'SubProcesses', 5380 'MadLoop5_resources.tar.gz')) 5381 5382 #Find the correct PDF input file 5383 input_files.append(self.get_pdf_input_filename()) 5384 5385 5386 output_files = [] 5387 required_output = [] 5388 5389 #Find the correct ajob 5390 suffix = "_%s" % int(float(argument[0])) 5391 if suffix == '_0': 5392 suffix = '' 5393 output_files = ['G%s%s' % (i, suffix) for i in argument[1:]] 5394 for G in output_files: 5395 required_output.append('%s/results.dat' % G) 5396 5397 # add the grid information if needed 5398 for G in output_files: 5399 if '.' in argument[0]: 5400 offset = int(str(argument[0]).split('.')[1]) 5401 else: 5402 offset = 0 5403 5404 if offset ==0 or offset == int(float(argument[0])): 5405 if os.path.exists(pjoin(cwd, G, 'input_app.txt')): 5406 os.remove(pjoin(cwd, G, 'input_app.txt')) 5407 5408 if os.path.exists(os.path.realpath(pjoin(cwd, G, 'ftn25'))): 5409 if offset == 0 or offset == int(float(argument[0])): 5410 os.remove(pjoin(cwd, G, 'ftn25')) 5411 continue 5412 else: 5413 input_files.append(pjoin(cwd, G, 'ftn25')) 5414 input_files.remove('input_app.txt') 5415 input_files.append(pjoin(cwd, G, 'input_app.txt')) 5416 elif os.path.lexists(pjoin(cwd, G, 'ftn25')): 5417 try: 5418 os.remove(pjoin(cwd,G,'ftn25')) 5419 except: 5420 pass 5421 5422 #submitting 5423 self.cluster.cluster_submit(exe, stdout=stdout, cwd=cwd, argument=argument, 5424 input_files=input_files, output_files=output_files, 5425 required_output=required_output, **opt) 5426 elif "refine_splitted.sh" in exename: 5427 input_files = ['madevent','symfact.dat','iproc.dat', 'dname.mg', 5428 pjoin(self.me_dir, 'SubProcesses','randinit')] 5429 5430 if os.path.exists(pjoin(self.me_dir,'SubProcesses', 5431 'MadLoop5_resources.tar.gz')) and cluster.need_transfer(self.options): 5432 input_files.append(pjoin(self.me_dir,'SubProcesses', 5433 'MadLoop5_resources.tar.gz')) 5434 5435 #Find the correct PDF input file 5436 input_files.append(self.get_pdf_input_filename()) 5437 5438 5439 output_files = [argument[0]] 5440 required_output = [] 5441 for G in output_files: 5442 required_output.append('%s/results.dat' % G) 5443 input_files.append(pjoin(argument[1], "input_app.txt")) 5444 input_files.append(pjoin(argument[1], "ftn26")) 5445 5446 #submitting 5447 self.cluster.cluster_submit(exe, stdout=stdout, cwd=cwd, argument=argument, 5448 input_files=input_files, output_files=output_files, 5449 required_output=required_output, **opt) 5450 5451 5452 5453 else: 5454 self.cluster.submit(exe, argument=argument, stdout=stdout, cwd=cwd, **opt)
5455 5456 5457 ############################################################################
5458 - def find_madevent_mode(self):
5459 """Find if Madevent is in Group mode or not""" 5460 5461 # The strategy is too look in the files Source/run_configs.inc 5462 # if we found: ChanPerJob=3 then it's a group mode. 5463 file_path = pjoin(self.me_dir, 'Source', 'run_config.inc') 5464 text = open(file_path).read() 5465 if re.search(r'''s*parameter\s+\(ChanPerJob=2\)''', text, re.I+re.M): 5466 return 'group' 5467 else: 5468 return 'v4'
5469 5470 ############################################################################
5471 - def monitor(self, run_type='monitor', mode=None, html=False):
5472 """ monitor the progress of running job """ 5473 5474 5475 starttime = time.time() 5476 if mode is None: 5477 mode = self.cluster_mode 5478 if mode > 0: 5479 if html: 5480 update_status = lambda idle, run, finish: \ 5481 self.update_status((idle, run, finish, run_type), level=None, 5482 force=False, starttime=starttime) 5483 update_first = lambda idle, run, finish: \ 5484 self.update_status((idle, run, finish, run_type), level=None, 5485 force=True, starttime=starttime) 5486 else: 5487 update_status = lambda idle, run, finish: None 5488 update_first = None 5489 try: 5490 self.cluster.wait(self.me_dir, update_status, update_first=update_first) 5491 except Exception, error: 5492 logger.info(error) 5493 if not self.force: 5494 ans = self.ask('Cluster Error detected. Do you want to clean the queue? ("c"=continue the run anyway)', 5495 default = 'y', choices=['y','n', 'c']) 5496 else: 5497 ans = 'y' 5498 if ans == 'y': 5499 self.cluster.remove() 5500 elif ans == 'c': 5501 return self.monitor(run_type=run_type, mode=mode, html=html) 5502 raise 5503 except KeyboardInterrupt, error: 5504 self.cluster.remove() 5505 raise
5506 5507 5508 5509 ############################################################################
5510 - def configure_directory(self, html_opening=True):
5511 """ All action require before any type of run """ 5512 5513 # Basic check 5514 assert os.path.exists(pjoin(self.me_dir,'SubProcesses')) 5515 5516 # environmental variables to be included in make_opts 5517 self.make_opts_var = {} 5518 5519 #see when the last file was modified 5520 time_mod = max([os.path.getmtime(pjoin(self.me_dir,'Cards','run_card.dat')), 5521 os.path.getmtime(pjoin(self.me_dir,'Cards','param_card.dat'))]) 5522 5523 if self.configured >= time_mod and hasattr(self, 'random') and hasattr(self, 'run_card'): 5524 #just ensure that cluster specific are correctly handled 5525 if self.cluster: 5526 self.cluster.modify_interface(self) 5527 return 5528 else: 5529 self.configured = time_mod 5530 self.update_status('compile directory', level=None, update_results=True) 5531 if self.options['automatic_html_opening'] and html_opening: 5532 misc.open_file(os.path.join(self.me_dir, 'crossx.html')) 5533 self.options['automatic_html_opening'] = False 5534 #open only once the web page 5535 # Change current working directory 5536 self.launching_dir = os.getcwd() 5537 5538 # Check if we need the MSSM special treatment 5539 model = self.find_model_name() 5540 if model == 'mssm' or model.startswith('mssm-'): 5541 param_card = pjoin(self.me_dir, 'Cards','param_card.dat') 5542 mg5_param = pjoin(self.me_dir, 'Source', 'MODEL', 'MG5_param.dat') 5543 check_param_card.convert_to_mg5card(param_card, mg5_param) 5544 check_param_card.check_valid_param_card(mg5_param) 5545 5546 # limit the number of event to 100k 5547 self.check_nb_events() 5548 5549 # this is in order to avoid conflicts between runs with and without 5550 # lhapdf 5551 misc.compile(['clean4pdf'], cwd = pjoin(self.me_dir, 'Source')) 5552 5553 # set lhapdf. 5554 if self.run_card['pdlabel'] == "lhapdf": 5555 self.make_opts_var['lhapdf'] = 'True' 5556 self.link_lhapdf(pjoin(self.me_dir,'lib')) 5557 pdfsetsdir = self.get_lhapdf_pdfsetsdir() 5558 lhaid_list = [int(self.run_card['lhaid'])] 5559 self.copy_lhapdf_set(lhaid_list, pdfsetsdir) 5560 if self.run_card['pdlabel'] != "lhapdf": 5561 self.pdffile = None 5562 self.make_opts_var['lhapdf'] = "" 5563 5564 # set random number 5565 if self.run_card['iseed'] != 0: 5566 self.random = int(self.run_card['iseed']) 5567 self.run_card['iseed'] = 0 5568 # Reset seed in run_card to 0, to ensure that following runs 5569 # will be statistically independent 5570 self.run_card.write(pjoin(self.me_dir, 'Cards','run_card.dat')) 5571 time_mod = max([os.path.getmtime(pjoin(self.me_dir,'Cards','run_card.dat')), 5572 os.path.getmtime(pjoin(self.me_dir,'Cards','param_card.dat'))]) 5573 self.configured = time_mod 5574 elif os.path.exists(pjoin(self.me_dir,'SubProcesses','randinit')): 5575 for line in open(pjoin(self.me_dir,'SubProcesses','randinit')): 5576 data = line.split('=') 5577 assert len(data) ==2 5578 self.random = int(data[1]) 5579 break 5580 else: 5581 self.random = random.randint(1, 30107) 5582 5583 #set random seed for python part of the code 5584 if self.run_card['python_seed'] == -2: #-2 means same as run_card 5585 import random 5586 random.seed(self.random) 5587 elif self.run_card['python_seed'] >= 0: 5588 import random 5589 random.seed(self.run_card['python_seed']) 5590 5591 if self.run_card['ickkw'] == 2: 5592 logger.info('Running with CKKW matching') 5593 self.treat_ckkw_matching() 5594 5595 # add the make_opts_var to make_opts 5596 self.update_make_opts() 5597 # reset list of Gdirectory 5598 self.Gdirs = None 5599 5600 # create param_card.inc and run_card.inc 5601 self.do_treatcards('') 5602 5603 logger.info("compile Source Directory") 5604 5605 # Compile 5606 for name in [ 'all', '../bin/internal/combine_events']: 5607 self.compile(arg=[name], cwd=os.path.join(self.me_dir, 'Source')) 5608 5609 bias_name = os.path.basename(self.run_card['bias_module']) 5610 if bias_name.lower()=='none': 5611 bias_name = 'dummy' 5612 5613 # Always refresh the bias dependencies file 5614 if os.path.exists(pjoin(self.me_dir, 'SubProcesses','bias_dependencies')): 5615 os.remove(pjoin(self.me_dir, 'SubProcesses','bias_dependencies')) 5616 if os.path.exists(pjoin(self.me_dir, 'Source','BIAS',bias_name,'bias_dependencies')): 5617 files.ln(pjoin(self.me_dir, 'Source','BIAS',bias_name,'bias_dependencies'), 5618 pjoin(self.me_dir, 'SubProcesses')) 5619 5620 if self.proc_characteristics['bias_module']!=bias_name and \ 5621 os.path.isfile(pjoin(self.me_dir, 'lib','libbias.a')): 5622 os.remove(pjoin(self.me_dir, 'lib','libbias.a')) 5623 5624 # Finally compile the bias module as well 5625 if self.run_card['bias_module']!='dummy': 5626 logger.debug("Compiling the bias module '%s'"%bias_name) 5627 # Verify the compatibility of the specified module 5628 bias_module_valid = misc.Popen(['make','requirements'], 5629 cwd=os.path.join(self.me_dir, 'Source','BIAS',bias_name), 5630 stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0] 5631 if 'VALID' not in bias_module_valid.upper() or \ 5632 'INVALID' in bias_module_valid.upper(): 5633 raise InvalidCmd("The bias module '%s' cannot be used because of:\n%s"% 5634 (bias_name,bias_module_valid)) 5635 5636 self.compile(arg=[], cwd=os.path.join(self.me_dir, 'Source','BIAS',bias_name)) 5637 self.proc_characteristics['bias_module']=bias_name 5638 # Update the proc_characterstics file 5639 self.proc_characteristics.write( 5640 pjoin(self.me_dir,'SubProcesses','proc_characteristics')) 5641 # Make sure that madevent will be recompiled 5642 subproc = [l.strip() for l in open(pjoin(self.me_dir,'SubProcesses', 5643 'subproc.mg'))] 5644 for nb_proc,subdir in enumerate(subproc): 5645 Pdir = pjoin(self.me_dir, 'SubProcesses',subdir.strip()) 5646 self.compile(['clean'], cwd=Pdir) 5647 5648 #see when the last file was modified 5649 time_mod = max([os.path.getmtime(pjoin(self.me_dir,'Cards','run_card.dat')), 5650 os.path.getmtime(pjoin(self.me_dir,'Cards','param_card.dat'))]) 5651 5652 self.configured = time_mod
5653 5654 ############################################################################ 5655 ## HELPING ROUTINE 5656 ############################################################################ 5657 @staticmethod
5658 - def check_dir(path, default=''):
5659 """check if the directory exists. if so return the path otherwise the 5660 default""" 5661 5662 if os.path.isdir(path): 5663 return path 5664 else: 5665 return default
5666 5667 5668 5669 ############################################################################
5670 - def get_Gdir(self, Pdir=None, symfact=None):
5671 """get the list of Gdirectory if not yet saved.""" 5672 5673 if hasattr(self, "Gdirs") and self.Gdirs: 5674 if self.me_dir in self.Gdirs[0]: 5675 if Pdir is None: 5676 if not symfact: 5677 return list(itertools.chain(*self.Gdirs[0].values())) 5678 else: 5679 return list(itertools.chain(*self.Gdirs[0].values())), self.Gdirs[1] 5680 else: 5681 if not symfact: 5682 return self.Gdirs[0][Pdir] 5683 else: 5684 return self.Gdirs[0][Pdir], self.Gdirs[1] 5685 5686 5687 Pdirs = self.get_Pdir() 5688 Gdirs = {self.me_dir:[]} 5689 mfactors = {} 5690 for P in Pdirs: 5691 Gdirs[P] = [] 5692 #for the next line do not use P, since in readonly mode it might not have symfact 5693 for line in open(pjoin(self.me_dir, 'SubProcesses',os.path.basename(P), "symfact.dat")): 5694 tag, mfactor = line.split() 5695 if int(mfactor) > 0: 5696 Gdirs[P].append( pjoin(P, "G%s" % tag) ) 5697 mfactors[pjoin(P, "G%s" % tag)] = mfactor 5698 self.Gdirs = (Gdirs, mfactors) 5699 return self.get_Gdir(Pdir, symfact=symfact)
5700 5701 ############################################################################
5702 - def set_run_name(self, name, tag=None, level='parton', reload_card=False, 5703 allow_new_tag=True):
5704 """define the run name, the run_tag, the banner and the results.""" 5705 5706 def get_last_tag(self, level): 5707 # Return the tag of the previous run having the required data for this 5708 # tag/run to working wel. 5709 if level == 'parton': 5710 return 5711 elif level in ['pythia','pythia8','madanalysis5_parton','madanalysis5_hadron']: 5712 return self.results[self.run_name][0]['tag'] 5713 else: 5714 for i in range(-1,-len(self.results[self.run_name])-1,-1): 5715 tagRun = self.results[self.run_name][i] 5716 if tagRun.pythia or tagRun.shower or tagRun.pythia8 : 5717 return tagRun['tag']
5718 5719 5720 # when are we force to change the tag new_run:previous run requiring changes 5721 upgrade_tag = {'parton': ['parton','pythia','pgs','delphes','madanalysis5_hadron','madanalysis5_parton'], 5722 'pythia': ['pythia','pgs','delphes','madanalysis5_hadron'], 5723 'pythia8': ['pythia8','pgs','delphes','madanalysis5_hadron'], 5724 'pgs': ['pgs'], 5725 'delphes':['delphes'], 5726 'madanalysis5_hadron':['madanalysis5_hadron'], 5727 'madanalysis5_parton':['madanalysis5_parton'], 5728 'plot':[], 5729 'syscalc':[]} 5730 5731 if name == self.run_name: 5732 if reload_card: 5733 run_card = pjoin(self.me_dir, 'Cards','run_card.dat') 5734 self.run_card = banner_mod.RunCard(run_card) 5735 5736 #check if we need to change the tag 5737 if tag: 5738 self.run_card['run_tag'] = tag 5739 self.run_tag = tag 5740 self.results.add_run(self.run_name, self.run_card) 5741 else: 5742 for tag in upgrade_tag[level]: 5743 if getattr(self.results[self.run_name][-1], tag): 5744 tag = self.get_available_tag() 5745 self.run_card['run_tag'] = tag 5746 self.run_tag = tag 5747 self.results.add_run(self.run_name, self.run_card) 5748 break 5749 return get_last_tag(self, level) 5750 5751 5752 # save/clean previous run 5753 if self.run_name: 5754 self.store_result() 5755 # store new name 5756 self.run_name = name 5757 5758 new_tag = False 5759 # First call for this run -> set the banner 5760 self.banner = banner_mod.recover_banner(self.results, level, name) 5761 if 'mgruncard' in self.banner: 5762 self.run_card = self.banner.charge_card('run_card') 5763 else: 5764 # Read run_card 5765 run_card = pjoin(self.me_dir, 'Cards','run_card.dat') 5766 self.run_card = banner_mod.RunCard(run_card) 5767 5768 if tag: 5769 self.run_card['run_tag'] = tag 5770 new_tag = True 5771 elif not self.run_name in self.results and level =='parton': 5772 pass # No results yet, so current tag is fine 5773 elif not self.run_name in self.results: 5774 #This is only for case when you want to trick the interface 5775 logger.warning('Trying to run data on unknown run.') 5776 self.results.add_run(name, self.run_card) 5777 self.results.update('add run %s' % name, 'all', makehtml=False) 5778 else: 5779 for tag in upgrade_tag[level]: 5780 5781 if getattr(self.results[self.run_name][-1], tag): 5782 # LEVEL is already define in the last tag -> need to switch tag 5783 tag = self.get_available_tag() 5784 self.run_card['run_tag'] = tag 5785 new_tag = True 5786 break 5787 if not new_tag: 5788 # We can add the results to the current run 5789 tag = self.results[self.run_name][-1]['tag'] 5790 self.run_card['run_tag'] = tag # ensure that run_tag is correct 5791 5792 if allow_new_tag and (name in self.results and not new_tag): 5793 self.results.def_current(self.run_name) 5794 else: 5795 self.results.add_run(self.run_name, self.run_card) 5796 5797 self.run_tag = self.run_card['run_tag'] 5798 5799 return get_last_tag(self, level) 5800 5801 5802 5803 ############################################################################
5804 - def check_nb_events(self):
5805 """Find the number of event in the run_card, and check that this is not 5806 too large""" 5807 5808 5809 nb_event = int(self.run_card['nevents']) 5810 if nb_event > 1000000: 5811 logger.warning("Attempting to generate more than 1M events") 5812 logger.warning("Limiting number to 1M. Use multi_run for larger statistics.") 5813 path = pjoin(self.me_dir, 'Cards', 'run_card.dat') 5814 os.system(r"""perl -p -i.bak -e "s/\d+\s*=\s*nevents/1000000 = nevents/" %s""" \ 5815 % path) 5816 self.run_card['nevents'] = 1000000 5817 5818 return
5819 5820 5821 ############################################################################
5822 - def update_random(self):
5823 """ change random number""" 5824 5825 self.random += 3 5826 if self.random > 30081*30081: # can't use too big random number 5827 raise MadGraph5Error,\ 5828 'Random seed too large ' + str(self.random) + ' > 30081*30081' 5829 if self.run_card['python_seed'] == -2: 5830 import random 5831 random.seed(self.random)
5832 5833 ############################################################################
5834 - def save_random(self):
5835 """save random number in appropirate file""" 5836 5837 fsock = open(pjoin(self.me_dir, 'SubProcesses','randinit'),'w') 5838 fsock.writelines('r=%s\n' % self.random)
5839
5840 - def do_quit(self, *args, **opts):
5841 5842 return common_run.CommonRunCmd.do_quit(self, *args, **opts)
5843 #return CmdExtended.do_quit(self, *args, **opts) 5844 5845 ############################################################################
5846 - def treat_CKKW_matching(self):
5847 """check for ckkw""" 5848 5849 lpp1 = self.run_card['lpp1'] 5850 lpp2 = self.run_card['lpp2'] 5851 e1 = self.run_card['ebeam1'] 5852 e2 = self.run_card['ebeam2'] 5853 pd = self.run_card['pdlabel'] 5854 lha = self.run_card['lhaid'] 5855 xq = self.run_card['xqcut'] 5856 translation = {'e1': e1, 'e2':e2, 'pd':pd, 5857 'lha':lha, 'xq':xq} 5858 5859 if lpp1 or lpp2: 5860 # Remove ':s from pd 5861 if pd.startswith("'"): 5862 pd = pd[1:] 5863 if pd.endswith("'"): 5864 pd = pd[:-1] 5865 5866 if xq >2 or xq ==2: 5867 xq = 2 5868 5869 # find data file 5870 if pd == "lhapdf": 5871 issudfile = 'lib/issudgrid-%(e1)s-%(e2)s-%(pd)s-%(lha)s-%(xq)s.dat.gz' 5872 else: 5873 issudfile = 'lib/issudgrid-%(e1)s-%(e2)s-%(pd)s-%(xq)s.dat.gz' 5874 if self.web: 5875 issudfile = pjoin(self.webbin, issudfile % translation) 5876 else: 5877 issudfile = pjoin(self.me_dir, issudfile % translation) 5878 5879 logger.info('Sudakov grid file: %s' % issudfile) 5880 5881 # check that filepath exists 5882 if os.path.exists(issudfile): 5883 path = pjoin(self.me_dir, 'lib', 'issudgrid.dat') 5884 misc.gunzip(issudfile, keep=True, stdout=path) 5885 else: 5886 msg = 'No sudakov grid file for parameter choice. Start to generate it. This might take a while' 5887 logger.info(msg) 5888 self.update_status('GENERATE SUDAKOV GRID', level='parton') 5889 5890 for i in range(-2,6): 5891 self.cluster.submit('%s/gensudgrid ' % self.dirbin, 5892 argument = ['%d'%i], 5893 cwd=self.me_dir, 5894 stdout=open(pjoin(self.me_dir, 'gensudgrid%s.log' % i),'w')) 5895 self.monitor() 5896 for i in range(-2,6): 5897 path = pjoin(self.me_dir, 'lib', 'issudgrid.dat') 5898 os.system('cat %s/gensudgrid%s.log >> %s' % (self.me_dir, path)) 5899 misc.gzip(path, stdout=issudfile)
5900 5901 ############################################################################
5902 - def create_root_file(self, input='unweighted_events.lhe', 5903 output='unweighted_events.root' ):
5904 """create the LHE root file """ 5905 self.update_status('Creating root files', level='parton') 5906 5907 eradir = self.options['exrootanalysis_path'] 5908 totar = False 5909 if input.endswith('.gz'): 5910 misc.gunzip(input, keep=True) 5911 totar = True 5912 input = input[:-3] 5913 5914 try: 5915 misc.call(['%s/ExRootLHEFConverter' % eradir, 5916 input, output], 5917 cwd=pjoin(self.me_dir, 'Events')) 5918 except Exception: 5919 logger.warning('fail to produce Root output [problem with ExRootAnalysis]') 5920 5921 if totar: 5922 if os.path.exists('%s.gz' % input): 5923 try: 5924 os.remove(input) 5925 except: 5926 pass 5927 else: 5928 misc.gzip(input,keep=False)
5929 5930
5931 - def run_syscalc(self, mode='parton', event_path=None, output=None):
5932 """create the syscalc output""" 5933 5934 if self.run_card['use_syst'] not in self.true: 5935 return 5936 5937 scdir = self.options['syscalc_path'] 5938 if not scdir or not os.path.exists(scdir): 5939 return 5940 5941 if self.run_card['event_norm'] != 'sum': 5942 logger.critical('SysCalc works only when event_norm is on \'sum\'.') 5943 return 5944 logger.info('running SysCalc on mode %s' % mode) 5945 5946 # Restore the old default for SysCalc+PY6 5947 if self.run_card['sys_matchscale']=='auto': 5948 self.run_card['sys_matchscale'] = "30 50" 5949 5950 # Check that all pdfset are correctly installed 5951 lhaid = [self.run_card.get_lhapdf_id()] 5952 if '&&' in self.run_card['sys_pdf']: 5953 line = ' '.join(self.run_card['sys_pdf']) 5954 sys_pdf = line.split('&&') 5955 lhaid += [l.split()[0] for l in sys_pdf] 5956 else: 5957 lhaid += [l for l in self.run_card['sys_pdf'].split() if not l.isdigit() or int(l) > 500] 5958 try: 5959 pdfsets_dir = self.get_lhapdf_pdfsetsdir() 5960 except Exception, error: 5961 logger.debug(str(error)) 5962 logger.warning('Systematic computation requires lhapdf to run. Bypass SysCalc') 5963 return 5964 5965 # Copy all the relevant PDF sets 5966 [self.copy_lhapdf_set([onelha], pdfsets_dir) for onelha in lhaid] 5967 5968 to_syscalc={'sys_scalefact': self.run_card['sys_scalefact'], 5969 'sys_alpsfact': self.run_card['sys_alpsfact'], 5970 'sys_matchscale': self.run_card['sys_matchscale'], 5971 'sys_scalecorrelation': self.run_card['sys_scalecorrelation'], 5972 'sys_pdf': self.run_card['sys_pdf']} 5973 5974 tag = self.run_card['run_tag'] 5975 card = pjoin(self.me_dir, 'bin','internal', 'syscalc_card.dat') 5976 template = open(pjoin(self.me_dir, 'bin','internal', 'syscalc_template.dat')).read() 5977 5978 if '&&' in to_syscalc['sys_pdf']: 5979 to_syscalc['sys_pdf'] = to_syscalc['sys_pdf'].split('#',1)[0].replace('&&',' \n ') 5980 else: 5981 data = to_syscalc['sys_pdf'].split() 5982 new = [] 5983 for d in data: 5984 if not d.isdigit(): 5985 new.append(d) 5986 elif int(d) > 500: 5987 new.append(d) 5988 else: 5989 new[-1] += ' %s' % d 5990 to_syscalc['sys_pdf'] = '\n'.join(new) 5991 5992 if to_syscalc['sys_pdf'].lower() in ['', 'f', 'false', 'none', '.false.']: 5993 to_syscalc['sys_pdf'] = '' 5994 if to_syscalc['sys_alpsfact'].lower() in ['', 'f', 'false', 'none','.false.']: 5995 to_syscalc['sys_alpsfact'] = '' 5996 5997 5998 5999 6000 # check if the scalecorrelation parameter is define: 6001 if not 'sys_scalecorrelation' in self.run_card: 6002 self.run_card['sys_scalecorrelation'] = -1 6003 open(card,'w').write(template % self.run_card) 6004 6005 if not os.path.exists(card): 6006 return False 6007 6008 6009 6010 event_dir = pjoin(self.me_dir, 'Events') 6011 6012 if not event_path: 6013 if mode == 'parton': 6014 event_path = pjoin(event_dir,self.run_name, 'unweighted_events.lhe') 6015 if not (os.path.exists(event_path) or os.path.exists(event_path+".gz")): 6016 event_path = pjoin(event_dir, 'unweighted_events.lhe') 6017 output = pjoin(event_dir, 'syscalc.lhe') 6018 stdout = open(pjoin(event_dir, self.run_name, '%s_systematics.log' % (mode)),'w') 6019 elif mode == 'Pythia': 6020 stdout = open(pjoin(event_dir, self.run_name, '%s_%s_syscalc.log' % (tag,mode)),'w') 6021 if 'mgpythiacard' in self.banner: 6022 pat = re.compile('''^\s*qcut\s*=\s*([\+\-\d.e]*)''', re.M+re.I) 6023 data = pat.search(self.banner['mgpythiacard']) 6024 if data: 6025 qcut = float(data.group(1)) 6026 xqcut = abs(self.run_card['xqcut']) 6027 for value in self.run_card['sys_matchscale'].split(): 6028 if float(value) < qcut: 6029 raise SysCalcError, 'qcut value for sys_matchscale lower than qcut in pythia_card. Bypass syscalc' 6030 if float(value) < xqcut: 6031 raise SysCalcError, 'qcut value for sys_matchscale lower than xqcut in run_card. Bypass syscalc' 6032 6033 6034 event_path = pjoin(event_dir,'syst.dat') 6035 output = pjoin(event_dir, 'syscalc.dat') 6036 else: 6037 raise self.InvalidCmd, 'Invalid mode %s' % mode 6038 6039 if not os.path.exists(event_path): 6040 if os.path.exists(event_path+'.gz'): 6041 misc.gunzip(event_path+'.gz') 6042 else: 6043 raise SysCalcError, 'Events file %s does not exits' % event_path 6044 6045 self.update_status('Calculating systematics for %s level' % mode, level = mode.lower()) 6046 try: 6047 proc = misc.call([os.path.join(scdir, 'sys_calc'), 6048 event_path, card, output], 6049 stdout = stdout, 6050 stderr = subprocess.STDOUT, 6051 cwd=event_dir) 6052 # Wait 5 s to make sure file is finished writing 6053 time.sleep(5) 6054 except OSError, error: 6055 logger.error('fail to run syscalc: %s. Please check that SysCalc is correctly installed.' % error) 6056 else: 6057 if not os.path.exists(output): 6058 logger.warning('SysCalc Failed. Please read the associate log to see the reason. Did you install the associate PDF set?') 6059 elif mode == 'parton': 6060 files.mv(output, event_path) 6061 6062 self.update_status('End syscalc for %s level' % mode, level = mode.lower(), 6063 makehtml=False) 6064 6065 return True
6066 6067 6068 action_switcher = AskRun 6069 ############################################################################
6070 - def ask_run_configuration(self, mode=None, args=[]):
6071 """Ask the question when launching generate_events/multi_run""" 6072 6073 passing_cmd = [] 6074 if '-R' in args or '--reweight' in args: 6075 passing_cmd.append('reweight=ON') 6076 if '-M' in args or '--madspin' in args: 6077 passing_cmd.append('madspin=ON') 6078 6079 switch, cmd_switch = self.ask('', '0', [], ask_class = self.action_switcher, 6080 mode=mode, line_args=args, force=self.force, 6081 first_cmd=passing_cmd, return_instance=True) 6082 # 6083 self.switch = switch # store the value of the switch for plugin purpose 6084 if 'dynamical' in switch: 6085 mode = 'auto' 6086 6087 # Now that we know in which mode we are check that all the card 6088 #exists (copy default if needed) 6089 6090 cards = ['param_card.dat', 'run_card.dat'] 6091 if switch['shower'] == 'Pythia6': 6092 cards.append('pythia_card.dat') 6093 if switch['shower'] == 'Pythia8': 6094 cards.append('pythia8_card.dat') 6095 if switch['detector'] in ['PGS','DELPHES+PGS']: 6096 cards.append('pgs_card.dat') 6097 if switch['detector'] in ['Delphes', 'DELPHES+PGS']: 6098 cards.append('delphes_card.dat') 6099 delphes3 = True 6100 if os.path.exists(pjoin(self.options['delphes_path'], 'data')): 6101 delphes3 = False 6102 cards.append('delphes_trigger.dat') 6103 if switch['madspin'] != 'OFF': 6104 cards.append('madspin_card.dat') 6105 if switch['reweight'] != 'OFF': 6106 cards.append('reweight_card.dat') 6107 if switch['analysis'].upper() in ['MADANALYSIS5']: 6108 cards.append('madanalysis5_parton_card.dat') 6109 if switch['analysis'].upper() in ['MADANALYSIS5'] and not switch['shower']=='OFF': 6110 cards.append('madanalysis5_hadron_card.dat') 6111 if switch['analysis'].upper() in ['MADANALYSIS4']: 6112 cards.append('plot_card.dat') 6113 6114 self.keep_cards(cards) 6115 6116 first_cmd = cmd_switch.get_cardcmd() 6117 6118 if os.path.isfile(pjoin(self.me_dir,'Cards','MadLoopParams.dat')): 6119 cards.append('MadLoopParams.dat') 6120 6121 if self.force: 6122 self.check_param_card(pjoin(self.me_dir,'Cards','param_card.dat' )) 6123 return switch 6124 6125 6126 if 'dynamical' in switch and switch['dynamical']: 6127 self.ask_edit_cards(cards, plot=False, mode='auto', first_cmd=first_cmd) 6128 else: 6129 self.ask_edit_cards(cards, plot=False, first_cmd=first_cmd) 6130 return switch
6131 6132 ############################################################################
6133 - def ask_pythia_run_configuration(self, mode=None, pythia_version=6, banner=None):
6134 """Ask the question when launching pythia""" 6135 6136 pythia_suffix = '' if pythia_version==6 else '%d'%pythia_version 6137 6138 available_mode = ['0', '1'] 6139 if pythia_version==6: 6140 available_mode.append('2') 6141 if self.options['delphes_path']: 6142 available_mode.append('3') 6143 name = {'0': 'auto', '2':'pgs', '3':'delphes'} 6144 name['1'] = 'pythia%s'%pythia_suffix 6145 options = available_mode + [name[val] for val in available_mode] 6146 question = """Which programs do you want to run? 6147 0 / auto : running existing cards\n""" 6148 if pythia_version==6: 6149 question += """ 1. pythia : Pythia\n""" 6150 question += """ 2. pgs : Pythia + PGS\n""" 6151 else: 6152 question += """ 1. pythia8 : Pythia8\n""" 6153 6154 if '3' in available_mode: 6155 question += """ 3. delphes : Pythia%s + Delphes.\n"""%pythia_suffix 6156 6157 if not self.force: 6158 if not mode: 6159 mode = self.ask(question, '0', options) 6160 elif not mode: 6161 mode = 'auto' 6162 6163 if mode.isdigit(): 6164 mode = name[mode] 6165 6166 auto = False 6167 if mode == 'auto': 6168 auto = True 6169 if pythia_version==6 and os.path.exists(pjoin(self.me_dir, 6170 'Cards', 'pgs_card.dat')): 6171 mode = 'pgs' 6172 elif os.path.exists(pjoin(self.me_dir, 'Cards', 'delphes_card.dat')): 6173 mode = 'delphes' 6174 else: 6175 mode = 'pythia%s'%pythia_suffix 6176 logger.info('Will run in mode %s' % mode) 6177 # Now that we know in which mode we are check that all the card 6178 #exists (copy default if needed) remove pointless one 6179 cards = ['pythia%s_card.dat'%pythia_suffix] 6180 if mode == 'pgs' and pythia_version==6: 6181 cards.append('pgs_card.dat') 6182 if mode == 'delphes': 6183 cards.append('delphes_card.dat') 6184 delphes3 = True 6185 if os.path.exists(pjoin(self.options['delphes_path'], 'data')): 6186 delphes3 = False 6187 cards.append('delphes_trigger.dat') 6188 self.keep_cards(cards, ignore=['madanalysis5_parton_card.dat','madanalysis5_hadron_card.dat', 6189 'plot_card.dat']) 6190 6191 if self.force: 6192 return mode 6193 6194 if not banner: 6195 banner = self.banner 6196 6197 if auto: 6198 self.ask_edit_cards(cards, from_banner=['param', 'run'], 6199 mode='auto', plot=(pythia_version==6), banner=banner 6200 ) 6201 else: 6202 self.ask_edit_cards(cards, from_banner=['param', 'run'], 6203 plot=(pythia_version==6), banner=banner) 6204 6205 return mode
6206
6207 #=============================================================================== 6208 # MadEventCmd 6209 #=============================================================================== 6210 -class MadEventCmdShell(MadEventCmd, cmd.CmdShell):
6211 """The command line processor of MadGraph"""
6212
6213 6214 6215 #=============================================================================== 6216 # HELPING FUNCTION For Subprocesses 6217 #=============================================================================== 6218 -class SubProcesses(object):
6219 6220 name_to_pdg = {} 6221 6222 @classmethod
6223 - def clean(cls):
6224 cls.name_to_pdg = {}
6225 6226 @staticmethod
6227 - def get_subP(me_dir):
6228 """return the list of Subprocesses""" 6229 6230 out = [] 6231 for line in open(pjoin(me_dir,'SubProcesses', 'subproc.mg')): 6232 if not line: 6233 continue 6234 name = line.strip() 6235 if os.path.exists(pjoin(me_dir, 'SubProcesses', name)): 6236 out.append(pjoin(me_dir, 'SubProcesses', name)) 6237 6238 return out
6239 6240 6241 6242 @staticmethod
6243 - def get_subP_info(path):
6244 """ return the list of processes with their name""" 6245 6246 nb_sub = 0 6247 names = {} 6248 old_main = '' 6249 6250 if not os.path.exists(os.path.join(path,'processes.dat')): 6251 return SubProcesses.get_subP_info_v4(path) 6252 6253 for line in open(os.path.join(path,'processes.dat')): 6254 main = line[:8].strip() 6255 if main == 'mirror': 6256 main = old_main 6257 if line[8:].strip() == 'none': 6258 continue 6259 else: 6260 main = int(main) 6261 old_main = main 6262 6263 sub_proccess = line[8:] 6264 nb_sub += sub_proccess.count(',') + 1 6265 if main in names: 6266 names[main] += [sub_proccess.split(',')] 6267 else: 6268 names[main]= [sub_proccess.split(',')] 6269 6270 return names
6271 6272 @staticmethod
6273 - def get_subP_info_v4(path):
6274 """ return the list of processes with their name in case without grouping """ 6275 6276 nb_sub = 0 6277 names = {'':[[]]} 6278 path = os.path.join(path, 'auto_dsig.f') 6279 found = 0 6280 for line in open(path): 6281 if line.startswith('C Process:'): 6282 found += 1 6283 names[''][0].append(line[15:]) 6284 elif found >1: 6285 break 6286 return names
6287 6288 6289 @staticmethod
6290 - def get_subP_ids(path):
6291 """return the pdg codes of the particles present in the Subprocesses""" 6292 6293 all_ids = [] 6294 for line in open(pjoin(path, 'leshouche.inc')): 6295 if not 'IDUP' in line: 6296 continue 6297 particles = re.search("/([\d,-]+)/", line) 6298 all_ids.append([int(p) for p in particles.group(1).split(',')]) 6299 return all_ids
6300
6301 6302 #=============================================================================== 6303 -class GridPackCmd(MadEventCmd):
6304 """The command for the gridpack --Those are not suppose to be use interactively--""" 6305
6306 - def __init__(self, me_dir = None, nb_event=0, seed=0, gran=-1, *completekey, **stdin):
6307 """Initialize the command and directly run""" 6308 6309 # Initialize properly 6310 self.readonly = False 6311 MadEventCmd.__init__(self, me_dir, *completekey, **stdin) 6312 self.run_mode = 0 6313 self.random = seed 6314 self.random_orig = self.random 6315 self.granularity = gran 6316 6317 self.options['automatic_html_opening'] = False 6318 #write the grid_card.dat on disk 6319 self.nb_event = int(nb_event) 6320 self.write_gridcard(nb_event, seed, gran) # set readonly on True if needed 6321 self.prepare_local_dir() # move to gridpack dir or create local structure 6322 # Now it's time to run! 6323 if me_dir and nb_event and seed: 6324 self.launch(nb_event, seed) 6325 else: 6326 raise MadGraph5Error,\ 6327 'Gridpack run failed: ' + str(me_dir) + str(nb_event) + \ 6328 str(seed)
6329 6330
6331 - def update_status(self, *args, **opts):
6332 return
6333
6334 - def load_results_db(self):
6335 """load the current results status""" 6336 model = self.find_model_name() 6337 process = self.process # define in find_model_name 6338 self.results = gen_crossxhtml.AllResults(model, process, self.me_dir) 6339 self.last_mode=''
6340
6341 - def save_random(self):
6342 """save random number in appropirate file""" 6343 6344 if not self.readonly: 6345 fsock = open(pjoin(self.me_dir, 'SubProcesses','randinit'),'w') 6346 else: 6347 fsock = open('randinit','w') 6348 fsock.writelines('r=%s\n' % self.random)
6349
6350 - def write_RunWeb(self, me_dir):
6351 try: 6352 super(GridPackCmd, self).write_RunWeb(me_dir) 6353 except IOError: 6354 self.readonly =True
6355
6356 - def write_gridcard(self, nb_event, seed, gran):
6357 """write the grid_card.dat file at appropriate location""" 6358 6359 # first try to write grid_card within the gridpack. 6360 print "WRITE GRIDCARD", self.me_dir 6361 if self.readonly: 6362 if not os.path.exists('Cards'): 6363 os.mkdir('Cards') 6364 fsock = open('grid_card.dat','w') 6365 else: 6366 fsock = open(pjoin(self.me_dir, 'Cards', 'grid_card.dat'),'w') 6367 6368 gridpackcard = banner_mod.GridpackCard() 6369 gridpackcard['GridRun'] = True 6370 gridpackcard['gevents'] = nb_event 6371 gridpackcard['gseed'] = seed 6372 gridpackcard['ngran'] = gran 6373 6374 gridpackcard.write(fsock)
6375 6376 ############################################################################
6377 - def get_Pdir(self):
6378 """get the list of Pdirectory if not yet saved.""" 6379 6380 if hasattr(self, "Pdirs"): 6381 if self.me_dir in self.Pdirs[0]: 6382 return self.Pdirs 6383 6384 if not self.readonly: 6385 self.Pdirs = [pjoin(self.me_dir, 'SubProcesses', l.strip()) 6386 for l in open(pjoin(self.me_dir,'SubProcesses', 'subproc.mg'))] 6387 else: 6388 self.Pdirs = [l.strip() 6389 for l in open(pjoin(self.me_dir,'SubProcesses', 'subproc.mg'))] 6390 6391 return self.Pdirs
6392
6393 - def prepare_local_dir(self):
6394 """create the P directory structure in the local directory""" 6395 6396 if not self.readonly: 6397 os.chdir(self.me_dir) 6398 else: 6399 for line in open(pjoin(self.me_dir,'SubProcesses','subproc.mg')): 6400 os.mkdir(line.strip())
6401 6402
6403 - def launch(self, nb_event, seed):
6404 """ launch the generation for the grid """ 6405 6406 # 1) Restore the default data 6407 logger.info('generate %s events' % nb_event) 6408 self.set_run_name('GridRun_%s' % seed) 6409 if not self.readonly: 6410 self.update_status('restoring default data', level=None) 6411 misc.call([pjoin(self.me_dir,'bin','internal','restore_data'), 6412 'default'], cwd=self.me_dir) 6413 6414 # 2) Run the refine for the grid 6415 self.update_status('Generating Events', level=None) 6416 #misc.call([pjoin(self.me_dir,'bin','refine4grid'), 6417 # str(nb_event), '0', 'Madevent','1','GridRun_%s' % seed], 6418 # cwd=self.me_dir) 6419 self.refine4grid(nb_event) 6420 6421 # 3) Combine the events/pythia/... 6422 self.exec_cmd('combine_events') 6423 if not self.readonly: 6424 self.exec_cmd('store_events') 6425 self.print_results_in_shell(self.results.current) 6426 if self.run_card['systematics_program'] == 'systematics': 6427 self.exec_cmd('systematics %s --from_card' % self.run_name, 6428 postcmd=False,printcmd=False) 6429 self.exec_cmd('decay_events -from_cards', postcmd=False) 6430 else: 6431 self.exec_cmd('systematics %s --from_card' % 6432 pjoin('Events', self.run_name, 'unweighted_events.lhe.gz'), 6433 postcmd=False,printcmd=False)
6434 6435
6436 - def refine4grid(self, nb_event):
6437 """Special refine for gridpack run.""" 6438 self.nb_refine += 1 6439 6440 precision = nb_event 6441 6442 self.opts = dict([(key,value[1]) for (key,value) in \ 6443 self._survey_options.items()]) 6444 6445 # initialize / remove lhapdf mode 6446 # self.configure_directory() # All this has been done before 6447 self.cluster_mode = 0 # force single machine 6448 6449 # Store seed in randinit file, to be read by ranmar.f 6450 self.save_random() 6451 6452 self.update_status('Refine results to %s' % precision, level=None) 6453 logger.info("Using random number seed offset = %s" % self.random) 6454 6455 refine_opt = {'err_goal': nb_event, 'split_channels': False, 6456 'ngran':self.granularity, 'readonly': self.readonly} 6457 x_improve = gen_ximprove.gen_ximprove_gridpack(self, refine_opt) 6458 x_improve.launch() # create the ajob for the refinment and run those! 6459 self.gscalefact = x_improve.gscalefact #store jacobian associate to the gridpack 6460 6461 6462 #bindir = pjoin(os.path.relpath(self.dirbin, pjoin(self.me_dir,'SubProcesses'))) 6463 #print 'run combine!!!' 6464 #combine_runs.CombineRuns(self.me_dir) 6465 6466 return 6467 #update html output 6468 Presults = sum_html.collect_result(self) 6469 cross, error = Presults.xsec, Presults.xerru 6470 self.results.add_detail('cross', cross) 6471 self.results.add_detail('error', error) 6472 6473 6474 #self.update_status('finish refine', 'parton', makehtml=False) 6475 #devnull.close() 6476 6477 6478 6479 return 6480 self.total_jobs = 0 6481 subproc = [P for P in os.listdir(pjoin(self.me_dir,'SubProcesses')) if 6482 P.startswith('P') and os.path.isdir(pjoin(self.me_dir,'SubProcesses', P))] 6483 devnull = open(os.devnull, 'w') 6484 for nb_proc,subdir in enumerate(subproc): 6485 subdir = subdir.strip() 6486 Pdir = pjoin(self.me_dir, 'SubProcesses',subdir) 6487 bindir = pjoin(os.path.relpath(self.dirbin, Pdir)) 6488 6489 logger.info(' %s ' % subdir) 6490 # clean previous run 6491 for match in misc.glob('*ajob*', Pdir): 6492 if os.path.basename(match)[:4] in ['ajob', 'wait', 'run.', 'done']: 6493 os.remove(pjoin(Pdir, match)) 6494 6495 6496 logfile = pjoin(Pdir, 'gen_ximprove.log') 6497 misc.call([pjoin(bindir, 'gen_ximprove')], 6498 stdin=subprocess.PIPE, 6499 stdout=open(logfile,'w'), 6500 cwd=Pdir) 6501 6502 if os.path.exists(pjoin(Pdir, 'ajob1')): 6503 alljobs = misc.glob('ajob*', Pdir) 6504 nb_tot = len(alljobs) 6505 self.total_jobs += nb_tot 6506 for i, job in enumerate(alljobs): 6507 job = os.path.basename(job) 6508 self.launch_job('%s' % job, cwd=Pdir, remaining=(nb_tot-i-1), 6509 run_type='Refine number %s on %s (%s/%s)' % 6510 (self.nb_refine, subdir, nb_proc+1, len(subproc))) 6511 if os.path.exists(pjoin(self.me_dir,'error')): 6512 self.monitor(html=True) 6513 raise MadEventError, \ 6514 'Error detected in dir %s: %s' % \ 6515 (Pdir, open(pjoin(self.me_dir,'error')).read()) 6516 self.monitor(run_type='All job submitted for refine number %s' % 6517 self.nb_refine) 6518 6519 self.update_status("Combining runs", level='parton') 6520 try: 6521 os.remove(pjoin(Pdir, 'combine_runs.log')) 6522 except Exception: 6523 pass 6524 6525 bindir = pjoin(os.path.relpath(self.dirbin, pjoin(self.me_dir,'SubProcesses'))) 6526 combine_runs.CombineRuns(self.me_dir) 6527 6528 #update html output 6529 cross, error = self.make_make_all_html_results() 6530 self.results.add_detail('cross', cross) 6531 self.results.add_detail('error', error) 6532 6533 6534 self.update_status('finish refine', 'parton', makehtml=False) 6535 devnull.close()
6536
6537 - def do_combine_events(self, line):
6538 """Advanced commands: Launch combine events""" 6539 6540 if self.readonly: 6541 outdir = 'Events' 6542 if not os.path.exists(outdir): 6543 os.mkdir(outdir) 6544 else: 6545 outdir = pjoin(self.me_dir, 'Events') 6546 args = self.split_arg(line) 6547 # Check argument's validity 6548 self.check_combine_events(args) 6549 gscalefact = self.gscalefact # {(C.get('name')): jac} 6550 # Define The Banner 6551 tag = self.run_card['run_tag'] 6552 # Update the banner with the pythia card 6553 if not self.banner: 6554 self.banner = banner_mod.recover_banner(self.results, 'parton') 6555 self.banner.load_basic(self.me_dir) 6556 # Add cross-section/event information 6557 self.banner.add_generation_info(self.results.current['cross'], self.run_card['nevents']) 6558 if not hasattr(self, 'random_orig'): self.random_orig = 0 6559 self.banner.change_seed(self.random_orig) 6560 6561 6562 if not os.path.exists(pjoin(outdir, self.run_name)): 6563 os.mkdir(pjoin(outdir, self.run_name)) 6564 self.banner.write(pjoin(outdir, self.run_name, 6565 '%s_%s_banner.txt' % (self.run_name, tag))) 6566 6567 get_wgt = lambda event: event.wgt 6568 AllEvent = lhe_parser.MultiEventFile() 6569 AllEvent.banner = self.banner 6570 6571 partials = 0 # if too many file make some partial unweighting 6572 sum_xsec, sum_xerru, sum_axsec = 0,[],0 6573 for Gdir in self.get_Gdir(): 6574 #mfactor already taken into accoun in auto_dsig.f 6575 if os.path.exists(pjoin(Gdir, 'events.lhe')): 6576 result = sum_html.OneResult('') 6577 result.read_results(pjoin(Gdir, 'results.dat')) 6578 AllEvent.add(pjoin(Gdir, 'events.lhe'), 6579 result.get('xsec')*gscalefact[Gdir], 6580 result.get('xerru')*gscalefact[Gdir], 6581 result.get('axsec')*gscalefact[Gdir] 6582 ) 6583 6584 sum_xsec += result.get('xsec')*gscalefact[Gdir] 6585 sum_xerru.append(result.get('xerru')*gscalefact[Gdir]) 6586 sum_axsec += result.get('axsec')*gscalefact[Gdir] 6587 6588 if len(AllEvent) >= 80: #perform a partial unweighting 6589 AllEvent.unweight(pjoin(self.me_dir, "Events", self.run_name, "partials%s.lhe.gz" % partials), 6590 get_wgt, log_level=5, trunc_error=1e-2, event_target=self.nb_event) 6591 AllEvent = lhe_parser.MultiEventFile() 6592 AllEvent.banner = self.banner 6593 AllEvent.add(pjoin(self.me_dir, "Events", self.run_name, "partials%s.lhe.gz" % partials), 6594 sum_xsec, 6595 math.sqrt(sum(x**2 for x in sum_xerru)), 6596 sum_axsec) 6597 partials +=1 6598 6599 if not hasattr(self,'proc_characteristic'): 6600 self.proc_characteristic = self.get_characteristics() 6601 6602 nb_event = AllEvent.unweight(pjoin(outdir, self.run_name, "unweighted_events.lhe.gz"), 6603 get_wgt, trunc_error=1e-2, event_target=self.nb_event, 6604 log_level=logging.DEBUG, normalization=self.run_card['event_norm'], 6605 proc_charac=self.proc_characteristic) 6606 6607 6608 if partials: 6609 for i in range(partials): 6610 try: 6611 os.remove(pjoin(outdir, self.run_name, "partials%s.lhe.gz" % i)) 6612 except Exception: 6613 os.remove(pjoin(outdir, self.run_name, "partials%s.lhe" % i)) 6614 6615 self.results.add_detail('nb_event', nb_event) 6616 6617 if self.run_card['bias_module'].lower() not in ['dummy', 'none']: 6618 self.correct_bias()
6619
6620 - def do_combine_events_v4(self, line):
6621 """Advanced commands: Launch combine events""" 6622 6623 args = self.split_arg(line) 6624 6625 # Check argument's validity 6626 self.check_combine_events(args) 6627 6628 self.update_status('Combining Events', level='parton') 6629 6630 try: 6631 os.remove(pjoin(self.me_dir,'SubProcesses', 'combine.log')) 6632 except Exception: 6633 pass 6634 6635 if not self.readonly: 6636 run_dir = pjoin(self.me_dir,'SubProcesses') 6637 stdout_file = pjoin(self.me_dir,'SubProcesses', 'combine.log') 6638 else: 6639 run_dir = pjoin('SubProcesses') 6640 stdout_file = pjoin('SubProcesses', 'combine.log') 6641 6642 cluster.onecore.launch_and_wait('../bin/internal/run_combine', 6643 args=[self.run_name], 6644 cwd=run_dir, 6645 stdout=stdout_file, 6646 required_output=[pjoin(self.me_dir,'SubProcesses', 'combine.log')]) 6647 6648 output = misc.mult_try_open(stdout_file).read() 6649 # Store the number of unweighted events for the results object 6650 pat = re.compile(r'''\s*Unweighting\s*selected\s*(\d+)\s*events''') 6651 try: 6652 nb_event = pat.search(output).groups()[0] 6653 except AttributeError: 6654 time.sleep(10) 6655 output = misc.mult_try_open(pjoin(self.me_dir,'SubProcesses','combine.log')).read() 6656 try: 6657 nb_event = pat.search(output).groups()[0] 6658 except AttributeError: 6659 logger.warning('Fail to read the number of unweighted events in the combine.log file') 6660 nb_event = 0 6661 self.results.add_detail('nb_event', nb_event) 6662 6663 # Define The Banner 6664 tag = self.run_card['run_tag'] 6665 6666 # Update the banner with the pythia card 6667 if not self.banner: 6668 self.banner = banner_mod.recover_banner(self.results, 'parton') 6669 self.banner.load_basic(self.me_dir) 6670 # Add cross-section/event information 6671 self.banner.add_generation_info(self.results.current['cross'], nb_event) 6672 if not hasattr(self, 'random_orig'): self.random_orig = 0 6673 self.banner.change_seed(self.random_orig) 6674 if not os.path.exists(pjoin(self.me_dir, 'Events', self.run_name)): 6675 os.mkdir(pjoin(self.me_dir, 'Events', self.run_name)) 6676 self.banner.write(pjoin(self.me_dir, 'Events', self.run_name, 6677 '%s_%s_banner.txt' % (self.run_name, tag))) 6678 6679 6680 self.banner.add_to_file(pjoin(self.me_dir,'Events', 'events.lhe'), 6681 out=pjoin(self.me_dir,'Events', self.run_name, 'events.lhe')) 6682 self.banner.add_to_file(pjoin(self.me_dir,'Events', 'unweighted_events.lhe'), 6683 out=pjoin(self.me_dir,'Events', self.run_name, 'unweighted_events.lhe'))
6684
6685 6686 -class MadLoopInitializer(object):
6687 """ A container class for the various methods for initializing MadLoop. It is 6688 placed in MadEventInterface because it is used by Madevent for loop-induced 6689 simulations. """ 6690 6691 @staticmethod
6692 - def make_and_run(dir_name,checkRam=False):
6693 """ Compile the check program in the directory dir_name. 6694 Return the compilation and running time. """ 6695 6696 # Make sure to recreate the executable and modified source 6697 # (The time stamps are sometimes not actualized if it is too fast) 6698 if os.path.isfile(pjoin(dir_name,'check')): 6699 os.remove(pjoin(dir_name,'check')) 6700 os.remove(pjoin(dir_name,'check_sa.o')) 6701 os.remove(pjoin(dir_name,'loop_matrix.o')) 6702 # Now run make 6703 devnull = open(os.devnull, 'w') 6704 start=time.time() 6705 retcode = misc.compile(arg=['-j1','check'], cwd=dir_name, nb_core=1) 6706 compilation_time = time.time()-start 6707 if retcode != 0: 6708 logging.info("Error while executing make in %s" % dir_name) 6709 return None, None, None 6710 6711 if not checkRam: 6712 start=time.time() 6713 retcode = subprocess.call('./check', 6714 cwd=dir_name, stdout=devnull, stderr=devnull) 6715 6716 run_time = time.time()-start 6717 ram_usage = None 6718 else: 6719 ptimer = misc.ProcessTimer(['./check'], cwd=dir_name, shell=False, \ 6720 stdout=devnull, stderr=devnull, close_fds=True) 6721 try: 6722 ptimer.execute() 6723 #poll as often as possible; otherwise the subprocess might 6724 # "sneak" in some extra memory usage while you aren't looking 6725 # Accuracy of .2 seconds is enough for the timing. 6726 while ptimer.poll(): 6727 time.sleep(.2) 6728 finally: 6729 #make sure that we don't leave the process dangling. 6730 ptimer.close() 6731 # Notice that ptimer.max_vms_memory is also available if needed. 6732 ram_usage = ptimer.max_rss_memory 6733 # Unfortunately the running time is less precise than with the 6734 # above version 6735 run_time = (ptimer.t1 - ptimer.t0) 6736 retcode = ptimer.p.returncode 6737 6738 devnull.close() 6739 6740 if retcode != 0: 6741 logging.warning("Error while executing ./check in %s" % dir_name) 6742 return None, None, None 6743 6744 return compilation_time, run_time, ram_usage
6745 6746 @staticmethod
6747 - def fix_PSPoint_in_check(dir_path, read_ps = True, npoints = 1, 6748 hel_config = -1, mu_r=0.0, split_orders=-1):
6749 """Set check_sa.f to be reading PS.input assuming a working dir dir_name. 6750 if hel_config is different than -1 then check_sa.f is configured so to 6751 evaluate only the specified helicity. 6752 If mu_r > 0.0, then the renormalization constant value will be hardcoded 6753 directly in check_sa.f, if is is 0 it will be set to Sqrt(s) and if it 6754 is < 0.0 the value in the param_card.dat is used. 6755 If the split_orders target (i.e. the target squared coupling orders for 6756 the computation) is != -1, it will be changed in check_sa.f via the 6757 subroutine CALL SET_COUPLINGORDERS_TARGET(split_orders).""" 6758 6759 file_path = dir_path 6760 if not os.path.isfile(dir_path) or \ 6761 not os.path.basename(dir_path)=='check_sa.f': 6762 file_path = pjoin(dir_path,'check_sa.f') 6763 if not os.path.isfile(file_path): 6764 directories = [d for d in misc.glob('P*_*', dir_path) \ 6765 if (re.search(r'.*P\d+_\w*$', d) and os.path.isdir(d))] 6766 if len(directories)>0: 6767 file_path = pjoin(directories[0],'check_sa.f') 6768 if not os.path.isfile(file_path): 6769 raise MadGraph5Error('Could not find the location of check_sa.f'+\ 6770 ' from the specified path %s.'%str(file_path)) 6771 6772 file = open(file_path, 'r') 6773 check_sa = file.read() 6774 file.close() 6775 6776 file = open(file_path, 'w') 6777 check_sa = re.sub(r"READPS = \S+\)","READPS = %s)"%('.TRUE.' if read_ps \ 6778 else '.FALSE.'), check_sa) 6779 check_sa = re.sub(r"NPSPOINTS = \d+","NPSPOINTS = %d"%npoints, check_sa) 6780 if hel_config != -1: 6781 check_sa = re.sub(r"SLOOPMATRIX\S+\(\S+,MATELEM,", 6782 "SLOOPMATRIXHEL_THRES(P,%d,MATELEM,"%hel_config, check_sa) 6783 else: 6784 check_sa = re.sub(r"SLOOPMATRIX\S+\(\S+,MATELEM,", 6785 "SLOOPMATRIX_THRES(P,MATELEM,",check_sa) 6786 if mu_r > 0.0: 6787 check_sa = re.sub(r"MU_R=SQRTS","MU_R=%s"%\ 6788 (("%.17e"%mu_r).replace('e','d')),check_sa) 6789 elif mu_r < 0.0: 6790 check_sa = re.sub(r"MU_R=SQRTS","",check_sa) 6791 6792 if split_orders > 0: 6793 check_sa = re.sub(r"SET_COUPLINGORDERS_TARGET\(-?\d+\)", 6794 "SET_COUPLINGORDERS_TARGET(%d)"%split_orders,check_sa) 6795 6796 file.write(check_sa) 6797 file.close()
6798 6799 @staticmethod
6800 - def run_initialization(run_dir=None, SubProc_dir=None, infos=None,\ 6801 req_files = ['HelFilter.dat','LoopFilter.dat'], 6802 attempts = [4,15]):
6803 """ Run the initialization of the process in 'run_dir' with success 6804 characterized by the creation of the files req_files in this directory. 6805 The directory containing the driving source code 'check_sa.f'. 6806 The list attempt gives the successive number of PS points the 6807 initialization should be tried with before calling it failed. 6808 Returns the number of PS points which were necessary for the init. 6809 Notice at least run_dir or SubProc_dir must be provided. 6810 A negative attempt number given in input means that quadprec will be 6811 forced for initialization.""" 6812 6813 # If the user does not want detailed info, then set the dictionary 6814 # to a dummy one. 6815 if infos is None: 6816 infos={} 6817 6818 if SubProc_dir is None and run_dir is None: 6819 raise MadGraph5Error, 'At least one of [SubProc_dir,run_dir] must'+\ 6820 ' be provided in run_initialization.' 6821 6822 # If the user does not specify where is check_sa.f, then it is assumed 6823 # to be one levels above run_dir 6824 if SubProc_dir is None: 6825 SubProc_dir = os.path.abspath(pjoin(run_dir,os.pardir)) 6826 6827 if run_dir is None: 6828 directories =[ dir for dir in misc.glob('P[0-9]*', SubProc_dir) 6829 if os.path.isdir(dir) ] 6830 if directories: 6831 run_dir = directories[0] 6832 else: 6833 raise MadGraph5Error, 'Could not find a valid running directory'+\ 6834 ' in %s.'%str(SubProc_dir) 6835 6836 # Use the presence of the file born_matrix.f to decide if it is a 6837 # loop-induced process or not. It's not crucial, but just that because 6838 # of the dynamic adjustment of the ref scale used for deciding what are 6839 # the zero contributions, more points are neeeded for loop-induced. 6840 if not os.path.isfile(pjoin(run_dir,'born_matrix.f')): 6841 if len(attempts)>=1 and attempts[0]<8: 6842 attempts[0]=8 6843 if len(attempts)>=2 and attempts[1]<25: 6844 attempts[1]=25 6845 6846 to_attempt = list(attempts) 6847 to_attempt.reverse() 6848 my_req_files = list(req_files) 6849 6850 MLCardPath = pjoin(SubProc_dir,'MadLoopParams.dat') 6851 if not os.path.isfile(MLCardPath): 6852 raise MadGraph5Error, 'Could not find MadLoopParams.dat at %s.'\ 6853 %MLCardPath 6854 else: 6855 MLCard = banner_mod.MadLoopParam(MLCardPath) 6856 MLCard_orig = banner_mod.MadLoopParam(MLCard) 6857 6858 # Make sure that LoopFilter really is needed. 6859 if not MLCard['UseLoopFilter']: 6860 try: 6861 my_req_files.remove('LoopFilter.dat') 6862 except ValueError: 6863 pass 6864 6865 if MLCard['HelicityFilterLevel']==0: 6866 try: 6867 my_req_files.remove('HelFilter.dat') 6868 except ValueError: 6869 pass 6870 6871 def need_init(): 6872 """ True if init not done yet.""" 6873 proc_prefix_file = open(pjoin(run_dir,'proc_prefix.txt'),'r') 6874 proc_prefix = proc_prefix_file.read() 6875 proc_prefix_file.close() 6876 return any([not os.path.exists(pjoin(run_dir,'MadLoop5_resources', 6877 proc_prefix+fname)) for fname in my_req_files]) or \ 6878 not os.path.isfile(pjoin(run_dir,'check')) or \ 6879 not os.access(pjoin(run_dir,'check'), os.X_OK)
6880 6881 # Check if this is a process without born by checking the presence of the 6882 # file born_matrix.f 6883 is_loop_induced = os.path.exists(pjoin(run_dir,'born_matrix.f')) 6884 6885 # For loop induced processes, always attempt quadruple precision if 6886 # double precision attempts fail and the user didn't specify himself 6887 # quadruple precision initializations attempts 6888 if not any(attempt<0 for attempt in to_attempt): 6889 to_attempt = [-attempt for attempt in to_attempt] + to_attempt 6890 use_quad_prec = 1 6891 curr_attempt = 1 6892 6893 MLCard.set('WriteOutFilters',True) 6894 6895 while to_attempt!=[] and need_init(): 6896 curr_attempt = to_attempt.pop() 6897 # if the attempt is a negative number it means we must force 6898 # quadruple precision at initialization time 6899 if curr_attempt < 0: 6900 use_quad_prec = -1 6901 # In quadruple precision we can lower the ZeroThres threshold 6902 MLCard.set('CTModeInit',4) 6903 MLCard.set('ZeroThres',1e-11) 6904 else: 6905 # Restore the default double precision intialization params 6906 MLCard.set('CTModeInit',1) 6907 MLCard.set('ZeroThres',1e-9) 6908 # Plus one because the filter are written on the next PS point after 6909 curr_attempt = abs(curr_attempt+1) 6910 MLCard.set('MaxAttempts',curr_attempt) 6911 MLCard.write(pjoin(SubProc_dir,'MadLoopParams.dat')) 6912 6913 # initialization is performed. 6914 MadLoopInitializer.fix_PSPoint_in_check(run_dir, read_ps = False, 6915 npoints = curr_attempt) 6916 compile_time, run_time, ram_usage = \ 6917 MadLoopInitializer.make_and_run(run_dir) 6918 if compile_time==None: 6919 logging.error("Failed at running the process in %s."%run_dir) 6920 attempts = None 6921 return None 6922 # Only set process_compilation time for the first compilation. 6923 if 'Process_compilation' not in infos.keys() or \ 6924 infos['Process_compilation']==None: 6925 infos['Process_compilation'] = compile_time 6926 infos['Initialization'] = run_time 6927 6928 MLCard_orig.write(pjoin(SubProc_dir,'MadLoopParams.dat')) 6929 if need_init(): 6930 return None 6931 else: 6932 return use_quad_prec*(curr_attempt-1)
6933 6934 @staticmethod
6935 - def need_MadLoopInit(proc_dir, subproc_prefix='PV'):
6936 """Checks whether the necessary filters are present or not.""" 6937 6938 def need_init(ML_resources_path, proc_prefix, r_files): 6939 """ Returns true if not all required files are present. """ 6940 return any([not os.path.exists(pjoin(ML_resources_path, 6941 proc_prefix+fname)) for fname in r_files])
6942 6943 MLCardPath = pjoin(proc_dir,'SubProcesses','MadLoopParams.dat') 6944 if not os.path.isfile(MLCardPath): 6945 raise MadGraph5Error, 'Could not find MadLoopParams.dat at %s.'\ 6946 %MLCardPath 6947 MLCard = banner_mod.MadLoopParam(MLCardPath) 6948 6949 req_files = ['HelFilter.dat','LoopFilter.dat'] 6950 # Make sure that LoopFilter really is needed. 6951 if not MLCard['UseLoopFilter']: 6952 try: 6953 req_files.remove('LoopFilter.dat') 6954 except ValueError: 6955 pass 6956 if MLCard['HelicityFilterLevel']==0: 6957 try: 6958 req_files.remove('HelFilter.dat') 6959 except ValueError: 6960 pass 6961 6962 for v_folder in glob.iglob(pjoin(proc_dir,'SubProcesses', 6963 '%s*'%subproc_prefix)): 6964 # Make sure it is a valid MadLoop directory 6965 if not os.path.isdir(v_folder) or not os.path.isfile(\ 6966 pjoin(v_folder,'loop_matrix.f')): 6967 continue 6968 proc_prefix_file = open(pjoin(v_folder,'proc_prefix.txt'),'r') 6969 proc_prefix = proc_prefix_file.read() 6970 proc_prefix_file.close() 6971 if need_init(pjoin(proc_dir,'SubProcesses','MadLoop5_resources'), 6972 proc_prefix, req_files): 6973 return True 6974 6975 return False 6976 6977 @staticmethod
6978 - def init_MadLoop(proc_dir, n_PS=None, subproc_prefix='PV', MG_options=None, 6979 interface = None):
6980 """Advanced commands: Compiles and run MadLoop on RAMBO random PS points to initilize the 6981 filters.""" 6982 6983 logger.debug('Compiling Source materials necessary for MadLoop '+ 6984 'initialization.') 6985 # Initialize all the virtuals directory, so as to generate the necessary 6986 # filters (essentially Helcity filter). 6987 # Make sure that the MadLoopCard has the loop induced settings 6988 if interface is None: 6989 misc.compile(arg=['treatCardsLoopNoInit'], cwd=pjoin(proc_dir,'Source')) 6990 else: 6991 interface.do_treatcards('all --no_MadLoopInit') 6992 6993 # First make sure that IREGI and CUTTOOLS are compiled if needed 6994 if os.path.exists(pjoin(proc_dir,'Source','CutTools')): 6995 misc.compile(arg=['libcuttools'],cwd=pjoin(proc_dir,'Source')) 6996 if os.path.exists(pjoin(proc_dir,'Source','IREGI')): 6997 misc.compile(arg=['libiregi'],cwd=pjoin(proc_dir,'Source')) 6998 # Then make sure DHELAS and MODEL are compiled 6999 misc.compile(arg=['libmodel'],cwd=pjoin(proc_dir,'Source')) 7000 misc.compile(arg=['libdhelas'],cwd=pjoin(proc_dir,'Source')) 7001 7002 # Now initialize the MadLoop outputs 7003 logger.info('Initializing MadLoop loop-induced matrix elements '+\ 7004 '(this can take some time)...') 7005 7006 # Setup parallelization 7007 if MG_options: 7008 mcore = cluster.MultiCore(**MG_options) 7009 else: 7010 mcore = cluster.onecore 7011 def run_initialization_wrapper(run_dir, infos, attempts): 7012 if attempts is None: 7013 n_PS = MadLoopInitializer.run_initialization( 7014 run_dir=run_dir, infos=infos) 7015 else: 7016 n_PS = MadLoopInitializer.run_initialization( 7017 run_dir=run_dir, infos=infos, attempts=attempts) 7018 infos['nPS'] = n_PS 7019 return 0
7020 7021 def wait_monitoring(Idle, Running, Done): 7022 if Idle+Running+Done == 0: 7023 return 7024 logger.debug('MadLoop initialization jobs: %d Idle, %d Running, %d Done'\ 7025 %(Idle, Running, Done)) 7026 7027 init_info = {} 7028 # List all virtual folders while making sure they are valid MadLoop folders 7029 VirtualFolders = [f for f in glob.iglob(pjoin(proc_dir,'SubProcesses', 7030 '%s*'%subproc_prefix)) if (os.path.isdir(f) or 7031 os.path.isfile(pjoin(f,'loop_matrix.f')))] 7032 logger.debug("Now Initializing MadLoop matrix element in %d folder%s:"%\ 7033 (len(VirtualFolders),'s' if len(VirtualFolders)>1 else '')) 7034 logger.debug(', '.join("'%s'"%os.path.basename(v_folder) for v_folder in 7035 VirtualFolders)) 7036 for v_folder in VirtualFolders: 7037 init_info[v_folder] = {} 7038 7039 # We try all multiples of n_PS from 1 to max_mult, first in DP and then 7040 # in QP before giving up, or use default values if n_PS is None. 7041 max_mult = 3 7042 if n_PS is None: 7043 # Then use the default list of number of PS points to try 7044 mcore.submit(run_initialization_wrapper, 7045 [pjoin(v_folder), init_info[v_folder], None]) 7046 else: 7047 # Use specific set of PS points 7048 mcore.submit(run_initialization_wrapper, [pjoin(v_folder), 7049 init_info[v_folder], 7050 [n_PS*multiplier for multiplier in range(1,max_mult+1)]]) 7051 7052 # Wait for all jobs to finish. 7053 mcore.wait('',wait_monitoring,update_first=wait_monitoring) 7054 for v_folder in VirtualFolders: 7055 init = init_info[v_folder] 7056 if init['nPS'] is None: 7057 raise MadGraph5Error, 'Failed the initialization of'+\ 7058 " loop-induced matrix element '%s'%s."%\ 7059 (os.path.basename(v_folder),' (using default n_PS points)' if\ 7060 n_PS is None else ' (trying with a maximum of %d PS points)'\ 7061 %(max_mult*n_PS)) 7062 if init['nPS']==0: 7063 logger.debug("Nothing to be done in '%s', all filters already "%\ 7064 os.path.basename(v_folder)+\ 7065 "present (use the '-r' option to force their recomputation)") 7066 else: 7067 logger.debug("'%s' finished using "%os.path.basename(v_folder)+ 7068 '%d PS points (%s), in %.3g(compil.) + %.3g(init.) secs.'%( 7069 abs(init['nPS']),'DP' if init['nPS']>0 else 'QP', 7070 init['Process_compilation'],init['Initialization'])) 7071 7072 logger.info('MadLoop initialization finished.') 7073 7074 AskforEditCard = common_run.AskforEditCard 7075 7076 7077 if '__main__' == __name__: 7078 # Launch the interface without any check if one code is already running. 7079 # This can ONLY run a single command !! 7080 import sys 7081 if not sys.version_info[0] == 2 or sys.version_info[1] < 6: 7082 sys.exit('MadGraph/MadEvent 5 works only with python 2.6 or later (but not python 3.X).\n'+\ 7083 'Please upgrate your version of python.') 7084 7085 import os 7086 import optparse 7087 # Get the directory of the script real path (bin) 7088 # and add it to the current PYTHONPATH 7089 root_path = os.path.dirname(os.path.dirname(os.path.realpath( __file__ ))) 7090 sys.path.insert(0, root_path)
7091 7092 - class MyOptParser(optparse.OptionParser):
7093 - class InvalidOption(Exception): pass
7094 - def error(self, msg=''):
7095 raise MyOptParser.InvalidOption(msg)
7096 # Write out nice usage message if called with -h or --help 7097 usage = "usage: %prog [options] [FILE] " 7098 parser = MyOptParser(usage=usage) 7099 parser.add_option("-l", "--logging", default='INFO', 7100 help="logging level (DEBUG|INFO|WARNING|ERROR|CRITICAL) [%default]") 7101 parser.add_option("","--web", action="store_true", default=False, dest='web', \ 7102 help='force toce to be in secure mode') 7103 parser.add_option("","--debug", action="store_true", default=False, dest='debug', \ 7104 help='force to launch debug mode') 7105 parser_error = '' 7106 done = False 7107 7108 for i in range(len(sys.argv)-1): 7109 try: 7110 (options, args) = parser.parse_args(sys.argv[1:len(sys.argv)-i]) 7111 done = True 7112 except MyOptParser.InvalidOption, error: 7113 pass 7114 else: 7115 args += sys.argv[len(sys.argv)-i:] 7116 if not done: 7117 # raise correct error: 7118 try: 7119 (options, args) = parser.parse_args() 7120 except MyOptParser.InvalidOption, error: 7121 print error 7122 sys.exit(2) 7123 7124 if len(args) == 0: 7125 args = '' 7126 7127 import subprocess 7128 import logging 7129 import logging.config 7130 # Set logging level according to the logging level given by options 7131 #logging.basicConfig(level=vars(logging)[options.logging]) 7132 import internal.coloring_logging 7133 try: 7134 if __debug__ and options.logging == 'INFO': 7135 options.logging = 'DEBUG' 7136 if options.logging.isdigit(): 7137 level = int(options.logging) 7138 else: 7139 level = eval('logging.' + options.logging) 7140 logging.config.fileConfig(os.path.join(root_path, 'internal', 'me5_logging.conf')) 7141 logging.root.setLevel(level) 7142 logging.getLogger('madgraph').setLevel(level) 7143 except: 7144 raise 7145 pass 7146 7147 # Call the cmd interface main loop 7148 try: 7149 if args: 7150 # a single command is provided 7151 if '--web' in args: 7152 i = args.index('--web') 7153 args.pop(i) 7154 cmd_line = MadEventCmd(os.path.dirname(root_path),force_run=True) 7155 else: 7156 cmd_line = MadEventCmdShell(os.path.dirname(root_path),force_run=True) 7157 if not hasattr(cmd_line, 'do_%s' % args[0]): 7158 if parser_error: 7159 print parser_error 7160 print 'and %s can not be interpreted as a valid command.' % args[0] 7161 else: 7162 print 'ERROR: %s not a valid command. Please retry' % args[0] 7163 else: 7164 cmd_line.use_rawinput = False 7165 cmd_line.run_cmd(' '.join(args)) 7166 cmd_line.run_cmd('quit') 7167 7168 except KeyboardInterrupt: 7169 print 'quit on KeyboardInterrupt' 7170 pass 7171