Coverage for python / lsst / analysis / tools / atools / deblenderMetric.py: 26%

58 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-05-05 18:53 +0000

1# This file is part of analysis_tools. 

2# 

3# Developed for the LSST Data Management System. 

4# This product includes software developed by the LSST Project 

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

21from __future__ import annotations 

22 

23__all__ = ("ParentDeblenderMetrics", "SkippedDeblenderMetrics", "BlendMetrics", "IsolatedDeblenderMetrics") 

24 

25from ..actions.scalar.scalarActions import CountAction, MeanAction, SumAction 

26from ..actions.vector.selectors import ( 

27 ChildObjectSelector, 

28 FlagSelector, 

29 ParentObjectSelector, 

30 ThresholdSelector, 

31) 

32from ..interfaces import AnalysisTool 

33 

34 

35class ParentDeblenderMetrics(AnalysisTool): 

36 """Calculate metrics based on the performance of the deblender""" 

37 

38 def setDefaults(self): 

39 super().setDefaults() 

40 

41 # Only select parents 

42 self.prep.selectors.parentSelector = ParentObjectSelector() 

43 

44 # Statistics for parent blends 

45 self.process.calculateActions.numParents = CountAction(vectorKey="parentObjectId") 

46 self.process.calculateActions.numDeblendFailed = SumAction(vectorKey="deblend_failed") 

47 self.process.calculateActions.numIncompleteData = SumAction(vectorKey="deblend_incompleteData") 

48 

49 # Total number of detected peaks 

50 self.process.calculateActions.numDetectedPeaks = SumAction(vectorKey="deblend_nPeaks") 

51 # Total number of deblended children 

52 self.process.calculateActions.numDeblendedChildren = SumAction(vectorKey="deblend_nChild") 

53 

54 self.produce.metric.units = { 

55 "numParents": "", 

56 "numDeblendFailed": "", 

57 "numIncompleteData": "", 

58 "numDetectedPeaks": "", 

59 "numDeblendedChildren": "", 

60 } 

61 

62 

63class SkippedDeblenderMetrics(AnalysisTool): 

64 """Calculate metrics based on blends skipped by the deblender""" 

65 

66 def setDefaults(self): 

67 super().setDefaults() 

68 

69 # Only select non-sky object parents that were skipped but did not fail 

70 # This also excludes isolated objects that were skipped 

71 # if isolated objects are not being deblended 

72 self.prep.selectors.parentSelector = ParentObjectSelector() 

73 self.prep.selectors.skippedSelector = FlagSelector() 

74 self.prep.selectors.skippedSelector.selectWhenTrue = ["deblend_skipped"] 

75 self.prep.selectors.skippedSelector.selectWhenFalse = [ 

76 "deblend_failed", 

77 "deblend_skipped_isolatedParent", 

78 ] 

79 

80 # Statistics for skipped blends 

81 self.process.calculateActions.numSkippedBlends = CountAction(vectorKey="parentObjectId") 

82 self.process.calculateActions.numBlendParentTooBig = SumAction( 

83 vectorKey="deblend_skipped_parentTooBig" 

84 ) 

85 self.process.calculateActions.numBlendTooManyPeaks = SumAction( 

86 vectorKey="deblend_skipped_tooManyPeaks" 

87 ) 

88 self.process.calculateActions.numBlendTooManyMasked = SumAction(vectorKey="deblend_skipped_masked") 

89 

90 # Total number of skipped peaks 

91 self.process.calculateActions.numSkippedPeaks = SumAction(vectorKey="deblend_nPeaks") 

92 

93 self.produce.metric.units = { 

94 "numSkippedBlends": "", 

95 "numBlendParentTooBig": "", 

96 "numBlendTooManyPeaks": "", 

97 "numBlendTooManyMasked": "", 

98 "numSkippedPeaks": "", 

99 } 

100 

101 

102class BlendMetrics(AnalysisTool): 

103 """Calculate metrics based on the performance of the deblender for blends 

104 with multiple children 

105 """ 

106 

107 def setDefaults(self): 

108 super().setDefaults() 

109 

110 # Only select parents that were successfully deblended 

111 # with more than one child 

112 self.prep.selectors.parentSelector = ParentObjectSelector() 

113 self.prep.selectors.blendSelector = ThresholdSelector() 

114 self.prep.selectors.blendSelector.vectorKey = "deblend_nChild" 

115 self.prep.selectors.blendSelector.op = "gt" 

116 self.prep.selectors.blendSelector.threshold = 1 

117 

118 # Statistics for blended parents 

119 self.process.calculateActions.numBlends = CountAction(vectorKey="parentObjectId") 

120 self.process.calculateActions.meanBlendIterations = MeanAction(vectorKey="deblend_iterations") 

121 self.process.calculateActions.meanBlendChi2 = MeanAction(vectorKey="deblend_chi2") 

122 

123 self.produce.metric.units = { 

124 "numBlends": "", 

125 "meanBlendIterations": "", 

126 "meanBlendChi2": "", 

127 } 

128 

129 

130class IsolatedDeblenderMetrics(AnalysisTool): 

131 """Calculate metrics based on the performance of the deblender for 

132 parents with only a single child peak. 

133 """ 

134 

135 def setDefaults(self): 

136 super().setDefaults() 

137 

138 # Only select parents that were successfully deblended with one child 

139 self.prep.selectors.parentSelector = ParentObjectSelector() 

140 self.prep.selectors.blendSelector = ThresholdSelector() 

141 self.prep.selectors.blendSelector.vectorKey = "deblend_nChild" 

142 self.prep.selectors.blendSelector.op = "eq" 

143 self.prep.selectors.blendSelector.threshold = 1 

144 

145 # Statistics for isolated parent scarlet_lite models 

146 self.process.calculateActions.numIsolated = CountAction(vectorKey="parentObjectId") 

147 self.process.calculateActions.meanIsolatedIterations = MeanAction(vectorKey="deblend_iterations") 

148 self.process.calculateActions.meanIsolatedChi2 = MeanAction(vectorKey="deblend_chi2") 

149 

150 self.produce.metric.units = { 

151 "numIsolated": "", 

152 "meanIsolatedIterations": "", 

153 "meanIsolatedChi2": "", 

154 } 

155 

156 

157class ChildDeblenderMetrics(AnalysisTool): 

158 """Calculate metrics based on the performance of the deblender for 

159 single sources. 

160 """ 

161 

162 def setDefaults(self): 

163 super().setDefaults() 

164 self.prep.selectors.childSelector = ChildObjectSelector() 

165 self.process.calculateActions.zeroFlux = SumAction(vectorKey="deblend_zeroFlux") 

166 

167 self.produce.metric.units = { 

168 "zeroFlux": "", 

169 }