new project structure
This commit is contained in:
108
rfg_adc_plotter/main.py
Normal file
108
rfg_adc_plotter/main.py
Normal file
@ -0,0 +1,108 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Реалтайм-плоттер для свипов из виртуального COM-порта.
|
||||
|
||||
Формат строк:
|
||||
- "Sweep_start" — начало нового свипа (предыдущий считается завершённым)
|
||||
- "s CH X Y" — точка (номер канала, индекс X, значение Y), все целые со знаком
|
||||
|
||||
Отрисовываются четыре графика:
|
||||
- Сырые данные: последний полученный свип (Y vs X)
|
||||
- Водопад сырых данных: последние N свипов
|
||||
- FFT текущего свипа
|
||||
- B-scan: водопад FFT-строк
|
||||
|
||||
Зависимости: numpy. PySerial опционален — при его отсутствии
|
||||
используется сырой доступ к TTY через termios.
|
||||
GUI: matplotlib (совместимый) или pyqtgraph (быстрый).
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
|
||||
|
||||
def build_parser() -> argparse.ArgumentParser:
|
||||
parser = argparse.ArgumentParser(
|
||||
description=(
|
||||
"Читает свипы из виртуального COM-порта и рисует: "
|
||||
"последний свип и водопад (реалтайм)."
|
||||
)
|
||||
)
|
||||
parser.add_argument(
|
||||
"port",
|
||||
help="Путь к порту, например /dev/ttyACM1 или COM3 (COM10+: \\\\.\\COM10)",
|
||||
)
|
||||
parser.add_argument("--baud", type=int, default=115200, help="Скорость (по умолчанию 115200)")
|
||||
parser.add_argument("--max-sweeps", type=int, default=200, help="Количество видимых свипов в водопаде")
|
||||
parser.add_argument("--max-fps", type=float, default=30.0, help="Лимит частоты отрисовки, кадров/с")
|
||||
parser.add_argument("--cmap", default="viridis", help="Цветовая карта водопада")
|
||||
parser.add_argument(
|
||||
"--spec-clip",
|
||||
default="2,98",
|
||||
help=(
|
||||
"Процентильная обрезка уровней водопада спектров, %% (min,max). "
|
||||
"Напр. 2,98. 'off' — отключить"
|
||||
),
|
||||
)
|
||||
parser.add_argument(
|
||||
"--spec-mean-sec",
|
||||
type=float,
|
||||
default=0.0,
|
||||
help=(
|
||||
"Вычитание среднего по каждой частоте за последние N секунд "
|
||||
"в водопаде спектров (0 — отключить)"
|
||||
),
|
||||
)
|
||||
parser.add_argument("--title", default="ADC Sweeps", help="Заголовок окна")
|
||||
parser.add_argument(
|
||||
"--fancy",
|
||||
action="store_true",
|
||||
help="Заполнять выпавшие точки средними значениями между соседними",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--ylim",
|
||||
type=str,
|
||||
default=None,
|
||||
help="Фиксированные Y-пределы для кривой формата min,max (например -1000,1000). По умолчанию авто",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--backend",
|
||||
choices=["auto", "pg", "mpl"],
|
||||
default="auto",
|
||||
help="Графический бэкенд: pyqtgraph (pg) — быстрее; matplotlib (mpl) — совместимый. По умолчанию auto",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--norm-type",
|
||||
choices=["projector", "simple"],
|
||||
default="projector",
|
||||
help="Тип нормировки: projector (по огибающим в [-1000,+1000]) или simple (raw/calib)",
|
||||
)
|
||||
return parser
|
||||
|
||||
|
||||
def main():
|
||||
args = build_parser().parse_args()
|
||||
|
||||
if args.backend == "pg":
|
||||
from rfg_adc_plotter.gui.pyqtgraph_backend import run_pyqtgraph
|
||||
try:
|
||||
run_pyqtgraph(args)
|
||||
except Exception as e:
|
||||
sys.stderr.write(f"[error] PyQtGraph бэкенд недоступен: {e}\n")
|
||||
sys.exit(1)
|
||||
return
|
||||
|
||||
if args.backend == "auto":
|
||||
try:
|
||||
from rfg_adc_plotter.gui.pyqtgraph_backend import run_pyqtgraph
|
||||
run_pyqtgraph(args)
|
||||
return
|
||||
except Exception:
|
||||
pass # Откатываемся на matplotlib
|
||||
|
||||
from rfg_adc_plotter.gui.matplotlib_backend import run_matplotlib
|
||||
run_matplotlib(args)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user