[segyio] 45/376: Testing read_all_traces in util module for segyviewer

Jørgen Kvalsvik jokva-guest at moszumanska.debian.org
Wed Sep 20 08:04:05 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 856f8ff2ca4a856067b4a465e8a9fc06e32db650
Author: Thorvald Johannessen <thorvjo at statoil.com>
Date:   Tue Oct 11 17:04:51 2016 +0200

    Testing read_all_traces in util module for segyviewer
    
    Adding a separate unit test class for the viewer.
---
 .travis.yml                          |  6 +++
 applications/segyviewer.py           | 98 +++++++++++++-----------------------
 python/segyview/CMakeLists.txt       |  1 +
 python/segyview/__init__.py          |  1 +
 python/segyview/linenavigationbar.py | 11 ++--
 python/segyview/segyplot.py          |  2 +-
 python/segyview/slicewidget.py       | 17 ++++---
 python/segyview/util.py              | 36 +++++++++++++
 tests/CMakeLists.txt                 |  6 ++-
 tests/test_segyview.py               | 33 ++++++++++++
 10 files changed, 134 insertions(+), 77 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 64b69ae..3e4eae7 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -28,6 +28,12 @@ addons:
         - cmake-data
         - valgrind
         - python-numpy
+        - python-matplotlib
+
+install:
+  - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
+      pip install --user matplotlib;
+    fi
 
 before_script:
   # Valgrind is experimental(ish) on MacOS with false positives on among others printf
diff --git a/applications/segyviewer.py b/applications/segyviewer.py
index edb2e07..c60d7ea 100755
--- a/applications/segyviewer.py
+++ b/applications/segyviewer.py
@@ -1,29 +1,28 @@
 #!/usr/bin/env python
 
 import sys
-
-import numpy as np
 import segyio
 from PyQt4 import QtGui, QtCore
 from segyview import *
+from segyview import util
 
 
 class LineSelectionMonitor(QtCore.QObject):
-    ilineChanged = QtCore.pyqtSignal(int)
-    xlineChanged = QtCore.pyqtSignal(int)
-    depthChanged = QtCore.pyqtSignal(int)
+    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 ilineUpdated(self, new_index):
-        self.ilineChanged.emit(new_index)
+    def iline_updated(self, new_index):
+        self.iline_changed.emit(new_index)
 
-    def xlineUpdated(self, new_index):
-        self.xlineChanged.emit(new_index)
+    def xline_updated(self, new_index):
+        self.xline_changed.emit(new_index)
 
-    def depthUpdated(self, new_index):
-        self.depthChanged.emit(new_index)
+    def depth_updated(self, new_index):
+        self.depth_changed.emit(new_index)
 
 
 class ColorMapMonitor(QtCore.QObject):
@@ -32,7 +31,7 @@ class ColorMapMonitor(QtCore.QObject):
     def __init__(self, parent=None):
         QtCore.QObject.__init__(self, parent)
 
-    def colormapUpdated(self, value):
+    def colormap_updated(self, value):
         self.cmap_changed.emit(str(value))
 
 
@@ -50,16 +49,16 @@ def configure_main_menu(menu, colormap_monitor, available_colormaps):
 
     colormap_monitor.cmap_changed.connect(set_selected_cmap)
 
-    def colormapChanger(color_map_name):
-        def performColorMapChange():
-            colormap_monitor.colormapUpdated(color_map_name)
+    def colormap_changer(color_map_name):
+        def perform_colormap_change():
+            colormap_monitor.colormap_updated(color_map_name)
 
-        return performColorMapChange
+        return perform_colormap_change
 
     for item in available_colormaps:
         action = menu.colormapMenu.addAction(item)
         action.setCheckable(True)
-        action.triggered.connect(colormapChanger(item))
+        action.triggered.connect(colormap_changer(item))
 
 
 class SegyViewer(QtGui.QMainWindow):
@@ -73,16 +72,15 @@ class SegyViewer(QtGui.QMainWindow):
         colormap_monitor = ColorMapMonitor(self)
         line_monitor = LineSelectionMonitor(self)
 
-
         # menus
         available_colormaps = ['seismic', 'spectral', 'RdGy', 'hot', 'jet', 'gray']
         configure_main_menu(self.menuBar(), colormap_monitor, available_colormaps)
 
-
         self.addToolBar(LineNavigationBar(s.xlines, s.ilines, range(s.samples), line_monitor))
         self.statusBar()
 
-        depth_slices, min_max = read_traces_to_memory(s)
+        # to avoid having to rescan the entire file for accessing each depth slice. all slices are read once.
+        depth_slices, min_max = util.read_traces_to_memory(s)
 
         # initialize
         x_slice_widget = SliceWidget(s.xline, s.xlines,
@@ -90,11 +88,13 @@ class SegyViewer(QtGui.QMainWindow):
                                      y_axis_indexes=('depth', range(s.samples)),
                                      show_v_indicator=True,
                                      v_min_max=min_max)
+
         i_slice_widget = SliceWidget(s.iline, s.ilines,
                                      x_axis_indexes=('x-lines', s.xlines.tolist()),
                                      y_axis_indexes=('depth', range(s.samples)),
                                      show_v_indicator=True,
                                      v_min_max=min_max)
+
         depth_slice_widget = SliceWidget(depth_slices, range(s.samples),
                                          x_axis_indexes=('i-lines', s.ilines.tolist()),
                                          y_axis_indexes=('x-lines', s.xlines.tolist()),
@@ -102,19 +102,19 @@ class SegyViewer(QtGui.QMainWindow):
                                          show_h_indicator=True,
                                          v_min_max=min_max)
 
-        # attach signals
-        x_slice_widget.indexChanged.connect(line_monitor.ilineUpdated)
-        i_slice_widget.indexChanged.connect(line_monitor.xlineUpdated)
+        # attach line-index change signals
+        x_slice_widget.index_changed.connect(line_monitor.iline_updated)
+        i_slice_widget.index_changed.connect(line_monitor.xline_updated)
 
-        line_monitor.ilineChanged.connect(x_slice_widget.set_vertical_line_indicator)
-        line_monitor.ilineChanged.connect(depth_slice_widget.set_vertical_line_indicator)
-        line_monitor.ilineChanged.connect(i_slice_widget.update_image)
+        line_monitor.iline_changed.connect(x_slice_widget.set_vertical_line_indicator)
+        line_monitor.iline_changed.connect(depth_slice_widget.set_vertical_line_indicator)
+        line_monitor.iline_changed.connect(i_slice_widget.update_image)
 
-        line_monitor.xlineChanged.connect(i_slice_widget.set_vertical_line_indicator)
-        line_monitor.xlineChanged.connect(depth_slice_widget.set_horizontal_line_indicator)
-        line_monitor.xlineChanged.connect(x_slice_widget.update_image)
+        line_monitor.xline_changed.connect(i_slice_widget.set_vertical_line_indicator)
+        line_monitor.xline_changed.connect(depth_slice_widget.set_horizontal_line_indicator)
+        line_monitor.xline_changed.connect(x_slice_widget.update_image)
 
-        line_monitor.depthChanged.connect(depth_slice_widget.update_image)
+        line_monitor.depth_changed.connect(depth_slice_widget.update_image)
 
         # colormap signals
         colormap_monitor.cmap_changed.connect(x_slice_widget.set_cmap)
@@ -144,45 +144,17 @@ class SegyViewer(QtGui.QMainWindow):
         main_widget.hide()
 
 
-def read_traces_to_memory(segy):
-    ''' read all samples into memory and identify min and max. A temporary utility method to handle the
-    challenge of navigating  up and down in depth slices. As each depth slice consist of samples from all traces in
-    the file '''
-    all_traces = np.empty(shape=((len(segy.ilines) * len(segy.xlines)), segy.samples), dtype=np.float32)
-
-    min_value = sys.float_info.max
-    max_value = sys.float_info.min
-
-    for i, t in enumerate(segy.trace):
-        all_traces[i] = t
-
-        local_min = np.nanmin(t)
-        local_max = np.nanmax(t)
-
-        if np.isfinite(local_min):
-            min_value = min(local_min, min_value)
-
-        if np.isfinite(local_max):
-            max_value = max(local_max, max_value)
-
-    all_traces2 = all_traces.reshape(len(segy.ilines), len(segy.xlines), segy.samples)
-
-    transposed_traces = all_traces2.transpose(2, 0, 1)
-
-    return transposed_traces, (min_value, max_value)
-
-
 def main():
     if len(sys.argv) < 2:
-        sys.exit("Usage: view.py [file]")
+        sys.exit("Usage: segyviewer.py [file]")
 
     filename = sys.argv[1]
 
     with segyio.open(filename, "r") as s:
-        qApp = QtGui.QApplication(sys.argv)
-        aw = SegyViewer(s)
-        aw.show()
-        sys.exit(qApp.exec_())
+        q_app = QtGui.QApplication(sys.argv)
+        segy_viewer = SegyViewer(s)
+        segy_viewer.show()
+        sys.exit(q_app.exec_())
 
 
 if __name__ == '__main__':
diff --git a/python/segyview/CMakeLists.txt b/python/segyview/CMakeLists.txt
index 2b157d1..ec81844 100644
--- a/python/segyview/CMakeLists.txt
+++ b/python/segyview/CMakeLists.txt
@@ -3,6 +3,7 @@ set(PYTHON_SOURCES
     linenavigationbar.py
     segyplot.py
     slicewidget.py
+    util.py
     )
 
 add_python_package(segyview segyview "${PYTHON_SOURCES}")
diff --git a/python/segyview/__init__.py b/python/segyview/__init__.py
index 640d109..c0e02e1 100644
--- a/python/segyview/__init__.py
+++ b/python/segyview/__init__.py
@@ -1,4 +1,5 @@
 from .segyplot import SegyPlot
+import util
 
 try:
     from .linenavigationbar import LineNavigationBar
diff --git a/python/segyview/linenavigationbar.py b/python/segyview/linenavigationbar.py
index 76cfb6c..aebff7e 100644
--- a/python/segyview/linenavigationbar.py
+++ b/python/segyview/linenavigationbar.py
@@ -27,6 +27,7 @@ class LineSelector(QtGui.QWidget):
         self.sbox.setValue(val)
         self.sbox.blockSignals(False)
 
+
 class LineNavigationBar(QtGui.QToolBar):
     def __init__(self, xline_indexes, iline_indexes, depth_indexes, line_selection_monitor):
         super(LineNavigationBar, self).__init__("")
@@ -36,15 +37,15 @@ class LineNavigationBar(QtGui.QToolBar):
         self.line_selection_monitor = line_selection_monitor
 
         # xline
-        self.xline_selector = LineSelector(self, "x-line", self.xline_indexes, self.line_selection_monitor.xlineUpdated)
-        self.line_selection_monitor.xlineChanged.connect(self.xline_selector.set_index)
+        self.xline_selector = LineSelector(self, "x-line", self.xline_indexes, self.line_selection_monitor.xline_updated)
+        self.line_selection_monitor.xline_changed.connect(self.xline_selector.set_index)
         self.addWidget(self.xline_selector)
 
         # iline
-        self.iline_selector = LineSelector(self, "i-line", self.iline_indexes, self.line_selection_monitor.ilineUpdated)
-        self.line_selection_monitor.ilineChanged.connect(self.iline_selector.set_index)
+        self.iline_selector = LineSelector(self, "i-line", self.iline_indexes, self.line_selection_monitor.iline_updated)
+        self.line_selection_monitor.iline_changed.connect(self.iline_selector.set_index)
         self.addWidget(self.iline_selector)
 
         # depth
-        self.depth_selector = LineSelector(self, "depth", self.depth_indexes, self.line_selection_monitor.depthUpdated)
+        self.depth_selector = LineSelector(self, "depth", self.depth_indexes, self.line_selection_monitor.depth_updated)
         self.addWidget(self.depth_selector)
diff --git a/python/segyview/segyplot.py b/python/segyview/segyplot.py
index d579d86..9848093 100644
--- a/python/segyview/segyplot.py
+++ b/python/segyview/segyplot.py
@@ -5,7 +5,7 @@ import matplotlib.patches as patches
 class SegyPlot(object):
 
     """
-    SegyPlot plots a segy slice and line indicators on the provided axes.
+    Plots a segy slice and line indicators on the provided axes.
     """
 
     def __init__(self, slices, indexes, axes, cmap='seismic', x_axis_indexes=None, y_axis_indexes=None,
diff --git a/python/segyview/slicewidget.py b/python/segyview/slicewidget.py
index 1d21e05..968d30c 100644
--- a/python/segyview/slicewidget.py
+++ b/python/segyview/slicewidget.py
@@ -2,14 +2,14 @@ from PyQt4 import QtGui, QtCore
 
 from segyplot import SegyPlot
 from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
-from matplotlib.figure import  Figure
+from matplotlib.figure import Figure
 
 
 class SliceWidget(QtGui.QWidget):
     """
     Main widget holding the slice matplotlib Figure wrapped in FigureCanvasQTAgg.
     """
-    indexChanged = QtCore.pyqtSignal(int)
+    index_changed = QtCore.pyqtSignal(int)
 
     def __init__(self, slices, indexes, dataset_title=None, default_cmap='seismic',
                  x_axis_indexes=None, y_axis_indexes=None,
@@ -36,10 +36,15 @@ class SliceWidget(QtGui.QWidget):
 
         self.axes = self.figure.add_subplot(111)
 
-        self.segy_plot = SegyPlot(self.slices, self.indexes, self.axes, self.default_cmap,
-                                        x_axis_indexes=x_axis_indexes, y_axis_indexes=y_axis_indexes,
-                                        display_horizontal_indicator=self.show_h_indicator,
-                                        display_vertical_indicator=self.show_v_indicator, v_min_max=v_min_max)
+        self.segy_plot = SegyPlot(self.slices,
+                                  self.indexes,
+                                  self.axes,
+                                  self.default_cmap,
+                                  x_axis_indexes=x_axis_indexes,
+                                  y_axis_indexes=y_axis_indexes,
+                                  display_horizontal_indicator=self.show_h_indicator,
+                                  display_vertical_indicator=self.show_v_indicator,
+                                  v_min_max=v_min_max)
 
         self.figure_canvas = FigureCanvas(self.figure)
         self.figure_canvas.setParent(self)
diff --git a/python/segyview/util.py b/python/segyview/util.py
new file mode 100644
index 0000000..47a4c4e
--- /dev/null
+++ b/python/segyview/util.py
@@ -0,0 +1,36 @@
+import sys
+import numpy as np
+
+
+def read_traces_to_memory(segy):
+    """ Read all traces into memory and identify global min and max values.
+
+    Utility method to handle the challenge of navigating up and down in depth slices,
+    as each depth slice consist of samples from all traces in the segy file.
+
+    The cube returned is transposed in aspect of the depth plane. Where each slice of the returned array
+    consists of all samples for the given depth, oriented by [iline, xline]
+    """
+
+    all_traces = np.empty(shape=((len(segy.ilines) * len(segy.xlines)), segy.samples), dtype=np.float32)
+
+    min_value = sys.float_info.max
+    max_value = sys.float_info.min
+
+    for i, t in enumerate(segy.trace):
+        all_traces[i] = t
+
+        local_min = np.nanmin(t)
+        local_max = np.nanmax(t)
+
+        if np.isfinite(local_min):
+            min_value = min(local_min, min_value)
+
+        if np.isfinite(local_max):
+            max_value = max(local_max, max_value)
+
+    reshaped_traces = all_traces.reshape(len(segy.ilines), len(segy.xlines), segy.samples)
+
+    transposed_traces = reshaped_traces.transpose(2, 0, 1)
+
+    return transposed_traces, (min_value, max_value)
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 8d91eb5..be98c05 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -13,8 +13,10 @@ if(BUILD_MEX)
     endif()
 endif()
 
+
 if(BUILD_PYTHON)
     add_python_test(python.segy test_segy.py)
     add_python_test(python.h.segy test_segyio_c.py)
-    add_python_test(enum.segy test_enum.py)
-endif()
\ No newline at end of file
+    add_python_test(python.enum.segy test_enum.py)
+    add_python_test(python.segyview test_segyview.py)
+endif()
diff --git a/tests/test_segyview.py b/tests/test_segyview.py
new file mode 100644
index 0000000..ea4d188
--- /dev/null
+++ b/tests/test_segyview.py
@@ -0,0 +1,33 @@
+from unittest import TestCase
+import segyio
+import segyview.util as util
+import itertools
+
+
+class TestSegyView(TestCase):
+
+    def setUp(self):
+        self.filename = "test-data/small.sgy"
+
+    def test_read_all_traces_to_memory_compare_with_depth_slice_and_verify_cube_rotation(self):
+
+        with segyio.open(self.filename, "r") as segy:
+            depth_slices, min_max = util.read_traces_to_memory(segy)
+
+            for i, slice in enumerate(depth_slices):
+                for ilno, xlno in itertools.product(range(len(segy.ilines)), range(len(segy.xlines))):
+
+                    self.assertEqual(slice[ilno, xlno], segy.depth_slice[i][ilno, xlno],
+                                     "the cube values from read_all_traces and depth_slice differ {0} != {1}"
+                                     .format(slice[ilno, xlno], segy.depth_slice[i][ilno, xlno]))
+
+
+
+
+
+
+
+
+
+
+

-- 
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