#!/usr/bin/env Python3 import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.axes_grid1 import host_subplot from matplotlib.colors import LogNorm from tabulate import tabulate import AstroAtmosphere ''' @ Author: Joost van den Born @ Contact: born@astron.nl @ Description: A comparison of various atmospheric refraction models. Also these are used to calculate the difference in atmospheric dispersion, given a set of conditions. This is a reproduction of and expansion on Figure 1 of Spàno (2014). ''' class atmosphericModel: def __init__(self, T, P, H, CO2, l1, l2): self.T = T self.P = P self.H = H self.CO2 = CO2 self.lrange = np.linspace(l1, l2, 100) def BarrellAndSears(self, l=None): if not l: l = self.lrange return (AstroAtmosphere.BarrellAndSears(l, T=self.T, p=self.P)-1) def Ciddor(self, l=None): if not l: l = self.lrange return (AstroAtmosphere.Ciddor(l, CO2=self.CO2)-1) def Edlen1953(self, l=None): if not l: l = self.lrange return(AstroAtmosphere.Edlen1953(l)-1) def Edlen1966(self, l=None): if not l: l = self.lrange return(AstroAtmosphere.Edlen1966(l)-1) def Owens(self, l=None): if not l: l = self.lrange return (AstroAtmosphere.Owens(l, T=self.T, p=self.P, RH=self.H)-1) def BonschPotulski(self, l=None): if not l: l = self.lrange return (AstroAtmosphere.BonschPotulski(l, T=self.T, p=self.P, CO2=self.CO2)-1) def BirchDowns(self, l=None): if not l: l = self.lrange return (AstroAtmosphere.BirchDowns(l)-1) def PeckReeder(self, l=None): if not l: l = self.lrange return (AstroAtmosphere.PeckReeder(l)-1) def HohenkerkAndSinclair(self, l=None): if not l: l = self.lrange return (AstroAtmosphere.HohenkerkAndSinclair(l, T=self.T, p=self.P, RH=self.H)-1) def slalib(self, l=None): if not l: l = self.lrange try: from pyslalib import slalib return(AstroAtmosphere.slalib(l, T=self.T, p=self.P, RH=self.H)-1) except ImportError as e: print('Could not import pyslalib.slalib. Using slower Python native function sla_refro().') h=0 lat=-24 tlr=0.0065 eps=1e-10 zObs = np.deg2rad(45.07182) p = self.P/100 R = [] if type(l) == float: l = [l] for wl in l: R.append(AstroAtmosphere.sla_refro(zObs, h, self.T, p, self.H, wl, lat, tlr, eps)) if len(l) == 1: return R[0] else: return np.asarray(R) if __name__ == '__main__': # Calculation of the refractivity of the different models # multiplication by 1e8 to make the differentials more # pronounced. at = atmosphericModel(T=288.15, P=101325, H=0, CO2=300, l1=0.3, l2=2.5) BSdata = 1e8 * at.BarrellAndSears() CiddorData = 1e8 * at.Ciddor() Edlen1953Data = 1e8 * at.Edlen1953() Edlen1966Data = 1e8 * at.Edlen1966() OwensData = 1e8 * at.Owens() BonschPotulskiData = 1e8 * at.BonschPotulski() BirchDownsData = 1e8 * at.BirchDowns() PeckReederData = 1e8 * at.PeckReeder() HSdata = 1e8 * at.HohenkerkAndSinclair() slalibData = 1e8 * at.slalib() # Plotting the results fig = plt.figure(figsize=(9,5)) ax2 = fig.add_subplot(111) ax2.grid(True, alpha=0.3) ax2.plot(at.lrange, BSdata - CiddorData, 'b-', label='Barrell & Sears (1939)') ax2.plot(at.lrange, CiddorData - CiddorData, 'k-', label='Ciddor (1996)') ax2.plot(at.lrange, Edlen1953Data - CiddorData, 'r:', label='Edlen (1953)') ax2.plot(at.lrange, Edlen1966Data - CiddorData, 'g--', label='Edlen (1966)') ax2.plot(at.lrange, OwensData - CiddorData, 'm--', label='Owens (1967)') ax2.plot(at.lrange, BonschPotulskiData - CiddorData, 'g-.', label='Bonsch & Potulski (1998)') ax2.plot(at.lrange, BirchDownsData - CiddorData, 'r-.', label='Birch & Downs (1993, 1994)') ax2.plot(at.lrange, PeckReederData - CiddorData, 'b--', label='Peck & Reeder (1972)') ax2.plot(at.lrange, HSdata - CiddorData, 'y--', label='Hohenkerk & Sinclair (1985)') ax2.plot(at.lrange, slalibData - CiddorData, 'y-', label='ZEMAX / SLALIB') box = ax2.get_position() ax2.set_position([box.x0, box.y0, box.width, box.height]) ax2.legend(loc='center left', bbox_to_anchor=(1, 0.5)) ax2.set_xlabel('Wavelength ($\mu m$)') ax2.set_ylabel('$\Delta$n $\\times$ $10^{8}$') ax2.set_ylim([-3,7]) plt.tight_layout() plt.show() # Let's compare the impact on the atmospheric dispersion. # For the dispersion we must compare the delta for two lambda values methodList = [ at.BarrellAndSears, at.Ciddor, at.Edlen1953, at.Edlen1966, at.Owens, at.BonschPotulski, at.BirchDowns, at.PeckReeder, at.HohenkerkAndSinclair, at.slalib ] filters = [ [0.800, 0.934], # I-band [1.150, 1.345], # J-band [1.490, 1.780], # H-band [1.970, 2.320] # K-band ] filterDispersion = [] # Iterate over the four MICADO broad band filters for f in filters: # Wavelengths of this particular filter l1 = f[0] l2 = f[1] dispersionList = [] for m in methodList: d1 = m(l=l1) d2 = m(l=l2) deltan = d1 - d2 # We assume, for sake of simplicity, a plane parallel atmosphere # and calculate the dispersion in milli arcseconds. dispersion = deltan * np.tan(np.deg2rad(45)) * 206265 * 1000 dispersionList.append(dispersion) # We compare the atmospheric dispersion relative to the atmospheric # dispersion as calculated using the Ciddor model. dispersionList = np.asarray(dispersionList) - dispersionList[1] filterDispersion.append(dispersionList) # Print the results in a table. methodStringList = ['Barrell & Sears (1939)', 'Ciddor (1996)', 'Edlen (1953)', 'Edlen (1966)', 'Owens (1967)', 'Bonsch & Potulski (1998)', 'Birch & Downs (1993, 1994)', 'Peck & Reeder (1972)', 'Hohenkerk & Sinclair (1985)', 'slalib'] tableData = [] for i in range(len(methodStringList)): tableData.append([methodStringList[i], filterDispersion[0][i], filterDispersion[1][i], filterDispersion[2][i], filterDispersion[3][i]]) print(tabulate(tableData, headers=['Model', 'I-band\n(0.8 - 0.934)', 'J-band\n(1.15 - 1.345)', 'H-band\n(1.49 - 1.78)', 'K-band\n(1.97 - 2.32)']))