Source code for parq_blockmodel.utils.pandas_accessors
from typing import TYPE_CHECKING
import pandas as pd
import numpy as np
if TYPE_CHECKING:
from parq_blockmodel import ParquetBlockModel
def _geometry_from_df(df: pd.DataFrame):
"""Infer a RegularGeometry from a DataFrame.
Resolution order:
1. ``df.attrs["parq-blockmodel"]`` – full production metadata.
2. ``df.attrs["geometry"]`` – lightweight demo-blockmodel metadata.
3. xyz-indexed MultiIndex – infer from centroid distribution (non-rotated only).
Raises ValueError if geometry cannot be determined.
"""
from parq_blockmodel import RegularGeometry
from parq_blockmodel.geometry import LocalGeometry, WorldFrame
# 1. Full parq-blockmodel metadata
if "parq-blockmodel" in df.attrs:
return RegularGeometry.from_attrs(df.attrs, key="parq-blockmodel")
# 2. Lightweight demo-blockmodel attrs (produced by create_demo_blockmodel)
if "geometry" in df.attrs:
g = df.attrs["geometry"]
from parq_blockmodel.utils.geometry_utils import angles_to_axes
rot = g.get("rotation", {})
axis_u, axis_v, axis_w = angles_to_axes(
axis_azimuth=rot.get("azimuth", 0.0),
axis_dip=rot.get("dip", 0.0),
axis_plunge=rot.get("plunge", 0.0),
)
return RegularGeometry(
local=LocalGeometry(
corner=g["corner"],
block_size=g["block_size"],
shape=g["shape"],
),
world=WorldFrame(axis_u=axis_u, axis_v=axis_v, axis_w=axis_w),
)
raise ValueError(
"Cannot determine geometry for the DataFrame. "
"Attach geometry via df.attrs['parq-blockmodel'], "
"df.attrs['geometry'], or use an xyz-indexed MultiIndex."
)
[docs]
@pd.api.extensions.register_dataframe_accessor("to_pyvista")
class PyVistaAccessor:
[docs]
def __init__(self, pandas_obj):
self._obj = pandas_obj
def __call__(self,
grid_type="image",
geometry=None,
block_size=None,
fill_value=np.nan,
frame: str = "world"
) -> "pv.ImageData | pv.StructuredGrid | pv.UnstructuredGrid":
if grid_type == "image":
from parq_blockmodel.utils.pyvista.pyvista_utils import df_to_pv_image_data
if geometry is None:
geometry = _geometry_from_df(self._obj)
return df_to_pv_image_data(self._obj, geometry, fill_value=fill_value, frame=frame)
elif grid_type == "structured":
from parq_blockmodel.utils.pyvista.pyvista_utils import df_to_pv_structured_grid
return df_to_pv_structured_grid(self._obj, block_size=block_size)
elif grid_type == "unstructured":
from parq_blockmodel.utils.pyvista.pyvista_utils import df_to_pv_unstructured_grid
if block_size is None:
raise ValueError("block_size must be provided for unstructured grid.")
return df_to_pv_unstructured_grid(self._obj, block_size=block_size)
else:
raise ValueError(f"Invalid grid_type: {grid_type}. Choose 'image', 'structured', or 'unstructured'.")
[docs]
@pd.api.extensions.register_dataframe_accessor("to_parquet_blockmodel")
class ParquetBlockModelAccessor:
[docs]
def __init__(self, pandas_obj):
self._obj = pandas_obj
def __call__(self, filename, **kwargs) -> "ParquetBlockModel":
from parq_blockmodel import ParquetBlockModel
return ParquetBlockModel.from_dataframe(self._obj, filename=filename, **kwargs)