LSST Applications  21.0.0-172-gfb10e10a+18fedfabac,22.0.0+297cba6710,22.0.0+80564b0ff1,22.0.0+8d77f4f51a,22.0.0+a28f4c53b1,22.0.0+dcf3732eb2,22.0.1-1-g7d6de66+2a20fdde0d,22.0.1-1-g8e32f31+297cba6710,22.0.1-1-geca5380+7fa3b7d9b6,22.0.1-12-g44dc1dc+2a20fdde0d,22.0.1-15-g6a90155+515f58c32b,22.0.1-16-g9282f48+790f5f2caa,22.0.1-2-g92698f7+dcf3732eb2,22.0.1-2-ga9b0f51+7fa3b7d9b6,22.0.1-2-gd1925c9+bf4f0e694f,22.0.1-24-g1ad7a390+a9625a72a8,22.0.1-25-g5bf6245+3ad8ecd50b,22.0.1-25-gb120d7b+8b5510f75f,22.0.1-27-g97737f7+2a20fdde0d,22.0.1-32-gf62ce7b1+aa4237961e,22.0.1-4-g0b3f228+2a20fdde0d,22.0.1-4-g243d05b+871c1b8305,22.0.1-4-g3a563be+32dcf1063f,22.0.1-4-g44f2e3d+9e4ab0f4fa,22.0.1-42-gca6935d93+ba5e5ca3eb,22.0.1-5-g15c806e+85460ae5f3,22.0.1-5-g58711c4+611d128589,22.0.1-5-g75bb458+99c117b92f,22.0.1-6-g1c63a23+7fa3b7d9b6,22.0.1-6-g50866e6+84ff5a128b,22.0.1-6-g8d3140d+720564cf76,22.0.1-6-gd805d02+cc5644f571,22.0.1-8-ge5750ce+85460ae5f3,master-g6e05de7fdc+babf819c66,master-g99da0e417a+8d77f4f51a,w.2021.48
LSST Data Management Base Package
Public Member Functions | Public Attributes | Static Public Attributes | List of all members
lsst.meas.algorithms.measureApCorr.MeasureApCorrTask Class Reference
Inheritance diagram for lsst.meas.algorithms.measureApCorr.MeasureApCorrTask:

Public Member Functions

def __init__ (self, schema, **kwds)
 
def run (self, exposure, catalog)
 

Public Attributes

 refFluxKeys
 
 toCorrect
 

Static Public Attributes

 ConfigClass = MeasureApCorrConfig
 

Detailed Description

Task to measure aperture correction

Definition at line 110 of file measureApCorr.py.

Constructor & Destructor Documentation

◆ __init__()

def lsst.meas.algorithms.measureApCorr.MeasureApCorrTask.__init__ (   self,
  schema,
**  kwds 
)
Construct a MeasureApCorrTask

For every name in lsst.meas.base.getApCorrNameSet():
- If the corresponding flux fields exist in the schema:
    - Add a new field apcorr_{name}_used
    - Add an entry to the self.toCorrect dict
- Otherwise silently skip the name

Definition at line 116 of file measureApCorr.py.

116  def __init__(self, schema, **kwds):
117  """Construct a MeasureApCorrTask
118 
119  For every name in lsst.meas.base.getApCorrNameSet():
120  - If the corresponding flux fields exist in the schema:
121  - Add a new field apcorr_{name}_used
122  - Add an entry to the self.toCorrect dict
123  - Otherwise silently skip the name
124  """
125  Task.__init__(self, **kwds)
126  self.refFluxKeys = FluxKeys(self.config.refFluxName, schema)
127  self.toCorrect = {} # dict of flux field name prefix: FluxKeys instance
128  for name in sorted(getApCorrNameSet()):
129  try:
130  self.toCorrect[name] = FluxKeys(name, schema)
131  except KeyError:
132  # if a field in the registry is missing, just ignore it.
133  pass
134  self.makeSubtask("sourceSelector")
135 

Member Function Documentation

◆ run()

def lsst.meas.algorithms.measureApCorr.MeasureApCorrTask.run (   self,
  exposure,
  catalog 
)
Measure aperture correction

Parameters
----------
exposure : `lsst.afw.image.Exposure`
    Exposure aperture corrections are being measured on. The
    bounding box is retrieved from it, and it is passed to the
    sourceSelector. The output aperture correction map is *not*
    added to the exposure; this is left to the caller.
catalog : `lsst.afw.table.SourceCatalog`
    SourceCatalog containing measurements to be used to
    compute aperture corrections.

Returns
-------
Struct : `lsst.pipe.base.Struct`
    Contains the following:

    ``apCorrMap``
        aperture correction map (`lsst.afw.image.ApCorrMap`)
        that contains two entries for each flux field:
        - flux field (e.g. base_PsfFlux_instFlux): 2d model
        - flux sigma field (e.g. base_PsfFlux_instFluxErr): 2d model of error

Definition at line 136 of file measureApCorr.py.

136  def run(self, exposure, catalog):
137  """Measure aperture correction
138 
139  Parameters
140  ----------
141  exposure : `lsst.afw.image.Exposure`
142  Exposure aperture corrections are being measured on. The
143  bounding box is retrieved from it, and it is passed to the
144  sourceSelector. The output aperture correction map is *not*
145  added to the exposure; this is left to the caller.
146  catalog : `lsst.afw.table.SourceCatalog`
147  SourceCatalog containing measurements to be used to
148  compute aperture corrections.
149 
150  Returns
151  -------
152  Struct : `lsst.pipe.base.Struct`
153  Contains the following:
154 
155  ``apCorrMap``
156  aperture correction map (`lsst.afw.image.ApCorrMap`)
157  that contains two entries for each flux field:
158  - flux field (e.g. base_PsfFlux_instFlux): 2d model
159  - flux sigma field (e.g. base_PsfFlux_instFluxErr): 2d model of error
160  """
161  bbox = exposure.getBBox()
162  import lsstDebug
163  display = lsstDebug.Info(__name__).display
164  doPause = lsstDebug.Info(__name__).doPause
165 
166  self.log.info("Measuring aperture corrections for %d flux fields", len(self.toCorrect))
167  # First, create a subset of the catalog that contains only selected stars
168  # with non-flagged reference fluxes.
169  subset1 = [record for record in self.sourceSelector.run(catalog, exposure=exposure).sourceCat
170  if (not record.get(self.refFluxKeys.flag)
171  and numpy.isfinite(record.get(self.refFluxKeys.flux)))]
172 
173  apCorrMap = ApCorrMap()
174 
175  # Outer loop over the fields we want to correct
176  for name, keys in self.toCorrect.items():
177  fluxName = name + "_instFlux"
178  fluxErrName = name + "_instFluxErr"
179 
180  # Create a more restricted subset with only the objects where the to-be-correct flux
181  # is not flagged.
182  fluxes = numpy.fromiter((record.get(keys.flux) for record in subset1), float)
183  with numpy.errstate(invalid="ignore"): # suppress NAN warnings
184  isGood = numpy.logical_and.reduce([
185  numpy.fromiter((not record.get(keys.flag) for record in subset1), bool),
186  numpy.isfinite(fluxes),
187  fluxes > 0.0,
188  ])
189  subset2 = [record for record, good in zip(subset1, isGood) if good]
190 
191  # Check that we have enough data points that we have at least the minimum of degrees of
192  # freedom specified in the config.
193  if len(subset2) - 1 < self.config.minDegreesOfFreedom:
194  if name in self.config.allowFailure:
195  self.log.warning("Unable to measure aperture correction for '%s': "
196  "only %d sources, but require at least %d.",
197  name, len(subset2), self.config.minDegreesOfFreedom + 1)
198  continue
199  raise RuntimeError("Unable to measure aperture correction for required algorithm '%s': "
200  "only %d sources, but require at least %d." %
201  (name, len(subset2), self.config.minDegreesOfFreedom + 1))
202 
203  # If we don't have enough data points to constrain the fit, reduce the order until we do
204  ctrl = self.config.fitConfig.makeControl()
205  while len(subset2) - ctrl.computeSize() < self.config.minDegreesOfFreedom:
206  if ctrl.orderX > 0:
207  ctrl.orderX -= 1
208  if ctrl.orderY > 0:
209  ctrl.orderY -= 1
210 
211  # Fill numpy arrays with positions and the ratio of the reference flux to the to-correct flux
212  x = numpy.zeros(len(subset2), dtype=float)
213  y = numpy.zeros(len(subset2), dtype=float)
214  apCorrData = numpy.zeros(len(subset2), dtype=float)
215  indices = numpy.arange(len(subset2), dtype=int)
216  for n, record in enumerate(subset2):
217  x[n] = record.getX()
218  y[n] = record.getY()
219  apCorrData[n] = record.get(self.refFluxKeys.flux)/record.get(keys.flux)
220 
221  for _i in range(self.config.numIter):
222 
223  # Do the fit, save it in the output map
224  apCorrField = ChebyshevBoundedField.fit(bbox, x, y, apCorrData, ctrl)
225 
226  if display:
227  plotApCorr(bbox, x, y, apCorrData, apCorrField, "%s, iteration %d" % (name, _i), doPause)
228 
229  # Compute errors empirically, using the RMS difference between the true reference flux and the
230  # corrected to-be-corrected flux.
231  apCorrDiffs = apCorrField.evaluate(x, y)
232  apCorrDiffs -= apCorrData
233  apCorrErr = numpy.mean(apCorrDiffs**2)**0.5
234 
235  # Clip bad data points
236  apCorrDiffLim = self.config.numSigmaClip * apCorrErr
237  with numpy.errstate(invalid="ignore"): # suppress NAN warning
238  keep = numpy.fabs(apCorrDiffs) <= apCorrDiffLim
239  x = x[keep]
240  y = y[keep]
241  apCorrData = apCorrData[keep]
242  indices = indices[keep]
243 
244  # Final fit after clipping
245  apCorrField = ChebyshevBoundedField.fit(bbox, x, y, apCorrData, ctrl)
246 
247  self.log.info("Aperture correction for %s: RMS %f from %d",
248  name, numpy.mean((apCorrField.evaluate(x, y) - apCorrData)**2)**0.5, len(indices))
249 
250  if display:
251  plotApCorr(bbox, x, y, apCorrData, apCorrField, "%s, final" % (name,), doPause)
252 
253  # Save the result in the output map
254  # The error is constant spatially (we could imagine being
255  # more clever, but we're not yet sure if it's worth the effort).
256  # We save the errors as a 0th-order ChebyshevBoundedField
257  apCorrMap[fluxName] = apCorrField
258  apCorrErrCoefficients = numpy.array([[apCorrErr]], dtype=float)
259  apCorrMap[fluxErrName] = ChebyshevBoundedField(bbox, apCorrErrCoefficients)
260 
261  # Record which sources were used
262  for i in indices:
263  subset2[i].set(keys.used, True)
264 
265  return Struct(
266  apCorrMap=apCorrMap,
267  )
268 
269 
std::vector< SchemaItem< Flag > > * items
daf::base::PropertySet * set
Definition: fits.cc:912
def run(self, coaddExposures, bbox, wcs)
Definition: getTemplate.py:603
def plotApCorr(bbox, xx, yy, zzMeasure, field, title, doPause)

Member Data Documentation

◆ ConfigClass

lsst.meas.algorithms.measureApCorr.MeasureApCorrTask.ConfigClass = MeasureApCorrConfig
static

Definition at line 113 of file measureApCorr.py.

◆ refFluxKeys

lsst.meas.algorithms.measureApCorr.MeasureApCorrTask.refFluxKeys

Definition at line 126 of file measureApCorr.py.

◆ toCorrect

lsst.meas.algorithms.measureApCorr.MeasureApCorrTask.toCorrect

Definition at line 127 of file measureApCorr.py.


The documentation for this class was generated from the following file: