def get_integer_formula_and_factor( self, max_denominator: int = 10000, iupac_ordering: bool = False ) -> Tuple[str, float]: """ Calculates an integer formula and factor. Args: max_denominator (int): all amounts in the el:amt dict are first converted to a Fraction with this maximum denominator iupac_ordering (bool, optional): Whether to order the formula by the iupac "electronegativity" series, defined in Table VI of "Nomenclature of Inorganic Chemistry (IUPAC Recommendations 2005)". This ordering effectively follows the groups and rows of the periodic table, except the Lanthanides, Actinides and hydrogen. Note that polyanions will still be determined based on the true electronegativity of the elements. Returns: A pretty normalized formula and a multiplicative factor, i.e., Li0.5O0.25 returns (Li2O, 0.25). O0.25 returns (O2, 0.125) """ el_amt = self.get_el_amt_dict() g = gcd_float(list(el_amt.values()), 1 / max_denominator) d = {k: round(v / g) for k, v in el_amt.items()} (formula, factor) = reduce_formula(d, iupac_ordering=iupac_ordering) if formula in Composition.special_formulas: formula = Composition.special_formulas[formula] factor /= 2 return formula, factor * g
def get_ordered_integer_formula(el_amt, max_denominator=1000): """Converts a mapping of {element: stoichiometric value} to a alphabetically ordered string. Given a dictionary of {element : stoichiometric value, ..}, returns a string with elements ordered alphabetically and stoichiometric values normalized to smallest common integer denominator. Args: el_amt: {element: stoichiometric value} mapping. max_denominator: The maximum common denominator of stoichiometric values to use for normalization. Smaller stoichiometric fractions will be converted to the same integer stoichiometry. Returns: A material formula string with elements ordered alphabetically and the stoichiometry normalized to the smallest integer fractions. """ g = gcd_float(list(el_amt.values()), 1 / max_denominator) d = {k: round(v / g) for k, v in el_amt.items()} formula = "" for k in sorted(d): if d[k] > 1: formula += k + str(d[k]) elif d[k] != 0: formula += k return formula
def get_integer_formula_and_factor(self, max_denominator=10000, iupac_ordering=False): """ Calculates an integer formula and factor. Args: max_denominator (int): all amounts in the el:amt dict are first converted to a Fraction with this maximum denominator iupac_ordering (bool, optional): Whether to order the formula by the iupac "electronegativity" series, defined in Table VI of "Nomenclature of Inorganic Chemistry (IUPAC Recommendations 2005)". This ordering effectively follows the groups and rows of the periodic table, except the Lanthanides, Actanides and hydrogen. Note that polyanions will still be determined based on the true electronegativity of the elements. Returns: A pretty normalized formula and a multiplicative factor, i.e., Li0.5O0.25 returns (Li2O, 0.25). O0.25 returns (O2, 0.125) """ el_amt = self.get_el_amt_dict() g = gcd_float(list(el_amt.values()), 1 / max_denominator) d = {k: round(v / g) for k, v in el_amt.items()} (formula, factor) = reduce_formula( d, iupac_ordering=iupac_ordering) if formula in Composition.special_formulas: formula = Composition.special_formulas[formula] factor /= 2 return formula, factor * g
def get_ordered_integer_formula(self, el_amt, max_denominator=1000): # return alphabetically ordered formula with integer fractions g = gcd_float(list(el_amt.values()), 1 / max_denominator) d = {k: round(v / g) for k, v in el_amt.items()} formula = "" for k in sorted(d): if d[k] > 1: formula += k + str(d[k]) else: formula += k return formula
def _str_from_comp(cls, coeffs, compositions, reduce=False): r_coeffs = np.zeros(len(coeffs)) r_formulas = [] for i, (amt, comp) in enumerate(zip(coeffs, compositions)): formula, factor = comp.get_reduced_formula_and_factor() r_coeffs[i] = amt * factor r_formulas.append(formula) if reduce: factor = 1 / gcd_float(np.abs(r_coeffs)) r_coeffs *= factor else: factor = 1 return cls._str_from_formulas(r_coeffs, r_formulas), factor
def _str_from_comp(cls, coeffs, compositions, reduce=False): r_coeffs = np.zeros(len(coeffs)) r_formulas = [] for i, (amt, comp) in enumerate(zip(coeffs, compositions)): formula, factor = comp.get_reduced_formula_and_factor() r_coeffs[i] = amt * factor r_formulas.append(formula) if reduce: factor = 1 / gcd_float(np.abs(r_coeffs)) r_coeffs *= factor else: factor = 1 return cls._str_from_formulas(r_coeffs, r_formulas), factor
def get_ordered_integer_formula(el_amt, max_denominator=1000): """ Given a dictionary of {element : stoichiometric value, ..}, returns a string with elements ordered alphabetically and stoichiometric values normalized to smallest common ingeger denominator :param el_amt: :param max_denominator: :return: """ # return alphabetically ordered formula with integer fractions g = gcd_float(list(el_amt.values()), 1 / max_denominator) d = {k: round(v / g) for k, v in el_amt.items()} formula = "" for k in sorted(d): if d[k] > 1: formula += k + str(d[k]) elif d[k] != 0: formula += k return formula
def get_integer_formula_and_factor(self, max_denominator=10000): """ Calculates an integer formula and factor. Args: max_denominator (int): all amounts in the el:amt dict are first converted to a Fraction with this maximum denominator Returns: A pretty normalized formula and a multiplicative factor, i.e., Li0.5O0.25 returns (Li2O, 0.25). O0.25 returns (O2, 0.125) """ el_amt = self.get_el_amt_dict() g = gcd_float(list(el_amt.values()), 1 / max_denominator) d = {k: round(v / g) for k, v in el_amt.items()} (formula, factor) = reduce_formula(d) if formula in Composition.special_formulas: formula = Composition.special_formulas[formula] factor /= 2 return formula, factor * g
def get_integer_formula_and_factor(self, max_denominator=10000): """ Calculates an integer formula and factor. Args: max_denominator (int): all amounts in the el:amt dict are first converted to a Fraction with this maximum denominator Returns: A pretty normalized formula and a multiplicative factor, i.e., Li0.5O0.25 returns (Li2O, 0.25). O0.25 returns (O2, 0.125) """ el_amt = self.get_el_amt_dict() g = gcd_float(list(el_amt.values()), 1 / max_denominator) d = {k: round(v / g) for k, v in el_amt.items()} (formula, factor) = reduce_formula(d) if formula in Composition.special_formulas: formula = Composition.special_formulas[formula] factor /= 2 return formula, factor * g
def test_gcd_float(self): vs = [6.2, 12.4, 15.5 + 5e-9] self.assertAlmostEqual(gcd_float(vs, 1e-8), 3.1)
def test_gcd_float(self): vs = [6.2, 12.4, 15.5 + 5e-9] self.assertAlmostEqual(gcd_float(vs, 1e-8), 3.1)