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 traceback
31 import gzip as ziplib
32 from distutils.version import LooseVersion, StrictVersion
33 import six
34 from six.moves import zip_longest
35 from six.moves import range
36 from six.moves import zip
37 from six.moves import input
38 StringIO = six
39 if six.PY3:
40 import io
41 file = io.IOBase
42 try:
43
44 import madgraph
45 except Exception as error:
46
47 import internal
48 from internal import MadGraph5Error, InvalidCmd
49 import internal.files as files
50 MADEVENT = True
51 else:
52 from madgraph import MadGraph5Error, InvalidCmd
53 import madgraph.iolibs.files as files
54 MADEVENT = False
55
56
57 logger = logging.getLogger('cmdprint.ext_program')
58 logger_stderr = logging.getLogger('madevent.misc')
59 pjoin = os.path.join
65 """Parse a newline separated list of "param=value" as a dictionnary
66 """
67
68 info_dict = {}
69 pattern = re.compile("(?P<name>\w*)\s*=\s*(?P<value>.*)",
70 re.IGNORECASE | re.VERBOSE)
71 for entry in fsock:
72 entry = entry.strip()
73 if len(entry) == 0: continue
74 m = pattern.match(entry)
75 if m is not None:
76 info_dict[m.group('name')] = m.group('value')
77 else:
78 raise IOError("String %s is not a valid info string" % entry)
79
80 return info_dict
81
82
83 -def glob(name, path=''):
84 """call to glob.glob with automatic security on path"""
85 import glob as glob_module
86 path = re.sub('(?P<name>\?|\*|\[|\])', '[\g<name>]', path)
87 return glob_module.glob(pjoin(path, name))
88
89
90
91
92 -def mute_logger(names=['madgraph','ALOHA','cmdprint','madevent'], levels=[50,50,50,50]):
93 """change the logger level and restore those at their initial value at the
94 end of the function decorated."""
95 def control_logger(f):
96 def restore_old_levels(names, levels):
97 for name, level in zip(names, levels):
98 log_module = logging.getLogger(name)
99 log_module.setLevel(level)
100
101 def f_with_no_logger(self, *args, **opt):
102 old_levels = []
103 for name, level in zip(names, levels):
104 log_module = logging.getLogger(name)
105 old_levels.append(log_module.level)
106 log_module.setLevel(level)
107 try:
108 out = f(self, *args, **opt)
109 restore_old_levels(names, old_levels)
110 return out
111 except:
112 restore_old_levels(names, old_levels)
113 raise
114
115 return f_with_no_logger
116 return control_logger
117
118 PACKAGE_INFO = {}
123 """Returns the current version information of the MadGraph5_aMC@NLO package,
124 as written in the VERSION text file. If the file cannot be found,
125 a dictionary with empty values is returned. As an option, an info
126 string can be passed to be read instead of the file content.
127 """
128 global PACKAGE_INFO
129
130 if info_str:
131 info_dict = parse_info_str(StringIO.StringIO(info_str))
132 return info_dict
133
134 if PACKAGE_INFO:
135 return PACKAGE_INFO
136
137 elif MADEVENT:
138 info_dict ={}
139 info_dict['version'] = open(pjoin(internal.__path__[0],'..','..','MGMEVersion.txt')).read().strip()
140 info_dict['date'] = '20xx-xx-xx'
141 PACKAGE_INFO = info_dict
142 else:
143 if PACKAGE_INFO:
144 return PACKAGE_INFO
145 info_dict = files.read_from_file(os.path.join(madgraph.__path__[0],
146 "VERSION"),
147 parse_info_str,
148 print_error=False)
149 PACKAGE_INFO = info_dict
150
151 return info_dict
152
157 """Returns the present time info for use in MG5 command history header.
158 """
159
160 creation_time = time.asctime()
161 time_info = {'time': creation_time,
162 'fill': ' ' * (26 - len(creation_time))}
163
164 return time_info
165
171 """ Returns None if compatible or, it not compatible, a string explaining
172 why it is so."""
173
174 ma5_version = None
175 try:
176 for line in open(pjoin(ma5path,'version.txt'),'r').read().split('\n'):
177 if line.startswith('MA5 version :'):
178 ma5_version=LooseVersion(line[13:].strip())
179 break
180 except:
181 ma5_version = None
182
183 if ma5_version is None:
184 reason = "No MadAnalysis5 version number could be read from the path supplied '%s'."%ma5path
185 reason += "\nThe specified version of MadAnalysis5 will not be active in your session."
186 return reason
187
188 mg5_version = None
189 try:
190 info = get_pkg_info()
191 mg5_version = LooseVersion(info['version'])
192 except:
193 mg5_version = None
194
195
196 if not mg5_version:
197 return None
198
199 if mg5_version < LooseVersion("2.6.1") and ma5_version >= LooseVersion("1.6.32"):
200 reason = "This active MG5aMC version is too old (v%s) for your selected version of MadAnalysis5 (v%s)"%(mg5_version,ma5_version)
201 reason += "\nUpgrade MG5aMC or re-install MA5 from within MG5aMC to fix this compatibility issue."
202 reason += "\nThe specified version of MadAnalysis5 will not be active in your session."
203 return reason
204
205 if mg5_version >= LooseVersion("2.6.1") and ma5_version < LooseVersion("1.6.32"):
206 reason = "Your selected version of MadAnalysis5 (v%s) is too old for this active version of MG5aMC (v%s)."%(ma5_version,mg5_version)
207 reason += "\nRe-install MA5 from within MG5aMC to fix this compatibility issue."
208 reason += "\nThe specified version of MadAnalysis5 will not be active in your session."
209 return reason
210
211 return None
212
217 """Browse the subdirectories of the path 'start_path' and returns the first
218 one found which contains at least one file ending with the string extension
219 given in argument."""
220
221 if not os.path.isdir(start_path):
222 return None
223 subdirs=[pjoin(start_path,dir) for dir in os.listdir(start_path)]
224 for subdir in subdirs:
225 if os.path.isfile(subdir):
226 if os.path.basename(subdir).endswith(extension):
227 return start_path
228 elif os.path.isdir(subdir):
229 path = find_includes_path(subdir, extension)
230 if path:
231 return path
232 return None
233
239 """ Get whether ninja supports quad prec in different ways"""
240
241
242 ninja_config = os.path.abspath(pjoin(
243 ninja_lib_path,os.pardir,'bin','ninja-config'))
244 if os.path.exists(ninja_config):
245 try:
246 p = Popen([ninja_config, '-quadsupport'], stdout=subprocess.PIPE,
247 stderr=subprocess.PIPE)
248 output, error = p.communicate()
249 return 'TRUE' in output.decode().upper()
250 except Exception:
251 pass
252
253
254
255 return False
256
257
258
259
260 -def which(program):
261 def is_exe(fpath):
262 return os.path.exists(fpath) and os.access(\
263 os.path.realpath(fpath), os.X_OK)
264
265 if not program:
266 return None
267
268 fpath, fname = os.path.split(program)
269 if fpath:
270 if is_exe(program):
271 return program
272 else:
273 for path in os.environ["PATH"].split(os.pathsep):
274 exe_file = os.path.join(path, program)
275 if is_exe(exe_file):
276 return exe_file
277 return None
278
294
300 """ Make sure to turn off some dependency of MG5aMC. """
301
302 def tell(msg):
303 if log == 'stdout':
304 print(msg)
305 elif callable(log):
306 log(msg)
307
308
309 if dependency in ['pjfry','golem','samurai','ninja','collier']:
310 if cmd.options[dependency] not in ['None',None,'']:
311 tell("Deactivating MG5_aMC dependency '%s'"%dependency)
312 cmd.options[dependency] = None
313
315 """ Checks whether the specfieid MG dependency can be activated if it was
316 not turned off in MG5 options."""
317
318 def tell(msg):
319 if log == 'stdout':
320 print(msg)
321 elif callable(log):
322 log(msg)
323
324 if cmd is None:
325 cmd = MGCmd.MasterCmd()
326
327 if dependency=='pjfry':
328 if cmd.options['pjfry'] in ['None',None,''] or \
329 (cmd.options['pjfry'] == 'auto' and which_lib('libpjfry.a') is None) or\
330 which_lib(pjoin(cmd.options['pjfry'],'libpjfry.a')) is None:
331 tell("Installing PJFry...")
332 cmd.do_install('PJFry')
333
334 if dependency=='golem':
335 if cmd.options['golem'] in ['None',None,''] or\
336 (cmd.options['golem'] == 'auto' and which_lib('libgolem.a') is None) or\
337 which_lib(pjoin(cmd.options['golem'],'libgolem.a')) is None:
338 tell("Installing Golem95...")
339 cmd.do_install('Golem95')
340
341 if dependency=='samurai':
342 raise MadGraph5Error('Samurai cannot yet be automatically installed.')
343
344 if dependency=='ninja':
345 if cmd.options['ninja'] in ['None',None,''] or\
346 (cmd.options['ninja'] == './HEPTools/lib' and not MG5dir is None and\
347 which_lib(pjoin(MG5dir,cmd.options['ninja'],'libninja.a')) is None):
348 tell("Installing ninja...")
349 cmd.do_install('ninja')
350
351 if dependency=='collier':
352 if cmd.options['collier'] in ['None',None,''] or\
353 (cmd.options['collier'] == 'auto' and which_lib('libcollier.a') is None) or\
354 which_lib(pjoin(cmd.options['collier'],'libcollier.a')) is None:
355 tell("Installing COLLIER...")
356 cmd.do_install('collier')
357
362 def is_lib(fpath):
363 return os.path.exists(fpath) and os.access(fpath, os.R_OK)
364
365 if not lib:
366 return None
367
368 fpath, fname = os.path.split(lib)
369 if fpath:
370 if is_lib(lib):
371 return lib
372 else:
373 locations = sum([os.environ[env_path].split(os.pathsep) for env_path in
374 ["DYLD_LIBRARY_PATH","LD_LIBRARY_PATH","LIBRARY_PATH","PATH"]
375 if env_path in os.environ],[])
376 for path in locations:
377 lib_file = os.path.join(path, lib)
378 if is_lib(lib_file):
379 return lib_file
380 return None
381
386 """ Return nice information on the current variable """
387
388
389 info = [('type',type(var)),('str', var)]
390 if hasattr(var, 'func_doc'):
391 info.append( ('DOC', var.__doc__) )
392 if hasattr(var, '__doc__'):
393 info.append( ('DOC', var.__doc__) )
394 if hasattr(var, '__dict__'):
395 info.append( ('ATTRIBUTE', list(var.__dict__.keys()) ))
396
397 spaces = ' ' * nb_space
398
399 outstr=''
400 for name, value in info:
401 outstr += '%s%3s : %s\n' % (spaces,name, value)
402
403 return outstr
404
405
406
407
408 wait_once = False
410
411 def deco_retry(f):
412 def deco_f_retry(*args, **opt):
413 for i in range(nb_try):
414 try:
415 return f(*args, **opt)
416 except KeyboardInterrupt:
417 raise
418 except Exception as error:
419 global wait_once
420 if not wait_once:
421 text = """Start waiting for update. (more info in debug mode)"""
422 logger.info(text)
423 logger_stderr.debug('fail to do %s function with %s args. %s try on a max of %s (%s waiting time)' %
424 (str(f), ', '.join([str(a) for a in args]), i+1, nb_try, sleep * (i+1)))
425 logger_stderr.debug('error is %s' % str(error))
426 if __debug__: logger_stderr.debug('and occurred at :'+traceback.format_exc())
427 wait_once = True
428 time.sleep(sleep * (i+1))
429
430 if __debug__:
431 raise
432 raise error.__class__('[Fail %i times] \n %s ' % (i+1, error))
433 return deco_f_retry
434 return deco_retry
435
440 """return a name of the type xxxx[A-B]yyy
441 where xxx and yyy are the common part between the two names.
442 """
443
444
445 base = [first[i] for i in range(len(first)) if first[:i+1] == last[:i+1]]
446
447 while base and base[0].isdigit():
448 base = base[1:]
449
450 end = [first[-(i+1)] for i in range(len(first)) if first[-(i+1):] == last[-(i+1):]]
451
452 while end and end[-1].isdigit():
453 end = end[:-1]
454 end.reverse()
455
456 base, end = ''.join(base), ''.join(end)
457 if end:
458 name = "%s[%s-%s]%s" % (base, first[len(base):-len(end)], last[len(base):-len(end)],end)
459 else:
460 name = "%s[%s-%s]%s" % (base, first[len(base):], last[len(base):],end)
461 return name
462
463
464
465
466 -def compile(arg=[], cwd=None, mode='fortran', job_specs = True, nb_core=1 ,**opt):
467 """compile a given directory"""
468
469 if 'nocompile' in opt:
470 if opt['nocompile'] == True:
471 if not arg:
472 return
473 if cwd:
474 executable = pjoin(cwd, arg[0])
475 else:
476 executable = arg[0]
477 if os.path.exists(executable):
478 return
479 del opt['nocompile']
480
481 cmd = ['make']
482 try:
483 if nb_core > 1:
484 cmd.append('-j%s' % nb_core)
485 cmd += arg
486 p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
487 stderr=subprocess.STDOUT, cwd=cwd, **opt)
488 (out, err) = p.communicate()
489 except OSError as error:
490 if cwd and not os.path.exists(cwd):
491 raise OSError('Directory %s doesn\'t exists. Impossible to run make' % cwd)
492 else:
493 error_text = "Impossible to compile %s directory\n" % cwd
494 error_text += "Trying to launch make command returns:\n"
495 error_text += " " + str(error) + "\n"
496 error_text += "In general this means that your computer is not able to compile."
497 if sys.platform == "darwin":
498 error_text += "Note that MacOSX doesn\'t have gmake/gfortan install by default.\n"
499 error_text += "Xcode contains gmake. For gfortran we advise: http://hpc.sourceforge.net/"
500 raise MadGraph5Error(error_text)
501
502 if p.returncode:
503
504 if not cwd:
505 cwd = os.getcwd()
506 all_file = [f.lower() for f in os.listdir(cwd)]
507 if 'makefile' not in all_file and '-f' not in arg:
508 raise OSError('no makefile present in %s' % os.path.realpath(cwd))
509
510 if mode == 'fortran' and not (which('g77') or which('gfortran')):
511 error_msg = 'A fortran compiler (g77 or gfortran) is required to create this output.\n'
512 error_msg += 'Please install g77 or gfortran on your computer and retry.'
513 raise MadGraph5Error(error_msg)
514 elif mode == 'cpp' and not which('g++'):
515 error_msg ='A C++ compiler (g++) is required to create this output.\n'
516 error_msg += 'Please install g++ (which is part of the gcc package) on your computer and retry.'
517 raise MadGraph5Error(error_msg)
518
519 try:
520 out = out.decode('utf-8')
521 except Exception:
522 out = str(out)
523
524
525 if any(tag.upper() in out.upper() for tag in ['real(kind=16)','real*16',
526 'complex*32']) and mode == 'fortran' and not \
527 ''.join(get_gfortran_version().split('.')) >= '46':
528 if not which('gfortran'):
529 raise MadGraph5Error('The fortran compiler gfortran v4.6 or later '+\
530 'is required to compile %s.\nPlease install it and retry.'%cwd)
531 else:
532 logger_stderr.error('ERROR, you could not compile %s because'%cwd+\
533 ' your version of gfortran is older than 4.6. MadGraph5_aMC@NLO will carry on,'+\
534 ' but will not be able to compile an executable.')
535 return p.returncode
536
537 error_text = 'A compilation Error occurs '
538 if cwd:
539 error_text += 'when trying to compile %s.\n' % cwd
540 error_text += 'The compilation fails with the following output message:\n'
541 error_text += ' '+out.replace('\n','\n ')+'\n'
542 error_text += 'Please try to fix this compilations issue and retry.\n'
543 error_text += 'Help might be found at https://answers.launchpad.net/mg5amcnlo.\n'
544 error_text += 'If you think that this is a bug, you can report this at https://bugs.launchpad.net/mg5amcnlo'
545 raise MadGraph5Error(error_text)
546 return p.returncode
547
549 """ Returns the gfortran version as a string.
550 Returns '0' if it failed."""
551 try:
552 p = Popen([compiler, '-dumpversion'], stdout=subprocess.PIPE,
553 stderr=subprocess.PIPE)
554 output, error = p.communicate()
555 output = output.decode("utf-8")
556 version_finder=re.compile(r"(?P<version>\d[\d.]*)")
557 version = version_finder.search(output).group('version')
558 return version
559 except Exception as error:
560 raise error
561 return '0'
562
563 -def mod_compilator(directory, new='gfortran', current=None, compiler_type='gfortran'):
564
565 if type(directory)!=list:
566 directory=[directory]
567
568
569 file_to_change=find_makefile_in_dir(directory)
570 if compiler_type == 'gfortran':
571 comp_re = re.compile('^(\s*)FC\s*=\s*(.+)\s*$')
572 var = 'FC'
573 elif compiler_type == 'cpp':
574 comp_re = re.compile('^(\s*)CXX\s*=\s*(.+)\s*$')
575 var = 'CXX'
576 else:
577 MadGraph5Error, 'Unknown compiler type: %s' % compiler_type
578
579 mod = False
580 for name in file_to_change:
581 lines = open(name,'r').read().split('\n')
582 for iline, line in enumerate(lines):
583 result = comp_re.match(line)
584 if result:
585 if new != result.group(2) and '$' not in result.group(2):
586 mod = True
587 lines[iline] = result.group(1) + var + "=" + new
588 elif compiler_type == 'gfortran' and line.startswith('DEFAULT_F_COMPILER'):
589 lines[iline] = "DEFAULT_F_COMPILER = %s" % new
590 elif compiler_type == 'cpp' and line.startswith('DEFAULT_CPP_COMPILER'):
591 lines[iline] = "DEFAULT_CPP_COMPILER = %s" % new
592
593 if mod:
594 open(name,'w').write('\n'.join(lines))
595
596 mod = False
597
599 """Check whether pid exists in the current process table.
600 UNIX only.
601 https://stackoverflow.com/questions/568271/how-to-check-if-there-exists-a-process-with-a-given-pid-in-python
602 """
603 import errno
604
605 if pid < 0:
606 return False
607 if pid == 0:
608
609
610
611
612 raise ValueError('invalid PID 0')
613 try:
614 os.kill(pid, 0)
615 except OSError as err:
616 if err.errno == errno.ESRCH:
617
618 return False
619 elif err.errno == errno.EPERM:
620
621 return True
622 else:
623
624
625 raise
626 else:
627 return True
628
635 """mute_logger (designed to work as with statement),
636 files allow to redirect the output of the log to a given file.
637 """
638
639 - def __init__(self, names, levels, files=None, **opt):
640 assert isinstance(names, list)
641 assert isinstance(names, list)
642
643 self.names = names
644 self.levels = levels
645 if isinstance(files, list):
646 self.files = files
647 else:
648 self.files = [files] * len(names)
649 self.logger_saved_info = {}
650 self.opts = opt
651
662
663 - def __exit__(self, ctype, value, traceback ):
674
676 """ Setup the logger by redirecting them all to logfiles in tmp """
677
678 logs = full_logname.split('.')
679 lognames = [ '.'.join(logs[:(len(logs)-i)]) for i in\
680 range(len(full_logname.split('.')))]
681 for logname in lognames:
682 try:
683 os.remove(path)
684 except Exception as error:
685 pass
686 my_logger = logging.getLogger(logname)
687 hdlr = logging.FileHandler(path)
688
689
690 self.logger_saved_info[logname] = [hdlr, my_logger.handlers]
691
692
693 for old_hdlr in list(my_logger.handlers):
694 my_logger.removeHandler(old_hdlr)
695 my_logger.addHandler(hdlr)
696
697 my_logger.debug('Log of %s' % logname)
698
700 """ Setup the logger by redirecting them all to logfiles in tmp """
701
702 logs = full_logname.split('.')
703 lognames = [ '.'.join(logs[:(len(logs)-i)]) for i in\
704 range(len(full_logname.split('.')))]
705 for logname in lognames:
706 if path:
707 try:
708 os.remove(path)
709 except Exception as error:
710 pass
711 my_logger = logging.getLogger(logname)
712 if logname in self.logger_saved_info:
713 my_logger.removeHandler(self.logger_saved_info[logname][0])
714 for old_hdlr in self.logger_saved_info[logname][1]:
715 my_logger.addHandler(old_hdlr)
716 else:
717 my_logger.setLevel(level)
718
719
720
721
722 nb_open =0
725 """
726 A context manager to temporarily redirect stdout or stderr
727
728 e.g.:
729
730
731 with stdchannel_redirected(sys.stderr, os.devnull):
732 if compiler.has_function('clock_gettime', libraries=['rt']):
733 libraries.append('rt')
734 """
735
736 try:
737 oldstdchannel = os.dup(stdchannel.fileno())
738 dest_file = open(dest_filename, 'w')
739 os.dup2(dest_file.fileno(), stdchannel.fileno())
740 yield
741 finally:
742 if oldstdchannel is not None:
743 os.dup2(oldstdchannel, stdchannel.fileno())
744 os.close(oldstdchannel)
745 if dest_file is not None:
746 dest_file.close()
747
749 '''
750 return the number of open file descriptors for current process
751
752 .. warning: will only work on UNIX-like os-es.
753 '''
754 import subprocess
755 import os
756
757 pid = os.getpid()
758 procs = subprocess.check_output(
759 [ "lsof", '-w', '-Ff', "-p", str( pid ) ] )
760 nprocs = [s for s in procs.split( '\n' ) if s and s[ 0 ] == 'f' and s[1: ].isdigit()]
761
762 return nprocs
763
765 """ Detects whether the specified C++ compiler is clang."""
766
767 try:
768 p = Popen([cpp_compiler, '--version'], stdout=subprocess.PIPE,
769 stderr=subprocess.PIPE)
770 output, error = p.communicate()
771 except Exception as error:
772
773 return False
774
775 output = output.decode()
776 return 'LLVM' in str(output) or "clang" in str(output)
777
780 """ Detects if the specified c++ compiler will normally link against the C++
781 standard library -lc++ or -libstdc++."""
782
783 is_clang = detect_if_cpp_compiler_is_clang(cpp_compiler)
784 if is_clang:
785 try:
786 import platform
787 v, _,_ = platform.mac_ver()
788 if not v:
789
790
791 return '-lc++'
792 else:
793 v = float(v.rsplit('.')[1])
794 if v >= 9:
795 return '-lc++'
796 else:
797 return '-lstdc++'
798 except:
799 return '-lstdc++'
800 return '-lstdc++'
801
803 """find the current compiler for the current directory"""
804
805
806
807 if compiler_type == 'fortran':
808 comp = re.compile("^\s*FC\s*=\s*([\w\/\\.\-]+)\s*")
809 elif compiler_type == 'cpp':
810 comp = re.compile("^\s*CXX\s*=\s*([\w\/\\.\-]+)\s*")
811 else:
812 MadGraph5Error, 'Unknown compiler type: %s' % compiler_type
813
814 for line in open(path):
815 if comp.search(line):
816 compiler = comp.search(line).groups()[0]
817 return compiler
818 elif compiler_type == 'fortran' and line.startswith('DEFAULT_F_COMPILER'):
819 return line.split('=')[1].strip()
820 elif compiler_type == 'cpp' and line.startswith('DEFAULT_CPP_COMPILER'):
821 return line.split('=')[1].strip()
822
824 """ return a list of all file starting with makefile in the given directory"""
825
826 out=[]
827
828 if type(directory)==list:
829 for name in directory:
830 out+=find_makefile_in_dir(name)
831 return out
832
833
834 for name in os.listdir(directory):
835 if os.path.isdir(directory+'/'+name):
836 out+=find_makefile_in_dir(directory+'/'+name)
837 elif os.path.isfile(directory+'/'+name) and name.lower().startswith('makefile'):
838 out.append(directory+'/'+name)
839 elif os.path.isfile(directory+'/'+name) and name.lower().startswith('make_opt'):
840 out.append(directory+'/'+name)
841 return out
842
844
845
846 os.path.walk('.', rm_file_extension, '.o')
847
848
849 libraries = ['libblocks.a', 'libgeneric_mw.a', 'libMWPS.a', 'libtools.a', 'libdhelas3.a',
850 'libdsample.a', 'libgeneric.a', 'libmodel.a', 'libpdf.a', 'libdhelas3.so', 'libTF.a',
851 'libdsample.so', 'libgeneric.so', 'libmodel.so', 'libpdf.so']
852 lib_pos='./lib'
853 [os.remove(os.path.join(lib_pos, lib)) for lib in libraries \
854 if os.path.exists(os.path.join(lib_pos, lib))]
855
869
873
877 replace_dict = dict(key_values)
878 replacement_function = lambda match: replace_dict[match.group(0)]
879 pattern = re.compile("|".join([re.escape(k) for k, v in key_values]), re.M)
880 return lambda string: pattern.sub(replacement_function, string)
881
884
887 def deco_check(f):
888 def deco_f(arg, *args, **opt):
889 try:
890 return f(arg, *args, **opt)
891 except OSError as error:
892 logger.debug('try to recover from %s' % error)
893 if isinstance(arg, (list,tuple)):
894 prog = arg[0]
895 else:
896 prog = arg
897
898
899 if error.errno == 13:
900 if os.path.exists(prog):
901 os.system('chmod +x %s' % prog)
902 elif 'cwd' in opt and opt['cwd'] and \
903 os.path.isfile(pjoin(opt['cwd'],arg[0])):
904 os.system('chmod +x %s' % pjoin(opt['cwd'],arg[0]))
905 return f(arg, *args, **opt)
906
907 elif error.errno == 2:
908
909 raise Exception('%s fails with no such file or directory' \
910 % arg)
911 else:
912 raise
913 return deco_f
914 return deco_check
915
916
917 @check_system_error()
918 -def call(arg, *args, **opt):
919 """nice way to call an external program with nice error treatment"""
920 try:
921 return subprocess.call(arg, *args, **opt)
922 except OSError:
923 arg[0] = './%s' % arg[0]
924 return subprocess.call(arg, *args, **opt)
925
926 @check_system_error()
927 -def Popen(arg, *args, **opt):
928 """nice way to call an external program with nice error treatment"""
929 return subprocess.Popen(arg, *args, **opt)
930
931 @check_system_error()
932 -def call_stdout(arg, *args, **opt):
933 """nice way to call an external program with nice error treatment"""
934 try:
935 out = subprocess.Popen(arg, *args, stdout=subprocess.PIPE, **opt)
936 except OSError:
937 arg[0] = './%s' % arg[0]
938 out = subprocess.call(arg, *args, stdout=subprocess.PIPE, **opt)
939
940 str_out = out.stdout.read().decode().strip()
941 return str_out
942
943
944 @multiple_try()
945 -def mult_try_open(filepath, *args, **opt):
946 """try to open a file with multiple try to ensure that filesystem is sync"""
947 return open(filepath, *args, ** opt)
948
949
950
951
952 -def tail(f, n, offset=None):
953 """Reads a n lines from f with an offset of offset lines. The return
954 value is a tuple in the form ``lines``.
955 """
956 avg_line_length = 74
957 to_read = n + (offset or 0)
958
959 while 1:
960 try:
961 f.seek(-(avg_line_length * to_read), 2)
962 except IOError:
963
964
965 f.seek(0)
966 pos = f.tell()
967 lines = f.read().splitlines()
968 if len(lines) >= to_read or pos == 0:
969 return lines[-to_read:offset and -offset or None]
970 avg_line_length *= 1.3
971 avg_line_length = int(avg_line_length)
972
974 """ makes a piping fifo (First-in First-out) file and nicely intercepts
975 error in case the file format of the target drive doesn't suppor tit."""
976
977 try:
978 os.mkfifo(fifo_path)
979 except:
980 raise OSError('MadGraph5_aMCatNLO could not create a fifo file at:\n'+
981 ' %s\n'%fifo_path+'Make sure that this file does not exist already'+
982 ' and that the file format of the target drive supports fifo file (i.e not NFS).')
983
988 """return the last line of a file"""
989
990 return tail(fsock, 1)[0]
991
995 """A generator that returns the lines of a file in reverse order"""
996 with open(filename) as fh:
997 segment = None
998 offset = 0
999 fh.seek(0, os.SEEK_END)
1000 file_size = remaining_size = fh.tell()
1001 while remaining_size > 0:
1002 offset = min(file_size, offset + buf_size)
1003 fh.seek(file_size - offset)
1004 buffer = fh.read(min(remaining_size, buf_size))
1005 remaining_size -= buf_size
1006 lines = buffer.split('\n')
1007
1008
1009
1010 if segment is not None:
1011
1012
1013
1014 if buffer[-1] != '\n':
1015 lines[-1] += segment
1016 else:
1017 yield segment
1018 segment = lines[0]
1019 for index in range(len(lines) - 1, 0, -1):
1020 if lines[index]:
1021 yield lines[index]
1022
1023 if segment is not None:
1024 yield segment
1025
1043
1057
1063 """create a temporary directory and ensure this one to be cleaned.
1064 """
1065
1066 - def __init__(self, suffix='', prefix='tmp', dir=None):
1067 self.nb_try_remove = 0
1068 import tempfile
1069 self.path = tempfile.mkdtemp(suffix, prefix, dir)
1070
1071
1072 - def __exit__(self, ctype, value, traceback ):
1073
1074 if False and isinstance(value, Exception):
1075 sprint("Directory %s not cleaned. This directory can be removed manually" % self.path)
1076 return False
1077 try:
1078 shutil.rmtree(self.path)
1079 except OSError:
1080 self.nb_try_remove += 1
1081 if self.nb_try_remove < 3:
1082 time.sleep(10)
1083 self.__exit__(ctype, value, traceback)
1084 else:
1085 logger.warning("Directory %s not completely cleaned. This directory can be removed manually" % self.path)
1086
1089
1091 """replace an attribute of a class with another value for the time of the
1092 context manager
1093 """
1094
1095 - def __init__(self, cls, attribute, value):
1096
1097 self.cls = cls
1098 self.attribute = attribute
1099 if isinstance(attribute, list):
1100 self.old_value = []
1101 for key, onevalue in zip(attribute, value):
1102 self.old_value.append(getattr(cls, key))
1103 setattr(self.cls, key, onevalue)
1104 else:
1105 self.old_value = getattr(cls, attribute)
1106 setattr(self.cls, self.attribute, value)
1107
1108 - def __exit__(self, ctype, value, traceback ):
1109
1110 if isinstance(self.attribute, list):
1111 for key, old_value in zip(self.attribute, self.old_value):
1112 setattr(self.cls, key, old_value)
1113 else:
1114 setattr(self.cls, self.attribute, self.old_value)
1115
1117 return self.old_value
1118
1119
1121 def wrapper(*args, **kwds):
1122 with self:
1123 return func(*args, **kwds)
1124
1125
1126
1127
1128 -def gunzip(path, keep=False, stdout=None):
1129 """ a standard replacement for os.system('gunzip -f %s.gz ' % event_path)"""
1130
1131
1132 if not path.endswith(".gz"):
1133 if os.path.exists("%s.gz" % path):
1134 path = "%s.gz" % path
1135 else:
1136 raise Exception("%(path)s does not finish by .gz and the file %(path)s.gz does not exists" %\
1137 {"path": path})
1138
1139
1140
1141 if os.path.getsize(path) > 1e8:
1142 if stdout:
1143 os.system('gunzip -c %s > %s' % (path, stdout))
1144 else:
1145 os.system('gunzip %s' % path)
1146 return 0
1147
1148 if not stdout:
1149 stdout = path[:-3]
1150 try:
1151 gfile = ziplib.open(path, "r")
1152 except IOError:
1153 raise
1154 else:
1155 try:
1156 open(stdout,'w').write(gfile.read().decode())
1157 except IOError as error:
1158 sprint(error)
1159
1160 if stdout == path:
1161 return
1162 else:
1163 files.cp(path, stdout)
1164 finally:
1165 gfile.close()
1166 if not keep:
1167 os.remove(path)
1168 return 0
1169
1170 -def gzip(path, stdout=None, error=True, forceexternal=False):
1171 """ a standard replacement for os.system('gzip %s ' % path)"""
1172
1173
1174 if os.path.getsize(path) > 1e9 or forceexternal:
1175 call(['gzip', '-f', path])
1176 if stdout:
1177 if not stdout.endswith(".gz"):
1178 stdout = "%s.gz" % stdout
1179 shutil.move('%s.gz' % path, stdout)
1180 return
1181
1182 if not stdout:
1183 stdout = "%s.gz" % path
1184 elif not stdout.endswith(".gz"):
1185 stdout = "%s.gz" % stdout
1186
1187 try:
1188 ziplib.open(stdout,"w").write(open(path).read().encode())
1189 except OverflowError:
1190 gzip(path, stdout, error=error, forceexternal=True)
1191 except Exception:
1192 if error:
1193 raise
1194 else:
1195 return
1196 finally:
1197 os.remove(path)
1198
1203 """ a convinient class to open a file """
1204
1205 web_browser = None
1206 eps_viewer = None
1207 text_editor = None
1208 configured = False
1209
1211 """open a file"""
1212
1213
1214 if not self.configured:
1215 self.configure()
1216
1217 try:
1218 extension = filename.rsplit('.',1)[1]
1219 except IndexError:
1220 extension = ''
1221
1222
1223
1224 if extension in ['html','htm','php']:
1225 self.open_program(self.web_browser, filename, background=True)
1226 elif extension in ['ps','eps']:
1227 self.open_program(self.eps_viewer, filename, background=True)
1228 else:
1229 self.open_program(self.text_editor,filename, mac_check=False)
1230
1231
1232 @classmethod
1255
1256 @classmethod
1294
1295
1296 @staticmethod
1298 """find a valid shell program in the list"""
1299
1300 for p in possibility:
1301 if which(p):
1302 logger.info('Using default %s \"%s\". ' % (program, p) + \
1303 'Set another one in ./input/mg5_configuration.txt')
1304 return p
1305
1306 logger.info('No valid %s found. ' % program + \
1307 'Please set in ./input/mg5_configuration.txt')
1308 return None
1309
1310
1311 - def open_program(self, program, file_path, mac_check=True, background=False):
1312 """ open a file with a given program """
1313
1314 if mac_check==True and sys.platform == 'darwin':
1315 return self.open_mac_program(program, file_path)
1316
1317
1318 if program:
1319 arguments = program.split()
1320 arguments.append(file_path)
1321
1322 if not background:
1323 subprocess.call(arguments)
1324 else:
1325 import six.moves._thread
1326 six.moves._thread.start_new_thread(subprocess.call,(arguments,))
1327 else:
1328 logger.warning('Not able to open file %s since no program configured.' % file_path + \
1329 'Please set one in ./input/mg5_configuration.txt')
1330
1332 """ open a text with the text editor """
1333
1334 if not program:
1335
1336 os.system('open %s' % file_path)
1337 elif which(program):
1338
1339 arguments = program.split()
1340 arguments.append(file_path)
1341 subprocess.call(arguments)
1342 else:
1343
1344 os.system('open -a %s %s' % (program, file_path))
1345
1365
1367 """ Try and guess what shell type does the user use."""
1368 try:
1369 if os.environ['SHELL'].endswith('bash'):
1370 return 'bash'
1371 elif os.environ['SHELL'].endswith('tcsh'):
1372 return 'tcsh'
1373 else:
1374
1375 return None
1376 except KeyError:
1377 return None
1378
1380 """ check if a path is executable"""
1381 try:
1382 return os.access(path, os.X_OK)
1383 except Exception:
1384 return False
1385
1387 """Option Peaser which raise an error instead as calling exit"""
1388
1389 - def exit(self, status=0, msg=None):
1394
1396 """Returns the current line number in our program."""
1397
1398 if not __debug__:
1399 return
1400
1401
1402 import inspect
1403 if 'cond' in opt and not opt['cond']:
1404 return
1405
1406 use_print = False
1407 if 'use_print' in opt and opt['use_print']:
1408 use_print = True
1409
1410 if 'log' in opt:
1411 log = opt['log']
1412 else:
1413 log = logging.getLogger('madgraph')
1414 if 'level' in opt:
1415 level = opt['level']
1416 else:
1417 level = logging.getLogger('madgraph').level
1418 if level == 0:
1419 use_print = True
1420
1421
1422
1423
1424 if 'wait' in opt:
1425 wait = bool(opt['wait'])
1426 else:
1427 wait = False
1428
1429 lineno = inspect.currentframe().f_back.f_lineno
1430 fargs = inspect.getframeinfo(inspect.currentframe().f_back)
1431 filename, lineno = fargs[:2]
1432
1433
1434 try:
1435 source = inspect.getsourcelines(inspect.currentframe().f_back)
1436 line = source[0][lineno-source[1]]
1437 line = re.findall(r"misc\.sprint\(\s*(.*)\)\s*($|#)", line)[0][0]
1438 if line.startswith("'") and line.endswith("'") and line.count(",") ==0:
1439 line= ''
1440 elif line.startswith("\"") and line.endswith("\"") and line.count(",") ==0:
1441 line= ''
1442 elif line.startswith(("\"","'")) and len(args)==1 and "%" in line:
1443 line= ''
1444 except Exception:
1445 line=''
1446
1447 if line:
1448 intro = ' %s = \033[0m' % line
1449 else:
1450 intro = ''
1451
1452
1453 if not use_print:
1454 log.log(level, ' '.join([intro]+[str(a) for a in args]) + \
1455 ' \033[1;30m[%s at line %s]\033[0m' % (os.path.basename(filename), lineno))
1456 else:
1457 print(' '.join([intro]+[str(a) for a in args]) + \
1458 ' \033[1;30m[%s at line %s]\033[0m' % (os.path.basename(filename), lineno))
1459
1460 if wait:
1461 input('press_enter to continue')
1462 elif 'sleep' in opt:
1463 time.sleep(int(opt['sleep']))
1464
1465 return
1466
1467
1468
1469
1470 -def equal(a,b,sig_fig=6, zero_limit=True):
1471 """function to check if two float are approximatively equal"""
1472 import math
1473
1474 if isinstance(sig_fig, int):
1475 if not a or not b:
1476 if zero_limit:
1477 if zero_limit is not True:
1478 power = zero_limit
1479 else:
1480 power = sig_fig + 1
1481 else:
1482 return a == b
1483 else:
1484 power = sig_fig - int(math.log10(abs(a)))
1485
1486 return ( a==b or abs(int(a*10**power) - int(b*10**power)) < 10)
1487 else:
1488 return abs(a-b) < sig_fig
1489
1490
1491
1492
1493
1494
1495
1496 -class chdir:
1498 self.newPath = newPath
1499
1501 self.savedPath = os.getcwd()
1502 os.chdir(self.newPath)
1503
1504 - def __exit__(self, etype, value, traceback):
1505 os.chdir(self.savedPath)
1506
1507
1508
1509
1510
1511 -def timeout(func, args=(), kwargs={}, timeout_duration=1, default=None):
1512 '''This function will spwan a thread and run the given function using the args, kwargs and
1513 return the given default value if the timeout_duration is exceeded
1514 '''
1515 import threading
1516 class InterruptableThread(threading.Thread):
1517 def __init__(self):
1518 threading.Thread.__init__(self)
1519 self.result = default
1520 def run(self):
1521 try:
1522 self.result = func(*args, **kwargs)
1523 except Exception as error:
1524 print(error)
1525 self.result = default
1526 it = InterruptableThread()
1527 it.start()
1528 it.join(timeout_duration)
1529 return it.result
1530
1531 -def mmin(iter, default=None):
1537
1538
1539
1540
1541
1542 -class digest:
1543
1545 try:
1546 return self.test_hashlib()
1547 except Exception:
1548 pass
1549 try:
1550 return self.test_md5()
1551 except Exception:
1552 pass
1553 try:
1554 return self.test_zlib()
1555 except Exception:
1556 pass
1557
1559 import hashlib
1560 def digest(text):
1561 """using mg5 for the hash"""
1562 t = hashlib.md5()
1563 t.update(text)
1564 return t.hexdigest()
1565 return digest
1566
1568 import md5
1569 def digest(text):
1570 """using mg5 for the hash"""
1571 t = md5.md5()
1572 t.update(text)
1573 return t.hexdigest()
1574 return digest
1575
1577 import zlib
1578 def digest(text):
1579 return zlib.adler32(text)
1580
1581 digest = digest().test_all()
1588 self.cmd_args = args
1589 self.cmd_opts = opts
1590 self.execution_state = False
1591
1593 self.max_vms_memory = 0
1594 self.max_rss_memory = 0
1595
1596 self.t1 = None
1597 self.t0 = time.time()
1598 self.p = subprocess.Popen(*self.cmd_args,**self.cmd_opts)
1599 self.execution_state = True
1600
1602 if not self.check_execution_state():
1603 return False
1604
1605 self.t1 = time.time()
1606
1607
1608
1609 flash = subprocess.Popen("ps -p %i -o rss"%self.p.pid,
1610 shell=True,stdout=subprocess.PIPE,stderr=open(os.devnull,"w"))
1611 stdout_list = flash.communicate()[0].decode().split('\n')
1612 rss_memory = int(stdout_list[1])
1613
1614 vms_memory = 0
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643 self.max_vms_memory = max(self.max_vms_memory,vms_memory)
1644 self.max_rss_memory = max(self.max_rss_memory,rss_memory)
1645
1646 return self.check_execution_state()
1647
1649
1650
1651 return self.p.poll() == None
1652
1654 if not self.execution_state:
1655 return False
1656 if self.is_running():
1657 return True
1658 self.executation_state = False
1659 self.t1 = time.time()
1660 return False
1661
1662 - def close(self,kill=False):
1663
1664 if self.p.poll() == None:
1665 if kill:
1666 self.p.kill()
1667 else:
1668 self.p.terminate()
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681 -class Applenotification(object):
1682
1684 self.init = False
1685 self.working = True
1686
1688 try:
1689 import Foundation
1690 import objc
1691 self.NSUserNotification = objc.lookUpClass('NSUserNotification')
1692 self.NSUserNotificationCenter = objc.lookUpClass('NSUserNotificationCenter')
1693 except:
1694 self.working=False
1695 self.working=True
1696
1697 - def __call__(self,subtitle, info_text, userInfo={}):
1698
1699 if not self.init:
1700 self.load_notification()
1701 if not self.working:
1702 return
1703 try:
1704 notification = self.NSUserNotification.alloc().init()
1705 notification.setTitle_('MadGraph5_aMC@NLO')
1706 notification.setSubtitle_(subtitle)
1707 notification.setInformativeText_(info_text)
1708 try:
1709 notification.setUserInfo_(userInfo)
1710 except:
1711 pass
1712 self.NSUserNotificationCenter.defaultUserNotificationCenter().scheduleNotification_(notification)
1713 except:
1714 pass
1715
1716
1717
1718 apple_notify = Applenotification()
1721
1722 done_notification = False
1723 message_aprilfirst =\
1724 {'error': ['Be careful, a cat is eating a lot of fish today. This makes the code unstable.',
1725 'Really, this sounds fishy.',
1726 '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?"',
1727 "Why does Heisenberg detest driving cars? Because, every time he looks at the speedometer he gets lost!",
1728 "May the mass times acceleration be with you.",
1729 "NOTE: This product may actually be nine-dimensional. If this is the case, functionality is not affected by the extra five dimensions.",
1730 "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.",
1731 "",
1732 'The fish are out of jokes. See you next year for more!'],
1733
1734
1735 }
1736
1737 default_banner_1 = "************************************************************\n" + \
1738 "* *\n" + \
1739 "* W E L C O M E to *\n" + \
1740 "* M A D G R A P H 5 _ a M C @ N L O *\n" + \
1741 "* *\n" + \
1742 "* *\n"
1743
1744
1745 default_banner_2 = "* *\n" + \
1746 "%s" + \
1747 "* *\n" + \
1748 "* The MadGraph5_aMC@NLO Development Team - Find us at *\n" + \
1749 "* https://server06.fynu.ucl.ac.be/projects/madgraph *\n" + \
1750 "* and *\n" + \
1751 "* http://amcatnlo.web.cern.ch/amcatnlo/ *\n" + \
1752 "* *\n" + \
1753 "* Type 'help' for in-line help. *\n" + \
1754 "* Type 'tutorial' to learn how MG5 works *\n" + \
1755 "* Type 'tutorial aMCatNLO' to learn how aMC@NLO works *\n" + \
1756 "* Type 'tutorial MadLoop' to learn how MadLoop works *\n" + \
1757 "* *\n" + \
1758 "************************************************************"
1759
1760 May4_banner = "* _____ *\n" + \
1761 "* ,-~\" \"~-. *\n" + \
1762 "* * ,^ ___ ^. * *\n" + \
1763 "* * / .^ ^. \ * *\n" + \
1764 "* * Y l o ! Y * *\n" + \
1765 "* * l_ `.___.' _,[ * *\n" + \
1766 "* * |^~\"--------------~\"\"^| * *\n" + \
1767 "* * ! May the 4th ! * *\n" + \
1768 "* * \ / * *\n" + \
1769 "* * ^. .^ * *\n" + \
1770 "* * \"-.._____.,-\" * *\n"
1771
1772 special_banner = {(4,5): May4_banner}
1773
1774
1813
1815 try:
1816 self.call_apple(msg)
1817 except:
1818 pass
1819
1825
1826
1828
1829
1830 p = subprocess.Popen("osascript -e 'get volume settings'", stdout=subprocess.PIPE, shell=True)
1831 output, _ = p.communicate()
1832 output = output.decode()
1833
1834 info = dict([[a.strip() for a in l.split(':',1)] for l in output.strip().split(',')])
1835 muted = False
1836 if 'output muted' in info and info['output muted'] == 'true':
1837 muted = True
1838 elif 'output volume' in info and info['output volume'] == '0':
1839 muted = True
1840
1841 if muted:
1842 if not EasterEgg.done_notification:
1843 apple_notify('On April first','turn up your volume!')
1844 EasterEgg.done_notification = True
1845 else:
1846 os.system('say %s' % msg)
1847
1848
1850
1851 fishPath = madgraph.MG5DIR+"/input/.cowgraph.cow"
1852 if os.path.exists(fishPath):
1853 fishPath = " -f " + fishPath
1854
1855
1856
1857 fishPole = which('cowthink')
1858 if not os.path.exists(fishPole):
1859 if os.path.exists(which('cowsay')):
1860 fishPole = which('cowsay')
1861 else:
1862 return
1863
1864
1865 fishCmd = fishPole + fishPath + " " + msg
1866 os.system(fishCmd)
1867
1870 """ return v2 if v1>v2
1871 return v1 if v1<v2
1872 return v1 if v1=v2
1873 return v1 if v2 is not in 1.2.3.4.5 format
1874 return v2 if v1 is not in 1.2.3.4.5 format
1875 """
1876
1877 for a1, a2 in zip_longest(v1, v2, fillvalue=0):
1878 try:
1879 a1= int(a1)
1880 except:
1881 return v2
1882 try:
1883 a2= int(a2)
1884 except:
1885 return v1
1886 if a1 > a2:
1887 return v2
1888 elif a1 < a2:
1889 return v1
1890 return v1
1891
1892
1893
1894 plugin_support = {}
1932
1933
1934
1935 -def set_global(loop=False, unitary=True, mp=False, cms=False):
1965 return deco_f_set
1966 return deco_set
1967
1972 """convenient way to import a plugin file/function"""
1973
1974 try:
1975 _temp = __import__('PLUGIN.%s' % module, globals(), locals(), fcts, -1)
1976 except ImportError:
1977 try:
1978 _temp = __import__('MG5aMC_PLUGIN.%s' % module, globals(), locals(), fcts, -1)
1979 except ImportError:
1980 raise MadGraph5Error(error_msg)
1981
1982 if not fcts:
1983 return _temp
1984 elif len(fcts) == 1:
1985 return getattr(_temp,fcts[0])
1986 else:
1987 return [getattr(_temp,name) for name in fcts]
1988
1989 -def from_plugin_import(plugin_path, target_type, keyname=None, warning=False,
1990 info=None):
1991 """return the class associated with keyname for a given plugin class
1992 if keyname is None, return all the name associated"""
1993
1994 validname = []
1995 for plugpath in plugin_path:
1996 plugindirname = os.path.basename(plugpath)
1997 for plug in os.listdir(plugpath):
1998 if os.path.exists(pjoin(plugpath, plug, '__init__.py')):
1999 try:
2000 with stdchannel_redirected(sys.stdout, os.devnull):
2001 __import__('%s.%s' % (plugindirname,plug))
2002 except Exception as error:
2003 if warning:
2004 logger.warning("error detected in plugin: %s.", plug)
2005 logger.warning("%s", error)
2006 continue
2007 plugin = sys.modules['%s.%s' % (plugindirname,plug)]
2008 if hasattr(plugin, target_type):
2009 if not is_plugin_supported(plugin):
2010 continue
2011 if keyname is None:
2012 validname += list(getattr(plugin, target_type).keys())
2013 else:
2014 if keyname in getattr(plugin, target_type):
2015 if not info:
2016 logger.info('Using from plugin %s mode %s' % (plug, keyname), '$MG:BOLD')
2017 else:
2018 logger.info(info % {'plug': plug, 'key':keyname}, '$MG:BOLD')
2019 return getattr(plugin, target_type)[keyname]
2020
2021 if not keyname:
2022 return validname
2023
2024
2025
2026
2027 python_lhapdf=None
2029 """load the python module of lhapdf return None if it can not be loaded"""
2030
2031
2032 global python_lhapdf
2033 if python_lhapdf:
2034 if python_lhapdf == -1:
2035 return None
2036 else:
2037 return python_lhapdf
2038
2039 use_lhapdf=False
2040 try:
2041
2042 lhapdf_libdir=subprocess.Popen([lhapdfconfig,'--libdir'],\
2043 stdout=subprocess.PIPE).stdout.read().decode().strip()
2044 except:
2045 use_lhapdf=False
2046 return False
2047 else:
2048 try:
2049 candidates=[dirname for dirname in os.listdir(lhapdf_libdir) \
2050 if os.path.isdir(os.path.join(lhapdf_libdir,dirname))]
2051 except OSError:
2052 candidates=[]
2053 for candidate in candidates:
2054 if os.path.isdir(os.path.join(lhapdf_libdir,candidate,'site-packages')):
2055 sys.path.insert(0,os.path.join(lhapdf_libdir,candidate,'site-packages'))
2056 try:
2057 import lhapdf
2058 use_lhapdf=True
2059 break
2060 except ImportError:
2061 sys.path.pop(0)
2062 continue
2063 if not use_lhapdf:
2064 try:
2065 candidates=[dirname for dirname in os.listdir(lhapdf_libdir+'64') \
2066 if os.path.isdir(os.path.join(lhapdf_libdir+'64',dirname))]
2067 except OSError:
2068 candidates=[]
2069 sprint(candidates, lhapdf_libdir+'64')
2070 for candidate in candidates:
2071 if os.path.isdir(os.path.join(lhapdf_libdir+'64',candidate,'site-packages')):
2072 sys.path.insert(0,os.path.join(lhapdf_libdir+'64',candidate,'site-packages'))
2073 try:
2074 import lhapdf
2075 use_lhapdf=True
2076 break
2077 except ImportError:
2078 sys.path.pop(0)
2079 continue
2080 if not use_lhapdf:
2081 try:
2082 import lhapdf
2083 use_lhapdf=True
2084 except ImportError:
2085 print('fail')
2086 logger.warning("Failed to access python version of LHAPDF: "\
2087 "If the python interface to LHAPDF is available on your system, try "\
2088 "adding its location to the PYTHONPATH environment variable and the"\
2089 "LHAPDF library location to LD_LIBRARY_PATH (linux) or DYLD_LIBRARY_PATH (mac os x)."\
2090 "The required LD_LIBRARY_PATH is "+ lhapdf_libdir
2091 )
2092
2093 if use_lhapdf:
2094 python_lhapdf = lhapdf
2095 python_lhapdf.setVerbosity(0)
2096 else:
2097 python_lhapdf = None
2098 return python_lhapdf
2099
2101 """implement newton method for solving f(x)=0, df is the derivate"""
2102 x = x0
2103 iter=0
2104 while abs(f(x)) > error:
2105 iter+=1
2106 x = x - f(x)/df(x)
2107 if iter ==maxiter:
2108 sprint('fail to solve equation')
2109 raise Exception
2110 return x
2111
2112 -def wget(http, path, *args, **opt):
2113 """a wget function for both unix and mac"""
2114
2115 if sys.platform == "darwin":
2116 return call(['curl', '-L', http, '-o%s' % path], *args, **opt)
2117 else:
2118 return call(['wget', http, '--output-document=%s'% path], *args, **opt)
2119
2121 'Convert a cmp= function into a key= function (for using python2 type of sort)'
2122
2123 class K:
2124 def __init__(self, obj, *args):
2125 self.obj = obj
2126 def __lt__(self, other):
2127 return mycmp(self.obj, other.obj) < 0
2128 def __gt__(self, other):
2129 return mycmp(self.obj, other.obj) > 0
2130 def __eq__(self, other):
2131 return mycmp(self.obj, other.obj) == 0
2132 def __le__(self, other):
2133 return mycmp(self.obj, other.obj) <= 0
2134 def __ge__(self, other):
2135 return mycmp(self.obj, other.obj) >= 0
2136 def __ne__(self, other):
2137 return mycmp(self.obj, other.obj) != 0
2138 return K
2139
2141 """return the smallest key adiff in A such that adiff not in B or A[adiff] != B[bdiff]"""
2142 diff_keys = [k for k in A if k not in B or A[k] != B[k]]
2143 return min(diff_keys)
2144
2146 if len(A) != len(B):
2147 return (len(A) > len(B)) - (len(A) < len(B))
2148 try:
2149 adiff = smallest_diff_key(A, B)
2150 except ValueError:
2151
2152 return 0
2153 bdiff = smallest_diff_key(B, A)
2154 if adiff != bdiff:
2155 a = adiff
2156 b = bdiff
2157 return (a > b) - (a < b)
2158 a = A[adiff]
2159 b = B[bdiff]
2160 if isinstance(a, dict):
2161 return dict_cmp(a,b,level=level+1)
2162 else:
2163 return (a > b) - (a < b)
2164
2165
2166 if six.PY3:
2167 import io
2168 file = io.FileIO
2171 """read a file returning the lines in reverse order for each call of readline()
2172 This actually just reads blocks (4096 bytes by default) of data from the end of
2173 the file and returns last line in an internal buffer."""
2174
2175
2177 """ readline in a backward way """
2178
2179 while len(self.data) == 1 and ((self.blkcount * self.blksize) < self.size):
2180 self.blkcount = self.blkcount + 1
2181 line = self.data[0]
2182 try:
2183 self.seek(-self.blksize * self.blkcount, 2)
2184 self.data = (self.read(self.blksize).decode() + line).split('\n')
2185 except IOError:
2186 self.seek(0)
2187 data = self.read(self.size - (self.blksize * (self.blkcount-1))).decode() + line
2188 self.data = data.split('\n')
2189
2190 if len(self.data) == 0:
2191 return ""
2192
2193 line = self.data.pop()
2194 return line + '\n'
2195
2196 - def __init__(self, filepos, blksize=4096):
2197 """initialize the internal structures"""
2198
2199
2200 self.size = os.stat(filepos)[6]
2201
2202 self.blksize = blksize
2203
2204 self.blkcount = 1
2205 file.__init__(self, filepos, 'rb')
2206
2207
2208 if self.size > self.blksize:
2209 self.seek(-self.blksize * self.blkcount, 2)
2210 self.data = self.read(self.blksize).decode().split('\n')
2211
2212
2213 if not self.data[-1]:
2214 self.data.pop()
2215
2217 line = self.readline()
2218 if line:
2219 return line
2220 else:
2221 raise StopIteration
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246