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
Beispiel #2
0
                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")
Beispiel #3
0
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
Beispiel #4
0
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>**