|
3 | 3 |
|
4 | 4 | from __future__ import annotations |
5 | 5 |
|
| 6 | +import logging |
6 | 7 | from datetime import datetime |
7 | 8 | from datetime import timezone |
8 | 9 | from importlib import metadata |
|
25 | 26 | from mdio.segy.utilities import get_grid_plan |
26 | 27 |
|
27 | 28 |
|
| 29 | +logger = logging.getLogger(__name__) |
| 30 | + |
28 | 31 | try: |
29 | 32 | API_VERSION = metadata.version("multidimio") |
30 | 33 | except metadata.PackageNotFoundError: |
@@ -52,6 +55,50 @@ def parse_index_types( |
52 | 55 | return parsed_types |
53 | 56 |
|
54 | 57 |
|
| 58 | +def grid_density_qc(grid: Grid, num_traces: int) -> None: |
| 59 | + """QC for sensible Grid density. |
| 60 | +
|
| 61 | + Basic qc of the grid to check density and provide warning/exception |
| 62 | + when indexing is problematic to provide user with insights to the use. |
| 63 | + If trace density on the specified grid is less than 50% a warning is |
| 64 | + logged. If denisty is less than 1% an exception is raised. |
| 65 | +
|
| 66 | + Args: |
| 67 | + grid: The grid instance to check. |
| 68 | + num_traces: Expected number of traces. |
| 69 | +
|
| 70 | + Raises: |
| 71 | + GridTraceCountError: When the grid is too sparse. |
| 72 | + """ |
| 73 | + grid_traces = np.prod(grid.shape[:-1], dtype=np.uint64) # Exclude sample |
| 74 | + dims = {k: v for k, v in zip(grid.dim_names, grid.shape)} # noqa: B905 |
| 75 | + |
| 76 | + logger.debug(f"Dimensions: {dims}") |
| 77 | + logger.debug(f"num_traces = {num_traces}") |
| 78 | + |
| 79 | + # Extreme case where the grid is very sparse (usually user error) |
| 80 | + if grid_traces > 10 * num_traces: |
| 81 | + for dim_name in grid.dim_names: |
| 82 | + dim_min = grid.get_min(dim_name) |
| 83 | + dim_max = grid.get_max(dim_name) |
| 84 | + logger.warning(f"{dim_name} min: {dim_min} max: {dim_max}") |
| 85 | + |
| 86 | + msg = ( |
| 87 | + f"Grid shape: {grid.shape} but SEG-Y tracecount: {num_traces}. " |
| 88 | + "This grid is very sparse and most likely user error with indexing." |
| 89 | + ) |
| 90 | + raise GridTraceCountError(msg) |
| 91 | + |
| 92 | + # Warning if we have above 50% sparsity. |
| 93 | + if grid_traces > 2 * num_traces: |
| 94 | + msg = ( |
| 95 | + f"Proposed ingestion grid is sparse. Ingestion grid: {dims}. " |
| 96 | + f"SEG-Y trace count:{num_traces}, grid trace count: {grid_traces}." |
| 97 | + ) |
| 98 | + |
| 99 | + logger.warning(msg) |
| 100 | + |
| 101 | + |
55 | 102 | def segy_to_mdio( |
56 | 103 | segy_path: str, |
57 | 104 | mdio_path_or_buffer: str, |
@@ -262,6 +309,9 @@ def segy_to_mdio( |
262 | 309 |
|
263 | 310 | # Make grid and build global live trace mask |
264 | 311 | grid = Grid(dims=dimensions) |
| 312 | + |
| 313 | + grid_density_qc(grid, num_traces) |
| 314 | + |
265 | 315 | grid.build_map(index_headers) |
266 | 316 |
|
267 | 317 | # Check grid validity by comparing trace numbers |
|
0 commit comments