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