def _median_ ( self , func , xmin , xmax , *args ) : ## need to know the integral from ostap.math.integral import IntegralCache iint = IntegralCache ( func , xmin , False , *args ) half = 2.0 / iint ( xmax ) from scipy import optimize ifun = lambda x : iint( x ) * half - 1.0 ## @see https://en.wikipedia.org/wiki/Median#Inequality_relating_means_and_medians try: meanv = Mean . __call__ ( self , func , *args ) sigma = RMS . __call__ ( self , func , *args ) import math xmn = meanv - 2 * sigma ## use 2 instead of 1 xmx = meanv + 2 * sigma ## use 2 instead of 1 # if isinstance ( xmin , float ) : xmn = max ( xmn , xmin ) if isinstance ( xmax , float ) : xmx = min ( xmx , xmax ) # result = optimize.brentq ( ifun , xmn , xmx ) except : result = optimize.brentq ( ifun , xmin , xmax ) return result
def __call__(self, func, *args): ## if 0.5 == self.Q: return Median.__call__(self, func, *args) elif 0.0 == self.Q: return self.xmin elif 1.0 == self.Q: return self.xmax ## need to know the integral from ostap.math.integral import IntegralCache iint = IntegralCache(func, self.xmin, err=False, args=args) quan = 1.0 / iint(self.xmax) / self.Q ifun = lambda x: iint(x) * quan - 1.0 xmn = self.xmin xmx = self.xmax p = 0.5 l = 0.5 ## make some bracketing before next step while (not isinstance(xmn, float)) or (not isinstance( xmx, float)) or l > 0.1: l /= 2 m = self._median_(func, xmn, xmx, *args) if self.Q < p: xmn = xmn xmx = float(m) p -= l elif self.Q > p: xmn = float(m) xmx = xmx p += l else: return m ## RETURN ## finally, calculate quantile from ostap.math.rootfinder import findroot result = findroot(ifun, xmn, xmx) return result
def _integral_(self, func, xmn, xmx, *args): from ostap.math.integral import IntegralCache integrator = IntegralCache(func, xmn, err=self.err, args=args) return integrator(xmx, *args)