Differences between revisions 1 and 2
Revision 1 as of 2010-11-23 05:33:09
Size: 3013
Editor: Eviatar
Comment:
Revision 2 as of 2010-11-23 05:35:51
Size: 3082
Editor: Eviatar
Comment:
Deletions are marked like this. Additions are marked like this.
Line 13: Line 13:
    '''Parses formulas and calculates molar mass using atomic weights at http://www.chem.qmul.ac.uk/iupac/AtWt/'''     '''Parses formulas and calculates molar mass using atomic weights at http://www.chem.qmul.ac.uk/iupac/AtWt/. It also shows the calculation used.'''
Line 98: Line 98:

{{attachment:molarmass.png}}

Sage Interactions - Chemistry

goto interact main page

Molar Mass Calculator

by Eviatar Bach

import re, urllib, decimal
def molarmass(compound):
    '''Parses formulas and calculates molar mass using atomic weights at http://www.chem.qmul.ac.uk/iupac/AtWt/. It also shows the calculation used.'''
    elementfinder=re.compile('([()]?)([A-Z]?[a-z]*)([()]?)(\d*)([()]?)'*len(compound))
    element=re.search(elementfinder, compound)
    elementlist=[]
    for a in range(1, len(compound)*5+1):
        try:
            elementlist.append(int(element.group(a)))
        except ValueError:
            elementlist.append(element.group(a))

    for item in range(len(elementlist)):
        try: elementlist.remove('')
        except ValueError:
            break

    var(reduce(lambda x, y: str(x)+' '+str(y), elementlist))

    #Adds multiplication for subscripts
    for index, i in enumerate(elementlist):
        try:
            eval(i)
            if isinstance(elementlist[index+1], int):
                elementlist.insert(index+1, '*')
        except:
            pass

    #Adds multiplication after brackets
    for index, a in enumerate(elementlist):
        if a==')' and isinstance(elementlist[index+1], int):
            elementlist.insert(index+1, '*')
            
    #Adds addition before brackets
    for index, a in enumerate(elementlist):
        try:
            if isinstance(a, int) and elementlist[index+1]=='(':
                elementlist.insert(index+1, '+')
        except IndexError:
            break
            
    #Adds addition
    for index, a in enumerate(elementlist):
        try:
            eval(a); eval(elementlist[index+1])
            elementlist.insert(index+1, '+')
        except:
            pass
            
    for index, a in enumerate(elementlist):
        try:
            eval(elementlist[index+1])
            if isinstance(a, int):
                elementlist.insert(index+1, '+')
        except:
            pass
            
    #Convert to ints
    for index, a in enumerate(elementlist):
        try:
            int(a) 
            elementlist[index]='int(%s)' %a
        except: pass

    elementpage=urllib.urlopen('http://www.chem.qmul.ac.uk/iupac/AtWt/').read()

    for index, atom in enumerate(elementlist):
        try:
            massfinder=re.compile('%s</td><td>\w+\s*</td><td>\[?(\d*\.?\d*)\]?\(?' %atom)
            found=re.search(massfinder, elementpage)
            elementlist[index]='decimal.Decimal("%s")' %found.group(int(1))
        except: pass
        
    print 'Calculation:',
        
    for a in elementlist:
        try: print str(eval(a)),
        except: print a,
            
    elementlist=reduce(lambda x, y: str(x)+str(y), elementlist)

    print '\n\n', 'Molar mass:', eval(elementlist), 'g/mol'

@interact
def _(compound=input_box(label='Compound', default='H2O', type=str)):
    molarmass(compound)

molarmass.png

interact/chemistry (last edited 2012-06-13 06:35:25 by eviatarbach)