LSSTApplications  17.0+124,17.0+14,17.0+73,18.0.0+37,18.0.0+80,18.0.0-4-g68ffd23+4,18.1.0-1-g0001055+12,18.1.0-1-g03d53ef+5,18.1.0-1-g1349e88+55,18.1.0-1-g2505f39+44,18.1.0-1-g5315e5e+4,18.1.0-1-g5e4b7ea+14,18.1.0-1-g7e8fceb+4,18.1.0-1-g85f8cd4+48,18.1.0-1-g8ff0b9f+4,18.1.0-1-ga2c679d+1,18.1.0-1-gd55f500+35,18.1.0-10-gb58edde+2,18.1.0-11-g0997b02+4,18.1.0-13-gfe4edf0b+12,18.1.0-14-g259bd21+21,18.1.0-19-gdb69f3f+2,18.1.0-2-g5f9922c+24,18.1.0-2-gd3b74e5+11,18.1.0-2-gfbf3545+32,18.1.0-26-g728bddb4+5,18.1.0-27-g6ff7ca9+2,18.1.0-3-g52aa583+25,18.1.0-3-g8ea57af+9,18.1.0-3-gb69f684+42,18.1.0-3-gfcaddf3+6,18.1.0-32-gd8786685a,18.1.0-4-gf3f9b77+6,18.1.0-5-g1dd662b+2,18.1.0-5-g6dbcb01+41,18.1.0-6-gae77429+3,18.1.0-7-g9d75d83+9,18.1.0-7-gae09a6d+30,18.1.0-9-gc381ef5+4,w.2019.45
LSSTDataManagementBasePackage
gaussianPsfFactory.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 
24 __all__ = ["GaussianPsfFactory", "SigmaPerFwhm"]
25 
26 import math
27 
28 from lsst.pex.config import Config, Field, ConfigurableField
29 from .singleGaussianPsf import SingleGaussianPsf
30 from .doubleGaussianPsf import DoubleGaussianPsf
31 
32 SigmaPerFwhm = 1.0 / (2.0 * math.sqrt(2.0 * math.log(2.0)))
33 
34 
35 def isPositive(x):
36  return x > 0
37 
38 
39 class GaussianPsfFactory(Config):
40  """Factory for simple Gaussian PSF models
41 
42  Provides a high-level interface to DoubleGaussianPsf and SingleGaussianPsf
43  by specifying Gaussian PSF model width in FWHM instead of sigma,
44  and supporting computing kernel size as a multiple of PSF width.
45  This makes it suitable for tasks where PSF width is not known in advance.
46  """
47  size = Field(
48  doc="Kernel size (width and height) (pixels); if None then sizeFactor is used",
49  dtype=int,
50  optional=True,
51  default=None,
52  check=isPositive,
53  )
54  sizeFactor = Field(
55  doc="Kernel size as a factor of fwhm (dimensionless); "
56  "size = sizeFactor * fwhm; ignored if size is not None",
57  dtype=float,
58  optional=False,
59  default=3.0,
60  check=isPositive,
61  )
62  minSize = Field(
63  doc="Minimum kernel size if using sizeFactor (pixels); ignored if size is not None",
64  dtype=int,
65  optional=True,
66  default=5,
67  check=isPositive,
68  )
69  maxSize = Field(
70  doc="Maximum kernel size if using sizeFactor (pixels); ignored if size is not None",
71  dtype=int,
72  optional=True,
73  default=None,
74  check=isPositive,
75  )
76  defaultFwhm = Field(
77  doc="Default FWHM of Gaussian model of core of star (pixels)",
78  dtype=float,
79  default=3.0,
80  check=isPositive,
81  )
82  addWing = Field(
83  doc="Add a Gaussian to represent wings?",
84  dtype=bool,
85  optional=False,
86  default=True,
87  )
88  wingFwhmFactor = Field(
89  doc="wing width, as a multiple of core width (dimensionless); ignored if addWing false",
90  dtype=float,
91  optional=False,
92  default=2.5,
93  check=isPositive,
94  )
95  wingAmplitude = Field(
96  doc="wing amplitude, as a multiple of core amplitude (dimensionless); ignored if addWing false",
97  dtype=float,
98  optional=False,
99  default=0.1,
100  check=isPositive,
101  )
102 
103  def computeSizeAndSigma(self, fwhm=None):
104  """Compute kernel size and star width as sigma
105 
106  kernel size will be odd unless minSize or maxSize is used and that value is even.
107 
108  @param[in] fwhm: FWHM of core star (pixels); if None then defaultFwhm is used
109  @return two values:
110  - kernel size (width == height) in pixels
111  - sigma equivalent to supplied fwhm, assuming a Gaussian (pixels)
112 
113  @warning assumes a valid config
114  """
115  if fwhm is None:
116  fwhm = self.defaultFwhm
117 
118  if self.size is not None:
119  size = self.size
120  else:
121  desSize = (int(self.sizeFactor * fwhm) // 2) * 2 + 1 # make result odd
122  if self.minSize and self.minSize > desSize:
123  size = self.minSize
124  elif self.maxSize and self.maxSize < desSize:
125  size = self.maxSize
126  else:
127  size = desSize
128 
129  return size, fwhm * SigmaPerFwhm
130 
131  def validate(self):
132  Config.validate(self)
133  if self.minSize and self.maxSize and self.minSize > self.maxSize:
134  raise RuntimeError("minSize=%s > maxSize=%s" % (self.minSize, self.maxSize))
135 
136  def apply(self, fwhm=None):
137  """Construct a GaussianPsf
138 
139  @param[in] self: an instance of ConfigClass
140  @param[in] fwhm: FWHM of core of star (pixels); if None then self.defaultFwhm is used
141  @return a DoubleGaussianPsf if self.addWing is True, else a SingleGaussianPsf
142  """
143  kernelSize, sigma = self.computeSizeAndSigma(fwhm)
144  if self.addWing:
145  wingsSigma = sigma * self.wingFwhmFactor
146  return DoubleGaussianPsf(kernelSize, kernelSize, sigma, wingsSigma, self.wingAmplitude)
147  else:
148  return SingleGaussianPsf(kernelSize, kernelSize, sigma)
149 
150  @classmethod
151  def makeField(cls, doc):
152  """Make an lsst.pex.config.ConfigurableField
153  """
154  def applyWrapper(config, **kwargs):
155  """Construct a Gaussian PSF
156 
157  @param[in] config: an instance of GaussianPsfFactory
158  """
159  return config.apply(**kwargs)
160  return ConfigurableField(
161  doc=doc,
162  target=applyWrapper,
163  ConfigClass=cls
164  )