def LPfit(v,i,init=dict(Te=50, Vf=15, I0=None), plot=None, maxits=None): #Takes about 2ms/it for 2500 points, and halving this only saves 10% if maxits is None: # this trickiness makes it work, but not pythonic. maxits = globals()['maxits'] if plot is None: plot = debug>0 Te = init['Te'] Vf = init['Vf'] I0 = init['I0'] if I0 is None: I0 = 1.7 * np.average(np.clip(i, 0, 1000)) var = [Te, Vf, I0] scale = np.array([Te, Te/3, I0]) fit_results = amoeba.amoeba(var, scale, error_fun, itmax = maxits, data = dict(v=v, i=i)) Te, Vf, I0 = fit_results[0] plotchar(v, Te, Vf, I0, linewidth=4) residual, mits = fit_results[1:3] if plot: plt.title('Te = {Te:.1f}eV, Vf = {Vf:.1f}, Isat = {I0:.3g}, resid = {r:.2g} {mits} its ' .format(Te=Te, Vf=Vf, I0=I0, r=-1*float(residual), mits=mits)) plt.suptitle('{shot} {tr} {d}' .format(tr=t_range, shot=shot_number, d=diag_name)) plt.show(block=0) return(fit_results)
def LPfit(v,i,init=dict(Te=50, Vf=15, I0=None), plot=None, maxits=None): #Takes about 2ms/it for 2500 points, and halving this only saves 10% if maxits is None: # this trickiness makes it work, but not pythonic. maxits = globals()['maxits'] if plot is None: plot = debug>0 Te = init['Te'] Vf = init['Vf'] I0 = init['I0'] if I0 is None: I0 = 1.7 * np.average(np.clip(i, 0, 1000)) var = [Te, Vf, I0] scale = np.array([Te, Te/3, I0]) fit_results = amoeba.amoeba(var, scale, error_fun, itmax = maxits, data = dict(v=v, i=i)) Te, Vf, I0 = fit_results[0] plotchar(v, Te, Vf, I0, linewidth=4) residual, mits = fit_results[1:3] if plot: plt.title('Te = {Te:.1f}eV, Vf = {Vf:.1f}, Isat = {I0:.3g}, resid = {r:.2e} {mits} its ' .format(Te=Te, Vf=Vf, I0=I0, r=-residual, mits=mits)) plt.suptitle('{shot} {tr} {d}' .format(tr=t_range, shot=shot_number, d=diag_name)) plt.show(block=0) return(fit_results)
def fit(self, init=None, plot=None, fit_params=None, default_init=dict(Te=50, Vf=15, I0=None)): """ Perform a curve fit operation with the given parameter and initial value. 'None' invokes the fit_params determined at creation of the class, and for 'init', the default_init """ # Takes about 2ms/it for 2500 points, and halving this only saves 10% # if maxits is None: # this trickiness makes it work, but not pythonic. # maxits = globals()['maxits'] if init is None: init = default_init else: default_init.update(init) init = default_init self.trace = [] if plot is None: plot = self.plot # if None, get the defaults from the __init__ if fit_params is None: if self.fit_params is not None: fit_params = self.fit_params else: raise ValueError('Need fit params in LPfitter class or call to .fit') self.actual_fparams = self.fit_params self.actual_fparams.update(fit_params) alg = self.actual_fparams['alg'] maxits = self.actual_fparams['maxits'] ftol = self.actual_fparams['ftol'] xtol = self.actual_fparams['xtol'] Lnorm = self.actual_fparams['Lnorm'] Te = init['Te'] Vf = init['Vf'] I0 = init['I0'] if I0 is None: I0 = 1.7 * np.average(np.clip(self.i, 0, 1000)) var = [Te, Vf, I0] scale = np.array([Te, Te/3, I0]) if alg == 'leastsq': pfit, pcov, infodict, msg, ier = \ leastsq(self.residuals, var, args=(self.v, self.i), maxfev=maxits, full_output=1, diag=scale, ftol=ftol*I0, xtol=xtol) # residual already raised to power Lnorm/2 = so just square here resid = np.power(np.mean(np.abs(infodict['fvec']**2)),1./Lnorm) # this is required to scale the covariance s_sq = (self.residuals(pfit, self.v, self.i)**2).sum()/(len(self.i)-len(init)) fit_results = [pfit, resid, infodict['nfev']] if ier not in [1,2,3,4]: fit_results[-1] = 9000+ier # keep it in uint16 range if self.parent is not None and self.parent.debug>0: if self.parent.debug>1 or ier not in [1,2,3,4]: print(ier, msg) elif alg == 'amoeba': fit_results = list(amoeba.amoeba(var, scale, self.error_fun, itmax=maxits, ftolerance=ftol*I0, xtolerance=xtol, data=dict(v=self.v, i=self.i))) fit_results[1] = -fit_results[1] # change residual back to positive s_sq = None # don't know how to get cov for amoeba pcov = None Te, Vf, I0 = fit_results[0] fit_results[1] /= I0 # normalise to IO residual, mits = fit_results[1:3] fit_results.append(maxits) self.pcov = pcov self.s_sq = s_sq if plot > 1: plt.scatter(self.v, self.i, c='r', s=80, alpha=min(1, 4/np.sqrt(len(self.v)))) self.plotchar(self.v, Te, Vf, I0, linewidth=4) # provide brief info about algorithm and Lnorm in the title plt.title('Te = {Te:.1f}eV, Vf = {Vf:.1f}, Isat = {I0:.3g}, <res> = {r:.2e} {mits} {A}{p}:its ' .format(Te=Te, Vf=Vf, I0=I0, r=residual, mits=mits, A=alg.upper()[0],p=Lnorm)) plt.show(block=0) return(fit_results)