283 self.
rng = np.random.RandomState(self.config.rngSeed)
287 [1e-2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
288 [1e-2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
289 [1e-2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
290 [1e-2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
291 [1e-2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
292 [1e-2, 0.0, 0.0, 2.2e-2, 0.0, 0.0, 0.0, 0.0],
293 [1e-2, 5e-3, 5e-4, 3e-3, 4e-2, 5e-3, 5e-3, 0.0]])
294 if getDebugFrame(self.
_display,
"mockCrosstalkCoeffs"):
295 self.
crosstalkCoeffs = np.array([[0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
296 [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
297 [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
298 [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
299 [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
300 [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
301 [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
302 [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]])
305 [4., 16., 26., 16., 4.],
306 [7., 26., 41., 26., 7.],
307 [4., 16., 26., 16., 4.],
308 [1., 4., 7., 4., 1.]]) / 273.0
429 """Generate a simulated ISR image.
433 exposure : `lsst.afw.image.Exposure` or `dict`
434 Simulated ISR image data.
438 This method currently constructs a "raw" data image by:
440 * Generating a simulated sky with noise
441 * Adding a single Gaussian "star"
442 * Adding the fringe signal
443 * Multiplying the frame by the simulated flat
444 * Adding dark current (and noise)
445 * Adding a bias offset (and noise)
446 * Adding an overscan gradient parallel to the pixel y-axis
447 * Simulating crosstalk by adding a scaled version of each
448 amplifier to each other amplifier.
450 The exposure with image data constructed this way is in one of
453 * A single image, with overscan and prescan regions retained
454 * A single image, with overscan and prescan regions trimmed
455 * A `dict`, containing the amplifer data indexed by the
458 The nonlinearity, CTE, and brighter fatter are currently not
461 Note that this method generates an image in the reverse
462 direction as the ISR processing, as the output image here has
463 had a series of instrument effects added to an idealized
468 for idx, amp
in enumerate(exposure.getDetector()):
470 if self.config.isTrimmed
is True:
473 bbox = amp.getRawDataBBox()
475 ampData = exposure.image[bbox]
477 if self.config.doAddSky
is True:
478 self.
amplifierAddNoise(ampData, self.config.skyLevel, np.sqrt(self.config.skyLevel))
480 if self.config.doAddSource
is True:
481 for sourceAmp, sourceFlux, sourceX, sourceY
in zip(self.config.sourceAmp,
482 self.config.sourceFlux,
484 self.config.sourceY):
488 if self.config.doAddFringe
is True:
490 x0=np.array(self.config.fringeX0),
491 y0=np.array(self.config.fringeY0))
493 if self.config.doAddFlat
is True:
494 if ampData.getArray().sum() == 0.0:
496 u0 = exposure.getDimensions().getX()
497 v0 = exposure.getDimensions().getY()
500 if self.config.doAddDark
is True:
502 self.config.darkRate * self.config.darkTime / self.config.gain,
503 np.sqrt(self.config.darkRate
504 * self.config.darkTime / self.config.gain))
506 if self.config.doAddCrosstalk
is True:
513 ctCalib.subtractCrosstalk(
516 doSubtrahendMasking=
True,
517 minPixelToMask=1e100,
522 for amp
in exposure.getDetector():
524 if self.config.isTrimmed
is True:
527 bbox = amp.getRawDataBBox()
529 ampData = exposure.image[bbox]
531 if self.config.doAddBias
is True:
533 self.config.readNoise / self.config.gain)
535 if self.config.doAddOverscan
is True:
536 oscanBBox = amp.getRawHorizontalOverscanBBox()
537 oscanData = exposure.image[oscanBBox]
539 self.config.readNoise / self.config.gain)
542 1.0 * self.config.overscanScale)
544 1.0 * self.config.overscanScale)
546 if self.config.doGenerateAmpDict
is True:
548 for amp
in exposure.getDetector():
549 expDict[amp.getName()] = exposure
583 """Construct a test exposure.
585 The test exposure has a simple WCS set, as well as a list of
586 unlikely header keywords that can be removed during ISR
587 processing to exercise that code.
591 isTrimmed : `bool` or `None`, optional
592 Override the configuration isTrimmed?
596 exposure : `lsst.afw.exposure.Exposure`
597 Construct exposure containing masked image of the
600 if isTrimmed
is None:
601 _isTrimmed = self.config.isTrimmed
603 _isTrimmed = isTrimmed
605 camera = self.
getCamera(isForAssembly=self.config.isLsstLike)
606 detector = camera[self.config.detectorIndex]
607 image = afwUtils.makeImageFromCcd(
609 isTrimmed=_isTrimmed,
613 imageFactory=afwImage.ImageF,
616 var = afwImage.ImageF(image.getDimensions())
622 exposure.setDetector(detector)
623 exposure.setWcs(self.
getWcs())
625 visitInfo =
afwImage.VisitInfo(exposureTime=self.config.expTime, darkTime=self.config.darkTime)
626 exposure.getInfo().setVisitInfo(visitInfo)
628 exposure.getInfo().setId(12345)
630 metadata = exposure.getMetadata()
631 metadata.add(
"SHEEP", 7.3,
"number of sheep on farm")
632 metadata.add(
"MONKEYS", 155,
"monkeys per tree")
633 metadata.add(
"VAMPIRES", 4,
"How scary are vampires.")
635 ccd = exposure.getDetector()
636 newCcd = ccd.rebuild()
639 'LL': ReadoutCorner.LL,
640 'LR': ReadoutCorner.LR,
641 'UR': ReadoutCorner.UR,
642 'UL': ReadoutCorner.UL,
645 newAmp = amp.rebuild()
646 newAmp.setLinearityCoeffs((0., 1., 0., 0.))
647 newAmp.setLinearityType(
"Polynomial")
648 newAmp.setGain(self.config.gain)
649 newAmp.setSuspectLevel(25000.0)
650 newAmp.setSaturation(32000.0)
651 readoutCorner = amp.getReadoutCorner().name
654 imageBBox = amp.getRawDataBBox()
655 rawBbox = amp.getRawBBox()
656 parallelOscanBBox = amp.getRawParallelOverscanBBox()
657 serialOscanBBox = amp.getRawSerialOverscanBBox()
658 prescanBBox = amp.getRawPrescanBBox()
660 if self.config.isLsstLike:
662 xoffset, yoffset = amp.getRawXYOffset()
664 flipx = bool(amp.getRawFlipX())
665 flipy = bool(amp.getRawFlipY())
667 xExt = rawBbox.getDimensions().getX()
669 imageBBox.flipLR(xExt)
670 parallelOscanBBox.flipLR(xExt)
671 serialOscanBBox.flipLR(xExt)
672 prescanBBox.flipLR(xExt)
674 yExt = rawBbox.getDimensions().getY()
676 imageBBox.flipTB(yExt)
677 parallelOscanBBox.flipTB(yExt)
678 serialOscanBBox.flipTB(yExt)
679 prescanBBox.flipTB(yExt)
680 if not flipx
and not flipy:
682 elif flipx
and not flipy:
684 elif flipx
and flipy:
686 elif not flipx
and flipy:
688 rawBbox.shift(offext)
689 imageBBox.shift(offext)
690 parallelOscanBBox.shift(offext)
691 serialOscanBBox.shift(offext)
692 prescanBBox.shift(offext)
693 newAmp.setReadoutCorner(readoutMap[readoutCorner])
694 newAmp.setRawBBox(rawBbox)
695 newAmp.setRawDataBBox(imageBBox)
696 newAmp.setRawParallelOverscanBBox(parallelOscanBBox)
697 newAmp.setRawSerialOverscanBBox(serialOscanBBox)
698 newAmp.setRawPrescanBBox(prescanBBox)
699 newAmp.setRawFlipX(
False)
700 newAmp.setRawFlipY(
False)
702 newAmp.setRawXYOffset(no_offset)
704 newCcd.append(newAmp)
706 exposure.setDetector(newCcd.finish())
708 exposure.image.array[:] = np.zeros(exposure.getImage().getDimensions()).transpose()
709 exposure.mask.array[:] = np.zeros(exposure.getMask().getDimensions()).transpose()
710 exposure.variance.array[:] = np.zeros(exposure.getVariance().getDimensions()).transpose()