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")
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
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())]
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)²⁺")
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)