def get_radial_transverse(self): """ Performs radial transverse rotation. Returns: radial_transverse: StationStream with the radial and transverse components. """ st_copy = self.rotation_data.copy() st_n = st_copy.select(component="[N1]") st_e = st_copy.select(component="[E2]") # Check that we have one northing and one easting channel if len(st_e) != 1 or len(st_n) != 1: raise Exception( "Radial_Transverse: Stream must have one north and one east channel." ) # Check that the orientations are orthogonal ho1 = st_e[0].stats.standard.horizontal_orientation ho2 = st_n[0].stats.standard.horizontal_orientation if abs(ho1 - ho2) not in [90, 270]: raise Exception("Radial_Transverse: Channels must be orthogonal.") # Check that the lengths of the two channels are the same if st_e[0].stats.npts != st_n[0].stats.npts: raise Exception( "Radial_Transverse: East and north channels must have same length." ) # First, rotate to North-East components if not already if st_n[0].stats.standard.horizontal_orientation != 0: az_diff = 360 - st_n[0].stats.standard.horizontal_orientation az_diff = np.deg2rad(az_diff) rotation_matrix = np.array([ [np.cos(az_diff), np.sin(az_diff)], [-np.sin(az_diff), np.cos(az_diff)], ]) data = np.array([st_n[0].data, st_e[0].data]) newdata = np.matmul(rotation_matrix, data) st_n[0].data = newdata[0] st_e[0].data = newdata[1] st_n[0].stats.channel = st_n[0].stats.channel[:-1] + "N" st_e[0].stats.channel = st_n[0].stats.channel[:-1] + "E" # For some reason the rotation does not update the channel # name in the rotation if it is not an obspy stream ne_stream = Stream([st_n[0], st_e[0]]) # Calculate back azimuth and perform rotation to radial and transverse baz = gps2dist_azimuth( st_e[0].stats.coordinates.latitude, st_e[0].stats.coordinates.longitude, self.event.latitude, self.event.longitude, )[1] ne_stream.rotate(method="NE->RT", back_azimuth=baz) radial_transverse = StationStream([ne_stream[0], ne_stream[1]]) return radial_transverse
try: #search for N/1 channel with high-frequency response inv=irisclient.get_stations(starttime=starttime,endtime=endtime,station=st,level="channel",channel="BHN,BH1,HHN,HH1,SHN,SH1") #find appropriate channels in the inventory (ASDF returns list, not inventory type) chan=inv.get_contents()['channels'][0].split('.') stream=irisclient.get_waveforms(chan[0],chan[1],chan[2],chan[3],starttime,endtime) wf1=stream[0] if wf1.stats['channel'][-1] == '1': wf2=irisclient.get_waveforms(chan[0],chan[1],chan[2],chan[3][0:-1]+'2',starttime,endtime)[0] wfz=irisclient.get_waveforms(chan[0],chan[1],chan[2],chan[3][0:-1]+'Z',starttime,endtime)[0] stream=Stream(traces=[wfz,wf1,wf2]) #get an inventory including the Z and E/2 channels IRISinv=irisclient.get_stations(starttime=starttime,endtime=endtime,station=st,level="channel") stream=stream.rotate(method="->ZNE",inventory=IRISinv) else: wf2=irisclient.get_waveforms(chan[0],chan[1],chan[2],chan[3][0:-1]+'E',starttime,endtime)[0] stream=Stream(traces=[wf1,wf2]) stream=stream.rotate(method="NE->RT",back_azimuth=baz) wf=None for trywf in stream: if trywf.stats['channel'][-1]=='T': wf=trywf break if wf and len(wf)>100: wf.resample(100) wf.detrend() wf.normalize() wf.write(saveDir+str(wfctr)+'_S.pkl',format="PICKLE")
def _getData(pick, fds, ic): if pick[0][0] == '#': #this line is commented return None net = pick[6] st = pick[7] ch = pick[8] time = UTCDateTime(float(pick[9])) starttime = time - 20 endtime = time + 40 if ch == '00T': baz = float(pick[14]) #get all the horizontal short-period channels at loc '00' or '' (assuming the 00 in 00T refers to #loc) try: inv = fds.get_stations(starttime, endtime, network=net, station=st) #find appropriate channels in the inventory (ASDF returns list, not inventory type) for chan in inv: if re.search('^[HBS].[N1]$', chan[3]): break if not re.search('^[HBS].[N1]$', chan[3]): raise Exception('no appropriate horizontal channels found') stream = fds.get_waveforms(net, st, chan[2], chan[3], starttime, endtime) wf1 = stream[0] if wf1.stats['channel'][-1] == '1': wf2 = fds.get_waveforms(net, st, chan[2], chan[3][0:-1] + '2', starttime, endtime)[0] wfz = fds.get_waveforms(net, st, chan[2], chan[3][0:-1] + 'Z', starttime, endtime)[0] stream = Stream(traces=[wfz, wf1, wf2]) #this is a necessary hack - ASDF inventories do not have orientation data for #the 1 and 2 channels so it is impossible to rotate to ZNE accurately. Therefore #we get station data off IRIS. All the OA installations have ZNE data provided, #so only the permanent stations need to rotate 12->NE, and being permanent they should #have metadata available through IRIS. IRISinv = ic.get_stations(network=net, station=st, channel=ch, level="channel") stream = stream.rotate(method="->ZNE", inventory=IRISinv) else: wf2 = fds.get_waveforms(net, st, chan[2], chan[3][0:-1] + 'E', starttime, endtime)[0] stream = Stream(traces=[wf1, wf2]) except Exception as e: #handle data missing print >> sys.stderr, e stream = None wf = None if stream: try: stream = stream.rotate(method='NE->RT', back_azimuth=baz) for trywf in stream: if trywf.stats['channel'][-1] == 'T': wf = trywf break except Exception as e: print >> sys.stderr, e wf = None else: try: #just grab the channel that the pick was on inv = fds.get_stations(starttime, endtime, network=net, station=st, channel=ch) loc = inv[0][2] wf = fds.get_waveforms(net, st, loc, ch, starttime, endtime)[0] except Exception as e: print >> sys.stderr, e wf = None if wf and len(wf) > 100: wf.resample(100) wf.detrend() wf.normalize() return wf.data else: print >> sys.stderr, 'Waveform not found. Skipping pick...' return None
def _getData(pick,fds,mintime): if pick[0][0]=='#': #this line is commented return None net=pick[6] st=pick[7] ch=pick[8] time=UTCDateTime(float(pick[9])) if mintime: if time < mintime: return None starttime=time-20 endtime=time+40 if ch=='00T': baz=float(pick[14]) #get all the horizontal short-period channels at loc '00' or '' (assuming the 00 in 00T refers to #loc) try: inv=fds.get_stations(starttime,endtime,network=net,station=st) #find appropriate channels in the inventory (ASDF returns list, not inventory type) for chan in inv: if re.search('^[HBS].[N1]$',chan[3]): break if not re.search('^[HBS].[N1]$',chan[3]): raise Exception('no appropriate horizontal channels found') stream=fds.get_waveforms(net,st,chan[2],chan[3],starttime,endtime) wf1=stream[0] wf2=fds.get_waveforms(net,st,chan[2],chan[3][0:-1]+'E',starttime,endtime)[0] #this is a hack and wrong. Hopefully 1 and 2 are only off from N and E by a few degrees max wf1.id=wf1.id[:-1]+'N' wf2.id=wf2.id[:-1]+'E' stream=Stream(traces=[wf1,wf2]) except Exception as e: #handle data missing print >> sys.stderr, e stream=None wf=None if stream: try: stream=stream.rotate(method='NE->RT',back_azimuth=baz) for trywf in stream: if trywf.stats['channel'][-1]=='T': wf=trywf break except Exception as e: print >>sys.stderr, e wf=None else: try: #just grab the channel that the pick was on inv=fds.get_stations(starttime,endtime,network=net,station=st,channel=ch) loc=inv[0][2] wf=fds.get_waveforms(net,st,loc,ch,starttime,endtime)[0] except Exception as e: print >> sys.stderr, e wf=None if wf and len(wf)>100: wf.resample(100) wf.detrend() wf.normalize() return wf.data else: print >> sys.stderr, 'Waveform not found. Skipping pick...' return None
station_longitude = 12.8782 # 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]) # rotate E-N component seismometer recordings to radial[1]-transverse[0] components using the theoretical BAz AC_original = AC.copy() #normalize AC_original.normalize() RLAS.normalize() AC.normalize() AC.rotate(method='NE->RT',back_azimuth=baz[2]) sampling_rate = int(RLAS[0].stats.sampling_rate) time = np.linspace(0, len(AC[0].data)/sampling_rate,len(AC[0].data)) # **Estimate correlation coefficients for different time windows and estimate BAZ** # In[5]: TauPy_model = TauPyModel('ak135') arrivals_p = TauPy_model.get_travel_times(distance_in_degree=0.001 * baz[0] / 111.11, source_depth_in_km=event.origins[0].depth*0.001, phase_list=["P","p","Pdiff","PP","PKiKP","PKIKP","Pn","Pg"])
print('Epicentral distance [m]: ', baz[0]) print('Theoretical azimuth [deg]: ', baz[1]) print('Theoretical backazimuth [deg]: ', baz[2]) # - # We now rotate the E-N component seismometer recordings to radial [0] and transverse [1] acceleration using the theoretical BAz.<br> # # In a last step the normalized **transverse acceleration** is plotted together with <font color='red'>**vertical rotation rate**</font>. # + from obspy.signal.rotate import rotate_ne_rt import numpy as np # rotate AC.rotate(method='NE->RT',back_azimuth=baz[2]) plt.figure(figsize=(15,2)) ax = plt.subplot(111) ax.plot(RLAS[0].times(), RLAS[0].data/np.max(np.abs(RLAS[0].data)), 'r', label='vertical rotation rate') ax.plot(AC[0].times(), AC[0].data/np.max(np.abs(AC[0].data)), 'k', label='transverse acceleration') ax.legend(loc=2, prop={"size":12}) ax.set_xlabel('time [s]') ax.set_ylabel('normalized amplitude') ax.set_xlim(0,max(RLAS[0].times())) plt.show() # - # **<big>Note: the vertical rotation rate and transverse acceleration are in phase!</big>**