-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added codes for filtering and examples on Nstage FWI
- Loading branch information
Showing
8 changed files
with
6,204 additions
and
3,978 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
import numpy as np | ||
import matplotlib.pyplot as plt | ||
|
||
from scipy.signal import butter, sosfiltfilt, correlate, freqs, hilbert | ||
|
||
|
||
def create_filter(nfilt, fmin, fmax, dt, plotflag=False): | ||
if fmin is None: | ||
b, a = butter(nfilt, fmax, 'low', analog=True) | ||
sos = butter(nfilt, fmax, 'low', fs=1 / dt, output='sos') | ||
else: | ||
b, a = butter(nfilt, [fmin, fmax], 'bandpass', analog=True) | ||
sos = butter(nfilt, [fmin, fmax], 'bandpass', fs=1 / dt, output='sos') | ||
|
||
if plotflag: | ||
w, h = freqs(b, a) | ||
plt.semilogx(w, 20 * np.log10(abs(h)), 'k', lw=2) | ||
plt.title('Butterworth filter frequency response') | ||
plt.xlabel('Frequency [radians / second]') | ||
plt.ylabel('Amplitude [dB]') | ||
plt.margins(0, 0.1) | ||
plt.grid(which='both', axis='both') | ||
plt.axvline(fmax, color='green') # cutoff frequency | ||
|
||
return b, a, sos | ||
|
||
|
||
def apply_filter(sos, inp): | ||
filtered = sosfiltfilt(sos, inp, axis=-1) | ||
return filtered | ||
|
||
|
||
def filter_data(nfilt, fmin, fmax, dt, inp, plotflag=False): | ||
"""Filter data | ||
Apply Butterworth band-pass filter to data | ||
Parameters | ||
---------- | ||
nfilt : :obj:`int` | ||
Size of filter | ||
fmin : :obj:`float` | ||
Minimum frequency | ||
fmax : :obj:`float` | ||
Maximum frequency | ||
dt : :obj:`float` | ||
Time sampling | ||
inp : :obj:`numpy.ndarray` | ||
Data of size `nx x nt` | ||
Returns | ||
------- | ||
b : :obj:`numpy.ndarray` | ||
Filter numerator coefficients | ||
b : :obj:`numpy.ndarray` | ||
Filter denominator coefficients | ||
sos : :obj:`numpy.ndarray` | ||
Filter sos | ||
filtered : :obj:`numpy.ndarray` | ||
Filtered data of size `nx x nt` | ||
""" | ||
b, a, sos = create_filter(nfilt, fmin, fmax, dt, plotflag=plotflag) | ||
filtered = apply_filter(sos, inp) | ||
|
||
return b, a, sos, filtered | ||
|
||
|
||
class Filter(): | ||
"""Filtering | ||
Define a sequence of filters to apply to a dataset/wavelet | ||
Parameters | ||
---------- | ||
freqs : :obj:`list` | ||
Minimum frequencies | ||
nfilt : :obj:`int` | ||
Size of filters | ||
dt : :obj:`float` | ||
Time sampling | ||
p | ||
""" | ||
def __init__(self, freqs, nfilts, dt, plotflag=False): | ||
self.freqs = freqs | ||
self.nfilts = nfilts | ||
self.dt = dt | ||
self.plotflag = plotflag | ||
self.filters = self._create_filters() | ||
|
||
def _create_filters(self): | ||
filters = [] | ||
|
||
for freq, nfilt in zip(self.freqs, self.nfilts): | ||
filters.append(create_filter(nfilt, None, freq, self.dt, plotflag=self.plotflag)[-1]) | ||
return filters | ||
|
||
def apply_filter(self, inp, ifilt=0): | ||
return apply_filter(self.filters[ifilt], inp) | ||
|
||
def find_optimal_t0(self, inp, pad=400, thresh=1e-2): | ||
"""Find optimal padding | ||
Identify optimal padding to avoid any filtered signal to become acausal. To be used when designing the filters | ||
to choose how much the wavelet and observed data must be padded | ||
""" | ||
inppad = np.pad(inp, (pad, pad)) | ||
itmax = np.argmax(np.abs(inppad)) | ||
it0 = np.where(np.abs(inppad[:itmax]) < thresh * inppad[itmax])[0][-1] | ||
for ifilt in range(len(self.filters)): | ||
inpfilt = apply_filter(self.filters[ifilt], inppad) | ||
inpfiltenv = np.abs(hilbert(inpfilt)) | ||
it0filt = np.where(np.abs(inpfiltenv[:itmax]) < thresh * inpfiltenv[itmax])[0][-1] | ||
it0 = min(it0, it0filt) | ||
optimalpad = pad - it0 | ||
return optimalpad |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
import numpy as np | ||
import matplotlib.pyplot as plt | ||
|
||
from examples.seismic.utils import sources, PointSource | ||
|
||
|
||
class CustomSource(PointSource): | ||
|
||
""" | ||
Abstract base class for symbolic objects that encapsulates a set of | ||
sources with a user defined source signal wavelet. | ||
Parameters | ||
---------- | ||
name : str | ||
Name for the resulting symbol. | ||
grid : Grid | ||
The computational domain. | ||
time_range : TimeAxis | ||
TimeAxis(start, step, num) object. | ||
wav : numpy.ndarray | ||
Wavelet | ||
""" | ||
|
||
__rkwargs__ = PointSource.__rkwargs__ + ['wav'] | ||
|
||
@classmethod | ||
def __args_setup__(cls, *args, **kwargs): | ||
kwargs.setdefault('npoint', 1) | ||
|
||
return super().__args_setup__(*args, **kwargs) | ||
|
||
def __init_finalize__(self, *args, **kwargs): | ||
super().__init_finalize__(*args, **kwargs) | ||
|
||
self.wav = kwargs.get('wav') | ||
|
||
if not self.alias: | ||
for p in range(kwargs['npoint']): | ||
self.data[:, p] = self.wavelet | ||
|
||
@property | ||
def wavelet(self): | ||
""" | ||
Return user-provided wavelet | ||
""" | ||
return self.wav | ||
|
||
def show(self, idx=0, wavelet=None): | ||
""" | ||
Plot the wavelet of the specified source. | ||
Parameters | ||
---------- | ||
idx : int | ||
Index of the source point for which to plot wavelet. | ||
wavelet : ndarray or callable | ||
Prescribed wavelet instead of one from this symbol. | ||
""" | ||
wavelet = wavelet or self.data[:, idx] | ||
plt.figure() | ||
plt.plot(self.time_values, wavelet) | ||
plt.xlabel('Time (ms)') | ||
plt.ylabel('Amplitude') | ||
plt.tick_params() | ||
plt.show() | ||
|
||
|
||
sources['CustomSource'] = CustomSource | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
from os import listdir, path | ||
from shutil import rmtree | ||
from tempfile import gettempdir | ||
|
||
|
||
def clear_devito_cache(): | ||
tempdir = gettempdir() | ||
for i in listdir(tempdir): | ||
if i.startswith('devito-'): | ||
try: | ||
target = path.join(tempdir, i) | ||
rmtree(target) | ||
except: | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
Oops, something went wrong.