Esempio n. 1
0
    def test_get_al(self):
        """Test getting element names"""
        specie = get_el_sp("Sn2+")
        self.assertEqual(get_el(specie), "Sn")

        element = get_el_sp("Sn")
        self.assertEqual(get_el(element), "Sn")

        self.assertEqual(get_el(50), "Sn")
Esempio n. 2
0
    def _get_poly_formula(
        self,
        geometry: Dict[str, Any],
        nn_sites: List[Dict[str, Any]],
        nnn_sites: List[Dict[str, Any]],
    ) -> Optional[str]:
        """Gets the polyhedra formula of the nearest neighbor atoms.

        The polyhedral formula is effectively the sorted nearest neighbor
        atoms in a reduced format. For example, if the nearest neighbors are
        3 I atoms, 2 Br atoms and 1 Cl atom, the polyhedral formula will be
        "I3Br2Cl". The polyhedral formula will be ``None`` if the site geometry
        is not in :data:`robocrys.util.connected_geometries`.

        Args:
            geometry: The site geometry as produced by
                :meth:`SiteAnalyzer.get_site_geometry`.
            nn_sites: The nearest neighbor sites as produced by
                :meth:`SiteAnalyzer.get_nearest_neighbors`.
            nnn_sites: The next nearest neighbor sites as produced by
                :meth:`SiteAnalyzer.get_next_nearest_neighbors`.

        Returns:
            The polyhedral formula if the site geometry is in
            :data:`robocrys.util.connected_geometries` else ``None``.
        """
        def order_elements(el):
            if self.use_iupac_formula:
                return [get_el_sp(el).X, el]
            else:
                return [get_el_sp(el).iupac_ordering, el]

        nnn_geometries = [nnn_site["geometry"] for nnn_site in nnn_sites]

        poly_formula = None
        if geometry["type"] in connected_geometries and any([
                nnn_geometry["type"] in connected_geometries
                for nnn_geometry in nnn_geometries
        ]):
            nn_els = [get_el(nn_site["element"]) for nn_site in nn_sites]
            comp = Composition("".join(nn_els))
            el_amt_dict = comp.get_el_amt_dict()

            poly_formula = ""
            for e in sorted(el_amt_dict.keys(), key=order_elements):
                poly_formula += e
                poly_formula += formula_double_format(el_amt_dict[e])

        return poly_formula
Esempio n. 3
0
    def _calculate_symmetry_labels(
            self, sym_equivalent_atoms: List[int]) -> List[int]:
        """Calculates the symmetry labels for all sites in the structure.

        The symmetry labels number the sites in the structure. If two sites
        are symmetrically equivalent they share the same symmetry label. The
        numbering begins at 1 for each element in the structure.

        Args:
            sym_equivalent_atoms: A :obj:`list` of indices mapping each site in
                the structure to a symmetrically equivalent site. The data
                should be formatted as given by the ``equivalent_atoms`` key in
                :meth`SpacegroupAnalyzer.get_symmetry_dataset()`.

        Returns:
            A mapping between the site index and symmetry label for that site.
        """
        symmetry_labels = dict()

        # this way is a little long winded but works if the sites aren't
        # grouped together by element
        for specie in self.bonded_structure.structure.species:
            el_indices = self.bonded_structure.structure.indices_from_symbol(
                get_el(specie))
            equiv_indices = [sym_equivalent_atoms[x] for x in el_indices]

            count = 1
            equiv_index_to_sym_label = {}
            for el_index, equiv_index in zip(el_indices, equiv_indices):
                if equiv_index in equiv_index_to_sym_label:
                    symmetry_labels[el_index] = equiv_index_to_sym_label[
                        equiv_index]
                else:
                    equiv_index_to_sym_label[equiv_index] = count
                    symmetry_labels[el_index] = count
                    count += 1

        return [symmetry_labels[i] for i in sorted(symmetry_labels.keys())]
Esempio n. 4
0
    def test_get_formatted_el(self):
        """Test getting formatted element strings."""
        specie = get_el_sp("Sn2+")
        form_el = get_formatted_el(specie, "")
        self.assertEqual(form_el, "Sn2+")

        element = get_el_sp("Sn")
        form_el = get_formatted_el(element, "")
        self.assertEqual(form_el, "Sn")

        form_el = get_formatted_el(get_el(50), "")
        self.assertEqual(form_el, "Sn")

        form_el = get_formatted_el("Sn2+",
                                   "(1,2)",
                                   use_oxi_state=True,
                                   use_sym_label=True,
                                   fmt="raw")
        self.assertEqual(form_el, "Sn(1,2)2+")

        form_el = get_formatted_el("Sn2+",
                                   "(1,2)",
                                   use_oxi_state=False,
                                   use_sym_label=True,
                                   fmt="raw")
        self.assertEqual(form_el, "Sn(1,2)")

        form_el = get_formatted_el("Sn2+",
                                   "(1,2)",
                                   use_oxi_state=True,
                                   use_sym_label=False,
                                   fmt="raw")
        self.assertEqual(form_el, "Sn2+")

        form_el = get_formatted_el("Sn2+",
                                   "(1,2)",
                                   use_oxi_state=False,
                                   use_sym_label=False,
                                   fmt="raw")
        self.assertEqual(form_el, "Sn")

        form_el = get_formatted_el("Sn2+",
                                   "(1,2)",
                                   use_oxi_state=True,
                                   use_sym_label=True,
                                   fmt="latex")
        self.assertEqual(form_el, "Sn(1,2)^{2+}")

        form_el = get_formatted_el("Sn2+",
                                   "(1,2)",
                                   use_oxi_state=True,
                                   use_sym_label=True,
                                   fmt="html")
        self.assertEqual(form_el, "Sn(1,2)<sup>2+</sup>")

        form_el = get_formatted_el("Sn2+",
                                   "(1,2)",
                                   use_oxi_state=True,
                                   use_sym_label=True,
                                   fmt="unicode")
        self.assertEqual(form_el, "Sn(1,2)²⁺")
Esempio n. 5
0
    def _get_poly_site_description(self, site_index: int):
        """Gets a description of a connected polyhedral site.

        If the site likeness (order parameter) is less than ``distorted_tol``,
        "distorted" will be added to the geometry description.

        Args:
            site_index: An inequivalent site index.

        Returns:
            A description the a polyhedral site, including connectivity.
        """
        site = self._da.sites[site_index]
        nnn_details = self._da.get_next_nearest_neighbor_details(
            site_index, group=not self.describe_symmetry_labels
        )

        from_element = get_formatted_el(
            site["element"],
            self._da.sym_labels[site_index],
            use_oxi_state=self.describe_oxidation_state,
            use_sym_label=self.describe_symmetry_labels,
            fmt=self.fmt,
        )

        from_poly_formula = site["poly_formula"]
        if self.fmt == "latex":
            from_poly_formula = latexify(from_poly_formula)
        elif self.fmt == "unicode":
            from_poly_formula = unicodeify(from_poly_formula)
        elif self.fmt == "html":
            from_poly_formula = htmlify(from_poly_formula)

        s_from_poly_formula = get_el(site["element"]) + from_poly_formula

        if site["geometry"]["likeness"] < self.distorted_tol:
            s_distorted = "distorted "
        else:
            s_distorted = ""
        s_polyhedra = geometry_to_polyhedra[site["geometry"]["type"]]
        s_polyhedra = polyhedra_plurals[s_polyhedra]

        nn_desc = self._get_nearest_neighbor_description(site_index)
        desc = f"{from_element} is bonded to {nn_desc} to form "

        # handle the case we were are connected to the same type of polyhedra
        if (
            nnn_details[0].element == site["element"]
            and len(
                {(nnn_site.element, nnn_site.poly_formula) for nnn_site in nnn_details}
            )
        ) == 1:
            connectivities = list({nnn_site.connectivity for nnn_site in nnn_details})
            s_mixture = "a mixture of " if len(connectivities) != 1 else ""
            s_connectivities = en.join(connectivities)

            desc += "{}{}{}-sharing {} {}".format(
                s_mixture,
                s_distorted,
                s_connectivities,
                s_from_poly_formula,
                s_polyhedra,
            )
            return desc

        # otherwise loop through nnn connectivities and describe individually
        desc += "{}{} {} that share ".format(
            s_distorted, s_from_poly_formula, s_polyhedra
        )
        nnn_descriptions = []
        for nnn_site in nnn_details:
            to_element = get_formatted_el(
                nnn_site.element,
                nnn_site.sym_label,
                use_oxi_state=False,
                use_sym_label=self.describe_symmetry_labels,
            )

            to_poly_formula = nnn_site.poly_formula
            if self.fmt == "latex":
                to_poly_formula = latexify(to_poly_formula)
            elif self.fmt == "unicode":
                to_poly_formula = unicodeify(to_poly_formula)
            elif self.fmt == "html":
                to_poly_formula = htmlify(to_poly_formula)

            to_poly_formula = to_element + to_poly_formula
            to_shape = geometry_to_polyhedra[nnn_site.geometry]

            if len(nnn_site.sites) == 1 and nnn_site.count != 1:
                s_equivalent = " equivalent "
            else:
                s_equivalent = " "

            if nnn_site.count == 1:
                s_an = f" {en.an(nnn_site.connectivity)}"
            else:
                s_an = ""
                to_shape = polyhedra_plurals[to_shape]

            nnn_descriptions.append(
                "{}{} with {}{}{} {}".format(
                    s_an,
                    en.plural(nnn_site.connectivity, nnn_site.count),
                    en.number_to_words(nnn_site.count),
                    s_equivalent,
                    to_poly_formula,
                    to_shape,
                )
            )

        return desc + en.join(nnn_descriptions)