//  [python]
def fit_data(self, x, y, p0=None, bounds=None):
        #nParams=5
        ## Bounds
        #self.setup_bounds(bounds,nParams) # TODO
        ## Initial conditions
        #self.setup_guess(p0,bounds,nParams) # TODO

        # Cleaning data, and store it in object
        x,y=self.clean_data(x,y)

        I = np.argsort(x)
        x=x[I]
        y=y[I]

        # Estimating deltas
        xMin, xMax=np.min(x),np.max(x)
        yMin, yMax=np.min(y),np.max(y)
        DeltaX = (xMax-xMin)*0.02
        DeltaY = (yMax-yMin)*0.02

        # Binning data
        x_bin=np.linspace(xMin,xMax,min(200,len(x)))
        x_lin=x_bin[0:-1]+np.diff(x_bin)
        #y_lin=np.interp(x_lin,x,y) # TODO replace by bining
        y_lin = np.histogram(y, x_bin, weights=y)[0]/ np.histogram(y, x_bin)[0]
        #y_lin, _, _ = stats.binned_statistic(x, y, statistic='mean', bins=x_bin)
        #x_lin, _, _ = stats.binned_statistic(x, x, statistic='mean', bins=x_bin)
        x_lin, y_lin, bin_number = binned_statistic(x,y,bins=x_bin,statistic='mean')
        bNaN=~np.isnan(y_lin)
        y_lin=y_lin[bNaN]
        x_lin=x_lin[bNaN]

        # --- Find good guess of parameters based on data
        # SpdGenOn
        iOn = np.where(y>0)[0][0]
        SpdGenOn_0    =  x[iOn]
        SpdGenOn_Bnds = (max(x[iOn]-DeltaX,xMin), min(x[iOn]+DeltaX,xMax))
        # Slpc
        Slpc_0    = 5
        Slpc_Bnds = (0,10)
        # RtTq
        RtTq_0    = yMax
        RtTq_Bnds = (yMax-DeltaY, yMax+DeltaY)
        # RtGnSp
        iCloseRt = np.where(y>yMax*0.50)[0][0]
        RtGnSp_0    = x[iCloseRt]
        RtGnSp_Bnds = ( RtGnSp_0 -DeltaX*2, RtGnSp_0+DeltaX*2)
        # Rgn2K
        #print('>>>',SpdGenOn_0, RtGnSp_0)
        bR2=np.logical_and(x>SpdGenOn_0, x<RtGnSp_0)
        exponents=[2]
        _, pfit, _ = fit_polynomial_discrete(x[bR2], y[bR2], exponents)
        #print(pfit)
        Rgn2K_0   =pfit[0]
        Rgn2K_Bnds=(pfit[0]/2, pfit[0]*2)
#         import matplotlib.pyplot as plt
#         fig,ax = plt.subplots(1, 1, sharey=False, figsize=(6.4,4.8)) # (6.4,4.8)
#         fig.subplots_adjust(left=0.12, right=0.95, top=0.95, bottom=0.11, hspace=0.20, wspace=0.20)
#         ax.plot(x,y ,'-'   , label='')
#         ax.plot(x[bR2],y[bR2],'ko', label='')
#         ax.plot(x_lin,y_lin,'bd', label='')
#         ax.set_xlabel('')
#         ax.set_ylabel('')
#         ax.tick_params(direction='in')
#         plt.show()
        def minimize_me(p):
            RtGnSp, RtTq  , Rgn2K , SlPc , SpdGenOn = p
            y_model=np.array([gentorque(x_lin, (RtGnSp, RtTq  , Rgn2K , SlPc , SpdGenOn))])
            eps = np.mean((y_lin-y_model)**2)
#             print(eps,p)
            return  eps
        bounds = (RtGnSp_Bnds, RtTq_Bnds, Rgn2K_Bnds, Slpc_Bnds, SpdGenOn_Bnds)
        p0     = [RtGnSp_0, RtTq_0, Rgn2K_0, Slpc_0, SpdGenOn_0]
        #print('Bounds',bounds)
        #print('p0',p0)
        res = so.minimize(minimize_me, x0=p0, bounds= bounds, method='SLSQP')
        pfit=res.x

        # --- Reporting information about the fit (after the fit)
        y_fit= gentorque(x, pfit)
        self.store_fit_info(y_fit, pfit)
        # --- Return a fitted function
        self.model['fitted_function']=lambda x: gentorque(x,pfit)