NEDAS.utils.optical_flow module

class NEDAS.utils.optical_flow.OpticalFlow(method='DIS', **kwargs)[source]

Bases: object

NEDAS.utils.optical_flow.optical_flow_HS_pyramid(grid, fld1, fld2, nlevel=5, niter_max=100, smoothness_weight=None, alpha_squared=None, local_weight=None, **kwargs)[source]

smoothness_weight is applied to a field ALREADY normalized to [0,1] below (using THIS call’s own xmax-xmin, recomputed fresh every call) – so a fixed smoothness_weight only matches the paper’s raw-field alpha^2 for field ranges close to whatever R was used to derive it (2026-07-08: smoothness_weight=alpha^2/R^2, R~52.7 measured once from a cp2-scale field). That fixed value silently drifts wrong whenever the ACTUAL field range differs (2026-07-09: confirmed at cp10’s longer, more nonlinear cycling period, where larger forecast divergence means R is genuinely larger – the same fixed 0.036 becomes an effectively much stronger alpha^2, over-smoothing and collapsing MSA’s performance below even plain MS). Pass alpha_squared (the paper’s true, field-range-independent physical constant, =100) instead of smoothness_weight to have this function derive the correctly-scaled weight itself from the SAME xmax/xmin it already computes for normalization, self-consistently, every call. smoothness_weight is kept as a direct override for callers that want the old fixed-value behavior (e.g. DIS/Farneback callers never touch this function at all).

local_weight (2026-07-20, s in [0,1)): self-normalizing alternative to alpha_squared/ smoothness_weight, added after both were found to land in wildly different effective regimes across models – alpha_squared=100 (its own field-range-independent physical constant) gave w/mean(data_term) ratios of 1517 (vort2d) vs 5022 (vort3d) at the coarsest pyramid level, because neither parameter accounts for how the actual competing quantity (xdx^2+xdy^2, the local squared gradient, i.e. the data term the smoothness weight w competes against in the solver’s denominator) depends on field roughness/resolution/pyramid level – only on the field’s global value range. local_weight instead computes, AT EACH PYRAMID LEVEL, d_ref = mean(xdx^2+xdy^2) over unmasked pixels at that level, then sets w = d_ref * s/(1-s). Since the solver’s local response scales as d(x,y)/(w+d(x,y)), at a TYPICAL-strength location (d=d_ref) this makes s directly mean “fraction of the typical- strength local response suppressed”: s=0 -> no smoothing (pure local fit, noisy); s=0.5 -> half the typical response passes; s->1 -> full suppression (matches what alpha_squared=100/ smoothness_weight=0.3 both did for vort3d). Stronger-than-typical local features (e.g. a coherent vortex core) still get a proportionally larger fraction through even at high s – naturally adaptive, unlike a single global w. Takes priority over alpha_squared/ smoothness_weight if given.

NEDAS.utils.optical_flow.coarsen_mask(x, lev1, lev2)[source]
NEDAS.utils.optical_flow.coarsen(x, lev1, lev2)[source]
NEDAS.utils.optical_flow.sharpen(x, lev1, lev2)[source]
NEDAS.utils.optical_flow.deriv_y(f)[source]
NEDAS.utils.optical_flow.deriv_x(f)[source]
NEDAS.utils.optical_flow.laplacian(f)[source]
NEDAS.utils.optical_flow.warp(x, u, v)[source]
NEDAS.utils.optical_flow.interp2d(x, io, jo)[source]