0

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?

4
Contributors
4
Replies
5
Views
9 Years
Discussion Span
Last Post by sneekula
0

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.

0

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!

0

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.

This question has already been answered. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.