def az_decompose(hdisp, station_pos, disk_pos): # both station_pos and disk_pos are tuples compass_bearing = haversine.calculate_initial_compass_bearing(station_pos, disk_pos); azimuth = 90 - compass_bearing; xdisp = hdisp * -np.cos(azimuth * np.pi / 180); ydisp = hdisp * -np.sin(azimuth * np.pi / 180); return [xdisp, ydisp];
def latlon2xy(loni,lati,lon0,lat0): # returns the distance between a point and a reference in km. radius = haversine.distance([lat0,lon0], [lati,loni]); bearing = haversine.calculate_initial_compass_bearing((lat0, lon0),(lati, loni)) azimuth = 90 - bearing; x = radius * np.cos(np.deg2rad(azimuth)); y = radius * np.sin(np.deg2rad(azimuth)); return [x, y];
def cross_track_pos(target_lon, target_lat, nearrange_lon, nearrange_lat, heading_cartesian): # Given the heading of a plane and the coordinates of one near-range point # Get the cross-track position of point in a coordinate system centered at (nearrange_lon, nearrange_lat) with given heading distance = haversine.distance((target_lat, target_lon), (nearrange_lat, nearrange_lon)) compass_bearing = haversine.calculate_initial_compass_bearing( (nearrange_lat, nearrange_lon), (target_lat, target_lon)) # this comes as CW from north theta = bearing_to_cartesian(compass_bearing) # the angle of the position vector in cartesian coords # heading_cartesian is the angle between the east unit vector and the flight direction x0 = distance * np.cos(np.deg2rad(theta)) y0 = distance * np.sin(np.deg2rad(theta)) # in the east-north coordinate systeem x_prime, y_prime = rotate_vector_by_angle(x0, y0, heading_cartesian) return y_prime
def compute_prem_load(station_array, load_array, disk_radius, greensfunc, max_distance): # For a given station and a given set of loads, # Compute the loading on a PREM earth structure # Max distance is in degrees total_disp_x = []; total_disp_y = []; total_disp_v = []; for i in range(len(station_array.lon)): # for each station... # Take a set of rectangular loads and tile them into disk loads. CircleLoads = get_disks(load_array, disk_radius, max_distance, station_array.lon[i], station_array.lat[i]); print("Number of circles: %d" % len(CircleLoads.lon)); disk_sum_v = 0; disk_sum_x = 0; disk_sum_y = 0; for j in range(np.size(CircleLoads.lon)): dist_from_center = haversine.distance([CircleLoads.lat[j], CircleLoads.lon[j]], [station_array.lat[i], station_array.lon[i]]); # reported in km azimuth = haversine.calculate_initial_compass_bearing((station_array.lat[i], station_array.lon[i]), (CircleLoads.lat[j], CircleLoads.lon[j])); myindex = find_closest_greens(greensfunc.km, dist_from_center); # find the nearest answer in the Green's functions vdisp = greensfunc.vload[myindex]; # in m hdisp = greensfunc.hload[myindex]; # in m [xdisp, ydisp] = az_decompose(hdisp, (station_array.lat[i], station_array.lon[i]), ( CircleLoads.lat[j], CircleLoads.lon[j])); # Decompose radial into x and y components disk_sum_v = disk_sum_v + vdisp * CircleLoads.pressure[ j] * 1000 / 9.81; # THIS SHOULD BE DIVIDED BY 9.81! the PREM code already has it. Result in mm disk_sum_x = disk_sum_x + xdisp * CircleLoads.pressure[ j] * 1000 / 9.81; # THIS SHOULD BE DIVIDED BY 9.81! the PREM code already has it. Result in mm disk_sum_y = disk_sum_y + ydisp * CircleLoads.pressure[ j] * 1000 / 9.81; # THIS SHOULD BE DIVIDED BY 9.81! the PREM code already has it. Result in mm total_disp_x.append(disk_sum_x); total_disp_y.append(disk_sum_y); total_disp_v.append(disk_sum_v); return total_disp_x, total_disp_y, total_disp_v; # should exactly match length of input station_array fields.
# 2016 event event_tuples.append((40.453, -126.194)) time_list.append("2016-12-08T14:49:38.000") name_list.append("2016 M6.6") fig, axs = plt.subplots(4, 1, sharex=True, figsize=(10, 10)) fig.subplots_adjust(hspace=0) # The waveform plots xarray = [] radial = [] transverse = [] vertical = [] for i in range(len(event_tuples)): print("working on %s" % name_list[i]) back_az = haversine.calculate_initial_compass_bearing( pt_station, event_tuples[i]) t = UTCDateTime(time_list[i]) st = client.get_waveforms("NC", station, "*", "HH*", t, t + num_minutes * 60, attach_response=True) st.remove_response(output="VEL") st.rotate('NE->RT', back_azimuth=back_az) tr = st[0] # the first trace df = tr.stats.sampling_rate npts = tr.stats.npts st.filter("bandpass", freqmin=fmin, freqmax=fmax)
def compute(lonbounds, latbounds, network_search, client_search, eqlon, eqlat, starttime, endtime, fmin, fmax, num_minutes): myclient = Client(client_search) waveform_client = Client("NCEDC") # this client has more waveforms than the IRIS client. network_split = network_search.split(',') # [BK,NC,etc]. inventory = myclient.get_stations(network=network_search, starttime=starttime, endtime=endtime, minlatitude=latbounds[0], maxlatitude=latbounds[1], minlongitude=lonbounds[0], maxlongitude=lonbounds[1], level='response', channel='?H?') # ?H? means broadband. # len(inventory) is the number of networks. inventory[0] is associated with the first network code. eqtuple = (eqlat, eqlon) # this is the required order for azimuth math. namecodes = [] lons = [] lats = [] radials = [] transverses = [] verticals = [] for i in range(len(inventory)): print(inventory[i]) for i in range(len(inventory)): # for each network for j in range(len(inventory[i])): # flipping through stations new_st = [] newcount = 0 mystation = inventory[i][j] # a station object. station_dictionary = mystation.get_contents() station_name = station_dictionary['stations'][0].split(' ')[0] # if station_name != 'GASB' and station_name != 'KHMB' and station_name != 'SUTB' and station_name != 'HATC': # continue; # GET RID OF THIS LATER. print("working on %s" % station_name) all_channels = station_dictionary['channels'] print(all_channels) channel0 = all_channels[0] # the first channel in the list (not very specific). channel_id = network_split[i] + '.' + channel0 channel_type = channel_id.split('.')[-1][0:2] + "*" # something like "BH*" or "HH*" depending on what the station has. # Parameters coords = inventory.get_coordinates(channel_id) pt_station = (coords['latitude'], coords['longitude']) back_az = haversine.calculate_initial_compass_bearing( pt_station, eqtuple) print(pt_station) print(eqtuple) print(back_az) t = UTCDateTime(starttime) # Parameters # Get some waveforms print("getting waveforms:") print( "waveform_client.get_waveforms(%s, %s, *, %s, %s, attach_response=True)\n" % (network_split[i], station_name, channel_type, starttime)) try: st = waveform_client.get_waveforms(network_split[i], station_name, "*", channel_type, t, t + num_minutes * 60, attach_response=True) except: print("Could not find data for station %s. Skipping. " % (station_name)) continue if station_name == 'JCC': print( "waveform_client.get_waveforms(%s, %s, *, %s, %s, attach_response=True)\n" % (network_split[i], station_name, "HH*", starttime)) try: st = waveform_client.get_waveforms(network_split[i], station_name, "*", "HH*", t, t + num_minutes * 60, attach_response=True) except: print("Could not find data for station %s. Skipping. " % (station_name)) continue obtained_channel = [] for k in range(len(st)): obtained_channel.append(str(st[k]).split()[0]) # appends things like 'BK.YBH.00.BHE'. print("Got channels:") print(obtained_channel) # Get the data from the station, and record its amplitude. # This is the meat of the program. # Processing once we have the stream. # Vertical only stations if len(st) == 1 and obtained_channel[0][-1] == 'Z': print("Only vertical traces") st.remove_response(output="VEL") st.filter("bandpass", freqmin=fmin, freqmax=fmax) vertical = st[0] vertical_number = np.nanmax(vertical) radial_number = np.nan transverse_number = np.nan # make_plot(st, channel_id, station_name); elif len(st) == 2: if obtained_channel[0][-1] == 'Z': vertical = st[0] elif obtained_channel[1][-1] == 'Z': vertical = st[1] else: print("cannot find vertical; continuing") continue print("Only using one vertical trace") st.remove_response(output="VEL") st.filter("bandpass", freqmin=fmin, freqmax=fmax) vertical = st[0] vertical_number = np.nanmax(vertical) radial_number = np.nan transverse_number = np.nan # make_plot(st, channel_id, station_name); # Three component stations. elif len(st) == 3: # We had a weird situation where JCC.BH* didn't have the same length of data. Trying a hard-coded fix with HH*. if len(st[0].data) != len(st[1].data) or len( st[1].data) != len(st[2].data) or len( st[0].data) != len(st[2].data): print("Bad data.") try: st = waveform_client.get_waveforms( network_split[i], station_name, "*", "HH*", t, t + num_minutes * 60, attach_response=True) except: print( "Could not find HH* data for station %s. Skipping. " % (station_name)) continue # Remove the response and rotate to transverse. st.remove_response(output="VEL") st.rotate('NE->RT', back_azimuth=back_az) st.filter("bandpass", freqmin=fmin, freqmax=fmax) make_plot(st, channel_id, station_name) transverse = st[0] radial = st[1] vertical = st[2] radial_number = np.nanmax(radial) transverse_number = np.nanmax(transverse) vertical_number = np.nanmax(vertical) elif len(st) > 3: print("Have %d traces. Removing some." % len(st)) for k in range(len(st)): if '.00.' in obtained_channel[k]: newcount = newcount + 1 print("Found %d trances with .00." % newcount) if station_name == 'JCC': # JCC is so messy! if len(st) == 6: new_st.append(st[0]) new_st.append(st[2]) new_st.append(st[4]) # 2014 has 4 traces with different time spans. This isn't so great. else: print("Don't know what to do with JCC.") continue elif newcount == 3: for k in range(len(st)): if '.00.' in obtained_channel[k]: new_st.append(st[k]) else: print( "Didn't find 3 .00. channels. Don't know what to do.") continue # Remove the response and rotate to transverse. st.remove_response(output="VEL") st.rotate('NE->RT', back_azimuth=back_az) st.filter("bandpass", freqmin=fmin, freqmax=fmax) # make_plot(st,channel_id,station_name); transverse = st[0] radial = st[1] vertical = st[2] radial_number = np.nanmax(radial) transverse_number = np.nanmax(transverse) vertical_number = np.nanmax(vertical) else: print("stream is %d traces long... not sure what to do" % (len(st))) print(st) continue # Saving data for the plotting function. lons.append(coords['longitude']) lats.append(coords['latitude']) namecodes.append(station_name) transverses.append(transverse_number) radials.append(radial_number) verticals.append(vertical_number) return [namecodes, lons, lats, radials, transverses, verticals]