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:
508 for idxS, ampS
in enumerate(exposure.getDetector()):
509 for idxT, ampT
in enumerate(exposure.getDetector()):
510 ampDataT = exposure.image[ampT.getBBox()
511 if self.config.isTrimmed
else ampT.getRawDataBBox()]
512 outAmp = ctCalib.extractAmp(exposure.getImage(), ampS, ampT,
513 isTrimmed=self.config.isTrimmed)
516 for amp
in exposure.getDetector():
518 if self.config.isTrimmed
is True:
521 bbox = amp.getRawDataBBox()
523 ampData = exposure.image[bbox]
525 if self.config.doAddBias
is True:
527 self.config.readNoise / self.config.gain)
529 if self.config.doAddOverscan
is True:
530 oscanBBox = amp.getRawHorizontalOverscanBBox()
531 oscanData = exposure.image[oscanBBox]
533 self.config.readNoise / self.config.gain)
536 1.0 * self.config.overscanScale)
538 1.0 * self.config.overscanScale)
540 if self.config.doGenerateAmpDict
is True:
542 for amp
in exposure.getDetector():
543 expDict[amp.getName()] = exposure
577 """Construct a test exposure.
579 The test exposure has a simple WCS set, as well as a list of
580 unlikely header keywords that can be removed during ISR
581 processing to exercise that code.
585 isTrimmed : `bool` or `None`, optional
586 Override the configuration isTrimmed?
590 exposure : `lsst.afw.exposure.Exposure`
591 Construct exposure containing masked image of the
594 if isTrimmed
is None:
595 _isTrimmed = self.config.isTrimmed
597 _isTrimmed = isTrimmed
599 camera = self.
getCamera(isForAssembly=self.config.isLsstLike)
600 detector = camera[self.config.detectorIndex]
601 image = afwUtils.makeImageFromCcd(
603 isTrimmed=_isTrimmed,
607 imageFactory=afwImage.ImageF,
610 var = afwImage.ImageF(image.getDimensions())
616 exposure.setDetector(detector)
617 exposure.setWcs(self.
getWcs())
619 visitInfo =
afwImage.VisitInfo(exposureTime=self.config.expTime, darkTime=self.config.darkTime)
620 exposure.getInfo().setVisitInfo(visitInfo)
622 exposure.getInfo().setId(12345)
624 metadata = exposure.getMetadata()
625 metadata.add(
"SHEEP", 7.3,
"number of sheep on farm")
626 metadata.add(
"MONKEYS", 155,
"monkeys per tree")
627 metadata.add(
"VAMPIRES", 4,
"How scary are vampires.")
629 ccd = exposure.getDetector()
630 newCcd = ccd.rebuild()
633 'LL': ReadoutCorner.LL,
634 'LR': ReadoutCorner.LR,
635 'UR': ReadoutCorner.UR,
636 'UL': ReadoutCorner.UL,
639 newAmp = amp.rebuild()
640 newAmp.setLinearityCoeffs((0., 1., 0., 0.))
641 newAmp.setLinearityType(
"Polynomial")
642 newAmp.setGain(self.config.gain)
643 newAmp.setSuspectLevel(25000.0)
644 newAmp.setSaturation(32000.0)
645 readoutCorner = amp.getReadoutCorner().name
648 imageBBox = amp.getRawDataBBox()
649 rawBbox = amp.getRawBBox()
650 parallelOscanBBox = amp.getRawParallelOverscanBBox()
651 serialOscanBBox = amp.getRawSerialOverscanBBox()
652 prescanBBox = amp.getRawPrescanBBox()
654 if self.config.isLsstLike:
656 xoffset, yoffset = amp.getRawXYOffset()
658 flipx = bool(amp.getRawFlipX())
659 flipy = bool(amp.getRawFlipY())
661 xExt = rawBbox.getDimensions().getX()
663 imageBBox.flipLR(xExt)
664 parallelOscanBBox.flipLR(xExt)
665 serialOscanBBox.flipLR(xExt)
666 prescanBBox.flipLR(xExt)
668 yExt = rawBbox.getDimensions().getY()
670 imageBBox.flipTB(yExt)
671 parallelOscanBBox.flipTB(yExt)
672 serialOscanBBox.flipTB(yExt)
673 prescanBBox.flipTB(yExt)
674 if not flipx
and not flipy:
676 elif flipx
and not flipy:
678 elif flipx
and flipy:
680 elif not flipx
and flipy:
682 rawBbox.shift(offext)
683 imageBBox.shift(offext)
684 parallelOscanBBox.shift(offext)
685 serialOscanBBox.shift(offext)
686 prescanBBox.shift(offext)
687 newAmp.setReadoutCorner(readoutMap[readoutCorner])
688 newAmp.setRawBBox(rawBbox)
689 newAmp.setRawDataBBox(imageBBox)
690 newAmp.setRawParallelOverscanBBox(parallelOscanBBox)
691 newAmp.setRawSerialOverscanBBox(serialOscanBBox)
692 newAmp.setRawPrescanBBox(prescanBBox)
693 newAmp.setRawFlipX(
False)
694 newAmp.setRawFlipY(
False)
696 newAmp.setRawXYOffset(no_offset)
698 newCcd.append(newAmp)
700 exposure.setDetector(newCcd.finish())
702 exposure.image.array[:] = np.zeros(exposure.getImage().getDimensions()).transpose()
703 exposure.mask.array[:] = np.zeros(exposure.getMask().getDimensions()).transpose()
704 exposure.variance.array[:] = np.zeros(exposure.getVariance().getDimensions()).transpose()