simple-scope-parser/scope_parser/owon_parser.py

108 lines
3.4 KiB
Python

"""
Parser for OWON oscilloscope CSV files.
"""
import csv
from typing import Dict, List
import numpy as np
from .base_parser import BaseOscilloscopeParser
from .data import ScopeData, ChannelData
class OwonParser(BaseOscilloscopeParser):
"""Parser for OWON oscilloscope CSV files."""
def can_parse(self, file_path: str) -> bool:
"""Check if file is from OWON scope."""
try:
with open(file_path, "r") as f:
first_lines = [f.readline().strip() for _ in range(10)]
# Look for OWON-specific patterns
return any("Channel" in line and "CH" in line for line in first_lines)
except:
return False
def parse(self, file_path: str) -> ScopeData:
"""Parse OWON oscilloscope CSV file."""
with open(file_path, "r") as f:
# Read header metadata
metadata_lines = []
data_start_line = 0
for i, line in enumerate(f):
line = line.strip()
if not line: # Empty line indicates end of metadata
data_start_line = i + 1
break
metadata_lines.append(line)
# Parse metadata
metadata = self._parse_metadata(metadata_lines)
# Reset file pointer to data section
f.seek(0)
for _ in range(data_start_line):
next(f)
# Parse CSV data
reader = csv.DictReader(f)
# Extract data columns
voltage_data = []
time_data = []
for row in reader:
# Get voltage data (look for CH*_Voltage column)
voltage_col = None
for col_name in row.keys():
if "Voltage" in col_name:
voltage_col = col_name
break
if voltage_col is None:
raise ValueError("Could not find voltage column in CSV data")
# Convert mV to volts
voltage_mv = float(row[voltage_col])
voltage_data.append(voltage_mv / 1000.0)
# Calculate time values from index and time interval
index = int(row["index"])
time_interval = self._extract_time_interval(metadata)
time_data.append(index * time_interval)
# Create channel data
channel_name = metadata.get("Channel", "CH1").replace(":", "").strip()
channel_data = ChannelData(
channel_name=channel_name,
voltage_values=np.array(voltage_data),
time_values=np.array(time_data),
metadata=metadata,
)
return ScopeData(channels={channel_name: channel_data}, metadata=metadata)
def _parse_metadata(self, metadata_lines: List[str]) -> Dict[str, str]:
"""
Parse metadata from header lines.
You can access the metadata like this:
data = parse_owon_data(".CSV")
print(data.frequency)
print(data.vpp)
"""
metadata = {}
for line in metadata_lines:
if "," in line:
parts = line.split(",", 1)
if len(parts) == 2:
key = parts[0].strip().rstrip(":").strip()
value = parts[1].strip()
metadata[key] = value
return metadata