Add seismic geometry abstractions
Opened this issue · 0 comments
tasansal commented
It would be nice to have geometry abstractions for standard interface and custom / geometry specific exception handling.
This has the following pros:
- Common interface for coordinate conversions.
- Trace iterators based on the type of data.
- Enforce usage of methods for geometry instances that may be added later.
- Improve maintainability.
- Allow custom things to be added, i.e., for shots, we add the conversion from unwrapped channels to wrapped channels
unwrap_channels,
and we still have a base implementation that should follow the extensible interface. - Encapsulate the logic for geometry specific chunk size and access pattern configurations
Long shot, but cython
or numba
jit versions may be even better. xarray
can also be used to handle named dimensions etc.
Would inherit from a base class like
# mdio/segy/geometry.py
from abc import ABC
class SeismicGeometry(ABC):
def __init__(self, args, kwargs):
...
@abstractmethod
def __iter__(self):
...
@abstractmethod
def __getitem__(self):
...
@abstractmethod
def xy_to_grid(self, x, y, method="nearest"):
...
@property
@abstractmethod
def num_traces(self):
...
Then we would have 3D as something like
from mdio.segy.geometry import SeismicGeometry
class SeismicStack3d(SeismicGeometry):
def __init__(self, inlines, crosslines, samples):
# set attributes, initialize grid etc.
def __iter__(self):
# logic to iterate traces on spatial il/xl grid
@abstractmethod
def xy_to_grid(self, x, y, method="nearest"):
# logic to convert CDP-X CDP-Y to inline and crossline
@property
def num_traces(self):
return self.get_size("inline") * self.get_size("crossline")
Or 3D shots like
from mdio.segy.geometry import SeismicGeometry
class SeismicShot3d(SeismicGeometry):
def __init__(self, shots, cables, channels, samples):
# set attributes, initialize grid etc.
def __iter__(self):
# logic to iterate traces on shot grid
@abstractmethod
def xy_to_grid(self, x, y, method="nearest"):
# logic to convert SHOT-X SHOT-Y to shot number
@property
def num_traces(self):
return self.get_size("shot") * self.get_size("cable") * self.get_size("channel")
@def unwrap_channels(self, channels_per_streamer: int):
return self.channel % channels_per_streamer + 1
and so on.