[segyio] 80/376: New "View" class holding a standalone QWidget that can be embedded in other QT programs.

Jørgen Kvalsvik jokva-guest at moszumanska.debian.org
Wed Sep 20 08:04:11 UTC 2017


This is an automated email from the git hooks/post-receive script.

jokva-guest pushed a commit to branch debian
in repository segyio.

commit 75525e055cb4e04af4709e279681af82037a60f2
Author: Thorvald Johannessen <thorvjo at statoil.com>
Date:   Thu Oct 27 13:46:33 2016 +0200

    New "View" class holding a standalone QWidget that can be embedded in other QT programs.
    
    Plus the necessary refactoring, to enable reuse classes for the different use cases.
---
 applications/segyviewer.py        | 223 ++++++++------------------------------
 python/segyview/CMakeLists.txt    |   2 +
 python/segyview/__init__.py       |   3 +
 python/segyview/progresswidget.py |  25 +++++
 python/segyview/viewer.py         | 177 ++++++++++++++++++++++++++++++
 5 files changed, 254 insertions(+), 176 deletions(-)

diff --git a/applications/segyviewer.py b/applications/segyviewer.py
index 21b0807..379e985 100755
--- a/applications/segyviewer.py
+++ b/applications/segyviewer.py
@@ -6,102 +6,6 @@ from PyQt4 import QtGui, QtCore
 from segyview import *
 
 
-class LineSelectionMonitor(QtCore.QObject):
-    iline_changed = QtCore.pyqtSignal(int)
-    xline_changed = QtCore.pyqtSignal(int)
-    depth_changed = QtCore.pyqtSignal(int)
-
-    def __init__(self, parent):
-        QtCore.QObject.__init__(self, parent)
-
-    def iline_updated(self, new_index):
-        self.iline_changed.emit(new_index)
-
-    def xline_updated(self, new_index):
-        self.xline_changed.emit(new_index)
-
-    def depth_updated(self, new_index):
-        self.depth_changed.emit(new_index)
-
-
-class ColorMapMonitor(QtCore.QObject):
-    cmap_changed = QtCore.pyqtSignal(str)
-
-    def __init__(self, parent=None):
-        QtCore.QObject.__init__(self, parent)
-
-    def colormap_updated(self, value):
-        self.cmap_changed.emit(str(value))
-
-
-class FileActivityMonitor(QtCore.QObject):
-    started = QtCore.pyqtSignal()
-    finished = QtCore.pyqtSignal()
-    cancelled_operation = False
-
-    def __init__(self, parent=None):
-        QtCore.QObject.__init__(self)
-        self.cancelled_operation = False
-
-    def reset(self):
-        self.cancelled_operation = False
-
-    def set_file_read_started(self):
-        self.started.emit()
-
-    def set_file_read_finished(self):
-        self.finished.emit()
-
-    def set_cancel_operation(self):
-        self.finished.emit()
-        self.cancelled_operation = True
-
-
-class ProgressWidget(QtGui.QWidget):
-
-    def __init__(self, call_on_cancel):
-        super(ProgressWidget, self).__init__()
-        self.call_on_cancel = call_on_cancel
-
-        layout = QtGui.QHBoxLayout()
-        # progress bar
-        self.p_bar = QtGui.QProgressBar(self)
-        cancel_file_load_btn = QtGui.QPushButton()
-        cancel_file_load_btn.setText("cancel")
-
-        cancel_file_load_btn.clicked.connect(self.call_on_cancel)
-
-        layout.addWidget(self.p_bar, 2)
-        layout.addWidget(cancel_file_load_btn)
-
-        self.setLayout(layout)
-
-    def set_value(self, int):
-        self.p_bar.setValue(int)
-
-
-class FileLoaderWorker(QtCore.QObject):
-    finished = QtCore.pyqtSignal(int)
-    progress = QtCore.pyqtSignal(int)
-
-    def __init__(self, segy_file_wrapper, filename, read_to_memory=False):
-        QtCore.QObject.__init__(self)
-        self.segy_file_wrapper = segy_file_wrapper
-        self.filename = filename
-        self.read_to_memory = read_to_memory
-
-    def load_file(self):
-        successful_file_open = self.segy_file_wrapper.open_file(self.filename,
-                                         read_to_memory=self.read_to_memory,
-                                         progress_callback=self.progress.emit)
-        if successful_file_open:
-            self.finished.emit(0)
-        else:
-            self.finished.emit(1)
-
-        return None
-
-
 class SegyViewer(QtGui.QMainWindow):
     def __init__(self, filename):
         QtGui.QMainWindow.__init__(self)
@@ -117,7 +21,7 @@ class SegyViewer(QtGui.QMainWindow):
         self.file_activity_monitor = FileActivityMonitor(self)
 
         # the wrapper around segyio
-        self.swrap = SegyIOWrapper(self.file_activity_monitor)
+        self.swrap = None
 
         # menus
         available_colormaps = ['seismic', 'spectral', 'RdGy', 'hot', 'jet', 'gray']
@@ -136,7 +40,7 @@ class SegyViewer(QtGui.QMainWindow):
         self.setup_dock_widgets()
 
         # progress bar
-        self.progress_bar = ProgressWidget(self.swrap.file_activity_monitor.set_cancel_operation)
+        self.progress_bar = ProgressWidget(self.file_activity_monitor.set_cancel_operation)
         self.statusBar().addWidget(self.progress_bar, 1)
         self.progress_bar.hide()
 
@@ -144,20 +48,15 @@ class SegyViewer(QtGui.QMainWindow):
         self.resize(1200, 800)
 
         # connect cursor overrides to file activity that might take long time
-        self.swrap.file_activity_monitor.started.connect(
+        self.file_activity_monitor.started.connect(
             lambda: QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.BusyCursor)))
-        self.swrap.file_activity_monitor.finished.connect(
+        self.file_activity_monitor.finished.connect(
             lambda: QtGui.QApplication.restoreOverrideCursor())
 
         # initiate the first file load
         if filename:
             self.load_file_and_setup_slice_widgets(filename)
 
-        # fix for making dock widgets fill entire window
-        # self.main_widget = QtGui.QWidget(self)
-        # self.main_widget.setFocus()
-        # self.setCentralWidget(self.main_widget)
-        # self.main_widget.hide()
 
     def setup_dock_widgets(self):
         self.setDockOptions(QtGui.QMainWindow.AllowNestedDocks)
@@ -206,55 +105,6 @@ class SegyViewer(QtGui.QMainWindow):
             for widgt in dock_widget.findChildren(SliceWidget):
                 widgt.deleteLater()
 
-    def setup_widgets_and_controls(self):
-        self.addToolBar(LineNavigationBar(self.swrap.xlines,
-                                          self.swrap.ilines,
-                                          range(self.swrap.samples),
-                                          self.line_monitor))
-
-        # initialize slice widgets
-        x_slice_widget = SliceWidget(self.swrap.xline, self.swrap.xlines,
-                                     x_axis_indexes=('i-lines', self.swrap.ilines),
-                                     y_axis_indexes=('depth', range(self.swrap.samples)),
-                                     show_v_indicator=True,
-                                     v_min_max=self.swrap.min_max)
-
-        i_slice_widget = SliceWidget(self.swrap.iline, self.swrap.ilines,
-                                     x_axis_indexes=('x-lines', self.swrap.xlines),
-                                     y_axis_indexes=('depth', range(self.swrap.samples)),
-                                     show_v_indicator=True,
-                                     v_min_max=self.swrap.min_max)
-
-        depth_slice_widget = SliceWidget(self.swrap.depth_slice, range(self.swrap.samples),
-                                         x_axis_indexes=('i-lines', self.swrap.ilines),
-                                         y_axis_indexes=('x-lines', self.swrap.xlines),
-                                         show_v_indicator=True,
-                                         show_h_indicator=True,
-                                         v_min_max=self.swrap.min_max)
-
-        # attach line-index change signals
-        x_slice_widget.index_changed.connect(self.line_monitor.iline_updated)
-        i_slice_widget.index_changed.connect(self.line_monitor.xline_updated)
-
-        self.line_monitor.iline_changed.connect(x_slice_widget.set_vertical_line_indicator)
-        self.line_monitor.iline_changed.connect(depth_slice_widget.set_vertical_line_indicator)
-        self.line_monitor.iline_changed.connect(i_slice_widget.update_image)
-
-        self.line_monitor.xline_changed.connect(i_slice_widget.set_vertical_line_indicator)
-        self.line_monitor.xline_changed.connect(depth_slice_widget.set_horizontal_line_indicator)
-        self.line_monitor.xline_changed.connect(x_slice_widget.update_image)
-
-        self.line_monitor.depth_changed.connect(depth_slice_widget.update_image)
-
-        # colormap signals
-        self.colormap_monitor.cmap_changed.connect(x_slice_widget.set_cmap)
-        self.colormap_monitor.cmap_changed.connect(i_slice_widget.set_cmap)
-        self.colormap_monitor.cmap_changed.connect(depth_slice_widget.set_cmap)
-
-        self.xdock.setWidget(x_slice_widget)
-        self.idock.setWidget(i_slice_widget)
-        self.ddock.setWidget(depth_slice_widget)
-
     def open_file_dialogue(self):
 
         f_dialog = QtGui.QFileDialog(self)
@@ -286,32 +136,53 @@ class SegyViewer(QtGui.QMainWindow):
         self.progress_bar.show()
 
         self.file_activity_monitor.reset()
-        self.swrap = SegyIOWrapper(self.file_activity_monitor)
-
-        # worker thread and worker obj are referenced from main thread to not get gc'ed by accident
-        self.file_loader_thread = QtCore.QThread()
-        self.file_loader_worker = FileLoaderWorker(self.swrap, filename, read_to_memory=read_to_memory)
-        self.file_loader_worker.moveToThread(self.file_loader_thread)
-
-        # what to do
-        self.file_loader_thread.started.connect(self.file_loader_worker.load_file)
-
-        # update progress
-        self.file_loader_worker.progress.connect(self.progress_bar.set_value)
-
-        # when finished
-        self.file_loader_worker.finished.connect(self.complete_finished_file_load_operation)
-
-        self.file_loader_thread.start()
 
-    def complete_finished_file_load_operation(self, status):
+        # calling close on current filehandler
+        if self.swrap is not None:
+            self.swrap.close()
+
+        # instantiating a new wrapper
+        self.swrap = SegyIOWrapper.open_file_and_wrap(file_name=filename,
+                                                      file_activity_monitor=self.file_activity_monitor)
+        # callback when finished
+        def complete_finished_file_load_operation(status):
+            if status == 0:  # when completed successfully
+                self.initialize_slice_widgets()
+            self.progress_bar.hide()
+            self.file_loader_thread.quit()
+
+        # a memory read, might take some time. Set up a separate thread and update the progressbar
+        if read_to_memory:
+            # worker thread and worker obj are referenced from main thread to not get gc'ed by accident
+            self.file_loader_thread = QtCore.QThread()
+            self.file_loader_worker = FileLoaderWorker(self.swrap)
+            self.file_loader_worker.moveToThread(self.file_loader_thread)
+
+            # what to do
+            self.file_loader_thread.started.connect(self.file_loader_worker.load_file)
+
+            # update progress
+            self.file_loader_worker.progress.connect(self.progress_bar.set_value)
+
+            # set up finished callback
+            self.file_loader_worker.finished.connect(complete_finished_file_load_operation)
+
+            # and start
+            self.file_loader_thread.start()
+        else:
+            complete_finished_file_load_operation(0)
 
-        if status == 0:  # when completed successfully
-            self.setup_widgets_and_controls()
+    def initialize_slice_widgets(self):
+        self.addToolBar(LineNavigationBar(self.swrap.xlines,
+                                          self.swrap.ilines,
+                                          range(self.swrap.samples),
+                                          self.line_monitor))
 
-        self.progress_bar.hide()
-        self.file_loader_thread.quit()
+        x_wdgt, i_wdgt, d_wdgt = viewer.initialize_slice_widgets(self.swrap, self.line_monitor, self.colormap_monitor)
 
+        self.xdock.setWidget(x_wdgt)
+        self.idock.setWidget(i_wdgt)
+        self.ddock.setWidget(d_wdgt)
 
 def main():
 
diff --git a/python/segyview/CMakeLists.txt b/python/segyview/CMakeLists.txt
index 42de12b..89bd465 100644
--- a/python/segyview/CMakeLists.txt
+++ b/python/segyview/CMakeLists.txt
@@ -1,9 +1,11 @@
 set(PYTHON_SOURCES
     __init__.py
     linenavigationbar.py
+    progresswidget.py
     segyiowrapper.py
     segyplot.py
     slicewidget.py
+    viewer.py
     )
 
 add_python_package(segyview segyview "${PYTHON_SOURCES}")
diff --git a/python/segyview/__init__.py b/python/segyview/__init__.py
index a8c2648..273d2c7 100644
--- a/python/segyview/__init__.py
+++ b/python/segyview/__init__.py
@@ -3,7 +3,10 @@ from .segyiowrapper import SegyIOWrapper, SlicesWrapper
 
 try:
     from .linenavigationbar import LineNavigationBar
+    from .progresswidget import ProgressWidget
     from .slicewidget import SliceWidget
+    from .segyiowrapper import SegyIOWrapper, SlicesWrapper
+    from .viewer import *
 except ImportError as e:
     import sys
     import traceback
diff --git a/python/segyview/progresswidget.py b/python/segyview/progresswidget.py
new file mode 100644
index 0000000..a530f9d
--- /dev/null
+++ b/python/segyview/progresswidget.py
@@ -0,0 +1,25 @@
+from PyQt4 import QtGui
+
+
+class ProgressWidget(QtGui.QWidget):
+
+    def __init__(self, call_on_cancel):
+        super(ProgressWidget, self).__init__()
+        self.call_on_cancel = call_on_cancel
+
+        layout = QtGui.QHBoxLayout()
+        # progress bar
+        self.p_bar = QtGui.QProgressBar(self)
+        cancel_file_load_btn = QtGui.QPushButton()
+        cancel_file_load_btn.setText("cancel")
+
+        cancel_file_load_btn.clicked.connect(self.call_on_cancel)
+
+        layout.addWidget(self.p_bar, 2)
+        layout.addWidget(cancel_file_load_btn)
+
+        self.setLayout(layout)
+
+    def set_value(self, int):
+        self.p_bar.setValue(int)
+
diff --git a/python/segyview/viewer.py b/python/segyview/viewer.py
new file mode 100644
index 0000000..32fad8f
--- /dev/null
+++ b/python/segyview/viewer.py
@@ -0,0 +1,177 @@
+from segyview import SegyIOWrapper, SliceWidget
+from PyQt4 import QtGui, QtCore
+
+
+class LineSelectionMonitor(QtCore.QObject):
+    iline_changed = QtCore.pyqtSignal(int)
+    xline_changed = QtCore.pyqtSignal(int)
+    depth_changed = QtCore.pyqtSignal(int)
+
+    def __init__(self, parent):
+        QtCore.QObject.__init__(self, parent)
+
+    def iline_updated(self, new_index):
+        self.iline_changed.emit(new_index)
+
+    def xline_updated(self, new_index):
+        self.xline_changed.emit(new_index)
+
+    def depth_updated(self, new_index):
+        self.depth_changed.emit(new_index)
+
+
+class ColorMapMonitor(QtCore.QObject):
+    cmap_changed = QtCore.pyqtSignal(str)
+
+    def __init__(self, parent=None):
+        QtCore.QObject.__init__(self, parent)
+
+    def colormap_updated(self, value):
+        self.cmap_changed.emit(str(value))
+
+
+class FileActivityMonitor(QtCore.QObject):
+    started = QtCore.pyqtSignal()
+    finished = QtCore.pyqtSignal()
+    cancelled_operation = False
+
+    def __init__(self, parent=None):
+        QtCore.QObject.__init__(self)
+        self.cancelled_operation = False
+
+    def reset(self):
+        self.cancelled_operation = False
+
+    def set_file_read_started(self):
+        self.started.emit()
+
+    def set_file_read_finished(self):
+        self.finished.emit()
+
+    def set_cancel_operation(self):
+        self.finished.emit()
+        self.cancelled_operation = True
+
+
+class FileLoaderWorker(QtCore.QObject):
+    finished = QtCore.pyqtSignal(int)
+    progress = QtCore.pyqtSignal(int)
+
+    def __init__(self, segyio_wrapper):
+        QtCore.QObject.__init__(self)
+        self.segyio_wrapper = segyio_wrapper
+
+    def load_file(self):
+
+        if self.segyio_wrapper.read_all_traces_to_memory(progress_callback=self.progress.emit):
+             self.finished.emit(0)
+        else:
+            self.finished.emit(1)
+
+        return None
+
+
+class View(object):
+    """ A container for a standalone pre defined three-slices view, wrapped in a single QWidget. Plus monitor instances
+    for qt-signaling GUI events either from or to the slice viewers.
+
+    The widget, and monitors are provided through the class properties.
+    """
+
+    def __init__(self, segy):
+
+        self.segy = segy
+
+        self._file_activity_monitor = FileActivityMonitor()
+
+        self._swrap = SegyIOWrapper.wrap(segy, self.file_activity_monitor)
+
+        self._main_widget = QtGui.QWidget()
+        self._line_selection_monitor = LineSelectionMonitor(self._main_widget)
+        self._colormap_monitor = ColorMapMonitor(self._main_widget)
+
+        x_slice_widget, i_slice_widget, depth_slice_widget = initialize_slice_widgets(self._swrap,
+                                                                                      self._line_selection_monitor,
+                                                                                      self._colormap_monitor)
+        # layout for the single parent widget
+        top_row = QtGui.QHBoxLayout()
+        top_row.addWidget(x_slice_widget, 0)
+        top_row.addWidget(depth_slice_widget, 0)
+
+        bottom_row = QtGui.QHBoxLayout()
+        bottom_row.addWidget(i_slice_widget)
+
+        layout = QtGui.QVBoxLayout()
+        layout.addLayout(top_row)
+        layout.addLayout(bottom_row)
+
+
+        self._main_widget.setLayout(layout)
+
+    @property
+    def main_widget(self):
+        return self._main_widget
+
+    @property
+    def line_selection_monitor(self):
+        return self._line_selection_monitor
+
+    @property
+    def colormap_monitor(self):
+        return self._colormap_monitor
+
+    @property
+    def file_activity_monitor(self):
+        return self._file_activity_monitor
+
+
+def initialize_slice_widgets(segyio_wrapper, line_selection_monitor, colormap_monitor):
+    """
+    Given a segio_wrapper, and signal monitors, sliceviewer widgets for all three slices in a segy-cube are created.
+    :param segyio_wrapper:
+    :param line_selection_monitor:
+    :param colormap_monitor:
+    :return: three QWidgets for the three segy slices, in x, i and depth slice order.
+    """
+
+    # initialize slice widgets
+    x_slice_widget = SliceWidget(segyio_wrapper.xline, segyio_wrapper.xlines,
+                                 x_axis_indexes=('i-lines', segyio_wrapper.ilines),
+                                 y_axis_indexes=('depth', range(segyio_wrapper.samples)),
+                                 show_v_indicator=True,
+                                 v_min_max=segyio_wrapper.min_max)
+
+    i_slice_widget = SliceWidget(segyio_wrapper.iline, segyio_wrapper.ilines,
+                                 x_axis_indexes=('x-lines', segyio_wrapper.xlines),
+                                 y_axis_indexes=('depth', range(segyio_wrapper.samples)),
+                                 show_v_indicator=True,
+                                 v_min_max=segyio_wrapper.min_max)
+
+    depth_slice_widget = SliceWidget(segyio_wrapper.depth_slice, range(segyio_wrapper.samples),
+                                     x_axis_indexes=('i-lines', segyio_wrapper.ilines),
+                                     y_axis_indexes=('x-lines', segyio_wrapper.xlines),
+                                     show_v_indicator=True,
+                                     show_h_indicator=True,
+                                     v_min_max=segyio_wrapper.min_max)
+
+    # attach line-index change signals
+    x_slice_widget.index_changed.connect(line_selection_monitor.iline_updated)
+    i_slice_widget.index_changed.connect(line_selection_monitor.xline_updated)
+
+    line_selection_monitor.iline_changed.connect(x_slice_widget.set_vertical_line_indicator)
+    line_selection_monitor.iline_changed.connect(depth_slice_widget.set_vertical_line_indicator)
+    line_selection_monitor.iline_changed.connect(i_slice_widget.update_image)
+
+    line_selection_monitor.xline_changed.connect(i_slice_widget.set_vertical_line_indicator)
+    line_selection_monitor.xline_changed.connect(depth_slice_widget.set_horizontal_line_indicator)
+    line_selection_monitor.xline_changed.connect(x_slice_widget.update_image)
+
+    line_selection_monitor.depth_changed.connect(depth_slice_widget.update_image)
+
+    # colormap signals
+    colormap_monitor.cmap_changed.connect(x_slice_widget.set_cmap)
+    colormap_monitor.cmap_changed.connect(i_slice_widget.set_cmap)
+    colormap_monitor.cmap_changed.connect(depth_slice_widget.set_cmap)
+
+    return x_slice_widget, i_slice_widget, depth_slice_widget
+

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/segyio.git



More information about the debian-science-commits mailing list