3737from mdio .ingestion .segy .validation import _validate_spec_in_template
3838from mdio .segy import blocked_io
3939from mdio .segy .file import get_segy_file_info
40+ from mdio .segy .geometry import GridOverrides
4041from mdio .segy .utilities import get_grid_plan
4142
4243if TYPE_CHECKING :
@@ -128,7 +129,7 @@ def filtered_add_coordinate( # noqa: ANN202
128129
129130def _update_template_from_grid_overrides (
130131 template : AbstractDatasetTemplate ,
131- grid_overrides : dict [ str , Any ] | None ,
132+ grid_overrides : GridOverrides | None ,
132133 segy_dimensions : list [Dimension ],
133134 full_chunk_shape : tuple [int , ...],
134135 chunk_size : tuple [int , ...],
@@ -178,30 +179,29 @@ def _update_template_from_grid_overrides(
178179
179180 # If using NonBinned override, expose non-binned dims as logical coordinates on the template instance
180181 # and patch _add_coordinates to skip adding them as 1D dimension coordinates
181- if grid_overrides and "NonBinned" in grid_overrides and "non_binned_dims" in grid_overrides :
182- non_binned_dims = tuple (grid_overrides ["non_binned_dims" ])
183- if non_binned_dims :
184- logger .debug (
185- "NonBinned grid override: exposing non-binned dims as coordinates: %s" ,
186- non_binned_dims ,
187- )
188- # Append any missing names; keep existing order and avoid duplicates
189- existing = set (template .coordinate_names )
190- to_add = tuple (n for n in non_binned_dims if n not in existing )
191- if to_add :
192- template ._logical_coord_names = template ._logical_coord_names + to_add
193-
194- # Patch _add_coordinates to skip adding non-binned dims as 1D dimension coordinates
195- # This prevents them from being added with wrong dimensions (e.g., just "trace")
196- # They will be added later by build_dataset with full spatial_dimension_names
197- _patch_add_coordinates_for_non_binned (template , set (non_binned_dims ))
182+ if grid_overrides is not None and grid_overrides .non_binned and grid_overrides .non_binned_dims :
183+ non_binned_dims = tuple (grid_overrides .non_binned_dims )
184+ logger .debug (
185+ "NonBinned grid override: exposing non-binned dims as coordinates: %s" ,
186+ non_binned_dims ,
187+ )
188+ # Append any missing names; keep existing order and avoid duplicates
189+ existing = set (template .coordinate_names )
190+ to_add = tuple (n for n in non_binned_dims if n not in existing )
191+ if to_add :
192+ template ._logical_coord_names = template ._logical_coord_names + to_add
193+
194+ # Patch _add_coordinates to skip adding non-binned dims as 1D dimension coordinates
195+ # This prevents them from being added with wrong dimensions (e.g., just "trace")
196+ # They will be added later by build_dataset with full spatial_dimension_names
197+ _patch_add_coordinates_for_non_binned (template , set (non_binned_dims ))
198198
199199
200200def _scan_for_headers (
201201 segy_file_kwargs : SegyFileArguments ,
202202 segy_file_info : SegyFileInfo ,
203203 template : AbstractDatasetTemplate ,
204- grid_overrides : dict [ str , Any ] | None = None ,
204+ grid_overrides : GridOverrides | None = None ,
205205) -> tuple [list [Dimension ], SegyHeaderArray ]:
206206 """Extract trace dimensions and index headers from the SEG-Y file.
207207
@@ -346,13 +346,34 @@ def determine_target_size(var_type: str) -> int:
346346 ds .variables [index ].metadata .chunk_grid = chunk_grid
347347
348348
349+ def _coerce_grid_overrides (
350+ grid_overrides : GridOverrides | dict [str , Any ] | None ,
351+ ) -> GridOverrides | None :
352+ """Normalize public ``grid_overrides`` input into a :class:`GridOverrides` model.
353+
354+ The internal ingestion pipeline only accepts the typed model. A legacy ``dict`` is
355+ converted via :meth:`GridOverrides.from_legacy_dict` and a deprecation message is logged.
356+ """
357+ if grid_overrides is None :
358+ return None
359+
360+ if isinstance (grid_overrides , GridOverrides ):
361+ return grid_overrides
362+
363+ logger .warning (
364+ "Passing `grid_overrides` as a dict is deprecated and will be removed in a "
365+ "future release; pass a `mdio.GridOverrides` instance instead."
366+ )
367+ return GridOverrides .model_validate (grid_overrides )
368+
369+
349370def segy_to_mdio ( # noqa PLR0913
350371 segy_spec : SegySpec ,
351372 mdio_template : AbstractDatasetTemplate ,
352373 input_path : UPath | Path | str ,
353374 output_path : UPath | Path | str ,
354375 overwrite : bool = False ,
355- grid_overrides : dict [str , Any ] | None = None ,
376+ grid_overrides : GridOverrides | dict [str , Any ] | None = None ,
356377 segy_header_overrides : SegyHeaderOverrides | None = None ,
357378) -> None :
358379 """A function that converts a SEG-Y file to an MDIO v1 file.
@@ -365,12 +386,15 @@ def segy_to_mdio( # noqa PLR0913
365386 input_path: The universal path of the input SEG-Y file.
366387 output_path: The universal path for the output MDIO v1 file.
367388 overwrite: Whether to overwrite the output file if it already exists. Defaults to False.
368- grid_overrides: Option to add grid overrides.
389+ grid_overrides: Option to add grid overrides. Prefer a :class:`mdio.GridOverrides`
390+ instance; ``dict`` is still accepted but emits a :class:`DeprecationWarning`.
369391 segy_header_overrides: Option to override specific SEG-Y headers during ingestion.
370392
371393 Raises:
372394 FileExistsError: If the output location already exists and overwrite is False.
373395 """
396+ typed_grid_overrides = _coerce_grid_overrides (grid_overrides )
397+
374398 settings = MDIOSettings ()
375399
376400 _validate_spec_in_template (segy_spec , mdio_template )
@@ -395,7 +419,7 @@ def segy_to_mdio( # noqa PLR0913
395419 segy_file_kwargs ,
396420 segy_file_info ,
397421 template = mdio_template ,
398- grid_overrides = grid_overrides ,
422+ grid_overrides = typed_grid_overrides ,
399423 )
400424 grid = _build_and_check_grid (segy_dimensions , segy_file_info , segy_headers )
401425
@@ -417,7 +441,7 @@ def segy_to_mdio( # noqa PLR0913
417441 mdio_template = _update_template_units (mdio_template , spatial_unit )
418442 mdio_ds : Dataset = mdio_template .build_dataset (name = mdio_template .name , sizes = grid .shape , header_dtype = header_dtype )
419443
420- _add_grid_override_to_metadata (dataset = mdio_ds , grid_overrides = grid_overrides )
444+ _add_grid_override_to_metadata (dataset = mdio_ds , grid_overrides = typed_grid_overrides )
421445
422446 # Dynamically chunk the variables based on their type
423447 _chunk_variable (ds = mdio_ds , target_variable_name = "trace_mask" ) # trace_mask is a Variable and not a Coordinate
0 commit comments