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 from __future__ import absolute_import
18 from __future__ import print_function
19 import contextlib
20 import itertools
21 import logging
22 import os
23 import re
24 import signal
25 import subprocess
26 import sys
27 import optparse
28 import time
29 import shutil
30 import stat
31 import traceback
32 import gzip as ziplib
33 from distutils.version import LooseVersion, StrictVersion
34 import six
35 from six.moves import zip_longest
36 from six.moves import range
37 from six.moves import zip
38 from six.moves import input
39 StringIO = six
40 if six.PY3:
41 import io
42 file = io.IOBase
43 try:
44
45 import madgraph
46 except Exception as error:
47
48 import internal
49 from internal import MadGraph5Error, InvalidCmd
50 import internal.files as files
51 MADEVENT = True
52 else:
53 from madgraph import MadGraph5Error, InvalidCmd
54 import madgraph.iolibs.files as files
55 MADEVENT = False
56
57
58 logger = logging.getLogger('cmdprint.ext_program')
59 logger_stderr = logging.getLogger('madevent.misc')
60 pjoin = os.path.join
66 """Parse a newline separated list of "param=value" as a dictionnary
67 """
68
69 info_dict = {}
70 pattern = re.compile("(?P<name>\w*)\s*=\s*(?P<value>.*)",
71 re.IGNORECASE | re.VERBOSE)
72 for entry in fsock:
73 entry = entry.strip()
74 if len(entry) == 0: continue
75 m = pattern.match(entry)
76 if m is not None:
77 info_dict[m.group('name')] = m.group('value')
78 else:
79 raise IOError("String %s is not a valid info string" % entry)
80
81 return info_dict
82
83
84 -def glob(name, path=''):
85 """call to glob.glob with automatic security on path"""
86 import glob as glob_module
87 path = re.sub('(?P<name>\?|\*|\[|\])', '[\g<name>]', path)
88 return glob_module.glob(pjoin(path, name))
89
90
91
92
93 -def mute_logger(names=['madgraph','ALOHA','cmdprint','madevent'], levels=[50,50,50,50]):
94 """change the logger level and restore those at their initial value at the
95 end of the function decorated."""
96 def control_logger(f):
97 def restore_old_levels(names, levels):
98 for name, level in zip(names, levels):
99 log_module = logging.getLogger(name)
100 log_module.setLevel(level)
101
102 def f_with_no_logger(self, *args, **opt):
103 old_levels = []
104 for name, level in zip(names, levels):
105 log_module = logging.getLogger(name)
106 old_levels.append(log_module.level)
107 log_module.setLevel(level)
108 try:
109 out = f(self, *args, **opt)
110 restore_old_levels(names, old_levels)
111 return out
112 except:
113 restore_old_levels(names, old_levels)
114 raise
115
116 return f_with_no_logger
117 return control_logger
118
119 PACKAGE_INFO = {}
124 """Returns the current version information of the MadGraph5_aMC@NLO package,
125 as written in the VERSION text file. If the file cannot be found,
126 a dictionary with empty values is returned. As an option, an info
127 string can be passed to be read instead of the file content.
128 """
129 global PACKAGE_INFO
130
131 if info_str:
132 info_dict = parse_info_str(StringIO.StringIO(info_str))
133 return info_dict
134
135 if PACKAGE_INFO:
136 return PACKAGE_INFO
137
138 elif MADEVENT:
139 info_dict ={}
140 info_dict['version'] = open(pjoin(internal.__path__[0],'..','..','MGMEVersion.txt')).read().strip()
141 info_dict['date'] = '20xx-xx-xx'
142 PACKAGE_INFO = info_dict
143 else:
144 if PACKAGE_INFO:
145 return PACKAGE_INFO
146 info_dict = files.read_from_file(os.path.join(madgraph.__path__[0],
147 "VERSION"),
148 parse_info_str,
149 print_error=False)
150 PACKAGE_INFO = info_dict
151
152 return info_dict
153
158 """Returns the present time info for use in MG5 command history header.
159 """
160
161 creation_time = time.asctime()
162 time_info = {'time': creation_time,
163 'fill': ' ' * (26 - len(creation_time))}
164
165 return time_info
166
172 """ Returns None if compatible or, it not compatible, a string explaining
173 why it is so."""
174
175 ma5_version = None
176 try:
177 for line in open(pjoin(ma5path,'version.txt'),'r').read().split('\n'):
178 if line.startswith('MA5 version :'):
179 ma5_version=LooseVersion(line[13:].strip())
180 break
181 except:
182 ma5_version = None
183
184 if ma5_version is None:
185 reason = "No MadAnalysis5 version number could be read from the path supplied '%s'."%ma5path
186 reason += "\nThe specified version of MadAnalysis5 will not be active in your session."
187 return reason
188
189 mg5_version = None
190 try:
191 info = get_pkg_info()
192 mg5_version = LooseVersion(info['version'])
193 except:
194 mg5_version = None
195
196
197 if not mg5_version:
198 return None
199
200 if mg5_version < LooseVersion("2.6.1") and ma5_version >= LooseVersion("1.6.32"):
201 reason = "This active MG5aMC version is too old (v%s) for your selected version of MadAnalysis5 (v%s)"%(mg5_version,ma5_version)
202 reason += "\nUpgrade MG5aMC or re-install MA5 from within MG5aMC to fix this compatibility issue."
203 reason += "\nThe specified version of MadAnalysis5 will not be active in your session."
204 return reason
205
206 if mg5_version >= LooseVersion("2.6.1") and ma5_version < LooseVersion("1.6.32"):
207 reason = "Your selected version of MadAnalysis5 (v%s) is too old for this active version of MG5aMC (v%s)."%(ma5_version,mg5_version)
208 reason += "\nRe-install MA5 from within MG5aMC to fix this compatibility issue."
209 reason += "\nThe specified version of MadAnalysis5 will not be active in your session."
210 return reason
211
212 return None
213
218 """Browse the subdirectories of the path 'start_path' and returns the first
219 one found which contains at least one file ending with the string extension
220 given in argument."""
221
222 if not os.path.isdir(start_path):
223 return None
224 subdirs=[pjoin(start_path,dir) for dir in os.listdir(start_path)]
225 for subdir in subdirs:
226 if os.path.isfile(subdir):
227 if os.path.basename(subdir).endswith(extension):
228 return start_path
229 elif os.path.isdir(subdir):
230 path = find_includes_path(subdir, extension)
231 if path:
232 return path
233 return None
234
240 """ Get whether ninja supports quad prec in different ways"""
241
242
243 ninja_config = os.path.abspath(pjoin(
244 ninja_lib_path,os.pardir,'bin','ninja-config'))
245 if os.path.exists(ninja_config):
246 try:
247 p = Popen([ninja_config, '-quadsupport'], stdout=subprocess.PIPE,
248 stderr=subprocess.PIPE)
249 output, error = p.communicate()
250 return 'TRUE' in output.decode(errors='ignore').upper()
251 except Exception:
252 pass
253
254
255
256 return False
257
258
259
260
261 -def which(program):
262 def is_exe(fpath):
263 return os.path.exists(fpath) and os.access(\
264 os.path.realpath(fpath), os.X_OK)
265
266 if not program:
267 return None
268
269 fpath, fname = os.path.split(program)
270 if fpath:
271 if is_exe(program):
272 return program
273 else:
274 for path in os.environ["PATH"].split(os.pathsep):
275 exe_file = os.path.join(path, program)
276 if is_exe(exe_file):
277 return exe_file
278 return None
279
295
301 """ Make sure to turn off some dependency of MG5aMC. """
302
303 def tell(msg):
304 if log == 'stdout':
305 print(msg)
306 elif callable(log):
307 log(msg)
308
309
310 if dependency in ['pjfry','golem','samurai','ninja','collier']:
311 if cmd.options[dependency] not in ['None',None,'']:
312 tell("Deactivating MG5_aMC dependency '%s'"%dependency)
313 cmd.options[dependency] = None
314
316 """ Checks whether the specfieid MG dependency can be activated if it was
317 not turned off in MG5 options."""
318
319 def tell(msg):
320 if log == 'stdout':
321 print(msg)
322 elif callable(log):
323 log(msg)
324
325 if cmd is None:
326 cmd = MGCmd.MasterCmd()
327
328 if dependency=='pjfry':
329 if cmd.options['pjfry'] in ['None',None,''] or \
330 (cmd.options['pjfry'] == 'auto' and which_lib('libpjfry.a') is None) or\
331 which_lib(pjoin(cmd.options['pjfry'],'libpjfry.a')) is None:
332 tell("Installing PJFry...")
333 cmd.do_install('PJFry')
334
335 if dependency=='golem':
336 if cmd.options['golem'] in ['None',None,''] or\
337 (cmd.options['golem'] == 'auto' and which_lib('libgolem.a') is None) or\
338 which_lib(pjoin(cmd.options['golem'],'libgolem.a')) is None:
339 tell("Installing Golem95...")
340 cmd.do_install('Golem95')
341
342 if dependency=='samurai':
343 raise MadGraph5Error('Samurai cannot yet be automatically installed.')
344
345 if dependency=='ninja':
346 if cmd.options['ninja'] in ['None',None,''] or\
347 (cmd.options['ninja'] == './HEPTools/lib' and not MG5dir is None and\
348 which_lib(pjoin(MG5dir,cmd.options['ninja'],'libninja.a')) is None):
349 tell("Installing ninja...")
350 cmd.do_install('ninja')
351
352 if dependency=='collier':
353 if cmd.options['collier'] in ['None',None,''] or\
354 (cmd.options['collier'] == 'auto' and which_lib('libcollier.a') is None) or\
355 which_lib(pjoin(cmd.options['collier'],'libcollier.a')) is None:
356 tell("Installing COLLIER...")
357 cmd.do_install('collier')
358
363 def is_lib(fpath):
364 return os.path.exists(fpath) and os.access(fpath, os.R_OK)
365
366 if not lib:
367 return None
368
369 fpath, fname = os.path.split(lib)
370 if fpath:
371 if is_lib(lib):
372 return lib
373 else:
374 locations = sum([os.environ[env_path].split(os.pathsep) for env_path in
375 ["DYLD_LIBRARY_PATH","LD_LIBRARY_PATH","LIBRARY_PATH","PATH"]
376 if env_path in os.environ],[])
377 for path in locations:
378 lib_file = os.path.join(path, lib)
379 if is_lib(lib_file):
380 return lib_file
381 return None
382
387 """ Return nice information on the current variable """
388
389
390 info = [('type',type(var)),('str', var)]
391 if hasattr(var, 'func_doc'):
392 info.append( ('DOC', var.__doc__) )
393 if hasattr(var, '__doc__'):
394 info.append( ('DOC', var.__doc__) )
395 if hasattr(var, '__dict__'):
396 info.append( ('ATTRIBUTE', list(var.__dict__.keys()) ))
397
398 spaces = ' ' * nb_space
399
400 outstr=''
401 for name, value in info:
402 outstr += '%s%3s : %s\n' % (spaces,name, value)
403
404 return outstr
405
406
407
408
409 wait_once = False
411
412 def deco_retry(f):
413 def deco_f_retry(*args, **opt):
414 for i in range(nb_try):
415 try:
416 return f(*args, **opt)
417 except KeyboardInterrupt:
418 raise
419 except Exception as error:
420 global wait_once
421 if not wait_once:
422 text = """Start waiting for update. (more info in debug mode)"""
423 logger.info(text)
424 logger_stderr.debug('fail to do %s function with %s args. %s try on a max of %s (%s waiting time)' %
425 (str(f), ', '.join([str(a) for a in args]), i+1, nb_try, sleep * (i+1)))
426 logger_stderr.debug('error is %s' % str(error))
427 if __debug__: logger_stderr.debug('and occurred at :'+traceback.format_exc())
428 wait_once = True
429 time.sleep(sleep * (i+1))
430
431 if __debug__:
432 raise
433 raise error.__class__('[Fail %i times] \n %s ' % (i+1, error))
434 return deco_f_retry
435 return deco_retry
436
441 """return a name of the type xxxx[A-B]yyy
442 where xxx and yyy are the common part between the two names.
443 """
444
445
446 base = [first[i] for i in range(len(first)) if first[:i+1] == last[:i+1]]
447
448 while base and base[0].isdigit():
449 base = base[1:]
450
451 end = [first[-(i+1)] for i in range(len(first)) if first[-(i+1):] == last[-(i+1):]]
452
453 while end and end[-1].isdigit():
454 end = end[:-1]
455 end.reverse()
456
457 base, end = ''.join(base), ''.join(end)
458 if end:
459 name = "%s[%s-%s]%s" % (base, first[len(base):-len(end)], last[len(base):-len(end)],end)
460 else:
461 name = "%s[%s-%s]%s" % (base, first[len(base):], last[len(base):],end)
462 return name
463
465
466 if 'copy_function' not in opts:
467 opts['copy_function'] = shutil.copy
468 return misc.copytree(*args, **opts)
469
470
471
472
473 -def compile(arg=[], cwd=None, mode='fortran', job_specs = True, nb_core=1 ,**opt):
474 """compile a given directory"""
475
476 if 'nocompile' in opt:
477 if opt['nocompile'] == True:
478 if not arg:
479 return
480 if cwd:
481 executable = pjoin(cwd, arg[0])
482 else:
483 executable = arg[0]
484 if os.path.exists(executable):
485 return
486 del opt['nocompile']
487
488 cmd = ['make']
489 try:
490 if nb_core > 1:
491 cmd.append('-j%s' % nb_core)
492 cmd += arg
493 p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
494 stderr=subprocess.STDOUT, cwd=cwd, **opt)
495 (out, err) = p.communicate()
496 except OSError as error:
497 if cwd and not os.path.exists(cwd):
498 raise OSError('Directory %s doesn\'t exists. Impossible to run make' % cwd)
499 else:
500 error_text = "Impossible to compile %s directory\n" % cwd
501 error_text += "Trying to launch make command returns:\n"
502 error_text += " " + str(error) + "\n"
503 error_text += "In general this means that your computer is not able to compile."
504 if sys.platform == "darwin":
505 error_text += "Note that MacOSX doesn\'t have gmake/gfortan install by default.\n"
506 error_text += "Xcode contains gmake. For gfortran we advise: http://hpc.sourceforge.net/"
507 raise MadGraph5Error(error_text)
508
509 if p.returncode:
510
511 if not cwd:
512 cwd = os.getcwd()
513 all_file = [f.lower() for f in os.listdir(cwd)]
514 if 'makefile' not in all_file and '-f' not in arg:
515 raise OSError('no makefile present in %s' % os.path.realpath(cwd))
516
517 if mode == 'fortran' and not (which('g77') or which('gfortran')):
518 error_msg = 'A fortran compiler (g77 or gfortran) is required to create this output.\n'
519 error_msg += 'Please install g77 or gfortran on your computer and retry.'
520 raise MadGraph5Error(error_msg)
521 elif mode == 'cpp' and not which('g++'):
522 error_msg ='A C++ compiler (g++) is required to create this output.\n'
523 error_msg += 'Please install g++ (which is part of the gcc package) on your computer and retry.'
524 raise MadGraph5Error(error_msg)
525
526 try:
527 out = out.decode('utf-8', errors='ignore')
528 except Exception:
529 out = str(out)
530
531
532 if any(tag.upper() in out.upper() for tag in ['real(kind=16)','real*16',
533 'complex*32']) and mode == 'fortran' and not \
534 ''.join(get_gfortran_version().split('.')) >= '46':
535 if not which('gfortran'):
536 raise MadGraph5Error('The fortran compiler gfortran v4.6 or later '+\
537 'is required to compile %s.\nPlease install it and retry.'%cwd)
538 else:
539 logger_stderr.error('ERROR, you could not compile %s because'%cwd+\
540 ' your version of gfortran is older than 4.6. MadGraph5_aMC@NLO will carry on,'+\
541 ' but will not be able to compile an executable.')
542 return p.returncode
543
544 error_text = 'A compilation Error occurs '
545 if cwd:
546 error_text += 'when trying to compile %s.\n' % cwd
547 error_text += 'The compilation fails with the following output message:\n'
548 error_text += ' '+out.replace('\n','\n ')+'\n'
549 error_text += 'Please try to fix this compilations issue and retry.\n'
550 error_text += 'Help might be found at https://answers.launchpad.net/mg5amcnlo.\n'
551 error_text += 'If you think that this is a bug, you can report this at https://bugs.launchpad.net/mg5amcnlo'
552 raise MadGraph5Error(error_text)
553 return p.returncode
554
556 """ Returns the gfortran version as a string.
557 Returns '0' if it failed."""
558 try:
559 p = Popen([compiler, '-dumpversion'], stdout=subprocess.PIPE,
560 stderr=subprocess.PIPE)
561 output, error = p.communicate()
562 output = output.decode("utf-8",errors='ignore')
563 version_finder=re.compile(r"(?P<version>\d[\d.]*)")
564 version = version_finder.search(output).group('version')
565 return version
566 except Exception as error:
567 raise error
568 return '0'
569
570 -def mod_compilator(directory, new='gfortran', current=None, compiler_type='gfortran'):
571
572 if type(directory)!=list:
573 directory=[directory]
574
575
576 file_to_change=find_makefile_in_dir(directory)
577 if compiler_type == 'gfortran':
578 comp_re = re.compile('^(\s*)FC\s*=\s*(.+)\s*$')
579 var = 'FC'
580 elif compiler_type == 'cpp':
581 comp_re = re.compile('^(\s*)CXX\s*=\s*(.+)\s*$')
582 var = 'CXX'
583 else:
584 MadGraph5Error, 'Unknown compiler type: %s' % compiler_type
585
586 mod = False
587 for name in file_to_change:
588 lines = open(name,'r').read().split('\n')
589 for iline, line in enumerate(lines):
590 result = comp_re.match(line)
591 if result:
592 if new != result.group(2) and '$' not in result.group(2):
593 mod = True
594 lines[iline] = result.group(1) + var + "=" + new
595 elif compiler_type == 'gfortran' and line.startswith('DEFAULT_F_COMPILER'):
596 lines[iline] = "DEFAULT_F_COMPILER = %s" % new
597 elif compiler_type == 'cpp' and line.startswith('DEFAULT_CPP_COMPILER'):
598 lines[iline] = "DEFAULT_CPP_COMPILER = %s" % new
599
600 if mod:
601 open(name,'w').write('\n'.join(lines))
602
603 mod = False
604
606 """Check whether pid exists in the current process table.
607 UNIX only.
608 https://stackoverflow.com/questions/568271/how-to-check-if-there-exists-a-process-with-a-given-pid-in-python
609 """
610 import errno
611
612 if pid < 0:
613 return False
614 if pid == 0:
615
616
617
618
619 raise ValueError('invalid PID 0')
620 try:
621 os.kill(pid, 0)
622 except OSError as err:
623 if err.errno == errno.ESRCH:
624
625 return False
626 elif err.errno == errno.EPERM:
627
628 return True
629 else:
630
631
632 raise
633 else:
634 return True
635
642 """mute_logger (designed to work as with statement),
643 files allow to redirect the output of the log to a given file.
644 """
645
646 - def __init__(self, names, levels, files=None, **opt):
647 assert isinstance(names, list)
648 assert isinstance(names, list)
649
650 self.names = names
651 self.levels = levels
652 if isinstance(files, list):
653 self.files = files
654 else:
655 self.files = [files] * len(names)
656 self.logger_saved_info = {}
657 self.opts = opt
658
669
670 - def __exit__(self, ctype, value, traceback ):
681
683 """ Setup the logger by redirecting them all to logfiles in tmp """
684
685 logs = full_logname.split('.')
686 lognames = [ '.'.join(logs[:(len(logs)-i)]) for i in\
687 range(len(full_logname.split('.')))]
688 for logname in lognames:
689 try:
690 os.remove(path)
691 except Exception as error:
692 pass
693 my_logger = logging.getLogger(logname)
694 hdlr = logging.FileHandler(path)
695
696
697 self.logger_saved_info[logname] = [hdlr, my_logger.handlers]
698
699
700 for old_hdlr in list(my_logger.handlers):
701 my_logger.removeHandler(old_hdlr)
702 my_logger.addHandler(hdlr)
703
704 my_logger.debug('Log of %s' % logname)
705
707 """ Setup the logger by redirecting them all to logfiles in tmp """
708
709 logs = full_logname.split('.')
710 lognames = [ '.'.join(logs[:(len(logs)-i)]) for i in\
711 range(len(full_logname.split('.')))]
712 for logname in lognames:
713 if path:
714 try:
715 os.remove(path)
716 except Exception as error:
717 pass
718 my_logger = logging.getLogger(logname)
719 if logname in self.logger_saved_info:
720 my_logger.removeHandler(self.logger_saved_info[logname][0])
721 for old_hdlr in self.logger_saved_info[logname][1]:
722 my_logger.addHandler(old_hdlr)
723 else:
724 my_logger.setLevel(level)
725
726
727
728
729 nb_open =0
732 """
733 A context manager to temporarily redirect stdout or stderr
734
735 e.g.:
736
737
738 with stdchannel_redirected(sys.stderr, os.devnull):
739 if compiler.has_function('clock_gettime', libraries=['rt']):
740 libraries.append('rt')
741 """
742
743 if logger.getEffectiveLevel()>5:
744
745 try:
746 oldstdchannel = os.dup(stdchannel.fileno())
747 dest_file = open(dest_filename, 'w')
748 os.dup2(dest_file.fileno(), stdchannel.fileno())
749 yield
750 finally:
751 if oldstdchannel is not None:
752 os.dup2(oldstdchannel, stdchannel.fileno())
753 os.close(oldstdchannel)
754 if dest_file is not None:
755 dest_file.close()
756 else:
757 try:
758 logger.debug('no stdout/stderr redirection due to debug level')
759 yield
760 finally:
761 return
762
765 '''
766 return the number of open file descriptors for current process
767
768 .. warning: will only work on UNIX-like os-es.
769 '''
770 import subprocess
771 import os
772
773 pid = os.getpid()
774 procs = subprocess.check_output(
775 [ "lsof", '-w', '-Ff', "-p", str( pid ) ] )
776 nprocs = [s for s in procs.split( '\n' ) if s and s[ 0 ] == 'f' and s[1: ].isdigit()]
777
778 return nprocs
779
781 """ Detects whether the specified C++ compiler is clang."""
782
783 try:
784 p = Popen([cpp_compiler, '--version'], stdout=subprocess.PIPE,
785 stderr=subprocess.PIPE)
786 output, error = p.communicate()
787 except Exception as error:
788
789 return False
790
791 output = output.decode(errors='ignore')
792 return 'LLVM' in str(output) or "clang" in str(output)
793
796 """ Detects if the specified c++ compiler will normally link against the C++
797 standard library -lc++ or -libstdc++."""
798
799 is_clang = detect_if_cpp_compiler_is_clang(cpp_compiler)
800 if is_clang:
801 try:
802 import platform
803 v, _,_ = platform.mac_ver()
804 if not v:
805
806
807 return '-lc++'
808 else:
809 maj, v = [float(x) for x in v.rsplit('.')[:2]]
810 if maj >=11 or (maj ==10 and v >= 9):
811 return '-lc++'
812 else:
813 return '-lstdc++'
814 except:
815 return '-lstdc++'
816 return '-lstdc++'
817
819 """find the current compiler for the current directory"""
820
821
822
823 if compiler_type == 'fortran':
824 comp = re.compile("^\s*FC\s*=\s*([\w\/\\.\-]+)\s*")
825 elif compiler_type == 'cpp':
826 comp = re.compile("^\s*CXX\s*=\s*([\w\/\\.\-]+)\s*")
827 else:
828 MadGraph5Error, 'Unknown compiler type: %s' % compiler_type
829
830 for line in open(path):
831 if comp.search(line):
832 compiler = comp.search(line).groups()[0]
833 return compiler
834 elif compiler_type == 'fortran' and line.startswith('DEFAULT_F_COMPILER'):
835 return line.split('=')[1].strip()
836 elif compiler_type == 'cpp' and line.startswith('DEFAULT_CPP_COMPILER'):
837 return line.split('=')[1].strip()
838
840 """ return a list of all file starting with makefile in the given directory"""
841
842 out=[]
843
844 if type(directory)==list:
845 for name in directory:
846 out+=find_makefile_in_dir(name)
847 return out
848
849
850 for name in os.listdir(directory):
851 if os.path.isdir(directory+'/'+name):
852 out+=find_makefile_in_dir(directory+'/'+name)
853 elif os.path.isfile(directory+'/'+name) and name.lower().startswith('makefile'):
854 out.append(directory+'/'+name)
855 elif os.path.isfile(directory+'/'+name) and name.lower().startswith('make_opt'):
856 out.append(directory+'/'+name)
857 return out
858
860
861
862 os.path.walk('.', rm_file_extension, '.o')
863
864
865 libraries = ['libblocks.a', 'libgeneric_mw.a', 'libMWPS.a', 'libtools.a', 'libdhelas3.a',
866 'libdsample.a', 'libgeneric.a', 'libmodel.a', 'libpdf.a', 'libdhelas3.so', 'libTF.a',
867 'libdsample.so', 'libgeneric.so', 'libmodel.so', 'libpdf.so']
868 lib_pos='./lib'
869 [os.remove(os.path.join(lib_pos, lib)) for lib in libraries \
870 if os.path.exists(os.path.join(lib_pos, lib))]
871
885
889
893 replace_dict = dict(key_values)
894 replacement_function = lambda match: replace_dict[match.group(0)]
895 pattern = re.compile("|".join([re.escape(k) for k, v in key_values]), re.M)
896 return lambda string: pattern.sub(replacement_function, string)
897
900
903 def deco_check(f):
904 def deco_f(arg, *args, **opt):
905 try:
906 return f(arg, *args, **opt)
907 except OSError as error:
908 logger.debug('try to recover from %s' % error)
909 if isinstance(arg, (list,tuple)):
910 prog = arg[0]
911 else:
912 prog = arg
913
914
915 if error.errno == 13:
916 if os.path.exists(prog):
917 os.system('chmod +x %s' % prog)
918 elif 'cwd' in opt and opt['cwd'] and \
919 os.path.isfile(pjoin(opt['cwd'],arg[0])):
920 os.system('chmod +x %s' % pjoin(opt['cwd'],arg[0]))
921 return f(arg, *args, **opt)
922
923 elif error.errno == 2:
924
925 raise Exception('%s fails with no such file or directory' \
926 % arg)
927 else:
928 raise
929 return deco_f
930 return deco_check
931
932
933 @check_system_error()
934 -def call(arg, *args, **opt):
935 """nice way to call an external program with nice error treatment"""
936 try:
937 return subprocess.call(arg, *args, **opt)
938 except OSError:
939 arg[0] = './%s' % arg[0]
940 return subprocess.call(arg, *args, **opt)
941
942 @check_system_error()
943 -def Popen(arg, *args, **opt):
944 """nice way to call an external program with nice error treatment"""
945 return subprocess.Popen(arg, *args, **opt)
946
947 @check_system_error()
948 -def call_stdout(arg, *args, **opt):
949 """nice way to call an external program with nice error treatment"""
950 try:
951 out = subprocess.Popen(arg, *args, stdout=subprocess.PIPE, **opt)
952 except OSError:
953 arg[0] = './%s' % arg[0]
954 out = subprocess.call(arg, *args, stdout=subprocess.PIPE, **opt)
955
956 str_out = out.stdout.read().decode(errors='ignore').strip()
957 return str_out
958
959
960
961 -def copytree(src, dst, symlinks = False, ignore = None):
962 if not os.path.exists(dst):
963 os.makedirs(dst)
964 shutil.copystat(src, dst)
965 lst = os.listdir(src)
966 if ignore:
967 excl = ignore(src, lst)
968 lst = [x for x in lst if x not in excl]
969 for item in lst:
970 s = os.path.join(src, item)
971 d = os.path.join(dst, item)
972 if symlinks and os.path.islink(s):
973 if os.path.lexists(d):
974 os.remove(d)
975 os.symlink(os.readlink(s), d)
976 try:
977 st = os.lstat(s)
978 mode = stat.S_IMODE(st.st_mode)
979 os.lchmod(d, mode)
980 except:
981 pass
982 elif os.path.isdir(s):
983 copytree(s, d, symlinks, ignore)
984 else:
985 shutil.copy2(s, d)
986
987
988
989 @multiple_try()
990 -def mult_try_open(filepath, *args, **opt):
991 """try to open a file with multiple try to ensure that filesystem is sync"""
992 return open(filepath, *args, ** opt)
993
994
995
996
997 -def tail(f, n, offset=None):
998 """Reads a n lines from f with an offset of offset lines. The return
999 value is a tuple in the form ``lines``.
1000 """
1001 avg_line_length = 74
1002 to_read = n + (offset or 0)
1003
1004 while 1:
1005 try:
1006 f.seek(-(avg_line_length * to_read), 2)
1007 except IOError:
1008
1009
1010 f.seek(0)
1011 pos = f.tell()
1012 lines = f.read().splitlines()
1013 if len(lines) >= to_read or pos == 0:
1014 return lines[-to_read:offset and -offset or None]
1015 avg_line_length *= 1.3
1016 avg_line_length = int(avg_line_length)
1017
1019 """ makes a piping fifo (First-in First-out) file and nicely intercepts
1020 error in case the file format of the target drive doesn't suppor tit."""
1021
1022 try:
1023 os.mkfifo(fifo_path)
1024 except:
1025 raise OSError('MadGraph5_aMCatNLO could not create a fifo file at:\n'+
1026 ' %s\n'%fifo_path+'Make sure that this file does not exist already'+
1027 ' and that the file format of the target drive supports fifo file (i.e not NFS).')
1028
1033 """return the last line of a file"""
1034
1035 return tail(fsock, 1)[0]
1036
1040 """A generator that returns the lines of a file in reverse order"""
1041 with open(filename) as fh:
1042 segment = None
1043 offset = 0
1044 fh.seek(0, os.SEEK_END)
1045 file_size = remaining_size = fh.tell()
1046 while remaining_size > 0:
1047 offset = min(file_size, offset + buf_size)
1048 fh.seek(file_size - offset)
1049 buffer = fh.read(min(remaining_size, buf_size))
1050 remaining_size -= buf_size
1051 lines = buffer.split('\n')
1052
1053
1054
1055 if segment is not None:
1056
1057
1058
1059 if buffer[-1] != '\n':
1060 lines[-1] += segment
1061 else:
1062 yield segment
1063 segment = lines[0]
1064 for index in range(len(lines) - 1, 0, -1):
1065 if lines[index]:
1066 yield lines[index]
1067
1068 if segment is not None:
1069 yield segment
1070
1088
1102
1108 """create a temporary directory and ensure this one to be cleaned.
1109 """
1110
1111 - def __init__(self, suffix='', prefix='tmp', dir=None):
1112 self.nb_try_remove = 0
1113 import tempfile
1114 self.path = tempfile.mkdtemp(suffix, prefix, dir)
1115
1116
1117 - def __exit__(self, ctype, value, traceback ):
1118
1119 if False and isinstance(value, Exception):
1120 sprint("Directory %s not cleaned. This directory can be removed manually" % self.path)
1121 return False
1122 try:
1123 shutil.rmtree(self.path)
1124 except OSError:
1125 self.nb_try_remove += 1
1126 if self.nb_try_remove < 3:
1127 time.sleep(10)
1128 self.__exit__(ctype, value, traceback)
1129 else:
1130 logger.warning("Directory %s not completely cleaned. This directory can be removed manually" % self.path)
1131
1134
1136 """replace an attribute of a class with another value for the time of the
1137 context manager
1138 """
1139
1140 - def __init__(self, cls, attribute, value):
1141
1142 self.cls = cls
1143 self.attribute = attribute
1144 if isinstance(attribute, list):
1145 self.old_value = []
1146 for key, onevalue in zip(attribute, value):
1147 self.old_value.append(getattr(cls, key))
1148 setattr(self.cls, key, onevalue)
1149 else:
1150 self.old_value = getattr(cls, attribute)
1151 setattr(self.cls, self.attribute, value)
1152
1153 - def __exit__(self, ctype, value, traceback ):
1154
1155 if isinstance(self.attribute, list):
1156 for key, old_value in zip(self.attribute, self.old_value):
1157 setattr(self.cls, key, old_value)
1158 else:
1159 setattr(self.cls, self.attribute, self.old_value)
1160
1162 return self.old_value
1163
1164
1166 def wrapper(*args, **kwds):
1167 with self:
1168 return func(*args, **kwds)
1169
1170
1171
1172
1173 -def gunzip(path, keep=False, stdout=None):
1174 """ a standard replacement for os.system('gunzip -f %s.gz ' % event_path)"""
1175
1176
1177 if not path.endswith(".gz"):
1178 if os.path.exists("%s.gz" % path):
1179 path = "%s.gz" % path
1180 else:
1181 raise Exception("%(path)s does not finish by .gz and the file %(path)s.gz does not exists" %\
1182 {"path": path})
1183
1184
1185
1186 if os.path.getsize(path) > 1e8:
1187 if stdout:
1188 os.system('gunzip -c %s > %s' % (path, stdout))
1189 else:
1190 os.system('gunzip %s' % path)
1191 return 0
1192
1193 if not stdout:
1194 stdout = path[:-3]
1195 try:
1196 gfile = ziplib.open(path, "r")
1197 except IOError:
1198 raise
1199 else:
1200 try:
1201 open(stdout,'w').write(gfile.read().decode(errors='ignore'))
1202 except IOError as error:
1203 sprint(error)
1204
1205 if stdout == path:
1206 return
1207 else:
1208 files.cp(path, stdout)
1209 finally:
1210 gfile.close()
1211 if not keep:
1212 os.remove(path)
1213 return 0
1214
1215 -def gzip(path, stdout=None, error=True, forceexternal=False):
1216 """ a standard replacement for os.system('gzip %s ' % path)"""
1217
1218
1219 if os.path.getsize(path) > 1e9 or forceexternal:
1220 call(['gzip', '-f', path])
1221 if stdout:
1222 if not stdout.endswith(".gz"):
1223 stdout = "%s.gz" % stdout
1224 shutil.move('%s.gz' % path, stdout)
1225 return
1226
1227 if not stdout:
1228 stdout = "%s.gz" % path
1229 elif not stdout.endswith(".gz"):
1230 stdout = "%s.gz" % stdout
1231
1232 try:
1233 ziplib.open(stdout,"w").write(open(path).read().encode())
1234 except OverflowError:
1235 gzip(path, stdout, error=error, forceexternal=True)
1236 except Exception:
1237 if error:
1238 raise
1239 else:
1240 return
1241 finally:
1242 os.remove(path)
1243
1248 """ a convinient class to open a file """
1249
1250 web_browser = None
1251 eps_viewer = None
1252 text_editor = None
1253 configured = False
1254
1256 """open a file"""
1257
1258
1259 if not self.configured:
1260 self.configure()
1261
1262 try:
1263 extension = filename.rsplit('.',1)[1]
1264 except IndexError:
1265 extension = ''
1266
1267
1268
1269 if extension in ['html','htm','php']:
1270 self.open_program(self.web_browser, filename, background=True)
1271 elif extension in ['ps','eps']:
1272 self.open_program(self.eps_viewer, filename, background=True)
1273 else:
1274 self.open_program(self.text_editor,filename, mac_check=False)
1275
1276
1277 @classmethod
1300
1301 @classmethod
1339
1340
1341 @staticmethod
1343 """find a valid shell program in the list"""
1344
1345 for p in possibility:
1346 if which(p):
1347 logger.info('Using default %s \"%s\". ' % (program, p) + \
1348 'Set another one in ./input/mg5_configuration.txt')
1349 return p
1350
1351 logger.info('No valid %s found. ' % program + \
1352 'Please set in ./input/mg5_configuration.txt')
1353 return None
1354
1355
1356 - def open_program(self, program, file_path, mac_check=True, background=False):
1357 """ open a file with a given program """
1358
1359 if mac_check==True and sys.platform == 'darwin':
1360 return self.open_mac_program(program, file_path)
1361
1362
1363 if program:
1364 arguments = program.split()
1365 arguments.append(file_path)
1366
1367 if not background:
1368 subprocess.call(arguments)
1369 else:
1370 import six.moves._thread
1371 six.moves._thread.start_new_thread(subprocess.call,(arguments,))
1372 else:
1373 logger.warning('Not able to open file %s since no program configured.' % file_path + \
1374 'Please set one in ./input/mg5_configuration.txt')
1375
1377 """ open a text with the text editor """
1378
1379 if not program:
1380
1381 os.system('open %s' % file_path)
1382 elif which(program):
1383
1384 arguments = program.split()
1385 arguments.append(file_path)
1386 subprocess.call(arguments)
1387 else:
1388
1389 os.system('open -a %s %s' % (program, file_path))
1390
1410
1412 """ Try and guess what shell type does the user use."""
1413 try:
1414 if os.environ['SHELL'].endswith('bash'):
1415 return 'bash'
1416 elif os.environ['SHELL'].endswith('tcsh'):
1417 return 'tcsh'
1418 else:
1419
1420 return None
1421 except KeyError:
1422 return None
1423
1425 """ check if a path is executable"""
1426 try:
1427 return os.access(path, os.X_OK)
1428 except Exception:
1429 return False
1430
1432 """Option Peaser which raise an error instead as calling exit"""
1433
1434 - def exit(self, status=0, msg=None):
1439
1441 """Returns the current line number in our program."""
1442
1443 if not __debug__:
1444 return
1445
1446
1447 import inspect
1448 if 'cond' in opt and not opt['cond']:
1449 return
1450
1451 use_print = False
1452 if 'use_print' in opt and opt['use_print']:
1453 use_print = True
1454
1455 if 'log' in opt:
1456 log = opt['log']
1457 else:
1458 log = logging.getLogger('madgraph')
1459 if 'level' in opt:
1460 level = opt['level']
1461 else:
1462 level = logging.getLogger('madgraph').level
1463 if level == 0:
1464 use_print = True
1465
1466
1467
1468
1469 if 'wait' in opt:
1470 wait = bool(opt['wait'])
1471 else:
1472 wait = False
1473
1474 lineno = inspect.currentframe().f_back.f_lineno
1475 fargs = inspect.getframeinfo(inspect.currentframe().f_back)
1476 filename, lineno = fargs[:2]
1477
1478
1479 try:
1480 source = inspect.getsourcelines(inspect.currentframe().f_back)
1481 line = source[0][lineno-source[1]]
1482 line = re.findall(r"misc\.sprint\(\s*(.*)\)\s*($|#)", line)[0][0]
1483 if line.startswith("'") and line.endswith("'") and line.count(",") ==0:
1484 line= ''
1485 elif line.startswith("\"") and line.endswith("\"") and line.count(",") ==0:
1486 line= ''
1487 elif line.startswith(("\"","'")) and len(args)==1 and "%" in line:
1488 line= ''
1489 except Exception:
1490 line=''
1491
1492 if line:
1493 intro = ' %s = \033[0m' % line
1494 else:
1495 intro = ''
1496
1497
1498 if not use_print:
1499 log.log(level, ' '.join([intro]+[str(a) for a in args]) + \
1500 ' \033[1;30m[%s at line %s]\033[0m' % (os.path.basename(filename), lineno))
1501 else:
1502 print(' '.join([intro]+[str(a) for a in args]) + \
1503 ' \033[1;30m[%s at line %s]\033[0m' % (os.path.basename(filename), lineno))
1504
1505 if wait:
1506 input('press_enter to continue')
1507 elif 'sleep' in opt:
1508 time.sleep(int(opt['sleep']))
1509
1510 return
1511
1512 -class misc(object):
1516
1517
1518
1519 -def equal(a,b,sig_fig=6, zero_limit=True):
1520 """function to check if two float are approximatively equal"""
1521 import math
1522
1523 if isinstance(sig_fig, int):
1524 if not a or not b:
1525 if zero_limit:
1526 if zero_limit is not True:
1527 power = zero_limit
1528 else:
1529 power = sig_fig + 1
1530 else:
1531 return a == b
1532 else:
1533 power = sig_fig - int(math.log10(abs(a)))
1534
1535 return ( a==b or abs(int(a*10**power) - int(b*10**power)) < 10)
1536 else:
1537 return abs(a-b) < sig_fig
1538
1539
1540
1541
1542
1543
1544
1545 -class chdir:
1547 self.newPath = newPath
1548
1550 self.savedPath = os.getcwd()
1551 os.chdir(self.newPath)
1552
1553 - def __exit__(self, etype, value, traceback):
1554 os.chdir(self.savedPath)
1555
1556
1557
1558
1559
1560 -def timeout(func, args=(), kwargs={}, timeout_duration=1, default=None):
1561 '''This function will spwan a thread and run the given function using the args, kwargs and
1562 return the given default value if the timeout_duration is exceeded
1563 '''
1564 import threading
1565 class InterruptableThread(threading.Thread):
1566 def __init__(self):
1567 threading.Thread.__init__(self)
1568 self.result = default
1569 def run(self):
1570 try:
1571 self.result = func(*args, **kwargs)
1572 except Exception as error:
1573 print(error)
1574 self.result = default
1575 it = InterruptableThread()
1576 it.start()
1577 it.join(timeout_duration)
1578 return it.result
1579
1580 -def mmin(iter, default=None):
1586
1587
1588
1589
1590
1591 -class digest:
1592
1594 try:
1595 return self.test_hashlib()
1596 except Exception:
1597 pass
1598 try:
1599 return self.test_md5()
1600 except Exception:
1601 pass
1602 try:
1603 return self.test_zlib()
1604 except Exception:
1605 pass
1606
1608 import hashlib
1609 def digest(text):
1610 """using mg5 for the hash"""
1611 t = hashlib.md5()
1612 t.update(text)
1613 return t.hexdigest()
1614 return digest
1615
1617 import md5
1618 def digest(text):
1619 """using mg5 for the hash"""
1620 t = md5.md5()
1621 t.update(text)
1622 return t.hexdigest()
1623 return digest
1624
1626 import zlib
1627 def digest(text):
1628 return zlib.adler32(text)
1629
1630 digest = digest().test_all()
1637 self.cmd_args = args
1638 self.cmd_opts = opts
1639 self.execution_state = False
1640
1642 self.max_vms_memory = 0
1643 self.max_rss_memory = 0
1644
1645 self.t1 = None
1646 self.t0 = time.time()
1647 self.p = subprocess.Popen(*self.cmd_args,**self.cmd_opts)
1648 self.execution_state = True
1649
1651 if not self.check_execution_state():
1652 return False
1653
1654 self.t1 = time.time()
1655
1656
1657
1658 flash = subprocess.Popen("ps -p %i -o rss"%self.p.pid,
1659 shell=True,stdout=subprocess.PIPE,stderr=open(os.devnull,"w"))
1660 stdout_list = flash.communicate()[0].decode(errors='ignore').split('\n')
1661 rss_memory = int(stdout_list[1])
1662
1663 vms_memory = 0
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692 self.max_vms_memory = max(self.max_vms_memory,vms_memory)
1693 self.max_rss_memory = max(self.max_rss_memory,rss_memory)
1694
1695 return self.check_execution_state()
1696
1698
1699
1700 return self.p.poll() == None
1701
1703 if not self.execution_state:
1704 return False
1705 if self.is_running():
1706 return True
1707 self.executation_state = False
1708 self.t1 = time.time()
1709 return False
1710
1711 - def close(self,kill=False):
1712
1713 if self.p.poll() == None:
1714 if kill:
1715 self.p.kill()
1716 else:
1717 self.p.terminate()
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730 -class Applenotification(object):
1731
1733 self.init = False
1734 self.working = True
1735
1737 try:
1738 import Foundation
1739 import objc
1740 self.NSUserNotification = objc.lookUpClass('NSUserNotification')
1741 self.NSUserNotificationCenter = objc.lookUpClass('NSUserNotificationCenter')
1742 except:
1743 self.working=False
1744 if which('osascript'):
1745 self.working = 'osascript'
1746 return
1747 self.working=True
1748
1749 - def __call__(self,subtitle, info_text, userInfo={}):
1750
1751 if not self.init:
1752 self.load_notification()
1753 if not self.working:
1754 return
1755 elif self.working is True:
1756 try:
1757 notification = self.NSUserNotification.alloc().init()
1758 notification.setTitle_('MadGraph5_aMC@NLO')
1759 notification.setSubtitle_(subtitle)
1760 notification.setInformativeText_(info_text)
1761 try:
1762 notification.setUserInfo_(userInfo)
1763 except:
1764 pass
1765 self.NSUserNotificationCenter.defaultUserNotificationCenter().scheduleNotification_(notification)
1766 except:
1767 pass
1768
1769 elif self.working=='osascript':
1770 try:
1771 os.system("""
1772 osascript -e 'display notification "{}" with title "MadGraph5_aMC@NLO" subtitle "{}"'
1773 """.format(info_text, subtitle))
1774 except:
1775 pass
1776
1777
1778
1779 apple_notify = Applenotification()
1782
1783 done_notification = False
1784 message_aprilfirst =\
1785 {'error': ['Be careful, a cat is eating a lot of fish today. This makes the code unstable.',
1786 'Really, this sounds fishy.',
1787 '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?"',
1788 "Why does Heisenberg detest driving cars? Because, every time he looks at the speedometer he gets lost!",
1789 "May the mass times acceleration be with you.",
1790 "NOTE: This product may actually be nine-dimensional. If this is the case, functionality is not affected by the extra five dimensions.",
1791 "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.",
1792 "",
1793 'The fish are out of jokes. See you next year for more!'],
1794
1795
1796 }
1797
1798 default_banner_1 = "************************************************************\n" + \
1799 "* *\n" + \
1800 "* W E L C O M E to *\n" + \
1801 "* M A D G R A P H 5 _ a M C @ N L O *\n" + \
1802 "* *\n" + \
1803 "* *\n"
1804
1805
1806 default_banner_2 = "* *\n" + \
1807 "%s" + \
1808 "* *\n" + \
1809 "* The MadGraph5_aMC@NLO Development Team - Find us at *\n" + \
1810 "* https://server06.fynu.ucl.ac.be/projects/madgraph *\n" + \
1811 "* and *\n" + \
1812 "* http://amcatnlo.web.cern.ch/amcatnlo/ *\n" + \
1813 "* *\n" + \
1814 "* Type 'help' for in-line help. *\n" + \
1815 "* Type 'tutorial' to learn how MG5 works *\n" + \
1816 "* Type 'tutorial aMCatNLO' to learn how aMC@NLO works *\n" + \
1817 "* Type 'tutorial MadLoop' to learn how MadLoop works *\n" + \
1818 "* *\n" + \
1819 "************************************************************"
1820
1821 May4_banner = "* _____ *\n" + \
1822 "* ,-~\" \"~-. *\n" + \
1823 "* * ,^ ___ ^. * *\n" + \
1824 "* * / .^ ^. \ * *\n" + \
1825 "* * Y l o ! Y * *\n" + \
1826 "* * l_ `.___.' _,[ * *\n" + \
1827 "* * |^~\"--------------~\"\"^| * *\n" + \
1828 "* * ! May the 4th ! * *\n" + \
1829 "* * \ / * *\n" + \
1830 "* * ^. .^ * *\n" + \
1831 "* * \"-.._____.,-\" * *\n"
1832
1833 special_banner = {(4,5): May4_banner}
1834
1835
1874
1876 try:
1877 self.call_apple(msg)
1878 except:
1879 pass
1880
1886
1887
1889
1890
1891 p = subprocess.Popen("osascript -e 'get volume settings'", stdout=subprocess.PIPE, shell=True)
1892 output, _ = p.communicate()
1893 output = output.decode(errors='ignore')
1894
1895 info = dict([[a.strip() for a in l.split(':',1)] for l in output.strip().split(',')])
1896 muted = False
1897 if 'output muted' in info and info['output muted'] == 'true':
1898 muted = True
1899 elif 'output volume' in info and info['output volume'] == '0':
1900 muted = True
1901
1902 if muted:
1903 if not EasterEgg.done_notification:
1904 apple_notify('On April first','turn up your volume!')
1905 EasterEgg.done_notification = True
1906 else:
1907 os.system('say %s' % msg)
1908
1909
1911
1912 fishPath = madgraph.MG5DIR+"/input/.cowgraph.cow"
1913 if os.path.exists(fishPath):
1914 fishPath = " -f " + fishPath
1915
1916
1917
1918 fishPole = which('cowthink')
1919 if not os.path.exists(fishPole):
1920 if os.path.exists(which('cowsay')):
1921 fishPole = which('cowsay')
1922 else:
1923 return
1924
1925
1926 fishCmd = fishPole + fishPath + " " + msg
1927 os.system(fishCmd)
1928
1931 """ return v2 if v1>v2
1932 return v1 if v1<v2
1933 return v1 if v1=v2
1934 return v1 if v2 is not in 1.2.3.4.5 format
1935 return v2 if v1 is not in 1.2.3.4.5 format
1936 """
1937
1938 for a1, a2 in zip_longest(v1, v2, fillvalue=0):
1939 try:
1940 a1= int(a1)
1941 except:
1942 return v2
1943 try:
1944 a2= int(a2)
1945 except:
1946 return v1
1947 if a1 > a2:
1948 return v2
1949 elif a1 < a2:
1950 return v1
1951 return v1
1952
1953
1954
1955 plugin_support = {}
1993
1994
1995
1996 -def set_global(loop=False, unitary=True, mp=False, cms=False):
2026 return deco_f_set
2027 return deco_set
2028
2033 """convenient way to import a plugin file/function"""
2034
2035 if six.PY2:
2036 level = -1
2037 else:
2038 level = 0
2039
2040 try:
2041 _temp = __import__('PLUGIN.%s' % module, globals(), locals(), fcts, level)
2042 except ImportError:
2043 try:
2044 _temp = __import__('MG5aMC_PLUGIN.%s' % module, globals(), locals(), fcts, level)
2045 except ImportError:
2046 raise MadGraph5Error(error_msg)
2047
2048 if not fcts:
2049 return _temp
2050 elif len(fcts) == 1:
2051 return getattr(_temp,fcts[0])
2052 else:
2053 return [getattr(_temp,name) for name in fcts]
2054
2055 -def from_plugin_import(plugin_path, target_type, keyname=None, warning=False,
2056 info=None):
2057 """return the class associated with keyname for a given plugin class
2058 if keyname is None, return all the name associated"""
2059
2060 validname = []
2061 for plugpath in plugin_path:
2062 plugindirname = os.path.basename(plugpath)
2063 for plug in os.listdir(plugpath):
2064 if os.path.exists(pjoin(plugpath, plug, '__init__.py')):
2065 try:
2066 with stdchannel_redirected(sys.stdout, os.devnull):
2067 __import__('%s.%s' % (plugindirname,plug))
2068 except Exception as error:
2069 if warning:
2070 logger.warning("error detected in plugin: %s.", plug)
2071 logger.warning("%s", error)
2072 continue
2073 plugin = sys.modules['%s.%s' % (plugindirname,plug)]
2074 if hasattr(plugin, target_type):
2075 if not is_plugin_supported(plugin):
2076 continue
2077 if keyname is None:
2078 validname += list(getattr(plugin, target_type).keys())
2079 else:
2080 if keyname in getattr(plugin, target_type):
2081 if not info:
2082 logger.info('Using from plugin %s mode %s' % (plug, keyname), '$MG:BOLD')
2083 else:
2084 logger.info(info % {'plug': plug, 'key':keyname}, '$MG:BOLD')
2085 return getattr(plugin, target_type)[keyname]
2086
2087 if not keyname:
2088 return validname
2089
2090
2091
2092
2093 python_lhapdf=None
2095 """load the python module of lhapdf return None if it can not be loaded"""
2096
2097
2098 global python_lhapdf
2099 if python_lhapdf:
2100 if python_lhapdf == -1:
2101 return None
2102 else:
2103 return python_lhapdf
2104
2105 use_lhapdf=False
2106 try:
2107
2108 lhapdf_libdir=subprocess.Popen([lhapdfconfig,'--libdir'],\
2109 stdout=subprocess.PIPE).stdout.read().decode(errors='ignore').strip()
2110 except:
2111 use_lhapdf=False
2112 return False
2113 else:
2114 try:
2115 candidates=[dirname for dirname in os.listdir(lhapdf_libdir) \
2116 if os.path.isdir(os.path.join(lhapdf_libdir,dirname))]
2117 except OSError:
2118 candidates=[]
2119 for candidate in candidates:
2120 if os.path.isdir(os.path.join(lhapdf_libdir,candidate,'site-packages')):
2121 sys.path.insert(0,os.path.join(lhapdf_libdir,candidate,'site-packages'))
2122 try:
2123 import lhapdf
2124 use_lhapdf=True
2125 break
2126 except ImportError:
2127 sys.path.pop(0)
2128 continue
2129 if not use_lhapdf:
2130 try:
2131 candidates=[dirname for dirname in os.listdir(lhapdf_libdir+'64') \
2132 if os.path.isdir(os.path.join(lhapdf_libdir+'64',dirname))]
2133 except OSError:
2134 candidates=[]
2135
2136 for candidate in candidates:
2137 if os.path.isdir(os.path.join(lhapdf_libdir+'64',candidate,'site-packages')):
2138 sys.path.insert(0,os.path.join(lhapdf_libdir+'64',candidate,'site-packages'))
2139 try:
2140 import lhapdf
2141 use_lhapdf=True
2142 break
2143 except ImportError:
2144 sys.path.pop(0)
2145 continue
2146 if not use_lhapdf:
2147 try:
2148 import lhapdf
2149 use_lhapdf=True
2150 except ImportError:
2151 print('fail')
2152 logger.warning("Failed to access python version of LHAPDF: "\
2153 "If the python interface to LHAPDF is available on your system, try "\
2154 "adding its location to the PYTHONPATH environment variable and the"\
2155 "LHAPDF library location to LD_LIBRARY_PATH (linux) or DYLD_LIBRARY_PATH (mac os x)."\
2156 "The required LD_LIBRARY_PATH is "+ lhapdf_libdir
2157 )
2158
2159 if use_lhapdf:
2160 python_lhapdf = lhapdf
2161 python_lhapdf.setVerbosity(0)
2162 else:
2163 python_lhapdf = None
2164 return python_lhapdf
2165
2167 """implement newton method for solving f(x)=0, df is the derivate"""
2168 x = x0
2169 iter=0
2170 while abs(f(x)) > error:
2171 iter+=1
2172 x = x - f(x)/df(x)
2173 if iter ==maxiter:
2174 sprint('fail to solve equation')
2175 raise Exception
2176 return x
2177
2178 -def wget(http, path, *args, **opt):
2179 """a wget function for both unix and mac"""
2180
2181 if sys.platform == "darwin":
2182 return call(['curl', '-L', http, '-o%s' % path], *args, **opt)
2183 else:
2184 return call(['wget', http, '--output-document=%s'% path], *args, **opt)
2185
2187 'Convert a cmp= function into a key= function (for using python2 type of sort)'
2188
2189 class K:
2190 def __init__(self, obj, *args):
2191 self.obj = obj
2192 def __lt__(self, other):
2193 return mycmp(self.obj, other.obj) < 0
2194 def __gt__(self, other):
2195 return mycmp(self.obj, other.obj) > 0
2196 def __eq__(self, other):
2197 return mycmp(self.obj, other.obj) == 0
2198 def __le__(self, other):
2199 return mycmp(self.obj, other.obj) <= 0
2200 def __ge__(self, other):
2201 return mycmp(self.obj, other.obj) >= 0
2202 def __ne__(self, other):
2203 return mycmp(self.obj, other.obj) != 0
2204 return K
2205
2207 """return the smallest key adiff in A such that adiff not in B or A[adiff] != B[bdiff]"""
2208 diff_keys = [k for k in A if k not in B or A[k] != B[k]]
2209 return min(diff_keys)
2210
2212 if len(A) != len(B):
2213 return (len(A) > len(B)) - (len(A) < len(B))
2214 try:
2215 adiff = smallest_diff_key(A, B)
2216 except ValueError:
2217
2218 return 0
2219 bdiff = smallest_diff_key(B, A)
2220 if adiff != bdiff:
2221 a = adiff
2222 b = bdiff
2223 return (a > b) - (a < b)
2224 a = A[adiff]
2225 b = B[bdiff]
2226 if isinstance(a, dict):
2227 return dict_cmp(a,b,level=level+1)
2228 else:
2229 return (a > b) - (a < b)
2230
2231
2232 if six.PY3:
2233 import io
2234 file = io.FileIO
2237 """read a file returning the lines in reverse order for each call of readline()
2238 This actually just reads blocks (4096 bytes by default) of data from the end of
2239 the file and returns last line in an internal buffer."""
2240
2241
2243 """ readline in a backward way """
2244
2245 while len(self.data) == 1 and ((self.blkcount * self.blksize) < self.size):
2246 self.blkcount = self.blkcount + 1
2247 line = self.data[0]
2248 try:
2249 self.seek(-self.blksize * self.blkcount, 2)
2250 self.data = (self.read(self.blksize).decode(errors='ignore') + line).split('\n')
2251 except IOError:
2252 self.seek(0)
2253 data = self.read(self.size - (self.blksize * (self.blkcount-1))).decode(errors='ignore') + line
2254 self.data = data.split('\n')
2255
2256 if len(self.data) == 0:
2257 return ""
2258
2259 line = self.data.pop()
2260 return line + '\n'
2261
2262 - def __init__(self, filepos, blksize=4096):
2263 """initialize the internal structures"""
2264
2265
2266 self.size = os.stat(filepos)[6]
2267
2268 self.blksize = blksize
2269
2270 self.blkcount = 1
2271 file.__init__(self, filepos, 'rb')
2272
2273
2274 if self.size > self.blksize:
2275 self.seek(-self.blksize * self.blkcount, 2)
2276 self.data = self.read(self.blksize).decode(errors='ignore').split('\n')
2277
2278
2279 if not self.data[-1]:
2280 self.data.pop()
2281
2283 line = self.readline()
2284 if line:
2285 return line
2286 else:
2287 raise StopIteration
2288 -def tqdm(iterator, **opts):
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315