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 self.exec_cmd('refine %s' % nb_event, postcmd=False) 1995 if not float(self.results.current['cross']): 1996 # Zero cross-section. Try to guess why 1997 text = '''Survey return zero cross section. 1998 Typical reasons are the following: 1999 1) A massive s-channel particle has a width set to zero. 2000 2) The pdf are zero for at least one of the initial state particles 2001 or you are using maxjetflavor=4 for initial state b:s. 2002 3) The cuts are too strong. 2003 Please check/correct your param_card and/or your run_card.''' 2004 logger_stderr.critical(text) 2005 raise ZeroResult('See https://cp3.irmp.ucl.ac.be/projects/madgraph/wiki/FAQ-General-14') 2006 2007 self.exec_cmd('refine %s' % nb_event, postcmd=False) 2008 2009 self.exec_cmd('combine_events', postcmd=False) 2010 self.print_results_in_shell(self.results.current) 2011 2012 2013 self.run_syscalc('parton') 2014 self.create_plot('parton') 2015 self.exec_cmd('store_events', postcmd=False) 2016 self.exec_cmd('reweight -from_cards', postcmd=False) 2017 self.exec_cmd('decay_events -from_cards', postcmd=False) 2018 if self.run_card['time_of_flight']>=0: 2019 self.exec_cmd("add_time_of_flight --threshold=%s" % self.run_card['time_of_flight'] ,postcmd=False) 2020 self.exec_cmd('pythia --no_default', postcmd=False, printcmd=False) 2021 # pythia launches pgs/delphes if needed 2022 self.store_result() 2023 2024 if self.param_card_iterator: 2025 param_card_iterator = self.param_card_iterator 2026 self.param_card_iterator = [] 2027 with misc.TMP_variable(self, 'allow_notification_center', False): 2028 param_card_iterator.store_entry(self.run_name, self.results.current['cross']) 2029 #check if the param_card defines a scan. 2030 orig_name = self.run_name 2031 for card in param_card_iterator: 2032 card.write(pjoin(self.me_dir,'Cards','param_card.dat')) 2033 next_name = param_card_iterator.get_next_name(self.run_name) 2034 self.exec_cmd("generate_events -f %s" % next_name, 2035 precmd=True, postcmd=True,errorhandling=False) 2036 param_card_iterator.store_entry(self.run_name, self.results.current['cross']) 2037 param_card_iterator.write(pjoin(self.me_dir,'Cards','param_card.dat')) 2038 name = misc.get_scan_name(orig_name, self.run_name) 2039 path = pjoin(self.me_dir, 'Events','scan_%s.txt' % name) 2040 logger.info("write all cross-section results in %s" % path ,'$MG:color:BLACK') 2041 param_card_iterator.write_summary(path) 2042 2043 2044 if self.allow_notification_center: 2045 misc.apple_notify('Run %s finished' % os.path.basename(self.me_dir), 2046 '%s: %s +- %s ' % (self.results.current['run_name'], 2047 self.results.current['cross'], 2048 self.results.current['error']))
2049
2050 - def do_initMadLoop(self,line):
2051 """Compile and run MadLoop for a certain number of PS point so as to 2052 initialize MadLoop (setup the zero helicity and loop filter.)""" 2053 2054 args = line.split() 2055 # Check argument's validity 2056 options = self.check_initMadLoop(args) 2057 2058 if not options['force']: 2059 self.ask_edit_cards(['MadLoopParams.dat'], mode='fixed', plot=False) 2060 self.exec_cmd('treatcards loop --no_MadLoopInit') 2061 2062 if options['refresh']: 2063 for filter in misc.glob('*Filter*', 2064 pjoin(self.me_dir,'SubProcesses','MadLoop5_resources')): 2065 logger.debug("Resetting filter '%s'."%os.path.basename(filter)) 2066 os.remove(filter) 2067 2068 MLCard = banner_mod.MadLoopParam(pjoin(self.me_dir, 2069 'Cards','MadLoopParams.dat')) 2070 if options['nPS'] is None: 2071 options['nPS'] = MLCard['CheckCycle']+2 2072 elif options['nPS'] < MLCard['CheckCycle']+2: 2073 new_n_PS = MLCard['CheckCycle']+2 2074 logger.debug('Hard-setting user-defined n_PS (%d) to %d, because '\ 2075 %(options['nPS'],new_n_PS)+"of the 'CheckCycle' value (%d) "%MLCard['CheckCycle']+\ 2076 "specified in the ML param card.") 2077 options['nPS'] = new_n_PS 2078 2079 MadLoopInitializer.init_MadLoop(self.me_dir,n_PS=options['nPS'], 2080 subproc_prefix='PV', MG_options=self.options, interface=self)
2081
2082 - def do_launch(self, line, *args, **opt):
2083 """Main Commands: exec generate_events for 2>N and calculate_width for 1>N""" 2084 if self.ninitial == 1: 2085 logger.info("Note that since 2.3. The launch for 1>N pass in event generation\n"+ 2086 " To have the previous behavior use the calculate_decay_widths function") 2087 self.do_calculate_decay_widths(line, *args, **opt) 2088 else: 2089 self.do_generate_events(line, *args, **opt)
2090
2091 - def print_results_in_shell(self, data):
2092 """Have a nice results prints in the shell, 2093 data should be of type: gen_crossxhtml.OneTagResults""" 2094 2095 if not data: 2096 return 2097 2098 if data['run_statistics']: 2099 globalstat = sum_html.RunStatistics() 2100 2101 logger.info(" " ) 2102 logger.debug(" === Run statistics summary ===") 2103 for key, value in data['run_statistics'].items(): 2104 globalstat.aggregate_statistics(value) 2105 level = 5 2106 if value.has_warning(): 2107 level = 10 2108 logger.log(level, value.nice_output(str('/'.join([key[0],'G%s'%key[1]]))).\ 2109 replace(' statistics','')) 2110 logger.info(" " ) 2111 logger.debug(globalstat.nice_output('combined', no_warning=True)) 2112 if globalstat.has_warning(): 2113 logger.warning(globalstat.get_warning_text()) 2114 logger.info(" ") 2115 2116 2117 logger.info(" === Results Summary for run: %s tag: %s ===\n" % (data['run_name'],data['tag'])) 2118 2119 total_time = int(sum(_['cumulative_timing'] for _ in data['run_statistics'].values())) 2120 if total_time > 0: 2121 logger.info(" Cumulative sequential time for this run: %s"%misc.format_time(total_time)) 2122 2123 if self.ninitial == 1: 2124 logger.info(" Width : %.4g +- %.4g GeV" % (data['cross'], data['error'])) 2125 else: 2126 logger.info(" Cross-section : %.4g +- %.4g pb" % (data['cross'], data['error'])) 2127 logger.info(" Nb of events : %s" % data['nb_event'] ) 2128 if data['cross_pythia'] and data['nb_event_pythia']: 2129 if self.ninitial == 1: 2130 logger.info(" Matched Width : %.4g +- %.4g GeV" % (data['cross_pythia'], data['error_pythia'])) 2131 else: 2132 logger.info(" Matched Cross-section : %.4g +- %.4g pb" % (data['cross_pythia'], data['error_pythia'])) 2133 logger.info(" Nb of events after Matching : %s" % data['nb_event_pythia']) 2134 if self.run_card['use_syst'] in self.true: 2135 logger.info(" Be carefull that matched information are here NOT for the central value. Refer to SysCalc output for it") 2136 2137 logger.info(" " )
2138
2139 - def print_results_in_file(self, data, path, mode='w', format='full'):
2140 """Have a nice results prints in the shell, 2141 data should be of type: gen_crossxhtml.OneTagResults""" 2142 if not data: 2143 return 2144 2145 fsock = open(path, mode) 2146 2147 if data['run_statistics']: 2148 logger.debug(" === Run statistics summary ===") 2149 for key, value in data['run_statistics'].items(): 2150 logger.debug(value.nice_output(str('/'.join([key[0],'G%s'%key[1]]))).\ 2151 replace(' statistics','')) 2152 logger.info(" " ) 2153 2154 if format == "full": 2155 fsock.write(" === Results Summary for run: %s tag: %s process: %s ===\n" % \ 2156 (data['run_name'],data['tag'], os.path.basename(self.me_dir))) 2157 2158 if self.ninitial == 1: 2159 fsock.write(" Width : %.4g +- %.4g GeV\n" % (data['cross'], data['error'])) 2160 else: 2161 fsock.write(" Cross-section : %.4g +- %.4g pb\n" % (data['cross'], data['error'])) 2162 fsock.write(" Nb of events : %s\n" % data['nb_event'] ) 2163 if data['cross_pythia'] and data['nb_event_pythia']: 2164 if self.ninitial == 1: 2165 fsock.write(" Matched Width : %.4g +- %.4g GeV\n" % (data['cross_pythia'], data['error_pythia'])) 2166 else: 2167 fsock.write(" Matched Cross-section : %.4g +- %.4g pb\n" % (data['cross_pythia'], data['error_pythia'])) 2168 fsock.write(" Nb of events after Matching : %s\n" % data['nb_event_pythia']) 2169 fsock.write(" \n" ) 2170 elif format == "short": 2171 if mode == "w": 2172 fsock.write("# run_name tag cross error Nb_event cross_after_matching nb_event_after matching\n") 2173 2174 if data['cross_pythia'] and data['nb_event_pythia']: 2175 text = "%(run_name)s %(tag)s %(cross)s %(error)s %(nb_event)s %(cross_pythia)s %(nb_event_pythia)s\n" 2176 else: 2177 text = "%(run_name)s %(tag)s %(cross)s %(error)s %(nb_event)s\n" 2178 fsock.write(text % data)
2179 2180 ############################################################################
2181 - def do_calculate_decay_widths(self, line):
2182 """Main Commands: launch decay width calculation and automatic inclusion of 2183 calculated widths and BRs in the param_card.""" 2184 2185 args = self.split_arg(line) 2186 # Check argument's validity 2187 accuracy = self.check_calculate_decay_widths(args) 2188 self.ask_run_configuration('parton') 2189 self.banner = None 2190 if not args: 2191 # No run name assigned -> assigned one automaticaly 2192 self.set_run_name(self.find_available_run_name(self.me_dir)) 2193 else: 2194 self.set_run_name(args[0], reload_card=True) 2195 args.pop(0) 2196 2197 self.configure_directory() 2198 2199 # Running gridpack warmup 2200 opts=[('accuracy', accuracy), # default 0.01 2201 ('points', 1000), 2202 ('iterations',9)] 2203 2204 logger.info('Calculating decay widths with run name %s' % self.run_name) 2205 2206 self.exec_cmd('survey %s %s' % \ 2207 (self.run_name, 2208 " ".join(['--' + opt + '=' + str(val) for (opt,val) \ 2209 in opts])), 2210 postcmd=False) 2211 self.refine_mode = "old" # specify how to combine event 2212 self.exec_cmd('combine_events', postcmd=False) 2213 self.exec_cmd('store_events', postcmd=False) 2214 2215 self.collect_decay_widths() 2216 self.print_results_in_shell(self.results.current) 2217 self.update_status('calculate_decay_widths done', 2218 level='parton', makehtml=False)
2219 2220 2221 ############################################################################
2222 - def collect_decay_widths(self):
2223 """ Collect the decay widths and calculate BRs for all particles, and put 2224 in param_card form. 2225 """ 2226 2227 particle_dict = {} # store the results 2228 run_name = self.run_name 2229 2230 # Looping over the Subprocesses 2231 for P_path in SubProcesses.get_subP(self.me_dir): 2232 ids = SubProcesses.get_subP_ids(P_path) 2233 # due to grouping we need to compute the ratio factor for the 2234 # ungroup resutls (that we need here). Note that initial particles 2235 # grouping are not at the same stage as final particle grouping 2236 nb_output = len(ids) / (len(set([p[0] for p in ids]))) 2237 results = open(pjoin(P_path, run_name + '_results.dat')).read().split('\n')[0] 2238 result = float(results.strip().split(' ')[0]) 2239 for particles in ids: 2240 try: 2241 particle_dict[particles[0]].append([particles[1:], result/nb_output]) 2242 except KeyError: 2243 particle_dict[particles[0]] = [[particles[1:], result/nb_output]] 2244 2245 self.update_width_in_param_card(particle_dict, 2246 initial = pjoin(self.me_dir, 'Cards', 'param_card.dat'), 2247 output=pjoin(self.me_dir, 'Events', run_name, "param_card.dat"))
2248 2249 @staticmethod
2250 - def update_width_in_param_card(decay_info, initial=None, output=None):
2251 # Open the param_card.dat and insert the calculated decays and BRs 2252 2253 if not output: 2254 output = initial 2255 2256 param_card_file = open(initial) 2257 param_card = param_card_file.read().split('\n') 2258 param_card_file.close() 2259 2260 decay_lines = [] 2261 line_number = 0 2262 # Read and remove all decays from the param_card 2263 while line_number < len(param_card): 2264 line = param_card[line_number] 2265 if line.lower().startswith('decay'): 2266 # Read decay if particle in decay_info 2267 # DECAY 6 1.455100e+00 2268 line = param_card.pop(line_number) 2269 line = line.split() 2270 particle = 0 2271 if int(line[1]) not in decay_info: 2272 try: # If formatting is wrong, don't want this particle 2273 particle = int(line[1]) 2274 width = float(line[2]) 2275 except Exception: 2276 particle = 0 2277 # Read BRs for this decay 2278 line = param_card[line_number] 2279 while line.startswith('#') or line.startswith(' '): 2280 line = param_card.pop(line_number) 2281 if not particle or line.startswith('#'): 2282 line=param_card[line_number] 2283 continue 2284 # 6.668201e-01 3 5 2 -1 2285 line = line.split() 2286 try: # Remove BR if formatting is wrong 2287 partial_width = float(line[0])*width 2288 decay_products = [int(p) for p in line[2:2+int(line[1])]] 2289 except Exception: 2290 line=param_card[line_number] 2291 continue 2292 try: 2293 decay_info[particle].append([decay_products, partial_width]) 2294 except KeyError: 2295 decay_info[particle] = [[decay_products, partial_width]] 2296 if line_number == len(param_card): 2297 break 2298 line=param_card[line_number] 2299 if particle and particle not in decay_info: 2300 # No decays given, only total width 2301 decay_info[particle] = [[[], width]] 2302 else: # Not decay 2303 line_number += 1 2304 # Clean out possible remaining comments at the end of the card 2305 while not param_card[-1] or param_card[-1].startswith('#'): 2306 param_card.pop(-1) 2307 2308 # Append calculated and read decays to the param_card 2309 param_card.append("#\n#*************************") 2310 param_card.append("# Decay widths *") 2311 param_card.append("#*************************") 2312 for key in sorted(decay_info.keys()): 2313 width = sum([r for p,r in decay_info[key]]) 2314 param_card.append("#\n# PDG Width") 2315 param_card.append("DECAY %i %e" % (key, width.real)) 2316 if not width: 2317 continue 2318 if decay_info[key][0][0]: 2319 param_card.append("# BR NDA ID1 ID2 ...") 2320 brs = [[(val[1]/width).real, val[0]] for val in decay_info[key] if val[1]] 2321 for val in sorted(brs, reverse=True): 2322 param_card.append(" %e %i %s # %s" % 2323 (val[0].real, len(val[1]), 2324 " ".join([str(v) for v in val[1]]), 2325 val[0] * width 2326 )) 2327 decay_table = open(output, 'w') 2328 decay_table.write("\n".join(param_card) + "\n") 2329 decay_table.close() 2330 logger.info("Results written to %s" % output)
2331 2332 2333 ############################################################################
2334 - def do_multi_run(self, line):
2335 2336 args = self.split_arg(line) 2337 # Check argument's validity 2338 mode = self.check_multi_run(args) 2339 nb_run = args.pop(0) 2340 if nb_run == 1: 2341 logger.warn("'multi_run 1' command is not optimal. Think of using generate_events instead") 2342 self.ask_run_configuration(mode) 2343 2344 self.check_survey(args, cmd='multi_run') 2345 main_name = self.run_name 2346 # check if the param_card requires a scan over parameter. 2347 path=pjoin(self.me_dir, 'Cards', 'param_card.dat') 2348 self.check_param_card(path, run=False) 2349 #store it locally to avoid relaunch 2350 param_card_iterator, self.param_card_iterator = self.param_card_iterator, [] 2351 2352 crossoversig = 0 2353 inv_sq_err = 0 2354 nb_event = 0 2355 for i in range(nb_run): 2356 self.nb_refine = 0 2357 self.exec_cmd('generate_events %s_%s -f' % (main_name, i), postcmd=False) 2358 # Update collected value 2359 nb_event += int(self.results[self.run_name][-1]['nb_event']) 2360 self.results.add_detail('nb_event', nb_event , run=main_name) 2361 cross = self.results[self.run_name][-1]['cross'] 2362 error = self.results[self.run_name][-1]['error'] + 1e-99 2363 crossoversig+=cross/error**2 2364 inv_sq_err+=1.0/error**2 2365 self.results[main_name][-1]['cross'] = crossoversig/inv_sq_err 2366 self.results[main_name][-1]['error'] = math.sqrt(1.0/inv_sq_err) 2367 self.results.def_current(main_name) 2368 self.run_name = main_name 2369 self.update_status("Merging LHE files", level='parton') 2370 try: 2371 os.mkdir(pjoin(self.me_dir,'Events', self.run_name)) 2372 except Exception: 2373 pass 2374 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' 2375 % {'bin': self.dirbin, 'event': pjoin(self.me_dir,'Events'), 2376 'name': self.run_name}) 2377 2378 eradir = self.options['exrootanalysis_path'] 2379 if eradir and misc.is_executable(pjoin(eradir,'ExRootLHEFConverter')): 2380 self.update_status("Create Root file", level='parton') 2381 misc.gunzip('%s/%s/unweighted_events.lhe.gz' % 2382 (pjoin(self.me_dir,'Events'), self.run_name)) 2383 2384 self.create_root_file('%s/unweighted_events.lhe' % self.run_name, 2385 '%s/unweighted_events.root' % self.run_name) 2386 2387 path = pjoin(self.me_dir, "Events", self.run_name, "unweighted_events.lhe") 2388 self.create_plot('parton', path, 2389 pjoin(self.me_dir, 'HTML',self.run_name, 'plots_parton.html') 2390 ) 2391 2392 2393 if not os.path.exists('%s.gz' % path): 2394 misc.gzip(path) 2395 2396 self.update_status('', level='parton') 2397 self.print_results_in_shell(self.results.current) 2398 2399 if param_card_iterator: 2400 2401 param_card_iterator.store_entry(self.run_name, self.results.current['cross']) 2402 #check if the param_card defines a scan. 2403 orig_name=self.run_name 2404 for card in param_card_iterator: 2405 card.write(pjoin(self.me_dir,'Cards','param_card.dat')) 2406 self.exec_cmd("multi_run %s -f " % nb_run ,precmd=True, postcmd=True,errorhandling=False) 2407 param_card_iterator.store_entry(self.run_name, self.results.current['cross']) 2408 param_card_iterator.write(pjoin(self.me_dir,'Cards','param_card.dat')) 2409 scan_name = misc.get_scan_name(orig_name, self.run_name) 2410 path = pjoin(self.me_dir, 'Events','scan_%s.txt' % scan_name) 2411 logger.info("write all cross-section results in %s" % path, '$MG:color:BLACK') 2412 param_card_iterator.write_summary(path)
2413 2414 2415 ############################################################################
2416 - def do_treatcards(self, line, mode=None, opt=None):
2417 """Advanced commands: create .inc files from param_card.dat/run_card.dat""" 2418 2419 if not mode and not opt: 2420 args = self.split_arg(line) 2421 mode, opt = self.check_treatcards(args) 2422 2423 # To decide whether to refresh MadLoop's helicity filters, it is necessary 2424 # to check if the model parameters where modified or not, before doing 2425 # anything else. 2426 need_MadLoopFilterUpdate = False 2427 # Just to record what triggered the reinitialization of MadLoop for a 2428 # nice debug message. 2429 type_of_change = '' 2430 if not opt['forbid_MadLoopInit'] and self.proc_characteristics['loop_induced'] \ 2431 and mode in ['loop', 'all']: 2432 paramDat = pjoin(self.me_dir, 'Cards','param_card.dat') 2433 paramInc = pjoin(opt['output_dir'], 'param_card.inc') 2434 if (not os.path.isfile(paramDat)) or (not os.path.isfile(paramInc)) or \ 2435 (os.path.getmtime(paramDat)-os.path.getmtime(paramInc)) > 0.0: 2436 need_MadLoopFilterUpdate = True 2437 type_of_change = 'model' 2438 2439 ML_in = pjoin(self.me_dir, 'Cards', 'MadLoopParams.dat') 2440 ML_out = pjoin(self.me_dir,"SubProcesses", 2441 "MadLoop5_resources", "MadLoopParams.dat") 2442 if (not os.path.isfile(ML_in)) or (not os.path.isfile(ML_out)) or \ 2443 (os.path.getmtime(ML_in)-os.path.getmtime(ML_out)) > 0.0: 2444 need_MadLoopFilterUpdate = True 2445 type_of_change = 'MadLoop' 2446 2447 #check if no 'Auto' are present in the file 2448 self.check_param_card(pjoin(self.me_dir, 'Cards','param_card.dat')) 2449 2450 if mode in ['param', 'all']: 2451 model = self.find_model_name() 2452 tmp_model = os.path.basename(model) 2453 if tmp_model == 'mssm' or tmp_model.startswith('mssm-'): 2454 if not '--param_card=' in line: 2455 param_card = pjoin(self.me_dir, 'Cards','param_card.dat') 2456 mg5_param = pjoin(self.me_dir, 'Source', 'MODEL', 'MG5_param.dat') 2457 check_param_card.convert_to_mg5card(param_card, mg5_param) 2458 check_param_card.check_valid_param_card(mg5_param) 2459 opt['param_card'] = pjoin(self.me_dir, 'Source', 'MODEL', 'MG5_param.dat') 2460 else: 2461 check_param_card.check_valid_param_card(opt['param_card']) 2462 2463 logger.debug('write compile file for card: %s' % opt['param_card']) 2464 param_card = check_param_card.ParamCard(opt['param_card']) 2465 outfile = pjoin(opt['output_dir'], 'param_card.inc') 2466 ident_card = pjoin(self.me_dir,'Cards','ident_card.dat') 2467 if os.path.isfile(pjoin(self.me_dir,'bin','internal','ufomodel','restrict_default.dat')): 2468 default = pjoin(self.me_dir,'bin','internal','ufomodel','restrict_default.dat') 2469 elif os.path.isfile(pjoin(self.me_dir,'bin','internal','ufomodel','param_card.dat')): 2470 default = pjoin(self.me_dir,'bin','internal','ufomodel','param_card.dat') 2471 elif not os.path.exists(pjoin(self.me_dir,'bin','internal','ufomodel')): 2472 fsock = open(pjoin(self.me_dir,'Source','param_card.inc'),'w') 2473 fsock.write(' ') 2474 fsock.close() 2475 if mode == 'all': 2476 self.do_treatcards('', 'run', opt) 2477 return 2478 else: 2479 devnull = open(os.devnull,'w') 2480 subprocess.call([sys.executable, 'write_param_card.py'], 2481 cwd=pjoin(self.me_dir,'bin','internal','ufomodel'), 2482 stdout=devnull) 2483 devnull.close() 2484 default = pjoin(self.me_dir,'bin','internal','ufomodel','param_card.dat') 2485 2486 need_mp = self.proc_characteristics['loop_induced'] 2487 param_card.write_inc_file(outfile, ident_card, default, need_mp=need_mp) 2488 2489 2490 if mode in ['run', 'all']: 2491 if not hasattr(self, 'run_card'): 2492 run_card = banner_mod.RunCard(opt['run_card']) 2493 else: 2494 run_card = self.run_card 2495 if self.ninitial == 1: 2496 run_card['lpp1'] = 0 2497 run_card['lpp2'] = 0 2498 run_card['ebeam1'] = 0 2499 run_card['ebeam2'] = 0 2500 2501 run_card.write_include_file(pjoin(opt['output_dir'],'run_card.inc')) 2502 2503 2504 if self.proc_characteristics['loop_induced'] and mode in ['loop', 'all']: 2505 self.MadLoopparam = banner_mod.MadLoopParam(pjoin(self.me_dir, 2506 'Cards', 'MadLoopParams.dat')) 2507 # The writing out of MadLoop filter is potentially dangerous 2508 # when running in multi-core with a central disk. So it is turned 2509 # off here. If these filters were not initialized then they will 2510 # have to be re-computed at the beginning of each run. 2511 if 'WriteOutFilters' in self.MadLoopparam.user_set and \ 2512 self.MadLoopparam.get('WriteOutFilters'): 2513 logger.info( 2514 """You chose to have MadLoop writing out filters. 2515 Beware that this can be dangerous for local multicore runs.""") 2516 self.MadLoopparam.set('WriteOutFilters',False, ifnotdefault=False) 2517 2518 # The conservative settings below for 'CTModeInit' and 'ZeroThres' 2519 # help adress issues for processes like g g > h z, and g g > h g 2520 # where there are some helicity configuration heavily suppressed 2521 # (by several orders of magnitude) so that the helicity filter 2522 # needs high numerical accuracy to correctly handle this spread in 2523 # magnitude. Also, because one cannot use the Born as a reference 2524 # scale, it is better to force quadruple precision *for the 2525 # initialization points only*. This avoids numerical accuracy issues 2526 # when setting up the helicity filters and does not significantly 2527 # slow down the run. 2528 # self.MadLoopparam.set('CTModeInit',4, ifnotdefault=False) 2529 # Consequently, we can allow for a finer threshold for vanishing 2530 # helicity configuration 2531 # self.MadLoopparam.set('ZeroThres',1.0e-11, ifnotdefault=False) 2532 2533 # It is a bit superficial to use the level 2 which tries to numerically 2534 # map matching helicities (because of CP symmetry typically) together. 2535 # It is useless in the context of MC over helicities and it can 2536 # potentially make the helicity double checking fail. 2537 self.MadLoopparam.set('HelicityFilterLevel',1, ifnotdefault=False) 2538 2539 # To be on the safe side however, we ask for 4 consecutive matching 2540 # helicity filters. 2541 self.MadLoopparam.set('CheckCycle',4, ifnotdefault=False) 2542 2543 # For now it is tricky to have eahc channel performing the helicity 2544 # double check. What we will end up doing is probably some kind 2545 # of new initialization round at the beginning of each launch 2546 # command, to reset the filters. 2547 self.MadLoopparam.set('DoubleCheckHelicityFilter',False, 2548 ifnotdefault=False) 2549 2550 # Thanks to TIR recycling, TIR is typically much faster for Loop-induced 2551 # processes, so that we place OPP last. 2552 if not hasattr(self, 'run_card'): 2553 run_card = banner_mod.RunCard(opt['run_card']) 2554 else: 2555 run_card = self.run_card 2556 if run_card['nhel'] == 0: 2557 if 'MLReductionLib' in self.MadLoopparam.user_set and \ 2558 (self.MadLoopparam.get('MLReductionLib').startswith('1') or 2559 self.MadLoopparam.get('MLReductionLib').startswith('6')): 2560 logger.warning( 2561 """You chose to set the preferred reduction technique in MadLoop to be OPP (see parameter MLReductionLib). 2562 Beware that this can bring significant slowdown; the optimal choice --when not MC over helicity-- being to first start with TIR reduction.""") 2563 # We do not include GOLEM for now since it cannot recycle TIR coefs yet. 2564 self.MadLoopparam.set('MLReductionLib','2|6|1', ifnotdefault=False) 2565 else: 2566 if 'MLReductionLib' in self.MadLoopparam.user_set and \ 2567 not (self.MadLoopparam.get('MLReductionLib').startswith('1') or 2568 self.MadLoopparam.get('MLReductionLib').startswith('6')): 2569 logger.warning( 2570 """You chose to set the preferred reduction technique in MadLoop to be different than OPP (see parameter MLReductionLib). 2571 Beware that this can bring significant slowdown; the optimal choice --when MC over helicity-- being to first start with OPP reduction.""") 2572 self.MadLoopparam.set('MLReductionLib','6|1|2', ifnotdefault=False) 2573 2574 # Also TIR cache will only work when NRotations_DP=0 (but only matters 2575 # when not MC-ing over helicities) so it will be hard-reset by MadLoop 2576 # to zero when not MC-ing over helicities, unless the parameter 2577 # Force_ML_Helicity_Sum is set to True in the matrix<i>.f codes. 2578 if run_card['nhel'] == 0: 2579 if ('NRotations_DP' in self.MadLoopparam.user_set and \ 2580 self.MadLoopparam.get('NRotations_DP')!=0) or \ 2581 ('NRotations_QP' in self.MadLoopparam.user_set and \ 2582 self.MadLoopparam.get('NRotations_QP')!=0): 2583 logger.warning( 2584 """You chose to also use a lorentz rotation for stability tests (see parameter NRotations_[DP|QP]). 2585 Beware that, for optimization purposes, MadEvent uses manual TIR cache clearing which is not compatible 2586 with the lorentz rotation stability test. The number of these rotations to be used will be reset to 2587 zero by MadLoop. You can avoid this by changing the parameter 'FORCE_ML_HELICITY_SUM' int he matrix<i>.f 2588 files to be .TRUE. so that the sum over helicity configurations is performed within MadLoop (in which case 2589 the helicity of final state particles cannot be speicfied in the LHE file.""") 2590 self.MadLoopparam.set('NRotations_DP',0,ifnotdefault=False) 2591 self.MadLoopparam.set('NRotations_QP',0,ifnotdefault=False) 2592 else: 2593 # When MC-ing over helicities, the manual TIR cache clearing is 2594 # not necessary, so that one can use the lorentz check 2595 # Using NRotations_DP=1 slows down the code by close to 100% 2596 # but it is typicaly safer. 2597 # self.MadLoopparam.set('NRotations_DP',0,ifnotdefault=False) 2598 # Revert to the above to be slightly less robust but twice faster. 2599 self.MadLoopparam.set('NRotations_DP',1,ifnotdefault=False) 2600 self.MadLoopparam.set('NRotations_QP',0,ifnotdefault=False) 2601 2602 # Finally, the stability tests are slightly less reliable for process 2603 # with less or equal than 4 final state particles because the 2604 # accessible kinematic is very limited (i.e. lorentz rotations don't 2605 # shuffle invariants numerics much). In these cases, we therefore 2606 # increase the required accuracy to 10^-7. 2607 # This is important for getting g g > z z [QCD] working with a 2608 # ptheavy cut as low as 1 GeV. 2609 if self.proc_characteristics['nexternal']<=4: 2610 if ('MLStabThres' in self.MadLoopparam.user_set and \ 2611 self.MadLoopparam.get('MLStabThres')>1.0e-7): 2612 logger.warning( 2613 """You chose to increase the default value of the MadLoop parameter 'MLStabThres' above 1.0e-7. 2614 Stability tests can be less reliable on the limited kinematic of processes with less or equal 2615 than four external legs, so this is not recommended (especially not for g g > z z).""") 2616 self.MadLoopparam.set('MLStabThres',1.0e-7,ifnotdefault=False) 2617 else: 2618 self.MadLoopparam.set('MLStabThres',1.0e-4,ifnotdefault=False) 2619 2620 #write the output file 2621 self.MadLoopparam.write(pjoin(self.me_dir,"SubProcesses","MadLoop5_resources", 2622 "MadLoopParams.dat")) 2623 2624 if self.proc_characteristics['loop_induced'] and mode in ['loop', 'all']: 2625 # Now Update MadLoop filters if necessary (if modifications were made to 2626 # the model parameters). 2627 if need_MadLoopFilterUpdate: 2628 logger.debug('Changes to the %s parameters'%type_of_change+\ 2629 ' have been detected. Madevent will then now reinitialize'+\ 2630 ' MadLoop filters.') 2631 self.exec_cmd('initMadLoop -r -f') 2632 # The need_MadLoopInit condition is just there so as to avoid useless 2633 # printout if there is not initialization to be performed. But even 2634 # without it, and because we call 'initMadLoop' without the '-r' option 2635 # no time would be wasted anyway, since the existing filters would not 2636 # be overwritten. 2637 elif not opt['forbid_MadLoopInit'] and \ 2638 MadLoopInitializer.need_MadLoopInit(self.me_dir): 2639 self.exec_cmd('initMadLoop -f')
2640 2641 ############################################################################
2642 - def do_survey(self, line):
2643 """Advanced commands: launch survey for the current process """ 2644 2645 2646 args = self.split_arg(line) 2647 # Check argument's validity 2648 self.check_survey(args) 2649 # initialize / remove lhapdf mode 2650 2651 if os.path.exists(pjoin(self.me_dir,'error')): 2652 os.remove(pjoin(self.me_dir,'error')) 2653 2654 self.configure_directory() 2655 # Save original random number 2656 self.random_orig = self.random 2657 logger.info("Using random number seed offset = %s" % self.random) 2658 # Update random number 2659 self.update_random() 2660 self.save_random() 2661 self.update_status('Running Survey', level=None) 2662 if self.cluster_mode: 2663 logger.info('Creating Jobs') 2664 2665 self.total_jobs = 0 2666 subproc = [l.strip() for l in open(pjoin(self.me_dir, 2667 'SubProcesses', 'subproc.mg'))] 2668 2669 P_zero_result = [] # check the number of times where they are no phase-space 2670 2671 # File for the loop (for loop induced) 2672 if os.path.exists(pjoin(self.me_dir,'SubProcesses', 2673 'MadLoop5_resources')) and cluster.need_transfer(self.options): 2674 tf=tarfile.open(pjoin(self.me_dir, 'SubProcesses', 2675 'MadLoop5_resources.tar.gz'), 'w:gz', dereference=True) 2676 tf.add(pjoin(self.me_dir,'SubProcesses','MadLoop5_resources'), 2677 arcname='MadLoop5_resources') 2678 tf.close() 2679 2680 logger.info('Working on SubProcesses') 2681 ajobcreator = gen_ximprove.gensym(self) 2682 2683 #check difficult PS case 2684 if float(self.run_card['mmjj']) > 0.01 * (float(self.run_card['ebeam1'])+float(self.run_card['ebeam2'])): 2685 self.pass_in_difficult_integration_mode() 2686 2687 jobs, P_zero_result = ajobcreator.launch() 2688 2689 # Check if all or only some fails 2690 if P_zero_result: 2691 if len(P_zero_result) == len(subproc): 2692 Pdir = pjoin(self.me_dir, 'SubProcesses',subproc[0].strip()) 2693 raise ZeroResult, '%s' % \ 2694 open(pjoin(Pdir,'ajob.no_ps.log')).read() 2695 else: 2696 logger.warning(''' %s SubProcesses doesn\'t have available phase-space. 2697 Please check mass spectrum.''' % ','.join(P_zero_result)) 2698 2699 2700 self.monitor(run_type='All jobs submitted for survey', html=True) 2701 if not self.history or 'survey' in self.history[-1] or self.ninitial ==1 or \ 2702 self.run_card['gridpack']: 2703 #will be done during the refine (more precisely in gen_ximprove) 2704 cross, error = sum_html.make_all_html_results(self) 2705 self.results.add_detail('cross', cross) 2706 self.results.add_detail('error', error) 2707 self.exec_cmd("print_results %s" % self.run_name, 2708 errorhandling=False, printcmd=False, precmd=False, postcmd=False) 2709 2710 self.results.add_detail('run_statistics', dict(ajobcreator.run_statistics)) 2711 self.update_status('End survey', 'parton', makehtml=False)
2712 2713 ############################################################################
2714 - def pass_in_difficult_integration_mode(self):
2715 """be more secure for the integration to not miss it due to strong cut""" 2716 2717 # improve survey options if default 2718 if self.opts['points'] == self._survey_options['points'][1]: 2719 self.opts['points'] = 2 * self._survey_options['points'][1] 2720 if self.opts['iterations'] == self._survey_options['iterations'][1]: 2721 self.opts['iterations'] = 1 + self._survey_options['iterations'][1] 2722 if self.opts['accuracy'] == self._survey_options['accuracy'][1]: 2723 self.opts['accuracy'] = self._survey_options['accuracy'][1]/2 2724 2725 # Modify run_config.inc in order to improve the refine 2726 #conf_path = pjoin(self.me_dir, 'Source','run_config.inc') 2727 #files.cp(conf_path, conf_path + '.bk') 2728 # 2729 #text = open(conf_path).read() 2730 #text = re.sub('''\(min_events = \d+\)''', '''(min_events = 7500 )''', text) 2731 #text = re.sub('''\(max_events = \d+\)''', '''(max_events = 20000 )''', text) 2732 #fsock = open(conf_path, 'w') 2733 #fsock.write(text) 2734 #fsock.close() 2735 2736 # Compile 2737 for name in ['../bin/internal/gen_ximprove', 'all', 2738 '../bin/internal/combine_events']: 2739 self.compile(arg=[name], cwd=os.path.join(self.me_dir, 'Source'))
2740 2741 2742 ############################################################################
2743 - def do_refine(self, line):
2744 """Advanced commands: launch survey for the current process """ 2745 devnull = open(os.devnull, 'w') 2746 self.nb_refine += 1 2747 args = self.split_arg(line) 2748 # Check argument's validity 2749 self.check_refine(args) 2750 2751 refine_opt = {'err_goal': args[0], 'split_channels': True} 2752 precision = args[0] 2753 if len(args) == 2: 2754 refine_opt['max_process']= args[1] 2755 2756 2757 # initialize / remove lhapdf mode 2758 self.configure_directory() 2759 2760 # Update random number 2761 self.update_random() 2762 self.save_random() 2763 2764 if self.cluster_mode: 2765 logger.info('Creating Jobs') 2766 self.update_status('Refine results to %s' % precision, level=None) 2767 2768 self.total_jobs = 0 2769 subproc = [l.strip() for l in open(pjoin(self.me_dir,'SubProcesses', 2770 'subproc.mg'))] 2771 2772 # cleanning the previous job 2773 for nb_proc,subdir in enumerate(subproc): 2774 subdir = subdir.strip() 2775 Pdir = pjoin(self.me_dir, 'SubProcesses', subdir) 2776 for match in misc.glob('*ajob*', Pdir): 2777 if os.path.basename(match)[:4] in ['ajob', 'wait', 'run.', 'done']: 2778 os.remove(match) 2779 2780 x_improve = gen_ximprove.gen_ximprove(self, refine_opt) 2781 # Load the run statistics from the survey 2782 survey_statistics = dict(self.results.get_detail('run_statistics')) 2783 # Printout survey statistics 2784 if __debug__ and survey_statistics: 2785 globalstat = sum_html.RunStatistics() 2786 logger.debug(" === Survey statistics summary ===") 2787 for key, value in survey_statistics.items(): 2788 globalstat.aggregate_statistics(value) 2789 level = 5 2790 if value.has_warning(): 2791 level = 10 2792 logger.log(level, 2793 value.nice_output(str('/'.join([key[0],'G%s'%key[1]]))). 2794 replace(' statistics','')) 2795 logger.debug(globalstat.nice_output('combined', no_warning=True)) 2796 2797 if survey_statistics: 2798 x_improve.run_statistics = survey_statistics 2799 2800 x_improve.launch() # create the ajob for the refinment. 2801 if not self.history or 'refine' not in self.history[-1]: 2802 cross, error = x_improve.update_html() #update html results for survey 2803 if cross == 0: 2804 return 2805 logger.info("Current estimate of cross-section: %s +- %s" % (cross, error)) 2806 2807 2808 if isinstance(x_improve, gen_ximprove.gen_ximprove_v4): 2809 # Non splitted mode is based on writting ajob so need to track them 2810 # Splitted mode handle the cluster submition internally. 2811 for nb_proc,subdir in enumerate(subproc): 2812 subdir = subdir.strip() 2813 Pdir = pjoin(self.me_dir, 'SubProcesses',subdir) 2814 bindir = pjoin(os.path.relpath(self.dirbin, Pdir)) 2815 2816 logger.info(' %s ' % subdir) 2817 2818 if os.path.exists(pjoin(Pdir, 'ajob1')): 2819 self.compile(['madevent'], cwd=Pdir) 2820 2821 alljobs = misc.glob('ajob*', Pdir) 2822 2823 #remove associated results.dat (ensure to not mix with all data) 2824 Gre = re.compile("\s*j=(G[\d\.\w]+)") 2825 for job in alljobs: 2826 Gdirs = Gre.findall(open(job).read()) 2827 for Gdir in Gdirs: 2828 if os.path.exists(pjoin(Pdir, Gdir, 'results.dat')): 2829 os.remove(pjoin(Pdir, Gdir,'results.dat')) 2830 2831 nb_tot = len(alljobs) 2832 self.total_jobs += nb_tot 2833 for i, job in enumerate(alljobs): 2834 job = os.path.basename(job) 2835 self.launch_job('%s' % job, cwd=Pdir, remaining=(nb_tot-i-1), 2836 run_type='Refine number %s on %s (%s/%s)' % 2837 (self.nb_refine, subdir, nb_proc+1, len(subproc))) 2838 2839 self.monitor(run_type='All job submitted for refine number %s' % self.nb_refine, 2840 html=True) 2841 2842 self.update_status("Combining runs", level='parton') 2843 try: 2844 os.remove(pjoin(Pdir, 'combine_runs.log')) 2845 except Exception: 2846 pass 2847 2848 if isinstance(x_improve, gen_ximprove.gen_ximprove_v4): 2849 # the merge of the events.lhe is handle in the x_improve class 2850 # for splitted runs. (and partly in store_events). 2851 combine_runs.CombineRuns(self.me_dir) 2852 self.refine_mode = "old" 2853 else: 2854 self.refine_mode = "new" 2855 2856 cross, error = sum_html.make_all_html_results(self) 2857 self.results.add_detail('cross', cross) 2858 self.results.add_detail('error', error) 2859 2860 self.results.add_detail('run_statistics', 2861 dict(self.results.get_detail('run_statistics'))) 2862 2863 self.update_status('finish refine', 'parton', makehtml=False) 2864 devnull.close()
2865 2866 ############################################################################
2867 - def do_combine_iteration(self, line):
2868 """Not in help: Combine a given iteration combine_iteration Pdir Gdir S|R step 2869 S is for survey 2870 R is for refine 2871 step is the iteration number (not very critical)""" 2872 2873 self.set_run_name("tmp") 2874 self.configure_directory(html_opening=False) 2875 Pdir, Gdir, mode, step = self.split_arg(line) 2876 if Gdir.startswith("G"): 2877 Gdir = Gdir[1:] 2878 if "SubProcesses" not in Pdir: 2879 Pdir = pjoin(self.me_dir, "SubProcesses", Pdir) 2880 if mode == "S": 2881 self.opts = dict([(key,value[1]) for (key,value) in \ 2882 self._survey_options.items()]) 2883 gensym = gen_ximprove.gensym(self) 2884 gensym.combine_iteration(Pdir, Gdir, int(step)) 2885 elif mode == "R": 2886 refine = gen_ximprove.gen_ximprove_share(self) 2887 refine.combine_iteration(Pdir, Gdir, int(step))
2888 2889 2890 2891 2892 ############################################################################
2893 - def do_combine_events(self, line):
2894 """Advanced commands: Launch combine events""" 2895 2896 args = self.split_arg(line) 2897 # Check argument's validity 2898 self.check_combine_events(args) 2899 2900 self.update_status('Combining Events', level='parton') 2901 2902 2903 if not hasattr(self, "refine_mode") or self.refine_mode == "old": 2904 try: 2905 os.remove(pjoin(self.me_dir,'SubProcesses', 'combine.log')) 2906 except Exception: 2907 pass 2908 2909 tmpcluster = cluster.MultiCore(nb_core=1) 2910 tmpcluster.launch_and_wait('../bin/internal/run_combine', 2911 args=[self.run_name], 2912 cwd=pjoin(self.me_dir,'SubProcesses'), 2913 stdout=pjoin(self.me_dir,'SubProcesses', 'combine.log'), 2914 required_output=[pjoin(self.me_dir,'SubProcesses', 'combine.log')]) 2915 2916 #self.cluster.launch_and_wait('../bin/internal/run_combine', 2917 # cwd=pjoin(self.me_dir,'SubProcesses'), 2918 # stdout=pjoin(self.me_dir,'SubProcesses', 'combine.log'), 2919 # required_output=[pjoin(self.me_dir,'SubProcesses', 'combine.log')]) 2920 2921 output = misc.mult_try_open(pjoin(self.me_dir,'SubProcesses','combine.log')).read() 2922 # Store the number of unweighted events for the results object 2923 pat = re.compile(r'''\s*Unweighting\s*selected\s*(\d+)\s*events''') 2924 try: 2925 nb_event = pat.search(output).groups()[0] 2926 except AttributeError: 2927 time.sleep(10) 2928 output = misc.mult_try_open(pjoin(self.me_dir,'SubProcesses','combine.log')).read() 2929 try: 2930 nb_event = pat.search(output).groups()[0] 2931 except AttributeError: 2932 logger.warning('Fail to read the number of unweighted events in the combine.log file') 2933 nb_event = 0 2934 2935 self.results.add_detail('nb_event', nb_event) 2936 2937 2938 # Define The Banner 2939 tag = self.run_card['run_tag'] 2940 2941 # Update the banner with the pythia card 2942 if not self.banner: 2943 self.banner = banner_mod.recover_banner(self.results, 'parton') 2944 self.banner.load_basic(self.me_dir) 2945 # Add cross-section/event information 2946 self.banner.add_generation_info(self.results.current['cross'], nb_event) 2947 if not hasattr(self, 'random_orig'): self.random_orig = 0 2948 self.banner.change_seed(self.random_orig) 2949 if not os.path.exists(pjoin(self.me_dir, 'Events', self.run_name)): 2950 os.mkdir(pjoin(self.me_dir, 'Events', self.run_name)) 2951 self.banner.write(pjoin(self.me_dir, 'Events', self.run_name, 2952 '%s_%s_banner.txt' % (self.run_name, tag))) 2953 2954 2955 self.banner.add_to_file(pjoin(self.me_dir,'Events', 'events.lhe'), 2956 out=pjoin(self.me_dir,'Events', self.run_name, 'events.lhe')) 2957 self.banner.add_to_file(pjoin(self.me_dir,'Events', 'unweighted_events.lhe'), 2958 out=pjoin(self.me_dir,'Events', self.run_name, 'unweighted_events.lhe')) 2959 2960 2961 elif self.refine_mode == "new": 2962 # Define The Banner 2963 tag = self.run_card['run_tag'] 2964 # Update the banner with the pythia card 2965 if not self.banner: 2966 self.banner = banner_mod.recover_banner(self.results, 'parton') 2967 self.banner.load_basic(self.me_dir) 2968 # Add cross-section/event information 2969 self.banner.add_generation_info(self.results.current['cross'], self.run_card['nevents']) 2970 if not hasattr(self, 'random_orig'): self.random_orig = 0 2971 self.banner.change_seed(self.random_orig) 2972 if not os.path.exists(pjoin(self.me_dir, 'Events', self.run_name)): 2973 os.mkdir(pjoin(self.me_dir, 'Events', self.run_name)) 2974 self.banner.write(pjoin(self.me_dir, 'Events', self.run_name, 2975 '%s_%s_banner.txt' % (self.run_name, tag))) 2976 2977 2978 AllEvent = lhe_parser.MultiEventFile() 2979 AllEvent.banner = self.banner 2980 2981 for Gdir,mfactor in self.get_Gdir(): 2982 if os.path.exists(pjoin(Gdir, 'events.lhe')): 2983 result = sum_html.OneResult('') 2984 result.read_results(pjoin(Gdir, 'results.dat')) 2985 AllEvent.add(pjoin(Gdir, 'events.lhe'), 2986 result.get('xsec'), 2987 result.get('xerru'), 2988 result.get('axsec') 2989 ) 2990 2991 get_wgt = lambda event: event.wgt 2992 nb_event = AllEvent.unweight(pjoin(self.me_dir, "Events", self.run_name, "unweighted_events.lhe.gz"), 2993 get_wgt, trunc_error=1e-2, event_target=self.run_card['nevents'], 2994 log_level=logging.DEBUG) 2995 2996 self.results.add_detail('nb_event', nb_event) 2997 2998 self.to_store.append('event') 2999 eradir = self.options['exrootanalysis_path'] 3000 madir = self.options['madanalysis_path'] 3001 td = self.options['td_path'] 3002 if eradir and misc.is_executable(pjoin(eradir,'ExRootLHEFConverter')) and\ 3003 os.path.exists(pjoin(self.me_dir, 'Events', 'unweighted_events.lhe')): 3004 if not os.path.exists(pjoin(self.me_dir, 'Events', self.run_name)): 3005 os.mkdir(pjoin(self.me_dir, 'Events', self.run_name)) 3006 self.create_root_file(output='%s/unweighted_events.root' % \ 3007 self.run_name)
3008 3009 ############################################################################
3010 - def do_store_events(self, line):
3011 """Advanced commands: Launch store events""" 3012 3013 args = self.split_arg(line) 3014 # Check argument's validity 3015 self.check_combine_events(args) 3016 self.update_status('Storing parton level results', level='parton') 3017 3018 run = self.run_name 3019 tag = self.run_card['run_tag'] 3020 devnull = open(os.devnull, 'w') 3021 3022 if not os.path.exists(pjoin(self.me_dir, 'Events', run)): 3023 os.mkdir(pjoin(self.me_dir, 'Events', run)) 3024 if not os.path.exists(pjoin(self.me_dir, 'HTML', run)): 3025 os.mkdir(pjoin(self.me_dir, 'HTML', run)) 3026 3027 # 1) Store overall process information 3028 input = pjoin(self.me_dir, 'SubProcesses', 'results.dat') 3029 output = pjoin(self.me_dir, 'SubProcesses', '%s_results.dat' % run) 3030 files.cp(input, output) 3031 3032 3033 # 2) Treat the files present in the P directory 3034 # Ensure that the number of events is different of 0 3035 if self.results.current['nb_event'] == 0: 3036 logger.warning("No event detected. No cleaning performed! This should allow to run:\n" + 3037 " cd Subprocesses; ../bin/internal/combine_events\n"+ 3038 " to have your events if those one are missing.") 3039 else: 3040 for P_path in SubProcesses.get_subP(self.me_dir): 3041 G_dir = [G for G in os.listdir(P_path) if G.startswith('G') and 3042 os.path.isdir(pjoin(P_path,G))] 3043 for G in G_dir: 3044 G_path = pjoin(P_path,G) 3045 try: 3046 # Remove events file (if present) 3047 if os.path.exists(pjoin(G_path, 'events.lhe')): 3048 os.remove(pjoin(G_path, 'events.lhe')) 3049 except Exception: 3050 continue 3051 try: 3052 # Store results.dat 3053 if os.path.exists(pjoin(G_path, 'results.dat')): 3054 input = pjoin(G_path, 'results.dat') 3055 output = pjoin(G_path, '%s_results.dat' % run) 3056 files.cp(input, output) 3057 except Exception: 3058 continue 3059 # Store log 3060 try: 3061 if os.path.exists(pjoin(G_path, 'log.txt')): 3062 input = pjoin(G_path, 'log.txt') 3063 output = pjoin(G_path, '%s_log.txt' % run) 3064 files.mv(input, output) 3065 except Exception: 3066 continue 3067 try: 3068 # Grid 3069 for name in ['ftn26']: 3070 if os.path.exists(pjoin(G_path, name)): 3071 if os.path.exists(pjoin(G_path, '%s_%s.gz'%(run,name))): 3072 os.remove(pjoin(G_path, '%s_%s.gz'%(run,name))) 3073 input = pjoin(G_path, name) 3074 output = pjoin(G_path, '%s_%s' % (run,name)) 3075 files.mv(input, output) 3076 misc.gzip(pjoin(G_path, output), error=None) 3077 except Exception: 3078 continue 3079 # Delete ftn25 to ensure reproducible runs 3080 if os.path.exists(pjoin(G_path, 'ftn25')): 3081 os.remove(pjoin(G_path, 'ftn25')) 3082 3083 # 3) Update the index.html 3084 misc.call(['%s/gen_cardhtml-pl' % self.dirbin], 3085 cwd=pjoin(self.me_dir)) 3086 3087 3088 # 4) Move the Files present in Events directory 3089 E_path = pjoin(self.me_dir, 'Events') 3090 O_path = pjoin(self.me_dir, 'Events', run) 3091 3092 # The events file 3093 for name in ['events.lhe', 'unweighted_events.lhe']: 3094 finput = pjoin(E_path, name) 3095 foutput = pjoin(O_path, name) 3096 if os.path.exists(finput): 3097 logger.debug("File %s exists BAAAAD. Not move anymore!" % pjoin(E_path, name)) 3098 if os.path.exists(foutput): 3099 misc.gzip(foutput, stdout="%s.gz" % foutput, error=False) 3100 # if os.path.exists(pjoin(O_path, '%s.gz' % name)): 3101 # os.remove(pjoin(O_path, '%s.gz' % name)) 3102 # input = pjoin(E_path, name) 3103 ## output = pjoin(O_path, name) 3104 3105 3106 self.update_status('End Parton', level='parton', makehtml=False) 3107 devnull.close()
3108 3109 3110 ############################################################################
3111 - def do_create_gridpack(self, line):
3112 """Advanced commands: Create gridpack from present run""" 3113 3114 self.update_status('Creating gridpack', level='parton') 3115 # compile gen_ximprove 3116 misc.compile(['../bin/internal/gen_ximprove'], cwd=pjoin(self.me_dir, "Source")) 3117 args = self.split_arg(line) 3118 self.check_combine_events(args) 3119 if not self.run_tag: self.run_tag = 'tag_1' 3120 os.system("sed -i.bak \"s/ *.false.*=.*GridRun/ .true. = GridRun/g\" %s/Cards/grid_card.dat" \ 3121 % self.me_dir) 3122 misc.call(['./bin/internal/restore_data', self.run_name], 3123 cwd=self.me_dir) 3124 misc.call(['./bin/internal/store4grid', 3125 self.run_name, self.run_tag], 3126 cwd=self.me_dir) 3127 misc.call(['./bin/internal/clean'], cwd=self.me_dir) 3128 misc.call(['./bin/internal/make_gridpack'], cwd=self.me_dir) 3129 files.mv(pjoin(self.me_dir, 'gridpack.tar.gz'), 3130 pjoin(self.me_dir, '%s_gridpack.tar.gz' % self.run_name)) 3131 os.system("sed -i.bak \"s/\s*.true.*=.*GridRun/ .false. = GridRun/g\" %s/Cards/grid_card.dat" \ 3132 % self.me_dir) 3133 self.update_status('gridpack created', level='gridpack')
3134 3135 ############################################################################
3136 - def do_pythia(self, line):
3137 """launch pythia""" 3138 3139 # Check argument's validity 3140 args = self.split_arg(line) 3141 if '--no_default' in args: 3142 if not os.path.exists(pjoin(self.me_dir, 'Cards', 'pythia_card.dat')): 3143 return 3144 no_default = True 3145 args.remove('--no_default') 3146 else: 3147 no_default = False 3148 3149 if not self.run_name: 3150 self.check_pythia(args) 3151 self.configure_directory(html_opening =False) 3152 else: 3153 # initialize / remove lhapdf mode 3154 self.configure_directory(html_opening =False) 3155 self.check_pythia(args) 3156 3157 3158 # the args are modify and the last arg is always the mode 3159 if not no_default: 3160 self.ask_pythia_run_configuration(args[-1]) 3161 3162 if self.options['automatic_html_opening']: 3163 misc.open_file(os.path.join(self.me_dir, 'crossx.html')) 3164 self.options['automatic_html_opening'] = False 3165 3166 # Update the banner with the pythia card 3167 if not self.banner or len(self.banner) <=1: 3168 self.banner = banner_mod.recover_banner(self.results, 'pythia') 3169 3170 3171 3172 pythia_src = pjoin(self.options['pythia-pgs_path'],'src') 3173 3174 self.update_status('Running Pythia', 'pythia') 3175 try: 3176 os.remove(pjoin(self.me_dir,'Events','pythia.done')) 3177 except Exception: 3178 pass 3179 3180 ## LAUNCHING PYTHIA 3181 # check that LHAPATH is define. 3182 if not re.search(r'^\s*LHAPATH=%s/PDFsets' % pythia_src, 3183 open(pjoin(self.me_dir,'Cards','pythia_card.dat')).read(), 3184 re.M): 3185 f = open(pjoin(self.me_dir,'Cards','pythia_card.dat'),'a') 3186 f.write('\n LHAPATH=%s/PDFsets' % pythia_src) 3187 f.close() 3188 tag = self.run_tag 3189 pythia_log = pjoin(self.me_dir, 'Events', self.run_name , '%s_pythia.log' % tag) 3190 self.cluster.launch_and_wait('../bin/internal/run_pythia', 3191 argument= [pythia_src], stdout= pythia_log, 3192 stderr=subprocess.STDOUT, 3193 cwd=pjoin(self.me_dir,'Events')) 3194 3195 os.remove(pjoin(self.me_dir, "Events", "unweighted_events.lhe")) 3196 3197 3198 3199 if not os.path.exists(pjoin(self.me_dir,'Events','pythia.done')): 3200 logger.warning('Fail to produce pythia output. More info in \n %s' % pythia_log) 3201 return 3202 else: 3203 os.remove(pjoin(self.me_dir,'Events','pythia.done')) 3204 3205 self.to_store.append('pythia') 3206 3207 # Find the matched cross-section 3208 if int(self.run_card['ickkw']): 3209 # read the line from the bottom of the file 3210 pythia_log = misc.BackRead(pjoin(self.me_dir,'Events', self.run_name, 3211 '%s_pythia.log' % tag)) 3212 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") 3213 for line in pythia_log: 3214 info = pythiare.search(line) 3215 if not info: 3216 continue 3217 try: 3218 # Pythia cross section in mb, we want pb 3219 sigma_m = float(info.group('xsec').replace('D','E')) *1e9 3220 Nacc = int(info.group('generated')) 3221 Ntry = int(info.group('tried')) 3222 except ValueError: 3223 # xsec is not float - this should not happen 3224 self.results.add_detail('cross_pythia', 0) 3225 self.results.add_detail('nb_event_pythia', 0) 3226 self.results.add_detail('error_pythia', 0) 3227 else: 3228 self.results.add_detail('cross_pythia', sigma_m) 3229 self.results.add_detail('nb_event_pythia', Nacc) 3230 #compute pythia error 3231 error = self.results[self.run_name].return_tag(self.run_tag)['error'] 3232 if Nacc: 3233 error_m = math.sqrt((error * Nacc/Ntry)**2 + sigma_m**2 *(1-Nacc/Ntry)/Nacc) 3234 else: 3235 error_m = 10000 * sigma_m 3236 # works both for fixed number of generated events and fixed accepted events 3237 self.results.add_detail('error_pythia', error_m) 3238 break 3239 3240 pythia_log.close() 3241 3242 pydir = pjoin(self.options['pythia-pgs_path'], 'src') 3243 eradir = self.options['exrootanalysis_path'] 3244 madir = self.options['madanalysis_path'] 3245 td = self.options['td_path'] 3246 3247 3248 3249 3250 #Update the banner 3251 self.banner.add(pjoin(self.me_dir, 'Cards','pythia_card.dat')) 3252 if int(self.run_card['ickkw']): 3253 # Add the matched cross-section 3254 if 'MGGenerationInfo' in self.banner: 3255 self.banner['MGGenerationInfo'] += '# Matched Integrated weight (pb) : %s\n' % self.results.current['cross_pythia'] 3256 else: 3257 self.banner['MGGenerationInfo'] = '# Matched Integrated weight (pb) : %s\n' % self.results.current['cross_pythia'] 3258 banner_path = pjoin(self.me_dir, 'Events', self.run_name, '%s_%s_banner.txt' % (self.run_name, tag)) 3259 self.banner.write(banner_path) 3260 3261 # Creating LHE file 3262 self.run_hep2lhe(banner_path) 3263 if int(self.run_card['ickkw']): 3264 misc.gzip(pjoin(self.me_dir,'Events','beforeveto.tree'), 3265 stdout=pjoin(self.me_dir,'Events',self.run_name, tag+'_pythia_beforeveto.tree.gz')) 3266 if self.run_card['use_syst'] in self.true: 3267 # Calculate syscalc info based on syst.dat 3268 try: 3269 self.run_syscalc('Pythia') 3270 except SysCalcError, error: 3271 logger.error(str(error)) 3272 else: 3273 if os.path.exists(pjoin(self.me_dir,'Events', 'syst.dat')): 3274 # Store syst.dat 3275 misc.gzip(pjoin(self.me_dir,'Events', 'syst.dat'), 3276 stdout=pjoin(self.me_dir,'Events',self.run_name, tag + '_pythia_syst.dat.gz')) 3277 3278 # Store syscalc.dat 3279 if os.path.exists(pjoin(self.me_dir, 'Events', 'syscalc.dat')): 3280 filename = pjoin(self.me_dir, 'Events' ,self.run_name, 3281 '%s_syscalc.dat' % self.run_tag) 3282 misc.gzip(pjoin(self.me_dir, 'Events','syscalc.dat'), 3283 stdout = "%s.gz" % filename) 3284 3285 # Plot for pythia 3286 self.create_plot('Pythia') 3287 3288 if os.path.exists(pjoin(self.me_dir,'Events','pythia_events.lhe')): 3289 misc.gzip(pjoin(self.me_dir,'Events','pythia_events.lhe'), 3290 stdout=pjoin(self.me_dir,'Events', self.run_name,'%s_pythia_events.lhe.gz' % tag)) 3291 3292 self.update_status('finish', level='pythia', makehtml=False) 3293 self.exec_cmd('pgs --no_default', postcmd=False, printcmd=False) 3294 if self.options['delphes_path']: 3295 self.exec_cmd('delphes --no_default', postcmd=False, printcmd=False) 3296 self.print_results_in_shell(self.results.current)
3297 3298 3299 ################################################################################
3300 - def do_remove(self, line):
3301 """Remove one/all run or only part of it""" 3302 3303 args = self.split_arg(line) 3304 run, tag, mode = self.check_remove(args) 3305 if 'banner' in mode: 3306 mode.append('all') 3307 3308 3309 if run == 'all': 3310 # Check first if they are not a run with a name run. 3311 if os.path.exists(pjoin(self.me_dir, 'Events', 'all')): 3312 logger.warning('A run with name all exists. So we will not supress all processes.') 3313 else: 3314 for match in misc.glob(pjoin('*','*_banner.txt'), pjoin(self.me_dir, 'Events')): 3315 run = match.rsplit(os.path.sep,2)[1] 3316 if self.force: 3317 args.append('-f') 3318 try: 3319 self.exec_cmd('remove %s %s' % (run, ' '.join(args[1:]) ) ) 3320 except self.InvalidCmd, error: 3321 logger.info(error) 3322 pass # run already clear 3323 return 3324 3325 # Check that run exists 3326 if not os.path.exists(pjoin(self.me_dir, 'Events', run)): 3327 raise self.InvalidCmd('No run \'%s\' detected' % run) 3328 3329 try: 3330 self.resuls.def_current(run) 3331 self.update_status(' Cleaning %s' % run, level=None) 3332 except Exception: 3333 misc.sprint('fail to update results or html status') 3334 pass # Just ensure that html never makes crash this function 3335 3336 3337 # Found the file to delete 3338 3339 to_delete = misc.glob('*', pjoin(self.me_dir, 'Events', run)) 3340 to_delete += misc.glob('*', pjoin(self.me_dir, 'HTML', run)) 3341 # forbid the banner to be removed 3342 to_delete = [os.path.basename(f) for f in to_delete if 'banner' not in f] 3343 if tag: 3344 to_delete = [f for f in to_delete if tag in f] 3345 if 'parton' in mode or 'all' in mode: 3346 try: 3347 if self.results[run][0]['tag'] != tag: 3348 raise Exception, 'dummy' 3349 except Exception: 3350 pass 3351 else: 3352 nb_rm = len(to_delete) 3353 if os.path.exists(pjoin(self.me_dir, 'Events', run, 'events.lhe.gz')): 3354 to_delete.append('events.lhe.gz') 3355 if os.path.exists(pjoin(self.me_dir, 'Events', run, 'unweighted_events.lhe.gz')): 3356 to_delete.append('unweighted_events.lhe.gz') 3357 if os.path.exists(pjoin(self.me_dir, 'HTML', run,'plots_parton.html')): 3358 to_delete.append(pjoin(self.me_dir, 'HTML', run,'plots_parton.html')) 3359 if nb_rm != len(to_delete): 3360 logger.warning('Be carefull that partonic information are on the point to be removed.') 3361 if 'all' in mode: 3362 pass # delete everything 3363 else: 3364 if 'pythia' not in mode: 3365 to_delete = [f for f in to_delete if 'pythia' not in f] 3366 if 'pgs' not in mode: 3367 to_delete = [f for f in to_delete if 'pgs' not in f] 3368 if 'delphes' not in mode: 3369 to_delete = [f for f in to_delete if 'delphes' not in f] 3370 if 'parton' not in mode: 3371 to_delete = [f for f in to_delete if 'delphes' in f 3372 or 'pgs' in f 3373 or 'pythia' in f] 3374 if not self.force and len(to_delete): 3375 question = 'Do you want to delete the following files?\n %s' % \ 3376 '\n '.join(to_delete) 3377 ans = self.ask(question, 'y', choices=['y','n']) 3378 else: 3379 ans = 'y' 3380 3381 if ans == 'y': 3382 for file2rm in to_delete: 3383 if os.path.exists(pjoin(self.me_dir, 'Events', run, file2rm)): 3384 try: 3385 os.remove(pjoin(self.me_dir, 'Events', run, file2rm)) 3386 except Exception: 3387 shutil.rmtree(pjoin(self.me_dir, 'Events', run, file2rm)) 3388 else: 3389 try: 3390 os.remove(pjoin(self.me_dir, 'HTML', run, file2rm)) 3391 except Exception: 3392 shutil.rmtree(pjoin(self.me_dir, 'HTML', run, file2rm)) 3393 3394 3395 3396 # Remove file in SubProcess directory 3397 if 'all' in mode or 'channel' in mode: 3398 try: 3399 if tag and self.results[run][0]['tag'] != tag: 3400 raise Exception, 'dummy' 3401 except Exception: 3402 pass 3403 else: 3404 to_delete = misc.glob('%s*' % run, pjoin(self.me_dir, 'SubProcesses')) 3405 to_delete += misc.glob(pjoin('*','%s*' % run), pjoin(self.me_dir, 'SubProcesses')) 3406 to_delete += misc.glob(pjoin('*','*','%s*' % run), pjoin(self.me_dir, 'SubProcesses')) 3407 3408 if self.force or len(to_delete) == 0: 3409 ans = 'y' 3410 else: 3411 question = 'Do you want to delete the following files?\n %s' % \ 3412 '\n '.join(to_delete) 3413 ans = self.ask(question, 'y', choices=['y','n']) 3414 3415 if ans == 'y': 3416 for file2rm in to_delete: 3417 os.remove(file2rm) 3418 3419 if 'banner' in mode: 3420 to_delete = misc.glob('*', pjoin(self.me_dir, 'Events', run)) 3421 if tag: 3422 # remove banner 3423 try: 3424 os.remove(pjoin(self.me_dir, 'Events',run,'%s_%s_banner.txt' % (run,tag))) 3425 except Exception: 3426 logger.warning('fail to remove the banner') 3427 # remove the run from the html output 3428 if run in self.results: 3429 self.results.delete_run(run, tag) 3430 return 3431 elif any(['banner' not in os.path.basename(p) for p in to_delete]): 3432 if to_delete: 3433 raise MadGraph5Error, '''Some output still exists for this run. 3434 Please remove those output first. Do for example: 3435 remove %s all banner 3436 ''' % run 3437 else: 3438 shutil.rmtree(pjoin(self.me_dir, 'Events',run)) 3439 if run in self.results: 3440 self.results.delete_run(run) 3441 return 3442 else: 3443 logger.info('''The banner is not removed. In order to remove it run: 3444 remove %s all banner %s''' % (run, tag and '--tag=%s ' % tag or '')) 3445 3446 # update database. 3447 self.results.clean(mode, run, tag) 3448 self.update_status('', level='all')
3449 3450 3451 3452 ############################################################################
3453 - def do_plot(self, line):
3454 """Create the plot for a given run""" 3455 3456 # Since in principle, all plot are already done automaticaly 3457 self.store_result() 3458 args = self.split_arg(line) 3459 # Check argument's validity 3460 self.check_plot(args) 3461 logger.info('plot for run %s' % self.run_name) 3462 if not self.force: 3463 self.ask_edit_cards([], args, plot=True) 3464 3465 if any([arg in ['all','parton'] for arg in args]): 3466 filename = pjoin(self.me_dir, 'Events', self.run_name, 'unweighted_events.lhe') 3467 if os.path.exists(filename+'.gz'): 3468 misc.gunzip('%s.gz' % filename, keep=True) 3469 if os.path.exists(filename): 3470 files.ln(filename, pjoin(self.me_dir, 'Events')) 3471 self.create_plot('parton') 3472 if not os.path.exists(filename+'.gz'): 3473 misc.gzip(pjoin(self.me_dir, 'Events', 'unweighted_events.lhe'), 3474 stdout= "%s.gz" % filename) 3475 else: 3476 try: 3477 os.remove(pjoin(self.me_dir, 'Events', 'unweighted_events.lhe')) 3478 os.remove(filename) 3479 except Exception: 3480 pass 3481 else: 3482 logger.info('No valid files for partonic plot') 3483 3484 if any([arg in ['all','pythia'] for arg in args]): 3485 filename = pjoin(self.me_dir, 'Events' ,self.run_name, 3486 '%s_pythia_events.lhe' % self.run_tag) 3487 if os.path.exists(filename+'.gz'): 3488 misc.gunzip("%s.gz" % filename) 3489 if os.path.exists(filename): 3490 shutil.move(filename, pjoin(self.me_dir, 'Events','pythia_events.lhe')) 3491 self.create_plot('Pythia') 3492 misc.gzip(pjoin(self.me_dir, 'Events','pythia_events.lhe'), 3493 stdout= "%s.gz" % filename) 3494 else: 3495 logger.info('No valid files for pythia plot') 3496 3497 3498 if any([arg in ['all','pgs'] for arg in args]): 3499 filename = pjoin(self.me_dir, 'Events', self.run_name, 3500 '%s_pgs_events.lhco' % self.run_tag) 3501 if os.path.exists(filename+'.gz'): 3502 misc.gunzip("%s.gz" % filename) 3503 if os.path.exists(filename): 3504 self.create_plot('PGS') 3505 misc.gzip(filename) 3506 else: 3507 logger.info('No valid files for pgs plot') 3508 3509 if any([arg in ['all','delphes'] for arg in args]): 3510 filename = pjoin(self.me_dir, 'Events', self.run_name, 3511 '%s_delphes_events.lhco' % self.run_tag) 3512 if os.path.exists(filename+'.gz'): 3513 misc.gunzip("%s.gz" % filename) 3514 if os.path.exists(filename): 3515 self.create_plot('Delphes') 3516 misc.gzip(filename) 3517 else: 3518 logger.info('No valid files for delphes plot')
3519 3520 ############################################################################
3521 - def do_syscalc(self, line):
3522 """Evaluate systematics variation weights for a given run""" 3523 3524 # Since in principle, all systematics run are already done automaticaly 3525 self.store_result() 3526 args = self.split_arg(line) 3527 # Check argument's validity 3528 self.check_syscalc(args) 3529 if self.ninitial == 1: 3530 logger.error('SysCalc can\'t be run for decay processes') 3531 return 3532 3533 logger.info('Calculating systematics for run %s' % self.run_name) 3534 3535 self.ask_edit_cards(['run_card'], args) 3536 self.run_card = banner_mod.RunCard(pjoin(self.me_dir, 'Cards', 'run_card.dat')) 3537 3538 if any([arg in ['all','parton'] for arg in args]): 3539 filename = pjoin(self.me_dir, 'Events', self.run_name, 'unweighted_events.lhe') 3540 if os.path.exists(filename+'.gz'): 3541 misc.gunzip("%s.gz" % filename) 3542 if os.path.exists(filename): 3543 shutil.move(filename, pjoin(self.me_dir, 'Events', 'unweighted_events.lhe')) 3544 self.run_syscalc('parton') 3545 misc.gzip(pjoin(self.me_dir, 'Events', 'unweighted_events.lhe'), 3546 stdout="%s.gz" % filename) 3547 else: 3548 logger.info('No valid files for parton level systematics run.') 3549 3550 if any([arg in ['all','pythia'] for arg in args]): 3551 filename = pjoin(self.me_dir, 'Events' ,self.run_name, 3552 '%s_pythia_syst.dat' % self.run_tag) 3553 if os.path.exists(filename+'.gz'): 3554 misc.gunzip("%s.gz" % filename) 3555 if os.path.exists(filename): 3556 shutil.move(filename, pjoin(self.me_dir, 'Events','syst.dat')) 3557 try: 3558 self.run_syscalc('Pythia') 3559 except SysCalcError, error: 3560 logger.warning(str(error)) 3561 return 3562 misc.gzip(pjoin(self.me_dir, 'Events','syst.dat'), "%s.gz" % filename) 3563 filename = pjoin(self.me_dir, 'Events' ,self.run_name, 3564 '%s_syscalc.dat' % self.run_tag) 3565 misc.gzip(pjoin(self.me_dir, 'Events','syscalc.dat'), 3566 stdout=filename) 3567 else: 3568 logger.info('No valid files for pythia level')
3569 3570
3571 - def store_result(self):
3572 """ tar the pythia results. This is done when we are quite sure that 3573 the pythia output will not be use anymore """ 3574 3575 if not self.run_name: 3576 return 3577 3578 self.results.save() 3579 3580 3581 if not self.to_store: 3582 return 3583 3584 tag = self.run_card['run_tag'] 3585 self.update_status('storring files of previous run', level=None,\ 3586 error=True) 3587 if 'event' in self.to_store: 3588 if not os.path.exists(pjoin(self.me_dir, 'Events',self.run_name, 'unweighted_events.lhe.gz')) and\ 3589 os.path.exists(pjoin(self.me_dir, 'Events',self.run_name, 'unweighted_events.lhe')): 3590 logger.info("gzipping output file: unweighted_events.lhe") 3591 misc.gzip(pjoin(self.me_dir,'Events',self.run_name,"unweighted_events.lhe")) 3592 if os.path.exists(pjoin(self.me_dir,'Events','reweight.lhe')): 3593 os.remove(pjoin(self.me_dir,'Events', 'reweight.lhe')) 3594 3595 if 'pythia' in self.to_store: 3596 self.update_status('Storing Pythia files of previous run', level='pythia', error=True) 3597 3598 p = pjoin(self.me_dir,'Events') 3599 n = self.run_name 3600 t = tag 3601 misc.gzip(pjoin(p,'pythia_events.hep'), 3602 stdout=pjoin(p,'%s/%s_pythia_events.hep' % (n,t))) 3603 3604 self.to_store.remove('pythia') 3605 self.update_status('Done', level='pythia',makehtml=False,error=True) 3606 3607 self.to_store = []
3608
3609 - def launch_job(self,exe, cwd=None, stdout=None, argument = [], remaining=0, 3610 run_type='', mode=None, **opt):
3611 """ """ 3612 argument = [str(arg) for arg in argument] 3613 if mode is None: 3614 mode = self.cluster_mode 3615 3616 # ensure that exe is executable 3617 if os.path.exists(exe) and not os.access(exe, os.X_OK): 3618 os.system('chmod +x %s ' % exe) 3619 elif (cwd and os.path.exists(pjoin(cwd, exe))) and not \ 3620 os.access(pjoin(cwd, exe), os.X_OK): 3621 os.system('chmod +x %s ' % pjoin(cwd, exe)) 3622 3623 if mode == 0: 3624 self.update_status((remaining, 1, 3625 self.total_jobs - remaining -1, run_type), level=None, force=False) 3626 start = time.time() 3627 #os.system('cd %s; ./%s' % (cwd,exe)) 3628 status = misc.call([exe] + argument, cwd=cwd, stdout=stdout, **opt) 3629 logger.info('%s run in %f s' % (exe, time.time() -start)) 3630 if status: 3631 raise MadGraph5Error, '%s didn\'t stop properly. Stop all computation' % exe 3632 3633 3634 elif mode in [1,2]: 3635 exename = os.path.basename(exe) 3636 # For condor cluster, create the input/output files 3637 if 'ajob' in exename: 3638 input_files = ['madevent','input_app.txt','symfact.dat','iproc.dat', 3639 pjoin(self.me_dir, 'SubProcesses','randinit')] 3640 if os.path.exists(pjoin(self.me_dir,'SubProcesses', 3641 'MadLoop5_resources.tar.gz')) and cluster.need_transfer(self.options): 3642 input_files.append(pjoin(self.me_dir,'SubProcesses', 'MadLoop5_resources.tar.gz')) 3643 3644 output_files = [] 3645 required_output = [] 3646 3647 3648 #Find the correct PDF input file 3649 input_files.append(self.get_pdf_input_filename()) 3650 3651 #Find the correct ajob 3652 Gre = re.compile("\s*j=(G[\d\.\w]+)") 3653 origre = re.compile("grid_directory=(G[\d\.\w]+)") 3654 try : 3655 fsock = open(exe) 3656 except Exception: 3657 fsock = open(pjoin(cwd,exe)) 3658 text = fsock.read() 3659 output_files = Gre.findall(text) 3660 if not output_files: 3661 Ire = re.compile("for i in ([\d\.\s]*) ; do") 3662 data = Ire.findall(text) 3663 data = ' '.join(data).split() 3664 for nb in data: 3665 output_files.append('G%s' % nb) 3666 required_output.append('G%s/results.dat' % nb) 3667 else: 3668 for G in output_files: 3669 if os.path.isdir(pjoin(cwd,G)): 3670 input_files.append(G) 3671 required_output.append('%s/results.dat' % G) 3672 3673 if origre.search(text): 3674 G_grid = origre.search(text).groups()[0] 3675 input_files.append(pjoin(G_grid, 'ftn26')) 3676 3677 #submitting 3678 self.cluster.submit2(exe, stdout=stdout, cwd=cwd, 3679 input_files=input_files, output_files=output_files, 3680 required_output=required_output) 3681 elif 'survey' in exename: 3682 input_files = ['madevent','input_app.txt','symfact.dat','iproc.dat', 3683 pjoin(self.me_dir, 'SubProcesses','randinit')] 3684 if os.path.exists(pjoin(self.me_dir,'SubProcesses', 3685 'MadLoop5_resources.tar.gz')) and cluster.need_transfer(self.options): 3686 input_files.append(pjoin(self.me_dir,'SubProcesses', 3687 'MadLoop5_resources.tar.gz')) 3688 3689 #Find the correct PDF input file 3690 input_files.append(self.get_pdf_input_filename()) 3691 3692 3693 output_files = [] 3694 required_output = [] 3695 3696 #Find the correct ajob 3697 suffix = "_%s" % int(float(argument[0])) 3698 if suffix == '_0': 3699 suffix = '' 3700 output_files = ['G%s%s' % (i, suffix) for i in argument[1:]] 3701 for G in output_files: 3702 required_output.append('%s/results.dat' % G) 3703 3704 # add the grid information if needed 3705 for G in output_files: 3706 if '.' in argument[0]: 3707 offset = int(str(argument[0]).split('.')[1]) 3708 else: 3709 offset = 0 3710 3711 if offset ==0 or offset == int(float(argument[0])): 3712 if os.path.exists(pjoin(cwd, G, 'input_app.txt')): 3713 os.remove(pjoin(cwd, G, 'input_app.txt')) 3714 3715 if os.path.exists(os.path.realpath(pjoin(cwd, G, 'ftn25'))): 3716 if offset == 0 or offset == int(float(argument[0])): 3717 os.remove(pjoin(cwd, G, 'ftn25')) 3718 continue 3719 else: 3720 input_files.append(pjoin(cwd, G, 'ftn25')) 3721 input_files.remove('input_app.txt') 3722 input_files.append(pjoin(cwd, G, 'input_app.txt')) 3723 elif os.path.lexists(pjoin(cwd, G, 'ftn25')): 3724 try: 3725 os.remove(pjoin(cwd,G,'ftn25')) 3726 except: 3727 pass 3728 3729 #submitting 3730 self.cluster.cluster_submit(exe, stdout=stdout, cwd=cwd, argument=argument, 3731 input_files=input_files, output_files=output_files, 3732 required_output=required_output, **opt) 3733 elif "refine_splitted.sh" in exename: 3734 input_files = ['madevent','symfact.dat','iproc.dat', 3735 pjoin(self.me_dir, 'SubProcesses','randinit')] 3736 3737 if os.path.exists(pjoin(self.me_dir,'SubProcesses', 3738 'MadLoop5_resources.tar.gz')) and cluster.need_transfer(self.options): 3739 input_files.append(pjoin(self.me_dir,'SubProcesses', 3740 'MadLoop5_resources.tar.gz')) 3741 3742 #Find the correct PDF input file 3743 input_files.append(self.get_pdf_input_filename()) 3744 3745 3746 output_files = [argument[0]] 3747 required_output = [] 3748 for G in output_files: 3749 required_output.append('%s/results.dat' % G) 3750 input_files.append(pjoin(argument[1], "input_app.txt")) 3751 input_files.append(pjoin(argument[1], "ftn26")) 3752 3753 #submitting 3754 self.cluster.cluster_submit(exe, stdout=stdout, cwd=cwd, argument=argument, 3755 input_files=input_files, output_files=output_files, 3756 required_output=required_output, **opt) 3757 3758 3759 3760 else: 3761 self.cluster.submit(exe, argument=argument, stdout=stdout, cwd=cwd, **opt)
3762 3763 3764 ############################################################################
3765 - def find_madevent_mode(self):
3766 """Find if Madevent is in Group mode or not""" 3767 3768 # The strategy is too look in the files Source/run_configs.inc 3769 # if we found: ChanPerJob=3 then it's a group mode. 3770 file_path = pjoin(self.me_dir, 'Source', 'run_config.inc') 3771 text = open(file_path).read() 3772 if re.search(r'''s*parameter\s+\(ChanPerJob=2\)''', text, re.I+re.M): 3773 return 'group' 3774 else: 3775 return 'v4'
3776 3777 ############################################################################
3778 - def monitor(self, run_type='monitor', mode=None, html=False):
3779 """ monitor the progress of running job """ 3780 3781 3782 starttime = time.time() 3783 if mode is None: 3784 mode = self.cluster_mode 3785 if mode > 0: 3786 if html: 3787 update_status = lambda idle, run, finish: \ 3788 self.update_status((idle, run, finish, run_type), level=None, 3789 force=False, starttime=starttime) 3790 update_first = lambda idle, run, finish: \ 3791 self.update_status((idle, run, finish, run_type), level=None, 3792 force=True, starttime=starttime) 3793 else: 3794 update_status = lambda idle, run, finish: None 3795 update_first = None 3796 try: 3797 self.cluster.wait(self.me_dir, update_status, update_first=update_first) 3798 except Exception, error: 3799 logger.info(error) 3800 if not self.force: 3801 ans = self.ask('Cluster Error detected. Do you want to clean the queue? ("c"=continue the run anyway)', 3802 default = 'y', choices=['y','n', 'c']) 3803 else: 3804 ans = 'y' 3805 if ans == 'y': 3806 self.cluster.remove() 3807 elif ans == 'c': 3808 return self.monitor(run_type=run_type, mode=mode, html=html) 3809 raise 3810 except KeyboardInterrupt, error: 3811 self.cluster.remove() 3812 raise
3813 3814 3815 3816 ############################################################################
3817 - def configure_directory(self, html_opening=True):
3818 """ All action require before any type of run """ 3819 3820 3821 # Basic check 3822 assert os.path.exists(pjoin(self.me_dir,'SubProcesses')) 3823 3824 # environmental variables to be included in make_opts 3825 self.make_opts_var = {} 3826 3827 #see when the last file was modified 3828 time_mod = max([os.path.getctime(pjoin(self.me_dir,'Cards','run_card.dat')), 3829 os.path.getctime(pjoin(self.me_dir,'Cards','param_card.dat'))]) 3830 if self.configured > time_mod and hasattr(self, 'random'): 3831 return 3832 else: 3833 self.configured = time.time() 3834 self.update_status('compile directory', level=None, update_results=True) 3835 if self.options['automatic_html_opening'] and html_opening: 3836 misc.open_file(os.path.join(self.me_dir, 'crossx.html')) 3837 self.options['automatic_html_opening'] = False 3838 #open only once the web page 3839 # Change current working directory 3840 self.launching_dir = os.getcwd() 3841 3842 # Check if we need the MSSM special treatment 3843 model = self.find_model_name() 3844 if model == 'mssm' or model.startswith('mssm-'): 3845 param_card = pjoin(self.me_dir, 'Cards','param_card.dat') 3846 mg5_param = pjoin(self.me_dir, 'Source', 'MODEL', 'MG5_param.dat') 3847 check_param_card.convert_to_mg5card(param_card, mg5_param) 3848 check_param_card.check_valid_param_card(mg5_param) 3849 3850 # limit the number of event to 100k 3851 self.check_nb_events() 3852 3853 # this is in order to avoid conflicts between runs with and without 3854 # lhapdf 3855 misc.compile(['clean4pdf'], cwd = pjoin(self.me_dir, 'Source')) 3856 3857 # set lhapdf. 3858 if self.run_card['pdlabel'] == "lhapdf": 3859 self.make_opts_var['lhapdf'] = 'True' 3860 self.link_lhapdf(pjoin(self.me_dir,'lib')) 3861 pdfsetsdir = self.get_lhapdf_pdfsetsdir() 3862 lhaid_list = [int(self.run_card['lhaid'])] 3863 self.copy_lhapdf_set(lhaid_list, pdfsetsdir) 3864 if self.run_card['pdlabel'] != "lhapdf": 3865 self.pdffile = None 3866 self.make_opts_var['lhapdf'] = "" 3867 3868 # set random number 3869 if self.run_card['iseed'] != 0: 3870 self.random = int(self.run_card['iseed']) 3871 self.run_card['iseed'] = 0 3872 # Reset seed in run_card to 0, to ensure that following runs 3873 # will be statistically independent 3874 self.run_card.write(pjoin(self.me_dir, 'Cards','run_card.dat')) 3875 elif os.path.exists(pjoin(self.me_dir,'SubProcesses','randinit')): 3876 for line in open(pjoin(self.me_dir,'SubProcesses','randinit')): 3877 data = line.split('=') 3878 assert len(data) ==2 3879 self.random = int(data[1]) 3880 break 3881 else: 3882 self.random = random.randint(1, 30107) 3883 3884 if self.run_card['ickkw'] == 2: 3885 logger.info('Running with CKKW matching') 3886 self.treat_CKKW_matching() 3887 3888 # add the make_opts_var to make_opts 3889 self.update_make_opts() 3890 3891 # create param_card.inc and run_card.inc 3892 self.do_treatcards('') 3893 3894 logger.info("compile Source Directory") 3895 # Compile 3896 for name in [ 'all', '../bin/internal/combine_events']: 3897 self.compile(arg=[name], cwd=os.path.join(self.me_dir, 'Source'))
3898 3899 3900 ############################################################################ 3901 ## HELPING ROUTINE 3902 ############################################################################ 3903 @staticmethod
3904 - def check_dir(path, default=''):
3905 """check if the directory exists. if so return the path otherwise the 3906 default""" 3907 3908 if os.path.isdir(path): 3909 return path 3910 else: 3911 return default
3912 3913 ############################################################################
3914 - def get_Pdir(self):
3915 """get the list of Pdirectory if not yet saved.""" 3916 3917 if hasattr(self, "Pdirs"): 3918 if self.me_dir in self.Pdirs[0]: 3919 return self.Pdirs 3920 self.Pdirs = [pjoin(self.me_dir, 'SubProcesses', l.strip()) 3921 for l in open(pjoin(self.me_dir,'SubProcesses', 'subproc.mg'))] 3922 return self.Pdirs
3923 3924 ############################################################################
3925 - def get_Gdir(self):
3926 """get the list of Gdirectory if not yet saved.""" 3927 3928 if hasattr(self, "Gdirs"): 3929 if self.me_dir in self.Gdirs[0]: 3930 return self.Gdirs 3931 3932 Pdirs = self.get_Pdir() 3933 Gdirs = [] 3934 for P in Pdirs: 3935 for line in open(pjoin(P, "symfact.dat")): 3936 tag, mfactor = line.split() 3937 Gdirs.append( (pjoin(P, "G%s" % tag), int(mfactor)) ) 3938 3939 3940 self.Gdirs = Gdirs 3941 return self.Gdirs
3942 3943 ############################################################################
3944 - def set_run_name(self, name, tag=None, level='parton', reload_card=False, 3945 allow_new_tag=True):
3946 """define the run name, the run_tag, the banner and the results.""" 3947 3948 # when are we force to change the tag new_run:previous run requiring changes 3949 upgrade_tag = {'parton': ['parton','pythia','pgs','delphes'], 3950 'pythia': ['pythia','pgs','delphes'], 3951 'pgs': ['pgs'], 3952 'delphes':['delphes'], 3953 'plot':[], 3954 'syscalc':[]} 3955 3956 3957 3958 if name == self.run_name: 3959 if reload_card: 3960 run_card = pjoin(self.me_dir, 'Cards','run_card.dat') 3961 self.run_card = banner_mod.RunCard(run_card) 3962 3963 #check if we need to change the tag 3964 if tag: 3965 self.run_card['run_tag'] = tag 3966 self.run_tag = tag 3967 self.results.add_run(self.run_name, self.run_card) 3968 else: 3969 for tag in upgrade_tag[level]: 3970 if getattr(self.results[self.run_name][-1], tag): 3971 tag = self.get_available_tag() 3972 self.run_card['run_tag'] = tag 3973 self.run_tag = tag 3974 self.results.add_run(self.run_name, self.run_card) 3975 break 3976 return # Nothing to do anymore 3977 3978 # save/clean previous run 3979 if self.run_name: 3980 self.store_result() 3981 # store new name 3982 self.run_name = name 3983 3984 new_tag = False 3985 # First call for this run -> set the banner 3986 self.banner = banner_mod.recover_banner(self.results, level, name) 3987 if 'mgruncard' in self.banner: 3988 self.run_card = self.banner.charge_card('run_card') 3989 else: 3990 # Read run_card 3991 run_card = pjoin(self.me_dir, 'Cards','run_card.dat') 3992 self.run_card = banner_mod.RunCard(run_card) 3993 3994 if tag: 3995 self.run_card['run_tag'] = tag 3996 new_tag = True 3997 elif not self.run_name in self.results and level =='parton': 3998 pass # No results yet, so current tag is fine 3999 elif not self.run_name in self.results: 4000 #This is only for case when you want to trick the interface 4001 logger.warning('Trying to run data on unknown run.') 4002 self.results.add_run(name, self.run_card) 4003 self.results.update('add run %s' % name, 'all', makehtml=False) 4004 else: 4005 for tag in upgrade_tag[level]: 4006 4007 if getattr(self.results[self.run_name][-1], tag): 4008 # LEVEL is already define in the last tag -> need to switch tag 4009 tag = self.get_available_tag() 4010 self.run_card['run_tag'] = tag 4011 new_tag = True 4012 break 4013 if not new_tag: 4014 # We can add the results to the current run 4015 tag = self.results[self.run_name][-1]['tag'] 4016 self.run_card['run_tag'] = tag # ensure that run_tag is correct 4017 4018 if allow_new_tag and (name in self.results and not new_tag): 4019 self.results.def_current(self.run_name) 4020 else: 4021 self.results.add_run(self.run_name, self.run_card) 4022 4023 self.run_tag = self.run_card['run_tag'] 4024 4025 # Return the tag of the previous run having the required data for this 4026 # tag/run to working wel. 4027 if level == 'parton': 4028 return 4029 elif level == 'pythia': 4030 return self.results[self.run_name][0]['tag'] 4031 else: 4032 for i in range(-1,-len(self.results[self.run_name])-1,-1): 4033 tagRun = self.results[self.run_name][i] 4034 if tagRun.pythia: 4035 return tagRun['tag']
4036 4037 4038 4039 4040 4041 4042 4043 4044 ############################################################################
4045 - def find_model_name(self):
4046 """ return the model name """ 4047 if hasattr(self, 'model_name'): 4048 return self.model_name 4049 4050 model = 'sm' 4051 proc = [] 4052 for line in open(os.path.join(self.me_dir,'Cards','proc_card_mg5.dat')): 4053 line = line.split('#')[0] 4054 #line = line.split('=')[0] 4055 if line.startswith('import') and 'model' in line: 4056 model = line.split()[2] 4057 proc = [] 4058 elif line.startswith('generate'): 4059 proc.append(line.split(None,1)[1]) 4060 elif line.startswith('add process'): 4061 proc.append(line.split(None,2)[2]) 4062 4063 self.model = model 4064 self.process = proc 4065 return model
4066 4067 4068 ############################################################################
4069 - def check_nb_events(self):
4070 """Find the number of event in the run_card, and check that this is not 4071 too large""" 4072 4073 4074 nb_event = int(self.run_card['nevents']) 4075 if nb_event > 1000000: 4076 logger.warning("Attempting to generate more than 1M events") 4077 logger.warning("Limiting number to 1M. Use multi_run for larger statistics.") 4078 path = pjoin(self.me_dir, 'Cards', 'run_card.dat') 4079 os.system(r"""perl -p -i.bak -e "s/\d+\s*=\s*nevents/1000000 = nevents/" %s""" \ 4080 % path) 4081 self.run_card['nevents'] = 1000000 4082 4083 return
4084 4085 4086 ############################################################################
4087 - def update_random(self):
4088 """ change random number""" 4089 4090 self.random += 3 4091 if self.random > 30081*30081: # can't use too big random number 4092 raise MadGraph5Error,\ 4093 'Random seed too large ' + str(self.random) + ' > 30081*30081'
4094 4095 ############################################################################
4096 - def save_random(self):
4097 """save random number in appropirate file""" 4098 4099 fsock = open(pjoin(self.me_dir, 'SubProcesses','randinit'),'w') 4100 fsock.writelines('r=%s\n' % self.random)
4101
4102 - def do_quit(self, *args, **opts):
4103 4104 common_run.CommonRunCmd.do_quit(self, *args, **opts) 4105 return CmdExtended.do_quit(self, *args, **opts)
4106 4107 ############################################################################
4108 - def treat_CKKW_matching(self):
4109 """check for ckkw""" 4110 4111 lpp1 = self.run_card['lpp1'] 4112 lpp2 = self.run_card['lpp2'] 4113 e1 = self.run_card['ebeam1'] 4114 e2 = self.run_card['ebeam2'] 4115 pd = self.run_card['pdlabel'] 4116 lha = self.run_card['lhaid'] 4117 xq = self.run_card['xqcut'] 4118 translation = {'e1': e1, 'e2':e2, 'pd':pd, 4119 'lha':lha, 'xq':xq} 4120 4121 if lpp1 or lpp2: 4122 # Remove ':s from pd 4123 if pd.startswith("'"): 4124 pd = pd[1:] 4125 if pd.endswith("'"): 4126 pd = pd[:-1] 4127 4128 if xq >2 or xq ==2: 4129 xq = 2 4130 4131 # find data file 4132 if pd == "lhapdf": 4133 issudfile = 'lib/issudgrid-%(e1)s-%(e2)s-%(pd)s-%(lha)s-%(xq)s.dat.gz' 4134 else: 4135 issudfile = 'lib/issudgrid-%(e1)s-%(e2)s-%(pd)s-%(xq)s.dat.gz' 4136 if self.web: 4137 issudfile = pjoin(self.webbin, issudfile % translation) 4138 else: 4139 issudfile = pjoin(self.me_dir, issudfile % translation) 4140 4141 logger.info('Sudakov grid file: %s' % issudfile) 4142 4143 # check that filepath exists 4144 if os.path.exists(issudfile): 4145 path = pjoin(self.me_dir, 'lib', 'issudgrid.dat') 4146 misc.gunzip(issudfile, keep=True, stdout=path) 4147 else: 4148 msg = 'No sudakov grid file for parameter choice. Start to generate it. This might take a while' 4149 logger.info(msg) 4150 self.update_status('GENERATE SUDAKOF GRID', level='parton') 4151 4152 for i in range(-2,6): 4153 self.cluster.submit('%s/gensudgrid ' % self.dirbin, 4154 arguments = [i], 4155 cwd=self.me_dir, 4156 stdout=open(pjoin(self.me_dir, 'gensudgrid%s.log' % i,'w'))) 4157 self.monitor() 4158 for i in range(-2,6): 4159 path = pjoin(self.me_dir, 'lib', 'issudgrid.dat') 4160 os.system('cat %s/gensudgrid%s.log >> %s' % (self.me_dir, path)) 4161 misc.gzip(path, stdout=issudfile)
4162 4163 ############################################################################
4164 - def create_root_file(self, input='unweighted_events.lhe', 4165 output='unweighted_events.root' ):
4166 """create the LHE root file """ 4167 self.update_status('Creating root files', level='parton') 4168 4169 eradir = self.options['exrootanalysis_path'] 4170 try: 4171 misc.call(['%s/ExRootLHEFConverter' % eradir, 4172 input, output], 4173 cwd=pjoin(self.me_dir, 'Events')) 4174 except Exception: 4175 logger.warning('fail to produce Root output [problem with ExRootAnalysis]')
4176
4177 - def run_syscalc(self, mode='parton', event_path=None, output=None):
4178 """create the syscalc output""" 4179 4180 if self.run_card['use_syst'] not in self.true: 4181 return 4182 4183 scdir = self.options['syscalc_path'] 4184 if not scdir or not os.path.exists(scdir): 4185 return 4186 logger.info('running syscalc on mode %s' % mode) 4187 4188 4189 # Check that all pdfset are correctly installed 4190 lhaid = [self.run_card.get_lhapdf_id()] 4191 sys_pdf = self.run_card['sys_pdf'].split('&&') 4192 lhaid += [l.split()[0] for l in sys_pdf] 4193 try: 4194 pdfsets_dir = self.get_lhapdf_pdfsetsdir() 4195 except Exception, error: 4196 logger.debug(str(error)) 4197 logger.warning('Systematic computation requires lhapdf to run. Bypass SysCalc') 4198 return 4199 4200 # Copy all the relevant PDF sets 4201 [self.copy_lhapdf_set([onelha], pdfsets_dir) for onelha in lhaid] 4202 4203 4204 4205 tag = self.run_card['run_tag'] 4206 card = pjoin(self.me_dir, 'bin','internal', 'syscalc_card.dat') 4207 template = open(pjoin(self.me_dir, 'bin','internal', 'syscalc_template.dat')).read() 4208 self.run_card['sys_pdf'] = self.run_card['sys_pdf'].split('#',1)[0].replace('&&',' \n ') 4209 4210 if self.run_card['sys_pdf'].lower() in ['', 'f', 'false', 'none', '.false.']: 4211 self.run_card['sys_pdf'] = '' 4212 if self.run_card['sys_alpsfact'].lower() in ['', 'f', 'false', 'none','.false.']: 4213 self.run_card['sys_alpsfact'] = '' 4214 4215 4216 4217 4218 # check if the scalecorrelation parameter is define: 4219 if not 'sys_scalecorrelation' in self.run_card: 4220 self.run_card['sys_scalecorrelation'] = -1 4221 open(card,'w').write(template % self.run_card) 4222 4223 if not os.path.exists(card): 4224 return False 4225 4226 4227 4228 event_dir = pjoin(self.me_dir, 'Events') 4229 4230 if not event_path: 4231 if mode == 'parton': 4232 event_path = pjoin(event_dir,self.run_name, 'unweighted_events.lhe') 4233 if not (os.path.exists(event_path) or os.path.exists(event_path+".gz")): 4234 event_path = pjoin(event_dir, 'unweighted_events.lhe') 4235 output = pjoin(event_dir, 'syscalc.lhe') 4236 elif mode == 'Pythia': 4237 if 'mgpythiacard' in self.banner: 4238 pat = re.compile('''^\s*qcut\s*=\s*([\+\-\d.e]*)''', re.M+re.I) 4239 data = pat.search(self.banner['mgpythiacard']) 4240 if data: 4241 qcut = float(data.group(1)) 4242 xqcut = abs(self.run_card['xqcut']) 4243 for value in self.run_card['sys_matchscale'].split(): 4244 if float(value) < qcut: 4245 raise SysCalcError, 'qcut value for sys_matchscale lower than qcut in pythia_card. Bypass syscalc' 4246 if float(value) < xqcut: 4247 raise SysCalcError, 'qcut value for sys_matchscale lower than xqcut in run_card. Bypass syscalc' 4248 4249 4250 event_path = pjoin(event_dir,'syst.dat') 4251 output = pjoin(event_dir, 'syscalc.dat') 4252 else: 4253 raise self.InvalidCmd, 'Invalid mode %s' % mode 4254 4255 if not os.path.exists(event_path): 4256 if os.path.exists(event_path+'.gz'): 4257 misc.gunzip(event_path+'.gz') 4258 else: 4259 raise SysCalcError, 'Events file %s does not exits' % event_path 4260 4261 self.update_status('Calculating systematics for %s level' % mode, level = mode.lower()) 4262 try: 4263 proc = misc.call([os.path.join(scdir, 'sys_calc'), 4264 event_path, card, output], 4265 stdout = open(pjoin(event_dir, self.run_name, '%s_%s_syscalc.log' % (tag,mode)),'w'), 4266 stderr = subprocess.STDOUT, 4267 cwd=event_dir) 4268 # Wait 5 s to make sure file is finished writing 4269 time.sleep(5) 4270 except OSError, error: 4271 logger.error('fail to run syscalc: %s. Please check that SysCalc is correctly installed.' % error) 4272 else: 4273 if not os.path.exists(output): 4274 logger.warning('SysCalc Failed. Please read the associate log to see the reason. Did you install the associate PDF set?') 4275 elif mode == 'parton': 4276 files.mv(output, event_path) 4277 4278 self.update_status('End syscalc for %s level' % mode, level = mode.lower(), 4279 makehtml=False) 4280 4281 return True
4282 4283 4284 4285 ############################################################################
4286 - def ask_run_configuration(self, mode=None, args=[]):
4287 """Ask the question when launching generate_events/multi_run""" 4288 4289 available_mode = ['0'] 4290 void = 'NOT INSTALLED' 4291 switch_order = ['pythia', 'pgs', 'delphes', 'madspin', 'reweight'] 4292 switch = {'pythia': void, 'pgs': void, 'delphes': void, 4293 'madspin': void, 'reweight': void} 4294 description = {'pythia': 'Run the pythia shower/hadronization:', 4295 'pgs': 'Run PGS as detector simulator:', 4296 'delphes':'Run Delphes as detector simulator:', 4297 'madspin':'Decay particles with the MadSpin module:', 4298 'reweight':'Add weights to the events based on changing model parameters:', 4299 } 4300 force_switch = {('pythia', 'OFF'): {'pgs': 'OFF', 'delphes': 'OFF'}, 4301 ('pgs', 'ON'): {'pythia':'ON'}, 4302 ('delphes', 'ON'): {'pythia': 'ON'}} 4303 switch_assign = lambda key, value: switch.__setitem__(key, value if switch[key] != void else void ) 4304 4305 4306 # Init the switch value according to the current status 4307 if self.options['pythia-pgs_path']: 4308 available_mode.append('1') 4309 available_mode.append('2') 4310 if os.path.exists(pjoin(self.me_dir,'Cards','pythia_card.dat')): 4311 switch['pythia'] = 'ON' 4312 else: 4313 switch['pythia'] = 'OFF' 4314 if os.path.exists(pjoin(self.me_dir,'Cards','pgs_card.dat')): 4315 switch['pgs'] = 'ON' 4316 else: 4317 switch['pgs'] = 'OFF' 4318 if self.options['delphes_path']: 4319 available_mode.append('3') 4320 if os.path.exists(pjoin(self.me_dir,'Cards','delphes_card.dat')): 4321 switch['delphes'] = 'ON' 4322 else: 4323 switch['delphes'] = 'OFF' 4324 4325 # Check switch status for MS/reweight 4326 if not MADEVENT or ('mg5_path' in self.options and self.options['mg5_path']): 4327 available_mode.append('4') 4328 available_mode.append('5') 4329 if os.path.exists(pjoin(self.me_dir,'Cards','madspin_card.dat')): 4330 switch['madspin'] = 'ON' 4331 else: 4332 switch['madspin'] = 'OFF' 4333 if misc.has_f2py() or self.options['f2py_compiler']: 4334 if os.path.exists(pjoin(self.me_dir,'Cards','reweight_card.dat')): 4335 switch['reweight'] = 'ON' 4336 else: 4337 switch['reweight'] = 'OFF' 4338 else: 4339 switch['reweight'] = 'Not available (requires NumPy)' 4340 4341 if '-R' in args or '--reweight' in args: 4342 if switch['reweight'] == 'OFF': 4343 switch['reweight'] = 'ON' 4344 elif switch['reweight'] != 'ON': 4345 logger.critical("Cannot run reweight: %s", switch['reweight']) 4346 if '-M' in args or '--madspin' in args: 4347 switch['madspin'] = 'ON' 4348 4349 options = list(available_mode) + ['auto', 'done'] 4350 for id, key in enumerate(switch_order): 4351 if switch[key] not in [void, 'Not available (requires NumPy)']: 4352 options += ['%s=%s' % (key, s) for s in ['ON','OFF']] 4353 options.append(key) 4354 options.append('parton') 4355 4356 #ask the question 4357 if mode or not self.force: 4358 answer = '' 4359 while answer not in ['0', 'done', 'auto']: 4360 if mode: 4361 answer = mode 4362 else: 4363 switch_format = " %i %-61s %10s=%s\n" 4364 question = "The following switches determine which programs are run:\n" 4365 for id, key in enumerate(switch_order): 4366 question += switch_format % (id+1, description[key], key, switch[key]) 4367 question += ' Either type the switch number (1 to %s) to change its default setting,\n' % (id+1) 4368 question += ' or set any switch explicitly (e.g. type \'madspin=ON\' at the prompt)\n' 4369 question += ' Type \'0\', \'auto\', \'done\' or just press enter when you are done.\n' 4370 answer = self.ask(question, '0', options) 4371 if answer.isdigit() and answer != '0': 4372 key = switch_order[int(answer) - 1] 4373 answer = '%s=%s' % (key, 'ON' if switch[key] == 'OFF' else 'OFF') 4374 4375 if '=' in answer: 4376 key, status = answer.split('=') 4377 switch[key] = status 4378 if (key, status) in force_switch: 4379 for key2, status2 in force_switch[(key, status)].items(): 4380 if switch[key2] not in [status2, void]: 4381 logger.info('For coherence \'%s\' is set to \'%s\'' 4382 % (key2, status2), '$MG:color:BLACK') 4383 switch[key2] = status2 4384 elif answer in ['0', 'auto', 'done']: 4385 continue 4386 else: 4387 logger.info('pass in %s only mode' % answer, '$MG:color:BLACK') 4388 switch_assign('madspin', 'OFF') 4389 switch_assign('reweight', 'OFF') 4390 if answer == 'parton': 4391 switch_assign('pythia', 'OFF') 4392 switch_assign('pgs', 'OFF') 4393 switch_assign('delphes', 'OFF') 4394 elif answer == 'pythia': 4395 switch_assign('pythia', 'ON') 4396 switch_assign('pgs', 'OFF') 4397 switch_assign('delphes', 'OFF') 4398 elif answer == 'pgs': 4399 switch_assign('pythia', 'ON') 4400 switch_assign('pgs', 'ON') 4401 switch_assign('delphes', 'OFF') 4402 elif answer == 'delphes': 4403 switch_assign('pythia', 'ON') 4404 switch_assign('pgs', 'OFF') 4405 switch_assign('delphes', 'ON') 4406 elif answer == 'madspin': 4407 switch_assign('madspin', 'ON') 4408 switch_assign('pythia', 'OFF') 4409 switch_assign('pgs', 'OFF') 4410 switch_assign('delphes', 'OF') 4411 elif answer == 'reweight': 4412 switch_assign('reweight', 'ON') 4413 switch_assign('pythia', 'OFF') 4414 switch_assign('pgs', 'OFF') 4415 switch_assign('delphes', 'OFF') 4416 4417 4418 if mode: 4419 answer = '0' #mode auto didn't pass here (due to the continue) 4420 else: 4421 answer = 'auto' 4422 4423 # Now that we know in which mode we are check that all the card 4424 #exists (copy default if needed) 4425 4426 cards = ['param_card.dat', 'run_card.dat'] 4427 if switch['pythia'] == 'ON': 4428 cards.append('pythia_card.dat') 4429 if switch['pgs'] == 'ON': 4430 cards.append('pgs_card.dat') 4431 if switch['delphes'] == 'ON': 4432 cards.append('delphes_card.dat') 4433 delphes3 = True 4434 if os.path.exists(pjoin(self.options['delphes_path'], 'data')): 4435 delphes3 = False 4436 cards.append('delphes_trigger.dat') 4437 if switch['madspin'] == 'ON': 4438 cards.append('madspin_card.dat') 4439 if switch['reweight'] == 'ON': 4440 cards.append('reweight_card.dat') 4441 self.keep_cards(cards) 4442 4443 if os.path.isfile(pjoin(self.me_dir,'Cards','MadLoopParams.dat')): 4444 cards.append('MadLoopParams.dat') 4445 4446 if self.force: 4447 self.check_param_card(pjoin(self.me_dir,'Cards','param_card.dat' )) 4448 return 4449 4450 if answer == 'auto': 4451 self.ask_edit_cards(cards, mode='auto') 4452 else: 4453 self.ask_edit_cards(cards) 4454 return
4455 4456 ############################################################################
4457 - def ask_pythia_run_configuration(self, mode=None):
4458 """Ask the question when launching pythia""" 4459 4460 available_mode = ['0', '1', '2'] 4461 if self.options['delphes_path']: 4462 available_mode.append('3') 4463 name = {'0': 'auto', '1': 'pythia', '2':'pgs', '3':'delphes'} 4464 options = available_mode + [name[val] for val in available_mode] 4465 question = """Which programs do you want to run? 4466 0 / auto : running existing card 4467 1 / pythia : Pythia 4468 2 / pgs : Pythia + PGS\n""" 4469 if '3' in available_mode: 4470 question += """ 3 / delphes : Pythia + Delphes.\n""" 4471 4472 if not self.force: 4473 if not mode: 4474 mode = self.ask(question, '0', options) 4475 elif not mode: 4476 mode = 'auto' 4477 4478 if mode.isdigit(): 4479 mode = name[mode] 4480 4481 auto = False 4482 if mode == 'auto': 4483 auto = True 4484 if os.path.exists(pjoin(self.me_dir, 'Cards', 'pgs_card.dat')): 4485 mode = 'pgs' 4486 elif os.path.exists(pjoin(self.me_dir, 'Cards', 'delphes_card.dat')): 4487 mode = 'delphes' 4488 else: 4489 mode = 'pythia' 4490 logger.info('Will run in mode %s' % mode) 4491 4492 # Now that we know in which mode we are check that all the card 4493 #exists (copy default if needed) remove pointless one 4494 cards = ['pythia_card.dat'] 4495 if mode == 'pgs': 4496 cards.append('pgs_card.dat') 4497 if mode == 'delphes': 4498 cards.append('delphes_card.dat') 4499 delphes3 = True 4500 if os.path.exists(pjoin(self.options['delphes_path'], 'data')): 4501 delphes3 = False 4502 cards.append('delphes_trigger.dat') 4503 self.keep_cards(cards) 4504 4505 if self.force: 4506 return mode 4507 4508 if auto: 4509 self.ask_edit_cards(cards, mode='auto') 4510 else: 4511 self.ask_edit_cards(cards) 4512 4513 return mode
4514
4515 4516 4517 4518 4519 #=============================================================================== 4520 # MadEventCmd 4521 #=============================================================================== 4522 -class MadEventCmdShell(MadEventCmd, cmd.CmdShell):
4523 """The command line processor of MadGraph"""
4524
4525 4526 4527 #=============================================================================== 4528 # HELPING FUNCTION For Subprocesses 4529 #=============================================================================== 4530 -class SubProcesses(object):
4531 4532 name_to_pdg = {} 4533 4534 @classmethod
4535 - def clean(cls):
4536 cls.name_to_pdg = {}
4537 4538 @staticmethod
4539 - def get_subP(me_dir):
4540 """return the list of Subprocesses""" 4541 4542 out = [] 4543 for line in open(pjoin(me_dir,'SubProcesses', 'subproc.mg')): 4544 if not line: 4545 continue 4546 name = line.strip() 4547 if os.path.exists(pjoin(me_dir, 'SubProcesses', name)): 4548 out.append(pjoin(me_dir, 'SubProcesses', name)) 4549 4550 return out
4551 4552 4553 4554 @staticmethod
4555 - def get_subP_info(path):
4556 """ return the list of processes with their name""" 4557 4558 nb_sub = 0 4559 names = {} 4560 old_main = '' 4561 4562 if not os.path.exists(os.path.join(path,'processes.dat')): 4563 return SubProcesses.get_subP_info_v4(path) 4564 4565 for line in open(os.path.join(path,'processes.dat')): 4566 main = line[:8].strip() 4567 if main == 'mirror': 4568 main = old_main 4569 if line[8:].strip() == 'none': 4570 continue 4571 else: 4572 main = int(main) 4573 old_main = main 4574 4575 sub_proccess = line[8:] 4576 nb_sub += sub_proccess.count(',') + 1 4577 if main in names: 4578 names[main] += [sub_proccess.split(',')] 4579 else: 4580 names[main]= [sub_proccess.split(',')] 4581 4582 return names
4583 4584 @staticmethod
4585 - def get_subP_info_v4(path):
4586 """ return the list of processes with their name in case without grouping """ 4587 4588 nb_sub = 0 4589 names = {'':[[]]} 4590 path = os.path.join(path, 'auto_dsig.f') 4591 found = 0 4592 for line in open(path): 4593 if line.startswith('C Process:'): 4594 found += 1 4595 names[''][0].append(line[15:]) 4596 elif found >1: 4597 break 4598 return names
4599 4600 4601 @staticmethod
4602 - def get_subP_ids(path):
4603 """return the pdg codes of the particles present in the Subprocesses""" 4604 4605 all_ids = [] 4606 for line in open(pjoin(path, 'leshouche.inc')): 4607 if not 'IDUP' in line: 4608 continue 4609 particles = re.search("/([\d,-]+)/", line) 4610 all_ids.append([int(p) for p in particles.group(1).split(',')]) 4611 return all_ids
4612
4613 4614 #=============================================================================== 4615 -class GridPackCmd(MadEventCmd):
4616 """The command for the gridpack --Those are not suppose to be use interactively--""" 4617
4618 - def __init__(self, me_dir = None, nb_event=0, seed=0, *completekey, **stdin):
4619 """Initialize the command and directly run""" 4620 4621 # Initialize properly 4622 4623 MadEventCmd.__init__(self, me_dir, *completekey, **stdin) 4624 self.run_mode = 0 4625 self.random = seed 4626 self.random_orig = self.random 4627 self.options['automatic_html_opening'] = False 4628 # Now it's time to run! 4629 if me_dir and nb_event and seed: 4630 self.launch(nb_event, seed) 4631 else: 4632 raise MadGraph5Error,\ 4633 'Gridpack run failed: ' + str(me_dir) + str(nb_event) + \ 4634 str(seed)
4635
4636 - def launch(self, nb_event, seed):
4637 """ launch the generation for the grid """ 4638 4639 # 1) Restore the default data 4640 logger.info('generate %s events' % nb_event) 4641 self.set_run_name('GridRun_%s' % seed) 4642 self.update_status('restoring default data', level=None) 4643 misc.call([pjoin(self.me_dir,'bin','internal','restore_data'), 4644 'default'], 4645 cwd=self.me_dir) 4646 4647 # 2) Run the refine for the grid 4648 self.update_status('Generating Events', level=None) 4649 #misc.call([pjoin(self.me_dir,'bin','refine4grid'), 4650 # str(nb_event), '0', 'Madevent','1','GridRun_%s' % seed], 4651 # cwd=self.me_dir) 4652 self.refine4grid(nb_event) 4653 4654 # 3) Combine the events/pythia/... 4655 self.exec_cmd('combine_events') 4656 self.exec_cmd('store_events') 4657 self.print_results_in_shell(self.results.current) 4658 self.exec_cmd('decay_events -from_cards', postcmd=False)
4659
4660 - def refine4grid(self, nb_event):
4661 """Special refine for gridpack run.""" 4662 self.nb_refine += 1 4663 4664 precision = nb_event 4665 4666 # initialize / remove lhapdf mode 4667 # self.configure_directory() # All this has been done before 4668 self.cluster_mode = 0 # force single machine 4669 4670 # Store seed in randinit file, to be read by ranmar.f 4671 self.save_random() 4672 4673 self.update_status('Refine results to %s' % precision, level=None) 4674 logger.info("Using random number seed offset = %s" % self.random) 4675 4676 self.total_jobs = 0 4677 subproc = [P for P in os.listdir(pjoin(self.me_dir,'SubProcesses')) if 4678 P.startswith('P') and os.path.isdir(pjoin(self.me_dir,'SubProcesses', P))] 4679 devnull = open(os.devnull, 'w') 4680 for nb_proc,subdir in enumerate(subproc): 4681 subdir = subdir.strip() 4682 Pdir = pjoin(self.me_dir, 'SubProcesses',subdir) 4683 bindir = pjoin(os.path.relpath(self.dirbin, Pdir)) 4684 4685 logger.info(' %s ' % subdir) 4686 # clean previous run 4687 for match in misc.glob('*ajob*', Pdir): 4688 if os.path.basename(match)[:4] in ['ajob', 'wait', 'run.', 'done']: 4689 os.remove(pjoin(Pdir, match)) 4690 4691 4692 logfile = pjoin(Pdir, 'gen_ximprove.log') 4693 misc.call([pjoin(bindir, 'gen_ximprove')], 4694 stdin=subprocess.PIPE, 4695 stdout=open(logfile,'w'), 4696 cwd=Pdir) 4697 4698 if os.path.exists(pjoin(Pdir, 'ajob1')): 4699 alljobs = misc.glob('ajob*', Pdir) 4700 nb_tot = len(alljobs) 4701 self.total_jobs += nb_tot 4702 for i, job in enumerate(alljobs): 4703 job = os.path.basename(job) 4704 self.launch_job('%s' % job, cwd=Pdir, remaining=(nb_tot-i-1), 4705 run_type='Refine number %s on %s (%s/%s)' % 4706 (self.nb_refine, subdir, nb_proc+1, len(subproc))) 4707 if os.path.exists(pjoin(self.me_dir,'error')): 4708 self.monitor(html=True) 4709 raise MadEventError, \ 4710 'Error detected in dir %s: %s' % \ 4711 (Pdir, open(pjoin(self.me_dir,'error')).read()) 4712 self.monitor(run_type='All job submitted for refine number %s' % 4713 self.nb_refine) 4714 4715 self.update_status("Combining runs", level='parton') 4716 try: 4717 os.remove(pjoin(Pdir, 'combine_runs.log')) 4718 except Exception: 4719 pass 4720 4721 bindir = pjoin(os.path.relpath(self.dirbin, pjoin(self.me_dir,'SubProcesses'))) 4722 combine_runs.CombineRuns(self.me_dir) 4723 4724 #update html output 4725 cross, error = sum_html.make_all_html_results(self) 4726 self.results.add_detail('cross', cross) 4727 self.results.add_detail('error', error) 4728 4729 4730 self.update_status('finish refine', 'parton', makehtml=False) 4731 devnull.close()
4732
4733 4734 -class MadLoopInitializer(object):
4735 """ A container class for the various methods for initializing MadLoop. It is 4736 placed in MadEventInterface because it is used by Madevent for loop-induced 4737 simulations. """ 4738 4739 @staticmethod
4740 - def make_and_run(dir_name,checkRam=False):
4741 """ Compile the check program in the directory dir_name. 4742 Return the compilation and running time. """ 4743 4744 # Make sure to recreate the executable and modified source 4745 # (The time stamps are sometimes not actualized if it is too fast) 4746 if os.path.isfile(pjoin(dir_name,'check')): 4747 os.remove(pjoin(dir_name,'check')) 4748 os.remove(pjoin(dir_name,'check_sa.o')) 4749 os.remove(pjoin(dir_name,'loop_matrix.o')) 4750 # Now run make 4751 devnull = open(os.devnull, 'w') 4752 start=time.time() 4753 retcode = subprocess.call(['make','check'], 4754 cwd=dir_name, stdout=devnull, stderr=devnull) 4755 compilation_time = time.time()-start 4756 if retcode != 0: 4757 logging.info("Error while executing make in %s" % dir_name) 4758 return None, None, None 4759 4760 if not checkRam: 4761 start=time.time() 4762 retcode = subprocess.call('./check', 4763 cwd=dir_name, stdout=devnull, stderr=devnull) 4764 4765 run_time = time.time()-start 4766 ram_usage = None 4767 else: 4768 ptimer = misc.ProcessTimer(['./check'], cwd=dir_name, shell=False, \ 4769 stdout=devnull, stderr=devnull, close_fds=True) 4770 try: 4771 ptimer.execute() 4772 #poll as often as possible; otherwise the subprocess might 4773 # "sneak" in some extra memory usage while you aren't looking 4774 # Accuracy of .2 seconds is enough for the timing. 4775 while ptimer.poll(): 4776 time.sleep(.2) 4777 finally: 4778 #make sure that we don't leave the process dangling. 4779 ptimer.close() 4780 # Notice that ptimer.max_vms_memory is also available if needed. 4781 ram_usage = ptimer.max_rss_memory 4782 # Unfortunately the running time is less precise than with the 4783 # above version 4784 run_time = (ptimer.t1 - ptimer.t0) 4785 retcode = ptimer.p.returncode 4786 4787 devnull.close() 4788 4789 if retcode != 0: 4790 logging.warning("Error while executing ./check in %s" % dir_name) 4791 return None, None, None 4792 4793 return compilation_time, run_time, ram_usage
4794 4795 @staticmethod
4796 - def fix_PSPoint_in_check(dir_path, read_ps = True, npoints = 1, 4797 hel_config = -1, mu_r=0.0, split_orders=-1):
4798 """Set check_sa.f to be reading PS.input assuming a working dir dir_name. 4799 if hel_config is different than -1 then check_sa.f is configured so to 4800 evaluate only the specified helicity. 4801 If mu_r > 0.0, then the renormalization constant value will be hardcoded 4802 directly in check_sa.f, if is is 0 it will be set to Sqrt(s) and if it 4803 is < 0.0 the value in the param_card.dat is used. 4804 If the split_orders target (i.e. the target squared coupling orders for 4805 the computation) is != -1, it will be changed in check_sa.f via the 4806 subroutine CALL SET_COUPLINGORDERS_TARGET(split_orders).""" 4807 4808 file_path = dir_path 4809 if not os.path.isfile(dir_path) or \ 4810 not os.path.basename(dir_path)=='check_sa.f': 4811 file_path = pjoin(dir_path,'check_sa.f') 4812 if not os.path.isfile(file_path): 4813 directories = [d for d in misc.glob('P*_*', dir_path) \ 4814 if (re.search(r'.*P\d+_\w*$', d) and os.path.isdir(d))] 4815 if len(directories)>0: 4816 file_path = pjoin(directories[0],'check_sa.f') 4817 if not os.path.isfile(file_path): 4818 raise MadGraph5Error('Could not find the location of check_sa.f'+\ 4819 ' from the specified path %s.'%str(file_path)) 4820 4821 file = open(file_path, 'r') 4822 check_sa = file.read() 4823 file.close() 4824 4825 file = open(file_path, 'w') 4826 check_sa = re.sub(r"READPS = \S+\)","READPS = %s)"%('.TRUE.' if read_ps \ 4827 else '.FALSE.'), check_sa) 4828 check_sa = re.sub(r"NPSPOINTS = \d+","NPSPOINTS = %d"%npoints, check_sa) 4829 if hel_config != -1: 4830 check_sa = re.sub(r"SLOOPMATRIX\S+\(\S+,MATELEM,", 4831 "SLOOPMATRIXHEL_THRES(P,%d,MATELEM,"%hel_config, check_sa) 4832 else: 4833 check_sa = re.sub(r"SLOOPMATRIX\S+\(\S+,MATELEM,", 4834 "SLOOPMATRIX_THRES(P,MATELEM,",check_sa) 4835 if mu_r > 0.0: 4836 check_sa = re.sub(r"MU_R=SQRTS","MU_R=%s"%\ 4837 (("%.17e"%mu_r).replace('e','d')),check_sa) 4838 elif mu_r < 0.0: 4839 check_sa = re.sub(r"MU_R=SQRTS","",check_sa) 4840 4841 if split_orders > 0: 4842 check_sa = re.sub(r"SET_COUPLINGORDERS_TARGET\(-?\d+\)", 4843 "SET_COUPLINGORDERS_TARGET(%d)"%split_orders,check_sa) 4844 4845 file.write(check_sa) 4846 file.close()
4847 4848 @staticmethod
4849 - def run_initialization(run_dir=None, SubProc_dir=None, infos=None,\ 4850 req_files = ['HelFilter.dat','LoopFilter.dat'], 4851 attempts = [4,15]):
4852 """ Run the initialization of the process in 'run_dir' with success 4853 characterized by the creation of the files req_files in this directory. 4854 The directory containing the driving source code 'check_sa.f'. 4855 The list attempt gives the successive number of PS points the 4856 initialization should be tried with before calling it failed. 4857 Returns the number of PS points which were necessary for the init. 4858 Notice at least run_dir or SubProc_dir must be provided. 4859 A negative attempt number given in input means that quadprec will be 4860 forced for initialization.""" 4861 4862 # If the user does not want detailed info, then set the dictionary 4863 # to a dummy one. 4864 if infos is None: 4865 infos={} 4866 4867 if SubProc_dir is None and run_dir is None: 4868 raise MadGraph5Error, 'At least one of [SubProc_dir,run_dir] must'+\ 4869 ' be provided in run_initialization.' 4870 4871 # If the user does not specify where is check_sa.f, then it is assumed 4872 # to be one levels above run_dir 4873 if SubProc_dir is None: 4874 SubProc_dir = os.path.abspath(pjoin(run_dir,os.pardir)) 4875 4876 if run_dir is None: 4877 directories =[ dir for dir in misc.glob('P[0-9]*', SubProc_dir) 4878 if os.path.isdir(dir) ] 4879 if directories: 4880 run_dir = directories[0] 4881 else: 4882 raise MadGraph5Error, 'Could not find a valid running directory'+\ 4883 ' in %s.'%str(SubProc_dir) 4884 4885 # Use the presence of the file born_matrix.f to decide if it is a 4886 # loop-induced process or not. It's not crucial, but just that because 4887 # of the dynamic adjustment of the ref scale used for deciding what are 4888 # the zero contributions, more points are neeeded for loop-induced. 4889 if not os.path.isfile(pjoin(run_dir,'born_matrix.f')): 4890 if len(attempts)>=1 and attempts[0]<8: 4891 attempts[0]=8 4892 if len(attempts)>=2 and attempts[1]<25: 4893 attempts[1]=25 4894 4895 to_attempt = list(attempts) 4896 to_attempt.reverse() 4897 my_req_files = list(req_files) 4898 4899 MLCardPath = pjoin(SubProc_dir,'MadLoopParams.dat') 4900 if not os.path.isfile(MLCardPath): 4901 raise MadGraph5Error, 'Could not find MadLoopParams.dat at %s.'\ 4902 %MLCardPath 4903 else: 4904 MLCard = banner_mod.MadLoopParam(MLCardPath) 4905 MLCard_orig = banner_mod.MadLoopParam(MLCard) 4906 4907 # Make sure that LoopFilter really is needed. 4908 if not MLCard['UseLoopFilter']: 4909 try: 4910 my_req_files.remove('LoopFilter.dat') 4911 except ValueError: 4912 pass 4913 4914 if MLCard['HelicityFilterLevel']==0: 4915 try: 4916 my_req_files.remove('HelFilter.dat') 4917 except ValueError: 4918 pass 4919 4920 def need_init(): 4921 """ True if init not done yet.""" 4922 proc_prefix_file = open(pjoin(run_dir,'proc_prefix.txt'),'r') 4923 proc_prefix = proc_prefix_file.read() 4924 proc_prefix_file.close() 4925 return any([not os.path.exists(pjoin(run_dir,'MadLoop5_resources', 4926 proc_prefix+fname)) for fname in my_req_files]) or \ 4927 not os.path.isfile(pjoin(run_dir,'check')) or \ 4928 not os.access(pjoin(run_dir,'check'), os.X_OK)
4929 4930 # Check if this is a process without born by checking the presence of the 4931 # file born_matrix.f 4932 is_loop_induced = os.path.exists(pjoin(run_dir,'born_matrix.f')) 4933 4934 # For loop induced processes, always attempt quadruple precision if 4935 # double precision attempts fail and the user didn't specify himself 4936 # quadruple precision initializations attempts 4937 if not any(attempt<0 for attempt in to_attempt): 4938 to_attempt = [-attempt for attempt in to_attempt] + to_attempt 4939 use_quad_prec = 1 4940 curr_attempt = 1 4941 4942 MLCard.set('WriteOutFilters',True) 4943 4944 while to_attempt!=[] and need_init(): 4945 curr_attempt = to_attempt.pop() 4946 # if the attempt is a negative number it means we must force 4947 # quadruple precision at initialization time 4948 if curr_attempt < 0: 4949 use_quad_prec = -1 4950 # In quadruple precision we can lower the ZeroThres threshold 4951 MLCard.set('CTModeInit',4) 4952 MLCard.set('ZeroThres',1e-11) 4953 else: 4954 # Restore the default double precision intialization params 4955 MLCard.set('CTModeInit',1) 4956 MLCard.set('ZeroThres',1e-9) 4957 # Plus one because the filter are written on the next PS point after 4958 curr_attempt = abs(curr_attempt+1) 4959 MLCard.set('MaxAttempts',curr_attempt) 4960 MLCard.write(pjoin(SubProc_dir,'MadLoopParams.dat')) 4961 4962 # initialization is performed. 4963 MadLoopInitializer.fix_PSPoint_in_check(run_dir, read_ps = False, 4964 npoints = curr_attempt) 4965 compile_time, run_time, ram_usage = \ 4966 MadLoopInitializer.make_and_run(run_dir) 4967 if compile_time==None: 4968 logging.error("Failed at running the process in %s."%run_dir) 4969 attempts = None 4970 return None 4971 # Only set process_compilation time for the first compilation. 4972 if 'Process_compilation' not in infos.keys() or \ 4973 infos['Process_compilation']==None: 4974 infos['Process_compilation'] = compile_time 4975 infos['Initialization'] = run_time 4976 4977 MLCard_orig.write(pjoin(SubProc_dir,'MadLoopParams.dat')) 4978 if need_init(): 4979 return None 4980 else: 4981 return use_quad_prec*(curr_attempt-1)
4982 4983 @staticmethod
4984 - def need_MadLoopInit(proc_dir, subproc_prefix='PV'):
4985 """Checks whether the necessary filters are present or not.""" 4986 4987 def need_init(ML_resources_path, proc_prefix, r_files): 4988 """ Returns true if not all required files are present. """ 4989 return any([not os.path.exists(pjoin(ML_resources_path, 4990 proc_prefix+fname)) for fname in r_files])
4991 4992 MLCardPath = pjoin(proc_dir,'SubProcesses','MadLoopParams.dat') 4993 if not os.path.isfile(MLCardPath): 4994 raise MadGraph5Error, 'Could not find MadLoopParams.dat at %s.'\ 4995 %MLCardPath 4996 MLCard = banner_mod.MadLoopParam(MLCardPath) 4997 4998 req_files = ['HelFilter.dat','LoopFilter.dat'] 4999 # Make sure that LoopFilter really is needed. 5000 if not MLCard['UseLoopFilter']: 5001 try: 5002 req_files.remove('LoopFilter.dat') 5003 except ValueError: 5004 pass 5005 if MLCard['HelicityFilterLevel']==0: 5006 try: 5007 req_files.remove('HelFilter.dat') 5008 except ValueError: 5009 pass 5010 5011 for v_folder in glob.iglob(pjoin(proc_dir,'SubProcesses', 5012 '%s*'%subproc_prefix)): 5013 # Make sure it is a valid MadLoop directory 5014 if not os.path.isdir(v_folder) or not os.path.isfile(\ 5015 pjoin(v_folder,'loop_matrix.f')): 5016 continue 5017 proc_prefix_file = open(pjoin(v_folder,'proc_prefix.txt'),'r') 5018 proc_prefix = proc_prefix_file.read() 5019 proc_prefix_file.close() 5020 if need_init(pjoin(proc_dir,'SubProcesses','MadLoop5_resources'), 5021 proc_prefix, req_files): 5022 return True 5023 5024 return False 5025 5026 @staticmethod
5027 - def init_MadLoop(proc_dir, n_PS=None, subproc_prefix='PV', MG_options=None, 5028 interface = None):
5029 """Advanced commands: Compiles and run MadLoop on RAMBO random PS points to initilize the 5030 filters.""" 5031 5032 logger.debug('Compiling Source materials necessary for MadLoop '+ 5033 'initialization.') 5034 # Initialize all the virtuals directory, so as to generate the necessary 5035 # filters (essentially Helcity filter). 5036 # Make sure that the MadLoopCard has the loop induced settings 5037 if interface is None: 5038 misc.compile(arg=['treatCardsLoopNoInit'], cwd=pjoin(proc_dir,'Source')) 5039 else: 5040 interface.do_treatcards('all --no_MadLoopInit') 5041 5042 # First make sure that IREGI and CUTTOOLS are compiled if needed 5043 if os.path.exists(pjoin(proc_dir,'Source','CUTTOOLS')): 5044 misc.compile(arg=['libcuttools'],cwd=pjoin(proc_dir,'Source')) 5045 if os.path.exists(pjoin(proc_dir,'Source','IREGI')): 5046 misc.compile(arg=['libiregi'],cwd=pjoin(proc_dir,'Source')) 5047 # Then make sure DHELAS and MODEL are compiled 5048 misc.compile(arg=['libmodel'],cwd=pjoin(proc_dir,'Source')) 5049 misc.compile(arg=['libdhelas'],cwd=pjoin(proc_dir,'Source')) 5050 5051 # Now initialize the MadLoop outputs 5052 logger.info('Initializing MadLoop loop-induced matrix elements '+\ 5053 '(this can take some time)...') 5054 5055 # Setup parallelization 5056 if MG_options: 5057 mcore = cluster.MultiCore(**MG_options) 5058 else: 5059 mcore = cluster.MultiCore(nb_core=1) 5060 def run_initialization_wrapper(run_dir, infos, attempts): 5061 if attempts is None: 5062 n_PS = MadLoopInitializer.run_initialization( 5063 run_dir=run_dir, infos=infos) 5064 else: 5065 n_PS = MadLoopInitializer.run_initialization( 5066 run_dir=run_dir, infos=infos, attempts=attempts) 5067 infos['nPS'] = n_PS 5068 return 0
5069 5070 def wait_monitoring(Idle, Running, Done): 5071 if Idle+Running+Done == 0: 5072 return 5073 logger.debug('MadLoop initialization jobs: %d Idle, %d Running, %d Done'\ 5074 %(Idle, Running, Done)) 5075 5076 init_info = {} 5077 # List all virtual folders while making sure they are valid MadLoop folders 5078 VirtualFolders = [f for f in glob.iglob(pjoin(proc_dir,'SubProcesses', 5079 '%s*'%subproc_prefix)) if (os.path.isdir(f) or 5080 os.path.isfile(pjoin(f,'loop_matrix.f')))] 5081 logger.debug("Now Initializing MadLoop matrix element in %d folder%s:"%\ 5082 (len(VirtualFolders),'s' if len(VirtualFolders)>1 else '')) 5083 logger.debug(', '.join("'%s'"%os.path.basename(v_folder) for v_folder in 5084 VirtualFolders)) 5085 for v_folder in VirtualFolders: 5086 init_info[v_folder] = {} 5087 5088 # We try all multiples of n_PS from 1 to max_mult, first in DP and then 5089 # in QP before giving up, or use default values if n_PS is None. 5090 max_mult = 3 5091 if n_PS is None: 5092 # Then use the default list of number of PS points to try 5093 mcore.submit(run_initialization_wrapper, 5094 [pjoin(v_folder), init_info[v_folder], None]) 5095 else: 5096 # Use specific set of PS points 5097 mcore.submit(run_initialization_wrapper, [pjoin(v_folder), 5098 init_info[v_folder], 5099 [n_PS*multiplier for multiplier in range(1,max_mult+1)]]) 5100 5101 # Wait for all jobs to finish. 5102 mcore.wait('',wait_monitoring,update_first=wait_monitoring) 5103 for v_folder in VirtualFolders: 5104 init = init_info[v_folder] 5105 if init['nPS'] is None: 5106 raise MadGraph5Error, 'Failed the initialization of'+\ 5107 " loop-induced matrix element '%s'%s."%\ 5108 (os.path.basename(v_folder),' (using default n_PS points)' if\ 5109 n_PS is None else ' (trying with a maximum of %d PS points)'\ 5110 %(max_mult*n_PS)) 5111 if init['nPS']==0: 5112 logger.debug("Nothing to be done in '%s', all filters already "%\ 5113 os.path.basename(v_folder)+\ 5114 "present (use the '-r' option to force their recomputation)") 5115 else: 5116 logger.debug("'%s' finished using "%os.path.basename(v_folder)+ 5117 '%d PS points (%s), in %.3g(compil.) + %.3g(init.) secs.'%( 5118 abs(init['nPS']),'DP' if init['nPS']>0 else 'QP', 5119 init['Process_compilation'],init['Initialization'])) 5120 5121 logger.info('MadLoop initialization finished.') 5122 5123 AskforEditCard = common_run.AskforEditCard 5124 5125 5126 if '__main__' == __name__: 5127 # Launch the interface without any check if one code is already running. 5128 # This can ONLY run a single command !! 5129 import sys 5130 if not sys.version_info[0] == 2 or sys.version_info[1] < 6: 5131 sys.exit('MadGraph/MadEvent 5 works only with python 2.6 or later (but not python 3.X).\n'+\ 5132 'Please upgrate your version of python.') 5133 5134 import os 5135 import optparse 5136 # Get the directory of the script real path (bin) 5137 # and add it to the current PYTHONPATH 5138 root_path = os.path.dirname(os.path.dirname(os.path.realpath( __file__ ))) 5139 sys.path.insert(0, root_path)
5140 5141 - class MyOptParser(optparse.OptionParser):
5142 - class InvalidOption(Exception): pass
5143 - def error(self, msg=''):
5144 raise MyOptParser.InvalidOption(msg)
5145 # Write out nice usage message if called with -h or --help 5146 usage = "usage: %prog [options] [FILE] " 5147 parser = MyOptParser(usage=usage) 5148 parser.add_option("-l", "--logging", default='INFO', 5149 help="logging level (DEBUG|INFO|WARNING|ERROR|CRITICAL) [%default]") 5150 parser.add_option("","--web", action="store_true", default=False, dest='web', \ 5151 help='force toce to be in secure mode') 5152 parser.add_option("","--debug", action="store_true", default=False, dest='debug', \ 5153 help='force to launch debug mode') 5154 parser_error = '' 5155 done = False 5156 5157 for i in range(len(sys.argv)-1): 5158 try: 5159 (options, args) = parser.parse_args(sys.argv[1:len(sys.argv)-i]) 5160 done = True 5161 except MyOptParser.InvalidOption, error: 5162 pass 5163 else: 5164 args += sys.argv[len(sys.argv)-i:] 5165 if not done: 5166 # raise correct error: 5167 try: 5168 (options, args) = parser.parse_args() 5169 except MyOptParser.InvalidOption, error: 5170 print error 5171 sys.exit(2) 5172 5173 if len(args) == 0: 5174 args = '' 5175 5176 import subprocess 5177 import logging 5178 import logging.config 5179 # Set logging level according to the logging level given by options 5180 #logging.basicConfig(level=vars(logging)[options.logging]) 5181 import internal.coloring_logging 5182 try: 5183 if __debug__ and options.logging == 'INFO': 5184 options.logging = 'DEBUG' 5185 if options.logging.isdigit(): 5186 level = int(options.logging) 5187 else: 5188 level = eval('logging.' + options.logging) 5189 print os.path.join(root_path, 'internal', 'me5_logging.conf') 5190 logging.config.fileConfig(os.path.join(root_path, 'internal', 'me5_logging.conf')) 5191 logging.root.setLevel(level) 5192 logging.getLogger('madgraph').setLevel(level) 5193 except: 5194 raise 5195 pass 5196 5197 # Call the cmd interface main loop 5198 try: 5199 if args: 5200 # a single command is provided 5201 if '--web' in args: 5202 i = args.index('--web') 5203 args.pop(i) 5204 cmd_line = MadEventCmd(force_run=True) 5205 else: 5206 cmd_line = MadEventCmdShell(force_run=True) 5207 if not hasattr(cmd_line, 'do_%s' % args[0]): 5208 if parser_error: 5209 print parser_error 5210 print 'and %s can not be interpreted as a valid command.' % args[0] 5211 else: 5212 print 'ERROR: %s not a valid command. Please retry' % args[0] 5213 else: 5214 cmd_line.use_rawinput = False 5215 cmd_line.run_cmd(' '.join(args)) 5216 cmd_line.run_cmd('quit') 5217 5218 except KeyboardInterrupt: 5219 print 'quit on KeyboardInterrupt' 5220 pass 5221