Skip to content

Commit 5749302

Browse files
committed
Merge branch 'master' of github.com:rbiswas4/ObsCond
2 parents 045aeef + 558ea48 commit 5749302

File tree

5 files changed

+6401
-138
lines changed

5 files changed

+6401
-138
lines changed

examples/Demo_SkyBrightness.ipynb

+193-123
Large diffs are not rendered by default.

examples/dc2_cadence.ipynb

+5,906
Large diffs are not rendered by default.

obscond/observingPotential.py

+272
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,272 @@
1+
from __future__ import print_function, division, absolute_import
2+
3+
__all__ = ['ObservationPotential']
4+
import time
5+
import numpy as np
6+
import pandas as pd
7+
8+
9+
import lsst.sims.skybrightness as sb
10+
from lsst.sims.utils import (Site, approx_RaDec2AltAz)
11+
import ephem
12+
from obscond import SkyCalculations as sm
13+
14+
15+
from lsst.sims.utils import angularSeparation
16+
from scipy.interpolate import interp1d
17+
18+
class ObservationPotential(object):
19+
"""
20+
Class to define the potential for observations
21+
22+
23+
Parameters
24+
----------
25+
fieldRA : float, in radians
26+
RA of the field
27+
fieldDec : float, in radians
28+
Dec of the field
29+
observatory : string, defaults to `LSST`
30+
string specifying observatory to `ephem`
31+
"""
32+
def __init__(self, fieldRA, fieldDec,
33+
observatory='LSST'):
34+
self.ra = np.degrees(fieldRA)
35+
self.dec = np.degrees(fieldDec)
36+
self.site = Site(observatory)
37+
self.sun = ephem.Sun()
38+
self.moon = ephem.Moon()
39+
self.obs = ephem.Observer()
40+
self.obs.lat = np.radians(self.site.latitude)
41+
self.obs.long = np.radians(self.site.longitude)
42+
self.obs.elevation = self.site.height
43+
self.doff = ephem.Date(0) - ephem.Date('1858/11/17')
44+
self._available_times = None
45+
self.sec = 1.0 / 24.0 / 60.0/ 60.0
46+
47+
def moonCoords_singleTime(self, mjd):
48+
"""
49+
returns the moon ra, dec, and alt in radians
50+
51+
Parameters
52+
----------
53+
mjd : `np.float`, unit day
54+
time of observation
55+
56+
Returns
57+
-------
58+
moon ra: radians
59+
moon dec: radians
60+
moon alt: radians
61+
"""
62+
self.obs.date = mjd - self.doff
63+
self.moon.compute(self.obs)
64+
return self.moon.ra, self.moon.dec, self.moon.alt
65+
66+
67+
def sunAlt_singleTime(self, tt):
68+
"""return the sun Altitude at a time tt in radians
69+
70+
Parameters
71+
----------
72+
tt : `np.float`, unit day
73+
time at which altitude is desired in mjd
74+
75+
Returns
76+
-------
77+
sun alt: radians
78+
"""
79+
self.obs.date = tt - self.doff
80+
self.sun.compute(self.obs)
81+
82+
return self.sun.alt
83+
84+
def sunAlt(self, mjd):
85+
"""return the sun Altitude at an array of times in degrees
86+
87+
Parameters
88+
----------
89+
mjd : array-like, MJD
90+
sequence of times of observation in MJD
91+
"""
92+
sunAlt = np.degrees(list(self.sunAlt_singleTime(tt) for tt in mjd))
93+
return sunAlt
94+
95+
def moonCoords(self, mjd):
96+
"""return the moon coordinates (ra, dec, Alt) at an array of times in
97+
degrees
98+
99+
100+
Parameters
101+
----------
102+
mjd : sequence of floats
103+
Times in Modified Julian Date
104+
105+
Returns
106+
-------
107+
moon ra: degrees
108+
moon dec: degrees
109+
moon alt: degrees
110+
"""
111+
moonRA, moonDec, moonAlt = list(zip(*(self.moonCoords_singleTime(tt) for tt in mjd)))
112+
return np.degrees(moonRA), np.degrees(moonDec), np.degrees(moonAlt)
113+
114+
115+
def field_coords(self, fieldRA, fieldDec, mjd):
116+
"""Return the field Coordinates in degrees.
117+
118+
Parameters
119+
----------
120+
fieldRA : float, or array, degrees
121+
RA of the field
122+
fiedlDec : float or array, degrees
123+
Dec of the field
124+
mjd : float or array
125+
Returns
126+
-------
127+
alt : degrees
128+
az : degrees
129+
"""
130+
ra = np.ravel(fieldRA)
131+
dec = np.ravel(fieldDec)
132+
mjd = np.ravel(mjd)
133+
134+
# note that all angle arguments are in degrees
135+
alt, az = approx_RaDec2AltAz(ra=ra, dec=dec,
136+
lat=self.site.latitude,
137+
lon=self.site.longitude,
138+
mjd=mjd,
139+
lmst=None)
140+
return alt, az
141+
142+
def potential_obscond(self, t, fieldRA, fieldDec,
143+
nightOffset=59579.6):
144+
"""
145+
Calculate the observing Conditions at a sequence of mjd values
146+
`t` for a location with ra and dec `fieldRA` and `fieldDec` in
147+
`degrees`.
148+
Parameters
149+
----------
150+
t : times at which observations are being made
151+
152+
fieldRA : RA, degree
153+
154+
fieldDec : Dec, degree
155+
156+
nightOffset : mjd value, defaults to 59579.6
157+
mjd value for night = 0 of the survey.
158+
"""
159+
alt, az = self.field_coords(fieldRA, fieldDec, mjd=t)
160+
moonra, moondec, moonalt = self.moonCoords(mjd=t)
161+
sunAlt = self.sunAlt(mjd=t)
162+
163+
df = pd.DataFrame(dict(mjd=t,
164+
alt=alt,
165+
az=az,
166+
sunAlt=sunAlt,
167+
moonRA=moonra,
168+
moonDec=moondec,
169+
moonAlt=moonalt,
170+
night=np.floor(t-59579.6).astype(np.int)))
171+
172+
df['moonDist'] = angularSeparation(moonra, moondec,
173+
np.degrees(self.ra),
174+
np.degrees(self.dec))
175+
176+
return df
177+
178+
def available_times(self, potential_times, constraints):
179+
"""returns available times
180+
"""
181+
self._available_times = potential_times.query(constraints)
182+
return self._available_times
183+
184+
@staticmethod
185+
def dc2_sequence(start_time, year_block, delta=1):
186+
"""
187+
188+
Parameters
189+
----------
190+
start_time :
191+
192+
year_block :
193+
194+
delta : , defaults to 1.
195+
"""
196+
sec = 1.0 / 24.0/60./60.
197+
198+
if year_block == 1:
199+
fraction = 0.75
200+
201+
if year_block == 2:
202+
fraction = 0.5
203+
delta = 0.
204+
205+
standard_sequence = np.array(list((20, 10, 20, 26, 20)))
206+
time = start_time
207+
l = []
208+
visitlist = []
209+
seq = standard_sequence
210+
extravisits = np.array([0, 1, 0, 1, 0]) * delta
211+
#print(seq)
212+
bandlist = []
213+
214+
# Iterate through the standard list of band, standard visit sequences
215+
# For on and off years
216+
for band, visits, morevisits in zip(list('rgizy'), seq, extravisits):
217+
numVisits = np.floor(visits * fraction) + morevisits
218+
times = np.linspace(time, time + (numVisits - 1) * 38 * sec,
219+
numVisits)
220+
l.append(times)
221+
visitlist.append(numVisits)
222+
time = times[-1] + 150.0 * sec
223+
bandlist.append(np.repeat(band, numVisits))
224+
df = pd.DataFrame(dict(expMJD=np.concatenate(l),
225+
filter=np.concatenate(bandlist)))
226+
return df, visitlist
227+
228+
@staticmethod
229+
def dc2_visits(start_times, year_block, delta=1, pointings=None):
230+
231+
vs = []
232+
for st in start_times.values:
233+
df, vl = ObservationPotential.dc2_sequence(st, year_block, delta)
234+
vs.append(df)
235+
df = pd.concat(vs)
236+
df['night'] = np.floor(df.expMJD - 59579.6)
237+
238+
if pointings is not None:
239+
rawSeeing = interp1d(pointings.expMJD.values,
240+
pointings.rawSeeing.values,
241+
kind='nearest')
242+
243+
df['rawSeeing'] = rawSeeing(df.expMJD.values)
244+
alt, az = approx_RaDec2AltAz(ra=ra, dec=dec,
245+
lat=self.site.latitude,
246+
lon=self.site.longitude,
247+
mjd=df.expMJD.values,
248+
lmst=None)
249+
df['alt'] = alt
250+
df['az'] = az
251+
252+
return df
253+
254+
@staticmethod
255+
def nightStats(availabletimes):
256+
df = availabletimes.groupby('night').agg(dict(mjd=(min, max))).reset_index()
257+
df = pd.DataFrame(df.values, columns=('night', 'minmjd', 'maxmjd'))
258+
df['availTime'] = (df.maxmjd - df.minmjd) * 24.0
259+
return df.set_index('night')
260+
261+
@staticmethod
262+
def start_times(nightStats, chosen_nights, rng):
263+
zz = nightStats
264+
df = zz.loc[chosen_nights]#.tolist())
265+
df['maxtime'] = df.maxmjd - 1.25 / 24.
266+
random = rng.uniform(size=len(chosen_nights))
267+
start_time = df.minmjd + (df.maxtime - df.minmjd) * random
268+
return start_time
269+
270+
@staticmethod
271+
def timerange(series):
272+
return (max(series) - min(series))*24.0

obscond/skybrightness.py

+29-14
Original file line numberDiff line numberDiff line change
@@ -134,9 +134,8 @@ def calculatePointings(self, pointings,
134134
for obsHistID, row in pointings.iterrows():
135135
ra =row[raCol]
136136
dec =row[decCol]
137-
bandName = row[bandCol]
138137
mjd = row[mjdCol]
139-
FWHMeff = row[FWHMeffCol]
138+
bandName = row[bandCol]
140139
sm.setRaDecMjd(lon=ra, lat=dec,
141140
filterNames=bandName, mjd=mjd,
142141
degrees=False, azAlt=False)
@@ -161,13 +160,16 @@ def calculatePointings(self, pointings,
161160
sunAz[count] = mydict['sunAz']
162161

163162
if calcDepths:
163+
bandName = row[bandCol]
164+
FWHMeff = row[FWHMeffCol]
164165
if count == 0:
165166
resultCols += ['fiveSigmaDepth']
166167
fiveSigmaDepth[count] = self.fiveSigmaDepth(bandName,
167168
FWHMeff, sm=sm,
168169
provided_airmass=airmass[count],
169170
use_provided_airmass=False)
170171
if calcSkyMags:
172+
bandName = row[bandCol]
171173
if count == 0:
172174
resultCols += ['filtSkyBrightness']
173175
skymags[count] = self.skymag(bandName, sm=sm,
@@ -176,17 +178,30 @@ def calculatePointings(self, pointings,
176178
idxs[count] = obsHistID
177179
count += 1
178180

179-
df = pd.DataFrame(dict(obsHistID=idxs, filtSkyBrightness=skymags,
180-
fiveSigmaDepth=fiveSigmaDepth,
181-
altitude=altitude,
182-
azimuth=azimuth,
183-
airmass=airmass,
184-
moonRA=moonRA,
185-
moonDec=moonDec,
186-
moonAZ=moonAZ,
187-
moonAlt=moonAlt,
188-
moonPhase=moonPhase,
189-
sunAlt=sunAlt,
190-
sunAz=sunAz)).set_index('obsHistID')
181+
if calcDepths:
182+
df = pd.DataFrame(dict(obsHistID=idxs, filtSkyBrightness=skymags,
183+
fiveSigmaDepth=fiveSigmaDepth,
184+
altitude=altitude,
185+
azimuth=azimuth,
186+
airmass=airmass,
187+
moonRA=moonRA,
188+
moonDec=moonDec,
189+
moonAZ=moonAZ,
190+
moonAlt=moonAlt,
191+
moonPhase=moonPhase,
192+
sunAlt=sunAlt,
193+
sunAz=sunAz)).set_index('obsHistID')
194+
else:
195+
df = pd.DataFrame(dict(obsHistID=idxs, filtSkyBrightness=skymags,
196+
altitude=altitude,
197+
azimuth=azimuth,
198+
airmass=airmass,
199+
moonRA=moonRA,
200+
moonDec=moonDec,
201+
moonAZ=moonAZ,
202+
moonAlt=moonAlt,
203+
moonPhase=moonPhase,
204+
sunAlt=sunAlt,
205+
sunAz=sunAz)).set_index('obsHistID')
191206
df.index = df.index.astype(np.int64)
192207
return df[resultCols]

obscond/version.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "0.5.0"
1+
__version__ = "0.5.2"

0 commit comments

Comments
 (0)