def setup_method(self): image_data = np.random.random(size=(100, 100)) position_list = [] for x in range(10, 100, 5): for y in range(10, 100, 5): position_list.append([x, y]) sublattice = Sublattice(np.array(position_list), image_data) sublattice.find_nearest_neighbors() self.sublattice = sublattice
def setup_method(self): image_data = np.arange(10000).reshape(100, 100) peaks0 = np.arange(20).reshape(10, 2) peaks1 = np.arange(26).reshape(13, 2) sublattice0 = Sublattice(atom_position_list=peaks0, image=image_data) sublattice1 = Sublattice(atom_position_list=peaks1, image=image_data) self.atom_lattice = al.Atom_Lattice() self.atom_lattice.sublattice_list.extend([sublattice0, sublattice1]) self.atom_lattice.image0 = image_data self.tmpdir = tempfile.TemporaryDirectory()
def test_toggle_one(self): atom_position_list = [[10, 10], [10, 20]] sublattice = Sublattice(atom_position_list, np.zeros((30, 30))) sublattice.toggle_atom_refine_position_with_gui() fig = plt.figure(1) x, y = fig.axes[0].transData.transform((10, 20)) assert sublattice.atom_list[1].refine_position fig.canvas.button_press_event(x, y, 1) assert not sublattice.atom_list[1].refine_position fig.canvas.button_press_event(x, y, 1) assert sublattice.atom_list[1].refine_position
def setup_method(self): self.atoms_N = 10 image_data = np.arange(10000).reshape(100, 100) peaks = np.arange(20).reshape(self.atoms_N, 2) sublattice = Sublattice(peaks, image_data) sublattice.original_image = image_data for atom in sublattice.atom_list: atom.sigma_x = 2. atom.sigma_y = 2. atom.amplitude_gaussian = 10. atom.amplitude_max_intensity = 10. self.sublattice = sublattice
def test_find_b_cation_atoms(self): a_sublattice = Sublattice( self.peaks, np.rot90(np.fliplr(self.s_adf_modified.data))) a_sublattice.pixel_size = self.pixel_size afr.construct_zone_axes_from_sublattice(a_sublattice) zone_vector_100 = a_sublattice.zones_axis_average_distances[1] b_atom_list = a_sublattice.find_missing_atoms_from_zone_vector( zone_vector_100) b_sublattice = Sublattice( b_atom_list, np.rot90( np.fliplr(self.s_adf_modified.data))) assert len(b_sublattice.atom_list) == 221
def test_save_load_atom_lattice_atom_values(self): image_data = np.arange(10000).reshape(100, 100) atom0_pos = np.random.random(size=(30, 2)) * 10 atom0_sigma_x = np.random.random(size=30) atom0_sigma_y = np.random.random(size=30) atom0_rot = np.random.random(size=30) atom1_pos = np.random.random(size=(30, 2)) * 10 atom1_sigma_x = np.random.random(size=30) atom1_sigma_y = np.random.random(size=30) atom1_rot = np.random.random(size=30) sublattice0 = Sublattice(atom_position_list=atom0_pos, image=image_data) sublattice1 = Sublattice(atom_position_list=atom1_pos, image=image_data) for i, atom in enumerate(sublattice0.atom_list): atom.sigma_x = atom0_sigma_x[i] atom.sigma_y = atom0_sigma_y[i] atom.rotation = atom0_rot[i] for i, atom in enumerate(sublattice1.atom_list): atom.sigma_x = atom1_sigma_x[i] atom.sigma_y = atom1_sigma_y[i] atom.rotation = atom1_rot[i] atom_lattice = al.Atom_Lattice() atom_lattice.sublattice_list.extend([sublattice0, sublattice1]) atom_lattice.image0 = image_data save_path = pjoin(self.tmpdir.name, "atomic_lattice.hdf5") atom_lattice.save(filename=save_path, overwrite=True) atom_lattice_load = load_atom_lattice_from_hdf5( save_path, construct_zone_axes=False) sl0 = atom_lattice_load.sublattice_list[0] sl1 = atom_lattice_load.sublattice_list[1] assert (sl0.x_position == atom0_pos[:, 0]).all() assert (sl0.y_position == atom0_pos[:, 1]).all() assert (sl1.x_position == atom1_pos[:, 0]).all() assert (sl1.y_position == atom1_pos[:, 1]).all() assert (sl0.sigma_x == atom0_sigma_x).all() assert (sl0.sigma_y == atom0_sigma_y).all() assert (sl1.sigma_x == atom1_sigma_x).all() assert (sl1.sigma_y == atom1_sigma_y).all() assert (sl0.rotation == atom0_rot).all() assert (sl1.rotation == atom1_rot).all()
def sublattice(self): atom_list = [] for atom in self.__sublattice.atom_list: new_atom = Atom_Position(x=atom.pixel_x, y=atom.pixel_y, sigma_x=atom.sigma_x, sigma_y=atom.sigma_y, rotation=atom.rotation, amplitude=atom.amplitude_gaussian) atom_list.append(new_atom) if self._sublattice_generate_image: image = self.signal.data else: image = np.zeros(self.data_extent[::-1]) sublattice = Sublattice([], image) sublattice.atom_list = atom_list return sublattice
def test_manual_processing(self): s_adf_filename = os.path.join( my_path, "datasets", "test_ADF_cropped.hdf5") s = load(s_adf_filename) s.change_dtype('float32') atom_positions = afr.get_atom_positions( signal=s, separation=17, threshold_rel=0.02, ) sublattice = Sublattice( atom_position_list=atom_positions, image=s.data) sublattice.find_nearest_neighbors() sublattice.refine_atom_positions_using_center_of_mass( sublattice.image, percent_to_nn=0.4) sublattice.refine_atom_positions_using_2d_gaussian( sublattice.image, percent_to_nn=0.4) Atom_Lattice(image=s.data, sublattice_list=[sublattice]) sublattice.construct_zone_axes()
def make_atom_lattice_dumbbell_structure( s, dumbbell_positions, dumbbell_vector, show_progressbar=True): """Make Atom_Lattice object from image of dumbbell structure. Parameters ---------- s : HyperSpy 2D signal dumbbell_positions : list of atomic positions In the form [[x0, y0], [x1, y1], [x2, y2], ...]. There should only be one position per dumbbell. dumbbell_vector : tuple show_progressbar : bool, default True Returns ------- dumbbell_lattice: Atomap Dumbbell_Lattice object Examples -------- >>> import atomap.initial_position_finding as ipf >>> s = am.dummy_data.get_dumbbell_signal() >>> dumbbell_positions = am.get_atom_positions(s, separation=16) >>> atom_positions = am.get_atom_positions(s, separation=4) >>> dumbbell_vector = ipf.find_dumbbell_vector(atom_positions) >>> dumbbell_lattice = ipf.make_atom_lattice_dumbbell_structure( ... s, dumbbell_positions, dumbbell_vector) """ dumbbell_list0, dumbbell_list1 = _get_dumbbell_arrays( s, dumbbell_positions, dumbbell_vector, show_progressbar=show_progressbar) s_modified = do_pca_on_signal(s) sublattice0 = Sublattice( atom_position_list=dumbbell_list0, original_image=s.data, image=s_modified.data, color='blue') sublattice1 = Sublattice( atom_position_list=dumbbell_list1, original_image=s.data, image=s_modified.data, color='red') sublattice0.find_nearest_neighbors() sublattice1.find_nearest_neighbors() atom_lattice = Dumbbell_Lattice( image=sublattice0.image, original_image=s.data, name="Dumbbell structure", sublattice_list=[sublattice0, sublattice1]) return(atom_lattice)
def setup_method(self): self.tdata = tt.MakeTestData(200, 200) for i in range(4): x, y = np.mgrid[60 * i:(i + 1) * 60:15, 10:200:15] x, y = x.flatten(), y.flatten() self.tdata.add_atom_list(x, y, sigma_x=2, sigma_y=2, amplitude=(i + 1) * 20, rotation=0.4) self.tdata.add_image_noise(sigma=0.02) atom_positions = atom_finding.get_atom_positions(self.tdata.signal, 8, threshold_rel=0.1) self.sublattice = Sublattice(atom_positions, self.tdata.signal.data) self.sublattice.construct_zone_axes() self.sublattice.refine_atom_positions_using_2d_gaussian( self.sublattice.image)
def test_load_simple(self): image_data = np.arange(10000).reshape(100, 100) peaks = np.arange(20).reshape(10, 2) sublattice = Sublattice(atom_position_list=peaks, image=image_data) dumbbell_lattice = al.Dumbbell_Lattice( image=image_data, sublattice_list=[sublattice, sublattice]) save_path = pjoin(self.tmpdir.name, "test_dumbbell_lattice_save.hdf5") dumbbell_lattice.save(filename=save_path, overwrite=True) dumbbell_lattice_load = load_atom_lattice_from_hdf5( save_path, construct_zone_axes=False) dl0_qualname = dumbbell_lattice.__class__.__qualname__ dl1_qualname = dumbbell_lattice_load.__class__.__qualname__ assert dl0_qualname == 'Dumbbell_Lattice' assert dl0_qualname == dl1_qualname
def statistical_quant(image, sublattice, model, num_atoms, plot=True): """Use the statistical quantification technique to estimate the number of atoms within each atomic column in an ADF-STEM image. Reference: Van Aert et al. Phys Rev B 87, (2013). Parameters ---------- image : Hyperspy Signal object or array-like sublattice : Sublattice object model : GaussianMixture model object num_atoms : int Number of atoms in longest atomic column as determined using the plot_statistical_quant_criteria() function. plot : bool, default True Returns ------- atom_lattice : Atomap Atom_Lattice Each sublattice contains columns of the same number of atoms. Example ------- >>> import numpy as np >>> import atomap.api as am >>> s = am.dummy_data.get_atom_counting_signal() >>> atom_positions = am.get_atom_positions(s, 8, threshold_rel=0.1) >>> sublattice = am.Sublattice(atom_positions, s) >>> sublattice.construct_zone_axes() >>> sublattice.refine_atom_positions_using_2d_gaussian() >>> models = am.quant.get_statistical_quant_criteria([sublattice], 10) >>> sub_lattices = am.quant.statistical_quant(s, sublattice, ... models[3], 4, plot=False) """ # Get array of intensities of Gaussians of each atom intensities = [2*np.pi*atom.amplitude_gaussian*atom.sigma_x*atom.sigma_y for atom in sublattice.atom_list] int_array = np.asarray(intensities) int_array = int_array.reshape(-1, 1) # model = mixture.GaussianMixture(num_atoms,covariance_type='tied'). # fit(int_array) sort_indices = model.means_.argsort(axis=0) labels = model.predict(int_array) dic = {} for i in range(num_atoms): dic[int(sort_indices[i])] = i sorted_labels = np.copy(labels) for k, v in dic.items(): sorted_labels[labels == k] = v from matplotlib import cm x = np.linspace(0.0, 1.0, num_atoms) rgb = cm.get_cmap('viridis')(x)[np.newaxis, :, :3].tolist() sub_lattices = {} sublattice_list = [] atom_positions = sublattice.atom_positions for num in sort_indices.ravel(): sub_lattices[num] = Sublattice( atom_positions[np.where(sorted_labels == num)], image=np.array(image.data), color=rgb[0][num]) for i in range(num_atoms): sublattice_list.append(sub_lattices[i]) atom_lattice = Atom_Lattice(image=np.array(image.data), name='quant', sublattice_list=sublattice_list) if plot: atom_lattice.plot() _plot_fitted_hist(int_array, model, rgb, sort_indices) return(atom_lattice)
class MakeTestData(object): def __init__(self, image_x, image_y, sublattice_generate_image=True): """ Class for generating test datasets of atomic resolution STEM images. Parameters ---------- image_x, image_y : int Size of the image data. sublattice_generate_image : bool, default True When generating sublattices, a raster image is generated to complement the atom position objects (found in sublattice.image). For large amounts of atom positions, this can take a very long time. If sublattice_generate_image is False, this image will not be generated. Useful for generating sublattice objects for testing quicker, when only the atom positions themselves are needed. Attributes ---------- signal : HyperSpy 2D Signal sublattice : Atomap Sublattice atom_lattice : Atomap Atom_Lattice gaussian_list : list of 2D Gaussians objects Examples -------- >>> from atomap.testing_tools import MakeTestData >>> test_data = MakeTestData(200, 200) >>> test_data.add_atom(x=10, y=20) >>> test_data.signal.plot() Adding many atoms >>> test_data = MakeTestData(200, 200) >>> import numpy as np >>> x, y = np.mgrid[0:200:10j, 0:200:10j] >>> x, y = x.flatten(), y.flatten() >>> test_data.add_atom_list(x, y) >>> test_data.signal.plot() Adding many atoms with different parameters >>> test_data = MakeTestData(200, 200) >>> x, y = np.mgrid[0:200:10j, 0:200:10j] >>> x, y = x.flatten(), y.flatten() >>> sx, sy = np.random.random(len(x)), np.random.random(len(x)) >>> A, r = np.random.random(len(x))*10, np.random.random(len(x))*3.14 >>> test_data.add_atom_list(x, y, sigma_x=sx, sigma_y=sy, ... amplitude=A, rotation=r) >>> test_data.signal.plot() The class also generates a sublattice object >>> test_data = MakeTestData(200, 200) >>> import numpy as np >>> x, y = np.mgrid[0:200:10j, 0:200:10j] >>> x, y = x.flatten(), y.flatten() >>> test_data.add_atom_list(x, y) >>> test_data.sublattice.plot() Also Atom_Lattice objects >>> atom_lattice = test_data.atom_lattice >>> atom_lattice.plot() Generating a sublattice with 22500 atoms quickly, by not generating the image >>> test_data = MakeTestData(200, 200, sublattice_generate_image=False) >>> import numpy as np >>> x, y = np.mgrid[0:1000:150j, 0:1000:150j] >>> x, y = x.flatten(), y.flatten() >>> test_data.add_atom_list(x, y) >>> sublattice = test_data.sublattice """ self.data_extent = (image_x, image_y) self._image_noise = False self._sublattice_generate_image = sublattice_generate_image self.__sublattice = Sublattice([], np.zeros((2, 2))) self.__sublattice.atom_list = [] @property def signal(self): signal = self.__sublattice.get_model_image( image_shape=self.data_extent, show_progressbar=False) if self._image_noise is not False: signal.data += self._image_noise return signal @property def gaussian_list(self): gaussian_list = [] for atom in self.__sublattice.atom_list: gaussian_list.append(atom.as_gaussian()) return gaussian_list @property def sublattice(self): atom_list = [] for atom in self.__sublattice.atom_list: new_atom = Atom_Position(x=atom.pixel_x, y=atom.pixel_y, sigma_x=atom.sigma_x, sigma_y=atom.sigma_y, rotation=atom.rotation, amplitude=atom.amplitude_gaussian) atom_list.append(new_atom) if self._sublattice_generate_image: image = self.signal.data else: image = np.zeros(self.data_extent[::-1]) sublattice = Sublattice([], image) sublattice.atom_list = atom_list return sublattice @property def atom_lattice(self): sublattice = self.sublattice atom_lattice = Atom_Lattice(image=sublattice.image, sublattice_list=[sublattice]) return atom_lattice def add_atom(self, x, y, sigma_x=1, sigma_y=1, amplitude=1, rotation=0): """ Add a single atom to the test data. Parameters ---------- x, y : numbers Position of the atom. sigma_x, sigma_y : numbers, default 1 amplitude : number, default 1 rotation : number, default 0 Examples -------- >>> from atomap.testing_tools import MakeTestData >>> test_data = MakeTestData(200, 200) >>> test_data.add_atom(x=10, y=20) >>> test_data.signal.plot() """ atom = Atom_Position(x=x, y=y, sigma_x=sigma_x, sigma_y=sigma_y, rotation=rotation, amplitude=amplitude) self.__sublattice.atom_list.append(atom) def add_atom_list(self, x, y, sigma_x=1, sigma_y=1, amplitude=1, rotation=0): """ Add several atoms to the test data. Parameters ---------- x, y : iterable Position of the atoms. Must be iterable, and have the same size. sigma_x, sigma_y : number or iterable, default 1 If number: all the atoms will have the same sigma. Use iterable for setting different sigmas for different atoms. If iterable: must be same length as x and y iterables. amplitude : number or iterable, default 1 If number: all the atoms will have the same amplitude. Use iterable for setting different amplitude for different atoms. If iterable: must be same length as x and y iterables. rotation : number or iterable, default 0 If number: all the atoms will have the same rotation. Use iterable for setting different rotation for different atoms. If iterable: must be same length as x and y iterables. Examples -------- >>> from atomap.testing_tools import MakeTestData >>> test_data = MakeTestData(200, 200) >>> import numpy as np >>> x, y = np.mgrid[0:200:10j, 0:200:10j] >>> x, y = x.flatten(), y.flatten() >>> test_data.add_atom_list(x, y) >>> test_data.signal.plot() """ if len(x) != len(y): raise ValueError("x and y needs to have the same length") if isiterable(sigma_x): if len(sigma_x) != len(x): raise ValueError("sigma_x and x needs to have the same length") else: sigma_x = [sigma_x] * len(x) if isiterable(sigma_y): if len(sigma_y) != len(y): raise ValueError("sigma_y and x needs to have the same length") else: sigma_y = [sigma_y] * len(x) if isiterable(amplitude): if len(amplitude) != len(x): raise ValueError( "amplitude and x needs to have the same length") else: amplitude = [amplitude] * len(x) if isiterable(rotation): if len(rotation) != len(x): raise ValueError( "rotation and x needs to have the same length") else: rotation = [rotation] * len(x) iterator = zip(x, y, sigma_x, sigma_y, amplitude, rotation) for tx, ty, tsigma_x, tsigma_y, tamplitude, trotation in iterator: self.add_atom(tx, ty, tsigma_x, tsigma_y, tamplitude, trotation) def add_image_noise(self, mu=0, sigma=0.005, only_positive=False, random_seed=None): """ Add white noise to the image signal. The noise component is Gaussian distributed, with a default expectation value at 0, and a sigma of 0.005. If only_positive is set to True, the absolute value of the noise is added to the signal. This can be useful for avoiding negative values in the image signal. Parameters ---------- mu : int, float The expectation value of the Gaussian distribution, default is 0 sigma : int, float The standard deviation of the Gaussian distribution, default is 0.005. only_positive : bool Default is False. If True, the absolute value of the noise is added to the image signal. random_seed : int, optional Set the random seed of the noise, which gives the same image noise each time. Useful for testing and comparing images. Example ------- >>> from atomap.testing_tools import MakeTestData >>> test_data = MakeTestData(300, 300) >>> import numpy as np >>> x, y = np.mgrid[10:290:15j, 10:290:15j] >>> test_data.add_atom_list(x.flatten(), y.flatten(), sigma_x=3, ... sigma_y=3) >>> test_data.add_image_noise() >>> test_data.signal.plot() Using a specific random seed >>> test_data.add_image_noise(random_seed=0) """ if random_seed is not None: np.random.seed(random_seed) shape = self.signal.axes_manager.shape noise = normal(mu, sigma, shape) if only_positive: self._image_noise = np.absolute(noise) else: self._image_noise = noise
class TestStatisticalQuant: def setup_method(self): self.tdata = tt.MakeTestData(200, 200) for i in range(4): x, y = np.mgrid[60 * i:(i + 1) * 60:15, 10:200:15] x, y = x.flatten(), y.flatten() self.tdata.add_atom_list(x, y, sigma_x=2, sigma_y=2, amplitude=(i + 1) * 20, rotation=0.4) self.tdata.add_image_noise(sigma=0.02) atom_positions = atom_finding.get_atom_positions(self.tdata.signal, 8, threshold_rel=0.1) self.sublattice = Sublattice(atom_positions, self.tdata.signal.data) self.sublattice.construct_zone_axes() self.sublattice.refine_atom_positions_using_2d_gaussian( self.sublattice.image) def test_quant_criteria(self): quant.get_statistical_quant_criteria([self.sublattice], 10) def test_plot_fitted_hist(self): models = quant.get_statistical_quant_criteria([self.sublattice], 10) model = models[3] intensities = [ 2 * np.pi * atom.amplitude_gaussian * atom.sigma_x * atom.sigma_y for atom in self.sublattice.atom_list ] int_array = np.asarray(intensities) int_array = int_array.reshape(-1, 1) sort_indices = model.means_.argsort(axis=0) labels = model.predict(int_array) dic = {} for i in range(4): dic[int(sort_indices[i])] = i sorted_labels = np.copy(labels) for k, v in dic.items(): sorted_labels[labels == k] = v from matplotlib import cm x = np.linspace(0.0, 1.0, 4) rgb = cm.get_cmap('viridis')(x)[np.newaxis, :, :3].tolist() quant._plot_fitted_hist(int_array, model, rgb, sort_indices) def test_statistical_method(self): models = quant.get_statistical_quant_criteria([self.sublattice], 10) atom_lattice = quant.statistical_quant(self.tdata.signal, self.sublattice, models[3], 4, plot=False) assert len(atom_lattice.sublattice_list[0].atom_list) == 39 assert len(atom_lattice.sublattice_list[1].atom_list) == 52 assert len(atom_lattice.sublattice_list[2].atom_list) == 52 assert len(atom_lattice.sublattice_list[3].atom_list) == 13
def load_atom_lattice_from_hdf5(filename, construct_zone_axes=True): """ Load an Atomap HDF5-file, restoring a saved Atom_Lattice. Parameters ---------- filename : string Filename of the HDF5-file. construct_zone_axes : bool If True, find relations between atomic positions by constructing atomic planes. Default True. Returns ------- Atomap Atom_Lattice object """ h5f = h5py.File(filename, 'r') atom_lattice = Atom_Lattice() sublattice_list = [] sublattice_index_list = [] for group_name in h5f: if ('atom_lattice' in group_name) or ('sublattice' in group_name): sublattice_set = h5f[group_name] modified_image_data = sublattice_set['modified_image_data'][:] original_image_data = sublattice_set['original_image_data'][:] atom_position_array = sublattice_set['atom_positions'][:] if 'sublattice_index' in sublattice_set.attrs.keys(): sublattice_index_list.append( sublattice_set.attrs['sublattice_index']) sublattice = Sublattice( atom_position_array, modified_image_data) sublattice.original_image = original_image_data if 'sigma_x' in sublattice_set.keys(): sigma_x_array = sublattice_set['sigma_x'][:] for atom, sigma_x in zip( sublattice.atom_list, sigma_x_array): atom.sigma_x = sigma_x if 'sigma_y' in sublattice_set.keys(): sigma_y_array = sublattice_set['sigma_y'][:] for atom, sigma_y in zip( sublattice.atom_list, sigma_y_array): atom.sigma_y = sigma_y if 'rotation' in sublattice_set.keys(): rotation_array = sublattice_set['rotation'][:] for atom, rotation in zip( sublattice.atom_list, rotation_array): atom.rotation = rotation #### if 'amplitude_max_intensity' in sublattice_set.keys(): amplitude_max_intensity_array = sublattice_set['amplitude_max_intensity'][:] for atom, amplitude_max_intensity in zip( sublattice.atom_list, amplitude_max_intensity_array): atom.amplitude_max_intensity = amplitude_max_intensity if 'amplitude_mean_intensity' in sublattice_set.keys(): amplitude_mean_intensity_array = sublattice_set['amplitude_mean_intensity'][:] for atom, amplitude_mean_intensity in zip( sublattice.atom_list, amplitude_mean_intensity_array): atom.amplitude_mean_intensity = amplitude_mean_intensity if 'amplitude_min_intensity' in sublattice_set.keys(): amplitude_min_intensity_array = sublattice_set['amplitude_min_intensity'][:] for atom, amplitude_min_intensity in zip( sublattice.atom_list, amplitude_min_intensity_array): atom.amplitude_min_intensity = amplitude_min_intensity if 'amplitude_total_intensity' in sublattice_set.keys(): amplitude_total_intensity_array = sublattice_set['amplitude_total_intensity'][:] for atom, amplitude_total_intensity in zip( sublattice.atom_list, amplitude_total_intensity_array): atom.amplitude_total_intensity = amplitude_total_intensity if 'elements' in sublattice_set.keys(): elements_array = sublattice_set['elements'][:] for atom, elements in zip( sublattice.atom_list, elements_array): atom.elements = elements if 'z_height' in sublattice_set.keys(): z_height_array = sublattice_set['z_height'][:] #z_height_array_2 = [] # first loop needed because i can't eval() the z_height itself, don't really know why #for i in range(0, len(z_height_array)): # z_h = ast.literal_eval(z_height_array[i]) # z_height_array_2.append(z_h) for atom, z_height in zip( sublattice.atom_list, z_height_array): atom.z_height = z_height #### sublattice.pixel_size = sublattice_set.attrs['pixel_size'] if 'tag' in sublattice_set.attrs.keys(): sublattice.name = sublattice_set.attrs['tag'] elif 'name' in sublattice_set.attrs.keys(): sublattice.name = sublattice_set.attrs['name'] else: sublattice.name = '' if type(sublattice.name) == bytes: sublattice.name = sublattice.name.decode() sublattice._plot_color = sublattice_set.attrs['plot_color'] if type(sublattice._plot_color) == bytes: sublattice._plot_color = sublattice._plot_color.decode() if 'pixel_separation' in sublattice_set.attrs.keys(): sublattice._pixel_separation = sublattice_set.attrs[ 'pixel_separation'] else: sublattice._pixel_separation = 0.0 if construct_zone_axes: construct_zone_axes_from_sublattice(sublattice) if 'zone_axis_names_byte' in sublattice_set.keys(): zone_axis_list_byte = sublattice_set.attrs[ 'zone_axis_names_byte'] zone_axis_list = [] for zone_axis_name_byte in zone_axis_list_byte: zone_axis_list.append(zone_axis_name_byte.decode()) sublattice.zones_axis_average_distances_names = zone_axis_list sublattice_list.append(sublattice) if group_name == 'image_data0': atom_lattice.image0 = h5f[group_name][:] atom_lattice.image = atom_lattice.image0 if group_name == 'image_data1': atom_lattice.image1 = h5f[group_name][:] sorted_sublattice_list = [] if not sublattice_index_list: # Support for older hdf5 files sublattice_index_list = range(len(sublattice_list)) for sublattice_index in sublattice_index_list: sorted_sublattice_list.append(sublattice_list[sublattice_index]) atom_lattice.sublattice_list.extend(sorted_sublattice_list) if 'name' in h5f.attrs.keys(): atom_lattice.name = h5f.attrs['name'] elif 'path_name' in h5f.attrs.keys(): atom_lattice.name = h5f.attrs['path_name'] if 'pixel_separation' in h5f.attrs.keys(): atom_lattice._pixel_separation = h5f.attrs['pixel_separation'] else: atom_lattice._pixel_separation = 0.8/sublattice.pixel_size if type(atom_lattice.name) == bytes: atom_lattice.name = atom_lattice.name.decode() h5f.close() return(atom_lattice)
def make_atom_lattice_from_image(s_image0, process_parameter=None, pixel_separation=None, s_image1=None, debug_plot=False): if s_image0.data.dtype == 'float16': raise ValueError( "s_image0 has the dtype float16, which is not supported. " "Convert it to something else, for example using " "s_image0.change_dtype('float64')") image0_filename = _get_signal_name(s_image0) name = image0_filename s_image0 = s_image0.deepcopy() s_image0_modified = run_image_filtering(s_image0) if process_parameter is None: process_parameter = pp.GenericStructure() image0_scale = s_image0.axes_manager[0].scale if pixel_separation is None: if process_parameter.peak_separation is None: raise ValueError("pixel_separation is not set.\ Either set it in the process_parameter.peak_separation\ or pixel_separation parameter") else: pixel_separation = process_parameter.peak_separation / image0_scale initial_atom_position_list = get_atom_positions( s_image0_modified, separation=pixel_separation) if s_image1 is not None: if s_image1.data.dtype == 'float16': raise ValueError( "s_image1 has the dtype float16, which is not supported. " "Convert it to something else, for example using " "s_image1.change_dtype('float64')") s_image1 = s_image1.deepcopy() s_image1.data = 1. / s_image1.data image1_data = s_image1.data ################################# image0_data = s_image0.data image0_data_modified = s_image0_modified.data atom_lattice = Atom_Lattice(name=name) atom_lattice._original_filename = image0_filename atom_lattice.image = image0_data if s_image1 is not None: atom_lattice.image_extra = image1_data atom_lattice._pixel_separation = pixel_separation for sublattice_index in range(process_parameter.number_of_sublattices): sublattice_para = process_parameter.get_sublattice_from_order( sublattice_index) if sublattice_para.image_type == 0: s_image = s_image0 image_data = image0_data image_data_modified = image0_data_modified if sublattice_para.image_type == 1: if s_image1 is not None: s_image = s_image1 image_data = image1_data image_data_modified = image1_data else: break if sublattice_para.sublattice_order == 0: sublattice = Sublattice(initial_atom_position_list, image_data_modified) else: temp_sublattice = atom_lattice.get_sublattice( sublattice_para.sublattice_position_sublattice) temp_zone_vector_index = temp_sublattice.get_zone_vector_index( sublattice_para.sublattice_position_zoneaxis) zone_vector = temp_sublattice.zones_axis_average_distances[ temp_zone_vector_index] atom_list = temp_sublattice.find_missing_atoms_from_zone_vector( zone_vector) sublattice = Sublattice(atom_list, image_data) zone_axis_para_list = False if hasattr(sublattice_para, 'zone_axis_list'): zone_axis_para_list = sublattice_para.zone_axis_list sublattice._plot_color = sublattice_para.color sublattice.name = sublattice_para.name sublattice.pixel_size = s_image.axes_manager[0].scale sublattice._pixel_separation = pixel_separation sublattice.original_image = image_data atom_lattice.sublattice_list.append(sublattice) if debug_plot: sublattice.plot_atom_list_on_image_data(figname=sublattice.name + "_initial_position.jpg") for atom in sublattice.atom_list: atom.sigma_x = sublattice._pixel_separation / 10. atom.sigma_y = sublattice._pixel_separation / 10. if not (sublattice_para.sublattice_order == 0): construct_zone_axes_from_sublattice( sublattice, zone_axis_para_list=zone_axis_para_list) atom_subtract_config = sublattice_para.atom_subtract_config image_data = sublattice.image for atom_subtract_para in atom_subtract_config: temp_sublattice = atom_lattice.get_sublattice( atom_subtract_para['sublattice']) neighbor_distance = atom_subtract_para['neighbor_distance'] image_data = remove_atoms_from_image_using_2d_gaussian( image_data, temp_sublattice, percent_to_nn=neighbor_distance) sublattice.image = image_data sublattice.original_image = image_data refinement_config = sublattice_para.refinement_config refinement_neighbor_distance = refinement_config['neighbor_distance'] refinement_steps = refinement_config['config'] for refinement_step in refinement_steps: if refinement_step[0] == 'image_data': refinement_step[0] = sublattice.original_image elif refinement_step[0] == 'image_data_modified': refinement_step[0] = sublattice.image else: refinement_step[0] = sublattice.original_image refine_sublattice(sublattice, refinement_steps, refinement_neighbor_distance) if sublattice_para.sublattice_order == 0: sublattice.construct_zone_axes( zone_axis_para_list=zone_axis_para_list) return (atom_lattice)
def load_atom_lattice_from_hdf5(filename, construct_zone_axes=True): """ Load an Atomap HDF5-file, restoring a saved Atom_Lattice. Parameters ---------- filename : string Filename of the HDF5-file. construct_zone_axes : bool If True, find relations between atomic positions by constructing atomic planes. Default True. Returns ------- Atomap Atom_Lattice object """ h5f = h5py.File(filename, 'r') if 'atom_lattice_type' in h5f.attrs.keys(): atom_lattice_type = h5f.attrs['atom_lattice_type'] if 'Atom_Lattice' in atom_lattice_type: atom_lattice = al.Atom_Lattice() elif 'Dumbbell_Lattice' in atom_lattice_type: atom_lattice = al.Dumbbell_Lattice() else: atom_lattice = al.Atom_Lattice() else: atom_lattice = al.Atom_Lattice() sublattice_list = [] sublattice_index_list = [] for group_name in h5f: if ('atom_lattice' in group_name) or ('sublattice' in group_name): sublattice_set = h5f[group_name] modified_image_data = sublattice_set['modified_image_data'][:] original_image_data = sublattice_set['original_image_data'][:] atom_position_array = sublattice_set['atom_positions'][:] if 'sublattice_index' in sublattice_set.attrs.keys(): sublattice_index_list.append( sublattice_set.attrs['sublattice_index']) sublattice = Sublattice(atom_position_array, modified_image_data) sublattice.original_image = original_image_data if 'sigma_x' in sublattice_set.keys(): sigma_x_array = sublattice_set['sigma_x'][:] for atom, sigma_x in zip(sublattice.atom_list, sigma_x_array): atom.sigma_x = sigma_x if 'sigma_y' in sublattice_set.keys(): sigma_y_array = sublattice_set['sigma_y'][:] for atom, sigma_y in zip(sublattice.atom_list, sigma_y_array): atom.sigma_y = sigma_y if 'rotation' in sublattice_set.keys(): rotation_array = sublattice_set['rotation'][:] for atom, rotation in zip(sublattice.atom_list, rotation_array): atom.rotation = rotation sublattice.pixel_size = sublattice_set.attrs['pixel_size'] if 'tag' in sublattice_set.attrs.keys(): sublattice.name = sublattice_set.attrs['tag'] elif 'name' in sublattice_set.attrs.keys(): sublattice.name = sublattice_set.attrs['name'] else: sublattice.name = '' if type(sublattice.name) == bytes: sublattice.name = sublattice.name.decode() sublattice._plot_color = sublattice_set.attrs['plot_color'] if type(sublattice._plot_color) == bytes: sublattice._plot_color = sublattice._plot_color.decode() if 'pixel_separation' in sublattice_set.attrs.keys(): sublattice._pixel_separation = sublattice_set.attrs[ 'pixel_separation'] else: sublattice._pixel_separation = 0.0 if construct_zone_axes: construct_zone_axes_from_sublattice(sublattice) if 'zone_axis_names_byte' in sublattice_set.keys(): zone_axis_list_byte = sublattice_set.attrs[ 'zone_axis_names_byte'] zone_axis_list = [] for zone_axis_name_byte in zone_axis_list_byte: zone_axis_list.append(zone_axis_name_byte.decode()) sublattice.zones_axis_average_distances_names = zone_axis_list sublattice_list.append(sublattice) if group_name == 'image_data': atom_lattice.image = h5f[group_name][:] if group_name == 'image_data0': atom_lattice.image = h5f[group_name][:] if group_name == 'image_extra_data': atom_lattice.image_extra = h5f[group_name][:] if group_name == 'image_data1': atom_lattice.image_extra = h5f[group_name][:] if group_name == 'original_image_data': atom_lattice.original_image = h5f[group_name][:] sorted_sublattice_list = [] if not sublattice_index_list: # Support for older hdf5 files sublattice_index_list = range(len(sublattice_list)) for sublattice_index in sublattice_index_list: sorted_sublattice_list.append(sublattice_list[sublattice_index]) atom_lattice.sublattice_list.extend(sorted_sublattice_list) if 'name' in h5f.attrs.keys(): atom_lattice.name = h5f.attrs['name'] elif 'path_name' in h5f.attrs.keys(): atom_lattice.name = h5f.attrs['path_name'] if 'pixel_separation' in h5f.attrs.keys(): atom_lattice._pixel_separation = h5f.attrs['pixel_separation'] else: atom_lattice._pixel_separation = 0.8 / sublattice.pixel_size if type(atom_lattice.name) == bytes: atom_lattice.name = atom_lattice.name.decode() h5f.close() return (atom_lattice)
def __init__(self, image_x, image_y, sublattice_generate_image=True): """ Class for generating test datasets of atomic resolution STEM images. Parameters ---------- image_x, image_y : int Size of the image data. sublattice_generate_image : bool, default True When generating sublattices, a raster image is generated to complement the atom position objects (found in sublattice.image). For large amounts of atom positions, this can take a very long time. If sublattice_generate_image is False, this image will not be generated. Useful for generating sublattice objects for testing quicker, when only the atom positions themselves are needed. Attributes ---------- signal : HyperSpy 2D Signal sublattice : Atomap Sublattice atom_lattice : Atomap Atom_Lattice gaussian_list : list of 2D Gaussians objects Examples -------- >>> from atomap.testing_tools import MakeTestData >>> test_data = MakeTestData(200, 200) >>> test_data.add_atom(x=10, y=20) >>> test_data.signal.plot() Adding many atoms >>> test_data = MakeTestData(200, 200) >>> import numpy as np >>> x, y = np.mgrid[0:200:10j, 0:200:10j] >>> x, y = x.flatten(), y.flatten() >>> test_data.add_atom_list(x, y) >>> test_data.signal.plot() Adding many atoms with different parameters >>> test_data = MakeTestData(200, 200) >>> x, y = np.mgrid[0:200:10j, 0:200:10j] >>> x, y = x.flatten(), y.flatten() >>> sx, sy = np.random.random(len(x)), np.random.random(len(x)) >>> A, r = np.random.random(len(x))*10, np.random.random(len(x))*3.14 >>> test_data.add_atom_list(x, y, sigma_x=sx, sigma_y=sy, ... amplitude=A, rotation=r) >>> test_data.signal.plot() The class also generates a sublattice object >>> test_data = MakeTestData(200, 200) >>> import numpy as np >>> x, y = np.mgrid[0:200:10j, 0:200:10j] >>> x, y = x.flatten(), y.flatten() >>> test_data.add_atom_list(x, y) >>> test_data.sublattice.plot() Also Atom_Lattice objects >>> atom_lattice = test_data.atom_lattice >>> atom_lattice.plot() Generating a sublattice with 22500 atoms quickly, by not generating the image >>> test_data = MakeTestData(200, 200, sublattice_generate_image=False) >>> import numpy as np >>> x, y = np.mgrid[0:1000:150j, 0:1000:150j] >>> x, y = x.flatten(), y.flatten() >>> test_data.add_atom_list(x, y) >>> sublattice = test_data.sublattice """ self.data_extent = (image_x, image_y) self._image_noise = False self._sublattice_generate_image = sublattice_generate_image self.__sublattice = Sublattice([], np.zeros((2, 2))) self.__sublattice.atom_list = []