23 from astropy
import units
24 from astropy.units
import cds
28 from lsst.afw.coord.weather
import Weather
30 __all__ = [
"refraction",
"differentialRefraction"]
34 deltaRefractScale = 1.0E8
37 def refraction(wavelength, elevation, observatory, weather=None):
38 """Calculate overall refraction under atmospheric and observing conditions. 43 wavelength is in nm (valid for 230.2 < wavelength < 2058.6) 44 elevation : `lsst.geom.Angle` 45 Elevation of the observation, as an Angle. 46 observatory : `lsst.afw.coord.Observatory` 47 Class containing the longitude, latitude, 48 and altitude of the observatory. 49 weather : `lsst.afw.coord.Weather`, optional 50 Class containing the measured temperature, pressure, and humidity 51 at the observatory during an observation 52 If omitted, typical conditions for the observatory's elevation will be calculated. 56 refraction : `lsst.geom.Angle` 57 The angular refraction for light of the given wavelength, 58 under the given observing conditions. 62 The calculation is taken from [1]_. 66 .. [1] R. C. Stone, "An Accurate Method for Computing Atmospheric 67 Refraction," Publications of the Astronomical Society of the Pacific, 68 vol. 108, p. 1051, 1996. 70 if wavelength < 230.2:
71 raise ValueError(
"Refraction calculation is valid for wavelengths between 230.2 and 2058.6 nm.")
72 if wavelength > 2058.6:
73 raise ValueError(
"Refraction calculation is valid for wavelengths between 230.2 and 2058.6 nm.")
74 latitude = observatory.getLatitude()
75 altitude = observatory.getElevation()
78 reducedN =
deltaN(wavelength, weather)/deltaRefractScale
80 atmosScaleheightRatio = 4.5908E-6*temperature.to_value(units.Kelvin)
84 relativeGravity = (1. + 0.005302*np.sin(latitude.asRadians())**2. -
85 0.00000583*np.sin(2.*latitude.asRadians())**2. - 0.000000315*altitude)
88 tanZ = np.tan(np.pi/2. - elevation.asRadians())
89 atmosTerm1 = reducedN*relativeGravity*(1. - atmosScaleheightRatio)
90 atmosTerm2 = reducedN*relativeGravity*(atmosScaleheightRatio - reducedN/2.)
91 result =
float(atmosTerm1*tanZ + atmosTerm2*tanZ**3.)*lsst.geom.radians
96 """Calculate the differential refraction between two wavelengths. 101 wavelength is in nm (valid for 230.2 < wavelength < 2058.6) 102 wavelengthRef : `float` 103 Reference wavelength, typically the effective wavelength of a filter. 104 elevation : `lsst.geom.Angle` 105 Elevation of the observation, as an Angle. 106 observatory : `lsst.afw.coord.Observatory` 107 Class containing the longitude, latitude, 108 and altitude of the observatory. 109 weather : `lsst.afw.coord.Weather`, optional 110 Class containing the measured temperature, pressure, and humidity 111 at the observatory during an observation 112 If omitted, typical conditions for the observatory's elevation will be calculated. 116 differentialRefraction : `lsst.geom.Angle` 117 The refraction at `wavelength` minus the refraction at `wavelengthRef`. 119 refractionStart =
refraction(wavelength, elevation, observatory, weather=weather)
120 refractionEnd =
refraction(wavelengthRef, elevation, observatory, weather=weather)
121 return refractionStart - refractionEnd
125 """Calculate the differential refractive index of air. 130 wavelength is in nanometers 131 weather : `lsst.afw.coord.Weather` 132 Class containing the measured temperature, pressure, and humidity 133 at the observatory during an observation 138 The difference of the refractive index of air from 1., 139 calculated as (n_air - 1)*10^8 143 The differential refractive index is the difference of 144 the refractive index from 1., multiplied by 1E8 to simplify 145 the notation and equations. Calculated as (n_air - 1)*10^8 147 This replicates equation 14 of [1]_ 151 .. [1] R. C. Stone, "An Accurate Method for Computing Atmospheric 152 Refraction," Publications of the Astronomical Society of the Pacific, 153 vol. 108, p. 1051, 1996. 155 waveNum = 1E3/wavelength
156 dryAirTerm = 2371.34 + (683939.7/(130. - waveNum**2.)) + (4547.3/(38.9 - waveNum**2.))
157 wetAirTerm = 6487.31 + 58.058*waveNum**2. - 0.71150*waveNum**4. + 0.08851*waveNum**6.
163 """Calculate dry air pressure term to refractive index calculation. 167 weather : `lsst.afw.coord.Weather` 168 Class containing the measured temperature, pressure, and humidity 169 at the observatory during an observation 173 densityFactor : `float` 174 Returns the relative density of dry air 175 at the given pressure and temperature. 179 This replicates equation 15 of [1]_ 183 .. [1] R. C. Stone, "An Accurate Method for Computing Atmospheric 184 Refraction," Publications of the Astronomical Society of the Pacific, 185 vol. 108, p. 1051, 1996. 189 airPressure = weather.getAirPressure()*units.pascal
190 dryPressure = airPressure - waterVaporPressure
191 eqn = dryPressure.to_value(cds.mbar)*(57.90E-8 - 9.3250E-4/temperature.to_value(units.Kelvin) +
192 0.25844/temperature.to_value(units.Kelvin)**2.)
193 densityFactor = (1. + eqn)*dryPressure.to_value(cds.mbar)/temperature.to_value(units.Kelvin)
198 """Calculate water vapor pressure term to refractive index calculation. 202 weather : `lsst.afw.coord.Weather` 203 Class containing the measured temperature, pressure, and humidity 204 at the observatory during an observation 208 densityFactor : `float` 209 Returns the relative density of water vapor 210 at the given pressure and temperature. 214 This replicates equation 16 of [1]_ 218 .. [1] R. C. Stone, "An Accurate Method for Computing Atmospheric 219 Refraction," Publications of the Astronomical Society of the Pacific, 220 vol. 108, p. 1051, 1996. 224 densityEqn1 = (-2.37321E-3 + 2.23366/temperature.to_value(units.Kelvin) -
225 710.792/temperature.to_value(units.Kelvin)**2. +
226 7.75141E-4/temperature.to_value(units.Kelvin)**3.)
227 densityEqn2 = waterVaporPressure.to_value(cds.mbar)*(1. + 3.7E-4*waterVaporPressure.to_value(cds.mbar))
228 relativeDensity = waterVaporPressure.to_value(cds.mbar)/temperature.to_value(units.Kelvin)
229 densityFactor = (1 + densityEqn2*densityEqn1)*relativeDensity
235 """Convert humidity and temperature to water vapor pressure. 239 weather : `lsst.afw.coord.Weather` 240 Class containing the measured temperature, pressure, and humidity 241 at the observatory during an observation 245 pressure : `astropy.units.Quantity` 246 The water vapor pressure in Pascals 247 calculated from the given humidity and temperature. 251 This replicates equations 18 & 20 of [1]_ 255 .. [1] R. C. Stone, "An Accurate Method for Computing Atmospheric 256 Refraction," Publications of the Astronomical Society of the Pacific, 257 vol. 108, p. 1051, 1996. 259 humidity = weather.getHumidity()
260 x = np.log(humidity/100.0)
262 temperatureEqn1 = (temperature + 238.3*units.Celsius)*x + 17.2694*temperature
263 temperatureEqn2 = (temperature + 238.3*units.Celsius)*(17.2694 - x) - 17.2694*temperature
264 dewPoint = 238.3*temperatureEqn1/temperatureEqn2
265 waterVaporPressure = (4.50874 + 0.341724*dewPoint + 0.0106778*dewPoint**2 + 0.184889E-3*dewPoint**3 +
266 0.238294E-5*dewPoint**4 + 0.203447E-7*dewPoint**5)*133.32239*units.pascal
268 return waterVaporPressure
272 """Thin wrapper to return the measured temperature from an observation. 276 weather : `lsst.afw.coord.Weather` 277 Class containing the measured temperature, pressure, and humidity 278 at the observatory during an observation 279 useKelvin : bool, optional 280 Set to True to return the temperature in Kelvin instead of Celsius 281 This is needed because Astropy can't easily convert 282 between Kelvin and Celsius. 286 temperature : `astropy.units.Quantity` 287 The temperature in Celsius, unless `useKelvin` is set. 289 temperature = weather.getAirTemperature()*units.Celsius
291 temperature = temperature.to(units.Kelvin, equivalencies=units.temperature())
296 """Set default local weather conditions if they are missing. 300 weather : `lsst.afw.coord.Weather` 301 Class containing the measured temperature, pressure, and humidity 302 at the observatory during an observation 303 altitude : `astropy.units.Quantity` 304 The altitude of the observatory, in meters. 308 default : `lsst.afw.coord.Weather` 309 Updated Weather class with any `nan` values replaced by defaults. 311 if isinstance(altitude, units.quantity.Quantity):
314 altitude2 = altitude*units.meter
315 p0 = 101325.*units.pascal
316 g = 9.80665*units.meter/units.second**2
317 R0 = 8.31447*units.Joule/(units.mol*units.Kelvin)
318 T0 = 19.*units.Celsius
319 lapseRate = -6.5*units.Celsius/units.km
320 M = 0.0289644*units.kg/units.mol
322 temperature = T0 + lapseRate*altitude2
323 temperatureK = temperature.to(units.Kelvin, equivalencies=units.temperature())
324 pressure = p0*np.exp(-(g*M*altitude2)/(R0*temperatureK))
326 weather = Weather((temperature/units.Celsius).value, (pressure/units.pascal).value, humidity)
def densityFactorWater(weather)
def humidityToPressure(weather)
def defaultWeather(altitude)
def refraction(wavelength, elevation, observatory, weather=None)
def densityFactorDry(weather)
def differentialRefraction(wavelength, wavelengthRef, elevation, observatory, weather=None)
def deltaN(wavelength, weather)
def extractTemperature(weather, useKelvin=False)