def test_get_azimuthal_integrator(self): dect = Detector(pixel1=1e-4, pixel2=1e-4, max_shape=(20, 20)) ai = get_azimuthal_integrator(detector=dect, detector_distance=0.001, shape=(20, 20), center=(10.5, 10.5)) assert isinstance(ai, AzimuthalIntegrator) ai_mask = get_azimuthal_integrator( detector=dect, detector_distance=1, shape=(20, 20), center=(10.5, 10.5), mask=np.zeros((20, 20)), ) assert isinstance(ai_mask, AzimuthalIntegrator) aff = [[1, 0, 0], [0, 1, 0], [0, 0, 1]] ai_affine = get_azimuthal_integrator( detector=dect, detector_distance=1, shape=(20, 20), center=(10.5, 10.5), mask=np.zeros((20, 20)), affine=aff, ) assert isinstance(ai_affine, AzimuthalIntegrator)
def test_1d_integrate_fast(self, radial_pattern): from pyxem.utils.pyfai_utils import get_azimuthal_integrator dect = Detector(pixel1=1e-4, pixel2=1e-4) ai = get_azimuthal_integrator(detector=dect, detector_distance=1, shape=np.shape(radial_pattern)) integration = azimuthal_integrate1d_fast( radial_pattern, ai, npt_rad=100, method="numpy", unit="2th_rad", correctSolidAngle=True, )
def to_ai(self, wavelength, **kwargs): sig_shape = np.shape(self.diffraction_pattern) unit = "k_A^-1" setup = _get_setup(wavelength, unit, self.diffraction_calibration) detector, dist, radial_range = setup ai = get_azimuthal_integrator( detector=detector, detector_distance=dist, shape=sig_shape, center=self.center, affine=self.affine_matrix, wavelength=wavelength, **kwargs, ) return ai
def azimuthal_integrate2d_slow( z, detector_distance, detector, npt_rad, npt_azim=360, wavelength=None, unit="2th_rad", center=None, mask=None, affine=None, method="splitpixel", correctSolidAngle=True, radial_range=None, azimuth_range=None, azimuthal_kwargs={}, integrate_kwargs={}, ): """Calculate the azimuthal integral in 2d around a determined origin. This method is used for signals where the origin is iterated, compared to azimuthal_integrate_fast which is used when the origin, mask and affine transformation in the data is constant. Parameters ---------- z : np.array() Two-dimensional data array containing the signal. origin : np.array() A size 2 numpy array containing the position of the origin. detector_distance : float Detector distance in meters passed to pyFAI AzimuthalIntegrator. detector : pyFAI.detectors.Detector object A pyFAI detector used for the AzimuthalIntegrator. wavelength : float The electron wavelength in meters. Used by pyFAI AzimuthalIntegrator. size_1d : int The size of the returned 1D signal. (i.e. number of pixels in the 1D azimuthal integral.) unit : str The unit for for PyFAI integrate1d. *args : Arguments to be passed to AzimuthalIntegrator. **kwargs : Keyword arguments to be passed to AzimuthalIntegrator. Returns ------- tth : np.array() One-dimensional scattering vector axis of z. I : np.array() One-dimensional azimuthal integral of z. """ shape = np.shape(z) ai = get_azimuthal_integrator(detector=detector, detector_distance=detector_distance, shape=shape, center=center, affine=affine, mask=mask, wavelength=wavelength, **azimuthal_kwargs) output = ai.integrate2d(z, npt_rad=npt_rad, npt_azim=npt_azim, method=method, unit=unit, correctSolidAngle=correctSolidAngle, azimuth_range=azimuth_range, radial_range=radial_range, **integrate_kwargs) return np.transpose(output[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