Commit 1a60c8b5 authored by Michele Maris's avatar Michele Maris
Browse files

u

parent 3f16e7c1
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
import numpy as np
import pandas as pd
from .stats import CumulativeOfData
from .struct import struct as STRUCT

class EnsembleFitting_Base :
    """This class implements Ensemble fitting with curve_fit for (a,b,c,Rdark) out of the input curve.
@@ -135,6 +137,22 @@ class EnsembleFitting_Base :
        except :
            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) :
        """
        the fitter function, must be specialized according to the this template
+56 −5
Original line number Diff line number Diff line
@@ -5,11 +5,13 @@ Simple stats
import numpy as np

class CumulativeOfData :
   """strucuture to handle the cumulative of 1d data"""
   """strucuture to handle the cumulative of 1d data
      It uses linear interpolations
   """
   @property
   def cdf(self) :
      """the cdf """
      return self._cdf
   def CDF(self) :
      """the cdf sampled curve """
      return self._eff
   @property
   def x(self) :
      """the score"""
@@ -18,6 +20,10 @@ class CumulativeOfData :
   def N(self) :
      """the number of finite samples"""
      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) :
      """:X: 1d array of scores"""
      idx=np.where(np.isfinite(X))
@@ -32,12 +38,57 @@ class CumulativeOfData :
      :x: the score
      """
      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) :
      """computes the percentile of samples for which x<=percentile(eff)
      
      :eff: the required percentile [0,1]
      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)