24 from functools
import lru_cache
32 __all__ = [
"makeCamera"]
37 """An imaging camera (e.g. the LSST 3Gpix camera)
42 Camera description YAML file.
46 camera : `lsst.afw.cameraGeom.Camera`
50 with open(cameraFile)
as fd:
51 cameraParams = yaml.load(fd, Loader=yaml.CLoader)
53 cameraName = cameraParams[
"name"]
58 plateScale =
geom.Angle(cameraParams[
"plateScale"], geom.arcseconds)
59 nativeSys = cameraGeom.CameraSys(cameraParams[
"transforms"].pop(
"nativeSys"))
62 ccdParams = cameraParams[
"CCDs"]
66 for ccdName, ccdValues
in ccdParams.items():
73 """Make a list of detector configs
77 detectorConfig : `list` of `lsst.afw.cameraGeom.DetectorConfig`
78 A list of detector configs.
81 for name, ccd
in ccdParams.items():
82 detectorConfig = cameraGeom.DetectorConfig()
83 detectorConfigs.append(detectorConfig)
85 detectorConfig.name = name
86 detectorConfig.id = ccd[
'id']
87 detectorConfig.serial = ccd[
'serial']
88 detectorConfig.detectorType = ccd[
'detectorType']
89 if 'physicalType' in ccd:
90 detectorConfig.physicalType = ccd[
'physicalType']
93 detectorConfig.bbox_x0, detectorConfig.bbox_y0 = ccd[
'bbox'][0]
94 detectorConfig.bbox_x1, detectorConfig.bbox_y1 = ccd[
'bbox'][1]
95 detectorConfig.pixelSize_x, detectorConfig.pixelSize_y = ccd[
'pixelSize']
96 detectorConfig.transformDict.nativeSys = ccd[
'transformDict'][
'nativeSys']
97 transforms = ccd[
'transformDict'][
'transforms']
98 detectorConfig.transformDict.transforms =
None if transforms ==
'None' else transforms
99 detectorConfig.refpos_x, detectorConfig.refpos_y = ccd[
'refpos']
100 detectorConfig.offset_x, detectorConfig.offset_y = ccd[
'offset']
101 detectorConfig.transposeDetector = ccd[
'transposeDetector']
102 detectorConfig.pitchDeg = ccd[
'pitch']
103 detectorConfig.yawDeg = ccd[
'yaw']
104 detectorConfig.rollDeg = ccd[
'roll']
105 if 'crosstalk' in ccd:
106 detectorConfig.crosstalk = ccd[
'crosstalk']
108 return detectorConfigs
112 """Construct a list of AmplifierBuilder objects
116 amp =
list(ccd[
'amplifiers'].values())[0]
119 xRawExtent, yRawExtent = rawBBox.getDimensions()
121 readCorners = {
"LL": ReadoutCorner.LL,
122 "LR": ReadoutCorner.LR,
123 "UL": ReadoutCorner.UL,
124 "UR": ReadoutCorner.UR}
127 for name, amp
in sorted(ccd[
'amplifiers'].
items(), key=
lambda x: x[1][
'hdu']):
129 amplifier.setName(name)
132 perAmpData = amp[
'perAmpData']
136 x0, y0 = ix*xRawExtent, iy*yRawExtent
139 xDataExtent, yDataExtent = rawDataBBox.getDimensions()
141 geom.PointI(ix*xDataExtent, iy*yDataExtent), rawDataBBox.getDimensions()))
145 amplifier.setRawBBox(rawBBox)
149 amplifier.setRawDataBBox(rawDataBBox)
153 amplifier.setRawHorizontalOverscanBBox(rawSerialOverscanBBox)
157 amplifier.setRawVerticalOverscanBBox(rawParallelOverscanBBox)
161 amplifier.setRawPrescanBBox(rawSerialPrescanBBox)
164 amplifier.setRawXYOffset(
geom.Extent2I(ix*xRawExtent, iy*yRawExtent))
168 amplifier.setReadoutCorner(readCorners[amp[
'readCorner']])
169 amplifier.setGain(amp[
'gain'])
170 amplifier.setReadNoise(amp[
'readNoise'])
171 amplifier.setSaturation(amp[
'saturation'])
172 amplifier.setSuspectLevel(amp.get(
'suspect', np.nan))
176 flipX, flipY = amp.get(
"flipXY")
178 amplifier.setRawFlipX(flipX)
179 amplifier.setRawFlipY(flipY)
181 amplifier.setLinearityCoeffs([float(val)
for val
in amp[
'linearityCoeffs']])
182 amplifier.setLinearityType(amp[
'linearityType'])
183 amplifier.setLinearityThreshold(float(amp[
'linearityThreshold']))
184 amplifier.setLinearityMaximum(float(amp[
'linearityMax']))
185 amplifier.setLinearityUnits(
"DN")
186 amplifierList.append(amplifier)
191 """Backward compatible name.
197 """Given a list [(x0, y0), (xsize, ysize)], probably from a yaml file,
200 (x0, y0), (xsize, ysize) = ylist
205 """Make a dictionary of TransformPoint2ToPoint2s from yaml, mapping from
210 nativeSys : `lsst.afw.cameraGeom.CameraSys`
211 transformDict : `dict`
212 A dict specifying parameters of transforms; keys are camera system
214 plateScale : `lsst.geom.Angle`
215 The size of a pixel in angular units/mm (e.g. 20 arcsec/mm for LSST)
220 A dict of `lsst.afw.cameraGeom.CameraSys` :
221 `lsst.afw.geom.TransformPoint2ToPoint2`
223 The resulting dict's keys are `~lsst.afw.cameraGeom.CameraSys`,
224 and the values are Transforms *from* NativeSys *to* CameraSys
228 assert nativeSys == cameraGeom.FOCAL_PLANE,
"Cameras with nativeSys != FOCAL_PLANE are not supported."
232 for key, transform
in transformDict.items():
233 transformType = transform[
"transformType"]
234 knownTransformTypes = [
"affine",
"radial"]
235 if transformType
not in knownTransformTypes:
236 raise RuntimeError(
"Saw unknown transform type for %s: %s (known types are: [%s])" % (
237 key, transform[
"transformType"],
", ".join(knownTransformTypes)))
239 if transformType ==
"affine":
241 np.array(transform[
"translation"]))
244 elif transformType ==
"radial":
251 radialCoeffs = np.array(transform[
"coeffs"])
253 radialCoeffs *= plateScale.asRadians()
256 raise RuntimeError(
"Impossible condition \"%s\" is not in: [%s])" % (
257 transform[
"transformType"],
", ".join(knownTransformTypes)))
259 resMap[cameraGeom.CameraSys(key)] = transform
265 pupilFactoryClass=cameraGeom.pupil.PupilFactory):
266 """Construct a Camera instance from a dictionary of
267 detector name : `lsst.afw.cameraGeom.amplifier`
272 The name of the camera
273 detectorConfigList : `list`
274 A list of `lsst.afw.cameraGeom.cameraConfig.DetectorConfig`
275 nativeSys : `lsst.afw.cameraGeom.CameraSys`
276 The native transformation type; must be
277 `lsst.afw.cameraGeom.FOCAL_PLANE`
278 transformDict : `dict`
279 A dict of lsst.afw.cameraGeom.CameraSys :
280 `lsst.afw.geom.TransformPoint2ToPoint2`
281 amplifierDict : `dict`
282 A dictionary of detector name :
283 `lsst.afw.cameraGeom.Amplifier.Builder`
284 pupilFactoryClass : `type`, optional
285 Class to attach to camera;
286 `lsst.default afw.cameraGeom.PupilFactory`
290 camera : `lsst.afw.cameraGeom.Camera`
295 Copied from `lsst.afw.cameraGeom.cameraFactory` with permission and
296 encouragement from Jim Bosch.
304 assert nativeSys == cameraGeom.FOCAL_PLANE,
"Cameras with nativeSys != FOCAL_PLANE are not supported."
306 focalPlaneToField = transformDict[cameraGeom.FIELD_ANGLE]
309 cameraBuilder.setPupilFactoryClass(pupilFactoryClass)
312 for toSys, transform
in transformDict.items():
313 cameraBuilder.setTransformFromFocalPlaneTo(toSys, transform)
315 for detectorConfig
in detectorConfigList:
317 cameraGeom.addDetectorBuilderFromConfig(cameraBuilder, detectorConfig,
318 amplifierDict[detectorConfig.name],
325 detectorNativeSys = detectorConfig.transformDict.nativeSys
326 detectorNativeSys = (cameraGeom.PIXELS
if detectorNativeSys
is None else
327 cameraGeom.CameraSysPrefix(detectorNativeSys))
336 assert detectorNativeSys == cameraGeom.PIXELS, \
337 "Detectors with nativeSys != PIXELS are not supported."
338 detectorNativeSys = cameraGeom.CameraSys(detectorNativeSys, detectorConfig.name)
340 return cameraBuilder.finish()