This commit is contained in:
awe
2026-04-10 16:20:48 +03:00
parent 9aac162320
commit 934ca33d58
4 changed files with 531 additions and 145 deletions

View File

@ -31,6 +31,9 @@ class RingBuffer:
self.last_freqs: Optional[np.ndarray] = None
self.y_min_fft: Optional[float] = None
self.y_max_fft: Optional[float] = None
self.last_push_valid_points = 0
self.last_push_fft_valid = False
self.last_push_axis_valid = False
@property
def is_ready(self) -> bool:
@ -55,6 +58,38 @@ class RingBuffer:
self.last_freqs = None
self.y_min_fft = None
self.y_max_fft = None
self.last_push_valid_points = 0
self.last_push_fft_valid = False
self.last_push_axis_valid = False
def _promote_fft_cache(self, fft_mag: np.ndarray) -> bool:
fft_mag_arr = np.asarray(fft_mag, dtype=np.float32).reshape(-1)
if fft_mag_arr.size <= 0:
self.last_push_fft_valid = False
return False
fft_db = fft_mag_to_db(fft_mag_arr)
finite_db = fft_db[np.isfinite(fft_db)]
if finite_db.size <= 0:
self.last_push_fft_valid = False
return False
self.last_fft_mag = fft_mag_arr.copy()
self.last_fft_db = fft_db
fr_min = float(np.min(finite_db))
fr_max = float(np.max(finite_db))
self.y_min_fft = fr_min if self.y_min_fft is None else min(self.y_min_fft, fr_min)
self.y_max_fft = fr_max if self.y_max_fft is None else max(self.y_max_fft, fr_max)
self.last_push_fft_valid = True
return True
def _promote_distance_axis(self, axis: np.ndarray) -> bool:
axis_arr = np.asarray(axis, dtype=np.float64).reshape(-1)
if axis_arr.size <= 0 or not np.all(np.isfinite(axis_arr)):
self.last_push_axis_valid = False
return False
self.distance_axis = axis_arr.copy()
self.last_push_axis_valid = True
return True
def ensure_init(self, sweep_width: int) -> bool:
"""Allocate or resize buffers. Returns True when geometry changed."""
@ -107,6 +142,8 @@ class RingBuffer:
self.fft_mode = normalized_mode
self.y_min_fft = None
self.y_max_fft = None
self.last_push_fft_valid = False
self.last_push_axis_valid = False
if self.ring is None or self.ring_fft is None:
return True
@ -131,17 +168,18 @@ class RingBuffer:
self.ring_fft[row_idx, :] = fft_mag
if self.last_freqs is not None:
self.distance_axis = compute_distance_axis(
self.last_freqs,
self.fft_bins,
mode=self.fft_mode,
self._promote_distance_axis(
compute_distance_axis(
self.last_freqs,
self.fft_bins,
mode=self.fft_mode,
)
)
last_idx = (self.head - 1) % self.max_sweeps
if self.ring_fft.shape[0] > 0:
last_fft = self.ring_fft[last_idx]
self.last_fft_mag = np.asarray(last_fft, dtype=np.float32).copy()
self.last_fft_db = fft_mag_to_db(last_fft)
self._promote_fft_cache(last_fft)
finite = self.ring_fft[np.isfinite(self.ring_fft)]
if finite.size > 0:
finite_db = fft_mag_to_db(finite.astype(np.float32, copy=False))
@ -170,6 +208,7 @@ class RingBuffer:
row = np.full((self.width,), np.nan, dtype=np.float32)
take = min(self.width, int(sweep.size))
row[:take] = np.asarray(sweep[:take], dtype=np.float32)
self.last_push_valid_points = int(np.count_nonzero(np.isfinite(row[:take])))
self.ring[self.head, :] = row
self.ring_time[self.head] = time.time()
if freqs is not None:
@ -183,16 +222,8 @@ class RingBuffer:
fft_mag = compute_fft_mag_row(fft_source, freqs, self.fft_bins, mode=self.fft_mode)
self.ring_fft[self.head, :] = fft_mag
self.last_fft_mag = np.asarray(fft_mag, dtype=np.float32).copy()
self.last_fft_db = fft_mag_to_db(fft_mag)
if self.last_fft_db.size > 0:
fr_min = float(np.nanmin(self.last_fft_db))
fr_max = float(np.nanmax(self.last_fft_db))
self.y_min_fft = fr_min if self.y_min_fft is None else min(self.y_min_fft, fr_min)
self.y_max_fft = fr_max if self.y_max_fft is None else max(self.y_max_fft, fr_max)
self.distance_axis = compute_distance_axis(freqs, self.fft_bins, mode=self.fft_mode)
self._promote_fft_cache(fft_mag)
self._promote_distance_axis(compute_distance_axis(freqs, self.fft_bins, mode=self.fft_mode))
self.head = (self.head + 1) % self.max_sweeps
def get_display_raw(self) -> np.ndarray: