From e126771248d6a208527b1a64e8ef114357b9f627 Mon Sep 17 00:00:00 2001 From: jan Date: Tue, 30 Dec 2025 02:51:57 -0800 Subject: [PATCH] [ova] more work on bin files --- backwash/ova_bin.py | 75 +++++++++++++++++++-------------------------- 1 file changed, 31 insertions(+), 44 deletions(-) diff --git a/backwash/ova_bin.py b/backwash/ova_bin.py index 0d653bf..c8251a9 100644 --- a/backwash/ova_bin.py +++ b/backwash/ova_bin.py @@ -14,49 +14,42 @@ logger = logging.getLogger(__name__) @dataclass class OVABINData: - te: NDArray[numpy.complex128] # time domain complex amplitude, polarization 1 - tm: NDArray[numpy.complex128] # time domain complex amplitude, polarization 2 - dt_ns: float # delta between time points + jones: NDArray[numpy.complex128] # jones matrix data [2 x 2 x n_pts] # TODO frequency domain or time? + df_GHz: float # delta between frequency points max_freq_GHz: float # sweep's max frequency (shortest wavelength) - ng_setting: float | None # set by user (for info only) meas_date: NDArray[numpy.int16] # 8 items: year month [week?] day hour min sec ms - _wip_metadata: NDArray[numpy.float64] | None # unknown metadata values - @property - def time_ns(self) -> NDArray[numpy.float64]: - """ - Time delay (x-axis) for `te` and `tm` data - """ - tt = numpy.arange(self.te.size, dtype=numpy.float64) * self.dt_ns - return tt + def time_ns(self, size: int) -> NDArray[numpy.float64]: + # To be used with tdr curve generated with e.g. fft(fftshift(data.jones)) + tt_ns = fftshift(fftfreq(size, d=self.df_GHz)) + return tt_ns @property def wl_range_nm(self) -> NDArray[numpy.float64]: freq_range = numpy.asarray([ - self.max_freq_GHz - 1 / (2 * self.dt_ns), + self.max_freq_GHz - self.df_GHz * self.jones.shape[2], self.max_freq_GHz, ]) return C0 / freq_range @property def ctr_freq_GHz(self) -> float: - return self.max_freq_GHz - 1 / (4 * self.dt_ns) + return self.max_freq_GHz - self.df_GHz * self.jones.shape[2] / 2 - def freqs(self, size: int) -> NDArray[numpy.float64]: - # To be used with spectrum generated with e.g. fft(fftshift(data.te)) - frq_GHz = fftshift(fftfreq(size, d=self.dt_ns)) + self.ctr_freq_GHz - return frq_GHz + @property + def freqs(self) -> NDArray[numpy.float64]: + return numpy.arange(self.jones.shape[2], dtype=numpy.float64)[::-1] * self.df_GHz + self.max_freq_GHz - def wls(self, size: int) -> NDArray[numpy.float64]: + @property + def wls(self) -> NDArray[numpy.float64]: # To be used with spectrum generated with e.g. fft(fftshift(data.te)) - return C0 / self.freqs(size) + return C0 / self.freqs def window(self, size: int) -> NDArray[numpy.float64]: - # Approximation of the generalized Hamming window used when freq_windowed==True + # Hann window for use before time domain fft nn = numpy.linspace(0, 1, size) - alpha = 0.572 - scale = 1.5 # likely related to "incoherent power gain compensation" for Hamming window (=1.54) - # 1.50 seems to fit the data better though + alpha = 0.500 + scale = 1 ham = alpha - (1 - alpha) * numpy.cos(2 * numpy.pi * nn) return scale * ham @@ -73,28 +66,22 @@ class OVABINData: logger.warning(f'Unexpected magic bytes: {magic}') metadata = fromfile(dtype=numpy.float64, offset=0x00, count=2) + data_count = fromfile(dtype=numpy.int32, offset=0x18, count=1) meas_date = fromfile(dtype=numpy.int16, offset=0x49, count=8) - wl_range = fromfile(dtype=numpy.int32, offset=0x17, count=1) - data_len = 4 * wl_range - arr = fromfile(dtype=numpy.float64, offset=0x59, count=data_len) + arr = fromfile(dtype=numpy.float64, offset=0x59, count=data_count * 2 * 4) ng = fromfile(dtype=numpy.float32, offset=0x21, count=1) - max_freq_GHz = metadata[0] - #dt_ns = metadata[3] / 2 + max_freq_GHz, df_GHz = metadata - arrs = numpy.split(arr, 4) - te = arrs[0] + 1j * arrs[1] - tm = arrs[2] + 1j * arrs[3] + arrs = numpy.split(arr, 4 * 2) + jones = (arrs[0::2] + 1j * arrs[1::2]).reshape(2, 2, -1) # TODO confirm result = OVABINData( - te = te, - tm = tm, - #dt_ns = dt_ns, + jones = jones, + df_GHz = df_GHz, max_freq_GHz = max_freq_GHz, - ng_setting = ng, meas_date = meas_date, - _wip_metadata = metadata[1:], ) return result @@ -105,17 +92,17 @@ Notes on .bin file format (OVA) 0x00: 9D A8 5A 6B C8 D0 0C 41 13 23 63 4D 22 74 C4 3F |max_freq_GHZ (f64)------ | f64 ??----------------- | - C0/freq = wl_nm 5.848e6 ~> 51.3nm if GHz - could be dt in ps? + C0/freq = wl_nm 0.1597... df_GHz + not sure what changes this, if anything 0x10: 40 53 33 33 4F 56 41 00 00 00 01 00 00 00 00 00 - | S 3 3 | O V A | wl range | - 1 = biggest range (58.97nm), others are exponents of 2 smaller (resolution) - effectively length of each sub-array (x 4 arrays) + | S 3 3 | O V A | ? | data_count |??|f64------ + 0x10000 = biggest range (58.97nm) + this * 8bytes * 2(complex) * 4 (jones matrix) = data length in bytes 0x20: 00 00 80 20 40 01 00 00 00 00 00 00 00 00 00 00 - | ng (f32) |----........| - ??? average count + -DUT length (m)|----........| + average count 0x30: 00 00 00 00 00 00 38 98 40 00 00 00 00 00 00 00 ???????????