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']
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,
True))
166 center = det.getOrientation().getFpPosition()
167 ax.text(center.getX(), center.getY(), det.getId()
if useIds
else det.getName(),
168 horizontalalignment=
'center', size=6)
170 patchCollection = PatchCollection(patches, alpha=0.6, facecolor=colors)
171 ax.add_collection(patchCollection)
172 ax.scatter(xs, ys, s=10, alpha=.7, linewidths=0., c=pcolors)
173 ax.set_xlim(
min(xvals) - abs(0.1*
min(xvals)),
174 max(xvals) + abs(0.1*
max(xvals)))
175 ax.set_ylim(
min(yvals) - abs(0.1*
min(yvals)),
176 max(yvals) + abs(0.1*
max(yvals)))
177 ax.set_xlabel(
'Focal Plane X (mm)')
178 ax.set_ylabel(
'Focal Plane Y (mm)')
179 if savePath
is not None:
180 plt.savefig(savePath)
185def makeImageFromAmp(amp, imValue=None, imageFactory=afwImage.ImageU, markSize=10, markValue=0,
186 scaleGain=lambda gain: (gain*1000)//10):
187 """Make an image from an amp object.
189 Since images are integer images by default, the gain needs to be scaled to
190 give enough dynamic range to see variation from amp to amp.
191 The scaling algorithm is assignable.
195 amp : `lsst.afw.table.AmpInfoRecord`
196 Amp record to use for constructing the raw amp image.
197 imValue : `float` or `None`
198 Value to assign to the constructed image, or scaleGain(gain) if `None`.
199 imageFactory : callable like `lsst.afw.image.Image`
200 Type of image to construct.
202 Size of mark at read corner in pixels.
204 Value of pixels in the read corner mark.
206 The function by which to scale the gain (must take a single argument).
210 ampImage : `lsst.afw.image`
211 An untrimmed amp image, of the type produced by ``imageFactory``.
213 bbox = amp.getRawBBox()
214 dbbox = amp.getRawDataBBox()
215 img = imageFactory(bbox)
217 img.set(int(scaleGain(amp.getGain())))
222 if amp.getReadoutCorner() == afwCameraGeom.ReadoutCorner.LL:
223 markbbox.include(dbbox.getMin())
225 elif amp.getReadoutCorner() == afwCameraGeom.ReadoutCorner.LR:
227 markbbox.include(cornerPoint)
229 elif amp.getReadoutCorner() == afwCameraGeom.ReadoutCorner.UR:
231 markbbox.include(cornerPoint)
233 elif amp.getReadoutCorner() == afwCameraGeom.ReadoutCorner.UL:
235 markbbox.include(cornerPoint)
238 raise RuntimeError(
"Could not set readout corner")
239 mimg = imageFactory(img, markbbox)
245 """Calculate the raw ccd bounding box.
249 ccd : `lsst.afw.cameraGeom.Detector`
250 Detector for which to calculate the un-trimmed bounding box.
254 bbox : `lsst.geom.Box2I` or `None`
255 Bounding box of the un-trimmed Detector, or `None` if there is not enough
256 information to calculate raw BBox.
260 tbbox = amp.getRawBBox()
261 tbbox.shift(amp.getRawXYOffset())
266def makeImageFromCcd(ccd, isTrimmed=True, showAmpGain=True, imageFactory=afwImage.ImageU, rcMarkSize=10,
268 """Make an Image of a CCD.
272 ccd : `lsst.afw.cameraGeom.Detector`
273 Detector to use in making the image.
275 Assemble a trimmed Detector image.
277 Use the per-amp gain to color the pixels in the image?
278 imageFactory : callable like `lsst.afw.image.Image`
279 Image type to generate.
281 Size of the mark to make in the amp images at the read corner.
283 Bin the image by this factor in both dimensions.
287 image : `lsst.afw.image.Image`
288 Image of the Detector (type returned by ``imageFactory``).
299 amp, imageFactory=imageFactory, markSize=rcMarkSize))
302 imageFactory=imageFactory, markSize=rcMarkSize))
305 if len(ampImages) > 0:
306 ccdImage = imageFactory(bbox)
307 for ampImage, amp
in zip(ampImages, ccd):
309 assembleAmplifierImage(ccdImage, ampImage, amp)
311 assembleAmplifierRawImage(ccdImage, ampImage, amp)
315 "Cannot create untrimmed CCD without amps with raw information")
316 ccdImage = imageFactory(ccd.getBBox())
322 """A class to retrieve synthetic images for display by the show* methods
327 Should amps be trimmed?
331 The value of any pixels that lie outside the CCDs.
333 Color the amp segments with the gain of the amp?
335 Size of the side of the box used to mark the read corner.
337 Value to assign the read corner mark.
338 ampImValue : `float` or `None`
339 Value to assign to amps; scaleGain(gain) is used if `None`.
341 Function to scale the gain by.
343 def __init__(self, isTrimmed=True, verbose=False, background=numpy.nan,
344 showAmpGain=True, markSize=10, markValue=0,
345 ampImValue=None, scaleGain=lambda gain: (gain*1000)//10):
356 """Return a CCD image for the detector and the (possibly updated) Detector.
360 det : `lsst.afw.cameraGeom.Detector`
361 Detector to use for making the image.
362 imageFactory : callable like `lsst.afw.image.Image`
363 Image constructor for making the image.
365 Bin the image by this factor in both dimensions.
369 ccdImage : `lsst.afw.image.Image`
370 The constructed image.
373 imageFactory=imageFactory, binSize=binSize)
377 """Return an amp segment image.
381 amp : `lsst.afw.table.AmpInfoTable`
382 AmpInfoTable for this amp.
383 imageFactory : callable like `lsst.afw.image.Image`
384 Image constructor for making the image.
388 ampImage : `lsst.afw.image.Image`
389 The constructed image.
395 ampImage = ampImage.Factory(ampImage, amp.getRawDataBBox())
400 """A class to return an Image of a given Ccd using the butler.
404 butler : `lsst.daf.butler.Butler` or `None`
405 The butler to use. If `None`, an empty image is returned. Assumes that
406 the instrument was specified during butler construction or is included
407 in the ``kwargs`` parameter.
409 The type of image to read (e.g. raw, bias, flat, calexp).
411 If true, the showCamera command expects to be given trimmed images.
413 Be chatty (in particular, log any error messages from the butler)?
415 The value of any pixels that lie outside the CCDs.
417 A function called with (image, detector, butler) for every image, which
418 returns the image to be displayed (e.g. rawCallback). The image must
419 be of the correct size, allowing for the value of isTrimmed.
421 Passed to the base class constructor.
423 Passed to the butler.
427 You can define a short named function as a callback::
429 def callback(im, ccd, imageSource):
430 return cameraGeom.utils.rawCallback(im, ccd, imageSource, correctGain=True)
433 isTrimmed=True, verbose=False, background=numpy.nan,
434 callback=None, *args, **kwargs):
451 im, ccd.getOrientation().getNQuarter())
455 def getCcdImage(self, ccd, imageFactory=afwImage.ImageF, binSize=1, asMaskedImage=False):
456 """Return an image of the specified ccd, and also the (possibly updated) ccd"""
458 log = _LOG.getChild(
"ButlerImage")
466 if self.
butler is not None:
470 except FitsError
as e:
471 err = IOError(e.args[0].split(
'\n')[0])
472 except Exception
as e:
475 ccd = im.getDetector()
479 im = im.getMaskedImage()
481 im = im.getMaskedImage().getImage()
485 print(f
"Reading {ccd.getId()}: {err}")
487 log.warning(
"Reading %s: %s", ccd.getId(), err)
490 return self.
_prepareImage(ccd, imageFactory(*bbox.getDimensions()), binSize), ccd
492 if self.
type ==
"raw":
493 if hasattr(im,
'convertF'):
501 im = self.
callback(im, ccd, imageSource=self)
504 log.exception(
"callback failed.")
505 im = imageFactory(*bbox.getDimensions())
509 return self.
_prepareImage(ccd, im, binSize, allowRotate=allowRotate), ccd
513 correctGain=False, subtractBias=False, convertToFloat=False, obeyNQuarter=True):
514 """A callback function that may or may not subtract bias/correct gain/trim
519 im : `lsst.afw.image.Image` or `lsst.afw.image.MaskedImage` or `lsst.afw.image.Exposure`
520 An image of a chip, ready to be binned and maybe rotated.
521 ccd : `lsst.afw.cameraGeom.Detector` or `None`
522 The Detector; if `None` assume that im is an exposure and extract its Detector.
523 imageSource : `FakeImageDataSource` or `None`
524 Source to get ccd images. Must have a `getCcdImage()` method.
526 Correct each amplifier for its gain?
527 subtractBias : `bool`
528 Subtract the bias from each amplifier?
529 convertToFloat : `bool`
530 Convert ``im`` to floating point if possible.
531 obeyNQuarter : `bool`
532 Obey nQuarter from the Detector (default: True)
536 image : `lsst.afw.image.Image` like
537 The constructed image (type returned by ``im.Factory``).
541 If imageSource is derived from ButlerImage, imageSource.butler is available.
544 ccd = im.getDetector()
545 if hasattr(im,
"getMaskedImage"):
546 im = im.getMaskedImage()
547 if convertToFloat
and hasattr(im,
"convertF"):
550 isTrimmed = imageSource.isTrimmed
559 data = im[a.getRawDataBBox()]
564 bias = im[a.getRawHorizontalOverscanBBox()]
569 ampImages.append(data)
571 ccdImage = im.Factory(bbox)
572 for ampImage, amp
in zip(ampImages, ccd):
574 assembleAmplifierImage(ccdImage, ampImage, amp)
576 assembleAmplifierRawImage(ccdImage, ampImage, amp)
579 nQuarter = ccd.getOrientation().getNQuarter()
586 isTrimmed=False, ccdOrigin=(0, 0), display=
None, binSize=1):
587 """Overlay bounding boxes on an image display.
591 ccd : `lsst.afw.cameraGeom.Detector`
592 Detector to iterate for the amp bounding boxes.
593 untrimmedCcdBbox : `lsst.geom.Box2I` or `None`
594 Bounding box of the un-trimmed Detector.
596 number of 90 degree rotations to apply to the bounding boxes (used for rotated chips).
598 Is the Detector image over which the boxes are layed trimmed?
599 ccdOrigin : `tuple` of `float`
600 Detector origin relative to the parent origin if in a larger pixel grid.
601 display : `lsst.afw.display.Display`
602 Image display to display on.
604 Bin the image by this factor in both dimensions.
609 - Entire detector GREEN
610 - All data for amp GREEN
611 - HorizontalPrescan YELLOW
612 - HorizontalOverscan RED
614 - VerticalOverscan MAGENTA
615 - VerticalOverscan MAGENTA
618 raise RuntimeError(
"Please specify a display")
620 if untrimmedCcdBbox
is None:
622 untrimmedCcdBbox = ccd.getBBox()
625 for a
in ccd.getAmplifiers():
626 bbox = a.getRawBBox()
627 untrimmedCcdBbox.include(bbox)
629 with display.Buffering():
630 ccdDim = untrimmedCcdBbox.getDimensions()
631 ccdBbox = rotateBBoxBy90(untrimmedCcdBbox, nQuarter, ccdDim)
634 ampbbox = amp.getBBox()
636 ampbbox = amp.getRawBBox()
638 ampbbox = rotateBBoxBy90(ampbbox, nQuarter, ccdDim)
640 displayUtils.drawBBox(ampbbox, origin=ccdOrigin, borderWidth=0.49,
641 display=display, bin=binSize)
644 for bbox, ctype
in ((amp.getRawHorizontalOverscanBBox(), afwDisplay.RED),
645 (amp.getRawDataBBox(), afwDisplay.BLUE),
646 (amp.getRawVerticalOverscanBBox(),
648 (amp.getRawPrescanBBox(), afwDisplay.YELLOW)):
650 bbox = rotateBBoxBy90(bbox, nQuarter, ccdDim)
651 displayUtils.drawBBox(bbox, origin=ccdOrigin, borderWidth=0.49, ctype=ctype,
652 display=display, bin=binSize)
654 xc, yc = ((ampbbox.getMin()[0] + ampbbox.getMax()[0])//2,
655 (ampbbox.getMin()[1] + ampbbox.getMax()[1])//2)
668 ccdHeight = ccdBbox.getHeight()
669 ccdWidth = ccdBbox.getWidth()
673 xc, yc = 0.5*ccdHeight + c*xc + s*yc, 0.5*ccdWidth + -s*xc + c*yc
678 display.dot(str(amp.getName()), xc/binSize,
679 yc/binSize, textAngle=nQuarter*90)
681 displayUtils.drawBBox(ccdBbox, origin=ccdOrigin,
682 borderWidth=0.49, ctype=afwDisplay.MAGENTA, display=display, bin=binSize)
685def showAmp(amp, imageSource=FakeImageDataSource(isTrimmed=
False), display=
None, overlay=
True,
686 imageFactory=afwImage.ImageU):
687 """Show an amp in an image display.
691 amp : `lsst.afw.tables.AmpInfoRecord`
692 Amp record to use in display.
693 imageSource : `FakeImageDataSource` or `None`
694 Source for getting the amp image. Must have a ``getAmpImage()`` method.
695 display : `lsst.afw.display.Display`
696 Image display to use.
698 Overlay bounding boxes?
699 imageFactory : callable like `lsst.afw.image.Image`
700 Type of image to display (only used if ampImage is `None`).
703 display = _getDisplayFromDisplayOrFrame(display)
705 ampImage = imageSource.getAmpImage(amp, imageFactory=imageFactory)
706 ampImSize = ampImage.getDimensions()
707 title = amp.getName()
708 display.mtv(ampImage, title=title)
710 with display.Buffering():
711 if ampImSize == amp.getRawBBox().getDimensions():
712 bboxes = [(amp.getRawBBox(), 0.49, afwDisplay.GREEN), ]
713 xy0 = bboxes[0][0].getMin()
715 (amp.getRawHorizontalOverscanBBox(), 0.49, afwDisplay.RED))
716 bboxes.append((amp.getRawDataBBox(), 0.49, afwDisplay.BLUE))
717 bboxes.append((amp.getRawPrescanBBox(),
718 0.49, afwDisplay.YELLOW))
719 bboxes.append((amp.getRawVerticalOverscanBBox(),
720 0.49, afwDisplay.MAGENTA))
722 bboxes = [(amp.getBBox(), 0.49,
None), ]
723 xy0 = bboxes[0][0].getMin()
725 for bbox, borderWidth, ctype
in bboxes:
730 displayUtils.drawBBox(
731 bbox, borderWidth=borderWidth, ctype=ctype, display=display)
734def showCcd(ccd, imageSource=FakeImageDataSource(), display=
None, overlay=
True,
735 imageFactory=afwImage.ImageF, binSize=1, inCameraCoords=
False):
736 """Show a CCD on display.
740 ccd : `lsst.afw.cameraGeom.Detector`
741 Detector to use in display.
742 imageSource : `FakeImageDataSource` or `None`
743 Source to get ccd images. Must have a ``getCcdImage()`` method.
744 display : `lsst.afw.display.Display`
745 image display to use.
747 Show amp bounding boxes on the displayed image?
748 imageFactory : callable like `lsst.afw.image.Image`
749 The image factory to use in generating the images.
751 Bin the image by this factor in both dimensions.
752 inCameraCoords : `bool`
753 Show the Detector in camera coordinates?
755 display = _getDisplayFromDisplayOrFrame(display)
759 ccdImage, ccd = imageSource.getCcdImage(
760 ccd, imageFactory=imageFactory, binSize=binSize)
762 ccdBbox = ccdImage.getBBox()
763 if ccdBbox.getDimensions() == ccd.getBBox().getDimensions():
769 nQuarter = ccd.getOrientation().getNQuarter()
771 title =
"{} [{}]".format(ccd.getName(), ccd.getId())
776 display.mtv(ccdImage, title=title)
780 ccdOrigin, display, binSize)
786 """Get the bounding boxes of a list of Detectors within a camera sized pixel grid
790 ccdList : `lsst.afw.cameraGeom.Detector`
793 Bin the image by this factor in both dimensions.
794 pixelSize_o : `float`
795 Size of the pixel in mm.
797 Origin of the camera pixel grid in pixels.
801 boxList : `list` [`lsst.geom.Box2I`]
802 A list of bounding boxes in camera pixel coordinates.
806 if not pixelSize_o == ccd.getPixelSize():
808 "Cameras with detectors with different pixel scales are not currently supported")
811 for corner
in ccd.getCorners(FOCAL_PLANE):
812 dbbox.include(corner)
814 nQuarter = ccd.getOrientation().getNQuarter()
815 cbbox = ccd.getBBox()
816 ex = cbbox.getDimensions().getX()//binSize
817 ey = cbbox.getDimensions().getY()//binSize
820 bbox = rotateBBoxBy90(bbox, nQuarter, bbox.getDimensions())
822 int(llc.getY()//pixelSize_o.getY()/binSize)))
824 -int(origin.getY())//binSize))
830 """Get the bounding box of a camera sized image in pixels
834 camBbox : `lsst.geom.Box2D`
835 Camera bounding box in focal plane coordinates (mm).
837 Size of a detector pixel in mm.
839 Buffer around edge of image in pixels.
843 box : `lsst.geom.Box2I`
844 The resulting bounding box.
847 int(camBbox.getMinY()//pixelSize.getY()))
849 int(camBbox.getMaxY()//pixelSize.getY()))
851 retBox.grow(bufferSize)
856 imageSource=FakeImageDataSource(), imageFactory=afwImage.ImageU, binSize=1):
857 """Make an Image of a Camera.
859 Put each detector's image in the correct location and orientation on the
860 focal plane. The input images can be binned to an integer fraction of their
865 camera : `lsst.afw.cameraGeom.Camera`
866 Camera object to use to make the image.
867 detectorNameList : `list` [`str`]
868 List of detector names from ``camera`` to use in building the image.
869 Use all Detectors if `None`.
871 Value to use where there is no Detector.
873 Size of border in binned pixels to make around the camera image.
874 imageSource : `FakeImageDataSource` or `None`
875 Source to get ccd images. Must have a ``getCcdImage()`` method.
876 imageFactory : callable like `lsst.afw.image.Image`
877 Type of image to build.
879 Bin the image by this factor in both dimensions.
883 image : `lsst.afw.image.Image`
884 Image of the entire camera.
886 log = _LOG.getChild(
"makeImageFromCamera")
888 if detectorNameList
is None:
891 ccdList = [camera[name]
for name
in detectorNameList]
893 if detectorNameList
is None:
894 camBbox = camera.getFpBBox()
897 for detName
in detectorNameList:
898 for corner
in camera[detName].getCorners(FOCAL_PLANE):
899 camBbox.include(corner)
901 pixelSize_o = camera[next(camera.getNameIter())].getPixelSize()
903 origin = camBbox.getMin()
905 camIm = imageFactory(int(math.ceil(camBbox.getDimensions().getX()/binSize)),
906 int(math.ceil(camBbox.getDimensions().getY()/binSize)))
907 camIm[:] = imageSource.background
909 assert imageSource.isTrimmed,
"isTrimmed is False isn't supported by getCcdInCamBBoxList"
912 for det, bbox
in zip(ccdList, boxList):
913 im = imageSource.getCcdImage(det, imageFactory, binSize)[0]
917 imView = camIm.Factory(camIm, bbox, afwImage.LOCAL)
921 log.exception(
"Unable to fit image for detector \"%s\" into image of camera.", det.getName())
926def showCamera(camera, imageSource=FakeImageDataSource(), imageFactory=afwImage.ImageF,
927 detectorNameList=
None, binSize=10, bufferSize=10, overlay=
True, title=
"",
928 showWcs=
None, ctype=afwDisplay.GREEN, textSize=1.25, originAtCenter=
True, display=
None,
930 """Show a Camera on display, with the specified display.
932 The rotation of the sensors is snapped to the nearest multiple of 90 deg.
933 Also note that the pixel size is constant over the image array. The lower
934 left corner (LLC) of each sensor amp is snapped to the LLC of the pixel
935 containing the LLC of the image.
939 camera : `lsst.afw.cameraGeom.Camera`
940 Camera object to use to make the image.
941 imageSource : `FakeImageDataSource` or `None`
942 Source to get ccd images. Must have a ``getCcdImage()`` method.
943 imageFactory : `lsst.afw.image.Image`
944 Type of image to make
945 detectorNameList : `list` [`str`] or `None`
946 List of detector names from `camera` to use in building the image.
947 Use all Detectors if `None`.
949 Bin the image by this factor in both dimensions.
951 Size of border in binned pixels to make around the camera image.
953 Overlay Detector IDs and boundaries?
955 Title to use in display.
957 Include a WCS in the display?
958 ctype : `lsst.afw.display.COLOR` or `str`
959 Color to use when drawing Detector boundaries.
961 Size of detector labels
962 originAtCenter : `bool`
963 Put origin of the camera WCS at the center of the image?
964 If `False`, the origin will be at the lower left.
965 display : `lsst.afw.display`
966 Image display on which to display.
968 All remaining keyword arguments are passed to makeImageFromCamera
972 image : `lsst.afw.image.Image`
975 display = _getDisplayFromDisplayOrFrame(display)
979 cameraImage =
makeImageFromCamera(camera, detectorNameList=detectorNameList, bufferSize=bufferSize,
980 imageSource=imageSource, imageFactory=imageFactory, binSize=binSize,
983 if detectorNameList
is None:
984 ccdList = [camera[name]
for name
in camera.getNameIter()]
986 ccdList = [camera[name]
for name
in detectorNameList]
988 if detectorNameList
is None:
989 camBbox = camera.getFpBBox()
992 for detName
in detectorNameList:
993 for corner
in camera[detName].getCorners(FOCAL_PLANE):
994 camBbox.include(corner)
995 pixelSize = ccdList[0].getPixelSize()
1000 cameraImage.getBBox()).getCenter()
1009 title = camera.getName()
1010 display.mtv(cameraImage, title=title, wcs=wcs)
1013 with display.Buffering():
1015 camBbox, pixelSize, bufferSize*binSize)
1017 ccdList, binSize, pixelSize, camBbox.getMin())
1018 for bbox, ccd
in zip(bboxList, ccdList):
1019 nQuarter = ccd.getOrientation().getNQuarter()
1022 displayUtils.drawBBox(
1023 bbox, borderWidth=0.5, ctype=ctype, display=display)
1024 dims = bbox.getDimensions()
1025 ccdLabel =
"{}\n[{}]".format(ccd.getName(), ccd.getId())
1026 display.dot(ccdLabel, bbox.getMinX() + dims.getX()/2, bbox.getMinY() + dims.getY()/2,
1027 ctype=ctype, size=textSize, textAngle=nQuarter*90)
1033 """Make a WCS for the focal plane geometry
1034 (i.e. one that returns positions in "mm")
1039 Size of the image pixels in physical units
1040 referencePixel : `lsst.geom.Point2D`
1041 Pixel for origin of WCS
1046 Wcs object for mapping between pixels and focal plane.
1049 if referencePixel
is None:
1052 md.set(
"CRPIX%d"%(i + 1), referencePixel[i])
1053 md.set(
"CRVAL%d"%(i + 1), 0.)
1054 md.set(
"CDELT1", pixelSize[0])
1055 md.set(
"CDELT2", pixelSize[1])
1056 md.set(
"CTYPE1",
"CAMERA_X")
1057 md.set(
"CTYPE2",
"CAMERA_Y")
1058 md.set(
"CUNIT1",
"mm")
1059 md.set(
"CUNIT2",
"mm")
1065 """Find the Amp with the specified pixel position within the composite
1069 ccd : `lsst.afw.cameraGeom.Detector`
1070 Detector to look in.
1071 pixelPosition : `lsst.geom.Point2I`
1072 The pixel position to find the amp for.
1076 `lsst.afw.table.AmpInfoCatalog`
1077 Amp record in which ``pixelPosition`` falls or `None` if no Amp found.
1080 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.
Reports attempts to exceed implementation-defined length limits for some classes.
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)