Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1# This file is part of ip_diffim. 

2# 

3# Developed for the LSST Data Management System. 

4# This product includes software developed by the LSST Project 

5# (http://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 <http://www.gnu.org/licenses/>. 

21# 

22 

23__all__ = [ 

24 "NumberSciSourcesMetricTask", "NumberSciSourcesMetricConfig", 

25 "FractionDiaSourcesToSciSourcesMetricTask", "FractionDiaSourcesToSciSourcesMetricConfig", 

26] 

27 

28 

29import numpy as np 

30import astropy.units as u 

31 

32from lsst.pipe.base import Struct, connectionTypes 

33from lsst.verify import Measurement 

34from lsst.verify.gen2tasks import register 

35from lsst.verify.tasks import MetricTask, MetricConfig, MetricConnections, \ 

36 MetricComputationError 

37 

38 

39class NumberSciSourcesMetricConnections( 

40 MetricConnections, 

41 defaultTemplates={"package": "ip_diffim", 

42 "metric": "numSciSources"}, 

43 dimensions={"instrument", "visit", "detector"}, 

44): 

45 sources = connectionTypes.Input( 

46 doc="The catalog of science sources.", 

47 name="src", 

48 storageClass="SourceCatalog", 

49 dimensions={"instrument", "visit", "detector"}, 

50 ) 

51 

52 

53class NumberSciSourcesMetricConfig( 

54 MetricConfig, 

55 pipelineConnections=NumberSciSourcesMetricConnections): 

56 pass 

57 

58 

59@register("numSciSources") 

60class NumberSciSourcesMetricTask(MetricTask): 

61 """Task that computes the number of cataloged non-sky science sources. 

62 

63 Notes 

64 ----- 

65 The task excludes any sky sources in the catalog, but it does not require 

66 that the catalog include a ``sky_sources`` column. 

67 """ 

68 _DefaultName = "numSciSources" 

69 ConfigClass = NumberSciSourcesMetricConfig 

70 

71 def run(self, sources): 

72 """Count the number of non-sky science sources. 

73 

74 Parameters 

75 ---------- 

76 sources : `lsst.afw.table.SourceCatalog` or `None` 

77 A science source catalog, which may be empty or `None`. 

78 

79 Returns 

80 ------- 

81 result : `lsst.pipe.base.Struct` 

82 A `~lsst.pipe.base.Struct` containing the following component: 

83 

84 ``measurement`` 

85 the total number of non-sky science sources (`lsst.verify.Measurement` 

86 or `None`) 

87 """ 

88 if sources is not None: 

89 nSciSources = _countRealSources(sources) 

90 meas = Measurement(self.config.metricName, nSciSources * u.count) 

91 else: 

92 self.log.info("Nothing to do: no catalogs found.") 

93 meas = None 

94 return Struct(measurement=meas) 

95 

96 

97class FractionDiaSourcesToSciSourcesMetricConnections( 

98 MetricTask.ConfigClass.ConnectionsClass, 

99 dimensions={"instrument", "visit", "detector"}, 

100 defaultTemplates={"coaddName": "deep", 

101 "fakesType": "", 

102 "package": "ip_diffim", 

103 "metric": "fracDiaSourcesToSciSources"}): 

104 sciSources = connectionTypes.Input( 

105 doc="The catalog of science sources.", 

106 name="src", 

107 storageClass="SourceCatalog", 

108 dimensions={"instrument", "visit", "detector"}, 

109 ) 

110 diaSources = connectionTypes.Input( 

111 doc="The catalog of DIASources.", 

112 name="{fakesType}{coaddName}Diff_diaSrc", 

113 storageClass="SourceCatalog", 

114 dimensions={"instrument", "visit", "detector"}, 

115 ) 

116 

117 

118class FractionDiaSourcesToSciSourcesMetricConfig( 

119 MetricTask.ConfigClass, 

120 pipelineConnections=FractionDiaSourcesToSciSourcesMetricConnections): 

121 pass 

122 

123 

124@register("fracDiaSourcesToSciSources") 

125class FractionDiaSourcesToSciSourcesMetricTask(MetricTask): 

126 """Task that computes the ratio of difference image sources to science 

127 sources in an image, visit, etc. 

128 

129 Notes 

130 ----- 

131 The task excludes any sky sources in the direct source catalog, but it 

132 does not require that either catalog include a ``sky_sources`` column. 

133 """ 

134 _DefaultName = "fracDiaSourcesToSciSources" 

135 ConfigClass = FractionDiaSourcesToSciSourcesMetricConfig 

136 

137 def run(self, sciSources, diaSources): 

138 """Compute the ratio of DIASources to non-sky science sources. 

139 

140 Parameters 

141 ---------- 

142 sciSources : `lsst.afw.table.SourceCatalog` or `None` 

143 A science source catalog, which may be empty or `None`. 

144 diaSources : `lsst.afw.table.SourceCatalog` or `None` 

145 A DIASource catalog for the same unit of processing 

146 as ``sciSources``. 

147 

148 Returns 

149 ------- 

150 result : `lsst.pipe.base.Struct` 

151 A `~lsst.pipe.base.Struct` containing the following component: 

152 

153 ``measurement`` 

154 the ratio (`lsst.verify.Measurement` or `None`) 

155 """ 

156 if diaSources is not None and sciSources is not None: 

157 nSciSources = _countRealSources(sciSources) 

158 nDiaSources = _countRealSources(diaSources) 

159 metricName = self.config.metricName 

160 if nSciSources <= 0.0: 

161 raise MetricComputationError( 

162 "No science sources found; ratio of DIASources to science sources ill-defined.") 

163 else: 

164 meas = Measurement(metricName, nDiaSources / nSciSources * u.dimensionless_unscaled) 

165 else: 

166 self.log.info("Nothing to do: no catalogs found.") 

167 meas = None 

168 return Struct(measurement=meas) 

169 

170 

171def _countRealSources(catalog): 

172 """Return the number of valid sources in a catalog. 

173 

174 At present, this definition excludes sky sources. If a catalog does not 

175 have a ``sky_source`` flag, all sources are assumed to be non-sky. 

176 

177 Parameters 

178 ---------- 

179 `catalog` : `lsst.afw.table.SourceCatalog` 

180 The catalog of sources to count. 

181 

182 Returns 

183 ------- 

184 count : `int` 

185 The number of sources that satisfy the criteria. 

186 """ 

187 if "sky_source" in catalog.schema: 

188 return np.count_nonzero(catalog["sky_source"] == False) # noqa: E712 

189 else: 

190 return len(catalog)