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_load – allocated_demand * demand_to_capacity_rate, in capacity units. - capacity – the resolved capacity_col, echoed back. - allocated_utilisation_ratio – allocated_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. - headroom – capacity - 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_ratio – allocated_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_headroom – headroom - 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.