1 """
2 Math-related helper functions.
3 """
4
5
6
7
8
9
10
11 import math
12
13 from gavo.utils import codetricks
14
15 DEG = math.pi/180
16 ARCSEC = DEG/3600
19 """returns an estimate for the minimum of the single-argument function f
20 on (left,right).
21
22 minInterval is a fourth of the smallest test interval considered.
23
24 For constant functions, a value close to left will be returned.
25
26 This function should only be used on functions having exactly
27 one minimum in the interval.
28 """
29
30
31 mid = (right+left)/2.
32 offset = (right-left)/4.
33 if offset<minInterval:
34 return mid
35 if f(left+offset)<=f(mid+offset):
36 return findMinimum(f, left, mid, minInterval)
37 else:
38 return findMinimum(f, mid, right, minInterval)
39
42 """returns a dictionary mapping hex chars to their binary expansions.
43 """
44 @classmethod
46 return dict(zip(
47 "0123456789abcdef",
48 ["0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111",
49 "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111",]))
50
51
52 -def toBinary(anInt, desiredLength=None):
53 """returns anInt as a string with its binary digits, MSB first.
54
55 If desiredLength is given and the binary expansion is shorter,
56 the value will be padded with zeros.
57
58 >>> toBinary(349)
59 '101011101'
60 >>> toBinary(349, 10)
61 '0101011101'
62 """
63 h2b = getHexToBin()
64 res = "".join(h2b[c] for c in "%x"%anInt).lstrip("0")
65 if desiredLength is not None:
66 res = "0"*(desiredLength-len(res))+res
67 return res
68
71 return sum(seq1[i]*seq2[i] for i in inds)
72
75 """A quick and easy 3d matrix.
76
77 This is just so we don't depend on numpy for trivial stuff. The
78 components are stored in a tuple of rows.
79 """
80 indices = range(3)
81
83 self.rows = (tuple(row1), tuple(row2), tuple(row3))
84
88
90 return not self.__eq__(other)
91
93 """returns the result of right-multiplying self to vec.
94
95 The sequence vec is interpreted as a column vector.
96 """
97 return tuple(_dotprod3(self.rows[i], vec) for i in self.indices)
98
100 """returns the result of multiplying mat to self from the right.
101 """
102 cols = mat.getColumns()
103 return self.__class__(*tuple(
104 tuple(_dotprod3(row, col) for col in cols)
105 for row in self.rows))
106
108 """returns the column vectors of this matrix in a 3-tuple.
109 """
110 return tuple(
111 tuple(self.rows[rowInd][colInd] for rowInd in self.indices)
112 for colInd in self.indices)
113
116 len = math.sqrt(_dotprod3(vec, vec))
117 return tuple(c/len for c in vec)
118
121 """returns a 3-rotation matrix for rotating angle radians around x.
122 """
123 c, s = math.cos(angle), math.sin(angle)
124 return Matrix3((1, 0, 0), (0, c, s), (0, -s, c))
125
128 """returns a 3-rotation matrix for rotating angle radians around z.
129 """
130 c, s = math.cos(angle), math.sin(angle)
131 return Matrix3((c, s, 0), (-s, c, 0), (0, 0, 1))
132
135 """returns a 3-cartesian unit vector pointing to longitude theta,
136 latitude phi.
137
138 The angles are in rad.
139 """
140 cp = math.cos(phi)
141 return math.cos(theta)*cp, math.sin(theta)*cp, math.sin(phi)
142
145 """returns spherical coordinates for a 3-unit vector.
146
147 We do not check if unitvector actually *is* a unit vector. The returned
148 angles are in rad.
149 """
150 x, y, z = unitvector
151 rInXY = math.sqrt(x**2+y**2)
152 if abs(rInXY)<1e-9:
153 theta = 0
154 else:
155 theta = math.atan2(y, x)
156 if theta<0:
157 theta += 2*math.pi
158 phi = math.atan2(z, rInXY)
159 return (theta, phi)
160
163 """returns the spherical distance (in radian) between the unit vectors
164 vec1 and vec2.
165 """
166 return math.acos(_dotprod3(vec1, vec2))
167
172
173
174 if __name__=="__main__":
175 _test()
176