torchbp.ops.ffbp module

torchbp.ops.ffbp.backprojection_polar_2d_tx_power_ffbp(wa, g, g_extent, grid, r_res, pos, att, stages, divisions=2, normalization=None, azimuth_resolution=True, downsample_r=4.0, downsample_theta=4.0, min_nsweeps=64, min_nr=32, min_ntheta=32, margin=4, altitude=0.0, beam_theta_samples=32.0, dem=None)[source]

Fast factorized version of backprojection_polar_2d_tx_power().

Splits the track recursively into subapertures like ffbp(), computes coarse per-subaperture accumulator maps and merges them pairwise with bilinear interpolation. Unlike the coherent FFBP the accumulated fields are smooth and phase-free, so the subaperture maps can be sampled much more coarsely than the output grid (downsample_r, downsample_theta) and the azimuth resolution moments merge exactly (Chan’s parallel variance formula).

Each subaperture gets its own grid extents computed from the output grid geometry as seen from the subaperture center, intersected with the azimuth range visible through the antenna pattern. Subapertures on a long or curved track that see the scene at a different angle than the output grid theta range are handled correctly, and subapertures that cannot see the output grid at all are skipped.

Implements the same moment-based azimuth resolution model as the direct function. Output matches the direct function up to interpolation errors, except near illumination edges where pixels with very few contributing pulses can differ. With altitude > 0 the region just outside the nadir shadow zone is also approximate because the slant range to ground range mapping is singular at the shadow boundary and the interpolated fields vary too fast there.

Parameters:
  • wa (Tensor) – Weighting coefficient for amplitude of each pulse, shape: [nsweeps].

  • g (Tensor) – Square-root of two-way antenna gain in spherical coordinates, shape: [elevation, azimuth]. (0, 0) angle is at the beam center.

  • g_extent (list) – Antenna pattern extent: [g_el0, g_az0, g_el1, g_az1] in radians.

  • grid (PolarGrid or dict) –

    Polar grid definition. Can be:

    • PolarGrid object: PolarGrid(r_range=(50, 100), theta_range=(-1, 1), nr=200, ntheta=400)

    • dict: {"r": (r0, r1), "theta": (theta0, theta1), "nr": nr, "ntheta": ntheta}

    where theta represents sin of angle (-1, 1 for 180 degree view).

  • r_res (float) – Range bin resolution. Unused, kept for signature parity with backprojection_polar_2d_tx_power().

  • pos (Tensor) – Position of the platform at each data point. Shape should be [nsweeps, 3].

  • att (Tensor) – Euler angles of the radar antenna at each data point. Shape should be [nsweeps, 3]. [Roll, pitch, yaw]. Pitch rotates the antenna pattern about its boresight (the along-track attitude angle for a side-looking antenna).

  • stages (int) – Number of recursions.

  • divisions (int) – Number of subaperture divisions per stage. Default is 2.

  • normalization (str or None) –

    Valid choices are:

    ”sigma” to divide each value by sin of incidence angle. “gamma” to divide each value by of tan of incidence angle. “beta” or None for no incidence angle normalization. “point” to normalize to constant reflectivity (no ground patch).

  • azimuth_resolution (bool) – If True (default), also normalize for the varying azimuth resolution. See backprojection_polar_2d_tx_power().

  • downsample_r (float) – Subaperture map range step relative to the output grid range step. The accumulated fields are smooth, so values well above 1 are usually fine. Default is 4.

  • downsample_theta (float) – Subaperture map azimuth step relative to the output grid theta step. The subaperture maps are sampled uniformly in azimuth angle psi = asin(theta), so relative to the output theta grid the maps get denser towards |theta| = 1 where the sin mapping compresses the antenna pattern features. Default is 4.

  • min_nsweeps (int) – Do not recurse into subapertures with fewer pulses than this.

  • min_nr (int) – Minimum number of range points in a subaperture map. Avoids large interpolation errors near edges of very small maps.

  • min_ntheta (int) – Minimum number of theta points in a subaperture map.

  • margin (int) – Extra margin in subaperture map cells around the computed extents.

  • altitude (float) – If greater than zero, use slant plane grid semantics identical to backprojection_polar_2d_tx_power_slant() with this reference altitude. Default 0 uses ground plane grid.

  • beam_theta_samples (float) – Minimum number of subaperture map azimuth samples across the half amplitude azimuth beamwidth of the antenna pattern. The interpolation error scales as the squared ratio of the azimuth step to the azimuth beamwidth, so a beam that is thin compared to the output grid theta step needs subaperture maps finer than downsample_theta implies. The azimuth step is the smaller of downsample_theta times the output grid theta step and the beamwidth divided by this value. A quarter of the same sample density is applied to the range step relative to the elevation beamwidth, which matters only when the near edge of the grid approaches nadir.

  • dem (Tensor or None) – Digital elevation model heights on the output polar grid, same convention as backprojection_polar_2d_tx_power() (shape [dem_nr, dem_ntheta] covering the grid extent, resolution can be lower). Resampled onto each subaperture node grid; the phase-free accumulator merges need no DEM. Not supported with altitude > 0. With normalization="gamma" the illumination goes to zero where the terrain approaches grazing local incidence; inside those near-null bands the interpolated maps are approximate like the illumination edges.

Returns:

tx_power – Pseudo-polar format image of square root of power returned from each pixel assuming constant reflectivity, shape [nr, ntheta].

Return type:

Tensor

torchbp.ops.ffbp.compute_subaperture_illumination(pos, att, g, g_extent, grid, decimation=1, dem=None)[source]

Compute illumination weight maps (sum of gains and sum of squared gains) for a subaperture.

This computes both W1 (sum of gains) and W2 (sum of squared gains) for each pixel, which are used to correctly weight subaperture contributions during FFBP merge.

Needed for antenna pattern weighted FFBP.

Parameters:
  • pos (Tensor) – Platform positions for the subaperture. Shape: [nsweeps, 3].

  • att (Tensor) – Antenna pointing for each sweep. Shape: [nsweeps, 3] with [roll, pitch, yaw].

  • g (Tensor) – Antenna gain pattern. Shape: [g_nel, g_naz].

  • g_extent (list) – Pattern extent: [g_el0, g_az0, g_el1, g_az1] in radians.

  • grid (PolarGrid or dict) – Polar grid for output weight map.

  • decimation (int) – Decimation factor for output (1 = full resolution, 4 = 1/16 size).

  • dem (Tensor or None) – Digital elevation model sampled on the output polar grid extent, shape [dem_nr, dem_ntheta]; may be coarser than the grid. The elevation look angle then references the pixel at the DEM height, matching backprojection_polar_2d with the same dem.

Returns:

(w1_map, w2_map) where: - w1_map: Sum of gains. Shape: [nr // decimation, ntheta // decimation]. - w2_map: Sum of squared gains. Shape: [nr // decimation, ntheta // decimation].

Return type:

tuple[Tensor, Tensor]

torchbp.ops.ffbp.ffbp(data, grid, fc, r_res, pos, stages, divisions=2, d0=0.0, interp_method=('knab', 6, 1.5), data_interp_method='linear', oversample_r=1.4, oversample_theta=1.4, grid_oversample=1, dealias=False, data_fmod=0, alias_fmod=None, use_poly=True, att=None, g=None, g_extent=None, weight_map_downsample=1, weight_eps=None, afbp_nsub=1, guard_max_ratio=0.125, dem=None, antenna_leaf_gain='pulse')[source]

Fast factorized backprojection.

Parameters:
  • data (Tensor or LazyData) – Range compressed input data. Shape should be [nsweeps, samples]. A torchbp.data.LazyData source is sliced lazily down the recursion tree and materialized one leaf subaperture at a time, so data much larger than memory can be processed; peak data residency is one leaf’s pulses. No gradient flows to the data through a lazy source.

  • grid (PolarGrid or dict) –

    Polar grid definition. Can be:

    • PolarGrid object (recommended): PolarGrid(r_range=(50, 100), theta_range=(-1, 1), nr=200, ntheta=400)

    • dict (legacy): {"r": (r0, r1), "theta": (theta0, theta1), "nr": nr, "ntheta": ntheta}

    where theta represents sin of angle (-1, 1 for 180 degree view).

  • fc (float) – RF center frequency in Hz.

  • r_res (float) – Range bin resolution in data (meters). For FMCW radar: c/(2*bw*oversample), where c is speed of light, bw is sweep bandwidth, and oversample is FFT oversampling factor.

  • pos (Tensor) – Position of the platform at each data point. Shape should be [nsweeps, 3]. Batched input is not supported. The output grid is referenced to the coordinate frame origin like backprojection_polar_2d(): a nonzero mean of the positions is honored, not re-centered away (internal subaperture frames are centered, but the final merge lands back on the input frame).

  • stages (int) – Number of recursions. This is an upper bound: the recursion also stops early where a further split would make the subaperture grids guard band dominated (guard above ~1/3 of the subaperture image, reached when the subaperture core drops below ~8 * (order/2 + 2) theta bins), where deeper splitting costs more in guard columns than it saves in backprojection. Large values are therefore safe.

  • divisions (int) –

    Number of subapertures divisions per stage. Default is 2.

    Subaperture grids at every level include an automatically sized theta guard band so that the merge interpolation has full window support at the scene theta edges. The guard band can extend past |theta| = 1 (e.g. with a full 180 degree scene), where the backprojection and merge kernels evaluate the smooth continuation of the azimuth signal past the fold, so edge accuracy does not depend on the subaperture size.

  • d0 (float) – Zero range correction.

  • interp_method (tuple) – Interpolation method of the polar-image merges: (“knab”, order, oversample) where order is the number of samples used and oversample is the oversampling factor of the internal polar grids (oversample_r/oversample_theta).

  • data_interp_method (str or tuple) – Range interpolation method of the range-compressed data in the base level backprojections, see backprojection_polar_2d(). Its oversample is the range FFT oversampling of the data, which is unrelated to the grid oversampling of interp_method. The base level is where range interpolation error enters the merge tree, so a short (“knab”, order, oversample) kernel here removes the range aliasing of insufficiently smooth data at a small cost relative to the merges. Default is “linear” (the previous behavior).

  • oversample_r (float) – Internally oversample range by this amount to avoid aliasing.

  • oversample_theta (float) – Internally oversample theta by this amount to avoid aliasing.

  • grid_oversample (float) – Oversample ratio of the output grid. Used only for calculating the alias_fmod when alias_fmod is None. 1 for critically sampled grid, 2 for twice oversampled grid, etc.

  • dealias (bool) – If True removes the range spectrum aliasing. Equivalent to applying torchbp.util.bp_polar_range_dealias on the SAR image. Default is False.

  • data_fmod (float) – Range modulation frequency applied to input data.

  • alias_fmod (float or None) –

    Range modulation frequency applied to SAR image. If None, the alias frequency is calculated automatically assuming that the image spectrum is at positive frequencies. grid_oversample should be given when automatic calculation is used.

    Note that when dealias is True and the alias_fmod is calculated automatically, the output will not have alias_fmod modulation and alias_fmod is used only internally to decrease interpolation errors.

  • use_poly (bool) – Use polynomial approximation for interpolation.

  • att (Tensor or None) – Antenna pointing for each sweep. Shape: [nsweeps, 3] with [roll, pitch, yaw]. Required when g is provided for antenna pattern weighting.

  • g (Tensor or None) – Antenna gain pattern. Shape: [g_nel, g_naz]. When provided, applies SNR-optimal weighted combination of subapertures.

  • g_extent (list or None) – Antenna pattern extent: [g_el0, g_az0, g_el1, g_az1] in radians. Required when g is provided.

  • weight_map_downsample (int) – Downsample factor for weight maps relative to image grid. Default 1. Lower values give more accurate weights but use more memory. Higher values reduce memory use and is faster to calculate, but increases error especially if the antenna pattern is not wide.

  • weight_eps (float or None) – Regularization for the antenna-pattern (Wiener) normalization img = A*W1/(W2 + weight_eps**2), in units of square-root illumination power. See _weighted_normalize(). If None (default) a small fixed fraction of the peak illumination power is used, which keeps illuminated pixels at the matched-filter value and only suppresses weakly illuminated ones. Exact value should not be critical. Ignored when no antenna pattern is given.

  • afbp_nsub (int) – If greater than 1, compute the base level subaperture images with afbp() using this many sub-subapertures instead of direct backprojection, which reduces the base level cost roughly afbp_nsub times. This does not change the image accuracy, which stays dominated by the merge interpolation error; the gain is that stages can be reduced by about log2(afbp_nsub) merge levels at constant total cost, which does reduce the error. With an antenna pattern the base illumination maps are computed from a 1/afbp_nsub subset of the pulses (see _illumination_pulse_decimated()), so their cost also drops afbp_nsub times instead of dominating the base level, at full map resolution. With a DEM the afbp fusion adds a small localized amplitude error at bright targets on strong theta terrain slopes (see the dem note of afbp()); use direct backprojection base level when peak amplitude accuracy on steep terrain matters. Default is 1 (direct backprojection).

  • guard_max_ratio (float) – Cap of the automatic theta guard band width, per side, as a fraction of the subaperture grid core theta bins (a minimum of a few interpolation windows is always kept). The guard band adds this fraction to every image in the merge tree, so it bounds the memory overhead to 1 + 2 * guard_max_ratio. When the subaperture origin offsets are comparable to the near range, full interpolation support at the scene theta edges can require a guard wider than the cap; a warning is emitted and edge accuracy at near range degrades gracefully instead of exhausting memory. Increase for full edge accuracy at more memory, decrease (0 gives the minimum window support) for less memory. Default is 0.125.

  • dem (Tensor or None) – Digital elevation model sampled on the scene polar grid. Shape [dem_nr, dem_ntheta], covering the same r and theta extent as grid; may be coarser than the image grid. Values are pixel z coordinates in the same frame as pos. Resampled internally onto every subaperture and merge grid; base images use the DEM-referenced dealias carrier so the merge interpolation sees a terrain-free residual. The output matches backprojection_polar_2d(..., dem=dem) with the same dealias (with a DEM the dealias carrier is always DEM-referenced). With an antenna pattern both the per-pulse gain weighting and the W1/W2 illumination normalization maps reference the DEM look angles.

  • antenna_leaf_gain (str) –

    Granularity of the antenna gain weighting at the base level subaperture backprojections (ignored without an antenna pattern):

    • ”pulse” (default): exact per-pulse gain toward each pixel inside the backprojection kernel.

    • ”subaperture”: approximate the gain as constant over each base subaperture: the leaves run the plain (unweighted) backprojection and are multiplied by a per-pixel mean gain map computed from a few sampled pulses, with the W1/W2 moments taken consistently as n*w and n*w**2. The merges still weight the subapertures against each other exactly, so this only freezes the gain variation within one leaf: the approximation error scales with how much the antenna footprint moves (platform motion, yaw oscillation) over one leaf subaperture, so it is accurate for short leaves (enough stages) and fast agile-beam data should keep “pulse” — except with an afbp base level (afbp_nsub > 1) on a scene that reaches the beam edges, where “pulse” has two failure modes. A gain table that ends inside the scene theta extent (e.g. full |theta| <= 1 grids) puts a hard cutoff step into the subaperture images, which the afbp wavenumber fusion cannot represent — the accumulation dims and smears around the cutoff while the illumination maps stay exact, so the Wiener normalization cannot recover it (afbp warns). And more generally per-pulse gain bakes the gain envelope into the fused signal, so the fusion’s spectral leakage lands at full amplitude in weakly illuminated theta zones, where the Wiener normalization then amplifies it. “subaperture” avoids both: the plain fused image is multiplied by the gain map afterwards, which attenuates any fusion leakage by exactly the factor the normalization later divides by. Its own error is the frozen gain over one leaf — with platform yaw and the long leaves of a shallow afbp configuration it concentrates at the beam edges: keep enough stages for the yaw rate and roll a hard pattern table edge off smoothly (torchbp.util.taper_antenna_pattern()) — the sweep of a hard edge across the beam-edge pixels is not representable by any frozen gain.

Returns:

img – SAR image.

Return type:

Tensor