Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show pre-results (without need for simulation run) on results page #82

Merged
merged 25 commits into from
Apr 30, 2024
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
93aec90
Fix detail form fields for floating numbers
henhuy Apr 10, 2024
7187b9a
Enable results menu tab
henhuy Apr 10, 2024
3509e73
Add celery make command
henhuy Apr 10, 2024
8400d03
Enable pre-results in results dropdown
henhuy Apr 12, 2024
5786643
Refactored heat demand 2045 to calculate results from datapackage ins…
henhuy Apr 15, 2024
e5bd00d
Add test for heat demand 2045
henhuy Apr 18, 2024
2ff24d4
Fix heat demand parameter keys
henhuy Apr 18, 2024
063242a
Refactor electricity demand from pre results
henhuy Apr 18, 2024
8794459
Always show results charts
henhuy Apr 18, 2024
79d10e0
Merge branch 'refs/heads/dev' into feature/pre_results
henhuy Apr 23, 2024
017ba52
Merge branch 'dev' into feature/pre_results
nesnoj Apr 23, 2024
11de6f0
Resolve migration conflict
nesnoj Apr 23, 2024
3d0671b
Extend list of pre-results for menu/choropleths
nesnoj Apr 24, 2024
379e47a
User settings are stored in map state; pre-results removed in backend
henhuy Apr 26, 2024
24f9908
Fix region charts to work with user settings
henhuy Apr 26, 2024
1fcf15e
Refactor potential shares calculation
henhuy Apr 29, 2024
70e09e0
Add hidden input for selected wind year
henhuy Apr 30, 2024
654c044
Fix parameter names extraction for settings
henhuy Apr 30, 2024
75c0e74
Fix capacities per municipality in 2045
henhuy Apr 30, 2024
3a83bc8
Fix square capacities per municipality in 2045
henhuy Apr 30, 2024
8cab967
Adapt new calculation of capacities in 2045 for charts
henhuy Apr 30, 2024
619b705
Adapt new calculation of energies in 2045 for choropleths, charts & p…
henhuy Apr 30, 2024
de8cc1c
Adapt wind turbine calculation
henhuy Apr 30, 2024
e80b665
Adapt energy share calculation
henhuy Apr 30, 2024
975cf02
Merge branch 'refs/heads/dev' into feature/pre_results
henhuy Apr 30, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ and this project tries to adhere to [Semantic Versioning](https://semver.org/spe
- Adapt municipality label font size according to zoom level
- update mapengine to v1.4.1

### Changed
- pre results can be shown before simulation has finished

### Fixed
- duplicate loading of JS modules due to missing module support in django staticfile storage
- settlement 200m layer is coupled to settlement layer (de)-activation
Expand Down
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ check_distill_coordinates:
local_env_file:
python merge_local_dotenvs_in_dotenv.py

celery:
redis-server --port 6379 & celery -A config.celery worker -l INFO

update_vendor_assets:
# Note: call this command from the same folder your Makefile is located
# Note: this run only update minor versions.
Expand Down
63 changes: 12 additions & 51 deletions digiplan/map/calculations.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ def energy_shares_2045_region(simulation_id: int) -> pd.DataFrame:
return energy_shares.astype(float).mul(1e2)


def electricity_demand_per_municipality_2045(simulation_id: int) -> pd.DataFrame:
def electricity_demand_per_municipality_2045(pre_result_id: int) -> pd.DataFrame:
"""
Calculate electricity demand per sector per municipality in GWh in 2045.

Expand All @@ -282,33 +282,13 @@ def electricity_demand_per_municipality_2045(simulation_id: int) -> pd.DataFrame
pd.DataFrame
Electricity demand per municipality (index) and sector (column)
"""
results = get_results(
simulation_id,
{
"electricity_demand": electricity_demand,
},
)
demand = results["electricity_demand"][
results["electricity_demand"].index.get_level_values(1).isin(config.SIMULATION_DEMANDS)
]
demand = demand.droplevel([0, 2])
demands_per_sector = datapackage.get_power_demand()
mappings = {
"hh": "ABW-electricity-demand_hh",
"cts": "ABW-electricity-demand_cts",
"ind": "ABW-electricity-demand_ind",
}
demand = demand.reindex(mappings.values())
sector_shares = pd.DataFrame(
{sector: demands_per_sector[sector]["2022"] / demands_per_sector[sector]["2022"].sum() for sector in mappings},
)
demand = sector_shares * demand.values
demand.columns = demand.columns.map(lambda column: config.SIMULATION_DEMANDS[mappings[column]])
demand = demand * 1e-3
return demand.astype(float)
demand = electricity_demand_per_municipality(year=2022)
pre_results = models.PreResults.objects.get(pk=pre_result_id)
shares = [pre_results.parameters[key] / 100 for key in ("s_v_3", "s_v_4", "s_v_5")]
return demand.iloc[:] * shares


def heat_demand_per_municipality() -> pd.DataFrame:
def heat_demand_per_municipality(year: int) -> pd.DataFrame:
"""
Calculate heat demand per sector per municipality in GWh.

Expand All @@ -319,7 +299,7 @@ def heat_demand_per_municipality() -> pd.DataFrame:
"""
demands_raw = datapackage.get_summed_heat_demand_per_municipality()
demands_per_sector = pd.concat(
[distributions["cen"]["2022"] + distributions["dec"]["2022"] for distributions in demands_raw.values()],
[distributions["cen"][str(year)] + distributions["dec"][str(year)] for distributions in demands_raw.values()],
axis=1,
)
demands_per_sector.columns = [
Expand All @@ -330,7 +310,7 @@ def heat_demand_per_municipality() -> pd.DataFrame:
return demands_per_sector.astype(float) * 1e-3


def heat_demand_per_municipality_2045(simulation_id: int) -> pd.DataFrame:
def heat_demand_per_municipality_2045(pre_result_id: int) -> pd.DataFrame:
"""
Calculate heat demand per sector per municipality in GWh in 2045.

Expand All @@ -339,29 +319,10 @@ def heat_demand_per_municipality_2045(simulation_id: int) -> pd.DataFrame:
pd.DataFrame
Heat demand per municipality (index) and sector (column)
"""
results = get_results(
simulation_id,
{
"heat_demand": heat_demand,
},
)
demand = results["heat_demand"]
demand.index = demand.index.map(lambda ind: f"heat-demand-{ind[1].split('_')[2]}")
demand = demand.groupby(level=0).sum()
demands_per_sector = datapackage.get_heat_demand()
mappings = {
"hh": "heat-demand-hh",
"cts": "heat-demand-cts",
"ind": "heat-demand-ind",
}
demand = demand.reindex(mappings.values())
sector_shares = pd.DataFrame(
{sector: demands_per_sector[sector]["2022"] / demands_per_sector[sector]["2022"].sum() for sector in mappings},
)
demand = sector_shares * demand.values
demand.columns = demand.columns.map(lambda column: config.SIMULATION_DEMANDS[mappings[column]])
demand = demand * 1e-3
return demand.astype(float)
demand = heat_demand_per_municipality(year=2022)
pre_results = models.PreResults.objects.get(pk=pre_result_id)
shares = [pre_results.parameters[key] / 100 for key in ("w_v_3", "w_v_4", "w_v_5")]
return demand.iloc[:] * shares


def ghg_reduction(simulation_id: int) -> pd.Series:
Expand Down
15 changes: 11 additions & 4 deletions digiplan/map/charts.py
Original file line number Diff line number Diff line change
Expand Up @@ -834,7 +834,7 @@ class HeatDemandRegionChart(Chart):

def get_chart_data(self) -> None:
"""Calculate capacities for whole region."""
return calculations.heat_demand_per_municipality().sum().round(1)
return calculations.heat_demand_per_municipality(year=2022).sum().round(1)

def get_chart_options(self) -> dict:
"""Overwrite title and unit."""
Expand All @@ -851,7 +851,7 @@ class HeatDemand2045RegionChart(SimulationChart):

def get_chart_data(self) -> None:
"""Calculate capacities for whole region."""
status_quo_data = calculations.heat_demand_per_municipality().sum().round(1)
status_quo_data = calculations.heat_demand_per_municipality(year=2022).sum().round(1)
future_data = calculations.heat_demand_per_municipality_2045(self.simulation_id).sum().astype(float).round(1)
return list(zip(status_quo_data, future_data))

Expand All @@ -873,7 +873,7 @@ def get_chart_data(self) -> None:
"""Calculate capacities for whole region."""
return (
calculations.calculate_capita_for_value(
pd.DataFrame(calculations.heat_demand_per_municipality().sum()).transpose(),
pd.DataFrame(calculations.heat_demand_per_municipality(year=2022).sum()).transpose(),
).sum()
* 1e6
).round(1)
Expand All @@ -895,7 +895,7 @@ def get_chart_data(self) -> pd.DataFrame:
"""Calculate capacities for whole region."""
status_quo_data = (
calculations.calculate_capita_for_value(
pd.DataFrame(calculations.heat_demand_per_municipality().sum()).transpose(),
pd.DataFrame(calculations.heat_demand_per_municipality(year=2022).sum()).transpose(),
).sum()
* 1e6
).round(1)
Expand Down Expand Up @@ -997,6 +997,13 @@ def get_chart_options(self) -> dict:
"batteries_capacity_statusquo_region": BatteriesCapacityRegionChart,
}

PRE_RESULTS = (
"electricity_demand_2045_region",
"electricity_demand_capita_2045_region",
"heat_demand_2045_region",
"heat_demand_capita_2045_region",
)


def create_chart(lookup: str, chart_data: Optional[Any] = None) -> dict:
"""
Expand Down
13 changes: 7 additions & 6 deletions digiplan/map/choropleths.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ def get_values_per_feature(self) -> dict[int, float]: # noqa: D102
class ElectricityDemand2045Choropleth(Choropleth): # noqa: D101
def get_values_per_feature(self) -> dict[int, float]: # noqa: D102
return (
calculations.electricity_demand_per_municipality_2045(self.map_state["simulation_id"]).sum(axis=1).to_dict()
calculations.electricity_demand_per_municipality_2045(self.map_state["pre_result_id"]).sum(axis=1).to_dict()
)


Expand All @@ -223,7 +223,7 @@ class ElectricityDemandCapita2045Choropleth(Choropleth): # noqa: D101
def get_values_per_feature(self) -> dict[int, float]: # noqa: D102
capita_demand = (
calculations.calculate_capita_for_value(
calculations.electricity_demand_per_municipality_2045(self.map_state["simulation_id"]),
calculations.electricity_demand_per_municipality_2045(self.map_state["pre_result_id"]),
).sum(axis=1)
* 1e6
)
Expand All @@ -232,18 +232,19 @@ def get_values_per_feature(self) -> dict[int, float]: # noqa: D102

class HeatDemandChoropleth(Choropleth): # noqa: D101
def get_values_per_feature(self) -> dict[int, float]: # noqa: D102
return calculations.heat_demand_per_municipality().sum(axis=1).to_dict()
return calculations.heat_demand_per_municipality(year=2022).sum(axis=1).to_dict()


class HeatDemand2045Choropleth(Choropleth): # noqa: D101
def get_values_per_feature(self) -> dict[int, float]: # noqa: D102
return calculations.heat_demand_per_municipality_2045(self.map_state["simulation_id"]).sum(axis=1).to_dict()
return calculations.heat_demand_per_municipality_2045(self.map_state["pre_result_id"]).sum(axis=1).to_dict()


class HeatDemandCapitaChoropleth(Choropleth): # noqa: D101
def get_values_per_feature(self) -> dict[int, float]: # noqa: D102
capita_demand = (
calculations.calculate_capita_for_value(calculations.heat_demand_per_municipality().sum(axis=1)) * 1e6
calculations.calculate_capita_for_value(calculations.heat_demand_per_municipality(year=2022).sum(axis=1))
* 1e6
)
return capita_demand.to_dict()

Expand All @@ -252,7 +253,7 @@ class HeatDemandCapita2045Choropleth(Choropleth): # noqa: D101
def get_values_per_feature(self) -> dict[int, float]: # noqa: D102
capita_demand = (
calculations.calculate_capita_for_value(
calculations.heat_demand_per_municipality_2045(self.map_state["simulation_id"]),
calculations.heat_demand_per_municipality_2045(self.map_state["pre_result_id"]),
).sum(axis=1)
* 1e6
)
Expand Down
4 changes: 2 additions & 2 deletions digiplan/map/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from itertools import count
from typing import TYPE_CHECKING

from django.forms import BooleanField, Form, IntegerField, TextInput, renderers
from django.forms import BooleanField, FloatField, Form, TextInput, renderers
from django.shortcuts import reverse
from django.utils.safestring import mark_safe

Expand Down Expand Up @@ -89,7 +89,7 @@ def generate_fields(self, parameters: dict, additional_parameters: dict | None =
charts.merge_dicts(parameters, additional_parameters)
for name, item in parameters.items():
if item["type"] == "slider":
field = IntegerField(
field = FloatField(
label=item["label"],
widget=TextInput(attrs=self.get_field_attrs(name, item)),
help_text=item["tooltip"],
Expand Down
21 changes: 21 additions & 0 deletions digiplan/map/migrations/0045_preresults.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Generated by Django 4.2.11 on 2024-04-12 11:54

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("map", "0044_merge_20240318_1859"),
]

operations = [
migrations.CreateModel(
name="PreResults",
fields=[
("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
("scenario", models.CharField(max_length=255)),
("parameters", models.JSONField()),
],
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Generated by Django 4.2.11 on 2024-04-23 15:29

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
("map", "0045_preresults"),
("map", "0045_regionboundaries"),
]

operations = []
7 changes: 7 additions & 0 deletions digiplan/map/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -708,3 +708,10 @@ class PotentialAreaWindSTP2018EG(StaticRegionModel): # noqa: D101
class PotentialAreaWindSTP2024VR(StaticRegionModel): # noqa: D101
data_file = "potentialarea_wind_stp_2024_vr"
layer = "potentialarea_wind_stp_2024_vr"


class PreResults(models.Model):
"""Model to store pre results ID related to given parameters."""

scenario = models.CharField(max_length=255)
parameters = models.JSONField()
18 changes: 10 additions & 8 deletions digiplan/map/popups.py
Original file line number Diff line number Diff line change
Expand Up @@ -697,7 +697,7 @@ class ElectricityDemand2045Popup(RegionPopup):
title = _("Strombedarf")

def get_detailed_data(self) -> pd.DataFrame: # noqa: D102
return calculations.electricity_demand_per_municipality_2045(self.map_state["simulation_id"])
return calculations.electricity_demand_per_municipality_2045(self.map_state["pre_result_id"])

def get_chart_data(self) -> Iterable:
"""Create capacity chart data for SQ and future scenario."""
Expand Down Expand Up @@ -744,7 +744,7 @@ class ElectricityDemandCapita2045Popup(RegionPopup):

def get_detailed_data(self) -> pd.DataFrame: # noqa: D102
return calculations.calculate_capita_for_value(
calculations.electricity_demand_per_municipality_2045(self.map_state["simulation_id"]),
calculations.electricity_demand_per_municipality_2045(self.map_state["pre_result_id"]),
)

def get_region_value(self) -> float: # noqa: D102
Expand Down Expand Up @@ -777,7 +777,7 @@ class HeatDemandPopup(RegionPopup):
title = _("Wärmebedarf")

def get_detailed_data(self) -> pd.DataFrame: # noqa: D102
return calculations.heat_demand_per_municipality().round(1)
return calculations.heat_demand_per_municipality(year=2022).round(1)

def get_chart_options(self) -> dict:
"""Overwrite title and unit."""
Expand All @@ -794,11 +794,11 @@ class HeatDemand2045Popup(RegionPopup):
title = _("Wärmebedarf")

def get_detailed_data(self) -> pd.DataFrame: # noqa: D102
return calculations.heat_demand_per_municipality_2045(self.map_state["simulation_id"])
return calculations.heat_demand_per_municipality_2045(self.map_state["pre_result_id"])

def get_chart_data(self) -> Iterable:
"""Create capacity chart data for SQ and future scenario."""
status_quo_data = calculations.heat_demand_per_municipality().loc[self.selected_id].round(1)
status_quo_data = calculations.heat_demand_per_municipality(year=2022).loc[self.selected_id].round(1)
future_data = super().get_chart_data().round(1)
return list(zip(status_quo_data, future_data))

Expand All @@ -818,7 +818,9 @@ class HeatDemandCapitaPopup(RegionPopup):
title = _("Wärmebedarf je EinwohnerIn")

def get_detailed_data(self) -> pd.DataFrame: # noqa: D102
return (calculations.calculate_capita_for_value(calculations.heat_demand_per_municipality()) * 1e6).round(1)
return (
calculations.calculate_capita_for_value(calculations.heat_demand_per_municipality(year=2022)) * 1e6
).round(1)

def get_region_value(self) -> float: # noqa: D102
return self.detailed_data.sum(axis=1).mean()
Expand All @@ -839,7 +841,7 @@ class HeatDemandCapita2045Popup(RegionPopup):

def get_detailed_data(self) -> pd.DataFrame: # noqa: D102
return calculations.calculate_capita_for_value(
calculations.heat_demand_per_municipality_2045(self.map_state["simulation_id"]),
calculations.heat_demand_per_municipality_2045(self.map_state["pre_result_id"]),
).mul(1e6)

def get_region_value(self) -> float: # noqa: D102
Expand All @@ -849,7 +851,7 @@ def get_chart_data(self) -> Iterable:
"""Create capacity chart data for SQ and future scenario."""
status_quo_data = (
calculations.calculate_capita_for_value(
calculations.heat_demand_per_municipality(),
calculations.heat_demand_per_municipality(year=2022),
)
.loc[self.selected_id]
.mul(1e6)
Expand Down
1 change: 1 addition & 0 deletions digiplan/map/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@
path("popup/<str:lookup>/<int:region>", views.get_popup, name="popup"),
path("charts", views.get_charts, name="charts"),
path("detail_key_results", views.DetailKeyResultsView.as_view(), name="detail_key_results"),
path("pre_result", views.store_pre_result, name="pre_result"),
]
Loading