Source code for xopto

# -*- coding: utf-8 -*-
################################ Begin license #################################
# Copyright (C) Laboratory of Imaging technologies,
#               Faculty of Electrical Engineering,
#               University of Ljubljana.
#
# This file is part of PyXOpto.
#
# PyXOpto is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# PyXOpto is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with PyXOpto. If not, see <https://www.gnu.org/licenses/>.
################################# End license ##################################

import os
import sys

__version__ = '0.2.2'


VERBOSE = False
''' Verbose reporting. '''

if 'PYXOPTO_VERBOSE' in os.environ and os.environ['PYXOPTO_VERBOSE']:
    VERBOSE = bool(os.environ['PYXOPTO_VERBOSE'])

if VERBOSE:
    print('Initializing PyXOpto {}'.format(__version__))
    os.environ['PYOPENCL_COMPILER_OUTPUT'] = '1'

ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
''' The package directory. '''

PICKLE_PROTOCOL = 4
''' Default pickle protocol of the package. '''

DATA_PATH = os.path.join(ROOT_PATH, 'data')
''' Main data storage directory. '''

BIN_PATH = os.path.join(ROOT_PATH, 'bin')
''' Directory of binary/executable files. '''

PRIMES_PATH = os.path.join(DATA_PATH, 'primes')
''' Location of OpenCL random number generator seeds. '''


SRC_PATH = os.path.join(ROOT_PATH, 'src')
''' Location of compilable source code. '''

USER_TMP_PATH = os.path.join(ROOT_PATH, 'tmp')
''' Temporary data path. '''

MCBASE_PATH = os.path.join(ROOT_PATH, 'mcbase')
''' Root directory of MC base. '''

MCCYL_PATH = os.path.join(ROOT_PATH, 'mccyl')
''' Root directory of MC Cyl. '''

MCML_PATH = os.path.join(ROOT_PATH, 'mcml')
''' Root directory of MC ML. '''

MCVOX_PATH = os.path.join(ROOT_PATH, 'mcvox')
''' Root directory of MC VOX. '''

UTIL_PATH = os.path.join(ROOT_PATH, 'util')
''' Root directory of MC utilities. '''

USER_PATH = os.path.join(os.path.expanduser('~'), '.xopto', 'pyxopto')
''' Root path of user data storage. '''
if 'PYXOPTO_USER_PATH' in os.environ and os.environ['PYXOPTO_USER_PATH']:
    USER_PATH = str(os.environ['PYXOPTO_USER_PATH'])

USER_DATA_PATH = os.path.join(USER_PATH, 'data')
''' User directory for precalculated data. '''

USER_BIN_PATH = os.path.join(USER_PATH, 'bin')
''' User directory for built libraries or executables. '''

USER_TMP_PATH = os.path.join(USER_PATH, 'tmp')
''' User directory for temporary data. '''

USER_BUILD_PATH = os.path.join(USER_PATH, 'build')
''' User directory for build. '''

USER_PRIMES_PATH = os.path.join(USER_DATA_PATH, 'primes')
''' User directory for RNG primes. '''

[docs]def fulfills_min(requirement: str) -> bool: ''' Checks if this version of PyXOpto fulfills the minimum required version. Parameters ---------- required: str Required version as a string, e.g. "0.2.1". Returns ------- fulfills: bool Returns True if PyXOpto fulfills the requirement, else False. Note ---- PyXOpto version is composed of three numbers (major, minor, patch), e.g. "0.2.0". ''' this_version = [int(item) for item in __version__.split('.')] for index, item in enumerate(requirement.split('.')): item = item.strip() if index >= len(this_version): break if item == '*': continue if this_version[index] < int(item): return False return True
[docs]def make_user_dirs(): ''' Create all the user directories for data, binary and temporary files. ''' for dir in (USER_DATA_PATH, USER_BIN_PATH, USER_TMP_PATH, USER_BUILD_PATH, USER_PRIMES_PATH): if not os.path.isdir(dir): try: os.makedirs(dir) except OSError: pass
make_user_dirs()
[docs]def rebuild(envvars: dict = None, verbose: bool = False): ''' Rebuilds all the external dependencies of xopto (rng). Parameters ---------- envvars: dict Additional environmental variables for the build process. verbose: bool Enables verbose output. Examples -------- Build with default settings and external library installation paths. >>> import xopto >>> xopto.rebuild() Compiling rng.cpp ... Linking rng.o ... Moving rng64.so to xopto/bin ... Cleanup ... All done. >>> ''' from xopto.util import build import platform if not os.path.isdir(USER_BIN_PATH): try: os.makedirs(USER_BIN_PATH) except OSError: pass if not os.path.isdir(USER_BUILD_PATH): try: os.makedirs(USER_BUILD_PATH) except OSError: pass env = None if envvars is not None: for key in envvars: os.environ[key] = envvars[key] env = dict(os.environ) srclist=[os.path.join(ROOT_PATH, 'src', 'rng', 'rng.cpp')] inclist = [os.path.join(ROOT_PATH, 'src', 'rng')] moveto = USER_BIN_PATH os_num_bits = build.os_bits() if platform.system() == 'Linux': build_target = 'rng{}.so'.format(os_num_bits) build.build_so_dll( srclist=srclist, inclist=inclist, target=build_target, moveto=moveto, envvars=envvars, cwd=USER_BUILD_PATH, verbose=verbose ) elif platform.system() == 'Windows': build_target = 'rng{}.dll'.format(os_num_bits) build.build_so_dll( srclist=srclist, inclist=inclist, target=build_target, moveto=moveto, envvars=envvars, cwd=USER_BUILD_PATH, verbose=verbose ) else: raise RuntimeError('Rebuild supported only on Linux and Windows OS!')
[docs]def rebuild_(envvars: dict = None): ''' Rebuilds all the external dependencies of xopto (rng). Parameters ---------- envvars: dict Additional environmental variables for the build process. Examples -------- Build with default settings and external library installation paths. >>> import xopto >>> xopto.rebuild() Compiling rng.cpp ... Linking rng.o ... Moving rng64.so to xopto/bin ... Cleanup ... All done. >>> ''' import subprocess import platform import math import sys if os.path.isdir(BIN_PATH): try: os.makedirs(BIN_PATH) except OSError: pass env = None if envvars is not None: for key in envvars: os.environ[key] = envvars[key] env = dict(os.environ) if platform.system() == 'Linux': cwd = os.path.join(ROOT_PATH, SRC_PATH, 'rng') if math.log(sys.maxsize)/math.log(2) > 32: proc = subprocess.Popen( ['./build64.sh'], cwd=cwd, env=env, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) else: proc = subprocess.Popen( ['./build32.sh'], cwd=cwd, env=env, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) for line in proc.stdout: if isinstance(line, bytes): line = line.decode('utf8') sys.stdout.write(line) elif platform.system() == 'Windows': cwd = os.path.join(ROOT_PATH, SRC_PATH, 'rng') cwd = cwd.replace('/', '\\') if math.log(sys.maxsize)/math.log(2) > 32: proc = subprocess.Popen( ['build64.bat', 'exit'], cwd=cwd, shell=True, env=env, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) else: proc = subprocess.Popen( ['build32.bat', 'exit'], cwd=cwd, shell=True, env=env, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) for line in proc.stdout: if isinstance(line, bytes): line = line.decode('utf8') sys.stdout.write(line) else: raise RuntimeError('Rebuild supported only on Linux and Windows OS!')