L’interface est localisée ; les présentations et documents des Skills sont traduits automatiquement par IA dans votre langue. Le code, les commandes, chemins et termes techniques restent en version originale, et le document de l’auteur fait foi.
Explorer les Skills
Données et recherche · SKILL.md

data-and-structure

data-and-structure

Construct, inspect, import, and mutate GemPy input tables and structural frames; use this for surface points, orientations, elements, groups, IDs, colors, and input validation.

Independent GitHub snapshot · Automated classification · Original documentation governs

Documentation de la Skill

GitHub

name: data-and-structure description: "Construct, inspect, import, and mutate GemPy input tables and structural frames; use this for surface points, orientations, elements, groups, IDs, colors, and input validation." disable-model-invocation: true metadata: disco-role: operating license: EUPL 1.2

GemPy data and structure

Use this sub-skill when a request concerns input data or geological organization, before model interpolation. A GemPy model stores input in this hierarchy:

GeoModel -> StructuralFrame -> StructuralGroup -> StructuralElement -> SurfacePointsTable + OrientationsTable.

A group is an ordered series/stack (or a fault group); an element is one named surface or fault. The frame's group order is geological structure, not merely a container order. Keep the same element names/IDs in surface points and orientations, and validate before computing.

Route and boundaries

  • Construct or compute a model, map a stack to surfaces, or run interpolation: use modeling.
  • Configure regular/custom/section/topography grids or plot input/results: use grids-and-visualization.
  • Save/load JSON or .gempy, or use advanced mesh/plugin workflows: use serialization-and-advanced.
  • Install GemPy or diagnose missing pandas/viewer/engine dependencies: use environment-and-troubleshooting.

The public data API is available through gempy as gp and gp.data. The recipes below use only caller-provided arrays, DataFrames, or file paths; they do not require GemPy's source checkout or example data.

Core workflow

  1. Build SurfacePointsTable and OrientationsTable from equal-length numeric arrays, usually with from_arrays.
  2. Use one explicit name_id_map for both tables when IDs must be controlled; otherwise let GemPy generate an opaque ID per distinct name.
  3. Build a frame with StructuralFrame.from_data_tables(surface_points, orientations) or start with StructuralFrame.initialize_default_structure() for incremental GeoModel construction.
  4. Inspect frame.elements_names, element_id_name_map, counts, and the table .df/.data before mapping or computing.
  5. Mutate through gp.add_*/gp.modify_*, or replace a frame table through the model setter. Re-run model.validate() and then route computation to modeling.

A minimal direct construction is:

import numpy as np
import gempy as gp

sp = gp.data.SurfacePointsTable.from_arrays(
    x=np.array([0., 1., 0.]), y=np.array([0., 0., 1.]), z=np.array([0., 0., 0.]),
    names="Layer",
)
ori = gp.data.OrientationsTable.from_arrays(
    x=np.array([0.5]), y=np.array([0.5]), z=np.array([0.]),
    G_x=np.array([0.]), G_y=np.array([0.]), G_z=np.array([1.]),
    names=["Layer"], name_id_map=sp.name_id_map,
)
frame = gp.data.StructuralFrame.from_data_tables(sp, ori)

from_data_tables creates one default erosional group and an element for each surface-point ID. An element with no matching orientation receives an empty orientation table; this is allowed as a data structure, but may be insufficient for later model validation/computation.

Input/mutation recipes

Add to an existing model

# model must already contain an element named "Layer"
gp.add_surface_points(
    model, x=[2., 3.], y=[0., 0.], z=[1., 1.],
    elements_names=["Layer", "Layer"],
)
gp.add_orientations(
    model, x=[2.], y=[0.], z=[1.], elements_names=["Layer"],
    pole_vector=np.array([[0., 0., 1.]]),
)

add_surface_points and add_orientations append rows to the named element and return the model's StructuralFrame. All coordinate/name/pole/nugget sequences must have the same length. An unknown element name raises ValueError; neither add_* creates a new element. Create an element and put it in a group first when adding a new surface.

add_orientations accepts a representation in one of these forms:

  • pole_vector: an (n, 3) array of gradient components [G_x, G_y, G_z].
  • orientation: an (n, 3) array [azimuth_degrees, dip_degrees, polarity].

Pass one representation. If both are supplied, the current implementation converts orientation and ignores the supplied pole vector. A missing representation raises ValueError. A missing nugget uses GemPy's current defaults (0.01 for orientations and 0.00002 for surface points).

Modify existing rows

# Target by element name, or use a global row index/slice.
gp.modify_surface_points(model, elements_names=["Layer"], Z=np.array([1., 1., 2.]))
gp.modify_surface_points(model, slice=0, X=0.25, nugget=0.00002)
gp.modify_orientations(
    model, slice=slice(0, 1),
    G_x=np.array([0.0]), G_y=np.array([0.0]), G_z=np.array([1.0]),
)

modify_surface_points accepts X, Y, Z, and nugget; modify_orientations accepts those coordinates plus G_x, G_y, G_z, and nugget. Scalars broadcast through NumPy structured-array assignment; arrays must match the selected row count. Surface-point selection cannot specify both elements_names and slice. These functions update the model through the frame table setters; returned value is the updated StructuralFrame.

The current inspected GemPy release exposes angular keyword handling in modify_orientations, but its implementation raises an unpacking ValueError when azimuth, dip, or polarity is used. Treat angular modification as a known compatibility gap: convert angles yourself and write G_x/G_y/G_z, or recreate the orientation rows with add_orientations. Do not claim angular modification works unless a later package version is verified.

Delete rows or elements

gp.delete_surface_points() and gp.delete_orientations() are exported but currently are zero-argument stubs that raise NotImplementedError; they do not provide a selector. For a controlled row deletion, filter a copy and assign it back, preserving the structured dtype:

sp = model.surface_points_copy
keep = sp.data["Z"] >= 0.0
sp.data = sp.data[keep]
model.surface_points = sp

ori = model.orientations_copy
keep_ori = ori.data["X"] != 2.0
ori.data = ori.data[keep_ori]
model.orientations = ori
model.validate()

This is a low-level workaround: filter by the table's numeric fields or IDs, never by an assumed row order, and validate immediately. Removing the only observations can make the model empty or underdetermined.

Validation gate

Before handing off to modeling, check model.validate(). It raises gempy.data.ModelValidationError, whose useful attributes are field, reason, message, and context. Current semantic checks include:

  • no surface points and no orientations (empty_model);
  • an empty structural group (empty_non_fault_group or empty_fault_group);
  • at most one surface point with no orientation (underdetermined_input);
  • a BASEMENT group before the final group (basement_relation_on_non_last_group).

For fault groups, accessing the frame's fault descriptor also requires a square fault-relation matrix with one row/column per structural group. For a failure, inspect model.structural_frame.structural_groups, elements_names, table lengths, IDs, and model.structural_frame.fault_relations; repair the structure before calling compute. A successful data-table construction is not proof that interpolation is determined.

Verification and recovery

Use the bundled table inspector for a caller-owned CSV pair:

python sub-skills/data-and-structure/scripts/inspect_tables.py \
  --surface-points points.csv --orientations orientations.csv

It reports canonical columns, row counts, IDs, names, and finite-value checks without modifying files. For numeric/shape errors, first convert inputs with np.asarray(..., dtype=float), assert all row counts agree, and print table.data.dtype/table.data.shape. For name/ID errors, pass the same name_id_map to both constructors and compare it with frame.element_name_id_map. For sparse inputs, add non-collinear surface points and at least one orientation per interpolated element, then call model.validate() again.

For more column-level contracts and structural relationships, read references/data-formats.md and references/api-reference.md. For failures, read references/troubleshooting.md. For persistence, route the already validated model to serialization-and-advanced; do not serialize ad hoc table internals as a replacement for model persistence.

Skills enregistrées