This will download seismic waveforms & measure waveform similarity between two data. ObsPy, numpy, scipy, matplotlib are required.
from obspy import read
from obspy import UTCDateTime
from obspy.clients.fdsn import Client
from obspy.geodetics.base import gps2dist_azimuth
from obspy.signal.rotate import rotate_ne_rt
from obspy.signal.rotate import rotate_rt_ne
from obspy.signal.rotate import rotate2zne
import obspy as ob
print("# obspy version = ",ob.__version__)
import numpy as np
import scipy as sp
import matplotlib as mp
print("# numpy version = ",np.__version__)
print("# scipy version = ",sp.__version__)
print("# matplotlib version = ",mp.__version__)
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
from scipy.fftpack import fft, ifft
from scipy import signal
from scipy.linalg import norm
from scipy import ndimage
import sys
import os
# font size
SMALL_SIZE = 16
MEDIUM_SIZE = 18
BIGGER_SIZE = 20
#SMALL_SIZE = 32
#MEDIUM_SIZE = 32
#BIGGER_SIZE = 36
plt.rc('font', size=SMALL_SIZE) # controls default text sizes
plt.rc('axes', titlesize=SMALL_SIZE) # fontsize of the axes title
plt.rc('axes', labelsize=MEDIUM_SIZE) # fontsize of the x and y labels
plt.rc('xtick', labelsize=SMALL_SIZE) # fontsize of the tick labels
plt.rc('ytick', labelsize=SMALL_SIZE) # fontsize of the tick labels
plt.rc('legend', fontsize=SMALL_SIZE) # legend fontsize
plt.rc('figure', titlesize=BIGGER_SIZE) # fontsize of the figure title
to extract seed_id from obspy stream.
def get_seedid (tr):
seedid=tr.stats.network+"."+tr.stats.station+"."+tr.stats.location+"."+tr.stats.channel
return seedid
to correct instrument response.
def st_remove_resp (st, deciopt, decifactor, pre_filt, output):
st.detrend() # remove linear trend
st.detrend("demean") # demean
st.taper(0.05) # cosin taper
if deciopt == 1:
# decimate to 100Hz
if decifactor == 100:
st.decimate(5, strict_length=False)
st.decimate(2, strict_length=False)
st.decimate(5, strict_length=False)
st.decimate(2, strict_length=False)
else:
st.decimate(factor=decifactor, strict_length=False)
st = st.remove_response(pre_filt=pre_filt,output=output,water_level=None) # get velocity data (m/s)
return st
to extract station coordinate from obspy stream.
def get_sta_coord (seedid, inv, starttime):
sta_coordinate = inv.get_coordinates(seedid, starttime)
return sta_coordinate
to extract sensor orientation from obspy stream.
def get_sta_orientation (seedid, inv, starttime):
sta_orientation = inv.get_orientation(seedid, starttime)
return sta_orientation
to rotate 3-com data into ZNE coordinate
def get_zne_data (st, inv, starttime):
st_len = len(st)
if st_len != 3:
print("# cannot do!")
sta_coordinate = []
sta_orientation = []
#for tr in st1:
for i, tr in enumerate(st, 1):
#print("# i = ",i)
seedid=get_seedid(tr)
#sta_coordinate[i] = get_sta_coord(tr, seedid, inv1, starttime)
sta_coordinate.append(get_sta_coord(seedid, inv, starttime))
sta_orientation.append(get_sta_orientation(seedid, inv, starttime))
#print("# seedid = ",seedid, sta_coordinate)
#print("# seedid = ",seedid, sta_orientation)
ztmp = st[2]
AzZ = sta_orientation[2]['azimuth']
DipZ = sta_orientation[2]['dip']
#print("# AzZ = ", AzZ, " DipZ = ", DipZ)
ntmp = st[1]
AzN = sta_orientation[1]['azimuth']
DipN = sta_orientation[1]['dip']
#print("# AzN = ", AzN, " DipN = ", DipN)
etmp = st[0]
AzE = sta_orientation[0]['azimuth']
DipE = sta_orientation[0]['dip']
#print("# AzE = ", AzE, " DipE = ", DipE)
t1z , t1n, t1e = rotate2zne(ztmp,AzZ,DipZ,ntmp,AzN,DipN,etmp,AzE,DipE)
st[0].data = t1e
st[1].data = t1n
st[2].data = t1z
#i_1.stats.channel[:-1] + \
# output_components[0]
st[0].stats.channel = st[0].stats.channel[:-1] + "E"
st[1].stats.channel = st[0].stats.channel[:-1] + "N"
st[2].stats.channel = st[0].stats.channel[:-1] + "Z"
return st
to compuete back-azimuth
def get_baz (st, inv, evla, evlo):
seedid=get_seedid(st[0])
sta_coord = get_sta_coord(seedid,inv,starttime)
stla = sta_coord['latitude']
stlo = sta_coord['longitude']
source_latitude = evla
source_longitude = evlo
station_latitude = stla
station_longitude = stlo
# theoretical backazimuth and distance
baz = gps2dist_azimuth(source_latitude, source_longitude, station_latitude, station_longitude)
#print('Epicentral distance [m]: ', baz[0])
#print('Theoretical azimuth [deg]: ', baz[1])
#print('Theoretical backazimuth [deg]: ', baz[2])
return baz
will add coherency later
def waveform_comparison (st, plotOPT):
sncl1 = get_seedid(st[0])
sncl2 = get_seedid(st[1])
#print("# sncl1 = ", sncl1)
#print("# sncl2 = ", sncl2)
plot_fi = plot_dir+"/"+sncl2+"_"+sncl1+"_"+event_para+".pdf"
#print("# plot_fi = ",plot_fi)
T1=st[0].stats.delta
N1=st[0].stats.npts
xf1 = np.linspace(0.0, 1.0/(2.0*T1), N1//2)
yf1 = fft(st[0].data)
T2=st[1].stats.delta
N2=st[1].stats.npts
xf2 = np.linspace(0.0, 1.0/(2.0*T2), N2//2)
yf2 = fft(st[1].data)
yf1_amp = 2.0/N1 * np.abs(yf1)
yf2_amp = 2.0/N2 * np.abs(yf2)
# no div N1 or N2 match sac results....
yf1_amp = 2.0/1.0 * np.abs(yf1)
yf2_amp = 2.0/1.0 * np.abs(yf2)
index_select = np.where( (fl <= xf2) & (xf2 <= fh) )
#yf1_amp_max = np.amax(yf1_amp[index_select])
#yf2_amp_max = np.amax(yf2_amp[index_select])
#print("# yf1_amp_max = ", yf1_amp_max)
#print("# yf2_amp_max = ", yf2_amp_max)
yf_amp_max = np.amax(np.concatenate((yf1_amp[index_select], yf2_amp[index_select]) ))
#print("# yf_amp_max = ", yf_amp_max)
yf_amp_min = np.amin(np.concatenate((yf1_amp[index_select], yf2_amp[index_select]) ))
#print("# yf_amp_min = ", yf_amp_min)
yf_amp_max2 = yf_amp_max * 5
yf_amp_min2 = yf_amp_min * 0.5
#set amfactor = 5
#set samaxIn = `cat depmax.out | grep depmax | awk '{print $3+0}' | head -1 | awk -v amfactor=$amfactor '{val=$1*amfactor; printf("%e\n",val); }' `
#set saminIn = `echo $samaxIn | awk '{val=$1*-1; printf("%e\n",val); }' `
#set amfactor = 0.5
#set saminIn = `cat depmin.out | grep depmin | awk '{print $3+0}' | tail -1 | awk -v amfactor=$amfactor '{val=$1*amfactor; printf("%e\n",val); }' `
yf_amp_ratio = yf2_amp / yf1_amp
#print(np.where(a < 4, -1, a))
#index200 = np.where( (190 <= periods) & (periods <= 210) )
#index_select_num = index_select.shape
#print("# index_select = ", index_select)
index_select_num = yf_amp_ratio[index_select].shape[0]
#print("# index_select_num = ", index_select_num)
#print("# yf_amp_ratio[index_select] = ", yf_amp_ratio[index_select])
amp_median = ndimage.median(yf_amp_ratio[index_select])
amp_l1 = norm(yf_amp_ratio[index_select]-amp_median, 1)/index_select_num
#print("# amp_median = ",amp_median," amp_l1 = ", amp_l1)
amp_l1_out = "{:.3f}".format(amp_l1)
amp_median_out = "{:.3f}".format(amp_median)
#print("# amp_median_out = ",amp_median_out," amp_l1_out = ", amp_l1_out)
yf1_ph = np.angle(yf1)
yf2_ph = np.angle(yf2)
yf1_ph = np.where(yf1_ph <= -np.pi, yf1_ph + 2*np.pi, yf1_ph)
yf1_ph = np.where (np.pi <= yf1_ph, yf1_ph - 2*np.pi, yf1_ph)
yf2_ph = np.where(yf2_ph <= -np.pi, yf2_ph + 2*np.pi, yf2_ph)
yf2_ph = np.where (np.pi <= yf2_ph, yf2_ph - 2*np.pi, yf2_ph)
yf_ph_diff = yf2_ph - yf1_ph
# phase diff also. need to check it later
#print("# yf_ph_diff[index_select] = ", yf_ph_diff[index_select])
#print("# max = ",np.amax(yf_ph_diff[index_select]))
yf_ph_diff = np.where(yf_ph_diff <= -np.pi, yf_ph_diff + 2*np.pi, yf_ph_diff)
yf_ph_diff = np.where (np.pi <= yf_ph_diff, yf_ph_diff - 2*np.pi, yf_ph_diff)
#print("# yf_ph_diff[index_select] = ", yf_ph_diff[index_select])
#print("# max = ",np.amax(yf_ph_diff[index_select]))
ph_median = ndimage.median(yf_ph_diff[index_select])
ph_l1 = norm(yf_ph_diff[index_select]-ph_median, 1)/index_select_num
#print("# ph_median = ",ph_median," ph_l1 = ", ph_l1)
ph_l1_out = "{:.3f}".format(ph_l1)
ph_median_out = "{:.3f}".format(ph_median)
#echo "# wmaxIn & wminIn are overwritted!"
#set wmaxIn = `cat depmax.out | grep depmax | awk '{print $3+0}' | head -1 | awk -v amfactor=$amfactor '{val=$1*amfactor; printf("%e\n",val); }' `
#set wminIn = `echo $wmaxIn | awk '{val=$1*-1; printf("%e\n",val); }' `
#echo "# wminIn = "$wminIn" wmaxIn = "$wmaxIn
yf_amp_max = np.amax(np.concatenate((yf1_amp[index_select], yf2_amp[index_select]) ))
data_all = np.concatenate((st[0].data, st[1].data) )
wf_amp_max = max(data_all.min(), data_all.max(), key=abs)
#print("# wf_amp_max = ", wf_amp_max)
wf_amp_max2 = wf_amp_max * 1.1
wf_amp_min2 = wf_amp_max2 * -1
if plotOPT:
#plt.rcParams['figure.figsize'] = 16, 16
gs = gridspec.GridSpec(3,2)
#gs = gridspec.GridSpec(6,2)
#fig = plt.figure()
fig = plt.figure(figsize=(16, 16))
#fig.text(0.41, 0.3, 'leftbottom4',ha='right')
#fig.text(0.42, 0.3, 'leftbottom5',ha='right')
#fig.text(0.34, 0.3, 'leftbottom6',ha='right')
t=fig.text(0.13, 0.86, str(fl)+"-"+str(fh)+" Hz BP filter")
t.set_bbox(dict(facecolor='white', alpha=0.7, edgecolor='white'))
t=fig.text(0.44, 0.3, "Median: "+str(amp_median_out), ha='right')
t.set_bbox(dict(facecolor='white', alpha=0.7, edgecolor='white'))
t=fig.text(0.44, 0.280, "L1 norm: "+str(amp_l1_out), ha='right')
t.set_bbox(dict(facecolor='white', alpha=0.7, edgecolor='white'))
t=fig.text(0.89, 0.160, "Median: "+str(ph_median_out), ha='right')
t.set_bbox(dict(facecolor='white', alpha=0.7, edgecolor='white'))
t=fig.text(0.89, 0.140, "L1 norm: "+str(ph_l1_out), ha='right')
t.set_bbox(dict(facecolor='white', alpha=0.7, edgecolor='white'))
#fig.text(1, 0, 'rightbottom', ha='right')
#fig.text(0, 1, 'lefttop', va='top')
#fig.text(1, 1, 'righttop', ha='right', va='top')
plt.subplots_adjust(wspace=0.4, hspace=0.4)
### waveforms
#plt.subplot(211)
plt.subplot(gs[0, :])
#plt.plot(st[0].times("matplotlib"), st[0].data*1,label=sncl1, color="red", linewidth=0.75)
#plt.xaxis_date()
plt.plot_date(st[0].times("matplotlib"), st[0].data*1, fmt='-', label=sncl1, color="red", linewidth=0.75, linestyle='solid')
plt.plot_date(st[1].times("matplotlib"), st[1].data*1, fmt='-', label=sncl2, color="blue", linewidth=0.75, linestyle='solid')
import matplotlib.dates as mdates
myFmt = mdates.DateFormatter("%D/%H:%M")
#mdates.DateFormatter("%Y-%m-%d\n%H:%M:%S")
myFmt = mdates.DateFormatter("%Y-%m-%d\n%H:%M:%S")
plt.gca().xaxis.set_major_formatter(myFmt)
plt.xlim(st[0].times("matplotlib")[0], st[0].times("matplotlib")[-1])
plt.ylim(wf_amp_min2 , wf_amp_max2 )
plt.grid()
#plt.title("Waveform comparison")
#
#Mw:7.8 ALASKA-PENINSULA
#plt.title("Origin Time:2020-07-22T06:12:44 IRIS event-id:11273635 \n Mw:7.8 ALASKA-PENINSULA ")
plt.title(event_para+" \n Origin Time:"+str(origin_time)+" USGS event-id:"+evid+" \n M"+str(evmag)+" "+event_region)
#plt.text(0.1, 0.9,'matplotlib', ha='center', va='center')
#plt.text(x, y, s, bbox=dict(facecolor='red', alpha=0.5))
#plt_pos = plt.get_position()
#fig = plt.figure()
#ax = plt.axes()
#txt = plt.text(0.1,0.5,"My text", transform = ax.transAxes)
#txt = plt.text(0.1,0.5,"My text")
plt.ylabel("Amplitude (m/s)")
#plt.xlabel("Time")
plt.legend(loc = "upper right")
#plt.legend(loc="upper left")
### waveforms
### amplitude spectra
#plt.subplot(313)
plt.subplot(gs[1,0])
plt.plot(xf1, (yf1_amp[0:N1//2]), label=sncl1, color="red", linewidth=0.75)
plt.plot(xf2, (yf2_amp[0:N2//2]), label=sncl2, color="blue", linewidth=0.75)
plt.xlim(fl,fh)
plt.ylim(yf_amp_min2, yf_amp_max2)
plt.grid()
#plt.rc('axes.formatter', useoffset=False)
#plset_major_formatter(mticker.ScalarFormatter())
#ax.ticklabel_format(useOffset=False, style='plain')
#matplotlib.pyplot.ticklabel_format(*, axis='both', style='', scilimits=None, useOffset=None, useLocale=None, useMathText=None)
#plt.ticklabel_format(useOffset=False, style='plain')
#plt.ticklabel_format(style='sci', axis='y', scilimits=(0,0))
#plt.ticklabel_format(style='plain', axis='x', scilimits=(0,0))
plt.yscale("log")
#plt.xscale("log")
#plt.ticklabel_format(style='sci', axis='y', scilimits=(0,0))
#plt.ticklabel_format(style='plain', axis='x', scilimits=(0,0))
plt.title("Amplitude spectra")
plt.ylabel("Amplitude (m$^2$/s$^2$/Hz)")
plt.xlabel("Frequency (Hz)")
plt.legend(loc = "upper right")
### amplitude spectra
### phase spectra
plt.subplot(gs[1,1])
plt.plot(xf1, (yf1_ph[0:N1//2]), label=sncl1, color="red", linewidth=0.75)
plt.plot(xf2, (yf2_ph[0:N2//2]), label=sncl2, color="blue", linewidth=0.75)
plt.xlim(fl,fh)
plt.ylim(-4,4)
plt.grid()
#plt.yscale("log")
#plt.xscale("log")
plt.title("Phase spectra")
plt.ylabel("Phase (rad)")
plt.xlabel("Frequency (Hz)")
plt.legend(loc = "upper right")
### phase spectra
### amplitude ratio
plt.subplot(gs[2,0])
plt.plot(xf1, (yf_amp_ratio[0:N1//2]), color="black", linewidth=0.75)
plt.plot([fl, fh], [amp_median, amp_median], color="black", linewidth=1.25, linestyle="dashed")
plt.xlim(fl,fh)
plt.ylim(0.5,1.5)
plt.grid()
#plt.yscale("log")
#plt.xscale("log")
plt.title("Spectral amplitude ratio")
plt.ylabel("Amp. ("+sncl2+"/"+sncl1+")")
plt.xlabel("Frequency (Hz)")
#plt.legend()
### amplitude ratio
### phase diff
plt.subplot(gs[2,1])
plt.plot(xf1, (yf_ph_diff[0:N1//2]), color="black", linewidth=0.75)
plt.plot([fl, fh], [ph_median, ph_median], color="black", linewidth=1.25, linestyle="dashed")
plt.xlim(fl,fh)
plt.ylim(-1.0,1.0)
#plt.ylim(-7.0,7.0)
plt.grid()
#plt.yscale("log")
#plt.xscale("log")
plt.title("Difference in spectral phase")
plt.ylabel("Phase ("+sncl2+"-"+sncl1+")")
plt.xlabel("Frequency (Hz)")
#plt.legend()
### phase diff
plt.savefig(plot_fi)
This example uses USGS. We can use other dataceneter (e.g., NCEDC, IRIS)
#clientEQ = Client("IRIS")
clientEQ = Client("USGS")
Set time window (st, et) and a range of magunitude (minmag, maxmag). This example will find the 22 July 2020 M 7.8 Alaska event.
#M 7.8 - Alaska Peninsula
#2020-07-22 06:12:44 (UTC)55.068°N 158.554°W28.0 km depth
#https://earthquake.usgs.gov/earthquakes/eventpage/us7000asvb/executive
st = UTCDateTime("2020-07-22T00:00:00") #
et = UTCDateTime("2020-07-23T00:00:00") #
minmag = 7.0
maxmag = 9.9
catalog = clientEQ.get_events(starttime=st , endtime=et,
minmagnitude=minmag, maxmagnitude=maxmag)
print(catalog)
_plot = catalog.plot()
# event info. origin time, location, magnitude
event = catalog[0]
origin = event.origins[0]
origin_time = origin.time
evla = origin.latitude
evlo = origin.longitude
evdp_km = origin.depth / 1000
evmag = event.magnitudes[0].mag
evyearOUT = origin_time.year
evjdayOUT = origin_time.julday
evhourOUT = origin_time.hour
evminOUT = origin_time.minute
evsecOUT = origin_time.second
evid = event.origins[0]['extra']['dataid']['value']
event_region = event.event_descriptions[0]['text']
# need for file name
evyearOUT2 = (str)(evyearOUT)
evjdayOUT2 = (str)(evjdayOUT)
if evjdayOUT < 100:
evjdayOUT2 = "0"+(str)(evjdayOUT)
if evjdayOUT < 10:
evjdayOUT2 = "00"+(str)(evjdayOUT)
evhourOUT2 = (str)(evhourOUT)
if evhourOUT < 10:
evhourOUT2 = "0"+(str)(evhourOUT)
evminOUT2 = (str)(evminOUT)
if evminOUT < 10:
evminOUT2 = "0"+(str)(evminOUT)
evsecOUT2 = (str)(evsecOUT)
if evsecOUT < 10:
evsecOUT2 = "0"+(str)(evsecOUT)
#print("# evyearOUT2 = ",evyearOUT2," evjdayOUT2 = ",evjdayOUT2," evhourOUT2 = ",evhourOUT2," evminOUT2 = ",evminOUT2," evsecOUT2 = ",evsecOUT2)
evmseedid = evyearOUT2+"."+evjdayOUT2+"."+evhourOUT2+""+evminOUT2+""+evsecOUT2
#print("# evmseedid = "+evmseedid)
event_para = evmseedid +"_M"+(str)(evmag)+"_"+(str)(evid)
This example will create directory "2020.204.061244_M7.8_us7000asvb" where all plots will be saved.
# name for output directory
pwd_dir = os.getcwd()
#sacdir= pwd_dir +"/"+ evmseedid +"_M"+(str)(evmag)+"_"+(str)(eventid_ncedc)+"_fl"+(str)(f2)+"_fh"+str(f3)+"_dist"+(str)(distkm_from_eq)+"km"
#plot_dir= pwd_dir +"/"+ evmseedid +"_M"+(str)(evmag)+"_"+(str)(evid)
#+"_fl"+(str)(f2)+"_fh"+str(f3)+"_dist"+(str)(distdeg_from_eq)+"deg"
plot_dir= pwd_dir +"/"+ event_para
print("# plot_dir = ",plot_dir)
# create output directory
if not os.path.exists(plot_dir):
os.makedirs(plot_dir)
This example extracts 90-min data for the 2020 M 7.8 Alaska earthquake
pre_tw = 0 # 0s if this is -10, then data from -10s from the origin time
stw = 90*60 # 90 min from the starting time (oriting_time + pre_tw)
starttime = origin_time + pre_tw
endtime = starttime + stw
#print("# starttime = ",starttime)
Which SNCL (Station, Network, Component, Location) we will use? sta1,net1,com1,loc1 for the target data, sta2,net2,com2,loc2 for the reference data.
sta1 = "BRK" # station
net1 = "BK" # network
com1 = "HH?" # component "HH?" to get all 3-com data from broadband sensor
loc1 = "00" # location
deciopt_1 = 1
#decifactor_1 = 100 # 100sps -> 1sps
decifactor_1 = 10 # 100sps -> 10 sps
client1 = Client("NCEDC") # data from NCEDC
sta2 = "BRK" # station
net2 = "BK" # network
com2 = "HN?" # component "HN?" to get all 3-com data from strong-motion sensor
loc2 = "00" # location
deciopt_2 = 1
#decifactor_2 = 100
decifactor_2 = 10
client2 = Client("NCEDC") # data from IRIS
Rvel = 4.2 # surface wave velocity (km/s)
tw_pre_tw = -500 # sec before Rwave_arrival
tw_trim = 2000 # 2000-s window length
set the frequency range (fl and fh) for waveform similarity analysis. This example will use 0.02-0.10 Hz band. Also this will use for pre-filter when we correct the instrument response.
#fl2 < fl < fh < fh2
fl2 = 0.01 # Hz
fl = 0.02 # Hz
fh = 0.10 # Hz
fh2 = 0.20 # Hz
#pre_filt = [0.015, 0.02, 45, 50]
pre_filt = [fl2, fl, fh, fh2]
use get_waveforms to download data and do st.plot() for plotting. Also use get_stsations to obtation station inventory file.
st1 = client1.get_waveforms(network=net1, station=sta1, location=loc1, channel=com1,
starttime=starttime, endtime=endtime,
attach_response=True)
inv1 = client1.get_stations(network=net1, station=sta1, location=loc1, channel=com1,
starttime=starttime, endtime=endtime,
level="response")
_plot = st1.plot(size=(1000,600))
#_plot = st1.plot()
st2 = client2.get_waveforms(network=net2, station=sta2, location=loc2, channel=com2,
starttime=starttime, endtime=endtime,
attach_response=True)
# for station locations
inv2 = client2.get_stations(network=net2, station=sta2, location=loc2, channel=com2,
starttime=starttime, endtime=endtime,
level="response")
_plot = st2.plot(size=(1000,600))
use st_remove_resp function uses obspy remove_response to remove instrument response. Example will provide ground velocity data (m/s)
st1 = st_remove_resp(st1, deciopt_1, decifactor_1, pre_filt, "VEL")
_plot = st1.plot(size=(1000,600))
st2 = st_remove_resp(st2, deciopt_2, decifactor_2, pre_filt, "VEL")
_plot = st2.plot(size=(1000,600))
use get_zne_data. This will provide ZNE coordinate data.
st1_zne = st1.copy()
st1_zne = get_zne_data (st1_zne, inv1, starttime)
_plot = st1_zne.plot(size=(1000,600))
st2_zne = st2.copy()
st2_zne = get_zne_data (st2_zne, inv2, starttime)
_plot = st2_zne.plot(size=(1000,600))
get_baz to esimate the back azimuth and then use obspy rotate to covert ZNE data into ZRT data
baz1 = get_baz(st1, inv1, evla, evlo)
st1_zrt = st1_zne.copy()
st1_zrt.rotate(method='NE->RT',back_azimuth=baz1[2])
_plot = st1_zrt.plot(size=(1000,600))
baz2 = get_baz(st2, inv2, evla, evlo)
st2_zrt = st2_zne.copy()
st2_zrt.rotate(method='NE->RT',back_azimuth=baz2[2])
_plot = st2_zrt.plot(size=(1000,600))
st_all includ all ZNERT data from two stations
#st_all = st2_zrt.copy() + st1_zrt.copy()
st_all = st2_zrt.copy() + st2_zne.select(component="E") + st2_zne.select(component="N") + st1_zrt.copy() + st1_zne.select(component="E") + st1_zne.select(component="N")
event ditance / Rvel (This example uses 4.2 km/s)
Rwave_arrival = baz2[0]/1000.0/Rvel
#print("# Rwave_arrival = ",Rwave_arrival)
tw_start = origin_time + Rwave_arrival + tw_pre_tw
tw_end = tw_start + tw_trim
#st_select.trim(dt, dt + tw_trim)
st_all.trim(tw_start, tw_end)
st_all.detrend() # remove linear trend
st_all.detrend("demean") # demean
st_all.taper(0.05)
_plot = st_all.plot(size=(1000,1000))
This example will use transverse component data
select_channel = "T"
#select_channel = ["N", "E" , "T", "R", "Z" ]
#select_channel = ["Z", "T", "R"]
for component in select_channel:
st_select = st_all.select(component=component)
waveform_comparison(st_select, 1)
#print(st_select)