Coverage for python/lsst/meas/algorithms/psfDeterminer.py: 61%

25 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2022-12-08 10:19 +0000

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__ = ["BasePsfDeterminerConfig", "BasePsfDeterminerTask", "psfDeterminerRegistry"] 

25 

26import abc 

27 

28import lsst.pipe.base as pipeBase 

29import lsst.pex.config as pexConfig 

30 

31 

32class BasePsfDeterminerConfig(pexConfig.Config): 

33 """Configuration that is likely to be shared by all PSF determiners 

34 

35 This is fairly sparse; more fields can be moved here once it is clear they are universal. 

36 """ 

37 stampSize = pexConfig.Field[int]( 37 ↛ exitline 37 didn't jump to the function exit

38 doc="Size of the postage stamp (in native pixels) to render the PSF model. Should be odd.", 

39 default=None, 

40 optional=True, 

41 check=lambda x: (x > 0) & (x % 2 == 1), 

42 ) 

43 kernelSize = pexConfig.Field[int]( 

44 doc="Size of the kernel to create. " 

45 "If less than 15, then the median of the square root of the " 

46 "stellar quadrupole moments is multiplied by kernelSize and " 

47 "used as the kernel size.", 

48 default=None, 

49 optional=True, 

50 deprecated="This field is deprecated and will be removed after v25. " 

51 "Use stampSize instead.", 

52 ) 

53 kernelSizeMin = pexConfig.Field[int]( 

54 doc="Minimum radius of the kernel. Relevant only if kernelSize < 15.", 

55 default=25, 

56 deprecated="This field is deprecated and will be removed after v25.", 

57 ) 

58 kernelSizeMax = pexConfig.Field[int]( 

59 doc="Maximum radius of the kernel. Relevant only if kernelSize < 15.", 

60 default=45, 

61 deprecated="This field is deprecated and will be removed after v25.", 

62 ) 

63 

64 def validate(self): 

65 # TODO: DM-36311: Lines involving kernelSize* (or the entire method) 

66 # may be removed after v25. 

67 super().validate() 

68 # Ensure that stampSize and kernelSize are not contradictory. 

69 if self.stampSize is not None and self.kernelSize is not None: 

70 raise pexConfig.FieldValidationError(self.__class__.kernelSize, self, 

71 "Only one of stampSize (preferable) and kernelSize " 

72 "(deprecated) must be set." 

73 ) 

74 if self.kernelSizeMin > self.kernelSizeMax: 

75 raise pexConfig.FieldValidationError(self.__class__.kernelSizeMax, self, 

76 "kernelSizeMin must be <= kernelSizeMax" 

77 ) 

78 

79 

80class BasePsfDeterminerTask(pipeBase.Task, metaclass=abc.ABCMeta): 

81 """Base class for PSF determiners 

82 

83 Register all PSF determiners with the psfDeterminerRegistry using: 

84 psfDeterminerRegistry.register(name, class) 

85 

86 Parameters 

87 ---------- 

88 config : `lsst.pexConfig.Config` 

89 Input for configuring the algorithm 

90 schema : `lsst.afw.table.Schema` 

91 Schema used for sources; passing a schema allows the 

92 determiner to reserve a flag field to mark stars used in 

93 PSF measurement, but some PSF determiners ignore this argument. 

94 """ 

95 

96 usesMatches = False # Does the PSF determiner use the "matches" argument in the "run method? Few do. 

97 ConfigClass = BasePsfDeterminerConfig 

98 _DefaultName = "psfDeterminer" 

99 

100 def __init__(self, config, schema=None, **kwds): 

101 pipeBase.Task.__init__(self, config=config, **kwds) 

102 

103 @abc.abstractmethod 

104 def determinePsf(self, exposure, psfCandidateList, metadata=None, flagKey=None): 

105 """Determine a PSF model. 

106 

107 Parameters 

108 ---------- 

109 exposure : `lsst.afw.Exposure` 

110 Exposure containing the psf candidates. 

111 psdCandidateList : `list` [`lsst.meas.algorithms.PsfCandidate`] 

112 A sequence of PSF candidates; typically obtained by 

113 detecting sources and then running them through a star 

114 selector. 

115 metadata : `str`, optional 

116 A place to save interesting items. 

117 flagKey: `lsst.afw.table.Key`, optional 

118 Schema key used to mark sources actually used in PSF determination. 

119 

120 Returns 

121 ------- 

122 psf : `lsst.afw.detection.Psf` 

123 The fit PSF. 

124 cellSet : `lsst.afw.math.SpatialCellSet` 

125 The spatial cell set used to determine the PSF 

126 """ 

127 raise NotImplementedError("BasePsfDeterminerTask is abstract, subclasses must override this method") 

128 

129 

130psfDeterminerRegistry = pexConfig.makeRegistry( 

131 doc="A registry of PSF determiners (subclasses of BasePsfDeterminerTask)", 

132)