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