Skip to content

petekSim (Python)

The product façade — the v2 declarative spec API and the whole stack behind one import.

import peteksim as ps

At a glance

Group Names
Synthetic data synth_asset
Structure specs Horizons, hz, Subzones, splits, Layering, Contacts, zone
Settings TieSettings, Gridding, decay_to_flat, flat, nearest, Run, ViewSettings
Property specs Props, Prop, Propagate, variogram, collocated
Uncertainty Mc, McSettings, shift, dist, aggregate, distribution_bundle
Charts Distribution, Tornado
Scenarios AssetSpec, spec_from_dict, registered_specs
Apply results Model, StaticModel, Uncertainty, ZonedUncertainty
Analytic box run_box_model
Errors NotYetSupported, ApplyError

See the petekSim guide, the flagship tutorial, and the full-workflow notebook.

Note

Project loading is owned by petekio, and static model construction is owned by petekstatic; peteksim no longer exposes Project or LoadSettings.

API

petekSim — fast field/discovery appraisal toolkit (Rust core, Python API).

Code-first: build a model in Python, then model.view() pops open a three.js render of it in your browser. The compute lives in the Rust extension (peteksim._core); the renderer is petekTools' horizontal petektools.viewer unit (owner ruling), which this package feeds a render payload and a live-section callback.

import peteksim
m = peteksim.run_box_model(area_km2=(0.32, 0.4, 0.52), gross_height_m=(12, 15, 20),
                             porosity=0.25, net_to_gross=0.8, water_saturation=0.3,
                             fvf=1.25, fluid="oil", contact_m=2743)
m.view()                       # opens the 3D viewer in a browser

sm = peteksim.Model(0.4, 15.0, ni=24, nj=24, nk=8,
                      top_m=1500, contact_m=1510.5)
sm.add_control(12, 12, 1489)   # a structural high, in code
sm.view()                      # build + view

All inputs are SI/metric (area km², lengths/depths m positive-down, FVF Rm³/Sm³); results in Sm³ (GRV in mcm = 10⁶ m³).

ApplyError

Bases: ValueError

A spec could not be resolved against the project at apply time (a missing name, an illegal combination). The message names BOTH the project object and the spec entry.

AssetSpec dataclass

AssetSpec(
    name="",
    horizons=None,
    subzones=None,
    layering=None,
    contacts=None,
    ties=None,
    gridding=None,
    props=None,
    mc=None,
    run=None,
    view=None,
)

Bases: Spec

A whole modelling scenario as one value — the durable, re-applicable descriptor (asset.to_dict() is a savable scenario file). Every field is a spec, so the round-trip is total.

contacts class-attribute instance-attribute

contacts = None

gridding class-attribute instance-attribute

gridding = None

horizons class-attribute instance-attribute

horizons = None

layering class-attribute instance-attribute

layering = None

mc class-attribute instance-attribute

mc = None

name class-attribute instance-attribute

name = ''

props class-attribute instance-attribute

props = None

run class-attribute instance-attribute

run = None

subzones class-attribute instance-attribute

subzones = None

ties class-attribute instance-attribute

ties = None

view class-attribute instance-attribute

view = None

CollocatedTrend dataclass

CollocatedTrend(surface='', corr=0.0, as_depth=False)

Bases: Spec

A collocated-cokriging trend that holds the steering surface's NAME (ps.collocated("depo_trend", corr=0.6)), resolved against the project at apply. as_depth=False reads the surface as a trend in its own units; True flips a structural elevation to positive-down depth.

as_depth class-attribute instance-attribute

as_depth = False

corr class-attribute instance-attribute

corr = 0.0

surface class-attribute instance-attribute

surface = ''

resolve

resolve(core, project_core)

Build the _core Trend by resolving surface on the project.

Extrapolation dataclass

Extrapolation(kind='nearest', range_m=None)

Bases: Spec

A gridding extrapolation policy — build with ps.decay_to_flat(range_m), ps.flat(), or ps.nearest(). Mirrors petekStatic's ExtrapolationPolicy; honoured once the structure-investigation gridding branch wires SolveOpts.

kind class-attribute instance-attribute

kind = 'nearest'

range_m class-attribute instance-attribute

range_m = None

McSettings dataclass

McSettings(lo_pct=10.0, hi_pct=90.0, workers=0)

Bases: Spec

MC run settings (ps.McSettings(lo_pct=10, hi_pct=90, workers=4)) — the percentile band + realize-loop sharding. Mirrors petekStatic's McSettings.

hi_pct class-attribute instance-attribute

hi_pct = 90.0

lo_pct class-attribute instance-attribute

lo_pct = 10.0

workers class-attribute instance-attribute

workers = 0

NotYetSupported

Bases: NotImplementedError

A spec field is valid and serializes, but the engine capability that would honour it has not landed yet. Raised LOUDLY at apply time, naming the task that carries the capability — never a silent no-op.

Propagate dataclass

Propagate(
    variogram=Variogram(),
    seed=1,
    max_neighbours=None,
    radius_m=None,
    trend=None,
    mode="level_shift",
    allow_mean_fill=False,
)

Bases: Spec

An SGS propagation recipe: a Variogram + seed + optional search (max_neighbours/radius_m) + optional collocated trend + mode ("level_shift" | "resimulate") + allow_mean_fill.

allow_mean_fill class-attribute instance-attribute

allow_mean_fill = False

max_neighbours class-attribute instance-attribute

max_neighbours = None

mode class-attribute instance-attribute

mode = 'level_shift'

radius_m class-attribute instance-attribute

radius_m = None

seed class-attribute instance-attribute

seed = 1

trend class-attribute instance-attribute

trend = None

variogram class-attribute instance-attribute

variogram = field(default_factory=Variogram)

Spec dataclass

Spec()

Immutable declarative value with family value-semantics.

Concrete specs are @dataclass(frozen=True, eq=False) subclasses decorated with @spec; store collection data as tuples (immutable + JSON-able). Equality + hash are canonical over to_dict so a spec is comparable and hashable regardless of its field types.

from_dict classmethod

from_dict(d)

replace

replace(*args, **changes)

Return a NEW value with field changes (the original is unchanged).

Collection specs (Horizons, Layering, Contacts, ...) override to accept a leading name/glob targeting matching entries — hz.replace("H1", surface=...), lay.replace("Z*", dz=0.5).

to_dict

to_dict()

A plain JSON-able dict carrying the "spec" type tag. A scenario is a durable file: removing/renaming a field is a CHANGELOG-gated break.

Variogram dataclass

Variogram(
    model="spherical", range_m=0.0, sill=1.0, nugget=0.0
)

Bases: Spec

A serializable variogram descriptor (ps.variogram("spherical", range_m=1500)) — built into a _core Vgm (petekTools' VariogramSpec) at apply. The single-home kernel stays downstream; this is the durable value.

model class-attribute instance-attribute

model = 'spherical'

nugget class-attribute instance-attribute

nugget = 0.0

range_m class-attribute instance-attribute

range_m = 0.0

sill class-attribute instance-attribute

sill = 1.0

resolve

resolve(core)

Contacts

Contacts(mapping=None)

Distribution

Distribution(gas=False, zone=None, name=None)

Gridding

Gridding(
    fidelity_m=None,
    extrapolation=None,
    collapse=True,
    min_cell=None,
)

Horizons

Horizons(*rows, zones=None, ties=None, gridding=None)

Layering

Layering(dz=None, nk=None, min_cell=None)

Mc

Mc(
    porosity=None,
    net_to_gross=None,
    water_saturation=None,
    fvf=None,
    gas_fvf=None,
    contacts=None,
    goc=None,
    per_zone=None,
    settings=None,
    n=10000,
    seed=42,
)

Build an Mc — normalizing scalars/_core spreads into serializable descriptors. contacts is the lower (FWL/OWC) spread; goc its own.

Prop

Prop(
    name,
    zone=None,
    upscale_method="arithmetic",
    net_only=False,
    net_cutoff=0.5,
    propagate=None,
)

Props

Props(*items)

Run

Run(memory_budget=None, workers=0)

Subzones

Subzones(mapping=None)

TieSettings

TieSettings(method='convergent', radius_m=None)

Tornado

Tornado(base=None, units='MSm³', fold_count=8)

ViewSettings

ViewSettings(
    property=None, open_browser=True, port=0, block=False
)

aggregate builtin

aggregate(segments, correlation='independent')

ps.aggregate([mc, ...], correlation="independent") — a field roll-up.

collocated

collocated(surface, corr, as_depth=False)

A collocated-cokriging trend. surface a name (str) → a name-holding CollocatedTrend spec resolved at apply (the v2 pattern). surface a _core.Surface → the v1 eager trend (deprecated: bind by name instead).

decay_to_flat

decay_to_flat(range_m)

Extrapolate beyond data by decaying the gradient to flat over range_m.

dist

dist(kind, *params)

A named distribution descriptor (ps.dist("normal", 0.25, 0.02)).

distribution_bundle builtin

distribution_bundle(
    segments,
    aggregate=None,
    names=None,
    gas=False,
    title=None,
)

ps.distribution_bundle([mc, ...], aggregate=field, names=[...], gas=False) — a multi-series distribution panel: one overlaid series per segment plus, if an aggregate dict (from ps.aggregate) is given, a "Field" series from its realization samples. Per-structure + field-aggregate in one histogram/CDF, in MSm³ (oil) / bcm (gas). Binning is deterministic (the plumbing's nice-bin rule); the viewer only draws.

exponential builtin

exponential(range_m, sill=1.0, nugget=0.0)

ps.exponential(range_m, sill=1, nugget=0).

fit_variogram builtin

fit_variogram(
    coords, model="spherical", lag=1.0, n_lags=10
)

ps.fit_variogram(coords, model="spherical", lag=.., n_lags=..) — fit a model to an experimental variogram over [x, y, value] rows.

flat

flat()

Hold the edge value flat beyond the data.

gaussian builtin

gaussian(
    variogram, seed=1, max_neighbours=None, radius_m=None
)

ps.gaussian(variogram, seed, max_neighbours=None, radius_m=None) — an SGS spec.

gaussian_vgm builtin

gaussian_vgm(range_m, sill=1.0, nugget=0.0)

ps.gaussian_vgm(range_m, sill=1, nugget=0).

hz

hz(name, surface=None, tie=None, sd=0.0, vgm=None)

A horizon row for ps.Horizonsps.hz("H1", tie="H1 picks", sd=3.0, vgm=("spherical", 2500)).

layers builtin

layers(n=None, dz_m=None, style='proportional')

ps.layers(n=None, dz_m=None, style="proportional").

style selects the conformity: - "proportional" (default) — equal-fraction layers; the count is n= (or dz_m=ceil(gross/dz)). - "follow_top" / "follow_base" — constant-dz_m drape parallel to the top (truncation/erosional) or base (onlap); nk is dz-derived at the build seam (capped at MAX_NK=200), deep/shallow layers truncate at pinch-outs. dz_m is required; n is ignored.

level_shift builtin

level_shift(sd)

ps.level_shift(sd) — a zero-mean additive shift for a modelled cube.

lognormal builtin

lognormal(mean, sd)

ps.lognormal(mean, sd) (log-space parameters).

nearest

nearest()

Nearest-node extrapolation beyond the data (the engine default).

normal builtin

normal(mean, sd)

ps.normal(mean, sd).

pick_spread builtin

pick_spread(sd_m)

ps.pick_spread(sd_m) — a contact spread.

registered_specs

registered_specs()

Every registered spec class (the conformance battery iterates this).

resimulate builtin

resimulate()

ps.resimulate() — select the resimulate MC mode for property.propagate(..., resimulate=...): a fresh SGS pattern per realization (captures heterogeneity uncertainty) instead of the default level-shift. Equivalent to resimulate=True; exposed because the symbol was expected to exist (propagate(resimulate=ps.resimulate())).

run_box_model builtin

run_box_model(
    area_km2,
    gross_height_m,
    porosity,
    net_to_gross,
    water_saturation,
    fvf,
    *,
    fluid="oil",
    top_m=0.0,
    contact_m=Ellipsis,
    ni=10,
    nj=10,
    nk=5,
    realizations=10000,
    seed=1
)

Run a box appraisal model end-to-end: area + height (+ properties) -> deterministic in-place and a Monte Carlo P90/P50/P10, plus a render mesh.

Units: area_km2 in km² (reservoir-scale-natural; converted to m² internally), heights/depths in m (positive down), FVF in Rm³/Sm³. Results are Sm³ (p90/p50/p10/mean/deterministic_in_place/samples), GRV in mcm; summary_msm3 / summary_bcm give the MSm³ / bcm reporting scales.

Each volumetric input accepts
  • a number → deterministic constant;
  • a (min, mode, max) tuple → triangular (shorthand);
  • a tagged dict → the matching distribution: {"normal": [mean, sd]}, {"lognormal": [mu, sigma]}, {"uniform": [lo, hi]}, {"triangular": [lo, mode, hi]}. (Area distributions are parameterised in km²; lognormal mu/sigma are log-space km² parameters.)

An unknown tag or wrong parameter count raises ValueError.

fluid is "oil" or "gas" (both report Sm³). contact_m is required (a finite depth in metres) — it defines the base of the hydrocarbon column.

The result's samples attribute holds every per-realization in-place value (draw order) behind the summary, for compositional workflows.

shift

shift(sd)

A zero-mean level shift (ps.shift(0.01)) for a modelled cube.

spec_from_dict

spec_from_dict(d)

Reconstruct any spec from its tagged dict (the family from_dict).

spherical builtin

spherical(range_m, sill=1.0, nugget=0.0)

ps.spherical(range_m, sill=1, nugget=0).

splits

splits(*entries, conformity='proportional')

A zone split recipe — each entry a name or (name, dict(surface=, tie=)): ps.splits("upper", ("lower", dict(surface="H3b"))).

triangular builtin

triangular(lo, mode, hi)

ps.triangular(lo, mode, hi).

truncated_normal builtin

truncated_normal(mean, sd, lo, hi)

ps.truncated_normal(mean, sd, lo, hi).

uniform builtin

uniform(lo, hi)

ps.uniform(lo, hi).

variogram

variogram(model, range_m, sill=1.0, nugget=0.0)

version builtin

version()

Return the installed petekSim version.

view

view(model, open_browser=True, port=0, block=False)

Open the viewer for any model/result (same as model.view()).

zone

zone(name, color=None)