24 from deprecated.sphinx 
import deprecated
 
   28 from .rgb 
import replaceSaturatedPixels, getZScale
 
   32     """Return a naive total intensity from the red, blue, and green intensities 
   36     imageR : `lsst.afw.image.MaskedImage`, `lsst.afw.image.Image`, or `numpy.ndarray`, (Nx, Ny) 
   37         intensity of image that'll be mapped to red; or intensity if imageG and imageB are None 
   38     imageG : `lsst.afw.image.MaskedImage`, `lsst.afw.image.Image`, or `numpy.ndarray`, (Nx, Ny) 
   39         intensity of image that'll be mapped to green; or None 
   40     imageB : `lsst.afw.image.MaskedImage`, `lsst.afw.image.Image`, or `numpy.ndarray`, (Nx, Ny) 
   41         intensity of image that'll be mapped to blue; or None 
   45     image : type of ``imageR``, ``imageG``, and `imageB`` 
   47     if imageG 
is None or imageB 
is None:
 
   48         assert imageG 
is None and imageB 
is None, \
 
   49             "Please specify either a single image or red, green, and blue images" 
   52     imageRGB = [imageR, imageG, imageB]
 
   54     for i, c 
in enumerate(imageRGB):
 
   55         if hasattr(c, 
"getImage"):
 
   56             c = imageRGB[i] = c.getImage()
 
   57         if hasattr(c, 
"getArray"):
 
   58             imageRGB[i] = c.getArray()
 
   60     intensity = (imageRGB[0] + imageRGB[1] + imageRGB[2])/float(3)
 
   64     Image = afwImage.ImageU 
if intensity.dtype == 
'uint16' else afwImage.ImageF
 
   66     if hasattr(imageR, 
"getImage"):  
 
   68     elif hasattr(imageR, 
"getArray"):
 
   69         intensity = Image(intensity)
 
   75     """Base class to map red, blue, green intensities into uint8 values 
   79     minimum : `float` or sequence of `float` 
   80         Intensity that should be mapped to black. If an array, has three 
   83         The image to be used to calculate the mapping. 
   84         If provided, also the default for makeRgbImage() 
   88         self.
_uint8Max = float(np.iinfo(np.uint8).max)
 
   94         assert len(minimum) == 3, 
"Please provide 1 or 3 values for minimum" 
  100                      xSize=None, ySize=None, rescaleFactor=None):
 
  101         """Convert 3 arrays, imageR, imageG, and imageB into a numpy RGB image 
  103         imageR : `lsst.afw.image.Image` or `numpy.ndarray`, (Nx, Ny) 
  104             Image to map to red (if `None`, use the image passed to the ctor) 
  105         imageG : `lsst.afw.image.Image` or `numpy.ndarray`, (Nx, Ny), optional 
  106             Image to map to green (if `None`, use imageR) 
  107         imageB : `lsst.afw.image.Image` or `numpy.ndarray`, (Nx, Ny), optional 
  108             Image to map to blue (if `None`, use imageR) 
  109         xSize : `int`, optional 
  110             Desired width of RGB image. If ``ySize`` is `None`, preserve aspect ratio 
  111         ySize : `int`, optional 
  112             Desired height of RGB image 
  113         rescaleFactor : `float`, optional 
  114             Make size of output image ``rescaleFactor*size`` of the input image 
  119                     "You must provide an image (or pass one to the constructor)")
 
  127         imageRGB = [imageR, imageG, imageB]
 
  128         for i, c 
in enumerate(imageRGB):
 
  129             if hasattr(c, 
"getImage"):
 
  130                 c = imageRGB[i] = c.getImage()
 
  131             if hasattr(c, 
"getArray"):
 
  132                 imageRGB[i] = c.getArray()
 
  134         if xSize 
is not None or ySize 
is not None:
 
  135             assert rescaleFactor 
is None, 
"You may not specify a size and rescaleFactor" 
  136             h, w = imageRGB[0].shape
 
  138                 ySize = int(xSize*h/float(w) + 0.5)
 
  140                 xSize = int(ySize*w/float(h) + 0.5)
 
  142             size = (ySize, xSize)  
 
  143         elif rescaleFactor 
is not None:
 
  144             size = float(rescaleFactor)  
 
  151             except ImportError 
as e:
 
  153                     f
"Unable to rescale as scipy.misc is unavailable: {e}")
 
  155             for i, im 
in enumerate(imageRGB):
 
  156                 imageRGB[i] = scipy.misc.imresize(
 
  157                     im, size, interp=
'bilinear', mode=
'F')
 
  162         """Return the total intensity from the red, blue, and green intensities 
  166         This is a naive computation, and may be overridden by subclasses 
  171         """Map an intensity into the range of a uint8, [0, 255] (but not converted to uint8) 
  173         with np.errstate(invalid=
'ignore', divide=
'ignore'):  
 
  174             return np.where(intensity <= 0, 0,
 
  177     def _convertImagesToUint8(self, imageR, imageG, imageB):
 
  178         """Use the mapping to convert images imageR, imageG, and imageB to a triplet of uint8 images 
  180         imageR = imageR - self.
minimum[0]  
 
  181         imageG = imageG - self.
minimum[1]
 
  182         imageB = imageB - self.
minimum[2]
 
  186         imageRGB = [imageR, imageG, imageB]
 
  187         with np.errstate(invalid=
"ignore"):  
 
  195         r0, g0, b0 = imageRGB
 
  198         with np.errstate(invalid=
'ignore', divide=
'ignore'):
 
  199             for i, c 
in enumerate(imageRGB):
 
  200                 c = np.where(r0 > g0,
 
  202                                       np.where(r0 >= pixmax, c*pixmax/r0, c),
 
  203                                       np.where(b0 >= pixmax, c*pixmax/b0, c)),
 
  205                                       np.where(g0 >= pixmax, c*pixmax/g0, c),
 
  206                                       np.where(b0 >= pixmax, c*pixmax/b0, c))).astype(np.uint8)
 
  207                 c[c > pixmax] = pixmax
 
  215     """A linear map of red, blue, green intensities into uint8 values 
  219     minimum : `float` or sequence of `float` 
  220         Intensity that should be mapped to black. If an array, has three 
  221         elements for R, G, B. 
  223         Intensity that should be mapped to white 
  225         Image to estimate minimum/maximum if not explicitly set 
  228     def __init__(self, minimum=None, maximum=None, image=None):
 
  229         if minimum 
is None or maximum 
is None:
 
  230             assert image 
is not None, 
"You must provide an image if you don't set both minimum and maximum" 
  234                 minimum = stats.getValue(afwMath.MIN)
 
  236                 maximum = stats.getValue(afwMath.MAX)
 
  238         Mapping.__init__(self, minimum, image)
 
  244             assert maximum - minimum != 0, 
"minimum and maximum values must not be equal" 
  245             self.
_range = float(maximum - minimum)
 
  248         """Return an array which, when multiplied by an image, returns that 
  249         image mapped to the range of a uint8, [0, 255] (but not converted to uint8) 
  251         The intensity is assumed to have had ``minimum`` subtracted (as that 
  252         can be done per-band) 
  254         with np.errstate(invalid=
'ignore', divide=
'ignore'):  
 
  255             return np.where(intensity <= 0, 0,
 
  256                             np.where(intensity >= self.
_range,
 
  261     """A mapping for a linear stretch chosen by the zscale algorithm 
  262     (preserving colours independent of brightness) 
  264     x = (I - minimum)/range 
  269         Image whose parameters are desired 
  271         The number of samples to use to estimate the zscale parameters 
  275     def __init__(self, image, nSamples=1000, contrast=0.25):
 
  276         if not hasattr(image, 
"getArray"):
 
  277             image = afwImage.ImageF(image)
 
  278         z1, z2 = 
getZScale(image, nSamples, contrast)
 
  280         LinearMapping.__init__(self, z1, z2, image)
 
  284     """A mapping for an asinh stretch (preserving colours independent of brightness) 
  286     x = asinh(Q (I - minimum)/range)/Q 
  290     This reduces to a linear stretch if Q == 0 
  292     See http://adsabs.harvard.edu/abs/2004PASP..116..133L 
  296         Mapping.__init__(self, minimum)
 
  313         self.
_soften = Q/float(dataRange)
 
  316         """Return an array which, when multiplied by an image, returns that image mapped to the range of a 
  317         uint8, [0, 255] (but not converted to uint8) 
  319         The intensity is assumed to have had minimum subtracted (as that can be done per-band) 
  321         with np.errstate(invalid=
'ignore', divide=
'ignore'):  
 
  322             return np.where(intensity <= 0, 0, np.arcsinh(intensity*self.
_soften)*self.
_slope/intensity)
 
  326     """A mapping for an asinh stretch, estimating the linear stretch by zscale 
  328     x = asinh(Q (I - z1)/(z2 - z1))/Q 
  333         The image to analyse, or a list of 3 images to be converted to an intensity image 
  335         The asinh softening parameter 
  336     pedestal : `float` or sequence of `float`, optional 
  337         The value, or array of 3 values, to subtract from the images 
  339         N.b. pedestal, if not None, is removed from the images when calculating the zscale 
  340         stretch, and added back into Mapping.minimum[] 
  349             assert len(image) 
in (1, 3,), 
"Please provide 1 or 3 images" 
  353         if pedestal 
is not None:
 
  355                 assert len(pedestal) 
in (
 
  356                     1, 3,), 
"Please provide 1 or 3 pedestals" 
  358                 pedestal = 3*[pedestal]
 
  361             for i, im 
in enumerate(image):
 
  362                 if pedestal[i] != 0.0:
 
  363                     if hasattr(im, 
"getImage"):
 
  365                     if hasattr(im, 
"getArray"):
 
  368                     image[i] = im - pedestal[i]  
 
  370             pedestal = len(image)*[0.0]
 
  376         dataRange = zscale.maximum - zscale.minimum[0]
 
  377         minimum = zscale.minimum
 
  379         for i, level 
in enumerate(pedestal):
 
  382         AsinhMapping.__init__(self, minimum, dataRange, Q)
 
  386 def makeRGB(imageR, imageG=None, imageB=None, minimum=0, dataRange=5, Q=8, fileName=None,
 
  387             saturatedBorderWidth=0, saturatedPixelValue=None,
 
  388             xSize=None, ySize=None, rescaleFactor=None):
 
  389     """Make a set of three images into an RGB image using an asinh stretch and 
  390     optionally write it to disk 
  397     minimum : `float` or sequence of `float` 
  401         The output file. The suffix defines the format, and must be supported by matplotlib 
  403         If saturatedBorderWidth is non-zero, replace saturated pixels with 
  404         ``saturatedPixelValue``. Note that replacing saturated pixels requires 
  405         that the input images be `lsst.afw.image.MaskedImage`. 
  416     if saturatedBorderWidth:
 
  417         if saturatedPixelValue 
is None:
 
  419                 "saturatedPixelValue must be set if saturatedBorderWidth is set")
 
  421                                saturatedBorderWidth, saturatedPixelValue)
 
  424     rgb = asinhMap.makeRgbImage(imageR, imageG, imageB,
 
  425                                 xSize=xSize, ySize=ySize, rescaleFactor=rescaleFactor)
 
  434     """Display an rgb image using matplotlib 
  439         The RGB image in question 
  441         If `True`, call `matplotlib.pyplot.show()` 
  443     import matplotlib.pyplot 
as plt
 
  444     plt.imshow(rgb, interpolation=
'nearest', origin=
"lower")
 
  451     """Write an RGB image to disk 
  456         The output file. The suffix defines the format, and must be supported by matplotlib 
  458         Most versions of matplotlib support png and pdf (although the eps/pdf/svg writers may be buggy, 
  459         possibly due an interaction with useTeX=True in the matplotlib settings). 
  461         If your matplotlib bundles pil/pillow you should also be able to write jpeg and tiff files. 
  463         The image, as made by e.g. makeRGB 
  465     import matplotlib.image
 
  466     matplotlib.image.imsave(fileName, rgbImage)
 
  473 @deprecated(reason=
"Use `AsinhMapping` instead. To be removed after 20.0.0.",
 
  474             category=FutureWarning)  
 
  476     """Deprecated object used to support legacy API 
  486     """Deprecated object used to support legacy API 
  489     def __init__(self, imageR, imageG, imageB, mapping):
 
  490         asinh = 
AsinhMapping(mapping.minimum, mapping.dataRange, mapping.Q)
 
  491         self.
rgb = asinh.makeRgbImage(imageR, imageG, imageB)
 
  498     reason=
"Use `Mapping.makeRgbImage` instead. To be removed after 20.0.0.",
 
  499     category=FutureWarning)
 
  501     """Deprecated legacy API 
  503     return _RgbImageF(imageR, imageG, imageB, mapping)