def get_pair_distances(structure: Structure, r_max: float = 8.0) -> List[dict]: """ Get pair distances from structure. The output will be a list of of dictionary, for example [{"specie": "Mo", "neighbors": {"S": [1.0, 2.0, ...], "Fe": [1.2, 3.0, ...]}}, {"specie": "Fe", "neighbors": {"Mo": [1.0, 3.0, ...]}}] it will be fairly easy to construct radial distribution func, etc from here Args: structure (Structure): pymatgen Structure r_max (float): maximum radius to consider Returns: """ index1, index2, _, distances = structure.get_neighbor_list(r_max) species = np.array([str(i.specie) for i in structure.sites]) res = [{"specie": i, "neighbors": {}} for i in species] neighbor_species = species[index2] tuples = np.array(list(zip(index1, neighbor_species)), dtype=[("index", "i4"), ("specie", "<U10")]) unique_tuples, indices = np.unique(tuples, return_inverse=True) for index, unique_tuple in enumerate(unique_tuples): res[unique_tuple[0]]["neighbors"][unique_tuple[1]] = distances[tuples == unique_tuple] return res
def _get_nbr_data( self, crystal: Structure) -> tuple[np.ndarray, np.ndarray, np.ndarray]: """Get neighbours for every site. Args: crystal (Structure): pymatgen Structure to get neighbours for Returns: tuple containing: - np.ndarray: Site indices - np.ndarray: Neighbour indices - np.ndarray: Distances between sites and neighbours """ self_idx, nbr_idx, _, nbr_dist = crystal.get_neighbor_list( self.radius, numerical_tol=1e-8) if self.max_num_nbr is not None: _self_idx, _nbr_idx, _nbr_dist = [], [], [] for i, g in groupby(zip(self_idx, nbr_idx, nbr_dist), key=lambda x: x[0]): s, n, d = zip(*sorted(g, key=lambda x: x[2])) _self_idx.extend(s[:self.max_num_nbr]) _nbr_idx.extend(n[:self.max_num_nbr]) _nbr_dist.extend(d[:self.max_num_nbr]) self_idx = np.array(_self_idx) nbr_idx = np.array(_nbr_idx) nbr_dist = np.array(_nbr_dist) return self_idx, nbr_idx, nbr_dist