Source code for diffpy.utils.transforms

import warnings
from copy import copy

import numpy as np

wavelength_warning_emsg = (
    "No wavelength has been specified. You can continue to use the DiffractionObject, but "
    "some of its powerful features will not be available. "
    "To specify a wavelength, if you have do = DiffractionObject(xarray, yarray, 'tth'), "
    "you may set do.wavelength = 1.54 for a wavelength of 1.54 angstroms."
)
invalid_tth_emsg = "Two theta exceeds 180 degrees. Please check the input values for errors."
invalid_q_or_d_or_wavelength_emsg = (
    "The supplied input array and wavelength will result in an impossible two-theta. "
    "Please check these values and re-instantiate the DiffractionObject with correct values."
)
inf_output_imsg = (
    "INFO: The largest output value in the array is infinite. This is allowed, but it will not be plotted."
)


def _validate_inputs(q, wavelength):
    if wavelength is None:
        warnings.warn(wavelength_warning_emsg, UserWarning)
        return np.empty(0)
    pre_factor = wavelength / (4 * np.pi)
    if np.any(np.abs(q * pre_factor) > 1.0):
        raise ValueError(invalid_q_or_d_or_wavelength_emsg)


[docs] def q_to_tth(q, wavelength): r"""Helper function to convert q to two-theta. If wavelength is missing, returns x-values that are integer indexes By definition the relationship is: .. math:: \sin\left(\frac{2\theta}{2}\right) = \frac{\lambda q}{4 \pi} thus .. math:: 2\theta_n = 2 \arcsin\left(\frac{\lambda q}{4 \pi}\right) Parameters ---------- q : ndarray The 1D array of :math:`q` values numpy.array([qs]). The units of q must be reciprocal of the units of wavelength. wavelength : float Wavelength of the incoming x-rays/neutrons/electrons Returns ------- tth : ndarray The 1D array of :math:`2\theta` values in degrees numpy.array([tths]). """ _validate_inputs(q, wavelength) q.astype(float) tth = copy(q) # initialize output array of same shape if wavelength is not None: tth = np.rad2deg(2.0 * np.arcsin(q * wavelength / (4 * np.pi))) else: # return intensities vs. an x-array that is just the index for i, _ in enumerate(q): tth[i] = i return tth
[docs] def tth_to_q(tth, wavelength): r"""Helper function to convert two-theta to q on independent variable axis. If wavelength is missing, returns independent variable axis as integer indexes. By definition the relationship is: .. math:: \sin\left(\frac{2\theta}{2}\right) = \frac{\lambda q}{4 \pi} thus .. math:: q = \frac{4 \pi \sin\left(\frac{2\theta}{2}\right)}{\lambda} Parameters ---------- tth : ndarray The 1D array of :math:`2\theta` values np.array([tths]). The units of tth are expected in degrees. wavelength : float The wavelength of the incoming x-rays/neutrons/electrons. Returns ------- q : ndarray The 1D array of :math:`q` values np.array([qs]). The units for the q-values are the inverse of the units of the provided wavelength. """ tth.astype(float) if np.any(np.deg2rad(tth) > np.pi): raise ValueError(invalid_tth_emsg) q = copy(tth) if wavelength is not None: pre_factor = (4.0 * np.pi) / wavelength q = pre_factor * np.sin(np.deg2rad(tth / 2)) else: # return intensities vs. an x-array that is just the index warnings.warn(wavelength_warning_emsg, UserWarning) for i, _ in enumerate(q): q[i] = i return q
[docs] def q_to_d(q): r"""Helper function to convert q to d on independent variable axis, using :math:`d = \frac{2 \pi}{q}`. Parameters ---------- q : ndarray The 1D array of :math:`q` values np.array([qs]). The units of q must be reciprocal of the units of wavelength. Returns ------- d : ndarray The 1D array of :math:`d` values np.array([ds]). """ if 0 in q: print(inf_output_imsg) return 2.0 * np.pi / copy(q)
[docs] def tth_to_d(tth, wavelength): r"""Helper function to convert two-theta to d on independent variable axis. The formula is .. math:: d = \frac{\lambda}{2 \sin\left(\frac{2\theta}{2}\right)}. Here we convert tth to q first, then to d. Parameters ---------- tth : nsarray The 1D array of :math:`2\theta` values np.array([tths]). The units of tth are expected in degrees. wavelength : float The wavelength of the incoming x-rays/neutrons/electrons. Returns ------- d : nsarray The 1D array of :math:`d` values np.array([ds]). """ q = tth_to_q(tth, wavelength) d = copy(tth) if wavelength is None: warnings.warn(wavelength_warning_emsg, UserWarning) for i, _ in enumerate(tth): d[i] = i return d if 0 in q: print(inf_output_imsg) return 2.0 * np.pi / copy(q)
[docs] def d_to_q(d): r"""Helper function to convert q to d using :math:`d = \frac{2 \pi}{q}`. Parameters ---------- d : nsarray The 1D array of :math:`d` values np.array([ds]). Returns ------- q : nsarray The 1D array of :math:`q` values np.array([qs]). The units of q must be reciprocal of the units of wavelength. """ if 0 in d: print(inf_output_imsg) return 2.0 * np.pi / copy(d)
[docs] def d_to_tth(d, wavelength): r"""Helper function to convert d to two-theta on independent variable axis. The formula is .. math:: 2\theta = 2 \arcsin\left(\frac{\lambda}{2d}\right). Here we convert d to q first, then to tth. Parameters ---------- d : nsarray The 1D array of :math:`d` values np.array([ds]). wavelength : float The wavelength of the incoming x-rays/neutrons/electrons. Returns ------- tth : nsarray The 1D array of :math:`2\theta` values np.array([tths]). The units of tth are expected in degrees. """ q = d_to_q(d) return q_to_tth(q, wavelength)