2222
2323__all__ = ("MatchedRefCoaddTool" , "MatchedRefCoaddDiffMagTool" , "MatchedRefCoaddDiffPositionTool" )
2424
25- from lsst .pex .config import ChoiceField
25+ from lsst .pex .config import ChoiceField , Config
2626
2727from ..actions .vector .selectors import GalaxySelector , StarSelector
2828from ..actions .vector .vectorActions import (
3737from ..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+
4051class 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
124153class 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 ()
0 commit comments