Digital Array Models API¶
ADC/DAC converters, bandwidth calculations, and timeline scheduling for digital phased arrays.
Overview¶
from phased_array_systems.models.digital import (
# Converters
enob_to_snr,
snr_to_enob,
enob_to_sfdr,
sfdr_to_enob,
quantization_noise_floor,
sample_rate_for_bandwidth,
max_signal_bandwidth,
adc_dynamic_range,
dac_output_power,
# Bandwidth
beam_bandwidth_product,
max_simultaneous_beams,
digital_beamformer_data_rate,
channelizer_output_rate,
processing_margin,
beamformer_operations,
# Scheduling
Dwell,
Timeline,
Function,
timeline_utilization,
max_update_rate,
search_timeline,
interleaved_timeline,
)
Converters¶
Functions for analyzing ADC/DAC performance including ENOB, SNR, SFDR, and quantization noise.
Key Relationships¶
- SNR (ideal) = 6.02 * ENOB + 1.76 dB
- SFDR ~ SNR for ideal converters
- Nyquist: fs >= 2 * BW (practical: fs >= 2.5 * BW)
enob_to_snr
¶
Convert Effective Number of Bits to SNR.
The ideal SNR for a converter with ENOB effective bits is
SNR = 6.02 * ENOB + 1.76 dB
This assumes full-scale sinusoidal input and ideal quantization.
| PARAMETER | DESCRIPTION |
|---|---|
enob
|
Effective number of bits
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
float
|
SNR in dB |
Source code in src/phased_array_systems/models/digital/converters.py
snr_to_enob
¶
Convert SNR to Effective Number of Bits.
Inverse of enob_to_snr
ENOB = (SNR - 1.76) / 6.02
Useful for determining effective resolution from measured SNR.
| PARAMETER | DESCRIPTION |
|---|---|
snr_db
|
Signal-to-noise ratio in dB
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
float
|
Effective number of bits |
Source code in src/phased_array_systems/models/digital/converters.py
enob_to_sfdr
¶
Estimate SFDR from ENOB.
For an ideal converter, SFDR is approximately equal to SNR. Real converters may have SFDR limited by harmonic distortion.
| PARAMETER | DESCRIPTION |
|---|---|
enob
|
Effective number of bits
TYPE:
|
margin_db
|
Derate factor for non-ideal behavior (default 0)
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
float
|
Estimated SFDR in dB |
Source code in src/phased_array_systems/models/digital/converters.py
sfdr_to_enob
¶
Convert SFDR to equivalent ENOB.
Useful for determining effective dynamic range in bits.
| PARAMETER | DESCRIPTION |
|---|---|
sfdr_db
|
Spurious-free dynamic range in dB
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
float
|
Equivalent ENOB |
Source code in src/phased_array_systems/models/digital/converters.py
quantization_noise_floor
¶
quantization_noise_floor(enob: float, full_scale_dbm: float, bandwidth_hz: float, sample_rate_hz: float) -> float
Calculate quantization noise floor in dBm/Hz.
The quantization noise power is spread across the Nyquist bandwidth. Noise floor density = Full scale - SNR - 10*log10(fs/2)
| PARAMETER | DESCRIPTION |
|---|---|
enob
|
Effective number of bits
TYPE:
|
full_scale_dbm
|
Full-scale input power in dBm
TYPE:
|
bandwidth_hz
|
Signal bandwidth in Hz
TYPE:
|
sample_rate_hz
|
Sample rate in Hz
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
float
|
Noise floor spectral density in dBm/Hz |
Source code in src/phased_array_systems/models/digital/converters.py
sample_rate_for_bandwidth
¶
Calculate minimum sample rate for a given signal bandwidth.
Nyquist requires fs >= 2*BW, but practical systems use oversampling to ease anti-aliasing filter requirements.
| PARAMETER | DESCRIPTION |
|---|---|
signal_bandwidth_hz
|
Signal bandwidth in Hz
TYPE:
|
oversampling_ratio
|
Ratio of sample rate to Nyquist rate - 2.0: Minimum (steep filter required) - 2.5: Typical (recommended) - 4.0: Relaxed filtering
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
float
|
Required sample rate in Hz |
Source code in src/phased_array_systems/models/digital/converters.py
max_signal_bandwidth
¶
Calculate maximum signal bandwidth for a given sample rate.
Inverse of sample_rate_for_bandwidth.
| PARAMETER | DESCRIPTION |
|---|---|
sample_rate_hz
|
ADC/DAC sample rate in Hz
TYPE:
|
oversampling_ratio
|
Ratio of sample rate to Nyquist rate
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
float
|
Maximum signal bandwidth in Hz |
Source code in src/phased_array_systems/models/digital/converters.py
adc_dynamic_range
¶
adc_dynamic_range(enob: float, noise_figure_db: float = 0.0, input_noise_dbm_hz: float = -174.0, bandwidth_hz: float = 1.0) -> dict[str, float]
Calculate ADC dynamic range metrics.
Computes the usable dynamic range considering both quantization noise and thermal noise contributions.
| PARAMETER | DESCRIPTION |
|---|---|
enob
|
Effective number of bits
TYPE:
|
noise_figure_db
|
Front-end noise figure in dB
TYPE:
|
input_noise_dbm_hz
|
Input noise density (default: thermal at 290K)
TYPE:
|
bandwidth_hz
|
Signal bandwidth for integrated noise
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
dict[str, float]
|
Dictionary with: - snr_db: Quantization-limited SNR - noise_floor_dbm: Integrated noise floor - max_input_dbm: Maximum input before clipping - dynamic_range_db: Usable dynamic range |
Source code in src/phased_array_systems/models/digital/converters.py
dac_output_power
¶
Calculate DAC output power metrics.
DACs typically operate with backoff from full scale to maintain linearity and avoid clipping on signal peaks.
| PARAMETER | DESCRIPTION |
|---|---|
enob
|
Effective number of bits
TYPE:
|
full_scale_dbm
|
Full-scale output power in dBm
TYPE:
|
backoff_db
|
Operating backoff from full scale
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
dict[str, float]
|
Dictionary with: - full_scale_dbm: Maximum output power - operating_power_dbm: Power with backoff - snr_db: Signal-to-quantization-noise ratio - sfdr_db: Estimated spurious-free dynamic range - noise_floor_dbm: Quantization noise floor |
Source code in src/phased_array_systems/models/digital/converters.py
Bandwidth¶
Functions for analyzing digital beamformer bandwidth constraints, beam-bandwidth products, and data rates.
beam_bandwidth_product
¶
Calculate total beam-bandwidth product.
The beam-bandwidth product represents the total instantaneous processing bandwidth required for simultaneous beams.
| PARAMETER | DESCRIPTION |
|---|---|
n_beams
|
Number of simultaneous beams
TYPE:
|
bandwidth_per_beam_hz
|
Bandwidth per beam in Hz
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
float
|
Total beam-bandwidth product in Hz |
Source code in src/phased_array_systems/models/digital/bandwidth.py
max_simultaneous_beams
¶
max_simultaneous_beams(processing_bandwidth_hz: float, bandwidth_per_beam_hz: float, overhead_factor: float = 1.1) -> int
Calculate maximum number of simultaneous beams.
Given a fixed processing bandwidth, determine how many beams can be formed simultaneously.
| PARAMETER | DESCRIPTION |
|---|---|
processing_bandwidth_hz
|
Total available processing bandwidth
TYPE:
|
bandwidth_per_beam_hz
|
Required bandwidth per beam
TYPE:
|
overhead_factor
|
Processing overhead (default 10%)
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
int
|
Maximum number of simultaneous beams (integer) |
Source code in src/phased_array_systems/models/digital/bandwidth.py
digital_beamformer_data_rate
¶
digital_beamformer_data_rate(n_elements: int, sample_rate_hz: float, bits_per_sample: int, n_channels: int = 2, overhead_factor: float = 1.25) -> dict[str, float]
Calculate digital beamformer input data rate.
Computes the raw data rate from ADCs into the digital beamformer.
| PARAMETER | DESCRIPTION |
|---|---|
n_elements
|
Number of array elements (each with ADC)
TYPE:
|
sample_rate_hz
|
ADC sample rate in Hz
TYPE:
|
bits_per_sample
|
Bits per sample (typically 12-16)
TYPE:
|
n_channels
|
Number of channels per element (2 for I/Q)
TYPE:
|
overhead_factor
|
Protocol overhead (framing, sync, etc.)
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
dict[str, float]
|
Dictionary with: - raw_rate_bps: Raw data rate in bits/second - raw_rate_gbps: Raw data rate in Gbps - with_overhead_gbps: Rate including overhead - per_element_gbps: Rate per element |
Source code in src/phased_array_systems/models/digital/bandwidth.py
channelizer_output_rate
¶
channelizer_output_rate(input_bandwidth_hz: float, n_channels: int, overlap_factor: float = 1.0, bits_per_output: int = 32) -> dict[str, float]
Calculate polyphase channelizer output data rate.
A channelizer divides a wideband input into narrowband channels. Output rate depends on channel count and overlap.
| PARAMETER | DESCRIPTION |
|---|---|
input_bandwidth_hz
|
Total input bandwidth
TYPE:
|
n_channels
|
Number of output channels
TYPE:
|
overlap_factor
|
Channel overlap (1.0 = no overlap, 2.0 = 50% overlap)
TYPE:
|
bits_per_output
|
Bits per output sample (32 for complex float)
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
dict[str, float]
|
Dictionary with: - channel_bandwidth_hz: Bandwidth per channel - channel_sample_rate_hz: Sample rate per channel - output_rate_gbps: Total output data rate - samples_per_channel_per_sec: Output samples per channel |
Source code in src/phased_array_systems/models/digital/bandwidth.py
processing_margin
¶
processing_margin(available_throughput_gops: float, required_throughput_gops: float) -> dict[str, float]
Calculate processing margin for digital beamformer.
Compares available FPGA/GPU throughput against requirements.
| PARAMETER | DESCRIPTION |
|---|---|
available_throughput_gops
|
Available processing (Giga-ops/sec)
TYPE:
|
required_throughput_gops
|
Required processing (Giga-ops/sec)
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
dict[str, float]
|
Dictionary with: - margin_ratio: Available / Required (>1 is good) - margin_db: Margin in dB - utilization_percent: Percentage of capacity used - headroom_percent: Remaining capacity |
Source code in src/phased_array_systems/models/digital/bandwidth.py
beamformer_operations
¶
beamformer_operations(n_elements: int, n_beams: int, sample_rate_hz: float, fft_size: int = 0) -> dict[str, float]
Estimate digital beamformer computational requirements.
Calculates operations per second for time-domain or frequency-domain beamforming.
| PARAMETER | DESCRIPTION |
|---|---|
n_elements
|
Number of array elements
TYPE:
|
n_beams
|
Number of simultaneous beams
TYPE:
|
sample_rate_hz
|
Sample rate in Hz
TYPE:
|
fft_size
|
FFT size (0 for time-domain beamforming)
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
dict[str, float]
|
Dictionary with: - complex_mults_per_sec: Complex multiplications/sec - complex_adds_per_sec: Complex additions/sec - total_gops: Total Giga-operations/sec - method: 'time_domain' or 'frequency_domain' |
Source code in src/phased_array_systems/models/digital/bandwidth.py
Scheduling¶
Classes and functions for timeline and scheduling in multi-function arrays.
Classes¶
Function
¶
Bases: str, Enum
Array function types for multi-function scheduling.
Dwell
dataclass
¶
Dwell(function: Function, duration_us: float, azimuth_deg: float = 0.0, elevation_deg: float = 0.0, bandwidth_hz: float = 0.0, priority: int = 1, metadata: dict = dict())
A single dwell (beam position) in the timeline.
| ATTRIBUTE | DESCRIPTION |
|---|---|
function |
Type of function being performed
TYPE:
|
duration_us |
Dwell duration in microseconds
TYPE:
|
azimuth_deg |
Beam azimuth angle in degrees
TYPE:
|
elevation_deg |
Beam elevation angle in degrees
TYPE:
|
bandwidth_hz |
Instantaneous bandwidth for this dwell
TYPE:
|
priority |
Scheduling priority (higher = more important)
TYPE:
|
metadata |
Additional function-specific parameters
TYPE:
|
Timeline
dataclass
¶
Timeline(dwells: list[Dwell], frame_time_ms: float, name: str = '')
A complete timeline of dwells over a frame period.
| ATTRIBUTE | DESCRIPTION |
|---|---|
dwells |
List of dwells in chronological order
TYPE:
|
frame_time_ms |
Total frame duration in milliseconds
TYPE:
|
name |
Optional timeline identifier
TYPE:
|
Functions¶
timeline_utilization
¶
timeline_utilization(timeline: Timeline) -> dict[str, float]
Calculate timeline utilization metrics.
Analyzes how efficiently the timeline uses available time and breaks down allocation by function.
| PARAMETER | DESCRIPTION |
|---|---|
timeline
|
Timeline object to analyze
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
dict[str, float]
|
Dictionary with: - total_utilization: Fraction of frame time used (0-1) - idle_time_ms: Unused time in milliseconds - by_function: Dict of function -> time allocation - by_function_percent: Dict of function -> percentage |
Source code in src/phased_array_systems/models/digital/scheduling.py
max_update_rate
¶
max_update_rate(scan_volume_sr: float, beam_solid_angle_sr: float, dwell_time_us: float, overhead_us: float = 10.0) -> dict[str, float]
Calculate maximum volume update rate for search.
Determines how quickly a phased array can search a given volume.
| PARAMETER | DESCRIPTION |
|---|---|
scan_volume_sr
|
Search volume in steradians
TYPE:
|
beam_solid_angle_sr
|
Beam solid angle in steradians (≈ θ_az * θ_el)
TYPE:
|
dwell_time_us
|
Time per beam position in microseconds
TYPE:
|
overhead_us
|
Beam switching overhead in microseconds
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
dict[str, float]
|
Dictionary with: - n_beam_positions: Number of beams to cover volume - frame_time_ms: Time to complete one scan - update_rate_hz: Volume scans per second - scan_time_s: Time for one complete scan |
Source code in src/phased_array_systems/models/digital/scheduling.py
search_timeline
¶
search_timeline(azimuth_range_deg: tuple[float, float], elevation_range_deg: tuple[float, float], azimuth_step_deg: float, elevation_step_deg: float, dwell_time_us: float, function: Function = RADAR_SEARCH) -> Timeline
Generate a raster search timeline.
Creates a timeline of dwells covering a rectangular search volume using a raster scan pattern.
| PARAMETER | DESCRIPTION |
|---|---|
azimuth_range_deg
|
(min, max) azimuth in degrees
TYPE:
|
elevation_range_deg
|
(min, max) elevation in degrees
TYPE:
|
azimuth_step_deg
|
Azimuth step between beams
TYPE:
|
elevation_step_deg
|
Elevation step between beams
TYPE:
|
dwell_time_us
|
Dwell time per position
TYPE:
|
function
|
Function type for dwells
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Timeline
|
Timeline with search dwells |
Source code in src/phased_array_systems/models/digital/scheduling.py
interleaved_timeline
¶
interleaved_timeline(functions: list[dict], frame_time_ms: float) -> Timeline
Generate an interleaved multi-function timeline.
Creates a timeline that allocates time to multiple functions based on specified priorities and time allocations.
| PARAMETER | DESCRIPTION |
|---|---|
functions
|
List of dicts with: - function: Function enum value - time_percent: Percentage of frame time - dwell_time_us: Duration of each dwell - dwells_per_burst: Number of consecutive dwells
TYPE:
|
frame_time_ms
|
Total frame duration
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Timeline
|
Timeline with interleaved function dwells |
Source code in src/phased_array_systems/models/digital/scheduling.py
Usage Examples¶
ADC Performance Analysis¶
from phased_array_systems.models.digital import (
enob_to_snr,
adc_dynamic_range,
sample_rate_for_bandwidth,
)
# 14-bit ADC analysis
enob = 14
snr = enob_to_snr(enob)
print(f"Ideal SNR: {snr:.1f} dB") # 86.0 dB
# Dynamic range with front-end noise
result = adc_dynamic_range(
enob=14,
noise_figure_db=3,
bandwidth_hz=100e6
)
print(f"Dynamic Range: {result['dynamic_range_db']:.1f} dB")
# Sample rate for 100 MHz signal
fs = sample_rate_for_bandwidth(100e6)
print(f"Required Sample Rate: {fs/1e6:.0f} MHz") # 250 MHz
Digital Beamformer Data Rate¶
from phased_array_systems.models.digital import (
digital_beamformer_data_rate,
beam_bandwidth_product,
max_simultaneous_beams,
)
# 256-element array with 1 GSPS ADCs
result = digital_beamformer_data_rate(
n_elements=256,
sample_rate_hz=1e9,
bits_per_sample=14,
)
print(f"Total Data Rate: {result['with_overhead_gbps']:.1f} Gbps")
# How many beams with 10 GHz processing bandwidth?
n_beams = max_simultaneous_beams(
processing_bandwidth_hz=10e9,
bandwidth_per_beam_hz=100e6,
)
print(f"Max Simultaneous Beams: {n_beams}")
Radar Search Timeline¶
from phased_array_systems.models.digital import (
search_timeline,
timeline_utilization,
max_update_rate,
)
# Generate raster search pattern
tl = search_timeline(
azimuth_range_deg=(-60, 60),
elevation_range_deg=(0, 30),
azimuth_step_deg=3.0,
elevation_step_deg=3.0,
dwell_time_us=100,
)
print(f"Search requires {tl.n_dwells} beam positions")
# Analyze utilization
util = timeline_utilization(tl)
print(f"Frame time: {util['frame_time_ms']:.1f} ms")
print(f"Utilization: {util['total_utilization']*100:.1f}%")
Multi-Function Interleaved Timeline¶
from phased_array_systems.models.digital import (
Function,
interleaved_timeline,
timeline_utilization,
)
# Create interleaved search/track timeline
tl = interleaved_timeline(
functions=[
{"function": Function.RADAR_SEARCH, "time_percent": 60,
"dwell_time_us": 100, "priority": 1},
{"function": Function.RADAR_TRACK, "time_percent": 30,
"dwell_time_us": 50, "priority": 2},
{"function": Function.ESM, "time_percent": 10,
"dwell_time_us": 200, "priority": 1},
],
frame_time_ms=100,
)
util = timeline_utilization(tl)
print(f"Search allocation: {util['by_function_percent']['radar_search']:.1f}%")
print(f"Track allocation: {util['by_function_percent']['radar_track']:.1f}%")
Key Equations¶
ENOB-SNR Relationship¶
Quantization Noise Floor¶
Beam-Bandwidth Product¶
Digital Beamformer Data Rate¶
See Also¶
- RF Models - RF cascade analysis
- Radar Models - Radar detection calculations
- Theory: Phased Arrays