-
Notifications
You must be signed in to change notification settings - Fork 0
/
units_parser.py
105 lines (93 loc) · 3.29 KB
/
units_parser.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# -*- coding: utf-8 -*-
# units_parser.py
# Christian Hill, 28/11/2011
#
# The units_parser module, which provides some methods for manipulating
# physical units:
import units
from pyparsing import Word, Group, Literal, Suppress, ParseException, oneOf,\
Optional
import codecs
class UnitsError(Exception):
def __init__(self, error_str):
self.error_str = error_str
def __str__(self):
return self.error_str
class UnitAtom(object):
def __init__(self, ustring):
pre = None
if len(ustring) > 1:
pre, post = ustring[0], ustring[1:]
else:
post = ustring
caps = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
lowers = caps.lower()
letters = u'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_0'
digits = u'123456789'
exponent = Word(digits + '-')
prefix = oneOf(units.si_prefixes.keys())
ustem = Word(letters + u'Å')
uatom = (Group( u'1' | (Optional(prefix) + ustem)) + Optional(exponent)) | (Group( u'1' | ustem) + Optional(exponent))
def parse_unit_atom(unit_atom):
#print ' ',unit_atom,
try:
uatom_data = uatom.parseString(unit_atom)
except ParseException:
raise
raise UnitsError("Invalid unit atom syntax: %s" % unit_atom)
if len(uatom_data[0]) == 1:
prefix = None; stem = uatom_data[0][0]
else:
prefix = uatom_data[0][0]; stem = uatom_data[0][1]
if stem not in units.base_unit_stems:
prefix = None; stem = ''.join(uatom_data[0])
try:
base_unit = units.base_unit_stems[stem]
except:
raise UnitsError("Unrecognised unit: %s" % unit_atom)
exponent = 1
if len(uatom_data) == 2:
exponent = int(uatom_data[1])
#print prefix, stem, exponent
return units.AtomUnit(prefix, base_unit, exponent)
def parse_mult_units(munit):
atom_units = []
for s_unit in munit.split('.'):
atom_unit = parse_unit_atom(s_unit)
if atom_unit.base_unit.stem != '1':
# the unity 'unit' is not really a unit
atom_units.append(atom_unit)
return units.CompoundUnit(atom_units)
def parse_compound_units(cunit):
#print cunit
dims = units.Dimensions()
div_fields = cunit.split('/')
ndiv_fields = len(div_fields)
compound_unit = parse_mult_units(div_fields[0])
for div_field in div_fields[1:]:
compound_unit = compound_unit / parse_unit_atom(div_field)
return compound_unit
#parse_unit_atom('cm3')
#parse_unit_atom('nmol')
#parse_unit_atom('Mmol')
#parse_unit_atom('mmHg')
#parse_unit_atom('pDa')
#parse_unit_atom('s-1')
#parse_unit_atom(u'μs')
#parse_unit_atom(u'Å')
#parse_unit_atom(u'mÅ-1')
#
#tests = ['cm/s-1/K2', '1/atm/cm']
#tests = []
#for line in codecs.open('xsams_units.txt', 'r', encoding='utf-8'):
# tests.append(line.strip())
#for test in tests:
# compound_unit = parse_compound_units(test)
# #print test,':',compound_unit,'conversion to SI:', compound_unit.to_si()
# print test,':',compound_unit,'dimensions:', compound_unit.dims
#compound_unit1 = parse_compound_units('cm-1/atm')
#compound_unit2 = parse_compound_units('cm-1/Pa')
#compound_unit3 = parse_compound_units('1/m/Torr')
#compound_unit1 = parse_compound_units('Torr')
#compound_unit2 = parse_compound_units('mbar')
#print compound_unit1,'to',compound_unit2,':', compound_unit1.conversion(compound_unit2)