diff --git a/OpenOTDR.py b/OpenOTDR.py index 0b0cb4d..0c7b9b4 100755 --- a/OpenOTDR.py +++ b/OpenOTDR.py @@ -5,19 +5,26 @@ 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 -from pyotdr import sorparse +#from pyotdr import sorparse +import otdrparser from matplotlib.figure import Figure from matplotlib import cm 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 @@ -44,28 +51,50 @@ def _low_pass_filter_trace(a_raw_trace, window_len): return a_trace -def prepare_data(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) - # 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} + #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']) + + 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(kind.get(k, None))) + value_text.setEditable(False) + self.meta_model.setItem(current_row, 1, value_text) + + 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])): @@ -133,9 +162,18 @@ 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) + self.user_interface.eventTableView.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.ResizeMode.ResizeToContents) +# + # 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) @@ -146,6 +184,9 @@ 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 self.raw_features = [] self.raw_traces = [] @@ -175,34 +216,89 @@ 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.files[url] = {"meta": d_meta, "raw_trace": l_raw_trace} + 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({"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 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(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) + + 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 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: +# 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) - 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)) + color=wavelength_to_rgb(str(wavelength))) +# self.plt.set_xlim([0, None]) + if self.canvas: self.user_interface.graphLayout.removeWidget(self.canvas) self.canvas.close() @@ -210,19 +306,29 @@ 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) + 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.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) + self.recalculate_events() + def open_project(self): '''Load a project from a file''' 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) + 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) @@ -236,15 +342,16 @@ def open_project(self): self._draw() self._draw() self.recalculate_events() + self._draw def save_project(self): '''Save a project to a file''' 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) + 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: @@ -274,16 +381,28 @@ 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: self._load_file(filename) + l_traces = [] + l_feature_points = [] for index in range(self.project_model.rowCount()): raw_data = self.project_model.item(index).data 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("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): @@ -298,14 +417,14 @@ 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''' 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": [] @@ -344,51 +463,125 @@ 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']) - # - 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) - 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) - event_type = QtGui.QStandardItem() - event_type.setEditable(True) - self.events_model.setItem(current_row, 0, event_type) + 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 + 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) + + 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)', +## '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) + 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 = [] 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, 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._update_events_table(d_events, d_data) APP = QtWidgets.QApplication(sys.argv) @@ -397,4 +590,4 @@ def recalculate_events(self): MAIN_WINDOW.setWindowTitle("OpenOTDR") MAIN_WINDOW.show() -sys.exit(APP.exec_()) +sys.exit(APP.exec()) 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` diff --git a/mainwindow.py b/mainwindow.py index e05a389..c375325 100644 --- a/mainwindow.py +++ b/mainwindow.py @@ -1,97 +1,94 @@ -# -*- coding: utf-8 -*- - # Form implementation generated from reading ui file 'mainwindow.ui' # -# Created by: PyQt5 UI code generator 5.15.9 +# 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, 755) - self.mainWidget = QtWidgets.QWidget(MainWindow) + MainWindow.resize(1280, 760) + 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) 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") 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) 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 = QtWidgets.QPushButton(parent=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("") + self.removeTrace = QtWidgets.QPushButton(parent=self.groupBox) 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) - 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) 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 = QtWidgets.QPushButton(parent=self.groupBox) + 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) + self.openProject = QtWidgets.QPushButton(parent=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") + self.printReport = QtWidgets.QPushButton(parent=self.groupBox) + 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) - 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, "") @@ -99,34 +96,21 @@ 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.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.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, "") self.horizontalLayout_3.addWidget(self.tabWidget) - self.dataWidget = QtWidgets.QWidget(self.mainWidget) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) - sizePolicy.setHorizontalStretch(0) + 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()) self.dataWidget.setSizePolicy(sizePolicy) @@ -134,9 +118,9 @@ 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) - sizePolicy.setHorizontalStretch(0) + 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()) self.graphWidget.setSizePolicy(sizePolicy) @@ -148,12 +132,12 @@ 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.Expanding, QtWidgets.QSizePolicy.Preferred) + 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()) @@ -165,7 +149,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) @@ -176,25 +160,19 @@ 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")) - 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")) @@ -205,4 +183,4 @@ def retranslateUi(self, MainWindow): ui = Ui_MainWindow() ui.setupUi(MainWindow) MainWindow.show() - sys.exit(app.exec_()) + sys.exit(app.exec()) diff --git a/mainwindow.ui b/mainwindow.ui index f5f99e6..d7947bd 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -7,7 +7,7 @@ 0 0 1280 - 755 + 760 @@ -19,7 +19,7 @@ - 0 + 1 0 @@ -29,9 +29,6 @@ 720 - - QTabWidget::West - 0 @@ -47,7 +44,7 @@ - 0 + 1 0 @@ -64,42 +61,47 @@ - true + false + + true + + + Add Trace + false - + + - - - + true - true + false + + Remove Trace + - + - - - - + - true + false @@ -107,53 +109,72 @@ - 0 + 1 0 + + Calculate Events + + + calc + - - - + - true + false + + Save Project + + + false + + + save + - - - + - true + false + + Open Project + + + open + - - - + - true + false + + Print + + + print + - - - + - true + false @@ -171,53 +192,23 @@ - - - - Project name - - - - - Location A - - - - - Location B - - - - - Total distance (km) - - - - - Total distance - - - - - Launch length (km) - - - - - Recieve length (km) - - - - - Average loss (dB/km) - - - - - Total loss(dB) - - - + + + + 1 + 0 + + + + + 300 + 200 + + + + true + + @@ -227,7 +218,7 @@ - 0 + 1 0 @@ -242,7 +233,7 @@ - 0 + 1 0 @@ -265,7 +256,7 @@ - + 1 0 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