def profile_simulation(): return ProfileSimulation( magnitudes=[ 0.31891931643691351, 0.52079306292509475, 0.6106839974876449, 0.73651261277849378, 0.80259601243613932, 0.9020400452156796, 0.95675794931074043, 1.0415861258501895, 1.0893168446141808, 1.1645286909108374, 1.2074090451670043, 1.2756772657476541, ], intensities=np.array( [ 100.0, 99.34619104, 64.1846346, 18.57137199, 28.84307971, 41.31084268, 23.42104951, 13.996264, 24.87559364, 20.85636003, 9.46737774, 5.43222307, ] ), hkls=[ {(1, 1, 1): 8}, {(2, 2, 0): 12}, {(3, 1, 1): 24}, {(4, 0, 0): 6}, {(3, 3, 1): 24}, {(4, 2, 2): 24}, {(3, 3, 3): 8, (5, 1, 1): 24}, {(4, 4, 0): 12}, {(5, 3, 1): 48}, {(6, 2, 0): 24}, {(5, 3, 3): 24}, {(4, 4, 4): 8}, ], )
def calculate_profile_data( self, structure, reciprocal_radius=1.0, minimum_intensity=1e-3, debye_waller_factors={}, ): """Calculates a one dimensional diffraction profile for a structure. Parameters ---------- structure : diffpy.structure.structure.Structure The structure for which to calculate the diffraction profile. reciprocal_radius : float The maximum radius of the sphere of reciprocal space to sample, in reciprocal angstroms. minimum_intensity : float The minimum intensity required for a diffraction peak to be considered real. Deals with numerical precision issues. debye_waller_factors : dict of str:value pairs Maps element names to their temperature-dependent Debye-Waller factors. Returns ------- diffsims.sims.diffraction_simulation.ProfileSimulation The diffraction profile corresponding to this structure and experimental conditions. """ wavelength = self.wavelength latt = structure.lattice # Obtain crystallographic reciprocal lattice points within range recip_latt = latt.reciprocal() spot_indices, _, spot_distances = get_points_in_sphere( recip_latt, reciprocal_radius ) ##spot_indicies is a numpy.array of the hkls allowd in the recip radius g_indices, multiplicities, g_hkls = get_intensities_params( recip_latt, reciprocal_radius ) i_hkl = get_kinematical_intensities( structure, g_indices, np.asarray(g_hkls), prefactor=multiplicities, scattering_params=self.scattering_params, debye_waller_factors=debye_waller_factors, ) if is_lattice_hexagonal(latt): # Use Miller-Bravais indices for hexagonal lattices. g_indices = ( g_indices[0], g_indices[1], -g_indices[0] - g_indices[1], g_indices[2], ) hkls_labels = ["".join([str(int(x)) for x in xs]) for xs in g_indices] peaks = {} for l, i, g in zip(hkls_labels, i_hkl, g_hkls): peaks[l] = [i, g] # Scale intensities so that the max intensity is 100. max_intensity = max([v[0] for v in peaks.values()]) x = [] y = [] hkls = [] for k in peaks.keys(): v = peaks[k] if v[0] / max_intensity * 100 > minimum_intensity and (k != "000"): x.append(v[1]) y.append(v[0]) hkls.append(k) y = np.asarray(y) / max(y) * 100 return ProfileSimulation(x, y, hkls)
def calculate_profile_data(self, structure, reciprocal_radius=1.0, magnitude_tolerance=1e-5, minimum_intensity=1e-3): """ Calculates a one dimensional diffraction profile for a structure. Parameters ---------- structure : Structure The structure for which to calculate the diffraction profile. reciprocal_radius : float The maximum radius of the sphere of reciprocal space to sample, in reciprocal angstroms. magnitude_tolerance : float The minimum difference between diffraction magnitudes in reciprocal angstroms for two peaks to be consdiered different. minimum_intensity : float The minimum intensity required for a diffraction peak to be considered real. Deals with numerical precision issues. Returns ------- diffsims.ProfileSimulation The diffraction profile corresponding to this structure and experimental conditions. """ max_r = reciprocal_radius wavelength = self.wavelength scattering_params = self.scattering_params latt = structure.lattice is_hex = is_lattice_hexagonal(latt) coeffs, fcoords, occus, dwfactors = get_vectorized_list_for_atomic_scattering_factors( structure, {}, scattering_params=scattering_params) # Obtain crystallographic reciprocal lattice points within range recip_latt = latt.reciprocal() spot_indicies, _, spot_distances = get_points_in_sphere( recip_latt, reciprocal_radius) peaks = {} mask = np.logical_not((np.any(spot_indicies, axis=1) == 0)) for hkl, g_hkl in zip(spot_indicies[mask], spot_distances[mask]): # Force miller indices to be integers. hkl = [int(round(i)) for i in hkl] d_hkl = 1 / g_hkl # Bragg condition # theta = asin(wavelength * g_hkl / 2) # s = sin(theta) / wavelength = 1 / 2d = |ghkl| / 2 (d = # 1/|ghkl|) s = g_hkl / 2 # Store s^2 since we are using it a few times. s2 = s**2 # Vectorized computation of g.r for all fractional coords and # hkl. g_dot_r = np.dot(fcoords, np.transpose([hkl])).T[0] # Highly vectorized computation of atomic scattering factors. fs = np.sum(coeffs[:, :, 0] * np.exp(-coeffs[:, :, 1] * s2), axis=1) dw_correction = np.exp(-dwfactors * s2) # Structure factor = sum of atomic scattering factors (with # position factor exp(2j * pi * g.r and occupancies). # Vectorized computation. f_hkl = np.sum(fs * occus * np.exp(2j * np.pi * g_dot_r) * dw_correction) # Intensity for hkl is modulus square of structure factor. i_hkl = (f_hkl * f_hkl.conjugate()).real # two_theta = degrees(2 * theta) if is_hex: # Use Miller-Bravais indices for hexagonal lattices. hkl = (hkl[0], hkl[1], -hkl[0] - hkl[1], hkl[2]) peaks[g_hkl] = [i_hkl, [tuple(hkl)], d_hkl] # Scale intensities so that the max intensity is 100. max_intensity = max([v[0] for v in peaks.values()]) x = [] y = [] hkls = [] d_hkls = [] for k in sorted(peaks.keys()): v = peaks[k] fam = get_unique_families(v[1]) if v[0] / max_intensity * 100 > minimum_intensity: x.append(k) y.append(v[0]) hkls.append(fam) d_hkls.append(v[2]) y = y / max(y) * 100 return ProfileSimulation(x, y, hkls)