예제 #1
0
def intensity(theta, amplitude, width, wavelength):
    result = np.clip(5 * np.random.randn(), 0, None)  # Gaussian noise
    for d in D_SPACINGS['Si']:
        assert wavelength < 2 * d, \
            "wavelength would result in illegal arg to arcsin"
        try:
            center = np.arcsin(wavelength / (2 * d))
        except Exception:
            print("DEAD"); center = 0
        result += voigt(theta, amplitude, center, width)
        result += voigt(-theta, amplitude, center, width)
    return result
예제 #2
0
    def dips(x, c0, wavelength, a1, sigma):
        sign = -1
        # x comes from hardware in [theta or two-theta] degrees
        x = np.deg2rad(x / factor - offset)  # radians
        assert np.all(wavelength < 2 * D), \
            "wavelength would result in illegal arg to arcsin"
        centers = np.arcsin(wavelength / (2 * D))
        # just look at one center for now
        c1 = centers[0]

        result = (
            voigt(x=x, amplitude=sign * a1, center=c0 - c1, sigma=sigma) +
            voigt(x=x, amplitude=sign * a1, center=c0 + c1, sigma=sigma))

        return result
예제 #3
0
def blurred_alpha(x,
                  nK=1e-7,
                  L=1e7,
                  p1_stat_weight=(4 / 6) * 0.7,
                  p1_center=766.504333,
                  p1_delta_f_C=3.19e9,
                  p2_stat_weight=0.35,
                  p2_center=769.913219,
                  p2_delta_f_C=3.04e9):

    # units converted from m to nm
    e = 1.6e-19
    me = 9.1e-31
    epsilon0 = 8.85e-39
    c = 3e17
    f0 = (e**2) / (4 * epsilon0 * me * (c**2))

    T = 3000
    kb = 1.38e-5
    K_MW = 39.1
    NA = 6.022E23
    mK = (K_MW / 1000) / NA
    # mK = 39*1.67e-27

    #TODO: convert to array math

    p1_delta_wl_D = 2 * np.sqrt(2 * np.log(2) * kb * T / mK) * (p1_center / c)
    p1_delta_wl_C = ((p1_center**2) / c) * p1_delta_f_C
    p1_prefactor = p1_stat_weight * f0 * p1_center**2

    p2_delta_wl_D = 2 * np.sqrt(2 * np.log(2) * kb * T / mK) * (p2_center / c)
    p2_delta_wl_C = ((p2_center**2) / c) * p2_delta_f_C
    p2_prefactor = p2_stat_weight * f0 * p2_center**2

    kappa = p1_prefactor * voigt(
        x, 1, p1_center, p1_delta_wl_D, p1_delta_wl_C) + p2_prefactor * voigt(
            x, 1, p2_center, p2_delta_wl_D, p2_delta_wl_C)

    y = 1 - np.exp(-nK * L * kappa)

    # assert all(np.diff(x) == np.diff(x)[0]) #Assuming all interpolated data at 0.026

    y = gaussian_filter1d(y, 1)
    return y
예제 #4
0
def conv_lorentzian_pvoigt(left, right, params, **kwargs):
    """Convolution between a Lorentzian and a pseudo-Voigt profile.

    .. math::

        \\begin{aligned}
        & a_L \\mathcal{L}_{\\sigma_L, center_L} \\otimes
        a_V . p\\mathcal{V}_{\\sigma, center, fraction} =

        &\\quad a_L a_V \\left[ (1 - fraction)
                \\mathcal{V}_{\\sigma_g, \\sigma, center + center_L}
                + fraction
                    \\mathcal{L}_{\\sigma + \\sigma_L, center + center_L}
            \\right]
        \\end{aligned}

    where :math:`p\\mathcal{V}` is the pseudo-Voigt, :math:`\\mathcal{V}` is
    a Voigt profile, :math:`\\sigma_g = \\frac{\\sigma}{\\sqrt{(2 log(2))}}`
    and :math:`\\mathcal{L}` is a Lorentzian.

    """
    # set left to lorentzian component if not so
    if left.func.__name__ == "pvoigt":
        left, right = (right, left)

    lp, rp, x, q, out, lglob, rglob = _getVariables(
        left, right, params, **kwargs
    )

    for qId, qVal in enumerate(q):
        amplitude = (
            lp["amplitude"]
            if "amplitude" in lglob
            else lp["amplitude_%i" % qId]
        )
        amplitude *= (
            rp["amplitude"]
            if "amplitude" in rglob
            else rp["amplitude_%i" % qId]
        )
        center = lp["center_%i" % qId] + rp["center_%i" % qId]
        rsigma = rp["sigma_%i" % qId]
        sigma_v = rsigma / np.sqrt(2 * np.log(2))
        frac = rp["fraction_%i" % qId]
        lsigma = (
            lp["sigma"] * qVal ** 2
            if "sigma" in lglob
            else lp["sigma_%i" % qId]
        )

        out.append(
            frac * voigt(x, amplitude, center, sigma_v, lsigma)
            + (1 - frac) * lorentzian(x, amplitude, center, lsigma + rsigma)
        )

    return np.array(out)
예제 #5
0
def conv_rotations_pvoigt(left, right, params, **kwargs):
    """Convolution between the rotation model and a pseudo-Voigt profile."""
    # set left to rotations component if not so
    if left.func.__name__ == "pvoigt":
        left, right = (right, left)

    lp, rp, x, q, out, lglob, rglob = _getVariables(
        left, right, params, **kwargs
    )

    for qId, qVal in enumerate(q):
        amplitude = (
            lp["amplitude"]
            if "amplitude" in lglob
            else lp["amplitude_%i" % qId]
        )
        amplitude *= (
            rp["amplitude"]
            if "amplitude" in rglob
            else rp["amplitude_%i" % qId]
        )
        center = lp["center_%i" % qId] + rp["center_%i" % qId]
        frac = rp["fraction_%i" % qId]
        lsigma = lp["sigma"] if "sigma" in lglob else lp["sigma_%i" % qId]
        rsigma = rp["sigma_%i" % qId]
        sigma_v = rsigma / np.sqrt(2 * np.log(2))
        bondDist = lp["bondDist"]

        eisf = spherical_jn(0, bondDist * qVal) ** 2
        eisf *= pvoigt(x, amplitude, center, rsigma, frac)
        qisf = np.sum(
            [
                spherical_jn(i, bondDist * qVal) ** 2
                * (2 * i + 1)
                * (
                    frac
                    * voigt(
                        x, amplitude, center, sigma_v, i * (i + 1) * lsigma
                    )
                    * (1 - frac)
                    * lorentzian(
                        amplitude, center, rsigma + i * (i + 1) * lsigma
                    )
                )
                for i in range(1, 5)
            ],
            axis=0,
        )

        out.append(eisf + qisf)

    return np.array(out)
예제 #6
0
def vibronic_ls(x, s, sigma, gamma, e_vib, kt=0, n_max=None, m_max=None):
    """
    Produce a vibronic (Frank-Condom) lineshape.
    
    The vibronic transition amplitude computed relative to 0 (ie: relative to 
    the electronic transition energy). Lines are broadened using a voigt
    profile.
    
    Parameters
    ----------
    x : np.ndarray
        Energy values. x==0 is the 0->0 line (no vibrational quanta change)
    s : float
        Huang-Rhys parameter S
    e_vib : float
        Energy of a vibrational quanta
    sigma : float
        Width (1/e^2) of gaussian component
    gamma : float
        Width of Lorententzian component
    kt : float
        Thermal energy. If >0, will compute transitions from vibrationally
        excited states. Default 0.
    n_max : int
        Largest vibrational number in final manifold. If not supplied, a guess 
        is provided, but may not be adequate.
    m_max : int
        Largest vibrational number in orginal manifold. If not supplied, a guess
        is provided, but may not be adequate.
    """
    #determine n, m, values
    if m_max is None:
        m_max = 0 if kt == 0 else int(kt / e_vib *
                                      10)  # found that factor with my thumb
    if n_max is None:
        n_max = m_max + int(10 * s)
    n = np.arange(n_max + 1)
    m = np.arange(m_max + 1)
    # compute boltzmann factors
    #boltz_f = np.exp(-m*e_vib/kt) if kt>0 else [1]
    #boltz_f /= np.sum(boltz_f)
    # FC factors
    #fcf = fc_factor(m, n, s)
    #fcf *= boltz_f[:,np.newaxis]
    fcf = vibronic_intensity(m, n, s, e_vib, kt)
    n, m = np.meshgrid(n, m)
    dvib = n - m
    y = np.zeros_like(x)
    for d, f in zip(dvib.flatten(), fcf.flatten()):
        y += voigt(x, f, d * e_vib, sigma, gamma)
    return y
예제 #7
0
    def peaks(x, c0, wavelength, a1, a2, sigma):
        # x comes from hardware in [theta or two-theta] degrees
        x = np.deg2rad(x / factor - offset)  # radians
        assert np.all(wavelength < 2 * D), \
            "wavelength would result in illegal arg to arcsin"
        cs = np.arcsin(wavelength / (2 * D))
        c1 = cs[0]
        c2 = cs[1]
        #c3 = cs[2]
        # first peak
        result = (
            voigt(x=x, amplitude=sign * a1, center=c0 - c1, sigma=sigma) +
            voigt(x=x, amplitude=sign * a1, center=c0 + c1, sigma=sigma))

        # second peak
        result += (
            voigt(x=x, amplitude=sign * a2, center=c0 - c2, sigma=sigma) +
            voigt(x=x, amplitude=sign * a2, center=c0 + c2, sigma=sigma))

        # third peak
        #result += (voigt(x=x, amplitude=sign*a3, center=c0 - c3, sigma=sigma) +
        #voigt(x=x, amplitude=sign*a3, center=c0 + c3, sigma=sigma))
        return result
예제 #8
0
def conv_gaussian_rotations(left, right, params, **kwargs):
    """Convolution of a Gaussian and a liquid rotations model."""
    # set left to Gaussian component if not so
    if left.func.__name__ == "rotations":
        left, right = (right, left)

    lp, rp, x, q, out, lglob, rglob = _getVariables(
        left, right, params, **kwargs
    )

    for qId, qVal in enumerate(q):
        amplitude = (
            lp["amplitude"]
            if "amplitude" in lglob
            else lp["amplitude_%i" % qId]
        )
        amplitude *= (
            rp["amplitude"]
            if "amplitude" in rglob
            else rp["amplitude_%i" % qId]
        )
        center = lp["center_%i" % qId] + rp["center_%i" % qId]
        lsigma = (
            lp["sigma"] * qVal ** 2
            if "sigma" in lglob
            else lp["sigma_%i" % qId]
        )
        bondDist = rp["bondDist"]
        rsigma = rp["sigma"] if "sigma" in rglob else lp["sigma_%i" % qId]

        eisf = spherical_jn(0, bondDist * qVal) ** 2
        eisf *= gaussian(x, amplitude, center, rsigma)
        qisf = np.sum(
            [
                spherical_jn(i, bondDist * qVal) ** 2
                * (2 * i + 1)
                * voigt(x, amplitude, center, lsigma, i * (i + 1) * rsigma)
                for i in range(1, 5)
            ],
            axis=0,
        )

        out.append(eisf + qisf)

    return np.array(out)
예제 #9
0
def conv_gaussian_lorentzian(left, right, params, **kwargs):
    """Convolution of a Gaussian and a Lorentzian.

    Results in a Voigt profile as defined in lineshapes.

    """
    # set left to Gaussian component if not so
    if left.func.__name__ == "lorentzian":
        left, right = (right, left)

    lp, rp, x, q, out, lglob, rglob = _getVariables(
        left, right, params, **kwargs
    )

    for qId, qVal in enumerate(q):
        amplitude = (
            lp["amplitude"]
            if "amplitude" in lglob
            else lp["amplitude_%i" % qId]
        )
        amplitude *= (
            rp["amplitude"]
            if "amplitude" in rglob
            else rp["amplitude_%i" % qId]
        )
        center = lp["center_%i" % qId] + rp["center_%i" % qId]
        sigma = (
            lp["sigma"] * qVal ** 2
            if "sigma" in lglob
            else lp["sigma_%i" % qId]
        )
        gamma = (
            rp["sigma"] * qVal ** 2
            if "sigma" in rglob
            else lp["sigma_%i" % qId]
        )

        out.append(voigt(x, amplitude, center, sigma, gamma))

    return np.array(out)
예제 #10
0
def conv_jumpdiff_pvoigt(left, right, params, **kwargs):
    """Convolution between the jump diffusion model and a
    pseudo-Voigt profile.

    """
    # set left to jump_diff component if not so
    if left.func.__name__ == "pvoigt":
        left, right = (right, left)

    lp, rp, x, q, out, lglob, rglob = _getVariables(
        left, right, params, **kwargs
    )

    for qId, qVal in enumerate(q):
        amplitude = (
            lp["amplitude"]
            if "amplitude" in lglob
            else lp["amplitude_%i" % qId]
        )
        amplitude *= (
            rp["amplitude"]
            if "amplitude" in rglob
            else rp["amplitude_%i" % qId]
        )
        center = lp["center_%i" % qId] + rp["center_%i" % qId]
        frac = rp["fraction_%i" % qId]
        lsigma = (
            lp["sigma"] * qVal ** 2 / (1 + lp["sigma"] * qVal ** 2 * lp["tau"])
            if "sigma" in lglob
            else lp["sigma_%i" % qId]
        )
        rsigma = rp["sigma_%i" % qId]
        sigma_v = rsigma / np.sqrt(2 * np.log(2))

        out.append(
            frac * voigt(x, amplitude, center, sigma_v, lsigma)
            + (1 - frac) * lorentzian(x, amplitude, center, lsigma + rsigma)
        )

    return np.array(out)
예제 #11
0
def bloch_reph_diag(x, amp, x0, s, g):
    """
    Rephasing bloch diagonal lineshape

    Parameters
    ----------
    x : array-like
        Independant axis (energy/frequency)
    amp : float
        Amplitude
    x0 : float
        Peak position
    s : float
        Inhomogeneous linewidth sigma
    g : float
        Homogeneous linewidth gamma

    Returns
    -------
    lineshape : array-like
        Complex lineshape amplitude
    """
    return np.sqrt(2 * np.pi) / g * voigt(x, amp, x0, s, g)
예제 #12
0
def peakfunc(x, amplitude, sigma, x0, slope, intercept):
    # amplitude is *not* amplitude!!! needs to be rescaled by sigma!!!!
    amplitude = amplitude * sigma * np.sqrt(2 * np.pi)
    result = voigt(x=x, amplitude=amplitude, center=x0, sigma=sigma)
    result += slope * x + intercept
    return result
예제 #13
0
 def dips(x, c1, a1, sigma):
     sign = -1
     result = voigt(x=x, amplitude=sign * a1, center=c1, sigma=sigma)
     return result
예제 #14
0
def conv_gaussian_pvoigt(left, right, params, **kwargs):
    """Convolution between a Gaussian and a pseudo-Voigt profile.

    .. math::

        \\begin{aligned}
        & a_L G_{\\sigma_G, center_G} \\otimes
        a_V . \\mathcal{pV}_{\\sigma, center, fraction} =

        & \\quad a_G a_V \\left[fraction
                \\mathcal{V}_{\\sigma_G, \\sigma, center + center_G}
            + (1 - fraction) G_{\\sigma_g + \\sigma_G, center + center_G}
            \\right]
        \\end{aligned}

    where :math:`\\mathcal{pV}` is the pseudo-Voigt, :math:`\\mathcal{V}` is
    a Voigt profile, and
    :math:`\\sigma_g = \\frac{\\sigma}{\\sqrt{(2 log(2))}}`.

    """
    # set left to gaussian component if not so
    if left.func.__name__ == "pvoigt":
        left, right = (right, left)

    lp, rp, x, q, out, lglob, rglob = _getVariables(
        left, right, params, **kwargs
    )

    for qId, qVal in enumerate(q):
        amplitude = (
            lp["amplitude"]
            if "amplitude" in lglob
            else lp["amplitude_%i" % qId]
        )
        amplitude *= (
            rp["amplitude"]
            if "amplitude" in rglob
            else rp["amplitude_%i" % qId]
        )
        center = lp["center_%i" % qId] + rp["center_%i" % qId]
        rsigma = rp["sigma_%i" % qId]
        frac = rp["fraction_%i" % qId]
        lsigma = (
            lp["sigma"] * qVal ** 2
            if "sigma" in lglob
            else lp["sigma_%i" % qId]
        )
        sigma_g = rsigma / np.sqrt(2 * np.log(2))

        convGauss = amplitude / np.sqrt(
            2 * np.pi * (sigma_g ** 2 + lsigma ** 2)
        )
        convGauss *= np.exp(
            -((x - center) ** 2) / (2 * sigma_g ** 2 + lsigma ** 2)
        )

        out.append(
            frac * convGauss
            + (1 - frac) * voigt(x, amplitude, center, lsigma, rsigma)
        )

    return np.array(out)