Impairments Module#
The impairments module provides functions to model real-world effects that degrade phased array performance, including mutual coupling, phase quantization, element failures, and scan blindness.
Mutual Coupling#
- phased_array.mutual_coupling_matrix_theoretical(geometry, k, coupling_model='sinc', coupling_coeff=0.3)[source]#
Compute theoretical mutual coupling matrix.
- Parameters:
geometry (
ArrayGeometry) – Array geometryk (
float) – Wavenumber (2*pi/wavelength)coupling_model (
str) – ‘sinc’ - sinc function model (good for dipoles) ‘exponential’ - exponential decay modelcoupling_coeff (
float) – Coupling coefficient (typical: 0.1-0.5)
- Returns:
C – N x N complex mutual coupling matrix
- Return type:
ndarray
- phased_array.mutual_coupling_matrix_measured(s_parameters)[source]#
Convert measured S-parameters to coupling matrix.
The coupling matrix relates actual element currents to excitation voltages: I = C^(-1) @ V
- Parameters:
s_parameters (
ndarray) – N x N S-parameter matrix (complex)- Returns:
C – Mutual coupling matrix
- Return type:
ndarray
- phased_array.apply_mutual_coupling(weights, C, mode='transmit')[source]#
Apply mutual coupling to element weights.
- Parameters:
weights (
ndarray) – Ideal element weights (N,)C (
ndarray) – Mutual coupling matrix (N x N)mode (
str) – ‘transmit’ - coupling affects radiated field ‘receive’ - coupling affects received signal ‘compensate’ - pre-distort to compensate coupling
- Returns:
effective_weights – Weights after coupling effects
- Return type:
ndarray
- phased_array.active_element_pattern(theta, phi, geometry, element_idx, C, k, isolated_element_pattern=None)[source]#
Compute active element pattern including mutual coupling.
The active element pattern is the pattern of a single element when all other elements are terminated in matched loads.
- Parameters:
theta (
ndarray) – Observation theta anglesphi (
ndarray) – Observation phi anglesgeometry (
ArrayGeometry) – Array geometryelement_idx (
int) – Index of the element to compute pattern forC (
ndarray) – Mutual coupling matrixk (
float) – Wavenumberisolated_element_pattern (
callable, optional) – Pattern function for isolated element
- Returns:
pattern – Active element pattern (complex)
- Return type:
ndarray
Phase Quantization#
- phased_array.quantize_phase(weights, n_bits)[source]#
Quantize phase shifter settings to discrete levels.
- Parameters:
weights (
ndarray) – Complex weights (phase will be quantized)n_bits (
int) – Number of bits for phase quantization (e.g., 3 bits = 8 levels)
- Returns:
quantized_weights – Weights with quantized phases
- Return type:
ndarray
Examples
Quantize to 3-bit phase shifters (8 levels, 45 deg steps):
>>> import numpy as np >>> import phased_array as pa >>> geom = pa.create_rectangular_array(8, 8, dx=0.5, dy=0.5) >>> k = pa.wavelength_to_k(1.0) >>> weights = pa.steering_vector(k, geom.x, geom.y, theta0_deg=15, phi0_deg=0) >>> weights_q = pa.quantize_phase(weights, n_bits=3) >>> weights_q.shape (64,)
Check phase quantization levels:
>>> phases_deg = np.rad2deg(np.angle(weights_q)) >>> np.unique(np.round(phases_deg / 45) * 45).size <= 8 True
Compare effect of different bit depths:
>>> rms_3bit = pa.quantization_rms_error(3) # ~13 degrees >>> rms_6bit = pa.quantization_rms_error(6) # ~1.6 degrees >>> rms_3bit > rms_6bit True
- phased_array.quantization_rms_error(n_bits)[source]#
Compute theoretical RMS phase error for quantization.
- phased_array.quantization_sidelobe_increase(n_bits)[source]#
Estimate sidelobe level increase due to phase quantization.
- phased_array.analyze_quantization_effect(weights, geometry, k, n_bits, theta_range=(0, 1.5707963267948966), n_points=361)[source]#
Analyze effect of phase quantization on the pattern.
- Parameters:
weights (
ndarray) – Ideal complex weightsgeometry (
ArrayGeometry) – Array geometryk (
float) – Wavenumbern_bits (
int) – Quantization bitstheta_range (
tuple) – Range for pattern computationn_points (
int) – Number of angle points
- Returns:
results – ‘theta_deg’: angle array ‘pattern_ideal_dB’: ideal pattern ‘pattern_quantized_dB’: quantized pattern ‘difference_dB’: pattern difference
- Return type:
Element Failures#
- phased_array.simulate_element_failures(weights, failure_rate, mode='off', seed=None)[source]#
Simulate random element failures.
- Parameters:
weights (
ndarray) – Nominal element weightsfailure_rate (
float) – Probability of failure per element (0 to 1)mode (
str) – ‘off’ - failed elements have zero output ‘stuck’ - failed elements stuck at nominal magnitude, random phase ‘full’ - failed elements at full power, random phaseseed (
int, optional) – Random seed
- Returns:
degraded_weights (
ndarray) – Weights with failures appliedfailure_mask (
ndarray) – Boolean array, True for failed elements
- Return type:
Examples
Simulate 5% element failure rate:
>>> import numpy as np >>> import phased_array as pa >>> geom = pa.create_rectangular_array(16, 16, dx=0.5, dy=0.5) >>> k = pa.wavelength_to_k(1.0) >>> weights = pa.steering_vector(k, geom.x, geom.y, theta0_deg=0, phi0_deg=0) >>> degraded, mask = pa.simulate_element_failures( ... weights, failure_rate=0.05, mode='off', seed=42 ... ) >>> n_failed = np.sum(mask) >>> degraded.shape (256,)
Compare failure modes:
>>> # 'off' mode: failed elements produce no output >>> w_off, m_off = pa.simulate_element_failures(weights, 0.1, mode='off', seed=1) >>> np.all(w_off[m_off] == 0) True
Analyze graceful degradation:
>>> results = pa.analyze_graceful_degradation( ... geom, k, weights, failure_rates=[0.0, 0.05, 0.1] ... )
- phased_array.analyze_graceful_degradation(weights, geometry, k, failure_rates, n_trials=100, mode='off')[source]#
Monte Carlo analysis of graceful degradation vs failure rate.
- Parameters:
weights (
ndarray) – Nominal weightsgeometry (
ArrayGeometry) – Array geometryk (
float) – Wavenumberfailure_rates (
list) – Failure rates to testn_trials (
int) – Number of Monte Carlo trials per ratemode (
str) – Failure mode
- Returns:
results – ‘failure_rates’: input rates ‘gain_loss_mean_dB’: mean gain loss ‘gain_loss_std_dB’: std of gain loss ‘sidelobe_increase_mean_dB’: mean sidelobe increase
- Return type:
Scan Blindness#
- phased_array.surface_wave_scan_angle(dx, dy, substrate_er=4.0, substrate_h=0.1)[source]#
Estimate scan blindness angles due to surface wave excitation.
- Parameters:
- Returns:
- Return type:
- phased_array.scan_blindness_model(theta, phi, theta_blind, phi_blind=None, null_width_deg=5.0, null_depth_dB=-30.0)[source]#
Model scan blindness as a Gaussian null at the blind angle.
- Parameters:
theta (
ndarray) – Observation theta angles (radians)phi (
ndarray) – Observation phi angles (radians)theta_blind (
float) – Blind angle theta (degrees)phi_blind (
float, optional) – Blind angle phi (degrees). If None, blindness is phi-independentnull_width_deg (
float) – Width of the null (degrees, 1-sigma)null_depth_dB (
float) – Depth of null in dB (negative)
- Returns:
factor – Multiplicative factor (0 to 1)
- Return type:
ndarray
- phased_array.apply_scan_blindness(pattern, theta, phi, theta_blind_list, phi_blind_list=None, null_width_deg=5.0, null_depth_dB=-30.0)[source]#
Apply scan blindness model to a computed pattern.
- Parameters:
pattern (
ndarray) – Complex or magnitude patterntheta (
ndarray) – Theta angles (radians)phi (
ndarray) – Phi angles (radians)theta_blind_list (
list) – List of blind angles (degrees)phi_blind_list (
list, optional) – List of blind phi anglesnull_width_deg (
float) – Null widthnull_depth_dB (
float) – Null depth
- Returns:
modified_pattern – Pattern with scan blindness applied
- Return type:
ndarray
- phased_array.compute_scan_loss(geometry, weights, k, theta_scan_deg, phi_scan_deg, element_pattern_func=None)[source]#
Compute scan loss (reduction in peak gain at scan angle).
- Parameters:
geometry (
ArrayGeometry) – Array geometryweights (
ndarray) – Element weightsk (
float) – Wavenumbertheta_scan_deg (
float) – Scan angle thetaphi_scan_deg (
float) – Scan angle phielement_pattern_func (
callable, optional) – Element pattern function
- Returns:
scan_loss_dB – Reduction in gain relative to broadside (negative or zero)
- Return type: