LSSTApplications  19.0.0-10-g4a5fae6+21,20.0.0,20.0.0+1,20.0.0+2,20.0.0+3,20.0.0+6,20.0.0+7,20.0.0+8,20.0.0-1-g10df615+6,20.0.0-1-g253301a+2,20.0.0-1-g32a200e+6,20.0.0-1-g596936a+6,20.0.0-1-g8a53f90,20.0.0-1-gc96f8cb+7,20.0.0-1-gd1c87d7,20.0.0-15-g34741e2+1,20.0.0-2-g04cfba9,20.0.0-2-g92e20685+7,20.0.0-2-gec03fae,20.0.0-3-g082faa5,20.0.0-3-g2fa8bb8+3,20.0.0-4-gde602ef96+1,20.0.0-4-ge48a6ca+1,20.0.0-7-g180d0f2+2,20.0.0-8-g7eef53f7+2,w.2020.27
LSSTDataManagementBasePackage
utils.py
Go to the documentation of this file.
1 # This file is part of afw.
2 #
3 # Developed for the LSST Data Management System.
4 # This product includes software developed by the LSST Project
5 # (https://www.lsst.org).
6 # See the COPYRIGHT file at the top-level directory of this distribution
7 # for details of code ownership.
8 #
9 # This program is free software: you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation, either version 3 of the License, or
12 # (at your option) any later version.
13 #
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
18 #
19 # You should have received a copy of the GNU General Public License
20 # along with this program. If not, see <https://www.gnu.org/licenses/>.
21 
22 """
23 Support for displaying cameraGeom objects.
24 """
25 
26 __all__ = ['prepareWcsData', 'plotFocalPlane', 'makeImageFromAmp', 'calcRawCcdBBox', 'makeImageFromCcd',
27  'FakeImageDataSource', 'ButlerImage', 'rawCallback', 'overlayCcdBoxes',
28  'showAmp', 'showCcd', 'getCcdInCamBBoxList', 'getCameraImageBBox',
29  'makeImageFromCamera', 'showCamera', 'makeFocalPlaneWcs', 'findAmp']
30 
31 import math
32 import numpy
33 
34 import lsst.geom
35 from lsst.afw.fits import FitsError
36 import lsst.afw.geom as afwGeom
37 import lsst.afw.image as afwImage
38 import lsst.afw.math as afwMath
39 import lsst.afw.cameraGeom as afwCameraGeom
40 import lsst.daf.base as dafBase
41 import lsst.log
42 import lsst.pex.exceptions as pexExceptions
43 
44 from .rotateBBoxBy90 import rotateBBoxBy90
45 from .assembleImage import assembleAmplifierImage, assembleAmplifierRawImage
46 from .cameraGeomLib import FIELD_ANGLE, FOCAL_PLANE
47 from lsst.afw.display.utils import _getDisplayFromDisplayOrFrame
48 from lsst.afw.cameraGeom import DetectorType
49 
50 import lsst.afw.display as afwDisplay
51 import lsst.afw.display.utils as displayUtils
52 
53 
54 def prepareWcsData(wcs, amp, isTrimmed=True):
55  """Put Wcs from an Amp image into CCD coordinates
56 
57  Parameters
58  ----------
59  wcs : `lsst.afw.geom.SkyWcs`
60  The WCS object to start from.
61  amp : `lsst.afw.table.AmpInfoRecord`
62  Amp object to use
63  isTrimmed : `bool`
64  Is the image to which the WCS refers trimmed of non-imaging pixels?
65 
66  Returns
67  -------
68  ampWcs : `lsst.afw.geom.SkyWcs`
69  The modified WCS.
70  """
71  if isTrimmed:
72  ampBox = amp.getRawDataBBox()
73  else:
74  ampBox = amp.getRawBBox()
75  ampCenter = lsst.geom.Point2D(ampBox.getDimensions()/2.0)
76  wcs = afwGeom.makeFlippedWcs(wcs, amp.getRawFlipX(), amp.getRawFlipY(), ampCenter)
77  # Shift WCS for trimming
78  if isTrimmed:
79  trim_shift = ampBox.getMin() - amp.getBBox().getMin()
80  wcs = wcs.copyAtShiftedPixelOrigin(lsst.geom.Extent2D(-trim_shift.getX(), -trim_shift.getY()))
81  # Account for shift of amp data in larger ccd matrix
82  offset = amp.getRawXYOffset()
83  return wcs.copyAtShiftedPixelOrigin(lsst.geom.Extent2D(offset))
84 
85 
86 def plotFocalPlane(camera, fieldSizeDeg_x=0, fieldSizeDeg_y=None, dx=0.1, dy=0.1, figsize=(10., 10.),
87  useIds=False, showFig=True, savePath=None):
88  """Make a plot of the focal plane along with a set points that sample
89  the field of view.
90 
91  Parameters
92  ----------
93  camera : `lsst.afw.cameraGeom.Camera`
94  A camera object
95  fieldSizeDeg_x : `float`
96  Amount of the field to sample in x in degrees
97  fieldSizeDeg_y : `float` or `None`
98  Amount of the field to sample in y in degrees
99  dx : `float`
100  Spacing of sample points in x in degrees
101  dy : `float`
102  Spacing of sample points in y in degrees
103  figsize : `tuple` containing two `float`
104  Matplotlib style tuple indicating the size of the figure in inches
105  useIds : `bool`
106  Label detectors by name, not id?
107  showFig : `bool`
108  Display the figure on the screen?
109  savePath : `str` or `None`
110  If not `None`, save a copy of the figure to this name.
111  """
112  try:
113  from matplotlib.patches import Polygon
114  from matplotlib.collections import PatchCollection
115  import matplotlib.pyplot as plt
116  except ImportError:
117  raise ImportError(
118  "Can't run plotFocalPlane: matplotlib has not been set up")
119 
120  if fieldSizeDeg_x:
121  if fieldSizeDeg_y is None:
122  fieldSizeDeg_y = fieldSizeDeg_x
123 
124  field_gridx, field_gridy = numpy.meshgrid(
125  numpy.arange(0., fieldSizeDeg_x + dx, dx) - fieldSizeDeg_x/2.,
126  numpy.arange(0., fieldSizeDeg_y + dy, dy) - fieldSizeDeg_y/2.)
127  field_gridx, field_gridy = field_gridx.flatten(), field_gridy.flatten()
128  else:
129  field_gridx, field_gridy = [], []
130 
131  xs = []
132  ys = []
133  pcolors = []
134 
135  # compute focal plane positions corresponding to field angles field_gridx, field_gridy
136  posFieldAngleList = [lsst.geom.Point2D(x*lsst.geom.radians, y*lsst.geom.radians)
137  for x, y in zip(field_gridx, field_gridy)]
138  posFocalPlaneList = camera.transform(posFieldAngleList, FIELD_ANGLE, FOCAL_PLANE)
139  for posFocalPlane in posFocalPlaneList:
140  xs.append(posFocalPlane.getX())
141  ys.append(posFocalPlane.getY())
142  dets = camera.findDetectors(posFocalPlane, FOCAL_PLANE)
143  if len(dets) > 0:
144  pcolors.append('w')
145  else:
146  pcolors.append('k')
147 
148  colorMap = {DetectorType.SCIENCE: 'b', DetectorType.FOCUS: 'y',
149  DetectorType.GUIDER: 'g', DetectorType.WAVEFRONT: 'r'}
150 
151  patches = []
152  colors = []
153  plt.figure(figsize=figsize)
154  ax = plt.gca()
155  xvals = []
156  yvals = []
157  for det in camera:
158  corners = [(c.getX(), c.getY()) for c in det.getCorners(FOCAL_PLANE)]
159  for corner in corners:
160  xvals.append(corner[0])
161  yvals.append(corner[1])
162  colors.append(colorMap[det.getType()])
163  patches.append(Polygon(corners, True))
164  center = det.getOrientation().getFpPosition()
165  ax.text(center.getX(), center.getY(), det.getId() if useIds else det.getName(),
166  horizontalalignment='center', size=6)
167 
168  patchCollection = PatchCollection(patches, alpha=0.6, facecolor=colors)
169  ax.add_collection(patchCollection)
170  ax.scatter(xs, ys, s=10, alpha=.7, linewidths=0., c=pcolors)
171  ax.set_xlim(min(xvals) - abs(0.1*min(xvals)),
172  max(xvals) + abs(0.1*max(xvals)))
173  ax.set_ylim(min(yvals) - abs(0.1*min(yvals)),
174  max(yvals) + abs(0.1*max(yvals)))
175  ax.set_xlabel('Focal Plane X (mm)')
176  ax.set_ylabel('Focal Plane Y (mm)')
177  if savePath is not None:
178  plt.savefig(savePath)
179  if showFig:
180  plt.show()
181 
182 
183 def makeImageFromAmp(amp, imValue=None, imageFactory=afwImage.ImageU, markSize=10, markValue=0,
184  scaleGain=lambda gain: (gain*1000)//10):
185  """Make an image from an amp object.
186 
187  Since images are integer images by default, the gain needs to be scaled to
188  give enough dynamic range to see variation from amp to amp.
189  The scaling algorithm is assignable.
190 
191  Parameters
192  ----------
193  amp : `lsst.afw.table.AmpInfoRecord`
194  Amp record to use for constructing the raw amp image.
195  imValue : `float` or `None`
196  Value to assign to the constructed image, or scaleGain(gain) if `None`.
197  imageFactory : callable like `lsst.afw.image.Image`
198  Type of image to construct.
199  markSize : `float`
200  Size of mark at read corner in pixels.
201  markValue : `float`
202  Value of pixels in the read corner mark.
203  scaleGain : callable
204  The function by which to scale the gain (must take a single argument).
205 
206  Returns
207  -------
208  ampImage : `lsst.afw.image`
209  An untrimmed amp image, of the type produced by ``imageFactory``.
210  """
211  bbox = amp.getRawBBox()
212  dbbox = amp.getRawDataBBox()
213  img = imageFactory(bbox)
214  if imValue is None:
215  img.set(int(scaleGain(amp.getGain())))
216  else:
217  img.set(imValue)
218  # Set the first pixel read to a different value
219  markbbox = lsst.geom.Box2I()
220  if amp.getReadoutCorner() == afwCameraGeom.ReadoutCorner.LL:
221  markbbox.include(dbbox.getMin())
222  markbbox.include(dbbox.getMin() + lsst.geom.Extent2I(markSize, markSize))
223  elif amp.getReadoutCorner() == afwCameraGeom.ReadoutCorner.LR:
224  cornerPoint = lsst.geom.Point2I(dbbox.getMaxX(), dbbox.getMinY())
225  markbbox.include(cornerPoint)
226  markbbox.include(cornerPoint + lsst.geom.Extent2I(-markSize, markSize))
227  elif amp.getReadoutCorner() == afwCameraGeom.ReadoutCorner.UR:
228  cornerPoint = lsst.geom.Point2I(dbbox.getMax())
229  markbbox.include(cornerPoint)
230  markbbox.include(cornerPoint + lsst.geom.Extent2I(-markSize, -markSize))
231  elif amp.getReadoutCorner() == afwCameraGeom.ReadoutCorner.UL:
232  cornerPoint = lsst.geom.Point2I(dbbox.getMinX(), dbbox.getMaxY())
233  markbbox.include(cornerPoint)
234  markbbox.include(cornerPoint + lsst.geom.Extent2I(markSize, -markSize))
235  else:
236  raise RuntimeError("Could not set readout corner")
237  mimg = imageFactory(img, markbbox)
238  mimg.set(markValue)
239  return img
240 
241 
242 def calcRawCcdBBox(ccd):
243  """Calculate the raw ccd bounding box.
244 
245  Parameters
246  ----------
247  ccd : `lsst.afw.cameraGeom.Detector`
248  Detector for which to calculate the un-trimmed bounding box.
249 
250  Returns
251  -------
252  bbox : `lsst.geom.Box2I` or `None`
253  Bounding box of the un-trimmed Detector, or `None` if there is not enough
254  information to calculate raw BBox.
255  """
256  bbox = lsst.geom.Box2I()
257  for amp in ccd:
258  tbbox = amp.getRawBBox()
259  tbbox.shift(amp.getRawXYOffset())
260  bbox.include(tbbox)
261  return bbox
262 
263 
264 def makeImageFromCcd(ccd, isTrimmed=True, showAmpGain=True, imageFactory=afwImage.ImageU, rcMarkSize=10,
265  binSize=1):
266  """Make an Image of a CCD.
267 
268  Parameters
269  ----------
270  ccd : `lsst.afw.cameraGeom.Detector`
271  Detector to use in making the image.
272  isTrimmed : `bool`
273  Assemble a trimmed Detector image.
274  showAmpGain : `bool`
275  Use the per-amp gain to color the pixels in the image?
276  imageFactory : callable like `lsst.afw.image.Image`
277  Image type to generate.
278  rcMarkSize : `float`
279  Size of the mark to make in the amp images at the read corner.
280  binSize : `int`
281  Bin the image by this factor in both dimensions.
282 
283  Returns
284  -------
285  image : `lsst.afw.image.Image`
286  Image of the Detector (type returned by ``imageFactory``).
287  """
288  ampImages = []
289  index = 0
290  if isTrimmed:
291  bbox = ccd.getBBox()
292  else:
293  bbox = calcRawCcdBBox(ccd)
294  for amp in ccd:
295  if showAmpGain:
296  ampImages.append(makeImageFromAmp(
297  amp, imageFactory=imageFactory, markSize=rcMarkSize))
298  else:
299  ampImages.append(makeImageFromAmp(amp, imValue=(index + 1)*1000,
300  imageFactory=imageFactory, markSize=rcMarkSize))
301  index += 1
302 
303  if len(ampImages) > 0:
304  ccdImage = imageFactory(bbox)
305  for ampImage, amp in zip(ampImages, ccd):
306  if isTrimmed:
307  assembleAmplifierImage(ccdImage, ampImage, amp)
308  else:
309  assembleAmplifierRawImage(ccdImage, ampImage, amp)
310  else:
311  if not isTrimmed:
312  raise RuntimeError(
313  "Cannot create untrimmed CCD without amps with raw information")
314  ccdImage = imageFactory(ccd.getBBox())
315  ccdImage = afwMath.binImage(ccdImage, binSize)
316  return ccdImage
317 
318 
320  """A class to retrieve synthetic images for display by the show* methods
321 
322  Parameters
323  ----------
324  isTrimmed : `bool`
325  Should amps be trimmed?
326  verbose : `bool`
327  Be chatty?
328  background : `float`
329  The value of any pixels that lie outside the CCDs.
330  showAmpGain : `bool`
331  Color the amp segments with the gain of the amp?
332  markSize : `float`
333  Size of the side of the box used to mark the read corner.
334  markValue : `float`
335  Value to assign the read corner mark.
336  ampImValue : `float` or `None`
337  Value to assign to amps; scaleGain(gain) is used if `None`.
338  scaleGain : callable
339  Function to scale the gain by.
340  """
341  def __init__(self, isTrimmed=True, verbose=False, background=numpy.nan,
342  showAmpGain=True, markSize=10, markValue=0,
343  ampImValue=None, scaleGain=lambda gain: (gain*1000)//10):
344  self.isTrimmed = isTrimmed
345  self.verbose = verbose
346  self.background = background
347  self.showAmpGain = showAmpGain
348  self.markSize = markSize
349  self.markValue = markValue
350  self.ampImValue = ampImValue
351  self.scaleGain = scaleGain
352 
353  def getCcdImage(self, det, imageFactory, binSize):
354  """Return a CCD image for the detector and the (possibly updated) Detector.
355 
356  Parameters
357  ----------
358  det : `lsst.afw.cameraGeom.Detector`
359  Detector to use for making the image.
360  imageFactory : callable like `lsst.afw.image.Image`
361  Image constructor for making the image.
362  binSize : `int`
363  Bin the image by this factor in both dimensions.
364 
365  Returns
366  -------
367  ccdImage : `lsst.afw.image.Image`
368  The constructed image.
369  """
370  ccdImage = makeImageFromCcd(det, isTrimmed=self.isTrimmed, showAmpGain=self.showAmpGain,
371  imageFactory=imageFactory, binSize=binSize)
372  return afwMath.rotateImageBy90(ccdImage, det.getOrientation().getNQuarter()), det
373 
374  def getAmpImage(self, amp, imageFactory):
375  """Return an amp segment image.
376 
377  Parameters
378  ----------
379  amp : `lsst.afw.table.AmpInfoTable`
380  AmpInfoTable for this amp.
381  imageFactory : callable like `lsst.afw.image.Image`
382  Image constructor for making the image.
383 
384  Returns
385  -------
386  ampImage : `lsst.afw.image.Image`
387  The constructed image.
388  """
389  ampImage = makeImageFromAmp(amp, imValue=self.ampImValue, imageFactory=imageFactory,
390  markSize=self.markSize, markValue=self.markValue,
391  scaleGain=self.scaleGain)
392  if self.isTrimmed:
393  ampImage = ampImage.Factory(ampImage, amp.getRawDataBBox())
394  return ampImage
395 
396 
398  """A class to return an Image of a given Ccd using the butler.
399 
400  Parameters
401  ----------
402  butler : `lsst.daf.persistence.Butler` or `None`
403  The butler to use. If `None`, an empty image is returned.
404  type : `str`
405  The type of image to read (e.g. raw, bias, flat, calexp).
406  isTrimmed : `bool`
407  If true, the showCamera command expects to be given trimmed images.
408  verbose : `bool`
409  Be chatty (in particular, log any error messages from the butler)?
410  background : `float`
411  The value of any pixels that lie outside the CCDs.
412  callback : callable
413  A function called with (image, ccd, butler) for every image, which
414  returns the image to be displayed (e.g. rawCallback). The image must
415  be of the correct size, allowing for the value of isTrimmed.
416  *args : `list`
417  Passed to the butler.
418  **kwargs : `dict`
419  Passed to the butler.
420 
421  Notes
422  -----
423  You can define a short named function as a callback::
424 
425  def callback(im, ccd, imageSource):
426  return cameraGeom.utils.rawCallback(im, ccd, imageSource, correctGain=True)
427  """
428  def __init__(self, butler=None, type="raw",
429  isTrimmed=True, verbose=False, background=numpy.nan,
430  callback=None, *args, **kwargs):
431  super(ButlerImage, self).__init__(*args)
432  self.isTrimmed = isTrimmed
433  self.type = type
434  self.butler = butler
435  self.kwargs = kwargs
436  self.isRaw = False
437  self.background = background
438  self.verbose = verbose
439  self.callback = callback
440 
441  def _prepareImage(self, ccd, im, binSize, allowRotate=True):
442  if binSize > 1:
443  im = afwMath.binImage(im, binSize)
444 
445  if allowRotate:
447  im, ccd.getOrientation().getNQuarter())
448 
449  return im
450 
451  def getCcdImage(self, ccd, imageFactory=afwImage.ImageF, binSize=1, asMaskedImage=False):
452  """Return an image of the specified ccd, and also the (possibly updated) ccd"""
453 
454  log = lsst.log.Log.getLogger("afw.cameraGeom.utils.ButlerImage")
455 
456  if self.isTrimmed:
457  bbox = ccd.getBBox()
458  else:
459  bbox = calcRawCcdBBox(ccd)
460 
461  im = None
462  if self.butler is not None:
463  err = None
464  for dataId in [dict(detector=ccd.getId()), dict(ccd=ccd.getId()), dict(ccd=ccd.getName())]:
465  try:
466  im = self.butler.get(self.type, dataId, **self.kwargs)
467  except FitsError as e: # no point trying another dataId
468  err = IOError(e.args[0].split('\n')[0]) # It's a very chatty error
469  break
470  except Exception as e: # try a different dataId
471  if err is None:
472  err = e
473  continue
474  else:
475  ccd = im.getDetector() # possibly modified by assembleCcdTask
476  break
477 
478  if im:
479  if asMaskedImage:
480  im = im.getMaskedImage()
481  else:
482  im = im.getMaskedImage().getImage()
483  else:
484  if self.verbose:
485  # Lost by jupyterlab.
486  print(f"Reading {ccd.getId()}: {err}")
487 
488  log.warn(f"Reading {ccd.getId()}: {err}")
489 
490  if im is None:
491  return self._prepareImage(ccd, imageFactory(*bbox.getDimensions()), binSize), ccd
492 
493  if self.type == "raw":
494  if hasattr(im, 'convertF'):
495  im = im.convertF()
496  if False and self.callback is None: # we need to trim the raw image
497  self.callback = rawCallback
498 
499  allowRotate = True
500  if self.callback:
501  try:
502  im = self.callback(im, ccd, imageSource=self)
503  except Exception as e:
504  if self.verbose:
505  log.error(f"callback failed: {e}")
506  im = imageFactory(*bbox.getDimensions())
507  else:
508  allowRotate = False # the callback was responsible for any rotations
509 
510  return self._prepareImage(ccd, im, binSize, allowRotate=allowRotate), ccd
511 
512 
513 def rawCallback(im, ccd=None, imageSource=None,
514  correctGain=False, subtractBias=False, convertToFloat=False, obeyNQuarter=True):
515  """A callback function that may or may not subtract bias/correct gain/trim
516  a raw image.
517 
518  Parameters
519  ----------
520  im : `lsst.afw.image.Image` or `lsst.afw.image.MaskedImage` or `lsst.afw.image.Exposure`
521  An image of a chip, ready to be binned and maybe rotated.
522  ccd : `lsst.afw.cameraGeom.Detector` or `None`
523  The Detector; if `None` assume that im is an exposure and extract its Detector.
524  imageSource : `FakeImageDataSource` or `None`
525  Source to get ccd images. Must have a `getCcdImage()` method.
526  correctGain : `bool`
527  Correct each amplifier for its gain?
528  subtractBias : `bool`
529  Subtract the bias from each amplifier?
530  convertToFloat : `bool`
531  Convert ``im`` to floating point if possible.
532  obeyNQuarter : `bool`
533  Obey nQuarter from the Detector (default: True)
534 
535  Returns
536  -------
537  image : `lsst.afw.image.Image` like
538  The constructed image (type returned by ``im.Factory``).
539 
540  Notes
541  -----
542  If imageSource is derived from ButlerImage, imageSource.butler is available.
543  """
544  if ccd is None:
545  ccd = im.getDetector()
546  if hasattr(im, "getMaskedImage"):
547  im = im.getMaskedImage()
548  if convertToFloat and hasattr(im, "convertF"):
549  im = im.convertF()
550 
551  isTrimmed = imageSource.isTrimmed
552  if isTrimmed:
553  bbox = ccd.getBBox()
554  else:
555  bbox = calcRawCcdBBox(ccd)
556 
557  ampImages = []
558  for a in ccd:
559  if isTrimmed:
560  data = im[a.getRawDataBBox()]
561  else:
562  data = im
563 
564  if subtractBias:
565  bias = im[a.getRawHorizontalOverscanBBox()]
566  data -= afwMath.makeStatistics(bias, afwMath.MEANCLIP).getValue()
567  if correctGain:
568  data *= a.getGain()
569 
570  ampImages.append(data)
571 
572  ccdImage = im.Factory(bbox)
573  for ampImage, amp in zip(ampImages, ccd):
574  if isTrimmed:
575  assembleAmplifierImage(ccdImage, ampImage, amp)
576  else:
577  assembleAmplifierRawImage(ccdImage, ampImage, amp)
578 
579  if obeyNQuarter:
580  nQuarter = ccd.getOrientation().getNQuarter()
581  ccdImage = afwMath.rotateImageBy90(ccdImage, nQuarter)
582 
583  return ccdImage
584 
585 
586 def overlayCcdBoxes(ccd, untrimmedCcdBbox=None, nQuarter=0,
587  isTrimmed=False, ccdOrigin=(0, 0), display=None, binSize=1):
588  """Overlay bounding boxes on an image display.
589 
590  Parameters
591  ----------
592  ccd : `lsst.afw.cameraGeom.Detector`
593  Detector to iterate for the amp bounding boxes.
594  untrimmedCcdBbox : `lsst.geom.Box2I` or `None`
595  Bounding box of the un-trimmed Detector.
596  nQuarter : `int`
597  number of 90 degree rotations to apply to the bounding boxes (used for rotated chips).
598  isTrimmed : `bool`
599  Is the Detector image over which the boxes are layed trimmed?
600  ccdOrigin : `tuple` of `float`
601  Detector origin relative to the parent origin if in a larger pixel grid.
602  display : `lsst.afw.display.Display`
603  Image display to display on.
604  binSize : `int`
605  Bin the image by this factor in both dimensions.
606 
607  Notes
608  -----
609  The colours are:
610  - Entire detector GREEN
611  - All data for amp GREEN
612  - HorizontalPrescan YELLOW
613  - HorizontalOverscan RED
614  - Data BLUE
615  - VerticalOverscan MAGENTA
616  - VerticalOverscan MAGENTA
617  """
618  if not display: # should be second parameter, and not defaulted!!
619  raise RuntimeError("Please specify a display")
620 
621  if untrimmedCcdBbox is None:
622  if isTrimmed:
623  untrimmedCcdBbox = ccd.getBBox()
624  else:
625  untrimmedCcdBbox = lsst.geom.Box2I()
626  for a in ccd.getAmplifiers():
627  bbox = a.getRawBBox()
628  untrimmedCcdBbox.include(bbox)
629 
630  with display.Buffering():
631  ccdDim = untrimmedCcdBbox.getDimensions()
632  ccdBbox = rotateBBoxBy90(untrimmedCcdBbox, nQuarter, ccdDim)
633  for amp in ccd:
634  if isTrimmed:
635  ampbbox = amp.getBBox()
636  else:
637  ampbbox = amp.getRawBBox()
638  if nQuarter != 0:
639  ampbbox = rotateBBoxBy90(ampbbox, nQuarter, ccdDim)
640 
641  displayUtils.drawBBox(ampbbox, origin=ccdOrigin, borderWidth=0.49,
642  display=display, bin=binSize)
643 
644  if not isTrimmed:
645  for bbox, ctype in ((amp.getRawHorizontalOverscanBBox(), afwDisplay.RED),
646  (amp.getRawDataBBox(), afwDisplay.BLUE),
647  (amp.getRawVerticalOverscanBBox(),
648  afwDisplay.MAGENTA),
649  (amp.getRawPrescanBBox(), afwDisplay.YELLOW)):
650  if nQuarter != 0:
651  bbox = rotateBBoxBy90(bbox, nQuarter, ccdDim)
652  displayUtils.drawBBox(bbox, origin=ccdOrigin, borderWidth=0.49, ctype=ctype,
653  display=display, bin=binSize)
654  # Label each Amp
655  xc, yc = ((ampbbox.getMin()[0] + ampbbox.getMax()[0])//2,
656  (ampbbox.getMin()[1] + ampbbox.getMax()[1])//2)
657  #
658  # Rotate the amp labels too
659  #
660  if nQuarter == 0:
661  c, s = 1, 0
662  elif nQuarter == 1:
663  c, s = 0, -1
664  elif nQuarter == 2:
665  c, s = -1, 0
666  elif nQuarter == 3:
667  c, s = 0, 1
668  c, s = 1, 0
669  ccdHeight = ccdBbox.getHeight()
670  ccdWidth = ccdBbox.getWidth()
671  xc -= 0.5*ccdHeight
672  yc -= 0.5*ccdWidth
673 
674  xc, yc = 0.5*ccdHeight + c*xc + s*yc, 0.5*ccdWidth + -s*xc + c*yc
675 
676  if ccdOrigin:
677  xc += ccdOrigin[0]
678  yc += ccdOrigin[1]
679  display.dot(str(amp.getName()), xc/binSize,
680  yc/binSize, textAngle=nQuarter*90)
681 
682  displayUtils.drawBBox(ccdBbox, origin=ccdOrigin,
683  borderWidth=0.49, ctype=afwDisplay.MAGENTA, display=display, bin=binSize)
684 
685 
686 def showAmp(amp, imageSource=FakeImageDataSource(isTrimmed=False), display=None, overlay=True,
687  imageFactory=afwImage.ImageU):
688  """Show an amp in an image display.
689 
690  Parameters
691  ----------
692  amp : `lsst.afw.tables.AmpInfoRecord`
693  Amp record to use in display.
694  imageSource : `FakeImageDataSource` or `None`
695  Source for getting the amp image. Must have a ``getAmpImage()`` method.
696  display : `lsst.afw.display.Display`
697  Image display to use.
698  overlay : `bool`
699  Overlay bounding boxes?
700  imageFactory : callable like `lsst.afw.image.Image`
701  Type of image to display (only used if ampImage is `None`).
702  """
703  if not display:
704  display = _getDisplayFromDisplayOrFrame(display)
705 
706  ampImage = imageSource.getAmpImage(amp, imageFactory=imageFactory)
707  ampImSize = ampImage.getDimensions()
708  title = amp.getName()
709  display.mtv(ampImage, title=title)
710  if overlay:
711  with display.Buffering():
712  if ampImSize == amp.getRawBBox().getDimensions():
713  bboxes = [(amp.getRawBBox(), 0.49, afwDisplay.GREEN), ]
714  xy0 = bboxes[0][0].getMin()
715  bboxes.append(
716  (amp.getRawHorizontalOverscanBBox(), 0.49, afwDisplay.RED))
717  bboxes.append((amp.getRawDataBBox(), 0.49, afwDisplay.BLUE))
718  bboxes.append((amp.getRawPrescanBBox(),
719  0.49, afwDisplay.YELLOW))
720  bboxes.append((amp.getRawVerticalOverscanBBox(),
721  0.49, afwDisplay.MAGENTA))
722  else:
723  bboxes = [(amp.getBBox(), 0.49, None), ]
724  xy0 = bboxes[0][0].getMin()
725 
726  for bbox, borderWidth, ctype in bboxes:
727  if bbox.isEmpty():
728  continue
729  bbox = lsst.geom.Box2I(bbox)
730  bbox.shift(-lsst.geom.ExtentI(xy0))
731  displayUtils.drawBBox(
732  bbox, borderWidth=borderWidth, ctype=ctype, display=display)
733 
734 
735 def showCcd(ccd, imageSource=FakeImageDataSource(), display=None, overlay=True,
736  imageFactory=afwImage.ImageF, binSize=1, inCameraCoords=False):
737  """Show a CCD on display.
738 
739  Parameters
740  ----------
741  ccd : `lsst.afw.cameraGeom.Detector`
742  Detector to use in display.
743  imageSource : `FakeImageDataSource` or `None`
744  Source to get ccd images. Must have a ``getCcdImage()`` method.
745  display : `lsst.afw.display.Display`
746  image display to use.
747  overlay : `bool`
748  Show amp bounding boxes on the displayed image?
749  imageFactory : callable like `lsst.afw.image.Image`
750  The image factory to use in generating the images.
751  binSize : `int`
752  Bin the image by this factor in both dimensions.
753  inCameraCoords : `bool`
754  Show the Detector in camera coordinates?
755  """
756  display = _getDisplayFromDisplayOrFrame(display)
757 
758  ccdOrigin = lsst.geom.Point2I(0, 0)
759  nQuarter = 0
760  ccdImage, ccd = imageSource.getCcdImage(
761  ccd, imageFactory=imageFactory, binSize=binSize)
762 
763  ccdBbox = ccdImage.getBBox()
764  if ccdBbox.getDimensions() == ccd.getBBox().getDimensions():
765  isTrimmed = True
766  else:
767  isTrimmed = False
768 
769  if inCameraCoords:
770  nQuarter = ccd.getOrientation().getNQuarter()
771  ccdImage = afwMath.rotateImageBy90(ccdImage, nQuarter)
772  title = ccd.getName()
773  if isTrimmed:
774  title += "(trimmed)"
775 
776  if display:
777  display.mtv(ccdImage, title=title)
778 
779  if overlay:
780  overlayCcdBoxes(ccd, ccdBbox, nQuarter, isTrimmed,
781  ccdOrigin, display, binSize)
782 
783  return ccdImage
784 
785 
786 def getCcdInCamBBoxList(ccdList, binSize, pixelSize_o, origin):
787  """Get the bounding boxes of a list of Detectors within a camera sized pixel grid
788 
789  Parameters
790  ----------
791  ccdList : `lsst.afw.cameraGeom.Detector`
792  List of Detector.
793  binSize : `int`
794  Bin the image by this factor in both dimensions.
795  pixelSize_o : `float`
796  Size of the pixel in mm.
797  origin : `int`
798  Origin of the camera pixel grid in pixels.
799 
800  Returns
801  -------
802  boxList : `list` [`lsst.geom.Box2I`]
803  A list of bounding boxes in camera pixel coordinates.
804  """
805  boxList = []
806  for ccd in ccdList:
807  if not pixelSize_o == ccd.getPixelSize():
808  raise RuntimeError(
809  "Cameras with detectors with different pixel scales are not currently supported")
810 
811  dbbox = lsst.geom.Box2D()
812  for corner in ccd.getCorners(FOCAL_PLANE):
813  dbbox.include(corner)
814  llc = dbbox.getMin()
815  nQuarter = ccd.getOrientation().getNQuarter()
816  cbbox = ccd.getBBox()
817  ex = cbbox.getDimensions().getX()//binSize
818  ey = cbbox.getDimensions().getY()//binSize
819  bbox = lsst.geom.Box2I(
820  cbbox.getMin(), lsst.geom.Extent2I(int(ex), int(ey)))
821  bbox = rotateBBoxBy90(bbox, nQuarter, bbox.getDimensions())
822  bbox.shift(lsst.geom.Extent2I(int(llc.getX()//pixelSize_o.getX()/binSize),
823  int(llc.getY()//pixelSize_o.getY()/binSize)))
824  bbox.shift(lsst.geom.Extent2I(-int(origin.getX()//binSize),
825  -int(origin.getY())//binSize))
826  boxList.append(bbox)
827  return boxList
828 
829 
830 def getCameraImageBBox(camBbox, pixelSize, bufferSize):
831  """Get the bounding box of a camera sized image in pixels
832 
833  Parameters
834  ----------
835  camBbox : `lsst.geom.Box2D`
836  Camera bounding box in focal plane coordinates (mm).
837  pixelSize : `float`
838  Size of a detector pixel in mm.
839  bufferSize : `int`
840  Buffer around edge of image in pixels.
841 
842  Returns
843  -------
844  box : `lsst.geom.Box2I`
845  The resulting bounding box.
846  """
847  pixMin = lsst.geom.Point2I(int(camBbox.getMinX()//pixelSize.getX()),
848  int(camBbox.getMinY()//pixelSize.getY()))
849  pixMax = lsst.geom.Point2I(int(camBbox.getMaxX()//pixelSize.getX()),
850  int(camBbox.getMaxY()//pixelSize.getY()))
851  retBox = lsst.geom.Box2I(pixMin, pixMax)
852  retBox.grow(bufferSize)
853  return retBox
854 
855 
856 def makeImageFromCamera(camera, detectorNameList=None, background=numpy.nan, bufferSize=10,
857  imageSource=FakeImageDataSource(), imageFactory=afwImage.ImageU, binSize=1):
858  """Make an Image of a Camera.
859 
860  Put each detector's image in the correct location and orientation on the
861  focal plane. The input images can be binned to an integer fraction of their
862  original bboxes.
863 
864  Parameters
865  ----------
866  camera : `lsst.afw.cameraGeom.Camera`
867  Camera object to use to make the image.
868  detectorNameList : `list` [`str`]
869  List of detector names from ``camera`` to use in building the image.
870  Use all Detectors if `None`.
871  background : `float`
872  Value to use where there is no Detector.
873  bufferSize : `int`
874  Size of border in binned pixels to make around the camera image.
875  imageSource : `FakeImageDataSource` or `None`
876  Source to get ccd images. Must have a ``getCcdImage()`` method.
877  imageFactory : callable like `lsst.afw.image.Image`
878  Type of image to build.
879  binSize : `int`
880  Bin the image by this factor in both dimensions.
881 
882  Returns
883  -------
884  image : `lsst.afw.image.Image`
885  Image of the entire camera.
886  """
887  log = lsst.log.Log.getLogger("afw.cameraGeom.utils.makeImageFromCamera")
888 
889  if detectorNameList is None:
890  ccdList = camera
891  else:
892  ccdList = [camera[name] for name in detectorNameList]
893 
894  if detectorNameList is None:
895  camBbox = camera.getFpBBox()
896  else:
897  camBbox = lsst.geom.Box2D()
898  for detName in detectorNameList:
899  for corner in camera[detName].getCorners(FOCAL_PLANE):
900  camBbox.include(corner)
901 
902  pixelSize_o = camera[next(camera.getNameIter())].getPixelSize()
903  camBbox = getCameraImageBBox(camBbox, pixelSize_o, bufferSize*binSize)
904  origin = camBbox.getMin()
905 
906  camIm = imageFactory(int(math.ceil(camBbox.getDimensions().getX()/binSize)),
907  int(math.ceil(camBbox.getDimensions().getY()/binSize)))
908  camIm[:] = imageSource.background
909 
910  assert imageSource.isTrimmed, "isTrimmed is False isn't supported by getCcdInCamBBoxList"
911 
912  boxList = getCcdInCamBBoxList(ccdList, binSize, pixelSize_o, origin)
913  for det, bbox in zip(ccdList, boxList):
914  im = imageSource.getCcdImage(det, imageFactory, binSize)[0]
915  if im is None:
916  continue
917 
918  imView = camIm.Factory(camIm, bbox, afwImage.LOCAL)
919  try:
920  imView[:] = im
921  except pexExceptions.LengthError as e:
922  log.error(f"Unable to fit image for detector \"{det.getName()}\" into image of camera: {e}")
923 
924  return camIm
925 
926 
927 def showCamera(camera, imageSource=FakeImageDataSource(), imageFactory=afwImage.ImageF,
928  detectorNameList=None, binSize=10, bufferSize=10, overlay=True, title="",
929  showWcs=None, ctype=afwDisplay.GREEN, textSize=1.25, originAtCenter=True, display=None,
930  **kwargs):
931  """Show a Camera on display, with the specified display.
932 
933  The rotation of the sensors is snapped to the nearest multiple of 90 deg.
934  Also note that the pixel size is constant over the image array. The lower
935  left corner (LLC) of each sensor amp is snapped to the LLC of the pixel
936  containing the LLC of the image.
937 
938  Parameters
939  ----------
940  camera : `lsst.afw.cameraGeom.Camera`
941  Camera object to use to make the image.
942  imageSource : `FakeImageDataSource` or `None`
943  Source to get ccd images. Must have a ``getCcdImage()`` method.
944  imageFactory : `lsst.afw.image.Image`
945  Type of image to make
946  detectorNameList : `list` [`str`] or `None`
947  List of detector names from `camera` to use in building the image.
948  Use all Detectors if `None`.
949  binSize : `int`
950  Bin the image by this factor in both dimensions.
951  bufferSize : `int`
952  Size of border in binned pixels to make around the camera image.
953  overlay : `bool`
954  Overlay Detector IDs and boundaries?
955  title : `str`
956  Title to use in display.
957  showWcs : `bool`
958  Include a WCS in the display?
959  ctype : `lsst.afw.display.COLOR` or `str`
960  Color to use when drawing Detector boundaries.
961  textSize : `float`
962  Size of detector labels
963  originAtCenter : `bool`
964  Put origin of the camera WCS at the center of the image?
965  If `False`, the origin will be at the lower left.
966  display : `lsst.afw.display`
967  Image display on which to display.
968  **kwargs :
969  All remaining keyword arguments are passed to makeImageFromCamera
970 
971  Returns
972  -------
973  image : `lsst.afw.image.Image`
974  The mosaic image.
975  """
976  display = _getDisplayFromDisplayOrFrame(display)
977 
978  if binSize < 1:
979  binSize = 1
980  cameraImage = makeImageFromCamera(camera, detectorNameList=detectorNameList, bufferSize=bufferSize,
981  imageSource=imageSource, imageFactory=imageFactory, binSize=binSize,
982  **kwargs)
983 
984  if detectorNameList is None:
985  ccdList = [camera[name] for name in camera.getNameIter()]
986  else:
987  ccdList = [camera[name] for name in detectorNameList]
988 
989  if detectorNameList is None:
990  camBbox = camera.getFpBBox()
991  else:
992  camBbox = lsst.geom.Box2D()
993  for detName in detectorNameList:
994  for corner in camera[detName].getCorners(FOCAL_PLANE):
995  camBbox.include(corner)
996  pixelSize = ccdList[0].getPixelSize()
997 
998  if showWcs:
999  if originAtCenter:
1000  wcsReferencePixel = lsst.geom.Box2D(
1001  cameraImage.getBBox()).getCenter()
1002  else:
1003  wcsReferencePixel = lsst.geom.Point2I(0, 0)
1004  wcs = makeFocalPlaneWcs(pixelSize*binSize, wcsReferencePixel)
1005  else:
1006  wcs = None
1007 
1008  if display:
1009  if title == "":
1010  title = camera.getName()
1011  display.mtv(cameraImage, title=title, wcs=wcs)
1012 
1013  if overlay:
1014  with display.Buffering():
1015  camBbox = getCameraImageBBox(
1016  camBbox, pixelSize, bufferSize*binSize)
1017  bboxList = getCcdInCamBBoxList(
1018  ccdList, binSize, pixelSize, camBbox.getMin())
1019  for bbox, ccd in zip(bboxList, ccdList):
1020  nQuarter = ccd.getOrientation().getNQuarter()
1021  # borderWidth to 0.5 to align with the outside edge of the
1022  # pixel
1023  displayUtils.drawBBox(
1024  bbox, borderWidth=0.5, ctype=ctype, display=display)
1025  dims = bbox.getDimensions()
1026  display.dot(ccd.getName(), bbox.getMinX() + dims.getX()/2, bbox.getMinY() + dims.getY()/2,
1027  ctype=ctype, size=textSize, textAngle=nQuarter*90)
1028 
1029  return cameraImage
1030 
1031 
1032 def makeFocalPlaneWcs(pixelSize, referencePixel):
1033  """Make a WCS for the focal plane geometry
1034  (i.e. one that returns positions in "mm")
1035 
1036  Parameters
1037  ----------
1038  pixelSize : `float`
1039  Size of the image pixels in physical units
1040  referencePixel : `lsst.geom.Point2D`
1041  Pixel for origin of WCS
1042 
1043  Returns
1044  -------
1045  `lsst.afw.geom.Wcs`
1046  Wcs object for mapping between pixels and focal plane.
1047  """
1048  md = dafBase.PropertySet()
1049  if referencePixel is None:
1050  referencePixel = lsst.geom.PointD(0, 0)
1051  for i in range(2):
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")
1060 
1061  return afwGeom.makeSkyWcs(md)
1062 
1063 
1064 def findAmp(ccd, pixelPosition):
1065  """Find the Amp with the specified pixel position within the composite
1066 
1067  Parameters
1068  ----------
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.
1073 
1074  Returns
1075  -------
1076  `lsst.afw.table.AmpInfoCatalog`
1077  Amp record in which ``pixelPosition`` falls or `None` if no Amp found.
1078  """
1079  for amp in ccd:
1080  if amp.getBBox().contains(pixelPosition):
1081  return amp
1082 
1083  return None
lsst::afw.display.utils
Definition: utils.py:1
lsst::afw::cameraGeom.utils.getCameraImageBBox
def getCameraImageBBox(camBbox, pixelSize, bufferSize)
Definition: utils.py:830
lsst::afw::image
Backwards-compatibility support for depersisting the old Calib (FluxMag0/FluxMag0Err) objects.
Definition: imageAlgorithm.dox:1
astshim.fitsChanContinued.next
def next(self)
Definition: fitsChanContinued.py:105
lsst::afw::cameraGeom.utils.makeImageFromAmp
def makeImageFromAmp(amp, imValue=None, imageFactory=afwImage.ImageU, markSize=10, markValue=0, scaleGain=lambda gain:(gain *1000)//10)
Definition: utils.py:183
lsst::afw::cameraGeom.utils.ButlerImage.callback
callback
Definition: utils.py:437
lsst::afw::cameraGeom.utils.showCcd
def showCcd(ccd, imageSource=FakeImageDataSource(), display=None, overlay=True, imageFactory=afwImage.ImageF, binSize=1, inCameraCoords=False)
Definition: utils.py:735
lsst::afw::cameraGeom.rotateBBoxBy90.rotateBBoxBy90
def rotateBBoxBy90(bbox, n90, dimensions)
Definition: rotateBBoxBy90.py:29
lsst::sphgeom::abs
Angle abs(Angle const &a)
Definition: Angle.h:106
lsst::afw.display
Definition: __init__.py:1
lsst::afw::math::makeStatistics
Statistics makeStatistics(lsst::afw::math::MaskedVector< EntryT > const &mv, std::vector< WeightPixel > const &vweights, int const flags, StatisticsControl const &sctrl=StatisticsControl())
The makeStatistics() overload to handle lsst::afw::math::MaskedVector<>
Definition: Statistics.h:520
lsst::afw::cameraGeom.utils.FakeImageDataSource.verbose
verbose
Definition: utils.py:343
lsst::log::Log::getLogger
static Log getLogger(Log const &logger)
Definition: Log.h:760
lsst::afw::cameraGeom.utils.ButlerImage.isRaw
isRaw
Definition: utils.py:434
lsst::afw::cameraGeom.utils.FakeImageDataSource
Definition: utils.py:319
lsst::afw::cameraGeom.utils.overlayCcdBoxes
def overlayCcdBoxes(ccd, untrimmedCcdBbox=None, nQuarter=0, isTrimmed=False, ccdOrigin=(0, 0), display=None, binSize=1)
Definition: utils.py:586
lsst::afw::cameraGeom.utils.FakeImageDataSource.markValue
markValue
Definition: utils.py:347
lsst::afw::cameraGeom.utils.ButlerImage.kwargs
kwargs
Definition: utils.py:433
lsst::afw::cameraGeom.assembleImage.assembleAmplifierImage
def assembleAmplifierImage(destImage, rawImage, amplifier)
Definition: assembleImage.py:54
lsst::afw::cameraGeom.utils.showAmp
def showAmp(amp, imageSource=FakeImageDataSource(isTrimmed=False), display=None, overlay=True, imageFactory=afwImage.ImageU)
Definition: utils.py:686
lsst::afw::cameraGeom.utils.ButlerImage.__init__
def __init__(self, butler=None, type="raw", isTrimmed=True, verbose=False, background=numpy.nan, callback=None, *args, **kwargs)
Definition: utils.py:428
lsst::afw::cameraGeom.utils.prepareWcsData
def prepareWcsData(wcs, amp, isTrimmed=True)
Definition: utils.py:54
lsst::afw::cameraGeom.utils.getCcdInCamBBoxList
def getCcdInCamBBoxList(ccdList, binSize, pixelSize_o, origin)
Definition: utils.py:786
lsst::afw::cameraGeom.utils.ButlerImage._prepareImage
def _prepareImage(self, ccd, im, binSize, allowRotate=True)
Definition: utils.py:441
lsst::afw::cameraGeom.utils.findAmp
def findAmp(ccd, pixelPosition)
Definition: utils.py:1064
lsst::afw::cameraGeom.utils.showCamera
def 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)
Definition: utils.py:927
lsst::afw::cameraGeom.utils.makeFocalPlaneWcs
def makeFocalPlaneWcs(pixelSize, referencePixel)
Definition: utils.py:1032
lsst::afw::cameraGeom.utils.FakeImageDataSource.isTrimmed
isTrimmed
Definition: utils.py:342
lsst::afw::cameraGeom.assembleImage.assembleAmplifierRawImage
def assembleAmplifierRawImage(destImage, rawImage, amplifier)
Definition: assembleImage.py:82
lsst::afw::cameraGeom.utils.ButlerImage
Definition: utils.py:397
astshim.fitsChanContinued.contains
def contains(self, name)
Definition: fitsChanContinued.py:127
lsst::afw::cameraGeom.utils.ButlerImage.type
type
Definition: utils.py:431
lsst::pex::exceptions::LengthError
Reports attempts to exceed implementation-defined length limits for some classes.
Definition: Runtime.h:76
lsst::afw::geom::makeFlippedWcs
std::shared_ptr< SkyWcs > makeFlippedWcs(SkyWcs const &wcs, bool flipLR, bool flipTB, lsst::geom::Point2D const &center)
Return a copy of a FITS-WCS with pixel positions flipped around a specified center.
Definition: SkyWcs.cc:472
lsst::log
Definition: Log.h:706
max
int max
Definition: BoundedField.cc:104
lsst::afw::geom::makeSkyWcs
std::shared_ptr< SkyWcs > makeSkyWcs(TransformPoint2ToPoint2 const &pixelsToFieldAngle, lsst::geom::Angle const &orientation, bool flipX, lsst::geom::SpherePoint const &boresight, std::string const &projection="TAN")
Construct a FITS SkyWcs from camera geometry.
Definition: SkyWcs.cc:536
lsst::afw::cameraGeom.utils.FakeImageDataSource.background
background
Definition: utils.py:344
lsst::geom
Definition: AffineTransform.h:36
lsst::afw::cameraGeom.utils.ButlerImage.butler
butler
Definition: utils.py:432
lsst::daf::base
Definition: Utils.h:47
lsst::afw::cameraGeom
Definition: Amplifier.h:33
lsst::afw::fits
Definition: fits.h:31
lsst::afw::cameraGeom.utils.FakeImageDataSource.showAmpGain
showAmpGain
Definition: utils.py:345
lsst::afw::cameraGeom.utils.ButlerImage.getCcdImage
def getCcdImage(self, ccd, imageFactory=afwImage.ImageF, binSize=1, asMaskedImage=False)
Definition: utils.py:451
lsst::afw::cameraGeom.utils.FakeImageDataSource.getCcdImage
def getCcdImage(self, det, imageFactory, binSize)
Definition: utils.py:353
lsst::afw::cameraGeom.utils.FakeImageDataSource.getAmpImage
def getAmpImage(self, amp, imageFactory)
Definition: utils.py:374
lsst::afw::math::rotateImageBy90
std::shared_ptr< ImageT > rotateImageBy90(ImageT const &image, int nQuarter)
Rotate an image by an integral number of quarter turns.
Definition: rotateImage.cc:39
min
int min
Definition: BoundedField.cc:103
lsst::afw::cameraGeom.utils.rawCallback
def rawCallback(im, ccd=None, imageSource=None, correctGain=False, subtractBias=False, convertToFloat=False, obeyNQuarter=True)
Definition: utils.py:513
lsst::afw::math
Definition: statistics.dox:6
lsst::afw::math::binImage
std::shared_ptr< ImageT > binImage(ImageT const &inImage, int const binsize, lsst::afw::math::Property const flags=lsst::afw::math::MEAN)
Definition: binImage.cc:38
lsst::geom::Point< double, 2 >
lsst::afw::cameraGeom.utils.FakeImageDataSource.scaleGain
scaleGain
Definition: utils.py:349
lsst::daf::base::PropertySet
Class for storing generic metadata.
Definition: PropertySet.h:67
lsst::geom::Box2I
An integer coordinate rectangle.
Definition: Box.h:55
lsst::afw::cameraGeom.utils.makeImageFromCcd
def makeImageFromCcd(ccd, isTrimmed=True, showAmpGain=True, imageFactory=afwImage.ImageU, rcMarkSize=10, binSize=1)
Definition: utils.py:264
lsst::pex::exceptions
Definition: Exception.h:37
lsst::afw::cameraGeom.utils.FakeImageDataSource.markSize
markSize
Definition: utils.py:346
lsst::afw::cameraGeom.utils.makeImageFromCamera
def makeImageFromCamera(camera, detectorNameList=None, background=numpy.nan, bufferSize=10, imageSource=FakeImageDataSource(), imageFactory=afwImage.ImageU, binSize=1)
Definition: utils.py:856
lsst::afw::cameraGeom.utils.calcRawCcdBBox
def calcRawCcdBBox(ccd)
Definition: utils.py:242
lsst::geom::Box2D
A floating-point coordinate rectangle geometry.
Definition: Box.h:413
lsst::afw::cameraGeom.utils.FakeImageDataSource.__init__
def __init__(self, isTrimmed=True, verbose=False, background=numpy.nan, showAmpGain=True, markSize=10, markValue=0, ampImValue=None, scaleGain=lambda gain:(gain *1000)//10)
Definition: utils.py:341
lsst::geom::Extent< double, 2 >
lsst::afw::cameraGeom.utils.plotFocalPlane
def plotFocalPlane(camera, fieldSizeDeg_x=0, fieldSizeDeg_y=None, dx=0.1, dy=0.1, figsize=(10., 10.), useIds=False, showFig=True, savePath=None)
Definition: utils.py:86
lsst::afw::cameraGeom.utils.FakeImageDataSource.ampImValue
ampImValue
Definition: utils.py:348
lsst::afw::geom
Definition: frameSetUtils.h:40