Coverage for python/lsst/sims/maf/stackers/nFollowStacker.py : 57%

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 builtins import zip
2import numpy as np
3from .baseStacker import BaseStacker
4from .coordStackers import raDec2AltAz
6__all__ = ['findTelescopes', 'NFollowStacker']
9def findTelescopes(minSize=3.):
10 """Finds telescopes larger than minSize, from list of large telescopes based on
11 http://astro.nineplanets.org/bigeyes.html.
13 Returns
14 -------
15 np.recarray
16 Array of large telescopes with columns [aperture, name, lat, lon].
17 """
18 # Aperture Name Location http://astro.nineplanets.org/bigeyes.html
19 telescopes = [
20 [10.4, 'Gran Canarias', 'La Palma'],
21 [10.0, 'Keck', 'Mauna Kea'],
22 [10.0, 'Keck II', 'Mauna Kea'],
23 [9.2, 'SALT', 'South African Astronomical Observatory'],
24 [9.2, 'Hobby-Eberly', 'Mt. Fowlkes'],
25 [8.4, 'Large Binocular Telescope', 'Mt. Graham'],
26 [8.3, 'Subaru', 'Mauna Kea'],
27 [8.2, 'Antu', 'Cerro Paranal'],
28 [8.2, 'Kueyen', 'Cerro Paranal'],
29 [8.2, 'Melipal', 'Cerro Paranal'],
30 [8.2, 'Yepun', 'Cerro Paranal'],
31 [8.1, 'Gemini North', 'Mauna Kea'],
32 [8.1, 'Gemini South', 'Cerro Pachon'],
33 [6.5, 'MMT', 'Mt. Hopkins'],
34 [6.5, 'Walter Baade', 'La Serena'],
35 [6.5, 'Landon Clay', 'La Serena'],
36 [6.0, 'Bolshoi Teleskop Azimutalnyi', 'Nizhny Arkhyz'],
37 [6.0, 'LZT', 'British Columbia'],
38 [5.0, 'Hale', 'Palomar Mountain'],
39 [4.3, 'Dicovery Channel', 'Lowell Observatory'],
40 [4.2, 'William Herschel', 'La Palma'],
41 [4.2, 'SOAR', 'Cerro Pachon'],
42 [4.2, 'LAMOST', 'Xinglong Station'],
43 [4.0, 'Victor Blanco', 'Cerro Tololo'],
44 [4.0, 'Vista', 'Cerro Paranal'],
45 [3.9, 'Anglo-Australian', 'Coonabarabran'],
46 [3.8, 'Mayall', 'Kitt Peak'],
47 [3.8, 'UKIRT', 'Mauna Kea'],
48 [3.6, '360', 'Cerro La Silla'],
49 [3.6, 'Canada-France-Hawaii', 'Mauna Kea'],
50 [3.6, 'Telescopio Nazionale Galileo', 'La Palma'],
51 [3.5, 'MPI-CAHA', 'Calar Alto'],
52 [3.5, 'New Technology', 'Cerro La Silla'],
53 [3.5, 'ARC', 'Apache Point'],
54 [3.5, 'WIYN', 'Kitt Peak'],
55 [3.0, 'Shane', 'Mount Hamilton'],
56 [3.0, 'NASA IRTF', 'Mauna Kea'],
57 ]
59 scopes = np.zeros(len(telescopes), dtype = list(zip(
60 ['aperture', 'name', 'lat', 'lon'], [float, (np.str, 38), float, float])))
62 # name, lat (S negative), lon (W negative)
63 observatories = [
64 ['Cerro Paranal', -24, 38, -70, 24],
65 ['Nizhny Arkhyz', 43, 39, 41, 26],
66 ['Cerro La Silla', -29, 15, -70, 44],
67 ['Lowell Observatory', 35, 12, -111, 40],
68 ['Apache Point', 32, 47, -105, 49],
69 ['Mount Hamilton', 37, 21, -121, 38],
70 ['South African Astronomical Observatory', -32, 23, 20, 49],
71 ['Cerro Pachon', -30, 20, -70, 59],
72 ['Coonabarabran', -31, 17, 149, 0o4],
73 ['Mt. Fowlkes', 30, 40, -104, 1],
74 ['La Palma', 28, 46, -17, 53],
75 ['Mt. Graham', 32, 42, -109, 53],
76 ['Calar Alto', 37, 13, -2, 33],
77 ['British Columbia', 49, 17, -122, 34],
78 ['Kitt Peak', 31, 57, -111, 37],
79 ['La Serena', -30, 10, -70, 48],
80 ['Palomar Mountain', 33, 21, -116, 52],
81 ['Xinglong Station', 40, 23, 105, 50],
82 ['Mt. Hopkins', 31, 41, -110, 53],
83 ['Cerro Tololo', -30, 10, -70, 49],
84 ['Mauna Kea', 19, 50, -155, 28]
85 ]
87 # Make a nice little dict to look up the observatory positions
88 obs = {}
89 for i, ob in enumerate(observatories):
90 obs[ob[0]] = [(np.abs(ob[1])+ob[2]/60.)*(ob[1]/np.abs(ob[1])),
91 (np.abs(ob[3])+ob[4]/60.)*(ob[3]/np.abs(ob[3]))]
93 for i, telescope in enumerate(telescopes):
94 scopes['aperture'][i] = telescope[0]
95 scopes['name'][i] = telescope[1]
96 scopes['lat'][i], scopes['lon'][i] = obs[telescope[2]]
98 scopes = scopes[np.where(scopes['aperture'] >= minSize)]
99 return scopes
102class NFollowStacker(BaseStacker):
103 """Add the number of telescopes ('nObservatories') that could follow up any visit
104 at (any of the) times in timeStep, specifying the minimum telescope size (in meters) and airmass limit.
106 Parameters
107 ----------
108 minSize: float, opt
109 The minimum telescope aperture to use, in meters. Default 3.0.
110 airmassLimit: float, opt
111 The maximum airmass allowable at the follow-up observatory. Default 2.5.
112 timeSteps: np.array or list of floats, opt
113 The timesteps to check for followup opportunities, in hours. Default is np.arange(0.5, 12., 3.0).
114 mjdCol: str, opt
115 The exposure MJD column name. Default 'observationStartMJD'.
116 raCol: str, opt
117 The RA column name. Default 'fieldRA'.
118 decCol: str, opt
119 The Dec column name. Default 'fieldDec'.
120 raDecDeg: bool, opt
121 Flag whether RA/Dec are in degrees (True) or radians (False).
122 """
123 colsAdded = ['nObservatories']
125 def __init__(self, minSize=3.0, airmassLimit=2.5, timeSteps=np.arange(0.5, 12., 3.0),
126 mjdCol='observationStartMJD', raCol='fieldRA', decCol='fieldDec', degrees=True):
127 self.mjdCol = mjdCol
128 self.raCol = raCol
129 self.decCol = decCol
130 self.degrees = degrees
131 self.colsAddedDtypes = [int]
132 self.colsReq = [self.mjdCol, self.raCol, self.decCol]
133 self.units = ['#']
134 self.airmassLimit = airmassLimit
135 self.timeSteps = timeSteps
136 self.telescopes = findTelescopes(minSize = minSize)
138 def _run(self, simData, cols_present=False):
139 if cols_present:
140 return simData
141 simData['nObservatories'] = 0
142 if self.degrees:
143 ra = np.radians(simData[self.raCol])
144 dec = np.radians(simData[self.decCol])
145 else:
146 ra = simData[self.raCol]
147 dec = simData[self.decCol]
148 for obs in self.telescopes:
149 obsGotIt = np.zeros(len(simData[self.raCol]), int)
150 obsLon = np.radians(obs['lon'])
151 obsLat = np.radians(obs['lat'])
152 for step in self.timeSteps:
153 alt, az = raDec2AltAz(ra, dec, obsLon, obsLat,
154 simData[self.mjdCol] + step / 24.0,
155 altonly=True)
156 airmass = 1. / (np.cos(np.pi / 2. - alt))
157 followed = np.where((airmass <= self.airmassLimit) & (airmass >= 1.))
158 # If the observatory got an observation, save this into obsGotIt.
159 # obsGotIt will be 1 if ANY of the times got an observation.
160 obsGotIt[followed] = 1
161 # If an observatory got an observation, count it in nObservatories.
162 simData['nObservatories'] += obsGotIt
163 return simData