Skip to content

Commit ffadae8

Browse files
committed
Replace MatchedRef(Chi/Diff)Context with pexConfig.ChoiceField
1 parent b575765 commit ffadae8

7 files changed

Lines changed: 153 additions & 143 deletions

File tree

pipelines/coaddDiffMatchedQualityExtended.yaml

Lines changed: 2 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -8,53 +8,10 @@ tasks:
88

99
# plots
1010
plots.matchedRefCModelMagDiffPlot: MatchedRefCoaddCModelFluxPlot
11-
plots.matchedRefCModelMagDiffPlot.applyContext: MatchedRefDiffContext
11+
plots.matchedRefCModelMagDiffPlot.context: "diff"
1212

1313
plots.matchedRefCModelFluxChiPlot: MatchedRefCoaddCModelFluxPlot
14-
plots.matchedRefCModelFluxChiPlot.applyContext: MatchedRefChiContext
15-
16-
# TODO: Can this be a one liner?
17-
plots.matchedRefPositionXDiffPlot: MatchedRefCoaddPositionPlot
18-
# TODO: variable must be defined before applyContext; can this be enforced?
19-
# (the resulting error if not is not very informative)
20-
plots.matchedRefPositionXDiffPlot.variable: x
21-
plots.matchedRefPositionXDiffPlot.applyContext: MatchedRefDiffContext
22-
23-
plots.matchedRefPositionXChiPlot: MatchedRefCoaddPositionPlot
24-
plots.matchedRefPositionXChiPlot.variable: x
25-
plots.matchedRefPositionXChiPlot.applyContext: MatchedRefChiContext
26-
27-
plots.matchedRefPositionYDiffPlot: MatchedRefCoaddPositionPlot
28-
plots.matchedRefPositionYDiffPlot.variable: y
29-
plots.matchedRefPositionYDiffPlot.applyContext: MatchedRefDiffContext
30-
31-
plots.matchedRefPositionYChiPlot: MatchedRefCoaddPositionPlot
32-
plots.matchedRefPositionYChiPlot.variable: y
33-
plots.matchedRefPositionYChiPlot.applyContext: MatchedRefChiContext
34-
35-
# metrics
36-
metrics.matchedRefCModelMagDiffMetric: MatchedRefCoaddCModelFluxMetric
37-
metrics.matchedRefCModelMagDiffMetric.applyContext: MatchedRefDiffContext
38-
39-
metrics.matchedRefCModelFluxChiMetric: MatchedRefCoaddCModelFluxMetric
40-
metrics.matchedRefCModelFluxChiMetric.applyContext: MatchedRefChiContext
41-
42-
metrics.matchedRefPositionXDiffMetric: MatchedRefCoaddPositionMetric
43-
metrics.matchedRefPositionXDiffMetric.variable: x
44-
metrics.matchedRefPositionXDiffMetric.applyContext: MatchedRefChiContext
45-
46-
metrics.matchedRefPositionXChiMetric: MatchedRefCoaddPositionMetric
47-
metrics.matchedRefPositionXChiMetric.variable: x
48-
metrics.matchedRefPositionXChiMetric.applyContext: MatchedRefChiContext
49-
50-
metrics.matchedRefPositionYDiffMetric: MatchedRefCoaddPositionMetric
51-
metrics.matchedRefPositionYDiffMetric.variable: y
52-
metrics.matchedRefPositionYDiffMetric.applyContext: MatchedRefDiffContext
53-
54-
metrics.matchedRefPositionYChiMetric: MatchedRefCoaddPositionMetric
55-
metrics.matchedRefPositionYChiMetric.variable: y
56-
metrics.matchedRefPositionYChiMetric.applyContext: MatchedRefChiContext
57-
14+
plots.matchedRefCModelFluxChiPlot.context: "chi"
5815

5916
python: |
6017
from lsst.analysis.tools.analysisMetrics.diffMatchedMetrics import (
@@ -66,8 +23,3 @@ tasks:
6623
MatchedRefCoaddCModelFluxPlot,
6724
MatchedRefCoaddPositionPlot,
6825
)
69-
70-
from lsst.analysis.tools.contexts._contexts import (
71-
MatchedRefDiffContext,
72-
MatchedRefChiContext,
73-
)

python/lsst/analysis/tools/analysisMetrics/diffMatchedMetrics.py

Lines changed: 35 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ def _validate(self):
5454
if self.name_prefix is None or self.unit is None:
5555
raise ValueError(
5656
f"{self.name_prefix=} and {self.unit=} must not be None;"
57-
f" did you forget to set a valid context?"
57+
f" did you correctly set {self.context=}"
5858
)
5959

6060
def configureMetrics(
@@ -144,36 +144,48 @@ def __call__(self, data: KeyedData, **kwargs):
144144
class MatchedRefCoaddCModelFluxMetric(MatchedRefCoaddDiffMagTool, MatchedRefCoaddMetric):
145145
"""Metric for diffs between reference and CModel coadd mags."""
146146

147-
def matchedRefDiffContext(self):
148-
super().matchedRefDiffContext()
149-
self.unit = "mmag"
150-
self.name_prefix = "photom_mag_cModelFlux_{name_class}_diff_"
151-
self.produce.units = self.configureMetrics()
152-
153-
def matchedRefChiContext(self):
154-
super().matchedRefChiContext()
155-
self.unit = ""
156-
self.name_prefix = "photom_mag_cModelFlux_{name_class}_chi_"
157-
self.produce.units = self.configureMetrics()
147+
def _setActions(self):
148+
if self.context == "diff":
149+
self.unit = "mmag"
150+
self.name_prefix = "photom_mag_cModelFlux_{name_class}_diff_"
151+
self.produce.units = self.configureMetrics()
152+
elif self.context == "chi":
153+
self.unit = ""
154+
self.name_prefix = "photom_mag_cModelFlux_{name_class}_chi_"
155+
self.produce.units = self.configureMetrics()
156+
else:
157+
raise ValueError(f"Unrecognized {self.context=}")
158158

159159
def setDefaults(self):
160160
super().setDefaults()
161161

162+
def validate(self):
163+
super().validate()
164+
# TODO: This check may be fragile and should move to finalize() ASAP
165+
if self.name_prefix is None:
166+
self._setActions()
167+
162168

163169
class MatchedRefCoaddPositionMetric(MatchedRefCoaddDiffPositionTool, MatchedRefCoaddMetric):
164170
"""Metric for diffs between reference and base coadd centroids."""
165171

166-
def matchedRefDiffContext(self):
167-
super().matchedRefDiffContext()
168-
self.unit = "pix"
169-
self.name_prefix = f"astrom_{self.variable}_{{name_class}}_diff_"
170-
self.produce.units = self.configureMetrics()
171-
172-
def matchedRefChiContext(self):
173-
super().matchedRefChiContext()
174-
self.unit = ""
175-
self.name_prefix = f"astrom_{self.variable}_{{name_class}}_diff_"
176-
self.produce.units = self.configureMetrics()
172+
def _setActions(self):
173+
if self.context == "diff":
174+
self.unit = "pix"
175+
self.name_prefix = f"astrom_{self.variable}_{{name_class}}_diff_"
176+
self.produce.units = self.configureMetrics()
177+
elif self.context == "chi":
178+
self.unit = ""
179+
self.name_prefix = f"astrom_{self.variable}_{{name_class}}_diff_"
180+
self.produce.units = self.configureMetrics()
181+
else:
182+
raise ValueError(f"Unrecognized {self.context=}")
177183

178184
def setDefaults(self):
179185
super().setDefaults()
186+
187+
def validate(self):
188+
super().validate()
189+
# TODO: This check may be fragile and should move to finalize() ASAP
190+
if self.name_prefix is None:
191+
self._setActions()

python/lsst/analysis/tools/analysisParts/coaddVisit.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
class CoaddVisitConfig(Config):
2828
"""Config for tools that can be applied in coadd and visit contexts."""
2929

30-
context = ChoiceField(
30+
context: ChoiceField = ChoiceField(
3131
doc="The analysis context for this class",
3232
dtype=str,
3333
allowed={"coadd": "Coadded images", "visit": "Single visit images"},

python/lsst/analysis/tools/analysisParts/diffMatched.py

Lines changed: 69 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
__all__ = ("MatchedRefCoaddTool", "MatchedRefCoaddDiffMagTool", "MatchedRefCoaddDiffPositionTool")
2424

25-
from lsst.pex.config import ChoiceField
25+
from lsst.pex.config import ChoiceField, Config
2626

2727
from ..actions.vector.selectors import GalaxySelector, StarSelector
2828
from ..actions.vector.vectorActions import (
@@ -37,6 +37,17 @@
3737
from ..interfaces import AnalysisTool
3838

3939

40+
class MatchedCoaddVisitConfig(Config):
41+
"""Config for tools that can be applied in coadd and visit contexts."""
42+
43+
context = ChoiceField(
44+
doc="The analysis context for this class",
45+
dtype=str,
46+
allowed={"coadd": "Coadded images", "visit": "Single visit images"},
47+
optional=False,
48+
)
49+
50+
4051
class MatchedRefCoaddTool(AnalysisTool):
4152
"""Base tool for matched-to-reference metrics/plots on coadds.
4253
@@ -50,6 +61,13 @@ class MatchedRefCoaddTool(AnalysisTool):
5061
appropriate candidates (and stores a match_candidate column).
5162
"""
5263

64+
context = ChoiceField(
65+
doc="The type of metric to compute",
66+
dtype=str,
67+
allowed={"diff": "Measured - ref value", "chi": "(Measured - ref value)/sigma (a.k.a. chi/pull)"},
68+
optional=False,
69+
)
70+
5371
def setDefaults(self):
5472
super().setDefaults()
5573
self.process.buildActions.fluxes_ref = LoadVector(vectorKey="refcat_flux_{band}")
@@ -85,26 +103,32 @@ class MatchedRefCoaddDiffMagTool(MatchedRefCoaddTool):
85103
The default model flux is cModel.
86104
"""
87105

88-
def matchedRefDiffContext(self):
89-
self.process.buildActions.diff = SubtractVector(
90-
actionA=MagColumnNanoJansky(
91-
vectorKey=self.process.buildActions.fluxes_meas.vectorKey, returnMillimags=True
92-
),
93-
actionB=DivideVector(
94-
actionA=self.process.buildActions.mags_ref,
95-
# To convert to mmag
96-
actionB=ConstantValue(value=1e-3),
97-
),
98-
)
99-
100-
def matchedRefChiContext(self):
101-
self.process.buildActions.diff = DivideVector(
102-
actionA=SubtractVector(
103-
actionA=LoadVector(vectorKey=self.process.buildActions.fluxes_meas.vectorKey),
104-
actionB=LoadVector(vectorKey=self.process.buildActions.fluxes_ref.vectorKey),
105-
),
106-
actionB=LoadVector(vectorKey=f"{self.process.buildActions.fluxes_meas.vectorKey}Err"),
107-
)
106+
def _setActions(self):
107+
frozen = self.process._frozen
108+
if frozen:
109+
self.process._frozen = False
110+
if self.context == "diff":
111+
self.process.buildActions.diff = SubtractVector(
112+
actionA=MagColumnNanoJansky(
113+
vectorKey=self.process.buildActions.fluxes_meas.vectorKey, returnMillimags=True
114+
),
115+
actionB=DivideVector(
116+
actionA=self.process.buildActions.mags_ref,
117+
# To convert to mmag
118+
actionB=ConstantValue(value=1e-3),
119+
),
120+
)
121+
elif self.context == "chi":
122+
self.process.buildActions.diff = DivideVector(
123+
actionA=SubtractVector(
124+
actionA=LoadVector(vectorKey=self.process.buildActions.fluxes_meas.vectorKey),
125+
actionB=LoadVector(vectorKey=self.process.buildActions.fluxes_ref.vectorKey),
126+
),
127+
actionB=LoadVector(vectorKey=f"{self.process.buildActions.fluxes_meas.vectorKey}Err"),
128+
)
129+
else:
130+
raise ValueError(f"Unrecognized {self.context=}")
131+
self.process._frozen = frozen
108132

109133
def setDefaults(self):
110134
super().setDefaults()
@@ -120,6 +144,11 @@ def setDefaults(self):
120144
vectorKey="diff", selector=VectorSelector(vectorKey="starSelector")
121145
)
122146

147+
def validate(self):
148+
super().validate()
149+
if not hasattr(self.process.buildActions, "diff"):
150+
self._setActions()
151+
123152

124153
class MatchedRefCoaddDiffPositionTool(MatchedRefCoaddTool):
125154
"""Base tool for diffs between reference and measured coadd astrometry."""
@@ -133,30 +162,25 @@ class MatchedRefCoaddDiffPositionTool(MatchedRefCoaddTool):
133162
optional=False,
134163
)
135164

136-
# TODO: Determine if this can be put back into setDefaults w/o this:
137-
# lsst.pex.config.config.FieldValidationError:
138-
# Field 'process.buildActions.pos_meas.vectorKey' failed validation:
139-
# Required value cannot be None
140-
def _setPos(self):
165+
def _setActions(self):
141166
self.process.buildActions.pos_meas = LoadVector(vectorKey=self.variable)
142167
self.process.buildActions.pos_ref = LoadVector(vectorKey=f"refcat_{self.variable}")
143168

144-
def matchedRefDiffContext(self):
145-
self._setPos()
146-
self.process.buildActions.diff = SubtractVector(
147-
actionA=self.process.buildActions.pos_meas,
148-
actionB=self.process.buildActions.pos_ref,
149-
)
150-
151-
def matchedRefChiContext(self):
152-
self._setPos()
153-
self.process.buildActions.diff = DivideVector(
154-
actionA=SubtractVector(
169+
if self.context == "diff":
170+
self.process.buildActions.diff = SubtractVector(
155171
actionA=self.process.buildActions.pos_meas,
156172
actionB=self.process.buildActions.pos_ref,
157-
),
158-
actionB=LoadVector(vectorKey=f"{self.process.buildActions.pos_meas.vectorKey}Err"),
159-
)
173+
)
174+
elif self.context == "chi":
175+
self.process.buildActions.diff = DivideVector(
176+
actionA=SubtractVector(
177+
actionA=self.process.buildActions.pos_meas,
178+
actionB=self.process.buildActions.pos_ref,
179+
),
180+
actionB=LoadVector(vectorKey=f"{self.process.buildActions.pos_meas.vectorKey}Err"),
181+
)
182+
else:
183+
raise ValueError(f"Unrecognized {self.context=}")
160184

161185
def setDefaults(self):
162186
super().setDefaults()
@@ -170,3 +194,8 @@ def setDefaults(self):
170194
self.process.filterActions.yStars = DownselectVector(
171195
vectorKey="diff", selector=VectorSelector(vectorKey="starSelector")
172196
)
197+
198+
def validate(self):
199+
super().validate()
200+
if not hasattr(self.process.buildActions, "diff"):
201+
self._setActions()

python/lsst/analysis/tools/analysisPlots/diffMatchedPlots.py

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ def setDefaults(self):
3535

3636
self.produce.plotTypes = ["galaxies", "stars"]
3737
self.produce.xAxisLabel = "Reference Magnitude (mag)"
38+
self.produce.yAxisLabel = ""
3839

3940

4041
class MatchedRefCoaddCModelPlot(MatchedRefCoaddPlot):
@@ -65,26 +66,50 @@ def setDefaults(self):
6566

6667

6768
class MatchedRefCoaddCModelFluxPlot(MatchedRefCoaddCModelPlot, MatchedRefCoaddDiffMagTool):
68-
def matchedRefDiffContext(self):
69-
super().matchedRefDiffContext()
70-
self.produce.yAxisLabel = "cModel - Reference mmag"
71-
72-
def matchedRefChiContext(self):
73-
super().matchedRefChiContext()
74-
self.produce.yAxisLabel = "chi = (cModel - Reference mag)/error"
69+
"""Matched reference plot of cModel mags"""
70+
71+
def _setLabels(self):
72+
frozen = self.produce._frozen
73+
if frozen:
74+
self.produce._frozen = False
75+
if self.context == "diff":
76+
self.produce.yAxisLabel = "cModel - Reference mmag"
77+
elif self.context == "chi":
78+
self.produce.yAxisLabel = "chi = (cModel - Reference mag)/error"
79+
else:
80+
raise ValueError(f"Unrecognized {self.context=}")
81+
self.produce._frozen = frozen
7582

7683
def setDefaults(self):
7784
super().setDefaults()
7885

86+
def validate(self):
87+
super().validate()
88+
# TODO: This check may be fragile and should move to finalize() ASAP
89+
if self.produce.yAxisLabel == "":
90+
self._setLabels()
7991

80-
class MatchedRefCoaddPositionPlot(MatchedRefCoaddCModelPlot, MatchedRefCoaddDiffPositionTool):
81-
def matchedRefDiffContext(self):
82-
super().matchedRefDiffContext()
83-
self.produce.yAxisLabel = f"{self.variable} position (pix)"
8492

85-
def matchedRefChiContext(self):
86-
super().matchedRefChiContext()
87-
self.produce.yAxisLabel = f"chi = (slot - Reference {self.variable} position)/error"
93+
class MatchedRefCoaddPositionPlot(MatchedRefCoaddCModelPlot, MatchedRefCoaddDiffPositionTool):
94+
"""Matched reference plot of slot positions (RA/Dec)"""
95+
96+
def _setActions(self):
97+
frozen = self.produce._frozen
98+
if frozen:
99+
self.produce._frozen = False
100+
if self.context == "diff":
101+
self.produce.yAxisLabel = f"{self.variable} position (pix)"
102+
elif self.context == "chi":
103+
self.produce.yAxisLabel = f"chi = (slot - Reference {self.variable} position)/error"
104+
else:
105+
raise ValueError(f"Unrecognized {self.context=}")
106+
self.produce._frozen = frozen
88107

89108
def setDefaults(self):
90109
super().setDefaults()
110+
111+
def validate(self):
112+
super().validate()
113+
# TODO: This check may be fragile and should move to finalize() ASAP
114+
if self.produce.yAxisLabel == "":
115+
self._setLabels()

0 commit comments

Comments
 (0)