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