def test_crop_float_unit_convertion_signal2D(self): # Should convert the unit to nm d = np.arange(512 * 512).reshape(512, 512) s = Signal2D(d) s.axes_manager[0].name = "x" s.axes_manager[0].scale = 0.01 s.axes_manager[0].units = "µm" s.axes_manager[1].name = "y" s.axes_manager[1].scale = 0.01 s.axes_manager[1].units = "µm" s.crop(0, 0.0, 0.5, convert_units=True) # also convert the other axis s.crop(1, 0.0, 500.0, convert_units=True) np.testing.assert_almost_equal(s.axes_manager[0].scale, 10.0) np.testing.assert_almost_equal(s.axes_manager[1].scale, 10.0) assert s.axes_manager[0].units == "nm" assert s.axes_manager[1].units == "nm" np.testing.assert_allclose(s.data, d[:50, :50]) # Should keep the unit to µm d = np.arange(512 * 512).reshape(512, 512) s = Signal2D(d) s.axes_manager[0].name = "x" s.axes_manager[0].scale = 0.01 s.axes_manager[0].units = "µm" s.axes_manager[1].name = "y" s.axes_manager[1].scale = 0.01 s.axes_manager[1].units = "µm" s.crop(0, 0.0, 5.0, convert_units=True) s.crop(1, 0.0, 5.0, convert_units=True) np.testing.assert_almost_equal(s.axes_manager[0].scale, 0.01) np.testing.assert_almost_equal(s.axes_manager[1].scale, 0.01) assert s.axes_manager[0].units == "µm" assert s.axes_manager[1].units == "µm" np.testing.assert_allclose(s.data, d[:500, :500])
def __init__(self, *args, **kwargs): """Basic unit of data in the program. Spectrums can be any dimension of array but all of the data should be of the same type from the same area... (Maybe define this better later... You can use it kind of however you want though) Extends the Signal2D Class from hyperspy so there is that added functionality Parameters ---------- data : numpy array The signal data. It can be an array of any dimensions. axes : dictionary (optional) Dictionary to define the axes (see the documentation of the AxesManager class for more details). attributes : dictionary (optional) A dictionary whose items are stored as attributes. metadata : dictionary (optional) A dictionary containing a set of parameters that will to stores in the `metadata` attribute. Some parameters might be mandatory in some cases. original_metadata : dictionary (optional) A dictionary containing a set of parameters that will to stores in the `original_metadata` attribute. It typically contains all the parameters that has been imported from the original data file. Notes: For more parameters see hyperspy's Signal2D Class """ Signal2D.__init__(self, *args, **kwargs) self.manav = MaskSlicer(self, isNavigation=True) self.masig = MaskSlicer(self, isNavigation=False) self.mask_passer= None
def test_input_signal_and_original_image_wrong_dim(self): s = Signal2D(np.zeros((100, 50))) s_orig = Signal2D(np.zeros((100, 50, 9))) with pytest.raises(ValueError): Sublattice(atom_position_list=self.peaks, image=s, original_image=s_orig)
class TestCorrelations: @pytest.fixture def flat_pattern(self): pd = PolarDiffraction2D(data=np.ones(shape=(2, 2, 5, 5))) pd.axes_manager.signal_axes[0].scale = 0.5 pd.axes_manager.signal_axes[0].name = "theta" pd.axes_manager.signal_axes[1].scale = 2 pd.axes_manager.signal_axes[1].name = "k" return pd def test_correlation_signal(self, flat_pattern): ac = flat_pattern.get_angular_correlation() assert isinstance(ac, Correlation2D) def test_axes_transfer(self, flat_pattern): ac = flat_pattern.get_angular_correlation() assert (ac.axes_manager.signal_axes[0].scale == flat_pattern.axes_manager.signal_axes[0].scale) assert (ac.axes_manager.signal_axes[1].scale == flat_pattern.axes_manager.signal_axes[1].scale) assert (ac.axes_manager.signal_axes[1].name == flat_pattern.axes_manager.signal_axes[1].name) @pytest.mark.parametrize( "mask", [None, np.zeros(shape=(5, 5)), Signal2D(np.zeros(shape=(2, 2, 5, 5)))]) def test_masking_correlation(self, flat_pattern, mask): ap = flat_pattern.get_angular_correlation(mask=mask) assert isinstance(ap, Correlation2D) def test_correlation_inplace(self, flat_pattern): ac = flat_pattern.get_angular_correlation(inplace=True) assert ac is None assert isinstance(flat_pattern, Correlation2D) @pytest.mark.parametrize( "mask", [None, np.zeros(shape=(5, 5)), Signal2D(np.zeros(shape=(2, 2, 5, 5)))]) def test_masking_angular_power(self, flat_pattern, mask): ap = flat_pattern.get_angular_power(mask=mask) print(ap) assert isinstance(ap, Power2D) def test_axes_transfer_power(self, flat_pattern): ac = flat_pattern.get_angular_power() assert ac.axes_manager.signal_axes[0].scale == 1 assert (ac.axes_manager.signal_axes[1].scale == flat_pattern.axes_manager.signal_axes[1].scale) assert (ac.axes_manager.signal_axes[1].name == flat_pattern.axes_manager.signal_axes[1].name) def test_power_inplace(self, flat_pattern): ac = flat_pattern.get_angular_power(inplace=True) assert ac is None assert isinstance(flat_pattern, Power2D)
def test_copy_all_axes_manager_wrong_shape(self): s0 = Signal2D(np.zeros((5, 40, 50))) s1 = Signal2D(np.zeros((6, 40, 50))) s2 = Signal2D(np.zeros((2, 5, 40, 50))) with pytest.raises(ValueError): pst._copy_signal_all_axes_metadata(s0, s1) with pytest.raises(ValueError): pst._copy_signal_all_axes_metadata(s0, s2)
def array2signal2d(numpy_array, scale=1.0, rotate_flip=False): if rotate_flip: signal = Signal2D(np.rot90(np.fliplr(numpy_array))) else: signal = Signal2D(numpy_array) signal.axes_manager[-1].scale = scale signal.axes_manager[-2].scale = scale return signal
def __init__(self, *args, **kwargs): Signal2D.__init__(self, *args, **kwargs) # Set default attributes if 'Acquisition_instrument' in self.metadata.as_dictionary(): if 'SEM' in self.metadata.as_dictionary()['Acquisition_instrument']: self.metadata.set_item( "Acquisition_instrument.TEM", self.metadata.Acquisition_instrument.SEM) del self.metadata.Acquisition_instrument.SEM self.decomposition.__func__.__doc__ = BaseSignal.decomposition.__doc__
def test_wrong_dimensions(self): s1 = Signal1D(np.random.random(200)) s3 = Signal2D(np.random.random((4, 200, 200))) s4 = Signal2D(np.random.random((3, 4, 200, 200))) with pytest.raises(ValueError): afr.get_atom_positions(s1, 2) with pytest.raises(ValueError): afr.get_atom_positions(s3, 2) with pytest.raises(ValueError): afr.get_atom_positions(s4, 2)
def __init__(self, *args, **kwargs): Signal2D.__init__(self, *args, **kwargs) # Attributes defaults if 'Acquisition_instrument.TEM' not in self.metadata: if 'Acquisition_instrument.SEM' in self.metadata: self.metadata.set_item( "Acquisition_instrument.TEM", self.metadata.Acquisition_instrument.SEM) del self.metadata.Acquisition_instrument.SEM self.decomposition.__func__.__doc__ = BaseSignal.decomposition.__doc__
def __init__(self, *args, **kwargs): """ If a hyperspy Signal2D is given, it is transformed into a ModifiedImage. In that case, additional *args and **kwargs are discarded. """ if len(args) > 0 and isinstance(args[0], Image): # Pretend it is a hs signal, copy axes and metadata sdict = args[0]._to_dictionary() Image.__init__(self, **sdict) else: Image.__init__(self, *args, **kwargs)
def get_diffraction_variance(self, dqe, set_data_type=None): """Calculates the variance in scattered intensity as a function of scattering vector. Parameters ---------- dqe : float Detective quantum efficiency of the detector for Poisson noise correction. data_type : numpy data type. For numpy data types, see https://docs.scipy.org/doc/numpy-1.13.0/user/basics.types.html. This is incorporated as squaring the numbers in meansq_dp results in considerably larger than the ones in the original array. This can result in an overflow error that is difficult to distinguish. Hence the data can be converted to a different data type to accommodate. Returns ------- vardps : DiffractionVariance2D A DiffractionVariance2D object containing the mean DP, mean squared DP, and variance DP. """ dp = self.signal mean_dp = dp.mean((0, 1)) if set_data_type is None: meansq_dp = Signal2D(np.square(dp.data)).mean((0, 1)) else: meansq_dp = Signal2D(np.square( dp.data.astype(set_data_type))).mean((0, 1)) normvar = (meansq_dp.data / np.square(mean_dp.data)) - 1. var_dp = Signal2D(normvar) corr_var_array = var_dp.data - (np.divide(dqe, mean_dp.data)) corr_var_array[np.isinf(corr_var_array)] = 0 corr_var_array[np.isnan(corr_var_array)] = 0 corr_var = Signal2D(corr_var_array) vardps = stack((mean_dp, meansq_dp, var_dp, corr_var)) sig_x = vardps.data.shape[1] sig_y = vardps.data.shape[2] dv = DiffractionVariance2D(vardps.data.reshape((2, 2, sig_x, sig_y))) dv = transfer_signal_axes(dv, self.signal) return dv
def setup_method(self, method): # Create test image 100x100 pixels: im = Signal2D(np.arange(50000).reshape([10, 50, 100])) im.axes_manager[0].scale = 1e-1 im.axes_manager[1].scale = 1e-2 im.axes_manager[2].scale = 1e-3 self.im = im
def test_model2D_linear_many_gaussians(self, nav2d): mesh, x, y = self.mesh, self.x, self.y gausslow, gausshigh = -8, 8 gauss_step = 8 X, Y = mesh z = np.zeros(X.shape) g = Gaussian2D() for i in np.arange(gausslow, gausshigh + 1, gauss_step): for j in np.arange(gausslow, gausshigh + 1, gauss_step): g.centre_x.value = i g.centre_y.value = j g.A.value = 10 z += g.function(X, Y) s = Signal2D(z) s.axes_manager[-2].offset = x[0] s.axes_manager[-1].offset = y[0] s.axes_manager[-2].scale = x[1] - x[0] s.axes_manager[-1].scale = y[1] - y[0] if nav2d: s = hs.stack([s] * 2) s = hs.stack([s] * 3) m = s.create_model() for i in np.arange(gausslow, gausshigh + 1, gauss_step): for j in np.arange(gausslow, gausshigh + 1, gauss_step): g = Gaussian2D(centre_x=i, centre_y=j) g.set_parameters_not_free() g.A.free = True m.append(g) m.fit(optimizer='lstsq') np.testing.assert_allclose(s.data, m.as_signal().data)
def library(diffraction_pattern): dp = diffraction_pattern.mean((0, 1)) im = Signal2D(np.ones((10, 10))) cdl = CalibrationDataLibrary( au_x_grating_dp=dp, au_x_grating_im=im, moo3_dp=dp, moo3_im=im ) return cdl
def get_ncc_matrix(self): """Get the normalised correlation coefficient (NCC) matrix containing the NCC between each pair of segments. Returns ------- ncc_matrix : Signal2D Normalised correlation coefficient matrix for loadings and factors. """ # Set up empty matrices of correct size to store NCC values. num_comp = np.shape(self.loadings.data)[0] ncc_loadings = np.zeros((num_comp, num_comp)) ncc_factors = np.zeros((num_comp, num_comp)) factors = self.factors.map(np.nan_to_num, inplace=False).copy() loadings = self.loadings.map(np.nan_to_num, inplace=False).copy() # Iterate through loadings calculating NCC values. for i in np.arange(num_comp): ncc_loadings[i] = list( map( lambda x: norm_cross_corr(x, template=loadings.data[i]), loadings.data, )) # Iterate through factors calculating NCC values. for i in np.arange(num_comp): ncc_factors[i] = list( map(lambda x: norm_cross_corr(x, template=factors.data[i]), factors.data)) # Convert matrix to Signal2D and set axes ncc_sig = Signal2D(np.array((ncc_loadings, ncc_factors))) ncc_sig.axes_manager.signal_axes[0].name = "index" ncc_sig.axes_manager.signal_axes[1].name = "index" ncc_sig.metadata.General.title = "Normalised Correlation Coefficient" return ncc_sig
def get_ncc_matrix(self): """Get the normalised correlation coefficient (NCC) matrix containing the NCC between each pair of segments. Returns ------- ncc_matrix : Signal2D Normalised correlation coefficient matrix. """ # TODO: This code should be factored out for reuse in other ncc method. # Set up an empty matrix of correct size to store NCC values. num_comp = np.shape(self.segments.data)[0] ncc_matrix = np.zeros((num_comp, num_comp)) # Iterate through segments calculating NCC values. for i in np.arange(num_comp): ncc_matrix[i] = list( map( lambda x: norm_cross_corr(x, template=self.segments.data[i]), self.segments.data, )) # Convert matrix to Signal2D and set axes ncc_sig = Signal2D(ncc_matrix) ncc_sig.axes_manager.signal_axes[0].name = "segment index" ncc_sig.axes_manager.signal_axes[1].name = "segment index" ncc_sig.metadata.General.title = "Normalised Correlation Coefficient" return ncc_sig
def get_atomic_resolution_tem_signal2d(): """Get an artificial atomic resolution TEM Signal2D. Returns ------- :py:class:`~hyperspy._signals.signal2d.Signal2D` Example ------- >>> s = hs.datasets.artificial_data.get_atomic_resolution_tem_signal2d() >>> s.plot() """ from hyperspy.signals import Signal2D from hyperspy import components2d sX, sY = 2, 2 x_array, y_array = np.mgrid[0:200, 0:200] image = np.zeros_like(x_array, dtype=np.float32) gaussian2d = components2d.Gaussian2D(sigma_x=sX, sigma_y=sY) for x in range(10, 195, 20): for y in range(10, 195, 20): gaussian2d.centre_x.value = x gaussian2d.centre_y.value = y image += gaussian2d.function(x_array, y_array) s = Signal2D(image) return s
def test_0d(self): data_shape = (10, 8) data = np.ones(data_shape) * 100.0 s = Signal2D(data) mask0 = pst._get_angle_sector_mask(s, angle0=0.0, angle1=np.pi / 2) np.testing.assert_array_equal(mask0, np.zeros_like(mask0, dtype=np.bool)) assert mask0.shape == data_shape s.axes_manager.signal_axes[0].offset = -5 s.axes_manager.signal_axes[1].offset = -5 mask1 = pst._get_angle_sector_mask(s, angle0=0.0, angle1=np.pi / 2) assert mask1[:5, :5].all() mask1[:5, :5] = False np.testing.assert_array_equal(mask1, np.zeros_like(mask1, dtype=np.bool)) s.axes_manager.signal_axes[0].offset = -15 s.axes_manager.signal_axes[1].offset = -15 mask2 = pst._get_angle_sector_mask(s, angle0=0.0, angle1=np.pi / 2) assert mask2.all() s.axes_manager.signal_axes[0].offset = -15 s.axes_manager.signal_axes[1].offset = -15 mask3 = pst._get_angle_sector_mask(s, angle0=np.pi * 3 / 2, angle1=np.pi * 2) assert not mask3.any()
def test_simple(self): s = Signal2D(np.zeros((110, 200))) x, y, semi_len0, semi_len1, rotation = 60, 70, 12, 9, 0.2 xx, yy = np.meshgrid(s.axes_manager[0].axis, s.axes_manager[1].axis) ellipse_image = mdtd._get_elliptical_ring(xx, yy, x, y, semi_len0, semi_len1, rotation, 3) assert ellipse_image.any()
def plot(self, fig=None): """Plots the current marker in a flat image Parameters ---------- fig : {Image, None} if an already plotted image, then updates. Otherwise creates a new one. Returns ------- fig: Image the resulting image. If passed again, will be updated (computationally cheaper operation). """ marker = self.samf.metadata.marker.copy() if marker.ndim > 2: marker = np.sum( marker, tuple([i for i in range(0, marker.ndim - 2)])) elif marker.ndim < 2: marker = np.atleast_2d(marker) from hyperspy.signals import Signal2D if not isinstance( fig, Signal2D) or fig._plot.signal_plot.figure is None: fig = Signal2D(marker) fig.plot() self.close_plot = fig._plot.signal_plot.close else: fig.data = marker fig._plot.signal_plot.update() return fig
def test_snapping_axis_values(snap): s = Signal2D(np.arange(100).reshape(10, 10)) s.axes_manager[0].offset = 5 r = roi.Line2DROI(x1=6, y1=0, x2=12, y2=4, linewidth=0) s.plot() _ = r.interactive(s, snap=snap)
def test_error_message(): im = Signal2D(np.arange(50000).reshape([10, 50, 100])) im.plot() im._plot.close() p = roi.Point1DROI(0.5) with pytest.raises(Exception, match='does not have an active plot.'): p.add_widget(signal=im, axes=[0, ], color="cyan")
def test_cover_no_signal(self): s = Signal2D(np.zeros((50, 56))) xx, yy = np.meshgrid(s.axes_manager[0].axis, s.axes_manager[1].axis) x, y, semi_len0, semi_len1, rotation = 523, 620, 20, 30, 2.0 ellipse_image = mdtd._get_elliptical_disk(xx, yy, x, y, semi_len0, semi_len1, rotation) assert not ellipse_image.any()
def test_simple(self): s = Signal2D(np.zeros((110, 200))) xx, yy = np.meshgrid(s.axes_manager[0].axis, s.axes_manager[1].axis) x, y, semi_len0, semi_len1, rotation = 60, 70, 12, 9, 0.2 ellipse_image = mdtd._get_elliptical_disk(xx, yy, x, y, semi_len0, semi_len1, rotation) assert s.data.shape == ellipse_image.shape
def get_direct_beam_mask(self, radius, center=None): """Generate a signal mask for the direct beam. Parameters ---------- radius : float Radius for the circular mask in pixel units. center : tuple, optional User specified (x, y) position of the diffraction pattern center. i.e. the direct beam position. If None (default) it is assumed that the direct beam is at the center of the diffraction pattern. Return ------ signal-mask : ndarray The mask of the direct beam """ shape = self.axes_manager.signal_shape if center is None: center = (shape[1] - 1) / 2, (shape[0] - 1) / 2 signal_mask = Signal2D( circular_mask(shape=shape, radius=radius, center=center)) return signal_mask
def test_get_one_string(self): s = Signal2D(np.zeros([3, 2, 2])) m = markers.text(x=list(range(3)), y=list(range(3)), text='one') m.axes_manager = s.axes_manager assert m.get_data_position('text') == 'one' s.axes_manager[0].index = 2 assert m.get_data_position('text') == 'one'
def setup_method(self, method): rng = np.random.RandomState(123) self.im = Signal2D(rng.random_sample(size=(2, 3, 4, 5))) self.im.axes_manager.signal_axes[0].units = "nm" self.im.axes_manager.signal_axes[1].units = "nm" self.im.axes_manager.signal_axes[0].scale = 10.0 self.im.axes_manager.signal_axes[1].scale = 10.0
def _test_plot_rectange_markers(): # Create test image 100x100 pixels: im = Signal2D(np.arange(100).reshape([10, 10])) # Add four line markers: m1 = markers.line_segment( x1=2, y1=2, x2=7, y2=2, color='red', linewidth=3) m2 = markers.line_segment( x1=2, y1=2, x2=2, y2=7, color='red', linewidth=3) m3 = markers.line_segment( x1=2, y1=7, x2=7, y2=7, color='red', linewidth=3) m4 = markers.line_segment( x1=7, y1=2, x2=7, y2=7, color='red', linewidth=3) # Add rectangle marker at same position: m = markers.rectangle(x1=2, x2=7, y1=2, y2=7, linewidth=4, color='blue', ls='dotted') # Plot image and add markers to img: im.plot() im.add_marker(m) im.add_marker(m1) im.add_marker(m2) im.add_marker(m3) im.add_marker(m4) return im
def test_changing_scale_offset(self): s = Signal2D(arange(100).reshape(10, 10)) signal_axis0 = s.axes_manager.signal_axes[0] signal_axis1 = s.axes_manager.signal_axes[1] signal_extent = ( signal_axis0.low_value, signal_axis0.high_value, signal_axis1.low_value, signal_axis1.high_value, ) assert signal_extent == s.axes_manager.signal_extent signal_axis0.scale = 0.2 signal_axis1.scale = 0.7 signal_extent = ( signal_axis0.low_value, signal_axis0.high_value, signal_axis1.low_value, signal_axis1.high_value, ) assert signal_extent == s.axes_manager.signal_extent signal_axis0.offset = -11 signal_axis1.scale = 23 signal_extent = ( signal_axis0.low_value, signal_axis0.high_value, signal_axis1.low_value, signal_axis1.high_value, ) assert signal_extent == s.axes_manager.signal_extent
def get_map(self, k_region=[3.0, 6.0], symmetry=None): """Creates a 2 dimensional map of from the power spectrum. Parameters ---------- k_region: array-like upper and lower k values to integrate over, allows both ints and floats for indexing symmetry: int or array-like specific integers or list of symmetries to average over when creating the map of the correlations. Returns ---------- symmetry_map: 2-d array 2 dimensional map of from the power spectrum """ if symmetry is None: sym_map = self.isig[:, k_region[0]:k_region[1]].sum( axis=[-1, -2]).transpose() elif isinstance(symmetry, int): sym_map = self.isig[symmetry, k_region[0]:k_region[1]].sum( axis=[-1]).transpose() else: sym_map = Signal2D( data=np.zeros(self.axes_manager.navigation_shape)) for sym in symmetry: sym_map = self.isig[sym, k_region[0]:k_region[1]].sum( axis=[-1]).transpose() + sym_map return sym_map