Merge branch 'rewrite' into header

This commit is contained in:
Robert Smallshire
2015-02-27 16:23:35 +01:00
15 changed files with 494 additions and 11 deletions
+32
View File
@@ -0,0 +1,32 @@
The SEG Y file format is one of several standards developed by the Society of Exploration Geophysicists for storing
geophysical seismic data. It is an open standard, and is controlled by the SEG Technical Standards Committee, a
non-profit organization.
This project aims to implement an open SEG Y module in Python for transporting seismic data between SEG Y files and
Python data structures in pure Python.
Status
======
*Segpy 2* is currently in alpha, so expect rough edges. That said, it seems to broadly work and is largely feature
complete.
What It Does
============
How To Get It
=============
*Segpy* is available on the Python Package index and can be installed with ``pip``::
$ pip install segpy
Requirements
============
*Segpy 2* work with Python 3.2 and higher (and 2.7 for now). For the majority of use *Segpy 2* has no external
dependencies. Optional modules with further dependencies such as *Numpy* are included in the ``segpy.ext`` package of
extras.
+11 -4
View File
@@ -1,6 +1,6 @@
=====
Segpy
=====
=======
Segpy 2
=======
Status
======
@@ -18,4 +18,11 @@ geophysical seismic data. It is an open standard, and is controlled by the SEG T
non-profit organization.
This project aims to implement an open SEG Y module in Python for transporting seismic data between SEG Y files and
Numpy arrays. Segpy is a package for reading, writing and manipulating SEG Y data in pure Python.
Python data structures in pure Python.
Segpy Versions
==============
Segpy 2.0 is a complete re-imagining of a SEG Y reader in Python and represents a complete break from Segpy 1.0 in terms
of the interface it presents to clients and the implementation behind those interfaces. Segpy 1.0 should be considered
unmaintained legacy software. The present and future of Segpy is Segpy 2.
+137
View File
@@ -0,0 +1,137 @@
"""Extract a timeslice from a 3D seismic volume to a Numpy array.
Usage: timeslice.py [-h] [--dtype DTYPE] [--null NULL]
segy-file npy-file slice-index
Positional arguments:
segy-file Path to an existing SEG Y file of 3D seismic data
npy-file Path to the Numpy array file to be created for the timeslice
slice-index Zero based index of the time slice to be extracted
Optional arguments:
-h, --help show this help message and exit
--dtype DTYPE Numpy data type. If not provided a dtype compatible with the
SEG Y data will be used.
--null NULL Sample value to use for missing or short traces.
Example:
timeslice.py stack_final_int8.sgy slice_800.npy 800 --null=42.0 --dtype=f
"""
from __future__ import print_function
import argparse
import os
import sys
import traceback
import numpy as np
from segpy.reader import create_reader
from segpy_numpy.numpy.dtypes import make_dtype
class DimensionalityError(Exception):
pass
def extract_timeslice(segy_filename, out_filename, slice_index, dtype=None, null=0):
"""Extract a timeslice from a 3D SEG Y file to a Numpy NPY file.
Args:
segy_filename: Filename of a SEG Y file.
out_filename: Filename of the NPY file.
slice_index: The zero-based index (increasing with depth) of the slice to be extracted.
dtype: Optional Numpy dtype for the result array. If not provided a dtype compatible with
the SEG Y data will be used.
null: Optional sample value to use for missing or short traces. Defaults to zero.
"""
with open(segy_filename, 'rb') as segy_file:
segy_reader = create_reader(segy_file)
if dtype is None:
dtype = make_dtype(segy_reader.data_sample_format)
if segy_reader.dimensionality != 3:
raise DimensionalityError("Cannot slice {n} dimensional seismic.".format(segy_reader.dimensionality))
i_line_range = segy_reader.inline_range()
x_line_range = segy_reader.xline_range()
i_size = len(i_line_range)
x_size = len(x_line_range)
t_size = segy_reader.max_num_trace_samples()
if not (0 <= slice_index < t_size):
raise ValueError("Time slice index {0} out of range {} to {}".format(slice_index, 0, t_size))
timeslice = np.full((x_size, i_size), null, dtype)
for inline_num, xline_num in segy_reader.inline_xline_numbers():
trace_index = segy_reader.trace_index((inline_num, xline_num))
trace = segy_reader.trace_samples(trace_index)
try:
sample = trace[slice_index]
except IndexError:
sample = null
i_index = inline_num - i_line_range.start
x_index = xline_num - x_line_range.start
timeslice[x_index, i_index] = sample
np.save(out_filename, timeslice)
def nullable_dtype(s):
return None if s == "" else np.dtype(s)
def main(argv=None):
parser = argparse.ArgumentParser()
parser.add_argument("segy_file", metavar="segy-file",
help="Path to an existing SEG Y file of 3D seismic data")
parser.add_argument("npy_file", metavar="npy-file",
help="Path to the Numpy array file to be created for the timeslice")
parser.add_argument("slice_index", metavar="slice-index", type=int,
help="Zero based index of the time slice to be extracted", )
parser.add_argument("--dtype", type=nullable_dtype, default="",
help="Numpy data type. If not provided a dtype compatible with the SEG Y data will be used.")
parser.add_argument("--null", type=float, default=0.0,
help="Sample value to use for missing or short traces.")
if argv is None:
argv = sys.argv[1:]
args = parser.parse_args(argv)
try:
extract_timeslice(args.segy_file,
args.npy_file,
args.slice_index,
args.dtype,
args.null)
except (FileNotFoundError, IsADirectoryError) as e:
print(e, file=sys.stderr)
return os.EX_NOINPUT
except PermissionError as e:
print(e, file=sys.stderr)
return os.EX_NOPERM
except Exception as e:
traceback.print_exception(type(e), e, e.__traceback__, file=sys.stderr)
return os.EX_SOFTWARE
return os.EX_OK
if __name__ == '__main__':
sys.exit(main())
+20
View File
@@ -0,0 +1,20 @@
Segpy-Numpy offers tools for working with both *Segpy* and *Numpy*. See the *Segpy* documentation for further details.
What It Does
============
How To Get It
=============
*Segpy-Numpy* is available on the Python Package index and can be installed with ``pip``::
$ pip install segpy-numpy
Requirements
============
*Segpy-Numpy* should work with Python 3.2 and higher (and 2.7 for now). For the majority of use *Segpy 2* has no
externaldependencies. Optional modules with further dependencies such as *Numpy* are included in the ``segpy.ext``
package of extras.
+1
View File
@@ -0,0 +1 @@
@@ -0,0 +1,10 @@
print("segpy_numpy.__init__ imported")
from pkgutil import extend_path
#__path__ = extend_path(__path__, __name__)
__version__ = '2.0.0a1'
def load():
pass
@@ -0,0 +1 @@
@@ -2,11 +2,11 @@
import numpy
NUMPY_DTYPES = {'ibm': numpy.dtype('f4'),
'l': numpy.dtype('i4'),
'h': numpy.dtype('i2'),
'f': numpy.dtype('f4'),
'b': numpy.dtype('i1')}
NUMPY_DTYPES = {'ibm': numpy.dtype('f4'),
'int32': numpy.dtype('i4'),
'int16': numpy.dtype('i2'),
'float32': numpy.dtype('f4'),
'int8': numpy.dtype('i1')}
def make_dtype(data_sample_format):
+5
View File
@@ -0,0 +1,5 @@
[bdist_wheel]
# This flag says that the code is written to work on both Python 2 and Python
# 3. If at all possible, it is good practice to do this. If you cannot, you
# will need to generate wheels for each Python version that you support.
universal=1
+127
View File
@@ -0,0 +1,127 @@
import io
import os
import re
from setuptools import setup, find_packages # Always prefer setuptools over distutils
from codecs import open # To use a consistent encoding
from os import path
def read(*names, **kwargs):
with io.open(
os.path.join(os.path.dirname(__file__), *names),
encoding=kwargs.get("encoding", "utf8")
) as fp:
return fp.read()
def find_version(*file_paths):
version_file = read(*file_paths)
version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]",
version_file, re.M)
if version_match:
return version_match.group(1)
raise RuntimeError("Unable to find version string.")
here = path.abspath(path.dirname(__file__))
def local_file(name):
return os.path.join(here, name)
# Get the long description from the relevant file
with open(local_file('DESCRIPTION.rst'), encoding='utf-8') as f:
long_description = f.read()
setup(
name='segpy-numpy',
# Versions should comply with PEP440. For a discussion on single-sourcing
# the version across setup.py and the project code, see
# https://packaging.python.org/en/latest/single_source_version.html
version=find_version("segpy_numpy/__init__.py"),
description='Interoperability between Numpy with Segpy.',
long_description=long_description,
# The project's main homepage.
url='https://github.com/rob-smallshire/segpy',
# Author details
author='Robert Smallshire',
author_email='robert@smallshire.org.uk',
# Choose your license
license='GPL',
# See https://pypi.python.org/pypi?%3Aaction=list_classifiers
classifiers=[
# How mature is this project? Common values are
# 3 - Alpha
# 4 - Beta
# 5 - Production/Stable
'Development Status :: 3 - Alpha',
# Indicate who your project is intended for
'Intended Audience :: Developers',
'Topic :: Scientific/Engineering',
'Topic :: Software Development :: Libraries',
# Pick your license as you wish (should match "license" above)
'License :: OSI Approved :: MIT License',
# Specify the Python versions you support here. In particular, ensure
# that you indicate whether you support Python 2, Python 3 or both.
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
],
# What does your project relate to?
keywords='seismic geocomputing geophysics numpy',
# You can just specify the packages manually here if your project is
# simple. Or you can use find_packages().
packages=find_packages(here, exclude=['segpy', 'contrib', 'docs', 'test*']),
# List run-time dependencies here. These will be installed by pip when your
# project is installed. For an analysis of "install_requires" vs pip's
# requirements files see:
# https://packaging.python.org/en/latest/requirements.html
install_requires=['numpy'],
# List additional groups of dependencies here (e.g. development dependencies).
# You can install these using the following syntax, for example:
# $ pip install -e .[dev,test]
extras_require = {
'dev': ['check-manifest', 'wheel'],
'doc': ['sphinx', 'cartouche'],
'test': ['coverage', 'hypothesis'],
},
# If there are data files included in your packages that need to be
# installed, specify them here. If using Python 2.6 or less, then these
# have to be included in MANIFEST.in as well.
package_data={
},
# Although 'package_data' is the preferred approach, in some case you may
# need to place data files outside of your packages.
# see http://docs.python.org/3.4/distutils/setupscript.html#installing-additional-files
# In this case, 'data_file' will be installed into '<sys.prefix>/my_data'
data_files=[],
# To provide executable scripts, use entry points in preference to the
# "scripts" keyword. Entry points provide cross-platform support and allow
# pip to create the appropriate form of executable for the target platform.
# Declare entry-points to modules.
entry_points={
'segpy.ext': 'segpy-numpy = segpy_numpy'
},
)
+1 -1
View File
@@ -1 +1 @@
__version__ = '2.0.0a1'
+19
View File
@@ -1 +1,20 @@
import pkg_resources
loaded = set()
def load_entry_points(name=None):
"""Load extension packages into the segpy.ext namespace.
Any packages registered against the 'segpy.ext' entry-point group will be
installed dynamically into the segpy.ext namespace.
"""
for entry_point in pkg_resources.iter_entry_points(group='segpy.ext', name=name):
package = entry_point.load()
if package not in loaded:
loaded.add(package)
__path__.extend(package.__path__)
package.load()
load_entry_points()
+5
View File
@@ -0,0 +1,5 @@
[bdist_wheel]
# This flag says that the code is written to work on both Python 2 and Python
# 3. If at all possible, it is good practice to do this. If you cannot, you
# will need to generate wheels for each Python version that you support.
universal=1
+119
View File
@@ -0,0 +1,119 @@
import io
import os
import re
from setuptools import setup, find_packages # Always prefer setuptools over distutils
from codecs import open # To use a consistent encoding
from os import path
def read(*names, **kwargs):
with io.open(
os.path.join(os.path.dirname(__file__), *names),
encoding=kwargs.get("encoding", "utf8")
) as fp:
return fp.read()
def find_version(*file_paths):
version_file = read(*file_paths)
version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]",
version_file, re.M)
if version_match:
return version_match.group(1)
raise RuntimeError("Unable to find version string.")
here = path.abspath(path.dirname(__file__))
# Get the long description from the relevant file
with open(path.join(here, 'DESCRIPTION.rst'), encoding='utf-8') as f:
long_description = f.read()
setup(
name='segpy',
# Versions should comply with PEP440. For a discussion on single-sourcing
# the version across setup.py and the project code, see
# https://packaging.python.org/en/latest/single_source_version.html
version=find_version("segpy/__init__.py"),
description='Transfer of seismic data to and from SEG Y files',
long_description=long_description,
# The project's main homepage.
url='https://github.com/rob-smallshire/segpy',
# Author details
author='Robert Smallshire',
author_email='robert@smallshire.org.uk',
# Choose your license
license='GPL',
# See https://pypi.python.org/pypi?%3Aaction=list_classifiers
classifiers=[
# How mature is this project? Common values are
# 3 - Alpha
# 4 - Beta
# 5 - Production/Stable
'Development Status :: 3 - Alpha',
# Indicate who your project is intended for
'Intended Audience :: Developers',
'Topic :: Scientific/Engineering',
'Topic :: Software Development :: Libraries',
# Pick your license as you wish (should match "license" above)
'License :: OSI Approved :: MIT License',
# Specify the Python versions you support here. In particular, ensure
# that you indicate whether you support Python 2, Python 3 or both.
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
],
# What does your project relate to?
keywords='seismic geocomputing geophysics',
# You can just specify the packages manually here if your project is
# simple. Or you can use find_packages().
packages=find_packages(exclude=['contrib', 'docs', 'test*']),
# List run-time dependencies here. These will be installed by pip when your
# project is installed. For an analysis of "install_requires" vs pip's
# requirements files see:
# https://packaging.python.org/en/latest/requirements.html
install_requires=[],
# List additional groups of dependencies here (e.g. development dependencies).
# You can install these using the following syntax, for example:
# $ pip install -e .[dev,test]
extras_require = {
'dev': ['check-manifest', 'wheel'],
'doc': ['sphinx', 'cartouche'],
'test': ['coverage', 'hypothesis'],
},
# If there are data files included in your packages that need to be
# installed, specify them here. If using Python 2.6 or less, then these
# have to be included in MANIFEST.in as well.
package_data={
},
# Although 'package_data' is the preferred approach, in some case you may
# need to place data files outside of your packages.
# see http://docs.python.org/3.4/distutils/setupscript.html#installing-additional-files
# In this case, 'data_file' will be installed into '<sys.prefix>/my_data'
data_files=[],
# To provide executable scripts, use entry points in preference to the
# "scripts" keyword. Entry points provide cross-platform support and allow
# pip to create the appropriate form of executable for the target platform.
entry_points={
'console_scripts': [
],
},
)
+1 -1
View File
@@ -15,7 +15,7 @@ class TestBatched(unittest.TestCase):
self.assertTrue(all(len(batch) == batch_size for batch in batches[:-1]))
@given([int],
integers_in_range(1, 1000))
integers_in_range(1, 1000))
def test_final_batch_sizes(self, items, batch_size):
assume(len(items) > 0)
assume(batch_size > 0)