geoml.data.geoh5
Interchange with Mira Geoscience’s geoh5 format — the workspace files
Geoscience ANALYST, a free viewer, opens as projects. The everyday surface
is on the containers themselves (to_geoh5/from_geoh5 on the mesh
classes, PointData, Blocks3D and BlockSet3D, and
DrillholeData.from_geoh5 for reading a drillhole database); this module
holds the workspace handle those methods share, and the listing helper.
The dependency is an optional extra: pip install geoml[geoh5].
Interchange with Mira Geoscience’s geoh5 format.
A .geoh5 file is a workspace holding any number of named objects, and
it is what Geoscience ANALYST — a free viewer — opens as one project,
so writing one turns that viewer into a 3D screen for geoML’s surfaces,
point predictions and block models. The user-facing surface is on the
containers — to_geoh5/from_geoh5 on the mesh classes, PointData
and BlockSet3D — each taking a path, or an open Workspace from
here when several exports belong together; contents() lists what a
workspace holds. Interchange, not persistence: to_zarr is what keeps a
geoML container whole, and what comes back from a geoh5 file is data as
the file spells it, not the tree that produced it.
The dependency is optional: pip install geoml[geoh5] brings geoh5py,
and nothing in this module is imported until one of these functions runs.
- class geoml.data.geoh5.Workspace(filename)[source]
Bases:
objectAn open geoh5 workspace, holding several exports together.
A
.geoh5file is what Geoscience ANALYST opens as one project, so a model’s pieces — surfaces, samples, block models — belong in one workspace rather than a file each. Passing the same path to everyto_geoh5already lands them together, at the price of opening and closing the file per call; this object opens it once and everyto_geoh5andfrom_geoh5given it writes and reads through the open handle:with geoml.data.geoh5.Workspace("assen.geoh5") as project: topo.to_geoh5(project, name="topography") ore.to_geoh5(project, name="ore body") blocks.to_geoh5(project, name="block model")
The file is created when it does not exist and appended to when it does. The workspace’s own name, as ANALYST shows it, is the file’s name: geoh5py accepts a display name at creation but does not persist it — measured, it reads back as “GEOSCIENCE” — so none is offered here; name the file.
- Parameters:
filename (path) – The
.geoh5file to open or create.
- geoml.data.geoh5.contents(workspace)[source]
What a geoh5 workspace holds: object names against their kinds.
- Parameters:
workspace (str | PathLike | Workspace) – Path of the workspace to look into, or an open Workspace.
- Returns:
listing (dict) – One entry per object, name to geoh5 type name (“Surface”, “Points”, “Octree”, …).
- Return type:
dict[str, str]
- geoml.data.geoh5.write_surface(mesh, workspace, name, replace=True, folder=None)[source]
Surface3D.to_geoh5 and its siblings land here.
- geoml.data.geoh5.read_surface(workspace, name=None)[source]
Mesh3D.from_geoh5 lands here: the geometry, classified after.
- geoml.data.geoh5.write_points(container, workspace, name, include='**', simulations=False, replace=True, folder=None)[source]
PointData.to_geoh5 lands here.
- geoml.data.geoh5.write_blocks(blocks, workspace, name, include='**', simulations=False, replace=True, folder=None)[source]
BlockSet3D.to_geoh5 lands here.
The lattice maps one to one: a block’s origin and size in base cells are an octree cell’s I J K NCells as they stand, in the model’s own row order, so the cell data rides with no reordering. The counts are padded to geoh5’s required power of two with nothing written in the padding, and the rotation — geoh5 carries exactly one, counter- clockwise about the vertical axis about the origin — is the negated azimuth, geoML’s rotation being the mining-convention clockwise one. max_levels rides in the object’s metadata: it is refinement capacity, which the cells alone cannot say once every coarse block has been split.
- geoml.data.geoh5.read_blocks(workspace, name=None)[source]
BlockSet3D.from_geoh5 lands here: the octree as plain arrays.
Negative cell sizes — a workspace with its origin at the top and the w axis running down is common — are normalized here: the axis is flipped to a positive step, the origin moved to the true low corner, and the cell indices re-counted from it. A flipped horizontal axis under a rotation would compose a reflection into the rotation, which no rotated block model can hold, and is refused.
- geoml.data.geoh5.write_grid_blocks(blocks, workspace, name, include='**', simulations=False, replace=True, folder=None)[source]
Blocks3D.to_geoh5 lands here: a uniform model as a BlockModel.
A geoh5 BlockModel is a tensor grid — per-axis edge positions from its origin — which a uniform model fills with equal steps. Cell data is stored u-fastest where geoML’s grids run x slowest, so every column is transposed on the way through, values and order agreeing with what geoh5py’s own centroids say.
- geoml.data.geoh5.read_grid_blocks(workspace, name=None)[source]
Blocks3D.from_geoh5 lands here: a BlockModel as plain arrays.
Only a uniform spacing has a geoML container — a true tartan grid is refused with its uneven axis named — and the cell data comes back in geoML’s own order.
- geoml.data.geoh5.read_drillholes(workspace, name=None)[source]
DrillholeData.from_geoh5 lands here: collars, surveys and the interval tables, as plain frames.
geoh5 stores one object per hole, its interval data as FROM/TO columns inside named property groups; the group names become the table names, gathered across every hole. Depth-associated data — a reading at a point down the hole rather than over an interval — has no place in an interval table and is left out. name narrows to one drillhole group, or to one hole.