Source code for minkit

########################################
# MIT License
#
# Copyright (c) 2020 Miguel Ramos Pernas
########################################
from .base.core import get_exposed_package_objects
from .backends import core as backends_core
from .backends import aop

import inspect
import os

PACKAGE_PATH = os.path.dirname(os.path.abspath(__file__))

__all__ = ['Backend']

minkit_api = get_exposed_package_objects(PACKAGE_PATH)

globals().update(minkit_api)

__all__ += list(minkit_api.keys())

__all__.sort()


[docs]class Backend(object): _exposed_objects = tuple(n for n, c in minkit_api.items( ) if inspect.isclass(c)) # loading all the classes def __init__(self, btype=backends_core.CPU, **kwargs): ''' Object used in order to do operations with objects of the :mod:`minkit` module. Any object depending on a backend can be directly built using this class, which will forward itself during its construction. :param btype: backend type (*cpu*, *cuda*, *opencl*). :type btype: str :param kwargs: arguments forwarded to the backend constructor (cuda and opencl backends only). See below for more details. :type kwargs: dict The keyword arguments can contain any of the following: * *device*: and integer defining the device to use. * *interactive*: whether to ask the user to select or correct the input device or not. If any problem appears and this argument is set to False (default), the first encountered device will be used and a warning will be displayed. These arguments are only available in *cuda* and *opencl* backends only. ''' super(Backend, self).__init__() self.__btype = btype.lower() self.__aop = aop.ArrayOperations(self, **kwargs) for n in Backend._exposed_objects: setattr(self, n, object_wrapper(minkit_api[n], self)) @property def aop(self): ''' Object to do operations on arrays. :type: ArrayOperations ''' return self.__aop @property def btype(self): ''' Backend type. :type: str ''' return self.__btype
class object_wrapper(object): def __init__(self, cls, backend): ''' Object to wrap the members of other objects so the backend is always set to that provided to this class. :param cls: class to wrap. :type cls: class :param backend: backend to use when calling the members. :type backend: Backend ''' super(object_wrapper, self).__init__() self._cls = cls self._backend = backend def __call_wrapper(self, func): ''' ''' if 'backend' in inspect.getfullargspec(func).args: def wrapper(*args, **kwargs): return func(*args, backend=self._backend, **kwargs) else: def wrapper(*args, **kwargs): return func(*args, **kwargs) wrapper.__name__ = func.__name__ wrapper.__doc__ = f''' Wrapper around the "{func.__name__}" function, which automatically sets the backend. ''' return wrapper def __call__(self, *args, **kwargs): ''' Initialize the wrapped class. :param args: arguments forwarded to the :meth:`object_wrapper.__init__` function. :type args: tuple :param kwargs: arguments forwarded to the :meth:`object_wrapper.__init__` function. :type kwargs: dict :returns: Wrapped object. ''' return self.__call_wrapper(self._cls)(*args, **kwargs) def __getattr__(self, name): ''' Get the given member of the object. :param name: name of the member. :type name: str :returns: Wrapped function. :rtype: function ''' return self.__call_wrapper(getattr(self._cls, name)) def __repr__(self): ''' Represent this class as a string. :returns: This class as a string. :rtype: str ''' return f'object_wrapper({self._cls.__name__})' # Determine the default backend DEFAULT_BACKEND_TYPE = os.environ.get( 'MINKIT_BACKEND', backends_core.CPU).lower() if DEFAULT_BACKEND_TYPE == backends_core.CPU: DEFAULT_BACKEND = Backend(DEFAULT_BACKEND_TYPE) else: dev = os.environ.get('MINKIT_DEVICE', 0) itv = os.environ.get('MINKIT_INTERACTIVE', True) DEFAULT_BACKEND = Backend(DEFAULT_BACKEND_TYPE, device=dev, interactive=itv) backends_core.set_default_aop(DEFAULT_BACKEND.aop)