Пример #1
0
    def get_background_model(self, saturation_radius):
        """Creates a model for the background of the signal.

        The mean radial profile is fitted with the following three components:

        * Voigt profile for the central beam
        * Exponential profile for the diffuse scatter
        * Linear profile for the background offset and to improve the fit

        Using the exponential profile and the linear profile, an
        ElectronDiffraction signal is produced representing the mean background
        of the signal. This may be used for background subtraction.

        Parameters
        ----------
        saturation_radius : int
            The radius of the region about the central beam in which pixels are
            saturated.

        Returns
        -------
        ElectronDiffraction
            The mean background of the signal.

        """
        # TODO: get this done without taking the mean
        profile = self.get_radial_profile().mean()
        model = profile.create_model()
        e1 = saturation_radius * profile.axes_manager.signal_axes[0].scale
        model.set_signal_range(e1)

        direct_beam = Voigt()
        direct_beam.centre.value = 0
        direct_beam.centre.free = False
        direct_beam.FWHM.value = 0.1
        direct_beam.area.bmin = 0
        model.append(direct_beam)

        diffuse_scatter = Exponential()
        diffuse_scatter.A.value = 0
        diffuse_scatter.A.bmin = 0
        diffuse_scatter.tau.value = 0
        diffuse_scatter.tau.bmin = 0
        model.append(diffuse_scatter)

        linear_decay = Polynomial(1)
        model.append(linear_decay)

        model.fit(bounded=True)

        x_axis = self.axes_manager.signal_axes[0].axis
        y_axis = self.axes_manager.signal_axes[1].axis
        xs, ys = np.meshgrid(x_axis, y_axis)
        rs = (xs ** 2 + ys ** 2) ** 0.5
        bg = ElectronDiffraction(
            diffuse_scatter.function(rs) + linear_decay.function(rs))
        for i in (0, 1):
            bg.axes_manager.signal_axes[i].update_from(
                self.axes_manager.signal_axes[i])
        return bg
Пример #2
0
def _make_radius_vs_angle_model(
    signal,
    radial_signal_span,
    angleN=15,
    centre_x=None,
    centre_y=None,
    prepeak_range=None,
    show_progressbar=True,
):
    s_ra = signal.angular_slice_radial_average(
        angleN=angleN,
        centre_x=centre_x,
        centre_y=centre_y,
        show_progressbar=show_progressbar,
    )
    s_ra = s_ra.isig[radial_signal_span[0]:radial_signal_span[1]]

    m_ra = s_ra.create_model()

    # Fit 1 order polynomial to edges of data to account for the background
    sa = m_ra.axes_manager.signal_axes[0]
    if prepeak_range is None:
        prepeak_range = (sa.low_value, sa.index2value(4))
    m_ra.set_signal_range(prepeak_range[0], prepeak_range[1])
    m_ra.add_signal_range(sa.index2value(-3), sa.high_value)

    polynomial = Polynomial(1)
    m_ra.append(polynomial)
    m_ra.multifit(show_progressbar=show_progressbar)
    polynomial.set_parameters_not_free()

    m_ra.reset_signal_range()

    # Fit Gaussian to diffraction ring
    centre_initial = (sa.high_value + sa.low_value) * 0.5
    sigma = 3
    A = (s_ra - s_ra.min(axis=1)).data.max() * 2 * sigma

    gaussian = Gaussian(A=A, sigma=sigma, centre=centre_initial)
    gaussian.centre.bmin = sa.low_value
    gaussian.centre.bmax = sa.high_value
    m_ra.append(gaussian)
    return m_ra