Loading src/yapsut/montecarlo_fitting.py +18 −0 Original line number Original line Diff line number Diff line import numpy as np import numpy as np import pandas as pd import pandas as pd from .stats import CumulativeOfData from .struct import struct as STRUCT class EnsembleFitting_Base : class EnsembleFitting_Base : """This class implements Ensemble fitting with curve_fit for (a,b,c,Rdark) out of the input curve. """This class implements Ensemble fitting with curve_fit for (a,b,c,Rdark) out of the input curve. Loading Loading @@ -135,6 +137,22 @@ class EnsembleFitting_Base : except : except : return np.ones(len(self._param_names))+np.nan return np.ones(len(self._param_names))+np.nan # # def montecarlo_cdf(self) : """returns a dictionary with the cdf for the montecarlo simulations. CDF are instatiations of .stats/CumulativeOfData so they are interpolating functions of the montecarlo distribution of each variable. """ try : self._mc[:,0] except : raise Exception("Error: no montecarlo simulation stored") # out=STRUCT() for ik,k in enumerate(self.param_names) : out[k]=CumulativeOfData(self._mc[:,ik]) return out # def fitting(self,X,Y,sgm) : def fitting(self,X,Y,sgm) : """ """ the fitter function, must be specialized according to the this template the fitter function, must be specialized according to the this template Loading src/yapsut/stats.py +56 −5 Original line number Original line Diff line number Diff line Loading @@ -5,11 +5,13 @@ Simple stats import numpy as np import numpy as np class CumulativeOfData : class CumulativeOfData : """strucuture to handle the cumulative of 1d data""" """strucuture to handle the cumulative of 1d data It uses linear interpolations """ @property @property def cdf(self) : def CDF(self) : """the cdf """ """the cdf sampled curve """ return self._cdf return self._eff @property @property def x(self) : def x(self) : """the score""" """the score""" Loading @@ -18,6 +20,10 @@ class CumulativeOfData : def N(self) : def N(self) : """the number of finite samples""" """the number of finite samples""" return self._N return self._N @property def z(self) : """normalized x: z(x) = (x-x.min())/(x.max()-x.min())""" return (self._x-self._x[0])/(self._x[-1]-self._x[0]) def __init__(self,X) : def __init__(self,X) : """:X: 1d array of scores""" """:X: 1d array of scores""" idx=np.where(np.isfinite(X)) idx=np.where(np.isfinite(X)) Loading @@ -32,12 +38,57 @@ class CumulativeOfData : :x: the score :x: the score """ """ return np.interp(x,self._x,self._eff,left=0.,right=1.) return np.interp(x,self._x,self._eff,left=0.,right=1.) # def sampled_pdf(self,x,method='hist') : """returns the sample pdf for a list of x output: hh, xx x must be monotously increasing or an integer if method = 'hist' the pdf is calculated using an histogram like function (default) if method = 'tan' the pdf is calculated using the local tangent to the cdf """ if not method in ['hist','tan'] : raise Exception("Error: method must be either 'hist' or 'tan'") # if method == 'hist' : if np.isscalar(x) : n=int(x) _x=np.linspace(self._x[0],self._x[-1],n) else : _x=np.sort(x) # yy=self.cdf(_x) hh=(yy[:-1]-yy[1:])/(_x[:-1]-_x[1:]) return hh, _x elif method == 'tan' : h=(self._x[-1]-self._x[0])*eps ydotF=(self.cdf(_x+h)-self.cdf(_x-h))/(2*h) ydotH=(self.cdf(_x+h/2)-self.cdf(_x-h/2))/(h) ydot=2*ydotH-ydotF # # if the lower limit is below the minimum value in the cdf if _x[0]-h<self._x[0] : ydotF=(self.cdf(_x[0]+h)-self.cdf(_x[0]))/(h) ydotH=((self.cdf(_x[0]+h)-self.cdf(_x[0])))/(h/2) ydot[0]=2*ydotH-ydotF # # if the upper limit is above the maximum value of the cdf if _x[-1]+h>self._x[-1] : ydotF=(self.cdf(_x[-1])-self.cdf(_x[-1]-h))/(h) ydotH=(self.cdf(_x[-1])-self.cdf(_x[-1]-h/2))/(h/2) ydot[-1]=2*ydotH-ydotF # return ydot, _x else : raise Exception("Error: method must be either 'hist' or 'tan'") # def percentile(self,eff) : def percentile(self,eff) : """computes the percentile of samples for which x<=percentile(eff) """computes the percentile of samples for which x<=percentile(eff) :eff: the required percentile [0,1] :eff: the required percentile [0,1] if eff<0 the result is -infty if eff<0 the result is -infty if eff>0 the result is +infty if eff>1 the result is +infty """ """ return np.interp(eff,self._eff,self._x,left=-np.infty,right=np.infty) return np.interp(eff,self._eff,self._x,left=-np.infty,right=np.infty) Loading Loading
src/yapsut/montecarlo_fitting.py +18 −0 Original line number Original line Diff line number Diff line import numpy as np import numpy as np import pandas as pd import pandas as pd from .stats import CumulativeOfData from .struct import struct as STRUCT class EnsembleFitting_Base : class EnsembleFitting_Base : """This class implements Ensemble fitting with curve_fit for (a,b,c,Rdark) out of the input curve. """This class implements Ensemble fitting with curve_fit for (a,b,c,Rdark) out of the input curve. Loading Loading @@ -135,6 +137,22 @@ class EnsembleFitting_Base : except : except : return np.ones(len(self._param_names))+np.nan return np.ones(len(self._param_names))+np.nan # # def montecarlo_cdf(self) : """returns a dictionary with the cdf for the montecarlo simulations. CDF are instatiations of .stats/CumulativeOfData so they are interpolating functions of the montecarlo distribution of each variable. """ try : self._mc[:,0] except : raise Exception("Error: no montecarlo simulation stored") # out=STRUCT() for ik,k in enumerate(self.param_names) : out[k]=CumulativeOfData(self._mc[:,ik]) return out # def fitting(self,X,Y,sgm) : def fitting(self,X,Y,sgm) : """ """ the fitter function, must be specialized according to the this template the fitter function, must be specialized according to the this template Loading
src/yapsut/stats.py +56 −5 Original line number Original line Diff line number Diff line Loading @@ -5,11 +5,13 @@ Simple stats import numpy as np import numpy as np class CumulativeOfData : class CumulativeOfData : """strucuture to handle the cumulative of 1d data""" """strucuture to handle the cumulative of 1d data It uses linear interpolations """ @property @property def cdf(self) : def CDF(self) : """the cdf """ """the cdf sampled curve """ return self._cdf return self._eff @property @property def x(self) : def x(self) : """the score""" """the score""" Loading @@ -18,6 +20,10 @@ class CumulativeOfData : def N(self) : def N(self) : """the number of finite samples""" """the number of finite samples""" return self._N return self._N @property def z(self) : """normalized x: z(x) = (x-x.min())/(x.max()-x.min())""" return (self._x-self._x[0])/(self._x[-1]-self._x[0]) def __init__(self,X) : def __init__(self,X) : """:X: 1d array of scores""" """:X: 1d array of scores""" idx=np.where(np.isfinite(X)) idx=np.where(np.isfinite(X)) Loading @@ -32,12 +38,57 @@ class CumulativeOfData : :x: the score :x: the score """ """ return np.interp(x,self._x,self._eff,left=0.,right=1.) return np.interp(x,self._x,self._eff,left=0.,right=1.) # def sampled_pdf(self,x,method='hist') : """returns the sample pdf for a list of x output: hh, xx x must be monotously increasing or an integer if method = 'hist' the pdf is calculated using an histogram like function (default) if method = 'tan' the pdf is calculated using the local tangent to the cdf """ if not method in ['hist','tan'] : raise Exception("Error: method must be either 'hist' or 'tan'") # if method == 'hist' : if np.isscalar(x) : n=int(x) _x=np.linspace(self._x[0],self._x[-1],n) else : _x=np.sort(x) # yy=self.cdf(_x) hh=(yy[:-1]-yy[1:])/(_x[:-1]-_x[1:]) return hh, _x elif method == 'tan' : h=(self._x[-1]-self._x[0])*eps ydotF=(self.cdf(_x+h)-self.cdf(_x-h))/(2*h) ydotH=(self.cdf(_x+h/2)-self.cdf(_x-h/2))/(h) ydot=2*ydotH-ydotF # # if the lower limit is below the minimum value in the cdf if _x[0]-h<self._x[0] : ydotF=(self.cdf(_x[0]+h)-self.cdf(_x[0]))/(h) ydotH=((self.cdf(_x[0]+h)-self.cdf(_x[0])))/(h/2) ydot[0]=2*ydotH-ydotF # # if the upper limit is above the maximum value of the cdf if _x[-1]+h>self._x[-1] : ydotF=(self.cdf(_x[-1])-self.cdf(_x[-1]-h))/(h) ydotH=(self.cdf(_x[-1])-self.cdf(_x[-1]-h/2))/(h/2) ydot[-1]=2*ydotH-ydotF # return ydot, _x else : raise Exception("Error: method must be either 'hist' or 'tan'") # def percentile(self,eff) : def percentile(self,eff) : """computes the percentile of samples for which x<=percentile(eff) """computes the percentile of samples for which x<=percentile(eff) :eff: the required percentile [0,1] :eff: the required percentile [0,1] if eff<0 the result is -infty if eff<0 the result is -infty if eff>0 the result is +infty if eff>1 the result is +infty """ """ return np.interp(eff,self._eff,self._x,left=-np.infty,right=np.infty) return np.interp(eff,self._eff,self._x,left=-np.infty,right=np.infty) Loading