Coverage for python/lsst/sims/maf/utils/snUtils.py : 11%

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
1import numpy as np
2import matplotlib.pyplot as plt
3from scipy import interpolate
4import numpy.lib.recfunctions as rf
7class Lims:
8 """
9 class to handle light curve of SN
11 Parameters
12 ---------------
13 Li_files : str
14 light curve reference file
15 mag_to_flux_files : str
16 files of magnitude to flux
17 band : str
18 band considered
19 SNR : float
20 Signal-To-Noise Ratio cut
21 mag_range : pair(float),opt
22 mag range considered
23 Default : (23., 27.5)
24 dt_range : pair(float)
25 difference time range considered (cadence)
26 Default : (0.5, 25.)
27 """
29 def __init__(self, Li_files, mag_to_flux_files, band, SNR,
30 mag_range=(23., 27.5), dt_range=(0.5, 25.)):
32 self.band = band
33 self.SNR = SNR
34 self.lims = []
35 self.mag_to_flux = []
36 self.mag_range = mag_range
37 self.dt_range = dt_range
39 for val in Li_files:
40 self.lims.append(self.get_lims(self.band, np.load(val), SNR))
41 for val in mag_to_flux_files:
42 self.mag_to_flux.append(np.load(val))
43 self.interp()
45 def get_lims(self, band, tab, SNR):
46 """
47 Estimations of the limits
49 Parameters
50 ---------------
51 band : str
52 band to consider
53 tab : numpy array
54 table of data
55 SNR : float
56 Signal-to-Noise Ratio cut
58 Returns:
59 -----------
60 dict of limits with redshift and band as keys.
62 """
64 lims = {}
66 for z in np.unique(tab['z']):
68 idx = (tab['z'] == z) & (tab['band'] == 'LSST::'+band)
69 idx &= (tab['flux_e'] > 0.)
70 sel = tab[idx]
72 if len(sel) > 0:
73 li2 = np.sqrt(np.sum(sel['flux_e']**2))
74 lim = 5. * li2 / SNR
75 if z not in lims.keys():
76 lims[z] = {}
77 lims[z][band] = lim
79 return lims
81 def mesh(self, mag_to_flux):
82 """
83 Mesh grid to estimate five-sigma depth values (m5) from mags input.
85 Parameters
86 ---------------
87 mag_to_flux : magnitude to flux values
89 Returns
90 -----------
91 m5 values
92 time difference dt (cadence)
93 metric=sqrt(dt)*F5 where F5 is the 5-sigma flux
95 """
96 dt = np.linspace(self.dt_range[0], self.dt_range[1], 100)
97 m5 = np.linspace(self.mag_range[0], self.mag_range[1], 50)
98 ida = mag_to_flux['band'] == self.band
99 fa = interpolate.interp1d(
100 mag_to_flux[ida]['m5'], mag_to_flux[ida]['flux_e'])
101 f5 = fa(m5)
102 F5, DT = np.meshgrid(f5, dt)
103 M5, DT = np.meshgrid(m5, dt)
104 metric = np.sqrt(DT) * F5
106 return M5, DT, metric
108 def interp(self):
109 """
110 Estimate a grid of interpolated values
111 in the plane (m5, cadence, metric)
113 Parameters
114 ---------------
115 None
117 """
119 M5_all = []
120 DT_all = []
121 metric_all = []
123 for val in self.mag_to_flux:
124 M5, DT, metric = self.mesh(val)
125 M5_all.append(M5)
126 DT_all.append(DT)
127 metric_all.append(metric)
129 sorted_keys = []
130 for i in range(len(self.lims)):
131 sorted_keys.append(np.sort([k for k in self.lims[i].keys()])[::-1])
132 figa, axa = plt.subplots()
134 for kk, lim in enumerate(self.lims):
135 fmt = {}
136 ll = [lim[zz][self.band] for zz in sorted_keys[kk]]
137 cs = axa.contour(M5_all[kk], DT_all[kk], metric_all[kk], ll)
139 points_values = None
140 for io, col in enumerate(cs.collections):
141 if col.get_segments():
143 myarray = col.get_segments()[0]
144 res = np.array(myarray[:, 0], dtype=[('m5', 'f8')])
145 res = rf.append_fields(res, 'cadence', myarray[:, 1])
146 res = rf.append_fields(
147 res, 'z', [sorted_keys[kk][io]]*len(res))
148 if points_values is None:
149 points_values = res
150 else:
151 points_values = np.concatenate((points_values, res))
152 self.points_ref = points_values
154 plt.close(figa) # do not display
156 def interp_griddata(self, data):
157 """
158 Estimate metric interpolation for data (m5,cadence)
160 Parameters
161 ---------------
162 data : data where interpolation has to be done (m5,cadence)
164 Returns
165 -----------
166 griddata interpolation (m5,cadence,metric)
168 """
170 ref_points = self.points_ref
171 res = interpolate.griddata((ref_points['m5'], ref_points['cadence']), ref_points['z'], (
172 data['m5_mean'], data['cadence_mean']), method='cubic')
173 return res
176class GenerateFakeObservations:
177 """ Class to generate Fake observations
179 Parameters
180 ---------
181 config: yaml-like
182 configuration file (parameter choice: filter, cadence, m5,Nseasons, ...)
183 list : str,opt
184 Name of the columns used.
185 Default : 'observationStartMJD', 'fieldRA', 'fieldDec','filter','fiveSigmaDepth','visitExposureTime','numExposures','visitTime','season'
187 Returns
188 ---------
189 recordarray of observations with the fields:
190 MJD, Ra, Dec, band,m5,Nexp, ExpTime, Season
191 """
193 def __init__(self, config,
194 mjdCol='observationStartMJD', RaCol='fieldRA',
195 DecCol='fieldDec', filterCol='filter', m5Col='fiveSigmaDepth',
196 exptimeCol='visitExposureTime', nexpCol='numExposures', seasonCol='season'):
198 self.mjdCol = mjdCol
199 self.m5Col = m5Col
200 self.filterCol = filterCol
201 self.RaCol = RaCol
202 self.DecCol = DecCol
203 self.exptimeCol = exptimeCol
204 self.seasonCol = seasonCol
205 self.nexpCol = nexpCol
207 # now make fake obs
208 self.make_fake(config)
210 def make_fake(self, config):
211 """ Generate Fake observations
213 Parameters
214 ---------
215 config: yaml-like
216 configuration file (parameter choice: filter, cadence, m5,Nseasons, ...)
219 """
220 bands = config['bands']
221 cadence = dict(zip(bands, config['Cadence']))
222 shift_days = dict(
223 zip(bands, [config['shift_days']*io for io in range(len(bands))]))
224 m5 = dict(zip(bands, config['m5']))
225 Nvisits = dict(zip(bands, config['Nvisits']))
226 Exposure_Time = dict(zip(bands, config['Exposure_Time']))
227 inter_season_gap = 300.
229 Ra = config['Ra']
230 Dec = config['Dec']
231 rtot = []
232 # for season in range(1, config['nseasons']+1):
233 for il, season in enumerate(config['seasons']):
234 # mjd_min = config['MJD_min'] + float(season-1)*inter_season_gap
235 mjd_min = config['MJD_min'][il]
236 mjd_max = mjd_min+config['season_length']
238 for i, band in enumerate(bands):
239 mjd = np.arange(mjd_min, mjd_max+cadence[band], cadence[band])
240 mjd += shift_days[band]
241 m5_coadded = self.m5_coadd(m5[band],
242 Nvisits[band],
243 Exposure_Time[band])
244 myarr = np.array(mjd, dtype=[(self.mjdCol, 'f8')])
245 myarr = rf.append_fields(myarr, [self.RaCol, self.DecCol, self.filterCol], [
246 [Ra]*len(myarr), [Dec]*len(myarr), [band]*len(myarr)])
247 myarr = rf.append_fields(myarr, [self.m5Col, self.nexpCol, self.exptimeCol, self.seasonCol], [
248 [m5_coadded]*len(myarr), [Nvisits[band]]*len(myarr), [Nvisits[band]*Exposure_Time[band]]*len(myarr), [season]*len(myarr)])
249 rtot.append(myarr)
251 res = np.copy(np.concatenate(rtot))
252 res.sort(order=self.mjdCol)
254 self.Observations = res
256 def m5_coadd(self, m5, Nvisits, Tvisit):
257 """ Coadded m5 estimation
259 Parameters
260 ---------
261 m5 : list(float)
262 list of five-sigma depth values
263 Nvisits : list(float)
264 list of the number of visits
265 Tvisit : list(float)
266 list of the visit times
268 Returns
269 ---------
270 m5_coadd : list(float)
271 list of m5 coadded values
273 """
274 m5_coadd = m5+1.25*np.log10(float(Nvisits)*Tvisit/30.)
275 return m5_coadd
278class ReferenceData:
279 """
280 class to handle light curve of SN
282 Parameters
283 ---------------
284 Li_files : str
285 light curve reference file
286 mag_to_flux_files : str
287 files of magnitude to flux
288 band : str
289 band considered
290 z : float
291 redshift considered
292 """
294 def __init__(self, Li_files, mag_to_flux_files, band, z):
296 self.band = band
297 self.z = z
298 self.fluxes = []
299 self.mag_to_flux = []
301 for val in Li_files:
302 self.fluxes.append(self.interp_fluxes(
303 self.band, np.load(val), self.z))
304 for val in mag_to_flux_files:
305 self.mag_to_flux.append(
306 self.interp_mag(self.band, np.load(val)))
308 def interp_fluxes(self, band, tab, z):
309 """
310 Flux interpolator
312 Parameters
313 ---------------
314 band : str
315 band considered
316 tab : array
317 reference data with (at least) fields z,band,time,DayMax
318 z : float
319 redshift considered
321 Returns
322 -----
323 list (float) of interpolated fluxes (in e/sec)
324 """
325 lims = {}
326 idx = (np.abs(tab['z'] - z) < 1.e-5) & (tab['band'] == 'LSST::'+band)
327 sel = tab[idx]
328 selc = np.copy(sel)
329 difftime = (sel['time']-sel['DayMax'])
330 selc = rf.append_fields(selc, 'deltaT', difftime)
331 return interpolate.interp1d(selc['deltaT'], selc['flux_e'], bounds_error=False, fill_value=0.)
333 def interp_mag(self, band, tab):
334 """
335 magnitude (m5) to flux (e/sec) interpolator
337 Parameters
338 ---------------
339 band : str
340 band considered
341 tab : array
342 reference data with (at least) fields band,m5,flux_e,
343 z : float
344 redshift considered
346 Returns
347 -----
348 list (float) of interpolated fluxes (in e/sec)
349 """
350 idx = tab['band'] == band
351 sel = tab[idx]
352 return interpolate.interp1d(sel['m5'], sel['flux_e'], bounds_error=False, fill_value=0.)