Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
7427454
Update Project.toml
mloubout Jun 21, 2025
5e0be22
add codecov
mloubout Jun 21, 2025
9926a26
Add full dataset scan test
mloubout Jun 21, 2025
9fe1033
Remove xfail from BP scan test and assert actual dataset counts
mloubout Jun 21, 2025
3df66b8
Clarify BP model scan test
mloubout Jun 21, 2025
bbdc534
Merge branch 'master' into codex/implement-python-version-of-package
mloubout Jun 21, 2025
98b1d56
add. codecov token
mloubout Jun 21, 2025
623a432
bump codecov step version
mloubout Jun 21, 2025
f617898
Add flake8 configuration and CI
mloubout Jun 21, 2025
8b166ee
Install flake8 plugin in CI
mloubout Jun 21, 2025
a396fa0
Merge pull request #4 from mloubout/codex/add-flake8-rules-and-ci-con…
mloubout Jun 21, 2025
64a96c7
Enable Codecov PR comments
mloubout Jun 21, 2025
714da09
Merge pull request #5 from mloubout/codex/add-codecov-pr-comment-setup
mloubout Jun 21, 2025
49d16f6
Merge pull request #3 from mloubout/codex/implement-python-version-of…
mloubout Jun 21, 2025
f3a801b
Add BP dataset scanning tutorial
mloubout Jun 21, 2025
2a4b0f5
Rewrite BP scan tutorial in Python
mloubout Jun 21, 2025
98b6be6
Revise BP dataset tutorial
mloubout Jun 22, 2025
44effd6
Add segy_scan utility and update tutorial
mloubout Jun 22, 2025
38c831d
Add lazy SegyScan object and update tutorial
mloubout Jun 22, 2025
b0a8b43
Update BP scan tutorial
mloubout Jun 22, 2025
bdc5913
Fix BP scan tutorial
mloubout Jun 22, 2025
d1c60a3
render notebook
mloubout Jun 22, 2025
c94745f
Merge pull request #6 from mloubout/codex/create-jupyter-notebook-tut…
mloubout Jun 22, 2025
c3ad8e4
Add additional tests for utilities and scanning
mloubout Jun 22, 2025
e10fb96
Merge pull request #7 from mloubout/codex/increase-test-coverage
mloubout Jun 22, 2025
0d8f709
Move imports to module level and fix style
mloubout Jun 23, 2025
8f69bd0
Add numpy dependency
mloubout Jun 23, 2025
64a2fe4
Install package in Python CI
mloubout Jun 23, 2025
62bd484
Merge pull request #8 from mloubout/codex/modify-segy_scan-to-support…
mloubout Jun 23, 2025
3c30e91
Refine header tracking and demo
mloubout Jun 23, 2025
5369a58
Improve object representations
mloubout Jun 23, 2025
6054d27
Include depth in scan source
mloubout Jun 23, 2025
429efed
tweak notebook
mloubout Jun 23, 2025
bb75dbc
Merge pull request #9 from mloubout/codex/add-human-readable-represen…
mloubout Jun 23, 2025
5fa9bdc
docstring format
mloubout Jun 23, 2025
1b4a982
Add async tests and benchmark
mloubout Jun 23, 2025
6eb32dc
Add async benchmark
mloubout Jun 23, 2025
2e8d926
Add logging and use as_completed
mloubout Jun 23, 2025
33cd632
Initialize package logger
mloubout Jun 23, 2025
f9347b0
Refactor logging and tests
mloubout Jun 23, 2025
857df6b
Parallelize header and trace parsing
mloubout Jun 23, 2025
e1b34c7
Improve scan efficiency with threads and asyncio
mloubout Jun 23, 2025
e30dbe2
Refactor scan and read helpers
mloubout Jun 23, 2025
1f5771f
fix pyproject
mloubout Jun 23, 2025
984b606
cleanup
mloubout Jun 23, 2025
6c0138c
Merge pull request #10 from mloubout/codex/improve-efficiency-with-mu…
mloubout Jun 23, 2025
a9e2df2
Clean filesystem API
mloubout Jun 23, 2025
3756cb4
Add fsspec dependency and fix flake8
mloubout Jun 23, 2025
5b4888d
Merge pull request #11 from mloubout/codex/extend-python-implementati…
mloubout Jun 24, 2025
16f8e33
Switch SegyScan serialization to cloudpickle
mloubout Jun 24, 2025
92f7484
Merge pull request #12 from mloubout/codex/add-utility-to-save-and-lo…
mloubout Jun 24, 2025
d2dc3ce
Update scan utilities and tutorial
mloubout Jun 24, 2025
3fd2a95
Add receiver coordinates utility
mloubout Jun 24, 2025
e06e982
Cache raw data in ShotRecord
mloubout Jun 24, 2025
f12636f
cleanup
mloubout Jun 24, 2025
af682a9
Merge pull request #13 from mloubout/codex/update-shotrecord-and-segy…
mloubout Jun 24, 2025
40acc40
tweak data
mloubout Jun 24, 2025
ef4d289
Fix __all__ spacing
mloubout Jun 24, 2025
111b131
Read segy files in chunks
mloubout Jun 24, 2025
7545812
tweak logger
mloubout Jun 24, 2025
dba27ec
remove unused
mloubout Jun 24, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .codecov.yml
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
comment: false
comment:
layout: "reach, diff, flags, files"
behavior: default
require_changes: true
20 changes: 20 additions & 0 deletions .github/workflows/flake8.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: Flake8

on:
pull_request:
push:
branches: [master]

jobs:
flake8:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: '3.10'
- name: Install flake8
run: python -m pip install flake8 flake8-pyproject
- name: Run flake8
run: flake8
37 changes: 34 additions & 3 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,49 @@ jobs:
fail-fast: false

matrix:
version: ['1.6', '1.7', '1.8', '1.9', '1.10']
version: ['1', 'lts']
os: [ubuntu-latest, macos-latest]

steps:
- name: Checkout SegyIO
uses: actions/checkout@v2

- name: Setup julia
uses: julia-actions/setup-julia@v1
uses: julia-actions/setup-julia@v2
with:
version: ${{ matrix.version }}
arch: x64

- name: Run tests
uses: julia-actions/julia-runtest@master
uses: julia-actions/julia-runtest@latest
with:
annotate: true

- uses: julia-actions/julia-processcoverage@v1

- uses: codecov/codecov-action@v4
with:
file: lcov.info
token: ${{ secrets.CODECOV_TOKEN }}

python-tests:
name: Python tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: '3.10'
- name: Install package
run: python -m pip install -e .
- name: Install dependencies
run: python -m pip install pytest pytest-cov codecov
- name: Run tests with coverage
run: pytest -vs --cov=pysegy --cov-report=xml
- name: Upload coverage
uses: codecov/codecov-action@v4
with:
fail_ci_if_error: true
files: coverage.xml
token: ${{ secrets.CODECOV_TOKEN }}
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
*.jl.cov
*.jl.*.cov
*.jl.mem
__pycache__/
pysegy/__pycache__/
pysegy/tests/__pycache__/
.coverage
coverage.xml
htmlcov/
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "SegyIO"
uuid = "157a0f19-4d44-4de5-a0d0-07e2f0ac4dfa"
authors = ["Henryk Modzelewski <henryk_modzelewski@mac.com>"]
authors = ["Henryk Modzelewski <henryk_modzelewski@mac.com>", "Mathias Louboutin <mathias@devitocodes.com>"]
version = "0.8.5"

[deps]
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,5 @@ SegyIO is a registered package and can be installed directly from the julia pack
## Extension

SegyIO is implemented for POSIX systems. For Cloud storage, use [CloudSegyIO.jl](https://github.com/slimgroup/CloudSegyIO.jl), the Cloud storage extension of SegyIO.

A minimal Python implementation of the core reader and writer is available in the `pysegy/` directory. Tests for this version run on GitHub Actions with coverage reporting via Codecov.
20 changes: 20 additions & 0 deletions benchmarks/scan_benchmark.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import os
import time
import pysegy as seg

DATA_DIR = os.path.join(os.path.dirname(__file__), '..', 'data')
PATTERN = 'overthrust_2D_shot_*.segy'


def main():
t0 = time.perf_counter()
seg.segy_scan(DATA_DIR, PATTERN, threads=1)
t1 = time.perf_counter()
seg.segy_scan(DATA_DIR, PATTERN)
t2 = time.perf_counter()
print(f"Sequential: {t1 - t0:.3f}s")
print(f"Threaded: {t2 - t1:.3f}s")


if __name__ == '__main__':
main()
350 changes: 350 additions & 0 deletions notebooks/bp_scan_tutorial.ipynb

Large diffs are not rendered by default.

46 changes: 46 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
[build-system]
requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "pysegy"
dynamic = ["version"]
description = "Minimal Python implementation of SegyIO"
authors = [
{ name = "Mathias Louboutin", email = "mathias@devitocodes.com" },
]
readme = "README.md"
requires-python = ">=3.10"
classifiers = [
"Programming Language :: Python :: 3",
]
license = { file = "LICENSE" }
dependencies = [
"numpy>=2,<3",
"fsspec>=2024.3",
"cloudpickle>=3",
]

[project.optional-dependencies]
dev = ["flake8", "flake8-pyproject"]

[tool.setuptools_scm]
fallback_version = "0+untagged"

[tool.pytest.ini_options]
addopts = "-v"
testpaths = ["pysegy/tests"]

[tool.flake8]
max-line-length = 90
ignore = [
"F403","E226","E731","E275",
"W503","F405","E722","E741",
"W504","W605"
]
exclude = [ ".github" ]

[tool.setuptools.packages.find]
where = ["."]
include = ["pysegy*"]

52 changes: 52 additions & 0 deletions pysegy/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
"""Minimal Python port of SegyIO.jl."""
# flake8: noqa

import logging


logger = logging.getLogger('pysegy')
stream_handler = logging.StreamHandler()
logger.addHandler(stream_handler)

from .types import (
BinaryFileHeader,
BinaryTraceHeader,
FileHeader,
SeisBlock,
)
from .read import (
read_fileheader,
read_traceheader,
read_file,
segy_read,
)
from .scan import SegyScan, segy_scan, save_scan, load_scan
from .write import (
write_fileheader,
write_traceheader,
write_block,
segy_write,
)
from .utils import get_header

__all__ = [
"BinaryFileHeader",
"BinaryTraceHeader",
"FileHeader",
"SeisBlock",
"SegyScan",
"read_fileheader",
"read_traceheader",
"read_file",
"segy_read",
"segy_scan",
"save_scan",
"load_scan",
"write_fileheader",
"write_traceheader",
"write_block",
"segy_write",
"get_header",
]

logging.basicConfig(level=logging.INFO)
67 changes: 67 additions & 0 deletions pysegy/ibm.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
"""
Conversion helpers between IBM and IEEE floating point formats.
"""

from typing import Union


def ibm_to_ieee(value: Union[bytes, bytearray, int]) -> float:
"""
Convert a 4-byte IBM floating point number to ``float``.

Parameters
----------
value : bytes or int
Input value encoded in the IBM 32-bit floating point format.

Returns
-------
float
Floating point number in IEEE representation.
"""
if isinstance(value, (bytes, bytearray)):
if len(value) != 4:
raise ValueError("IBM float must be 4 bytes")
val = int.from_bytes(value, byteorder='big', signed=False)
else:
val = value & 0xffffffff
if val == 0:
return 0.0
sign = 1 if (val >> 31) == 0 else -1
exponent = (val >> 24) & 0x7f
fraction = val & 0x00ffffff
# IBM exponent is base 16 biased by 64
mant = fraction / float(0x01000000)
return sign * mant * 16 ** (exponent - 64)


def ieee_to_ibm(f: float) -> bytes:
"""
Convert ``float`` to IBM 32-bit floating point bytes.

Parameters
----------
f : float
Numeric value in IEEE representation.

Returns
-------
bytes
The value encoded using the IBM format.
"""
if f == 0.0:
return b"\x00\x00\x00\x00"
sign = 0
if f < 0:
sign = 0x80
f = -f
exponent = 64
while f < 1.0:
f *= 16.0
exponent -= 1
while f >= 16.0:
f /= 16.0
exponent += 1
fraction = int(f * 0x01000000) & 0x00ffffff
val = (sign << 24) | (exponent << 24) | fraction
return val.to_bytes(4, byteorder='big')
Loading
Loading