Skip to content

Commit

Permalink
MAINT: resolve import roxar vs import rmsapi
Browse files Browse the repository at this point in the history
  • Loading branch information
jcrivenaes committed Oct 29, 2024
1 parent f208649 commit 251d777
Show file tree
Hide file tree
Showing 11 changed files with 103 additions and 97 deletions.
7 changes: 1 addition & 6 deletions src/xtgeo/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,6 @@ def _xprint(msg):

_xprint("XTGEO __init__ ...")

ROXAR = True
try:
import roxar
except ImportError:
ROXAR = False

try:
from xtgeo.common.version import __version__, version
Expand Down Expand Up @@ -159,7 +154,7 @@ def _xprint(msg):
_xprint("XTGEO __init__ done")

# Remove symbols imported for internal use
del os, platform, sys, timeit, warnings, TIME0, DEBUG, ROXAR, _timer, _xprint
del os, platform, sys, timeit, warnings, TIME0, DEBUG, _timer, _xprint

# Let type-checkers know what is exported
__all__ = [
Expand Down
6 changes: 1 addition & 5 deletions src/xtgeo/cube/_cube_roxapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

from xtgeo.common import XTGeoDialog, null_logger
from xtgeo.roxutils import RoxUtils
from xtgeo.roxutils._roxar_loader import roxar

xtg = XTGeoDialog()

Expand Down Expand Up @@ -132,11 +133,6 @@ def export_cube_roxapi(
def _roxapi_export_cube(
self, proj, rox, name, folder=None, domain="time", compression=("wavelet", 5)
): # type: ignore # pragma: no cover
try:
import roxar # type: ignore
except ImportError:
roxar = None

logger.info(
"There are issues with compression %s, hence it is ignored", compression
)
Expand Down
32 changes: 14 additions & 18 deletions src/xtgeo/grid3d/_grid_roxapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,21 @@
from xtgeo import _cxtgeo
from xtgeo.common import XTGeoDialog, null_logger
from xtgeo.common.constants import UNDEF_LIMIT
from xtgeo.roxutils._roxar_loader import roxar, roxar_grids
from xtgeo.roxutils.roxutils import RoxUtils

xtg = XTGeoDialog()

logger = null_logger(__name__)

if TYPE_CHECKING:
import contextlib

from xtgeo.grid3d.grid import Grid
# from xtgeo.roxutils._roxar_loader import RoxarGrid3DType

if roxar is not None:
from roxar import grids as RoxarGridType
from roxar.grids import Grid3D as RoxarGrid3DType

with contextlib.suppress(ImportError):
import roxar

# self is Grid() instance

Expand All @@ -47,13 +49,13 @@ def import_grid_roxapi(
return _import_grid_roxapi(rox, gname, realisation, info)


def _display_roxapi_grid_info(roxgrid: roxar.grids.Grid3D) -> None:
def _display_roxapi_grid_info(roxgrid: RoxarGrid3DType) -> None:
"""Push info to screen (mostly for debugging), experimental."""

indexer = roxgrid.grid_indexer
ncol, nrow, _ = indexer.dimensions

xtg.say("ROXAPI with support for CornerPointGeometry")
xtg.say("ROXAPI with support for CornerPointGridGeometry")
geom = roxgrid.get_geometry()
defined_cells = geom.get_defined_cells()
xtg.say(f"Defined cells \n{defined_cells}")
Expand Down Expand Up @@ -103,7 +105,7 @@ def _import_grid_roxapi(
return result


def _convert_to_xtgeo_grid(roxgrid: roxar.grids.Grid3D, gname: str) -> dict[str, Any]:
def _convert_to_xtgeo_grid(roxgrid: RoxarGrid3DType, gname: str) -> dict[str, Any]:
"""Convert from roxar CornerPointGeometry to xtgeo, version 2 using _xtgformat=2."""
indexer = roxgrid.grid_indexer

Expand Down Expand Up @@ -204,18 +206,15 @@ def _export_grid_cornerpoint_roxapi_v1(
self: Grid, rox: RoxUtils, gname: str, realisation: int, info: bool
) -> None:
"""Convert xtgeo geometry to pillar spec in ROXAPI and store."""
try:
from roxar.grids import CornerPointGridGeometry as CPG
except ImportError:
raise RuntimeError("Cannot load Roxar module")

logger.info("Load grid via CornerPointGridGeometry...")

grid_model = rox.project.grid_models.create(gname)
grid_model.set_empty(realisation)
grid = grid_model.get_grid(realisation)

geom = CPG.create(self.dimensions)
roxar_grid_: RoxarGridType = roxar_grids # for mypy
geom = roxar_grid_.CornerPointGridGeometry.create(self.dimensions)

logger.info(geom)
scopy = self.copy()
Expand Down Expand Up @@ -272,16 +271,13 @@ def _export_grid_cornerpoint_roxapi_v2(
self: Grid, rox: RoxUtils, gname: str, realisation: int, info: bool
) -> None:
"""Convert xtgeo geometry to pillar spec in ROXAPI and store _xtgformat=2."""
try:
from roxar.grids import CornerPointGridGeometry as CPG
except ImportError:
raise RuntimeError("Cannot load Roxar module")

grid_model = rox.project.grid_models.create(gname)
grid_model.set_empty(realisation)
grid = grid_model.get_grid(realisation)

geom = CPG.create(self.dimensions)
roxar_grids_: RoxarGridType = roxar_grids # for mypy
geom = roxar_grids_.CornerPointGridGeometry.create(self.dimensions)

scopy = self.copy()
scopy.make_zconsistent()
Expand Down Expand Up @@ -332,7 +328,7 @@ def _export_grid_cornerpoint_roxapi_v2(
del scopy


def _set_subgrids(self: Grid, rox: RoxUtils, grid: roxar.grids.Grid3D) -> None:
def _set_subgrids(self: Grid, rox: RoxUtils, grid: RoxarGrid3DType) -> None:
"""Export the subgrid index (zones) to Roxar API.
From roxar API:
Expand Down
24 changes: 15 additions & 9 deletions src/xtgeo/grid3d/_gridprop_roxapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

from __future__ import annotations

import contextlib
from typing import TYPE_CHECKING, Any, Literal

import numpy as np
Expand All @@ -12,20 +11,26 @@
from xtgeo.common import null_logger
from xtgeo.common.constants import UNDEF, UNDEF_INT, UNDEF_INT_LIMIT, UNDEF_LIMIT
from xtgeo.roxutils import RoxUtils

with contextlib.suppress(ImportError):
import roxar
from xtgeo.roxutils._roxar_loader import roxar

if TYPE_CHECKING:
from xtgeo.grid3d.grid_property import GridProperty

if roxar is not None:
from roxar import Project as RoxarProjectType
from roxar.grids import Grid3D as RoxarGrid3DType

logger = null_logger(__name__)

VALID_ROXAR_DTYPES = [np.uint8, np.uint16, np.float32]


def import_prop_roxapi(
project: roxar.Project, gname: str, pname: str, realisation: int, faciescodes: bool
project: RoxarProjectType,
gname: str,
pname: str,
realisation: int,
faciescodes: bool,
) -> dict[str, Any]:
"""Import a Property via ROXAR API spec."""
logger.info("Opening RMS project ...")
Expand Down Expand Up @@ -108,7 +113,7 @@ def _convert_to_xtgeo_prop(

def export_prop_roxapi(
self: GridProperty,
project: roxar.Project,
project: RoxarProjectType,
gname: str,
pname: str,
realisation: int = 0,
Expand All @@ -133,7 +138,7 @@ def export_prop_roxapi(
def _store_in_roxar(
self: GridProperty,
pname: str,
roxgrid: roxar.grid.Grid3D,
roxgrid: RoxarGrid3DType,
realisation: int,
casting: Literal["no", "equiv", "safe", "same_kind", "unsafe"] | None,
) -> None:
Expand Down Expand Up @@ -163,10 +168,11 @@ def _store_in_roxar(

pvalues = roxgrid.get_grid(realisation=realisation).generate_values(data_type=dtype)

roxtype: Any = roxar # needed for mypy
roxar_property_type = (
roxar.GridPropertyType.discrete
roxtype.GridPropertyType.discrete
if self.isdiscrete
else roxar.GridPropertyType.continuous
else roxtype.GridPropertyType.continuous
)

pvalues[cellno] = val3d[iind, jind, kind]
Expand Down
54 changes: 54 additions & 0 deletions src/xtgeo/roxutils/_roxar_loader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
"""Loading rmsapi or roxar module based on availability"""

import importlib
from typing import TYPE_CHECKING, Any, Optional, TypeVar

# Roxar*Type are placeholders for the actual types which are not known at this point,
# and these may be replaced in modules by e.g:
# ---------
# from xtgeo.roxutils._roxar_loader import roxar
# if TYPE_CHECKING:
# from xtgeo.grid3d.grid_property import GridProperty
# if roxar is not None:
# from roxar.grids import Grid3D as RoxarGridType
# ---------


def load_module(module_name: str) -> Optional[Any]:
try:
return importlib.import_module(module_name)
except ImportError:
return None


rmsapi = load_module("rmsapi")
roxar = rmsapi if rmsapi else load_module("roxar")

if rmsapi:
roxar_well_picks = load_module("rmsapi.well_picks")
roxar_jobs = load_module("rmsapi.jobs")
roxar_grids = load_module("rmsapi.grids")
else:
roxar_well_picks = load_module("roxar.well_picks")
roxar_jobs = load_module("roxar.jobs")
roxar_grids = load_module("roxar.grids")

# Use TypeVar correctly
RoxarType = TypeVar("RoxarType")
RoxarGridType = TypeVar("RoxarGridType")
RoxarGrid3DType = TypeVar("RoxarGrid3DType")
RoxarWellpicksType = TypeVar("RoxarWellpicksType")
RoxarJobsType = TypeVar("RoxarJobsType")

if TYPE_CHECKING:
if roxar is not None:
import roxar.grids as RoxarGridType # noqa # type: ignore
from roxar.grids import Grid3D as RoxarGrid3DType # noqa # type: ignore
from roxar.jobs import Jobs as RoxarJobsType # noqa # type: ignore
from roxar.well_picks import WellPicks as RoxarWellpicksType # noqa # type: ignore

# Explicitly type the roxar* as Optional to indicate it may be None
roxar: Optional[Any] = roxar
roxar_grids: Optional[Any] = roxar_grids
roxar_well_picks: Optional[Any] = roxar_well_picks
roxar_jobs: Optional[Any] = roxar_jobs
7 changes: 2 additions & 5 deletions src/xtgeo/roxutils/_roxutils_etc.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
"""Private module for etc functions"""

import contextlib

with contextlib.suppress(ImportError):
import roxar

from xtgeo.common.log import null_logger

from ._roxar_loader import roxar

logger = null_logger(__name__)


Expand Down
6 changes: 1 addition & 5 deletions src/xtgeo/roxutils/roxutils.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
"""Module for simplifying various operation in the Roxar python interface."""

import contextlib

from packaging.version import parse as versionparse

with contextlib.suppress(ImportError):
import roxar

from xtgeo.common.log import null_logger
from xtgeo.common.xtgeo_dialog import XTGeoDialog

from . import _roxutils_etc
from ._roxar_loader import roxar

xtg = XTGeoDialog()
logger = null_logger(__name__)
Expand Down
13 changes: 1 addition & 12 deletions src/xtgeo/surface/_regsurf_roxapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

from xtgeo.common.log import null_logger
from xtgeo.roxutils import RoxUtils
from xtgeo.roxutils._roxar_loader import roxar

logger = null_logger(__name__)

Expand Down Expand Up @@ -214,12 +215,6 @@ def _roxapi_export_surface(
)
# here a workound; trends.surfaces are read-only in Roxar API, but is seems
# that load() in RMS is an (undocumented?) workaround...
try:
import roxar
except ImportError as err:
raise ImportError(
"roxar not available, this functionality is not available"
) from err

roxsurf = proj.trends.surfaces[name]
with tempfile.TemporaryDirectory() as tmpdir:
Expand All @@ -234,12 +229,6 @@ def _roxapi_export_surface(

def _xtgeo_to_roxapi_grid(self): # pragma: no cover
# Create a 2D grid
try:
import roxar
except ImportError as err:
raise ImportError(
"roxar not available, this functionality is not available"
) from err

return roxar.RegularGrid2D.create(
x_origin=self.xori,
Expand Down
6 changes: 1 addition & 5 deletions src/xtgeo/well/_blockedwell_roxapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,7 @@
from xtgeo.common.exceptions import WellNotFoundError
from xtgeo.common.log import null_logger
from xtgeo.roxutils import RoxUtils

try:
import roxar # type: ignore
except ImportError:
roxar = None
from xtgeo.roxutils._roxar_loader import roxar

logger = null_logger(__name__)

Expand Down
Loading

0 comments on commit 251d777

Please sign in to comment.