Results and paths

The Result, Frame and Paths records returned by Radar's verbs, with every field, the processing shortcuts on Frame, and the ProcessingAxes metadata.

simulate and echo return a Result; stream yields one Result per frame; trace returns Paths. All three are frozen dataclasses that hold data only.

from witwin.radar import Frame, Paths, Result

Result#

What one simulate or echo call produced. You do not construct it yourself.

FieldTypeMeaning
cubetorch.TensorComplex cube [frame, tx, rx, slow, fast]. Carries the autograd graph when grad was set.
times_stuple[float, ...]Frame start times, s.
kindstrWaveform kind: "fmcw", "ofdm" or "pulsed".
axis_namestuple[str, ...]Names of the cube axes, for example ('frame', 'tx', 'rx', 'chirp', 'range_bin').
axesProcessingAxesPhysical axes and conventions of the cube.
phasorstrPhase convention of the cube.
time_dependencestrTime convention, exp(+j·2π·f·t).
reference_frequency_hzfloatCarrier the paths were evaluated at, Hz.
output_domainstr"spectrum" or "beat" for FMCW, "cfr" (channel frequency response) for OFDM, "time" for pulsed.
epochstuple[int, ...]Compile epoch of each frame. A new epoch means the Scene was recompiled.
rediscovery_reasonstuple[str or None, ...]Why the topology was rediscovered at each frame, or None.
compile_countintNumber of Scene compiles in the run.
discovery_countintNumber of path discoveries in the run.
sample_times_stupleObservation times used in each frame.
path_set_completeboolTrue when no path appearance can have been missed.
motion_sampling_exhaustiveboolTrue when no observation was interpolated.
motion_samplingstrThe motion mode that ran, for example "chirp" or "adc". Motion.auto() reports the mode it chose.
adaptive_diagnosticstuple[dict, ...]Per-frame adaptive statistics; empty without Motion.adaptive().
last_snapshotobjectCore snapshot of the last frame.
last_compiled_sceneobjectChannel compiled Scene of the last frame.
last_propagationobjectPropagation legs of the last frame.
last_radar_pathsRadarPathBatchComposed round trips of the last frame's final observation.

last_radar_paths has, among others, path_count, sensor_pair_count, total_delay_s (round-trip delay per row, s) and complex_transfer_ref (transfer coefficient per row at the carrier). The last_* fields alias that frame's device tensors, so holding a Result holds that memory.

An adaptive diagnostics dictionary has the keys evaluations, topology_refinements, accepted_intervals, max_tested_phase_error_rad, max_tested_relative_amplitude_error, max_interval_s, exhaustive, topology_proved_complete, interpolation_nodes, observation_count and synthesis_batches.

Result.frame_count#

int, the number of frames in cube.

Result.frame#

Result.frame(index=0) -> Frame

One frame with the metadata processing needs. A view: the cube is indexed, not copied.

indexintdefault 0

Frame index within this result.

Returns Frame.

Result.frame_synthesis#

Result.frame_synthesis(frame_index=0) -> SynthesisResult

One frame's cube and its conventions as a SynthesisResult, without running synthesis again. See Synthesis.

Frame#

One frame of a Result. Its methods call witwin.radar.processing with the frame's own cube and axes, so a cube cannot be paired with the wrong array.

FieldTypeMeaning
cubetorch.TensorComplex [tx, rx, slow, fast].
axesProcessingAxesPhysical axes of this frame.
time_sfloatFrame start time, s.
indexintIndex within the Result. 0 for every frame from stream.
synthesisSynthesisResultThe frame's synthesis record.

Frame.processing_cube#

Frame.processing_cube() -> ProcessingCube

The cube and its axes as the typed record every processing function takes.

Frame.range_profile#

Frame.range_profile(*, window=None, remove_dc=False) -> RangeProfile

Range profile of every TX-RX pair and slow-time sample.

windowstr | Nonedefault None

Fast-time window: "rectangular", "hann", "hamming" or "blackman". None is rectangular. An FMCW "spectrum" cube is already range-transformed and refuses a window; use Fmcw(output="beat") to taper.

remove_dcbooldefault False

Subtract the fast-time mean before the transform.

Frame.range_doppler#

Frame.range_doppler(*, window='hann', range_window=None, remove_dc=False) -> RangeDopplerMap

Range-Doppler map, [tx, rx, doppler, range], with a positive Doppler bin for a closing target.

windowstr | Nonedefault 'hann'

Slow-time window.

range_windowstr | Nonedefault None

Fast-time window, passed to the range stage.

remove_dcbooldefault False

Subtract the fast-time mean before the range transform.

Frame.array#

Frame.array() -> ArrayGeometry

The virtual-array geometry the frame's axes describe. See Angle estimation.

Frame.points#

Frame.points(*, pfa=0.0001, guard_cells=(2, 4), training_cells=(4, 8), route='phase_comparison',
             fft_size=64, max_points=None, window='hann') -> PointCloud

Range-Doppler map, coherent sum over sensor pairs, CA-CFAR and a point cloud, in one call.

pfafloatdefault 0.0001

Design false-alarm probability of the CA-CFAR threshold.

guard_cellstuple[int, int]default (2, 4)

Guard cells on each side, (doppler, range).

training_cellstuple[int, int]default (4, 8)

Training cells on each side beyond the guard cells, (doppler, range).

routestrdefault 'phase_comparison'

Angle estimator: "phase_comparison" or "fft2".

fft_sizeintdefault 64

Angle FFT size.

max_pointsint | Nonedefault None

Keep only the strongest cells. None keeps every detection.

windowstr | Nonedefault 'hann'

Slow-time window of the range-Doppler stage.

Returns PointCloud. See Detection.

frame = result.frame(0)
rd = frame.range_doppler()
cloud = frame.points(max_points=64)
print(frame.axes.range_bin_m, len(cloud))

ProcessingAxes#

The physical axes and conventions of a cube, in witwin.radar.processing. Frame.axes and Result.axes hold one. Every processing stage reads its axes from here.

FieldMeaning
waveform, output_domainWaveform kind and output domain.
fast_time_name, slow_time_nameAxis names, for example "range_bin" and "chirp".
slow_time_period_sSlow-time sample period, s. For TDM-MIMO FMCW, the slot period chirp_period · num_tx.
range_bin_count, doppler_bin_countAxis lengths.
range_bin_m, range_origin_mRange bin size and first bin, m.
max_unambiguous_range_mRange at which the axis wraps, m.
velocity_bin_mps, max_unambiguous_speed_mpsVelocity bin size and aliasing bound, m/s.
wavelength_m, reference_frequency_hzCarrier wavelength, m, and frequency, Hz.
phasor, doppler_signPhase convention and the sign used to make closing velocity positive.
num_tx, num_rx, element_spacing_mArray size and grid spacing, m.
tx_loc_half_wavelength, rx_loc_half_wavelengthElement offsets in half wavelengths.
range_m[R] float64 range axis, m.
velocity_mps[D] float64 velocity axis, m/s, closing positive.
range_oversampleRange oversampling factor.

axes.units returns a dictionary from each scalar name to its SI unit, and axes.sensor_pair_count is num_tx · num_rx.

Paths#

The round trips one trace call composed, before any waveform or receiver stage. Pass it to Radar.echo.

Field or propertyMeaning
kindHow often the world was sampled: "static", "chirp", "adc" or "adaptive".
carrier, waveformCarrier and waveform the schedule was built from.
times, sample_timesFrame times and observation times, s.
los, reflections, grad, motionThe trace request.
epochs, rediscovery_reasons, compile_count, discovery_countAs on Result.
path_set_complete, motion_sampling_exhaustive, adaptive_diagnosticsAs on Result.
last_snapshot, last_compiled_scene, last_propagation, last_radar_pathsAs on Result.
frame_countFrames covered.
observation_countObservation instants evaluated, summed over frames. For adaptive traces, the schedule size, not the probe count.
row_countComposed rows kept, summed over every observation.

Paths.frame#

Paths.frame(index) -> Paths

One frame's rows as a Paths of its own, which can be echoed.

Paths.rows#

Paths.rows(frame=0, observation=-1) -> RadarPathBatch

One observation's composed rows. An adaptive frame keeps only its closing observation; asking for another raises.

paths = radar.trace(scene, targets, times=(0.0, 0.05), reflections=1)
rows = paths.rows(frame=0)
print(rows.path_count, rows.total_delay_s[:4], rows.complex_transfer_ref[:4])
single = radar.echo(paths.frame(1))