1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 """A set of functions performing routine administrative I/O tasks."""
16
17 import contextlib
18 import itertools
19 import logging
20 import os
21 import re
22 import signal
23 import subprocess
24 import sys
25 import StringIO
26 import sys
27 import optparse
28 import time
29 import shutil
30 import traceback
31 import gzip as ziplib
32
33 try:
34
35 import madgraph
36 except Exception, error:
37
38 import internal
39 from internal import MadGraph5Error, InvalidCmd
40 import internal.files as files
41 MADEVENT = True
42 else:
43 from madgraph import MadGraph5Error, InvalidCmd
44 import madgraph.iolibs.files as files
45 MADEVENT = False
46
47
48 logger = logging.getLogger('cmdprint.ext_program')
49 logger_stderr = logging.getLogger('madevent.misc')
50 pjoin = os.path.join
56 """Parse a newline separated list of "param=value" as a dictionnary
57 """
58
59 info_dict = {}
60 pattern = re.compile("(?P<name>\w*)\s*=\s*(?P<value>.*)",
61 re.IGNORECASE | re.VERBOSE)
62 for entry in fsock:
63 entry = entry.strip()
64 if len(entry) == 0: continue
65 m = pattern.match(entry)
66 if m is not None:
67 info_dict[m.group('name')] = m.group('value')
68 else:
69 raise IOError, "String %s is not a valid info string" % entry
70
71 return info_dict
72
73
74 -def glob(name, path=''):
75 """call to glob.glob with automatic security on path"""
76 import glob as glob_module
77 path = re.sub('(?P<name>\?|\*|\[|\])', '[\g<name>]', path)
78 return glob_module.glob(pjoin(path, name))
79
80
81
82
83 -def mute_logger(names=['madgraph','ALOHA','cmdprint','madevent'], levels=[50,50,50,50]):
84 """change the logger level and restore those at their initial value at the
85 end of the function decorated."""
86 def control_logger(f):
87 def restore_old_levels(names, levels):
88 for name, level in zip(names, levels):
89 log_module = logging.getLogger(name)
90 log_module.setLevel(level)
91
92 def f_with_no_logger(self, *args, **opt):
93 old_levels = []
94 for name, level in zip(names, levels):
95 log_module = logging.getLogger(name)
96 old_levels.append(log_module.level)
97 log_module.setLevel(level)
98 try:
99 out = f(self, *args, **opt)
100 restore_old_levels(names, old_levels)
101 return out
102 except:
103 restore_old_levels(names, old_levels)
104 raise
105
106 return f_with_no_logger
107 return control_logger
108
109 PACKAGE_INFO = {}
114 """Returns the current version information of the MadGraph5_aMC@NLO package,
115 as written in the VERSION text file. If the file cannot be found,
116 a dictionary with empty values is returned. As an option, an info
117 string can be passed to be read instead of the file content.
118 """
119 global PACKAGE_INFO
120
121 if info_str:
122 info_dict = parse_info_str(StringIO.StringIO(info_str))
123
124 elif MADEVENT:
125 info_dict ={}
126 info_dict['version'] = open(pjoin(internal.__path__[0],'..','..','MGMEVersion.txt')).read().strip()
127 info_dict['date'] = '20xx-xx-xx'
128 else:
129 if PACKAGE_INFO:
130 return PACKAGE_INFO
131 info_dict = files.read_from_file(os.path.join(madgraph.__path__[0],
132 "VERSION"),
133 parse_info_str,
134 print_error=False)
135 PACKAGE_INFO = info_dict
136
137 return info_dict
138
143 """Returns the present time info for use in MG5 command history header.
144 """
145
146 creation_time = time.asctime()
147 time_info = {'time': creation_time,
148 'fill': ' ' * (26 - len(creation_time))}
149
150 return time_info
151
156 """Browse the subdirectories of the path 'start_path' and returns the first
157 one found which contains at least one file ending with the string extension
158 given in argument."""
159
160 if not os.path.isdir(start_path):
161 return None
162 subdirs=[pjoin(start_path,dir) for dir in os.listdir(start_path)]
163 for subdir in subdirs:
164 if os.path.isfile(subdir):
165 if os.path.basename(subdir).endswith(extension):
166 return start_path
167 elif os.path.isdir(subdir):
168 path = find_includes_path(subdir, extension)
169 if path:
170 return path
171 return None
172
178 """ Get whether ninja supports quad prec in different ways"""
179
180
181 ninja_config = os.path.abspath(pjoin(
182 ninja_lib_path,os.pardir,'bin','ninja-config'))
183 if os.path.exists(ninja_config):
184 try:
185 p = Popen([ninja_config, '-quadsupport'], stdout=subprocess.PIPE,
186 stderr=subprocess.PIPE)
187 output, error = p.communicate()
188 return 'TRUE' in output.upper()
189 except Exception:
190 pass
191
192
193
194 return False
195
196
197
198
199 -def which(program):
200 def is_exe(fpath):
201 return os.path.exists(fpath) and os.access(\
202 os.path.realpath(fpath), os.X_OK)
203
204 if not program:
205 return None
206
207 fpath, fname = os.path.split(program)
208 if fpath:
209 if is_exe(program):
210 return program
211 else:
212 for path in os.environ["PATH"].split(os.pathsep):
213 exe_file = os.path.join(path, program)
214 if is_exe(exe_file):
215 return exe_file
216 return None
217
233
239 """ Make sure to turn off some dependency of MG5aMC. """
240
241 def tell(msg):
242 if log == 'stdout':
243 print msg
244 elif callable(log):
245 log(msg)
246
247
248 if dependency in ['pjfry','golem','samurai','ninja','collier']:
249 if cmd.options[dependency] not in ['None',None,'']:
250 tell("Deactivating MG5_aMC dependency '%s'"%dependency)
251 cmd.options[dependency] = None
252
254 """ Checks whether the specfieid MG dependency can be activated if it was
255 not turned off in MG5 options."""
256
257 def tell(msg):
258 if log == 'stdout':
259 print msg
260 elif callable(log):
261 log(msg)
262
263 if cmd is None:
264 cmd = MGCmd.MasterCmd()
265
266 if dependency=='pjfry':
267 if cmd.options['pjfry'] in ['None',None,''] or \
268 (cmd.options['pjfry'] == 'auto' and which_lib('libpjfry.a') is None) or\
269 which_lib(pjoin(cmd.options['pjfry'],'libpjfry.a')) is None:
270 tell("Installing PJFry...")
271 cmd.do_install('PJFry')
272
273 if dependency=='golem':
274 if cmd.options['golem'] in ['None',None,''] or\
275 (cmd.options['golem'] == 'auto' and which_lib('libgolem.a') is None) or\
276 which_lib(pjoin(cmd.options['golem'],'libgolem.a')) is None:
277 tell("Installing Golem95...")
278 cmd.do_install('Golem95')
279
280 if dependency=='samurai':
281 raise MadGraph5Error, 'Samurai cannot yet be automatically installed.'
282
283 if dependency=='ninja':
284 if cmd.options['ninja'] in ['None',None,''] or\
285 (cmd.options['ninja'] == './HEPTools/lib' and not MG5dir is None and\
286 which_lib(pjoin(MG5dir,cmd.options['ninja'],'libninja.a')) is None):
287 tell("Installing ninja...")
288 cmd.do_install('ninja')
289
290 if dependency=='collier':
291 if cmd.options['collier'] in ['None',None,''] or\
292 (cmd.options['collier'] == 'auto' and which_lib('libcollier.a') is None) or\
293 which_lib(pjoin(cmd.options['collier'],'libcollier.a')) is None:
294 tell("Installing COLLIER...")
295 cmd.do_install('collier')
296
301 def is_lib(fpath):
302 return os.path.exists(fpath) and os.access(fpath, os.R_OK)
303
304 if not lib:
305 return None
306
307 fpath, fname = os.path.split(lib)
308 if fpath:
309 if is_lib(lib):
310 return lib
311 else:
312 locations = sum([os.environ[env_path].split(os.pathsep) for env_path in
313 ["DYLD_LIBRARY_PATH","LD_LIBRARY_PATH","LIBRARY_PATH","PATH"]
314 if env_path in os.environ],[])
315 for path in locations:
316 lib_file = os.path.join(path, lib)
317 if is_lib(lib_file):
318 return lib_file
319 return None
320
325 """ Return nice information on the current variable """
326
327
328 info = [('type',type(var)),('str', var)]
329 if hasattr(var, 'func_doc'):
330 info.append( ('DOC', var.func_doc) )
331 if hasattr(var, '__doc__'):
332 info.append( ('DOC', var.__doc__) )
333 if hasattr(var, '__dict__'):
334 info.append( ('ATTRIBUTE', var.__dict__.keys() ))
335
336 spaces = ' ' * nb_space
337
338 outstr=''
339 for name, value in info:
340 outstr += '%s%3s : %s\n' % (spaces,name, value)
341
342 return outstr
343
344
345
346
347 wait_once = False
349
350 def deco_retry(f):
351 def deco_f_retry(*args, **opt):
352 for i in range(nb_try):
353 try:
354 return f(*args, **opt)
355 except KeyboardInterrupt:
356 raise
357 except Exception, error:
358 global wait_once
359 if not wait_once:
360 text = """Start waiting for update. (more info in debug mode)"""
361 logger.info(text)
362 logger_stderr.debug('fail to do %s function with %s args. %s try on a max of %s (%s waiting time)' %
363 (str(f), ', '.join([str(a) for a in args]), i+1, nb_try, sleep * (i+1)))
364 logger_stderr.debug('error is %s' % str(error))
365 if __debug__: logger_stderr.debug('and occurred at :'+traceback.format_exc())
366 wait_once = True
367 time.sleep(sleep * (i+1))
368
369 if __debug__:
370 raise
371 raise error.__class__, '[Fail %i times] \n %s ' % (i+1, error)
372 return deco_f_retry
373 return deco_retry
374
379 """return a name of the type xxxx[A-B]yyy
380 where xxx and yyy are the common part between the two names.
381 """
382
383
384 base = [first[i] for i in range(len(first)) if first[:i+1] == last[:i+1]]
385
386 while base and base[0].isdigit():
387 base = base[1:]
388
389 end = [first[-(i+1)] for i in range(len(first)) if first[-(i+1):] == last[-(i+1):]]
390
391 while end and end[-1].isdigit():
392 end = end[:-1]
393 end.reverse()
394
395 base, end = ''.join(base), ''.join(end)
396 if end:
397 name = "%s[%s-%s]%s" % (base, first[len(base):-len(end)], last[len(base):-len(end)],end)
398 else:
399 name = "%s[%s-%s]%s" % (base, first[len(base):], last[len(base):],end)
400 return name
401
402
403
404
405 -def compile(arg=[], cwd=None, mode='fortran', job_specs = True, nb_core=1 ,**opt):
406 """compile a given directory"""
407
408 if 'nocompile' in opt:
409 if opt['nocompile'] == True:
410 if not arg:
411 return
412 if cwd:
413 executable = pjoin(cwd, arg[0])
414 else:
415 executable = arg[0]
416 if os.path.exists(executable):
417 return
418 del opt['nocompile']
419
420 cmd = ['make']
421 try:
422 if nb_core > 1:
423 cmd.append('-j%s' % nb_core)
424 cmd += arg
425 p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
426 stderr=subprocess.STDOUT, cwd=cwd, **opt)
427 (out, err) = p.communicate()
428 except OSError, error:
429 if cwd and not os.path.exists(cwd):
430 raise OSError, 'Directory %s doesn\'t exists. Impossible to run make' % cwd
431 else:
432 error_text = "Impossible to compile %s directory\n" % cwd
433 error_text += "Trying to launch make command returns:\n"
434 error_text += " " + str(error) + "\n"
435 error_text += "In general this means that your computer is not able to compile."
436 if sys.platform == "darwin":
437 error_text += "Note that MacOSX doesn\'t have gmake/gfortan install by default.\n"
438 error_text += "Xcode3 contains those required programs"
439 raise MadGraph5Error, error_text
440
441 if p.returncode:
442
443 if not cwd:
444 cwd = os.getcwd()
445 all_file = [f.lower() for f in os.listdir(cwd)]
446 if 'makefile' not in all_file and '-f' not in arg:
447 raise OSError, 'no makefile present in %s' % os.path.realpath(cwd)
448
449 if mode == 'fortran' and not (which('g77') or which('gfortran')):
450 error_msg = 'A fortran compiler (g77 or gfortran) is required to create this output.\n'
451 error_msg += 'Please install g77 or gfortran on your computer and retry.'
452 raise MadGraph5Error, error_msg
453 elif mode == 'cpp' and not which('g++'):
454 error_msg ='A C++ compiler (g++) is required to create this output.\n'
455 error_msg += 'Please install g++ (which is part of the gcc package) on your computer and retry.'
456 raise MadGraph5Error, error_msg
457
458
459 if any(tag.upper() in out.upper() for tag in ['real(kind=16)','real*16',
460 'complex*32']) and mode == 'fortran' and not \
461 ''.join(get_gfortran_version().split('.')) >= '46':
462 if not which('gfortran'):
463 raise MadGraph5Error, 'The fortran compiler gfortran v4.6 or later '+\
464 'is required to compile %s.\nPlease install it and retry.'%cwd
465 else:
466 logger_stderr.error('ERROR, you could not compile %s because'%cwd+\
467 ' your version of gfortran is older than 4.6. MadGraph5_aMC@NLO will carry on,'+\
468 ' but will not be able to compile an executable.')
469 return p.returncode
470
471 error_text = 'A compilation Error occurs '
472 if cwd:
473 error_text += 'when trying to compile %s.\n' % cwd
474 error_text += 'The compilation fails with the following output message:\n'
475 error_text += ' '+out.replace('\n','\n ')+'\n'
476 error_text += 'Please try to fix this compilations issue and retry.\n'
477 error_text += 'Help might be found at https://answers.launchpad.net/mg5amcnlo.\n'
478 error_text += 'If you think that this is a bug, you can report this at https://bugs.launchpad.net/mg5amcnlo'
479 raise MadGraph5Error, error_text
480 return p.returncode
481
483 """ Returns the gfortran version as a string.
484 Returns '0' if it failed."""
485 try:
486 p = Popen([compiler, '-dumpversion'], stdout=subprocess.PIPE,
487 stderr=subprocess.PIPE)
488 output, error = p.communicate()
489 version_finder=re.compile(r"(?P<version>(\d.)*\d)")
490 version = version_finder.search(output).group('version')
491 return version
492 except Exception:
493 return '0'
494
495 -def mod_compilator(directory, new='gfortran', current=None, compiler_type='gfortran'):
496
497 if type(directory)!=list:
498 directory=[directory]
499
500
501 file_to_change=find_makefile_in_dir(directory)
502 if compiler_type == 'gfortran':
503 comp_re = re.compile('^(\s*)FC\s*=\s*(.+)\s*$')
504 var = 'FC'
505 elif compiler_type == 'cpp':
506 comp_re = re.compile('^(\s*)CXX\s*=\s*(.+)\s*$')
507 var = 'CXX'
508 else:
509 MadGraph5Error, 'Unknown compiler type: %s' % compiler_type
510
511 mod = False
512 for name in file_to_change:
513 lines = open(name,'r').read().split('\n')
514 for iline, line in enumerate(lines):
515 result = comp_re.match(line)
516 if result:
517 if new != result.group(2) and '$' not in result.group(2):
518 mod = True
519 lines[iline] = result.group(1) + var + "=" + new
520 elif compiler_type == 'gfortran' and line.startswith('DEFAULT_F_COMPILER'):
521 lines[iline] = "DEFAULT_F_COMPILER = %s" % new
522 elif compiler_type == 'cpp' and line.startswith('DEFAULT_CPP_COMPILER'):
523 lines[iline] = "DEFAULT_CPP_COMPILER = %s" % new
524
525 if mod:
526 open(name,'w').write('\n'.join(lines))
527
528 mod = False
529
534 """mute_logger (designed to work as with statement),
535 files allow to redirect the output of the log to a given file.
536 """
537
538 - def __init__(self, names, levels, files=None, **opt):
539 assert isinstance(names, list)
540 assert isinstance(names, list)
541
542 self.names = names
543 self.levels = levels
544 if isinstance(files, list):
545 self.files = files
546 else:
547 self.files = [files] * len(names)
548 self.logger_saved_info = {}
549 self.opts = opt
550
561
562 - def __exit__(self, ctype, value, traceback ):
573
575 """ Setup the logger by redirecting them all to logfiles in tmp """
576
577 logs = full_logname.split('.')
578 lognames = [ '.'.join(logs[:(len(logs)-i)]) for i in\
579 range(len(full_logname.split('.')))]
580 for logname in lognames:
581 try:
582 os.remove(path)
583 except Exception, error:
584 pass
585 my_logger = logging.getLogger(logname)
586 hdlr = logging.FileHandler(path)
587
588
589 self.logger_saved_info[logname] = [hdlr, my_logger.handlers]
590
591
592 for old_hdlr in list(my_logger.handlers):
593 my_logger.removeHandler(old_hdlr)
594 my_logger.addHandler(hdlr)
595
596 my_logger.debug('Log of %s' % logname)
597
599 """ Setup the logger by redirecting them all to logfiles in tmp """
600
601 logs = full_logname.split('.')
602 lognames = [ '.'.join(logs[:(len(logs)-i)]) for i in\
603 range(len(full_logname.split('.')))]
604 for logname in lognames:
605 if path:
606 try:
607 os.remove(path)
608 except Exception, error:
609 pass
610 my_logger = logging.getLogger(logname)
611 if logname in self.logger_saved_info:
612 my_logger.removeHandler(self.logger_saved_info[logname][0])
613 for old_hdlr in self.logger_saved_info[logname][1]:
614 my_logger.addHandler(old_hdlr)
615 else:
616 my_logger.setLevel(level)
617
618
619
620
621 nb_open =0
624 """
625 A context manager to temporarily redirect stdout or stderr
626
627 e.g.:
628
629
630 with stdchannel_redirected(sys.stderr, os.devnull):
631 if compiler.has_function('clock_gettime', libraries=['rt']):
632 libraries.append('rt')
633 """
634
635 try:
636 oldstdchannel = os.dup(stdchannel.fileno())
637 dest_file = open(dest_filename, 'w')
638 os.dup2(dest_file.fileno(), stdchannel.fileno())
639 yield
640 finally:
641 if oldstdchannel is not None:
642 os.dup2(oldstdchannel, stdchannel.fileno())
643 os.close(oldstdchannel)
644 if dest_file is not None:
645 dest_file.close()
646
648 '''
649 return the number of open file descriptors for current process
650
651 .. warning: will only work on UNIX-like os-es.
652 '''
653 import subprocess
654 import os
655
656 pid = os.getpid()
657 procs = subprocess.check_output(
658 [ "lsof", '-w', '-Ff', "-p", str( pid ) ] )
659 nprocs = filter(
660 lambda s: s and s[ 0 ] == 'f' and s[1: ].isdigit(),
661 procs.split( '\n' ) )
662
663 return nprocs
664
666 """ Detects whether the specified C++ compiler is clang."""
667
668 try:
669 p = Popen([cpp_compiler, '--version'], stdout=subprocess.PIPE,
670 stderr=subprocess.PIPE)
671 output, error = p.communicate()
672 except Exception, error:
673
674 return False
675 return 'LLVM' in output
676
678 """ Detects if the specified c++ compiler will normally link against the C++
679 standard library -lc++ or -libstdc++."""
680
681 is_clang = detect_if_cpp_compiler_is_clang(cpp_compiler)
682 if is_clang:
683 try:
684 import platform
685 v, _,_ = platform.mac_ver()
686 if not v:
687
688
689 return '-lc++'
690 else:
691 v = float(v.rsplit('.')[1])
692 if v >= 9:
693 return '-lc++'
694 else:
695 return '-lstdc++'
696 except:
697 return '-lstdc++'
698 return '-lstdc++'
699
701 """find the current compiler for the current directory"""
702
703
704
705 if compiler_type == 'fortran':
706 comp = re.compile("^\s*FC\s*=\s*([\w\/\\.\-]+)\s*")
707 elif compiler_type == 'cpp':
708 comp = re.compile("^\s*CXX\s*=\s*([\w\/\\.\-]+)\s*")
709 else:
710 MadGraph5Error, 'Unknown compiler type: %s' % compiler_type
711
712 for line in open(path):
713 if comp.search(line):
714 compiler = comp.search(line).groups()[0]
715 return compiler
716 elif compiler_type == 'fortran' and line.startswith('DEFAULT_F_COMPILER'):
717 return line.split('=')[1].strip()
718 elif compiler_type == 'cpp' and line.startswith('DEFAULT_CPP_COMPILER'):
719 return line.split('=')[1].strip()
720
722 """ return a list of all file starting with makefile in the given directory"""
723
724 out=[]
725
726 if type(directory)==list:
727 for name in directory:
728 out+=find_makefile_in_dir(name)
729 return out
730
731
732 for name in os.listdir(directory):
733 if os.path.isdir(directory+'/'+name):
734 out+=find_makefile_in_dir(directory+'/'+name)
735 elif os.path.isfile(directory+'/'+name) and name.lower().startswith('makefile'):
736 out.append(directory+'/'+name)
737 elif os.path.isfile(directory+'/'+name) and name.lower().startswith('make_opt'):
738 out.append(directory+'/'+name)
739 return out
740
742
743
744 os.path.walk('.', rm_file_extension, '.o')
745
746
747 libraries = ['libblocks.a', 'libgeneric_mw.a', 'libMWPS.a', 'libtools.a', 'libdhelas3.a',
748 'libdsample.a', 'libgeneric.a', 'libmodel.a', 'libpdf.a', 'libdhelas3.so', 'libTF.a',
749 'libdsample.so', 'libgeneric.so', 'libmodel.so', 'libpdf.so']
750 lib_pos='./lib'
751 [os.remove(os.path.join(lib_pos, lib)) for lib in libraries \
752 if os.path.exists(os.path.join(lib_pos, lib))]
753
767
771
775 replace_dict = dict(key_values)
776 replacement_function = lambda match: replace_dict[match.group(0)]
777 pattern = re.compile("|".join([re.escape(k) for k, v in key_values]), re.M)
778 return lambda string: pattern.sub(replacement_function, string)
779
782
785 def deco_check(f):
786 def deco_f(arg, *args, **opt):
787 try:
788 return f(arg, *args, **opt)
789 except OSError, error:
790 logger.debug('try to recover from %s' % error)
791 if isinstance(arg, list):
792 prog = arg[0]
793 else:
794 prog = arg[0]
795
796
797 if error.errno == 13:
798 if os.path.exists(prog):
799 os.system('chmod +x %s' % prog)
800 elif 'cwd' in opt and opt['cwd'] and \
801 os.path.isfile(pjoin(opt['cwd'],arg[0])):
802 os.system('chmod +x %s' % pjoin(opt['cwd'],arg[0]))
803 return f(arg, *args, **opt)
804
805 elif error.errno == 2:
806
807 raise Exception, '%s fails with no such file or directory' \
808 % arg
809 else:
810 raise
811 return deco_f
812 return deco_check
813
814
815 @check_system_error()
816 -def call(arg, *args, **opt):
817 """nice way to call an external program with nice error treatment"""
818 try:
819 return subprocess.call(arg, *args, **opt)
820 except OSError:
821 arg[0] = './%s' % arg[0]
822 return subprocess.call(arg, *args, **opt)
823
824 @check_system_error()
825 -def Popen(arg, *args, **opt):
826 """nice way to call an external program with nice error treatment"""
827 return subprocess.Popen(arg, *args, **opt)
828
831 """try to open a file with multiple try to ensure that filesystem is sync"""
832 return open(filepath, *args, ** opt)
833
834
835
836
837 -def tail(f, n, offset=None):
838 """Reads a n lines from f with an offset of offset lines. The return
839 value is a tuple in the form ``lines``.
840 """
841 avg_line_length = 74
842 to_read = n + (offset or 0)
843
844 while 1:
845 try:
846 f.seek(-(avg_line_length * to_read), 2)
847 except IOError:
848
849
850 f.seek(0)
851 pos = f.tell()
852 lines = f.read().splitlines()
853 if len(lines) >= to_read or pos == 0:
854 return lines[-to_read:offset and -offset or None]
855 avg_line_length *= 1.3
856 avg_line_length = int(avg_line_length)
857
859 """ makes a piping fifo (First-in First-out) file and nicely intercepts
860 error in case the file format of the target drive doesn't suppor tit."""
861
862 try:
863 os.mkfifo(fifo_path)
864 except:
865 raise OSError('MadGraph5_aMCatNLO could not create a fifo file at:\n'+
866 ' %s\n'%fifo_path+'Make sure that this file does not exist already'+
867 ' and that the file format of the target drive supports fifo file (i.e not NFS).')
868
873 """return the last line of a file"""
874
875 return tail(fsock, 1)[0]
876
878 """read a file returning the lines in reverse order for each call of readline()
879 This actually just reads blocks (4096 bytes by default) of data from the end of
880 the file and returns last line in an internal buffer."""
881
882
884 """ readline in a backward way """
885
886 while len(self.data) == 1 and ((self.blkcount * self.blksize) < self.size):
887 self.blkcount = self.blkcount + 1
888 line = self.data[0]
889 try:
890 self.seek(-self.blksize * self.blkcount, 2)
891 self.data = (self.read(self.blksize) + line).split('\n')
892 except IOError:
893 self.seek(0)
894 data = self.read(self.size - (self.blksize * (self.blkcount-1))) + line
895 self.data = data.split('\n')
896
897 if len(self.data) == 0:
898 return ""
899
900 line = self.data.pop()
901 return line + '\n'
902
903 - def __init__(self, filepos, blksize=4096):
904 """initialize the internal structures"""
905
906
907 self.size = os.stat(filepos)[6]
908
909 self.blksize = blksize
910
911 self.blkcount = 1
912 file.__init__(self, filepos, 'rb')
913
914
915 if self.size > self.blksize:
916 self.seek(-self.blksize * self.blkcount, 2)
917 self.data = self.read(self.blksize).split('\n')
918
919
920 if not self.data[-1]:
921 self.data.pop()
922
924 line = self.readline()
925 if line:
926 return line
927 else:
928 raise StopIteration
929
945
959
965 """create a temporary directory and ensure this one to be cleaned.
966 """
967
968 - def __init__(self, suffix='', prefix='tmp', dir=None):
969 self.nb_try_remove = 0
970 import tempfile
971 self.path = tempfile.mkdtemp(suffix, prefix, dir)
972
973
974 - def __exit__(self, ctype, value, traceback ):
975
976 if False and isinstance(value, Exception):
977 sprint("Directory %s not cleaned. This directory can be removed manually" % self.path)
978 return False
979 try:
980 shutil.rmtree(self.path)
981 except OSError:
982 self.nb_try_remove += 1
983 if self.nb_try_remove < 3:
984 time.sleep(10)
985 self.__exit__(ctype, value, traceback)
986 else:
987 logger.warning("Directory %s not completely cleaned. This directory can be removed manually" % self.path)
988
991
993 """create a temporary directory and ensure this one to be cleaned.
994 """
995
996 - def __init__(self, cls, attribute, value):
997
998 self.cls = cls
999 self.attribute = attribute
1000 if isinstance(attribute, list):
1001 self.old_value = []
1002 for key, onevalue in zip(attribute, value):
1003 self.old_value.append(getattr(cls, key))
1004 setattr(self.cls, key, onevalue)
1005 else:
1006 self.old_value = getattr(cls, attribute)
1007 setattr(self.cls, self.attribute, value)
1008
1009 - def __exit__(self, ctype, value, traceback ):
1010
1011 if isinstance(self.attribute, list):
1012 for key, old_value in zip(self.attribute, self.old_value):
1013 setattr(self.cls, key, old_value)
1014 else:
1015 setattr(self.cls, self.attribute, self.old_value)
1016
1018 return self.old_value
1019
1020
1021
1022
1023 -def gunzip(path, keep=False, stdout=None):
1024 """ a standard replacement for os.system('gunzip -f %s.gz ' % event_path)"""
1025
1026 if not path.endswith(".gz"):
1027 if os.path.exists("%s.gz" % path):
1028 path = "%s.gz" % path
1029 else:
1030 raise Exception, "%(path)s does not finish by .gz and the file %(path)s.gz does not exists" %\
1031 {"path": path}
1032
1033
1034
1035 if os.path.getsize(path) > 1e8:
1036 if stdout:
1037 os.system('gunzip -c %s > %s' % (path, stdout))
1038 else:
1039 os.system('gunzip %s' % path)
1040 return 0
1041
1042 if not stdout:
1043 stdout = path[:-3]
1044 try:
1045 gfile = ziplib.open(path, "r")
1046 except IOError:
1047 raise
1048 else:
1049 try:
1050 open(stdout,'w').write(gfile.read())
1051 except IOError:
1052
1053 if stdout == path:
1054 return
1055 else:
1056 files.cp(path, stdout)
1057
1058 if not keep:
1059 os.remove(path)
1060 return 0
1061
1062 -def gzip(path, stdout=None, error=True, forceexternal=False):
1063 """ a standard replacement for os.system('gzip %s ' % path)"""
1064
1065
1066 if os.path.getsize(path) > 1e9 or forceexternal:
1067 call(['gzip', '-f', path])
1068 if stdout:
1069 if not stdout.endswith(".gz"):
1070 stdout = "%s.gz" % stdout
1071 shutil.move('%s.gz' % path, stdout)
1072 return
1073
1074 if not stdout:
1075 stdout = "%s.gz" % path
1076 elif not stdout.endswith(".gz"):
1077 stdout = "%s.gz" % stdout
1078
1079 try:
1080 ziplib.open(stdout,"w").write(open(path).read())
1081 except OverflowError:
1082 gzip(path, stdout, error=error, forceexternal=True)
1083 except Exception:
1084 if error:
1085 raise
1086 else:
1087 os.remove(path)
1088
1093 """ a convinient class to open a file """
1094
1095 web_browser = None
1096 eps_viewer = None
1097 text_editor = None
1098 configured = False
1099
1101 """open a file"""
1102
1103
1104 if not self.configured:
1105 self.configure()
1106
1107 try:
1108 extension = filename.rsplit('.',1)[1]
1109 except IndexError:
1110 extension = ''
1111
1112
1113
1114 if extension in ['html','htm','php']:
1115 self.open_program(self.web_browser, filename, background=True)
1116 elif extension in ['ps','eps']:
1117 self.open_program(self.eps_viewer, filename, background=True)
1118 else:
1119 self.open_program(self.text_editor,filename, mac_check=False)
1120
1121
1122 @classmethod
1145
1146 @classmethod
1184
1185
1186 @staticmethod
1188 """find a valid shell program in the list"""
1189
1190 for p in possibility:
1191 if which(p):
1192 logger.info('Using default %s \"%s\". ' % (program, p) + \
1193 'Set another one in ./input/mg5_configuration.txt')
1194 return p
1195
1196 logger.info('No valid %s found. ' % program + \
1197 'Please set in ./input/mg5_configuration.txt')
1198 return None
1199
1200
1201 - def open_program(self, program, file_path, mac_check=True, background=False):
1202 """ open a file with a given program """
1203
1204 if mac_check==True and sys.platform == 'darwin':
1205 return self.open_mac_program(program, file_path)
1206
1207
1208 if program:
1209 arguments = program.split()
1210 arguments.append(file_path)
1211
1212 if not background:
1213 subprocess.call(arguments)
1214 else:
1215 import thread
1216 thread.start_new_thread(subprocess.call,(arguments,))
1217 else:
1218 logger.warning('Not able to open file %s since no program configured.' % file_path + \
1219 'Please set one in ./input/mg5_configuration.txt')
1220
1222 """ open a text with the text editor """
1223
1224 if not program:
1225
1226 os.system('open %s' % file_path)
1227 elif which(program):
1228
1229 arguments = program.split()
1230 arguments.append(file_path)
1231 subprocess.call(arguments)
1232 else:
1233
1234 os.system('open -a %s %s' % (program, file_path))
1235
1255
1257 """ Try and guess what shell type does the user use."""
1258 try:
1259 if os.environ['SHELL'].endswith('bash'):
1260 return 'bash'
1261 elif os.environ['SHELL'].endswith('tcsh'):
1262 return 'tcsh'
1263 else:
1264
1265 return None
1266 except KeyError:
1267 return None
1268
1270 """ check if a path is executable"""
1271 try:
1272 return os.access(path, os.X_OK)
1273 except Exception:
1274 return False
1275
1277 """Option Peaser which raise an error instead as calling exit"""
1278
1279 - def exit(self, status=0, msg=None):
1284
1286 """Returns the current line number in our program."""
1287
1288 if not __debug__:
1289 return
1290
1291 use_print = False
1292 import inspect
1293 if opt.has_key('cond') and not opt['cond']:
1294 return
1295
1296 if opt.has_key('log'):
1297 log = opt['log']
1298 else:
1299 log = logging.getLogger('madgraph')
1300 if opt.has_key('level'):
1301 level = opt['level']
1302 else:
1303 level = logging.getLogger('madgraph').level
1304 if level == 0:
1305 use_print = True
1306
1307
1308
1309
1310 if opt.has_key('wait'):
1311 wait = bool(opt['wait'])
1312 else:
1313 wait = False
1314
1315 lineno = inspect.currentframe().f_back.f_lineno
1316 fargs = inspect.getframeinfo(inspect.currentframe().f_back)
1317 filename, lineno = fargs[:2]
1318
1319
1320 try:
1321 source = inspect.getsourcelines(inspect.currentframe().f_back)
1322 line = source[0][lineno-source[1]]
1323 line = re.findall(r"misc\.sprint\(\s*(.*)\)\s*($|#)", line)[0][0]
1324 if line.startswith("'") and line.endswith("'") and line.count(",") ==0:
1325 line= ''
1326 elif line.startswith("\"") and line.endswith("\"") and line.count(",") ==0:
1327 line= ''
1328 elif line.startswith(("\"","'")) and len(args)==1 and "%" in line:
1329 line= ''
1330 except Exception:
1331 line=''
1332
1333 if line:
1334 intro = ' %s = \033[0m' % line
1335 else:
1336 intro = ''
1337
1338
1339 if not use_print:
1340 log.log(level, ' '.join([intro]+[str(a) for a in args]) + \
1341 ' \033[1;30m[%s at line %s]\033[0m' % (os.path.basename(filename), lineno))
1342 else:
1343 print ' '.join([intro]+[str(a) for a in args]) + \
1344 ' \033[1;30m[%s at line %s]\033[0m' % (os.path.basename(filename), lineno)
1345
1346 if wait:
1347 raw_input('press_enter to continue')
1348
1349 return
1350
1351
1352
1353
1354 -def equal(a,b,sig_fig=6, zero_limit=True):
1355 """function to check if two float are approximatively equal"""
1356 import math
1357
1358 if isinstance(sig_fig, int):
1359 if not a or not b:
1360 if zero_limit:
1361 power = sig_fig + 1
1362 else:
1363 return a == b
1364 else:
1365 power = sig_fig - int(math.log10(abs(a))) + 1
1366
1367 return ( a==b or abs(int(a*10**power) - int(b*10**power)) < 10)
1368 else:
1369 return abs(a-b) < sig_fig
1370
1371
1372
1373
1374
1375
1376
1377 -class chdir:
1379 self.newPath = newPath
1380
1382 self.savedPath = os.getcwd()
1383 os.chdir(self.newPath)
1384
1385 - def __exit__(self, etype, value, traceback):
1386 os.chdir(self.savedPath)
1387
1388
1389
1390
1391
1392 -def timeout(func, args=(), kwargs={}, timeout_duration=1, default=None):
1393 '''This function will spwan a thread and run the given function using the args, kwargs and
1394 return the given default value if the timeout_duration is exceeded
1395 '''
1396 import threading
1397 class InterruptableThread(threading.Thread):
1398 def __init__(self):
1399 threading.Thread.__init__(self)
1400 self.result = default
1401 def run(self):
1402 try:
1403 self.result = func(*args, **kwargs)
1404 except Exception,error:
1405 print error
1406 self.result = default
1407 it = InterruptableThread()
1408 it.start()
1409 it.join(timeout_duration)
1410 return it.result
1411
1412
1413
1414
1415
1416 -class digest:
1417
1419 try:
1420 return self.test_hashlib()
1421 except Exception:
1422 pass
1423 try:
1424 return self.test_md5()
1425 except Exception:
1426 pass
1427 try:
1428 return self.test_zlib()
1429 except Exception:
1430 pass
1431
1433 import hashlib
1434 def digest(text):
1435 """using mg5 for the hash"""
1436 t = hashlib.md5()
1437 t.update(text)
1438 return t.hexdigest()
1439 return digest
1440
1442 import md5
1443 def digest(text):
1444 """using mg5 for the hash"""
1445 t = md5.md5()
1446 t.update(text)
1447 return t.hexdigest()
1448 return digest
1449
1451 import zlib
1452 def digest(text):
1453 return zlib.adler32(text)
1454
1455 digest = digest().test_all()
1462 self.cmd_args = args
1463 self.cmd_opts = opts
1464 self.execution_state = False
1465
1467 self.max_vms_memory = 0
1468 self.max_rss_memory = 0
1469
1470 self.t1 = None
1471 self.t0 = time.time()
1472 self.p = subprocess.Popen(*self.cmd_args,**self.cmd_opts)
1473 self.execution_state = True
1474
1476 if not self.check_execution_state():
1477 return False
1478
1479 self.t1 = time.time()
1480
1481
1482
1483 flash = subprocess.Popen("ps -p %i -o rss"%self.p.pid,
1484 shell=True,stdout=subprocess.PIPE,stderr=open(os.devnull,"w"))
1485 stdout_list = flash.communicate()[0].split('\n')
1486 rss_memory = int(stdout_list[1])
1487
1488 vms_memory = 0
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
1516
1517 self.max_vms_memory = max(self.max_vms_memory,vms_memory)
1518 self.max_rss_memory = max(self.max_rss_memory,rss_memory)
1519
1520 return self.check_execution_state()
1521
1523
1524
1525 return self.p.poll() == None
1526
1528 if not self.execution_state:
1529 return False
1530 if self.is_running():
1531 return True
1532 self.executation_state = False
1533 self.t1 = time.time()
1534 return False
1535
1536 - def close(self,kill=False):
1537
1538 if self.p.poll() == None:
1539 if kill:
1540 self.p.kill()
1541 else:
1542 self.p.terminate()
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555 -class Applenotification(object):
1556
1558 self.init = False
1559 self.working = True
1560
1562 try:
1563 import Foundation
1564 import objc
1565 self.NSUserNotification = objc.lookUpClass('NSUserNotification')
1566 self.NSUserNotificationCenter = objc.lookUpClass('NSUserNotificationCenter')
1567 except:
1568 self.working=False
1569 self.working=True
1570
1571 - def __call__(self,subtitle, info_text, userInfo={}):
1572
1573 if not self.init:
1574 self.load_notification()
1575 if not self.working:
1576 return
1577 try:
1578 notification = self.NSUserNotification.alloc().init()
1579 notification.setTitle_('MadGraph5_aMC@NLO')
1580 notification.setSubtitle_(subtitle)
1581 notification.setInformativeText_(info_text)
1582 try:
1583 notification.setUserInfo_(userInfo)
1584 except:
1585 pass
1586 self.NSUserNotificationCenter.defaultUserNotificationCenter().scheduleNotification_(notification)
1587 except:
1588 pass
1589
1590
1591
1592 apple_notify = Applenotification()
1595
1596 done_notification = False
1597 message_aprilfirst =\
1598 {'error': ['Be careful, a cat is eating a lot of fish today. This makes the code unstable.',
1599 'Really, this sounds fishy.',
1600 'A Higgs boson walks into a church. The priest says "We don\'t allow Higgs bosons in here." The Higgs boson replies, "But without me, how can you have mass?"',
1601 "Why does Heisenberg detest driving cars? Because, every time he looks at the speedometer he gets lost!",
1602 "May the mass times acceleration be with you.",
1603 "NOTE: This product may actually be nine-dimensional. If this is the case, functionality is not affected by the extra five dimensions.",
1604 "IMPORTANT: This product is composed of 100%% matter: It is the responsibility of the User to make sure that it does not come in contact with antimatter.",
1605 'The fish are out of jokes. See you next year for more!'],
1606 'loading': ['Hi %(user)s, You are Loading Madgraph. Please be patient, we are doing the work.'],
1607 'quit': ['Thanks %(user)s for using MadGraph5_aMC@NLO, even on April 1st!']
1608 }
1609
1611
1612 try:
1613 now = time.localtime()
1614 date = now.tm_mday, now.tm_mon
1615 if date in [(1,4)]:
1616 if msgtype in EasterEgg.message_aprilfirst:
1617 choices = EasterEgg.message_aprilfirst[msgtype]
1618 if len(choices) == 0:
1619 return
1620 elif len(choices) == 1:
1621 msg = choices[0]
1622 else:
1623 import random
1624 msg = choices[random.randint(0,len(choices)-2)]
1625 EasterEgg.message_aprilfirst[msgtype].remove(msg)
1626
1627 else:
1628 return
1629 if MADEVENT:
1630 return
1631
1632 import os
1633 import pwd
1634 username =pwd.getpwuid( os.getuid() )[ 0 ]
1635 msg = msg % {'user': username}
1636 if sys.platform == "darwin":
1637 self.call_apple(msg)
1638 else:
1639 self.call_linux(msg)
1640 except Exception, error:
1641 sprint(error)
1642 pass
1643
1645 try:
1646 self.call_apple(msg)
1647 except:
1648 pass
1649
1651
1652
1653 p = subprocess.Popen("osascript -e 'get volume settings'", stdout=subprocess.PIPE, shell=True)
1654 output, _ = p.communicate()
1655
1656 info = dict([[a.strip() for a in l.split(':',1)] for l in output.strip().split(',')])
1657 muted = False
1658 if 'output muted' in info and info['output muted'] == 'true':
1659 muted = True
1660 elif 'output volume' in info and info['output volume'] == '0':
1661 muted = True
1662
1663 if muted:
1664 if not EasterEgg.done_notification:
1665 apple_notify('On April first','turn up your volume!')
1666 EasterEgg.done_notification = True
1667 else:
1668 os.system('say %s' % msg)
1669
1670
1672
1673 fishPath = madgraph.MG5DIR+"/input/.cowgraph.cow"
1674 if os.path.exists(fishPath):
1675 fishPath = " -f " + fishPath
1676
1677
1678
1679 fishPole = which('cowthink')
1680 if not os.path.exists(fishPole):
1681 if os.path.exists(which('cowsay')):
1682 fishPole = which('cowsay')
1683 else:
1684 return
1685
1686
1687 fishCmd = fishPole + fishPath + " " + msg
1688 os.system(fishCmd)
1689
1690
1691 if __debug__:
1692 try:
1693 import os
1694 import pwd
1695 username =pwd.getpwuid( os.getuid() )[ 0 ]
1696 if 'hirschi' in username or 'vryonidou' in username and __debug__:
1697 EasterEgg('loading')
1698 except:
1699 pass
1703 """ return v2 if v1>v2
1704 return v1 if v1<v2
1705 return v1 if v1=v2
1706 return v1 if v2 is not in 1.2.3.4.5 format
1707 return v2 if v1 is not in 1.2.3.4.5 format
1708 """
1709 from itertools import izip_longest
1710 for a1, a2 in izip_longest(v1, v2, fillvalue=0):
1711 try:
1712 a1= int(a1)
1713 except:
1714 return v2
1715 try:
1716 a2= int(a2)
1717 except:
1718 return v1
1719 if a1 > a2:
1720 return v2
1721 elif a1 < a2:
1722 return v1
1723 return v1
1724
1725
1726
1727 plugin_support = {}
1761
1762
1763
1764 -def set_global(loop=False, unitary=True, mp=False, cms=False):
1794 return deco_f_set
1795 return deco_set
1796
1797
1798
1799
1800
1801
1802
1803 python_lhapdf=None
1805 """load the python module of lhapdf return None if it can not be loaded"""
1806
1807
1808 global python_lhapdf
1809 if python_lhapdf:
1810 if python_lhapdf == -1:
1811 return None
1812 else:
1813 return python_lhapdf
1814
1815 use_lhapdf=False
1816 try:
1817 lhapdf_libdir=subprocess.Popen([lhapdfconfig,'--libdir'],\
1818 stdout=subprocess.PIPE).stdout.read().strip()
1819 except:
1820 use_lhapdf=False
1821 return False
1822 else:
1823 try:
1824 candidates=[dirname for dirname in os.listdir(lhapdf_libdir) \
1825 if os.path.isdir(os.path.join(lhapdf_libdir,dirname))]
1826 except OSError:
1827 candidates=[]
1828 for candidate in candidates:
1829 if os.path.isfile(os.path.join(lhapdf_libdir,candidate,'site-packages','lhapdf.so')):
1830 sys.path.insert(0,os.path.join(lhapdf_libdir,candidate,'site-packages'))
1831 try:
1832 import lhapdf
1833 use_lhapdf=True
1834 break
1835 except ImportError:
1836 sys.path.pop(0)
1837 continue
1838 if not use_lhapdf:
1839 try:
1840 candidates=[dirname for dirname in os.listdir(lhapdf_libdir+'64') \
1841 if os.path.isdir(os.path.join(lhapdf_libdir+'64',dirname))]
1842 except OSError:
1843 candidates=[]
1844 for candidate in candidates:
1845 if os.path.isfile(os.path.join(lhapdf_libdir+'64',candidate,'site-packages','lhapdf.so')):
1846 sys.path.insert(0,os.path.join(lhapdf_libdir+'64',candidate,'site-packages'))
1847 try:
1848 import lhapdf
1849 use_lhapdf=True
1850 break
1851 except ImportError:
1852 sys.path.pop(0)
1853 continue
1854 if not use_lhapdf:
1855 try:
1856 import lhapdf
1857 use_lhapdf=True
1858 except ImportError:
1859 print 'fail'
1860 logger.warning("Failed to access python version of LHAPDF: "\
1861 "If the python interface to LHAPDF is available on your system, try "\
1862 "adding its location to the PYTHONPATH environment variable and the"\
1863 "LHAPDF library location to LD_LIBRARY_PATH (linux) or DYLD_LIBRARY_PATH (mac os x).")
1864
1865 if use_lhapdf:
1866 python_lhapdf = lhapdf
1867 python_lhapdf.setVerbosity(0)
1868 else:
1869 python_lhapdf = None
1870 return python_lhapdf
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895