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