1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 """A set of functions performing routine administrative I/O tasks."""
17
18 import contextlib
19 import itertools
20 import logging
21 import os
22 import re
23 import signal
24 import subprocess
25 import sys
26 import StringIO
27 import sys
28 import optparse
29 import time
30 import shutil
31 import traceback
32 import gzip as ziplib
33
34 try:
35
36 import madgraph
37 except Exception, error:
38
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
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
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
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
120 if info_str:
121 info_dict = parse_info_str(StringIO.StringIO(info_str))
122
123 elif MADEVENT:
124 info_dict ={}
125 info_dict['version'] = open(pjoin(internal.__path__[0],'..','..','MGMEVersion.txt')).read().strip()
126 info_dict['date'] = '20xx-xx-xx'
127 else:
128 info_dict = files.read_from_file(os.path.join(madgraph.__path__[0],
129 "VERSION"),
130 parse_info_str,
131 print_error=False)
132
133 return info_dict
134
139 """Returns the present time info for use in MG5 command history header.
140 """
141
142 creation_time = time.asctime()
143 time_info = {'time': creation_time,
144 'fill': ' ' * (26 - len(creation_time))}
145
146 return time_info
147
152 """Browse the subdirectories of the path 'start_path' and returns the first
153 one found which contains at least one file ending with the string extension
154 given in argument."""
155
156 if not os.path.isdir(start_path):
157 return None
158 subdirs=[pjoin(start_path,dir) for dir in os.listdir(start_path)]
159 for subdir in subdirs:
160 if os.path.isfile(subdir):
161 if os.path.basename(subdir).endswith(extension):
162 return start_path
163 elif os.path.isdir(subdir):
164 path = find_includes_path(subdir, extension)
165 if path:
166 return path
167 return None
168
174 """ Get whether ninja supports quad prec in different ways"""
175
176
177 ninja_config = os.path.abspath(pjoin(
178 ninja_lib_path,os.pardir,'bin','ninja-config'))
179 if os.path.exists(ninja_config):
180 try:
181 p = Popen([ninja_config, '-quadsupport'], stdout=subprocess.PIPE,
182 stderr=subprocess.PIPE)
183 output, error = p.communicate()
184 return 'TRUE' in output.upper()
185 except Exception:
186 pass
187
188
189
190 return False
191
192
193
194
195 -def which(program):
196 def is_exe(fpath):
197 return os.path.exists(fpath) and os.access(\
198 os.path.realpath(fpath), os.X_OK)
199
200 if not program:
201 return None
202
203 fpath, fname = os.path.split(program)
204 if fpath:
205 if is_exe(program):
206 return program
207 else:
208 for path in os.environ["PATH"].split(os.pathsep):
209 exe_file = os.path.join(path, program)
210 if is_exe(exe_file):
211 return exe_file
212 return None
213
229
235 """ Make sure to turn off some dependency of MG5aMC. """
236
237 def tell(msg):
238 if log == 'stdout':
239 print msg
240 elif callable(log):
241 log(msg)
242
243
244 if dependency in ['pjfry','golem','samurai','ninja','collier']:
245 if cmd.options[dependency] not in ['None',None,'']:
246 tell("Deactivating MG5_aMC dependency '%s'"%dependency)
247 cmd.options[dependency] = None
248
250 """ Checks whether the specfieid MG dependency can be activated if it was
251 not turned off in MG5 options."""
252
253 def tell(msg):
254 if log == 'stdout':
255 print msg
256 elif callable(log):
257 log(msg)
258
259 if cmd is None:
260 cmd = MGCmd.MasterCmd()
261
262 if dependency=='pjfry':
263 if cmd.options['pjfry'] in ['None',None,''] or \
264 (cmd.options['pjfry'] == 'auto' and which_lib('libpjfry.a') is None) or\
265 which_lib(pjoin(cmd.options['pjfry'],'libpjfry.a')) is None:
266 tell("Installing PJFry...")
267 cmd.do_install('PJFry')
268
269 if dependency=='golem':
270 if cmd.options['golem'] in ['None',None,''] or\
271 (cmd.options['golem'] == 'auto' and which_lib('libgolem.a') is None) or\
272 which_lib(pjoin(cmd.options['golem'],'libgolem.a')) is None:
273 tell("Installing Golem95...")
274 cmd.do_install('Golem95')
275
276 if dependency=='samurai':
277 raise MadGraph5Error, 'Samurai cannot yet be automatically installed.'
278
279 if dependency=='ninja':
280 if cmd.options['ninja'] in ['None',None,''] or\
281 (cmd.options['ninja'] == './HEPTools/lib' and not MG5dir is None and\
282 which_lib(pjoin(MG5dir,cmd.options['ninja'],'libninja.a')) is None):
283 tell("Installing ninja...")
284 cmd.do_install('ninja')
285
286 if dependency=='collier':
287 if cmd.options['collier'] in ['None',None,''] or\
288 (cmd.options['collier'] == 'auto' and which_lib('libcollier.a') is None) or\
289 which_lib(pjoin(cmd.options['collier'],'libcollier.a')) is None:
290 tell("Installing COLLIER...")
291 cmd.do_install('collier')
292
297 def is_lib(fpath):
298 return os.path.exists(fpath) and os.access(fpath, os.R_OK)
299
300 if not lib:
301 return None
302
303 fpath, fname = os.path.split(lib)
304 if fpath:
305 if is_lib(lib):
306 return lib
307 else:
308 locations = sum([os.environ[env_path].split(os.pathsep) for env_path in
309 ["DYLD_LIBRARY_PATH","LD_LIBRARY_PATH","LIBRARY_PATH","PATH"]
310 if env_path in os.environ],[])
311 for path in locations:
312 lib_file = os.path.join(path, lib)
313 if is_lib(lib_file):
314 return lib_file
315 return None
316
321 """ Return nice information on the current variable """
322
323
324 info = [('type',type(var)),('str', var)]
325 if hasattr(var, 'func_doc'):
326 info.append( ('DOC', var.func_doc) )
327 if hasattr(var, '__doc__'):
328 info.append( ('DOC', var.__doc__) )
329 if hasattr(var, '__dict__'):
330 info.append( ('ATTRIBUTE', var.__dict__.keys() ))
331
332 spaces = ' ' * nb_space
333
334 outstr=''
335 for name, value in info:
336 outstr += '%s%3s : %s\n' % (spaces,name, value)
337
338 return outstr
339
340
341
342
343 wait_once = False
345
346 def deco_retry(f):
347 def deco_f_retry(*args, **opt):
348 for i in range(nb_try):
349 try:
350 return f(*args, **opt)
351 except KeyboardInterrupt:
352 raise
353 except Exception, error:
354 global wait_once
355 if not wait_once:
356 text = """Start waiting for update. (more info in debug mode)"""
357 logger.info(text)
358 logger_stderr.debug('fail to do %s function with %s args. %s try on a max of %s (%s waiting time)' %
359 (str(f), ', '.join([str(a) for a in args]), i+1, nb_try, sleep * (i+1)))
360 logger_stderr.debug('error is %s' % str(error))
361 if __debug__: logger_stderr.debug('and occurred at :'+traceback.format_exc())
362 wait_once = True
363 time.sleep(sleep * (i+1))
364
365 if __debug__:
366 raise
367 raise error.__class__, '[Fail %i times] \n %s ' % (i+1, error)
368 return deco_f_retry
369 return deco_retry
370
375 """return a name of the type xxxx[A-B]yyy
376 where xxx and yyy are the common part between the two names.
377 """
378
379
380 base = [first[i] for i in range(len(first)) if first[:i+1] == last[:i+1]]
381
382 while base and base[0].isdigit():
383 base = base[1:]
384
385 end = [first[-(i+1)] for i in range(len(first)) if first[-(i+1):] == last[-(i+1):]]
386
387 while end and end[-1].isdigit():
388 end = end[:-1]
389 end.reverse()
390
391 base, end = ''.join(base), ''.join(end)
392 if end:
393 name = "%s[%s-%s]%s" % (base, first[len(base):-len(end)], last[len(base):-len(end)],end)
394 else:
395 name = "%s[%s-%s]%s" % (base, first[len(base):], last[len(base):],end)
396 return name
397
398
399
400
401 -def compile(arg=[], cwd=None, mode='fortran', job_specs = True, nb_core=1 ,**opt):
402 """compile a given directory"""
403
404 if 'nocompile' in opt:
405 if opt['nocompile'] == True:
406 if not arg:
407 return
408 if cwd:
409 executable = pjoin(cwd, arg[0])
410 else:
411 executable = arg[0]
412 if os.path.exists(executable):
413 return
414 del opt['nocompile']
415
416 cmd = ['make']
417 try:
418 if nb_core > 1:
419 cmd.append('-j%s' % nb_core)
420 cmd += arg
421 p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
422 stderr=subprocess.STDOUT, cwd=cwd, **opt)
423 (out, err) = p.communicate()
424 except OSError, error:
425 if cwd and not os.path.exists(cwd):
426 raise OSError, 'Directory %s doesn\'t exists. Impossible to run make' % cwd
427 else:
428 error_text = "Impossible to compile %s directory\n" % cwd
429 error_text += "Trying to launch make command returns:\n"
430 error_text += " " + str(error) + "\n"
431 error_text += "In general this means that your computer is not able to compile."
432 if sys.platform == "darwin":
433 error_text += "Note that MacOSX doesn\'t have gmake/gfortan install by default.\n"
434 error_text += "Xcode3 contains those required programs"
435 raise MadGraph5Error, error_text
436
437 if p.returncode:
438
439 if not cwd:
440 cwd = os.getcwd()
441 all_file = [f.lower() for f in os.listdir(cwd)]
442 if 'makefile' not in all_file and '-f' not in arg:
443 raise OSError, 'no makefile present in %s' % os.path.realpath(cwd)
444
445 if mode == 'fortran' and not (which('g77') or which('gfortran')):
446 error_msg = 'A fortran compiler (g77 or gfortran) is required to create this output.\n'
447 error_msg += 'Please install g77 or gfortran on your computer and retry.'
448 raise MadGraph5Error, error_msg
449 elif mode == 'cpp' and not which('g++'):
450 error_msg ='A C++ compiler (g++) is required to create this output.\n'
451 error_msg += 'Please install g++ (which is part of the gcc package) on your computer and retry.'
452 raise MadGraph5Error, error_msg
453
454
455 if any(tag.upper() in out.upper() for tag in ['real(kind=16)','real*16',
456 'complex*32']) and mode == 'fortran' and not \
457 ''.join(get_gfortran_version().split('.')) >= '46':
458 if not which('gfortran'):
459 raise MadGraph5Error, 'The fortran compiler gfortran v4.6 or later '+\
460 'is required to compile %s.\nPlease install it and retry.'%cwd
461 else:
462 logger_stderr.error('ERROR, you could not compile %s because'%cwd+\
463 ' your version of gfortran is older than 4.6. MadGraph5_aMC@NLO will carry on,'+\
464 ' but will not be able to compile an executable.')
465 return p.returncode
466
467 error_text = 'A compilation Error occurs '
468 if cwd:
469 error_text += 'when trying to compile %s.\n' % cwd
470 error_text += 'The compilation fails with the following output message:\n'
471 error_text += ' '+out.replace('\n','\n ')+'\n'
472 error_text += 'Please try to fix this compilations issue and retry.\n'
473 error_text += 'Help might be found at https://answers.launchpad.net/mg5amcnlo.\n'
474 error_text += 'If you think that this is a bug, you can report this at https://bugs.launchpad.net/mg5amcnlo'
475 raise MadGraph5Error, error_text
476 return p.returncode
477
479 """ Returns the gfortran version as a string.
480 Returns '0' if it failed."""
481 try:
482 p = Popen([compiler, '-dumpversion'], stdout=subprocess.PIPE,
483 stderr=subprocess.PIPE)
484 output, error = p.communicate()
485 version_finder=re.compile(r"(?P<version>(\d.)*\d)")
486 version = version_finder.search(output).group('version')
487 return version
488 except Exception:
489 return '0'
490
491 -def mod_compilator(directory, new='gfortran', current=None, compiler_type='gfortran'):
492
493 if type(directory)!=list:
494 directory=[directory]
495
496
497 file_to_change=find_makefile_in_dir(directory)
498 if compiler_type == 'gfortran':
499 comp_re = re.compile('^(\s*)FC\s*=\s*(.+)\s*$')
500 var = 'FC'
501 elif compiler_type == 'cpp':
502 comp_re = re.compile('^(\s*)CXX\s*=\s*(.+)\s*$')
503 var = 'CXX'
504 else:
505 MadGraph5Error, 'Unknown compiler type: %s' % compiler_type
506
507 mod = False
508 for name in file_to_change:
509 lines = open(name,'r').read().split('\n')
510 for iline, line in enumerate(lines):
511 result = comp_re.match(line)
512 if result:
513 if new != result.group(2) and '$' not in result.group(2):
514 mod = True
515 lines[iline] = result.group(1) + var + "=" + new
516 elif compiler_type == 'gfortran' and line.startswith('DEFAULT_F_COMPILER'):
517 lines[iline] = "DEFAULT_F_COMPILER = %s" % new
518 elif compiler_type == 'cpp' and line.startswith('DEFAULT_CPP_COMPILER'):
519 lines[iline] = "DEFAULT_CPP_COMPILER = %s" % new
520
521 if mod:
522 open(name,'w').write('\n'.join(lines))
523
524 mod = False
525
530 """mute_logger (designed to work as with statement),
531 files allow to redirect the output of the log to a given file.
532 """
533
534 - def __init__(self, names, levels, files=None, **opt):
535 assert isinstance(names, list)
536 assert isinstance(names, list)
537
538 self.names = names
539 self.levels = levels
540 if isinstance(files, list):
541 self.files = files
542 else:
543 self.files = [files] * len(names)
544 self.logger_saved_info = {}
545 self.opts = opt
546
557
558 - def __exit__(self, ctype, value, traceback ):
569
571 """ Setup the logger by redirecting them all to logfiles in tmp """
572
573 logs = full_logname.split('.')
574 lognames = [ '.'.join(logs[:(len(logs)-i)]) for i in\
575 range(len(full_logname.split('.')))]
576 for logname in lognames:
577 try:
578 os.remove(path)
579 except Exception, error:
580 pass
581 my_logger = logging.getLogger(logname)
582 hdlr = logging.FileHandler(path)
583
584
585 self.logger_saved_info[logname] = [hdlr, my_logger.handlers]
586
587
588 for old_hdlr in list(my_logger.handlers):
589 my_logger.removeHandler(old_hdlr)
590 my_logger.addHandler(hdlr)
591
592 my_logger.debug('Log of %s' % logname)
593
595 """ Setup the logger by redirecting them all to logfiles in tmp """
596
597 logs = full_logname.split('.')
598 lognames = [ '.'.join(logs[:(len(logs)-i)]) for i in\
599 range(len(full_logname.split('.')))]
600 for logname in lognames:
601 if path:
602 try:
603 os.remove(path)
604 except Exception, error:
605 pass
606 my_logger = logging.getLogger(logname)
607 if logname in self.logger_saved_info:
608 my_logger.removeHandler(self.logger_saved_info[logname][0])
609 for old_hdlr in self.logger_saved_info[logname][1]:
610 my_logger.addHandler(old_hdlr)
611 else:
612 my_logger.setLevel(level)
613
614
615
616
617 nb_open =0
620 """
621 A context manager to temporarily redirect stdout or stderr
622
623 e.g.:
624
625
626 with stdchannel_redirected(sys.stderr, os.devnull):
627 if compiler.has_function('clock_gettime', libraries=['rt']):
628 libraries.append('rt')
629 """
630
631 try:
632 oldstdchannel = os.dup(stdchannel.fileno())
633 dest_file = open(dest_filename, 'w')
634 os.dup2(dest_file.fileno(), stdchannel.fileno())
635 yield
636 finally:
637 if oldstdchannel is not None:
638 os.dup2(oldstdchannel, stdchannel.fileno())
639 os.close(oldstdchannel)
640 if dest_file is not None:
641 dest_file.close()
642
644 '''
645 return the number of open file descriptors for current process
646
647 .. warning: will only work on UNIX-like os-es.
648 '''
649 import subprocess
650 import os
651
652 pid = os.getpid()
653 procs = subprocess.check_output(
654 [ "lsof", '-w', '-Ff', "-p", str( pid ) ] )
655 nprocs = filter(
656 lambda s: s and s[ 0 ] == 'f' and s[1: ].isdigit(),
657 procs.split( '\n' ) )
658
659 return nprocs
660
662 """ Detects whether the specified C++ compiler is clang."""
663
664 try:
665 p = Popen([cpp_compiler, '--version'], stdout=subprocess.PIPE,
666 stderr=subprocess.PIPE)
667 output, error = p.communicate()
668 except Exception, error:
669
670 return False
671 return 'LLVM' in output
672
674 """ Detects if the specified c++ compiler will normally link against the C++
675 standard library -lc++ or -libstdc++."""
676
677 is_clang = detect_if_cpp_compiler_is_clang(cpp_compiler)
678 if is_clang:
679 try:
680 import platform
681 v, _,_ = platform.mac_ver()
682 if not v:
683
684
685 return '-lc++'
686 else:
687 v = float(v.rsplit('.')[1])
688 if v >= 9:
689 return '-lc++'
690 else:
691 return '-lstdc++'
692 except:
693 return '-lstdc++'
694 return '-lstdc++'
695
697 """find the current compiler for the current directory"""
698
699
700
701 if compiler_type == 'fortran':
702 comp = re.compile("^\s*FC\s*=\s*([\w\/\\.\-]+)\s*")
703 elif compiler_type == 'cpp':
704 comp = re.compile("^\s*CXX\s*=\s*([\w\/\\.\-]+)\s*")
705 else:
706 MadGraph5Error, 'Unknown compiler type: %s' % compiler_type
707
708 for line in open(path):
709 if comp.search(line):
710 compiler = comp.search(line).groups()[0]
711 return compiler
712 elif compiler_type == 'fortran' and line.startswith('DEFAULT_F_COMPILER'):
713 return line.split('=')[1].strip()
714 elif compiler_type == 'cpp' and line.startswith('DEFAULT_CPP_COMPILER'):
715 return line.split('=')[1].strip()
716
718 """ return a list of all file starting with makefile in the given directory"""
719
720 out=[]
721
722 if type(directory)==list:
723 for name in directory:
724 out+=find_makefile_in_dir(name)
725 return out
726
727
728 for name in os.listdir(directory):
729 if os.path.isdir(directory+'/'+name):
730 out+=find_makefile_in_dir(directory+'/'+name)
731 elif os.path.isfile(directory+'/'+name) and name.lower().startswith('makefile'):
732 out.append(directory+'/'+name)
733 elif os.path.isfile(directory+'/'+name) and name.lower().startswith('make_opt'):
734 out.append(directory+'/'+name)
735 return out
736
738
739
740 os.path.walk('.', rm_file_extension, '.o')
741
742
743 libraries = ['libblocks.a', 'libgeneric_mw.a', 'libMWPS.a', 'libtools.a', 'libdhelas3.a',
744 'libdsample.a', 'libgeneric.a', 'libmodel.a', 'libpdf.a', 'libdhelas3.so', 'libTF.a',
745 'libdsample.so', 'libgeneric.so', 'libmodel.so', 'libpdf.so']
746 lib_pos='./lib'
747 [os.remove(os.path.join(lib_pos, lib)) for lib in libraries \
748 if os.path.exists(os.path.join(lib_pos, lib))]
749
763
767
771 replace_dict = dict(key_values)
772 replacement_function = lambda match: replace_dict[match.group(0)]
773 pattern = re.compile("|".join([re.escape(k) for k, v in key_values]), re.M)
774 return lambda string: pattern.sub(replacement_function, string)
775
778
781 def deco_check(f):
782 def deco_f(arg, *args, **opt):
783 try:
784 return f(arg, *args, **opt)
785 except OSError, error:
786 logger.debug('try to recover from %s' % error)
787 if isinstance(arg, list):
788 prog = arg[0]
789 else:
790 prog = arg[0]
791
792
793 if error.errno == 13:
794 if os.path.exists(prog):
795 os.system('chmod +x %s' % prog)
796 elif 'cwd' in opt and opt['cwd'] and \
797 os.path.isfile(pjoin(opt['cwd'],arg[0])):
798 os.system('chmod +x %s' % pjoin(opt['cwd'],arg[0]))
799 return f(arg, *args, **opt)
800
801 elif error.errno == 2:
802
803 raise Exception, '%s fails with no such file or directory' \
804 % arg
805 else:
806 raise
807 return deco_f
808 return deco_check
809
810
811 @check_system_error()
812 -def call(arg, *args, **opt):
813 """nice way to call an external program with nice error treatment"""
814 try:
815 return subprocess.call(arg, *args, **opt)
816 except OSError:
817 arg[0] = './%s' % arg[0]
818 return subprocess.call(arg, *args, **opt)
819
820 @check_system_error()
821 -def Popen(arg, *args, **opt):
822 """nice way to call an external program with nice error treatment"""
823 return subprocess.Popen(arg, *args, **opt)
824
827 """try to open a file with multiple try to ensure that filesystem is sync"""
828 return open(filepath, *args, ** opt)
829
830
831
832
833 -def tail(f, n, offset=None):
834 """Reads a n lines from f with an offset of offset lines. The return
835 value is a tuple in the form ``lines``.
836 """
837 avg_line_length = 74
838 to_read = n + (offset or 0)
839
840 while 1:
841 try:
842 f.seek(-(avg_line_length * to_read), 2)
843 except IOError:
844
845
846 f.seek(0)
847 pos = f.tell()
848 lines = f.read().splitlines()
849 if len(lines) >= to_read or pos == 0:
850 return lines[-to_read:offset and -offset or None]
851 avg_line_length *= 1.3
852 avg_line_length = int(avg_line_length)
853
855 """ makes a piping fifo (First-in First-out) file and nicely intercepts
856 error in case the file format of the target drive doesn't suppor tit."""
857
858 try:
859 os.mkfifo(fifo_path)
860 except:
861 raise OSError('MadGraph5_aMCatNLO could not create a fifo file at:\n'+
862 ' %s\n'%fifo_path+'Make sure that this file does not exist already'+
863 ' and that the file format of the target drive supports fifo file (i.e not NFS).')
864
869 """return the last line of a file"""
870
871 return tail(fsock, 1)[0]
872
874 """read a file returning the lines in reverse order for each call of readline()
875 This actually just reads blocks (4096 bytes by default) of data from the end of
876 the file and returns last line in an internal buffer."""
877
878
880 """ readline in a backward way """
881
882 while len(self.data) == 1 and ((self.blkcount * self.blksize) < self.size):
883 self.blkcount = self.blkcount + 1
884 line = self.data[0]
885 try:
886 self.seek(-self.blksize * self.blkcount, 2)
887 self.data = (self.read(self.blksize) + line).split('\n')
888 except IOError:
889 self.seek(0)
890 data = self.read(self.size - (self.blksize * (self.blkcount-1))) + line
891 self.data = data.split('\n')
892
893 if len(self.data) == 0:
894 return ""
895
896 line = self.data.pop()
897 return line + '\n'
898
899 - def __init__(self, filepos, blksize=4096):
900 """initialize the internal structures"""
901
902
903 self.size = os.stat(filepos)[6]
904
905 self.blksize = blksize
906
907 self.blkcount = 1
908 file.__init__(self, filepos, 'rb')
909
910
911 if self.size > self.blksize:
912 self.seek(-self.blksize * self.blkcount, 2)
913 self.data = self.read(self.blksize).split('\n')
914
915
916 if not self.data[-1]:
917 self.data.pop()
918
920 line = self.readline()
921 if line:
922 return line
923 else:
924 raise StopIteration
925
941
955
961 """create a temporary directory and ensure this one to be cleaned.
962 """
963
964 - def __init__(self, suffix='', prefix='tmp', dir=None):
965 self.nb_try_remove = 0
966 import tempfile
967 self.path = tempfile.mkdtemp(suffix, prefix, dir)
968
969
970 - def __exit__(self, ctype, value, traceback ):
971
972 if False and isinstance(value, Exception):
973 sprint("Directory %s not cleaned. This directory can be removed manually" % self.path)
974 return False
975 try:
976 shutil.rmtree(self.path)
977 except OSError:
978 self.nb_try_remove += 1
979 if self.nb_try_remove < 3:
980 time.sleep(10)
981 self.__exit__(ctype, value, traceback)
982 else:
983 logger.warning("Directory %s not completely cleaned. This directory can be removed manually" % self.path)
984
987
989 """create a temporary directory and ensure this one to be cleaned.
990 """
991
992 - def __init__(self, cls, attribute, value):
993
994 self.cls = cls
995 self.attribute = attribute
996 if isinstance(attribute, list):
997 self.old_value = []
998 for key, onevalue in zip(attribute, value):
999 self.old_value.append(getattr(cls, key))
1000 setattr(self.cls, key, onevalue)
1001 else:
1002 self.old_value = getattr(cls, attribute)
1003 setattr(self.cls, self.attribute, value)
1004
1005 - def __exit__(self, ctype, value, traceback ):
1006
1007 if isinstance(self.attribute, list):
1008 for key, old_value in zip(self.attribute, self.old_value):
1009 setattr(self.cls, key, old_value)
1010 else:
1011 setattr(self.cls, self.attribute, self.old_value)
1012
1014 return self.old_value
1015
1016
1017
1018
1019 -def gunzip(path, keep=False, stdout=None):
1020 """ a standard replacement for os.system('gunzip -f %s.gz ' % event_path)"""
1021
1022 if not path.endswith(".gz"):
1023 if os.path.exists("%s.gz" % path):
1024 path = "%s.gz" % path
1025 else:
1026 raise Exception, "%(path)s does not finish by .gz and the file %(path)s.gz does not exists" %\
1027 {"path": path}
1028
1029
1030
1031 if os.path.getsize(path) > 1e8:
1032 if stdout:
1033 os.system('gunzip -c %s > %s' % (path, stdout))
1034 else:
1035 os.system('gunzip %s' % path)
1036 return 0
1037
1038 if not stdout:
1039 stdout = path[:-3]
1040 try:
1041 gfile = ziplib.open(path, "r")
1042 except IOError:
1043 raise
1044 else:
1045 try:
1046 open(stdout,'w').write(gfile.read())
1047 except IOError:
1048
1049 if stdout == path:
1050 return
1051 else:
1052 files.cp(path, stdout)
1053
1054 if not keep:
1055 os.remove(path)
1056 return 0
1057
1058 -def gzip(path, stdout=None, error=True, forceexternal=False):
1059 """ a standard replacement for os.system('gzip %s ' % path)"""
1060
1061
1062 if os.path.getsize(path) > 1e9 or forceexternal:
1063 call(['gzip', '-f', path])
1064 if stdout:
1065 if not stdout.endswith(".gz"):
1066 stdout = "%s.gz" % stdout
1067 shutil.move('%s.gz' % path, stdout)
1068 return
1069
1070 if not stdout:
1071 stdout = "%s.gz" % path
1072 elif not stdout.endswith(".gz"):
1073 stdout = "%s.gz" % stdout
1074
1075 try:
1076 ziplib.open(stdout,"w").write(open(path).read())
1077 except OverflowError:
1078 gzip(path, stdout, error=error, forceexternal=True)
1079 except Exception:
1080 if error:
1081 raise
1082 else:
1083 os.remove(path)
1084
1089 """ a convinient class to open a file """
1090
1091 web_browser = None
1092 eps_viewer = None
1093 text_editor = None
1094 configured = False
1095
1097 """open a file"""
1098
1099
1100 if not self.configured:
1101 self.configure()
1102
1103 try:
1104 extension = filename.rsplit('.',1)[1]
1105 except IndexError:
1106 extension = ''
1107
1108
1109
1110 if extension in ['html','htm','php']:
1111 self.open_program(self.web_browser, filename, background=True)
1112 elif extension in ['ps','eps']:
1113 self.open_program(self.eps_viewer, filename, background=True)
1114 else:
1115 self.open_program(self.text_editor,filename, mac_check=False)
1116
1117
1118 @classmethod
1141
1142 @classmethod
1180
1181
1182 @staticmethod
1184 """find a valid shell program in the list"""
1185
1186 for p in possibility:
1187 if which(p):
1188 logger.info('Using default %s \"%s\". ' % (program, p) + \
1189 'Set another one in ./input/mg5_configuration.txt')
1190 return p
1191
1192 logger.info('No valid %s found. ' % program + \
1193 'Please set in ./input/mg5_configuration.txt')
1194 return None
1195
1196
1197 - def open_program(self, program, file_path, mac_check=True, background=False):
1198 """ open a file with a given program """
1199
1200 if mac_check==True and sys.platform == 'darwin':
1201 return self.open_mac_program(program, file_path)
1202
1203
1204 if program:
1205 arguments = program.split()
1206 arguments.append(file_path)
1207
1208 if not background:
1209 subprocess.call(arguments)
1210 else:
1211 import thread
1212 thread.start_new_thread(subprocess.call,(arguments,))
1213 else:
1214 logger.warning('Not able to open file %s since no program configured.' % file_path + \
1215 'Please set one in ./input/mg5_configuration.txt')
1216
1218 """ open a text with the text editor """
1219
1220 if not program:
1221
1222 os.system('open %s' % file_path)
1223 elif which(program):
1224
1225 arguments = program.split()
1226 arguments.append(file_path)
1227 subprocess.call(arguments)
1228 else:
1229
1230 os.system('open -a %s %s' % (program, file_path))
1231
1251
1253 """ Try and guess what shell type does the user use."""
1254 try:
1255 if os.environ['SHELL'].endswith('bash'):
1256 return 'bash'
1257 elif os.environ['SHELL'].endswith('tcsh'):
1258 return 'tcsh'
1259 else:
1260
1261 return None
1262 except KeyError:
1263 return None
1264
1266 """ check if a path is executable"""
1267 try:
1268 return os.access(path, os.X_OK)
1269 except Exception:
1270 return False
1271
1273 """Option Peaser which raise an error instead as calling exit"""
1274
1275 - def exit(self, status=0, msg=None):
1280
1282 """Returns the current line number in our program."""
1283
1284 if not __debug__:
1285 return
1286
1287 use_print = False
1288 import inspect
1289 if opt.has_key('cond') and not opt['cond']:
1290 return
1291
1292 if opt.has_key('log'):
1293 log = opt['log']
1294 else:
1295 log = logging.getLogger('madgraph')
1296 if opt.has_key('level'):
1297 level = opt['level']
1298 else:
1299 level = logging.getLogger('madgraph').level
1300 if level == 0:
1301 use_print = True
1302
1303
1304
1305
1306 if opt.has_key('wait'):
1307 wait = bool(opt['wait'])
1308 else:
1309 wait = False
1310
1311 lineno = inspect.currentframe().f_back.f_lineno
1312 fargs = inspect.getframeinfo(inspect.currentframe().f_back)
1313 filename, lineno = fargs[:2]
1314
1315
1316 try:
1317 source = inspect.getsourcelines(inspect.currentframe().f_back)
1318 line = source[0][lineno-source[1]]
1319 line = re.findall(r"misc\.sprint\(\s*(.*)\)\s*($|#)", line)[0][0]
1320 if line.startswith("'") and line.endswith("'") and line.count(",") ==0:
1321 line= ''
1322 elif line.startswith("\"") and line.endswith("\"") and line.count(",") ==0:
1323 line= ''
1324 elif line.startswith(("\"","'")) and len(args)==1 and "%" in line:
1325 line= ''
1326 except Exception:
1327 line=''
1328
1329 if line:
1330 intro = ' %s = \033[0m' % line
1331 else:
1332 intro = ''
1333
1334
1335 if not use_print:
1336 log.log(level, ' '.join([intro]+[str(a) for a in args]) + \
1337 ' \033[1;30m[%s at line %s]\033[0m' % (os.path.basename(filename), lineno))
1338 else:
1339 print ' '.join([intro]+[str(a) for a in args]) + \
1340 ' \033[1;30m[%s at line %s]\033[0m' % (os.path.basename(filename), lineno)
1341
1342 if wait:
1343 raw_input('press_enter to continue')
1344
1345 return
1346
1347
1348
1349
1350 -def equal(a,b,sig_fig=6, zero_limit=True):
1351 """function to check if two float are approximatively equal"""
1352 import math
1353
1354 if not a or not b:
1355 if zero_limit:
1356 power = sig_fig + 1
1357 else:
1358 return a == b
1359 else:
1360 power = sig_fig - int(math.log10(abs(a))) + 1
1361
1362 return ( a==b or abs(int(a*10**power) - int(b*10**power)) < 10)
1363
1364
1365
1366
1367
1368
1369
1370 -class chdir:
1372 self.newPath = newPath
1373
1375 self.savedPath = os.getcwd()
1376 os.chdir(self.newPath)
1377
1378 - def __exit__(self, etype, value, traceback):
1379 os.chdir(self.savedPath)
1380
1381
1382
1383
1384
1385 -def timeout(func, args=(), kwargs={}, timeout_duration=1, default=None):
1386 '''This function will spwan a thread and run the given function using the args, kwargs and
1387 return the given default value if the timeout_duration is exceeded
1388 '''
1389 import threading
1390 class InterruptableThread(threading.Thread):
1391 def __init__(self):
1392 threading.Thread.__init__(self)
1393 self.result = default
1394 def run(self):
1395 try:
1396 self.result = func(*args, **kwargs)
1397 except Exception,error:
1398 print error
1399 self.result = default
1400 it = InterruptableThread()
1401 it.start()
1402 it.join(timeout_duration)
1403 return it.result
1404
1405
1406
1407
1408
1409 -class digest:
1410
1412 try:
1413 return self.test_hashlib()
1414 except Exception:
1415 pass
1416 try:
1417 return self.test_md5()
1418 except Exception:
1419 pass
1420 try:
1421 return self.test_zlib()
1422 except Exception:
1423 pass
1424
1426 import hashlib
1427 def digest(text):
1428 """using mg5 for the hash"""
1429 t = hashlib.md5()
1430 t.update(text)
1431 return t.hexdigest()
1432 return digest
1433
1435 import md5
1436 def digest(text):
1437 """using mg5 for the hash"""
1438 t = md5.md5()
1439 t.update(text)
1440 return t.hexdigest()
1441 return digest
1442
1444 import zlib
1445 def digest(text):
1446 return zlib.adler32(text)
1447
1448 digest = digest().test_all()
1455 self.cmd_args = args
1456 self.cmd_opts = opts
1457 self.execution_state = False
1458
1460 self.max_vms_memory = 0
1461 self.max_rss_memory = 0
1462
1463 self.t1 = None
1464 self.t0 = time.time()
1465 self.p = subprocess.Popen(*self.cmd_args,**self.cmd_opts)
1466 self.execution_state = True
1467
1469 if not self.check_execution_state():
1470 return False
1471
1472 self.t1 = time.time()
1473
1474
1475
1476 flash = subprocess.Popen("ps -p %i -o rss"%self.p.pid,
1477 shell=True,stdout=subprocess.PIPE,stderr=open(os.devnull,"w"))
1478 stdout_list = flash.communicate()[0].split('\n')
1479 rss_memory = int(stdout_list[1])
1480
1481 vms_memory = 0
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510 self.max_vms_memory = max(self.max_vms_memory,vms_memory)
1511 self.max_rss_memory = max(self.max_rss_memory,rss_memory)
1512
1513 return self.check_execution_state()
1514
1516
1517
1518 return self.p.poll() == None
1519
1521 if not self.execution_state:
1522 return False
1523 if self.is_running():
1524 return True
1525 self.executation_state = False
1526 self.t1 = time.time()
1527 return False
1528
1529 - def close(self,kill=False):
1530
1531 if self.p.poll() == None:
1532 if kill:
1533 self.p.kill()
1534 else:
1535 self.p.terminate()
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548 try:
1549 import Foundation
1550 import objc
1551 NSUserNotification = objc.lookUpClass('NSUserNotification')
1552 NSUserNotificationCenter = objc.lookUpClass('NSUserNotificationCenter')
1555 try:
1556 notification = NSUserNotification.alloc().init()
1557 notification.setTitle_('MadGraph5_aMC@NLO')
1558 notification.setSubtitle_(subtitle)
1559 notification.setInformativeText_(info_text)
1560 notification.setUserInfo_(userInfo)
1561 NSUserNotificationCenter.defaultUserNotificationCenter().scheduleNotification_(notification)
1562 except:
1563 pass
1564 except:
1567
1571 """ return v2 if v1>v2
1572 return v1 if v1<v2
1573 return v1 if v1=v2
1574 return v1 if v2 is not in 1.2.3.4.5 format
1575 return v2 if v1 is not in 1.2.3.4.5 format
1576 """
1577 from itertools import izip_longest
1578 for a1, a2 in izip_longest(v1, v2, fillvalue=0):
1579 try:
1580 a1= int(a1)
1581 except:
1582 return v2
1583 try:
1584 a2= int(a2)
1585 except:
1586 return v1
1587 if a1 > a2:
1588 return v2
1589 elif a1 < a2:
1590 return v1
1591 return v1
1592
1593
1594
1595 plugin_support = {}
1629
1630
1631
1632 -def set_global(loop=False, unitary=True, mp=False, cms=False):
1662 return deco_f_set
1663 return deco_set
1664
1665
1666
1667
1668
1669
1670
1671 python_lhapdf=None
1673 """load the python module of lhapdf return None if it can not be loaded"""
1674
1675
1676 global python_lhapdf
1677 if python_lhapdf:
1678 if python_lhapdf == -1:
1679 return None
1680 else:
1681 return python_lhapdf
1682
1683 use_lhapdf=False
1684 try:
1685 lhapdf_libdir=subprocess.Popen([lhapdfconfig,'--libdir'],\
1686 stdout=subprocess.PIPE).stdout.read().strip()
1687 except:
1688 use_lhapdf=False
1689 return False
1690 else:
1691 try:
1692 candidates=[dirname for dirname in os.listdir(lhapdf_libdir) \
1693 if os.path.isdir(os.path.join(lhapdf_libdir,dirname))]
1694 except OSError:
1695 candidates=[]
1696 for candidate in candidates:
1697 if os.path.isfile(os.path.join(lhapdf_libdir,candidate,'site-packages','lhapdf.so')):
1698 sys.path.insert(0,os.path.join(lhapdf_libdir,candidate,'site-packages'))
1699 try:
1700 import lhapdf
1701 use_lhapdf=True
1702 break
1703 except ImportError:
1704 sys.path.pop(0)
1705 continue
1706 if not use_lhapdf:
1707 try:
1708 candidates=[dirname for dirname in os.listdir(lhapdf_libdir+'64') \
1709 if os.path.isdir(os.path.join(lhapdf_libdir+'64',dirname))]
1710 except OSError:
1711 candidates=[]
1712 for candidate in candidates:
1713 if os.path.isfile(os.path.join(lhapdf_libdir+'64',candidate,'site-packages','lhapdf.so')):
1714 sys.path.insert(0,os.path.join(lhapdf_libdir+'64',candidate,'site-packages'))
1715 try:
1716 import lhapdf
1717 use_lhapdf=True
1718 break
1719 except ImportError:
1720 sys.path.pop(0)
1721 continue
1722 if not use_lhapdf:
1723 try:
1724 import lhapdf
1725 use_lhapdf=True
1726 except ImportError:
1727 print 'fail'
1728 logger.warning("Failed to access python version of LHAPDF: "\
1729 "If the python interface to LHAPDF is available on your system, try "\
1730 "adding its location to the PYTHONPATH environment variable and the"\
1731 "LHAPDF library location to LD_LIBRARY_PATH (linux) or DYLD_LIBRARY_PATH (mac os x).")
1732
1733 if use_lhapdf:
1734 python_lhapdf = lhapdf
1735 python_lhapdf.setVerbosity(0)
1736 else:
1737 python_lhapdf = None
1738 return python_lhapdf
1739