Compare commits

...

7 Commits

10 changed files with 2601995 additions and 2 deletions

File diff suppressed because it is too large Load Diff

210241
data/energy_demand_data.csv Normal file

File diff suppressed because it is too large Load Diff

View 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

View 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")

View File

@ -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
View 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

View File

@ -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)

View 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
View 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

File diff suppressed because it is too large Load Diff