[segyio] 212/376: segy.attributes - file-wide header read
Jørgen Kvalsvik
jokva-guest at moszumanska.debian.org
Wed Sep 20 08:04:35 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 a72e77bca0e70eb62d7003d917a343aaff1a3f70
Author: Jørgen Kvalsvik <jokva at statoil.com>
Date: Fri Feb 24 15:45:33 2017 +0100
segy.attributes - file-wide header read
The new function segy.attribute leverages the segy_field_forall function
to support reading some field across the full file or parts of the file.
Uses cases include learning things about a new file, make assumptions on
structure and plot ensembles, CDP etc.
The interface is designed to quickly give control to numpy or other
third-party libs, and the return value is always an array or a simple
value. Supports looking up attributes for a single trace, a range (via
slice operations [start:stop:step]) or lists of indices.
---
python/segyio/_segyio.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++++
python/segyio/segy.py | 53 +++++++++++++++++++++
python/test/segy.py | 41 ++++++++++++++++
3 files changed, 216 insertions(+)
diff --git a/python/segyio/_segyio.c b/python/segyio/_segyio.c
index 2cc1ccc..73c904c 100644
--- a/python/segyio/_segyio.c
+++ b/python/segyio/_segyio.c
@@ -480,6 +480,126 @@ static PyObject *py_write_trace_header(PyObject *self, PyObject *args) {
}
}
+static PyObject *py_field_forall(PyObject *self, PyObject *args ) {
+ errno = 0;
+ PyObject *file_capsule = NULL;
+ PyObject *buffer_out;
+ int start, stop, step;
+ long trace0;
+ int trace_bsize;
+ int field;
+
+ PyArg_ParseTuple(args, "OOiiiili", &file_capsule,
+ &buffer_out,
+ &start,
+ &stop,
+ &step,
+ &field,
+ &trace0,
+ &trace_bsize );
+
+ segy_file* fp = get_FILE_pointer_from_capsule(file_capsule);
+
+ if (PyErr_Occurred()) { return NULL; }
+
+ if (!PyObject_CheckBuffer(buffer_out)) {
+ PyErr_SetString(PyExc_TypeError, "The destination buffer is not of the correct type.");
+ return NULL;
+ }
+
+ Py_buffer buffer;
+ PyObject_GetBuffer(buffer_out, &buffer, PyBUF_FORMAT | PyBUF_C_CONTIGUOUS | PyBUF_WRITEABLE);
+
+ int error = segy_field_forall( fp,
+ field,
+ start,
+ stop,
+ step,
+ buffer.buf,
+ trace0,
+ trace_bsize );
+
+ int errorno = errno;
+
+ PyBuffer_Release( &buffer );
+ if( error != SEGY_OK ) {
+ return py_handle_segy_error( error, errno );
+ }
+
+ Py_IncRef(buffer_out);
+ return buffer_out;
+}
+
+static PyObject *py_field_foreach(PyObject *self, PyObject *args ) {
+ errno = 0;
+ PyObject *file_capsule = NULL;
+ PyObject *buffer_out;
+ PyObject *indices;
+ int field;
+ long trace0;
+ int trace_bsize;
+
+ PyArg_ParseTuple(args, "OOOili", &file_capsule,
+ &buffer_out,
+ &indices,
+ &field,
+ &trace0,
+ &trace_bsize );
+
+ segy_file* fp = get_FILE_pointer_from_capsule(file_capsule);
+
+ if (PyErr_Occurred()) { return NULL; }
+
+ if (!PyObject_CheckBuffer(buffer_out)) {
+ PyErr_SetString(PyExc_TypeError, "The destination buffer is not of the correct type.");
+ return NULL;
+ }
+
+ if (!PyObject_CheckBuffer(indices)) {
+ PyErr_SetString(PyExc_TypeError, "The indices buffer is not of the correct type.");
+ return NULL;
+ }
+
+ Py_buffer bufout;
+ PyObject_GetBuffer(buffer_out, &bufout, PyBUF_FORMAT | PyBUF_C_CONTIGUOUS | PyBUF_WRITEABLE);
+
+ Py_buffer bufindices;
+ PyObject_GetBuffer(indices, &bufindices, PyBUF_FORMAT | PyBUF_C_CONTIGUOUS);
+
+ int len = bufindices.len / bufindices.itemsize;
+ if( bufout.len / bufout.itemsize != len ) {
+ PyErr_SetString(PyExc_ValueError, "Attributes array length != indices" );
+ PyBuffer_Release( &bufout );
+ PyBuffer_Release( &bufindices );
+ return NULL;
+ }
+
+ int err = 0;
+ const int* ind = bufindices.buf;
+ int* out = bufout.buf;
+ for( int i = 0; i < len; ++i ) {
+ err = segy_field_forall( fp, field,
+ ind[ i ],
+ ind[ i ] + 1,
+ 1,
+ out + i,
+ trace0,
+ trace_bsize );
+
+ if( err != SEGY_OK ) {
+ PyBuffer_Release( &bufout );
+ PyBuffer_Release( &bufindices );
+ return py_handle_segy_error( err, errno );
+ }
+ }
+
+ PyBuffer_Release( &bufout );
+ PyBuffer_Release( &bufindices );
+
+ Py_IncRef(buffer_out);
+ return buffer_out;
+}
+
static PyObject *py_trace_bsize(PyObject *self, PyObject *args) {
errno = 0;
int sample_count;
@@ -1031,6 +1151,8 @@ static PyMethodDef SegyMethods[] = {
{"empty_traceheader", (PyCFunction) py_empty_trace_header, METH_NOARGS, "Create empty trace header for a segy file."},
{"read_traceheader", (PyCFunction) py_read_trace_header, METH_VARARGS, "Read a trace header from a segy file."},
{"write_traceheader", (PyCFunction) py_write_trace_header, METH_VARARGS, "Write a trace header to a segy file."},
+ {"field_forall", (PyCFunction) py_field_forall, METH_VARARGS, "Read a single attribute from a set of headers."},
+ {"field_foreach", (PyCFunction) py_field_foreach, METH_VARARGS, "Read a single attribute from a set of headers, given by a list of indices."},
{"trace_bsize", (PyCFunction) py_trace_bsize, METH_VARARGS, "Returns the number of bytes in a trace."},
{"get_field", (PyCFunction) py_get_field, METH_VARARGS, "Get a header field."},
diff --git a/python/segyio/segy.py b/python/segyio/segy.py
index 5f42234..4ceebd2 100644
--- a/python/segyio/segy.py
+++ b/python/segyio/segy.py
@@ -290,6 +290,59 @@ class SegyFile(object):
for i, v in zip(range(self.tracecount), val):
h[i, buf] = v
+ def attributes(self, field):
+ """ File-wide attribute (header word) reading
+
+ A range-oriented function that reads some attribute for all the
+ specified headers file-wide. Supports index lookup, slices and
+ numpy-style list-of-indices.
+
+ Examples:
+ Read all unique sweep frequency end::
+ >>> end = segyio.TraceField.SweepFrequencyEnd
+ >>> sfe = np.unique(f.attributes( end )[:])
+
+ Discover the first traces of each unique sweep frequency end::
+ >>> end = segyio.TraceField.SweepFrequencyEnd
+ >>> attrs = f.attributes(end)
+ >>> sfe, tracenos = np.unique(attrs[:], return_index = True)
+
+ Scatter plot group x/y-coordinates with SFEs (using matplotlib)::
+ >>> end = segyio.TraceField.SweepFrequencyEnd
+ >>> attrs = f.attributes(end)
+ >>> _, tracenos = np.unique(attrs[:], return_index = True)
+ >>> gx = f.attributes(segyio.TraceField.GroupX)[tracenos]
+ >>> gy = f.attributes(segyio.TraceField.GroupY)[tracenos]
+ >>> scatter(gx, gy)
+ """
+ class attr:
+ def __getitem__(inner, rng):
+ try: iter(rng)
+ except TypeError: pass
+ else: return inner._getitem_list(rng)
+
+ if not isinstance(rng, slice):
+ rng = slice(rng, rng + 1, 1)
+
+ traces = self.tracecount
+ start, stop, step = rng.indices(traces)
+ attrs = np.empty(len(range(*rng.indices(traces))), dtype = np.intc)
+ return _segyio.field_forall(self.xfd, attrs,
+ start, stop, step, field,
+ self._tr0, self._bsz)
+
+ def _getitem_list(inner, xs):
+ if not isinstance(xs, np.ndarray):
+ xs = np.asarray(xs, dtype = np.intc)
+
+ xs = xs.astype(dtype = np.intc, order = 'C', copy = False)
+ attrs = np.empty(len(xs), dtype = np.intc)
+ return _segyio.field_foreach(self.xfd, attrs, xs, field,
+ self._tr0, self._bsz)
+
+ return attr()
+
+
@property
def trace(self):
""" Interact with segy in trace mode.
diff --git a/python/test/segy.py b/python/test/segy.py
index 439caf3..88ae144 100644
--- a/python/test/segy.py
+++ b/python/test/segy.py
@@ -232,6 +232,47 @@ class TestSegy(TestCase):
self.assertEqual(f.header[1][xl], 13)
self.assertEqual(f.header[2][xl], 2)
+ def test_attributes(self):
+ with segyio.open(self.filename) as f:
+ il = TraceField.INLINE_3D
+ xl = TraceField.CROSSLINE_3D
+
+ self.assertEqual(1, f.attributes(il)[0])
+ self.assertEqual(20, f.attributes(xl)[0])
+
+ ils = [(i // 5) + 1 for i in range(25)]
+ attrils = list(map(int, f.attributes(il)[:]))
+ self.assertListEqual(ils, attrils)
+
+ xls = [(i % 5) + 20 for i in range(25)]
+ attrxls = list(map(int, f.attributes(xl)[:]))
+ self.assertListEqual(xls, attrxls)
+
+ ils = [(i // 5) + 1 for i in range(25)][::-1]
+ attrils = list(map(int, f.attributes(il)[::-1]))
+ self.assertListEqual(ils, attrils)
+
+ xls = [(i % 5) + 20 for i in range(25)][::-1]
+ attrxls = list(map(int, f.attributes(xl)[::-1]))
+ self.assertListEqual(xls, attrxls)
+
+ ils = [(i // 5) + 1 for i in range(25)][1:21:3]
+ attrils = list(map(int, f.attributes(il)[1:21:3]))
+ self.assertListEqual(ils, attrils)
+
+ xls = [(i % 5) + 20 for i in range(25)][2:17:5]
+ attrxls = list(map(int, f.attributes(xl)[2:17:5]))
+ self.assertListEqual(xls, attrxls)
+
+ ils = [1, 2, 3, 4, 5]
+ attrils = list(map(int, f.attributes(il)[[0, 5, 11, 17, 23]]))
+ self.assertListEqual(ils, attrils)
+
+ ils = [1, 2, 3, 4, 5]
+ indices = np.asarray([0, 5, 11, 17, 23])
+ attrils = list(map(int, f.attributes(il)[indices]))
+ self.assertListEqual(ils, attrils)
+
def test_iline_offset(self):
with segyio.open(self.prestack, "r") as f:
--
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