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