equinor / segyio

Fast Python library for SEGY files.
Other
476 stars 214 forks source link

How can I make a working copy of SEG-Y file? #442

Closed AlexUser97 closed 4 years ago

AlexUser97 commented 4 years ago

How can I make a working copy of sgy file? Code, which indicated in manual isn't working. Program show this error:
'File "D:/1/3.py", line 11, in with segyio.create('3.sgy', spec) as dst: File "C:\Users\Alexandr\AppData\Local\Programs\Python\Python38\lib\site-packages\segyio\create.py", line 182, in create tracecount = spec.tracecount AttributeError: 'spec' object has no attribute 'tracecount'

My version of code is showed below: import segyio import numpy as np from shutil import copyfile with segyio.open('1.sgy', 'r') as f: spec=segyio.spec() spec.sorting=f.sorting spec.format=f.format spec.samples=f.samples spec.ilines=f.ilines spec.xline=f.xlines with segyio.create('3.sgy', spec) as dst: dst.text[0] = f.text[0] dst.bin = f.bin dst.header=f.header dst.trace=f.trace

jokva commented 4 years ago

You did not set spec.tracecount, like the error message indicates.

AlexUser97 commented 4 years ago

How can I install spec.tracecount? To do this, I need to download some module in Python?

jokva commented 4 years ago

It is a member on the 'spec' object you just created.

But since you're copying the file anyway, you can use metadata from tools, instead of manually building the spec object.

https://segyio.readthedocs.io/en/latest/segyio.html#segyio.tools.metadata

gsakkis commented 4 years ago

Hi, I'm trying to create a copy_segy function that works for any sgy file, however it fails for some of the samples under test-data:

# examples/copy-segy.py

import filecmp
import logging
import os
import sys

import segyio

def copy_segy(sourcefile, destfile, **kwargs):
    is_su = os.path.splitext(sourcefile)[1] == ".su"
    open_segy = segyio.su.open if is_su else segyio.open
    with open_segy(sourcefile, **kwargs) as src:
        spec = segyio.tools.metadata(src)
        if is_su:
            del spec.ext_headers
        with segyio.create(destfile, spec) as dst:
            if not is_su:
                for i in range(1 + src.ext_headers):
                    dst.text[i] = src.text[i]
                dst.bin = src.bin
            dst.header = src.header
            dst.trace = src.trace

def main():
    # logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s")
    if len(sys.argv) < 3:
        sys.exit("Usage: {} [source-dir] [destination-dir]".format(sys.argv[0]))
    sourcedir, destdir = map(os.path.normpath, sys.argv[1:])
    for parent, dirs, files in os.walk(sourcedir):
        for file in files:
            sourcefile = os.path.join(parent, file)
            destfile = sourcefile.replace(sourcedir, destdir)
            os.makedirs(os.path.dirname(destfile), exist_ok=True)
            kwargs = {}
            if "lsb" in sourcefile:
                kwargs["endian"] = "lsb"
            if os.path.basename(sourcefile) in ("shot-gather.sgy", "long.sgy"):
                kwargs["ignore_geometry"] = True
            try:
                copy_segy(sourcefile, destfile, **kwargs)
            except Exception as ex:
                logging.exception(f"{sourcefile}: {ex}")
                if os.path.exists(destfile):
                    os.remove(destfile)
            else:
                if filecmp.cmp(sourcefile, destfile):
                    logging.info(f"{sourcefile}: identical copy")
                else:
                    logging.warning(f"{sourcefile}: non-identical copy")

if __name__ == "__main__":
    main()

Output:

$ PYTHONPATH=. python examples/copy-segy.py ../test-data ../test-data-copy

ERROR:root:../test-data/text.sgy: I/O operation failed on trace header 0, likely corrupted file
Traceback (most recent call last):
  File "examples/copy-segy.py", line 42, in main
    copy_segy(sourcefile, destfile, **kwargs)
  File "examples/copy-segy.py", line 13, in copy_segy
    with open_segy(sourcefile, **kwargs) as src:
  File "/home/gsk/projects/ESA/segyio/python/segyio/open.py", line 175, in open
    dt = segyio.tools.dt(f, fallback_dt = 4000.0) / 1000.0
  File "/home/gsk/projects/ESA/segyio/python/segyio/tools.py", line 32, in dt
    return f.xfd.getdt(fallback_dt)
OSError: I/O operation failed on trace header 0, likely corrupted file
WARNING:root:../test-data/small-lsb.su: non-identical copy
WARNING:root:../test-data/long.sgy: non-identical copy
WARNING:root:../test-data/small.su: non-identical copy
/home/gsk/projects/segyio/python/segyio/segy.py:73: UserWarning: Unknown trace value format 4, falling back to ibm float
  warnings.warn(', '.join((problem, solution)))
WARNING:root:../test-data/multiformats/Format4lsb.sgy: non-identical copy
WARNING:root:../test-data/multiformats/Format4msb.sgy: non-identical copy
jokva commented 4 years ago

The files in the test-data dir are all built for very specific testing purposes, and quite a few aren't really valid SEG-Y files, so this isn't too unexpected. I'm not sure what exactly the issue here is supposed to be, but feel free to open an issue if something is unclear or you believe something is wrong.

gsakkis commented 4 years ago

Yes I figured it out for some files, e.g. the Format4*.sgy, though for long.sgy and the two *.su I can't tell if they're invalid or I'm missing something.

I guess my issue can be rephrased as a feature request: add a SegyFile.save(filename) (and sufile.save() if necessary) method. I'll open a new issue for it.