[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