3 freq diversion
This commit is contained in:
@ -10,7 +10,12 @@ from rfg_adc_plotter.constants import (
|
||||
FREQ_MIN_GHZ,
|
||||
WF_WIDTH,
|
||||
)
|
||||
from rfg_adc_plotter.processing.fourier import compute_ifft_profile_from_sweep
|
||||
from rfg_adc_plotter.processing.fourier import (
|
||||
build_frequency_axis_hz,
|
||||
compute_ifft_profile_from_sweep,
|
||||
perform_ifft_depth_response,
|
||||
reconstruct_complex_spectrum_from_real_trace,
|
||||
)
|
||||
|
||||
|
||||
class RingBuffer:
|
||||
@ -38,6 +43,17 @@ class RingBuffer:
|
||||
self.y_max_fft: Optional[float] = None
|
||||
# FFT последнего свипа (для отображения без повторного вычисления)
|
||||
self.last_fft_vals: Optional[np.ndarray] = None
|
||||
# FFT-профили по третям входного частотного диапазона (для line-plot).
|
||||
self.last_fft_third_axes_m: tuple[Optional[np.ndarray], Optional[np.ndarray], Optional[np.ndarray]] = (
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
)
|
||||
self.last_fft_third_vals: tuple[Optional[np.ndarray], Optional[np.ndarray], Optional[np.ndarray]] = (
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
)
|
||||
|
||||
@property
|
||||
def is_ready(self) -> bool:
|
||||
@ -64,6 +80,8 @@ class RingBuffer:
|
||||
self.fft_depth_axis_m = None
|
||||
self.fft_bins = 0
|
||||
self.last_fft_vals = None
|
||||
self.last_fft_third_axes_m = (None, None, None)
|
||||
self.last_fft_third_vals = (None, None, None)
|
||||
self.y_min_fft = None
|
||||
self.y_max_fft = None
|
||||
return True
|
||||
@ -94,6 +112,11 @@ class RingBuffer:
|
||||
self._push_fft(s)
|
||||
|
||||
def _push_fft(self, s: np.ndarray):
|
||||
empty_thirds = (
|
||||
np.zeros((0,), dtype=np.float32),
|
||||
np.zeros((0,), dtype=np.float32),
|
||||
np.zeros((0,), dtype=np.float32),
|
||||
)
|
||||
depth_axis_m, fft_row = compute_ifft_profile_from_sweep(
|
||||
s,
|
||||
complex_mode=self.fft_complex_mode,
|
||||
@ -103,6 +126,8 @@ class RingBuffer:
|
||||
|
||||
n = min(int(fft_row.size), int(depth_axis_m.size))
|
||||
if n <= 0:
|
||||
self.last_fft_third_axes_m = empty_thirds
|
||||
self.last_fft_third_vals = empty_thirds
|
||||
return
|
||||
if n != fft_row.size:
|
||||
fft_row = fft_row[:n]
|
||||
@ -144,6 +169,7 @@ class RingBuffer:
|
||||
prev_head = (self.head - 1) % self.ring_fft.shape[0]
|
||||
self.ring_fft[prev_head, :] = fft_row
|
||||
self.last_fft_vals = fft_row
|
||||
self.last_fft_third_axes_m, self.last_fft_third_vals = self._compute_fft_thirds(s)
|
||||
|
||||
fr_min = np.nanmin(fft_row)
|
||||
fr_max = float(np.nanpercentile(fft_row, 90))
|
||||
@ -152,6 +178,65 @@ class RingBuffer:
|
||||
if self.y_max_fft is None or (not np.isnan(fr_max) and fr_max > self.y_max_fft):
|
||||
self.y_max_fft = float(fr_max)
|
||||
|
||||
def _compute_fft_thirds(
|
||||
self, s: np.ndarray
|
||||
) -> tuple[tuple[np.ndarray, np.ndarray, np.ndarray], tuple[np.ndarray, np.ndarray, np.ndarray]]:
|
||||
sweep = np.asarray(s, dtype=np.float64).ravel()
|
||||
total = int(sweep.size)
|
||||
|
||||
def _empty() -> np.ndarray:
|
||||
return np.zeros((0,), dtype=np.float32)
|
||||
|
||||
if total <= 0:
|
||||
return (_empty(), _empty(), _empty()), (_empty(), _empty(), _empty())
|
||||
|
||||
freq_hz = build_frequency_axis_hz(total)
|
||||
edges = np.linspace(0, total, 4, dtype=np.int64)
|
||||
|
||||
axes: list[np.ndarray] = []
|
||||
vals: list[np.ndarray] = []
|
||||
|
||||
for idx in range(3):
|
||||
i0 = int(edges[idx])
|
||||
i1 = int(edges[idx + 1])
|
||||
if i1 - i0 < 2:
|
||||
axes.append(_empty())
|
||||
vals.append(_empty())
|
||||
continue
|
||||
|
||||
seg = sweep[i0:i1]
|
||||
seg_freq = freq_hz[i0:i1]
|
||||
seg_complex = reconstruct_complex_spectrum_from_real_trace(
|
||||
seg,
|
||||
complex_mode=self.fft_complex_mode,
|
||||
)
|
||||
depth_m, seg_fft = perform_ifft_depth_response(seg_complex, seg_freq, axis="abs")
|
||||
|
||||
depth_m = np.asarray(depth_m, dtype=np.float32).ravel()
|
||||
seg_fft = np.asarray(seg_fft, dtype=np.float32).ravel()
|
||||
n = min(int(depth_m.size), int(seg_fft.size))
|
||||
if n <= 0:
|
||||
axes.append(_empty())
|
||||
vals.append(_empty())
|
||||
continue
|
||||
|
||||
depth_m = depth_m[:n]
|
||||
seg_fft = seg_fft[:n]
|
||||
|
||||
n_keep = max(1, (n + 1) // 2)
|
||||
axes.append(depth_m[:n_keep])
|
||||
vals.append(seg_fft[:n_keep])
|
||||
|
||||
return (
|
||||
axes[0],
|
||||
axes[1],
|
||||
axes[2],
|
||||
), (
|
||||
vals[0],
|
||||
vals[1],
|
||||
vals[2],
|
||||
)
|
||||
|
||||
def get_display_ring(self) -> np.ndarray:
|
||||
"""Кольцо в порядке от старого к новому, ось времени по X. Форма: (width, time)."""
|
||||
if self.ring is None:
|
||||
|
||||
Reference in New Issue
Block a user