From 5158a0790a49c07850b850c71842054fe591f3e2 Mon Sep 17 00:00:00 2001 From: Max Nutz Date: Thu, 26 Mar 2026 13:22:14 +0100 Subject: [PATCH 1/2] add statistics-function and mapping; include test class for function --- .../configs/mapping.default.yaml | 1 + .../statistics_functions.py | 42 +++++++++++++++++ tests/test_statistics_functions.py | 47 +++++++++++++++++++ 3 files changed, 90 insertions(+) diff --git a/pypsa_validation_processing/configs/mapping.default.yaml b/pypsa_validation_processing/configs/mapping.default.yaml index 754603e..7faf62b 100644 --- a/pypsa_validation_processing/configs/mapping.default.yaml +++ b/pypsa_validation_processing/configs/mapping.default.yaml @@ -7,3 +7,4 @@ Final Energy [by Carrier]|Electricity: Final_Energy_by_Carrier__Electricity Final Energy [by Sector]|Transportation: Final_Energy_by_Sector__Transportation +Final Energy [by Sector]|Agriculture: Final_Energy_by_Sector__Agriculture \ No newline at end of file diff --git a/pypsa_validation_processing/statistics_functions.py b/pypsa_validation_processing/statistics_functions.py index 70fc6cf..53e325e 100644 --- a/pypsa_validation_processing/statistics_functions.py +++ b/pypsa_validation_processing/statistics_functions.py @@ -109,3 +109,45 @@ def Final_Energy_by_Sector__Transportation( .sum() ) return res + + +def Final_Energy_by_Sector__Agriculture(n: pypsa.Network) -> pd.Series: + """Extract agriculture-sector final energy from a PyPSA Network. + + Returns the total energy consumed by the transportation sector (excluding + transmission / distribution losses) across the pypsa-network. + + Parameters + ---------- + n : pypsa.Network + PyPSA network to process. + + Returns + ------- + pd.Series + Pandas Series with Multiindex of ``country`` and ``unit`` + + Notes + ----- + Includes carriers ['agriculture electricity','agriculture heat','agriculture machinery electric', + 'agriculture machinery oil'] executed on Load-Components. agriculture machinery oil is also carrier + of Links and Buses, as Demand is assued fixed. _Timeseries of Agriculture demand are assumed + to be constant in PyPSA-EUR._ + """ + carriers = [ + "agriculture electricity", + "agriculture heat", + "agriculture machinery electric", + "agriculture machinery oil", + ] + res = ( + n.statistics.energy_balance( + carrier=carriers, + groupby=["carrier", "unit", "country"], + components="Load", + direction="withdrawal", # for positive values + ) + .groupby(["country", "unit"]) + .sum() + ) + return res diff --git a/tests/test_statistics_functions.py b/tests/test_statistics_functions.py index 89f5803..f559185 100644 --- a/tests/test_statistics_functions.py +++ b/tests/test_statistics_functions.py @@ -7,6 +7,7 @@ from pypsa_validation_processing.statistics_functions import ( Final_Energy_by_Carrier__Electricity, + Final_Energy_by_Sector__Agriculture, Final_Energy_by_Sector__Transportation, ) @@ -103,3 +104,49 @@ def test_multiple_networks(self, mock_network_collection: MockNetworkCollection) assert isinstance(result.index, pd.MultiIndex) assert result.index.names == ["country", "unit"] assert len(result) > 0 + + +# --------------------------------------------------------------------------- +# Tests for Final_Energy_by_Sector__Agriculture +# --------------------------------------------------------------------------- + + +class TestFinalEnergyBySectorAgriculture: + """Test suite for Final_Energy_by_Sector__Agriculture function.""" + + def test_returns_series(self, mock_network: MockPyPSANetwork): + """Test that the function returns a pandas Series.""" + result = Final_Energy_by_Sector__Agriculture(mock_network) + assert isinstance(result, pd.Series) + + def test_has_country_and_unit_multiindex(self, mock_network: MockPyPSANetwork): + """Test that result has MultiIndex with country and unit levels.""" + result = Final_Energy_by_Sector__Agriculture(mock_network) + assert isinstance(result.index, pd.MultiIndex) + assert result.index.names == ["country", "unit"] + + def test_not_empty(self, mock_network: MockPyPSANetwork): + """Test that result is not empty.""" + result = Final_Energy_by_Sector__Agriculture(mock_network) + assert len(result) > 0 + + def test_numeric_values(self, mock_network: MockPyPSANetwork): + """Test that result values are numeric.""" + result = Final_Energy_by_Sector__Agriculture(mock_network) + assert result.dtype in [float, int] or pd.api.types.is_numeric_dtype( + result.dtype + ) + + def test_contains_austria(self, mock_network: MockPyPSANetwork): + """Test that result contains Austria (AT) data.""" + result = Final_Energy_by_Sector__Agriculture(mock_network) + assert "AT" in result.index.get_level_values("country") + + def test_multiple_networks(self, mock_network_collection: MockNetworkCollection): + """Test processing multiple networks from collection.""" + for network in mock_network_collection: + result = Final_Energy_by_Sector__Agriculture(network) + assert isinstance(result, pd.Series) + assert isinstance(result.index, pd.MultiIndex) + assert result.index.names == ["country", "unit"] + assert len(result) > 0 From 21d2f33811b4f3ea2aa4dbecbaed8b9625c9c532 Mon Sep 17 00:00:00 2001 From: max_nutz Date: Thu, 26 Mar 2026 13:53:28 +0100 Subject: [PATCH 2/2] Update pypsa_validation_processing/statistics_functions.py Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> --- pypsa_validation_processing/statistics_functions.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pypsa_validation_processing/statistics_functions.py b/pypsa_validation_processing/statistics_functions.py index 53e325e..e5450ee 100644 --- a/pypsa_validation_processing/statistics_functions.py +++ b/pypsa_validation_processing/statistics_functions.py @@ -130,8 +130,8 @@ def Final_Energy_by_Sector__Agriculture(n: pypsa.Network) -> pd.Series: Notes ----- Includes carriers ['agriculture electricity','agriculture heat','agriculture machinery electric', - 'agriculture machinery oil'] executed on Load-Components. agriculture machinery oil is also carrier - of Links and Buses, as Demand is assued fixed. _Timeseries of Agriculture demand are assumed + 'agriculture machinery oil'] executed on Load-Components. Agriculture machinery oil is also carrier + of Links and Buses, as Demand is assumed fixed. _Time series of Agriculture demand are assumed to be constant in PyPSA-EUR._ """ carriers = [