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