diff --git a/python/lsst/ip/isr/isrMock.py b/python/lsst/ip/isr/isrMock.py index 49c2b8153..0f5412fda 100644 --- a/python/lsst/ip/isr/isrMock.py +++ b/python/lsst/ip/isr/isrMock.py @@ -295,6 +295,7 @@ def __init__(self, **kwargs): [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]]) + # Generic gaussian BF kernel self.bfKernel = np.array([[1., 4., 7., 4., 1.], [4., 16., 26., 16., 4.], [7., 26., 41., 26., 7.], diff --git a/python/lsst/ip/isr/isrMockLSST.py b/python/lsst/ip/isr/isrMockLSST.py index 98d4a4cc9..74e0ef3d6 100644 --- a/python/lsst/ip/isr/isrMockLSST.py +++ b/python/lsst/ip/isr/isrMockLSST.py @@ -26,6 +26,7 @@ "TransmissionMockLSST"] import numpy as np +import galsim import lsst.geom as geom import lsst.pex.config as pexConfig @@ -36,6 +37,7 @@ from .defects import Defects from .assembleCcdTask import AssembleCcdTask from .linearize import Linearizer +from .brighterFatterKernel import BrighterFatterKernel class IsrMockLSSTConfig(IsrMockConfig): @@ -68,6 +70,22 @@ class IsrMockLSSTConfig(IsrMockConfig): default=30000.0, doc="Bright defect level (electron).", ) + doAddBrighterFatter = pexConfig.Field( + dtype=bool, + default=False, + doc="Add brighter fatter and/or diffusion effects to image.", + ) + bfStrength = pexConfig.Field( + dtype=float, + default=2.0, + doc="The brighter fatter effect scaling parameter (cannot be zero)." + "Nominally = 1, but = 2 is more realistic." + ) + nRecalc = pexConfig.Field( + dtype=int, + default=10000, + doc="Number of electrons to accumulate before recalculating pixel shapes.", + ) doAddClockInjectedOffset = pexConfig.Field( dtype=bool, default=True, @@ -168,9 +186,116 @@ class IsrMockLSST(IsrMock): _DefaultName = "isrMockLSST" def __init__(self, **kwargs): - # cross-talk coeffs, bf kernel are defined in the parent class. super().__init__(**kwargs) + # Get kernel derived from imSim generated flats with BFE. The kernel + # was used for Ops Rehearsal 3 for LSSTCam-type sensors + # See https://rubinobs.atlassian.net/browse/DM-43059 for more details. + self.bfKernel = np.array([[4.83499829e-01, 8.10171823e-01, 5.31096720e-01, + 3.54369868e-02, -8.44782871e-01, -1.64614462e+00, + -3.83933101e+00, -5.60243416e+00, -6.51691578e+00, + -5.60243416e+00, -3.83933101e+00, -1.64614462e+00, + -8.44782871e-01, 3.54369868e-02, 5.31096720e-01, + 8.10171823e-01, 4.83499829e-01], + [1.12382749e+00, 2.22609074e+00, 1.27877807e+00, + 4.55434098e-01, -1.76842385e+00, -1.90046460e+00, + -8.10874526e+00, -1.20534899e+01, -1.48627948e+01, + -1.20534899e+01, -8.10874526e+00, -1.90046460e+00, + -1.76842385e+00, 4.55434098e-01, 1.27877807e+00, + 2.22609074e+00, 1.12382749e+00], + [1.78571940e+00, 4.38918110e+00, 3.95098587e+00, + 3.70961649e-01, -3.48151981e+00, -9.61567736e+00, + -1.78621172e+01, -2.32278872e+01, -2.31833727e+01, + -2.32278872e+01, -1.78621172e+01, -9.61567736e+00, + -3.48151981e+00, 3.70961649e-01, 3.95098587e+00, + 4.38918110e+00, 1.78571940e+00], + [1.62986900e+00, 3.67851228e+00, 5.68645252e+00, + 2.15342566e-01, -8.89937202e+00, -1.44739813e+01, + -2.98952660e+01, -4.37420817e+01, -4.83160958e+01, + -4.37420817e+01, -2.98952660e+01, -1.44739813e+01, + -8.89937202e+00, 2.15342566e-01, 5.68645252e+00, + 3.67851228e+00, 1.62986900e+00], + [1.05524430e+00, 1.71917897e+00, 1.73105590e+00, + -2.10088420e+00, -1.15118208e+01, -2.55007598e+01, + -4.73056159e+01, -6.97257685e+01, -8.09264433e+01, + -6.97257685e+01, -4.73056159e+01, -2.55007598e+01, + -1.15118208e+01, -2.10088420e+00, 1.73105590e+00, + 1.71917897e+00, 1.05524430e+00], + [8.71929228e-01, 5.41025574e-01, 9.47560771e-01, + -5.75314708e-01, -7.46104027e+00, -4.42314481e+01, + -9.54126971e+01, -1.61603201e+02, -2.07520692e+02, + -1.61603201e+02, -9.54126971e+01, -4.42314481e+01, + -7.46104027e+00, -5.75314708e-01, 9.47560771e-01, + 5.41025574e-01, 8.71929228e-01], + [1.89144704e+00, 3.57543979e+00, -6.91419168e-02, + -3.37950835e+00, -1.46695089e+01, -7.22850746e+01, + -1.65563055e+02, -3.10820425e+02, -4.70026655e+02, + -3.10820425e+02, -1.65563055e+02, -7.22850746e+01, + -1.46695089e+01, -3.37950835e+00, -6.91419168e-02, + 3.57543979e+00, 1.89144704e+00], + [3.11841913e+00, 7.84024994e+00, 1.88495248e+00, + -7.69011009e+00, -2.71782400e+01, -1.04343326e+02, + -2.47561370e+02, -5.32959841e+02, -1.16529012e+03, + -5.32959841e+02, -2.47561370e+02, -1.04343326e+02, + -2.71782400e+01, -7.69011009e+00, 1.88495248e+00, + 7.84024994e+00, 3.11841913e+00], + [2.74197956e+00, 4.73107997e+00, -9.48352966e-01, + -9.44822832e+00, -3.06477671e+01, -1.26788739e+02, + -3.22828411e+02, -8.47943472e+02, -3.87702420e+03, + -8.47943472e+02, -3.22828411e+02, -1.26788739e+02, + -3.06477671e+01, -9.44822832e+00, -9.48352966e-01, + 4.73107997e+00, 2.74197956e+00], + [3.11841913e+00, 7.84024994e+00, 1.88495248e+00, + -7.69011009e+00, -2.71782400e+01, -1.04343326e+02, + -2.47561370e+02, -5.32959841e+02, -1.16529012e+03, + -5.32959841e+02, -2.47561370e+02, -1.04343326e+02, + -2.71782400e+01, -7.69011009e+00, 1.88495248e+00, + 7.84024994e+00, 3.11841913e+00], + [1.89144704e+00, 3.57543979e+00, -6.91419168e-02, + -3.37950835e+00, -1.46695089e+01, -7.22850746e+01, + -1.65563055e+02, -3.10820425e+02, -4.70026655e+02, + -3.10820425e+02, -1.65563055e+02, -7.22850746e+01, + -1.46695089e+01, -3.37950835e+00, -6.91419168e-02, + 3.57543979e+00, 1.89144704e+00], + [8.71929228e-01, 5.41025574e-01, 9.47560771e-01, + -5.75314708e-01, -7.46104027e+00, -4.42314481e+01, + -9.54126971e+01, -1.61603201e+02, -2.07520692e+02, + -1.61603201e+02, -9.54126971e+01, -4.42314481e+01, + -7.46104027e+00, -5.75314708e-01, 9.47560771e-01, + 5.41025574e-01, 8.71929228e-01], + [1.05524430e+00, 1.71917897e+00, 1.73105590e+00, + -2.10088420e+00, -1.15118208e+01, -2.55007598e+01, + -4.73056159e+01, -6.97257685e+01, -8.09264433e+01, + -6.97257685e+01, -4.73056159e+01, -2.55007598e+01, + -1.15118208e+01, -2.10088420e+00, 1.73105590e+00, + 1.71917897e+00, 1.05524430e+00], + [1.62986900e+00, 3.67851228e+00, 5.68645252e+00, + 2.15342566e-01, -8.89937202e+00, -1.44739813e+01, + -2.98952660e+01, -4.37420817e+01, -4.83160958e+01, + -4.37420817e+01, -2.98952660e+01, -1.44739813e+01, + -8.89937202e+00, 2.15342566e-01, 5.68645252e+00, + 3.67851228e+00, 1.62986900e+00], + [1.78571940e+00, 4.38918110e+00, 3.95098587e+00, + 3.70961649e-01, -3.48151981e+00, -9.61567736e+00, + -1.78621172e+01, -2.32278872e+01, -2.31833727e+01, + -2.32278872e+01, -1.78621172e+01, -9.61567736e+00, + -3.48151981e+00, 3.70961649e-01, 3.95098587e+00, + 4.38918110e+00, 1.78571940e+00], + [1.12382749e+00, 2.22609074e+00, 1.27877807e+00, + 4.55434098e-01, -1.76842385e+00, -1.90046460e+00, + -8.10874526e+00, -1.20534899e+01, -1.48627948e+01, + -1.20534899e+01, -8.10874526e+00, -1.90046460e+00, + -1.76842385e+00, 4.55434098e-01, 1.27877807e+00, + 2.22609074e+00, 1.12382749e+00], + [4.83499829e-01, 8.10171823e-01, 5.31096720e-01, + 3.54369868e-02, -8.44782871e-01, -1.64614462+00, + -3.83933101e+00, -5.60243416e+00, -6.51691578e+00, + -5.60243416e+00, -3.83933101e+00, -1.64614462e+00, + -8.44782871e-01, 3.54369868e-02, 5.31096720e-01, + 8.10171823e-01, 4.83499829e-01]]) * 1e-10 + + # cross-talk coeffs are defined in the parent class. + self.makeSubtask("assembleCcd") def run(self): @@ -220,6 +345,7 @@ def makeImage(self): rng2DBias = np.random.RandomState(seed=self.config.rngSeed + 3) rngOverscan = np.random.RandomState(seed=self.config.rngSeed + 4) rngReadNoise = np.random.RandomState(seed=self.config.rngSeed + 5) + rngBrighterFatter = galsim.BaseDeviate(self.config.rngSeed + 6) # Create the linearizer if we will need it. if self.config.doAddHighSignalNonlinearity: @@ -322,7 +448,11 @@ def makeImage(self): self.amplifierAddNoise(ampImageData, darkLevel, darkNoise, rng=rngDark) # 3. Add BF effect (electron) to imaging portion of the amp. - # TODO + if self.config.doAddBrighterFatter is True: + self.amplifierAddBrighterFatter(ampImageData, + rngBrighterFatter, + self.config.bfStrength, + self.config.nRecalc) # 4. Add serial CTI (electron) to amplifier (imaging + overscan). # TODO @@ -536,6 +666,55 @@ def makeDefectList(self, isTrimmed=True): return Defects.fromFootprintList(footprintSet.getFootprints()) + def makeBfKernel(self): + """Generate a simple simulated brighter-fatter kernel. + Returns + ------- + kernel : `lsst.ip.isr.BrighterFatterKernel` + Simulated brighter-fatter kernel. + """ + bfkArray = super().makeBfKernel() + bfKernelObject = BrighterFatterKernel() + bfKernelObject.level = 'AMP' + bfKernelObject.gain = self.config.gainDict + + for amp in self.getExposure().getDetector(): + # Kernel must be in (y,x) orientation + bfKernelObject.ampKernels[amp.getName()] = bfkArray.T + + return bfKernelObject + + def amplifierAddBrighterFatter(self, ampImageData, rng, bfStrength, nRecalc): + """Add brighter fatter effect and/or diffusion to the image. + Parameters + ---------- + ampImageData : `lsst.afw.image.ImageF` + Amplifier image to operate on. + rng : `galsim.BaseDeviate` + Random number generator. + bfStrength : `float` + Scaling parameter of the brighter fatter effect (nominally = 1) + nRecalc: 'int' + The number of electrons to accumulate before recalculating the + distortion of the pixel shapes. + """ + + incidentImage = galsim.Image(ampImageData.array, scale=1) + measuredImage = galsim.ImageF(ampImageData.array.shape[1], + ampImageData.array.shape[0], + scale=1) + photons = galsim.PhotonArray.makeFromImage(incidentImage) + + sensorModel = galsim.SiliconSensor(strength=bfStrength, + rng=rng, + diffusion_factor=0.0, + nrecalc=nRecalc) + + totalFluxAdded = sensorModel.accumulate(photons, measuredImage) + ampImageData.array = measuredImage.array + + return totalFluxAdded + def makeLinearizer(self): # docstring inherited. diff --git a/python/lsst/ip/isr/isrTaskLSST.py b/python/lsst/ip/isr/isrTaskLSST.py index f18b5bea9..c941f6899 100644 --- a/python/lsst/ip/isr/isrTaskLSST.py +++ b/python/lsst/ip/isr/isrTaskLSST.py @@ -412,11 +412,6 @@ class IsrTaskLSSTConfig(pipeBase.PipelineTaskConfig, "from the previous iteration summed over all the pixels.", default=1000, ) - brighterFatterApplyGain = pexConfig.Field( - dtype=bool, - doc="Should the gain be applied when applying the brighter-fatter correction?", - default=True, - ) brighterFatterMaskListToInterpolate = pexConfig.ListField( dtype=str, doc="List of mask planes that should be interpolated over when applying the brighter-fatter " @@ -427,7 +422,7 @@ class IsrTaskLSSTConfig(pipeBase.PipelineTaskConfig, dtype=int, doc="Number of pixels to grow the masks listed in config.brighterFatterMaskListToInterpolate " "when brighter-fatter correction is applied.", - default=0, + default=2, ) brighterFatterFwhmForInterpolation = pexConfig.Field( dtype=float, @@ -1061,39 +1056,55 @@ def getBrighterFatterKernel(self, detector, bfKernel): else: raise RuntimeError("Failed to extract kernel from new-style BF kernel.") elif bfKernel.level == 'AMP': - self.log.warning("Making DETECTOR level kernel from AMP based brighter " - "fatter kernels.") + self.log.info("Making DETECTOR level kernel from AMP based brighter " + "fatter kernels.") bfKernel.makeDetectorKernelFromAmpwiseKernels(detName) bfKernelOut = bfKernel.detKernels[detName] return bfKernelOut, bfGains - def applyBrighterFatterCorrection(self, ccdExposure, flat, dark, bfKernel, bfGains): - # We need to apply flats and darks before we can interpolate, and - # we need to interpolate before we do B-F, but we do B-F without - # the flats and darks applied so we can work in units of electrons - # or holes. This context manager applies and then removes the darks - # and flats. - # - # We also do not want to interpolate values here, so operate on - # temporary images so we can apply only the BF-correction and roll - # back the interpolation. - # This won't be necessary once the gain normalization - # is done appropriately. + def applyBrighterFatterCorrection(self, ccdExposure, flat, dark, bfKernel, brighterFatterApplyGain, + bfGains): + """Apply a brighter fatter correction to the image using the + method defined in Coulton et al. 2019. + + Note that this correction requires that the image is in units + electrons. + + Parameters + ---------- + ccdExposure : `lsst.afw.image.Exposure` + Exposure to process. + flat : `lsst.afw.image.Exposure` + Flat exposure the same size as ``exp``. + dark : `lsst.afw.image.Exposure`, optional + Dark exposure the same size as ``exp``. + bfKernel : `lsst.ip.isr.BrighterFatterKernel` + The brighter-fatter kernel. + brighterFatterApplyGain : `bool` + Apply the gain to convert the image to electrons? + bfGains : `dict` + The gains to use if brighterFatterApplyGain = True. + + Yields + ------ + exp : `lsst.afw.image.Exposure` + The flat and dark corrected exposure. + """ interpExp = ccdExposure.clone() - with self.flatContext(interpExp, flat, dark): - isrFunctions.interpolateFromMask( - maskedImage=interpExp.getMaskedImage(), - fwhm=self.config.brighterFatterFwhmForInterpolation, - growSaturatedFootprints=self.config.growSaturationFootprintSize, - maskNameList=list(self.config.brighterFatterMaskListToInterpolate) - ) + + # We need to interpolate before we do B-F. Note that + # brighterFatterFwhmForInterpolation is currently unused. + isrFunctions.interpolateFromMask( + maskedImage=interpExp.getMaskedImage(), + fwhm=self.config.brighterFatterFwhmForInterpolation, + growSaturatedFootprints=self.config.growSaturationFootprintSize, + maskNameList=list(self.config.brighterFatterMaskListToInterpolate) + ) bfExp = interpExp.clone() - self.log.info("Applying brighter-fatter correction using kernel type %s / gains %s.", - type(bfKernel), type(bfGains)) bfResults = isrFunctions.brighterFatterCorrection(bfExp, bfKernel, self.config.brighterFatterMaxIter, self.config.brighterFatterThreshold, - self.config.brighterFatterApplyGain, + brighterFatterApplyGain, bfGains) if bfResults[1] == self.config.brighterFatterMaxIter: self.log.warning("Brighter-fatter correction did not converge, final difference %f.", @@ -1655,12 +1666,32 @@ def run(self, ccdExposure, *, dnlLUT=None, bias=None, deferredChargeCalib=None, isrFunctions.widenSaturationTrails(ccdExposure.getMaskedImage().getMask()) # Brighter/Fatter - # FIXME: watch out (again) for gain units. # Units: electron if self.config.doBrighterFatter: - self.log.info("Applying Bright-Fatter kernels.") + self.log.info("Applying brighter-fatter correction.") + bfKernelOut, bfGains = self.getBrighterFatterKernel(detector, bfKernel) - ccdExposure = self.applyBrighterFatterCorrection(ccdExposure, flat, dark, bfKernelOut, bfGains) + + # Needs to be done in electrons; applyBrighterFatterCorrection + # will convert the image if necessary. + if exposureMetadata["LSST ISR UNITS"] == "electron": + brighterFatterApplyGain = False + else: + brighterFatterApplyGain = True + + if brighterFatterApplyGain and (ptc is not None) and (bfGains != gains): + # The supplied ptc should be the same as the ptc used to + # generate the bfKernel, in which case they will have the + # same stored amp-keyed dictionary of gains. If not, there + # is a mismatch in the calibrations being used. This should + # not be always be a fatal error, but ideally, everything + # should to be consistent. + self.log.warning("Need to apply gain for brighter-fatter, but the stored" + "gains in the kernel are not the same as the gains stored" + "in the PTC. Using the kernel gains.") + + ccdExposure = self.applyBrighterFatterCorrection(ccdExposure, flat, dark, bfKernelOut, + brighterFatterApplyGain, bfGains) # Variance plane creation # Units: electron diff --git a/tests/test_isrMockLSST.py b/tests/test_isrMockLSST.py index bd1bf4c31..2eef52094 100644 --- a/tests/test_isrMockLSST.py +++ b/tests/test_isrMockLSST.py @@ -27,6 +27,7 @@ import lsst.afw.image as afwImage import lsst.ip.isr.isrMockLSST as isrMockLSST +from lsst.ip.isr.brighterFatterKernel import BrighterFatterKernel class IsrMockLSSTCases(lsst.utils.tests.TestCase): @@ -109,7 +110,7 @@ def test_productTypes(self): """Tests non-image data are returned as the expected type, taking the same approach as in test_isrMock. """ - self.assertIsInstance(isrMockLSST.BfKernelMockLSST().run(), np.ndarray) + self.assertIsInstance(isrMockLSST.BfKernelMockLSST().run(), BrighterFatterKernel) self.assertIsInstance(isrMockLSST.CrosstalkCoeffMockLSST().run(), np.ndarray) self.assertIsInstance(isrMockLSST.DefectMockLSST().run()[0], lsst.meas.algorithms.Defect) diff --git a/tests/test_isrTaskLSST.py b/tests/test_isrTaskLSST.py index e12544a33..e4d597a01 100644 --- a/tests/test_isrTaskLSST.py +++ b/tests/test_isrTaskLSST.py @@ -24,6 +24,7 @@ import unittest import numpy as np import logging +import galsim import lsst.ip.isr.isrMockLSST as isrMockLSST import lsst.utils.tests @@ -476,6 +477,103 @@ def test_isrFlat(self): ratio = result2.exposure.image.array / result.exposure.image.array self.assertFloatsAlmostEqual(ratio, flat_nodefects.image.array, atol=1e-4) + def test_isrBrighterFatter(self): + """Test processing of a flat frame.""" + # Image with brighter-fatter correction + mock_config = self.get_mock_config_no_signal() + mock_config.isTrimmed = False + mock_config.doAddDark = True + mock_config.doAddFlat = True + mock_config.doAddSky = True + mock_config.doAddSource = True + mock_config.sourceFlux = [75000.0] + mock_config.doAddBrighterFatter = True + + mock = isrMockLSST.IsrMockLSST(config=mock_config) + input_exp = mock.run() + + isr_config = self.get_isr_config_electronic_corrections() + isr_config.doBias = True + isr_config.doDark = True + isr_config.doFlat = True + isr_config.doBrighterFatter = True + + isr_task = IsrTaskLSST(config=isr_config) + with self.assertNoLogs(level=logging.WARNING): + result = isr_task.run( + input_exp.clone(), + bias=self.bias, + dark=self.dark, + flat=self.flat, + crosstalk=self.crosstalk, + defects=self.defects, + ptc=self.ptc, + linearizer=self.linearizer, + bfKernel=self.bf_kernel, + ) + + mock_config = self.get_mock_config_no_signal() + mock_config.isTrimmed = False + mock_config.doAddDark = True + mock_config.doAddFlat = True + mock_config.doAddSky = True + mock_config.doAddSource = True + mock_config.sourceFlux = [75000.0] + mock_config.doAddBrighterFatter = False + + mock = isrMockLSST.IsrMockLSST(config=mock_config) + input_truth = mock.run() + + isr_config = self.get_isr_config_electronic_corrections() + isr_config.doBias = True + isr_config.doDark = True + isr_config.doFlat = True + isr_config.doBrighterFatter = False + + isr_task = IsrTaskLSST(config=isr_config) + with self.assertNoLogs(level=logging.WARNING): + result_truth = isr_task.run( + input_truth.clone(), + bias=self.bias, + dark=self.dark, + flat=self.flat, + crosstalk=self.crosstalk, + defects=self.defects, + ptc=self.ptc, + linearizer=self.linearizer, + bfKernel=self.bf_kernel, + ) + + # Measure the source size in the BF-corrected image. + # The injected source is a Gaussian with 3.0px + image = galsim.ImageF(result.exposure.image.array) + image_truth = galsim.ImageF(result_truth.exposure.image.array) + source_centroid = galsim.PositionD(mock_config.sourceX[0], mock_config.sourceY[0]) + hsm_result = galsim.hsm.FindAdaptiveMom(image, guess_centroid=source_centroid, strict=False) + hsm_result_truth = galsim.hsm.FindAdaptiveMom(image_truth, guess_centroid=source_centroid, + strict=False) + measured_sigma = hsm_result.moments_sigma + true_sigma = hsm_result_truth.moments_sigma + self.assertFloatsAlmostEqual(measured_sigma, true_sigma, rtol=3e-3) + + # Check that the variance in an amp far away from the + # source is expected. The source is in amp 0; this will + # check the variation in neighboring amp 1 + test_amp_bbox = result.exposure.detector.getAmplifiers()[1].getBBox() + n_pixels = test_amp_bbox.getArea() + stdev = np.std(result.exposure[test_amp_bbox].image.array) + stdev_truth = np.std(result_truth.exposure[test_amp_bbox].image.array) + self.assertFloatsAlmostEqual(stdev, stdev_truth, atol=3*stdev_truth/np.sqrt(n_pixels)) + + # Check that the variance in the amp with a defect is + # unchanged as a result of applying the BF correction after + # interpolating. The defect was added to amplifier 2. + test_amp_bbox = result.exposure.detector.getAmplifiers()[2].getBBox() + good_pixels = self.get_non_defect_pixels(result.exposure[test_amp_bbox].mask) + stdev = np.nanstd(result.exposure[test_amp_bbox].image.array[good_pixels]) + stdev_truth = np.nanstd(result_truth.exposure[test_amp_bbox].image.array[good_pixels]) + self.assertFloatsAlmostEqual(stdev, stdev_truth, atol=3*stdev_truth/np.sqrt(n_pixels)) + def test_isrSkyImage(self): """Test processing of a sky image.""" mock_config = self.get_mock_config_no_signal() @@ -691,8 +789,6 @@ def get_mock_config_no_signal(self): mock_config.doAddHighSignalNonlinearity = True mock_config.doApplyGain = True mock_config.doRoundAdu = True - # NOTE: additional electronic effects (BF, CTI) should - # be added here when they are supported. # We always want to generate the image with these configs. mock_config.doGenerateImage = True @@ -773,10 +869,13 @@ def get_isr_config_electronic_corrections(self): isr_config.doDefect = True isr_config.doLinearize = True - # These are the electronic effects we do not support in tetss yet. + # This is False because it is only used in a single test case + # as it takes a while to solve + isr_config.doBrighterFatter = False + + # These are the electronic effects we do not support in tests yet. isr_config.doDeferredCharge = False isr_config.doCorrectGains = False - isr_config.doBrighterFatter = False # We override the leading/trailing to skip here because of the limited # size of the test camera overscan regions.