LSST Applications g0265f82a02+093ff98f47,g02d81e74bb+10352d6f39,g1f3e9fa97e+40b0fc677d,g2079a07aa2+14824f138e,g2bbee38e9b+093ff98f47,g337abbeb29+093ff98f47,g3ddfee87b4+064c02c7ee,g487adcacf7+7e842ebf4b,g50ff169b8f+5929b3527e,g52b1c1532d+a6fc98d2e7,g568d43a26c+1d7ac31cb0,g591dd9f2cf+fb1f69e2ea,g858d7b2824+10352d6f39,g8a8a8dda67+a6fc98d2e7,g8cdfe0ae6a+66d966b544,g99cad8db69+7ce8a7c20a,g9ddcbc5298+d4bad12328,ga1e77700b3+246acaaf9c,ga2e4dd1c03+064c02c7ee,ga8c6da7877+04f6ba86dc,gae46bcf261+093ff98f47,gb0e22166c9+3863383f4c,gba4ed39666+9664299f35,gbb8dafda3b+db40f59a7d,gbeb006f7da+e6a448e96d,gbf5cecdb8a+10352d6f39,gc0f3af6251+10a3fd39cd,gc120e1dc64+5839e50a77,gc28159a63d+093ff98f47,gcf0d15dbbd+064c02c7ee,gd2a12a3803+0c2c227a2b,gdaeeff99f8+a38ce5ea23,ge79ae78c31+093ff98f47,gee10cc3b42+a6fc98d2e7,gf1cff7945b+10352d6f39,w.2024.15
LSST Data Management Base Package
Loading...
Searching...
No Matches
Public Member Functions | Public Attributes | Protected Member Functions | List of all members
lsst.jointcal.cameraGeometry.CameraModel Class Reference

Public Member Functions

 __init__ (self, wcsList, detectors, camera, n=100)
 
 computeDistortionModel (self)
 
 computePixelScale (self)
 
 computeCameraPixelScale (self, detector_id=30)
 

Public Attributes

 wcsList
 
 camera
 
 detectors
 
 maxFocalRadius
 
 n
 
 fieldAngle
 
 radialScale
 
 tangentialScale
 
 fieldAngles
 
 radialScales
 
 tangentialScales
 
 fieldAngleStd
 
 radialScaleStd
 
 tangentialScaleStd
 
 log
 

Protected Member Functions

 _computeDetectorPixelScale (self, detector_id, wcs)
 

Detailed Description

Convert a jointcal `~lsst.afw.geom.SkyWcs` into a distortion model and
detector positions (TODO) that can be used by `~lsst.afw.cameraGeom`.

Because this code only operates on the WCS, it is independent of the
format of the persisted output (e.g. gen2 separate files vs. gen3 bundled
visits).

Parameters
----------
wcsList : `list` [`lsst.afw.geom.SkyWcs`]
    The WCS to use to compute the distortion model from, preferably from
    multiple visits on the same tract.
detectors : `list` [`int`]
    Detector ids that correspond one-to-one with ``wcsList``.
camera : `lsst.afw.cameraGeom.Camera`
    The camera these WCS were fit for.
n : `int`
    Number of points to compute the pixel scale at, along the +y axis.

Definition at line 38 of file cameraGeometry.py.

Constructor & Destructor Documentation

◆ __init__()

lsst.jointcal.cameraGeometry.CameraModel.__init__ ( self,
wcsList,
detectors,
camera,
n = 100 )

Definition at line 58 of file cameraGeometry.py.

58 def __init__(self, wcsList, detectors, camera, n=100):
59 self.wcsList = wcsList
60 self.camera = camera
61 self.detectors = detectors
62 self.maxFocalRadius = self.camera.computeMaxFocalPlaneRadius()
63 self.n = n
64 # the computed radius and pixel scales
65 self.fieldAngle = None # degrees
66 self.radialScale = None # arcsec
67 self.tangentialScale = None # arcsec
68 # the computed values for every input wcs
69 self.fieldAngles = None
70 self.radialScales = None
71 self.tangentialScales = None
72 self.fieldAngleStd = None
73 self.radialScaleStd = None
74 self.tangentialScaleStd = None
75
76 self.log = _LOG.getChild("CameraModel")
77

Member Function Documentation

◆ _computeDetectorPixelScale()

lsst.jointcal.cameraGeometry.CameraModel._computeDetectorPixelScale ( self,
detector_id,
wcs )
protected
Compute pixel scale in radial and tangential directions as a
function of field angle.

Parameters
----------
detector_id: `int`
    Detector identifier for the detector of this wcs.
wcs : `lsst.afw.geom.SkyWcs`
    Full focal-plane model to compute pixel scale on.

Returns
-------
fieldAngle : `numpy.ndarray`
    Field angles in degrees.
radialScale : `numpy.ndarray`
    Radial direction pixel scales in arcseconds/pixel.
tangentialScale : `numpy.ndarray`
    Tangential direction pixel scales in arcseconds/pixel.

Notes
-----
Pixel scales are calculated from finite differences only along the +y
focal plane direction.

Definition at line 171 of file cameraGeometry.py.

171 def _computeDetectorPixelScale(self, detector_id, wcs):
172 """Compute pixel scale in radial and tangential directions as a
173 function of field angle.
174
175 Parameters
176 ----------
177 detector_id: `int`
178 Detector identifier for the detector of this wcs.
179 wcs : `lsst.afw.geom.SkyWcs`
180 Full focal-plane model to compute pixel scale on.
181
182 Returns
183 -------
184 fieldAngle : `numpy.ndarray`
185 Field angles in degrees.
186 radialScale : `numpy.ndarray`
187 Radial direction pixel scales in arcseconds/pixel.
188 tangentialScale : `numpy.ndarray`
189 Tangential direction pixel scales in arcseconds/pixel.
190
191 Notes
192 -----
193 Pixel scales are calculated from finite differences only along the +y
194 focal plane direction.
195 """
196 focalToSky = wcs.getFrameDict().getMapping('FOCAL', 'SKY')
197 mmPerPixel = self.camera[detector_id].getPixelSize()
198
199 focalToPixels = wcs.getFrameDict().getMapping('FOCAL', 'PIXELS')
200 trans = wcs.getTransform() # Pixels to Sky as Point2d -> SpherePoint
201 boresight = trans.applyForward(Point2D(focalToPixels.applyForward([0, 0])))
202
203 rs = np.linspace(0, self.maxFocalRadius, self.n) # focal plane units
204 fieldAngle = np.zeros_like(rs)
205 radialScale = np.zeros_like(rs)
206 tangentialScale = np.zeros_like(rs)
207 for i, r in enumerate(rs):
208 # point on the sky at position r along the focal plane +y axis
209 sp1 = SpherePoint(*focalToSky.applyForward(Point2D([0, r])), radians)
210 # point on the sky one pixel further along the focal plane +y axis
211 sp2 = SpherePoint(*focalToSky.applyForward(Point2D([0, r + mmPerPixel.getY()])), radians)
212 # point on the sky one pixel off of the focal plane +y axis at r
213 sp3 = SpherePoint(*focalToSky.applyForward(Point2D([mmPerPixel.getX(), r])), radians)
214 fieldAngle[i] = boresight.separation(sp1).asDegrees()
215 radialScale[i] = sp1.separation(sp2).asArcseconds()
216 tangentialScale[i] = sp1.separation(sp3).asArcseconds()
217 return fieldAngle, radialScale, tangentialScale

◆ computeCameraPixelScale()

lsst.jointcal.cameraGeometry.CameraModel.computeCameraPixelScale ( self,
detector_id = 30 )
Compute the radial and tangential pixel scales using the distortion
model supplied with the camera.

This is designed to be directly comparable with the results of
`~CameraModel.computePixelScale`.

Parameters
----------
detector_id: `int`
    Detector identifier for the detector_id to use for the calculation.

Returns
-------
fieldAngle : `numpy.ndarray`
    Field angles in degrees.
radialScale : `numpy.ndarray`
    Radial direction pixel scales in arcseconds/pixel.
tangentialScale : `numpy.ndarray`
    Tangential direction pixel scales in arcseconds/pixel.

Definition at line 127 of file cameraGeometry.py.

127 def computeCameraPixelScale(self, detector_id=30):
128 """Compute the radial and tangential pixel scales using the distortion
129 model supplied with the camera.
130
131 This is designed to be directly comparable with the results of
132 `~CameraModel.computePixelScale`.
133
134 Parameters
135 ----------
136 detector_id: `int`
137 Detector identifier for the detector_id to use for the calculation.
138
139 Returns
140 -------
141 fieldAngle : `numpy.ndarray`
142 Field angles in degrees.
143 radialScale : `numpy.ndarray`
144 Radial direction pixel scales in arcseconds/pixel.
145 tangentialScale : `numpy.ndarray`
146 Tangential direction pixel scales in arcseconds/pixel.
147 """
148 # Make a trivial SkyWcs to get a field angle->sky transform from.
149 iwcToSkyWcs = lsst.afw.geom.makeSkyWcs(Point2D(0, 0), SpherePoint(0, 0, radians),
150 lsst.afw.geom.makeCdMatrix(1.0 * radians, 0 * radians, True))
151 iwcToSkyMap = iwcToSkyWcs.getFrameDict().getMapping("PIXELS", "SKY")
152 skyFrame = iwcToSkyWcs.getFrameDict().getFrame("SKY")
153
154 # Extract the transforms that are defined just on the camera.
155 pixSys = self.camera[detector_id].makeCameraSys(cameraGeom.PIXELS)
156 pixelsToFocal = self.camera.getTransform(pixSys, cameraGeom.FOCAL_PLANE)
157 focalToField = self.camera.getTransform(cameraGeom.FOCAL_PLANE, cameraGeom.FIELD_ANGLE)
158
159 # Build a SkyWcs that combines each of the above components.
160 pixelFrame = ast.Frame(2, "Domain=PIXELS")
161 focalFrame = ast.Frame(2, "Domain=FOCAL")
162 iwcFrame = ast.Frame(2, "Domain=IWC")
163 frameDict = ast.FrameDict(pixelFrame)
164 frameDict.addFrame("PIXELS", pixelsToFocal.getMapping(), focalFrame)
165 frameDict.addFrame("FOCAL", focalToField.getMapping(), iwcFrame)
166 frameDict.addFrame("IWC", iwcToSkyMap, skyFrame)
167 wcs = lsst.afw.geom.SkyWcs(frameDict)
168
169 return self._computeDetectorPixelScale(detector_id, wcs)
170
A FrameSet whose frames can be referenced by domain name.
Definition FrameDict.h:67
Frame is used to represent a coordinate system.
Definition Frame.h:157
A 2-dimensional celestial WCS that transform pixels to ICRS RA/Dec, using the LSST standard for pixel...
Definition SkyWcs.h:117
std::shared_ptr< SkyWcs > makeSkyWcs(daf::base::PropertySet &metadata, bool strip=false)
Construct a SkyWcs from FITS keywords.
Definition SkyWcs.cc:521
Eigen::Matrix2d makeCdMatrix(lsst::geom::Angle const &scale, lsst::geom::Angle const &orientation=0 *lsst::geom::degrees, bool flipX=false)
Make a WCS CD matrix.
Definition SkyWcs.cc:133

◆ computeDistortionModel()

lsst.jointcal.cameraGeometry.CameraModel.computeDistortionModel ( self)
Calculate the afw cameraGeom distortion model to be included in an
on-disk camera model.

PLACEHOLDER: This may be as simple as running `computePixelScale` and
then doing a numpy polynomial fit to it for the cameraGeom input.
However, we need to check details of how that distortion model is
stored in a Camera. e.g.:
np.polyfit(self.fieldAngle, self.radialScale, poly_degree)

Definition at line 78 of file cameraGeometry.py.

78 def computeDistortionModel(self):
79 """Calculate the afw cameraGeom distortion model to be included in an
80 on-disk camera model.
81
82 PLACEHOLDER: This may be as simple as running `computePixelScale` and
83 then doing a numpy polynomial fit to it for the cameraGeom input.
84 However, we need to check details of how that distortion model is
85 stored in a Camera. e.g.:
86 np.polyfit(self.fieldAngle, self.radialScale, poly_degree)
87 """
88 raise NotImplementedError("not yet!")
89

◆ computePixelScale()

lsst.jointcal.cameraGeometry.CameraModel.computePixelScale ( self)
Compute the radial and tangential pixel scale by averaging over
multiple jointcal WCS models.

Also computes the standard deviation and logs any WCS that are
significant outliers.
The calculations are stored in the ``fieldAngle[s]``,
``radialScale[s]``, and ``tangentialScale[s]`` member variables.

Definition at line 90 of file cameraGeometry.py.

90 def computePixelScale(self):
91 """Compute the radial and tangential pixel scale by averaging over
92 multiple jointcal WCS models.
93
94 Also computes the standard deviation and logs any WCS that are
95 significant outliers.
96 The calculations are stored in the ``fieldAngle[s]``,
97 ``radialScale[s]``, and ``tangentialScale[s]`` member variables.
98 """
99 self.fieldAngles = []
100 self.radialScales = []
101 self.tangentialScales = []
102 for id, wcs in zip(self.detectors, self.wcsList):
103 fieldAngle, radial, tangential = self._computeDetectorPixelScale(id, wcs)
104 self.fieldAngles.append(fieldAngle)
105 self.radialScales.append(radial)
106 self.tangentialScales.append(tangential)
107 # TODO: For now, don't worry about small differences in the computed
108 # field angles vs. their respective radial/tangential scales, just
109 # assume all fieldAngle positions are "close enough" and warn if not.
110 self.fieldAngle = np.mean(self.fieldAngles, axis=0)
111 self.fieldAngleStd = np.std(self.fieldAngles, axis=0)
112 if self.fieldAngleStd.max() > 1e-4:
113 self.log.warning("Large stddev in computed field angles between visits (max: %s degree).",
114 self.fieldAngleStd.max())
115 # import os; print(os.getpid()); import ipdb; ipdb.set_trace();
116 self.radialScale = np.mean(self.radialScales, axis=0)
117 self.radialScaleStd = np.std(self.radialScales, axis=0)
118 if self.radialScaleStd.max() > 1e-4:
119 self.log.warning("Large stddev in computed radial scales between visits (max: %s arcsec).",
120 self.radialScaleStd.max())
121 self.tangentialScale = np.mean(self.tangentialScales, axis=0)
122 self.tangentialScaleStd = np.std(self.tangentialScales, axis=0)
123 if self.tangentialScaleStd.max() > 1e-4:
124 self.log.warning("Large stddev in computed tangential scales between visits (max: %s arcsec).",
125 self.tangentialScaleStd.max())
126
int max

Member Data Documentation

◆ camera

lsst.jointcal.cameraGeometry.CameraModel.camera

Definition at line 60 of file cameraGeometry.py.

◆ detectors

lsst.jointcal.cameraGeometry.CameraModel.detectors

Definition at line 61 of file cameraGeometry.py.

◆ fieldAngle

lsst.jointcal.cameraGeometry.CameraModel.fieldAngle

Definition at line 65 of file cameraGeometry.py.

◆ fieldAngles

lsst.jointcal.cameraGeometry.CameraModel.fieldAngles

Definition at line 69 of file cameraGeometry.py.

◆ fieldAngleStd

lsst.jointcal.cameraGeometry.CameraModel.fieldAngleStd

Definition at line 72 of file cameraGeometry.py.

◆ log

lsst.jointcal.cameraGeometry.CameraModel.log

Definition at line 76 of file cameraGeometry.py.

◆ maxFocalRadius

lsst.jointcal.cameraGeometry.CameraModel.maxFocalRadius

Definition at line 62 of file cameraGeometry.py.

◆ n

lsst.jointcal.cameraGeometry.CameraModel.n

Definition at line 63 of file cameraGeometry.py.

◆ radialScale

lsst.jointcal.cameraGeometry.CameraModel.radialScale

Definition at line 66 of file cameraGeometry.py.

◆ radialScales

lsst.jointcal.cameraGeometry.CameraModel.radialScales

Definition at line 70 of file cameraGeometry.py.

◆ radialScaleStd

lsst.jointcal.cameraGeometry.CameraModel.radialScaleStd

Definition at line 73 of file cameraGeometry.py.

◆ tangentialScale

lsst.jointcal.cameraGeometry.CameraModel.tangentialScale

Definition at line 67 of file cameraGeometry.py.

◆ tangentialScales

lsst.jointcal.cameraGeometry.CameraModel.tangentialScales

Definition at line 71 of file cameraGeometry.py.

◆ tangentialScaleStd

lsst.jointcal.cameraGeometry.CameraModel.tangentialScaleStd

Definition at line 74 of file cameraGeometry.py.

◆ wcsList

lsst.jointcal.cameraGeometry.CameraModel.wcsList

Definition at line 59 of file cameraGeometry.py.


The documentation for this class was generated from the following file: