def test_write_read_nd_crystalmap_properties(self, temp_file_path, crystal_map): """Crystal map properties with more than one value in each point (e.g. top matching scores from dictionary indexing) can be written and read from file correctly. """ xmap = crystal_map map_size = xmap.size prop2d_name = "prop2d" prop2d_shape = (map_size, 2) prop2d = np.arange(map_size * 2).reshape(prop2d_shape) xmap.prop[prop2d_name] = prop2d prop3d_name = "prop3d" prop3d_shape = (map_size, 2, 2) prop3d = np.arange(map_size * 4).reshape(prop3d_shape) xmap.prop[prop3d_name] = prop3d save(filename=temp_file_path, object2write=xmap) xmap2 = load(temp_file_path) assert np.allclose(xmap2.prop[prop2d_name], xmap.prop[prop2d_name]) assert np.allclose(xmap2.prop[prop3d_name], xmap.prop[prop3d_name]) assert np.allclose(xmap2.prop[prop2d_name].reshape(prop2d_shape), prop2d) assert np.allclose(xmap2.prop[prop3d_name].reshape(prop3d_shape), prop3d)
def test_point_group_aliases(self, crystal_map, tmp_path, point_group): crystal_map.phases[0].point_group = point_group fname = tmp_path / "test_point_group_aliases.ang" save(fname, crystal_map) xmap_reload = load(fname) phase_ids = xmap_reload.phases.ids assert xmap_reload.phases[phase_ids[0]].point_group.name == point_group
def test_points_not_in_data(self, crystal_map, tmp_path): crystal_map.prop["iq"] = np.ones(crystal_map.size) crystal_map[2].iq = 0 xmap2 = crystal_map[crystal_map.iq == 1] fname = tmp_path / "test_points_not_in_data.ang" save(fname, xmap2) xmap_reload = load(fname) assert not xmap2.is_in_data.all() assert np.allclose(xmap2.is_in_data, xmap_reload.is_indexed)
def test_write_read_loop(self, crystal_map, tmp_path): fname = tmp_path / "test_write_read_loop.ang" save(filename=fname, object2write=crystal_map) xmap_reload = load(filename=fname) assert np.allclose( xmap_reload.rotations.to_euler(), crystal_map.rotations.to_euler(), ) assert np.allclose(xmap_reload.phase_id - 1, crystal_map.phase_id)
def test_save_overwrite(self, temp_file_path, crystal_map, overwrite, expected_phase_name): assert crystal_map.phases[0].name == "" save(temp_file_path, crystal_map) assert os.path.isfile(temp_file_path) is True crystal_map.phases[0].name = "hepp" save(temp_file_path, crystal_map, overwrite=overwrite) crystal_map2 = load(temp_file_path) assert crystal_map2.phases[0].name == expected_phase_name
def test_1d_map(self, crystal_map_input, tmp_path): xmap = CrystalMap(**crystal_map_input) assert xmap.ndim == 1 fname = tmp_path / "test_1d_map.ang" save(fname, xmap) xmap_reload = load(fname) assert xmap_reload.ndim == 1 assert np.allclose(xmap.rotations.to_euler(), xmap_reload.rotations.to_euler())
def test_write_read_masked(self, crystal_map_input, temp_file_path): cm = CrystalMap(**crystal_map_input) save(filename=temp_file_path, object2write=cm[cm.x > 2]) cm2 = load(temp_file_path) assert cm2.size != cm.size with pytest.raises(ValueError, match="operands could not be broadcast"): _ = np.allclose(cm2.x, cm.x) cm2.is_in_data = cm.is_in_data assert cm2.size == cm.size assert np.allclose(cm2.x, cm.x)
def test_load_emsoft( self, temp_emsoft_h5ebsd_file, map_shape, step_sizes, example_rot, n_top_matches, refined, ): xmap = load(temp_emsoft_h5ebsd_file.filename, refined=refined) assert xmap.shape == map_shape assert (xmap.dy, xmap.dx) == step_sizes if refined: n_top_matches = 1 assert xmap.rotations_per_point == n_top_matches # Properties expected_props = [ "AvDotProductMap", "CI", "CIMap", "IQ", "IQMap", "ISM", "ISMap", "KAM", "OSM", "TopDotProductList", "TopMatchIndices", ] if refined: expected_props += ["RefinedDotProducts"] actual_props = list(xmap.prop.keys()) actual_props.sort() expected_props.sort() assert actual_props == expected_props assert xmap.phases["austenite"].structure == Structure( title="austenite", lattice=Lattice(a=3.595, b=3.595, c=3.595, alpha=90, beta=90, gamma=90), ) # Ensure Euler angles in degrees are read correctly from file if not refined: assert np.rad2deg(xmap.rotations.to_euler().min()) >= 150 assert np.rad2deg(xmap.rotations.to_euler().max()) <= 160
def test_non_indexed_points(self, crystal_map, tmp_path): crystal_map[2].phase_id = -1 fname = tmp_path / "test_non_indexed_points.ang" save(fname, crystal_map) xmap_reload = load(fname) crystal_map.phases[0].name = "phase1" assert xmap_reload.phases.names == crystal_map.phases.names new_phase_ids = xmap_reload.phase_id new_phase_ids[xmap_reload.is_indexed] -= 1 assert np.allclose(new_phase_ids, crystal_map.phase_id)
def test_extra_prop(self, crystal_map, tmp_path, extra_prop): fname = tmp_path / "test_extra_prop.ang" desired_arrays = [] n_points = crystal_map.size for i, name in enumerate(extra_prop): new_array = np.arange(n_points) * i crystal_map.prop[name] = new_array desired_arrays.append(new_array) save(fname, crystal_map, extra_prop=extra_prop) xmap_reload = load(fname) for name in extra_prop: assert np.allclose(xmap_reload.prop[name], crystal_map.prop[name])
def test_extra_phases(self, crystal_map, tmp_path, extra_phase_names): crystal_map.phases.add_not_indexed() for i, name in enumerate(extra_phase_names): crystal_map.phases.add(Phase(name=name)) crystal_map[i].phase_id = crystal_map.phases.id_from_name(name) fname = tmp_path / "test_extra_phases.ang" save(fname, crystal_map) xmap_reload = load(fname) crystal_map.phases[0].name = "phase1" assert np.allclose(xmap_reload.phase_id - 1, crystal_map.phase_id) pl = crystal_map.phases del pl[-1] assert xmap_reload.phases.names == pl.names
def test_load_emsoft( self, temp_emsoft_h5ebsd_file, map_shape, step_sizes, example_rot, n_top_matches, refined, ): cm = load(temp_emsoft_h5ebsd_file.filename, refined=refined) assert cm.shape == map_shape assert (cm.dy, cm.dx) == step_sizes if refined: n_top_matches = 1 assert cm.rotations_per_point == n_top_matches # Properties expected_props = [ "AvDotProductMap", "CI", "CIMap", "IQ", "IQMap", "ISM", "ISMap", "KAM", "OSM", "TopDotProductList", "TopMatchIndices", ] if refined: expected_props += ["RefinedDotProducts"] actual_props = list(cm.prop.keys()) actual_props.sort() expected_props.sort() assert actual_props == expected_props assert cm.phases["austenite"].structure == Structure( title="austenite", lattice=Lattice(a=3.595, b=3.595, c=3.595, alpha=90, beta=90, gamma=90), )
def test_read_point_group_from_v0_3_x(self, temp_file_path, crystal_map): crystal_map.phases[0].point_group = "1" save(filename=temp_file_path, object2write=crystal_map) # First, ensure point group data set name is named "symmetry", as in v0.3.0 with File(temp_file_path, mode="r+") as f: for phase in f["crystal_map/header/phases"].values(): phase["symmetry"] = phase["point_group"] del phase["point_group"] # Then, make sure it can still be read cm2 = load(filename=temp_file_path) # And that the symmetry operations are the same, for good measure print(crystal_map) print(cm2) assert np.allclose(crystal_map.phases[0].point_group.data, cm2.phases[0].point_group.data)
def test_load_ang_astar( self, angfile_astar, map_shape, step_sizes, phase_id, example_rot, ): cm = load(angfile_astar) # Properties assert list(cm.prop.keys()) == ["ind", "rel", "relx100"] # Coordinates ny, nx = map_shape dy, dx = step_sizes assert np.allclose(cm.x, np.tile(np.arange(nx) * dx, ny)) assert np.allclose(cm.y, np.sort(np.tile(np.arange(ny) * dy, nx))) # Map shape and size assert cm.shape == map_shape assert cm.size == np.prod(map_shape) # Attributes are within expected ranges or have a certain value assert cm.prop["ind"].max() <= 100 assert cm.prop["rel"].max() <= 1 assert cm.prop["relx100"].max() <= 100 relx100 = (cm.prop["rel"] * 100).astype(int) assert np.allclose(cm.prop["relx100"], relx100) # Phase IDs assert np.allclose(cm.phase_id, phase_id) # Rotations rot_unique = np.unique(cm.rotations.to_euler(), axis=0) assert np.allclose(np.sort(rot_unique, axis=0), np.sort(example_rot, axis=0), atol=1e-6) # Phases assert cm.phases.size == 1 assert cm.phases.ids == [1] phase = cm.phases[1] assert phase.name == "Nickel" assert phase.point_group.name == "432"
def test_write_data_layer_i(self, crystal_map_input, tmp_path, index): xmap = CrystalMap(**crystal_map_input) xmap.prop["ci"] = np.arange(xmap.size * xmap.rotations_per_point).reshape( (xmap.size, xmap.rotations_per_point)) xmap.prop["iq"] = np.arange(xmap.size) extra_prop = "iq_times_ci" xmap.prop[extra_prop] = xmap.ci * xmap.iq[:, np.newaxis] fname = tmp_path / "test_write_data_layer_i.ang" save(fname, xmap, index=index, extra_prop=[extra_prop, "iq"]) xmap_reload = load(fname) assert np.allclose(xmap.rotations[:, index].to_euler(), xmap_reload.rotations.to_euler()) assert np.allclose(xmap_reload.iq, np.zeros(xmap.size)) assert np.allclose(xmap_reload.ci, xmap.ci[:, index]) assert np.allclose(xmap_reload.iq_times_ci, xmap.iq_times_ci[:, index])
def test_load_ang_emsoft( self, angfile_emsoft, map_shape, step_sizes, phase_id, example_rot, ): cm = load(angfile_emsoft) # Properties assert list(cm.prop.keys()) == ["iq", "dp"] # Coordinates ny, nx = map_shape dy, dx = step_sizes assert np.allclose(cm.x, np.tile(np.arange(nx) * dx, ny)) assert np.allclose(cm.y, np.sort(np.tile(np.arange(ny) * dy, nx))) # Map shape and size assert cm.shape == map_shape assert cm.size == np.prod(map_shape) # Attributes are within expected ranges or have a certain value assert cm.prop["iq"].max() <= 100 assert cm.prop["dp"].max() <= 1 # Phase IDs assert np.allclose(cm.phase_id, phase_id) # Rotations rot_unique = np.unique(cm.rotations.to_euler(), axis=0) assert np.allclose(np.sort(rot_unique, axis=0), np.sort(example_rot, axis=0), atol=1e-5) # Phases (change if file header is changed!) phases_in_data = cm["indexed"].phases_in_data assert phases_in_data.size == 2 assert phases_in_data.ids == [1, 2] assert phases_in_data.names == ["austenite", "ferrite"] assert [i.name for i in phases_in_data.point_groups] == ["432"] * 2
def test_file_reader(self, crystal_map, temp_file_path): save(filename=temp_file_path, object2write=crystal_map) cm2 = load(filename=temp_file_path) assert_dictionaries_are_equal(crystal_map.__dict__, cm2.__dict__)
def test_load_no_filename_match(self): fname = "what_is_hip.ang" with pytest.raises(IOError, match=f"No filename matches '{fname}'."): _ = load(fname)
def test_load_unsupported_format(self, temp_file_path): np.savetxt(temp_file_path, X=np.random.rand(100, 8)) with pytest.raises(IOError, match=f"Could not read "): _ = load(temp_file_path)
def test_load_ang_tsl( self, angfile_tsl, map_shape, step_sizes, phase_id, n_unknown_columns, example_rot, ): cm = load(angfile_tsl) # Fraction of non-indexed points non_indexed_fraction = int(np.prod(map_shape) * 0.1) assert non_indexed_fraction == np.sum(~cm.is_indexed) # Properties assert list(cm.prop.keys()) == [ "iq", "ci", "unknown1", "fit", "unknown2", "unknown3", "unknown4", "unknown5", ] # Coordinates ny, nx = map_shape dy, dx = step_sizes assert np.allclose(cm.x, np.tile(np.arange(nx) * dx, ny)) assert np.allclose(cm.y, np.sort(np.tile(np.arange(ny) * dy, nx))) # Map shape and size assert cm.shape == map_shape assert cm.size == np.prod(map_shape) # Attributes are within expected ranges or have a certain value assert cm.prop["ci"].max() <= 1 assert cm["indexed"].fit.max() <= 3 assert all(cm["not_indexed"].fit == 180) assert all(cm["not_indexed"].ci == -1) # Phase IDs (accounting for non-indexed points) phase_id[cm["not_indexed"].id] = -1 assert np.allclose(cm.phase_id, phase_id) # Rotations rot_unique = np.unique(cm["indexed"].rotations.to_euler(), axis=0) assert np.allclose(np.sort(rot_unique, axis=0), np.sort(example_rot, axis=0), atol=1e-5) assert np.allclose( cm["not_indexed"].rotations.to_euler()[0], np.array([np.pi, 0, np.pi]), atol=1e-5, ) # Phases assert cm.phases.size == 2 # Including non-indexed assert cm.phases.ids == [-1, 0] phase = cm.phases[0] assert phase.name == "Aluminum" assert phase.point_group.name == "432"