def filterData(data, levels): consts = Constants() filt_data = np.empty((int(levels), 4)) for ii, line in enumerate(data): filt_data[ii, 0] = float(line[16:21]) a = float(line[22:27]) / 10 + 273.15 try: filt_data[ii, 1] = (consts.GAMMA * consts.R / consts.M_0 * a)**0.5 except TypeError: filt_data[ii, 1] = np.nan filt_data[ii, 3] = (float(line[40:45]) + 180) % 360 filt_data[ii, 2] = float(line[46:51]) / 10 filt_data[filt_data == -9999.0] = np.nan filt_data = filt_data[~np.isnan(filt_data).any(axis=1)] filt_data = np.flip(filt_data, axis=0) return filt_data
def parseWeather(setup, t=0, lat=None, lon=None): """ Generates a cubic weather profile of all altitudes within a 5 deg lat/lon area from lat/lon centre. """ consts = Constants() # Parse weather type setup.weather_type = setup.weather_type.lower() if setup.weather_type not in [ 'custom', 'none', 'ecmwf', 'merra', 'ukmo', 'binary', 'radio' ]: print( 'INI ERROR: [Atmospheric] weather_type must be one of: custom, radio, none, ecmwf, merra, ukmo, binary' ) return None # Custom weather data if setup.weather_type == 'custom': # try: sounding = readCustAtm(setup.sounding_file, consts) # except: # print('ERROR: Could not read custom atmosphere profile!') # exit() # Check file name if len(sounding) < 2: print('FILE ERROR: file must have at least two data points!') sys.exit() # MERRA-2 elif setup.weather_type == 'merra': # Check file type if '.nc' not in setup.sounding_file: print("FILE ERROR: custom data set must be a .nc file!") sys.exit() # # Run data fetching script # if setup.get_data == True: # print('Getting data...') # fetchMERRA(setup) try: sounding = storeHDF(setup.sounding_file, consts) except: print('ERROR: could not read merra atmosphere profile!') exit() # ECMWF elif setup.weather_type == 'ecmwf': # Check file type if '.nc' not in setup.sounding_file: print("FILE ERROR: custom data set must be a .nc file from ECMWF!") return None # # Run data fetching script # if setup.get_data == True: # fetchECMWF(setup, setup.sounding_file) # GetIRISData/MakeIRISPicks try: #Get closest hour start_time = (setup.fireball_datetime.hour + np.round( setup.fireball_datetime.minute / 60) + t) % 24 if lat is not None and lon is not None: sounding = storeNetCDFECMWF(setup.sounding_file, lat, lon, consts, start_time=start_time) else: sounding = storeNetCDFECMWF(setup.sounding_file, setup.lat_centre, setup.lon_centre, consts, start_time=start_time) # SeismicTrajectory except: try: start_time = (setup.fireball_datetime.hour + t) % 24 sounding = storeNetCDFECMWF(setup.sounding_file, setup.x0, setup.y0, consts, start_time=start_time) except: print( "ERROR: Unable to use weather file, or setup.start_datetime/setup.atm_hour is set up incorrectly. Try checking if sounding_file exists" ) # UKMO elif setup.weather_type == 'ukmo': # Check file type if '.nc' not in setup.sounding_file: print("FILE ERROR: custom data set must be a .nc file from UKMO!") sys.exit() try: sounding = storeNetCDFUKMO(setup.sounding_file, setup.search_area, consts) except: print('ERROR: Could not read UKMO atmosphere profile!') exit() elif setup.weather_type == 'binary': sounding = storeAus(consts) elif setup.weather_type == 'radio': time_of_sound = [ setup.fireball_datetime.year, setup.fireball_datetime.month, setup.fireball_datetime.day, setup.fireball_datetime.hour ] sounding = parseRadio(setup.sounding_file, time_of_sound) else: # Sample fake weather profile, the absolute minimum that can be passed sounding = np.array([[0.0, setup.v_sound, 0.0, 0.0], [0.0, setup.v_sound, 0.0, 0.0], [99999.0, setup.v_sound, 0.0, 0.0]]) return sounding
import pyximport pyximport.install(setup_args={'include_dirs': [np.get_include()]}) from scipy.interpolate import CubicSpline from supra.Utils.AngleConv import roundToNearest from supra.Utils.Classes import Constants from supra.Supracenter.cyzInteg import zInteg from supra.GUI.Tools.GUITools import * from supra.Atmosphere.Pressure import pressureConv, estPressure from supra.Atmosphere.NRLMSISE import getAtmDensity from wmpl.Utils.TrajConversions import date2JD from supra.Atmosphere.HWM93 import getHWM consts = Constants() class AtmosType: def __init__(self): pass def interp(self, lat, lon, div=0.25): """ Approximately interpolates grid points of a division between point A and point B lat: [lat_initial, lat_final] lon: [lon_initial, lon_final] """ # Collect interpolated points
import numpy as np import matplotlib.pyplot as plt import scipy from supra.Utils.Classes import Constants, Position c = Constants() # function [dp,dpws,dpratio,tau,tauws,Z,td,talt,Ro] = overpressureihmod_Ro(meteor,stn,Ro,v,theta,dphi,atmos,sw); def overpressureihmod_Ro(meteor, stn, Ro, v, theta, dphi, atmos, sw): # %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% # % # % Theoretical Acoustic Overpressure Prediction using Line Source Theory # % (ReVelle D.O., 1976: On Meteor-Generated Infrasound, JGR, 81, pp.1217-1229. # % # % Usage: # % [dp,dpws,dpratio,tau,tauws,Z,td,talt,Ro,dm] = overpressureihmod(meteor,stn,mass,rhom,v,theta,dphi,atmos,sw); # % # % Given: meteor - [latitude,longitude,altitude] of meteor source [DD.ddd,DD.ddd,km] # % stn - [latitude,longitude,elevation] of observing station [DD.ddd,DD.ddd,km] # % mass - meteoroid mass in kilograms (kg) # % rhom - meteoroid bulk density in kilograms per metre cubed (kg/m^3) # % v - meteoroid velocity in kilometres per second (km/s) # % theta - entry angle of meteoroid measured from horizontal (degrees) # % dphi - angular deviation from the meteoroid trajectory (degrees) # % atmos - atmospheric model (nx3) - MUST encompass altitudes for direct propagation # % - altitude (m) # % - pressure (hPa/mbars) # % - temperature (oC)
def outputWeather(n_stations, x_opt, stns, setup, ref_pos, atmos, output_name, s_name, kotc, w, prefs, theo): """ Function to calculate the results of the optimal Supracenter and export interpolated weather data from each station. Arguments: n_stations: [int] number of stations x_opt: [list] lat, lon, and height of the optimal supracenter xstn: [list] lat, lon, and height of all the stations setup: [Object] object storing user-defined setup consts: [Object] object storing physical constants ref_pos: [list] mean position of the stations to act as the origin for the local coordinate system dataset: [ndarray] atmospheric profile of search area output_name: [string] folder name to save output files in s_name: [list] name of all the stations kotc: [list] user-defined occurence time [HH, MM, SS] tobs: [list] station arrival times to each station w: [list] weights of each station Returns: time3D: [list] calculated travel time to each station az: [list] initial azimuth angle to each station tf: [list] initial takeoff angle to each station r: [list] residuals to each station """ consts = Constants() # Station Times tobs = stns[0:n_stations, 4] # Station Location xstn = stns[0:n_stations, 0:3] # Travel time to each station time3D = np.zeros(n_stations) # Initial azimuths angles of each station az = np.zeros(n_stations) # Initial takeoff angles of each station tf = np.zeros(n_stations) # difference in theoretical and simulated travel times sotc = np.zeros_like(tobs) #difference in theoretical and simulated travel times r = np.zeros_like(tobs) trace = [] # Find parameters of optimal location print('Exporting weather profiles...') for j in range(n_stations): #print(np.array(x_opt), np.array(xstn[j, :])) # get interpolated weather profile D = Position(0, 0, 0) D.x, D.y, D.z = xstn[j, 0], xstn[j, 1], xstn[j, 2] D.pos_geo(ref_pos) if not theo: sounding, _ = atmos.getSounding(lat=[x_opt.lat, D.lat], lon=[x_opt.lon, D.lon], heights=[x_opt.elev, D.elev], ref_time=setup.fireball_datetime) # Rotate winds to match with coordinate system #sounding[:, 3] = np.radians(angle2NDE(np.degrees(sounding[:, 3]))) # Export the interpolated weather profiles from the optimal Supracenter for each station # with open(os.path.join(output_name, s_name[j] + '_sounding.txt'), 'w') as f: # # With winds # if prefs.wind_en == True: # if prefs.atm_type == 'custom' or prefs.atm_type == 'none' or prefs.atm_type == 'radio': # f.write('| Height (m) | Temp (K) | soundSpd (m/s) | wdSpd (m/s) | wdDir (deg fN) |\n') # else: # f.write('| Latitude (deg N) | Longitude (deg E) | Height (m) | Temp (K) | soundSpd (m/s) | wdSpd (m/s) | wdDir (deg fN) |\n') # # No winds # else: # if prefs.atm_type == 'custom' or prefs.atm_type == 'none' or prefs.atm_type== 'radio': # f.write('| Height (m) | Temp (K) | soundSpd (m/s) |\n') # else: # f.write('| Latitude (deg N) | Longitude (deg E) | Height (m) | Temp (K) | soundSpd (m/s) |\n') # for ii in range(len(sounding)): # if prefs.wind_en == True: # if prefs.atm_type == 'custom' or prefs.atm_type == 'none' or prefs.atm_type == 'radio': # f.write('| {:8.2f} | {:7.3f} | {:6.4f} | {:7.3f} | {:6.2f} |\n'\ # .format(sounding[ii, 0], sounding[ii, 1]**2*consts.M_0/consts.GAMMA/consts.R, \ # sounding[ii, 1], sounding[ii, 2], sounding[ii, 3])) # else: # f.write('| {:7.4f} | {:7.4f} | {:8.2f} | {:7.3f} | {:6.4f} | {:7.3f} | {:6.2f} |\n'\ # .format(points[ii][0], points[ii][1], sounding[ii, 0], sounding[ii, 1]**2*consts.M_0/consts.GAMMA/consts.R, \ # sounding[ii, 1], sounding[ii, 2], sounding[ii, 3])) # else: # if prefs.atm_type == 'custom' or prefs.atm_type == 'none' or prefs.atm_type == 'radio': # f.write('| {:8.2f} | {:7.3f} | {:6.4f} |\n'\ # .format(sounding[ii, 0], sounding[ii, 1]**2*consts.M_0/consts.GAMMA/consts.R, sounding[ii, 1])) # else: # f.write('| {:7.4f} | {:7.4f} | {:8.2f} | {:7.3f} | {:6.4f} |\n'\ # .format(points[ii][0], points[ii][1], sounding[ii, 0], sounding[ii, 1]**2*consts.M_0/consts.GAMMA/consts.R, sounding[ii, 1])) # ray tracing function # _, _, _, _, temp_trace = slowscan(x_opt.xyz, np.array(xstn[j, :]), sounding, \ # wind=prefs.wind_en, n_theta=prefs.pso_theta, n_phi=prefs.pso_phi,\ # h_tol=prefs.pso_min_ang, v_tol=prefs.pso_min_dist) time3D[j], _, _, _ = cyscan(x_opt.xyz, np.array(xstn[j, :]), sounding, \ wind=prefs.wind_en, h_tol=prefs.pso_min_ang, v_tol=prefs.pso_min_dist, processes=1) else: time3D[j] = x_opt.pos_distance(D) / prefs.avg_sp_sound # trace.append(temp_trace) # find residuals sotc[j] = tobs[j] - time3D[j] # for ii, element in enumerate(time3D): # if np.isnan(element): # w[ii] = 0 # User defined occurrence time if kotc != None: motc = kotc index = [] # elif setup.manual_fragmentation_search != '' and len(setup.manual_fragmentation_search) > 0: # motc = setup.manual_fragmentation_search[3] # Unknown occurrence time else: w = np.array([1] * len(sotc)) index = np.isnan(sotc) sotc[index] = 0 motc = np.dot(w, sotc) / sum(w) # Station residuals (from average) r = sotc - motc r[index] = np.nan return time3D, az, tf, r, motc, sotc, trace