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, ditherStacker=None, ditherkwargs=None): 

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 ditherStacker: str or lsst.sims.maf.stackers.BaseDitherStacker 

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

34 ditherkwargs: dict, opt 

35 Optional dictionary of kwargs for the dither stacker. 

36 

37 Returns 

38 ------- 

39 metricBundleDict 

40 """ 

41 if colmap is None: 

42 colmap = ColMapDict('fbs') 

43 

44 bundleList = [] 

45 

46 sql = '' 

47 metadata = 'All visits' 

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

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

50 sql = extraSql 

51 if extraMetadata is None: 

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

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

54 if extraMetadata is not None: 

55 metadata = extraMetadata 

56 

57 subgroup = metadata 

58 

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

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

61 metadata = combineMetadata(metadata, ditherMeta) 

62 

63 # Set up fO metric. 

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

65 

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

67 

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

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

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

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

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

73 Asky=benchmarkArea, Nvisit=benchmarkNvisits), 

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

75 Asky=benchmarkArea, Nvisit=benchmarkNvisits), 

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

77 Asky=benchmarkArea, Nvisit=benchmarkNvisits), 

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

79 Asky=benchmarkArea, Nvisit=benchmarkNvisits)] 

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

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

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

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

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

85 displayDict['caption'] = caption 

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

87 stackerList = [ditherStacker], 

88 displayDict=displayDict, summaryMetrics=summaryMetrics, 

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

90 bundleList.append(bundle) 

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

92 for b in bundleList: 

93 b.setRunName(runName) 

94 return mb.makeBundlesDictFromList(bundleList) 

95 

96 

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

98 extraSql=None, extraMetadata=None, 

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

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

101 

102 Parameters 

103 ---------- 

104 colmap : dict or None, opt 

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

106 runName : str, opt 

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

108 nside : int, opt 

109 Nside for the healpix slicer. Default 64. 

110 extraSql : str or None, opt 

111 Additional sql constraint to apply to all metrics. 

112 extraMetadata : str or None, opt 

113 Additional metadata to apply to all results. 

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

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

116 ditherkwargs: dict, opt 

117 Optional dictionary of kwargs for the dither stacker. 

118 

119 Returns 

120 ------- 

121 metricBundleDict 

122 """ 

123 if colmap is None: 

124 colmap = ColMapDict('fbs') 

125 bundleList = [] 

126 

127 sql = '' 

128 metadata = 'All visits' 

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

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

131 sql = extraSql 

132 if extraMetadata is None: 

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

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

135 if extraMetadata is not None: 

136 metadata = extraMetadata 

137 

138 subgroup = metadata 

139 

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

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

142 metadata = combineMetadata(metadata, ditherMeta) 

143 

144 rmags_para = [22.4, 24.0] 

145 rmags_pm = [20.5, 24.0] 

146 

147 # Set up parallax/dcr stackers. 

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

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

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

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

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

153 

154 # Set up parallax metrics. 

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

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

157 

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

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

160 # Expected error on parallax at 10 AU. 

161 plotmaxVals = (2.0, 15.0) 

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

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

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

165 summary.extend(standardSummary()) 

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

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

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

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

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

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

172 stackerList=[parallaxStacker, ditherStacker], 

173 displayDict=displayDict, plotDict=plotDict, 

174 summaryMetrics=summary, 

175 plotFuncs=subsetPlots) 

176 bundleList.append(bundle) 

177 displayDict['order'] += 1 

178 

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

180 # This separates the effect of cadence from depth. 

181 for rmag in rmags_para: 

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

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

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

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

186 stackerList=[parallaxStacker, ditherStacker], 

187 displayDict=displayDict, 

188 summaryMetrics=standardSummary(), 

189 plotFuncs=subsetPlots) 

190 bundleList.append(bundle) 

191 displayDict['order'] += 1 

192 # Parallax factor coverage. 

193 for rmag in rmags_para: 

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

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

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

197 seeingCol=colmap['seeingGeom']) 

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

199 stackerList=[parallaxStacker, ditherStacker], 

200 displayDict=displayDict, summaryMetrics=standardSummary(), 

201 plotFuncs=subsetPlots) 

202 bundleList.append(bundle) 

203 displayDict['order'] += 1 

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

205 for rmag in rmags_para: 

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

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

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

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

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

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

212 stackerList=[dcrStacker, parallaxStacker, ditherStacker], 

213 displayDict=displayDict, summaryMetrics=standardSummary(), 

214 plotFuncs=subsetPlots) 

215 bundleList.append(bundle) 

216 displayDict['order'] += 1 

217 

218 # Proper Motion metrics. 

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

220 # Proper motion errors. 

221 plotmaxVals = (1.0, 5.0) 

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

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

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

225 summary.extend(standardSummary()) 

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

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

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

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

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

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

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

233 stackerList=[ditherStacker], 

234 displayDict=displayDict, plotDict=plotDict, 

235 summaryMetrics=summary, 

236 plotFuncs=subsetPlots) 

237 bundleList.append(bundle) 

238 displayDict['order'] += 1 

239 # Normalized proper motion. 

240 for rmag in rmags_pm: 

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

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

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

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

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

246 stackerList=[ditherStacker], 

247 displayDict=displayDict, summaryMetrics=standardSummary(), 

248 plotFuncs=subsetPlots) 

249 bundleList.append(bundle) 

250 displayDict['order'] += 1 

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 rapidRevisitBatch(colmap=None, runName='opsim', 

259 extraSql=None, extraMetadata=None, nside=64, 

260 ditherStacker=None, ditherkwargs=None): 

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

262 

263 Parameters 

264 ---------- 

265 colmap : dict or None, opt 

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

267 runName : str, opt 

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

269 nside : int, opt 

270 Nside for the healpix slicer. Default 64. 

271 extraSql : str or None, opt 

272 Additional sql constraint to apply to all metrics. 

273 extraMetadata : str or None, opt 

274 Additional metadata to apply to all results. 

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

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

277 ditherkwargs: dict, opt 

278 Optional dictionary of kwargs for the dither stacker. 

279 

280 Returns 

281 ------- 

282 metricBundleDict 

283 """ 

284 if colmap is None: 

285 colmap = ColMapDict('fbs') 

286 bundleList = [] 

287 

288 sql = '' 

289 metadata = 'All visits' 

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

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

292 sql = extraSql 

293 if extraMetadata is None: 

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

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

296 if extraMetadata is not None: 

297 metadata = extraMetadata 

298 

299 subgroup = metadata 

300 

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

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

303 metadata = combineMetadata(metadata, ditherMeta) 

304 

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

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

307 

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

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

310 

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

312 dTmax = 30 # time in minutes 

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

314 metricName='NumberOfQuickRevisits') 

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

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

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

318 displayDict['caption'] = caption 

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

320 stackerList=[ditherStacker], 

321 metadata=metadata, displayDict=displayDict, 

322 summaryMetrics=standardSummary(withCount=False)) 

323 bundleList.append(bundle) 

324 displayDict['order'] += 1 

325 

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

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

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

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

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

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

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

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

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

335 scale = pixArea * hp.nside2npix(nside) 

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

337 dTmin=dTmin / 60.0 / 60.0 / 24.0, dTpairs = dTpairs / 60.0 / 24.0, 

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

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

340 cutoff1 = 0.9 

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

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

343 % (nOne, dTmin, dTmax) 

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

345 % (nTwo, dTmin, dTpairs) 

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

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

348 displayDict['caption'] = caption 

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

350 stackerList=[ditherStacker], 

351 metadata=metadata, displayDict=displayDict, summaryMetrics=summaryStats) 

352 bundleList.append(bundle) 

353 displayDict['order'] += 1 

354 

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

356 for b in bundleList: 

357 b.setRunName(runName) 

358 return mb.makeBundlesDictFromList(bundleList) 

359