文件
gpr-sidl-inv/readgssi/filtering.py
葛峻恺 a02133baed program
Signed-off-by: 葛峻恺 <202115006@mail.sdu.edu.cn>
2025-04-07 12:31:46 +00:00

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