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"""Some basic physical quantity metrics. 

2""" 

3import lsst.sims.maf.metrics as metrics 

4import lsst.sims.maf.slicers as slicers 

5import lsst.sims.maf.stackers as stackers 

6import lsst.sims.maf.plots as plots 

7import lsst.sims.maf.metricBundles as mb 

8from .colMapDict import ColMapDict 

9from .common import standardSummary, extendedMetrics, standardAngleMetrics, \ 

10 filterList, radecCols, combineMetadata 

11 

12__all__ = ['metadataBasics', 'metadataBasicsAngle', 'allMetadata', 'metadataMaps'] 

13 

14 

15def metadataBasics(value, colmap=None, runName='opsim', 

16 valueName=None, groupName=None, extraSql=None, 

17 extraMetadata=None, nside=64, 

18 ditherStacker=None, ditherkwargs=None): 

19 """Calculate basic metrics on visit metadata 'value' (e.g. airmass, normalized airmass, seeing..). 

20 

21 Calculates extended standard metrics (with unislicer) on the quantity (all visits and per filter), 

22 makes histogram of the value (all visits and per filter), 

23 

24 TODO: handle stackers which need configuration (degrees, in particular) more automatically. 

25 Currently have a hack for HA & normairmass. 

26 

27 Parameters 

28 ---------- 

29 value : str 

30 The column name for the quantity to evaluate. (column name in the database or created by a stacker). 

31 colmap : dict or None, opt 

32 A dictionary with a mapping of column names. Default will use OpsimV4 column names. 

33 runName : str, opt 

34 The name of the simulated survey. Default is "opsim". 

35 valueName : str, opt 

36 The name of the value to be reported in the resultsDb and added to the metric. 

37 This is intended to help standardize metric comparison between sim versions. 

38 value = name as it is in the database (seeingFwhmGeom, etc). 

39 valueName = name to be recorded ('seeingGeom', etc.). Default is None, which will match 'value'. 

40 groupName : str, opt 

41 The group name for this quantity in the displayDict. Default is the same as 'valueName', capitalized. 

42 extraSql : str, opt 

43 Additional constraint to add to any sql constraints (e.g. 'propId=1' or 'fieldID=522'). 

44 Default None, for no additional constraints. 

45 extraMetadata : str, opt 

46 Additional metadata to add before any below (i.e. "WFD"). Default is None. 

47 nside : int, opt 

48 Nside value for healpix slicer. Default 64. 

49 If "None" is passed, the healpixslicer-based metrics will be skipped. 

50 ditherStacker: str or lsst.sims.maf.stackers.BaseDitherStacker 

51 Optional dither stacker to use to define ra/dec columns. 

52 ditherkwargs: dict, opt 

53 Optional dictionary of kwargs for the dither stacker. 

54 

55 Returns 

56 ------- 

57 metricBundleDict 

58 """ 

59 if colmap is None: 

60 colmap = ColMapDict('fbs') 

61 bundleList = [] 

62 

63 if valueName is None: 

64 valueName = value 

65 

66 if groupName is None: 

67 groupName = valueName.capitalize() 

68 subgroup = extraMetadata 

69 else: 

70 groupName = groupName.capitalize() 

71 subgroup = valueName.capitalize() 

72 

73 if subgroup is None: 

74 subgroup = 'All visits' 

75 

76 displayDict = {'group': groupName, 'subgroup': subgroup} 

77 

78 raCol, decCol, degrees, ditherStacker, ditherMeta = radecCols(ditherStacker, colmap, ditherkwargs) 

79 extraMetadata = combineMetadata(extraMetadata, ditherMeta) 

80 # Set up basic all and per filter sql constraints. 

81 filterlist, colors, orders, sqls, metadata = filterList(all=True, 

82 extraSql=extraSql, 

83 extraMetadata=extraMetadata) 

84 

85 # Hack to make HA work, but really I need to account for any stackers/colmaps. 

86 if value == 'HA': 

87 stackerList = [stackers.HourAngleStacker(lstCol=colmap['lst'], raCol=raCol, 

88 degrees=degrees)] 

89 elif value == 'normairmass': 

90 stackerList = [stackers.NormAirmassStacker(degrees=degrees)] 

91 else: 

92 stackerList = None 

93 if ditherStacker is not None: 

94 if stackerList is None: 

95 stackerList = [ditherStacker] 

96 else: 

97 stackerList.append(ditherStacker) 

98 

99 # Summarize values over all and per filter (min/mean/median/max/percentiles/outliers/rms). 

100 slicer = slicers.UniSlicer() 

101 for f in filterlist: 

102 for m in extendedMetrics(value, replace_colname=valueName): 

103 displayDict['caption'] = '%s for %s.' % (m.name, metadata[f]) 

104 displayDict['order'] = orders[f] 

105 bundle = mb.MetricBundle(m, slicer, sqls[f], stackerList=stackerList, 

106 metadata=metadata[f], displayDict=displayDict) 

107 bundleList.append(bundle) 

108 

109 # Histogram values over all and per filter. 

110 for f in filterlist: 

111 displayDict['caption'] = 'Histogram of %s' % (value) 

112 if valueName != value: 

113 displayDict['caption'] += ' (%s)' % (valueName) 

114 displayDict['caption'] += ' for %s.' % (metadata[f]) 

115 displayDict['order'] = orders[f] 

116 m = metrics.CountMetric(value, metricName='%s Histogram' % (valueName)) 

117 slicer = slicers.OneDSlicer(sliceColName=value) 

118 bundle = mb.MetricBundle(m, slicer, sqls[f], stackerList=stackerList, 

119 metadata=metadata[f], displayDict=displayDict) 

120 bundleList.append(bundle) 

121 

122 # Make maps of min/median/max for all and per filter, per RA/Dec, with standard summary stats. 

123 mList = [] 

124 mList.append(metrics.MinMetric(value, metricName='Min %s' % (valueName))) 

125 mList.append(metrics.MedianMetric(value, metricName='Median %s' % (valueName))) 

126 mList.append(metrics.MaxMetric(value, metricName='Max %s' % (valueName))) 

127 slicer = slicers.HealpixSlicer(nside=nside, latCol=decCol, lonCol=raCol, 

128 latLonDeg=degrees) 

129 subsetPlots = [plots.HealpixSkyMap(), plots.HealpixHistogram()] 

130 for f in filterlist: 

131 for m in mList: 

132 displayDict['caption'] = 'Map of %s' % m.name 

133 if valueName != value: 

134 displayDict['caption'] += ' (%s)' % value 

135 displayDict['caption'] += ' for %s.' % metadata[f] 

136 displayDict['order'] = orders[f] 

137 bundle = mb.MetricBundle(m, slicer, sqls[f], stackerList=stackerList, 

138 metadata=metadata[f], plotFuncs=subsetPlots, 

139 displayDict=displayDict, 

140 summaryMetrics=standardSummary()) 

141 bundleList.append(bundle) 

142 

143 # Set the runName for all bundles and return the bundleDict. 

144 for b in bundleList: 

145 b.setRunName(runName) 

146 return mb.makeBundlesDictFromList(bundleList) 

147 

148 

149def metadataBasicsAngle(value, colmap=None, runName='opsim', 

150 valueName=None, groupName=None, extraSql=None, 

151 extraMetadata=None, nside=64, 

152 ditherStacker=None, ditherkwargs=None): 

153 """Calculate basic metrics on visit metadata 'value', where value is a wrap-around angle. 

154 

155 Calculates extended standard metrics (with unislicer) on the quantity (all visits and per filter), 

156 makes histogram of the value (all visits and per filter), 

157 

158 

159 Parameters 

160 ---------- 

161 value : str 

162 The column name for the quantity to evaluate. (column name in the database or created by a stacker). 

163 colmap : dict or None, opt 

164 A dictionary with a mapping of column names. Default will use OpsimV4 column names. 

165 runName : str, opt 

166 The name of the simulated survey. Default is "opsim". 

167 valueName : str, opt 

168 The name of the value to be reported in the resultsDb and added to the metric. 

169 This is intended to help standardize metric comparison between sim versions. 

170 value = name as it is in the database (seeingFwhmGeom, etc). 

171 valueName = name to be recorded ('seeingGeom', etc.). Default is None, which will match 'value'. 

172 groupName : str, opt 

173 The group name for this quantity in the displayDict. Default is the same as 'valueName', capitalized. 

174 extraSql : str, opt 

175 Additional constraint to add to any sql constraints (e.g. 'propId=1' or 'fieldID=522'). 

176 Default None, for no additional constraints. 

177 extraMetadata : str, opt 

178 Additional metadata to add before any below (i.e. "WFD"). Default is None. 

179 nside : int, opt 

180 Nside value for healpix slicer. Default 64. 

181 If "None" is passed, the healpixslicer-based metrics will be skipped. 

182 ditherStacker: str or lsst.sims.maf.stackers.BaseDitherStacker 

183 Optional dither stacker to use to define ra/dec columns. 

184 ditherkwargs: dict, opt 

185 Optional dictionary of kwargs for the dither stacker. 

186 

187 Returns 

188 ------- 

189 metricBundleDict 

190 """ 

191 if colmap is None: 

192 colmap = ColMapDict('opsimV4') 

193 bundleList = [] 

194 

195 if valueName is None: 

196 valueName = value 

197 

198 if groupName is None: 

199 groupName = valueName.capitalize() 

200 subgroup = extraMetadata 

201 else: 

202 groupName = groupName.capitalize() 

203 subgroup = valueName.capitalize() 

204 

205 if subgroup is None: 

206 subgroup = 'All visits' 

207 

208 displayDict = {'group': groupName, 'subgroup': subgroup} 

209 

210 raCol, decCol, degrees, ditherStacker, ditherMeta = radecCols(ditherStacker, colmap, ditherkwargs) 

211 extraMetadata = combineMetadata(extraMetadata, ditherMeta) 

212 # Set up basic all and per filter sql constraints. 

213 filterlist, colors, orders, sqls, metadata = filterList(all=True, 

214 extraSql=extraSql, 

215 extraMetadata=extraMetadata) 

216 

217 stackerList = [ditherStacker] 

218 

219 # Summarize values over all and per filter. 

220 slicer = slicers.UniSlicer() 

221 for f in filterlist: 

222 for m in standardAngleMetrics(value, replace_colname=valueName): 

223 displayDict['caption'] = '%s for %s.' % (m.name, metadata[f]) 

224 displayDict['order'] = orders[f] 

225 bundle = mb.MetricBundle(m, slicer, sqls[f], stackerList=stackerList, 

226 metadata=metadata[f], displayDict=displayDict) 

227 bundleList.append(bundle) 

228 

229 # Histogram values over all and per filter. 

230 for f in filterlist: 

231 displayDict['caption'] = 'Histogram of %s' % (value) 

232 if valueName != value: 

233 displayDict['caption'] += ' (%s)' % (valueName) 

234 displayDict['caption'] += ' for %s.' % (metadata[f]) 

235 displayDict['order'] = orders[f] 

236 m = metrics.CountMetric(value, metricName='%s Histogram' % (valueName)) 

237 slicer = slicers.OneDSlicer(sliceColName=value) 

238 bundle = mb.MetricBundle(m, slicer, sqls[f], stackerList=stackerList, 

239 metadata=metadata[f], displayDict=displayDict) 

240 bundleList.append(bundle) 

241 

242 # Make maps of min/median/max for all and per filter, per RA/Dec, with standard summary stats. 

243 mList = [] 

244 mList.append(metrics.MeanAngleMetric(value, metricName='AngleMean %s' % (valueName))) 

245 mList.append(metrics.FullRangeAngleMetric(value, metricName='AngleRange %s' % (valueName))) 

246 mList.append(metrics.RmsAngleMetric(value, metricName='AngleRms %s' % (valueName))) 

247 slicer = slicers.HealpixSlicer(nside=nside, latCol=decCol, lonCol=raCol, 

248 latLonDeg=degrees) 

249 subsetPlots = [plots.HealpixSkyMap(), plots.HealpixHistogram()] 

250 for f in filterlist: 

251 for m in mList: 

252 displayDict['caption'] = 'Map of %s' % m.name 

253 if valueName != value: 

254 displayDict['caption'] += ' (%s)' % value 

255 displayDict['caption'] += ' for %s.' % metadata[f] 

256 displayDict['order'] = orders[f] 

257 bundle = mb.MetricBundle(m, slicer, sqls[f], stackerList=stackerList, 

258 metadata=metadata[f], plotFuncs=subsetPlots, 

259 displayDict=displayDict, 

260 summaryMetrics=standardSummary()) 

261 bundleList.append(bundle) 

262 

263 # Set the runName for all bundles and return the bundleDict. 

264 for b in bundleList: 

265 b.setRunName(runName) 

266 return mb.makeBundlesDictFromList(bundleList) 

267 

268 

269def allMetadata(colmap=None, runName='opsim', extraSql=None, extraMetadata=None, 

270 ditherStacker=None, ditherkwargs=None): 

271 """Generate a large set of metrics about the metadata of each visit - 

272 distributions of airmass, normalized airmass, seeing, sky brightness, single visit depth, 

273 hour angle, distance to the moon, and solar elongation. 

274 The exact metadata which is analyzed is set by the colmap['metadataList'] value. 

275 

276 Parameters 

277 ---------- 

278 colmap : dict or None, opt 

279 A dictionary with a mapping of column names. Default will use OpsimV4 column names. 

280 runName : str, opt 

281 The name of the simulated survey. Default is "opsim". 

282 extraSql : str, opt 

283 Sql constraint (such as WFD only). Default is None. 

284 extraMetadata : str, opt 

285 Metadata to identify the sql constraint (such as WFD). Default is None. 

286 

287 Returns 

288 ------- 

289 metricBundleDict 

290 """ 

291 

292 if colmap is None: 

293 colmap = ColMapDict('opsimV4') 

294 

295 bdict = {} 

296 

297 for valueName in colmap['metadataList']: 

298 if valueName in colmap: 

299 value = colmap[valueName] 

300 else: 

301 value = valueName 

302 bdict.update(metadataBasics(value, colmap=colmap, runName=runName, 

303 valueName=valueName, 

304 extraSql=extraSql, extraMetadata=extraMetadata, 

305 ditherStacker=ditherStacker, ditherkwargs=ditherkwargs)) 

306 for valueName in colmap['metadataAngleList']: 

307 if valueName in colmap: 

308 value = colmap[valueName] 

309 else: 

310 value = valueName 

311 bdict.update(metadataBasicsAngle(value, colmap=colmap, runName=runName, 

312 valueName=valueName, 

313 extraSql=extraSql, extraMetadata=extraMetadata, 

314 ditherStacker=ditherStacker, ditherkwargs=ditherkwargs)) 

315 return bdict 

316 

317 

318def metadataMaps(value, colmap=None, runName='opsim', 

319 valueName=None, groupName=None, extraSql=None, 

320 extraMetadata=None, nside=64, 

321 ditherStacker=None, ditherkwargs=None): 

322 """Calculate 25/50/75 percentile values on maps across sky for a single metadata value. 

323 

324 TODO: handle stackers which need configuration (degrees, in particular) more automatically. 

325 Currently have a hack for HA & normairmass. 

326 

327 Parameters 

328 ---------- 

329 value : str 

330 The column name for the quantity to evaluate. (column name in the database or created by a stacker). 

331 colmap : dict or None, opt 

332 A dictionary with a mapping of column names. Default will use OpsimV4 column names. 

333 runName : str, opt 

334 The name of the simulated survey. Default is "opsim". 

335 valueName : str, opt 

336 The name of the value to be reported in the resultsDb and added to the metric. 

337 This is intended to help standardize metric comparison between sim versions. 

338 value = name as it is in the database (seeingFwhmGeom, etc). 

339 valueName = name to be recorded ('seeingGeom', etc.). Default is None, which will match 'value'. 

340 groupName : str, opt 

341 The group name for this quantity in the displayDict. Default is the same as 'valueName', capitalized. 

342 extraSql : str, opt 

343 Additional constraint to add to any sql constraints (e.g. 'propId=1' or 'fieldID=522'). 

344 Default None, for no additional constraints. 

345 extraMetadata : str, opt 

346 Additional metadata to add before any below (i.e. "WFD"). Default is None. 

347 nside : int, opt 

348 Nside value for healpix slicer. Default 64. 

349 If "None" is passed, the healpixslicer-based metrics will be skipped. 

350 ditherStacker: str or lsst.sims.maf.stackers.BaseDitherStacker 

351 Optional dither stacker to use to define ra/dec columns. 

352 ditherkwargs: dict, opt 

353 Optional dictionary of kwargs for the dither stacker. 

354 

355 Returns 

356 ------- 

357 metricBundleDict 

358 """ 

359 if colmap is None: 

360 colmap = ColMapDict('opsimV4') 

361 bundleList = [] 

362 

363 if valueName is None: 

364 valueName = value 

365 

366 if groupName is None: 

367 groupName = valueName.capitalize() 

368 subgroup = extraMetadata 

369 else: 

370 groupName = groupName.capitalize() 

371 subgroup = valueName.capitalize() 

372 

373 if subgroup is None: 

374 subgroup = 'All visits' 

375 

376 displayDict = {'group': groupName, 'subgroup': subgroup} 

377 

378 raCol, decCol, degrees, ditherStacker, ditherMeta = radecCols(ditherStacker, colmap, ditherkwargs) 

379 extraMetadata = combineMetadata(extraMetadata, ditherMeta) 

380 # Set up basic all and per filter sql constraints. 

381 filterlist, colors, orders, sqls, metadata = filterList(all=True, 

382 extraSql=extraSql, 

383 extraMetadata=extraMetadata) 

384 

385 # Hack to make HA work, but really I need to account for any stackers/colmaps. 

386 if value == 'HA': 

387 stackerList = [stackers.HourAngleStacker(lstCol=colmap['lst'], raCol=raCol, 

388 degrees=degrees)] 

389 elif value == 'normairmass': 

390 stackerList = [stackers.NormAirmassStacker(degrees=degrees)] 

391 else: 

392 stackerList = None 

393 if ditherStacker is not None: 

394 if stackerList is None: 

395 stackerList = [ditherStacker] 

396 else: 

397 stackerList.append(ditherStacker) 

398 

399 # Make maps of 25/median/75 for all and per filter, per RA/Dec, with standard summary stats. 

400 mList = [] 

401 mList.append(metrics.PercentileMetric(value, percentile=25, 

402 metricName='25thPercentile %s' % (valueName))) 

403 mList.append(metrics.MedianMetric(value, metricName='Median %s' % (valueName))) 

404 mList.append(metrics.PercentileMetric(value, percentile=75, 

405 metricName='75thPercentile %s' % (valueName))) 

406 slicer = slicers.HealpixSlicer(nside=nside, latCol=decCol, lonCol=raCol, 

407 latLonDeg=degrees) 

408 subsetPlots = [plots.HealpixSkyMap(), plots.HealpixHistogram()] 

409 for f in filterlist: 

410 for m in mList: 

411 displayDict['caption'] = 'Map of %s' % m.name 

412 if valueName != value: 

413 displayDict['caption'] += ' (%s)' % value 

414 displayDict['caption'] += ' for %s.' % metadata[f] 

415 displayDict['order'] = orders[f] 

416 bundle = mb.MetricBundle(m, slicer, sqls[f], stackerList=stackerList, 

417 metadata=metadata[f], plotFuncs=subsetPlots, 

418 displayDict=displayDict, 

419 summaryMetrics=standardSummary()) 

420 bundleList.append(bundle) 

421 

422 # Set the runName for all bundles and return the bundleDict. 

423 for b in bundleList: 

424 b.setRunName(runName) 

425 plotBundles = [] 

426 return mb.makeBundlesDictFromList(bundleList), plotBundles