mirror of
https://gitlab.astro-wise.org/micado/atmosphericmodel.git
synced 2026-10-30 05:01:02 +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
@@ -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
|
||||
|
||||
Reference in new issue
Block a user