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