Implementing FK filter #405
Replies: 2 comments 2 replies
-
|
Hey @Shihao-Yuan, this is a good start, and the examples are compelling. As far as suggestions, a few things come to mind:
So implementing these ideas (I haven't tested this, its just to get you started): import dascore as dc
@dc.patch_function()
def ft_slope_filter(patch, filt, dims=("time", "distance"), directional=False, notch=False):
"""
Filter the patch over certain slopes in the 2D Fourier domain.
Most commonly this used as an F-K (frequency wavenumber) filter to attenuate energy with specified
apparent velocities.
Parameters
-----------------
patch
The patch to filter.
filt
A length 4 sequence of the form (va, vb, vc, vd). If notch is False, {describe filter shape}
dims
The dimensions to filter/transform which
directional
If True, the filter should be considered direction. That is to say, the sign of the values in `filt` indicate the
direction (towards or away) with increasing coordinate values. This can be used for up-down/left-right
separation.
notch
If True, the filter represents a notch.
Examples
-----------------
# need several examples of each feature here, including passing a patch that has already been dft'ed.
Notes
---------
- It is a good idea to first pad the transformed dimensions to fast fft lengths. See [Patch.pad](`dascore.Patch.pad`).
- See the [F-K filter page](`docs/processing/fk.qmd`).
"""
# Perform dft if needed.
dft_patch = patch.dft(dims)
transformed = dft_patch is not patch # if dft didn't create a new patch it was already in dft.
# Get slope array for specified dimensions
assert len(dims) == 2, "dims must be a length 2 tuple"
coord1 = dft_patch.get_array(f"ft_{dims[0]}")
coord2 = dft_patch.get_array(f"ft_{dims[1]}")
vel = coord1 / coord2[:, None]
if not directional:
vel = np.abs(vel)
# Apply filter with tapering function
fac = np.where((vel >= va) & (vel <= vb), 1.0 - np.sin(0.5 * np.pi * (vel - va) / (vb - va)), 1.0)
fac = np.where((vel >= vb) & (vel <= vc), 0.0, fac)
fac = np.where((vel >= vc) & (vel <= vd), np.sin(0.5 * np.pi * (vel - vc) / (vd - vc)), fac)
if passband:
fac = 1.0 - fac
# Apply filter
new_data = fft_patch.data * fac
out = fft_patch.update(data=new_data)
# Undo transformation if an un-transformed patch was passed in.
if transformed:
out = fft_patch.idft()
return outSince this is a really powerful filter, I suggest we create a recipe or processing page called f-k filtering. In that page we could show:
Does anyone else have any thoughts on this function design? |
Beta Was this translation helpful? Give feedback.
-
|
closed by #413 |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
I've implemented an F-K filter function for the Patch data type. Could any of you please test it and provide feedback?
Beta Was this translation helpful? Give feedback.
All reactions