From 874c4863c85ae9833675e19afec56b6cf352b962 Mon Sep 17 00:00:00 2001 From: jared Date: Fri, 6 Dec 2024 21:04:02 -0500 Subject: [PATCH 01/13] update --- OpenOTDR.py | 47 ++++++++++++++++++++++++++ mainwindow.py | 57 ++++++++++++++++---------------- mainwindow.ui | 91 +++++++++++++++++++++++++++++++-------------------- 3 files changed, 132 insertions(+), 63 deletions(-) diff --git a/OpenOTDR.py b/OpenOTDR.py index 0b0cb4d..d896805 100755 --- a/OpenOTDR.py +++ b/OpenOTDR.py @@ -18,6 +18,8 @@ from matplotlib import colors from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar +from matplotlib.widgets import Cursor + import mainwindow @@ -146,6 +148,7 @@ def __init__(self): self.user_interface.recalculateEvents.clicked.connect(self.recalculate_events) self.window_len = 0 self.canvas = None + self.cursor = None self.toolbar = None self.raw_features = [] self.raw_traces = [] @@ -191,6 +194,31 @@ def _load_file(self, url, _project=False): item.data = d_data self.project_model.appendRow(item) + def hover(event, graph_info): +# print("hover event:", dir(event)) +# hover graph_info: ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_guiEvent', '_guiEvent_deleted', '_last_axes_ref', '_lastevent', '_process', '_set_inaxes', 'button', 'canvas', 'dblclick', 'guiEvent', 'inaxes', 'key', 'lastevent', 'modifiers', 'name', 'step', 'x', 'xdata', 'y', 'ydata'] + + print("hover graph_info:", dir(graph_info)) + print("graph_info.guiEvent:", graph_info.guiEvent) + print("graph_info.inaxes:", graph_info.inaxes) + print("graph_info.key:", graph_info.key) + print("graph_info.x:", graph_info.x) + print("graph_info.y:", graph_info.y) + print("graph_info.xdata:", graph_info.xdata) + print("graph_info.ydata:", graph_info.ydata) + print("graph_info.name:", graph_info.name) + + if graph_info.inaxes == graph_info.ax: + cont, ind = line.contains(event) + if cont: + update_annot(ind) + annot.set_visible(True) + fig.canvas.draw_idle() + else: + if vis: + annot.set_visible(False) + fig.canvas.draw_idle() + def _draw(self): '''(re)draw the plot with the latest data''' fig = Figure() @@ -203,6 +231,7 @@ def _draw(self): d_final_data["trace"][0], label=wavelength, color=wavelength_to_rgb(wavelength)) + self.cursor = Cursor(plt, useblit=True, color='red', linewidth=2) if self.canvas: self.user_interface.graphLayout.removeWidget(self.canvas) self.canvas.close() @@ -210,10 +239,14 @@ def _draw(self): self.user_interface.graphLayout.removeWidget(self.toolbar) self.toolbar.close() fig.legend() +# if i want to have my own hover function +# fig.canvas.mpl_connect("motion_notify_event", self.hover) self.canvas = FigureCanvas(fig) self.toolbar = CustomNavigationToolbar(self.canvas, self, coordinates=True) self.user_interface.graphLayout.addWidget(self.canvas) self.user_interface.graphLayout.addWidget(self.toolbar) + self.recalculate_events() + def open_project(self): '''Load a project from a file''' @@ -236,6 +269,7 @@ def open_project(self): self._draw() self._draw() self.recalculate_events() + self._draw def save_project(self): '''Save a project to a file''' @@ -284,6 +318,7 @@ def add_trace(self): for index in range(self.project_model.rowCount()): raw_data = self.project_model.item(index).data self.raw_traces.append(raw_data) + self.recalculate_events() self._draw() def remove_trace(self): @@ -344,11 +379,15 @@ def __calculate_loss_and_dispersion(self, raw_traces, meta_data): def _update_events_table(self, d_events, raw_traces): '''Update the events table in the UI''' + print("_update_events_table") self.events_model.clear() self.events_model.setHorizontalHeaderLabels(['Event', 'Distance (km)', 'Loss (dB)', 'Dispersion factor']) +# +# Qt.AlignRight + # for position, meta_data in d_events.items(): current_row = self.events_model.rowCount() @@ -370,9 +409,16 @@ def _update_events_table(self, d_events, raw_traces): event_type.setEditable(True) self.events_model.setItem(current_row, 0, event_type) self.events_model.sort(1) + print("events_model", dir(self.events_model)) + print("events_model.property", self.events_model.property) + print("events_proxy_model", dir(self.events_proxy_model)) + print("events_proxy_model", self.events_proxy_model.property) +# self.events_proxy_model.resizeColumnsToContents() +# self.user_interface.eventTableView.setModel.resizeColumnsToContents() def recalculate_events(self): '''Recalculate the events''' + print("starting recalculate_events()") if self.busy.locked(): return with self.busy: @@ -385,6 +431,7 @@ def recalculate_events(self): l_feature_points.append(find_edges(differentiate_data(d_data))) raw_features = l_feature_points raw_traces = l_traces + print("recalculate_events: raw_features:", raw_features) if not raw_features: return d_events = self._filter_events(raw_features) diff --git a/mainwindow.py b/mainwindow.py index e05a389..caccb9e 100644 --- a/mainwindow.py +++ b/mainwindow.py @@ -2,7 +2,7 @@ # Form implementation generated from reading ui file 'mainwindow.ui' # -# Created by: PyQt5 UI code generator 5.15.9 +# Created by: PyQt5 UI code generator 5.15.11 # # WARNING: Any manual changes made to this file will be lost when pyuic5 is # run again. Do not edit this file unless you know what you are doing. @@ -14,7 +14,7 @@ class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") - MainWindow.resize(1280, 755) + MainWindow.resize(1280, 761) self.mainWidget = QtWidgets.QWidget(MainWindow) self.mainWidget.setObjectName("mainWidget") self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.mainWidget) @@ -26,7 +26,6 @@ def setupUi(self, MainWindow): sizePolicy.setHeightForWidth(self.tabWidget.sizePolicy().hasHeightForWidth()) self.tabWidget.setSizePolicy(sizePolicy) self.tabWidget.setMinimumSize(QtCore.QSize(320, 720)) - self.tabWidget.setTabPosition(QtWidgets.QTabWidget.West) self.tabWidget.setObjectName("tabWidget") self.projectWidget = QtWidgets.QWidget() self.projectWidget.setObjectName("projectWidget") @@ -41,24 +40,23 @@ def setupUi(self, MainWindow): self.groupBox.setSizePolicy(sizePolicy) self.groupBox.setMinimumSize(QtCore.QSize(0, 20)) self.groupBox.setBaseSize(QtCore.QSize(0, 30)) - self.groupBox.setFlat(True) + self.groupBox.setFlat(False) self.groupBox.setObjectName("groupBox") self.horizontalLayout = QtWidgets.QHBoxLayout(self.groupBox) self.horizontalLayout.setObjectName("horizontalLayout") self.addTrace = QtWidgets.QPushButton(self.groupBox) + self.addTrace.setAcceptDrops(True) self.addTrace.setAutoFillBackground(False) - self.addTrace.setText("") icon = QtGui.QIcon.fromTheme("list-add") self.addTrace.setIcon(icon) self.addTrace.setDefault(True) - self.addTrace.setFlat(True) + self.addTrace.setFlat(False) self.addTrace.setObjectName("addTrace") self.horizontalLayout.addWidget(self.addTrace) self.removeTrace = QtWidgets.QPushButton(self.groupBox) - self.removeTrace.setText("") icon = QtGui.QIcon.fromTheme("list-remove") self.removeTrace.setIcon(icon) - self.removeTrace.setFlat(True) + self.removeTrace.setFlat(False) self.removeTrace.setObjectName("removeTrace") self.horizontalLayout.addWidget(self.removeTrace) self.recalculateEvents = QtWidgets.QPushButton(self.groupBox) @@ -69,25 +67,26 @@ def setupUi(self, MainWindow): self.recalculateEvents.setSizePolicy(sizePolicy) icon = QtGui.QIcon.fromTheme("view-refresh") self.recalculateEvents.setIcon(icon) - self.recalculateEvents.setFlat(True) + self.recalculateEvents.setFlat(False) self.recalculateEvents.setObjectName("recalculateEvents") self.horizontalLayout.addWidget(self.recalculateEvents) self.saveProject = QtWidgets.QPushButton(self.groupBox) - icon = QtGui.QIcon.fromTheme("document-save") + self.saveProject.setAutoFillBackground(False) + icon = QtGui.QIcon.fromTheme("media-floppy") self.saveProject.setIcon(icon) - self.saveProject.setFlat(True) + self.saveProject.setFlat(False) self.saveProject.setObjectName("saveProject") self.horizontalLayout.addWidget(self.saveProject) self.openProject = QtWidgets.QPushButton(self.groupBox) icon = QtGui.QIcon.fromTheme("folder-open") self.openProject.setIcon(icon) - self.openProject.setFlat(True) + self.openProject.setFlat(False) self.openProject.setObjectName("openProject") self.horizontalLayout.addWidget(self.openProject) self.printReport = QtWidgets.QPushButton(self.groupBox) - icon = QtGui.QIcon.fromTheme("document-print") + icon = QtGui.QIcon.fromTheme("QIcon::ThemeIcon::Printer") self.printReport.setIcon(icon) - self.printReport.setFlat(True) + self.printReport.setFlat(False) self.printReport.setObjectName("printReport") self.horizontalLayout.addWidget(self.printReport) self.verticalLayout_3.addWidget(self.groupBox) @@ -126,7 +125,7 @@ def setupUi(self, MainWindow): self.horizontalLayout_3.addWidget(self.tabWidget) self.dataWidget = QtWidgets.QWidget(self.mainWidget) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) - sizePolicy.setHorizontalStretch(0) + sizePolicy.setHorizontalStretch(1) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.dataWidget.sizePolicy().hasHeightForWidth()) self.dataWidget.setSizePolicy(sizePolicy) @@ -136,7 +135,7 @@ def setupUi(self, MainWindow): self.verticalLayout_2.setObjectName("verticalLayout_2") self.graphWidget = QtWidgets.QWidget(self.dataWidget) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) - sizePolicy.setHorizontalStretch(0) + sizePolicy.setHorizontalStretch(1) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.graphWidget.sizePolicy().hasHeightForWidth()) self.graphWidget.setSizePolicy(sizePolicy) @@ -153,8 +152,8 @@ def setupUi(self, MainWindow): self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.widget) self.horizontalLayout_4.setObjectName("horizontalLayout_4") self.eventTableView = QtWidgets.QTableView(self.widget) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(1) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.eventTableView.sizePolicy().hasHeightForWidth()) self.eventTableView.setSizePolicy(sizePolicy) @@ -176,6 +175,18 @@ def setupUi(self, MainWindow): def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) + self.addTrace.setToolTip(_translate("MainWindow", "Add Trace")) + self.addTrace.setText(_translate("MainWindow", "+")) + self.removeTrace.setToolTip(_translate("MainWindow", "Remove Trace")) + self.removeTrace.setText(_translate("MainWindow", "-")) + self.recalculateEvents.setToolTip(_translate("MainWindow", "Calculate Events")) + self.recalculateEvents.setText(_translate("MainWindow", "calc")) + self.saveProject.setToolTip(_translate("MainWindow", "Save Project")) + self.saveProject.setText(_translate("MainWindow", "save")) + self.openProject.setToolTip(_translate("MainWindow", "Open Project")) + self.openProject.setText(_translate("MainWindow", "open")) + self.printReport.setToolTip(_translate("MainWindow", "Print")) + self.printReport.setText(_translate("MainWindow", "print")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.projectWidget), _translate("MainWindow", "Project")) item = self.metaDataTable.verticalHeaderItem(0) item.setText(_translate("MainWindow", "Project name")) @@ -196,13 +207,3 @@ def retranslateUi(self, MainWindow): item = self.metaDataTable.verticalHeaderItem(8) item.setText(_translate("MainWindow", "Total loss(dB)")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.metaDataWidget), _translate("MainWindow", "Meta Data")) - - -if __name__ == "__main__": - import sys - app = QtWidgets.QApplication(sys.argv) - MainWindow = QtWidgets.QMainWindow() - ui = Ui_MainWindow() - ui.setupUi(MainWindow) - MainWindow.show() - sys.exit(app.exec_()) diff --git a/mainwindow.ui b/mainwindow.ui index f5f99e6..c159679 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -7,7 +7,7 @@ 0 0 1280 - 755 + 761 @@ -29,9 +29,6 @@ 720 - - QTabWidget::West - 0 @@ -64,42 +61,47 @@ - true + false + + true + + + Add Trace + false - + + - - - + true - true + false + + Remove Trace + - + - - - - + - true + false @@ -111,49 +113,68 @@ 0 + + Calculate Events + + + calc + - - - + - true + false + + Save Project + + + false + + + save + - - - + - true + false + + Open Project + + + open + - - - + - true + false + + Print + + + print + - - - + - true + false @@ -227,7 +248,7 @@ - 0 + 1 0 @@ -242,7 +263,7 @@ - 0 + 1 0 @@ -265,8 +286,8 @@ - - 1 + + 0 0 From 3833d94ec01aa4629f8c5ef908c13279ae80d93f Mon Sep 17 00:00:00 2001 From: jared Date: Fri, 6 Dec 2024 22:41:04 -0500 Subject: [PATCH 02/13] pyqt6 --- OpenOTDR.py | 31 +++++++++++++------------- mainwindow.py | 60 +++++++++++++++++++++++++-------------------------- mainwindow.ui | 10 ++++----- 3 files changed, 50 insertions(+), 51 deletions(-) diff --git a/OpenOTDR.py b/OpenOTDR.py index d896805..3f30dab 100755 --- a/OpenOTDR.py +++ b/OpenOTDR.py @@ -5,10 +5,14 @@ import json from collections import deque from threading import Lock -from PyQt5 import QtWidgets -from PyQt5 import QtPrintSupport -from PyQt5 import QtGui -from PyQt5 import QtCore +from PyQt6 import QtWidgets +from PyQt6.QtWidgets import QFileDialog +from PyQt6 import QtPrintSupport +from PyQt6 import QtGui +from PyQt6 import QtCore +#from PyQt6 import Qt +import PyQt6 +import PyQt6.QtCore import numpy as np from scipy.ndimage import zoom from scipy.signal import find_peaks @@ -135,7 +139,7 @@ def __init__(self): # self.events_proxy_model = NaturalSortFilterProxyModel() self.events_proxy_model.setSourceModel(self.events_model) - self.events_proxy_model.sort(1, QtCore.Qt.AscendingOrder) + self.events_proxy_model.sort(1, PyQt6.QtCore.Qt.SortOrder.AscendingOrder) # self.user_interface.eventTableView.setModel(self.events_proxy_model) # @@ -253,9 +257,7 @@ def open_project(self): if self.busy.locked(): return with self.busy: - options = QtWidgets.QFileDialog.Options() - options |= QtWidgets.QFileDialog.DontUseNativeDialog - uri, _ = QtWidgets.QFileDialog.getOpenFileName(self, "Open project", "", "OpenOTDR Project Files(*.opro);;All Files (*)", options=options) + uri, _ = QtWidgets.QFileDialog.getOpenFileName(self, "Open project", "", "OpenOTDR Project Files(*.opro);;All Files (*)", options=QtWidgets.QFileDialog.DontUseNativeDialog) if uri: with open(uri, "r") as file: content = json.load(file) @@ -276,9 +278,7 @@ def save_project(self): if self.busy.locked(): return with self.busy: - options = QtWidgets.QFileDialog.Options() - options |= QtWidgets.QFileDialog.DontUseNativeDialog - uri, _ = QtWidgets.QFileDialog.getSaveFileName(self, "Save project", "", "OpenOTDR Project Files(*.opro);;All Files (*)", options=options) + uri, _ = QtWidgets.QFileDialog.getSaveFileName(self, "Save project", "", "OpenOTDR Project Files(*.opro);;All Files (*)", options=QtWidgets.QFileDialog.DontUseNativeDialog) if uri: _, extension = os.path.splitext(uri) if not extension: @@ -308,9 +308,9 @@ def add_trace(self): if self.busy.locked(): return with self.busy: - options = QtWidgets.QFileDialog.Options() - options |= QtWidgets.QFileDialog.DontUseNativeDialog - files, _ = QtWidgets.QFileDialog.getOpenFileNames(self, "Add traces", "", "OTDR Trace Files(*.sor);;All Files (*)", options=options) + dialog = QtWidgets.QFileDialog(self) + dialog.setOption(QFileDialog.Option.DontUseNativeDialog, True) + files, _ = dialog.getOpenFileNames(self, "Add traces", "", "OTDR Trace Files(*.sor);;All Files (*)") if not files: return for filename in files: @@ -409,6 +409,7 @@ def _update_events_table(self, d_events, raw_traces): event_type.setEditable(True) self.events_model.setItem(current_row, 0, event_type) self.events_model.sort(1) +# self.eventTableView.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents) print("events_model", dir(self.events_model)) print("events_model.property", self.events_model.property) print("events_proxy_model", dir(self.events_proxy_model)) @@ -444,4 +445,4 @@ def recalculate_events(self): MAIN_WINDOW.setWindowTitle("OpenOTDR") MAIN_WINDOW.show() -sys.exit(APP.exec_()) +sys.exit(APP.exec()) diff --git a/mainwindow.py b/mainwindow.py index caccb9e..fc69fd1 100644 --- a/mainwindow.py +++ b/mainwindow.py @@ -1,27 +1,25 @@ -# -*- coding: utf-8 -*- - # Form implementation generated from reading ui file 'mainwindow.ui' # -# Created by: PyQt5 UI code generator 5.15.11 +# Created by: PyQt6 UI code generator 6.7.1 # -# WARNING: Any manual changes made to this file will be lost when pyuic5 is +# WARNING: Any manual changes made to this file will be lost when pyuic6 is # run again. Do not edit this file unless you know what you are doing. -from PyQt5 import QtCore, QtGui, QtWidgets +from PyQt6 import QtCore, QtGui, QtWidgets class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(1280, 761) - self.mainWidget = QtWidgets.QWidget(MainWindow) + self.mainWidget = QtWidgets.QWidget(parent=MainWindow) self.mainWidget.setObjectName("mainWidget") self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.mainWidget) self.horizontalLayout_3.setObjectName("horizontalLayout_3") - self.tabWidget = QtWidgets.QTabWidget(self.mainWidget) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) - sizePolicy.setHorizontalStretch(0) + self.tabWidget = QtWidgets.QTabWidget(parent=self.mainWidget) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Expanding) + sizePolicy.setHorizontalStretch(1) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.tabWidget.sizePolicy().hasHeightForWidth()) self.tabWidget.setSizePolicy(sizePolicy) @@ -31,10 +29,10 @@ def setupUi(self, MainWindow): self.projectWidget.setObjectName("projectWidget") self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.projectWidget) self.verticalLayout_3.setObjectName("verticalLayout_3") - self.groupBox = QtWidgets.QGroupBox(self.projectWidget) + self.groupBox = QtWidgets.QGroupBox(parent=self.projectWidget) self.groupBox.setEnabled(True) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Preferred, QtWidgets.QSizePolicy.Policy.Fixed) + sizePolicy.setHorizontalStretch(1) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.groupBox.sizePolicy().hasHeightForWidth()) self.groupBox.setSizePolicy(sizePolicy) @@ -44,7 +42,7 @@ def setupUi(self, MainWindow): self.groupBox.setObjectName("groupBox") self.horizontalLayout = QtWidgets.QHBoxLayout(self.groupBox) self.horizontalLayout.setObjectName("horizontalLayout") - self.addTrace = QtWidgets.QPushButton(self.groupBox) + self.addTrace = QtWidgets.QPushButton(parent=self.groupBox) self.addTrace.setAcceptDrops(True) self.addTrace.setAutoFillBackground(False) icon = QtGui.QIcon.fromTheme("list-add") @@ -53,15 +51,15 @@ def setupUi(self, MainWindow): self.addTrace.setFlat(False) self.addTrace.setObjectName("addTrace") self.horizontalLayout.addWidget(self.addTrace) - self.removeTrace = QtWidgets.QPushButton(self.groupBox) + self.removeTrace = QtWidgets.QPushButton(parent=self.groupBox) icon = QtGui.QIcon.fromTheme("list-remove") self.removeTrace.setIcon(icon) self.removeTrace.setFlat(False) self.removeTrace.setObjectName("removeTrace") self.horizontalLayout.addWidget(self.removeTrace) - self.recalculateEvents = QtWidgets.QPushButton(self.groupBox) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) + self.recalculateEvents = QtWidgets.QPushButton(parent=self.groupBox) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Fixed, QtWidgets.QSizePolicy.Policy.Fixed) + sizePolicy.setHorizontalStretch(1) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.recalculateEvents.sizePolicy().hasHeightForWidth()) self.recalculateEvents.setSizePolicy(sizePolicy) @@ -70,27 +68,27 @@ def setupUi(self, MainWindow): self.recalculateEvents.setFlat(False) self.recalculateEvents.setObjectName("recalculateEvents") self.horizontalLayout.addWidget(self.recalculateEvents) - self.saveProject = QtWidgets.QPushButton(self.groupBox) + self.saveProject = QtWidgets.QPushButton(parent=self.groupBox) self.saveProject.setAutoFillBackground(False) icon = QtGui.QIcon.fromTheme("media-floppy") self.saveProject.setIcon(icon) self.saveProject.setFlat(False) self.saveProject.setObjectName("saveProject") self.horizontalLayout.addWidget(self.saveProject) - self.openProject = QtWidgets.QPushButton(self.groupBox) + self.openProject = QtWidgets.QPushButton(parent=self.groupBox) icon = QtGui.QIcon.fromTheme("folder-open") self.openProject.setIcon(icon) self.openProject.setFlat(False) self.openProject.setObjectName("openProject") self.horizontalLayout.addWidget(self.openProject) - self.printReport = QtWidgets.QPushButton(self.groupBox) + self.printReport = QtWidgets.QPushButton(parent=self.groupBox) icon = QtGui.QIcon.fromTheme("QIcon::ThemeIcon::Printer") self.printReport.setIcon(icon) self.printReport.setFlat(False) self.printReport.setObjectName("printReport") self.horizontalLayout.addWidget(self.printReport) self.verticalLayout_3.addWidget(self.groupBox) - self.treeView = QtWidgets.QTreeView(self.projectWidget) + self.treeView = QtWidgets.QTreeView(parent=self.projectWidget) self.treeView.setObjectName("treeView") self.verticalLayout_3.addWidget(self.treeView) self.tabWidget.addTab(self.projectWidget, "") @@ -98,7 +96,7 @@ def setupUi(self, MainWindow): self.metaDataWidget.setObjectName("metaDataWidget") self.verticalLayout = QtWidgets.QVBoxLayout(self.metaDataWidget) self.verticalLayout.setObjectName("verticalLayout") - self.metaDataTable = QtWidgets.QTableWidget(self.metaDataWidget) + self.metaDataTable = QtWidgets.QTableWidget(parent=self.metaDataWidget) self.metaDataTable.setObjectName("metaDataTable") self.metaDataTable.setColumnCount(0) self.metaDataTable.setRowCount(9) @@ -123,8 +121,8 @@ def setupUi(self, MainWindow): self.verticalLayout.addWidget(self.metaDataTable) self.tabWidget.addTab(self.metaDataWidget, "") self.horizontalLayout_3.addWidget(self.tabWidget) - self.dataWidget = QtWidgets.QWidget(self.mainWidget) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + self.dataWidget = QtWidgets.QWidget(parent=self.mainWidget) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Expanding) sizePolicy.setHorizontalStretch(1) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.dataWidget.sizePolicy().hasHeightForWidth()) @@ -133,8 +131,8 @@ def setupUi(self, MainWindow): self.dataWidget.setObjectName("dataWidget") self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.dataWidget) self.verticalLayout_2.setObjectName("verticalLayout_2") - self.graphWidget = QtWidgets.QWidget(self.dataWidget) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + self.graphWidget = QtWidgets.QWidget(parent=self.dataWidget) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Expanding) sizePolicy.setHorizontalStretch(1) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.graphWidget.sizePolicy().hasHeightForWidth()) @@ -147,13 +145,13 @@ def setupUi(self, MainWindow): self.graphLayout.setObjectName("graphLayout") self.horizontalLayout_2.addLayout(self.graphLayout) self.verticalLayout_2.addWidget(self.graphWidget) - self.widget = QtWidgets.QWidget(self.dataWidget) + self.widget = QtWidgets.QWidget(parent=self.dataWidget) self.widget.setObjectName("widget") self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.widget) self.horizontalLayout_4.setObjectName("horizontalLayout_4") - self.eventTableView = QtWidgets.QTableView(self.widget) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) + self.eventTableView = QtWidgets.QTableView(parent=self.widget) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Expanding) + sizePolicy.setHorizontalStretch(1) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.eventTableView.sizePolicy().hasHeightForWidth()) self.eventTableView.setSizePolicy(sizePolicy) @@ -164,7 +162,7 @@ def setupUi(self, MainWindow): self.verticalLayout_2.addWidget(self.widget) self.horizontalLayout_3.addWidget(self.dataWidget) MainWindow.setCentralWidget(self.mainWidget) - self.statusbar = QtWidgets.QStatusBar(MainWindow) + self.statusbar = QtWidgets.QStatusBar(parent=MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) diff --git a/mainwindow.ui b/mainwindow.ui index c159679..14f7561 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -19,7 +19,7 @@ - 0 + 1 0 @@ -44,7 +44,7 @@ - 0 + 1 0 @@ -109,7 +109,7 @@ - 0 + 1 0 @@ -286,8 +286,8 @@ - - 0 + + 1 0 From e7e1ad594311764ed033951c13cfa07a284ab3fb Mon Sep 17 00:00:00 2001 From: Jared Mauch Date: Fri, 6 Dec 2024 22:44:10 -0500 Subject: [PATCH 03/13] qt6 --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7068a03..6786974 100644 --- a/README.md +++ b/README.md @@ -4,5 +4,5 @@ OpenOTDR is an Open Source OTDR reporting tool. It takes raw OTDR traces as .SOR files, detects and classifies features on the trace, and generates reports. -You may need `pyqt5-dev-tools` package if you edit the ui file -then you will need to run `pyuic5 -x mainwindow.ui -o mainwindow.py` +You may need `pyqt6-dev-tools` package if you edit the ui file +then you will need to run `pyuic6 -x mainwindow.ui -o mainwindow.py` From 53999224e54a5cf7509085aa1dfc1ef6ad4c0184 Mon Sep 17 00:00:00 2001 From: Jared Mauch Date: Fri, 6 Dec 2024 22:47:46 -0500 Subject: [PATCH 04/13] cleanup --- OpenOTDR.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/OpenOTDR.py b/OpenOTDR.py index 3f30dab..2e125fe 100755 --- a/OpenOTDR.py +++ b/OpenOTDR.py @@ -257,7 +257,9 @@ def open_project(self): if self.busy.locked(): return with self.busy: - uri, _ = QtWidgets.QFileDialog.getOpenFileName(self, "Open project", "", "OpenOTDR Project Files(*.opro);;All Files (*)", options=QtWidgets.QFileDialog.DontUseNativeDialog) + dialog = QtWidgets.QFileDialog(self) + dialog.setOption(QFileDialog.Option.DontUseNativeDialog, True) + uri, _ = dialog.getOpenFileName(self, "Open project", "", "OpenOTDR Project Files(*.opro);;All Files (*)") if uri: with open(uri, "r") as file: content = json.load(file) @@ -278,7 +280,9 @@ def save_project(self): if self.busy.locked(): return with self.busy: - uri, _ = QtWidgets.QFileDialog.getSaveFileName(self, "Save project", "", "OpenOTDR Project Files(*.opro);;All Files (*)", options=QtWidgets.QFileDialog.DontUseNativeDialog) + dialog = QtWidgets.QFileDialog(self) + dialog.setOption(QFileDialog.Option.DontUseNativeDialog, True) + uri, _ = dialog.getSaveFileName(self, "Save project", "", "OpenOTDR Project Files(*.opro);;All Files (*)") if uri: _, extension = os.path.splitext(uri) if not extension: @@ -318,7 +322,7 @@ def add_trace(self): for index in range(self.project_model.rowCount()): raw_data = self.project_model.item(index).data self.raw_traces.append(raw_data) - self.recalculate_events() + self.recalculate_events() self._draw() def remove_trace(self): @@ -333,7 +337,7 @@ def remove_trace(self): self.project_model.removeRow(index.row()) del self.raw_traces[index.row()] self._draw() - + @staticmethod def _filter_events(raw_features): '''Filter the detected features of each trace to make a single set with no duplicates or ghosts''' From 78bcf32a4f0927f9a78ef1ddcb7521fddc992176 Mon Sep 17 00:00:00 2001 From: Jared Mauch Date: Fri, 6 Dec 2024 23:00:38 -0500 Subject: [PATCH 05/13] add cursor --- OpenOTDR.py | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/OpenOTDR.py b/OpenOTDR.py index 2e125fe..0e245e0 100755 --- a/OpenOTDR.py +++ b/OpenOTDR.py @@ -235,7 +235,6 @@ def _draw(self): d_final_data["trace"][0], label=wavelength, color=wavelength_to_rgb(wavelength)) - self.cursor = Cursor(plt, useblit=True, color='red', linewidth=2) if self.canvas: self.user_interface.graphLayout.removeWidget(self.canvas) self.canvas.close() @@ -247,6 +246,7 @@ def _draw(self): # fig.canvas.mpl_connect("motion_notify_event", self.hover) self.canvas = FigureCanvas(fig) self.toolbar = CustomNavigationToolbar(self.canvas, self, coordinates=True) + self.cursor = Cursor(plt, horizOn=True, vertOn=True, useblit=True, color='red', linewidth=2) self.user_interface.graphLayout.addWidget(self.canvas) self.user_interface.graphLayout.addWidget(self.toolbar) self.recalculate_events() @@ -322,7 +322,22 @@ def add_trace(self): for index in range(self.project_model.rowCount()): raw_data = self.project_model.item(index).data self.raw_traces.append(raw_data) - self.recalculate_events() +# recalculate_events inline + l_traces = [] + l_feature_points = [] + for index in range(self.project_model.rowCount()): + raw_data = self.project_model.item(index).data + d_data = prepare_data(raw_data, self.window_len) + l_traces.append(d_data) + l_feature_points.append(find_edges(differentiate_data(d_data))) + raw_features = l_feature_points + raw_traces = l_traces + print("recalculate_events: raw_features:", raw_features) + if not raw_features: + return + d_events = self._filter_events(raw_features) + self._update_events_table(d_events, raw_traces) + self._draw() def remove_trace(self): @@ -425,6 +440,7 @@ def recalculate_events(self): '''Recalculate the events''' print("starting recalculate_events()") if self.busy.locked(): + print("recalculate_events self.busy.locked()") return with self.busy: l_traces = [] From 934e21d2ae734bba1110177d898c49c51b17d30a Mon Sep 17 00:00:00 2001 From: Jared Mauch Date: Sat, 7 Dec 2024 00:21:07 -0500 Subject: [PATCH 06/13] update some more --- OpenOTDR.py | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/OpenOTDR.py b/OpenOTDR.py index 0e245e0..f2fb459 100755 --- a/OpenOTDR.py +++ b/OpenOTDR.py @@ -142,6 +142,10 @@ def __init__(self): self.events_proxy_model.sort(1, PyQt6.QtCore.Qt.SortOrder.AscendingOrder) # self.user_interface.eventTableView.setModel(self.events_proxy_model) + print("self.user_interface.eventTableView:", type(self.user_interface.eventTableView)) + print("self.user_interface.eventTableView.horizontalHeader():", type(self.user_interface.eventTableView.horizontalHeader())) + self.user_interface.eventTableView.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.ResizeMode.ResizeToContents) + # self.user_interface.openProject.clicked.connect(self.open_project) self.user_interface.saveProject.clicked.connect(self.save_project) @@ -189,7 +193,7 @@ def _load_file(self, url, _project=False): d_meta = _project["meta"] l_raw_trace = _project["raw_trace"] self.files[url] = {"meta": d_meta, "raw_trace": l_raw_trace} -# print("d_meta=", json.dumps(d_meta, sort_keys=True, indent=4)) + print("d_meta=", json.dumps(d_meta, sort_keys=True, indent=4)) # print("l_raw_trace=", json.dumps(l_raw_trace, sort_keys=True, indent=4)) a_trace = self.__preprocess_data(d_meta, l_raw_trace) d_data= prepare_data({"meta":d_meta, "trace":a_trace}, self.window_len) @@ -235,6 +239,8 @@ def _draw(self): d_final_data["trace"][0], label=wavelength, color=wavelength_to_rgb(wavelength)) + plt.set_xlim([0, None]) + if self.canvas: self.user_interface.graphLayout.removeWidget(self.canvas) self.canvas.close() @@ -403,7 +409,7 @@ def _update_events_table(self, d_events, raw_traces): self.events_model.setHorizontalHeaderLabels(['Event', 'Distance (km)', 'Loss (dB)', - 'Dispersion factor']) + 'Dispersion factor', 'Distance kft']) # # Qt.AlignRight @@ -411,28 +417,43 @@ def _update_events_table(self, d_events, raw_traces): for position, meta_data in d_events.items(): current_row = self.events_model.rowCount() self.events_model.insertRow(current_row) - event_position = QtGui.QStandardItem() - event_position.setText(str(position)) - event_position.setEditable(False) - self.events_model.setItem(current_row, 1, event_position) + event_position_km = QtGui.QStandardItem() + event_position_km.setText(str(position)) + event_position_km.setEditable(False) + self.events_model.setItem(current_row, 1, event_position_km) + + event_position_kft = QtGui.QStandardItem() + event_position_kft.setEditable(False) + event_position_kft.setText(str(position * 3280.8399)) + self.events_model.setItem(current_row, 4, event_position_kft) + loss, dispersion_factor = self.__calculate_loss_and_dispersion(raw_traces, meta_data) + event_loss = QtGui.QStandardItem() event_loss.setText(str(loss)) event_loss.setEditable(False) self.events_model.setItem(current_row, 2, event_loss) + event_dispersion = QtGui.QStandardItem() event_dispersion.setText(str(dispersion_factor)) event_dispersion.setEditable(False) self.events_model.setItem(current_row, 3, event_dispersion) + + # pull in event type from the trace ideally event_type = QtGui.QStandardItem() event_type.setEditable(True) +# event_type.setText("%s %s" % (str(position), str(meta_data))) self.events_model.setItem(current_row, 0, event_type) +# self.events_model.resizeColumnToContents(current_row) + self.events_model.sort(1) # self.eventTableView.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents) - print("events_model", dir(self.events_model)) - print("events_model.property", self.events_model.property) - print("events_proxy_model", dir(self.events_proxy_model)) - print("events_proxy_model", self.events_proxy_model.property) + self.user_interface.eventTableView.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.ResizeMode.ResizeToContents) + +# print("events_model", dir(self.events_model)) +# print("events_model.property", self.events_model.property) +# print("events_proxy_model", dir(self.events_proxy_model)) +# print("events_proxy_model", self.events_proxy_model.property) # self.events_proxy_model.resizeColumnsToContents() # self.user_interface.eventTableView.setModel.resizeColumnsToContents() From 0d32d74701ba2455d86eb983758b2819adf75968 Mon Sep 17 00:00:00 2001 From: Jared Mauch Date: Sat, 7 Dec 2024 19:51:08 -0500 Subject: [PATCH 07/13] update code --- OpenOTDR.py | 86 ++++++++++++++++++++++++++++++++++++--------------- mainwindow.py | 50 +++++++----------------------- mainwindow.ui | 2 +- 3 files changed, 73 insertions(+), 65 deletions(-) diff --git a/OpenOTDR.py b/OpenOTDR.py index f2fb459..6c755c4 100755 --- a/OpenOTDR.py +++ b/OpenOTDR.py @@ -50,13 +50,29 @@ def _low_pass_filter_trace(a_raw_trace, window_len): return a_trace -def prepare_data(d_data, window_len): +def prepare_data(self, d_data, window_len): '''Transforms the trace data to unify sample width and signal quality''' a_raw_trace = d_data["trace"] # Smoothing a_smooth_trace = _low_pass_filter_trace(a_raw_trace, window_len) # Scale to ensure resolution per distance unit is equal. a_trace = zoom(a_smooth_trace, zoom=(1.0, d_data["meta"]["FxdParams"]["resolution"]), order=1) +# for k in d_data["meta"]["FxdParams"]: +## QtGui.QStandardItemModel() +# print(k) +# current_row = self.user_interface.metaDataTable.rowCount() +# self.user_interface.metaDataTable.insertRow(current_row) +# value_text = QtGui.QStandardItem() +# value_text.setText(str(k)) +# value_text.setEditable(False) +# self.user_interface.metaDataTable.setItem(current_row, 0, value_text) +# +# value_text = QtGui.QStandardItem() +# value_text.setText(str(d_data["meta"]["FxdParams"].get(k, None))) +# value_text.setEditable(False) +# self.user_interface.metaDataTable.setItem(current_row, 1, value_text) + + # Offsetting to make all launch levels the same # print("a_trace[0] =", a_trace[0]) # print("len(a_trace[0]) =", len(a_trace[0])) @@ -142,10 +158,10 @@ def __init__(self): self.events_proxy_model.sort(1, PyQt6.QtCore.Qt.SortOrder.AscendingOrder) # self.user_interface.eventTableView.setModel(self.events_proxy_model) - print("self.user_interface.eventTableView:", type(self.user_interface.eventTableView)) - print("self.user_interface.eventTableView.horizontalHeader():", type(self.user_interface.eventTableView.horizontalHeader())) +# print("self.user_interface.eventTableView:", type(self.user_interface.eventTableView)) +# print("self.user_interface.eventTableView.horizontalHeader():", type(self.user_interface.eventTableView.horizontalHeader())) self.user_interface.eventTableView.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.ResizeMode.ResizeToContents) - + self.user_interface.metaDataTable = QtGui.QStandardItemModel() # self.user_interface.openProject.clicked.connect(self.open_project) self.user_interface.saveProject.clicked.connect(self.save_project) @@ -156,6 +172,7 @@ def __init__(self): self.user_interface.recalculateEvents.clicked.connect(self.recalculate_events) self.window_len = 0 self.canvas = None + self.plt = None self.cursor = None self.toolbar = None self.raw_features = [] @@ -196,7 +213,7 @@ def _load_file(self, url, _project=False): print("d_meta=", json.dumps(d_meta, sort_keys=True, indent=4)) # print("l_raw_trace=", json.dumps(l_raw_trace, sort_keys=True, indent=4)) a_trace = self.__preprocess_data(d_meta, l_raw_trace) - d_data= prepare_data({"meta":d_meta, "trace":a_trace}, self.window_len) + d_data= prepare_data(self, {"meta":d_meta, "trace":a_trace}, self.window_len) filename = os.path.basename(url) item = QtGui.QStandardItem(filename) item.data = d_data @@ -212,7 +229,8 @@ def hover(event, graph_info): print("graph_info.key:", graph_info.key) print("graph_info.x:", graph_info.x) print("graph_info.y:", graph_info.y) - print("graph_info.xdata:", graph_info.xdata) + print("graph_info.xdata(km):", graph_info.xdata) + print("grpah_info.xdata(feet):", graph_info.xdata * 3280.8399) print("graph_info.ydata:", graph_info.ydata) print("graph_info.name:", graph_info.name) @@ -227,19 +245,43 @@ def hover(event, graph_info): annot.set_visible(False) fig.canvas.draw_idle() + + def on_draw(self, event): + print("on_draw:", event) +# self.cursor = Cursor(self.plt, horizOn=True, vertOn=True, useblit=True, color='red', linewidth=2) + + def button_press(event, graph_info): +# print("button_press event:", dir(event)) +# button_press graph_info: ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_guiEvent', '_guiEvent_deleted', '_last_axes_ref', '_lastevent', '_process', '_set_inaxes', 'button', 'canvas', 'dblclick', 'guiEvent', 'inaxes', 'key', 'lastevent', 'modifiers', 'name', 'step', 'x', 'xdata', 'y', 'ydata'] + +# print("button_press graph_info:", dir(graph_info)) + print("graph_info.guiEvent:", graph_info.guiEvent) + print("graph_info.inaxes:", graph_info.inaxes) + print("graph_info.key:", graph_info.key) + print("graph_info.button:", graph_info.button) # (1 left, 2 middle, 3 right) + print("graph_info.dblclick:", graph_info.dblclick) # doubleclick? +# print("graph_info.x:", graph_info.x) +# print("graph_info.y:", graph_info.y) + print("graph_info.xdata(km):", graph_info.xdata) + print("grpah_info.xdata(feet):", graph_info.xdata * 3280.8399) + + print("graph_info.ydata:", graph_info.ydata) + print("graph_info.name:", graph_info.name) + + def _draw(self): '''(re)draw the plot with the latest data''' fig = Figure() - plt = fig.add_subplot(1, 1, 1) + self.plt = fig.add_subplot(1, 1, 1) if self.raw_traces: for d_final_data in self.raw_traces: wavelength = d_final_data["meta"]["GenParams"]["wavelength"] # print("wavelength=", wavelength) - plt.plot(d_final_data["trace"][1], + self.plt.plot(d_final_data["trace"][1], d_final_data["trace"][0], label=wavelength, color=wavelength_to_rgb(wavelength)) - plt.set_xlim([0, None]) + self.plt.set_xlim([0, None]) if self.canvas: self.user_interface.graphLayout.removeWidget(self.canvas) @@ -250,9 +292,13 @@ def _draw(self): fig.legend() # if i want to have my own hover function # fig.canvas.mpl_connect("motion_notify_event", self.hover) + fig.canvas.mpl_connect("button_press_event", self.button_press) +# fig.canvas.mpl_connect("scroll_event", self.zoom) + fig.canvas.mpl_connect('draw_event', self.on_draw) + self.canvas = FigureCanvas(fig) self.toolbar = CustomNavigationToolbar(self.canvas, self, coordinates=True) - self.cursor = Cursor(plt, horizOn=True, vertOn=True, useblit=True, color='red', linewidth=2) + self.cursor = Cursor(self.plt, horizOn=True, vertOn=True, useblit=True, color='red', linewidth=2) self.user_interface.graphLayout.addWidget(self.canvas) self.user_interface.graphLayout.addWidget(self.toolbar) self.recalculate_events() @@ -333,7 +379,7 @@ def add_trace(self): l_feature_points = [] for index in range(self.project_model.rowCount()): raw_data = self.project_model.item(index).data - d_data = prepare_data(raw_data, self.window_len) + d_data = prepare_data(self, raw_data, self.window_len) l_traces.append(d_data) l_feature_points.append(find_edges(differentiate_data(d_data))) raw_features = l_feature_points @@ -365,7 +411,7 @@ def _filter_events(raw_features): d_events = {} for trace_features in raw_features: for index, feature in enumerate(trace_features[2]): - feature_position = round_sig(feature, 1) + feature_position = round_sig(feature, 3) if feature_position not in d_events and feature_position-0.1 not in d_events and feature_position+0.1 not in d_events: d_events[feature_position] = { "indexes": [] @@ -407,11 +453,10 @@ def _update_events_table(self, d_events, raw_traces): print("_update_events_table") self.events_model.clear() self.events_model.setHorizontalHeaderLabels(['Event', - 'Distance (km)', + 'Dist (km)', 'Loss (dB)', - 'Dispersion factor', 'Distance kft']) + 'Dispersion factor', 'Dist ft']) # -# Qt.AlignRight # for position, meta_data in d_events.items(): @@ -442,20 +487,11 @@ def _update_events_table(self, d_events, raw_traces): # pull in event type from the trace ideally event_type = QtGui.QStandardItem() event_type.setEditable(True) -# event_type.setText("%s %s" % (str(position), str(meta_data))) self.events_model.setItem(current_row, 0, event_type) -# self.events_model.resizeColumnToContents(current_row) self.events_model.sort(1) -# self.eventTableView.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents) self.user_interface.eventTableView.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.ResizeMode.ResizeToContents) -# print("events_model", dir(self.events_model)) -# print("events_model.property", self.events_model.property) -# print("events_proxy_model", dir(self.events_proxy_model)) -# print("events_proxy_model", self.events_proxy_model.property) -# self.events_proxy_model.resizeColumnsToContents() -# self.user_interface.eventTableView.setModel.resizeColumnsToContents() def recalculate_events(self): '''Recalculate the events''' @@ -468,7 +504,7 @@ def recalculate_events(self): l_feature_points = [] for index in range(self.project_model.rowCount()): raw_data = self.project_model.item(index).data - d_data = prepare_data(raw_data, self.window_len) + d_data = prepare_data(self, raw_data, self.window_len) l_traces.append(d_data) l_feature_points.append(find_edges(differentiate_data(d_data))) raw_features = l_feature_points diff --git a/mainwindow.py b/mainwindow.py index fc69fd1..2908353 100644 --- a/mainwindow.py +++ b/mainwindow.py @@ -96,28 +96,8 @@ def setupUi(self, MainWindow): self.metaDataWidget.setObjectName("metaDataWidget") self.verticalLayout = QtWidgets.QVBoxLayout(self.metaDataWidget) self.verticalLayout.setObjectName("verticalLayout") - self.metaDataTable = QtWidgets.QTableWidget(parent=self.metaDataWidget) + self.metaDataTable = QtWidgets.QTableView(parent=self.metaDataWidget) self.metaDataTable.setObjectName("metaDataTable") - self.metaDataTable.setColumnCount(0) - self.metaDataTable.setRowCount(9) - item = QtWidgets.QTableWidgetItem() - self.metaDataTable.setVerticalHeaderItem(0, item) - item = QtWidgets.QTableWidgetItem() - self.metaDataTable.setVerticalHeaderItem(1, item) - item = QtWidgets.QTableWidgetItem() - self.metaDataTable.setVerticalHeaderItem(2, item) - item = QtWidgets.QTableWidgetItem() - self.metaDataTable.setVerticalHeaderItem(3, item) - item = QtWidgets.QTableWidgetItem() - self.metaDataTable.setVerticalHeaderItem(4, item) - item = QtWidgets.QTableWidgetItem() - self.metaDataTable.setVerticalHeaderItem(5, item) - item = QtWidgets.QTableWidgetItem() - self.metaDataTable.setVerticalHeaderItem(6, item) - item = QtWidgets.QTableWidgetItem() - self.metaDataTable.setVerticalHeaderItem(7, item) - item = QtWidgets.QTableWidgetItem() - self.metaDataTable.setVerticalHeaderItem(8, item) self.verticalLayout.addWidget(self.metaDataTable) self.tabWidget.addTab(self.metaDataWidget, "") self.horizontalLayout_3.addWidget(self.tabWidget) @@ -186,22 +166,14 @@ def retranslateUi(self, MainWindow): self.printReport.setToolTip(_translate("MainWindow", "Print")) self.printReport.setText(_translate("MainWindow", "print")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.projectWidget), _translate("MainWindow", "Project")) - item = self.metaDataTable.verticalHeaderItem(0) - item.setText(_translate("MainWindow", "Project name")) - item = self.metaDataTable.verticalHeaderItem(1) - item.setText(_translate("MainWindow", "Location A")) - item = self.metaDataTable.verticalHeaderItem(2) - item.setText(_translate("MainWindow", "Location B")) - item = self.metaDataTable.verticalHeaderItem(3) - item.setText(_translate("MainWindow", "Total distance (km)")) - item = self.metaDataTable.verticalHeaderItem(4) - item.setText(_translate("MainWindow", "Total distance")) - item = self.metaDataTable.verticalHeaderItem(5) - item.setText(_translate("MainWindow", "Launch length (km)")) - item = self.metaDataTable.verticalHeaderItem(6) - item.setText(_translate("MainWindow", "Recieve length (km)")) - item = self.metaDataTable.verticalHeaderItem(7) - item.setText(_translate("MainWindow", "Average loss (dB/km)")) - item = self.metaDataTable.verticalHeaderItem(8) - item.setText(_translate("MainWindow", "Total loss(dB)")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.metaDataWidget), _translate("MainWindow", "Meta Data")) + + +if __name__ == "__main__": + import sys + app = QtWidgets.QApplication(sys.argv) + MainWindow = QtWidgets.QMainWindow() + ui = Ui_MainWindow() + ui.setupUi(MainWindow) + MainWindow.show() + sys.exit(app.exec()) diff --git a/mainwindow.ui b/mainwindow.ui index 14f7561..fee7561 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -192,7 +192,7 @@ - + Project name From e9109f817a0bf0e8f5a036dbbb694732efc0059b Mon Sep 17 00:00:00 2001 From: Jared Mauch Date: Sun, 8 Dec 2024 17:24:18 -0500 Subject: [PATCH 08/13] use builtin toolbar --- OpenOTDR.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OpenOTDR.py b/OpenOTDR.py index 6c755c4..5ea4192 100755 --- a/OpenOTDR.py +++ b/OpenOTDR.py @@ -297,7 +297,8 @@ def _draw(self): fig.canvas.mpl_connect('draw_event', self.on_draw) self.canvas = FigureCanvas(fig) - self.toolbar = CustomNavigationToolbar(self.canvas, self, coordinates=True) +# self.toolbar = CustomNavigationToolbar(self.canvas, self, coordinates=True) + self.toolbar = NavigationToolbar(self.canvas, self, coordinates=True) self.cursor = Cursor(self.plt, horizOn=True, vertOn=True, useblit=True, color='red', linewidth=2) self.user_interface.graphLayout.addWidget(self.canvas) self.user_interface.graphLayout.addWidget(self.toolbar) From 7342e65271f251fd5f2efdd876f22f4162d689f2 Mon Sep 17 00:00:00 2001 From: Jared Mauch Date: Sun, 8 Dec 2024 17:36:49 -0500 Subject: [PATCH 09/13] update code --- mainwindow.py | 8 ++++---- mainwindow.ui | 50 ++------------------------------------------------ 2 files changed, 6 insertions(+), 52 deletions(-) diff --git a/mainwindow.py b/mainwindow.py index 2908353..879f3ab 100644 --- a/mainwindow.py +++ b/mainwindow.py @@ -12,7 +12,7 @@ class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") - MainWindow.resize(1280, 761) + MainWindow.resize(1280, 760) self.mainWidget = QtWidgets.QWidget(parent=MainWindow) self.mainWidget.setObjectName("mainWidget") self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.mainWidget) @@ -96,9 +96,9 @@ def setupUi(self, MainWindow): self.metaDataWidget.setObjectName("metaDataWidget") self.verticalLayout = QtWidgets.QVBoxLayout(self.metaDataWidget) self.verticalLayout.setObjectName("verticalLayout") - self.metaDataTable = QtWidgets.QTableView(parent=self.metaDataWidget) - self.metaDataTable.setObjectName("metaDataTable") - self.verticalLayout.addWidget(self.metaDataTable) + self.metaTableView = QtWidgets.QTableView(parent=self.metaDataWidget) + self.metaTableView.setObjectName("metaTableView") + self.verticalLayout.addWidget(self.metaTableView) self.tabWidget.addTab(self.metaDataWidget, "") self.horizontalLayout_3.addWidget(self.tabWidget) self.dataWidget = QtWidgets.QWidget(parent=self.mainWidget) diff --git a/mainwindow.ui b/mainwindow.ui index fee7561..9df89fc 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -7,7 +7,7 @@ 0 0 1280 - 761 + 760 @@ -192,53 +192,7 @@ - - - - Project name - - - - - Location A - - - - - Location B - - - - - Total distance (km) - - - - - Total distance - - - - - Launch length (km) - - - - - Recieve length (km) - - - - - Average loss (dB/km) - - - - - Total loss(dB) - - - + From 8e34a41cafec6ed58b49f2a6162130929a4d25c0 Mon Sep 17 00:00:00 2001 From: Jared Mauch Date: Mon, 9 Dec 2024 09:52:14 -0500 Subject: [PATCH 10/13] display metadata from sor file in metadata tab --- OpenOTDR.py | 43 ++++++++++++++++++++++++++----------------- mainwindow.py | 7 +++++++ mainwindow.ui | 18 +++++++++++++++++- 3 files changed, 50 insertions(+), 18 deletions(-) diff --git a/OpenOTDR.py b/OpenOTDR.py index 5ea4192..2e43c97 100755 --- a/OpenOTDR.py +++ b/OpenOTDR.py @@ -57,20 +57,24 @@ def prepare_data(self, d_data, window_len): a_smooth_trace = _low_pass_filter_trace(a_raw_trace, window_len) # Scale to ensure resolution per distance unit is equal. a_trace = zoom(a_smooth_trace, zoom=(1.0, d_data["meta"]["FxdParams"]["resolution"]), order=1) -# for k in d_data["meta"]["FxdParams"]: -## QtGui.QStandardItemModel() -# print(k) -# current_row = self.user_interface.metaDataTable.rowCount() -# self.user_interface.metaDataTable.insertRow(current_row) -# value_text = QtGui.QStandardItem() -# value_text.setText(str(k)) -# value_text.setEditable(False) -# self.user_interface.metaDataTable.setItem(current_row, 0, value_text) + self.meta_model.clear() + self.meta_model.setHorizontalHeaderLabels(['Name', 'Value']) + + for k in d_data["meta"]["FxdParams"]: +# print(dir(self.user_interface.metaTableView)) + current_row = self.meta_model.rowCount() + self.meta_model.insertRow(current_row) + value_text = QtGui.QStandardItem() + value_text.setText(str(k)) + value_text.setEditable(False) + self.meta_model.setItem(current_row, 0, value_text) # -# value_text = QtGui.QStandardItem() -# value_text.setText(str(d_data["meta"]["FxdParams"].get(k, None))) -# value_text.setEditable(False) -# self.user_interface.metaDataTable.setItem(current_row, 1, value_text) + value_text = QtGui.QStandardItem() + value_text.setText(str(d_data["meta"]["FxdParams"].get(k, None))) + value_text.setEditable(False) + self.meta_model.setItem(current_row, 1, value_text) + +# self.user_interface.metaTableView.horizontalHeaderItem().setSectionResizeMode(QtWidgets.QHeaderView.ResizeMode.ResizeToContents) # Offsetting to make all launch levels the same @@ -156,12 +160,17 @@ def __init__(self): self.events_proxy_model = NaturalSortFilterProxyModel() self.events_proxy_model.setSourceModel(self.events_model) self.events_proxy_model.sort(1, PyQt6.QtCore.Qt.SortOrder.AscendingOrder) - # self.user_interface.eventTableView.setModel(self.events_proxy_model) -# print("self.user_interface.eventTableView:", type(self.user_interface.eventTableView)) -# print("self.user_interface.eventTableView.horizontalHeader():", type(self.user_interface.eventTableView.horizontalHeader())) self.user_interface.eventTableView.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.ResizeMode.ResizeToContents) - self.user_interface.metaDataTable = QtGui.QStandardItemModel() +# + # meta processing model + self.meta_model = QtGui.QStandardItemModel() +# + self.meta_proxy_model = NaturalSortFilterProxyModel() + self.meta_proxy_model.setSourceModel(self.meta_model) +# self.meta_proxy_model.sort(1, PyQt6.QtCore.Qt.SortOrder.AscendingOrder) + self.user_interface.metaTableView.setModel(self.meta_proxy_model) + self.user_interface.metaTableView.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.ResizeMode.ResizeToContents) # self.user_interface.openProject.clicked.connect(self.open_project) self.user_interface.saveProject.clicked.connect(self.save_project) diff --git a/mainwindow.py b/mainwindow.py index 879f3ab..c375325 100644 --- a/mainwindow.py +++ b/mainwindow.py @@ -97,6 +97,13 @@ def setupUi(self, MainWindow): self.verticalLayout = QtWidgets.QVBoxLayout(self.metaDataWidget) self.verticalLayout.setObjectName("verticalLayout") self.metaTableView = QtWidgets.QTableView(parent=self.metaDataWidget) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Expanding) + sizePolicy.setHorizontalStretch(1) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.metaTableView.sizePolicy().hasHeightForWidth()) + self.metaTableView.setSizePolicy(sizePolicy) + self.metaTableView.setMinimumSize(QtCore.QSize(300, 200)) + self.metaTableView.setSortingEnabled(True) self.metaTableView.setObjectName("metaTableView") self.verticalLayout.addWidget(self.metaTableView) self.tabWidget.addTab(self.metaDataWidget, "") diff --git a/mainwindow.ui b/mainwindow.ui index 9df89fc..d7947bd 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -192,7 +192,23 @@ - + + + + 1 + 0 + + + + + 300 + 200 + + + + true + + From 6ff4e674113f5172edb13df90d5fb9138e42223d Mon Sep 17 00:00:00 2001 From: Jared Mauch Date: Mon, 9 Dec 2024 17:23:42 -0500 Subject: [PATCH 11/13] use OTDR trace events by default --- OpenOTDR.py | 121 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 96 insertions(+), 25 deletions(-) diff --git a/OpenOTDR.py b/OpenOTDR.py index 2e43c97..f0b4927 100755 --- a/OpenOTDR.py +++ b/OpenOTDR.py @@ -60,7 +60,22 @@ def prepare_data(self, d_data, window_len): self.meta_model.clear() self.meta_model.setHorizontalHeaderLabels(['Name', 'Value']) - for k in d_data["meta"]["FxdParams"]: + # GenParams + for k in d_data["meta"]["GenParams"]: +# print(dir(self.user_interface.metaTableView)) + current_row = self.meta_model.rowCount() + self.meta_model.insertRow(current_row) + value_text = QtGui.QStandardItem() + value_text.setText(str(k)) + value_text.setEditable(False) + self.meta_model.setItem(current_row, 0, value_text) +# + value_text = QtGui.QStandardItem() + value_text.setText(str(d_data["meta"]["GenParams"].get(k, None))) + value_text.setEditable(False) + self.meta_model.setItem(current_row, 1, value_text) + + for k in d_data["meta"]["FxdParams"]: # print(dir(self.user_interface.metaTableView)) current_row = self.meta_model.rowCount() self.meta_model.insertRow(current_row) @@ -74,6 +89,7 @@ def prepare_data(self, d_data, window_len): value_text.setEditable(False) self.meta_model.setItem(current_row, 1, value_text) + # self.user_interface.metaTableView.horizontalHeaderItem().setSectionResizeMode(QtWidgets.QHeaderView.ResizeMode.ResizeToContents) @@ -181,6 +197,7 @@ def __init__(self): self.user_interface.recalculateEvents.clicked.connect(self.recalculate_events) self.window_len = 0 self.canvas = None + self.d_meta = None self.plt = None self.cursor = None self.toolbar = None @@ -218,6 +235,7 @@ def _load_file(self, url, _project=False): else: d_meta = _project["meta"] l_raw_trace = _project["raw_trace"] + self.d_meta = d_meta self.files[url] = {"meta": d_meta, "raw_trace": l_raw_trace} print("d_meta=", json.dumps(d_meta, sort_keys=True, indent=4)) # print("l_raw_trace=", json.dumps(l_raw_trace, sort_keys=True, indent=4)) @@ -462,43 +480,96 @@ def _update_events_table(self, d_events, raw_traces): '''Update the events table in the UI''' print("_update_events_table") self.events_model.clear() - self.events_model.setHorizontalHeaderLabels(['Event', - 'Dist (km)', - 'Loss (dB)', - 'Dispersion factor', 'Dist ft']) -# - - # - for position, meta_data in d_events.items(): + key_events = self.d_meta.get('KeyEvents', None) +# print("update_events_table: key_events:", key_events) + num_events = 0 + if key_events is not None: + num_events = int(key_events.get('num events', 0)) + print("num_events:", num_events) + self.events_model.setHorizontalHeaderLabels(['comment', 'dist(km)', 'dist(ft)', 'peak', 'refl loss', 'slope', 'splice_loss', 'type']) + + for e_num in range (1, num_events + 1): + event = key_events.get("event %d" % e_num) current_row = self.events_model.rowCount() self.events_model.insertRow(current_row) + + event_comment = QtGui.QStandardItem() + event_comment.setText(str(event.get('comments'))) + event_comment.setEditable(False) + self.events_model.setItem(current_row, 0, event_comment) + event_position_km = QtGui.QStandardItem() - event_position_km.setText(str(position)) + event_position_km.setText(str(event.get('distance', 0))) event_position_km.setEditable(False) self.events_model.setItem(current_row, 1, event_position_km) - event_position_kft = QtGui.QStandardItem() - event_position_kft.setEditable(False) - event_position_kft.setText(str(position * 3280.8399)) - self.events_model.setItem(current_row, 4, event_position_kft) + event_position_ft = QtGui.QStandardItem() + event_position_ft.setEditable(False) + event_position_ft.setText(str(float(event.get('distance', 0)) * 3280.8399)) + self.events_model.setItem(current_row, 2, event_position_ft) - loss, dispersion_factor = self.__calculate_loss_and_dispersion(raw_traces, meta_data) + event_peak = QtGui.QStandardItem() + event_peak.setText(str(event.get('peak'))) + event_peak.setEditable(False) + self.events_model.setItem(current_row, 3, event_peak) event_loss = QtGui.QStandardItem() - event_loss.setText(str(loss)) + event_loss.setText(str(event.get('refl loss'))) event_loss.setEditable(False) - self.events_model.setItem(current_row, 2, event_loss) + self.events_model.setItem(current_row, 4, event_loss) - event_dispersion = QtGui.QStandardItem() - event_dispersion.setText(str(dispersion_factor)) - event_dispersion.setEditable(False) - self.events_model.setItem(current_row, 3, event_dispersion) + event_slope = QtGui.QStandardItem() + event_slope.setText(str(event.get('slope'))) + event_slope.setEditable(False) + self.events_model.setItem(current_row, 5, event_slope) - # pull in event type from the trace ideally - event_type = QtGui.QStandardItem() - event_type.setEditable(True) - self.events_model.setItem(current_row, 0, event_type) + event_splice_loss = QtGui.QStandardItem() + event_splice_loss.setText(str(event.get('splice loss'))) + event_splice_loss.setEditable(False) + self.events_model.setItem(current_row, 6, event_splice_loss) + event_type = QtGui.QStandardItem() + event_type.setText(str(event.get('type'))) + event_type.setEditable(False) + self.events_model.setItem(current_row, 7, event_type) + +## self.events_model.setHorizontalHeaderLabels(['Event', +## 'Dist (km)', +## 'Loss (dB)', +## 'Dispersion factor', 'Dist ft']) +### +## +## # +## for position, meta_data in d_events.items(): +## current_row = self.events_model.rowCount() +## self.events_model.insertRow(current_row) +## event_position_km = QtGui.QStandardItem() +## event_position_km.setText(str(position)) +## event_position_km.setEditable(False) +## self.events_model.setItem(current_row, 1, event_position_km) +## +## event_position_ft = QtGui.QStandardItem() +## event_position_ft.setEditable(False) +## event_position_ft.setText(str(position * 3280.8399)) +## self.events_model.setItem(current_row, 4, event_position_ft) +## +## loss, dispersion_factor = self.__calculate_loss_and_dispersion(raw_traces, meta_data) +## +## event_loss = QtGui.QStandardItem() +## event_loss.setText(str(loss)) +## event_loss.setEditable(False) +## self.events_model.setItem(current_row, 2, event_loss) +## +## event_dispersion = QtGui.QStandardItem() +## event_dispersion.setText(str(dispersion_factor)) +## event_dispersion.setEditable(False) +## self.events_model.setItem(current_row, 3, event_dispersion) +## +## # pull in event type from the trace ideally +## event_type = QtGui.QStandardItem() +## event_type.setEditable(True) +## self.events_model.setItem(current_row, 0, event_type) +## self.events_model.sort(1) self.user_interface.eventTableView.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.ResizeMode.ResizeToContents) From c1511161b0875760de05071c5a8381bcee503d18 Mon Sep 17 00:00:00 2001 From: Jared Mauch Date: Tue, 10 Dec 2024 00:57:22 -0500 Subject: [PATCH 12/13] update --- OpenOTDR.py | 161 ++++++++++++++++++++++------------------------- requirements.txt | 11 ++-- 2 files changed, 80 insertions(+), 92 deletions(-) diff --git a/OpenOTDR.py b/OpenOTDR.py index f0b4927..596e8a1 100755 --- a/OpenOTDR.py +++ b/OpenOTDR.py @@ -16,7 +16,8 @@ import numpy as np from scipy.ndimage import zoom from scipy.signal import find_peaks -from pyotdr import sorparse +#from pyotdr import sorparse +import otdrparser from matplotlib.figure import Figure from matplotlib import cm from matplotlib import colors @@ -50,64 +51,50 @@ def _low_pass_filter_trace(a_raw_trace, window_len): return a_trace -def prepare_data(self, d_data, window_len): +def prepare_data(self, window_len): '''Transforms the trace data to unify sample width and signal quality''' - a_raw_trace = d_data["trace"] + #a_raw_trace = d_data["trace"] # Smoothing - a_smooth_trace = _low_pass_filter_trace(a_raw_trace, window_len) + #a_smooth_trace = _low_pass_filter_trace(a_raw_trace, window_len) # Scale to ensure resolution per distance unit is equal. - a_trace = zoom(a_smooth_trace, zoom=(1.0, d_data["meta"]["FxdParams"]["resolution"]), order=1) + #a_trace = zoom(a_smooth_trace, zoom=(1.0, d_data["meta"]["FxdParams"]["resolution"]), order=1) self.meta_model.clear() self.meta_model.setHorizontalHeaderLabels(['Name', 'Value']) - # GenParams - for k in d_data["meta"]["GenParams"]: -# print(dir(self.user_interface.metaTableView)) - current_row = self.meta_model.rowCount() - self.meta_model.insertRow(current_row) - value_text = QtGui.QStandardItem() - value_text.setText(str(k)) - value_text.setEditable(False) - self.meta_model.setItem(current_row, 0, value_text) + raw_data = {} + raw_data[0] = [] + raw_data[1] = [] + for kind in self.d_meta: + if kind.get('name', None) == 'DataPts': + data_pts = kind.get('data_points', None) + for dp in data_pts: + raw_data[0].append(dp[0]) + raw_data[1].append(dp[1]) + + if kind.get('name', None) in ('GenParams', 'SupParams', 'FxdParams'): +# print(kind) + for k in kind: +# print("k=", k) + if k == 'name': + continue + current_row = self.meta_model.rowCount() + self.meta_model.insertRow(current_row) + value_text = QtGui.QStandardItem() + value_text.setText(str(k)) + value_text.setEditable(False) + self.meta_model.setItem(current_row, 0, value_text) # - value_text = QtGui.QStandardItem() - value_text.setText(str(d_data["meta"]["GenParams"].get(k, None))) - value_text.setEditable(False) - self.meta_model.setItem(current_row, 1, value_text) - - for k in d_data["meta"]["FxdParams"]: -# print(dir(self.user_interface.metaTableView)) - current_row = self.meta_model.rowCount() - self.meta_model.insertRow(current_row) - value_text = QtGui.QStandardItem() - value_text.setText(str(k)) - value_text.setEditable(False) - self.meta_model.setItem(current_row, 0, value_text) -# - value_text = QtGui.QStandardItem() - value_text.setText(str(d_data["meta"]["FxdParams"].get(k, None))) - value_text.setEditable(False) - self.meta_model.setItem(current_row, 1, value_text) - - -# self.user_interface.metaTableView.horizontalHeaderItem().setSectionResizeMode(QtWidgets.QHeaderView.ResizeMode.ResizeToContents) - + value_text = QtGui.QStandardItem() + value_text.setText(str(kind.get(k, None))) + value_text.setEditable(False) + self.meta_model.setItem(current_row, 1, value_text) - # Offsetting to make all launch levels the same -# print("a_trace[0] =", a_trace[0]) -# print("len(a_trace[0]) =", len(a_trace[0])) - try: - n_offset = -a_trace[0][325] - except: - n_offset = 0.0 -# print("n_offset=", n_offset) - a_trace[0] = a_trace[0] + n_offset - return {"meta": d_data["meta"], "trace": a_trace} + return raw_data def differentiate_data(d_data): '''Calculates the 1st order differential of the data''' - a_raw_trace = d_data["trace"] + a_raw_trace = d_data a_diff_trace = np.diff(a_raw_trace[0]) a_clean_trace = [] for sample_index in range(len(a_raw_trace[0])): @@ -175,7 +162,7 @@ def __init__(self): # self.events_proxy_model = NaturalSortFilterProxyModel() self.events_proxy_model.setSourceModel(self.events_model) - self.events_proxy_model.sort(1, PyQt6.QtCore.Qt.SortOrder.AscendingOrder) +# self.events_proxy_model.sort(1, PyQt6.QtCore.Qt.SortOrder.AscendingOrder) self.user_interface.eventTableView.setModel(self.events_proxy_model) self.user_interface.eventTableView.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.ResizeMode.ResizeToContents) # @@ -229,18 +216,18 @@ def __preprocess_data(self, d_meta, l_raw_trace): def _load_file(self, url, _project=False): '''Load the raw SOR file from provided url into the internal data format''' - if not _project: - _, d_meta, l_raw_trace = sorparse(url) - d_meta["url"] = url - else: - d_meta = _project["meta"] - l_raw_trace = _project["raw_trace"] - self.d_meta = d_meta - self.files[url] = {"meta": d_meta, "raw_trace": l_raw_trace} - print("d_meta=", json.dumps(d_meta, sort_keys=True, indent=4)) + with open(url, 'rb') as fp: + d_meta = otdrparser.parse(fp) + self.d_meta = d_meta + data_pts = None + for row in d_meta: + if row.get('name', None) == "DataPts": + data_pts = row + self.files[url] = {"meta": d_meta, "raw_trace": data_pts} +# print("d_meta=", json.dumps(d_meta, sort_keys=True, indent=4)) # print("l_raw_trace=", json.dumps(l_raw_trace, sort_keys=True, indent=4)) - a_trace = self.__preprocess_data(d_meta, l_raw_trace) - d_data= prepare_data(self, {"meta":d_meta, "trace":a_trace}, self.window_len) +# a_trace = self.__preprocess_data(d_meta, l_raw_trace) + d_data= prepare_data(self, self.window_len) filename = os.path.basename(url) item = QtGui.QStandardItem(filename) item.data = d_data @@ -301,14 +288,16 @@ def _draw(self): fig = Figure() self.plt = fig.add_subplot(1, 1, 1) if self.raw_traces: +# print("self.raw_traces:", self.raw_traces) for d_final_data in self.raw_traces: - wavelength = d_final_data["meta"]["GenParams"]["wavelength"] + wavelength = 1310 + print("d_final_data", d_final_data) # print("wavelength=", wavelength) - self.plt.plot(d_final_data["trace"][1], - d_final_data["trace"][0], + self.plt.plot(d_final_data[0], + d_final_data[1], label=wavelength, - color=wavelength_to_rgb(wavelength)) - self.plt.set_xlim([0, None]) + color=wavelength_to_rgb(str(wavelength))) +# self.plt.set_xlim([0, None]) if self.canvas: self.user_interface.graphLayout.removeWidget(self.canvas) @@ -399,25 +388,21 @@ def add_trace(self): return for filename in files: self._load_file(filename) - for index in range(self.project_model.rowCount()): - raw_data = self.project_model.item(index).data - self.raw_traces.append(raw_data) -# recalculate_events inline l_traces = [] l_feature_points = [] for index in range(self.project_model.rowCount()): raw_data = self.project_model.item(index).data - d_data = prepare_data(self, raw_data, self.window_len) + self.raw_traces.append(raw_data) + d_data = prepare_data(self, self.window_len) l_traces.append(d_data) l_feature_points.append(find_edges(differentiate_data(d_data))) raw_features = l_feature_points raw_traces = l_traces - print("recalculate_events: raw_features:", raw_features) - if not raw_features: - return +# print("add_trace: raw_features:", raw_features) +# if not raw_features: +# return d_events = self._filter_events(raw_features) self._update_events_table(d_events, raw_traces) - self._draw() def remove_trace(self): @@ -480,41 +465,43 @@ def _update_events_table(self, d_events, raw_traces): '''Update the events table in the UI''' print("_update_events_table") self.events_model.clear() - key_events = self.d_meta.get('KeyEvents', None) + key_events = None + for row in self.d_meta: + if row.get('name', None) == 'KeyEvents': + key_events = row # print("update_events_table: key_events:", key_events) num_events = 0 if key_events is not None: - num_events = int(key_events.get('num events', 0)) - print("num_events:", num_events) + number_of_events = int(key_events.get('number_of_events', 0)) + print("number_of_events:", number_of_events) self.events_model.setHorizontalHeaderLabels(['comment', 'dist(km)', 'dist(ft)', 'peak', 'refl loss', 'slope', 'splice_loss', 'type']) - for e_num in range (1, num_events + 1): - event = key_events.get("event %d" % e_num) + for event in key_events.get('events', []): current_row = self.events_model.rowCount() self.events_model.insertRow(current_row) event_comment = QtGui.QStandardItem() - event_comment.setText(str(event.get('comments'))) + event_comment.setText(str(event.get('comment'))) event_comment.setEditable(False) self.events_model.setItem(current_row, 0, event_comment) event_position_km = QtGui.QStandardItem() - event_position_km.setText(str(event.get('distance', 0))) + event_position_km.setText(str(event.get('distance_of_travel', 0))) event_position_km.setEditable(False) self.events_model.setItem(current_row, 1, event_position_km) event_position_ft = QtGui.QStandardItem() event_position_ft.setEditable(False) - event_position_ft.setText(str(float(event.get('distance', 0)) * 3280.8399)) + event_position_ft.setText(str(float(event.get('distance_of_travel', 0)) * 3280.8399)) self.events_model.setItem(current_row, 2, event_position_ft) event_peak = QtGui.QStandardItem() - event_peak.setText(str(event.get('peak'))) + event_peak.setText(str(event.get('peak_point'))) event_peak.setEditable(False) self.events_model.setItem(current_row, 3, event_peak) event_loss = QtGui.QStandardItem() - event_loss.setText(str(event.get('refl loss'))) + event_loss.setText(str(event.get('reflection_loss'))) event_loss.setEditable(False) self.events_model.setItem(current_row, 4, event_loss) @@ -524,12 +511,12 @@ def _update_events_table(self, d_events, raw_traces): self.events_model.setItem(current_row, 5, event_slope) event_splice_loss = QtGui.QStandardItem() - event_splice_loss.setText(str(event.get('splice loss'))) + event_splice_loss.setText(str(event.get('splice_loss'))) event_splice_loss.setEditable(False) self.events_model.setItem(current_row, 6, event_splice_loss) event_type = QtGui.QStandardItem() - event_type.setText(str(event.get('type'))) + event_type.setText(str(event.get('event_type_details')['event'])) event_type.setEditable(False) self.events_model.setItem(current_row, 7, event_type) @@ -585,7 +572,7 @@ def recalculate_events(self): l_feature_points = [] for index in range(self.project_model.rowCount()): raw_data = self.project_model.item(index).data - d_data = prepare_data(self, raw_data, self.window_len) + d_data = prepare_data(self, self.window_len) l_traces.append(d_data) l_feature_points.append(find_edges(differentiate_data(d_data))) raw_features = l_feature_points @@ -594,7 +581,7 @@ def recalculate_events(self): if not raw_features: return d_events = self._filter_events(raw_features) - self._update_events_table(d_events, raw_traces) + self._update_events_table(d_events, d_data) APP = QtWidgets.QApplication(sys.argv) diff --git a/requirements.txt b/requirements.txt index 3042185..156a511 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,6 @@ -scipy==1.10.1 -matplotlib==3.6.3 -pyotdr==1.0.0 -numpy==1.24.2 -PyQt5==* +scipy +matplotlib +#pyotdr==1.0.0 +otdrparser +numpy +PyQt6 From b3f4cfa07e063c7ccebbdc1615416be6b083231a Mon Sep 17 00:00:00 2001 From: Jared Mauch Date: Tue, 10 Dec 2024 10:02:50 -0500 Subject: [PATCH 13/13] handle errors --- OpenOTDR.py | 88 ++++++++++++++++++++++++++--------------------------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/OpenOTDR.py b/OpenOTDR.py index 596e8a1..0c7b9b4 100755 --- a/OpenOTDR.py +++ b/OpenOTDR.py @@ -471,54 +471,54 @@ def _update_events_table(self, d_events, raw_traces): key_events = row # print("update_events_table: key_events:", key_events) num_events = 0 + self.events_model.setHorizontalHeaderLabels(['comment', 'dist(km)', 'dist(ft)', 'peak', 'refl loss', 'slope', 'splice_loss', 'type']) if key_events is not None: number_of_events = int(key_events.get('number_of_events', 0)) print("number_of_events:", number_of_events) - self.events_model.setHorizontalHeaderLabels(['comment', 'dist(km)', 'dist(ft)', 'peak', 'refl loss', 'slope', 'splice_loss', 'type']) - for event in key_events.get('events', []): - current_row = self.events_model.rowCount() - self.events_model.insertRow(current_row) - - event_comment = QtGui.QStandardItem() - event_comment.setText(str(event.get('comment'))) - event_comment.setEditable(False) - self.events_model.setItem(current_row, 0, event_comment) - - event_position_km = QtGui.QStandardItem() - event_position_km.setText(str(event.get('distance_of_travel', 0))) - event_position_km.setEditable(False) - self.events_model.setItem(current_row, 1, event_position_km) - - event_position_ft = QtGui.QStandardItem() - event_position_ft.setEditable(False) - event_position_ft.setText(str(float(event.get('distance_of_travel', 0)) * 3280.8399)) - self.events_model.setItem(current_row, 2, event_position_ft) - - event_peak = QtGui.QStandardItem() - event_peak.setText(str(event.get('peak_point'))) - event_peak.setEditable(False) - self.events_model.setItem(current_row, 3, event_peak) - - event_loss = QtGui.QStandardItem() - event_loss.setText(str(event.get('reflection_loss'))) - event_loss.setEditable(False) - self.events_model.setItem(current_row, 4, event_loss) - - event_slope = QtGui.QStandardItem() - event_slope.setText(str(event.get('slope'))) - event_slope.setEditable(False) - self.events_model.setItem(current_row, 5, event_slope) - - event_splice_loss = QtGui.QStandardItem() - event_splice_loss.setText(str(event.get('splice_loss'))) - event_splice_loss.setEditable(False) - self.events_model.setItem(current_row, 6, event_splice_loss) - - event_type = QtGui.QStandardItem() - event_type.setText(str(event.get('event_type_details')['event'])) - event_type.setEditable(False) - self.events_model.setItem(current_row, 7, event_type) + for event in key_events.get('events', []): + current_row = self.events_model.rowCount() + self.events_model.insertRow(current_row) + + event_comment = QtGui.QStandardItem() + event_comment.setText(str(event.get('comment'))) + event_comment.setEditable(False) + self.events_model.setItem(current_row, 0, event_comment) + + event_position_km = QtGui.QStandardItem() + event_position_km.setText(str(event.get('distance_of_travel', 0))) + event_position_km.setEditable(False) + self.events_model.setItem(current_row, 1, event_position_km) + + event_position_ft = QtGui.QStandardItem() + event_position_ft.setEditable(False) + event_position_ft.setText(str(float(event.get('distance_of_travel', 0)) * 3280.8399)) + self.events_model.setItem(current_row, 2, event_position_ft) + + event_peak = QtGui.QStandardItem() + event_peak.setText(str(event.get('peak_point'))) + event_peak.setEditable(False) + self.events_model.setItem(current_row, 3, event_peak) + + event_loss = QtGui.QStandardItem() + event_loss.setText(str(event.get('reflection_loss'))) + event_loss.setEditable(False) + self.events_model.setItem(current_row, 4, event_loss) + + event_slope = QtGui.QStandardItem() + event_slope.setText(str(event.get('slope'))) + event_slope.setEditable(False) + self.events_model.setItem(current_row, 5, event_slope) + + event_splice_loss = QtGui.QStandardItem() + event_splice_loss.setText(str(event.get('splice_loss'))) + event_splice_loss.setEditable(False) + self.events_model.setItem(current_row, 6, event_splice_loss) + + event_type = QtGui.QStandardItem() + event_type.setText(str(event.get('event_type_details')['event'])) + event_type.setEditable(False) + self.events_model.setItem(current_row, 7, event_type) ## self.events_model.setHorizontalHeaderLabels(['Event', ## 'Dist (km)',