mirror of
https://gitlab.astro-wise.org/micado/atmosphericmodel.git
synced 2026-10-29 20:51:05 +00:00
137 lines
4.1 KiB
Python
137 lines
4.1 KiB
Python
#!/usr/bin/env Python3
|
|
import numpy as np
|
|
import matplotlib.pyplot as plt
|
|
from AstroAtmosphere import *
|
|
from ADC import *
|
|
import sys
|
|
import scipy.optimize as opt
|
|
|
|
|
|
|
|
'''
|
|
@ Author: Joost van den Born
|
|
@ Contact: born@astron.nl
|
|
@ Description: This script finds the filter constant using
|
|
- Direct application of equation 18 and 19
|
|
- The minimization algorithm implemented in the ADC class
|
|
and compares these two.
|
|
'''
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class filter:
|
|
def __init__(self, name, l1, l2):
|
|
self.name = name
|
|
self.lmin = np.min([l1,l2])
|
|
self.lmax = np.max([l1,l2])
|
|
self.bandwidth = self.lmax - self.lmin
|
|
self.optimumAngle = None
|
|
self.residualDispersion = None
|
|
self.optimumAngleForAllZ = None
|
|
self.cf = None
|
|
|
|
def analytic_optimum_position_ADC(self, z, l1, l2, dispersion_object, adc_object):
|
|
disp = dispersion_object
|
|
adc = adc_object
|
|
|
|
_R = disp.rc / (disp.rc + disp.H)
|
|
n1 = at.n_tph(l=self.lmin, T=T, p=P, RH=H, xc=xc)
|
|
n2 = at.n_tph(l=self.lmax, T=T, p=P, RH=H, xc=xc)
|
|
dn_atm = n2 - n1
|
|
_dispersion = np.deg2rad(disp.cassini(n1,n2,z))
|
|
|
|
_A1 = np.deg2rad(adc.p1.tilt2x_OG - adc.p1.tilt1x_OG)
|
|
_A2 = np.deg2rad(adc.p2.tilt2x_OG - adc.p2.tilt1x_OG)
|
|
|
|
_A3 = -1 * np.deg2rad(adc.p3.tilt2x_OG - adc.p3.tilt1x_OG) # -1 because doublet gets flipped after setting rotation
|
|
_A4 = -1 * np.deg2rad(adc.p4.tilt2x_OG - adc.p4.tilt1x_OG) # -1 because doublet gets flipped after setting rotation
|
|
|
|
_dn_p1 = adc.p1.indexOfRefraction(l1) - adc.p1.indexOfRefraction(l2)
|
|
_dn_p2 = adc.p2.indexOfRefraction(l1) - adc.p2.indexOfRefraction(l2)
|
|
|
|
_pupilRatio = 0.07943/38.542
|
|
_Psi = (_dn_p1 * (_A1 + _A4) + _dn_p2 * (_A2 + _A3)) * _pupilRatio
|
|
|
|
_cf = -1/_pupilRatio * (dn_atm)/((_dn_p1 * (_A1 + _A4) + _dn_p2 * (_A2 + _A3)))
|
|
_thetaOpt = np.arccos(1/_Psi * _dispersion)
|
|
return np.degrees(_thetaOpt), _cf
|
|
|
|
def ADCposAnalytical(z, Cf):
|
|
return np.arccos(Cf*np.tan(np.deg2rad(z)))*180/np.pi
|
|
|
|
|
|
if __name__ == "__main__":
|
|
Iband = filter('I-band',0.8,0.934)
|
|
Jband = filter('J-band',1.15,1.345)
|
|
Hband = filter('H-band',1.49,1.78)
|
|
Kband = filter('K-band',1.97,2.32)
|
|
|
|
|
|
##########################################################
|
|
# Atmospheric model
|
|
# Parameters at Cerro Armazones
|
|
T = 279.65 # k
|
|
P = 71200 # Pa
|
|
H = 0.22
|
|
xc = 450 # ppm
|
|
lat = -24.5983 # degrees
|
|
h = 3064 # m
|
|
|
|
# Initializing dispersion model
|
|
at = Observatory()
|
|
|
|
# Density of the atmosphere (following CIPM-81/91 equations)
|
|
rho = at.rho(p=P, T=T, RH=H, xc=xc)
|
|
|
|
# Initializing dispersion object
|
|
disp = dispersion(lat, h)
|
|
disp.setReducedHeight(P, rho)
|
|
|
|
##########################################################
|
|
|
|
adc = ADC()
|
|
|
|
|
|
# Unlock this when the above works
|
|
# zRange = range(2,62)
|
|
zRange = np.arange(5,65.1,0.1)
|
|
optimumAngleFilterList = []
|
|
fig = plt.figure()
|
|
ax = fig.add_subplot(111)
|
|
|
|
|
|
for f in [Hband, Iband, Jband, Kband]:
|
|
# For new filters or if the zenith values are different, the new values are calculated
|
|
print ('Starting %s...' %f.name )
|
|
# Calculating indices of refraction for l1 and l2
|
|
n1 = at.n_tph(l=f.lmin, T=T, p=P, RH=H, xc=xc)
|
|
n2 = at.n_tph(l=f.lmax, T=T, p=P, RH=H, xc=xc)
|
|
dispersion_obs = disp.cassini(n1, n2, zRange)*3.6e6
|
|
|
|
adc.setOrientation(0)
|
|
theta_opt = [adc.optimize(disp, f.lmin, f.lmax) for disp in dispersion_obs]
|
|
f.optimumAngleForAllZ = theta_opt
|
|
# Plotting the data
|
|
ax.plot(zRange, f.optimumAngleForAllZ, label=f.name)
|
|
|
|
for f in [Hband, Iband, Jband, Kband]:
|
|
popt, pcov = opt.curve_fit(ADCposAnalytical, zRange[:-50], f.optimumAngleForAllZ[:-50], p0=0.5)
|
|
f.cf = popt[0]
|
|
ax.plot(zRange, ADCposAnalytical(zRange, f.cf), 'k--', label='best fit %s' %f.name)
|
|
theta_opt_analytical, cf_analytical = f.analytic_optimum_position_ADC(zRange, f.lmin, f.lmax, disp, adc)
|
|
ax.plot(zRange, ADCposAnalytical(zRange, cf_analytical), 'b--', label='analytical cf %s' %f.name)
|
|
print('{} - Best fit: {} - Analytical: {}'.format(f.name, f.cf, cf_analytical))
|
|
|
|
# Plot properties
|
|
ax.set_title('Optimum rotation angle of the first ADC prism', fontsize=9)
|
|
ax.set_ylabel('Rotation angle (deg)', fontsize=9)
|
|
ax.set_xlabel('Zenith angle (deg)', fontsize=9)
|
|
ax.grid(True, alpha=0.5)
|
|
ax.legend(fontsize=9)
|
|
|
|
plt.show()
|
|
|