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