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().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
464
465
466
467 -def compile(arg=[], cwd=None, mode='fortran', job_specs = True, nb_core=1 ,**opt):
468 """compile a given directory"""
469
470 if 'nocompile' in opt:
471 if opt['nocompile'] == True:
472 if not arg:
473 return
474 if cwd:
475 executable = pjoin(cwd, arg[0])
476 else:
477 executable = arg[0]
478 if os.path.exists(executable):
479 return
480 del opt['nocompile']
481
482 cmd = ['make']
483 try:
484 if nb_core > 1:
485 cmd.append('-j%s' % nb_core)
486 cmd += arg
487 p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
488 stderr=subprocess.STDOUT, cwd=cwd, **opt)
489 (out, err) = p.communicate()
490 except OSError as error:
491 if cwd and not os.path.exists(cwd):
492 raise OSError('Directory %s doesn\'t exists. Impossible to run make' % cwd)
493 else:
494 error_text = "Impossible to compile %s directory\n" % cwd
495 error_text += "Trying to launch make command returns:\n"
496 error_text += " " + str(error) + "\n"
497 error_text += "In general this means that your computer is not able to compile."
498 if sys.platform == "darwin":
499 error_text += "Note that MacOSX doesn\'t have gmake/gfortan install by default.\n"
500 error_text += "Xcode contains gmake. For gfortran we advise: http://hpc.sourceforge.net/"
501 raise MadGraph5Error(error_text)
502
503 if p.returncode:
504
505 if not cwd:
506 cwd = os.getcwd()
507 all_file = [f.lower() for f in os.listdir(cwd)]
508 if 'makefile' not in all_file and '-f' not in arg:
509 raise OSError('no makefile present in %s' % os.path.realpath(cwd))
510
511 if mode == 'fortran' and not (which('g77') or which('gfortran')):
512 error_msg = 'A fortran compiler (g77 or gfortran) is required to create this output.\n'
513 error_msg += 'Please install g77 or gfortran on your computer and retry.'
514 raise MadGraph5Error(error_msg)
515 elif mode == 'cpp' and not which('g++'):
516 error_msg ='A C++ compiler (g++) is required to create this output.\n'
517 error_msg += 'Please install g++ (which is part of the gcc package) on your computer and retry.'
518 raise MadGraph5Error(error_msg)
519
520 try:
521 out = out.decode('utf-8')
522 except Exception:
523 out = str(out)
524
525
526 if any(tag.upper() in out.upper() for tag in ['real(kind=16)','real*16',
527 'complex*32']) and mode == 'fortran' and not \
528 ''.join(get_gfortran_version().split('.')) >= '46':
529 if not which('gfortran'):
530 raise MadGraph5Error('The fortran compiler gfortran v4.6 or later '+\
531 'is required to compile %s.\nPlease install it and retry.'%cwd)
532 else:
533 logger_stderr.error('ERROR, you could not compile %s because'%cwd+\
534 ' your version of gfortran is older than 4.6. MadGraph5_aMC@NLO will carry on,'+\
535 ' but will not be able to compile an executable.')
536 return p.returncode
537
538 error_text = 'A compilation Error occurs '
539 if cwd:
540 error_text += 'when trying to compile %s.\n' % cwd
541 error_text += 'The compilation fails with the following output message:\n'
542 error_text += ' '+out.replace('\n','\n ')+'\n'
543 error_text += 'Please try to fix this compilations issue and retry.\n'
544 error_text += 'Help might be found at https://answers.launchpad.net/mg5amcnlo.\n'
545 error_text += 'If you think that this is a bug, you can report this at https://bugs.launchpad.net/mg5amcnlo'
546 raise MadGraph5Error(error_text)
547 return p.returncode
548
550 """ Returns the gfortran version as a string.
551 Returns '0' if it failed."""
552 try:
553 p = Popen([compiler, '-dumpversion'], stdout=subprocess.PIPE,
554 stderr=subprocess.PIPE)
555 output, error = p.communicate()
556 output = output.decode("utf-8")
557 version_finder=re.compile(r"(?P<version>\d[\d.]*)")
558 version = version_finder.search(output).group('version')
559 return version
560 except Exception as error:
561 raise error
562 return '0'
563
564 -def mod_compilator(directory, new='gfortran', current=None, compiler_type='gfortran'):
565
566 if type(directory)!=list:
567 directory=[directory]
568
569
570 file_to_change=find_makefile_in_dir(directory)
571 if compiler_type == 'gfortran':
572 comp_re = re.compile('^(\s*)FC\s*=\s*(.+)\s*$')
573 var = 'FC'
574 elif compiler_type == 'cpp':
575 comp_re = re.compile('^(\s*)CXX\s*=\s*(.+)\s*$')
576 var = 'CXX'
577 else:
578 MadGraph5Error, 'Unknown compiler type: %s' % compiler_type
579
580 mod = False
581 for name in file_to_change:
582 lines = open(name,'r').read().split('\n')
583 for iline, line in enumerate(lines):
584 result = comp_re.match(line)
585 if result:
586 if new != result.group(2) and '$' not in result.group(2):
587 mod = True
588 lines[iline] = result.group(1) + var + "=" + new
589 elif compiler_type == 'gfortran' and line.startswith('DEFAULT_F_COMPILER'):
590 lines[iline] = "DEFAULT_F_COMPILER = %s" % new
591 elif compiler_type == 'cpp' and line.startswith('DEFAULT_CPP_COMPILER'):
592 lines[iline] = "DEFAULT_CPP_COMPILER = %s" % new
593
594 if mod:
595 open(name,'w').write('\n'.join(lines))
596
597 mod = False
598
600 """Check whether pid exists in the current process table.
601 UNIX only.
602 https://stackoverflow.com/questions/568271/how-to-check-if-there-exists-a-process-with-a-given-pid-in-python
603 """
604 import errno
605
606 if pid < 0:
607 return False
608 if pid == 0:
609
610
611
612
613 raise ValueError('invalid PID 0')
614 try:
615 os.kill(pid, 0)
616 except OSError as err:
617 if err.errno == errno.ESRCH:
618
619 return False
620 elif err.errno == errno.EPERM:
621
622 return True
623 else:
624
625
626 raise
627 else:
628 return True
629
636 """mute_logger (designed to work as with statement),
637 files allow to redirect the output of the log to a given file.
638 """
639
640 - def __init__(self, names, levels, files=None, **opt):
641 assert isinstance(names, list)
642 assert isinstance(names, list)
643
644 self.names = names
645 self.levels = levels
646 if isinstance(files, list):
647 self.files = files
648 else:
649 self.files = [files] * len(names)
650 self.logger_saved_info = {}
651 self.opts = opt
652
663
664 - def __exit__(self, ctype, value, traceback ):
675
677 """ Setup the logger by redirecting them all to logfiles in tmp """
678
679 logs = full_logname.split('.')
680 lognames = [ '.'.join(logs[:(len(logs)-i)]) for i in\
681 range(len(full_logname.split('.')))]
682 for logname in lognames:
683 try:
684 os.remove(path)
685 except Exception as error:
686 pass
687 my_logger = logging.getLogger(logname)
688 hdlr = logging.FileHandler(path)
689
690
691 self.logger_saved_info[logname] = [hdlr, my_logger.handlers]
692
693
694 for old_hdlr in list(my_logger.handlers):
695 my_logger.removeHandler(old_hdlr)
696 my_logger.addHandler(hdlr)
697
698 my_logger.debug('Log of %s' % logname)
699
701 """ Setup the logger by redirecting them all to logfiles in tmp """
702
703 logs = full_logname.split('.')
704 lognames = [ '.'.join(logs[:(len(logs)-i)]) for i in\
705 range(len(full_logname.split('.')))]
706 for logname in lognames:
707 if path:
708 try:
709 os.remove(path)
710 except Exception as error:
711 pass
712 my_logger = logging.getLogger(logname)
713 if logname in self.logger_saved_info:
714 my_logger.removeHandler(self.logger_saved_info[logname][0])
715 for old_hdlr in self.logger_saved_info[logname][1]:
716 my_logger.addHandler(old_hdlr)
717 else:
718 my_logger.setLevel(level)
719
720
721
722
723 nb_open =0
726 """
727 A context manager to temporarily redirect stdout or stderr
728
729 e.g.:
730
731
732 with stdchannel_redirected(sys.stderr, os.devnull):
733 if compiler.has_function('clock_gettime', libraries=['rt']):
734 libraries.append('rt')
735 """
736
737 if logger.getEffectiveLevel()>5:
738
739 try:
740 oldstdchannel = os.dup(stdchannel.fileno())
741 dest_file = open(dest_filename, 'w')
742 os.dup2(dest_file.fileno(), stdchannel.fileno())
743 yield
744 finally:
745 if oldstdchannel is not None:
746 os.dup2(oldstdchannel, stdchannel.fileno())
747 os.close(oldstdchannel)
748 if dest_file is not None:
749 dest_file.close()
750 else:
751 try:
752 logger.debug('no stdout/stderr redirection due to debug level')
753 yield
754 finally:
755 return
756
759 '''
760 return the number of open file descriptors for current process
761
762 .. warning: will only work on UNIX-like os-es.
763 '''
764 import subprocess
765 import os
766
767 pid = os.getpid()
768 procs = subprocess.check_output(
769 [ "lsof", '-w', '-Ff', "-p", str( pid ) ] )
770 nprocs = [s for s in procs.split( '\n' ) if s and s[ 0 ] == 'f' and s[1: ].isdigit()]
771
772 return nprocs
773
775 """ Detects whether the specified C++ compiler is clang."""
776
777 try:
778 p = Popen([cpp_compiler, '--version'], stdout=subprocess.PIPE,
779 stderr=subprocess.PIPE)
780 output, error = p.communicate()
781 except Exception as error:
782
783 return False
784
785 output = output.decode()
786 return 'LLVM' in str(output) or "clang" in str(output)
787
790 """ Detects if the specified c++ compiler will normally link against the C++
791 standard library -lc++ or -libstdc++."""
792
793 is_clang = detect_if_cpp_compiler_is_clang(cpp_compiler)
794 if is_clang:
795 try:
796 import platform
797 v, _,_ = platform.mac_ver()
798 if not v:
799
800
801 return '-lc++'
802 else:
803 maj, v = [float(x) for x in v.rsplit('.')[:2]]
804 if maj >=11 or (maj ==10 and v >= 9):
805 return '-lc++'
806 else:
807 return '-lstdc++'
808 except:
809 return '-lstdc++'
810 return '-lstdc++'
811
813 """find the current compiler for the current directory"""
814
815
816
817 if compiler_type == 'fortran':
818 comp = re.compile("^\s*FC\s*=\s*([\w\/\\.\-]+)\s*")
819 elif compiler_type == 'cpp':
820 comp = re.compile("^\s*CXX\s*=\s*([\w\/\\.\-]+)\s*")
821 else:
822 MadGraph5Error, 'Unknown compiler type: %s' % compiler_type
823
824 for line in open(path):
825 if comp.search(line):
826 compiler = comp.search(line).groups()[0]
827 return compiler
828 elif compiler_type == 'fortran' and line.startswith('DEFAULT_F_COMPILER'):
829 return line.split('=')[1].strip()
830 elif compiler_type == 'cpp' and line.startswith('DEFAULT_CPP_COMPILER'):
831 return line.split('=')[1].strip()
832
834 """ return a list of all file starting with makefile in the given directory"""
835
836 out=[]
837
838 if type(directory)==list:
839 for name in directory:
840 out+=find_makefile_in_dir(name)
841 return out
842
843
844 for name in os.listdir(directory):
845 if os.path.isdir(directory+'/'+name):
846 out+=find_makefile_in_dir(directory+'/'+name)
847 elif os.path.isfile(directory+'/'+name) and name.lower().startswith('makefile'):
848 out.append(directory+'/'+name)
849 elif os.path.isfile(directory+'/'+name) and name.lower().startswith('make_opt'):
850 out.append(directory+'/'+name)
851 return out
852
854
855
856 os.path.walk('.', rm_file_extension, '.o')
857
858
859 libraries = ['libblocks.a', 'libgeneric_mw.a', 'libMWPS.a', 'libtools.a', 'libdhelas3.a',
860 'libdsample.a', 'libgeneric.a', 'libmodel.a', 'libpdf.a', 'libdhelas3.so', 'libTF.a',
861 'libdsample.so', 'libgeneric.so', 'libmodel.so', 'libpdf.so']
862 lib_pos='./lib'
863 [os.remove(os.path.join(lib_pos, lib)) for lib in libraries \
864 if os.path.exists(os.path.join(lib_pos, lib))]
865
879
883
887 replace_dict = dict(key_values)
888 replacement_function = lambda match: replace_dict[match.group(0)]
889 pattern = re.compile("|".join([re.escape(k) for k, v in key_values]), re.M)
890 return lambda string: pattern.sub(replacement_function, string)
891
894
897 def deco_check(f):
898 def deco_f(arg, *args, **opt):
899 try:
900 return f(arg, *args, **opt)
901 except OSError as error:
902 logger.debug('try to recover from %s' % error)
903 if isinstance(arg, (list,tuple)):
904 prog = arg[0]
905 else:
906 prog = arg
907
908
909 if error.errno == 13:
910 if os.path.exists(prog):
911 os.system('chmod +x %s' % prog)
912 elif 'cwd' in opt and opt['cwd'] and \
913 os.path.isfile(pjoin(opt['cwd'],arg[0])):
914 os.system('chmod +x %s' % pjoin(opt['cwd'],arg[0]))
915 return f(arg, *args, **opt)
916
917 elif error.errno == 2:
918
919 raise Exception('%s fails with no such file or directory' \
920 % arg)
921 else:
922 raise
923 return deco_f
924 return deco_check
925
926
927 @check_system_error()
928 -def call(arg, *args, **opt):
929 """nice way to call an external program with nice error treatment"""
930 try:
931 return subprocess.call(arg, *args, **opt)
932 except OSError:
933 arg[0] = './%s' % arg[0]
934 return subprocess.call(arg, *args, **opt)
935
936 @check_system_error()
937 -def Popen(arg, *args, **opt):
938 """nice way to call an external program with nice error treatment"""
939 return subprocess.Popen(arg, *args, **opt)
940
941 @check_system_error()
942 -def call_stdout(arg, *args, **opt):
943 """nice way to call an external program with nice error treatment"""
944 try:
945 out = subprocess.Popen(arg, *args, stdout=subprocess.PIPE, **opt)
946 except OSError:
947 arg[0] = './%s' % arg[0]
948 out = subprocess.call(arg, *args, stdout=subprocess.PIPE, **opt)
949
950 str_out = out.stdout.read().decode().strip()
951 return str_out
952
953
954
955 -def copytree(src, dst, symlinks = False, ignore = None):
956 if not os.path.exists(dst):
957 os.makedirs(dst)
958 shutil.copystat(src, dst)
959 lst = os.listdir(src)
960 if ignore:
961 excl = ignore(src, lst)
962 lst = [x for x in lst if x not in excl]
963 for item in lst:
964 s = os.path.join(src, item)
965 d = os.path.join(dst, item)
966 if symlinks and os.path.islink(s):
967 if os.path.lexists(d):
968 os.remove(d)
969 os.symlink(os.readlink(s), d)
970 try:
971 st = os.lstat(s)
972 mode = stat.S_IMODE(st.st_mode)
973 os.lchmod(d, mode)
974 except:
975 pass
976 elif os.path.isdir(s):
977 copytree(s, d, symlinks, ignore)
978 else:
979 shutil.copy2(s, d)
980
981
982
983 @multiple_try()
984 -def mult_try_open(filepath, *args, **opt):
985 """try to open a file with multiple try to ensure that filesystem is sync"""
986 return open(filepath, *args, ** opt)
987
988
989
990
991 -def tail(f, n, offset=None):
992 """Reads a n lines from f with an offset of offset lines. The return
993 value is a tuple in the form ``lines``.
994 """
995 avg_line_length = 74
996 to_read = n + (offset or 0)
997
998 while 1:
999 try:
1000 f.seek(-(avg_line_length * to_read), 2)
1001 except IOError:
1002
1003
1004 f.seek(0)
1005 pos = f.tell()
1006 lines = f.read().splitlines()
1007 if len(lines) >= to_read or pos == 0:
1008 return lines[-to_read:offset and -offset or None]
1009 avg_line_length *= 1.3
1010 avg_line_length = int(avg_line_length)
1011
1013 """ makes a piping fifo (First-in First-out) file and nicely intercepts
1014 error in case the file format of the target drive doesn't suppor tit."""
1015
1016 try:
1017 os.mkfifo(fifo_path)
1018 except:
1019 raise OSError('MadGraph5_aMCatNLO could not create a fifo file at:\n'+
1020 ' %s\n'%fifo_path+'Make sure that this file does not exist already'+
1021 ' and that the file format of the target drive supports fifo file (i.e not NFS).')
1022
1027 """return the last line of a file"""
1028
1029 return tail(fsock, 1)[0]
1030
1034 """A generator that returns the lines of a file in reverse order"""
1035 with open(filename) as fh:
1036 segment = None
1037 offset = 0
1038 fh.seek(0, os.SEEK_END)
1039 file_size = remaining_size = fh.tell()
1040 while remaining_size > 0:
1041 offset = min(file_size, offset + buf_size)
1042 fh.seek(file_size - offset)
1043 buffer = fh.read(min(remaining_size, buf_size))
1044 remaining_size -= buf_size
1045 lines = buffer.split('\n')
1046
1047
1048
1049 if segment is not None:
1050
1051
1052
1053 if buffer[-1] != '\n':
1054 lines[-1] += segment
1055 else:
1056 yield segment
1057 segment = lines[0]
1058 for index in range(len(lines) - 1, 0, -1):
1059 if lines[index]:
1060 yield lines[index]
1061
1062 if segment is not None:
1063 yield segment
1064
1082
1096
1102 """create a temporary directory and ensure this one to be cleaned.
1103 """
1104
1105 - def __init__(self, suffix='', prefix='tmp', dir=None):
1106 self.nb_try_remove = 0
1107 import tempfile
1108 self.path = tempfile.mkdtemp(suffix, prefix, dir)
1109
1110
1111 - def __exit__(self, ctype, value, traceback ):
1112
1113 if False and isinstance(value, Exception):
1114 sprint("Directory %s not cleaned. This directory can be removed manually" % self.path)
1115 return False
1116 try:
1117 shutil.rmtree(self.path)
1118 except OSError:
1119 self.nb_try_remove += 1
1120 if self.nb_try_remove < 3:
1121 time.sleep(10)
1122 self.__exit__(ctype, value, traceback)
1123 else:
1124 logger.warning("Directory %s not completely cleaned. This directory can be removed manually" % self.path)
1125
1128
1130 """replace an attribute of a class with another value for the time of the
1131 context manager
1132 """
1133
1134 - def __init__(self, cls, attribute, value):
1135
1136 self.cls = cls
1137 self.attribute = attribute
1138 if isinstance(attribute, list):
1139 self.old_value = []
1140 for key, onevalue in zip(attribute, value):
1141 self.old_value.append(getattr(cls, key))
1142 setattr(self.cls, key, onevalue)
1143 else:
1144 self.old_value = getattr(cls, attribute)
1145 setattr(self.cls, self.attribute, value)
1146
1147 - def __exit__(self, ctype, value, traceback ):
1148
1149 if isinstance(self.attribute, list):
1150 for key, old_value in zip(self.attribute, self.old_value):
1151 setattr(self.cls, key, old_value)
1152 else:
1153 setattr(self.cls, self.attribute, self.old_value)
1154
1156 return self.old_value
1157
1158
1160 def wrapper(*args, **kwds):
1161 with self:
1162 return func(*args, **kwds)
1163
1164
1165
1166
1167 -def gunzip(path, keep=False, stdout=None):
1168 """ a standard replacement for os.system('gunzip -f %s.gz ' % event_path)"""
1169
1170
1171 if not path.endswith(".gz"):
1172 if os.path.exists("%s.gz" % path):
1173 path = "%s.gz" % path
1174 else:
1175 raise Exception("%(path)s does not finish by .gz and the file %(path)s.gz does not exists" %\
1176 {"path": path})
1177
1178
1179
1180 if os.path.getsize(path) > 1e8:
1181 if stdout:
1182 os.system('gunzip -c %s > %s' % (path, stdout))
1183 else:
1184 os.system('gunzip %s' % path)
1185 return 0
1186
1187 if not stdout:
1188 stdout = path[:-3]
1189 try:
1190 gfile = ziplib.open(path, "r")
1191 except IOError:
1192 raise
1193 else:
1194 try:
1195 open(stdout,'w').write(gfile.read().decode())
1196 except IOError as error:
1197 sprint(error)
1198
1199 if stdout == path:
1200 return
1201 else:
1202 files.cp(path, stdout)
1203 finally:
1204 gfile.close()
1205 if not keep:
1206 os.remove(path)
1207 return 0
1208
1209 -def gzip(path, stdout=None, error=True, forceexternal=False):
1210 """ a standard replacement for os.system('gzip %s ' % path)"""
1211
1212
1213 if os.path.getsize(path) > 1e9 or forceexternal:
1214 call(['gzip', '-f', path])
1215 if stdout:
1216 if not stdout.endswith(".gz"):
1217 stdout = "%s.gz" % stdout
1218 shutil.move('%s.gz' % path, stdout)
1219 return
1220
1221 if not stdout:
1222 stdout = "%s.gz" % path
1223 elif not stdout.endswith(".gz"):
1224 stdout = "%s.gz" % stdout
1225
1226 try:
1227 ziplib.open(stdout,"w").write(open(path).read().encode())
1228 except OverflowError:
1229 gzip(path, stdout, error=error, forceexternal=True)
1230 except Exception:
1231 if error:
1232 raise
1233 else:
1234 return
1235 finally:
1236 os.remove(path)
1237
1242 """ a convinient class to open a file """
1243
1244 web_browser = None
1245 eps_viewer = None
1246 text_editor = None
1247 configured = False
1248
1250 """open a file"""
1251
1252
1253 if not self.configured:
1254 self.configure()
1255
1256 try:
1257 extension = filename.rsplit('.',1)[1]
1258 except IndexError:
1259 extension = ''
1260
1261
1262
1263 if extension in ['html','htm','php']:
1264 self.open_program(self.web_browser, filename, background=True)
1265 elif extension in ['ps','eps']:
1266 self.open_program(self.eps_viewer, filename, background=True)
1267 else:
1268 self.open_program(self.text_editor,filename, mac_check=False)
1269
1270
1271 @classmethod
1294
1295 @classmethod
1333
1334
1335 @staticmethod
1337 """find a valid shell program in the list"""
1338
1339 for p in possibility:
1340 if which(p):
1341 logger.info('Using default %s \"%s\". ' % (program, p) + \
1342 'Set another one in ./input/mg5_configuration.txt')
1343 return p
1344
1345 logger.info('No valid %s found. ' % program + \
1346 'Please set in ./input/mg5_configuration.txt')
1347 return None
1348
1349
1350 - def open_program(self, program, file_path, mac_check=True, background=False):
1351 """ open a file with a given program """
1352
1353 if mac_check==True and sys.platform == 'darwin':
1354 return self.open_mac_program(program, file_path)
1355
1356
1357 if program:
1358 arguments = program.split()
1359 arguments.append(file_path)
1360
1361 if not background:
1362 subprocess.call(arguments)
1363 else:
1364 import six.moves._thread
1365 six.moves._thread.start_new_thread(subprocess.call,(arguments,))
1366 else:
1367 logger.warning('Not able to open file %s since no program configured.' % file_path + \
1368 'Please set one in ./input/mg5_configuration.txt')
1369
1371 """ open a text with the text editor """
1372
1373 if not program:
1374
1375 os.system('open %s' % file_path)
1376 elif which(program):
1377
1378 arguments = program.split()
1379 arguments.append(file_path)
1380 subprocess.call(arguments)
1381 else:
1382
1383 os.system('open -a %s %s' % (program, file_path))
1384
1404
1406 """ Try and guess what shell type does the user use."""
1407 try:
1408 if os.environ['SHELL'].endswith('bash'):
1409 return 'bash'
1410 elif os.environ['SHELL'].endswith('tcsh'):
1411 return 'tcsh'
1412 else:
1413
1414 return None
1415 except KeyError:
1416 return None
1417
1419 """ check if a path is executable"""
1420 try:
1421 return os.access(path, os.X_OK)
1422 except Exception:
1423 return False
1424
1426 """Option Peaser which raise an error instead as calling exit"""
1427
1428 - def exit(self, status=0, msg=None):
1433
1435 """Returns the current line number in our program."""
1436
1437 if not __debug__:
1438 return
1439
1440
1441 import inspect
1442 if 'cond' in opt and not opt['cond']:
1443 return
1444
1445 use_print = False
1446 if 'use_print' in opt and opt['use_print']:
1447 use_print = True
1448
1449 if 'log' in opt:
1450 log = opt['log']
1451 else:
1452 log = logging.getLogger('madgraph')
1453 if 'level' in opt:
1454 level = opt['level']
1455 else:
1456 level = logging.getLogger('madgraph').level
1457 if level == 0:
1458 use_print = True
1459
1460
1461
1462
1463 if 'wait' in opt:
1464 wait = bool(opt['wait'])
1465 else:
1466 wait = False
1467
1468 lineno = inspect.currentframe().f_back.f_lineno
1469 fargs = inspect.getframeinfo(inspect.currentframe().f_back)
1470 filename, lineno = fargs[:2]
1471
1472
1473 try:
1474 source = inspect.getsourcelines(inspect.currentframe().f_back)
1475 line = source[0][lineno-source[1]]
1476 line = re.findall(r"misc\.sprint\(\s*(.*)\)\s*($|#)", line)[0][0]
1477 if line.startswith("'") and line.endswith("'") and line.count(",") ==0:
1478 line= ''
1479 elif line.startswith("\"") and line.endswith("\"") and line.count(",") ==0:
1480 line= ''
1481 elif line.startswith(("\"","'")) and len(args)==1 and "%" in line:
1482 line= ''
1483 except Exception:
1484 line=''
1485
1486 if line:
1487 intro = ' %s = \033[0m' % line
1488 else:
1489 intro = ''
1490
1491
1492 if not use_print:
1493 log.log(level, ' '.join([intro]+[str(a) for a in args]) + \
1494 ' \033[1;30m[%s at line %s]\033[0m' % (os.path.basename(filename), lineno))
1495 else:
1496 print(' '.join([intro]+[str(a) for a in args]) + \
1497 ' \033[1;30m[%s at line %s]\033[0m' % (os.path.basename(filename), lineno))
1498
1499 if wait:
1500 input('press_enter to continue')
1501 elif 'sleep' in opt:
1502 time.sleep(int(opt['sleep']))
1503
1504 return
1505
1506 -class misc(object):
1510
1511
1512
1513 -def equal(a,b,sig_fig=6, zero_limit=True):
1514 """function to check if two float are approximatively equal"""
1515 import math
1516
1517 if isinstance(sig_fig, int):
1518 if not a or not b:
1519 if zero_limit:
1520 if zero_limit is not True:
1521 power = zero_limit
1522 else:
1523 power = sig_fig + 1
1524 else:
1525 return a == b
1526 else:
1527 power = sig_fig - int(math.log10(abs(a)))
1528
1529 return ( a==b or abs(int(a*10**power) - int(b*10**power)) < 10)
1530 else:
1531 return abs(a-b) < sig_fig
1532
1533
1534
1535
1536
1537
1538
1539 -class chdir:
1541 self.newPath = newPath
1542
1544 self.savedPath = os.getcwd()
1545 os.chdir(self.newPath)
1546
1547 - def __exit__(self, etype, value, traceback):
1548 os.chdir(self.savedPath)
1549
1550
1551
1552
1553
1554 -def timeout(func, args=(), kwargs={}, timeout_duration=1, default=None):
1555 '''This function will spwan a thread and run the given function using the args, kwargs and
1556 return the given default value if the timeout_duration is exceeded
1557 '''
1558 import threading
1559 class InterruptableThread(threading.Thread):
1560 def __init__(self):
1561 threading.Thread.__init__(self)
1562 self.result = default
1563 def run(self):
1564 try:
1565 self.result = func(*args, **kwargs)
1566 except Exception as error:
1567 print(error)
1568 self.result = default
1569 it = InterruptableThread()
1570 it.start()
1571 it.join(timeout_duration)
1572 return it.result
1573
1574 -def mmin(iter, default=None):
1580
1581
1582
1583
1584
1585 -class digest:
1586
1588 try:
1589 return self.test_hashlib()
1590 except Exception:
1591 pass
1592 try:
1593 return self.test_md5()
1594 except Exception:
1595 pass
1596 try:
1597 return self.test_zlib()
1598 except Exception:
1599 pass
1600
1602 import hashlib
1603 def digest(text):
1604 """using mg5 for the hash"""
1605 t = hashlib.md5()
1606 t.update(text)
1607 return t.hexdigest()
1608 return digest
1609
1611 import md5
1612 def digest(text):
1613 """using mg5 for the hash"""
1614 t = md5.md5()
1615 t.update(text)
1616 return t.hexdigest()
1617 return digest
1618
1620 import zlib
1621 def digest(text):
1622 return zlib.adler32(text)
1623
1624 digest = digest().test_all()
1631 self.cmd_args = args
1632 self.cmd_opts = opts
1633 self.execution_state = False
1634
1636 self.max_vms_memory = 0
1637 self.max_rss_memory = 0
1638
1639 self.t1 = None
1640 self.t0 = time.time()
1641 self.p = subprocess.Popen(*self.cmd_args,**self.cmd_opts)
1642 self.execution_state = True
1643
1645 if not self.check_execution_state():
1646 return False
1647
1648 self.t1 = time.time()
1649
1650
1651
1652 flash = subprocess.Popen("ps -p %i -o rss"%self.p.pid,
1653 shell=True,stdout=subprocess.PIPE,stderr=open(os.devnull,"w"))
1654 stdout_list = flash.communicate()[0].decode().split('\n')
1655 rss_memory = int(stdout_list[1])
1656
1657 vms_memory = 0
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686 self.max_vms_memory = max(self.max_vms_memory,vms_memory)
1687 self.max_rss_memory = max(self.max_rss_memory,rss_memory)
1688
1689 return self.check_execution_state()
1690
1692
1693
1694 return self.p.poll() == None
1695
1697 if not self.execution_state:
1698 return False
1699 if self.is_running():
1700 return True
1701 self.executation_state = False
1702 self.t1 = time.time()
1703 return False
1704
1705 - def close(self,kill=False):
1706
1707 if self.p.poll() == None:
1708 if kill:
1709 self.p.kill()
1710 else:
1711 self.p.terminate()
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724 -class Applenotification(object):
1725
1727 self.init = False
1728 self.working = True
1729
1731 try:
1732 import Foundation
1733 import objc
1734 self.NSUserNotification = objc.lookUpClass('NSUserNotification')
1735 self.NSUserNotificationCenter = objc.lookUpClass('NSUserNotificationCenter')
1736 except:
1737 self.working=False
1738 if which('osascript'):
1739 self.working = 'osascript'
1740 return
1741 self.working=True
1742
1743 - def __call__(self,subtitle, info_text, userInfo={}):
1744
1745 if not self.init:
1746 self.load_notification()
1747 if not self.working:
1748 return
1749 elif self.working is True:
1750 try:
1751 notification = self.NSUserNotification.alloc().init()
1752 notification.setTitle_('MadGraph5_aMC@NLO')
1753 notification.setSubtitle_(subtitle)
1754 notification.setInformativeText_(info_text)
1755 try:
1756 notification.setUserInfo_(userInfo)
1757 except:
1758 pass
1759 self.NSUserNotificationCenter.defaultUserNotificationCenter().scheduleNotification_(notification)
1760 except:
1761 pass
1762
1763 elif self.working=='osascript':
1764 try:
1765 os.system("""
1766 osascript -e 'display notification "{}" with title "MadGraph5_aMC@NLO" subtitle "{}"'
1767 """.format(info_text, subtitle))
1768 except:
1769 pass
1770
1771
1772
1773 apple_notify = Applenotification()
1776
1777 done_notification = False
1778 message_aprilfirst =\
1779 {'error': ['Be careful, a cat is eating a lot of fish today. This makes the code unstable.',
1780 'Really, this sounds fishy.',
1781 '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?"',
1782 "Why does Heisenberg detest driving cars? Because, every time he looks at the speedometer he gets lost!",
1783 "May the mass times acceleration be with you.",
1784 "NOTE: This product may actually be nine-dimensional. If this is the case, functionality is not affected by the extra five dimensions.",
1785 "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.",
1786 "",
1787 'The fish are out of jokes. See you next year for more!'],
1788
1789
1790 }
1791
1792 default_banner_1 = "************************************************************\n" + \
1793 "* *\n" + \
1794 "* W E L C O M E to *\n" + \
1795 "* M A D G R A P H 5 _ a M C @ N L O *\n" + \
1796 "* *\n" + \
1797 "* *\n"
1798
1799
1800 default_banner_2 = "* *\n" + \
1801 "%s" + \
1802 "* *\n" + \
1803 "* The MadGraph5_aMC@NLO Development Team - Find us at *\n" + \
1804 "* https://server06.fynu.ucl.ac.be/projects/madgraph *\n" + \
1805 "* and *\n" + \
1806 "* http://amcatnlo.web.cern.ch/amcatnlo/ *\n" + \
1807 "* *\n" + \
1808 "* Type 'help' for in-line help. *\n" + \
1809 "* Type 'tutorial' to learn how MG5 works *\n" + \
1810 "* Type 'tutorial aMCatNLO' to learn how aMC@NLO works *\n" + \
1811 "* Type 'tutorial MadLoop' to learn how MadLoop works *\n" + \
1812 "* *\n" + \
1813 "************************************************************"
1814
1815 May4_banner = "* _____ *\n" + \
1816 "* ,-~\" \"~-. *\n" + \
1817 "* * ,^ ___ ^. * *\n" + \
1818 "* * / .^ ^. \ * *\n" + \
1819 "* * Y l o ! Y * *\n" + \
1820 "* * l_ `.___.' _,[ * *\n" + \
1821 "* * |^~\"--------------~\"\"^| * *\n" + \
1822 "* * ! May the 4th ! * *\n" + \
1823 "* * \ / * *\n" + \
1824 "* * ^. .^ * *\n" + \
1825 "* * \"-.._____.,-\" * *\n"
1826
1827 special_banner = {(4,5): May4_banner}
1828
1829
1868
1870 try:
1871 self.call_apple(msg)
1872 except:
1873 pass
1874
1880
1881
1883
1884
1885 p = subprocess.Popen("osascript -e 'get volume settings'", stdout=subprocess.PIPE, shell=True)
1886 output, _ = p.communicate()
1887 output = output.decode()
1888
1889 info = dict([[a.strip() for a in l.split(':',1)] for l in output.strip().split(',')])
1890 muted = False
1891 if 'output muted' in info and info['output muted'] == 'true':
1892 muted = True
1893 elif 'output volume' in info and info['output volume'] == '0':
1894 muted = True
1895
1896 if muted:
1897 if not EasterEgg.done_notification:
1898 apple_notify('On April first','turn up your volume!')
1899 EasterEgg.done_notification = True
1900 else:
1901 os.system('say %s' % msg)
1902
1903
1905
1906 fishPath = madgraph.MG5DIR+"/input/.cowgraph.cow"
1907 if os.path.exists(fishPath):
1908 fishPath = " -f " + fishPath
1909
1910
1911
1912 fishPole = which('cowthink')
1913 if not os.path.exists(fishPole):
1914 if os.path.exists(which('cowsay')):
1915 fishPole = which('cowsay')
1916 else:
1917 return
1918
1919
1920 fishCmd = fishPole + fishPath + " " + msg
1921 os.system(fishCmd)
1922
1925 """ return v2 if v1>v2
1926 return v1 if v1<v2
1927 return v1 if v1=v2
1928 return v1 if v2 is not in 1.2.3.4.5 format
1929 return v2 if v1 is not in 1.2.3.4.5 format
1930 """
1931
1932 for a1, a2 in zip_longest(v1, v2, fillvalue=0):
1933 try:
1934 a1= int(a1)
1935 except:
1936 return v2
1937 try:
1938 a2= int(a2)
1939 except:
1940 return v1
1941 if a1 > a2:
1942 return v2
1943 elif a1 < a2:
1944 return v1
1945 return v1
1946
1947
1948
1949 plugin_support = {}
1987
1988
1989
1990 -def set_global(loop=False, unitary=True, mp=False, cms=False):
2020 return deco_f_set
2021 return deco_set
2022
2027 """convenient way to import a plugin file/function"""
2028
2029 if six.PY2:
2030 level = -1
2031 else:
2032 level = 0
2033
2034 try:
2035 _temp = __import__('PLUGIN.%s' % module, globals(), locals(), fcts, level)
2036 except ImportError:
2037 try:
2038 _temp = __import__('MG5aMC_PLUGIN.%s' % module, globals(), locals(), fcts, level)
2039 except ImportError:
2040 raise MadGraph5Error(error_msg)
2041
2042 if not fcts:
2043 return _temp
2044 elif len(fcts) == 1:
2045 return getattr(_temp,fcts[0])
2046 else:
2047 return [getattr(_temp,name) for name in fcts]
2048
2049 -def from_plugin_import(plugin_path, target_type, keyname=None, warning=False,
2050 info=None):
2051 """return the class associated with keyname for a given plugin class
2052 if keyname is None, return all the name associated"""
2053
2054 validname = []
2055 for plugpath in plugin_path:
2056 plugindirname = os.path.basename(plugpath)
2057 for plug in os.listdir(plugpath):
2058 if os.path.exists(pjoin(plugpath, plug, '__init__.py')):
2059 try:
2060 with stdchannel_redirected(sys.stdout, os.devnull):
2061 __import__('%s.%s' % (plugindirname,plug))
2062 except Exception as error:
2063 if warning:
2064 logger.warning("error detected in plugin: %s.", plug)
2065 logger.warning("%s", error)
2066 continue
2067 plugin = sys.modules['%s.%s' % (plugindirname,plug)]
2068 if hasattr(plugin, target_type):
2069 if not is_plugin_supported(plugin):
2070 continue
2071 if keyname is None:
2072 validname += list(getattr(plugin, target_type).keys())
2073 else:
2074 if keyname in getattr(plugin, target_type):
2075 if not info:
2076 logger.info('Using from plugin %s mode %s' % (plug, keyname), '$MG:BOLD')
2077 else:
2078 logger.info(info % {'plug': plug, 'key':keyname}, '$MG:BOLD')
2079 return getattr(plugin, target_type)[keyname]
2080
2081 if not keyname:
2082 return validname
2083
2084
2085
2086
2087 python_lhapdf=None
2089 """load the python module of lhapdf return None if it can not be loaded"""
2090
2091
2092 global python_lhapdf
2093 if python_lhapdf:
2094 if python_lhapdf == -1:
2095 return None
2096 else:
2097 return python_lhapdf
2098
2099 use_lhapdf=False
2100 try:
2101
2102 lhapdf_libdir=subprocess.Popen([lhapdfconfig,'--libdir'],\
2103 stdout=subprocess.PIPE).stdout.read().decode().strip()
2104 except:
2105 use_lhapdf=False
2106 return False
2107 else:
2108 try:
2109 candidates=[dirname for dirname in os.listdir(lhapdf_libdir) \
2110 if os.path.isdir(os.path.join(lhapdf_libdir,dirname))]
2111 except OSError:
2112 candidates=[]
2113 for candidate in candidates:
2114 if os.path.isdir(os.path.join(lhapdf_libdir,candidate,'site-packages')):
2115 sys.path.insert(0,os.path.join(lhapdf_libdir,candidate,'site-packages'))
2116 try:
2117 import lhapdf
2118 use_lhapdf=True
2119 break
2120 except ImportError:
2121 sys.path.pop(0)
2122 continue
2123 if not use_lhapdf:
2124 try:
2125 candidates=[dirname for dirname in os.listdir(lhapdf_libdir+'64') \
2126 if os.path.isdir(os.path.join(lhapdf_libdir+'64',dirname))]
2127 except OSError:
2128 candidates=[]
2129
2130 for candidate in candidates:
2131 if os.path.isdir(os.path.join(lhapdf_libdir+'64',candidate,'site-packages')):
2132 sys.path.insert(0,os.path.join(lhapdf_libdir+'64',candidate,'site-packages'))
2133 try:
2134 import lhapdf
2135 use_lhapdf=True
2136 break
2137 except ImportError:
2138 sys.path.pop(0)
2139 continue
2140 if not use_lhapdf:
2141 try:
2142 import lhapdf
2143 use_lhapdf=True
2144 except ImportError:
2145 print('fail')
2146 logger.warning("Failed to access python version of LHAPDF: "\
2147 "If the python interface to LHAPDF is available on your system, try "\
2148 "adding its location to the PYTHONPATH environment variable and the"\
2149 "LHAPDF library location to LD_LIBRARY_PATH (linux) or DYLD_LIBRARY_PATH (mac os x)."\
2150 "The required LD_LIBRARY_PATH is "+ lhapdf_libdir
2151 )
2152
2153 if use_lhapdf:
2154 python_lhapdf = lhapdf
2155 python_lhapdf.setVerbosity(0)
2156 else:
2157 python_lhapdf = None
2158 return python_lhapdf
2159
2161 """implement newton method for solving f(x)=0, df is the derivate"""
2162 x = x0
2163 iter=0
2164 while abs(f(x)) > error:
2165 iter+=1
2166 x = x - f(x)/df(x)
2167 if iter ==maxiter:
2168 sprint('fail to solve equation')
2169 raise Exception
2170 return x
2171
2172 -def wget(http, path, *args, **opt):
2173 """a wget function for both unix and mac"""
2174
2175 if sys.platform == "darwin":
2176 return call(['curl', '-L', http, '-o%s' % path], *args, **opt)
2177 else:
2178 return call(['wget', http, '--output-document=%s'% path], *args, **opt)
2179
2181 'Convert a cmp= function into a key= function (for using python2 type of sort)'
2182
2183 class K:
2184 def __init__(self, obj, *args):
2185 self.obj = obj
2186 def __lt__(self, other):
2187 return mycmp(self.obj, other.obj) < 0
2188 def __gt__(self, other):
2189 return mycmp(self.obj, other.obj) > 0
2190 def __eq__(self, other):
2191 return mycmp(self.obj, other.obj) == 0
2192 def __le__(self, other):
2193 return mycmp(self.obj, other.obj) <= 0
2194 def __ge__(self, other):
2195 return mycmp(self.obj, other.obj) >= 0
2196 def __ne__(self, other):
2197 return mycmp(self.obj, other.obj) != 0
2198 return K
2199
2201 """return the smallest key adiff in A such that adiff not in B or A[adiff] != B[bdiff]"""
2202 diff_keys = [k for k in A if k not in B or A[k] != B[k]]
2203 return min(diff_keys)
2204
2206 if len(A) != len(B):
2207 return (len(A) > len(B)) - (len(A) < len(B))
2208 try:
2209 adiff = smallest_diff_key(A, B)
2210 except ValueError:
2211
2212 return 0
2213 bdiff = smallest_diff_key(B, A)
2214 if adiff != bdiff:
2215 a = adiff
2216 b = bdiff
2217 return (a > b) - (a < b)
2218 a = A[adiff]
2219 b = B[bdiff]
2220 if isinstance(a, dict):
2221 return dict_cmp(a,b,level=level+1)
2222 else:
2223 return (a > b) - (a < b)
2224
2225
2226 if six.PY3:
2227 import io
2228 file = io.FileIO
2231 """read a file returning the lines in reverse order for each call of readline()
2232 This actually just reads blocks (4096 bytes by default) of data from the end of
2233 the file and returns last line in an internal buffer."""
2234
2235
2237 """ readline in a backward way """
2238
2239 while len(self.data) == 1 and ((self.blkcount * self.blksize) < self.size):
2240 self.blkcount = self.blkcount + 1
2241 line = self.data[0]
2242 try:
2243 self.seek(-self.blksize * self.blkcount, 2)
2244 self.data = (self.read(self.blksize).decode() + line).split('\n')
2245 except IOError:
2246 self.seek(0)
2247 data = self.read(self.size - (self.blksize * (self.blkcount-1))).decode() + line
2248 self.data = data.split('\n')
2249
2250 if len(self.data) == 0:
2251 return ""
2252
2253 line = self.data.pop()
2254 return line + '\n'
2255
2256 - def __init__(self, filepos, blksize=4096):
2257 """initialize the internal structures"""
2258
2259
2260 self.size = os.stat(filepos)[6]
2261
2262 self.blksize = blksize
2263
2264 self.blkcount = 1
2265 file.__init__(self, filepos, 'rb')
2266
2267
2268 if self.size > self.blksize:
2269 self.seek(-self.blksize * self.blkcount, 2)
2270 self.data = self.read(self.blksize).decode().split('\n')
2271
2272
2273 if not self.data[-1]:
2274 self.data.pop()
2275
2277 line = self.readline()
2278 if line:
2279 return line
2280 else:
2281 raise StopIteration
2282 -def tqdm(iterator, **opts):
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309