你已经派生过 gpr-sidl-inv
镜像自地址
https://gitee.com/sduem/gpr-sidl-inv.git
已同步 2025-08-03 10:56:50 +08:00
142 行
5.4 KiB
Python
142 行
5.4 KiB
Python
import numpy as np
|
|
from scipy.ndimage.filters import uniform_filter1d
|
|
from scipy.signal import firwin, lfilter
|
|
import readgssi.functions as fx
|
|
|
|
"""
|
|
Mathematical filtering routines for array manipulation
|
|
Written in part by François-Xavier Simon (@fxsimon)
|
|
"""
|
|
|
|
def bgr(ar, header, win=0, verbose=False):
|
|
"""
|
|
Horizontal background removal (BGR). Subtracts off row averages for full-width or window-length slices. For usage see :ref:`Getting rid of horizontal noise`.
|
|
|
|
:param numpy.ndarray ar: The radar array
|
|
:param dict header: The file header dictionary
|
|
:param int win: The window length to process. 0 resolves to full-width, whereas positive integers dictate the window size in post-stack traces.
|
|
:rtype: :py:class:`numpy.ndarray`
|
|
"""
|
|
if (int(win) > 1) & (int(win) < ar.shape[1]):
|
|
window = int(win)
|
|
how = 'boxcar (%s trace window)' % window
|
|
else:
|
|
how = 'full only'
|
|
if verbose:
|
|
fx.printmsg('removing horizontal background using method=%s...' % (how))
|
|
i = 0
|
|
for row in ar: # each row
|
|
mean = np.mean(row)
|
|
ar[i] = row - mean
|
|
i += 1
|
|
if how != 'full only':
|
|
if window < 10:
|
|
fx.printmsg('WARNING: BGR window size is very short. be careful, this may obscure horizontal layering')
|
|
if window < 3:
|
|
window = 3
|
|
elif (window / 2. == int(window / 2)):
|
|
window = window + 1
|
|
ar -= uniform_filter1d(ar, size=window, mode='constant', cval=0, axis=1)
|
|
|
|
return ar
|
|
|
|
def dewow(ar, verbose=False):
|
|
"""
|
|
Polynomial dewow filter. Written by fxsimon.
|
|
|
|
.. warning:: This filter is still experimental.
|
|
|
|
:param numpy.ndarray ar: The radar array
|
|
:param bool verbose: Verbose, default is False
|
|
:rtype: :py:class:`numpy.ndarray`
|
|
"""
|
|
fx.printmsg('WARNING: dewow filter is experimental')
|
|
if verbose:
|
|
fx.printmsg('dewowing data...')
|
|
signal = list(zip(*ar))[10]
|
|
model = np.polyfit(range(len(signal)), signal, 3)
|
|
predicted = list(np.polyval(model, range(len(signal))))
|
|
i = 0
|
|
for column in ar.T: # each column
|
|
ar.T[i] = column + predicted
|
|
i += 1
|
|
return ar
|
|
|
|
def bp(ar, header, freqmin, freqmax, zerophase=True, verbose=False):
|
|
"""
|
|
Vertical butterworth bandpass. This filter is not as effective as :py:func:`triangular` and thus is not available through the command line interface or through :py:func:`readgssi.readgssi.readgssi`.
|
|
|
|
Filter design and implementation are dictated by :py:func:`obspy.signal.filter.bandpass`.
|
|
|
|
:param np.ndarray ar: The radar array
|
|
:param dict header: The file header dictionary
|
|
:param int freqmin: The lower corner of the bandpass
|
|
:param int freqmax: The upper corner of the bandpass
|
|
:param bool zerophase: Whether to run the filter forwards and backwards in order to counteract the phase shift
|
|
:param bool verbose: Verbose, defaults to False
|
|
:rtype: :py:class:`numpy.ndarray`
|
|
"""
|
|
from obspy.signal.filter import bandpass
|
|
|
|
if verbose:
|
|
fx.printmsg('vertical butterworth bandpass filter')
|
|
fx.printmsg('NOTE: better results are achieved with readgssi.filtering.triangular()')
|
|
#samp_freq = 1 / ((header['rhf_depth'] * 2) / header['cr'] / header['rh_nsamp'])
|
|
samp_freq = header['samp_freq']
|
|
freqmin = freqmin * 10 ** 6
|
|
freqmax = freqmax * 10 ** 6
|
|
|
|
corners = 1
|
|
|
|
if verbose:
|
|
fx.printmsg('sampling frequency: %.2E Hz' % samp_freq)
|
|
fx.printmsg('minimum filter frequency: %.2E Hz' % freqmin)
|
|
fx.printmsg('maximum filter frequency: %.2E Hz' % freqmax)
|
|
fx.printmsg('corners: %s, zerophase: %s' % (corners, zerophase))
|
|
|
|
i = 0
|
|
for t in ar.T:
|
|
f = bandpass(data=t, freqmin=freqmin, freqmax=freqmax, df=samp_freq, corners=corners, zerophase=zerophase)
|
|
ar[:,i] = f
|
|
i += 1
|
|
return ar
|
|
|
|
def triangular(ar, header, freqmin, freqmax, zerophase=True, verbose=False):
|
|
"""
|
|
Vertical triangular FIR bandpass. This filter is designed to closely emulate that of RADAN.
|
|
|
|
Filter design is implemented by :py:func:`scipy.signal.firwin` with :code:`numtaps=25` and implemented with :py:func:`scipy.signal.lfilter`.
|
|
|
|
.. note:: This function is not compatible with scipy versions prior to 1.3.0.
|
|
|
|
:param np.ndarray ar: The radar array
|
|
:param dict header: The file header dictionary
|
|
:param int freqmin: The lower corner of the bandpass
|
|
:param int freqmax: The upper corner of the bandpass
|
|
:param bool zerophase: Whether to run the filter forwards and backwards in order to counteract the phase shift
|
|
:param bool verbose: Verbose, defaults to False
|
|
:rtype: :py:class:`numpy.ndarray`
|
|
"""
|
|
if verbose:
|
|
fx.printmsg('vertical triangular FIR bandpass filter')
|
|
#samp_freq = 1 / ((header['rhf_depth'] * 2) / header['cr'] / header['rh_nsamp'])
|
|
samp_freq = header['samp_freq']
|
|
freqmin = freqmin * 10 ** 6
|
|
freqmax = freqmax * 10 ** 6
|
|
|
|
numtaps = 25
|
|
|
|
if verbose:
|
|
fx.printmsg('sampling frequency: %.2E Hz' % samp_freq)
|
|
fx.printmsg('minimum filter frequency: %.2E Hz' % freqmin)
|
|
fx.printmsg('maximum filter frequency: %.2E Hz' % freqmax)
|
|
fx.printmsg('numtaps: %s, zerophase: %s' % (numtaps, zerophase))
|
|
|
|
filt = firwin(numtaps=numtaps, cutoff=[freqmin, freqmax], window='triangle', pass_zero='bandpass', fs=samp_freq)
|
|
|
|
far = lfilter(filt, 1.0, ar, axis=0).copy()
|
|
if zerophase:
|
|
far = lfilter(filt, 1.0, far[::-1], axis=0)[::-1]
|
|
|
|
return far
|