Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1# This file is part of faro. 

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 

22import astropy.units as u 

23import numpy as np 

24 

25from lsst.pipe.base import Struct, Task 

26from lsst.verify import Measurement, Datum 

27from lsst.pex.config import Config, Field 

28from lsst.faro.utils.stellar_locus import stellarLocusResid, calcQuartileClippedStats 

29from lsst.faro.utils.matcher import makeMatchedPhotom 

30from lsst.faro.utils.extinction_corr import extinction_corr 

31from lsst.faro.utils.tex import calculateTEx 

32 

33__all__ = ("WPerpConfig", "WPerpTask", "TExConfig", "TExTask") 

34 

35 

36class WPerpConfig(Config): 

37 # These are cuts to apply to the r-band only: 

38 bright_rmag_cut = Field( 

39 doc="Bright limit of catalog entries to include", dtype=float, default=17.0 

40 ) 

41 faint_rmag_cut = Field( 

42 doc="Faint limit of catalog entries to include", dtype=float, default=23.0 

43 ) 

44 

45 

46class WPerpTask(Task): 

47 ConfigClass = WPerpConfig 

48 _DefaultName = "WPerpTask" 

49 

50 def run( 

51 self, metricName, catalogs, photoCalibs=None, astromCalibs=None, dataIds=None 

52 ): 

53 self.log.info("Measuring %s", metricName) 

54 bands = set([f["band"] for f in dataIds]) 

55 

56 if ("g" in bands) & ("r" in bands) & ("i" in bands): 

57 rgicatAll = makeMatchedPhotom(dataIds, catalogs, photoCalibs) 

58 magcut = (rgicatAll["base_PsfFlux_mag_r"] < self.config.faint_rmag_cut) & ( 

59 rgicatAll["base_PsfFlux_mag_r"] > self.config.bright_rmag_cut 

60 ) 

61 rgicat = rgicatAll[magcut] 

62 extVals = extinction_corr(rgicat, bands) 

63 

64 wPerp = self.calcWPerp(rgicat, extVals, metricName) 

65 return wPerp 

66 else: 

67 return Struct(measurement=Measurement(metricName, np.nan * u.mmag)) 

68 

69 def calcWPerp(self, phot, extinctionVals, metricName): 

70 p1, p2, p1coeffs, p2coeffs = stellarLocusResid( 

71 phot["base_PsfFlux_mag_g"] - extinctionVals["A_g"], 

72 phot["base_PsfFlux_mag_r"] - extinctionVals["A_r"], 

73 phot["base_PsfFlux_mag_i"] - extinctionVals["A_i"], 

74 ) 

75 

76 if np.size(p2) > 2: 

77 p2_rms = calcQuartileClippedStats(p2).rms * u.mag 

78 extras = { 

79 "p1_coeffs": Datum( 

80 p1coeffs * u.Unit(""), 

81 label="p1_coefficients", 

82 description="p1 coeffs from wPerp fit", 

83 ), 

84 "p2_coeffs": Datum( 

85 p2coeffs * u.Unit(""), 

86 label="p2_coefficients", 

87 description="p2_coeffs from wPerp fit", 

88 ), 

89 } 

90 

91 return Struct( 

92 measurement=Measurement(metricName, p2_rms.to(u.mmag), extras=extras) 

93 ) 

94 else: 

95 return Struct(measurement=Measurement(metricName, np.nan * u.mmag)) 

96 

97 

98class TExConfig(Config): 

99 minSep = Field( 

100 doc="Inner radius of the annulus in arcmin", dtype=float, default=0.25 

101 ) 

102 maxSep = Field( 

103 doc="Outer radius of the annulus in arcmin", dtype=float, default=1.0 

104 ) 

105 nbins = Field(doc="Number of log-spaced angular bins", dtype=int, default=10) 

106 rhoStat = Field(doc="Rho statistic to be computed", dtype=int, default=1) 

107 shearConvention = Field( 

108 doc="Use shear ellipticity convention rather than distortion", 

109 dtype=bool, 

110 default=False, 

111 ) 

112 columnPsf = Field( 

113 doc="Column to use for PSF model shape moments", 

114 dtype=str, 

115 default="base_SdssShape_psf", 

116 ) 

117 column = Field( 

118 doc="Column to use for shape moments", dtype=str, default="base_SdssShape" 

119 ) 

120 # Eventually want to add option to use only PSF reserve stars 

121 

122 

123class TExTask(Task): 

124 ConfigClass = TExConfig 

125 _DefaultName = "TExTask" 

126 

127 def run( 

128 self, metricName, catalogs, photoCalibs=None, astromCalibs=None, dataIds=None 

129 ): 

130 self.log.info("Measuring %s", metricName) 

131 

132 result = calculateTEx(catalogs, photoCalibs, astromCalibs, self.config) 

133 if "corr" not in result.keys(): 

134 return Struct(measurement=Measurement(metricName, np.nan * u.Unit(""))) 

135 

136 writeExtras = True 

137 if writeExtras: 

138 extras = {} 

139 extras["radius"] = Datum( 

140 result["radius"], label="radius", description="Separation (arcmin)." 

141 ) 

142 extras["corr"] = Datum( 

143 result["corr"], label="Correlation", description="Correlation." 

144 ) 

145 extras["corrErr"] = Datum( 

146 result["corrErr"], 

147 label="Correlation Uncertianty", 

148 description="Correlation Uncertainty.", 

149 ) 

150 else: 

151 extras = None 

152 return Struct( 

153 measurement=Measurement( 

154 metricName, np.mean(np.abs(result["corr"])), extras=extras 

155 ) 

156 )