23Support for displaying cameraGeom objects.
26__all__ = [
'prepareWcsData',
'plotFocalPlane',
'makeImageFromAmp',
'calcRawCcdBBox',
'makeImageFromCcd',
27 'FakeImageDataSource',
'ButlerImage',
'rawCallback',
'overlayCcdBoxes',
28 'showAmp',
'showCcd',
'getCcdInCamBBoxList',
'getCameraImageBBox',
29 'makeImageFromCamera',
'showCamera',
'makeFocalPlaneWcs',
'findAmp']
38import lsst.afw.image
as afwImage
44from ._rotateBBoxBy90
import rotateBBoxBy90
45from ._assembleImage
import assembleAmplifierImage, assembleAmplifierRawImage
46from ._cameraGeom
import FIELD_ANGLE, FOCAL_PLANE
53_LOG = logging.getLogger(__name__)
57 """Put Wcs from an Amp image into CCD coordinates
61 wcs : `lsst.afw.geom.SkyWcs`
62 The WCS object to start from.
63 amp : `lsst.afw.table.AmpInfoRecord`
66 Is the image to which the WCS refers trimmed of non-imaging pixels?
70 ampWcs : `lsst.afw.geom.SkyWcs`
74 ampBox = amp.getRawDataBBox()
76 ampBox = amp.getRawBBox()
81 trim_shift = ampBox.getMin() - amp.getBBox().getMin()
82 wcs = wcs.copyAtShiftedPixelOrigin(
lsst.geom.Extent2D(-trim_shift.getX(), -trim_shift.getY()))
84 offset = amp.getRawXYOffset()
88def plotFocalPlane(camera, fieldSizeDeg_x=0, fieldSizeDeg_y=None, dx=0.1, dy=0.1, figsize=(10., 10.),
89 useIds=
False, showFig=
True, savePath=
None):
90 """Make a plot of the focal plane along with a set points that sample
95 camera : `lsst.afw.cameraGeom.Camera`
97 fieldSizeDeg_x : `float`
98 Amount of the field to sample in x in degrees
99 fieldSizeDeg_y : `float` or `None`
100 Amount of the field to sample in y in degrees
102 Spacing of sample points in x in degrees
104 Spacing of sample points in y in degrees
105 figsize : `tuple` containing two `float`
106 Matplotlib style tuple indicating the size of the figure in inches
108 Label detectors by name, not id?
110 Display the figure on the screen?
111 savePath : `str` or `None`
112 If not `None`, save a copy of the figure to this name.
115 from matplotlib.patches
import Polygon
116 from matplotlib.collections
import PatchCollection
117 import matplotlib.pyplot
as plt
120 "Can't run plotFocalPlane: matplotlib has not been set up")
123 if fieldSizeDeg_y
is None:
124 fieldSizeDeg_y = fieldSizeDeg_x
126 field_gridx, field_gridy = numpy.meshgrid(
127 numpy.arange(0., fieldSizeDeg_x + dx, dx) - fieldSizeDeg_x/2.,
128 numpy.arange(0., fieldSizeDeg_y + dy, dy) - fieldSizeDeg_y/2.)
129 field_gridx, field_gridy = field_gridx.flatten(), field_gridy.flatten()
131 field_gridx, field_gridy = [], []
139 for x, y
in zip(field_gridx, field_gridy)]
140 posFocalPlaneList = camera.transform(posFieldAngleList, FIELD_ANGLE, FOCAL_PLANE)
141 for posFocalPlane
in posFocalPlaneList:
142 xs.append(posFocalPlane.getX())
143 ys.append(posFocalPlane.getY())
144 dets = camera.findDetectors(posFocalPlane, FOCAL_PLANE)
150 colorMap = {DetectorType.SCIENCE:
'b', DetectorType.FOCUS:
'y',
151 DetectorType.GUIDER:
'g', DetectorType.WAVEFRONT:
'r'}
155 plt.figure(figsize=figsize)
160 corners = [(c.getX(), c.getY())
for c
in det.getCorners(FOCAL_PLANE)]
161 for corner
in corners:
162 xvals.append(corner[0])
163 yvals.append(corner[1])
164 colors.append(colorMap[det.getType()])
165 patches.append(Polygon(corners, closed=
True))
166 center = det.getOrientation().getFpPosition()
167 if det.getName()
in [
'R04_SW0',
'R04_SW1',
'R40_SW0',
'R40_SW1']:
168 text_rotation =
'vertical'
170 text_rotation =
'horizontal'
171 ax.text(center.getX(), center.getY(), det.getId()
if useIds
else det.getName(),
172 horizontalalignment=
'center', rotation=text_rotation,
173 rotation_mode=
'anchor', size=6)
174 patchCollection = PatchCollection(patches, alpha=0.6, facecolor=colors)
175 ax.add_collection(patchCollection)
176 ax.scatter(xs, ys, s=10, alpha=.7, linewidths=0., c=pcolors)
177 ax.set_xlim(min(xvals) - abs(0.1*min(xvals)),
178 max(xvals) + abs(0.1*max(xvals)))
179 ax.set_ylim(min(yvals) - abs(0.1*min(yvals)),
180 max(yvals) + abs(0.1*max(yvals)))
181 ax.set_xlabel(
'Focal Plane X (mm)')
182 ax.set_ylabel(
'Focal Plane Y (mm)')
183 if savePath
is not None:
184 plt.savefig(savePath)
189def makeImageFromAmp(amp, imValue=None, imageFactory=afwImage.ImageU, markSize=10, markValue=0,
190 scaleGain=lambda gain: (gain*1000)//10):
191 """Make an image from an amp object.
193 Since images are integer images by default, the gain needs to be scaled to
194 give enough dynamic range to see variation from amp to amp.
195 The scaling algorithm is assignable.
199 amp : `lsst.afw.table.AmpInfoRecord`
200 Amp record to use for constructing the raw amp image.
201 imValue : `float` or `None`
202 Value to assign to the constructed image, or scaleGain(gain) if `None`.
203 imageFactory : callable like `lsst.afw.image.Image`
204 Type of image to construct.
206 Size of mark at read corner in pixels.
208 Value of pixels in the read corner mark.
210 The function by which to scale the gain (must take a single argument).
214 ampImage : `lsst.afw.image`
215 An untrimmed amp image, of the type produced by ``imageFactory``.
217 bbox = amp.getRawBBox()
218 dbbox = amp.getRawDataBBox()
219 img = imageFactory(bbox)
221 img.set(int(scaleGain(amp.getGain())))
226 if amp.getReadoutCorner() == afwCameraGeom.ReadoutCorner.LL:
227 markbbox.include(dbbox.getMin())
229 elif amp.getReadoutCorner() == afwCameraGeom.ReadoutCorner.LR:
231 markbbox.include(cornerPoint)
233 elif amp.getReadoutCorner() == afwCameraGeom.ReadoutCorner.UR:
235 markbbox.include(cornerPoint)
237 elif amp.getReadoutCorner() == afwCameraGeom.ReadoutCorner.UL:
239 markbbox.include(cornerPoint)
242 raise RuntimeError(
"Could not set readout corner")
243 mimg = imageFactory(img, markbbox)
249 """Calculate the raw ccd bounding box.
253 ccd : `lsst.afw.cameraGeom.Detector`
254 Detector for which to calculate the un-trimmed bounding box.
258 bbox : `lsst.geom.Box2I` or `None`
259 Bounding box of the un-trimmed Detector, or `None` if there is not enough
260 information to calculate raw BBox.
264 tbbox = amp.getRawBBox()
265 tbbox.shift(amp.getRawXYOffset())
270def makeImageFromCcd(ccd, isTrimmed=True, showAmpGain=True, imageFactory=afwImage.ImageU, rcMarkSize=10,
272 """Make an Image of a CCD.
276 ccd : `lsst.afw.cameraGeom.Detector`
277 Detector to use in making the image.
279 Assemble a trimmed Detector image.
281 Use the per-amp gain to color the pixels in the image?
282 imageFactory : callable like `lsst.afw.image.Image`
283 Image type to generate.
285 Size of the mark to make in the amp images at the read corner.
287 Bin the image by this factor in both dimensions.
291 image : `lsst.afw.image.Image`
292 Image of the Detector (type returned by ``imageFactory``).
303 amp, imageFactory=imageFactory, markSize=rcMarkSize))
306 imageFactory=imageFactory, markSize=rcMarkSize))
309 if len(ampImages) > 0:
310 ccdImage = imageFactory(bbox)
311 for ampImage, amp
in zip(ampImages, ccd):
319 "Cannot create untrimmed CCD without amps with raw information")
320 ccdImage = imageFactory(ccd.getBBox())
326 """A class to retrieve synthetic images for display by the show* methods
331 Should amps be trimmed?
335 The value of any pixels that lie outside the CCDs.
337 Color the amp segments with the gain of the amp?
339 Size of the side of the box used to mark the read corner.
341 Value to assign the read corner mark.
342 ampImValue : `float` or `None`
343 Value to assign to amps; scaleGain(gain) is used if `None`.
345 Function to scale the gain by.
347 def __init__(self, isTrimmed=True, verbose=False, background=numpy.nan,
348 showAmpGain=True, markSize=10, markValue=0,
349 ampImValue=None, scaleGain=lambda gain: (gain*1000)//10):
360 """Return a CCD image for the detector and the (possibly updated) Detector.
364 det : `lsst.afw.cameraGeom.Detector`
365 Detector to use for making the image.
366 imageFactory : callable like `lsst.afw.image.Image`
367 Image constructor for making the image.
369 Bin the image by this factor in both dimensions.
373 ccdImage : `lsst.afw.image.Image`
374 The constructed image.
377 imageFactory=imageFactory, binSize=binSize)
381 """Return an amp segment image.
385 amp : `lsst.afw.table.AmpInfoTable`
386 AmpInfoTable for this amp.
387 imageFactory : callable like `lsst.afw.image.Image`
388 Image constructor for making the image.
392 ampImage : `lsst.afw.image.Image`
393 The constructed image.
399 ampImage = ampImage.Factory(ampImage, amp.getRawDataBBox())
404 """A class to return an Image of a given Ccd using the butler.
408 butler : `lsst.daf.butler.Butler` or `None`
409 The butler to use. If `None`, an empty image is returned. Assumes that
410 the instrument was specified during butler construction or is included
411 in the ``kwargs`` parameter.
413 The type of image to read (e.g. raw, bias, flat, calexp).
415 If true, the showCamera command expects to be given trimmed images.
417 Be chatty (in particular, log any error messages from the butler)?
419 The value of any pixels that lie outside the CCDs.
421 A function called with (image, detector, butler) for every image, which
422 returns the image to be displayed (e.g. rawCallback). The image must
423 be of the correct size, allowing for the value of isTrimmed.
425 Passed to the base class constructor.
427 Passed to the butler.
431 You can define a short named function as a callback::
433 def callback(im, ccd, imageSource):
434 return cameraGeom.utils.rawCallback(im, ccd, imageSource, correctGain=True)
437 isTrimmed=True, verbose=False, background=numpy.nan,
438 callback=None, *args, **kwargs):
455 im, ccd.getOrientation().getNQuarter())
459 def getCcdImage(self, ccd, imageFactory=afwImage.ImageF, binSize=1, asMaskedImage=False):
460 """Return an image of the specified ccd, and also the (possibly updated) ccd"""
462 log = _LOG.getChild(
"ButlerImage")
470 if self.
butler is not None:
474 except FitsError
as e:
475 err = IOError(e.args[0].split(
'\n')[0])
476 except Exception
as e:
479 ccd = im.getDetector()
483 im = im.getMaskedImage()
485 im = im.getMaskedImage().getImage()
489 print(f
"Reading {ccd.getId()}: {err}")
491 log.warning(
"Reading %s: %s", ccd.getId(), err)
494 return self.
_prepareImage(ccd, imageFactory(*bbox.getDimensions()), binSize), ccd
496 if self.
type ==
"raw":
497 if hasattr(im,
'convertF'):
505 im = self.
callback(im, ccd, imageSource=self)
508 log.exception(
"callback failed.")
509 im = imageFactory(*bbox.getDimensions())
513 return self.
_prepareImage(ccd, im, binSize, allowRotate=allowRotate), ccd
517 correctGain=False, subtractBias=False, convertToFloat=False, obeyNQuarter=True):
518 """A callback function that may or may not subtract bias/correct gain/trim
523 im : `lsst.afw.image.Image` or `lsst.afw.image.MaskedImage` or `lsst.afw.image.Exposure`
524 An image of a chip, ready to be binned and maybe rotated.
525 ccd : `lsst.afw.cameraGeom.Detector` or `None`
526 The Detector; if `None` assume that im is an exposure and extract its Detector.
527 imageSource : `FakeImageDataSource` or `None`
528 Source to get ccd images. Must have a `getCcdImage()` method.
530 Correct each amplifier for its gain?
531 subtractBias : `bool`
532 Subtract the bias from each amplifier?
533 convertToFloat : `bool`
534 Convert ``im`` to floating point if possible.
535 obeyNQuarter : `bool`
536 Obey nQuarter from the Detector (default: True)
540 image : `lsst.afw.image.Image` like
541 The constructed image (type returned by ``im.Factory``).
545 If imageSource is derived from ButlerImage, imageSource.butler is available.
548 ccd = im.getDetector()
549 if hasattr(im,
"getMaskedImage"):
550 im = im.getMaskedImage()
551 if convertToFloat
and hasattr(im,
"convertF"):
554 isTrimmed = imageSource.isTrimmed
563 data = im[a.getRawDataBBox()]
568 bias = im[a.getRawHorizontalOverscanBBox()]
573 ampImages.append(data)
575 ccdImage = im.Factory(bbox)
576 for ampImage, amp
in zip(ampImages, ccd):
583 nQuarter = ccd.getOrientation().getNQuarter()
590 isTrimmed=False, ccdOrigin=(0, 0), display=
None, binSize=1):
591 """Overlay bounding boxes on an image display.
595 ccd : `lsst.afw.cameraGeom.Detector`
596 Detector to iterate for the amp bounding boxes.
597 untrimmedCcdBbox : `lsst.geom.Box2I` or `None`
598 Bounding box of the un-trimmed Detector.
600 number of 90 degree rotations to apply to the bounding boxes (used for rotated chips).
602 Is the Detector image over which the boxes are layed trimmed?
603 ccdOrigin : `tuple` of `float`
604 Detector origin relative to the parent origin if in a larger pixel grid.
605 display : `lsst.afw.display.Display`
606 Image display to display on.
608 Bin the image by this factor in both dimensions.
613 - Entire detector GREEN
614 - All data for amp GREEN
615 - HorizontalPrescan YELLOW
616 - HorizontalOverscan RED
618 - VerticalOverscan MAGENTA
619 - VerticalOverscan MAGENTA
622 raise RuntimeError(
"Please specify a display")
624 if untrimmedCcdBbox
is None:
626 untrimmedCcdBbox = ccd.getBBox()
629 for a
in ccd.getAmplifiers():
630 bbox = a.getRawBBox()
631 untrimmedCcdBbox.include(bbox)
633 with display.Buffering():
634 ccdDim = untrimmedCcdBbox.getDimensions()
638 ampbbox = amp.getBBox()
640 ampbbox = amp.getRawBBox()
644 displayUtils.drawBBox(ampbbox, origin=ccdOrigin, borderWidth=0.49,
645 display=display, bin=binSize)
648 for bbox, ctype
in ((amp.getRawHorizontalOverscanBBox(), afwDisplay.RED),
649 (amp.getRawDataBBox(), afwDisplay.BLUE),
650 (amp.getRawVerticalOverscanBBox(),
652 (amp.getRawPrescanBBox(), afwDisplay.YELLOW)):
655 displayUtils.drawBBox(bbox, origin=ccdOrigin, borderWidth=0.49, ctype=ctype,
656 display=display, bin=binSize)
658 xc, yc = ((ampbbox.getMin()[0] + ampbbox.getMax()[0])//2,
659 (ampbbox.getMin()[1] + ampbbox.getMax()[1])//2)
672 ccdHeight = ccdBbox.getHeight()
673 ccdWidth = ccdBbox.getWidth()
677 xc, yc = 0.5*ccdHeight + c*xc + s*yc, 0.5*ccdWidth + -s*xc + c*yc
682 display.dot(str(amp.getName()), xc/binSize,
683 yc/binSize, textAngle=nQuarter*90)
685 displayUtils.drawBBox(ccdBbox, origin=ccdOrigin,
686 borderWidth=0.49, ctype=afwDisplay.MAGENTA, display=display, bin=binSize)
689def showAmp(amp, imageSource=FakeImageDataSource(isTrimmed=
False), display=
None, overlay=
True,
690 imageFactory=afwImage.ImageU):
691 """Show an amp in an image display.
695 amp : `lsst.afw.tables.AmpInfoRecord`
696 Amp record to use in display.
697 imageSource : `FakeImageDataSource` or `None`
698 Source for getting the amp image. Must have a ``getAmpImage()`` method.
699 display : `lsst.afw.display.Display`
700 Image display to use.
702 Overlay bounding boxes?
703 imageFactory : callable like `lsst.afw.image.Image`
704 Type of image to display (only used if ampImage is `None`).
707 display = _getDisplayFromDisplayOrFrame(display)
709 ampImage = imageSource.getAmpImage(amp, imageFactory=imageFactory)
710 ampImSize = ampImage.getDimensions()
711 title = amp.getName()
712 display.mtv(ampImage, title=title)
714 with display.Buffering():
715 if ampImSize == amp.getRawBBox().getDimensions():
716 bboxes = [(amp.getRawBBox(), 0.49, afwDisplay.GREEN), ]
717 xy0 = bboxes[0][0].getMin()
719 (amp.getRawHorizontalOverscanBBox(), 0.49, afwDisplay.RED))
720 bboxes.append((amp.getRawDataBBox(), 0.49, afwDisplay.BLUE))
721 bboxes.append((amp.getRawPrescanBBox(),
722 0.49, afwDisplay.YELLOW))
723 bboxes.append((amp.getRawVerticalOverscanBBox(),
724 0.49, afwDisplay.MAGENTA))
726 bboxes = [(amp.getBBox(), 0.49,
None), ]
727 xy0 = bboxes[0][0].getMin()
729 for bbox, borderWidth, ctype
in bboxes:
734 displayUtils.drawBBox(
735 bbox, borderWidth=borderWidth, ctype=ctype, display=display)
738def showCcd(ccd, imageSource=FakeImageDataSource(), display=
None, overlay=
True,
739 imageFactory=afwImage.ImageF, binSize=1, inCameraCoords=
False):
740 """Show a CCD on display.
744 ccd : `lsst.afw.cameraGeom.Detector`
745 Detector to use in display.
746 imageSource : `FakeImageDataSource` or `None`
747 Source to get ccd images. Must have a ``getCcdImage()`` method.
748 display : `lsst.afw.display.Display`
749 image display to use.
751 Show amp bounding boxes on the displayed image?
752 imageFactory : callable like `lsst.afw.image.Image`
753 The image factory to use in generating the images.
755 Bin the image by this factor in both dimensions.
756 inCameraCoords : `bool`
757 Show the Detector in camera coordinates?
759 display = _getDisplayFromDisplayOrFrame(display)
763 ccdImage, ccd = imageSource.getCcdImage(
764 ccd, imageFactory=imageFactory, binSize=binSize)
766 ccdBbox = ccdImage.getBBox()
767 if ccdBbox.getDimensions() == ccd.getBBox().getDimensions():
773 nQuarter = ccd.getOrientation().getNQuarter()
775 title =
"{} [{}]".format(ccd.getName(), ccd.getId())
780 display.mtv(ccdImage, title=title)
784 ccdOrigin, display, binSize)
790 """Get the bounding boxes of a list of Detectors within a camera sized pixel grid
794 ccdList : `lsst.afw.cameraGeom.Detector`
797 Bin the image by this factor in both dimensions.
798 pixelSize_o : `float`
799 Size of the pixel in mm.
801 Origin of the camera pixel grid in pixels.
805 boxList : `list` [`lsst.geom.Box2I`]
806 A list of bounding boxes in camera pixel coordinates.
810 if not pixelSize_o == ccd.getPixelSize():
812 "Cameras with detectors with different pixel scales are not currently supported")
815 for corner
in ccd.getCorners(FOCAL_PLANE):
816 dbbox.include(corner)
818 nQuarter = ccd.getOrientation().getNQuarter()
819 cbbox = ccd.getBBox()
820 ex = cbbox.getDimensions().getX()//binSize
821 ey = cbbox.getDimensions().getY()//binSize
826 int(llc.getY()//pixelSize_o.getY()/binSize)))
828 -int(origin.getY())//binSize))
834 """Get the bounding box of a camera sized image in pixels
838 camBbox : `lsst.geom.Box2D`
839 Camera bounding box in focal plane coordinates (mm).
841 Size of a detector pixel in mm.
843 Buffer around edge of image in pixels.
847 box : `lsst.geom.Box2I`
848 The resulting bounding box.
851 int(camBbox.getMinY()//pixelSize.getY()))
853 int(camBbox.getMaxY()//pixelSize.getY()))
855 retBox.grow(bufferSize)
860 imageSource=FakeImageDataSource(), imageFactory=afwImage.ImageU, binSize=1):
861 """Make an Image of a Camera.
863 Put each detector's image in the correct location and orientation on the
864 focal plane. The input images can be binned to an integer fraction of their
869 camera : `lsst.afw.cameraGeom.Camera`
870 Camera object to use to make the image.
871 detectorNameList : `list` [`str`]
872 List of detector names from ``camera`` to use in building the image.
873 Use all Detectors if `None`.
875 Value to use where there is no Detector.
877 Size of border in binned pixels to make around the camera image.
878 imageSource : `FakeImageDataSource` or `None`
879 Source to get ccd images. Must have a ``getCcdImage()`` method.
880 imageFactory : callable like `lsst.afw.image.Image`
881 Type of image to build.
883 Bin the image by this factor in both dimensions.
887 image : `lsst.afw.image.Image`
888 Image of the entire camera.
890 log = _LOG.getChild(
"makeImageFromCamera")
892 if detectorNameList
is None:
895 ccdList = [camera[name]
for name
in detectorNameList]
897 if detectorNameList
is None:
898 camBbox = camera.getFpBBox()
901 for detName
in detectorNameList:
902 for corner
in camera[detName].getCorners(FOCAL_PLANE):
903 camBbox.include(corner)
905 pixelSize_o = camera[next(camera.getNameIter())].getPixelSize()
907 origin = camBbox.getMin()
909 camIm = imageFactory(int(math.ceil(camBbox.getDimensions().getX()/binSize)),
910 int(math.ceil(camBbox.getDimensions().getY()/binSize)))
911 camIm[:] = imageSource.background
913 assert imageSource.isTrimmed,
"isTrimmed is False isn't supported by getCcdInCamBBoxList"
916 for det, bbox
in zip(ccdList, boxList):
917 im = imageSource.getCcdImage(det, imageFactory, binSize)[0]
921 imView = camIm.Factory(camIm, bbox, afwImage.LOCAL)
924 except pexExceptions.LengthError:
925 log.exception(
"Unable to fit image for detector \"%s\" into image of camera.", det.getName())
930def showCamera(camera, imageSource=FakeImageDataSource(), imageFactory=afwImage.ImageF,
931 detectorNameList=
None, binSize=10, bufferSize=10, overlay=
True, title=
"",
932 showWcs=
None, ctype=afwDisplay.GREEN, textSize=1.25, originAtCenter=
True, display=
None,
934 """Show a Camera on display, with the specified display.
936 The rotation of the sensors is snapped to the nearest multiple of 90 deg.
937 Also note that the pixel size is constant over the image array. The lower
938 left corner (LLC) of each sensor amp is snapped to the LLC of the pixel
939 containing the LLC of the image.
943 camera : `lsst.afw.cameraGeom.Camera`
944 Camera object to use to make the image.
945 imageSource : `FakeImageDataSource` or `None`
946 Source to get ccd images. Must have a ``getCcdImage()`` method.
947 imageFactory : `lsst.afw.image.Image`
948 Type of image to make
949 detectorNameList : `list` [`str`] or `None`
950 List of detector names from `camera` to use in building the image.
951 Use all Detectors if `None`.
953 Bin the image by this factor in both dimensions.
955 Size of border in binned pixels to make around the camera image.
957 Overlay Detector IDs and boundaries?
959 Title to use in display.
961 Include a WCS in the display?
962 ctype : `lsst.afw.display.COLOR` or `str`
963 Color to use when drawing Detector boundaries.
965 Size of detector labels
966 originAtCenter : `bool`
967 Put origin of the camera WCS at the center of the image?
968 If `False`, the origin will be at the lower left.
969 display : `lsst.afw.display`
970 Image display on which to display.
972 All remaining keyword arguments are passed to makeImageFromCamera
976 image : `lsst.afw.image.Image`
979 display = _getDisplayFromDisplayOrFrame(display)
983 cameraImage =
makeImageFromCamera(camera, detectorNameList=detectorNameList, bufferSize=bufferSize,
984 imageSource=imageSource, imageFactory=imageFactory, binSize=binSize,
987 if detectorNameList
is None:
988 ccdList = [camera[name]
for name
in camera.getNameIter()]
990 ccdList = [camera[name]
for name
in detectorNameList]
992 if detectorNameList
is None:
993 camBbox = camera.getFpBBox()
996 for detName
in detectorNameList:
997 for corner
in camera[detName].getCorners(FOCAL_PLANE):
998 camBbox.include(corner)
999 pixelSize = ccdList[0].getPixelSize()
1004 cameraImage.getBBox()).getCenter()
1013 title = camera.getName()
1014 display.mtv(cameraImage, title=title, wcs=wcs)
1017 with display.Buffering():
1019 camBbox, pixelSize, bufferSize*binSize)
1021 ccdList, binSize, pixelSize, camBbox.getMin())
1022 for bbox, ccd
in zip(bboxList, ccdList):
1023 nQuarter = ccd.getOrientation().getNQuarter()
1026 displayUtils.drawBBox(
1027 bbox, borderWidth=0.5, ctype=ctype, display=display)
1028 dims = bbox.getDimensions()
1029 ccdLabel =
"{}\n[{}]".format(ccd.getName(), ccd.getId())
1030 display.dot(ccdLabel, bbox.getMinX() + dims.getX()/2, bbox.getMinY() + dims.getY()/2,
1031 ctype=ctype, size=textSize, textAngle=nQuarter*90)
1037 """Make a WCS for the focal plane geometry
1038 (i.e. one that returns positions in "mm")
1043 Size of the image pixels in physical units
1044 referencePixel : `lsst.geom.Point2D`
1045 Pixel for origin of WCS
1050 Wcs object for mapping between pixels and focal plane.
1053 if referencePixel
is None:
1056 md.set(
"CRPIX%d"%(i + 1), referencePixel[i])
1057 md.set(
"CRVAL%d"%(i + 1), 0.)
1058 md.set(
"CDELT1", pixelSize[0])
1059 md.set(
"CDELT2", pixelSize[1])
1060 md.set(
"CTYPE1",
"CAMERA_X")
1061 md.set(
"CTYPE2",
"CAMERA_Y")
1062 md.set(
"CUNIT1",
"mm")
1063 md.set(
"CUNIT2",
"mm")
1069 """Find the Amp with the specified pixel position within the composite
1073 ccd : `lsst.afw.cameraGeom.Detector`
1074 Detector to look in.
1075 pixelPosition : `lsst.geom.Point2I`
1076 The pixel position to find the amp for.
1080 `lsst.afw.table.AmpInfoCatalog`
1081 Amp record in which ``pixelPosition`` falls or `None` if no Amp found.
1084 if amp.getBBox().contains(pixelPosition):
_prepareImage(self, ccd, im, binSize, allowRotate=True)
__init__(self, butler=None, type="raw", isTrimmed=True, verbose=False, background=numpy.nan, callback=None, *args, **kwargs)
getCcdImage(self, ccd, imageFactory=afwImage.ImageF, binSize=1, asMaskedImage=False)
__init__(self, isTrimmed=True, verbose=False, background=numpy.nan, showAmpGain=True, markSize=10, markValue=0, ampImValue=None, scaleGain=lambda gain:(gain *1000)//10)
getAmpImage(self, amp, imageFactory)
getCcdImage(self, det, imageFactory, binSize)
Class for storing generic metadata.
A floating-point coordinate rectangle geometry.
An integer coordinate rectangle.
assembleAmplifierImage(destImage, rawImage, amplifier)
assembleAmplifierRawImage(destImage, rawImage, amplifier)
rotateBBoxBy90(bbox, n90, dimensions)
findAmp(ccd, pixelPosition)
overlayCcdBoxes(ccd, untrimmedCcdBbox=None, nQuarter=0, isTrimmed=False, ccdOrigin=(0, 0), display=None, binSize=1)
getCcdInCamBBoxList(ccdList, binSize, pixelSize_o, origin)
showAmp(amp, imageSource=FakeImageDataSource(isTrimmed=False), display=None, overlay=True, imageFactory=afwImage.ImageU)
showCcd(ccd, imageSource=FakeImageDataSource(), display=None, overlay=True, imageFactory=afwImage.ImageF, binSize=1, inCameraCoords=False)
makeImageFromCcd(ccd, isTrimmed=True, showAmpGain=True, imageFactory=afwImage.ImageU, rcMarkSize=10, binSize=1)
plotFocalPlane(camera, fieldSizeDeg_x=0, fieldSizeDeg_y=None, dx=0.1, dy=0.1, figsize=(10., 10.), useIds=False, showFig=True, savePath=None)
rawCallback(im, ccd=None, imageSource=None, correctGain=False, subtractBias=False, convertToFloat=False, obeyNQuarter=True)
prepareWcsData(wcs, amp, isTrimmed=True)
getCameraImageBBox(camBbox, pixelSize, bufferSize)
makeImageFromCamera(camera, detectorNameList=None, background=numpy.nan, bufferSize=10, imageSource=FakeImageDataSource(), imageFactory=afwImage.ImageU, binSize=1)
showCamera(camera, imageSource=FakeImageDataSource(), imageFactory=afwImage.ImageF, detectorNameList=None, binSize=10, bufferSize=10, overlay=True, title="", showWcs=None, ctype=afwDisplay.GREEN, textSize=1.25, originAtCenter=True, display=None, **kwargs)
makeFocalPlaneWcs(pixelSize, referencePixel)
makeImageFromAmp(amp, imValue=None, imageFactory=afwImage.ImageU, markSize=10, markValue=0, scaleGain=lambda gain:(gain *1000)//10)
std::shared_ptr< SkyWcs > makeSkyWcs(daf::base::PropertySet &metadata, bool strip=false)
Construct a SkyWcs from FITS keywords.
std::shared_ptr< SkyWcs > makeFlippedWcs(SkyWcs const &wcs, bool flipLR, bool flipTB, lsst::geom::Point2D const ¢er)
Return a copy of a FITS-WCS with pixel positions flipped around a specified center.
Statistics makeStatistics(lsst::afw::image::Image< Pixel > const &img, lsst::afw::image::Mask< image::MaskPixel > const &msk, int const flags, StatisticsControl const &sctrl=StatisticsControl())
Handle a watered-down front-end to the constructor (no variance)
std::shared_ptr< ImageT > rotateImageBy90(ImageT const &image, int nQuarter)
Rotate an image by an integral number of quarter turns.
std::shared_ptr< ImageT > binImage(ImageT const &inImage, int const binX, int const binY, lsst::afw::math::Property const flags=lsst::afw::math::MEAN)