1 |
jonathan |
887 |
#!/usr/bin/env python |
2 |
|
|
# |
3 |
|
|
# Copyright (C) 2002, 2003 by Intevation GmbH |
4 |
|
|
# Authors: |
5 |
|
|
# Thomas Koester <[email protected]> |
6 |
|
|
# |
7 |
|
|
# This program is free software under the GPL (>=v2) |
8 |
|
|
# Read the file COPYING coming with the software for details. |
9 |
|
|
|
10 |
|
|
""" |
11 |
|
|
Range class for Scientific Parameter |
12 |
|
|
""" |
13 |
|
|
|
14 |
|
|
__version__ = "$Revision$" |
15 |
|
|
# $Source$ |
16 |
|
|
# $Id$ |
17 |
|
|
|
18 |
|
|
import re |
19 |
|
|
|
20 |
|
|
_inf = float('1e1000') # FIXME: hack for infinity |
21 |
|
|
|
22 |
|
|
class Range: |
23 |
|
|
|
24 |
|
|
number_re = '(?P<%s>-?(\d+\.?\d*([eE][\-+]?\d+)?|oo))' |
25 |
|
|
brace_re = '(?P<%s>[][])' |
26 |
|
|
range_re = '^' + brace_re % 'left' + number_re % 'begin' + \ |
27 |
|
|
';' + number_re % 'end' + brace_re % 'right' + '$' |
28 |
|
|
parse_range = re.compile(range_re) |
29 |
|
|
|
30 |
|
|
def __init__(self, range=None): |
31 |
|
|
self.SetRange(range) |
32 |
|
|
|
33 |
|
|
def SetRange(self, range): |
34 |
|
|
if isinstance(range, Range): |
35 |
|
|
self.SetRange(str(range)) |
36 |
|
|
elif range in [None, '']: |
37 |
|
|
self.SetRange(']-oo;oo[') |
38 |
|
|
else: |
39 |
|
|
self._range = range |
40 |
|
|
match = self.parse_range.match(self._range) |
41 |
|
|
if match: |
42 |
|
|
self._left = match.group('left') |
43 |
|
|
self._begin = self.float(match.group('begin')) |
44 |
|
|
self._end = self.float(match.group('end')) |
45 |
|
|
self._right = match.group('right') |
46 |
|
|
else: |
47 |
|
|
raise ValueError("can't parse range: %s" % range) |
48 |
|
|
if (self._begin > self._end or |
49 |
|
|
(self._begin == self._end and |
50 |
|
|
(self._left != '[' or self._right != ']'))): |
51 |
|
|
raise ValueError("illegal range: %s" % range) |
52 |
|
|
|
53 |
|
|
def GetRange(self): |
54 |
|
|
"""return internal representation of range |
55 |
|
|
|
56 |
|
|
4-tuple ('[' or ']', begin(float), end(float), '[' or ']') |
57 |
|
|
|
58 |
|
|
""" |
59 |
|
|
return (self._left, self._begin, self._end, self._right) |
60 |
|
|
|
61 |
|
|
def float(self, string): |
62 |
|
|
if string == 'oo': |
63 |
|
|
return _inf |
64 |
|
|
elif string == '-oo': |
65 |
|
|
return -_inf |
66 |
|
|
else: |
67 |
|
|
return float(string) |
68 |
|
|
|
69 |
|
|
def _float2string(self, value): |
70 |
|
|
"""convert float value to string |
71 |
|
|
|
72 |
|
|
(minus) infinity will be converted to (-)oo, |
73 |
|
|
scientific notation will be used if necessary. |
74 |
|
|
|
75 |
|
|
""" |
76 |
|
|
if value == _inf: |
77 |
|
|
return 'oo' |
78 |
|
|
elif value == -_inf: |
79 |
|
|
return '-oo' |
80 |
|
|
else: |
81 |
|
|
return "%g" % value |
82 |
|
|
|
83 |
|
|
def string(self, range): |
84 |
|
|
"""convert internal representation to string""" |
85 |
|
|
left, begin, end, right = range |
86 |
|
|
return "%s%s;%s%s" % (left, self._float2string(begin), |
87 |
|
|
self._float2string(end), right) |
88 |
|
|
|
89 |
|
|
def __contains__(self, value): |
90 |
|
|
if self._left == ']': |
91 |
|
|
contains = value > self._begin |
92 |
|
|
else: |
93 |
|
|
contains = value >= self._begin |
94 |
|
|
if self._right == '[': |
95 |
|
|
contains = contains and (value < self._end) |
96 |
|
|
else: |
97 |
|
|
contains = contains and (value <= self._end) |
98 |
|
|
return contains |
99 |
|
|
|
100 |
|
|
def __eq__(self, other): |
101 |
|
|
return (self.GetRange() == other.GetRange()) |
102 |
|
|
|
103 |
|
|
def __ne__(self, other): |
104 |
|
|
return not self.__eq__(other) |
105 |
|
|
|
106 |
|
|
def __str__(self): |
107 |
|
|
return self.string(self.GetRange()) |
108 |
|
|
|
109 |
|
|
|
110 |
|
|
def _test(): |
111 |
|
|
range1 = Range(']0;99]') |
112 |
|
|
print 'range1 =', range1, range1.GetRange() |
113 |
|
|
for i in [-0.1, 0, 0.1, 9.9, 99, 99.9]: |
114 |
|
|
print '%4.1f in range1 =' % i, i in range1 |
115 |
|
|
range2 = Range(']-oo;10[') |
116 |
|
|
print 'range2 =', range2, range2.GetRange() |
117 |
|
|
for i in [-0.1, 0, 0.1, 9.9, 10, 10.1]: |
118 |
|
|
print '%4.1f not in range2 =' % i, i not in range2 |
119 |
|
|
range3 = Range(']1e-1;1E2]') |
120 |
|
|
print 'range3 =', range3, range3.GetRange() |
121 |
|
|
for i in [0, 0.1, 0.11, 10, 100, 101]: |
122 |
|
|
print '%4.1f not in range3 =' % i, i not in range3 |
123 |
|
|
print 'range3 != range2 =', range3 != range2 |
124 |
|
|
print 'range3 != Range("]1e-1;1E2]") =', range3 != Range("]1e-1;1E2]") |
125 |
|
|
|
126 |
|
|
range4 = Range('') |
127 |
|
|
print 'range4 =', range4, range4.GetRange() |
128 |
|
|
|
129 |
|
|
range5 = Range(']0;99E+00]') |
130 |
|
|
print 'range5 =', range5, range5.GetRange() |
131 |
|
|
range6 = Range(']0;99E+01]') |
132 |
|
|
print 'range6 =', range6, range6.GetRange() |
133 |
|
|
range7 = Range(']0;99E-01]') |
134 |
|
|
print 'range7 =', range7, range7.GetRange() |
135 |
|
|
|
136 |
|
|
if __name__ == "__main__": |
137 |
|
|
_test() |