def presSearch(p, gem_inputs, paths=False): Ro = 10.0 target_pres = p pres_ws = 0 tol = 1e-3 source_list, stat, v, theta, dphi, sounding_pres, sw, wind, dopplershift = gem_inputs search_min = [tol] search_max = [100] Ro, f_opt = pso(overpressureErr, search_min, search_max, \ args=gem_inputs + [p, 'pres', 'ws'], swarmsize=SWARM_SIZE, maxiter=MAX_ITER, processes=1, minfunc=tol, minstep=1e-3) Ro = Ro[0] print("Pressure Weak Shock: {:.2f} mPa Ro = {:.3f} m".format(p * 1000, Ro)) Ro_ws = Ro Ro = 10.0 pres_lin = 0 Ro, f_opt = pso(overpressureErr, search_min, search_max, \ args=gem_inputs + [p, 'pres', 'lin'], swarmsize=SWARM_SIZE, maxiter=MAX_ITER, processes=1, minfunc=tol, minstep=1e-3) Ro = Ro[0] print("Pressure Linear: {:.2f} mPa Ro = {:.3f} m".format(p * 1000, Ro)) Ro_lin = Ro if paths: source_list, stat, v, theta, dphi, sounding_pres, sw, wind, dopplershift = gem_inputs tau, tauws, Z, sR, inc, talt, dpws, dp, it = overpressureihmod_Ro( source_list, stat, Ro_ws, v, theta, dphi, sounding_pres, sw, wind=wind, dopplershift=dopplershift) weak_path = tau[:it] + tauws[it:] tau, tauws, Z, sR, inc, talt, dpws, dp, it = overpressureihmod_Ro( source_list, stat, Ro_lin, v, theta, dphi, sounding_pres, sw, wind=wind, dopplershift=dopplershift) lin_path = tau return Ro_ws, Ro_lin, weak_path, lin_path, tau, Z, it return Ro_ws, Ro_lin
def inverse_gunc(self, p_ans): a, b = pso(gunc_error, [1], [15], args=([p_ans, self.J_m, \ self.W_0, self.P, self.P_0, self.Jd, self.c_m, self.f_d, self.R,\ self.P_a, self.k, self.b, self.I, self.cf, self.horizontal_range, self.v]), \ processes=1, swarmsize=1000, maxiter=1000) return 10**(a[0])
def findHeightFromTime(sounding, t, approx_height): traj = self.bam.setup.trajectory found = False prev_err = 999 TIME_TOL = 1e-3 BOUNDS = 4000 indxs = 100 stat_pos = self.getStat() SWARM_SIZE = 100 MAXITER = 25 PHIP = 0.5 PHIG = 0.5 OMEGA = 0.5 MINFUNC = 1e-3 MINSTEP = 1e-2 search_min = [approx_height - BOUNDS] search_max = [approx_height + BOUNDS] f_opt, x_opt = pso(heightErr, search_min, search_max, \ args=[t, traj, stat_pos, sounding], processes=multiprocessing.cpu_count()-1, particle_output=False, swarmsize=SWARM_SIZE,\ maxiter=MAXITER, phip=PHIP, phig=PHIG, \ debug=False, omega=OMEGA, minfunc=MINFUNC, minstep=MINSTEP) best_height = f_opt[0] print("Best Height = {:.5f} km".format(best_height / 1000)) return best_height
def psoSearch(stns, w, s_name, bam, prefs, ref_pos, manual=False, pert_num=0, override_supra=[], theo=False): """ Optimizes the paths between the detector stations and a supracenter to find the best fit for the position of the supracenter, within the given search area. The supracenter is found with an initial guess, in a given grid, and is moved closer to points of better fit through particle swarm optimization. Produces a graph with the stations and residual results, and prints out the optimal supracenter location """ print('Data converted. Searching...') setup = bam.setup atmos = bam.atmos search_min = Position(setup.lat_min, setup.lon_min, setup.elev_min) search_max = Position(setup.lat_max, setup.lon_max, setup.elev_max) if not manual: try: search_min.pos_loc(ref_pos) search_max.pos_loc(ref_pos) except (AttributeError, TypeError) as e: errorMessage('Search min and search max have not been defined! Aborting search!', 2, info='Please define a search area in the "Sources" tab on the left side of the screen!', detail='{:}'.format(e)) return None output_name = prefs.workdir if not isinstance(override_supra, list): single_point = override_supra else: single_point = setup.manual_fragmentation_search[0] if single_point.toList()[0] is None and manual: errorMessage('Manual Fragmentation Point undefined', 2, info='Unable to parse: Lat: {:} Lon: {:} Elev: {:} Time: {:}'.format(*single_point.toList())) return None ref_time = setup.fireball_datetime if setup.enable_restricted_time: kotc = setup.restricted_time else: kotc = None # check if user defined occurrence time is used if kotc != None: kotc = (kotc - ref_time).total_seconds() # number of stations total n_stations = len(stns) # Station Location xstn = stns[0:n_stations, 0:3] # Initialize arrays # 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(n_stations) # Initialize variables # combined weights nwn = sum(w) if prefs.ballistic_en: try: v = -setup.trajectory.vector.xyz setup.ref_pos = setup.trajectory.pos_f if prefs.debug: print("Constraining Trajectory") except: v = [None] if prefs.debug: print("Free Search") else: v = [None] if prefs.debug: print("Free Search") # If automatic search if not manual: # Prevent search below stations if search_min.elev < max(xstn[:, 2]): # Must be just above the stations search_min.elev = max(xstn[:, 2]) + 0.0001 # Boundaries of search volume # [x, y, z] local coordinates # arguments to be passed to timeFunction() args = (stns, w, kotc, setup, ref_pos, atmos, prefs, v, pert_num, theo) # Particle Swarm Optimization # x_opt - optimal supracenter location # f_opt - optimal supracenter error # if setup.restrict_to_trajectory: # #cons = [lineConstraintx, lineConstrainty, lineConstraintz] # x_opt, f_opt = pso(timeFunction, lb, ub, f_ieqcons=lineConstraint, args=args, swarmsize=int(setup.swarmsize), maxiter=int(setup.maxiter), \ # phip=setup.phip, phig=setup.phig, debug=False, omega=setup.omega, minfunc=setup.minfunc, minstep=setup.minstep) # else: # # Restricted to trajectory # if v[0] != None: # x_opt_temp, f_opt, sup, errors = pso(timeFunction, search_min.xyz, search_max.xyz, \ # ieqcons=[trajConstraints, timeConstraints], args=args,\ # swarmsize=int(prefs.pso_swarm_size), maxiter=int(prefs.pso_max_iter), \ # phip=prefs.pso_phi_p, phig=prefs.pso_phi_g, debug=False, omega=prefs.pso_omega, \ # minfunc=prefs.pso_min_error, minstep=prefs.pso_min_step, processes=1, particle_output=True) x_opt_temp, f_opt, sup, errors = pso(timeFunction, search_min.xyz, search_max.xyz, \ args=args, swarmsize=int(prefs.pso_swarm_size), maxiter=int(prefs.pso_max_iter), \ phip=prefs.pso_phi_p, phig=prefs.pso_phi_g, debug=False, omega=prefs.pso_omega,\ minfunc=prefs.pso_min_error, minstep=prefs.pso_min_step, processes=1, particle_output=True) print('Done Searching') x_opt = Position(0, 0, 0) x_opt.x = x_opt_temp[0] x_opt.y = x_opt_temp[1] x_opt.z = x_opt_temp[2] x_opt.pos_geo(ref_pos) # If manual search else: single_point.position.pos_loc(ref_pos) x_opt = single_point.position sup = single_point.position.xyz errors=0 # Get results for current Supracenter time3D, az, tf, r, motc, sotc, trace = outputWeather(n_stations, x_opt, stns, setup, \ ref_pos, atmos, output_name, s_name, kotc, w, prefs, theo) for ii, element in enumerate(time3D): if np.isnan(element): w[ii] = 0 sotc[ii] = 0 # Find error for manual searches if manual: f_opt = np.dot(w, np.absolute(sotc - np.dot(w, sotc)/nwn))/nwn # x, y distance from Supracenter to each station horz_dist = np.zeros(n_stations) for i in range(n_stations): horz_dist[i] = np.sqrt((x_opt.x - xstn[i, 0])**2 + (x_opt.y - xstn[i, 1])**2)/1000 # Calculate and Set the Occurrence Time into HH:MM:SS time_diff = motc + ref_time.microsecond/1e6 + ref_time.second + ref_time.minute*60 + ref_time.hour*3600 try: otc = (datetime.datetime.min + datetime.timedelta(seconds=time_diff)).time() except (ValueError, OverflowError): print('STATUS: Unable to parse otc') otc = None try: #while max(errors) > setup.max_error/100: a = [] std_error = np.std(errors) lim = np.mean(errors) + 0*std_error for i in range(len(errors)): if errors[i] >= lim: a.append(i) errors = np.delete(errors, (a), axis=0) sup = np.delete(sup, (a), axis=0) except: print("WARNING: Unable to filter errors") class Results: def __init__(self): pass results = Results() results.r = r results.w = w results.x_opt = x_opt results.f_opt = f_opt results.sup = sup results.errors = errors results.horz_dist = horz_dist results.time3D = time3D results.az = az results.tf = tf results.motc = motc results.sotc = sotc results.kotc = kotc results.otc = otc results.trace = trace return results # # scatter plot(s) # min_search, max_search = scatterPlot(single_point, n_stations, xstn, s_name, r, x_opt, \ # reported_points, search, output_name, ref_pos, sup, errors, tweaks, dataset) # # residual plot # residPlot(x_opt, s_name, xstn, r, output_name, n_stations) # # output results # outputText(min_search, max_search, single_point, ref_time, otc, kotc, x_opt, f_opt, n_stations, tweaks, s_name, xstn, \ # r, w, az, tf, time3D, horz_dist, output_name, tstn)
def psoTrajectory(station_list, bam, prefs): point_on_traj = None ref_pos = Position(bam.setup.lat_centre, bam.setup.lon_centre, 0) # ref_pos = bam.setup.trajectory.pos_f if bam.setup.pos_min.isNone() or bam.setup.pos_max.isNone(): errorMessage( 'Search boundaries are not defined!', 2, info= 'Please define the minimum and maximum parameters in the "Sources" tab on the left side of the screen!' ) return None bam.setup.pos_min.pos_loc(ref_pos) bam.setup.pos_max.pos_loc(ref_pos) if point_on_traj is None: bounds = [ (bam.setup.pos_min.x, bam.setup.pos_max.x), # X0 (bam.setup.pos_min.y, bam.setup.pos_max.y), # Y0 (bam.setup.t_min, bam.setup.t_max), # t0 (bam.setup.v_min, bam.setup.v_max), # Velocity (m/s) (bam.setup.azimuth_min.deg, bam.setup.azimuth_max.deg), # Azimuth (bam.setup.zenith_min.deg, bam.setup.zenith_max.deg ) # Zenith angle ] else: bounds = [ (bam.setup.v_min, bam.setup.v_max), # Velocity (m/s) (bam.setup.azimuth_min.deg, bam.setup.azimuth_max.deg), # Azimuth (bam.setup.zenith_min.deg, bam.setup.zenith_max.deg ) # Zenith angle ] lower_bounds = [bound[0] for bound in bounds] upper_bounds = [bound[1] for bound in bounds] if prefs.debug: print('Free Search') import matplotlib.pyplot as plt plt.ion() fig, ax = plt.subplots(2, 3, sharey='row') ax[0, 0].set_ylabel("Total Error") ax[1, 0].set_ylabel("Total Error") ax[0, 0].set_xlabel("Latitude") ax[0, 1].set_xlabel("Longitude") ax[0, 2].set_xlabel("Time") ax[1, 0].set_xlabel("Velocity") ax[1, 1].set_xlabel("Azimuth") ax[1, 2].set_xlabel("Zenith") plot = [] for i in range(2): for j in range(3): plot.append(ax[i, j].scatter([], [])) x, fopt = pso(trajSearch, lower_bounds, upper_bounds, args=(station_list, ref_pos, bam, prefs, plot, ax, fig, point_on_traj), \ maxiter=prefs.pso_max_iter, swarmsize=prefs.pso_swarm_size, \ phip=prefs.pso_phi_p, phig=prefs.pso_phi_g, debug=False, omega=prefs.pso_omega, \ particle_output=False) # if point_on_traj is None: print('Results:') print('X: {:.4f}'.format(x[0])) print('Y: {:.4f}'.format(x[1])) print('Time: {:.4f}'.format(x[2])) print('Velocity: {:.4f}'.format(x[3])) print('Azimuth: {:.4f}'.format(x[4])) print('Zenith: {:.4f}'.format(x[5])) print('Adjusted Error: {:.4f}'.format(fopt)) # else: # print('Results:') # print('Velocity: {:.4f}'.format(x[0])) # print('Azimuth: {:.4f}'.format(x[1])) # print('Zenith: {:.4f}'.format(x[2])) # print('Adjusted Error: {:.4f}'.format(fopt)) # if point_on_traj is None: geo = Position(0, 0, 0) geo.x = x[0] geo.y = x[1] geo.z = 0 geo.pos_geo(ref_pos) print('Geometric Landing Point:') print(geo) stat_names = [] stat_pick = [] final_traj = Trajectory(x[2], x[3], zenith=Angle(x[5]), azimuth=Angle(x[4]), pos_f=geo) points = final_traj.findPoints(gridspace=100, min_p=17000, max_p=50000) for stn in station_list: stat_names.append("{:}-{:}".format(stn[1], stn[2])) t_nom, t_pert = timeOfArrival(np.array([stn[3], stn[4], stn[5]]), final_traj, bam, prefs, points, ref_loc=ref_pos) stat_pick.append(t_nom - stn[6]) return [x, fopt, geo, stat_names, stat_pick]
def cyscan(S, D, z_profile, trace=False, plot=False, particle_output=False, debug=False, wind=False, h_tol=330, v_tol=3000, \ print_times=False): # phi, theta search_min = [0, 90] search_max = [360, 180] cyscan_inputs = [S, z_profile, D, wind, debug, h_tol, v_tol] if particle_output: f_opt, x_opt, f_particle, x_particle = pso(angleErr, search_min, search_max, \ args=cyscan_inputs, processes=multiprocessing.cpu_count()-1, particle_output=True, swarmsize=SWARM_SIZE,\ maxiter=MAXITER, phip=PHIP, phig=PHIG, \ debug=False, omega=OMEGA, minfunc=MINFUNC, \ minstep=MINSTEP) else: f_opt, x_opt = pso(angleErr, search_min, search_max, \ args=cyscan_inputs, processes=1, particle_output=False, swarmsize=SWARM_SIZE,\ maxiter=MAXITER, phip=PHIP, phig=PHIG, \ debug=False, omega=OMEGA, minfunc=MINFUNC, \ minstep=MINSTEP) if trace: r = anglescan(S, f_opt[0], f_opt[1], z_profile, trace=True) tr = np.array(r[1]) if plot: fig = plt.figure() ax = Axes3D(fig) ax.scatter(S.lon, S.lat, S.elev, c='r', marker='*') ax.scatter(D.lon, D.lat, D.elev, c='g', marker='^') ax.scatter(tr[:, 0], tr[:, 1], tr[:, 2], c='b') ax.plot(tr[:, 0], tr[:, 1], tr[:, 2], c='k') # Plot all missed angles if particle_output: for particle in range(len(f_particle)): r = anglescan(S, f_particle[particle][0], f_particle[particle][1], z_profile, trace=True) tr = np.array(r[1]) ax.plot(tr[:, 0], tr[:, 1], tr[:, 2], alpha=0.3) plt.show() else: r = anglescan(S, f_opt[0], f_opt[1], z_profile, trace=False) if debug: print("Final Solution: {:.2f} {:.2f}".format(f_opt[0], f_opt[1])) print("Final Error: {:.2f}".format(x_opt)) if trace: phi_list = [] the_list = [] for i in range(len(tr[:, 2]) - 1): f_v = np.abs(tr[i + 1, 2] - tr[i, 2]) f_h = np.sqrt((tr[i + 1, 0] - tr[i, 0])**2 + (tr[i + 1, 1] - tr[i, 1])**2) f_x = tr[i + 1, 0] - tr[i, 0] f_y = tr[i + 1, 1] - tr[i, 1] tr_phi = np.degrees(np.arctan2(f_x, f_y)) tr_theta = np.degrees(np.arctan2(f_v, f_h)) + 90 phi_list.append(tr_phi) the_list.append(tr_theta) if i == 0: # Note that the trace solution may not equal the actual solution if there are winds print("Trace Solution: {:.2f} {:.2f}".format( tr_phi, tr_theta)) print("Mean Angles: {:.2f} {:.2f}".format(np.nanmean(phi_list), np.nanmean(the_list))) if trace: x, y, z, T = r[0] else: x, y, z, T = r # if print_times: # alltimes = [] # for particle in range(len(f_particle)): # r = anglescan(S, f_particle[particle][0], f_particle[particle][1], z_profile, trace=False) # x_t, y_t, z, T = r # h_err = np.sqrt((D[0] - x)**2 + (D[1] - y)**2) # v_err = np.sqrt(D[2] - z) # if h_err <= h_tol and v_err <= v_tol: # alltimes.append(T) # if len(alltimes) == 0: # print("No times within error!") # else: # print("Times:") # print("Minimum Time: {:.4f} s".format(np.nanmin(alltimes))) # print("Maximum Time: {:.4f} s".format(np.nanmax(alltimes))) # print("Time of Minimum Error: {:.4f} s".format(T)) h_err = np.sqrt((x - D[0])**2 + (y - D[1])**2) v_err = np.abs(z - D[2]) if h_err <= h_tol and v_err <= v_tol: # Good Arrival R = [T, f_opt[0], f_opt[1], x_opt] else: R = [np.nan, np.nan, np.nan, x_opt] tr = [[np.nan, np.nan, np.nan, np.nan]] if trace: if particle_output: return R, tr, f_particle return R, tr else: if particle_output: return R, f_particle return R
def estimateSeismicTrajectoryAzimuth(station_list, setup, sounding, p0=None, azim_range=None, elev_range=None, \ v_fixed=None, allTimes=[], ax=None): """ Estimate the trajectory of a fireball from seismic/infrasound data by modelling the arrival times of the balistic shock at given stations. The method is implemented according to Pujol et al. (2005) and Ishihara et al. (2003). Arguments: station_list: [list] A list of stations and arrival times, each entry is a tuple of: (name, lat, lon, elev, arrival_time_jd), where latitude and longitude are in radians, the zangle is in meters and Julian date of the arrival time. setup: [Object] Object containing all user-defined parameters sounding: [ndarray] atmospheric profile of the search area Keyword arguments: p0: [6 element ndarray] Initial parameters for trajectory estimation: p0[0]: [float] p0, north-south offset of the trajectory intersection with the ground (in km, +S). p0[1]: [float] y0, east-west offset of the trajectory intersection with the ground (in km, +E). p0[2]: [float] Time when the trajectory was at point (p0, y0), reference to the reference time (seconds). p0[3]: [float] Velocity of the fireball (km/s). p0[4]: [float] Initial azimuth (+E of due north) of the fireball (radians). p0[5]: [float] Initial zenith angle of the fireball (radians). azim_range: [list of floats] (min, max) azimuths for the search, azimuths should be +E of due North in degrees. If the range of azmiuths traverses the 0/360 discontinuity, please use negative values for azimuths > 180 deg! elev_range: [list of floats] (min, max) zangles for the search, in degrees. The zangle is measured from the horizon up. v_fixed: [float or None] value to restrict the velocity of the meteor. If set to None, there is no restriction """ t0 = time.time() if ax is None: ax = plt.gca() # Extract all Julian dates jd_list = [entry[6] for entry in station_list] pick_time = [float(entry[7]) for entry in station_list] station_no = [int(float(entry[8])) for entry in station_list] # Calculate the arrival times as the time in seconds from the earliest JD jd_ref = min(jd_list) jd_list = np.array(jd_list) # Get the index of the first arrival station first_arrival_indx = np.argwhere(jd_list == jd_ref)[0][0] ref_pick_time = pick_time[first_arrival_indx] # Convert station coordiantes to local coordinates, with the station of the first arrival being the # origin of the coordinate system stat_coord_list = convertStationCoordinates(station_list, first_arrival_indx) ref_pos = Position(setup.lat_centre, setup.lon_centre, 0) setup.pos_min.pos_loc(ref_pos) setup.pos_max.pos_loc(ref_pos) bounds = [ (setup.pos_min.x, setup.pos_max.x), # X0 (setup.pos_min.y, setup.pos_max.y), # Y0 (setup.t_min, setup.t_max), # t0 (setup.v_min, setup.v_max), # Velocity (m/s) (setup.azimuth_min.deg, setup.azimuth_max.deg), # Azimuth (setup.zenith_min.deg, setup.zenith_max.deg) # Zenith angle ] print("Bounds:") print("x : {:+8.2f} - {:+8.2f} km".format(setup.pos_min.x / 1000, setup.pos_max.x / 1000)) print("y : {:+8.2f} - {:+8.2f} km".format(setup.pos_min.y / 1000, setup.pos_max.y / 1000)) print("t : {:8.2f} - {:8.2f} s".format(setup.t_min, setup.t_max)) print("v : {:8.2f} - {:8.2f} km/s".format(setup.v_min / 1000, setup.v_max / 1000)) print("Azimuth: {:8.2f} - {:8.2f} deg fN".format(setup.azimuth_min.deg, setup.azimuth_max.deg)) print("Zenith : {:8.2f} - {:8.2f} deg".format(setup.zenith_min.deg, setup.zenith_max.deg)) # Extract lower and upper bounds lower_bounds = [bound[0] for bound in bounds] upper_bounds = [bound[1] for bound in bounds] class MiniResults(): def __init__(self): self.x = None # Run PSO several times and choose the best solution solutions = [] for i in range(setup.run_times): # Use PSO for minimization x, fopt, particles, errors = pso(timeResidualsAzimuth, lower_bounds, upper_bounds, args=(stat_coord_list, \ pick_time, setup, sounding, v_fixed), maxiter=setup.maxiter, swarmsize=setup.swarmsize, \ phip=setup.phip, phig=setup.phig, debug=False, omega=setup.omega, \ processes=multiprocessing.cpu_count(), particle_output=True) #multiprocessing.cpu_count() solutions.append([x, fopt]) print('Computational best estimation', fopt) print(solutions) ### TESTING WITHOUT PERTS if setup.perturb and False: #allTimes = [perturb_no, station_no, ball/frag, frag_no] try: perturb_times = allTimes.shape[0] p_arrival_times = allTimes[:, station_no, 0, 0] - float(ref_pick_time) x_perturb = [0] * perturb_times fopt_perturb = [0] * perturb_times for i in range(1, perturb_times): #remove nan #p_arrival_times[i] = [j for j in p_arrival_times[i] if j != j] # Use PSO for minimization, with perturbed arrival times x_perturb[i], fopt_perturb[i] = pso(timeResidualsAzimuth, lower_bounds, upper_bounds, args=(stat_coord_list, \ p_arrival_times[i], setup, sounding, v_fixed), maxiter=setup.maxiter, swarmsize=setup.swarmsize, \ phip=setup.phip, phig=setup.phig, debug=False, omega=setup.omega, processes=multiprocessing.cpu_count()) print(x_perturb[i], fopt_perturb[i]) print('Perturbation', i, 'best estimation', fopt_perturb[i]) except AttributeError: x_perturb, fopt_perturb = [], [] setup.perturb = False else: x_perturb, fopt_perturb = [], [] # Choose the solution with the smallest residuals fopt_array = np.array([fopt for x_val, fopt_val in solutions]) best_indx = np.argmin(fopt_array) x, fopt = solutions[best_indx] res = MiniResults() res.x = x # Extract estimated parameters x0, y0 = res.x[:2] t0 = res.x[2] v_est = res.x[3] azim, zangle = res.x[4:] ref_pos = Position(setup.lat_centre, setup.lon_centre, 0) lat_fin, lon_fin, _ = loc2Geo(ref_pos.lat, ref_pos.lon, ref_pos.elev, [x0, y0, 0]) # Print the time residuals per every station timeResidualsAzimuth(res.x, stat_coord_list, pick_time, setup, sounding, v_fixed=v_fixed, print_residuals=True) # Plot the stations and the estimated trajectory residuals = plotStationsAndTrajectory( station_list, [x0, y0, t0, v_est / 1000, azim, zangle], setup, sounding, x_perturb=x_perturb, ax=ax) final_pos = Position(lat_fin, lon_fin, 0) results = [final_pos, ref_pos, t0, v_est, azim, zangle, residuals] results = [] print("Results:") print("Trajectory (Nominal) | Lat {:+10.4f} N Lon {:+10.4f} E t {:5.2f} s v {:7.4f} km/s Azimuth {:6.2f} deg fN Zenith {:5.2f} Error {:10.4f}"\ .format(lat_fin, lon_fin, t0, v_est/1000, azim, zangle, fopt)) results.append([lat_fin, lon_fin, t0, v_est / 1000, azim, zangle, fopt]) # for i in range(perturb_times): # lat_fin, lon_fin, _ = loc2Geo(ref_pos.lat, ref_pos.lon, ref_pos.elev, [x_perturb[i][0], x_perturb[i][1], 0]) # print("Trajectory (Perturbation {:4d}) | Lat {:+10.4f} N Lon {:+10.4f} E t {:5.2f} s v {:7.4f} km/s Azimuth {:6.2f} deg fN Zenith {:5.2f} Error {:10.4f}"\ # .format(i, lat_fin, lon_fin, x_perturb[i][2], x_perturb[i][3]/1000,\ # x_perturb[i][4], x_perturb[i][5], fopt_perturb[i])) # results.append([lat_fin, lon_fin, x_perturb[i][2], x_perturb[i][3]/1000, x_perturb[i][4], x_perturb[i][5], fopt_perturb[i]]) particles = np.array(particles) errors = np.array(particles) return particles, errors, results
def periodSearch(p, gem_inputs, paths=False): ''' Uses PSO to find the Relaxation radius that returns the desired period through the Geminus program ''' Ro = 10.0 target_period = p period_ws = 0 tol = 1e-3 tau = [] search_min = [tol] search_max = [100] Ro, f_opt = pso(overpressureErr, search_min, search_max, \ args=gem_inputs + [p, 'period', 'ws'], swarmsize=SWARM_SIZE, maxiter=MAX_ITER, processes=1, minfunc=tol, minstep=1e-3) Ro = Ro[0] print("Period Weak Shock: {:.2f} s Ro = {:.3f} m".format(p, Ro)) Ro_ws = Ro Ro = 10.0 period_lin = 0 Ro, f_opt = pso(overpressureErr, search_min, search_max, \ args=gem_inputs + [p, 'period', 'lin'], swarmsize=SWARM_SIZE, maxiter=MAX_ITER, processes=1, minfunc=tol, minstep=1e-3) Ro = Ro[0] print("Period Linear: {:.2f} s Ro = {:.3f} m".format(p, Ro)) Ro_lin = Ro if paths: source_list, stat, v, theta, dphi, sounding_pres, sw, wind, dopplershift = gem_inputs tau, tauws, Z, sR, inc, talt, dpws, dp, it = overpressureihmod_Ro( source_list, stat, Ro_ws, v, theta, dphi, sounding_pres, sw, wind=wind, dopplershift=dopplershift) weak_path = tau[:it] + tauws[it:] tau, tauws, Z, sR, inc, talt, dpws, dp, it = overpressureihmod_Ro( source_list, stat, Ro_lin, v, theta, dphi, sounding_pres, sw, wind=wind, dopplershift=dopplershift) lin_path = tau return Ro_ws, Ro_lin, weak_path, lin_path, tau, Z, it return Ro_ws, Ro_lin
def findScaledDistance(x, func): # Use magnitude for faster search a, b = pso(func, [-2], [7], args=x, maxiter=1000, swarmsize=1000) scaled_distance = 10**a[0] return scaled_distance