feat(parser): route BinRAW captures through RAW identification path
Reconstruct a signed pulse train from BinRAW Data_RAW demodulated bits (run-length encoded at TE-µs steps) so BinRAW files populate raw_data and flow through the existing RAW identification pipeline. Previously 0/120 BinRAW files yielded a predicted_category; now 118/120 categorize via the live SignatureMatcher engine. RAW code path is unchanged. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -182,6 +182,20 @@ class SubFileParser:
|
|||||||
data_hex = self.fields['Data_RAW'].replace(' ', '')
|
data_hex = self.fields['Data_RAW'].replace(' ', '')
|
||||||
metadata.bin_raw_data = bytes.fromhex(data_hex)
|
metadata.bin_raw_data = bytes.fromhex(data_hex)
|
||||||
|
|
||||||
|
# Reconstruct a signed pulse train (µs) from the demodulated bit
|
||||||
|
# stream so BinRAW captures flow through the same RAW identification
|
||||||
|
# path as RAW_Data files. Data_RAW is the signal sampled at TE-µs
|
||||||
|
# steps: a run of N identical bits is one pulse of N*TE µs (+high on
|
||||||
|
# 1s, -low on 0s). This populates raw_data, which makes the
|
||||||
|
# has_raw_data property true.
|
||||||
|
n_bits = metadata.bin_raw_bit or metadata.bit_length
|
||||||
|
if metadata.bin_raw_data and metadata.bin_raw_te and n_bits:
|
||||||
|
pulses = self._binraw_to_pulses(
|
||||||
|
metadata.bin_raw_data, n_bits, metadata.bin_raw_te)
|
||||||
|
if pulses:
|
||||||
|
metadata.raw_data = pulses
|
||||||
|
metadata.pulse_count = len(pulses)
|
||||||
|
|
||||||
# Calculate duration
|
# Calculate duration
|
||||||
if metadata.bit_length and metadata.bin_raw_te:
|
if metadata.bit_length and metadata.bin_raw_te:
|
||||||
metadata.duration_ms = (metadata.bit_length * metadata.bin_raw_te) / 1000.0
|
metadata.duration_ms = (metadata.bit_length * metadata.bin_raw_te) / 1000.0
|
||||||
@@ -190,6 +204,32 @@ class SubFileParser:
|
|||||||
self.errors.append(f"Error parsing BinRAW fields: {e}")
|
self.errors.append(f"Error parsing BinRAW fields: {e}")
|
||||||
logger.warning(f"Parse error: {e}")
|
logger.warning(f"Parse error: {e}")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _binraw_to_pulses(data: bytes, n_bits: int, te: int) -> List[int]:
|
||||||
|
"""Expand a BinRAW bit stream into a signed timing array (µs).
|
||||||
|
|
||||||
|
Bits are read MSB-first, truncated to ``n_bits``, then run-length
|
||||||
|
encoded: each run of ``k`` equal bits becomes ``k*te`` µs, signed
|
||||||
|
positive for 1s (pulse) and negative for 0s (gap).
|
||||||
|
"""
|
||||||
|
bits = []
|
||||||
|
for byte in data:
|
||||||
|
for i in range(7, -1, -1):
|
||||||
|
bits.append((byte >> i) & 1)
|
||||||
|
bits = bits[:n_bits]
|
||||||
|
if not bits:
|
||||||
|
return []
|
||||||
|
pulses: List[int] = []
|
||||||
|
current, run = bits[0], 1
|
||||||
|
for b in bits[1:]:
|
||||||
|
if b == current:
|
||||||
|
run += 1
|
||||||
|
else:
|
||||||
|
pulses.append(run * te * (1 if current else -1))
|
||||||
|
current, run = b, 1
|
||||||
|
pulses.append(run * te * (1 if current else -1))
|
||||||
|
return pulses
|
||||||
|
|
||||||
|
|
||||||
def parse_sub_file(file_path: str) -> SignalMetadata:
|
def parse_sub_file(file_path: str) -> SignalMetadata:
|
||||||
"""
|
"""
|
||||||
|
|||||||
Reference in New Issue
Block a user