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#!/usr/bin/env python 

2# 

3# LSST Data Management System 

4# 

5# Copyright 2018 AURA/LSST. 

6# 

7# This product includes software developed by the 

8# LSST Project (http://www.lsst.org/). 

9# 

10# This program is free software: you can redistribute it and/or modify 

11# it under the terms of the GNU General Public License as published by 

12# the Free Software Foundation, either version 3 of the License, or 

13# (at your option) any later version. 

14# 

15# This program is distributed in the hope that it will be useful, 

16# but WITHOUT ANY WARRANTY; without even the implied warranty of 

17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

18# GNU General Public License for more details. 

19# 

20# You should have received a copy of the LSST License Statement and 

21# the GNU General Public License along with this program. If not, 

22# see <https://www.lsstcorp.org/LegalNotices/>. 

23# 

24import os 

25import glob 

26import numpy as np 

27 

28from lsst.afw.image import TransmissionCurve, Filter 

29from lsst.utils import getPackageDir 

30from .hscMapper import HscMapper 

31 

32__all__ = ("getOpticsTransmission", "getSensorTransmission", "getAtmosphereTransmission", 

33 "getFilterTransmission",) 

34 

35DATA_DIR = os.path.join(getPackageDir("obs_subaru"), "hsc", "transmission") 

36 

37HSC_BEGIN = "2012-12-18" # initial date for curves valid for entire lifetime of HSC 

38 

39 

40def getLongFilterName(short): 

41 """Return a long HSC filter name (e.g. 'HSC-R') that's usable as a data ID 

42 value from the short one (e.g. 'r') declared canonical in afw.image.Filter. 

43 """ 

44 HscMapper.addFilters() 

45 if short.startswith("HSC"): 

46 return short 

47 if short.startswith("NB") or short.startswith("IB"): 

48 num = int(short[2:].lstrip("0")) 

49 return "%s%04d" % (short[:2], num) 

50 f = Filter(short) 

51 for a in f.getAliases(): 

52 if a.startswith("HSC") or a.startswith("NB") or a.startswith("IB"): 

53 return a 

54 return short 

55 

56 

57def readTransmissionCurveFromFile(filename, unit="angstrom", atMin=None, atMax=None): 

58 """Load a spatial TransmissionCurve from a text file with wavelengths and 

59 throughputs in columns. 

60 

61 Parameters 

62 ---------- 

63 filename : `str` 

64 Name of the file to read. 

65 unit : `str` 

66 Wavelength unit; one of "nm" or "angstrom". 

67 atMin : `float` 

68 Throughput to use at wavelengths below the tabulated minimum. If 

69 ``None``, the tabulated throughput at the mininum will be used. 

70 atMax : `float` 

71 Throughput to use at wavelengths above the tabulated maximum. If 

72 ``None``, the tabulated throughput at the maximum will be used. 

73 """ 

74 wavelengths, throughput = np.loadtxt(os.path.join(DATA_DIR, filename), usecols=[0, 1], unpack=True) 

75 i = np.argsort(wavelengths) 

76 wavelengths = wavelengths[i] 

77 throughput = throughput[i] 

78 if unit == "nm": 

79 wavelengths *= 10 

80 elif unit != "angstrom": 

81 raise ValueError("Invalid wavelength unit") 

82 if atMin is None: 

83 atMin = throughput[0] 

84 if atMax is None: 

85 atMax = throughput[-1] 

86 return TransmissionCurve.makeSpatiallyConstant(throughput=throughput, wavelengths=wavelengths, 

87 throughputAtMin=atMin, throughputAtMax=atMax) 

88 

89 

90def getOpticsTransmission(): 

91 """Return a dictionary of TransmissionCurves describing the combined 

92 throughput of HSC and the Subaru primary mirror. 

93 

94 Dictionary keys are string dates (YYYY-MM-DD) indicating the beginning of 

95 the validity period for the curve stored as the associated dictionary 

96 value. If the curve is spatially varying, it will be defined in focal 

97 plane coordinates. 

98 

99 Dictionary values may be None to indicate that no TransmissionCurve is 

100 valid after the date provided in the key. 

101 """ 

102 mirror2010 = readTransmissionCurveFromFile("M1-2010s.txt", unit="nm") 

103 camera = readTransmissionCurveFromFile("throughput_popt2.txt") 

104 camera *= readTransmissionCurveFromFile("throughput_win.txt") 

105 return { 

106 HSC_BEGIN: mirror2010*camera, 

107 "2017-10-01": None # mirror recoating begins, approximately 

108 } 

109 

110 

111def getSensorTransmission(): 

112 """Return a nested dictionary of TransmissionCurves describing the 

113 throughput of each sensor. 

114 

115 Outer directionary keys are string dates (YYYY-MM-DD), with values 

116 a dictionary mapping CCD ID to TransmissionCurve. If the curve 

117 is spatially varying, it will be defined in pixel coordinates. 

118 

119 Outer dictionary values may be None to indicate that no TransmissionCurve 

120 is valid after the date provided in the key. 

121 """ 

122 qe = readTransmissionCurveFromFile("qe_ccd_HSC.txt", atMin=0.0, atMax=0.0) 

123 return {HSC_BEGIN: {n: qe for n in range(112)}} 

124 

125 

126def getAtmosphereTransmission(): 

127 """Return a dictionary of TransmissionCurves describing the atmospheric 

128 throughput at Mauna Kea. 

129 

130 Dictionary keys are string dates (YYYY-MM-DD) indicating the beginning of 

131 the validity period for the curve stored as the associated dictionary 

132 value. The curve is guaranteed not to be spatially-varying. 

133 

134 Dictionary values may be None to indicate that no TransmissionCurve is 

135 valid after the date provided in the key. 

136 """ 

137 average = readTransmissionCurveFromFile("modtran_maunakea_am12_pwv15_binned10ang.dat") 

138 return {HSC_BEGIN: average} 

139 

140 

141def getFilterTransmission(): 

142 """Return a nested dictionary of TransmissionCurves describing the 

143 throughput of each HSC filter. 

144 

145 Outer directionary keys are string dates (YYYY-MM-DD), with values 

146 a dictionary mapping filter name to TransmissionCurve. If the curve 

147 is spatially varying, it will be defined in pixel coordinates. 

148 

149 Filter curve names are in the long form used as data ID values (e.g. 

150 'HSC-I'). 

151 

152 Outer dictionary values may be None to indicate that no TransmissionCurve 

153 is valid after the date provided in the key. 

154 """ 

155 module = {} 

156 filename = os.path.join(DATA_DIR, "filterTraces.py") 

157 with open(filename) as file: 

158 exec(compile(file.read(), filename, mode='exec'), module) 

159 result = {} 

160 for band, data in module["FILTER_DATA"].items(): 

161 result[getLongFilterName(band)] = TransmissionCurve.makeRadial( 

162 throughput=data["T"], wavelengths=data["lam"]*10, 

163 radii=data['radius']/module["PIXEL_SIZE"], 

164 throughputAtMin=0.0, throughputAtMax=0.0 

165 ) 

166 for filename in glob.glob(os.path.join(DATA_DIR, "wHSC-*.txt")): 

167 band = getLongFilterName(os.path.split(filename)[1][len("wHSC-"): -len(".txt")]) 

168 if band not in result: 

169 result[band] = readTransmissionCurveFromFile(filename, atMin=0.0, atMax=0.0) 

170 return {HSC_BEGIN: result}