Skip to content

Python API Reference

This page is generated from the source docstrings by mkdocstrings. It documents the layer facades — the eight modules that make up Gridalyn's supported import surface:

Facade Import it for
gridalyn The flat top-level convenience surface.
gridalyn.foundation Governance, the report contract, capabilities, workspaces.
gridalyn.twin Network topology, ingest adapters, the semantic graph.
gridalyn.assets Building, load, EV, DER modeling and synthetic data generation.
gridalyn.simulation Power-flow builders, scenarios, network-impact analytics.
gridalyn.operations Flexibility-market clearing, dispatch, settlement, KPIs.
gridalyn.projects The StudyProject contract, workflow runner, regression.
gridalyn.interfaces CLI entry points, reporting catalogs, visualization.

Scope of this page

Import from a facade, not from a private submodule. gridalyn.simulation is a supported import path; gridalyn.simulation.simulators.powerflow.builder is an implementation detail that may move between releases.

Only the facades are rendered here. Per-symbol reference pages for every exported name are deliberately out of scope — see Not covered here at the bottom of the page.

How the lazy facades are rendered

Every facade defines its public names in a _LAZY_EXPORTS map and resolves them on first access through a module-level __getattr__, so that import gridalyn stays cheap and optional heavy dependencies (pandapower, lightsim2grid) are never imported until something actually needs them. See Module Boundaries for why.

A consequence is that the exported names do not exist in the module namespace until they are touched, so static analysis of these files finds no members at all. The mkdocstrings python handler is therefore configured with force_inspection: true: it imports each facade and reads its members, which resolves every entry in _LAZY_EXPORTS. Each facade also defines a __dir__, so dir() and inspect.getmembers report the same names the documentation does.

All eight facades are introspectable this way; none had to be omitted. A facade entry that is a plain re-export or alias resolves to the symbol it points at, so it is documented once, under its owning definition.

Only names carrying a docstring are shown. 213 of the 220 names exported by the seven layer facades render; 7 do not, because the function they ultimately resolve to has no docstring yet:

Facade Name
gridalyn.twin build_semantic_graph, validate_semantic_graph
gridalyn.interfaces build_digital_twin_reports, canonical_report, write_dashboard_catalog, write_json, write_report

They are importable and supported; they are simply undocumented, and they will appear here as soon as they are described at their definition site.


gridalyn

Gridalyn public Python API.

The top-level facade re-exports a curated subset of the layer facades below, so a script can do from gridalyn import build_ieee33_benchmark_feeder without knowing which layer owns it. Its 51 names are documented under their owning layer rather than repeated here.

gridalyn.foundation

Foundation contracts for governance, validation, and artifacts.

This facade is the stable home for cross-cutting platform contracts.

TYPE_CHECKING = False

bool(x) -> bool

Returns True when the argument x is true, False otherwise. The builtins True and False are the only two instances of the class bool. The class bool is a subclass of the class int, and cannot be subclassed.

ArtifactLayout

Canonical artifact paths for a Gridalyn workspace.

A workspace can materialize more than one digital twin. The instance field selects which named twin under <root>/instances/ the layout points at; "default" is the canonical workspace twin and the unchanged default for existing callers. Commands, scripts, tests, documentation, and dashboard mounts resolve through ArtifactLayout(root, instance=...) so that gridalyn twin is a general mechanism for any twin of any project, not a single hard-wired instance.

root is the WORKSPACE root -- the directory holding pyproject.toml, gridalyn/, projects/ and instances/ -- never a study's own directory. Passing a study directory is what pointed a layout at a path that does not exist in bd 7rt; the :class:WorkspaceRoot type makes mypy reject it.

default_instance

Legacy alias for the canonical default instance directory.

instance = 'default'

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

instance_dir

Directory of the selected named twin instance.

observations

Directory a deployment's MEASURED observations are read from.

The one artifact directory whose contents this repo never ships. The SDK ships the ingest path -- gridalyn.twin.observation.ingest -- and a deployment becomes a digital shadow when its operator puts their own AMI/SCADA export here alongside the entity join. Naming the location in the layout is what lets the catalog say "there are none, and here is where they would go" rather than leaving a consumer to guess whether it looked in the right place.

root = PosixPath('.')

Path subclass for non-Windows systems.

On a POSIX system, instantiating a Path should return this object.

ArtifactPolicy

Small, serializable artifact policy for a Gridalyn repository.

allowed_tracked_patterns = ('gridalyn/assets/datagen/models/weights/*.pkl',)

Built-in immutable sequence.

If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.

If the argument is a tuple, the return value is the same object.

forbidden_tracked_patterns = ('_build/*', 'site/*', 'cache/*', '.roo/*', '.agents/*', '.codex/*', '.claude/*', '.cursor/*', '.windsurf/*', 'manuscripts/*', 'examples/generated/cache/*', 'examples/generated/outputs/*', 'projects/*/outputs/*', 'dashboard/public/*', 'instances/*/digital_twin/timeseries/*', 'instances/*/digital_twin/**/*.parquet', 'instances/*/digital_twin/**/*.pkl', 'instances/*/digital_twin/**/*.npy', 'instances/*/digital_twin/**/*.npz', 'instances/*/digital_twin/models/**/*.parquet', 'instances/*/digital_twin/semantic/*.parquet', 'manuscripts/**/*.aux', 'manuscripts/**/*.bbl', 'manuscripts/**/*.bcf', 'manuscripts/**/*.blg', 'manuscripts/**/*.fdb_latexmk', 'manuscripts/**/*.fls', 'manuscripts/**/*.lof', 'manuscripts/**/*.log', 'manuscripts/**/*.lot', 'manuscripts/**/*.out', 'manuscripts/**/*.run.xml', 'manuscripts/**/*.synctex.gz', 'manuscripts/**/*.toc', 'manuscripts/**/*.pdf', '*.h5', '*.hdf5', '*.pkl', '*.npy', '*.npz')

Built-in immutable sequence.

If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.

If the argument is a tuple, the return value is the same object.

max_demo_dataset_bytes = 10485760

int([x]) -> integer int(x, base=10) -> integer

Convert a number or string to an integer, or return 0 if no arguments are given. If x is a number, return x.int(). For floating-point numbers, this truncates towards zero.

If x is not a number or if base is given, then x must be a string, bytes, or bytearray instance representing an integer literal in the given base. The literal can be preceded by '+' or '-' and be surrounded by whitespace. The base defaults to 10. Valid bases are 0 and 2-36. Base 0 means to interpret the base from the string as an integer literal.

int('0b100', base=0) 4

minimal_dataset = 'examples/tutorials/data/minimal'

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

required_gitignore_patterns = ('_build/', '/site', 'cache/', '.roo/', '.agents/', '.codex/', '.claude/', '.cursor/', '.windsurf/', 'manuscripts/', 'examples/generated/outputs/', 'examples/generated/cache/', 'projects/*/outputs/', 'dashboard/public/', 'instances/*/digital_twin/**/*.parquet', 'instances/*/digital_twin/timeseries/', 'manuscripts/**/*.aux', 'manuscripts/**/*.fdb_latexmk', 'manuscripts/**/*.synctex.gz', 'manuscripts/**/*.pdf')

Built-in immutable sequence.

If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.

If the argument is a tuple, the return value is the same object.

required_minimal_dataset_files = ('manifest.json', 'grid_nodes.geojson', 'grid_edges.geojson', 'buildings.geojson', 'scenarios.json', 'expected_summary.json')

Built-in immutable sequence.

If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.

If the argument is a tuple, the return value is the same object.

ArtifactPolicyReport

Result of checking a repository against an artifact policy.

GridalynWorkspace

A repository or application workspace using Gridalyn artifact contracts.

root is the workspace root, as for :class:ArtifactLayout.

instance = 'default'

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

root = PosixPath('.')

Path subclass for non-Windows systems.

On a POSIX system, instantiating a Path should return this object.

ModelVersion

Version contract for a digital-twin model snapshot.

ReportMetadata

Identity and provenance header for a platform report.

Every artifact-producing run emits a report through :func:write_report, and this frozen record supplies the non-payload half of that envelope: what the report is called, which domain produced it, and the governance ids that let a result be traced back to the model version and study run it came from.

Attributes:

Name Type Description
report_id

Stable identifier for this report within its domain.

source_domain

Producing layer or domain, e.g. "simulation".

schema_version

Report contract version; defaults to :data:SCHEMA_VERSION.

project

Project descriptor (name, paths) carried into the envelope.

model_version_id

Governance id of the model version used, if tracked.

study_run_id

Governance id tying this report to one study run.

schema_version = '1.0'

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

StudyRun

Run contract for a governed project workflow execution.

ProjectDir(x)

NewType creates simple unique types with almost zero runtime overhead.

NewType(name, tp) is considered a subtype of tp by static type checkers. At runtime, NewType(name, tp) returns a dummy callable that simply returns its argument.

Usage::

UserId = NewType('UserId', int)

def name_by_id(user_id: UserId) -> str:
    ...

UserId('user')          # Fails type check

name_by_id(42)          # Fails type check
name_by_id(UserId(42))  # OK

num = UserId(5) + 1     # type: int

WorkspaceRoot(x)

NewType creates simple unique types with almost zero runtime overhead.

NewType(name, tp) is considered a subtype of tp by static type checkers. At runtime, NewType(name, tp) returns a dummy callable that simply returns its argument.

Usage::

UserId = NewType('UserId', int)

def name_by_id(user_id: UserId) -> str:
    ...

UserId('user')          # Fails type check

name_by_id(42)          # Fails type check
name_by_id(UserId(42))  # OK

num = UserId(5) + 1     # type: int

build_model_version(*, source_system, source_adapter, source_standard, source_format, artifact_metadata, counts, validation, lineage=None, schema_version='1.0', created_at=None)

Build a deterministic model version from source lineage and artifacts.

build_report(*, metadata, inputs=None, artifacts=None, summary=None, validation=None, uncertainty=None)

Build a report payload that follows the platform report contract.

Parameters:

Name Type Description Default
metadata ReportMetadata

Identity and provenance header for the report.

required
inputs list[dict[str, Any]] | None

Input provenance records.

None
artifacts list[dict[str, Any]] | None

Artifact provenance records.

None
summary dict[str, Any] | None

The run's headline numbers.

None
validation dict[str, Any] | None

The run's own pass/fail payload.

None
uncertainty dict[str, Any] | None

Optional intervals qualifying headline numbers in summary, keyed by metric name. Build it with :func:gridalyn.foundation.platform.uncertainty.build_uncertainty rather than by hand. Omitted from the payload when absent -- an empty block is a contract error, not a neutral default.

None

Returns:

Type Description
dict[str, Any]

The report payload.

Raises:

Type Description
ValueError

If uncertainty is given but does not satisfy the contract, naming each failing field.

build_study_run(*, project_id, project_version, workflow_id, dry_run, status, started_at, ended_at, git_commit, stages, lineage=None, schema_version='1.0')

Build a governed project run summary from stage execution records.

check_artifact_policy(root, *, policy=None, tracked_files=None)

Check artifact policy without mutating the repository.

file_reference(path, root=None)

Return a small provenance record for a file.

find_workspace_root(start='.')

Discover a Gridalyn workspace from a nested path.

Git metadata is useful during development, but public archives should also work cleanly. The marker walk keeps source distributions independent from a local repository checkout.

layout_from_environment(*, default_root=PosixPath('.'), instance_env='GRIDALYN_INSTANCE', root_env='GRIDALYN_WORKSPACE_ROOT')

Resolve a twin layout from CLI-threaded environment variables.

gridalyn twin sets GRIDALYN_WORKSPACE_ROOT and GRIDALYN_INSTANCE before dispatching a layer script, so every twin layer script can materialize on any named instance of any workspace without knowing the workspace root or instance itself. When the variables are unset (scripts run directly), the layout falls back to the script's own default root and the canonical default instance — unchanged from pre-generalization behaviour.

read_json_report(path)

Read a JSON report into a dictionary.

validate_report(payload)

Return contract validation errors for a report payload.

validate_workspace(root='.', *, projects=None, check_project_artifacts=True, run_regression=False)

Validate repository-level policy and one or more project contracts.

Delegates to the validator the projects layer registers on import; every supported entry point (the gridalyn CLI, from gridalyn import projects, the project scripting helpers) imports that layer before calling this function.

Parameters:

Name Type Description Default
root Path | str

Workspace root, or any path inside it, to validate.

'.'
projects list[str] | tuple[str, ...] | None

Repo-relative project paths to check; when None, every project the workspace discovers is checked.

None
check_project_artifacts bool

Also check required project reports and figures exist.

True
run_regression bool

Also run configured project regression checks.

False

Returns:

Type Description
The composed check payload

{"valid", "checks", "summary"}.

Raises:

Type Description
RuntimeError

If no validator has been registered yet, with the remediation in the message.

workspace_from_environment(*, default_root=PosixPath('.'), instance_env='GRIDALYN_INSTANCE', root_env='GRIDALYN_WORKSPACE_ROOT')

Resolve a twin workspace from CLI-threaded environment variables.

Companion to :func:layout_from_environment for scripts that bind a GridalynWorkspace instead of a bare layout (e.g. the base exporter).

workspace_from_path(start='.', *, instance='default')

Create a workspace object by discovering the nearest Gridalyn root.

workspace_from_root(root=PosixPath('.'), *, instance='default')

Create a workspace object from a repository root.

write_manifest(path, *, reports, root=None, report_paths=None)

Write a compact manifest indexing platform reports by report_id.

write_report(path, *, metadata, inputs=None, artifacts=None, summary=None, validation=None, uncertainty=None)

Build, validate, and write a platform report.

Parameters:

Name Type Description Default
path Path | str

Destination for the JSON report.

required
metadata ReportMetadata

Identity and provenance header.

required
inputs list[dict[str, Any]] | None

Input provenance records.

None
artifacts list[dict[str, Any]] | None

Artifact provenance records.

None
summary dict[str, Any] | None

The run's headline numbers.

None
validation dict[str, Any] | None

The run's own pass/fail payload.

None
uncertainty dict[str, Any] | None

Optional intervals qualifying entries of summary.

None

Returns:

Type Description
dict[str, Any]

The written payload.

Raises:

Type Description
ValueError

If the assembled payload violates the report contract.

gridalyn.twin

Digital-twin model, observation, adapter, and semantic graph facade.

This is one of the advertised public layer facades (see tests/test_public_api_surface.py), so it declares what the layer is, not merely what other in-repo modules happen to import from it. The layer owns four things and each is reachable here: the canonical model (:class:NetworkModel and its identity), the repository that loads and validates it, the source adapters that produce it, and — since the observation contract came down from gridalyn.simulation — the observed state. That observed-state surface has two producers, both reachable here: the simulated one reads state off a solved network (:func:observe_network), and the measured ingest reads tidy measurement rows against a user-declared :class:EntityJoin (:func:read_measured_observations / :func:load_measurements), each resolved by explicit ID through the observation producer registry (:func:default_observation_producer_registry).

The criterion every entry below satisfies, derived from the entries that were already here: a name belongs on this facade when it is a public entry point of the layer, or a type that appears in the signature of one. That is why :class:NetworkIntegrityReport, :class:DownstreamAssets and :class:ModelIdentity are here despite no in-repo module importing them from this path — they are what :class:NetworkModelRepository hands back, and this facade is an advertised SDK surface rather than a record of internal imports.

ModelAuthoritySet and ModelProfile are exported because both source adapters' authority_sets() and profiles() return them — the criterion above, which they were already recorded as meeting. Like every other entry they resolve through a sub-facade: gridalyn.twin.adapters re-exports them from the implementation module gridalyn.twin.adapters.authority, and this facade points at gridalyn.twin.adapters, never at the implementation. (The module path moved from …adapters.cim to …adapters.authority in review cycle 1 of Phase 11 — see that module's docstring for why.)

Names deliberately NOT re-exported here, each for a measured reason:

  • BASE_TABLE_SCHEMAS / table_schema (gridalyn.twin.network.schema) — the declared column contract between the repository and its adapters. It appears in no public signature and both of its production consumers live inside this layer, so promoting it would advertise an internal contract as SDK surface.
  • AS_OF_ABSENT_REASON / SCENARIO_TIME_ABSENT_REASON — documentation constants that travel with their fields, not API.

CimParquetAdapter

Adapter from CIM-like Parquet tables to canonical base Parquet.

adapter_id = 'cim_parquet'

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

capabilities = ('load_snapshot', 'export_base_parquet', 'write_base_metadata', 'write_validation_report')

Built-in immutable sequence.

If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.

If the argument is a tuple, the return value is the same object.

source_adapter = 'CimParquetAdapter'

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

source_format = 'cim-parquet'

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

source_standard = 'cim'

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

authority_sets()

Return the Model Authority Sets partitioning models this produces.

Returns:

Type Description
tuple[ModelAuthoritySet, ...]

The declared partition. Measured today it has exactly one member -- see :data:~gridalyn.twin.adapters.authority.AUTHORITY_SET_PARTITION_IS_SINGLE_MEMBER.

Raises:

Type Description
UnknownModelAuthoritySetError

If this adapter declares no set.

describe()

Return stable adapter identity and capability metadata.

export(*, out_dir, root)

Write canonical base artifacts and repository-centric metadata.

load_snapshot()

Load CIM-like source tables and normalize them to canonical tables.

Returns:

Type Description
The canonical

class:NetworkModel.

Raises:

Type Description
ValueError

If this adapter's declared Model Authority Sets do not partition the canonical base artifacts. Checked here, before any IO, so the CGMES declarations are consumed on every load rather than only when a model is exported.

profiles()

Return the declared profiles of the base this adapter exports.

Returns:

Type Description
tuple[ModelProfile, ...]

Every profile in :data:~gridalyn.twin.adapters.authority.BASE_MODEL_PROFILES, ordered by profile ID.

ConnectedEquipment

Equipment and customer assets directly connected to a bus.

DownstreamAssets

Customer assets served by one upstream network element.

Attributes:

Name Type Description
upstream_id

Identifier of the element the assets hang off -- a transformer for :meth:NetworkModelRepository.get_downstream, a feeder for :meth:NetworkModelRepository.get_feeder. It was called constraint_id until Phase 11 (plan 11-03), which was wrong twice over: get_feeder stored a feeder id in it, and neither query takes a constraint. constraint_zone_id in gridalyn/operations is a different, live concept -- the flexibility-market zone -- and is untouched.

building_ids

Buildings served, sorted and deduplicated.

load_ids

Loads served, sorted and deduplicated.

bus_ids

Buses the served customers connect to, sorted and deduplicated.

EntityJoin

User-supplied declared join from measured entities to twin buses.

The join is configuration, never inference: which measured entity sits on which bus is a fact only the operator of the observed system knows, and inventing it is exactly what disqualified the datasets/hq branch as a measured producer -- its 1000 anonymous ordinal columns carry no key into the twin's building_id/bus_id namespace, so any binding would have been manufactured rather than measured. An entity absent from this join is therefore a located error naming the entity, never a guess.

Attributes:

Name Type Description
bus_by_entity

Declared mapping from a measured entity_id to the bus_id it sits on. Both are strings; bus_id is the twin's declared grid_buses identity namespace (:data:gridalyn.twin.network.schema.GRID_BUSES).

from_frame(frame)

Build a join from a two-column entity_id/bus_id frame.

Parameters:

Name Type Description Default
frame DataFrame

Declared join table carrying an entity_id column and a bus_id column. Identifier values are read through astype(str), the identity comparison the declared schema uses for every grid_buses reference.

required

Returns:

Type Description
EntityJoin

The validated join.

Raises:

Type Description
ValueError

If a required column is missing, any entry is null, or an entity_id appears more than once (the duplicates are named).

from_mapping(mapping)

Build a join from a declared entity_id -> bus_id mapping.

Parameters:

Name Type Description Default
mapping Mapping[str, str]

Declared entity-to-bus pairs. Must be non-empty, and every key and value must be a non-empty string.

required

Returns:

Type Description
EntityJoin

The validated join.

Raises:

Type Description
ValueError

If the mapping is empty, or any key or value is None, empty, or not a string.

ModelAuthoritySet

A CGMES Model Authority Set expressed over the canonical parquet tables.

In CGMES a Model Authority Set is the disjoint set of objects one party owns, so an interconnection model can be assembled from parts with different owners. Here the "objects" are canonical base artifacts and the "party" is the source adapter that produced them.

Attributes:

Name Type Description
authority_set_id

Stable identifier, the CGMES Model.modelingAuthority Set analogue. Never derived from a class name at run time, so renaming a class cannot silently repartition a model.

authority

Name of the party that owns the artifacts -- the producing adapter class.

adapter_id

Stable adapter ID this set is keyed by, matching metadata.json's adapter_id and the network adapter registry.

source_standard

Source data standard the authority publishes in.

artifacts

Canonical artifacts this authority owns, written out as a literal. Must be a subset of :data:CANONICAL_ARTIFACTS; the partition as a whole must cover it exactly and without overlap. Aliasing :data:CANONICAL_ARTIFACTS here is what made the rule tautological in plan 11-05 -- see that constant's docstring.

as_dict()

Render the set as JSON-native values.

Returns:

Type Description
dict[str, Any]

A mapping of str keys to str/list[str] values only, so it serializes with :func:json.dumps without a custom encoder and can land in a manifest as-is.

ModelIdentity

Identity of a canonical network model, read from its manifest.

Three fields carry CGMES FullModel header semantics — not the RDF/XML serialization, which this repository does not produce:

================== ========================================================== CGMES header field Source in this repository ================== ========================================================== id (mRID) metadata.json model_version_id (a content digest produced by :func:build_model_version) created metadata.json created_at scenarioTime no source — always None; see :data:SCENARIO_TIME_ABSENT_REASON profile :data:BASE_PROFILE_ID joined to the manifest's BASE_METADATA_SCHEMA_VERSION ================== ==========================================================

profile is constant for every model this repository can produce, and that is correct rather than a defect: a CGMES profile identifier names the profile a model conforms to, so all models conforming to one profile share it. It varies when a second profile is declared, not per model.

Two fields deliberately do not claim a CGMES mapping, because the values they carry do not honour one. Both were named for CGMES fields by plan 11-01 and renamed in review cycle 1 of Phase 11:

  • artifact_paths (was dependent_on) holds workspace-relative parquet paths. CGMES Model.DependentOn references other models by mRID; a base here is assembled from files, not from other models, and there is exactly one model per base, so the CGMES field has nothing to point at. The name now says what the field holds.
  • governance_schema_version (was version) holds model_version.schema_version, which is :data:~gridalyn.foundation.platform.governance.GOVERNANCE_SCHEMA_VERSION — the literal "1.0" for every model this repository can produce. CGMES version exists to order successive revisions of the same model; nothing here revises a model, and what does distinguish two models is the content digest already carried in id. A constant cannot do the job the CGMES name advertises, so the field is named for the constant it is.

Attributes:

Name Type Description
id

Content digest identifying this model, the CGMES mRID analogue.

created

ISO-8601 UTC instant the model version was stamped.

scenario_time

Always None; see :data:SCENARIO_TIME_ABSENT_REASON.

governance_schema_version

Governance contract version the manifest's model_version record was built against.

profile

Profile identifier the base conforms to.

artifact_paths

Workspace-relative paths of the parquet artifacts the manifest declares this model is assembled from, sorted.

artifact_paths = ()

Built-in immutable sequence.

If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.

If the argument is a tuple, the return value is the same object.

ModelProfile

A profile declaration over the canonical base artifacts.

A CGMES profile composes the dataset exchanged for one purpose. Here the analogue is a canonical artifact set, and the dependencies are derived from :data:gridalyn.twin.network.schema.BASE_TABLE_SCHEMAS -- a profile depends on another exactly when one of its declared columns references that artifact. Nothing here is hand-declared, so a dependency cannot be invented and cannot go stale against the schema.

depends_on is not CGMES Model.DependentOn. That header field references other model instances by mRID; this repository produces exactly one model per base, so there is no second model to reference and the CGMES field has no analogue here. What this field holds is profile IDs -- a dependency between profiles, which is a different relation -- and it is named, and serialized, for what it holds. Plan 11-05 serialized it under the key dependent_on, which dressed profile IDs as the header field; that rename is undone.

Attributes:

Name Type Description
profile_id

Stable identifier, e.g. "gridalyn:digital-twin-base/grid_lines".

version

Manifest schema version the profile is declared against.

artifacts

Canonical artifacts the profile carries.

depends_on

Profile IDs this profile cannot be read without. Every entry is a key of :data:BASE_MODEL_PROFILES.

as_dict()

Render the profile as JSON-native values.

Returns:

Type Description
dict[str, Any]

A mapping of str keys to str/list[str] values only, so it serializes with :func:json.dumps without a custom encoder. The depends_on key matches the field name: these are profile IDs, not CGMES Model.DependentOn model references.

NetworkAdapterDescriptor

Stable identity and capability metadata for a network source adapter.

contract_version = '1'

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

NetworkAdapterRegistry

Discover and instantiate network source adapters by stable ID.

create(adapter_id, **kwargs)

Instantiate a registered adapter.

get_descriptor(adapter_id)

Return descriptor metadata for a registered adapter.

list_descriptors()

Return registered adapter descriptors sorted by adapter ID.

register(factory, *, descriptor=None, replace=False)

Register an adapter factory.

NetworkExportResult

Result of exporting a canonical base network snapshot.

Attributes:

Name Type Description
out_dir

Directory the canonical artifacts were written to.

metadata_path

Path of the metadata.json manifest written.

validation_report_path

Path of the adapter validation report.

artifact_paths

Canonical artifact name to the path written.

counts

Row counts per canonical table.

identity

Identity of the model just exported, read back through the repository read path rather than assembled by the producer -- see :func:exported_model_identity.

NetworkIntegrityReport

Validation summary for a loaded network model.

NetworkModel

The canonical network model: five asset tables plus its own identity.

This is the only canonical model type. The adapter-side twin of it — NetworkSnapshot — was merged into it in Phase 11 (plan 11-01) because the two held the same five frames with byte-identical counts.

Attributes:

Name Type Description
operational_state

Which operational state this snapshot represents, or None when nothing has declared one — see :data:OPERATIONAL_STATE_ABSENT_REASON. None rather than "base" is deliberate: a model built in memory by a source adapter has no evidence for any state, and this module already refuses to invent such values twice over (scenario_time is permanently None with :data:SCENARIO_TIME_ABSENT_REASON, and provenance_status defaults to the ABSENT sentinel rather than to a plausible value). "base" is a repository resolution default, not a model-level claim: :meth:~gridalyn.twin.network.repository.NetworkModelRepository.load_model always stamps a non-None state, while a bare model carries None.

counts

Return row counts per canonical table plus the distinct load count.

has_provenance

Report whether an on-disk metadata.json manifest backs this model.

Returns:

Type Description
bool

True only when the model was loaded from a repository whose metadata manifest was present and parseable. A model built in memory by a source adapter is False: it carries source_adapter and source_standard, but no manifest has been written for it yet.

provenance_status = 'absent'

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

write_parquet(out_dir)

Write the model to the canonical base Parquet artifacts.

Parameters:

Name Type Description Default
out_dir Path

Directory to write the five canonical tables into; created with parents if it does not exist.

required

Returns:

Type Description
dict[str, Path]

Mapping of canonical artifact name to the path written.

NetworkModelRepository

Read and query a canonical network model snapshot.

Attributes:

Name Type Description
base_dir

Directory holding the canonical base Parquet artifacts and their metadata.json manifest.

provenance

What to do when the manifest is absent -- and, for "ignore", whether the manifest is consulted as authority at all. "require" raises, "warn" (the default) returns an explicitly degraded model and warns, "ignore" returns the degraded model silently and exists for the manifest producer, which by construction runs before the manifest it writes. A model loaded without provenance is never a silent success under the default policy.

"ignore" therefore also means an existing manifest is not read as authority: its "operational_state" is neither used nor validated, and the state resolves from this repository's declared one, else :data:~gridalyn.twin.network.model.DEFAULT_OPERATIONAL_STATE. Without that widening the producer would be gated on the very file it is about to overwrite, so a corrupt "operational_state" would block the writer that exists to repair it. "warn" and "require" read and validate the key exactly as before.

Each policy has a production caller, which is why all three are kept: "ignore" in :func:build_base_metadata, "require" in :func:gridalyn.twin.adapters.network.exported_model_identity (the export post-condition), "warn" everywhere else by default.

operational_state

Which operational state this repository loads its models as, or None when the caller declared none. None means UNDECLARED, not "base": collapsing the two would make "the caller explicitly asked for base" and "the caller said nothing" the same value, and the resolution order that reads a state back off the manifest branches on exactly that difference. A caller that declares nothing still loads a model stamped :data:~gridalyn.twin.network.model.DEFAULT_OPERATIONAL_STATE, so the sentinel costs no existing call site a change.

provenance = 'warn'

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

get_connected_equipment(bus_id)

Return lines, transformers, buildings, and loads connected to a bus.

get_downstream(transformer_id)

Return buildings, loads, and buses downstream of a transformer.

Parameters:

Name Type Description Default
transformer_id str

Identifier of the MV/LV transformer to look under.

required

Returns:

Type Description
DownstreamAssets

The assets it serves, keyed by upstream_id.

Raises:

Type Description
ValueError

If a non-empty connectivity table declares no transformer column (see :mod:gridalyn.twin.network.schema).

get_feeder(feeder_id)

Return customer assets served by a feeder or LV feeder bus.

Parameters:

Name Type Description Default
feeder_id str

Identifier of the feeder, its head bus, or -- for producers that write only the integer LV cluster label -- that label rendered as a string.

required

Returns:

Type Description
DownstreamAssets

The assets it serves, keyed by upstream_id.

Raises:

Type Description
ValueError

If a non-empty connectivity table declares no feeder column (see :mod:gridalyn.twin.network.schema).

load_model()

Load the canonical network tables together with their provenance.

Returns:

Type Description
A

class:NetworkModel whose identity and provenance_status come from metadata.json when it is present, and which is explicitly marked "absent" when it is not. Its operational_state is always non-None, resolved on both paths as declared state, else manifest, else :data:~gridalyn.twin.network.model.DEFAULT_OPERATIONAL_STATE, with the manifest leg skipped under provenance="ignore", where the file is not authority (see :attr:provenance).

Raises:

Type Description
FileNotFoundError

If the manifest is missing and this repository was constructed with provenance="require".

ValueError

If the manifest exists but is not a JSON object, or -- under any policy but "ignore" -- records an unreadable "operational_state".

resolved_operational_state()

Return the operational state this repository loads models as.

Resolves all three legs of the rule — the state this repository declared, else the snapshot manifest's "operational_state", else :data:~gridalyn.twin.network.model.DEFAULT_OPERATIONAL_STATE — by delegating to the same resolver and the same manifest read that :meth:load_model uses. The two therefore agree by construction: repo.resolved_operational_state() is what repo.load_model().operational_state will be.

Reading the manifest is what buys that agreement, so this method touches disk and obeys the provenance policy exactly as :meth:load_model does: on a snapshot with no manifest, provenance="warn" (the default) emits :class:MissingProvenanceWarning, provenance="require" raises, and provenance="ignore" is silent. Under "ignore" the manifest is additionally not consulted for the state itself -- see :attr:provenance -- so the answer is the declared state, else the default. Call it once and keep the value if that matters.

Returns:

Type Description
The resolved state, never ``None``

every model this repository loads carries one, while a model built in memory by a source adapter carries None — see :data:~gridalyn.twin.network.model.OPERATIONAL_STATE_ABSENT_REASON.

Raises:

Type Description
FileNotFoundError

If the manifest is missing and this repository was constructed with provenance="require".

ValueError

If the manifest exists but is not a JSON object, or records an unreadable "operational_state".

validate_integrity()

Validate that the declared base artifacts exist and hang together.

Three outcomes are kept apart, which is the whole point of the declared schema: an absent artifact is an error, because a missing file and an empty table are otherwise the same observation and the answer degenerates to "healthy"; a present but empty artifact is a warning, because every check over it is vacuous but a source adapter may legitimately export one (a CIM source with no power_transformers table, for instance); an intact artifact is checked for real.

Returns:

Type Description
NetworkIntegrityReport

The integrity report. valid is false when any error was raised, including an absent artifact.

NetworkObservation

What a controller can see from one solved network state.

Constructed either from a solved network via :func:observe_network or directly from arrays by any producer of solved results -- a different power-flow backend, or a surrogate. No field is a pandapower type, which is what makes this a seam rather than a helper.

Comparison is by identity (eq=False): the generated __eq__ would compare array fields element-wise and then raise ValueError on the ambiguous truth value. Compare fields explicitly instead.

The arrays alias the result tables they were read from, exactly as the to_numpy(dtype=float) calls they replace did. Treat them as read-only.

Attributes:

Name Type Description
converged

Whether the producer reported a converged solution.

bus_ids

Identifier per entry of bus_voltage_pu, in the same order.

bus_voltage_pu

Per-bus voltage magnitude in per-unit. Empty when the producer reported no bus voltages.

line_loading_percent

Per-line loading as a percentage of rating. Empty when the producer reported no line loadings.

total_line_loss_mw

Total active line loss in MW, or None when the producer reported no loss at all. None and 0.0 are different answers and callers that distinguish them rely on it.

provenance

Where the values came from -- "simulated" or "measured". This is what lets a consumer holding only the object distinguish a simulation result from a measurement. Required deliberately, with no default, so that no producer can omit the answer.

as_of

The instant this state belongs to, supplied by whoever knows it. None means no instant was reported -- see :data:AS_OF_ABSENT_REASON. It is never filled in from the wall clock, so None here is a fact about the producer rather than a gap in the reader's knowledge.

max_line_loading_percent

Return the highest line loading as a percentage of rating.

Returns:

Type Description
float

The maximum over non-NaN entries, or nan when no line loading was observed.

max_voltage_pu

Return the highest bus voltage magnitude in per-unit.

Returns:

Type Description
float

The maximum over non-NaN entries, or nan when no bus voltage was observed.

min_voltage_pu

Return the lowest bus voltage magnitude in per-unit.

Returns:

Type Description
float

The minimum over non-NaN entries, or nan when no bus voltage was observed.

drop_missing()

Return the observation restricted to entries that were reported.

Bus and line arrays are filtered independently, each keeping only its non-NaN entries, exactly as the separate dropna() calls this replaces did. This is the explicit form of a distinction the tree already made silently: reductions agree either way, but any count divided by the array length does not.

Returns:

Type Description
NetworkObservation

A new observation over the reported entries. converged, total_line_loss_mw, provenance and as_of are scalars and carry through unchanged -- filtering unobserved buses moves neither the instant the state belongs to nor where it came from.

voltage_frame()

Return the canonical two-column bus-voltage table.

Returns:

Type Description
DataFrame

A frame with columns ["bus_id", "vm_pu"], one row per observed bus, in observation order -- the shape both the scenario runner and the voltage-profile figure rebuilt independently.

voltage_violation_counts(*, below_pu, above_pu)

Count buses outside a voltage band.

Parameters:

Name Type Description Default
below_pu float

Lower limit; a bus strictly below it is under-voltage.

required
above_pu float

Upper limit; a bus strictly above it is over-voltage.

required

Returns:

Type Description
tuple[int, int]

(under_voltage_count, over_voltage_count) over :attr:bus_voltage_pu as held. A NaN entry compares false against both limits and so counts as neither, matching the pandas comparisons these counts replace. Call :meth:drop_missing first when the denominator must exclude unobserved buses.

NetworkSourceAdapter

Bases: typing.Protocol

Contract for adapters that can produce canonical network snapshots.

Declared as read-only properties, not plain attributes: every known implementer (SyntheticPandapowerAdapter, CimParquetAdapter) is a frozen dataclass, so a plain name: type declaration -- which Protocol structural matching treats as requiring a settable attribute -- flags a false-positive mismatch against both. Nothing ever assigns to these fields; read-only is what every implementer already is.

adapter_id

Stable identifier of the network source adapter.

capabilities

Capabilities this adapter declares.

geographic_crs

CRS the lat/lon columns this adapter writes are measured in.

A declaration of what the adapter produces, exactly like :attr:source_standard and :attr:source_format, not an inference about the data it happened to read. None means the adapter makes no claim, and a reader then falls back to :data:~gridalyn.twin.network.geography.DEFAULT_GEOGRAPHIC_CRS and reports the value as assumed rather than declared.

source_adapter

Class name of the producing source adapter.

source_format

Source serialization format.

source_standard

Source data standard, e.g. "pandapower".

export(*, out_dir, root)

Write canonical base artifacts and metadata.

load_snapshot()

Load a source model into the canonical in-memory tables.

ObservationProducerDescriptor

Identity and provenance metadata for a registered producer.

Attributes:

Name Type Description
producer_id

Stable ID the producer resolves by. Explicit and declared at registration -- never discovered from an entry point.

provenance

The :data:ObservationProvenance every observation this producer emits carries, so a caller can pick a producer by where its values come from before resolving it.

summary

One human-readable sentence naming the producer's source.

contract_version = '1'

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

ObservationProducerRegistry

Look up observation producers by stable, explicit ID.

Producers are functions, not instantiable adapters, so :meth:resolve replaces the adapter registry's create: it returns the registered callable itself rather than calling a factory.

get_descriptor(producer_id)

Return descriptor metadata for a registered producer.

Parameters:

Name Type Description Default
producer_id str

Stable ID of the producer.

required

Returns:

Type Description
ObservationProducerDescriptor

The descriptor supplied at registration.

Raises:

Type Description
UnknownObservationProducerError

If no producer carries the ID; the message lists the available IDs.

list_descriptors()

Return registered producer descriptors sorted by producer ID.

Returns:

Type Description
list[ObservationProducerDescriptor]

The descriptors, in ascending producer_id order.

register(producer, *, descriptor, replace=False)

Register an observation producer under its descriptor's ID.

Parameters:

Name Type Description Default
producer Callable

The producer callable, handed back verbatim by :meth:resolve.

required
descriptor ObservationProducerDescriptor

Identity and provenance metadata. Keyword-only and required: producers are plain functions, so there is nothing to derive a descriptor from.

required
replace bool

Allow overwriting an existing registration. Defaults to False so a duplicate ID fails loudly.

False

Raises:

Type Description
ValueError

If the ID is already registered and replace is False.

resolve(producer_id)

Return the registered producer callable itself.

This is the deliberate divergence from NetworkAdapterRegistry.create: producers are functions rather than instantiable adapters, so there is no factory to call -- the registry hands back the real producer, never a wrapper.

Parameters:

Name Type Description Default
producer_id str

Stable ID of the producer.

required

Returns:

Type Description
Callable

The callable registered under producer_id, identical to the object passed to :meth:register.

Raises:

Type Description
UnknownObservationProducerError

If no producer carries the ID; the message lists the available IDs.

PandapowerGridBuilder

Builds a pandapower network from a PowerGridGraph instance.

This class serves as a bridge between the geospatial grid representation in PowerGridGraph and the power flow simulation capabilities of pandapower. It provides a suite of methods for systematically constructing a complete pandapower network, including buses, lines, transformers, and loads, based on the topology and data defined in a PowerGridGraph.

The builder is highly configurable, allowing users to specify the electrical parameters of the network components through a configuration dictionary. It also includes validation methods to ensure the consistency and correctness of the resulting pandapower network.

Attributes:

Name Type Description
power_grid PowerGridGraph

The PowerGridGraph instance containing the network topology.

net pandapowerNet

The pandapower network being built.

config Dict

A configuration dictionary for the network components.

node_to_bus_mapping Dict[str, int]

A mapping from graph node names to pandapower bus indices.

build_hv_buses_and_lines()

Builds the HV buses and lines in the pandapower network.

Returns:

Type Description
Tuple[int, int]

A tuple containing the number of added buses and lines.

build_loads_from_graph_buildings()

Builds loads in the pandapower network based on building data.

Returns:

Type Description
Tuple[int, List[str]]

A tuple containing the number of loads added and a list of any building nodes that could not be matched to a bus.

Raises:

Type Description
ValueError

If the building graph has not been initialized.

build_lv_buses_and_lines()

Builds the LV buses and lines in the pandapower network.

Returns:

Type Description
Tuple[int, int]

A tuple containing the number of added buses and lines.

build_lv_mv_power_transformers()

Builds the LV-MV power transformers in the pandapower network.

Returns:

Type Description
List[str]

A list of the names of the created transformers.

Raises:

Type Description
ValueError

If the required graphs have not been initialized.

build_mv_buses_and_lines()

Builds the MV buses and lines in the pandapower network.

Returns:

Type Description
Tuple[int, int]

A tuple containing the number of added buses and lines.

build_mv_hv_power_transformers()

Builds the MV-HV power transformers in the pandapower network.

Returns:

Type Description
List[str]

A list of the names of the created transformers.

Raises:

Type Description
ValueError

If the required graphs have not been initialized.

connect_hv_bus_to_ext_grid()

Connects the HV buses to the external grid.

Returns:

Type Description
List[int]

A list of the indices of the created external grid connections.

Raises:

Type Description
ValueError

If the HV graph has not been initialized or if the buses are not found.

create_bus_geodata()

Creates the bus_geodata table from the graph nodes.

get_pandapower_net()

Returns the constructed pandapower network.

Returns:

Type Description
pandapowerNet

The complete pandapower network instance.

validate_network_consistency()

Validates the consistency of the pandapower network.

This method performs a comprehensive validation by checking that all nodes and edges in the underlying graphs have corresponding buses and lines in the pandapower network, and that there are no orphaned elements.

Returns:

Type Description
bool

True if the validation passes, False otherwise.

Raises:

Type Description
ValueError

If any of the required graphs have not been initialized.

SemanticGraphRepository

Read and query Gridalyn semantic graph node and edge tables.

assets_in_scenario(scenario_id, semantic_type=None)

Return scenario-scoped assets, optionally filtered by semantic type.

A deprecated type (cls:SoftCLSContract) is resolved to its replacement and the properties that now carry what its name encoded, with a :class:DeprecationWarning.

get_asset_context(node_id)

Return a node plus grouped incoming and outgoing relationships.

get_node(node_id)

Return one node as a dict with parsed properties.

neighbors(node_id, relationship_type=None, *, direction='out', scenario_id=None)

Return neighboring node IDs for a relationship direction.

timeseries_for_asset(asset_id, *, scenario_id=None)

Return time-series datasets relevant to an asset or its scenario.

SyntheticPandapowerAdapter

Adapter from synthetic pandapower/Gridalyn objects to base Parquet.

Two sources, chosen by whether footprints_path is set:

  • unset (default): load_snapshot normalizes an already-built network it reads from cache_dir's pp_net_cache.pkl/pg_graph_cache.pkl -- the historical, adapt-only path.
  • set: load_snapshot builds the network fresh from the building footprints via :func:~gridalyn.twin.adapters.pandapower_builder.build_power_grid_and_network (Phase 29, 2026-08-19) -- no gridalyn.simulation dependency, no cache required. This is what gives gridalyn.twin a real construction capability instead of only ever adapting a network someone else already built.

adapter_id = 'synthetic_pandapower'

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

capabilities = ('load_snapshot', 'export_base_parquet', 'write_base_metadata', 'write_validation_report')

Built-in immutable sequence.

If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.

If the argument is a tuple, the return value is the same object.

geographic_crs = 'EPSG:4326'

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

source_adapter = 'SyntheticPandapowerAdapter'

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

source_format = 'pandapower-cache'

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

source_standard = 'pandapower'

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

authority_sets()

Return the Model Authority Sets partitioning models this produces.

Returns:

Type Description
tuple[ModelAuthoritySet, ...]

The declared partition. Measured today it has exactly one member -- see :data:~gridalyn.twin.adapters.authority.AUTHORITY_SET_PARTITION_IS_SINGLE_MEMBER.

Raises:

Type Description
UnknownModelAuthoritySetError

If this adapter declares no set.

describe()

Return stable adapter identity and capability metadata.

export(*, out_dir, root)

Write base network artifacts and repository-centric metadata.

load_snapshot()

Build or load the synthetic grid and normalize it to base tables.

Builds fresh from footprints_path when set (Phase 29); otherwise loads cache_dir's pickled net/graph, the historical adapt-only path.

Returns:

Type Description
The canonical

class:NetworkModel.

Raises:

Type Description
ValueError

If this adapter's declared Model Authority Sets do not partition the canonical base artifacts. Checked here, before any IO, so the declarations are consumed on the path that actually produces the committed base rather than only on the CIM path.

profiles()

Return the declared profiles of the base this adapter exports.

Returns:

Type Description
tuple[ModelProfile, ...]

Every profile in :data:~gridalyn.twin.adapters.authority.BASE_MODEL_PROFILES, ordered by profile ID.

UnknownNetworkAdapterError

Bases: builtins.KeyError

Raised when a requested network adapter is not registered.

UnknownObservationProducerError

Bases: builtins.KeyError

Raised when a requested observation producer is not registered.

build_network_adapter_validation_report(*, base_dir, root, adapter_id=None, source_adapter, source_standard, source_format=None, adapter_capabilities=None, artifact_paths, metadata_path)

Build a standard validation report for an exported network snapshot.

build_power_grid_and_network(*, footprints_path, config, clustering_crs='auto', snap_transformers_to_streets=None, lv_assignment=None, block_penalty_km2=None)

Build a PowerGridGraph and pandapower network from building footprints.

Pure topology construction: extracts building centroids, builds the LV/MV/HV graph hierarchy, and builds buses/lines/transformers/loads via PandapowerGridBuilder under the default uniform line-sizing mode. No power-flow solve and no load-aware line sizing -- both are gridalyn.simulation-layer concerns; see gridalyn.simulation.simulators.powerflow.synthetic_network for the full orchestration that adds them.

The partition and siting options can be declared in config["topology"] (keys in :data:TOPOLOGY_KEYS) and the slack setpoint in config["external_grid"]["vm_pu"], so a study pins them as data and a change to them changes the config hash every cache keys on. An explicit argument here overrides the config; a config without those blocks builds exactly what it built before they existed.

Parameters:

Name Type Description Default
footprints_path str | Path

GeoJSON file with building polygons.

required
config Dict[str, Any]

Grid configuration mapping (buses/lines/transformers/loads, and optionally topology/external_grid).

required
clustering_crs str | int | None

Metric CRS for clustering. "auto" estimates a local UTM CRS from the footprint layer. Graph geodata stays longitude/latitude.

'auto'
snap_transformers_to_streets bool | None

When true, site every transformer on the nearest street instead of on the building it serves. Requires the geo extra and a network fetch. Defaults to false, and the default is load-bearing: the transformer-to-building link is a pandapower line, pinned today at min_length_km because the two nodes coincide. Siting on the street turns that stub into roughly 20 m of conductor and moves the power flow, so enabling this is a deliberate re-base, not a display change. None takes the config's value.

None
lv_assignment str | None

How buildings are shared among MV/LV transformers, one of :data:LV_ASSIGNMENT_METHODS. "kmeans" (the default) partitions by geometry alone, which on the shipped footprints leaves 43 of 193 transformers above 100% at the declared envelope. "capacitated" caps every transformer at the building count it was sized for. Defaults to kmeans, and the default is load-bearing: changing the partition changes which buildings share a transformer, so enabling it is a deliberate re-base. None takes the config's value.

None
block_penalty_km2 float | None

With "capacitated", the penalty in km^2 of squared distance for serving a building from a cluster centred on another street block. Capacity alone pushes edge buildings across the street; 0.005 was measured to recover that while keeping every transformer within its limit. Needs streets: a declared topology.street_layer file, or the geo extra and a live fetch. None takes the config's value, else 0.0.

None

Returns:

Type Description
Tuple[PowerGridGraph, pandapowerNet]

(power_grid, net). power_grid.building_data carries the extracted building count and coordinates for a caller that needs them.

build_semantic_graph(*, buses, lines, transformers, buildings, connectivity, asset_registry=None, provider_registry=None, timeseries_manifests=None, interaction_log=None, capabilities=None, registry=None)

Build the semantic node/edge graph from the canonical twin tables.

Parameters:

Name Type Description Default
buses DataFrame

grid_buses table.

required
lines DataFrame

grid_lines table.

required
transformers DataFrame

grid_transformers table.

required
buildings DataFrame

buildings table.

required
connectivity DataFrame

building_grid_connectivity table.

required
asset_registry DataFrame | None

Scenario asset registry; empty when absent.

None
provider_registry DataFrame | None

Flexibility provider registry; empty when absent.

None
timeseries_manifests dict[str, Any] | None

Run manifests keyed by name.

None
interaction_log DataFrame | None

Message log an interaction protocol wrote, as parquet; empty when absent. Read as a table, never imported.

None
capabilities set[str] | None

Declared semantic capability IDs. None applies the legacy default (flexibility); an explicit set builds the model-first core plus exactly those capabilities (set() for a pure model-first graph).

None
registry SemanticCapabilityRegistry | None

Capability registry to resolve against; defaults to the shared default registry.

None

Returns:

Type Description
tuple[DataFrame, DataFrame, dict[str, Any]]

(nodes, edges, manifest). The frames are sorted by ID, so the order the emitters run in does not reach the artifact. The manifest records the capabilities the graph was built with, which is what gridalyn semantic validate validates it against.

Raises:

Type Description
UnknownSemanticCapabilityError

A declared capability is not registered.

ValueError

The composed profile is inconsistent, or an emitter produced a type or a predicate the profile does not declare.

default_network_adapter_registry()

Return the shared default registry of network source adapters.

Built once and cached so external adapters registered via :func:register_network_adapter_extension stay resolvable through the default path. Holds the synthetic pandapower adapter, the CIM parquet adapter, and the topology-only pandapower adapter (no building-footprint layer).

default_observation_producer_registry()

Return the shared default registry holding the two shipped producers.

Built once and cached so external producers registered via :func:register_observation_producer_extension stay resolvable through the default path. Resolves "powerflow" to :func:gridalyn.twin.observation.contract.observe_network and "measured-ingest" to :func:gridalyn.twin.observation.ingest.read_measured_observations.

describe_network_source_adapter(adapter)

Describe an adapter using the platform network source contract.

Accepts either an adapter instance or the adapter class itself, because :meth:~gridalyn.twin.adapters.registry.NetworkAdapterRegistry.register describes a factory before anything is constructed.

Parameters:

Name Type Description Default
adapter NetworkSourceAdapter | type

Adapter instance or adapter class declaring the identity attributes of the network source contract.

required

Returns:

Type Description
NetworkAdapterDescriptor

The adapter's stable identity and capability metadata.

Raises:

Type Description
ValueError

If the adapter declares neither adapter_id nor source_adapter, so no stable ID can be derived.

load_measurements(path)

Load tidy measurement rows from a CSV or parquet export.

Returns the raw frame; validation happens in :func:read_measured_observations, once, so both entry paths -- a frame built in memory and a file loaded here -- share the same contract.

Parameters:

Name Type Description Default
path Path | str

Export to read. .csv is read with the timestamp column parsed; .parquet is read as written.

required

Returns:

Type Description
DataFrame

The loaded frame, unvalidated.

Raises:

Type Description
ValueError

If the suffix is not a supported measurement format.

north_america_profile()

Return the model-first core profile, with no capability composed over it.

observe_network(results, *, as_of=None)

Read a :class:NetworkObservation off a solved network's result tables.

This is the pandapower-shaped adapter, and the only place in the contract that knows those table names. It reads by attribute and column name rather than by type, so anything exposing res_bus / res_line frames satisfies it, and anything that does not can build a :class:NetworkObservation directly.

Parameters:

Name Type Description Default
results Any

A solved network -- typically a pandapowerNet mutated in place by the simulation layer's power-flow backend. A missing table or column is read as "not reported" rather than raising, because the summary writers this replaces already tolerated it.

required
as_of datetime | None

The instant the solved state belongs to. Keyword-only and defaulting to None because results carries no clock of its own: only the caller that chose the operating point knows which instant it represents. Nothing is inferred when it is omitted -- see :data:AS_OF_ABSENT_REASON.

None

Returns:

Type Description
NetworkObservation

The observation. Absent bus/line tables yield empty arrays; an absent loss column yields total_line_loss_mw=None, which is a different answer from 0.0; an omitted as_of yields as_of=None. The provenance is always "simulated": this producer reads solver results, so that is the only honest answer it can give.

read_measured_observations(measurements, *, join)

Read measured rows into one observation per instant.

Groups the validated rows by their (tz-aware) timestamps, sorted ascending, and emits one :class:NetworkObservation per instant with provenance="measured" and as_of stamped from the datum. Mixed UTC offsets are normalized to UTC for grouping: the stamped as_of is the datum's instant expressed in UTC, never a different instant.

converged is True on every emitted observation, deliberately: a measurement is a real operating point of the observed system, so convergence -- a solver concept -- does not apply, and True ("this state occurred") is the honest reading.

Parameters:

Name Type Description Default
measurements DataFrame

Tidy rows carrying :data:MEASUREMENT_COLUMNS. An empty frame (zero rows) yields () -- "no data" is not an error at this layer; loaders and callers decide.

required
join EntityJoin

The declared entity-to-bus join. Keyword-only, because the join is the one input that must never be defaulted or inferred.

required

Returns:

Type Description
tuple[NetworkObservation, ...]

One observation per distinct instant, in ascending as_of order. Each carries the joined bus ids in stable entity-sorted order, the measured voltages as float64, empty line arrays, and no loss total.

Raises:

Type Description
ValueError

On a missing required column, a naive, missing (NaT/null) or unparseable timestamp, an unsupported quantity, an entity absent from the join, a duplicate (timestamp, entity_id, quantity) datum, or a non-numeric value. Every message locates the failure and names the remedy.

register_network_adapter_extension(factory, *, descriptor, replace=False, registry=None)

Register an external network source adapter (host API).

A third-party adapter conforms to the :class:NetworkSourceAdapter contract, carries a :class:NetworkAdapterDescriptor with a supported contract_version, and registers it here — no edit to gridalyn's codebase required. Defaults to the shared default registry.

register_observation_producer_extension(producer, *, descriptor, replace=False, registry=None)

Register an external observation producer (host API).

A third-party producer conforms to the observation contract, carries an :class:ObservationProducerDescriptor with a supported contract_version, and registers it here — no edit to gridalyn's codebase required. Defaults to the shared default registry.

validate_semantic_graph(nodes, edges, profile, expected_scenario_counts=None)

Validate a semantic graph against the profile it was built with.

Parameters:

Name Type Description Default
nodes DataFrame

The graph's node table.

required
edges DataFrame

The graph's edge table.

required
profile Mapping[str, Any]

A profile from :func:~gridalyn.twin.semantic.profile.profile_with_capabilities.

required
expected_scenario_counts Mapping[str, Mapping[str, int]] | None

{scenario_id: {count_key: value}}. Every key must have a rule in profile["scenario_counts"]; a key with no rule is an error, never a silent skip.

None

Returns:

Type Description
dict[str, Any]

A report with valid, node and edge counts, errors and warnings.

write_network_adapter_validation_report(*, path, base_dir, root, adapter_id=None, source_adapter, source_standard, source_format=None, adapter_capabilities=None, artifact_paths, metadata_path)

Write a governed validation report for an exported network snapshot.

gridalyn.assets

Asset, building, load, EV, DER, and flexibility model facade.

IEEE_33_BUS_BENCHMARK = IeeeBenchmarkFeederSpec(benchmark_id='ieee_33_bus', display_name='IEEE 33-Bus Distribution Feeder', source_name='pandapower.networks.case33bw', expected_bus_count=33, expected_line_count=37, expected_load_count=32)

Stable Gridalyn contract for a known IEEE distribution benchmark.

BatteryAsset

Battery capability and operating state bounds.

BuildingDownloader

Fetch OpenStreetMap building footprints for a geographic area.

Wraps osmnx feature queries and writes the polygon footprints out as GeoJSON, which is the ingest format the synthetic-network builders read. Non-polygon and untagged features are dropped, and an empty result raises rather than writing an empty file.

download_buildings(polygon_coordinates, output_path)

Downloads building shapes for a given polygon using osmnx and saves them to a file.

Parameters:

Name Type Description Default
polygon_coordinates Tuple[Tuple[float, float], ...]

The polygon coordinates to download building shapes for.

required
output_path str

The path to save the downloaded building shapes.

required

Raises:

Type Description
MissingCapabilityError

If the geo extra (osmnx) is not installed.

ValueError

If OSMnx returns no usable building footprints.

DERDispatchAsset

PV and battery charging capability attached to one feeder bus.

FakeGeoJSONGenerator

Generates a fake GeoJSON FeatureCollection of buildings in a grid layout.

generate_building(x, y, building_id)

Generate a building polygon in a grid layout

generate_geojson()

Generate a GeoJSON FeatureCollection with neighborhood features

save_to_file(file_path)

Save generated GeoJSON to file

GeoProcessor

Class for processing GeoJSON building data.

get_building_by_id(building_id)

Get data for a specific building by ID.

Parameters:

Name Type Description Default
building_id Union[int, str]

Building identifier

required

Returns:

Type Description
Optional[Dict]

Building data dictionary or None if not found

get_building_data()

Get processed building data as DataFrame.

Returns:

Type Description
Optional[DataFrame]

DataFrame with building data or None if no data processed

get_statistics()

Get statistics about the processed buildings.

Returns:

Type Description
dict

Dictionary containing statistics: - num_buildings: Total number of buildings - total_area: Total building area in square meters - avg_area: Average building area in square meters - min_area: Minimum building area in square meters - max_area: Maximum building area in square meters

load_geojson(source)

Load and validate GeoJSON data from file path or dictionary.

Parameters:

Name Type Description Default
source Union[str, Dict[str, Any]]

File path (str) or dictionary containing GeoJSON data

required

Returns:

Type Description
tuple

(success, message) - success: Boolean indicating if loading was successful - message: Description of any loading issues

load_geojson_from_url(url)

Load and validate GeoJSON data from a URL.

Parameters:

Name Type Description Default
url str

URL to the GeoJSON data

required

Returns:

Type Description
tuple

(success, message) - success: Boolean indicating if loading was successful - message: Description of any loading issues

process_buildings()

Process building features from loaded GeoJSON.

Returns:

Type Description
tuple

(success, message) - success: Boolean indicating if processing was successful - message: Description of any processing issues

process_buildings_in_polygon()

Loads building footprints from a GeoJSON file, selects buildings within a given polygon, and saves the result to a new GeoJSON file.

IeeeBenchmarkFeederSpec

Stable Gridalyn contract for a known IEEE distribution benchmark.

PVAsset

Static PV capability connected through a prosumer or network asset.

ProsumerAsset

Prosumer with colocated PV and battery resources.

RadialFeederSpec

Deterministic radial feeder contract backed by pandapower.

bus_y_step = 0.2

Convert a string or number to a floating-point number, if possible.

line_c_nf_per_km = 5.0

Convert a string or number to a floating-point number, if possible.

line_length_km = 0.5

Convert a string or number to a floating-point number, if possible.

line_max_i_ka = 0.2

Convert a string or number to a floating-point number, if possible.

line_r_ohm_per_km = 0.5

Convert a string or number to a floating-point number, if possible.

line_x_ohm_per_km = 0.3

Convert a string or number to a floating-point number, if possible.

q_to_p_ratio = 0.3

Convert a string or number to a floating-point number, if possible.

ThermalForecast

Dynamic transformer active-power limit derived from ambient temperature.

TransformerThermalModel

IEEE C57.91-2011 thermal model for a distribution/power transformer.

Parameters (defaults for a typical 25 MVA ONAN distribution transformer)

s_rated_kva : Rated apparent power (kVA) pf : Power factor at rated load delta_theta_to_r : Rated top-oil temperature rise over ambient (°C) delta_theta_hs_r : Rated hottest-spot rise over top-oil (°C) tau_to_min : Oil thermal time constant (minutes) tau_hs_min : Winding thermal time constant (minutes) r_loss_ratio : Ratio of load losses to no-load losses at rated n : Top-oil rise exponent (ONAN: 0.8, ONAF: 0.9, OFAF: 1.0) m : Winding hottest-spot exponent (ONAN: 0.8, ONAF: 0.8) theta_max : Maximum allowable hottest-spot temperature (°C)

delta_theta_hs_r = 25.0

Convert a string or number to a floating-point number, if possible.

delta_theta_to_r = 55.0

Convert a string or number to a floating-point number, if possible.

m = 0.8

Convert a string or number to a floating-point number, if possible.

n = 0.8

Convert a string or number to a floating-point number, if possible.

p_rated_kw

Rated active power (kW).

pf = 0.95

Convert a string or number to a floating-point number, if possible.

r_loss_ratio = 5.0

Convert a string or number to a floating-point number, if possible.

s_rated_kva = 25000.0

Convert a string or number to a floating-point number, if possible.

tau_hs_min = 8.0

Convert a string or number to a floating-point number, if possible.

tau_to_min = 180.0

Convert a string or number to a floating-point number, if possible.

theta_max = 120.0

Convert a string or number to a floating-point number, if possible.

max_load_for_temp(ambient_c, theta_max=None)

Find the maximum sustained load (kW) that keeps θ_H ≤ θ_max at a given ambient temperature (steady-state).

Uses bisection over load ratio K ∈ [0, 2.0].

reset(ambient_c=20.0, load_kw=0.0)

Initialize thermal state to steady-state at given load and ambient.

simulate_profile(load_profile_kw, ambient_profile_c, dt_min=1.0, initial_load_kw=None, initial_ambient_c=None)

Simulate θ_H over a load + ambient profile.

Parameters

load_profile_kw : array of load values (kW), one per timestep ambient_profile_c : array of ambient temperatures (°C), same length dt_min : timestep in minutes initial_load_kw : initial steady-state load for warm-up (default: first value) initial_ambient_c : initial ambient (default: first value)

Returns

theta_h_profile : array of hottest-spot temperatures (°C)

steady_state(load_kw, ambient_c)

Equilibrium hottest-spot temperature at given load and ambient. θ_H = θ_ambient + ΔΘ_TO,U(K) + ΔΘ_HS,U(K)

step(load_kw, ambient_c, dt_min=1.0)

Advance the thermal model by dt_min minutes under given load and ambient.

Uses the exponential approach to ultimate (Clause 7): ΔΘ(t+Δt) = ΔΘ_U + (ΔΘ(t) - ΔΘ_U) × exp(-Δt/τ)

Parameters

load_kw : active power load (kW) ambient_c : ambient temperature (°C) dt_min : timestep in minutes

Returns

theta_h : hottest-spot temperature (°C)

VoltageControlDERSpec

PV plus battery asset used by voltage-control algorithms.

build_asset_registry(buildings, assignments, *, soft_participation_rate, soft_assignment_seed, default_soft_capacity_fraction=0.65, prefer_existing_soft_participants=False)

Build one row per scenario/building with EV and CLS contract roles.

build_thermal_forecast(n_steps, resolution_minutes=5, *, s_rated_kva=15000.0, theta_max=110.0, duration_hours=28, tmy=None)

Build a synthetic ambient forecast and transformer limit trace from TMY data.

tmy lets callers pin an explicit weather table (e.g. a committed project input) instead of the downloaded/cached one.

build_thermal_forecast_from_ambient(ambient_c, *, resolution_minutes, s_rated_kva, theta_max, start_time)

Build a dynamic thermal limit trace from an explicit ambient-temperature trace.

calculate_area(coordinates)

Calculate the area of a polygon in square meters.

Parameters:

Name Type Description Default
coordinates List[List[float]]

List of [lon, lat] coordinates forming a polygon

required

Returns:

Type Description
float

Area in square meters

Note

Uses the Shoelace formula (also known as surveyor's formula) for calculating the area of a simple polygon.

calculate_centroid(coordinates)

Calculate the centroid of a polygon.

Parameters:

Name Type Description Default
coordinates List[List[float]]

List of [lon, lat] coordinates forming a polygon

required

Returns:

Type Description
tuple

(longitude, latitude) of the centroid

der_dispatch_assets_to_frame(assets)

Convert DER dispatch assets into the canonical tabular contract.

extract_building_data(geojson)

Extract building data from GeoJSON features.

Parameters:

Name Type Description Default
geojson Dict[str, Any]

GeoJSON data as dictionary

required

Returns:

Type Description
list

List of dictionaries containing building data: - id: Building identifier - coordinates: Building polygon coordinates - area: Building area in square meters - centroid: (longitude, latitude) of building centroid

generate_residential_load_profiles(n_units, *, day='peak', duration_hours=24, resolution_minutes=15, seed=42, generator='parametric', weather='auto')

Generate per-unit residential load profiles for one study day.

Returns a DataFrame in kilowatts with shape (time_steps, n_units), columns unit_000 ..., and a DatetimeIndex at resolution_minutes. Deterministic for a fixed seed when weather="synthetic".

load_base_inputs(base_dir=PosixPath('/home/runner/_work/gridalyn/gridalyn/instances/default/digital_twin/base'))

Load canonical digital-twin building inputs.

prosumer_assets_to_frame(assets)

Convert prosumer assets to the stable tabular project contract.

summarize_asset_registry(registry)

Summarize registry participation and EV/CLS overlap by scenario.

synthesize_building_model_tables(buildings, connectivity=None, *, profile='north_america_residential_v1', include_evse=True)

Create normalized building, zone, device, and end-use tables.

synthesize_scenario_device_tables(building_models, base_device_registry, asset_registry, *, scenario_id=None)

Create scenario-specific device overlays from model and asset tables.

thermal_forecast_metadata(forecast, peak_idx=None, peak_label=None, winter_design_limit_mw=None)

Return stable JSON metadata for a thermal-limit forecast.

validate_der_dispatch_assets(feeder, assets)

Validate DER dispatch assets against a feeder model contract.

validate_geojson(data)

Validate GeoJSON data structure and geometry.

Parameters:

Name Type Description Default
data Union[str, Dict[str, Any]]

GeoJSON data as string or dictionary

required

Returns:

Type Description
tuple

(is_valid, message) - is_valid: Boolean indicating if the GeoJSON is valid - message: Description of any validation issues

validate_radial_feeder_spec(spec)

Validate a radial feeder asset-model contract.

validate_voltage_control_der(feeder, der)

Validate a DER asset contract against a feeder asset contract.

voltage_control_assets_to_frame(der)

Convert voltage-control DER specs into a stable tabular contract.

write_building_model_artifacts(buildings, connectivity=None, *, out_dir=PosixPath('/home/runner/_work/gridalyn/gridalyn/instances/default/digital_twin/models'), root=PosixPath('.'), profile='north_america_residential_v1', tables=None)

Write synthesized model tables plus a portable manifest.

write_scenario_model_artifacts(building_models, base_device_registry, asset_registry, *, out_dir=PosixPath('/home/runner/_work/gridalyn/gridalyn/instances/default/digital_twin/models/scenarios'), root=PosixPath('.'), scenario_id=None)

Write scenario model overlay Parquet files and manifest.

gridalyn.simulation

Simulation, powerflow, network-impact, and validation facade.

DEFAULT_CHANNEL_MODEL_ID = 'ideal'

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

VALIDATION_FILENAME = 'synthetic_network_validation.json'

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

BernoulliLossChannel

Lose each message independently with probability loss_probability.

DESCRIPTOR = ChannelModelDescriptor(channel_model_id='bernoulli_loss', name='independent per-message loss', parameters={'loss_probability': 0.0, 'seed': 0, 'latency': 0.0}, contract_version='1')

Identity and parameters of a channel model.

Attributes:

Name Type Description
channel_model_id

Stable ID a caller resolves the model by.

name

Human-readable description for reports and manifests.

parameters

What this instance was constructed with, including its seed when it draws randomness -- the record of which channel ran.

contract_version

Version of this contract the model implements.

descriptor

Return the descriptor, recording probability, seed and latency.

transmit(*, key, sender, receiver, sent_at)

Lose the message when its draw falls below loss_probability.

ChannelModel

Bases: typing.Protocol

Decide whether, and when, a message between two agents arrives.

descriptor

Return what a run records about this channel.

transmit(*, key, sender, receiver, sent_at)

Return the delivery of one message.

Parameters:

Name Type Description Default
key str

Stable message identifier; stochastic models draw from it.

required
sender str

Identifier of the sending agent.

required
receiver str

Identifier of the receiving agent.

required
sent_at float

Simulated time the message is sent.

required

ChannelModelDescriptor

Identity and parameters of a channel model.

Attributes:

Name Type Description
channel_model_id

Stable ID a caller resolves the model by.

name

Human-readable description for reports and manifests.

parameters

What this instance was constructed with, including its seed when it draws randomness -- the record of which channel ran.

contract_version

Version of this contract the model implements.

contract_version = '1'

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

as_dict()

Return a plain-JSON view of the descriptor for provenance.

ChannelModelRegistry

Resolve channel models by stable, explicitly registered ID.

create(channel_model_id, **kwargs)

Instantiate a registered channel model.

Parameters:

Name Type Description Default
channel_model_id str

The registered ID; no discovery, no fallback.

required
**kwargs Any

Parameters forwarded to the model factory.

required

Raises:

Type Description
UnknownChannelModelError

channel_model_id is not registered.

get_descriptor(channel_model_id)

Return descriptor metadata for a registered channel model.

Parameters:

Name Type Description Default
channel_model_id str

The registered ID.

required

list_descriptors()

Return registered descriptors sorted by channel-model ID.

register(factory, *, descriptor=None, replace=False, source='core', version=None)

Register a channel-model factory under its descriptor's ID.

Parameters:

Name Type Description Default
factory Callable[..., ChannelModel]

Callable returning a :class:ChannelModel.

required
descriptor ChannelModelDescriptor | None

Descriptor to register under. Defaults to the one the factory declares.

None
replace bool

Allow overwriting an already-registered ID.

False
source Literal

"core" for shipped models, "host" for a host extension; only :data:ExtensionSource values are accepted.

'core'
version str | None

Optional semantic version when an extension supplies one.

None

Raises:

Type Description
UnsupportedContractVersionError

The descriptor declares a contract version this engine does not support.

ValueError

source is unknown, or the ID is taken and replace is false.

registration_source(channel_model_id)

Return the source a channel model was registered under.

Parameters:

Name Type Description Default
channel_model_id str

The registered ID.

required

registration_version(channel_model_id)

Return the semantic version an extension recorded, if any.

Parameters:

Name Type Description Default
channel_model_id str

The registered ID.

required

Delivery

The outcome of transmitting one message.

Attributes:

Name Type Description
deliver_at

Simulated time the message arrives, or None when lost.

delivered

Return whether the message arrives at all.

ErrorBound

A surrogate's accuracy against the physical model it approximates.

Attributes:

Name Type Description
metric

Name of the statistic, e.g. mae_relief_pct_per_kw.

units

Physical units of value, so a number is never quoted bare.

value

The measured statistic, or None when status is unmeasured. Never a target, never a placeholder.

sample_size

Number of label rows the statistic was computed over. Zero only when status is unmeasured.

method

How the number was produced -- the evaluation protocol and the dataset -- in enough detail to re-run it.

reference

The physical model the surrogate was compared against.

status

measured or unmeasured.

reason

Why no measurement exists. Required when status is unmeasured, and must be located enough to act on.

status = 'measured'

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

as_dict()

Return a plain-JSON view of the bound for reports and manifests.

Returns:

Type Description
dict[str, Any]

A dict of JSON-native values only, so it embeds in a governed report without a custom encoder.

EventScheduler

Order events by (time, priority, key, sequence) in simulated time.

now

Return the simulated time of the last event popped, or the start.

drain(handler, *, limit=1000000)

Handle every scheduled event, including those handlers schedule.

Parameters:

Name Type Description Default
handler Callable[[ScheduledEvent], None]

Called once per event, in scheduling order.

required
limit int

Most events to handle before concluding the handlers are scheduling forever.

1000000

Returns:

Type Description
int

How many events were handled.

Raises:

Type Description
RuntimeError

More than limit events were handled.

peek_time()

Return when the next event fires, or None when none is scheduled.

pop()

Remove and return the next event, advancing :attr:now to its time.

Raises:

Type Description
IndexError

No event is scheduled.

run_until(time, handler)

Handle, in order, every event that fires at or before time.

The handler may schedule further events; those that fire at or before time are handled in the same call. :attr:now ends at time.

Parameters:

Name Type Description Default
time float

Simulated time to advance to.

required
handler Callable[[ScheduledEvent], None]

Called once per event, in scheduling order.

required

Returns:

Type Description
int

How many events were handled.

Raises:

Type Description
ValueError

time is not finite or lies before :attr:now.

schedule(*, time, key, payload=None, priority=0)

Schedule an event.

Parameters:

Name Type Description Default
time float

Simulated time the event fires at; not before :attr:now.

required
key str

Stable identifier used as the third ordering key.

required
payload Any

Anything; never inspected.

None
priority int

Lower fires first among events at the same time.

0

Returns:

Type Description
ScheduledEvent

The scheduled event.

Raises:

Type Description
ValueError

time is not finite or lies before :attr:now.

FixedLatencyChannel

Deliver every message after the same latency.

DESCRIPTOR = ChannelModelDescriptor(channel_model_id='fixed_latency', name='fixed latency, no loss', parameters={'latency': 0.0}, contract_version='1')

Identity and parameters of a channel model.

Attributes:

Name Type Description
channel_model_id

Stable ID a caller resolves the model by.

name

Human-readable description for reports and manifests.

parameters

What this instance was constructed with, including its seed when it draws randomness -- the record of which channel ran.

contract_version

Version of this contract the model implements.

descriptor

Return the descriptor, recording the latency.

transmit(*, key, sender, receiver, sent_at)

Deliver the message latency after sent_at.

FixedOutageChannel

Silence an exact, seeded subset of endpoints for the channel's lifetime.

The silent endpoints are endpoints[i] for i in the first round(outage_fraction * len(endpoints)) entries of numpy.random.default_rng(seed).permutation(len(endpoints)). With one seed, a larger fraction silences a superset of a smaller one.

DESCRIPTOR = ChannelModelDescriptor(channel_model_id='fixed_outage', name='fixed outage: exact seeded subset of silent endpoints', parameters={'outage_fraction': 0.0, 'seed': 0, 'latency': 0.0}, contract_version='1')

Identity and parameters of a channel model.

Attributes:

Name Type Description
channel_model_id

Stable ID a caller resolves the model by.

name

Human-readable description for reports and manifests.

parameters

What this instance was constructed with, including its seed when it draws randomness -- the record of which channel ran.

contract_version

Version of this contract the model implements.

descriptor

Return the descriptor, recording counts, fraction, seed and latency.

silent_endpoints

Return the silenced endpoints, in permutation order.

transmit(*, key, sender, receiver, sent_at)

Lose any message whose sender or receiver is silent.

IdealChannel

Deliver every message at the time it is sent.

DESCRIPTOR = ChannelModelDescriptor(channel_model_id='ideal', name='ideal channel: zero latency, no loss', parameters={}, contract_version='1')

Identity and parameters of a channel model.

Attributes:

Name Type Description
channel_model_id

Stable ID a caller resolves the model by.

name

Human-readable description for reports and manifests.

parameters

What this instance was constructed with, including its seed when it draws randomness -- the record of which channel ran.

contract_version

Version of this contract the model implements.

descriptor

Return the ideal channel's descriptor; it has no parameters.

transmit(*, key, sender, receiver, sent_at)

Deliver the message at sent_at.

LightSimPowerflowAdapter

Wrap LightSim2Grid's grid model behind a narrow Gridalyn API.

LineSizingResult

Structured result of a read-only line-sizing diagnostic.

Attributes:

Name Type Description
converged

Whether the loading_percent values reflect a converged power flow. When False every loading_percent row entry is NaN but the structural downstream-load vs max_i_ka correlation is still populated.

rows

One dict per on-tree line, each carrying the keys idx, level, max_i_ka, length_km, downstream_load_mw, downstream_count and loading_percent.

per_level

Per voltage-level aggregates keyed by "LV" / "MV" / "HV" (only levels present on the tree appear).

correlations

Correlation blocks. "downstream_load_vs_max_i_ka" is always present (structural); "downstream_load_vs_loading_percent" is present only when finite loading values exist.

NetworkObservation

What a controller can see from one solved network state.

Constructed either from a solved network via :func:observe_network or directly from arrays by any producer of solved results -- a different power-flow backend, or a surrogate. No field is a pandapower type, which is what makes this a seam rather than a helper.

Comparison is by identity (eq=False): the generated __eq__ would compare array fields element-wise and then raise ValueError on the ambiguous truth value. Compare fields explicitly instead.

The arrays alias the result tables they were read from, exactly as the to_numpy(dtype=float) calls they replace did. Treat them as read-only.

Attributes:

Name Type Description
converged

Whether the producer reported a converged solution.

bus_ids

Identifier per entry of bus_voltage_pu, in the same order.

bus_voltage_pu

Per-bus voltage magnitude in per-unit. Empty when the producer reported no bus voltages.

line_loading_percent

Per-line loading as a percentage of rating. Empty when the producer reported no line loadings.

total_line_loss_mw

Total active line loss in MW, or None when the producer reported no loss at all. None and 0.0 are different answers and callers that distinguish them rely on it.

provenance

Where the values came from -- "simulated" or "measured". This is what lets a consumer holding only the object distinguish a simulation result from a measurement. Required deliberately, with no default, so that no producer can omit the answer.

as_of

The instant this state belongs to, supplied by whoever knows it. None means no instant was reported -- see :data:AS_OF_ABSENT_REASON. It is never filled in from the wall clock, so None here is a fact about the producer rather than a gap in the reader's knowledge.

max_line_loading_percent

Return the highest line loading as a percentage of rating.

Returns:

Type Description
float

The maximum over non-NaN entries, or nan when no line loading was observed.

max_voltage_pu

Return the highest bus voltage magnitude in per-unit.

Returns:

Type Description
float

The maximum over non-NaN entries, or nan when no bus voltage was observed.

min_voltage_pu

Return the lowest bus voltage magnitude in per-unit.

Returns:

Type Description
float

The minimum over non-NaN entries, or nan when no bus voltage was observed.

drop_missing()

Return the observation restricted to entries that were reported.

Bus and line arrays are filtered independently, each keeping only its non-NaN entries, exactly as the separate dropna() calls this replaces did. This is the explicit form of a distinction the tree already made silently: reductions agree either way, but any count divided by the array length does not.

Returns:

Type Description
NetworkObservation

A new observation over the reported entries. converged, total_line_loss_mw, provenance and as_of are scalars and carry through unchanged -- filtering unobserved buses moves neither the instant the state belongs to nor where it came from.

voltage_frame()

Return the canonical two-column bus-voltage table.

Returns:

Type Description
DataFrame

A frame with columns ["bus_id", "vm_pu"], one row per observed bus, in observation order -- the shape both the scenario runner and the voltage-profile figure rebuilt independently.

voltage_violation_counts(*, below_pu, above_pu)

Count buses outside a voltage band.

Parameters:

Name Type Description Default
below_pu float

Lower limit; a bus strictly below it is under-voltage.

required
above_pu float

Upper limit; a bus strictly above it is over-voltage.

required

Returns:

Type Description
tuple[int, int]

(under_voltage_count, over_voltage_count) over :attr:bus_voltage_pu as held. A NaN entry compares false against both limits and so counts as neither, matching the pandas comparisons these counts replace. Call :meth:drop_missing first when the denominator must exclude unobserved buses.

PandapowerGridBuilder

Builds a pandapower network from a PowerGridGraph instance.

This class serves as a bridge between the geospatial grid representation in PowerGridGraph and the power flow simulation capabilities of pandapower. It provides a suite of methods for systematically constructing a complete pandapower network, including buses, lines, transformers, and loads, based on the topology and data defined in a PowerGridGraph.

The builder is highly configurable, allowing users to specify the electrical parameters of the network components through a configuration dictionary. It also includes validation methods to ensure the consistency and correctness of the resulting pandapower network.

Attributes:

Name Type Description
power_grid PowerGridGraph

The PowerGridGraph instance containing the network topology.

net pandapowerNet

The pandapower network being built.

config Dict

A configuration dictionary for the network components.

node_to_bus_mapping Dict[str, int]

A mapping from graph node names to pandapower bus indices.

build_hv_buses_and_lines()

Builds the HV buses and lines in the pandapower network.

Returns:

Type Description
Tuple[int, int]

A tuple containing the number of added buses and lines.

build_loads_from_graph_buildings()

Builds loads in the pandapower network based on building data.

Returns:

Type Description
Tuple[int, List[str]]

A tuple containing the number of loads added and a list of any building nodes that could not be matched to a bus.

Raises:

Type Description
ValueError

If the building graph has not been initialized.

build_lv_buses_and_lines()

Builds the LV buses and lines in the pandapower network.

Returns:

Type Description
Tuple[int, int]

A tuple containing the number of added buses and lines.

build_lv_mv_power_transformers()

Builds the LV-MV power transformers in the pandapower network.

Returns:

Type Description
List[str]

A list of the names of the created transformers.

Raises:

Type Description
ValueError

If the required graphs have not been initialized.

build_mv_buses_and_lines()

Builds the MV buses and lines in the pandapower network.

Returns:

Type Description
Tuple[int, int]

A tuple containing the number of added buses and lines.

build_mv_hv_power_transformers()

Builds the MV-HV power transformers in the pandapower network.

Returns:

Type Description
List[str]

A list of the names of the created transformers.

Raises:

Type Description
ValueError

If the required graphs have not been initialized.

connect_hv_bus_to_ext_grid()

Connects the HV buses to the external grid.

Returns:

Type Description
List[int]

A list of the indices of the created external grid connections.

Raises:

Type Description
ValueError

If the HV graph has not been initialized or if the buses are not found.

create_bus_geodata()

Creates the bus_geodata table from the graph nodes.

get_pandapower_net()

Returns the constructed pandapower network.

Returns:

Type Description
pandapowerNet

The complete pandapower network instance.

validate_network_consistency()

Validates the consistency of the pandapower network.

This method performs a comprehensive validation by checking that all nodes and edges in the underlying graphs have corresponding buses and lines in the pandapower network, and that there are no orphaned elements.

Returns:

Type Description
bool

True if the validation passes, False otherwise.

Raises:

Type Description
ValueError

If any of the required graphs have not been initialized.

PowerFlowBackend

Bases: typing.Protocol

A single, provenance-bearing way to solve a pandapower network.

Implementations must expose descriptor (what will be recorded) and solve (the only place a solver call is made).

descriptor

Return what will be recorded in provenance.powerflow_backend.

Declared read-only: implementations expose it as a property so a consumer cannot rebind the record of what a run solved with.

solve(net, **kwargs)

Solve net in place, applying descriptor settings then kwargs.

Parameters:

Name Type Description Default
net Any

A pandapower network, mutated in place with res_* tables.

required
**kwargs Any

Per-call solver keywords that override the backend's own settings, so a caller-parametrised site keeps its behaviour.

required

PowerFlowBackendDescriptor

Identity, capability requirement and settings of a power-flow backend.

Attributes:

Name Type Description
backend_id

Stable ID a caller resolves the backend by.

name

Human-readable engine description for reports and manifests.

capability

Optional-capability name this backend needs (a key of OPTIONAL_CAPABILITY_MODULES), or None when it needs none.

settings

Solver keywords this backend applies before any caller override.

Read this as the backend's DECLARED settings, not as a full record of each solve. solve(net, **kwargs) merges per-call keywords over these, and those never reach the manifest: a site passing numba=True or max_iteration=100 is recorded as the descriptor alone. The gap is narrow -- per-call keywords tune how the declared engine runs, not which engine ran, and the engine is what distinguished two otherwise-identical runs -- but the field does not state what was asked of the solver, only what the backend asked before the caller spoke. A site wanting its keywords recorded resolves the backend WITH them (resolve_powerflow_backend(id, numba=True)) so they land in the instance descriptor, rather than passing them per solve.

contract_version = '1'

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

as_dict()

Return a plain-JSON view of the descriptor for provenance.

Returns:

Type Description
dict[str, Any]

A dict with only str/None/JSON-native values, so it can be embedded in the run manifest without a custom encoder.

PowerFlowBackendRegistry

Resolve power-flow backends by stable, explicitly registered ID.

create(backend_id, **kwargs)

Instantiate a registered backend.

Parameters:

Name Type Description Default
backend_id str

The registered ID; no discovery, no fallback.

required
**kwargs Any

Settings forwarded to the backend factory.

required

Returns:

Type Description
PowerFlowBackend

A ready-to-use backend.

Raises:

Type Description
UnknownPowerFlowBackendError

If backend_id is not registered.

MissingCapabilityError

If the backend needs an optional extra that is not installed.

get_descriptor(backend_id)

Return descriptor metadata for a registered backend.

Parameters:

Name Type Description Default
backend_id str

The registered ID.

required

Returns:

Type Description
PowerFlowBackendDescriptor

The registered descriptor.

list_descriptors()

Return registered backend descriptors sorted by backend ID.

Returns:

Type Description
list[PowerFlowBackendDescriptor]

One descriptor per registration, ordered by ID so callers and manifests see a stable sequence.

register(factory, *, descriptor=None, replace=False, source='core', version=None)

Register a backend factory under its descriptor's ID.

Parameters:

Name Type Description Default
factory Callable[..., PowerFlowBackend]

Callable returning a :class:PowerFlowBackend.

required
descriptor PowerFlowBackendDescriptor | None

Descriptor to register under. Defaults to the one the factory declares.

None
replace bool

Allow overwriting an already-registered ID.

False
source Literal

Registration source -- "core" for the shipped defaults, "host" when a host extension registers. Only the enumerated :data:ExtensionSource values are accepted, mirroring ExtensionDescriptor.__post_init__ -- a typo'd source must not silently brand a core backend as an extension in the governed manifest.

'core'
version str | None

Optional semantic version when an extension supplies one.

None

Raises:

Type Description
ValueError

If the ID is taken and replace is false. The message names the ID and the flag that would permit it.

ValueError

If source is not one of the declared :data:ExtensionSource values.

registration_source(backend_id)

Return the source a backend was registered under.

Parameters:

Name Type Description Default
backend_id str

The registered ID.

required

Returns:

Type Description
Literal

"core" for the shipped defaults, "host" for a host extension registration.

registration_version(backend_id)

Return the semantic version an extension recorded, if any.

Parameters:

Name Type Description Default
backend_id str

The registered ID.

required

Returns:

Type Description
str | None

The recorded version, or None when the registration did not supply one.

ScheduledEvent

One event waiting in, or popped from, an :class:EventScheduler.

Attributes:

Name Type Description
time

Simulated time the event fires at.

priority

Lower fires first among events at the same time.

key

Stable identifier that breaks remaining ties, e.g. a message id.

sequence

Insertion order; the final tie-break.

payload

Opaque to the scheduler.

StandardPowerflowScenario

Declarative load/PV/EV operating case for a pandapower network.

ev_buses = ()

Built-in immutable sequence.

If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.

If the argument is a tuple, the return value is the same object.

ev_mw_per_bus = 0.0

Convert a string or number to a floating-point number, if possible.

load_multiplier = 1.0

Convert a string or number to a floating-point number, if possible.

pv_buses = ()

Built-in immutable sequence.

If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.

If the argument is a tuple, the return value is the same object.

pv_mw_per_bus = 0.0

Convert a string or number to a floating-point number, if possible.

Surrogate

Bases: typing.Protocol

A fast estimator with a declared physical reference and known error.

The three methods are a lifecycle, not a schema: fit a model (trivially, for a fit-free surrogate), predict whatever frame the surrogate's own domain defines, and verify it against that domain's physical labels. verify is what makes the stated bound falsifiable rather than prose.

The network-impact surrogates this module shipped first predict a selector-compatible impact frame and verify against finite-difference physics labels, but that pairing is theirs, not the protocol's. A surrogate in another domain -- a thermal model checked against a building-physics reference, say -- implements the same three methods over its own frames and states its accuracy through :func:measure_error_bound.

descriptor

Return the surrogate's identity and stated error bound.

Declared read-only: implementations expose it as a property so a consumer cannot rebind the accuracy a decision was justified by.

fit(training, labels=None)

Fit the surrogate and return the model it will predict with.

Parameters:

Name Type Description Default
training DataFrame

Feature table from build_training_dataset.

required
labels DataFrame | None

Physics labels, for surrogates that need supervision.

None

Returns:

Type Description
The fitted model, passed back to

meth:predict.

predict(training, model=None)

Predict selector-compatible provider impact.

Parameters:

Name Type Description Default
training DataFrame

Feature table from build_training_dataset.

required
model dict[str, Any] | None

The model returned by :meth:fit, where one is needed.

None

Returns:

Type Description
DataFrame

A prediction frame carrying :data:PREDICTED_DELTA_LOADING_COLUMN.

verify(predictions, labels)

Re-measure this surrogate's accuracy against physics labels.

Parameters:

Name Type Description Default
predictions DataFrame

A frame returned by :meth:predict.

required
labels DataFrame

Finite-difference physics labels.

required

Returns:

Type Description
A freshly measured

class:ErrorBound.

SurrogateDescriptor

Identity, physical reference and stated accuracy of a surrogate.

Attributes:

Name Type Description
surrogate_id

Stable ID a caller resolves the surrogate by.

name

Human-readable description for reports and manifests.

physical_model

The physical model this surrogate approximates. Named, not implied, because the error bound is meaningless without it.

error_bound

The surrogate's stated accuracy. Optional on the dataclass so an unbounded descriptor can be constructed and refused; the registry rejects None at registration.

contract_version = '1'

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

as_dict()

Return a plain-JSON view of the descriptor for reports.

Returns:

Type Description
dict[str, Any]

A dict of JSON-native values only.

SurrogateRegistry

Resolve surrogates by stable, explicitly registered ID.

create(surrogate_id, **kwargs)

Instantiate a registered surrogate.

Parameters:

Name Type Description Default
surrogate_id str

The registered ID; no discovery, no fallback.

required
**kwargs Any

Settings forwarded to the surrogate factory.

required

Returns:

Type Description
Surrogate

A ready-to-use surrogate.

Raises:

Type Description
UnknownSurrogateError

If surrogate_id is not registered.

get_descriptor(surrogate_id)

Return descriptor metadata for a registered surrogate.

Parameters:

Name Type Description Default
surrogate_id str

The registered ID.

required

Returns:

Type Description
SurrogateDescriptor

The registered descriptor, including its stated error bound.

list_descriptors()

Return registered surrogate descriptors sorted by surrogate ID.

Returns:

Type Description
list[SurrogateDescriptor]

One descriptor per registration, ordered by ID so callers and reports see a stable sequence.

register(factory, *, descriptor=None, replace=False, source='core', version=None)

Register a surrogate factory under its descriptor's ID.

Parameters:

Name Type Description Default
factory Callable[..., Surrogate]

Callable returning a :class:~gridalyn.simulation.surrogates.contract.Surrogate.

required
descriptor SurrogateDescriptor | None

Descriptor to register under. Defaults to the one the factory declares.

None
replace bool

Allow overwriting an already-registered ID.

False

Raises:

Type Description
UnboundedSurrogateError

If the descriptor states no error bound.

ValueError

If the ID is taken and replace is false. The message names the ID and the flag that would permit it.

registration_source(surrogate_id)

Return the source a surrogate was registered under.

Parameters:

Name Type Description Default
surrogate_id str

The registered ID.

required

Returns:

Type Description
Literal

"core" for the shipped defaults, "host" for a host extension registration.

registration_version(surrogate_id)

Return the semantic version an extension recorded, if any.

Parameters:

Name Type Description Default
surrogate_id str

The registered ID.

required

Returns:

Type Description
str | None

The recorded version, or None when the registration did not supply one.

SyntheticNetworkBuildResult

Artifacts created by :func:build_synthetic_network_from_geojson.

TabularVoltageControlConfig

Configuration for a compact tabular voltage-control policy.

alpha = 0.28

Convert a string or number to a floating-point number, if possible.

baseline_epsilon = 0.0

Convert a string or number to a floating-point number, if possible.

episode_count = 90

int([x]) -> integer int(x, base=10) -> integer

Convert a number or string to an integer, or return 0 if no arguments are given. If x is a number, return x.int(). For floating-point numbers, this truncates towards zero.

If x is not a number or if base is given, then x must be a string, bytes, or bytearray instance representing an integer literal in the given base. The literal can be preceded by '+' or '-' and be surrounded by whitespace. The base defaults to 10. Valid bases are 0 and 2-36. Base 0 means to interpret the base from the string as an integer literal.

int('0b100', base=0) 4

gamma = 0.88

Convert a string or number to a floating-point number, if possible.

initial_epsilon = 0.55

Convert a string or number to a floating-point number, if possible.

min_epsilon = 0.04

Convert a string or number to a floating-point number, if possible.

random_seed = 7

int([x]) -> integer int(x, base=10) -> integer

Convert a number or string to an integer, or return 0 if no arguments are given. If x is a number, return x.int(). For floating-point numbers, this truncates towards zero.

If x is not a number or if base is given, then x must be a string, bytes, or bytearray instance representing an integer literal in the given base. The literal can be preceded by '+' or '-' and be surrounded by whitespace. The base defaults to 10. Valid bases are 0 and 2-36. Base 0 means to interpret the base from the string as an integer literal.

int('0b100', base=0) 4

soc_high_bin_mwh = 0.3

Convert a string or number to a floating-point number, if possible.

soc_low_bin_mwh = 0.16

Convert a string or number to a floating-point number, if possible.

step_count = 24

int([x]) -> integer int(x, base=10) -> integer

Convert a number or string to an integer, or return 0 if no arguments are given. If x is a number, return x.int(). For floating-point numbers, this truncates towards zero.

If x is not a number or if base is given, then x must be a string, bytes, or bytearray instance representing an integer literal in the given base. The literal can be preceded by '+' or '-' and be surrounded by whitespace. The base defaults to 10. Valid bases are 0 and 2-36. Base 0 means to interpret the base from the string as an integer literal.

int('0b100', base=0) 4

voltage_high_bin_pu = 1.025

Convert a string or number to a floating-point number, if possible.

voltage_low_bin_pu = 0.995

Convert a string or number to a floating-point number, if possible.

TabularVoltageControlResult

Tables produced by training and evaluating a tabular voltage controller.

TransformerPeakValidationConfig

Parameters for a compact transformer peak-loading validation network.

ext_grid_vm_pu = 1.02

Convert a string or number to a floating-point number, if possible.

feeder_c_nf_per_km = 400.0

Convert a string or number to a floating-point number, if possible.

feeder_length_km = 4.0

Convert a string or number to a floating-point number, if possible.

feeder_max_i_ka = 0.5

Convert a string or number to a floating-point number, if possible.

feeder_r_ohm_per_km = 0.1

Convert a string or number to a floating-point number, if possible.

feeder_x_ohm_per_km = 0.1

Convert a string or number to a floating-point number, if possible.

load_q_to_p_ratio = 0.33

Convert a string or number to a floating-point number, if possible.

winter_design_ambient_c = -22.5

Convert a string or number to a floating-point number, if possible.

UnboundedSurrogateError

Bases: builtins.ValueError

Raised when a surrogate is registered without a stated error bound.

UnknownChannelModelError

Bases: builtins.KeyError

Raised when a requested channel model is not registered.

UnknownPowerFlowBackendError

Bases: builtins.KeyError

Raised when a requested power-flow backend is not registered.

UnknownSurrogateError

Bases: builtins.KeyError

Raised when a requested surrogate is not registered.

VoltageControlEnvironment

Deterministic voltage-control environment for RL and policy evaluation.

reset()

Reset the battery state of charge to its configured initial value.

step(step, action_mw)

Apply an externally supplied action and return the resulting metrics.

Parameters:

Name Type Description Default
step int

Zero-based step index.

required
action_mw float

Requested battery action in MW; the environment still applies its own state-of-charge feasibility clamp.

required

Returns:

Type Description
dict

A record with the applied action, resulting voltages and reward.

VoltageControlEnvironmentSpec

Configuration contract for a voltage-control simulation environment.

action_weight = 0.25

Convert a string or number to a floating-point number, if possible.

voltage_deviation_weight = 8.0

Convert a string or number to a floating-point number, if possible.

voltage_violation_weight = 120.0

Convert a string or number to a floating-point number, if possible.

analyze_line_sizing(net, *, assume_converged=None)

Diagnose AC line sizing against downstream load -- strictly read-only.

The input network is treated as immutable: only net.bus, net.load, net.line, net.trafo, net.ext_grid and (when present) net.res_line are read. No power flow is run here; this entry only reads existing results. Use :func:analyze_synthetic_line_sizing when a flow may need to be (re)run on a copy.

Parameters:

Name Type Description Default
net Any

A pandapower network. Not mutated.

required
assume_converged bool | None

Override convergence detection. When None the value of net.converged is used.

None

Returns:

Type Description
A

class:LineSizingResult with per-line rows, per-level aggregates and correlations. When the flow has not converged, loading_percent entries are NaN and converged is False but the structural downstream-load vs max_i_ka correlation is still computed.

analyze_synthetic_line_sizing(*, footprints_path, config, clustering_crs='auto', run_powerflow=True, **build_kwargs)

Build a synthetic network then run the read-only line-sizing diagnostic.

Parameters:

Name Type Description Default
footprints_path Path | str

Path to the building-footprints GeoJSON.

required
config Mapping[str, Any]

Synthetic-network configuration mapping.

required
clustering_crs str | int | None

CRS used to cluster footprints ("auto" by default).

'auto'
run_powerflow bool

When True, ensure a power flow is solved (on a deep copy) before reading loading values, so the build result's network stays unmodified.

True
**build_kwargs Any

Forwarded to build_synthetic_network_from_config (e.g. out_dir, write_cache).

required

Returns:

Type Description
A

class:LineSizingResult. Non-convergence is handled gracefully: loading_percent is optional while the structural correlation is always computed.

apply_battery_dispatch_to_pandapower(net, dispatch)

Add dispatched battery injections as pandapower static generators.

apply_der_dispatch_setpoints_to_pandapower(net, der_assets, pv_dispatch_mw, battery_charge_mw)

Attach DER PV dispatch and battery-charge setpoints to a pandapower net.

apply_pv_generation_to_pandapower(net, prosumers, *, pv_factor)

Add PV static generators for prosumer rows and return element IDs.

apply_standard_powerflow_scenario(net, scenario)

Apply load growth, distributed PV, and EV charging to a pandapower net.

build_der_dispatch_pandapower_network(build_feeder, der_assets, pv_dispatch_mw, battery_charge_mw, *, run_powerflow=True)

Build a feeder snapshot with DER dispatch setpoints applied.

build_graph_snapshot(providers, sensitivity, *, scenario_id=None)

Build graph node/edge records with schemas compatible with a future GNN.

build_ieee33_benchmark_feeder(spec=IeeeBenchmarkFeederSpec(benchmark_id='ieee_33_bus', display_name='IEEE 33-Bus Distribution Feeder', source_name='pandapower.networks.case33bw', expected_bus_count=33, expected_line_count=37, expected_load_count=32), *, run_powerflow=False)

Build the IEEE 33-bus benchmark through Gridalyn's model contract.

build_network_impact_catalog(report_paths, *, expected_scenarios, root)

Group existing Network Impact reports by their declared scenario_id.

build_network_impact_verification_report(*, scenario_id, constraint_ids, case_metrics, dispatch_summaries, surrogate_error_bounds=None)

Build the canonical network-impact verification report.

Parameters:

Name Type Description Default
scenario_id str

Scenario the cases were solved for.

required
constraint_ids list[str]

Constraints the dispatch targeted.

required
case_metrics dict[str, dict[str, Any]]

Solved metrics per case; must include unmanaged.

required
dispatch_summaries dict[str, dict[str, Any]]

Delivery/shortfall summaries per case.

required
surrogate_error_bounds Mapping[str, ErrorBound] | None

Stated accuracy of the surrogates whose rankings fed the dispatch, keyed by surrogate ID. Omitted from the payload when None, so an existing caller's report is unchanged; supply it to make the screening accuracy part of the verification record rather than folklore.

None

Returns:

Type Description
dict[str, Any]

The verification report payload.

Raises:

Type Description
ValueError

If case_metrics has no unmanaged baseline to compare the managed cases against.

build_pandapower_summary(net, *, network=None, simulation_engine='pandapower', extra=None)

Build a compact, stable summary for a solved pandapower network.

build_physics_surrogate_report(model, predictions, *, scenario_id)

Summarize the physics-trained surrogate predictions.

build_provider_impact_predictions(training)

Score provider/constraint pairs with the deterministic v1 tabular surrogate.

build_radial_pandapower_feeder(spec)

Build a simple radial pandapower feeder from a stable Gridalyn spec.

build_surrogate_report(nodes, edges, training, predictions, *, scenario_id)

Summarize surrogate artifacts and make the validation boundary explicit.

build_synthetic_network_from_config(*, footprints_path, config, out_dir=None, config_source='runtime_config', clustering_crs='auto', write_cache=False, run_powerflow=False, building_peak_loads_kw=None, check_line_sizing=False, lv_assignment=None, block_penalty_km2=None, snap_transformers_to_streets=None)

Build a synthetic distribution network from an explicit config mapping.

Parameters:

Name Type Description Default
footprints_path Path | str

GeoJSON file with building polygons.

required
config dict[str, Any]

Grid configuration mapping.

required
out_dir Path | str | None

Optional directory for cache files and validation report.

None
config_source Path | str

Provenance label or path recorded in the report.

'runtime_config'
clustering_crs str | int | None

Metric CRS for clustering ("auto" estimates UTM).

'auto'
write_cache bool

When true, write the graph/net cache pickles to out_dir.

False
run_powerflow bool

When true, run an AC power flow and record convergence.

False
building_peak_loads_kw Sequence[float] | None

Optional per-building peak loads (kW) overriding the uniform config envelope.

None
check_line_sizing bool

When true, run the read-only line-sizing diagnostic on a deep copy after the build and warn on over-100% loading or a ~0 downstream-load/conductor correlation. Adds no report bytes. Defaults to False (zero behavior change).

False
lv_assignment str | None

"kmeans" or "capacitated"; None (the default) takes config["topology"], else K-means. See :func:gridalyn.twin.adapters.pandapower_builder.build_power_grid_and_network.

None
block_penalty_km2 float | None

With "capacitated", keep clusters from straddling streets; None takes the config's value.

None
snap_transformers_to_streets bool | None

Site transformers on the street; None takes the config's value.

None

Returns:

Type Description
A

class:SyntheticNetworkBuildResult.

build_synthetic_network_from_geojson(*, footprints_path, config_path, out_dir=None, clustering_crs='auto', write_cache=False, run_powerflow=False, building_peak_loads_kw=None, check_line_sizing=False, lv_assignment=None, block_penalty_km2=None, snap_transformers_to_streets=None)

Build a synthetic distribution network from building footprints.

Parameters:

Name Type Description Default
footprints_path Path | str

GeoJSON file with building polygons.

required
config_path Path | str

Grid configuration JSON.

required
out_dir Path | str | None

Optional directory for cache files and validation report.

None
clustering_crs str | int | None

Metric CRS for clustering. "auto" estimates a local UTM CRS from the footprint layer. Graph geodata remains longitude/latitude.

'auto'
write_cache bool

When true, write pg_graph_cache.pkl and pp_net_cache.pkl in out_dir for downstream adapters.

False
run_powerflow bool

When true, run a pandapower AC power flow and record convergence in the report.

False
building_peak_loads_kw Sequence[float] | None

Optional per-building peak loads (kW) that override the uniform config envelope, one value per network load in load-table order. Transformer and line sizing still use the declared envelope; q/p ratios are preserved.

None
check_line_sizing bool

When true, run the read-only line-sizing diagnostic on a deep copy after the build and emit a runtime warning on over-100% loading or a ~0 downstream-load/conductor correlation. Adds no report bytes. Defaults to False (zero behavior change).

False
lv_assignment str | None

"kmeans" or "capacitated"; None (the default) takes config["topology"], else K-means. See :func:gridalyn.twin.adapters.pandapower_builder.build_power_grid_and_network.

None
block_penalty_km2 float | None

With "capacitated", keep clusters from straddling streets; None takes the config's value.

None
snap_transformers_to_streets bool | None

Site transformers on the street; None takes the config's value.

None

build_training_dataset(providers, sensitivity, *, scenario_id)

Build a deterministic training table for the first surrogate baseline.

build_voltage_control_feeder(feeder, der)

Build a radial feeder with named PV and battery control elements.

configure_headless_matplotlib(cache_dir=PosixPath('outputs/cache/matplotlib'))

Configure Matplotlib for workflow scripts that run without a display.

default_channel_model_registry()

Return the shared default registry of channel models.

Built once and cached, so an extension registered through :func:register_channel_model_extension stays resolvable on the default path. Building it registers the shipped models and constructs none.

default_powerflow_backend_registry()

Return the shared default registry of power-flow backends.

The registry is built once and cached: external backends registered via :func:register_powerflow_backend_extension must stay resolvable through the default resolution path, which requires one persistent instance. Building it registers the shipped backends and constructs nothing, so it needs neither pandapower nor lightsim2grid.

default_surrogate_registry()

Return the shared default registry of surrogates.

Built once and cached so external surrogates registered via :func:register_surrogate_extension stay resolvable through the default path. Holds exactly the surrogates this repository ships: the deterministic topology surrogate behind network_impact_predictions.parquet and the physics-fitted lookup behind network_impact_physics_predictions.parquet.

describe_channel_model(factory)

Return the descriptor a channel-model factory declares.

Parameters:

Name Type Description Default
factory Any

A channel-model class carrying a DESCRIPTOR attribute.

required

Returns:

Type Description
ChannelModelDescriptor

The declared descriptor.

Raises:

Type Description
TypeError

factory declares no usable DESCRIPTOR; the message names the factory and what to add.

fit_physics_surrogate(training, labels)

Fit an explainable physics surrogate from pandapower finite differences.

measure_relief_error_bound(predictions, labels, *, reference, method)

Measure a surrogate's relief prediction against physics labels.

The comparison is schema-defined rather than per-surrogate: a surrogate's predicted relief per kW is the negation of :data:PREDICTED_DELTA_LOADING_COLUMN, and the physical model's is :data:RELIEF_LABEL_COLUMN. Both are percentage points of constraint transformer loading per curtailed kW, so the difference is meaningful without a unit conversion.

Parameters:

Name Type Description Default
predictions DataFrame

A surrogate prediction frame carrying the join keys and :data:PREDICTED_DELTA_LOADING_COLUMN.

required
labels DataFrame

Finite-difference physics labels from perturbation_sampler.build_physics_labels.

required
reference str

The physical model the labels came from.

required
method str

The evaluation protocol and dataset, recorded on the bound.

required

Returns:

Type Description
A ``measured``

class:ErrorBound, or an unmeasured one when the join leaves no labelled rows -- an empty overlap is a missing measurement, not an accuracy of zero.

Raises:

Type Description
ValueError

If either frame is missing a column the comparison needs. The message names the frame and the missing columns.

observe_network(results, *, as_of=None)

Read a :class:NetworkObservation off a solved network's result tables.

This is the pandapower-shaped adapter, and the only place in the contract that knows those table names. It reads by attribute and column name rather than by type, so anything exposing res_bus / res_line frames satisfies it, and anything that does not can build a :class:NetworkObservation directly.

Parameters:

Name Type Description Default
results Any

A solved network -- typically a pandapowerNet mutated in place by the simulation layer's power-flow backend. A missing table or column is read as "not reported" rather than raising, because the summary writers this replaces already tolerated it.

required
as_of datetime | None

The instant the solved state belongs to. Keyword-only and defaulting to None because results carries no clock of its own: only the caller that chose the operating point knows which instant it represents. Nothing is inferred when it is omitted -- see :data:AS_OF_ABSENT_REASON.

None

Returns:

Type Description
NetworkObservation

The observation. Absent bus/line tables yield empty arrays; an absent loss column yields total_line_loss_mw=None, which is a different answer from 0.0; an omitted as_of yields as_of=None. The provenance is always "simulated": this producer reads solver results, so that is the only honest answer it can give.

predict_physics_impact(training, model)

Predict selector-compatible provider impact from a physics surrogate.

prepare_synthetic_topology_cache(*, input_file, cache_dir, config, manifest_path=None, force_rebuild=False, notes=None)

Build a synthetic topology cache and write a lineage manifest.

register_channel_model_extension(factory, *, descriptor, replace=False, version=None, registry=None)

Register an external channel model (host API).

The registration is recorded with source="host" and the given version, so a record can name the extension that served the role.

Parameters:

Name Type Description Default
factory Callable[..., ChannelModel]

Callable returning a :class:ChannelModel.

required
descriptor ChannelModelDescriptor

Descriptor declaring the model's identity and contract version.

required
replace bool

Allow overwriting an already-registered ID.

False
version str | None

Optional semantic version of the extension.

None
registry ChannelModelRegistry | None

Registry to register into; defaults to the shared default.

None

register_policy_extension(factory, *, descriptor, replace=False, registry=None)

Register an external voltage-control policy (host API).

A third-party policy conforms to the :class:Policy contract, carries a :class:PolicyDescriptor with a supported contract_version, and registers it here — no edit to gridalyn's codebase required. Defaults to the shared default registry.

register_powerflow_backend_extension(factory, *, descriptor, replace=False, version=None, registry=None)

Register an external power-flow backend (host API).

A third-party backend conforms to the :class:PowerFlowBackend contract, carries a :class:PowerFlowBackendDescriptor with a supported contract_version, and registers it here -- no edit to gridalyn's codebase required. Defaults to the shared default registry. The registration is recorded with source="host" so the run manifest can name the extension that served the backend role.

Parameters:

Name Type Description Default
factory Callable[..., PowerFlowBackend]

Callable returning a :class:PowerFlowBackend.

required
descriptor PowerFlowBackendDescriptor

Descriptor declaring the backend's identity and contract version.

required
replace bool

Allow overwriting an already-registered ID.

False
version str | None

Optional semantic version of the extension.

None
registry PowerFlowBackendRegistry | None

Registry to register into; defaults to the shared default.

None

register_surrogate_extension(factory, *, descriptor, replace=False, registry=None)

Register an external surrogate (host API).

A third-party surrogate conforms to the :class:Surrogate contract, carries a :class:SurrogateDescriptor with a stated error bound and a supported contract_version, and registers it here — no edit to gridalyn's codebase required. Defaults to the shared default registry.

registered_error_bounds()

Return every registered surrogate's stated error bound, by ID.

Returns:

Type Description
dict[str, dict[str, Any]]

A plain-JSON mapping suitable for embedding in a verification report, so a report states the accuracy of every surrogate it could have used rather than only the one it did.

resolve_channel_model(channel_model_id='ideal', **parameters)

Resolve one channel model from the default registry by explicit ID.

Parameters:

Name Type Description Default
channel_model_id str

Registered ID; defaults to the ideal channel.

'ideal'
**parameters Any

Parameters forwarded to the model factory.

required

resolve_powerflow_backend(backend_id='pandapower_native', **settings)

Resolve one backend from the default registry by explicit ID.

Parameters:

Name Type Description Default
backend_id str

Registered backend ID. Defaults to the pandapower-native backend, which needs no optional extra.

'pandapower_native'
**settings Any

Settings forwarded to the backend factory.

required

Returns:

Type Description
PowerFlowBackend

A ready-to-use backend.

resolve_surrogate(surrogate_id='network_impact_tabular_v1', **settings)

Resolve one surrogate from the default registry by explicit ID.

Parameters:

Name Type Description Default
surrogate_id str

Registered surrogate ID.

'network_impact_tabular_v1'
**settings Any

Settings forwarded to the surrogate factory.

required

Returns:

Type Description
Surrogate

A ready-to-use surrogate.

run_standard_powerflow_scenario(net, scenario, *, algorithm='nr', init='auto')

Apply and solve a standard operating scenario.

scenario_to_record(scenario)

Serialize a standard scenario declaration for project inputs.

select_line_std_type(net, *, level, i_design_ka, utilization_margin)

Snap a design current to a pandapower standard line type.

The catalog is :func:pandapower.available_std_types filtered to the matching voltage_rating family and sorted ascending by (max_i_ka, std_type_name) so ties are deterministic regardless of catalog/dict ordering. The first entry whose max_i_ka is at least the required rating i_design_ka / utilization_margin is chosen — the margin RESERVES HEADROOM (a line at design load sits at <= utilization_margin of its chosen ampacity). When the required current exceeds the largest entry, the largest is returned with over_capacity set so the shortfall is surfaced rather than silently clipped (parallel feeders are out of scope).

.. note:: An earlier formula used i_design_ka * utilization_margin, which inverted the margin (snapped below design current) and overloaded the twin. This is the corrected, headroom-reserving form.

Parameters:

Name Type Description Default
net Any

A pandapower network (read only; used to read the std-type catalog).

required
level str

Voltage level family, "LV" / "MV" / "HV" (case-insensitive).

required
i_design_ka float

Design current in kA.

required
utilization_margin float

Target design-current-to-rating ratio in (0, 1]; the required rating is i_design_ka / utilization_margin (e.g. 0.8 reserves 20% headroom). Values <= 0 are treated as no-margin (required rating == i_design_ka).

required

Returns:

Type Description
tuple[str, dict[str, float], bool]

A tuple (std_type_name, catalog_row, over_capacity) where catalog_row is a mapping with max_i_ka, r_ohm_per_km, x_ohm_per_km and c_nf_per_km from the chosen entry.

Raises:

Type Description
ValueError

When no catalog entry exists for level -- the message lists the available families to remediate.

size_lines_load_aware(net, config)

Rewrite each on-tree line's conductor from its full downstream load.

This is an in-place post-pass intended to run on the builder's network during generation, before any cache is written. For every line that lies on the radial tree rooted at the ext_grid bus it computes the FULL (non-coincident) downstream subtree demand — the load the power flow actually injects — derives the design current, snaps to a pandapower standard line type via :func:select_line_std_type, and copies the chosen std_type plus max_i_ka / r_ohm_per_km / x_ohm_per_km / c_nf_per_km onto the line row. Lines not on the rooted tree keep their current values.

No diversity/coincidence reduction is applied: the generator assigns each building its full load and the power flow injects it in full, so sizing for a diversified demand would undersize conductors by ~the diversity factor and overload the simulated network.

Parameters:

Name Type Description Default
net Any

A pandapower network. Mutated in place (line table only).

required
config dict[str, Any]

Synthetic-network configuration mapping. Reads lines.sizing.utilization_margin (default 0.8). The margin reserves headroom: each line is snapped to a rating >= i_design / margin so it sits at <= margin of ampacity at design load (corrects an earlier inverted * margin formula).

required

Returns:

Type Description
list[dict[str, Any]]

A per-line sizing summary list in net.line index order, one dict per on-tree line with keys idx, level, downstream_load_mw, i_design_ka, chosen_std_type, max_i_ka and over_capacity. downstream_load_mw is the FULL non-coincident subtree load. Float fields are rounded to 6 decimals to stay below the 1e-6 regression noise floor.

solve_power_flow(net, *, backend_id='pandapower_native', **kwargs)

Solve net in place through a registry-resolved backend.

The single-call convenience behind every power-flow call site in this repository. Call sites that solve in a loop should resolve a backend once with :func:resolve_powerflow_backend and reuse it instead.

Parameters:

Name Type Description Default
net Any

A pandapower network, mutated in place with res_* tables.

required
backend_id str

Registered backend ID.

'pandapower_native'
**kwargs Any

Per-call solver keywords; they override the backend's own settings.

required

summarize_tabular_voltage_control(result, spec, config=TabularVoltageControlConfig(episode_count=90, step_count=24, alpha=0.28, gamma=0.88, random_seed=7, baseline_epsilon=0.0, initial_epsilon=0.55, min_epsilon=0.04, voltage_low_bin_pu=0.995, voltage_high_bin_pu=1.025, soc_low_bin_mwh=0.16, soc_high_bin_mwh=0.3))

Build the canonical report summary for a tabular voltage-control run.

train_tabular_voltage_controller(spec, config=TabularVoltageControlConfig(episode_count=90, step_count=24, alpha=0.28, gamma=0.88, random_seed=7, baseline_epsilon=0.0, initial_epsilon=0.55, min_epsilon=0.04, voltage_low_bin_pu=0.995, voltage_high_bin_pu=1.025, soc_low_bin_mwh=0.16, soc_high_bin_mwh=0.3))

Train and evaluate a tabular Q-learning voltage controller.

unmeasured_error_bound(*, metric, units, reference, reason)

Build a bound that honestly states no measurement exists.

Parameters:

Name Type Description Default
metric str

The statistic that would have been measured.

required
units str

Units that statistic would carry.

required
reference str

The physical model it would have been measured against.

required
reason str

Located explanation of what blocked the measurement.

required

Returns:

Type Description
An ``unmeasured``

class:ErrorBound.

validate_transformer_peak_scenarios(*, scenarios, config)

Run pandapower peak-loading checks for unmanaged scenario peaks.

write_network_impact_catalog(path, catalog)

Write the dashboard Network Impact catalog.

write_pandapower_element_tables(net, output_dir, *, elements=('bus', 'line', 'load'))

Write standard pandapower element/result tables and return their paths.

write_powerflow_report(path, *, metadata, net, inputs=None, artifacts=(), summary=None, validation=None)

Write a standard Gridalyn report for a pandapower power-flow run.

write_tabular_voltage_control_figure(result, path, *, voltage_low_pu, voltage_high_pu)

Write the canonical tabular voltage-control training figure.

write_voltage_profile_figure(net, path, *, title, lower_limit_pu=0.95, upper_limit_pu=1.05, xlabel='Bus', ylabel='Voltage magnitude [p.u.]', figsize=(8.5, 4.6))

Write a standard feeder voltage-profile figure.

gridalyn.operations

Operational services, market clearing, dispatch, and settlement facade.

DR_PROGRAM_PROTOCOL = ProtocolSpec(protocol_id='dr_program', version='2', standard='OpenADR 3.1.0 event and report objects; cancellation, opt-out and the simulated-time activation window are flexint extensions', states=('idle', 'notified', 'active', 'completed', 'cancelled', 'opted_out'), initial='idle', message_types=(MessageTypeSpec(message_type='event', source='OpenADR 3.1.0', required_fields=('programID', 'intervals', 'flexint:activeFrom', 'flexint:activeUntil')), MessageTypeSpec(message_type='report', source='OpenADR 3.1.0', required_fields=('clientID', 'eventID', 'clientName', 'resources')), MessageTypeSpec(message_type='flexint:EventCancellation', source='flexint extension', required_fields=('eventID',)), MessageTypeSpec(message_type='flexint:OptOut', source='flexint extension', required_fields=('eventID', 'clientName'))), transitions=(MessageTransition(source='idle', message_type='event', performative='inform', sender_roles=('program_administrator',), receiver_roles=('aggregator', 'active_customer'), target='notified'), MessageTransition(source='notified', message_type='event', performative='inform', sender_roles=('program_administrator',), receiver_roles=('aggregator', 'active_customer'), target='notified'), MessageTransition(source='notified', message_type='flexint:EventCancellation', performative='cancel', sender_roles=('program_administrator',), receiver_roles=('aggregator', 'active_customer'), target='cancelled'), MessageTransition(source='active', message_type='flexint:EventCancellation', performative='cancel', sender_roles=('program_administrator',), receiver_roles=('aggregator', 'active_customer'), target='cancelled'), MessageTransition(source='notified', message_type='flexint:OptOut', performative='refuse', sender_roles=('aggregator', 'active_customer'), receiver_roles=('program_administrator',), target='opted_out'), MessageTransition(source='active', message_type='flexint:OptOut', performative='refuse', sender_roles=('aggregator', 'active_customer'), receiver_roles=('program_administrator',), target='opted_out'), MessageTransition(source='active', message_type='report', performative='inform', sender_roles=('aggregator', 'active_customer'), receiver_roles=('program_administrator',), target='active'), MessageTransition(source='completed', message_type='report', performative='inform', sender_roles=('aggregator', 'active_customer'), receiver_roles=('program_administrator',), target='completed'), MessageTransition(source='idle', message_type='flexint:EventCancellation', performative='cancel', sender_roles=('program_administrator',), receiver_roles=('aggregator', 'active_customer'), target='cancelled'), MessageTransition(source='opted_out', message_type='flexint:EventCancellation', performative='cancel', sender_roles=('program_administrator',), receiver_roles=('aggregator', 'active_customer'), target='opted_out'), MessageTransition(source='completed', message_type='flexint:EventCancellation', performative='cancel', sender_roles=('program_administrator',), receiver_roles=('aggregator', 'active_customer'), target='completed'), MessageTransition(source='cancelled', message_type='flexint:OptOut', performative='refuse', sender_roles=('aggregator', 'active_customer'), receiver_roles=('program_administrator',), target='cancelled'), MessageTransition(source='completed', message_type='flexint:OptOut', performative='refuse', sender_roles=('aggregator', 'active_customer'), receiver_roles=('program_administrator',), target='completed')), deadline_transitions=(DeadlineTransition(source='notified', deadline='flexint:activeFrom', target='active'), DeadlineTransition(source='active', deadline='flexint:activeUntil', target='completed')))

A protocol: its states, messages and transitions, checked on construction.

Attributes:

Name Type Description
protocol_id

The protocol's id.

version

This spec's version; bumped when the state machine changes.

standard

The standard the protocol is aligned to.

states

Every state, in reading order.

initial

The state a new conversation starts in.

message_types

Every message the protocol exchanges.

transitions

Message-driven transitions.

deadline_transitions

Time-driven transitions.

FLEX_TRADING_PROTOCOL = ProtocolSpec(protocol_id='flex_trading', version='1', standard='UFTP 3.1.0 message names between the USEF 2021 DSO and AGR roles', states=('idle', 'requested', 'offered', 'revoked', 'ordered', 'settled'), initial='idle', message_types=(MessageTypeSpec(message_type='FlexRequest', source='UFTP 3.1.0', required_fields=('event_id', 'constraint_id', 'timestep', 'required_kw')), MessageTypeSpec(message_type='FlexOffer', source='UFTP 3.1.0', required_fields=('offers',)), MessageTypeSpec(message_type='FlexOfferRevocation', source='UFTP 3.1.0', required_fields=('offer_ids',)), MessageTypeSpec(message_type='FlexOrder', source='UFTP 3.1.0', required_fields=('instructions',)), MessageTypeSpec(message_type='FlexSettlement', source='UFTP 3.1.0', required_fields=('settlements',))), transitions=(MessageTransition(source='idle', message_type='FlexRequest', performative='cfp', sender_roles=('distribution_operator',), receiver_roles=('aggregator',), target='requested'), MessageTransition(source='requested', message_type='FlexOffer', performative='propose', sender_roles=('aggregator',), receiver_roles=('distribution_operator',), target='offered'), MessageTransition(source='offered', message_type='FlexOffer', performative='propose', sender_roles=('aggregator',), receiver_roles=('distribution_operator',), target='offered'), MessageTransition(source='offered', message_type='FlexOfferRevocation', performative='cancel', sender_roles=('aggregator',), receiver_roles=('distribution_operator',), target='revoked'), MessageTransition(source='offered', message_type='FlexOrder', performative='accept-proposal', sender_roles=('distribution_operator',), receiver_roles=('aggregator',), target='ordered'), MessageTransition(source='ordered', message_type='FlexSettlement', performative='inform', sender_roles=('distribution_operator',), receiver_roles=('aggregator',), target='settled')), deadline_transitions=())

A protocol: its states, messages and transitions, checked on construction.

Attributes:

Name Type Description
protocol_id

The protocol's id.

version

This spec's version; bumped when the state machine changes.

standard

The standard the protocol is aligned to.

states

Every state, in reading order.

initial

The state a new conversation starts in.

message_types

Every message the protocol exchanges.

transitions

Message-driven transitions.

deadline_transitions

Time-driven transitions.

AgentRef

An agent, the party it belongs to, and the role it plays.

Attributes:

Name Type Description
agent_id

Identifier of the agent; unique within a run.

party_id

Identifier of the party the agent acts for. Several agents, in different roles, may share one party.

role

The functional role the agent plays.

as_dict()

Return a plain-JSON view.

AggregatorPortfolio

Aggregator portfolio over a scenario-specific provider set.

ConversationBook

Every conversation seen so far, created on its first accepted message.

accept(message, *, at=None)

Advance the message's conversation, starting it if this is its first.

A first message the protocol refuses starts nothing.

Parameters:

Name Type Description Default
message Message

The message received.

required
at float | None

Simulated receipt time; defaults to message.sent_at.

None

Returns:

Type Description
Conversation

The conversation, after the message.

Raises:

Type Description
ValueError

The conversation refuses the message (see :meth:Conversation.accept).

advance_to(time)

Advance every conversation's clock to time.

Returns:

Type Description
int

How many deadline transitions fired, across all conversations.

Raises:

Type Description
ValueError

time lies before some conversation's clock.

states()

Return each conversation's state, keyed by conversation id, sorted.

DERVoltageDispatchConfig

Configuration for linearized voltage-constrained DER dispatch.

battery_charge_weight = 0.04

Convert a string or number to a floating-point number, if possible.

perturbation_mw = 0.05

Convert a string or number to a floating-point number, if possible.

solver_name = 'CLARABEL'

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

voltage_deviation_weight = 0.05

Convert a string or number to a floating-point number, if possible.

voltage_max_pu = 1.05

Convert a string or number to a floating-point number, if possible.

voltage_min_pu = 0.95

Convert a string or number to a floating-point number, if possible.

voltage_target_pu = 1.01

Convert a string or number to a floating-point number, if possible.

DERVoltageDispatchResult

Tables and metadata produced by a DER voltage dispatch run.

The two observations are kept apart on purpose. They are two network states -- the feeder at full PV output and the feeder at the optimized setpoints -- not a full and a filtered view of one state, and the summary reports a maximum for both but a minimum only for the optimized one. Collapsing them would change what the study reports.

Attributes:

Name Type Description
sensitivity

Per-bus, per-DER voltage sensitivity table.

dispatch

Per-DER dispatch decision table.

verification

Per-bus voltages under both verified network states.

optimization_metadata

Solver name, status and objective value.

full_pv_converged

Whether the full-PV verification net converged.

optimized_converged

Whether the optimized verification net converged.

full_pv_observation

Observation of the full-PV verification net.

optimized_observation

Observation of the optimized verification net.

DispatchInstruction

Cleared dispatch action issued to a provider or aggregator.

FlexibilityOffer

Provider offer usable by a utility clearing operation.

source_standard = 'GridalynFlexibilityOperation'

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

FlexibilityOperationContext

Identity and governance scope for a flexibility clearing operation.

market_role = 'dso_flexibility_clearing'

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

ontology_profile = 'north_america'

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

schema_version = '1.0'

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

source_domain = 'operations.flexibility'

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

FlexibilityOperationValidation

Validation result for operation inputs.

Message

One message from one agent to another, inside one conversation.

Build messages with :func:build_message, which canonicalizes a payload mapping; constructing one directly requires payload_json to already be a JSON object.

Attributes:

Name Type Description
conversation_id

The conversation this message belongs to.

protocol

The protocol that conversation follows.

message_type

The protocol's name for the message, e.g. FlexOrder.

performative

The FIPA communicative act the message performs.

sender

The agent sending it, with the role it sends in.

receiver

The agent it is addressed to, with the role it receives in.

sent_at

Simulated time the message is sent.

payload_json

The payload as canonical JSON.

message_id

SHA-256 of every field above; derived, never passed.

payload

Return a fresh copy of the payload; mutating it changes nothing.

payload_json = '{}'

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

from_record(record)

Rebuild a message from a row :meth:to_record wrote.

Parameters:

Name Type Description Default
record Mapping[str, Any]

A mapping carrying every field in :data:MESSAGE_RECORD_FIELDS.

required

Returns:

Type Description
Message

The message, with its id re-derived from its content.

Raises:

Type Description
ValueError

A field is missing or invalid, or the stored id does not match the content -- the row was edited after it was written.

to_record()

Return the message as one flat row, in :data:MESSAGE_RECORD_FIELDS.

MessageBus

Send messages through a channel and deliver them in simulated time.

channel

Return the channel messages cross.

conversations

Return the conversations delivered messages have advanced.

log

Return every message sent so far, with its outcome.

scheduler

Return the scheduler deliveries are placed on.

deliver(event, handler=None)

Deliver event if it is one of this bus's messages.

Parameters:

Name Type Description Default
event ScheduledEvent

An event popped from the scheduler.

required
handler Callable | None

Called with the message and its arrival time, after its conversation has accepted it.

None

Returns:

Type Description
bool

Whether the event was a message of this bus.

Raises:

Type Description
ValueError

The message's conversation refuses it.

drain(handler=None, *, limit=1000000)

Deliver every scheduled message, including those handlers send.

Every conversation ends with its clock at the time of the last event.

Returns:

Type Description
int

How many messages were delivered.

run_until(time, handler=None)

Deliver every message arriving by time, then advance conversations.

Handlers may send further messages; those arriving by time are delivered in the same call. Every conversation ends with its clock at time, so deadlines passed by then have fired.

Returns:

Type Description
int

How many messages were delivered.

send(message)

Send a message: ask the channel, log it, and schedule its arrival.

Parameters:

Name Type Description Default
message Message

The message; sent_at may not precede the scheduler's current time.

required

Returns:

Type Description
Delivery

The channel's verdict.

Raises:

Type Description
ValueError

The message is sent in the past, or the channel delivers it before it was sent.

MessageLog

Every message a run sent, in send order.

Attributes:

Name Type Description
entries

One entry per message sent.

entries = ()

Built-in immutable sequence.

If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.

If the argument is a tuple, the return value is the same object.

count(outcome)

Return how many entries have this outcome.

delivered_in_order()

Return the delivered entries in arrival order.

from_frame(frame)

Rebuild a log from a frame :meth:to_frame produced.

Raises:

Type Description
ValueError

A column is missing, or a row is invalid; the message names the row.

to_frame()

Return the log as a frame in :data:MESSAGE_LOG_COLUMNS.

NetworkConstraint

Active network constraint that can be cleared by flexibility.

NetworkConstraintModel

Bases: typing.Protocol

Network interface required by DSO dispatch and market simulation.

probabilistic_constraint_check(p_mean_kw, p_std_kw, *, ambient_c=None, epsilon=0.05)

Return probabilistic congestion status and relief requirement.

OperationRun

Traceable execution record for a utility operation.

report_id = 'operation_run'

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

schema_version = '1.0'

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

status = 'completed'

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

OperationRunValidation

Validation result for an operation run document.

ProsumerRealtimeMarketConfig

Configuration for a rolling-horizon prosumer battery market.

locational_credit_usd_per_mwh = 2.0

Convert a string or number to a floating-point number, if possible.

reserve_fraction = 0.55

Convert a string or number to a floating-point number, if possible.

scarcity_adder_usd_per_mwh = 6.0

Convert a string or number to a floating-point number, if possible.

ProsumerRealtimeMarketResult

Tables generated by a prosumer real-time market run.

ProtocolSpec

A protocol: its states, messages and transitions, checked on construction.

Attributes:

Name Type Description
protocol_id

The protocol's id.

version

This spec's version; bumped when the state machine changes.

standard

The standard the protocol is aligned to.

states

Every state, in reading order.

initial

The state a new conversation starts in.

message_types

Every message the protocol exchanges.

transitions

Message-driven transitions.

deadline_transitions

Time-driven transitions.

deadline_transitions = ()

Built-in immutable sequence.

If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.

If the argument is a tuple, the return value is the same object.

terminal_states

Return the states no transition leaves, in declaration order.

as_dict()

Return a plain-JSON view of the whole protocol, for reports.

find_transition(state, message_type, sender_role, receiver_role)

Return the transition that accepts this message in state, or None.

message_type_spec(message_type)

Return the declared message type, or None.

transitions_from(state)

Return the message transitions leaving state, in declaration order.

SettlementRecord

Settlement line for a cleared dispatch instruction.

SpatialClsResult

Per-load Soft/Hard CLS allocation outcome.

allocate_addition_by_headroom(load_kw, target_kw, eligible, charger_kw)

Allocate rebound/additional EV load across eligible charger headroom.

allocate_reduction(load_kw, target_kw, eligible)

Allocate an aggregate reduction proportionally across eligible loads.

apply_locational_selections(*, building_kw, ev_kw, selections, providers, dt_h)

Apply provider-level locational clearing selections to load matrices.

apply_spatial_cls(building_kw, ev_kw, soft_cls_kw, hard_cls_kw, soft_eligible, hard_preferred, ev_eligible)

Apply aggregate Soft and Hard CLS targets to per-load matrices.

build_aggregator_portfolios(providers, *, scenario_id)

Build one portfolio row per aggregator in a scenario provider registry.

build_constraint_requirements(*, transformer_timeseries, transformer_id_by_idx, constraint_ids, limit_percent=100.0)

Convert transformer loading above a limit into local kW requirements.

build_conversation_book(log, *, until=None)

Replay a log's delivered messages, in arrival order, into conversations.

Parameters:

Name Type Description Default
log MessageLog

The log to replay.

required
until float | None

Simulated time to advance every conversation to afterwards, so deadlines that passed after the last message fire; pass the time the run ended at.

None

Returns:

Type Description
ConversationBook

The conversations, as the run's receivers saw them.

Raises:

Type Description
ValueError

A delivered message is refused by its conversation; the message is the conversation's located refusal.

build_dispatch_instructions(*, selections, providers, context)

Promote clearing selections into dispatch instructions.

build_flex_trading_messages(*, events, offers, dispatch, settlement, operator)

Write a cleared round as flex_trading messages, in causal order.

One conversation per event and aggregator: every aggregator holding an offer in the event's constraint zone, or ordered for the event, receives a FlexRequest and answers with a FlexOffer. An aggregator with dispatch instructions for the event then receives a FlexOrder, and a FlexSettlement when settlement records exist for them. Every message is sent at the event's timestep. Events are taken in (timestep, event_id) order and aggregators in id order, so the same round always gives the same messages.

Parameters:

Name Type Description Default
events DataFrame

Clearing events (build_locational_clearing).

required
offers DataFrame

The offer book (build_provider_offers).

required
dispatch DataFrame

Dispatch instructions (build_dispatch_instructions).

required
settlement DataFrame

Settlement records (build_settlement_records).

required
operator AgentRef

The distribution operator requesting flexibility.

required

Returns:

Type Description
The messages, ready for

func:run_message_transcript.

Raises:

Type Description
ValueError

operator is not a distribution operator, a frame lacks a column, a row is not a valid record, an instruction names no aggregator, or an instruction orders a provider that has no offer from that aggregator.

build_flexibility_clearing_scorecard(*, topology_report, physics_report=None, market_report=None, locational_report=None)

Build a scenario scorecard from pandapower-validated policy reports.

build_interval_forecast(issue_index, *, base_load_mw, total_pv_capacity_mw, config)

Create a rolling forecast issued before clearing one market interval.

build_locational_clearing(*, requirements, providers, impact, scenario_id, dt_h, clearing_method='surrogate', max_selected_providers_per_event=1000)

Clear transformer-level requirements with locational provider offers.

build_locational_clearing_verification_report(*, scenario_id, clearing_summary, case_metrics, constraint_ids)

Build a report comparing locational clearing against unmanaged load.

build_message(*, conversation_id, protocol, message_type, performative, sender, receiver, sent_at, payload=None)

Build a message, serializing payload to canonical JSON.

Numpy scalars are accepted and written as plain numbers.

Returns:

Type Description
Message

The message, with its content-derived id.

Raises:

Type Description
ValueError

The payload holds NaN/infinity or a value JSON cannot carry, or any field is invalid; the message names the message type and conversation.

build_network_constraint_set(requirements, *, scenario_id, source='network_constraint_requirements', model_version_id=None, study_run_id=None)

Normalize active requirement rows into a network constraint set.

build_network_sensitivity(providers)

Build a topology-based provider-to-transformer sensitivity table.

build_operation_context(*, scenario_id, clearing_method, dt_h, requirements, providers, impact, model_version_id=None, study_run_id=None)

Build a deterministic operation context from the operation scope.

build_operation_run(*, operation_id, operation_type, scenario_id, network_model_version_id, study_run_id, input_artifacts, output_artifacts, kpi_report, clearing_method=None, status='completed', validation=None, metrics=None, governance=None)

Build an operation run record from operation lineage and outputs.

build_operational_kpi_report(*, events, dispatch_instructions, settlement_records, constraints, context, dt_h)

Build mechanism-intelligence KPIs for an operation.

build_prosumer_realtime_market_summary(result, *, config)

Build the report summary for a prosumer real-time market result.

build_provider_offers(providers, *, scenario_id)

Convert provider registry rows into a scenario offer book.

build_provider_registry(asset_registry, connectivity, scenario_device_registry=None)

Build one row per controllable Soft CLS building and Hard CLS EV provider.

build_settlement_records(dispatch_instructions, *, dt_h)

Build settlement records from dispatch instructions.

build_shadow_report(dispatch, providers, sensitivity, *, scenario_id, constraint_ids, max_selected_providers_per_event=20)

Build a non-invasive report comparing aggregate dispatch to local selection.

clear_prosumer_interval(prosumers, soc, forecast, *, config)

Clear one interval of the rolling-horizon prosumer market.

Parameters:

Name Type Description Default
prosumers DataFrame

Per-prosumer battery/offer parameters for this interval.

required
soc dict[str, float]

Mutable map of prosumer_id to state-of-charge in MWh. Mutated in place: each cleared prosumer's entry is decremented by its dispatched energy so that state carries across intervals. run_prosumer_realtime_market relies on this contract to thread SoC through the rolling horizon. Callers that need to reuse a SoC map across independent runs must pass a fresh copy to avoid state bleed.

required
forecast DataFrame

Rolling-horizon forecast frame for this issue interval.

required
config ProsumerRealtimeMarketConfig

Market configuration parameters.

required

Returns:

Type Description
tuple[list[dict], list[dict], float, float, float | None]

A tuple of (dispatch_rows, offers, cleared_mw, cleared_cost, clearing_price).

load_message_log(path)

Load a message log written by :func:write_message_log.

Raises:

Type Description
FileNotFoundError

No file exists at path.

ValueError

The file is not a valid message log.

materialize_flexibility_operation_artifacts(*, root, project_id, scenario_id, flexibility_dir=None, out_dir=None, report_path=None, catalog_path=None, manifest_path=None)

Write project-local operational Parquet artifacts and KPI reports.

run_der_voltage_dispatch(build_feeder, der_assets, config=DERVoltageDispatchConfig(voltage_min_pu=0.95, voltage_max_pu=1.05, perturbation_mw=0.05, voltage_target_pu=1.01, battery_charge_weight=0.04, voltage_deviation_weight=0.05, solver_name='CLARABEL'))

Solve DER dispatch and verify the result with an AC pandapower snapshot.

run_flexibility_clearing_operation(*, requirements, providers, impact, scenario_id, dt_h, clearing_method='surrogate', model_version_id=None, study_run_id=None, max_selected_providers_per_event=1000)

Validate and execute a flexibility clearing operation.

run_message_transcript(messages)

Send a fixed sequence of messages through an ideal channel and deliver them.

For messages written after the fact -- such as :func:~gridalyn.operations.interaction.flex_trading.build_flex_trading_messages -- rather than by agents reacting to each other. Messages arrive in the order given (at equal times) and every conversation validates them.

Parameters:

Name Type Description Default
messages Iterable[Message]

The messages, in causal order.

required

Returns:

Type Description
MessageBus

The drained bus; read log, conversations and scheduler.now.

Raises:

Type Description
ValueError

A conversation refuses a message.

run_prosumer_powerflow(*, build_feeder, load_multiplier, prosumers, pv_factor, dispatch)

Run feeder verification for one prosumer market interval.

None enters the return type with the observation contract: a network that reports no line-loss column at all is a different answer from one that reports zero loss. Every value produced here is unchanged -- the feeder is solved immediately above, so the loss is always a float.

run_prosumer_realtime_market(*, prosumers, build_feeder, config)

Run rolling-horizon clearing, dispatch, and feeder verification.

select_providers_for_constraint(providers, sensitivity, *, scenario_id, constraint_id, required_kw)

Select local providers by effective cost until required relief is covered.

summarize_der_voltage_dispatch(result)

Build the canonical report summary for a DER voltage dispatch result.

summarize_network_constraints(constraints)

Summarize a normalized network constraint set.

summarize_provider_registry(providers)

Summarize provider counts and available capacity by scenario.

validate_cls_output_consistency(*, ev_summary, flex_requirements, pandapower_validation, dispatch_timeseries, temporal_bounds, n_buildings, dispatch_scenario='S4_40pct', tolerance=1e-09)

Validate that CLS JSON/parquet artifacts describe the same study run.

validate_flexibility_operation_inputs(*, requirements, providers, impact, context)

Validate the tabular inputs needed by the flexibility operation service.

validate_operation_run(run)

Validate the minimal lineage required for an operation run.

write_der_voltage_dispatch_figure(verification, dispatch, path, *, voltage_max_pu=1.05)

Write the canonical DER voltage-dispatch figure.

write_flexibility_clearing_scorecard(path, scorecard)

Write a clearing scorecard JSON report.

write_interaction_report(path, *, log, book, log_path, metadata, until=None, channel=None, root=None)

Write the governed report of an interaction run, checked by replay.

The report references the parquet log at log_path. Before writing, it loads that file and replays it: a file that is not the log passed, or that replays to different conversations than book, makes the report's validation.valid false with one error per difference.

inputs records each protocol the log uses (its whole state machine), the channel model, and until.

Parameters:

Name Type Description Default
path Path | str

Where to write the report JSON.

required
log MessageLog

The run's message log.

required
book ConversationBook

The run's conversations.

required
log_path Path | str

Where log was written with :func:write_message_log.

required
metadata ReportMetadata

Report identity.

required
until float | None

Simulated time the run ended at; replay advances to it.

None
channel ChannelModelDescriptor | None

The channel model the run used.

None
root Path | str | None

Root that artifact paths are recorded relative to.

None

Returns:

Type Description
The written report payload, as

func:write_report returns it.

Raises:

Type Description
FileNotFoundError

log_path does not exist.

write_locational_clearing_outputs(*, out_dir, events, selections, report)

Write locational clearing events, selections, and summary artifacts.

write_locational_verification_outputs(*, dispatch, dispatch_path, report_path)

Write the dispatch artifact and prepare the verification report path.

The report JSON itself is serialized by the caller — the workflow stage module gridalyn.projects.workflows.flexibility.locational_verification is the single writer of report_path (report-contract audit §5.2). This helper used to write the same path first with absolute machine paths in artifacts; that duplicate write was removed so the caller's ROOT-relative payload is the only one ever on disk.

Parameters:

Name Type Description Default
dispatch DataFrame

Per-timestep delivered/shortfall dispatch matrix.

required
dispatch_path Path

Destination for the dispatch parquet artifact.

required
report_path Path

Destination the caller writes the report JSON to; its parent directory is created here.

required

Returns:

Type Description
dict[str, Path]

Mapping with the dispatch and report destination paths.

write_message_log(path, log)

Write a message log as parquet.

Returns:

Type Description
Path

The path written.

write_operation_run(path, run)

Write an operation run JSON document.

write_prosumer_market_dispatch_figure(clearing, path, *, import_limit_mw)

Write the standard prosumer real-time market dispatch figure.

write_shadow_report(path, report)

Write a provider-selection shadow report JSON artifact.

gridalyn.projects

Project and workflow contracts for reproducible Gridalyn studies.

CreatedProject

Paths to the workspace :func:init_project just wrote.

Returned so a caller can go straight from scaffolding a project to loading or running it, without re-deriving the two YAML paths from the root.

Attributes:

Name Type Description
root

Project workspace directory that was created or populated.

project_file

Path to the generated project.yaml.

workflow_file

Path to the generated workflow.yaml.

ExperimentSpec

ExperimentSpec(id: 'str', objective: 'str' = '', scenario: 'str | None' = None, scenarios: 'tuple[str, ...]' = (), metrics: 'tuple[str, ...]' = (), model: 'str | None' = None, artifacts: 'tuple[str, ...]' = (), parameters: 'dict[str, Any]' = )

artifacts = ()

Built-in immutable sequence.

If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.

If the argument is a tuple, the return value is the same object.

metrics = ()

Built-in immutable sequence.

If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.

If the argument is a tuple, the return value is the same object.

objective = ''

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

scenarios = ()

Built-in immutable sequence.

If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.

If the argument is a tuple, the return value is the same object.

ProblemSpec

ProblemSpec(type: 'str', dataset: 'str', environment: 'str', objective: 'str', model: 'dict[str, Any]', scenarios: 'tuple[ScenarioSpec, ...]')

ProjectComponents

Named components a stage script binds once from a project's contracts.

Attributes:

Name Type Description
script

The ProjectScript the components were bound from.

feeder_spec

The declared RadialFeederSpec (sourceNetwork input), or None if the project declares none.

load_profiles

The generated load-profile frame (loadGeneration input), or None if the project declares none.

backend

The resolved power-flow backend, or None if the project declares none.

surrogate

The resolved surrogate standing in for a full solve. Like backend this is never optional -- a study that declares none gets the registry default -- so it is None only if resolution was skipped entirely.

registered

Explicit-ID components the project registered through the per-role registries, keyed by their role name (backend and surrogate today; the platform's observation_producer / policy roles are declared follow-up surface).

build_feeder()

Construct the network through the SDK builder with the bound backend.

Returns:

Type Description
Any

A pandapower-style net built from the bound feeder_spec. The backend is left untouched here (solve is the caller's choice via the bound backend) so a stage that only builds + reports never solves implicitly.

Raises:

Type Description
ValueError

If no feeder spec is bound.

consume(role, component_id)

Return a project-registered component by role and explicit ID.

Parameters:

Name Type Description Default
role str

The per-role registry name. Currently wired: backend. The observation_producer / surrogate / policy roles are declared follow-up surface (their registries do not yet expose a registration_source discriminator).

required
component_id str

The explicit component ID the project registered.

required

Returns:

Type Description
Any

The registered component object (a resolved PowerFlowBackend for the backend role).

Raises:

Type Description
ValueError

If the role or ID is not registered.

to_dict()

Return a JSON-native summary of the bound components.

ProjectScript

Loaded project plus the prepared workspace a stage script writes into.

base_dir

The working directory the runner starts this study's stages in.

Not a root to build paths from: it is the workspace root under pathBase: repo and :attr:root otherwise. Pass :attr:root or :attr:workspace_root, whichever the callee names.

root

The study's directory, the parent of project.yaml.

Use it for anything the study owns. For workspace-level artifacts -- ArtifactLayout, the twin's instances, another study -- use :attr:workspace_root instead.

workspace_root

The Gridalyn workspace enclosing this study.

What ArtifactLayout and the operations/catalog helpers take as root. Discovered from :attr:root, so it does not depend on spec.pathBase. Resolved once per script: discovery can spawn git.

channel_model(**runtime)

Resolve the channel model this study declares, with its declared seed.

A stage whose agents exchange messages calls this rather than building a channel directly, so the channel that carried them is the one provenance.channel_model records.

Parameters:

Name Type Description Default
**runtime Any

Parameters known only when the stage runs -- the endpoints a fixed_outage channel silences -- merged over the declared ones. The seed is not among them: it comes from spec.simulation.seeds.

required

Returns:

Type Description
Any

A ChannelModel ready to transmit.

Raises:

Type Description
ValueError

seed is passed at run time, or the model cannot be built from the declared and runtime parameters.

channel_model_id()

Return the channel model ID this study declares in spec.simulation.

file_reference(path)

Return a provenance record for a file, relative to the project root.

input(key)

Return one named mapping from spec.inputs.

load_demand_response_program(input_key='drProgram')

Return the demand-response program declared in spec.inputs.

load_project_module(relative)

Import a project-relative module by dotted path.

Imports e.g. "scripts.config" resolved under the project root, without sys.path mutation or Path(__file__).parents[N] boilerplate. Repeated calls return the cached module.

Parameters:

Name Type Description Default
relative str

Dotted project-relative module path (e.g. "scripts.config").

required

Returns:

Type Description
module

The imported module.

Raises:

Type Description
ValueError

If relative is not a dotted module path.

FileNotFoundError

If the resolved module file does not exist, naming the dotted path and the file looked up.

path(relative)

Resolve a project-relative output path, creating parent directories.

powerflow_backend(**settings)

Resolve the power-flow backend this study declares.

A solving stage calls this instead of pandapower.runpp so that the engine it uses is the one provenance.powerflow_backend.backend_id records. Resolution is strict by design: naming an unavailable backend raises MissingCapabilityError at this call rather than degrading to a different solver, because a silent downgrade changes solved values while leaving every governed artifact unchanged.

Parameters:

Name Type Description Default
**settings Any

Solver keywords overriding the backend's declared settings for this instance.

required

Returns:

Type Description
Any

A PowerFlowBackend whose solve(net, **kwargs) is the single place this stage may solve.

powerflow_backend_id()

Return the backend ID this study declares in spec.simulation.

read_json(relative)

Read a project-relative JSON file and return the parsed payload.

Parameters:

Name Type Description Default
relative Path | str

Project-relative path to the JSON file.

required

Returns:

Type Description
Any

The parsed JSON value.

Raises:

Type Description
FileNotFoundError

If the resolved file does not exist, naming the resolved absolute path.

ValueError

If the file is not valid JSON, naming the path.

relative(path)

Render an absolute path the way an artifact should record it.

The inverse of :meth:path. A study artifact that stores where the machine that produced it kept its files cannot reproduce byte-for-byte anywhere else, and a reader diffing two runs across machines sees a difference that looks like a regression and is not one (bd r5j).

Parameters:

Name Type Description Default
path Path | str

A path, normally under this project's outputs/.

required

Returns:

Type Description
str

The POSIX path relative to the project root. A path outside the project is returned unchanged rather than rewritten with .., because an artifact naming something outside its own study is a fact worth seeing rather than hiding.

report_metadata(report_id)

Return ReportMetadata stamped with this project's identity.

resolve_extensions()

Resolve the extensions this study declares and route each to its role.

A stage runs as its own process, so what the runner contributed before the run is not registered here. A stage that builds with a declared extension's contribution -- a semantic capability, say -- calls this first. It is a no-op for a study that declares no extension (bd 4ky.8).

Returns:

Type Description
list[Any]

The resolved extension descriptors, sorted by ID.

Raises:

Type Description
UnknownExtensionError

A declared ID is not installed.

MissingCapabilityError

A declared extension's required capabilities are not importable.

ValueError

A declared extension claims a role that cannot be contributed, or its capability ID is already held by another declaration.

TypeError

A declared extension's factory returns the wrong type for its role.

simulation_seed(stream)

Return one named RNG seed this study declares in spec.simulation.

Parameters:

Name Type Description Default
stream str

Name of the declared stream, e.g. "policy".

required

Returns:

Type Description
int

The declared integer seed, so the value the manifest records is the value this stage actually draws from.

surrogate(**settings)

Resolve the surrogate this study declares.

A stage that substitutes a surrogate for a full solve calls this rather than importing one directly, so the component that answered is the one provenance.surrogate.surrogate_id records. Every registered surrogate carries a stated error bound; resolving through the registry is what keeps that bound attached to the choice.

Parameters:

Name Type Description Default
**settings Any

Settings forwarded to the surrogate factory.

required

Returns:

Type Description
Any

A Surrogate ready to predict.

surrogate_id()

Return the surrogate ID this study declares in spec.simulation.

write_json(relative, payload)

Write deterministic JSON to a project-relative path.

Writes json.dumps(payload, indent=2, sort_keys=True) plus a trailing newline so the bytes are reproducible across runs, then returns the file_reference provenance record for the written file.

Parameters:

Name Type Description Default
relative Path | str

Project-relative output path.

required
payload Mapping[str, Any] | list[Any]

JSON-serialisable payload to write.

required

Returns:

Type Description
dict[str, Any]

The provenance record (path/bytes/sha256) for the file.

write_report(report_id, *, path=None, inputs=None, artifacts=None, summary=None, validation=None, uncertainty=None)

Write a platform report with project metadata pre-filled.

Defaults to outputs/reports/<report_id>.json inside the project.

Parameters:

Name Type Description Default
report_id str

Report identifier, also the default file name.

required
path Path | str | None

Explicit destination, overriding the default.

None
inputs list[dict[str, Any]] | None

Input provenance records.

None
artifacts list[dict[str, Any]] | None

Artifact provenance records.

None
summary dict[str, Any] | None

The stage's headline numbers.

None
validation dict[str, Any] | None

The stage's own pass/fail payload.

None
uncertainty dict[str, Any] | None

Optional intervals qualifying entries of summary, built with build_uncertainty. A stage that samples a distribution should report it here rather than discard it.

None

Returns:

Type Description
dict[str, Any]

The written report payload.

ScenarioSpec

ScenarioSpec(id: 'str', role: 'str', description: 'str' = '', parameters: 'dict[str, Any]' = )

description = ''

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

StudyProject

A loaded study: its identity, contract and the directories it involves.

Attributes:

Name Type Description
root

The study's own directory, the parent of project.yaml. Every path the study declares resolves against it (bd 6ns.2), and it is what to pass wherever a :class:ProjectDir is required.

base_dir

The directory the runner starts stage commands in -- the workspace root under pathBase: repo, root otherwise. It is a working directory, not a root: it equals the workspace root for only some studies, so passing it where a :class:WorkspaceRoot is required is right by coincidence (bd 7rt).

path_base

The spec.pathBase value that chose base_dir.

ValidationReport

ValidationReport(valid: 'bool' = True, errors: 'list[str]' = , warnings: 'list[str]' = , checked_files: 'list[str]' = )

valid = True

bool(x) -> bool

Returns True when the argument x is true, False otherwise. The builtins True and False are the only two instances of the class bool. The class bool is a subclass of the class int, and cannot be subclassed.

WorkflowSpec

WorkflowSpec(name: 'str', path: 'Path', stages: 'tuple[WorkflowStage, ...]')

WorkflowStage

WorkflowStage(id: 'str', command: 'str', needs: 'tuple[str, ...]' = (), inputs: 'tuple[str, ...]' = (), outputs: 'tuple[str, ...]' = ())

inputs = ()

Built-in immutable sequence.

If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.

If the argument is a tuple, the return value is the same object.

needs = ()

Built-in immutable sequence.

If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.

If the argument is a tuple, the return value is the same object.

outputs = ()

Built-in immutable sequence.

If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.

If the argument is a tuple, the return value is the same object.

bind_project_components(script)

Resolve a project's declared components once and return them bound.

Resolves the declared sourceNetwork feeder spec, the loadGeneration profiles and the declared power-flow backend through the ProjectScript typed loaders — never by re-deriving project.yaml literals or paths. A project with none of those declared returns a minimal-but-valid bundle (a stage that only writes reports needs nothing bound).

Absent inputs are optional (bound to None); a declared-but-malformed input is a contract violation and the loader's located ValueError propagates — a silent swallow would mask a typo'd sourceNetwork as "no sourceNetwork declared".

Parameters:

Name Type Description Default
script ProjectScript

The prepared ProjectScript for the running project.

required

Returns:

Type Description
A frozen

class:ProjectComponents with the declared components bound.

Raises:

Type Description
ValueError

If a declared component is present but cannot be resolved (a located error naming the YAML key and available inputs, per the loader contract).

init_project(target, name=None, force=False, template='minimal')

Create a project workspace from a registered template.

list_projects(root='.')

List governed project workspaces under a repository or projects folder.

load_der_dispatch_assets(project_or_path, input_key='derAssets')

Load DER dispatch assets from a project input list.

load_generated_bus_loads_mw(project_or_path, input_key='loadGeneration', *, anchor_loads_mw)

Return a diversified coincident-peak loads_mw snapshot.

Per-bus shares come from the generated profiles; the system total is anchored to sum(anchor_loads_mw) so the declared operating point is preserved.

load_generated_load_multipliers(project_or_path, input_key='loadGeneration')

Build a normalized multiplier series from a loadGeneration input.

Requires the multipliers sub-block (intervals and peakMultiplier); the generated aggregate shape is scaled so its maximum equals the declared peakMultiplier.

load_generated_load_profiles(project_or_path, input_key='loadGeneration')

Generate per-unit load profiles declared in spec.inputs.<input_key>.

Returns the kW DataFrame from :func:gridalyn.assets.datagen.generate_residential_load_profiles. weather defaults to "synthetic" in project context so results are byte-stable across environments.

load_numeric_profile_array(project_or_path, input_key)

Load a numeric project input list as a float numpy array.

load_project(path)

Load a project from either a workspace directory or project.yaml path.

load_prosumer_assets(project_or_path, input_key='prosumerAssets')

Load prosumer PV+battery assets from a project input list.

load_radial_feeder_spec(project_or_path, input_key='sourceNetwork')

Load a RadialFeederSpec from spec.inputs.<input_key>.model.

load_voltage_control_der_spec(project_or_path, input_key='voltageControlDer', feeder=None)

Load a voltage-control DER contract from a project input mapping.

load_workflow(path)

Load a kind: Workflow contract into a :class:WorkflowSpec.

Parameters:

Name Type Description Default
path Path | str

The workflow YAML file.

required

Returns:

Type Description
WorkflowSpec

The parsed workflow, with its stages in declaration order.

Raises:

Type Description
ValueError

If a field in :data:WORKFLOW_REQUIRED_FIELDS is missing or has the wrong shape; the message names the file and the YAML path.

plan_project(project_or_path)

Return workflow stages in execution order.

prepare_project_workspace(root=PosixPath('.'), output_directories=('outputs/data', 'outputs/figures', 'outputs/manifests', 'outputs/operations', 'outputs/reports', 'outputs/cache'))

Create standard output directories for a governed project.

project_input(project_or_path, key)

Return one named mapping from a project spec.inputs contract.

project_regression(path)

Run a project regression baseline when one is configured.

project_script(root=None, headless_matplotlib=True)

Load the surrounding project and prepare its output workspace.

Resolves the project workspace by searching for project.yaml upward from the current directory (and the running script's directory), creates the standard outputs/* tree, points the matplotlib cache inside it, and switches matplotlib to the headless Agg backend.

project_sense_check(path, write=True)

Run objective-specific plausibility checks for a project workspace.

project_status(path, check_artifacts=False)

Return a compact status summary for a project workspace.

project_verify(path, write=True)

Run the agent-friendly project verification ladder.

The ladder combines structural validation, artifact/report status, and objective-specific sense checks into one JSON payload suitable for humans, CI jobs, and coding agents.

project_verify_all(root='.', write=False)

Run project verification for every governed project in a workspace.

run_project_regression(*, project_root, baseline='baselines/results_baseline.json', report='outputs/reports/regression_report.json')

Run a project regression baseline and write the regression report.

run_workflow(project_or_path, dry_run=False, manifest_path=None, echo=False, stages=None)

Run or dry-run a project workflow.

echo streams per-stage progress to stderr. stages restricts the run to the named stages plus their transitive dependencies.

validate_project(path, check_artifacts=False)

Validate a project workspace or project.yaml file.

gridalyn.interfaces

User and system interface facade for CLI, reports, dashboard, and graphs.

GridPlotter

Handles the visualization of power grid networks.

This class provides a suite of methods for creating interactive, geographic visualizations of power grid networks using Folium. It is designed to work with the PowerGridGraph class to provide a clear and intuitive representation of the grid, supporting the visualization of building locations, LV, MV, and HV network components, and the overall network topology.

The class can also be used to visualize the results of power flow simulations, such as voltage deviations and line loadings, making it an essential tool for analyzing and understanding the behavior of the power grid.

Attributes:

Name Type Description
power_grid PowerGridGraph

The PowerGridGraph instance to be visualized.

plot_building_and_centroid_graph(plot_lv_edges=True, plot_mv_edges=True, plot_hv_edges=True)

Plots the power grid on a Folium map.

This method visualizes the LV, MV, and HV components of the power grid on an interactive map. It includes options to toggle the visibility of edges for each voltage level.

Parameters:

Name Type Description Default
plot_lv_edges bool

Whether to display the low-voltage edges.

True
plot_mv_edges bool

Whether to display the medium-voltage edges.

True
plot_hv_edges bool

Whether to display the high-voltage edges.

True

Returns:

Type Description
Map

An interactive Folium map of the power grid.

plot_stochastic_bounds(mc_ext_p_mw, mc_raw_p_mw, mc_max_line, resolution_minutes, output_path)

Creates the Stochastic boundary plot matrix for Monte Carlo simulations.

apply_hour_axis(ax, *, start=0.0, end=28.0, step=4.0, label='Time of Day [HH:MM]', fontsize=14)

Apply a common hour-of-day x-axis to a Matplotlib axis.

build_dashboard_catalog(*, scenario_index, powerflow_summary, optional_extensions, root, network_repository=None, projects=None, semantic_dir=None, scenario_assets=None, observations_dir=None)

Build a study-agnostic scenario catalog for the dashboard.

Parameters:

Name Type Description Default
scenario_index dict[str, Any]

Parsed scenario index.

required
powerflow_summary dict[str, Any]

Parsed powerflow summary.

required
optional_extensions dict[str, Path] | None

Onward catalogs to link, by key.

required
root WorkspaceRoot

Workspace root that served paths are expressed relative to.

required
network_repository NetworkModelRepository | None

Base snapshot to describe, or None.

None
projects Iterable[Any] | None

Loaded StudyProject objects whose declared result artifacts should be catalogued. None records an empty list. Studies are described, not embedded: the dashboard reads a project's artifacts as a source, which is why this belongs here -- the catalog is written by the projects layer, which may legitimately see both a twin and a study.

None
semantic_dir Path | None

Directory holding the materialized semantic graph, or None. None publishes no semantic block at all, which is the honest rendering for a twin that has none -- an empty block would claim the ontology was looked for and found empty.

None
scenario_assets Path | None

Path to the scenario asset registry, or None. Contributes the one class population that varies within an artifact, which is what a map can encode as a dimension.

None
observations_dir Path | None

Where this instance's MEASURED observations are read from. Unlike semantic_dir, the resulting block is published whether or not anything is there: "is anything here measured?" is a question every consumer must be able to ask of every instance, and omitting the key would make "no measured data" and "this catalog is too old to say" the same observation. None still publishes the block, naming no directory.

None

Returns:

Type Description
dict[str, Any]

The catalog payload.

build_digital_twin_reports(*, root=PosixPath('.'), out_dir=None, instance='default')

Build the canonical digital-twin reports for a workspace root.

Parameters:

Name Type Description Default
root WorkspaceRoot

Workspace root containing instances/<instance>/digital_twin. Defaults to the current directory, matching ArtifactLayout.

PosixPath('.')
out_dir Path | None

Destination directory for the canonical reports; defaults to <root>/instances/<instance>/digital_twin/reports/canonical.

None
instance str

Named twin instance to report on (default: default).

'default'

Returns:

Type Description
dict[str, Any]

The canonical report manifest, mapping report ids to written paths.

Raises:

Type Description
FileNotFoundError

If root holds no digital-twin artifact tree — the guard that keeps an installed package from reading empty inputs and writing degenerate reports outside a workspace.

dashboard_main(argv=None)

Run the gridalyn dashboard command group.

Dispatches catalog (generate the digital-twin dashboard catalog) and verify (check dashboard consistency). No capability preflight is needed: the modules these commands use (folium, leafmap) are base dependencies, guaranteed by install.

Parameters:

Name Type Description Default
argv list[str] | None

Argument list to parse; defaults to sys.argv[1:].

None

Returns:

Type Description
int

Exit code from the selected subcommand.

digital_twin_main(argv=None)

Run the gridalyn twin command group.

Dispatches build (assemble twin artifacts), clip-buildings, and download-osm-buildings to their handlers.

Parameters:

Name Type Description Default
argv list[str] | None

Argument list to parse; defaults to sys.argv[1:].

None

Returns:

Type Description
int

Exit code from the selected subcommand handler.

dispatch_timeseries_metrics(dispatch, *, time_column='t_hours', energy_columns=None, limit_column='p_limit_trace_mw')

Summarize a dispatch time-series DataFrame or parquet path.

flexibility_main(argv=None)

Run the gridalyn market command group.

Dispatches the flexibility and network-impact commands -- provider registry, network-impact surrogate, locational clearing and the network-impact catalog -- after confirming the optional ops capability is installed.

Parameters:

Name Type Description Default
argv list[str] | None

Argument list to parse; defaults to sys.argv[1:].

None

Returns:

Type Description
int

Exit code from the selected subcommand, or 2 if the ops capability is missing.

format_hour_label(hour)

Format a decimal hour as an HH:MM label.

gridalyn_main(argv=None)

Run the root gridalyn command.

Handles the top-level quickstart, validate and doctor commands, and otherwise delegates to the domain CLI registered in :data:DOMAIN_MODULEStwin, project, market, semantic, dashboard or platform — including their aliases and --help.

Parameters:

Name Type Description Default
argv list[str] | None

Argument list to parse; defaults to sys.argv[1:].

None

Returns:

Type Description
int

Exit code from the selected command or delegated domain CLI.

platform_main(argv=None)

Run the gridalyn platform command group.

Dispatches the governance commands, currently check-artifacts, which checks the Git artifact policy and the minimal demo dataset contract.

Parameters:

Name Type Description Default
argv list[str] | None

Argument list to parse; defaults to sys.argv[1:].

None

Returns:

Type Description
int

Exit code from the selected subcommand handler.

project_main(argv=None)

Run the gridalyn project command group.

Dispatches the project-workspace lifecycle commands — init, validate, plan, run, prepare-workspace, status, regression, sense-check, verify, verify-all and list.

Parameters:

Name Type Description Default
argv list[str] | None

Argument list to parse; defaults to sys.argv[1:].

None

Returns:

Type Description
int

Exit code from the selected subcommand handler.

save_figure_pair(fig, output_path, *, dpi=200, pdf=True, bbox_inches='tight')

Save a figure to PNG and, by default, matching PDF.

semantic_main(argv=None)

Run the gridalyn semantic command group.

Dispatches build (generate the digital-twin semantic graph) and validate (check the graph against the ontology profile). The commands are parquet-only and need no optional extra (the former semantic capability, whose only module was the unconsumed falkordb, was removed 2026-08-07).

Parameters:

Name Type Description Default
argv list[str] | None

Argument list to parse; defaults to sys.argv[1:].

None

Returns:

Type Description
int

Exit code from the selected subcommand.

style_timeseries_axis(ax, *, grid=True, grid_style='--', grid_alpha=0.4, hide_top_right=False)

Apply a restrained default style for project time-series figures.

write_report(path, report, *, root)

Validate and write a canonical report, returning its root-relative path.

Parameters:

Name Type Description Default
path Path

Destination file for the canonical report JSON.

required
report dict[str, Any]

Report payload; must satisfy the platform report contract.

required
root Path

Workspace root used to relativize the returned path.

required

Returns:

Type Description
str

The written report's path relative to root.

Raises:

Type Description
ValueError

If report fails :func:validate_report; the message names the destination file, the contract errors, and the fix.


Not covered here

  • Per-symbol pages. Dedicated pages for each of the ~287 exported targets are a separate piece of work, tracked as a follow-up. This page enables the machinery and covers the facades; exhaustive pages are a project of their own.
  • Private submodules. Anything under a facade that is not in its _LAZY_EXPORTS map is internal and carries no stability promise.
  • Command-line usage. See the CLI Reference.
  • YAML contracts. See the YAML Reference and Report Schemas.