def test_from_cod(self): """ Test building a Crystal object from the COD """ # revision = None and latest revision should give the same Crystal c = Crystal.from_cod(1521124) c2 = Crystal.from_cod(1521124, revision=176429) self.assertEqual(c, c2)
def gen_xyz(file, n=[0, 0, 1], rep=[1, 1, 1], pad=0, xyz='', **kwargs): ''' convert cif file into autoslic .xyz input file - file : cif_file - rep : super cell repeat - n : reorient of the z axis into n - pad : amount of padding on each side (in unit of super cell size) ''' if isinstance(file, str): tail = ''.join(np.array(n, dtype=str)) + '.xyz' if file.split('.')[-1] == 'cif': crys = Crystal.from_cif(file) if not xyz: xyz = file.replace('.cif', tail) elif sum(np.array(list(Crystal.builtins)) == file): crys = Crystal.from_database(file) if not xyz: xyz = file + tail lat_vec = np.array(crys.lattice_vectors) lat_params = crys.lattice_parameters[:3] pattern = np.array([[a.atomic_number] + list(a.coords_cartesian) + [a.occupancy, 1.0] for a in crys.atoms]) else: if not xyz: raise Exception('xyz filename required') pattern = file pattern, lat = make_xyz(xyz, pattern, lat_vec, lat_params, n=n, pad=pad, rep=rep, **kwargs) npy_file = xyz.replace('.xyz', '.npy') np.save(npy_file, [lat, pattern]) print(colors.green + 'binary coords file saved :' + colors.yellow + npy_file + colors.black)
def test_equality(self): """ Test that __eq__ works as expected """ c1 = Crystal.from_database("Pu-alpha") c2 = deepcopy(c1) self.assertEqual(c1, c2) c3 = Crystal.from_database("Pu-epsilon") self.assertNotEqual(c1, c3)
def test_equality(): """Test that __eq__ works as expected""" c1 = Crystal.from_database("Pu-alpha") c2 = deepcopy(c1) assert c1 == c2 c3 = Crystal.from_database("Pu-epsilon") assert c1 != c3
def import_crys(file): if file.split('.')[-1] == 'cif': crys = Crystal.from_cif(file) elif sum(np.array(list(Crystal.builtins)) == file): crys = Crystal.from_database(file) else: raise Exception('cannot import %s' % file) return crys
def test_reciprocal_matrix1(self): c = Crystal("quartz") c.lattice_angles_deg = np.fromstring("90.0 90.0 120.0", sep=' ') c.lattice_lengths = np.fromstring("4.913 4.913 5.400", sep=' ') c.calculate_reciprocal() isaw_rec = np.fromstring(""" 1.278890 0.000000 0.000000 0.738367 1.476735 -0.000000 -0.000000 -0.000000 1.163553""", sep=' ').reshape(3,3) assert np.allclose(isaw_rec, c.reciprocal_lattice), "Reciprocal lattice of %s matches ISAW lattice." % c.name
def test_reciprocal_matrix2(self): c = Crystal("oxalic acid") c.lattice_angles_deg = np.fromstring("90.0 103.2 90.0", sep=' ') c.lattice_lengths = np.fromstring("6.094 3.601 11.915", sep=' ') c.calculate_reciprocal() isaw_rec = np.fromstring(""" 1.031045 0.000000 0.000000 -0.000000 1.744845 0.000000 0.241829 -0.000000 0.54164""", sep=' ').reshape(3,3) assert np.allclose(isaw_rec, c.reciprocal_lattice), "Reciprocal lattice of %s matches ISAW lattice." % c.name
def __init__(self, unitCell, latticeVectors): self._unitCell = [Atom(atom[0], coords=atom[1]) for atom in unitCell] Crystal.__init__(self, self._unitCell, latticeVectors) self.atomsPerUnitCell = len(unitCell) self.atomicWeights = [atom.mass for atom in self._unitCell] self.atomLabels = [ f'{inx}_{atom.element}' for atom, inx in zip(self._unitCell, range(self.atomsPerUnitCell)) ]
def test_reciprocal_matrix4(self): c = Crystal("Natrolite(conventional orthorhombic cell)") c.lattice_angles_deg = np.fromstring("90.0 90.0 90.0", sep=' ') c.lattice_lengths = np.fromstring("18.328 18.585 6.597", sep=' ') c.calculate_reciprocal() isaw_rec = np.fromstring(""" 0.342819 0.000000 0.000000 -0.000000 0.338078 0.000000 -0.000000 -0.000000 0.952431 """, sep=' ').reshape(3,3) #print c.reciprocal_lattice, "\n\n\n" assert np.allclose(isaw_rec, c.reciprocal_lattice, atol=1e-5), "Reciprocal lattice of %s matches ISAW lattice." % c.name
def test_reciprocal_matrix3(self): c = Crystal("Natrolite(reduced cell)") c.lattice_angles_deg = np.fromstring("83.5 70.5 70.2", sep=' ') c.lattice_lengths = np.fromstring("6.601 9.739 9.893", sep=' ') c.calculate_reciprocal() isaw_rec = np.fromstring(""" 0.951854 -0.000000 0.000000 -0.342876 0.685738 0.000000 -0.336898 0.000033 0.673719 """, sep=' ').reshape(3,3) #print c.reciprocal_lattice, "\n\n\n" assert np.allclose(isaw_rec, c.reciprocal_lattice, atol=1e-3), "Reciprocal lattice of %s matches ISAW lattice." % c.name
def test_ase_atoms_back_and_forth(name): """ Test conversion to and from ase Atoms """ crystal = Crystal.from_database(name) to_ase = crystal.to_ase() crystal2 = Crystal.from_ase(to_ase) # ase has different handling of coordinates which can lead to # rounding beyond 1e-3. Therefore, we cannot compare directly sets # assertSetEqual(set(crystal), set(crystal2)) assert len(crystal) == len(crystal2)
def test_cif_writer_idempotence(name): """ Test that conversion to CIF of a structure loaded from CIF is idempotent. """ # Testing on all built-in structure assures us that corner cases # are taken care of. cryst = Crystal.from_database(name) with tempfile.TemporaryDirectory() as temp_dir: f = Path(temp_dir) / "temp.cif" cryst.to_cif(f) cryst2 = Crystal.from_cif(f) assert cryst == cryst2
def test_powdersim_peak_alignment(): """ Test that the diffraction peaks align with what is expected. """ crystal = Crystal.from_database("C") for reflection in [(0, 1, 1), (1, 2, 0), (-1, 2, 0)]: qknown = np.linalg.norm(crystal.scattering_vector((0, 1, 1))) # Range of scattering vectors is tightly centered around a particular reflection # So that the maximum of the diffraction pattern MUST be at reflection (010) q = np.linspace(qknown - 0.1, qknown + 0.1, 256) pattern = powdersim(Crystal.from_database("C"), q) assert abs(q[np.argmax(pattern)] - qknown) < q[1] - q[0]
def test_idempotence(self): """ Test that conversion to CIF of a structure loaded from CIF is idempotent. """ # Testing on all built-in structure assures us that corner cases # are taken care of. for name in Crystal.builtins: with self.subTest(f"CIF idempotence {name}"): cryst = Crystal.from_database(name) with tempfile.TemporaryDirectory() as temp_dir: f = Path(temp_dir) / "temp.cif" cryst.to_cif(f) cryst2 = Crystal.from_cif(f) self.assertEqual(cryst, cryst2)
def test_constructors(self): """ Test Supercell constructors for varyous 'builtin' structures """ for name in islice(Crystal.builtins, 20): with self.subTest(name): s = Crystal.from_database(name).supercell(2, 2, 2) self.assertEqual(len(s), 8 * len(s.crystal))
def load_datagrid_sim(folder, arr, x): ''' Load cif files from folder into ase crystal objects, simulate crystal diffraction and represent data in timeseries Args: folder (string): Where we load the data from. arr (list): List of cif filenames in folder. x (nparray): representation of 1/angström for powder simulation. Returns: fd (datagrid): representation of intensity values and 1/angström values in datagrid object. ''' filename_arr = [] crys_arr = [] for file in arr: filename = os.sep.join([folder, file]) filename_arr.append(file) crys = read(filename) crys = Crystal.from_ase(crys) diff = powdersim(crys, x) diff_norm = diff / diff.max() crys_arr.append(diff_norm) crys_arr = np.array(crys_arr) print(crys_arr) return crys_arr
def test_side_effects(): """ Test that mesh arrays are not written to in pelectrostatic """ crystal = Crystal.from_database("C") xx, yy = np.meshgrid(np.linspace(-10, 10, 32), np.linspace(-10, 10, 32)) xx.setflags(write=False) yy.setflags(write=False) potential = pelectrostatic(crystal, xx, yy)
def test_return_shape(): """ Test that the return shape of pelectrostatic is the same as input arrays """ crystal = Crystal.from_database("C") xx, yy = np.meshgrid(np.linspace(-10, 10, 32), np.linspace(-10, 10, 32)) potential = pelectrostatic(crystal, xx, yy) assert xx.shape == potential.shape
def test_simulation_3_peaks(self): """ Test calibration from simulation, down to 1% error . Peaks (200) and (220) from monoclinic VO2 are used, """ s = np.linspace(0.11, 0.8, 1024) q = 4 * np.pi * s c = Crystal.from_database("vo2-m1") I = powdersim(c, s) peak1 = (2, 0, 0) Gx1, Gy1, Gz1 = c.scattering_vector(peak1) q1 = np.sqrt(Gx1 ** 2 + Gy1 ** 2 + Gz1 ** 2) arr_index1 = np.argmin(np.abs(q - q1)) peak2 = (2, 2, 0) Gx2, Gy2, Gz2 = c.scattering_vector(peak2) q2 = np.sqrt(Gx2 ** 2 + Gy2 ** 2 + Gz2 ** 2) arr_index2 = np.argmin(np.abs(q - q2)) peak3 = (3, 0, -2) Gx2, Gy2, Gz2 = c.scattering_vector(peak3) q3 = np.sqrt(Gx2 ** 2 + Gy2 ** 2 + Gz2 ** 2) arr_index3 = np.argmin(np.abs(q - q3)) calibrated = powder_calq( I, c, peak_indices=(arr_index1, arr_index2, arr_index3), miller_indices=(peak1, peak2, peak3), ) self.assertTupleEqual(I.shape, calibrated.shape) self.assertTrue(np.allclose(q, calibrated, rtol=0.01))
def pow_sim(path1): filename1 = Path(path1).name #filename2 = Path(path2).name # load cif file to an ase object cry1 = read(path1) #cry2 = read(path2) # crystal object for powdersim in skued lib crys1 = Crystal.from_ase(cry1) #crys2 = Crystal.from_ase(cry2) # powder simulation with range of q q = np.linspace(1, 7, 512) diff1 = powdersim(crys1, q, fwhm_g = 0.01, fwhm_l=0.03) #diff2 = powdersim(crys2, q) # matplotlib config plt.figure() plt.plot(q, diff1/diff1.max(), '-b', label=filename1, alpha= 0.3) #plt.plot(q, diff2/diff2.max(), '-r', label=filename2, alpha= 0.3) plt.legend() plt.xlim([q.min(), q.max()]) plt.xlabel('$q (1/\AA)$') plt.ylabel('Diffracted intensity (A.u.)') plt.title('Crystal diffraction ') plt.show()
def test_reciprocal_symmetry_operations(name): """Test that the reciprocal symmetry operations output makes sense""" identity = np.eye(4) c = Crystal.from_database(name) symops = c.reciprocal_symmetry_operations() assert np.allclose(identity, symops[0])
def setUp(self): self.crystal = Crystal.from_database("C") self.reflections = list(combinations_with_replacement(range(-3, 4), 3)) self.intensities = [ np.abs(structure_factor(self.crystal, *reflection))**2 for reflection in self.reflections ]
def test_from_cod_new_dir(): """Test that a cache dir is created by Crystal.from_cod""" with tempfile.TemporaryDirectory() as temp_dir: download_dir = Path(temp_dir) / "test_cod" assert not download_dir.exists() c = Crystal.from_cod(1521124, download_dir=download_dir) assert download_dir.exists()
def test_from_cod_new_dir(self): """ Test that a cache dir is created by Crystal.from_cod """ with tempfile.TemporaryDirectory() as temp_dir: download_dir = Path(temp_dir) / "test_cod" self.assertFalse(download_dir.exists()) c = Crystal.from_cod(1521124, download_dir=download_dir) self.assertTrue(download_dir.exists())
def load_datagrid_sim(folder, arr, x): ''' Load cif files from folder into ase crystal objects, simulate crystal diffraction and represent data in timeseries Args: folder (string): Where we load the data from. arr (list): List of cif filenames in folder. x (nparray): representation of 1/angström for powder simulation. Returns: fd (datagrid): representation of intensity values and 1/angström values in datagrid object. ''' filename_arr = [] crys_arr = [] for file in arr: filename = os.sep.join([folder, file]) filename_arr.append(file) crys = read(filename) crys = Crystal.from_ase(crys) diff = powdersim(crys, x, fwhm_l=50) diff_norm = diff / diff.max() crys_arr.append(diff_norm) crys_arr = np.array(crys_arr) fd = FDataGrid(crys_arr, x, dataset_name='Diffraction Curves', argument_names=[r'$q (1/\AA)$'], coordinate_names=['Diffracted intensity (A.u.)']) print(fd) return fd
def Li_rots(): crys = Crystal.from_database('Li') coords = np.array([a.coords_cartesian for a in crys.atoms]) # files = rcc.rotate_xyz(crys,Nrot=8,name='dat/Lithium/rots/',opt='p') files = rcc.orient_crystal(coords,ez=[0,0,1],n_u=[0,,1]) for file in files[:4] : rcc.show_grid(file,title=file,equal=1)#,xyTicks=3.49,xylims=[0,100,0,100])
def test_primitive_for_builtins(self): """ Test that all built-in crystal have a primitive cell """ for name in Crystal.builtins: with self.subTest(name): c = Crystal.from_database(name) prim = c.primitive(symprec=0.1) self.assertLessEqual(len(prim), len(c))
def get_pendulossung(name='Si', miller=[0, 0, 0], keV=200, opt='p'): ''' give the theorertical 2-beam approximation Pendullosung thickness - `name` : compound - `miller` : [h,k,l] - `keV` : wavelength (keV) RETURN - xi : Pendullosung thickness (A) ''' # compute structure factor from crystals import Crystal crys = Crystal.from_database(name) lat_vec = crys.reciprocal_vectors pattern = np.array( [list(a.coords_fractional) + [a.atomic_number] for a in crys.atoms]) hkl, Fhkl = structure_factor3D(pattern, lat_vec, hklMax=max(miller), sym=0, v='') ax, by, cz = crys.lattice_parameters[:3] Vcell = crys.volume # compute Pendullosung h, k, l = miller Ug, K = np.abs(Fhkl[h, k, l]) / Vcell, 1 / scatf.wavelength(keV) xi = K / Ug if 'p' in opt: print(green + "\tPendullosung thickness " + name + '[%d%d%d]' % (h, k, l) + black) print('%-5s= %.2f\n%-5s= %.2f\n%-5s= %.2f' % ('K', K, 'Ug', Ug, 'xi', xi)) return xi
def import_cif(file, xyz='', n=[0, 0, 1], rep=[1, 1, 1], pad=0, dopt='s', lfact=1.0, tail=''): ''' convert cif file into autoslic .xyz input file - file : cif_file - rep : super cell repeat - n : reorient of the z axis into n - pad : amount of padding on each side (in unit of super cell size) ''' crys = Crystal.from_cif(file) lat_vec = np.array(crys.lattice_vectors) lat_params = crys.lattice_parameters[:3] pattern = np.array([[a.atomic_number] + list(lfact * a.coords_cartesian) + [a.occupancy, 1.0] for a in crys.atoms]) if xyz: make_xyz(xyz, pattern, lat_vec, lat_params, n=n, pad=pad, rep=rep, fmt='%.4f', dopt=dopt) pattern[:, 1:4] = rcc.orient_crystal(pattern[:, 1:4], n_u=n) #,lat_params #pattern,crys # file return pattern
def test_substructure_preservation(): """Test that initializing a crystal with substructures preserves the substructures""" atoms = [Atom("Ag", [0, 0, 0]), Atom("Ag", [1, 1, 1])] substructures = [AtomicStructure(atoms=[Atom("U", [0, 0, 0])])] c = Crystal(unitcell=atoms + substructures, lattice_vectors=np.eye(3)) assert len(c) == 3 assert substructures[0] in c.substructures
def test_builtins(self): """ Test that all names in Crystal.builtins build without errors, and that Crystal.source is correctly recorded. """ for name in Crystal.builtins: with self.subTest(name): c = Crystal.from_database(name) self.assertIn(name, c.source)
def test_substructure_preservation(self): """ Test that initializing a crystal with substructures preserves the substructures """ atoms = [Atom("Ag", [0, 0, 0]), Atom("Ag", [1, 1, 1])] substructures = [AtomicStructure(atoms=[Atom("U", [0, 0, 0])])] c = Crystal(unitcell=atoms + substructures, lattice_vectors=np.eye(3)) self.assertEqual(len(c), 3) self.assertIn(substructures[0], c.substructures)
def test_chemical_composition_add_to_unity(self): """ Test that AtomicStructure.chemical_composition always adds up to 1 """ # Faster to create a large atomic structure from a Crystal object # Testing for 10 crystal structures only for name in islice(Crystal.builtins, 10): with self.subTest("Chemical composition: " + name): structure = AtomicStructure(atoms=Crystal.from_database(name)) self.assertAlmostEqual(sum(structure.chemical_composition.values()), 1)
def test_back_and_forth(self): """ Test conversion to and from ase Atoms """ to_ase = self.crystal.to_ase() crystal2 = Crystal.from_ase(to_ase) # ase has different handling of coordinates which can lead to # rounding beyond 1e-3. Therefore, we cannot compare directly sets # self.assertSetEqual(set(self.crystal), set(crystal2)) self.assertEqual(len(self.crystal), len(crystal2))
def dont_test_compare_ubs(self): """ISAWev does not take into account the goniometer angles when outputting the UB matrix file. ISAW does. This compares the U and B matrices obtained from both. """ #0, np.pi/4, 0 c = Crystal("oxalic acid") c.read_ISAW_ubmatrix_file("data/TOPAZ_1204.mat", angles=[0, np.pi/4, 0]) c2 = Crystal("oxalic acid from EV") c2.read_ISAW_ubmatrix_file("data/TOPAZ_1204_ev.mat", angles=[0, 0, 0]) assert np.allclose(c.reciprocal_lattice, c2.reciprocal_lattice, atol=0.05), "B matrices match, roughly. %s vs %s" % (c.reciprocal_lattice, c2.reciprocal_lattice) assert np.allclose(c.u_matrix, c2.u_matrix, atol=0.02), "U matrices match, roughly. %s vs %s" % (c.u_matrix, c2.u_matrix) print "\n\n\n" print c.u_matrix print c2.u_matrix