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.def_web_mode(self.web) 1614 1615 self.prompt = "%s>"%os.path.basename(pjoin(self.me_dir)) 1616 self.configured = 0 # time for reading the card 1617 self._options = {} # for compatibility with extended_cmd
1618
1619 - def pass_in_web_mode(self):
1620 """configure web data""" 1621 self.web = True 1622 self.results.def_web_mode(True) 1623 self.force = True 1624 if os.environ['MADGRAPH_BASE']: 1625 self.options['mg5_path'] = pjoin(os.environ['MADGRAPH_BASE'],'MG5')
1626 1627 ############################################################################
1628 - def check_output_type(self, path):
1629 """ Check that the output path is a valid madevent directory """ 1630 1631 bin_path = os.path.join(path,'bin') 1632 if os.path.isfile(os.path.join(bin_path,'generate_events')): 1633 return True 1634 else: 1635 return False
1636 1637 ############################################################################
1638 - def set_configuration(self, amcatnlo=False, final=True, **opt):
1639 """assign all configuration variable from file 1640 loop over the different config file if config_file not define """ 1641 1642 super(MadEventCmd,self).set_configuration(amcatnlo=amcatnlo, 1643 final=final, **opt) 1644 if not final: 1645 return self.options # the return is usefull for unittest 1646 1647 # Treat each expected input 1648 # delphes/pythia/... path 1649 # ONLY the ONE LINKED TO Madevent ONLY!!! 1650 for key in (k for k in self.options if k.endswith('path')): 1651 path = self.options[key] 1652 if path is None: 1653 continue 1654 if not os.path.isdir(path): 1655 path = pjoin(self.me_dir, self.options[key]) 1656 if os.path.isdir(path): 1657 self.options[key] = None 1658 if key == "pythia-pgs_path": 1659 if not os.path.exists(pjoin(path, 'src','pythia')): 1660 logger.info("No valid pythia-pgs path found") 1661 continue 1662 elif key == "delphes_path": 1663 if not os.path.exists(pjoin(path, 'Delphes')) and not\ 1664 os.path.exists(pjoin(path, 'DelphesSTDHEP')): 1665 logger.info("No valid Delphes path found") 1666 continue 1667 elif key == "madanalysis_path": 1668 if not os.path.exists(pjoin(path, 'plot_events')): 1669 logger.info("No valid MadAnalysis path found") 1670 continue 1671 elif key == "td_path": 1672 if not os.path.exists(pjoin(path, 'td')): 1673 logger.info("No valid td path found") 1674 continue 1675 elif key == "syscalc_path": 1676 if not os.path.exists(pjoin(path, 'sys_calc')): 1677 logger.info("No valid SysCalc path found") 1678 continue 1679 # No else since the next line reinitialize the option to the 1680 #previous value anyway 1681 self.options[key] = os.path.realpath(path) 1682 continue 1683 else: 1684 self.options[key] = None 1685 1686 1687 return self.options
1688 1689 ############################################################################
1690 - def do_add_time_of_flight(self, line):
1691 1692 args = self.split_arg(line) 1693 #check the validity of the arguments and reformat args 1694 self.check_add_time_of_flight(args) 1695 1696 event_path, threshold = args 1697 #gunzip the file 1698 if event_path.endswith('.gz'): 1699 need_zip = True 1700 misc.gunzip(event_path) 1701 event_path = event_path[:-3] 1702 else: 1703 need_zip = False 1704 1705 import random 1706 try: 1707 import madgraph.various.lhe_parser as lhe_parser 1708 except: 1709 import internal.lhe_parser as lhe_parser 1710 1711 logger.info('Add time of flight information on file %s' % event_path) 1712 lhe = lhe_parser.EventFile(event_path) 1713 output = open('%s_2vertex.lhe' % event_path, 'w') 1714 #write the banner to the output file 1715 output.write(lhe.banner) 1716 1717 # get the associate param_card 1718 begin_param = lhe.banner.find('<slha>') 1719 end_param = lhe.banner.find('</slha>') 1720 param_card = lhe.banner[begin_param+6:end_param].split('\n') 1721 param_card = check_param_card.ParamCard(param_card) 1722 1723 cst = 6.58211915e-25 1724 # Loop over all events 1725 for event in lhe: 1726 for particle in event: 1727 id = particle.pid 1728 width = param_card['decay'].get((abs(id),)).value 1729 if width: 1730 vtim = random.expovariate(width/cst) 1731 if vtim > threshold: 1732 particle.vtim = vtim 1733 #write this modify event 1734 output.write(str(event)) 1735 output.write('</LesHouchesEvents>\n') 1736 output.close() 1737 1738 files.mv('%s_2vertex.lhe' % event_path, event_path) 1739 1740 if need_zip: 1741 misc.gzip(event_path)
1742 1743 ############################################################################
1744 - def do_banner_run(self, line):
1745 """Make a run from the banner file""" 1746 1747 args = self.split_arg(line) 1748 #check the validity of the arguments 1749 self.check_banner_run(args) 1750 1751 # Remove previous cards 1752 for name in ['delphes_trigger.dat', 'delphes_card.dat', 1753 'pgs_card.dat', 'pythia_card.dat', 'madspin_card.dat', 1754 'reweight_card.dat']: 1755 try: 1756 os.remove(pjoin(self.me_dir, 'Cards', name)) 1757 except Exception: 1758 pass 1759 1760 banner_mod.split_banner(args[0], self.me_dir, proc_card=False) 1761 1762 # Check if we want to modify the run 1763 if not self.force: 1764 ans = self.ask('Do you want to modify the Cards?', 'n', ['y','n']) 1765 if ans == 'n': 1766 self.force = True 1767 1768 # Call Generate events 1769 self.exec_cmd('generate_events %s %s' % (self.run_name, self.force and '-f' or ''))
1770 1771 1772 1773 ############################################################################
1774 - def do_display(self, line, output=sys.stdout):
1775 """Display current internal status""" 1776 1777 args = self.split_arg(line) 1778 #check the validity of the arguments 1779 self.check_display(args) 1780 1781 if args[0] == 'run_name': 1782 #return valid run_name 1783 data = glob.glob(pjoin(self.me_dir, 'Events', '*','*_banner.txt')) 1784 data = [n.rsplit('/',2)[1:] for n in data] 1785 1786 if data: 1787 out = {} 1788 for name, tag in data: 1789 tag = tag[len(name)+1:-11] 1790 if name in out: 1791 out[name].append(tag) 1792 else: 1793 out[name] = [tag] 1794 print 'the runs available are:' 1795 for run_name, tags in out.items(): 1796 print ' run: %s' % run_name 1797 print ' tags: ', 1798 print ', '.join(tags) 1799 else: 1800 print 'No run detected.' 1801 1802 elif args[0] == 'options': 1803 outstr = " Run Options \n" 1804 outstr += " ----------- \n" 1805 for key, default in self.options_madgraph.items(): 1806 value = self.options[key] 1807 if value == default: 1808 outstr += " %25s \t:\t%s\n" % (key,value) 1809 else: 1810 outstr += " %25s \t:\t%s (user set)\n" % (key,value) 1811 outstr += "\n" 1812 outstr += " MadEvent Options \n" 1813 outstr += " ---------------- \n" 1814 for key, default in self.options_madevent.items(): 1815 if key in self.options: 1816 value = self.options[key] 1817 else: 1818 default = '' 1819 if value == default: 1820 outstr += " %25s \t:\t%s\n" % (key,value) 1821 else: 1822 outstr += " %25s \t:\t%s (user set)\n" % (key,value) 1823 outstr += "\n" 1824 outstr += " Configuration Options \n" 1825 outstr += " --------------------- \n" 1826 for key, default in self.options_configuration.items(): 1827 value = self.options[key] 1828 if value == default: 1829 outstr += " %25s \t:\t%s\n" % (key,value) 1830 else: 1831 outstr += " %25s \t:\t%s (user set)\n" % (key,value) 1832 output.write(outstr) 1833 elif args[0] == 'results': 1834 self.do_print_results(' '.join(args[1:])) 1835 else: 1836 super(MadEventCmd, self).do_display(line, output)
1837
1838 - def do_save(self, line, check=True, to_keep={}):
1839 """Not in help: Save information to file""" 1840 1841 args = self.split_arg(line) 1842 # Check argument validity 1843 if check: 1844 self.check_save(args) 1845 1846 if args[0] == 'options': 1847 # First look at options which should be put in MG5DIR/input 1848 to_define = {} 1849 for key, default in self.options_configuration.items(): 1850 if self.options[key] != self.options_configuration[key]: 1851 to_define[key] = self.options[key] 1852 1853 if not '--auto' in args: 1854 for key, default in self.options_madevent.items(): 1855 if self.options[key] != self.options_madevent[key]: 1856 to_define[key] = self.options[key] 1857 1858 if '--all' in args: 1859 for key, default in self.options_madgraph.items(): 1860 if self.options[key] != self.options_madgraph[key]: 1861 to_define[key] = self.options[key] 1862 elif not '--auto' in args: 1863 for key, default in self.options_madgraph.items(): 1864 if self.options[key] != self.options_madgraph[key]: 1865 logger.info('The option %s is modified [%s] but will not be written in the configuration files.' \ 1866 % (key,self.options_madgraph[key]) ) 1867 logger.info('If you want to make this value the default for future session, you can run \'save options --all\'') 1868 if len(args) >1 and not args[1].startswith('--'): 1869 filepath = args[1] 1870 else: 1871 filepath = pjoin(self.me_dir, 'Cards', 'me5_configuration.txt') 1872 basefile = pjoin(self.me_dir, 'Cards', 'me5_configuration.txt') 1873 basedir = self.me_dir 1874 1875 if to_keep: 1876 to_define = to_keep 1877 self.write_configuration(filepath, basefile, basedir, to_define)
1878 1879 1880 1881 1882 1883 1884 ############################################################################ 1885 1886 ############################################################################
1887 - def do_generate_events(self, line):
1888 """Main Commands: launch the full chain """ 1889 1890 args = self.split_arg(line) 1891 # Check argument's validity 1892 mode = self.check_generate_events(args) 1893 self.ask_run_configuration(mode) 1894 if not args: 1895 # No run name assigned -> assigned one automaticaly 1896 self.set_run_name(self.find_available_run_name(self.me_dir), None, 'parton') 1897 else: 1898 self.set_run_name(args[0], None, 'parton', True) 1899 args.pop(0) 1900 1901 if self.run_card['gridpack'] in self.true: 1902 # Running gridpack warmup 1903 gridpack_opts=[('accuracy', 0.01), 1904 ('points', 2000), 1905 ('iterations',8), 1906 ('gridpack','.true.')] 1907 logger.info('Generating gridpack with run name %s' % self.run_name) 1908 self.exec_cmd('survey %s %s' % \ 1909 (self.run_name, 1910 " ".join(['--' + opt + '=' + str(val) for (opt,val) \ 1911 in gridpack_opts])), 1912 postcmd=False) 1913 self.exec_cmd('combine_events', postcmd=False) 1914 self.exec_cmd('store_events', postcmd=False) 1915 self.exec_cmd('decay_events -from_cards', postcmd=False) 1916 self.exec_cmd('create_gridpack', postcmd=False) 1917 else: 1918 # Regular run mode 1919 logger.info('Generating %s events with run name %s' % 1920 (self.run_card['nevents'], self.run_name)) 1921 1922 self.exec_cmd('survey %s %s' % (self.run_name,' '.join(args)), 1923 postcmd=False) 1924 if not float(self.results.current['cross']): 1925 # Zero cross-section. Try to guess why 1926 text = '''Survey return zero cross section. 1927 Typical reasons are the following: 1928 1) A massive s-channel particle has a width set to zero. 1929 2) The pdf are zero for at least one of the initial state particles 1930 or you are using maxjetflavor=4 for initial state b:s. 1931 3) The cuts are too strong. 1932 Please check/correct your param_card and/or your run_card.''' 1933 logger_stderr.critical(text) 1934 raise ZeroResult('See https://cp3.irmp.ucl.ac.be/projects/madgraph/wiki/FAQ-General-14') 1935 nb_event = self.run_card['nevents'] 1936 self.exec_cmd('refine %s' % nb_event, postcmd=False) 1937 self.exec_cmd('refine %s' % nb_event, postcmd=False) 1938 self.exec_cmd('combine_events', postcmd=False) 1939 self.print_results_in_shell(self.results.current) 1940 self.run_syscalc('parton') 1941 self.create_plot('parton') 1942 self.exec_cmd('store_events', postcmd=False) 1943 self.exec_cmd('reweight -from_cards', postcmd=False) 1944 self.exec_cmd('decay_events -from_cards', postcmd=False) 1945 self.exec_cmd('pythia --no_default', postcmd=False, printcmd=False) 1946 # pythia launches pgs/delphes if needed 1947 self.store_result()
1948 1949
1950 - def do_launch(self, line, *args, **opt):
1951 """Main Commands: exec generate_events for 2>N and calculate_width for 1>N""" 1952 if self.ninitial == 1: 1953 self.do_calculate_decay_widths(line, *args, **opt) 1954 else: 1955 self.do_generate_events(line, *args, **opt)
1956
1957 - def print_results_in_shell(self, data):
1958 """Have a nice results prints in the shell, 1959 data should be of type: gen_crossxhtml.OneTagResults""" 1960 if not data: 1961 return 1962 logger.info(" === Results Summary for run: %s tag: %s ===\n" % (data['run_name'],data['tag'])) 1963 if self.ninitial == 1: 1964 logger.info(" Width : %.4g +- %.4g GeV" % (data['cross'], data['error'])) 1965 else: 1966 logger.info(" Cross-section : %.4g +- %.4g pb" % (data['cross'], data['error'])) 1967 logger.info(" Nb of events : %s" % data['nb_event'] ) 1968 if data['cross_pythia'] and data['nb_event_pythia']: 1969 if self.ninitial == 1: 1970 logger.info(" Matched Width : %.4g +- %.4g GeV" % (data['cross_pythia'], data['error_pythia'])) 1971 else: 1972 logger.info(" Matched Cross-section : %.4g +- %.4g pb" % (data['cross_pythia'], data['error_pythia'])) 1973 logger.info(" Nb of events after Matching : %s" % data['nb_event_pythia']) 1974 if self.run_card['use_syst'] in self.true: 1975 logger.info(" Be carefull that matched information are here NOT for the central value. Refer to SysCalc output for it") 1976 1977 logger.info(" " )
1978
1979 - def print_results_in_file(self, data, path, mode='w'):
1980 """Have a nice results prints in the shell, 1981 data should be of type: gen_crossxhtml.OneTagResults""" 1982 if not data: 1983 return 1984 1985 fsock = open(path, mode) 1986 1987 fsock.write(" === Results Summary for run: %s tag: %s process: %s ===\n" % \ 1988 (data['run_name'],data['tag'], os.path.basename(self.me_dir))) 1989 1990 if self.ninitial == 1: 1991 fsock.write(" Width : %.4g +- %.4g GeV\n" % (data['cross'], data['error'])) 1992 else: 1993 fsock.write(" Cross-section : %.4g +- %.4g pb\n" % (data['cross'], data['error'])) 1994 fsock.write(" Nb of events : %s\n" % data['nb_event'] ) 1995 if data['cross_pythia'] and data['nb_event_pythia']: 1996 if self.ninitial == 1: 1997 fsock.write(" Matched Width : %.4g +- %.4g GeV\n" % (data['cross_pythia'], data['error_pythia'])) 1998 else: 1999 fsock.write(" Matched Cross-section : %.4g +- %.4g pb\n" % (data['cross_pythia'], data['error_pythia'])) 2000 fsock.write(" Nb of events after Matching : %s\n" % data['nb_event_pythia']) 2001 fsock.write(" \n" )
2002 2003 ############################################################################
2004 - def do_calculate_decay_widths(self, line):
2005 """Main Commands: launch decay width calculation and automatic inclusion of 2006 calculated widths and BRs in the param_card.""" 2007 2008 args = self.split_arg(line) 2009 # Check argument's validity 2010 accuracy = self.check_calculate_decay_widths(args) 2011 self.ask_run_configuration('parton') 2012 if not args: 2013 # No run name assigned -> assigned one automaticaly 2014 self.set_run_name(self.find_available_run_name(self.me_dir)) 2015 else: 2016 self.set_run_name(args[0], reload_card=True) 2017 args.pop(0) 2018 2019 self.configure_directory() 2020 2021 # Running gridpack warmup 2022 opts=[('accuracy', accuracy), # default 0.01 2023 ('points', 1000), 2024 ('iterations',9)] 2025 2026 logger.info('Calculating decay widths with run name %s' % self.run_name) 2027 2028 self.exec_cmd('survey %s %s' % \ 2029 (self.run_name, 2030 " ".join(['--' + opt + '=' + str(val) for (opt,val) \ 2031 in opts])), 2032 postcmd=False) 2033 self.exec_cmd('combine_events', postcmd=False) 2034 self.exec_cmd('store_events', postcmd=False) 2035 2036 self.collect_decay_widths() 2037 self.update_status('calculate_decay_widths done', 2038 level='parton', makehtml=False)
2039 2040 2041 ############################################################################
2042 - def collect_decay_widths(self):
2043 """ Collect the decay widths and calculate BRs for all particles, and put 2044 in param_card form. 2045 """ 2046 2047 particle_dict = {} # store the results 2048 run_name = self.run_name 2049 2050 # Looping over the Subprocesses 2051 for P_path in SubProcesses.get_subP(self.me_dir): 2052 ids = SubProcesses.get_subP_ids(P_path) 2053 # due to grouping we need to compute the ratio factor for the 2054 # ungroup resutls (that we need here). Note that initial particles 2055 # grouping are not at the same stage as final particle grouping 2056 nb_output = len(ids) / (len(set([p[0] for p in ids]))) 2057 results = open(pjoin(P_path, run_name + '_results.dat')).read().split('\n')[0] 2058 result = float(results.strip().split(' ')[0]) 2059 for particles in ids: 2060 try: 2061 particle_dict[particles[0]].append([particles[1:], result/nb_output]) 2062 except KeyError: 2063 particle_dict[particles[0]] = [[particles[1:], result/nb_output]] 2064 2065 self.update_width_in_param_card(particle_dict, 2066 initial = pjoin(self.me_dir, 'Cards', 'param_card.dat'), 2067 output=pjoin(self.me_dir, 'Events', run_name, "param_card.dat"))
2068 2069 @staticmethod
2070 - def update_width_in_param_card(decay_info, initial=None, output=None):
2071 # Open the param_card.dat and insert the calculated decays and BRs 2072 2073 if not output: 2074 output = initial 2075 2076 param_card_file = open(initial) 2077 param_card = param_card_file.read().split('\n') 2078 param_card_file.close() 2079 2080 decay_lines = [] 2081 line_number = 0 2082 # Read and remove all decays from the param_card 2083 while line_number < len(param_card): 2084 line = param_card[line_number] 2085 if line.lower().startswith('decay'): 2086 # Read decay if particle in decay_info 2087 # DECAY 6 1.455100e+00 2088 line = param_card.pop(line_number) 2089 line = line.split() 2090 particle = 0 2091 if int(line[1]) not in decay_info: 2092 try: # If formatting is wrong, don't want this particle 2093 particle = int(line[1]) 2094 width = float(line[2]) 2095 except Exception: 2096 particle = 0 2097 # Read BRs for this decay 2098 line = param_card[line_number] 2099 while line.startswith('#') or line.startswith(' '): 2100 line = param_card.pop(line_number) 2101 if not particle or line.startswith('#'): 2102 line=param_card[line_number] 2103 continue 2104 # 6.668201e-01 3 5 2 -1 2105 line = line.split() 2106 try: # Remove BR if formatting is wrong 2107 partial_width = float(line[0])*width 2108 decay_products = [int(p) for p in line[2:2+int(line[1])]] 2109 except Exception: 2110 line=param_card[line_number] 2111 continue 2112 try: 2113 decay_info[particle].append([decay_products, partial_width]) 2114 except KeyError: 2115 decay_info[particle] = [[decay_products, partial_width]] 2116 if line_number == len(param_card): 2117 break 2118 line=param_card[line_number] 2119 if particle and particle not in decay_info: 2120 # No decays given, only total width 2121 decay_info[particle] = [[[], width]] 2122 else: # Not decay 2123 line_number += 1 2124 # Clean out possible remaining comments at the end of the card 2125 while not param_card[-1] or param_card[-1].startswith('#'): 2126 param_card.pop(-1) 2127 2128 # Append calculated and read decays to the param_card 2129 param_card.append("#\n#*************************") 2130 param_card.append("# Decay widths *") 2131 param_card.append("#*************************") 2132 for key in sorted(decay_info.keys()): 2133 width = sum([r for p,r in decay_info[key]]) 2134 param_card.append("#\n# PDG Width") 2135 param_card.append("DECAY %i %e" % (key, width.real)) 2136 if not width: 2137 continue 2138 if decay_info[key][0][0]: 2139 param_card.append("# BR NDA ID1 ID2 ...") 2140 brs = [[(val[1]/width).real, val[0]] for val in decay_info[key] if val[1]] 2141 for val in sorted(brs, reverse=True): 2142 param_card.append(" %e %i %s # %s" % 2143 (val[0].real, len(val[1]), 2144 " ".join([str(v) for v in val[1]]), 2145 val[0] * width 2146 )) 2147 decay_table = open(output, 'w') 2148 decay_table.write("\n".join(param_card) + "\n") 2149 decay_table.close() 2150 logger.info("Results written to %s" % output)
2151 2152 2153 ############################################################################
2154 - def do_multi_run(self, line):
2155 2156 args = self.split_arg(line) 2157 # Check argument's validity 2158 mode = self.check_multi_run(args) 2159 nb_run = args.pop(0) 2160 if nb_run == 1: 2161 logger.warn("'multi_run 1' command is not optimal. Think of using generate_events instead") 2162 self.ask_run_configuration(mode) 2163 main_name = self.run_name 2164 2165 2166 2167 2168 2169 crossoversig = 0 2170 inv_sq_err = 0 2171 nb_event = 0 2172 for i in range(nb_run): 2173 self.nb_refine = 0 2174 self.exec_cmd('generate_events %s_%s -f' % (main_name, i), postcmd=False) 2175 # Update collected value 2176 nb_event += int(self.results[self.run_name][-1]['nb_event']) 2177 self.results.add_detail('nb_event', nb_event , run=main_name) 2178 cross = self.results[self.run_name][-1]['cross'] 2179 error = self.results[self.run_name][-1]['error'] + 1e-99 2180 crossoversig+=cross/error**2 2181 inv_sq_err+=1.0/error**2 2182 self.results[main_name][-1]['cross'] = crossoversig/inv_sq_err 2183 self.results[main_name][-1]['error'] = math.sqrt(1.0/inv_sq_err) 2184 self.results.def_current(main_name) 2185 self.run_name = main_name 2186 self.update_status("Merging LHE files", level='parton') 2187 try: 2188 os.mkdir(pjoin(self.me_dir,'Events', self.run_name)) 2189 except Exception: 2190 pass 2191 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' 2192 % {'bin': self.dirbin, 'event': pjoin(self.me_dir,'Events'), 2193 'name': self.run_name}) 2194 2195 eradir = self.options['exrootanalysis_path'] 2196 if eradir and misc.is_executable(pjoin(eradir,'ExRootLHEFConverter')): 2197 self.update_status("Create Root file", level='parton') 2198 misc.gunzip('%s/%s/unweighted_events.lhe.gz' % 2199 (pjoin(self.me_dir,'Events'), self.run_name)) 2200 2201 self.create_root_file('%s/unweighted_events.lhe' % self.run_name, 2202 '%s/unweighted_events.root' % self.run_name) 2203 2204 path = pjoin(self.me_dir, "Events", self.run_name, "unweighted_events.lhe") 2205 self.create_plot('parton', path, 2206 pjoin(self.me_dir, 'HTML',self.run_name, 'plots_parton.html') 2207 ) 2208 2209 2210 if not os.path.exists('%s.gz' % path): 2211 misc.gzip(path) 2212 2213 self.update_status('', level='parton') 2214 self.print_results_in_shell(self.results.current)
2215 2216 2217 ############################################################################
2218 - def do_treatcards(self, line, mode=None, opt=None):
2219 """Advanced commands: create .inc files from param_card.dat/run_card.dat""" 2220 2221 2222 if not mode and not opt: 2223 args = self.split_arg(line) 2224 mode, opt = self.check_treatcards(args) 2225 #check if no 'Auto' are present in the file 2226 self.check_param_card(pjoin(self.me_dir, 'Cards','param_card.dat')) 2227 2228 2229 if mode in ['param', 'all']: 2230 model = self.find_model_name() 2231 tmp_model = os.path.basename(model) 2232 if tmp_model == 'mssm' or tmp_model.startswith('mssm-'): 2233 if not '--param_card=' in line: 2234 param_card = pjoin(self.me_dir, 'Cards','param_card.dat') 2235 mg5_param = pjoin(self.me_dir, 'Source', 'MODEL', 'MG5_param.dat') 2236 check_param_card.convert_to_mg5card(param_card, mg5_param) 2237 check_param_card.check_valid_param_card(mg5_param) 2238 opt['param_card'] = pjoin(self.me_dir, 'Source', 'MODEL', 'MG5_param.dat') 2239 else: 2240 check_param_card.check_valid_param_card(opt['param_card']) 2241 2242 logger.debug('write compile file for card: %s' % opt['param_card']) 2243 param_card = check_param_card.ParamCard(opt['param_card']) 2244 outfile = pjoin(opt['output_dir'], 'param_card.inc') 2245 ident_card = pjoin(self.me_dir,'Cards','ident_card.dat') 2246 if os.path.isfile(pjoin(self.me_dir,'bin','internal','ufomodel','restrict_default.dat')): 2247 default = pjoin(self.me_dir,'bin','internal','ufomodel','restrict_default.dat') 2248 elif os.path.isfile(pjoin(self.me_dir,'bin','internal','ufomodel','param_card.dat')): 2249 default = pjoin(self.me_dir,'bin','internal','ufomodel','param_card.dat') 2250 elif not os.path.exists(pjoin(self.me_dir,'bin','internal','ufomodel')): 2251 fsock = open(pjoin(self.me_dir,'Source','param_card.inc'),'w') 2252 fsock.write(' ') 2253 fsock.close() 2254 if mode == 'all': 2255 self.do_treatcards('', 'run', opt) 2256 return 2257 else: 2258 devnull = open(os.devnull,'w') 2259 subprocess.call([sys.executable, 'write_param_card.py'], 2260 cwd=pjoin(self.me_dir,'bin','internal','ufomodel'), 2261 stdout=devnull) 2262 devnull.close() 2263 default = pjoin(self.me_dir,'bin','internal','ufomodel','param_card.dat') 2264 param_card.write_inc_file(outfile, ident_card, default) 2265 2266 2267 if mode in ['run', 'all']: 2268 if not hasattr(self, 'run_card'): 2269 run_card = banner_mod.RunCard(opt['run_card']) 2270 else: 2271 run_card = self.run_card 2272 if self.ninitial == 1: 2273 run_card['lpp1'] = 0 2274 run_card['lpp2'] = 0 2275 run_card['ebeam1'] = 0 2276 run_card['ebeam2'] = 0 2277 2278 run_card.write_include_file(pjoin(opt['output_dir'],'run_card.inc'))
2279 2280 ############################################################################
2281 - def do_survey(self, line):
2282 """Advanced commands: launch survey for the current process """ 2283 2284 2285 args = self.split_arg(line) 2286 # Check argument's validity 2287 self.check_survey(args) 2288 # initialize / remove lhapdf mode 2289 2290 if os.path.exists(pjoin(self.me_dir,'error')): 2291 os.remove(pjoin(self.me_dir,'error')) 2292 2293 self.configure_directory() 2294 # Save original random number 2295 self.random_orig = self.random 2296 logger.info("Using random number seed offset = %s" % self.random) 2297 # Update random number 2298 self.update_random() 2299 self.save_random() 2300 self.update_status('Running Survey', level=None) 2301 if self.cluster_mode: 2302 logger.info('Creating Jobs') 2303 2304 logger.info('Working on SubProcesses') 2305 self.total_jobs = 0 2306 subproc = [l.strip() for l in open(pjoin(self.me_dir,'SubProcesses', 2307 'subproc.mg'))] 2308 #check difficult PS case 2309 if float(self.run_card['mmjj']) > 0.01 * (float(self.run_card['ebeam1'])+float(self.run_card['ebeam2'])): 2310 self.pass_in_difficult_integration_mode() 2311 2312 P_zero_result = [] # check the number of times where they are no phase-space 2313 2314 nb_tot_proc = len(subproc) 2315 for nb_proc,subdir in enumerate(subproc): 2316 self.update_status('Compiling for process %s/%s. <br> (previous processes already running)' % \ 2317 (nb_proc+1,nb_tot_proc), level=None) 2318 subdir = subdir.strip() 2319 Pdir = pjoin(self.me_dir, 'SubProcesses',subdir) 2320 logger.info(' %s ' % subdir) 2321 # clean previous run 2322 for match in glob.glob(pjoin(Pdir, '*ajob*')): 2323 if os.path.basename(match)[:4] in ['ajob', 'wait', 'run.', 'done']: 2324 os.remove(match) 2325 for match in glob.glob(pjoin(Pdir, 'G*')): 2326 if os.path.exists(pjoin(match,'results.dat')): 2327 os.remove(pjoin(match, 'results.dat')) 2328 2329 #compile gensym 2330 self.compile(['gensym'], cwd=Pdir) 2331 if not os.path.exists(pjoin(Pdir, 'gensym')): 2332 raise MadEventError, 'Error make gensym not successful' 2333 2334 # Launch gensym 2335 p = misc.Popen(['./gensym'], stdin=subprocess.PIPE, 2336 stdout=subprocess.PIPE, 2337 stderr=subprocess.STDOUT, cwd=Pdir) 2338 sym_input = "%(points)d %(iterations)d %(accuracy)f \n" % self.opts 2339 (stdout, stderr) = p.communicate(sym_input) 2340 if os.path.exists(pjoin(self.me_dir,'error')): 2341 files.mv(pjoin(self.me_dir,'error'), pjoin(Pdir,'ajob.no_ps.log')) 2342 P_zero_result.append(subdir) 2343 continue 2344 2345 if not os.path.exists(pjoin(Pdir, 'ajob1')) or p.returncode: 2346 logger.critical(stdout) 2347 raise MadEventError, 'Error gensym run not successful' 2348 2349 2350 self.compile(['madevent'], cwd=Pdir) 2351 2352 alljobs = glob.glob(pjoin(Pdir,'ajob*')) 2353 self.total_jobs += len(alljobs) 2354 for i, job in enumerate(alljobs): 2355 job = os.path.basename(job) 2356 self.launch_job('%s' % job, cwd=Pdir, remaining=(len(alljobs)-i-1), 2357 run_type='survey on %s (%s/%s)' % (subdir,nb_proc+1,len(subproc))) 2358 if os.path.exists(pjoin(self.me_dir,'error')): 2359 self.monitor(html=False) 2360 raise MadEventError, 'Error detected Stop running: %s' % \ 2361 open(pjoin(self.me_dir,'error')).read() 2362 2363 # Check if all or only some fails 2364 if P_zero_result: 2365 if len(P_zero_result) == len(subproc): 2366 raise ZeroResult, '%s' % \ 2367 open(pjoin(Pdir,'ajob.no_ps.log')).read() 2368 else: 2369 logger.warning(''' %s SubProcesses doesn\'t have available phase-space. 2370 Please check mass spectrum.''' % ','.join(P_zero_result)) 2371 2372 2373 self.monitor(run_type='All jobs submitted for survey', html=True) 2374 cross, error = sum_html.make_all_html_results(self) 2375 self.results.add_detail('cross', cross) 2376 self.results.add_detail('error', error) 2377 self.update_status('End survey', 'parton', makehtml=False)
2378 2379 ############################################################################
2380 - def pass_in_difficult_integration_mode(self):
2381 """be more secure for the integration to not miss it due to strong cut""" 2382 2383 # improve survey options if default 2384 if self.opts['points'] == self._survey_options['points'][1]: 2385 self.opts['points'] = 2 * self._survey_options['points'][1] 2386 if self.opts['iterations'] == self._survey_options['iterations'][1]: 2387 self.opts['iterations'] = 1 + self._survey_options['iterations'][1] 2388 if self.opts['accuracy'] == self._survey_options['accuracy'][1]: 2389 self.opts['accuracy'] = self._survey_options['accuracy'][1]/2 2390 2391 # Modify run_config.inc in order to improve the refine 2392 conf_path = pjoin(self.me_dir, 'Source','run_config.inc') 2393 files.cp(conf_path, conf_path + '.bk') 2394 2395 text = open(conf_path).read() 2396 text = re.sub('''\(min_events = \d+\)''', '''(min_events = 7500 )''', text) 2397 text = re.sub('''\(max_events = \d+\)''', '''(max_events = 20000 )''', text) 2398 fsock = open(conf_path, 'w') 2399 fsock.write(text) 2400 fsock.close() 2401 2402 # Compile 2403 for name in ['../bin/internal/gen_ximprove', 'all', 2404 '../bin/internal/combine_events']: 2405 self.compile(arg=[name], cwd=os.path.join(self.me_dir, 'Source'))
2406 2407 2408 2409 2410 2411 2412 2413 ############################################################################
2414 - def do_refine(self, line):
2415 """Advanced commands: launch survey for the current process """ 2416 devnull = open(os.devnull, 'w') 2417 self.nb_refine += 1 2418 args = self.split_arg(line) 2419 # Check argument's validity 2420 self.check_refine(args) 2421 2422 precision = args[0] 2423 if len(args) == 2: 2424 max_process = args[1] 2425 else: 2426 max_process = 5 2427 2428 # initialize / remove lhapdf mode 2429 self.configure_directory() 2430 2431 # Update random number 2432 self.update_random() 2433 self.save_random() 2434 2435 if self.cluster_mode: 2436 logger.info('Creating Jobs') 2437 self.update_status('Refine results to %s' % precision, level=None) 2438 2439 self.total_jobs = 0 2440 subproc = [l.strip() for l in open(pjoin(self.me_dir,'SubProcesses', 2441 'subproc.mg'))] 2442 for nb_proc,subdir in enumerate(subproc): 2443 subdir = subdir.strip() 2444 Pdir = pjoin(self.me_dir, 'SubProcesses',subdir) 2445 bindir = pjoin(os.path.relpath(self.dirbin, Pdir)) 2446 2447 logger.info(' %s ' % subdir) 2448 # clean previous run 2449 for match in glob.glob(pjoin(Pdir, '*ajob*')): 2450 if os.path.basename(match)[:4] in ['ajob', 'wait', 'run.', 'done']: 2451 os.remove(match) 2452 2453 proc = misc.Popen([pjoin(bindir, 'gen_ximprove')], 2454 stdout=devnull, 2455 stdin=subprocess.PIPE, 2456 cwd=Pdir) 2457 proc.communicate('%s %s T\n' % (precision, max_process)) 2458 2459 if os.path.exists(pjoin(Pdir, 'ajob1')): 2460 self.compile(['madevent'], cwd=Pdir) 2461 alljobs = glob.glob(pjoin(Pdir,'ajob*')) 2462 2463 #remove associated results.dat (ensure to not mix with all data) 2464 Gre = re.compile("\s*j=(G[\d\.\w]+)") 2465 for job in alljobs: 2466 Gdirs = Gre.findall(open(job).read()) 2467 for Gdir in Gdirs: 2468 if os.path.exists(pjoin(Pdir, Gdir, 'results.dat')): 2469 os.remove(pjoin(Pdir, Gdir,'results.dat')) 2470 2471 nb_tot = len(alljobs) 2472 self.total_jobs += nb_tot 2473 for i, job in enumerate(alljobs): 2474 job = os.path.basename(job) 2475 self.launch_job('%s' % job, cwd=Pdir, remaining=(nb_tot-i-1), 2476 run_type='Refine number %s on %s (%s/%s)' % 2477 (self.nb_refine, subdir, nb_proc+1, len(subproc))) 2478 self.monitor(run_type='All job submitted for refine number %s' % self.nb_refine, 2479 html=True) 2480 2481 self.update_status("Combining runs", level='parton') 2482 try: 2483 os.remove(pjoin(Pdir, 'combine_runs.log')) 2484 except Exception: 2485 pass 2486 2487 bindir = pjoin(os.path.relpath(self.dirbin, pjoin(self.me_dir,'SubProcesses'))) 2488 2489 combine_runs.CombineRuns(self.me_dir) 2490 2491 cross, error = sum_html.make_all_html_results(self) 2492 self.results.add_detail('cross', cross) 2493 self.results.add_detail('error', error) 2494 2495 self.update_status('finish refine', 'parton', makehtml=False) 2496 devnull.close()
2497 2498 ############################################################################
2499 - def do_combine_events(self, line):
2500 """Advanced commands: Launch combine events""" 2501 2502 args = self.split_arg(line) 2503 # Check argument's validity 2504 self.check_combine_events(args) 2505 2506 self.update_status('Combining Events', level='parton') 2507 try: 2508 os.remove(pjoin(self.me_dir,'SubProcesses', 'combine.log')) 2509 except Exception: 2510 pass 2511 self.cluster.launch_and_wait('../bin/internal/run_combine', 2512 cwd=pjoin(self.me_dir,'SubProcesses'), 2513 stdout=pjoin(self.me_dir,'SubProcesses', 'combine.log'), 2514 required_output=[pjoin(self.me_dir,'SubProcesses', 'combine.log')]) 2515 2516 output = misc.mult_try_open(pjoin(self.me_dir,'SubProcesses','combine.log')).read() 2517 # Store the number of unweighted events for the results object 2518 pat = re.compile(r'''\s*Unweighting\s*selected\s*(\d+)\s*events''') 2519 try: 2520 nb_event = pat.search(output).groups()[0] 2521 except AttributeError: 2522 time.sleep(10) 2523 output = misc.mult_try_open(pjoin(self.me_dir,'SubProcesses','combine.log')).read() 2524 try: 2525 nb_event = pat.search(output).groups()[0] 2526 except AttributeError: 2527 logger.warning('Fail to read the number of unweighted events in the combine.log file') 2528 nb_event = 0 2529 2530 self.results.add_detail('nb_event', nb_event) 2531 2532 2533 # Define The Banner 2534 tag = self.run_card['run_tag'] 2535 # Update the banner with the pythia card 2536 if not self.banner: 2537 self.banner = banner_mod.recover_banner(self.results, 'parton') 2538 self.banner.load_basic(self.me_dir) 2539 # Add cross-section/event information 2540 self.banner.add_generation_info(self.results.current['cross'], nb_event) 2541 if not hasattr(self, 'random_orig'): self.random_orig = 0 2542 self.banner.change_seed(self.random_orig) 2543 if not os.path.exists(pjoin(self.me_dir, 'Events', self.run_name)): 2544 os.mkdir(pjoin(self.me_dir, 'Events', self.run_name)) 2545 self.banner.write(pjoin(self.me_dir, 'Events', self.run_name, 2546 '%s_%s_banner.txt' % (self.run_name, tag))) 2547 2548 2549 self.banner.add_to_file(pjoin(self.me_dir,'Events', 'events.lhe')) 2550 self.banner.add_to_file(pjoin(self.me_dir,'Events', 'unweighted_events.lhe')) 2551 2552 2553 eradir = self.options['exrootanalysis_path'] 2554 madir = self.options['madanalysis_path'] 2555 td = self.options['td_path'] 2556 if eradir and misc.is_executable(pjoin(eradir,'ExRootLHEFConverter')) and\ 2557 os.path.exists(pjoin(self.me_dir, 'Events', 'unweighted_events.lhe')): 2558 if not os.path.exists(pjoin(self.me_dir, 'Events', self.run_name)): 2559 os.mkdir(pjoin(self.me_dir, 'Events', self.run_name)) 2560 self.create_root_file(output='%s/unweighted_events.root' % \ 2561 self.run_name)
2562 2563 2564 2565 2566 2567 ############################################################################
2568 - def do_store_events(self, line):
2569 """Advanced commands: Launch store events""" 2570 2571 args = self.split_arg(line) 2572 # Check argument's validity 2573 self.check_combine_events(args) 2574 self.update_status('Storing parton level results', level='parton') 2575 2576 run = self.run_name 2577 tag = self.run_card['run_tag'] 2578 devnull = open(os.devnull, 'w') 2579 2580 if not os.path.exists(pjoin(self.me_dir, 'Events', run)): 2581 os.mkdir(pjoin(self.me_dir, 'Events', run)) 2582 if not os.path.exists(pjoin(self.me_dir, 'HTML', run)): 2583 os.mkdir(pjoin(self.me_dir, 'HTML', run)) 2584 2585 # 1) Store overall process information 2586 input = pjoin(self.me_dir, 'SubProcesses', 'results.dat') 2587 output = pjoin(self.me_dir, 'SubProcesses', '%s_results.dat' % run) 2588 files.cp(input, output) 2589 2590 # 2) Treat the files present in the P directory 2591 for P_path in SubProcesses.get_subP(self.me_dir): 2592 G_dir = [G for G in os.listdir(P_path) if G.startswith('G') and 2593 os.path.isdir(pjoin(P_path,G))] 2594 for G in G_dir: 2595 G_path = pjoin(P_path,G) 2596 # Remove events file (if present) 2597 if os.path.exists(pjoin(G_path, 'events.lhe')): 2598 os.remove(pjoin(G_path, 'events.lhe')) 2599 # Store results.dat 2600 if os.path.exists(pjoin(G_path, 'results.dat')): 2601 input = pjoin(G_path, 'results.dat') 2602 output = pjoin(G_path, '%s_results.dat' % run) 2603 files.cp(input, output) 2604 # Store log 2605 if os.path.exists(pjoin(G_path, 'log.txt')): 2606 input = pjoin(G_path, 'log.txt') 2607 output = pjoin(G_path, '%s_log.txt' % run) 2608 files.mv(input, output) 2609 # Grid 2610 for name in ['ftn26']: 2611 if os.path.exists(pjoin(G_path, name)): 2612 if os.path.exists(pjoin(G_path, '%s_%s.gz'%(run,name))): 2613 os.remove(pjoin(G_path, '%s_%s.gz'%(run,name))) 2614 input = pjoin(G_path, name) 2615 output = pjoin(G_path, '%s_%s' % (run,name)) 2616 files.mv(input, output) 2617 misc.gzip(pjoin(G_path, output), error=None) 2618 # Delete ftn25 to ensure reproducible runs 2619 if os.path.exists(pjoin(G_path, 'ftn25')): 2620 os.remove(pjoin(G_path, 'ftn25')) 2621 2622 # 3) Update the index.html 2623 misc.call(['%s/gen_cardhtml-pl' % self.dirbin], 2624 cwd=pjoin(self.me_dir)) 2625 2626 # 4) Move the Files present in Events directory 2627 E_path = pjoin(self.me_dir, 'Events') 2628 O_path = pjoin(self.me_dir, 'Events', run) 2629 # The events file 2630 for name in ['events.lhe', 'unweighted_events.lhe']: 2631 if os.path.exists(pjoin(E_path, name)): 2632 if os.path.exists(pjoin(O_path, '%s.gz' % name)): 2633 os.remove(pjoin(O_path, '%s.gz' % name)) 2634 input = pjoin(E_path, name) 2635 output = pjoin(O_path, name) 2636 misc.gzip(input, stdout="%s.gz" % output, error=False) 2637 2638 self.update_status('End Parton', level='parton', makehtml=False) 2639 devnull.close()
2640 2641 ############################################################################
2642 - def do_reweight(self, line):
2643 """ Allow to reweight the events generated with a new choices of model 2644 parameter. 2645 """ 2646 2647 if '-from_cards' in line and not os.path.exists(pjoin(self.me_dir, 'Cards', 'reweight_card.dat')): 2648 return 2649 2650 # Check that MG5 directory is present . 2651 if MADEVENT and not self.options['mg5_path']: 2652 raise self.InvalidCmd, '''The module reweight requires that MG5 is installed on the system. 2653 You can install it and set its path in ./Cards/me5_configuration.txt''' 2654 elif MADEVENT: 2655 sys.path.append(self.options['mg5_path']) 2656 try: 2657 import madgraph.interface.reweight_interface as reweight_interface 2658 except ImportError: 2659 raise self.ConfigurationError, '''Can\'t load Reweight module. 2660 The variable mg5_path might not be correctly configured.''' 2661 2662 self.to_store.append('event') 2663 if not '-from_cards' in line: 2664 self.keep_cards(['reweight_card.dat']) 2665 self.ask_edit_cards(['reweight_card.dat'], 'fixed', plot=False) 2666 2667 # forbid this function to create an empty item in results. 2668 if self.results.current['cross'] == 0 and self.run_name: 2669 self.results.delete_run(self.run_name, self.run_tag) 2670 2671 # load the name of the event file 2672 args = self.split_arg(line) 2673 self.check_decay_events(args) 2674 # args now alway content the path to the valid files 2675 reweight_cmd = reweight_interface.ReweightInterface(args[0]) 2676 reweight_cmd. mother = self 2677 self.update_status('Running Reweight', level='madspin') 2678 2679 2680 path = pjoin(self.me_dir, 'Cards', 'reweight_card.dat') 2681 reweight_cmd.me_dir = self.me_dir 2682 reweight_cmd.import_command_file(path) 2683 2684 # re-define current run 2685 try: 2686 self.results.def_current(self.run_name, self.run_tag) 2687 except Exception: 2688 pass
2689 2690 ############################################################################
2691 - def do_create_gridpack(self, line):
2692 """Advanced commands: Create gridpack from present run""" 2693 2694 self.update_status('Creating gridpack', level='parton') 2695 args = self.split_arg(line) 2696 self.check_combine_events(args) 2697 if not self.run_tag: self.run_tag = 'tag_1' 2698 os.system("sed -i.bak \"s/ *.false.*=.*GridRun/ .true. = GridRun/g\" %s/Cards/grid_card.dat" \ 2699 % self.me_dir) 2700 misc.call(['./bin/internal/restore_data', self.run_name], 2701 cwd=self.me_dir) 2702 misc.call(['./bin/internal/store4grid', 2703 self.run_name, self.run_tag], 2704 cwd=self.me_dir) 2705 misc.call(['./bin/internal/clean'], cwd=self.me_dir) 2706 misc.call(['./bin/internal/make_gridpack'], cwd=self.me_dir) 2707 files.mv(pjoin(self.me_dir, 'gridpack.tar.gz'), 2708 pjoin(self.me_dir, '%s_gridpack.tar.gz' % self.run_name)) 2709 os.system("sed -i.bak \"s/\s*.true.*=.*GridRun/ .false. = GridRun/g\" %s/Cards/grid_card.dat" \ 2710 % self.me_dir) 2711 self.update_status('gridpack created', level='gridpack')
2712 2713 ############################################################################
2714 - def do_pythia(self, line):
2715 """launch pythia""" 2716 2717 # Check argument's validity 2718 args = self.split_arg(line) 2719 if '--no_default' in args: 2720 if not os.path.exists(pjoin(self.me_dir, 'Cards', 'pythia_card.dat')): 2721 return 2722 no_default = True 2723 args.remove('--no_default') 2724 else: 2725 no_default = False 2726 2727 if not self.run_name: 2728 self.check_pythia(args) 2729 self.configure_directory(html_opening =False) 2730 else: 2731 # initialize / remove lhapdf mode 2732 self.configure_directory(html_opening =False) 2733 self.check_pythia(args) 2734 2735 # the args are modify and the last arg is always the mode 2736 if not no_default: 2737 self.ask_pythia_run_configuration(args[-1]) 2738 2739 if self.options['automatic_html_opening']: 2740 misc.open_file(os.path.join(self.me_dir, 'crossx.html')) 2741 self.options['automatic_html_opening'] = False 2742 2743 # Update the banner with the pythia card 2744 if not self.banner: 2745 self.banner = banner_mod.recover_banner(self.results, 'pythia') 2746 2747 2748 2749 pythia_src = pjoin(self.options['pythia-pgs_path'],'src') 2750 2751 self.update_status('Running Pythia', 'pythia') 2752 try: 2753 os.remove(pjoin(self.me_dir,'Events','pythia.done')) 2754 except Exception: 2755 pass 2756 2757 ## LAUNCHING PYTHIA 2758 tag = self.run_tag 2759 pythia_log = pjoin(self.me_dir, 'Events', self.run_name , '%s_pythia.log' % tag) 2760 self.cluster.launch_and_wait('../bin/internal/run_pythia', 2761 argument= [pythia_src], stdout= pythia_log, 2762 stderr=subprocess.STDOUT, 2763 cwd=pjoin(self.me_dir,'Events')) 2764 2765 if not os.path.exists(pjoin(self.me_dir,'Events','pythia.done')): 2766 logger.warning('Fail to produce pythia output. More info in \n %s' % pythia_log) 2767 return 2768 else: 2769 os.remove(pjoin(self.me_dir,'Events','pythia.done')) 2770 2771 self.to_store.append('pythia') 2772 2773 # Find the matched cross-section 2774 if int(self.run_card['ickkw']): 2775 # read the line from the bottom of the file 2776 pythia_log = misc.BackRead(pjoin(self.me_dir,'Events', self.run_name, 2777 '%s_pythia.log' % tag)) 2778 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") 2779 for line in pythia_log: 2780 info = pythiare.search(line) 2781 if not info: 2782 continue 2783 try: 2784 # Pythia cross section in mb, we want pb 2785 sigma_m = float(info.group('xsec').replace('D','E')) *1e9 2786 Nacc = int(info.group('generated')) 2787 Ntry = int(info.group('tried')) 2788 except ValueError: 2789 # xsec is not float - this should not happen 2790 self.results.add_detail('cross_pythia', 0) 2791 self.results.add_detail('nb_event_pythia', 0) 2792 self.results.add_detail('error_pythia', 0) 2793 else: 2794 self.results.add_detail('cross_pythia', sigma_m) 2795 self.results.add_detail('nb_event_pythia', Nacc) 2796 #compute pythia error 2797 error = self.results[self.run_name].return_tag(self.run_tag)['error'] 2798 error_m = math.sqrt((error * Nacc/Ntry)**2 + sigma_m**2 *(1-Nacc/Ntry)/Nacc) 2799 # works both for fixed number of generated events and fixed accepted events 2800 self.results.add_detail('error_pythia', error_m) 2801 break 2802 2803 pythia_log.close() 2804 2805 pydir = pjoin(self.options['pythia-pgs_path'], 'src') 2806 eradir = self.options['exrootanalysis_path'] 2807 madir = self.options['madanalysis_path'] 2808 td = self.options['td_path'] 2809 2810 2811 #Update the banner 2812 self.banner.add(pjoin(self.me_dir, 'Cards','pythia_card.dat')) 2813 if int(self.run_card['ickkw']): 2814 # Add the matched cross-section 2815 if 'MGGenerationInfo' in self.banner: 2816 self.banner['MGGenerationInfo'] += '# Matched Integrated weight (pb) : %s\n' % self.results.current['cross_pythia'] 2817 else: 2818 self.banner['MGGenerationInfo'] = '# Matched Integrated weight (pb) : %s\n' % self.results.current['cross_pythia'] 2819 banner_path = pjoin(self.me_dir, 'Events', self.run_name, '%s_%s_banner.txt' % (self.run_name, tag)) 2820 self.banner.write(banner_path) 2821 2822 # Creating LHE file 2823 self.run_hep2lhe(banner_path) 2824 if int(self.run_card['ickkw']): 2825 misc.gzip(pjoin(self.me_dir,'Events','beforeveto.tree'), 2826 stdout=pjoin(self.me_dir,'Events',self.run_name, tag+'_pythia_beforeveto.tree.gz')) 2827 2828 if self.run_card['use_syst'] in self.true: 2829 # Calculate syscalc info based on syst.dat 2830 try: 2831 self.run_syscalc('Pythia') 2832 except SysCalcError, error: 2833 logger.error(str(error)) 2834 else: 2835 # Store syst.dat 2836 misc.gzip(pjoin(self.me_dir,'Events', 'syst.dat'), 2837 stdout=pjoin(self.me_dir,'Events',self.run_name, tag + '_pythia_syst.dat.gz')) 2838 2839 # Store syscalc.dat 2840 if os.path.exists(pjoin(self.me_dir, 'Events', 'syscalc.dat')): 2841 filename = pjoin(self.me_dir, 'Events' ,self.run_name, 2842 '%s_syscalc.dat' % self.run_tag) 2843 misc.gzip(pjoin(self.me_dir, 'Events','syscalc.dat'), 2844 stdout = "%s.gz" % filename) 2845 2846 # Plot for pythia 2847 self.create_plot('Pythia') 2848 2849 if os.path.exists(pjoin(self.me_dir,'Events','pythia_events.lhe')): 2850 misc.gzip(pjoin(self.me_dir,'Events','pythia_events.lhe'), 2851 stdout=pjoin(self.me_dir,'Events', self.run_name,'%s_pythia_events.lhe.gz' % tag)) 2852 2853 self.update_status('finish', level='pythia', makehtml=False) 2854 self.exec_cmd('pgs --no_default', postcmd=False, printcmd=False) 2855 if self.options['delphes_path']: 2856 self.exec_cmd('delphes --no_default', postcmd=False, printcmd=False) 2857 self.print_results_in_shell(self.results.current)
2858 2859 2860 ################################################################################
2861 - def do_remove(self, line):
2862 """Remove one/all run or only part of it""" 2863 2864 args = self.split_arg(line) 2865 run, tag, mode = self.check_remove(args) 2866 if 'banner' in mode: 2867 mode.append('all') 2868 2869 2870 if run == 'all': 2871 # Check first if they are not a run with a name run. 2872 if os.path.exists(pjoin(self.me_dir, 'Events', 'all')): 2873 logger.warning('A run with name all exists. So we will not supress all processes.') 2874 else: 2875 for match in glob.glob(pjoin(self.me_dir, 'Events','*','*_banner.txt')): 2876 run = match.rsplit(os.path.sep,2)[1] 2877 try: 2878 self.exec_cmd('remove %s %s' % (run, ' '.join(args[1:]) ) ) 2879 except self.InvalidCmd, error: 2880 logger.info(error) 2881 pass # run already clear 2882 return 2883 2884 # Check that run exists 2885 if not os.path.exists(pjoin(self.me_dir, 'Events', run)): 2886 raise self.InvalidCmd('No run \'%s\' detected' % run) 2887 2888 try: 2889 self.resuls.def_current(run) 2890 self.update_status(' Cleaning %s' % run, level=None) 2891 except Exception: 2892 misc.sprint('fail to update results or html status') 2893 pass # Just ensure that html never makes crash this function 2894 2895 2896 # Found the file to delete 2897 2898 to_delete = glob.glob(pjoin(self.me_dir, 'Events', run, '*')) 2899 to_delete += glob.glob(pjoin(self.me_dir, 'HTML', run, '*')) 2900 # forbid the banner to be removed 2901 to_delete = [os.path.basename(f) for f in to_delete if 'banner' not in f] 2902 if tag: 2903 to_delete = [f for f in to_delete if tag in f] 2904 if 'parton' in mode or 'all' in mode: 2905 try: 2906 if self.results[run][0]['tag'] != tag: 2907 raise Exception, 'dummy' 2908 except Exception: 2909 pass 2910 else: 2911 nb_rm = len(to_delete) 2912 if os.path.exists(pjoin(self.me_dir, 'Events', run, 'events.lhe.gz')): 2913 to_delete.append('events.lhe.gz') 2914 if os.path.exists(pjoin(self.me_dir, 'Events', run, 'unweighted_events.lhe.gz')): 2915 to_delete.append('unweighted_events.lhe.gz') 2916 if os.path.exists(pjoin(self.me_dir, 'HTML', run,'plots_parton.html')): 2917 to_delete.append(pjoin(self.me_dir, 'HTML', run,'plots_parton.html')) 2918 if nb_rm != len(to_delete): 2919 logger.warning('Be carefull that partonic information are on the point to be removed.') 2920 if 'all' in mode: 2921 pass # delete everything 2922 else: 2923 if 'pythia' not in mode: 2924 to_delete = [f for f in to_delete if 'pythia' not in f] 2925 if 'pgs' not in mode: 2926 to_delete = [f for f in to_delete if 'pgs' not in f] 2927 if 'delphes' not in mode: 2928 to_delete = [f for f in to_delete if 'delphes' not in f] 2929 if 'parton' not in mode: 2930 to_delete = [f for f in to_delete if 'delphes' in f 2931 or 'pgs' in f 2932 or 'pythia' in f] 2933 if not self.force and len(to_delete): 2934 question = 'Do you want to delete the following files?\n %s' % \ 2935 '\n '.join(to_delete) 2936 ans = self.ask(question, 'y', choices=['y','n']) 2937 else: 2938 ans = 'y' 2939 2940 if ans == 'y': 2941 for file2rm in to_delete: 2942 if os.path.exists(pjoin(self.me_dir, 'Events', run, file2rm)): 2943 try: 2944 os.remove(pjoin(self.me_dir, 'Events', run, file2rm)) 2945 except Exception: 2946 shutil.rmtree(pjoin(self.me_dir, 'Events', run, file2rm)) 2947 else: 2948 try: 2949 os.remove(pjoin(self.me_dir, 'HTML', run, file2rm)) 2950 except Exception: 2951 shutil.rmtree(pjoin(self.me_dir, 'HTML', run, file2rm)) 2952 2953 2954 2955 # Remove file in SubProcess directory 2956 if 'all' in mode or 'channel' in mode: 2957 try: 2958 if tag and self.results[run][0]['tag'] != tag: 2959 raise Exception, 'dummy' 2960 except Exception: 2961 pass 2962 else: 2963 to_delete = glob.glob(pjoin(self.me_dir, 'SubProcesses', '%s*' % run)) 2964 to_delete += glob.glob(pjoin(self.me_dir, 'SubProcesses', '*','%s*' % run)) 2965 to_delete += glob.glob(pjoin(self.me_dir, 'SubProcesses', '*','*','%s*' % run)) 2966 2967 if self.force or len(to_delete) == 0: 2968 ans = 'y' 2969 else: 2970 question = 'Do you want to delete the following files?\n %s' % \ 2971 '\n '.join(to_delete) 2972 ans = self.ask(question, 'y', choices=['y','n']) 2973 2974 if ans == 'y': 2975 for file2rm in to_delete: 2976 os.remove(file2rm) 2977 2978 if 'banner' in mode: 2979 to_delete = glob.glob(pjoin(self.me_dir, 'Events', run, '*')) 2980 if tag: 2981 # remove banner 2982 try: 2983 os.remove(pjoin(self.me_dir, 'Events',run,'%s_%s_banner.txt' % (run,tag))) 2984 except Exception: 2985 logger.warning('fail to remove the banner') 2986 # remove the run from the html output 2987 if run in self.results: 2988 self.results.delete_run(run, tag) 2989 return 2990 elif any(['banner' not in os.path.basename(p) for p in to_delete]): 2991 if to_delete: 2992 raise MadGraph5Error, '''Some output still exists for this run. 2993 Please remove those output first. Do for example: 2994 remove %s all banner 2995 ''' % run 2996 else: 2997 shutil.rmtree(pjoin(self.me_dir, 'Events',run)) 2998 if run in self.results: 2999 self.results.delete_run(run) 3000 return 3001 else: 3002 logger.info('''The banner is not removed. In order to remove it run: 3003 remove %s all banner %s''' % (run, tag and '--tag=%s ' % tag or '')) 3004 3005 # update database. 3006 self.results.clean(mode, run, tag) 3007 self.update_status('', level='all')
3008 3009 3010 3011 ############################################################################
3012 - def do_plot(self, line):
3013 """Create the plot for a given run""" 3014 3015 # Since in principle, all plot are already done automaticaly 3016 self.store_result() 3017 args = self.split_arg(line) 3018 # Check argument's validity 3019 self.check_plot(args) 3020 logger.info('plot for run %s' % self.run_name) 3021 if not self.force: 3022 self.ask_edit_cards([], args, plot=True) 3023 3024 if any([arg in ['all','parton'] for arg in args]): 3025 filename = pjoin(self.me_dir, 'Events', self.run_name, 'unweighted_events.lhe') 3026 if os.path.exists(filename+'.gz'): 3027 misc.gunzip('%s.gz' % filename) 3028 if os.path.exists(filename): 3029 shutil.move(filename, pjoin(self.me_dir, 'Events', 'unweighted_events.lhe')) 3030 self.create_plot('parton') 3031 misc.gzip(pjoin(self.me_dir, 'Events', 'unweighted_events.lhe'), 3032 stdout= "%s.gz" % filename) 3033 else: 3034 logger.info('No valid files for partonic plot') 3035 3036 if any([arg in ['all','pythia'] for arg in args]): 3037 filename = pjoin(self.me_dir, 'Events' ,self.run_name, 3038 '%s_pythia_events.lhe' % self.run_tag) 3039 if os.path.exists(filename+'.gz'): 3040 misc.gunzip("%s.gz" % filename) 3041 if os.path.exists(filename): 3042 shutil.move(filename, pjoin(self.me_dir, 'Events','pythia_events.lhe')) 3043 self.create_plot('Pythia') 3044 misc.gzip(pjoin(self.me_dir, 'Events','pythia_events.lhe'), 3045 stdout= "%s.gz" % filename) 3046 else: 3047 logger.info('No valid files for pythia plot') 3048 3049 3050 if any([arg in ['all','pgs'] for arg in args]): 3051 filename = pjoin(self.me_dir, 'Events', self.run_name, 3052 '%s_pgs_events.lhco' % self.run_tag) 3053 if os.path.exists(filename+'.gz'): 3054 misc.gunzip("%s.gz" % filename) 3055 if os.path.exists(filename): 3056 self.create_plot('PGS') 3057 misc.gzip(filename) 3058 else: 3059 logger.info('No valid files for pgs plot') 3060 3061 if any([arg in ['all','delphes'] for arg in args]): 3062 filename = pjoin(self.me_dir, 'Events', self.run_name, 3063 '%s_delphes_events.lhco' % self.run_tag) 3064 if os.path.exists(filename+'.gz'): 3065 misc.gunzip("%s.gz" % filename) 3066 if os.path.exists(filename): 3067 self.create_plot('Delphes') 3068 misc.gzip(filename) 3069 else: 3070 logger.info('No valid files for delphes plot')
3071 3072 ############################################################################
3073 - def do_syscalc(self, line):
3074 """Evaluate systematics variation weights for a given run""" 3075 3076 # Since in principle, all systematics run are already done automaticaly 3077 self.store_result() 3078 args = self.split_arg(line) 3079 # Check argument's validity 3080 self.check_syscalc(args) 3081 if self.ninitial == 1: 3082 logger.error('SysCalc can\'t be run for decay processes') 3083 return 3084 3085 logger.info('Calculating systematics for run %s' % self.run_name) 3086 3087 self.ask_edit_cards(['run_card'], args) 3088 3089 if any([arg in ['all','parton'] for arg in args]): 3090 filename = pjoin(self.me_dir, 'Events', self.run_name, 'unweighted_events.lhe') 3091 if os.path.exists(filename+'.gz'): 3092 misc.gunzip("%s.gz" % filename) 3093 if os.path.exists(filename): 3094 shutil.move(filename, pjoin(self.me_dir, 'Events', 'unweighted_events.lhe')) 3095 self.run_syscalc('parton') 3096 misc.gzip(pjoin(self.me_dir, 'Events', 'unweighted_events.lhe'), 3097 stdout="%s.gz" % filename) 3098 else: 3099 logger.info('No valid files for parton level systematics run.') 3100 3101 if any([arg in ['all','pythia'] for arg in args]): 3102 filename = pjoin(self.me_dir, 'Events' ,self.run_name, 3103 '%s_pythia_syst.dat' % self.run_tag) 3104 if os.path.exists(filename+'.gz'): 3105 misc.gunzip("%s.gz" % filename) 3106 if os.path.exists(filename): 3107 shutil.move(filename, pjoin(self.me_dir, 'Events','syst.dat')) 3108 try: 3109 self.run_syscalc('Pythia') 3110 except SysCalcError, error: 3111 logger.warning(str(error)) 3112 return 3113 misc.gzip(pjoin(self.me_dir, 'Events','syst.dat'), "%s.gz" % filename) 3114 filename = pjoin(self.me_dir, 'Events' ,self.run_name, 3115 '%s_syscalc.dat' % self.run_tag) 3116 misc.gzip(pjoin(self.me_dir, 'Events','syscalc.dat'), 3117 stdout=filename) 3118 else: 3119 logger.info('No valid files for pythia level')
3120 3121
3122 - def store_result(self):
3123 """ tar the pythia results. This is done when we are quite sure that 3124 the pythia output will not be use anymore """ 3125 3126 if not self.run_name: 3127 return 3128 3129 self.results.save() 3130 3131 3132 if not self.to_store: 3133 return 3134 3135 tag = self.run_card['run_tag'] 3136 self.update_status('storring files of Previous run', level=None,\ 3137 error=True) 3138 if 'event' in self.to_store: 3139 if not os.path.exists(pjoin(self.me_dir, 'Events',self.run_name, 'unweighted_events.lhe.gz')): 3140 misc.gzip(pjoin(self.me_dir,'Events',self.run_name,"unweighted_events.lhe")) 3141 3142 if 'pythia' in self.to_store: 3143 self.update_status('Storing Pythia files of Previous run', level='pythia', error=True) 3144 3145 p = pjoin(self.me_dir,'Events') 3146 n = self.run_name 3147 t = tag 3148 misc.gzip(pjoin(p,'pythia_events.hep'), 3149 stdout=pjoin(p,'%s/%s_pythia_events.hep' % (n,t))) 3150 3151 self.to_store.remove('pythia') 3152 self.update_status('Done', level='pythia',makehtml=False,error=True) 3153 3154 self.to_store = []
3155
3156 - def launch_job(self,exe, cwd=None, stdout=None, argument = [], remaining=0, 3157 run_type='', mode=None, **opt):
3158 """ """ 3159 argument = [str(arg) for arg in argument] 3160 if mode is None: 3161 mode = self.cluster_mode 3162 3163 # ensure that exe is executable 3164 if os.path.exists(exe) and not os.access(exe, os.X_OK): 3165 os.system('chmod +x %s ' % exe) 3166 elif (cwd and os.path.exists(pjoin(cwd, exe))) and not \ 3167 os.access(pjoin(cwd, exe), os.X_OK): 3168 os.system('chmod +x %s ' % pjoin(cwd, exe)) 3169 3170 if mode == 0: 3171 self.update_status((remaining, 1, 3172 self.total_jobs - remaining -1, run_type), level=None, force=False) 3173 start = time.time() 3174 #os.system('cd %s; ./%s' % (cwd,exe)) 3175 status = misc.call(['./'+exe] + argument, cwd=cwd, 3176 stdout=stdout, **opt) 3177 logger.info('%s run in %f s' % (exe, time.time() -start)) 3178 if status: 3179 raise MadGraph5Error, '%s didn\'t stop properly. Stop all computation' % exe 3180 3181 3182 elif mode in [1,2]: 3183 # For condor cluster, create the input/output files 3184 if 'ajob' in exe: 3185 input_files = ['madevent','input_app.txt','symfact.dat','iproc.dat', 3186 pjoin(self.me_dir, 'SubProcesses','randinit')] 3187 output_files = [] 3188 required_output = [] 3189 3190 3191 #Find the correct PDF input file 3192 input_files.append(self.get_pdf_input_filename()) 3193 3194 #Find the correct ajob 3195 Gre = re.compile("\s*j=(G[\d\.\w]+)") 3196 Ire = re 3197 try : 3198 fsock = open(exe) 3199 except Exception: 3200 fsock = open(pjoin(cwd,exe)) 3201 text = fsock.read() 3202 output_files = Gre.findall(text) 3203 if not output_files: 3204 Ire = re.compile("for i in ([\d\.\s]*) ; do") 3205 data = Ire.findall(text) 3206 data = ' '.join(data).split() 3207 for nb in data: 3208 output_files.append('G%s' % nb) 3209 required_output.append('G%s/results.dat' % nb) 3210 else: 3211 for G in output_files: 3212 if os.path.isdir(pjoin(cwd,G)): 3213 input_files.append(G) 3214 required_output.append('%s/results.dat' % G) 3215 3216 #submitting 3217 self.cluster.submit2(exe, stdout=stdout, cwd=cwd, 3218 input_files=input_files, output_files=output_files, 3219 required_output=required_output) 3220 3221 else: 3222 self.cluster.submit(exe, stdout=stdout, cwd=cwd)
3223 3224 3225 ############################################################################
3226 - def find_madevent_mode(self):
3227 """Find if Madevent is in Group mode or not""" 3228 3229 # The strategy is too look in the files Source/run_configs.inc 3230 # if we found: ChanPerJob=3 then it's a group mode. 3231 file_path = pjoin(self.me_dir, 'Source', 'run_config.inc') 3232 text = open(file_path).read() 3233 if re.search(r'''s*parameter\s+\(ChanPerJob=2\)''', text, re.I+re.M): 3234 return 'group' 3235 else: 3236 return 'v4'
3237 3238 ############################################################################
3239 - def monitor(self, run_type='monitor', mode=None, html=False):
3240 """ monitor the progress of running job """ 3241 3242 starttime = time.time() 3243 if mode is None: 3244 mode = self.cluster_mode 3245 if mode > 0: 3246 if html: 3247 update_status = lambda idle, run, finish: \ 3248 self.update_status((idle, run, finish, run_type), level=None, 3249 force=False, starttime=starttime) 3250 else: 3251 update_status = lambda idle, run, finish: None 3252 try: 3253 self.cluster.wait(self.me_dir, update_status) 3254 except Exception, error: 3255 logger.info(error) 3256 if not self.force: 3257 ans = self.ask('Cluster Error detected. Do you want to clean the queue?', 3258 default = 'y', choices=['y','n']) 3259 else: 3260 ans = 'y' 3261 if ans == 'y': 3262 self.cluster.remove() 3263 raise 3264 except KeyboardInterrupt, error: 3265 self.cluster.remove() 3266 raise
3267 3268 3269 3270 ############################################################################
3271 - def configure_directory(self, html_opening=True):
3272 """ All action require before any type of run """ 3273 3274 3275 # Basic check 3276 assert os.path.exists(pjoin(self.me_dir,'SubProcesses')) 3277 3278 #see when the last file was modified 3279 time_mod = max([os.path.getctime(pjoin(self.me_dir,'Cards','run_card.dat')), 3280 os.path.getctime(pjoin(self.me_dir,'Cards','param_card.dat'))]) 3281 if self.configured > time_mod and hasattr(self, 'random'): 3282 return 3283 else: 3284 self.configured = time.time() 3285 self.update_status('compile directory', level=None, update_results=True) 3286 if self.options['automatic_html_opening'] and html_opening: 3287 misc.open_file(os.path.join(self.me_dir, 'crossx.html')) 3288 self.options['automatic_html_opening'] = False 3289 #open only once the web page 3290 # Change current working directory 3291 self.launching_dir = os.getcwd() 3292 3293 # Check if we need the MSSM special treatment 3294 model = self.find_model_name() 3295 if model == 'mssm' or model.startswith('mssm-'): 3296 param_card = pjoin(self.me_dir, 'Cards','param_card.dat') 3297 mg5_param = pjoin(self.me_dir, 'Source', 'MODEL', 'MG5_param.dat') 3298 check_param_card.convert_to_mg5card(param_card, mg5_param) 3299 check_param_card.check_valid_param_card(mg5_param) 3300 3301 # limit the number of event to 100k 3302 self.check_nb_events() 3303 3304 # this is in order to avoid conflicts between runs with and without 3305 # lhapdf 3306 misc.compile(['clean4pdf'], cwd = pjoin(self.me_dir, 'Source')) 3307 3308 # set environment variable for lhapdf. 3309 if self.run_card['pdlabel'] == "lhapdf": 3310 os.environ['lhapdf'] = 'True' 3311 self.link_lhapdf(pjoin(self.me_dir,'lib')) 3312 pdfsetsdir = self.get_lhapdf_pdfsetsdir() 3313 lhaid_list = [int(self.run_card['lhaid'])] 3314 self.copy_lhapdf_set(lhaid_list, pdfsetsdir) 3315 elif 'lhapdf' in os.environ.keys(): 3316 del os.environ['lhapdf'] 3317 if self.run_card['pdlabel'] != "lhapdf": 3318 self.pdffile = None 3319 3320 # set random number 3321 if self.run_card['iseed'] != '0': 3322 self.random = int(self.run_card['iseed']) 3323 self.run_card['iseed'] = '0' 3324 # Reset seed in run_card to 0, to ensure that following runs 3325 # will be statistically independent 3326 text = open(pjoin(self.me_dir, 'Cards','run_card.dat')).read() 3327 (t,n) = re.subn(r'\d+\s*= iseed','0 = iseed',text) 3328 open(pjoin(self.me_dir, 'Cards','run_card.dat'),'w').write(t) 3329 elif os.path.exists(pjoin(self.me_dir,'SubProcesses','randinit')): 3330 for line in open(pjoin(self.me_dir,'SubProcesses','randinit')): 3331 data = line.split('=') 3332 assert len(data) ==2 3333 self.random = int(data[1]) 3334 break 3335 else: 3336 self.random = random.randint(1, 30107) 3337 3338 if self.run_card['ickkw'] == '2': 3339 logger.info('Running with CKKW matching') 3340 self.treat_CKKW_matching() 3341 3342 # create param_card.inc and run_card.inc 3343 self.do_treatcards('') 3344 3345 # Compile 3346 for name in ['../bin/internal/gen_ximprove', 'all', 3347 '../bin/internal/combine_events']: 3348 self.compile(arg=[name], cwd=os.path.join(self.me_dir, 'Source'))
3349 3350 3351 ############################################################################ 3352 ## HELPING ROUTINE 3353 ############################################################################ 3354 @staticmethod
3355 - def check_dir(path, default=''):
3356 """check if the directory exists. if so return the path otherwise the 3357 default""" 3358 3359 if os.path.isdir(path): 3360 return path 3361 else: 3362 return default
3363 3364 ############################################################################
3365 - def set_run_name(self, name, tag=None, level='parton', reload_card=False, 3366 allow_new_tag=True):
3367 """define the run name, the run_tag, the banner and the results.""" 3368 3369 # when are we force to change the tag new_run:previous run requiring changes 3370 upgrade_tag = {'parton': ['parton','pythia','pgs','delphes'], 3371 'pythia': ['pythia','pgs','delphes'], 3372 'pgs': ['pgs'], 3373 'delphes':['delphes'], 3374 'plot':[], 3375 'syscalc':[]} 3376 3377 3378 3379 if name == self.run_name: 3380 if reload_card: 3381 run_card = pjoin(self.me_dir, 'Cards','run_card.dat') 3382 self.run_card = banner_mod.RunCard(run_card) 3383 3384 #check if we need to change the tag 3385 if tag: 3386 self.run_card['run_tag'] = tag 3387 self.run_tag = tag 3388 self.results.add_run(self.run_name, self.run_card) 3389 else: 3390 for tag in upgrade_tag[level]: 3391 if getattr(self.results[self.run_name][-1], tag): 3392 tag = self.get_available_tag() 3393 self.run_card['run_tag'] = tag 3394 self.run_tag = tag 3395 self.results.add_run(self.run_name, self.run_card) 3396 break 3397 return # Nothing to do anymore 3398 3399 # save/clean previous run 3400 if self.run_name: 3401 self.store_result() 3402 # store new name 3403 self.run_name = name 3404 3405 new_tag = False 3406 # First call for this run -> set the banner 3407 self.banner = banner_mod.recover_banner(self.results, level, name) 3408 if 'mgruncard' in self.banner: 3409 self.run_card = self.banner.charge_card('run_card') 3410 else: 3411 # Read run_card 3412 run_card = pjoin(self.me_dir, 'Cards','run_card.dat') 3413 self.run_card = banner_mod.RunCard(run_card) 3414 3415 if tag: 3416 self.run_card['run_tag'] = tag 3417 new_tag = True 3418 elif not self.run_name in self.results and level =='parton': 3419 pass # No results yet, so current tag is fine 3420 elif not self.run_name in self.results: 3421 #This is only for case when you want to trick the interface 3422 logger.warning('Trying to run data on unknown run.') 3423 self.results.add_run(name, self.run_card) 3424 self.results.update('add run %s' % name, 'all', makehtml=False) 3425 else: 3426 for tag in upgrade_tag[level]: 3427 3428 if getattr(self.results[self.run_name][-1], tag): 3429 # LEVEL is already define in the last tag -> need to switch tag 3430 tag = self.get_available_tag() 3431 self.run_card['run_tag'] = tag 3432 new_tag = True 3433 break 3434 if not new_tag: 3435 # We can add the results to the current run 3436 tag = self.results[self.run_name][-1]['tag'] 3437 self.run_card['run_tag'] = tag # ensure that run_tag is correct 3438 3439 if allow_new_tag and (name in self.results and not new_tag): 3440 self.results.def_current(self.run_name) 3441 else: 3442 self.results.add_run(self.run_name, self.run_card) 3443 3444 self.run_tag = self.run_card['run_tag'] 3445 3446 # Return the tag of the previous run having the required data for this 3447 # tag/run to working wel. 3448 if level == 'parton': 3449 return 3450 elif level == 'pythia': 3451 return self.results[self.run_name][0]['tag'] 3452 else: 3453 for i in range(-1,-len(self.results[self.run_name])-1,-1): 3454 tagRun = self.results[self.run_name][i] 3455 if tagRun.pythia: 3456 return tagRun['tag']
3457 3458 3459 3460 3461 3462 3463 3464 3465 ############################################################################
3466 - def find_model_name(self):
3467 """ return the model name """ 3468 if hasattr(self, 'model_name'): 3469 return self.model_name 3470 3471 model = 'sm' 3472 proc = [] 3473 for line in open(os.path.join(self.me_dir,'Cards','proc_card_mg5.dat')): 3474 line = line.split('#')[0] 3475 #line = line.split('=')[0] 3476 if line.startswith('import') and 'model' in line: 3477 model = line.split()[2] 3478 proc = [] 3479 elif line.startswith('generate'): 3480 proc.append(line.split(None,1)[1]) 3481 elif line.startswith('add process'): 3482 proc.append(line.split(None,2)[2]) 3483 3484 self.model = model 3485 self.process = proc 3486 return model
3487 3488 3489 ############################################################################
3490 - def check_nb_events(self):
3491 """Find the number of event in the run_card, and check that this is not 3492 too large""" 3493 3494 3495 nb_event = int(self.run_card['nevents']) 3496 if nb_event > 1000000: 3497 logger.warning("Attempting to generate more than 1M events") 3498 logger.warning("Limiting number to 1M. Use multi_run for larger statistics.") 3499 path = pjoin(self.me_dir, 'Cards', 'run_card.dat') 3500 os.system(r"""perl -p -i.bak -e "s/\d+\s*=\s*nevents/1000000 = nevents/" %s""" \ 3501 % path) 3502 self.run_card['nevents'] = 1000000 3503 3504 return
3505 3506 3507 ############################################################################
3508 - def update_random(self):
3509 """ change random number""" 3510 3511 self.random += 3 3512 if self.random > 30081*30081: # can't use too big random number 3513 raise MadGraph5Error,\ 3514 'Random seed too large ' + str(self.random) + ' > 30081*30081'
3515 3516 ############################################################################
3517 - def save_random(self):
3518 """save random number in appropirate file""" 3519 3520 fsock = open(pjoin(self.me_dir, 'SubProcesses','randinit'),'w') 3521 fsock.writelines('r=%s\n' % self.random)
3522
3523 - def do_quit(self, *args, **opts):
3524 3525 common_run.CommonRunCmd.do_quit(self, *args, **opts) 3526 return CmdExtended.do_quit(self, *args, **opts)
3527 3528 ############################################################################
3529 - def treat_ckkw_matching(self):
3530 """check for ckkw""" 3531 3532 lpp1 = self.run_card['lpp1'] 3533 lpp2 = self.run_card['lpp2'] 3534 e1 = self.run_card['ebeam1'] 3535 e2 = self.run_card['ebeam2'] 3536 pd = self.run_card['pdlabel'] 3537 lha = self.run_card['lhaid'] 3538 xq = self.run_card['xqcut'] 3539 translation = {'e1': e1, 'e2':e2, 'pd':pd, 3540 'lha':lha, 'xq':xq} 3541 3542 if lpp1 or lpp2: 3543 # Remove ':s from pd 3544 if pd.startswith("'"): 3545 pd = pd[1:] 3546 if pd.endswith("'"): 3547 pd = pd[:-1] 3548 3549 if xq >2 or xq ==2: 3550 xq = 2 3551 3552 # find data file 3553 if pd == "lhapdf": 3554 issudfile = 'lib/issudgrid-%(e1)s-%(e2)s-%(pd)s-%(lha)s-%(xq)s.dat.gz' 3555 else: 3556 issudfile = 'lib/issudgrid-%(e1)s-%(e2)s-%(pd)s-%(xq)s.dat.gz' 3557 if self.web: 3558 issudfile = pjoin(self.webbin, issudfile % translation) 3559 else: 3560 issudfile = pjoin(self.me_dir, issudfile % translation) 3561 3562 logger.info('Sudakov grid file: %s' % issudfile) 3563 3564 # check that filepath exists 3565 if os.path.exists(issudfile): 3566 path = pjoin(self.me_dir, 'lib', 'issudgrid.dat') 3567 misc.gunzip(issudfile, keep=True, stdout=path) 3568 else: 3569 msg = 'No sudakov grid file for parameter choice. Start to generate it. This might take a while' 3570 logger.info(msg) 3571 self.update_status('GENERATE SUDAKOF GRID', level='parton') 3572 3573 for i in range(-2,6): 3574 self.cluster.submit('%s/gensudgrid ' % self.dirbin, 3575 arguments = [i], 3576 cwd=self.me_dir, 3577 stdout=open(pjoin(self.me_dir, 'gensudgrid%s.log' % i,'w'))) 3578 self.monitor() 3579 for i in range(-2,6): 3580 path = pjoin(self.me_dir, 'lib', 'issudgrid.dat') 3581 os.system('cat %s/gensudgrid%s.log >> %s' % (self.me_dir, path)) 3582 misc.gzip(path, stdout=issudfile)
3583 3584 ############################################################################
3585 - def create_root_file(self, input='unweighted_events.lhe', 3586 output='unweighted_events.root' ):
3587 """create the LHE root file """ 3588 self.update_status('Creating root files', level='parton') 3589 3590 eradir = self.options['exrootanalysis_path'] 3591 try: 3592 misc.call(['%s/ExRootLHEFConverter' % eradir, 3593 input, output], 3594 cwd=pjoin(self.me_dir, 'Events')) 3595 except Exception: 3596 logger.warning('fail to produce Root output [problem with ExRootAnalysis]')
3597
3598 - def run_syscalc(self, mode='parton', event_path=None, output=None):
3599 """create the syscalc output""" 3600 3601 logger.info('running syscalc on mode %s' % mode) 3602 if self.run_card['use_syst'] not in self.true: 3603 return 3604 3605 scdir = self.options['syscalc_path'] 3606 tag = self.run_card['run_tag'] 3607 card = pjoin(self.me_dir, 'bin','internal', 'syscalc_card.dat') 3608 template = open(pjoin(self.me_dir, 'bin','internal', 'syscalc_template.dat')).read() 3609 self.run_card['sys_pdf'] = self.run_card['sys_pdf'].split('#',1)[0].replace('&&',' \n ') 3610 # check if the scalecorrelation parameter is define: 3611 if not 'sys_scalecorrelation' in self.run_card: 3612 self.run_card['sys_scalecorrelation'] = -1 3613 open(card,'w').write(template % self.run_card) 3614 3615 if not scdir or \ 3616 not os.path.exists(card): 3617 return False 3618 event_dir = pjoin(self.me_dir, 'Events') 3619 3620 if not event_path: 3621 if mode == 'parton': 3622 event_path = pjoin(event_dir,'unweighted_events.lhe') 3623 output = pjoin(event_dir, 'syscalc.lhe') 3624 elif mode == 'Pythia': 3625 if 'mgpythiacard' in self.banner: 3626 pat = re.compile('''^\s*qcut\s*=\s*([\+\-\d.e]*)''', re.M+re.I) 3627 data = pat.search(self.banner['mgpythiacard']) 3628 if data: 3629 qcut = float(data.group(1)) 3630 xqcut = abs(self.run_card['xqcut']) 3631 for value in self.run_card['sys_matchscale'].split(): 3632 if float(value) < qcut: 3633 raise SysCalcError, 'qcut value for sys_matchscale lower than qcut in pythia_card. Bypass syscalc' 3634 if float(value) < xqcut: 3635 raise SysCalcError, 'qcut value for sys_matchscale lower than xqcut in run_card. Bypass syscalc' 3636 3637 3638 event_path = pjoin(event_dir,'syst.dat') 3639 output = pjoin(event_dir, 'syscalc.dat') 3640 else: 3641 raise self.InvalidCmd, 'Invalid mode %s' % mode 3642 3643 if not os.path.exists(event_path): 3644 if os.path.exists(event_path+'.gz'): 3645 misc.gzip(event_path) 3646 else: 3647 raise SysCalcError, 'Events file %s does not exits' % event_path 3648 3649 self.update_status('Calculating systematics for %s level' % mode, level = mode.lower()) 3650 try: 3651 proc = misc.call([os.path.join(scdir, 'sys_calc'), 3652 event_path, card, output], 3653 stdout = open(pjoin(event_dir, self.run_name, '%s_%s_syscalc.log' % (tag,mode)),'w'), 3654 stderr = subprocess.STDOUT, 3655 cwd=event_dir) 3656 # Wait 5 s to make sure file is finished writing 3657 time.sleep(5) 3658 except OSError, error: 3659 logger.error('fail to run syscalc: %s. Please check that SysCalc is correctly installed.' % error) 3660 else: 3661 if mode == 'parton' and os.path.exists(output): 3662 files.mv(output, event_path) 3663 else: 3664 logger.warning('SysCalc Failed. Please read the associate log to see the reason. Did you install the associate PDF set?') 3665 self.update_status('End syscalc for %s level' % mode, level = mode.lower(), 3666 makehtml=False) 3667 3668 return True
3669 3670 3671 3672 ############################################################################
3673 - def ask_run_configuration(self, mode=None):
3674 """Ask the question when launching generate_events/multi_run""" 3675 3676 available_mode = ['0'] 3677 void = 'NOT INSTALLED' 3678 switch_order = ['pythia', 'pgs', 'delphes', 'madspin', 'reweight'] 3679 switch = {'pythia': void, 'pgs': void, 'delphes': void, 3680 'madspin': void, 'reweight': void} 3681 description = {'pythia': 'Run the pythia shower/hadronization:', 3682 'pgs': 'Run PGS as detector simulator:', 3683 'delphes':'Run Delphes as detector simulator:', 3684 'madspin':'Decay particles with the MadSpin module:', 3685 'reweight':'Add weight to events based on coupling parameters:', 3686 } 3687 force_switch = {('pythia', 'OFF'): {'pgs': 'OFF', 'delphes': 'OFF'}, 3688 ('pgs', 'ON'): {'pythia':'ON'}, 3689 ('delphes', 'ON'): {'pythia': 'ON'}} 3690 switch_assign = lambda key, value: switch.__setitem__(key, value if switch[key] != void else void ) 3691 3692 3693 # Init the switch value according to the current status 3694 if self.options['pythia-pgs_path']: 3695 available_mode.append('1') 3696 available_mode.append('2') 3697 if os.path.exists(pjoin(self.me_dir,'Cards','pythia_card.dat')): 3698 switch['pythia'] = 'ON' 3699 else: 3700 switch['pythia'] = 'OFF' 3701 if os.path.exists(pjoin(self.me_dir,'Cards','pgs_card.dat')): 3702 switch['pgs'] = 'ON' 3703 else: 3704 switch['pgs'] = 'OFF' 3705 if self.options['delphes_path']: 3706 available_mode.append('3') 3707 if os.path.exists(pjoin(self.me_dir,'Cards','delphes_card.dat')): 3708 switch['delphes'] = 'ON' 3709 else: 3710 switch['delphes'] = 'OFF' 3711 3712 # Check switch status for MS/reweight 3713 if not MADEVENT or self.options['mg5_path']: 3714 available_mode.append('4') 3715 available_mode.append('5') 3716 if os.path.exists(pjoin(self.me_dir,'Cards','madspin_card.dat')): 3717 switch['madspin'] = 'ON' 3718 else: 3719 switch['madspin'] = 'OFF' 3720 if os.path.exists(pjoin(self.me_dir,'Cards','reweight_card.dat')): 3721 switch['reweight'] = 'ON' 3722 else: 3723 switch['reweight'] = 'OFF' 3724 3725 3726 3727 options = list(available_mode) + ['auto', 'done'] 3728 for id, key in enumerate(switch_order): 3729 if switch[key] != void: 3730 options += ['%s=%s' % (key, s) for s in ['ON','OFF']] 3731 options.append(key) 3732 options.append('parton') 3733 3734 #ask the question 3735 if mode or not self.force: 3736 answer = '' 3737 while answer not in ['0', 'done', 'auto']: 3738 if mode: 3739 answer = mode 3740 else: 3741 switch_format = " %i %-50s %10s=%s\n" 3742 question = "The following switches determine which programs are run:\n" 3743 for id, key in enumerate(switch_order): 3744 question += switch_format % (id+1, description[key], key, switch[key]) 3745 question += ' Either type the switch number (1 to %s) to change its default setting,\n' % (id+1) 3746 question += ' or set any switch explicitly (e.g. type \'madspin=ON\' at the prompt)\n' 3747 question += ' Type \'0\', \'auto\', \'done\' or just press enter when you are done.\n' 3748 answer = self.ask(question, '0', options) 3749 if answer.isdigit() and answer != '0': 3750 key = switch_order[int(answer) - 1] 3751 answer = '%s=%s' % (key, 'ON' if switch[key] == 'OFF' else 'OFF') 3752 3753 if '=' in answer: 3754 key, status = answer.split('=') 3755 switch[key] = status 3756 if (key, status) in force_switch: 3757 for key2, status2 in force_switch[(key, status)].items(): 3758 if switch[key2] not in [status2, void]: 3759 logger.info('For coherence \'%s\' is set to \'%s\'' 3760 % (key2, status2), '$MG:color:BLACK') 3761 switch[key2] = status2 3762 elif answer in ['0', 'auto', 'done']: 3763 continue 3764 else: 3765 logger.info('pass in %s only mode' % answer, '$MG:color:BLACK') 3766 switch_assign('madspin', 'OFF') 3767 switch_assign('reweight', 'OFF') 3768 if answer == 'parton': 3769 switch_assign('pythia', 'OFF') 3770 switch_assign('pgs', 'OFF') 3771 switch_assign('delphes', 'OFF') 3772 elif answer == 'pythia': 3773 switch_assign('pythia', 'ON') 3774 switch_assign('pgs', 'OFF') 3775 switch_assign('delphes', 'OFF') 3776 elif answer == 'pgs': 3777 switch_assign('pythia', 'ON') 3778 switch_assign('pgs', 'ON') 3779 switch_assign('delphes', 'OFF') 3780 elif answer == 'delphes': 3781 switch_assign('pythia', 'ON') 3782 switch_assign('pgs', 'OFF') 3783 switch_assign('delphes', 'ON') 3784 elif answer == 'madspin': 3785 switch_assign('madspin', 'ON') 3786 switch_assign('pythia', 'OFF') 3787 switch_assign('pgs', 'OFF') 3788 switch_assign('delphes', 'OF') 3789 elif answer == 'reweight': 3790 switch_assign('reweight', 'ON') 3791 switch_assign('pythia', 'OFF') 3792 switch_assign('pgs', 'OFF') 3793 switch_assign('delphes', 'OFF') 3794 3795 3796 if mode: 3797 answer = '0' #mode auto didn't pass here (due to the continue) 3798 else: 3799 answer = 'auto' 3800 3801 # Now that we know in which mode we are check that all the card 3802 #exists (copy default if needed) 3803 3804 cards = ['param_card.dat', 'run_card.dat'] 3805 if switch['pythia'] == 'ON': 3806 cards.append('pythia_card.dat') 3807 if switch['pgs'] == 'ON': 3808 cards.append('pgs_card.dat') 3809 if switch['delphes'] == 'ON': 3810 cards.append('delphes_card.dat') 3811 delphes3 = True 3812 if os.path.exists(pjoin(self.options['delphes_path'], 'data')): 3813 delphes3 = False 3814 cards.append('delphes_trigger.dat') 3815 if switch['madspin'] == 'ON': 3816 cards.append('madspin_card.dat') 3817 if switch['reweight'] == 'ON': 3818 cards.append('reweight_card.dat') 3819 self.keep_cards(cards) 3820 if self.force: 3821 self.check_param_card(pjoin(self.me_dir,'Cards','param_card.dat' )) 3822 return 3823 3824 if answer == 'auto': 3825 self.ask_edit_cards(cards, mode='auto') 3826 else: 3827 self.ask_edit_cards(cards) 3828 return
3829 3830 ############################################################################
3831 - def ask_pythia_run_configuration(self, mode=None):
3832 """Ask the question when launching pythia""" 3833 3834 available_mode = ['0', '1', '2'] 3835 if self.options['delphes_path']: 3836 available_mode.append('3') 3837 name = {'0': 'auto', '1': 'pythia', '2':'pgs', '3':'delphes'} 3838 options = available_mode + [name[val] for val in available_mode] 3839 question = """Which programs do you want to run? 3840 0 / auto : running existing card 3841 1 / pythia : Pythia 3842 2 / pgs : Pythia + PGS\n""" 3843 if '3' in available_mode: 3844 question += """ 3 / delphes : Pythia + Delphes.\n""" 3845 3846 if not self.force: 3847 if not mode: 3848 mode = self.ask(question, '0', options) 3849 elif not mode: 3850 mode = 'auto' 3851 3852 if mode.isdigit(): 3853 mode = name[mode] 3854 3855 auto = False 3856 if mode == 'auto': 3857 auto = True 3858 if os.path.exists(pjoin(self.me_dir, 'Cards', 'pgs_card.dat')): 3859 mode = 'pgs' 3860 elif os.path.exists(pjoin(self.me_dir, 'Cards', 'delphes_card.dat')): 3861 mode = 'delphes' 3862 else: 3863 mode = 'pythia' 3864 logger.info('Will run in mode %s' % mode) 3865 3866 # Now that we know in which mode we are check that all the card 3867 #exists (copy default if needed) remove pointless one 3868 cards = ['pythia_card.dat'] 3869 if mode == 'pgs': 3870 cards.append('pgs_card.dat') 3871 if mode == 'delphes': 3872 cards.append('delphes_card.dat') 3873 delphes3 = True 3874 if os.path.exists(pjoin(self.options['delphes_path'], 'data')): 3875 delphes3 = False 3876 cards.append('delphes_trigger.dat') 3877 self.keep_cards(cards) 3878 3879 if self.force: 3880 return mode 3881 3882 if auto: 3883 self.ask_edit_cards(cards, mode='auto') 3884 else: 3885 self.ask_edit_cards(cards) 3886 3887 return mode
3888
3889 3890 3891 3892 3893 #=============================================================================== 3894 # MadEventCmd 3895 #=============================================================================== 3896 -class MadEventCmdShell(MadEventCmd, cmd.CmdShell):
3897 """The command line processor of MadGraph"""
3898
3899 3900 3901 #=============================================================================== 3902 # HELPING FUNCTION For Subprocesses 3903 #=============================================================================== 3904 -class SubProcesses(object):
3905 3906 name_to_pdg = {} 3907 3908 @classmethod
3909 - def clean(cls):
3910 cls.name_to_pdg = {}
3911 3912 @staticmethod
3913 - def get_subP(me_dir):
3914 """return the list of Subprocesses""" 3915 3916 out = [] 3917 for line in open(pjoin(me_dir,'SubProcesses', 'subproc.mg')): 3918 if not line: 3919 continue 3920 name = line.strip() 3921 if os.path.exists(pjoin(me_dir, 'SubProcesses', name)): 3922 out.append(pjoin(me_dir, 'SubProcesses', name)) 3923 3924 return out
3925 3926 3927 3928 @staticmethod
3929 - def get_subP_info(path):
3930 """ return the list of processes with their name""" 3931 3932 nb_sub = 0 3933 names = {} 3934 old_main = '' 3935 3936 if not os.path.exists(os.path.join(path,'processes.dat')): 3937 return SubProcesses.get_subP_info_v4(path) 3938 3939 for line in open(os.path.join(path,'processes.dat')): 3940 main = line[:8].strip() 3941 if main == 'mirror': 3942 main = old_main 3943 if line[8:].strip() == 'none': 3944 continue 3945 else: 3946 main = int(main) 3947 old_main = main 3948 3949 sub_proccess = line[8:] 3950 nb_sub += sub_proccess.count(',') + 1 3951 if main in names: 3952 names[main] += [sub_proccess.split(',')] 3953 else: 3954 names[main]= [sub_proccess.split(',')] 3955 3956 return names
3957 3958 @staticmethod
3959 - def get_subP_info_v4(path):
3960 """ return the list of processes with their name in case without grouping """ 3961 3962 nb_sub = 0 3963 names = {'':[[]]} 3964 path = os.path.join(path, 'auto_dsig.f') 3965 found = 0 3966 for line in open(path): 3967 if line.startswith('C Process:'): 3968 found += 1 3969 names[''][0].append(line[15:]) 3970 elif found >1: 3971 break 3972 return names
3973 3974 3975 @staticmethod
3976 - def get_subP_ids(path):
3977 """return the pdg codes of the particles present in the Subprocesses""" 3978 3979 all_ids = [] 3980 for line in open(pjoin(path, 'leshouche.inc')): 3981 if not 'IDUP' in line: 3982 continue 3983 particles = re.search("/([\d,-]+)/", line) 3984 all_ids.append([int(p) for p in particles.group(1).split(',')]) 3985 return all_ids
3986
3987 3988 #=============================================================================== 3989 -class GridPackCmd(MadEventCmd):
3990 """The command for the gridpack --Those are not suppose to be use interactively--""" 3991
3992 - def __init__(self, me_dir = None, nb_event=0, seed=0, *completekey, **stdin):
3993 """Initialize the command and directly run""" 3994 3995 # Initialize properly 3996 3997 MadEventCmd.__init__(self, me_dir, *completekey, **stdin) 3998 self.run_mode = 0 3999 self.random = seed 4000 self.random_orig = self.random 4001 self.options['automatic_html_opening'] = False 4002 # Now it's time to run! 4003 if me_dir and nb_event and seed: 4004 self.launch(nb_event, seed) 4005 else: 4006 raise MadGraph5Error,\ 4007 'Gridpack run failed: ' + str(me_dir) + str(nb_event) + \ 4008 str(seed)
4009
4010 - def launch(self, nb_event, seed):
4011 """ launch the generation for the grid """ 4012 4013 # 1) Restore the default data 4014 logger.info('generate %s events' % nb_event) 4015 self.set_run_name('GridRun_%s' % seed) 4016 self.update_status('restoring default data', level=None) 4017 misc.call([pjoin(self.me_dir,'bin','internal','restore_data'), 4018 'default'], 4019 cwd=self.me_dir) 4020 4021 # 2) Run the refine for the grid 4022 self.update_status('Generating Events', level=None) 4023 #misc.call([pjoin(self.me_dir,'bin','refine4grid'), 4024 # str(nb_event), '0', 'Madevent','1','GridRun_%s' % seed], 4025 # cwd=self.me_dir) 4026 self.refine4grid(nb_event) 4027 4028 # 3) Combine the events/pythia/... 4029 self.exec_cmd('combine_events') 4030 self.exec_cmd('store_events') 4031 self.print_results_in_shell(self.results.current) 4032 self.exec_cmd('decay_events -from_cards', postcmd=False)
4033
4034 - def refine4grid(self, nb_event):
4035 """Special refine for gridpack run.""" 4036 self.nb_refine += 1 4037 4038 precision = nb_event 4039 4040 # initialize / remove lhapdf mode 4041 # self.configure_directory() # All this has been done before 4042 self.cluster_mode = 0 # force single machine 4043 4044 # Store seed in randinit file, to be read by ranmar.f 4045 self.save_random() 4046 4047 self.update_status('Refine results to %s' % precision, level=None) 4048 logger.info("Using random number seed offset = %s" % self.random) 4049 4050 self.total_jobs = 0 4051 subproc = [P for P in os.listdir(pjoin(self.me_dir,'SubProcesses')) if 4052 P.startswith('P') and os.path.isdir(pjoin(self.me_dir,'SubProcesses', P))] 4053 devnull = open(os.devnull, 'w') 4054 for nb_proc,subdir in enumerate(subproc): 4055 subdir = subdir.strip() 4056 Pdir = pjoin(self.me_dir, 'SubProcesses',subdir) 4057 bindir = pjoin(os.path.relpath(self.dirbin, Pdir)) 4058 4059 logger.info(' %s ' % subdir) 4060 # clean previous run 4061 for match in glob.glob(pjoin(Pdir, '*ajob*')): 4062 if os.path.basename(match)[:4] in ['ajob', 'wait', 'run.', 'done']: 4063 os.remove(pjoin(Pdir, match)) 4064 4065 4066 logfile = pjoin(Pdir, 'gen_ximprove.log') 4067 misc.call([pjoin(bindir, 'gen_ximprove')], 4068 stdin=subprocess.PIPE, 4069 stdout=open(logfile,'w'), 4070 cwd=Pdir) 4071 4072 if os.path.exists(pjoin(Pdir, 'ajob1')): 4073 alljobs = glob.glob(pjoin(Pdir,'ajob*')) 4074 nb_tot = len(alljobs) 4075 self.total_jobs += nb_tot 4076 for i, job in enumerate(alljobs): 4077 job = os.path.basename(job) 4078 self.launch_job('%s' % job, cwd=Pdir, remaining=(nb_tot-i-1), 4079 run_type='Refine number %s on %s (%s/%s)' % 4080 (self.nb_refine, subdir, nb_proc+1, len(subproc))) 4081 if os.path.exists(pjoin(self.me_dir,'error')): 4082 self.monitor(html=True) 4083 raise MadEventError, \ 4084 'Error detected in dir %s: %s' % \ 4085 (Pdir, open(pjoin(self.me_dir,'error')).read()) 4086 self.monitor(run_type='All job submitted for refine number %s' % 4087 self.nb_refine) 4088 4089 self.update_status("Combining runs", level='parton') 4090 try: 4091 os.remove(pjoin(Pdir, 'combine_runs.log')) 4092 except Exception: 4093 pass 4094 4095 bindir = pjoin(os.path.relpath(self.dirbin, pjoin(self.me_dir,'SubProcesses'))) 4096 combine_runs.CombineRuns(self.me_dir) 4097 4098 #update html output 4099 cross, error = sum_html.make_all_html_results(self) 4100 self.results.add_detail('cross', cross) 4101 self.results.add_detail('error', error) 4102 4103 4104 self.update_status('finish refine', 'parton', makehtml=False) 4105 devnull.close()
4106 4107 4108 4109 AskforEditCard = common_run.AskforEditCard 4110