pycsamt.emtools.source_array#

Phased-array (PAS) transmitter design and radiation pattern analysis for CSAMT.

Implements the element and array-factor formulas from:
gxac023Fan, Zhang & Wang (2022), “A novel phased-array transmitting

source in controlled-source audio-frequency magnetotellurics”, J. Geophys. Eng. 19, 595–614.

A traditional CSAMT transmitter is a single-dipole antenna source (SDAS). The novel PAS consists of N co-linear SDASes with independent phase control. The energy is focussed into a steerable beam, improving SNR and enlarging the area of interest (AoI) without increasing transmitter power.

Key formulas#

Element pattern (eq. 7):

F(θ) = [cos(kl cosθ/2) − cos(kl/2)] / sinθ θ measured from dipole/array axis (y). θ=0 → null; θ=90° → maximum.

Array factor (eq. 19):

AF_n = sin(N ψ/2) / [N sin(ψ/2)], ψ = k d sin θ_b + β θ_b = broadside angle from perpendicular to array.

Beam-steering condition (eq. 23):

β = −k d sin θ_m

Earth wavenumber for CSAMT (real part of complex k₁):

k_eff = sqrt(π f μ₀ / ρ) [m⁻¹]

Functions

array_factor(theta_b_deg, N, d, k[, beta])

Normalised array factor AF_n for an N-element linear PAS (eq.

beam_steer(theta_m_deg, d, k)

Inter-element phase shift β [rad] to steer the main lobe to θ_m (eq.

pas_pattern(theta_b_deg, N, d, k[, beta, l, ...])

Total normalised far-field pattern of an N-element PAS.

plot_radiation_pattern(theta_b_deg, patterns, *)

Plot one or more radiation patterns in polar or Cartesian format.

sdas_directivity(l, k, *[, n_theta])

2-D horizontal-plane directivity D₀ = 2π U_max / ∫ U(θ) dθ (eq.

sdas_element_pattern(theta_deg, l, k, *[, ...])

Far-field element pattern for a single finite-length SDAS (eq.

snr_gain_db(N)

SNR improvement of an N-element PAS relative to a single SDAS [dB].

steering_angles(N, d, k, beta, *[, n_range])

All main-lobe broadside angles [degrees] for the given PAS configuration.

wavenumber(freq[, rho])

Effective real wavenumber k [m⁻¹] for CSAMT or free-space propagation.

pycsamt.emtools.source_array.wavenumber(freq, rho=None)[source]#

Effective real wavenumber k [m⁻¹] for CSAMT or free-space propagation.

Parameters:
  • freq (float) – Frequency [Hz].

  • rho (float or None) – Half-space resistivity [Ω·m]. If given, returns the earth (CSAMT) effective wavenumber Re(k₁) = sqrt(π f μ₀ / ρ). If None, returns the free-space wavenumber f / c.

Returns:

k – Wavenumber [m⁻¹].

Return type:

float

Notes

The complex earth wavenumber is k₁ = √(i ω μ₀ / ρ). Its real part equals |k₁| / √2 = √(π f μ₀ / ρ). The corresponding wavelength is λ = 2π / k_eff ≈ 2π × 503 × √(ρ/f) [m].

pycsamt.emtools.source_array.sdas_element_pattern(theta_deg, l, k, *, normalize=True)[source]#

Far-field element pattern for a single finite-length SDAS (eq. 7).

The dipole / array axis is the y-axis. The angle θ is measured FROM the y-axis, so θ = 0° is along the dipole (null) and θ = 90° is broadside (maximum).

Parameters:
  • theta_deg (float or ndarray) – Angle(s) from the dipole axis [degrees], range [0, 180].

  • l (float) – SDAS (dipole) physical length [m].

  • k (float) – Wavenumber [m⁻¹]. Use wavenumber() to compute for given frequency and resistivity.

  • normalize (bool) – Normalize the peak to 1.0 (default True).

Returns:

F|F(θ)| pattern values (≥ 0).

Return type:

ndarray

Notes

F(θ) = |[cos(kl cosθ/2) − cos(kl/2)]| / |sinθ|. The singularity at θ = 0° and 180° resolves to zero by L’Hôpital’s rule.

pycsamt.emtools.source_array.array_factor(theta_b_deg, N, d, k, beta=0.0)[source]#

Normalised array factor AF_n for an N-element linear PAS (eq. 19).

The angle θ_b is measured FROM BROADSIDE (perpendicular to the array axis). θ_b = 0° is the maximum direction when β = 0; θ_b = ±90° is along the array (end-fire direction).

Parameters:
  • theta_b_deg (float or ndarray) – Broadside angle(s) [degrees], range [−90, 90].

  • N (int) – Number of SDAS elements.

  • d (float) – Element-to-element spacing [m].

  • k (float) – Wavenumber [m⁻¹].

  • beta (float) – Inter-element phase shift [rad]. β = 0 → broadside array; use beam_steer() to compute β for a target angle.

Returns:

AF – Normalised |AF_n(θ_b)| ∈ [0, 1].

Return type:

ndarray

Notes

AF_n = sin(N ψ/2) / [N sin(ψ/2)], ψ = k d sinθ_b + β.

pycsamt.emtools.source_array.pas_pattern(theta_b_deg, N, d, k, beta=0.0, l=1000.0, *, normalize=True)[source]#

Total normalised far-field pattern of an N-element PAS.

The combined pattern is the product of the SDAS element pattern and the array factor, evaluated at the same observation angle.

Parameters:
  • theta_b_deg (float or ndarray) – Broadside angle(s) [degrees], range [−90, 90].

  • N (int) – Number of SDAS elements.

  • d (float) – Element spacing [m].

  • k (float) – Wavenumber [m⁻¹].

  • beta (float) – Inter-element phase shift [rad].

  • l (float) – SDAS length [m] (default 1000 m matching gxac023).

  • normalize (bool) – Normalize peak to 1.0 (default True).

Returns:

pattern – Combined |E_total(θ_b)| pattern (≥ 0).

Return type:

ndarray

pycsamt.emtools.source_array.beam_steer(theta_m_deg, d, k)[source]#

Inter-element phase shift β [rad] to steer the main lobe to θ_m (eq. 23).

Parameters:
  • theta_m_deg (float) – Target main-lobe broadside angle [degrees].

  • d (float) – Element spacing [m].

  • k (float) – Wavenumber [m⁻¹].

Returns:

beta – Required phase shift [rad]. Apply the same β to each SDAS via the feed-network inductance delay.

Return type:

float

Notes

Condition (eq. 23): β = −k d sinθ_m.

pycsamt.emtools.source_array.steering_angles(N, d, k, beta, *, n_range=3)[source]#

All main-lobe broadside angles [degrees] for the given PAS configuration.

Solves k d sinθ + β = ±2nπ (eq. 21) for n = 0, ±1, ±2, …

Parameters:
  • N (int / float) – Array parameters (as in array_factor()).

  • d (int / float) – Array parameters (as in array_factor()).

  • k (int / float) – Array parameters (as in array_factor()).

  • beta (float) – Inter-element phase shift [rad].

  • n_range (int) – Search over n = −n_range … +n_range (default 3).

Returns:

angles – Sorted array of main-lobe broadside angles [degrees] inside [−90°, 90°].

Return type:

ndarray

pycsamt.emtools.source_array.sdas_directivity(l, k, *, n_theta=2000)[source]#

2-D horizontal-plane directivity D₀ = 2π U_max / ∫ U(θ) dθ (eq. 12).

Parameters:
  • l (float) – SDAS length [m].

  • k (float) – Wavenumber [m⁻¹].

  • n_theta (int) – Number of angular samples for numerical integration.

Returns:

D0 – Directivity (dimensionless). A perfect omnidirectional source has D₀ = 1 in 2-D.

Return type:

float

pycsamt.emtools.source_array.snr_gain_db(N)[source]#

SNR improvement of an N-element PAS relative to a single SDAS [dB].

For coherent beam forming, the gain scales as N²: G_PAS / G_SDAS = N² → 10 log₁₀(N²) = 20 log₁₀(N) dB.

Parameters:

N (int) – Number of SDAS elements.

Returns:

gain_dB – SNR gain [dB].

Return type:

float

pycsamt.emtools.source_array.plot_radiation_pattern(theta_b_deg, patterns, *, labels=None, polar=True, normalize=True, log_scale=False, db_floor=-40.0, title='Radiation pattern', figsize=(7.0, 7.0), ax=None)[source]#

Plot one or more radiation patterns in polar or Cartesian format.

Parameters:
  • theta_b_deg (array-like) – Broadside angles [degrees], range [−90, 90].

  • patterns (array-like or list of array-like) – Pattern amplitude(s). A 2-D array is treated as multiple patterns with shape (n_patterns, n_angles).

  • labels (list of str or None) – Legend labels for each pattern.

  • polar (bool) – Polar (default) or Cartesian plot.

  • normalize (bool) – Normalise each pattern to its peak before plotting.

  • log_scale (bool) – Convert to dB (20 log₁₀) for the radial / y-axis.

  • db_floor (float) – Minimum dB value when log_scale=True (default −40 dB).

  • title (str) – Axes title.

  • figsize (tuple) – Figure size if a new figure is created.

  • ax (matplotlib.axes.Axes or None) – Axes to draw on; created if None.

Returns:

ax

Return type:

matplotlib.axes.Axes