Пример #1
0
    def test_rotate2zne_round_trip(self):
        """
        The rotate2zne() function has an inverse argument. Thus round
        tripping should work.
        """
        np.random.seed(45645623)
        z = np.random.random(10)
        n = np.random.random(10)
        e = np.random.random(10)

        for _ in range(100):
            # The risk of producing linear dependent directions is very
            # small (the seed value should also prevent it across machines).
            dip_1, dip_2, dip_3 = np.random.random(3) * 180.0 - 90.0
            azi_1, azi_2, azi_3 = np.random.random(3) * 360.0

            a, b, c = rotate2zne(z, azi_1, dip_1,
                                 n, azi_2, dip_2,
                                 e, azi_3, dip_3)

            z_new, n_new, e_new = rotate2zne(a, azi_1, dip_1,
                                             b, azi_2, dip_2,
                                             c, azi_3, dip_3,
                                             inverse=True)

            np.testing.assert_allclose(z, z_new, rtol=1E-7, atol=1e-7)
            np.testing.assert_allclose(n, n_new, rtol=1E-7, atol=1e-7)
            np.testing.assert_allclose(e, e_new, rtol=1E-7, atol=1e-7)
Пример #2
0
    def test_rotate2zne_against_ne_rt_picking_any_two_horizontal_comps(self):
        """
        This also tests non-orthogonal configurations to some degree.
        """
        np.random.seed(456)
        z = np.random.random(10)
        n = np.random.random(10)
        e = np.random.random(10)

        # Careful to not pick any coordinate axes.
        for ba in [14.325, 38.234, 78.1, 136.3435, 265.4, 351.35]:
            r, t = rotate_ne_rt(n=n, e=e, ba=ba)

            _r = [r, ba + 180, 0]
            _t = [t, ba + 270, 0]
            _n = [n, 0, 0]
            _e = [e, 90, 0]

            # Picking any two should be enough to reconstruct n and e.
            for a, b in itertools.permutations([_r, _t, _n, _e], 2):
                z_new, n_new, e_new = rotate2zne(z, 0, -90,
                                                 a[0], a[1], a[2],
                                                 b[0], b[1], b[2])
                np.testing.assert_allclose(z_new, z)
                np.testing.assert_allclose(n_new, n)
                np.testing.assert_allclose(e_new, e)
Пример #3
0
def rotme(st, ang):
    azis = ang[0:3]
    dips = ang[3:6]
    data = rotate2zne(st[0].data, azis[0], dips[0], st[1].data, azis[1],
                      dips[1], st[2].data, azis[2], dips[2])
    st[0].data, st[1].data, st[2].data = data[0], data[1], data[2]
    return st
Пример #4
0
    def rotate2ZNE(self):
        """
        Rotates non ZNE stations to ZNE
        """

        orientation_list = []

        for i in range(len(self.condensed_stream)):
            orientation_list.append(self.condensed_stream[i].stats.channel[2])

        if "E" not in orientation_list and "N" not in orientation_list:

            stat_orientation = []
            stat_waveform = []
            stat_lens = []

            for i in range(len(self.condensed_stream)):

                stat_orientation.append(
                    self.stn.response.get_orientation(
                        self.condensed_stream[i].get_id()))
                stat_waveform.append(np.copy(self.condensed_stream[i].data))
                stat_lens.append(len(stat_waveform[i]))

            # wavelengths must all be the same length
            min_len = np.min(stat_lens)

            waveform_array = rotate2zne(stat_waveform[0][0:min_len], stat_orientation[0]['azimuth'], stat_orientation[0]['dip'],\
                                        stat_waveform[1][0:min_len], stat_orientation[1]['azimuth'], stat_orientation[1]['dip'],\
                                        stat_waveform[2][0:min_len], stat_orientation[2]['azimuth'], stat_orientation[2]['dip'])

            for i in range(len(self.condensed_stream)):

                self.condensed_stream[i].data = waveform_array[i]
Пример #5
0
    def test_galperin_configuration(self):
        """
        Equal arrays on a Galperin configuration should result in only the
        vertical component remaining.
        """
        dip = - (90.0 - np.rad2deg(np.arctan(np.sqrt(2.0))))

        u = np.array([1.0, 0.0, 1.0])
        v = np.array([1.0, 1.0, -1.0])
        w = np.array([1.0, -1.0, -1.0])

        z, n, e = rotate2zne(
            u, -90, dip,
            v, 30, dip,
            w, 150, dip)

        fac = 1.0 / np.sqrt(6.0)

        z_ref = np.array([fac * 3.0 * np.sqrt(2.0), 0.0, -fac * np.sqrt(2.0)])
        n_ref = np.array([0.0, fac * 2.0 * np.sqrt(3.0), 0.0])
        e_ref = np.array([0.0, 0.0, -4.0 * fac])

        self.assertTrue(np.allclose(z, z_ref, rtol=1E-7, atol=1E-7))
        self.assertTrue(np.allclose(n, n_ref, rtol=1E-7, atol=1E-7))
        self.assertTrue(np.allclose(e, e_ref, rtol=1E-7, atol=1E-7))
Пример #6
0
def _rotate_specific_channels_to_zne(
        self, network, station, location, channels):
    """
    Rotate three explicitly specified channels to ZNE.

    :type network: str
    :param network: Network code of channels that should be rotated.
    :type station: str
    :param station: Station code of channels that should be rotated.
    :type location: str
    :param location: Location code of channels that should be rotated.
    :type channels: list
    :param channels: The three channel codes of channels that should be
        rotated.
    """
    from obspy.signal.rotate import rotate2ZNE as rotate2zne
    # build temporary stream that has only those traces that are supposed
    # to be used in rotation
    st = self.select(network=network, station=station, location=location)
    st = (st.select(channel=channels[0]) + st.select(channel=channels[1]) +
          st.select(channel=channels[2]))
    # remove the original unrotated traces from the stream
    for tr in st.traces:
        self.remove(tr)
    # cut data so that we end up with a set of matching pieces for the tree
    # components (i.e. cut away any parts where one of the three components
    # has no data)
    st = _trim_common_channels(st)
    # sort by start time, so each three consecutive traces can then be used
    # in one rotation run
    st.sort(keys=["starttime"])
    # woooops, that's unexpected. must be a bug in the trimming helper
    # routine
    if len(st) % 3 != 0:
        msg = ("Unexpected behavior in rotation. Please file a bug "
               "report on github.")
        raise NotImplementedError(msg)
    num_pieces = len(st) / 3
    for i in range(num_pieces):
        # three consecutive traces are always the ones that combine for one
        # rotation run
        traces = [st.pop() for i in range(3)]
        # paranoid.. do a quick check of the channels again.
        if set([tr.stats.channel for tr in traces]) != set(channels):
            msg = ("Unexpected behavior in rotation. Please file a bug "
                   "report on github.")
            raise NotImplementedError(msg)
        zne = rotate2zne(
            traces[0], traces[0].stats.orientation["azimuth"],
            traces[0].stats.orientation["dip"],
            traces[1], traces[1].stats.orientation["azimuth"],
            traces[1].stats.orientation["dip"],
            traces[2], traces[2].stats.orientation["azimuth"],
            traces[2].stats.orientation["dip"])
        for tr, new_data, component in zip(traces, zne, "ZNE"):
            tr.data = new_data
            tr.stats.channel = tr.stats.channel[:-1] + component
        self.traces += traces
    return self
Пример #7
0
def rotateZNE(st):
    try:
        zne = rotate2zne(st[0], st[0].stats.sac.cmpaz, st[0].stats.sac.cmpinc,
                         st[1], st[1].stats.sac.cmpaz, st[1].stats.sac.cmpinc,
                         st[2], st[2].stats.sac.cmpaz, st[2].stats.sac.cmpinc)
    except Exception as e:
        raise ValueError('No specified cmpaz or cmpinc. {}'.format(e))
    for tr, new_data, component in zip(st, zne, "ZNE"):
        tr.data = new_data
        tr.stats.channel = tr.stats.channel[:-1] + component
Пример #8
0
    def test_rotate2zne_round_trip(self):
        """
        The rotate2zne() function has an inverse argument. Thus round
        tripping should work.
        """
        z = np.ones(10, dtype=np.float64)
        n = 2.0 * np.ones(10, dtype=np.float64)
        e = 3.0 * np.ones(10, dtype=np.float64)

        # Random values.
        dip_1, dip_2, dip_3 = 0.0, 30.0, 60.0
        azi_1, azi_2, azi_3 = 0.0, 170.0, 35.0

        a, b, c = rotate2zne(z, azi_1, dip_1, n, azi_2, dip_2, e, azi_3, dip_3)

        z_new, n_new, e_new = rotate2zne(a, azi_1, dip_1,
                                         b, azi_2, dip_2,
                                         c, azi_3, dip_3,
                                         inverse=True)

        self.assertTrue(np.allclose(z, z_new, rtol=1E-7, atol=1e-7))
        self.assertTrue(np.allclose(n, n_new, rtol=1E-7, atol=1e-7))
        self.assertTrue(np.allclose(e, e_new, rtol=1E-7, atol=1e-7))
Пример #9
0
def rotate_trace_to_zrt(str1):
    """
      This function rotates a stream object (either in ENZ or 12Z) in to a stream object of TRZ
    """

    for k, tr in enumerate(str1):
        if tr.stats.channel[2] == 'Z':
            tr_z = tr
        elif tr.stats.channel[2] == 'E' or tr.stats.channel[2] == '1':
            tr_e = tr
        elif tr.stats.channel[2] == 'N' or tr.stats.channel[2] == '2':
            tr_n = tr
        else:
            sys.exit('Problem with ' + tr.stats.channel)

    if 'tr_e' not in vars():
        sys.exit('No east component')
    else:
        tr_r = tr_e.copy()
    if 'tr_n' not in vars():
        sys.exit('No north component')
    else:
        tr_t = tr_n.copy()
    if 'tr_z' not in vars():
        sys.exit('No vertical component')
    else:
        tr_z2 = tr_z.copy()

    # note that even traces labelled as E or N in the channel name may not have the right cmpaz.
    (tr_z2.data, tr_n.data,
     tr_e.data) = rotate2zne(tr_z.data, tr_z.stats.cmpaz, tr_z.stats.dip,
                             tr_n.data, tr_n.stats.cmpaz, tr_n.stats.dip,
                             tr_e.data, tr_e.stats.cmpaz, tr_e.stats.dip)
    baz = tr_z2.stats.back_azimuth
    #baz=19.29817039741116 vs baz_sac= 1.937192e+01 # the baz in sac is not accurate enough that could cause discrepancy with the rotation results
    # what is in rotate_ne_to_tr (confirmed)
    # ba = radians(ba)
    #r = - e * sin(ba) - n * cos(ba)
    #t = - e * cos(ba) + n * sin(ba)
    (tr_r.data, tr_t.data) = rotate_ne_rt(tr_n.data, tr_e.data, baz)

    # after rotation, inclination is not changed but azimuth is changed
    (tr_r.stats.cmpinc, tr_t.stats.cmpinc) = (90, 90)
    (tr_r.stats.cmpaz, tr_t.stats.cmpaz) = ((baz + 180) % 360.,
                                            (baz + 270) % 360.)
    (tr_r.stats.channel, tr_t.stats.channel) = (tr_r.stats.channel[0:2] + 'R',
                                                tr_t.stats.channel[0:2] + 'T')

    str2 = Stream(traces=[tr_t, tr_r, tr_z2])
    return str2
Пример #10
0
    def test_rotate2zne_against_rotate_ne_rt(self):
        np.random.seed(123)
        z = np.random.random(10)
        n = np.random.random(10)
        e = np.random.random(10)

        for ba in [0.0, 14.325, 38.234, 78.1, 90.0, 136.3435, 265.4, 351.35]:
            r, t = rotate_ne_rt(n=n, e=e, ba=ba)

            # Unrotate with rotate2zne() - this should make sure the azimuth is
            # interpreted correctly.
            z_new, n_new, e_new = rotate2zne(z, 0, -90,
                                             r, ba + 180, 0,
                                             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)
Пример #11
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)
def data_process(event2find):
    print('Running code for: Event ' + event2find)
    for i in range(0, len(event)):
        event1 = str(event[i])
        if event1 == event2find:
            a = i
    time_1 = str(eventtime[a])
    t1l = len(time_1) - 3
    time_2 = time_1
    class_1 = str(eventclass[a])
    c1l = len(class_1) - 3
    class_2 = class_1
    quality_1 = str(quality[a])
    q1l = len(quality_1) - 3
    quality_2 = quality_1
    print('Event: ' + event2find)
    print('Datetime of the event: ' + time_2)
    print('Class: ' + class_2)
    print('Quality: ' + quality_2)
    from obspy import UTCDateTime
    time = UTCDateTime(time_2)
    starttime = time - 60 * 30
    print(starttime)
    endtime = time + 60 * 90
    print(endtime)
    net = 'XB'
    sta = 'ELYSE'
    loc = '02'
    chan = 'BH*'
    from obspy.clients.fdsn import Client
    client = Client('IRIS')
    st = client.get_waveforms(net,
                              sta,
                              loc,
                              chan,
                              starttime,
                              endtime,
                              attach_response=True)
    print(st)
    # Sometimes more than one traces are available for one component, therefore a merge is necessary.
    for tr in st.select(component='U'):
        st.merge(tr)
    print('----------------------')
    print('Streams after merging')
    print('----------------------')
    print(st)
    timeE1 = st[0].stats.starttime
    timeN1 = st[1].stats.starttime
    timeZ1 = st[2].stats.starttime
    stime = max(timeE1, timeN1, timeZ1)
    timeEe = st[0].stats.endtime
    timeNe = st[1].stats.endtime
    timeZe = st[2].stats.endtime
    etime = min(timeEe, timeNe, timeZe)
    st[0].trim(stime, etime)
    st[1].trim(stime, etime)
    st[2].trim(stime, etime)
    print('----------------------')
    print('Streams after trimming')
    print('----------------------')
    print(st)
    import obspy
    from obspy import read
    from obspy import read_inventory
    inv = obspy.read_inventory('ELYSE.dataless')
    for q in range(1, 4):
        if q == 1:
            comp = ('DISP')
        elif q == 2:
            comp = ('VEL')
        elif q == 3:
            comp = ('ACC')
        st_rem1 = st.copy()
        pre_filt = [0.005, 0.01, 8, 10]  #for 20 Hz data
        st_rem1.remove_response(output=comp,
                                taper_fraction=0.05,
                                pre_filt=pre_filt,
                                inventory=inv)
        sta = inv[0][0]
        azs = []
        dips = []
        trs = []
        channels = ['BHU', 'BHV', 'BHW']
        for chn in channels:
            chndata = sta.select(channel=chn)[0]
            print('CHNDATA--------------------------------')
            print(chndata)
            azs.append(chndata.azimuth)
            dips.append(chndata.dip)
        from obspy.signal.rotate import rotate2zne
        (z, n, e) = rotate2zne(st_rem1[0], azs[0], dips[0], st_rem1[1], azs[1],
                               dips[1], st_rem1[2], azs[2], dips[2])
        from scipy import signal
        lenz = len(z)
        alp = 5e-2
        window = signal.tukey(len(z), alpha=alp)
        z = z * window
        n = n * window
        e = e * window
        st_new1 = st_rem1.copy()
        st_new1[0].data = z
        st_new1[0].stats.channel = 'BHZ'
        st_new1[1].data = n
        st_new1[1].stats.channel = 'BHN'
        st_new1[2].data = e
        st_new1[2].stats.channel = 'BHE'
        print('- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -')
        print(st_new1[0].stats)
        print('- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -')
        print(st_new1[1].stats)
        print('- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -')
        print(st_new1[2].stats)
        import os
        path = ('DATA/')
        check = os.path.isdir(path)
        if check == False:
            os.mkdir(path)
        path = ('DATA/' + class_2 + '/')
        check = os.path.isdir(path)
        if check == False:
            os.mkdir(path)
        path = ('DATA/' + class_2 + '/' + quality_2 + '/')
        check = os.path.isdir(path)
        if check == False:
            os.mkdir(path)
        path = ('DATA/' + class_2 + '/' + quality_2 + '/' + event2find + '/')
        check = os.path.isdir(path)
        if check == False:
            os.mkdir(path)
        filename1 = (path + '/' + event2find + '_' + comp + '.mseed')
        st_new1.write(filename1, format='MSEED')

    targetfile = (path + '/' + event2find + '.mseed')
    from shutil import copyfile
    #copyfile('fdsnws_msds.mseed', targetfile)
    st.write(targetfile, format='MSEED')
Пример #13
0
    def rotate(self, vp=None, vs=None, align=None):
        """
        Rotates 3-component seismograms from vertical (Z),
        east (E) and north (N) to longitudinal (L), 
        radial (Q) and tangential (T) components of motion.
        Note that the method 'rotate' from ``obspy.core.stream.Stream``
        is used for the rotation ``'ZNE->ZRT'`` and ``'ZNE->LQT'``.
        Rotation ``'ZNE->PVH'`` is implemented separately here 
        due to different conventions.

        Parameters
        ----------
        vp : float
            P-wave velocity at surface (km/s)
        vs : float
            S-wave velocity at surface (km/s)
        align : str
            Alignment of coordinate system for rotation
            ('ZRT', 'LQT', or 'PVH')

        Returns
        -------
        rotated : bool
            Whether or not the object has been rotated

        """

        if not self.meta.accept:
            return

        if self.meta.rotated:
            print("Data have been rotated already - continuing")
            return

        # Use default values from meta data if arguments are not specified
        if not align:
            align = self.meta.align

        if align == 'ZNE':
            from obspy.signal.rotate import rotate2zne

            # Copy traces
            trZ = self.data.select(component='Z')[0].copy()
            trN = self.data.select(component='1')[0].copy()
            trE = self.data.select(component='2')[0].copy()

            azim = self.sta.azcorr

            # Try EBS with left handed system
            Z, N, E = rotate2zne(trZ.data, 0., -90., trN.data, azim, 0.,
                                 trE.data, azim + 90., 0.)

            # Z, N, E = rotate2zne(trZ.data, 0., -90., trN.data,
            #                      azim, 0., trE.data, azim+90., 0.)
            trN.data = N
            trE.data = E

            # Update stats of streams
            trN.stats.channel = trN.stats.channel[:-1] + 'N'
            trE.stats.channel = trE.stats.channel[:-1] + 'E'

            self.data = Stream(traces=[trZ, trN, trE])

        elif align == 'ZRT':
            self.data.rotate('NE->RT', back_azimuth=self.meta.baz)
            self.meta.align = align
            self.meta.rotated = True

        elif align == 'LQT':
            self.data.rotate('ZNE->LQT',
                             back_azimuth=self.meta.baz,
                             inclination=self.meta.inc)
            for tr in self.data:
                if tr.stats.channel.endswith('Q'):
                    tr.data = -tr.data
            self.meta.align = align
            self.meta.rotated = True

        elif align == 'PVH':

            # First rotate to ZRT
            self.data.rotate('NE->RT', back_azimuth=self.meta.baz)

            # Copy traces
            trP = self.data.select(component='Z')[0].copy()
            trV = self.data.select(component='R')[0].copy()
            trH = self.data.select(component='T')[0].copy()

            slow = self.meta.slow
            if not vp:
                vp = self.meta.vp
            if not vs:
                vs = self.meta.vs

            # Vertical slownesses
            # P vertical slowness
            qp = np.sqrt(1. / vp / vp - slow * slow)
            # S vertical slowness
            qs = np.sqrt(1. / vs / vs - slow * slow)

            # Elements of rotation matrix
            m11 = slow * vs * vs / vp
            m12 = -(1. - 2. * vs * vs * slow * slow) / (2. * vp * qp)
            m21 = (1. - 2. * vs * vs * slow * slow) / (2. * vs * qs)
            m22 = slow * vs

            # Rotation matrix
            rot = np.array([[-m11, m12], [-m21, m22]])

            # Vector of Radial and Vertical
            r_z = np.array([trV.data, trP.data])

            # Rotation
            vec = np.dot(rot, r_z)

            # Extract P and SV, SH components
            trP.data = vec[0, :]
            trV.data = vec[1, :]
            trH.data = -trH.data / 2.

            # Update stats of streams
            trP.stats.channel = trP.stats.channel[:-1] + 'P'
            trV.stats.channel = trV.stats.channel[:-1] + 'V'
            trH.stats.channel = trH.stats.channel[:-1] + 'H'

            # Over-write data attribute
            self.data = Stream(traces=[trP, trV, trH])
            self.meta.align = align
            self.meta.rotated = True

        else:
            raise (Exception("incorrect 'align' argument"))
                         taper_fraction=0.05,
                         pre_filt=pre_filt,
                         inventory=inv)
 sta = inv[0][0]
 azs = []
 dips = []
 trs = []
 channels = ['BHU', 'BHV', 'BHW']
 for chn in channels:
     chndata = sta.select(channel=chn)[0]
     print('CHNDATA--------------------------------')
     print(chndata)
     azs.append(chndata.azimuth)
     dips.append(chndata.dip)
 from obspy.signal.rotate import rotate2zne
 (z, n, e) = rotate2zne(st_rem1[0], azs[0], dips[0], st_rem1[1], azs[1],
                        dips[1], st_rem1[2], azs[2], dips[2])
 from scipy import signal
 lenz = len(z)
 alp = 5e-2
 window = signal.tukey(len(z), alpha=alp)
 z = z * window
 n = n * window
 e = e * window
 st_new1 = st_rem1.copy()
 st_new1[0].data = z
 st_new1[0].stats.channel = 'BHZ'
 st_new1[1].data = n
 st_new1[1].stats.channel = 'BHN'
 st_new1[2].data = e
 st_new1[2].stats.channel = 'BHE'
 print('- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -')
def getobs(mseed_filename,
           client,
           event,
           phases,
           frq4,
           windows,
           stas,
           stalocs,
           picks=None,
           delta_T={
               'P': 1.,
               'SH': 1.,
               'R': 10.,
               'L': 10.
           },
           taper=None,
           adjtime=None):
    # Connect to arclink server
    #st = read('../mseed/mini.seed')
    org = event.preferred_origin()
    if org is None:
        org = event.origins[0]
    st = read(mseed_filename)
    stobs = {'params': {'filter': frq4, 'windows': windows}}
    syn = {}
    torg = org.time
    trngmx = 3600.
    invout = None
    # First do any requried time adjustments
    if not adjtime is None:
        for tr in st:
            if not tr.stats.station in adjtime.keys():
                continue
            print 'Adjusting time for station %s by %g secs' % \
                (tr.stats.station,adjtime[tr.stats.station])
            tr.stats.starttime -= adjtime[tr.stats.station]

    for phase in phases:
        if not phase in stas.keys(): continue
        stobs[phase] = Stream()
        for sta in stas[phase]:
            # If this is a body wave phase find the pick - skip if none found
            if phase == 'P' or phase == 'SH':
                sta_pick = None
                # If no picks supplied then get them from events
                if picks is None:
                    for pick in event.picks:
                        if pick.phase_hint == phase[0:1] and \
                            pick.waveform_id.station_code == sta:
                            sta_pick = pick
                            break
                else:  # Get them from picks - e.g. returned by get_isctimes
                    if sta in picks.keys() and phase[0:1] in picks[sta]:
                        sta_pick = Pick()
                        sta_pick.time = picks[sta][phase[0:1]]
                if sta_pick is None:
                    print 'No %s pick found for station %s - skipping' % (
                        phase, sta)
                    continue

            # Set location code if prescribed, otherwise use '00' (preferred)
            if sta in stalocs.keys():
                loc = stalocs[sta]
            else:
                loc = '00'
            # Select the channels for this station - skip if none found
            chans = st.select(station=sta, location=loc)
            if len(chans) == 0:  # if nothing for loc='00', try also with ''
                loc = ''
                chans = st.select(station=sta, location=loc)
            if len(chans) == 0:
                print 'No channels found for %s' % sta
                continue
            try:
                inv = client.get_stations(network=chans[0].stats.network,
                                          station=sta,
                                          location=loc,
                                          starttime=torg,
                                          endtime=torg + 100.,
                                          level='response')
            except Exception as e:
                warnings.warn(str(e))
                print 'FDSNWS request failed for trace id %s - skipping' % sta
                continue
            try:
                coordinates = inv[0].get_coordinates(chans[0].id)
            except:
                print 'No coordinates found for station %s, channel %s' % \
                            (sta,chans[0].id)
                continue
            dist, azm, bazm = gps2dist_azimuth(org['latitude'],
                                               org['longitude'],
                                               coordinates['latitude'],
                                               coordinates['longitude'])
            gcarc = locations2degrees(org['latitude'], org['longitude'],
                                      coordinates['latitude'],
                                      coordinates['longitude'])
            if phase == 'R' or phase == 'P':  # Rayleigh or P wave
                try:
                    tr = st.select(station=sta, component='Z', location=loc)[0]
                except IndexError:
                    print 'No vertical for %s:%s' % (sta, loc)
                    continue
                try:
                    inv = client.get_stations(network=tr.stats.network,
                                              station=sta,
                                              channel=tr.stats.channel,
                                              location=loc,
                                              starttime=torg,
                                              endtime=torg + 100.,
                                              level='response')
                except Exception as e:
                    warnings.warn(str(e))
                    print 'FDSNWS request failed for trace id %s - skipping' % tr.id
                    continue
                tr = tr.copy()
                tr.stats.response = inv[0].get_response(tr.id, torg)
                tr.stats.coordinates = inv[0].get_coordinates(tr.id)
                tr.remove_response(pre_filt=frq4[phase], output='DISP')
                tr.stats.gcarc = gcarc
                tr.stats.azimuth = azm
                #t1 = minv[0].get_responeax(tr.stats.starttime,t+dist/rvmax)
                #t2 = min(tr.stats.endtime  ,t+dist/rvmin)
                t1 = max(torg, tr.stats.starttime)
                t2 = min(torg + trngmx, tr.stats.endtime)
                tr.trim(starttime=t1, endtime=t2)
                decim = int(0.01 + delta_T[phase] / tr.stats.delta)
                ch = inv.select(station=sta, channel=tr.stats.channel)[0][0][0]
                print tr.id,' ',tr.stats.sampling_rate,' decimated by ',decim,\
                        'sensitivity=',ch.response.instrument_sensitivity.value
                if tr.stats.starttime - torg < 0.:
                    tr.trim(starttime=torg)
                tr.decimate(factor=decim, no_filter=True)
                tr.data *= 1.e6  # Convert to microns
            elif phase == 'L' or phase == 'SH':  # Love or SH wave
                if len(chans.select(component='E')) != 0:
                    try:
                        tr1a = st.select(station=sta,
                                         component='E',
                                         location=loc)[0]
                        tr2a = st.select(station=sta,
                                         component='N',
                                         location=loc)[0]
                    except:
                        print 'Station %s does not have 2 horizontal componets -skipping' % sta
                        continue
                elif len(chans.select(component='1')) != 0:
                    try:
                        tr1a = st.select(station=sta,
                                         component='1',
                                         location=loc)[0]
                        tr2a = st.select(station=sta,
                                         component='2',
                                         location=loc)[0]
                    except:
                        print 'Station %s does not have 2 horizontal componets -skipping' % sta
                        continue
                tr1 = tr1a.copy()
                tr1.data = tr1a.data.copy()
                tr2 = tr2a.copy()
                tr2.data = tr2a.data.copy()
                ch1 = inv.select(station=sta,
                                 channel=tr1.stats.channel)[0][0][0]
                ch2 = inv.select(station=sta,
                                 channel=tr2.stats.channel)[0][0][0]
                tr1.stats.response = ch1.response
                tr1.remove_response(pre_filt=frq4[phase], output='DISP')
                tr2.stats.response = ch2.response
                tr2.remove_response(pre_filt=frq4[phase], output='DISP')
                strt = max(tr1.stats.starttime, tr2.stats.starttime)
                endt = min(tr1.stats.endtime, tr2.stats.endtime)
                tr1.trim(starttime=strt, endtime=endt)
                tr2.trim(starttime=strt, endtime=endt)
                # Rotate components first to ZNE
                vert, north, east = rotate2zne(tr1.data, ch1.azimuth, 0.,
                                               tr2.data, ch2.azimuth, 0.,
                                               np.zeros(tr1.stats.npts), 0.,
                                               0.)
                radial, transverse = rotate_ne_rt(north, east, bazm)
                tr = Trace(header=tr1.stats, data=transverse)
                tr2 = Trace(header=tr2.stats, data=radial)
                tr.stats.channel = tr.stats.channel[:-1] + 'T'
                # Change one of the invout channels to end in 'T'
                net = inv[-1]
                stn = net[0]
                chn = stn[0]
                chn.code = chn.code[:-1] + 'T'
                #
                tr.stats.gcarc = gcarc
                tr.stats.azimuth = azm
                decim = int(0.01 + delta_T[phase] / tr.stats.delta)
                print tr.id, ' ', tr.stats.sampling_rate, ' decimated by ', decim
                print '%s: sensitivity=%g, azimuth=%g, dip=%g' % (
                    ch1.code, ch1.response.instrument_sensitivity.value,
                    ch1.azimuth, ch1.dip)
                print '%s: sensitivity=%g, azimuth=%g, dip=%g' % (
                    ch2.code, ch2.response.instrument_sensitivity.value,
                    ch2.azimuth, ch2.dip)
                if tr.stats.starttime - torg < 0.:
                    tr.trim(starttime=torg)
                    tr2.trim(starttime=torg)
                tr.decimate(factor=decim, no_filter=True)
                tr2.decimate(factor=decim, no_filter=True)
                tr.radial = 1.e6 * tr2.data
                tr.stats.coordinates = coordinates
                tr.data *= 1.e6  # Convert to microns
            if phase == 'R' or phase == 'L':  # Window according to group velocity window
                gwin = windows[phase]
                tbeg, tend = (dist * .001 / gwin[1], dist * .001 / gwin[0])
                tr.trim(torg + tbeg, torg + tend)
            elif phase == 'P' or phase == 'SH':  # Window by times before and after pick
                tbef, taft = windows[phase]
                tr.trim(sta_pick.time - tbef, sta_pick.time + taft)
                idx = int(0.5 + tbef / tr.stats.delta)
                avg = tr.data[:idx].mean()
                tr.data -= avg
                if not taper is None:
                    itp = int(taper * tr.stats.npts)
                    for i in range(tr.stats.npts - itp, tr.stats.npts):
                        tr.data[i] *= 0.5 * (1. + mt.cos(
                            mt.pi * (i - (tr.stats.npts - itp)) / float(itp)))
                tr.stats.pick = sta_pick
            stobs[phase].append(tr)
            # Appen station inventory to invout
            if invout is None:
                invout = inv
            else:
                invout += inv
        # Pickle to file
    return stobs, invout
Пример #16
0
    def rotate_components(wfstream, metadata=None):
        """rotates components if orientation code is numeric.
        azimut and dip are fetched from metadata"""
        try:
            # indexing fails if metadata is None
            metadata[0]
        except:
            if verbosity:
                msg = 'Warning: could not rotate traces since no metadata was given\nset Inventory file!'
                print(msg)
            return wfstream
        if metadata[0] is None:
            # sometimes metadata is (None, (None,))
            if verbosity:
                msg = 'Warning: could not rotate traces since no metadata was given\nCheck inventory directory!'
                print(msg)
            return wfstream
        else:
            parser = metadata[1]

        def get_dip_azimut(parser, trace_id):
            """gets azimut and dip for a trace out of the metadata parser"""
            dip = None
            azimut = None
            try:
                blockettes = parser._select(trace_id)
            except SEEDParserException as e:
                print(e)
                raise ValueError
            for blockette_ in blockettes:
                if blockette_.id != 52:
                    continue
                dip = blockette_.dip
                azimut = blockette_.azimuth
                break
            if dip is None or azimut is None:
                error_msg = 'Dip and azimuth not available for trace_id {}'.format(
                    trace_id)
                raise ValueError(error_msg)
            return dip, azimut

        trace_ids = [trace.id for trace in wfstream]
        for trace_id in trace_ids:
            orientation = trace_id[-1]
            if orientation.isnumeric():
                # misaligned channels have a number as orientation
                azimuts = []
                dips = []
                for trace_id in trace_ids:
                    try:
                        dip, azimut = get_dip_azimut(parser, trace_id)
                    except ValueError as e:
                        print(e)
                        print(
                            'Failed to rotate station {}, no azimuth or dip available in metadata'
                            .format(trace_id))
                        return wfstream
                    azimuts.append(azimut)
                    dips.append(dip)
                # to rotate all traces must have same length
                wfstream = trim_station_components(wfstream,
                                                   trim_start=True,
                                                   trim_end=True)
                z, n, e = rotate2zne(wfstream[0], azimuts[0], dips[0],
                                     wfstream[1], azimuts[1], dips[1],
                                     wfstream[2], azimuts[2], dips[2])
                print('check4rotated: rotated station {} to ZNE'.format(
                    trace_id))
                z_index = dips.index(min(
                    dips))  # get z-trace index (dip is measured from 0 to -90
                wfstream[z_index].data = z
                wfstream[z_index].stats.channel = wfstream[
                    z_index].stats.channel[0:-1] + 'Z'
                del trace_ids[z_index]
                for trace_id in trace_ids:
                    dip, az = get_dip_azimut(parser, trace_id)
                    trace = wfstream.select(id=trace_id)[0]
                    if az > 315 and az <= 45 or az > 135 and az <= 225:
                        trace.data = n
                        trace.stats.channel = trace.stats.channel[0:-1] + 'N'
                    elif az > 45 and az <= 135 or az > 225 and az <= 315:
                        trace.data = e
                        trace.stats.channel = trace.stats.channel[0:-1] + 'E'
                break
            else:
                continue
        return wfstream
Пример #17
0
        except Exception:
            print('Missing data for station: ',str(sta))
            continue
        H1azi = ori.loc[sta]['H1azi']
        for itr in range(0,len(st)):
            if st[itr].stats.channel == H1comp:
                h1 = st[itr].data
            elif st[itr].stats.channel == H2comp:
                h2 = st[itr].data
            elif st[itr].stats.channel == Zcomp:
                z = st[itr].data
        ba = st[0].stats.sac.baz
        
        # Rotate Z-H1-H2 to Z-N-E
        traces_zne = rotate2zne(data_1=z , azimuth_1=0, dip_1=-90, 
                   data_2=h1, azimuth_2=H1azi, dip_2=0, 
                   data_3=h2, azimuth_3=H1azi+90, dip_3=0)
        z2 = traces_zne[0]
        n = traces_zne[1]
        e = traces_zne[2]
        
        # Rotate N-E to R-T
        traces_rt = rotate_ne_rt(n=n, e=e, ba=ba)
        r = traces_rt[0]
        t = traces_rt[1]

        # Define new data streams
        st_bhn = st[0].copy()
        st_bhn.stats.channel = Ncomp
        st_bhn.data = n
        st_bhe = st[0].copy()
Пример #18
0
# Process the traces
#
st.detrend(type='demean')
st.detrend(type='linear')
st.decimate(factor=int(st[0].stats.sampling_rate), no_filter=True)

# Scale to mm
for tr in st:
    tr.data = tr.data * 1000

# Rotate to real NEZ
ch1_azimuth, ch1_dip, = get_channel_orientation(args.t, args.n, args.s, args.l, args.d, args.c[0])
ch2_azimuth, ch2_dip, = get_channel_orientation(args.t, args.n, args.s, args.l, args.d, args.c[1])
ch3_azimuth, ch3_dip, = get_channel_orientation(args.t, args.n, args.s, args.l, args.d, args.c[2])
st[2].data, st[0].data, st[1].data = rotate2zne(st[0].data, ch1_azimuth, ch1_dip,
                                                st[1].data, ch2_azimuth, ch2_dip,
                                                st[2].data, ch3_azimuth, ch3_dip,
                                                inverse=False)

#
# Make a time array
#
time = np.arange(st[0].stats.npts)
time = time / st[0].stats.sampling_rate

#
# Add zero padding for plotting
#
time = np.concatenate((np.zeros([trail-1]), time))

for tr in st:
    tr.data = np.concatenate((np.zeros([trail-1]), tr.data))
Пример #19
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)
Пример #20
0
    def test_with_real_data(self):
        # Filtered and downsampled test data with two co-located
        # seismometers on a step table. One (UVW) in Galperin configuration,
        # the other (XYZ) oriented 25 degree towards counter-clockwise from
        # North.
        #
        # Original data can be found here:
        # http://examples.obspy.org/step_table_galperin_and_xyz.mseed
        #
        # Picture of setup:
        # http://examples.obspy.org/step_table_galperin_and_xyz.jpg
        u = np.array([
            -887.77005805, 7126.9690531, 48436.17065483, 138585.24660557,
            220190.69362083, 179040.5715419, -21365.23030094,
            -253885.25529288, -344888.20815164, -259362.36082208,
            -117476.30748613, - 42988.81966958, -45995.43307308,
            -57130.87444412, -30545.75344533, 16298.87665025])
        v = np.array([
            2.33308511e+02, 8.16259596e+03, 5.11074487e+04, 1.48229541e+05,
            2.41322335e+05, 2.08201013e+05, 4.93732289e+03, -2.39867750e+05,
            -3.44167596e+05, -2.66558032e+05, -1.27714987e+05, -5.54712804e+04,
            -6.19973652e+04, -7.66740787e+04, -5.17925310e+04,
            -4.71673443e+03])
        w = np.array([
            1692.48532892, 9875.6136413, 53089.61423663, 149373.52749023,
            240009.30157128, 204362.69005767, 1212.47406863, -239380.57384624,
            -336783.01040666, -252884.65411222, -110766.44577398,
            -38182.18142102, -45729.92956198, -61691.87092415,
            -38434.81993441, 6224.73096858])
        x = np.array([
            -1844.85832046, -1778.44974024, -2145.6117388, -4325.27560474,
            -8278.1836905, -10842.53378841, -8565.12113951, -2024.53838011,
            4439.22322848, 7340.96354878, 7081.65449722, 6303.91640198,
            6549.98692684, 7223.59663617, 7133.72073748, 6068.56702479])
        y = np.array([
            -242.70568894, -458.3864756, -351.75925077, 2142.51669733,
            8287.98182002, 15822.24351111, 20151.78532927, 18511.90136103,
            12430.22438956, 5837.66044337, 1274.9580289, -1597.06115226,
            -4331.40686142, -7529.87533286, -10544.34374306, -12656.77586305])
        z = np.array([
            5.79050980e+02, 1.45190734e+04, 8.85582128e+04, 2.53690907e+05,
            4.08578800e+05, 3.45046937e+05, -8.15914926e+03, -4.26449298e+05,
            -5.97207861e+05, -4.53464470e+05, -2.07176498e+05, -7.94526512e+04,
            -8.95206215e+04, -1.14008287e+05, -7.05797830e+04, 1.01175730e+04])

        # Component orientations.
        u = (u, 90.0, -(90.0 - 54.7), "U")
        v = (v, 330.0, -(90.0 - 54.7), "V")
        w = (w, 210.0, -(90.0 - 54.7), "W")
        x = (x, 65.0, 0.0, "X")
        y = (y, 335.0, 0.0, "Y")
        z = (z, 0.0, -90.0, "Z")

        # Any three should result in the same ZNE.
        success_count = 0
        failure_count = 0
        for a, b, c in itertools.permutations([x, y, z, u], 3):
            # Except if "X" and "Y" are both part of it because they don't
            # really contain any data (vertical step table).
            if set(["X", "Y"]).issubset(set([a[-1], b[-1], c[-1]])):
                failure_count += 1
                continue

            z_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[0], rtol=1E-5)
            success_count += 1

            # Sanity check that it fails for slightly different rotations.
            z_new, _, _ = rotate2zne(
                a[0], a[1] + 1.5, a[2] - 1.5,
                b[0], b[1] - 0.7, b[2] + 1.2,
                c[0], c[1] + 1.0, c[2] - 0.4)
            with self.assertRaises(AssertionError):
                np.testing.assert_allclose(z_new, z[0], rtol=1E-5)

        self.assertEqual(success_count, 12)
        self.assertEqual(failure_count, 12)
def data_process(event2find):
    print('Running code for: Event ' + event2find + ' and ' + comp)
    for i in range(0, len(event)):
        event1 = str(event[i])
        if event1 == event2find:
            a = i
    time_1 = str(eventtime[a])
    t1l = len(time_1) - 3
    time_2 = time_1
    class_1 = str(eventclass[a])
    c1l = len(class_1) - 3
    class_2 = class_1
    quality_1 = str(quality[a])
    q1l = len(quality_1) - 3
    quality_2 = quality_1
    print('Event: ' + event2find)
    print('Datetime of the event: ' + time_2)
    print('Class: ' + class_2)
    print('Quality: ' + quality_2)
    from obspy import UTCDateTime
    time = UTCDateTime(time_2)
    starttime = time - 60 * 30
    print(starttime)
    endtime = time + 60 * 90
    print(endtime)
    net = 'XB'
    sta = 'ELYSE'
    loc = '02'
    chan = 'BH*'
    url = ('https://ws.seis-insight.eu/fdsnws/dataselect/1/query?network=' +
           net + '&station=' + sta + '&startTime=' + str(starttime) +
           '&endTime=' + str(endtime) + '&location=*&channel=' + chan)
    r = requests.get(url, auth=(username, password))
    filename = ('fdsnws_msds.mseed')
    if r.status_code == 200:
        with open(filename, 'wb') as out:
            for bits in r.iter_content():
                out.write(bits)
    import obspy
    from obspy import read
    st = read('fdsnws_msds.mseed')
    print(st)
    for tr in st.select(component='U'):
        st.merge(tr)
    print('----------------------')
    print('Streams after merging')
    print('----------------------')
    print(st)
    timeE1 = st[0].stats.starttime
    timeN1 = st[1].stats.starttime
    timeZ1 = st[2].stats.starttime
    stime = max(timeE1, timeN1, timeZ1)
    timeEe = st[0].stats.endtime
    timeNe = st[1].stats.endtime
    timeZe = st[2].stats.endtime
    etime = min(timeEe, timeNe, timeZe)
    st[0].trim(stime, etime)
    st[1].trim(stime, etime)
    st[2].trim(stime, etime)
    print('----------------------')
    print('Streams after trimming')
    print('----------------------')
    print(st)
    from obspy import read_inventory
    inv = obspy.read_inventory('dataless.XB.ELYSE.seed')
    st_rem1 = st.copy()
    pre_filt = [0.005, 0.01, 8, 10]  #for 20 Hz data
    st_rem1.remove_response(output=comp,
                            taper_fraction=0.05,
                            pre_filt=pre_filt,
                            inventory=inv)
    sta = inv[0][0]
    azs = []
    dips = []
    trs = []
    channels = ['BHU', 'BHV', 'BHW']
    for chn in channels:
        chndata = sta.select(channel=chn)[0]
        print('CHNDATA--------------------------------')
        print(chndata)
        azs.append(chndata.azimuth)
        dips.append(chndata.dip)
    from obspy.signal.rotate import rotate2zne
    (z, n, e) = rotate2zne(st_rem1[0], azs[0], dips[0], st_rem1[1], azs[1],
                           dips[1], st_rem1[2], azs[2], dips[2])
    from scipy import signal
    lenz = len(z)
    alp = 5e-2
    window = signal.tukey(len(z), alpha=alp)
    z = z * window
    n = n * window
    e = e * window
    st_new1 = st_rem1.copy()
    st_new1[0].data = z
    st_new1[0].stats.channel = 'BHZ'
    st_new1[1].data = n
    st_new1[1].stats.channel = 'BHN'
    st_new1[2].data = e
    st_new1[2].stats.channel = 'BHE'
    print('- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -')
    print(st_new1[0].stats)
    print('- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -')
    print(st_new1[1].stats)
    print('- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -')
    print(st_new1[2].stats)
    import os
    path = ('Treated/')
    check = os.path.isdir(path)
    if check == False:
        os.mkdir(path)
    path = ('Treated/' + class_2 + '/')
    check = os.path.isdir(path)
    if check == False:
        os.mkdir(path)
    path = ('Treated/' + class_2 + '/' + quality_2 + '/')
    check = os.path.isdir(path)
    if check == False:
        os.mkdir(path)
    path = ('Treated/' + class_2 + '/' + quality_2 + '/' + event2find + '/')
    check = os.path.isdir(path)
    if check == False:
        os.mkdir(path)
    filename1 = (path + '/' + event2find + '_' + comp + '.mseed')
    st_new1.write(filename1, format='MSEED')

    targetfile = (path + '/' + event2find + '.mseed')
    from shutil import copyfile
    copyfile('fdsnws_msds.mseed', targetfile)
Пример #22
0
def rotation(stream, method="NE->RT", acc_type="event"):
    """
    Rotatation.

    :param stream: obspy stream to be rotated
    :param method: "NE->RT" or "ZNE->LQT"
    :param acc_type: "event", "noise"
    :return stream: obspy stream after rotation.

    .. note::
        The keywords `component_azimuth` and `component_inclination` must be given in the stats.
        Currently, only acc_type="event" are well debugged.
        The input 3-component data should be in the roughly same periods or time window.
    """

    rot_stream = Stream()

    # function to extract 3-component stream.
    # if the data are given event the data, then use onset as the key word to find the 3-component data
    if acc_type == "event":
        key = "onset"
    elif acc_type == "noise":
        key = "starttime"

    def iter3c(stream):
        return IterMultipleComponents(stream,
                                      key=key,
                                      number_components=(2, 3))

    for st3c in iter3c(stream):

        tmin, tmax = _find_start_end_time(stream=st3c)
        if tmin > tmax:
            continue
        st3c.trim(starttime=tmin, endtime=tmax)

        # handling the borehole components 1, 2, Z or 1, 2, 3.
        comp = []
        for tr in st3c:
            comp.append(tr.stats.channel[-1])
        comp.sort()
        cc = "".join(comp)
        if cc == "12Z":
            cc = "Z12"
        # rotate2zne
        if cc in ["123", "Z12"]:
            zne = rotate2zne(st3c[0].data, st3c[0].stats.component_azimuth,
                             st3c[0].stats.component_inclination, st3c[1].data,
                             st3c[1].stats.component_azimuth,
                             st3c[1].stats.component_inclination, st3c[2].data,
                             st3c[2].stats.component_azimuth,
                             st3c[2].stats.component_inclination)

            for tr, new_data, component in zip(st3c, zne, "ZNE"):
                tr.data = new_data
                tr.stats.channel = tr.stats.channel[:-1] + component
        # rotate to various coordinates
        st3c.rotate(method=method)
        rot_stream += st3c

    return rot_stream