I want to make a small Molecular Weight calculator. If the user for instance enters the molecular formula for dichloro-benzoic acid as "C6H3Cl2COOH", I would like to split it into a list like so I can then combine all the carbons, chlorines, oxygens and hydrogens and go on to the calculation.

Any good ideas how to do the splitting?

Recommended Answers

All 4 Replies

A split on a number followed by a letter is the obvious place to start. It would be nice if all of the symbols were camel case, but I don't think you can rely on that. For the "OOH" in "C6H3Cl2COOH" (no pun intended), you can look for a match in a dictionary of symbols, but would have to allow for "He" and not stop at the "H". Just some off the top of my head thoughts.

Hello Sneekula, glad to see you back and still using Python for your chemistry problems.

Your problem is a bit more hairy, since you have to parse the string with a look ahead so you can separate it into something useful, like a list of (element, number) tuples. You can then iterate through the list a tuple at a time, look up the element for its atomic weight in a {element:atomic-weight} dictionary (just happen to have one of those laying around). Then multiply the atomic-weight by the number and sum up the results to give you the total molecular weight.

Here is one way to get the list of tuples ...

# molecular weight calculator version 1

mf = "C6H3Cl2COOH"

char_list = list(mf)
# test it ...
print char_list
"""
my result -->
['C', '6', 'H', '3', 'C', 'l', '2', 'C', 'O', 'O', 'H']
"""

temp_list = []
temp_str = ""
temp_num = ""
for x, c in enumerate(char_list):
    #print x, c
    if c.isupper():
        temp_str = ""
        temp_num = ""
    if c.isalpha():
        temp_str += c
    if c.isdigit():
        temp_num += c
    # do your look ahead
    if x+1 < len(char_list):
        if char_list[x+1].isupper() and temp_num == "":
            temp_num = "1"
        if char_list[x+1].isupper():
            temp_list.append((temp_str, int(temp_num)))
    # except for the last element
    else:
        if temp_num == "":
            temp_num = "1"
        temp_list.append((temp_str, int(temp_num)))

# test it ...
print temp_list
"""
my result -->
[('C', 6), ('H', 3), ('Cl', 2), ('C', 1), ('O', 1), ('O', 1), ('H', 1)]
"""

Here is the element_dictionary (from an old Delphi program of mine) ...

# dictionary of element:atomic-weight pairs courtesy of vegaseat
element_dict = {
'Ac': 227.000000,
'Ag': 107.868000,
'Al': 26.981540,
'Am': 243.000000,
'Ar': 39.948000,
'As': 74.921600,
'At': 210.000000,
'Au': 196.966500,
'B': 10.811000,
'Ba': 137.330000,
'Be': 9.012180,
'Bi': 208.980400,
'Br': 79.904000,
'C': 12.011000,
'Ca': 40.078000,
'Cd': 112.410000,
'Ce': 140.120000,
'Cl': 35.452700,
'Co': 58.933200,
'Cr': 51.996000,
'Cs': 132.905400,
'Cu': 63.546000,
'Dy': 162.500000,
'Er': 167.260000,
'Eu': 151.965000,
'F': 18.998400,
'Fe': 55.847000,
'Fr': 223.000000,
'Ga': 69.723000,
'Gd': 157.250000,
'Ge': 72.610000,
'H': 1.007940,
'He': 4.002600,
'Hf': 178.490000,
'Hg': 200.590000,
'Ho': 164.930300,
'I': 126.904500,
'In': 114.820000,
'Ir': 192.220000,
'K': 39.098300,
'Kr': 83.800000,
'La': 138.905500,
'Li': 6.941000,
'Lu': 174.967000,
'Mg': 24.305000,
'Mn': 54.938000,
'Mo': 95.940000,
'N': 14.006700,
'Na': 22.989770,
'Nb': 92.906400,
'Nd': 144.240000,
'Ne': 20.179700,
'Ni': 58.693400,
'Np': 237.048200,
'O': 15.999400,
'Os': 190.200000,
'P': 30.973760,
'Pa': 231.035900,
'Pb': 207.200000,
'Pd': 106.420000,
'Pm': 145.000000,
'Po': 209.000000,
'Pr': 140.907700,
'Pt': 195.080000,
'Pu': 244.000000,
'Ra': 226.025400,
'Rb': 85.467800,
'Re': 186.207000,
'Rh': 102.905500,
'Rn': 222.000000,
'Ru': 101.070000,
'S': 32.066000,
'Sb': 121.757000,
'Sc': 44.955900,
'Se': 78.960000,
'Si': 28.085500,
'Sm': 150.360000,
'Sn': 118.710000,
'Sr': 87.620000,
'Ta': 180.947900,
'Tb': 158.925300,
'Tc': 98.000000,
'Te': 127.600000,
'Th': 232.038100,
'Ti': 47.880000,
'Tl': 204.383000,
'Tm': 168.934200,
'U': 238.029000,
'V': 50.941500,
'W': 183.850000,
'Xe': 131.290000,
'Y': 88.905900,
'Yb': 173.040000,
'Zn': 65.390000,
'Zr': 91.224000,
}

Let us know what you did with it!

I once wrote one :icon_wink: It's part of one of the greatest periodic table programs of the world *cough*. You can find it here.

Then there is pyparsing. You might be interested in one of the examples ... chemicalFormulas.py :)

Thanks mawe, your Periodic Table program is sweet!

Thanks vegaseat, I will follow your advice for my simple MW calculator. When done, I will put it into the Python snippets.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.