diff --git a/src/topupopt/data/buildings/dk/bbr.py b/src/topupopt/data/buildings/dk/bbr.py index ca1aa034e842d0e7d251dbc4de92e71bc7908bb5..0fbb541862444fa04eb18398d2df2d398f5c26a4 100644 --- a/src/topupopt/data/buildings/dk/bbr.py +++ b/src/topupopt/data/buildings/dk/bbr.py @@ -511,8 +511,8 @@ list_labels_bbr = [ label_bbr_extra_heating ] -#****************************************************************************** -#****************************************************************************** +# ***************************************************************************** +# ***************************************************************************** def get_bbr_building_data_geodataframe( building_entrance_ids: list, @@ -521,8 +521,8 @@ def get_bbr_building_data_geodataframe( selected_bbr_building_point_labels: list = SELECT_BBR_BDG_POINT_LABELS ) -> Tuple[GeoDataFrame,list]: - #************************************************************************** - #************************************************************************** + # ************************************************************************* + # ************************************************************************* # get data about building entrances @@ -548,8 +548,8 @@ def get_bbr_building_data_geodataframe( index=dict_building_entrances.keys() ) - #************************************************************************** - #************************************************************************** + # ************************************************************************* + # ************************************************************************* # get data about buildings @@ -577,8 +577,8 @@ def get_bbr_building_data_geodataframe( index=dict_buildings.keys() ) - #************************************************************************** - #************************************************************************** + # ************************************************************************* + # ************************************************************************* # get building point data @@ -626,8 +626,8 @@ def get_bbr_building_data_geodataframe( left_index=True, suffixes=(None,"_y")) # adds "_y" to duplicate columns - #************************************************************************** - #************************************************************************** + # ************************************************************************* + # ************************************************************************* # create a geodataframe whose geometry is that of building points @@ -671,17 +671,17 @@ def get_bbr_building_data_geodataframe( return gdf_buildings, list_failures - #************************************************************************** - #************************************************************************** + # ************************************************************************* + # ************************************************************************* -#****************************************************************************** -#****************************************************************************** +# ***************************************************************************** +# ***************************************************************************** def fetch_building_entrance_data(building_entrance_ids: list) -> Tuple[dict, list]: - #************************************************************************** - #************************************************************************** + # ************************************************************************* + # ************************************************************************* # retrieve data about each node identified through OSM @@ -733,21 +733,21 @@ def fetch_building_entrance_data(building_entrance_ids: list) -> Tuple[dict, response.close() - #************************************************************************** - #************************************************************************** + # ************************************************************************* + # ************************************************************************* return dict_building_entrances, list_failures - #************************************************************************** - #************************************************************************** + # ************************************************************************* + # ************************************************************************* -#****************************************************************************** -#****************************************************************************** +# ***************************************************************************** +# ***************************************************************************** def fetch_building_data(building_codes: list): - #************************************************************************** - #************************************************************************** + # ************************************************************************* + # ************************************************************************* # get data about each specific building @@ -781,13 +781,13 @@ def fetch_building_data(building_codes: list): response.close() - #************************************************************************** - #************************************************************************** + # ************************************************************************* + # ************************************************************************* return dict_buildings - #************************************************************************** - #************************************************************************** + # ************************************************************************* + # ************************************************************************* -#****************************************************************************** -#****************************************************************************** \ No newline at end of file +# ***************************************************************************** +# ***************************************************************************** \ No newline at end of file diff --git a/src/topupopt/data/buildings/dk/heat.py b/src/topupopt/data/buildings/dk/heat.py index 47941b589a4ed9ea2ff5cc11bc54779a15550313..29743a1a70c683584050c830685af856d8ca874b 100644 --- a/src/topupopt/data/buildings/dk/heat.py +++ b/src/topupopt/data/buildings/dk/heat.py @@ -1,5 +1,5 @@ -#****************************************************************************** -#****************************************************************************** +# ***************************************************************************** +# ***************************************************************************** import numpy as np @@ -11,8 +11,8 @@ from ...misc.utils import create_profile_using_time_weighted_state from .bbr import label_bbr_entrance_id, label_bbr_housing_area -#****************************************************************************** -#****************************************************************************** +# ***************************************************************************** +# ***************************************************************************** # labels @@ -58,8 +58,8 @@ selected_bbr_building_labels = [ label_osm_entrance_id = 'osak:identifier' -#****************************************************************************** -#****************************************************************************** +# ***************************************************************************** +# ***************************************************************************** def heat_demand_dict_by_building_entrance( gdf_osm: GeoDataFrame, @@ -67,7 +67,7 @@ def heat_demand_dict_by_building_entrance( number_intervals: int, time_interval_durations: list, bdg_specific_demand: dict, - bdg_base_load_avg_ratio: dict, + bdg_min_to_max_ratio: dict, bdg_demand_phase_shift: dict = None, key_osm_entr_id: str = label_osm_entrance_id, key_bbr_entr_id: str = label_bbr_entrance_id, @@ -119,7 +119,7 @@ def heat_demand_dict_by_building_entrance( discrete_sinusoid_matching_integral( bdg_specific_demand[building_index]*area, time_interval_durations=time_interval_durations, - ratio_min_avg=bdg_base_load_avg_ratio[building_index], + min_to_max_ratio=bdg_min_to_max_ratio[building_index], phase_shift_radians=( bdg_demand_phase_shift[building_index] # bdg_demand_phase_shift_amplitude*np.random.random() @@ -142,7 +142,7 @@ def heat_demand_dict_by_building_entrance( ), avg_state=avg_state, time_interval_durations=time_interval_durations, - ratio_min_avg=bdg_base_load_avg_ratio[building_index], + min_to_max_ratio=bdg_min_to_max_ratio[building_index], state_correlates_with_output=state_correlates_with_output ) ) @@ -173,8 +173,8 @@ def heat_demand_dict_by_building_entrance( return demand_dict -#****************************************************************************** -#****************************************************************************** +# ***************************************************************************** +# ***************************************************************************** def total_heating_area( gdf_osm: GeoDataFrame, @@ -206,5 +206,5 @@ def total_heating_area( return area -#****************************************************************************** -#****************************************************************************** \ No newline at end of file +# ***************************************************************************** +# ***************************************************************************** \ No newline at end of file diff --git a/src/topupopt/data/gis/utils.py b/src/topupopt/data/gis/utils.py index 6e7b42f91a699e8349fcec5a670d8ded4f142298..af38c35857c4678e3ed352a1cf751f7796a6cd2e 100644 --- a/src/topupopt/data/gis/utils.py +++ b/src/topupopt/data/gis/utils.py @@ -812,23 +812,32 @@ def simplify_network(network: MultiDiGraph, protected_nodes, max_iterations=dead_end_probing_depth ) - # 2) remove longer parallel edges (tends to create straight paths) + # 2) remove self loops (tends to create straight paths and dead ends) + gis_mod.remove_self_loops(network) + # 3) join segments (can create self-loops) + simplifiable_paths = gis_iden.find_simplifiable_paths( + network, + protected_nodes, + consider_reversed_edges=True + ) + for path in simplifiable_paths: + gis_mod.replace_path(network, path) + # 4) remove longer parallel edges (tends to create straight paths) gis_mod.remove_longer_parallel_edges( network, ignore_edge_directions=remove_opposite_parallel_edges ) - # 3) remove self loops (tends to create straight paths and dead ends) + # 5) remove self loops (tends to create straight paths and dead ends) gis_mod.remove_self_loops(network) - # 4) join segments (can create self-loops) + # 6) join segments (can create self-loops) simplifiable_paths = gis_iden.find_simplifiable_paths( network, - protected_nodes + protected_nodes, + consider_reversed_edges=True ) for path in simplifiable_paths: gis_mod.replace_path(network, path) - # 4) remove self loops (tends to create straight paths and dead ends) - gis_mod.remove_self_loops(network) - # 5) transform roundabouts into crossroads (can create straight paths) + # 7) transform roundabouts into crossroads (can create straight paths) list_roundabout_nodes = gis_iden.find_roundabouts( network, **roundabout_conditions) @@ -836,7 +845,7 @@ def simplify_network(network: MultiDiGraph, network, list_roundabout_nodes ) - # 6) update street count + # 8) update street count if update_street_count_per_node: gis_calc.update_street_count(network) diff --git a/tests/test_data_buildings_dk.py b/tests/test_data_buildings_dk.py new file mode 100644 index 0000000000000000000000000000000000000000..280c990245eaca8f2b3766e9c88d911eccc26168 --- /dev/null +++ b/tests/test_data_buildings_dk.py @@ -0,0 +1,139 @@ +# imports + +# standard + +import math +import random +from numbers import Real +from statistics import mean + +import geopandas as gpd + +# ***************************************************************************** +# ***************************************************************************** + +# local, internal +from src.topupopt.data.gis.utils import read_gdf_file +from src.topupopt.data.buildings.dk import heat +from src.topupopt.data.buildings.dk import bbr + +# ***************************************************************************** +# ***************************************************************************** + +class TestDataBuildingsDK: + + # ************************************************************************* + # ************************************************************************* + + def test_demand_dict(self): + + # heat_demand_dict_by_building_entrance + + osm_data_filename = 'tests/data/gdf_osm.gpkg' + building_data_filename = 'tests/data/gdf_buildings.gpkg' + bdg_gdf_container_columns = ('ejerskaber','koordinater','bygningspunkt') + number_time_intervals = 12 + min_to_max_ratio = 0.1 + intraperiod_time_interval_duration = [ + 30*24*3600 + for i in range(number_time_intervals) + ] + annual_heat_demand_scenario = 1000 + total_area = 1000 + air_temperature_scenario = [10 for i in range(number_time_intervals)] + + gdf_osm = gpd.read_file(osm_data_filename) + gdf_osm.set_index(['element_type', 'osmid'], drop=True, inplace=True) + + gdf_buildings = read_gdf_file( + filename=building_data_filename, + packed_columns=bdg_gdf_container_columns, + index='index' + ) + + # order by state + + heat_demand_dict = heat.heat_demand_dict_by_building_entrance( + gdf_osm=gdf_osm, + gdf_buildings=gdf_buildings, + number_intervals=number_time_intervals, + time_interval_durations=intraperiod_time_interval_duration, + bdg_min_to_max_ratio={ + index: min_to_max_ratio for index in gdf_buildings.index + }, + bdg_specific_demand={ + index: annual_heat_demand_scenario/total_area + for index in gdf_buildings.index + }, + bdg_demand_phase_shift=None, + avg_state=air_temperature_scenario, + state_correlates_with_output=False + ) + assert type(heat_demand_dict) == dict + assert len(heat_demand_dict) == len(gdf_osm) + + # no state preference, use phase shift + + heat_demand_dict2 = heat.heat_demand_dict_by_building_entrance( + gdf_osm=gdf_osm, + gdf_buildings=gdf_buildings, + number_intervals=number_time_intervals, + time_interval_durations=intraperiod_time_interval_duration, + bdg_min_to_max_ratio={ + index: min_to_max_ratio for index in gdf_buildings.index + }, + bdg_specific_demand={ + index: annual_heat_demand_scenario/total_area + for index in gdf_buildings.index + }, + bdg_demand_phase_shift={ + index: 2*math.pi*random.random() for index in gdf_buildings.index + }, + avg_state=None, + state_correlates_with_output=False + ) + assert type(heat_demand_dict2) == dict + assert len(heat_demand_dict2) == len(gdf_osm) + + # total heating area + + heating_area = heat.total_heating_area(gdf_osm, gdf_buildings) + assert isinstance(heating_area, Real) + assert math.isclose(heating_area, 100882, abs_tol=1e-3) + + # ************************************************************************* + # ************************************************************************* + + # def test_bbr(self): + + # # test get_bbr_building_data_geodataframe + + # osm_data_filename = 'tests/data/gdf_osm.gpkg' + + # gdf_osm = gpd.read_file(osm_data_filename) + # gdf_osm.set_index(['element_type', 'osmid'], drop=True, inplace=True) + + # error_raised = False + # try: + # gdf_buildings, drop_list = bbr.get_bbr_building_data_geodataframe( + # list(gdf_osm[heat.label_osm_entrance_id]), + # None, + # None, + # None) + # except UnboundLocalError: + # error_raised = True + # assert error_raised + + # # drop the rows with no data + # gdf_osm = gdf_osm.drop( + # index=[ + # (gdf_osm[ + # gdf_osm[ + # heat.label_osm_entrance_id + # ]==bdg_entrance_id].index)[0] + # for bdg_entrance_id in drop_list + # ] + # ) + +# ***************************************************************************** +# ***************************************************************************** \ No newline at end of file