Esempio n. 1
0
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
Esempio n. 2
0
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
Esempio n. 3
0
def dofit(x,
          y,
          pars,
          lims=[[1e-2, 1e6], [1, 4000.], [0.001, 100.]],
          yerr=None,
          einf=1.,
          drude=None,
          rep=1,
          opti='lbf',
          fix=None,
          args=()):
    '''fitting reflectivity/transmissivity with N-resonator model
    pars is a 2-d array (ampl,freq,absorb)
    errors not yet implemented
    fitting method either TNC, light BFGS or Cobyla ('tnc/lbf/cob')
    '''
    global gang, fit
    extrapars = {}
    if opti == 'tnc':
        from scipy.optimize import tnc as optimod
        mizer = optimod.fmin_tnc
        extrapars = {'messages': 0}
    else:
        from scipy.optimize import lbfgsb as optimod
        mizer = optimod.fmin_l_bfgs_b
    from numpy import array
    if fit == None:  #no fit functions entered
        dierep = -1
        if len(y.shape) == 2 and y.shape[1] == 2:
            y = y[:, 0] + 1j * y[:, 1]
            if yerr != None: weight = 1 / yerr[:, 0] + 1j / yerr[:, 1]
            print("fitting complex numbers: ellipsometry")
            #dierep=
        elif str(y.dtype)[:7] == 'complex':
            dierep = 0  # calculating in complex plane
            if yerr != None: weight = 1 / yerr.real + 1j / yerr.imag
            print("fitting complex numbers")
        else:
            if yerr != None: weight = 1 / yerr
        if drude != None:

            def fit(spars):
                ospars = array(spars[3:]).reshape((len(spars) - 3) // 3,
                                                  3)  #oscilator parameters
                dif = y.copy()
                if dierep == 0:
                    dif -= dielect(x, spars[0], ospars, drude=spars[1:3])
                else:
                    dif -= rdielect(x,
                                    spars[0],
                                    ospars,
                                    drude=spars[1:3],
                                    ang=gang)
                if yerr != None: dif *= weight
                return sum(abs(dif)**2)  #dif*conj(dif))
        else:

            def fit(spars):
                ospars = array(spars[1:]).reshape((len(spars) - 1) // 3, 3)
                dif = y.copy()
                if dierep == 0: dif -= dielect(x, spars[0], ospars)
                else: dif -= rdielect(x, spars[0], ospars, ang=gang)
                if yerr != None: dif *= weight
                return sum(abs(dif)**2)  #sum(dif*conj(dif))

        if rep == -3: return fit
        #def fit(spars,args):
        #    return sum((args[1]-dielect(args[0],spars[0],array(spars[1:]).reshape((len(spars)-1)//3,3)))**2)
    if type(pars) == list: pars = array(pars)
    if len(pars.shape) == 2: pars = pars.reshape(pars.shape + (1, ))
    if einf == None: ipars = [1.]
    else: ipars = type(einf) == list and einf[:1] or [einf]
    if drude != None: ipars += list(drude)
    ipars += list(pars[:, :, 0].flat)
    if rep == -2: return ipars
    if lims != None:
        if len(lims) == len(ipars): blims = lims
        else:
            blims = [elims]
            if drude != None: blims += [[0.1, 100], [0.1, 100.]]
            if len(lims) == len(ipars) - 1: blims += lims
            elif len(lims) == 3:
                print('setting limits')
                for i in range(len(pars)):
                    for j in range(3):
                        if lims[j][0] < 0:
                            blims.append([pars[i, j, 0] + a for a in lims[j]])
                        else:
                            blims.append(lims[j])
            #if type(lims[0]==list)
        if rep == -1: return blims
        blims = array(blims)
    else:
        blims = None
    if opti == 'cob':
        from scipy.optimize import fmin_cobyla as mizer
        par_con = [
            lambda p: (p[i] - blims[i][0]) * (blims[i][1] - p[i])
            for i in range(len(blims))
        ]
        out = mizer(fit, array(ipars), par_con, args=args)
    else:
        out = mizer(fit,
                    array(ipars),
                    None,
                    args=args,
                    approx_grad=True,
                    bounds=blims,
                    **extrapars)
    return out
Esempio n. 4
0
def dofit(x,y,pars,lims=[[1e-2,1e6],[1,4000.],[0.001,100.]],yerr=None,einf=1.,drude=None,rep=1,opti='lbf',fix=None,args=()):
    '''fitting reflectivity/transmissivity with N-resonator model
    pars is a 2-d array (ampl,freq,absorb)
    errors not yet implemented
    fitting method either TNC, light BFGS or Cobyla ('tnc/lbf/cob')
    '''
    global gang,fit
    extrapars={}
    if opti=='tnc':
        from scipy.optimize import tnc as optimod
        mizer=optimod.fmin_tnc
        extrapars={'messages':0}
    else:
        from scipy.optimize import lbfgsb as optimod
        mizer=optimod.fmin_l_bfgs_b
    from numpy import array
    if fit==None: #no fit functions entered
        dierep=-1
        if len(y.shape)==2 and y.shape[1]==2: 
            y=y[:,0]+1j*y[:,1]
            if yerr!=None: weight=1/yerr[:,0]+1j/yerr[:,1]
            print("fitting complex numbers: ellipsometry")
            #dierep=
        elif str(y.dtype)[:7]=='complex': 
            dierep=0 # calculating in complex plane
            if yerr!=None: weight=1/yerr.real+1j/yerr.imag
            print("fitting complex numbers")
        else:
            if yerr!=None: weight=1/yerr
        if drude!=None:
            def fit(spars):
                ospars=array(spars[3:]).reshape((len(spars)-3)//3,3) #oscilator parameters
                dif=y.copy()
                if dierep==0: dif-=dielect(x,spars[0],ospars,drude=spars[1:3])
                else: dif-=rdielect(x,spars[0],ospars,drude=spars[1:3],ang=gang)
                if yerr!=None: dif*=weight
                return sum(abs(dif)**2)#dif*conj(dif))
        else:
            def fit(spars):
                ospars=array(spars[1:]).reshape((len(spars)-1)//3,3)
                dif=y.copy()
                if dierep==0: dif-=dielect(x,spars[0],ospars)
                else: dif-=rdielect(x,spars[0],ospars,ang=gang)
                if yerr!=None: dif*=weight
                return sum(abs(dif)**2)#sum(dif*conj(dif))
        if rep==-3: return fit
        #def fit(spars,args):
        #    return sum((args[1]-dielect(args[0],spars[0],array(spars[1:]).reshape((len(spars)-1)//3,3)))**2)
    if type(pars)==list: pars=array(pars)
    if len(pars.shape)==2: pars=pars.reshape(pars.shape+(1,))
    if einf==None: ipars=[1.]
    else: ipars=type(einf)==list and einf[:1] or [einf]
    if drude!=None: ipars+=list(drude)
    ipars+=list(pars[:,:,0].flat)
    if rep==-2: return ipars
    if lims!=None:
        if len(lims)==len(ipars): blims=lims
        else:
            blims=[elims]
            if drude!=None: blims+=[[0.1,100],[0.1,100.]]
            if len(lims)==len(ipars)-1: blims+=lims
            elif len(lims)==3:
                print('setting limits')
                for i in range(len(pars)):
                    for j in range(3):
                        if lims[j][0]<0: blims.append([pars[i,j,0]+a for a in lims[j]])
                        else: blims.append(lims[j])
            #if type(lims[0]==list)
        if rep==-1: return blims
        blims=array(blims)
    else:
        blims=None
    if opti=='cob':
        from scipy.optimize import fmin_cobyla as mizer
        par_con=[lambda p:(p[i]-blims[i][0])*(blims[i][1]-p[i]) for i in range(len(blims))]
        out=mizer(fit,array(ipars),par_con,args=args)
    else:
        out=mizer(fit,array(ipars),None,args=args,approx_grad=True,bounds=blims,**extrapars)
    return out