When to Enable CV Normalization for Gain-Invariant Processing in ESPectre

Enable CV normalization when CSI amplitudes are not gain-locked—such as when hardware AGC/FFT gain varies between packets—and disable it when the device maintains a fixed gain lock to maximize turbulence sensitivity.

In the ESPectre Wi-Fi sensing framework, CV normalization (coefficient-of-variation) ensures turbulence metrics remain valid when hardware gain fluctuates. Knowing when to enable CV normalization for gain-invariant processing is critical for accurate channel state information (CSI) analysis, as it determines whether the system uses std/mean or raw standard deviation for spatial turbulence calculations. The decision relies on the hardware's ability to lock AGC/FFT gain, with automatic detection implemented in the run_gain_lock routine.

Gain-Lock Detection Logic

The decision to enable CV normalization starts in micro-espectre/src/main.py within the run_gain_lock function. This routine returns needs_cv_normalization=True under three specific conditions: when the platform lacks hardware gain-lock support, when config.GAIN_LOCK_MODE is explicitly "disabled", or when the mode is "auto" and the measured median AGC is lower than config.GAIN_LOCK_MIN_SAFE_AGC (indicating a signal too strong for reliable locking). In all other scenarios—specifically when gain-lock succeeds—the function returns False, signaling that raw standard deviation provides maximum sensitivity.

Propagation to the Detector and Calibrator

Once determined, the boolean flag flows through the system architecture. The detector.set_cv_normalization method in micro-espectre/src/mvs_detector.py receives this value and stores it in self._context.use_cv_normalization. All subsequent turbulence calculations reference this context flag. Similarly, the NBVICalibrator class in micro-espectre/src/nbvi_calibrator.py mirrors this setting to ensure calibration statistics use the identical normalization mode as the detector, maintaining consistency across the processing pipeline.

Turbulence Calculation Implementation

The actual mathematical switch occurs in micro-espectre/src/segmentation.py and micro-espectre/src/utils.py. The SegmentationContext.compute_spatial_turbulence method and the standalone calculate_spatial_turbulence function accept a use_cv_normalization parameter. When this flag is True, the functions return std / mean, which cancels multiplicative gain factors. When False, they return plain std, preserving amplitude sensitivity for gain-locked scenarios. The default value is True, but the detector overwrites this based on the gain-lock outcome.

Practical Code Examples

Forcing CV Normalization Manually

When you know the hardware gain is unlocked, explicitly enable normalization:

from src.mvs_detector import MVSDetector

detector = MVSDetector()

# Force gain-invariant mode when gain is not locked

detector.set_cv_normalization(True)

# Compute turbulence on a CSI packet

turbulence = detector.calculate_spatial_turbulence(csi_packet)
print("CV-normalised turbulence:", turbulence)

Automatic Configuration via Gain-Lock

Let the system decide based on hardware conditions:

from src.main import run_gain_lock, MainLoopState
from src.detectord_interface import DetectorInterface

# Assume wlan is a connected Wi-Fi object with CSI enabled

agc, fft, needs_cv = run_gain_lock(wlan)

# Store flag for the processing loop

state = MainLoopState()
state.needs_cv_normalization = needs_cv

detector = DetectorInterface()
detector.set_cv_normalization(needs_cv)

Querying the Current Mode

Verify the active normalization strategy at runtime:

print("CV normalisation active?", detector.use_cv_normalization)

# Output: True (gain not locked) or False (gain locked)

Summary

  • Enable CV normalization when hardware gain is not locked (varying AGC/FFT) to ensure gain-invariant turbulence metrics via std/mean calculation.
  • Disable CV normalization when gain-lock is active to maximize sensitivity using raw standard deviation.
  • The run_gain_lock function in micro-espectre/src/main.py automates this decision based on hardware capabilities, config.GAIN_LOCK_MODE, and signal strength thresholds.
  • The flag propagates through detector.set_cv_normalization in micro-espectre/src/mvs_detector.py and aligns with NBVICalibrator to maintain consistent processing across the ESPectre pipeline.

Frequently Asked Questions

When should I manually enable CV normalization in ESPectre?

Manually enable CV normalization when working with hardware that does not support automatic gain control (AGC) locking, or when analyzing CSI data where gain values vary between packets. This ensures the turbulence metric remains invariant to multiplicative gain changes by computing the coefficient of variation (std/mean) rather than raw standard deviation.

What happens if I leave CV normalization enabled during gain-lock?

If CV normalization remains enabled while the hardware maintains a fixed gain lock, the system calculates std/mean instead of using raw standard deviation. This reduces sensitivity to small amplitude fluctuations because the division by mean introduces unnecessary normalization when the gain factor is already constant, potentially masking subtle environmental changes in the CSI data.

How does the NBVI calibrator use the CV normalization setting?

The NBVICalibrator class in micro-espectre/src/nbvi_calibrator.py reads the same use_cv_normalization flag set on the detector to ensure calibration statistics are computed with identical normalization. This alignment guarantees that calibration values and real-time turbulence measurements use the same mathematical basis, preventing mismatches between training and inference data.

Where is the turbulence calculation actually performed?

The core turbulence calculation resides in micro-espectre/src/segmentation.py within the SegmentationContext.compute_spatial_turbulence method, with a helper implementation in micro-espectre/src/utils.py called calculate_spatial_turbulence. Both locations check the use_cv_normalization boolean to decide whether to return the coefficient of variation or the raw standard deviation of the CSI amplitudes.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →