LSST Applications 26.0.0,g0265f82a02+6660c170cc,g07994bdeae+30b05a742e,g0a0026dc87+17526d298f,g0a60f58ba1+17526d298f,g0e4bf8285c+96dd2c2ea9,g0ecae5effc+c266a536c8,g1e7d6db67d+6f7cb1f4bb,g26482f50c6+6346c0633c,g2bbee38e9b+6660c170cc,g2cc88a2952+0a4e78cd49,g3273194fdb+f6908454ef,g337abbeb29+6660c170cc,g337c41fc51+9a8f8f0815,g37c6e7c3d5+7bbafe9d37,g44018dc512+6660c170cc,g4a941329ef+4f7594a38e,g4c90b7bd52+5145c320d2,g58be5f913a+bea990ba40,g635b316a6c+8d6b3a3e56,g67924a670a+bfead8c487,g6ae5381d9b+81bc2a20b4,g93c4d6e787+26b17396bd,g98cecbdb62+ed2cb6d659,g98ffbb4407+81bc2a20b4,g9ddcbc5298+7f7571301f,ga1e77700b3+99e9273977,gae46bcf261+6660c170cc,gb2715bf1a1+17526d298f,gc86a011abf+17526d298f,gcf0d15dbbd+96dd2c2ea9,gdaeeff99f8+0d8dbea60f,gdb4ec4c597+6660c170cc,ge23793e450+96dd2c2ea9,gf041782ebf+171108ac67
LSST Data Management Base Package
Loading...
Searching...
No Matches
pupil.py
Go to the documentation of this file.
1# This file is part of afw.
2#
3# Developed for the LSST Data Management System.
4# This product includes software developed by the LSST Project
5# (https://www.lsst.org).
6# See the COPYRIGHT file at the top-level directory of this distribution
7# for details of code ownership.
8#
9# This program is free software: you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 3 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program. If not, see <https://www.gnu.org/licenses/>.
21
22__all__ = ['PupilFactory', 'Pupil']
23
24import numpy as np
25
26
27class Pupil:
28 """Pupil obscuration function.
29
30 Parameters
31 ----------
32 illuminated : `numpy.ndarray`, (Nx, Ny)
33 2D numpy array indicating which parts of the pupil plane are
34 illuminated.
35 size : `float`
36 Size of pupil plane array in meters. Note that this may be larger
37 than the actual diameter of the illuminated pupil to accommodate
38 zero-padding.
39 scale : `float`
40 Sampling interval of pupil plane array in meters.
41 """
42
43 def __init__(self, illuminated, size, scale):
44 self.illuminated = illuminated
45 self.size = size
46 self.scale = scale
47
48
50 """Pupil obscuration function factory for use with Fourier optics.
51
52 Parameters
53 ----------
54 visitInfo : `lsst.afw.image.VisitInfo`
55 Visit information for a particular exposure.
56 pupilSize : `float`
57 Size in meters of constructed Pupil array.
58 Note that this may be larger than the actual diameter of the
59 illuminated pupil to accommodate zero-padding.
60 npix : `int`
61 Constructed Pupils will be npix x npix.
62 """
63
64 def __init__(self, visitInfo, pupilSize, npix):
65 self.visitInfo = visitInfo
66 self.pupilSize = pupilSize
67 self.npix = npix
68 self.pupilScale = pupilSize/npix
69 u = (np.arange(npix, dtype=np.float64) - (npix - 1)/2) * self.pupilScale
70 self.u, self.v = np.meshgrid(u, u)
71
72 def getPupil(self, point):
73 """Calculate a Pupil at a given point in the focal plane.
74
75 Parameters
76 ----------
77 point : `lsst.geom.Point2D`
78 The focal plane coordinates.
79
80 Returns
81 -------
82 pupil : `Pupil`
83 The Pupil at ``point``.
84 """
85 raise NotImplementedError(
86 "PupilFactory not implemented for this camera")
87
88 @staticmethod
89 def _pointLineDistance(p0, p1, p2):
90 """Compute the right-angle distance between the points given by `p0`
91 and the line that passes through `p1` and `p2`.
92
93 Parameters
94 ----------
95 p0 : `tuple` of `numpy.ndarray`
96 2-tuple of numpy arrays (x, y focal plane coordinates)
97 p1 : ``pair`` of `float`
98 x,y focal plane coordinates
99 p2 : ``pair`` of `float`
100 x,y focal plane coordinates
101
102 Returns
103 -------
104 distances : `numpy.ndarray`
105 Numpy array of distances; shape congruent to p0[0].
106 """
107 x0, y0 = p0
108 x1, y1 = p1
109 x2, y2 = p2
110 dy21 = y2 - y1
111 dx21 = x2 - x1
112 return np.abs(dy21*x0 - dx21*y0 + x2*y1 - y2*x1)/np.hypot(dy21, dx21)
113
114 def _fullPupil(self):
115 """Make a fully-illuminated Pupil.
116
117 Returns
118 -------
119 pupil : `Pupil`
120 The illuminated pupil.
121 """
122 illuminated = np.ones(self.u.shape, dtype=bool)
123 return Pupil(illuminated, self.pupilSize, self.pupilScale)
124
125 def _cutCircleInterior(self, pupil, p0, r):
126 """Cut out the interior of a circular region from a Pupil.
127
128 Parameters
129 ----------
130 pupil : `Pupil`
131 Pupil to modify in place.
132 p0 : `pair`` of `float`
133 2-tuple indicating region center.
134 r : `float`
135 Circular region radius.
136 """
137 r2 = (self.u - p0[0])**2 + (self.v - p0[1])**2
138 pupil.illuminated[r2 < r**2] = False
139
140 def _cutCircleExterior(self, pupil, p0, r):
141 """Cut out the exterior of a circular region from a Pupil.
142
143 Parameters
144 ----------
145 pupil : `Pupil`
146 Pupil to modify in place
147 p0 : `pair`` of `float`
148 2-tuple indicating region center.
149 r : `float`
150 Circular region radius.
151 """
152 r2 = (self.u - p0[0])**2 + (self.v - p0[1])**2
153 pupil.illuminated[r2 > r**2] = False
154
155 def _cutRay(self, pupil, p0, angle, thickness):
156 """Cut out a ray from a Pupil.
157
158 Parameters
159 ----------
160 pupil : `Pupil`
161 Pupil to modify in place.
162 p0 : `pair`` of `float`
163 2-tuple indicating ray starting point.
164 angle : `pair` of `float`
165 Ray angle measured CCW from +x.
166 thickness : `float`
167 Thickness of cutout.
168 """
169 angleRad = angle.asRadians()
170 # the 1 is arbitrary, just need something to define another point on
171 # the line
172 p1 = (p0[0] + 1, p0[1] + np.tan(angleRad))
173 d = PupilFactory._pointLineDistance((self.u, self.v), p0, p1)
174 pupil.illuminated[(d < 0.5*thickness)
175 & ((self.u - p0[0])*np.cos(angleRad)
176 + (self.v - p0[1])*np.sin(angleRad) >= 0)] = False
177
178 def _centerPupil(self, pupil):
179 """Center the illuminated portion of the pupil in array.
180
181 Parameters
182 ----------
183 pupil : `Pupil`
184 Pupil to modify in place
185 """
186 def center(arr, axis):
187 smash = np.sum(arr, axis=axis)
188 w = np.where(smash)[0]
189 return int(0.5*(np.min(w)+np.max(w)))
190 ycenter = center(pupil.illuminated, 0)
191 xcenter = center(pupil.illuminated, 1)
192 ytarget = pupil.illuminated.shape[0]//2
193 xtarget = pupil.illuminated.shape[1]//2
194 pupil.illuminated = np.roll(np.roll(pupil.illuminated,
195 xtarget-xcenter,
196 axis=0),
197 ytarget-ycenter,
198 axis=1)
_cutRay(self, pupil, p0, angle, thickness)
Definition pupil.py:155
__init__(self, visitInfo, pupilSize, npix)
Definition pupil.py:64
_cutCircleExterior(self, pupil, p0, r)
Definition pupil.py:140
_cutCircleInterior(self, pupil, p0, r)
Definition pupil.py:125
__init__(self, illuminated, size, scale)
Definition pupil.py:43
Information about a single exposure of an imaging camera.
Definition VisitInfo.h:68