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 """Calculate basic metrics on visit metadata 'value' (e.g. airmass, normalized airmass, seeing..). 

19 Calculates this around the sky (HealpixSlicer), makes histograms of all visits (OneDSlicer), 

20 and calculates statistics on all visits (UniSlicer) for the quantity in all visits and per filter. 

21 

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

23 Currently have a hack for HA & normairmass. 

24 

25 Parameters 

26 ---------- 

27 value : str 

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

29 colmap : dict or None, opt 

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

31 runName : str, opt 

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

33 valueName : str, opt 

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

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

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

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

38 groupName : str, opt 

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

40 extraSql : str, opt 

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

42 Default None, for no additional constraints. 

43 extraMetadata : str, opt 

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

45 nside : int, opt 

46 Nside value for healpix slicer. Default 64. 

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

48 

49 Returns 

50 ------- 

51 metricBundleDict 

52 """ 

53 if colmap is None: 

54 colmap = ColMapDict('fbs') 

55 bundleList = [] 

56 

57 if valueName is None: 

58 valueName = value 

59 

60 if groupName is None: 

61 groupName = valueName.capitalize() 

62 subgroup = extraMetadata 

63 else: 

64 groupName = groupName.capitalize() 

65 subgroup = valueName.capitalize() 

66 

67 if subgroup is None: 

68 subgroup = 'All visits' 

69 

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

71 

72 raCol, decCol, degrees, ditherStacker, ditherMeta = radecCols(None, colmap, None) 

73 extraMetadata = combineMetadata(extraMetadata, ditherMeta) 

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

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

76 extraSql=extraSql, 

77 extraMetadata=extraMetadata) 

78 

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

80 if value == 'HA': 

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

82 degrees=degrees)] 

83 elif value == 'normairmass': 

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

85 else: 

86 stackerList = None 

87 

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

89 slicer = slicers.UniSlicer() 

90 for f in filterlist: 

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

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

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

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

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

96 bundleList.append(bundle) 

97 

98 # Histogram values over all and per filter. 

99 for f in filterlist: 

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

101 if valueName != value: 

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

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

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

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

106 slicer = slicers.OneDSlicer(sliceColName=value) 

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

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

109 bundleList.append(bundle) 

110 

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

112 mList = [] 

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

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

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

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

117 latLonDeg=degrees) 

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

119 for f in filterlist: 

120 for m in mList: 

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

122 if valueName != value: 

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

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

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

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

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

128 displayDict=displayDict, 

129 summaryMetrics=standardSummary()) 

130 bundleList.append(bundle) 

131 

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

133 for b in bundleList: 

134 b.setRunName(runName) 

135 return mb.makeBundlesDictFromList(bundleList) 

136 

137 

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

139 valueName=None, groupName=None, extraSql=None, 

140 extraMetadata=None, nside=64, 

141 ditherStacker=None, ditherkwargs=None): 

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

143 

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

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

146 

147 

148 Parameters 

149 ---------- 

150 value : str 

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

152 colmap : dict or None, opt 

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

154 runName : str, opt 

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

156 valueName : str, opt 

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

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

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

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

161 groupName : str, opt 

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

163 extraSql : str, opt 

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

165 Default None, for no additional constraints. 

166 extraMetadata : str, opt 

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

168 nside : int, opt 

169 Nside value for healpix slicer. Default 64. 

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

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

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

173 ditherkwargs: dict, opt 

174 Optional dictionary of kwargs for the dither stacker. 

175 

176 Returns 

177 ------- 

178 metricBundleDict 

179 """ 

180 if colmap is None: 

181 colmap = ColMapDict('opsimV4') 

182 bundleList = [] 

183 

184 if valueName is None: 

185 valueName = value 

186 

187 if groupName is None: 

188 groupName = valueName.capitalize() 

189 subgroup = extraMetadata 

190 else: 

191 groupName = groupName.capitalize() 

192 subgroup = valueName.capitalize() 

193 

194 if subgroup is None: 

195 subgroup = 'All visits' 

196 

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

198 

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

200 extraMetadata = combineMetadata(extraMetadata, ditherMeta) 

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

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

203 extraSql=extraSql, 

204 extraMetadata=extraMetadata) 

205 

206 stackerList = [ditherStacker] 

207 

208 # Summarize values over all and per filter. 

209 slicer = slicers.UniSlicer() 

210 for f in filterlist: 

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

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

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

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

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

216 bundleList.append(bundle) 

217 

218 # Histogram values over all and per filter. 

219 for f in filterlist: 

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

221 if valueName != value: 

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

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

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

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

226 slicer = slicers.OneDSlicer(sliceColName=value) 

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

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

229 bundleList.append(bundle) 

230 

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

232 mList = [] 

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

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

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

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

237 latLonDeg=degrees) 

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

239 for f in filterlist: 

240 for m in mList: 

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

242 if valueName != value: 

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

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

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

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

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

248 displayDict=displayDict, 

249 summaryMetrics=standardSummary()) 

250 bundleList.append(bundle) 

251 

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

253 for b in bundleList: 

254 b.setRunName(runName) 

255 return mb.makeBundlesDictFromList(bundleList) 

256 

257 

258def allMetadata(colmap=None, runName='opsim', extraSql=None, extraMetadata=None): 

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

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

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

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

263 

264 Parameters 

265 ---------- 

266 colmap : dict or None, opt 

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

268 runName : str, opt 

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

270 extraSql : str, opt 

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

272 extraMetadata : str, opt 

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

274 

275 Returns 

276 ------- 

277 metricBundleDict 

278 """ 

279 

280 if colmap is None: 

281 colmap = ColMapDict('opsimV4') 

282 

283 bdict = {} 

284 

285 for valueName in colmap['metadataList']: 

286 if valueName in colmap: 

287 value = colmap[valueName] 

288 else: 

289 value = valueName 

290 mdict = metadataBasics(value, colmap=colmap, runName=runName, valueName=valueName, 

291 extraSql=extraSql, extraMetadata=extraMetadata) 

292 bdict.update(mdict) 

293 for valueName in colmap['metadataAngleList']: 

294 if valueName in colmap: 

295 value = colmap[valueName] 

296 else: 

297 value = valueName 

298 mdict = metadataBasicsAngle(value, colmap=colmap, runName=runName, valueName=valueName, 

299 extraSql=extraSql, extraMetadata=extraMetadata) 

300 bdict.update(mdict) 

301 return bdict 

302 

303 

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

305 valueName=None, groupName=None, extraSql=None, 

306 extraMetadata=None, nside=64): 

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

308 

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

310 Currently have a hack for HA & normairmass. 

311 

312 Parameters 

313 ---------- 

314 value : str 

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

316 colmap : dict or None, opt 

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

318 runName : str, opt 

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

320 valueName : str, opt 

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

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

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

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

325 groupName : str, opt 

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

327 extraSql : str, opt 

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

329 Default None, for no additional constraints. 

330 extraMetadata : str, opt 

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

332 nside : int, opt 

333 Nside value for healpix slicer. Default 64. 

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

335 

336 Returns 

337 ------- 

338 metricBundleDict 

339 """ 

340 if colmap is None: 

341 colmap = ColMapDict('opsimV4') 

342 bundleList = [] 

343 

344 if valueName is None: 

345 valueName = value 

346 

347 if groupName is None: 

348 groupName = valueName.capitalize() 

349 subgroup = extraMetadata 

350 else: 

351 groupName = groupName.capitalize() 

352 subgroup = valueName.capitalize() 

353 

354 if subgroup is None: 

355 subgroup = 'All visits' 

356 

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

358 

359 raCol, decCol, degrees, ditherStacker, ditherMeta = radecCols(None, colmap, None) 

360 extraMetadata = combineMetadata(extraMetadata, ditherMeta) 

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

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

363 extraSql=extraSql, 

364 extraMetadata=extraMetadata) 

365 

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

367 if value == 'HA': 

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

369 degrees=degrees)] 

370 elif value == 'normairmass': 

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

372 else: 

373 stackerList = None 

374 

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

376 mList = [] 

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

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

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

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

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

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

383 latLonDeg=degrees) 

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

385 for f in filterlist: 

386 for m in mList: 

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

388 if valueName != value: 

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

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

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

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

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

394 displayDict=displayDict, 

395 summaryMetrics=standardSummary()) 

396 bundleList.append(bundle) 

397 

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

399 for b in bundleList: 

400 b.setRunName(runName) 

401 plotBundles = [] 

402 return mb.makeBundlesDictFromList(bundleList), plotBundles