def add_geo_to_arrivals(arrivals, source_latitude_in_deg, source_longitude_in_deg, receiver_latitude_in_deg, receiver_longitude_in_deg, radius_of_earth_in_km, flattening_of_earth): """ Add geographical information to arrivals. :param arrivals: Set of taup arrivals :type: :class:`Arrivals` :param source_latitude_in_deg: Source location latitude in degrees :type source_latitude_in_deg: float :param source_longitude_in_deg: Source location longitude in degrees :type source_longitude_in_deg: float :param receiver_latitude_in_deg: Receiver location latitude in degrees :type receiver_latitude_in_deg: float :param receiver_longitude_in_deg: Receiver location longitude in degrees :type receiver_longitude_in_deg: float :param radius_of_earth_in_km: Radius of the Earth in km :type radius_of_earth_in_km: float :param flattening_of_earth: Flattening of Earth (0 for a sphere) :type receiver_longitude_in_deg: float :return: List of ``Arrival`` objects, each of which has the time, corresponding phase name, ray parameter, takeoff angle, etc. as attributes. :rtype: :class:`Arrivals` """ if geodetics.HAS_GEOGRAPHICLIB: ellipsoid = Geodesic(a=radius_of_earth_in_km * 1000.0, f=flattening_of_earth) g = ellipsoid.Inverse(source_latitude_in_deg, source_longitude_in_deg, receiver_latitude_in_deg, receiver_longitude_in_deg) azimuth = g['azi1'] line = ellipsoid.Line(source_latitude_in_deg, source_longitude_in_deg, azimuth) # We may need to update many arrival objects # and each could have pierce points and a # path for arrival in arrivals: if arrival.pierce is not None: geo_pierce = np.empty(arrival.pierce.shape, dtype=TimeDistGeo) for i, pierce_point in enumerate(arrival.pierce): pos = line.ArcPosition(np.degrees(pierce_point['dist'])) geo_pierce[i] = (pierce_point['p'], pierce_point['time'], pierce_point['dist'], pierce_point['depth'], pos['lat2'], pos['lon2']) arrival.pierce = geo_pierce if arrival.path is not None: geo_path = np.empty(arrival.path.shape, dtype=TimeDistGeo) for i, path_point in enumerate(arrival.path): pos = line.ArcPosition(np.degrees(path_point['dist'])) geo_path[i] = (path_point['p'], path_point['time'], path_point['dist'], path_point['depth'], pos['lat2'], pos['lon2']) arrival.path = geo_path else: # geographiclib is not installed ... # and obspy/geodetics does not help much msg = "You need to install the Python module 'geographiclib' in " + \ "order to add geographical information to arrivals." raise ImportError(msg) return arrivals
def add_geo_to_arrivals(arrivals, source_latitude_in_deg, source_longitude_in_deg, receiver_latitude_in_deg, receiver_longitude_in_deg, radius_of_planet_in_km, flattening_of_planet): """ Add geographical information to arrivals. :param arrivals: Set of taup arrivals :type: :class:`Arrivals` :param source_latitude_in_deg: Source location latitude in degrees :type source_latitude_in_deg: float :param source_longitude_in_deg: Source location longitude in degrees :type source_longitude_in_deg: float :param receiver_latitude_in_deg: Receiver location latitude in degrees :type receiver_latitude_in_deg: float :param receiver_longitude_in_deg: Receiver location longitude in degrees :type receiver_longitude_in_deg: float :param radius_of_planet_in_km: Radius of the planet in km :type radius_of_planet_in_km: float :param flattening_of_planet: Flattening of planet (0 for a sphere) :type receiver_longitude_in_deg: float :return: List of ``Arrival`` objects, each of which has the time, corresponding phase name, ray parameter, takeoff angle, etc. as attributes. :rtype: :class:`Arrivals` """ if geodetics.HAS_GEOGRAPHICLIB: if not geodetics.GEOGRAPHICLIB_VERSION_AT_LEAST_1_34: # geographiclib is not installed ... # and obspy/geodetics does not help much msg = ("This functionality needs the Python module " "'geographiclib' in version 1.34 or higher.") raise ImportError(msg) ellipsoid = Geodesic(a=radius_of_planet_in_km * 1000.0, f=flattening_of_planet) g = ellipsoid.Inverse(source_latitude_in_deg, source_longitude_in_deg, receiver_latitude_in_deg, receiver_longitude_in_deg) azimuth = g['azi1'] line = ellipsoid.Line(source_latitude_in_deg, source_longitude_in_deg, azimuth) # We may need to update many arrival objects # and each could have pierce points and a # path for arrival in arrivals: # check if we go in minor or major arc direction distance = arrival.purist_distance % 360. if distance > 180.: sign = -1 az_arr = (azimuth + 180.) % 360. else: sign = 1 az_arr = azimuth arrival.azimuth = az_arr if arrival.pierce is not None: geo_pierce = np.empty(arrival.pierce.shape, dtype=TimeDistGeo) for i, pierce_point in enumerate(arrival.pierce): dir_degrees = np.degrees(sign * pierce_point['dist']) pos = line.ArcPosition(dir_degrees) geo_pierce[i] = (pierce_point['p'], pierce_point['time'], pierce_point['dist'], pierce_point['depth'], pos['lat2'], pos['lon2']) arrival.pierce = geo_pierce if arrival.path is not None: geo_path = np.empty(arrival.path.shape, dtype=TimeDistGeo) for i, path_point in enumerate(arrival.path): dir_degrees = np.degrees(sign * path_point['dist']) pos = line.ArcPosition(dir_degrees) geo_path[i] = (path_point['p'], path_point['time'], path_point['dist'], path_point['depth'], pos['lat2'], pos['lon2']) arrival.path = geo_path else: # geographiclib is not installed ... # and obspy/geodetics does not help much msg = "You need to install the Python module 'geographiclib' in " + \ "order to add geographical information to arrivals." raise ImportError(msg) return arrivals
def organizebounds(num_bounds,iwall,idl,idr,lona,lata,lonb,latb,bound_ind,large_wall_inds,vt_ew,vt_ns,dsegtr,dseged,polarity,rad_km): # divide trenches and edges into segments lona_temp = []; lata_temp = []; lonb_temp = []; latb_temp = []; iwall_temp = []; idl_temp = []; idr_temp = []; bound_ind_temp = [] vt_ew_temp = []; vt_ns_temp = []; polarity_temp = []; large_wall_inds_temp = []; num_segs = 0; num_wall_segs = 0 print "------------------------" print "%.0f original boundaries" % num_bounds for i in range(num_bounds): # great circle distance [km] length = haversine(lona[i],lata[i],lonb[i],latb[i],rad_km) print "orig. length of segment %.0f = %.8f km" % (i+1,length) if iwall[i] == 1: iseg = int(.999 * length/dsegtr) + 1 elif (idl[i] != idr[i]) and iwall[i] == 0: iseg = int(.999 * length/dseged) + 1 else: iseg = 1 # strike-slip (iwall=2) # https://geographiclib.sourceforge.io/html/python/ geod = Geodesic(rad_km * 1e3, 0) # sphere gd = geod.Inverse(lata[i], lona[i], latb[i], lonb[i]) # total great-circle distance line = geod.Line(gd['lat1'], gd['lon1'], gd['azi1']) for iset in range(0,iseg): pointa = line.Position((gd['s12'] / iseg) * iset) pointb = line.Position((gd['s12'] / iseg) * (iset+1)) lona2 = pointa['lon2'] if lona2 < 0.: lona2 = 360. + lona2 lona_temp.append(lona2) lata_temp.append(pointa['lat2']) lonb2 = pointb['lon2'] if lonb2 < 0.: lonb2 = 360. + lonb2 lonb_temp.append(lonb2) latb_temp.append(pointb['lat2']) iwall_temp.append(iwall[i]); idl_temp.append(idl[i]); idr_temp.append(idr[i]); bound_ind_temp.append(bound_ind[i]) large_wall_inds_temp.append(large_wall_inds[i]) vt_ew_temp.append(vt_ew[i]) vt_ns_temp.append(vt_ns[i]) polarity_temp.append(polarity[i]) num_segs += iseg; if iwall[i] == 1: num_wall_segs += iseg; # # Double up wall boundaries n_segs = num_segs + num_wall_segs lona = np.zeros((n_segs)); lata = np.zeros((n_segs)) lonb = np.zeros((n_segs)); latb = np.zeros((n_segs)) vt_ew = np.zeros((n_segs)); vt_ns = np.zeros((n_segs)); polarity = np.zeros((n_segs)); iwall = [0] * n_segs; bound_ind = [0] * n_segs idl = [0] * n_segs; idr = [0] * n_segs; large_wall_inds = [0] * n_segs nwall = 0; for i in range(num_segs): lona[i] = lona_temp[i] lata[i] = lata_temp[i] lonb[i] = lonb_temp[i] latb[i] = latb_temp[i] iwall[i] = iwall_temp[i] idl[i] = idl_temp[i] idr[i] = idr_temp[i] bound_ind[i] = bound_ind_temp[i] large_wall_inds[i] = large_wall_inds_temp[i] vt_ew[i] = vt_ew_temp[i] vt_ns[i] = vt_ns_temp[i] polarity[i] = polarity_temp[i] if iwall_temp[i] == 1: lona[num_segs+nwall] = lona_temp[i] lata[num_segs+nwall] = lata_temp[i] lonb[num_segs+nwall] = lonb_temp[i] latb[num_segs+nwall] = latb_temp[i] iwall[num_segs+nwall] = iwall_temp[i] idl[num_segs+nwall] = idl_temp[i] idr[num_segs+nwall] = idr_temp[i] bound_ind[num_segs+nwall] = bound_ind_temp[i] large_wall_inds[num_segs+nwall] = large_wall_inds_temp[i] vt_ew[num_segs+nwall] = vt_ew_temp[i] vt_ns[num_segs+nwall] = vt_ns_temp[i] polarity[num_segs+nwall] = polarity_temp[i] nwall += 1; return (n_segs,num_segs,iwall,idl,idr,lona,lata,lonb,latb,bound_ind,large_wall_inds,vt_ew,vt_ns,polarity,num_wall_segs)
def add_geo_to_arrivals(arrivals, source_latitude_in_deg, source_longitude_in_deg, receiver_latitude_in_deg, receiver_longitude_in_deg, radius_of_planet_in_km, flattening_of_planet, resample=False, sampleds=5.0): """ Add geographical information to arrivals. :param arrivals: Set of taup arrivals :type: :class:`Arrivals` :param source_latitude_in_deg: Source location latitude in degrees :type source_latitude_in_deg: float :param source_longitude_in_deg: Source location longitude in degrees :type source_longitude_in_deg: float :param receiver_latitude_in_deg: Receiver location latitude in degrees :type receiver_latitude_in_deg: float :param receiver_longitude_in_deg: Receiver location longitude in degrees :type receiver_longitude_in_deg: float :param radius_of_planet_in_km: Radius of the planet in km :type radius_of_planet_in_km: float :param flattening_of_planet: Flattening of planet (0 for a sphere) :type receiver_longitude_in_deg: float :param resample: adds sample points to allow for easy cartesian interpolation. This is especially useful for phases like Pdiff. :type resample: boolean :return: List of ``Arrival`` objects, each of which has the time, corresponding phase name, ray parameter, takeoff angle, etc. as attributes. :rtype: :class:`Arrivals` """ if geodetics.HAS_GEOGRAPHICLIB: if not geodetics.GEOGRAPHICLIB_VERSION_AT_LEAST_1_34: # geographiclib is not installed ... # and obspy/geodetics does not help much msg = ("This functionality needs the Python module " "'geographiclib' in version 1.34 or higher.") raise ImportError(msg) ellipsoid = Geodesic(a=radius_of_planet_in_km * 1000.0, f=flattening_of_planet) g = ellipsoid.Inverse(source_latitude_in_deg, source_longitude_in_deg, receiver_latitude_in_deg, receiver_longitude_in_deg) azimuth = g['azi1'] line = ellipsoid.Line(source_latitude_in_deg, source_longitude_in_deg, azimuth) # We may need to update many arrival objects # and each could have pierce points and a # path for arrival in arrivals: # check if we go in minor or major arc direction distance = arrival.purist_distance % 360. if distance > 180.: sign = -1 az_arr = (azimuth + 180.) % 360. else: sign = 1 az_arr = azimuth arrival.azimuth = az_arr if arrival.pierce is not None: geo_pierce = np.empty(arrival.pierce.shape, dtype=TimeDistGeo) for i, pierce_point in enumerate(arrival.pierce): signed_dist = np.degrees(sign * pierce_point['dist']) pos = line.ArcPosition(signed_dist) geo_pierce[i] = (pierce_point['p'], pierce_point['time'], pierce_point['dist'], pierce_point['depth'], pos['lat2'], pos['lon2']) arrival.pierce = geo_pierce # choose whether we need to resample the trace if arrival.path is not None: if resample: rplanet = radius_of_planet_in_km # compute approximate distance between sampling points # mindist = 200 # km mindist = sampleds radii = rplanet - arrival.path['depth'] rmean = np.sqrt(radii[1:] * radii[:-1]) diff_dists = rmean * np.diff(arrival.path['dist']) npts_extra = np.floor(diff_dists / mindist).astype(np.int) # count number of extra points and initialize array npts_old = len(arrival.path) npts_new = int(npts_old + np.sum(npts_extra)) geo_path = np.empty(npts_new, dtype=TimeDistGeo) # now loop through path, adding extra points i_new = 0 for i_old, path_point in enumerate(arrival.path): # first add the original point at the new index dist = np.degrees(sign * path_point['dist']) pos = line.ArcPosition(dist) geo_path[i_new] = (path_point['p'], path_point['time'], path_point['dist'], path_point['depth'], pos['lat2'], pos['lon2']) i_new += 1 if i_old > npts_old - 2: continue # now check if we need to add new points npts_new = npts_extra[i_old] if npts_new > 0: # if yes, distribute them linearly between the old # and the next point next_point = arrival.path[i_old + 1] dist_next = np.degrees(sign * next_point['dist']) dists_new = np.linspace(dist, dist_next, npts_new + 2)[1:-1] # now get all interpolated parameters xs = [dist, dist_next] ys = [path_point['p'], next_point['p']] p_interp = np.interp(dists_new, xs, ys) ys = [path_point['time'], next_point['time']] time_interp = np.interp(dists_new, xs, ys) ys = [path_point['depth'], next_point['depth']] depth_interp = np.interp(dists_new, xs, ys) pos_interp = [ line.ArcPosition(dist_new) for dist_new in dists_new ] lat_interp = [ point['lat2'] for point in pos_interp ] lon_interp = [ point['lon2'] for point in pos_interp ] # add them to geo_path # dists_new --> np.radians(dists_new), modified by Hongjian Fang for i_extra in range(npts_new): geo_path[i_new] = (p_interp[i_extra], time_interp[i_extra], np.radians( dists_new[i_extra]), depth_interp[i_extra], lat_interp[i_extra], lon_interp[i_extra]) i_new += 1 arrival.path = geo_path else: geo_path = np.empty(arrival.path.shape, dtype=TimeDistGeo) for i, path_point in enumerate(arrival.path): signed_dist = np.degrees(sign * path_point['dist']) pos = line.ArcPosition(signed_dist) geo_path[i] = (path_point['p'], path_point['time'], path_point['dist'], path_point['depth'], pos['lat2'], pos['lon2']) arrival.path = geo_path else: # geographiclib is not installed ... # and obspy/geodetics does not help much msg = "You need to install the Python module 'geographiclib' in " + \ "order to add geographical information to arrivals." raise ImportError(msg) return arrivals