269 self.
rng = np.random.RandomState(self.config.rngSeed)
271 [1e-2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
272 [1e-2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
273 [1e-2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
274 [1e-2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
275 [1e-2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
276 [1e-2, 0.0, 0.0, 2.2e-2, 0.0, 0.0, 0.0, 0.0],
277 [1e-2, 5e-3, 5e-4, 3e-3, 4e-2, 5e-3, 5e-3, 0.0]])
278 if getDebugFrame(self.
_display,
"mockCrosstalkCoeffs"):
279 self.
crosstalkCoeffs = np.array([[0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
280 [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
281 [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
282 [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
283 [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
284 [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
285 [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
286 [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]])
288 [4., 16., 26., 16., 4.],
289 [7., 26., 41., 26., 7.],
290 [4., 16., 26., 16., 4.],
291 [1., 4., 7., 4., 1.]]) / 273.0
391 """Generate a simulated ISR image.
395 exposure : `lsst.afw.image.Exposure` or `dict`
396 Simulated ISR image data.
400 This method currently constructs a "raw" data image by:
402 * Generating a simulated sky with noise
403 * Adding a single Gaussian "star"
404 * Adding the fringe signal
405 * Multiplying the frame by the simulated flat
406 * Adding dark current (and noise)
407 * Adding a bias offset (and noise)
408 * Adding an overscan gradient parallel to the pixel y-axis
409 * Simulating crosstalk by adding a scaled version of each
410 amplifier to each other amplifier.
412 The exposure with image data constructed this way is in one of
415 * A single image, with overscan and prescan regions retained
416 * A single image, with overscan and prescan regions trimmed
417 * A `dict`, containing the amplifer data indexed by the
420 The nonlinearity, CTE, and brighter fatter are currently not
423 Note that this method generates an image in the reverse
424 direction as the ISR processing, as the output image here has
425 had a series of instrument effects added to an idealized
430 for idx, amp
in enumerate(exposure.getDetector()):
432 if self.config.isTrimmed
is True:
435 bbox = amp.getRawDataBBox()
437 ampData = exposure.image[bbox]
439 if self.config.doAddSky
is True:
440 self.
amplifierAddNoise(ampData, self.config.skyLevel, np.sqrt(self.config.skyLevel))
442 if self.config.doAddSource
is True:
443 for sourceAmp, sourceFlux, sourceX, sourceY
in zip(self.config.sourceAmp,
444 self.config.sourceFlux,
446 self.config.sourceY):
450 if self.config.doAddFringe
is True:
452 x0=np.array(self.config.fringeX0),
453 y0=np.array(self.config.fringeY0))
455 if self.config.doAddFlat
is True:
456 if ampData.getArray().sum() == 0.0:
458 u0 = exposure.getDimensions().getX()
459 v0 = exposure.getDimensions().getY()
462 if self.config.doAddDark
is True:
464 self.config.darkRate * self.config.darkTime / self.config.gain,
465 np.sqrt(self.config.darkRate
466 * self.config.darkTime / self.config.gain))
468 if self.config.doAddCrosstalk
is True:
470 for idxS, ampS
in enumerate(exposure.getDetector()):
471 for idxT, ampT
in enumerate(exposure.getDetector()):
472 ampDataT = exposure.image[ampT.getBBox()
473 if self.config.isTrimmed
else ampT.getRawDataBBox()]
474 outAmp = ctCalib.extractAmp(exposure.getImage(), ampS, ampT,
475 isTrimmed=self.config.isTrimmed)
478 for amp
in exposure.getDetector():
480 if self.config.isTrimmed
is True:
483 bbox = amp.getRawDataBBox()
485 ampData = exposure.image[bbox]
487 if self.config.doAddBias
is True:
489 self.config.readNoise / self.config.gain)
491 if self.config.doAddOverscan
is True:
492 oscanBBox = amp.getRawHorizontalOverscanBBox()
493 oscanData = exposure.image[oscanBBox]
495 self.config.readNoise / self.config.gain)
498 1.0 * self.config.overscanScale)
500 1.0 * self.config.overscanScale)
502 if self.config.doGenerateAmpDict
is True:
504 for amp
in exposure.getDetector():
505 expDict[amp.getName()] = exposure
528 """Construct a test exposure.
530 The test exposure has a simple WCS set, as well as a list of
531 unlikely header keywords that can be removed during ISR
532 processing to exercise that code.
536 exposure : `lsst.afw.exposure.Exposure`
537 Construct exposure containing masked image of the
541 detector = camera[self.config.detectorIndex]
542 image = afwUtils.makeImageFromCcd(detector,
543 isTrimmed=self.config.isTrimmed,
547 imageFactory=afwImage.ImageF)
549 var = afwImage.ImageF(image.getDimensions())
550 mask = afwImage.Mask(image.getDimensions())
553 maskedImage = afwImage.makeMaskedImage(image, mask, var)
554 exposure = afwImage.makeExposure(maskedImage)
555 exposure.setDetector(detector)
556 exposure.setWcs(self.
getWcs())
558 visitInfo = afwImage.VisitInfo(exposureTime=self.config.expTime, darkTime=self.config.darkTime)
559 exposure.getInfo().setVisitInfo(visitInfo)
561 metadata = exposure.getMetadata()
562 metadata.add(
"SHEEP", 7.3,
"number of sheep on farm")
563 metadata.add(
"MONKEYS", 155,
"monkeys per tree")
564 metadata.add(
"VAMPIRES", 4,
"How scary are vampires.")
566 ccd = exposure.getDetector()
567 newCcd = ccd.rebuild()
570 'LL': ReadoutCorner.LL,
571 'LR': ReadoutCorner.LR,
572 'UR': ReadoutCorner.UR,
573 'UL': ReadoutCorner.UL,
576 newAmp = amp.rebuild()
577 newAmp.setLinearityCoeffs((0., 1., 0., 0.))
578 newAmp.setLinearityType(
"Polynomial")
579 newAmp.setGain(self.config.gain)
580 newAmp.setSuspectLevel(25000.0)
581 newAmp.setSaturation(32000.0)
585 imageBBox = amp.getRawDataBBox()
586 rawBbox = amp.getRawBBox()
587 parallelOscanBBox = amp.getRawParallelOverscanBBox()
588 serialOscanBBox = amp.getRawSerialOverscanBBox()
589 prescanBBox = amp.getRawPrescanBBox()
591 if self.config.isLsstLike:
593 xoffset, yoffset = amp.getRawXYOffset()
595 flipx = bool(amp.getRawFlipX())
596 flipy = bool(amp.getRawFlipY())
598 xExt = rawBbox.getDimensions().getX()
600 imageBBox.flipLR(xExt)
601 parallelOscanBBox.flipLR(xExt)
602 serialOscanBBox.flipLR(xExt)
603 prescanBBox.flipLR(xExt)
605 yExt = rawBbox.getDimensions().getY()
607 imageBBox.flipTB(yExt)
608 parallelOscanBBox.flipTB(yExt)
609 serialOscanBBox.flipTB(yExt)
610 prescanBBox.flipTB(yExt)
611 if not flipx
and not flipy:
613 elif flipx
and not flipy:
615 elif flipx
and flipy:
617 elif not flipx
and flipy:
619 rawBbox.shift(offext)
620 imageBBox.shift(offext)
621 parallelOscanBBox.shift(offext)
622 serialOscanBBox.shift(offext)
623 prescanBBox.shift(offext)
624 newAmp.setReadoutCorner(readoutMap[readoutCorner])
625 newAmp.setRawBBox(rawBbox)
626 newAmp.setRawDataBBox(imageBBox)
627 newAmp.setRawParallelOverscanBBox(parallelOscanBBox)
628 newAmp.setRawSerialOverscanBBox(serialOscanBBox)
629 newAmp.setRawPrescanBBox(prescanBBox)
630 newAmp.setRawFlipX(
False)
631 newAmp.setRawFlipY(
False)
633 newAmp.setRawXYOffset(no_offset)
635 newCcd.append(newAmp)
637 exposure.setDetector(newCcd.finish())
639 exposure.image.array[:] = np.zeros(exposure.getImage().getDimensions()).transpose()
640 exposure.mask.array[:] = np.zeros(exposure.getMask().getDimensions()).transpose()
641 exposure.variance.array[:] = np.zeros(exposure.getVariance().getDimensions()).transpose()