/usr/lib/python3/dist-packages/photutils/aperture/mask.py is in python3-photutils 0.4-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 | # Licensed under a 3-clause BSD style license - see LICENSE.rst
from __future__ import (absolute_import, division, print_function,
unicode_literals)
import numpy as np
import astropy.units as u
__all__ = ['ApertureMask']
class ApertureMask(object):
"""
Class for an aperture mask.
Parameters
----------
mask : array_like
A 2D array of an aperture mask representing the fractional
overlap of the aperture on the pixel grid. This should be the
full-sized (i.e. not truncated) array that is the direct output
of one of the low-level `photutils.geometry` functions.
bbox : `photutils.BoundingBox`
The bounding box object defining the aperture minimal bounding
box.
"""
def __init__(self, data, bbox):
self.data = np.asanyarray(data)
if self.data.shape != bbox.shape:
raise ValueError('mask data and bounding box must have the same '
'shape')
self.bbox = bbox
def __array__(self):
"""
Array representation of the mask data array (e.g., for matplotlib).
"""
return self.data
@property
def shape(self):
"""
The shape of the mask data array.
"""
return self.data.shape
def _overlap_slices(self, shape):
"""
Calculate the slices for the overlapping part of the bounding
box and an array of the given shape.
Parameters
----------
shape : tuple of int
The ``(ny, nx)`` shape of array where the slices are to be
applied.
Returns
-------
slices_large : tuple of slices
A tuple of slice objects for each axis of the large array,
such that ``large_array[slices_large]`` extracts the region
of the large array that overlaps with the small array.
slices_small : slice
A tuple of slice objects for each axis of the small array,
such that ``small_array[slices_small]`` extracts the region
of the small array that is inside the large array.
"""
if len(shape) != 2:
raise ValueError('input shape must have 2 elements.')
xmin = self.bbox.ixmin
xmax = self.bbox.ixmax
ymin = self.bbox.iymin
ymax = self.bbox.iymax
if xmin >= shape[1] or ymin >= shape[0] or xmax <= 0 or ymax <= 0:
# no overlap of the aperture with the data
return None, None
slices_large = (slice(max(ymin, 0), min(ymax, shape[0])),
slice(max(xmin, 0), min(xmax, shape[1])))
slices_small = (slice(max(-ymin, 0),
min(ymax - ymin, shape[0] - ymin)),
slice(max(-xmin, 0),
min(xmax - xmin, shape[1] - xmin)))
return slices_large, slices_small
def to_image(self, shape):
"""
Return an image of the mask in a 2D array of the given shape,
taking any edge effects into account.
Parameters
----------
shape : tuple of int
The ``(ny, nx)`` shape of the output array.
Returns
-------
result : `~numpy.ndarray`
A 2D array of the mask.
"""
if len(shape) != 2:
raise ValueError('input shape must have 2 elements.')
mask = np.zeros(shape)
try:
mask[self.bbox.slices] = self.data
except ValueError: # partial or no overlap
slices_large, slices_small = self._overlap_slices(shape)
if slices_small is None:
return None # no overlap
mask = np.zeros(shape)
mask[slices_large] = self.data[slices_small]
return mask
def cutout(self, data, fill_value=0.):
"""
Create a cutout from the input data over the mask bounding box,
taking any edge effects into account.
Parameters
----------
data : array_like or `~astropy.units.Quantity`
A 2D array on which to apply the aperture mask.
fill_value : float, optional
The value is used to fill pixels where the aperture mask
does not overlap with the input ``data``. The default is 0.
Returns
-------
result : `~numpy.ndarray`
A 2D array cut out from the input ``data`` representing the
same cutout region as the aperture mask. If there is a
partial overlap of the aperture mask with the input data,
pixels outside of the data will be assigned to
``fill_value``. `None` is returned if there is no overlap
of the aperture with the input ``data``.
"""
data = np.asanyarray(data)
cutout = data[self.bbox.slices]
if cutout.shape != self.shape:
slices_large, slices_small = self._overlap_slices(data.shape)
if slices_small is None:
return None # no overlap
cutout = np.zeros(self.shape, dtype=data.dtype)
cutout[:] = fill_value
cutout[slices_small] = data[slices_large]
if isinstance(data, u.Quantity):
cutout = u.Quantity(cutout, unit=data.unit)
return cutout
def multiply(self, data, fill_value=0.):
"""
Multiply the aperture mask with the input data, taking any edge
effects into account.
The result is a mask-weighted cutout from the data.
Parameters
----------
data : array_like or `~astropy.units.Quantity`
The 2D array to multiply with the aperture mask.
fill_value : float, optional
The value is used to fill pixels where the aperture mask
does not overlap with the input ``data``. The default is 0.
Returns
-------
result : `~numpy.ndarray`
A 2D mask-weighted cutout from the input ``data``. If there
is a partial overlap of the aperture mask with the input
data, pixels outside of the data will be assigned to
``fill_value`` before being multipled with the mask. `None`
is returned if there is no overlap of the aperture with the
input ``data``.
"""
return self.cutout(data, fill_value=fill_value) * self.data
|