Utilities
common
ΒΆ
General utility functions for PyPSA.
Classes:
-
UnexpectedErrorβCustom error for unexpected conditions with issue tracker reference.
Functions:
-
as_indexβReturn a pd.Index object from a list-like or scalar object.
-
equalsβCheck if two objects are equal and track the location of differences.
-
list_as_stringβConvert a list to a formatted string.
-
pass_none_if_keyerrorβDecorate functions to pass None if a KeyError or AttributeError is raised.
-
resample_timeseriesβResample a DataFrame with proper handling of numeric and non-numeric columns.
-
expand_seriesβExpand a series to a dataframe quickly.
-
annuityβCalculate the annuity factor for a given discount rate and lifetime.
pypsa.common.UnexpectedError
ΒΆ
UnexpectedError(message: str = '')
Bases: AssertionError
Custom error for unexpected conditions with issue tracker reference.
Parameters:
-
message(str, default:'') βMessage to be displayed.
Examples:
>>> try:
... raise UnexpectedError("This is an unexpected error.")
... except UnexpectedError as e:
... print(str(e))
This is an unexpected error.
Please track this issue in our issue tracker: https://go.pypsa.org/report-bug
pypsa.common.as_index
ΒΆ
as_index(
n: NetworkType,
values: Any,
network_attribute: str,
force_subset: bool = True,
) -> Index
Return a pd.Index object from a list-like or scalar object.
Also checks if the values are a subset of the corresponding attribute of the network object. If values is None, it is also used as the default.
Parameters:
-
n(Network) βNetwork object from which to extract the default values.
-
values(Any) βList-like or scalar object or None.
-
network_attribute(str) βName of the network attribute to be used as the default values. Only used if values is None.
-
force_subset(bool, default:True) βIf True, the values must be a subset of the network attribute. Otherwise this is not checked, by default True.
Returns:
-
pd.Index: values as a pd.Index object.β
Examples:
>>> # Convert list to Index using network snapshots
>>> first_two = list(n.snapshots[:2])
>>> pypsa.common.as_index(n, first_two, 'snapshots')
DatetimeIndex([..., ...], dtype='datetime64[ns]', name='snapshot', freq=None)
>>> # Using None returns all snapshots
>>> pypsa.common.as_index(n, None, 'snapshots')
DatetimeIndex([..., ...], dtype='datetime64[ns]', name='snapshot', freq=None)
pypsa.common.equals
ΒΆ
equals(
a: Any,
b: Any,
ignored_classes: Any = None,
log_mode: str = "silent",
path: str = "",
) -> bool
Check if two objects are equal and track the location of differences.
Parameters:
-
a(Any) βFirst object to compare.
-
b(Any) βSecond object to compare.
-
ignored_classes(Any, default:None) βClasses to ignore during comparison. If None, no classes are ignored.
-
log_mode(str, default:'silent') βControls how differences are reported: - 'silent': No logging, just returns True/False - 'verbose': Prints differences but doesn't raise errors - 'strict': Raises ValueError on first difference
-
path(str, default:'') βCurrent path in the object structure (used for tracking differences).
Raises:
-
ValueErrorβIf log_mode is 'strict' and components are not equal.
Returns:
-
boolβTrue if the objects are equal, False otherwise.
Examples:
>>> # Compare pandas DataFrames
>>> df1 = pd.DataFrame({'a': [1, 2], 'b': [3, 4]})
>>> df2 = pd.DataFrame({'a': [1, 2], 'b': [3, 4]})
>>> pypsa.common.equals(df1, df2)
True
>>> # Compare lists
>>> pypsa.common.equals([1, 2, 3], [1, 2, 4])
False
>>> # Handle NaN values correctly
>>> pypsa.common.equals(np.nan, np.nan)
True
pypsa.common.list_as_string
ΒΆ
list_as_string(
list_: Sequence | dict | set,
prefix: str = "",
style: str = "comma-separated",
) -> str
Convert a list to a formatted string.
Parameters:
-
list_(Sequence) βThe input sequence to be converted.
-
prefix(str, default:'') βString to prepend to each line, by default "".
-
style(('same-line', 'bullet-list'), default:'same-line') βOutput format style, by default "same-line".
Returns:
-
strβFormatted string representation of the input sequence.
Raises:
-
ValueErrorβIf an invalid style is provided.
Examples:
>>> list_as_string(['a', 'b', 'c'])
'a, b, c'
>>> list_as_string(['x', 'y'], prefix=' ')
' x, y'
pypsa.common.pass_none_if_keyerror
ΒΆ
pass_none_if_keyerror(func: Callable) -> Callable
Decorate functions to pass None if a KeyError or AttributeError is raised.
Parameters:
-
func(Callable) βThe function to decorate.
Returns:
-
CallableβThe decorated function.
pypsa.common.resample_timeseries
ΒΆ
resample_timeseries(
df: DataFrame,
freq: str,
numeric_columns: list[str] | None = None,
) -> DataFrame
Resample a DataFrame with proper handling of numeric and non-numeric columns.
Parameters:
-
df(DataFrame) βDataFrame to resample, must have a datetime index
-
freq(str) βFrequency string for resampling (e.g. 'H' for hourly)
-
numeric_columns(list[str] | None, default:None) βList of numeric column names to resample. If None, auto-detected.
Returns:
-
DataFrameβResampled DataFrame with numeric columns aggregated by mean and non-numeric columns forward-filled
Examples:
>>> # Create time series with mixed data types
>>> dates = pd.date_range('2020-01-01', periods=4, freq='15min')
>>> df = pd.DataFrame({
... 'value': [1.0, 2.0, 3.0, 4.0],
... 'label': ['A', 'A', 'B', 'B']
... }, index=dates)
>>> resampled = pypsa.common.resample_timeseries(df, '30min')
>>> resampled['value'].iloc[0] # Mean of first two values
np.float64(1.5)
>>> resampled['label'].iloc[0] # Forward-filled non-numeric
'A'
pypsa.common.expand_series
ΒΆ
expand_series(
ser: Series, columns: Sequence[str]
) -> DataFrame
Expand a series to a dataframe quickly.
Columns are the given series and every single column being the equal to the given series.
Parameters:
-
ser(Series) βInput series to expand.
-
columns(Sequence[str]) βColumn names for the resulting DataFrame.
Returns:
-
DataFrameβDataFrame with all columns containing the same values as the input series.
Examples:
>>> ser = pd.Series([1, 2, 3], index=['a', 'b', 'c'])
>>> df = pypsa.common.expand_series(ser, ['col1', 'col2'])
>>> df
col1 col2
a 1.0 1.0
b 2.0 2.0
c 3.0 3.0
pypsa.common.annuity
ΒΆ
annuity(
r: float | Series, n: int | Series
) -> float | Series
Calculate the annuity factor for a given discount rate and lifetime.
According to formula \(r / (1 - (1 + r)^{-n})\).
Parameters:
-
r(float | Series) βDiscount rate (as a decimal, e.g. 0.05 for 5%).
-
n(int | Series) βLifetime of loan or asset (in years).
Returns:
-
float | SeriesβThe annuity factor.
Examples:
>>> pypsa.common.annuity(0.05, 10) # 5% discount rate over 10 years
0.12950457496545661
geo
ΒΆ
Functionality to help with georeferencing and calculate distances/areas.
Functions:
-
compute_bboxβCompute bounding box for given x, y coordinates.
-
get_projected_area_factorβGet scale of current vs original projection in terms of area.
-
get_projection_from_crsβGet cartopy projection from EPSG code or proj4 string.
-
haversineβCompute the distance in km between two sets of points in long/lat.
-
haversine_ptsβDetermine crow-flies distance between points in a and b.
pypsa.geo.compute_bbox
ΒΆ
compute_bbox(
x: ArrayLike, y: ArrayLike, margin: float = 0
) -> tuple[tuple[float, float], tuple[float, float]]
Compute bounding box for given x, y coordinates.
Also adds a margin around the bounding box, if desired. Defaults to 0.
Parameters:
-
x(array - like) βArrays of x and y coordinates
-
y(array - like) βArrays of x and y coordinates
-
margin(float, default:0) βMargin around the bounding box, by default 0
Returns:
-
tupleβTuple of two tuples, representing the lower left (x1, y1) and upper right (x2, y2) corners of the bounding box
Examples:
>>> x = np.array([1, 2, 3])
>>> y = np.array([4, 5, 6])
>>> compute_bbox(x, y)
((np.int64(1), np.int64(4)), (np.int64(3), np.int64(6)))
>>> # With margin to expand the bounding box
>>> compute_bbox(x, y, margin=0.1)
((..., ...), (..., ...))
pypsa.geo.get_projected_area_factor
ΒΆ
get_projected_area_factor(
ax: GeoAxes, original_crs: int | str = DEFAULT_EPSG
) -> float
Get scale of current vs original projection in terms of area.
The default 'original crs' is assumed to be 4326, which translates to the cartopy default cartopy.crs.PlateCarree()
Examples:
>>> import cartopy.crs as ccrs
>>> import matplotlib.pyplot as plt
>>> fig, ax = plt.subplots(subplot_kw={"projection": ccrs.Mercator()})
>>> ax.set_extent([-10, 10, 40, 60], crs=ccrs.PlateCarree())
>>> area_factor = get_projected_area_factor(ax)
>>> area_factor
np.float64(140056.26937534288)
pypsa.geo.get_projection_from_crs
ΒΆ
get_projection_from_crs(crs: int | str) -> Projection
Get cartopy projection from EPSG code or proj4 string.
If the projection is not found, a warning is issued and the default PlateCarree projection is returned.
Parameters:
-
crs(int | str) βEPSG code or proj4 string
Returns:
-
projection(Projection) βCartopy projection object
Examples:
>>> get_projection_from_crs(4326)
<Projected CRS: +proj=eqc +ellps=WGS84 +a=6378137.0 +lon_0=0.0 +to ...>
Name: unknown
Axis Info [cartesian]:
- E[east]: Easting (unknown)
- N[north]: Northing (unknown)
- h[up]: Ellipsoidal height (metre)
Area of Use:
- undefined
Coordinate Operation:
- name: unknown
- method: Equidistant Cylindrical
Datum: Unknown based on WGS 84 ellipsoid
- Ellipsoid: WGS 84
- Prime Meridian: Greenwich
pypsa.geo.haversine
ΒΆ
haversine(a: ArrayLike, b: ArrayLike) -> ndarray
Compute the distance in km between two sets of points in long/lat.
One dimension of a* should be 2; longitude then latitude. Uses haversine formula.
Parameters:
-
a(N x 2 - array of dtype float) βCoordinates of first point, dimensions (N, 2)
-
b(array-like of at most 2 dimensions) βCoordinates of second point, dimensions (M, 2)
Returns:
-
distance_km(array) β2-dimensional array of distances in km between points in a, b
Examples:
>>> haversine([10.1, 52.6], [[10.8, 52.1], [-34, 56.]])
array([[ 73.15416698, 2836.6707696 ]])
pypsa.geo.haversine_pts
ΒΆ
haversine_pts(a: ArrayLike, b: ArrayLike) -> ndarray
Determine crow-flies distance between points in a and b.
ie. distance[i] = crow-fly-distance between a[i] and b[i]
Parameters:
-
a(N x 2 - array of dtype float) βGeographical coordinates in longitude, latitude ordering
-
b(N x 2 - array of dtype float) βGeographical coordinates in longitude, latitude ordering
Returns:
-
c(N - array of dtype float) βDistance in km
Examples:
>>> a = np.array([[10.1, 52.6], [10.8, 52.1]])
>>> b = np.array([[10.8, 52.1], [-34, 56.]])
>>> haversine_pts(a, b)
array([ 73.15416698, 2903.73511621])