#!/usr/bin/env python3
"""
.. module:: caching
:synopsis: The memoize technique, for caching.
.. moduleauthor:: Andre Lessa <lessa.a.p@gmail.com>
.. moduleauthor:: Wolfgang Waltenberger <wolfgang.waltenberger@gmail.com>
"""
from functools import wraps
from unum import IncompatibleUnitsError
from smodels.base.physicsUnits import GeV, fb
import numpy as np
from collections.abc import Iterable
from smodels.statistics.basicStats import observed, apriori, aposteriori, NllEvalType
from functools import lru_cache, wraps
[docs]def roundObj(obj, digits : int):
""" round <obj> to <digits> digits """
if isinstance(obj,Iterable):
new_obj = tuple([np.round(x,digits) for x in obj])
else:
new_obj = float(np.round(obj,digits))
return new_obj
[docs]def roundCache(argname = None, argpos : int = 0, digits : int = 8,
maxsize: int = 128, verbose : bool = False,
turnoff : bool = False ):
"""
Returns the cached function called with the argument defined
by argname and in the position argpos rounded to the
amount of desired digits.
"""
def roundCacheDec(function):
func_cache = lru_cache(maxsize=maxsize)(function)
@wraps(func_cache)
def wrapper(*args, **kwargs):
rounded_kwargs = kwargs
rounded_args = list(args)
if argname in rounded_kwargs:
rounded_kwargs[argname] = roundObj(rounded_kwargs[argname],digits)
elif argpos < len(rounded_args):
rounded_args[argpos] = roundObj(rounded_args[argpos],digits)
rounded_args = tuple(rounded_args)
if verbose:
print ( f"[cache] mu={args[1]} kwargs {kwargs} returns {func_cache(*rounded_args, **rounded_kwargs)}" )
print ( f"[cache] orig {function(*rounded_args, **rounded_kwargs)}" )
if turnoff:
return function(*rounded_args, **rounded_kwargs )
return func_cache(*rounded_args, **rounded_kwargs)
return wrapper
return roundCacheDec
if __name__ == "__main__":
from typing import Union, Text
class TestCase:
def __init__ ( self ):
self.bla = 0
@roundCache(argname='mu',argpos=1,digits=5)
def myfunc ( self, mu : float = 0., evaluationType : NllEvalType = observed,
asimov : Union[None,float] = None ):
print ( "calling myfunc" )
ret = mu
if evaluationType == apriori:
ret += 10.
if evaluationType == aposteriori:
ret += 20.
if asimov != None:
ret += 1000.*(asimov+1000.)
if asimov == None:
ret = None
return ret
test = TestCase()
print ( test.myfunc ( 1. ) )
print ( test.myfunc ( 1. ) )
print ( test.myfunc ( mu=1. ) )
print ( test.myfunc ( mu=1. ) )
print ( test.myfunc ( 1.,evaluationType=apriori, asimov=0. ) )
print ( test.myfunc ( 1.,evaluationType=apriori, asimov=0. ) )
print ( test.myfunc ( 1.,apriori, asimov=0. ) )
print ( test.myfunc ( 1.,apriori, asimov=0. ) )