32__all__ = (
'VignetteConfig',
'VignetteTask',
'setValidPolygonCcdIntersect',
33 'maskVignettedRegion')
37 """Settings to define vignetting pattern.
41 doc="Center of vignetting pattern, in focal plane x coordinates.",
46 doc=
"Center of vignetting pattern, in focal plane y coordinates.",
51 doc=
"Radius of vignetting pattern, in focal plane coordinates.",
53 check=
lambda x: x >= 0
57 doc=
"Number of points used to define the vignette polygon.",
62 doc=
"Persist polygon used to define vignetted region?",
64 deprecated=(
"Vignetted polygon is added to the exposure by default."
65 " This option is no longer used, and will be removed after v24.")
70 """Define a simple circular vignette pattern and optionally update mask
73 ConfigClass = VignetteConfig
74 _DefaultName = "isrVignette"
76 def run(self, exposure=None, doUpdateMask=True, maskPlane="NO_DATA", vignetteValue=None, log=None):
77 """Generate circular vignette pattern.
82 Exposure to construct, apply, and optionally mask vignette
for.
83 doUpdateMask : `bool`, optional
84 If true, the mask will be updated to mask the vignetted region.
85 maskPlane : `str`, optional
86 Mask plane to assign vignetted pixels to.
87 vignetteValue : `float`
or `
None`, optional
88 Value to assign to the image array pixels within the ``polygon``
89 region. If `
None`, image pixel values are
not replaced.
90 log : `logging.Logger`, optional
91 Log object to write to.
96 Polygon defining the boundary of the vignetted region.
98 theta = np.linspace(0, 2*np.pi, num=self.config.numPolygonPoints, endpoint=False)
99 x = self.config.radius*np.cos(theta) + self.config.xCenter
100 y = self.config.radius*np.sin(theta) + self.config.yCenter
101 points = np.array([x, y]).transpose()
111 polygon = exposure.getInfo().getValidPolygon()
112 maskVignettedRegion(exposure, polygon, maskPlane=
"NO_DATA", vignetteValue=vignetteValue, log=log)
117 """Set valid polygon on ccdExposure associated with focal plane polygon.
119 The ccd exposure's valid polygon is the intersection of fpPolygon,
120 a valid polygon in focal plane coordinates,
and the ccd corners,
121 in ccd pixel coordinates.
128 Polygon
in focal plane coordinates.
129 log : `logging.Logger`, optional
130 Log object to write to.
133 ccd = ccdExposure.getDetector()
134 fpCorners = ccd.getCorners(cameraGeom.FOCAL_PLANE)
138 intersect = ccdPolygon.intersectionSingle(fpPolygon)
141 if intersect
is not None:
143 ccdPoints = ccd.transform(intersect, cameraGeom.FOCAL_PLANE, cameraGeom.PIXELS)
145 ccdExposure.getInfo().setValidPolygon(validPolygon)
148 log.info(
"Ccd exposure does not overlap with focal plane polygon. Not setting validPolygon.")
152 """Add mask bit to image pixels according to vignetted polygon region.
154 NOTE: this function could be used to mask and replace pixels associated
155 with any polygon
in the exposure pixel coordinates.
160 Image whose mask plane
is to be updated.
162 Polygon region defining the vignetted region
in the pixel coordinates
164 maskPlane : `str`, optional
165 Mask plane to assign vignetted pixels to.
166 vignetteValue : `float`
or `
None`, optional
167 Value to assign to the image array pixels within the ``polygon``
168 region. If `
None`, image pixel values are
not replaced.
169 log : `logging.Logger`, optional
170 Log object to write to.
175 Raised
if no valid polygon exists.
177 log = log if log
else logging.getLogger(__name__)
179 log.info(
"No polygon provided. Masking nothing.")
182 fullyIlluminated =
True
183 for corner
in exposure.getBBox().getCorners():
185 fullyIlluminated =
False
186 log.info(
"Exposure is fully illuminated? %s", fullyIlluminated)
188 if not fullyIlluminated:
190 mask = exposure.getMask()
191 numPixels = mask.getBBox().getArea()
192 xx, yy = np.meshgrid(np.arange(0, mask.getWidth(), dtype=int),
193 np.arange(0, mask.getHeight(), dtype=int))
195 vignMask = np.array([
not polygon.contains(
geom.Point2D(x, y))
for x, y
in
196 zip(xx.reshape(numPixels), yy.reshape(numPixels))])
197 vignMask = vignMask.reshape(mask.getHeight(), mask.getWidth())
199 bitMask = mask.getPlaneBitMask(maskPlane)
200 maskArray = mask.getArray()
201 maskArray[vignMask] |= bitMask
202 log.info(
"Exposure contains {} vignetted pixels which are now masked with mask plane {}.".
203 format(np.count_nonzero(vignMask), maskPlane))
205 if vignetteValue
is not None:
206 imageArray = exposure.getImage().getArray()
207 imageArray[vignMask] = vignetteValue
208 log.info(
"Vignetted pixels in image array have been replaced with {}.".
format(vignetteValue))
An exception that indicates the single-polygon assumption has been violated.
A class to contain the data, WCS, and other information needed to describe an image of the sky.
def run(self, exposure=None, doUpdateMask=True, maskPlane="NO_DATA", vignetteValue=None, log=None)
def maskVignettedRegion(exposure, polygon, maskPlane="NO_DATA", vignetteValue=None, log=None)
def setValidPolygonCcdIntersect(ccdExposure, fpPolygon, log=None)
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)