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