Coverage for src/galsbi/ucat/filters_util.py: 99%

154 statements  

« prev     ^ index     » next       coverage.py v7.8.0, created at 2025-04-03 17:18 +0000

1# Copyright (C) 2018 ETH Zurich, Institute for Particle Physics and Astrophysics 

2 

3""" 

4Created Sept 2021 

5author: Tomasz Kacprzak 

6 

7This script manipulates filter information. It can create the filters_collection.h5 

8file, which contains all listed filters we use. 

9""" 

10 

11import os 

12from collections import OrderedDict 

13 

14import h5py 

15import numpy as np 

16from cosmic_toolbox import logger 

17from scipy.integrate import simpson as simps 

18 

19LOGGER = logger.get_logger(__file__) 

20 

21 

22def create_filter_collection(dirpath_res): 

23 """ 

24 Create a filter collection file 

25 Currently supported instruments: DECam, VISTA, GenericBessel 

26 """ 

27 

28 def add_decam_filters(filters_collect): 

29 # data downloaded from: 

30 # https://noirlab.edu/science/programs/ctio/filters/Dark-Energy-Camera 

31 filepath_filters = os.path.join( 

32 dirpath_res, "filters/DECam_filters_with_atm.txt" 

33 ) 

34 # LAMBDA g r i z Y atm 

35 filter_data = np.loadtxt(filepath_filters).T 

36 atm = filter_data[-1] 

37 lam = filter_data[0] 

38 for i, b in enumerate(["g", "r", "i", "z", "Y"]): 

39 filters_collect[f"DECam_{b}"] = dict(amp=filter_data[i + 1], lam=lam) 

40 filters_collect[f"DECamNoAtm_{b}"] = dict( 

41 amp=filter_data[i + 1] / atm, lam=lam 

42 ) 

43 LOGGER.info(f"added DECam {b}-band") 

44 

45 b = "u" 

46 decam_u_lam, decam_u_amp = np.loadtxt( 

47 os.path.join(dirpath_res, "filters/DECam_2014_u.res") 

48 ).T 

49 filters_collect[f"DECam_{b}"] = dict(amp=decam_u_amp, lam=decam_u_lam) 

50 LOGGER.info(f"added DECam {b}-band") 

51 

52 def add_bessel_filters(filters_collect): 

53 # generic Bessel filters from from 

54 # http://adsabs.harvard.edu/abs/1990PASP..102.1181B 

55 # http://svo2.cab.inta-csic.es/svo/theory/fps3/index.php?mode=browse&gname=Generic&asttype= 

56 bands = ["B", "I", "R", "U", "V"] 

57 

58 for b in bands: 

59 lam, amp = np.loadtxt( 

60 os.path.join(dirpath_res, f"filters/Generic_Bessell.{b}.dat") 

61 ).T 

62 filters_collect[f"GenericBessel_{b}"] = dict(amp=amp, lam=lam) 

63 LOGGER.info(f"added GenericBessel {b}-band") 

64 

65 bands = ["J", "H", "K", "L", "M"] 

66 for b in bands: 

67 lam, amp = np.loadtxt( 

68 os.path.join(dirpath_res, f"filters/Generic_Bessell_JHKLM.{b}.dat") 

69 ).T 

70 filters_collect[f"GenericBessel_{b}"] = dict(amp=amp, lam=lam) 

71 LOGGER.info(f"added GenericBessel {b}-band") 

72 

73 def add_johnson_filters(filters_collect): 

74 # generic Bessel filters from from 

75 # http://adsabs.harvard.edu/abs/1990PASP..102.1181B 

76 # http://svo2.cab.inta-csic.es/svo/theory/fps3/index.php?mode=browse&gname=Generic&asttype= 

77 bands = ["U", "B", "V", "R", "I", "J", "M"] 

78 

79 for b in bands: 

80 lam, amp = np.loadtxt( 

81 os.path.join(dirpath_res, f"filters/Generic_Johnson.{b}.dat") 

82 ).T 

83 filters_collect[f"GenericJohnson_{b}"] = dict(amp=amp, lam=lam) 

84 LOGGER.info(f"added GenericJohnson {b}-band") 

85 

86 def add_cosmos_filters(filters_collect): 

87 # https://ftp.iap.fr/pub/from_users/hjmcc/COSMOS2015/COSMOS2015_Laigle+.header 

88 # https://cosmos.astro.caltech.edu/page/photom 

89 filters = {} 

90 filters["Vircam_Ks"] = dict( 

91 filename="K_uv.res", telescope="VISTA" 

92 ) # Ks_MAG_AUTO 

93 filters["Vircam_Y"] = dict(filename="Y_uv.res", telescope="VISTA") # Y_MAG_AUTO 

94 filters["Vircam_H"] = dict(filename="H_uv.res", telescope="VISTA") # H_MAG_AUTO 

95 filters["Vircam_J"] = dict(filename="J_uv.res", telescope="VISTA") # J_MAG_AUTO 

96 filters["SuprimeCam_B"] = dict( 

97 filename="B_subaru.res", telescope="SUBARU" 

98 ) # B_MAG_AUTO 

99 filters["SuprimeCam_V"] = dict( 

100 filename="V_subaru.res", telescope="SUBARU" 

101 ) # V_MAG_AUTO 

102 filters["SuprimeCam_ip"] = dict( 

103 filename="i_subaru.res", telescope="SUBARU" 

104 ) # ip_MAG_AUTO 

105 filters["SuprimeCam_r"] = dict( 

106 filename="r_subaru.res", telescope="SUBARU" 

107 ) # r_MAG_AUTO 

108 filters["SuprimeCam_zp"] = dict( 

109 filename="z_subaru.res", telescope="SUBARU" 

110 ) # zp_MAG_AUTO 

111 filters["SuprimeCam_zpp"] = dict( 

112 filename="suprime_FDCCD_z.res", telescope="SUBARU" 

113 ) # zpp_MAG_AUTO 

114 filters["MegaPrime_u"] = dict( 

115 filename="u_megaprime_sagem.res", telescope="CFHT" 

116 ) # u_MAG_AUTO 

117 filters["SuprimeCam_IA427"] = dict( 

118 filename="IA427.SuprimeCam.pb", telescope="SUBARU" 

119 ) # IB427_MAG_AUTO 

120 filters["SuprimeCam_IB464"] = dict( 

121 filename="IA464.SuprimeCam.pb", telescope="SUBARU" 

122 ) # IB464_MAG_AUTO 

123 filters["SuprimeCam_IA484"] = dict( 

124 filename="IA484.SuprimeCam.pb", telescope="SUBARU" 

125 ) # IA484_MAG_AUTO 

126 filters["SuprimeCam_IA505"] = dict( 

127 filename="IA505.SuprimeCam.pb", telescope="SUBARU" 

128 ) # IB505_MAG_AUTO 

129 filters["SuprimeCam_IA527"] = dict( 

130 filename="IA527.SuprimeCam.pb", telescope="SUBARU" 

131 ) # IA527_MAG_AUTO 

132 filters["SuprimeCam_IA574"] = dict( 

133 filename="IA574.SuprimeCam.pb", telescope="SUBARU" 

134 ) # IB574_MAG_AUTO 

135 filters["SuprimeCam_IA624"] = dict( 

136 filename="IA624.SuprimeCam.pb", telescope="SUBARU" 

137 ) # IA624_MAG_AUTO 

138 filters["SuprimeCam_IA679"] = dict( 

139 filename="IA679.SuprimeCam.pb", telescope="SUBARU" 

140 ) # IA679_MAG_AUTO 

141 filters["SuprimeCam_IA709"] = dict( 

142 filename="IA709.SuprimeCam.pb", telescope="SUBARU" 

143 ) # IB709_MAG_AUTO 

144 filters["SuprimeCam_IA738"] = dict( 

145 filename="IA738.SuprimeCam.pb", telescope="SUBARU" 

146 ) # IA738_MAG_AUTO 

147 filters["SuprimeCam_IA767"] = dict( 

148 filename="IA767.SuprimeCam.pb", telescope="SUBARU" 

149 ) # IA767_MAG_AUTO 

150 filters["SuprimeCam_IA827"] = dict( 

151 filename="IA827.SuprimeCam.pb", telescope="SUBARU" 

152 ) # IB827_MAG_AUTO 

153 filters["SuprimeCam_NB711"] = dict( 

154 filename="NB711.SuprimeCam.pb", telescope="SUBARU" 

155 ) # NB711_MAG_AUTO 

156 filters["SuprimeCam_NB816"] = dict( 

157 filename="NB816.SuprimeCam.pb", telescope="SUBARU" 

158 ) # NB816_MAG_AUTO 

159 filters["wircam_H"] = dict( 

160 filename="wircam_H.res", telescope="SUBARU" 

161 ) # Hw_MAG_AUTO 

162 filters["wircam_Ks"] = dict( 

163 filename="wircam_Ks.res", telescope="SUBARU" 

164 ) # Ksw_MAG_AUTO 

165 filters["irac_ch1"] = dict( 

166 filename="irac_ch1.res", telescope="SPITZER" 

167 ) # SPLASH_1_MAG 

168 filters["irac_ch2"] = dict( 

169 filename="irac_ch2.res", telescope="SPITZER" 

170 ) # SPLASH_2_MAG 

171 filters["irac_ch3"] = dict( 

172 filename="irac_ch3.res", telescope="SPITZER" 

173 ) # SPLASH_3_MAG 

174 filters["irac_ch4"] = dict( 

175 filename="irac_ch4.res", telescope="SPITZER" 

176 ) # SPLASH_4_MAG 

177 filters["mips_24"] = dict(filename="mips24.res", telescope="SPITZER") # MAG_24 

178 filters["GALEX_FUV"] = dict( 

179 filename="galex1500.res", telescope="GALEX" 

180 ) # MAG_GALEX_FUV 

181 filters["GALEX_NUV"] = dict( 

182 filename="galex2500.res", telescope="GALEX" 

183 ) # MAG_GALEX_NUV 

184 

185 for f in filters: 

186 lam, amp = np.loadtxt( 

187 os.path.join( 

188 dirpath_res, "filters/filters_cosmos2015", filters[f]["filename"] 

189 ) 

190 ).T 

191 filters_collect[f] = dict(amp=amp, lam=lam) 

192 LOGGER.info(f"added Cosmos2015 {f}") 

193 

194 def add_hsc_filters(filters_collect): 

195 # https://hsc-release.mtk.nao.ac.jp/doc/index.php/survey__pdr3/ 

196 # https://hsc-release.mtk.nao.ac.jp/doc/wp-content/uploads/2021/08/hsc_responses_all_rev4.zip 

197 

198 bands = ["g", "r", "r2", "i", "i2", "z", "y"] 

199 for b in bands: 

200 path = os.path.join( 

201 dirpath_res, "filters/filters_hsc_v2018", f"hsc_{b}_v2018.dat" 

202 ) 

203 lam, amp = np.loadtxt(path, comments="#").T 

204 filters_collect[f"HyperSuprimeCam_{b}"] = dict(amp=amp, lam=lam) 

205 LOGGER.info(f"added HyperSuprimeCam_{b}") 

206 

207 def add_sdss_filters(filters_collect): 

208 # http://svo2.cab.inta-csic.es/svo/theory/fps3/index.php?mode=browse&gname=SLOAN 

209 bands = ["u", "g", "r", "i", "z"] 

210 for b in bands: 

211 path = os.path.join(dirpath_res, f"filters/filters_sdss/SLOAN_SDSS.{b}.dat") 

212 lam, amp = np.loadtxt(path).T 

213 filters_collect[f"SDSS_{b}"] = dict(amp=amp, lam=lam) 

214 LOGGER.info(f"added SDSS_{b}") 

215 

216 def add_vista_filters(filters_collect): 

217 # http://svo2.cab.inta-csic.es/svo/theory/fps3/index.php?mode=browse&gname=Paranal&gname2=VISTA 

218 bands = ["Z", "Y", "J", "H", "Ks"] 

219 for b in bands: 

220 path = os.path.join( 

221 dirpath_res, f"filters/filters_vista/Paranal_VISTA.{b}.dat" 

222 ) 

223 lam, amp = np.loadtxt(path).T 

224 filters_collect[f"VISTA_{b}"] = dict(amp=amp, lam=lam) 

225 LOGGER.info(f"added VISTA_{b}") 

226 for b in bands: 

227 path = os.path.join( 

228 dirpath_res, f"filters/filters_vista/Paranal_VISTA.{b}_filter.dat" 

229 ) 

230 lam, amp = np.loadtxt(path).T 

231 filters_collect[f"VISTA_NoAtm{b}"] = dict(amp=amp, lam=lam) 

232 LOGGER.info(f"added VISTA_NoAtm{b}") 

233 

234 LOGGER.info("============ creating filter collection") 

235 filters_collect = {} 

236 add_decam_filters(filters_collect) 

237 add_bessel_filters(filters_collect) 

238 add_johnson_filters(filters_collect) 

239 add_cosmos_filters(filters_collect) 

240 add_hsc_filters(filters_collect) 

241 add_sdss_filters(filters_collect) 

242 add_vista_filters(filters_collect) 

243 

244 return filters_collect 

245 

246 

247def store_filter_collection(filepath_collection, filters_collect): 

248 # store collection 

249 n_filters = len(filters_collect) 

250 with h5py.File(filepath_collection, "w") as f: 

251 for b in filters_collect: 

252 for k in filters_collect[b]: 

253 f[f"{b}/{k}"] = filters_collect[b][k] 

254 

255 LOGGER.info(f"wrote {filepath_collection} with {n_filters} filters") 

256 LOGGER.info(filters_collect.keys()) 

257 

258 

259def load_filters(filepath_filters, filter_names=None, lam_scale=1): 

260 filters = OrderedDict() 

261 with h5py.File(filepath_filters, "r") as f: 

262 filter_names = list(f.keys()) if filter_names is None else filter_names 

263 for b in filter_names: 

264 amp = np.array(f[b]["amp"]) 

265 lam = np.array(f[b]["lam"]) * lam_scale 

266 integ = simps(x=lam, y=amp / lam) 

267 LOGGER.debug(f"filter {b} integral={integ:2.5e}") 

268 filters[b] = dict(amp=amp, lam=lam, integ=integ) 

269 return filters 

270 

271 

272class UseShortFilterNames: 

273 """ 

274 Interface between short and long filter names 

275 """ 

276 

277 def __init__(self, func, filters_full_names): 

278 self.func = func 

279 self.filters_full_names = filters_full_names 

280 self.filters_full_names_rev = {ff: fs for fs, ff in filters_full_names.items()} 

281 

282 def __call__(self, **kw): 

283 if "filter_names" in kw: 

284 kw["filter_names"] = [ 

285 self.filters_full_names[f] for f in kw["filter_names"] 

286 ] 

287 

288 out = self.func(**kw) 

289 

290 if not isinstance(out, dict): 

291 return out 

292 else: 

293 out_ = {} 

294 for k in out: 

295 if k in self.filters_full_names_rev: 

296 out_[self.filters_full_names_rev[k]] = out[k] 

297 return out_ 

298 

299 def __getattr__(self, name): 

300 return getattr(self.func, name) 

301 

302 

303def get_default_full_filter_names(filters): 

304 filters_full_names = {f: f for f in filters} 

305 

306 return filters_full_names 

307 

308 

309# 'Ks_MAG_AUTO' Ks_uv.res 

310# 'Y_MAG_AUTO' Y_uv.res 

311# 'H_MAG_AUTO' H_uv.res 

312# 'J_MAG_AUTO' J_uv.res 

313# 'B_MAG_AUTO' B_subaru.res 

314# 'V_MAG_AUTO' V_subaru.res 

315# 'ip_MAG_AUTO' i_Subaru.res 

316# 'r_MAG_AUTO' r_subaru.res 

317# 'zp_MAG_AUTO' z_subaru.res 

318# 'zpp_MAG_AUTO' suprime_FDCCD_z.res 

319# 'u_MAG_AUTO' u_megaprime_sagem.res 

320# 'IB427_MAG_AUTO' IB427.SuprimeCam.pb 

321# 'IB464_MAG_AUTO' IB464.SuprimeCam.pb 

322# 'IA484_MAG_AUTO' IA484.SuprimeCam.pb 

323# 'IB505_MAG_AUTO' IB505.SuprimeCam.pb 

324# 'IA527_MAG_AUTO' IA527.SuprimeCam.pb 

325# 'IB574_MAG_AUTO' IB574.SuprimeCam.pb 

326# 'IA624_MAG_AUTO' IA624.SuprimeCam.pb 

327# 'IA679_MAG_AUTO' IA679.SuprimeCam.pb 

328# 'IB709_MAG_AUTO' IB709.SuprimeCam.pb 

329# 'IA738_MAG_AUTO' IA738.SuprimeCam.pb 

330# 'IA767_MAG_AUTO' IA767.SuprimeCam.pb 

331# 'IB827_MAG_AUTO' IB827.SuprimeCam.pb 

332# 'NB711_MAG_AUTO' NB711.SuprimeCam.pb 

333# 'NB816_MAG_AUTO' NB816.SuprimeCam.pb 

334# 'Hw_MAG_AUTO' wircam_H.res 

335# 'Ksw_MAG_AUTO' wircam_Ks.res 

336# 'yHSC_MAG_AUTO' y_HSC.txt 

337# 'SPLASH_1_MAG', irac_ch1.res 

338# 'SPLASH_2_MAG', irac_ch2.res 

339# 'SPLASH_3_MAG', irac_ch3.res 

340# 'SPLASH_4_MAG', irac_ch4.res 

341# 'MAG_24', mips24.res 

342# 'MAG_GALEX_FUV' galex1500.res 

343# 'MAG_GALEX_NUV' galex2500.res