downscale.proxy
Build proxy (reference-distribution) shares from named proxy frames.
A proxy is the reference distribution used to split a coarse IAM regional value across
country-level members. Proxies are supplied as a name→frame registry
({"population": ..., "gdp": ..., "heating_demand": ..., "cooling_demand": ...}); each proxy
frame is a MultiIndex[(iso2, year)] with a value column (the shape produced by
io.ssp.read_ssp_data and — via :func:build_demand_proxy_from_dd — io.degree_days.read_degree_days).
A sector's weight dict names which proxies to blend and with what weight (e.g.
{"gdp": 0.6, "population": 0.4} for AC, {"heating_demand": 1.0} for heating,
{"cooling_demand": 1.0} for cooling). No proxy is privileged.
The heating/cooling proxies are demand distributions (population × HDD / population × CDD,
built by :func:build_demand_proxy_from_dd) — not raw degree-days — hence the *_demand names: raw
degree-days are an intensity and would over-allocate to small hot/cold countries.
build_demand_proxy_from_dd(degree_days, population, *, value_col='value')
¶
Build an extensive heating/cooling demand proxy from degree-days × population.
Degree-days are an intensity, so splitting demand by raw HDD/CDD over-allocates to small
hot/cold countries. Multiplying by population (an extensive size variable) yields a
demand-distribution proxy — population × HDD for heating, population × CDD for cooling —
which is what belongs in the proxies registry (keyed heating_demand / cooling_demand).
Both frames are MultiIndex[(iso2, year)] with a value column. For each (iso2, year)
in degree_days, population is taken at the nearest available year for that country
(so a single-year degree-day frame pairs with the closest population year). Countries absent
from population are dropped. Returns the same MultiIndex[(iso2, year)] shape.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
degree_days
|
DataFrame
|
The intensive degree-day frame (HDD or CDD). |
required |
population
|
DataFrame
|
The extensive population frame to weight by. |
required |
value_col
|
str
|
The column name in both frames to multiply. |
'value'
|
Returns: pd.DataFrame: The extensive heating/cooling demand proxy frame.
Source code in src/iampypsa/downscale/proxy.py
build_proxy_shares(members, year, sector, proxies, sector_weights, configured_countries=None)
¶
Return {country: share} for the region's members, selected year, and sector.
Shares are a weighted blend of the normalised proxy frames named in the sector's weight dict
sector_weights[sector]. Proxy years are clamped per proxy to that
proxy's last available year (so degree-day frames covering fewer years clamp independently of
population/GDP).
Missing proxy data for configured countries raises; unconfigured countries with missing data get zero weight.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
members
|
list[str]
|
The region's member countries (ISO2). |
required |
year
|
int
|
The scenario year. |
required |
sector
|
str
|
The sector name (e.g. "AC"). |
required |
proxies
|
dict[str, DataFrame]
|
Name→frame registry of proxy frames. |
required |
sector_weights
|
dict
|
Sector→proxy-weight dict. |
required |
configured_countries
|
set[str] | None
|
Countries to include in the shares; if |
None
|
Raises:
ValueError: If a sector requests a proxy that is not present in `proxies
ValueError: If a configured country is missing proxy data for the selected year.
Returns:
dict[str, float]: The normalised shares for the configured countries.
Example:
>>> proxies = {
... "population": pd.DataFrame(
... {"value": [10, 20, 30, 40]},
... index=pd.MultiIndex.from_tuples(
... [("DE", 2020), ("FR", 2020), ("DE", 2030), ("FR", 2030)],
... names=["iso2", "year"],
... ),
... ),
... "gdp": pd.DataFrame(
... {"value": [100, 200, 300, 400]},
... index=pd.MultiIndex.from_tuples(
... [("DE", 2020), ("FR", 2020), ("DE", 2030), ("FR", 2030)],
... names=["iso2", "year"],
... ),
... ),
... }
>>> sector_weights = {"AC": {"population": 0.4, "gdp": 0.6}}"
Source code in src/iampypsa/downscale/proxy.py
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | |
build_ssp_shares(members, year, sector, pop_data, gdp_data, sector_weights, configured_countries=None)
¶
Deprecated thin shim over :func:build_proxy_shares for the population/GDP-only case.
Prefer calling build_proxy_shares with an explicit proxies registry; this wrapper
exists so pre-registry callers keep working.
Source code in src/iampypsa/downscale/proxy.py
normalise(s)
¶
Normalise to sum 1; return uniform shares if the total is non-positive.