Compare commits
7 Commits
main
...
feature/cm
Author | SHA1 | Date | |
---|---|---|---|
b4f1a2471e | |||
79edd8f6a2 | |||
04214be864 | |||
f6955130be | |||
7cc7221ab8 | |||
0a2ea1061f | |||
a477a2b893 |
1265846
data/cmm_points_function_vintage_surface.csv
Normal file
1265846
data/cmm_points_function_vintage_surface.csv
Normal file
File diff suppressed because it is too large
Load Diff
210241
data/energy_demand_data.csv
Normal file
210241
data/energy_demand_data.csv
Normal file
File diff suppressed because it is too large
Load Diff
56
hub/city_model_structure/simplified_building.py
Normal file
56
hub/city_model_structure/simplified_building.py
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
|
|
||||||
|
class SimplifiedBuilding:
|
||||||
|
"""
|
||||||
|
SimplifiedBuilding class
|
||||||
|
"""
|
||||||
|
def __init__(self, name, centroid=None, postal_code=None, total_floor_area=None, year_of_construction=None, function=None, city=None):
|
||||||
|
self._name = name
|
||||||
|
self._centroid = centroid
|
||||||
|
self._total_floor_area = total_floor_area
|
||||||
|
self._year_of_construction = year_of_construction
|
||||||
|
self._function = function
|
||||||
|
self._postal_code = postal_code
|
||||||
|
self._city = city
|
||||||
|
self._type = 'building'
|
||||||
|
self.heating_demand = []
|
||||||
|
self.cooling_demand = []
|
||||||
|
self.electricity_demand = []
|
||||||
|
self.appliance_demand = []
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
return self._name
|
||||||
|
|
||||||
|
@property
|
||||||
|
def centroid(self):
|
||||||
|
return self._centroid
|
||||||
|
|
||||||
|
@property
|
||||||
|
def postal_code(self):
|
||||||
|
return self._postal_code
|
||||||
|
|
||||||
|
@property
|
||||||
|
def total_floor_area(self):
|
||||||
|
return self._total_floor_area
|
||||||
|
|
||||||
|
@property
|
||||||
|
def year_of_construction(self):
|
||||||
|
return self._year_of_construction
|
||||||
|
|
||||||
|
@property
|
||||||
|
def function(self) -> Union[None, str]:
|
||||||
|
return self._function
|
||||||
|
|
||||||
|
@property
|
||||||
|
def type(self):
|
||||||
|
return self._type
|
||||||
|
|
||||||
|
@property
|
||||||
|
def city(self):
|
||||||
|
return self._city
|
||||||
|
|
||||||
|
@city.setter
|
||||||
|
def city(self, value):
|
||||||
|
self._city = value
|
31
hub/city_model_structure/simplified_city.py
Normal file
31
hub/city_model_structure/simplified_city.py
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
from typing import List
|
||||||
|
from hub.city_model_structure.simplified_building import SimplifiedBuilding
|
||||||
|
|
||||||
|
class SimplifiedCity:
|
||||||
|
"""
|
||||||
|
SimplifiedCity class
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self._name = "Montreal Metropolitan Area"
|
||||||
|
self._buildings = []
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
return self._name
|
||||||
|
|
||||||
|
@name.setter
|
||||||
|
def name(self, value):
|
||||||
|
if value is not None:
|
||||||
|
self._name = str(value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def buildings(self) -> List[SimplifiedBuilding]:
|
||||||
|
return self._buildings
|
||||||
|
|
||||||
|
def add_city_object(self, new_city_object):
|
||||||
|
if new_city_object.type == 'building':
|
||||||
|
self._buildings.append(new_city_object)
|
||||||
|
new_city_object.city = self
|
||||||
|
else:
|
||||||
|
raise NotImplementedError(f"Type {new_city_object.type} is not supported")
|
|
@ -627,7 +627,333 @@ class MontrealFunctionToHubFunction:
|
||||||
'4815': cte.NON_HEATED,
|
'4815': cte.NON_HEATED,
|
||||||
'6651': cte.WORKSHOP,
|
'6651': cte.WORKSHOP,
|
||||||
'2822': cte.INDUSTRY,
|
'2822': cte.INDUSTRY,
|
||||||
'2821': cte.INDUSTRY
|
'2821': cte.INDUSTRY,
|
||||||
|
'1211': cte.RESIDENTIAL,
|
||||||
|
'8133': cte.INDUSTRY,
|
||||||
|
'6572': cte.HEALTH_CARE,
|
||||||
|
'2734': cte.INDUSTRY,
|
||||||
|
'8132': cte.INDUSTRY,
|
||||||
|
'6659': cte.INDUSTRY,
|
||||||
|
'6332': cte.COMMERCIAL,
|
||||||
|
'6595': cte.COMMERCIAL,
|
||||||
|
'5393': cte.COMMERCIAL,
|
||||||
|
'5450': cte.COMMERCIAL,
|
||||||
|
'8127': cte.INDUSTRY,
|
||||||
|
'5595': cte.COMMERCIAL,
|
||||||
|
'6571': cte.HEALTH_CARE,
|
||||||
|
'5030': cte.COMMERCIAL,
|
||||||
|
'9460': cte.WAREHOUSE,
|
||||||
|
'7516': cte.SPORTS_LOCATION,
|
||||||
|
'5523': cte.COMMERCIAL,
|
||||||
|
'5722': cte.COMMERCIAL,
|
||||||
|
'4732': cte.NON_HEATED,
|
||||||
|
'7491': cte.SPORTS_LOCATION,
|
||||||
|
'3262': cte.INDUSTRY,
|
||||||
|
'8543': cte.INDUSTRY,
|
||||||
|
'6129': cte.COMMERCIAL,
|
||||||
|
'5362': cte.COMMERCIAL,
|
||||||
|
'8122': cte.INDUSTRY,
|
||||||
|
'5597': cte.COMMERCIAL,
|
||||||
|
'3269': cte.INDUSTRY,
|
||||||
|
'5331': cte.COMMERCIAL,
|
||||||
|
'5522': cte.COMMERCIAL,
|
||||||
|
'7421': cte.WAREHOUSE,
|
||||||
|
'2723': cte.INDUSTRY,
|
||||||
|
'4822': cte.NON_HEATED,
|
||||||
|
'6319': cte.COMMERCIAL,
|
||||||
|
'8131': cte.INDUSTRY,
|
||||||
|
'7422': cte.SPORTS_LOCATION,
|
||||||
|
'3140': cte.INDUSTRY,
|
||||||
|
'9220': cte.NON_HEATED,
|
||||||
|
'4852': cte.NON_HEATED,
|
||||||
|
'3694': cte.INDUSTRY,
|
||||||
|
'6632': cte.COMMERCIAL,
|
||||||
|
'6656': cte.WAREHOUSE,
|
||||||
|
'8322': cte.INDUSTRY,
|
||||||
|
'8126': cte.INDUSTRY,
|
||||||
|
'6638': cte.COMMERCIAL,
|
||||||
|
'2292': cte.INDUSTRY,
|
||||||
|
'6392': cte.COMMERCIAL,
|
||||||
|
'4313': cte.WAREHOUSE,
|
||||||
|
'4312': cte.NON_HEATED,
|
||||||
|
'6417': cte.COMMERCIAL,
|
||||||
|
'6234': cte.COMMERCIAL,
|
||||||
|
'6254': cte.COMMERCIAL,
|
||||||
|
'7396': cte.SPORTS_LOCATION,
|
||||||
|
'3579': cte.INDUSTRY,
|
||||||
|
'6596': cte.COMMERCIAL,
|
||||||
|
'5397': cte.COMMERCIAL,
|
||||||
|
'5946': cte.COMMERCIAL,
|
||||||
|
'6657': cte.COMMERCIAL,
|
||||||
|
'6995': cte.COMMERCIAL,
|
||||||
|
'6711': cte.OFFICE_AND_ADMINISTRATION,
|
||||||
|
'5713': cte.COMMERCIAL,
|
||||||
|
'5954': cte.COMMERCIAL,
|
||||||
|
'6342': cte.COMMERCIAL,
|
||||||
|
'6333': cte.COMMERCIAL,
|
||||||
|
'5932': cte.COMMERCIAL,
|
||||||
|
'5332': cte.COMMERCIAL,
|
||||||
|
'3510': cte.INDUSTRY,
|
||||||
|
'5732': cte.COMMERCIAL,
|
||||||
|
'4811': cte.INDUSTRY,
|
||||||
|
'5422': cte.COMMERCIAL,
|
||||||
|
'5596': cte.COMMERCIAL,
|
||||||
|
'5740': cte.COMMERCIAL,
|
||||||
|
'3232': cte.INDUSTRY,
|
||||||
|
'5933': cte.COMMERCIAL,
|
||||||
|
'5992': cte.COMMERCIAL,
|
||||||
|
'3443': cte.INDUSTRY,
|
||||||
|
'2472': cte.INDUSTRY,
|
||||||
|
'6151': cte.COMMERCIAL,
|
||||||
|
'3263': cte.INDUSTRY,
|
||||||
|
'5396': cte.COMMERCIAL,
|
||||||
|
'3249': cte.INDUSTRY,
|
||||||
|
'4752': cte.COMMERCIAL,
|
||||||
|
'6836': cte.EDUCATION,
|
||||||
|
'3934': cte.INDUSTRY,
|
||||||
|
'4849': cte.NON_HEATED,
|
||||||
|
'4749': cte.NON_HEATED,
|
||||||
|
'3441': cte.INDUSTRY,
|
||||||
|
'7441': cte.SPORTS_LOCATION,
|
||||||
|
'6320': cte.COMMERCIAL,
|
||||||
|
'6191': cte.COMMERCIAL,
|
||||||
|
'6561': cte.HEALTH_CARE,
|
||||||
|
'5185': cte.COMMERCIAL,
|
||||||
|
'4731': cte.COMMERCIAL,
|
||||||
|
'5680': cte.COMMERCIAL,
|
||||||
|
'9458': cte.COMMERCIAL,
|
||||||
|
'2737': cte.INDUSTRY,
|
||||||
|
'3264': cte.INDUSTRY,
|
||||||
|
'6233': cte.COMMERCIAL,
|
||||||
|
'4819': cte.INDUSTRY,
|
||||||
|
'5183': cte.COMMERCIAL,
|
||||||
|
'6724': cte.OFFICE_AND_ADMINISTRATION,
|
||||||
|
'6131': cte.COMMERCIAL,
|
||||||
|
'8121': cte.INDUSTRY,
|
||||||
|
'6652': cte.WAREHOUSE,
|
||||||
|
'5983': cte.COMMERCIAL,
|
||||||
|
'7393': cte.SPORTS_LOCATION,
|
||||||
|
'3350': cte.INDUSTRY,
|
||||||
|
'6397': cte.COMMERCIAL,
|
||||||
|
'3594': cte.INDUSTRY,
|
||||||
|
'6637': cte.WAREHOUSE,
|
||||||
|
'5191': cte.COMMERCIAL,
|
||||||
|
'6636': cte.WAREHOUSE,
|
||||||
|
'2061': cte.INDUSTRY,
|
||||||
|
'2049': cte.INDUSTRY,
|
||||||
|
'8299': cte.WAREHOUSE,
|
||||||
|
'8180': cte.COMMERCIAL,
|
||||||
|
'6516': cte.HEALTH_CARE,
|
||||||
|
'6597': cte.OFFICE_AND_ADMINISTRATION,
|
||||||
|
'2933': cte.INDUSTRY,
|
||||||
|
'5154': cte.COMMERCIAL,
|
||||||
|
'6371': cte.WAREHOUSE,
|
||||||
|
'5995': cte.COMMERCIAL,
|
||||||
|
'4772': cte.COMMERCIAL,
|
||||||
|
'4760': cte.COMMERCIAL,
|
||||||
|
'6493': cte.COMMERCIAL,
|
||||||
|
'5947': cte.COMMERCIAL,
|
||||||
|
'5242': cte.COMMERCIAL,
|
||||||
|
'5892': cte.COMMERCIAL,
|
||||||
|
'5719': cte.COMMERCIAL,
|
||||||
|
'2895': cte.INDUSTRY,
|
||||||
|
'7415': cte.SPORTS_LOCATION,
|
||||||
|
'4563': cte.NON_HEATED,
|
||||||
|
'3014': cte.INDUSTRY,
|
||||||
|
'5691': cte.COMMERCIAL,
|
||||||
|
'3111': cte.INDUSTRY,
|
||||||
|
'8198': cte.INDUSTRY,
|
||||||
|
'8141': cte.INDUSTRY,
|
||||||
|
'7452': cte.WAREHOUSE,
|
||||||
|
'3222': cte.INDUSTRY,
|
||||||
|
'2713': cte.INDUSTRY,
|
||||||
|
'2088': cte.INDUSTRY,
|
||||||
|
'6564': cte.HEALTH_CARE,
|
||||||
|
'6622': cte.WAREHOUSE,
|
||||||
|
'5440': cte.COMMERCIAL,
|
||||||
|
'2894': cte.INDUSTRY,
|
||||||
|
'6625': cte.WAREHOUSE,
|
||||||
|
'6239': cte.COMMERCIAL,
|
||||||
|
'8129': cte.WAREHOUSE,
|
||||||
|
'6647': cte.WAREHOUSE,
|
||||||
|
'8137': cte.WAREHOUSE,
|
||||||
|
'6553': cte.COMMERCIAL,
|
||||||
|
'3442': cte.INDUSTRY,
|
||||||
|
'4391': cte.NON_HEATED,
|
||||||
|
'5591': cte.COMMERCIAL,
|
||||||
|
'5151': cte.COMMERCIAL,
|
||||||
|
'5196': cte.COMMERCIAL,
|
||||||
|
'6616': cte.COMMERCIAL,
|
||||||
|
'2216': cte.INDUSTRY,
|
||||||
|
'8191': cte.WAREHOUSE,
|
||||||
|
'6422': cte.COMMERCIAL,
|
||||||
|
'1212': cte.RESIDENTIAL,
|
||||||
|
'8134': cte.WAREHOUSE,
|
||||||
|
'5194': cte.COMMERCIAL,
|
||||||
|
'6658': cte.WAREHOUSE,
|
||||||
|
'8123': cte.WAREHOUSE,
|
||||||
|
'6346': cte.COMMERCIAL,
|
||||||
|
'2731': cte.INDUSTRY,
|
||||||
|
'7445': cte.COMMERCIAL,
|
||||||
|
'8125': cte.WAREHOUSE,
|
||||||
|
'4746': cte.NON_HEATED,
|
||||||
|
'3922': cte.INDUSTRY,
|
||||||
|
'5360': cte.WAREHOUSE,
|
||||||
|
'3330': cte.WAREHOUSE,
|
||||||
|
'7610': cte.WAREHOUSE,
|
||||||
|
'6142': cte.WAREHOUSE,
|
||||||
|
'4610': cte.WAREHOUSE,
|
||||||
|
'6552': cte.WAREHOUSE,
|
||||||
|
'8120': cte.WAREHOUSE,
|
||||||
|
'6313': cte.WAREHOUSE,
|
||||||
|
'6398': cte.WAREHOUSE,
|
||||||
|
'6730': cte.WAREHOUSE,
|
||||||
|
'6153': cte.WAREHOUSE,
|
||||||
|
'3013': cte.WAREHOUSE,
|
||||||
|
'5187': cte.WAREHOUSE,
|
||||||
|
'5182': cte.WAREHOUSE,
|
||||||
|
'6336': cte.WAREHOUSE,
|
||||||
|
'5122': cte.WAREHOUSE,
|
||||||
|
'3914': cte.WAREHOUSE,
|
||||||
|
'3480': cte.WAREHOUSE,
|
||||||
|
'8135': cte.WAREHOUSE,
|
||||||
|
'3979': cte.WAREHOUSE,
|
||||||
|
'8319': cte.WAREHOUSE,
|
||||||
|
'6155': cte.WAREHOUSE,
|
||||||
|
'5998': cte.WAREHOUSE,
|
||||||
|
'3016': cte.WAREHOUSE,
|
||||||
|
'5333': cte.WAREHOUSE,
|
||||||
|
'6381': cte.WAREHOUSE,
|
||||||
|
'5912': cte.WAREHOUSE,
|
||||||
|
'4829': cte.WAREHOUSE,
|
||||||
|
'2732': cte.WAREHOUSE,
|
||||||
|
'5993': cte.WAREHOUSE,
|
||||||
|
'2735': cte.WAREHOUSE,
|
||||||
|
'6421': cte.WAREHOUSE,
|
||||||
|
'5981': cte.WAREHOUSE,
|
||||||
|
'7213': cte.WAREHOUSE,
|
||||||
|
'5994': cte.WAREHOUSE,
|
||||||
|
'3940': cte.WAREHOUSE,
|
||||||
|
'3893': cte.WAREHOUSE,
|
||||||
|
'6729': cte.WAREHOUSE,
|
||||||
|
'3152': cte.WAREHOUSE,
|
||||||
|
'6991': cte.WAREHOUSE,
|
||||||
|
'6626': cte.WAREHOUSE,
|
||||||
|
'6149': cte.WAREHOUSE,
|
||||||
|
'4764': cte.WAREHOUSE,
|
||||||
|
'7511': cte.WAREHOUSE,
|
||||||
|
'6655': cte.WAREHOUSE,
|
||||||
|
'8229': cte.WAREHOUSE,
|
||||||
|
'6418': cte.WAREHOUSE,
|
||||||
|
'6356': cte.WAREHOUSE,
|
||||||
|
'6562': cte.WAREHOUSE,
|
||||||
|
'6654': cte.WAREHOUSE,
|
||||||
|
'5164': cte.WAREHOUSE,
|
||||||
|
'5188': cte.WAREHOUSE,
|
||||||
|
'6996': cte.WAREHOUSE,
|
||||||
|
'3221': cte.WAREHOUSE,
|
||||||
|
'8124': cte.WAREHOUSE,
|
||||||
|
'2494': cte.WAREHOUSE,
|
||||||
|
'6215': cte.WAREHOUSE,
|
||||||
|
'6644': cte.WAREHOUSE,
|
||||||
|
'6262': cte.WAREHOUSE,
|
||||||
|
'4927': cte.WAREHOUSE,
|
||||||
|
'3991': cte.WAREHOUSE,
|
||||||
|
'2215': cte.WAREHOUSE,
|
||||||
|
'5144': cte.WAREHOUSE,
|
||||||
|
'2740': cte.WAREHOUSE,
|
||||||
|
'5670': cte.WAREHOUSE,
|
||||||
|
'6442': cte.WAREHOUSE,
|
||||||
|
'3612': cte.WAREHOUSE,
|
||||||
|
'5990': cte.WAREHOUSE,
|
||||||
|
'5193': cte.WAREHOUSE,
|
||||||
|
'5197': cte.WAREHOUSE,
|
||||||
|
'3974': cte.WAREHOUSE,
|
||||||
|
'2019': cte.WAREHOUSE,
|
||||||
|
'7314': cte.WAREHOUSE,
|
||||||
|
'3542': cte.WAREHOUSE,
|
||||||
|
'5165': cte.WAREHOUSE,
|
||||||
|
'4291': cte.WAREHOUSE,
|
||||||
|
'1913': cte.WAREHOUSE,
|
||||||
|
'5270': cte.WAREHOUSE,
|
||||||
|
'7481': cte.WAREHOUSE,
|
||||||
|
'4855': cte.WAREHOUSE,
|
||||||
|
'6261': cte.WAREHOUSE,
|
||||||
|
'2733': cte.WAREHOUSE,
|
||||||
|
'5943': cte.WAREHOUSE,
|
||||||
|
'7522': cte.WAREHOUSE,
|
||||||
|
'5714': cte.WAREHOUSE,
|
||||||
|
'5653': cte.WAREHOUSE,
|
||||||
|
'2640': cte.WAREHOUSE,
|
||||||
|
'4813': cte.WAREHOUSE,
|
||||||
|
'6345': cte.WAREHOUSE,
|
||||||
|
'5177': cte.WAREHOUSE,
|
||||||
|
'4789': cte.WAREHOUSE,
|
||||||
|
'5195': cte.WAREHOUSE,
|
||||||
|
'3017': cte.WAREHOUSE,
|
||||||
|
'4872': cte.WAREHOUSE,
|
||||||
|
'7411': cte.WAREHOUSE,
|
||||||
|
'3973': cte.WAREHOUSE,
|
||||||
|
'3039': cte.WAREHOUSE,
|
||||||
|
'6159': cte.WAREHOUSE,
|
||||||
|
'5982': cte.WAREHOUSE,
|
||||||
|
'5539': cte.WAREHOUSE,
|
||||||
|
'8542': cte.WAREHOUSE,
|
||||||
|
'2222': cte.WAREHOUSE,
|
||||||
|
'8312': cte.WAREHOUSE,
|
||||||
|
'3832': cte.WAREHOUSE,
|
||||||
|
'3592': cte.WAREHOUSE,
|
||||||
|
'8128': cte.WAREHOUSE,
|
||||||
|
'6523': cte.WAREHOUSE,
|
||||||
|
'3430': cte.WAREHOUSE,
|
||||||
|
'5395': cte.WAREHOUSE,
|
||||||
|
'3716': cte.WAREHOUSE,
|
||||||
|
'7223': cte.WAREHOUSE,
|
||||||
|
'7521': cte.WAREHOUSE,
|
||||||
|
'2738': cte.WAREHOUSE,
|
||||||
|
'2217': cte.WAREHOUSE,
|
||||||
|
'8311': cte.WAREHOUSE,
|
||||||
|
'3693': cte.WAREHOUSE,
|
||||||
|
'6123': cte.WAREHOUSE,
|
||||||
|
'7115': cte.WAREHOUSE,
|
||||||
|
'4567': cte.WAREHOUSE,
|
||||||
|
'4742': cte.WAREHOUSE,
|
||||||
|
'5159': cte.WAREHOUSE,
|
||||||
|
'5192': cte.WAREHOUSE,
|
||||||
|
'5178': cte.WAREHOUSE,
|
||||||
|
'5716': cte.WAREHOUSE,
|
||||||
|
'7392': cte.WAREHOUSE,
|
||||||
|
'2913': cte.WAREHOUSE,
|
||||||
|
'4854': cte.WAREHOUSE,
|
||||||
|
'2062': cte.WAREHOUSE,
|
||||||
|
'5363': cte.WAREHOUSE,
|
||||||
|
'6347': cte.WAREHOUSE,
|
||||||
|
'1914': cte.WAREHOUSE,
|
||||||
|
'7519': cte.WAREHOUSE,
|
||||||
|
'2094': cte.WAREHOUSE,
|
||||||
|
'6645': cte.WAREHOUSE,
|
||||||
|
'7414': cte.WAREHOUSE,
|
||||||
|
'6732': cte.WAREHOUSE,
|
||||||
|
'6554': cte.WAREHOUSE,
|
||||||
|
'7394': cte.WAREHOUSE,
|
||||||
|
'6222': cte.WAREHOUSE,
|
||||||
|
'3520': cte.WAREHOUSE,
|
||||||
|
'6741': cte.WAREHOUSE,
|
||||||
|
'7116': cte.WAREHOUSE,
|
||||||
|
'8099': cte.WAREHOUSE,
|
||||||
|
'3642': cte.WAREHOUSE,
|
||||||
|
'6614': cte.WAREHOUSE,
|
||||||
|
'6252': cte.WAREHOUSE,
|
||||||
|
'2452': cte.WAREHOUSE,
|
||||||
|
'3251': cte.WAREHOUSE,
|
||||||
|
'5115': cte.WAREHOUSE,
|
||||||
|
'6366': cte.WAREHOUSE,
|
||||||
|
'5143': cte.WAREHOUSE,
|
||||||
|
'5493': cte.WAREHOUSE,
|
||||||
|
'7395': cte.WAREHOUSE,
|
||||||
|
'6363': cte.WAREHOUSE,
|
||||||
|
'6393': cte.WAREHOUSE,
|
||||||
|
'6244': cte.WAREHOUSE
|
||||||
}
|
}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
115
hub/imports/geometry/csv.py
Normal file
115
hub/imports/geometry/csv.py
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
import csv
|
||||||
|
import uuid
|
||||||
|
from decimal import Decimal, InvalidOperation
|
||||||
|
from pyproj import Transformer
|
||||||
|
from hub.city_model_structure.simplified_building import SimplifiedBuilding
|
||||||
|
from hub.city_model_structure.simplified_city import SimplifiedCity
|
||||||
|
|
||||||
|
|
||||||
|
class Csv:
|
||||||
|
"""
|
||||||
|
CSV class
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self,
|
||||||
|
path,
|
||||||
|
centroid_x_field=None,
|
||||||
|
centroid_y_field=None,
|
||||||
|
postal_code_field=None,
|
||||||
|
year_of_construction_field=None,
|
||||||
|
function_field=None,
|
||||||
|
function_to_hub=None,
|
||||||
|
total_floor_area_field=None):
|
||||||
|
self._simplified_city = None
|
||||||
|
self._centroid_x_field = centroid_x_field
|
||||||
|
self._centroid_y_field = centroid_y_field
|
||||||
|
self._postal_code_field = postal_code_field
|
||||||
|
self._year_of_construction_field = year_of_construction_field
|
||||||
|
self._function_field = function_field
|
||||||
|
self._function_to_hub = function_to_hub
|
||||||
|
self._total_floor_area_field = total_floor_area_field
|
||||||
|
self.transformer = Transformer.from_crs("EPSG:3857", "EPSG:4326", always_xy=True)
|
||||||
|
|
||||||
|
with open(path, 'r', encoding='utf8') as csv_file:
|
||||||
|
reader = csv.DictReader(csv_file)
|
||||||
|
self._csv_data = [row for row in reader]
|
||||||
|
|
||||||
|
def safe_int(self, value):
|
||||||
|
if value in ('NULL', '', None):
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
return int(value)
|
||||||
|
except ValueError:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def safe_str(self, value):
|
||||||
|
if value in ('NULL', '', None):
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
return str(value)
|
||||||
|
except ValueError:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def safe_float(self, value):
|
||||||
|
if value in ('NULL', '', None):
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
return float(value)
|
||||||
|
except ValueError:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def safe_decimal(self, value):
|
||||||
|
if value in ('NULL', '', None):
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
return Decimal(value)
|
||||||
|
except InvalidOperation:
|
||||||
|
return None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def city(self) -> SimplifiedCity:
|
||||||
|
if self._simplified_city is None:
|
||||||
|
self._simplified_city = SimplifiedCity()
|
||||||
|
for index, row in enumerate(self._csv_data):
|
||||||
|
centroid = None
|
||||||
|
if self._centroid_x_field and self._centroid_y_field:
|
||||||
|
centroid_x = self.safe_float(row[self._centroid_x_field])
|
||||||
|
centroid_y = self.safe_float(row.get(self._centroid_y_field))
|
||||||
|
if centroid_x is not None and centroid_y is not None:
|
||||||
|
lon, lat = self.transformer.transform(centroid_x, centroid_y)
|
||||||
|
centroid = (lon, lat)
|
||||||
|
|
||||||
|
postal_code = None
|
||||||
|
if self._postal_code_field:
|
||||||
|
postal_code = self.safe_float(row[self._postal_code_field])
|
||||||
|
|
||||||
|
year_of_construction = None
|
||||||
|
if self._year_of_construction_field:
|
||||||
|
year_of_construction = self.safe_int(row[self._year_of_construction_field])
|
||||||
|
|
||||||
|
function = None
|
||||||
|
if self._function_field:
|
||||||
|
function = row[self._function_field]
|
||||||
|
if self._function_to_hub:
|
||||||
|
function = self._function_to_hub.get(function, function)
|
||||||
|
|
||||||
|
total_floor_area = None
|
||||||
|
if self._total_floor_area_field:
|
||||||
|
total_floor_area = self.safe_float(row[self._total_floor_area_field])
|
||||||
|
|
||||||
|
# Use index as the name of the building
|
||||||
|
building_name = f"Building_{index + 1}"
|
||||||
|
|
||||||
|
building = SimplifiedBuilding(
|
||||||
|
name=building_name,
|
||||||
|
centroid=centroid,
|
||||||
|
postal_code=postal_code,
|
||||||
|
total_floor_area=total_floor_area,
|
||||||
|
year_of_construction=year_of_construction,
|
||||||
|
function=function
|
||||||
|
)
|
||||||
|
|
||||||
|
if building.total_floor_area is not None and building.total_floor_area >= 25:
|
||||||
|
self._simplified_city.add_city_object(building)
|
||||||
|
|
||||||
|
return self._simplified_city
|
|
@ -6,10 +6,12 @@ Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from hub.city_model_structure.city import City
|
from hub.city_model_structure.city import City
|
||||||
|
from hub.city_model_structure.simplified_city import SimplifiedCity
|
||||||
from hub.helpers.utils import validate_import_export_type
|
from hub.helpers.utils import validate_import_export_type
|
||||||
from hub.imports.geometry.citygml import CityGml
|
from hub.imports.geometry.citygml import CityGml
|
||||||
from hub.imports.geometry.geojson import Geojson
|
from hub.imports.geometry.geojson import Geojson
|
||||||
from hub.imports.geometry.obj import Obj
|
from hub.imports.geometry.obj import Obj
|
||||||
|
from hub.imports.geometry.csv import Csv
|
||||||
|
|
||||||
|
|
||||||
class GeometryFactory:
|
class GeometryFactory:
|
||||||
|
@ -20,19 +22,27 @@ class GeometryFactory:
|
||||||
path=None,
|
path=None,
|
||||||
aliases_field=None,
|
aliases_field=None,
|
||||||
height_field=None,
|
height_field=None,
|
||||||
|
centroid_x_field=None,
|
||||||
|
centroid_y_field=None,
|
||||||
|
position_x_field=None,
|
||||||
year_of_construction_field=None,
|
year_of_construction_field=None,
|
||||||
function_field=None,
|
function_field=None,
|
||||||
function_to_hub=None,
|
function_to_hub=None,
|
||||||
hub_crs=None):
|
hub_crs=None,
|
||||||
|
total_floor_area_field=None):
|
||||||
self._file_type = '_' + file_type.lower()
|
self._file_type = '_' + file_type.lower()
|
||||||
validate_import_export_type(GeometryFactory, file_type)
|
validate_import_export_type(GeometryFactory, file_type)
|
||||||
self._path = path
|
self._path = path
|
||||||
self._aliases_field = aliases_field
|
self._aliases_field = aliases_field
|
||||||
self._height_field = height_field
|
self._height_field = height_field
|
||||||
|
self._centroid_x_field = centroid_x_field
|
||||||
|
self._centroid_y_field = centroid_y_field
|
||||||
|
self._position_x_field = position_x_field
|
||||||
self._year_of_construction_field = year_of_construction_field
|
self._year_of_construction_field = year_of_construction_field
|
||||||
self._function_field = function_field
|
self._function_field = function_field
|
||||||
self._function_to_hub = function_to_hub
|
self._function_to_hub = function_to_hub
|
||||||
self._hub_crs = hub_crs
|
self._hub_crs = hub_crs
|
||||||
|
self._total_floor_area_field = total_floor_area_field
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _citygml(self) -> City:
|
def _citygml(self) -> City:
|
||||||
|
@ -68,6 +78,17 @@ class GeometryFactory:
|
||||||
self._function_to_hub,
|
self._function_to_hub,
|
||||||
self._hub_crs).city
|
self._hub_crs).city
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _csv(self) -> SimplifiedCity:
|
||||||
|
return Csv(self._path,
|
||||||
|
self._centroid_x_field,
|
||||||
|
self._centroid_y_field,
|
||||||
|
self._position_x_field,
|
||||||
|
self._year_of_construction_field,
|
||||||
|
self._function_field,
|
||||||
|
self._function_to_hub,
|
||||||
|
self._total_floor_area_field).city
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def city(self) -> City:
|
def city(self) -> City:
|
||||||
"""
|
"""
|
||||||
|
@ -75,3 +96,11 @@ class GeometryFactory:
|
||||||
:return: City
|
:return: City
|
||||||
"""
|
"""
|
||||||
return getattr(self, self._file_type, lambda: None)
|
return getattr(self, self._file_type, lambda: None)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def simplified_city(self) -> SimplifiedCity:
|
||||||
|
"""
|
||||||
|
Enrich the city given to the class using the class given handler
|
||||||
|
:return: SimplifiedCity
|
||||||
|
"""
|
||||||
|
return getattr(self, self._file_type, lambda: None)
|
||||||
|
|
152
hub/imports/results/archetype_based_demand.py
Normal file
152
hub/imports/results/archetype_based_demand.py
Normal file
|
@ -0,0 +1,152 @@
|
||||||
|
import pandas as pd
|
||||||
|
from sqlalchemy import create_engine, text
|
||||||
|
|
||||||
|
|
||||||
|
class DemandEnricher:
|
||||||
|
"""
|
||||||
|
DemandEnricher class to enrich buildings with demand data
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, database_url):
|
||||||
|
# Create a SQLAlchemy engine using the provided database URL
|
||||||
|
self.engine = create_engine(database_url)
|
||||||
|
# Initialize the function mapping and cache
|
||||||
|
self.create_function_mapping()
|
||||||
|
self.archetype_cache = {}
|
||||||
|
|
||||||
|
def create_function_mapping(self):
|
||||||
|
# Define function mapping from city functions to archetype functions
|
||||||
|
self.function_mapping = {
|
||||||
|
'residential': 'Maison Unifamiliale',
|
||||||
|
'single family house': 'Maison Unifamiliale',
|
||||||
|
'multifamily house': 'Apartements partie 3 du code',
|
||||||
|
'medium office': 'Bureaux',
|
||||||
|
'office and administration': 'Bureaux',
|
||||||
|
'commercial': 'Commercial attaché',
|
||||||
|
'warehouse': 'Commercial détaché', # Approximate
|
||||||
|
'restaurant': 'Commercial attaché', # Approximate
|
||||||
|
'hotel': 'Commercial attaché', # Approximate
|
||||||
|
# Add more mappings as needed
|
||||||
|
}
|
||||||
|
|
||||||
|
def get_vintage_range(self, year):
|
||||||
|
# Determine the vintage range based on the year of construction
|
||||||
|
if year <= 1947:
|
||||||
|
return 'avant 1947'
|
||||||
|
elif 1947 < year <= 1983:
|
||||||
|
return '1947-1983'
|
||||||
|
elif 1983 < year <= 2010:
|
||||||
|
return '1984-2010'
|
||||||
|
elif year > 2010:
|
||||||
|
return 'après 2010'
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_archetype_demands(self, type_of_building):
|
||||||
|
# Check if the demands for this archetype are already cached
|
||||||
|
if type_of_building in self.archetype_cache:
|
||||||
|
return self.archetype_cache[type_of_building]
|
||||||
|
|
||||||
|
# Construct the SQL query
|
||||||
|
query = text("""
|
||||||
|
SELECT heating, cooling, equipment, lighting
|
||||||
|
FROM energy_data
|
||||||
|
WHERE type_of_building = :type_of_building
|
||||||
|
ORDER BY timestamp
|
||||||
|
""")
|
||||||
|
|
||||||
|
# Execute the query with parameter substitution
|
||||||
|
with self.engine.connect() as conn:
|
||||||
|
result = conn.execute(query, type_of_building=type_of_building)
|
||||||
|
demands = result.fetchall()
|
||||||
|
if not demands:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Convert the result to a DataFrame
|
||||||
|
demands_df = pd.DataFrame(demands, columns=['heating', 'cooling', 'equipment', 'lighting'])
|
||||||
|
# Convert columns to numeric types
|
||||||
|
for demand_column in ['heating', 'cooling', 'equipment', 'lighting']:
|
||||||
|
demands_df[demand_column] = pd.to_numeric(demands_df[demand_column], errors='coerce')
|
||||||
|
demands_df[demand_column].fillna(0, inplace=True)
|
||||||
|
|
||||||
|
# Cache the demands for future use
|
||||||
|
self.archetype_cache[type_of_building] = demands_df
|
||||||
|
return demands_df
|
||||||
|
|
||||||
|
def enrich_city(self, city):
|
||||||
|
# Enrich each building in the city with demand data
|
||||||
|
for building in city.buildings:
|
||||||
|
# Ensure the building has the necessary attributes
|
||||||
|
if (building.year_of_construction is not None and
|
||||||
|
building.function is not None and
|
||||||
|
building.total_floor_area is not None):
|
||||||
|
# Map the building's function to an archetype function
|
||||||
|
building_function_lower = building.function.lower()
|
||||||
|
mapped_function = None
|
||||||
|
for key in self.function_mapping:
|
||||||
|
if key in building_function_lower:
|
||||||
|
mapped_function = self.function_mapping[key]
|
||||||
|
break
|
||||||
|
if mapped_function:
|
||||||
|
# Determine the vintage range
|
||||||
|
vintage_range = self.get_vintage_range(building.year_of_construction)
|
||||||
|
if vintage_range:
|
||||||
|
# Construct the Type_of_building string
|
||||||
|
type_of_building = f"{mapped_function} {vintage_range}"
|
||||||
|
# Get the demands for this archetype
|
||||||
|
demands_df = self.get_archetype_demands(type_of_building)
|
||||||
|
if demands_df is not None:
|
||||||
|
# Check total_floor_area
|
||||||
|
total_floor_area = building.total_floor_area
|
||||||
|
if not isinstance(total_floor_area, (int, float)) or pd.isnull(total_floor_area):
|
||||||
|
print(f"Invalid total_floor_area for building {building.name}. Skipping.")
|
||||||
|
building.heating_demand = []
|
||||||
|
building.cooling_demand = []
|
||||||
|
building.electricity_demand = []
|
||||||
|
building.appliance_demand = []
|
||||||
|
continue
|
||||||
|
# Proceed with multiplication
|
||||||
|
try:
|
||||||
|
demands_df['Heating_total'] = demands_df['heating'] * total_floor_area
|
||||||
|
demands_df['Cooling_total'] = demands_df['cooling'] * total_floor_area
|
||||||
|
demands_df['Equipment_total'] = demands_df['equipment'] * total_floor_area
|
||||||
|
demands_df['Lighting_total'] = demands_df['lighting'] * total_floor_area
|
||||||
|
# Assign the total demand profiles to the building's attributes
|
||||||
|
building.heating_demand = demands_df['Heating_total'].tolist()
|
||||||
|
building.cooling_demand = demands_df['Cooling_total'].tolist()
|
||||||
|
building.electricity_demand = demands_df['Lighting_total'].tolist()
|
||||||
|
building.appliance_demand = demands_df['Equipment_total'].tolist()
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error calculating demands for building {building.name}: {e}")
|
||||||
|
building.heating_demand = []
|
||||||
|
building.cooling_demand = []
|
||||||
|
building.electricity_demand = []
|
||||||
|
building.appliance_demand = []
|
||||||
|
else:
|
||||||
|
# No data found for this Type_of_building
|
||||||
|
building.heating_demand = []
|
||||||
|
building.cooling_demand = []
|
||||||
|
building.electricity_demand = []
|
||||||
|
building.appliance_demand = []
|
||||||
|
else:
|
||||||
|
# Vintage range could not be determined
|
||||||
|
building.heating_demand = []
|
||||||
|
building.cooling_demand = []
|
||||||
|
building.electricity_demand = []
|
||||||
|
building.appliance_demand = []
|
||||||
|
else:
|
||||||
|
# Function mapping not found
|
||||||
|
building.heating_demand = []
|
||||||
|
building.cooling_demand = []
|
||||||
|
building.electricity_demand = []
|
||||||
|
building.appliance_demand = []
|
||||||
|
else:
|
||||||
|
# Missing necessary attributes
|
||||||
|
building.heating_demand = []
|
||||||
|
building.cooling_demand = []
|
||||||
|
building.electricity_demand = []
|
||||||
|
building.appliance_demand = []
|
||||||
|
|
||||||
|
def close_connection(self):
|
||||||
|
# Dispose of the engine to close the database connection
|
||||||
|
self.engine.dispose()
|
41
main.py
Normal file
41
main.py
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
from hub.imports.geometry_factory import GeometryFactory
|
||||||
|
from hub.helpers.dictionaries import Dictionaries
|
||||||
|
from hub.imports.results.archetype_based_demand import DemandEnricher
|
||||||
|
import urllib.parse
|
||||||
|
|
||||||
|
input_file = "data/cmm_points_function_vintage_surface.csv"
|
||||||
|
output_file = "output_buildings.csv"
|
||||||
|
|
||||||
|
# Database credentials
|
||||||
|
db_username = 'postgres'
|
||||||
|
db_password = 'your_password_with_special_characters' # Replace with your actual password
|
||||||
|
db_host = 'localhost'
|
||||||
|
db_port = '5432'
|
||||||
|
db_name = 'energydemanddb'
|
||||||
|
|
||||||
|
# URL-encode username and password
|
||||||
|
db_username_encoded = urllib.parse.quote_plus(db_username)
|
||||||
|
db_password_encoded = urllib.parse.quote_plus(db_password)
|
||||||
|
|
||||||
|
# Construct the database connection URL
|
||||||
|
database_url = f'postgresql://{db_username_encoded}:{db_password_encoded}@{db_host}:{db_port}/{db_name}'
|
||||||
|
|
||||||
|
# Initialize city object from GeometryFactory
|
||||||
|
city = GeometryFactory(
|
||||||
|
file_type="csv",
|
||||||
|
path=input_file,
|
||||||
|
centroid_x_field="centroid_x",
|
||||||
|
centroid_y_field="centroid_y",
|
||||||
|
year_of_construction_field="anne_cnstr",
|
||||||
|
function_field="code_util",
|
||||||
|
function_to_hub=Dictionaries().montreal_function_to_hub_function,
|
||||||
|
total_floor_area_field="supfi_etag"
|
||||||
|
).city
|
||||||
|
|
||||||
|
# Create an instance of DemandEnricher using the database URL
|
||||||
|
demand_enricher = DemandEnricher(database_url)
|
||||||
|
demand_enricher.enrich_city(city)
|
||||||
|
# Close the database connection when done
|
||||||
|
demand_enricher.close_connection()
|
||||||
|
|
||||||
|
print("done")
|
1125156
output_buildings.csv
Normal file
1125156
output_buildings.csv
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user