LSSTApplications  18.1.0
LSSTDataManagementBasePackage
installGaussianPsf.py
Go to the documentation of this file.
1 #
2 # LSST Data Management System
3 #
4 # Copyright 2008-2017 AURA/LSST.
5 #
6 # This product includes software developed by the
7 # LSST Project (http://www.lsst.org/).
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 LSST License Statement and
20 # the GNU General Public License along with this program. If not,
21 # see <https://www.lsstcorp.org/LegalNotices/>.
22 #
23 __all__ = ["InstallGaussianPsfConfig", "InstallGaussianPsfTask"]
24 
25 import math
26 
27 import lsst.pex.config as pexConfig
28 import lsst.pipe.base as pipeBase
29 from lsst.meas.algorithms import SingleGaussianPsf
30 
31 FwhmPerSigma = 2.0*math.sqrt(2.0*math.log(2.0))
32 
33 
34 class InstallGaussianPsfConfig(pexConfig.Config):
35  """!Config for InstallGaussianPsfTask"""
36  fwhm = pexConfig.Field(
37  dtype=float,
38  default=1.5 * FwhmPerSigma,
39  doc="Estimated FWHM of simple Gaussian PSF model, in pixels. "
40  "Ignored if input exposure has a PSF model."
41  )
42  width = pexConfig.RangeField(
43  dtype=int,
44  doc="Width and height of PSF model, in pixels. Must be odd.",
45  default=11,
46  min=1,
47  )
48 
49  def validate(self):
50  if self.width % 2 == 0:
51  raise RuntimeError("width=%s must be odd" % (self.width,))
52 
53 
54 
60 
61 class InstallGaussianPsfTask(pipeBase.Task):
62  r"""!Install a Gaussian PSF model in an exposure
63 
64  @anchor InstallGaussianPsfTask_
65 
66  @section pipe_tasks_installGaussianPsf_Contents Contents
67 
68  - @ref pipe_tasks_installGaussianPsf_Purpose
69  - @ref pipe_tasks_installGaussianPsf_Initialize
70  - @ref pipe_tasks_installGaussianPsf_IO
71  - @ref pipe_tasks_installGaussianPsf_Config
72  - @ref pipe_tasks_installGaussianPsf_Metadata
73  - @ref pipe_tasks_installGaussianPsf_Debug
74  - @ref pipe_tasks_installGaussianPsf_Example
75 
76  @section pipe_tasks_installGaussianPsf_Purpose Description
77 
78  Install a Gaussian PSF model in an exposure.
79  If the exposure already has a PSF model then the new model
80  has the same sigma and size (width and height in pixels) of the existing model.
81  If the exposure does not have a PSF model then the PSF sigma and size
82  are taken from the config.
83 
84  At present the produced model is always circularly symmetric, but it is planned
85  to change this to an elliptical PSF model (only for the case that the exposure
86  already has a PSF model), once the necessary PSF object is available.
87 
88  A variant of this task may someday exist to estimate the PSF
89  from the pixel data if no PSF model is present.
90 
91  @section pipe_tasks_installGaussianPsf_Initialize Task initialisation
92 
93  @copydoc \_\_init\_\_
94 
95  @section pipe_tasks_installGaussianPsf_IO Invoking the Task
96 
97  The main method is `run`.
98 
99  @section pipe_tasks_installGaussianPsf_Config Configuration parameters
100 
101  See @ref InstallGaussianPsfConfig
102 
103  @section pipe_tasks_installGaussianPsf_Debug Debug variables
104 
105  This task has no debug display
106 
107  @section pipe_tasks_installGaussianPsf_Example A complete example of using InstallGaussianPsfTask
108 
109  from lsst.afw.image import ExposureF
110  from lsst.meas.algorithms.installGaussianPsf import InstallGaussianPsfTask, FwhmPerSigma
111 
112  exposure = ExposureF(100, 100)
113  task = InstallGaussianPsfTask()
114  task.run(exposure=exposure)
115 
116  # This particular exposure had no PSF model to begin with, so the new PSF model
117  # uses the config's FWHM. However, measured FWHM is based on the truncated
118  # PSF image, so it does not exactly match the input
119  measFwhm = exposure.getPsf().computeShape().getDeterminantRadius() * FwhmPerSigma
120  assert abs(measFwhm - task.config.fwhm) < 1e-3
121  """
122  ConfigClass = InstallGaussianPsfConfig
123  _DefaultName = "installSimplePsfModel"
124 
125  def run(self, exposure):
126  """!Set exposure's PSF to a simple PSF model
127 
128  The sigma and width of the new simple PSF model matches the sigma and width of the current model,
129  if any, else the config parameters are used.
130 
131  @param[in,out] exposure exposure to which to replace or add the PSF model
132  """
133  if exposure.hasPsf():
134  psfModel = exposure.getPsf()
135  psfSigma = psfModel.computeShape().getDeterminantRadius()
136  width, height = psfModel.computeImage().getDimensions()
137  else:
138  psfSigma = self.config.fwhm / FwhmPerSigma
139  width = height = self.config.width
140 
141  if psfSigma <= 0:
142  raise RuntimeError("psfSigma = %s <= 0" % (psfSigma,))
143 
144  self.log.debug("installing a simple Gaussian PSF model with width=%s, height=%s, FWHM=%0.3f",
145  width, height, psfSigma*FwhmPerSigma)
146  psfModel = SingleGaussianPsf(width, height, psfSigma)
147  exposure.setPsf(psfModel)
Fit spatial kernel using approximate fluxes for candidates, and solving a linear system of equations...
Represent a PSF as a circularly symmetrical Gaussian.
def run(self, exposure)
Set exposure&#39;s PSF to a simple PSF model.