lsst.pipe.tasks
g2c8cee2ce7+1ac6cedd78
Toggle main menu visibility
Loading...
Searching...
No Matches
python
lsst
pipe
tasks
colorterms.py
Go to the documentation of this file.
1
# This file is part of pipe_tasks.
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/>.
21
22
__all__ = [
"ColortermNotFoundError"
,
"Colorterm"
,
"ColortermDict"
,
"ColortermLibrary"
]
23
24
import
fnmatch
25
import
warnings
26
27
import
numpy
as
np
28
import
astropy.units
as
u
29
30
from
lsst.afw.image
import
abMagErrFromFluxErr
31
from
lsst.pex.config
import
Config, Field, ConfigDictField
32
33
34
class
ColortermNotFoundError
(LookupError):
35
"""Exception class indicating we couldn't find a colorterm
36
"""
37
pass
38
39
40
class
Colorterm
(Config):
41
"""Colorterm correction for one pair of filters
42
43
Notes
44
-----
45
The transformed magnitude p' is given by:
46
p' = primary + c0 + c1*(primary - secondary) + c2*(primary - secondary)**2
47
48
To construct a Colorterm, use keyword arguments:
49
Colorterm(primary=primaryFilterName, secondary=secondaryFilterName, c0=c0value, c1=c1Coeff, c2=c2Coeff)
50
where c0-c2 are optional. For example (omitting c2):
51
Colorterm(primary="g", secondary="r", c0=-0.00816446, c1=-0.08366937)
52
53
This is subclass of Config. That is a bit of a hack to make it easy to store the data
54
in an appropriate obs_* package as a config override file. In the long term some other
55
means of persistence will be used, at which point the constructor can be simplified
56
to not require keyword arguments. (Fixing DM-2831 will also allow making a custom constructor).
57
"""
58
primary = Field(dtype=str, doc=
"name of primary filter"
)
59
secondary = Field(dtype=str, doc=
"name of secondary filter"
)
60
c0 = Field(dtype=float, default=0.0, doc=
"Constant parameter"
)
61
c1 = Field(dtype=float, default=0.0, doc=
"First-order parameter"
)
62
c2 = Field(dtype=float, default=0.0, doc=
"Second-order parameter"
)
63
64
def
getCorrectedMagnitudes
(self, refCat, filterName="deprecatedArgument"):
65
"""Return the colorterm corrected magnitudes for a given filter.
66
67
Parameters
68
----------
69
refCat : `lsst.afw.table.SimpleCatalog`
70
The reference catalog to apply color corrections to.
71
filterName : `str`, deprecated
72
The camera filter to correct the reference catalog into.
73
The ``filterName`` argument is unused and will be removed in v23.
74
75
Returns
76
-------
77
refMag : `np.ndarray`
78
The corrected AB magnitudes.
79
refMagErr : `np.ndarray`
80
The corrected AB magnitude errors.
81
82
Raises
83
------
84
KeyError
85
Raised if the reference catalog does not have a flux uncertainty
86
for that filter.
87
88
Notes
89
-----
90
WARNING: I do not know that we can trust the propagation of magnitude
91
errors returned by this method. They need more thorough tests.
92
"""
93
if
filterName !=
"deprecatedArgument"
:
94
msg =
"Colorterm.getCorrectedMagnitudes() `filterName` arg is unused and will be removed in v23."
95
warnings.warn(msg, category=FutureWarning, stacklevel=2)
96
97
def
getFluxes(fluxField):
98
"""Get the flux and fluxErr of this field from refCat.
99
100
Parameters
101
----------
102
fluxField : `str`
103
Name of the source flux field to use.
104
105
Returns
106
-------
107
refFlux : `Unknown`
108
refFluxErr : `Unknown`
109
110
Raises
111
------
112
KeyError
113
Raised if reference catalog does not have flux uncertainties for the given flux field.
114
"""
115
fluxKey = refCat.schema.find(fluxField).key
116
refFlux = refCat[fluxKey]
117
try
:
118
fluxErrKey = refCat.schema.find(fluxField +
"Err"
).key
119
refFluxErr = refCat[fluxErrKey]
120
except
KeyError
as
e:
121
raise
KeyError(
"Reference catalog does not have flux uncertainties for %s"
% fluxField)
from
e
122
123
return
refFlux, refFluxErr
124
125
primaryFlux, primaryErr = getFluxes(self.
primary
+
"_flux"
)
126
secondaryFlux, secondaryErr = getFluxes(self.
secondary
+
"_flux"
)
127
128
primaryMag = u.Quantity(primaryFlux, u.nJy).to_value(u.ABmag)
129
secondaryMag = u.Quantity(secondaryFlux, u.nJy).to_value(u.ABmag)
130
131
refMag = self.
transformMags
(primaryMag, secondaryMag)
132
refFluxErrArr = self.
propagateFluxErrors
(primaryErr, secondaryErr)
133
134
# HACK convert to Jy until we have a replacement for this (DM-16903)
135
refMagErr = abMagErrFromFluxErr(refFluxErrArr*1e-9, primaryFlux*1e-9)
136
137
return
refMag, refMagErr
138
139
def
transformSource
(self, source):
140
"""Transform the brightness of a source
141
142
Parameters
143
----------
144
source : `Unknown`
145
Source whose brightness is to be converted; must support get(filterName)
146
(e.g. source.get("r")) method, as do afw::table::Source and dicts.
147
148
Returns
149
-------
150
transformed : `float`
151
The transformed source magnitude.
152
"""
153
return
self.
transformMags
(source.get(self.
primary
), source.get(self.
secondary
))
154
155
def
transformMags
(self, primary, secondary):
156
"""Transform brightness
157
158
Parameters
159
----------
160
primary : `float`
161
Brightness in primary filter (magnitude).
162
secondary : `float`
163
Brightness in secondary filter (magnitude).
164
165
Returns
166
-------
167
transformed : `float`
168
The transformed brightness (as a magnitude).
169
"""
170
color = primary - secondary
171
return
primary + self.
c0
+ color*(self.
c1
+ color*self.
c2
)
172
173
def
propagateFluxErrors
(self, primaryFluxErr, secondaryFluxErr):
174
return
np.hypot((1 + self.
c1
)*primaryFluxErr, self.
c1
*secondaryFluxErr)
175
176
177
class
ColortermDict
(Config):
178
"""A mapping of physical filter label to Colorterm
179
180
Different reference catalogs may need different ColortermDicts; see ColortermLibrary
181
182
To construct a ColortermDict use keyword arguments:
183
ColortermDict(data=dataDict)
184
where dataDict is a Python dict of filterName: Colorterm
185
For example:
186
ColortermDict(data={
187
'g': Colorterm(primary="g", secondary="r", c0=-0.00816446, c1=-0.08366937, c2=-0.00726883),
188
'r': Colorterm(primary="r", secondary="i", c0= 0.00231810, c1= 0.01284177, c2=-0.03068248),
189
'i': Colorterm(primary="i", secondary="z", c0= 0.00130204, c1=-0.16922042, c2=-0.01374245),
190
})
191
The constructor will likely be simplified at some point.
192
193
This is subclass of Config. That is a bit of a hack to make it easy to store the data
194
in an appropriate obs_* package as a config override file. In the long term some other
195
means of persistence will be used, at which point the constructor can be made saner.
196
"""
197
data = ConfigDictField(
198
doc=
"Mapping of filter name to Colorterm"
,
199
keytype=str,
200
itemtype=Colorterm,
201
default={},
202
)
203
204
205
class
ColortermLibrary
(Config):
206
"""A mapping of photometric reference catalog name or glob to ColortermDict
207
208
Notes
209
-----
210
This allows photometric calibration using a variety of reference catalogs.
211
212
To construct a ColortermLibrary, use keyword arguments:
213
ColortermLibrary(data=dataDict)
214
where dataDict is a Python dict of catalog_name_or_glob: ColortermDict
215
216
Examples
217
--------
218
219
.. code-block:: none
220
221
ColortermLibrary(data = {
222
"hsc": ColortermDict(data={
223
'g': Colorterm(primary="g", secondary="g"),
224
'r': Colorterm(primary="r", secondary="r"),
225
...
226
}),
227
"sdss": ColortermDict(data={
228
'g': Colorterm(primary="g",
229
secondary="r",
230
c0=-0.00816446,
231
c1=-0.08366937,
232
c2=-0.00726883),
233
'r': Colorterm(primary="r",
234
secondary="i",
235
c0= 0.00231810,
236
c1= 0.01284177,
237
c2=-0.03068248),
238
...
239
}),
240
})
241
242
This is subclass of Config. That is a bit of a hack to make it easy to store the data
243
in an appropriate obs package as a config override file. In the long term some other
244
means of persistence will be used, at which point the constructor can be made saner.
245
"""
246
data = ConfigDictField(
247
doc=
"Mapping of reference catalog name (or glob) to ColortermDict"
,
248
keytype=str,
249
itemtype=ColortermDict,
250
default={},
251
)
252
253
def
getColorterm
(self, physicalFilter, photoCatName, doRaise=True):
254
"""Get the appropriate Colorterm from the library
255
256
Use dict of color terms in the library that matches the photoCatName.
257
If the photoCatName exactly matches an entry in the library, that
258
dict is used; otherwise if the photoCatName matches a single glob (shell syntax,
259
e.g., "sdss-*" will match "sdss-dr8"), then that is used. If there is no
260
exact match and no unique match to the globs, raise an exception.
261
262
Parameters
263
----------
264
physicalFilter : `str`
265
Label of physical filter to correct to.
266
photoCatName : `str`
267
Name of photometric reference catalog from which to retrieve the data.
268
This argument is not glob-expanded (but the catalog names in the library are,
269
if no exact match is found).
270
doRaise : `bool`
271
If True then raise ColortermNotFoundError if no suitable Colorterm found;
272
If False then return a null Colorterm with physicalFilter as the primary and secondary filter.
273
274
Returns
275
-------
276
ctDict : `Unknown`
277
The appropriate Colorterm.
278
279
Raises
280
------
281
ColortermNotFoundError
282
If no suitable Colorterm found and doRaise true;
283
other exceptions may be raised for unexpected errors, regardless of the value of doRaise.
284
"""
285
try
:
286
trueRefCatName =
None
287
ctDictConfig = self.
data
.get(photoCatName)
288
if
ctDictConfig
is
None
:
289
# try glob expression
290
matchList = [libRefNameGlob
for
libRefNameGlob
in
self.
data
291
if
fnmatch.fnmatch(photoCatName, libRefNameGlob)]
292
if
len(matchList) == 1:
293
trueRefCatName = matchList[0]
294
ctDictConfig = self.
data
[trueRefCatName]
295
elif
len(matchList) > 1:
296
raise
ColortermNotFoundError
(
297
"Multiple library globs match photoCatName %r: %s"
% (photoCatName, matchList))
298
else
:
299
raise
ColortermNotFoundError
(
300
"No colorterm dict found with photoCatName %r"
% photoCatName)
301
ctDict = ctDictConfig.data
302
if
physicalFilter
not
in
ctDict:
303
errMsg =
"No colorterm found for filter %r with photoCatName %r"
% (
304
physicalFilter, photoCatName)
305
if
trueRefCatName
is
not
None
:
306
errMsg +=
" = catalog %r"
% (trueRefCatName,)
307
raise
ColortermNotFoundError
(errMsg)
308
return
ctDict[physicalFilter]
309
except
ColortermNotFoundError:
310
if
doRaise:
311
raise
312
else
:
313
return
Colorterm
(physicalFilter, physicalFilter)
lsst.pipe.tasks.colorterms.ColortermDict
Definition
colorterms.py:177
lsst.pipe.tasks.colorterms.Colorterm
Definition
colorterms.py:40
lsst.pipe.tasks.colorterms.Colorterm.secondary
secondary
Definition
colorterms.py:59
lsst.pipe.tasks.colorterms.Colorterm.propagateFluxErrors
propagateFluxErrors(self, primaryFluxErr, secondaryFluxErr)
Definition
colorterms.py:173
lsst.pipe.tasks.colorterms.Colorterm.c1
c1
Definition
colorterms.py:61
lsst.pipe.tasks.colorterms.Colorterm.c2
c2
Definition
colorterms.py:62
lsst.pipe.tasks.colorterms.Colorterm.getCorrectedMagnitudes
getCorrectedMagnitudes(self, refCat, filterName="deprecatedArgument")
Definition
colorterms.py:64
lsst.pipe.tasks.colorterms.Colorterm.transformSource
transformSource(self, source)
Definition
colorterms.py:139
lsst.pipe.tasks.colorterms.Colorterm.primary
primary
Definition
colorterms.py:58
lsst.pipe.tasks.colorterms.Colorterm.transformMags
transformMags(self, primary, secondary)
Definition
colorterms.py:155
lsst.pipe.tasks.colorterms.Colorterm.c0
c0
Definition
colorterms.py:60
lsst.pipe.tasks.colorterms.ColortermLibrary
Definition
colorterms.py:205
lsst.pipe.tasks.colorterms.ColortermLibrary.getColorterm
getColorterm(self, physicalFilter, photoCatName, doRaise=True)
Definition
colorterms.py:253
lsst.pipe.tasks.colorterms.ColortermLibrary.data
data
Definition
colorterms.py:246
lsst.pipe.tasks.colorterms.ColortermNotFoundError
Definition
colorterms.py:34
lsst::afw::image
lsst::pex::config
Generated on
for lsst.pipe.tasks by
1.17.0