Skip to content

fluxopt.stats

Derived statistics from optimization results.

Computes post-processing quantities that require ModelData (dt, weights) — energy totals, effect contributions, solver metadata.

Classes:

Name Description
StatsAccessor

Post-processing statistics for a solved optimization result.

StatsAccessor

StatsAccessor(result: Result)

Post-processing statistics for a solved optimization result.

Accessed via result.stats.

Parameters:

Name Type Description Default

result

Result

Solved Result.

required

Attributes:

Name Type Description
flow_hours DataArray

Energy per flow per timestep: P_{f,t} * dt_t.

total_flow_hours DataArray

Total energy per flow over the horizon, weighted.

carrier_balance DataArray

Each flow's signed contribution to its carrier — (flow, time).

effect_contributions_direct Dataset

Per-contributor effect breakdown without cross-effect propagation.

effect_contributions Dataset

Per-contributor effect breakdown with cross-effects propagated.

resolved_sizes DataArray

Per-flow size resolved from declared or optimized values.

total_duration DataArray

Weighted length of the modeled horizon: Σ_t dt_t · w_t.

capacity_factor DataArray

Mean utilization per flow: Σ(P·dt·w) / (size · Σ(dt·w)).

resolved_capacities DataArray

Per-storage energy capacity resolved from declared or optimized values.

relative_mean_level DataArray

Mean fractional charge level per storage: ⟨E⟩ / capacity.

summary Dataset

Headline KPIs as a named namespace.

Source code in src/fluxopt/stats.py
def __init__(self, result: Result) -> None:
    self._result = result

flow_hours cached property

flow_hours: DataArray

Energy per flow per timestep: P_{f,t} * dt_t.

Returns:

Type Description
DataArray

DataArray (flow, time) in energy units (e.g. MWh).

total_flow_hours cached property

total_flow_hours: DataArray

Total energy per flow over the horizon, weighted.

Returns:

Type Description
DataArray

DataArray (flow,) — weighted sum of flow_hours over time.

carrier_balance cached property

carrier_balance: DataArray

Each flow's signed contribution to its carrier — (flow, time).

Positive produces into the carrier, negative consumes from it. The carrier a flow belongs to rides along as a coordinate rather than as an axis: a flow is on exactly one, so an axis would be mostly holes. Group by it to get the balance itself, which the model holds at zero::

balance = result.stats.carrier_balance
balance.groupby('carrier').sum()

effect_contributions_direct cached property

effect_contributions_direct: Dataset

Per-contributor effect breakdown without cross-effect propagation.

Each contributor carries only effects it directly emits — contribution_from chains are ignored. Useful for attributing physical quantities (raw CO2, say) without conflating them with priced-in monetary ones.

Derived from :attr:effect_contributions by undoing the fold the binder applied — (I - C) . charged — which is a forward multiply, so the two views cannot disagree about anything but floating point.

Returns:

Type Description
Dataset

Dataset with temporal, lump, and total DataArrays.

effect_contributions cached property

effect_contributions: Dataset

Per-contributor effect breakdown with cross-effects propagated.

Decomposes effect totals into per-contributor parts on a unified contributor dimension (flow IDs + storage IDs)::

contrib = result.stats.effect_contributions
contrib['temporal']  # (contributor, effect, time)
contrib['lump']  # (contributor, effect)
contrib['total']  # (contributor, effect) — temporal sum + lump

Cross-effects (CO2 into cost via Effect.contribution_from) are already carried: the coefficients bound to the program hold the Leontief inverse, so each contributor is charged the full priced-in cost by the same expressions the ledger sums.

Returns:

Type Description
Dataset

Dataset with temporal, lump, and total DataArrays.

Raises:

Type Description
ValueError

If the solve did not record a breakdown. It is read off the model's named expressions at solve time and cannot be recovered from the solution alone.

resolved_sizes cached property

resolved_sizes: DataArray

Per-flow size resolved from declared or optimized values.

Unlike :attr:Result.sizes (optimized/invested flows only), this carries every flow — fixed sizes as declared, invested sizes from the solution, and NaN for unsized flows.

Named resolved_* rather than installed_* on purpose: advanced multi-period investment (#88 — cumulative builds, early retirement) will give "installed capacity" a precise per-period meaning (cap[t] = cap[t-1] + cap_new[t] - cap_retired[t]). This stays the plainer "the size value resolved for each flow" so it doesn't collide with that future modeling term. The computation already keys off flow--size (the solver's per-period in-place capacity), so it remains correct when #88 lands; only the value, not the API, changes.

Returns:

Type Description
DataArray

DataArray (flow,) in power units (e.g. MW).

total_duration cached property

total_duration: DataArray

Weighted length of the modeled horizon: Σ_t dt_t · w_t.

The reference window for utilization metrics. Full load hours, if wanted, are capacity_factor * total_duration.

Returns:

Type Description
DataArray

Scalar DataArray in hours.

capacity_factor cached property

capacity_factor: DataArray

Mean utilization per flow: Σ(P·dt·w) / (size · Σ(dt·w)).

Dimensionless in [0, 1] — energy delivered relative to running at full size over the whole weighted horizon. Unlike full load hours, the weighted duration cancels, so it is independent of horizon length and weight convention, and a per-period value needs no period weighting. NaN where the size is unknown (unsized flows) or zero.

Returns:

Type Description
DataArray

DataArray (flow[, period]) — fraction of rated capacity used.

resolved_capacities cached property

resolved_capacities: DataArray

Per-storage energy capacity resolved from declared or optimized values.

Storage analogue of :attr:resolved_sizes (see its note on the resolved_* naming vs #88's future "installed capacity"). Empty when the model has no storages.

Returns:

Type Description
DataArray

DataArray (storage,) in energy units (e.g. MWh).

relative_mean_level cached property

relative_mean_level: DataArray

Mean fractional charge level per storage: ⟨E⟩ / capacity.

Time-mean level (weighted by dt·w) over the reservoir capacity — the storage analogue of :attr:capacity_factor, and the running-average sibling of the relative_level_min / relative_level_max bounds. Dimensionless in [0, 1] and horizon-independent. NaN where capacity is unknown or zero. Empty when the model has no storages.

Returns:

Type Description
DataArray

DataArray (storage[, period]) — mean fill fraction.

summary cached property

summary: Dataset

Headline KPIs as a named namespace.

Composes existing accessors — :attr:Result.objective, :attr:Result.effect_totals, :attr:total_duration, :attr:resolved_sizes, :attr:total_flow_hours, :attr:capacity_factor, and (when the model has storages) :attr:resolved_capacities and :attr:relative_mean_level — into one Dataset. The variables live on different dimensions (effect vs flow vs storage), so access them by name: this is a KPI namespace, not a flat table, and to_dataframe() would broadcast the unrelated axes together.

Returns:

Type Description
Dataset

Dataset with objective, effect_totals, total_duration,

Dataset

size, total_flow_hours, capacity_factor, and — with

Dataset

storages — capacity and relative_mean_level.