1 """
2 Determining equivalence for STC systems.
3
4 Frequenently, one needs to decide if two systems are "close enough" to
5 work together, e.g., when building geometries or for ADQL geometry
6 predicates. This code lets you define matching policies.
7 """
8
9
10
11
12
13
14
15 import re
16
17 from gavo import utils
18
19
20 _identifierPat = re.compile("[a-zA-Z_][a-zA-Z_]*$")
24 """returns a function getting key from an object.
25
26 key is dot-seperated sequence of python identifiers (this is checked; a
27 ValueError is raised at generation time for malformed keys).
28
29 This function is used to generate functions accessing parts of
30 STC trees. If any attribute within key does not exist, the generated
31 functions return None.
32 """
33 if (not key.strip()
34 or None in (_identifierPat.match(p) for p in key.split("."))):
35 raise ValueError("'%s' is no valid STC key."%key)
36 getterSrc = "\n".join([
37 "def get(ob):",
38 " try:",
39 " return ob.%s"%key,
40 " except AttributeError:",
41 " return None"])
42 ns = {}
43 exec getterSrc in ns
44 return ns["get"]
45
48 """A base class for EquivalencePolicy elements.
49
50 An EquivalenceCondition has a
51 check(sys1, sys2) -> boolean
52 method. Everything else is up to the individual objects.
53 """
54 - def check(self, sys1, sys2):
55 """returns true when sys1 and sys2 are equivalent as far as this
56 condition is concerned.
57
58 sysN are dm.CoordSys instances.
59 """
60 return False
61
63 """returns True if val1 or val2 are None of if they are equal.
64
65 This should be the default logic for Equ.Pols.
66 """
67 if val1 is None or val2 is None:
68 return True
69 return val1==val2
70
73 """An equivalence condition specifying a certain key being equal if
74 non-None in both objects.
75
76 key is a dot-seperated sequence of attribute names withing STC system
77 objects.
78 """
81
82 - def check(self, sys1, sys2):
83 return self._checkWithNone(
84 self.getKey(sys1), self.getKey(sys2))
85
88 """An equivalence condition tailored for reference frames.
89
90 It considers ICRS and FK5 J2000 equivalent.
91 """
95
96 - def check(self, sys1, sys2):
97 frame1, frame2 = self.getFrame(sys1), self.getFrame(sys2)
98 eq1, eq2 = self.getEquinox(sys1), self.getEquinox(sys2)
99 if (self._checkWithNone(frame1, frame2)
100 and self._checkWithNone(eq1, eq2)):
101 return True
102
103 if (set([frame1, frame2])==set(["ICRS", "FK5"])):
104
105 eq = [eq for eq in (eq1, eq2) if eq][0]
106 if eq.startswith("J2000"):
107 return True
108 return False
109
112 """A policy specifying when two STC system objects are considered equivalent.
113
114 checkedKeys is a sequence of EquivalenceConditions or strings. If
115 strings are passed, they are turned into KeysEquivalent conditions
116 for the keys specified in the strings.
117
118 You can also pass entire STC trees to match.
119 """
127
128 - def match(self, ast1, ast2):
129 ast1 = getattr(ast1, "astroSystem", ast1)
130 ast2 = getattr(ast2, "astroSystem", ast2)
131 for cond in self.conditions:
132 if not cond.check(ast1, ast2):
133 return False
134 return True
135
136
137
138
139 defaultPolicy = EquivalencePolicy([
140 RefFramesEquivalent(),
141 "timeFrame.timeScale",
142 "spaceFrame.flavor",
143 "spaceFrame.nDim",
144 "spectralFrame.refPos.standardOrigin",
145 "redshiftFrame.refPos.standardOrigin",
146 "redshiftFrame.type",
147 "redshiftFrame.dopplerDef",])
148