LSSTApplications  16.0-11-g09ed895+2,16.0-11-g12e47bd,16.0-11-g9bb73b2+6,16.0-12-g5c924a4+6,16.0-14-g9a974b3+1,16.0-15-g1417920+1,16.0-15-gdd5ca33+1,16.0-16-gf0259e2,16.0-17-g31abd91+7,16.0-17-g7d7456e+7,16.0-17-ga3d2e9f+13,16.0-18-ga4d4bcb+1,16.0-18-gd06566c+1,16.0-2-g0febb12+21,16.0-2-g9d5294e+69,16.0-2-ga8830df+6,16.0-20-g21842373+7,16.0-24-g3eae5ec,16.0-28-gfc9ea6c+4,16.0-29-ge8801f9,16.0-3-ge00e371+34,16.0-4-g18f3627+13,16.0-4-g5f3a788+20,16.0-4-ga3eb747+10,16.0-4-gabf74b7+29,16.0-4-gb13d127+6,16.0-49-g42e581f7+6,16.0-5-g27fb78a+7,16.0-5-g6a53317+34,16.0-5-gb3f8a4b+87,16.0-6-g9321be7+4,16.0-6-gcbc7b31+42,16.0-6-gf49912c+29,16.0-7-gd2eeba5+51,16.0-71-ge89f8615e,16.0-8-g21fd5fe+29,16.0-8-g3a9f023+20,16.0-8-g4734f7a+1,16.0-8-g5858431+3,16.0-9-gf5c1f43+8,master-gd73dc1d098+1,w.2019.01
LSSTDataManagementBasePackage
pupil.py
Go to the documentation of this file.
1 #
2 # LSST Data Management System
3 # Copyright 2017 LSST Corporation.
4 #
5 # This product includes software developed by the
6 # LSST Project (http://www.lsst.org/).
7 #
8 # This program is free software: you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation, either version 3 of the License, or
11 # (at your option) any later version.
12 #
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
17 #
18 # You should have received a copy of the LSST License Statement and
19 # the GNU General Public License along with this program. If not,
20 # see <http://www.lsstcorp.org/LegalNotices/>.
21 #
22 
23 __all__ = ['PupilFactory', 'Pupil']
24 
25 import numpy as np
26 
27 
28 class Pupil:
29  """!Pupil obscuration function.
30  """
31 
32  def __init__(self, illuminated, size, scale):
33  """!Construct a Pupil
34 
35  @param[in] illuminated 2D numpy array indicating which parts of
36  the pupil plane are illuminated.
37  @param[in] size Size of pupil plane array in meters. Note
38  that this may be larger than the actual
39  diameter of the illuminated pupil to
40  accommodate zero-padding.
41  @param[in] scale Sampling interval of pupil plane array in
42  meters.
43  """
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 
53  def __init__(self, visitInfo, pupilSize, npix):
54  """!Construct a PupilFactory.
55 
56  @param[in] visitInfo VisitInfo object for a particular exposure.
57  @param[in] pupilSize Size in meters of constructed Pupil array.
58  Note that this may be larger than the actual
59  diameter of the illuminated pupil to
60  accommodate zero-padding.
61  @param[in] npix Constructed Pupils will be npix x npix.
62  """
63  self.visitInfo = visitInfo
64  self.pupilSize = pupilSize
65  self.npix = npix
66  self.pupilScale = pupilSize/npix
67  u = (np.arange(npix, dtype=np.float64) - (npix - 1)/2) * self.pupilScale
68  self.u, self.v = np.meshgrid(u, u)
69 
70  def getPupil(self, point):
71  """!Calculate a Pupil at a given point in the focal plane.
72 
73  @param point Point2D indicating focal plane coordinates.
74  @returns Pupil
75  """
76  raise NotImplementedError(
77  "PupilFactory not implemented for this camera")
78 
79  @staticmethod
80  def _pointLineDistance(p0, p1, p2):
81  """Compute the right-angle distance between the points given by `p0`
82  and the line that passes through `p1` and `p2`.
83 
84  @param[in] p0 2-tuple of numpy arrays (x,y coords)
85  @param[in] p1 2-tuple of scalars (x,y coords)
86  @param[in] p2 2-tuple of scalars (x,y coords)
87  @returns numpy array of distances; shape congruent to p0[0]
88  """
89  x0, y0 = p0
90  x1, y1 = p1
91  x2, y2 = p2
92  dy21 = y2 - y1
93  dx21 = x2 - x1
94  return np.abs(dy21*x0 - dx21*y0 + x2*y1 - y2*x1)/np.hypot(dy21, dx21)
95 
96  def _fullPupil(self):
97  """Make a fully-illuminated Pupil.
98 
99  @returns Pupil
100  """
101  illuminated = np.ones(self.u.shape, dtype=np.bool)
102  return Pupil(illuminated, self.pupilSize, self.pupilScale)
103 
104  def _cutCircleInterior(self, pupil, p0, r):
105  """Cut out the interior of a circular region from a Pupil.
106 
107  @param[in,out] pupil Pupil to modify in place
108  @param[in] p0 2-tuple indicating region center
109  @param[in] r Circular region radius
110  """
111  r2 = (self.u - p0[0])**2 + (self.v - p0[1])**2
112  pupil.illuminated[r2 < r**2] = False
113 
114  def _cutCircleExterior(self, pupil, p0, r):
115  """Cut out the exterior of a circular region from a Pupil.
116 
117  @param[in,out] pupil Pupil to modify in place
118  @param[in] p0 2-tuple indicating region center
119  @param[in] r Circular region radius
120  """
121  r2 = (self.u - p0[0])**2 + (self.v - p0[1])**2
122  pupil.illuminated[r2 > r**2] = False
123 
124  def _cutRay(self, pupil, p0, angle, thickness):
125  """Cut out a ray from a Pupil.
126 
127  @param[in,out] pupil Pupil to modify in place
128  @param[in] p0 2-tuple indicating ray starting point
129  @param[in] angle Ray angle measured CCW from +x.
130  @param[in] thickness Thickness of cutout
131  """
132  angleRad = angle.asRadians()
133  # the 1 is arbitrary, just need something to define another point on
134  # the line
135  p1 = (p0[0] + 1, p0[1] + np.tan(angleRad))
136  d = PupilFactory._pointLineDistance((self.u, self.v), p0, p1)
137  pupil.illuminated[(d < 0.5*thickness) &
138  ((self.u - p0[0])*np.cos(angleRad) +
139  (self.v - p0[1])*np.sin(angleRad) >= 0)] = False
140 
141  def _centerPupil(self, pupil):
142  """Center the illuminated portion of the pupil in array.
143 
144  @param[in,out] pupil Pupil to modify in place
145  """
146  def center(arr, axis):
147  smash = np.sum(arr, axis=axis)
148  w = np.where(smash)[0]
149  return int(0.5*(np.min(w)+np.max(w)))
150  ycenter = center(pupil.illuminated, 0)
151  xcenter = center(pupil.illuminated, 1)
152  ytarget = pupil.illuminated.shape[0]//2
153  xtarget = pupil.illuminated.shape[1]//2
154  pupil.illuminated = np.roll(np.roll(pupil.illuminated,
155  xtarget-xcenter,
156  axis=0),
157  ytarget-ycenter,
158  axis=1)
def __init__(self, visitInfo, pupilSize, npix)
Construct a PupilFactory.
Definition: pupil.py:53
Pupil obscuration function.
Definition: pupil.py:28
def getPupil(self, point)
Calculate a Pupil at a given point in the focal plane.
Definition: pupil.py:70
Pupil obscuration function factory for use with Fourier optics.
Definition: pupil.py:49
def __init__(self, illuminated, size, scale)
Construct a Pupil.
Definition: pupil.py:32