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
Esempio n. 2
0
    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)
Esempio n. 3
0
    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")
Esempio n. 5
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)
Esempio n. 6
0
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)
Esempio n. 7
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)
Esempio n. 8
0
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)