[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