Open OUCyf opened 1 year ago
Or it could be possible to add the arf
function in the package? Hope it will be easy for you!
Dear Fu,
Apologies for my belated reply. At the moment, there is no direct way to plot array response functions in TwistPy. However, there is a simple workaround that allows you to readily compute ARF's with the current version of the code.
What you should do is generate some reference data for a monochromatic plane-wave with a specific reference slowness (typically, the reference slowness vector is chosen to be equal to 0, corresponding to a plane wave at vertical incidence) and then perform beamforming on this reference data. The output should then directly correspond to the ARF.
Please find an example for a cross-shaped array with 0 reference slowness below:
import numpy as np
import matplotlib.pyplot as plt
from obspy import Trace, UTCDateTime
from twistpy.array_processing import BeamformingArray
from twistpy.convenience import to_obspy_stream
N = 5 # Number of sensors per line
s_ref = np.array([0, 0, 0]) # Reference slowness vector
f = 0.02 # Frequency of the signal (Hz)
t = np.arange(0, 1 / f, 1 / f / 1001) # Time axis stretching over 1 period
x = 1e3 * np.linspace(-300, 300, N) # x-coordinates of the sensors
y = 1e3 * np.linspace(-300, 300, N) # y-coordinates of the sensors
x = np.concatenate((x, np.zeros(x.shape)))
y = np.concatenate((np.zeros(y.shape), y))
z = np.zeros((2 * N,)) # z-coordinates of the sensors (Assuming a flat topography)
coordinates = np.array([x, y, z]).T
# Generate a monochromatic plane wave propagating in the direction given by the reference slowness vector
data = np.sin(
2 * np.pi * np.dot(np.array([x, y, z]).T, s_ref)
- 2 * np.pi * f * np.reshape(t, (t.size, 1))
)
start_time = UTCDateTime(2022, 2, 1, 10, 00, 00, 0)
data_st = to_obspy_stream(data.T, start_time, t[1] - t[0])
# Beamforming
inclination = (
0,
90,
1,
) # Search space for the inclination in degrees (min_value, max_value, increment)
azimuth = (
0,
360,
1,
) # Search space for the back-azimuth in degrees (min_value, max_value, increment)
velocity = 1000.0 # Intra-array velocity in m/s
# The array response function will be plotted as a function of
# the horizontaal slowness which is given by s = sin(inclination)* (1 / velocity)
s_max = 1 / velocity # Maximum slowness (s/m)
# is unknown and part of the search
number_of_sources = 1 # Specify the number of interfering sources that will be estimated in the time window
# (only relevant for MUSIC)
array = BeamformingArray(name="Test Array", coordinates=coordinates)
array.add_data(data_st)
array.compute_steering_vectors(
frequency=f,
inclination=inclination,
azimuth=azimuth,
intra_array_velocity=velocity,
)
freq_band = (0.01, 0.03) # Frequency band of interest
P_BARTLETT = array.beamforming(
method="BARTLETT",
event_time=start_time + t[501],
frequency_band=freq_band,
window=1,
)
P_MVDR = array.beamforming(
method="MVDR", event_time=start_time + t[501], frequency_band=freq_band, window=1
)
P_MUSIC = array.beamforming(
method="MUSIC",
event_time=start_time + t[501],
frequency_band=freq_band,
window=1,
number_of_sources=1,
)
# Plot the ARF for the different methods
azi_plot = np.arange(azimuth[0], azimuth[1] + azimuth[2], azimuth[2])
inc_plot = np.arange(inclination[0], inclination[1] + inclination[2], inclination[2])
azi_plot, inc_plot = np.meshgrid(
np.radians(azi_plot), np.sin(np.radians(inc_plot)) * (s_max)
)
fig_bf_polar, ax_bf_polar = plt.subplots(
1, 3, sharex=True, sharey=True, figsize=(15, 6), subplot_kw=dict(polar=True)
)
for ax_p in ax_bf_polar:
ax_p.set_theta_direction(-1)
ax_p.set_theta_offset(np.pi / 2.0)
ax_bf_polar[0].pcolormesh(azi_plot, inc_plot, P_MUSIC.squeeze())
ax_bf_polar[0].set_xlabel("Horizontal Slowness")
ax_bf_polar[0].set_title("MUSIC ARF")
ax_bf_polar[1].pcolormesh(azi_plot, inc_plot, P_MVDR.squeeze())
ax_bf_polar[1].set_xlabel("Horizontal Slowness")
ax_bf_polar[1].set_title("MVDR (Capon) ARF")
ax_bf_polar[2].pcolormesh(azi_plot, inc_plot, P_BARTLETT.squeeze())
ax_bf_polar[2].set_xlabel("Horizontal Slowness")
ax_bf_polar[2].set_title("BARTLETT (Conventional) ARF")
plt.figure()
plt.plot(x, y, "vk")
plt.title("Array geometry")
plt.xlabel("X (m)")
plt.ylabel("Y (m)")
plt.grid()
plt.show()
I didn't have time to test this extensively, so it would be great if you could confirm that this is what you are looking for. At first glance, the plots I get look as expected.
I will keep this issue open and potentially include a simpler way to plot ARF's in the future.
Best regards,
David
Thanks David! I appreciate that a lot!
Greetings, I'm Fu, and very nice package! When i use the beamforming method, I modify some of your code to get the
array response function
, but the results look like very weird.According to the book 2018
seismic ambient noise
, I set the cross spectral densityC
matrix to be the identity matrix in the following, I don't it is correct or not?Best, Fu
and the function
compute_steering_vectors
: