1 """
2 Definitions and shared code for STC processing.
3 """
4
5
6
7
8
9
10
11 import math
12 import operator
13
14 from gavo import utils
15 from gavo.utils import ElementTree
16 from gavo.utils.stanxml import Stub, registerPrefix, schemaURL
17
18
21
23 """is raised if an STC-S expression could not be parsed.
24
25 Low-level routines raise a pyparsing ParseException. Only higher
26 level functions raise this error. The offending expression is in
27 the expr attribute, the start position of the offending phrase in pos.
28 """
29 - def __init__(self, msg, expr=None, pos=None):
33
34
36 """is raised when a literal is not well-formed.
37
38 There is an attribute literal giving the malformed literal.
39 """
41 STCError.__init__(self, msg)
42 self.args = [msg, literal]
43 self.literal = literal
44
46 """is raised when assumptions about the library behaviour are violated.
47 """
48
50 """is raised when some STC specification is inconsistent.
51 """
52
54 """is raised when some impossible operation on units is requested.
55 """
56
58 """is raised when something is wrong with STC-X.
59 """
60
62 """is raised when the current implementation limits are reached.
63 """
64
65
66
67 TWO_PI = 2*math.pi
68 tropicalYear = 365.242198781
69 secsPerJCy = 36525*86400.
70
71 STCNamespace = "http://www.ivoa.net/xml/STC/stc-v1.30.xsd"
72 XlinkNamespace = "http://www.w3.org/1999/xlink"
73
74 registerPrefix("stc", STCNamespace,
75 schemaURL("stc-v1.30.xsd"))
76 registerPrefix("xlink", XlinkNamespace,
77 schemaURL("xlink.xsd"))
78
79
80
81
82
83
84 stcSpaceRefFrames = set(["ICRS", "FK4", "FK5", "ECLIPTIC", "GALACTIC_I",
85 "GALACTIC_II", "SUPER_GALACTIC", "AZ_EL", "BODY", "GEO_C", "GEO_D", "MAG",
86 "GSE", "GSM", "SM", "HGC", "HGS", "HPC", "HPR", "HEE", "HEEQ", "HGI",
87 "HRTN", "MERCURY_C", "VENUS_C", "LUNA_C", "MARS_C", "JUPITER_C_III",
88 "SATURN_C_III", "UNKNOWNFrame"])
89
90
91 stcRefPositions = set(["TOPOCENTER", "BARYCENTER", "HELIOCENTER", "GEOCENTER",
92 "LSR", "LSRK", "LSRD", "GALACTIC_CENTER", "LOCAL_GROUP_CENTER", "MOON",
93 "EMBARYCENTER", "MERCURY", "VENUS", "MARS", "JUPITER", "SATURN", "URANUS",
94 "NEPTUNE", "PLUTO", "RELOCATABLE", "UNKNOWNRefPos", "CoordRefPos"])
95
96
97 stcCoordFlavors = set(["SPHERICAL", "CARTESIAN", "UNITSPHERE", "POLAR",
98 "CYLINDRICAL", "STRING", "HEALPIX"])
99
100
101 stcTimeScales = set(["TT", "TDT", "ET", "TAI", "IAT", "UTC", "TEB", "TDB",
102 "TCG", "TCB", "LST", "nil"])
103
104
105
106
108 """returns true if val1==val2 up to a fudge factor.
109
110 This only works for floats.
111
112 >>> _compareFloat(30.0, 29.999999999999996)
113 True
114 """
115 try:
116 return abs(val1-val2)/val1<1e-12
117 except ZeroDivisionError:
118 return val2==0
119
120
122 """compares val1 and val2 inexactly.
123
124 This is for comparing floats or sequences of floats. If you pass in
125 other sequences, bad things will happen.
126
127 It will return true if val1 and val2 are deemed equal.
128
129 >>> _aboutEqual(2.3, 2.2999999999999997)
130 True
131 >>> _aboutEqual(2.3, 2.299999997)
132 False
133 >>> _aboutEqual(None, 2.3)
134 False
135 >>> _aboutEqual((1e-10,1e10), (1.00000000000001e-10,1.00000000000001e10))
136 True
137 >>> _aboutEqual((1e-10,1e10), (1.0000000001e-10,1.000000001e10))
138 False
139 """
140 if val1==val2:
141 return True
142 if isinstance(val1, float) and isinstance(val2, float):
143 return _compareFloat(val1, val2)
144 try:
145 return reduce(operator.and_, (_compareFloat(*p)
146 for p in zip(val1, val2)))
147 except TypeError:
148 return False
149
150
152 """The base class for all nodes in STC ASTs.
153 """
154 _a_ucd = None
155 _a_id = None
156
157 inexactAttrs = set()
158
159
161 if not isinstance(other, self.__class__):
162 return False
163 if self is other:
164 return True
165 for name, _ in self._nodeAttrs:
166 if name=="id":
167 continue
168 if name in self.inexactAttrs:
169 if not _aboutEqual(getattr(self, name), getattr(other, name)):
170 return False
171 elif getattr(self, name)!=getattr(other, name):
172 return False
173 return True
174
176 return not self==other
177
179 return hash(id(self))
180
182 """sets id to some value if still None.
183 """
184 if self.id is None:
185 self.id = utils.intToFunnyWord(id(self))
186
187
189 """A column reference instead of a true value, occurring in an STC-S tree.
190 """
191 name_ = "_colRef"
192
193
194
195
196 toParam = False
197
200
201
203 raise STCValueError("ColRefs (here, %s) cannot be used in arithmetic"
204 " expressions."%repr(self))
205
207 return self.dest.encode(encoding)
208
211
213 return func(self, self.dest, {}, [])
214
215
217 """A ColRef that refers to an in-DB geometry.
218
219 These comprise the entire arguments of a geometry (or all coordinates
220 of a vector). They implement __len__ as soon as they are validated
221 (in stcsast; we don't do col. refs in stc-x); their len is the
222 expected number of elements.
223 """
224 expectedLength = None
225
231
234
235
237 """returns val standardized as a latitude.
238
239 Our latitudes are always in [0, 2*pi].
240 """
241 val = math.fmod(val, TWO_PI)
242 if val<0:
243 val += TWO_PI
244 return val
245
246
248 """returns val standardized as a latitude.
249
250 Our latitudes are always in [-pi, pi].
251 """
252 val = math.fmod(val, TWO_PI)
253 if val<-math.pi:
254 val += TWO_PI
255 if val>math.pi:
256 val -= TWO_PI
257 return val
258
259
263
264 if __name__=="__main__":
265 _test()
266