Esempio n. 1
0
def conv(e, mu, kernel='gaussian', fwhm_e=None, efermi=None):
    """ linear broadening

    Parameters
    ----------
    e : x-axis (energy)
    mu : f(x) to convolve with g(x) kernel, mu(energy)
    kernel : convolution kernel, g(x)
             'gaussian'
             'lorentzian'
    fwhm_e: the full width half maximum in eV for the kernel
            broadening. It is an array of size 'e' with constants or
            an energy-dependent values determined by a function as
            'lin_gamma()' or 'atan_gamma()'
    """
    f = np.copy(mu)
    z = np.zeros_like(f)
    if efermi is not None:
        #ief = index_nearest(e, efermi)
        ief = np.argmin(np.abs(e-efermi))
        f[0:ief] *= 0
    if e.shape != fwhm_e.shape:
        print("Error: 'fwhm_e' does not have the same shape of 'e'")
        return 0
    # linar fit upper part of the spectrum to avoid border effects
    # polyfit => pf
    lpf = len(e)/2.
    cpf = np.polyfit(e[-lpf:], f[-lpf:], 1)
    fpf = np.poly1d(cpf)
    # extend upper energy border to 3*fhwm_e[-1]
    estep = (e[-1] - e[-2])
    eup = np.append(e, np.arange(e[-1]+estep, e[-1]+3*fwhm_e[-1], estep))
    for n in range(len(f)):
        #from now on I change e with eup
        eimin, eimax = get_ene_index(eup, eup[n], 1.5*fwhm_e[n])
        if ((eimin is None) or (eimax is None)):
            if DEBUG:
                raise IndexError('e[{0}]'.format(n))
        if len(range(eimin, eimax)) % 2 == 0:
            kx = eup[eimin:eimax+1] # odd range centered at the convolution point
        else:
            kx = eup[eimin:eimax]
        ### kernel ###
        hwhm = fwhm_e[n]/2.0
        if ('gauss' in kernel.lower()):
            ky = gaussian(kx, cen=eup[n], sigma=hwhm)
        elif ('lor' in kernel.lower()):
            ky = lorentzian(kx, cen=eup[n], sigma=hwhm)
        else:
            raise ValueError("convolution kernel '{0}' not implemented".format(kernel))
        ky = ky/ky.sum() # normalize
        zn = 0
        lk = len(kx)
        for mf, mg in zip( range(-(lk/2), (lk/2)+1), range(lk) ):
            if ( ((n+mf) >= 0) and ((n+mf) < len(f)) ):
                zn += f[n+mf] * ky[mg]
            elif ((n+mf) >= 0):
                zn += fpf(eup[n+mf]) * ky[mg]
        z[n] = zn
    return z
Esempio n. 2
0
def lsmooth(x, sigma=1, gamma=None, form='lorentzian', npad=None):
    """convolve a 1-d array with a lorentzian, gaussian, or voigt function.

    fconvolve(x, sigma=1, gamma=None, form='lorentzian', npad=None)

    arguments:
    ------------
      x       input 1-d array for smoothing.
      sigma   primary width parameter for convolving function
      gamma   secondary width parameter for convolving function
      form    name of convolving function:
                 'lorentzian' or 'gaussian' or 'voigt' ['lorentzian']
      npad    number of padding pixels to use [length of x]

    returns:
    --------
      smoothed 1-d array with same length as input array x
    """
    if npad is None:
        npad  = len(x)
    wx = arange(2*npad)
    if form.lower().startswith('gauss'):
        win = gaussian(wx, cen=npad, sigma=sigma)
    elif form.lower().startswith('voig'):
        win = voigt(wx, cen=npad, sigma=sigma, gamma=gamma)
    else:
        win = lorentzian(wx, cen=npad, sigma=sigma)

    xax = concatenate((x[2*npad:0:-1], x, x[-1:-2*npad-1:-1]))
    out = convolve(win/win.sum(), xax, mode='valid')
    nextra = int((len(out) - len(x))/2)
    return (out[nextra:])[:len(x)]
Esempio n. 3
0
def smooth(x, y, sigma=1, gamma=None, npad=None, form='lorentzian'):
    """smooth a function y(x) by convolving wih a lorentzian, gaussian,
    or voigt function.

    arguments:
    ------------
      x       input 1-d array for absicca
      y       input 1-d array for ordinate: data to be smoothed
      sigma   primary width parameter for convolving function
      gamma   secondary width parameter for convolving function
      delx    delta x to use for interpolation [mean of
      form    name of convolving function:
                 'lorentzian' or 'gaussian' or 'voigt' ['lorentzian']
      npad    number of padding pixels to use [length of x]

    returns:
    --------
      1-d array with same length as input array y
    """
    # make uniform x, y data
    TINY = 1.e-12
    xstep = min(diff(x))
    if xstep < TINY:
        raise Warning('Cannot smooth data: must be strictly increasing ')
    npad = 5
    xmin = xstep * int( (min(x) - npad*xstep)/xstep)
    xmax = xstep * int( (max(x) + npad*xstep)/xstep)
    npts = 1 + int(abs(xmax-xmin+xstep*0.1)/xstep)
    x0  = linspace(xmin, xmax, npts)
    y0  = interp(x0, x, y)

    # put sigma in units of 1 for convolving window function
    sigma *= 1.0 / xstep
    if gamma is not None:
        gamma *= 1.0 / xstep

    wx = arange(2*npts)
    if form.lower().startswith('gauss'):
        win = gaussian(wx, cen=npts, sigma=sigma)
    elif form.lower().startswith('voig'):
        win = voigt(wx, cen=npts, sigma=sigma, gamma=gamma)
    else:
        win = lorentzian(wx, cen=npts, sigma=sigma)

    y1 = concatenate((y0[npts:0:-1], y0, y0[-1:-npts-1:-1]))
    y2 = convolve(win/win.sum(), y1, mode='valid')
    if len(y2) > len(x0):
        nex = int((len(y2) - len(x0))/2)
        y2 = (y2[nex:])[:len(x0)]
    return interp(x, x0, y2)
def conv(e, mu, kernel='gaussian', fwhm_e=None, efermi=None):
    """ linear broadening

    Parameters
    ----------
    e : x-axis (energy)
    mu : f(x) to convolve with g(x) kernel, mu(energy)
    kernel : convolution kernel, g(x)
             'gaussian'
             'lorentzian'
    fwhm_e: the full width half maximum in eV for the kernel
            broadening. It is an array of size 'e' with constants or
            an energy-dependent values determined by a function as
            'lin_gamma()' or 'atan_gamma()'
    """
    f = np.copy(mu)
    z = np.zeros_like(f)
    if efermi is not None:
        #ief = index_nearest(e, efermi)
        ief = np.argmin(np.abs(e - efermi))
        f[0:ief] *= 0
    if e.shape != fwhm_e.shape:
        print("Error: 'fwhm_e' does not have the same shape of 'e'")
        return 0
    # linar fit upper part of the spectrum to avoid border effects
    # polyfit => pf
    lpf = len(e) / 2.
    cpf = np.polyfit(e[-lpf:], f[-lpf:], 1)
    fpf = np.poly1d(cpf)
    # extend upper energy border to 3*fhwm_e[-1]
    estep = (e[-1] - e[-2])
    eup = np.append(e, np.arange(e[-1] + estep, e[-1] + 3 * fwhm_e[-1], estep))
    for n in range(len(f)):
        #from now on I change e with eup
        eimin, eimax = get_ene_index(eup, eup[n], 1.5 * fwhm_e[n])
        if ((eimin is None) or (eimax is None)):
            if DEBUG:
                raise IndexError('e[{0}]'.format(n))
        if len(range(eimin, eimax)) % 2 == 0:
            kx = eup[eimin:eimax +
                     1]  # odd range centered at the convolution point
        else:
            kx = eup[eimin:eimax]
        ### kernel ###
        hwhm = fwhm_e[n] / 2.0
        if ('gauss' in kernel.lower()):
            ky = gaussian(kx, cen=eup[n], sigma=hwhm)
        elif ('lor' in kernel.lower()):
            ky = lorentzian(kx, cen=eup[n], sigma=hwhm)
        else:
            raise ValueError(
                "convolution kernel '{0}' not implemented".format(kernel))
        ky = ky / ky.sum()  # normalize
        zn = 0
        lk = len(kx)
        for mf, mg in zip(range(-(lk / 2), (lk / 2) + 1), range(lk)):
            if (((n + mf) >= 0) and ((n + mf) < len(f))):
                zn += f[n + mf] * ky[mg]
            elif ((n + mf) >= 0):
                zn += fpf(eup[n + mf]) * ky[mg]
        z[n] = zn
    return z