Coverage for python/lsst/sims/maf/stackers/m5OptimalStacker.py : 42%

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 numpy as np
3from .baseStacker import BaseStacker
4from lsst.sims.utils import Site
5from .generalStackers import FiveSigmaStacker
7__all__ = ['M5OptimalStacker', 'generate_sky_slopes']
10def generate_sky_slopes():
11 """
12 Fit a line to how the sky brightness changes with airmass.
13 """
14 import lsst.sims.skybrightness as sb
15 import healpy as hp
16 sm = sb.SkyModel(mags=True, moon=False, twilight=False, zodiacal=False)
17 mjd = 57000
18 nside = 32
19 airmass_limit = 2.0
20 dec, ra = hp.pix2ang(nside, np.arange(hp.nside2npix(nside)))
21 dec = np.pi/2 - dec
22 sm.setRaDecMjd(ra, dec, mjd)
23 mags = sm.returnMags()
24 filters = mags.dtype.names
25 filter_slopes = {}
26 for filterName in filters:
27 good = np.where((~np.isnan(mags[filterName])) & (sm.airmass < airmass_limit))
28 pf = np.polyfit(sm.airmass[good], mags[filterName][good], 1)
29 filter_slopes[filterName] = pf[0]
30 print(filter_slopes)
33class M5OptimalStacker(BaseStacker):
34 """
35 Make a new m5 column as if observations were taken on the meridian.
36 If the moon is up, assume sky brightness stays the same.
38 Assumes seeing scales as airmass^0.6. Uses linear fits for sky and airmass relation.
40 Parameters
41 ----------
42 airmassCol : str ('airmass')
43 Column name for the airmass per pointing.
44 decCol : str ('dec_rad')
45 Column name for the pointing declination.
46 skyBrightCol: str ('filtSkyBrightness')
47 Column name for the sky brighntess per pointing.
48 filterCol : str ('filter')
49 Column name for the filter name.
50 m5Col : str ('fiveSigmaDepth')
51 Colum name for the five sigma limiting depth per pointing.
52 moonAltCol : str ('moonAlt')
53 Column name for the moon altitude per pointing.
54 sunAltCol : str ('sunAltCol')
55 Column name for the sun altitude column.
56 site : str ('LSST')
57 Name of the site.
59 Returns
60 -------
61 numpy.array
62 Adds a column to that is approximately what the five-sigma depth would have
63 been if the observation had been taken on the meridian.
64 """
65 colsAdded = ['m5Optimal']
67 def __init__(self, airmassCol='airmass', decCol='fieldDec',
68 skyBrightCol='skyBrightness', seeingCol='seeingFwhmEff',
69 filterCol='filter',
70 moonAltCol='moonAlt', sunAltCol='sunAlt',
71 site='LSST'):
73 self.site = Site(site)
74 self.units = ['mags']
75 self.airmassCol = airmassCol
76 self.decCol = decCol
77 self.skyBrightCol = skyBrightCol
78 self.seeingCol = seeingCol
79 self.filterCol = filterCol
80 self.moonAltCol = moonAltCol
81 self.sunAltCol = sunAltCol
82 self.m5_stacker = FiveSigmaStacker()
83 self.m5Col = self.m5_stacker.colsAdded[0]
84 self.colsReq = [airmassCol, decCol, skyBrightCol,
85 seeingCol, filterCol, moonAltCol, sunAltCol]
86 self.colsReq.extend(self.m5_stacker.colsReq)
87 self.colsReq = list(set(self.colsReq))
89 def _run(self, simData, cols_present=False):
90 simData, m5col_present = self.m5_stacker._addStackerCols(simData)
91 simData = self.m5_stacker._run(simData, m5col_present)
92 # kAtm values from lsst.sims.operations gen_output.py
93 kAtm = {'u': 0.50, 'g': 0.21, 'r': 0.13, 'i': 0.10,
94 'z': 0.07, 'y': 0.18}
95 # Linear fits to sky brightness change, no moon, twilight, or zodiacal components
96 # Use generate_sky_slopes to regenerate if needed.
97 skySlopes = {'g': -0.52611780327408397, 'i': -0.67898669252082422,
98 'r': -0.61378749766766827, 'u': -0.27840980367303503,
99 'y': -0.69635091524779691, 'z': -0.69652846002009128}
100 min_z_possible = np.abs(np.radians(simData[self.decCol]) - self.site.latitude_rad)
101 min_airmass_possible = 1./np.cos(min_z_possible)
102 for filterName in np.unique(simData[self.filterCol]):
103 deltaSky = skySlopes[filterName]*(simData[self.airmassCol] - min_airmass_possible)
104 deltaSky[np.where((simData[self.moonAltCol] > 0) |
105 (simData[self.sunAltCol] > np.radians(-18.)))] = 0
106 # Using Approximation that FWHM~X^0.6. So seeing term in m5 of: 0.25 * log (7.0/FWHMeff )
107 # Goes to 0.15 log(FWHM_min / FWHM_eff) in the difference
108 m5Optimal = (simData[self.m5Col] - 0.5*deltaSky -
109 0.15*np.log10(min_airmass_possible / simData[self.airmassCol]) -
110 kAtm[filterName]*(min_airmass_possible - simData[self.airmassCol]))
111 good = np.where(simData[self.filterCol] == filterName)
112 simData['m5Optimal'][good] = m5Optimal[good]
113 return simData