add some .bin work, change name

This commit is contained in:
jan 2025-12-30 00:15:31 -08:00
parent 333c475e0d
commit 1b2e2070f9
9 changed files with 139 additions and 5 deletions

View File

@ -79,7 +79,7 @@ class OBRData:
metadata = fromfile(dtype=numpy.float64, offset=0x0c, count=4)
ng = fromfile(dtype=numpy.float64, offset=0x2e, count=1)
gain_dB = fromfile(dtype=numpy.int16, offset=0x36, count=1)
dates = fromfile(dtype=numpy.int16, offset=0x46, count=2)
dates = fromfile(dtype=numpy.int16, offset=0x46, count=2 * 8)
t0half = fromfile(dtype=numpy.float64, offset=0x96, count=1)
freq_windowed = fromfile(dtype=numpy.int8, offset=0xb6, count=1).any()
arr = fromfile(dtype=numpy.float64, offset=0x800)
@ -92,7 +92,6 @@ class OBRData:
tm = arrs[2] + 1j * arrs[3]
meas_date, calib_date = numpy.split(dates, 2)
tt = numpy.arange(arrs[0].size) * dt_ns + t0half * 2
result = OBRData(
te = te,

135
backwash/ova_bin.py Normal file
View File

@ -0,0 +1,135 @@
from typing import IO, Self
from dataclasses import dataclass
from pathlib import Path
import logging
import numpy
from numpy.typing import NDArray
from numpy.fft import fftshift, fftfreq
from .utils import C0
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
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.tee.size) * self.dt_ns
return tt
@property
def wl_range_nm(self) -> NDArray[numpy.float64]:
freq_range = numpy.asarray([
self.max_freq_GHz - 1 / (2 * self.dt_ns),
welf.max_freq_GHz,
])
return C0 / freq_range
@property
def ctr_freq_GHz(self) -> float:
return self.max_freq_GHz - 1 / (4 * self.dt_ns)
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
def wls(self, size: int) -> NDArray[numpy.float64]:
# To be used with spectrum generated with e.g. fft(fftshift(data.te))
return C0 / self.freqs(size)
def window(self, size: int) -> NDArray[numpy.float64]:
# Approximation of the generalized Hamming window used when freq_windowed==True
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
ham = alpha - (1 - alpha) * numpy.cos(2 * numpy.pi * nn)
return scale * ham
@staticmethod
def read(file: str | IO[bytes] | Path) -> Self:
raise NotImplementedError('Still WIP')
def fromfile(*args, **kwargs) -> NDArray:
if not isinstance(file, str | Path):
file.seek(0)
return numpy.fromfile(file, *args, **kwargs)
magic = fromfile(dtype=numpy.uint8, offset=0x10, count=7)
if (magic != [0x40] + [ord(cc) for cc in 'S33OVA']).any():
logger.warning(f'Unexpected magic bytes: {magic}')
metadata = fromfile(dtype=numpy.float64, offset=0x00, count=2)
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)
ng = fromfile(dtype=numpy.float32, offset=0x21, count=1)
max_freq_GHz = metadata[0]
#dt_ns = metadata[3] / 2
arrs = numpy.split(arr, 4)
te = arrs[0] + 1j * arrs[1]
tm = arrs[2] + 1j * arrs[3]
result = OVABINData(
te = te,
tm = tm,
#dt_ns = dt_ns,
max_freq_GHz = max_freq_GHz,
ng_setting = ng,
meas_date = meas_date,
_wip_metadata = metadata[1:],
)
"""
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?
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)
0x20: 00 00 80 20 40 01 00 00 00 00 00 00 00 00 00 00
| ng (f32) |----........|
??? average count
0x30: 00 00 00 00 00 00 38 98 40 00 00 00 00 00 00 00
???????????
0x40: 00 00 00 00 00 00 00 00 00 E7 07 0A 00 05 00 06
|year month week? day-
acquisition timestamp
0x50: 00 12 00 0F 00 0F 00 23 00 F7 27 6F E5 17 A1 A7
--- hr minute sec ms | f64 data starts----
(offset 0x59)
0x400040:
3F C8 E2 3E 89 8A A4 8C BF A9 4D A8 8A D6 9B 94
0x400050:
3F 8E BB 79 0C C2 84 92 3F 4E 4F 4E 45 40
|N O N E |
"""

View File

@ -1,5 +1,5 @@
[project]
name = "blowback"
name = "backwash"
description = "Optical reflectometry file format reader"
readme = "README.md"
license = { file = "LICENSE.md" }
@ -39,7 +39,7 @@ dependencies = [
"numpy>=1.26",
]
[tool.hatch.version]
path = "blowback/__init__.py"
path = "backwash/__init__.py"
[tool.ruff]

2
uv.lock generated
View File

@ -3,7 +3,7 @@ revision = 3
requires-python = ">=3.13"
[[package]]
name = "blowback"
name = "backwash"
version = "0.1.0"
source = { virtual = "." }
dependencies = [