system_assignation/scripts/random_assignation.py

167 lines
7.0 KiB
Python

"""
This project aims to assign energy systems archetype names to Montreal buildings.
The random assignation is based on statistical information extracted from different sources, being:
- For residential buildings:
- SHEU 2015: https://oee.nrcan.gc.ca/corporate/statistics/neud/dpa/menus/sheu/2015/tables.cfm
- For non-residential buildings:
- Montreal dataportal: https://dataportalforcities.org/north-america/canada/quebec/montreal
- https://www.eia.gov/consumption/commercial/data/2018/
"""
import glob
import json
import random
from pathlib import Path
from hub.city_model_structure.building import Building
from hub.city_model_structure.city import City
import hub.helpers.constants as cte
energy_systems_format = 'montreal_custom'
# parameters:
residential_systems_percentage = {'system 1 gas': 44,
'system 1 electricity': 6,
'system 2 gas': 0,
'system 2 electricity': 0,
'system 3 and 4 gas': 0,
'system 3 and 4 electricity': 0,
'system 5 gas': 0,
'system 5 electricity': 0,
'system 6 gas': 0,
'system 6 electricity': 0,
'system 8 gas': 44,
'system 8 electricity': 6}
residential_new_systems_percentage = {'PV+ASHP+GasBoiler+TES': 100,
'PV+ASHP+ElectricBoiler+TES': 0,
'PV+GSHP+GasBoiler+TES': 0,
'PV+GSHP+ElectricBoiler+TES': 0,
'PV+WSHP+GasBoiler+TES': 0,
'PV+WSHP+ElectricBoiler+TES': 0}
non_residential_systems_percentage = {'system 1 gas': 0,
'system 1 electricity': 0,
'system 2 gas': 0,
'system 2 electricity': 0,
'system 3 and 4 gas': 39,
'system 3 and 4 electricity': 36,
'system 5 gas': 0,
'system 5 electricity': 0,
'system 6 gas': 13,
'system 6 electricity': 12,
'system 8 gas': 0,
'system 8 electricity': 0}
def _retrieve_buildings(path, year_of_construction_field=None,
function_field=None, function_to_hub=None, aliases_field=None):
_buildings = []
with open(path, 'r', encoding='utf8') as json_file:
_geojson = json.loads(json_file.read())
for feature in _geojson['features']:
_building = {}
year_of_construction = None
if year_of_construction_field is not None:
year_of_construction = int(feature['properties'][year_of_construction_field])
function = None
if function_field is not None:
function = feature['properties'][function_field]
if function_to_hub is not None:
# use the transformation dictionary to retrieve the proper function
if function in function_to_hub:
function = function_to_hub[function]
building_name = ''
building_aliases = []
if 'id' in feature:
building_name = feature['id']
if aliases_field is not None:
for alias_field in aliases_field:
building_aliases.append(feature['properties'][alias_field])
_building['year_of_construction'] = year_of_construction
_building['function'] = function
_building['building_name'] = building_name
_building['building_aliases'] = building_aliases
_buildings.append(_building)
return _buildings
def call_random(_buildings: [Building], _systems_percentage):
_buildings_with_systems = []
_systems_distribution = []
_selected_buildings = list(range(0, len(_buildings)))
random.shuffle(_selected_buildings)
total = 0
maximum = 0
add_to = 0
for _system in _systems_percentage:
if _systems_percentage[_system] > 0:
number_of_buildings = round(_systems_percentage[_system] / 100 * len(_selected_buildings))
_systems_distribution.append({'system': _system, 'number': _systems_percentage[_system],
'number_of_buildings': number_of_buildings})
if number_of_buildings > maximum:
maximum = number_of_buildings
add_to = len(_systems_distribution) - 1
total += number_of_buildings
missing = 0
if total != len(_selected_buildings):
missing = len(_selected_buildings) - total
if missing != 0:
_systems_distribution[add_to]['number_of_buildings'] += missing
_position = 0
for case in _systems_distribution:
for i in range(0, case['number_of_buildings']):
_buildings[_selected_buildings[_position]].energy_systems_archetype_name = case['system']
_position += 1
return _buildings
# try:
# print('[simulation start]')
# input_path = Path('').resolve()
# output_path = Path('').resolve()
# files = glob.glob(str(input_path / '*'))
# processed_files = glob.glob(str(output_path / '*'))
#
# files_to_skip = []
#
# # keep track of processed pickles, so we don't process them again
# for processed_file in processed_files:
# files_to_skip.append(Path(processed_file).resolve().stem)
#
# for file in files:
# if Path(file).stem not in files_to_skip:
# city = City.load(file)
# available_systems = residential_systems_percentage.keys()
# residential_buildings = []
# non_residential_buildings = []
# for building in city.buildings:
# if building.function == cte.RESIDENTIAL:
# residential_buildings.append(building)
# else:
# non_residential_buildings.append(building)
# buildings_with_systems = _call_random(residential_buildings, available_systems, residential_systems_percentage)
# buildings_with_systems.extend(_call_random(non_residential_buildings, available_systems,
# non_residential_systems_percentage))
# file_path = (output_path / f'{Path(file).stem}.pickle').resolve()
# city.save(file_path)
# print(f'[{file_path} completed]')
#
# else:
# print(f"{Path(file)} already processed - skipping")
#
# except Exception as ex:
# print(ex)
# print('error: ', ex)
# print('[simulation abort]')
####My Randomization
# num_buildings = len(city.buildings)
# energy_systems = []
# for _ in range(num_buildings):
# system_archetype = random.choices(
# list(random_assignation.residential_systems_percentage.keys()),
# weights=list(random_assignation.residential_systems_percentage.values())
# )[0]
# energy_systems.append(system_archetype)
# for building, energy_system in zip(city.buildings, energy_systems):
# building.energy_systems_archetype_name = energy_system