mirror of
https://gitlab.astro-wise.org/micado/atmosphericmodel.git
synced 2026-10-29 20:51:05 +00:00
Updated documentation, descriptions for v1.0 release.
This commit is contained in:
1 parent
56051bb6a5
commit
8d50899db6
31 files changed
+17833
-192
No files matched your search
+208
-19
@@ -16,6 +16,53 @@ from scipy import integrate
|
||||
'''
|
||||
|
||||
class Observatory:
|
||||
'''
|
||||
Class used for all function to calculate the refractive index
|
||||
and the corresponding uncertainties.
|
||||
|
||||
...
|
||||
|
||||
Attributes
|
||||
----------
|
||||
dT : float (optional)
|
||||
Uncertainty in the atmospheric temperature in Kelvin
|
||||
dP : float (optional)
|
||||
Uncertainty in the atmospheric pressure in Pascal
|
||||
dH : float (optional)
|
||||
Uncertainty in the atmospheric relative humidity
|
||||
dCO2: float (optional)
|
||||
Uncertianty in the atmospheric CO2 density in parts
|
||||
per million.
|
||||
dl : float (optional)
|
||||
Uncertainty in the wavelengths in micron
|
||||
|
||||
Methods
|
||||
-------
|
||||
n_as(l)
|
||||
Returns the refractive index for standard atmospheric conditions.
|
||||
n_axs(l, xc)
|
||||
Same as n_as(l), but with a different CO2 density given by xc
|
||||
n_ws(l)
|
||||
Returns the refractive index of air for standard moist contions.
|
||||
f(p,T)
|
||||
Returns the enchancement factor of water vapour in air.
|
||||
svp(T)
|
||||
Returns the saturation vapour pressure in Pa.
|
||||
svp2(T)
|
||||
Returns the saturation vapour pressure in Pa.
|
||||
From IAPWS formula, based on documentation by NIST toolbox.
|
||||
xw(p, T, RH)
|
||||
Returns the molar fraction of water vapour in moist air.
|
||||
Z(p, T, RH, xw='')
|
||||
Returns the compressibility of moist air
|
||||
rho(p, T, RH, xc, xw='')
|
||||
Returns the density of atmospheric air at the given parameters.
|
||||
n_tph(l, T, p, RH, xc)
|
||||
Returns the refractive index for any atmospheric conditions.
|
||||
dn_tph(l, T, p, RH, xc, dl=None, dT=None, dP=None, dRH=None, dCO2=None)
|
||||
Returns the uncertainty in the refractive index for any atmospheric
|
||||
conditions, given the parameters.
|
||||
'''
|
||||
def __init__(self, dT=0.2, dP=20, dH=0.02, dCO2=20, dl=0.001):
|
||||
self.dT = dT # in K
|
||||
self.dP = dP # in Pa
|
||||
@@ -28,6 +75,17 @@ class Observatory:
|
||||
Formula that calculate the refractive index for standard atmospheric
|
||||
conditions, i.e. 15 C, 101,325 Pa, 0% RH, 450 ppm CO2.
|
||||
It returns n_as, not (n_as - 1) * 1e8!
|
||||
|
||||
Parameters
|
||||
----------
|
||||
l : float
|
||||
Wavelength of light in microns
|
||||
|
||||
Returns
|
||||
-------
|
||||
n : float
|
||||
Refractive index of air at standard atmospheric conditions.
|
||||
|
||||
'''
|
||||
_s = 1 / l
|
||||
_k0 = 238.0185 # um^-2
|
||||
@@ -42,6 +100,18 @@ class Observatory:
|
||||
Formula that calculate the refractive index for standard atmospheric
|
||||
conditions, i.e. 15 C, 101,325 Pa, 0% RH, but with xc ppm of CO2.
|
||||
It returns n_axs, not (n_axs - 1)
|
||||
|
||||
Parameters
|
||||
----------
|
||||
l : float
|
||||
Wavelength of light in microns
|
||||
xc : float
|
||||
CO2 density in parts per million
|
||||
|
||||
Returns
|
||||
-------
|
||||
n : float
|
||||
Refractive index of air
|
||||
'''
|
||||
_n_as = self.n_as(l)
|
||||
return ( (_n_as - 1) * (1 + 0.534e-6 * (xc - 450) ) ) + 1
|
||||
@@ -52,6 +122,16 @@ class Observatory:
|
||||
Formula that calculates the refractivity of air for standard moist conditions
|
||||
as defined by B&S (1939), i.e. 20 C, 1333 Pa
|
||||
Returns n_ws, not (n_ws - 1) * 1e8
|
||||
|
||||
Parameters
|
||||
----------
|
||||
l : float
|
||||
Wavelength of light in microns
|
||||
|
||||
Returns
|
||||
-------
|
||||
n : float
|
||||
Refractive index of standard moist air.
|
||||
'''
|
||||
_s = 1 / l
|
||||
_cf = 1.022
|
||||
@@ -65,8 +145,18 @@ class Observatory:
|
||||
def f(self, p, T):
|
||||
'''
|
||||
Enhancement factor of water vapour in air
|
||||
t in degrees celsius
|
||||
p in Pascal (Pa)
|
||||
|
||||
Parameters
|
||||
----------
|
||||
p : float
|
||||
Atmospheric pressure in Pascal
|
||||
T : float
|
||||
Atmospheric temperature in Kelvin
|
||||
|
||||
Returns
|
||||
-------
|
||||
f : float
|
||||
Enhancement factor of water vapour in air
|
||||
'''
|
||||
_t = T - 273.15
|
||||
_a = 1.00062
|
||||
@@ -78,6 +168,16 @@ class Observatory:
|
||||
def svp(self, T):
|
||||
'''
|
||||
Saturation vapour pressure in Pa.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
T : float
|
||||
Atmospheric temperature in Kelvin
|
||||
|
||||
Returns
|
||||
-------
|
||||
svp : float
|
||||
Saturation vapour pressure
|
||||
'''
|
||||
_A = 1.2378847e-5 # K^-2
|
||||
_B = -1.9121316e-2 # K^-2
|
||||
@@ -88,7 +188,18 @@ class Observatory:
|
||||
|
||||
def svp2(self, T):
|
||||
'''
|
||||
Calculation of svp from IAPWS formula, based on documentation by NIST toolbox.
|
||||
Calculation of svp from IAPWS formula, based on documentation
|
||||
by NIST toolbox.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
T : float
|
||||
Atmospheric temperature in Kelvin
|
||||
|
||||
Returns
|
||||
-------
|
||||
svp : float
|
||||
Saturation vapour pressure
|
||||
'''
|
||||
K1 = 1.16705214528e+03
|
||||
K2 = -7.24213167032e+05
|
||||
@@ -111,6 +222,20 @@ class Observatory:
|
||||
def xw(self, p, T, RH):
|
||||
'''
|
||||
Molar fraction of water vapour in moist air.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
p : float
|
||||
Atmospheric pressure in Pascal
|
||||
T : float
|
||||
Atmospheric temperature in Kelvin
|
||||
RH : float
|
||||
Atmospheric relative humidity (0<=RH<=1)
|
||||
|
||||
Returns
|
||||
-------
|
||||
xw : float
|
||||
Molar fraction of water vapour in moist air
|
||||
'''
|
||||
_f = self.f(p, T)
|
||||
_svp = self.svp(T)
|
||||
@@ -120,6 +245,20 @@ class Observatory:
|
||||
def Z(self, p, T, RH, xw=''):
|
||||
'''
|
||||
Compressibility of moist air
|
||||
|
||||
Parameters
|
||||
----------
|
||||
p : float
|
||||
Atmospheric pressure in Pascal
|
||||
T : float
|
||||
Atmospheric temperature in Kelvin
|
||||
RH : float
|
||||
Atmospheric relative humidity (0<=RH<=1)
|
||||
|
||||
Returns
|
||||
-------
|
||||
Z : float
|
||||
Compressibility of moist air
|
||||
'''
|
||||
_a0 = 1.58123e-6 # K Pa^-1
|
||||
_a1 = -2.9331e-8 # Pa^-1
|
||||
@@ -142,10 +281,25 @@ class Observatory:
|
||||
def rho(self, p, T, RH, xc, xw=''):
|
||||
'''
|
||||
Calculates the density of air for the given parameters.
|
||||
T in Kelvin
|
||||
p in Pascal
|
||||
RH between 0 and 1
|
||||
xc in ppm
|
||||
|
||||
Parameters
|
||||
----------
|
||||
p : float
|
||||
Atmospheric pressure in Pascal
|
||||
T : float
|
||||
Atmospheric temperature in Kelvin
|
||||
RH : float
|
||||
Atmospheric relative humidity (0<=RH<=1)
|
||||
xc : float
|
||||
CO2 density in parts per million
|
||||
xw : str or float
|
||||
Placeholder for molar fraction of water vapour in moist air.
|
||||
Used to pass the function along where it should go.
|
||||
|
||||
Returns
|
||||
-------
|
||||
rho : float
|
||||
Density of air
|
||||
'''
|
||||
_Ma = 1e-3 * (28.9635 + 12.011e-6 * (xc - 400) ) # Molar mass in kg/mol of dry air containing xc ppm of CO2
|
||||
_Mw = 0.018015 # kg/mol
|
||||
@@ -161,6 +315,25 @@ class Observatory:
|
||||
def n_tph(self, l, T, p, RH, xc):
|
||||
'''
|
||||
Calculates the refraction of the atmosphere for any conditions.
|
||||
Follows the equations by Ciddor (1996).
|
||||
|
||||
Parameters
|
||||
----------
|
||||
l : float
|
||||
Wavelength of light in microns
|
||||
p : float
|
||||
Atmospheric pressure in Pascal
|
||||
T : float
|
||||
Atmospheric temperature in Kelvin
|
||||
RH : float
|
||||
Atmospheric relative humidity (0<=RH<=1)
|
||||
xc : float
|
||||
CO2 density in parts per million
|
||||
|
||||
Returns
|
||||
-------
|
||||
n : float
|
||||
Refractive index of air
|
||||
'''
|
||||
_n_a = self.n_axs(l, xc)
|
||||
_n_w = self.n_ws(l)
|
||||
@@ -193,18 +366,34 @@ class Observatory:
|
||||
by using fully propagated error analysis.
|
||||
This involves almost endless use of the chain rule and evaluation of both the moist
|
||||
air and dry air components. Note: dry air does not contain any water, i.e. H=0, x_w=0, etc.
|
||||
|
||||
Parameters:
|
||||
l - Wavelength in micron (0.4 - 2.5 micron)
|
||||
T - Temperature in Kelvin
|
||||
p - Pressure in Pascals
|
||||
RH - Relative humidity (no units, don't use percentage but value 0<x<1)
|
||||
xc - CO2 density in ppm
|
||||
dl - Uncertainty in the blue wavelength
|
||||
dT - Uncertainty in the temperature, default: 0.2 K
|
||||
dP - Uncertainty in the pressure, default: 20 Pa
|
||||
dRH - Uncertainty in the relative humidity, default: 0.02
|
||||
dCO2- Uncertainty in the CO2 density, default: 20
|
||||
|
||||
Parameters
|
||||
----------
|
||||
l : float
|
||||
Wavelength of light in microns
|
||||
p : float
|
||||
Atmospheric pressure in Pascal
|
||||
T : float
|
||||
Atmospheric temperature in Kelvin
|
||||
RH : float
|
||||
Atmospheric relative humidity (0<=RH<=1)
|
||||
xc : float
|
||||
CO2 density in parts per million
|
||||
dl : float
|
||||
Uncertainty in the wavelength in microns
|
||||
dT : float (default: 0.2)
|
||||
Uncertainty in the atmospheric temperature in Kelvin
|
||||
dP : float (default: 20)
|
||||
Uncertainty in the atmospheric pressure in Pascal
|
||||
dRH : float (default: 0.02)
|
||||
Uncertainty in the atmospheric relative humidity
|
||||
dCO2: float (default: 20)
|
||||
Uncertainty in the atmospheric CO2 density in parts per million
|
||||
|
||||
Returns
|
||||
-------
|
||||
dn : float
|
||||
Uncertainty in the refractive index of air
|
||||
'''
|
||||
|
||||
if dP == None:
|
||||
|
||||
@@ -3,6 +3,7 @@ import numpy as np
|
||||
from scipy import integrate
|
||||
import os
|
||||
from .ciddorModel import Observatory
|
||||
|
||||
'''
|
||||
@ Author: Joost van den Born
|
||||
@ Contact: born@astron.nl
|
||||
@@ -17,19 +18,99 @@ from .ciddorModel import Observatory
|
||||
'''
|
||||
|
||||
class dispersion(Observatory):
|
||||
'''
|
||||
Class that sets the observer location.
|
||||
These location attributes are then used to calculate the
|
||||
appropriate atmospheric dispersion.
|
||||
|
||||
See also:
|
||||
Observatory()
|
||||
refraction()
|
||||
...
|
||||
|
||||
Attributes
|
||||
-----------
|
||||
lat : float
|
||||
Latitude of the observer in degrees
|
||||
h : float
|
||||
Altitude above mean sea level of the observer in meters
|
||||
Other Observatory() attributes
|
||||
|
||||
Methods
|
||||
-------
|
||||
setReducedHeight(p, rho)
|
||||
Sets the reduced atmospheric height.
|
||||
planeParallel(n1, n2, zenith)
|
||||
Returns the atmospheric dispersion assuming a plane parallel
|
||||
atmosphere
|
||||
cassini(n1, n2, zenith, reduced_height=None)
|
||||
Returns the atmospheric dispersion asusming Cassini's homegeneous
|
||||
atmosphere model
|
||||
tan5(n1, n2, zenith, reduced_height=None)
|
||||
Returns the atmospheric dispersion following Oriani's theorem,
|
||||
including a fifth order term in the expansion.
|
||||
oriani(n1, n2, zenith, reduced_height=None)
|
||||
Returns the atmospheric dispersion following the classic version
|
||||
of Oriani's theorem.
|
||||
corbard(n1, n2, zenith, reduced_height=None)
|
||||
Returns the atmospheric dispersion following the method described
|
||||
in Corbard et al., 2019.
|
||||
refractionIntegral(n1, n2, z0, R0=None, useStandardAtmosphere=True, heightData=None, rhoData=None)
|
||||
Returns the atmospheric dispersion following the refraction integral.
|
||||
psi(x)
|
||||
Submethod for corbard()
|
||||
set_rc()
|
||||
Sets the local radius of curvature of the Earth at the observer.
|
||||
set_H(p, rho)
|
||||
Sets the reduced height for the conditions at the observer, assuming
|
||||
an adiabatic atmosphere.
|
||||
H_isotherm(T)
|
||||
Sets the reduced height for the conditions at the observer, assuming
|
||||
an isothermal atmosphere.
|
||||
cassiniError(z, l1, l2, T, p, RH, xc, dl1=0, dl2=0, dT=0.2, dP=20,
|
||||
dRH=0.02, dCO2=20, dz=0, lat=None, h=None)
|
||||
Returns the uncertainty in the atmospheric dispersion, assuming
|
||||
Cassini's homegeneous atmosphere model and the given parameters.
|
||||
Other Observatory() methods
|
||||
'''
|
||||
def __init__(self, lat, h):
|
||||
Observatory.__init__(self)
|
||||
self.h = h # height above sea level in meters
|
||||
self.lat = lat # Latitude of the observer in degrees
|
||||
self.rc = self.set_rc() * 1000 # Radius of curvature of the earth at the observer
|
||||
|
||||
def setReducedHeight(self, P, rho):
|
||||
self.H = self.set_H(P, rho) # Reduced height of the atmosphere assuming ideal gas law
|
||||
def setReducedHeight(self, p, rho):
|
||||
'''
|
||||
Sets the reduced atmospheric height.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
p : float
|
||||
Atmospheric pressure in Pascal
|
||||
rho : float
|
||||
Density of the atmospheric air at the observer
|
||||
'''
|
||||
self.H = self.set_H(p, rho) # Reduced height of the atmosphere assuming ideal gas law
|
||||
|
||||
|
||||
def planeParallel(self, n1, n2, zenith):
|
||||
'''
|
||||
Refraction based on a flat atmosphere, easily derived from Snell's law.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
n1 : float
|
||||
Refractive index at the shortest wavelength of interest
|
||||
n2 : float
|
||||
Refractive index at the longest wavelength of interest
|
||||
zenith : float
|
||||
Angle of observation in degrees.
|
||||
zenith = 0 means the observation is directly overhead.
|
||||
|
||||
Returns
|
||||
-------
|
||||
dR : float
|
||||
Atmospheric dispersion in degrees
|
||||
'''
|
||||
_R1 = np.arcsin(n1 * np.sin( np.deg2rad(zenith) )) - np.deg2rad(zenith)
|
||||
_R2 = np.arcsin(n2 * np.sin( np.deg2rad(zenith) )) - np.deg2rad(zenith)
|
||||
@@ -40,6 +121,24 @@ class dispersion(Observatory):
|
||||
def cassini(self, n1, n2, zenith, reduced_height=None):
|
||||
'''
|
||||
Refraction of spherical atmosphere, derived from geometry using Sine law
|
||||
|
||||
Parameters
|
||||
----------
|
||||
n1 : float
|
||||
Refractive index at the shortest wavelength of interest
|
||||
n2 : float
|
||||
Refractive index at the longest wavelength of interest
|
||||
zenith : float
|
||||
Angle of observation in degrees.
|
||||
zenith = 0 means the observation is directly overhead.
|
||||
reduced_height : float (optional)
|
||||
Reduced height of the atmosphere. Default value is calculated
|
||||
from the object attributes.
|
||||
|
||||
Returns
|
||||
-------
|
||||
dR : float
|
||||
Atmospheric dispersion in degrees
|
||||
'''
|
||||
if reduced_height:
|
||||
H = reduced_height
|
||||
@@ -56,6 +155,24 @@ class dispersion(Observatory):
|
||||
'''
|
||||
Same as oriani's theorem, but including a higher order term.
|
||||
Found in Corbard et al., 2019.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
n1 : float
|
||||
Refractive index at the shortest wavelength of interest
|
||||
n2 : float
|
||||
Refractive index at the longest wavelength of interest
|
||||
zenith : float
|
||||
Angle of observation in degrees.
|
||||
zenith = 0 means the observation is directly overhead.
|
||||
reduced_height : float (optional)
|
||||
Reduced height of the atmosphere. Default value is calculated
|
||||
from the object attributes.
|
||||
|
||||
Returns
|
||||
-------
|
||||
dR : float
|
||||
Atmospheric dispersion in degrees
|
||||
'''
|
||||
if reduced_height:
|
||||
H = reduced_height
|
||||
@@ -74,8 +191,27 @@ class dispersion(Observatory):
|
||||
|
||||
def oriani(self, n1, n2, zenith, reduced_height=None):
|
||||
'''
|
||||
Classic refraction formula with two tan(z) terms. This does not assume any
|
||||
information about the structure of the atmosphere. Found with Oriani's theorem.
|
||||
Classic refraction formula with two tan(z) terms.
|
||||
This does not assume any information about the structure
|
||||
of the atmosphere. Found with Oriani's theorem.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
n1 : float
|
||||
Refractive index at the shortest wavelength of interest
|
||||
n2 : float
|
||||
Refractive index at the longest wavelength of interest
|
||||
zenith : float
|
||||
Angle of observation in degrees.
|
||||
zenith = 0 means the observation is directly overhead.
|
||||
reduced_height : float (optional)
|
||||
Reduced height of the atmosphere. Default value is calculated
|
||||
from the object attributes.
|
||||
|
||||
Returns
|
||||
-------
|
||||
dR : float
|
||||
Atmospheric dispersion in degrees
|
||||
'''
|
||||
if reduced_height:
|
||||
H = reduced_height
|
||||
@@ -94,9 +230,28 @@ class dispersion(Observatory):
|
||||
|
||||
def corbard(self, n1, n2, zenith, reduced_height=None):
|
||||
'''
|
||||
Corbard et al., 2019, mention an additional formula based on the error function.
|
||||
Oriani's theorem can be derived from this equation by 'keeping only the three first
|
||||
terms of its asymptotic expansion'.
|
||||
Corbard et al., 2019, mention an additional formula based on
|
||||
the error function. Oriani's theorem can be derived from this
|
||||
equation by 'keeping only the three first terms of its
|
||||
asymptotic expansion'.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
n1 : float
|
||||
Refractive index at the shortest wavelength of interest
|
||||
n2 : float
|
||||
Refractive index at the longest wavelength of interest
|
||||
zenith : float
|
||||
Angle of observation in degrees.
|
||||
zenith = 0 means the observation is directly overhead.
|
||||
reduced_height : float (optional)
|
||||
Reduced height of the atmosphere. Default value is calculated
|
||||
from the object attributes.
|
||||
|
||||
Returns
|
||||
-------
|
||||
dR : float
|
||||
Atmospheric dispersion in degrees
|
||||
'''
|
||||
if reduced_height:
|
||||
H = reduced_height
|
||||
@@ -113,15 +268,46 @@ class dispersion(Observatory):
|
||||
|
||||
|
||||
|
||||
def refractionIntegral(self, n1, n2, z0, R0=None, useStandardAtmosphere=True, heightData=None, rhoData=None):
|
||||
def refractionIntegral(self, n1, n2, z0, R0=None, useStandardAtmosphere=True,
|
||||
heightData=None, rhoData=None):
|
||||
'''
|
||||
Using data that gives temperature, pressure and density as a function of height,
|
||||
the gladstone-dale relation is invoked to calculate the path of a light ray
|
||||
along the atmosphere. This is allows us to also include atmospheric activity in
|
||||
Using data that gives temperature, pressure and density as a
|
||||
function of height, the gladstone-dale relation is invoked to
|
||||
calculate the path of a light ray along the atmosphere.
|
||||
This is allows us to also include atmospheric activity in
|
||||
different atmosphere layers.
|
||||
Recommended use with the US Standard Atmosphere from 1976.
|
||||
USSA1976 data generated from code supplied by http://www.pdas.com/atmos.html
|
||||
The method described in eq. 3 in Auer & Standish (2000) is used for the calculation.
|
||||
The method described in eq. 3 in Auer & Standish (2000) is used for the
|
||||
calculation.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
n1 : float
|
||||
Refractive index at the shortest wavelength of interest
|
||||
n2 : float
|
||||
Refractive index at the longest wavelength of interest
|
||||
z0 : float
|
||||
Angle of observation in degrees.
|
||||
zenith = 0 means the observation is directly overhead.
|
||||
R0 : float (optional)
|
||||
Local radius of curvature of the Earth in km.
|
||||
useStandardAtmosphere : bool
|
||||
Flag to use the included USSA1976 data
|
||||
heightData : 1D Array
|
||||
If "useStandardAtmosphere" is False, the function will ask
|
||||
for alternative atmospheric data to integrate over. This
|
||||
gives the altitudinal points
|
||||
rhoData : 1D Array
|
||||
If useStandardAtmosphere is False, the function will ask
|
||||
for alternative atmospheric data to integrate over. This
|
||||
gives the atmospheric density at the points defined by
|
||||
"heightData".
|
||||
|
||||
Returns
|
||||
-------
|
||||
dR : float
|
||||
Atmospheric dispersion in degrees
|
||||
'''
|
||||
if not R0:
|
||||
R0 = self.rc
|
||||
@@ -163,6 +349,19 @@ class dispersion(Observatory):
|
||||
|
||||
|
||||
def psi(self, x):
|
||||
'''
|
||||
Submethod for corbard(). Described explicitly in Corbard et al.,2019.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
x : float
|
||||
Input of the function
|
||||
|
||||
Returns
|
||||
-------
|
||||
y : float
|
||||
Output of the function
|
||||
'''
|
||||
_f = lambda a: np.exp(-a**2)
|
||||
_int = integrate.quad(_f, x, np.inf)
|
||||
return np.exp(x**2) * _int[0]
|
||||
@@ -173,6 +372,11 @@ class dispersion(Observatory):
|
||||
Returns the radius of the curvature at the observer in km,
|
||||
taking into account the latitude of the observer and the corresponding
|
||||
ellipsoidality of the earth.
|
||||
|
||||
Returns
|
||||
-------
|
||||
rc : float
|
||||
Local radius of curvature of the Earth in kilometers.
|
||||
'''
|
||||
_A = 6378.137 # km
|
||||
_B = 6356.752 # km
|
||||
@@ -182,9 +386,21 @@ class dispersion(Observatory):
|
||||
return _rc0 + self.h/1000
|
||||
|
||||
|
||||
def set_H(self, P, rho):
|
||||
def set_H(self, p, rho):
|
||||
'''
|
||||
Calculates the reduced height of the atmosphere, assuming ideal gas law.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
p : float
|
||||
Atmospheric pressure in Pascal
|
||||
rho : float
|
||||
Density of the atmospheric air at the observer
|
||||
|
||||
Returns
|
||||
-------
|
||||
H : float
|
||||
Reduced height of the atmosphere in meters
|
||||
'''
|
||||
_phi = np.deg2rad(self.lat)
|
||||
_c1 = 5.2790414e-3
|
||||
@@ -194,11 +410,22 @@ class dispersion(Observatory):
|
||||
_g0 = 9.780327 # m/s^2
|
||||
_g0_local = _g0 * (1 + _c1 * np.sin(_phi)**2 + _c2 * np.sin(_phi)**4 + _c3 * np.sin(_phi)**6 + _c4 * np.sin(_phi)**8)
|
||||
_g = _g0_local - (3.0877e-6 - 4.3e-9 * np.sin(_phi)**2) * self.h + 7.2e-13 * self.h**2
|
||||
return P / (rho * _g)
|
||||
return p / (rho * _g)
|
||||
|
||||
def H_isotherm(self, T):
|
||||
'''
|
||||
Calculates the reduced height of the atmosphere, assuming an isotherm distribution.
|
||||
Calculates the reduced height of the atmosphere,
|
||||
assuming an isotherm distribution.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
T : float
|
||||
Atmospheric temperature in Kelvin
|
||||
|
||||
Returns
|
||||
-------
|
||||
H : float
|
||||
Reduced height of the atmosphere in meters
|
||||
'''
|
||||
_kb = 1.38064852e-23 # kg m2 s-2 K-1
|
||||
_m = 4.809651698e-26 # kg (weight per molecule of air, assuming dry air)
|
||||
@@ -213,32 +440,63 @@ class dispersion(Observatory):
|
||||
|
||||
return (_kb*T) / (_m * _g0_local)
|
||||
|
||||
def cassiniError(self, z, l1, l2, T, p, RH, xc, dl1=0, dl2=0, dT=0.2, dP=20, dRH=0.02, dCO2=20, dz=0, lat=None, h=None):
|
||||
def cassiniError(self, z, l1, l2, T, p, RH, xc, dl1=0, dl2=0, dT=0.2, dP=20,
|
||||
dRH=0.02, dCO2=20, dz=0, lat=None, h=None):
|
||||
'''
|
||||
Calculates the uncertainty in the atmospheric dispersion, following the Cassini model,
|
||||
by using fully propagated error analysis.
|
||||
This involves almost endless use of the chain rule and evaluation of both the moist
|
||||
air and dry air components. Note: dry air does not contain any water, i.e. H=0, x_w=0, etc.
|
||||
Calculates the uncertainty in the atmospheric dispersion,
|
||||
following the Cassini model, by using fully propagated error analysis.
|
||||
This involves almost endless use of the chain rule and evaluation
|
||||
of both the moist air and dry air components.
|
||||
Note: dry air does not contain any water, i.e. H=0, x_w=0, etc.
|
||||
|
||||
Not taken into account is the errror propagation in the scale height of the atmosphere or
|
||||
the zenith error, from my results this should give a small or even negligible difference.
|
||||
Not taken into account is the errror propagation in the scale height
|
||||
of the atmosphere, from my results this should give a small or even
|
||||
negligible difference.
|
||||
|
||||
Parameters:
|
||||
z - Zenith angle in degrees
|
||||
l1 - Bluest wavelength in micron (0.4 - 2.5 micron)
|
||||
l2 - Reddest wavelength in micron (0.4 - 2.5 micron)
|
||||
T - Temperature in Kelvin
|
||||
p - Pressure in Pascals
|
||||
RH - Relative humidity (no units, don't use percentage but value 0<x<1)
|
||||
xc - CO2 density in ppm
|
||||
dl1 - Uncertainty in the blue wavelength
|
||||
dl2 - Uncertainty in the red wavelength
|
||||
dT - Uncertainty in the temperature, default: 0.2 K
|
||||
dP - Uncertainty in the pressure, default: 20 Pa
|
||||
dRH - Uncertainty in the relative humidity, default: 0.02
|
||||
dCO2- Uncertainty in the CO2 density, default: 20
|
||||
lat - [Optional] Latitude of the observatory in degrees
|
||||
h - [Optional] Height in m of the observatory
|
||||
Parameters
|
||||
----------
|
||||
z : float
|
||||
Angle of observation in degrees.
|
||||
zenith = 0 means the observation is directly overhead.
|
||||
l1 : float
|
||||
Wavelength of light in microns, at the shortest wavelength
|
||||
of interest
|
||||
l2 : float
|
||||
Wavelength of light in microns, at the longest wavelength
|
||||
of interest
|
||||
T : float
|
||||
Atmospheric temperature in Kelvin
|
||||
p : float
|
||||
Atmospheric pressure in Pascal
|
||||
RH : float
|
||||
Atmospheric relative humidity (0<=RH<=1)
|
||||
xc : float
|
||||
CO2 density in parts per million
|
||||
dl1 : float
|
||||
Uncertainty in the wavelength in microns, at the shortest
|
||||
wavelength of interest
|
||||
dl2 : float
|
||||
Uncertainty in the wavelength in microns, at the longest
|
||||
wavelength of interest
|
||||
dT : float (default: 0.2)
|
||||
Uncertainty in the atmospheric temperature in Kelvin
|
||||
dP : float (default: 20)
|
||||
Uncertainty in the atmospheric pressure in Pascal
|
||||
dRH : float (default: 0.02)
|
||||
Uncertainty in the atmospheric relative humidity
|
||||
dCO2: float (default: 20)
|
||||
Uncertainty in the atmospheric CO2 density in parts per million
|
||||
dz : float (default: 0)
|
||||
Uncertainty in the zenith angle, in degrees.
|
||||
lat : float (default: None)
|
||||
If entered, overrides the latitude attribute of the class.
|
||||
h : float (default=None)
|
||||
If entered, overrides the altitude attribute of the class.
|
||||
|
||||
Returns
|
||||
-------
|
||||
dRR : float
|
||||
Uncertainty in the atmospheric dispersion in degrees.
|
||||
'''
|
||||
if lat == None:
|
||||
lat = self.lat
|
||||
|
||||
+122
-23
@@ -2,55 +2,119 @@
|
||||
from .ciddorModel import Observatory
|
||||
from .refractionModels import refraction
|
||||
from .dispersionModels import dispersion
|
||||
|
||||
'''
|
||||
Author: Joost van den Born
|
||||
Some functions for quick testing.
|
||||
@ Author: Joost van den Born
|
||||
@ Contact: born@astron.nl
|
||||
@ Description: Some functions for quick testing.
|
||||
'''
|
||||
|
||||
|
||||
def quick_refractive_index(l, conditions='STANDARD'):
|
||||
def quick_refractive_index(l, conditions='STANDARD', T=288.15, p=101325,
|
||||
H=0.0, xc=450, lat=0, h=0):
|
||||
'''
|
||||
Function to quickly calculate the refractive index
|
||||
of atmospheric air at reference conditions, given
|
||||
a wavelength l.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
l : float
|
||||
Wavelength in microns
|
||||
conditions: string
|
||||
'STANDARD' or 'CERRO_ARMAZONES', refers
|
||||
to the standard atmospheric conditions.
|
||||
T : float (optional)
|
||||
Temperature in Kelvin
|
||||
p : float (optional)
|
||||
Atmospheric pressure in Pa
|
||||
H : float (optional)
|
||||
Relative humidity
|
||||
xc : float (optional)
|
||||
CO2 density in parts per million
|
||||
lat : float (optional)
|
||||
Latitude of the observer in degrees
|
||||
h : float (optional)
|
||||
Altitude of the observer in meters
|
||||
|
||||
Returns
|
||||
-------
|
||||
n : float
|
||||
Refractive index for the given conditions.
|
||||
'''
|
||||
if conditions == 'STANDARD':
|
||||
# Parameters at Cerro Armazones
|
||||
T = 288.15 # k
|
||||
P = 101325 # Pa
|
||||
p = 101325 # Pa
|
||||
H = 0.0
|
||||
xc = 450 # ppm
|
||||
lat = 0 # degrees
|
||||
h = 0 # m
|
||||
|
||||
|
||||
elif conditions == 'CERRO_ARMAZONES':
|
||||
# Parameters at Cerro Armazones
|
||||
T = 279.65 # k
|
||||
P = 71200 # Pa
|
||||
p = 71200 # Pa
|
||||
H = 0.22
|
||||
xc = 450 # ppm
|
||||
lat = -24.5983 # degrees
|
||||
h = 3064 # m
|
||||
|
||||
|
||||
# Initializing dispersion model
|
||||
at = Observatory()
|
||||
|
||||
# Calculating indices of refraction for l
|
||||
n = at.n_tph(l=l, T=T, p=P, RH=H, xc=xc)
|
||||
n = at.n_tph(l=l, T=T, p=p, RH=H, xc=xc)
|
||||
return n
|
||||
|
||||
def quick_refraction(l, z, conditions='STANDARD'):
|
||||
|
||||
def quick_refraction(l, z, conditions='STANDARD', T=288.15, p=101325,
|
||||
H=0.0, xc=450, lat=0, h=0):
|
||||
'''
|
||||
Function to quickly calculate the refraction
|
||||
of atmospheric air at reference conditions,
|
||||
given a wavelength l.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
l : float
|
||||
Wavelength in microns
|
||||
z : float
|
||||
Zenith angle of the observation
|
||||
conditions : string
|
||||
'STANDARD' or 'CERRO_ARMAZONES', refers
|
||||
to the standard atmospheric conditions.
|
||||
T : float (optional)
|
||||
Temperature in Kelvin
|
||||
p : float (optional)
|
||||
Atmospheric pressure in Pa
|
||||
H : float (optional)
|
||||
Relative humidity
|
||||
xc : float (optional)
|
||||
CO2 density in parts per million
|
||||
lat : float (optional)
|
||||
Latitude of the observer in degrees
|
||||
h : float (optional)
|
||||
Altitude of the observer in meters
|
||||
|
||||
Returns
|
||||
-------
|
||||
R : float
|
||||
Refraction in degrees
|
||||
'''
|
||||
if conditions == 'STANDARD':
|
||||
# Parameters at Cerro Armazones
|
||||
T = 288.15 # k
|
||||
P = 101325 # Pa
|
||||
p = 101325 # Pa
|
||||
H = 0.0
|
||||
xc = 450 # ppm
|
||||
lat = 0 # degrees
|
||||
h = 0 # m
|
||||
|
||||
|
||||
elif conditions == 'CERRO_ARMAZONES':
|
||||
# Parameters at Cerro Armazones
|
||||
T = 279.65 # k
|
||||
P = 71200 # Pa
|
||||
p = 71200 # Pa
|
||||
H = 0.22
|
||||
xc = 450 # ppm
|
||||
lat = -24.5983 # degrees
|
||||
@@ -60,31 +124,66 @@ def quick_refraction(l, z, conditions='STANDARD'):
|
||||
at = Observatory()
|
||||
|
||||
# Calculating indices of refraction for l
|
||||
n = at.n_tph(l=l, T=T, p=P, RH=H, xc=xc)
|
||||
n = at.n_tph(l=l, T=T, p=p, RH=H, xc=xc)
|
||||
|
||||
# Density of the atmosphere (following CIPM-81/91 equations)
|
||||
rho = at.rho(p=P, T=T, RH=H, xc=xc)
|
||||
rho = at.rho(p=p, T=T, RH=H, xc=xc)
|
||||
|
||||
# Initializing refraction model and setting the reduced height
|
||||
ref = refraction(lat, h)
|
||||
ref.setReducedHeight(P, rho)
|
||||
ref.setReducedHeight(p, rho)
|
||||
return ref.cassini(n, z)
|
||||
|
||||
def quick_dispersion(l1, l2, z, conditions='STANDARD'):
|
||||
|
||||
def quick_dispersion(l1, l2, z, conditions='STANDARD', T=288.15,
|
||||
p=101325, H=0.0, xc=450, lat=0, h=0):
|
||||
'''
|
||||
Function to quickly calculate the dispersion
|
||||
of atmospheric air at reference conditions,
|
||||
given a wavelength l.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
l1 : float
|
||||
Shortest wavelength of interest in micron.
|
||||
l2 : float
|
||||
Longest wavelength of interest in micron.
|
||||
z : float
|
||||
Zenith angle of the observation
|
||||
conditions : string
|
||||
'STANDARD' or 'CERRO_ARMAZONES', refers
|
||||
to the standard atmospheric conditions.
|
||||
T : float (optional)
|
||||
Temperature in Kelvin
|
||||
p : float (optional)
|
||||
Atmospheric pressure in Pa
|
||||
H : float (optional)
|
||||
Relative humidity
|
||||
xc : float (optional)
|
||||
CO2 density in parts per million
|
||||
lat : float (optional)
|
||||
Latitude of the observer in degrees
|
||||
h : float (optional)
|
||||
Altitude of the observer in meters
|
||||
|
||||
Returns
|
||||
-------
|
||||
dR : float
|
||||
Atmospheric dispersion in degrees
|
||||
'''
|
||||
if conditions == 'STANDARD':
|
||||
# Parameters at Cerro Armazones
|
||||
T = 288.15 # k
|
||||
P = 101325 # Pa
|
||||
p = 101325 # Pa
|
||||
H = 0.0
|
||||
xc = 450 # ppm
|
||||
lat = 0 # degrees
|
||||
h = 0 # m
|
||||
|
||||
|
||||
elif conditions == 'CERRO_ARMAZONES':
|
||||
# Parameters at Cerro Armazones
|
||||
T = 279.65 # k
|
||||
P = 71200 # Pa
|
||||
p = 71200 # Pa
|
||||
H = 0.22
|
||||
xc = 450 # ppm
|
||||
lat = -24.5983 # degrees
|
||||
@@ -94,13 +193,13 @@ def quick_dispersion(l1, l2, z, conditions='STANDARD'):
|
||||
at = Observatory()
|
||||
|
||||
# Calculating indices of refraction for l1 and l2
|
||||
n1 = at.n_tph(l=l1, T=T, p=P, RH=H, xc=xc)
|
||||
n2 = at.n_tph(l=l2, T=T, p=P, RH=H, xc=xc)
|
||||
n1 = at.n_tph(l=l1, T=T, p=p, RH=H, xc=xc)
|
||||
n2 = at.n_tph(l=l2, T=T, p=p, RH=H, xc=xc)
|
||||
|
||||
# Density of the atmosphere (following CIPM-81/91 equations)
|
||||
rho = at.rho(p=P, T=T, RH=H, xc=xc)
|
||||
rho = at.rho(p=p, T=T, RH=H, xc=xc)
|
||||
|
||||
# Initializing refraction model and setting the reduced height
|
||||
disp = dispersion(lat, h)
|
||||
disp.setReducedHeight(P, rho)
|
||||
disp.setReducedHeight(p, rho)
|
||||
return disp.cassini(n1, n2, z)
|
||||
@@ -3,6 +3,7 @@ import numpy as np
|
||||
from scipy import integrate
|
||||
import os
|
||||
from .ciddorModel import Observatory
|
||||
|
||||
'''
|
||||
@ Author: Joost van den Born
|
||||
@ Contact: born@astron.nl
|
||||
@@ -17,6 +18,61 @@ from .ciddorModel import Observatory
|
||||
'''
|
||||
|
||||
class refraction(Observatory):
|
||||
'''
|
||||
Class that sets the observer location.
|
||||
These location attributes are then used to calculate the
|
||||
appropriate atmospheric refraction.
|
||||
|
||||
See also:
|
||||
Observatory()
|
||||
dispersion()
|
||||
...
|
||||
|
||||
Attributes
|
||||
-----------
|
||||
lat : float
|
||||
Latitude of the observer in degrees
|
||||
h : float
|
||||
Altitude above mean sea level of the observer in meters
|
||||
Other Observatory() attributes
|
||||
|
||||
Methods
|
||||
-------
|
||||
setReducedHeight(p, rho)
|
||||
Sets the reduced atmospheric height.
|
||||
planeParallel(n1, n2, zenith)
|
||||
Returns the atmospheric refraction assuming a plane parallel
|
||||
atmosphere
|
||||
cassini(n1, n2, zenith, reduced_height=None)
|
||||
Returns the atmospheric refraction asusming Cassini's homegeneous
|
||||
atmosphere model
|
||||
tan5(n1, n2, zenith, reduced_height=None)
|
||||
Returns the atmospheric refraction following Oriani's theorem,
|
||||
including a fifth order term in the expansion.
|
||||
oriani(n1, n2, zenith, reduced_height=None)
|
||||
Returns the atmospheric refraction following the classic version
|
||||
of Oriani's theorem.
|
||||
corbard(n1, n2, zenith, reduced_height=None)
|
||||
Returns the atmospheric refraction following the method described
|
||||
in Corbard et al., 2019.
|
||||
refractionIntegral(n1, n2, z0, R0=None, useStandardAtmosphere=True, heightData=None, rhoData=None)
|
||||
Returns the atmospheric refraction following the refraction integral.
|
||||
psi(x)
|
||||
Submethod for corbard()
|
||||
set_rc()
|
||||
Sets the local radius of curvature of the Earth at the observer.
|
||||
set_H(p, rho)
|
||||
Sets the reduced height for the conditions at the observer, assuming
|
||||
an adiabatic atmosphere.
|
||||
H_isotherm(T)
|
||||
Sets the reduced height for the conditions at the observer, assuming
|
||||
an isothermal atmosphere.
|
||||
cassiniError(z, l1, l2, T, p, RH, xc, dl1=0, dl2=0, dT=0.2, dP=20,
|
||||
dRH=0.02, dCO2=20, dz=0, lat=None, h=None)
|
||||
Returns the uncertainty in the atmospheric refraction, assuming
|
||||
Cassini's homegeneous atmosphere model and the given parameters.
|
||||
Other Observatory() methods
|
||||
'''
|
||||
def __init__(self, lat, h):
|
||||
Observatory.__init__(self)
|
||||
self.h = h # height above sea level in meters
|
||||
@@ -24,13 +80,36 @@ class refraction(Observatory):
|
||||
self.rc = self.set_rc() * 1000 # Radius of curvature of the earth at the observer
|
||||
# self.H2 = self.H_isotherm(T) # Reduced height of isotherm atmosphere
|
||||
|
||||
def setReducedHeight(self, P, rho):
|
||||
self.H = self.set_H(P, rho) # Reduced height of the atmosphere assuming ideal gas law
|
||||
def setReducedHeight(self, p, rho):
|
||||
'''
|
||||
Sets the reduced atmospheric height.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
p : float
|
||||
Atmospheric pressure in Pascal
|
||||
rho : float
|
||||
Density of the atmospheric air at the observer
|
||||
'''
|
||||
self.H = self.set_H(p, rho) # Reduced height of the atmosphere assuming ideal gas law
|
||||
|
||||
|
||||
def planeParallel(self, n, zenith):
|
||||
def planeParallel(self, n1, zenith):
|
||||
'''
|
||||
Refraction based on a flat atmosphere, easily derived from Snell's law.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
n1 : float
|
||||
Refractive index at the wavelength of interest
|
||||
zenith : float
|
||||
Angle of observation in degrees.
|
||||
zenith = 0 means the observation is directly overhead.
|
||||
|
||||
Returns
|
||||
-------
|
||||
R : float
|
||||
Atmospheric refraction in degrees
|
||||
'''
|
||||
_R = np.arcsin(n * np.sin( np.deg2rad(zenith) )) - np.deg2rad(zenith)
|
||||
return np.degrees(_R)
|
||||
@@ -40,6 +119,22 @@ class refraction(Observatory):
|
||||
def cassini(self, n1, zenith, reduced_height=None):
|
||||
'''
|
||||
Refraction of spherical atmosphere, derived from geometry using Sine law
|
||||
|
||||
Parameters
|
||||
----------
|
||||
n1 : float
|
||||
Refractive index at the wavelength of interest
|
||||
zenith : float
|
||||
Angle of observation in degrees.
|
||||
zenith = 0 means the observation is directly overhead.
|
||||
reduced_height : float (optional)
|
||||
Reduced height of the atmosphere. Default value is calculated
|
||||
from the object attributes.
|
||||
|
||||
Returns
|
||||
-------
|
||||
R : float
|
||||
Atmospheric refraction in degrees
|
||||
'''
|
||||
if reduced_height:
|
||||
H = reduced_height
|
||||
@@ -55,6 +150,22 @@ class refraction(Observatory):
|
||||
'''
|
||||
Same as oriani's theorem, but including a higher order term.
|
||||
Found in Corbard et al., 2019.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
n1 : float
|
||||
Refractive index at the wavelength of interest
|
||||
zenith : float
|
||||
Angle of observation in degrees.
|
||||
zenith = 0 means the observation is directly overhead.
|
||||
reduced_height : float (optional)
|
||||
Reduced height of the atmosphere. Default value is calculated
|
||||
from the object attributes.
|
||||
|
||||
Returns
|
||||
-------
|
||||
R : float
|
||||
Atmospheric refraction in degrees
|
||||
'''
|
||||
if reduced_height:
|
||||
H = reduced_height
|
||||
@@ -70,8 +181,25 @@ class refraction(Observatory):
|
||||
|
||||
def oriani(self, n1, zenith, reduced_height=None):
|
||||
'''
|
||||
Classic refraction formula with two tan(z) terms. This does not assume any
|
||||
information about the structure of the atmosphere. Found with Oriani's theorem.
|
||||
Classic refraction formula with two tan(z) terms. This does not
|
||||
assume any information about the structure of the atmosphere.
|
||||
Found with Oriani's theorem.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
n1 : float
|
||||
Refractive index at the wavelength of interest
|
||||
zenith : float
|
||||
Angle of observation in degrees.
|
||||
zenith = 0 means the observation is directly overhead.
|
||||
reduced_height : float (optional)
|
||||
Reduced height of the atmosphere. Default value is calculated
|
||||
from the object attributes.
|
||||
|
||||
Returns
|
||||
-------
|
||||
R : float
|
||||
Atmospheric refraction in degrees
|
||||
'''
|
||||
if reduced_height:
|
||||
H = reduced_height
|
||||
@@ -90,6 +218,22 @@ class refraction(Observatory):
|
||||
Corbard et al., 2019, mention an additional formula based on the error function.
|
||||
Oriani's theorem can be derived from this equation by 'keeping only the three first
|
||||
terms of its asymptotic expansion'.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
n1 : float
|
||||
Refractive index at the wavelength of interest
|
||||
zenith : float
|
||||
Angle of observation in degrees.
|
||||
zenith = 0 means the observation is directly overhead.
|
||||
reduced_height : float (optional)
|
||||
Reduced height of the atmosphere. Default value is calculated
|
||||
from the object attributes.
|
||||
|
||||
Returns
|
||||
-------
|
||||
R : float
|
||||
Atmospheric refraction in degrees
|
||||
'''
|
||||
if reduced_height:
|
||||
H = reduced_height
|
||||
@@ -103,14 +247,44 @@ class refraction(Observatory):
|
||||
|
||||
|
||||
|
||||
def refractionIntegral(self, n0, z0, R0=None, useStandardAtmosphere=True, heightData=None, rhoData=None):
|
||||
def refractionIntegral(self, n1, z0, R0=None, useStandardAtmosphere=True, heightData=None, rhoData=None):
|
||||
'''
|
||||
Using data that gives temperature, pressure and density as a function of height,
|
||||
the gladstone-dale relation is invoked to calculate the path of a light ray
|
||||
along the atmosphere. This is allows us to also include atmospheric activity in
|
||||
Using data that gives temperature, pressure and density as a
|
||||
function of height, the gladstone-dale relation is invoked to
|
||||
calculate the path of a light ray along the atmosphere.
|
||||
This is allows us to also include atmospheric activity in
|
||||
different atmosphere layers.
|
||||
Recommended use with the US Standard Atmosphere from 1976.
|
||||
USSA1976 data generated from code supplied by http://www.pdas.com/atmos.html
|
||||
The method described in eq. 3 in Auer & Standish (2000) is used for the
|
||||
calculation.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
n1 : float
|
||||
Refractive index at the wavelength of interest
|
||||
z0 : float
|
||||
Angle of observation in degrees.
|
||||
zenith = 0 means the observation is directly overhead.
|
||||
R0 : float (optional)
|
||||
Local radius of curvature of the Earth in km.
|
||||
useStandardAtmosphere : bool
|
||||
Flag to use the included USSA1976 data
|
||||
heightData : 1D Array
|
||||
If "useStandardAtmosphere" is False, the function will ask
|
||||
for alternative atmospheric data to integrate over. This
|
||||
gives the altitudinal points
|
||||
rhoData : 1D Array
|
||||
If useStandardAtmosphere is False, the function will ask
|
||||
for alternative atmospheric data to integrate over. This
|
||||
gives the atmospheric density at the points defined by
|
||||
"heightData".
|
||||
|
||||
Returns
|
||||
-------
|
||||
R : float
|
||||
Atmospheric refraction in degrees
|
||||
|
||||
'''
|
||||
if not R0:
|
||||
R0 = self.rc
|
||||
@@ -148,6 +322,19 @@ class refraction(Observatory):
|
||||
|
||||
|
||||
def psi(self, x):
|
||||
'''
|
||||
Submethod for corbard(). Described explicitly in Corbard et al.,2019.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
x : float
|
||||
Input of the function
|
||||
|
||||
Returns
|
||||
-------
|
||||
y : float
|
||||
Output of the function
|
||||
'''
|
||||
_f = lambda a: np.exp(-a**2)
|
||||
_int = integrate.quad(_f, x, np.inf)
|
||||
return np.exp(x**2) * _int[0]
|
||||
@@ -159,6 +346,11 @@ class refraction(Observatory):
|
||||
Returns the radius of the curvature at the observer in km,
|
||||
taking into account the latitude of the observer and the corresponding
|
||||
ellipsoidality of the earth.
|
||||
|
||||
Returns
|
||||
-------
|
||||
rc : float
|
||||
Local radius of curvature of the Earth in kilometers.
|
||||
'''
|
||||
_A = 6378.137 # km
|
||||
_B = 6356.752 # km
|
||||
@@ -169,9 +361,21 @@ class refraction(Observatory):
|
||||
|
||||
|
||||
|
||||
def set_H(self, P, rho):
|
||||
def set_H(self, p, rho):
|
||||
'''
|
||||
Calculates the reduced height of the atmosphere, assuming ideal gas law.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
p : float
|
||||
Atmospheric pressure in Pascal
|
||||
rho : float
|
||||
Density of the atmospheric air at the observer
|
||||
|
||||
Returns
|
||||
-------
|
||||
H : float
|
||||
Reduced height of the atmosphere in meters
|
||||
'''
|
||||
_phi = np.deg2rad(self.lat)
|
||||
_c1 = 5.2790414e-3
|
||||
@@ -181,11 +385,22 @@ class refraction(Observatory):
|
||||
_g0 = 9.780327 # m/s^2
|
||||
_g0_local = _g0 * (1 + _c1 * np.sin(_phi)**2 + _c2 * np.sin(_phi)**4 + _c3 * np.sin(_phi)**6 + _c4 * np.sin(_phi)**8)
|
||||
_g = _g0_local - (3.0877e-6 - 4.3e-9 * np.sin(_phi)**2) * self.h + 7.2e-13 * self.h**2
|
||||
return P / (rho * _g)
|
||||
return p / (rho * _g)
|
||||
|
||||
def H_isotherm(self, T):
|
||||
'''
|
||||
Calculates the reduced height of the atmosphere, assuming an isotherm distribution.
|
||||
Calculates the reduced height of the atmosphere,
|
||||
assuming an isotherm distribution.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
T : float
|
||||
Atmospheric temperature in Kelvin
|
||||
|
||||
Returns
|
||||
-------
|
||||
H : float
|
||||
Reduced height of the atmosphere in meters
|
||||
'''
|
||||
_kb = 1.38064852e-23 # kg m2 s-2 K-1
|
||||
_m = 4.809651698e-26 # kg (weight per molecule of air, assuming dry air)
|
||||
@@ -203,6 +418,28 @@ class refraction(Observatory):
|
||||
def cassiniError(self, n, dn, zenith, dz=0, reduced_height=None):
|
||||
'''
|
||||
Calculates the uncertainty in the refraction angle in degrees.
|
||||
See Observatory().n_tph() and Observatory().dn_tph() on how to
|
||||
calculate the refractive index and it's uncertainty.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
n : float
|
||||
Refractive index of air
|
||||
dn : float
|
||||
Uncertainty in the refractive index of air
|
||||
zenith : float
|
||||
Angle of observation in degrees.
|
||||
zenith = 0 means the observation is directly overhead.
|
||||
dz : float (optional)
|
||||
Uncertainty in the zenith angle, in degrees.
|
||||
reduced_height : float (optional)
|
||||
Reduced height of the atmosphere. Default value is calculated
|
||||
from the object attributes.
|
||||
|
||||
Returns
|
||||
-------
|
||||
dR : float
|
||||
Uncertainty in the atmospheric refraction in degrees.
|
||||
'''
|
||||
if reduced_height:
|
||||
_H = reduced_height
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#!/usr/bin/env Python3
|
||||
import numpy as np
|
||||
|
||||
|
||||
'''
|
||||
@ Author: Joost van den Born
|
||||
@ Contact: born@astron.nl
|
||||
@@ -17,14 +16,21 @@ def BarrellAndSears(l, T=288.15, p=101325, H=0):
|
||||
For atmospheric air (i.e. CO2 = 300 ppm)
|
||||
This equation is applicable for the ranges T=10-30C and p=720-800 mmHg.
|
||||
|
||||
Input:
|
||||
l - Wavelength in microns
|
||||
T - Temperature in Kelvin
|
||||
p - Atmospheric pressure in Pa
|
||||
H - fractional humidity (0=<H=<1)
|
||||
Parameters
|
||||
----------
|
||||
l : float
|
||||
Wavelength in microns
|
||||
T : float
|
||||
Temperature in Kelvin
|
||||
p : float
|
||||
Atmospheric pressure in Pascal
|
||||
H : float
|
||||
Relative humidity (0=<H=<1)
|
||||
|
||||
Returns:
|
||||
n - Refractive index of atmospheric air at the given conditions
|
||||
Returns
|
||||
-------
|
||||
n : float
|
||||
Refractive index of atmospheric air at the given conditions
|
||||
'''
|
||||
T = K2C(T)
|
||||
P = hPA2mmHg(p/100)
|
||||
@@ -39,11 +45,15 @@ def Ciddor(l, CO2=450):
|
||||
At default conditions only. For more flexibility use
|
||||
Observatory.n_tph()
|
||||
|
||||
Input:
|
||||
l - Wavelength in microns
|
||||
Parameters
|
||||
----------
|
||||
l : float
|
||||
Wavelength in microns
|
||||
|
||||
Returns:
|
||||
n - Refractive index of atmospheric air at the given conditions
|
||||
Returns
|
||||
-------
|
||||
n : float
|
||||
Refractive index of atmospheric air at the given conditions
|
||||
'''
|
||||
s = 1 / l
|
||||
R = 5792105 / (238.0185 - s**2) + 167917 / (57.362 - s**2)
|
||||
@@ -59,11 +69,15 @@ def Edlen1953(l):
|
||||
|
||||
At standard conditions only
|
||||
|
||||
Input:
|
||||
l - Wavelength in microns
|
||||
Parameters
|
||||
----------
|
||||
l : float
|
||||
Wavelength in microns
|
||||
|
||||
Returns:
|
||||
n - Refractive index of atmospheric air at the given conditions
|
||||
Returns
|
||||
-------
|
||||
n : float
|
||||
Refractive index of atmospheric air at the given conditions
|
||||
'''
|
||||
s = 1 / l
|
||||
R = 6432.8 + 2949810 / (146 - s**2) + 25540/(41-s**2)
|
||||
@@ -77,11 +91,15 @@ def Edlen1966(l):
|
||||
|
||||
At standard conditions only
|
||||
|
||||
Input:
|
||||
l - Wavelength in microns
|
||||
Parameters
|
||||
----------
|
||||
l : float
|
||||
Wavelength in microns
|
||||
|
||||
Returns:
|
||||
n - Refractive index of atmospheric air at the given conditions
|
||||
Returns
|
||||
-------
|
||||
n : float
|
||||
Refractive index of atmospheric air at the given conditions
|
||||
'''
|
||||
s = 1 / l
|
||||
R = 8342.13 + 2406030 / (130 - s**2) + 15997 / (38.9 - s**2)
|
||||
@@ -95,14 +113,21 @@ def Owens(l, T=288.15, p=101325, H=0):
|
||||
Note that the pressure P and H are in torricelli (Torr),
|
||||
however, this is almost precisely 1 Torr = 1 mmHg
|
||||
|
||||
Input:
|
||||
l - wavelength in micron
|
||||
T - Temperature in Kelvin
|
||||
p - Atmospheric pressure in Pa
|
||||
H - Humdity (0<=H<=1)
|
||||
Parameters
|
||||
----------
|
||||
l : float
|
||||
wavelength in micron
|
||||
T : float
|
||||
Temperature in Kelvin
|
||||
p : float
|
||||
Atmospheric pressure in Pa
|
||||
H : float
|
||||
Humdity (0<=H<=1)
|
||||
|
||||
Returns:
|
||||
n - Refractive index of atmospheric air at the given conditions
|
||||
Returns
|
||||
-------
|
||||
n : float
|
||||
Refractive index of atmospheric air at the given conditions
|
||||
'''
|
||||
P = hPA2mmHg(p/100)
|
||||
T = K2C(T)
|
||||
@@ -116,14 +141,21 @@ def BonschPotulski(l, T=288.15, p=101325, CO2=450):
|
||||
From Bonsch & Potulski, 1998
|
||||
Equations 6, 7, 8
|
||||
|
||||
Input:
|
||||
l - Wavelength in microns
|
||||
T - Temperature in Kelvin
|
||||
p - Atmospheric pressure in Pa
|
||||
CO2 - Particles per million of CO2
|
||||
Parameters
|
||||
----------
|
||||
l : float
|
||||
Wavelength in microns
|
||||
T : float
|
||||
Temperature in Kelvin
|
||||
p : float
|
||||
Atmospheric pressure in Pa
|
||||
CO2 : float
|
||||
Particles per million of CO2
|
||||
|
||||
Returns:
|
||||
n - Refractive index of atmospheric air at the given conditions
|
||||
Returns
|
||||
-------
|
||||
n : float
|
||||
Refractive index of atmospheric air at the given conditions
|
||||
'''
|
||||
x = CO2 / 1e6
|
||||
T = K2C(T)
|
||||
@@ -143,11 +175,15 @@ def BirchDowns(l):
|
||||
|
||||
Only at standard conditions
|
||||
|
||||
Input:
|
||||
l - wavelength in micron
|
||||
Parameters
|
||||
----------
|
||||
l : float
|
||||
wavelength in micron
|
||||
|
||||
Returns:
|
||||
n - Refractive index of atmospheric air at the given conditions
|
||||
Returns
|
||||
-------
|
||||
n : float
|
||||
Refractive index of atmospheric air at the given conditions
|
||||
'''
|
||||
s = 1 / l
|
||||
R = 8342.54 + 2406147 / (130 - s**2) + 15998 / (38.9-s**2)
|
||||
@@ -161,11 +197,15 @@ def PeckReeder(l):
|
||||
|
||||
Only at standard conditions
|
||||
|
||||
Input:
|
||||
l - wavelength in micron
|
||||
Parameters
|
||||
----------
|
||||
l : float
|
||||
wavelength in micron
|
||||
|
||||
Returns:
|
||||
n - Refractive index of atmospheric air at the given conditions
|
||||
Returns
|
||||
-------
|
||||
n : float
|
||||
Refractive index of atmospheric air at the given conditions
|
||||
'''
|
||||
s = 1 / l
|
||||
R = 8060.51 + 2480990 / (132.274 - s**2) + 17455.7 / (39.32957 - s**2)
|
||||
@@ -180,18 +220,29 @@ def slalib(l, T=288.15, p=101325, H=0, h=0, lat=-24, tlr=0.0065, eps=1e-10):
|
||||
They take the B&S refraction formula as a basis.
|
||||
Requires the pySLALIB package to work.
|
||||
|
||||
Input:
|
||||
l - Wavelength in microns
|
||||
T - Temperature in Kelvin
|
||||
p - Atmospheric pressure in Pa
|
||||
H - fractional humidity (0=<H=<1)
|
||||
h - Altitude of the observer (default=0 m)
|
||||
lat - Latitude of the observer (default=-24)
|
||||
tlr - temperature lapse rate (default=0.0065)
|
||||
eps - precision at which the calculation is aborted (default=1e-10)
|
||||
Parameters
|
||||
----------
|
||||
l : float
|
||||
Wavelength in microns
|
||||
T : float
|
||||
Temperature in Kelvin
|
||||
p : float
|
||||
Atmospheric pressure in Pa
|
||||
H : float
|
||||
fractional humidity (0=<H=<1)
|
||||
h : float
|
||||
Altitude of the observer (default=0 m)
|
||||
lat : float
|
||||
Latitude of the observer (default=-24)
|
||||
tlr : float
|
||||
temperature lapse rate (default=0.0065)
|
||||
eps : float
|
||||
precision at which the calculation is aborted (default=1e-10)
|
||||
|
||||
Returns:
|
||||
n - Refractive index of atmospheric air at the given conditions
|
||||
Returns
|
||||
-------
|
||||
n : float
|
||||
Refractive index of atmospheric air at the given conditions
|
||||
'''
|
||||
try:
|
||||
from pyslalib import slalib
|
||||
@@ -215,17 +266,27 @@ def slalib(l, T=288.15, p=101325, H=0, h=0, lat=-24, tlr=0.0065, eps=1e-10):
|
||||
def Mathar(l, T=288.15, p=101325, H=0):
|
||||
'''
|
||||
Refractivity model by Mathar (2007), valid above 1.4 microns
|
||||
Code taken and modified from:
|
||||
Code taken from
|
||||
https://github.com/polyanskiy/refractiveindex.info-scripts/blob/master/scripts/Mathar%202007%20-%20Air%201.3-2.5um.py
|
||||
(better known from refractiveindex.info). The code was subsequently
|
||||
minimally modified to make it suitable for this package.
|
||||
|
||||
Input:
|
||||
l - Wavelength in microns
|
||||
T - Temperature in Kelvin
|
||||
p - Atmospheric pressure in Pa
|
||||
H - fractional humidity (0=<H=<1)
|
||||
|
||||
Returns:
|
||||
n - Refractive index of atmospheric air at the given conditions
|
||||
Parameters
|
||||
----------
|
||||
l : float
|
||||
Wavelength in microns
|
||||
T : float
|
||||
Temperature in Kelvin
|
||||
p : float
|
||||
Atmospheric pressure in Pa
|
||||
H : float
|
||||
fractional humidity (0=<H=<1)
|
||||
|
||||
Returns
|
||||
-------
|
||||
n : float
|
||||
Refractive index of atmospheric air at the given conditions
|
||||
'''
|
||||
if l < 1.3 or l > 24:
|
||||
print('Using the Mathar model at this wavelength (l={:.3f}) is not recommended!'.format(l))
|
||||
@@ -346,11 +407,32 @@ def Mathar(l, T=288.15, p=101325, H=0):
|
||||
def K2C(K):
|
||||
'''
|
||||
Kelvin to Celsius conversion
|
||||
|
||||
Parameters
|
||||
----------
|
||||
K : float
|
||||
Temperature in Kelvin
|
||||
|
||||
Returns
|
||||
-------
|
||||
C : float
|
||||
Temperature in Celsius
|
||||
'''
|
||||
return K - 273.15
|
||||
|
||||
def hPA2mmHg(hPa):
|
||||
'''
|
||||
hPa to mmHg conversion
|
||||
|
||||
Parameters
|
||||
----------
|
||||
hPa : float
|
||||
Atmospheric pressure in hPa (hecto Pascal)
|
||||
|
||||
Returns
|
||||
-------
|
||||
mmHg : float
|
||||
Atmospheric pressure in mmHg
|
||||
'''
|
||||
return 0.7500616827 * hPa
|
||||
return 0.7500616827 * hPa
|
||||
|
||||
Reference in new issue
Block a user