8 from .cameraGeomLib
import PIXELS, TAN_PIXELS, PUPIL, FOCAL_PLANE, SCIENCE, ACTUAL_PIXELS, \
9 CameraSys, Detector, Orientation
10 from .cameraConfig
import DetectorConfig, CameraConfig
11 from .cameraFactory
import makeCameraFromCatalogs
12 from .makePixelToTanPixel
import makePixelToTanPixel
14 __all__ = [
"DetectorWrapper",
"CameraWrapper"]
18 """!A Detector and the data used to construct it
20 Intended for use with unit tests, thus saves a copy of all input parameters.
21 Does not support setting details of amplifiers.
30 pixelSize=(0.02, 0.02),
34 radialDistortion=0.925,
37 """!Construct a DetectorWrapper
39 @param[in] name detector name
40 @param[in] id detector ID (int)
41 @param[in] detType detector type (an lsst.afw.cameraGeom.DetectorType)
42 @param[in] serial serial "number" (a string)
43 @param[in] bbox bounding box; defaults to (0, 0), (1024x1024) (an lsst.afw.geom.Box2I)
44 @param[in] numAmps number of amplifiers (int)
45 @param[in] pixelSize pixel size (mm) (an lsst.afw.geom.Point2D)
46 @param[in] ampExtent dimensions of amplifier image bbox (an lsst.afw.geom.Extent2I)
47 @param[in] orientation orientation of CCC in focal plane (lsst.afw.cameraGeom.Orientation)
48 @param[in] plateScale plate scale in arcsec/mm; 20.0 is for LSST
49 @param[in] radialDistortion radial distortion, in mm/rad^2
50 (the r^3 coefficient of the radial distortion polynomial
51 that converts PUPIL in radians to FOCAL_PLANE in mm);
52 0.925 is the value Dave Monet measured for lsstSim data
53 @param[in] modFunc a function that can modify attributes just before constructing the detector;
54 modFunc receives one argument: a DetectorWrapper with all attributes except detector set.
68 schema = afwTable.AmpInfoTable.makeMinimalSchema()
70 for i
in range(numAmps):
71 record = self.ampInfo.addNew()
72 ampName =
"amp %d" % (i + 1,)
73 record.setName(ampName)
75 record.setGain(1.71234e3)
76 record.setReadNoise(0.521237e2)
77 record.setReadoutCorner(afwTable.LL)
78 record.setHasRawInfo(
False)
83 radialDistortCoeffs = [0.0, 1.0/pScaleRad, 0.0, self.
radialDistortion/pScaleRad]
88 focalPlaneToPupil = focalPlaneToPupil,
94 FOCAL_PLANE: self.orientation.makePixelFpTransform(self.
pixelSize),
113 """A simple Camera and the data used to construct it
115 Intended for use with unit tests, thus saves some interesting information.
117 def __init__(self, plateScale=20.0, radialDistortion=0.925, isLsstLike=False):
118 """!Construct a CameraWrapper
120 @param[in] plateScale plate scale in arcsec/mm; 20.0 is for LSST
121 @param[in] radialDistortion radial distortion, in mm/rad^2
122 (the r^3 coefficient of the radial distortion polynomial
123 that converts PUPIL in radians to FOCAL_PLANE in mm);
124 0.925 is the value Dave Monet measured for lsstSim data
125 @param[in] isLsstLike make repository products with one raw image per amplifier (True)
126 or with one raw image per detector (False)
143 """!Return the number of detectors"""
147 """!Construct a list of DetectorConfig, one per detector
152 with open(detFile)
as fh:
153 names = fh.readline().rstrip().lstrip(
"#").split(
"|")
155 els = l.rstrip().split(
"|")
156 detectorProps = dict([(name, el)
for name, el
in zip(names, els)])
157 detectors.append(detectorProps)
159 for i, detector
in enumerate(detectors):
160 detectorId = (i + 1) * 10
161 detectorName = detector[
'name']
162 detConfig = DetectorConfig()
163 detConfig.name = detectorName
164 detConfig.id = detectorId
165 detConfig.bbox_x0 = 0
166 detConfig.bbox_y0 = 0
167 detConfig.bbox_x1 = int(detector[
'npix_x']) - 1
168 detConfig.bbox_y1 = int(detector[
'npix_y']) - 1
169 detConfig.serial = str(detector[
'serial'])
170 detConfig.detectorType = int(detector[
'detectorType'])
171 detConfig.offset_x = float(detector[
'x'])
172 detConfig.offset_y = float(detector[
'y'])
173 detConfig.refpos_x = float(detector[
'refPixPos_x'])
174 detConfig.refpos_y = float(detector[
'refPixPos_y'])
175 detConfig.yawDeg = float(detector[
'yaw'])
176 detConfig.pitchDeg = float(detector[
'pitch'])
177 detConfig.rollDeg = float(detector[
'roll'])
178 detConfig.pixelSize_x = float(detector[
'pixelSize'])
179 detConfig.pixelSize_y = float(detector[
'pixelSize'])
180 detConfig.transposeDetector =
False
181 detConfig.transformDict.nativeSys = PIXELS.getSysName()
182 detectorConfigs.append(detConfig)
183 self.detectorNameList.append(detectorName)
184 self.detectorIdList.append(detectorId)
185 return detectorConfigs
188 """!Construct a list of AmpInfoCatalog, one per detector
190 @param[in] ampFile path to amplifier data file
191 @param[in] isLsstLike if True then there is one raw image per amplifier;
192 if False then there is one raw image per detector
194 readoutMap = {
'LL':0,
'LR':1,
'UR':2, 'UL':3}
196 with open(ampFile)
as fh:
197 names = fh.readline().rstrip().lstrip(
"#").split(
"|")
199 els = l.rstrip().split(
"|")
200 ampProps = dict([(name, el)
for name, el
in zip(names, els)])
201 amps.append(ampProps)
203 schema = afwTable.AmpInfoTable.makeMinimalSchema()
204 linThreshKey = schema.addField(
'linearityThreshold', type=float)
205 linMaxKey = schema.addField(
'linearityMaximum', type=float)
206 linUnitsKey = schema.addField(
'linearityUnits', type=str, size=9)
209 if amp[
'ccd_name']
in ampTablesDict:
210 ampCatalog = ampTablesDict[amp[
'ccd_name']]
214 ampTablesDict[amp[
'ccd_name']] = ampCatalog
215 self.
ampInfoDict[amp[
'ccd_name']] = {
'namps':1,
'linInfo':{}}
216 record = ampCatalog.addNew()
229 xoffset = int(amp[
'x_offset'])
230 yoffset = int(amp[
'y_offset'])
231 flipx = bool(int(amp[
'flipx']))
232 flipy = bool(int(amp[
'flipy']))
237 xExt = rawBbox.getDimensions().getX()
239 rawDataBbox.flipLR(xExt)
240 rawHOverscanBbox.flipLR(xExt)
241 rawVOverscanBbox.flipLR(xExt)
242 rawPrescanBbox.flipLR(xExt)
244 yExt = rawBbox.getDimensions().getY()
246 rawDataBbox.flipTB(yExt)
247 rawHOverscanBbox.flipTB(yExt)
248 rawVOverscanBbox.flipTB(yExt)
249 rawPrescanBbox.flipTB(yExt)
250 if not flipx
and not flipy:
252 elif flipx
and not flipy:
254 elif flipx
and flipy:
256 elif not flipx
and flipy:
259 raise RuntimeError(
"Couldn't find read corner")
263 rawBbox.shift(offext)
264 rawDataBbox.shift(offext)
265 rawHOverscanBbox.shift(offext)
266 rawVOverscanBbox.shift(offext)
267 rawPrescanBbox.shift(offext)
272 record.setRawXYOffset(offset)
273 record.setName(str(amp[
'name']))
274 record.setReadoutCorner(readoutMap[readcorner])
275 record.setGain(float(amp[
'gain']))
276 record.setReadNoise(float(amp[
'readnoise']))
277 record.setLinearityCoeffs([float(amp[
'lin_coeffs']),])
278 record.setLinearityType(str(amp[
'lin_type']))
279 record.setHasRawInfo(
True)
280 record.setRawFlipX(flipx)
281 record.setRawFlipY(flipy)
282 record.setRawBBox(rawBbox)
283 record.setRawDataBBox(rawDataBbox)
284 record.setRawHorizontalOverscanBBox(rawHOverscanBbox)
285 record.setRawVerticalOverscanBBox(rawVOverscanBbox)
286 record.setRawPrescanBBox(rawPrescanBbox)
287 record.set(linThreshKey, float(amp[
'lin_thresh']))
288 record.set(linMaxKey, float(amp[
'lin_max']))
289 record.set(linUnitsKey, str(amp[
'lin_units']))
291 saveCoeffs = (float(amp[
'lin_coeffs']),)
292 saveCoeffs += (numpy.nan, numpy.nan, numpy.nan)
293 self.
ampInfoDict[amp[
'ccd_name']][
'linInfo'][amp[
'name']] = \
294 {
'lincoeffs':saveCoeffs,
'lintype':str(amp[
'lin_type']),
295 'linthresh':float(amp[
'lin_thresh']),
'linmax':float(amp[
'lin_max']),
296 'linunits':str(amp[
'lin_units'])}
300 """!Make camera config and amp catalog dictionary, using default detector and amp files
302 @param[in] isLsstLike if True then there is one raw image per amplifier;
303 if False then there is one raw image per detector
305 detFile = os.path.join(self.
_afwTestDir,
"testCameraDetectors.dat")
307 ampFile = os.path.join(self.
_afwTestDir,
"testCameraAmps.dat")
309 camConfig = CameraConfig()
310 camConfig.name =
"testCamera%s"%(
'LSST' if isLsstLike
else 'SC')
311 camConfig.detectorList = dict((i, detConfig)
for i, detConfig
in enumerate(detectorConfigs))
314 radialDistortCoeffs = [0.0, 1.0/pScaleRad, 0.0, self.
radialDistortion/pScaleRad]
315 tConfig = afwGeom.TransformConfig()
316 tConfig.transform.name =
'inverted'
317 radialClass = afwGeom.xyTransformRegistry[
'radial']
318 tConfig.transform.active.transform.retarget(radialClass)
319 tConfig.transform.active.transform.coeffs = radialDistortCoeffs
320 tmc = afwGeom.TransformMapConfig()
321 tmc.nativeSys = FOCAL_PLANE.getSysName()
322 tmc.transforms = {PUPIL.getSysName():tConfig}
323 camConfig.transformDict = tmc
324 return camConfig, ampCatalogDict
def __init__
Construct a CameraWrapper.
def makeTestRepositoryItems
Make camera config and amp catalog dictionary, using default detector and amp files.
A custom container class for records, based on std::vector.
def nDetectors
Return the number of detectors.
A Detector and the data used to construct it.
def __init__
Construct a DetectorWrapper.
An integer coordinate rectangle.
std::string getPackageDir(std::string const &packageName)
return the root directory of a setup package
def makePixelToTanPixel
Make an XYTransform whose forward direction converts PIXEL to TAN_PIXEL for one detector.
def makeDetectorConfigs
Construct a list of DetectorConfig, one per detector.
def makeAmpCatalogs
Construct a list of AmpInfoCatalog, one per detector.
def makeCameraFromCatalogs
Construct a Camera instance from a dictionary of detector name: AmpInfoCatalog.
double arcsecToRad(double x)