示例#1
0
    def ppoints(self, pp_depth, pp_phase=None, model='iasp91'):
        """
        Return coordinates of piercing point calculated by 1D ray tracing.

        Piercing point coordinates are stored in the
        stats attributes plat and plon. Needs stats attributes
        station_latitude, station_longitude, slowness and back_azimuth.

        :param pp_depth: depth of interface in km
        :param pp_phase: 'P' for piercing points of P wave, 'S' for piercing
            points of S wave or multiples, if None will be
            set to 'P' or 'S' depending on method
        :param model: path to model file (see `.SimpleModel`, default: iasp91)
        :return: NumPy array with coordinates of piercing points

        .. note::

            ``phase='S'`` is usually wanted for P receiver functions and
            ``'P'`` for S receiver functions.
        """
        if pp_phase is None:
            pp_phase = {'P': 'S', 'S': 'P'}[self.method]
        model = load_model(model)
        for tr in self:
            model.ppoint(tr.stats, pp_depth, phase=pp_phase)
        return np.array([(tr.stats.pp_latitude, tr.stats.pp_longitude)
                         for tr in self])
示例#2
0
    def ppoint(self, pp_depth, pp_phase='S', model='iasp91'):
        """
        Calculate coordinates of piercing point by 1D ray tracing.

        The iasp91 model is used. Piercing point coordinates are stored in the
        stats attributes plat and plon. Needs stats attributes
        station_latitude, station_longitude, slowness and back_azimuth.

        :param pp_depth: depth of interface in km
        :param pp_phase: 'P' for piercing points of P wave, 'S' for piercing
            points of S wave. Multiples are possible, too.
        :param model: Path to model file
            (see :class:`~rf.simple_model.SimpleModel`, default: iasp91)
        :return: NumPy array with coordinates of piercing points

        .. note::

            `phase='S'` is usually wanted for P receiver functions and 'P'
            for S receiver functions.
        """
        model = load_model(model)
        for tr in self:
            model.ppoint(tr.stats, pp_depth, phase=pp_phase)
        return np.array([(tr.stats.pp_latitude, tr.stats.pp_longitude)
                         for tr in self])
示例#3
0
文件: rfstream.py 项目: seism/rf
    def moveout(self, phase='Ps', ref=6.4, model='iasp91'):
        """
        In-place moveout correction to a reference slowness.

        Needs stats attributes slowness and onset.

        :param phase: 'Ps', 'Sp', 'Ppss' or other multiples
        :param ref: reference ray parameter in s/deg
        :param model: path to model file or 'iasp91'
        """
        model = load_model(model)
        model.moveout(self, phase=phase, ref=ref)
示例#4
0
    def moveout(self, phase='Ps', ref=6.4, model='iasp91'):
        """
        In-place moveout correction to a reference slowness.

        Needs stats attributes slowness and onset.

        :param phase: 'Ps', 'Sp', 'Ppss' or other multiples
        :param ref: reference ray parameter in s/deg
        :param model: Path to model file
            (see :class:`~rf.simple_model.SimpleModel`, default: iasp91)
        """
        model = load_model(model)
        model.moveout(self, phase=phase, ref=ref)
示例#5
0
    def moveout(self, phase=None, ref=6.4, model='iasp91'):
        """
        In-place moveout correction to a reference slowness.

        Needs stats attributes slowness and onset.

        :param phase: 'Ps', 'Sp', 'Ppss' or other multiples, if None is set to
            'Ps' for P receiver functions or 'Sp' for S receiver functions
        :param ref: reference ray parameter in s/deg
        :param model: Path to model file
            (see `.SimpleModel`, default: iasp91)
        """
        if phase is None:
            phase = self.method + {'P': 's', 'S': 'p'}[self.method]
        model = load_model(model)
        model.moveout(self, phase=phase, ref=ref)
        for tr in self:
            tr.stats.moveout = phase
            tr.stats.slowness_before_moveout = tr.stats.slowness
            tr.stats.slowness = ref
        return self
示例#6
0
文件: rfstream.py 项目: trichter/rf
    def moveout(self, phase=None, ref=6.4, model='iasp91'):
        """
        In-place moveout correction to a reference slowness.

        Needs stats attributes slowness and onset.

        :param phase: 'Ps', 'Sp', 'Ppss' or other multiples, if None is set to
            'Ps' for P receiver functions or 'Sp' for S receiver functions
        :param ref: reference ray parameter in s/deg
        :param model: Path to model file
            (see `.SimpleModel`, default: iasp91)
        """
        if phase is None:
            phase = self.method + {'P': 's', 'S': 'p'}[self.method]
        model = load_model(model)
        model.moveout(self, phase=phase, ref=ref)
        for tr in self:
            tr.stats.moveout = phase
            tr.stats.slowness_before_moveout = tr.stats.slowness
            tr.stats.slowness = ref
        return self
示例#7
0
文件: rfstream.py 项目: trichter/rf
    def ppoints(self, pp_depth, pp_phase=None, model='iasp91'):
        """
        Return coordinates of piercing point calculated by 1D ray tracing.

        Piercing point coordinates are stored in the
        stats attributes plat and plon. Needs stats attributes
        station_latitude, station_longitude, slowness and back_azimuth.

        :param pp_depth: depth of interface in km
        :param pp_phase: 'P' for piercing points of P wave, 'S' for piercing
            points of S wave or multiples, if None will be
            set to 'S' for P receiver functions or 'S' for S receiver functions
        :param model: path to model file (see `.SimpleModel`, default: iasp91)
        :return: NumPy array with coordinates of piercing points
        """
        if pp_phase is None:
            pp_phase = {'P': 'S', 'S': 'P'}[self.method]
        model = load_model(model)
        for tr in self:
            model.ppoint(tr.stats, pp_depth, phase=pp_phase)
        return np.array([(tr.stats.pp_latitude, tr.stats.pp_longitude)
                         for tr in self])
示例#8
0
def rfstats(obj=None,
            event=None,
            station=None,
            phase='P',
            dist_range='default',
            tt_model='iasp91',
            pp_depth=None,
            pp_phase=None,
            model='iasp91'):
    """
    Calculate ray specific values like slowness for given event and station.

    :param obj: `~obspy.core.trace.Stats` object with event and/or station
        attributes. Can be None if both event and station are given.
        It is possible to specify a stream object, too. Then, rfstats will be
        called for each Trace.stats object and traces outside dist_range will
        be discarded.
    :param event: ObsPy `~obspy.core.event.event.Event` object
    :param station: dictionary like object with items latitude, longitude and
        elevation
    :param phase: string with phase. Usually this will be 'P' or
        'S' for P and S receiver functions, respectively.
    :type dist_range: tuple of length 2
    :param dist_range: if epicentral of event is not in this intervall, None
        is returned by this function,\n
        if phase == 'P' defaults to (30, 90),\n
        if phase == 'S' defaults to (50, 85)
    :param tt_model: model for travel time calculation.
        (see the `obspy.taup` module, default: iasp91)
    :param pp_depth: Depth for piercing point calculation
        (in km, default: None -> No calculation)
    :param pp_phase: Phase for pp calculation (default: 'S' for P-receiver
        function and 'P' for S-receiver function)
    :param model: Path to model file for pp calculation
        (see `.SimpleModel`, default: iasp91)
    :return: `~obspy.core.trace.Stats` object with event and station
        attributes, distance, back_azimuth, inclination, onset and
        slowness or None if epicentral distance is not in the given interval.
        Stream instance if stream was specified instead of stats.
    """
    if isinstance(obj, (Stream, RFStream)):
        stream = obj
        kwargs = {
            'event': event,
            'station': station,
            'phase': phase,
            'dist_range': dist_range,
            'tt_model': tt_model,
            'pp_depth': pp_depth,
            'pp_phase': pp_phase,
            'model': model
        }
        traces = []
        for tr in stream:
            if rfstats(tr.stats, **kwargs) is not None:
                traces.append(tr)
        stream.traces = traces
        return stream
    if dist_range == 'default' and phase.upper() in 'PS':
        dist_range = (30, 90) if phase.upper() == 'P' else (50, 85)
    stats = AttribDict({}) if obj is None else obj
    if event is not None and station is not None:
        stats.update(obj2stats(event=event, station=station))
    dist, baz, _ = gps2dist_azimuth(stats.station_latitude,
                                    stats.station_longitude,
                                    stats.event_latitude,
                                    stats.event_longitude)
    dist = dist / 1000 / DEG2KM
    if dist_range and not dist_range[0] <= dist <= dist_range[1]:
        return
    tt_model = TauPyModel(model=tt_model)
    arrivals = tt_model.get_travel_times(stats.event_depth, dist, (phase, ))
    if len(arrivals) == 0:
        raise Exception('TauPy does not return phase %s at distance %s' %
                        (phase, dist))
    if len(arrivals) > 1:
        msg = ('TauPy returns more than one arrival for phase %s at '
               'distance -> take first arrival')
        warnings.warn(msg % (phase, dist))
    arrival = arrivals[0]
    onset = stats.event_time + arrival.time
    inc = arrival.incident_angle
    slowness = arrival.ray_param_sec_degree
    stats.update({
        'distance': dist,
        'back_azimuth': baz,
        'inclination': inc,
        'onset': onset,
        'slowness': slowness,
        'phase': phase
    })
    if pp_depth is not None:
        model = load_model(model)
        if pp_phase is None:
            pp_phase = 'S' if phase.upper().endswith('P') else 'P'
        model.ppoint(stats, pp_depth, phase=pp_phase)
    return stats
示例#9
0
def plot_profile(profile,
                 fname=None,
                 scale=1,
                 fillcolors=('r', 'b'),
                 trim=None,
                 top=None,
                 moveout_model='iasp91'):
    """
    Plot receiver function profile.

    :param profile: stream holding the profile
    :param fname: filename to save plot to. Can be None. In this case
        the figure is left open.
    :param scale: scale for individual traces
    :param fillcolors: fill colors for positive and negative wiggles
    :param trim: trim stream relative to onset before plotting using
         `~.rfstream.RFStream.slice2()`
    :param top: show second axes on top of profile with additional information.
        Valid values: 'hist' - Plot histogram showing the number of receiver
        functions stacked in the corresponding bin
    :param moveout_model: string with model filename. Will be loaded into a
        `~.simple_model.SimpleModel` object to calculate depths for
        tick labels.
    """
    if len(profile) == 0:
        return
    if trim:
        profile = profile.slice2(*trim, reftime='onset')
    fig = plt.figure()
    ax = fig.add_axes([0.1, 0.1, 0.8, 0.7])
    widths = [tr.stats.box_length for tr in profile]
    pad = max(1, scale) * min(widths)
    xlim = (min(tr.stats.box_pos for tr in profile) - pad,
            max(tr.stats.box_pos for tr in profile) + pad)
    max_ = max(np.max(np.abs(tr.data)) for tr in profile)
    for tr in profile:
        x = tr.stats.box_pos + scale * tr.data / max_ * min(widths)
        y = tr.times() - (tr.stats.onset - tr.stats.starttime)
        ax.plot(x, y, 'k')
        c1, c2 = fillcolors
        if c1:
            ax.fill_betweenx(y,
                             x,
                             tr.stats.box_pos,
                             where=x >= tr.stats.box_pos,
                             facecolor=c1)
        if c2:
            ax.fill_betweenx(y,
                             x,
                             tr.stats.box_pos,
                             where=x < tr.stats.box_pos,
                             facecolor=c2)
    ax.set_xlabel('distance (km)')
    ax.set_ylim(max(y), min(y))
    ax.set_ylabel('time (s)')
    if moveout_model:
        from rf.simple_model import load_model
        model = load_model(moveout_model)
        phase = profile[0].stats.moveout
        slowness = profile[0].stats.slowness
        pd = model.calculate_delay_times(phase=phase, slowness=slowness)
        ax2 = ax.twinx()
        ax.get_shared_y_axes().join(ax, ax2)
        dkm = 50
        if profile[0].stats.endtime - profile[0].stats.onset > 50:
            dkm = 200
        d1 = np.arange(20) * dkm
        d2 = np.arange(100) * dkm / 5
        t1 = np.interp(d1, model.z, pd)
        t2 = np.interp(d2, model.z, pd)
        myLocator = FixedLocator(t1)
        myMinorLocator = FixedLocator(t2)
        myFormatter = FixedFormatter([str(i) for i in d1])
        ax2.yaxis.set_major_locator(myLocator)
        ax2.yaxis.set_minor_locator(myMinorLocator)
        ax2.yaxis.set_major_formatter(myFormatter)
        ax2.set_ylabel('depth (km)')
        ax2.set_ylim(ax.get_ylim())
    if top is not None:
        ax3 = fig.add_axes([0.1, 0.85, 0.8, 0.1], sharex=ax)
    if top == 'hist':
        left = [tr.stats.box_pos - tr.stats.box_length / 2 for tr in profile]
        height = [tr.stats.num for tr in profile]
        ax3.bar(left, height, widths, color='cadetblue')
        plt.setp(ax3.get_xticklabels(), visible=False)
        ax3.spines['top'].set_color('none')
        ax3.spines['right'].set_color('none')
        ax3.spines['left'].set_color('none')
        ax3.xaxis.set_ticks_position('bottom')
        ax3.yaxis.set_ticks_position('left')
        ax3.set_yticks(ax3.get_ylim())
    elif top is not None:
        raise NotImplementedError("'%s' not supported for top parameter" % top)
    ax.set_xlim(*xlim)
    if fname:
        fig.savefig(fname)
        plt.close(fig)
示例#10
0
 def setUp(self):
     self.model = load_model()
示例#11
0
 def setUp(self):
     self.stream = RFStream(read())
     self.stream._write_test_header()
     self.model = load_model()
示例#12
0
 def setUp(self):
     self.model = load_model()
示例#13
0
文件: rfstream.py 项目: trichter/rf
def rfstats(obj=None, event=None, station=None,
            phase='P', dist_range='default', tt_model='iasp91',
            pp_depth=None, pp_phase=None, model='iasp91'):
    """
    Calculate ray specific values like slowness for given event and station.

    :param obj: `~obspy.core.trace.Stats` object with event and/or station
        attributes. Can be None if both event and station are given.
        It is possible to specify a stream object, too. Then, rfstats will be
        called for each Trace.stats object and traces outside dist_range will
        be discarded.
    :param event: ObsPy `~obspy.core.event.event.Event` object
    :param station: dictionary like object with items latitude, longitude and
        elevation
    :param phase: string with phase. Usually this will be 'P' or
        'S' for P and S receiver functions, respectively.
    :type dist_range: tuple of length 2
    :param dist_range: if epicentral of event is not in this intervall, None
        is returned by this function,\n
        if phase == 'P' defaults to (30, 90),\n
        if phase == 'S' defaults to (50, 85)
    :param tt_model: model for travel time calculation.
        (see the `obspy.taup` module, default: iasp91)
    :param pp_depth: Depth for piercing point calculation
        (in km, default: None -> No calculation)
    :param pp_phase: Phase for pp calculation (default: 'S' for P-receiver
        function and 'P' for S-receiver function)
    :param model: Path to model file for pp calculation
        (see `.SimpleModel`, default: iasp91)
    :return: `~obspy.core.trace.Stats` object with event and station
        attributes, distance, back_azimuth, inclination, onset and
        slowness or None if epicentral distance is not in the given interval.
        Stream instance if stream was specified instead of stats.
    """
    if isinstance(obj, (Stream, RFStream)):
        stream = obj
        kwargs = {'event': event, 'station': station,
                  'phase': phase, 'dist_range': dist_range,
                  'tt_model': tt_model, 'pp_depth': pp_depth,
                  'pp_phase': pp_phase, 'model': model}
        traces = []
        for tr in stream:
            if rfstats(tr.stats, **kwargs) is not None:
                traces.append(tr)
        stream.traces = traces
        return stream
    if dist_range == 'default' and phase.upper() in 'PS':
        dist_range = (30, 90) if phase.upper() == 'P' else (50, 85)
    stats = AttribDict({}) if obj is None else obj
    if event is not None and station is not None:
        stats.update(obj2stats(event=event, station=station))
    dist, baz, _ = gps2dist_azimuth(stats.station_latitude,
                                    stats.station_longitude,
                                    stats.event_latitude,
                                    stats.event_longitude)
    dist = dist / 1000 / DEG2KM
    if dist_range and not dist_range[0] <= dist <= dist_range[1]:
        return
    tt_model = TauPyModel(model=tt_model)
    arrivals = tt_model.get_travel_times(stats.event_depth, dist, (phase,))
    if len(arrivals) == 0:
        raise Exception('TauPy does not return phase %s at distance %s' %
                        (phase, dist))
    if len(arrivals) > 1:
        msg = ('TauPy returns more than one arrival for phase %s at '
               'distance -> take first arrival')
        warnings.warn(msg % (phase, dist))
    arrival = arrivals[0]
    onset = stats.event_time + arrival.time
    inc = arrival.incident_angle
    slowness = arrival.ray_param_sec_degree
    stats.update({'distance': dist, 'back_azimuth': baz, 'inclination': inc,
                  'onset': onset, 'slowness': slowness, 'phase': phase})
    if pp_depth is not None:
        model = load_model(model)
        if pp_phase is None:
            pp_phase = 'S' if phase.upper().endswith('P') else 'P'
        model.ppoint(stats, pp_depth, phase=pp_phase)
    return stats
示例#14
0
def rfstats(stats=None, event=None, station=None, stream=None,
            phase='P', dist_range=None, tt_model='iasp91',
            pp_depth=None, pp_phase=None, model='iasp91'):
    """
    Calculate ray specific values like slowness for given event and station.

    :param stats: stats object with event and/or station attributes. Can be
        None if both event and station are given.
    :param event: ObsPy :class:`~obspy.core.event.Event` object
    :param station: station object with attributes latitude, longitude and
        elevation
    :param stream: If a stream is given, stats has to be None. In this case
        rfstats will be called for every stats object in the stream.
    :param phase: string with phase. Usually this will be 'P' or
        'S' for P and S receiver functions, respectively.
    :type dist_range: tuple of length 2
    :param dist_range: if epicentral of event is not in this intervall, None
        is returned by this function,\n
        if phase == 'P' defaults to (30, 90),\n
        if phase == 'S' defaults to (50, 85)
    :param tt_model: model for travel time calculation.
        (see the :mod:`obspy.taup` module, default: iasp91)
    :param pp_depth: Depth for piercing point calculation
        (in km, default: None -> No calculation)
    :param pp_phase: Phase for pp calculation (default: 'S' for P-receiver
        function and 'P' for S-receiver function)
    :param model': Path to model file for pp calculation
        (see :class:`~rf.simple_model.SimpleModel`, default: iasp91)
    :return: ``stats`` object with event and station attributes, distance,
        back_azimuth, inclination, onset and slowness or None if epicentral
        distance is not in the given intervall
    """
    if stream is not None:
        assert stats is None
        kwargs = {'event': event, 'station': station, 'stream':None,
                  'phase': phase, 'dist_range': dist_range,
                  'tt_model':tt_model, 'pp_depth': pp_depth,
                  'pp_phase': pp_phase, 'model': model}
        for tr in stream:
            rfstats(stats=tr.stats, **kwargs)
        return
    phase = phase.upper()
    if dist_range is None and phase in 'PS':
        dist_range = (30, 90) if phase == 'P' else (50, 85)
    if stats is None:
        stats = AttribDict({})
    if event is not None and station is not None:
        stats.update(obj2stats(event=event, station=station))
    dist, baz, _ = gps2DistAzimuth(stats.station_latitude,
                                   stats.station_longitude,
                                   stats.event_latitude,
                                   stats.event_longitude)
    dist = kilometer2degrees(dist / 1000)
    if dist_range and not dist_range[0] <= dist <= dist_range[1]:
        return
    tt_model = TauPyModel(model=tt_model)
    arrivals = tt_model.get_travel_times(stats.event_depth, dist, (phase,))
    if len(arrivals) == 0:
        raise Exception('TauPy does not return phase %s at distance %s' %
                        (phase, dist))
    if len(arrivals) > 1:
        from warnings import warn
        msg = ('TauPy returns more than one arrival for phase %s at '
               'distance -> take first arrival' )
        warn(msg % (phase, dist))
    arrival = arrivals[0]
    onset = stats.event_time + arrival.time
    inc = arrival.incident_angle
    slowness = arrival.ray_param_sec_degree
    stats.update({'distance': dist, 'back_azimuth': baz, 'inclination': inc,
                  'onset': onset, 'slowness': slowness})
    if pp_depth is not None:
        model = load_model(model)
        if pp_phase is None:
            pp_phase = 'S' if phase.upper().endswith('P') else 'P'
        model.ppoint(stats, pp_depth, phase=pp_phase)
    return stats