[segyio] 250/376: Gather mode

Jørgen Kvalsvik jokva-guest at moszumanska.debian.org
Wed Sep 20 08:04:40 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 b80daea4c0ed79836350bf0477db8c39029973db
Author: Jørgen Kvalsvik <jokva at statoil.com>
Date:   Wed Mar 29 14:31:25 2017 +0200

    Gather mode
    
    Support for reading data from some intersection in a cube.
---
 python/CMakeLists.txt    |  1 +
 python/segyio/_gather.py | 82 ++++++++++++++++++++++++++++++++++++++++++++++++
 python/segyio/segy.py    | 38 ++++++++++++++++++++++
 python/test/segy.py      | 45 ++++++++++++++++++++++++++
 4 files changed, 166 insertions(+)

diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt
index c797160..fd322c8 100644
--- a/python/CMakeLists.txt
+++ b/python/CMakeLists.txt
@@ -39,6 +39,7 @@ add_python_package(pysegyio segyio
                     TARGETS _segyio
                     SOURCES segyio/__init__.py
                             segyio/_header.py
+                            segyio/_gather.py
                             segyio/_line.py
                             segyio/_field.py
                             segyio/_trace.py
diff --git a/python/segyio/_gather.py b/python/segyio/_gather.py
new file mode 100644
index 0000000..e4be93e
--- /dev/null
+++ b/python/segyio/_gather.py
@@ -0,0 +1,82 @@
+import itertools
+import numpy as np
+
+import segyio.tools as tools
+from segyio.tracesortingformat import TraceSortingFormat
+
+class Gather:
+    """ Gather mode. Internal.
+
+    Provides the implementation for f.gather, reading n offsets from the
+    intersection of two lines in a cube.
+    """
+
+    def __init__(self, trace, iline, xline, offsets, sort):
+        # cache constructed modes for performance
+        self.trace     = trace
+        self.iline     = iline
+        self.xline     = xline
+        self.offsets   = offsets
+        self.sort      = sort
+
+    def _getindex(self, il, xl, offset, sorting):
+        """ Get the trace index for an (il, xl, offset) tuple
+
+        :rtype: int
+        """
+        if sorting == TraceSortingFormat.INLINE_SORTING:
+            xlind = self.xline._index(xl, None)
+            return self.iline._index(il, offset) + xlind
+        else:
+            ilind = self.iline._index(il, None)
+            return self.xline._index(xl, offset) + ilind
+
+    def __getitem__(self, index):
+        """ :rtype: iterator[numpy.ndarray]|numpy.ndarray """
+        if len(index) < 3:
+            index = (index[0], index[1], slice(None))
+
+        il, xl, off = index
+        sort = self.sort
+
+        def isslice(x): return isinstance(x, slice)
+
+        # gather[int,int,int]
+        if not any(map(isslice, [il, xl, off])):
+            return self.trace[self._getindex(il, xl, off, sort)]
+
+        offs = off if isslice(off) else slice(off, off+1, 1)
+
+        xs = list(filter(self.offsets.__contains__,
+                    range(*offs.indices(self.offsets[-1]+1))))
+
+        empty = np.empty(0, dtype = np.single)
+        # gather[int,int,:]
+        if not any(map(isslice, [il, xl])):
+            if len(xs) == 0: return empty
+            return tools.collect(
+                    self.trace[self._getindex(il, xl, x, sort)]
+                    for x in xs)
+
+        # gather[:,:,:]
+        def gen():
+            ils, _ = self.iline._indices(il, None)
+            xls, _ = self.xline._indices(xl, None)
+
+            # gather[:, :, int]
+            # i.e. every yielded array is 1-dimensional
+            if not isslice(off):
+                for i, x in itertools.product(ils, xls):
+                    yield self.trace[self._getindex(i, x, off, sort)]
+                return
+
+            if len(xs) == 0:
+                for _, _ in itertools.product(ils, xls): yield empty
+                return
+
+            for i, x in itertools.product(ils, xls):
+                yield tools.collect(
+                        self.trace[self._getindex(i, x, o, sort)]
+                        for o in xs)
+
+        return gen()
diff --git a/python/segyio/segy.py b/python/segyio/segy.py
index af3a28c..3e9d86d 100644
--- a/python/segyio/segy.py
+++ b/python/segyio/segy.py
@@ -18,6 +18,7 @@ import itertools
 import numpy as np
 
 from segyio._header import Header
+from segyio._gather import Gather
 from segyio._line import Line
 from segyio._trace import Trace
 from segyio._field import Field
@@ -895,6 +896,43 @@ class SegyFile(object):
         self.depth_slice[:] = value
 
     @property
+    def gather(self):
+        """ Interact with segy in gather mode
+
+        A gather is in this context the intersection of lines in a cube, i.e.
+        all the offsets at some iline/xline intersection. The primary data type
+        is the numpy ndarray, with dimensions depending on the range of offsets
+        specified. Offsets uses the line and offset numbers (names), not
+        0-based indices.
+
+        When using ranges over lines, a generator is returned.
+
+        Examples:
+
+            Read one offset at an intersection::
+                >>> f.gather[200, 241, 25] # returns a samples-long 1d-array
+
+            Read all offsets at an intersection::
+                >>> f.gather[200, 241, :] # returns offsets x samples ndarray
+                >>> # If no offset is specified, this is implicitly (:)
+                >>> f.gather[200, 241, :] == f.gather[200, 241]
+
+            All offsets for a set of ilines, intersecting one crossline::
+                >>> f.gather[200:300, 241, :]
+
+            Some offsets for a set of ilines, interescting one crossline::
+                >>> f.gather[200:300, 241, 10:25:5]
+
+            Some offsets for a set of ilines and xlines. This effectively yields a subcube::
+                >>> f.gather[200:300, 241:248, 1:10]
+        """
+        if self.unstructured:
+            raise ValueError(self._unstructured_errmsg)
+
+        return Gather(self.trace, self.iline, self.xline,
+                      self.offsets, self.sorting)
+
+    @property
     def text(self):
         """ Interact with segy in text mode.
 
diff --git a/python/test/segy.py b/python/test/segy.py
index 20048a0..833e888 100644
--- a/python/test/segy.py
+++ b/python/test/segy.py
@@ -366,6 +366,51 @@ class TestSegy(TestCase):
             self.assertEqual((offs // 2) * (ils // 2), sum(1 for _ in f.iline[::2, ::-2]))
             self.assertEqual((offs // 2) * (ils // 2), sum(1 for _ in f.iline[::-2, ::2]))
 
+
+    def test_gather_mode(self):
+        with segyio.open(self.prestack) as f:
+            empty = np.empty(0, dtype = np.single)
+            # should raise
+            with self.assertRaises(KeyError):
+                self.assertTrue(np.array_equal(empty, f.gather[2, 3, 3]))
+
+            with self.assertRaises(KeyError):
+                self.assertTrue(np.array_equal(empty, f.gather[2, 5, 1]))
+
+            with self.assertRaises(KeyError):
+                self.assertTrue(np.array_equal(empty, f.gather[5, 2, 1]))
+
+            self.assertTrue(np.array_equal(f.trace[10], f.gather[2, 3, 1]))
+            self.assertTrue(np.array_equal(f.trace[11], f.gather[2, 3, 2]))
+
+            traces = segyio.tools.collect(f.trace[10:12])
+            gather = f.gather[2,3,:]
+            self.assertTrue(np.array_equal(traces, gather))
+            self.assertTrue(np.array_equal(traces, f.gather[2,3]))
+            self.assertTrue(np.array_equal(empty,  f.gather[2,3,1:0]))
+            self.assertTrue(np.array_equal(empty,  f.gather[2,3,3:4]))
+
+            for g, line in zip(f.gather[1:3, 3, 1], f.iline[1:3]):
+                self.assertEqual(10, len(g))
+                self.assertEqual((10,), g.shape)
+                self.assertTrue(np.array_equal(line[2], g))
+
+            for g, line in zip(f.gather[1:3, 3, :], f.iline[1:3]):
+                self.assertEqual(2, len(g))
+                self.assertEqual((2, 10), g.shape)
+                self.assertTrue(np.array_equal(line[2], g[0]))
+
+            for g, line in zip(f.gather[1, 1:3, 1], f.xline[1:3]):
+                self.assertEqual(10, len(g))
+                self.assertEqual((10,), g.shape)
+                self.assertTrue(np.array_equal(line[0], g))
+
+            for g, line in zip(f.gather[1, 1:3, :], f.xline[1:3]):
+                self.assertEqual(2, len(g))
+                self.assertEqual((2, 10), g.shape)
+                self.assertTrue(np.array_equal(line[0], g[0]))
+
+
     def test_line_generators(self):
         with segyio.open(self.filename, "r") as f:
             for line in f.iline:

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