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(): 

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.CountMetric(), 

118 metrics.MaxMetric(), 

119 metrics.MinMetric(), 

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

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

122 return standardSummary 

123 

124 

125def extendedSummary(): 

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

127 plus 25/75 percentiles.""" 

128 

129 extendedStats = standardSummary() 

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

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

132 return extendedStats 

133 

134 

135def standardMetrics(colname, replace_colname=None): 

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

137 

138 Parameters 

139 ---------- 

140 colname : str 

141 The column name to apply the metrics to. 

142 replace_colname: str or None, opt 

143 Value to replace colname with in the metricName. 

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

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

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

147 

148 Returns 

149 ------- 

150 List of configured metrics. 

151 """ 

152 standardMetrics = [metrics.MeanMetric(colname), 

153 metrics.MedianMetric(colname), 

154 metrics.MinMetric(colname), 

155 metrics.MaxMetric(colname)] 

156 if replace_colname is not None: 

157 for m in standardMetrics: 

158 if len(replace_colname) > 0: 

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

160 else: 

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

162 return standardMetrics 

163 

164 

165def extendedMetrics(colname, replace_colname=None): 

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

167 

168 Parameters 

169 ---------- 

170 colname : str 

171 The column name to apply the metrics to. 

172 replace_colname: str or None, opt 

173 Value to replace colname with in the metricName. 

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

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

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

177 

178 Returns 

179 ------- 

180 List of configured metrics. 

181 """ 

182 extendedMetrics = standardMetrics(colname, replace_colname=None) 

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

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

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

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

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

188 metrics.CountMetric(colname)] 

189 if replace_colname is not None: 

190 for m in extendedMetrics: 

191 if len(replace_colname) > 0: 

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

193 else: 

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

195 return extendedMetrics 

196 

197 

198def standardAngleMetrics(colname, replace_colname=None): 

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

200 

201 Parameters 

202 ---------- 

203 colname : str 

204 The column name to apply the metrics to. 

205 replace_colname: str or None, opt 

206 Value to replace colname with in the metricName. 

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

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

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

210 

211 Returns 

212 ------- 

213 List of configured metrics. 

214 """ 

215 standardAngleMetrics = [metrics.MeanAngleMetric(colname), 

216 metrics.RmsAngleMetric(colname), 

217 metrics.FullRangeAngleMetric(colname), 

218 metrics.MinMetric(colname), 

219 metrics.MaxMetric(colname)] 

220 if replace_colname is not None: 

221 for m in standardAngleMetrics: 

222 if len(replace_colname) > 0: 

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

224 else: 

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

226 return standardAngleMetrics 

227 

228 

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

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

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

232 

233 Parameters 

234 ---------- 

235 times : np.ndarray or list 

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

237 Hval : float 

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

239 Hindex : float, opt 

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

241 Default is 0.33. 

242 

243 Returns 

244 ------- 

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

246 """ 

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

248 cumulative=False), 

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

250 cumulative=True)] 

251 return summaryMetrics 

252 

253 

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

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

256 

257 Parameters 

258 ---------- 

259 requiredChances : int, opt 

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

261 Hindex : float, opt 

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

263 Default is 0.33. 

264 

265 Returns 

266 ------- 

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

268 """ 

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

270 cumulative=False, Hindex=Hindex), 

271 metrics.MoCompletenessMetric(threshold=requiredChances, 

272 cumulative=True, Hindex=Hindex)] 

273 return summaryMetrics 

274 

275 

276def fractionPopulationAtThreshold(thresholds, optnames=None): 

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

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

279 

280 Parameters 

281 ---------- 

282 thresholds : list of float 

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

284 optnames : list of str, opt 

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

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

287 Returns 

288 ------- 

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

290 """ 

291 fracMetrics = [] 

292 for i, threshold in enumerate(thresholds): 

293 if optnames is not None: 

294 opt = optnames[i] 

295 else: 

296 opt = threshold 

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

298 metricName=f'FractionPop {opt}') 

299 fracMetrics.append(m) 

300 return fracMetrics