def compound_name(formula):
    periodic_table = PeriodicTable()
    ions = Ions()
    common_compounds = CommonCompounds()
    if formula in common_compounds:
        return common_compounds[formula]
    root = parse_formula(formula)
    components = root[0].children
    if len(components) == 2:
        cation = _find_ion(components[0], periodic_table, ions)
        anion = _find_ion(components[1], periodic_table, ions)
        first = cation.name
        if isinstance(cation.charge, list):
            total_charge = abs(int(components[1].count) * anion.charge)
            first += ('(' + ('I' * total_charge) + ')')
        second = anion.name
        if '-' in first:
            first = first.replace('-', '')
        if '-' in second:
            second = second.split('-')[0] + 'ide'
        #TODO there is probably a better way to do this
        if anion.charge != -1 and cation.charge != 1:
            first = prefix(components[0].count, cation.symbol[0]) + first
            second = prefix(components[1].count, anion.symbol[0]) + second
        return first + ' ' + second
    else:
        return 'unknown'
def test_parse_formula_N2H4_as_liquid():
    actual = parse_formula('N2H4(l)')
    expected = FormulaRoot('N2H4(l)', [])
    expected.children.append(
        CompoundNode(Count(1), 'N2H4',
                     [AtomNode(Count(2), 'N'),
                      AtomNode(Count(4), 'H')], CompoundState.LIQUID))
    assert actual == expected
def test_parse_formula_HCl():
    actual = parse_formula('HCl')
    #expected = [(Decimal('1.000'), 'H'), (Decimal('1.000'), 'Cl')]
    expected = FormulaRoot('HCl', [])
    expected.children.append(
        FormulaNode(Count(1), 'HCl', FormulaNodeType.COMPOUND, [
            FormulaNode(Count(1), 'H', FormulaNodeType.ATOM, []),
            FormulaNode(Count(1), 'Cl', FormulaNodeType.ATOM, [])
        ]))

    assert actual == expected
def test_parse_formula_K2SO4():
    actual = parse_formula('K2SO4')
    expected = FormulaRoot('K2SO4', [])
    expected.children.append(
        FormulaNode(Count(1), 'K2SO4', FormulaNodeType.COMPOUND, [
            FormulaNode(Count(2), 'K', FormulaNodeType.ATOM, []),
            FormulaNode(Count(1), 'SO4', FormulaNodeType.POLYATOMIC_ION, [
                FormulaNode(Count(1), 'S', FormulaNodeType.ATOM, []),
                FormulaNode(Count(4), 'O', FormulaNodeType.ATOM, [])
            ])
        ]))
    assert actual == expected
def test_parse_formula_BaOH2():
    actual = parse_formula('Ba(OH)2')
    expected = FormulaRoot('Ba(OH)2', [])
    expected.children.append(
        FormulaNode(Count(1), 'Ba(OH)2', FormulaNodeType.COMPOUND, [
            FormulaNode(Count(1), 'Ba', FormulaNodeType.ATOM, []),
            FormulaNode(Count(2), 'OH', FormulaNodeType.POLYATOMIC_ION, [
                FormulaNode(Count(1), 'O', FormulaNodeType.ATOM, []),
                FormulaNode(Count(1), 'H', FormulaNodeType.ATOM, [])
            ])
        ]))
    assert actual == expected
Exemple #6
0
def molar_mass(formula: str) -> Measurement:
    """Calculates the molar mass of a compound"""
    if isinstance(formula, list):
        atoms = formula
    else:
        atoms = parse_formula(formula).flatten()
    total_mass = Measurement("0", GRAMS / MOLES)
    table = PeriodicTable()
    for index, atom in enumerate(atoms):
        count, symbol = atom
        mass = Scinot(table[symbol].atomic_mass)
        product = Measurement(mass * count, GRAMS / MOLES)
        total_mass += product
    return total_mass
def composition(
    formula: str, mass: Measurement = grams('1.000')) -> [Component]:

    composition = Composition()
    elements = parse_formula(formula).flatten()
    _molar_mass = molar_mass(elements)
    for element in elements:
        count, symbol = element
        _mass_percent = molar_mass(symbol) / _molar_mass
        _mass_percent = _mass_percent.value.decimal() * int(count)
        _mass = mass * _mass_percent
        _mass_percent = round(_mass_percent * 100, 2)
        composition.append(Component(count, symbol, _mass, _mass_percent))

    return composition
def test_parse_formula_Fe2O3_combined_with_H2O():
    actual = parse_formula('Fe2O3*[3/2]H2O')
    expected = FormulaRoot('Fe2O3*[3/2]H2O', [])
    expected.children.append(
        FormulaNode(Count(1), 'Fe2O3', FormulaNodeType.COMPOUND, [
            FormulaNode(Count(2), 'Fe', FormulaNodeType.ATOM, []),
            FormulaNode(Count(3), 'O', FormulaNodeType.ATOM, [])
        ]))
    expected.children.append(
        FormulaNode(Count('1.5'), 'H2O', FormulaNodeType.COMPOUND, [
            FormulaNode(Count(2), 'H', FormulaNodeType.ATOM, []),
            FormulaNode(Count(1), 'O', FormulaNodeType.ATOM, [])
        ]))

    assert actual == expected
def test_flatten_formula_Fe2O3_combined_with_H2O():
    actual = parse_formula('Fe2O3*[3/2]H2O').flatten()
    expected = [(Count(2), 'Fe'), (Count('9/2'), 'O'), (Count(3), 'H')]
    assert actual == expected