def spec_fit(waf, prange=[.2, 2], lbin=8, loud=0, istart=50, uband=0, esel=[], mode='inve'): bd = waf.samps[istart].bands[uband] zsel = bd.sel.copy() if len(esel) > 1: zsel[bd.ix < esel[0]] = False zsel[bd.ix > esel[1]] = False x = bd.ix[zsel].copy() x -= x.mean() import spectra of, chi = spectra.fitting(x, bd.absol()[zsel], lbin=lbin, prange=prange, loud=abs(loud), fit_mode=0, refr_mode=mode) #"simpl") apars, achi = [], [] if loud < 0: return of, chi for s in waf.samps: cof, chi = spectra.fitting(x, s.bands[uband].absol()[zsel], lbin=lbin, p0=of, prange=prange, loud=0, fit_mode=0, refr_mode=mode) apars.append(cof) achi.append(chi) return np.array(apars).T, np.array(achi)
def fitting(rang=[0,10],res=None,erange=[1.5,1.9],plim=120,prange=[0.025,0.035]): ''' prange: range of allowed periods ''' if res==None: res=array([ -3.6493, 12.2222, -10.0929, 0.02989, -0.5501, -0.8253, 3.0086, -2.462]) sint=(bins>erange[0])*(bins<erange[1]) rar=zeros((len(zzall[0]),8)) rep=[] for k in range(rang[0],rang[1]): rar[:,:]=0 selel=array(mall[k])>plim sys.stdout.write('scanning %i points in line %i\n'%(sum(selel),k)) sys.stdout.flush() zz2=zzall[k]/nomal*refe[:2600] parad=[spectra.fitting(bins[sint],zz2[i][sint],res,prange=prange) for i in where(selel)[0]] rar[(array(mall[k])>120)]=array([p[0] for p in parad]) mval=[mean(polyval(a[5:],bins[sint])) for a in rar] rep+=[rar.copy()] return rep
def multifit(x=None, y=None, epsil=None, wid=None, ang=0, mix=None, opti='lbf', yerr=None, smooth=None, dierep=0, ifit=None, nfit_lays=0, lims=None): '''fitting thickness of multiple layers / mixing ratios in dierep: fitting complete dielectric function uses tabulated values of dielec. function (given in epsil) additional parameters to fit can produce polynomial shift of diel. fun (layer adjusted is specified by global "mod_layer" parameter) ADDed: smoothing option to reduce sensitivity to fast variations floating_norm global parameter (in the case of smoothing) global setting non_uniform: accounts for spread of widths over illuminated area (large diaphragm) ''' global idix, fit #if ang>0: print 'incidence at %.1f deg '%ang if opti == 'tnc': from scipy.optimize import tnc as optimod mizer = optimod.fmin_tnc else: from scipy.optimize import lbfgsb as optimod mizer = optimod.fmin_l_bfgs_b from numpy import array, all, conj, sqrt, ones if wid[0] == 0: #no assumptions about initial parameters from spectra import fitting out = fitting(x, y) wid[0] = per_conv[0] / ( (out[0][3] - per_conv[1]) * sqrt(epsil[0].real.mean())) #wid[0]=per_conv/(out[3]*sqrt(epsil[0].real.mean())) print('estimated principal layer width %f' % wid[0]) if yerr != None and all(yerr.real > 0): weight = 1 / yerr.real if all(yerr.imag > 0): weight += 1j / yerr.imag if ifit == None: #no fit functions entered r, sh, psi = plate(x, epsil, wid, ang=ang, rep=-1) from numpy import convolve, polyfit, polyval if smooth != None: y = convolve(y, smooth)[len(smooth):-len(smooth)] print('data shape %i' % y.shape) def fit(spars, rep=0): global idix #print spars slate = convolve( abs( friter([t.copy() for t in r], [sh[i] * spars[i] for i in range(len(sh))], psi))**2, smooth)[len(smooth):-len(smooth)] #slate=convolve(plate(x,epsil,list(spars),meth=0,ang=ang,rep=dierep),smooth)[len(smooth):-len(smooth)] if floating_norm > 0: idix = polyfit(slate, y, floating_norm) dif = y - polyval(idix, slate) else: dif = y - slate if yerr != None: dif *= weight if rep == 1: return dif return sum((dif * conj(dif)).real) else: def fit(spars, rep=0): global idix #print spars rlays = [t.copy() for t in r] shlays = [ sh[i] * spars[i] for i in range(min(len(sh), len(spars))) ] if len(spars) < len(sh): shlays.extend(sh[len(spars):]) elif len(spars) > len(sh): prof = polyval(spars[:len(sh) - 1:-1], x) rlays[mod_layer] *= prof shlays[mod_layer] *= prof if non_uniform: dif = y - wid_spread( rlays, shlays, psi, [1 - abs(non_uniform), 1 + abs(non_uniform)], wind=non_uniform_layer, ang=ang, rep=-2) if floating_norm >= 0: slate = abs(friter(rlays, shlays, psi))**2 if floating_norm == 0: from extra import rob_polyfit a, c = rob_polyfit(slate, y, wei=-1) if c > 0.6: # minimal correlation to do renormalization idix = rob_polyfit(slate, y, wei=2) dif = y - polyval(idix, slate) else: dif = y - slate else: idix = polyfit(slate, y, floating_norm) dif = y - polyval(idix, slate) else: dif = y - abs(friter(rlays, shlays, psi))**2 #dif=y-plate(x,epsil,list(spars),meth=0,ang=ang,rep=dierep) if yerr != None: dif *= weight if rep == 1: return dif return sum((dif * conj(dif)).real) if dierep == -2: return fit else: fit = ifit if nfit_lays == 0: nfit_lays = len(wid) if lims: out = mizer(fit, ones(nfit_lays), None, args=(), approx_grad=True, bounds=array(lims)) else: out = mizer(fit, ones(nfit_lays), None, args=(), approx_grad=True) return out, wid
def multifit(x=None,y=None,epsil=None,wid=None,ang=0,mix=None,opti='lbf',yerr=None,smooth=None,dierep=0,ifit=None,nfit_lays=0,lims=None): '''fitting thickness of multiple layers / mixing ratios in dierep: fitting complete dielectric function uses tabulated values of dielec. function (given in epsil) additional parameters to fit can produce polynomial shift of diel. fun (layer adjusted is specified by global "mod_layer" parameter) ADDed: smoothing option to reduce sensitivity to fast variations floating_norm global parameter (in the case of smoothing) global setting non_uniform: accounts for spread of widths over illuminated area (large diaphragm) ''' global idix,fit #if ang>0: print 'incidence at %.1f deg '%ang if opti=='tnc': from scipy.optimize import tnc as optimod mizer=optimod.fmin_tnc else: from scipy.optimize import lbfgsb as optimod mizer=optimod.fmin_l_bfgs_b from numpy import array,all,conj,sqrt,ones if wid[0]==0: #no assumptions about initial parameters from spectra import fitting out=fitting(x,y) wid[0]=per_conv[0]/((out[0][3]-per_conv[1])*sqrt(epsil[0].real.mean())) #wid[0]=per_conv/(out[3]*sqrt(epsil[0].real.mean())) print('estimated principal layer width %f'%wid[0]) if yerr!=None and all(yerr.real>0): weight=1/yerr.real if all(yerr.imag>0): weight+=1j/yerr.imag if ifit==None: #no fit functions entered r,sh,psi=plate(x,epsil,wid,ang=ang,rep=-1) from numpy import convolve,polyfit,polyval if smooth!=None: y=convolve(y,smooth)[len(smooth):-len(smooth)] print('data shape %i'%y.shape) def fit(spars,rep=0): global idix #print spars slate=convolve(abs(friter([t.copy() for t in r],[sh[i]*spars[i] for i in range(len(sh))],psi))**2,smooth)[len(smooth):-len(smooth)] #slate=convolve(plate(x,epsil,list(spars),meth=0,ang=ang,rep=dierep),smooth)[len(smooth):-len(smooth)] if floating_norm>0: idix=polyfit(slate,y,floating_norm) dif=y-polyval(idix,slate) else: dif=y-slate if yerr!=None: dif*=weight if rep==1: return dif return sum((dif*conj(dif)).real) else: def fit(spars,rep=0): global idix #print spars rlays=[t.copy() for t in r] shlays=[sh[i]*spars[i] for i in range(min(len(sh),len(spars)))] if len(spars)<len(sh): shlays.extend(sh[len(spars):]) elif len(spars)>len(sh): prof=polyval(spars[:len(sh)-1:-1],x) rlays[mod_layer]*=prof shlays[mod_layer]*=prof if non_uniform: dif=y-wid_spread(rlays,shlays,psi,[1-abs(non_uniform),1+abs(non_uniform)],wind=non_uniform_layer,ang=ang,rep=-2) if floating_norm>=0: slate=abs(friter(rlays,shlays,psi))**2 if floating_norm==0: from extra import rob_polyfit a,c=rob_polyfit(slate,y,wei=-1) if c>0.6: # minimal correlation to do renormalization idix=rob_polyfit(slate,y,wei=2) dif=y-polyval(idix,slate) else: dif=y-slate else: idix=polyfit(slate,y,floating_norm) dif=y-polyval(idix,slate) else: dif=y-abs(friter(rlays,shlays,psi))**2 #dif=y-plate(x,epsil,list(spars),meth=0,ang=ang,rep=dierep) if yerr!=None: dif*=weight if rep==1: return dif return sum((dif*conj(dif)).real) if dierep==-2: return fit else: fit=ifit if nfit_lays==0:nfit_lays=len(wid) if lims: out=mizer(fit,ones(nfit_lays),None,args=(),approx_grad=True,bounds=array(lims)) else: out=mizer(fit,ones(nfit_lays),None,args=(),approx_grad=True) return out,wid