equinor / segyio

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

Feature request: save method #471

Closed gsakkis closed 3 years ago

gsakkis commented 4 years ago

Following up from this comment, I'd like to propose a new SegyFile.save(filename) method that saves the current state of this segy file to filename. The reason is that (a) it's not currently trivial to achieve this and (b) it's apparently different for seismic unix files.

Draft implementation for SegyFile:

    def save(self, filename):
        if os.path.abspath(filename) == os.path.abspath(self._filename):
            self.flush()
        else:
            spec = segyio.tools.metadata(self)
            with segyio.create(filename, spec) as other:
                for i in range(self.ext_headers + 1):
                    other.text[i] = self.text[i]
                other.bin = self.bin
                other.header = self.header
                other.trace = self.trace

By the way it becomes a bit clearer if the text property is made settable:

    @text.setter
    def text(self, value):
        for i in range(self.ext_headers + 1):
            self.text[i] = value[i]

    def save(self, filename):
        if os.path.abspath(filename) == os.path.abspath(self._filename):
            self.flush()
        else:
            spec = segyio.tools.metadata(self)
            with segyio.create(filename, spec) as other:
                other.text = self.text
                other.bin = self.bin
                other.header = self.header
                other.trace = self.trace
jokva commented 3 years ago

Hi,

I'm afraid a save() function is a bit out of segyio's scope. While the occasional high-level feature bleeds through, a generic save-current-state would have to make too many assumptions to ever really be useful. I would argue that the reason writing a save() function is not trivial right now is because of the SEG-Y format itself. For segyio to provide a save() function, it would have to decide what it's version of SEG-Y should look like, and that would alienate too many real-world files.

There are already the from_array family of functions in the tools module that do something similar, and they're really only intended for quickly dumping (basically serializing) experiments to disk, not for writing good files. There are just too many headers that needs to be set (that segyio doesn't need to function) for a file to be healthy.

This is, however, something that is more appropriate in a project like https://github.com/trhallam/segysak

gsakkis commented 3 years ago

Unlike the from_array functions, the proposal is for a SegyFile.save method, not a generic save function: there is already a SegyFile instantiated somehow so it (presumably) knows its version of SEG-Y and every other necessary information. Unless segyio.open(filename) doesn't preserve all the relevant information from filename, I'm not sure why segyio.open(filename).save(new_filename) would need to make any assumptions.

jokva commented 3 years ago

every other necessary information

Except virtually every header word, e.g. coordinates, depths, units, lag, gain, and depth. segyio.open(filename) reads as little information as possible to be able to read data, and makes no (well, few) assumptions to help interpret the data. That's up to the user, and quite different when creating files.