Package madgraph :: Package various :: Module misc
[hide private]
[frames] | no frames]

Source Code for Module madgraph.various.misc

   1  ################################################################################ 
   2  # 
   3  # Copyright (c) 2009 The MadGraph5_aMC@NLO Development team and Contributors 
   4  # 
   5  # This file is a part of the MadGraph5_aMC@NLO project, an application which  
   6  # automatically generates Feynman diagrams and matrix elements for arbitrary 
   7  # high-energy processes in the Standard Model and beyond. 
   8  # 
   9  # It is subject to the MadGraph5_aMC@NLO license which should accompany this  
  10  # distribution. 
  11  # 
  12  # For more information, visit madgraph.phys.ucl.ac.be and amcatnlo.web.cern.ch 
  13  # 
  14  ################################################################################ 
  15  """A set of functions performing routine administrative I/O tasks.""" 
  16   
  17  import contextlib 
  18  import itertools 
  19  import logging 
  20  import os 
  21  import re 
  22  import signal 
  23  import subprocess 
  24  import sys 
  25  import StringIO 
  26  import sys 
  27  import optparse 
  28  import time 
  29  import shutil 
  30  import traceback 
  31  import gzip as ziplib 
  32   
  33  try: 
  34      # Use in MadGraph 
  35      import madgraph 
  36  except Exception, error: 
  37      # Use in MadEvent 
  38      import internal 
  39      from internal import MadGraph5Error, InvalidCmd 
  40      import internal.files as files 
  41      MADEVENT = True     
  42  else: 
  43      from madgraph import MadGraph5Error, InvalidCmd 
  44      import madgraph.iolibs.files as files 
  45      MADEVENT = False 
  46   
  47       
  48  logger = logging.getLogger('cmdprint.ext_program') 
  49  logger_stderr = logging.getLogger('madevent.misc') 
  50  pjoin = os.path.join 
51 52 #=============================================================================== 53 # parse_info_str 54 #=============================================================================== 55 -def parse_info_str(fsock):
56 """Parse a newline separated list of "param=value" as a dictionnary 57 """ 58 59 info_dict = {} 60 pattern = re.compile("(?P<name>\w*)\s*=\s*(?P<value>.*)", 61 re.IGNORECASE | re.VERBOSE) 62 for entry in fsock: 63 entry = entry.strip() 64 if len(entry) == 0: continue 65 m = pattern.match(entry) 66 if m is not None: 67 info_dict[m.group('name')] = m.group('value') 68 else: 69 raise IOError, "String %s is not a valid info string" % entry 70 71 return info_dict
72
73 74 -def glob(name, path=''):
75 """call to glob.glob with automatic security on path""" 76 import glob as glob_module 77 path = re.sub('(?P<name>\?|\*|\[|\])', '[\g<name>]', path) 78 return glob_module.glob(pjoin(path, name))
79
80 #=============================================================================== 81 # mute_logger (designed to be a decorator) 82 #=============================================================================== 83 -def mute_logger(names=['madgraph','ALOHA','cmdprint','madevent'], levels=[50,50,50,50]):
84 """change the logger level and restore those at their initial value at the 85 end of the function decorated.""" 86 def control_logger(f): 87 def restore_old_levels(names, levels): 88 for name, level in zip(names, levels): 89 log_module = logging.getLogger(name) 90 log_module.setLevel(level)
91 92 def f_with_no_logger(self, *args, **opt): 93 old_levels = [] 94 for name, level in zip(names, levels): 95 log_module = logging.getLogger(name) 96 old_levels.append(log_module.level) 97 log_module.setLevel(level) 98 try: 99 out = f(self, *args, **opt) 100 restore_old_levels(names, old_levels) 101 return out 102 except: 103 restore_old_levels(names, old_levels) 104 raise 105 106 return f_with_no_logger 107 return control_logger 108 109 PACKAGE_INFO = {}
110 #=============================================================================== 111 # get_pkg_info 112 #=============================================================================== 113 -def get_pkg_info(info_str=None):
114 """Returns the current version information of the MadGraph5_aMC@NLO package, 115 as written in the VERSION text file. If the file cannot be found, 116 a dictionary with empty values is returned. As an option, an info 117 string can be passed to be read instead of the file content. 118 """ 119 global PACKAGE_INFO 120 121 if info_str: 122 info_dict = parse_info_str(StringIO.StringIO(info_str)) 123 124 elif MADEVENT: 125 info_dict ={} 126 info_dict['version'] = open(pjoin(internal.__path__[0],'..','..','MGMEVersion.txt')).read().strip() 127 info_dict['date'] = '20xx-xx-xx' 128 else: 129 if PACKAGE_INFO: 130 return PACKAGE_INFO 131 info_dict = files.read_from_file(os.path.join(madgraph.__path__[0], 132 "VERSION"), 133 parse_info_str, 134 print_error=False) 135 PACKAGE_INFO = info_dict 136 137 return info_dict
138
139 #=============================================================================== 140 # get_time_info 141 #=============================================================================== 142 -def get_time_info():
143 """Returns the present time info for use in MG5 command history header. 144 """ 145 146 creation_time = time.asctime() 147 time_info = {'time': creation_time, 148 'fill': ' ' * (26 - len(creation_time))} 149 150 return time_info
151
152 #=============================================================================== 153 # Find the subdirectory which includes the files ending with a given extension 154 #=============================================================================== 155 -def find_includes_path(start_path, extension):
156 """Browse the subdirectories of the path 'start_path' and returns the first 157 one found which contains at least one file ending with the string extension 158 given in argument.""" 159 160 if not os.path.isdir(start_path): 161 return None 162 subdirs=[pjoin(start_path,dir) for dir in os.listdir(start_path)] 163 for subdir in subdirs: 164 if os.path.isfile(subdir): 165 if os.path.basename(subdir).endswith(extension): 166 return start_path 167 elif os.path.isdir(subdir): 168 path = find_includes_path(subdir, extension) 169 if path: 170 return path 171 return None
172
173 #=============================================================================== 174 # Given the path of a ninja installation, this function determines if it 175 # supports quadruple precision or not. 176 #=============================================================================== 177 -def get_ninja_quad_prec_support(ninja_lib_path):
178 """ Get whether ninja supports quad prec in different ways""" 179 180 # First try with the ninja-config executable if present 181 ninja_config = os.path.abspath(pjoin( 182 ninja_lib_path,os.pardir,'bin','ninja-config')) 183 if os.path.exists(ninja_config): 184 try: 185 p = Popen([ninja_config, '-quadsupport'], stdout=subprocess.PIPE, 186 stderr=subprocess.PIPE) 187 output, error = p.communicate() 188 return 'TRUE' in output.upper() 189 except Exception: 190 pass 191 192 # If no ninja-config is present, then simply use the presence of 193 # 'quadninja' in the include 194 return False
195
196 #=============================================================================== 197 # find a executable 198 #=============================================================================== 199 -def which(program):
200 def is_exe(fpath): 201 return os.path.exists(fpath) and os.access(\ 202 os.path.realpath(fpath), os.X_OK)
203 204 if not program: 205 return None 206 207 fpath, fname = os.path.split(program) 208 if fpath: 209 if is_exe(program): 210 return program 211 else: 212 for path in os.environ["PATH"].split(os.pathsep): 213 exe_file = os.path.join(path, program) 214 if is_exe(exe_file): 215 return exe_file 216 return None 217
218 -def has_f2py():
219 has_f2py = False 220 if which('f2py'): 221 has_f2py = True 222 elif sys.version_info[1] == 6: 223 if which('f2py-2.6'): 224 has_f2py = True 225 elif which('f2py2.6'): 226 has_f2py = True 227 else: 228 if which('f2py-2.7'): 229 has_f2py = True 230 elif which('f2py2.7'): 231 has_f2py = True 232 return has_f2py
233
234 #=============================================================================== 235 # Activate dependencies if possible. Mainly for tests 236 #=============================================================================== 237 238 -def deactivate_dependence(dependency, cmd=None, log = None):
239 """ Make sure to turn off some dependency of MG5aMC. """ 240 241 def tell(msg): 242 if log == 'stdout': 243 print msg 244 elif callable(log): 245 log(msg)
246 247 248 if dependency in ['pjfry','golem','samurai','ninja','collier']: 249 if cmd.options[dependency] not in ['None',None,'']: 250 tell("Deactivating MG5_aMC dependency '%s'"%dependency) 251 cmd.options[dependency] = None 252
253 -def activate_dependence(dependency, cmd=None, log = None, MG5dir=None):
254 """ Checks whether the specfieid MG dependency can be activated if it was 255 not turned off in MG5 options.""" 256 257 def tell(msg): 258 if log == 'stdout': 259 print msg 260 elif callable(log): 261 log(msg)
262 263 if cmd is None: 264 cmd = MGCmd.MasterCmd() 265 266 if dependency=='pjfry': 267 if cmd.options['pjfry'] in ['None',None,''] or \ 268 (cmd.options['pjfry'] == 'auto' and which_lib('libpjfry.a') is None) or\ 269 which_lib(pjoin(cmd.options['pjfry'],'libpjfry.a')) is None: 270 tell("Installing PJFry...") 271 cmd.do_install('PJFry') 272 273 if dependency=='golem': 274 if cmd.options['golem'] in ['None',None,''] or\ 275 (cmd.options['golem'] == 'auto' and which_lib('libgolem.a') is None) or\ 276 which_lib(pjoin(cmd.options['golem'],'libgolem.a')) is None: 277 tell("Installing Golem95...") 278 cmd.do_install('Golem95') 279 280 if dependency=='samurai': 281 raise MadGraph5Error, 'Samurai cannot yet be automatically installed.' 282 283 if dependency=='ninja': 284 if cmd.options['ninja'] in ['None',None,''] or\ 285 (cmd.options['ninja'] == './HEPTools/lib' and not MG5dir is None and\ 286 which_lib(pjoin(MG5dir,cmd.options['ninja'],'libninja.a')) is None): 287 tell("Installing ninja...") 288 cmd.do_install('ninja') 289 290 if dependency=='collier': 291 if cmd.options['collier'] in ['None',None,''] or\ 292 (cmd.options['collier'] == 'auto' and which_lib('libcollier.a') is None) or\ 293 which_lib(pjoin(cmd.options['collier'],'libcollier.a')) is None: 294 tell("Installing COLLIER...") 295 cmd.do_install('collier') 296
297 #=============================================================================== 298 # find a library 299 #=============================================================================== 300 -def which_lib(lib):
301 def is_lib(fpath): 302 return os.path.exists(fpath) and os.access(fpath, os.R_OK)
303 304 if not lib: 305 return None 306 307 fpath, fname = os.path.split(lib) 308 if fpath: 309 if is_lib(lib): 310 return lib 311 else: 312 locations = sum([os.environ[env_path].split(os.pathsep) for env_path in 313 ["DYLD_LIBRARY_PATH","LD_LIBRARY_PATH","LIBRARY_PATH","PATH"] 314 if env_path in os.environ],[]) 315 for path in locations: 316 lib_file = os.path.join(path, lib) 317 if is_lib(lib_file): 318 return lib_file 319 return None 320
321 #=============================================================================== 322 # Return Nice display for a random variable 323 #=============================================================================== 324 -def nice_representation(var, nb_space=0):
325 """ Return nice information on the current variable """ 326 327 #check which data to put: 328 info = [('type',type(var)),('str', var)] 329 if hasattr(var, 'func_doc'): 330 info.append( ('DOC', var.func_doc) ) 331 if hasattr(var, '__doc__'): 332 info.append( ('DOC', var.__doc__) ) 333 if hasattr(var, '__dict__'): 334 info.append( ('ATTRIBUTE', var.__dict__.keys() )) 335 336 spaces = ' ' * nb_space 337 338 outstr='' 339 for name, value in info: 340 outstr += '%s%3s : %s\n' % (spaces,name, value) 341 342 return outstr
343 344 # 345 # Decorator for re-running a crashing function automatically. 346 # 347 wait_once = False
348 -def multiple_try(nb_try=5, sleep=20):
349 350 def deco_retry(f): 351 def deco_f_retry(*args, **opt): 352 for i in range(nb_try): 353 try: 354 return f(*args, **opt) 355 except KeyboardInterrupt: 356 raise 357 except Exception, error: 358 global wait_once 359 if not wait_once: 360 text = """Start waiting for update. (more info in debug mode)""" 361 logger.info(text) 362 logger_stderr.debug('fail to do %s function with %s args. %s try on a max of %s (%s waiting time)' % 363 (str(f), ', '.join([str(a) for a in args]), i+1, nb_try, sleep * (i+1))) 364 logger_stderr.debug('error is %s' % str(error)) 365 if __debug__: logger_stderr.debug('and occurred at :'+traceback.format_exc()) 366 wait_once = True 367 time.sleep(sleep * (i+1)) 368 369 if __debug__: 370 raise 371 raise error.__class__, '[Fail %i times] \n %s ' % (i+1, error)
372 return deco_f_retry 373 return deco_retry 374
375 #=============================================================================== 376 # helper for scan. providing a nice formatted string for the scan name 377 #=============================================================================== 378 -def get_scan_name(first, last):
379 """return a name of the type xxxx[A-B]yyy 380 where xxx and yyy are the common part between the two names. 381 """ 382 383 # find the common string at the beginning 384 base = [first[i] for i in range(len(first)) if first[:i+1] == last[:i+1]] 385 # remove digit even if in common 386 while base and base[0].isdigit(): 387 base = base[1:] 388 # find the common string at the end 389 end = [first[-(i+1)] for i in range(len(first)) if first[-(i+1):] == last[-(i+1):]] 390 # remove digit even if in common 391 while end and end[-1].isdigit(): 392 end = end[:-1] 393 end.reverse() 394 #convert to string 395 base, end = ''.join(base), ''.join(end) 396 if end: 397 name = "%s[%s-%s]%s" % (base, first[len(base):-len(end)], last[len(base):-len(end)],end) 398 else: 399 name = "%s[%s-%s]%s" % (base, first[len(base):], last[len(base):],end) 400 return name
401
402 #=============================================================================== 403 # Compiler which returns smart output error in case of trouble 404 #=============================================================================== 405 -def compile(arg=[], cwd=None, mode='fortran', job_specs = True, nb_core=1 ,**opt):
406 """compile a given directory""" 407 408 if 'nocompile' in opt: 409 if opt['nocompile'] == True: 410 if not arg: 411 return 412 if cwd: 413 executable = pjoin(cwd, arg[0]) 414 else: 415 executable = arg[0] 416 if os.path.exists(executable): 417 return 418 del opt['nocompile'] 419 420 cmd = ['make'] 421 try: 422 if nb_core > 1: 423 cmd.append('-j%s' % nb_core) 424 cmd += arg 425 p = subprocess.Popen(cmd, stdout=subprocess.PIPE, 426 stderr=subprocess.STDOUT, cwd=cwd, **opt) 427 (out, err) = p.communicate() 428 except OSError, error: 429 if cwd and not os.path.exists(cwd): 430 raise OSError, 'Directory %s doesn\'t exists. Impossible to run make' % cwd 431 else: 432 error_text = "Impossible to compile %s directory\n" % cwd 433 error_text += "Trying to launch make command returns:\n" 434 error_text += " " + str(error) + "\n" 435 error_text += "In general this means that your computer is not able to compile." 436 if sys.platform == "darwin": 437 error_text += "Note that MacOSX doesn\'t have gmake/gfortan install by default.\n" 438 error_text += "Xcode3 contains those required programs" 439 raise MadGraph5Error, error_text 440 441 if p.returncode: 442 # Check that makefile exists 443 if not cwd: 444 cwd = os.getcwd() 445 all_file = [f.lower() for f in os.listdir(cwd)] 446 if 'makefile' not in all_file and '-f' not in arg: 447 raise OSError, 'no makefile present in %s' % os.path.realpath(cwd) 448 449 if mode == 'fortran' and not (which('g77') or which('gfortran')): 450 error_msg = 'A fortran compiler (g77 or gfortran) is required to create this output.\n' 451 error_msg += 'Please install g77 or gfortran on your computer and retry.' 452 raise MadGraph5Error, error_msg 453 elif mode == 'cpp' and not which('g++'): 454 error_msg ='A C++ compiler (g++) is required to create this output.\n' 455 error_msg += 'Please install g++ (which is part of the gcc package) on your computer and retry.' 456 raise MadGraph5Error, error_msg 457 458 # Check if this is due to the need of gfortran 4.6 for quadruple precision 459 if any(tag.upper() in out.upper() for tag in ['real(kind=16)','real*16', 460 'complex*32']) and mode == 'fortran' and not \ 461 ''.join(get_gfortran_version().split('.')) >= '46': 462 if not which('gfortran'): 463 raise MadGraph5Error, 'The fortran compiler gfortran v4.6 or later '+\ 464 'is required to compile %s.\nPlease install it and retry.'%cwd 465 else: 466 logger_stderr.error('ERROR, you could not compile %s because'%cwd+\ 467 ' your version of gfortran is older than 4.6. MadGraph5_aMC@NLO will carry on,'+\ 468 ' but will not be able to compile an executable.') 469 return p.returncode 470 # Other reason 471 error_text = 'A compilation Error occurs ' 472 if cwd: 473 error_text += 'when trying to compile %s.\n' % cwd 474 error_text += 'The compilation fails with the following output message:\n' 475 error_text += ' '+out.replace('\n','\n ')+'\n' 476 error_text += 'Please try to fix this compilations issue and retry.\n' 477 error_text += 'Help might be found at https://answers.launchpad.net/mg5amcnlo.\n' 478 error_text += 'If you think that this is a bug, you can report this at https://bugs.launchpad.net/mg5amcnlo' 479 raise MadGraph5Error, error_text 480 return p.returncode
481
482 -def get_gfortran_version(compiler='gfortran'):
483 """ Returns the gfortran version as a string. 484 Returns '0' if it failed.""" 485 try: 486 p = Popen([compiler, '-dumpversion'], stdout=subprocess.PIPE, 487 stderr=subprocess.PIPE) 488 output, error = p.communicate() 489 version_finder=re.compile(r"(?P<version>(\d.)*\d)") 490 version = version_finder.search(output).group('version') 491 return version 492 except Exception: 493 return '0'
494
495 -def mod_compilator(directory, new='gfortran', current=None, compiler_type='gfortran'):
496 #define global regular expression 497 if type(directory)!=list: 498 directory=[directory] 499 500 #search file 501 file_to_change=find_makefile_in_dir(directory) 502 if compiler_type == 'gfortran': 503 comp_re = re.compile('^(\s*)FC\s*=\s*(.+)\s*$') 504 var = 'FC' 505 elif compiler_type == 'cpp': 506 comp_re = re.compile('^(\s*)CXX\s*=\s*(.+)\s*$') 507 var = 'CXX' 508 else: 509 MadGraph5Error, 'Unknown compiler type: %s' % compiler_type 510 511 mod = False 512 for name in file_to_change: 513 lines = open(name,'r').read().split('\n') 514 for iline, line in enumerate(lines): 515 result = comp_re.match(line) 516 if result: 517 if new != result.group(2) and '$' not in result.group(2): 518 mod = True 519 lines[iline] = result.group(1) + var + "=" + new 520 elif compiler_type == 'gfortran' and line.startswith('DEFAULT_F_COMPILER'): 521 lines[iline] = "DEFAULT_F_COMPILER = %s" % new 522 elif compiler_type == 'cpp' and line.startswith('DEFAULT_CPP_COMPILER'): 523 lines[iline] = "DEFAULT_CPP_COMPILER = %s" % new 524 525 if mod: 526 open(name,'w').write('\n'.join(lines)) 527 # reset it to change the next file 528 mod = False
529
530 #=============================================================================== 531 # mute_logger (designed to work as with statement) 532 #=============================================================================== 533 -class MuteLogger(object):
534 """mute_logger (designed to work as with statement), 535 files allow to redirect the output of the log to a given file. 536 """ 537
538 - def __init__(self, names, levels, files=None, **opt):
539 assert isinstance(names, list) 540 assert isinstance(names, list) 541 542 self.names = names 543 self.levels = levels 544 if isinstance(files, list): 545 self.files = files 546 else: 547 self.files = [files] * len(names) 548 self.logger_saved_info = {} 549 self.opts = opt
550
551 - def __enter__(self):
552 old_levels = [] 553 for name, level, path in zip(self.names, self.levels, self.files): 554 if path: 555 self.setup_logFile_for_logger(path, name, **self.opts) 556 log_module = logging.getLogger(name) 557 old_levels.append(log_module.level) 558 log_module = logging.getLogger(name) 559 log_module.setLevel(level) 560 self.levels = old_levels
561
562 - def __exit__(self, ctype, value, traceback ):
563 for name, level, path in zip(self.names, self.levels, self.files): 564 565 if path: 566 if 'keep' in self.opts and not self.opts['keep']: 567 self.restore_logFile_for_logger(name, level, path=path) 568 else: 569 self.restore_logFile_for_logger(name, level) 570 else: 571 log_module = logging.getLogger(name) 572 log_module.setLevel(level)
573
574 - def setup_logFile_for_logger(self, path, full_logname, **opts):
575 """ Setup the logger by redirecting them all to logfiles in tmp """ 576 577 logs = full_logname.split('.') 578 lognames = [ '.'.join(logs[:(len(logs)-i)]) for i in\ 579 range(len(full_logname.split('.')))] 580 for logname in lognames: 581 try: 582 os.remove(path) 583 except Exception, error: 584 pass 585 my_logger = logging.getLogger(logname) 586 hdlr = logging.FileHandler(path) 587 # I assume below that the orders of the handlers in my_logger.handlers 588 # remains the same after having added/removed the FileHandler 589 self.logger_saved_info[logname] = [hdlr, my_logger.handlers] 590 #for h in my_logger.handlers: 591 # h.setLevel(logging.CRITICAL) 592 for old_hdlr in list(my_logger.handlers): 593 my_logger.removeHandler(old_hdlr) 594 my_logger.addHandler(hdlr) 595 #my_logger.setLevel(level) 596 my_logger.debug('Log of %s' % logname)
597
598 - def restore_logFile_for_logger(self, full_logname, level, path=None, **opts):
599 """ Setup the logger by redirecting them all to logfiles in tmp """ 600 601 logs = full_logname.split('.') 602 lognames = [ '.'.join(logs[:(len(logs)-i)]) for i in\ 603 range(len(full_logname.split('.')))] 604 for logname in lognames: 605 if path: 606 try: 607 os.remove(path) 608 except Exception, error: 609 pass 610 my_logger = logging.getLogger(logname) 611 if logname in self.logger_saved_info: 612 my_logger.removeHandler(self.logger_saved_info[logname][0]) 613 for old_hdlr in self.logger_saved_info[logname][1]: 614 my_logger.addHandler(old_hdlr) 615 else: 616 my_logger.setLevel(level)
617 618 #for i, h in enumerate(my_logger.handlers): 619 # h.setLevel(cls.logger_saved_info[logname][2][i]) 620 621 nb_open =0
622 @contextlib.contextmanager 623 -def stdchannel_redirected(stdchannel, dest_filename):
624 """ 625 A context manager to temporarily redirect stdout or stderr 626 627 e.g.: 628 629 630 with stdchannel_redirected(sys.stderr, os.devnull): 631 if compiler.has_function('clock_gettime', libraries=['rt']): 632 libraries.append('rt') 633 """ 634 635 try: 636 oldstdchannel = os.dup(stdchannel.fileno()) 637 dest_file = open(dest_filename, 'w') 638 os.dup2(dest_file.fileno(), stdchannel.fileno()) 639 yield 640 finally: 641 if oldstdchannel is not None: 642 os.dup2(oldstdchannel, stdchannel.fileno()) 643 os.close(oldstdchannel) 644 if dest_file is not None: 645 dest_file.close()
646
647 -def get_open_fds():
648 ''' 649 return the number of open file descriptors for current process 650 651 .. warning: will only work on UNIX-like os-es. 652 ''' 653 import subprocess 654 import os 655 656 pid = os.getpid() 657 procs = subprocess.check_output( 658 [ "lsof", '-w', '-Ff', "-p", str( pid ) ] ) 659 nprocs = filter( 660 lambda s: s and s[ 0 ] == 'f' and s[1: ].isdigit(), 661 procs.split( '\n' ) ) 662 663 return nprocs
664
665 -def detect_if_cpp_compiler_is_clang(cpp_compiler):
666 """ Detects whether the specified C++ compiler is clang.""" 667 668 try: 669 p = Popen([cpp_compiler, '--version'], stdout=subprocess.PIPE, 670 stderr=subprocess.PIPE) 671 output, error = p.communicate() 672 except Exception, error: 673 # Cannot probe the compiler, assume not clang then 674 return False 675 return 'LLVM' in output
676
677 -def detect_cpp_std_lib_dependence(cpp_compiler):
678 """ Detects if the specified c++ compiler will normally link against the C++ 679 standard library -lc++ or -libstdc++.""" 680 681 is_clang = detect_if_cpp_compiler_is_clang(cpp_compiler) 682 if is_clang: 683 try: 684 import platform 685 v, _,_ = platform.mac_ver() 686 if not v: 687 # We will not attempt to support clang elsewhere than on macs, so 688 # we venture a guess here. 689 return '-lc++' 690 else: 691 v = float(v.rsplit('.')[1]) 692 if v >= 9: 693 return '-lc++' 694 else: 695 return '-lstdc++' 696 except: 697 return '-lstdc++' 698 return '-lstdc++'
699
700 -def detect_current_compiler(path, compiler_type='fortran'):
701 """find the current compiler for the current directory""" 702 703 # comp = re.compile("^\s*FC\s*=\s*(\w+)\s*") 704 # The regular expression below allows for compiler definition with absolute path 705 if compiler_type == 'fortran': 706 comp = re.compile("^\s*FC\s*=\s*([\w\/\\.\-]+)\s*") 707 elif compiler_type == 'cpp': 708 comp = re.compile("^\s*CXX\s*=\s*([\w\/\\.\-]+)\s*") 709 else: 710 MadGraph5Error, 'Unknown compiler type: %s' % compiler_type 711 712 for line in open(path): 713 if comp.search(line): 714 compiler = comp.search(line).groups()[0] 715 return compiler 716 elif compiler_type == 'fortran' and line.startswith('DEFAULT_F_COMPILER'): 717 return line.split('=')[1].strip() 718 elif compiler_type == 'cpp' and line.startswith('DEFAULT_CPP_COMPILER'): 719 return line.split('=')[1].strip()
720
721 -def find_makefile_in_dir(directory):
722 """ return a list of all file starting with makefile in the given directory""" 723 724 out=[] 725 #list mode 726 if type(directory)==list: 727 for name in directory: 728 out+=find_makefile_in_dir(name) 729 return out 730 731 #single mode 732 for name in os.listdir(directory): 733 if os.path.isdir(directory+'/'+name): 734 out+=find_makefile_in_dir(directory+'/'+name) 735 elif os.path.isfile(directory+'/'+name) and name.lower().startswith('makefile'): 736 out.append(directory+'/'+name) 737 elif os.path.isfile(directory+'/'+name) and name.lower().startswith('make_opt'): 738 out.append(directory+'/'+name) 739 return out
740
741 -def rm_old_compile_file():
742 743 # remove all the .o files 744 os.path.walk('.', rm_file_extension, '.o') 745 746 # remove related libraries 747 libraries = ['libblocks.a', 'libgeneric_mw.a', 'libMWPS.a', 'libtools.a', 'libdhelas3.a', 748 'libdsample.a', 'libgeneric.a', 'libmodel.a', 'libpdf.a', 'libdhelas3.so', 'libTF.a', 749 'libdsample.so', 'libgeneric.so', 'libmodel.so', 'libpdf.so'] 750 lib_pos='./lib' 751 [os.remove(os.path.join(lib_pos, lib)) for lib in libraries \ 752 if os.path.exists(os.path.join(lib_pos, lib))]
753
754 755 -def format_time(n_secs):
756 m, s = divmod(n_secs, 60) 757 h, m = divmod(m, 60) 758 d, h = divmod(h, 24) 759 if d > 0: 760 return "%d day%s,%dh%02dm%02ds" % (d,'' if d<=1 else 's',h, m, s) 761 elif h > 0: 762 return "%dh%02dm%02ds" % (h, m, s) 763 elif m > 0: 764 return "%dm%02ds" % (m, s) 765 else: 766 return "%d second%s" % (s, '' if s<=1 else 's')
767
768 -def rm_file_extension( ext, dirname, names):
769 770 [os.remove(os.path.join(dirname, name)) for name in names if name.endswith(ext)]
771
772 773 774 -def multiple_replacer(*key_values):
775 replace_dict = dict(key_values) 776 replacement_function = lambda match: replace_dict[match.group(0)] 777 pattern = re.compile("|".join([re.escape(k) for k, v in key_values]), re.M) 778 return lambda string: pattern.sub(replacement_function, string)
779
780 -def multiple_replace(string, *key_values):
781 return multiple_replacer(*key_values)(string)
782
783 # Control 784 -def check_system_error(value=1):
785 def deco_check(f): 786 def deco_f(arg, *args, **opt): 787 try: 788 return f(arg, *args, **opt) 789 except OSError, error: 790 logger.debug('try to recover from %s' % error) 791 if isinstance(arg, list): 792 prog = arg[0] 793 else: 794 prog = arg[0] 795 796 # Permission denied 797 if error.errno == 13: 798 if os.path.exists(prog): 799 os.system('chmod +x %s' % prog) 800 elif 'cwd' in opt and opt['cwd'] and \ 801 os.path.isfile(pjoin(opt['cwd'],arg[0])): 802 os.system('chmod +x %s' % pjoin(opt['cwd'],arg[0])) 803 return f(arg, *args, **opt) 804 # NO such file or directory 805 elif error.errno == 2: 806 # raise a more meaningfull error message 807 raise Exception, '%s fails with no such file or directory' \ 808 % arg 809 else: 810 raise
811 return deco_f 812 return deco_check 813
814 815 @check_system_error() 816 -def call(arg, *args, **opt):
817 """nice way to call an external program with nice error treatment""" 818 try: 819 return subprocess.call(arg, *args, **opt) 820 except OSError: 821 arg[0] = './%s' % arg[0] 822 return subprocess.call(arg, *args, **opt)
823
824 @check_system_error() 825 -def Popen(arg, *args, **opt):
826 """nice way to call an external program with nice error treatment""" 827 return subprocess.Popen(arg, *args, **opt)
828
829 @multiple_try() 830 -def mult_try_open(filepath, *args, **opt):
831 """try to open a file with multiple try to ensure that filesystem is sync""" 832 return open(filepath, *args, ** opt)
833
834 ################################################################################ 835 # TAIL FUNCTION 836 ################################################################################ 837 -def tail(f, n, offset=None):
838 """Reads a n lines from f with an offset of offset lines. The return 839 value is a tuple in the form ``lines``. 840 """ 841 avg_line_length = 74 842 to_read = n + (offset or 0) 843 844 while 1: 845 try: 846 f.seek(-(avg_line_length * to_read), 2) 847 except IOError: 848 # woops. apparently file is smaller than what we want 849 # to step back, go to the beginning instead 850 f.seek(0) 851 pos = f.tell() 852 lines = f.read().splitlines() 853 if len(lines) >= to_read or pos == 0: 854 return lines[-to_read:offset and -offset or None] 855 avg_line_length *= 1.3 856 avg_line_length = int(avg_line_length)
857
858 -def mkfifo(fifo_path):
859 """ makes a piping fifo (First-in First-out) file and nicely intercepts 860 error in case the file format of the target drive doesn't suppor tit.""" 861 862 try: 863 os.mkfifo(fifo_path) 864 except: 865 raise OSError('MadGraph5_aMCatNLO could not create a fifo file at:\n'+ 866 ' %s\n'%fifo_path+'Make sure that this file does not exist already'+ 867 ' and that the file format of the target drive supports fifo file (i.e not NFS).')
868
869 ################################################################################ 870 # LAST LINE FUNCTION 871 ################################################################################ 872 -def get_last_line(fsock):
873 """return the last line of a file""" 874 875 return tail(fsock, 1)[0]
876
877 -class BackRead(file):
878 """read a file returning the lines in reverse order for each call of readline() 879 This actually just reads blocks (4096 bytes by default) of data from the end of 880 the file and returns last line in an internal buffer.""" 881 882
883 - def readline(self):
884 """ readline in a backward way """ 885 886 while len(self.data) == 1 and ((self.blkcount * self.blksize) < self.size): 887 self.blkcount = self.blkcount + 1 888 line = self.data[0] 889 try: 890 self.seek(-self.blksize * self.blkcount, 2) # read from end of file 891 self.data = (self.read(self.blksize) + line).split('\n') 892 except IOError: # can't seek before the beginning of the file 893 self.seek(0) 894 data = self.read(self.size - (self.blksize * (self.blkcount-1))) + line 895 self.data = data.split('\n') 896 897 if len(self.data) == 0: 898 return "" 899 900 line = self.data.pop() 901 return line + '\n'
902
903 - def __init__(self, filepos, blksize=4096):
904 """initialize the internal structures""" 905 906 # get the file size 907 self.size = os.stat(filepos)[6] 908 # how big of a block to read from the file... 909 self.blksize = blksize 910 # how many blocks we've read 911 self.blkcount = 1 912 file.__init__(self, filepos, 'rb') 913 # if the file is smaller than the blocksize, read a block, 914 # otherwise, read the whole thing... 915 if self.size > self.blksize: 916 self.seek(-self.blksize * self.blkcount, 2) # read from end of file 917 self.data = self.read(self.blksize).split('\n') 918 # strip the last item if it's empty... a byproduct of the last line having 919 # a newline at the end of it 920 if not self.data[-1]: 921 self.data.pop()
922
923 - def next(self):
924 line = self.readline() 925 if line: 926 return line 927 else: 928 raise StopIteration
929
930 931 -def write_PS_input(filePath, PS):
932 """ Write out in file filePath the PS point to be read by the MadLoop.""" 933 try: 934 PSfile = open(filePath, 'w') 935 # Add a newline in the end as the implementation fortran 'read' 936 # command on some OS is problematic if it ends directly with the 937 # floating point number read. 938 939 PSfile.write('\n'.join([' '.join(['%.16E'%pi for pi in p]) \ 940 for p in PS])+'\n') 941 PSfile.close() 942 except Exception: 943 raise MadGraph5Error, 'Could not write out the PS point to file %s.'\ 944 %str(filePath)
945
946 -def format_timer(running_time):
947 """ return a nicely string representing the time elapsed.""" 948 if running_time < 2e-2: 949 running_time = running_time = 'current time: %02dh%02d' % (time.localtime().tm_hour, time.localtime().tm_min) 950 elif running_time < 10: 951 running_time = ' %.2gs ' % running_time 952 elif 60 > running_time >= 10: 953 running_time = ' %.3gs ' % running_time 954 elif 3600 > running_time >= 60: 955 running_time = ' %im %is ' % (running_time // 60, int(running_time % 60)) 956 else: 957 running_time = ' %ih %im ' % (running_time // 3600, (running_time//60 % 60)) 958 return running_time
959
960 961 #=============================================================================== 962 # TMP_directory (designed to work as with statement) 963 #=============================================================================== 964 -class TMP_directory(object):
965 """create a temporary directory and ensure this one to be cleaned. 966 """ 967
968 - def __init__(self, suffix='', prefix='tmp', dir=None):
969 self.nb_try_remove = 0 970 import tempfile 971 self.path = tempfile.mkdtemp(suffix, prefix, dir)
972 973
974 - def __exit__(self, ctype, value, traceback ):
975 #True only for debugging: 976 if False and isinstance(value, Exception): 977 sprint("Directory %s not cleaned. This directory can be removed manually" % self.path) 978 return False 979 try: 980 shutil.rmtree(self.path) 981 except OSError: 982 self.nb_try_remove += 1 983 if self.nb_try_remove < 3: 984 time.sleep(10) 985 self.__exit__(ctype, value, traceback) 986 else: 987 logger.warning("Directory %s not completely cleaned. This directory can be removed manually" % self.path)
988
989 - def __enter__(self):
990 return self.path
991
992 -class TMP_variable(object):
993 """create a temporary directory and ensure this one to be cleaned. 994 """ 995
996 - def __init__(self, cls, attribute, value):
997 998 self.cls = cls 999 self.attribute = attribute 1000 if isinstance(attribute, list): 1001 self.old_value = [] 1002 for key, onevalue in zip(attribute, value): 1003 self.old_value.append(getattr(cls, key)) 1004 setattr(self.cls, key, onevalue) 1005 else: 1006 self.old_value = getattr(cls, attribute) 1007 setattr(self.cls, self.attribute, value)
1008
1009 - def __exit__(self, ctype, value, traceback ):
1010 1011 if isinstance(self.attribute, list): 1012 for key, old_value in zip(self.attribute, self.old_value): 1013 setattr(self.cls, key, old_value) 1014 else: 1015 setattr(self.cls, self.attribute, self.old_value)
1016
1017 - def __enter__(self):
1018 return self.old_value
1019
1020 # 1021 # GUNZIP/GZIP 1022 # 1023 -def gunzip(path, keep=False, stdout=None):
1024 """ a standard replacement for os.system('gunzip -f %s.gz ' % event_path)""" 1025 1026 if not path.endswith(".gz"): 1027 if os.path.exists("%s.gz" % path): 1028 path = "%s.gz" % path 1029 else: 1030 raise Exception, "%(path)s does not finish by .gz and the file %(path)s.gz does not exists" %\ 1031 {"path": path} 1032 1033 1034 #for large file (>1G) it is faster and safer to use a separate thread 1035 if os.path.getsize(path) > 1e8: 1036 if stdout: 1037 os.system('gunzip -c %s > %s' % (path, stdout)) 1038 else: 1039 os.system('gunzip %s' % path) 1040 return 0 1041 1042 if not stdout: 1043 stdout = path[:-3] 1044 try: 1045 gfile = ziplib.open(path, "r") 1046 except IOError: 1047 raise 1048 else: 1049 try: 1050 open(stdout,'w').write(gfile.read()) 1051 except IOError: 1052 # this means that the file is actually not gzip 1053 if stdout == path: 1054 return 1055 else: 1056 files.cp(path, stdout) 1057 1058 if not keep: 1059 os.remove(path) 1060 return 0
1061
1062 -def gzip(path, stdout=None, error=True, forceexternal=False):
1063 """ a standard replacement for os.system('gzip %s ' % path)""" 1064 1065 #for large file (>1G) it is faster and safer to use a separate thread 1066 if os.path.getsize(path) > 1e9 or forceexternal: 1067 call(['gzip', '-f', path]) 1068 if stdout: 1069 if not stdout.endswith(".gz"): 1070 stdout = "%s.gz" % stdout 1071 shutil.move('%s.gz' % path, stdout) 1072 return 1073 1074 if not stdout: 1075 stdout = "%s.gz" % path 1076 elif not stdout.endswith(".gz"): 1077 stdout = "%s.gz" % stdout 1078 1079 try: 1080 ziplib.open(stdout,"w").write(open(path).read()) 1081 except OverflowError: 1082 gzip(path, stdout, error=error, forceexternal=True) 1083 except Exception: 1084 if error: 1085 raise 1086 else: 1087 os.remove(path)
1088
1089 # 1090 # Global function to open supported file types 1091 # 1092 -class open_file(object):
1093 """ a convinient class to open a file """ 1094 1095 web_browser = None 1096 eps_viewer = None 1097 text_editor = None 1098 configured = False 1099
1100 - def __init__(self, filename):
1101 """open a file""" 1102 1103 # Check that the class is correctly configure 1104 if not self.configured: 1105 self.configure() 1106 1107 try: 1108 extension = filename.rsplit('.',1)[1] 1109 except IndexError: 1110 extension = '' 1111 1112 1113 # dispatch method 1114 if extension in ['html','htm','php']: 1115 self.open_program(self.web_browser, filename, background=True) 1116 elif extension in ['ps','eps']: 1117 self.open_program(self.eps_viewer, filename, background=True) 1118 else: 1119 self.open_program(self.text_editor,filename, mac_check=False)
1120 # mac_check to False avoid to use open cmd in mac 1121 1122 @classmethod
1123 - def configure(cls, configuration=None):
1124 """ configure the way to open the file """ 1125 1126 cls.configured = True 1127 1128 # start like this is a configuration for mac 1129 cls.configure_mac(configuration) 1130 if sys.platform == 'darwin': 1131 return # done for MAC 1132 1133 # on Mac some default (eps/web) might be kept on None. This is not 1134 #suitable for LINUX which doesn't have open command. 1135 1136 # first for eps_viewer 1137 if not cls.eps_viewer: 1138 cls.eps_viewer = cls.find_valid(['evince','gv', 'ggv'], 'eps viewer') 1139 1140 # Second for web browser 1141 if not cls.web_browser: 1142 cls.web_browser = cls.find_valid( 1143 ['firefox', 'chrome', 'safari','opera'], 1144 'web browser')
1145 1146 @classmethod
1147 - def configure_mac(cls, configuration=None):
1148 """ configure the way to open a file for mac """ 1149 1150 if configuration is None: 1151 configuration = {'text_editor': None, 1152 'eps_viewer':None, 1153 'web_browser':None} 1154 1155 for key in configuration: 1156 if key == 'text_editor': 1157 # Treat text editor ONLY text base editor !! 1158 if configuration[key]: 1159 program = configuration[key].split()[0] 1160 if not which(program): 1161 logger.warning('Specified text editor %s not valid.' % \ 1162 configuration[key]) 1163 else: 1164 # All is good 1165 cls.text_editor = configuration[key] 1166 continue 1167 #Need to find a valid default 1168 if os.environ.has_key('EDITOR'): 1169 cls.text_editor = os.environ['EDITOR'] 1170 else: 1171 cls.text_editor = cls.find_valid( 1172 ['vi', 'emacs', 'vim', 'gedit', 'nano'], 1173 'text editor') 1174 1175 elif key == 'eps_viewer': 1176 if configuration[key]: 1177 cls.eps_viewer = configuration[key] 1178 continue 1179 # else keep None. For Mac this will use the open command. 1180 elif key == 'web_browser': 1181 if configuration[key]: 1182 cls.web_browser = configuration[key] 1183 continue
1184 # else keep None. For Mac this will use the open command. 1185 1186 @staticmethod
1187 - def find_valid(possibility, program='program'):
1188 """find a valid shell program in the list""" 1189 1190 for p in possibility: 1191 if which(p): 1192 logger.info('Using default %s \"%s\". ' % (program, p) + \ 1193 'Set another one in ./input/mg5_configuration.txt') 1194 return p 1195 1196 logger.info('No valid %s found. ' % program + \ 1197 'Please set in ./input/mg5_configuration.txt') 1198 return None
1199 1200
1201 - def open_program(self, program, file_path, mac_check=True, background=False):
1202 """ open a file with a given program """ 1203 1204 if mac_check==True and sys.platform == 'darwin': 1205 return self.open_mac_program(program, file_path) 1206 1207 # Shell program only 1208 if program: 1209 arguments = program.split() # allow argument in program definition 1210 arguments.append(file_path) 1211 1212 if not background: 1213 subprocess.call(arguments) 1214 else: 1215 import thread 1216 thread.start_new_thread(subprocess.call,(arguments,)) 1217 else: 1218 logger.warning('Not able to open file %s since no program configured.' % file_path + \ 1219 'Please set one in ./input/mg5_configuration.txt')
1220
1221 - def open_mac_program(self, program, file_path):
1222 """ open a text with the text editor """ 1223 1224 if not program: 1225 # Ask to mac manager 1226 os.system('open %s' % file_path) 1227 elif which(program): 1228 # shell program 1229 arguments = program.split() # Allow argument in program definition 1230 arguments.append(file_path) 1231 subprocess.call(arguments) 1232 else: 1233 # not shell program 1234 os.system('open -a %s %s' % (program, file_path))
1235
1236 -def get_HEPTools_location_setter(HEPToolsDir,type):
1237 """ Checks whether mg5dir/HEPTools/<type> (which is 'lib', 'bin' or 'include') 1238 is in the environment paths of the user. If not, it returns a preamble that 1239 sets it before calling the exectuable, for example: 1240 <preamble> ./my_exe 1241 with <preamble> -> DYLD_LIBRARY_PATH=blabla:$DYLD_LIBRARY_PATH""" 1242 1243 assert(type in ['bin','include','lib']) 1244 1245 target_env_var = 'PATH' if type in ['bin','include'] else \ 1246 ('DYLD_LIBRARY_PATH' if sys.platform=='darwin' else 'LD_LIBRARY_PATH') 1247 1248 target_path = os.path.abspath(pjoin(HEPToolsDir,type)) 1249 1250 if target_env_var not in os.environ or \ 1251 target_path not in os.environ[target_env_var].split(os.pathsep): 1252 return "%s=%s:$%s "%(target_env_var,target_path,target_env_var) 1253 else: 1254 return ''
1255
1256 -def get_shell_type():
1257 """ Try and guess what shell type does the user use.""" 1258 try: 1259 if os.environ['SHELL'].endswith('bash'): 1260 return 'bash' 1261 elif os.environ['SHELL'].endswith('tcsh'): 1262 return 'tcsh' 1263 else: 1264 # If unknown, return None 1265 return None 1266 except KeyError: 1267 return None
1268
1269 -def is_executable(path):
1270 """ check if a path is executable""" 1271 try: 1272 return os.access(path, os.X_OK) 1273 except Exception: 1274 return False
1275
1276 -class OptionParser(optparse.OptionParser):
1277 """Option Peaser which raise an error instead as calling exit""" 1278
1279 - def exit(self, status=0, msg=None):
1280 if msg: 1281 raise InvalidCmd, msg 1282 else: 1283 raise InvalidCmd
1284
1285 -def sprint(*args, **opt):
1286 """Returns the current line number in our program.""" 1287 1288 if not __debug__: 1289 return 1290 1291 use_print = False 1292 import inspect 1293 if opt.has_key('cond') and not opt['cond']: 1294 return 1295 1296 if opt.has_key('log'): 1297 log = opt['log'] 1298 else: 1299 log = logging.getLogger('madgraph') 1300 if opt.has_key('level'): 1301 level = opt['level'] 1302 else: 1303 level = logging.getLogger('madgraph').level 1304 if level == 0: 1305 use_print = True 1306 #print "madgraph level",level 1307 #if level == 20: 1308 # level = 10 #avoid info level 1309 #print "use", level 1310 if opt.has_key('wait'): 1311 wait = bool(opt['wait']) 1312 else: 1313 wait = False 1314 1315 lineno = inspect.currentframe().f_back.f_lineno 1316 fargs = inspect.getframeinfo(inspect.currentframe().f_back) 1317 filename, lineno = fargs[:2] 1318 #file = inspect.currentframe().f_back.co_filename 1319 #print type(file) 1320 try: 1321 source = inspect.getsourcelines(inspect.currentframe().f_back) 1322 line = source[0][lineno-source[1]] 1323 line = re.findall(r"misc\.sprint\(\s*(.*)\)\s*($|#)", line)[0][0] 1324 if line.startswith("'") and line.endswith("'") and line.count(",") ==0: 1325 line= '' 1326 elif line.startswith("\"") and line.endswith("\"") and line.count(",") ==0: 1327 line= '' 1328 elif line.startswith(("\"","'")) and len(args)==1 and "%" in line: 1329 line= '' 1330 except Exception: 1331 line='' 1332 1333 if line: 1334 intro = ' %s = \033[0m' % line 1335 else: 1336 intro = '' 1337 1338 1339 if not use_print: 1340 log.log(level, ' '.join([intro]+[str(a) for a in args]) + \ 1341 ' \033[1;30m[%s at line %s]\033[0m' % (os.path.basename(filename), lineno)) 1342 else: 1343 print ' '.join([intro]+[str(a) for a in args]) + \ 1344 ' \033[1;30m[%s at line %s]\033[0m' % (os.path.basename(filename), lineno) 1345 1346 if wait: 1347 raw_input('press_enter to continue') 1348 1349 return
1350
1351 ################################################################################ 1352 # function to check if two float are approximatively equal 1353 ################################################################################ 1354 -def equal(a,b,sig_fig=6, zero_limit=True):
1355 """function to check if two float are approximatively equal""" 1356 import math 1357 1358 if isinstance(sig_fig, int): 1359 if not a or not b: 1360 if zero_limit: 1361 power = sig_fig + 1 1362 else: 1363 return a == b 1364 else: 1365 power = sig_fig - int(math.log10(abs(a))) + 1 1366 1367 return ( a==b or abs(int(a*10**power) - int(b*10**power)) < 10) 1368 else: 1369 return abs(a-b) < sig_fig
1370
1371 ################################################################################ 1372 # class to change directory with the "with statement" 1373 # Exemple: 1374 # with chdir(path) as path: 1375 # pass 1376 ################################################################################ 1377 -class chdir:
1378 - def __init__(self, newPath):
1379 self.newPath = newPath
1380
1381 - def __enter__(self):
1382 self.savedPath = os.getcwd() 1383 os.chdir(self.newPath)
1384
1385 - def __exit__(self, etype, value, traceback):
1386 os.chdir(self.savedPath)
1387
1388 ################################################################################ 1389 # Timeout FUNCTION 1390 ################################################################################ 1391 1392 -def timeout(func, args=(), kwargs={}, timeout_duration=1, default=None):
1393 '''This function will spwan a thread and run the given function using the args, kwargs and 1394 return the given default value if the timeout_duration is exceeded 1395 ''' 1396 import threading 1397 class InterruptableThread(threading.Thread): 1398 def __init__(self): 1399 threading.Thread.__init__(self) 1400 self.result = default
1401 def run(self): 1402 try: 1403 self.result = func(*args, **kwargs) 1404 except Exception,error: 1405 print error 1406 self.result = default 1407 it = InterruptableThread() 1408 it.start() 1409 it.join(timeout_duration) 1410 return it.result 1411
1412 1413 ################################################################################ 1414 # TAIL FUNCTION 1415 ################################################################################ 1416 -class digest:
1417
1418 - def test_all(self):
1419 try: 1420 return self.test_hashlib() 1421 except Exception: 1422 pass 1423 try: 1424 return self.test_md5() 1425 except Exception: 1426 pass 1427 try: 1428 return self.test_zlib() 1429 except Exception: 1430 pass
1431
1432 - def test_hashlib(self):
1433 import hashlib 1434 def digest(text): 1435 """using mg5 for the hash""" 1436 t = hashlib.md5() 1437 t.update(text) 1438 return t.hexdigest()
1439 return digest
1440
1441 - def test_md5(self):
1442 import md5 1443 def digest(text): 1444 """using mg5 for the hash""" 1445 t = md5.md5() 1446 t.update(text) 1447 return t.hexdigest()
1448 return digest 1449
1450 - def test_zlib(self):
1451 import zlib 1452 def digest(text): 1453 return zlib.adler32(text)
1454 1455 digest = digest().test_all()
1456 1457 #=============================================================================== 1458 # Helper class for timing and RAM flashing of subprocesses. 1459 #=============================================================================== 1460 -class ProcessTimer:
1461 - def __init__(self,*args,**opts):
1462 self.cmd_args = args 1463 self.cmd_opts = opts 1464 self.execution_state = False
1465
1466 - def execute(self):
1467 self.max_vms_memory = 0 1468 self.max_rss_memory = 0 1469 1470 self.t1 = None 1471 self.t0 = time.time() 1472 self.p = subprocess.Popen(*self.cmd_args,**self.cmd_opts) 1473 self.execution_state = True
1474
1475 - def poll(self):
1476 if not self.check_execution_state(): 1477 return False 1478 1479 self.t1 = time.time() 1480 # I redirect stderr to void, because from MacOX snow leopard onward, this 1481 # ps -p command writes a million times the following stupid warning 1482 # dyld: DYLD_ environment variables being ignored because main executable (/bin/ps) is setuid or setgid 1483 flash = subprocess.Popen("ps -p %i -o rss"%self.p.pid, 1484 shell=True,stdout=subprocess.PIPE,stderr=open(os.devnull,"w")) 1485 stdout_list = flash.communicate()[0].split('\n') 1486 rss_memory = int(stdout_list[1]) 1487 # for now we ignore vms 1488 vms_memory = 0 1489 1490 # This is the neat version using psutil 1491 # try: 1492 # pp = psutil.Process(self.p.pid) 1493 # 1494 # # obtain a list of the subprocess and all its descendants 1495 # descendants = list(pp.get_children(recursive=True)) 1496 # descendants = descendants + [pp] 1497 # 1498 # rss_memory = 0 1499 # vms_memory = 0 1500 # 1501 # # calculate and sum up the memory of the subprocess and all its descendants 1502 # for descendant in descendants: 1503 # try: 1504 # mem_info = descendant.get_memory_info() 1505 # 1506 # rss_memory += mem_info[0] 1507 # vms_memory += mem_info[1] 1508 # except psutil.error.NoSuchProcess: 1509 # # sometimes a subprocess descendant will have terminated between the time 1510 # # we obtain a list of descendants, and the time we actually poll this 1511 # # descendant's memory usage. 1512 # pass 1513 # 1514 # except psutil.error.NoSuchProcess: 1515 # return self.check_execution_state() 1516 1517 self.max_vms_memory = max(self.max_vms_memory,vms_memory) 1518 self.max_rss_memory = max(self.max_rss_memory,rss_memory) 1519 1520 return self.check_execution_state()
1521
1522 - def is_running(self):
1523 # Version with psutil 1524 # return psutil.pid_exists(self.p.pid) and self.p.poll() == None 1525 return self.p.poll() == None
1526
1527 - def check_execution_state(self):
1528 if not self.execution_state: 1529 return False 1530 if self.is_running(): 1531 return True 1532 self.executation_state = False 1533 self.t1 = time.time() 1534 return False
1535
1536 - def close(self,kill=False):
1537 1538 if self.p.poll() == None: 1539 if kill: 1540 self.p.kill() 1541 else: 1542 self.p.terminate()
1543
1544 # Again a neater handling with psutil 1545 # try: 1546 # pp = psutil.Process(self.p.pid) 1547 # if kill: 1548 # pp.kill() 1549 # else: 1550 # pp.terminate() 1551 # except psutil.error.NoSuchProcess: 1552 # pass 1553 1554 ## Define apple_notify (in a way which is system independent 1555 -class Applenotification(object):
1556
1557 - def __init__(self):
1558 self.init = False 1559 self.working = True
1560
1561 - def load_notification(self):
1562 try: 1563 import Foundation 1564 import objc 1565 self.NSUserNotification = objc.lookUpClass('NSUserNotification') 1566 self.NSUserNotificationCenter = objc.lookUpClass('NSUserNotificationCenter') 1567 except: 1568 self.working=False 1569 self.working=True
1570
1571 - def __call__(self,subtitle, info_text, userInfo={}):
1572 1573 if not self.init: 1574 self.load_notification() 1575 if not self.working: 1576 return 1577 try: 1578 notification = self.NSUserNotification.alloc().init() 1579 notification.setTitle_('MadGraph5_aMC@NLO') 1580 notification.setSubtitle_(subtitle) 1581 notification.setInformativeText_(info_text) 1582 try: 1583 notification.setUserInfo_(userInfo) 1584 except: 1585 pass 1586 self.NSUserNotificationCenter.defaultUserNotificationCenter().scheduleNotification_(notification) 1587 except: 1588 pass
1589 1590 1591 1592 apple_notify = Applenotification()
1593 1594 -class EasterEgg(object):
1595 1596 done_notification = False 1597 message_aprilfirst =\ 1598 {'error': ['Be careful, a cat is eating a lot of fish today. This makes the code unstable.', 1599 'Really, this sounds fishy.', 1600 'A Higgs boson walks into a church. The priest says "We don\'t allow Higgs bosons in here." The Higgs boson replies, "But without me, how can you have mass?"', 1601 "Why does Heisenberg detest driving cars? Because, every time he looks at the speedometer he gets lost!", 1602 "May the mass times acceleration be with you.", 1603 "NOTE: This product may actually be nine-dimensional. If this is the case, functionality is not affected by the extra five dimensions.", 1604 "IMPORTANT: This product is composed of 100%% matter: It is the responsibility of the User to make sure that it does not come in contact with antimatter.", 1605 'The fish are out of jokes. See you next year for more!'], 1606 'loading': ['Hi %(user)s, You are Loading Madgraph. Please be patient, we are doing the work.'], 1607 'quit': ['Thanks %(user)s for using MadGraph5_aMC@NLO, even on April 1st!'] 1608 } 1609
1610 - def __init__(self, msgtype):
1611 1612 try: 1613 now = time.localtime() 1614 date = now.tm_mday, now.tm_mon 1615 if date in [(1,4)]: 1616 if msgtype in EasterEgg.message_aprilfirst: 1617 choices = EasterEgg.message_aprilfirst[msgtype] 1618 if len(choices) == 0: 1619 return 1620 elif len(choices) == 1: 1621 msg = choices[0] 1622 else: 1623 import random 1624 msg = choices[random.randint(0,len(choices)-2)] 1625 EasterEgg.message_aprilfirst[msgtype].remove(msg) 1626 1627 else: 1628 return 1629 if MADEVENT: 1630 return 1631 1632 import os 1633 import pwd 1634 username =pwd.getpwuid( os.getuid() )[ 0 ] 1635 msg = msg % {'user': username} 1636 if sys.platform == "darwin": 1637 self.call_apple(msg) 1638 else: 1639 self.call_linux(msg) 1640 except Exception, error: 1641 sprint(error) 1642 pass
1643
1644 - def __call__(self, msg):
1645 try: 1646 self.call_apple(msg) 1647 except: 1648 pass
1649
1650 - def call_apple(self, msg):
1651 1652 #1. control if the volume is on or not 1653 p = subprocess.Popen("osascript -e 'get volume settings'", stdout=subprocess.PIPE, shell=True) 1654 output, _ = p.communicate() 1655 #output volume:25, input volume:71, alert volume:100, output muted:true 1656 info = dict([[a.strip() for a in l.split(':',1)] for l in output.strip().split(',')]) 1657 muted = False 1658 if 'output muted' in info and info['output muted'] == 'true': 1659 muted = True 1660 elif 'output volume' in info and info['output volume'] == '0': 1661 muted = True 1662 1663 if muted: 1664 if not EasterEgg.done_notification: 1665 apple_notify('On April first','turn up your volume!') 1666 EasterEgg.done_notification = True 1667 else: 1668 os.system('say %s' % msg)
1669 1670
1671 - def call_linux(self, msg):
1672 # check for fishing path 1673 fishPath = madgraph.MG5DIR+"/input/.cowgraph.cow" 1674 if os.path.exists(fishPath): 1675 fishPath = " -f " + fishPath 1676 #sprint("got fishPath: ",fishPath) 1677 1678 # check for fishing pole 1679 fishPole = which('cowthink') 1680 if not os.path.exists(fishPole): 1681 if os.path.exists(which('cowsay')): 1682 fishPole = which('cowsay') 1683 else: 1684 return 1685 1686 # go fishing 1687 fishCmd = fishPole + fishPath + " " + msg 1688 os.system(fishCmd)
1689 1690 1691 if __debug__: 1692 try: 1693 import os 1694 import pwd 1695 username =pwd.getpwuid( os.getuid() )[ 0 ] 1696 if 'hirschi' in username or 'vryonidou' in username and __debug__: 1697 EasterEgg('loading') 1698 except: 1699 pass
1700 1701 1702 -def get_older_version(v1, v2):
1703 """ return v2 if v1>v2 1704 return v1 if v1<v2 1705 return v1 if v1=v2 1706 return v1 if v2 is not in 1.2.3.4.5 format 1707 return v2 if v1 is not in 1.2.3.4.5 format 1708 """ 1709 from itertools import izip_longest 1710 for a1, a2 in izip_longest(v1, v2, fillvalue=0): 1711 try: 1712 a1= int(a1) 1713 except: 1714 return v2 1715 try: 1716 a2= int(a2) 1717 except: 1718 return v1 1719 if a1 > a2: 1720 return v2 1721 elif a1 < a2: 1722 return v1 1723 return v1
1724 1725 1726 1727 plugin_support = {}
1728 -def is_plugin_supported(obj):
1729 global plugin_support 1730 1731 name = obj.__name__ 1732 if name in plugin_support: 1733 return plugin_support[name] 1734 1735 # get MG5 version 1736 if '__mg5amcnlo__' in plugin_support: 1737 mg5_ver = plugin_support['__mg5amcnlo__'] 1738 else: 1739 info = get_pkg_info() 1740 mg5_ver = info['version'].split('.') 1741 try: 1742 min_ver = obj.minimal_mg5amcnlo_version 1743 max_ver = obj.maximal_mg5amcnlo_version 1744 val_ver = obj.latest_validated_version 1745 except: 1746 logger.error("Plugin %s misses some required info to be valid. It is therefore discarded" % name) 1747 plugin_support[name] = False 1748 return 1749 1750 if get_older_version(min_ver, mg5_ver) == min_ver and \ 1751 get_older_version(mg5_ver, max_ver) == mg5_ver: 1752 plugin_support[name] = True 1753 if get_older_version(mg5_ver, val_ver) == val_ver: 1754 logger.warning("""Plugin %s has marked as NOT being validated with this version. 1755 It has been validated for the last time with version: %s""", 1756 name, '.'.join(str(i) for i in val_ver)) 1757 else: 1758 logger.error("Plugin %s is not supported by this version of MG5aMC." % name) 1759 plugin_support[name] = False 1760 return plugin_support[name]
1761
1762 1763 #decorator 1764 -def set_global(loop=False, unitary=True, mp=False, cms=False):
1765 from functools import wraps 1766 import aloha 1767 import aloha.aloha_lib as aloha_lib 1768 def deco_set(f): 1769 @wraps(f) 1770 def deco_f_set(*args, **opt): 1771 old_loop = aloha.loop_mode 1772 old_gauge = aloha.unitary_gauge 1773 old_mp = aloha.mp_precision 1774 old_cms = aloha.complex_mass 1775 aloha.loop_mode = loop 1776 aloha.unitary_gauge = unitary 1777 aloha.mp_precision = mp 1778 aloha.complex_mass = cms 1779 aloha_lib.KERNEL.clean() 1780 try: 1781 out = f(*args, **opt) 1782 except: 1783 aloha.loop_mode = old_loop 1784 aloha.unitary_gauge = old_gauge 1785 aloha.mp_precision = old_mp 1786 aloha.complex_mass = old_cms 1787 raise 1788 aloha.loop_mode = old_loop 1789 aloha.unitary_gauge = old_gauge 1790 aloha.mp_precision = old_mp 1791 aloha.complex_mass = old_cms 1792 aloha_lib.KERNEL.clean() 1793 return out
1794 return deco_f_set 1795 return deco_set 1796 1797 1798 1799 1800 1801 1802 1803 python_lhapdf=None
1804 -def import_python_lhapdf(lhapdfconfig):
1805 """load the python module of lhapdf return None if it can not be loaded""" 1806 1807 #save the result to have it faster and avoid the segfault at the second try if lhapdf is not compatible 1808 global python_lhapdf 1809 if python_lhapdf: 1810 if python_lhapdf == -1: 1811 return None 1812 else: 1813 return python_lhapdf 1814 1815 use_lhapdf=False 1816 try: 1817 lhapdf_libdir=subprocess.Popen([lhapdfconfig,'--libdir'],\ 1818 stdout=subprocess.PIPE).stdout.read().strip() 1819 except: 1820 use_lhapdf=False 1821 return False 1822 else: 1823 try: 1824 candidates=[dirname for dirname in os.listdir(lhapdf_libdir) \ 1825 if os.path.isdir(os.path.join(lhapdf_libdir,dirname))] 1826 except OSError: 1827 candidates=[] 1828 for candidate in candidates: 1829 if os.path.isfile(os.path.join(lhapdf_libdir,candidate,'site-packages','lhapdf.so')): 1830 sys.path.insert(0,os.path.join(lhapdf_libdir,candidate,'site-packages')) 1831 try: 1832 import lhapdf 1833 use_lhapdf=True 1834 break 1835 except ImportError: 1836 sys.path.pop(0) 1837 continue 1838 if not use_lhapdf: 1839 try: 1840 candidates=[dirname for dirname in os.listdir(lhapdf_libdir+'64') \ 1841 if os.path.isdir(os.path.join(lhapdf_libdir+'64',dirname))] 1842 except OSError: 1843 candidates=[] 1844 for candidate in candidates: 1845 if os.path.isfile(os.path.join(lhapdf_libdir+'64',candidate,'site-packages','lhapdf.so')): 1846 sys.path.insert(0,os.path.join(lhapdf_libdir+'64',candidate,'site-packages')) 1847 try: 1848 import lhapdf 1849 use_lhapdf=True 1850 break 1851 except ImportError: 1852 sys.path.pop(0) 1853 continue 1854 if not use_lhapdf: 1855 try: 1856 import lhapdf 1857 use_lhapdf=True 1858 except ImportError: 1859 print 'fail' 1860 logger.warning("Failed to access python version of LHAPDF: "\ 1861 "If the python interface to LHAPDF is available on your system, try "\ 1862 "adding its location to the PYTHONPATH environment variable and the"\ 1863 "LHAPDF library location to LD_LIBRARY_PATH (linux) or DYLD_LIBRARY_PATH (mac os x).") 1864 1865 if use_lhapdf: 1866 python_lhapdf = lhapdf 1867 python_lhapdf.setVerbosity(0) 1868 else: 1869 python_lhapdf = None 1870 return python_lhapdf
1871 1872 ############################### TRACQER FOR OPEN FILE 1873 #openfiles = set() 1874 #oldfile = __builtin__.file 1875 # 1876 #class newfile(oldfile): 1877 # done = 0 1878 # def __init__(self, *args): 1879 # self.x = args[0] 1880 # if 'matplotlib' in self.x: 1881 # raise Exception 1882 # print "### OPENING %s ### %s " % (str(self.x) , time.time()-start) 1883 # oldfile.__init__(self, *args) 1884 # openfiles.add(self) 1885 # 1886 # def close(self): 1887 # print "### CLOSING %s ### %s" % (str(self.x), time.time()-start) 1888 # oldfile.close(self) 1889 # openfiles.remove(self) 1890 #oldopen = __builtin__.open 1891 #def newopen(*args): 1892 # return newfile(*args) 1893 #__builtin__.file = newfile 1894 #__builtin__.open = newopen 1895