lsst.skymap
g6512b7a353+dfe4f595c2
Toggle main menu visibility
Loading...
Searching...
No Matches
python
lsst
skymap
detail
dodecahedron.py
Go to the documentation of this file.
1
#!/usr/bin/env python
2
3
__all__ = [
'Dodecahedron'
]
4
5
import
math
6
import
numpy
7
8
9
class
Dodecahedron
:
10
"""A dodecahedron with positions of faces and associated vertices.
11
12
Parameters
13
----------
14
withFacesOnPoles : `bool`
15
If True center a face on each pole, else put a vertex on each pole.
16
"""
17
def
__init__
(self, withFacesOnPoles=False):
18
self.
_withFacesOnPoles
= bool(withFacesOnPoles)
19
20
# Basis cartesian vectors describing the faces of a dodecahedron;
21
# the full set of vectors is obtained by choosing both signs of each
22
# nonzero component of each vector.
23
# The orientation of the resulting dodecahedron, while very convenient
24
# for specifying face vectors, is not an orientation we want so it
25
# must be rotated.
26
g = (1.0 + math.sqrt(5.0)) / 2.0
27
faceBases = (
28
(0, 1, g),
29
(1, g, 0),
30
(g, 0, 1),
31
)
32
unrotFaceVecList =
_computeFullVecList
(faceBases)
33
unrotVertexVecList =
_computeDodecahedronVertices
(unrotFaceVecList)
34
35
if
self.
_withFacesOnPoles
:
36
# one face is centered on each pole
37
vec0, vec1 =
_findClosePair
(unrotFaceVecList, 0)
38
rotMat =
_computeCoordTransform
(vec0, vec1)
39
else
:
40
# one vertex is on each pole
41
vec0, vec1 =
_findClosePair
(unrotVertexVecList, 0)
42
rotMat =
_computeCoordTransform
(vec0, vec1, vec1NegativeX=
True
)
43
self.
vertexVecList
= [numpy.dot(rotMat, unrotVertexVec)
for
unrotVertexVec
in
unrotVertexVecList]
44
unsortedFaceList = [numpy.dot(rotMat, unrotFaceVec)
for
unrotFaceVec
in
unrotFaceVecList]
45
self.
faceVecList
=
_sortedVectorList
(unsortedFaceList)
46
47
def
getFaceCtrList
(self):
48
"""Return a list of face centers.
49
50
Returns
51
-------
52
results : `list` of `numpy.ndarray`
53
A list of face centers (in index order); each a unit vector.
54
"""
55
return
self.
faceVecList
[:]
56
57
def
getFaceCtr
(self, ind):
58
"""Return the center of the specified face.
59
60
Parameters
61
----------
62
ind : `int`
63
Index of the face to look up.
64
65
Returns
66
-------
67
results : `numpy.ndarray`
68
Face center as a unit vector.
69
"""
70
return
self.
faceVecList
[ind][:]
71
72
def
getVertices
(self, ind):
73
"""Return the vertices for a given face.
74
75
Parameters
76
----------
77
ind : `int`
78
Face index.
79
80
Returns
81
-------
82
sortedVertexList : `list` of `numpy.ndarray`
83
A list of vertices, each a unit vector.
84
"""
85
faceVec = self.
getFaceCtr
(ind)
86
vertexList, indList =
_findCloseList
(self.
vertexVecList
, faceVec)
87
88
# sort vertex list about face vector (direction is random)
89
sortedVertexList = [vertexList[0]]
90
vertexList = list(vertexList[1:])
91
while
len(vertexList) != 0:
92
nearVertexList, nearInd =
_findCloseList
(vertexList, sortedVertexList[-1])
93
sortedVertexList.append(nearVertexList[0])
94
vertexList.pop(nearInd[0])
95
return
sortedVertexList
96
97
def
getFaceInd
(self, vec):
98
"""Return the index of the face containing the cartesian vector.
99
100
Parameters
101
----------
102
vec : `numpy.ndarray`
103
Cartesian vector (length is ignored).
104
105
Returns
106
-------
107
results : `numpy.ndarray`
108
Index of face containing vec.
109
"""
110
return
numpy.argmax(numpy.dot(self.
faceVecList
, vec))
111
112
def
getWithFacesOnPoles
(self):
113
return
self.
_withFacesOnPoles
114
115
116
def
computeRotationMatrix
(angle, axis):
117
"""Return a 3D rotation matrix for rotation by a specified amount around a
118
specified axis.
119
120
Parameters
121
----------
122
angle : `float`
123
Amount of rotation (rad).
124
axis : `int`
125
Axis of rotation; one of 0, 1 or 2 for x, y or z.
126
"""
127
cosAng = math.cos(angle)
128
sinAng = math.sin(angle)
129
rotMat = numpy.zeros((3, 3), dtype=float)
130
rotMat[axis, axis] = 1
131
rotMat[(axis + 1) % 3, (axis + 1) % 3] = cosAng
132
rotMat[(axis + 2) % 3, (axis + 1) % 3] = sinAng
133
rotMat[(axis + 1) % 3, (axis + 2) % 3] = -sinAng
134
rotMat[(axis + 2) % 3, (axis + 2) % 3] = cosAng
135
return
rotMat
136
137
138
def
_computeCoordTransform
(vec0, vec1, vec1NegativeX=False):
139
"""Compute a rotation matrix that puts vec0 along z and vec1 along +x in
140
the xz plane.
141
142
Parameters
143
----------
144
vec0 : `numpy.ndarray`
145
vector 0
146
vec1 : `numpy.ndarray`
147
vector 1
148
vec1NegativeX : `bool`
149
If True then vec1 is rotated to face negative x.
150
"""
151
# rotate around x by angle of vec0 from z to y
152
xAng = math.atan2(vec0[1], vec0[2])
153
xRotMat =
computeRotationMatrix
(xAng, 0)
154
155
# rotate around y by -angle of rotated vec0 from z to x
156
vec0RotX = numpy.dot(xRotMat, vec0)
157
yAng = -math.atan2(vec0RotX[0], vec0RotX[2])
158
yRotMat =
computeRotationMatrix
(yAng, 1)
159
xyRotMat = numpy.dot(yRotMat, xRotMat)
160
161
# rotate around z by -angle of rotated vec1 from +/-x to y
162
vec1RotXY = numpy.dot(xyRotMat, vec1)
163
xVal = vec1RotXY[0]
164
if
vec1NegativeX:
165
xVal = -xVal
166
zAng = -math.atan2(vec1RotXY[1], xVal)
167
zRotMat =
computeRotationMatrix
(zAng, 2)
168
xyzRotMat = numpy.dot(zRotMat, xyRotMat)
169
return
xyzRotMat
170
171
172
def
_computeDodecahedronVertices
(faceVecList):
173
"""Given a vector of face positions of a Dodecahedron compute the vertices.
174
"""
175
closeIndSetList = []
176
vertexDict = {}
177
for
i
in
range(len(faceVecList)):
178
closeIndSet =
_findCloseIndexSet
(faceVecList, i)
179
if
len(closeIndSet) != 5:
180
raise
RuntimeError(
"Found %s vertices instead of 5 near %s: %s"
%
181
(len(closeIndSet), faceVecList[i], closeIndSet))
182
closeIndSetList.append(closeIndSet)
183
for
i, iCloseIndSet
in
enumerate(closeIndSetList):
184
for
j
in
iCloseIndSet:
185
jCloseIndSet = closeIndSetList[j]
186
sharedCloseIndSet = iCloseIndSet.intersection(jCloseIndSet)
187
if
len(sharedCloseIndSet) != 2:
188
raise
RuntimeError(
"Found %s vertices instead of 2 near %s and %s: %s"
%
189
(len(sharedCloseIndSet), faceVecList[i], faceVecList[j],
190
sharedCloseIndSet))
191
for
k
in
sharedCloseIndSet:
192
key = frozenset((i, j, k))
193
if
key
in
vertexDict:
194
continue
195
vertexVec = faceVecList[i] + faceVecList[j] + faceVecList[k]
196
vertexVec /= numpy.sqrt(numpy.sum(vertexVec**2))
197
vertexDict[key] = vertexVec
198
return
list(vertexDict.values())
199
200
201
def
_computeFullVecList
(basisSet):
202
"""Given a collection of basis vectors, compute all permutations with both
203
signs of all nonzero values.
204
205
For example::
206
207
[(0, 1, 2)] -> [(0, 1, 2), (0, -1, 2), (0, 1, -2), (0, -1, -2)]
208
"""
209
fullSet = []
210
for
basisVec
in
basisSet:
211
vecLen = math.sqrt(numpy.sum(numpy.array(basisVec)**2))
212
valueList = []
213
for
basisValue
in
basisVec:
214
if
basisValue == 0:
215
valueList.append((0,))
216
else
:
217
valueList.append((basisValue, -basisValue))
218
fullSet += list(numpy.array((x, y, z))/vecLen
219
for
z
in
valueList[2]
220
for
y
in
valueList[1]
221
for
x
in
valueList[0]
222
)
223
return
fullSet
224
225
226
def
_findCloseIndexSet
(vecList, ind):
227
"""Given a list of cartesian vectors, return a set of indices of those
228
closest to one of them.
229
230
This is intended for regular grids where distances are quantized.
231
232
Parameters
233
----------
234
vecList : `list`
235
List of cartesian vectors.
236
ind : `int`
237
Index of vector to be nearest.
238
"""
239
dotProductList = numpy.round(numpy.dot(vecList, vecList[ind]), 2)
240
dotProductList[ind] = -9e99
241
minDist = numpy.max(dotProductList)
242
indList = numpy.arange(len(dotProductList))[dotProductList == minDist]
243
return
set(indList)
244
245
246
def
_findCloseList
(vecList, vec):
247
"""Given a list of cartesian vectors, return all those closest to a
248
specified position
249
250
This is intended for regular grids where distances are quantized
251
252
Parameters
253
----------
254
vecList : `list`
255
List of cartesian vectors.
256
vec : `iterable` of `float`
257
Vector to be near.
258
259
Returns
260
-------
261
retList : `list`
262
List of closest vectors.
263
indList : `list`
264
List if indices of those vectors.
265
"""
266
dotProductList = numpy.round(numpy.dot(vecList, vec), 2)
267
minDist = numpy.max(dotProductList)
268
indList = numpy.arange(len(dotProductList))[dotProductList == minDist]
269
retList = numpy.take(vecList, indList, 0)
270
return
retList, indList
271
272
273
def
_findClosePair
(vecList, ind=0):
274
"""Given a list of cartesian vectors and an index, return the vector and
275
one of its closest neighbors.
276
277
Parameters
278
----------
279
vecList : `list` of `numpy.ndarray`
280
List of cartesian vectors.
281
ind : `int`
282
Index of first vector.
283
"""
284
vec = vecList[ind]
285
otherVecList = vecList[0:ind] + vecList[ind+1:]
286
ind1 = numpy.argmax(numpy.dot(otherVecList, vec))
287
return
vec, otherVecList[ind1]
288
289
290
def
_sortedVectorList
(vecList):
291
"""Return a list of cartesian vectors sorted by decreasing latitude and
292
increasing longitude.
293
"""
294
def
vecToSort(vec):
295
ang = round(math.atan2(vec[1], vec[0]), 2)
296
if
ang < 0:
297
ang += 2.0 * math.pi
298
return
(-round(vec[2], 1), ang, vec)
299
300
decoratedList = [vecToSort(v)
for
v
in
vecList]
301
decoratedList.sort()
302
return
[d[2]
for
d
in
decoratedList]
303
304
305
if
__name__ ==
"__main__"
:
306
numpy.set_printoptions(precision=2, suppress=
True
, linewidth=120)
307
308
print(
"Dodecahedron with vertices on poles"
)
309
vertexDodec =
Dodecahedron
(withFacesOnPoles=
False
)
310
for
i
in
range(12):
311
faceVec = vertexDodec.getFaceCtr(i)
312
print(
"Face %2d: %s"
% (i, faceVec))
lsst.skymap.detail.dodecahedron.Dodecahedron
Definition
dodecahedron.py:9
lsst.skymap.detail.dodecahedron.Dodecahedron.__init__
__init__(self, withFacesOnPoles=False)
Definition
dodecahedron.py:17
lsst.skymap.detail.dodecahedron.Dodecahedron.vertexVecList
list vertexVecList
Definition
dodecahedron.py:43
lsst.skymap.detail.dodecahedron.Dodecahedron.getWithFacesOnPoles
getWithFacesOnPoles(self)
Definition
dodecahedron.py:112
lsst.skymap.detail.dodecahedron.Dodecahedron.getFaceCtrList
getFaceCtrList(self)
Definition
dodecahedron.py:47
lsst.skymap.detail.dodecahedron.Dodecahedron._withFacesOnPoles
_withFacesOnPoles
Definition
dodecahedron.py:18
lsst.skymap.detail.dodecahedron.Dodecahedron.getVertices
getVertices(self, ind)
Definition
dodecahedron.py:72
lsst.skymap.detail.dodecahedron.Dodecahedron.getFaceInd
getFaceInd(self, vec)
Definition
dodecahedron.py:97
lsst.skymap.detail.dodecahedron.Dodecahedron.faceVecList
faceVecList
Definition
dodecahedron.py:45
lsst.skymap.detail.dodecahedron.Dodecahedron.getFaceCtr
getFaceCtr(self, ind)
Definition
dodecahedron.py:57
lsst.skymap.detail.dodecahedron.computeRotationMatrix
computeRotationMatrix(angle, axis)
Definition
dodecahedron.py:116
lsst.skymap.detail.dodecahedron._sortedVectorList
_sortedVectorList(vecList)
Definition
dodecahedron.py:290
lsst.skymap.detail.dodecahedron._findCloseIndexSet
_findCloseIndexSet(vecList, ind)
Definition
dodecahedron.py:226
lsst.skymap.detail.dodecahedron._findCloseList
_findCloseList(vecList, vec)
Definition
dodecahedron.py:246
lsst.skymap.detail.dodecahedron._findClosePair
_findClosePair(vecList, ind=0)
Definition
dodecahedron.py:273
lsst.skymap.detail.dodecahedron._computeCoordTransform
_computeCoordTransform(vec0, vec1, vec1NegativeX=False)
Definition
dodecahedron.py:138
lsst.skymap.detail.dodecahedron._computeFullVecList
_computeFullVecList(basisSet)
Definition
dodecahedron.py:201
lsst.skymap.detail.dodecahedron._computeDodecahedronVertices
_computeDodecahedronVertices(faceVecList)
Definition
dodecahedron.py:172
Generated on
for lsst.skymap by
1.17.0