31 __all__ = [
"ColortermNotFoundError",
"Colorterm",
"ColortermDict",
"ColortermLibrary"]
34 """Exception class indicating we couldn't find a colorterm
40 """!Colorterm correction for one pair of filters
42 The transformed magnitude p' is given by
43 p' = primary + c0 + c1*(primary - secondary) + c2*(primary - secondary)**2
45 To construct a Colorterm, use keyword arguments:
46 Colorterm(primary=primaryFilterName, secondary=secondaryFilterName, c0=c0value, c1=c1Coeff, c2=c2Coeff)
47 where c0-c2 are optional. For example (omitting c2):
48 Colorterm(primary="g", secondary="r", c0=-0.00816446, c1=-0.08366937)
50 This is subclass of Config. That
is a bit of a hack to make it easy to store the data
51 in an appropriate obs_* package
as a config override file. In the long term some other
52 means of persistence will be used, at which point the constructor can be simplified
53 to
not require keyword arguments. (Fixing DM-2831 will also allow making a custom constructor).
55 primary = Field(dtype=str, doc="name of primary filter")
56 secondary = Field(dtype=str, doc="name of secondary filter")
57 c0 = Field(dtype=float, default=0.0, doc="Constant parameter")
58 c1 = Field(dtype=float, default=0.0, doc="First-order parameter")
59 c2 = Field(dtype=float, default=0.0, doc="Second-order parameter")
61 def transformSource(self, source):
62 """!Transform the brightness of a source
64 @param[
in] source source whose brightness
is to be converted; must support get(filterName)
65 (e.g. source.get(
"r")) method, as do afw::table::Source and dicts.
66 @return the transformed source magnitude
68 return self.transformMags(source.get(self.primary), source.get(self.secondary))
70 def transformMags(self, primary, secondary):
71 """!Transform brightness
73 @param[
in] primary brightness
in primary filter (magnitude)
74 @param[
in] secondary brightness
in secondary filter (magnitude)
75 @
return the transformed brightness (
as a magnitude)
77 color = primary - secondary
78 return primary + self.c0 + color*(self.c1 + color*self.c2)
80 def propagateFluxErrors(self, primaryFluxErr, secondaryFluxErr):
81 return np.hypot((1 + self.c1)*primaryFluxErr, self.c1*secondaryFluxErr)
84 class ColortermDict(Config):
85 """!A mapping of filterName to Colorterm
87 Different reference catalogs may need different ColortermDicts; see ColortermLibrary
89 To construct a ColortermDict use keyword arguments:
91 where dataDict
is a Python dict of filterName: Colorterm
94 'g':
Colorterm(primary=
"g", secondary=
"r", c0=-0.00816446, c1=-0.08366937, c2=-0.00726883),
95 'r': Colorterm(primary="r", secondary="i", c0= 0.00231810, c1= 0.01284177, c2=-0.03068248),
96 'i':
Colorterm(primary=
"i", secondary=
"z", c0= 0.00130204, c1=-0.16922042, c2=-0.01374245),
98 The constructor will likely be simplified at some point.
100 This
is subclass of Config. That
is a bit of a hack to make it easy to store the data
101 in an appropriate obs_* package
as a config override file. In the long term some other
102 means of persistence will be used, at which point the constructor can be made saner.
104 data = ConfigDictField(
105 doc="Mapping of filter name to Colorterm",
112 class ColortermLibrary(Config):
113 """!A mapping of photometric reference catalog name
or glob to ColortermDict
115 This allows photometric calibration using a variety of reference catalogs.
117 To construct a ColortermLibrary, use keyword arguments:
119 where dataDict
is a Python dict of catalog_name_or_glob: ColortermDict
124 'g':
Colorterm(primary=
"g", secondary=
"g"),
125 'r': Colorterm(primary="r", secondary="r"),
129 'g':
Colorterm(primary=
"g", secondary=
"r", c0=-0.00816446, c1=-0.08366937, c2=-0.00726883),
130 'r': Colorterm(primary="r", secondary="i", c0= 0.00231810, c1= 0.01284177, c2=-0.03068248),
135 This
is subclass of Config. That
is a bit of a hack to make it easy to store the data
136 in an appropriate obs_* package
as a config override file. In the long term some other
137 means of persistence will be used, at which point the constructor can be made saner.
139 data = ConfigDictField(
140 doc="Mapping of reference catalog name (or glob) to ColortermDict",
142 itemtype=ColortermDict,
146 def getColorterm(self, filterName, photoCatName, doRaise=True):
147 """!Get the appropriate Colorterm
from the library
149 Use dict of color terms
in the library that matches the photoCatName.
150 If the photoCatName exactly matches an entry
in the library, that
151 dict
is used; otherwise
if the photoCatName matches a single glob (shell syntax,
152 e.g.,
"sdss-*" will match
"sdss-dr8"), then that
is used. If there
is no
153 exact match
and no unique match to the globs,
raise an exception.
155 @param filterName name of filter
156 @param photoCatName name of photometric reference catalog
from which to retrieve the data.
157 This argument
is not glob-expanded (but the catalog names
in the library are,
158 if no exact match
is found).
159 @param[
in] doRaise
if True then
raise ColortermNotFoundError
if no suitable Colorterm found;
160 if False then
return a null Colorterm with filterName
as the primary
and secondary filter
161 @
return the appropriate Colorterm
163 @throw ColortermNotFoundError
if no suitable Colorterm found
and doRaise true;
164 other exceptions may be raised
for unexpected errors, regardless of the value of doRaise
167 trueRefCatName = None
168 ctDictConfig = self.data.get(photoCatName)
169 if ctDictConfig is None:
170 # try glob expression
171 matchList = [libRefNameGlob for libRefNameGlob in self.data
172 if fnmatch.fnmatch(photoCatName, libRefNameGlob)]
173 if len(matchList) == 1:
174 trueRefCatName = matchList[0]
175 ctDictConfig = self.data[trueRefCatName]
176 elif len(matchList) > 1:
177 raise ColortermNotFoundError(
178 "Multiple library globs match photoCatName %r: %s" % (photoCatName, matchList))
180 raise ColortermNotFoundError("No colorterm dict found with photoCatName %r" % photoCatName)
181 ctDict = ctDictConfig.data
182 if filterName not in ctDict:
183 # Perhaps it's an alias
185 filterName = Filter(Filter(filterName).getId()).getName()
186 except pexExcept.NotFoundError:
187 pass # this will be handled shortly
188 if filterName not in ctDict:
189 errMsg = "No colorterm found for filter %r with photoCatName %r" % (filterName, photoCatName)
190 if trueRefCatName is not None:
191 errMsg += " = catalog %r" % (trueRefCatName,)
192 raise ColortermNotFoundError(errMsg)
193 return ctDict[filterName]
194 except ColortermNotFoundError:
198 return Colorterm(filterName, filterName)
A mapping of filterName to Colorterm.
A mapping of photometric reference catalog name or glob to ColortermDict.
Colorterm correction for one pair of filters.