def to_crystal_map(self): """ Exports an indexation result with multiple results per navigation position to crystal map with one result per pixel Returns ------- orix.CrystalMap """ _s = self.data.map(_get_best_match,inplace=False) """ Gets properties """ phase_id = _s.isig[0].data.flatten() alpha = _s.isig[1].data.flatten() beta = _s.isig[2].data.flatten() gamma = _s.isig[3].data.flatten() score = _s.isig[4].data.flatten() """ Gets navigation placements """ xy = np.indices(_s.data.shape[:2]) x = xy[1].flatten() y = xy[0].flatten() """ Tidies up so we can put these things into CrystalMap """ euler = np.vstack((alpha,beta,gamma)).T rotations = Rotation.from_euler(euler,convention="bunge", direction="crystal2lab") properties = {"score":score} return CrystalMap( rotations=rotations, phase_id=phase_id, x=x, y=y, prop=properties)
def test_get_item( self, nickel_ebsd_simulation_generator, nav_idx, desired_shape, desired_pc, desired_rotation, ): """Desired PC and rotation values from __getitem__().""" simgen = nickel_ebsd_simulation_generator simgen.navigation_shape = (5, 5) simgen.detector.pc[nav_idx] = desired_pc r = Rotation.from_euler(desired_rotation) simgen.rotations[nav_idx] = r simgen2 = simgen[nav_idx] assert simgen2.navigation_shape == desired_shape assert np.allclose(simgen2.detector.pc, desired_pc) assert np.allclose(simgen2.rotations.data, r.data) new_pc = [ 0.5, ] * 3 simgen2.detector.pc[0] = new_pc assert not np.allclose(simgen[nav_idx].detector.pc, simgen2.detector.pc)
def test_merging_refined_maps(self): ny, nx = (3, 3) nav_size = ny * nx r = Rotation.from_euler(np.ones((nav_size, 3))) x = np.tile(np.arange(ny), nx) y = np.repeat(np.arange(nx), ny) # Simulation indices n_sim_indices = 10 sim_indices1 = np.random.randint(low=0, high=1000, size=n_sim_indices * nav_size).reshape( (nav_size, n_sim_indices)) sim_indices2 = np.random.randint(low=0, high=1000, size=n_sim_indices * nav_size).reshape( (nav_size, n_sim_indices)) # Scores scores1 = np.ones(nav_size) scores1[0] = 3 scores2 = 2 * np.ones(nav_size) xmap1 = CrystalMap( rotations=r, phase_id=np.ones(nav_size) * 0, phase_list=PhaseList(Phase(name="a")), x=x, y=y, prop={ "simulation_indices": sim_indices1, "scores": scores1 }, ) xmap2 = CrystalMap( rotations=r, phase_id=np.ones(nav_size), phase_list=PhaseList(Phase(name="b")), x=x, y=y, prop={ "simulation_indices": sim_indices2, "scores": scores2 }, ) xmap_merged = merge_crystal_maps(crystal_maps=[xmap1, xmap2]) assert "simulation_indices" not in xmap_merged.prop.keys() assert "merged_simulation_indices" not in xmap_merged.prop.keys() with pytest.raises(ValueError, match="Cannot merge maps with more"): _ = merge_crystal_maps( crystal_maps=[xmap1, xmap2], simulation_indices_prop="simulation_indices", )
def compute_refine_orientation_projection_center_results( results: list, detector, xmap: CrystalMap, master_pattern, ): """Compute the results from :meth:`~kikuchipy.signals.EBSD.refine_orientation_projection_center` and return the :class:`~orix.crystal_map.CrystalMap` and :class:`~kikuchipy.detectors.EBSDDetector`. Parameters ---------- results Results returned from `refine_orientation_projection_center()`, which is a list of :class:`~dask.delayed.Delayed`. detector : ~kikuchipy.detectors.EBSDDetector Detector passed to `refine_orientation_projection_center()` to obtain `results`. xmap Crystal map passed to `refine_orientation_projection_center()` to obtain `results`. master_pattern : ~kikuchipy.signals.EBSDMasterPattern Master pattern passed to `refine_orientation_projection_center()` to obtain `results`. Returns ------- xmap_refined : :class:`~orix.crystal_map.CrystalMap` Crystal map with refined orientations and scores. new_detector : :class:`~kikuchipy.detectors.EBSDDetector` EBSD detector with refined projection center parameters. """ n_patterns = len(results) nav_shape = xmap.shape with ProgressBar(): print( f"Refining {n_patterns} orientation(s) and projection center(s):", file=sys.stdout, ) computed_results = dask.compute(*results) computed_results = np.array(computed_results) # (n, score, phi1, Phi, phi2, PCx, PCy, PCz) xmap_refined = CrystalMap( rotations=Rotation.from_euler(computed_results[:, 1:4]), phase_id=np.zeros(n_patterns), x=xmap.x, y=xmap.y, phase_list=PhaseList(phases=master_pattern.phase), prop=dict(scores=computed_results[:, 0]), scan_unit=xmap.scan_unit, ) new_detector = detector.deepcopy() new_detector.pc = computed_results[:, 4:].reshape(nav_shape + (3, )) return xmap_refined, new_detector
def to_crystal_map(self): """Obtain a crystallographic map specifying the best matching phase and orientation at each probe position with corresponding metrics. Raises ------- ValueError("Currently under development") """ raise ValueError("Currently under development") _s = self.map( crystal_from_vector_matching, inplace=False) """ Gets phase, the easy bit """ phase_id = _s.isig[0].data.flatten() """ Deals with the properties, hard coded as of v0.13 """ # need to invert an array of dicts into a dict of arrays def _map_to_get_property(prop): return d[prop] # assume same properties at every point of the signal key_list = [] for key in _s.inav[0,0].isig[2]: key_list.append(key) properties = {} for key in key_list: _key_signal = _s.isig[2].map(_map_to_get_property,prop=key,inplace=False) properties[key] = _key_signal """ Deal with the rotations """ def _map_for_alpha_beta_gamma(ix): return z[ix] alpha = _s.isig[1].map(_map_for_alpha_beta_gamma,ix=0,inplace=False) beta = _s.isig[1].map(_map_for_alpha_beta_gamma,ix=1,inplace=False) gamma = _s.isig[1].map(_map_for_alpha_beta_gamma,ix=2,inplace=False) euler = np.vstack((alpha,beta,gamma)).T rotations = Rotation.from_euler(euler,convention="bunge", direction="crystal2lab") """ Gets navigation placements """ xy = np.indices(_s.data.shape[:2]) x = xy[1].flatten() y = xy[0].flatten() return CrystalMap( rotations=rotations, phase_id=phase_id, x=x, y=y, prop=properties)
def test_simulated_patterns_xmap_detector(self): mp = nickel_ebsd_master_pattern_small(projection="lambert") r = Rotation.from_euler([[0, 0, 0], [0, np.pi / 2, 0]]) detector = EBSDDetector( shape=(60, 60), pc=[0.5, 0.5, 0.5], sample_tilt=70, convention="tsl", ) s = mp.get_patterns(rotations=r, detector=detector, energy=20) assert np.allclose(s.xmap.rotations.to_euler(), r.to_euler()) assert s.xmap.phases.names == [mp.phase.name] assert s.xmap.phases[0].point_group.name == mp.phase.point_group.name assert s.detector.shape == detector.shape assert np.allclose(s.detector.pc, detector.pc) assert s.detector.sample_tilt == detector.sample_tilt
async def preview_dictionary(req: DictionaryIndexingIn): if req.ebsd_info.uid not in kp_signals: raise HTTPException(status_code=404, detail="Patterns not found") s = kp_signals[req.ebsd_info.uid] detector = kp.detectors.EBSDDetector( shape=s.axes_manager.signal_shape[::-1], pc=req.detector.pc, sample_tilt=req.detector.sample_tilt, convention=req.detector.pc_convention, tilt=req.detector.camera_tilt, ) res = PreviewDictionary(patterns=[]) if req.preview_angles: euler = np.array(req.preview_angles) else: euler = np.array([0.0, 0.0, 0.0]) for mp_req in req.masterpatterns: mp = kp.load( mp_req.filepath, projection=mp_req.projection, hemisphere="both", energy=mp_req.energy, ) sim = mp.get_patterns( rotations=Rotation.from_euler(np.deg2rad(euler)), detector=detector, energy=mp_req.energy, compute=True, ) svg_string = io.StringIO() plt.figure() plt.imshow(sim.data[0], cmap="gray") plt.title( f"{mp.phase.name.capitalize()}\n($\phi_1, \Phi, \phi_2)$ = {np.array_str(euler, precision=1)}" ) plt.axis("off") plt.savefig(svg_string, format="svg", bbox_inches="tight", transparent=True) svg_string.seek(0) res.patterns.append(svg_string.getvalue()) return res
def test_get_patterns_chunk(self): r = Rotation.from_euler(((0, 0, 0), (1, 1, 1), (2, 2, 2))) dc = _get_direction_cosines(self.detector) mpn = np.empty((1001, 1001)) mps = mpn npx = 1001 npy = npx out = _get_patterns_chunk( rotations_array=r.data, dc=dc, master_north=mpn, master_south=mps, npx=npx, npy=npy, scale=(npx - 1) / 2, rescale=False, ) assert out.shape == r.shape + dc.shape
def compute_refine_orientation_results(results: list, xmap: CrystalMap, master_pattern): """Compute the results from :meth:`~kikuchipy.signals.EBSD.refine_orientation` and return the :class:`~orix.crystal_map.CrystalMap`. Parameters ---------- results Results returned from `refine_orientation()`, which is a list of :class:`~dask.delayed.Delayed`. xmap Crystal map passed to `refine_orientation()` to obtain `results`. master_pattern : ~kikuchipy.signals.EBSDMasterPattern Master pattern passed to `refine_orientation()` to obtain `results`. Returns ------- refined_xmap : :class:`~orix.crystal_map.CrystalMap` Crystal map with refined orientations and scores. """ n_patterns = len(results) with ProgressBar(): print(f"Refining {n_patterns} orientation(s):", file=sys.stdout) computed_results = dask.compute(*results) # (n, score, phi1, Phi, phi2) computed_results = np.array(computed_results) xmap_refined = CrystalMap( rotations=Rotation.from_euler(computed_results[:, 1:]), phase_id=np.zeros(n_patterns), x=xmap.x, y=xmap.y, phase_list=PhaseList(phases=master_pattern.phase), prop=dict(scores=computed_results[:, 0]), scan_unit=xmap.scan_unit, ) return xmap_refined
def test_project_patterns_from_master_pattern(self): """Make sure the Numba function is covered.""" r = Rotation.from_euler(((0, 0, 0), (1, 1, 1), (2, 2, 2))) dc = _get_direction_cosines_for_single_pc_from_detector(self.detector) npx = npy = 101 mpn = mps = np.zeros((npy, npx)) patterns = _project_patterns_from_master_pattern.py_func( rotations=r.data, direction_cosines=dc, master_north=mpn, master_south=mps, npx=npx, npy=npy, scale=float((npx - 1) / 2), dtype_out=mpn.dtype, rescale=False, # Aren't used out_min=1, out_max=2, ) assert patterns.shape == r.shape + dc.shape[:-1]
def test_get_patterns(self): # Ni Test EMSOFT_EBSD_FILE = os.path.join( DIR_PATH, "../../data/emsoft_ebsd/EBSD_TEST_Ni.h5") emsoft_key = load(EMSOFT_EBSD_FILE) emsoft_key = emsoft_key.data[0] angles = np.array((120, 45, 60)) r = Rotation.from_euler(np.radians(angles)) kp_mp = nickel_ebsd_master_pattern_small(projection="lambert", hemisphere="both") kp_pattern = kp_mp.get_patterns(rotations=r, detector=self.detector, energy=20, dtype_out=np.uint8) kp_pat = kp_pattern.data[0].compute() ncc1 = ncc(kp_pat, emsoft_key) ndp1 = ndp(kp_pat, emsoft_key) assert ncc1 >= 0.935 assert ndp1 >= 0.935 detector_shape = self.detector.shape r2 = Rotation.from_euler(((0, 0, 0), (1, 1, 1), (2, 2, 2))) mp_a = EBSDMasterPattern(np.zeros((2, 10, 11, 11))) print(mp_a.axes_manager) mp_a.axes_manager[0].name = "hemisphere" mp_a.axes_manager[1].name = "energy" mp_a.projection = "lambert" mp_a.phase = Phase("Ni", 225) out_a = mp_a.get_patterns(r2, self.detector, 5) assert isinstance(out_a, LazyEBSD) desired_data_shape = (3, ) + detector_shape[::-1] assert out_a.axes_manager.shape == desired_data_shape mp_b = EBSDMasterPattern(np.zeros((10, 11, 11))) mp_b.axes_manager[0].name = "energy" mp_b.projection = "lambert" mp_b.phase = Phase("Ni", 225) out_b = mp_b.get_patterns(r2, self.detector, 5) assert isinstance(out_b, LazyEBSD) assert out_b.axes_manager.shape == desired_data_shape mp_c = EBSDMasterPattern(np.zeros((11, 11))) mp_c.projection = "lambert" mp_c.phase = Phase("Ni", 225) out_c = mp_c.get_patterns(r2, self.detector, 5) out_c_2 = mp_c.get_patterns(r2, self.detector, 5, compute=True) assert isinstance(out_c, LazyEBSD) assert isinstance(out_c_2, EBSD) assert out_c.axes_manager.shape == desired_data_shape mp_c2 = EBSDMasterPattern(np.zeros((11, 11))) mp_c2.projection = "lambert" mp_c2.phase = Phase("!Ni", 220) with pytest.raises(AttributeError): mp_c2.get_patterns(r2, self.detector, 5) mp_d = EBSDMasterPattern(np.zeros((2, 11, 11))) with pytest.raises(NotImplementedError): mp_d.get_patterns(r2, self.detector, 5) mp_e = EBSDMasterPattern(np.zeros((10, 11, 11))) mp_e.axes_manager[0].name = "energy" mp_e.projection = "lambert" mp_e.phase = Phase("!Ni", 220) with pytest.raises(AttributeError): mp_e.get_patterns(r2, self.detector, 5) # More than one Projection center is currently not supported so # it should fail d2 = EBSDDetector( shape=(10, 10), px_size=50, pc=((0, 0, 15000), (0, 0, 15000)), convention="emsoft4", tilt=0, sample_tilt=70, ) with pytest.raises(NotImplementedError): mp_c.get_patterns(r2, d2, 5)
def test_results_dict_to_crystal_map(test_library_phases_multi, test_lib_gen): """Test getting a :class:`orix.crystal_map.CrystalMap` from returns from :func:`index_dataset_with_template_rotation`. """ # Map and signal shapes nav_shape = (2, 3) sig_shape = (80, 80) test_set = np.zeros(nav_shape + sig_shape) # Diffraction conditions diff_lib = test_lib_gen.get_diffraction_library( test_library_phases_multi, calibration=0.015, reciprocal_radius=1.18, half_shape=tuple(np.array(sig_shape) // 2), with_direct_beam=False, ) # Simulate multi-phase results phase_id = np.zeros(nav_shape, dtype=int) phase_id[:, [0, 2]] = 1 phase_names = list(diff_lib.keys()) # Simulate patterns sim_kwargs = dict(size=sig_shape[0], sigma=4) for idx in np.ndindex(*nav_shape): i = phase_id[idx] j = int(idx[1] / 2) test_pattern = diff_lib[phase_names[i]]["simulations"][j].\ get_diffraction_pattern(**sim_kwargs) test_set[idx] = test_pattern # Perform template matching n_best = 3 results, phase_dict = index_dataset_with_template_rotation( Signal2D(test_set), diff_lib, phases=phase_names, n_best=n_best, ) # Extract various results once phase_id = results["phase_index"].reshape((-1, n_best)) ori = np.deg2rad(results["orientation"].reshape((-1, n_best, 3))) # Property names in `results` prop_names = ["correlation", "mirrored_template", "template_index"] # Only get the bast match when multiple phases match best to some # patterns xmap = results_dict_to_crystal_map(results, phase_dict, diffraction_library=diff_lib) assert np.allclose(xmap.phase_id, phase_id[:, 0]) assert xmap.rotations_per_point == 1 assert xmap.phases.names == phase_names assert (xmap.phases.structures[0].lattice.abcABG() == test_library_phases_multi.structures[0].lattice.abcABG()) # Raise warning when a property is not present as expected del results[prop_names[0]] with pytest.warns(UserWarning, match=f"Property '{prop_names[0]}' was expected"): xmap2 = results_dict_to_crystal_map(results, phase_dict, diffraction_library=diff_lib) assert list(xmap2.prop.keys()) == prop_names[1:] # Raise error when trying to access a best match which isn't # available with pytest.raises(ValueError, match="`index` cannot be higher than 2"): _ = results_dict_to_crystal_map(results, phase_dict, index=3) # Get second best match i = 1 xmap3 = results_dict_to_crystal_map(results, phase_dict, index=i) assert xmap3.rotations_per_point == 1 assert np.allclose(xmap3.phase_id, phase_id[:, i]) assert np.allclose(xmap3.rotations.data, Rotation.from_euler(ori[:, i]).data) assert np.allclose(xmap3.prop[prop_names[1]], results[prop_names[1]][:, :, i].flatten()) # Make map single-phase and get all matches per point results["phase_index"][..., 0] = 0 xmap4 = results_dict_to_crystal_map(results, phase_dict) assert np.all(xmap4.phase_id == 0) assert xmap4.phases.names[0] == phase_names[0] assert xmap4.rotations_per_point == 3 # Get only best match even though map is single-phase i = 0 xmap5 = results_dict_to_crystal_map(results, phase_dict, index=i) assert xmap5.rotations_per_point == 1 assert np.allclose(xmap5.rotations.data, Rotation.from_euler(ori[:, i]).data) assert np.allclose(xmap5.prop[prop_names[1]], results[prop_names[1]][:, :, i].flatten())
def file_reader( filename: str, scan_size: Union[None, int, Tuple[int, ...]] = None, lazy: bool = False, **kwargs, ) -> List[dict]: """Read dynamically simulated electron backscatter diffraction patterns from EMsoft's format produced by their EMEBSD.f90 program. Parameters ---------- filename Full file path of the HDF file. scan_size Scan size in number of patterns in width and height. lazy Open the data lazily without actually reading the data from disk until requested. Allows opening datasets larger than available memory. Default is False. kwargs : Keyword arguments passed to h5py.File. Returns ------- signal_dict_list: list of dicts Data, axes, metadata and original metadata. """ mode = kwargs.pop("mode", "r") f = File(filename, mode=mode, **kwargs) _check_file_format(f) # Read original metadata omd = hdf5group2dict(f["/"], data_dset_names=["EBSDPatterns"], recursive=True) # Set metadata and original metadata dictionaries md = _get_metadata(omd) md.update({ "Signal": { "signal_type": "EBSD", "record_by": "image" }, "General": { "title": f.filename.split("/")[-1].split(".")[0], "original_filename": f.filename.split("/")[-1], }, }) scan = {"metadata": md, "original_metadata": omd} # Read patterns dataset = f["EMData/EBSD/EBSDPatterns"] if lazy: chunks = "auto" if dataset.chunks is None else dataset.chunks patterns = da.from_array(dataset, chunks=chunks) else: patterns = np.asanyarray(dataset) # Reshape data if desired sy = omd["NMLparameters"]["EBSDNameList"]["numsy"] sx = omd["NMLparameters"]["EBSDNameList"]["numsx"] if scan_size is not None: if isinstance(scan_size, int): new_shape = (scan_size, sy, sx) else: new_shape = scan_size + (sy, sx) patterns = patterns.reshape(new_shape) scan["data"] = patterns # Set navigation and signal axes pixel_size = omd["NMLparameters"]["EBSDNameList"]["delta"] ndim = patterns.ndim units = ["px", "um", "um"] names = ["x", "dy", "dx"] scales = np.array([1, pixel_size, pixel_size]) if ndim == 4: units = ["px"] + units names = ["y"] + names scales = np.append([1], scales) scan["axes"] = [{ "size": patterns.shape[i], "index_in_array": i, "name": names[i], "scale": scales[i], "offset": 0, "units": units[i], } for i in range(patterns.ndim)] # Get crystal map phase = _crystaldata2phase(hdf5group2dict(f["CrystalData"])) xtal_fname = f["EMData/EBSD/xtalname"][()][0].decode().split("/")[-1] phase.name, _ = os.path.splitext(xtal_fname) scan["xmap"] = CrystalMap( rotations=Rotation.from_euler(f["EMData/EBSD/EulerAngles"][()]), phase_list=PhaseList(phase), ) if not lazy: f.close() return [scan]
def test_get_patterns(self): emsoft_key = load(EMSOFT_EBSD_FILE) emsoft_key = emsoft_key.data[0] r = Rotation.from_euler(np.radians([120, 45, 60])) mp1 = nickel_ebsd_master_pattern_small(projection="lambert", hemisphere="both") kp_pattern = mp1.get_patterns(rotations=r, detector=self.detector, energy=20, dtype_out=emsoft_key.dtype) kp_pat = kp_pattern.data[0].compute() assert kp_pat.dtype == emsoft_key.dtype ncc = NormalizedCrossCorrelationMetric(1, 1) ncc1 = ncc(kp_pat, emsoft_key) assert ncc1 >= 0.935 ndp = NormalizedDotProductMetric(1, 1) ndp1 = ndp(kp_pat, emsoft_key) assert ndp1 >= 0.935 detector_shape = self.detector.shape r2 = Rotation.from_euler(((0, 0, 0), (1, 1, 1), (2, 2, 2))) mp2 = kp.signals.EBSDMasterPattern(np.zeros((2, 10, 11, 11))) mp2.axes_manager[0].name = "hemisphere" mp2.axes_manager[1].name = "energy" mp2.projection = "lambert" mp2.phase = Phase("Ni", 225) out2 = mp2.get_patterns(r2, self.detector, 5) assert isinstance(out2, kp.signals.LazyEBSD) desired_data_shape = (3, ) + detector_shape[::-1] assert out2.axes_manager.shape == desired_data_shape mp3 = kp.signals.EBSDMasterPattern(np.zeros((10, 11, 11))) mp3.axes_manager[0].name = "energy" mp3.projection = "lambert" mp3.phase = Phase("Ni", 225) out3 = mp3.get_patterns(r2, self.detector, 5) assert isinstance(out3, kp.signals.LazyEBSD) assert out3.axes_manager.shape == desired_data_shape mp4 = kp.signals.EBSDMasterPattern(np.zeros((11, 11))) mp4.projection = "lambert" mp4.phase = Phase("Ni", 225) out41 = mp4.get_patterns(r2, self.detector, 5) out42 = mp4.get_patterns(r2, self.detector, 5, compute=True) assert isinstance(out41, kp.signals.LazyEBSD) assert isinstance(out42, kp.signals.EBSD) assert out41.axes_manager.shape == desired_data_shape mp5 = kp.signals.EBSDMasterPattern(np.zeros((11, 11))) mp5.projection = "lambert" mp5.phase = Phase("!Ni", 220) with pytest.raises(AttributeError): _ = mp5.get_patterns(r2, self.detector, 5) mp6 = kp.signals.EBSDMasterPattern(np.zeros((2, 11, 11))) with pytest.raises(AttributeError, match="Master pattern `phase` attribute"): _ = mp6.get_patterns(r2, self.detector, 5) mp7 = kp.signals.EBSDMasterPattern(np.zeros((10, 11, 11))) mp7.axes_manager[0].name = "energy" mp7.projection = "lambert" mp7.phase = Phase("!Ni", 220) with pytest.raises(AttributeError, match="For point groups without inversion"): _ = mp7.get_patterns(r2, self.detector, 5) # More than one PC is currently not supported so should fail d2 = kp.detectors.EBSDDetector( shape=(10, 10), px_size=50, pc=((0, 0, 15000), (0, 0, 15000)), convention="emsoft4", sample_tilt=70, ) with pytest.raises(NotImplementedError): _ = mp4.get_patterns(r2, d2, 5)