Coverage for python/lsst/obs/subaru/filterFraction.py: 17%
57 statements
« prev ^ index » next coverage.py v6.5.0, created at 2023-02-09 04:31 -0800
« prev ^ index » next coverage.py v6.5.0, created at 2023-02-09 04:31 -0800
1#
2# LSST Data Management System
3# Copyright 2017 LSST/AURA.
4#
5# This product includes software developed by the
6# LSST Project (http://www.lsst.org/).
7#
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation, either version 3 of the License, or
11# (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the LSST License Statement and
19# the GNU General Public License along with this program. If not,
20# see <http://www.lsstcorp.org/LegalNotices/>.
21#
22import lsst.meas.base
24__all__ = ["FilterFractionPlugin"]
27class FilterFractionPluginConfig(lsst.meas.base.SingleFramePluginConfig):
28 pass
31@lsst.meas.base.register("subaru_FilterFraction")
32class FilterFractionPlugin(lsst.meas.base.SingleFramePlugin):
33 """Record the fraction of the input images from two physical_filters
34 at the positions of objects on the coadd.
35 """
37 ConfigClass = FilterFractionPluginConfig
39 @classmethod
40 def getExecutionOrder(cls):
41 return cls.FLUX_ORDER
43 def __init__(self, config, name, schema, metadata):
44 lsst.meas.base.SingleFramePlugin.__init__(self, config, name, schema, metadata)
45 self.unweightedKey = schema.addField(
46 schema.join(name, "unweighted"), type=float,
47 doc=("Fraction of observations taken with the preferred version of this filter. "
48 "For filters with a single version, this will always be 1; for HSC-I or HSC-R, "
49 "the preferred filter is the replacement filter (HSC-I2 or HSC-R2)."),
50 doReplace=True
51 )
52 self.weightedKey = schema.addField(
53 schema.join(name, "weighted"), type=float,
54 doc=("Contribution-weighted fraction of observations taken with the preferred "
55 "version of this filter. "
56 "For filters with a single version, this will always be 1; for HSC HSC-I or HSC-R, "
57 "the preferred filter is the replacement filter (HSC-I2 or HSC-R2)."),
58 doReplace=True
59 )
61 def measure(self, measRecord, exposure):
62 """Count the number of filters used to create the coadd.
64 Parameters
65 ----------
66 measRecord : `lsst.afw.table.SourceRecord`
67 Record describing the object being measured. Previously-measured
68 quantities may be retrieved from here, and it will be updated
69 in-place with the outputs of this plugin.
70 exposure : `lsst.afw.image.ExposureF`
71 The Coadd exposure, which must contain a CoaddInput object
72 describing the inputs to this Coadd, and a valid WCS.
73 """
75 try:
76 ccds = exposure.getInfo().getCoaddInputs().ccds
77 except AttributeError:
78 raise lsst.meas.base.FatalAlgorithmError("FilterFraction can only be run on coadds.")
79 overlapping = ccds.subsetContaining(measRecord.getCentroid(), exposure.getWcs(),
80 includeValidPolygon=True)
81 if not overlapping:
82 measRecord.set(self.key, float("NaN")) # no inputs in any filter
83 return
84 counts = {}
85 weights = {}
86 filterKey = overlapping.schema.find("filter").key
87 try:
88 weightKey = overlapping.schema.find("weight").key
89 except KeyError:
90 weightKey = None
91 for ccd in overlapping:
92 filterName = ccd.get(filterKey)
93 counts[filterName] = counts.get(filterName, 0) + 1
94 if weightKey is not None:
95 weight = ccd.get(weightKey)
96 weights[filterName] = weights.get(filterName, 0.0) + weight
97 if "HSC-I" in counts:
98 weird = set(counts.keys()) - set(["HSC-I", "HSC-I2"])
99 if weird:
100 raise lsst.meas.base.FatalAlgorithmError(
101 "Unexpected filter combination found in coadd: %s" % counts.keys()
102 )
103 measRecord.set(self.unweightedKey, counts.get("HSC-I2", 0.0)/len(overlapping))
104 if weightKey is not None:
105 measRecord.set(self.weightedKey, weights.get("HSC-I2", 0.0)/sum(weights.values()))
106 elif "HSC-R" in counts:
107 weird = set(counts.keys()) - set(["HSC-R", "HSC-R2"])
108 if weird:
109 raise lsst.meas.base.FatalAlgorithmError(
110 "Unexpected filter combination found in coadd: %s" % counts.keys()
111 )
112 measRecord.set(self.unweightedKey, counts.get("HSC-R2", 0.0)/len(overlapping))
113 if weightKey is not None:
114 measRecord.set(self.weightedKey, weights.get("HSC-R2", 0.0)/sum(weights.values()))
115 elif len(counts) > 1:
116 raise lsst.meas.base.FatalAlgorithmError(
117 "Unexpected filter combination found in coadd: %s" % counts.keys()
118 )
119 else:
120 measRecord.set(self.unweightedKey, 1.0)
121 if weightKey is not None:
122 measRecord.set(self.weightedKey, 1.0)
124 def fail(self, measRecord, error=None):
125 # this plugin can only raise fatal exceptions
126 pass