Skip to content

API — nefi

Generated by scripts/gen_api_docs.py — do not edit by hand. Index

nefi

nefi — Neural-Field Inversion.

def enable_logging(level: int = 20)

Send nefi logs to stderr (idempotent).

def invert(problem: InverseProblem, curriculum: Curriculum | None = None, **solver_kw) -> Result

One-call entry point: run Solver(problem, curriculum, **solver_kw).run().

nefi.auto

Adaptive defaults — from your differentiable forward model to a ready-to-solve problem.

def auto_curriculum(shape: Sequence[int], budget: str | int = 'default', multiscale: bool = True, representation: str = 'neural', *, lr: float | None = None, noise_known: bool ...

A robust default curriculum for a field of grid shape.

def balance_weights(problem: InverseProblem, strengths: Mapping[str, float] | None = None, *, probe_steps: int = 25, lr: float = 0.001, shape: Sequence[int] | None = None, targ...

Automatic loss weights: data term = target at the initial iterate, and each regularizer worth strength × target at a reference iterate.

def budget_steps(budget: str | int, shape: Sequence[int]) -> int

Total optimization steps for a budget name (scaled by field size) or an explicit int.

def default_lr(representation: str = 'neural', hidden: int | None = None) -> float

Default peak learning rate: :data:DEFAULT_LR, scaled by sqrt(64 / hidden) for MLPs.

def default_octaves(shape: Sequence[int]) -> int

clamp(ceil(log2(max(shape))), 4, 12) Fourier octaves for a grid.

def estimate_noise(measurement: Measurement | torch.Tensor | np.ndarray, *, axes: Sequence[int] | None = None, method: str = 'auto', order: int | None = None, region: torch.Te...

Robust estimate of the additive noise standard deviation of a measurement.

def from_forward(forward: Callable | Operator, measurement: Measurement | torch.Tensor | np.ndarray, shape: Sequence[int] | int, *, extent: Sequence[tuple[float, float]] | N...

Build a complete :class:~nefi.problem.InverseProblem from a differentiable forward model.

def lr_range_test(problem: InverseProblem, lrs: Sequence[float] = (0.0001, 0.0003, 0.001, 0.003, 0.01, 0.03, 0.1), steps: int = 20, *, shape: Sequence[int] | None = None, pro...

Cheap learning-rate probe: pick the LR with the largest loss decrease without divergence.

def quick_report(result, problem: InverseProblem, gt: Any = None) -> str

Compact markdown summary: does the fit reach the noise floor, and what happened.

nefi.cli

nefi command-line interface.

class CLIError(...)

User-facing command-line error (bad target, missing file, malformed option).

class RunSpec(instance: str, config: dict[str, Any] = <factory>, curriculum: dict[str, Any] | None = None, solver: dict[str, Any] = <factory>, run: dict[str, Any] = <fact...

Everything a command needs to build an instance and its solver settings.

def build_parser()

The argparse front-end (always available).

def build_typer_app()

The typer front-end (same commands and options as :func:build_parser).

def cmd_ablate(target: str, variants: str = Ellipsis, n: int = 4, seeds: str = '0,1,2', independent: bool = False, base: str | None = None, classes: str | None = None, dev...

Cumulative (or one-at-a-time) ablation of the instance's method.

def cmd_autotune(target: str, level: str = 'standard', device: str | None = None, seed: int | None = None, scene: str | None = None, out: str | None = None, smoke: bool = Fa...

Auto-tune an instance on a fresh measurement; save the report and a tuned config.

def cmd_bench(target: str, methods: str | None = None, n: int = 4, seeds: str = '0,1,2', classes: str | None = None, metrics: str | None = None, device: str | None = None...

Paired benchmark of several methods; prints the markdown table and saves the reports.

def cmd_bench_merge(directory: str, out: str | None = None, by_class: bool = False, allow_missing: bool = False, quiet: bool = False, verbose: bool = False) -> int

Merge the benchmark shards of a directory into one table (writes the usual reports).

def cmd_diagnose(target: str, device: str | None = None, seed: int | None = None, scene: str | None = None, out: str | None = None, smoke: bool = False, smoke_steps: int = 4...

Diagnostics on a fresh measurement (at initialization, or at the solution with --solve).

def cmd_list(kind: str | None = None, verbose: bool = False, as_json: bool = False) -> int

List registered components (instances, fields, operators, losses, baselines, metrics…).

def cmd_run(target: str, device: str | None = None, seed: int | None = None, scene: str | None = None, out: str | None = None, smoke: bool = False, smoke_steps: int = 4...

Generate a measurement, invert it, evaluate, save everything and print a summary.

def cmd_sweep(target: str, axis: str = Ellipsis, values: str = Ellipsis, n: int = 4, seeds: str = '0,1,2', base: str | None = None, classes: str | None = None, device: st...

One-axis hyperparameter sweep (config field, stage., curriculum., optim., weight.).

def config_files() -> list[Path]

All *.yaml / *.yml / *.json files in :func:config_dirs.

def import_plugin(ref: str)

Import a plugin module by dotted name or by .py path (idempotent).

def load_plugins(extra: Sequence[str] = ())

Import NEFI_PLUGINS, nefi.plugins entry points and extra modules / files.

def load_spec(target: str, overrides: Sequence[str] = (), smoke: bool = False) -> RunSpec

Resolve a CLI target (instance name or config file) plus --smoke and --set.

def main(argv: Sequence[str] | None = None) -> int

Console-script entry point; returns the exit code (usable in-process).

def make_instance(spec: RunSpec) -> Any

Instantiate the registered instance from the configuration file's settings.

def read_spec_file(path: str | Path) -> RunSpec

Parse a config file in either accepted layout (see the module docstring).

def resolve_curriculum(spec: RunSpec, default: Curriculum, smoke: bool = False, smoke_steps: int = 40) -> Curriculum

Curriculum from the config file (or default) + overrides + smoke budget cap.

nefi.config

Config helpers: dataclass <-> dict / YAML, and stable config hashing.

def config_hash(cfg: Any, n: int = 10) -> str

Stable short hash of a config (dataclass or dict).

def from_dict(cls: type[T], d: dict) -> T

Build a (possibly nested) dataclass from a dict, ignoring unknown keys with an error.

def load_config(path: str | Path) -> dict

def save_config(cfg: Any, path: str | Path)

def to_dict(obj: Any) -> Any

Recursively convert dataclasses / tuples / tensors to JSON-serializable objects.

nefi.domain

Physical domain: extents, resolution and normalized coordinate grids.

class Domain(shape: tuple[int, ...], extent: tuple[tuple[float, float], ...], axes: tuple[str, ...] | None = None)

A rectangular physical domain discretized on a uniform grid.

  • at(self, shape: Sequence[int] | int) -> Domain — Same physical extent at a different resolution.
  • axis_coords(self, shape=None, normalized: bool = True, device=None, dtype=None) — List of 1-D cell-center coordinate tensors, one per axis.
  • coarsen(self, factor: int = 2, min_size: int = 4) -> Domain
  • coords(self, shape=None, device=None, dtype=None) -> torch.Tensor — Normalized cell-centered grid, shape (*shape, ndim) with values in [-1, 1].
  • from_dict(d: dict) -> Domain
  • from_spacing(shape: Sequence[int] | int, spacing: float | Sequence[float], origin: float | Sequence[float] = 0.0, axes: Sequence[str] | None = None) -> Domain — Domain from grid shape and physical cell size (e.g. NeTMY: 64 px × 20 nm).
  • ndim (property)
  • numel (property)
  • physical_coords(self, shape=None, device=None, dtype=None) -> torch.Tensor — Physical cell-centered grid, shape (*shape, ndim).
  • refine(self, factor: int = 2) -> Domain
  • size (property) — Physical side lengths.
  • spacing(self, shape: Sequence[int] | None = None) -> tuple[float, ...] — Physical cell size per axis at resolution shape (default native).
  • to_dict(self) -> dict
  • to_normalized(self, x: torch.Tensor) -> torch.Tensor — Map physical coordinates (..., ndim) to [-1, 1].
  • to_physical(self, u: torch.Tensor) -> torch.Tensor
  • unit(shape: Sequence[int] | int, axes: Sequence[str] | None = None) -> Domain — Domain [0, 1]^d.

nefi.errors

Exception hierarchy for nefi. All library errors derive from :class:NefiError.

class ConfigError(...)

Raised for invalid or incomplete configuration.

class NefiError(...)

Base class for all nefi errors.

class OperatorError(...)

Raised by forward operators for invalid inputs.

class RegistryError(...)

Raised when a registry lookup fails.

class ShapeError(...)

Raised when tensor / grid shapes are inconsistent.

class SolverError(...)

Raised when optimization cannot proceed (e.g. persistent NaNs).

nefi.measurement

Observed data container.

class Measurement(data: torch.Tensor, mask: torch.Tensor | None = None, noise_std: float | torch.Tensor | None = None, meta: dict = <factory>)

An observation produced by the forward operator plus noise.

  • energy(self) -> torch.Tensor — Total observed energy ∑ data (masked), used by energy-anchored scale correction.
  • masked_mean(self, x: torch.Tensor) -> torch.Tensor — Mean of x over observed entries.
  • resampled(self, shape: Sequence[int], mode: str = 'auto') -> Measurement — Resample the trailing dims of data (and mask) to shape.
  • shape (property)
  • to(self, device=None, dtype=None) -> Measurement

nefi.priors

The prior catalogue: what you physically know about the unknown → heads, losses, hints.

class Binary(lo: float = 0.0, hi: float = 1.0, sharpen: bool = True, eps_start: float = 1.0, eps_end: float = 0.05, perimeter: float = 0.0)

Two-phase field x ∈ {lo, hi} via a sharpening level-set head.

  • curriculum_hints(self)
  • head(self) -> Head
  • interval(self)
  • losses(self, field_name, context=None)

class Bounded(lo: float = 0.0, hi: float = 1.0, init: float | None = None)

lo ≤ x ≤ hi through a sigmoid head (NeFTY Eq. 6).

  • head(self) -> Head
  • interval(self)

class CombinedPrior(priors: list[Prior], field: str = 'x', ndim: int | None = None, domain: Any = None, top: Prior = <factory>, periodic_axes: tuple[int, ...] = ())

The resolved set of priors for one field (see :func:combine).

  • auto_init (property)
  • base_head(self) -> Head
  • build_field(self, builder: Callable[[int], Field], ndim: int) -> Field — Build the (possibly symmetry-wrapped) field; builder(ndim) makes the inner field.
  • context(self) -> PriorContext
  • curriculum_hints(self) -> dict[str, Any]
  • describe(self) -> str
  • field_hints(self) -> dict[str, Any]
  • head(self) -> Head — The output head: the top prior's head wrapped by modifiers (support, conservation).
  • losses(self) -> LossSpec — {name: (Loss, relative_strength)} of every prior (names made unique).
  • postprocess(self) -> list[Postprocess]

class Conserved(total: float = 1.0, kind: str = 'sum', hard: Any = 'auto', weight: float = 1.0)

The field's total is known (mass / charge / number of particles).

  • losses(self, field_name, context=None)
  • wrap_head(self, head, context)

class KnownSupport(mask: Any = None, fill: float | None = None, hard: bool = True, weight: float = 1.0)

The unknown vanishes (equals fill) outside a known support mask (1 = inside).

  • losses(self, field_name, context=None)
  • wrap_head(self, head, context)

class Monotone(axis: int = 0, direction: str = 'increasing', weight: float = 1.0)

Monotone along an axis (soft penalty on violations).

  • losses(self, field_name, context=None)

class NonNegative(init: Any = 'auto', beta: float = 1.0, peak_ratio: float = 3.0)

x ≥ 0 through a softplus head (x = s · softplus(h)).

  • head(self) -> Head
  • headroom(self) -> float
  • interval(self)

class Periodic(axes: Any = None)

Periodic domain along axes (default: all): regularizers wrap around; with all axes periodic the neural field uses a purely periodic Fourier encoding (no raw coordinates).

  • field_hints(self, ndim=None)
  • resolved_axes(self, ndim: int | None) -> tuple[int, ...]

class PiecewiseConstant(tv: float = 0.01, eps: float = 1e-06, isotropic: bool = True)

Piecewise-constant field: total-variation penalty (isotropic, NeFTY Eq. 22).

  • losses(self, field_name, context=None)

class Positive(init: Any = 'auto')

x > 0 with a log-parameterization x = s · exp(h) (large dynamic ranges).

  • head(self) -> Head
  • interval(self)

class Prior()

Base class. Subclasses are dataclasses with a class-level key (DSL name).

  • auto_init(self) -> bool — True when the head's scale should be fitted to the data by from_forward.
  • curriculum_hints(self) -> dict[str, Any] — Suggestions for :func:nefi.auto.auto_curriculum (e.g. anneal_fraction).
  • describe(self) -> str
  • field_hints(self, ndim: int | None = None) -> dict[str, Any] — Suggestions for the representation (e.g. max_octaves, include_input).
  • head(self) -> Head | None — The output head, or None if this prior does not define one.
  • headroom(self) -> float — Ratio between the head's natural scale and the fitted initial level (1 = same).
  • inner_ndim(self, ndim: int) -> int — Coordinate dimension of the field wrapped by :meth:wrap_field.
  • interval(self) -> tuple[float, float] — Values allowed by this prior (used to check compatibility with other priors).
  • losses(self, field_name: str, context: PriorContext | None = None) -> LossSpec — {name: (Loss, relative_strength)} contributed by this prior.
  • params(self) -> dict[str, Any]
  • parse(spec: Any) -> list[Prior] — Parse the prior DSL (or pass through Prior objects / lists) into a list of priors.
  • postprocess(self, field_name: str | None = None) -> list[Postprocess]
  • rank(self) -> int — Specificity of the head this prior defines (-1: no head).
  • wrap_field(self, inner: Field, ndim: int) -> Field
  • wrap_head(self, head: Head, context: PriorContext) -> Head — Wrap the resolved head (head modifiers such as known support / conservation).

class PriorContext(field: str = 'x', ndim: int | None = None, domain: Any = None, periodic_axes: tuple[int, ...] = (), value_range: tuple[float, float] = (-inf, inf))

Information shared with priors while building losses / heads / fields.

class PriorList(iterable=())

A list of priors supporting + with priors, strings and lists.

class Scale(homogeneity: float | None = None)

Recover the absolute scale after fitting (energy-anchored correction, NeTMY Eq. 30).

  • postprocess(self, field_name=None)

class Smooth(laplacian: float | None = None, tikhonov: float | None = None, gradient: float | None = None)

Smooth field: Laplacian (second-order), gradient (first-order Tikhonov) and/or ridge penalties. With no argument: laplacian=1e-2.

  • field_hints(self, ndim=None)
  • losses(self, field_name, context=None)

class Sparse(l1: float = 0.01, gated: bool = True, init: Any = 'auto', peak_ratio: float = 30.0)

Mostly-zero, non-negative field: gated softplus head (NeTMY Eq. 5) + L1 penalty.

  • auto_init(self) -> bool
  • head(self) -> Head | None
  • headroom(self) -> float
  • interval(self)
  • losses(self, field_name, context=None)
  • rank(self) -> int

class Symmetric(kind: str = 'mirror_x', axes: Any = None, hard: bool = True, weight: float = 1.0)

Mirror or radial symmetry, exact by coordinate folding (hard) or as a penalty.

  • inner_ndim(self, ndim: int) -> int
  • losses(self, field_name, context=None)
  • wrap_field(self, inner, ndim)
  • wraps_field (property)

class Unconstrained(init: Any = 'auto', scale: float = 1.0, offset: float = 0.0)

Signed, unconstrained values (identity/affine head).

  • head(self) -> Head

def combine(priors: Any, field: str = 'x', ndim: int | None = None, domain: Any = None) -> CombinedPrior

Resolve a set of priors for one field: pick the head, check compatibility.

def describe_catalogue() -> str

Markdown table of the DSL (name, class, meaning) — used by the docs.

def parse(spec: Any) -> list[Prior]

Parse spec (DSL string, Prior, list/tuple of those, CombinedPrior) into priors.

def register_prior(name: str, cls: type[Prior]) -> type[Prior]

Make a custom :class:Prior subclass available in the DSL under name.

nefi.problem

The inverse problem: domain + field + operator + losses + measurement (+ post-processing).

class InverseProblem(domain: Domain, field: Field, operator: Operator, losses: LossSet, measurement: Measurement, postprocess: Sequence[Postprocess] = (), curriculum: Curriculum...

A fully specified per-measurement inverse problem.

  • context(self, shape=None, progress: float = 1.0, stage=None, step: int = 0) -> Context
  • describe(self) -> dict
  • device (property)
  • dtype (property)
  • evaluate(self, shape: Sequence[int] | None = None, progress: float = 1.0, grad: bool = False) -> tuple[dict[str, torch.Tensor], torch.Tensor] — Fields and prediction at shape (default native resolution).
  • loss(self, shape=None, progress: float = 1.0, stage=None, step: int = 0) — Total loss and components at the current parameters (with autograd).
  • measurement_at(self, shape: Sequence[int]) -> Measurement
  • to(self, device=None, dtype=None) -> InverseProblem — Move modules to device and cast real floating tensors to dtype.

nefi.registry

A tiny registry so every component is constructible from config ({"type": name, ...}).

def build(kind: str, cfg: str | dict | Any, **extra: Any) -> Any

Instantiate a registered component.

def get(kind: str, name: str) -> Any

def list_registered(kind: str | None = None) -> dict[str, list[str]]

def register(kind: str, name: str | None = None) -> Callable

Decorator registering a class / factory under kind and name.