Coverage for python / lsst / analysis / tools / atools / deblenderMetric.py: 26%
58 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-22 09:08 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-22 09:08 +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
23__all__ = ("ParentDeblenderMetrics", "SkippedDeblenderMetrics", "BlendMetrics", "IsolatedDeblenderMetrics")
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
35class ParentDeblenderMetrics(AnalysisTool):
36 """Calculate metrics based on the performance of the deblender"""
38 def setDefaults(self):
39 super().setDefaults()
41 # Only select parents
42 self.prep.selectors.parentSelector = ParentObjectSelector()
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")
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")
54 self.produce.metric.units = {
55 "numParents": "",
56 "numDeblendFailed": "",
57 "numIncompleteData": "",
58 "numDetectedPeaks": "",
59 "numDeblendedChildren": "",
60 }
63class SkippedDeblenderMetrics(AnalysisTool):
64 """Calculate metrics based on blends skipped by the deblender"""
66 def setDefaults(self):
67 super().setDefaults()
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 ]
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")
90 # Total number of skipped peaks
91 self.process.calculateActions.numSkippedPeaks = SumAction(vectorKey="deblend_nPeaks")
93 self.produce.metric.units = {
94 "numSkippedBlends": "",
95 "numBlendParentTooBig": "",
96 "numBlendTooManyPeaks": "",
97 "numBlendTooManyMasked": "",
98 "numSkippedPeaks": "",
99 }
102class BlendMetrics(AnalysisTool):
103 """Calculate metrics based on the performance of the deblender for blends
104 with multiple children
105 """
107 def setDefaults(self):
108 super().setDefaults()
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
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")
123 self.produce.metric.units = {
124 "numBlends": "",
125 "meanBlendIterations": "",
126 "meanBlendChi2": "",
127 }
130class IsolatedDeblenderMetrics(AnalysisTool):
131 """Calculate metrics based on the performance of the deblender for
132 parents with only a single child peak.
133 """
135 def setDefaults(self):
136 super().setDefaults()
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
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")
150 self.produce.metric.units = {
151 "numIsolated": "",
152 "meanIsolatedIterations": "",
153 "meanIsolatedChi2": "",
154 }
157class ChildDeblenderMetrics(AnalysisTool):
158 """Calculate metrics based on the performance of the deblender for
159 single sources.
160 """
162 def setDefaults(self):
163 super().setDefaults()
164 self.prep.selectors.childSelector = ChildObjectSelector()
165 self.process.calculateActions.zeroFlux = SumAction(vectorKey="deblend_zeroFlux")
167 self.produce.metric.units = {
168 "zeroFlux": "",
169 }