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"""Sets of metrics to look at the SRD metrics. 

2""" 

3import numpy as np 

4import healpy as hp 

5import lsst.sims.maf.metrics as metrics 

6import lsst.sims.maf.slicers as slicers 

7import lsst.sims.maf.stackers as stackers 

8import lsst.sims.maf.plots as plots 

9import lsst.sims.maf.metricBundles as mb 

10from .colMapDict import ColMapDict 

11from .common import standardSummary, radecCols, combineMetadata 

12 

13__all__ = ['fOBatch', 'astrometryBatch', 'rapidRevisitBatch'] 

14 

15 

16def fOBatch(colmap=None, runName='opsim', extraSql=None, extraMetadata=None, nside=64, 

17 benchmarkArea=18000, benchmarkNvisits=825, minNvisits=750): 

18 """Metrics for calculating fO. 

19 

20 Parameters 

21 ---------- 

22 colmap : dict or None, opt 

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

24 runName : str, opt 

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

26 nside : int, opt 

27 Nside for the healpix slicer. Default 64. 

28 extraSql : str or None, opt 

29 Additional sql constraint to apply to all metrics. 

30 extraMetadata : str or None, opt 

31 Additional metadata to apply to all results. 

32 

33 Returns 

34 ------- 

35 metricBundleDict 

36 """ 

37 if colmap is None: 

38 colmap = ColMapDict('fbs') 

39 

40 bundleList = [] 

41 

42 sql = '' 

43 metadata = 'All visits' 

44 # Add additional sql constraint (such as wfdWhere) and metadata, if provided. 

45 if (extraSql is not None) and (len(extraSql) > 0): 

46 sql = extraSql 

47 if extraMetadata is None: 

48 metadata = extraSql.replace('filter =', '').replace('filter=', '') 

49 metadata = metadata.replace('"', '').replace("'", '') 

50 if extraMetadata is not None: 

51 metadata = extraMetadata 

52 

53 subgroup = metadata 

54 

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

56 # Don't want dither info in subgroup (too long), but do want it in bundle name. 

57 metadata = combineMetadata(metadata, ditherMeta) 

58 

59 # Set up fO metric. 

60 slicer = slicers.HealpixSlicer(nside=nside, lonCol=raCol, latCol=decCol, latLonDeg=degrees) 

61 

62 displayDict = {'group': 'SRD FO metrics', 'subgroup': subgroup, 'order': 0} 

63 

64 # Configure the count metric which is what is used for f0 slicer. 

65 metric = metrics.CountExplimMetric(col=colmap['mjd'], metricName='fO', expCol=colmap['exptime']) 

66 plotDict = {'xlabel': 'Number of Visits', 'Asky': benchmarkArea, 

67 'Nvisit': benchmarkNvisits, 'xMin': 0, 'xMax': 1500} 

68 summaryMetrics = [metrics.fOArea(nside=nside, norm=False, metricName='fOArea', 

69 Asky=benchmarkArea, Nvisit=benchmarkNvisits), 

70 metrics.fOArea(nside=nside, norm=True, metricName='fOArea/benchmark', 

71 Asky=benchmarkArea, Nvisit=benchmarkNvisits), 

72 metrics.fONv(nside=nside, norm=False, metricName='fONv', 

73 Asky=benchmarkArea, Nvisit=benchmarkNvisits), 

74 metrics.fONv(nside=nside, norm=True, metricName='fONv/benchmark', 

75 Asky=benchmarkArea, Nvisit=benchmarkNvisits), 

76 metrics.fOArea(nside=nside, norm=False, metricName=f'fOArea_{minNvisits}', 

77 Asky=benchmarkArea, Nvisit=minNvisits)] 

78 caption = 'The FO metric evaluates the overall efficiency of observing. ' 

79 caption += ('foNv: out of %.2f sq degrees, the area receives at least X and a median of Y visits ' 

80 '(out of %d, if compared to benchmark). ' % (benchmarkArea, benchmarkNvisits)) 

81 caption += ('fOArea: this many sq deg (out of %.2f sq deg if compared ' 

82 'to benchmark) receives at least %d visits. ' % (benchmarkArea, benchmarkNvisits)) 

83 displayDict['caption'] = caption 

84 bundle = mb.MetricBundle(metric, slicer, sql, plotDict=plotDict, 

85 stackerList = [ditherStacker], 

86 displayDict=displayDict, summaryMetrics=summaryMetrics, 

87 plotFuncs=[plots.FOPlot()], metadata=metadata) 

88 bundleList.append(bundle) 

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

90 for b in bundleList: 

91 b.setRunName(runName) 

92 return mb.makeBundlesDictFromList(bundleList) 

93 

94 

95def astrometryBatch(colmap=None, runName='opsim', 

96 extraSql=None, extraMetadata=None, 

97 nside=64, ditherStacker=None, ditherkwargs=None): 

98 """Metrics for evaluating proper motion and parallax. 

99 

100 Parameters 

101 ---------- 

102 colmap : dict or None, opt 

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

104 runName : str, opt 

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

106 nside : int, opt 

107 Nside for the healpix slicer. Default 64. 

108 extraSql : str or None, opt 

109 Additional sql constraint to apply to all metrics. 

110 extraMetadata : str or None, opt 

111 Additional metadata to apply to all results. 

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

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

114 ditherkwargs: dict, opt 

115 Optional dictionary of kwargs for the dither stacker. 

116 

117 Returns 

118 ------- 

119 metricBundleDict 

120 """ 

121 if colmap is None: 

122 colmap = ColMapDict('fbs') 

123 bundleList = [] 

124 

125 sql = '' 

126 metadata = 'All visits' 

127 # Add additional sql constraint (such as wfdWhere) and metadata, if provided. 

128 if (extraSql is not None) and (len(extraSql) > 0): 

129 sql = extraSql 

130 if extraMetadata is None: 

131 metadata = extraSql.replace('filter =', '').replace('filter=', '') 

132 metadata = metadata.replace('"', '').replace("'", '') 

133 if extraMetadata is not None: 

134 metadata = extraMetadata 

135 

136 subgroup = metadata 

137 

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

139 # Don't want dither info in subgroup (too long), but do want it in bundle name. 

140 metadata = combineMetadata(metadata, ditherMeta) 

141 

142 rmags_para = [22.4, 24.0] 

143 rmags_pm = [20.5, 24.0] 

144 

145 # Set up parallax/dcr stackers. 

146 parallaxStacker = stackers.ParallaxFactorStacker(raCol=raCol, decCol=decCol, 

147 dateCol=colmap['mjd'], degrees=degrees) 

148 dcrStacker = stackers.DcrStacker(filterCol=colmap['filter'], altCol=colmap['alt'], degrees=degrees, 

149 raCol=raCol, decCol=decCol, lstCol=colmap['lst'], 

150 site='LSST', mjdCol=colmap['mjd']) 

151 

152 # Set up parallax metrics. 

153 slicer = slicers.HealpixSlicer(nside=nside, lonCol=raCol, latCol=decCol, latLonDeg=degrees) 

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

155 

156 displayDict = {'group': 'SRD Parallax', 'subgroup': subgroup, 

157 'order': 0, 'caption': None} 

158 # Expected error on parallax at 10 AU. 

159 plotmaxVals = (2.0, 15.0) 

160 summary = [metrics.AreaSummaryMetric(area=18000, reduce_func=np.median, decreasing=False, 

161 metricName='Median Parallax Error (18k)')] 

162 summary.append(metrics.PercentileMetric(percentile=95, metricName='95th Percentile Parallax Error')) 

163 summary.extend(standardSummary()) 

164 for rmag, plotmax in zip(rmags_para, plotmaxVals): 

165 plotDict = {'xMin': 0, 'xMax': plotmax, 'colorMin': 0, 'colorMax': plotmax} 

166 metric = metrics.ParallaxMetric(metricName='Parallax Error @ %.1f' % (rmag), rmag=rmag, 

167 seeingCol=colmap['seeingGeom'], filterCol=colmap['filter'], 

168 m5Col=colmap['fiveSigmaDepth'], normalize=False) 

169 bundle = mb.MetricBundle(metric, slicer, sql, metadata=metadata, 

170 stackerList=[parallaxStacker, ditherStacker], 

171 displayDict=displayDict, plotDict=plotDict, 

172 summaryMetrics=summary, 

173 plotFuncs=subsetPlots) 

174 bundleList.append(bundle) 

175 displayDict['order'] += 1 

176 

177 # Parallax normalized to 'best possible' if all visits separated by 6 months. 

178 # This separates the effect of cadence from depth. 

179 for rmag in rmags_para: 

180 metric = metrics.ParallaxMetric(metricName='Normalized Parallax @ %.1f' % (rmag), rmag=rmag, 

181 seeingCol=colmap['seeingGeom'], filterCol=colmap['filter'], 

182 m5Col=colmap['fiveSigmaDepth'], normalize=True) 

183 bundle = mb.MetricBundle(metric, slicer, sql, metadata=metadata, 

184 stackerList=[parallaxStacker, ditherStacker], 

185 displayDict=displayDict, 

186 summaryMetrics=standardSummary(), 

187 plotFuncs=subsetPlots) 

188 bundleList.append(bundle) 

189 displayDict['order'] += 1 

190 # Parallax factor coverage. 

191 for rmag in rmags_para: 

192 metric = metrics.ParallaxCoverageMetric(metricName='Parallax Coverage @ %.1f' % (rmag), 

193 rmag=rmag, m5Col=colmap['fiveSigmaDepth'], 

194 mjdCol=colmap['mjd'], filterCol=colmap['filter'], 

195 seeingCol=colmap['seeingGeom']) 

196 bundle = mb.MetricBundle(metric, slicer, sql, metadata=metadata, 

197 stackerList=[parallaxStacker, ditherStacker], 

198 displayDict=displayDict, summaryMetrics=standardSummary(), 

199 plotFuncs=subsetPlots) 

200 bundleList.append(bundle) 

201 displayDict['order'] += 1 

202 # Parallax problems can be caused by HA and DCR degeneracies. Check their correlation. 

203 for rmag in rmags_para: 

204 metric = metrics.ParallaxDcrDegenMetric(metricName='Parallax-DCR degeneracy @ %.1f' % (rmag), 

205 rmag=rmag, seeingCol=colmap['seeingEff'], 

206 filterCol=colmap['filter'], m5Col=colmap['fiveSigmaDepth']) 

207 caption = 'Correlation between parallax offset magnitude and hour angle for a r=%.1f star.' % (rmag) 

208 caption += ' (0 is good, near -1 or 1 is bad).' 

209 bundle = mb.MetricBundle(metric, slicer, sql, metadata=metadata, 

210 stackerList=[dcrStacker, parallaxStacker, ditherStacker], 

211 displayDict=displayDict, summaryMetrics=standardSummary(), 

212 plotFuncs=subsetPlots) 

213 bundleList.append(bundle) 

214 displayDict['order'] += 1 

215 

216 # Proper Motion metrics. 

217 displayDict = {'group': 'SRD Proper Motion', 'subgroup': subgroup, 'order': 0, 'caption': None} 

218 # Proper motion errors. 

219 plotmaxVals = (1.0, 5.0) 

220 summary = [metrics.AreaSummaryMetric(area=18000, reduce_func=np.median, decreasing=False, 

221 metricName='Median Proper Motion Error (18k)')] 

222 summary.append(metrics.PercentileMetric(metricName='95th Percentile Proper Motion Error')) 

223 summary.extend(standardSummary()) 

224 for rmag, plotmax in zip(rmags_pm, plotmaxVals): 

225 plotDict = {'xMin': 0, 'xMax': plotmax, 'colorMin': 0, 'colorMax': plotmax} 

226 metric = metrics.ProperMotionMetric(metricName='Proper Motion Error @ %.1f' % rmag, 

227 rmag=rmag, m5Col=colmap['fiveSigmaDepth'], 

228 mjdCol=colmap['mjd'], filterCol=colmap['filter'], 

229 seeingCol=colmap['seeingGeom'], normalize=False) 

230 bundle = mb.MetricBundle(metric, slicer, sql, metadata=metadata, 

231 stackerList=[ditherStacker], 

232 displayDict=displayDict, plotDict=plotDict, 

233 summaryMetrics=summary, 

234 plotFuncs=subsetPlots) 

235 bundleList.append(bundle) 

236 displayDict['order'] += 1 

237 # Normalized proper motion. 

238 for rmag in rmags_pm: 

239 metric = metrics.ProperMotionMetric(metricName='Normalized Proper Motion @ %.1f' % rmag, 

240 rmag=rmag, m5Col=colmap['fiveSigmaDepth'], 

241 mjdCol=colmap['mjd'], filterCol=colmap['filter'], 

242 seeingCol=colmap['seeingGeom'], normalize=True) 

243 bundle = mb.MetricBundle(metric, slicer, sql, metadata=metadata, 

244 stackerList=[ditherStacker], 

245 displayDict=displayDict, summaryMetrics=standardSummary(), 

246 plotFuncs=subsetPlots) 

247 bundleList.append(bundle) 

248 displayDict['order'] += 1 

249 

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

251 for b in bundleList: 

252 b.setRunName(runName) 

253 return mb.makeBundlesDictFromList(bundleList) 

254 

255 

256def rapidRevisitBatch(colmap=None, runName='opsim', 

257 extraSql=None, extraMetadata=None, nside=64, 

258 ditherStacker=None, ditherkwargs=None): 

259 """Metrics for evaluating proper motion and parallax. 

260 

261 Parameters 

262 ---------- 

263 colmap : dict or None, opt 

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

265 runName : str, opt 

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

267 nside : int, opt 

268 Nside for the healpix slicer. Default 64. 

269 extraSql : str or None, opt 

270 Additional sql constraint to apply to all metrics. 

271 extraMetadata : str or None, opt 

272 Additional metadata to apply to all results. 

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

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

275 ditherkwargs: dict, opt 

276 Optional dictionary of kwargs for the dither stacker. 

277 

278 Returns 

279 ------- 

280 metricBundleDict 

281 """ 

282 if colmap is None: 

283 colmap = ColMapDict('fbs') 

284 bundleList = [] 

285 

286 sql = '' 

287 metadata = 'All visits' 

288 # Add additional sql constraint (such as wfdWhere) and metadata, if provided. 

289 if (extraSql is not None) and (len(extraSql) > 0): 

290 sql = extraSql 

291 if extraMetadata is None: 

292 metadata = extraSql.replace('filter =', '').replace('filter=', '') 

293 metadata = metadata.replace('"', '').replace("'", '') 

294 if extraMetadata is not None: 

295 metadata = extraMetadata 

296 

297 subgroup = metadata 

298 

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

300 # Don't want dither info in subgroup (too long), but do want it in bundle name. 

301 metadata = combineMetadata(metadata, ditherMeta) 

302 

303 slicer = slicers.HealpixSlicer(nside=nside, lonCol=raCol, latCol=decCol, latLonDeg=degrees) 

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

305 

306 displayDict = {'group': 'SRD Rapid Revisits', 'subgroup': subgroup, 

307 'order': 0, 'caption': None} 

308 

309 # Calculate the actual number of revisits within 30 minutes. 

310 dTmax = 30 # time in minutes 

311 m2 = metrics.NRevisitsMetric(dT=dTmax, mjdCol=colmap['mjd'], normed=False, 

312 metricName='NumberOfQuickRevisits') 

313 plotDict = {'colorMin': 400, 'colorMax': 2000, 'xMin': 400, 'xMax': 2000} 

314 caption = 'Number of consecutive visits with return times faster than %.1f minutes, ' % (dTmax) 

315 caption += 'in any filter, all proposals. ' 

316 displayDict['caption'] = caption 

317 bundle = mb.MetricBundle(m2, slicer, sql, plotDict=plotDict, plotFuncs=subsetPlots, 

318 stackerList=[ditherStacker], 

319 metadata=metadata, displayDict=displayDict, 

320 summaryMetrics=standardSummary(withCount=False)) 

321 bundleList.append(bundle) 

322 displayDict['order'] += 1 

323 

324 # Better version of the rapid revisit requirements: require a minimum number of visits between 

325 # dtMin and dtMax, but also a minimum number of visits between dtMin and dtPair (the typical pair time). 

326 # 1 means the healpix met the requirements (0 means did not). 

327 dTmin = 40.0/60.0 # (minutes) 40s minumum for rapid revisit range 

328 dTpairs = 20.0 # minutes (time when pairs should start kicking in) 

329 dTmax = 30.0 # 30 minute maximum for rapid revisit range 

330 nOne = 82 # Number of revisits between 40s-30m required 

331 nTwo = 28 # Number of revisits between 40s - tPairs required. 

332 pixArea = float(hp.nside2pixarea(nside, degrees=True)) 

333 scale = pixArea * hp.nside2npix(nside) 

334 m1 = metrics.RapidRevisitMetric(metricName='RapidRevisits', mjdCol=colmap['mjd'], 

335 dTmin=dTmin / 60.0 / 60.0 / 24.0, dTpairs = dTpairs / 60.0 / 24.0, 

336 dTmax=dTmax / 60.0 / 24.0, minN1=nOne, minN2=nTwo) 

337 plotDict = {'xMin': 0, 'xMax': 1, 'colorMin': 0, 'colorMax': 1, 'logScale': False} 

338 cutoff1 = 0.9 

339 summaryStats = [metrics.FracAboveMetric(cutoff=cutoff1, scale=scale, metricName='Area (sq deg)')] 

340 caption = 'Rapid Revisit: area that receives at least %d visits between %.3f and %.1f minutes, ' \ 

341 % (nOne, dTmin, dTmax) 

342 caption += 'with at least %d of those visits falling between %.3f and %.1f minutes. ' \ 

343 % (nTwo, dTmin, dTpairs) 

344 caption += 'Summary statistic "Area" indicates the area on the sky which meets this requirement.' \ 

345 ' (SRD design specification is 2000 sq deg).' 

346 displayDict['caption'] = caption 

347 bundle = mb.MetricBundle(m1, slicer, sql, plotDict=plotDict, plotFuncs=subsetPlots, 

348 stackerList=[ditherStacker], 

349 metadata=metadata, displayDict=displayDict, summaryMetrics=summaryStats) 

350 bundleList.append(bundle) 

351 displayDict['order'] += 1 

352 

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

354 for b in bundleList: 

355 b.setRunName(runName) 

356 return mb.makeBundlesDictFromList(bundleList) 

357