Пример #1
0
    def search_inc(self, bazi):
        inc_range = np.arange(0.1, 90, 0.1)
        s_range = self.trim(20, 20, isreturn=True)
        power = np.zeros(inc_range.shape[0])
        for i in range(len(inc_range)):
            l_comp, _, _ = rotate_zne_lqt(s_range[2].data, s_range[1].data,
                                          s_range[0].data, bazi, inc_range[i])
            power[i] = np.mean(l_comp**2)

        real_inc_idx = np.argmin(power)
        real_inc = inc_range[real_inc_idx]
        self.inc_correction = real_inc - self.inc
        self.inc = real_inc
Пример #2
0
 def test_rotate_zne_lqt_vs_pitsa(self):
     """
     Test LQT component rotation against PITSA. Test back-rotation.
     """
     # load test files
     with gzip.open(os.path.join(self.path, 'rjob_20051006.gz')) as f:
         data_z = np.loadtxt(f)
     with gzip.open(os.path.join(self.path, 'rjob_20051006_n.gz')) as f:
         data_n = np.loadtxt(f)
     with gzip.open(os.path.join(self.path, 'rjob_20051006_e.gz')) as f:
         data_e = np.loadtxt(f)
     # test different backazimuth/incidence combinations
     for ba, inci in ((60, 130), (210, 60)):
         # rotate traces
         data_l, data_q, data_t = \
             rotate_zne_lqt(data_z, data_n, data_e, ba, inci)
         # rotate traces back to ZNE
         data_back_z, data_back_n, data_back_e = \
             rotate_lqt_zne(data_l, data_q, data_t, ba, inci)
         # load pitsa files
         with gzip.open(os.path.join(self.path,
                                     'rjob_20051006_q_%sba_%sinc.gz' %
                                     (ba, inci))) as f:
             data_pitsa_q = np.loadtxt(f)
         with gzip.open(os.path.join(self.path,
                                     'rjob_20051006_t_%sba_%sinc.gz' %
                                     (ba, inci))) as f:
             data_pitsa_t = np.loadtxt(f)
         with gzip.open(os.path.join(self.path,
                                     'rjob_20051006_l_%sba_%sinc.gz' %
                                     (ba, inci))) as f:
             data_pitsa_l = np.loadtxt(f)
         # Assert the output. Has to be to rather low accuracy due to
         # rounding error prone rotation and single precision value.
         self.assertTrue(
             np.allclose(data_l, data_pitsa_l, rtol=1E-3, atol=1E-5))
         self.assertTrue(
             np.allclose(data_q, data_pitsa_q, rtol=1E-3, atol=1E-5))
         self.assertTrue(
             np.allclose(data_t, data_pitsa_t, rtol=1E-3, atol=1E-5))
         self.assertTrue(
             np.allclose(data_z, data_back_z, rtol=1E-3, atol=1E-5))
         self.assertTrue(
             np.allclose(data_n, data_back_n, rtol=1E-3, atol=1E-5))
         self.assertTrue(
             np.allclose(data_e, data_back_e, rtol=1E-3, atol=1E-5))
Пример #3
0
    def search_inc(self, bazi):
        inc_range = np.arange(0.1, 90, 0.1)
        # bazi_range = np.repeat(bazi, len(inc_range))
        # M_all = seispy.geo.rot3D(bazi=bazi_range, inc=inc_range)
        # ZEN = np.array([self.rf[2].data, self.rf[0].data, self.rf[1].data])
        s_range = self.trim(10, 10, phase='S', isreturn=True)
        # LQT_all = np.zeros([ZEN.shape[0], ZEN.shape[1], M_all.shape[2]])
        power = np.zeros(inc_range.shape[0])
        for i in range(len(inc_range)):
            # LQT_all[:, :, i] = M_all[:, :, i].dot(ZEN)
            l_comp, _, _ = rotate_zne_lqt(s_range[2].data, s_range[1].data, s_range[0].data, bazi, inc_range[i])
            power[i] = np.mean(l_comp ** 2)

        # real_inc_idx = seispy.geo.extrema(power, opt='min')
        real_inc_idx = np.argmin(power)
        # print(real_inc_idx)
        real_inc = inc_range[real_inc_idx]
        return real_inc
Пример #4
0
    def test_rotate2zne_against_lqt(self):
        np.random.seed(789)
        z = np.random.random(10)
        n = np.random.random(10)
        e = np.random.random(10)

        bas = [0.0, 14.325, 38.234, 78.1, 90.0, 136.3435, 265.4, 180.0,
               351.35, 360.0]
        incs = [0.0, 10.325, 32.23, 88.1, 90.0, 132.3435, 245.4, 180.0,
                341.35, 360.0]

        for ba, inc in itertools.product(bas, incs):
            l, q, t = rotate_zne_lqt(z=z, n=n, e=e, ba=ba, inc=inc)

            dip_l = (inc % 180.0) - 90.0
            if 180 <= inc < 360:
                dip_l *= -1.0

            dip_q = ((inc + 90) % 180) - 90
            if 0 < inc < 90 or 270 <= inc < 360:
                dip_q *= -1.0

            az_l = ba + 180.0
            az_q = ba

            # Azimuths flip depending on the incidence angle.
            if inc > 180:
                az_l += 180
            if 90 < inc <= 270:
                az_q += 180

            z_new, n_new, e_new = rotate2zne(l, az_l, dip_l,
                                             q, az_q, dip_q,
                                             t, ba + 270, 0)
            np.testing.assert_allclose(z_new, z)
            np.testing.assert_allclose(n_new, n)
            np.testing.assert_allclose(e_new, e)
Пример #5
0
   def get_P_rf(self, window_start=-10.0, window_end=100.0,
                      wl = 0.1,  rotation_method = 'RTZ', 
                      type = 'earth_model',plot = False,
                      decon_type='water_level'):

       self.window_start = window_start
       self.window_end   = window_end

       #initialize receiver function time series
       len_s    = self.window_end - self.window_start
       len_i    = int(len_s/self.ses3d_seismogram.dt)

       if(type == 'earth_model'):

          model = TauPyModel(model='pyrolite_5km')
          tt = model.get_travel_times(source_depth_in_km = self.eq_depth,
                                  distance_in_degree = self.delta_deg,
                                  phase_list=["P","P660s"])

          #just in case there's more than one phase arrival, loop through tt list
          for i in range(0,len(tt)):
             if tt[i].name == 'P':
                p_wave_arrival = tt[i].time
                p_i             = int(p_wave_arrival / self.ses3d_seismogram.dt)
             elif tt[i].name == 'P660s':
                self.slowness = tt[i].ray_param * (np.pi/180.0)

       
       elif(type == 'toy_model'):
          p_i = np.argmax(self.ses3d_seismogram.trace_z)
          p_wave_arrival = p_i * self.ses3d_seismogram.dt

       #window seismograms to [P-window_start : P+window_end] 
       wi_start   = int((p_wave_arrival+window_start)/self.ses3d_seismogram.dt) 
       wi_end     = int((p_wave_arrival+window_end)/self.ses3d_seismogram.dt)  
       trace_x_windowed = self.ses3d_seismogram.trace_x[wi_start:wi_end]
       trace_y_windowed = self.ses3d_seismogram.trace_y[wi_start:wi_end]
       trace_z_windowed = self.ses3d_seismogram.trace_z[wi_start:wi_end]

       #find incidence angle from P wave amplitudes. first rotate to rtz
       r_here, t_here  = rotate.rotate_ne_rt(trace_x_windowed, trace_y_windowed, self.back_az)
       z_here          = trace_z_windowed
       r_amp           = np.amax(r_here)
       z_amp           = np.amax(z_here)
       incidence_angle = np.arctan(r_amp/z_amp) * (180/np.pi)

       #rotate
       if rotation_method == 'RTZ':
          self.r, self.t = rotate.rotate_ne_rt(trace_x_windowed,
                                               trace_y_windowed,
                                               self.back_az)
          self.z         = trace_z_windowed
       elif rotation_method == 'LQT' and type == 'earth_model':
          self.z, self.r, self.t = rotate.rotate_zne_lqt(trace_z_windowed,
                                                         trace_x_windowed,
                                                         trace_y_windowed,
                                                         self.back_az,
                                                         incidence_angle)
       elif rotation_method == 'LQT' and type == 'toy_model':
          raise ValueError('rotation method LQT not implemented for type : toy_model')

       #deconvolve Z (apprx. P wave pulse) from R
       self.time = np.linspace(window_start, window_end, len(self.r))
       if decon_type == 'water_level':
          self.prf  = water_level(self.r,self.z,wl)
       elif decon_type == 'damped_lstsq':
          self.prf  = damped_lstsq(self.r,self.z,damping=0.001)

       #plot the two waveforms being deconvolved
       if plot == True:
          plt.plot(self.time, self.r)
          plt.plot(self.time, self.z)

       if decon_type=='water_level':
          #center of the receiver function on the P arrival
          spike       = np.exp((-1.0*(self.time)**2)/0.1)
          spike_omega = np.fft.fft(spike)
          prf_omega   = np.fft.fft(self.prf)
          prf_shifted = spike_omega*prf_omega
          self.prf    = np.real(np.fft.ifft(prf_shifted))

       #normalize
       self.prf /= self.prf.max()
       if rotation_method=='LQT':
          self.prf *= -1.0
Пример #6
0
    def test_rotate2zne_against_lqt_different_combinations(self):
        np.random.seed(101112)
        z = np.random.random(10)
        n = np.random.random(10)
        e = np.random.random(10)

        # Exclude coordinate axis.
        bas = [14.325, 38.234, 78.1, 136.3435, 265.4, 351.35]
        incs = [10.325, 32.23, 88.1, 132.3435, 245.4, 341.35]

        success_count = 0
        failure_count = 0

        for ba, inc in itertools.product(bas, incs):
            l, q, t = rotate_zne_lqt(z=z, n=n, e=e, ba=ba, inc=inc)

            dip_l = (inc % 180.0) - 90.0
            if 180 <= inc < 360:
                dip_l *= -1.0

            dip_q = ((inc + 90) % 180) - 90
            if 0 < inc < 90 or 270 <= inc < 360:
                dip_q *= -1.0

            az_l = ba + 180.0
            az_q = ba

            # Azimuths flip depending on the incidence angle.
            if inc > 180:
                az_l += 180
            if 90 < inc <= 270:
                az_q += 180

            _z = [z, 0, -90, "Z"]
            _n = [n, 0, 0, "N"]
            _e = [e, 90, 0, "E"]
            _l = [l, az_l, dip_l, "L"]
            _q = [q, az_q, dip_q, "Q"]
            _t = [t, ba + 270, 0, "T"]

            # Any three of them (except three horizontal ones) should be
            # able to reconstruct ZNE.
            for a, b, c in itertools.permutations([_l, _q, _t, _z, _n, _e], 3):

                # Three horizontal components are linearly dependent, as are
                # Z, Q, and L.
                if a[2] == b[2] == c[2] == 0 or \
                        set([_i[3] for _i in (a, b, c)]) == \
                        set(["Z", "Q", "L"]):
                    with self.assertRaises(ValueError) as err:
                        rotate2zne(a[0], a[1], a[2],
                                   b[0], b[1], b[2],
                                   c[0], c[1], c[2])
                    self.assertTrue(err.exception.args[0].startswith(
                        "The given directions are not linearly independent, "
                        "at least within numerical precision. Determinant of "
                        "the base change matrix:"))
                    failure_count += 1
                    continue

                z_new, n_new, e_new = rotate2zne(a[0], a[1], a[2],
                                                 b[0], b[1], b[2],
                                                 c[0], c[1], c[2])
                np.testing.assert_allclose(z_new, z)
                np.testing.assert_allclose(n_new, n)
                np.testing.assert_allclose(e_new, e)
                success_count += 1
        # Make sure it actually tested all combinations.
        self.assertEqual(success_count, 3888)
        # Also the linearly dependent variants.
        self.assertEqual(failure_count, 432)
Пример #7
0
    def get_P_rf(self,
                 window_start=-10.0,
                 window_end=100.0,
                 wl=0.1,
                 rotation_method='RTZ',
                 type='earth_model',
                 plot=False,
                 decon_type='water_level'):

        self.window_start = window_start
        self.window_end = window_end

        #initialize receiver function time series
        len_s = self.window_end - self.window_start
        len_i = int(len_s / self.ses3d_seismogram.dt)

        if (type == 'earth_model'):

            model = TauPyModel(model='pyrolite_5km')
            tt = model.get_travel_times(source_depth_in_km=self.eq_depth,
                                        distance_in_degree=self.delta_deg,
                                        phase_list=["P", "P660s"])

            #just in case there's more than one phase arrival, loop through tt list
            for i in range(0, len(tt)):
                if tt[i].name == 'P':
                    p_wave_arrival = tt[i].time
                    p_i = int(p_wave_arrival / self.ses3d_seismogram.dt)
                elif tt[i].name == 'P660s':
                    self.slowness = tt[i].ray_param * (np.pi / 180.0)

        elif (type == 'toy_model'):
            p_i = np.argmax(self.ses3d_seismogram.trace_z)
            p_wave_arrival = p_i * self.ses3d_seismogram.dt

        #window seismograms to [P-window_start : P+window_end]
        wi_start = int(
            (p_wave_arrival + window_start) / self.ses3d_seismogram.dt)
        wi_end = int((p_wave_arrival + window_end) / self.ses3d_seismogram.dt)
        trace_x_windowed = self.ses3d_seismogram.trace_x[wi_start:wi_end]
        trace_y_windowed = self.ses3d_seismogram.trace_y[wi_start:wi_end]
        trace_z_windowed = self.ses3d_seismogram.trace_z[wi_start:wi_end]

        #find incidence angle from P wave amplitudes. first rotate to rtz
        r_here, t_here = rotate.rotate_ne_rt(trace_x_windowed,
                                             trace_y_windowed, self.back_az)
        z_here = trace_z_windowed
        r_amp = np.amax(r_here)
        z_amp = np.amax(z_here)
        incidence_angle = np.arctan(r_amp / z_amp) * (180 / np.pi)

        #rotate
        if rotation_method == 'RTZ':
            self.r, self.t = rotate.rotate_ne_rt(trace_x_windowed,
                                                 trace_y_windowed,
                                                 self.back_az)
            self.z = trace_z_windowed
        elif rotation_method == 'LQT' and type == 'earth_model':
            self.z, self.r, self.t = rotate.rotate_zne_lqt(
                trace_z_windowed, trace_x_windowed, trace_y_windowed,
                self.back_az, incidence_angle)
        elif rotation_method == 'LQT' and type == 'toy_model':
            raise ValueError(
                'rotation method LQT not implemented for type : toy_model')

        #deconvolve Z (apprx. P wave pulse) from R
        self.time = np.linspace(window_start, window_end, len(self.r))
        if decon_type == 'water_level':
            self.prf = water_level(self.r, self.z, wl)
        elif decon_type == 'damped_lstsq':
            self.prf = damped_lstsq(self.r, self.z, damping=0.001)

        #plot the two waveforms being deconvolved
        if plot == True:
            plt.plot(self.time, self.r)
            plt.plot(self.time, self.z)

        if decon_type == 'water_level':
            #center of the receiver function on the P arrival
            spike = np.exp((-1.0 * (self.time)**2) / 0.1)
            spike_omega = np.fft.fft(spike)
            prf_omega = np.fft.fft(self.prf)
            prf_shifted = spike_omega * prf_omega
            self.prf = np.real(np.fft.ifft(prf_shifted))

        #normalize
        self.prf /= self.prf.max()
        if rotation_method == 'LQT':
            self.prf *= -1.0