def makeCasuWfcam(): path = os.path.join(getPackageDir("obs_ukirt"), "casuWfcam", "camera") for detNum, (gain, sat) in enumerate(zip(GAIN, SATURATION), 1): det = AmpInfoCatalog(AmpInfoTable.makeMinimalSchema()) amp = det.addNew() amp.setName(str(detNum)) amp.setBBox(Box2I()) amp.setGain(gain) amp.setReadNoise(READNOISE) amp.setSaturation(sat) # amp.setSuspectLevel(float("nan")) amp.setReadoutCorner(LL) amp.setLinearityType("none") amp.setHasRawInfo(False) det.writeFits(os.path.join(path, "%d.fits" % (detNum,)))
def _makeAmpInfoCatalog(self): """Construct a trivial amplifier information catalog. The CBP code makes no use of this catalog, so it is as simple as possible: one amplifiers that covers the whole CCD, with no overscan, and semi-plausible values for everything else. Returns ------- ampInfo : `lsst.afw.cameraGeom.AmpInfoCatalog` Amplifier information catalog. """ ampExtent = lsst.geom.Extent2I(self.detectorWidthPix, self.detectorHeightPix) saturationLevel = 65535 linearityType = cameraGeom.NullLinearityType linearityCoeffs = [0, 0, 0, 0] schema = AmpInfoTable.makeMinimalSchema() self.ampInfoDict = {} ampCatalog = AmpInfoCatalog(schema) gain = 1.8 readNoise = 3.9 record = ampCatalog.addNew() record.setName("0") ampBBox = lsst.geom.Box2I(lsst.geom.Point2I(0, 0), ampExtent) record.setBBox(ampBBox) readCorner = LL record.setRawBBox(ampBBox) record.setRawDataBBox(ampBBox) record.setRawHorizontalOverscanBBox(lsst.geom.Box2I()) record.setRawXYOffset(lsst.geom.Extent2I(0, 0)) record.setReadoutCorner(readCorner) record.setGain(gain) record.setReadNoise(readNoise) record.setSaturation(saturationLevel) record.setSuspectLevel(float("nan")) record.setLinearityCoeffs([float(val) for val in linearityCoeffs]) record.setLinearityType(linearityType) record.setHasRawInfo(True) record.setRawFlipX(False) record.setRawFlipY(False) record.setRawVerticalOverscanBBox(lsst.geom.Box2I()) record.setRawPrescanBBox(lsst.geom.Box2I()) return ampCatalog
def makeCasuWfcam(): path = os.path.join(getPackageDir("obs_ukirt"), "casuWfcam", "camera") for detNum, (gain, sat) in enumerate(zip(GAIN, SATURATION), 1): det = AmpInfoCatalog(AmpInfoTable.makeMinimalSchema()) amp = det.addNew() amp.setName(str(detNum)) amp.setBBox(Box2I()) amp.setGain(gain) amp.setReadNoise(READNOISE) amp.setSaturation(sat) # amp.setSuspectLevel(float("nan")) amp.setReadoutCorner(LL) amp.setLinearityType("none") amp.setHasRawInfo(False) det.writeFits(os.path.join(path, "%d.fits" % (detNum, )))
def _makeAmpInfoCatalog(self): """Construct an amplifier info catalog """ # Fake amp of zero size. Not needed unless ISR is run xDataExtent = 0 yDataExtent = 0 saturation = 65535 schema = AmpInfoTable.makeMinimalSchema() ampCatalog = AmpInfoCatalog(schema) record = ampCatalog.addNew() ampX, ampY = (0, 0) record.setName("%d%d" % (ampX, ampY)) if bool(ampY): record.setBBox( afwGeom.Box2I( afwGeom.Point2I(ampX * xDataExtent, ampY * yDataExtent), afwGeom.Extent2I(xDataExtent, yDataExtent), )) else: record.setBBox( afwGeom.Box2I( afwGeom.Point2I(ampX * xDataExtent, ampY * yDataExtent), afwGeom.Extent2I(xDataExtent, yDataExtent), )) readCorner = LL # in raw frames; always LL because raws are in amp coords record.setReadoutCorner(readCorner) record.setGain(1.) record.setReadNoise(0.) record.setSaturation(saturation) record.setHasRawInfo(False) return ampCatalog
def setUp(self): """Constructs a CCD with two amplifiers and prepares for ISR""" np.random.seed(12345) baseValue = 100.0 gain = 1.0 readNoise = 123456789.0 saturation = 987654321.0 height = 234 imageSize = Extent2I(123, height) overscanSize = Extent2I(16, height) self.sigma = 1.234 # Set up the various regions overscan1 = Box2I(Point2I(0, 0), overscanSize) image1 = Box2I(Point2I(overscanSize[0], 0), imageSize) image2 = Box2I(Point2I(overscanSize[0] + imageSize[0], 0), imageSize) overscan2 = Box2I(Point2I(overscanSize[0] + 2*imageSize[0], 0), overscanSize) leftBox = Box2I(overscan1.getMin(), Extent2I(overscan1.getWidth() + image1.getWidth(), height)) rightBox = Box2I(image2.getMin(), Extent2I(image2.getWidth() + overscan2.getWidth(), height)) target1 = Box2I(Point2I(0, 0), imageSize) target2 = Box2I(Point2I(image1.getWidth(), 0), imageSize) # Set the pixels exposure = ExposureF(Box2I(Point2I(0, 0), Extent2I(imageSize[0]*2 + overscanSize[0]*2, height))) yy = np.arange(0, height, 1, dtype=np.float32) leftImage = ExposureF(exposure, leftBox) leftImage.image.array[:] = baseValue + yy[:, np.newaxis] rightImage = ExposureF(exposure, rightBox) rightImage.image.array[:] = baseValue - yy[:, np.newaxis] leftOverscan = ExposureF(exposure, overscan1) leftOverscan.image.array += np.random.normal(0.0, self.sigma, leftOverscan.image.array.shape) rightOverscan = ExposureF(exposure, overscan2) rightOverscan.image.array += np.random.normal(0.0, self.sigma, leftOverscan.image.array.shape) exposure.mask.array[:] = 0.0 exposure.variance.array[:] = np.nan # Construct the detectors amps = AmpInfoCatalog(AmpInfoTable.makeMinimalSchema()) makeAmplifier(amps, "left", target1, image1, overscan1, gain, readNoise, saturation) makeAmplifier(amps, "right", target2, image2, overscan2, gain, readNoise, saturation) ccdBox = Box2I(Point2I(0, 0), Extent2I(image1.getWidth() + image2.getWidth(), height)) ccd = Detector("detector", 1, SCIENCE, "det1", ccdBox, amps, Orientation(), Extent2D(1.0, 1.0), {}) exposure.setDetector(ccd) header = PropertyList() header.add("EXPTIME", 0.0) exposure.getInfo().setVisitInfo(VisitInfo(header)) self.exposure = exposure self.config = IsrTask.ConfigClass() # Disable everything we don't care about self.config.doBias = False self.config.doDark = False self.config.doFlat = False self.config.doFringe = False self.config.doDefect = False self.config.doAddDistortionModel = False self.config.doWrite = False self.config.expectWcs = False self.config.doLinearize = False self.config.doCrosstalk = False self.config.doBrighterFatter = False self.config.doAttachTransmissionCurve = False # Set the things that match our test setup self.config.overscanFitType = "CHEB" self.config.overscanOrder = 1 self.config.doEmpiricalReadNoise = True self.task = IsrTask(config=self.config)
def _makeAmpInfoCatalog(self): """Construct an amplifier info catalog """ extended = 1024 # extended register x_overscan = 40 # number of overscan pixel in x saturation = 65535 # Linearity correction is still under discussion, so this is a placeholder. linearityType = "PROPORTIONAL" linearityThreshold = 0 linearityMax = saturation linearityCoeffs = [linearityThreshold, linearityMax] schema = AmpInfoTable.makeMinimalSchema() linThreshKey = schema.addField('linearityThreshold', type=float) linMaxKey = schema.addField('linearityMaximum', type=float) linUnitsKey = schema.addField('linearityUnits', type=str, size=9) # end placeholder self.ampInfoDict = {} ampCatalog = AmpInfoCatalog(schema) for ampY in range(1, 3): for ampX in range(1, 3): record = ampCatalog.addNew() record.setName("%d%d" % (ampX, ampY)) print('Amp Name : %s, %s' % (ampX, ampY)) if ((ampX == 1) & (ampY == 1)): record.setBBox( afwGeom.Box2I( afwGeom.Point2I(0, 0), afwGeom.Extent2I(extended, extended), )) record.setRawHorizontalOverscanBBox( afwGeom.Box2I( afwGeom.Point2I(1044, 0), afwGeom.Extent2I(x_overscan, extended), )) record.setRawXYOffset(\ afwGeom.Extent2I(1084, 1024)) # bias region record.setRawBBox( afwGeom.Box2I( afwGeom.Point2I(10, 0), afwGeom.Extent2I(extended, extended), )) record.setRawDataBBox( afwGeom.Box2I( afwGeom.Point2I(10, 0), afwGeom.Extent2I(extended, extended), )) if ((ampX == 1) & (ampY == 2)): record.setBBox( afwGeom.Box2I( afwGeom.Point2I(1024, 0), afwGeom.Extent2I(extended, extended), )) record.setRawHorizontalOverscanBBox( afwGeom.Box2I( afwGeom.Point2I(1084, 0), afwGeom.Extent2I(x_overscan, extended), )) record.setRawXYOffset(\ afwGeom.Extent2I(1084, 1024)) # bias region record.setRawBBox( afwGeom.Box2I( afwGeom.Point2I(1134, 0), afwGeom.Extent2I(extended, extended), )) record.setRawDataBBox( afwGeom.Box2I( afwGeom.Point2I(1134, 0), afwGeom.Extent2I(extended, extended), )) if ((ampX == 2) & (ampY == 1)): record.setBBox( afwGeom.Box2I( afwGeom.Point2I(0, 1024), afwGeom.Extent2I(extended, extended), )) record.setRawHorizontalOverscanBBox( afwGeom.Box2I( afwGeom.Point2I(1044, 1024), afwGeom.Extent2I(x_overscan, extended), )) record.setRawXYOffset(\ afwGeom.Extent2I(1084, 1024)) # bias region record.setRawBBox( afwGeom.Box2I( afwGeom.Point2I(10, 1024), afwGeom.Extent2I(extended, extended), )) record.setRawDataBBox( afwGeom.Box2I( afwGeom.Point2I(10, 1024), afwGeom.Extent2I(extended, extended), )) if ((ampX == 2) & (ampY == 2)): record.setBBox( afwGeom.Box2I( afwGeom.Point2I(1024, 1024), afwGeom.Extent2I(extended, extended), )) record.setRawHorizontalOverscanBBox( afwGeom.Box2I( afwGeom.Point2I(1084, 1024), afwGeom.Extent2I(x_overscan, extended), )) record.setRawXYOffset(\ afwGeom.Extent2I(1084, 1024)) # bias region record.setRawBBox( afwGeom.Box2I( afwGeom.Point2I(1134, 1024), afwGeom.Extent2I(extended, extended), )) record.setRawDataBBox( afwGeom.Box2I( afwGeom.Point2I(1134, 1024), afwGeom.Extent2I(extended, extended), )) readCorner = LL # in raw frames; always LL because raws are in amp coords record.setReadoutCorner(readCorner) record.setGain(self.gain[(ampX, ampY)]) record.setReadNoise(self.readNoise[(ampX, ampY)]) record.setSaturation(saturation) record.setHasRawInfo(True) record.setRawPrescanBBox(afwGeom.Box2I()) # linearity placeholder stuff record.setLinearityCoeffs( [float(val) for val in linearityCoeffs]) record.setLinearityType(linearityType) record.set(linThreshKey, float(linearityThreshold)) record.set(linMaxKey, float(linearityMax)) record.set(linUnitsKey, "DN") return ampCatalog
def _makeAmpInfoCatalog(self, ccd): """Construct an amplifier info catalog """ # Much of this will need to be filled in when we know it. assert len(ccd['amplifiers']) > 0 amp = list(ccd['amplifiers'].values())[0] rawBBox = self._makeBBoxFromList(amp['rawBBox']) # total in file xRawExtent, yRawExtent = rawBBox.getDimensions() from lsst.afw.table import LL, LR, UL, UR readCorners = dict(LL=LL, LR=LR, UL=UL, UR=UR) schema = AmpInfoTable.makeMinimalSchema() linThreshKey = schema.addField('linearityThreshold', type=float) linMaxKey = schema.addField('linearityMaximum', type=float) linUnitsKey = schema.addField('linearityUnits', type=str, size=9) hduKey = schema.addField('hdu', type=np.int32) # end placeholder self.ampInfoDict = {} ampCatalog = AmpInfoCatalog(schema) for name, amp in sorted(ccd['amplifiers'].items(), key=lambda x: x[1]['hdu']): record = ampCatalog.addNew() record.setName(name) record.set(hduKey, amp['hdu']) ix, iy = amp['ixy'] perAmpData = amp['perAmpData'] if perAmpData: x0, y0 = 0, 0 # origin of data within each amp image else: x0, y0 = ix * xRawExtent, iy * yRawExtent rawDataBBox = self._makeBBoxFromList( amp['rawDataBBox']) # Photosensitive area xDataExtent, yDataExtent = rawDataBBox.getDimensions() record.setBBox( afwGeom.BoxI( afwGeom.PointI(ix * xDataExtent, iy * yDataExtent), rawDataBBox.getDimensions())) rawBBox = self._makeBBoxFromList(amp['rawBBox']) rawBBox.shift(afwGeom.ExtentI(x0, y0)) record.setRawBBox(rawBBox) rawDataBBox = self._makeBBoxFromList(amp['rawDataBBox']) rawDataBBox.shift(afwGeom.ExtentI(x0, y0)) record.setRawDataBBox(rawDataBBox) rawSerialOverscanBBox = self._makeBBoxFromList( amp['rawSerialOverscanBBox']) rawSerialOverscanBBox.shift(afwGeom.ExtentI(x0, y0)) record.setRawHorizontalOverscanBBox(rawSerialOverscanBBox) rawParallelOverscanBBox = self._makeBBoxFromList( amp['rawParallelOverscanBBox']) rawParallelOverscanBBox.shift(afwGeom.ExtentI(x0, y0)) record.setRawVerticalOverscanBBox(rawParallelOverscanBBox) rawSerialPrescanBBox = self._makeBBoxFromList( amp['rawSerialPrescanBBox']) rawSerialPrescanBBox.shift(afwGeom.ExtentI(x0, y0)) record.setRawPrescanBBox(rawSerialPrescanBBox) if perAmpData: record.setRawXYOffset( afwGeom.Extent2I(ix * xRawExtent, iy * yRawExtent)) else: record.setRawXYOffset(afwGeom.Extent2I(0, 0)) record.setReadoutCorner(readCorners[amp['readCorner']]) record.setGain(amp['gain']) record.setReadNoise(amp['readNoise']) record.setSaturation(amp['saturation']) record.setHasRawInfo(True) # flip data when assembling if needs be (e.g. data from the serial at the top of a CCD) flipX, flipY = amp.get("flipXY") record.setRawFlipX(flipX) record.setRawFlipY(flipY) # linearity placeholder stuff record.setLinearityCoeffs( [float(val) for val in amp['linearityCoeffs']]) record.setLinearityType(amp['linearityType']) record.set(linThreshKey, float(amp['linearityThreshold'])) record.set(linMaxKey, float(amp['linearityMax'])) record.set(linUnitsKey, "DN") return ampCatalog
def _makeAmpInfoCatalog(self): """Construct an amplifier info catalog """ # Much of this will need to be filled in when we know it. xDataExtent = 512 # trimmed yDataExtent = 2002 extended = 10 # extended register h_overscan = 22 # number of overscan in x v_overscan = 46 # number of overscan in y xRawExtent = extended + h_overscan + xDataExtent yRawExtent = v_overscan + yDataExtent # no prescan in vertical saturation = 65535 # Linearity correction is still under discussion, so this is a placeholder. linearityType = "PROPORTIONAL" linearityThreshold = 0 linearityMax = saturation linearityCoeffs = [linearityThreshold, linearityMax] schema = AmpInfoTable.makeMinimalSchema() linThreshKey = schema.addField('linearityThreshold', type=float) linMaxKey = schema.addField('linearityMaximum', type=float) linUnitsKey = schema.addField('linearityUnits', type=str, size=9) # end placeholder self.ampInfoDict = {} ampCatalog = AmpInfoCatalog(schema) for ampY in (0, 1): for ampX in range(8): record = ampCatalog.addNew() record.setName("%d%d" % (ampX, ampY)) if bool(ampY): record.setBBox( afwGeom.Box2I( afwGeom.Point2I(ampX * xDataExtent, ampY * yDataExtent), afwGeom.Extent2I(xDataExtent, yDataExtent), )) else: record.setBBox( afwGeom.Box2I( afwGeom.Point2I((7 - ampX) * xDataExtent, ampY * yDataExtent), afwGeom.Extent2I(xDataExtent, yDataExtent), )) readCorner = LL # in raw frames; always LL because raws are in amp coords # bias region x0Bias = extended + xDataExtent y0Data = 0 x0Data = extended record.setRawBBox( afwGeom.Box2I( afwGeom.Point2I(0, 0), afwGeom.Extent2I(xRawExtent, yRawExtent), )) record.setRawDataBBox( afwGeom.Box2I( afwGeom.Point2I(x0Data, y0Data), afwGeom.Extent2I(xDataExtent, yDataExtent), )) record.setRawHorizontalOverscanBBox( afwGeom.Box2I( afwGeom.Point2I(x0Bias, y0Data), afwGeom.Extent2I(h_overscan, yDataExtent), )) record.setRawVerticalOverscanBBox( afwGeom.Box2I( afwGeom.Point2I(x0Data, y0Data + yDataExtent), afwGeom.Extent2I(xDataExtent, v_overscan), )) record.setRawXYOffset( afwGeom.Extent2I(ampX * xRawExtent, ampY * yRawExtent)) record.setReadoutCorner(readCorner) record.setGain(self.gain[(ampX, ampY)]) record.setReadNoise(self.readNoise[(ampX, ampY)]) record.setSaturation(saturation) record.setHasRawInfo(True) record.setRawFlipX(bool(ampY)) # flip data when assembling if in top of chip record.setRawFlipY(bool(ampY)) record.setRawPrescanBBox(afwGeom.Box2I()) # linearity placeholder stuff record.setLinearityCoeffs( [float(val) for val in linearityCoeffs]) record.setLinearityType(linearityType) record.set(linThreshKey, float(linearityThreshold)) record.set(linMaxKey, float(linearityMax)) record.set(linUnitsKey, "DN") return ampCatalog
def _makeAmpInfoCatalog(self): """Construct an amplifier info catalog The LSSTSim S12 amplifiers are unusual in that they start with 4 pixels of usable bias region (which is used to set rawHOverscanBbox, despite the name), followed by the data. There is no other underscan or overscan. """ xDataExtent = 509 # trimmed yDataExtent = 1000 xBiasExtent = 4 xRawExtent = xDataExtent + xBiasExtent yRawExtent = yDataExtent readNoise = 3.975 # amplifier read noise, in e- saturationLevel = 65535 linearityType = NullLinearityType linearityCoeffs = [0, 0, 0, 0] schema = AmpInfoTable.makeMinimalSchema() self.ampInfoDict = {} ampCatalog = AmpInfoCatalog(schema) for ampX in (0, 1): for ampY in (0, 1): # amplifier gain (e-/ADU) and read noiuse (ADU/pixel) from lsstSim raw data # note that obs_test amp <ampX><ampY> = lsstSim amp C<ampY>,<ampX> (axes are swapped) gain = { (0, 0): 1.7741, # C0,0 (0, 1): 1.65881, # C1,0 (1, 0): 1.74151, # C0,1 (1, 1): 1.67073, # C1,1 }[(ampX, ampY)] readNoise = { (0, 0): 3.97531706217237, # C0,0 (0, 1): 4.08263755342685, # C1,0 (1, 0): 4.02753931932633, # C0,1 (1, 1): 4.1890610691135, # C1,1 }[(ampX, ampY)] record = ampCatalog.addNew() record.setName("%d%d" % (ampX, ampY)) record.setBBox( afwGeom.Box2I( afwGeom.Point2I(ampX * xDataExtent, ampY * yDataExtent), afwGeom.Extent2I(xDataExtent, yDataExtent), )) x0Raw = ampX * xRawExtent y0Raw = ampY * yRawExtent # bias region (which is prescan, in this case) is before the data readCorner = LL x0Bias = x0Raw x0Data = x0Bias + xBiasExtent record.setRawBBox( afwGeom.Box2I( afwGeom.Point2I(x0Raw, y0Raw), afwGeom.Extent2I(xRawExtent, yRawExtent), )) record.setRawDataBBox( afwGeom.Box2I( afwGeom.Point2I(x0Data, y0Raw), afwGeom.Extent2I(xDataExtent, yDataExtent), )) record.setRawHorizontalOverscanBBox( afwGeom.Box2I( afwGeom.Point2I(x0Bias, y0Raw), afwGeom.Extent2I(xBiasExtent, yRawExtent), )) record.setRawXYOffset(afwGeom.Extent2I(x0Raw, y0Raw)) record.setReadoutCorner(readCorner) record.setGain(gain) record.setReadNoise(readNoise) record.setSaturation(saturationLevel) record.setSuspectLevel(float("nan")) record.setLinearityCoeffs( [float(val) for val in linearityCoeffs]) record.setLinearityType(linearityType) record.setHasRawInfo(True) record.setRawFlipX(False) record.setRawFlipY(False) record.setRawVerticalOverscanBBox( afwGeom.Box2I()) # no vertical overscan record.setRawPrescanBBox( afwGeom.Box2I()) # no horizontal prescan return ampCatalog
def _makeAmpInfoCatalog(self): """Construct an amplifier info catalog The LSSTSim S12 amplifiers are unusual in that they start with 4 pixels of usable bias region (which is used to set rawHOverscanBbox, despite the name), followed by the data. There is no other underscan or overscan. """ xDataExtent = 509 # trimmed yDataExtent = 1000 xBiasExtent = 4 xRawExtent = xDataExtent + xBiasExtent yRawExtent = yDataExtent readNoise = 3.975 # amplifier read noise, in e- linearityType = "PROPORTIONAL" linearityThreshold = 0 linearityMax = 65535 linearityCoeffs = [linearityThreshold, linearityMax] schema = AmpInfoTable.makeMinimalSchema() linThreshKey = schema.addField('linearityThreshold', type=float) linMaxKey = schema.addField('linearityMaximum', type=float) linUnitsKey = schema.addField('linearityUnits', type=str, size=9) self.ampInfoDict = {} ampCatalog = AmpInfoCatalog(schema) for ampX in (0, 1): for ampY in (0, 1): # amplifier gain (e-/ADU) and read noiuse (ADU/pixel) from lsstSim raw data # note that obs_test amp <ampX><ampY> = lsstSim amp C<ampY>,<ampX> (axes are swapped) gain = { (0, 0): 1.7741, # C0,0 (0, 1): 1.65881, # C1,0 (1, 0): 1.74151, # C0,1 (1, 1): 1.67073, # C1,1 }[(ampX, ampY)] readNoise = { (0, 0): 3.97531706217237, # C0,0 (0, 1): 4.08263755342685, # C1,0 (1, 0): 4.02753931932633, # C0,1 (1, 1): 4.1890610691135, # C1,1 }[(ampX, ampY)] record = ampCatalog.addNew() record.setName("%d%d" % (ampX, ampY)) record.setBBox(afwGeom.Box2I( afwGeom.Point2I(ampX * xDataExtent, ampY * yDataExtent), afwGeom.Extent2I(xDataExtent, yDataExtent), )) x0Raw = ampX * xRawExtent y0Raw = ampY * yRawExtent # bias region (which is prescan, in this case) is before the data readCorner = LL x0Bias = x0Raw x0Data = x0Bias + xBiasExtent record.setRawBBox(afwGeom.Box2I( afwGeom.Point2I(x0Raw, y0Raw), afwGeom.Extent2I(xRawExtent, yRawExtent), )) record.setRawDataBBox(afwGeom.Box2I( afwGeom.Point2I(x0Data, y0Raw), afwGeom.Extent2I(xDataExtent, yDataExtent), )) record.setRawHorizontalOverscanBBox(afwGeom.Box2I( afwGeom.Point2I(x0Bias, y0Raw), afwGeom.Extent2I(xBiasExtent, yRawExtent), )) record.setRawXYOffset(afwGeom.Extent2I(x0Raw, y0Raw)) record.setReadoutCorner(readCorner) record.setGain(gain) record.setReadNoise(readNoise) record.setSaturation(linearityMax) record.setLinearityCoeffs([float(val) for val in linearityCoeffs]) record.setLinearityType(linearityType) record.setHasRawInfo(True) record.setRawFlipX(False) record.setRawFlipY(False) record.setRawVerticalOverscanBBox(afwGeom.Box2I()) # no vertical overscan record.setRawPrescanBBox(afwGeom.Box2I()) # no horizontal prescan record.set(linThreshKey, float(linearityThreshold)) record.set(linMaxKey, float(linearityMax)) record.set(linUnitsKey, "DN") return ampCatalog