def test_scattering_vector(self): Fe_fcc = Lattice.face_centered_cubic(0.287) # FCC iron hkl = HklPlane(2, 0, 0, Fe_fcc) Gc = hkl.scattering_vector() self.assertAlmostEqual(np.linalg.norm(Gc), 1 / hkl.interplanar_spacing()) Al_fcc = Lattice.face_centered_cubic(0.405) hkl = HklPlane(0, 0, 2, lattice=Al_fcc) Gc = hkl.scattering_vector() self.assertAlmostEqual(np.linalg.norm(Gc), 1 / hkl.interplanar_spacing())
def dct_projection(orientations, data, dif_grains, omega, lambda_keV, detector, lattice, include_direct_beam=True, att=5, verbose=True): '''Work in progress, will replace function in the microstructure module.''' full_proj = np.zeros(detector.size, dtype=np.float) lambda_nm = lambda_keV_to_nm(lambda_keV) omegar = omega * np.pi / 180 R = np.array([[np.cos(omegar), -np.sin(omegar), 0], [np.sin(omegar), np.cos(omegar), 0], [0, 0, 1]]) if include_direct_beam: # add the direct beam part by computing the radiograph of the sample without the diffracting grains data_abs = np.where(data > 0, 1, 0) for (gid, (h, k, l)) in dif_grains: mask_dif = (data == gid) data_abs[mask_dif] = 0 # remove this grain from the absorption proj = radiograph(data_abs, omega) add_to_image(full_proj, proj[::-1, ::-1] / att, np.array(full_proj.shape) // 2) # add diffraction spots X = np.array([1., 0., 0.]) / lambda_nm for (gid, (h, k, l)) in dif_grains: grain_data = np.where(data == gid, 1, 0) if np.sum(grain_data) < 1: print('skipping grain %d' % gid) continue local_com = np.array(ndimage.measurements.center_of_mass(grain_data, data)) print('local center of mass (voxel): {0}'.format(local_com)) g_center_mm = detector.pixel_size * (local_com - 0.5 * np.array(data.shape)) print('center of mass (voxel): {0}'.format(local_com - 0.5 * np.array(data.shape))) print('center of mass (mm): {0}'.format(g_center_mm)) # compute scattering vector gt = orientations[gid].orientation_matrix().transpose() # gt = micro.get_grain(gid).orientation_matrix().transpose() p = HklPlane(h, k, l, lattice) G = np.dot(R, np.dot(gt, p.scattering_vector())) K = X + G # position of the grain at this rotation g_pos_rot = np.dot(R, g_center_mm) pg = detector.project_along_direction(K, g_pos_rot) (up, vp) = detector.lab_to_pixel(pg) if verbose: print('\n* gid=%d, (%d,%d,%d) plane, angle=%.1f' % (gid, h, k, l, omega)) print('diffraction vector:', K) print('postion of the grain at omega=%.1f is ' % omega, g_pos_rot) print('up=%d, vp=%d for plane (%d,%d,%d)' % (up, vp, h, k, l)) data_dif = grain_data[ndimage.find_objects(data == gid)[0]] proj_dif = radiograph(data_dif, omega) # (Y, Z) coordinate system add_to_image(full_proj, proj_dif[::-1, ::-1], (up, vp), verbose) # (u, v) axes correspond to (-Y, -Z) return full_proj
def test_110_normal_monoclinic(self): """Testing (110) plane normal in monoclinic crystal structure. This test comes from http://www.mse.mtu.edu/~drjohn/my3200/stereo/sg5.html corrected for a few errors in the html page. In this test, the lattice is defined with the c-axis aligned with the Z direction of the Cartesian frame. """ Mg2Si = Lattice.from_parameters(1.534, 0.405, 0.683, 90., 106., 90., x_aligned_with_a=False) a = Mg2Si.matrix[0] b = Mg2Si.matrix[1] c = Mg2Si.matrix[2] self.assertAlmostEqual(a[0], 1.475, 3) self.assertAlmostEqual(a[1], 0., 3) self.assertAlmostEqual(a[2], -0.423, 3) self.assertAlmostEqual(b[0], 0., 3) self.assertAlmostEqual(b[1], 0.405, 3) self.assertAlmostEqual(b[2], 0., 3) self.assertAlmostEqual(c[0], 0., 3) self.assertAlmostEqual(c[1], 0., 3) self.assertAlmostEqual(c[2], 0.683, 3) p = HklPlane(1, 1, 1, Mg2Si) Gc = p.scattering_vector() self.assertAlmostEqual(Gc[0], 1.098, 3) self.assertAlmostEqual(Gc[1], 2.469, 3) self.assertAlmostEqual(Gc[2], 1.464, 3) self.assertAlmostEqual(p.interplanar_spacing(), 0.325, 3) Ghkl = np.dot(Mg2Si.matrix, Gc) self.assertEqual(Ghkl[0], 1.) # h self.assertEqual(Ghkl[1], 1.) # k self.assertEqual(Ghkl[2], 1.) # l
def dct_projection(self, omega, include_direct_beam=True, att=5): """Function to compute a full DCT projection at a given omega angle. :param float omega: rotation angle in degrees. :param bool include_direct_beam: flag to compute the transmission through the sample. :param float att: an attenuation factor used to limit the gray levels in the direct beam. :return: the dct projection as a 2D numpy array """ if len(self.reflections) == 0: print( 'empty list of reflections, you should run the setup function first' ) return None grain_ids = self.exp.get_sample().get_grain_ids() detector = self.exp.get_active_detector() lambda_keV = self.exp.source.max_energy lattice = self.exp.get_sample().get_material() index = np.argmax(self.omegas > omega) dif_grains = self.reflections[ index - 1] # grains diffracting between omegas[index - 1] and omegas[index] # intialize image result full_proj = np.zeros(detector.get_size_px(), dtype=np.float) lambda_nm = lambda_keV_to_nm(lambda_keV) omegar = omega * np.pi / 180 R = np.array([[np.cos(omegar), -np.sin(omegar), 0], [np.sin(omegar), np.cos(omegar), 0], [0, 0, 1]]) if include_direct_beam: # add the direct beam part by computing the radiograph of the sample without the diffracting grains data_abs = np.where(grain_ids > 0, 1, 0) for (gid, (h, k, l)) in dif_grains: mask_dif = (grain_ids == gid) data_abs[mask_dif] = 0 # remove this grain from the absorption proj = radiograph( data_abs, omega )[:, ::-1] # (u, v) axes correspond to (Y, -Z) for DCT detector add_to_image(full_proj, proj / att, np.array(full_proj.shape) // 2) # add diffraction spots X = np.array([1., 0., 0.]) / lambda_nm for (gid, (h, k, l)) in dif_grains: grain_data = np.where(grain_ids == gid, 1, 0) if np.sum(grain_data) < 1: print('skipping grain %d' % gid) continue local_com = np.array( ndimage.measurements.center_of_mass(grain_data, grain_ids)) print('local center of mass (voxel): {0}'.format(local_com)) g_center_mm = detector.get_pixel_size() * ( local_com - 0.5 * np.array(grain_ids.shape)) print('center of mass (voxel): {0}'.format( local_com - 0.5 * np.array(grain_ids.shape))) print('center of mass (mm): {0}'.format(g_center_mm)) # compute scattering vector gt = self.exp.get_sample().get_microstructure().get_grain( gid).orientation_matrix().transpose() p = HklPlane(h, k, l, lattice) G = np.dot(R, np.dot(gt, p.scattering_vector())) K = X + G # position of the grain at this rotation angle g_pos_rot = np.dot(R, g_center_mm) pg = detector.project_along_direction(K, g_pos_rot) up, vp = detector.lab_to_pixel(pg)[0] if self.verbose: print('\n* gid=%d, (%d,%d,%d) plane, angle=%.1f' % (gid, h, k, l, omega)) print('diffraction vector:', K) print('postion of the grain at omega=%.1f is ' % omega, g_pos_rot) print('up=%d, vp=%d for plane (%d,%d,%d)' % (up, vp, h, k, l)) data_dif = grain_data[ndimage.find_objects(grain_ids == gid)[0]] proj_dif = radiograph(data_dif, omega) # (Y, Z) coordinate system add_to_image(full_proj, proj_dif[:, ::-1], (up, vp), self.verbose) # (u, v) axes correspond to (Y, -Z) return full_proj