def normalize_rho(orbitfile, lat, lon, alt, rho, base_alt): """ Uses the MSIS empirical model to return the helium and total mass density in an array Arguments: orbitfile: the filename of the DE-2 orbit lat : array of latitudes [deg] long : array of longitudes [deg] alt : array of altitudes above body surface [km] rho : array of unnormalized number density values for helium (1/cm^3) base_alt: the fixed altitude to normalize density value Returns: rho_matrix : a 2Xn matrix of normalized number densities at the fixed "base altitude" and the expected MSIS value densites are first row - i.e. rho_matrix[0:all] MSIS expected values are second row - i.e. rho_matrix[1:all] """ species = whatplot rho_norm = np.zeros(len(rho)) rho_MSIS_fixed, rho_MSIS_vary = np.zeros(len(rho)), np.zeros(len(rho)) ratio = np.zeros(len(rho)) date = make_date(orbitfile) for i in range(0, len(rho)): # MSIS Point objects - pt1 = fixed alt, pt2 = variable alt pt1 = Point(date, lat[i], lon[i], base_alt) pt2 = Point(date, lat[i], lon[i], alt[i]) result1, result2 = pt1.run_msis(), pt2.run_msis( ) # call MSIS for these Point objects rho_MSIS_fixed[i] = result1.nn[species] # particles/cm^3 rho_MSIS_vary[i] = result2.nn[species] ratio[i] = rho_MSIS_fixed[i] / rho_MSIS_vary[i] rho_norm[i] = rho[i] * ratio[i] plt.subplot(211) plt.title(filenames[j]) plt.plot(alt, rho_MSIS_fixed, label='MSIS rho fixed') plt.plot(alt, rho_MSIS_vary, label='MSIS rho vary') plt.plot(alt, rho, label='rho') plt.plot(alt, rho_norm, label='rho norm') plt.legend(loc=1) plt.ylabel(whatplot + ' Density 1/cm^3') plt.ticklabel_format(axis='y', style='sci', scilimits=(0, 0)) plt.grid() plt.subplot(212) plt.plot(alt, ratio) plt.xlabel('Altitude') plt.ylabel(r'Ratio MSIS $\rho(z_0))/ \rho(z)$') plt.minorticks_on() plt.grid() plt.show() rho_matrix = np.array([rho_norm, rho_MSIS_fixed]) return rho_matrix # return both so you can plot
def ne2xy_converter(stn, dt, nan=True, elevation=None): """ ??? """ station_info = STATION_MAP[stn.upper()] lat = station_info.glat lon = station_info.glon point = Point(dt, lat, lon, elevation / 1e3 if elevation else 0) point.run_igrf() dec_deg = point.dec logger.info('using declination angle {:f} (deg) for {}'.format( dec_deg, stn)) dec_rad = math.radians(dec_deg) cos_dec = math.cos(dec_rad) sin_dec = math.sin(dec_rad) def ne2xy(n, e): if n in [88888, 99999] or e in [88888, 99999]: if nan: return NP.nan, NP.nan else: return 88888, 88888 x = cos_dec * n - sin_dec * e y = sin_dec * n + cos_dec * e return x, y return ne2xy
def fun(pos): llh = pos.llh point = Point(dt, llh[0], llh[1], llh[2] / 1e3) point.run_iri() if point.ne < 0: logger.warning('negative IRI Ne detected (h={:.1f} [km])'.format( llh[2] / 1e3)) return 0 else: return point.ne / 1e7
def get_B(pos): """ Use pyglow to get IGRF magnetic field in ECEF coordinates """ lat_lon_h = jcoord.ecef2geodetic(pos[0], pos[1], pos[2]) pt = Point(datetime.datetime(2000, 1, 1, 1, 0), lat_lon_h[0], lat_lon_h[1], lat_lon_h[2] / 1e3) pt.run_igrf() Bxyz = jcoord.enu2ecef(lat_lon_h[0], lat_lon_h[1], lat_lon_h[2], pt.Bx, pt.By, pt.Bz) return (Bxyz)
def pyglowinput( latlonalt=[65.1367, -147.4472, 250.00], dn_list=[datetime(2015, 3, 21, 8, 00), datetime(2015, 3, 21, 20, 00)], z=None): if z is None: z = sp.linspace(50., 1000., 200) dn_diff = sp.diff(dn_list) dn_diff_sec = dn_diff[-1].seconds timelist = sp.array([calendar.timegm(i.timetuple()) for i in dn_list]) time_arr = sp.column_stack((timelist, sp.roll(timelist, -1))) time_arr[-1, -1] = time_arr[-1, 0] + dn_diff_sec v = [] coords = sp.column_stack((sp.zeros((len(z), 2), dtype=z.dtype), z)) all_spec = ['O+', 'NO+', 'O2+', 'H+', 'HE+'] Param_List = sp.zeros((len(z), len(dn_list), len(all_spec), 2)) for idn, dn in enumerate(dn_list): for iz, zcur in enumerate(z): latlonalt[2] = zcur pt = Point(dn, *latlonalt) pt.run_igrf() pt.run_msis() pt.run_iri() # so the zonal pt.u and meriodinal winds pt.v will coorispond to x and y even though they are # supposed to be east west and north south. Pyglow does not seem to have # vertical winds. v.append([pt.u, pt.v, 0]) for is1, ispec in enumerate(all_spec): Param_List[iz, idn, is1, 0] = pt.ni[ispec] * 1e6 Param_List[iz, idn, :, 1] = pt.Ti Param_List[iz, idn, -1, 0] = pt.ne * 1e6 Param_List[iz, idn, -1, 1] = pt.Te Param_sum = Param_List[:, :, :, 0].sum(0).sum(0) spec_keep = Param_sum > 0. species = sp.array(all_spec)[spec_keep[:-1]].tolist() species.append('e-') Param_List[:, :] = Param_List[:, :, spec_keep] Iono_out = IonoContainer(coords, Param_List, times=time_arr, species=species) return Iono_out
def calculate_delay( time, lat, lon, frequency, elevation, ): '''TODO: Docstring ''' if Point is None or gcoord is None: raise ImportError('pyglow must be installed to calculate delay') if not isinstance(time, Time): dn = time else: dn = time.tt.datetime num = 500 alts = np.linspace(0, 4000, num=num) distance = np.linspace(0, 4000, num=num) ne = np.zeros(num) xyz_prev = 0.0 for ai, a in enumerate(alts): llh = coord.az_el_r2geodetic(lat, lon, 0, 180.0, elevation, a * 1e3) pt = Point(dn, llh[0], llh[1], llh[2] / 1e3) pt.run_iri() if pt.ne > 0.0: ne[ai] = pt.ne * 1e6 else: ne[ai] = 0.0 xyz = gcoord.lla2ecef(np.array([lat, lon, a]))[0] if ai == 0: distance[ai] = 0.0 else: distance[ai] = np.sqrt(np.dot(xyz - xyz_prev, xyz - xyz_prev)) + distance[ai - 1] xyz_prev = xyz f_p = 8.98 * np.sqrt(ne) v_g = constants.c * np.sqrt(1 - (f_p / frequency)**2.0) dt2 = integrate.simps(1.0 - 1.0 / (np.sqrt(1 - (f_p / frequency)**2.0)), distance * 1e3) / constants.c return dt2, ne, distance
def get_dec_tenths_arcminute(header, date): """ Return the local magnetic declination angle associated with a sensor at the location given in *header* and *date*. The returned angle is in tenths of arcminutes (there are 360 * 60 * 10 tenths of arcminnutes in one circle). """ point = Point(date, header['Geodetic Latitude'], header['Geodetic Longitude'], header['Elevation']) point.run_igrf() dec_deg = point.dec if 'IAGA CODE' in header: logger.info('using declination angle {:f} (deg) for {}'.format( dec_deg, header['IAGA CODE'])) else: logger.info('using declination angle {:f} (deg)'.format(dec_deg)) return fix_sign(deg2tenths_of_arcminute(dec_deg))
def get_delay(dn=datetime(2016, 3, 23, 00, 00), f=233e6, lat=e3d._tx[0].lat, lon=e3d._tx[0].lon, elevation=30.0, plot=False): np = 500 alts = n.linspace(0, 4000, num=np) distance = n.linspace(0, 4000, num=np) ne = n.zeros(np) xyz_prev = 0.0 for ai, a in enumerate(alts): llh = coord.az_el_r2geodetic(lat, lon, 0, 180.0, elevation, a * 1e3) # print(llh[2]) pt = Point(dn, llh[0], llh[1], llh[2] / 1e3) pt.run_iri() if pt.ne > 0.0: ne[ai] = pt.ne * 1e6 else: ne[ai] = 0.0 xyz = gcoord.lla2ecef(n.array([lat, lon, a]))[0] if ai == 0: distance[ai] = 0.0 else: distance[ai] = n.sqrt(n.dot(xyz - xyz_prev, xyz - xyz_prev)) + distance[ai - 1] xyz_prev = xyz f_p = 8.98 * n.sqrt(ne) v_g = c.c * n.sqrt(1 - (f_p / f)**2.0) dt2 = si.simps(1.0 - 1.0 / (n.sqrt(1 - (f_p / f)**2.0)), distance * 1e3) / c.c if plot: print("ionospheric delay (s)") print(dt2) plt.plot(ne, distance) plt.ylabel("Distance (km)") plt.xlabel("$N_e$ ($m^{-3}$)") plt.show() return (dt2, ne, distance)
lat[k] = float(line.split(delimiter)[i]) elif i == 5: long[k] = float(line.split(delimiter)[i]) elif i == 6: LST[k] = float(line.split(delimiter)[i]) else: continue k += 1 # only increment k once per two lines counter += 1 fread.close() # Get MSIS temperature data if add_MSIS: date = make_date(filenames[j]) for i in range(0, len(temp)): pt = Point(date, lat[i], long[i], alt[i]) result = pt.run_msis() # call MSIS for these Point objects temp_MSIS[i] = result.Tn_msis # plt the data.... print('Done reading files. Plotting...') plt.title('DE2 Orbit 1614 - LT 19.0') plt.scatter(lat, temp, marker='.', label='DE-2') if add_MSIS: plt.scatter(lat, temp_MSIS, marker='.', label='MSIS') plt.ylabel('Neutral Temperature [K]') plt.xlabel('Latitude [deg]') plt.legend() #plt.ylim([850, 1425])
def ray_trace_error( time, lat, lon, frequency, elevation, azimuth, ionosphere=False, error_std=0.05, ): '''TODO: Docstring ''' if Point is None or gcoord is None: raise ImportError('pyglow must be installed to ray trace') if not isinstance(time, Time): dn = time else: dn = time.tt.datetime num = 2000 alts = np.repeat(1e99, num) distance = np.linspace(0, 4000, num=num) ne = np.zeros(num) ne2 = np.zeros(num) dtheta = np.zeros(num) dalt = np.zeros(num) dnex = np.zeros(num) dney = np.zeros(num) dnez = np.zeros(num) xyz_prev = 0.0 dk = np.zeros(num) px = np.zeros(num) py = np.zeros(num) pz = np.zeros(num) t_vec = np.zeros(num) t_i_vec = np.zeros(num) k_vecs = [] # initial direction and position k = frames.azel_to_ecef(lat, lon, 10e3, az, elevation) k0 = k p = frames.geodetic_to_ITRS(lat, lon, 10e3) dh = 4e3 dt = 20e-6 # correlated errors std=1, 100 km correlation length scale_length = 40.0 ne_errors_x = np.convolve( np.repeat(1.0 / np.sqrt(scale_length), scale_length), np.random.randn(10000)) ne_errors_y = np.convolve( np.repeat(1.0 / np.sqrt(scale_length), scale_length), np.random.randn(10000)) ne_errors_z = np.convolve( np.repeat(1.0 / np.sqrt(scale_length), scale_length), np.random.randn(10000)) p_orig = p ray_time = 0.0 v_c = constants.c for ai, a in enumerate(alts): # go forward in time dhp = v_c * dt p = p + k * dhp ray_time += dt print(ray_time * 1e6) t_vec[ai + 1] = dt k_vecs.append(k) dpx = p + np.array([1.0, 0.0, 0.0]) * dh dpy = p + np.array([0.0, 1.0, 0.0]) * dh dpz = p + np.array([0.0, 0.0, 1.0]) * dh llh = frames.ITRS_to_geodetic(p[0], p[1], p[2]) if llh[2] / 1e3 > 2100: break alts[ai] = llh[2] / 1e3 pt = Point(dn, llh[0], llh[1], llh[2] / 1e3) pt.run_iri() if pt.ne > 0.0: ne[ai] = pt.ne * (1.0 + error_std * ne_errors_x[ai]) * 1e6 if ionosphere: f0 = 8.98 * np.sqrt(ne[ai]) f_p = 8.98 * np.sqrt(ne[ai]) # update group velocity v_c = constants.c * np.sqrt(1.0 - (f0 / frequency)**2.0) else: ne[ai] = 0.0 llh = frames.ITRS_to_geodetic(dpx[0], dpx[1], dpx[2]) pt = Point(dn, llh[0], llh[1], llh[2] / 1e3) pt.run_iri() if pt.ne > 0.0: dnex[ai] = (ne[ai] - pt.ne * (1.0 + error_std * ne_errors_x[ai]) * 1e6) / dh else: dnex[ai] = 0.0 llh = frames.ITRS_to_geodetic(dpy[0], dpy[1], dpy[2]) pt = Point(dn, llh[0], llh[1], llh[2] / 1e3) pt.run_iri() if pt.ne > 0.0: dney[ai] = (ne[ai] - pt.ne * (1.0 + error_std * ne_errors_x[ai]) * 1e6) / dh else: dney[ai] = 0.0 llh = frames.ITRS_to_geodetic(dpz[0], dpz[1], dpz[2]) pt = Point(dn, llh[0], llh[1], llh[2] / 1e3) pt.run_iri() if pt.ne > 0.0: dnez[ai] = (ne[ai] - pt.ne * (1.0 + error_std * ne_errors_x[ai]) * 1e6) / dh else: dnez[ai] = 0.0 grad = np.array([dnex[ai], dney[ai], dnez[ai]]) px[ai] = p[0] py[ai] = p[1] pz[ai] = p[2] dk[ai] = np.arccos( np.dot(k0, k) / (np.sqrt(np.dot(k0, k0)) * np.sqrt(np.dot(k, k)))) # no bending if gradient too small if np.dot(grad, grad) > 100.0 and ionosphere: grad1 = grad / np.sqrt(np.dot(grad, grad)) p2 = p + k * dh llh = frames.ITRS_to_geodetic(p2[0], p2[1], p2[2]) pt = Point(dn, llh[0], llh[1], llh[2] / 1e3) pt.run_iri() if pt.ne > 0.0: ne2 = pt.ne * (1.0 + error_std * ne_errors_x[ai]) * 1e6 else: ne2 = 0.0 f0 = 8.98 * np.sqrt(ne[ai]) n0 = np.sqrt(1.0 - (f0 / frequency)**2.0) f1 = 8.98 * np.sqrt(ne2) n1 = np.sqrt(1.0 - (f1 / frequency)**2.0) theta0 = np.arccos( np.dot(grad, k) / (np.sqrt(np.dot(grad, grad)) * np.sqrt(np.dot(k, k)))) # angle cannot be over 90 if theta0 > np.pi / 2.0: theta0 = np.pi - theta0 sin_theta_1 = (n0 / n1) * np.sin(theta0) dtheta[ai] = 180.0 * np.arcsin( sin_theta_1) / np.pi - 180.0 * theta0 / np.pi # print("n0/n1 %1.10f theta0 %1.2f theta1-theta0 %1.10f"%(n0/n1,180.0*theta0/np.pi,dtheta[ai])) cos_theta_1 = np.sqrt(1.0 - sin_theta_1**2.0) k_ref = (n0 / n1) * k + ( (n0 / n1) * np.cos(theta0) - cos_theta_1) * grad1 # normalize k_ref / np.sqrt(np.dot(k_ref, k_ref)) k = k_ref angle = np.arccos( np.dot(grad, k) / np.sqrt(np.dot(grad, grad)) * np.sqrt(np.dot(k, k))) return t_vec, px, py, pz, alts, ne, k_vecs
def plot_indices(d1, d2, fig=None, style='display', bar_lw=0.2, dst_lw=1.75, edgecolor=(0.1, 0.1, 0.1), title_dt_format='%Y-%m-%d %H:%M', stats=False): """ """ # gather Kp kp = [] kp_dt = [] for dt in PD.date_range(d1, d2, freq='3H'): point = Point(dt, 0, 0, 0) kp.append(point.kp) kp_dt.append(dt) # gather Dst dst = [] dst_dt = [] for dt in PD.date_range(d1, d2, freq='1H'): point = Point(dt, 0, 0, 0) dst.append(point.dst) dst_dt.append(dt) # create plot N_days = (dst_dt[-1] - dst_dt[0]).total_seconds() / 60 / 60 / 24 if fig is None: fig = PL.figure(figsize=(11 * N_days / 6, 5)) kp_colors, kp_hatch = STYLE_MAP[style] # Kp subplot ax1 = PL.subplot(111) left = NP.array(kp_dt) - timedelta(hours=1.5) width = 3 / 24 height = kp color = [kp_colors[int(math.floor(x))] for x in kp] hatch = [kp_hatch[int(math.floor(x))] if kp_hatch else None for x in kp] left = [x.to_pydatetime() for x in left] bars = PL.bar(left, height, width=width, color=color, linewidth=bar_lw, edgecolor=[edgecolor] * len(left)) for bar, hatch_i in zip(bars, hatch): bar.set_hatch(hatch_i) ax1.xaxis_date() PL.ylim(0, 9) PL.xlabel('UT') PL.ylabel('3-hour Kp index') # Dst subplot ax2 = ax1.twinx() PL.plot_date(dst_dt, dst, lw=dst_lw, marker=None, ls='-') PL.ylabel('Hourly DST [nT]') d1_str = datetime.strftime(dst_dt[0], title_dt_format) d2_str = datetime.strftime(dst_dt[-1], title_dt_format) title = 'GFZ $K_p$ and Dst Indices, {} to {}'.format(d1_str, d2_str) PL.title(title) if stats: index_stats = IndexStats(Stats(*kp), Stats(*dst)) return index_stats, fig, ax1, ax2 else: return fig, ax1, ax2
import matplotlib.pyplot as plt import numpy as np month = np.array([1,4,7,10])#specify what months to pull data from year = range(1981, 2002, 1) He = np.zeros(len(month)*len(year)) Oxy = np.zeros(len(He)) F107 = np.zeros(len(He)) lat = 40. lon = -80. n = 0 for x in year: for y in month: dn = datetime(x,y,1,12,0) pt = Point(dn, lat, lon, 400) result = pt.run_msis() He[n] = result.nn['HE'] Oxy[n] = result.nn['O'] F107[n] = result.f107 n = n+1 He_avg = np.sum(He)/len(He)#Find mean value He_delta = He/He_avg*100#Find percent change Oxy_avg = np.sum(Oxy)/len(Oxy) Oxy_delta = Oxy/Oxy_avg*100 cycle = np.linspace(year[0], year[-1], len(He)) fig = plt.figure() ax = plt.subplot(111) ax.plot(cycle, He_delta, label='Helium')
# To begin, lets first create a Point object from Jan 1st, 2000. #-------------- Variables to change --------------- date = datetime(2000, 1, 1, 0, 0) # (yr, month, day, hour, minute) - refer to datetime module online latitude = 45 longitude = 90 altitude = 400 #-------------------------------------------------- # for now we will not deal with inputting our out geophys indices, so we let the Point obj do this for us. # Now make the Point object! new_pt = Point(date, latitude, longitude, altitude) # from this new_pt Point object, we can run MSIS (or anything else in the Point class). result = new_pt.run_msis() # result now contains the neutral temp, number densities (given in the run_msis fuction) # and total number density for the specific variables given above ''' check them out... which neutral species do you what to look at? Can be: HE, O, N2, O2, AR, H, N, O_anomalous, or rho (total number density) Or: Tn_msis (neutral temperature [K]) '''
''' from pyglow.pyglow import Point from datetime import datetime import matplotlib.pyplot as plt import numpy as np lat = 0 # Geographic Latitude alt = 590 # Altitude lons = np.arange(0, 360) # Longitudes dn = datetime(2004, 9, 21, 1, 0) # 1 UT Te = np.empty(len(lons)) for i, lon in enumerate(lons): pt = Point(dn, lat, lon, alt) pt.run_iri() Te[i] = pt.Te plt.plot(lons, Te, 'k') plt.title('Electron Temperatures') plt.xlabel('Longitude, Degree') plt.ylabel('Te, K') plt.ylim(500, 3000) plt.xlim(0, 400) plt.xticks([0, 100, 200, 300, 400]) plt.grid() plt.show()
return x_star if __name__ == '__main__': from pyglow.pyglow import Point N = 200 alt = NP.linspace(100, 1500, N) dt = datetime(2000, 1, 1) lat = 0 lon = 0 iri_ne = [] for alt_i in alt: point = Point(dt, lat, lon, alt_i) point.run_iri() iri_ne.append(point.ne) Nm_star, Hm_star, H_O_star = chapman_fit(alt, iri_ne, verbose=True) chapman_ne = [chapman(z, Nm_star, Hm_star, H_O_star) for z in alt] fig = PL.figure(figsize=(6, 10)) PL.plot(iri_ne, alt, color='b', label='IRI') PL.plot(chapman_ne, alt, color='g', label='Chapman fit') PL.legend() PL.xlabel('Electron density [cm$^{-3}$]') PL.ylabel('Height [km]') PL.ticklabel_format(style='sci', axis='x', scilimits=(0, 0)) PL.axis('tight')
def add_msis(inst, glat_label='glat', glong_label='glong', alt_label='alt'): """ Uses MSIS model to obtain thermospheric values. Uses pyglow module to run MSIS. Configured to use actual solar parameters to run model. Example ------- # function added velow modifies the inst object upon every inst.load call inst.custom.add(add_msis, 'modify', glat_label='custom_label') Parameters ---------- inst : pysat.Instrument Designed with pysat_sgp4 in mind glat_label : string label used in inst to identify WGS84 geodetic latitude (degrees) glong_label : string label used in inst to identify WGS84 geodetic longitude (degrees) alt_label : string label used in inst to identify WGS84 geodetic altitude (km, height above surface) Returns ------- inst Input pysat.Instrument object modified to include MSIS values winds. 'Nn' total neutral density particles/cm^3 'Nn_N' Nitrogen number density (particles/cm^3) 'Nn_N2' N2 number density (particles/cm^3) 'Nn_O' Oxygen number density (particles/cm^3) 'Nn_O2' O2 number density (particles/cm^3) 'Tn_msis' Temperature from MSIS (Kelvin) """ import pyglow from pyglow.pyglow import Point msis_params = [] # print 'IRI Simulations' for time, lat, lon, alt in zip(inst.data.index, inst[glat_label], inst[glong_label], inst[alt_label]): pt = Point(time, lat, lon, alt) pt.run_msis() msis = {} total = 0 for key in pt.nn.keys(): total += pt.nn[key] msis['Nn'] = total msis['Nn_N'] = pt.nn['N'] msis['Nn_N2'] = pt.nn['N2'] msis['Nn_O'] = pt.nn['O'] msis['Nn_O2'] = pt.nn['O2'] msis['Tn_msis'] = pt.Tn_msis msis_params.append(msis) # print 'Complete.' msis = pds.DataFrame(msis_params) msis.index = inst.data.index inst[msis.keys()] = msis # metadata inst.meta['Nn'] = { 'units': 'cm^-3', 'desc': 'Total neutral number particle density from MSIS.' } inst.meta['Nn_N'] = { 'units': 'cm^-3', 'desc': 'Total nitrogen number particle density from MSIS.' } inst.meta['Nn_N2'] = { 'units': 'cm^-3', 'desc': 'Total N2 number particle density from MSIS.' } inst.meta['Nn_O'] = { 'units': 'cm^-3', 'desc': 'Total oxygen number particle density from MSIS.' } inst.meta['Nn_O2'] = { 'units': 'cm^-3', 'desc': 'Total O2 number particle density from MSIS.' } inst.meta['Tn_msis'] = { 'units': 'K', 'desc': 'Neutral temperature from MSIS.' } return
def add_iri_thermal_plasma(inst, glat_label='glat', glong_label='glong', alt_label='alt'): """ Uses IRI (International Reference Ionosphere) model to simulate an ionosphere. Uses pyglow module to run IRI. Configured to use actual solar parameters to run model. Example ------- # function added velow modifies the inst object upon every inst.load call inst.custom.add(add_iri_thermal_plasma, 'modify', glat_label='custom_label') Parameters ---------- inst : pysat.Instrument Designed with pysat_sgp4 in mind glat_label : string label used in inst to identify WGS84 geodetic latitude (degrees) glong_label : string label used in inst to identify WGS84 geodetic longitude (degrees) alt_label : string label used in inst to identify WGS84 geodetic altitude (km, height above surface) Returns ------- inst Input pysat.Instrument object modified to include thermal plasma parameters. 'ion_temp' for ion temperature in Kelvin 'e_temp' for electron temperature in Kelvin 'ion_dens' for the total ion density (O+ and H+) 'frac_dens_o' for the fraction of total density that is O+ 'frac_dens_h' for the fraction of total density that is H+ """ import pyglow from pyglow.pyglow import Point iri_params = [] # print 'IRI Simulations' for time, lat, lon, alt in zip(inst.data.index, inst[glat_label], inst[glong_label], inst[alt_label]): # Point class is instantiated. Its parameters are a function of time and spatial location pt = Point(time, lat, lon, alt) pt.run_iri() iri = {} # After the model is run, its members like Ti, ni[O+], etc. can be accessed iri['ion_temp'] = pt.Ti iri['e_temp'] = pt.Te iri['ion_dens'] = pt.ni['O+'] + pt.ni['H+'] + pt.ni[ 'HE+'] #pt.ne - pt.ni['NO+'] - pt.ni['O2+'] - pt.ni['HE+'] iri['frac_dens_o'] = pt.ni['O+'] / iri['ion_dens'] iri['frac_dens_h'] = pt.ni['H+'] / iri['ion_dens'] iri['frac_dens_he'] = pt.ni['HE+'] / iri['ion_dens'] iri_params.append(iri) # print 'Complete.' iri = pds.DataFrame(iri_params) iri.index = inst.data.index inst[iri.keys()] = iri inst.meta['ion_temp'] = {'units': 'Kelvin', 'long_name': 'Ion Temperature'} inst.meta['ion_dens'] = { 'units': 'N/cc', 'long_name': 'Ion Density', 'desc': 'Total ion density including O+ and H+ from IRI model run.' } inst.meta['frac_dens_o'] = { 'units': '', 'long_name': 'Fractional O+ Density' } inst.meta['frac_dens_h'] = { 'units': '', 'long_name': 'Fractional H+ Density' }
def ray_trace_error(dn=datetime(2016, 6, 21, 12, 00), f=233e6, lat=e3d._tx[0].lat, lon=e3d._tx[0].lon, elevation=30.0, az=180.0, fpref="", ionosphere=False, error_std=0.05, plot=False): np = 2000 alts = n.repeat(1e99, np) distance = n.linspace(0, 4000, num=np) ne = n.zeros(np) ne2 = n.zeros(np) dtheta = n.zeros(np) dalt = n.zeros(np) dnex = n.zeros(np) dney = n.zeros(np) dnez = n.zeros(np) xyz_prev = 0.0 dk = n.zeros(np) px = n.zeros(np) py = n.zeros(np) pz = n.zeros(np) t_vec = n.zeros(np) t_i_vec = n.zeros(np) k_vecs = [] # initial direction and position k = coord.azel_ecef(lat, lon, 10e3, az, elevation) k0 = k p = coord.geodetic2ecef(lat, lon, 10e3) dh = 4e3 dt = 20e-6 # correlated errors std=1, 100 km correlation length scale_length = 40.0 ne_errors_x = n.convolve( n.repeat(1.0 / n.sqrt(scale_length), scale_length), n.random.randn(10000)) ne_errors_y = n.convolve( n.repeat(1.0 / n.sqrt(scale_length), scale_length), n.random.randn(10000)) ne_errors_z = n.convolve( n.repeat(1.0 / n.sqrt(scale_length), scale_length), n.random.randn(10000)) p_orig = p ray_time = 0.0 v_c = c.c for ai, a in enumerate(alts): # go forward in time dhp = v_c * dt p = p + k * dhp ray_time += dt print(ray_time * 1e6) t_vec[ai + 1] = dt k_vecs.append(k) dpx = p + n.array([1.0, 0.0, 0.0]) * dh dpy = p + n.array([0.0, 1.0, 0.0]) * dh dpz = p + n.array([0.0, 0.0, 1.0]) * dh llh = coord.ecef2geodetic(p[0], p[1], p[2]) if llh[2] / 1e3 > 2100: break alts[ai] = llh[2] / 1e3 pt = Point(dn, llh[0], llh[1], llh[2] / 1e3) pt.run_iri() if pt.ne > 0.0: ne[ai] = pt.ne * (1.0 + error_std * ne_errors_x[ai]) * 1e6 if ionosphere: f0 = 8.98 * n.sqrt(ne[ai]) f_p = 8.98 * n.sqrt(ne[ai]) # update group velocity v_c = c.c * n.sqrt(1.0 - (f0 / f)**2.0) else: ne[ai] = 0.0 llh = coord.ecef2geodetic(dpx[0], dpx[1], dpx[2]) pt = Point(dn, llh[0], llh[1], llh[2] / 1e3) pt.run_iri() if pt.ne > 0.0: dnex[ai] = (ne[ai] - pt.ne * (1.0 + error_std * ne_errors_x[ai]) * 1e6) / dh else: dnex[ai] = 0.0 llh = coord.ecef2geodetic(dpy[0], dpy[1], dpy[2]) pt = Point(dn, llh[0], llh[1], llh[2] / 1e3) pt.run_iri() if pt.ne > 0.0: dney[ai] = (ne[ai] - pt.ne * (1.0 + error_std * ne_errors_x[ai]) * 1e6) / dh else: dney[ai] = 0.0 llh = coord.ecef2geodetic(dpz[0], dpz[1], dpz[2]) pt = Point(dn, llh[0], llh[1], llh[2] / 1e3) pt.run_iri() if pt.ne > 0.0: dnez[ai] = (ne[ai] - pt.ne * (1.0 + error_std * ne_errors_x[ai]) * 1e6) / dh else: dnez[ai] = 0.0 grad = n.array([dnex[ai], dney[ai], dnez[ai]]) px[ai] = p[0] py[ai] = p[1] pz[ai] = p[2] dk[ai] = n.arccos( n.dot(k0, k) / (n.sqrt(n.dot(k0, k0)) * n.sqrt(n.dot(k, k)))) # no bending if gradient too small if n.dot(grad, grad) > 100.0 and ionosphere: grad1 = grad / n.sqrt(n.dot(grad, grad)) p2 = p + k * dh llh = coord.ecef2geodetic(p2[0], p2[1], p2[2]) pt = Point(dn, llh[0], llh[1], llh[2] / 1e3) pt.run_iri() if pt.ne > 0.0: ne2 = pt.ne * (1.0 + error_std * ne_errors_x[ai]) * 1e6 else: ne2 = 0.0 f0 = 8.98 * n.sqrt(ne[ai]) n0 = n.sqrt(1.0 - (f0 / f)**2.0) f1 = 8.98 * n.sqrt(ne2) n1 = n.sqrt(1.0 - (f1 / f)**2.0) theta0 = n.arccos( n.dot(grad, k) / (n.sqrt(n.dot(grad, grad)) * n.sqrt(n.dot(k, k)))) # angle cannot be over 90 if theta0 > n.pi / 2.0: theta0 = n.pi - theta0 sin_theta_1 = (n0 / n1) * n.sin(theta0) dtheta[ai] = 180.0 * n.arcsin( sin_theta_1) / n.pi - 180.0 * theta0 / n.pi # print("n0/n1 %1.10f theta0 %1.2f theta1-theta0 %1.10f"%(n0/n1,180.0*theta0/n.pi,dtheta[ai])) cos_theta_1 = n.sqrt(1.0 - sin_theta_1**2.0) k_ref = (n0 / n1) * k + ( (n0 / n1) * n.cos(theta0) - cos_theta_1) * grad1 # normalize k_ref / n.sqrt(n.dot(k_ref, k_ref)) k = k_ref angle = n.arccos( n.dot(grad, k) / n.sqrt(n.dot(grad, grad)) * n.sqrt(n.dot(k, k))) return (t_vec, px, py, pz, alts, ne, k_vecs)
T2 = np.zeros(len(m)) M2 = np.zeros(len(m)) Kn1 = np.zeros(len(m)) #Knudsen number for characteristic length Kn2 = np.zeros(len(m)) Kn1At = np.zeros(len(m)) #Atmospheric knudsen number Kn2At = np.zeros(len(m)) k = 1.3806 * 10**(-23) #Boltzmann's constant g0 = 9.81 #m/s^2 R = 6373 #Radius of earth in km Av = 6.022141 * 10**23 #Avogadro's Constant n = 0 rho = np.zeros(len(m)) #Iterate through altitudes in range m for x in m: pt = Point(dn, lat, lon, x) pt2 = Point(dn2, lat, lon, x) result = pt.run_msis() result2 = pt2.run_msis() #Knudsen number estimate n_dens_tot = result.nn['HE']+result.nn['N2']+result.nn['O2'] \ +result.nn['AR']+result.nn['H']+result.nn['O']+result.nn['N']# number density per cm^3 d_avg = (result.nn['HE']/n_dens_tot*260+result.nn['N2']/n_dens_tot*364\ +result.nn['O2']/n_dens_tot*346+result.nn['AR']/n_dens_tot*340)\ *10**(-12)+(result.nn['H']+result.nn['O']+result.nn['N'])/n_dens_tot*5.046*10**(-10)# average kinetic diameter of # molecules in atmosphere. Note H and O are ignored due to no data on # their kinetic diameters and the breakdown of the model with ions # (hard sphere collisions of molecules) lam = 1 / (math.sqrt(2) * math.pi * d_avg**2 * n_dens_tot * 10**(6))
def ray_trace(dn=datetime(2016, 6, 21, 12, 00), f=233e6, lat=e3d._tx[0].lat, lon=e3d._tx[0].lon, elevation=30.0, az=180.0, fpref="", plot=False): np = 1000 alts = n.linspace(0, 4000, num=np) distance = n.linspace(0, 4000, num=np) ne = n.zeros(np) ne2 = n.zeros(np) dnex = n.zeros(np) dtheta = n.zeros(np) dalt = n.zeros(np) dney = n.zeros(np) dnez = n.zeros(np) xyz_prev = 0.0 px = n.zeros(np) dk = n.zeros(np) py = n.zeros(np) pz = n.zeros(np) p0x = n.zeros(np) p0y = n.zeros(np) p0z = n.zeros(np) # initial direction and position k = coord.azel_ecef(lat, lon, 10e3, az, elevation) k0 = k p = coord.geodetic2ecef(lat, lon, 10e3) pe = coord.geodetic2ecef(lat, lon, 10e3) p0 = coord.geodetic2ecef(lat, lon, 10e3) dh = 4e3 vg = 1.0 p_orig = p ray_time = 0.0 for ai, a in enumerate(alts): p = p + k * dh * vg p0 = p0 + k0 * dh ray_time += dh / c.c dpx = p + n.array([1.0, 0.0, 0.0]) * dh dpy = p + n.array([0.0, 1.0, 0.0]) * dh dpz = p + n.array([0.0, 0.0, 1.0]) * dh llh = coord.ecef2geodetic(p[0], p[1], p[2]) llh_1 = coord.ecef2geodetic(p0[0], p0[1], p0[2]) dalt[ai] = llh_1[2] - llh[2] if llh[2] / 1e3 > 1900: break alts[ai] = llh[2] / 1e3 pt = Point(dn, llh[0], llh[1], llh[2] / 1e3) pt.run_iri() if pt.ne > 0.0: ne[ai] = pt.ne * 1e6 f_p = 8.98 * n.sqrt(ne[ai]) v_g = n.sqrt(1.0 - (f_p / f)**2.0) else: ne[ai] = 0.0 llh = coord.ecef2geodetic(dpx[0], dpx[1], dpx[2]) pt = Point(dn, llh[0], llh[1], llh[2] / 1e3) pt.run_iri() if pt.ne > 0.0: dnex[ai] = (ne[ai] - pt.ne * 1e6) / dh else: dnex[ai] = 0.0 llh = coord.ecef2geodetic(dpy[0], dpy[1], dpy[2]) pt = Point(dn, llh[0], llh[1], llh[2] / 1e3) pt.run_iri() if pt.ne > 0.0: dney[ai] = (ne[ai] - pt.ne * 1e6) / dh else: dney[ai] = 0.0 llh = coord.ecef2geodetic(dpz[0], dpz[1], dpz[2]) pt = Point(dn, llh[0], llh[1], llh[2] / 1e3) pt.run_iri() if pt.ne > 0.0: dnez[ai] = (ne[ai] - pt.ne * 1e6) / dh else: dnez[ai] = 0.0 grad = n.array([dnex[ai], dney[ai], dnez[ai]]) px[ai] = p[0] py[ai] = p[1] pz[ai] = p[2] p0x[ai] = p0[0] p0y[ai] = p0[1] p0z[ai] = p0[2] # print(ai) dk[ai] = n.arccos( n.dot(k0, k) / (n.sqrt(n.dot(k0, k0)) * n.sqrt(n.dot(k, k)))) # no bending if gradient too small if n.dot(grad, grad) > 100.0: grad1 = grad / n.sqrt(n.dot(grad, grad)) p2 = p + k * dh llh = coord.ecef2geodetic(p2[0], p2[1], p2[2]) pt = Point(dn, llh[0], llh[1], llh[2] / 1e3) pt.run_iri() if pt.ne > 0.0: ne2 = pt.ne * 1e6 else: ne2 = 0.0 f0 = 8.98 * n.sqrt(ne[ai]) n0 = n.sqrt(1.0 - (f0 / f)**2.0) f1 = 8.98 * n.sqrt(ne2) n1 = n.sqrt(1.0 - (f1 / f)**2.0) theta0 = n.arccos( n.dot(grad, k) / (n.sqrt(n.dot(grad, grad)) * n.sqrt(n.dot(k, k)))) # angle cannot be over 90 if theta0 > n.pi / 2.0: theta0 = n.pi - theta0 sin_theta_1 = (n0 / n1) * n.sin(theta0) dtheta[ai] = 180.0 * n.arcsin( sin_theta_1) / n.pi - 180.0 * theta0 / n.pi # print("n0/n1 %1.10f theta0 %1.2f theta1-theta0 %1.10f"%(n0/n1,180.0*theta0/n.pi,dtheta[ai])) cos_theta_1 = n.sqrt(1.0 - sin_theta_1**2.0) k_ref = (n0 / n1) * k + ( (n0 / n1) * n.cos(theta0) - cos_theta_1) * grad1 # normalize k_ref / n.sqrt(n.dot(k_ref, k_ref)) k = k_ref angle = n.arccos( n.dot(grad, k) / n.sqrt(n.dot(grad, grad)) * n.sqrt(n.dot(k, k))) los_time = n.sqrt(n.dot(p_orig - p, p_orig - p)) / c.c excess_ionospheric_delay = ray_time - los_time print("Excess propagation time %1.20f mus" % ((1e6 * (ray_time - los_time)))) theta = n.arccos( n.dot(k0, k) / (n.sqrt(n.dot(k0, k0)) * n.sqrt(n.dot(k, k)))) theta_p = n.arccos( n.dot(p0, p) / (n.sqrt(n.dot(p0, p0)) * n.sqrt(n.dot(p, p)))) llh0 = coord.ecef2geodetic(px[ai - 2], py[ai - 2], pz[ai - 2]) llh1 = coord.ecef2geodetic(p0x[ai - 2], p0y[ai - 2], p0z[ai - 2]) print("d_coord") print(llh0 - llh1) if plot: print(p0 - p) print(180.0 * theta_p / n.pi) fig = plt.figure(figsize=(14, 8)) plt.clf() plt.subplot(131) plt.title("Elevation=%1.0f" % (elevation)) plt.plot(n.sqrt((p0x - px)**2.0 + (p0y - py)**2.0 + (p0z - pz)**2.0), alts, label="Total error") plt.plot(dalt, alts, label="Altitude error") plt.ylim([0, 1900]) # plt.xlim([-50,800.0]) plt.grid() plt.legend() plt.xlabel("Position error (m)") plt.ylabel("Altitude km") plt.subplot(132) plt.plot(dtheta * 1e6, alts) # plt.plot(1e6*180.0*dk/n.pi,alts) plt.xlabel("Ray-bending ($\mu$deg/km)") plt.ylabel("Altitude km") plt.title("Total error=%1.2g (deg)" % (180.0 * theta_p / n.pi)) plt.ylim([0, 1900]) plt.subplot(133) plt.plot(ne, alts) plt.xlabel("$N_{\mathrm{e}}$ ($\mathrm{m}^{-3}$)") plt.ylabel("Altitude km") plt.ylim([0, 1900]) # ax.plot(px,py,pz) plt.tight_layout() plt.savefig("ref-%s-%d-%d.png" % (fpref, f / 1e6, elevation)) plt.close() return (p0, p, 180.0 * theta_p / n.pi, excess_ionospheric_delay)
def ray_trace( time, lat, lon, frequency, elevation, azimuth, ): '''TODO: Docstring ''' if Point is None or gcoord is None: raise ImportError('pyglow must be installed to ray trace') if not isinstance(time, Time): dn = time else: dn = time.tt.datetime num = 1000 alts = np.linspace(0, 4000, num=num) distance = np.linspace(0, 4000, num=num) ne = np.zeros(num) ne2 = np.zeros(num) dnex = np.zeros(num) dtheta = np.zeros(num) dalt = np.zeros(num) dney = np.zeros(num) dnez = np.zeros(num) xyz_prev = 0.0 px = np.zeros(num) dk = np.zeros(num) py = np.zeros(num) pz = np.zeros(num) p0x = np.zeros(num) p0y = np.zeros(num) p0z = np.zeros(num) # initial direction and position k = frames.azel_to_ecef(lat, lon, 10e3, azimuth, elevation) k0 = k p = frames.geodetic_to_ITRS(lat, lon, 10e3) pe = frames.geodetic_to_ITRS(lat, lon, 10e3) p0 = frames.geodetic_to_ITRS(lat, lon, 10e3) dh = 4e3 vg = 1.0 p_orig = p ray_time = 0.0 for ai, a in enumerate(alts): p = p + k * dh * vg p0 = p0 + k0 * dh ray_time += dh / constants.c dpx = p + np.array([1.0, 0.0, 0.0]) * dh dpy = p + np.array([0.0, 1.0, 0.0]) * dh dpz = p + np.array([0.0, 0.0, 1.0]) * dh llh = frames.ITRS_to_geodetic(p[0], p[1], p[2]) llh_1 = frames.ITRS_to_geodetic(p0[0], p0[1], p0[2]) dalt[ai] = llh_1[2] - llh[2] if llh[2] / 1e3 > 1900: break alts[ai] = llh[2] / 1e3 pt = Point(dn, llh[0], llh[1], llh[2] / 1e3) pt.run_iri() if pt.ne > 0.0: ne[ai] = pt.ne * 1e6 f_p = 8.98 * np.sqrt(ne[ai]) v_g = np.sqrt(1.0 - (f_p / frequency)**2.0) else: ne[ai] = 0.0 llh = frames.ITRS_to_geodetic(dpx[0], dpx[1], dpx[2]) pt = Point(dn, llh[0], llh[1], llh[2] / 1e3) pt.run_iri() if pt.ne > 0.0: dnex[ai] = (ne[ai] - pt.ne * 1e6) / dh else: dnex[ai] = 0.0 llh = frames.ITRS_to_geodetic(dpy[0], dpy[1], dpy[2]) pt = Point(dn, llh[0], llh[1], llh[2] / 1e3) pt.run_iri() if pt.ne > 0.0: dney[ai] = (ne[ai] - pt.ne * 1e6) / dh else: dney[ai] = 0.0 llh = frames.ITRS_to_geodetic(dpz[0], dpz[1], dpz[2]) pt = Point(dn, llh[0], llh[1], llh[2] / 1e3) pt.run_iri() if pt.ne > 0.0: dnez[ai] = (ne[ai] - pt.ne * 1e6) / dh else: dnez[ai] = 0.0 grad = np.array([dnex[ai], dney[ai], dnez[ai]]) px[ai] = p[0] py[ai] = p[1] pz[ai] = p[2] p0x[ai] = p0[0] p0y[ai] = p0[1] p0z[ai] = p0[2] dk[ai] = np.arccos( np.dot(k0, k) / (np.sqrt(np.dot(k0, k0)) * np.sqrt(np.dot(k, k)))) # no bending if gradient too small if np.dot(grad, grad) > 100.0: grad1 = grad / np.sqrt(np.dot(grad, grad)) p2 = p + k * dh llh = frames.ITRS_to_geodetic(p2[0], p2[1], p2[2]) pt = Point(dn, llh[0], llh[1], llh[2] / 1e3) pt.run_iri() if pt.ne > 0.0: ne2 = pt.ne * 1e6 else: ne2 = 0.0 f0 = 8.98 * np.sqrt(ne[ai]) n0 = np.sqrt(1.0 - (f0 / frequency)**2.0) f1 = 8.98 * np.sqrt(ne2) n1 = np.sqrt(1.0 - (f1 / frequency)**2.0) theta0 = np.arccos( np.dot(grad, k) / (np.sqrt(np.dot(grad, grad)) * np.sqrt(np.dot(k, k)))) # angle cannot be over 90 if theta0 > np.pi / 2.0: theta0 = np.pi - theta0 sin_theta_1 = (n0 / n1) * np.sin(theta0) dtheta[ai] = 180.0 * np.arcsin( sin_theta_1) / np.pi - 180.0 * theta0 / np.pi #print("n0/n1 %1.10f theta0 %1.2f theta1-theta0 %1.10f"%(n0/n1,180.0*theta0/np.pi,dtheta[ai])) cos_theta_1 = np.sqrt(1.0 - sin_theta_1**2.0) k_ref = (n0 / n1) * k + ( (n0 / n1) * np.cos(theta0) - cos_theta_1) * grad1 # normalize k_ref / np.sqrt(np.dot(k_ref, k_ref)) k = k_ref angle = np.arccos( np.dot(grad, k) / np.sqrt(np.dot(grad, grad)) * np.sqrt(np.dot(k, k))) los_time = np.sqrt(np.dot(p_orig - p, p_orig - p)) / constants.c excess_ionospheric_delay = ray_time - los_time # print("Excess propagation time %1.20f mus"%((1e6*(ray_time-los_time)))) theta = np.arccos( np.dot(k0, k) / (np.sqrt(np.dot(k0, k0)) * np.sqrt(np.dot(k, k)))) theta_p = np.arccos( np.dot(p0, p) / (np.sqrt(np.dot(p0, p0)) * np.sqrt(np.dot(p, p)))) llh0 = frames.ITRS_to_geodetic(px[ai - 2], py[ai - 2], pz[ai - 2]) llh1 = frames.ITRS_to_geodetic(p0x[ai - 2], p0y[ai - 2], p0z[ai - 2]) # print("d_coord") # print(llh0-llh1) ret = dict( px=px, py=py, pz=pz, p0x=p0x, p0y=p0y, p0z=p0z, ray_bending=dtheta, electron_density=ne, altitudes=alts, altitude_errors=dalt, excess_ionospheric_delay=excess_ionospheric_delay, total_angle_error=180.0 * theta_p / np.pi, p_end=p, p0_end=p0, ) return ret
def add_igrf(inst, glat_label='glat', glong_label='glong', alt_label='alt'): """ Uses International Geomagnetic Reference Field (IGRF) model to obtain geomagnetic field values. Uses pyglow module to run IGRF. Configured to use actual solar parameters to run model. Example ------- # function added velow modifies the inst object upon every inst.load call inst.custom.add(add_igrf, 'modify', glat_label='custom_label') Parameters ---------- inst : pysat.Instrument Designed with pysat_sgp4 in mind glat_label : string label used in inst to identify WGS84 geodetic latitude (degrees) glong_label : string label used in inst to identify WGS84 geodetic longitude (degrees) alt_label : string label used in inst to identify WGS84 geodetic altitude (km, height above surface) Returns ------- inst Input pysat.Instrument object modified to include HWM winds. 'B' total geomagnetic field 'B_east' Geomagnetic field component along east/west directions (+ east) 'B_north' Geomagnetic field component along north/south directions (+ north) 'B_up' Geomagnetic field component along up/down directions (+ up) 'B_ecef_x' Geomagnetic field component along ECEF x 'B_ecef_y' Geomagnetic field component along ECEF y 'B_ecef_z' Geomagnetic field component along ECEF z """ import pyglow from pyglow.pyglow import Point import pysatMagVect igrf_params = [] # print 'IRI Simulations' for time, lat, lon, alt in zip(inst.data.index, inst[glat_label], inst[glong_label], inst[alt_label]): pt = Point(time, lat, lon, alt) pt.run_igrf() igrf = {} igrf['B'] = pt.B igrf['B_east'] = pt.Bx igrf['B_north'] = pt.By igrf['B_up'] = pt.Bz igrf_params.append(igrf) # print 'Complete.' igrf = pds.DataFrame(igrf_params) igrf.index = inst.data.index inst[igrf.keys()] = igrf # convert magnetic field in East/north/up to ECEF basis x, y, z = pysatMagVect.enu_to_ecef_vector(inst['B_east'], inst['B_north'], inst['B_up'], inst[glat_label], inst[glong_label]) inst['B_ecef_x'] = x inst['B_ecef_y'] = y inst['B_ecef_z'] = z # metadata inst.meta['B'] = { 'units': 'nT', 'desc': 'Total geomagnetic field from IGRF.' } inst.meta['B_east'] = { 'units': 'nT', 'desc': 'Geomagnetic field from IGRF expressed using the East/North/Up (ENU) basis.' } inst.meta['B_north'] = { 'units': 'nT', 'desc': 'Geomagnetic field from IGRF expressed using the East/North/Up (ENU) basis.' } inst.meta['B_up'] = { 'units': 'nT', 'desc': 'Geomagnetic field from IGRF expressed using the East/North/Up (ENU) basis.' } inst.meta['B_ecef_x'] = { 'units': 'nT', 'desc': 'Geomagnetic field from IGRF expressed using the Earth Centered Earth Fixed (ECEF) basis.' } inst.meta['B_ecef_y'] = { 'units': 'nT', 'desc': 'Geomagnetic field from IGRF expressed using the Earth Centered Earth Fixed (ECEF) basis.' } inst.meta['B_ecef_z'] = { 'units': 'nT', 'desc': 'Geomagnetic field from IGRF expressed using the Earth Centered Earth Fixed (ECEF) basis.' } return
#============================================================================== #Load magnetic equator data points to be overlayed on plot mag_equator = np.loadtxt("Magnetic_equator_lat_lon.txt", delimiter=',') top = mag_equator[180:360, :] bottom = mag_equator[0:180, :] mag_equator = np.concatenate((top, bottom), axis=0) data = np.zeros((120, 240)) marklon = 0 #Loop through lat and lon. select what MSIS values are desired for Lon in range(-120, 120, 1): marklat = 0 for Lat in range(-60, 60, 1): pt = Point(dn, Lat * 1.5, Lon * 1.5, 400) #1.5 degree grid size pt.f107a = 180 pt.f107p = 180 # previous day's F10.7 pt.apmsis = [ 0, ] * 7 result = pt.run_msis() #data[marklat,marklon] = math.log10((result.nn['HE']*4/Av)/(result.rho-result.nn['HE']*4/Av),10) #Derived helium if whatplot == 'He': data[marklat, marklon] = result.nn[ 'HE'] * .004003 / Av * 10**6 # MSIS helium (Should be the same as derived) elif whatplot == 'Temp': data[marklat, marklon] = result.Tn_msis #Neutral Temperature else: print('Bad Plot input')
O1 = np.zeros(len(m)) Hp_mbar = np.zeros(len(m)) Hp_he = np.zeros(len(m)) Hp_n2 = np.zeros(len(m)) Hp_o1 = np.zeros(len(m)) k = 1.3806 * 10**(-23) #Boltzmann's constant g0 = 9.81 #m/s^2 R = 6373 #Radius of earth in km Av = 6.022141 * 10**23 #Avogadro's Constant n = 0 rho = np.zeros(len(m)) #Iterate through altitudes in range m for x in m: pt = Point(dn, lat, lon, x) result = pt.run_msis() #Knudsen number estimate n_dens_tot = result.nn['HE']+result.nn['N2']+result.nn['O2'] \ +result.nn['AR']+result.nn['H']+result.nn['O']+result.nn['N']# number density per cm^3 g = g0 * R**2 / (R + x)**2 m_dens1 = (result.nn['HE']*.004003/Av+result.nn['N2']*.0280134/Av\ +result.nn['O2']*.032/Av+result.nn['AR']*.039948/Av+result.nn['N']\ *.01401/Av+result.nn['H']*.001/Av+result.nn['O']*.016/Av)#kg/cm^3 Mbar[n] = m_dens1 * Av * 1000 / (n_dens_tot) #kg/kmol Tn[n] = result.Tn_msis #Follows form of kT/mg for pressure scale height Hp_mbar[n] = k * Tn[n] / (Mbar[n] * g) * Av
dn = datetime(1992, 3, 20, 0, 2)#year,month,day,hour,minute Av = 6.022141*10**23 #============================================================================== # pt = Point(dn, lat, lon, 400) # result = pt.run_msis() # print pt # print result.f107 #============================================================================== data = np.zeros(121) marklon = 0 latitudes = range(-60,61,1) #Run MSIS for range of latitudes for Lat in range(-60,61,1) : pt = Point(dn, Lat, lon, 400) result = pt.run_msis() data[marklon] = result.Tn_msis marklon = marklon+1 f=result.f107 fa=result.f107a apmsis=result.apmsis #Plot the data fig = plt.figure() plt.plot(latitudes,data) plt.title('Temperature ETA MSIS lon=%.1f UT=0.03 F10.7=%.1f'%(lon,f),fontweight='bold') plt.ylabel('Neutral Temperature (K)') plt.xlabel('Latitude')