site_capacity_summary

site.SiteSolutionSet.site_capacity_summary(
    capacity_col=None,
    demand_to_capacity_rate=1.0,
    sort_by=None,
    solution_rank=1,
    site_names=None,
    site_indices=None,
    matrix=None,
    demand=None,
)

Per-site comparison of a chosen solution’s allocated demand against registered capacity: does each selected site have room for the demand it is closest to?

Builds directly on site_allocation_summary(by="demand") – this is “does the allocation fit?”, where that method answers “who gets allocated where?”. This is a diagnostic only: it does not feed back into solve(), which still has no capacitated search strategy (capacitated=True raises NotImplementedError).

Parameters

Name Type Description Default
capacity_col str Column in candidate_sites giving each site’s capacity, in whatever unit the caller’s capacity is measured in (e.g. appointments/week). Defaults to the capacity_col registered via add_sites(); passing one here overrides it for this call only, so the same solution can be scored under a different capacity definition, mirroring two_step_floating_catchment’s call-time supply_col. Raises if neither is available. None
demand_to_capacity_rate float Converts allocated demand into capacity units, e.g. 5.2 appointments consumed per unit of demand per year. Demand (e.g. population) and capacity (e.g. appointment slots) are usually in different units, so a raw demand-over-capacity ratio is meaningless without this. Must be a positive real number – this is deliberately a single scalar applied uniformly to every site and region; it cannot yet vary by region (e.g. by age structure or deprivation), which would systematically understate load in demographics with higher real usage rates. 1.0
sort_by str None
solution_rank int 1
site_names list None
site_indices list Solution selection, as in site_allocation_summary. Priority is site_indices > site_names > sort_by/solution_rank. None
matrix str Label of a secondary travel matrix registered via add_secondary_travel_matrix(). Passed through to site_allocation_summary(); capacity itself is a property of the site, not the matrix, so it is unaffected. None
demand str Label of a secondary demand scenario registered via add_secondary_demand(). Passed through to site_allocation_summary(). None

Returns

Name Type Description
pandas.DataFrame One row per site in the chosen solution, indexed by site name (“site”) in canonical site-index order (not sorted – use e.g. .sort_values("allocated_utilisation_ratio", ascending=False) to rank sites by pressure). Columns: - n_regions, allocated_demand – as in site_allocation_summary(). - allocated_loadallocated_demand * demand_to_capacity_rate, in capacity units. - capacity – the resolved capacity_col, echoed back. - allocated_utilisation_ratioallocated_load / capacity. 1.0 means exactly full; values above 1.0 are genuinely over capacity and are not clipped. Present only if current_load_col or utilisation_col was registered via add_sites(): - current_load – present iff current_load_col was registered; the raw registered value, echoed back. - baseline_utilisation_ratio – present iff utilisation_col was registered; the raw registered ratio, echoed back. - headroomcapacity - current_load on the raw-counts path, or capacity * (1 - baseline_utilisation_ratio) on the precomputed-ratio path. Present whenever either input above is present: unlike site_utilisation_summary(), capacity is mandatory here, so the ratio path can always derive it. - incremental_headroom_ratioallocated_load / headroom. Not clipped; a negative value means the site is already over capacity today, so no allocation is absorbable at all – see residual_headroom for a more readable version of that case. - residual_headroomheadroom - allocated_load. Negative means a shortfall in capacity units.

Raises

Name Type Description
ValueError If no capacity_col is available (neither passed nor registered), if the resolved capacity column is not found, is non-numeric, or has a negative value for a selected site, if demand_to_capacity_rate is not a positive real number, or if no demand data is registered.
KeyError If a selected site is missing from candidate_sites.

Notes

allocated_utilisation_ratio and incremental_headroom_ratio encode contradictory assumptions about what the allocated demand represents, and only one is usually right for a given study. allocated_utilisation_ratio assumes the allocated demand replaces today’s activity entirely – the whole-network reallocation that solve() actually models, where every region is served by its closest selected site. incremental_headroom_ratio assumes the allocated demand lands on top of today’s activity – e.g. a new service line delivered from existing sites, where the modelled cohort is additional to current caseload. Which one applies depends on what the study is asking, not on whether current_load_col/utilisation_col happened to be registered – so read the Notes above before trusting either number, and don’t assume the mere presence of incremental_headroom_ratio means it is the metric to use.

A zero-allocation site (see site_allocation_summary’s Notes) gets an explicit row with allocated_demand=0, allocated_load=0 and allocated_utilisation_ratio=0.0 – genuinely measured and idle, not “not measured”.

Capacity of 0 with a nonzero allocation gives inf, not a clipped or coerced value – infinitely over capacity is the honest answer. Capacity of 0 with zero allocation gives NaN (0/0), a known ambiguity between “no capacity” and “undefined”. NaN capacity for a site (only reachable when capacity_col allows missing values, unlike add_sites(capacity_col=...) which does not) NaN’s every ratio for that site and raises a UserWarning naming it, rather than silently reading as 0.0 (“measured, and empty”).

Unreachable demand locations (add_travel_matrix(allow_missing= True)) are excluded from site_allocation_summary()’s allocation entirely, so allocated_demand – and therefore every ratio here – understates true load for every site, with no visible sum- to-less-than-1.0 tell the way proportion has. A UserWarning is raised whenever the selected solution has regions_unreachable > 0, naming the count, so this doesn’t pass silently.

If a call-time capacity_col differs from the one registered via add_sites(), headroom is computed from the call-time capacity on both the raw-counts and precomputed-ratio paths, so it can differ from site_utilisation_summary()’s own headroom for the same site.

Back to top