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