Files
templates/docs/reference-comparison.md
T
Andrey 41e24629ce Расширить DEIF, загрузку CAN и общую обработку сигналов
Добавить общее ядро DEIF, эмуляцию приборов и переносимые панели Python/Qt.
Расширить загрузчики F2812 и F28335, обновление Flash и профиль STM Invertor.
Добавить альтернативный МНК Eigen, модели неисправностей и диагностику сигналов.
Обновить справочники устройств, проекты CCS и регрессионные проверки.
2026-10-24 15:40:51 +03:00

19 KiB
Raw Blame History

Сравнение сигналов с CSV-эталоном

Общее ядро set_devices.signal_reference и Qt-порт set_devices.qt_ports.reference_comparison сравнивают измеренную запись с эталоном. Они не импортируют приложение, не выбирают его каталоги и не требуют конкретного движка отрисовки. Ядро использует только стандартную библиотеку Python; Qt-порт поддерживает PySide6 и PySide2.

Численный API

Comparison.analysis содержит локальный параметрический отчёт: summary, details, attention, findings, features, model_report. Он рассчитывается set_devices.signal_diagnostics по тому же интервалу, временному сдвигу и допускам. Исходные метрики используют все общие отсчёты; объём выборки подбора моделей явно указан в model_report. Добавлено необязательное поле с пустым словарём по умолчанию: прежний конструктор Comparison с пятью аргументами сохраняет совместимость.

Для одинаковых известных обозначений Uce, Uge, Ic анализ различает повторные полные переходы, усиленный звон Uce после выключения, отсутствие переключения, растянутые фронты и временной сдвиг. Общие причины включают смещение, шум и неопределённое изменение формы. Разные известные физические каналы, недостаточное число точек и неполное покрытие отражаются в выводе. На неизвестных каналах аппаратные гипотезы о снаббере и транзисторе не строятся.

set_devices.signal_fault_models подбирает смещение, масштаб, дрейф, задержку, растяжение фронтов, постоянный уровень, кусочные прерывания и затухающий отклик RLC. set_devices.signal_joint_models добавляет локальную ВАХ Uce=U0+Rdiff*Ic, остаточный ток выключенного состояния и совпадение провалов управления/проводимости по трём каналам.

compare(..., circuit=..., channels=...) принимает необязательные известные inductance_h, capacitance_f, resistance_ohm в СИ и словарь связанных каналов dict(measured=..., reference=...). GUI формирует эти снимки сам. Однозначность физических имён и единиц проверяется до совместного анализа.

Глобальные модели сравниваются по BIC общей обучающей выборки и RMSE на каждой третьей отложенной точке. JSON сохраняет всех конкурентов, число параметров, формулы, критерии и ограничения. BIC не интерпретируется как вероятность аппаратного отказа. Без известного элемента R/L/C не выдаются три произвольных номинала: доступны только LC и R/L последовательного эквивалента полюсов.

ComparisonAnalysis в qt_ports.reference_results показывает одну строку и кнопку отчёта с таблицей моделей и подробным текстом по образцу Android GUI. Компонент используется и над исходным графиком, и в полной форме сравнения; изменение входов, чтение другого эталона и ошибки очищают прежний анализ. JSON-экспорт обоих видов включает analysis рядом с metrics. Ядро не использует сеть или обученную модель; пороги признаков и ограничения указаны в подробностях.

Trace(name, times, values) содержит имя, строго возрастающие временные метки в миллисекундах и амплитуды в единицах канала. trace_from_pairs создаёт такой снимок из пар (time_ms, value); необязательный transform применяет множитель или иное преобразование амплитуды.

read_reference(path, cancel=...) потоково читает UTF-8 CSV с необязательным BOM. Первый столбец — time_ms либо timestamp с ISO-временем и явным часовым поясом. Остальные столбцы имеют непустые уникальные имена каналов. Поддерживаются запятая, точка с запятой и табуляция. Пустые ячейки и NaN сохраняются как пропуски; повторное время, бесконечности и повреждённые строки отклоняются.

from set_devices.signal_reference import compare, read_reference, trace_from_pairs  # Ядро можно использовать без Qt и графика.
measured = trace_from_pairs('U (V)', [(0., 2.), (1., 4.), (2., 6.)])  # Время задано в миллисекундах, амплитуда — в вольтах.
reference = read_reference('reference.csv')['U (V)']  # Столбец выбирается по полному имени канала.
result = compare(measured, reference, absolute_tolerance=.1, relative_tolerance_pct=2.)  # Допуск равен 0,1 В плюс 2% модуля эталона.
print(result.metrics['rmse'])  # Показатель рассчитан по всем корректным точкам измерения в общем интервале.

compare возвращает Comparison: нормализованные кривые measured и reference, остаток difference, эталон на сетке остатка expected и словарь metrics. Статистика включает покрытие, пропуски, среднее смещение, MAE, RMSE, СКО без смещения, максимальную ошибку и выходы за допуск.

Эталон линейно интерполируется на исходную сетку измерения без экстраполяции и соединения через NaN. Остаток равен измерению минус эталон. Допуск равен absolute_tolerance + relative_tolerance_pct / 100 * abs(reference); равенство границе допуска не считается превышением. Экранная децимация не участвует в расчёте.

По умолчанию начала записей совмещаются. align_start=False сохраняет различие абсолютных начал; положительный shift_ms сдвигает эталон вправо. interval=(start_ms, stop_ms) задаётся от начала измерения, обе границы включены. Callback cancel() прерывает подготовку, чтение и сравнение через InterruptedError.

Наложение на существующий график

Для добавления эталона в уже работающий график используйте set_devices.qt_ports.reference_overlay.ReferenceOverlayPanel. Это компактные параметры без canvas. Оригинальный график остаётся у потребителя и продолжает показывать измерение при загрузке и изменении эталона.

Конструктор принимает sources, parent, source_path и необязательный path_provider с тем же смыслом, что в таблице ниже. load_reference(path) автоматически читает CSV, совмещает выбранные каналы и рассчитывает показатели в рабочем потоке. Отдельной кнопки запуска расчёта нет. Изменение канала, сдвига, совмещения начал или допусков обновляет результат автоматически.

Сигнал changed сообщает потребителю, что overlay() вернёт актуальные спецификации и точки одной дополнительной кривой. Потребитель добавляет их к оригинальным рядам и общей легенде своего canvas. RESULT_KEY отличает эталон от измерений; оранжевая кривая имеет подпись Эталон: <канал>. Временные метки эталона уже находятся в исходной шкале измерения: начало оригинала не обнуляется. Потребитель применяет своё перебазирование короткой развёртки к обеим кривым одинаково.

set_sources(sources) обновляет кадр прибора или преобразование амплитуд, сохраняя загруженный эталон. Сигнал remove_requested предлагает владельцу удалить дополнительный слой и параметры. report() и раскрываемая строка «Допуски и отчёт» предоставляют актуальную статистику и экспорт JSON. Если общей части времени нет, кривая остаётся доступна, а показатели заменяются объяснением отсутствия перекрытия. close() останавливает worker, не закрывая график потребителя.

Истории, переданные в одном снимке sources, должны быть неизменяемыми; для нового кадра передайте новую историю через set_sources. Порт поддерживает PySide6 и PySide2 без импорта приложения.

Подробные показатели рядом с исходным графиком

ReferenceOverlayPanel.results — виджет ComparisonResults с полной таблицей всех 14 показателей: покрытие, пропуски, смещение, MAE, RMSE, СКО, максимум и его время, нормированная ошибка и выходы за допуск. Потребитель размещает его в существующей боковой области рядом с canvas; в SETGUI он открывается автоматически во вкладке «Отклонения и расчёты». Сигнал results_requested кнопки «Расчёты» позволяет вернуться к этой области после выбора обычной легенды.

Флажок results.delta_curve добавляет в overlay() кривую с ключом DIFFERENCE_KEY. Её временные метки находятся в той же исходной шкале, что эталон и оригинал. Исходные кривые сохраняются, отдельный canvas не создаётся. Кнопка JSON рядом с таблицей экспортирует тот же актуальный результат. Изменение параметров и ошибки очищают устаревшие показатели.

comparison_rows(metrics) из qt_ports.reference_results задаёт единые подписи, порядок и единицы как для этой таблицы, так и для прежнего диалога.

Совместимые Qt-панель и отдельное окно

ReferenceComparisonPanel — обычный QWidget для существующей страницы графика. Кнопка «К записи» испускает back_requested; потребитель сам скрывает панель и возвращает исходный вид. При повторном показе той же панели сохраняются эталон, параметры и рассчитанные показатели.

ReferenceComparisonDialog — отдельный QDialog с тем же расчётом и настройками. Оба конструктора принимают:

Параметр Контракт
sources Последовательность пар (source, points): source.name — имя, source.display_value(value) — преобразование амплитуды, points — полная неизменяемая история (time_ms, value)
parent Родительский QWidget; для встроенной панели передайте страницу графика
source_path Происхождение измерения для JSON-отчёта, по умолчанию пустая строка
plot_factory Обязательная фабрика без аргументов, возвращающая настроенный QWidget графика
series_factory Обязательная фабрика factory(key, name, color=..., timestamps=..., values=...), создающая кривую потребителя
path_provider Необязательный callback filename → начальный путь; пустое имя используется для открытия эталона, reference_comparison.json — для отчёта
from set_devices.qt_ports.reference_comparison import ReferenceComparisonPanel  # Qt загружается только при импорте конкретного порта.
panel = ReferenceComparisonPanel(  # Один компонент обслуживает выбор каналов, параметры, фоновый расчёт и экспорт.
    sources=recording_channels,  # Потребитель фиксирует полные истории и преобразование амплитуд до создания панели.
    parent=chart_page,  # Сравнение размещается в существующей рабочей области.
    source_path=recording_filename,  # Имя исходной записи попадёт в отчёт.
    plot_factory=create_comparison_canvas,  # Адаптер создаёт график с единой шкалой Y для обеих кривых.
    series_factory=create_series,  # Контейнеры кривых принадлежат используемому движку отрисовки.
    path_provider=recording_path,  # Папки и правила хранения остаются политикой потребителя.
)  # Все функции и объекты адаптера задаются приложением до этого вызова.
chart_page.layout().addWidget(panel, 1)  # Панель занимает свободное место страницы.
panel.back_requested.connect(show_recording)  # Обработчик скрывает сравнение и возвращает исходный график.

Canvas должен предоставлять изменяемый список _series, методы reset_interaction(), _sync_bounds(), стандартные update() и close(), флажки axis_lock_x и axis_lock_y с setChecked(), поле axis_limits, visible_bounds.left/right в миллисекундах и viewport типа protocan.plot.Viewport. _sync_bounds() задаёт конечный ненулевой диапазон X даже для пустого графика. Обе наложенные кривые используют одну шкалу Y; автоматическое разделение каналов на независимые оси отключает адаптер. Дополнительные кнопки canvas, подписи и правила снимков также настраиваются в plot_factory.

Панель передаёт фабрике кривых полные массивы: их экранное сокращение остаётся ответственностью canvas. Временные поля интерфейса показывают микросекунды, ядро и JSON-отчёт используют миллисекунды. Явно различающиеся единицы в скобках имён каналов блокируют сравнение; автоматической конвертации нет.

Истории и настройки источников нельзя менять, пока панель использует их снимок. При смене записи или преобразования канала закройте старую панель и создайте новую. close() встроенной панели отменяет и дожидается worker; уничтожение родителя также останавливает поток до удаления дочерних объектов. Отдельный диалог откладывает закрытие до завершения кооперативной отмены.

load_reference(path) позволяет открыть эталон программно, report() возвращает актуальный словарь отчёта либо None. Изменение входных параметров очищает старые кривые и показатели до следующего расчёта.

Проверки

python/tests/test_reference_comparison_port.py проверяет внедрение стороннего canvas, преобразование амплитуд, отклонение и экспорт с внешним provider путей, а также API отдельного диалога. Его можно запустить из каталога templates/python командой python -m unittest discover -s tests -p test_reference_comparison_port.py.

python/tests/test_shared_library_boundary.py проверяет независимость вычислительных модулей от GUI и Qt. Интеграционные проверки потребителя дополнительно покрывают полные истории, общий масштаб Y, отмену, смену записи, возврат к графику и полноэкранный режим.