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   
  38  try: 
  39      import readline 
  40      GNU_SPLITTING = ('GNU' in readline.__doc__) 
  41  except: 
  42      GNU_SPLITTING = True 
  43   
  44  root_path = os.path.split(os.path.dirname(os.path.realpath( __file__ )))[0] 
  45  root_path = os.path.split(root_path)[0] 
  46  sys.path.insert(0, os.path.join(root_path,'bin')) 
  47   
  48  # usefull shortcut 
  49  pjoin = os.path.join 
  50  # Special logger for the Cmd Interface 
  51  logger = logging.getLogger('madevent.stdout') # -> stdout 
  52  logger_stderr = logging.getLogger('madevent.stderr') # ->stderr 
  53    
  54  try: 
  55      # import from madgraph directory 
  56      import madgraph.interface.extended_cmd as cmd 
  57      import madgraph.interface.common_run_interface as common_run 
  58      import madgraph.iolibs.files as files 
  59      import madgraph.iolibs.save_load_object as save_load_object 
  60      import madgraph.various.banner as banner_mod 
  61      import madgraph.various.cluster as cluster 
  62      import madgraph.various.gen_crossxhtml as gen_crossxhtml 
  63      import madgraph.various.sum_html as sum_html 
  64      import madgraph.various.misc as misc 
  65      import madgraph.various.combine_runs as combine_runs 
  66   
  67      import models.check_param_card as check_param_card     
  68      from madgraph import InvalidCmd, MadGraph5Error, MG5DIR, ReadWrite 
  69      MADEVENT = False 
  70  except ImportError, error: 
  71      if __debug__: 
  72          print error 
  73      # import from madevent directory 
  74      import internal.extended_cmd as cmd 
  75      import internal.common_run_interface as common_run 
  76      import internal.banner as banner_mod 
  77      import internal.misc as misc     
  78      from internal import InvalidCmd, MadGraph5Error, ReadWrite 
  79      import internal.files as files 
  80      import internal.gen_crossxhtml as gen_crossxhtml 
  81      import internal.save_load_object as save_load_object 
  82      import internal.cluster as cluster 
  83      import internal.check_param_card as check_param_card 
  84      import internal.sum_html as sum_html 
  85      import internal.combine_runs as combine_runs 
  86      MADEVENT = True 
87 88 -class MadEventError(Exception):
89 pass
90
91 -class ZeroResult(MadEventError):
92 pass
93
94 -class SysCalcError(InvalidCmd): pass
95 96 MadEventAlreadyRunning = common_run.MadEventAlreadyRunning
97 98 #=============================================================================== 99 # CmdExtended 100 #=============================================================================== 101 -class CmdExtended(common_run.CommonRunCmd):
102 """Particularisation of the cmd command for MadEvent""" 103 104 #suggested list of command 105 next_possibility = { 106 'start': [], 107 } 108 109 debug_output = 'ME5_debug' 110 error_debug = 'Please report this bug on https://bugs.launchpad.net/madgraph5\n' 111 error_debug += 'More information is found in \'%(debug)s\'.\n' 112 error_debug += 'Please attach this file to your report.' 113 114 config_debug = 'If you need help with this issue please contact us on https://answers.launchpad.net/madgraph5\n' 115 116 117 keyboard_stop_msg = """stopping all operation 118 in order to quit MadGraph5_aMC@NLO please enter exit""" 119 120 # Define the Error 121 InvalidCmd = InvalidCmd 122 ConfigurationError = MadGraph5Error 123
124 - def __init__(self, me_dir, options, *arg, **opt):
125 """Init history and line continuation""" 126 127 # Tag allowing/forbiding question 128 self.force = False 129 130 # If possible, build an info line with current version number 131 # and date, from the VERSION text file 132 info = misc.get_pkg_info() 133 info_line = "" 134 if info and info.has_key('version') and info.has_key('date'): 135 len_version = len(info['version']) 136 len_date = len(info['date']) 137 if len_version + len_date < 30: 138 info_line = "#* VERSION %s %s %s *\n" % \ 139 (info['version'], 140 (30 - len_version - len_date) * ' ', 141 info['date']) 142 else: 143 version = open(pjoin(root_path,'MGMEVersion.txt')).readline().strip() 144 info_line = "#* VERSION %s %s *\n" % \ 145 (version, (24 - len(version)) * ' ') 146 147 # Create a header for the history file. 148 # Remember to fill in time at writeout time! 149 self.history_header = \ 150 '#************************************************************\n' + \ 151 '#* MadGraph5_aMC@NLO/MadEvent *\n' + \ 152 '#* *\n' + \ 153 "#* * * *\n" + \ 154 "#* * * * * *\n" + \ 155 "#* * * * * 5 * * * * *\n" + \ 156 "#* * * * * *\n" + \ 157 "#* * * *\n" + \ 158 "#* *\n" + \ 159 "#* *\n" + \ 160 info_line + \ 161 "#* *\n" + \ 162 "#* The MadGraph5_aMC@NLO Development Team - Find us at *\n" + \ 163 "#* https://server06.fynu.ucl.ac.be/projects/madgraph *\n" + \ 164 '#* *\n' + \ 165 '#************************************************************\n' + \ 166 '#* *\n' + \ 167 '#* Command File for MadEvent *\n' + \ 168 '#* *\n' + \ 169 '#* run as ./bin/madevent.py filename *\n' + \ 170 '#* *\n' + \ 171 '#************************************************************\n' 172 173 if info_line: 174 info_line = info_line[1:] 175 176 logger.info(\ 177 "************************************************************\n" + \ 178 "* *\n" + \ 179 "* W E L C O M E to *\n" + \ 180 "* M A D G R A P H 5 _ a M C @ N L O *\n" + \ 181 "* M A D E V E N T *\n" + \ 182 "* *\n" + \ 183 "* * * *\n" + \ 184 "* * * * * *\n" + \ 185 "* * * * * 5 * * * * *\n" + \ 186 "* * * * * *\n" + \ 187 "* * * *\n" + \ 188 "* *\n" + \ 189 info_line + \ 190 "* *\n" + \ 191 "* The MadGraph5_aMC@NLO Development Team - Find us at *\n" + \ 192 "* https://server06.fynu.ucl.ac.be/projects/madgraph *\n" + \ 193 "* *\n" + \ 194 "* Type 'help' for in-line help. *\n" + \ 195 "* *\n" + \ 196 "************************************************************") 197 super(CmdExtended, self).__init__(me_dir, options, *arg, **opt)
198
199 - def get_history_header(self):
200 """return the history header""" 201 return self.history_header % misc.get_time_info()
202
203 - def stop_on_keyboard_stop(self):
204 """action to perform to close nicely on a keyboard interupt""" 205 try: 206 if hasattr(self, 'cluster'): 207 logger.info('rm jobs on queue') 208 self.cluster.remove() 209 if hasattr(self, 'results'): 210 self.update_status('Stop by the user', level=None, makehtml=False, error=True) 211 self.add_error_log_in_html(KeyboardInterrupt) 212 except: 213 pass
214
215 - def postcmd(self, stop, line):
216 """ Update the status of the run for finishing interactive command """ 217 218 stop = super(CmdExtended, self).postcmd(stop, line) 219 # relaxing the tag forbidding question 220 self.force = False 221 222 if not self.use_rawinput: 223 return stop 224 225 if self.results and not self.results.current: 226 return stop 227 228 arg = line.split() 229 if len(arg) == 0: 230 return stop 231 if isinstance(self.results.status, str) and self.results.status.startswith('Error'): 232 return stop 233 if isinstance(self.results.status, str) and self.results.status == 'Stop by the user': 234 self.update_status('%s Stop by the user' % arg[0], level=None, error=True) 235 return stop 236 elif not self.results.status: 237 return stop 238 elif str(arg[0]) in ['exit','quit','EOF']: 239 return stop 240 241 try: 242 self.update_status('Command \'%s\' done.<br> Waiting for instruction.' % arg[0], 243 level=None, error=True) 244 except Exception: 245 misc.sprint('update_status fails') 246 pass
247 248
249 - def nice_user_error(self, error, line):
250 """If a ME run is currently running add a link in the html output""" 251 252 self.add_error_log_in_html() 253 cmd.Cmd.nice_user_error(self, error, line)
254
255 - def nice_config_error(self, error, line):
256 """If a ME run is currently running add a link in the html output""" 257 258 self.add_error_log_in_html() 259 cmd.Cmd.nice_config_error(self, error, line) 260 261 262 try: 263 debug_file = open(self.debug_output, 'a') 264 debug_file.write(open(pjoin(self.me_dir,'Cards','proc_card_mg5.dat'))) 265 debug_file.close() 266 except: 267 pass
268 269
270 - def nice_error_handling(self, error, line):
271 """If a ME run is currently running add a link in the html output""" 272 273 if isinstance(error, ZeroResult): 274 self.add_error_log_in_html(error) 275 logger.warning('Zero result detected: %s' % error) 276 # create a banner if needed 277 try: 278 if not self.banner: 279 self.banner = banner_mod.Banner() 280 if 'slha' not in self.banner: 281 self.banner.add(pjoin(self.me_dir,'Cards','param_card.dat')) 282 if 'mgruncard' not in self.banner: 283 self.banner.add(pjoin(self.me_dir,'Cards','run_card.dat')) 284 if 'mg5proccard' not in self.banner: 285 proc_card = pjoin(self.me_dir,'Cards','proc_card_mg5.dat') 286 if os.path.exists(proc_card): 287 self.banner.add(proc_card) 288 289 out_dir = pjoin(self.me_dir, 'Events', self.run_name) 290 if not os.path.isdir(out_dir): 291 os.mkdir(out_dir) 292 output_path = pjoin(out_dir, '%s_%s_banner.txt' % \ 293 (self.run_name, self.run_tag)) 294 self.banner.write(output_path) 295 except Exception: 296 if __debug__: 297 raise 298 else: 299 pass 300 else: 301 self.add_error_log_in_html() 302 cmd.Cmd.nice_error_handling(self, error, line) 303 try: 304 debug_file = open(self.debug_output, 'a') 305 debug_file.write(open(pjoin(self.me_dir,'Cards','proc_card_mg5.dat'))) 306 debug_file.close() 307 except: 308 pass
309
310 311 #=============================================================================== 312 # HelpToCmd 313 #=============================================================================== 314 -class HelpToCmd(object):
315 """ The Series of help routine for the MadEventCmd""" 316
317 - def help_banner_run(self):
318 logger.info("syntax: banner_run Path|RUN [--run_options]") 319 logger.info("-- Reproduce a run following a given banner") 320 logger.info(" One of the following argument is require:") 321 logger.info(" Path should be the path of a valid banner.") 322 logger.info(" RUN should be the name of a run of the current directory") 323 self.run_options_help([('-f','answer all question by default'), 324 ('--name=X', 'Define the name associated with the new run')])
325
326 - def help_open(self):
327 logger.info("syntax: open FILE ") 328 logger.info("-- open a file with the appropriate editor.") 329 logger.info(' If FILE belongs to index.html, param_card.dat, run_card.dat') 330 logger.info(' the path to the last created/used directory is used') 331 logger.info(' The program used to open those files can be chosen in the') 332 logger.info(' configuration file ./input/mg5_configuration.txt')
333 334
335 - def run_options_help(self, data):
336 if data: 337 logger.info('-- local options:') 338 for name, info in data: 339 logger.info(' %s : %s' % (name, info)) 340 341 logger.info("-- session options:") 342 logger.info(" Note that those options will be kept for the current session") 343 logger.info(" --cluster : Submit to the cluster. Current cluster: %s" % self.options['cluster_type']) 344 logger.info(" --multicore : Run in multi-core configuration") 345 logger.info(" --nb_core=X : limit the number of core to use to X.")
346 347
348 - def help_generate_events(self):
349 logger.info("syntax: generate_events [run_name] [options])") 350 logger.info("-- Launch the full chain of script for the generation of events") 351 logger.info(" Including possible plotting, shower and detector resolution.") 352 logger.info(" Those steps are performed if the related program are installed") 353 logger.info(" and if the related card are present in the Cards directory.") 354 self.run_options_help([('-f', 'Use default for all questions.'), 355 ('--laststep=', 'argument might be parton/pythia/pgs/delphes and indicate the last level to be run.')])
356 357
358 - def help_add_time_of_flight(self):
359 logger.info("syntax: add_time_of_flight [run_name|path_to_file] [--treshold=]") 360 logger.info('-- Add in the lhe files the information') 361 logger.info(' of how long it takes to a particle to decay.') 362 logger.info(' threshold option allows to change the minimal value required to') 363 logger.info(' a non zero value for the particle (default:1e-12s)')
364
366 367 if self.ninitial != 1: 368 logger.warning("This command is only valid for processes of type A > B C.") 369 logger.warning("This command can not be run in current context.") 370 logger.warning("") 371 372 logger.info("syntax: calculate_decay_widths [run_name] [options])") 373 logger.info("-- Calculate decay widths and enter widths and BRs in param_card") 374 logger.info(" for a series of processes of type A > B C ...") 375 self.run_options_help([('-f', 'Use default for all questions.'), 376 ('--accuracy=', 'accuracy (for each partial decay width).'\ 377 + ' Default is 0.01.')])
378
379 - def help_multi_run(self):
380 logger.info("syntax: multi_run NB_RUN [run_name] [--run_options])") 381 logger.info("-- Launch the full chain of script for the generation of events") 382 logger.info(" NB_RUN times. This chains includes possible plotting, shower") 383 logger.info(" and detector resolution.") 384 self.run_options_help([('-f', 'Use default for all questions.'), 385 ('--laststep=', 'argument might be parton/pythia/pgs/delphes and indicate the last level to be run.')])
386
387 - def help_survey(self):
388 logger.info("syntax: survey [run_name] [--run_options])") 389 logger.info("-- evaluate the different channel associate to the process") 390 self.run_options_help([("--" + key,value[-1]) for (key,value) in \ 391 self._survey_options.items()])
392
393 - def help_launch(self):
394 """exec generate_events for 2>N and calculate_width for 1>N""" 395 logger.info("syntax: launch [run_name] [options])") 396 logger.info(" --alias for either generate_events/calculate_decay_widths") 397 logger.info(" depending of the number of particles in the initial state.") 398 399 if self.ninitial == 1: 400 logger.info("For this directory this is equivalent to calculate_decay_widths") 401 self.help_calculate_decay_widths() 402 else: 403 logger.info("For this directory this is equivalent to $generate_events") 404 self.help_generate_events()
405
406 - def help_refine(self):
407 logger.info("syntax: refine require_precision [max_channel] [--run_options]") 408 logger.info("-- refine the LAST run to achieve a given precision.") 409 logger.info(" require_precision: can be either the targeted number of events") 410 logger.info(' or the required relative error') 411 logger.info(' max_channel:[5] maximal number of channel per job') 412 self.run_options_help([])
413
414 - def help_combine_events(self):
415 """ """ 416 logger.info("syntax: combine_events [run_name] [--tag=tag_name] [--run_options]") 417 logger.info("-- Combine the last run in order to write the number of events") 418 logger.info(" asked in the run_card.") 419 self.run_options_help([])
420
421 - def help_store_events(self):
422 """ """ 423 logger.info("syntax: store_events [--run_options]") 424 logger.info("-- Write physically the events in the files.") 425 logger.info(" should be launch after \'combine_events\'") 426 self.run_options_help([])
427
428 - def help_create_gridpack(self):
429 """ """ 430 logger.info("syntax: create_gridpack [--run_options]") 431 logger.info("-- create the gridpack. ") 432 logger.info(" should be launch after \'store_events\'") 433 self.run_options_help([])
434
435 - def help_import(self):
436 """ """ 437 logger.info("syntax: import command PATH") 438 logger.info("-- Execute the command present in the file") 439 self.run_options_help([])
440
441 - def help_syscalc(self):
442 logger.info("syntax: syscalc [RUN] [%s] [-f | --tag=]" % '|'.join(self._plot_mode)) 443 logger.info("-- calculate systematics information for the RUN (current run by default)") 444 logger.info(" at different stages of the event generation for scale/pdf/...")
445
446 - def help_remove(self):
447 logger.info("syntax: remove RUN [all|parton|pythia|pgs|delphes|banner] [-f] [--tag=]") 448 logger.info("-- Remove all the files linked to previous run RUN") 449 logger.info(" if RUN is 'all', then all run will be cleaned.") 450 logger.info(" The optional argument precise which part should be cleaned.") 451 logger.info(" By default we clean all the related files but the banners.") 452 logger.info(" the optional '-f' allows to by-pass all security question") 453 logger.info(" The banner can be remove only if all files are removed first.")
454
455 456 457 #=============================================================================== 458 # CheckValidForCmd 459 #=============================================================================== 460 -class CheckValidForCmd(object):
461 """ The Series of check routine for the MadEventCmd""" 462
463 - def check_banner_run(self, args):
464 """check the validity of line""" 465 466 if len(args) == 0: 467 self.help_banner_run() 468 raise self.InvalidCmd('banner_run requires at least one argument.') 469 470 tag = [a[6:] for a in args if a.startswith('--tag=')] 471 472 473 if os.path.exists(args[0]): 474 type ='banner' 475 format = self.detect_card_type(args[0]) 476 if format != 'banner': 477 raise self.InvalidCmd('The file is not a valid banner.') 478 elif tag: 479 args[0] = pjoin(self.me_dir,'Events', args[0], '%s_%s_banner.txt' % \ 480 (args[0], tag)) 481 if not os.path.exists(args[0]): 482 raise self.InvalidCmd('No banner associates to this name and tag.') 483 else: 484 name = args[0] 485 type = 'run' 486 banners = glob.glob(pjoin(self.me_dir,'Events', args[0], '*_banner.txt')) 487 if not banners: 488 raise self.InvalidCmd('No banner associates to this name.') 489 elif len(banners) == 1: 490 args[0] = banners[0] 491 else: 492 #list the tag and propose those to the user 493 tags = [os.path.basename(p)[len(args[0])+1:-11] for p in banners] 494 tag = self.ask('which tag do you want to use?', tags[0], tags) 495 args[0] = pjoin(self.me_dir,'Events', args[0], '%s_%s_banner.txt' % \ 496 (args[0], tag)) 497 498 run_name = [arg[7:] for arg in args if arg.startswith('--name=')] 499 if run_name: 500 try: 501 self.exec_cmd('remove %s all banner -f' % run_name) 502 except Exception: 503 pass 504 self.set_run_name(args[0], tag=None, level='parton', reload_card=True) 505 elif type == 'banner': 506 self.set_run_name(self.find_available_run_name(self.me_dir)) 507 elif type == 'run': 508 if not self.results[name].is_empty(): 509 run_name = self.find_available_run_name(self.me_dir) 510 logger.info('Run %s is not empty so will use run_name: %s' % \ 511 (name, run_name)) 512 self.set_run_name(run_name) 513 else: 514 try: 515 self.exec_cmd('remove %s all banner -f' % run_name) 516 except Exception: 517 pass 518 self.set_run_name(name)
519
520 - def check_history(self, args):
521 """check the validity of line""" 522 523 if len(args) > 1: 524 self.help_history() 525 raise self.InvalidCmd('\"history\" command takes at most one argument') 526 527 if not len(args): 528 return 529 elif args[0] != 'clean': 530 dirpath = os.path.dirname(args[0]) 531 if dirpath and not os.path.exists(dirpath) or \ 532 os.path.isdir(args[0]): 533 raise self.InvalidCmd("invalid path %s " % dirpath)
534
535 - def check_save(self, args):
536 """ check the validity of the line""" 537 538 if len(args) == 0: 539 args.append('options') 540 541 if args[0] not in self._save_opts: 542 raise self.InvalidCmd('wrong \"save\" format') 543 544 if args[0] != 'options' and len(args) != 2: 545 self.help_save() 546 raise self.InvalidCmd('wrong \"save\" format') 547 elif args[0] != 'options' and len(args) == 2: 548 basename = os.path.dirname(args[1]) 549 if not os.path.exists(basename): 550 raise self.InvalidCmd('%s is not a valid path, please retry' % \ 551 args[1]) 552 553 if args[0] == 'options': 554 has_path = None 555 for arg in args[1:]: 556 if arg in ['--auto', '--all']: 557 continue 558 elif arg.startswith('--'): 559 raise self.InvalidCmd('unknow command for \'save options\'') 560 else: 561 basename = os.path.dirname(arg) 562 if not os.path.exists(basename): 563 raise self.InvalidCmd('%s is not a valid path, please retry' % \ 564 arg) 565 elif has_path: 566 raise self.InvalidCmd('only one path is allowed') 567 else: 568 args.remove(arg) 569 args.insert(1, arg) 570 has_path = True 571 if not has_path: 572 if '--auto' in arg and self.options['mg5_path']: 573 args.insert(1, pjoin(self.options['mg5_path'],'input','mg5_configuration.txt')) 574 else: 575 args.insert(1, pjoin(self.me_dir,'Cards','me5_configuration.txt'))
576
577 - def check_set(self, args):
578 """ check the validity of the line""" 579 580 if len(args) < 2: 581 self.help_set() 582 raise self.InvalidCmd('set needs an option and an argument') 583 584 if args[0] not in self._set_options + self.options.keys(): 585 self.help_set() 586 raise self.InvalidCmd('Possible options for set are %s' % \ 587 self._set_options) 588 589 if args[0] in ['stdout_level']: 590 if args[1] not in ['DEBUG','INFO','WARNING','ERROR','CRITICAL'] \ 591 and not args[1].isdigit(): 592 raise self.InvalidCmd('output_level needs ' + \ 593 'a valid level') 594 595 if args[0] in ['timeout']: 596 if not args[1].isdigit(): 597 raise self.InvalidCmd('timeout values should be a integer')
598
599 - def check_open(self, args):
600 """ check the validity of the line """ 601 602 if len(args) != 1: 603 self.help_open() 604 raise self.InvalidCmd('OPEN command requires exactly one argument') 605 606 if args[0].startswith('./'): 607 if not os.path.isfile(args[0]): 608 raise self.InvalidCmd('%s: not such file' % args[0]) 609 return True 610 611 # if special : create the path. 612 if not self.me_dir: 613 if not os.path.isfile(args[0]): 614 self.help_open() 615 raise self.InvalidCmd('No MadEvent path defined. Unable to associate this name to a file') 616 else: 617 return True 618 619 path = self.me_dir 620 if os.path.isfile(os.path.join(path,args[0])): 621 args[0] = os.path.join(path,args[0]) 622 elif os.path.isfile(os.path.join(path,'Cards',args[0])): 623 args[0] = os.path.join(path,'Cards',args[0]) 624 elif os.path.isfile(os.path.join(path,'HTML',args[0])): 625 args[0] = os.path.join(path,'HTML',args[0]) 626 # special for card with _default define: copy the default and open it 627 elif '_card.dat' in args[0]: 628 name = args[0].replace('_card.dat','_card_default.dat') 629 if os.path.isfile(os.path.join(path,'Cards', name)): 630 files.cp(os.path.join(path,'Cards', name), os.path.join(path,'Cards', args[0])) 631 args[0] = os.path.join(path,'Cards', args[0]) 632 else: 633 raise self.InvalidCmd('No default path for this file') 634 elif not os.path.isfile(args[0]): 635 raise self.InvalidCmd('No default path for this file')
636
637 - def check_treatcards(self, args):
638 """check that treatcards arguments are valid 639 [param|run|all] [--output_dir=] [--param_card=] [--run_card=] 640 """ 641 642 opt = {'output_dir':pjoin(self.me_dir,'Source'), 643 'param_card':pjoin(self.me_dir,'Cards','param_card.dat'), 644 'run_card':pjoin(self.me_dir,'Cards','run_card.dat')} 645 mode = 'all' 646 for arg in args: 647 if arg.startswith('--') and '=' in arg: 648 key,value =arg[2:].split('=',1) 649 if not key in opt: 650 self.help_treatcards() 651 raise self.InvalidCmd('Invalid option for treatcards command:%s ' \ 652 % key) 653 if key in ['param_card', 'run_card']: 654 if os.path.isfile(value): 655 card_name = self.detect_card_type(value) 656 if card_name != key: 657 raise self.InvalidCmd('Format for input file detected as %s while expecting %s' 658 % (card_name, key)) 659 opt[key] = value 660 elif os.path.isfile(pjoin(self.me_dir,value)): 661 card_name = self.detect_card_type(pjoin(self.me_dir,value)) 662 if card_name != key: 663 raise self.InvalidCmd('Format for input file detected as %s while expecting %s' 664 % (card_name, key)) 665 opt[key] = value 666 else: 667 raise self.InvalidCmd('No such file: %s ' % value) 668 elif key in ['output_dir']: 669 if os.path.isdir(value): 670 opt[key] = value 671 elif os.path.isdir(pjoin(self.me_dir,value)): 672 opt[key] = pjoin(self.me_dir, value) 673 else: 674 raise self.InvalidCmd('No such directory: %s' % value) 675 elif arg in ['param','run','all']: 676 mode = arg 677 else: 678 self.help_treatcards() 679 raise self.InvalidCmd('Unvalid argument %s' % arg) 680 681 return mode, opt
682 683
684 - def check_survey(self, args, cmd='survey'):
685 """check that the argument for survey are valid""" 686 687 688 self.opts = dict([(key,value[1]) for (key,value) in \ 689 self._survey_options.items()]) 690 691 # Treat any arguments starting with '--' 692 while args and args[-1].startswith('--'): 693 arg = args.pop(-1) 694 try: 695 for opt,value in self._survey_options.items(): 696 if arg.startswith('--%s=' % opt): 697 exec('self.opts[\'%s\'] = %s(arg.split(\'=\')[-1])' % \ 698 (opt, value[0])) 699 arg = "" 700 if arg != "": raise Exception 701 except Exception: 702 self.help_survey() 703 raise self.InvalidCmd('invalid %s argument'% arg) 704 705 if len(args) > 1: 706 self.help_survey() 707 raise self.InvalidCmd('Too many argument for %s command' % cmd) 708 elif not args: 709 # No run name assigned -> assigned one automaticaly 710 self.set_run_name(self.find_available_run_name(self.me_dir)) 711 else: 712 self.set_run_name(args[0], None,'parton', True) 713 args.pop(0) 714 715 return True
716
717 - def check_generate_events(self, args):
718 """check that the argument for generate_events are valid""" 719 720 run = None 721 if args and args[-1].startswith('--laststep='): 722 run = args[-1].split('=')[-1] 723 if run not in ['auto','parton', 'pythia', 'pgs', 'delphes']: 724 self.help_generate_events() 725 raise self.InvalidCmd('invalid %s argument'% args[-1]) 726 if run != 'parton' and not self.options['pythia-pgs_path']: 727 raise self.InvalidCmd('''pythia-pgs not install. Please install this package first. 728 To do so type: \'install pythia-pgs\' in the mg5 interface''') 729 if run == 'delphes' and not self.options['delphes_path']: 730 raise self.InvalidCmd('''delphes not install. Please install this package first. 731 To do so type: \'install Delphes\' in the mg5 interface''') 732 del args[-1] 733 734 if len(args) > 1: 735 self.help_generate_events() 736 raise self.InvalidCmd('Too many argument for generate_events command: %s' % cmd) 737 738 return run
739
740 - def check_add_time_of_flight(self, args):
741 """check that the argument are correct""" 742 743 744 if len(args) >2: 745 self.help_time_of_flight() 746 raise self.InvalidCmd('Too many arguments') 747 748 # check if the threshold is define. and keep it's value 749 if args and args[-1].startswith('--threshold='): 750 try: 751 threshold = float(args[-1].split('=')[1]) 752 except ValueError: 753 raise self.InvalidCmd('threshold options require a number.') 754 args.remove(args[-1]) 755 else: 756 threshold = 1e-12 757 758 if len(args) == 1 and os.path.exists(args[0]): 759 event_path = args[0] 760 else: 761 if len(args) and self.run_name != args[0]: 762 self.set_run_name(args.pop(0)) 763 elif not self.run_name: 764 self.help_add_time_of_flight() 765 raise self.InvalidCmd('Need a run_name to process') 766 event_path = pjoin(self.me_dir, 'Events', self.run_name, 'unweighted_events.lhe.gz') 767 if not os.path.exists(event_path): 768 event_path = event_path[:-3] 769 if not os.path.exists(event_path): 770 raise self.InvalidCmd('No unweighted events associate to this run.') 771 772 773 774 #reformat the data 775 args[:] = [event_path, threshold]
776
777 - def check_calculate_decay_widths(self, args):
778 """check that the argument for calculate_decay_widths are valid""" 779 780 if self.ninitial != 1: 781 raise self.InvalidCmd('Can only calculate decay widths for decay processes A > B C ...') 782 783 accuracy = 0.01 784 run = None 785 if args and args[-1].startswith('--accuracy='): 786 try: 787 accuracy = float(args[-1].split('=')[-1]) 788 except Exception: 789 raise self.InvalidCmd('Argument error in calculate_decay_widths command') 790 del args[-1] 791 if len(args) > 1: 792 self.help_calculate_decay_widths() 793 raise self.InvalidCmd('Too many argument for calculate_decay_widths command: %s' % cmd) 794 795 return accuracy
796 797 798
799 - def check_multi_run(self, args):
800 """check that the argument for survey are valid""" 801 802 run = None 803 804 if not len(args): 805 self.help_multi_run() 806 raise self.InvalidCmd("""multi_run command requires at least one argument for 807 the number of times that it call generate_events command""") 808 809 if args[-1].startswith('--laststep='): 810 run = args[-1].split('=')[-1] 811 if run not in ['parton', 'pythia', 'pgs', 'delphes']: 812 self.help_multi_run() 813 raise self.InvalidCmd('invalid %s argument'% args[-1]) 814 if run != 'parton' and not self.options['pythia-pgs_path']: 815 raise self.InvalidCmd('''pythia-pgs not install. Please install this package first. 816 To do so type: \'install pythia-pgs\' in the mg5 interface''') 817 if run == 'delphes' and not self.options['delphes_path']: 818 raise self.InvalidCmd('''delphes not install. Please install this package first. 819 To do so type: \'install Delphes\' in the mg5 interface''') 820 del args[-1] 821 822 823 elif not args[0].isdigit(): 824 self.help_multi_run() 825 raise self.InvalidCmd("The first argument of multi_run should be a integer.") 826 nb_run = args.pop(0) 827 self.check_survey(args, cmd='multi_run') 828 args.insert(0, int(nb_run)) 829 830 return run
831
832 - def check_refine(self, args):
833 """check that the argument for survey are valid""" 834 835 # if last argument is not a number -> it's the run_name (Not allow anymore) 836 try: 837 float(args[-1]) 838 except ValueError: 839 self.help_refine() 840 raise self.InvalidCmd('Not valid arguments') 841 except IndexError: 842 self.help_refine() 843 raise self.InvalidCmd('require_precision argument is require for refine cmd') 844 845 846 if not self.run_name: 847 if self.results.lastrun: 848 self.set_run_name(self.results.lastrun) 849 else: 850 raise self.InvalidCmd('No run_name currently define. Unable to run refine') 851 852 if len(args) > 2: 853 self.help_refine() 854 raise self.InvalidCmd('Too many argument for refine command') 855 else: 856 try: 857 [float(arg) for arg in args] 858 except ValueError: 859 self.help_refine() 860 raise self.InvalidCmd('refine arguments are suppose to be number') 861 862 return True
863
864 - def check_combine_events(self, arg):
865 """ Check the argument for the combine events command """ 866 867 tag = [a for a in arg if a.startswith('--tag=')] 868 if tag: 869 arg.remove(tag[0]) 870 tag = tag[0][6:] 871 elif not self.run_tag: 872 tag = 'tag_1' 873 else: 874 tag = self.run_tag 875 self.run_tag = tag 876 877 if len(arg) > 1: 878 self.help_combine_events() 879 raise self.InvalidCmd('Too many argument for combine_events command') 880 881 if len(arg) == 1: 882 self.set_run_name(arg[0], self.run_tag, 'parton', True) 883 884 if not self.run_name: 885 if not self.results.lastrun: 886 raise self.InvalidCmd('No run_name currently define. Unable to run combine') 887 else: 888 self.set_run_name(self.results.lastrun) 889 890 return True
891
892 - def check_pythia(self, args):
893 """Check the argument for pythia command 894 syntax: pythia [NAME] 895 Note that other option are already remove at this point 896 """ 897 898 mode = None 899 laststep = [arg for arg in args if arg.startswith('--laststep=')] 900 if laststep and len(laststep)==1: 901 mode = laststep[0].split('=')[-1] 902 if mode not in ['auto', 'pythia', 'pgs', 'delphes']: 903 self.help_pythia() 904 raise self.InvalidCmd('invalid %s argument'% args[-1]) 905 elif laststep: 906 raise self.InvalidCmd('only one laststep argument is allowed') 907 908 # If not pythia-pgs path 909 if not self.options['pythia-pgs_path']: 910 logger.info('Retry to read configuration file to find pythia-pgs path') 911 self.set_configuration() 912 913 if not self.options['pythia-pgs_path'] or not \ 914 os.path.exists(pjoin(self.options['pythia-pgs_path'],'src')): 915 error_msg = 'No valid pythia-pgs path set.\n' 916 error_msg += 'Please use the set command to define the path and retry.\n' 917 error_msg += 'You can also define it in the configuration file.\n' 918 raise self.InvalidCmd(error_msg) 919 920 921 922 tag = [a for a in args if a.startswith('--tag=')] 923 if tag: 924 args.remove(tag[0]) 925 tag = tag[0][6:] 926 927 if len(args) == 0 and not self.run_name: 928 if self.results.lastrun: 929 args.insert(0, self.results.lastrun) 930 else: 931 raise self.InvalidCmd('No run name currently define. Please add this information.') 932 933 if len(args) >= 1: 934 if args[0] != self.run_name and\ 935 not os.path.exists(pjoin(self.me_dir,'Events',args[0], 'unweighted_events.lhe.gz')): 936 raise self.InvalidCmd('No events file corresponding to %s run. '% args[0]) 937 self.set_run_name(args[0], tag, 'pythia') 938 else: 939 if tag: 940 self.run_card['run_tag'] = tag 941 self.set_run_name(self.run_name, tag, 'pythia') 942 943 input_file = pjoin(self.me_dir,'Events',self.run_name, 'unweighted_events.lhe') 944 output_file = pjoin(self.me_dir, 'Events', 'unweighted_events.lhe') 945 if not os.path.exists('%s.gz' % input_file): 946 if not os.path.exists(input_file): 947 raise self.InvalidCmd('No events file corresponding to %s run. '% self.run_name) 948 files.cp(input_file, output_file) 949 else: 950 misc.gunzip(input_file, keep=True, stdout=output_file) 951 952 args.append(mode)
953
954 - def check_remove(self, args):
955 """Check that the remove command is valid""" 956 957 tmp_args = args[:] 958 959 tag = [a[6:] for a in tmp_args if a.startswith('--tag=')] 960 if tag: 961 tag = tag[0] 962 tmp_args.remove('--tag=%s' % tag) 963 964 965 if len(tmp_args) == 0: 966 self.help_remove() 967 raise self.InvalidCmd('clean command require the name of the run to clean') 968 elif len(tmp_args) == 1: 969 return tmp_args[0], tag, ['all'] 970 else: 971 for arg in tmp_args[1:]: 972 if arg not in self._clean_mode: 973 self.help_remove() 974 raise self.InvalidCmd('%s is not a valid options for clean command'\ 975 % arg) 976 return tmp_args[0], tag, tmp_args[1:]
977
978 - def check_plot(self, args):
979 """Check the argument for the plot command 980 plot run_name modes""" 981 982 madir = self.options['madanalysis_path'] 983 td = self.options['td_path'] 984 985 if not madir or not td: 986 logger.info('Retry to read configuration file to find madanalysis/td') 987 self.set_configuration() 988 989 madir = self.options['madanalysis_path'] 990 td = self.options['td_path'] 991 992 if not madir: 993 error_msg = 'No valid MadAnalysis path set.\n' 994 error_msg += 'Please use the set command to define the path and retry.\n' 995 error_msg += 'You can also define it in the configuration file.\n' 996 raise self.InvalidCmd(error_msg) 997 if not td: 998 error_msg = 'No valid td path set.\n' 999 error_msg += 'Please use the set command to define the path and retry.\n' 1000 error_msg += 'You can also define it in the configuration file.\n' 1001 raise self.InvalidCmd(error_msg) 1002 1003 if len(args) == 0: 1004 if not hasattr(self, 'run_name') or not self.run_name: 1005 self.help_plot() 1006 raise self.InvalidCmd('No run name currently define. Please add this information.') 1007 args.append('all') 1008 return 1009 1010 1011 if args[0] not in self._plot_mode: 1012 self.set_run_name(args[0], level='plot') 1013 del args[0] 1014 if len(args) == 0: 1015 args.append('all') 1016 elif not self.run_name: 1017 self.help_plot() 1018 raise self.InvalidCmd('No run name currently define. Please add this information.') 1019 1020 for arg in args: 1021 if arg not in self._plot_mode and arg != self.run_name: 1022 self.help_plot() 1023 raise self.InvalidCmd('unknown options %s' % arg)
1024
1025 - def check_syscalc(self, args):
1026 """Check the argument for the syscalc command 1027 syscalc run_name modes""" 1028 1029 scdir = self.options['syscalc_path'] 1030 1031 if not scdir: 1032 logger.info('Retry to read configuration file to find SysCalc') 1033 self.set_configuration() 1034 1035 scdir = self.options['syscalc_path'] 1036 1037 if not scdir: 1038 error_msg = 'No valid SysCalc path set.\n' 1039 error_msg += 'Please use the set command to define the path and retry.\n' 1040 error_msg += 'You can also define it in the configuration file.\n' 1041 error_msg += 'Please note that you need to compile SysCalc first.' 1042 raise self.InvalidCmd(error_msg) 1043 1044 if len(args) == 0: 1045 if not hasattr(self, 'run_name') or not self.run_name: 1046 self.help_syscalc() 1047 raise self.InvalidCmd('No run name currently defined. Please add this information.') 1048 args.append('all') 1049 return 1050 1051 #deal options 1052 tag = [a for a in args if a.startswith('--tag=')] 1053 if tag: 1054 args.remove(tag[0]) 1055 tag = tag[0][6:] 1056 1057 if args[0] not in self._syscalc_mode: 1058 self.set_run_name(args[0], tag=tag, level='syscalc') 1059 del args[0] 1060 if len(args) == 0: 1061 args.append('all') 1062 elif not self.run_name: 1063 self.help_syscalc() 1064 raise self.InvalidCmd('No run name currently defined. Please add this information.') 1065 elif tag and tag != self.run_tag: 1066 self.set_run_name(self.run_name, tag=tag, level='syscalc') 1067 1068 for arg in args: 1069 if arg not in self._syscalc_mode and arg != self.run_name: 1070 self.help_syscalc() 1071 raise self.InvalidCmd('unknown options %s' % arg) 1072 1073 if self.run_card['use_syst'] not in self.true: 1074 raise self.InvalidCmd('Run %s does not include ' % self.run_name + \ 1075 'systematics information needed for syscalc.')
1076 1077
1078 - def check_pgs(self, arg):
1079 """Check the argument for pythia command 1080 syntax: pgs [NAME] 1081 Note that other option are already remove at this point 1082 """ 1083 1084 # If not pythia-pgs path 1085 if not self.options['pythia-pgs_path']: 1086 logger.info('Retry to read configuration file to find pythia-pgs path') 1087 self.set_configuration() 1088 1089 if not self.options['pythia-pgs_path'] or not \ 1090 os.path.exists(pjoin(self.options['pythia-pgs_path'],'src')): 1091 error_msg = 'No valid pythia-pgs path set.\n' 1092 error_msg += 'Please use the set command to define the path and retry.\n' 1093 error_msg += 'You can also define it in the configuration file.\n' 1094 raise self.InvalidCmd(error_msg) 1095 1096 tag = [a for a in arg if a.startswith('--tag=')] 1097 if tag: 1098 arg.remove(tag[0]) 1099 tag = tag[0][6:] 1100 1101 1102 if len(arg) == 0 and not self.run_name: 1103 if self.results.lastrun: 1104 arg.insert(0, self.results.lastrun) 1105 else: 1106 raise self.InvalidCmd('No run name currently define. Please add this information.') 1107 1108 if len(arg) == 1 and self.run_name == arg[0]: 1109 arg.pop(0) 1110 1111 if not len(arg) and \ 1112 not os.path.exists(pjoin(self.me_dir,'Events','pythia_events.hep')): 1113 self.help_pgs() 1114 raise self.InvalidCmd('''No file file pythia_events.hep currently available 1115 Please specify a valid run_name''') 1116 1117 lock = None 1118 if len(arg) == 1: 1119 prev_tag = self.set_run_name(arg[0], tag, 'pgs') 1120 if not os.path.exists(pjoin(self.me_dir,'Events',self.run_name,'%s_pythia_events.hep.gz' % prev_tag)): 1121 raise self.InvalidCmd('No events file corresponding to %s run with tag %s. '% (self.run_name, prev_tag)) 1122 else: 1123 input_file = pjoin(self.me_dir,'Events', self.run_name, '%s_pythia_events.hep.gz' % prev_tag) 1124 output_file = pjoin(self.me_dir, 'Events', 'pythia_events.hep') 1125 lock = cluster.asyncrone_launch('gunzip',stdout=open(output_file,'w'), 1126 argument=['-c', input_file]) 1127 1128 else: 1129 if tag: 1130 self.run_card['run_tag'] = tag 1131 self.set_run_name(self.run_name, tag, 'pgs') 1132 1133 return lock
1134
1135 - def check_delphes(self, arg):
1136 """Check the argument for pythia command 1137 syntax: delphes [NAME] 1138 Note that other option are already remove at this point 1139 """ 1140 1141 # If not pythia-pgs path 1142 if not self.options['delphes_path']: 1143 logger.info('Retry to read configuration file to find delphes path') 1144 self.set_configuration() 1145 1146 if not self.options['delphes_path']: 1147 error_msg = 'No valid Delphes path set.\n' 1148 error_msg += 'Please use the set command to define the path and retry.\n' 1149 error_msg += 'You can also define it in the configuration file.\n' 1150 raise self.InvalidCmd(error_msg) 1151 1152 tag = [a for a in arg if a.startswith('--tag=')] 1153 if tag: 1154 arg.remove(tag[0]) 1155 tag = tag[0][6:] 1156 1157 1158 if len(arg) == 0 and not self.run_name: 1159 if self.results.lastrun: 1160 arg.insert(0, self.results.lastrun) 1161 else: 1162 raise self.InvalidCmd('No run name currently define. Please add this information.') 1163 1164 if len(arg) == 1 and self.run_name == arg[0]: 1165 arg.pop(0) 1166 1167 if not len(arg) and \ 1168 not os.path.exists(pjoin(self.me_dir,'Events','pythia_events.hep')): 1169 self.help_pgs() 1170 raise self.InvalidCmd('''No file file pythia_events.hep currently available 1171 Please specify a valid run_name''') 1172 1173 lock = None 1174 if len(arg) == 1: 1175 prev_tag = self.set_run_name(arg[0], tag, 'delphes') 1176 if not os.path.exists(pjoin(self.me_dir,'Events',self.run_name, '%s_pythia_events.hep.gz' % prev_tag)): 1177 raise self.InvalidCmd('No events file corresponding to %s run with tag %s.:%s '\ 1178 % (self.run_name, prev_tag, 1179 pjoin(self.me_dir,'Events',self.run_name, '%s_pythia_events.hep.gz' % prev_tag))) 1180 else: 1181 input_file = pjoin(self.me_dir,'Events', self.run_name, '%s_pythia_events.hep.gz' % prev_tag) 1182 output_file = pjoin(self.me_dir, 'Events', 'pythia_events.hep') 1183 lock = cluster.asyncrone_launch('gunzip',stdout=open(output_file,'w'), 1184 argument=['-c', input_file]) 1185 else: 1186 if tag: 1187 self.run_card['run_tag'] = tag 1188 self.set_run_name(self.run_name, tag, 'delphes') 1189 1190 return lock
1191
1192 - def check_display(self, args):
1193 """check the validity of line 1194 syntax: display XXXXX 1195 """ 1196 1197 if len(args) < 1 or args[0] not in self._display_opts: 1198 self.help_display() 1199 raise self.InvalidCmd 1200 1201 if args[0] == 'variable' and len(args) !=2: 1202 raise self.InvalidCmd('variable need a variable name')
1203 1204 1205 1206 1207
1208 - def check_import(self, args):
1209 """check the validity of line""" 1210 1211 if not args: 1212 self.help_import() 1213 raise self.InvalidCmd('wrong \"import\" format') 1214 1215 if args[0] != 'command': 1216 args.insert(0,'command') 1217 1218 1219 if not len(args) == 2 or not os.path.exists(args[1]): 1220 raise self.InvalidCmd('PATH is mandatory for import command\n')
1221
1222 1223 #=============================================================================== 1224 # CompleteForCmd 1225 #=============================================================================== 1226 -class CompleteForCmd(CheckValidForCmd):
1227 """ The Series of help routine for the MadGraphCmd""" 1228 1229
1230 - def complete_add_time_of_flight(self, text, line, begidx, endidx):
1231 "Complete command" 1232 1233 args = self.split_arg(line[0:begidx], error=False) 1234 1235 if len(args) == 1: 1236 #return valid run_name 1237 data = glob.glob(pjoin(self.me_dir, 'Events', '*','unweighted_events.lhe.gz')) 1238 data = [n.rsplit('/',2)[1] for n in data] 1239 return self.list_completion(text, data + ['--threshold='], line) 1240 elif args[-1].endswith(os.path.sep): 1241 return self.path_completion(text, 1242 os.path.join('.',*[a for a in args \ 1243 if a.endswith(os.path.sep)])) 1244 else: 1245 return self.list_completion(text, ['--threshold='], line)
1246
1247 - def complete_banner_run(self, text, line, begidx, endidx):
1248 "Complete the banner run command" 1249 try: 1250 1251 1252 args = self.split_arg(line[0:begidx], error=False) 1253 1254 if args[-1].endswith(os.path.sep): 1255 return self.path_completion(text, 1256 os.path.join('.',*[a for a in args \ 1257 if a.endswith(os.path.sep)])) 1258 1259 1260 if len(args) > 1: 1261 # only options are possible 1262 tags = glob.glob(pjoin(self.me_dir, 'Events' , args[1],'%s_*_banner.txt' % args[1])) 1263 tags = ['%s' % os.path.basename(t)[len(args[1])+1:-11] for t in tags] 1264 1265 if args[-1] != '--tag=': 1266 tags = ['--tag=%s' % t for t in tags] 1267 else: 1268 return self.list_completion(text, tags) 1269 return self.list_completion(text, tags +['--name=','-f'], line) 1270 1271 # First argument 1272 possibilites = {} 1273 1274 comp = self.path_completion(text, os.path.join('.',*[a for a in args \ 1275 if a.endswith(os.path.sep)])) 1276 if os.path.sep in line: 1277 return comp 1278 else: 1279 possibilites['Path from ./'] = comp 1280 1281 run_list = glob.glob(pjoin(self.me_dir, 'Events', '*','*_banner.txt')) 1282 run_list = [n.rsplit('/',2)[1] for n in run_list] 1283 possibilites['RUN Name'] = self.list_completion(text, run_list) 1284 1285 return self.deal_multiple_categories(possibilites) 1286 1287 1288 except Exception, error: 1289 print error
1290 1291
1292 - def complete_history(self, text, line, begidx, endidx):
1293 "Complete the history command" 1294 1295 args = self.split_arg(line[0:begidx], error=False) 1296 1297 # Directory continuation 1298 if args[-1].endswith(os.path.sep): 1299 return self.path_completion(text, 1300 os.path.join('.',*[a for a in args \ 1301 if a.endswith(os.path.sep)])) 1302 1303 if len(args) == 1: 1304 return self.path_completion(text)
1305
1306 - def complete_open(self, text, line, begidx, endidx):
1307 """ complete the open command """ 1308 1309 args = self.split_arg(line[0:begidx]) 1310 1311 # Directory continuation 1312 if os.path.sep in args[-1] + text: 1313 return self.path_completion(text, 1314 os.path.join('.',*[a for a in args if \ 1315 a.endswith(os.path.sep)])) 1316 1317 possibility = [] 1318 if self.me_dir: 1319 path = self.me_dir 1320 possibility = ['index.html'] 1321 if os.path.isfile(os.path.join(path,'README')): 1322 possibility.append('README') 1323 if os.path.isdir(os.path.join(path,'Cards')): 1324 possibility += [f for f in os.listdir(os.path.join(path,'Cards')) 1325 if f.endswith('.dat')] 1326 if os.path.isdir(os.path.join(path,'HTML')): 1327 possibility += [f for f in os.listdir(os.path.join(path,'HTML')) 1328 if f.endswith('.html') and 'default' not in f] 1329 else: 1330 possibility.extend(['./','../']) 1331 if os.path.exists('ME5_debug'): 1332 possibility.append('ME5_debug') 1333 if os.path.exists('MG5_debug'): 1334 possibility.append('MG5_debug') 1335 return self.list_completion(text, possibility)
1336
1337 - def complete_set(self, text, line, begidx, endidx):
1338 "Complete the set command" 1339 1340 args = self.split_arg(line[0:begidx]) 1341 1342 # Format 1343 if len(args) == 1: 1344 return self.list_completion(text, self._set_options + self.options.keys() ) 1345 1346 if len(args) == 2: 1347 if args[1] == 'stdout_level': 1348 return self.list_completion(text, ['DEBUG','INFO','WARNING','ERROR','CRITICAL']) 1349 else: 1350 first_set = ['None','True','False'] 1351 # directory names 1352 second_set = [name for name in self.path_completion(text, '.', only_dirs = True)] 1353 return self.list_completion(text, first_set + second_set) 1354 elif len(args) >2 and args[-1].endswith(os.path.sep): 1355 return self.path_completion(text, 1356 os.path.join('.',*[a for a in args if a.endswith(os.path.sep)]), 1357 only_dirs = True)
1358
1359 - def complete_survey(self, text, line, begidx, endidx):
1360 """ Complete the survey command """ 1361 1362 if line.endswith('nb_core=') and not text: 1363 import multiprocessing 1364 max = multiprocessing.cpu_count() 1365 return [str(i) for i in range(2,max+1)] 1366 1367 return self.list_completion(text, self._run_options, line)
1368 1369 complete_refine = complete_survey 1370 complete_combine_events = complete_survey 1371 complite_store = complete_survey 1372 complete_generate_events = complete_survey 1373 complete_create_gridpack = complete_survey 1374
1375 - def complete_generate_events(self, text, line, begidx, endidx):
1376 """ Complete the generate events""" 1377 1378 if line.endswith('nb_core=') and not text: 1379 import multiprocessing 1380 max = multiprocessing.cpu_count() 1381 return [str(i) for i in range(2,max+1)] 1382 if line.endswith('laststep=') and not text: 1383 return ['parton','pythia','pgs','delphes'] 1384 elif '--laststep=' in line.split()[-1] and line and line[-1] != ' ': 1385 return self.list_completion(text,['parton','pythia','pgs','delphes'],line) 1386 1387 opts = self._run_options + self._generate_options 1388 return self.list_completion(text, opts, line)
1389
1390 - def complete_launch(self, *args, **opts):
1391 1392 if self.ninitial == 1: 1393 return self.complete_calculate_decay_widths(*args, **opts) 1394 else: 1395 return self.complete_generate_events(*args, **opts)
1396
1397 - def complete_calculate_decay_widths(self, text, line, begidx, endidx):
1398 """ Complete the calculate_decay_widths command""" 1399 1400 if line.endswith('nb_core=') and not text: 1401 import multiprocessing 1402 max = multiprocessing.cpu_count() 1403 return [str(i) for i in range(2,max+1)] 1404 1405 opts = self._run_options + self._calculate_decay_options 1406 return self.list_completion(text, opts, line)
1407
1408 - def complete_display(self, text, line, begidx, endidx):
1409 """ Complete the display command""" 1410 1411 args = self.split_arg(line[0:begidx], error=False) 1412 if len(args) >= 2 and args[1] =='results': 1413 start = line.find('results') 1414 return self.complete_print_results(text, 'print_results '+line[start+7:], begidx+2+start, endidx+2+start) 1415 return super(CompleteForCmd, self).complete_display(text, line, begidx, endidx)
1416
1417 - def complete_multi_run(self, text, line, begidx, endidx):
1418 """complete multi run command""" 1419 1420 args = self.split_arg(line[0:begidx], error=False) 1421 if len(args) == 1: 1422 data = [str(i) for i in range(0,20)] 1423 return self.list_completion(text, data, line) 1424 1425 if line.endswith('run=') and not text: 1426 return ['parton','pythia','pgs','delphes'] 1427 elif '--laststep=' in line.split()[-1] and line and line[-1] != ' ': 1428 return self.list_completion(text,['parton','pythia','pgs','delphes'],line) 1429 1430 opts = self._run_options + self._generate_options 1431 return self.list_completion(text, opts, line) 1432 1433 1434 1435 if line.endswith('nb_core=') and not text: 1436 import multiprocessing 1437 max = multiprocessing.cpu_count() 1438 return [str(i) for i in range(2,max+1)] 1439 opts = self._run_options + self._generate_options 1440 return self.list_completion(text, opts, line)
1441
1442 - def complete_plot(self, text, line, begidx, endidx):
1443 """ Complete the plot command """ 1444 1445 args = self.split_arg(line[0:begidx], error=False) 1446 if len(args) > 1: 1447 return self.list_completion(text, self._plot_mode) 1448 else: 1449 return self.list_completion(text, self._plot_mode + self.results.keys())
1450
1451 - def complete_syscalc(self, text, line, begidx, endidx):
1452 """ Complete the syscalc command """ 1453 1454 output = {} 1455 args = self.split_arg(line[0:begidx], error=False) 1456 1457 if len(args) <=1: 1458 output['RUN_NAME'] = self.list_completion(self.results.keys()) 1459 output['MODE'] = self.list_completion(text, self._syscalc_mode) 1460 output['options'] = ['-f'] 1461 if len(args) > 1 and (text.startswith('--t')): 1462 run = args[1] 1463 if run in self.results: 1464 tags = ['--tag=%s' % tag['tag'] for tag in self.results[run]] 1465 output['options'] += tags 1466 1467 return self.deal_multiple_categories(output)
1468
1469 - def complete_remove(self, text, line, begidx, endidx):
1470 """Complete the remove command """ 1471 1472 args = self.split_arg(line[0:begidx], error=False) 1473 if len(args) > 1 and (text.startswith('--t')): 1474 run = args[1] 1475 tags = ['--tag=%s' % tag['tag'] for tag in self.results[run]] 1476 return self.list_completion(text, tags) 1477 elif len(args) > 1 and '--' == args[-1]: 1478 run = args[1] 1479 tags = ['tag=%s' % tag['tag'] for tag in self.results[run]] 1480 return self.list_completion(text, tags) 1481 elif len(args) > 1 and '--tag=' == args[-1]: 1482 run = args[1] 1483 tags = [tag['tag'] for tag in self.results[run]] 1484 return self.list_completion(text, tags) 1485 elif len(args) > 1: 1486 return self.list_completion(text, self._clean_mode + ['-f','--tag=']) 1487 else: 1488 data = glob.glob(pjoin(self.me_dir, 'Events','*','*_banner.txt')) 1489 data = [n.rsplit('/',2)[1] for n in data] 1490 return self.list_completion(text, ['all'] + data)
1491 1492
1493 - def complete_pythia(self,text, line, begidx, endidx):
1494 "Complete the pythia command" 1495 args = self.split_arg(line[0:begidx], error=False) 1496 1497 if len(args) == 1: 1498 #return valid run_name 1499 data = glob.glob(pjoin(self.me_dir, 'Events', '*','unweighted_events.lhe.gz')) 1500 data = [n.rsplit('/',2)[1] for n in data] 1501 tmp1 = self.list_completion(text, data) 1502 if not self.run_name: 1503 return tmp1 1504 else: 1505 tmp2 = self.list_completion(text, self._run_options + ['-f', 1506 '--no_default', '--tag='], line) 1507 return tmp1 + tmp2 1508 elif line[-1] != '=': 1509 return self.list_completion(text, self._run_options + ['-f', 1510 '--no_default','--tag='], line)
1511
1512 - def complete_pgs(self,text, line, begidx, endidx):
1513 "Complete the pythia command" 1514 args = self.split_arg(line[0:begidx], error=False) 1515 if len(args) == 1: 1516 #return valid run_name 1517 data = glob.glob(pjoin(self.me_dir, 'Events', '*', '*_pythia_events.hep.gz')) 1518 data = [n.rsplit('/',2)[1] for n in data] 1519 tmp1 = self.list_completion(text, data) 1520 if not self.run_name: 1521 return tmp1 1522 else: 1523 tmp2 = self.list_completion(text, self._run_options + ['-f', 1524 '--tag=' ,'--no_default'], line) 1525 return tmp1 + tmp2 1526 else: 1527 return self.list_completion(text, self._run_options + ['-f', 1528 '--tag=','--no_default'], line)
1529 1530 complete_delphes = complete_pgs 1531
1532 1533 1534 1535 1536 #=============================================================================== 1537 # MadEventCmd 1538 #=============================================================================== 1539 -class MadEventCmd(CompleteForCmd, CmdExtended, HelpToCmd, common_run.CommonRunCmd):
1540 1541 """The command line processor of MadGraph""" 1542 1543 # Truth values 1544 true = ['T','.true.',True,'true'] 1545 # Options and formats available 1546 _run_options = ['--cluster','--multicore','--nb_core=','--nb_core=2', '-c', '-m'] 1547 _generate_options = ['-f', '--laststep=parton', '--laststep=pythia', '--laststep=pgs', '--laststep=delphes'] 1548 _calculate_decay_options = ['-f', '--accuracy=0.'] 1549 _set_options = ['stdout_level','fortran_compiler','timeout'] 1550 _plot_mode = ['all', 'parton','pythia','pgs','delphes','channel', 'banner'] 1551 _syscalc_mode = ['all', 'parton','pythia'] 1552 _clean_mode = _plot_mode 1553 _display_opts = ['run_name', 'options', 'variable', 'results'] 1554 _save_opts = ['options'] 1555 # survey options, dict from name to type, default value, and help text 1556 _survey_options = {'points':('int', 1000,'Number of points for first iteration'), 1557 'iterations':('int', 5, 'Number of iterations'), 1558 'accuracy':('float', 0.1, 'Required accuracy'), 1559 'gridpack':('str', '.false.', 'Gridpack generation')} 1560 # Variables to store object information 1561 true = ['T','.true.',True,'true', 1, '1'] 1562 web = False 1563 cluster_mode = 0 1564 queue = 'madgraph' 1565 nb_core = None 1566 1567 next_possibility = { 1568 'start': ['generate_events [OPTIONS]', 'multi_run [OPTIONS]', 1569 'calculate_decay_widths [OPTIONS]', 1570 'help generate_events'], 1571 'generate_events': ['generate_events [OPTIONS]', 'multi_run [OPTIONS]', 'pythia', 'pgs','delphes'], 1572 'calculate_decay_widths': ['calculate_decay_widths [OPTIONS]', 1573 'generate_events [OPTIONS]'], 1574 'multi_run': ['generate_events [OPTIONS]', 'multi_run [OPTIONS]'], 1575 'survey': ['refine'], 1576 'refine': ['combine_events'], 1577 'combine_events': ['store'], 1578 'store': ['pythia'], 1579 'pythia': ['pgs', 'delphes'], 1580 'pgs': ['generate_events [OPTIONS]', 'multi_run [OPTIONS]'], 1581 'delphes' : ['generate_events [OPTIONS]', 'multi_run [OPTIONS]'] 1582 } 1583 1584 ############################################################################
1585 - def __init__(self, me_dir = None, options={}, *completekey, **stdin):
1586 """ add information to the cmd """ 1587 1588 CmdExtended.__init__(self, me_dir, options, *completekey, **stdin) 1589 #common_run.CommonRunCmd.__init__(self, me_dir, options) 1590 1591 self.mode = 'madevent' 1592 self.nb_refine=0 1593 if self.web: 1594 os.system('touch %s' % pjoin(self.me_dir,'Online')) 1595 1596 1597 # load the current status of the directory 1598 if os.path.exists(pjoin(self.me_dir,'HTML','results.pkl')): 1599 try: 1600 self.results = save_load_object.load_from_file(pjoin(self.me_dir,'HTML','results.pkl')) 1601 except Exception: 1602 #the pickle fail -> need to recreate the library 1603 model = self.find_model_name() 1604 process = self.process # define in find_model_name 1605 self.results = gen_crossxhtml.AllResults(model, process, self.me_dir) 1606 self.results.resetall(self.me_dir) 1607 else: 1608 self.results.resetall(self.me_dir) 1609 else: 1610 model = self.find_model_name() 1611 process = self.process # define in find_model_name 1612 self.results = gen_crossxhtml.AllResults(model, process, self.me_dir) 1613 self.results.resetall(self.me_dir) 1614 self.results.def_web_mode(self.web) 1615 1616 self.prompt = "%s>"%os.path.basename(pjoin(self.me_dir)) 1617 self.configured = 0 # time for reading the card 1618 self._options = {} # for compatibility with extended_cmd
1619
1620 - def pass_in_web_mode(self):
1621 """configure web data""" 1622 self.web = True 1623 self.results.def_web_mode(True) 1624 self.force = True 1625 if os.environ['MADGRAPH_BASE']: 1626 self.options['mg5_path'] = pjoin(os.environ['MADGRAPH_BASE'],'MG5')
1627 1628 ############################################################################
1629 - def check_output_type(self, path):
1630 """ Check that the output path is a valid madevent directory """ 1631 1632 bin_path = os.path.join(path,'bin') 1633 if os.path.isfile(os.path.join(bin_path,'generate_events')): 1634 return True 1635 else: 1636 return False
1637 1638 ############################################################################
1639 - def set_configuration(self, amcatnlo=False, final=True, **opt):
1640 """assign all configuration variable from file 1641 loop over the different config file if config_file not define """ 1642 1643 super(MadEventCmd,self).set_configuration(amcatnlo=amcatnlo, 1644 final=final, **opt) 1645 if not final: 1646 return self.options # the return is usefull for unittest 1647 1648 # Treat each expected input 1649 # delphes/pythia/... path 1650 # ONLY the ONE LINKED TO Madevent ONLY!!! 1651 for key in (k for k in self.options if k.endswith('path')): 1652 path = self.options[key] 1653 if path is None: 1654 continue 1655 if not os.path.isdir(path): 1656 path = pjoin(self.me_dir, self.options[key]) 1657 if os.path.isdir(path): 1658 self.options[key] = None 1659 if key == "pythia-pgs_path": 1660 if not os.path.exists(pjoin(path, 'src','pythia')): 1661 logger.info("No valid pythia-pgs path found") 1662 continue 1663 elif key == "delphes_path": 1664 if not os.path.exists(pjoin(path, 'Delphes')) and not\ 1665 os.path.exists(pjoin(path, 'DelphesSTDHEP')): 1666 logger.info("No valid Delphes path found") 1667 continue 1668 elif key == "madanalysis_path": 1669 if not os.path.exists(pjoin(path, 'plot_events')): 1670 logger.info("No valid MadAnalysis path found") 1671 continue 1672 elif key == "td_path": 1673 if not os.path.exists(pjoin(path, 'td')): 1674 logger.info("No valid td path found") 1675 continue 1676 elif key == "syscalc_path": 1677 if not os.path.exists(pjoin(path, 'sys_calc')): 1678 logger.info("No valid SysCalc path found") 1679 continue 1680 # No else since the next line reinitialize the option to the 1681 #previous value anyway 1682 self.options[key] = os.path.realpath(path) 1683 continue 1684 else: 1685 self.options[key] = None 1686 1687 1688 return self.options
1689 1690 ############################################################################
1691 - def do_add_time_of_flight(self, line):
1692 1693 args = self.split_arg(line) 1694 #check the validity of the arguments and reformat args 1695 self.check_add_time_of_flight(args) 1696 1697 event_path, threshold = args 1698 #gunzip the file 1699 if event_path.endswith('.gz'): 1700 need_zip = True 1701 misc.gunzip(event_path) 1702 event_path = event_path[:-3] 1703 else: 1704 need_zip = False 1705 1706 import random 1707 try: 1708 import madgraph.various.lhe_parser as lhe_parser 1709 except: 1710 import internal.lhe_parser as lhe_parser 1711 1712 logger.info('Add time of flight information on file %s' % event_path) 1713 lhe = lhe_parser.EventFile(event_path) 1714 output = open('%s_2vertex.lhe' % event_path, 'w') 1715 #write the banner to the output file 1716 output.write(lhe.banner) 1717 1718 # get the associate param_card 1719 begin_param = lhe.banner.find('<slha>') 1720 end_param = lhe.banner.find('</slha>') 1721 param_card = lhe.banner[begin_param+6:end_param].split('\n') 1722 param_card = check_param_card.ParamCard(param_card) 1723 1724 cst = 6.58211915e-25 1725 # Loop over all events 1726 for event in lhe: 1727 for particle in event: 1728 id = particle.pid 1729 width = param_card['decay'].get((abs(id),)).value 1730 if width: 1731 vtim = random.expovariate(width/cst) 1732 if vtim > threshold: 1733 particle.vtim = vtim 1734 #write this modify event 1735 output.write(str(event)) 1736 output.write('</LesHouchesEvents>\n') 1737 output.close() 1738 1739 files.mv('%s_2vertex.lhe' % event_path, event_path) 1740 1741 if need_zip: 1742 misc.gzip(event_path)
1743 1744 ############################################################################
1745 - def do_banner_run(self, line):
1746 """Make a run from the banner file""" 1747 1748 args = self.split_arg(line) 1749 #check the validity of the arguments 1750 self.check_banner_run(args) 1751 1752 # Remove previous cards 1753 for name in ['delphes_trigger.dat', 'delphes_card.dat', 1754 'pgs_card.dat', 'pythia_card.dat', 'madspin_card.dat', 1755 'reweight_card.dat']: 1756 try: 1757 os.remove(pjoin(self.me_dir, 'Cards', name)) 1758 except Exception: 1759 pass 1760 1761 banner_mod.split_banner(args[0], self.me_dir, proc_card=False) 1762 1763 # Check if we want to modify the run 1764 if not self.force: 1765 ans = self.ask('Do you want to modify the Cards?', 'n', ['y','n']) 1766 if ans == 'n': 1767 self.force = True 1768 1769 # Call Generate events 1770 self.exec_cmd('generate_events %s %s' % (self.run_name, self.force and '-f' or ''))
1771 1772 1773 1774 ############################################################################
1775 - def do_display(self, line, output=sys.stdout):
1776 """Display current internal status""" 1777 1778 args = self.split_arg(line) 1779 #check the validity of the arguments 1780 self.check_display(args) 1781 1782 if args[0] == 'run_name': 1783 #return valid run_name 1784 data = glob.glob(pjoin(self.me_dir, 'Events', '*','*_banner.txt')) 1785 data = [n.rsplit('/',2)[1:] for n in data] 1786 1787 if data: 1788 out = {} 1789 for name, tag in data: 1790 tag = tag[len(name)+1:-11] 1791 if name in out: 1792 out[name].append(tag) 1793 else: 1794 out[name] = [tag] 1795 print 'the runs available are:' 1796 for run_name, tags in out.items(): 1797 print ' run: %s' % run_name 1798 print ' tags: ', 1799 print ', '.join(tags) 1800 else: 1801 print 'No run detected.' 1802 1803 elif args[0] == 'options': 1804 outstr = " Run Options \n" 1805 outstr += " ----------- \n" 1806 for key, default in self.options_madgraph.items(): 1807 value = self.options[key] 1808 if value == default: 1809 outstr += " %25s \t:\t%s\n" % (key,value) 1810 else: 1811 outstr += " %25s \t:\t%s (user set)\n" % (key,value) 1812 outstr += "\n" 1813 outstr += " MadEvent Options \n" 1814 outstr += " ---------------- \n" 1815 for key, default in self.options_madevent.items(): 1816 if key in self.options: 1817 value = self.options[key] 1818 else: 1819 default = '' 1820 if value == default: 1821 outstr += " %25s \t:\t%s\n" % (key,value) 1822 else: 1823 outstr += " %25s \t:\t%s (user set)\n" % (key,value) 1824 outstr += "\n" 1825 outstr += " Configuration Options \n" 1826 outstr += " --------------------- \n" 1827 for key, default in self.options_configuration.items(): 1828 value = self.options[key] 1829 if value == default: 1830 outstr += " %25s \t:\t%s\n" % (key,value) 1831 else: 1832 outstr += " %25s \t:\t%s (user set)\n" % (key,value) 1833 output.write(outstr) 1834 elif args[0] == 'results': 1835 self.do_print_results(' '.join(args[1:])) 1836 else: 1837 super(MadEventCmd, self).do_display(line, output)
1838
1839 - def do_save(self, line, check=True, to_keep={}):
1840 """Not in help: Save information to file""" 1841 1842 args = self.split_arg(line) 1843 # Check argument validity 1844 if check: 1845 self.check_save(args) 1846 1847 if args[0] == 'options': 1848 # First look at options which should be put in MG5DIR/input 1849 to_define = {} 1850 for key, default in self.options_configuration.items(): 1851 if self.options[key] != self.options_configuration[key]: 1852 to_define[key] = self.options[key] 1853 1854 if not '--auto' in args: 1855 for key, default in self.options_madevent.items(): 1856 if self.options[key] != self.options_madevent[key]: 1857 to_define[key] = self.options[key] 1858 1859 if '--all' in args: 1860 for key, default in self.options_madgraph.items(): 1861 if self.options[key] != self.options_madgraph[key]: 1862 to_define[key] = self.options[key] 1863 elif not '--auto' in args: 1864 for key, default in self.options_madgraph.items(): 1865 if self.options[key] != self.options_madgraph[key]: 1866 logger.info('The option %s is modified [%s] but will not be written in the configuration files.' \ 1867 % (key,self.options_madgraph[key]) ) 1868 logger.info('If you want to make this value the default for future session, you can run \'save options --all\'') 1869 if len(args) >1 and not args[1].startswith('--'): 1870 filepath = args[1] 1871 else: 1872 filepath = pjoin(self.me_dir, 'Cards', 'me5_configuration.txt') 1873 basefile = pjoin(self.me_dir, 'Cards', 'me5_configuration.txt') 1874 basedir = self.me_dir 1875 1876 if to_keep: 1877 to_define = to_keep 1878 self.write_configuration(filepath, basefile, basedir, to_define)
1879 1880 1881 1882 1883 1884 1885 ############################################################################ 1886 1887 ############################################################################
1888 - def do_generate_events(self, line):
1889 """Main Commands: launch the full chain """ 1890 1891 args = self.split_arg(line) 1892 # Check argument's validity 1893 mode = self.check_generate_events(args) 1894 self.ask_run_configuration(mode) 1895 if not args: 1896 # No run name assigned -> assigned one automaticaly 1897 self.set_run_name(self.find_available_run_name(self.me_dir), None, 'parton') 1898 else: 1899 self.set_run_name(args[0], None, 'parton', True) 1900 args.pop(0) 1901 1902 if self.run_card['gridpack'] in self.true: 1903 # Running gridpack warmup 1904 gridpack_opts=[('accuracy', 0.01), 1905 ('points', 2000), 1906 ('iterations',8), 1907 ('gridpack','.true.')] 1908 logger.info('Generating gridpack with run name %s' % self.run_name) 1909 self.exec_cmd('survey %s %s' % \ 1910 (self.run_name, 1911 " ".join(['--' + opt + '=' + str(val) for (opt,val) \ 1912 in gridpack_opts])), 1913 postcmd=False) 1914 self.exec_cmd('combine_events', postcmd=False) 1915 self.exec_cmd('store_events', postcmd=False) 1916 self.exec_cmd('decay_events -from_cards', postcmd=False) 1917 self.exec_cmd('create_gridpack', postcmd=False) 1918 else: 1919 # Regular run mode 1920 logger.info('Generating %s events with run name %s' % 1921 (self.run_card['nevents'], self.run_name)) 1922 1923 self.exec_cmd('survey %s %s' % (self.run_name,' '.join(args)), 1924 postcmd=False) 1925 if not float(self.results.current['cross']): 1926 # Zero cross-section. Try to guess why 1927 text = '''Survey return zero cross section. 1928 Typical reasons are the following: 1929 1) A massive s-channel particle has a width set to zero. 1930 2) The pdf are zero for at least one of the initial state particles 1931 or you are using maxjetflavor=4 for initial state b:s. 1932 3) The cuts are too strong. 1933 Please check/correct your param_card and/or your run_card.''' 1934 logger_stderr.critical(text) 1935 raise ZeroResult('See https://cp3.irmp.ucl.ac.be/projects/madgraph/wiki/FAQ-General-14') 1936 nb_event = self.run_card['nevents'] 1937 self.exec_cmd('refine %s' % nb_event, postcmd=False) 1938 self.exec_cmd('refine %s' % nb_event, postcmd=False) 1939 self.exec_cmd('combine_events', postcmd=False) 1940 self.print_results_in_shell(self.results.current) 1941 self.run_syscalc('parton') 1942 self.create_plot('parton') 1943 self.exec_cmd('store_events', postcmd=False) 1944 self.exec_cmd('reweight -from_cards', postcmd=False) 1945 self.exec_cmd('decay_events -from_cards', postcmd=False) 1946 self.exec_cmd('pythia --no_default', postcmd=False, printcmd=False) 1947 # pythia launches pgs/delphes if needed 1948 self.store_result()
1949 1950
1951 - def do_launch(self, line, *args, **opt):
1952 """Main Commands: exec generate_events for 2>N and calculate_width for 1>N""" 1953 if self.ninitial == 1: 1954 self.do_calculate_decay_widths(line, *args, **opt) 1955 else: 1956 self.do_generate_events(line, *args, **opt)
1957
1958 - def print_results_in_shell(self, data):
1959 """Have a nice results prints in the shell, 1960 data should be of type: gen_crossxhtml.OneTagResults""" 1961 if not data: 1962 return 1963 logger.info(" === Results Summary for run: %s tag: %s ===\n" % (data['run_name'],data['tag'])) 1964 if self.ninitial == 1: 1965 logger.info(" Width : %.4g +- %.4g GeV" % (data['cross'], data['error'])) 1966 else: 1967 logger.info(" Cross-section : %.4g +- %.4g pb" % (data['cross'], data['error'])) 1968 logger.info(" Nb of events : %s" % data['nb_event'] ) 1969 if data['cross_pythia'] and data['nb_event_pythia']: 1970 if self.ninitial == 1: 1971 logger.info(" Matched Width : %.4g +- %.4g GeV" % (data['cross_pythia'], data['error_pythia'])) 1972 else: 1973 logger.info(" Matched Cross-section : %.4g +- %.4g pb" % (data['cross_pythia'], data['error_pythia'])) 1974 logger.info(" Nb of events after Matching : %s" % data['nb_event_pythia']) 1975 if self.run_card['use_syst'] in self.true: 1976 logger.info(" Be carefull that matched information are here NOT for the central value. Refer to SysCalc output for it") 1977 1978 logger.info(" " )
1979
1980 - def print_results_in_file(self, data, path, mode='w'):
1981 """Have a nice results prints in the shell, 1982 data should be of type: gen_crossxhtml.OneTagResults""" 1983 if not data: 1984 return 1985 1986 fsock = open(path, mode) 1987 1988 fsock.write(" === Results Summary for run: %s tag: %s process: %s ===\n" % \ 1989 (data['run_name'],data['tag'], os.path.basename(self.me_dir))) 1990 1991 if self.ninitial == 1: 1992 fsock.write(" Width : %.4g +- %.4g GeV\n" % (data['cross'], data['error'])) 1993 else: 1994 fsock.write(" Cross-section : %.4g +- %.4g pb\n" % (data['cross'], data['error'])) 1995 fsock.write(" Nb of events : %s\n" % data['nb_event'] ) 1996 if data['cross_pythia'] and data['nb_event_pythia']: 1997 if self.ninitial == 1: 1998 fsock.write(" Matched Width : %.4g +- %.4g GeV\n" % (data['cross_pythia'], data['error_pythia'])) 1999 else: 2000 fsock.write(" Matched Cross-section : %.4g +- %.4g pb\n" % (data['cross_pythia'], data['error_pythia'])) 2001 fsock.write(" Nb of events after Matching : %s\n" % data['nb_event_pythia']) 2002 fsock.write(" \n" )
2003 2004 ############################################################################
2005 - def do_calculate_decay_widths(self, line):
2006 """Main Commands: launch decay width calculation and automatic inclusion of 2007 calculated widths and BRs in the param_card.""" 2008 2009 args = self.split_arg(line) 2010 # Check argument's validity 2011 accuracy = self.check_calculate_decay_widths(args) 2012 self.ask_run_configuration('parton') 2013 if not args: 2014 # No run name assigned -> assigned one automaticaly 2015 self.set_run_name(self.find_available_run_name(self.me_dir)) 2016 else: 2017 self.set_run_name(args[0], reload_card=True) 2018 args.pop(0) 2019 2020 self.configure_directory() 2021 2022 # Running gridpack warmup 2023 opts=[('accuracy', accuracy), # default 0.01 2024 ('points', 1000), 2025 ('iterations',9)] 2026 2027 logger.info('Calculating decay widths with run name %s' % self.run_name) 2028 2029 self.exec_cmd('survey %s %s' % \ 2030 (self.run_name, 2031 " ".join(['--' + opt + '=' + str(val) for (opt,val) \ 2032 in opts])), 2033 postcmd=False) 2034 self.exec_cmd('combine_events', postcmd=False) 2035 self.exec_cmd('store_events', postcmd=False) 2036 2037 self.collect_decay_widths() 2038 self.update_status('calculate_decay_widths done', 2039 level='parton', makehtml=False)
2040 2041 2042 ############################################################################
2043 - def collect_decay_widths(self):
2044 """ Collect the decay widths and calculate BRs for all particles, and put 2045 in param_card form. 2046 """ 2047 2048 particle_dict = {} # store the results 2049 run_name = self.run_name 2050 2051 # Looping over the Subprocesses 2052 for P_path in SubProcesses.get_subP(self.me_dir): 2053 ids = SubProcesses.get_subP_ids(P_path) 2054 # due to grouping we need to compute the ratio factor for the 2055 # ungroup resutls (that we need here). Note that initial particles 2056 # grouping are not at the same stage as final particle grouping 2057 nb_output = len(ids) / (len(set([p[0] for p in ids]))) 2058 results = open(pjoin(P_path, run_name + '_results.dat')).read().split('\n')[0] 2059 result = float(results.strip().split(' ')[0]) 2060 for particles in ids: 2061 try: 2062 particle_dict[particles[0]].append([particles[1:], result/nb_output]) 2063 except KeyError: 2064 particle_dict[particles[0]] = [[particles[1:], result/nb_output]] 2065 2066 self.update_width_in_param_card(particle_dict, 2067 initial = pjoin(self.me_dir, 'Cards', 'param_card.dat'), 2068 output=pjoin(self.me_dir, 'Events', run_name, "param_card.dat"))
2069 2070 @staticmethod
2071 - def update_width_in_param_card(decay_info, initial=None, output=None):
2072 # Open the param_card.dat and insert the calculated decays and BRs 2073 2074 if not output: 2075 output = initial 2076 2077 param_card_file = open(initial) 2078 param_card = param_card_file.read().split('\n') 2079 param_card_file.close() 2080 2081 decay_lines = [] 2082 line_number = 0 2083 # Read and remove all decays from the param_card 2084 while line_number < len(param_card): 2085 line = param_card[line_number] 2086 if line.lower().startswith('decay'): 2087 # Read decay if particle in decay_info 2088 # DECAY 6 1.455100e+00 2089 line = param_card.pop(line_number) 2090 line = line.split() 2091 particle = 0 2092 if int(line[1]) not in decay_info: 2093 try: # If formatting is wrong, don't want this particle 2094 particle = int(line[1]) 2095 width = float(line[2]) 2096 except Exception: 2097 particle = 0 2098 # Read BRs for this decay 2099 line = param_card[line_number] 2100 while line.startswith('#') or line.startswith(' '): 2101 line = param_card.pop(line_number) 2102 if not particle or line.startswith('#'): 2103 line=param_card[line_number] 2104 continue 2105 # 6.668201e-01 3 5 2 -1 2106 line = line.split() 2107 try: # Remove BR if formatting is wrong 2108 partial_width = float(line[0])*width 2109 decay_products = [int(p) for p in line[2:2+int(line[1])]] 2110 except Exception: 2111 line=param_card[line_number] 2112 continue 2113 try: 2114 decay_info[particle].append([decay_products, partial_width]) 2115 except KeyError: 2116 decay_info[particle] = [[decay_products, partial_width]] 2117 if line_number == len(param_card): 2118 break 2119 line=param_card[line_number] 2120 if particle and particle not in decay_info: 2121 # No decays given, only total width 2122 decay_info[particle] = [[[], width]] 2123 else: # Not decay 2124 line_number += 1 2125 # Clean out possible remaining comments at the end of the card 2126 while not param_card[-1] or param_card[-1].startswith('#'): 2127 param_card.pop(-1) 2128 2129 # Append calculated and read decays to the param_card 2130 param_card.append("#\n#*************************") 2131 param_card.append("# Decay widths *") 2132 param_card.append("#*************************") 2133 for key in sorted(decay_info.keys()): 2134 width = sum([r for p,r in decay_info[key]]) 2135 param_card.append("#\n# PDG Width") 2136 param_card.append("DECAY %i %e" % (key, width.real)) 2137 if not width: 2138 continue 2139 if decay_info[key][0][0]: 2140 param_card.append("# BR NDA ID1 ID2 ...") 2141 brs = [[(val[1]/width).real, val[0]] for val in decay_info[key] if val[1]] 2142 for val in sorted(brs, reverse=True): 2143 param_card.append(" %e %i %s # %s" % 2144 (val[0].real, len(val[1]), 2145 " ".join([str(v) for v in val[1]]), 2146 val[0] * width 2147 )) 2148 decay_table = open(output, 'w') 2149 decay_table.write("\n".join(param_card) + "\n") 2150 decay_table.close() 2151 logger.info("Results written to %s" % output)
2152 2153 2154 ############################################################################
2155 - def do_multi_run(self, line):
2156 2157 args = self.split_arg(line) 2158 # Check argument's validity 2159 mode = self.check_multi_run(args) 2160 nb_run = args.pop(0) 2161 if nb_run == 1: 2162 logger.warn("'multi_run 1' command is not optimal. Think of using generate_events instead") 2163 self.ask_run_configuration(mode) 2164 main_name = self.run_name 2165 2166 2167 2168 2169 2170 crossoversig = 0 2171 inv_sq_err = 0 2172 nb_event = 0 2173 for i in range(nb_run): 2174 self.nb_refine = 0 2175 self.exec_cmd('generate_events %s_%s -f' % (main_name, i), postcmd=False) 2176 # Update collected value 2177 nb_event += int(self.results[self.run_name][-1]['nb_event']) 2178 self.results.add_detail('nb_event', nb_event , run=main_name) 2179 cross = self.results[self.run_name][-1]['cross'] 2180 error = self.results[self.run_name][-1]['error'] + 1e-99 2181 crossoversig+=cross/error**2 2182 inv_sq_err+=1.0/error**2 2183 self.results[main_name][-1]['cross'] = crossoversig/inv_sq_err 2184 self.results[main_name][-1]['error'] = math.sqrt(1.0/inv_sq_err) 2185 self.results.def_current(main_name) 2186 self.run_name = main_name 2187 self.update_status("Merging LHE files", level='parton') 2188 try: 2189 os.mkdir(pjoin(self.me_dir,'Events', self.run_name)) 2190 except Exception: 2191 pass 2192 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' 2193 % {'bin': self.dirbin, 'event': pjoin(self.me_dir,'Events'), 2194 'name': self.run_name}) 2195 2196 eradir = self.options['exrootanalysis_path'] 2197 if eradir and misc.is_executable(pjoin(eradir,'ExRootLHEFConverter')): 2198 self.update_status("Create Root file", level='parton') 2199 misc.gunzip('%s/%s/unweighted_events.lhe.gz' % 2200 (pjoin(self.me_dir,'Events'), self.run_name)) 2201 2202 self.create_root_file('%s/unweighted_events.lhe' % self.run_name, 2203 '%s/unweighted_events.root' % self.run_name) 2204 2205 path = pjoin(self.me_dir, "Events", self.run_name, "unweighted_events.lhe") 2206 self.create_plot('parton', path, 2207 pjoin(self.me_dir, 'HTML',self.run_name, 'plots_parton.html') 2208 ) 2209 2210 2211 if not os.path.exists('%s.gz' % path): 2212 misc.gzip(path) 2213 2214 self.update_status('', level='parton') 2215 self.print_results_in_shell(self.results.current)
2216 2217 2218 ############################################################################
2219 - def do_treatcards(self, line, mode=None, opt=None):
2220 """Advanced commands: create .inc files from param_card.dat/run_card.dat""" 2221 2222 2223 if not mode and not opt: 2224 args = self.split_arg(line) 2225 mode, opt = self.check_treatcards(args) 2226 #check if no 'Auto' are present in the file 2227 self.check_param_card(pjoin(self.me_dir, 'Cards','param_card.dat')) 2228 2229 2230 if mode in ['param', 'all']: 2231 model = self.find_model_name() 2232 tmp_model = os.path.basename(model) 2233 if tmp_model == 'mssm' or tmp_model.startswith('mssm-'): 2234 if not '--param_card=' in line: 2235 param_card = pjoin(self.me_dir, 'Cards','param_card.dat') 2236 mg5_param = pjoin(self.me_dir, 'Source', 'MODEL', 'MG5_param.dat') 2237 check_param_card.convert_to_mg5card(param_card, mg5_param) 2238 check_param_card.check_valid_param_card(mg5_param) 2239 opt['param_card'] = pjoin(self.me_dir, 'Source', 'MODEL', 'MG5_param.dat') 2240 else: 2241 check_param_card.check_valid_param_card(opt['param_card']) 2242 2243 logger.debug('write compile file for card: %s' % opt['param_card']) 2244 param_card = check_param_card.ParamCard(opt['param_card']) 2245 outfile = pjoin(opt['output_dir'], 'param_card.inc') 2246 ident_card = pjoin(self.me_dir,'Cards','ident_card.dat') 2247 if os.path.isfile(pjoin(self.me_dir,'bin','internal','ufomodel','restrict_default.dat')): 2248 default = pjoin(self.me_dir,'bin','internal','ufomodel','restrict_default.dat') 2249 elif os.path.isfile(pjoin(self.me_dir,'bin','internal','ufomodel','param_card.dat')): 2250 default = pjoin(self.me_dir,'bin','internal','ufomodel','param_card.dat') 2251 elif not os.path.exists(pjoin(self.me_dir,'bin','internal','ufomodel')): 2252 fsock = open(pjoin(self.me_dir,'Source','param_card.inc'),'w') 2253 fsock.write(' ') 2254 fsock.close() 2255 if mode == 'all': 2256 self.do_treatcards('', 'run', opt) 2257 return 2258 else: 2259 devnull = open(os.devnull,'w') 2260 subprocess.call([sys.executable, 'write_param_card.py'], 2261 cwd=pjoin(self.me_dir,'bin','internal','ufomodel'), 2262 stdout=devnull) 2263 devnull.close() 2264 default = pjoin(self.me_dir,'bin','internal','ufomodel','param_card.dat') 2265 param_card.write_inc_file(outfile, ident_card, default) 2266 2267 2268 if mode in ['run', 'all']: 2269 if not hasattr(self, 'run_card'): 2270 run_card = banner_mod.RunCard(opt['run_card']) 2271 else: 2272 run_card = self.run_card 2273 if self.ninitial == 1: 2274 run_card['lpp1'] = 0 2275 run_card['lpp2'] = 0 2276 run_card['ebeam1'] = 0 2277 run_card['ebeam2'] = 0 2278 2279 run_card.write_include_file(pjoin(opt['output_dir'],'run_card.inc'))
2280 2281 ############################################################################
2282 - def do_survey(self, line):
2283 """Advanced commands: launch survey for the current process """ 2284 2285 2286 args = self.split_arg(line) 2287 # Check argument's validity 2288 self.check_survey(args) 2289 # initialize / remove lhapdf mode 2290 2291 if os.path.exists(pjoin(self.me_dir,'error')): 2292 os.remove(pjoin(self.me_dir,'error')) 2293 2294 self.configure_directory() 2295 # Save original random number 2296 self.random_orig = self.random 2297 logger.info("Using random number seed offset = %s" % self.random) 2298 # Update random number 2299 self.update_random() 2300 self.save_random() 2301 self.update_status('Running Survey', level=None) 2302 if self.cluster_mode: 2303 logger.info('Creating Jobs') 2304 2305 logger.info('Working on SubProcesses') 2306 self.total_jobs = 0 2307 subproc = [l.strip() for l in open(pjoin(self.me_dir,'SubProcesses', 2308 'subproc.mg'))] 2309 #check difficult PS case 2310 if float(self.run_card['mmjj']) > 0.01 * (float(self.run_card['ebeam1'])+float(self.run_card['ebeam2'])): 2311 self.pass_in_difficult_integration_mode() 2312 2313 P_zero_result = [] # check the number of times where they are no phase-space 2314 2315 nb_tot_proc = len(subproc) 2316 for nb_proc,subdir in enumerate(subproc): 2317 self.update_status('Compiling for process %s/%s. <br> (previous processes already running)' % \ 2318 (nb_proc+1,nb_tot_proc), level=None) 2319 subdir = subdir.strip() 2320 Pdir = pjoin(self.me_dir, 'SubProcesses',subdir) 2321 logger.info(' %s ' % subdir) 2322 # clean previous run 2323 for match in glob.glob(pjoin(Pdir, '*ajob*')): 2324 if os.path.basename(match)[:4] in ['ajob', 'wait', 'run.', 'done']: 2325 os.remove(match) 2326 for match in glob.glob(pjoin(Pdir, 'G*')): 2327 if os.path.exists(pjoin(match,'results.dat')): 2328 os.remove(pjoin(match, 'results.dat')) 2329 2330 #compile gensym 2331 self.compile(['gensym'], cwd=Pdir) 2332 if not os.path.exists(pjoin(Pdir, 'gensym')): 2333 raise MadEventError, 'Error make gensym not successful' 2334 2335 # Launch gensym 2336 p = misc.Popen(['./gensym'], stdin=subprocess.PIPE, 2337 stdout=subprocess.PIPE, 2338 stderr=subprocess.STDOUT, cwd=Pdir) 2339 sym_input = "%(points)d %(iterations)d %(accuracy)f \n" % self.opts 2340 (stdout, stderr) = p.communicate(sym_input) 2341 if os.path.exists(pjoin(self.me_dir,'error')): 2342 files.mv(pjoin(self.me_dir,'error'), pjoin(Pdir,'ajob.no_ps.log')) 2343 P_zero_result.append(subdir) 2344 continue 2345 2346 if not os.path.exists(pjoin(Pdir, 'ajob1')) or p.returncode: 2347 logger.critical(stdout) 2348 raise MadEventError, 'Error gensym run not successful' 2349 2350 2351 self.compile(['madevent'], cwd=Pdir) 2352 2353 alljobs = glob.glob(pjoin(Pdir,'ajob*')) 2354 self.total_jobs += len(alljobs) 2355 for i, job in enumerate(alljobs): 2356 job = os.path.basename(job) 2357 self.launch_job('%s' % job, cwd=Pdir, remaining=(len(alljobs)-i-1), 2358 run_type='survey on %s (%s/%s)' % (subdir,nb_proc+1,len(subproc))) 2359 if os.path.exists(pjoin(self.me_dir,'error')): 2360 self.monitor(html=False) 2361 raise MadEventError, 'Error detected Stop running: %s' % \ 2362 open(pjoin(self.me_dir,'error')).read() 2363 2364 # Check if all or only some fails 2365 if P_zero_result: 2366 if len(P_zero_result) == len(subproc): 2367 raise ZeroResult, '%s' % \ 2368 open(pjoin(Pdir,'ajob.no_ps.log')).read() 2369 else: 2370 logger.warning(''' %s SubProcesses doesn\'t have available phase-space. 2371 Please check mass spectrum.''' % ','.join(P_zero_result)) 2372 2373 2374 self.monitor(run_type='All jobs submitted for survey', html=True) 2375 cross, error = sum_html.make_all_html_results(self) 2376 self.results.add_detail('cross', cross) 2377 self.results.add_detail('error', error) 2378 self.update_status('End survey', 'parton', makehtml=False)
2379 2380 ############################################################################
2381 - def pass_in_difficult_integration_mode(self):
2382 """be more secure for the integration to not miss it due to strong cut""" 2383 2384 # improve survey options if default 2385 if self.opts['points'] == self._survey_options['points'][1]: 2386 self.opts['points'] = 2 * self._survey_options['points'][1] 2387 if self.opts['iterations'] == self._survey_options['iterations'][1]: 2388 self.opts['iterations'] = 1 + self._survey_options['iterations'][1] 2389 if self.opts['accuracy'] == self._survey_options['accuracy'][1]: 2390 self.opts['accuracy'] = self._survey_options['accuracy'][1]/2 2391 2392 # Modify run_config.inc in order to improve the refine 2393 conf_path = pjoin(self.me_dir, 'Source','run_config.inc') 2394 files.cp(conf_path, conf_path + '.bk') 2395 2396 text = open(conf_path).read() 2397 text = re.sub('''\(min_events = \d+\)''', '''(min_events = 7500 )''', text) 2398 text = re.sub('''\(max_events = \d+\)''', '''(max_events = 20000 )''', text) 2399 fsock = open(conf_path, 'w') 2400 fsock.write(text) 2401 fsock.close() 2402 2403 # Compile 2404 for name in ['../bin/internal/gen_ximprove', 'all', 2405 '../bin/internal/combine_events']: 2406 self.compile(arg=[name], cwd=os.path.join(self.me_dir, 'Source'))
2407 2408 2409 2410 2411 2412 2413 2414 ############################################################################
2415 - def do_refine(self, line):
2416 """Advanced commands: launch survey for the current process """ 2417 devnull = open(os.devnull, 'w') 2418 self.nb_refine += 1 2419 args = self.split_arg(line) 2420 # Check argument's validity 2421 self.check_refine(args) 2422 2423 precision = args[0] 2424 if len(args) == 2: 2425 max_process = args[1] 2426 else: 2427 max_process = 5 2428 2429 # initialize / remove lhapdf mode 2430 self.configure_directory() 2431 2432 # Update random number 2433 self.update_random() 2434 self.save_random() 2435 2436 if self.cluster_mode: 2437 logger.info('Creating Jobs') 2438 self.update_status('Refine results to %s' % precision, level=None) 2439 2440 self.total_jobs = 0 2441 subproc = [l.strip() for l in open(pjoin(self.me_dir,'SubProcesses', 2442 'subproc.mg'))] 2443 for nb_proc,subdir in enumerate(subproc): 2444 subdir = subdir.strip() 2445 Pdir = pjoin(self.me_dir, 'SubProcesses',subdir) 2446 bindir = pjoin(os.path.relpath(self.dirbin, Pdir)) 2447 2448 logger.info(' %s ' % subdir) 2449 # clean previous run 2450 for match in glob.glob(pjoin(Pdir, '*ajob*')): 2451 if os.path.basename(match)[:4] in ['ajob', 'wait', 'run.', 'done']: 2452 os.remove(match) 2453 2454 proc = misc.Popen([pjoin(bindir, 'gen_ximprove')], 2455 stdout=devnull, 2456 stdin=subprocess.PIPE, 2457 cwd=Pdir) 2458 proc.communicate('%s %s T\n' % (precision, max_process)) 2459 2460 if os.path.exists(pjoin(Pdir, 'ajob1')): 2461 self.compile(['madevent'], cwd=Pdir) 2462 alljobs = glob.glob(pjoin(Pdir,'ajob*')) 2463 2464 #remove associated results.dat (ensure to not mix with all data) 2465 Gre = re.compile("\s*j=(G[\d\.\w]+)") 2466 for job in alljobs: 2467 Gdirs = Gre.findall(open(job).read()) 2468 for Gdir in Gdirs: 2469 if os.path.exists(pjoin(Pdir, Gdir, 'results.dat')): 2470 os.remove(pjoin(Pdir, Gdir,'results.dat')) 2471 2472 nb_tot = len(alljobs) 2473 self.total_jobs += nb_tot 2474 for i, job in enumerate(alljobs): 2475 job = os.path.basename(job) 2476 self.launch_job('%s' % job, cwd=Pdir, remaining=(nb_tot-i-1), 2477 run_type='Refine number %s on %s (%s/%s)' % 2478 (self.nb_refine, subdir, nb_proc+1, len(subproc))) 2479 self.monitor(run_type='All job submitted for refine number %s' % self.nb_refine, 2480 html=True) 2481 2482 self.update_status("Combining runs", level='parton') 2483 try: 2484 os.remove(pjoin(Pdir, 'combine_runs.log')) 2485 except Exception: 2486 pass 2487 2488 bindir = pjoin(os.path.relpath(self.dirbin, pjoin(self.me_dir,'SubProcesses'))) 2489 2490 combine_runs.CombineRuns(self.me_dir) 2491 2492 cross, error = sum_html.make_all_html_results(self) 2493 self.results.add_detail('cross', cross) 2494 self.results.add_detail('error', error) 2495 2496 self.update_status('finish refine', 'parton', makehtml=False) 2497 devnull.close()
2498 2499 ############################################################################
2500 - def do_combine_events(self, line):
2501 """Advanced commands: Launch combine events""" 2502 2503 args = self.split_arg(line) 2504 # Check argument's validity 2505 self.check_combine_events(args) 2506 2507 self.update_status('Combining Events', level='parton') 2508 try: 2509 os.remove(pjoin(self.me_dir,'SubProcesses', 'combine.log')) 2510 except Exception: 2511 pass 2512 2513 if self.options['run_mode'] ==1 and self.options['cluster_tmp_path']: 2514 tmpcluster = cluster.MultiCore(nb_core=1) 2515 tmpcluster.launch_and_wait('../bin/internal/run_combine', 2516 cwd=pjoin(self.me_dir,'SubProcesses'), 2517 stdout=pjoin(self.me_dir,'SubProcesses', 'combine.log'), 2518 required_output=[pjoin(self.me_dir,'SubProcesses', 'combine.log')]) 2519 else: 2520 self.cluster.launch_and_wait('../bin/internal/run_combine', 2521 cwd=pjoin(self.me_dir,'SubProcesses'), 2522 stdout=pjoin(self.me_dir,'SubProcesses', 'combine.log'), 2523 required_output=[pjoin(self.me_dir,'SubProcesses', 'combine.log')]) 2524 2525 output = misc.mult_try_open(pjoin(self.me_dir,'SubProcesses','combine.log')).read() 2526 # Store the number of unweighted events for the results object 2527 pat = re.compile(r'''\s*Unweighting\s*selected\s*(\d+)\s*events''') 2528 try: 2529 nb_event = pat.search(output).groups()[0] 2530 except AttributeError: 2531 time.sleep(10) 2532 output = misc.mult_try_open(pjoin(self.me_dir,'SubProcesses','combine.log')).read() 2533 try: 2534 nb_event = pat.search(output).groups()[0] 2535 except AttributeError: 2536 logger.warning('Fail to read the number of unweighted events in the combine.log file') 2537 nb_event = 0 2538 2539 self.results.add_detail('nb_event', nb_event) 2540 2541 2542 # Define The Banner 2543 tag = self.run_card['run_tag'] 2544 # Update the banner with the pythia card 2545 if not self.banner: 2546 self.banner = banner_mod.recover_banner(self.results, 'parton') 2547 self.banner.load_basic(self.me_dir) 2548 # Add cross-section/event information 2549 self.banner.add_generation_info(self.results.current['cross'], nb_event) 2550 if not hasattr(self, 'random_orig'): self.random_orig = 0 2551 self.banner.change_seed(self.random_orig) 2552 if not os.path.exists(pjoin(self.me_dir, 'Events', self.run_name)): 2553 os.mkdir(pjoin(self.me_dir, 'Events', self.run_name)) 2554 self.banner.write(pjoin(self.me_dir, 'Events', self.run_name, 2555 '%s_%s_banner.txt' % (self.run_name, tag))) 2556 2557 2558 self.banner.add_to_file(pjoin(self.me_dir,'Events', 'events.lhe')) 2559 self.banner.add_to_file(pjoin(self.me_dir,'Events', 'unweighted_events.lhe')) 2560 2561 2562 eradir = self.options['exrootanalysis_path'] 2563 madir = self.options['madanalysis_path'] 2564 td = self.options['td_path'] 2565 if eradir and misc.is_executable(pjoin(eradir,'ExRootLHEFConverter')) and\ 2566 os.path.exists(pjoin(self.me_dir, 'Events', 'unweighted_events.lhe')): 2567 if not os.path.exists(pjoin(self.me_dir, 'Events', self.run_name)): 2568 os.mkdir(pjoin(self.me_dir, 'Events', self.run_name)) 2569 self.create_root_file(output='%s/unweighted_events.root' % \ 2570 self.run_name)
2571 2572 2573 2574 2575 2576 ############################################################################
2577 - def do_store_events(self, line):
2578 """Advanced commands: Launch store events""" 2579 2580 args = self.split_arg(line) 2581 # Check argument's validity 2582 self.check_combine_events(args) 2583 self.update_status('Storing parton level results', level='parton') 2584 2585 2586 2587 run = self.run_name 2588 tag = self.run_card['run_tag'] 2589 devnull = open(os.devnull, 'w') 2590 2591 if not os.path.exists(pjoin(self.me_dir, 'Events', run)): 2592 os.mkdir(pjoin(self.me_dir, 'Events', run)) 2593 if not os.path.exists(pjoin(self.me_dir, 'HTML', run)): 2594 os.mkdir(pjoin(self.me_dir, 'HTML', run)) 2595 2596 # 1) Store overall process information 2597 input = pjoin(self.me_dir, 'SubProcesses', 'results.dat') 2598 output = pjoin(self.me_dir, 'SubProcesses', '%s_results.dat' % run) 2599 files.cp(input, output) 2600 2601 # 2) Treat the files present in the P directory 2602 # Ensure that the number of events is different of 0 2603 if self.results.current['nb_event'] == 0: 2604 logger.warning("No event detected. No cleaning performed! This should allow to run:\n" + 2605 " cd Subprocesses; ../bin/internal/combine_events\n"+ 2606 " to have your events if those one are missing.") 2607 else: 2608 for P_path in SubProcesses.get_subP(self.me_dir): 2609 G_dir = [G for G in os.listdir(P_path) if G.startswith('G') and 2610 os.path.isdir(pjoin(P_path,G))] 2611 for G in G_dir: 2612 G_path = pjoin(P_path,G) 2613 try: 2614 # Remove events file (if present) 2615 if os.path.exists(pjoin(G_path, 'events.lhe')): 2616 os.remove(pjoin(G_path, 'events.lhe')) 2617 except Exception: 2618 continue 2619 try: 2620 # Store results.dat 2621 if os.path.exists(pjoin(G_path, 'results.dat')): 2622 input = pjoin(G_path, 'results.dat') 2623 output = pjoin(G_path, '%s_results.dat' % run) 2624 files.cp(input, output) 2625 except Exception: 2626 continue 2627 # Store log 2628 try: 2629 if os.path.exists(pjoin(G_path, 'log.txt')): 2630 input = pjoin(G_path, 'log.txt') 2631 output = pjoin(G_path, '%s_log.txt' % run) 2632 files.mv(input, output) 2633 except Exception: 2634 continue 2635 try: 2636 # Grid 2637 for name in ['ftn26']: 2638 if os.path.exists(pjoin(G_path, name)): 2639 if os.path.exists(pjoin(G_path, '%s_%s.gz'%(run,name))): 2640 os.remove(pjoin(G_path, '%s_%s.gz'%(run,name))) 2641 input = pjoin(G_path, name) 2642 output = pjoin(G_path, '%s_%s' % (run,name)) 2643 files.mv(input, output) 2644 misc.gzip(pjoin(G_path, output), error=None) 2645 except Exception: 2646 continue 2647 # Delete ftn25 to ensure reproducible runs 2648 if os.path.exists(pjoin(G_path, 'ftn25')): 2649 os.remove(pjoin(G_path, 'ftn25')) 2650 2651 # 3) Update the index.html 2652 misc.call(['%s/gen_cardhtml-pl' % self.dirbin], 2653 cwd=pjoin(self.me_dir)) 2654 2655 # 4) Move the Files present in Events directory 2656 E_path = pjoin(self.me_dir, 'Events') 2657 O_path = pjoin(self.me_dir, 'Events', run) 2658 # The events file 2659 for name in ['events.lhe', 'unweighted_events.lhe']: 2660 if os.path.exists(pjoin(E_path, name)): 2661 if os.path.exists(pjoin(O_path, '%s.gz' % name)): 2662 os.remove(pjoin(O_path, '%s.gz' % name)) 2663 input = pjoin(E_path, name) 2664 output = pjoin(O_path, name) 2665 misc.gzip(input, stdout="%s.gz" % output, error=False) 2666 2667 self.update_status('End Parton', level='parton', makehtml=False) 2668 devnull.close()
2669 2670 ############################################################################
2671 - def do_reweight(self, line):
2672 """ Allow to reweight the events generated with a new choices of model 2673 parameter. 2674 """ 2675 2676 if '-from_cards' in line and not os.path.exists(pjoin(self.me_dir, 'Cards', 'reweight_card.dat')): 2677 return 2678 2679 # Check that MG5 directory is present . 2680 if MADEVENT and not self.options['mg5_path']: 2681 raise self.InvalidCmd, '''The module reweight requires that MG5 is installed on the system. 2682 You can install it and set its path in ./Cards/me5_configuration.txt''' 2683 elif MADEVENT: 2684 sys.path.append(self.options['mg5_path']) 2685 try: 2686 import madgraph.interface.reweight_interface as reweight_interface 2687 except ImportError: 2688 raise self.ConfigurationError, '''Can\'t load Reweight module. 2689 The variable mg5_path might not be correctly configured.''' 2690 2691 self.to_store.append('event') 2692 if not '-from_cards' in line: 2693 self.keep_cards(['reweight_card.dat']) 2694 self.ask_edit_cards(['reweight_card.dat'], 'fixed', plot=False) 2695 2696 # forbid this function to create an empty item in results. 2697 if self.results.current['cross'] == 0 and self.run_name: 2698 self.results.delete_run(self.run_name, self.run_tag) 2699 2700 # load the name of the event file 2701 args = self.split_arg(line) 2702 self.check_decay_events(args) 2703 # args now alway content the path to the valid files 2704 reweight_cmd = reweight_interface.ReweightInterface(args[0]) 2705 reweight_cmd. mother = self 2706 self.update_status('Running Reweight', level='madspin') 2707 2708 2709 path = pjoin(self.me_dir, 'Cards', 'reweight_card.dat') 2710 reweight_cmd.me_dir = self.me_dir 2711 reweight_cmd.import_command_file(path) 2712 2713 # re-define current run 2714 try: 2715 self.results.def_current(self.run_name, self.run_tag) 2716 except Exception: 2717 pass
2718 2719 ############################################################################
2720 - def do_create_gridpack(self, line):
2721 """Advanced commands: Create gridpack from present run""" 2722 2723 self.update_status('Creating gridpack', level='parton') 2724 args = self.split_arg(line) 2725 self.check_combine_events(args) 2726 if not self.run_tag: self.run_tag = 'tag_1' 2727 os.system("sed -i.bak \"s/ *.false.*=.*GridRun/ .true. = GridRun/g\" %s/Cards/grid_card.dat" \ 2728 % self.me_dir) 2729 misc.call(['./bin/internal/restore_data', self.run_name], 2730 cwd=self.me_dir) 2731 misc.call(['./bin/internal/store4grid', 2732 self.run_name, self.run_tag], 2733 cwd=self.me_dir) 2734 misc.call(['./bin/internal/clean'], cwd=self.me_dir) 2735 misc.call(['./bin/internal/make_gridpack'], cwd=self.me_dir) 2736 files.mv(pjoin(self.me_dir, 'gridpack.tar.gz'), 2737 pjoin(self.me_dir, '%s_gridpack.tar.gz' % self.run_name)) 2738 os.system("sed -i.bak \"s/\s*.true.*=.*GridRun/ .false. = GridRun/g\" %s/Cards/grid_card.dat" \ 2739 % self.me_dir) 2740 self.update_status('gridpack created', level='gridpack')
2741 2742 ############################################################################
2743 - def do_pythia(self, line):
2744 """launch pythia""" 2745 2746 # Check argument's validity 2747 args = self.split_arg(line) 2748 if '--no_default' in args: 2749 if not os.path.exists(pjoin(self.me_dir, 'Cards', 'pythia_card.dat')): 2750 return 2751 no_default = True 2752 args.remove('--no_default') 2753 else: 2754 no_default = False 2755 2756 if not self.run_name: 2757 self.check_pythia(args) 2758 self.configure_directory(html_opening =False) 2759 else: 2760 # initialize / remove lhapdf mode 2761 self.configure_directory(html_opening =False) 2762 self.check_pythia(args) 2763 2764 # the args are modify and the last arg is always the mode 2765 if not no_default: 2766 self.ask_pythia_run_configuration(args[-1]) 2767 2768 if self.options['automatic_html_opening']: 2769 misc.open_file(os.path.join(self.me_dir, 'crossx.html')) 2770 self.options['automatic_html_opening'] = False 2771 2772 # Update the banner with the pythia card 2773 if not self.banner: 2774 self.banner = banner_mod.recover_banner(self.results, 'pythia') 2775 2776 2777 2778 pythia_src = pjoin(self.options['pythia-pgs_path'],'src') 2779 2780 self.update_status('Running Pythia', 'pythia') 2781 try: 2782 os.remove(pjoin(self.me_dir,'Events','pythia.done')) 2783 except Exception: 2784 pass 2785 2786 ## LAUNCHING PYTHIA 2787 tag = self.run_tag 2788 pythia_log = pjoin(self.me_dir, 'Events', self.run_name , '%s_pythia.log' % tag) 2789 self.cluster.launch_and_wait('../bin/internal/run_pythia', 2790 argument= [pythia_src], stdout= pythia_log, 2791 stderr=subprocess.STDOUT, 2792 cwd=pjoin(self.me_dir,'Events')) 2793 2794 if not os.path.exists(pjoin(self.me_dir,'Events','pythia.done')): 2795 logger.warning('Fail to produce pythia output. More info in \n %s' % pythia_log) 2796 return 2797 else: 2798 os.remove(pjoin(self.me_dir,'Events','pythia.done')) 2799 2800 self.to_store.append('pythia') 2801 2802 # Find the matched cross-section 2803 if int(self.run_card['ickkw']): 2804 # read the line from the bottom of the file 2805 pythia_log = misc.BackRead(pjoin(self.me_dir,'Events', self.run_name, 2806 '%s_pythia.log' % tag)) 2807 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") 2808 for line in pythia_log: 2809 info = pythiare.search(line) 2810 if not info: 2811 continue 2812 try: 2813 # Pythia cross section in mb, we want pb 2814 sigma_m = float(info.group('xsec').replace('D','E')) *1e9 2815 Nacc = int(info.group('generated')) 2816 Ntry = int(info.group('tried')) 2817 except ValueError: 2818 # xsec is not float - this should not happen 2819 self.results.add_detail('cross_pythia', 0) 2820 self.results.add_detail('nb_event_pythia', 0) 2821 self.results.add_detail('error_pythia', 0) 2822 else: 2823 self.results.add_detail('cross_pythia', sigma_m) 2824 self.results.add_detail('nb_event_pythia', Nacc) 2825 #compute pythia error 2826 error = self.results[self.run_name].return_tag(self.run_tag)['error'] 2827 error_m = math.sqrt((error * Nacc/Ntry)**2 + sigma_m**2 *(1-Nacc/Ntry)/Nacc) 2828 # works both for fixed number of generated events and fixed accepted events 2829 self.results.add_detail('error_pythia', error_m) 2830 break 2831 2832 pythia_log.close() 2833 2834 pydir = pjoin(self.options['pythia-pgs_path'], 'src') 2835 eradir = self.options['exrootanalysis_path'] 2836 madir = self.options['madanalysis_path'] 2837 td = self.options['td_path'] 2838 2839 2840 #Update the banner 2841 self.banner.add(pjoin(self.me_dir, 'Cards','pythia_card.dat')) 2842 if int(self.run_card['ickkw']): 2843 # Add the matched cross-section 2844 if 'MGGenerationInfo' in self.banner: 2845 self.banner['MGGenerationInfo'] += '# Matched Integrated weight (pb) : %s\n' % self.results.current['cross_pythia'] 2846 else: 2847 self.banner['MGGenerationInfo'] = '# Matched Integrated weight (pb) : %s\n' % self.results.current['cross_pythia'] 2848 banner_path = pjoin(self.me_dir, 'Events', self.run_name, '%s_%s_banner.txt' % (self.run_name, tag)) 2849 self.banner.write(banner_path) 2850 2851 # Creating LHE file 2852 self.run_hep2lhe(banner_path) 2853 if int(self.run_card['ickkw']): 2854 misc.gzip(pjoin(self.me_dir,'Events','beforeveto.tree'), 2855 stdout=pjoin(self.me_dir,'Events',self.run_name, tag+'_pythia_beforeveto.tree.gz')) 2856 2857 if self.run_card['use_syst'] in self.true: 2858 # Calculate syscalc info based on syst.dat 2859 try: 2860 self.run_syscalc('Pythia') 2861 except SysCalcError, error: 2862 logger.error(str(error)) 2863 else: 2864 # Store syst.dat 2865 misc.gzip(pjoin(self.me_dir,'Events', 'syst.dat'), 2866 stdout=pjoin(self.me_dir,'Events',self.run_name, tag + '_pythia_syst.dat.gz')) 2867 2868 # Store syscalc.dat 2869 if os.path.exists(pjoin(self.me_dir, 'Events', 'syscalc.dat')): 2870 filename = pjoin(self.me_dir, 'Events' ,self.run_name, 2871 '%s_syscalc.dat' % self.run_tag) 2872 misc.gzip(pjoin(self.me_dir, 'Events','syscalc.dat'), 2873 stdout = "%s.gz" % filename) 2874 2875 # Plot for pythia 2876 self.create_plot('Pythia') 2877 2878 if os.path.exists(pjoin(self.me_dir,'Events','pythia_events.lhe')): 2879 misc.gzip(pjoin(self.me_dir,'Events','pythia_events.lhe'), 2880 stdout=pjoin(self.me_dir,'Events', self.run_name,'%s_pythia_events.lhe.gz' % tag)) 2881 2882 self.update_status('finish', level='pythia', makehtml=False) 2883 self.exec_cmd('pgs --no_default', postcmd=False, printcmd=False) 2884 if self.options['delphes_path']: 2885 self.exec_cmd('delphes --no_default', postcmd=False, printcmd=False) 2886 self.print_results_in_shell(self.results.current)
2887 2888 2889 ################################################################################
2890 - def do_remove(self, line):
2891 """Remove one/all run or only part of it""" 2892 2893 args = self.split_arg(line) 2894 run, tag, mode = self.check_remove(args) 2895 if 'banner' in mode: 2896 mode.append('all') 2897 2898 2899 if run == 'all': 2900 # Check first if they are not a run with a name run. 2901 if os.path.exists(pjoin(self.me_dir, 'Events', 'all')): 2902 logger.warning('A run with name all exists. So we will not supress all processes.') 2903 else: 2904 for match in glob.glob(pjoin(self.me_dir, 'Events','*','*_banner.txt')): 2905 run = match.rsplit(os.path.sep,2)[1] 2906 try: 2907 self.exec_cmd('remove %s %s' % (run, ' '.join(args[1:]) ) ) 2908 except self.InvalidCmd, error: 2909 logger.info(error) 2910 pass # run already clear 2911 return 2912 2913 # Check that run exists 2914 if not os.path.exists(pjoin(self.me_dir, 'Events', run)): 2915 raise self.InvalidCmd('No run \'%s\' detected' % run) 2916 2917 try: 2918 self.resuls.def_current(run) 2919 self.update_status(' Cleaning %s' % run, level=None) 2920 except Exception: 2921 misc.sprint('fail to update results or html status') 2922 pass # Just ensure that html never makes crash this function 2923 2924 2925 # Found the file to delete 2926 2927 to_delete = glob.glob(pjoin(self.me_dir, 'Events', run, '*')) 2928 to_delete += glob.glob(pjoin(self.me_dir, 'HTML', run, '*')) 2929 # forbid the banner to be removed 2930 to_delete = [os.path.basename(f) for f in to_delete if 'banner' not in f] 2931 if tag: 2932 to_delete = [f for f in to_delete if tag in f] 2933 if 'parton' in mode or 'all' in mode: 2934 try: 2935 if self.results[run][0]['tag'] != tag: 2936 raise Exception, 'dummy' 2937 except Exception: 2938 pass 2939 else: 2940 nb_rm = len(to_delete) 2941 if os.path.exists(pjoin(self.me_dir, 'Events', run, 'events.lhe.gz')): 2942 to_delete.append('events.lhe.gz') 2943 if os.path.exists(pjoin(self.me_dir, 'Events', run, 'unweighted_events.lhe.gz')): 2944 to_delete.append('unweighted_events.lhe.gz') 2945 if os.path.exists(pjoin(self.me_dir, 'HTML', run,'plots_parton.html')): 2946 to_delete.append(pjoin(self.me_dir, 'HTML', run,'plots_parton.html')) 2947 if nb_rm != len(to_delete): 2948 logger.warning('Be carefull that partonic information are on the point to be removed.') 2949 if 'all' in mode: 2950 pass # delete everything 2951 else: 2952 if 'pythia' not in mode: 2953 to_delete = [f for f in to_delete if 'pythia' not in f] 2954 if 'pgs' not in mode: 2955 to_delete = [f for f in to_delete if 'pgs' not in f] 2956 if 'delphes' not in mode: 2957 to_delete = [f for f in to_delete if 'delphes' not in f] 2958 if 'parton' not in mode: 2959 to_delete = [f for f in to_delete if 'delphes' in f 2960 or 'pgs' in f 2961 or 'pythia' in f] 2962 if not self.force and len(to_delete): 2963 question = 'Do you want to delete the following files?\n %s' % \ 2964 '\n '.join(to_delete) 2965 ans = self.ask(question, 'y', choices=['y','n']) 2966 else: 2967 ans = 'y' 2968 2969 if ans == 'y': 2970 for file2rm in to_delete: 2971 if os.path.exists(pjoin(self.me_dir, 'Events', run, file2rm)): 2972 try: 2973 os.remove(pjoin(self.me_dir, 'Events', run, file2rm)) 2974 except Exception: 2975 shutil.rmtree(pjoin(self.me_dir, 'Events', run, file2rm)) 2976 else: 2977 try: 2978 os.remove(pjoin(self.me_dir, 'HTML', run, file2rm)) 2979 except Exception: 2980 shutil.rmtree(pjoin(self.me_dir, 'HTML', run, file2rm)) 2981 2982 2983 2984 # Remove file in SubProcess directory 2985 if 'all' in mode or 'channel' in mode: 2986 try: 2987 if tag and self.results[run][0]['tag'] != tag: 2988 raise Exception, 'dummy' 2989 except Exception: 2990 pass 2991 else: 2992 to_delete = glob.glob(pjoin(self.me_dir, 'SubProcesses', '%s*' % run)) 2993 to_delete += glob.glob(pjoin(self.me_dir, 'SubProcesses', '*','%s*' % run)) 2994 to_delete += glob.glob(pjoin(self.me_dir, 'SubProcesses', '*','*','%s*' % run)) 2995 2996 if self.force or len(to_delete) == 0: 2997 ans = 'y' 2998 else: 2999 question = 'Do you want to delete the following files?\n %s' % \ 3000 '\n '.join(to_delete) 3001 ans = self.ask(question, 'y', choices=['y','n']) 3002 3003 if ans == 'y': 3004 for file2rm in to_delete: 3005 os.remove(file2rm) 3006 3007 if 'banner' in mode: 3008 to_delete = glob.glob(pjoin(self.me_dir, 'Events', run, '*')) 3009 if tag: 3010 # remove banner 3011 try: 3012 os.remove(pjoin(self.me_dir, 'Events',run,'%s_%s_banner.txt' % (run,tag))) 3013 except Exception: 3014 logger.warning('fail to remove the banner') 3015 # remove the run from the html output 3016 if run in self.results: 3017 self.results.delete_run(run, tag) 3018 return 3019 elif any(['banner' not in os.path.basename(p) for p in to_delete]): 3020 if to_delete: 3021 raise MadGraph5Error, '''Some output still exists for this run. 3022 Please remove those output first. Do for example: 3023 remove %s all banner 3024 ''' % run 3025 else: 3026 shutil.rmtree(pjoin(self.me_dir, 'Events',run)) 3027 if run in self.results: 3028 self.results.delete_run(run) 3029 return 3030 else: 3031 logger.info('''The banner is not removed. In order to remove it run: 3032 remove %s all banner %s''' % (run, tag and '--tag=%s ' % tag or '')) 3033 3034 # update database. 3035 self.results.clean(mode, run, tag) 3036 self.update_status('', level='all')
3037 3038 3039 3040 ############################################################################
3041 - def do_plot(self, line):
3042 """Create the plot for a given run""" 3043 3044 # Since in principle, all plot are already done automaticaly 3045 self.store_result() 3046 args = self.split_arg(line) 3047 # Check argument's validity 3048 self.check_plot(args) 3049 logger.info('plot for run %s' % self.run_name) 3050 if not self.force: 3051 self.ask_edit_cards([], args, plot=True) 3052 3053 if any([arg in ['all','parton'] for arg in args]): 3054 filename = pjoin(self.me_dir, 'Events', self.run_name, 'unweighted_events.lhe') 3055 if os.path.exists(filename+'.gz'): 3056 misc.gunzip('%s.gz' % filename) 3057 if os.path.exists(filename): 3058 shutil.move(filename, pjoin(self.me_dir, 'Events', 'unweighted_events.lhe')) 3059 self.create_plot('parton') 3060 misc.gzip(pjoin(self.me_dir, 'Events', 'unweighted_events.lhe'), 3061 stdout= "%s.gz" % filename) 3062 else: 3063 logger.info('No valid files for partonic plot') 3064 3065 if any([arg in ['all','pythia'] for arg in args]): 3066 filename = pjoin(self.me_dir, 'Events' ,self.run_name, 3067 '%s_pythia_events.lhe' % self.run_tag) 3068 if os.path.exists(filename+'.gz'): 3069 misc.gunzip("%s.gz" % filename) 3070 if os.path.exists(filename): 3071 shutil.move(filename, pjoin(self.me_dir, 'Events','pythia_events.lhe')) 3072 self.create_plot('Pythia') 3073 misc.gzip(pjoin(self.me_dir, 'Events','pythia_events.lhe'), 3074 stdout= "%s.gz" % filename) 3075 else: 3076 logger.info('No valid files for pythia plot') 3077 3078 3079 if any([arg in ['all','pgs'] for arg in args]): 3080 filename = pjoin(self.me_dir, 'Events', self.run_name, 3081 '%s_pgs_events.lhco' % self.run_tag) 3082 if os.path.exists(filename+'.gz'): 3083 misc.gunzip("%s.gz" % filename) 3084 if os.path.exists(filename): 3085 self.create_plot('PGS') 3086 misc.gzip(filename) 3087 else: 3088 logger.info('No valid files for pgs plot') 3089 3090 if any([arg in ['all','delphes'] for arg in args]): 3091 filename = pjoin(self.me_dir, 'Events', self.run_name, 3092 '%s_delphes_events.lhco' % self.run_tag) 3093 if os.path.exists(filename+'.gz'): 3094 misc.gunzip("%s.gz" % filename) 3095 if os.path.exists(filename): 3096 self.create_plot('Delphes') 3097 misc.gzip(filename) 3098 else: 3099 logger.info('No valid files for delphes plot')
3100 3101 ############################################################################
3102 - def do_syscalc(self, line):
3103 """Evaluate systematics variation weights for a given run""" 3104 3105 # Since in principle, all systematics run are already done automaticaly 3106 self.store_result() 3107 args = self.split_arg(line) 3108 # Check argument's validity 3109 self.check_syscalc(args) 3110 if self.ninitial == 1: 3111 logger.error('SysCalc can\'t be run for decay processes') 3112 return 3113 3114 logger.info('Calculating systematics for run %s' % self.run_name) 3115 3116 self.ask_edit_cards(['run_card'], args) 3117 3118 if any([arg in ['all','parton'] for arg in args]): 3119 filename = pjoin(self.me_dir, 'Events', self.run_name, 'unweighted_events.lhe') 3120 if os.path.exists(filename+'.gz'): 3121 misc.gunzip("%s.gz" % filename) 3122 if os.path.exists(filename): 3123 shutil.move(filename, pjoin(self.me_dir, 'Events', 'unweighted_events.lhe')) 3124 self.run_syscalc('parton') 3125 misc.gzip(pjoin(self.me_dir, 'Events', 'unweighted_events.lhe'), 3126 stdout="%s.gz" % filename) 3127 else: 3128 logger.info('No valid files for parton level systematics run.') 3129 3130 if any([arg in ['all','pythia'] for arg in args]): 3131 filename = pjoin(self.me_dir, 'Events' ,self.run_name, 3132 '%s_pythia_syst.dat' % self.run_tag) 3133 if os.path.exists(filename+'.gz'): 3134 misc.gunzip("%s.gz" % filename) 3135 if os.path.exists(filename): 3136 shutil.move(filename, pjoin(self.me_dir, 'Events','syst.dat')) 3137 try: 3138 self.run_syscalc('Pythia') 3139 except SysCalcError, error: 3140 logger.warning(str(error)) 3141 return 3142 misc.gzip(pjoin(self.me_dir, 'Events','syst.dat'), "%s.gz" % filename) 3143 filename = pjoin(self.me_dir, 'Events' ,self.run_name, 3144 '%s_syscalc.dat' % self.run_tag) 3145 misc.gzip(pjoin(self.me_dir, 'Events','syscalc.dat'), 3146 stdout=filename) 3147 else: 3148 logger.info('No valid files for pythia level')
3149 3150
3151 - def store_result(self):
3152 """ tar the pythia results. This is done when we are quite sure that 3153 the pythia output will not be use anymore """ 3154 3155 if not self.run_name: 3156 return 3157 3158 self.results.save() 3159 3160 3161 if not self.to_store: 3162 return 3163 3164 tag = self.run_card['run_tag'] 3165 self.update_status('storring files of Previous run', level=None,\ 3166 error=True) 3167 if 'event' in self.to_store: 3168 if not os.path.exists(pjoin(self.me_dir, 'Events',self.run_name, 'unweighted_events.lhe.gz')): 3169 misc.gzip(pjoin(self.me_dir,'Events',self.run_name,"unweighted_events.lhe")) 3170 3171 if 'pythia' in self.to_store: 3172 self.update_status('Storing Pythia files of Previous run', level='pythia', error=True) 3173 3174 p = pjoin(self.me_dir,'Events') 3175 n = self.run_name 3176 t = tag 3177 misc.gzip(pjoin(p,'pythia_events.hep'), 3178 stdout=pjoin(p,'%s/%s_pythia_events.hep' % (n,t))) 3179 3180 self.to_store.remove('pythia') 3181 self.update_status('Done', level='pythia',makehtml=False,error=True) 3182 3183 self.to_store = []
3184
3185 - def launch_job(self,exe, cwd=None, stdout=None, argument = [], remaining=0, 3186 run_type='', mode=None, **opt):
3187 """ """ 3188 argument = [str(arg) for arg in argument] 3189 if mode is None: 3190 mode = self.cluster_mode 3191 3192 # ensure that exe is executable 3193 if os.path.exists(exe) and not os.access(exe, os.X_OK): 3194 os.system('chmod +x %s ' % exe) 3195 elif (cwd and os.path.exists(pjoin(cwd, exe))) and not \ 3196 os.access(pjoin(cwd, exe), os.X_OK): 3197 os.system('chmod +x %s ' % pjoin(cwd, exe)) 3198 3199 if mode == 0: 3200 self.update_status((remaining, 1, 3201 self.total_jobs - remaining -1, run_type), level=None, force=False) 3202 start = time.time() 3203 #os.system('cd %s; ./%s' % (cwd,exe)) 3204 status = misc.call(['./'+exe] + argument, cwd=cwd, 3205 stdout=stdout, **opt) 3206 logger.info('%s run in %f s' % (exe, time.time() -start)) 3207 if status: 3208 raise MadGraph5Error, '%s didn\'t stop properly. Stop all computation' % exe 3209 3210 3211 elif mode in [1,2]: 3212 # For condor cluster, create the input/output files 3213 if 'ajob' in exe: 3214 input_files = ['madevent','input_app.txt','symfact.dat','iproc.dat', 3215 pjoin(self.me_dir, 'SubProcesses','randinit')] 3216 output_files = [] 3217 required_output = [] 3218 3219 3220 #Find the correct PDF input file 3221 input_files.append(self.get_pdf_input_filename()) 3222 3223 #Find the correct ajob 3224 Gre = re.compile("\s*j=(G[\d\.\w]+)") 3225 Ire = re 3226 try : 3227 fsock = open(exe) 3228 except Exception: 3229 fsock = open(pjoin(cwd,exe)) 3230 text = fsock.read() 3231 output_files = Gre.findall(text) 3232 if not output_files: 3233 Ire = re.compile("for i in ([\d\.\s]*) ; do") 3234 data = Ire.findall(text) 3235 data = ' '.join(data).split() 3236 for nb in data: 3237 output_files.append('G%s' % nb) 3238 required_output.append('G%s/results.dat' % nb) 3239 else: 3240 for G in output_files: 3241 if os.path.isdir(pjoin(cwd,G)): 3242 input_files.append(G) 3243 required_output.append('%s/results.dat' % G) 3244 3245 #submitting 3246 self.cluster.submit2(exe, stdout=stdout, cwd=cwd, 3247 input_files=input_files, output_files=output_files, 3248 required_output=required_output) 3249 3250 else: 3251 self.cluster.submit(exe, stdout=stdout, cwd=cwd)
3252 3253 3254 ############################################################################
3255 - def find_madevent_mode(self):
3256 """Find if Madevent is in Group mode or not""" 3257 3258 # The strategy is too look in the files Source/run_configs.inc 3259 # if we found: ChanPerJob=3 then it's a group mode. 3260 file_path = pjoin(self.me_dir, 'Source', 'run_config.inc') 3261 text = open(file_path).read() 3262 if re.search(r'''s*parameter\s+\(ChanPerJob=2\)''', text, re.I+re.M): 3263 return 'group' 3264 else: 3265 return 'v4'
3266 3267 ############################################################################
3268 - def monitor(self, run_type='monitor', mode=None, html=False):
3269 """ monitor the progress of running job """ 3270 3271 starttime = time.time() 3272 if mode is None: 3273 mode = self.cluster_mode 3274 if mode > 0: 3275 if html: 3276 update_status = lambda idle, run, finish: \ 3277 self.update_status((idle, run, finish, run_type), level=None, 3278 force=False, starttime=starttime) 3279 else: 3280 update_status = lambda idle, run, finish: None 3281 try: 3282 self.cluster.wait(self.me_dir, update_status) 3283 except Exception, error: 3284 logger.info(error) 3285 if not self.force: 3286 ans = self.ask('Cluster Error detected. Do you want to clean the queue?', 3287 default = 'y', choices=['y','n']) 3288 else: 3289 ans = 'y' 3290 if ans == 'y': 3291 self.cluster.remove() 3292 raise 3293 except KeyboardInterrupt, error: 3294 self.cluster.remove() 3295 raise
3296 3297 3298 3299 ############################################################################
3300 - def configure_directory(self, html_opening=True):
3301 """ All action require before any type of run """ 3302 3303 3304 # Basic check 3305 assert os.path.exists(pjoin(self.me_dir,'SubProcesses')) 3306 3307 #see when the last file was modified 3308 time_mod = max([os.path.getctime(pjoin(self.me_dir,'Cards','run_card.dat')), 3309 os.path.getctime(pjoin(self.me_dir,'Cards','param_card.dat'))]) 3310 if self.configured > time_mod and hasattr(self, 'random'): 3311 return 3312 else: 3313 self.configured = time.time() 3314 self.update_status('compile directory', level=None, update_results=True) 3315 if self.options['automatic_html_opening'] and html_opening: 3316 misc.open_file(os.path.join(self.me_dir, 'crossx.html')) 3317 self.options['automatic_html_opening'] = False 3318 #open only once the web page 3319 # Change current working directory 3320 self.launching_dir = os.getcwd() 3321 3322 # Check if we need the MSSM special treatment 3323 model = self.find_model_name() 3324 if model == 'mssm' or model.startswith('mssm-'): 3325 param_card = pjoin(self.me_dir, 'Cards','param_card.dat') 3326 mg5_param = pjoin(self.me_dir, 'Source', 'MODEL', 'MG5_param.dat') 3327 check_param_card.convert_to_mg5card(param_card, mg5_param) 3328 check_param_card.check_valid_param_card(mg5_param) 3329 3330 # limit the number of event to 100k 3331 self.check_nb_events() 3332 3333 # this is in order to avoid conflicts between runs with and without 3334 # lhapdf 3335 misc.compile(['clean4pdf'], cwd = pjoin(self.me_dir, 'Source')) 3336 3337 # set environment variable for lhapdf. 3338 if self.run_card['pdlabel'] == "lhapdf": 3339 os.environ['lhapdf'] = 'True' 3340 self.link_lhapdf(pjoin(self.me_dir,'lib')) 3341 pdfsetsdir = self.get_lhapdf_pdfsetsdir() 3342 lhaid_list = [int(self.run_card['lhaid'])] 3343 self.copy_lhapdf_set(lhaid_list, pdfsetsdir) 3344 elif 'lhapdf' in os.environ.keys(): 3345 del os.environ['lhapdf'] 3346 if self.run_card['pdlabel'] != "lhapdf": 3347 self.pdffile = None 3348 3349 # set random number 3350 if self.run_card['iseed'] != '0': 3351 self.random = int(self.run_card['iseed']) 3352 self.run_card['iseed'] = '0' 3353 # Reset seed in run_card to 0, to ensure that following runs 3354 # will be statistically independent 3355 text = open(pjoin(self.me_dir, 'Cards','run_card.dat')).read() 3356 (t,n) = re.subn(r'\d+\s*= iseed','0 = iseed',text) 3357 open(pjoin(self.me_dir, 'Cards','run_card.dat'),'w').write(t) 3358 elif os.path.exists(pjoin(self.me_dir,'SubProcesses','randinit')): 3359 for line in open(pjoin(self.me_dir,'SubProcesses','randinit')): 3360 data = line.split('=') 3361 assert len(data) ==2 3362 self.random = int(data[1]) 3363 break 3364 else: 3365 self.random = random.randint(1, 30107) 3366 3367 if self.run_card['ickkw'] == '2': 3368 logger.info('Running with CKKW matching') 3369 self.treat_CKKW_matching() 3370 3371 # create param_card.inc and run_card.inc 3372 self.do_treatcards('') 3373 3374 # Compile 3375 for name in ['../bin/internal/gen_ximprove', 'all', 3376 '../bin/internal/combine_events']: 3377 self.compile(arg=[name], cwd=os.path.join(self.me_dir, 'Source'))
3378 3379 3380 ############################################################################ 3381 ## HELPING ROUTINE 3382 ############################################################################ 3383 @staticmethod
3384 - def check_dir(path, default=''):
3385 """check if the directory exists. if so return the path otherwise the 3386 default""" 3387 3388 if os.path.isdir(path): 3389 return path 3390 else: 3391 return default
3392 3393 ############################################################################
3394 - def set_run_name(self, name, tag=None, level='parton', reload_card=False, 3395 allow_new_tag=True):
3396 """define the run name, the run_tag, the banner and the results.""" 3397 3398 # when are we force to change the tag new_run:previous run requiring changes 3399 upgrade_tag = {'parton': ['parton','pythia','pgs','delphes'], 3400 'pythia': ['pythia','pgs','delphes'], 3401 'pgs': ['pgs'], 3402 'delphes':['delphes'], 3403 'plot':[], 3404 'syscalc':[]} 3405 3406 3407 3408 if name == self.run_name: 3409 if reload_card: 3410 run_card = pjoin(self.me_dir, 'Cards','run_card.dat') 3411 self.run_card = banner_mod.RunCard(run_card) 3412 3413 #check if we need to change the tag 3414 if tag: 3415 self.run_card['run_tag'] = tag 3416 self.run_tag = tag 3417 self.results.add_run(self.run_name, self.run_card) 3418 else: 3419 for tag in upgrade_tag[level]: 3420 if getattr(self.results[self.run_name][-1], tag): 3421 tag = self.get_available_tag() 3422 self.run_card['run_tag'] = tag 3423 self.run_tag = tag 3424 self.results.add_run(self.run_name, self.run_card) 3425 break 3426 return # Nothing to do anymore 3427 3428 # save/clean previous run 3429 if self.run_name: 3430 self.store_result() 3431 # store new name 3432 self.run_name = name 3433 3434 new_tag = False 3435 # First call for this run -> set the banner 3436 self.banner = banner_mod.recover_banner(self.results, level, name) 3437 if 'mgruncard' in self.banner: 3438 self.run_card = self.banner.charge_card('run_card') 3439 else: 3440 # Read run_card 3441 run_card = pjoin(self.me_dir, 'Cards','run_card.dat') 3442 self.run_card = banner_mod.RunCard(run_card) 3443 3444 if tag: 3445 self.run_card['run_tag'] = tag 3446 new_tag = True 3447 elif not self.run_name in self.results and level =='parton': 3448 pass # No results yet, so current tag is fine 3449 elif not self.run_name in self.results: 3450 #This is only for case when you want to trick the interface 3451 logger.warning('Trying to run data on unknown run.') 3452 self.results.add_run(name, self.run_card) 3453 self.results.update('add run %s' % name, 'all', makehtml=False) 3454 else: 3455 for tag in upgrade_tag[level]: 3456 3457 if getattr(self.results[self.run_name][-1], tag): 3458 # LEVEL is already define in the last tag -> need to switch tag 3459 tag = self.get_available_tag() 3460 self.run_card['run_tag'] = tag 3461 new_tag = True 3462 break 3463 if not new_tag: 3464 # We can add the results to the current run 3465 tag = self.results[self.run_name][-1]['tag'] 3466 self.run_card['run_tag'] = tag # ensure that run_tag is correct 3467 3468 if allow_new_tag and (name in self.results and not new_tag): 3469 self.results.def_current(self.run_name) 3470 else: 3471 self.results.add_run(self.run_name, self.run_card) 3472 3473 self.run_tag = self.run_card['run_tag'] 3474 3475 # Return the tag of the previous run having the required data for this 3476 # tag/run to working wel. 3477 if level == 'parton': 3478 return 3479 elif level == 'pythia': 3480 return self.results[self.run_name][0]['tag'] 3481 else: 3482 for i in range(-1,-len(self.results[self.run_name])-1,-1): 3483 tagRun = self.results[self.run_name][i] 3484 if tagRun.pythia: 3485 return tagRun['tag']
3486 3487 3488 3489 3490 3491 3492 3493 3494 ############################################################################
3495 - def find_model_name(self):
3496 """ return the model name """ 3497 if hasattr(self, 'model_name'): 3498 return self.model_name 3499 3500 model = 'sm' 3501 proc = [] 3502 for line in open(os.path.join(self.me_dir,'Cards','proc_card_mg5.dat')): 3503 line = line.split('#')[0] 3504 #line = line.split('=')[0] 3505 if line.startswith('import') and 'model' in line: 3506 model = line.split()[2] 3507 proc = [] 3508 elif line.startswith('generate'): 3509 proc.append(line.split(None,1)[1]) 3510 elif line.startswith('add process'): 3511 proc.append(line.split(None,2)[2]) 3512 3513 self.model = model 3514 self.process = proc 3515 return model
3516 3517 3518 ############################################################################
3519 - def check_nb_events(self):
3520 """Find the number of event in the run_card, and check that this is not 3521 too large""" 3522 3523 3524 nb_event = int(self.run_card['nevents']) 3525 if nb_event > 1000000: 3526 logger.warning("Attempting to generate more than 1M events") 3527 logger.warning("Limiting number to 1M. Use multi_run for larger statistics.") 3528 path = pjoin(self.me_dir, 'Cards', 'run_card.dat') 3529 os.system(r"""perl -p -i.bak -e "s/\d+\s*=\s*nevents/1000000 = nevents/" %s""" \ 3530 % path) 3531 self.run_card['nevents'] = 1000000 3532 3533 return
3534 3535 3536 ############################################################################
3537 - def update_random(self):
3538 """ change random number""" 3539 3540 self.random += 3 3541 if self.random > 30081*30081: # can't use too big random number 3542 raise MadGraph5Error,\ 3543 'Random seed too large ' + str(self.random) + ' > 30081*30081'
3544 3545 ############################################################################
3546 - def save_random(self):
3547 """save random number in appropirate file""" 3548 3549 fsock = open(pjoin(self.me_dir, 'SubProcesses','randinit'),'w') 3550 fsock.writelines('r=%s\n' % self.random)
3551
3552 - def do_quit(self, *args, **opts):
3553 3554 common_run.CommonRunCmd.do_quit(self, *args, **opts) 3555 return CmdExtended.do_quit(self, *args, **opts)
3556 3557 ############################################################################
3558 - def treat_ckkw_matching(self):
3559 """check for ckkw""" 3560 3561 lpp1 = self.run_card['lpp1'] 3562 lpp2 = self.run_card['lpp2'] 3563 e1 = self.run_card['ebeam1'] 3564 e2 = self.run_card['ebeam2'] 3565 pd = self.run_card['pdlabel'] 3566 lha = self.run_card['lhaid'] 3567 xq = self.run_card['xqcut'] 3568 translation = {'e1': e1, 'e2':e2, 'pd':pd, 3569 'lha':lha, 'xq':xq} 3570 3571 if lpp1 or lpp2: 3572 # Remove ':s from pd 3573 if pd.startswith("'"): 3574 pd = pd[1:] 3575 if pd.endswith("'"): 3576 pd = pd[:-1] 3577 3578 if xq >2 or xq ==2: 3579 xq = 2 3580 3581 # find data file 3582 if pd == "lhapdf": 3583 issudfile = 'lib/issudgrid-%(e1)s-%(e2)s-%(pd)s-%(lha)s-%(xq)s.dat.gz' 3584 else: 3585 issudfile = 'lib/issudgrid-%(e1)s-%(e2)s-%(pd)s-%(xq)s.dat.gz' 3586 if self.web: 3587 issudfile = pjoin(self.webbin, issudfile % translation) 3588 else: 3589 issudfile = pjoin(self.me_dir, issudfile % translation) 3590 3591 logger.info('Sudakov grid file: %s' % issudfile) 3592 3593 # check that filepath exists 3594 if os.path.exists(issudfile): 3595 path = pjoin(self.me_dir, 'lib', 'issudgrid.dat') 3596 misc.gunzip(issudfile, keep=True, stdout=path) 3597 else: 3598 msg = 'No sudakov grid file for parameter choice. Start to generate it. This might take a while' 3599 logger.info(msg) 3600 self.update_status('GENERATE SUDAKOF GRID', level='parton') 3601 3602 for i in range(-2,6): 3603 self.cluster.submit('%s/gensudgrid ' % self.dirbin, 3604 arguments = [i], 3605 cwd=self.me_dir, 3606 stdout=open(pjoin(self.me_dir, 'gensudgrid%s.log' % i,'w'))) 3607 self.monitor() 3608 for i in range(-2,6): 3609 path = pjoin(self.me_dir, 'lib', 'issudgrid.dat') 3610 os.system('cat %s/gensudgrid%s.log >> %s' % (self.me_dir, path)) 3611 misc.gzip(path, stdout=issudfile)
3612 3613 ############################################################################
3614 - def create_root_file(self, input='unweighted_events.lhe', 3615 output='unweighted_events.root' ):
3616 """create the LHE root file """ 3617 self.update_status('Creating root files', level='parton') 3618 3619 eradir = self.options['exrootanalysis_path'] 3620 try: 3621 misc.call(['%s/ExRootLHEFConverter' % eradir, 3622 input, output], 3623 cwd=pjoin(self.me_dir, 'Events')) 3624 except Exception: 3625 logger.warning('fail to produce Root output [problem with ExRootAnalysis]')
3626
3627 - def run_syscalc(self, mode='parton', event_path=None, output=None):
3628 """create the syscalc output""" 3629 3630 logger.info('running syscalc on mode %s' % mode) 3631 if self.run_card['use_syst'] not in self.true: 3632 return 3633 3634 scdir = self.options['syscalc_path'] 3635 tag = self.run_card['run_tag'] 3636 card = pjoin(self.me_dir, 'bin','internal', 'syscalc_card.dat') 3637 template = open(pjoin(self.me_dir, 'bin','internal', 'syscalc_template.dat')).read() 3638 self.run_card['sys_pdf'] = self.run_card['sys_pdf'].split('#',1)[0].replace('&&',' \n ') 3639 # check if the scalecorrelation parameter is define: 3640 if not 'sys_scalecorrelation' in self.run_card: 3641 self.run_card['sys_scalecorrelation'] = -1 3642 open(card,'w').write(template % self.run_card) 3643 3644 if not scdir or \ 3645 not os.path.exists(card): 3646 return False 3647 event_dir = pjoin(self.me_dir, 'Events') 3648 3649 if not event_path: 3650 if mode == 'parton': 3651 event_path = pjoin(event_dir,'unweighted_events.lhe') 3652 output = pjoin(event_dir, 'syscalc.lhe') 3653 elif mode == 'Pythia': 3654 if 'mgpythiacard' in self.banner: 3655 pat = re.compile('''^\s*qcut\s*=\s*([\+\-\d.e]*)''', re.M+re.I) 3656 data = pat.search(self.banner['mgpythiacard']) 3657 if data: 3658 qcut = float(data.group(1)) 3659 xqcut = abs(self.run_card['xqcut']) 3660 for value in self.run_card['sys_matchscale'].split(): 3661 if float(value) < qcut: 3662 raise SysCalcError, 'qcut value for sys_matchscale lower than qcut in pythia_card. Bypass syscalc' 3663 if float(value) < xqcut: 3664 raise SysCalcError, 'qcut value for sys_matchscale lower than xqcut in run_card. Bypass syscalc' 3665 3666 3667 event_path = pjoin(event_dir,'syst.dat') 3668 output = pjoin(event_dir, 'syscalc.dat') 3669 else: 3670 raise self.InvalidCmd, 'Invalid mode %s' % mode 3671 3672 if not os.path.exists(event_path): 3673 if os.path.exists(event_path+'.gz'): 3674 misc.gzip(event_path) 3675 else: 3676 raise SysCalcError, 'Events file %s does not exits' % event_path 3677 3678 self.update_status('Calculating systematics for %s level' % mode, level = mode.lower()) 3679 try: 3680 proc = misc.call([os.path.join(scdir, 'sys_calc'), 3681 event_path, card, output], 3682 stdout = open(pjoin(event_dir, self.run_name, '%s_%s_syscalc.log' % (tag,mode)),'w'), 3683 stderr = subprocess.STDOUT, 3684 cwd=event_dir) 3685 # Wait 5 s to make sure file is finished writing 3686 time.sleep(5) 3687 except OSError, error: 3688 logger.error('fail to run syscalc: %s. Please check that SysCalc is correctly installed.' % error) 3689 else: 3690 if mode == 'parton' and os.path.exists(output): 3691 files.mv(output, event_path) 3692 else: 3693 logger.warning('SysCalc Failed. Please read the associate log to see the reason. Did you install the associate PDF set?') 3694 self.update_status('End syscalc for %s level' % mode, level = mode.lower(), 3695 makehtml=False) 3696 3697 return True
3698 3699 3700 3701 ############################################################################
3702 - def ask_run_configuration(self, mode=None):
3703 """Ask the question when launching generate_events/multi_run""" 3704 3705 available_mode = ['0'] 3706 void = 'NOT INSTALLED' 3707 switch_order = ['pythia', 'pgs', 'delphes', 'madspin', 'reweight'] 3708 switch = {'pythia': void, 'pgs': void, 'delphes': void, 3709 'madspin': void, 'reweight': void} 3710 description = {'pythia': 'Run the pythia shower/hadronization:', 3711 'pgs': 'Run PGS as detector simulator:', 3712 'delphes':'Run Delphes as detector simulator:', 3713 'madspin':'Decay particles with the MadSpin module:', 3714 'reweight':'Add weight to events based on coupling parameters:', 3715 } 3716 force_switch = {('pythia', 'OFF'): {'pgs': 'OFF', 'delphes': 'OFF'}, 3717 ('pgs', 'ON'): {'pythia':'ON'}, 3718 ('delphes', 'ON'): {'pythia': 'ON'}} 3719 switch_assign = lambda key, value: switch.__setitem__(key, value if switch[key] != void else void ) 3720 3721 3722 # Init the switch value according to the current status 3723 if self.options['pythia-pgs_path']: 3724 available_mode.append('1') 3725 available_mode.append('2') 3726 if os.path.exists(pjoin(self.me_dir,'Cards','pythia_card.dat')): 3727 switch['pythia'] = 'ON' 3728 else: 3729 switch['pythia'] = 'OFF' 3730 if os.path.exists(pjoin(self.me_dir,'Cards','pgs_card.dat')): 3731 switch['pgs'] = 'ON' 3732 else: 3733 switch['pgs'] = 'OFF' 3734 if self.options['delphes_path']: 3735 available_mode.append('3') 3736 if os.path.exists(pjoin(self.me_dir,'Cards','delphes_card.dat')): 3737 switch['delphes'] = 'ON' 3738 else: 3739 switch['delphes'] = 'OFF' 3740 3741 # Check switch status for MS/reweight 3742 if not MADEVENT or self.options['mg5_path']: 3743 available_mode.append('4') 3744 available_mode.append('5') 3745 if os.path.exists(pjoin(self.me_dir,'Cards','madspin_card.dat')): 3746 switch['madspin'] = 'ON' 3747 else: 3748 switch['madspin'] = 'OFF' 3749 if os.path.exists(pjoin(self.me_dir,'Cards','reweight_card.dat')): 3750 switch['reweight'] = 'ON' 3751 else: 3752 switch['reweight'] = 'OFF' 3753 3754 3755 3756 options = list(available_mode) + ['auto', 'done'] 3757 for id, key in enumerate(switch_order): 3758 if switch[key] != void: 3759 options += ['%s=%s' % (key, s) for s in ['ON','OFF']] 3760 options.append(key) 3761 options.append('parton') 3762 3763 #ask the question 3764 if mode or not self.force: 3765 answer = '' 3766 while answer not in ['0', 'done', 'auto']: 3767 if mode: 3768 answer = mode 3769 else: 3770 switch_format = " %i %-50s %10s=%s\n" 3771 question = "The following switches determine which programs are run:\n" 3772 for id, key in enumerate(switch_order): 3773 question += switch_format % (id+1, description[key], key, switch[key]) 3774 question += ' Either type the switch number (1 to %s) to change its default setting,\n' % (id+1) 3775 question += ' or set any switch explicitly (e.g. type \'madspin=ON\' at the prompt)\n' 3776 question += ' Type \'0\', \'auto\', \'done\' or just press enter when you are done.\n' 3777 answer = self.ask(question, '0', options) 3778 if answer.isdigit() and answer != '0': 3779 key = switch_order[int(answer) - 1] 3780 answer = '%s=%s' % (key, 'ON' if switch[key] == 'OFF' else 'OFF') 3781 3782 if '=' in answer: 3783 key, status = answer.split('=') 3784 switch[key] = status 3785 if (key, status) in force_switch: 3786 for key2, status2 in force_switch[(key, status)].items(): 3787 if switch[key2] not in [status2, void]: 3788 logger.info('For coherence \'%s\' is set to \'%s\'' 3789 % (key2, status2), '$MG:color:BLACK') 3790 switch[key2] = status2 3791 elif answer in ['0', 'auto', 'done']: 3792 continue 3793 else: 3794 logger.info('pass in %s only mode' % answer, '$MG:color:BLACK') 3795 switch_assign('madspin', 'OFF') 3796 switch_assign('reweight', 'OFF') 3797 if answer == 'parton': 3798 switch_assign('pythia', 'OFF') 3799 switch_assign('pgs', 'OFF') 3800 switch_assign('delphes', 'OFF') 3801 elif answer == 'pythia': 3802 switch_assign('pythia', 'ON') 3803 switch_assign('pgs', 'OFF') 3804 switch_assign('delphes', 'OFF') 3805 elif answer == 'pgs': 3806 switch_assign('pythia', 'ON') 3807 switch_assign('pgs', 'ON') 3808 switch_assign('delphes', 'OFF') 3809 elif answer == 'delphes': 3810 switch_assign('pythia', 'ON') 3811 switch_assign('pgs', 'OFF') 3812 switch_assign('delphes', 'ON') 3813 elif answer == 'madspin': 3814 switch_assign('madspin', 'ON') 3815 switch_assign('pythia', 'OFF') 3816 switch_assign('pgs', 'OFF') 3817 switch_assign('delphes', 'OF') 3818 elif answer == 'reweight': 3819 switch_assign('reweight', 'ON') 3820 switch_assign('pythia', 'OFF') 3821 switch_assign('pgs', 'OFF') 3822 switch_assign('delphes', 'OFF') 3823 3824 3825 if mode: 3826 answer = '0' #mode auto didn't pass here (due to the continue) 3827 else: 3828 answer = 'auto' 3829 3830 # Now that we know in which mode we are check that all the card 3831 #exists (copy default if needed) 3832 3833 cards = ['param_card.dat', 'run_card.dat'] 3834 if switch['pythia'] == 'ON': 3835 cards.append('pythia_card.dat') 3836 if switch['pgs'] == 'ON': 3837 cards.append('pgs_card.dat') 3838 if switch['delphes'] == 'ON': 3839 cards.append('delphes_card.dat') 3840 delphes3 = True 3841 if os.path.exists(pjoin(self.options['delphes_path'], 'data')): 3842 delphes3 = False 3843 cards.append('delphes_trigger.dat') 3844 if switch['madspin'] == 'ON': 3845 cards.append('madspin_card.dat') 3846 if switch['reweight'] == 'ON': 3847 cards.append('reweight_card.dat') 3848 self.keep_cards(cards) 3849 if self.force: 3850 self.check_param_card(pjoin(self.me_dir,'Cards','param_card.dat' )) 3851 return 3852 3853 if answer == 'auto': 3854 self.ask_edit_cards(cards, mode='auto') 3855 else: 3856 self.ask_edit_cards(cards) 3857 return
3858 3859 ############################################################################
3860 - def ask_pythia_run_configuration(self, mode=None):
3861 """Ask the question when launching pythia""" 3862 3863 available_mode = ['0', '1', '2'] 3864 if self.options['delphes_path']: 3865 available_mode.append('3') 3866 name = {'0': 'auto', '1': 'pythia', '2':'pgs', '3':'delphes'} 3867 options = available_mode + [name[val] for val in available_mode] 3868 question = """Which programs do you want to run? 3869 0 / auto : running existing card 3870 1 / pythia : Pythia 3871 2 / pgs : Pythia + PGS\n""" 3872 if '3' in available_mode: 3873 question += """ 3 / delphes : Pythia + Delphes.\n""" 3874 3875 if not self.force: 3876 if not mode: 3877 mode = self.ask(question, '0', options) 3878 elif not mode: 3879 mode = 'auto' 3880 3881 if mode.isdigit(): 3882 mode = name[mode] 3883 3884 auto = False 3885 if mode == 'auto': 3886 auto = True 3887 if os.path.exists(pjoin(self.me_dir, 'Cards', 'pgs_card.dat')): 3888 mode = 'pgs' 3889 elif os.path.exists(pjoin(self.me_dir, 'Cards', 'delphes_card.dat')): 3890 mode = 'delphes' 3891 else: 3892 mode = 'pythia' 3893 logger.info('Will run in mode %s' % mode) 3894 3895 # Now that we know in which mode we are check that all the card 3896 #exists (copy default if needed) remove pointless one 3897 cards = ['pythia_card.dat'] 3898 if mode == 'pgs': 3899 cards.append('pgs_card.dat') 3900 if mode == 'delphes': 3901 cards.append('delphes_card.dat') 3902 delphes3 = True 3903 if os.path.exists(pjoin(self.options['delphes_path'], 'data')): 3904 delphes3 = False 3905 cards.append('delphes_trigger.dat') 3906 self.keep_cards(cards) 3907 3908 if self.force: 3909 return mode 3910 3911 if auto: 3912 self.ask_edit_cards(cards, mode='auto') 3913 else: 3914 self.ask_edit_cards(cards) 3915 3916 return mode
3917
3918 3919 3920 3921 3922 #=============================================================================== 3923 # MadEventCmd 3924 #=============================================================================== 3925 -class MadEventCmdShell(MadEventCmd, cmd.CmdShell):
3926 """The command line processor of MadGraph"""
3927
3928 3929 3930 #=============================================================================== 3931 # HELPING FUNCTION For Subprocesses 3932 #=============================================================================== 3933 -class SubProcesses(object):
3934 3935 name_to_pdg = {} 3936 3937 @classmethod
3938 - def clean(cls):
3939 cls.name_to_pdg = {}
3940 3941 @staticmethod
3942 - def get_subP(me_dir):
3943 """return the list of Subprocesses""" 3944 3945 out = [] 3946 for line in open(pjoin(me_dir,'SubProcesses', 'subproc.mg')): 3947 if not line: 3948 continue 3949 name = line.strip() 3950 if os.path.exists(pjoin(me_dir, 'SubProcesses', name)): 3951 out.append(pjoin(me_dir, 'SubProcesses', name)) 3952 3953 return out
3954 3955 3956 3957 @staticmethod
3958 - def get_subP_info(path):
3959 """ return the list of processes with their name""" 3960 3961 nb_sub = 0 3962 names = {} 3963 old_main = '' 3964 3965 if not os.path.exists(os.path.join(path,'processes.dat')): 3966 return SubProcesses.get_subP_info_v4(path) 3967 3968 for line in open(os.path.join(path,'processes.dat')): 3969 main = line[:8].strip() 3970 if main == 'mirror': 3971 main = old_main 3972 if line[8:].strip() == 'none': 3973 continue 3974 else: 3975 main = int(main) 3976 old_main = main 3977 3978 sub_proccess = line[8:] 3979 nb_sub += sub_proccess.count(',') + 1 3980 if main in names: 3981 names[main] += [sub_proccess.split(',')] 3982 else: 3983 names[main]= [sub_proccess.split(',')] 3984 3985 return names
3986 3987 @staticmethod
3988 - def get_subP_info_v4(path):
3989 """ return the list of processes with their name in case without grouping """ 3990 3991 nb_sub = 0 3992 names = {'':[[]]} 3993 path = os.path.join(path, 'auto_dsig.f') 3994 found = 0 3995 for line in open(path): 3996 if line.startswith('C Process:'): 3997 found += 1 3998 names[''][0].append(line[15:]) 3999 elif found >1: 4000 break 4001 return names
4002 4003 4004 @staticmethod
4005 - def get_subP_ids(path):
4006 """return the pdg codes of the particles present in the Subprocesses""" 4007 4008 all_ids = [] 4009 for line in open(pjoin(path, 'leshouche.inc')): 4010 if not 'IDUP' in line: 4011 continue 4012 particles = re.search("/([\d,-]+)/", line) 4013 all_ids.append([int(p) for p in particles.group(1).split(',')]) 4014 return all_ids
4015
4016 4017 #=============================================================================== 4018 -class GridPackCmd(MadEventCmd):
4019 """The command for the gridpack --Those are not suppose to be use interactively--""" 4020
4021 - def __init__(self, me_dir = None, nb_event=0, seed=0, *completekey, **stdin):
4022 """Initialize the command and directly run""" 4023 4024 # Initialize properly 4025 4026 MadEventCmd.__init__(self, me_dir, *completekey, **stdin) 4027 self.run_mode = 0 4028 self.random = seed 4029 self.random_orig = self.random 4030 self.options['automatic_html_opening'] = False 4031 # Now it's time to run! 4032 if me_dir and nb_event and seed: 4033 self.launch(nb_event, seed) 4034 else: 4035 raise MadGraph5Error,\ 4036 'Gridpack run failed: ' + str(me_dir) + str(nb_event) + \ 4037 str(seed)
4038
4039 - def launch(self, nb_event, seed):
4040 """ launch the generation for the grid """ 4041 4042 # 1) Restore the default data 4043 logger.info('generate %s events' % nb_event) 4044 self.set_run_name('GridRun_%s' % seed) 4045 self.update_status('restoring default data', level=None) 4046 misc.call([pjoin(self.me_dir,'bin','internal','restore_data'), 4047 'default'], 4048 cwd=self.me_dir) 4049 4050 # 2) Run the refine for the grid 4051 self.update_status('Generating Events', level=None) 4052 #misc.call([pjoin(self.me_dir,'bin','refine4grid'), 4053 # str(nb_event), '0', 'Madevent','1','GridRun_%s' % seed], 4054 # cwd=self.me_dir) 4055 self.refine4grid(nb_event) 4056 4057 # 3) Combine the events/pythia/... 4058 self.exec_cmd('combine_events') 4059 self.exec_cmd('store_events') 4060 self.print_results_in_shell(self.results.current) 4061 self.exec_cmd('decay_events -from_cards', postcmd=False)
4062
4063 - def refine4grid(self, nb_event):
4064 """Special refine for gridpack run.""" 4065 self.nb_refine += 1 4066 4067 precision = nb_event 4068 4069 # initialize / remove lhapdf mode 4070 # self.configure_directory() # All this has been done before 4071 self.cluster_mode = 0 # force single machine 4072 4073 # Store seed in randinit file, to be read by ranmar.f 4074 self.save_random() 4075 4076 self.update_status('Refine results to %s' % precision, level=None) 4077 logger.info("Using random number seed offset = %s" % self.random) 4078 4079 self.total_jobs = 0 4080 subproc = [P for P in os.listdir(pjoin(self.me_dir,'SubProcesses')) if 4081 P.startswith('P') and os.path.isdir(pjoin(self.me_dir,'SubProcesses', P))] 4082 devnull = open(os.devnull, 'w') 4083 for nb_proc,subdir in enumerate(subproc): 4084 subdir = subdir.strip() 4085 Pdir = pjoin(self.me_dir, 'SubProcesses',subdir) 4086 bindir = pjoin(os.path.relpath(self.dirbin, Pdir)) 4087 4088 logger.info(' %s ' % subdir) 4089 # clean previous run 4090 for match in glob.glob(pjoin(Pdir, '*ajob*')): 4091 if os.path.basename(match)[:4] in ['ajob', 'wait', 'run.', 'done']: 4092 os.remove(pjoin(Pdir, match)) 4093 4094 4095 logfile = pjoin(Pdir, 'gen_ximprove.log') 4096 misc.call([pjoin(bindir, 'gen_ximprove')], 4097 stdin=subprocess.PIPE, 4098 stdout=open(logfile,'w'), 4099 cwd=Pdir) 4100 4101 if os.path.exists(pjoin(Pdir, 'ajob1')): 4102 alljobs = glob.glob(pjoin(Pdir,'ajob*')) 4103 nb_tot = len(alljobs) 4104 self.total_jobs += nb_tot 4105 for i, job in enumerate(alljobs): 4106 job = os.path.basename(job) 4107 self.launch_job('%s' % job, cwd=Pdir, remaining=(nb_tot-i-1), 4108 run_type='Refine number %s on %s (%s/%s)' % 4109 (self.nb_refine, subdir, nb_proc+1, len(subproc))) 4110 if os.path.exists(pjoin(self.me_dir,'error')): 4111 self.monitor(html=True) 4112 raise MadEventError, \ 4113 'Error detected in dir %s: %s' % \ 4114 (Pdir, open(pjoin(self.me_dir,'error')).read()) 4115 self.monitor(run_type='All job submitted for refine number %s' % 4116 self.nb_refine) 4117 4118 self.update_status("Combining runs", level='parton') 4119 try: 4120 os.remove(pjoin(Pdir, 'combine_runs.log')) 4121 except Exception: 4122 pass 4123 4124 bindir = pjoin(os.path.relpath(self.dirbin, pjoin(self.me_dir,'SubProcesses'))) 4125 combine_runs.CombineRuns(self.me_dir) 4126 4127 #update html output 4128 cross, error = sum_html.make_all_html_results(self) 4129 self.results.add_detail('cross', cross) 4130 self.results.add_detail('error', error) 4131 4132 4133 self.update_status('finish refine', 'parton', makehtml=False) 4134 devnull.close()
4135 4136 4137 4138 AskforEditCard = common_run.AskforEditCard 4139