LSST Applications 28.0.0,g1653933729+a8ce1bb630,g1a997c3884+a8ce1bb630,g28da252d5a+5bd70b7e6d,g2bbee38e9b+638fca75ac,g2bc492864f+638fca75ac,g3156d2b45e+07302053f8,g347aa1857d+638fca75ac,g35bb328faa+a8ce1bb630,g3a166c0a6a+638fca75ac,g3e281a1b8c+7bbb0b2507,g4005a62e65+17cd334064,g414038480c+5b5cd4fff3,g41af890bb2+4ffae9de63,g4e1a3235cc+0f1912dca3,g6249c6f860+3c3976f90c,g80478fca09+46aba80bd6,g82479be7b0+77990446f6,g858d7b2824+78ba4d1ce1,g89c8672015+f667a5183b,g9125e01d80+a8ce1bb630,ga5288a1d22+2a6264e9ca,gae0086650b+a8ce1bb630,gb58c049af0+d64f4d3760,gc22bb204ba+78ba4d1ce1,gc28159a63d+638fca75ac,gcf0d15dbbd+32ddb6096f,gd6b7c0dfd1+3e339405e9,gda3e153d99+78ba4d1ce1,gda6a2b7d83+32ddb6096f,gdaeeff99f8+1711a396fd,gdd5a9049c5+b18c39e5e3,ge2409df99d+a5e4577cdc,ge33fd446bb+78ba4d1ce1,ge79ae78c31+638fca75ac,gf0baf85859+64e8883e75,gf5289d68f6+e1b046a8d7,gfa443fc69c+91d9ed1ecf,gfda6b12a05+8419469a56
LSST Data Management Base Package
Loading...
Searching...
No Matches
lsst.ip.isr.isrMockLSST.IsrMockLSST Class Reference
Inheritance diagram for lsst.ip.isr.isrMockLSST.IsrMockLSST:
lsst.ip.isr.isrMock.IsrMock lsst.ip.isr.isrMockLSST.BfKernelMockLSST lsst.ip.isr.isrMockLSST.CrosstalkCoeffMockLSST lsst.ip.isr.isrMockLSST.DefectMockLSST lsst.ip.isr.isrMockLSST.DeferredChargeMockLSST lsst.ip.isr.isrMockLSST.LinearizerMockLSST lsst.ip.isr.isrMockLSST.RawMockLSST lsst.ip.isr.isrMockLSST.ReferenceMockLSST lsst.ip.isr.isrMockLSST.TransmissionMockLSST

Public Member Functions

 __init__ (self, **kwargs)
 
 run (self)
 
 makeImage (self)
 
 addBiasLevel (self, ampData, biasLevel)
 
 makeDefectList (self, isTrimmed=True)
 
 makeBfKernel (self)
 
 makeDeferredChargeCalib (self)
 
 amplifierAddBrighterFatter (self, ampImageData, rng, bfStrength, nRecalc)
 
 amplifierAddDeferredCharge (self, exposure, amp)
 
 makeLinearizer (self)
 
 amplifierAddNonlinearity (self, ampData, centers, values, offset)
 
 amplifierMultiplyFlat (self, amp, ampData, fracDrop, u0=100.0, v0=100.0)
 
 applyGain (self, ampData, gain)
 
 roundADU (self, ampData)
 
 amplifierAddXGradient (self, ampData, start, end)
 
 getFullSerialOverscanBBox (self, amp)
 

Public Attributes

 bfKernel
 
 splineTrapCoeffs
 
 ctiCalibDict
 
 deferredChargeCalib
 
 cti
 

Static Public Attributes

 ConfigClass = IsrMockLSSTConfig
 

Static Protected Attributes

str _DefaultName = "isrMockLSST"
 

Detailed Description

Class to generate consistent mock images for ISR testing.

Definition at line 220 of file isrMockLSST.py.

Constructor & Destructor Documentation

◆ __init__()

lsst.ip.isr.isrMockLSST.IsrMockLSST.__init__ ( self,
** kwargs )

Reimplemented from lsst.ip.isr.isrMock.IsrMock.

Reimplemented in lsst.ip.isr.isrMockLSST.BfKernelMockLSST, lsst.ip.isr.isrMockLSST.BiasMockLSST, lsst.ip.isr.isrMockLSST.CalibratedRawMockLSST, lsst.ip.isr.isrMockLSST.CrosstalkCoeffMockLSST, lsst.ip.isr.isrMockLSST.DarkMockLSST, lsst.ip.isr.isrMockLSST.DefectMockLSST, lsst.ip.isr.isrMockLSST.DeferredChargeMockLSST, lsst.ip.isr.isrMockLSST.FlatMockLSST, lsst.ip.isr.isrMockLSST.FringeMockLSST, lsst.ip.isr.isrMockLSST.LinearizerMockLSST, lsst.ip.isr.isrMockLSST.RawMockLSST, lsst.ip.isr.isrMockLSST.ReferenceMockLSST, lsst.ip.isr.isrMockLSST.TransmissionMockLSST, and lsst.ip.isr.isrMockLSST.TrimmedRawMockLSST.

Definition at line 226 of file isrMockLSST.py.

226 def __init__(self, **kwargs):
227 super().__init__(**kwargs)
228
229 # Get kernel derived from imSim generated flats with BFE. The kernel
230 # was used for Ops Rehearsal 3 for LSSTCam-type sensors
231 # See https://rubinobs.atlassian.net/browse/DM-43059 for more details.
232 self.bfKernel = np.array([[4.83499829e-01, 8.10171823e-01, 5.31096720e-01,
233 3.54369868e-02, -8.44782871e-01, -1.64614462e+00,
234 -3.83933101e+00, -5.60243416e+00, -6.51691578e+00,
235 -5.60243416e+00, -3.83933101e+00, -1.64614462e+00,
236 -8.44782871e-01, 3.54369868e-02, 5.31096720e-01,
237 8.10171823e-01, 4.83499829e-01],
238 [1.12382749e+00, 2.22609074e+00, 1.27877807e+00,
239 4.55434098e-01, -1.76842385e+00, -1.90046460e+00,
240 -8.10874526e+00, -1.20534899e+01, -1.48627948e+01,
241 -1.20534899e+01, -8.10874526e+00, -1.90046460e+00,
242 -1.76842385e+00, 4.55434098e-01, 1.27877807e+00,
243 2.22609074e+00, 1.12382749e+00],
244 [1.78571940e+00, 4.38918110e+00, 3.95098587e+00,
245 3.70961649e-01, -3.48151981e+00, -9.61567736e+00,
246 -1.78621172e+01, -2.32278872e+01, -2.31833727e+01,
247 -2.32278872e+01, -1.78621172e+01, -9.61567736e+00,
248 -3.48151981e+00, 3.70961649e-01, 3.95098587e+00,
249 4.38918110e+00, 1.78571940e+00],
250 [1.62986900e+00, 3.67851228e+00, 5.68645252e+00,
251 2.15342566e-01, -8.89937202e+00, -1.44739813e+01,
252 -2.98952660e+01, -4.37420817e+01, -4.83160958e+01,
253 -4.37420817e+01, -2.98952660e+01, -1.44739813e+01,
254 -8.89937202e+00, 2.15342566e-01, 5.68645252e+00,
255 3.67851228e+00, 1.62986900e+00],
256 [1.05524430e+00, 1.71917897e+00, 1.73105590e+00,
257 -2.10088420e+00, -1.15118208e+01, -2.55007598e+01,
258 -4.73056159e+01, -6.97257685e+01, -8.09264433e+01,
259 -6.97257685e+01, -4.73056159e+01, -2.55007598e+01,
260 -1.15118208e+01, -2.10088420e+00, 1.73105590e+00,
261 1.71917897e+00, 1.05524430e+00],
262 [8.71929228e-01, 5.41025574e-01, 9.47560771e-01,
263 -5.75314708e-01, -7.46104027e+00, -4.42314481e+01,
264 -9.54126971e+01, -1.61603201e+02, -2.07520692e+02,
265 -1.61603201e+02, -9.54126971e+01, -4.42314481e+01,
266 -7.46104027e+00, -5.75314708e-01, 9.47560771e-01,
267 5.41025574e-01, 8.71929228e-01],
268 [1.89144704e+00, 3.57543979e+00, -6.91419168e-02,
269 -3.37950835e+00, -1.46695089e+01, -7.22850746e+01,
270 -1.65563055e+02, -3.10820425e+02, -4.70026655e+02,
271 -3.10820425e+02, -1.65563055e+02, -7.22850746e+01,
272 -1.46695089e+01, -3.37950835e+00, -6.91419168e-02,
273 3.57543979e+00, 1.89144704e+00],
274 [3.11841913e+00, 7.84024994e+00, 1.88495248e+00,
275 -7.69011009e+00, -2.71782400e+01, -1.04343326e+02,
276 -2.47561370e+02, -5.32959841e+02, -1.16529012e+03,
277 -5.32959841e+02, -2.47561370e+02, -1.04343326e+02,
278 -2.71782400e+01, -7.69011009e+00, 1.88495248e+00,
279 7.84024994e+00, 3.11841913e+00],
280 [2.74197956e+00, 4.73107997e+00, -9.48352966e-01,
281 -9.44822832e+00, -3.06477671e+01, -1.26788739e+02,
282 -3.22828411e+02, -8.47943472e+02, -3.87702420e+03,
283 -8.47943472e+02, -3.22828411e+02, -1.26788739e+02,
284 -3.06477671e+01, -9.44822832e+00, -9.48352966e-01,
285 4.73107997e+00, 2.74197956e+00],
286 [3.11841913e+00, 7.84024994e+00, 1.88495248e+00,
287 -7.69011009e+00, -2.71782400e+01, -1.04343326e+02,
288 -2.47561370e+02, -5.32959841e+02, -1.16529012e+03,
289 -5.32959841e+02, -2.47561370e+02, -1.04343326e+02,
290 -2.71782400e+01, -7.69011009e+00, 1.88495248e+00,
291 7.84024994e+00, 3.11841913e+00],
292 [1.89144704e+00, 3.57543979e+00, -6.91419168e-02,
293 -3.37950835e+00, -1.46695089e+01, -7.22850746e+01,
294 -1.65563055e+02, -3.10820425e+02, -4.70026655e+02,
295 -3.10820425e+02, -1.65563055e+02, -7.22850746e+01,
296 -1.46695089e+01, -3.37950835e+00, -6.91419168e-02,
297 3.57543979e+00, 1.89144704e+00],
298 [8.71929228e-01, 5.41025574e-01, 9.47560771e-01,
299 -5.75314708e-01, -7.46104027e+00, -4.42314481e+01,
300 -9.54126971e+01, -1.61603201e+02, -2.07520692e+02,
301 -1.61603201e+02, -9.54126971e+01, -4.42314481e+01,
302 -7.46104027e+00, -5.75314708e-01, 9.47560771e-01,
303 5.41025574e-01, 8.71929228e-01],
304 [1.05524430e+00, 1.71917897e+00, 1.73105590e+00,
305 -2.10088420e+00, -1.15118208e+01, -2.55007598e+01,
306 -4.73056159e+01, -6.97257685e+01, -8.09264433e+01,
307 -6.97257685e+01, -4.73056159e+01, -2.55007598e+01,
308 -1.15118208e+01, -2.10088420e+00, 1.73105590e+00,
309 1.71917897e+00, 1.05524430e+00],
310 [1.62986900e+00, 3.67851228e+00, 5.68645252e+00,
311 2.15342566e-01, -8.89937202e+00, -1.44739813e+01,
312 -2.98952660e+01, -4.37420817e+01, -4.83160958e+01,
313 -4.37420817e+01, -2.98952660e+01, -1.44739813e+01,
314 -8.89937202e+00, 2.15342566e-01, 5.68645252e+00,
315 3.67851228e+00, 1.62986900e+00],
316 [1.78571940e+00, 4.38918110e+00, 3.95098587e+00,
317 3.70961649e-01, -3.48151981e+00, -9.61567736e+00,
318 -1.78621172e+01, -2.32278872e+01, -2.31833727e+01,
319 -2.32278872e+01, -1.78621172e+01, -9.61567736e+00,
320 -3.48151981e+00, 3.70961649e-01, 3.95098587e+00,
321 4.38918110e+00, 1.78571940e+00],
322 [1.12382749e+00, 2.22609074e+00, 1.27877807e+00,
323 4.55434098e-01, -1.76842385e+00, -1.90046460e+00,
324 -8.10874526e+00, -1.20534899e+01, -1.48627948e+01,
325 -1.20534899e+01, -8.10874526e+00, -1.90046460e+00,
326 -1.76842385e+00, 4.55434098e-01, 1.27877807e+00,
327 2.22609074e+00, 1.12382749e+00],
328 [4.83499829e-01, 8.10171823e-01, 5.31096720e-01,
329 3.54369868e-02, -8.44782871e-01, -1.64614462+00,
330 -3.83933101e+00, -5.60243416e+00, -6.51691578e+00,
331 -5.60243416e+00, -3.83933101e+00, -1.64614462e+00,
332 -8.44782871e-01, 3.54369868e-02, 5.31096720e-01,
333 8.10171823e-01, 4.83499829e-01]]) * 1e-10
334
335 # Spline trap coefficients and the ctiCalibDict are all taken from a
336 # cti calibration measured from LSSTCam sensor R03_S12 during Run 5
337 # EO testing. These are the coefficients for the spline trap model
338 # used in the deferred charge calibration. The collection can be
339 # found in /repo/ir2: u/abrought/13144/cti (processed 3/4/2024).
340 self.splineTrapCoeffs = np.array([0.0, 28.1, 47.4, 56.4, 66.6, 78.6, 92.4, 109.4,
341 129.0, 151.9, 179.4, 211.9, 250.5, 296.2, 350.0,
342 413.5, 488.0, 576.0, 680.4, 753.0, 888.2, 1040.5,
343 1254.1, 1478.9, 1747.0, 2055.7, 2416.9, 2855.2,
344 3361.9, 3969.4, 4665.9, 5405.3, 6380.0, 7516.7,
345 8875.9, 10488.6, 12681.9, 14974.2, 17257.6, 20366.5,
346 24026.7, 28372.1, 33451.7, 39550.4, 46624.8, 55042.9,
347 64862.7, 76503.1, 90265.6, 106384.2, 0.0, 0.0, 0.0,
348 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1,
349 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 0.0,
350 0.1, 0.2, 0.6, 0.1, 0.0, 0.1, 0.0, 0.6, 0.3, 0.5, 0.8,
351 0.8, 1.5, 2.0, 1.8, 2.4, 2.6, 3.7, 5.0, 6.4, 8.4, 10.9,
352 14.5, 21.1, 28.9])
353
354 self.ctiCalibDict = {'driftScale': {'C:0,0': 0.000127,
355 'C:0,1': 0.000137,
356 'C:0,2': 0.000138,
357 'C:0,3': 0.000147,
358 'C:1,0': 0.000147,
359 'C:1,1': 0.000122,
360 'C:1,2': 0.000123,
361 'C:1,3': 0.000116},
362 'decayTime': {'C:0,0': 2.30,
363 'C:0,1': 2.21,
364 'C:0,2': 2.28,
365 'C:0,3': 2.34,
366 'C:1,0': 2.30,
367 'C:1,1': 2.40,
368 'C:1,2': 2.51,
369 'C:1,3': 2.21},
370 'globalCti': {'C:0,0': 5.25e-07,
371 'C:0,1': 5.38e-07,
372 'C:0,2': 5.80e-07,
373 'C:0,3': 5.91e-07,
374 'C:1,0': 6.24e-07,
375 'C:1,1': 5.72e-07,
376 'C:1,2': 5.60e-07,
377 'C:1,3': 4.40e-07},
378 'serialTraps': {'C:0,0': {'size': 20000.0,
379 'emissionTime': 0.4,
380 'pixel': 1,
381 'trap_type': 'spline',
382 'coeffs': self.splineTrapCoeffs},
383 'C:0,1': {'size': 20000.0,
384 'emissionTime': 0.4,
385 'pixel': 1,
386 'trap_type': 'spline',
387 'coeffs': self.splineTrapCoeffs},
388 'C:0,2': {'size': 20000.0,
389 'emissionTime': 0.4,
390 'pixel': 1,
391 'trap_type': 'spline',
392 'coeffs': self.splineTrapCoeffs},
393 'C:0,3': {'size': 20000.0,
394 'emissionTime': 0.4,
395 'pixel': 1,
396 'trap_type': 'spline',
397 'coeffs': self.splineTrapCoeffs},
398 'C:1,0': {'size': 20000.0,
399 'emissionTime': 0.4,
400 'pixel': 1,
401 'trap_type': 'spline',
402 'coeffs': self.splineTrapCoeffs},
403 'C:1,1': {'size': 20000.0,
404 'emissionTime': 0.4,
405 'pixel': 1,
406 'trap_type': 'spline',
407 'coeffs': self.splineTrapCoeffs},
408 'C:1,2': {'size': 20000.0,
409 'emissionTime': 0.4,
410 'pixel': 1,
411 'trap_type': 'spline',
412 'coeffs': self.splineTrapCoeffs},
413 'C:1,3': {'size': 20000.0,
414 'emissionTime': 0.4,
415 'pixel': 1,
416 'trap_type': 'spline',
417 'coeffs': self.splineTrapCoeffs}}}
418
419 self.deferredChargeCalib = self.makeDeferredChargeCalib()
420
421 # Cross-talk coeffs are defined in the parent class.
422
423 self.makeSubtask("assembleCcd")
424

Member Function Documentation

◆ addBiasLevel()

lsst.ip.isr.isrMockLSST.IsrMockLSST.addBiasLevel ( self,
ampData,
biasLevel )
Add bias level to an amplifier's image data.

Parameters
----------
ampData : `lsst.afw.image.ImageF`
    Amplifier image to operate on.
biasLevel : `float`
    Bias level to be added to the image.

Definition at line 766 of file isrMockLSST.py.

766 def addBiasLevel(self, ampData, biasLevel):
767 """Add bias level to an amplifier's image data.
768
769 Parameters
770 ----------
771 ampData : `lsst.afw.image.ImageF`
772 Amplifier image to operate on.
773 biasLevel : `float`
774 Bias level to be added to the image.
775 """
776 ampArr = ampData.array
777 ampArr[:] = ampArr[:] + biasLevel
778

◆ amplifierAddBrighterFatter()

lsst.ip.isr.isrMockLSST.IsrMockLSST.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.

Definition at line 858 of file isrMockLSST.py.

858 def amplifierAddBrighterFatter(self, ampImageData, rng, bfStrength, nRecalc):
859 """Add brighter fatter effect and/or diffusion to the image.
860 Parameters
861 ----------
862 ampImageData : `lsst.afw.image.ImageF`
863 Amplifier image to operate on.
864 rng : `galsim.BaseDeviate`
865 Random number generator.
866 bfStrength : `float`
867 Scaling parameter of the brighter fatter effect (nominally = 1)
868 nRecalc: 'int'
869 The number of electrons to accumulate before recalculating the
870 distortion of the pixel shapes.
871 """
872
873 incidentImage = galsim.Image(ampImageData.array, scale=1)
874 measuredImage = galsim.ImageF(
875 ampImageData.array.shape[1],
876 ampImageData.array.shape[0],
877 scale=1,
878 )
879 photons = galsim.PhotonArray.makeFromImage(incidentImage)
880
881 sensorModel = galsim.SiliconSensor(
882 strength=bfStrength,
883 rng=rng,
884 diffusion_factor=0.0,
885 nrecalc=nRecalc,
886 )
887
888 totalFluxAdded = sensorModel.accumulate(photons, measuredImage)
889 ampImageData.array = measuredImage.array
890
891 return totalFluxAdded
892

◆ amplifierAddDeferredCharge()

lsst.ip.isr.isrMockLSST.IsrMockLSST.amplifierAddDeferredCharge ( self,
exposure,
amp )
Add serial CTI to the amplifier data.

Parameters
----------
exposure : `lsst.afw.image.ExposureF`
    The exposure object containing the amplifier
    to apply deferred charge to.
amp : `lsst.afw.image.Amplifier`
    The amplifier object (contains geometry info).

Definition at line 893 of file isrMockLSST.py.

893 def amplifierAddDeferredCharge(self, exposure, amp):
894 """Add serial CTI to the amplifier data.
895
896 Parameters
897 ----------
898 exposure : `lsst.afw.image.ExposureF`
899 The exposure object containing the amplifier
900 to apply deferred charge to.
901 amp : `lsst.afw.image.Amplifier`
902 The amplifier object (contains geometry info).
903 """
904 # Get the amplifier's geometry parameters.
905 # When adding deferred charge, we have already assured that
906 # isTrimmed is False. Therefore we want to make sure that we
907 # get the RawDataBBox.
908 readoutCorner = amp.getReadoutCorner()
909 prescanWidth = amp.getRawHorizontalPrescanBBox().getWidth()
910 serialOverscanWidth = amp.getRawHorizontalOverscanBBox().getWidth()
911 parallelOverscanWidth = amp.getRawVerticalOverscanBBox().getHeight()
912 bboxFreeCharge = amp.getRawDataBBox()
913 bboxFreeCharge = bboxFreeCharge.expandedTo(amp.getRawHorizontalOverscanBBox())
914 bboxFreeCharge = bboxFreeCharge.expandedTo(amp.getRawHorizontalPrescanBBox())
915 bboxFreeCharge = bboxFreeCharge.expandedTo(amp.getRawVerticalOverscanBBox())
916
917 ampFreeChargeData = exposure.image[bboxFreeCharge]
918 ampImageData = exposure.image[amp.getRawDataBBox()]
919
920 # Get the deferred charge parameters for this amplifier.
921 cti = self.deferredChargeCalib.globalCti[amp.getName()]
922 traps = self.deferredChargeCalib.serialTraps[amp.getName()]
923 driftScale = self.deferredChargeCalib.driftScale[amp.getName()]
924 decayTime = self.deferredChargeCalib.decayTime[amp.getName()]
925
926 # Create a fake amplifier object that contains some deferred charge
927 # paramters.
928 floatingOutputAmplifier = FloatingOutputAmplifier(
929 gain=1.0, # Everything is already in electrons.
930 scale=driftScale,
931 decay_time=decayTime,
932 noise=0.0,
933 offset=0.0,
934 )
935
936 def flipImage(arr, readoutCorner):
937 # Flip an array so that the readout corner is in
938 # the lower left.
939 if readoutCorner == ReadoutCorner.LR:
940 return np.fliplr(arr)
941 elif readoutCorner == ReadoutCorner.UR:
942 return np.fliplr(np.flipud(arr))
943 elif readoutCorner == ReadoutCorner.UL:
944 return np.flipud(arr)
945 else:
946 pass
947
948 return arr
949
950 # The algorithm expects that the readout corner is in
951 # the lower left corner. Flip it to be so:
952 imageData = ampImageData.array
953 imageData = flipImage(imageData, readoutCorner)
954
955 # Simulate the amplifier.
956 ampSim = SegmentSimulator(
957 imarr=imageData,
958 prescan_width=prescanWidth,
959 output_amplifier=floatingOutputAmplifier,
960 cti=cti,
961 traps=traps,
962 )
963
964 # Simulate deferred charge!
965 # Note that the readout() method uses the image region data and the
966 # overscan dimensions provided as input parameters. It then creates
967 # overscan nd adds it to the image data to create the raw image.
968 result = ampSim.readout(
969 serial_overscan_width=serialOverscanWidth,
970 parallel_overscan_width=parallelOverscanWidth,
971 )
972
973 # Flip the image back to the original orientation.
974 result = flipImage(result, readoutCorner)
975
976 # Set the image with the deferred charge added.
977 ampFreeChargeData.array[:, :] = result
978

◆ amplifierAddNonlinearity()

lsst.ip.isr.isrMockLSST.IsrMockLSST.amplifierAddNonlinearity ( self,
ampData,
centers,
values,
offset )
Add non-linearity to amplifier data.

Parameters
----------
ampData : `lsst.afw.image.ImageF`
    Amplifier image to operate on.
centers : `np.ndarray`
    Spline nodes.
values : `np.ndarray`
    Spline values.
offset : `float`
    Offset zero-point between linearizer (internal vs external).

Definition at line 1022 of file isrMockLSST.py.

1022 def amplifierAddNonlinearity(self, ampData, centers, values, offset):
1023 """Add non-linearity to amplifier data.
1024
1025 Parameters
1026 ----------
1027 ampData : `lsst.afw.image.ImageF`
1028 Amplifier image to operate on.
1029 centers : `np.ndarray`
1030 Spline nodes.
1031 values : `np.ndarray`
1032 Spline values.
1033 offset : `float`
1034 Offset zero-point between linearizer (internal vs external).
1035 """
1036 # I'm not sure what to do about negative values...
1037
1039 centers,
1040 values,
1041 afwMath.stringToInterpStyle("AKIMA_SPLINE"),
1042 )
1043
1044 delta = np.asarray(spl.interpolate(ampData.array.ravel() - offset))
1045
1046 ampData.array[:, :] += delta.reshape(ampData.array.shape)
1047
Interpolate::Style stringToInterpStyle(std::string const &style)
Conversion function to switch a string to an Interpolate::Style.
std::shared_ptr< Interpolate > makeInterpolate(std::vector< double > const &x, std::vector< double > const &y, Interpolate::Style const style=Interpolate::AKIMA_SPLINE)
A factory function to make Interpolate objects.

◆ amplifierAddXGradient()

lsst.ip.isr.isrMockLSST.IsrMockLSST.amplifierAddXGradient ( self,
ampData,
start,
end )
Add a x-axis linear gradient to an amplifier's image data.

 This method operates in the amplifier coordinate frame.

Parameters
----------
ampData : `lsst.afw.image.ImageF`
    Amplifier image to operate on.
start : `float`
    Start value of the gradient (at x=0).
end : `float`
    End value of the gradient (at x=xmax).

Definition at line 1103 of file isrMockLSST.py.

1103 def amplifierAddXGradient(self, ampData, start, end):
1104 """Add a x-axis linear gradient to an amplifier's image data.
1105
1106 This method operates in the amplifier coordinate frame.
1107
1108 Parameters
1109 ----------
1110 ampData : `lsst.afw.image.ImageF`
1111 Amplifier image to operate on.
1112 start : `float`
1113 Start value of the gradient (at x=0).
1114 end : `float`
1115 End value of the gradient (at x=xmax).
1116 """
1117 nPixX = ampData.getDimensions().getX()
1118 ampArr = ampData.array
1119 ampArr[:] = ampArr[:] + (np.interp(range(nPixX), (0, nPixX - 1), (start, end)).reshape(1, nPixX)
1120 + np.zeros(ampData.getDimensions()).transpose())
1121

◆ amplifierMultiplyFlat()

lsst.ip.isr.isrMockLSST.IsrMockLSST.amplifierMultiplyFlat ( self,
amp,
ampData,
fracDrop,
u0 = 100.0,
v0 = 100.0 )
Multiply an amplifier's image data by a flat-like pattern.

Parameters
----------
amp : `lsst.afw.ampInfo.AmpInfoRecord`
    Amplifier to operate on. Needed for amp<->exp coordinate
    transforms.
ampData : `lsst.afw.image.ImageF`
    Amplifier image to operate on.
fracDrop : `float`
    Fractional drop from center to edge of detector along x-axis.
u0 : `float`
    Peak location in detector coordinates.
v0 : `float`
    Peak location in detector coordinates.

Reimplemented from lsst.ip.isr.isrMock.IsrMock.

Definition at line 1048 of file isrMockLSST.py.

1048 def amplifierMultiplyFlat(self, amp, ampData, fracDrop, u0=100.0, v0=100.0):
1049 """Multiply an amplifier's image data by a flat-like pattern.
1050
1051 Parameters
1052 ----------
1053 amp : `lsst.afw.ampInfo.AmpInfoRecord`
1054 Amplifier to operate on. Needed for amp<->exp coordinate
1055 transforms.
1056 ampData : `lsst.afw.image.ImageF`
1057 Amplifier image to operate on.
1058 fracDrop : `float`
1059 Fractional drop from center to edge of detector along x-axis.
1060 u0 : `float`
1061 Peak location in detector coordinates.
1062 v0 : `float`
1063 Peak location in detector coordinates.
1064 """
1065 if fracDrop >= 1.0:
1066 raise RuntimeError("Flat fractional drop cannot be greater than 1.0")
1067
1068 sigma = u0 / np.sqrt(2.0 * fracDrop)
1069
1070 for x in range(0, ampData.getDimensions().getX()):
1071 for y in range(0, ampData.getDimensions().getY()):
1072 (u, v) = self.localCoordToExpCoord(amp, x, y)
1073 f = np.exp(-0.5 * ((u - u0)**2 + (v - v0)**2) / sigma**2)
1074 ampData.array[y][x] = (ampData.array[y][x] * f)
1075

◆ applyGain()

lsst.ip.isr.isrMockLSST.IsrMockLSST.applyGain ( self,
ampData,
gain )
Apply gain to the amplifier's data.
This method divides the data by the gain
because the mocks need to convert the data in electron to adu,
so it does the inverse operation to applyGains in isrFunctions.

Parameters
----------
ampData : `lsst.afw.image.ImageF`
    Amplifier image to operate on.
gain : `float`
    Gain value in electron/adu.

Definition at line 1076 of file isrMockLSST.py.

1076 def applyGain(self, ampData, gain):
1077 """Apply gain to the amplifier's data.
1078 This method divides the data by the gain
1079 because the mocks need to convert the data in electron to adu,
1080 so it does the inverse operation to applyGains in isrFunctions.
1081
1082 Parameters
1083 ----------
1084 ampData : `lsst.afw.image.ImageF`
1085 Amplifier image to operate on.
1086 gain : `float`
1087 Gain value in electron/adu.
1088 """
1089 ampArr = ampData.array
1090 ampArr[:] = ampArr[:] / gain
1091

◆ getFullSerialOverscanBBox()

lsst.ip.isr.isrMockLSST.IsrMockLSST.getFullSerialOverscanBBox ( self,
amp )
Get the full serial overscan bounding box from an amplifier.

This includes the serial/parallel overscan region.

Parameters
----------
amp : `lsst.afw.ampInfo.AmpInfoRecord`
    Amplifier to operate on.

Returns
-------
bbox : `lsst.geom.Box2I`

Definition at line 1122 of file isrMockLSST.py.

1122 def getFullSerialOverscanBBox(self, amp):
1123 """Get the full serial overscan bounding box from an amplifier.
1124
1125 This includes the serial/parallel overscan region.
1126
1127 Parameters
1128 ----------
1129 amp : `lsst.afw.ampInfo.AmpInfoRecord`
1130 Amplifier to operate on.
1131
1132 Returns
1133 -------
1134 bbox : `lsst.geom.Box2I`
1135 """
1136 # This only works for untrimmed data.
1137 bbox = amp.getRawDataBBox()
1138
1139 parallelOverscanBBox = amp.getRawParallelOverscanBBox()
1140 grownImageBBox = bbox.expandedTo(parallelOverscanBBox)
1141
1142 serialOverscanBBox = amp.getRawSerialOverscanBBox()
1143 # Extend the serial overscan bbox to include corners
1144 serialOverscanBBox = geom.Box2I(
1145 geom.Point2I(serialOverscanBBox.getMinX(),
1146 grownImageBBox.getMinY()),
1147 geom.Extent2I(serialOverscanBBox.getWidth(),
1148 grownImageBBox.getHeight()))
1149
1150 return serialOverscanBBox
1151
1152
An integer coordinate rectangle.
Definition Box.h:55

◆ makeBfKernel()

lsst.ip.isr.isrMockLSST.IsrMockLSST.makeBfKernel ( self)
Generate a simple simulated brighter-fatter kernel.
Returns
-------
kernel : `lsst.ip.isr.BrighterFatterKernel`
    Simulated brighter-fatter kernel.

Reimplemented from lsst.ip.isr.isrMock.IsrMock.

Definition at line 816 of file isrMockLSST.py.

816 def makeBfKernel(self):
817 """Generate a simple simulated brighter-fatter kernel.
818 Returns
819 -------
820 kernel : `lsst.ip.isr.BrighterFatterKernel`
821 Simulated brighter-fatter kernel.
822 """
823 bfkArray = super().makeBfKernel()
824 bfKernelObject = BrighterFatterKernel()
825 bfKernelObject.level = 'AMP'
826 bfKernelObject.gain = self.config.gainDict
827
828 for amp in self.getExposure().getDetector():
829 # Kernel must be in (y,x) orientation
830 bfKernelObject.ampKernels[amp.getName()] = bfkArray.T
831
832 return bfKernelObject
833

◆ makeDefectList()

lsst.ip.isr.isrMockLSST.IsrMockLSST.makeDefectList ( self,
isTrimmed = True )
Generate a simple defect list.

Parameters
----------
isTrimmed : `bool`, optional
    Return defects in trimmed coordinates?

Returns
-------
defectList : `lsst.meas.algorithms.Defects`
    Simulated defect list

Reimplemented from lsst.ip.isr.isrMock.IsrMock.

Definition at line 779 of file isrMockLSST.py.

779 def makeDefectList(self, isTrimmed=True):
780 """Generate a simple defect list.
781
782 Parameters
783 ----------
784 isTrimmed : `bool`, optional
785 Return defects in trimmed coordinates?
786
787 Returns
788 -------
789 defectList : `lsst.meas.algorithms.Defects`
790 Simulated defect list
791 """
792 defectBoxesUntrimmed = [
794 geom.Point2I(50, 118),
795 geom.Extent2I(1, 51),
796 ),
797 ]
798
799 if not isTrimmed:
800 return Defects(defectBoxesUntrimmed)
801
802 # If trimmed, we need to convert.
803 tempExp = self.getExposure(isTrimmed=False)
804 tempExp.image.array[:, :] = 0.0
805 for bbox in defectBoxesUntrimmed:
806 tempExp.image[bbox] = 1.0
807
808 assembledExp = self.assembleCcd.assembleCcd(tempExp)
809
810 # Use thresholding code to find defect footprints/boxes.
811 threshold = afwDetection.createThreshold(1.0, "value", polarity=True)
812 footprintSet = afwDetection.FootprintSet(assembledExp.image, threshold)
813
814 return Defects.fromFootprintList(footprintSet.getFootprints())
815

◆ makeDeferredChargeCalib()

lsst.ip.isr.isrMockLSST.IsrMockLSST.makeDeferredChargeCalib ( self)
Generate a CTI calibration.

Returns
-------
cti : `lsst.ip.isr.deferredCharge.DeferredChargeCalib`
    Simulated deferred charge calibration.

Reimplemented from lsst.ip.isr.isrMock.IsrMock.

Definition at line 834 of file isrMockLSST.py.

834 def makeDeferredChargeCalib(self):
835 """Generate a CTI calibration.
836
837 Returns
838 -------
839 cti : `lsst.ip.isr.deferredCharge.DeferredChargeCalib`
840 Simulated deferred charge calibration.
841 """
842
843 metadataDict = {'metadata': PropertyList()}
844 metadataDict['metadata'].add(name="OBSTYPE", value="CTI")
845 metadataDict['metadata'].add(name="CALIBCLS",
846 value="lsst.ip.isr.deferredCharge.DeferredChargeCalib")
847 # This should always be True for the new ISR task
848 # because gains have already been applied and the
849 # mock and the correction are always in electrons.
850 # We will pass where necessary gains of 1.0.
851 metadataDict['metadata'].add("USEGAINS", value=True)
852 self.ctiCalibDict = {**metadataDict, **self.ctiCalibDict}
853 deferredChargeCalib = DeferredChargeCalib(useGains=True)
854 self.cti = deferredChargeCalib.fromDict(self.ctiCalibDict)
855
856 return self.cti
857

◆ makeImage()

lsst.ip.isr.isrMockLSST.IsrMockLSST.makeImage ( self)
Generate a simulated ISR LSST image.

Returns
-------
exposure : `lsst.afw.image.Exposure` or `dict`
    Simulated ISR image data.

Notes
-----
This method constructs a "raw" data image.

Reimplemented from lsst.ip.isr.isrMock.IsrMock.

Definition at line 451 of file isrMockLSST.py.

451 def makeImage(self):
452 """Generate a simulated ISR LSST image.
453
454 Returns
455 -------
456 exposure : `lsst.afw.image.Exposure` or `dict`
457 Simulated ISR image data.
458
459 Notes
460 -----
461 This method constructs a "raw" data image.
462 """
463 exposure = self.getExposure()
464
465 # Set up random number generators for consistency of components,
466 # no matter the group that are configured.
467 rngSky = np.random.RandomState(seed=self.config.rngSeed + 1)
468 rngDark = np.random.RandomState(seed=self.config.rngSeed + 2)
469 rng2DBias = np.random.RandomState(seed=self.config.rngSeed + 3)
470 rngOverscan = np.random.RandomState(seed=self.config.rngSeed + 4)
471 rngReadNoise = np.random.RandomState(seed=self.config.rngSeed + 5)
472 rngBrighterFatter = galsim.BaseDeviate(self.config.rngSeed + 6)
473
474 # Create the linearizer if we will need it.
475 if self.config.doAddHighSignalNonlinearity:
476 linearizer = LinearizerMockLSST().run()
477
478 # We introduce effects as they happen from a source to the signal,
479 # so the effects go from electron to adu.
480 # The ISR steps will then correct these effects in the reverse order.
481 for idx, amp in enumerate(exposure.getDetector()):
482 # Get image bbox and data
483 bbox = None
484 if self.config.isTrimmed:
485 bbox = amp.getBBox()
486 bboxFull = bbox
487 else:
488 bbox = amp.getRawDataBBox()
489 bboxFull = amp.getRawBBox()
490
491 # This is the image data (excluding pre/overscans).
492 ampImageData = exposure.image[bbox]
493 # This is the full data (including pre/overscans if untrimmed).
494 ampFullData = exposure.image[bboxFull]
495
496 # Astrophysical signals are all in electron (e-).
497 # These are only applied to the imaging portion of the
498 # amplifier (ampImageData)
499
500 if self.config.doAddSky:
501 # The sky effects are in electron.
502 self.amplifierAddNoise(
503 ampImageData,
504 self.config.skyLevel,
505 np.sqrt(self.config.skyLevel),
506 rng=rngSky,
507 )
508
509 if self.config.doAddSource:
510 for sourceAmp, sourceFlux, sourceX, sourceY in zip(self.config.sourceAmp,
511 self.config.sourceFlux,
512 self.config.sourceX,
513 self.config.sourceY):
514 if idx == sourceAmp:
515 # The source flux is in electron.
516 self.amplifierAddSource(ampImageData, sourceFlux, sourceX, sourceY)
517
518 if self.config.doAddFringe:
519 # Fringes are added in electron.
520 self.amplifierAddFringe(amp,
521 ampImageData,
522 np.array(self.config.fringeScale),
523 x0=np.array(self.config.fringeX0),
524 y0=np.array(self.config.fringeY0))
525
526 if self.config.doAddFlat:
527 if self.config.calibMode:
528 # In case we are making a combined flat,
529 # add a non-zero signal so the mock flat can be multiplied
530 self.amplifierAddNoise(ampImageData, 1.0, 0.0)
531 # Multiply each amplifier by a Gaussian centered on u0 and v0
532 u0 = exposure.getDetector().getBBox().getDimensions().getX()/2.
533 v0 = exposure.getDetector().getBBox().getDimensions().getY()/2.
534 self.amplifierMultiplyFlat(amp, ampImageData, self.config.flatDrop, u0=u0, v0=v0)
535
536 # On-chip electronic effects.
537
538 # 1. Add bright defect(s).
539 if self.config.doAddBrightDefects:
540 defectList = self.makeDefectList(isTrimmed=self.config.isTrimmed)
541
542 for defect in defectList:
543 exposure.image[defect.getBBox()] = self.config.brightDefectLevel
544
545 for idx, amp in enumerate(exposure.getDetector()):
546 # Get image bbox and data
547 bbox = None
548 if self.config.isTrimmed:
549 bbox = amp.getBBox()
550 bboxFull = bbox
551 else:
552 bbox = amp.getRawDataBBox()
553 bboxFull = amp.getRawBBox()
554
555 # This is the image data (excluding pre/overscans).
556 ampImageData = exposure.image[bbox]
557 # This is the full data (including pre/overscans if untrimmed).
558 ampFullData = exposure.image[bboxFull]
559
560 # 2. Add dark current (electron) to imaging portion of the amp.
561 if self.config.doAddDark or self.config.doAddDarkNoiseOnly:
562 if self.config.doAddDarkNoiseOnly:
563 darkLevel = 0.0
564 else:
565 darkLevel = self.config.darkRate * self.config.darkTime
566 if self.config.calibMode:
567 darkNoise = 0.0
568 else:
569 darkNoise = np.sqrt(self.config.darkRate * self.config.darkTime)
570
571 self.amplifierAddNoise(ampImageData, darkLevel, darkNoise, rng=rngDark)
572
573 # 3. Add BF effect (electron) to imaging portion of the amp.
574 if self.config.doAddBrighterFatter is True:
575 self.amplifierAddBrighterFatter(
576 ampImageData,
577 rngBrighterFatter,
578 self.config.bfStrength,
579 self.config.nRecalc,
580 )
581
582 # 4. Add serial CTI (electron) to amplifier (imaging + overscan).
583 if self.config.doAddDeferredCharge:
584 # Get the free charge area for the amplifier.
585 self.amplifierAddDeferredCharge(exposure, amp)
586
587 # 5. Add 2D bias residual (electron) to imaging portion of the amp.
588 if self.config.doAdd2DBias:
589 # For now we use an unstructured noise field to add some
590 # consistent 2D bias residual that can be subtracted. In
591 # the future this can be made into a warm corner (for example).
592 self.amplifierAddNoise(
593 ampImageData,
594 0.0,
595 self.config.noise2DBias,
596 rng=rng2DBias,
597 )
598
599 # 6. Add clock-injected offset (electron) to amplifer
600 # (imaging + overscan).
601 # This is just an offset that will be crosstalked and modified by
602 # the gain, and does not have a noise associated with it.
603 if self.config.doAddClockInjectedOffset:
604 self.amplifierAddNoise(
605 ampFullData,
606 self.config.clockInjectedOffsetLevel,
607 0.0,
608 )
609
610 # 7./8. Add serial and parallel overscan slopes (electron)
611 # (imaging + overscan)
612 if (self.config.doAddParallelOverscanRamp or self.config.doAddSerialOverscanRamp) and \
613 not self.config.isTrimmed:
614
615 if self.config.doAddParallelOverscanRamp:
616 # Apply gradient along the X axis.
617 self.amplifierAddXGradient(ampFullData, -1.0 * self.config.overscanScale,
618 1.0 * self.config.overscanScale)
619
620 if self.config.doAddSerialOverscanRamp:
621 # Apply the gradient along the Y axis.
622 self.amplifierAddYGradient(ampFullData, -1.0 * self.config.overscanScale,
623 1.0 * self.config.overscanScale)
624
625 # 9. Add non-linearity (electron) to amplifier
626 # (imaging + overscan).
627 if self.config.doAddHighSignalNonlinearity:
628 # The linearizer coefficients come from makeLinearizer().
629 if linearizer.linearityType[amp.getName()] != "Spline":
630 raise RuntimeError("IsrMockLSST only supports spline non-linearity.")
631
632 coeffs = linearizer.linearityCoeffs[amp.getName()]
633 centers, values = np.split(coeffs, 2)
634
635 # This is an application of high signal non-linearity, so we
636 # set the lower values to 0.0 (this cut is arbitrary).
637 values[centers < self.config.highSignalNonlinearityThreshold] = 0.0
638
639 # The linearizer is units of adu, so convert to electron
640 values *= self.config.gainDict[amp.getName()]
641
642 # Note that the linearity spline is in "overscan subtracted"
643 # units so needs to be applied without the clock-injected
644 # offset.
645 self.amplifierAddNonlinearity(
646 ampFullData,
647 centers,
648 values,
649 self.config.clockInjectedOffsetLevel if self.config.doAddClockInjectedOffset else 0.0,
650 )
651
652 # 10. Add read noise (electron) to the amplifier
653 # (imaging + overscan).
654 # Unsure if this should be before or after crosstalk.
655 # Probably some of both; hopefully doesn't matter.
656 if not self.config.calibMode:
657 # Add read noise to the imaging region.
658 self.amplifierAddNoise(
659 ampImageData,
660 0.0,
661 self.config.readNoise,
662 rng=rngReadNoise,
663 )
664
665 # If not trimmed, add to the overscan regions.
666 if not self.config.isTrimmed:
667 parallelOverscanBBox = amp.getRawParallelOverscanBBox()
668 parallelOverscanData = exposure.image[parallelOverscanBBox]
669
670 serialOverscanBBox = self.getFullSerialOverscanBBox(amp)
671 serialOverscanData = exposure.image[serialOverscanBBox]
672
673 # Add read noise of mean 0
674 # to the parallel and serial overscan regions.
675 self.amplifierAddNoise(
676 parallelOverscanData,
677 0.0,
678 self.config.readNoise,
679 rng=rngOverscan,
680 )
681 self.amplifierAddNoise(
682 serialOverscanData,
683 0.0,
684 self.config.readNoise,
685 rng=rngOverscan,
686 )
687
688 # 7b. Add bad column to the parallel overscan region.
689 if self.config.doAddBadParallelOverscanColumn and not self.config.isTrimmed:
690 # We want to place this right above the defect, to simulate
691 # bleeding into the parallel overscan region.
692 amp = exposure.getDetector()[2]
693 parBBox = amp.getRawParallelOverscanBBox()
694 bboxBad = geom.Box2I(
695 corner=geom.Point2I(50, parBBox.getMinY()),
696 dimensions=geom.Extent2I(1, parBBox.getHeight()),
697 )
698 exposure[bboxBad].image.array[:, :] = self.config.badParallelOverscanColumnLevel
699
700 if self.config.doAddBadParallelOverscanColumnNeighbors:
701 for neighbor in [49, 51]:
702 bboxBad = geom.Box2I(
703 corner=geom.Point2I(neighbor, parBBox.getMinY()),
704 dimensions=geom.Extent2I(1, parBBox.getHeight()),
705 )
706 exposure[bboxBad].image.array[:, :] += self.config.badParallelOverscanColumnNeighborsLevel
707
708 # 11. Add crosstalk (electron) to all the amplifiers
709 # (imaging + overscan).
710 if self.config.doAddCrosstalk:
711 ctCalib = CrosstalkCalib()
712 exposureClean = exposure.clone()
713 for idxS, ampS in enumerate(exposure.getDetector()):
714 for idxT, ampT in enumerate(exposure.getDetector()):
715 ampDataTarget = exposure.image[ampT.getBBox() if self.config.isTrimmed
716 else ampT.getRawBBox()]
717 ampDataSource = ctCalib.extractAmp(exposureClean.image, ampS, ampT,
718 isTrimmed=self.config.isTrimmed,
719 fullAmplifier=True)
720 self.amplifierAddCT(ampDataSource, ampDataTarget, self.crosstalkCoeffs[idxS][idxT])
721
722 for amp in exposure.getDetector():
723 # Get image bbox and data (again).
724 bbox = None
725 if self.config.isTrimmed:
726 bbox = amp.getBBox()
727 bboxFull = bbox
728 else:
729 bbox = amp.getRawDataBBox()
730 bboxFull = amp.getRawBBox()
731
732 # This is the image data (excluding pre/overscans).
733 ampImageData = exposure.image[bbox]
734 # This is the full data (including pre/overscans if untrimmed).
735 ampFullData = exposure.image[bboxFull]
736
737 # 12. Gain un-normalize (from electron to floating point adu)
738 if self.config.doApplyGain:
739 gain = self.config.gainDict.get(amp.getName(), self.config.gain)
740 self.applyGain(ampFullData, gain)
741
742 # 13. Add overall bias level (adu) to the amplifier
743 # (imaging + overscan)
744 if self.config.doAddBias:
745 self.addBiasLevel(ampFullData, self.config.biasLevel)
746
747 # 14. Round/Truncate to integers (adu)
748 if self.config.doRoundAdu:
749 self.roundADU(ampFullData)
750
751 # Add units metadata to calibrations.
752 if self.config.calibMode:
753 if self.config.doApplyGain:
754 exposure.metadata["LSST ISR UNITS"] = "adu"
755 else:
756 exposure.metadata["LSST ISR UNITS"] = "electron"
757
758 if self.config.doGenerateAmpDict:
759 expDict = dict()
760 for amp in exposure.getDetector():
761 expDict[amp.getName()] = exposure
762 return expDict
763 else:
764 return exposure
765

◆ makeLinearizer()

lsst.ip.isr.isrMockLSST.IsrMockLSST.makeLinearizer ( self)

Definition at line 979 of file isrMockLSST.py.

979 def makeLinearizer(self):
980 # docstring inherited.
981
982 # The linearizer has units of adu.
983 nNodes = 10
984 # Set this to just above the mock saturation (adu)
985 maxADU = 101_000
986 nonLinSplineNodes = np.linspace(0, maxADU, nNodes)
987 # These values come from cp_pipe/tests/test_linearity.py and
988 # are based on a test fit to LSSTCam data, run 7193D, detector 22,
989 # amp C00.
990 nonLinSplineValues = np.array(
991 [0.0, -8.87, 1.46, 1.69, -6.92, -68.23, -78.01, -11.56, 80.26, 185.01]
992 )
993
994 if self.config.doAddHighSignalNonlinearity and not self.config.doAddLowSignalNonlinearity:
995 nonLinSplineValues[nonLinSplineNodes < self.config.highSignalNonlinearityThreshold] = 0.0
996 elif self.config.doAddLowSignalNonlinearity:
997 raise NotImplementedError("Low signal non-linearity is not implemented.")
998
999 exp = self.getExposure()
1000 detector = exp.getDetector()
1001
1002 linearizer = Linearizer(detector=detector)
1003 linearizer.updateMetadataFromExposures([exp])
1004
1005 # We need to set override by hand because we are constructing a
1006 # linearizer manually and not from a serialized object.
1007 linearizer.override = True
1008 linearizer.hasLinearity = True
1009 linearizer.validate()
1010 linearizer.updateMetadata(camera=self.getCamera(), detector=detector, filterName='NONE')
1011 linearizer.updateMetadata(setDate=True, setCalibId=True)
1012
1013 for amp in detector:
1014 ampName = amp.getName()
1015 linearizer.linearityType[ampName] = "Spline"
1016 linearizer.linearityCoeffs[ampName] = np.concatenate([nonLinSplineNodes, nonLinSplineValues])
1017 # We need to specify the raw bbox here.
1018 linearizer.linearityBBox[ampName] = amp.getRawBBox()
1019
1020 return linearizer
1021

◆ roundADU()

lsst.ip.isr.isrMockLSST.IsrMockLSST.roundADU ( self,
ampData )
Round adu to nearest integer.

Parameters
----------
ampData : `lsst.afw.image.ImageF`
    Amplifier image to operate on.

Definition at line 1092 of file isrMockLSST.py.

1092 def roundADU(self, ampData):
1093 """Round adu to nearest integer.
1094
1095 Parameters
1096 ----------
1097 ampData : `lsst.afw.image.ImageF`
1098 Amplifier image to operate on.
1099 """
1100 ampArr = ampData.array
1101 ampArr[:] = np.around(ampArr)
1102

◆ run()

lsst.ip.isr.isrMockLSST.IsrMockLSST.run ( self)
Generate a mock ISR product following LSSTCam ISR, and return it.

Returns
-------
image : `lsst.afw.image.Exposure`
    Simulated ISR image with signals added.
dataProduct :
    Simulated ISR data products.
None :
    Returned if no valid configuration was found.

Raises
------
RuntimeError
    Raised if both doGenerateImage and doGenerateData are specified.

Reimplemented from lsst.ip.isr.isrMock.IsrMock.

Definition at line 425 of file isrMockLSST.py.

425 def run(self):
426 """Generate a mock ISR product following LSSTCam ISR, and return it.
427
428 Returns
429 -------
430 image : `lsst.afw.image.Exposure`
431 Simulated ISR image with signals added.
432 dataProduct :
433 Simulated ISR data products.
434 None :
435 Returned if no valid configuration was found.
436
437 Raises
438 ------
439 RuntimeError
440 Raised if both doGenerateImage and doGenerateData are specified.
441 """
442 if self.config.doGenerateImage and self.config.doGenerateData:
443 raise RuntimeError("Only one of doGenerateImage and doGenerateData may be specified.")
444 elif self.config.doGenerateImage:
445 return self.makeImage()
446 elif self.config.doGenerateData:
447 return self.makeData()
448 else:
449 return None
450

Member Data Documentation

◆ _DefaultName

str lsst.ip.isr.isrMockLSST.IsrMockLSST._DefaultName = "isrMockLSST"
staticprotected

Definition at line 224 of file isrMockLSST.py.

◆ bfKernel

lsst.ip.isr.isrMockLSST.IsrMockLSST.bfKernel

Definition at line 232 of file isrMockLSST.py.

◆ ConfigClass

lsst.ip.isr.isrMockLSST.IsrMockLSST.ConfigClass = IsrMockLSSTConfig
static

Definition at line 223 of file isrMockLSST.py.

◆ cti

lsst.ip.isr.isrMockLSST.IsrMockLSST.cti

Definition at line 854 of file isrMockLSST.py.

◆ ctiCalibDict

lsst.ip.isr.isrMockLSST.IsrMockLSST.ctiCalibDict

Definition at line 354 of file isrMockLSST.py.

◆ deferredChargeCalib

lsst.ip.isr.isrMockLSST.IsrMockLSST.deferredChargeCalib

Definition at line 419 of file isrMockLSST.py.

◆ splineTrapCoeffs

lsst.ip.isr.isrMockLSST.IsrMockLSST.splineTrapCoeffs

Definition at line 340 of file isrMockLSST.py.


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