lsst.ip.isr g7ad7012e6f+f269f3cbf4
Loading...
Searching...
No Matches
masking.py
Go to the documentation of this file.
1# This file is part of ip_isr.
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# import os
22
23__all__ = ["MaskingConfig", "MaskingTask", "DECamEdgeBleedMaskConfig", "DECamEdgeBleedMaskTask"]
24
25from lsst.pex.config import Config, Field
26from lsst.pipe.base import Task
27
28from . import isrFunctions
29
30
31class MaskingConfig(Config):
32 doSpecificMasking = Field(
33 dtype=bool,
34 doc="Masking configuration.",
35 default=False,
36 )
37
38
39class MaskingTask(Task):
40 """Perform extra masking for detector issues such as ghosts and glints.
41 """
42 ConfigClass = MaskingConfig
43 _DefaultName = "isrMasking"
44
45 def run(self, exposure):
46 """Mask a known bad region of an exposure.
47
48 Parameters
49 ----------
50 exposure : `lsst.afw.image.Exposure`
51 Exposure to construct detector-specific masks for.
52
53 Returns
54 -------
55 status : scalar
56 This task is currently not implemented, and should be
57 retargeted by a camera specific version.
58 """
59 return
60
61
62class DECamEdgeBleedMaskConfig(Config):
63 satMinArea = Field(
64 dtype=int,
65 doc="Minimum area (pixels) of a saturated footprint to be considered.",
66 default=10000,
67 )
68 approachRows = Field(
69 dtype=int,
70 doc=("A saturated footprint must come within this many rows of the read edge to trigger the "
71 "edge bleed check."),
72 default=20,
73 )
74 nSigma = Field(
75 dtype=float,
76 doc="A pixel is \"low\" if it is more than this many sigma below sky.",
77 default=5.0,
78 )
79 nRowsCheck = Field(
80 dtype=int,
81 doc="Number of rows from the read edge to check for an edge bleed dip.",
82 default=20,
83 )
84 nRowsCheckShort = Field(
85 dtype=int,
86 doc="A second, shorter window from the read edge to check for a short edge bleed dip.",
87 default=5,
88 )
89 minUsablePixelsPerRow = Field(
90 dtype=int,
91 doc=("Minimum number of pixels not saturated, bad or missing to search for dips. "
92 "Rows with fewer pixels may be \"blocked\" due to a drained register."),
93 default=30,
94 )
95 minLowFraction = Field(
96 dtype=float,
97 doc=("Mean fraction of usable pixels that are low, over either nRowsCheck or nRowsCheckShort, "
98 "to confirm a dip."),
99 default=0.03,
100 )
101 minLowFractionExtent = Field(
102 dtype=float,
103 doc=("Fraction of usable pixels that are low that each row must exceed to count toward the "
104 "bleed height; the scan stops after five consecutive rows that do not. "
105 "Should not exceed minLowFraction."),
106 default=0.01,
107 )
108 minBlockedRows = Field(
109 dtype=int,
110 doc="Minimum number of blocked rows beyond the normal border at the read edge to be masked if found.",
111 default=5,
112 )
113 marginFraction = Field(
114 dtype=float,
115 doc=("Extra rows masked beyond the measured height, as a fraction of that height "
116 "(plus one row)."),
117 default=0.125,
118 )
119 saturatedMaskName = Field(
120 dtype=str,
121 doc="Name of mask plane holding saturated pixels; must match the parent ISR task.",
122 default="SAT",
123 )
124
125 def validate(self):
126 super().validate()
127 if not 0.0 < self.minLowFraction < 1.0 or not 0.0 < self.minLowFractionExtent < 1.0:
128 raise ValueError("minLowFraction and minLowFractionExtent must be between 0 and 1.")
130 raise ValueError("minLowFractionExtent must not exceed minLowFraction.")
131
132
134 """Mask DECam-style edge bleeds: depressed rows next to the read register
135 below a large saturated star.
136
137 Intended as a retarget for ``IsrTaskConfig.masking`` (enabled with
138 ``doCameraSpecificMasking``). Must run after saturation masking.
139 """
140 ConfigClass = DECamEdgeBleedMaskConfig
141 _DefaultName = "decamEdgeBleedMask"
142
143 def run(self, exposure):
144 """Mask edge bleeds in every amplifier of an exposure.
145
146 Parameters
147 ----------
148 exposure : `lsst.afw.image.Exposure`
149 Assembled exposure with saturation already masked. The mask
150 plane is modified in place.
151 """
152 isrFunctions.maskDECamEdgeBleed(
153 exposure,
154 satMinArea=self.config.satMinArea,
155 approachRows=self.config.approachRows,
156 nSigma=self.config.nSigma,
157 nRowsCheck=self.config.nRowsCheck,
158 nRowsCheckShort=self.config.nRowsCheckShort,
159 minUsablePixelsPerRow=self.config.minUsablePixelsPerRow,
160 minLowFraction=self.config.minLowFraction,
161 minLowFractionExtent=self.config.minLowFractionExtent,
162 minBlockedRows=self.config.minBlockedRows,
163 marginFraction=self.config.marginFraction,
164 saturatedMaskName=self.config.saturatedMaskName,
165 log=self.log,
166 )