Пример #1
0
def _build_weight(config, spec, specnoise):
    weight = spec.copy()
    if specnoise is not None:
        weight.data /= specnoise.data
        # save data to raw_data
        weight.data_raw = weight.data.copy()
        # The inversion is done in magnitude units,
        # so let's take log10 of weight
        weight.data = np.log10(weight.data)
        # Weight spectrum is smoothed once more
        _smooth_spectrum(weight, config.spectral_smooth_width_decades)
        weight.data /= np.max(weight.data)
        # slightly taper weight at low frequencies, to avoid overestimating
        # weight at low frequencies, in cases where noise is underestimated
        cosine_taper(weight.data, spec.stats.delta / 4, left_taper=True)
        # Make sure weight is positive
        weight.data[weight.data <= 0] = 0.001
    else:
        msg = '{}: No available noise window: a uniform weight will be applied'
        msg = msg.format(weight.get_id()[0:-1])
        logger.warning(msg)
        weight.data = np.ones(len(spec.data))
    # interpolate to log-frequencies
    f = interp1d(weight.get_freq(), weight.data, fill_value='extrapolate')
    weight.data_log = f(weight.freq_log)
    weight.data_log /= np.max(weight.data_log)
    # Make sure weight is positive
    weight.data_log[weight.data_log <= 0] = 0.001
    return weight
def _get_cut_times(config, tr):
    """Get trace cut times between P arrival and end of envelope coda."""
    tr_env = tr.copy()
    # remove the mean...
    tr_env.detrend(type='constant')
    # ...and the linear trend...
    tr_env.detrend(type='linear')
    # ...filter
    freqmin = 1.
    freqmax = 20.
    nyquist = 1./(2. * tr.stats.delta)
    if freqmax >= nyquist:
        freqmax = nyquist * 0.999
        msg = '%s: maximum frequency for bandpass filtering ' % tr.id
        msg += 'in local magnitude computation is larger than or equal '
        msg += 'to Nyquist. Setting it to %s Hz' % freqmax
        logger.warning(msg)
    cosine_taper(tr_env.data, width=config.taper_halfwidth)
    tr_env.filter(type='bandpass', freqmin=freqmin, freqmax=freqmax)
    tr_env.data = envelope(tr_env.data)
    tr_env.data = smooth(tr_env.data, 100)

    # Skip traces which do not have arrivals
    try:
        p_arrival_time = tr.stats.arrivals['P'][1]
    except Exception:
        logger.warning('%s: Trace has no P arrival: skipping trace' % tr.id)
        raise RuntimeError
    t1 = p_arrival_time - config.win_length
    t2 = p_arrival_time + config.win_length

    tr_noise = tr_env.copy()
    tr_signal = tr_env.copy()
    tr_noise.trim(starttime=t1, endtime=p_arrival_time,
                  pad=True, fill_value=0)
    tr_signal.trim(starttime=p_arrival_time, endtime=t2,
                   pad=True, fill_value=0)
    ampmin = tr_noise.data.mean()
    ampmax = tr_signal.data.mean()
    if ampmax <= ampmin:
        logger.warning(
            '%s: Trace has too high noise before P arrival: '
            'skipping trace' % tr.id)
        raise RuntimeError

    trigger = trigger_onset(tr_env.data, ampmax, ampmin,
                            max_len=9e99, max_len_delete=False)[0]
    t0 = p_arrival_time
    t1 = t0 + trigger[-1] * tr.stats.delta
    if t1 > tr.stats.endtime:
        t1 = tr.stats.endtime
    return t0, t1
Пример #3
0
def _process_trace(config, tr, t0, t1):
    """Convert to Wood-Anderson, filter, trim."""
    tr_process = tr.copy()
    # Do a preliminary trim, in order to check if there is enough
    # data within the selected time window
    tr_process.trim(starttime=t0, endtime=t1, pad=True, fill_value=0)
    npts = len(tr_process.data)
    if npts == 0:
        logger.warning('%s: No data for the selected cut interval: '
                       'skipping trace' % tr.id)
        raise RuntimeError
    nzeros = len(np.where(tr_process.data == 0)[0])
    if nzeros > npts / 4:
        logger.warning('%s: Too many gaps for the selected cut '
                       'interval: skipping trace' % tr.id)
        raise RuntimeError

    # If the check is ok, recover the full trace
    # (it will be cutted later on)
    tr_process = tr.copy()
    # remove the mean...
    tr_process.detrend(type='constant')
    # ...and the linear trend...
    tr_process.detrend(type='linear')
    freqmin = config.ml_bp_freqmin
    freqmax = config.ml_bp_freqmax
    # ...remove response...
    pre_filt = (freqmin, freqmin * 1.1, freqmax * 0.9, freqmax)
    remove_instr_response(tr_process, config.correct_instrumental_response,
                          pre_filt)
    # ...filter
    tr_process.filter(type='bandpass', freqmin=freqmin, freqmax=freqmax)
    # Convert to Wood-Anderson
    # note: conversion to Wood-Anderson integrates the signal once
    if tr.stats.instrtype == 'acc':
        WA_double_int = deepcopy(WOODANDERSON)
        # we remove a zero to add an integration step
        WA_double_int['zeros'].pop()
        tr_process.simulate(paz_simulate=WA_double_int)
    else:
        tr_process.simulate(paz_simulate=WOODANDERSON)
    # trim...
    tr_process.trim(starttime=t0, endtime=t1, pad=True, fill_value=0)
    # ...and taper
    cosine_taper(tr_process.data, width=config.taper_halfwidth)
    return tr_process
Пример #4
0
def _cut_signal_noise(config, trace):
    trace_signal = trace.copy()
    trace_noise = trace.copy()

    # Integrate in time domain, if required.
    # (otherwhise frequency-domain integration is
    # performed later)
    if config.time_domain_int:
        _time_integrate(config, trace_signal)
        _time_integrate(config, trace_noise)

    # trim...
    t1 = trace.stats.arrivals['S1'][1]
    t2 = trace.stats.arrivals['S2'][1]
    trace_signal.trim(starttime=t1, endtime=t2, pad=True, fill_value=0)
    # Noise time window for weighting function:
    noise_t1 = trace.stats.arrivals['N1'][1]
    noise_t2 = trace.stats.arrivals['N2'][1]
    trace_noise.trim(starttime=noise_t1,
                     endtime=noise_t2,
                     pad=True,
                     fill_value=0)
    # ...taper...
    cosine_taper(trace_signal.data, width=config.taper_halfwidth)
    cosine_taper(trace_noise.data, width=config.taper_halfwidth)
    if config.spectral_win_length is not None:
        # ...and zero pad to spectral_win_length
        trace_signal.trim(starttime=t1,
                          endtime=t1 + config.spectral_win_length,
                          pad=True,
                          fill_value=0)
        trace_noise.trim(starttime=noise_t1,
                         endtime=noise_t1 + config.spectral_win_length,
                         pad=True,
                         fill_value=0)
    # Be sure that both traces have same length:
    if len(trace_signal) != len(trace_noise):
        npts = min(len(trace_signal), len(trace_noise))
        trace_signal.data = trace_signal.data[:npts]
        trace_noise.data = trace_noise.data[:npts]

    return trace_signal, trace_noise