def test_k3_peaks_periodic(self): """Tests that the final spectra does not change when translating atoms in a periodic cell. This is not trivially true unless the weight of angles is weighted according to the cell indices of the involved three atoms. Notice that the values of the geometry and weight functions are not equal before summing them up in the final graph. """ scale = 0.85 desc = MBTR( species=["H"], k3={ "geometry": {"function": "angle"}, "grid": {"min": 0, "max": 180, "sigma": 5, "n": 2000}, "weighting": {"function": "exp", "scale": scale, "cutoff": 1e-3}, }, normalize_gaussians=False, periodic=True, flatten=True, sparse=False ) atoms = Atoms( cell=[ [10, 0, 0], [0, 10, 0], [0, 0, 10], ], symbols=3*["H"], scaled_positions=[ [0.05, 0.40, 0.5], [0.05, 0.60, 0.5], [0.95, 0.5, 0.5], ], pbc=True ) features = desc.create(atoms)[0, :] x = desc.get_k3_axis() # Calculate assumed locations and intensities. assumed_locs = np.array([45, 90]) dist = 2+2*np.sqrt(2) # The total distance around the three atoms weight = np.exp(-scale*dist) assumed_ints = np.array([4*weight, 2*weight]) assumed_ints /= 2 # The periodic distances ar halved because they belong to different cells # Check the H-H-H peaks hhh_feat = features[desc.get_location(("H", "H", "H"))] hhh_peak_indices = find_peaks(hhh_feat, prominence=0.01)[0] hhh_peak_locs = x[hhh_peak_indices] hhh_peak_ints = hhh_feat[hhh_peak_indices] self.assertTrue(np.allclose(hhh_peak_locs, assumed_locs, rtol=0, atol=1e-1)) self.assertTrue(np.allclose(hhh_peak_ints, assumed_ints, rtol=0, atol=1e-1)) # Check that everything else is zero features[desc.get_location(("H", "H", "H"))] = 0 self.assertEqual(features.sum(), 0)
def test_k2_peaks_periodic(self): """Tests the correct peak locations and intensities are found for the k=2 term in periodic systems. """ atoms = Atoms( cell=[ [10, 0, 0], [10, 10, 0], [10, 0, 10], ], symbols=["H", "C"], scaled_positions=[ [0.1, 0.5, 0.5], [0.9, 0.5, 0.5], ] ) desc = MBTR( species=["H", "C"], k2={ "geometry": {"function": "distance"}, "grid": {"min": 0, "max": 10, "sigma": 0.5, "n": 1000}, "weighting": {"function": "exp", "scale": 0.8, "cutoff": 1e-3}, }, normalize_gaussians=False, periodic=True, flatten=True, sparse=False ) features = desc.create(atoms)[0, :] x = desc.get_k2_axis() # Calculate assumed locations and intensities. assumed_locs = np.array([2, 8]) assumed_ints = np.exp(-0.8*np.array([2, 8])) assumed_ints[0] *= 2 # There are two periodic distances at 2Å assumed_ints[0] /= 2 # The periodic distances ar halved because they belong to different cells # Check the H-C peaks hc_feat = features[desc.get_location(("H", "C"))] hc_peak_indices = find_peaks(hc_feat, prominence=0.001)[0] hc_peak_locs = x[hc_peak_indices] hc_peak_ints = hc_feat[hc_peak_indices] self.assertTrue(np.allclose(hc_peak_locs, assumed_locs, rtol=0, atol=1e-2)) self.assertTrue(np.allclose(hc_peak_ints, assumed_ints, rtol=0, atol=1e-2)) # Check that everything else is zero features[desc.get_location(("H", "C"))] = 0 self.assertEqual(features.sum(), 0)
def test_k3_peaks_finite(self): """Tests that all the correct angles are present in finite systems. There should be n*(n-1)*(n-2)/2 unique angles where the division by two gets rid of duplicate angles. """ desc = MBTR( species=["H", "O"], k3={ "geometry": {"function": "angle"}, "grid": {"min": -10, "max": 180, "sigma": 5, "n": 2000}, "weighting": {"function": "unity"}, }, normalize_gaussians=False, periodic=False, flatten=True, sparse=False ) features = desc.create(H2O)[0, :] x = desc.get_k3_axis() # Check the H-H-O peaks hho_assumed_locs = np.array([38]) hho_assumed_ints = np.array([2]) hho_feat = features[desc.get_location(("H", "H", "O"))] hho_peak_indices = find_peaks(hho_feat, prominence=0.5)[0] hho_peak_locs = x[hho_peak_indices] hho_peak_ints = hho_feat[hho_peak_indices] self.assertTrue(np.allclose(hho_peak_locs, hho_assumed_locs, rtol=0, atol=5e-2)) self.assertTrue(np.allclose(hho_peak_ints, hho_assumed_ints, rtol=0, atol=5e-2)) # Check the H-O-H peaks hoh_assumed_locs = np.array([104]) hoh_assumed_ints = np.array([1]) hoh_feat = features[desc.get_location(("H", "O", "H"))] hoh_peak_indices = find_peaks(hoh_feat, prominence=0.5)[0] hoh_peak_locs = x[hoh_peak_indices] hoh_peak_ints = hoh_feat[hoh_peak_indices] self.assertTrue(np.allclose(hoh_peak_locs, hoh_assumed_locs, rtol=0, atol=5e-2)) self.assertTrue(np.allclose(hoh_peak_ints, hoh_assumed_ints, rtol=0, atol=5e-2)) # Check that everything else is zero features[desc.get_location(("H", "H", "O"))] = 0 features[desc.get_location(("H", "O", "H"))] = 0 self.assertEqual(features.sum(), 0)
def test_k2_peaks_finite(self): """Tests the correct peak locations and intensities are found for the k=2 term in finite systems. """ desc = MBTR( species=[1, 8], k2={ "geometry": {"function": "distance"}, "grid": {"min": -1, "max": 3, "sigma": 0.5, "n": 1000}, "weighting": {"function": "unity"}, }, normalize_gaussians=False, periodic=False, flatten=True, sparse=False ) features = desc.create(H2O)[0, :] pos = H2O.get_positions() x = desc.get_k2_axis() # Check the H-H peaks hh_feat = features[desc.get_location(("H", "H"))] hh_peak_indices = find_peaks(hh_feat, prominence=0.5)[0] hh_peak_locs = x[hh_peak_indices] hh_peak_ints = hh_feat[hh_peak_indices] self.assertTrue(np.allclose(hh_peak_locs, [np.linalg.norm(pos[0] - pos[2])], rtol=0, atol=1e-2)) self.assertTrue(np.allclose(hh_peak_ints, [1], rtol=0, atol=1e-2)) # Check the O-H peaks ho_feat = features[desc.get_location(("H", "O"))] ho_peak_indices = find_peaks(ho_feat, prominence=0.5)[0] ho_peak_locs = x[ho_peak_indices] ho_peak_ints = ho_feat[ho_peak_indices] self.assertTrue(np.allclose(ho_peak_locs, np.linalg.norm(pos[0] - pos[1]), rtol=0, atol=1e-2)) self.assertTrue(np.allclose(ho_peak_ints, [2], rtol=0, atol=1e-2)) # Check that everything else is zero features[desc.get_location(("H", "H"))] = 0 features[desc.get_location(("H", "O"))] = 0 self.assertEqual(features.sum(), 0)
def test_k1_peaks_finite(self): """Tests the correct peak locations and intensities are found for the k=1 term. """ desc = MBTR( species=[1, 8], k1={ "geometry": {"function": "atomic_number"}, "grid": {"min": 0, "max": 9, "sigma": 0.5, "n": 1000} }, normalize_gaussians=False, periodic=False, flatten=True, sparse=False ) features = desc.create(H2O)[0, :] x = desc.get_k1_axis() # Check the H peaks h_feat = features[desc.get_location(("H"))] h_peak_indices = find_peaks(h_feat, prominence=1)[0] h_peak_locs = x[h_peak_indices] h_peak_ints = h_feat[h_peak_indices] self.assertTrue(np.allclose(h_peak_locs, [1], rtol=0, atol=1e-2)) self.assertTrue(np.allclose(h_peak_ints, [2], rtol=0, atol=1e-2)) # Check the O peaks o_feat = features[desc.get_location(("O"))] o_peak_indices = find_peaks(o_feat, prominence=1)[0] o_peak_locs = x[o_peak_indices] o_peak_ints = o_feat[o_peak_indices] self.assertTrue(np.allclose(o_peak_locs, [8], rtol=0, atol=1e-2)) self.assertTrue(np.allclose(o_peak_ints, [1], rtol=0, atol=1e-2)) # Check that everything else is zero features[desc.get_location(("H"))] = 0 features[desc.get_location(("O"))] = 0 self.assertEqual(features.sum(), 0)
) # Create from ase.build import molecule water = molecule("H2O") # Create MBTR output for the system mbtr_water = mbtr.create(water) print(mbtr_water) print(mbtr_water.shape) # Locations # The locations of specific element combinations can be retrieved like this. h_loc = mbtr.get_location(("H")) ho_loc = mbtr.get_location(("H", "O")) hoh_loc = mbtr.get_location(("H", "O", "H")) # These locations can be directly used to slice the corresponding part from an # MBTR output for e.g. plotting. mbtr_water[0, h_loc] mbtr_water[0, ho_loc] mbtr_water[0, hoh_loc] # Visualization import ase.data from ase.build import bulk import matplotlib.pyplot as mpl # The MBTR-object is configured with flatten=False so that we can easily