new adc
This commit is contained in:
@ -65,14 +65,23 @@ def set_calibration_base_value(index: int, value: float) -> np.ndarray:
|
||||
def calibrate_freqs(sweep: Mapping[str, Any]) -> SweepData:
|
||||
"""Return a sweep copy with calibrated and resampled frequency axis."""
|
||||
freqs = np.asarray(sweep["F"], dtype=np.float64).copy()
|
||||
values = np.asarray(sweep["I"], dtype=np.float64).copy()
|
||||
values_in = np.asarray(sweep["I"]).reshape(-1)
|
||||
values = np.asarray(
|
||||
values_in,
|
||||
dtype=np.complex128 if np.iscomplexobj(values_in) else np.float64,
|
||||
).copy()
|
||||
coeffs = np.asarray(CALIBRATION_C, dtype=np.float64)
|
||||
if freqs.size > 0:
|
||||
freqs = coeffs[0] + coeffs[1] * freqs + coeffs[2] * (freqs * freqs)
|
||||
|
||||
if freqs.size >= 2:
|
||||
freqs_cal = np.linspace(float(freqs[0]), float(freqs[-1]), freqs.size, dtype=np.float64)
|
||||
values_cal = np.interp(freqs_cal, freqs, values).astype(np.float64)
|
||||
if np.iscomplexobj(values):
|
||||
values_real = np.interp(freqs_cal, freqs, values.real.astype(np.float64, copy=False))
|
||||
values_imag = np.interp(freqs_cal, freqs, values.imag.astype(np.float64, copy=False))
|
||||
values_cal = (values_real + (1j * values_imag)).astype(np.complex64)
|
||||
else:
|
||||
values_cal = np.interp(freqs_cal, freqs, values).astype(np.float64)
|
||||
else:
|
||||
freqs_cal = freqs.copy()
|
||||
values_cal = values.copy()
|
||||
|
||||
@ -24,6 +24,21 @@ def _finite_freq_bounds(freqs: Optional[np.ndarray]) -> Optional[Tuple[float, fl
|
||||
return f_min, f_max
|
||||
|
||||
|
||||
def _coerce_sweep_array(sweep: np.ndarray) -> np.ndarray:
|
||||
values = np.asarray(sweep).reshape(-1)
|
||||
if np.iscomplexobj(values):
|
||||
return np.asarray(values, dtype=np.complex64)
|
||||
return np.asarray(values, dtype=np.float32)
|
||||
|
||||
|
||||
def _interp_signal(x_uniform: np.ndarray, x_known: np.ndarray, y_known: np.ndarray) -> np.ndarray:
|
||||
if np.iscomplexobj(y_known):
|
||||
real = np.interp(x_uniform, x_known, np.asarray(y_known.real, dtype=np.float64))
|
||||
imag = np.interp(x_uniform, x_known, np.asarray(y_known.imag, dtype=np.float64))
|
||||
return (real + (1j * imag)).astype(np.complex64)
|
||||
return np.interp(x_uniform, x_known, np.asarray(y_known, dtype=np.float64)).astype(np.float32)
|
||||
|
||||
|
||||
def prepare_fft_segment(
|
||||
sweep: np.ndarray,
|
||||
freqs: Optional[np.ndarray],
|
||||
@ -34,8 +49,10 @@ def prepare_fft_segment(
|
||||
if take_fft <= 0:
|
||||
return None
|
||||
|
||||
sweep_seg = np.asarray(sweep[:take_fft], dtype=np.float32)
|
||||
fallback = np.nan_to_num(sweep_seg, nan=0.0).astype(np.float32, copy=False)
|
||||
sweep_arr = _coerce_sweep_array(sweep)
|
||||
sweep_seg = sweep_arr[:take_fft]
|
||||
fallback_dtype = np.complex64 if np.iscomplexobj(sweep_seg) else np.float32
|
||||
fallback = np.nan_to_num(sweep_seg, nan=0.0).astype(fallback_dtype, copy=False)
|
||||
if freqs is None:
|
||||
return fallback, take_fft
|
||||
|
||||
@ -59,7 +76,7 @@ def prepare_fft_segment(
|
||||
return fallback, take_fft
|
||||
|
||||
x_uniform = np.linspace(float(x_unique[0]), float(x_unique[-1]), take_fft, dtype=np.float64)
|
||||
resampled = np.interp(x_uniform, x_unique, y_unique).astype(np.float32)
|
||||
resampled = _interp_signal(x_uniform, x_unique, y_unique)
|
||||
return resampled, take_fft
|
||||
|
||||
|
||||
@ -94,18 +111,20 @@ def build_symmetric_ifft_spectrum(
|
||||
|
||||
fft_seg, take_fft = prepared
|
||||
if take_fft != band_len:
|
||||
fft_seg = np.asarray(fft_seg[:band_len], dtype=np.float32)
|
||||
fft_dtype = np.complex64 if np.iscomplexobj(fft_seg) else np.float32
|
||||
fft_seg = np.asarray(fft_seg[:band_len], dtype=fft_dtype)
|
||||
if fft_seg.size < band_len:
|
||||
padded = np.zeros((band_len,), dtype=np.float32)
|
||||
padded = np.zeros((band_len,), dtype=fft_dtype)
|
||||
padded[: fft_seg.size] = fft_seg
|
||||
fft_seg = padded
|
||||
|
||||
window = np.hanning(band_len).astype(np.float32)
|
||||
band = np.nan_to_num(fft_seg, nan=0.0).astype(np.float32, copy=False) * window
|
||||
band_dtype = np.complex64 if np.iscomplexobj(fft_seg) else np.float32
|
||||
band = np.nan_to_num(fft_seg, nan=0.0).astype(band_dtype, copy=False) * window
|
||||
|
||||
spectrum = np.zeros((int(fft_len),), dtype=np.float32)
|
||||
spectrum = np.zeros((int(fft_len),), dtype=band_dtype)
|
||||
spectrum[pos_idx] = band
|
||||
spectrum[neg_idx] = band[::-1]
|
||||
spectrum[neg_idx] = np.conj(band[::-1]) if np.iscomplexobj(band) else band[::-1]
|
||||
return spectrum
|
||||
|
||||
|
||||
@ -137,16 +156,18 @@ def build_positive_only_centered_ifft_spectrum(
|
||||
|
||||
fft_seg, take_fft = prepared
|
||||
if take_fft != band_len:
|
||||
fft_seg = np.asarray(fft_seg[:band_len], dtype=np.float32)
|
||||
fft_dtype = np.complex64 if np.iscomplexobj(fft_seg) else np.float32
|
||||
fft_seg = np.asarray(fft_seg[:band_len], dtype=fft_dtype)
|
||||
if fft_seg.size < band_len:
|
||||
padded = np.zeros((band_len,), dtype=np.float32)
|
||||
padded = np.zeros((band_len,), dtype=fft_dtype)
|
||||
padded[: fft_seg.size] = fft_seg
|
||||
fft_seg = padded
|
||||
|
||||
window = np.hanning(band_len).astype(np.float32)
|
||||
band = np.nan_to_num(fft_seg, nan=0.0).astype(np.float32, copy=False) * window
|
||||
band_dtype = np.complex64 if np.iscomplexobj(fft_seg) else np.float32
|
||||
band = np.nan_to_num(fft_seg, nan=0.0).astype(band_dtype, copy=False) * window
|
||||
|
||||
spectrum = np.zeros((int(fft_len),), dtype=np.float32)
|
||||
spectrum = np.zeros((int(fft_len),), dtype=band_dtype)
|
||||
spectrum[pos_idx] = band
|
||||
return spectrum
|
||||
|
||||
@ -168,7 +189,8 @@ def _compute_fft_mag_row_direct(
|
||||
return np.full((bins,), np.nan, dtype=np.float32)
|
||||
|
||||
fft_seg, take_fft = prepared
|
||||
fft_in = np.zeros((FFT_LEN,), dtype=np.float32)
|
||||
fft_dtype = np.complex64 if np.iscomplexobj(fft_seg) else np.float32
|
||||
fft_in = np.zeros((FFT_LEN,), dtype=fft_dtype)
|
||||
window = np.hanning(take_fft).astype(np.float32)
|
||||
fft_in[:take_fft] = fft_seg * window
|
||||
spec = np.fft.ifft(fft_in)
|
||||
|
||||
@ -150,18 +150,24 @@ def resample_envelope(envelope: np.ndarray, width: int) -> np.ndarray:
|
||||
|
||||
def normalize_by_envelope(raw: np.ndarray, envelope: np.ndarray) -> np.ndarray:
|
||||
"""Normalize a sweep by an envelope with safe resampling and zero protection."""
|
||||
raw_arr = np.asarray(raw, dtype=np.float32).reshape(-1)
|
||||
raw_in = np.asarray(raw).reshape(-1)
|
||||
raw_dtype = np.complex64 if np.iscomplexobj(raw_in) else np.float32
|
||||
raw_arr = np.asarray(raw_in, dtype=raw_dtype).reshape(-1)
|
||||
if raw_arr.size == 0:
|
||||
return raw_arr.copy()
|
||||
|
||||
env = resample_envelope(envelope, raw_arr.size)
|
||||
out = np.full_like(raw_arr, np.nan, dtype=np.float32)
|
||||
out = np.full(raw_arr.shape, np.nan + 0j if np.iscomplexobj(raw_arr) else np.nan, dtype=raw_dtype)
|
||||
den_eps = np.float32(1e-9)
|
||||
valid = np.isfinite(raw_arr) & np.isfinite(env)
|
||||
if np.any(valid):
|
||||
with np.errstate(divide="ignore", invalid="ignore"):
|
||||
denom = env[valid] + np.where(env[valid] >= 0.0, den_eps, -den_eps)
|
||||
out[valid] = raw_arr[valid] / denom
|
||||
if np.iscomplexobj(out):
|
||||
out_real = np.nan_to_num(out.real, nan=np.nan, posinf=np.nan, neginf=np.nan)
|
||||
out_imag = np.nan_to_num(out.imag, nan=np.nan, posinf=np.nan, neginf=np.nan)
|
||||
return (out_real + (1j * out_imag)).astype(np.complex64, copy=False)
|
||||
return np.nan_to_num(out, nan=np.nan, posinf=np.nan, neginf=np.nan)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user