def extrema_coords(volumetric_data: VolumetricData, find_min: bool, params: VolumetricDataAnalyzeParams) -> DataFrame: result = ChargeDensityAnalyzer(chgcar=volumetric_data) result.get_local_extrema(threshold_frac=params.threshold_frac, threshold_abs=params.threshold_abs, find_min=find_min) if params.min_dist: # Remove sites near host atoms. result.remove_collisions(params.min_dist) if params.tol: try: # Cluster interstitials that are too close together using a tol. result.cluster_nodes(tol=params.tol) except ValueError: # error raised when only a single local extreme point. pass if params.radius: result.sort_sites_by_integrated_chg(r=params.radius) result = result.extrema_df if "avg_charge_den" in result.columns: result.rename(columns={'avg_charge_den': 'ave_value'}, inplace=True) result.rename(columns={'Charge Density': 'value'}, inplace=True) logger.info("\n" + result.__str__()) return result
def test_remove_collisions(self): ca = ChargeDensityAnalyzer(self.chg_FePO4) ca.get_local_extrema(threshold_frac=0) ca.remove_collisions() # should not trigger error self.assertEqual(len(ca.extrema_df), 0) self.ca_FePO4.get_local_extrema(find_min=False, threshold_frac=1.0) self.ca_FePO4.remove_collisions(min_dist=0.5) self.assertEqual(len(self.ca_FePO4.extrema_df), 0)
def interstitials_from_volumetric_data(volumetric_data: VolumetricData, find_min: bool = True, threshold_frac: float = None, threshold_abs: float = None, min_dist: float = 0.5, tol: float = 0.5, radius: float = 0.4) -> None: cda = ChargeDensityAnalyzer(chgcar=volumetric_data) cda.get_local_extrema(threshold_frac=threshold_frac, threshold_abs=threshold_abs, find_min=find_min) cda.sort_sites_by_integrated_chg(r=radius) # Remove sites near host atoms. cda.remove_collisions(min_dist) # Cluster interstitials that are too close together using a tol. try: cda.cluster_nodes(tol=tol) except ValueError: # error raised when only a single local extreme point. pass print(cda.extrema_df) structure: Structure = volumetric_data.structure.copy() start_index = len(structure) end_index = len(structure) + len(cda.extrema_coords) interstitial_indices = [i for i in range(start_index, end_index)] for coords in cda.extrema_coords: structure.append(Element.H, coords) symmetrizer = StructureSymmetrizer(structure) equiv_atoms = symmetrizer.spglib_sym_data["equivalent_atoms"] print(f"Host symmetry {symmetrizer.spglib_sym_data['international']}") print("++ Inequivalent indices and site symmetries ++") orig_num_atoms = len(volumetric_data.structure) structure_for_visualize: Structure = volumetric_data.structure.copy() for i, ii in enumerate(interstitial_indices): if ii == equiv_atoms[ii]: idx = orig_num_atoms + i coords = structure[idx].frac_coords def element(): for z in range(1, 100): e = Element.from_Z(z) if e not in structure_for_visualize.composition: yield e structure_for_visualize.append(next(element()), coords) idx_coords = \ f"{i:>3} {coords[0]:8.4f} {coords[1]:8.4f} {coords[2]:8.4f}" print(idx_coords, symmetrizer.spglib_sym_data["site_symmetry_symbols"][ii]) structure_for_visualize.to(filename="POSCAR-w-interstitials")
def test_cluster_nodes(self): ca = ChargeDensityAnalyzer(self.chg_FePO4) ca.get_local_extrema() ca.cluster_nodes(tol=20) self.assertEqual(len(ca.extrema_df), 1)
class ChgDenAnalyzerTest(unittest.TestCase): def setUp(self): # This is a CHGCAR_sum file with reduced grid size chgcar_path = os.path.join(test_dir, "CHGCAR.FePO4") chg_FePO4 = Chgcar.from_file(chgcar_path) self.chgcar_path = chgcar_path self.chg_FePO4 = chg_FePO4 self.ca_FePO4 = ChargeDensityAnalyzer(chg_FePO4) self.s_LiFePO4 = Structure.from_file( os.path.join(test_dir, "LiFePO4.cif")) def test_get_local_extrema(self): ca = ChargeDensityAnalyzer.from_file(self.chgcar_path) threshold_frac = random.random() threshold_abs_min = random.randrange(2, 14) threshold_abs_max = random.randrange(27e2, 28e4) # Minima test full_list_min = self.ca_FePO4.get_local_extrema(find_min=True, threshold_frac=1.0) frac_list_min_frac = self.ca_FePO4.get_local_extrema( find_min=True, threshold_frac=threshold_frac) frac_list_min_abs = self.ca_FePO4.get_local_extrema( find_min=True, threshold_abs=threshold_abs_min) self.assertAlmostEqual(len(full_list_min) * threshold_frac, len(frac_list_min_frac), delta=1) ca.get_local_extrema(find_min=True) df_expected = ca.extrema_df[ ca.extrema_df["Charge Density"] <= threshold_abs_min] self.assertEqual(len(frac_list_min_abs), len(df_expected)) # Maxima test full_list_max = self.ca_FePO4.get_local_extrema(find_min=False, threshold_frac=1.0) frac_list_max = self.ca_FePO4.get_local_extrema( find_min=False, threshold_frac=threshold_frac) frac_list_max_abs = self.ca_FePO4.get_local_extrema( find_min=False, threshold_abs=threshold_abs_max) self.assertAlmostEqual(len(full_list_max) * threshold_frac, len(frac_list_max), delta=1) # Local maxima should finds all center of atoms self.assertEqual(len(self.ca_FePO4.structure), len(full_list_max)) ca.get_local_extrema(find_min=False) df_expected = ca.extrema_df[ ca.extrema_df["Charge Density"] >= threshold_abs_max] self.assertEqual(len(frac_list_max_abs), len(df_expected)) def test_remove_collisions(self): ca = ChargeDensityAnalyzer(self.chg_FePO4) ca.get_local_extrema(threshold_frac=0) ca.remove_collisions() # should not trigger error self.assertEqual(len(ca.extrema_df), 0) self.ca_FePO4.get_local_extrema(find_min=False, threshold_frac=1.0) self.ca_FePO4.remove_collisions(min_dist=0.5) self.assertEqual(len(self.ca_FePO4.extrema_df), 0) def test_cluster_nodes(self): ca = ChargeDensityAnalyzer(self.chg_FePO4) ca.get_local_extrema() ca.cluster_nodes(tol=20) self.assertEqual(len(ca.extrema_df), 1) def test_get_structure_with_nodes(self): s_FePO4 = self.ca_FePO4.get_structure_with_nodes(find_min=True) sites_predicted = np.array([ self.s_LiFePO4[i].frac_coords for i in range(len(self.s_LiFePO4)) if self.s_LiFePO4[i].species_string == "Li" ]) sites_guess = np.array([ s_FePO4[i].frac_coords for i in range(len(s_FePO4)) if s_FePO4[i].species_string == "X0+" ]) distances = s_FePO4.lattice.get_all_distances(sites_predicted, sites_guess).flatten() distances = [d for d in distances if d < 0.1] self.assertEqual(len(distances), len(sites_predicted)) def test_from_file(self): ca = ChargeDensityAnalyzer.from_file(self.chgcar_path) self.assertTrue(isinstance(ca, ChargeDensityAnalyzer)) def test_sort_sites_by_integrated_chg(self): print(self.chgcar_path) ca = ChargeDensityAnalyzer.from_file(self.chgcar_path) ca.get_local_extrema() ca.sort_sites_by_integrated_chg() print(ca._extrema_df.iloc[0], 0.5) self.assertAlmostEqual(ca._extrema_df.iloc[0]['a'], 0.0) self.assertAlmostEqual(ca._extrema_df.iloc[0]['b'], 0.5) self.assertAlmostEqual(ca._extrema_df.iloc[0]['c'], 0.0) self.assertAlmostEqual(ca._extrema_df.iloc[0]['Charge Density'], 1.65288944124) self.assertAlmostEqual(ca._extrema_df.iloc[0]['Int. Charge Density'], 0.0018375161626331743)
class ChgDenAnalyzerTest(unittest.TestCase): def setUp(self): # This is a CHGCAR_sum file with reduced grid size chgcar_path = os.path.join(test_dir, "CHGCAR.FePO4") chg_FePO4 = Chgcar.from_file(chgcar_path) self.chgcar_path = chgcar_path self.chg_FePO4 = chg_FePO4 self.ca_FePO4 = ChargeDensityAnalyzer(chg_FePO4) self.s_LiFePO4 = Structure.from_file( os.path.join(test_dir, "LiFePO4.cif")) def test_get_local_extrema(self): ca = ChargeDensityAnalyzer.from_file(self.chgcar_path) threshold_frac = random.random() threshold_abs_min = random.randrange(2, 14) threshold_abs_max = random.randrange(27e2, 28e4) # Minima test full_list_min = self.ca_FePO4.get_local_extrema(find_min=True, threshold_frac=1.0) frac_list_min_frac = self.ca_FePO4.get_local_extrema(find_min=True, threshold_frac=threshold_frac) frac_list_min_abs = self.ca_FePO4.get_local_extrema(find_min=True, threshold_abs=threshold_abs_min) self.assertAlmostEqual(len(full_list_min) * threshold_frac, len(frac_list_min_frac), delta=1) ca.get_local_extrema(find_min=True) df_expected = ca.extrema_df[ ca.extrema_df["Charge Density"] <= threshold_abs_min] self.assertEqual(len(frac_list_min_abs), len(df_expected)) # Maxima test full_list_max = self.ca_FePO4.get_local_extrema(find_min=False, threshold_frac=1.0) frac_list_max = self.ca_FePO4.get_local_extrema(find_min=False, threshold_frac=threshold_frac) frac_list_max_abs = self.ca_FePO4.get_local_extrema(find_min=False, threshold_abs=threshold_abs_max) self.assertAlmostEqual(len(full_list_max) * threshold_frac, len(frac_list_max), delta=1) # Local maxima should finds all center of atoms self.assertEqual(len(self.ca_FePO4.structure), len(full_list_max)) ca.get_local_extrema(find_min=False) df_expected = ca.extrema_df[ ca.extrema_df["Charge Density"] >= threshold_abs_max] self.assertEqual(len(frac_list_max_abs), len(df_expected)) def test_remove_collisions(self): ca = ChargeDensityAnalyzer(self.chg_FePO4) ca.get_local_extrema(threshold_frac=0) ca.remove_collisions() # should not trigger error self.assertEqual(len(ca.extrema_df), 0) self.ca_FePO4.get_local_extrema(find_min=False, threshold_frac=1.0) self.ca_FePO4.remove_collisions(min_dist=0.5) self.assertEqual(len(self.ca_FePO4.extrema_df), 0) def test_cluster_nodes(self): ca = ChargeDensityAnalyzer(self.chg_FePO4) ca.get_local_extrema() ca.cluster_nodes(tol=20) self.assertEqual(len(ca.extrema_df), 1) def test_get_structure_with_nodes(self): s_FePO4 = self.ca_FePO4.get_structure_with_nodes(find_min=True) sites_predicted = np.array([ self.s_LiFePO4[i].frac_coords for i in range(len(self.s_LiFePO4)) if self.s_LiFePO4[i].species_string == "Li" ]) sites_guess = np.array( [s_FePO4[i].frac_coords for i in range(len(s_FePO4)) if s_FePO4[i].species_string == "X0+"]) distances = s_FePO4.lattice.get_all_distances(sites_predicted, sites_guess).flatten() distances = [d for d in distances if d < 0.1] self.assertEqual(len(distances), len(sites_predicted)) def test_from_file(self): ca = ChargeDensityAnalyzer.from_file(self.chgcar_path) self.assertTrue(isinstance(ca, ChargeDensityAnalyzer)) def test_sort_sites_by_integrated_chg(self): print(self.chgcar_path) ca = ChargeDensityAnalyzer.from_file(self.chgcar_path) ca.get_local_extrema() ca.sort_sites_by_integrated_chg() print(ca._extrema_df.iloc[0], 0.5) print(ca._extrema_df.iloc[0]['avg_charge_den']) self.assertAlmostEqual(ca._extrema_df.iloc[0]['a'], 0.0) self.assertAlmostEqual(ca._extrema_df.iloc[0]['b'], 0.5) self.assertAlmostEqual(ca._extrema_df.iloc[0]['c'], 0.0) self.assertAlmostEqual(ca._extrema_df.iloc[0]['Charge Density'], 1.65288944124) self.assertAlmostEqual(ca._extrema_df.iloc[0]['avg_charge_den'], 0.006831484178753711)