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

1from __future__ import print_function 

2import inspect 

3 

4import lsst.sims.maf.metrics as metrics 

5import lsst.sims.maf.stackers as stackers 

6 

7__all__ = ['combineMetadata', 'filterList', 'radecCols', 'standardSummary', 'extendedSummary', 

8 'standardMetrics', 'extendedMetrics', 'standardAngleMetrics', 

9 'summaryCompletenessAtTime', 'summaryCompletenessOverH', 'fractionPopulationAtThreshold'] 

10 

11 

12def combineMetadata(meta1, meta2): 

13 if meta1 is not None and meta2 is not None: 

14 meta = meta1 + ' ' + meta2 

15 elif meta1 is not None: 

16 meta = meta1 

17 elif meta2 is not None: 

18 meta = meta2 

19 else: 

20 meta = None 

21 return meta 

22 

23 

24def filterList(all=True, extraSql=None, extraMetadata=None): 

25 """Return a list of filters, plot colors and orders. 

26 

27 Parameters 

28 ---------- 

29 all : boolean, opt 

30 Include 'all' in the list of filters and as part of the colors/orders dictionaries. 

31 Default True. 

32 extraSql : str, opt 

33 Additional sql constraint to add to sqlconstraints returned per filter. 

34 Default None. 

35 extraMetadata : str, opt 

36 Substitute metadata to add to metadata strings composed per band. 

37 Default None. 

38 

39 Returns 

40 ------- 

41 list, dict, dict 

42 List of filter names, dictionary of colors (for plots), dictionary of orders (for display) 

43 """ 

44 if all: 

45 filterlist = ('all', 'u', 'g', 'r', 'i', 'z', 'y') 

46 else: 

47 filterlist = ('u', 'g', 'r', 'i', 'z', 'y') 

48 colors = {'u': 'cyan', 'g': 'g', 'r': 'orange', 'i': 'r', 'z': 'm', 'y': 'b'} 

49 orders = {'u': 1, 'g': 2, 'r': 3, 'i': 4, 'z': 5, 'y': 6} 

50 if all: 

51 colors['all'] = 'k' 

52 orders['all'] = 0 

53 sqls = {} 

54 metadata = {} 

55 if extraMetadata is None: 

56 if extraSql is None or len(extraSql) == 0: 

57 md = '' 

58 else: 

59 md = '%s ' % extraSql 

60 else: 

61 md = '%s ' % extraMetadata 

62 for f in filterlist: 

63 if f == 'all': 

64 sqls[f] = '' 

65 metadata[f] = md + 'all bands' 

66 else: 

67 sqls[f] = 'filter = "%s"' % f 

68 metadata[f] = md + '%s band' % f 

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

70 for s in sqls: 

71 if s == 'all': 

72 sqls[s] = extraSql 

73 else: 

74 sqls[s] = '(%s) and (%s)' % (extraSql, sqls[s]) 

75 return filterlist, colors, orders, sqls, metadata 

76 

77 

78def radecCols(ditherStacker, colmap, ditherkwargs=None): 

79 degrees = colmap['raDecDeg'] 

80 if ditherStacker is None: 

81 raCol = colmap['ra'] 

82 decCol = colmap['dec'] 

83 stacker = None 

84 ditherMeta = None 

85 else: 

86 if isinstance(ditherStacker, stackers.BaseDitherStacker): 

87 stacker = ditherStacker 

88 else: 

89 s = stackers.BaseStacker().registry[ditherStacker] 

90 args = [f for f in inspect.getfullargspec(s).args if f.endswith('Col')] 

91 # Set up default dither kwargs. 

92 kwargs = {} 

93 for a in args: 

94 colmapCol = a.replace('Col', '') 

95 if colmapCol in colmap: 

96 kwargs[a] = colmap[colmapCol] 

97 # Update with passed values, if any. 

98 if ditherkwargs is not None: 

99 kwargs.update(ditherkwargs) 

100 stacker = s(degrees=degrees, **kwargs) 

101 raCol = stacker.colsAdded[0] 

102 decCol = stacker.colsAdded[1] 

103 # Send back some metadata information. 

104 ditherMeta = stacker.__class__.__name__.replace('Stacker', '') 

105 if ditherkwargs is not None: 

106 for k, v in ditherkwargs.items(): 

107 ditherMeta += ' ' + '%s:%s' % (k, v) 

108 return raCol, decCol, degrees, stacker, ditherMeta 

109 

110 

111def standardSummary(withCount=True): 

112 """A set of standard summary metrics, to calculate Mean, RMS, Median, #, Max/Min, and # 3-sigma outliers. 

113 """ 

114 standardSummary = [metrics.MeanMetric(), 

115 metrics.RmsMetric(), 

116 metrics.MedianMetric(), 

117 metrics.MaxMetric(), 

118 metrics.MinMetric(), 

119 metrics.NoutliersNsigmaMetric(metricName='N(+3Sigma)', nSigma=3), 

120 metrics.NoutliersNsigmaMetric(metricName='N(-3Sigma)', nSigma=-3.)] 

121 if withCount: 

122 standardSummary += [metrics.CountMetric()] 

123 return standardSummary 

124 

125 

126def extendedSummary(): 

127 """An extended set of summary metrics, to calculate all that is in the standard summary stats, 

128 plus 25/75 percentiles.""" 

129 

130 extendedStats = standardSummary() 

131 extendedStats += [metrics.PercentileMetric(metricName='25th%ile', percentile=25), 

132 metrics.PercentileMetric(metricName='75th%ile', percentile=75)] 

133 return extendedStats 

134 

135 

136def standardMetrics(colname, replace_colname=None): 

137 """A set of standard simple metrics for some quantity. Typically would be applied with unislicer. 

138 

139 Parameters 

140 ---------- 

141 colname : str 

142 The column name to apply the metrics to. 

143 replace_colname: str or None, opt 

144 Value to replace colname with in the metricName. 

145 i.e. if replace_colname='' then metric name is Mean, instead of Mean Airmass, or 

146 if replace_colname='seeingGeom', then metric name is Mean seeingGeom instead of Mean seeingFwhmGeom. 

147 Default is None, which does not alter the metric name. 

148 

149 Returns 

150 ------- 

151 List of configured metrics. 

152 """ 

153 standardMetrics = [metrics.MeanMetric(colname), 

154 metrics.MedianMetric(colname), 

155 metrics.MinMetric(colname), 

156 metrics.MaxMetric(colname)] 

157 if replace_colname is not None: 

158 for m in standardMetrics: 

159 if len(replace_colname) > 0: 

160 m.name = m.name.replace('%s' % colname, '%s' % replace_colname) 

161 else: 

162 m.name = m.name.rstrip(' %s' % colname) 

163 return standardMetrics 

164 

165 

166def extendedMetrics(colname, replace_colname=None): 

167 """An extended set of simple metrics for some quantity. Typically applied with unislicer. 

168 

169 Parameters 

170 ---------- 

171 colname : str 

172 The column name to apply the metrics to. 

173 replace_colname: str or None, opt 

174 Value to replace colname with in the metricName. 

175 i.e. if replace_colname='' then metric name is Mean, instead of Mean Airmass, or 

176 if replace_colname='seeingGeom', then metric name is Mean seeingGeom instead of Mean seeingFwhmGeom. 

177 Default is None, which does not alter the metric name. 

178 

179 Returns 

180 ------- 

181 List of configured metrics. 

182 """ 

183 extendedMetrics = standardMetrics(colname, replace_colname=None) 

184 extendedMetrics += [metrics.RmsMetric(colname), 

185 metrics.NoutliersNsigmaMetric(colname, metricName='N(+3Sigma) ' + colname, nSigma=3), 

186 metrics.NoutliersNsigmaMetric(colname, metricName='N(-3Sigma) ' + colname, nSigma=-3), 

187 metrics.PercentileMetric(colname, percentile=25), 

188 metrics.PercentileMetric(colname, percentile=75), 

189 metrics.CountMetric(colname)] 

190 if replace_colname is not None: 

191 for m in extendedMetrics: 

192 if len(replace_colname) > 0: 

193 m.name = m.name.replace('%s' % colname, '%s' % replace_colname) 

194 else: 

195 m.name = m.name.rstrip(' %s' % colname) 

196 return extendedMetrics 

197 

198 

199def standardAngleMetrics(colname, replace_colname=None): 

200 """A set of standard simple metrics for some quantity which is a wrap-around angle. 

201 

202 Parameters 

203 ---------- 

204 colname : str 

205 The column name to apply the metrics to. 

206 replace_colname: str or None, opt 

207 Value to replace colname with in the metricName. 

208 i.e. if replace_colname='' then metric name is Mean, instead of Mean Airmass, or 

209 if replace_colname='seeingGeom', then metric name is Mean seeingGeom instead of Mean seeingFwhmGeom. 

210 Default is None, which does not alter the metric name. 

211 

212 Returns 

213 ------- 

214 List of configured metrics. 

215 """ 

216 standardAngleMetrics = [metrics.MeanAngleMetric(colname), 

217 metrics.RmsAngleMetric(colname), 

218 metrics.FullRangeAngleMetric(colname), 

219 metrics.MinMetric(colname), 

220 metrics.MaxMetric(colname)] 

221 if replace_colname is not None: 

222 for m in standardAngleMetrics: 

223 if len(replace_colname) > 0: 

224 m.name = m.name.replace('%s' % colname, '%s' % replace_colname) 

225 else: 

226 m.name = m.name.rstrip(' %s' % colname) 

227 return standardAngleMetrics 

228 

229 

230def summaryCompletenessAtTime(times, Hval, Hindex=0.33): 

231 """A simple list of summary metrics to be applied to the Discovery_Time or PreviouslyKnown metrics. 

232 (can be used with any moving object metric which returns the time of discovery). 

233 

234 Parameters 

235 ---------- 

236 times : np.ndarray or list 

237 The times at which to evaluate the completeness @ Hval. 

238 Hval : float 

239 The H value at which to evaluate the completeness (cumulative and differential). 

240 Hindex : float, opt 

241 The index of the power law to integrate H over (for cumulative completeness). 

242 Default is 0.33. 

243 

244 Returns 

245 ------- 

246 List of moving object MoCompletenessAtTime metrics (cumulative and differential) 

247 """ 

248 summaryMetrics = [metrics.MoCompletenessAtTimeMetric(times=times, Hval=Hval, Hindex=Hindex, 

249 cumulative=False), 

250 metrics.MoCompletenessAtTimeMetric(times=times, Hval=Hval, Hindex=Hindex, 

251 cumulative=True)] 

252 return summaryMetrics 

253 

254 

255def summaryCompletenessOverH(requiredChances=1, Hindex=0.33): 

256 """A simple list of summary metrics to be applied to the Discovery_N_Chances metric. 

257 

258 Parameters 

259 ---------- 

260 requiredChances : int, opt 

261 Number of discovery opportunities required to consider an object 'discovered'. 

262 Hindex : float, opt 

263 The index of the power law to integrate H over (for cumulative completeness). 

264 Default is 0.33. 

265 

266 Returns 

267 ------- 

268 List of moving object MoCompleteness metrics (cumulative and differential) 

269 """ 

270 summaryMetrics = [metrics.MoCompletenessMetric(threshold=requiredChances, 

271 cumulative=False, Hindex=Hindex), 

272 metrics.MoCompletenessMetric(threshold=requiredChances, 

273 cumulative=True, Hindex=Hindex)] 

274 return summaryMetrics 

275 

276 

277def fractionPopulationAtThreshold(thresholds, optnames=None): 

278 """Creates a list of summary metrics to be applied to any moving object metric 

279 which reports a float value, calculating the fraction of the population above X. 

280 

281 Parameters 

282 ---------- 

283 thresholds : list of float 

284 The thresholds at which to calculate what fraction of the population exceeds these values. 

285 optnames : list of str, opt 

286 If provided, these names will be used instead of the threshold values when constructing 

287 the metric names. This allows more descriptive summary statistic names. 

288 Returns 

289 ------- 

290 List of moving object MoCompleteness metrics (differential fractions of the population). 

291 """ 

292 fracMetrics = [] 

293 for i, threshold in enumerate(thresholds): 

294 if optnames is not None: 

295 opt = optnames[i] 

296 else: 

297 opt = threshold 

298 m = metrics.MoCompletenessMetric(threshold=threshold, cumulative=False, 

299 metricName=f'FractionPop {opt}') 

300 fracMetrics.append(m) 

301 return fracMetrics