Beispiel #1
0
 def test_get_extent(self):
     dect = Detector(pixel1=1e-4, pixel2=1e-4)
     ai = AzimuthalIntegrator(detector=dect, dist=0.1)
     ai.setFit2D(directDist=1000, centerX=50.5, centerY=50.5)
     extent = _get_radial_extent(ai=ai, shape=(100, 100), unit="2th_rad")
     max_rad = 50 * np.sqrt(2)
     calc_extent = np.arctan(max_rad * 1e-4 / 1)
     np.testing.assert_almost_equal(
         extent[1],
         calc_extent,
     )
Beispiel #2
0
    def get_azimuthal_integral2d(
        self,
        npt_rad,
        npt_azim=360,
        center=None,
        affine=None,
        mask=None,
        radial_range=None,
        azimuth_range=None,
        wavelength=None,
        unit="pyxem",
        inplace=False,
        method="splitpixel",
        map_kwargs={},
        detector=None,
        detector_dist=None,
        correctSolidAngle=True,
        ai_kwargs={},
        integrate2d_kwargs={},
    ):
        """Creates a polar reprojection using pyFAI's azimuthal integrate 2d.

        This function is designed to be fairly flexible to account for 2 different cases:

        1 - If the unit is "pyxem" then it lets pyXEM take the lead. If wavelength is none in that case
        it doesn't account for the Ewald sphere.

        2 - If unit is any of the options from pyFAI then detector cannot be None and the handling of
        units is passed to pyxem and those units are used.

        Parameters
        ---------------
        npt_rad: int
            The number of radial points to calculate
        npt_azim: int
            The number of azimuthal points to calculate
        center: None or (x,y) or BaseSignal
            The center of the pattern in pixels to preform the integration around
        affine: 3x3 array or BaseSignal
            An affine transformation to apply during the transformation
             (creates a spline map that is used by pyFAI)
        mask:  boolean array or BaseSignal
            A boolean mask to apply to the data to exclude some points.
            If mask is a baseSignal then it is itereated over as well.
        radial_range: None or (float, float)
            The radial range over which to perform the integration. Default is
            the full frame
        azim_range:None or (float, float)
            The azimuthal range over which to perform the integration. Default is
            from -pi to pi
        wavelength: None or float
            The wavelength of for the microscope. Has to be in the same units as the pyxem units if you want
            it to properly work.
        unit: str
            The unit can be "pyxem" to use the pyxem units and “q_nm^-1”, “q_A^-1”, “2th_deg”, “2th_rad”, “r_mm”
            if pyFAI is used for unit handling
        inplace: bool
            If the signal is overwritten or copied to a new signal
        detector: pyFai.detector.Detector
            The detector set up to be used by the integrator
        detector_dist: float
            distance sample - detector plan (orthogonal distance, not along the beam), in meter.
        map_kwargs: dict
            Any other keyword arguments for hyperspys map function
        integrate2d_kwargs:dict
            Any keyword arguements for PyFAI's integrate2d function

        Returns
        ----------
        polar: PolarDiffraction2D
            A polar diffraction signal

        Examples
        ----------
        Basic case using "2th_deg" units (no wavelength needed)

        >>> ds.unit = "2th_deg"
        >>> ds.get_azimuthal_integral2d(npt_rad=100)

        Basic case using a curved Ewald Sphere approximation and pyXEM units
        (wavelength needed)

        >>> ds.unit = "k_nm^-1" # setting units
        >>> ds.get_azimuthal_integral1d(npt_rad=100, wavelength=2.5e-12)

        Using pyFAI to define a detector case using a curved Ewald Sphere approximation and pyXEM units

        >>> from pyFAI.detectors import Detector
        >>> det = Detector(pixel1=1e-4, pixel2=1e-4)
        >>> ds.get_azimuthal_integral1d(npt_rad=100, detector_dist=.2, detector= det, wavelength=2.508e-12)
        """
        pyxem_units = False
        sig_shape = self.axes_manager.signal_shape

        if unit == "pyxem":
            pyxem_units = True
            pixel_scale = [
                self.axes_manager.signal_axes[0].scale,
                self.axes_manager.signal_axes[1].scale,
            ]
            if wavelength is None and self.unit not in ["2th_deg", "2th_rad"]:
                print('if the unit is not "2th_deg", "2th_rad"'
                      "then a wavelength must be given. ")
                return
            setup = _get_setup(wavelength, self.unit, pixel_scale,
                               radial_range)
            detector, detector_dist, radial_range, unit, scale_factor = setup
        use_iterate = any([
            isinstance(mask, BaseSignal),
            isinstance(affine, BaseSignal),
            isinstance(center, BaseSignal),
        ])
        if use_iterate:
            if radial_range is None:  # need consistent range
                if isinstance(center, BaseSignal):
                    ind = (0, ) * len(self.axes_manager.navigation_shape)
                    cen = center.inav[ind].data
                else:
                    cen = center
                ai = get_azimuthal_integrator(
                    detector=detector,
                    detector_distance=detector_dist,
                    shape=sig_shape,
                    center=cen,
                    wavelength=wavelength,
                )  # take 1st center
                radial_range = _get_radial_extent(ai=ai,
                                                  shape=sig_shape,
                                                  unit=unit)
                radial_range[0] = 0
            integration = self.map(azimuthal_integrate2d_slow,
                                   npt_azim=npt_azim,
                                   detector=detector,
                                   center=center,
                                   mask=mask,
                                   affine=affine,
                                   detector_distance=detector_dist,
                                   npt_rad=npt_rad,
                                   wavelength=wavelength,
                                   radial_range=radial_range,
                                   azimuth_range=azimuth_range,
                                   inplace=inplace,
                                   unit=unit,
                                   method=method,
                                   correctSolidAngle=correctSolidAngle,
                                   **integrate2d_kwargs,
                                   **map_kwargs)  # Uses slow methodology

        else:  # much simpler and no changing integrator without using map iterate
            ai = get_azimuthal_integrator(detector=detector,
                                          detector_distance=detector_dist,
                                          shape=sig_shape,
                                          center=center,
                                          affine=affine,
                                          mask=mask,
                                          wavelength=wavelength,
                                          **ai_kwargs)
            if radial_range is None:
                radial_range = _get_radial_extent(ai=ai,
                                                  shape=sig_shape,
                                                  unit=unit)
                radial_range[0] = 0

            integration = self.map(azimuthal_integrate2d_fast,
                                   azimuthal_integrator=ai,
                                   npt_rad=npt_rad,
                                   npt_azim=npt_azim,
                                   azimuth_range=azimuth_range,
                                   radial_range=radial_range,
                                   method=method,
                                   inplace=inplace,
                                   unit=unit,
                                   correctSolidAngle=correctSolidAngle,
                                   **integrate2d_kwargs,
                                   **map_kwargs)

        # Dealing with axis changes
        if inplace:
            t_axis = self.axes_manager.signal_axes[0]
            k_axis = self.axes_manager.signal_axes[1]
            self.set_signal_type("polar_diffraction")
        else:
            transfer_navigation_axes(integration, self)
            integration.set_signal_type("polar_diffraction")
            t_axis = integration.axes_manager.signal_axes[0]
            k_axis = integration.axes_manager.signal_axes[1]
        t_axis.name = "Radians"
        if azimuth_range is None:
            t_axis.scale = np.pi * 2 / npt_azim
            t_axis.offset = -np.pi
        else:
            t_axis.scale = (azimuth_range[1] - azimuth_range[0]) / npt_rad
            t_axis.offset = azimuth_range[0]
        k_axis.name = "Radius"
        if pyxem_units:
            k_axis.scale = (radial_range[1] -
                            radial_range[0]) / npt_rad / scale_factor
            k_axis.offset = radial_range[0] / scale_factor
        else:
            k_axis.scale = (radial_range[1] - radial_range[0]) / npt_rad
            k_axis.units = unit
            k_axis.offset = radial_range[0]

        return integration