示例#1
0
文件: stack.py 项目: pan3rock/yam
def stack(stream, length=None, move=None):
    """
    Stack traces in stream by correlation id

    :param stream: |Stream| object with correlations
    :param length: time span of one trace in the stack in seconds
        (alternatively a string consisting of a number and a unit
        -- ``'d'`` for days and ``'h'`` for hours -- can be specified,
        i.e. ``'3d'`` stacks together all traces inside a three days time
        window, default: None, which stacks together all traces)
    :param move: define a moving stack, float or string,
        default: None -- no moving stack,
        if specified move usually is smaller than length to get an overlap
        in the stacked traces
    :return: |Stream| object with stacked correlations
    """
    stream.sort()
    stream_stack = obspy.Stream()
    ids = {_corr_id(tr) for tr in stream}
    ids.discard(None)
    for id_ in ids:
        traces = [tr for tr in stream if _corr_id(tr) == id_]
        if length is None:
            data = np.mean([tr.data for tr in traces], dtype=float, axis=0)
            tr_stack = obspy.Trace(data, header=traces[0].stats)
            tr_stack.stats.key = tr_stack.stats.key + '_s'
            if 'num' in traces[0].stats:
                tr_stack.stats.num = sum(tr.stats.num for tr in traces)
            else:
                tr_stack.stats.num = len(traces)
            stream_stack.append(tr_stack)
        else:
            t1 = traces[0].stats.starttime
            lensec = _time2sec(length)
            movesec = _time2sec(move) if move else lensec
            if (lensec % (24 * 3600) == 0
                    or isinstance(length, str) and 'd' in length):
                t1 = UTC(t1.year, t1.month, t1.day)
            elif (lensec % 3600 == 0
                  or isinstance(length, str) and 'm' in length):
                t1 = UTC(t1.year, t1.month, t1.day, t1.hour)
            t2 = max(t1, traces[-1].stats.endtime - lensec)
            for t in IterTime(t1, t2, dt=movesec):
                sel = [
                    tr for tr in traces
                    if -0.1 <= tr.stats.starttime - t <= lensec + 0.1
                ]
                if len(sel) == 0:
                    continue
                data = np.mean([tr.data for tr in sel], dtype=float, axis=0)
                tr_stack = obspy.Trace(data, header=sel[0].stats)
                key_add = '_s%s' % length + (move is not None) * ('m%s' % move)
                tr_stack.stats.key = tr_stack.stats.key + key_add
                tr_stack.stats.starttime = t
                if 'num' in traces[0].stats:
                    tr_stack.stats.num = sum(tr.stats.num for tr in sel)
                else:
                    tr_stack.stats.num = len(sel)
                stream_stack.append(tr_stack)
    return stream_stack
示例#2
0
文件: imaging.py 项目: junxie01/yam
def plot_corr_vs_dist(stream,
                      fname,
                      figsize=(10, 5),
                      ext='png',
                      dpi=None,
                      components='ZZ',
                      line_style='k',
                      scale=1,
                      dist_unit='km',
                      xlim=None,
                      ylim=None,
                      time_period=None):
    """
    Plot stacked correlations versus inter-station distance

    .. image:: _static/corr_vs_dist.png
       :width: 30%

    This plot can be created from the command line with ``--plottype vs_dist``.

    :param components: component combination to plot
    :param scale: scale wiggles (default 1)
    :param dist_unit: one of ``('km', 'm', 'deg')``
    :time_period: use correlations only from this time span (tuple of dates)
    """
    # scale relative to axis
    traces = [
        tr for tr in stream
        if _corr_id(tr).split('-')[0][-1] + _corr_id(tr)[-1] == components
    ]
    stream.traces = traces
    _trim_time_period(stream, time_period)
    stack = yam.stack.stack(stream)
    if len(stack) == 0:
        msg = 'Not plotting anything. No traces in stack with components %s'
        warn(msg % components)
        return
    fig = plt.figure(figsize=figsize)
    ax = fig.add_subplot(111)
    dist_scale = (1 if dist_unit == 'm' else 1000 *
                  111.2 if dist_unit == 'deg' else 1000)
    max_dist = max(tr.stats.dist / dist_scale for tr in stack)
    for tr in stack:
        lag_times = _trim(tr, xlim)
        scaled_data = tr.stats.dist / dist_scale + tr.data * max_dist * scale
        ax.plot(lag_times, scaled_data, line_style)
    fname = '%s_%s' % (fname, components)
    label = os.path.basename(fname)
    ax.set_ylim(ylim)
    ax.annotate(label, (0, 1), (10, 10),
                'axes fraction',
                'offset points',
                annotation_clip=False,
                va='bottom')
    ax.set_ylabel('distance (%s)' % dist_unit)
    ax.set_xlabel('time (s)')
    fig.savefig(fname + '.' + ext, dpi=dpi)
示例#3
0
def plot_corr_vs_time_wiggle(stream,
                             fname=None,
                             figsize=(10, 5),
                             ext='png',
                             dpi=None,
                             xlim=None,
                             ylim=None,
                             scale=20,
                             plot_kw={}):
    """
    Plot correlation wiggles versus time

    .. image:: _static/corr_vs_time_wiggle.png
       :width: 30%
    .. image:: _static/corr_vs_time_wiggle2.png
       :width: 40%

    This plot can be created from the command line with ``--plottype wiggle``.

    :param scale: scale of wiggles (default 20)
    """
    plot_kw = plot_kw.copy()
    plot_kw.setdefault('lw', 0.5)
    plot_kw.setdefault('color', 'black')
    # scale relative to neighboring wiggles
    ids = {_corr_id(tr) for tr in stream}
    if len(ids) != 1:
        warn('Different ids in stream: %s' % ids)
    stream.sort(['starttime'])
    _trim_time_period(stream, ylim)
    times = [tr.stats.starttime.matplotlib_date for tr in stream]
    dt = np.median(np.diff(times))
    fig = plt.figure(figsize=figsize)
    ax = fig.add_subplot(111)
    for tr in stream:
        lag_times = _trim(tr, xlim)
        scaled_data = tr.stats.starttime.matplotlib_date + tr.data * dt * scale
        ax.plot(lag_times, scaled_data, **plot_kw)
    label = '' if fname is None else os.path.basename(fname)
    ax.annotate(label, (0, 1), (10, 10),
                'axes fraction',
                'offset points',
                annotation_clip=False,
                va='bottom')
    ax.set_ylabel('date')
    ax.set_xlabel('time (s)')
    ax.yaxis_date()
    if fname is not None:
        fig.savefig(fname + '.' + ext, dpi=dpi)
示例#4
0
文件: stretch.py 项目: trichter/yam
def stretch(stream,
            max_stretch,
            num_stretch,
            tw,
            tw_relative=None,
            reftr=None,
            sides='both',
            max_lag=None,
            time_period=None):
    """
    Stretch traces in stream and return dictionary with results

    See e.g. Richter et al. (2015) for a description of the procedure.

    :param stream: |Stream| object with correlations
    :param float max_stretch: stretching range in percent
    :param int num_stretch: number of values in stretching vector
    :param tw: definition of the time window in the correlation --
        tuple of length 2 with start and end time in seconds (positive)
    :param tw_relative: time windows can be defined relative to a
        velocity, default None or 0 -- time windows relative to zero lag time,
        otherwise velocity is given in km/s
    :param reftr: reference trace, by default the stack of stream is used
        as reference
    :param sides: one of left, right, both
    :param max_lag: max lag time in seconds, stream is trimmed to
        ``(-max_lag, max_lag)`` before stretching
    :param time_period: use correlations only from this time span
        (tuple of dates)
    """
    if len(stream) <= 1:
        log.warning('For stretch the stream must have a minimum length of 2')
        return
    ids = {_corr_id(tr) for tr in stream}
    if None in ids:
        ids.discard(None)
        stream.traces = [tr for tr in stream if _corr_id(tr) is not None]
    if len(ids) != 1:
        warn('Different ids in stream: %s' % ids)
    _trim_time_period(stream, time_period)
    stream.sort()
    tr0 = stream[0]
    if max_lag is not None:
        for tr in stream:
            _trim(tr, (-max_lag, max_lag))
    rel = 0 if tw_relative is None else tr0.stats.dist / 1000 / tw_relative
    twabs = rel + np.array(tw)
    starttime = tr0.stats.starttime
    mid = starttime + (tr0.stats.endtime - starttime) / 2
    times = tr0.times(reftime=mid)
    data = np.array([tr.data for tr in stream])
    data[np.isnan(data)] = 0  # bug fix
    data[np.isinf(data)] = 0
    if reftr is None:
        reftr = yam.stack.stack(stream)[0]
    stretch_vector_perc = np.linspace(-max_stretch, max_stretch, num_stretch)
    stretch_factor = 1 + stretch_vector_perc / 100
    # MIIC approximation:
    #stretch_factor = np.exp(stretch_vector_percent / 100)

    mask1 = np.logical_and(times >= twabs[0], times <= twabs[1])
    mask2 = np.logical_and(times <= -twabs[0], times >= -twabs[1])
    if sides == 'left':
        mask = mask1
    elif sides == 'right':
        mask = mask2
    elif sides == 'both':
        mask = np.logical_or(mask1, mask2)
    else:
        raise ValueError('sides = %s not a valid option' % sides)
    sim_mat = _stretch_helper(data, reftr.data, mask, stretch_factor)
    times = np.array([str(tr.stats.starttime)[:19] for tr in stream],
                     dtype='S19')
    result = {
        'sim_mat': sim_mat,
        'velchange_values': stretch_vector_perc,
        'times': times,
        'tw': twabs,
        'attrs': {
            'num_stretch': num_stretch,
            'max_stretch': max_stretch,
            'sides': sides,
            'starttime': stream[0].stats.starttime,
            'endtime': stream[-1].stats.starttime
        }
    }
    _update_result(result)
    for k in ('network1', 'network2', 'station1', 'station2', 'location1',
              'location2', 'channel1', 'channel2', 'sampling_rate', 'dist',
              'azi', 'baz'):
        if k in tr0.stats:
            result['attrs'][k] = tr0.stats[k]
    return result
示例#5
0
def stretch(stream, reftr=None, str_range=10, nstr=100,
            time_windows=None,
            time_windows_relative=None, sides='right',
            max_lag=None, time_period=None
            ):
    """
    Stretch traces in stream and return dictionary with results

    See e.g. Richter et al. (2015) for a description of the procedure.

    :param stream: |Stream| object with correlations
    :param reftr: reference trace -- not implemented yet, the reference
        is the stack of the stream
    :param float str_range: stretching range in percent
    :param int nstr: number of values in stretching vector
    :param time_windows: definition of time windows in the correlation --
        tuple of length 2, first entry: tuple of start times in seconds,
        second entry: length in seconds, e.g. ``((5, 10, 15), 5)`` defines
        three time windows of length 5 seconds starting at 5, 10, 15 seconds
    :param time_windows_relative: time windows can be defined relative to a
        velocity, default None or 0 -- time windows relative to zero leg time,
        otherwise velocity is given in km/s
    :param max_lag: max lag time in seconds, stream is trimmed to
        ``(-max_lag, max_lag)`` before stretching
    :param time_period: use correlations only from this time span
        (tuple of dates)
    """
    if len(stream) <= 1:
        log.warning('For stretch the stream must have a minimum length of 2')
        return
    ids = {_corr_id(tr) for tr in stream}
    if None in ids:
        ids.discard(None)
        stream.traces = [tr for tr in stream if _corr_id(tr) is not None]
    if len(ids) != 1:
        warn('Different ids in stream: %s' % ids)
    _trim_time_period(stream, time_period)
    stream.sort()
    sr = stream[0].stats.sampling_rate
    rel = 0.
    if time_windows_relative is not None:
        rel = np.round(stream[0].stats.dist / 1000 / time_windows_relative)
    if time_windows is not None and isinstance(time_windows[1], (float, int)):
        args = ((rel + np.array(time_windows[0])) * int(sr),
                time_windows[1] * int(sr))
        tw_mat = time_windows_creation(*args)
    else:
        raise ValueError('Wrong format for time_window')
    if max_lag is not None:
        for tr in stream:
            _trim(tr, (-max_lag, max_lag))
    data = np.array([tr.data for tr in stream])
    if np.min(tw_mat) < 0 or data.shape[1] < np.max(tw_mat):
        msg = ('Defined time window outside of data. '
               'shape, mintw index, maxtw index: %s, %s, %s')
        raise ValueError(msg % (data.shape[1], np.min(tw_mat), np.max(tw_mat)))
    data[np.isnan(data)] = 0  # bug fix
    data[np.isinf(data)] = 0
    if reftr is None:
        reftr = yam.stack.stack(stream)[0]
    if reftr != 'alternative':
        if hasattr(reftr, 'stats'):
            assert reftr.stats.sampling_rate == sr
            ref_data = reftr.data
            #ref_data = _stream2matrix(obspy.Stream([reftr]))[0, :]
        else:
            ref_data = reftr
#        log.debug('calculate correlations and time shifts...')
        # convert str_range from % to decimal
        tse = time_stretch_estimate(
            data, ref_trc=ref_data, tw=tw_mat, stretch_range=str_range / 100,
            stretch_steps=nstr, sides=sides)
#    else:
#        assert len(tw_mat) == len(stretch)
#        tses = []
#        log.debug('calculate correlations and time shifts...')
#        for i in range(len(tw_mat)):
#            tw = tw_mat[i:i + 1]
#            st = stretch[i]
#            sim_mat = time_stretch_apply(data, st, single_sided=False)
#            ref_data = np.mean(sim_mat, axis=0)
#            tse = time_stretch_estimate(data, ref_trc=ref_data, tw=tw,
#                                 stretch_range=str_range, stretch_steps=nstr,
#                                 sides=sides)
#            tses.append(tse)
#        for i in ('corr', 'stretch'):
#            tse[i] = np.hstack([t[i] for t in tses])
#        i = 'sim_mat'
#        tse[i] = np.vstack([t[i] for t in tses])
    times = np.array([str(tr.stats.starttime)[:19] for tr in stream],
                     dtype='S19')
    ltw1 = rel + np.array(time_windows[0])
    # convert streching to velocity change
    # -> minus at several places
    result = {'sim_mat': tse['sim_mat'][:, ::-1, :],
              'velchange_values': -tse['second_axis'][::-1] * 100,
              'times': times,
              #'velchange_vs_time': -tse['value'] * 100,
              #'corr_vs_time': tse['corr'],
              'lag_time_windows': np.transpose([ltw1, ltw1 + time_windows[1]]),
              'attrs': {'nstr': nstr,
                        'str_range': str_range,
                        'sides': sides,
                        'starttime': stream[0].stats.starttime,
                        'endtime': stream[-1].stats.starttime
                        }
              }
    _update_result(result)
    for k in ('network1', 'network2', 'station1', 'station2',
              'location1', 'location2', 'channel1', 'channel2',
              'sampling_rate', 'dist', 'azi', 'baz'):
        result['attrs'][k] = stream[0].stats[k]
    return result
示例#6
0
def plot_corr_vs_time(stream,
                      fname,
                      figsize=(10, 5),
                      ext='png',
                      xlim=None,
                      ylim=None,
                      vmax=None,
                      cmap='RdBu_r',
                      show_stack=True,
                      line_style='k',
                      line_width=1):
    """
    Plot correlations versus time

    .. image:: _static/corr_vs_time.png
       :width: 30%
    .. image:: _static/corr_vs_time_zoom.png
       :width: 30%

    Default correlation plot.

    :param vmax: maximum value in colormap
    :param cmap: used colormap
    :param show_stack: show a wiggle plot of the stack at top
    """
    ids = {_corr_id(tr) for tr in stream}
    if len(ids) != 1:
        warn('Different ids in stream: %s' % ids)
    stream.sort(['starttime'])
    _trim_time_period(stream, ylim)
    for tr in stream:
        lag_times = _trim(tr, xlim)
    times = [tr.stats.starttime.matplotlib_date for tr in stream]
    fig = plt.figure(figsize=figsize)
    ax = fig.add_axes([0.15, 0.1, 0.75, 0.75])
    cax = fig.add_axes([0.91, 0.375, 0.008, 0.25])
    data = np.array([tr.data for tr in stream])
    if vmax is None:
        vmax = min(0.8 * np.max(data), 0.1)
    no_data = _get_times_no_data(times)
    times = _add_value(times, no_data)
    times2 = _align_values_for_pcolormesh(times)
    lag_times2 = _align_values_for_pcolormesh(lag_times)
    data2 = _add_value(np.transpose(data), no_data, value=0, masked=True)
    data2 = np.transpose(data2)
    mesh = ax.pcolormesh(lag_times2,
                         times2,
                         data2,
                         cmap=cmap,
                         vmin=-vmax,
                         vmax=vmax)
    fig.colorbar(mesh, cax)
    ax.set_ylabel('date')
    ax.set_xlabel('time (s)')
    ax.yaxis_date()
    ax_ano = ax
    if show_stack:
        ax2 = fig.add_axes([0.15, 0.85, 0.75, 0.05], sharex=ax)
        stack = yam.stack.stack(stream)
        ax2.plot(lag_times, stack[0].data, line_style, lw=line_width)
        ax2.set_ylim(-vmax, vmax)
        ax2.set_ylabel('stack')
        plt.setp(ax2.get_xticklabels(), visible=False)
        ax_ano = ax2
    ax.set_xlim(lag_times[0], lag_times[-1])
    label = os.path.basename(fname)
    ax_ano.annotate(label, (0, 1), (10, 10),
                    'axes fraction',
                    'offset points',
                    annotation_clip=False,
                    va='bottom')
    fig.savefig(fname + '.' + ext)
示例#7
0
def plot_corr_vs_time(stream,
                      fname=None,
                      figsize=(10, 5),
                      ext='png',
                      dpi=None,
                      xlim=None,
                      ylim=None,
                      vmax=None,
                      cmap='RdBu_r',
                      stack_plot_kw={}):
    """
    Plot correlations versus time

    .. image:: _static/corr_vs_time.png
       :width: 30%
    .. image:: _static/corr_vs_time_zoom.png
       :width: 30%

    Default correlation plot.

    :param vmax: maximum value in colormap
    :param cmap: used colormap
    """
    ids = {_corr_id(tr) for tr in stream}
    srs = {tr.stats.sampling_rate for tr in stream}
    lens = {len(tr) for tr in stream}
    if len(ids) != 1:
        warn('Different ids in stream: %s' % ids)
    # These checks should be done when saving the correlations to hdf5.
    # On the other hand side, these problems will not occur often.
    if len(srs) != 1:
        sr = np.median([tr.stats.sampling_rate for tr in stream])
        msg = 'Different sampling rates in stream: %s -> set %s Hz (%s)'
        warn(msg % (srs, sr, stream[0].id))
        for tr in stream:
            tr.stats.sampling_rate = sr
    if len(lens) != 1:
        msg = ('Different lengths of traces in stream: %s (%s)'
               '-> Plese use xlim parameter to trim traces')
        warn(msg % (lens, stream[0].id))
    stream.sort(['starttime'])
    _trim_time_period(stream, ylim)
    for tr in stream:
        lag_times = _trim(tr, xlim)
    times = [tr.stats.starttime.matplotlib_date for tr in stream]
    fig = plt.figure(figsize=figsize)
    ax = fig.add_axes([0.15, 0.1, 0.75, 0.75])
    cax = fig.add_axes([0.91, 0.375, 0.008, 0.25])
    data = np.array([tr.data for tr in stream])
    if vmax is None:
        vmax = min(0.8 * np.max(data), 0.1)
    no_data = _get_times_no_data(times)
    times = _add_value(times, no_data)
    times2 = _align_values_for_pcolormesh(times)
    lag_times2 = _align_values_for_pcolormesh(lag_times)
    data2 = _add_value(np.transpose(data), no_data, value=0, masked=True)
    data2 = np.transpose(data2)
    mesh = ax.pcolormesh(lag_times2,
                         times2,
                         data2,
                         cmap=cmap,
                         vmin=-vmax,
                         vmax=vmax)
    fig.colorbar(mesh, cax)
    ax.set_ylabel('date')
    ax.set_xlabel('time (s)')
    ax.yaxis_date()
    ax_ano = ax
    if stack_plot_kw is not None:
        stack_plot_kw = stack_plot_kw.copy()
        stack_plot_kw.setdefault('color', 'black')
        stack_plot_kw.setdefault('lw', 1)
        ax2 = fig.add_axes([0.15, 0.85, 0.75, 0.05], sharex=ax)
        stack = yam.stack.stack(stream)
        ax2.plot(lag_times, stack[0].data, **stack_plot_kw)
        ax2.set_ylim(-vmax, vmax)
        ax2.set_ylabel('stack')
        plt.setp(ax2.get_xticklabels(), visible=False)
        ax_ano = ax2
    ax.set_xlim(lag_times[0], lag_times[-1])
    label = '' if fname is None else os.path.basename(fname)
    ax_ano.annotate(label, (0, 1), (10, 10),
                    'axes fraction',
                    'offset points',
                    annotation_clip=False,
                    va='bottom')
    if fname is not None:
        fig.savefig(fname + '.' + ext, dpi=dpi)