def density_lookup(year, month, day, hour, altitude, glat, glon): """ Function: density_lookup Gets atmospheric density using MSISE-00 atmospheric model. Must have https://pypi.org/project/msise00/ library installed. Inputs: year month day hour altitude (km) glat: geodetic latitude glon: geodetic longitude Outputs: rho: atmospheric density (kg/m^3) """ atmos = msise00.run(time=datetime(year, month, day, hour), altkm=altitude, glat=glat, glon=glon) rho = atmos.Total.values[0].item() return rho
def msise00_model(alt, datetime_obj): atmos = msise00.run(time=datetime_obj, altkm=alt/1000, glat=65., glon=-148.) r = D(atmos['Total'].values[0,0,0,0]) # Denisty (kg/m^3) T = D(atmos['Tn'].values[0,0,0,0]) # Temperature (K) p = r*D(0.2869)*T # Pressure (kPa) return [T-D(273.15), p, r] # Return C, kPa, kg/m^3
def test_forecast(): t = datetime(2023, 3, 31, 12) altkm = 150.0 glat = 65.0 glon = -148.0 atmos = msise00.run(t, altkm, glat, glon) assert atmos["He"].ndim == 4 assert atmos["He"].size == 1 dims = list(atmos.dims) assert ["alt_km", "lat", "lon", "time"] == dims assert atmos["He"].item() == approx(4.3926901e12) assert atmos["O"].item() == approx(4.5728936e15) assert atmos["N2"].item() == approx(3.7001117e16) assert atmos["O2"].item() == approx(8.1215314e15) assert atmos["Ar"].item() == approx(3.3594181e14) assert atmos["Total"].item() == approx(2.2950717e-09) assert atmos["N"].item() == approx(2.155302e12) assert atmos["AnomalousO"].item() == approx(8.7590428e-16) assert atmos.species == [ "He", "O", "N2", "O2", "Ar", "Total", "H", "N", "AnomalousO" ] assert atmos["Tn"].item() == approx(667.06, abs=0.01) assert atmos["Texo"].item() == approx(922.28, abs=0.01)
def test_ccmc(): t = datetime(2001, 2, 2, 8, 0, 0) glat = 60.0 glon = -70.0 altkm = 400.0 indices = {"f107s": 163.6666, "f107": 146.7, "Ap": 7} with importlib.resources.path(__package__, "ccmc.log") as fn: A = np.loadtxt(fn, skiprows=25) atmos = msise00.run(t, altkm, glat, glon, indices) assert atmos.f107s == approx(indices["f107s"]) assert atmos.f107 == approx(indices["f107"]) assert atmos.Ap == indices["Ap"] assert A[0] == approx(altkm) assert A[1] == approx(atmos["O"].item() / 1e6, rel=0.01) assert A[2] == approx(atmos["N2"].item() / 1e6, rel=0.01) assert A[3] == approx(atmos["O2"].item() / 1e6, rel=0.01) assert A[7] == approx(atmos["He"].item() / 1e6, rel=0.01) assert A[8] == approx(atmos["Ar"].item() / 1e6, rel=0.01) assert A[9] == approx(atmos["H"].item() / 1e6, rel=0.01) assert A[10] == approx(atmos["N"].item() / 1e6, rel=0.01) assert A[11] == approx(atmos["AnomalousO"].item() / 1e6, rel=0.01) assert A[5] == approx(atmos["Tn"].item(), rel=0.001) assert A[6] == approx(atmos["Texo"].item(), rel=0.001)
def test_past(): t = datetime(2013, 3, 31, 12) altkm = 150.0 glat = 65.0 glon = -148.0 try: atmos = msise00.run(t, altkm, glat, glon) except ConnectionError: pytest.skip("unable to download RecentIndices.txt") assert atmos["He"].ndim == 4 assert atmos["He"].size == 1 dims = list(atmos.dims) assert ["alt_km", "lat", "lon", "time"] == dims # daily resolution assert atmos["He"].item() == approx(1.2523275e13) assert atmos["O"].item() == approx(1.3222577e16) assert atmos["N2"].item() == approx(2.9318694e16) assert atmos["O2"].item() == approx(2.6164412e15) assert atmos["Ar"].item() == approx(5.9933693e13) assert atmos["Total"].item() == approx(1.8571854e-9) assert atmos["N"].item() == approx(9.1038102e12) assert atmos["AnomalousO"].item() == approx(4.503e-14) assert atmos["Tn"].item() == approx(655.79, abs=0.01) assert atmos["Texo"].item() == approx(875.18, abs=0.01) assert atmos.species == [ "He", "O", "N2", "O2", "Ar", "Total", "H", "N", "AnomalousO" ]
def test_forecast(): t = datetime(2023, 3, 31, 12) altkm = 150.0 glat = 65.0 glon = -148.0 atmos = msise00.run(t, altkm, glat, glon) assert atmos["He"].ndim == 4 assert atmos["He"].size == 1 dims = list(atmos.dims) assert ["alt_km", "lat", "lon", "time"] == dims assert atmos["He"].item() == approx(1240641440000.0) assert atmos["O"].item() == approx(3047968100000000.0) assert atmos["N2"].item() == approx(3.597249e16) assert atmos["O2"].item() == approx(7343665540000000.0) assert atmos["Ar"].item() == approx(334703983000000.0) assert atmos["Total"].item() == approx(2.16534546e-09) assert atmos["N"].item() == approx(2576280450000.0) assert atmos["AnomalousO"].item() == approx(8.75042368e-16) assert atmos.species == [ "He", "O", "N2", "O2", "Ar", "Total", "H", "N", "AnomalousO" ] assert atmos["Tn"].item() == approx(671.513, abs=0.01) assert atmos["Texo"].item() == approx(883.342, abs=0.01)
def test_ccmc(): t = datetime(2001, 2, 2, 8, 0, 0) glat = 60.0 glon = -70.0 altkm = 400.0 indices = {"f107s": 163.6666, "f107": 146.7, "Ap": 7} A = np.loadtxt(reffn, skiprows=25) atmos = msise00.run(t, altkm, glat, glon, indices) assert atmos.f107s == approx(163.6666) assert atmos.f107 == approx(146.7) assert atmos.Ap == approx(7) assert A[0] == approx(altkm) assert A[1] == approx(atmos["O"].item() / 1e6, rel=0.05) assert A[2] == approx(atmos["N2"].item() / 1e6, rel=0.3) assert A[3] == approx(atmos["O2"].item() / 1e6, rel=0.35) assert A[7] == approx(atmos["He"].item() / 1e6, rel=0.2) assert A[8] == approx(atmos["Ar"].item() / 1e6, rel=0.6) assert A[9] == approx(atmos["H"].item() / 1e6, rel=0.1) assert A[10] == approx(atmos["N"].item() / 1e6, rel=0.3) assert A[11] == approx(atmos["AnomalousO"].item() / 1e6, rel=0.3) assert A[5] == approx(atmos["Tn"].item(), rel=0.1) assert A[6] == approx(atmos["Texo"].item(), rel=0.1)
def test_one_loc_one_time(altkm, reffn): pytest.importorskip("netCDF4") ref = xarray.open_dataset(R / reffn) try: dat_mod = msise00.run(time, altkm, lat, lon).squeeze() except ConnectionError: pytest.skip("unable to download RecentIndices.txt") xarray.tests.assert_allclose(ref, dat_mod)
def test_multiple_time(): pytest.importorskip("netCDF4") ref = xarray.open_dataset(R / "ref4.nc") lat, lon = msise00.worldgrid.latlonworldgrid(90, 90) try: dat_mod = msise00.run(time, altkm, lat, lon).squeeze() except ConnectionError: pytest.skip("unable to download RecentIndices.txt") xarray.tests.assert_allclose(ref, dat_mod)
def test_one_alt_one_time(): pytest.importorskip("netCDF4") ref = xarray.open_dataset(R / "ref3.nc") lat, lon = msise00.worldgrid.latlonworldgrid(30, 60) indices = {"f107": 79.3, "f107s": 76.6802469, "Ap": 39} try: dat_mod = msise00.run(time, altkm, lat, lon, indices).squeeze() except ConnectionError: pytest.skip("unable to download RecentIndices.txt") xarray.tests.assert_allclose(ref, dat_mod)
def test_one_alt_one_time(): pytest.importorskip("netCDF4") with importlib.resources.path(__package__, "ref3.nc") as fn: ref = xarray.open_dataset(fn) lat, lon = msise00.worldgrid.latlonworldgrid(30, 60) try: dat_mod = msise00.run(time, altkm, lat, lon).squeeze() except ConnectionError: pytest.skip("unable to download RecentIndices.txt") xarray.tests.assert_allclose(ref, dat_mod)
def test_ccmc2(): t = datetime(2018, 5, 17, 21, 0, 0) glat = 55.0 glon = 120.0 altkm = 300.0 indices = {"f107s": 72.6, "f107": 71.5, "Ap": 9.5} atmos = msise00.run(t, altkm, glat, glon, indices) assert 4.874e7 == approx(atmos["N2"].item() / 1e6, rel=0.2) assert 1.622e6 == approx(atmos["O2"].item() / 1e6, rel=0.1) assert 794.1 == approx(atmos["Tn"].item(), rel=0.1) assert 800.0 == approx(atmos["Texo"].item(), rel=0.1)
def test_past(): t = datetime(2013, 3, 31, 12) altkm = 150.0 glat = 65.0 glon = -148.0 try: atmos = msise00.run(t, altkm, glat, glon) except ConnectionError: pytest.skip("unable to download RecentIndices.txt") assert atmos["He"].ndim == 4 assert atmos["He"].size == 1 dims = list(atmos.dims) assert ["alt_km", "lat", "lon", "time"] == dims try: # daily resolution assert atmos["He"].item() == approx(4365665440000.0) assert atmos["O"].item() == approx(9612878760000000.0) assert atmos["N2"].item() == approx(3.15052301e16) assert atmos["O2"].item() == approx(2312921490000000.0) assert atmos["Ar"].item() == approx(71974164400000.0) assert atmos["Total"].item() == approx(1.84757176e-09) assert atmos["N"].item() == approx(9424203680000.0) assert atmos["AnomalousO"].item() == approx(1.17317104e-14) assert atmos["Tn"].item() == approx(682.538, abs=0.01) assert atmos["Texo"].item() == approx(948.350, abs=0.01) except AssertionError: # monthly resolution assert atmos["He"].item() == approx(4200180480000.0) assert atmos["O"].item() == approx(9338048100000000.0) assert atmos["N2"].item() == approx(3.23984781e16) assert atmos["O2"].item() == approx(2413811350000000.0) assert atmos["Ar"].item() == approx(81071685200000.0) assert atmos["Total"].item() == approx(1.88774951e-09) assert atmos["N"].item() == approx(9310465690000.0) assert atmos["AnomalousO"].item() == approx(5.3806201e-15) assert atmos["Tn"].item() == approx(699.021, abs=0.01) assert atmos["Texo"].item() == approx(1000.513, abs=0.01) assert atmos.species == [ "He", "O", "N2", "O2", "Ar", "Total", "H", "N", "AnomalousO" ]
def get_atmos(time, lat, lon, altitude=(0, 140, 1), apindex=35): """ Retrieve atmospheric conditions (temperature and wind) from MSISE-00 and HWM2014 models. """ alt_vector = np.arange(*altitude) Tn = msise00.run(time, altkm=alt_vector, glat=lat, glon=lon).Tn.data.ravel() wind = HWM14(altlim=[alt_vector[0], alt_vector[-1]], altstp=altitude[2], glat=lat, glon=lon, ap=[-1, apindex], ut=time.hour, day=time.julday, year=time.year, verbose=0) W_zonal, W_meridional = np.array([wind.Uwind, wind.Vwind]) return alt_vector, Tn, W_zonal, W_meridional
mOxygen = 2.6567e-26; mNitrogen = 2.3259e-26; mHelium = 6.646477e-27; mArgon = 6.6335e-26; mHydrogen = 1.674e-27; mOxygen2 = mOxygen * 2.; mNitrogen2= mNitrogen * 2.; # Construct altitude array altitudeArr = np.linspace(lowerAlt, upperAlt, int((upperAlt+altitudeStepSize)/altitudeStepSize)); # Call MSIS model atmos = msise00.run(time=time, altkm=altitudeArr, glat=g_lat_lon[0], glon=g_lat_lon[1]) # If program gets any arguments it'll plot the profiles if len(sys.argv) > 1: import matplotlib.pyplot as plt fig = plt.figure(); ax1 = fig.add_subplot(131) for var in atmos.species: if var is not 'Total': atmos[var].plot(y='alt_km', label=var, ax=ax1) plt.xscale('log'); plt.legend(fontsize=8); plt.xlabel('Species number density [m$^{-3}$]') plt.ylabel('Altitude [km]'); plt.title('Number Density Profile') plt.grid();
def main(): p = ArgumentParser( description='calls MSISE-00 from Python, save to NetCDF4 and/or plot') p.add_argument( '-t', '--time', help= 'time: (single time or START STOP (1 hour time step) or list of times)', nargs='+', required=True) p.add_argument( '-a', '--altkm', help='altitude (km). scalar, or (start,stop,step) or list of alts.', type=float, nargs='+', required=True) p.add_argument('-c', '--latlon', help='geodetic latitude/longitude (deg)', metavar=('lat', 'lon'), type=float, nargs=2) p.add_argument('-o', '--odir', help='directory to write plots to') p.add_argument('-w', help='NetCDF4 .nc filename to write') p.add_argument('-gs', help='geographic grid spacing (lat, lon)', nargs=2, type=float, default=(10, 10)) p.add_argument('-q', '--quiet', help='disable plotting', action='store_true') P = p.parse_args() # %% altitude if len(P.altkm) == 1: altkm = P.altkm[0] elif len(P.altkm) == 3: altkm = np.arange(*P.altkm) else: altkm = P.altkm # %% latlon if P.latlon is not None: glat, glon = P.latlon else: glat, glon = latlonworldgrid(*P.gs) # %% run atmos = msise00.run(P.time, altkm, glat, glon) # %% save if P.w: ncfn = Path(P.w).expanduser() print('saving', ncfn) # NOTE: .squeeze() avoids ValueError: unsupported dtype for netCDF4 variable: datetime64[ns] atmos.squeeze().to_netcdf(ncfn) # %% plot if msplots is not None and not P.quiet: msplots.plotgtd(atmos, P.odir) show() else: print('skipped plots')
#!/usr/bin/env python """ Time profile example """ import numpy as np from datetime import datetime, timedelta from matplotlib.pyplot import show import msise00.plots as msplots import msise00 glat = 65.1 glon = -147.5 alt_km = 200 t0 = datetime(2015, 12, 13, 10, 0, 0) t1 = datetime(2015, 12, 14, 10, 0, 0) times = np.arange(t0, t1, timedelta(hours=1)) atmos = msise00.run(times, alt_km, glat, glon) msplots.plotgtd(atmos) show()
#%% altitude 1-D mode if p.latlon is not None: print('entering single location mode') if p.altkm is None: p.altkm = (60., 1000, 5) altkm = np.arange(*p.altkm) glat, glon = p.latlon #%% lat/lon grid mode at constant altitude else: # len(p.altkm)==1: print( 'lat/lon not specified, entering auto whole-world grid mode at first altitude' ) if p.altkm is None: altkm = 200. else: altkm = p.altkm[0] glat, glon = latlonworldgrid() altkm = np.atleast_1d(altkm) print(f'using altitudes from {altkm[0]:.1f} to {altkm[-1]:.1f} km') # %% run atmos = msise00.run(time, altkm, glat, glon) #%% if p.w: ncfn = Path(p.w).expanduser() print('saving', ncfn) atmos.to_netcdf(ncfn) plotgtd(atmos, p.odir) show()