Ejemplo n.º 1
0
    def _set_distance_matrix(self, structure: IStructure):
        """Utility func to calculate distance between structure and minerals.

        First checks to see if the distances have already been calculated for
        the structure. If not, the distances are stored in a class variable
        for use by other class methods.

        Args:
            structure: A structure.
        """
        if self._structure == structure and self._mineral_db is not None:
            return

        data = self.mineral_db.copy()
        fingerprint = get_structure_fingerprint(structure)

        if np.linalg.norm(fingerprint) < 0.4:
            # fingerprint is too small for a reasonable match, indicates very
            # little bonding or small order parameter matches
            fingerprint = get_structure_fingerprint(structure,
                                                    prototype_match=False)

        data["distance"] = data["fingerprint"].apply(
            lambda x: get_fingerprint_distance(x, fingerprint))

        self._mineral_db = data.sort_values(by="distance")
        self._structure = structure
Ejemplo n.º 2
0
    def test_get_structure_fingerprint(self):
        """Test to check structure fingerprinting."""
        fingerprint = get_structure_fingerprint(self.fe)
        self.assertAlmostEqual(fingerprint[4], 1.98432036e-03)

        # test stats option
        fingerprint = get_structure_fingerprint(self.fe, stats=('mean', ))
        self.assertAlmostEqual(fingerprint[31], 2.51322893e-01)
Ejemplo n.º 3
0
    def test_get_fingerprint_distance(self):
        """Tests to check getting fingerprint distance."""
        finger_1 = [0, 0, 0, 1]
        finger_2 = [1, 0, 0, 0]
        dist = get_fingerprint_distance(finger_1, finger_2)
        self.assertAlmostEqual(dist, 1.4142135623730951)

        # test automatic conversion from structure to fingerprint
        dist = get_fingerprint_distance(self.fe, self.fe)
        self.assertAlmostEqual(dist, 0.)

        # test one structure one fingerprint
        finger_1 = get_structure_fingerprint(self.fe)
        dist = get_fingerprint_distance(self.fe, finger_1)
        self.assertAlmostEqual(dist, 0.)
Ejemplo n.º 4
0
def get_structure_inequiv_components(
        components: List[Component],
        use_structure_graph: bool = False,
        fingerprint_tol: int = 0.01) -> List[Component]:
    """Gets and counts the structurally inequivalent components.

    Supports matching through StructureMatcher or by a combined structure graph/
    site fingerprint approach. For the latter method, the component data has to
    have been generated with ``inc_graph=True``.

    Args:
        components: A list of structure components, generated using
            :obj:`pymatgen.analysis.dimensionality.get_structure_components`.
            If ``use_structure_graph=True``, the components should be generated
            with ``inc_graph=True``.
        use_structure_graph: Whether to use the bonding graph and site
            fingerprints to determine if components are structurally equivalent.
            If ``False``,
            :obj:`pymatgen.analysis.structure_matcher.StructureMatcher` will be
            used to compare the components.
        fingerprint_tol: The fingerprint tolerance to determine whether two
            components have a matching fingerprint. This option is ignored if
            ``use_structure_graph=False``.

    Returns:
        A list of the structurally inequivalent components. Any duplicate
        components will only be returned once. The component objects are in the
        same format is given by
        :obj:`pymatgen.analysis.dimensionality.get_structure_components` but
        have an additional field:

        - ``"count"`` (:obj:`int`): The number of times this component appears
          in the structure.
    """
    components = deepcopy(components)

    for component in components:
        component['count'] = 1

    if use_structure_graph:
        # check fingerprints match and components are isomorphic.
        fingerprints = [
            get_structure_fingerprint(c['structure_graph'].structure)
            for c in components
        ]

        seen_components = [components[0]]
        seen_fingers = [fingerprints[0]]
        for component, fingerprint in zip(components[1:], fingerprints[1:]):
            graph_match = [
                components_are_isomorphic(component, c)
                for c in seen_components
            ]
            finger_match = [
                np.linalg.norm(fingerprint - c) < fingerprint_tol
                for c in seen_fingers
            ]
            structure_match = [
                i and f for i, f in zip(graph_match, finger_match)
            ]

            if any(structure_match):
                # there should only ever be a single match so we take index of
                # the first match and increment the component count
                loc = np.where(structure_match)[0][0]
                seen_components[loc]['count'] += 1
            else:
                seen_components.append(component)
                seen_fingers.append(fingerprint)

    else:
        sm = StructureMatcher()
        seen_components = [components[0]]

        for component in components[1:]:
            structure_match = [
                sm.fit(component['structure_graph'].structure,
                       c['structure_graph'].structure) for c in seen_components
            ]
            if any(structure_match):
                # there should only ever be a single match so we take index of
                # the first match and increment the component count
                loc = np.where(structure_match)[0][0]
                seen_components[loc]['count'] += 1
            else:
                seen_components.append(component)

    return seen_components