[segyio] 123/376: Line.__setitem__ with offset support

Jørgen Kvalsvik jokva-guest at moszumanska.debian.org
Wed Sep 20 08:04:19 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 ea1ef80215f9a36c12f0623ac7c64ed886aced23
Author: Jørgen Kvalsvik <jokva at statoil.com>
Date:   Mon Nov 14 14:21:19 2016 +0100

    Line.__setitem__ with offset support
    
    The __getitem__ help methods have been split up to be either index
    generating method (_get_iter, _index, _santize_slice) and action methods
    (_get). This way the same index generations can be used for __setitem__
    which differs only in the direction of writing (disk versus memory) and
    lazyness.
---
 python/segyio/_header.py |  6 ++--
 python/segyio/_line.py   | 90 +++++++++++++++++++++++-------------------------
 python/segyio/_trace.py  |  1 -
 python/segyio/segy.py    |  4 ++-
 tests/test_segy.py       | 63 +++++++++++++++++++++++++++++++++
 5 files changed, 113 insertions(+), 51 deletions(-)

diff --git a/python/segyio/_header.py b/python/segyio/_header.py
index ffb54ce..e800d3f 100644
--- a/python/segyio/_header.py
+++ b/python/segyio/_header.py
@@ -47,14 +47,16 @@ class Header(object):
     def readfn(self, t0, length, stride, buf):
         def gen():
             start = t0
-            stop = t0 + (length * stride)
-            for i in range(start, stop, stride):
+            step = stride * len(self.segy.offsets)
+            stop = t0 + (length * step)
+            for i in range(start, stop, step):
                 yield Field.trace(buf, traceno=i, segy=self.segy)
 
         return gen()
 
     def writefn(self, t0, length, stride, val):
         start = t0
+        stride *= len(self.segy.offsets)
         stop = t0 + (length * stride)
 
         if isinstance(val, Field) or isinstance(val, dict):
diff --git a/python/segyio/_line.py b/python/segyio/_line.py
index ffef196..eef5d8d 100644
--- a/python/segyio/_line.py
+++ b/python/segyio/_line.py
@@ -29,9 +29,8 @@ class Line:
         self.readfn = readfn
         self.writefn = writefn
 
-    def _get(self, lineno, offset, buf):
-        """ :rtype: numpy.ndarray"""
-
+    def _index(self, lineno, offset):
+        """ :rtype: int"""
         offs = self.segy.offsets
 
         if offset is None:
@@ -52,27 +51,8 @@ class Line:
         except TypeError:
             raise TypeError("Must be int or slice")
 
-        t0 = self.trace0fn(lineno, offset)
-        return self.readfn(t0, self.len, self.stride, buf)
-
-    # in order to support [:end] syntax, we must make sure
-    # start has a non-None value. lineno.indices() would set it
-    # to 0, but we don't know if that's a reasonable value or
-    # not. If start is None we set it to the first line
-    def _sanitize_slice(self, s, source):
-        if all((s.start, s.stop, s.step)):
-            return s
-
-        start, stop, step = s.start, s.stop, s.step
-        increasing = step is None or step > 0
-
-        if start is None:
-            start = source[0] if increasing else source[-1]
-
-        if stop is None:
-            stop = source[-1]+1 if increasing else source[0]-1
-
-        return slice(start, stop, step)
+        trace0 = segyio._segyio.fread_trace0(lineno, len(self.other_lines), self.stride, len(offs), self.lines, self.name)
+        return offset + trace0
 
     def _indices(self, lineno, offset):
         """ :rtype: tuple[collections.Iterable, collections.Iterable]"""
@@ -96,16 +76,36 @@ class Line:
 
         return filter(lns.__contains__, lrng), filter(offs.__contains__, orng)
 
+    # in order to support [:end] syntax, we must make sure
+    # start has a non-None value. lineno.indices() would set it
+    # to 0, but we don't know if that's a reasonable value or
+    # not. If start is None we set it to the first line
+    def _sanitize_slice(self, s, source):
+        if all((s.start, s.stop, s.step)):
+            return s
+
+        start, stop, step = s.start, s.stop, s.step
+        increasing = step is None or step > 0
+
+        if start is None:
+            start = source[0] if increasing else source[-1]
+
+        if stop is None:
+            stop = source[-1]+1 if increasing else source[0]-1
+
+        return slice(start, stop, step)
+
+    def _get(self, lineno, offset, buf):
+        """ :rtype: numpy.ndarray"""
+        t0 = self._index(lineno, offset)
+        return self.readfn(t0, self.len, self.stride, buf)
+
+
     def _get_iter(self, lineno, off, buf):
         """ :rtype: collections.Iterable[numpy.ndarray]"""
 
-        def gen():
-            lines, offsets = self._indices(lineno, off)
-            for line in lines:
-                for offset in offsets:
-                    yield self._get(line, offset, buf)
-
-        return gen()
+        for line, offset in itertools.product(*self._indices(lineno, off)):
+            yield self._get(line, offset, buf)
 
     def __getitem__(self, lineno, offset = None):
         """ :rtype: numpy.ndarray|collections.Iterable[numpy.ndarray]"""
@@ -119,26 +119,22 @@ class Line:
 
         return self._get(lineno, offset, buf)
 
-    def trace0fn(self, lineno, offset_index):
-        offsets = len(self.segy.offsets)
-        trace0 = segyio._segyio.fread_trace0(lineno, len(self.other_lines), self.stride, offsets, self.lines, self.name)
-        return offset_index + trace0
-
     def __setitem__(self, lineno, val):
-        if isinstance(lineno, slice):
-            if lineno.start is None:
-                lineno = slice(self.lines[0], lineno.stop, lineno.step)
-
-            rng = range(*lineno.indices(self.lines[-1] + 1))
-            s = set(self.lines)
+        offset = None
+        if isinstance(lineno, tuple):
+            lineno, offset = lineno
 
-            for i, x in itertools.izip(filter(s.__contains__, rng), val):
-                self.__setitem__(i, x)
+        if isinstance(lineno, slice) or isinstance(offset, slice):
+            lines, offsets = self._indices(lineno, offset)
 
-            return
+            indices = itertools.product(*self._indices(lineno, offset))
+            for (line, offset), x in itertools.izip(indices, val):
+                t0 = self._index(line, offset)
+                self.writefn(t0, self.len, self.stride, x)
 
-        t0 = self.trace0fn(lineno, 0)
-        self.writefn(t0, self.len, self.stride, val)
+        else:
+            t0 = self._index(lineno, offset)
+            self.writefn(t0, self.len, self.stride, val)
 
     def __len__(self):
         return len(self.lines)
diff --git a/python/segyio/_trace.py b/python/segyio/_trace.py
index 8453a33..3ad1459 100644
--- a/python/segyio/_trace.py
+++ b/python/segyio/_trace.py
@@ -94,7 +94,6 @@ class Trace:
         :type buf: ?
         :type segy: segyio.SegyFile
         """
-
         segyio._segyio.write_trace(segy.xfd, traceno, buf, segy._tr0, segy._bsz, segy._fmt, segy.samples)
 
     @property
diff --git a/python/segyio/segy.py b/python/segyio/segy.py
index e7b8dec..5f1d853 100644
--- a/python/segyio/segy.py
+++ b/python/segyio/segy.py
@@ -447,7 +447,8 @@ class SegyFile(object):
 
         def writefn(t0, length, step, val):
             val = buffn(val)
-            for i, v in itertools.izip(range(t0, t0 + step * length, step), val):
+            step *= len(self.offsets)
+            for i, v in itertools.izip(range(t0, t0 + (step * length), step), val):
                 Trace.write_trace(i, v, self)
 
         return Line(self, il_len, il_stride, lines, other_lines, buffn, readfn, writefn, "Inline")
@@ -528,6 +529,7 @@ class SegyFile(object):
 
         def writefn(t0, length, step, val):
             val = buffn(val)
+            step *= len(self.offsets)
             for i, v in itertools.izip(range(t0, t0 + step * length, step), val):
                 Trace.write_trace(i, v, self)
 
diff --git a/tests/test_segy.py b/tests/test_segy.py
index bfb7d0a..1b9f53e 100644
--- a/tests/test_segy.py
+++ b/tests/test_segy.py
@@ -205,6 +205,25 @@ class TestSegy(TestCase):
             self.assertEqual(f.header[0][xl], f.header[1][xl])
             self.assertNotEqual(f.header[1][xl], f.header[2][xl])
 
+    def test_headers_line_offset(self):
+        fname = self.prestack.replace( ".sgy", "-line-header.sgy")
+        shutil.copyfile(self.prestack, fname)
+
+        il, xl = TraceField.INLINE_3D, TraceField.CROSSLINE_3D
+        with segyio.open(fname, "r+") as f:
+            f.header.iline[1,2] = { il: 11 }
+            f.header.iline[1,2] = { xl: 13 }
+
+        with segyio.open(fname, "r") as f:
+            self.assertEqual(f.header[0][il], 1)
+            self.assertEqual(f.header[1][il], 11)
+            self.assertEqual(f.header[2][il], 1)
+
+            self.assertEqual(f.header[0][xl], 1)
+            self.assertEqual(f.header[1][xl], 13)
+            self.assertEqual(f.header[2][xl], 2)
+
+
     def test_iline_offset(self):
         with segyio.open(self.prestack, "r") as f:
 
@@ -543,6 +562,50 @@ class TestSegy(TestCase):
             self.assertEqual(f.header[0][TraceField.offset], f.header[1][TraceField.offset])
             self.assertEqual(1, f.header[1][TraceField.offset])
 
+    def test_create_from_naught_prestack(self):
+        fname = "test-data/mk-ps.sgy"
+        spec = segyio.spec()
+        spec.format  = 5
+        spec.sorting = 2
+        spec.samples = 7
+        spec.ilines  = range(1, 4)
+        spec.xlines  = range(1, 3)
+        spec.offsets = range(1, 6)
+
+        cube_size = len(spec.ilines) * len(spec.xlines)
+
+        with segyio.create(fname, spec) as dst:
+            arr = np.arange( start = 0.000,
+                             stop = 0.007,
+                             step = 0.001,
+                             dtype = np.single)
+
+            arr = np.concatenate([[arr + 0.01], [arr + 0.02]], axis = 0)
+            lines = [arr + i for i in spec.ilines]
+            cube = [(off * 100) + line for line in lines for off in spec.offsets]
+
+            dst.iline[:,:] = cube
+
+            for of in spec.offsets:
+                for il in spec.ilines:
+                    dst.header.iline[il,of] = { TraceField.INLINE_3D: il,
+                                                TraceField.offset: of
+                                              }
+                for xl in spec.xlines:
+                    dst.header.xline[xl,of] = { TraceField.CROSSLINE_3D: xl }
+
+        with segyio.open(fname, "r") as f:
+            self.assertAlmostEqual(101.010, f.trace[0][0],  places = 4)
+            self.assertAlmostEqual(101.011, f.trace[0][1],  places = 4)
+            self.assertAlmostEqual(101.016, f.trace[0][-1], places = 4)
+            self.assertAlmostEqual(503.025, f.trace[-1][5], places = 4)
+            self.assertNotEqual(f.header[0][TraceField.offset], f.header[1][TraceField.offset])
+            self.assertEqual(1, f.header[0][TraceField.offset])
+            self.assertEqual(2, f.header[1][TraceField.offset])
+
+            for x, y in itertools.izip(f.iline[:,:], cube):
+                self.assertListEqual(list(x.flatten()), list(y.flatten()))
+
     def test_create_write_lines(self):
         fname = "test-data/mklines.sgy"
 

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