def minimum_symmetry_measure(self, ag: AbstractGeometry) -> float:
     distorted_points = ag.points_wocs_csc()
     to_return = min(
         symmetry_measure(np.array(p), self.reference_points)
         ['symmetry_measure'] for p in permutations(distorted_points))
     assert isinstance(to_return, float)
     return to_return
Пример #2
0
 def minimum_symmetry_measure(self, ag):
     distorted_points = ag.points_wocs_csc()
     return min(
         symmetry_measure(np.array(p), self.reference_points)
         ['symmetry_measure'] for p in permutations(distorted_points))
Пример #3
0
    def test_abstract_geometry(self):
        cg_ts3 = self.lgf.allcg["TS:3"]
        cg_tet = self.lgf.allcg["T:4"]
        abstract_geom = AbstractGeometry.from_cg(cg=cg_ts3,
                                                 centering_type="central_site")
        self.assertArrayAlmostEqual(abstract_geom.centre, [0.0, 0.0, 0.0])
        abstract_geom = AbstractGeometry.from_cg(cg=cg_ts3,
                                                 centering_type="centroid")
        self.assertArrayAlmostEqual(abstract_geom.centre,
                                    [0.0, 0.0, 0.33333333333])
        with self.assertRaises(ValueError) as cm:
            AbstractGeometry.from_cg(
                cg=cg_ts3,
                centering_type="central_site",
                include_central_site_in_centroid=True,
            )
        self.assertEqual(
            str(cm.exception),
            "The center is the central site, no calculation of the centroid, "
            "variable include_central_site_in_centroid should be set to False",
        )
        abstract_geom = AbstractGeometry.from_cg(
            cg=cg_ts3,
            centering_type="centroid",
            include_central_site_in_centroid=True)
        self.assertArrayAlmostEqual(abstract_geom.centre, [0.0, 0.0, 0.25])

        # WHY ARE WE TESTING STRINGS????
        # self.assertEqual(abstract_geom.__str__(),
        #                  '\nAbstract Geometry with 3 points :\n'
        #                  '  [-1.    0.   -0.25]\n'
        #                  '  [ 1.    0.   -0.25]\n'
        #                  '  [ 0.   0.   0.75]\n'
        #                  'Points are referenced to the centroid (calculated with the central site) :\n'
        #                  '  [ 0.   0.   0.25]\n')

        symm_dict = symmetry_measure([[0.0, 0.0, 0.0]], [1.1, 2.2, 3.3])
        self.assertAlmostEqual(symm_dict["symmetry_measure"], 0.0)
        self.assertEqual(symm_dict["scaling_factor"], None)
        self.assertEqual(symm_dict["rotation_matrix"], None)

        tio2_struct = self.get_structure("TiO2")

        envs = self.lgf.compute_coordination_environments(
            structure=tio2_struct, indices=[0])
        self.assertAlmostEqual(envs[0][0]["csm"], 1.5309987846957258)
        self.assertAlmostEqual(envs[0][0]["ce_fraction"], 1.0)
        self.assertEqual(envs[0][0]["ce_symbol"], "O:6")
        self.assertEqual(sorted(envs[0][0]["permutation"]),
                         sorted([0, 4, 1, 5, 2, 3]))

        self.lgf.setup_random_structure(coordination=5)
        self.assertEqual(len(self.lgf.structure), 6)

        self.lgf.setup_random_indices_local_geometry(coordination=5)
        self.assertEqual(self.lgf.icentral_site, 0)
        self.assertEqual(len(self.lgf.indices), 5)

        self.lgf.setup_ordered_indices_local_geometry(coordination=5)
        self.assertEqual(self.lgf.icentral_site, 0)
        self.assertEqual(self.lgf.indices, list(range(1, 6)))

        self.lgf.setup_explicit_indices_local_geometry(
            explicit_indices=[3, 5, 2, 0, 1, 4])
        self.assertEqual(self.lgf.icentral_site, 0)
        self.assertEqual(self.lgf.indices, [4, 6, 3, 1, 2, 5])

        LiFePO4_struct = self.get_structure("LiFePO4")
        isite = 10
        envs_LiFePO4 = self.lgf.compute_coordination_environments(
            structure=LiFePO4_struct, indices=[isite])
        self.assertAlmostEqual(envs_LiFePO4[isite][0]["csm"], 0.140355832317)
        nbs_coords = [
            np.array([6.16700437, -4.55194317, -5.89031356]),
            np.array([4.71588167, -4.54248093, -3.75553856]),
            np.array([6.88012571, -5.79877503, -3.73177541]),
            np.array([6.90041188, -3.32797839, -3.71812416]),
        ]
        self.lgf.setup_structure(LiFePO4_struct)
        self.lgf.setup_local_geometry(isite, coords=nbs_coords)

        perfect_tet = AbstractGeometry.from_cg(
            cg=cg_tet,
            centering_type="centroid",
            include_central_site_in_centroid=False)
        points_perfect_tet = perfect_tet.points_wcs_ctwcc()
        res = self.lgf.coordination_geometry_symmetry_measures_fallback_random(
            coordination_geometry=cg_tet,
            NRANDOM=5,
            points_perfect=points_perfect_tet)
        (
            permutations_symmetry_measures,
            permutations,
            algos,
            local2perfect_maps,
            perfect2local_maps,
        ) = res
        for perm_csm_dict in permutations_symmetry_measures:
            self.assertAlmostEqual(perm_csm_dict["symmetry_measure"],
                                   0.140355832317)
    def discrete_orientation(self,
                             points: np.ndarray) -> OrientationDict:
        """Find the discrete "closest orientation" for an input polyhedron of points.

        For example, a tetrahedon has 12 pure rotation symmetry operations. A distorted
        tetrahedron with vertices approximately aligned along the unordered vectors::

            [[ 1.0, -1.0,  1.0],
             [-1.0, -1.0, -1.0],
             [ 1.0,  1.0, -1.0],
             [-1.0,  1.0,  1.0]]

        can be in one of 12 orientations. This method compares the input points to
        all permutations of self.reference_points that can be generated by proper rotations, and returns
        an index for orientation that minimises the rotational distance between the reordered
        reference points and the input points.

        The algorithm is:
        1. Perform continuous symmetry measure analysis for all permutations of reference points.
        2. Collect operations that have the minimum continous symmetry measure value.
        These give the set of all propert and improper rotations.
        3. Find all proper rotations using det(M_rot)>0.
        4. Calculate the rotational distance.

        Args:
            points (np.array(float)): Nx3 numpy array of points describing the coordinates of the
                input polyhedron, centered around zero.

        Returns:
            (dict): Dictionary describing the orientation, with keys:
                - ``orientation_index`` (int): Index of this particular orientation.
                - ``reference_geometry_index`` (int): Index of the reference geometry
                    the closest discrete orientation is equivalent to.
                - ``rotational_distance`` (float): Angle of rotation from the relevant
                    reference orientation, in radians.
                - ``all_rotational_distances`` (np.array(float)): Array of angles of rotation
                    from each reference orientation.
                - ``symmetry_measure`` (float): The continuous symmetry measure (CSM)
                  for this polyhedron (J. Am. Chem. Soc., 114, 7843-7851 (1992)) 

        """
        points -= np.mean(points, axis=0, dtype=float)
        sm = []
        for rp in self.reference_points:
            sm.extend([symmetry_measure(points, p) for p in permutations(rp)])
        min_sm = min([s['symmetry_measure'] for s in sm])
        pure_rot_sm = [s for s in sm if math.isclose(
            s['symmetry_measure'], min_sm)]
        proper_rot_sm = [s for s in pure_rot_sm if np.linalg.det(
            s['rotation_matrix']) > 0]
        proper_rot_matrices = np.array(
            [s['rotation_matrix'] for s in proper_rot_sm])
        trace = np.trace(proper_rot_matrices, axis1=1, axis2=2)
        rot_distance = np.arccos((trace - 1.0) / 2.0)
        index = int(np.argmin(rot_distance))
        reference_geometry_index = index // int(
            len(proper_rot_sm) / len(self.reference_points))
        return OrientationDict(orientation_index=index,
                               reference_geometry_index=reference_geometry_index,
                               rotational_distance=rot_distance[index],
                               symmetry_measure=proper_rot_sm[index]['symmetry_measure'],
                               all_rotational_distances=rot_distance)
    def test_abstract_geometry(self):
        cg_ts3 = self.lgf.allcg['TS:3']
        cg_tet = self.lgf.allcg['T:4']
        abstract_geom = AbstractGeometry.from_cg(cg=cg_ts3, centering_type='central_site')
        self.assertArrayAlmostEqual(abstract_geom.centre, [0.0, 0.0, 0.0])
        abstract_geom = AbstractGeometry.from_cg(cg=cg_ts3, centering_type='centroid')
        self.assertArrayAlmostEqual(abstract_geom.centre, [0.0, 0.0, 0.33333333333])
        with self.assertRaises(ValueError) as cm:
            AbstractGeometry.from_cg(cg=cg_ts3, centering_type='central_site',
                                     include_central_site_in_centroid=True)
        self.assertEqual(str(cm.exception), 'The center is the central site, no calculation of the centroid, '
                                            'variable include_central_site_in_centroid should be set to False')
        abstract_geom = AbstractGeometry.from_cg(cg=cg_ts3, centering_type='centroid',
                                                 include_central_site_in_centroid=True)
        self.assertArrayAlmostEqual(abstract_geom.centre, [0.0, 0.0, 0.25])

        self.assertEqual(abstract_geom.__str__(),
                         '\nAbstract Geometry with 3 points :\n'
                         '  [-1.    0.   -0.25]\n'
                         '  [ 1.    0.   -0.25]\n'
                         '  [0.   0.   0.75]\n'
                         'Points are referenced to the centroid (calculated with the central site) :\n'
                         '  [0.   0.   0.25]\n')

        symm_dict = symmetry_measure([[0.0, 0.0, 0.0]], [1.1, 2.2, 3.3])
        self.assertAlmostEqual(symm_dict['symmetry_measure'], 0.0)
        self.assertEqual(symm_dict['scaling_factor'], None)
        self.assertEqual(symm_dict['rotation_matrix'], None)

        tio2_struct = self.get_structure('TiO2')

        envs = self.lgf.compute_coordination_environments(structure=tio2_struct, indices=[0])
        self.assertAlmostEqual(envs[0][0]['csm'], 1.5309987846957258)
        self.assertAlmostEqual(envs[0][0]['ce_fraction'], 1.0)
        self.assertEqual(envs[0][0]['ce_symbol'], 'O:6')
        self.assertEqual(sorted(envs[0][0]['permutation']), sorted([0, 4, 1, 5, 2, 3]))

        self.lgf.setup_random_structure(coordination=5)
        self.assertEqual(len(self.lgf.structure), 6)

        self.lgf.setup_random_indices_local_geometry(coordination=5)
        self.assertEqual(self.lgf.icentral_site, 0)
        self.assertEqual(len(self.lgf.indices), 5)

        self.lgf.setup_ordered_indices_local_geometry(coordination=5)
        self.assertEqual(self.lgf.icentral_site, 0)
        self.assertEqual(self.lgf.indices, list(range(1, 6)))

        self.lgf.setup_explicit_indices_local_geometry(explicit_indices=[3, 5, 2, 0, 1, 4])
        self.assertEqual(self.lgf.icentral_site, 0)
        self.assertEqual(self.lgf.indices, [4, 6, 3, 1, 2, 5])

        LiFePO4_struct = self.get_structure('LiFePO4')
        isite = 10
        envs_LiFePO4 = self.lgf.compute_coordination_environments(structure=LiFePO4_struct, indices=[isite])
        self.assertAlmostEqual(envs_LiFePO4[isite][0]['csm'], 0.140355832317)
        nbs_coords = [np.array([6.16700437, -4.55194317, -5.89031356]),
                      np.array([4.71588167, -4.54248093, -3.75553856]),
                      np.array([6.88012571, -5.79877503, -3.73177541]),
                      np.array([6.90041188, -3.32797839, -3.71812416])]
        self.lgf.setup_structure(LiFePO4_struct)
        self.lgf.setup_local_geometry(isite, coords=nbs_coords)

        perfect_tet = AbstractGeometry.from_cg(cg=cg_tet,
                                               centering_type='centroid',
                                               include_central_site_in_centroid=False)
        points_perfect_tet = perfect_tet.points_wcs_ctwcc()
        res = self.lgf.coordination_geometry_symmetry_measures_fallback_random(coordination_geometry=cg_tet,
                                                                               NRANDOM=5,
                                                                               points_perfect=points_perfect_tet)
        permutations_symmetry_measures, permutations, algos, local2perfect_maps, perfect2local_maps = res
        for perm_csm_dict in permutations_symmetry_measures:
            self.assertAlmostEqual(perm_csm_dict['symmetry_measure'], 0.140355832317)
def calculate_info(initial_string, icsd, dim, delta):
    print(icsd, dim)
    initial_string = initial_string.rstrip()
    if dim == 0:
        for i in range(11):
            initial_string += ";-1"
    else:
        delta = up_delta
        g = open(
            "cif_files/data_" + icsd + "-ICSD.cif", "r"
        )  #assuming all cif files are present in the cif_files folder with that particular format
        cif_file = g.read()
        g.close()
        cif_file = re.sub(r"[^\x00-\x7F]", "",
                          cif_file)  #remove non-ascii characters
        cif_file = re.sub(
            r"(\(\d+)(\s|\n)", r"\1\)\2",
            cif_file)  #close any open brackets (throws an error otherwise)
        structure = CifParser.from_string(
            cif_file,
            occupancy_tolerance=100).get_structures(primitive=False)[0]
        filtering = Filtering(structure)
        filtering.form_neighbor_list()
        G = filtering.define_bonds(delta)
        delta_check = filtering.check_for_delta(G, dim)
        layers_angles_stuff = filtering.calculate_layers_angles_and_stuff(
            G, dim)

        while not delta_check:
            delta = delta - 0.1
            if (delta >= low_delta):
                G = filtering.define_bonds(delta)
                delta_check = filtering.check_for_delta(G, dim)
            else:
                break

        if delta < low_delta:
            layers_angles_stuff = filtering.calculate_layers_angles_and_stuff(
                filtering.define_bonds(up_delta), dim)
            initial_string += ";" + str(up_delta)
        else:
            layers_angles_stuff = filtering.calculate_layers_angles_and_stuff(
                G, dim)
            initial_string += ";" + str(delta)

        for stuff in layers_angles_stuff[:-2]:
            initial_string += ";" + str(stuff)

        # bonded lattice
        bonded_lattice = {}
        for key, value in layers_angles_stuff[-2].items():
            points_distorted = value
            coord_no = str(layers_angles_stuff[3][key])
            if coord_no in points_perfect:
                bonded_lattice[key] = {}
                for i in range(len(points_perfect[coord_no])):
                    bonded_lattice[key][lattices[coord_no][i]] = str(
                        np.round(symmetry_measure(
                            points_distorted,
                            points_perfect[coord_no][i])["symmetry_measure"],
                                 decimals=1))
            else:
                bonded_lattice[key] = -1

        # magnetic metal lattice
        metal_neigh_lattice = {}
        for key, value in layers_angles_stuff[-1].items():
            points_distorted = value
            coord_no = str(layers_angles_stuff[7][key])
            if coord_no in metal_points_perfect:
                metal_neigh_lattice[key] = {}
                metal_neigh_lattice[key][metal_lattices[coord_no]] = str(
                    np.round(symmetry_measure(
                        points_distorted,
                        metal_points_perfect[coord_no])["symmetry_measure"],
                             decimals=1))
            else:
                metal_neigh_lattice[key] = -1

        initial_string += ";" + str(bonded_lattice) + ";" + str(
            metal_neigh_lattice)
    f = open("results_" + str(os.getpid()) + ".txt", "a")
    print(initial_string)
    f.write(initial_string + "\n")
    f.close()