99
1010import datetime as dt
1111import logging
12+ import warnings
1213from collections import namedtuple
1314from operator import itemgetter
1415from pathlib import Path
15- from typing import TYPE_CHECKING
16+ from typing import TYPE_CHECKING , Literal
1617
1718import geopandas as gpd
1819import numpy as np
4344logger = logging .getLogger (__name__ )
4445
4546if TYPE_CHECKING :
46- from typing import Literal
47-
4847 from atlite .resource import TurbineConfig
4948
5049
50+ def _aggregate_time (da : xr .DataArray , method : str | None ) -> xr .DataArray :
51+ if method == "sum" :
52+ return da .sum ("time" , keep_attrs = True )
53+ elif method == "mean" :
54+ return da .mean ("time" , keep_attrs = True )
55+ return da
56+
57+
5158def convert_and_aggregate (
5259 cutout ,
5360 convert_func ,
@@ -58,6 +65,7 @@ def convert_and_aggregate(
5865 shapes_crs = 4326 ,
5966 per_unit = False ,
6067 return_capacity = False ,
68+ aggregate_time : Literal ["sum" , "mean" , "legacy" ] | None = "legacy" ,
6169 capacity_factor = False ,
6270 capacity_factor_timeseries = False ,
6371 show_progress = False ,
@@ -93,12 +101,18 @@ def convert_and_aggregate(
93101 return_capacity : boolean
94102 Additionally returns the installed capacity at each bus corresponding
95103 to ``layout`` (defaults to False).
104+ aggregate_time : "sum", "mean", "legacy", or None
105+ Controls temporal aggregation of results. ``"sum"`` sums over time,
106+ ``"mean"`` averages over time, ``None`` returns full timeseries.
107+ ``"legacy"`` (default) preserves historical behavior: time-summed
108+ without spatial aggregation and full timeseries with spatial
109+ aggregation; this option is deprecated and will be removed in a
110+ future release. Replaces the deprecated ``capacity_factor`` and
111+ ``capacity_factor_timeseries`` parameters.
96112 capacity_factor : boolean
97- If True, the static capacity factor of the chosen resource for each
98- grid cell is computed.
113+ Deprecated. Use ``aggregate_time="mean"`` instead.
99114 capacity_factor_timeseries : boolean
100- If True, the capacity factor time series of the chosen resource for
101- each grid cell is computed.
115+ Deprecated. Use ``aggregate_time=None`` instead (which is the default).
102116 show_progress : boolean, default False
103117 Whether to show a progress bar.
104118 dask_kwargs : dict, default {}
@@ -116,17 +130,21 @@ def convert_and_aggregate(
116130
117131 **With aggregation** (``matrix``, ``shapes``, or ``layout`` given):
118132 Time-series of renewable generation aggregated to buses, with
119- dimensions ``(bus, time)``.
133+ dimensions ``(bus, time)``. If ``aggregate_time`` is set, the time
134+ dimension is reduced accordingly.
120135
121136 **Without aggregation** (none of the above given):
122137
123- - ``capacity_factor_timeseries=True``: per-cell capacity factor
124- time series with dimensions ``(time, y, x)`` in p.u. Individual
125- locations can be extracted with
126- ``result.sel(x=lon, y=lat, method="nearest")``.
127- - ``capacity_factor=True``: time-averaged capacity factor per cell
128- with dimensions ``(y, x)`` in p.u.
129- - Otherwise: total energy sum per cell with dimensions ``(y, x)``.
138+ - ``aggregate_time=None``: per-cell timeseries ``(time, y, x)``.
139+ - ``aggregate_time="mean"``: time-averaged per cell ``(y, x)``.
140+ - ``aggregate_time="sum"``: time-summed per cell ``(y, x)``.
141+
142+ Legacy behavior (deprecated):
143+
144+ - ``aggregate_time="legacy"``: historical context-dependent default.
145+ - ``capacity_factor_timeseries=True``: equivalent to
146+ ``aggregate_time=None``.
147+ - ``capacity_factor=True``: equivalent to ``aggregate_time="mean"``.
130148
131149 units : xr.DataArray (optional)
132150 The installed units per bus in MW corresponding to ``layout``
@@ -138,6 +156,42 @@ def convert_and_aggregate(
138156 pv : Generate solar PV generation time-series.
139157
140158 """
159+ if aggregate_time not in ("sum" , "mean" , "legacy" , None ):
160+ raise ValueError (
161+ f"aggregate_time must be 'sum', 'mean', 'legacy', or None, "
162+ f"got { aggregate_time !r} "
163+ )
164+
165+ if aggregate_time == "legacy" :
166+ warnings .warn (
167+ "aggregate_time='legacy' is deprecated and will be removed in a "
168+ "future release. Pass 'sum', 'mean', or None explicitly." ,
169+ FutureWarning ,
170+ stacklevel = 2 ,
171+ )
172+
173+ if capacity_factor or capacity_factor_timeseries :
174+ if aggregate_time != "legacy" :
175+ raise ValueError (
176+ "Cannot use 'aggregate_time' together with deprecated "
177+ "'capacity_factor' or 'capacity_factor_timeseries'."
178+ )
179+ if capacity_factor :
180+ warnings .warn (
181+ "capacity_factor is deprecated. Use aggregate_time='mean' instead." ,
182+ FutureWarning ,
183+ stacklevel = 2 ,
184+ )
185+ aggregate_time = "mean"
186+ if capacity_factor_timeseries :
187+ warnings .warn (
188+ "capacity_factor_timeseries is deprecated. "
189+ "Use aggregate_time=None instead." ,
190+ FutureWarning ,
191+ stacklevel = 2 ,
192+ )
193+ aggregate_time = None
194+
141195 func_name = convert_func .__name__ .replace ("convert_" , "" )
142196 logger .info (f"Convert and aggregate '{ func_name } '." )
143197 da = convert_func (cutout .data , ** convert_kwds )
@@ -150,16 +204,10 @@ def convert_and_aggregate(
150204 "One of `matrix`, `shapes` and `layout` must be "
151205 "given for `per_unit` or `return_capacity`"
152206 )
153- if capacity_factor or capacity_factor_timeseries :
154- if capacity_factor_timeseries :
155- res = da .rename ("capacity factor" )
156- else :
157- res = da .mean ("time" ).rename ("capacity factor" )
158- res .attrs ["units" ] = "p.u."
159- return maybe_progressbar (res , show_progress , ** dask_kwargs )
160- else :
161- res = da .sum ("time" , keep_attrs = True )
162- return maybe_progressbar (res , show_progress , ** dask_kwargs )
207+
208+ agg = "sum" if aggregate_time == "legacy" else aggregate_time
209+ res = _aggregate_time (da , agg )
210+ return maybe_progressbar (res , show_progress , ** dask_kwargs )
163211
164212 if matrix is not None :
165213 if shapes is not None :
@@ -216,6 +264,9 @@ def convert_and_aggregate(
216264 else :
217265 results .attrs ["units" ] = "MW"
218266
267+ if aggregate_time != "legacy" :
268+ results = _aggregate_time (results , aggregate_time )
269+
219270 if return_capacity :
220271 return maybe_progressbar (results , show_progress , ** dask_kwargs ), capacity
221272 else :
@@ -666,7 +717,7 @@ def wind(
666717 Get per-cell capacity factor time series (no aggregation):
667718
668719 >>> cf = cutout.wind(turbine="Vestas_V112_3MW",
669- ... capacity_factor_timeseries=True )
720+ ... aggregate_time=None )
670721 >>> cf.dims
671722 ('time', 'y', 'x')
672723 >>> location_cf = cf.sel(x=6.9, y=53.1, method="nearest")
@@ -850,7 +901,7 @@ def pv(cutout, panel, orientation, tracking=None, clearsky_model=None, **params)
850901 Get per-cell capacity factor time series (no aggregation):
851902
852903 >>> cf = cutout.pv(panel="CSi", orientation="latitude_optimal",
853- ... capacity_factor_timeseries=True )
904+ ... aggregate_time=None )
854905 >>> location_cf = cf.sel(x=6.9, y=53.1, method="nearest")
855906
856907 References
0 commit comments