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 atexit 
  21  import cmath 
  22  import glob 
  23  import logging 
  24  import math 
  25  import optparse 
  26  import os 
  27  import pydoc 
  28  import random 
  29  import re 
  30  import signal 
  31  import shutil 
  32  import stat 
  33  import subprocess 
  34  import sys 
  35  import traceback 
  36  import time 
  37  import tarfile 
  38   
  39  try: 
  40      import readline 
  41      GNU_SPLITTING = ('GNU' in readline.__doc__) 
  42  except: 
  43      GNU_SPLITTING = True 
  44   
  45  root_path = os.path.split(os.path.dirname(os.path.realpath( __file__ )))[0] 
  46  root_path = os.path.split(root_path)[0] 
  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   
  58       
  59  except ImportError:  
  60      # import from madevent directory 
  61      MADEVENT = True 
  62      import internal.extended_cmd as cmd 
  63      import internal.common_run_interface as common_run 
  64      import internal.banner as banner_mod 
  65      import internal.misc as misc     
  66      from internal import InvalidCmd, MadGraph5Error, ReadWrite 
  67      import internal.files as files 
  68      import internal.gen_crossxhtml as gen_crossxhtml 
  69      import internal.gen_ximprove as gen_ximprove 
  70      import internal.save_load_object as save_load_object 
  71      import internal.cluster as cluster 
  72      import internal.check_param_card as check_param_card 
  73      import internal.sum_html as sum_html 
  74      import internal.combine_runs as combine_runs 
  75      import internal.lhe_parser as lhe_parser 
  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   
  92      import models.check_param_card as check_param_card     
  93      from madgraph import InvalidCmd, MadGraph5Error, MG5DIR, ReadWrite 
94 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_banner_run(self):
328 logger.info("syntax: banner_run Path|RUN [--run_options]") 329 logger.info("-- Reproduce a run following a given banner") 330 logger.info(" One of the following argument is require:") 331 logger.info(" Path should be the path of a valid banner.") 332 logger.info(" RUN should be the name of a run of the current directory") 333 self.run_options_help([('-f','answer all question by default'), 334 ('--name=X', 'Define the name associated with the new run')])
335
336 - def help_open(self):
337 logger.info("syntax: open FILE ") 338 logger.info("-- open a file with the appropriate editor.") 339 logger.info(' If FILE belongs to index.html, param_card.dat, run_card.dat') 340 logger.info(' the path to the last created/used directory is used') 341 logger.info(' The program used to open those files can be chosen in the') 342 logger.info(' configuration file ./input/mg5_configuration.txt')
343 344
345 - def run_options_help(self, data):
346 if data: 347 logger.info('-- local options:') 348 for name, info in data: 349 logger.info(' %s : %s' % (name, info)) 350 351 logger.info("-- session options:") 352 logger.info(" Note that those options will be kept for the current session") 353 logger.info(" --cluster : Submit to the cluster. Current cluster: %s" % self.options['cluster_type']) 354 logger.info(" --multicore : Run in multi-core configuration") 355 logger.info(" --nb_core=X : limit the number of core to use to X.")
356 357
358 - def help_generate_events(self):
359 logger.info("syntax: generate_events [run_name] [options]",) 360 logger.info("-- Launch the full chain of script for the generation of events") 361 logger.info(" Including possible plotting, shower and detector resolution.") 362 logger.info(" Those steps are performed if the related program are installed") 363 logger.info(" and if the related card are present in the Cards directory.") 364 self.run_options_help([('-f', 'Use default for all questions.'), 365 ('--laststep=', 'argument might be parton/pythia/pgs/delphes and indicate the last level to be run.'), 366 ('-M', 'in order to add MadSpin'), 367 ('-R', 'in order to add the reweighting module')])
368
369 - def help_initMadLoop(self):
370 logger.info("syntax: initMadLoop [options]",'$MG:color:GREEN') 371 logger.info( 372 """-- Command only useful when MadEvent simulates loop-induced processes. This command compiles and run 373 the MadLoop output for the matrix element computation so as to initialize the filter for analytically 374 zero helicity configurations and loop topologies. If you suspect that a change you made in the model 375 parameters can have affected these filters, this command allows you to automatically refresh them. """) 376 logger.info(" The available options are:",'$MG:color:BLUE') 377 logger.info(" -f : Bypass the edition of MadLoopParams.dat.",'$MG:color:BLUE') 378 logger.info(" -r : Refresh of the existing filters (erasing them if already present).",'$MG:color:BLUE') 379 logger.info(" --nPS=<int> : Specify how many phase-space points should be tried to set up the filters.",'$MG:color:BLUE')
380
381 - def help_add_time_of_flight(self):
382 logger.info("syntax: add_time_of_flight [run_name|path_to_file] [--threshold=]") 383 logger.info('-- Add in the lhe files the information') 384 logger.info(' of how long it takes to a particle to decay.') 385 logger.info(' threshold option allows to change the minimal value required to') 386 logger.info(' a non zero value for the particle (default:1e-12s)')
387
389 390 if self.ninitial != 1: 391 logger.warning("This command is only valid for processes of type A > B C.") 392 logger.warning("This command can not be run in current context.") 393 logger.warning("") 394 395 logger.info("syntax: calculate_decay_widths [run_name] [options])") 396 logger.info("-- Calculate decay widths and enter widths and BRs in param_card") 397 logger.info(" for a series of processes of type A > B C ...") 398 self.run_options_help([('-f', 'Use default for all questions.'), 399 ('--accuracy=', 'accuracy (for each partial decay width).'\ 400 + ' Default is 0.01.')])
401
402 - def help_multi_run(self):
403 logger.info("syntax: multi_run NB_RUN [run_name] [--run_options])") 404 logger.info("-- Launch the full chain of script for the generation of events") 405 logger.info(" NB_RUN times. This chains includes possible plotting, shower") 406 logger.info(" and detector resolution.") 407 self.run_options_help([('-f', 'Use default for all questions.'), 408 ('--laststep=', 'argument might be parton/pythia/pgs/delphes and indicate the last level to be run.')])
409
410 - def help_survey(self):
411 logger.info("syntax: survey [run_name] [--run_options])") 412 logger.info("-- evaluate the different channel associate to the process") 413 self.run_options_help([("--" + key,value[-1]) for (key,value) in \ 414 self._survey_options.items()])
415
416 - def help_launch(self):
417 """exec generate_events for 2>N and calculate_width for 1>N""" 418 logger.info("syntax: launch [run_name] [options])") 419 logger.info(" --alias for either generate_events/calculate_decay_widths") 420 logger.info(" depending of the number of particles in the initial state.") 421 422 if self.ninitial == 1: 423 logger.info("For this directory this is equivalent to calculate_decay_widths") 424 self.help_calculate_decay_widths() 425 else: 426 logger.info("For this directory this is equivalent to $generate_events") 427 self.help_generate_events()
428
429 - def help_refine(self):
430 logger.info("syntax: refine require_precision [max_channel] [--run_options]") 431 logger.info("-- refine the LAST run to achieve a given precision.") 432 logger.info(" require_precision: can be either the targeted number of events") 433 logger.info(' or the required relative error') 434 logger.info(' max_channel:[5] maximal number of channel per job') 435 self.run_options_help([])
436
437 - def help_combine_events(self):
438 """ """ 439 logger.info("syntax: combine_events [run_name] [--tag=tag_name] [--run_options]") 440 logger.info("-- Combine the last run in order to write the number of events") 441 logger.info(" asked in the run_card.") 442 self.run_options_help([])
443
444 - def help_store_events(self):
445 """ """ 446 logger.info("syntax: store_events [--run_options]") 447 logger.info("-- Write physically the events in the files.") 448 logger.info(" should be launch after \'combine_events\'") 449 self.run_options_help([])
450
451 - def help_create_gridpack(self):
452 """ """ 453 logger.info("syntax: create_gridpack [--run_options]") 454 logger.info("-- create the gridpack. ") 455 logger.info(" should be launch after \'store_events\'") 456 self.run_options_help([])
457
458 - def help_import(self):
459 """ """ 460 logger.info("syntax: import command PATH") 461 logger.info("-- Execute the command present in the file") 462 self.run_options_help([])
463
464 - def help_syscalc(self):
465 logger.info("syntax: syscalc [RUN] [%s] [-f | --tag=]" % '|'.join(self._plot_mode)) 466 logger.info("-- calculate systematics information for the RUN (current run by default)") 467 logger.info(" at different stages of the event generation for scale/pdf/...")
468
469 - def help_remove(self):
470 logger.info("syntax: remove RUN [all|parton|pythia|pgs|delphes|banner] [-f] [--tag=]") 471 logger.info("-- Remove all the files linked to previous run RUN") 472 logger.info(" if RUN is 'all', then all run will be cleaned.") 473 logger.info(" The optional argument precise which part should be cleaned.") 474 logger.info(" By default we clean all the related files but the banners.") 475 logger.info(" the optional '-f' allows to by-pass all security question") 476 logger.info(" The banner can be remove only if all files are removed first.")
477
478 479 480 #=============================================================================== 481 # CheckValidForCmd 482 #=============================================================================== 483 -class CheckValidForCmd(object):
484 """ The Series of check routine for the MadEventCmd""" 485
486 - def check_banner_run(self, args):
487 """check the validity of line""" 488 489 if len(args) == 0: 490 self.help_banner_run() 491 raise self.InvalidCmd('banner_run requires at least one argument.') 492 493 tag = [a[6:] for a in args if a.startswith('--tag=')] 494 495 496 if os.path.exists(args[0]): 497 type ='banner' 498 format = self.detect_card_type(args[0]) 499 if format != 'banner': 500 raise self.InvalidCmd('The file is not a valid banner.') 501 elif tag: 502 args[0] = pjoin(self.me_dir,'Events', args[0], '%s_%s_banner.txt' % \ 503 (args[0], tag)) 504 if not os.path.exists(args[0]): 505 raise self.InvalidCmd('No banner associates to this name and tag.') 506 else: 507 name = args[0] 508 type = 'run' 509 banners = misc.glob('*_banner.txt', pjoin(self.me_dir,'Events', args[0])) 510 if not banners: 511 raise self.InvalidCmd('No banner associates to this name.') 512 elif len(banners) == 1: 513 args[0] = banners[0] 514 else: 515 #list the tag and propose those to the user 516 tags = [os.path.basename(p)[len(args[0])+1:-11] for p in banners] 517 tag = self.ask('which tag do you want to use?', tags[0], tags) 518 args[0] = pjoin(self.me_dir,'Events', args[0], '%s_%s_banner.txt' % \ 519 (args[0], tag)) 520 521 run_name = [arg[7:] for arg in args if arg.startswith('--name=')] 522 if run_name: 523 try: 524 self.exec_cmd('remove %s all banner -f' % run_name) 525 except Exception: 526 pass 527 self.set_run_name(args[0], tag=None, level='parton', reload_card=True) 528 elif type == 'banner': 529 self.set_run_name(self.find_available_run_name(self.me_dir)) 530 elif type == 'run': 531 if not self.results[name].is_empty(): 532 run_name = self.find_available_run_name(self.me_dir) 533 logger.info('Run %s is not empty so will use run_name: %s' % \ 534 (name, run_name)) 535 self.set_run_name(run_name) 536 else: 537 try: 538 self.exec_cmd('remove %s all banner -f' % run_name) 539 except Exception: 540 pass 541 self.set_run_name(name)
542
543 - def check_history(self, args):
544 """check the validity of line""" 545 546 if len(args) > 1: 547 self.help_history() 548 raise self.InvalidCmd('\"history\" command takes at most one argument') 549 550 if not len(args): 551 return 552 elif args[0] != 'clean': 553 dirpath = os.path.dirname(args[0]) 554 if dirpath and not os.path.exists(dirpath) or \ 555 os.path.isdir(args[0]): 556 raise self.InvalidCmd("invalid path %s " % dirpath)
557
558 - def check_save(self, args):
559 """ check the validity of the line""" 560 561 if len(args) == 0: 562 args.append('options') 563 564 if args[0] not in self._save_opts: 565 raise self.InvalidCmd('wrong \"save\" format') 566 567 if args[0] != 'options' and len(args) != 2: 568 self.help_save() 569 raise self.InvalidCmd('wrong \"save\" format') 570 elif args[0] != 'options' and len(args) == 2: 571 basename = os.path.dirname(args[1]) 572 if not os.path.exists(basename): 573 raise self.InvalidCmd('%s is not a valid path, please retry' % \ 574 args[1]) 575 576 if args[0] == 'options': 577 has_path = None 578 for arg in args[1:]: 579 if arg in ['--auto', '--all']: 580 continue 581 elif arg.startswith('--'): 582 raise self.InvalidCmd('unknow command for \'save options\'') 583 else: 584 basename = os.path.dirname(arg) 585 if not os.path.exists(basename): 586 raise self.InvalidCmd('%s is not a valid path, please retry' % \ 587 arg) 588 elif has_path: 589 raise self.InvalidCmd('only one path is allowed') 590 else: 591 args.remove(arg) 592 args.insert(1, arg) 593 has_path = True 594 if not has_path: 595 if '--auto' in arg and self.options['mg5_path']: 596 args.insert(1, pjoin(self.options['mg5_path'],'input','mg5_configuration.txt')) 597 else: 598 args.insert(1, pjoin(self.me_dir,'Cards','me5_configuration.txt'))
599
600 - def check_set(self, args):
601 """ check the validity of the line""" 602 603 if len(args) < 2: 604 self.help_set() 605 raise self.InvalidCmd('set needs an option and an argument') 606 607 if args[0] not in self._set_options + self.options.keys(): 608 self.help_set() 609 raise self.InvalidCmd('Possible options for set are %s' % \ 610 self._set_options) 611 612 if args[0] in ['stdout_level']: 613 if args[1] not in ['DEBUG','INFO','WARNING','ERROR','CRITICAL'] \ 614 and not args[1].isdigit(): 615 raise self.InvalidCmd('output_level needs ' + \ 616 'a valid level') 617 618 if args[0] in ['timeout']: 619 if not args[1].isdigit(): 620 raise self.InvalidCmd('timeout values should be a integer')
621
622 - def check_open(self, args):
623 """ check the validity of the line """ 624 625 if len(args) != 1: 626 self.help_open() 627 raise self.InvalidCmd('OPEN command requires exactly one argument') 628 629 if args[0].startswith('./'): 630 if not os.path.isfile(args[0]): 631 raise self.InvalidCmd('%s: not such file' % args[0]) 632 return True 633 634 # if special : create the path. 635 if not self.me_dir: 636 if not os.path.isfile(args[0]): 637 self.help_open() 638 raise self.InvalidCmd('No MadEvent path defined. Unable to associate this name to a file') 639 else: 640 return True 641 642 path = self.me_dir 643 if os.path.isfile(os.path.join(path,args[0])): 644 args[0] = os.path.join(path,args[0]) 645 elif os.path.isfile(os.path.join(path,'Cards',args[0])): 646 args[0] = os.path.join(path,'Cards',args[0]) 647 elif os.path.isfile(os.path.join(path,'HTML',args[0])): 648 args[0] = os.path.join(path,'HTML',args[0]) 649 # special for card with _default define: copy the default and open it 650 elif '_card.dat' in args[0]: 651 name = args[0].replace('_card.dat','_card_default.dat') 652 if os.path.isfile(os.path.join(path,'Cards', name)): 653 files.cp(os.path.join(path,'Cards', name), os.path.join(path,'Cards', args[0])) 654 args[0] = os.path.join(path,'Cards', args[0]) 655 else: 656 raise self.InvalidCmd('No default path for this file') 657 elif not os.path.isfile(args[0]): 658 raise self.InvalidCmd('No default path for this file')
659
660 - def check_initMadLoop(self, args):
661 """ check initMadLoop command arguments are valid.""" 662 663 opt = {'refresh': False, 'nPS': None, 'force': False} 664 665 for arg in args: 666 if arg in ['-r','--refresh']: 667 opt['refresh'] = True 668 if arg in ['-f','--force']: 669 opt['force'] = True 670 elif arg.startswith('--nPS='): 671 n_attempts = arg.split('=')[1] 672 try: 673 opt['nPS'] = int(n_attempts) 674 except ValueError: 675 raise InvalidCmd("The number of attempts specified "+ 676 "'%s' is not a valid integer."%n_attempts) 677 678 return opt
679
680 - def check_treatcards(self, args):
681 """check that treatcards arguments are valid 682 [param|run|all] [--output_dir=] [--param_card=] [--run_card=] 683 """ 684 685 opt = {'output_dir':pjoin(self.me_dir,'Source'), 686 'param_card':pjoin(self.me_dir,'Cards','param_card.dat'), 687 'run_card':pjoin(self.me_dir,'Cards','run_card.dat'), 688 'forbid_MadLoopInit': False} 689 mode = 'all' 690 for arg in args: 691 if arg.startswith('--') and '=' in arg: 692 key,value =arg[2:].split('=',1) 693 if not key in opt: 694 self.help_treatcards() 695 raise self.InvalidCmd('Invalid option for treatcards command:%s ' \ 696 % key) 697 if key in ['param_card', 'run_card']: 698 if os.path.isfile(value): 699 card_name = self.detect_card_type(value) 700 if card_name != key: 701 raise self.InvalidCmd('Format for input file detected as %s while expecting %s' 702 % (card_name, key)) 703 opt[key] = value 704 elif os.path.isfile(pjoin(self.me_dir,value)): 705 card_name = self.detect_card_type(pjoin(self.me_dir,value)) 706 if card_name != key: 707 raise self.InvalidCmd('Format for input file detected as %s while expecting %s' 708 % (card_name, key)) 709 opt[key] = value 710 else: 711 raise self.InvalidCmd('No such file: %s ' % value) 712 elif key in ['output_dir']: 713 if os.path.isdir(value): 714 opt[key] = value 715 elif os.path.isdir(pjoin(self.me_dir,value)): 716 opt[key] = pjoin(self.me_dir, value) 717 else: 718 raise self.InvalidCmd('No such directory: %s' % value) 719 elif arg in ['loop','param','run','all']: 720 mode = arg 721 elif arg == '--no_MadLoopInit': 722 opt['forbid_MadLoopInit'] = True 723 else: 724 self.help_treatcards() 725 raise self.InvalidCmd('Unvalid argument %s' % arg) 726 727 return mode, opt
728 729
730 - def check_survey(self, args, cmd='survey'):
731 """check that the argument for survey are valid""" 732 733 734 self.opts = dict([(key,value[1]) for (key,value) in \ 735 self._survey_options.items()]) 736 737 # Treat any arguments starting with '--' 738 while args and args[-1].startswith('--'): 739 arg = args.pop(-1) 740 try: 741 for opt,value in self._survey_options.items(): 742 if arg.startswith('--%s=' % opt): 743 exec('self.opts[\'%s\'] = %s(arg.split(\'=\')[-1])' % \ 744 (opt, value[0])) 745 arg = "" 746 if arg != "": raise Exception 747 except Exception: 748 self.help_survey() 749 raise self.InvalidCmd('invalid %s argument'% arg) 750 751 if len(args) > 1: 752 self.help_survey() 753 raise self.InvalidCmd('Too many argument for %s command' % cmd) 754 elif not args: 755 # No run name assigned -> assigned one automaticaly 756 self.set_run_name(self.find_available_run_name(self.me_dir)) 757 else: 758 self.set_run_name(args[0], None,'parton', True) 759 args.pop(0) 760 761 return True
762
763 - def check_generate_events(self, args):
764 """check that the argument for generate_events are valid""" 765 766 run = None 767 if args and args[-1].startswith('--laststep='): 768 run = args[-1].split('=')[-1] 769 if run not in ['auto','parton', 'pythia', 'pgs', 'delphes']: 770 self.help_generate_events() 771 raise self.InvalidCmd('invalid %s argument'% args[-1]) 772 if run != 'parton' and not self.options['pythia-pgs_path']: 773 raise self.InvalidCmd('''pythia-pgs not install. Please install this package first. 774 To do so type: \'install pythia-pgs\' in the mg5 interface''') 775 if run == 'delphes' and not self.options['delphes_path']: 776 raise self.InvalidCmd('''delphes not install. Please install this package first. 777 To do so type: \'install Delphes\' in the mg5 interface''') 778 del args[-1] 779 780 781 #if len(args) > 1: 782 # self.help_generate_events() 783 # raise self.InvalidCmd('Too many argument for generate_events command: %s' % cmd) 784 785 return run
786
787 - def check_add_time_of_flight(self, args):
788 """check that the argument are correct""" 789 790 791 if len(args) >2: 792 self.help_time_of_flight() 793 raise self.InvalidCmd('Too many arguments') 794 795 # check if the threshold is define. and keep it's value 796 if args and args[-1].startswith('--threshold='): 797 try: 798 threshold = float(args[-1].split('=')[1]) 799 except ValueError: 800 raise self.InvalidCmd('threshold options require a number.') 801 args.remove(args[-1]) 802 else: 803 threshold = 1e-12 804 805 if len(args) == 1 and os.path.exists(args[0]): 806 event_path = args[0] 807 else: 808 if len(args) and self.run_name != args[0]: 809 self.set_run_name(args.pop(0)) 810 elif not self.run_name: 811 self.help_add_time_of_flight() 812 raise self.InvalidCmd('Need a run_name to process') 813 event_path = pjoin(self.me_dir, 'Events', self.run_name, 'unweighted_events.lhe.gz') 814 if not os.path.exists(event_path): 815 event_path = event_path[:-3] 816 if not os.path.exists(event_path): 817 raise self.InvalidCmd('No unweighted events associate to this run.') 818 819 820 821 #reformat the data 822 args[:] = [event_path, threshold]
823
824 - def check_calculate_decay_widths(self, args):
825 """check that the argument for calculate_decay_widths are valid""" 826 827 if self.ninitial != 1: 828 raise self.InvalidCmd('Can only calculate decay widths for decay processes A > B C ...') 829 830 accuracy = 0.01 831 run = None 832 if args and args[-1].startswith('--accuracy='): 833 try: 834 accuracy = float(args[-1].split('=')[-1]) 835 except Exception: 836 raise self.InvalidCmd('Argument error in calculate_decay_widths command') 837 del args[-1] 838 if len(args) > 1: 839 self.help_calculate_decay_widths() 840 raise self.InvalidCmd('Too many argument for calculate_decay_widths command: %s' % cmd) 841 842 return accuracy
843 844 845
846 - def check_multi_run(self, args):
847 """check that the argument for survey are valid""" 848 849 run = None 850 851 if not len(args): 852 self.help_multi_run() 853 raise self.InvalidCmd("""multi_run command requires at least one argument for 854 the number of times that it call generate_events command""") 855 856 if args[-1].startswith('--laststep='): 857 run = args[-1].split('=')[-1] 858 if run not in ['parton', 'pythia', 'pgs', 'delphes']: 859 self.help_multi_run() 860 raise self.InvalidCmd('invalid %s argument'% args[-1]) 861 if run != 'parton' and not self.options['pythia-pgs_path']: 862 raise self.InvalidCmd('''pythia-pgs not install. Please install this package first. 863 To do so type: \'install pythia-pgs\' in the mg5 interface''') 864 if run == 'delphes' and not self.options['delphes_path']: 865 raise self.InvalidCmd('''delphes not install. Please install this package first. 866 To do so type: \'install Delphes\' in the mg5 interface''') 867 del args[-1] 868 869 870 elif not args[0].isdigit(): 871 self.help_multi_run() 872 raise self.InvalidCmd("The first argument of multi_run should be a integer.") 873 #pass nb run to an integer 874 nb_run = args.pop(0) 875 args.insert(0, int(nb_run)) 876 877 878 return run
879
880 - def check_refine(self, args):
881 """check that the argument for survey are valid""" 882 883 # if last argument is not a number -> it's the run_name (Not allow anymore) 884 try: 885 float(args[-1]) 886 except ValueError: 887 self.help_refine() 888 raise self.InvalidCmd('Not valid arguments') 889 except IndexError: 890 self.help_refine() 891 raise self.InvalidCmd('require_precision argument is require for refine cmd') 892 893 894 if not self.run_name: 895 if self.results.lastrun: 896 self.set_run_name(self.results.lastrun) 897 else: 898 raise self.InvalidCmd('No run_name currently define. Unable to run refine') 899 900 if len(args) > 2: 901 self.help_refine() 902 raise self.InvalidCmd('Too many argument for refine command') 903 else: 904 try: 905 [float(arg) for arg in args] 906 except ValueError: 907 self.help_refine() 908 raise self.InvalidCmd('refine arguments are suppose to be number') 909 910 return True
911
912 - def check_combine_events(self, arg):
913 """ Check the argument for the combine events command """ 914 915 tag = [a for a in arg if a.startswith('--tag=')] 916 if tag: 917 arg.remove(tag[0]) 918 tag = tag[0][6:] 919 elif not self.run_tag: 920 tag = 'tag_1' 921 else: 922 tag = self.run_tag 923 self.run_tag = tag 924 925 if len(arg) > 1: 926 self.help_combine_events() 927 raise self.InvalidCmd('Too many argument for combine_events command') 928 929 if len(arg) == 1: 930 self.set_run_name(arg[0], self.run_tag, 'parton', True) 931 932 if not self.run_name: 933 if not self.results.lastrun: 934 raise self.InvalidCmd('No run_name currently define. Unable to run combine') 935 else: 936 self.set_run_name(self.results.lastrun) 937 938 return True
939
940 - def check_pythia(self, args):
941 """Check the argument for pythia command 942 syntax is "pythia [NAME]" 943 Note that other option are already remove at this point 944 """ 945 946 mode = None 947 laststep = [arg for arg in args if arg.startswith('--laststep=')] 948 if laststep and len(laststep)==1: 949 mode = laststep[0].split('=')[-1] 950 if mode not in ['auto', 'pythia', 'pgs', 'delphes']: 951 self.help_pythia() 952 raise self.InvalidCmd('invalid %s argument'% args[-1]) 953 elif laststep: 954 raise self.InvalidCmd('only one laststep argument is allowed') 955 956 # If not pythia-pgs path 957 if not self.options['pythia-pgs_path']: 958 logger.info('Retry to read configuration file to find pythia-pgs path') 959 self.set_configuration() 960 961 if not self.options['pythia-pgs_path'] or not \ 962 os.path.exists(pjoin(self.options['pythia-pgs_path'],'src')): 963 error_msg = 'No valid pythia-pgs path set.\n' 964 error_msg += 'Please use the set command to define the path and retry.\n' 965 error_msg += 'You can also define it in the configuration file.\n' 966 raise self.InvalidCmd(error_msg) 967 968 969 970 tag = [a for a in args if a.startswith('--tag=')] 971 if tag: 972 args.remove(tag[0]) 973 tag = tag[0][6:] 974 975 if len(args) == 0 and not self.run_name: 976 if self.results.lastrun: 977 args.insert(0, self.results.lastrun) 978 else: 979 raise self.InvalidCmd('No run name currently define. Please add this information.') 980 981 if len(args) >= 1: 982 if args[0] != self.run_name and\ 983 not os.path.exists(pjoin(self.me_dir,'Events',args[0], 'unweighted_events.lhe.gz')): 984 raise self.InvalidCmd('No events file corresponding to %s run. '% args[0]) 985 self.set_run_name(args[0], tag, 'pythia') 986 else: 987 if tag: 988 self.run_card['run_tag'] = tag 989 self.set_run_name(self.run_name, tag, 'pythia') 990 991 input_file = pjoin(self.me_dir,'Events',self.run_name, 'unweighted_events.lhe') 992 output_file = pjoin(self.me_dir, 'Events', 'unweighted_events.lhe') 993 if not os.path.exists('%s.gz' % input_file): 994 if not os.path.exists(input_file): 995 raise self.InvalidCmd('No events file corresponding to %s run. '% self.run_name) 996 files.ln(input_file, os.path.dirname(output_file)) 997 else: 998 misc.gunzip(input_file, keep=True, stdout=output_file) 999 1000 args.append(mode)
1001
1002 - def check_remove(self, args):
1003 """Check that the remove command is valid""" 1004 1005 tmp_args = args[:] 1006 1007 tag = [a[6:] for a in tmp_args if a.startswith('--tag=')] 1008 if tag: 1009 tag = tag[0] 1010 tmp_args.remove('--tag=%s' % tag) 1011 1012 1013 if len(tmp_args) == 0: 1014 self.help_remove() 1015 raise self.InvalidCmd('clean command require the name of the run to clean') 1016 elif len(tmp_args) == 1: 1017 return tmp_args[0], tag, ['all'] 1018 else: 1019 for arg in tmp_args[1:]: 1020 if arg not in self._clean_mode: 1021 self.help_remove() 1022 raise self.InvalidCmd('%s is not a valid options for clean command'\ 1023 % arg) 1024 return tmp_args[0], tag, tmp_args[1:]
1025
1026 - def check_plot(self, args):
1027 """Check the argument for the plot command 1028 plot run_name modes""" 1029 1030 madir = self.options['madanalysis_path'] 1031 td = self.options['td_path'] 1032 1033 if not madir or not td: 1034 logger.info('Retry to read configuration file to find madanalysis/td') 1035 self.set_configuration() 1036 1037 madir = self.options['madanalysis_path'] 1038 td = self.options['td_path'] 1039 1040 if not madir: 1041 error_msg = 'No valid MadAnalysis path set.\n' 1042 error_msg += 'Please use the set command to define the path and retry.\n' 1043 error_msg += 'You can also define it in the configuration file.\n' 1044 raise self.InvalidCmd(error_msg) 1045 if not td: 1046 error_msg = 'No valid td path set.\n' 1047 error_msg += 'Please use the set command to define the path and retry.\n' 1048 error_msg += 'You can also define it in the configuration file.\n' 1049 raise self.InvalidCmd(error_msg) 1050 1051 if len(args) == 0: 1052 if not hasattr(self, 'run_name') or not self.run_name: 1053 self.help_plot() 1054 raise self.InvalidCmd('No run name currently define. Please add this information.') 1055 args.append('all') 1056 return 1057 1058 1059 if args[0] not in self._plot_mode: 1060 self.set_run_name(args[0], level='plot') 1061 del args[0] 1062 if len(args) == 0: 1063 args.append('all') 1064 elif not self.run_name: 1065 self.help_plot() 1066 raise self.InvalidCmd('No run name currently define. Please add this information.') 1067 1068 for arg in args: 1069 if arg not in self._plot_mode and arg != self.run_name: 1070 self.help_plot() 1071 raise self.InvalidCmd('unknown options %s' % arg)
1072
1073 - def check_syscalc(self, args):
1074 """Check the argument for the syscalc command 1075 syscalc run_name modes""" 1076 1077 scdir = self.options['syscalc_path'] 1078 1079 if not scdir: 1080 logger.info('Retry to read configuration file to find SysCalc') 1081 self.set_configuration() 1082 1083 scdir = self.options['syscalc_path'] 1084 1085 if not scdir: 1086 error_msg = 'No valid SysCalc path set.\n' 1087 error_msg += 'Please use the set command to define the path and retry.\n' 1088 error_msg += 'You can also define it in the configuration file.\n' 1089 error_msg += 'Please note that you need to compile SysCalc first.' 1090 raise self.InvalidCmd(error_msg) 1091 1092 if len(args) == 0: 1093 if not hasattr(self, 'run_name') or not self.run_name: 1094 self.help_syscalc() 1095 raise self.InvalidCmd('No run name currently defined. Please add this information.') 1096 args.append('all') 1097 return 1098 1099 #deal options 1100 tag = [a for a in args if a.startswith('--tag=')] 1101 if tag: 1102 args.remove(tag[0]) 1103 tag = tag[0][6:] 1104 1105 if args[0] not in self._syscalc_mode: 1106 self.set_run_name(args[0], tag=tag, level='syscalc') 1107 del args[0] 1108 if len(args) == 0: 1109 args.append('all') 1110 elif not self.run_name: 1111 self.help_syscalc() 1112 raise self.InvalidCmd('No run name currently defined. Please add this information.') 1113 elif tag and tag != self.run_tag: 1114 self.set_run_name(self.run_name, tag=tag, level='syscalc') 1115 1116 for arg in args: 1117 if arg not in self._syscalc_mode and arg != self.run_name: 1118 self.help_syscalc() 1119 raise self.InvalidCmd('unknown options %s' % arg) 1120 1121 if self.run_card['use_syst'] not in self.true: 1122 raise self.InvalidCmd('Run %s does not include ' % self.run_name + \ 1123 'systematics information needed for syscalc.')
1124 1125
1126 - def check_pgs(self, arg, no_default=False):
1127 """Check the argument for pythia command 1128 syntax is "pgs [NAME]" 1129 Note that other option are already remove at this point 1130 """ 1131 1132 # If not pythia-pgs path 1133 if not self.options['pythia-pgs_path']: 1134 logger.info('Retry to read configuration file to find pythia-pgs path') 1135 self.set_configuration() 1136 1137 if not self.options['pythia-pgs_path'] or not \ 1138 os.path.exists(pjoin(self.options['pythia-pgs_path'],'src')): 1139 error_msg = 'No valid pythia-pgs path set.\n' 1140 error_msg += 'Please use the set command to define the path and retry.\n' 1141 error_msg += 'You can also define it in the configuration file.\n' 1142 raise self.InvalidCmd(error_msg) 1143 1144 tag = [a for a in arg if a.startswith('--tag=')] 1145 if tag: 1146 arg.remove(tag[0]) 1147 tag = tag[0][6:] 1148 1149 1150 if len(arg) == 0 and not self.run_name: 1151 if self.results.lastrun: 1152 arg.insert(0, self.results.lastrun) 1153 else: 1154 raise self.InvalidCmd('No run name currently define. Please add this information.') 1155 1156 if len(arg) == 1 and self.run_name == arg[0]: 1157 arg.pop(0) 1158 1159 if not len(arg) and \ 1160 not os.path.exists(pjoin(self.me_dir,'Events','pythia_events.hep')): 1161 if not no_default: 1162 self.help_pgs() 1163 raise self.InvalidCmd('''No file file pythia_events.hep currently available 1164 Please specify a valid run_name''') 1165 1166 lock = None 1167 if len(arg) == 1: 1168 prev_tag = self.set_run_name(arg[0], tag, 'pgs') 1169 if not os.path.exists(pjoin(self.me_dir,'Events',self.run_name,'%s_pythia_events.hep.gz' % prev_tag)): 1170 raise self.InvalidCmd('No events file corresponding to %s run with tag %s. '% (self.run_name, prev_tag)) 1171 else: 1172 input_file = pjoin(self.me_dir,'Events', self.run_name, '%s_pythia_events.hep.gz' % prev_tag) 1173 output_file = pjoin(self.me_dir, 'Events', 'pythia_events.hep') 1174 lock = cluster.asyncrone_launch('gunzip',stdout=open(output_file,'w'), 1175 argument=['-c', input_file]) 1176 1177 else: 1178 if tag: 1179 self.run_card['run_tag'] = tag 1180 self.set_run_name(self.run_name, tag, 'pgs') 1181 1182 return lock
1183
1184 - def check_delphes(self, arg):
1185 """Check the argument for pythia command 1186 syntax is "delphes [NAME]" 1187 Note that other option are already remove at this point 1188 """ 1189 1190 # If not pythia-pgs path 1191 if not self.options['delphes_path']: 1192 logger.info('Retry to read configuration file to find delphes path') 1193 self.set_configuration() 1194 1195 if not self.options['delphes_path']: 1196 error_msg = 'No valid Delphes path set.\n' 1197 error_msg += 'Please use the set command to define the path and retry.\n' 1198 error_msg += 'You can also define it in the configuration file.\n' 1199 raise self.InvalidCmd(error_msg) 1200 1201 tag = [a for a in arg if a.startswith('--tag=')] 1202 if tag: 1203 arg.remove(tag[0]) 1204 tag = tag[0][6:] 1205 1206 1207 if len(arg) == 0 and not self.run_name: 1208 if self.results.lastrun: 1209 arg.insert(0, self.results.lastrun) 1210 else: 1211 raise self.InvalidCmd('No run name currently define. Please add this information.') 1212 1213 if len(arg) == 1 and self.run_name == arg[0]: 1214 arg.pop(0) 1215 1216 if not len(arg) and \ 1217 not os.path.exists(pjoin(self.me_dir,'Events','pythia_events.hep')): 1218 self.help_pgs() 1219 raise self.InvalidCmd('''No file file pythia_events.hep currently available 1220 Please specify a valid run_name''') 1221 1222 lock = None 1223 if len(arg) == 1: 1224 prev_tag = self.set_run_name(arg[0], tag, 'delphes') 1225 if not os.path.exists(pjoin(self.me_dir,'Events',self.run_name, '%s_pythia_events.hep.gz' % prev_tag)): 1226 raise self.InvalidCmd('No events file corresponding to %s run with tag %s.:%s '\ 1227 % (self.run_name, prev_tag, 1228 pjoin(self.me_dir,'Events',self.run_name, '%s_pythia_events.hep.gz' % prev_tag))) 1229 else: 1230 input_file = pjoin(self.me_dir,'Events', self.run_name, '%s_pythia_events.hep.gz' % prev_tag) 1231 output_file = pjoin(self.me_dir, 'Events', 'pythia_events.hep') 1232 lock = cluster.asyncrone_launch('gunzip',stdout=open(output_file,'w'), 1233 argument=['-c', input_file]) 1234 else: 1235 if tag: 1236 self.run_card['run_tag'] = tag 1237 self.set_run_name(self.run_name, tag, 'delphes') 1238 1239 return lock
1240
1241 - def check_display(self, args):
1242 """check the validity of line 1243 syntax is "display XXXXX" 1244 """ 1245 1246 if len(args) < 1 or args[0] not in self._display_opts: 1247 self.help_display() 1248 raise self.InvalidCmd 1249 1250 if args[0] == 'variable' and len(args) !=2: 1251 raise self.InvalidCmd('variable need a variable name')
1252 1253 1254 1255 1256
1257 - def check_import(self, args):
1258 """check the validity of line""" 1259 1260 if not args: 1261 self.help_import() 1262 raise self.InvalidCmd('wrong \"import\" format') 1263 1264 if args[0] != 'command': 1265 args.insert(0,'command') 1266 1267 1268 if not len(args) == 2 or not os.path.exists(args[1]): 1269 raise self.InvalidCmd('PATH is mandatory for import command\n')
1270
1271 1272 #=============================================================================== 1273 # CompleteForCmd 1274 #=============================================================================== 1275 -class CompleteForCmd(CheckValidForCmd):
1276 """ The Series of help routine for the MadGraphCmd""" 1277 1278
1279 - def complete_add_time_of_flight(self, text, line, begidx, endidx):
1280 "Complete command" 1281 1282 args = self.split_arg(line[0:begidx], error=False) 1283 1284 if len(args) == 1: 1285 #return valid run_name 1286 data = misc.glob(pjoin('*','unweighted_events.lhe.gz'), pjoin(self.me_dir, 'Events')) 1287 data = [n.rsplit('/',2)[1] for n in data] 1288 return self.list_completion(text, data + ['--threshold='], line) 1289 elif args[-1].endswith(os.path.sep): 1290 return self.path_completion(text, 1291 os.path.join('.',*[a for a in args \ 1292 if a.endswith(os.path.sep)])) 1293 else: 1294 return self.list_completion(text, ['--threshold='], line)
1295
1296 - def complete_banner_run(self, text, line, begidx, endidx):
1297 "Complete the banner run command" 1298 try: 1299 1300 1301 args = self.split_arg(line[0:begidx], error=False) 1302 1303 if args[-1].endswith(os.path.sep): 1304 return self.path_completion(text, 1305 os.path.join('.',*[a for a in args \ 1306 if a.endswith(os.path.sep)])) 1307 1308 1309 if len(args) > 1: 1310 # only options are possible 1311 tags = misc.glob('%s_*_banner.txt' % args[1], pjoin(self.me_dir, 'Events' , args[1])) 1312 tags = ['%s' % os.path.basename(t)[len(args[1])+1:-11] for t in tags] 1313 1314 if args[-1] != '--tag=': 1315 tags = ['--tag=%s' % t for t in tags] 1316 else: 1317 return self.list_completion(text, tags) 1318 return self.list_completion(text, tags +['--name=','-f'], line) 1319 1320 # First argument 1321 possibilites = {} 1322 1323 comp = self.path_completion(text, os.path.join('.',*[a for a in args \ 1324 if a.endswith(os.path.sep)])) 1325 if os.path.sep in line: 1326 return comp 1327 else: 1328 possibilites['Path from ./'] = comp 1329 1330 run_list = misc.glob(pjoin('*','*_banner.txt'), pjoin(self.me_dir, 'Events')) 1331 run_list = [n.rsplit('/',2)[1] for n in run_list] 1332 possibilites['RUN Name'] = self.list_completion(text, run_list) 1333 1334 return self.deal_multiple_categories(possibilites) 1335 1336 1337 except Exception, error: 1338 print error
1339 1340
1341 - def complete_history(self, text, line, begidx, endidx):
1342 "Complete the history command" 1343 1344 args = self.split_arg(line[0:begidx], error=False) 1345 1346 # Directory continuation 1347 if args[-1].endswith(os.path.sep): 1348 return self.path_completion(text, 1349 os.path.join('.',*[a for a in args \ 1350 if a.endswith(os.path.sep)])) 1351 1352 if len(args) == 1: 1353 return self.path_completion(text)
1354
1355 - def complete_open(self, text, line, begidx, endidx):
1356 """ complete the open command """ 1357 1358 args = self.split_arg(line[0:begidx]) 1359 1360 # Directory continuation 1361 if os.path.sep in args[-1] + text: 1362 return self.path_completion(text, 1363 os.path.join('.',*[a for a in args if \ 1364 a.endswith(os.path.sep)])) 1365 1366 possibility = [] 1367 if self.me_dir: 1368 path = self.me_dir 1369 possibility = ['index.html'] 1370 if os.path.isfile(os.path.join(path,'README')): 1371 possibility.append('README') 1372 if os.path.isdir(os.path.join(path,'Cards')): 1373 possibility += [f for f in os.listdir(os.path.join(path,'Cards')) 1374 if f.endswith('.dat')] 1375 if os.path.isdir(os.path.join(path,'HTML')): 1376 possibility += [f for f in os.listdir(os.path.join(path,'HTML')) 1377 if f.endswith('.html') and 'default' not in f] 1378 else: 1379 possibility.extend(['./','../']) 1380 if os.path.exists('ME5_debug'): 1381 possibility.append('ME5_debug') 1382 if os.path.exists('MG5_debug'): 1383 possibility.append('MG5_debug') 1384 return self.list_completion(text, possibility)
1385
1386 - def complete_set(self, text, line, begidx, endidx):
1387 "Complete the set command" 1388 1389 args = self.split_arg(line[0:begidx]) 1390 1391 # Format 1392 if len(args) == 1: 1393 return self.list_completion(text, self._set_options + self.options.keys() ) 1394 1395 if len(args) == 2: 1396 if args[1] == 'stdout_level': 1397 return self.list_completion(text, ['DEBUG','INFO','WARNING','ERROR','CRITICAL']) 1398 else: 1399 first_set = ['None','True','False'] 1400 # directory names 1401 second_set = [name for name in self.path_completion(text, '.', only_dirs = True)] 1402 return self.list_completion(text, first_set + second_set) 1403 elif len(args) >2 and args[-1].endswith(os.path.sep): 1404 return self.path_completion(text, 1405 os.path.join('.',*[a for a in args if a.endswith(os.path.sep)]), 1406 only_dirs = True)
1407
1408 - def complete_survey(self, text, line, begidx, endidx):
1409 """ Complete the survey command """ 1410 1411 if line.endswith('nb_core=') and not text: 1412 import multiprocessing 1413 max = multiprocessing.cpu_count() 1414 return [str(i) for i in range(2,max+1)] 1415 1416 return self.list_completion(text, self._run_options, line)
1417 1418 complete_refine = complete_survey 1419 complete_combine_events = complete_survey 1420 complite_store = complete_survey 1421 complete_generate_events = complete_survey 1422 complete_create_gridpack = complete_survey 1423
1424 - def complete_generate_events(self, text, line, begidx, endidx):
1425 """ Complete the generate events""" 1426 1427 if line.endswith('nb_core=') and not text: 1428 import multiprocessing 1429 max = multiprocessing.cpu_count() 1430 return [str(i) for i in range(2,max+1)] 1431 if line.endswith('laststep=') and not text: 1432 return ['parton','pythia','pgs','delphes'] 1433 elif '--laststep=' in line.split()[-1] and line and line[-1] != ' ': 1434 return self.list_completion(text,['parton','pythia','pgs','delphes'],line) 1435 1436 opts = self._run_options + self._generate_options 1437 return self.list_completion(text, opts, line)
1438 1439
1440 - def complete_initMadLoop(self, text, line, begidx, endidx):
1441 "Complete the initMadLoop command" 1442 1443 numbers = [str(i) for i in range(10)] 1444 opts = ['-f','-r','--nPS='] 1445 1446 args = self.split_arg(line[0:begidx], error=False) 1447 if len(line) >=6 and line[begidx-6:begidx]=='--nPS=': 1448 return self.list_completion(text, numbers, line) 1449 else: 1450 return self.list_completion(text, [opt for opt in opts if not opt in 1451 line], line)
1452
1453 - def complete_launch(self, *args, **opts):
1454 1455 if self.ninitial == 1: 1456 return self.complete_calculate_decay_widths(*args, **opts) 1457 else: 1458 return self.complete_generate_events(*args, **opts)
1459
1460 - def complete_calculate_decay_widths(self, text, line, begidx, endidx):
1461 """ Complete the calculate_decay_widths command""" 1462 1463 if line.endswith('nb_core=') and not text: 1464 import multiprocessing 1465 max = multiprocessing.cpu_count() 1466 return [str(i) for i in range(2,max+1)] 1467 1468 opts = self._run_options + self._calculate_decay_options 1469 return self.list_completion(text, opts, line)
1470
1471 - def complete_display(self, text, line, begidx, endidx):
1472 """ Complete the display command""" 1473 1474 args = self.split_arg(line[0:begidx], error=False) 1475 if len(args) >= 2 and args[1] =='results': 1476 start = line.find('results') 1477 return self.complete_print_results(text, 'print_results '+line[start+7:], begidx+2+start, endidx+2+start) 1478 return super(CompleteForCmd, self).complete_display(text, line, begidx, endidx)
1479
1480 - def complete_multi_run(self, text, line, begidx, endidx):
1481 """complete multi run command""" 1482 1483 args = self.split_arg(line[0:begidx], error=False) 1484 if len(args) == 1: 1485 data = [str(i) for i in range(0,20)] 1486 return self.list_completion(text, data, line) 1487 1488 if line.endswith('run=') and not text: 1489 return ['parton','pythia','pgs','delphes'] 1490 elif '--laststep=' in line.split()[-1] and line and line[-1] != ' ': 1491 return self.list_completion(text,['parton','pythia','pgs','delphes'],line) 1492 1493 opts = self._run_options + self._generate_options 1494 return self.list_completion(text, opts, line) 1495 1496 1497 1498 if line.endswith('nb_core=') and not text: 1499 import multiprocessing 1500 max = multiprocessing.cpu_count() 1501 return [str(i) for i in range(2,max+1)] 1502 opts = self._run_options + self._generate_options 1503 return self.list_completion(text, opts, line)
1504
1505 - def complete_plot(self, text, line, begidx, endidx):
1506 """ Complete the plot command """ 1507 1508 args = self.split_arg(line[0:begidx], error=False) 1509 if len(args) > 1: 1510 return self.list_completion(text, self._plot_mode) 1511 else: 1512 return self.list_completion(text, self._plot_mode + self.results.keys())
1513
1514 - def complete_syscalc(self, text, line, begidx, endidx):
1515 """ Complete the syscalc command """ 1516 1517 output = {} 1518 args = self.split_arg(line[0:begidx], error=False) 1519 1520 if len(args) <=1: 1521 output['RUN_NAME'] = self.list_completion(self.results.keys()) 1522 output['MODE'] = self.list_completion(text, self._syscalc_mode) 1523 output['options'] = ['-f'] 1524 if len(args) > 1 and (text.startswith('--t')): 1525 run = args[1] 1526 if run in self.results: 1527 tags = ['--tag=%s' % tag['tag'] for tag in self.results[run]] 1528 output['options'] += tags 1529 1530 return self.deal_multiple_categories(output)
1531
1532 - def complete_remove(self, text, line, begidx, endidx):
1533 """Complete the remove command """ 1534 1535 args = self.split_arg(line[0:begidx], error=False) 1536 if len(args) > 1 and (text.startswith('--t')): 1537 run = args[1] 1538 tags = ['--tag=%s' % tag['tag'] for tag in self.results[run]] 1539 return self.list_completion(text, tags) 1540 elif len(args) > 1 and '--' == args[-1]: 1541 run = args[1] 1542 tags = ['tag=%s' % tag['tag'] for tag in self.results[run]] 1543 return self.list_completion(text, tags) 1544 elif len(args) > 1 and '--tag=' == args[-1]: 1545 run = args[1] 1546 tags = [tag['tag'] for tag in self.results[run]] 1547 return self.list_completion(text, tags) 1548 elif len(args) > 1: 1549 return self.list_completion(text, self._clean_mode + ['-f','--tag=']) 1550 else: 1551 data = misc.glob(pjoin('*','*_banner.txt'), pjoin(self.me_dir, 'Events')) 1552 data = [n.rsplit('/',2)[1] for n in data] 1553 return self.list_completion(text, ['all'] + data)
1554 1555
1556 - def complete_pythia(self,text, line, begidx, endidx):
1557 "Complete the pythia command" 1558 args = self.split_arg(line[0:begidx], error=False) 1559 1560 if len(args) == 1: 1561 #return valid run_name 1562 data = misc.glob(pjoin('*','unweighted_events.lhe.gz'), pjoin(self.me_dir, 'Events')) 1563 data = [n.rsplit('/',2)[1] for n in data] 1564 tmp1 = self.list_completion(text, data) 1565 if not self.run_name: 1566 return tmp1 1567 else: 1568 tmp2 = self.list_completion(text, self._run_options + ['-f', 1569 '--no_default', '--tag='], line) 1570 return tmp1 + tmp2 1571 elif line[-1] != '=': 1572 return self.list_completion(text, self._run_options + ['-f', 1573 '--no_default','--tag='], line)
1574
1575 - def complete_pgs(self,text, line, begidx, endidx):
1576 "Complete the pythia command" 1577 args = self.split_arg(line[0:begidx], error=False) 1578 if len(args) == 1: 1579 #return valid run_name 1580 data = misc.glob(pjoin('*', '*_pythia_events.hep.gz'), pjoin(self.me_dir, 'Events')) 1581 data = [n.rsplit('/',2)[1] for n in data] 1582 tmp1 = self.list_completion(text, data) 1583 if not self.run_name: 1584 return tmp1 1585 else: 1586 tmp2 = self.list_completion(text, self._run_options + ['-f', 1587 '--tag=' ,'--no_default'], line) 1588 return tmp1 + tmp2 1589 else: 1590 return self.list_completion(text, self._run_options + ['-f', 1591 '--tag=','--no_default'], line)
1592 1593 complete_delphes = complete_pgs 1594
1595 1596 1597 1598 1599 #=============================================================================== 1600 # MadEventCmd 1601 #=============================================================================== 1602 -class MadEventCmd(CompleteForCmd, CmdExtended, HelpToCmd, common_run.CommonRunCmd):
1603 1604 """The command line processor of MadGraph""" 1605 1606 # Truth values 1607 true = ['T','.true.',True,'true'] 1608 # Options and formats available 1609 _run_options = ['--cluster','--multicore','--nb_core=','--nb_core=2', '-c', '-m'] 1610 _generate_options = ['-f', '--laststep=parton', '--laststep=pythia', '--laststep=pgs', '--laststep=delphes'] 1611 _calculate_decay_options = ['-f', '--accuracy=0.'] 1612 _set_options = ['stdout_level','fortran_compiler','timeout'] 1613 _plot_mode = ['all', 'parton','pythia','pgs','delphes','channel', 'banner'] 1614 _syscalc_mode = ['all', 'parton','pythia'] 1615 _clean_mode = _plot_mode 1616 _display_opts = ['run_name', 'options', 'variable', 'results'] 1617 _save_opts = ['options'] 1618 _initMadLoop_opts = ['-f','-r','--nPS='] 1619 # survey options, dict from name to type, default value, and help text 1620 _survey_options = {'points':('int', 1000,'Number of points for first iteration'), 1621 'iterations':('int', 5, 'Number of iterations'), 1622 'accuracy':('float', 0.1, 'Required accuracy'), 1623 'gridpack':('str', '.false.', 'Gridpack generation')} 1624 # Variables to store object information 1625 true = ['T','.true.',True,'true', 1, '1'] 1626 web = False 1627 cluster_mode = 0 1628 queue = 'madgraph' 1629 nb_core = None 1630 1631 next_possibility = { 1632 'start': ['generate_events [OPTIONS]', 'multi_run [OPTIONS]', 1633 'calculate_decay_widths [OPTIONS]', 1634 'help generate_events'], 1635 'generate_events': ['generate_events [OPTIONS]', 'multi_run [OPTIONS]', 'pythia', 'pgs','delphes'], 1636 'calculate_decay_widths': ['calculate_decay_widths [OPTIONS]', 1637 'generate_events [OPTIONS]'], 1638 'multi_run': ['generate_events [OPTIONS]', 'multi_run [OPTIONS]'], 1639 'survey': ['refine'], 1640 'refine': ['combine_events'], 1641 'combine_events': ['store'], 1642 'store': ['pythia'], 1643 'pythia': ['pgs', 'delphes'], 1644 'pgs': ['generate_events [OPTIONS]', 'multi_run [OPTIONS]'], 1645 'delphes' : ['generate_events [OPTIONS]', 'multi_run [OPTIONS]'] 1646 } 1647 1648 ############################################################################
1649 - def __init__(self, me_dir = None, options={}, *completekey, **stdin):
1650 """ add information to the cmd """ 1651 1652 CmdExtended.__init__(self, me_dir, options, *completekey, **stdin) 1653 #common_run.CommonRunCmd.__init__(self, me_dir, options) 1654 1655 self.mode = 'madevent' 1656 self.nb_refine=0 1657 if self.web: 1658 os.system('touch %s' % pjoin(self.me_dir,'Online')) 1659 1660 self.load_results_db() 1661 self.results.def_web_mode(self.web) 1662 1663 self.prompt = "%s>"%os.path.basename(pjoin(self.me_dir)) 1664 self.configured = 0 # time for reading the card 1665 self._options = {} # for compatibility with extended_cmd
1666 1667
1668 - def pass_in_web_mode(self):
1669 """configure web data""" 1670 self.web = True 1671 self.results.def_web_mode(True) 1672 self.force = True 1673 if os.environ['MADGRAPH_BASE']: 1674 self.options['mg5_path'] = pjoin(os.environ['MADGRAPH_BASE'],'MG5')
1675 1676 ############################################################################
1677 - def check_output_type(self, path):
1678 """ Check that the output path is a valid madevent directory """ 1679 1680 bin_path = os.path.join(path,'bin') 1681 if os.path.isfile(os.path.join(bin_path,'generate_events')): 1682 return True 1683 else: 1684 return False
1685 1686 ############################################################################
1687 - def set_configuration(self, amcatnlo=False, final=True, **opt):
1688 """assign all configuration variable from file 1689 loop over the different config file if config_file not define """ 1690 1691 super(MadEventCmd,self).set_configuration(amcatnlo=amcatnlo, 1692 final=final, **opt) 1693 1694 if not final: 1695 return self.options # the return is usefull for unittest 1696 1697 1698 # Treat each expected input 1699 # delphes/pythia/... path 1700 # ONLY the ONE LINKED TO Madevent ONLY!!! 1701 for key in (k for k in self.options if k.endswith('path')): 1702 path = self.options[key] 1703 if path is None or key.startswith("cluster"): 1704 continue 1705 if not os.path.isdir(path): 1706 path = pjoin(self.me_dir, self.options[key]) 1707 if os.path.isdir(path): 1708 self.options[key] = None 1709 if key == "pythia-pgs_path": 1710 if not os.path.exists(pjoin(path, 'src','pythia')): 1711 logger.info("No valid pythia-pgs path found") 1712 continue 1713 elif key == "delphes_path": 1714 if not os.path.exists(pjoin(path, 'Delphes')) and not\ 1715 os.path.exists(pjoin(path, 'DelphesSTDHEP')): 1716 logger.info("No valid Delphes path found") 1717 continue 1718 elif key == "madanalysis_path": 1719 if not os.path.exists(pjoin(path, 'plot_events')): 1720 logger.info("No valid MadAnalysis path found") 1721 continue 1722 elif key == "td_path": 1723 if not os.path.exists(pjoin(path, 'td')): 1724 logger.info("No valid td path found") 1725 continue 1726 elif key == "syscalc_path": 1727 if not os.path.exists(pjoin(path, 'sys_calc')): 1728 logger.info("No valid SysCalc path found") 1729 continue 1730 # No else since the next line reinitialize the option to the 1731 #previous value anyway 1732 self.options[key] = os.path.realpath(path) 1733 continue 1734 else: 1735 self.options[key] = None 1736 1737 1738 return self.options
1739 1740 ############################################################################
1741 - def do_add_time_of_flight(self, line):
1742 1743 args = self.split_arg(line) 1744 #check the validity of the arguments and reformat args 1745 self.check_add_time_of_flight(args) 1746 1747 event_path, threshold = args 1748 #gunzip the file 1749 if event_path.endswith('.gz'): 1750 need_zip = True 1751 misc.gunzip(event_path) 1752 event_path = event_path[:-3] 1753 else: 1754 need_zip = False 1755 1756 import random 1757 try: 1758 import madgraph.various.lhe_parser as lhe_parser 1759 except: 1760 import internal.lhe_parser as lhe_parser 1761 1762 logger.info('Add time of flight information on file %s' % event_path) 1763 lhe = lhe_parser.EventFile(event_path) 1764 output = open('%s_2vertex.lhe' % event_path, 'w') 1765 #write the banner to the output file 1766 output.write(lhe.banner) 1767 1768 # get the associate param_card 1769 begin_param = lhe.banner.find('<slha>') 1770 end_param = lhe.banner.find('</slha>') 1771 param_card = lhe.banner[begin_param+6:end_param].split('\n') 1772 param_card = check_param_card.ParamCard(param_card) 1773 1774 cst = 6.58211915e-25 # hbar in GeV s 1775 c = 299792458000 # speed of light in mm/s 1776 # Loop over all events 1777 for event in lhe: 1778 for particle in event: 1779 id = particle.pid 1780 width = param_card['decay'].get((abs(id),)).value 1781 if width: 1782 vtim = c * random.expovariate(width/cst) 1783 if vtim > threshold: 1784 particle.vtim = vtim 1785 #write this modify event 1786 output.write(str(event)) 1787 output.write('</LesHouchesEvents>\n') 1788 output.close() 1789 1790 files.mv('%s_2vertex.lhe' % event_path, event_path) 1791 1792 if need_zip: 1793 misc.gzip(event_path)
1794 1795 ############################################################################
1796 - def do_banner_run(self, line):
1797 """Make a run from the banner file""" 1798 1799 args = self.split_arg(line) 1800 #check the validity of the arguments 1801 self.check_banner_run(args) 1802 1803 # Remove previous cards 1804 for name in ['delphes_trigger.dat', 'delphes_card.dat', 1805 'pgs_card.dat', 'pythia_card.dat', 'madspin_card.dat', 1806 'reweight_card.dat']: 1807 try: 1808 os.remove(pjoin(self.me_dir, 'Cards', name)) 1809 except Exception: 1810 pass 1811 1812 banner_mod.split_banner(args[0], self.me_dir, proc_card=False) 1813 1814 # Check if we want to modify the run 1815 if not self.force: 1816 ans = self.ask('Do you want to modify the Cards?', 'n', ['y','n']) 1817 if ans == 'n': 1818 self.force = True 1819 1820 # Call Generate events 1821 self.exec_cmd('generate_events %s %s' % (self.run_name, self.force and '-f' or ''))
1822 1823 1824 1825 ############################################################################
1826 - def do_display(self, line, output=sys.stdout):
1827 """Display current internal status""" 1828 1829 args = self.split_arg(line) 1830 #check the validity of the arguments 1831 self.check_display(args) 1832 1833 if args[0] == 'run_name': 1834 #return valid run_name 1835 data = misc.glob(pjoin('*','*_banner.txt'), pjoin(self.me_dir, 'Events')) 1836 data = [n.rsplit('/',2)[1:] for n in data] 1837 1838 if data: 1839 out = {} 1840 for name, tag in data: 1841 tag = tag[len(name)+1:-11] 1842 if name in out: 1843 out[name].append(tag) 1844 else: 1845 out[name] = [tag] 1846 print 'the runs available are:' 1847 for run_name, tags in out.items(): 1848 print ' run: %s' % run_name 1849 print ' tags: ', 1850 print ', '.join(tags) 1851 else: 1852 print 'No run detected.' 1853 1854 elif args[0] == 'options': 1855 outstr = " Run Options \n" 1856 outstr += " ----------- \n" 1857 for key, default in self.options_madgraph.items(): 1858 value = self.options[key] 1859 if value == default: 1860 outstr += " %25s \t:\t%s\n" % (key,value) 1861 else: 1862 outstr += " %25s \t:\t%s (user set)\n" % (key,value) 1863 outstr += "\n" 1864 outstr += " MadEvent Options \n" 1865 outstr += " ---------------- \n" 1866 for key, default in self.options_madevent.items(): 1867 if key in self.options: 1868 value = self.options[key] 1869 else: 1870 default = '' 1871 if value == default: 1872 outstr += " %25s \t:\t%s\n" % (key,value) 1873 else: 1874 outstr += " %25s \t:\t%s (user set)\n" % (key,value) 1875 outstr += "\n" 1876 outstr += " Configuration Options \n" 1877 outstr += " --------------------- \n" 1878 for key, default in self.options_configuration.items(): 1879 value = self.options[key] 1880 if value == default: 1881 outstr += " %25s \t:\t%s\n" % (key,value) 1882 else: 1883 outstr += " %25s \t:\t%s (user set)\n" % (key,value) 1884 output.write(outstr) 1885 elif args[0] == 'results': 1886 self.do_print_results(' '.join(args[1:])) 1887 else: 1888 super(MadEventCmd, self).do_display(line, output)
1889
1890 - def do_save(self, line, check=True, to_keep={}):
1891 """Not in help: Save information to file""" 1892 1893 args = self.split_arg(line) 1894 # Check argument validity 1895 if check: 1896 self.check_save(args) 1897 1898 if args[0] == 'options': 1899 # First look at options which should be put in MG5DIR/input 1900 to_define = {} 1901 for key, default in self.options_configuration.items(): 1902 if self.options[key] != self.options_configuration[key]: 1903 to_define[key] = self.options[key] 1904 1905 if not '--auto' in args: 1906 for key, default in self.options_madevent.items(): 1907 if self.options[key] != self.options_madevent[key]: 1908 to_define[key] = self.options[key] 1909 1910 if '--all' in args: 1911 for key, default in self.options_madgraph.items(): 1912 if self.options[key] != self.options_madgraph[key]: 1913 to_define[key] = self.options[key] 1914 elif not '--auto' in args: 1915 for key, default in self.options_madgraph.items(): 1916 if self.options[key] != self.options_madgraph[key]: 1917 logger.info('The option %s is modified [%s] but will not be written in the configuration files.' \ 1918 % (key,self.options_madgraph[key]) ) 1919 logger.info('If you want to make this value the default for future session, you can run \'save options --all\'') 1920 if len(args) >1 and not args[1].startswith('--'): 1921 filepath = args[1] 1922 else: 1923 filepath = pjoin(self.me_dir, 'Cards', 'me5_configuration.txt') 1924 basefile = pjoin(self.me_dir, 'Cards', 'me5_configuration.txt') 1925 basedir = self.me_dir 1926 1927 if to_keep: 1928 to_define = to_keep 1929 self.write_configuration(filepath, basefile, basedir, to_define)
1930 1931 1932 1933
1934 - def do_edit_cards(self, line):
1935 """Advanced commands: Basic edition of the cards""" 1936 args = self.split_arg(line) 1937 # Check argument's validity 1938 mode = self.check_generate_events(args) 1939 self.ask_run_configuration(mode) 1940 1941 return
1942 1943 ############################################################################ 1944 1945 ############################################################################
1946 - def do_generate_events(self, line):
1947 """Main Commands: launch the full chain """ 1948 1949 self.banner = None 1950 args = self.split_arg(line) 1951 # Check argument's validity 1952 mode = self.check_generate_events(args) 1953 self.ask_run_configuration(mode, args) 1954 if not args: 1955 # No run name assigned -> assigned one automaticaly 1956 self.set_run_name(self.find_available_run_name(self.me_dir), None, 'parton') 1957 else: 1958 self.set_run_name(args[0], None, 'parton', True) 1959 args.pop(0) 1960 1961 if self.proc_characteristics['loop_induced'] and self.options['run_mode']==0: 1962 # Also the single core mode is not supported for loop-induced. 1963 # We therefore emulate it with multi-core mode with one core 1964 logger.warning( 1965 """Single-core mode not supported for loop-induced processes. 1966 Beware that MG5aMC now changes your runtime options to a multi-core mode with only one active core.""") 1967 self.do_set('run_mode 2') 1968 self.do_set('nb_core 1') 1969 1970 if self.run_card['gridpack'] in self.true: 1971 # Running gridpack warmup 1972 gridpack_opts=[('accuracy', 0.01), 1973 ('points', 2000), 1974 ('iterations',8), 1975 ('gridpack','.true.')] 1976 logger.info('Generating gridpack with run name %s' % self.run_name) 1977 self.exec_cmd('survey %s %s' % \ 1978 (self.run_name, 1979 " ".join(['--' + opt + '=' + str(val) for (opt,val) \ 1980 in gridpack_opts])), 1981 postcmd=False) 1982 self.exec_cmd('combine_events', postcmd=False) 1983 self.exec_cmd('store_events', postcmd=False) 1984 self.exec_cmd('decay_events -from_cards', postcmd=False) 1985 self.exec_cmd('create_gridpack', postcmd=False) 1986 else: 1987 # Regular run mode 1988 logger.info('Generating %s events with run name %s' % 1989 (self.run_card['nevents'], self.run_name)) 1990 1991 self.exec_cmd('survey %s %s' % (self.run_name,' '.join(args)), 1992 postcmd=False) 1993 nb_event = self.run_card['nevents'] 1994 bypass_run=False 1995 self.exec_cmd('refine %s' % nb_event, postcmd=False) 1996 if not float(self.results.current['cross']): 1997 # Zero cross-section. Try to guess why 1998 text = '''Survey return zero cross section. 1999 Typical reasons are the following: 2000 1) A massive s-channel particle has a width set to zero. 2001 2) The pdf are zero for at least one of the initial state particles 2002 or you are using maxjetflavor=4 for initial state b:s. 2003 3) The cuts are too strong. 2004 Please check/correct your param_card and/or your run_card.''' 2005 logger_stderr.critical(text) 2006 if not self.param_card_iterator: 2007 raise ZeroResult('See https://cp3.irmp.ucl.ac.be/projects/madgraph/wiki/FAQ-General-14') 2008 else: 2009 bypass_run = True 2010 2011 #we can bypass the following if scan and first result is zero 2012 if not bypass_run: 2013 self.exec_cmd('refine %s' % nb_event, postcmd=False) 2014 2015 self.exec_cmd('combine_events', postcmd=False) 2016 self.print_results_in_shell(self.results.current) 2017 2018 2019 self.run_syscalc('parton') 2020 self.create_plot('parton') 2021 self.exec_cmd('store_events', postcmd=False) 2022 self.exec_cmd('reweight -from_cards', postcmd=False) 2023 self.exec_cmd('decay_events -from_cards', postcmd=False) 2024 if self.run_card['time_of_flight']>=0: 2025 self.exec_cmd("add_time_of_flight --threshold=%s" % self.run_card['time_of_flight'] ,postcmd=False) 2026 self.exec_cmd('pythia --no_default', postcmd=False, printcmd=False) 2027 # pythia launches pgs/delphes if needed 2028 self.store_result() 2029 2030 if self.param_card_iterator: 2031 param_card_iterator = self.param_card_iterator 2032 self.param_card_iterator = [] 2033 with misc.TMP_variable(self, 'allow_notification_center', False): 2034 param_card_iterator.store_entry(self.run_name, self.results.current['cross']) 2035 #check if the param_card defines a scan. 2036 orig_name = self.run_name 2037 for card in param_card_iterator: 2038 card.write(pjoin(self.me_dir,'Cards','param_card.dat')) 2039 next_name = param_card_iterator.get_next_name(self.run_name) 2040 try: 2041 self.exec_cmd("generate_events -f %s" % next_name, 2042 precmd=True, postcmd=True,errorhandling=False) 2043 except ZeroResult: 2044 param_card_iterator.store_entry(self.run_name, 0) 2045 else: 2046 param_card_iterator.store_entry(self.run_name, self.results.current['cross']) 2047 param_card_iterator.write(pjoin(self.me_dir,'Cards','param_card.dat')) 2048 name = misc.get_scan_name(orig_name, self.run_name) 2049 path = pjoin(self.me_dir, 'Events','scan_%s.txt' % name) 2050 logger.info("write all cross-section results in %s" % path ,'$MG:color:BLACK') 2051 param_card_iterator.write_summary(path) 2052 2053 2054 if self.allow_notification_center: 2055 misc.apple_notify('Run %s finished' % os.path.basename(self.me_dir), 2056 '%s: %s +- %s ' % (self.results.current['run_name'], 2057 self.results.current['cross'], 2058 self.results.current['error']))
2059
2060 - def do_initMadLoop(self,line):
2061 """Compile and run MadLoop for a certain number of PS point so as to 2062 initialize MadLoop (setup the zero helicity and loop filter.)""" 2063 2064 args = line.split() 2065 # Check argument's validity 2066 options = self.check_initMadLoop(args) 2067 2068 if not options['force']: 2069 self.ask_edit_cards(['MadLoopParams.dat'], mode='fixed', plot=False) 2070 self.exec_cmd('treatcards loop --no_MadLoopInit') 2071 2072 if options['refresh']: 2073 for filter in misc.glob('*Filter*', 2074 pjoin(self.me_dir,'SubProcesses','MadLoop5_resources')): 2075 logger.debug("Resetting filter '%s'."%os.path.basename(filter)) 2076 os.remove(filter) 2077 2078 MLCard = banner_mod.MadLoopParam(pjoin(self.me_dir, 2079 'Cards','MadLoopParams.dat')) 2080 if options['nPS'] is None: 2081 options['nPS'] = MLCard['CheckCycle']+2 2082 elif options['nPS'] < MLCard['CheckCycle']+2: 2083 new_n_PS = MLCard['CheckCycle']+2 2084 logger.debug('Hard-setting user-defined n_PS (%d) to %d, because '\ 2085 %(options['nPS'],new_n_PS)+"of the 'CheckCycle' value (%d) "%MLCard['CheckCycle']+\ 2086 "specified in the ML param card.") 2087 options['nPS'] = new_n_PS 2088 2089 MadLoopInitializer.init_MadLoop(self.me_dir,n_PS=options['nPS'], 2090 subproc_prefix='PV', MG_options=self.options, interface=self)
2091
2092 - def do_launch(self, line, *args, **opt):
2093 """Main Commands: exec generate_events for 2>N and calculate_width for 1>N""" 2094 if self.ninitial == 1: 2095 logger.info("Note that since 2.3. The launch for 1>N pass in event generation\n"+ 2096 " To have the previous behavior use the calculate_decay_widths function") 2097 self.do_calculate_decay_widths(line, *args, **opt) 2098 else: 2099 self.do_generate_events(line, *args, **opt)
2100
2101 - def print_results_in_shell(self, data):
2102 """Have a nice results prints in the shell, 2103 data should be of type: gen_crossxhtml.OneTagResults""" 2104 2105 if not data: 2106 return 2107 2108 if data['run_statistics']: 2109 globalstat = sum_html.RunStatistics() 2110 2111 logger.info(" " ) 2112 logger.debug(" === Run statistics summary ===") 2113 for key, value in data['run_statistics'].items(): 2114 globalstat.aggregate_statistics(value) 2115 level = 5 2116 if value.has_warning(): 2117 level = 10 2118 logger.log(level, value.nice_output(str('/'.join([key[0],'G%s'%key[1]]))).\ 2119 replace(' statistics','')) 2120 logger.info(" " ) 2121 logger.debug(globalstat.nice_output('combined', no_warning=True)) 2122 if globalstat.has_warning(): 2123 logger.warning(globalstat.get_warning_text()) 2124 logger.info(" ") 2125 2126 2127 logger.info(" === Results Summary for run: %s tag: %s ===\n" % (data['run_name'],data['tag'])) 2128 2129 total_time = int(sum(_['cumulative_timing'] for _ in data['run_statistics'].values())) 2130 if total_time > 0: 2131 logger.info(" Cumulative sequential time for this run: %s"%misc.format_time(total_time)) 2132 2133 if self.ninitial == 1: 2134 logger.info(" Width : %.4g +- %.4g GeV" % (data['cross'], data['error'])) 2135 else: 2136 logger.info(" Cross-section : %.4g +- %.4g pb" % (data['cross'], data['error'])) 2137 logger.info(" Nb of events : %s" % data['nb_event'] ) 2138 if data['cross_pythia'] and data['nb_event_pythia']: 2139 if self.ninitial == 1: 2140 logger.info(" Matched Width : %.4g +- %.4g GeV" % (data['cross_pythia'], data['error_pythia'])) 2141 else: 2142 logger.info(" Matched Cross-section : %.4g +- %.4g pb" % (data['cross_pythia'], data['error_pythia'])) 2143 logger.info(" Nb of events after Matching : %s" % data['nb_event_pythia']) 2144 if self.run_card['use_syst'] in self.true: 2145 logger.info(" Be carefull that matched information are here NOT for the central value. Refer to SysCalc output for it") 2146 2147 logger.info(" " )
2148
2149 - def print_results_in_file(self, data, path, mode='w', format='full'):
2150 """Have a nice results prints in the shell, 2151 data should be of type: gen_crossxhtml.OneTagResults""" 2152 if not data: 2153 return 2154 2155 fsock = open(path, mode) 2156 2157 if data['run_statistics']: 2158 logger.debug(" === Run statistics summary ===") 2159 for key, value in data['run_statistics'].items(): 2160 logger.debug(value.nice_output(str('/'.join([key[0],'G%s'%key[1]]))).\ 2161 replace(' statistics','')) 2162 logger.info(" " ) 2163 2164 if format == "full": 2165 fsock.write(" === Results Summary for run: %s tag: %s process: %s ===\n" % \ 2166 (data['run_name'],data['tag'], os.path.basename(self.me_dir))) 2167 2168 if self.ninitial == 1: 2169 fsock.write(" Width : %.4g +- %.4g GeV\n" % (data['cross'], data['error'])) 2170 else: 2171 fsock.write(" Cross-section : %.4g +- %.4g pb\n" % (data['cross'], data['error'])) 2172 fsock.write(" Nb of events : %s\n" % data['nb_event'] ) 2173 if data['cross_pythia'] and data['nb_event_pythia']: 2174 if self.ninitial == 1: 2175 fsock.write(" Matched Width : %.4g +- %.4g GeV\n" % (data['cross_pythia'], data['error_pythia'])) 2176 else: 2177 fsock.write(" Matched Cross-section : %.4g +- %.4g pb\n" % (data['cross_pythia'], data['error_pythia'])) 2178 fsock.write(" Nb of events after Matching : %s\n" % data['nb_event_pythia']) 2179 fsock.write(" \n" ) 2180 elif format == "short": 2181 if mode == "w": 2182 fsock.write("# run_name tag cross error Nb_event cross_after_matching nb_event_after matching\n") 2183 2184 if data['cross_pythia'] and data['nb_event_pythia']: 2185 text = "%(run_name)s %(tag)s %(cross)s %(error)s %(nb_event)s %(cross_pythia)s %(nb_event_pythia)s\n" 2186 else: 2187 text = "%(run_name)s %(tag)s %(cross)s %(error)s %(nb_event)s\n" 2188 fsock.write(text % data)
2189 2190 ############################################################################
2191 - def do_calculate_decay_widths(self, line):
2192 """Main Commands: launch decay width calculation and automatic inclusion of 2193 calculated widths and BRs in the param_card.""" 2194 2195 args = self.split_arg(line) 2196 # Check argument's validity 2197 accuracy = self.check_calculate_decay_widths(args) 2198 self.ask_run_configuration('parton') 2199 self.banner = None 2200 if not args: 2201 # No run name assigned -> assigned one automaticaly 2202 self.set_run_name(self.find_available_run_name(self.me_dir)) 2203 else: 2204 self.set_run_name(args[0], reload_card=True) 2205 args.pop(0) 2206 2207 self.configure_directory() 2208 2209 # Running gridpack warmup 2210 opts=[('accuracy', accuracy), # default 0.01 2211 ('points', 1000), 2212 ('iterations',9)] 2213 2214 logger.info('Calculating decay widths with run name %s' % self.run_name) 2215 2216 self.exec_cmd('survey %s %s' % \ 2217 (self.run_name, 2218 " ".join(['--' + opt + '=' + str(val) for (opt,val) \ 2219 in opts])), 2220 postcmd=False) 2221 self.refine_mode = "old" # specify how to combine event 2222 self.exec_cmd('combine_events', postcmd=False) 2223 self.exec_cmd('store_events', postcmd=False) 2224 2225 self.collect_decay_widths() 2226 self.print_results_in_shell(self.results.current) 2227 self.update_status('calculate_decay_widths done', 2228 level='parton', makehtml=False)
2229 2230 2231 ############################################################################
2232 - def collect_decay_widths(self):
2233 """ Collect the decay widths and calculate BRs for all particles, and put 2234 in param_card form. 2235 """ 2236 2237 particle_dict = {} # store the results 2238 run_name = self.run_name 2239 2240 # Looping over the Subprocesses 2241 for P_path in SubProcesses.get_subP(self.me_dir): 2242 ids = SubProcesses.get_subP_ids(P_path) 2243 # due to grouping we need to compute the ratio factor for the 2244 # ungroup resutls (that we need here). Note that initial particles 2245 # grouping are not at the same stage as final particle grouping 2246 nb_output = len(ids) / (len(set([p[0] for p in ids]))) 2247 results = open(pjoin(P_path, run_name + '_results.dat')).read().split('\n')[0] 2248 result = float(results.strip().split(' ')[0]) 2249 for particles in ids: 2250 try: 2251 particle_dict[particles[0]].append([particles[1:], result/nb_output]) 2252 except KeyError: 2253 particle_dict[particles[0]] = [[particles[1:], result/nb_output]] 2254 2255 self.update_width_in_param_card(particle_dict, 2256 initial = pjoin(self.me_dir, 'Cards', 'param_card.dat'), 2257 output=pjoin(self.me_dir, 'Events', run_name, "param_card.dat"))
2258 2259 @staticmethod
2260 - def update_width_in_param_card(decay_info, initial=None, output=None):
2261 # Open the param_card.dat and insert the calculated decays and BRs 2262 2263 if not output: 2264 output = initial 2265 2266 param_card_file = open(initial) 2267 param_card = param_card_file.read().split('\n') 2268 param_card_file.close() 2269 2270 decay_lines = [] 2271 line_number = 0 2272 # Read and remove all decays from the param_card 2273 while line_number < len(param_card): 2274 line = param_card[line_number] 2275 if line.lower().startswith('decay'): 2276 # Read decay if particle in decay_info 2277 # DECAY 6 1.455100e+00 2278 line = param_card.pop(line_number) 2279 line = line.split() 2280 particle = 0 2281 if int(line[1]) not in decay_info: 2282 try: # If formatting is wrong, don't want this particle 2283 particle = int(line[1]) 2284 width = float(line[2]) 2285 except Exception: 2286 particle = 0 2287 # Read BRs for this decay 2288 line = param_card[line_number] 2289 while line.startswith('#') or line.startswith(' '): 2290 line = param_card.pop(line_number) 2291 if not particle or line.startswith('#'): 2292 line=param_card[line_number] 2293 continue 2294 # 6.668201e-01 3 5 2 -1 2295 line = line.split() 2296 try: # Remove BR if formatting is wrong 2297 partial_width = float(line[0])*width 2298 decay_products = [int(p) for p in line[2:2+int(line[1])]] 2299 except Exception: 2300 line=param_card[line_number] 2301 continue 2302 try: 2303 decay_info[particle].append([decay_products, partial_width]) 2304 except KeyError: 2305 decay_info[particle] = [[decay_products, partial_width]] 2306 if line_number == len(param_card): 2307 break 2308 line=param_card[line_number] 2309 if particle and particle not in decay_info: 2310 # No decays given, only total width 2311 decay_info[particle] = [[[], width]] 2312 else: # Not decay 2313 line_number += 1 2314 # Clean out possible remaining comments at the end of the card 2315 while not param_card[-1] or param_card[-1].startswith('#'): 2316 param_card.pop(-1) 2317 2318 # Append calculated and read decays to the param_card 2319 param_card.append("#\n#*************************") 2320 param_card.append("# Decay widths *") 2321 param_card.append("#*************************") 2322 for key in sorted(decay_info.keys()): 2323 width = sum([r for p,r in decay_info[key]]) 2324 param_card.append("#\n# PDG Width") 2325 param_card.append("DECAY %i %e" % (key, width.real)) 2326 if not width: 2327 continue 2328 if decay_info[key][0][0]: 2329 param_card.append("# BR NDA ID1 ID2 ...") 2330 brs = [[(val[1]/width).real, val[0]] for val in decay_info[key] if val[1]] 2331 for val in sorted(brs, reverse=True): 2332 param_card.append(" %e %i %s # %s" % 2333 (val[0].real, len(val[1]), 2334 " ".join([str(v) for v in val[1]]), 2335 val[0] * width 2336 )) 2337 decay_table = open(output, 'w') 2338 decay_table.write("\n".join(param_card) + "\n") 2339 decay_table.close() 2340 logger.info("Results written to %s" % output)
2341 2342 2343 ############################################################################
2344 - def do_multi_run(self, line):
2345 2346 args = self.split_arg(line) 2347 # Check argument's validity 2348 mode = self.check_multi_run(args) 2349 nb_run = args.pop(0) 2350 if nb_run == 1: 2351 logger.warn("'multi_run 1' command is not optimal. Think of using generate_events instead") 2352 self.ask_run_configuration(mode) 2353 2354 self.check_survey(args, cmd='multi_run') 2355 main_name = self.run_name 2356 # check if the param_card requires a scan over parameter. 2357 path=pjoin(self.me_dir, 'Cards', 'param_card.dat') 2358 self.check_param_card(path, run=False) 2359 #store it locally to avoid relaunch 2360 param_card_iterator, self.param_card_iterator = self.param_card_iterator, [] 2361 2362 crossoversig = 0 2363 inv_sq_err = 0 2364 nb_event = 0 2365 for i in range(nb_run): 2366 self.nb_refine = 0 2367 self.exec_cmd('generate_events %s_%s -f' % (main_name, i), postcmd=False) 2368 # Update collected value 2369 nb_event += int(self.results[self.run_name][-1]['nb_event']) 2370 self.results.add_detail('nb_event', nb_event , run=main_name) 2371 cross = self.results[self.run_name][-1]['cross'] 2372 error = self.results[self.run_name][-1]['error'] + 1e-99 2373 crossoversig+=cross/error**2 2374 inv_sq_err+=1.0/error**2 2375 self.results[main_name][-1]['cross'] = crossoversig/inv_sq_err 2376 self.results[main_name][-1]['error'] = math.sqrt(1.0/inv_sq_err) 2377 self.results.def_current(main_name) 2378 self.run_name = main_name 2379 self.update_status("Merging LHE files", level='parton') 2380 try: 2381 os.mkdir(pjoin(self.me_dir,'Events', self.run_name)) 2382 except Exception: 2383 pass 2384 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' 2385 % {'bin': self.dirbin, 'event': pjoin(self.me_dir,'Events'), 2386 'name': self.run_name}) 2387 2388 eradir = self.options['exrootanalysis_path'] 2389 if eradir and misc.is_executable(pjoin(eradir,'ExRootLHEFConverter')): 2390 self.update_status("Create Root file", level='parton') 2391 misc.gunzip('%s/%s/unweighted_events.lhe.gz' % 2392 (pjoin(self.me_dir,'Events'), self.run_name)) 2393 2394 self.create_root_file('%s/unweighted_events.lhe' % self.run_name, 2395 '%s/unweighted_events.root' % self.run_name) 2396 2397 path = pjoin(self.me_dir, "Events", self.run_name, "unweighted_events.lhe") 2398 self.create_plot('parton', path, 2399 pjoin(self.me_dir, 'HTML',self.run_name, 'plots_parton.html') 2400 ) 2401 2402 2403 if not os.path.exists('%s.gz' % path): 2404 misc.gzip(path) 2405 2406 self.update_status('', level='parton') 2407 self.print_results_in_shell(self.results.current) 2408 2409 if param_card_iterator: 2410 2411 param_card_iterator.store_entry(self.run_name, self.results.current['cross']) 2412 #check if the param_card defines a scan. 2413 orig_name=self.run_name 2414 for card in param_card_iterator: 2415 card.write(pjoin(self.me_dir,'Cards','param_card.dat')) 2416 self.exec_cmd("multi_run %s -f " % nb_run ,precmd=True, postcmd=True,errorhandling=False) 2417 param_card_iterator.store_entry(self.run_name, self.results.current['cross']) 2418 param_card_iterator.write(pjoin(self.me_dir,'Cards','param_card.dat')) 2419 scan_name = misc.get_scan_name(orig_name, self.run_name) 2420 path = pjoin(self.me_dir, 'Events','scan_%s.txt' % scan_name) 2421 logger.info("write all cross-section results in %s" % path, '$MG:color:BLACK') 2422 param_card_iterator.write_summary(path)
2423 2424 2425 ############################################################################
2426 - def do_treatcards(self, line, mode=None, opt=None):
2427 """Advanced commands: create .inc files from param_card.dat/run_card.dat""" 2428 2429 if not mode and not opt: 2430 args = self.split_arg(line) 2431 mode, opt = self.check_treatcards(args) 2432 2433 # To decide whether to refresh MadLoop's helicity filters, it is necessary 2434 # to check if the model parameters where modified or not, before doing 2435 # anything else. 2436 need_MadLoopFilterUpdate = False 2437 # Just to record what triggered the reinitialization of MadLoop for a 2438 # nice debug message. 2439 type_of_change = '' 2440 if not opt['forbid_MadLoopInit'] and self.proc_characteristics['loop_induced'] \ 2441 and mode in ['loop', 'all']: 2442 paramDat = pjoin(self.me_dir, 'Cards','param_card.dat') 2443 paramInc = pjoin(opt['output_dir'], 'param_card.inc') 2444 if (not os.path.isfile(paramDat)) or (not os.path.isfile(paramInc)) or \ 2445 (os.path.getmtime(paramDat)-os.path.getmtime(paramInc)) > 0.0: 2446 need_MadLoopFilterUpdate = True 2447 type_of_change = 'model' 2448 2449 ML_in = pjoin(self.me_dir, 'Cards', 'MadLoopParams.dat') 2450 ML_out = pjoin(self.me_dir,"SubProcesses", 2451 "MadLoop5_resources", "MadLoopParams.dat") 2452 if (not os.path.isfile(ML_in)) or (not os.path.isfile(ML_out)) or \ 2453 (os.path.getmtime(ML_in)-os.path.getmtime(ML_out)) > 0.0: 2454 need_MadLoopFilterUpdate = True 2455 type_of_change = 'MadLoop' 2456 2457 #check if no 'Auto' are present in the file 2458 self.check_param_card(pjoin(self.me_dir, 'Cards','param_card.dat')) 2459 2460 if mode in ['param', 'all']: 2461 model = self.find_model_name() 2462 tmp_model = os.path.basename(model) 2463 if tmp_model == 'mssm' or tmp_model.startswith('mssm-'): 2464 if not '--param_card=' in line: 2465 param_card = pjoin(self.me_dir, 'Cards','param_card.dat') 2466 mg5_param = pjoin(self.me_dir, 'Source', 'MODEL', 'MG5_param.dat') 2467 check_param_card.convert_to_mg5card(param_card, mg5_param) 2468 check_param_card.check_valid_param_card(mg5_param) 2469 opt['param_card'] = pjoin(self.me_dir, 'Source', 'MODEL', 'MG5_param.dat') 2470 else: 2471 check_param_card.check_valid_param_card(opt['param_card']) 2472 2473 logger.debug('write compile file for card: %s' % opt['param_card']) 2474 param_card = check_param_card.ParamCard(opt['param_card']) 2475 outfile = pjoin(opt['output_dir'], 'param_card.inc') 2476 ident_card = pjoin(self.me_dir,'Cards','ident_card.dat') 2477 if os.path.isfile(pjoin(self.me_dir,'bin','internal','ufomodel','restrict_default.dat')): 2478 default = pjoin(self.me_dir,'bin','internal','ufomodel','restrict_default.dat') 2479 elif os.path.isfile(pjoin(self.me_dir,'bin','internal','ufomodel','param_card.dat')): 2480 default = pjoin(self.me_dir,'bin','internal','ufomodel','param_card.dat') 2481 elif not os.path.exists(pjoin(self.me_dir,'bin','internal','ufomodel')): 2482 fsock = open(pjoin(self.me_dir,'Source','param_card.inc'),'w') 2483 fsock.write(' ') 2484 fsock.close() 2485 if mode == 'all': 2486 self.do_treatcards('', 'run', opt) 2487 return 2488 else: 2489 devnull = open(os.devnull,'w') 2490 subprocess.call([sys.executable, 'write_param_card.py'], 2491 cwd=pjoin(self.me_dir,'bin','internal','ufomodel'), 2492 stdout=devnull) 2493 devnull.close() 2494 default = pjoin(self.me_dir,'bin','internal','ufomodel','param_card.dat') 2495 2496 need_mp = self.proc_characteristics['loop_induced'] 2497 param_card.write_inc_file(outfile, ident_card, default, need_mp=need_mp) 2498 2499 2500 if mode in ['run', 'all']: 2501 if not hasattr(self, 'run_card'): 2502 run_card = banner_mod.RunCard(opt['run_card']) 2503 else: 2504 run_card = self.run_card 2505 if self.ninitial == 1: 2506 run_card['lpp1'] = 0 2507 run_card['lpp2'] = 0 2508 run_card['ebeam1'] = 0 2509 run_card['ebeam2'] = 0 2510 2511 run_card.write_include_file(pjoin(opt['output_dir'],'run_card.inc')) 2512 2513 2514 if self.proc_characteristics['loop_induced'] and mode in ['loop', 'all']: 2515 self.MadLoopparam = banner_mod.MadLoopParam(pjoin(self.me_dir, 2516 'Cards', 'MadLoopParams.dat')) 2517 # The writing out of MadLoop filter is potentially dangerous 2518 # when running in multi-core with a central disk. So it is turned 2519 # off here. If these filters were not initialized then they will 2520 # have to be re-computed at the beginning of each run. 2521 if 'WriteOutFilters' in self.MadLoopparam.user_set and \ 2522 self.MadLoopparam.get('WriteOutFilters'): 2523 logger.info( 2524 """You chose to have MadLoop writing out filters. 2525 Beware that this can be dangerous for local multicore runs.""") 2526 self.MadLoopparam.set('WriteOutFilters',False, ifnotdefault=False) 2527 2528 # The conservative settings below for 'CTModeInit' and 'ZeroThres' 2529 # help adress issues for processes like g g > h z, and g g > h g 2530 # where there are some helicity configuration heavily suppressed 2531 # (by several orders of magnitude) so that the helicity filter 2532 # needs high numerical accuracy to correctly handle this spread in 2533 # magnitude. Also, because one cannot use the Born as a reference 2534 # scale, it is better to force quadruple precision *for the 2535 # initialization points only*. This avoids numerical accuracy issues 2536 # when setting up the helicity filters and does not significantly 2537 # slow down the run. 2538 # self.MadLoopparam.set('CTModeInit',4, ifnotdefault=False) 2539 # Consequently, we can allow for a finer threshold for vanishing 2540 # helicity configuration 2541 # self.MadLoopparam.set('ZeroThres',1.0e-11, ifnotdefault=False) 2542 2543 # It is a bit superficial to use the level 2 which tries to numerically 2544 # map matching helicities (because of CP symmetry typically) together. 2545 # It is useless in the context of MC over helicities and it can 2546 # potentially make the helicity double checking fail. 2547 self.MadLoopparam.set('HelicityFilterLevel',1, ifnotdefault=False) 2548 2549 # To be on the safe side however, we ask for 4 consecutive matching 2550 # helicity filters. 2551 self.MadLoopparam.set('CheckCycle',4, ifnotdefault=False) 2552 2553 # For now it is tricky to have eahc channel performing the helicity 2554 # double check. What we will end up doing is probably some kind 2555 # of new initialization round at the beginning of each launch 2556 # command, to reset the filters. 2557 self.MadLoopparam.set('DoubleCheckHelicityFilter',False, 2558 ifnotdefault=False) 2559 2560 # Thanks to TIR recycling, TIR is typically much faster for Loop-induced 2561 # processes, so that we place OPP last. 2562 if not hasattr(self, 'run_card'): 2563 run_card = banner_mod.RunCard(opt['run_card']) 2564 else: 2565 run_card = self.run_card 2566 if run_card['nhel'] == 0: 2567 if 'MLReductionLib' in self.MadLoopparam.user_set and \ 2568 (self.MadLoopparam.get('MLReductionLib').startswith('1') or 2569 self.MadLoopparam.get('MLReductionLib').startswith('6')): 2570 logger.warning( 2571 """You chose to set the preferred reduction technique in MadLoop to be OPP (see parameter MLReductionLib). 2572 Beware that this can bring significant slowdown; the optimal choice --when not MC over helicity-- being to first start with TIR reduction.""") 2573 # We do not include GOLEM for now since it cannot recycle TIR coefs yet. 2574 self.MadLoopparam.set('MLReductionLib','2|6|1', ifnotdefault=False) 2575 else: 2576 if 'MLReductionLib' in self.MadLoopparam.user_set and \ 2577 not (self.MadLoopparam.get('MLReductionLib').startswith('1') or 2578 self.MadLoopparam.get('MLReductionLib').startswith('6')): 2579 logger.warning( 2580 """You chose to set the preferred reduction technique in MadLoop to be different than OPP (see parameter MLReductionLib). 2581 Beware that this can bring significant slowdown; the optimal choice --when MC over helicity-- being to first start with OPP reduction.""") 2582 self.MadLoopparam.set('MLReductionLib','6|1|2', ifnotdefault=False) 2583 2584 # Also TIR cache will only work when NRotations_DP=0 (but only matters 2585 # when not MC-ing over helicities) so it will be hard-reset by MadLoop 2586 # to zero when not MC-ing over helicities, unless the parameter 2587 # Force_ML_Helicity_Sum is set to True in the matrix<i>.f codes. 2588 if run_card['nhel'] == 0: 2589 if ('NRotations_DP' in self.MadLoopparam.user_set and \ 2590 self.MadLoopparam.get('NRotations_DP')!=0) or \ 2591 ('NRotations_QP' in self.MadLoopparam.user_set and \ 2592 self.MadLoopparam.get('NRotations_QP')!=0): 2593 logger.warning( 2594 """You chose to also use a lorentz rotation for stability tests (see parameter NRotations_[DP|QP]). 2595 Beware that, for optimization purposes, MadEvent uses manual TIR cache clearing which is not compatible 2596 with the lorentz rotation stability test. The number of these rotations to be used will be reset to 2597 zero by MadLoop. You can avoid this by changing the parameter 'FORCE_ML_HELICITY_SUM' int he matrix<i>.f 2598 files to be .TRUE. so that the sum over helicity configurations is performed within MadLoop (in which case 2599 the helicity of final state particles cannot be speicfied in the LHE file.""") 2600 self.MadLoopparam.set('NRotations_DP',0,ifnotdefault=False) 2601 self.MadLoopparam.set('NRotations_QP',0,ifnotdefault=False) 2602 else: 2603 # When MC-ing over helicities, the manual TIR cache clearing is 2604 # not necessary, so that one can use the lorentz check 2605 # Using NRotations_DP=1 slows down the code by close to 100% 2606 # but it is typicaly safer. 2607 # self.MadLoopparam.set('NRotations_DP',0,ifnotdefault=False) 2608 # Revert to the above to be slightly less robust but twice faster. 2609 self.MadLoopparam.set('NRotations_DP',1,ifnotdefault=False) 2610 self.MadLoopparam.set('NRotations_QP',0,ifnotdefault=False) 2611 2612 # Finally, the stability tests are slightly less reliable for process 2613 # with less or equal than 4 final state particles because the 2614 # accessible kinematic is very limited (i.e. lorentz rotations don't 2615 # shuffle invariants numerics much). In these cases, we therefore 2616 # increase the required accuracy to 10^-7. 2617 # This is important for getting g g > z z [QCD] working with a 2618 # ptheavy cut as low as 1 GeV. 2619 if self.proc_characteristics['nexternal']<=4: 2620 if ('MLStabThres' in self.MadLoopparam.user_set and \ 2621 self.MadLoopparam.get('MLStabThres')>1.0e-7): 2622 logger.warning( 2623 """You chose to increase the default value of the MadLoop parameter 'MLStabThres' above 1.0e-7. 2624 Stability tests can be less reliable on the limited kinematic of processes with less or equal 2625 than four external legs, so this is not recommended (especially not for g g > z z).""") 2626 self.MadLoopparam.set('MLStabThres',1.0e-7,ifnotdefault=False) 2627 else: 2628 self.MadLoopparam.set('MLStabThres',1.0e-4,ifnotdefault=False) 2629 2630 #write the output file 2631 self.MadLoopparam.write(pjoin(self.me_dir,"SubProcesses","MadLoop5_resources", 2632 "MadLoopParams.dat")) 2633 2634 if self.proc_characteristics['loop_induced'] and mode in ['loop', 'all']: 2635 # Now Update MadLoop filters if necessary (if modifications were made to 2636 # the model parameters). 2637 if need_MadLoopFilterUpdate: 2638 logger.debug('Changes to the %s parameters'%type_of_change+\ 2639 ' have been detected. Madevent will then now reinitialize'+\ 2640 ' MadLoop filters.') 2641 self.exec_cmd('initMadLoop -r -f') 2642 # The need_MadLoopInit condition is just there so as to avoid useless 2643 # printout if there is not initialization to be performed. But even 2644 # without it, and because we call 'initMadLoop' without the '-r' option 2645 # no time would be wasted anyway, since the existing filters would not 2646 # be overwritten. 2647 elif not opt['forbid_MadLoopInit'] and \ 2648 MadLoopInitializer.need_MadLoopInit(self.me_dir): 2649 self.exec_cmd('initMadLoop -f')
2650 2651 ############################################################################
2652 - def do_survey(self, line):
2653 """Advanced commands: launch survey for the current process """ 2654 2655 2656 args = self.split_arg(line) 2657 # Check argument's validity 2658 self.check_survey(args) 2659 # initialize / remove lhapdf mode 2660 2661 if os.path.exists(pjoin(self.me_dir,'error')): 2662 os.remove(pjoin(self.me_dir,'error')) 2663 2664 self.configure_directory() 2665 # Save original random number 2666 self.random_orig = self.random 2667 logger.info("Using random number seed offset = %s" % self.random) 2668 # Update random number 2669 self.update_random() 2670 self.save_random() 2671 self.update_status('Running Survey', level=None) 2672 if self.cluster_mode: 2673 logger.info('Creating Jobs') 2674 2675 self.total_jobs = 0 2676 subproc = [l.strip() for l in open(pjoin(self.me_dir, 2677 'SubProcesses', 'subproc.mg'))] 2678 2679 P_zero_result = [] # check the number of times where they are no phase-space 2680 2681 # File for the loop (for loop induced) 2682 if os.path.exists(pjoin(self.me_dir,'SubProcesses', 2683 'MadLoop5_resources')) and cluster.need_transfer(self.options): 2684 tf=tarfile.open(pjoin(self.me_dir, 'SubProcesses', 2685 'MadLoop5_resources.tar.gz'), 'w:gz', dereference=True) 2686 tf.add(pjoin(self.me_dir,'SubProcesses','MadLoop5_resources'), 2687 arcname='MadLoop5_resources') 2688 tf.close() 2689 2690 logger.info('Working on SubProcesses') 2691 ajobcreator = gen_ximprove.gensym(self) 2692 2693 #check difficult PS case 2694 if float(self.run_card['mmjj']) > 0.01 * (float(self.run_card['ebeam1'])+float(self.run_card['ebeam2'])): 2695 self.pass_in_difficult_integration_mode() 2696 2697 jobs, P_zero_result = ajobcreator.launch() 2698 2699 # Check if all or only some fails 2700 if P_zero_result: 2701 if len(P_zero_result) == len(subproc): 2702 Pdir = pjoin(self.me_dir, 'SubProcesses',subproc[0].strip()) 2703 raise ZeroResult, '%s' % \ 2704 open(pjoin(Pdir,'ajob.no_ps.log')).read() 2705 else: 2706 logger.warning(''' %s SubProcesses doesn\'t have available phase-space. 2707 Please check mass spectrum.''' % ','.join(P_zero_result)) 2708 2709 2710 self.monitor(run_type='All jobs submitted for survey', html=True) 2711 if not self.history or 'survey' in self.history[-1] or self.ninitial ==1 or \ 2712 self.run_card['gridpack']: 2713 #will be done during the refine (more precisely in gen_ximprove) 2714 cross, error = sum_html.make_all_html_results(self) 2715 self.results.add_detail('cross', cross) 2716 self.results.add_detail('error', error) 2717 self.exec_cmd("print_results %s" % self.run_name, 2718 errorhandling=False, printcmd=False, precmd=False, postcmd=False) 2719 2720 self.results.add_detail('run_statistics', dict(ajobcreator.run_statistics)) 2721 self.update_status('End survey', 'parton', makehtml=False)
2722 2723 ############################################################################
2724 - def pass_in_difficult_integration_mode(self):
2725 """be more secure for the integration to not miss it due to strong cut""" 2726 2727 # improve survey options if default 2728 if self.opts['points'] == self._survey_options['points'][1]: 2729 self.opts['points'] = 2 * self._survey_options['points'][1] 2730 if self.opts['iterations'] == self._survey_options['iterations'][1]: 2731 self.opts['iterations'] = 1 + self._survey_options['iterations'][1] 2732 if self.opts['accuracy'] == self._survey_options['accuracy'][1]: 2733 self.opts['accuracy'] = self._survey_options['accuracy'][1]/2 2734 2735 # Modify run_config.inc in order to improve the refine 2736 #conf_path = pjoin(self.me_dir, 'Source','run_config.inc') 2737 #files.cp(conf_path, conf_path + '.bk') 2738 # 2739 #text = open(conf_path).read() 2740 #text = re.sub('''\(min_events = \d+\)''', '''(min_events = 7500 )''', text) 2741 #text = re.sub('''\(max_events = \d+\)''', '''(max_events = 20000 )''', text) 2742 #fsock = open(conf_path, 'w') 2743 #fsock.write(text) 2744 #fsock.close() 2745 2746 # Compile 2747 for name in ['../bin/internal/gen_ximprove', 'all', 2748 '../bin/internal/combine_events']: 2749 self.compile(arg=[name], cwd=os.path.join(self.me_dir, 'Source'))
2750 2751 2752 ############################################################################
2753 - def do_refine(self, line):
2754 """Advanced commands: launch survey for the current process """ 2755 devnull = open(os.devnull, 'w') 2756 self.nb_refine += 1 2757 args = self.split_arg(line) 2758 # Check argument's validity 2759 self.check_refine(args) 2760 2761 refine_opt = {'err_goal': args[0], 'split_channels': True} 2762 precision = args[0] 2763 if len(args) == 2: 2764 refine_opt['max_process']= args[1] 2765 2766 2767 # initialize / remove lhapdf mode 2768 self.configure_directory() 2769 2770 # Update random number 2771 self.update_random() 2772 self.save_random() 2773 2774 if self.cluster_mode: 2775 logger.info('Creating Jobs') 2776 self.update_status('Refine results to %s' % precision, level=None) 2777 2778 self.total_jobs = 0 2779 subproc = [l.strip() for l in open(pjoin(self.me_dir,'SubProcesses', 2780 'subproc.mg'))] 2781 2782 # cleanning the previous job 2783 for nb_proc,subdir in enumerate(subproc): 2784 subdir = subdir.strip() 2785 Pdir = pjoin(self.me_dir, 'SubProcesses', subdir) 2786 for match in misc.glob('*ajob*', Pdir): 2787 if os.path.basename(match)[:4] in ['ajob', 'wait', 'run.', 'done']: 2788 os.remove(match) 2789 2790 x_improve = gen_ximprove.gen_ximprove(self, refine_opt) 2791 # Load the run statistics from the survey 2792 survey_statistics = dict(self.results.get_detail('run_statistics')) 2793 # Printout survey statistics 2794 if __debug__ and survey_statistics: 2795 globalstat = sum_html.RunStatistics() 2796 logger.debug(" === Survey statistics summary ===") 2797 for key, value in survey_statistics.items(): 2798 globalstat.aggregate_statistics(value) 2799 level = 5 2800 if value.has_warning(): 2801 level = 10 2802 logger.log(level, 2803 value.nice_output(str('/'.join([key[0],'G%s'%key[1]]))). 2804 replace(' statistics','')) 2805 logger.debug(globalstat.nice_output('combined', no_warning=True)) 2806 2807 if survey_statistics: 2808 x_improve.run_statistics = survey_statistics 2809 2810 x_improve.launch() # create the ajob for the refinment. 2811 if not self.history or 'refine' not in self.history[-1]: 2812 cross, error = x_improve.update_html() #update html results for survey 2813 if cross == 0: 2814 return 2815 logger.info("Current estimate of cross-section: %s +- %s" % (cross, error)) 2816 2817 2818 if isinstance(x_improve, gen_ximprove.gen_ximprove_v4): 2819 # Non splitted mode is based on writting ajob so need to track them 2820 # Splitted mode handle the cluster submition internally. 2821 for nb_proc,subdir in enumerate(subproc): 2822 subdir = subdir.strip() 2823 Pdir = pjoin(self.me_dir, 'SubProcesses',subdir) 2824 bindir = pjoin(os.path.relpath(self.dirbin, Pdir)) 2825 2826 logger.info(' %s ' % subdir) 2827 2828 if os.path.exists(pjoin(Pdir, 'ajob1')): 2829 self.compile(['madevent'], cwd=Pdir) 2830 2831 alljobs = misc.glob('ajob*', Pdir) 2832 2833 #remove associated results.dat (ensure to not mix with all data) 2834 Gre = re.compile("\s*j=(G[\d\.\w]+)") 2835 for job in alljobs: 2836 Gdirs = Gre.findall(open(job).read()) 2837 for Gdir in Gdirs: 2838 if os.path.exists(pjoin(Pdir, Gdir, 'results.dat')): 2839 os.remove(pjoin(Pdir, Gdir,'results.dat')) 2840 2841 nb_tot = len(alljobs) 2842 self.total_jobs += nb_tot 2843 for i, job in enumerate(alljobs): 2844 job = os.path.basename(job) 2845 self.launch_job('%s' % job, cwd=Pdir, remaining=(nb_tot-i-1), 2846 run_type='Refine number %s on %s (%s/%s)' % 2847 (self.nb_refine, subdir, nb_proc+1, len(subproc))) 2848 2849 self.monitor(run_type='All job submitted for refine number %s' % self.nb_refine, 2850 html=True) 2851 2852 self.update_status("Combining runs", level='parton') 2853 try: 2854 os.remove(pjoin(Pdir, 'combine_runs.log')) 2855 except Exception: 2856 pass 2857 2858 if isinstance(x_improve, gen_ximprove.gen_ximprove_v4): 2859 # the merge of the events.lhe is handle in the x_improve class 2860 # for splitted runs. (and partly in store_events). 2861 combine_runs.CombineRuns(self.me_dir) 2862 self.refine_mode = "old" 2863 else: 2864 self.refine_mode = "new" 2865 2866 cross, error = sum_html.make_all_html_results(self) 2867 self.results.add_detail('cross', cross) 2868 self.results.add_detail('error', error) 2869 2870 self.results.add_detail('run_statistics', 2871 dict(self.results.get_detail('run_statistics'))) 2872 2873 self.update_status('finish refine', 'parton', makehtml=False) 2874 devnull.close()
2875 2876 ############################################################################
2877 - def do_combine_iteration(self, line):
2878 """Not in help: Combine a given iteration combine_iteration Pdir Gdir S|R step 2879 S is for survey 2880 R is for refine 2881 step is the iteration number (not very critical)""" 2882 2883 self.set_run_name("tmp") 2884 self.configure_directory(html_opening=False) 2885 Pdir, Gdir, mode, step = self.split_arg(line) 2886 if Gdir.startswith("G"): 2887 Gdir = Gdir[1:] 2888 if "SubProcesses" not in Pdir: 2889 Pdir = pjoin(self.me_dir, "SubProcesses", Pdir) 2890 if mode == "S": 2891 self.opts = dict([(key,value[1]) for (key,value) in \ 2892 self._survey_options.items()]) 2893 gensym = gen_ximprove.gensym(self) 2894 gensym.combine_iteration(Pdir, Gdir, int(step)) 2895 elif mode == "R": 2896 refine = gen_ximprove.gen_ximprove_share(self) 2897 refine.combine_iteration(Pdir, Gdir, int(step))
2898 2899 2900 2901 2902 ############################################################################
2903 - def do_combine_events(self, line):
2904 """Advanced commands: Launch combine events""" 2905 2906 args = self.split_arg(line) 2907 # Check argument's validity 2908 self.check_combine_events(args) 2909 2910 self.update_status('Combining Events', level='parton') 2911 2912 2913 if False: #not hasattr(self, "refine_mode") or self.refine_mode == "old": 2914 try: 2915 os.remove(pjoin(self.me_dir,'SubProcesses', 'combine.log')) 2916 except Exception: 2917 pass 2918 2919 cluster.onecore.launch_and_wait('../bin/internal/run_combine', 2920 args=[self.run_name], 2921 cwd=pjoin(self.me_dir,'SubProcesses'), 2922 stdout=pjoin(self.me_dir,'SubProcesses', 'combine.log'), 2923 required_output=[pjoin(self.me_dir,'SubProcesses', 'combine.log')]) 2924 2925 #self.cluster.launch_and_wait('../bin/internal/run_combine', 2926 # cwd=pjoin(self.me_dir,'SubProcesses'), 2927 # stdout=pjoin(self.me_dir,'SubProcesses', 'combine.log'), 2928 # required_output=[pjoin(self.me_dir,'SubProcesses', 'combine.log')]) 2929 2930 output = misc.mult_try_open(pjoin(self.me_dir,'SubProcesses','combine.log')).read() 2931 # Store the number of unweighted events for the results object 2932 pat = re.compile(r'''\s*Unweighting\s*selected\s*(\d+)\s*events''') 2933 try: 2934 nb_event = pat.search(output).groups()[0] 2935 except AttributeError: 2936 time.sleep(10) 2937 output = misc.mult_try_open(pjoin(self.me_dir,'SubProcesses','combine.log')).read() 2938 try: 2939 nb_event = pat.search(output).groups()[0] 2940 except AttributeError: 2941 logger.warning('Fail to read the number of unweighted events in the combine.log file') 2942 nb_event = 0 2943 2944 self.results.add_detail('nb_event', nb_event) 2945 2946 2947 # Define The Banner 2948 tag = self.run_card['run_tag'] 2949 2950 # Update the banner with the pythia card 2951 if not self.banner: 2952 self.banner = banner_mod.recover_banner(self.results, 'parton') 2953 self.banner.load_basic(self.me_dir) 2954 # Add cross-section/event information 2955 self.banner.add_generation_info(self.results.current['cross'], nb_event) 2956 if not hasattr(self, 'random_orig'): self.random_orig = 0 2957 self.banner.change_seed(self.random_orig) 2958 if not os.path.exists(pjoin(self.me_dir, 'Events', self.run_name)): 2959 os.mkdir(pjoin(self.me_dir, 'Events', self.run_name)) 2960 self.banner.write(pjoin(self.me_dir, 'Events', self.run_name, 2961 '%s_%s_banner.txt' % (self.run_name, tag))) 2962 2963 2964 self.banner.add_to_file(pjoin(self.me_dir,'Events', 'events.lhe'), 2965 out=pjoin(self.me_dir,'Events', self.run_name, 'events.lhe')) 2966 self.banner.add_to_file(pjoin(self.me_dir,'Events', 'unweighted_events.lhe'), 2967 out=pjoin(self.me_dir,'Events', self.run_name, 'unweighted_events.lhe')) 2968 2969 2970 elif True:#self.refine_mode == "new": 2971 # Define The Banner 2972 tag = self.run_card['run_tag'] 2973 # Update the banner with the pythia card 2974 if not self.banner: 2975 self.banner = banner_mod.recover_banner(self.results, 'parton') 2976 self.banner.load_basic(self.me_dir) 2977 # Add cross-section/event information 2978 self.banner.add_generation_info(self.results.current['cross'], self.run_card['nevents']) 2979 if not hasattr(self, 'random_orig'): self.random_orig = 0 2980 self.banner.change_seed(self.random_orig) 2981 if not os.path.exists(pjoin(self.me_dir, 'Events', self.run_name)): 2982 os.mkdir(pjoin(self.me_dir, 'Events', self.run_name)) 2983 self.banner.write(pjoin(self.me_dir, 'Events', self.run_name, 2984 '%s_%s_banner.txt' % (self.run_name, tag))) 2985 2986 2987 get_wgt = lambda event: event.wgt 2988 AllEvent = lhe_parser.MultiEventFile() 2989 AllEvent.banner = self.banner 2990 2991 partials = 0 # if too many file make some partial unweighting 2992 sum_xsec, sum_xerru, sum_axsec = 0,[],0 2993 for Gdir,mfactor in self.get_Gdir(): 2994 if os.path.exists(pjoin(Gdir, 'events.lhe')): 2995 result = sum_html.OneResult('') 2996 result.read_results(pjoin(Gdir, 'results.dat')) 2997 AllEvent.add(pjoin(Gdir, 'events.lhe'), 2998 result.get('xsec'), 2999 result.get('xerru'), 3000 result.get('axsec') 3001 ) 3002 sum_xsec += result.get('xsec') 3003 sum_xerru.append(result.get('xerru')) 3004 sum_axsec += result.get('axsec') 3005 3006 if len(AllEvent) >= 80: #perform a partial unweighting 3007 AllEvent.unweight(pjoin(self.me_dir, "Events", self.run_name, "partials%s.lhe.gz" % partials), 3008 get_wgt, log_level=logging.DEBUG, write_init=True) 3009 AllEvent = lhe_parser.MultiEventFile() 3010 AllEvent.banner = self.banner 3011 AllEvent.add(pjoin(self.me_dir, "Events", self.run_name, "partials%s.lhe.gz" % partials), 3012 sum_xsec, 3013 math.sqrt(sum(x**2 for x in sum_xerru)), 3014 sum_axsec) 3015 partials +=1 3016 3017 nb_event = AllEvent.unweight(pjoin(self.me_dir, "Events", self.run_name, "unweighted_events.lhe.gz"), 3018 get_wgt, trunc_error=1e-2, event_target=self.run_card['nevents'], 3019 log_level=logging.DEBUG) 3020 3021 if partials: 3022 misc.sprint("used partials") 3023 for i in range(partials): 3024 os.remove(pjoin(self.me_dir, "Events", self.run_name, "partials%s.lhe.gz" % i)) 3025 3026 self.results.add_detail('nb_event', nb_event) 3027 3028 self.to_store.append('event') 3029 eradir = self.options['exrootanalysis_path'] 3030 madir = self.options['madanalysis_path'] 3031 td = self.options['td_path'] 3032 if eradir and misc.is_executable(pjoin(eradir,'ExRootLHEFConverter')) and\ 3033 os.path.exists(pjoin(self.me_dir, 'Events', 'unweighted_events.lhe')): 3034 if not os.path.exists(pjoin(self.me_dir, 'Events', self.run_name)): 3035 os.mkdir(pjoin(self.me_dir, 'Events', self.run_name)) 3036 self.create_root_file(output='%s/unweighted_events.root' % \ 3037 self.run_name)
3038 3039 ############################################################################
3040 - def do_store_events(self, line):
3041 """Advanced commands: Launch store events""" 3042 3043 args = self.split_arg(line) 3044 # Check argument's validity 3045 self.check_combine_events(args) 3046 self.update_status('Storing parton level results', level='parton') 3047 3048 run = self.run_name 3049 tag = self.run_card['run_tag'] 3050 devnull = open(os.devnull, 'w') 3051 3052 if not os.path.exists(pjoin(self.me_dir, 'Events', run)): 3053 os.mkdir(pjoin(self.me_dir, 'Events', run)) 3054 if not os.path.exists(pjoin(self.me_dir, 'HTML', run)): 3055 os.mkdir(pjoin(self.me_dir, 'HTML', run)) 3056 3057 # 1) Store overall process information 3058 #input = pjoin(self.me_dir, 'SubProcesses', 'results.dat') 3059 #output = pjoin(self.me_dir, 'SubProcesses', '%s_results.dat' % run) 3060 #files.cp(input, output) 3061 3062 3063 # 2) Treat the files present in the P directory 3064 # Ensure that the number of events is different of 0 3065 if self.results.current['nb_event'] == 0: 3066 logger.warning("No event detected. No cleaning performed! This should allow to run:\n" + 3067 " cd Subprocesses; ../bin/internal/combine_events\n"+ 3068 " to have your events if those one are missing.") 3069 else: 3070 for P_path in SubProcesses.get_subP(self.me_dir): 3071 G_dir = [G for G in os.listdir(P_path) if G.startswith('G') and 3072 os.path.isdir(pjoin(P_path,G))] 3073 for G in G_dir: 3074 G_path = pjoin(P_path,G) 3075 try: 3076 # Remove events file (if present) 3077 if os.path.exists(pjoin(G_path, 'events.lhe')): 3078 os.remove(pjoin(G_path, 'events.lhe')) 3079 except Exception: 3080 continue 3081 #try: 3082 # # Store results.dat 3083 # if os.path.exists(pjoin(G_path, 'results.dat')): 3084 # input = pjoin(G_path, 'results.dat') 3085 # output = pjoin(G_path, '%s_results.dat' % run) 3086 # files.cp(input, output) 3087 #except Exception: 3088 # continue 3089 # Store log 3090 try: 3091 if os.path.exists(pjoin(G_path, 'log.txt')): 3092 input = pjoin(G_path, 'log.txt') 3093 output = pjoin(G_path, '%s_log.txt' % run) 3094 files.mv(input, output) 3095 except Exception: 3096 continue 3097 #try: 3098 # # Grid 3099 # for name in ['ftn26']: 3100 # if os.path.exists(pjoin(G_path, name)): 3101 # if os.path.exists(pjoin(G_path, '%s_%s.gz'%(run,name))): 3102 # os.remove(pjoin(G_path, '%s_%s.gz'%(run,name))) 3103 # input = pjoin(G_path, name) 3104 # output = pjoin(G_path, '%s_%s' % (run,name)) 3105 # files.mv(input, output) 3106 # misc.gzip(pjoin(G_path, output), error=None) 3107 #except Exception: 3108 # continue 3109 # Delete ftn25 to ensure reproducible runs 3110 if os.path.exists(pjoin(G_path, 'ftn25')): 3111 os.remove(pjoin(G_path, 'ftn25')) 3112 3113 # 3) Update the index.html 3114 misc.call(['%s/gen_cardhtml-pl' % self.dirbin], 3115 cwd=pjoin(self.me_dir)) 3116 3117 3118 # 4) Move the Files present in Events directory 3119 E_path = pjoin(self.me_dir, 'Events') 3120 O_path = pjoin(self.me_dir, 'Events', run) 3121 3122 # The events file 3123 for name in ['events.lhe', 'unweighted_events.lhe']: 3124 finput = pjoin(E_path, name) 3125 foutput = pjoin(O_path, name) 3126 if os.path.exists(finput): 3127 logger.debug("File %s exists BAAAAD. Not move anymore!" % pjoin(E_path, name)) 3128 if os.path.exists(foutput): 3129 misc.gzip(foutput, stdout="%s.gz" % foutput, error=False) 3130 # if os.path.exists(pjoin(O_path, '%s.gz' % name)): 3131 # os.remove(pjoin(O_path, '%s.gz' % name)) 3132 # input = pjoin(E_path, name) 3133 ## output = pjoin(O_path, name) 3134 3135 3136 self.update_status('End Parton', level='parton', makehtml=False) 3137 devnull.close()
3138 3139 3140 ############################################################################
3141 - def do_create_gridpack(self, line):
3142 """Advanced commands: Create gridpack from present run""" 3143 3144 self.update_status('Creating gridpack', level='parton') 3145 # compile gen_ximprove 3146 misc.compile(['../bin/internal/gen_ximprove'], cwd=pjoin(self.me_dir, "Source")) 3147 args = self.split_arg(line) 3148 self.check_combine_events(args) 3149 if not self.run_tag: self.run_tag = 'tag_1' 3150 os.system("sed -i.bak \"s/ *.false.*=.*GridRun/ .true. = GridRun/g\" %s/Cards/grid_card.dat" \ 3151 % self.me_dir) 3152 misc.call(['./bin/internal/restore_data', self.run_name], 3153 cwd=self.me_dir) 3154 misc.call(['./bin/internal/store4grid', 3155 self.run_name, self.run_tag], 3156 cwd=self.me_dir) 3157 misc.call(['./bin/internal/clean'], cwd=self.me_dir) 3158 misc.call(['./bin/internal/make_gridpack'], cwd=self.me_dir) 3159 files.mv(pjoin(self.me_dir, 'gridpack.tar.gz'), 3160 pjoin(self.me_dir, '%s_gridpack.tar.gz' % self.run_name)) 3161 os.system("sed -i.bak \"s/\s*.true.*=.*GridRun/ .false. = GridRun/g\" %s/Cards/grid_card.dat" \ 3162 % self.me_dir) 3163 self.update_status('gridpack created', level='gridpack')
3164 3165 ############################################################################
3166 - def do_pythia(self, line):
3167 """launch pythia""" 3168 3169 # Check argument's validity 3170 args = self.split_arg(line) 3171 if '--no_default' in args: 3172 if not os.path.exists(pjoin(self.me_dir, 'Cards', 'pythia_card.dat')): 3173 return 3174 no_default = True 3175 args.remove('--no_default') 3176 else: 3177 no_default = False 3178 3179 if not self.run_name: 3180 self.check_pythia(args) 3181 self.configure_directory(html_opening =False) 3182 else: 3183 # initialize / remove lhapdf mode 3184 self.configure_directory(html_opening =False) 3185 self.check_pythia(args) 3186 3187 3188 # the args are modify and the last arg is always the mode 3189 if not no_default: 3190 self.ask_pythia_run_configuration(args[-1]) 3191 3192 if self.options['automatic_html_opening']: 3193 misc.open_file(os.path.join(self.me_dir, 'crossx.html')) 3194 self.options['automatic_html_opening'] = False 3195 3196 # Update the banner with the pythia card 3197 if not self.banner or len(self.banner) <=1: 3198 self.banner = banner_mod.recover_banner(self.results, 'pythia') 3199 3200 3201 3202 pythia_src = pjoin(self.options['pythia-pgs_path'],'src') 3203 3204 self.update_status('Running Pythia', 'pythia') 3205 try: 3206 os.remove(pjoin(self.me_dir,'Events','pythia.done')) 3207 except Exception: 3208 pass 3209 3210 ## LAUNCHING PYTHIA 3211 # check that LHAPATH is define. 3212 if not re.search(r'^\s*LHAPATH=%s/PDFsets' % pythia_src, 3213 open(pjoin(self.me_dir,'Cards','pythia_card.dat')).read(), 3214 re.M): 3215 f = open(pjoin(self.me_dir,'Cards','pythia_card.dat'),'a') 3216 f.write('\n LHAPATH=%s/PDFsets' % pythia_src) 3217 f.close() 3218 tag = self.run_tag 3219 pythia_log = pjoin(self.me_dir, 'Events', self.run_name , '%s_pythia.log' % tag) 3220 self.cluster.launch_and_wait('../bin/internal/run_pythia', 3221 argument= [pythia_src], stdout= pythia_log, 3222 stderr=subprocess.STDOUT, 3223 cwd=pjoin(self.me_dir,'Events')) 3224 3225 os.remove(pjoin(self.me_dir, "Events", "unweighted_events.lhe")) 3226 3227 3228 3229 if not os.path.exists(pjoin(self.me_dir,'Events','pythia.done')): 3230 logger.warning('Fail to produce pythia output. More info in \n %s' % pythia_log) 3231 return 3232 else: 3233 os.remove(pjoin(self.me_dir,'Events','pythia.done')) 3234 3235 self.to_store.append('pythia') 3236 3237 # Find the matched cross-section 3238 if int(self.run_card['ickkw']): 3239 # read the line from the bottom of the file 3240 pythia_log = misc.BackRead(pjoin(self.me_dir,'Events', self.run_name, 3241 '%s_pythia.log' % tag)) 3242 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") 3243 for line in pythia_log: 3244 info = pythiare.search(line) 3245 if not info: 3246 continue 3247 try: 3248 # Pythia cross section in mb, we want pb 3249 sigma_m = float(info.group('xsec').replace('D','E')) *1e9 3250 Nacc = int(info.group('generated')) 3251 Ntry = int(info.group('tried')) 3252 except ValueError: 3253 # xsec is not float - this should not happen 3254 self.results.add_detail('cross_pythia', 0) 3255 self.results.add_detail('nb_event_pythia', 0) 3256 self.results.add_detail('error_pythia', 0) 3257 else: 3258 self.results.add_detail('cross_pythia', sigma_m) 3259 self.results.add_detail('nb_event_pythia', Nacc) 3260 #compute pythia error 3261 error = self.results[self.run_name].return_tag(self.run_tag)['error'] 3262 if Nacc: 3263 error_m = math.sqrt((error * Nacc/Ntry)**2 + sigma_m**2 *(1-Nacc/Ntry)/Nacc) 3264 else: 3265 error_m = 10000 * sigma_m 3266 # works both for fixed number of generated events and fixed accepted events 3267 self.results.add_detail('error_pythia', error_m) 3268 break 3269 3270 pythia_log.close() 3271 3272 pydir = pjoin(self.options['pythia-pgs_path'], 'src') 3273 eradir = self.options['exrootanalysis_path'] 3274 madir = self.options['madanalysis_path'] 3275 td = self.options['td_path'] 3276 3277 3278 3279 3280 #Update the banner 3281 self.banner.add(pjoin(self.me_dir, 'Cards','pythia_card.dat')) 3282 if int(self.run_card['ickkw']): 3283 # Add the matched cross-section 3284 if 'MGGenerationInfo' in self.banner: 3285 self.banner['MGGenerationInfo'] += '# Matched Integrated weight (pb) : %s\n' % self.results.current['cross_pythia'] 3286 else: 3287 self.banner['MGGenerationInfo'] = '# Matched Integrated weight (pb) : %s\n' % self.results.current['cross_pythia'] 3288 banner_path = pjoin(self.me_dir, 'Events', self.run_name, '%s_%s_banner.txt' % (self.run_name, tag)) 3289 self.banner.write(banner_path) 3290 3291 # Creating LHE file 3292 self.run_hep2lhe(banner_path) 3293 if int(self.run_card['ickkw']): 3294 misc.gzip(pjoin(self.me_dir,'Events','beforeveto.tree'), 3295 stdout=pjoin(self.me_dir,'Events',self.run_name, tag+'_pythia_beforeveto.tree.gz')) 3296 if self.run_card['use_syst'] in self.true: 3297 # Calculate syscalc info based on syst.dat 3298 try: 3299 self.run_syscalc('Pythia') 3300 except SysCalcError, error: 3301 logger.error(str(error)) 3302 else: 3303 if os.path.exists(pjoin(self.me_dir,'Events', 'syst.dat')): 3304 # Store syst.dat 3305 misc.gzip(pjoin(self.me_dir,'Events', 'syst.dat'), 3306 stdout=pjoin(self.me_dir,'Events',self.run_name, tag + '_pythia_syst.dat.gz')) 3307 3308 # Store syscalc.dat 3309 if os.path.exists(pjoin(self.me_dir, 'Events', 'syscalc.dat')): 3310 filename = pjoin(self.me_dir, 'Events' ,self.run_name, 3311 '%s_syscalc.dat' % self.run_tag) 3312 misc.gzip(pjoin(self.me_dir, 'Events','syscalc.dat'), 3313 stdout = "%s.gz" % filename) 3314 3315 # Plot for pythia 3316 self.create_plot('Pythia') 3317 3318 if os.path.exists(pjoin(self.me_dir,'Events','pythia_events.lhe')): 3319 misc.gzip(pjoin(self.me_dir,'Events','pythia_events.lhe'), 3320 stdout=pjoin(self.me_dir,'Events', self.run_name,'%s_pythia_events.lhe.gz' % tag)) 3321 3322 self.update_status('finish', level='pythia', makehtml=False) 3323 self.exec_cmd('pgs --no_default', postcmd=False, printcmd=False) 3324 if self.options['delphes_path']: 3325 self.exec_cmd('delphes --no_default', postcmd=False, printcmd=False) 3326 self.print_results_in_shell(self.results.current)
3327 3328 3329 ################################################################################
3330 - def do_remove(self, line):
3331 """Remove one/all run or only part of it""" 3332 3333 args = self.split_arg(line) 3334 run, tag, mode = self.check_remove(args) 3335 if 'banner' in mode: 3336 mode.append('all') 3337 3338 3339 if run == 'all': 3340 # Check first if they are not a run with a name run. 3341 if os.path.exists(pjoin(self.me_dir, 'Events', 'all')): 3342 logger.warning('A run with name all exists. So we will not supress all processes.') 3343 else: 3344 for match in misc.glob(pjoin('*','*_banner.txt'), pjoin(self.me_dir, 'Events')): 3345 run = match.rsplit(os.path.sep,2)[1] 3346 if self.force: 3347 args.append('-f') 3348 try: 3349 self.exec_cmd('remove %s %s' % (run, ' '.join(args[1:]) ) ) 3350 except self.InvalidCmd, error: 3351 logger.info(error) 3352 pass # run already clear 3353 return 3354 3355 # Check that run exists 3356 if not os.path.exists(pjoin(self.me_dir, 'Events', run)): 3357 raise self.InvalidCmd('No run \'%s\' detected' % run) 3358 3359 try: 3360 self.resuls.def_current(run) 3361 self.update_status(' Cleaning %s' % run, level=None) 3362 except Exception: 3363 misc.sprint('fail to update results or html status') 3364 pass # Just ensure that html never makes crash this function 3365 3366 3367 # Found the file to delete 3368 3369 to_delete = misc.glob('*', pjoin(self.me_dir, 'Events', run)) 3370 to_delete += misc.glob('*', pjoin(self.me_dir, 'HTML', run)) 3371 # forbid the banner to be removed 3372 to_delete = [os.path.basename(f) for f in to_delete if 'banner' not in f] 3373 if tag: 3374 to_delete = [f for f in to_delete if tag in f] 3375 if 'parton' in mode or 'all' in mode: 3376 try: 3377 if self.results[run][0]['tag'] != tag: 3378 raise Exception, 'dummy' 3379 except Exception: 3380 pass 3381 else: 3382 nb_rm = len(to_delete) 3383 if os.path.exists(pjoin(self.me_dir, 'Events', run, 'events.lhe.gz')): 3384 to_delete.append('events.lhe.gz') 3385 if os.path.exists(pjoin(self.me_dir, 'Events', run, 'unweighted_events.lhe.gz')): 3386 to_delete.append('unweighted_events.lhe.gz') 3387 if os.path.exists(pjoin(self.me_dir, 'HTML', run,'plots_parton.html')): 3388 to_delete.append(pjoin(self.me_dir, 'HTML', run,'plots_parton.html')) 3389 if nb_rm != len(to_delete): 3390 logger.warning('Be carefull that partonic information are on the point to be removed.') 3391 if 'all' in mode: 3392 pass # delete everything 3393 else: 3394 if 'pythia' not in mode: 3395 to_delete = [f for f in to_delete if 'pythia' not in f] 3396 if 'pgs' not in mode: 3397 to_delete = [f for f in to_delete if 'pgs' not in f] 3398 if 'delphes' not in mode: 3399 to_delete = [f for f in to_delete if 'delphes' not in f] 3400 if 'parton' not in mode: 3401 to_delete = [f for f in to_delete if 'delphes' in f 3402 or 'pgs' in f 3403 or 'pythia' in f] 3404 if not self.force and len(to_delete): 3405 question = 'Do you want to delete the following files?\n %s' % \ 3406 '\n '.join(to_delete) 3407 ans = self.ask(question, 'y', choices=['y','n']) 3408 else: 3409 ans = 'y' 3410 3411 if ans == 'y': 3412 for file2rm in to_delete: 3413 if os.path.exists(pjoin(self.me_dir, 'Events', run, file2rm)): 3414 try: 3415 os.remove(pjoin(self.me_dir, 'Events', run, file2rm)) 3416 except Exception: 3417 shutil.rmtree(pjoin(self.me_dir, 'Events', run, file2rm)) 3418 else: 3419 try: 3420 os.remove(pjoin(self.me_dir, 'HTML', run, file2rm)) 3421 except Exception: 3422 shutil.rmtree(pjoin(self.me_dir, 'HTML', run, file2rm)) 3423 3424 3425 3426 # Remove file in SubProcess directory 3427 if 'all' in mode or 'channel' in mode: 3428 try: 3429 if tag and self.results[run][0]['tag'] != tag: 3430 raise Exception, 'dummy' 3431 except Exception: 3432 pass 3433 else: 3434 to_delete = misc.glob('%s*' % run, pjoin(self.me_dir, 'SubProcesses')) 3435 to_delete += misc.glob(pjoin('*','%s*' % run), pjoin(self.me_dir, 'SubProcesses')) 3436 to_delete += misc.glob(pjoin('*','*','%s*' % run), pjoin(self.me_dir, 'SubProcesses')) 3437 3438 if self.force or len(to_delete) == 0: 3439 ans = 'y' 3440 else: 3441 question = 'Do you want to delete the following files?\n %s' % \ 3442 '\n '.join(to_delete) 3443 ans = self.ask(question, 'y', choices=['y','n']) 3444 3445 if ans == 'y': 3446 for file2rm in to_delete: 3447 os.remove(file2rm) 3448 3449 if 'banner' in mode: 3450 to_delete = misc.glob('*', pjoin(self.me_dir, 'Events', run)) 3451 if tag: 3452 # remove banner 3453 try: 3454 os.remove(pjoin(self.me_dir, 'Events',run,'%s_%s_banner.txt' % (run,tag))) 3455 except Exception: 3456 logger.warning('fail to remove the banner') 3457 # remove the run from the html output 3458 if run in self.results: 3459 self.results.delete_run(run, tag) 3460 return 3461 elif any(['banner' not in os.path.basename(p) for p in to_delete]): 3462 if to_delete: 3463 raise MadGraph5Error, '''Some output still exists for this run. 3464 Please remove those output first. Do for example: 3465 remove %s all banner 3466 ''' % run 3467 else: 3468 shutil.rmtree(pjoin(self.me_dir, 'Events',run)) 3469 if run in self.results: 3470 self.results.delete_run(run) 3471 return 3472 else: 3473 logger.info('''The banner is not removed. In order to remove it run: 3474 remove %s all banner %s''' % (run, tag and '--tag=%s ' % tag or '')) 3475 3476 # update database. 3477 self.results.clean(mode, run, tag) 3478 self.update_status('', level='all')
3479 3480 3481 3482 ############################################################################
3483 - def do_plot(self, line):
3484 """Create the plot for a given run""" 3485 3486 # Since in principle, all plot are already done automaticaly 3487 self.store_result() 3488 args = self.split_arg(line) 3489 # Check argument's validity 3490 self.check_plot(args) 3491 logger.info('plot for run %s' % self.run_name) 3492 if not self.force: 3493 self.ask_edit_cards([], args, plot=True) 3494 3495 if any([arg in ['all','parton'] for arg in args]): 3496 filename = pjoin(self.me_dir, 'Events', self.run_name, 'unweighted_events.lhe') 3497 if os.path.exists(filename+'.gz'): 3498 misc.gunzip('%s.gz' % filename, keep=True) 3499 if os.path.exists(filename): 3500 files.ln(filename, pjoin(self.me_dir, 'Events')) 3501 self.create_plot('parton') 3502 if not os.path.exists(filename+'.gz'): 3503 misc.gzip(pjoin(self.me_dir, 'Events', 'unweighted_events.lhe'), 3504 stdout= "%s.gz" % filename) 3505 else: 3506 try: 3507 os.remove(pjoin(self.me_dir, 'Events', 'unweighted_events.lhe')) 3508 os.remove(filename) 3509 except Exception: 3510 pass 3511 else: 3512 logger.info('No valid files for partonic plot') 3513 3514 if any([arg in ['all','pythia'] for arg in args]): 3515 filename = pjoin(self.me_dir, 'Events' ,self.run_name, 3516 '%s_pythia_events.lhe' % self.run_tag) 3517 if os.path.exists(filename+'.gz'): 3518 misc.gunzip("%s.gz" % filename) 3519 if os.path.exists(filename): 3520 shutil.move(filename, pjoin(self.me_dir, 'Events','pythia_events.lhe')) 3521 self.create_plot('Pythia') 3522 misc.gzip(pjoin(self.me_dir, 'Events','pythia_events.lhe'), 3523 stdout= "%s.gz" % filename) 3524 else: 3525 logger.info('No valid files for pythia plot') 3526 3527 3528 if any([arg in ['all','pgs'] for arg in args]): 3529 filename = pjoin(self.me_dir, 'Events', self.run_name, 3530 '%s_pgs_events.lhco' % self.run_tag) 3531 if os.path.exists(filename+'.gz'): 3532 misc.gunzip("%s.gz" % filename) 3533 if os.path.exists(filename): 3534 self.create_plot('PGS') 3535 misc.gzip(filename) 3536 else: 3537 logger.info('No valid files for pgs plot') 3538 3539 if any([arg in ['all','delphes'] for arg in args]): 3540 filename = pjoin(self.me_dir, 'Events', self.run_name, 3541 '%s_delphes_events.lhco' % self.run_tag) 3542 if os.path.exists(filename+'.gz'): 3543 misc.gunzip("%s.gz" % filename) 3544 if os.path.exists(filename): 3545 self.create_plot('Delphes') 3546 misc.gzip(filename) 3547 else: 3548 logger.info('No valid files for delphes plot')
3549 3550 ############################################################################
3551 - def do_syscalc(self, line):
3552 """Evaluate systematics variation weights for a given run""" 3553 3554 # Since in principle, all systematics run are already done automaticaly 3555 self.store_result() 3556 args = self.split_arg(line) 3557 # Check argument's validity 3558 self.check_syscalc(args) 3559 if self.ninitial == 1: 3560 logger.error('SysCalc can\'t be run for decay processes') 3561 return 3562 3563 logger.info('Calculating systematics for run %s' % self.run_name) 3564 3565 self.ask_edit_cards(['run_card'], args) 3566 self.run_card = banner_mod.RunCard(pjoin(self.me_dir, 'Cards', 'run_card.dat')) 3567 3568 if any([arg in ['all','parton'] for arg in args]): 3569 filename = pjoin(self.me_dir, 'Events', self.run_name, 'unweighted_events.lhe') 3570 if os.path.exists(filename+'.gz'): 3571 misc.gunzip("%s.gz" % filename) 3572 if os.path.exists(filename): 3573 shutil.move(filename, pjoin(self.me_dir, 'Events', 'unweighted_events.lhe')) 3574 self.run_syscalc('parton') 3575 misc.gzip(pjoin(self.me_dir, 'Events', 'unweighted_events.lhe'), 3576 stdout="%s.gz" % filename) 3577 else: 3578 logger.info('No valid files for parton level systematics run.') 3579 3580 if any([arg in ['all','pythia'] for arg in args]): 3581 filename = pjoin(self.me_dir, 'Events' ,self.run_name, 3582 '%s_pythia_syst.dat' % self.run_tag) 3583 if os.path.exists(filename+'.gz'): 3584 misc.gunzip("%s.gz" % filename) 3585 if os.path.exists(filename): 3586 shutil.move(filename, pjoin(self.me_dir, 'Events','syst.dat')) 3587 try: 3588 self.run_syscalc('Pythia') 3589 except SysCalcError, error: 3590 logger.warning(str(error)) 3591 return 3592 misc.gzip(pjoin(self.me_dir, 'Events','syst.dat'), "%s.gz" % filename) 3593 filename = pjoin(self.me_dir, 'Events' ,self.run_name, 3594 '%s_syscalc.dat' % self.run_tag) 3595 misc.gzip(pjoin(self.me_dir, 'Events','syscalc.dat'), 3596 stdout=filename) 3597 else: 3598 logger.info('No valid files for pythia level')
3599 3600
3601 - def store_result(self):
3602 """ tar the pythia results. This is done when we are quite sure that 3603 the pythia output will not be use anymore """ 3604 3605 if not self.run_name: 3606 return 3607 3608 self.results.save() 3609 3610 3611 if not self.to_store: 3612 return 3613 3614 tag = self.run_card['run_tag'] 3615 self.update_status('storring files of previous run', level=None,\ 3616 error=True) 3617 if 'event' in self.to_store: 3618 if not os.path.exists(pjoin(self.me_dir, 'Events',self.run_name, 'unweighted_events.lhe.gz')) and\ 3619 os.path.exists(pjoin(self.me_dir, 'Events',self.run_name, 'unweighted_events.lhe')): 3620 logger.info("gzipping output file: unweighted_events.lhe") 3621 misc.gzip(pjoin(self.me_dir,'Events',self.run_name,"unweighted_events.lhe")) 3622 if os.path.exists(pjoin(self.me_dir,'Events','reweight.lhe')): 3623 os.remove(pjoin(self.me_dir,'Events', 'reweight.lhe')) 3624 3625 if 'pythia' in self.to_store: 3626 self.update_status('Storing Pythia files of previous run', level='pythia', error=True) 3627 3628 p = pjoin(self.me_dir,'Events') 3629 n = self.run_name 3630 t = tag 3631 misc.gzip(pjoin(p,'pythia_events.hep'), 3632 stdout=pjoin(p,'%s/%s_pythia_events.hep' % (n,t))) 3633 3634 self.to_store.remove('pythia') 3635 self.update_status('Done', level='pythia',makehtml=False,error=True) 3636 3637 self.to_store = []
3638
3639 - def launch_job(self,exe, cwd=None, stdout=None, argument = [], remaining=0, 3640 run_type='', mode=None, **opt):
3641 """ """ 3642 argument = [str(arg) for arg in argument] 3643 if mode is None: 3644 mode = self.cluster_mode 3645 3646 # ensure that exe is executable 3647 if os.path.exists(exe) and not os.access(exe, os.X_OK): 3648 os.system('chmod +x %s ' % exe) 3649 elif (cwd and os.path.exists(pjoin(cwd, exe))) and not \ 3650 os.access(pjoin(cwd, exe), os.X_OK): 3651 os.system('chmod +x %s ' % pjoin(cwd, exe)) 3652 3653 if mode == 0: 3654 self.update_status((remaining, 1, 3655 self.total_jobs - remaining -1, run_type), level=None, force=False) 3656 start = time.time() 3657 #os.system('cd %s; ./%s' % (cwd,exe)) 3658 status = misc.call([exe] + argument, cwd=cwd, stdout=stdout, **opt) 3659 logger.info('%s run in %f s' % (exe, time.time() -start)) 3660 if status: 3661 raise MadGraph5Error, '%s didn\'t stop properly. Stop all computation' % exe 3662 3663 3664 elif mode in [1,2]: 3665 exename = os.path.basename(exe) 3666 # For condor cluster, create the input/output files 3667 if 'ajob' in exename: 3668 input_files = ['madevent','input_app.txt','symfact.dat','iproc.dat', 3669 pjoin(self.me_dir, 'SubProcesses','randinit')] 3670 if os.path.exists(pjoin(self.me_dir,'SubProcesses', 3671 'MadLoop5_resources.tar.gz')) and cluster.need_transfer(self.options): 3672 input_files.append(pjoin(self.me_dir,'SubProcesses', 'MadLoop5_resources.tar.gz')) 3673 3674 output_files = [] 3675 required_output = [] 3676 3677 3678 #Find the correct PDF input file 3679 input_files.append(self.get_pdf_input_filename()) 3680 3681 #Find the correct ajob 3682 Gre = re.compile("\s*j=(G[\d\.\w]+)") 3683 origre = re.compile("grid_directory=(G[\d\.\w]+)") 3684 try : 3685 fsock = open(exe) 3686 except Exception: 3687 fsock = open(pjoin(cwd,exe)) 3688 text = fsock.read() 3689 output_files = Gre.findall(text) 3690 if not output_files: 3691 Ire = re.compile("for i in ([\d\.\s]*) ; do") 3692 data = Ire.findall(text) 3693 data = ' '.join(data).split() 3694 for nb in data: 3695 output_files.append('G%s' % nb) 3696 required_output.append('G%s/results.dat' % nb) 3697 else: 3698 for G in output_files: 3699 if os.path.isdir(pjoin(cwd,G)): 3700 input_files.append(G) 3701 required_output.append('%s/results.dat' % G) 3702 3703 if origre.search(text): 3704 G_grid = origre.search(text).groups()[0] 3705 input_files.append(pjoin(G_grid, 'ftn26')) 3706 3707 #submitting 3708 self.cluster.submit2(exe, stdout=stdout, cwd=cwd, 3709 input_files=input_files, output_files=output_files, 3710 required_output=required_output) 3711 elif 'survey' in exename: 3712 input_files = ['madevent','input_app.txt','symfact.dat','iproc.dat', 3713 pjoin(self.me_dir, 'SubProcesses','randinit')] 3714 if os.path.exists(pjoin(self.me_dir,'SubProcesses', 3715 'MadLoop5_resources.tar.gz')) and cluster.need_transfer(self.options): 3716 input_files.append(pjoin(self.me_dir,'SubProcesses', 3717 'MadLoop5_resources.tar.gz')) 3718 3719 #Find the correct PDF input file 3720 input_files.append(self.get_pdf_input_filename()) 3721 3722 3723 output_files = [] 3724 required_output = [] 3725 3726 #Find the correct ajob 3727 suffix = "_%s" % int(float(argument[0])) 3728 if suffix == '_0': 3729 suffix = '' 3730 output_files = ['G%s%s' % (i, suffix) for i in argument[1:]] 3731 for G in output_files: 3732 required_output.append('%s/results.dat' % G) 3733 3734 # add the grid information if needed 3735 for G in output_files: 3736 if '.' in argument[0]: 3737 offset = int(str(argument[0]).split('.')[1]) 3738 else: 3739 offset = 0 3740 3741 if offset ==0 or offset == int(float(argument[0])): 3742 if os.path.exists(pjoin(cwd, G, 'input_app.txt')): 3743 os.remove(pjoin(cwd, G, 'input_app.txt')) 3744 3745 if os.path.exists(os.path.realpath(pjoin(cwd, G, 'ftn25'))): 3746 if offset == 0 or offset == int(float(argument[0])): 3747 os.remove(pjoin(cwd, G, 'ftn25')) 3748 continue 3749 else: 3750 input_files.append(pjoin(cwd, G, 'ftn25')) 3751 input_files.remove('input_app.txt') 3752 input_files.append(pjoin(cwd, G, 'input_app.txt')) 3753 elif os.path.lexists(pjoin(cwd, G, 'ftn25')): 3754 try: 3755 os.remove(pjoin(cwd,G,'ftn25')) 3756 except: 3757 pass 3758 3759 #submitting 3760 self.cluster.cluster_submit(exe, stdout=stdout, cwd=cwd, argument=argument, 3761 input_files=input_files, output_files=output_files, 3762 required_output=required_output, **opt) 3763 elif "refine_splitted.sh" in exename: 3764 input_files = ['madevent','symfact.dat','iproc.dat', 3765 pjoin(self.me_dir, 'SubProcesses','randinit')] 3766 3767 if os.path.exists(pjoin(self.me_dir,'SubProcesses', 3768 'MadLoop5_resources.tar.gz')) and cluster.need_transfer(self.options): 3769 input_files.append(pjoin(self.me_dir,'SubProcesses', 3770 'MadLoop5_resources.tar.gz')) 3771 3772 #Find the correct PDF input file 3773 input_files.append(self.get_pdf_input_filename()) 3774 3775 3776 output_files = [argument[0]] 3777 required_output = [] 3778 for G in output_files: 3779 required_output.append('%s/results.dat' % G) 3780 input_files.append(pjoin(argument[1], "input_app.txt")) 3781 input_files.append(pjoin(argument[1], "ftn26")) 3782 3783 #submitting 3784 self.cluster.cluster_submit(exe, stdout=stdout, cwd=cwd, argument=argument, 3785 input_files=input_files, output_files=output_files, 3786 required_output=required_output, **opt) 3787 3788 3789 3790 else: 3791 self.cluster.submit(exe, argument=argument, stdout=stdout, cwd=cwd, **opt)
3792 3793 3794 ############################################################################
3795 - def find_madevent_mode(self):
3796 """Find if Madevent is in Group mode or not""" 3797 3798 # The strategy is too look in the files Source/run_configs.inc 3799 # if we found: ChanPerJob=3 then it's a group mode. 3800 file_path = pjoin(self.me_dir, 'Source', 'run_config.inc') 3801 text = open(file_path).read() 3802 if re.search(r'''s*parameter\s+\(ChanPerJob=2\)''', text, re.I+re.M): 3803 return 'group' 3804 else: 3805 return 'v4'
3806 3807 ############################################################################
3808 - def monitor(self, run_type='monitor', mode=None, html=False):
3809 """ monitor the progress of running job """ 3810 3811 3812 starttime = time.time() 3813 if mode is None: 3814 mode = self.cluster_mode 3815 if mode > 0: 3816 if html: 3817 update_status = lambda idle, run, finish: \ 3818 self.update_status((idle, run, finish, run_type), level=None, 3819 force=False, starttime=starttime) 3820 update_first = lambda idle, run, finish: \ 3821 self.update_status((idle, run, finish, run_type), level=None, 3822 force=True, starttime=starttime) 3823 else: 3824 update_status = lambda idle, run, finish: None 3825 update_first = None 3826 try: 3827 self.cluster.wait(self.me_dir, update_status, update_first=update_first) 3828 except Exception, error: 3829 logger.info(error) 3830 if not self.force: 3831 ans = self.ask('Cluster Error detected. Do you want to clean the queue? ("c"=continue the run anyway)', 3832 default = 'y', choices=['y','n', 'c']) 3833 else: 3834 ans = 'y' 3835 if ans == 'y': 3836 self.cluster.remove() 3837 elif ans == 'c': 3838 return self.monitor(run_type=run_type, mode=mode, html=html) 3839 raise 3840 except KeyboardInterrupt, error: 3841 self.cluster.remove() 3842 raise
3843 3844 3845 3846 ############################################################################
3847 - def configure_directory(self, html_opening=True):
3848 """ All action require before any type of run """ 3849 3850 3851 # Basic check 3852 assert os.path.exists(pjoin(self.me_dir,'SubProcesses')) 3853 3854 # environmental variables to be included in make_opts 3855 self.make_opts_var = {} 3856 3857 #see when the last file was modified 3858 time_mod = max([os.path.getctime(pjoin(self.me_dir,'Cards','run_card.dat')), 3859 os.path.getctime(pjoin(self.me_dir,'Cards','param_card.dat'))]) 3860 if self.configured > time_mod and hasattr(self, 'random'): 3861 return 3862 else: 3863 self.configured = time.time() 3864 self.update_status('compile directory', level=None, update_results=True) 3865 if self.options['automatic_html_opening'] and html_opening: 3866 misc.open_file(os.path.join(self.me_dir, 'crossx.html')) 3867 self.options['automatic_html_opening'] = False 3868 #open only once the web page 3869 # Change current working directory 3870 self.launching_dir = os.getcwd() 3871 3872 # Check if we need the MSSM special treatment 3873 model = self.find_model_name() 3874 if model == 'mssm' or model.startswith('mssm-'): 3875 param_card = pjoin(self.me_dir, 'Cards','param_card.dat') 3876 mg5_param = pjoin(self.me_dir, 'Source', 'MODEL', 'MG5_param.dat') 3877 check_param_card.convert_to_mg5card(param_card, mg5_param) 3878 check_param_card.check_valid_param_card(mg5_param) 3879 3880 # limit the number of event to 100k 3881 self.check_nb_events() 3882 3883 # this is in order to avoid conflicts between runs with and without 3884 # lhapdf 3885 misc.compile(['clean4pdf'], cwd = pjoin(self.me_dir, 'Source')) 3886 3887 # set lhapdf. 3888 if self.run_card['pdlabel'] == "lhapdf": 3889 self.make_opts_var['lhapdf'] = 'True' 3890 self.link_lhapdf(pjoin(self.me_dir,'lib')) 3891 pdfsetsdir = self.get_lhapdf_pdfsetsdir() 3892 lhaid_list = [int(self.run_card['lhaid'])] 3893 self.copy_lhapdf_set(lhaid_list, pdfsetsdir) 3894 if self.run_card['pdlabel'] != "lhapdf": 3895 self.pdffile = None 3896 self.make_opts_var['lhapdf'] = "" 3897 3898 # set random number 3899 if self.run_card['iseed'] != 0: 3900 self.random = int(self.run_card['iseed']) 3901 self.run_card['iseed'] = 0 3902 # Reset seed in run_card to 0, to ensure that following runs 3903 # will be statistically independent 3904 self.run_card.write(pjoin(self.me_dir, 'Cards','run_card.dat')) 3905 elif os.path.exists(pjoin(self.me_dir,'SubProcesses','randinit')): 3906 for line in open(pjoin(self.me_dir,'SubProcesses','randinit')): 3907 data = line.split('=') 3908 assert len(data) ==2 3909 self.random = int(data[1]) 3910 break 3911 else: 3912 self.random = random.randint(1, 30107) 3913 3914 if self.run_card['ickkw'] == 2: 3915 logger.info('Running with CKKW matching') 3916 self.treat_CKKW_matching() 3917 3918 # add the make_opts_var to make_opts 3919 self.update_make_opts() 3920 3921 # create param_card.inc and run_card.inc 3922 self.do_treatcards('') 3923 3924 logger.info("compile Source Directory") 3925 # Compile 3926 for name in [ 'all', '../bin/internal/combine_events']: 3927 self.compile(arg=[name], cwd=os.path.join(self.me_dir, 'Source'))
3928 3929 3930 ############################################################################ 3931 ## HELPING ROUTINE 3932 ############################################################################ 3933 @staticmethod
3934 - def check_dir(path, default=''):
3935 """check if the directory exists. if so return the path otherwise the 3936 default""" 3937 3938 if os.path.isdir(path): 3939 return path 3940 else: 3941 return default
3942 3943 ############################################################################
3944 - def get_Pdir(self):
3945 """get the list of Pdirectory if not yet saved.""" 3946 3947 if hasattr(self, "Pdirs"): 3948 if self.me_dir in self.Pdirs[0]: 3949 return self.Pdirs 3950 self.Pdirs = [pjoin(self.me_dir, 'SubProcesses', l.strip()) 3951 for l in open(pjoin(self.me_dir,'SubProcesses', 'subproc.mg'))] 3952 return self.Pdirs
3953 3954 ############################################################################
3955 - def get_Gdir(self):
3956 """get the list of Gdirectory if not yet saved.""" 3957 3958 if hasattr(self, "Gdirs"): 3959 if self.me_dir in self.Gdirs[0]: 3960 return self.Gdirs 3961 3962 Pdirs = self.get_Pdir() 3963 Gdirs = [] 3964 for P in Pdirs: 3965 for line in open(pjoin(P, "symfact.dat")): 3966 tag, mfactor = line.split() 3967 Gdirs.append( (pjoin(P, "G%s" % tag), int(mfactor)) ) 3968 3969 3970 self.Gdirs = Gdirs 3971 return self.Gdirs
3972 3973 ############################################################################
3974 - def set_run_name(self, name, tag=None, level='parton', reload_card=False, 3975 allow_new_tag=True):
3976 """define the run name, the run_tag, the banner and the results.""" 3977 3978 # when are we force to change the tag new_run:previous run requiring changes 3979 upgrade_tag = {'parton': ['parton','pythia','pgs','delphes'], 3980 'pythia': ['pythia','pgs','delphes'], 3981 'pgs': ['pgs'], 3982 'delphes':['delphes'], 3983 'plot':[], 3984 'syscalc':[]} 3985 3986 3987 3988 if name == self.run_name: 3989 if reload_card: 3990 run_card = pjoin(self.me_dir, 'Cards','run_card.dat') 3991 self.run_card = banner_mod.RunCard(run_card) 3992 3993 #check if we need to change the tag 3994 if tag: 3995 self.run_card['run_tag'] = tag 3996 self.run_tag = tag 3997 self.results.add_run(self.run_name, self.run_card) 3998 else: 3999 for tag in upgrade_tag[level]: 4000 if getattr(self.results[self.run_name][-1], tag): 4001 tag = self.get_available_tag() 4002 self.run_card['run_tag'] = tag 4003 self.run_tag = tag 4004 self.results.add_run(self.run_name, self.run_card) 4005 break 4006 return # Nothing to do anymore 4007 4008 # save/clean previous run 4009 if self.run_name: 4010 self.store_result() 4011 # store new name 4012 self.run_name = name 4013 4014 new_tag = False 4015 # First call for this run -> set the banner 4016 self.banner = banner_mod.recover_banner(self.results, level, name) 4017 if 'mgruncard' in self.banner: 4018 self.run_card = self.banner.charge_card('run_card') 4019 else: 4020 # Read run_card 4021 run_card = pjoin(self.me_dir, 'Cards','run_card.dat') 4022 self.run_card = banner_mod.RunCard(run_card) 4023 4024 if tag: 4025 self.run_card['run_tag'] = tag 4026 new_tag = True 4027 elif not self.run_name in self.results and level =='parton': 4028 pass # No results yet, so current tag is fine 4029 elif not self.run_name in self.results: 4030 #This is only for case when you want to trick the interface 4031 logger.warning('Trying to run data on unknown run.') 4032 self.results.add_run(name, self.run_card) 4033 self.results.update('add run %s' % name, 'all', makehtml=False) 4034 else: 4035 for tag in upgrade_tag[level]: 4036 4037 if getattr(self.results[self.run_name][-1], tag): 4038 # LEVEL is already define in the last tag -> need to switch tag 4039 tag = self.get_available_tag() 4040 self.run_card['run_tag'] = tag 4041 new_tag = True 4042 break 4043 if not new_tag: 4044 # We can add the results to the current run 4045 tag = self.results[self.run_name][-1]['tag'] 4046 self.run_card['run_tag'] = tag # ensure that run_tag is correct 4047 4048 if allow_new_tag and (name in self.results and not new_tag): 4049 self.results.def_current(self.run_name) 4050 else: 4051 self.results.add_run(self.run_name, self.run_card) 4052 4053 self.run_tag = self.run_card['run_tag'] 4054 4055 # Return the tag of the previous run having the required data for this 4056 # tag/run to working wel. 4057 if level == 'parton': 4058 return 4059 elif level == 'pythia': 4060 return self.results[self.run_name][0]['tag'] 4061 else: 4062 for i in range(-1,-len(self.results[self.run_name])-1,-1): 4063 tagRun = self.results[self.run_name][i] 4064 if tagRun.pythia: 4065 return tagRun['tag']
4066 4067 4068 4069 4070 4071 4072 4073 4074 ############################################################################
4075 - def find_model_name(self):
4076 """ return the model name """ 4077 if hasattr(self, 'model_name'): 4078 return self.model_name 4079 4080 model = 'sm' 4081 proc = [] 4082 for line in open(os.path.join(self.me_dir,'Cards','proc_card_mg5.dat')): 4083 line = line.split('#')[0] 4084 #line = line.split('=')[0] 4085 if line.startswith('import') and 'model' in line: 4086 model = line.split()[2] 4087 proc = [] 4088 elif line.startswith('generate'): 4089 proc.append(line.split(None,1)[1]) 4090 elif line.startswith('add process'): 4091 proc.append(line.split(None,2)[2]) 4092 4093 self.model = model 4094 self.process = proc 4095 return model
4096 4097 4098 ############################################################################
4099 - def check_nb_events(self):
4100 """Find the number of event in the run_card, and check that this is not 4101 too large""" 4102 4103 4104 nb_event = int(self.run_card['nevents']) 4105 if nb_event > 1000000: 4106 logger.warning("Attempting to generate more than 1M events") 4107 logger.warning("Limiting number to 1M. Use multi_run for larger statistics.") 4108 path = pjoin(self.me_dir, 'Cards', 'run_card.dat') 4109 os.system(r"""perl -p -i.bak -e "s/\d+\s*=\s*nevents/1000000 = nevents/" %s""" \ 4110 % path) 4111 self.run_card['nevents'] = 1000000 4112 4113 return
4114 4115 4116 ############################################################################
4117 - def update_random(self):
4118 """ change random number""" 4119 4120 self.random += 3 4121 if self.random > 30081*30081: # can't use too big random number 4122 raise MadGraph5Error,\ 4123 'Random seed too large ' + str(self.random) + ' > 30081*30081'
4124 4125 ############################################################################
4126 - def save_random(self):
4127 """save random number in appropirate file""" 4128 4129 fsock = open(pjoin(self.me_dir, 'SubProcesses','randinit'),'w') 4130 fsock.writelines('r=%s\n' % self.random)
4131
4132 - def do_quit(self, *args, **opts):
4133 4134 common_run.CommonRunCmd.do_quit(self, *args, **opts) 4135 return CmdExtended.do_quit(self, *args, **opts)
4136 4137 ############################################################################
4138 - def treat_CKKW_matching(self):
4139 """check for ckkw""" 4140 4141 lpp1 = self.run_card['lpp1'] 4142 lpp2 = self.run_card['lpp2'] 4143 e1 = self.run_card['ebeam1'] 4144 e2 = self.run_card['ebeam2'] 4145 pd = self.run_card['pdlabel'] 4146 lha = self.run_card['lhaid'] 4147 xq = self.run_card['xqcut'] 4148 translation = {'e1': e1, 'e2':e2, 'pd':pd, 4149 'lha':lha, 'xq':xq} 4150 4151 if lpp1 or lpp2: 4152 # Remove ':s from pd 4153 if pd.startswith("'"): 4154 pd = pd[1:] 4155 if pd.endswith("'"): 4156 pd = pd[:-1] 4157 4158 if xq >2 or xq ==2: 4159 xq = 2 4160 4161 # find data file 4162 if pd == "lhapdf": 4163 issudfile = 'lib/issudgrid-%(e1)s-%(e2)s-%(pd)s-%(lha)s-%(xq)s.dat.gz' 4164 else: 4165 issudfile = 'lib/issudgrid-%(e1)s-%(e2)s-%(pd)s-%(xq)s.dat.gz' 4166 if self.web: 4167 issudfile = pjoin(self.webbin, issudfile % translation) 4168 else: 4169 issudfile = pjoin(self.me_dir, issudfile % translation) 4170 4171 logger.info('Sudakov grid file: %s' % issudfile) 4172 4173 # check that filepath exists 4174 if os.path.exists(issudfile): 4175 path = pjoin(self.me_dir, 'lib', 'issudgrid.dat') 4176 misc.gunzip(issudfile, keep=True, stdout=path) 4177 else: 4178 msg = 'No sudakov grid file for parameter choice. Start to generate it. This might take a while' 4179 logger.info(msg) 4180 self.update_status('GENERATE SUDAKOF GRID', level='parton') 4181 4182 for i in range(-2,6): 4183 self.cluster.submit('%s/gensudgrid ' % self.dirbin, 4184 arguments = [i], 4185 cwd=self.me_dir, 4186 stdout=open(pjoin(self.me_dir, 'gensudgrid%s.log' % i,'w'))) 4187 self.monitor() 4188 for i in range(-2,6): 4189 path = pjoin(self.me_dir, 'lib', 'issudgrid.dat') 4190 os.system('cat %s/gensudgrid%s.log >> %s' % (self.me_dir, path)) 4191 misc.gzip(path, stdout=issudfile)
4192 4193 ############################################################################
4194 - def create_root_file(self, input='unweighted_events.lhe', 4195 output='unweighted_events.root' ):
4196 """create the LHE root file """ 4197 self.update_status('Creating root files', level='parton') 4198 4199 eradir = self.options['exrootanalysis_path'] 4200 try: 4201 misc.call(['%s/ExRootLHEFConverter' % eradir, 4202 input, output], 4203 cwd=pjoin(self.me_dir, 'Events')) 4204 except Exception: 4205 logger.warning('fail to produce Root output [problem with ExRootAnalysis]')
4206
4207 - def run_syscalc(self, mode='parton', event_path=None, output=None):
4208 """create the syscalc output""" 4209 4210 if self.run_card['use_syst'] not in self.true: 4211 return 4212 4213 scdir = self.options['syscalc_path'] 4214 if not scdir or not os.path.exists(scdir): 4215 return 4216 logger.info('running syscalc on mode %s' % mode) 4217 4218 4219 # Check that all pdfset are correctly installed 4220 lhaid = [self.run_card.get_lhapdf_id()] 4221 sys_pdf = self.run_card['sys_pdf'].split('&&') 4222 lhaid += [l.split()[0] for l in sys_pdf] 4223 try: 4224 pdfsets_dir = self.get_lhapdf_pdfsetsdir() 4225 except Exception, error: 4226 logger.debug(str(error)) 4227 logger.warning('Systematic computation requires lhapdf to run. Bypass SysCalc') 4228 return 4229 4230 # Copy all the relevant PDF sets 4231 [self.copy_lhapdf_set([onelha], pdfsets_dir) for onelha in lhaid] 4232 4233 4234 4235 tag = self.run_card['run_tag'] 4236 card = pjoin(self.me_dir, 'bin','internal', 'syscalc_card.dat') 4237 template = open(pjoin(self.me_dir, 'bin','internal', 'syscalc_template.dat')).read() 4238 self.run_card['sys_pdf'] = self.run_card['sys_pdf'].split('#',1)[0].replace('&&',' \n ') 4239 4240 if self.run_card['sys_pdf'].lower() in ['', 'f', 'false', 'none', '.false.']: 4241 self.run_card['sys_pdf'] = '' 4242 if self.run_card['sys_alpsfact'].lower() in ['', 'f', 'false', 'none','.false.']: 4243 self.run_card['sys_alpsfact'] = '' 4244 4245 4246 4247 4248 # check if the scalecorrelation parameter is define: 4249 if not 'sys_scalecorrelation' in self.run_card: 4250 self.run_card['sys_scalecorrelation'] = -1 4251 open(card,'w').write(template % self.run_card) 4252 4253 if not os.path.exists(card): 4254 return False 4255 4256 4257 4258 event_dir = pjoin(self.me_dir, 'Events') 4259 4260 if not event_path: 4261 if mode == 'parton': 4262 event_path = pjoin(event_dir,self.run_name, 'unweighted_events.lhe') 4263 if not (os.path.exists(event_path) or os.path.exists(event_path+".gz")): 4264 event_path = pjoin(event_dir, 'unweighted_events.lhe') 4265 output = pjoin(event_dir, 'syscalc.lhe') 4266 elif mode == 'Pythia': 4267 if 'mgpythiacard' in self.banner: 4268 pat = re.compile('''^\s*qcut\s*=\s*([\+\-\d.e]*)''', re.M+re.I) 4269 data = pat.search(self.banner['mgpythiacard']) 4270 if data: 4271 qcut = float(data.group(1)) 4272 xqcut = abs(self.run_card['xqcut']) 4273 for value in self.run_card['sys_matchscale'].split(): 4274 if float(value) < qcut: 4275 raise SysCalcError, 'qcut value for sys_matchscale lower than qcut in pythia_card. Bypass syscalc' 4276 if float(value) < xqcut: 4277 raise SysCalcError, 'qcut value for sys_matchscale lower than xqcut in run_card. Bypass syscalc' 4278 4279 4280 event_path = pjoin(event_dir,'syst.dat') 4281 output = pjoin(event_dir, 'syscalc.dat') 4282 else: 4283 raise self.InvalidCmd, 'Invalid mode %s' % mode 4284 4285 if not os.path.exists(event_path): 4286 if os.path.exists(event_path+'.gz'): 4287 misc.gunzip(event_path+'.gz') 4288 else: 4289 raise SysCalcError, 'Events file %s does not exits' % event_path 4290 4291 self.update_status('Calculating systematics for %s level' % mode, level = mode.lower()) 4292 try: 4293 proc = misc.call([os.path.join(scdir, 'sys_calc'), 4294 event_path, card, output], 4295 stdout = open(pjoin(event_dir, self.run_name, '%s_%s_syscalc.log' % (tag,mode)),'w'), 4296 stderr = subprocess.STDOUT, 4297 cwd=event_dir) 4298 # Wait 5 s to make sure file is finished writing 4299 time.sleep(5) 4300 except OSError, error: 4301 logger.error('fail to run syscalc: %s. Please check that SysCalc is correctly installed.' % error) 4302 else: 4303 if not os.path.exists(output): 4304 logger.warning('SysCalc Failed. Please read the associate log to see the reason. Did you install the associate PDF set?') 4305 elif mode == 'parton': 4306 files.mv(output, event_path) 4307 4308 self.update_status('End syscalc for %s level' % mode, level = mode.lower(), 4309 makehtml=False) 4310 4311 return True
4312 4313 4314 4315 ############################################################################
4316 - def ask_run_configuration(self, mode=None, args=[]):
4317 """Ask the question when launching generate_events/multi_run""" 4318 4319 available_mode = ['0'] 4320 void = 'NOT INSTALLED' 4321 switch_order = ['pythia', 'pgs', 'delphes', 'madspin', 'reweight'] 4322 switch = {'pythia': void, 'pgs': void, 'delphes': void, 4323 'madspin': void, 'reweight': void} 4324 description = {'pythia': 'Run the pythia shower/hadronization:', 4325 'pgs': 'Run PGS as detector simulator:', 4326 'delphes':'Run Delphes as detector simulator:', 4327 'madspin':'Decay particles with the MadSpin module:', 4328 'reweight':'Add weights to the events based on changing model parameters:', 4329 } 4330 force_switch = {('pythia', 'OFF'): {'pgs': 'OFF', 'delphes': 'OFF'}, 4331 ('pgs', 'ON'): {'pythia':'ON'}, 4332 ('delphes', 'ON'): {'pythia': 'ON'}} 4333 switch_assign = lambda key, value: switch.__setitem__(key, value if switch[key] != void else void ) 4334 4335 4336 # Init the switch value according to the current status 4337 if self.options['pythia-pgs_path']: 4338 available_mode.append('1') 4339 available_mode.append('2') 4340 if os.path.exists(pjoin(self.me_dir,'Cards','pythia_card.dat')): 4341 switch['pythia'] = 'ON' 4342 else: 4343 switch['pythia'] = 'OFF' 4344 if os.path.exists(pjoin(self.me_dir,'Cards','pgs_card.dat')): 4345 switch['pgs'] = 'ON' 4346 else: 4347 switch['pgs'] = 'OFF' 4348 if self.options['delphes_path']: 4349 available_mode.append('3') 4350 if os.path.exists(pjoin(self.me_dir,'Cards','delphes_card.dat')): 4351 switch['delphes'] = 'ON' 4352 else: 4353 switch['delphes'] = 'OFF' 4354 4355 # Check switch status for MS/reweight 4356 if not MADEVENT or ('mg5_path' in self.options and self.options['mg5_path']): 4357 available_mode.append('4') 4358 available_mode.append('5') 4359 if os.path.exists(pjoin(self.me_dir,'Cards','madspin_card.dat')): 4360 switch['madspin'] = 'ON' 4361 else: 4362 switch['madspin'] = 'OFF' 4363 if misc.has_f2py() or self.options['f2py_compiler']: 4364 if os.path.exists(pjoin(self.me_dir,'Cards','reweight_card.dat')): 4365 switch['reweight'] = 'ON' 4366 else: 4367 switch['reweight'] = 'OFF' 4368 else: 4369 switch['reweight'] = 'Not available (requires NumPy)' 4370 4371 if '-R' in args or '--reweight' in args: 4372 if switch['reweight'] == 'OFF': 4373 switch['reweight'] = 'ON' 4374 elif switch['reweight'] != 'ON': 4375 logger.critical("Cannot run reweight: %s", switch['reweight']) 4376 if '-M' in args or '--madspin' in args: 4377 switch['madspin'] = 'ON' 4378 4379 options = list(available_mode) + ['auto', 'done'] 4380 for id, key in enumerate(switch_order): 4381 if switch[key] not in [void, 'Not available (requires NumPy)']: 4382 options += ['%s=%s' % (key, s) for s in ['ON','OFF']] 4383 options.append(key) 4384 options.append('parton') 4385 4386 #ask the question 4387 if mode or not self.force: 4388 answer = '' 4389 while answer not in ['0', 'done', 'auto']: 4390 if mode: 4391 answer = mode 4392 else: 4393 switch_format = " %i %-61s %10s=%s\n" 4394 question = "The following switches determine which programs are run:\n" 4395 for id, key in enumerate(switch_order): 4396 question += switch_format % (id+1, description[key], key, switch[key]) 4397 question += ' Either type the switch number (1 to %s) to change its default setting,\n' % (id+1) 4398 question += ' or set any switch explicitly (e.g. type \'madspin=ON\' at the prompt)\n' 4399 question += ' Type \'0\', \'auto\', \'done\' or just press enter when you are done.\n' 4400 answer = self.ask(question, '0', options) 4401 if answer.isdigit() and answer != '0': 4402 key = switch_order[int(answer) - 1] 4403 answer = '%s=%s' % (key, 'ON' if switch[key] == 'OFF' else 'OFF') 4404 4405 if '=' in answer: 4406 key, status = answer.split('=') 4407 switch[key] = status 4408 if (key, status) in force_switch: 4409 for key2, status2 in force_switch[(key, status)].items(): 4410 if switch[key2] not in [status2, void]: 4411 logger.info('For coherence \'%s\' is set to \'%s\'' 4412 % (key2, status2), '$MG:color:BLACK') 4413 switch[key2] = status2 4414 elif answer in ['0', 'auto', 'done']: 4415 continue 4416 else: 4417 logger.info('pass in %s only mode' % answer, '$MG:color:BLACK') 4418 switch_assign('madspin', 'OFF') 4419 switch_assign('reweight', 'OFF') 4420 if answer == 'parton': 4421 switch_assign('pythia', 'OFF') 4422 switch_assign('pgs', 'OFF') 4423 switch_assign('delphes', 'OFF') 4424 elif answer == 'pythia': 4425 switch_assign('pythia', 'ON') 4426 switch_assign('pgs', 'OFF') 4427 switch_assign('delphes', 'OFF') 4428 elif answer == 'pgs': 4429 switch_assign('pythia', 'ON') 4430 switch_assign('pgs', 'ON') 4431 switch_assign('delphes', 'OFF') 4432 elif answer == 'delphes': 4433 switch_assign('pythia', 'ON') 4434 switch_assign('pgs', 'OFF') 4435 switch_assign('delphes', 'ON') 4436 elif answer == 'madspin': 4437 switch_assign('madspin', 'ON') 4438 switch_assign('pythia', 'OFF') 4439 switch_assign('pgs', 'OFF') 4440 switch_assign('delphes', 'OF') 4441 elif answer == 'reweight': 4442 switch_assign('reweight', 'ON') 4443 switch_assign('pythia', 'OFF') 4444 switch_assign('pgs', 'OFF') 4445 switch_assign('delphes', 'OFF') 4446 4447 4448 if mode: 4449 answer = '0' #mode auto didn't pass here (due to the continue) 4450 else: 4451 answer = 'auto' 4452 4453 # Now that we know in which mode we are check that all the card 4454 #exists (copy default if needed) 4455 4456 cards = ['param_card.dat', 'run_card.dat'] 4457 if switch['pythia'] == 'ON': 4458 cards.append('pythia_card.dat') 4459 if switch['pgs'] == 'ON': 4460 cards.append('pgs_card.dat') 4461 if switch['delphes'] == 'ON': 4462 cards.append('delphes_card.dat') 4463 delphes3 = True 4464 if os.path.exists(pjoin(self.options['delphes_path'], 'data')): 4465 delphes3 = False 4466 cards.append('delphes_trigger.dat') 4467 if switch['madspin'] == 'ON': 4468 cards.append('madspin_card.dat') 4469 if switch['reweight'] == 'ON': 4470 cards.append('reweight_card.dat') 4471 self.keep_cards(cards) 4472 4473 if os.path.isfile(pjoin(self.me_dir,'Cards','MadLoopParams.dat')): 4474 cards.append('MadLoopParams.dat') 4475 4476 if self.force: 4477 self.check_param_card(pjoin(self.me_dir,'Cards','param_card.dat' )) 4478 return 4479 4480 if answer == 'auto': 4481 self.ask_edit_cards(cards, mode='auto') 4482 else: 4483 self.ask_edit_cards(cards) 4484 return
4485 4486 ############################################################################
4487 - def ask_pythia_run_configuration(self, mode=None):
4488 """Ask the question when launching pythia""" 4489 4490 available_mode = ['0', '1', '2'] 4491 if self.options['delphes_path']: 4492 available_mode.append('3') 4493 name = {'0': 'auto', '1': 'pythia', '2':'pgs', '3':'delphes'} 4494 options = available_mode + [name[val] for val in available_mode] 4495 question = """Which programs do you want to run? 4496 0 / auto : running existing card 4497 1 / pythia : Pythia 4498 2 / pgs : Pythia + PGS\n""" 4499 if '3' in available_mode: 4500 question += """ 3 / delphes : Pythia + Delphes.\n""" 4501 4502 if not self.force: 4503 if not mode: 4504 mode = self.ask(question, '0', options) 4505 elif not mode: 4506 mode = 'auto' 4507 4508 if mode.isdigit(): 4509 mode = name[mode] 4510 4511 auto = False 4512 if mode == 'auto': 4513 auto = True 4514 if os.path.exists(pjoin(self.me_dir, 'Cards', 'pgs_card.dat')): 4515 mode = 'pgs' 4516 elif os.path.exists(pjoin(self.me_dir, 'Cards', 'delphes_card.dat')): 4517 mode = 'delphes' 4518 else: 4519 mode = 'pythia' 4520 logger.info('Will run in mode %s' % mode) 4521 4522 # Now that we know in which mode we are check that all the card 4523 #exists (copy default if needed) remove pointless one 4524 cards = ['pythia_card.dat'] 4525 if mode == 'pgs': 4526 cards.append('pgs_card.dat') 4527 if mode == 'delphes': 4528 cards.append('delphes_card.dat') 4529 delphes3 = True 4530 if os.path.exists(pjoin(self.options['delphes_path'], 'data')): 4531 delphes3 = False 4532 cards.append('delphes_trigger.dat') 4533 self.keep_cards(cards) 4534 4535 if self.force: 4536 return mode 4537 4538 if auto: 4539 self.ask_edit_cards(cards, mode='auto') 4540 else: 4541 self.ask_edit_cards(cards) 4542 4543 return mode
4544
4545 4546 4547 4548 4549 #=============================================================================== 4550 # MadEventCmd 4551 #=============================================================================== 4552 -class MadEventCmdShell(MadEventCmd, cmd.CmdShell):
4553 """The command line processor of MadGraph"""
4554
4555 4556 4557 #=============================================================================== 4558 # HELPING FUNCTION For Subprocesses 4559 #=============================================================================== 4560 -class SubProcesses(object):
4561 4562 name_to_pdg = {} 4563 4564 @classmethod
4565 - def clean(cls):
4566 cls.name_to_pdg = {}
4567 4568 @staticmethod
4569 - def get_subP(me_dir):
4570 """return the list of Subprocesses""" 4571 4572 out = [] 4573 for line in open(pjoin(me_dir,'SubProcesses', 'subproc.mg')): 4574 if not line: 4575 continue 4576 name = line.strip() 4577 if os.path.exists(pjoin(me_dir, 'SubProcesses', name)): 4578 out.append(pjoin(me_dir, 'SubProcesses', name)) 4579 4580 return out
4581 4582 4583 4584 @staticmethod
4585 - def get_subP_info(path):
4586 """ return the list of processes with their name""" 4587 4588 nb_sub = 0 4589 names = {} 4590 old_main = '' 4591 4592 if not os.path.exists(os.path.join(path,'processes.dat')): 4593 return SubProcesses.get_subP_info_v4(path) 4594 4595 for line in open(os.path.join(path,'processes.dat')): 4596 main = line[:8].strip() 4597 if main == 'mirror': 4598 main = old_main 4599 if line[8:].strip() == 'none': 4600 continue 4601 else: 4602 main = int(main) 4603 old_main = main 4604 4605 sub_proccess = line[8:] 4606 nb_sub += sub_proccess.count(',') + 1 4607 if main in names: 4608 names[main] += [sub_proccess.split(',')] 4609 else: 4610 names[main]= [sub_proccess.split(',')] 4611 4612 return names
4613 4614 @staticmethod
4615 - def get_subP_info_v4(path):
4616 """ return the list of processes with their name in case without grouping """ 4617 4618 nb_sub = 0 4619 names = {'':[[]]} 4620 path = os.path.join(path, 'auto_dsig.f') 4621 found = 0 4622 for line in open(path): 4623 if line.startswith('C Process:'): 4624 found += 1 4625 names[''][0].append(line[15:]) 4626 elif found >1: 4627 break 4628 return names
4629 4630 4631 @staticmethod
4632 - def get_subP_ids(path):
4633 """return the pdg codes of the particles present in the Subprocesses""" 4634 4635 all_ids = [] 4636 for line in open(pjoin(path, 'leshouche.inc')): 4637 if not 'IDUP' in line: 4638 continue 4639 particles = re.search("/([\d,-]+)/", line) 4640 all_ids.append([int(p) for p in particles.group(1).split(',')]) 4641 return all_ids
4642
4643 4644 #=============================================================================== 4645 -class GridPackCmd(MadEventCmd):
4646 """The command for the gridpack --Those are not suppose to be use interactively--""" 4647
4648 - def __init__(self, me_dir = None, nb_event=0, seed=0, *completekey, **stdin):
4649 """Initialize the command and directly run""" 4650 4651 # Initialize properly 4652 4653 MadEventCmd.__init__(self, me_dir, *completekey, **stdin) 4654 self.run_mode = 0 4655 self.random = seed 4656 self.random_orig = self.random 4657 self.options['automatic_html_opening'] = False 4658 # Now it's time to run! 4659 if me_dir and nb_event and seed: 4660 self.launch(nb_event, seed) 4661 else: 4662 raise MadGraph5Error,\ 4663 'Gridpack run failed: ' + str(me_dir) + str(nb_event) + \ 4664 str(seed)
4665
4666 - def launch(self, nb_event, seed):
4667 """ launch the generation for the grid """ 4668 4669 # 1) Restore the default data 4670 logger.info('generate %s events' % nb_event) 4671 self.set_run_name('GridRun_%s' % seed) 4672 self.update_status('restoring default data', level=None) 4673 misc.call([pjoin(self.me_dir,'bin','internal','restore_data'), 4674 'default'], 4675 cwd=self.me_dir) 4676 4677 # 2) Run the refine for the grid 4678 self.update_status('Generating Events', level=None) 4679 #misc.call([pjoin(self.me_dir,'bin','refine4grid'), 4680 # str(nb_event), '0', 'Madevent','1','GridRun_%s' % seed], 4681 # cwd=self.me_dir) 4682 self.refine4grid(nb_event) 4683 4684 # 3) Combine the events/pythia/... 4685 self.exec_cmd('combine_events') 4686 self.exec_cmd('store_events') 4687 self.print_results_in_shell(self.results.current) 4688 self.exec_cmd('decay_events -from_cards', postcmd=False)
4689
4690 - def refine4grid(self, nb_event):
4691 """Special refine for gridpack run.""" 4692 self.nb_refine += 1 4693 4694 precision = nb_event 4695 4696 # initialize / remove lhapdf mode 4697 # self.configure_directory() # All this has been done before 4698 self.cluster_mode = 0 # force single machine 4699 4700 # Store seed in randinit file, to be read by ranmar.f 4701 self.save_random() 4702 4703 self.update_status('Refine results to %s' % precision, level=None) 4704 logger.info("Using random number seed offset = %s" % self.random) 4705 4706 self.total_jobs = 0 4707 subproc = [P for P in os.listdir(pjoin(self.me_dir,'SubProcesses')) if 4708 P.startswith('P') and os.path.isdir(pjoin(self.me_dir,'SubProcesses', P))] 4709 devnull = open(os.devnull, 'w') 4710 for nb_proc,subdir in enumerate(subproc): 4711 subdir = subdir.strip() 4712 Pdir = pjoin(self.me_dir, 'SubProcesses',subdir) 4713 bindir = pjoin(os.path.relpath(self.dirbin, Pdir)) 4714 4715 logger.info(' %s ' % subdir) 4716 # clean previous run 4717 for match in misc.glob('*ajob*', Pdir): 4718 if os.path.basename(match)[:4] in ['ajob', 'wait', 'run.', 'done']: 4719 os.remove(pjoin(Pdir, match)) 4720 4721 4722 logfile = pjoin(Pdir, 'gen_ximprove.log') 4723 misc.call([pjoin(bindir, 'gen_ximprove')], 4724 stdin=subprocess.PIPE, 4725 stdout=open(logfile,'w'), 4726 cwd=Pdir) 4727 4728 if os.path.exists(pjoin(Pdir, 'ajob1')): 4729 alljobs = misc.glob('ajob*', Pdir) 4730 nb_tot = len(alljobs) 4731 self.total_jobs += nb_tot 4732 for i, job in enumerate(alljobs): 4733 job = os.path.basename(job) 4734 self.launch_job('%s' % job, cwd=Pdir, remaining=(nb_tot-i-1), 4735 run_type='Refine number %s on %s (%s/%s)' % 4736 (self.nb_refine, subdir, nb_proc+1, len(subproc))) 4737 if os.path.exists(pjoin(self.me_dir,'error')): 4738 self.monitor(html=True) 4739 raise MadEventError, \ 4740 'Error detected in dir %s: %s' % \ 4741 (Pdir, open(pjoin(self.me_dir,'error')).read()) 4742 self.monitor(run_type='All job submitted for refine number %s' % 4743 self.nb_refine) 4744 4745 self.update_status("Combining runs", level='parton') 4746 try: 4747 os.remove(pjoin(Pdir, 'combine_runs.log')) 4748 except Exception: 4749 pass 4750 4751 bindir = pjoin(os.path.relpath(self.dirbin, pjoin(self.me_dir,'SubProcesses'))) 4752 combine_runs.CombineRuns(self.me_dir) 4753 4754 #update html output 4755 cross, error = sum_html.make_all_html_results(self) 4756 self.results.add_detail('cross', cross) 4757 self.results.add_detail('error', error) 4758 4759 4760 self.update_status('finish refine', 'parton', makehtml=False) 4761 devnull.close()
4762
4763 4764 -class MadLoopInitializer(object):
4765 """ A container class for the various methods for initializing MadLoop. It is 4766 placed in MadEventInterface because it is used by Madevent for loop-induced 4767 simulations. """ 4768 4769 @staticmethod
4770 - def make_and_run(dir_name,checkRam=False):
4771 """ Compile the check program in the directory dir_name. 4772 Return the compilation and running time. """ 4773 4774 # Make sure to recreate the executable and modified source 4775 # (The time stamps are sometimes not actualized if it is too fast) 4776 if os.path.isfile(pjoin(dir_name,'check')): 4777 os.remove(pjoin(dir_name,'check')) 4778 os.remove(pjoin(dir_name,'check_sa.o')) 4779 os.remove(pjoin(dir_name,'loop_matrix.o')) 4780 # Now run make 4781 devnull = open(os.devnull, 'w') 4782 start=time.time() 4783 retcode = subprocess.call(['make','check'], 4784 cwd=dir_name, stdout=devnull, stderr=devnull) 4785 compilation_time = time.time()-start 4786 if retcode != 0: 4787 logging.info("Error while executing make in %s" % dir_name) 4788 return None, None, None 4789 4790 if not checkRam: 4791 start=time.time() 4792 retcode = subprocess.call('./check', 4793 cwd=dir_name, stdout=devnull, stderr=devnull) 4794 4795 run_time = time.time()-start 4796 ram_usage = None 4797 else: 4798 ptimer = misc.ProcessTimer(['./check'], cwd=dir_name, shell=False, \ 4799 stdout=devnull, stderr=devnull, close_fds=True) 4800 try: 4801 ptimer.execute() 4802 #poll as often as possible; otherwise the subprocess might 4803 # "sneak" in some extra memory usage while you aren't looking 4804 # Accuracy of .2 seconds is enough for the timing. 4805 while ptimer.poll(): 4806 time.sleep(.2) 4807 finally: 4808 #make sure that we don't leave the process dangling. 4809 ptimer.close() 4810 # Notice that ptimer.max_vms_memory is also available if needed. 4811 ram_usage = ptimer.max_rss_memory 4812 # Unfortunately the running time is less precise than with the 4813 # above version 4814 run_time = (ptimer.t1 - ptimer.t0) 4815 retcode = ptimer.p.returncode 4816 4817 devnull.close() 4818 4819 if retcode != 0: 4820 logging.warning("Error while executing ./check in %s" % dir_name) 4821 return None, None, None 4822 4823 return compilation_time, run_time, ram_usage
4824 4825 @staticmethod
4826 - def fix_PSPoint_in_check(dir_path, read_ps = True, npoints = 1, 4827 hel_config = -1, mu_r=0.0, split_orders=-1):
4828 """Set check_sa.f to be reading PS.input assuming a working dir dir_name. 4829 if hel_config is different than -1 then check_sa.f is configured so to 4830 evaluate only the specified helicity. 4831 If mu_r > 0.0, then the renormalization constant value will be hardcoded 4832 directly in check_sa.f, if is is 0 it will be set to Sqrt(s) and if it 4833 is < 0.0 the value in the param_card.dat is used. 4834 If the split_orders target (i.e. the target squared coupling orders for 4835 the computation) is != -1, it will be changed in check_sa.f via the 4836 subroutine CALL SET_COUPLINGORDERS_TARGET(split_orders).""" 4837 4838 file_path = dir_path 4839 if not os.path.isfile(dir_path) or \ 4840 not os.path.basename(dir_path)=='check_sa.f': 4841 file_path = pjoin(dir_path,'check_sa.f') 4842 if not os.path.isfile(file_path): 4843 directories = [d for d in misc.glob('P*_*', dir_path) \ 4844 if (re.search(r'.*P\d+_\w*$', d) and os.path.isdir(d))] 4845 if len(directories)>0: 4846 file_path = pjoin(directories[0],'check_sa.f') 4847 if not os.path.isfile(file_path): 4848 raise MadGraph5Error('Could not find the location of check_sa.f'+\ 4849 ' from the specified path %s.'%str(file_path)) 4850 4851 file = open(file_path, 'r') 4852 check_sa = file.read() 4853 file.close() 4854 4855 file = open(file_path, 'w') 4856 check_sa = re.sub(r"READPS = \S+\)","READPS = %s)"%('.TRUE.' if read_ps \ 4857 else '.FALSE.'), check_sa) 4858 check_sa = re.sub(r"NPSPOINTS = \d+","NPSPOINTS = %d"%npoints, check_sa) 4859 if hel_config != -1: 4860 check_sa = re.sub(r"SLOOPMATRIX\S+\(\S+,MATELEM,", 4861 "SLOOPMATRIXHEL_THRES(P,%d,MATELEM,"%hel_config, check_sa) 4862 else: 4863 check_sa = re.sub(r"SLOOPMATRIX\S+\(\S+,MATELEM,", 4864 "SLOOPMATRIX_THRES(P,MATELEM,",check_sa) 4865 if mu_r > 0.0: 4866 check_sa = re.sub(r"MU_R=SQRTS","MU_R=%s"%\ 4867 (("%.17e"%mu_r).replace('e','d')),check_sa) 4868 elif mu_r < 0.0: 4869 check_sa = re.sub(r"MU_R=SQRTS","",check_sa) 4870 4871 if split_orders > 0: 4872 check_sa = re.sub(r"SET_COUPLINGORDERS_TARGET\(-?\d+\)", 4873 "SET_COUPLINGORDERS_TARGET(%d)"%split_orders,check_sa) 4874 4875 file.write(check_sa) 4876 file.close()
4877 4878 @staticmethod
4879 - def run_initialization(run_dir=None, SubProc_dir=None, infos=None,\ 4880 req_files = ['HelFilter.dat','LoopFilter.dat'], 4881 attempts = [4,15]):
4882 """ Run the initialization of the process in 'run_dir' with success 4883 characterized by the creation of the files req_files in this directory. 4884 The directory containing the driving source code 'check_sa.f'. 4885 The list attempt gives the successive number of PS points the 4886 initialization should be tried with before calling it failed. 4887 Returns the number of PS points which were necessary for the init. 4888 Notice at least run_dir or SubProc_dir must be provided. 4889 A negative attempt number given in input means that quadprec will be 4890 forced for initialization.""" 4891 4892 # If the user does not want detailed info, then set the dictionary 4893 # to a dummy one. 4894 if infos is None: 4895 infos={} 4896 4897 if SubProc_dir is None and run_dir is None: 4898 raise MadGraph5Error, 'At least one of [SubProc_dir,run_dir] must'+\ 4899 ' be provided in run_initialization.' 4900 4901 # If the user does not specify where is check_sa.f, then it is assumed 4902 # to be one levels above run_dir 4903 if SubProc_dir is None: 4904 SubProc_dir = os.path.abspath(pjoin(run_dir,os.pardir)) 4905 4906 if run_dir is None: 4907 directories =[ dir for dir in misc.glob('P[0-9]*', SubProc_dir) 4908 if os.path.isdir(dir) ] 4909 if directories: 4910 run_dir = directories[0] 4911 else: 4912 raise MadGraph5Error, 'Could not find a valid running directory'+\ 4913 ' in %s.'%str(SubProc_dir) 4914 4915 # Use the presence of the file born_matrix.f to decide if it is a 4916 # loop-induced process or not. It's not crucial, but just that because 4917 # of the dynamic adjustment of the ref scale used for deciding what are 4918 # the zero contributions, more points are neeeded for loop-induced. 4919 if not os.path.isfile(pjoin(run_dir,'born_matrix.f')): 4920 if len(attempts)>=1 and attempts[0]<8: 4921 attempts[0]=8 4922 if len(attempts)>=2 and attempts[1]<25: 4923 attempts[1]=25 4924 4925 to_attempt = list(attempts) 4926 to_attempt.reverse() 4927 my_req_files = list(req_files) 4928 4929 MLCardPath = pjoin(SubProc_dir,'MadLoopParams.dat') 4930 if not os.path.isfile(MLCardPath): 4931 raise MadGraph5Error, 'Could not find MadLoopParams.dat at %s.'\ 4932 %MLCardPath 4933 else: 4934 MLCard = banner_mod.MadLoopParam(MLCardPath) 4935 MLCard_orig = banner_mod.MadLoopParam(MLCard) 4936 4937 # Make sure that LoopFilter really is needed. 4938 if not MLCard['UseLoopFilter']: 4939 try: 4940 my_req_files.remove('LoopFilter.dat') 4941 except ValueError: 4942 pass 4943 4944 if MLCard['HelicityFilterLevel']==0: 4945 try: 4946 my_req_files.remove('HelFilter.dat') 4947 except ValueError: 4948 pass 4949 4950 def need_init(): 4951 """ True if init not done yet.""" 4952 proc_prefix_file = open(pjoin(run_dir,'proc_prefix.txt'),'r') 4953 proc_prefix = proc_prefix_file.read() 4954 proc_prefix_file.close() 4955 return any([not os.path.exists(pjoin(run_dir,'MadLoop5_resources', 4956 proc_prefix+fname)) for fname in my_req_files]) or \ 4957 not os.path.isfile(pjoin(run_dir,'check')) or \ 4958 not os.access(pjoin(run_dir,'check'), os.X_OK)
4959 4960 # Check if this is a process without born by checking the presence of the 4961 # file born_matrix.f 4962 is_loop_induced = os.path.exists(pjoin(run_dir,'born_matrix.f')) 4963 4964 # For loop induced processes, always attempt quadruple precision if 4965 # double precision attempts fail and the user didn't specify himself 4966 # quadruple precision initializations attempts 4967 if not any(attempt<0 for attempt in to_attempt): 4968 to_attempt = [-attempt for attempt in to_attempt] + to_attempt 4969 use_quad_prec = 1 4970 curr_attempt = 1 4971 4972 MLCard.set('WriteOutFilters',True) 4973 4974 while to_attempt!=[] and need_init(): 4975 curr_attempt = to_attempt.pop() 4976 # if the attempt is a negative number it means we must force 4977 # quadruple precision at initialization time 4978 if curr_attempt < 0: 4979 use_quad_prec = -1 4980 # In quadruple precision we can lower the ZeroThres threshold 4981 MLCard.set('CTModeInit',4) 4982 MLCard.set('ZeroThres',1e-11) 4983 else: 4984 # Restore the default double precision intialization params 4985 MLCard.set('CTModeInit',1) 4986 MLCard.set('ZeroThres',1e-9) 4987 # Plus one because the filter are written on the next PS point after 4988 curr_attempt = abs(curr_attempt+1) 4989 MLCard.set('MaxAttempts',curr_attempt) 4990 MLCard.write(pjoin(SubProc_dir,'MadLoopParams.dat')) 4991 4992 # initialization is performed. 4993 MadLoopInitializer.fix_PSPoint_in_check(run_dir, read_ps = False, 4994 npoints = curr_attempt) 4995 compile_time, run_time, ram_usage = \ 4996 MadLoopInitializer.make_and_run(run_dir) 4997 if compile_time==None: 4998 logging.error("Failed at running the process in %s."%run_dir) 4999 attempts = None 5000 return None 5001 # Only set process_compilation time for the first compilation. 5002 if 'Process_compilation' not in infos.keys() or \ 5003 infos['Process_compilation']==None: 5004 infos['Process_compilation'] = compile_time 5005 infos['Initialization'] = run_time 5006 5007 MLCard_orig.write(pjoin(SubProc_dir,'MadLoopParams.dat')) 5008 if need_init(): 5009 return None 5010 else: 5011 return use_quad_prec*(curr_attempt-1)
5012 5013 @staticmethod
5014 - def need_MadLoopInit(proc_dir, subproc_prefix='PV'):
5015 """Checks whether the necessary filters are present or not.""" 5016 5017 def need_init(ML_resources_path, proc_prefix, r_files): 5018 """ Returns true if not all required files are present. """ 5019 return any([not os.path.exists(pjoin(ML_resources_path, 5020 proc_prefix+fname)) for fname in r_files])
5021 5022 MLCardPath = pjoin(proc_dir,'SubProcesses','MadLoopParams.dat') 5023 if not os.path.isfile(MLCardPath): 5024 raise MadGraph5Error, 'Could not find MadLoopParams.dat at %s.'\ 5025 %MLCardPath 5026 MLCard = banner_mod.MadLoopParam(MLCardPath) 5027 5028 req_files = ['HelFilter.dat','LoopFilter.dat'] 5029 # Make sure that LoopFilter really is needed. 5030 if not MLCard['UseLoopFilter']: 5031 try: 5032 req_files.remove('LoopFilter.dat') 5033 except ValueError: 5034 pass 5035 if MLCard['HelicityFilterLevel']==0: 5036 try: 5037 req_files.remove('HelFilter.dat') 5038 except ValueError: 5039 pass 5040 5041 for v_folder in glob.iglob(pjoin(proc_dir,'SubProcesses', 5042 '%s*'%subproc_prefix)): 5043 # Make sure it is a valid MadLoop directory 5044 if not os.path.isdir(v_folder) or not os.path.isfile(\ 5045 pjoin(v_folder,'loop_matrix.f')): 5046 continue 5047 proc_prefix_file = open(pjoin(v_folder,'proc_prefix.txt'),'r') 5048 proc_prefix = proc_prefix_file.read() 5049 proc_prefix_file.close() 5050 if need_init(pjoin(proc_dir,'SubProcesses','MadLoop5_resources'), 5051 proc_prefix, req_files): 5052 return True 5053 5054 return False 5055 5056 @staticmethod
5057 - def init_MadLoop(proc_dir, n_PS=None, subproc_prefix='PV', MG_options=None, 5058 interface = None):
5059 """Advanced commands: Compiles and run MadLoop on RAMBO random PS points to initilize the 5060 filters.""" 5061 5062 logger.debug('Compiling Source materials necessary for MadLoop '+ 5063 'initialization.') 5064 # Initialize all the virtuals directory, so as to generate the necessary 5065 # filters (essentially Helcity filter). 5066 # Make sure that the MadLoopCard has the loop induced settings 5067 if interface is None: 5068 misc.compile(arg=['treatCardsLoopNoInit'], cwd=pjoin(proc_dir,'Source')) 5069 else: 5070 interface.do_treatcards('all --no_MadLoopInit') 5071 5072 # First make sure that IREGI and CUTTOOLS are compiled if needed 5073 if os.path.exists(pjoin(proc_dir,'Source','CUTTOOLS')): 5074 misc.compile(arg=['libcuttools'],cwd=pjoin(proc_dir,'Source')) 5075 if os.path.exists(pjoin(proc_dir,'Source','IREGI')): 5076 misc.compile(arg=['libiregi'],cwd=pjoin(proc_dir,'Source')) 5077 # Then make sure DHELAS and MODEL are compiled 5078 misc.compile(arg=['libmodel'],cwd=pjoin(proc_dir,'Source')) 5079 misc.compile(arg=['libdhelas'],cwd=pjoin(proc_dir,'Source')) 5080 5081 # Now initialize the MadLoop outputs 5082 logger.info('Initializing MadLoop loop-induced matrix elements '+\ 5083 '(this can take some time)...') 5084 5085 # Setup parallelization 5086 if MG_options: 5087 mcore = cluster.MultiCore(**MG_options) 5088 else: 5089 mcore = cluster.onecore 5090 def run_initialization_wrapper(run_dir, infos, attempts): 5091 if attempts is None: 5092 n_PS = MadLoopInitializer.run_initialization( 5093 run_dir=run_dir, infos=infos) 5094 else: 5095 n_PS = MadLoopInitializer.run_initialization( 5096 run_dir=run_dir, infos=infos, attempts=attempts) 5097 infos['nPS'] = n_PS 5098 return 0
5099 5100 def wait_monitoring(Idle, Running, Done): 5101 if Idle+Running+Done == 0: 5102 return 5103 logger.debug('MadLoop initialization jobs: %d Idle, %d Running, %d Done'\ 5104 %(Idle, Running, Done)) 5105 5106 init_info = {} 5107 # List all virtual folders while making sure they are valid MadLoop folders 5108 VirtualFolders = [f for f in glob.iglob(pjoin(proc_dir,'SubProcesses', 5109 '%s*'%subproc_prefix)) if (os.path.isdir(f) or 5110 os.path.isfile(pjoin(f,'loop_matrix.f')))] 5111 logger.debug("Now Initializing MadLoop matrix element in %d folder%s:"%\ 5112 (len(VirtualFolders),'s' if len(VirtualFolders)>1 else '')) 5113 logger.debug(', '.join("'%s'"%os.path.basename(v_folder) for v_folder in 5114 VirtualFolders)) 5115 for v_folder in VirtualFolders: 5116 init_info[v_folder] = {} 5117 5118 # We try all multiples of n_PS from 1 to max_mult, first in DP and then 5119 # in QP before giving up, or use default values if n_PS is None. 5120 max_mult = 3 5121 if n_PS is None: 5122 # Then use the default list of number of PS points to try 5123 mcore.submit(run_initialization_wrapper, 5124 [pjoin(v_folder), init_info[v_folder], None]) 5125 else: 5126 # Use specific set of PS points 5127 mcore.submit(run_initialization_wrapper, [pjoin(v_folder), 5128 init_info[v_folder], 5129 [n_PS*multiplier for multiplier in range(1,max_mult+1)]]) 5130 5131 # Wait for all jobs to finish. 5132 mcore.wait('',wait_monitoring,update_first=wait_monitoring) 5133 for v_folder in VirtualFolders: 5134 init = init_info[v_folder] 5135 if init['nPS'] is None: 5136 raise MadGraph5Error, 'Failed the initialization of'+\ 5137 " loop-induced matrix element '%s'%s."%\ 5138 (os.path.basename(v_folder),' (using default n_PS points)' if\ 5139 n_PS is None else ' (trying with a maximum of %d PS points)'\ 5140 %(max_mult*n_PS)) 5141 if init['nPS']==0: 5142 logger.debug("Nothing to be done in '%s', all filters already "%\ 5143 os.path.basename(v_folder)+\ 5144 "present (use the '-r' option to force their recomputation)") 5145 else: 5146 logger.debug("'%s' finished using "%os.path.basename(v_folder)+ 5147 '%d PS points (%s), in %.3g(compil.) + %.3g(init.) secs.'%( 5148 abs(init['nPS']),'DP' if init['nPS']>0 else 'QP', 5149 init['Process_compilation'],init['Initialization'])) 5150 5151 logger.info('MadLoop initialization finished.') 5152 5153 AskforEditCard = common_run.AskforEditCard 5154 5155 5156 if '__main__' == __name__: 5157 # Launch the interface without any check if one code is already running. 5158 # This can ONLY run a single command !! 5159 import sys 5160 if not sys.version_info[0] == 2 or sys.version_info[1] < 6: 5161 sys.exit('MadGraph/MadEvent 5 works only with python 2.6 or later (but not python 3.X).\n'+\ 5162 'Please upgrate your version of python.') 5163 5164 import os 5165 import optparse 5166 # Get the directory of the script real path (bin) 5167 # and add it to the current PYTHONPATH 5168 root_path = os.path.dirname(os.path.dirname(os.path.realpath( __file__ ))) 5169 sys.path.insert(0, root_path)
5170 5171 - class MyOptParser(optparse.OptionParser):
5172 - class InvalidOption(Exception): pass
5173 - def error(self, msg=''):
5174 raise MyOptParser.InvalidOption(msg)
5175 # Write out nice usage message if called with -h or --help 5176 usage = "usage: %prog [options] [FILE] " 5177 parser = MyOptParser(usage=usage) 5178 parser.add_option("-l", "--logging", default='INFO', 5179 help="logging level (DEBUG|INFO|WARNING|ERROR|CRITICAL) [%default]") 5180 parser.add_option("","--web", action="store_true", default=False, dest='web', \ 5181 help='force toce to be in secure mode') 5182 parser.add_option("","--debug", action="store_true", default=False, dest='debug', \ 5183 help='force to launch debug mode') 5184 parser_error = '' 5185 done = False 5186 5187 for i in range(len(sys.argv)-1): 5188 try: 5189 (options, args) = parser.parse_args(sys.argv[1:len(sys.argv)-i]) 5190 done = True 5191 except MyOptParser.InvalidOption, error: 5192 pass 5193 else: 5194 args += sys.argv[len(sys.argv)-i:] 5195 if not done: 5196 # raise correct error: 5197 try: 5198 (options, args) = parser.parse_args() 5199 except MyOptParser.InvalidOption, error: 5200 print error 5201 sys.exit(2) 5202 5203 if len(args) == 0: 5204 args = '' 5205 5206 import subprocess 5207 import logging 5208 import logging.config 5209 # Set logging level according to the logging level given by options 5210 #logging.basicConfig(level=vars(logging)[options.logging]) 5211 import internal.coloring_logging 5212 try: 5213 if __debug__ and options.logging == 'INFO': 5214 options.logging = 'DEBUG' 5215 if options.logging.isdigit(): 5216 level = int(options.logging) 5217 else: 5218 level = eval('logging.' + options.logging) 5219 print os.path.join(root_path, 'internal', 'me5_logging.conf') 5220 logging.config.fileConfig(os.path.join(root_path, 'internal', 'me5_logging.conf')) 5221 logging.root.setLevel(level) 5222 logging.getLogger('madgraph').setLevel(level) 5223 except: 5224 raise 5225 pass 5226 5227 # Call the cmd interface main loop 5228 try: 5229 if args: 5230 # a single command is provided 5231 if '--web' in args: 5232 i = args.index('--web') 5233 args.pop(i) 5234 cmd_line = MadEventCmd(force_run=True) 5235 else: 5236 cmd_line = MadEventCmdShell(force_run=True) 5237 if not hasattr(cmd_line, 'do_%s' % args[0]): 5238 if parser_error: 5239 print parser_error 5240 print 'and %s can not be interpreted as a valid command.' % args[0] 5241 else: 5242 print 'ERROR: %s not a valid command. Please retry' % args[0] 5243 else: 5244 cmd_line.use_rawinput = False 5245 cmd_line.run_cmd(' '.join(args)) 5246 cmd_line.run_cmd('quit') 5247 5248 except KeyboardInterrupt: 5249 print 'quit on KeyboardInterrupt' 5250 pass 5251