Coverage for python/lsst/obs/subaru/filterFraction.py: 19%

57 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2023-11-04 11:50 +0000

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 

23 

24__all__ = ["FilterFractionPlugin"] 

25 

26 

27class FilterFractionPluginConfig(lsst.meas.base.SingleFramePluginConfig): 

28 pass 

29 

30 

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 """ 

36 

37 ConfigClass = FilterFractionPluginConfig 

38 

39 @classmethod 

40 def getExecutionOrder(cls): 

41 return cls.FLUX_ORDER 

42 

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 ) 

60 

61 def measure(self, measRecord, exposure): 

62 """Count the number of filters used to create the coadd. 

63 

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 """ 

74 

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) 

123 

124 def fail(self, measRecord, error=None): 

125 # this plugin can only raise fatal exceptions 

126 pass