From 0ce76bef133f728902f5a8285c6baf65e0c8abf2 Mon Sep 17 00:00:00 2001 From: Andrea Gabaldon Moreno Date: Mon, 22 Jul 2024 18:14:54 -0400 Subject: [PATCH] 20240722 changes --- .gitignore | 16 + comparing.py | 215 +++++++++++++ hub/city_model_structure/building.py | 8 +- main.py | 69 +++-- main_results_in_geojson.py | 176 +++++++++++ processor.py | 446 +++++++++++++++++++-------- 6 files changed, 770 insertions(+), 160 deletions(-) create mode 100644 comparing.py create mode 100644 main_results_in_geojson.py diff --git a/.gitignore b/.gitignore index 6c93083d..0a983239 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,19 @@ **/.idea/ cerc_hub.egg-info /out_files +hub/data/construction/nrcan_constructions.json +hub/helpers/data/hub_function_to_nrcan_construction_function.py +hub/imports/construction/nrcan_physics_parameters.py +input_files/Lachine_moved_2019.geojson +input_files/Lachine_moved_2024.geojson +input_files/Lachine_moved_existing_year.geojson +input_files/Lachine_moved_existing_year_type_2.geojson +input_files/Lachine_moved_existing_year_type_3.geojson +input_files/district_demand.csv +input_files/Lachine_moved_2024_type.geojson +input_files/Lachine_moved_2024_type_2.geojson +input_files/Lachine_moved_2024_type_3.geojson +input_files/new_demands_existing_year.xlsx +input_files/updated_buildings_with_all_data_2024.geojson +input_files/updated_buildings_with_all_data_baseline.geojson +.spyproject diff --git a/comparing.py b/comparing.py new file mode 100644 index 00000000..cfe69875 --- /dev/null +++ b/comparing.py @@ -0,0 +1,215 @@ +import json +from pathlib import Path + +import matplotlib.pyplot as plt +# Specify the GeoJSON file path +input_files_path = (Path(__file__).parent / 'input_files') +# Load the updated GeoJSON file cotaining the results +baseline_scenario_path =input_files_path / 'updated_buildings_with_all_data_baseline.geojson' +energy_efficient_scenario_path = input_files_path / 'updated_buildings_with_all_data_2024.geojson' + +with open(baseline_scenario_path , 'r') as f: + baseline_scenario = json.load(f) +with open(energy_efficient_scenario_path, 'r') as f: + energy_efficient_scenario=json.load(f) +percentage_data = { + 1646: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 2672.550473, "total_floor_area": 26725.50473}, + 1647: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 2653.626087, "total_floor_area": 26536.26087}, + 1648: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 1056.787496, "total_floor_area": 10567.87496}, + 1649: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 1906.620746, "total_floor_area": 19066.20746}, + 1650: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 659.1119416, "total_floor_area": 5272.895533}, + 1651: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 1167.208109, "total_floor_area": 9337.664871}, + 1652: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 1193.251653, "total_floor_area": 9546.013222}, + 1653: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 1491.722543, "total_floor_area": 11933.78035}, + 1654: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 1168.005028, "total_floor_area": 9344.040224}, + 1655: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 1264.906961, "total_floor_area": 10119.25569}, + 1656: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 1281.768818, "total_floor_area": 10254.15054}, + 1657: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 290.3886018, "total_floor_area": 2323.108814}, + 1658: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 847.5095193, "total_floor_area": 6780.076155}, + 1659: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 1115.319153, "total_floor_area": 8922.553224}, + 1660: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 469.2918062, "total_floor_area": 3754.33445}, + 1661: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 1292.298346, "total_floor_area": 10338.38677}, + 1662: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 625.7828863, "total_floor_area": 5006.263091}, + 1663: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 1876.02897, "total_floor_area": 15008.23176}, + 1664: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 1118.224781, "total_floor_area": 22364.49562}, + 1665: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 1502.787808, "total_floor_area": 30055.75617}, + 1666: {"type1_%": 0.891045711, "type2_%": 0.108954289, "type3_%": 0, "roof_area": 3038.486076, "total_floor_area": 30384.86076}, + 1667: {"type1_%": 0.8, "type2_%": 0.2, "type3_%": 0, "roof_area": 1343.832818, "total_floor_area": 13438.32818}, + 1668: {"type1_%": 0.7, "type2_%": 0.3, "type3_%": 0, "roof_area": 961.0996956, "total_floor_area": 4805.498478}, + 1669: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 489.1282111, "total_floor_area": 1956.512845}, + 1673: {"type1_%": 0.7, "type2_%": 0.3, "type3_%": 0, "roof_area": 1693.141465, "total_floor_area": 5079.424396}, + 1674: {"type1_%": 0.7, "type2_%": 0.3, "type3_%": 0, "roof_area": 3248.827576, "total_floor_area": 9746.482729}, + 1675: {"type1_%": 0.7, "type2_%": 0.3, "type3_%": 0, "roof_area": 4086.842191, "total_floor_area": 12260.52657}, + 1676: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 2786.114146, "total_floor_area": 11144.45658}, + 1677: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 5142.784184, "total_floor_area": 15428.35255}, + 1678: {"type1_%": 0.7, "type2_%": 0.3, "type3_%": 0, "roof_area": 6068.664574, "total_floor_area": 18205.99372}, + 1679: {"type1_%": 0.7, "type2_%": 0.3, "type3_%": 0, "roof_area": 5646.751407, "total_floor_area": 16940.25422}, + 1680: {"type1_%": 0.7, "type2_%": 0.3, "type3_%": 0, "roof_area": 1601.765953, "total_floor_area": 4805.297859}, + 1681: {"type1_%": 0.7, "type2_%": 0.3, "type3_%": 0, "roof_area": 9728.221797, "total_floor_area": 29184.66539}, + 1687: {"type1_%": 0.606611029, "type2_%": 0.28211422, "type3_%": 0.11127475, "roof_area": 4268.608743, "total_floor_area": 59760.52241}, + 1688: {"type1_%": 0.92, "type2_%": 0.08, "type3_%": 0, "roof_area": 2146.654828, "total_floor_area": 38639.7869}, + 1689: {"type1_%": 0.96, "type2_%": 0.04, "type3_%": 0, "roof_area": 2860.270711, "total_floor_area": 57205.41421}, + 1690: {"type1_%": 0.94, "type2_%": 0.06, "type3_%": 0, "roof_area": 2189.732519, "total_floor_area": 28466.52275}, + 1691: {"type1_%": 0.75, "type2_%": 0.25, "type3_%": 0, "roof_area": 3159.077523, "total_floor_area": 31590.77523}, +} +# Define the demand types to be plotted +demand_types = [ + 'heating_demand_kWh', + 'cooling_demand_kWh', + 'domestic_hot_water_heat_demand_kWh', + 'appliances_electrical_demand_kWh', + 'lighting_electrical_demand_kWh' +] + +# # Function to extract demand data from the GeoJSON +# def extract_demand_data(geojson_data, demand_type, period_start, period_end): +# demand_data = {} +# for feature in geojson_data['features']: +# building_id = int(feature['properties']['id']) +# if demand_type in feature['properties']: +# demand_series = feature['properties'][demand_type][period_start:period_end] +# demand_data[building_id] = demand_series +# return demand_data +# +# # Define time periods +# period_start_january = 0 +# period_end_january = 168 # First week of January (0-168h) +# period_start_summer = 3360 +# period_end_summer = 3528 # One week in summer +# +# # Function to plot data for all buildings +# def plot_all_buildings(data, period, title): +# plt.figure(figsize=(15, 8)) +# for building_id, values in data.items(): +# plt.plot(range(len(values)), values, label=f'Building {building_id}') +# plt.xlabel('Hour') +# plt.ylabel('Energy Consumption (kWh)') +# plt.title(title) +# plt.legend(loc='upper right', bbox_to_anchor=(1.15, 1)) +# plt.show() +# +# # Function to compare baseline and efficient scenarios for selected buildings +# def plot_comparison(selected_buildings, baseline_data, efficient_data, period, title): +# plt.figure(figsize=(15, 8)) +# for building_id in selected_buildings: +# baseline = baseline_data.get(building_id, []) +# efficient = efficient_data.get(building_id, []) +# plt.plot(range(len(baseline)), baseline, label=f'Baseline Building {building_id}') +# plt.plot(range(len(efficient)), efficient, linestyle='--', label=f'Efficient Building {building_id}') +# plt.xlabel('Hour') +# plt.ylabel('Energy Consumption (kWh)') +# plt.title(title) +# plt.legend(loc='upper right', bbox_to_anchor=(1.15, 1)) +# plt.show() +# +# # Loop through each demand type and extract data, then plot +# for demand_type in demand_types: +# # Extract demand data for the specified periods +# baseline_january = extract_demand_data(baseline_scenario, demand_type, period_start_january, period_end_january) +# baseline_summer = extract_demand_data(baseline_scenario, demand_type, period_start_summer, period_end_summer) +# efficient_january = extract_demand_data(energy_efficient_scenario, demand_type, period_start_january, period_end_january) +# efficient_summer = extract_demand_data(energy_efficient_scenario, demand_type, period_start_summer, period_end_summer) +# +# # Plot all buildings for the first week of January and one week in summer +# plot_all_buildings(baseline_january, range(period_start_january, period_end_january), f'First Week of January - Baseline Scenario - {demand_type}') +# plot_all_buildings(baseline_summer, range(period_start_summer, period_end_summer), f'One Week in Summer - Baseline Scenario - {demand_type}') +# +# # Selected buildings for comparison +# selected_buildings = [1646, 1691, 1687] +# +# # Plot comparison for the first week of January and one week in summer +# plot_comparison(selected_buildings, baseline_january, efficient_january, range(period_start_january, period_end_january), f'First Week of January - Comparison - {demand_type}') +# plot_comparison(selected_buildings, baseline_summer, efficient_summer, range(period_start_summer, period_end_summer), f'One Week in Summer - Comparison - {demand_type}') +# + + +# Function to extract and sum demand data from the GeoJSON +def extract_and_sum_demand_data(geojson_data, demand_type, period_start, period_end): + district_demand = [0] * (period_end - period_start) + for feature in geojson_data['features']: + if demand_type in feature['properties']: + demand_series = feature['properties'][demand_type][period_start:period_end] + district_demand = [sum(x) for x in zip(district_demand, demand_series)] + # Convert kWh to MWh + district_demand_mwh = [value / 1000 for value in district_demand] + return district_demand_mwh + +# Define time periods +period_start_january = 0 +period_end_january = 168 # First week of January (0-168h) +period_start_summer = 3360 +period_end_summer = 3528 # One week in summer + +# Function to plot district demand +def plot_district_demand(district_demand, title): + plt.figure(figsize=(15, 8)) + plt.plot(range(len(district_demand)), district_demand, label='District Demand') + plt.xlabel('Hour') + plt.ylabel('Energy Consumption (MWh)') + plt.title(title) + plt.legend(loc='upper right') + plt.show() + +# Function to compare district demands between baseline and efficient scenarios +def plot_district_comparison(district_demand_baseline, district_demand_efficient, title): + plt.figure(figsize=(15, 8)) + plt.plot(range(len(district_demand_baseline)), district_demand_baseline, label='Baseline District Demand') + plt.plot(range(len(district_demand_efficient)), district_demand_efficient, linestyle='--', label='Efficient District Demand') + plt.xlabel('Hour') + plt.ylabel('Energy Consumption (MWh)') + plt.title(title) + plt.legend(loc='upper right') + plt.show() + +# # Loop through each demand type, extract and sum data, then plot +# for demand_type in demand_types: +# # Extract and sum demand data for the specified periods +# district_demand_january_baseline = extract_and_sum_demand_data(baseline_scenario, demand_type, period_start_january, period_end_january) +# district_demand_summer_baseline = extract_and_sum_demand_data(baseline_scenario, demand_type, period_start_summer, period_end_summer) +# district_demand_january_efficient = extract_and_sum_demand_data(energy_efficient_scenario, demand_type, period_start_january, period_end_january) +# district_demand_summer_efficient = extract_and_sum_demand_data(energy_efficient_scenario, demand_type, period_start_summer, period_end_summer) +# +# # Plot district demand for the first week of January and one week in summer for baseline scenario +# plot_district_demand(district_demand_january_baseline, f'District Demand - First Week of January - Baseline Scenario - {demand_type}') +# plot_district_demand(district_demand_summer_baseline, f'District Demand - One Week in Summer - Baseline Scenario - {demand_type}') +# +# # Plot district demand for the first week of January and one week in summer for energy-efficient scenario +# plot_district_demand(district_demand_january_efficient, f'District Demand - First Week of January - Energy Efficient Scenario - {demand_type}') +# plot_district_demand(district_demand_summer_efficient, f'District Demand - One Week in Summer - Energy Efficient Scenario - {demand_type}') +# +# # Plot comparison of district demand between baseline and energy-efficient scenarios +# plot_district_comparison(district_demand_january_baseline, district_demand_january_efficient, f'District Demand Comparison - First Week of January - {demand_type}') +# plot_district_comparison(district_demand_summer_baseline, district_demand_summer_efficient, f'District Demand Comparison - One Week in Summer - {demand_type}') +# Function to extract and sum demand data from the GeoJSON +# Define time period for a year +period_start = 0 +period_end = 8760 # Full year (0-8760h) + +# Dictionary to store the district demand data for export +district_demand_data = {'hour': list(range(period_start, period_end))} +import pandas as pd +# Loop through each demand type, extract and sum data, then store in dictionary +for demand_type in demand_types: + # Extract and sum demand data for the full year + district_demand_mwh_baseline = extract_and_sum_demand_data(baseline_scenario, demand_type, period_start, period_end) + district_demand_mwh_efficient = extract_and_sum_demand_data(energy_efficient_scenario, demand_type, period_start, + period_end) + + # Store data in the dictionary + district_demand_data[f'{demand_type}_baseline'] = district_demand_mwh_baseline + district_demand_data[f'{demand_type}_efficient'] = district_demand_mwh_efficient + + # Calculate total district demand values for the year + total_district_baseline = sum(district_demand_mwh_baseline) + total_district_efficient = sum(district_demand_mwh_efficient) + + # Print total district demand values + print(f'Total District Demand for {demand_type} (Baseline): {total_district_baseline:.2f} MWh') + print(f'Total District Demand for {demand_type} (Efficient): {total_district_efficient:.2f} MWh') + +# Convert dictionary to DataFrame and export to CSV +district_demand_df = pd.DataFrame(district_demand_data) +output_csv_path = input_files_path / 'district_demand.csv' +district_demand_df.to_csv(output_csv_path, index=False) + +print(f'District demand data exported to {output_csv_path}') \ No newline at end of file diff --git a/hub/city_model_structure/building.py b/hub/city_model_structure/building.py index 387a4bf9..ed7ba168 100644 --- a/hub/city_model_structure/building.py +++ b/hub/city_model_structure/building.py @@ -415,8 +415,8 @@ class Building(CityObject): peak = max(schedule.values) * lighting.density * thermal_zone.total_floor_area if peak > peak_lighting: peak_lighting = peak - results[cte.MONTH] = [peak for _ in range(0, 12)] - results[cte.YEAR] = [peak] + results[cte.MONTH] = [float(peak) for _ in range(0, 12)] + results[cte.YEAR] = [float(peak)] return results @property @@ -434,8 +434,8 @@ class Building(CityObject): peak = max(schedule.values) * appliances.density * thermal_zone.total_floor_area if peak > peak_appliances: peak_appliances = peak - results[cte.MONTH] = [peak for _ in range(0, 12)] - results[cte.YEAR] = [peak] + results[cte.MONTH] = [float(peak) for _ in range(0, 12)] + results[cte.YEAR] = [float(peak)] return results @property diff --git a/main.py b/main.py index 98ef9d66..349e9be9 100644 --- a/main.py +++ b/main.py @@ -13,12 +13,12 @@ input_files_path = (Path(__file__).parent / 'input_files') building_type_2_modelling=2 #'Lachine_New_Developments.geojson' -geojson_file_path = input_files_path / 'Lachine_moved_existing_year_type.geojson' +geojson_file_path = input_files_path / 'Lachine_moved_2024_type.geojson' if building_type_2_modelling==1: gdf = gpd.read_file(geojson_file_path) # Filter gdf when 'building_type_2' is not null filtered_gdf = gdf[gdf['building_type_2'].notnull()] - output_geojson =input_files_path /'Lachine_moved_existing_year_type_2.geojson' + output_geojson =input_files_path /'Lachine_moved_2024_type_2.geojson' geojson_file_path =output_geojson filtered_gdf.to_file(output_geojson, driver='GeoJSON') print(f"New GeoJSON saved in: {output_geojson}") @@ -26,7 +26,7 @@ if building_type_2_modelling==2: gdf = gpd.read_file(geojson_file_path) # Filter gdf when 'building_type_3' is not null filtered_gdf = gdf[gdf['building_type_3'].notnull()] - output_geojson =input_files_path /'Lachine_moved_existing_year_type_3.geojson' + output_geojson =input_files_path /'Lachine_moved_2024_type_3.geojson' geojson_file_path = output_geojson filtered_gdf.to_file(output_geojson, driver='GeoJSON') print(f"New GeoJSON saved in: {output_geojson}") @@ -48,6 +48,8 @@ WeatherFactory('epw', city).enrich() energy_plus_workflow(city) def to_dict(building, total_floor_area): return { + 'roof_area': building.floor_area, + 'total_floor_area': total_floor_area, 'year_of_construction' : building.year_of_construction, 'type_function':building.function, 'beam_kWh_per_m2': sum(building.beam[cte.HOUR])/ (3.6e6), @@ -61,11 +63,11 @@ def to_dict(building, total_floor_area): 'heating_peak_load_kW': building.heating_peak_load[cte.YEAR][0]/ (1e3), 'cooling_peak_load_kW': building.cooling_peak_load[cte.YEAR][0]/ (1e3), 'lighting_peak_load_kW': building.lighting_peak_load[cte.YEAR][0]/ (1e3), - 'heating_demand_kWh_per_m2' : building.heating_demand[cte.YEAR][0]/ (3.6e6 * total_floor_area), - 'cooling_demand_kWh_per_m2' : building.cooling_demand[cte.YEAR][0]/ (3.6e6 * total_floor_area), - 'domestic_hot_water_heat_demand_kWh_per_m2':building.domestic_hot_water_heat_demand[cte.YEAR][0]/ (3.6e6 * total_floor_area), - 'appliances_electrical_demand_kWh_per_m2':building.appliances_electrical_demand[cte.YEAR][0]/ (3.6e6 * total_floor_area), - 'lighting_electrical_demand_kWh_per_m2': building.lighting_electrical_demand[cte.YEAR][0]/ (3.6e6 * total_floor_area), + 'heating_demand_kWh_per_m2' : sum(building.heating_demand[cte.HOUR])/ (3.6e6 * total_floor_area), + 'cooling_demand_kWh_per_m2' : sum(building.cooling_demand[cte.HOUR])/ (3.6e6 * total_floor_area), + 'domestic_hot_water_heat_demand_kWh_per_m2': sum(building.domestic_hot_water_heat_demand[cte.HOUR])/ (3.6e6 * total_floor_area), + 'appliances_electrical_demand_kWh_per_m2':sum(building.appliances_electrical_demand[cte.HOUR])/ (3.6e6 * total_floor_area), + 'lighting_electrical_demand_kWh_per_m2': sum(building.lighting_electrical_demand[cte.HOUR])/ (3.6e6 * total_floor_area), 'heating_demand_kWh': [x / (cte.WATTS_HOUR_TO_JULES * 1000) for x in building.heating_demand[cte.HOUR]], 'cooling_demand_kWh':[x / (cte.WATTS_HOUR_TO_JULES * 1000) for x in building.cooling_demand[cte.HOUR]], 'domestic_hot_water_heat_demand_kWh': [x / (cte.WATTS_HOUR_TO_JULES * 1000) for x in building.domestic_hot_water_heat_demand[cte.HOUR]], @@ -74,6 +76,7 @@ def to_dict(building, total_floor_area): } buildings_dic={} + for building in city.buildings: total_floor_area = 0 @@ -126,31 +129,31 @@ with open(updated_geojson_file_path, 'w') as f: json.dump(geojson_data, f, indent=4) -EnergySystemsFactory('montreal_custom', city).enrich() -print('test') -for building in city.buildings: - energy_systems = building.energy_systems - for energy_system in energy_systems: - generation_units = energy_system.generation_systems - if cte.HEATING in energy_system.demand_types: - for generation_unit in generation_units: - generation_unit.heat_efficiency = 0.96 +# EnergySystemsFactory('montreal_custom', city).enrich() +# print('test') # for building in city.buildings: -# building.function = cte.COMMERCIAL -# -# ConstructionFactory('nrcan', city).enrich() -# UsageFactory('nrcan', city).enrich() -# energy_plus_workflow(city) -# for building in city.buildings: -# print(building.heating_demand[cte.YEAR][0] / 3.6e6) -# print(building.name) -# total_floor_area = 0 -# for thermal_zone in building.thermal_zones_from_internal_zones: -# total_floor_area += thermal_zone.total_floor_area -# print(building.heating_demand[cte.YEAR][0] / (3.6e6 * total_floor_area)) +# energy_systems = building.energy_systems +# for energy_system in energy_systems: +# generation_units = energy_system.generation_systems +# if cte.HEATING in energy_system.demand_types: +# for generation_unit in generation_units: +# generation_unit.heat_efficiency = 0.96 +# # for building in city.buildings: +# # building.function = cte.COMMERCIAL +# # +# # ConstructionFactory('nrcan', city).enrich() +# # UsageFactory('nrcan', city).enrich() +# # energy_plus_workflow(city) +# # for building in city.buildings: +# # print(building.heating_demand[cte.YEAR][0] / 3.6e6) +# # print(building.name) +# # total_floor_area = 0 +# # for thermal_zone in building.thermal_zones_from_internal_zones: +# # total_floor_area += thermal_zone.total_floor_area +# # print(building.heating_demand[cte.YEAR][0] / (3.6e6 * total_floor_area)) -for building in city.buildings: - print(building.name) - print(building.year_of_construction) - print(building.usages_percentage) \ No newline at end of file +# for building in city.buildings: +# print(building.name) +# print(building.year_of_construction) +# print(building.usages_percentage) \ No newline at end of file diff --git a/main_results_in_geojson.py b/main_results_in_geojson.py new file mode 100644 index 00000000..ed14e54d --- /dev/null +++ b/main_results_in_geojson.py @@ -0,0 +1,176 @@ +from pathlib import Path +from scripts.ep_workflow import energy_plus_workflow +from hub.helpers.monthly_values import MonthlyValues +from hub.imports.geometry_factory import GeometryFactory +from hub.helpers.dictionaries import Dictionaries +from hub.imports.construction_factory import ConstructionFactory +from hub.imports.usage_factory import UsageFactory +from hub.imports.weather_factory import WeatherFactory +import hub.helpers.constants as cte +from hub.imports.energy_systems_factory import EnergySystemsFactory +from hub.helpers.peak_loads import PeakLoads + +import geopandas as gpd +import json +# Specify the GeoJSON file path +input_files_path = (Path(__file__).parent / 'input_files') +output_path = (Path(__file__).parent / 'out_files').resolve() +output_path.mkdir(parents=True, exist_ok=True) + +geojson_file_path = output_path / 'updated_buildings_with_all_data.geojson' +with open(geojson_file_path , 'r') as f: + building_type_data = json.load(f) + + + +# Create city object from GeoJSON file +city = GeometryFactory('geojson', + path=geojson_file_path, + height_field='maximum_roof_height', + year_of_construction_field='year_built', + function_field='building_type', + function_to_hub=Dictionaries().montreal_function_to_hub_function).city +# Enrich city data +ConstructionFactory('nrcan', city).enrich() +UsageFactory('nrcan', city).enrich() +WeatherFactory('epw', city).enrich() + +# #energy plus is not going to be processed here, as demand has been obtained before +# energy_plus_workflow(city) +percentage_data = { + 1646: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 2672.550473, "total_floor_area": 26725.50473}, + 1647: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 2653.626087, "total_floor_area": 26536.26087}, + 1648: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 1056.787496, "total_floor_area": 10567.87496}, + 1649: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 1906.620746, "total_floor_area": 19066.20746}, + 1650: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 659.1119416, "total_floor_area": 5272.895533}, + 1651: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 1167.208109, "total_floor_area": 9337.664871}, + 1652: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 1193.251653, "total_floor_area": 9546.013222}, + 1653: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 1491.722543, "total_floor_area": 11933.78035}, + 1654: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 1168.005028, "total_floor_area": 9344.040224}, + 1655: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 1264.906961, "total_floor_area": 10119.25569}, + 1656: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 1281.768818, "total_floor_area": 10254.15054}, + 1657: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 290.3886018, "total_floor_area": 2323.108814}, + 1658: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 847.5095193, "total_floor_area": 6780.076155}, + 1659: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 1115.319153, "total_floor_area": 8922.553224}, + 1660: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 469.2918062, "total_floor_area": 3754.33445}, + 1661: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 1292.298346, "total_floor_area": 10338.38677}, + 1662: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 625.7828863, "total_floor_area": 5006.263091}, + 1663: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 1876.02897, "total_floor_area": 15008.23176}, + 1664: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 1118.224781, "total_floor_area": 22364.49562}, + 1665: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 1502.787808, "total_floor_area": 30055.75617}, + 1666: {"type1_%": 0.891045711, "type2_%": 0.108954289, "type3_%": 0, "roof_area": 3038.486076, "total_floor_area": 30384.86076}, + 1667: {"type1_%": 0.8, "type2_%": 0.2, "type3_%": 0, "roof_area": 1343.832818, "total_floor_area": 13438.32818}, + 1668: {"type1_%": 0.7, "type2_%": 0.3, "type3_%": 0, "roof_area": 961.0996956, "total_floor_area": 4805.498478}, + 1669: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 489.1282111, "total_floor_area": 1956.512845}, + 1673: {"type1_%": 0.7, "type2_%": 0.3, "type3_%": 0, "roof_area": 1693.141465, "total_floor_area": 5079.424396}, + 1674: {"type1_%": 0.7, "type2_%": 0.3, "type3_%": 0, "roof_area": 3248.827576, "total_floor_area": 9746.482729}, + 1675: {"type1_%": 0.7, "type2_%": 0.3, "type3_%": 0, "roof_area": 4086.842191, "total_floor_area": 12260.52657}, + 1676: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 2786.114146, "total_floor_area": 11144.45658}, + 1677: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 5142.784184, "total_floor_area": 15428.35255}, + 1678: {"type1_%": 0.7, "type2_%": 0.3, "type3_%": 0, "roof_area": 6068.664574, "total_floor_area": 18205.99372}, + 1679: {"type1_%": 0.7, "type2_%": 0.3, "type3_%": 0, "roof_area": 5646.751407, "total_floor_area": 16940.25422}, + 1680: {"type1_%": 0.7, "type2_%": 0.3, "type3_%": 0, "roof_area": 1601.765953, "total_floor_area": 4805.297859}, + 1681: {"type1_%": 0.7, "type2_%": 0.3, "type3_%": 0, "roof_area": 9728.221797, "total_floor_area": 29184.66539}, + 1687: {"type1_%": 0.606611029, "type2_%": 0.28211422, "type3_%": 0.11127475, "roof_area": 4268.608743, "total_floor_area": 59760.52241}, + 1688: {"type1_%": 0.92, "type2_%": 0.08, "type3_%": 0, "roof_area": 2146.654828, "total_floor_area": 38639.7869}, + 1689: {"type1_%": 0.96, "type2_%": 0.04, "type3_%": 0, "roof_area": 2860.270711, "total_floor_area": 57205.41421}, + 1690: {"type1_%": 0.94, "type2_%": 0.06, "type3_%": 0, "roof_area": 2189.732519, "total_floor_area": 28466.52275}, + 1691: {"type1_%": 0.75, "type2_%": 0.25, "type3_%": 0, "roof_area": 3159.077523, "total_floor_area": 31590.77523}, +} + +def enrich_buildings_with_geojson_data (building_type_data, city): + for building in city.buildings: + for idx, feature in enumerate(building_type_data['features']): + if feature['properties']['id'] == str(building.name): + building.heating_demand[cte.HOUR] = [x *1000* cte.WATTS_HOUR_TO_JULES for x in building_type_data['features'][idx]['properties'].get('heating_demand_kWh', [0])] + building.cooling_demand[cte.HOUR] = [x *1000* cte.WATTS_HOUR_TO_JULES for x in building_type_data['features'][idx]['properties'].get('cooling_demand_kWh', [0])] + building.domestic_hot_water_heat_demand[cte.HOUR] = [x *1000* cte.WATTS_HOUR_TO_JULES for x in building_type_data['features'][idx]['properties'].get('domestic_hot_water_heat_demand_kWh', [0])] + building.appliances_electrical_demand[cte.HOUR] = [x *1000* cte.WATTS_HOUR_TO_JULES for x in building_type_data['features'][idx]['properties'].get('appliances_electrical_demand_kWh', [0])] + building.lighting_electrical_demand[cte.HOUR] = [x *1000* cte.WATTS_HOUR_TO_JULES for x in building_type_data['features'][idx]['properties'].get('lighting_electrical_demand_kWh', [0])] + building.heating_demand[cte.MONTH] = MonthlyValues.get_total_month(building.heating_demand[cte.HOUR]) + building.cooling_demand[cte.MONTH] = MonthlyValues.get_total_month(building.cooling_demand[cte.HOUR]) + building.domestic_hot_water_heat_demand[cte.MONTH] = (MonthlyValues.get_total_month(building.domestic_hot_water_heat_demand[cte.HOUR])) + building.appliances_electrical_demand[cte.MONTH] = (MonthlyValues.get_total_month(building.appliances_electrical_demand[cte.HOUR])) + building.lighting_electrical_demand[cte.MONTH] = (MonthlyValues.get_total_month(building.lighting_electrical_demand[cte.HOUR])) + building.heating_demand[cte.YEAR] = [sum(building.heating_demand[cte.MONTH])] + building.cooling_demand[cte.YEAR] = [sum(building.cooling_demand[cte.MONTH])] + building.domestic_hot_water_heat_demand[cte.YEAR] = [sum(building.domestic_hot_water_heat_demand[cte.MONTH])] + building.appliances_electrical_demand[cte.YEAR] = [sum(building.appliances_electrical_demand[cte.MONTH])] + building.lighting_electrical_demand[cte.YEAR] = [sum(building.lighting_electrical_demand[cte.MONTH])] + + + +enrich_buildings_with_geojson_data (building_type_data, city) +# for building in city.buildings: +# monthly_values = PeakLoads().peak_loads_from_hourly(building.lighting_electrical_demand[cte.HOUR]) +# building.lighting_peak_load[cte.MONTH]=[x / cte.WATTS_HOUR_TO_JULES for x in monthly_values] +# building.lighting_peak_load[cte.YEAR] = [max(monthly_values) / cte.WATTS_HOUR_TO_JULES] +# monthly_values = PeakLoads().peak_loads_from_hourly(building.appliances_electrical_demand[cte.HOUR]) +# building.appliances_electrical_demand[cte.MONTH]=[x / cte.WATTS_HOUR_TO_JULES for x in monthly_values] +# building.appliances_electrical_demand[cte.YEAR] = [max(monthly_values) / cte.WATTS_HOUR_TO_JULES] + + + + +# def to_dict(building, total_floor_area): +# return { +# 'roof_area': building.floor_area, +# 'total_floor_area': total_floor_area, +# 'year_of_construction' : building.year_of_construction, +# 'type_function':building.function, +# 'beam_kWh_per_m2': sum(building.beam[cte.HOUR])/ (3.6e6), +# 'diffuse_kWh_per_m2': sum(building.diffuse[cte.HOUR])/ (3.6e6), +# 'direct_normal_kWh_per_m2': sum(building.direct_normal[cte.HOUR])/ (3.6e6), +# 'average_storey_height_meters': building.average_storey_height, +# 'max_height_meters_meters': building.max_height, +# 'global_horizontal_kWh_per_m2': sum(building.global_horizontal[cte.HOUR])/ (3.6e6), +# 'appliances_peak_load_kW':building.appliances_peak_load[cte.YEAR][0]/ (1e3), +# 'domestic_hot_water_peak_load_kW': building.domestic_hot_water_peak_load[cte.YEAR][0]/ (1e3), +# 'heating_peak_load_kW': building.heating_peak_load[cte.YEAR][0]/ (1e3), +# 'cooling_peak_load_kW': building.cooling_peak_load[cte.YEAR][0]/ (1e3), +# 'lighting_peak_load_kW': building.lighting_peak_load[cte.YEAR][0]/ (1e3), +# 'heating_demand_kWh_per_m2' : sum(building.heating_demand[cte.HOUR])/ (3.6e6 * total_floor_area), +# 'cooling_demand_kWh_per_m2' : sum(building.cooling_demand[cte.HOUR])/ (3.6e6 * total_floor_area), +# 'domestic_hot_water_heat_demand_kWh_per_m2': sum(building.domestic_hot_water_heat_demand[cte.HOUR])/ (3.6e6 * total_floor_area), +# 'appliances_electrical_demand_kWh_per_m2':sum(building.appliances_electrical_demand[cte.HOUR])/ (3.6e6 * total_floor_area), +# 'lighting_electrical_demand_kWh_per_m2': sum(building.lighting_electrical_demand[cte.HOUR])/ (3.6e6 * total_floor_area), +# 'heating_demand_kWh': [x / (cte.WATTS_HOUR_TO_JULES * 1000) for x in building.heating_demand[cte.HOUR]], +# 'cooling_demand_kWh':[x / (cte.WATTS_HOUR_TO_JULES * 1000) for x in building.cooling_demand[cte.HOUR]], +# 'domestic_hot_water_heat_demand_kWh': [x / (cte.WATTS_HOUR_TO_JULES * 1000) for x in building.domestic_hot_water_heat_demand[cte.HOUR]], +# 'appliances_electrical_demand_kWh':[x / (cte.WATTS_HOUR_TO_JULES * 1000) for x in building.appliances_electrical_demand[cte.HOUR]], +# 'lighting_electrical_demand_kWh': [x / (cte.WATTS_HOUR_TO_JULES * 1000) for x in building.lighting_electrical_demand[cte.HOUR]] +# } +# buildings_dic={} + + +for building in city.buildings: + + total_floor_area = 0 + for thermal_zone in building.thermal_zones_from_internal_zones: + total_floor_area += thermal_zone.total_floor_area + print(building.heating_demand[cte.YEAR][0] / (3.6e6 * total_floor_area)) + building.energy_systems_archetype_name = 'system 1 gas' + + + + + +EnergySystemsFactory('montreal_custom', city).enrich() +print('test') +for building in city.buildings: + energy_systems = building.energy_systems + for energy_system in energy_systems: + generation_units = energy_system.generation_systems + if cte.HEATING in energy_system.demand_types: + for generation_unit in generation_units: + generation_unit.heat_efficiency = 0.96 + + +# for building in city.buildings: +# print(building.heating_demand[cte.YEAR][0] / 3.6e6) +# print(building.name) +# total_floor_area = 0 +# for thermal_zone in building.thermal_zones_from_internal_zones: +# total_floor_area += thermal_zone.total_floor_area +# print(building.heating_demand[cte.YEAR][0] / (3.6e6 * total_floor_area)) + diff --git a/processor.py b/processor.py index 9ebcba06..094aaac2 100644 --- a/processor.py +++ b/processor.py @@ -2,144 +2,344 @@ import json from pathlib import Path import pandas as pd import geopandas as gpd -# Specify the GeoJSON file path -input_files_path = (Path(__file__).parent / 'input_files') -geojson_file_path = input_files_path / 'Lachine_moved_existing_year_type.geojson' -#read it to use later -gdf = gpd.read_file(geojson_file_path) + + #define output path output_path = (Path(__file__).parent / 'out_files').resolve() output_path.mkdir(parents=True, exist_ok=True) # Define output folders output_folders = ['building_type', 'building_type_2', 'building_type_3'] #output paths containing energy+ results are read - -gdf_building_outputs={} - -output_paths = {} -# Create directories for the output folders -for folder in output_folders: - path = output_path / folder - path.mkdir(parents=True, exist_ok=True) - output_paths[folder] = path -# Read the resulting GeoDataFrames saved in each folder -gdf_building_outputs = {} -for folder in output_folders: - path = output_paths[folder] / 'updated_buildings.geojson' - if path.exists(): - gdf_building_outputs[folder] = gpd.read_file(path) - else: - gdf_building_outputs[folder] = gpd.GeoDataFrame() - - - - - +path1=r'C:\Users\a_gabald\PycharmProjects\summer_course_2024\out_files\building_type\updated_buildings.geojson' +path2=r'C:\Users\a_gabald\PycharmProjects\summer_course_2024\out_files\building_type_2\updated_buildings.geojson' +path3=r'C:\Users\a_gabald\PycharmProjects\summer_course_2024\out_files\building_type_3\updated_buildings.geojson' +with open(path1, 'r') as f: + building_type_data = json.load(f) +with open(path2, 'r') as f: + building_type_data2 = json.load(f) +with open(path3, 'r') as f: + building_type_data3 = json.load(f) percentage_data = { - 1646: {"type1_%": 1, "type2_%": 0, "type3_%": 0}, - 1647: {"type1_%": 1, "type2_%": 0, "type3_%": 0}, - 1648: {"type1_%": 1, "type2_%": 0, "type3_%": 0}, - 1649: {"type1_%": 1, "type2_%": 0, "type3_%": 0}, - 1650: {"type1_%": 1, "type2_%": 0, "type3_%": 0}, - 1651: {"type1_%": 1, "type2_%": 0, "type3_%": 0}, - 1652: {"type1_%": 1, "type2_%": 0, "type3_%": 0}, - 1653: {"type1_%": 1, "type2_%": 0, "type3_%": 0}, - 1654: {"type1_%": 1, "type2_%": 0, "type3_%": 0}, - 1655: {"type1_%": 1, "type2_%": 0, "type3_%": 0}, - 1656: {"type1_%": 1, "type2_%": 0, "type3_%": 0}, - 1657: {"type1_%": 1, "type2_%": 0, "type3_%": 0}, - 1658: {"type1_%": 1, "type2_%": 0, "type3_%": 0}, - 1659: {"type1_%": 1, "type2_%": 0, "type3_%": 0}, - 1660: {"type1_%": 1, "type2_%": 0, "type3_%": 0}, - 1661: {"type1_%": 1, "type2_%": 0, "type3_%": 0}, - 1662: {"type1_%": 1, "type2_%": 0, "type3_%": 0}, - 1663: {"type1_%": 1, "type2_%": 0, "type3_%": 0}, - 1664: {"type1_%": 1, "type2_%": 0, "type3_%": 0}, - 1665: {"type1_%": 1, "type2_%": 0, "type3_%": 0}, - 1666: {"type1_%": 0.891045711, "type2_%": 0.108954289, "type3_%": 0}, - 1667: {"type1_%": 0.8, "type2_%": 0.2, "type3_%": 0}, - 1668: {"type1_%": 0.666666667, "type2_%": 0.333333333, "type3_%": 0}, - 1669: {"type1_%": 1, "type2_%": 0, "type3_%": 0}, - 1673: {"type1_%": 0.666666667, "type2_%": 0.3, "type3_%": 0}, - 1674: {"type1_%": 0.666666667, "type2_%": 0.3, "type3_%": 0}, - 1675: {"type1_%": 0.666666667, "type2_%": 0.3, "type3_%": 0}, - 1676: {"type1_%": 1, "type2_%": 0, "type3_%": 0}, - 1677: {"type1_%": 1, "type2_%": 0, "type3_%": 0}, - 1678: {"type1_%": 0.666666667, "type2_%": 0.3, "type3_%": 0}, - 1679: {"type1_%": 0.666666667, "type2_%": 0.3, "type3_%": 0}, - 1680: {"type1_%": 0.666666667, "type2_%": 0.3, "type3_%": 0}, - 1681: {"type1_%": 0.666666667, "type2_%": 0.3, "type3_%": 0}, - 1687: {"type1_%": 0.606611029, "type2_%": 0.28211422, "type3_%": 0.11127475}, - 1688: {"type1_%": 0.92, "type2_%": 0.1, "type3_%": 0}, - 1689: {"type1_%": 0.96, "type2_%": 0, "type3_%": 0}, - 1690: {"type1_%": 0.94, "type2_%": 0.1, "type3_%": 0}, - 1691: {"type1_%": 0.75, "type2_%": 0.3, "type3_%": 0}, + 1646: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 2672.550473, "total_floor_area": 26725.50473}, + 1647: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 2653.626087, "total_floor_area": 26536.26087}, + 1648: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 1056.787496, "total_floor_area": 10567.87496}, + 1649: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 1906.620746, "total_floor_area": 19066.20746}, + 1650: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 659.1119416, "total_floor_area": 5272.895533}, + 1651: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 1167.208109, "total_floor_area": 9337.664871}, + 1652: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 1193.251653, "total_floor_area": 9546.013222}, + 1653: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 1491.722543, "total_floor_area": 11933.78035}, + 1654: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 1168.005028, "total_floor_area": 9344.040224}, + 1655: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 1264.906961, "total_floor_area": 10119.25569}, + 1656: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 1281.768818, "total_floor_area": 10254.15054}, + 1657: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 290.3886018, "total_floor_area": 2323.108814}, + 1658: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 847.5095193, "total_floor_area": 6780.076155}, + 1659: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 1115.319153, "total_floor_area": 8922.553224}, + 1660: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 469.2918062, "total_floor_area": 3754.33445}, + 1661: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 1292.298346, "total_floor_area": 10338.38677}, + 1662: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 625.7828863, "total_floor_area": 5006.263091}, + 1663: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 1876.02897, "total_floor_area": 15008.23176}, + 1664: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 1118.224781, "total_floor_area": 22364.49562}, + 1665: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 1502.787808, "total_floor_area": 30055.75617}, + 1666: {"type1_%": 0.891045711, "type2_%": 0.108954289, "type3_%": 0, "roof_area": 3038.486076, "total_floor_area": 30384.86076}, + 1667: {"type1_%": 0.8, "type2_%": 0.2, "type3_%": 0, "roof_area": 1343.832818, "total_floor_area": 13438.32818}, + 1668: {"type1_%": 0.7, "type2_%": 0.3, "type3_%": 0, "roof_area": 961.0996956, "total_floor_area": 4805.498478}, + 1669: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 489.1282111, "total_floor_area": 1956.512845}, + 1673: {"type1_%": 0.7, "type2_%": 0.3, "type3_%": 0, "roof_area": 1693.141465, "total_floor_area": 5079.424396}, + 1674: {"type1_%": 0.7, "type2_%": 0.3, "type3_%": 0, "roof_area": 3248.827576, "total_floor_area": 9746.482729}, + 1675: {"type1_%": 0.7, "type2_%": 0.3, "type3_%": 0, "roof_area": 4086.842191, "total_floor_area": 12260.52657}, + 1676: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 2786.114146, "total_floor_area": 11144.45658}, + 1677: {"type1_%": 1, "type2_%": 0, "type3_%": 0, "roof_area": 5142.784184, "total_floor_area": 15428.35255}, + 1678: {"type1_%": 0.7, "type2_%": 0.3, "type3_%": 0, "roof_area": 6068.664574, "total_floor_area": 18205.99372}, + 1679: {"type1_%": 0.7, "type2_%": 0.3, "type3_%": 0, "roof_area": 5646.751407, "total_floor_area": 16940.25422}, + 1680: {"type1_%": 0.7, "type2_%": 0.3, "type3_%": 0, "roof_area": 1601.765953, "total_floor_area": 4805.297859}, + 1681: {"type1_%": 0.7, "type2_%": 0.3, "type3_%": 0, "roof_area": 9728.221797, "total_floor_area": 29184.66539}, + 1687: {"type1_%": 0.606611029, "type2_%": 0.28211422, "type3_%": 0.11127475, "roof_area": 4268.608743, "total_floor_area": 59760.52241}, + 1688: {"type1_%": 0.92, "type2_%": 0.08, "type3_%": 0, "roof_area": 2146.654828, "total_floor_area": 38639.7869}, + 1689: {"type1_%": 0.96, "type2_%": 0.04, "type3_%": 0, "roof_area": 2860.270711, "total_floor_area": 57205.41421}, + 1690: {"type1_%": 0.94, "type2_%": 0.06, "type3_%": 0, "roof_area": 2189.732519, "total_floor_area": 28466.52275}, + 1691: {"type1_%": 0.75, "type2_%": 0.25, "type3_%": 0, "roof_area": 3159.077523, "total_floor_area": 31590.77523}, } # Define a function to calculate new demands based on percentages -def calculate_demands(building_id, percentages, gdf_building_type, gdf_building_type_2, gdf_building_type_3): +def calculate_demands(building_id, percentages, building_type_data, building_type_data2, building_type_data3): new_demands = {} - for demand_type in [ - 'heating_demand_kWh', 'cooling_demand_kWh', - 'domestic_hot_water_heat_demand_kWh', - 'appliances_electrical_demand_kWh', - 'lighting_electrical_demand_kWh']: - demand_type_1 = gdf_building_type.loc[gdf_building_type['id'] == building_id, demand_type].values[ - 0] if not gdf_building_type.empty else 0 - demand_type_2 = gdf_building_type_2.loc[gdf_building_type_2['id'] == building_id, demand_type].values[ - 0] if not gdf_building_type_2.empty else 0 - demand_type_3 = gdf_building_type_3.loc[gdf_building_type_3['id'] == building_id, demand_type].values[ - 0] if not gdf_building_type_3.empty else 0 - new_demand = ( - demand_type_1 * percentages['type1_%'] + - demand_type_2 * percentages['type2_%'] + - demand_type_3 * percentages['type3_%'] - ) - new_demands[demand_type] = new_demand + for idx, feature in enumerate(building_type_data['features']): + if feature['properties']['id'] == str(building_id): + for demand_type in [ + 'heating_demand_kWh', 'cooling_demand_kWh', + 'domestic_hot_water_heat_demand_kWh', + 'appliances_electrical_demand_kWh', + 'lighting_electrical_demand_kWh']: + + demand_list_1 = building_type_data['features'][idx]['properties'].get(demand_type, [0]) + + # Initialize demand lists for type 2 and type 3 with zeros + demand_list_2 = [0] * len(demand_list_1) + demand_list_3 = [0] * len(demand_list_1) + + # Update demand_list_2 if percentages['type2_%'] is not zero + if percentages['type2_%'] != 0: + for feature2 in building_type_data2['features']: + if feature2['properties']['id'] == str(building_id): + demand_list_2 = feature2['properties'].get(demand_type, [0]) + break + + # Update demand_list_3 if percentages['type3_%'] is not zero + if percentages['type3_%'] != 0: + for feature3 in building_type_data3['features']: + if feature3['properties']['id'] == str(building_id): + demand_list_3 = feature3['properties'].get(demand_type, [0]) + break + + # Ensure the demand lists are the same length by padding with zeros if necessary + max_len = max(len(demand_list_1), len(demand_list_2), len(demand_list_3)) + demand_list_1 += [0] * (max_len - len(demand_list_1)) + demand_list_2 += [0] * (max_len - len(demand_list_2)) + demand_list_3 += [0] * (max_len - len(demand_list_3)) + + new_demand_list = [ + demand_list_1[i] * percentages['type1_%'] + + demand_list_2[i] * percentages['type2_%'] + + demand_list_3[i] * percentages['type3_%'] + for i in range(max_len) + ] + new_demands[demand_type] = new_demand_list + return new_demands -# Process each building in the GeoJSON -for idx, feature in gdf.iterrows(): - building_id = feature['id'] # Adjust this based on your GeoJSON structure - if building_id == 1673: - percentages = percentage_data[building_id] - print(percentages) - new_demands = calculate_demands(building_id, percentages, - gdf_building_outputs.get('building_type', gpd.GeoDataFrame()), - gdf_building_outputs.get('building_type_2', gpd.GeoDataFrame()), - gdf_building_outputs.get('building_type_3', gpd.GeoDataFrame())) - print(new_demands) - # Update the properties of the feature - gdf.at[idx, 'heating_demand_kWh'] = new_demands['heating_demand_kWh'] - gdf.at[idx, 'cooling_demand_kWh'] = new_demands['cooling_demand_kWh'] - gdf.at[idx, 'domestic_hot_water_heat_demand_kWh'] = new_demands['domestic_hot_water_heat_demand_kWh'] - gdf.at[idx, 'appliances_electrical_demand_kWh'] = new_demands['appliances_electrical_demand_kWh'] - gdf.at[idx, 'lighting_electrical_demand_kWh'] = new_demands['lighting_electrical_demand_kWh'] +# Calculate demand per square meter for each building +def calculate_demand_per_m2(building_type_data, building_type_data2, building_type_data3, percentage_data): + results = {} + + for building_id, percentages in percentage_data.items(): + print(percentages ["total_floor_area"]) + new_demands = calculate_demands(building_id, percentages, building_type_data, building_type_data2, + building_type_data3) + + for idx, feature in enumerate(building_type_data['features']): + if feature['properties']['id'] == str(building_id): + total_floor_area = percentages ["total_floor_area"] + + results[building_id] = { + 'roof_area':percentages["roof_area"], + 'total_floor_area': percentages["total_floor_area"], + 'heating_demand_kWh':new_demands.get('heating_demand_kWh', []), + 'cooling_demand_kWh':new_demands.get('cooling_demand_kWh', []), + 'domestic_hot_water_heat_demand_kWh': new_demands.get('domestic_hot_water_heat_demand_kWh', []), + 'appliances_electrical_demand_kWh': new_demands.get('appliances_electrical_demand_kWh', []), + 'lighting_electrical_demand_kWh': new_demands.get('lighting_electrical_demand_kWh', []), + 'heating_demand_kWh_per_m2': sum(new_demands.get('heating_demand_kWh', [])) / total_floor_area, + 'cooling_demand_kWh_per_m2': sum(new_demands.get('cooling_demand_kWh', [])) / total_floor_area, + 'domestic_hot_water_heat_demand_kWh_per_m2': sum( + new_demands.get('domestic_hot_water_heat_demand_kWh', [])) / total_floor_area, + 'appliances_electrical_demand_kWh_per_m2': sum( + new_demands.get('appliances_electrical_demand_kWh', [])) / total_floor_area, + 'lighting_electrical_demand_kWh_per_m2': sum( + new_demands.get('lighting_electrical_demand_kWh', [])) / total_floor_area, + 'appliances_peak_load_kW': max( + new_demands.get('appliances_electrical_demand_kWh', [])), + 'domestic_hot_water_peak_load_kW': max( + new_demands.get('domestic_hot_water_heat_demand_kWh', [])) , + 'heating_peak_load_kW': max(new_demands.get('heating_demand_kWh', [])), + 'cooling_peak_load_kW': max(new_demands.get('cooling_demand_kWh', [])), + 'lighting_peak_load_kW': max( + new_demands.get('lighting_electrical_demand_kWh', [])), + } + + return results + +# Example usage +new_demands = calculate_demand_per_m2(building_type_data, building_type_data2, building_type_data3, percentage_data) +# for building_id, demand_data in results.items(): +# print(f"Building ID: {building_id}") +# for demand_type, value in demand_data.items(): +# print(f" {demand_type}: {value}") +# new_demands = {} +# for building_id, percentages in percentage_data.items(): +# print(building_id) +# new_demands[building_id] = calculate_demands(building_id, percentages, building_type_data, building_type_data2, building_type_data3) + +# # +import pandas as pd + +# Export the DataFrame to an Excel file +output_path = r'C:\Users\a_gabald\PycharmProjects\summer_course_2024\out_files\new_demands.xlsx' + +# Create an Excel writer object +with pd.ExcelWriter(output_path, engine='xlsxwriter') as writer: + for building_id, demands in new_demands.items(): + # Convert demands to a DataFrame + df_demands = pd.DataFrame(demands) + # Convert building_id to string and check its length + sheet_name = str(building_id) + if len(sheet_name) > 31: + sheet_name = sheet_name[:31] # Truncate to 31 characters if necessary + # Write the DataFrame to a specific sheet named after the building_id + df_demands.to_excel(writer, sheet_name=sheet_name, index=False) + + +import matplotlib.pyplot as plt +import numpy as np + +# Assume calculate_demand_per_m2 and results have been computed as before + +def extract_demands(data, building_id, demand_type): + for feature in data['features']: + if feature['properties']['id'] == str(building_id): + return feature['properties'].get(demand_type, [0]) + return 0 + +# Create a list of building IDs +building_ids = list(percentage_data.keys()) + +# Define the demand types to be plotted +demand_types = [ + 'heating_demand_kWh_per_m2', + 'cooling_demand_kWh_per_m2', + 'domestic_hot_water_heat_demand_kWh_per_m2', + 'appliances_electrical_demand_kWh_per_m2', + 'lighting_electrical_demand_kWh_per_m2' +] + +# Initialize lists to store values for plotting +new_demands_values = {demand_type: [] for demand_type in demand_types} +building_type_data_values = {demand_type: [] for demand_type in demand_types} +building_type_data2_values = {demand_type: [] for demand_type in demand_types} +building_type_data3_values = {demand_type: [] for demand_type in demand_types} + +# Populate the lists with the corresponding values +for building_id in building_ids: + for demand_type in demand_types: + new_demands_values[demand_type].append(new_demands[building_id][demand_type]) + building_type_data_values[demand_type].append(extract_demands(building_type_data, building_id, demand_type)) + building_type_data2_values[demand_type].append(extract_demands(building_type_data2, building_id, demand_type)) + building_type_data3_values[demand_type].append(extract_demands(building_type_data3, building_id, demand_type)) + +# Plot the values for each demand type +for demand_type in demand_types: + x = np.arange(len(building_ids)) # the label locations + width = 0.2 # the width of the bars + + fig, ax = plt.subplots(figsize=(15, 7)) + + ax.bar(x - 1.5 * width, new_demands_values[demand_type], width, label='New Demands') + ax.bar(x - 0.5 * width, building_type_data_values[demand_type], width, label='Old Demands - Type 1') + ax.bar(x + 0.5 * width, building_type_data2_values[demand_type], width, label='Old Demands - Type 2') + ax.bar(x + 1.5 * width, building_type_data3_values[demand_type], width, label='Old Demands - Type 3') + + # Add some text for labels, title, and custom x-axis tick labels, etc. + ax.set_xlabel('Building ID') + ax.set_ylabel(f'{demand_type} (kWh/m²)') + ax.set_title(f'Comparison of {demand_type} by Building ID') + ax.set_xticks(x) + ax.set_xticklabels(building_ids, rotation=90) + ax.legend() + + fig.tight_layout() + + plt.show() + + + + +# Load the existing GeoJSON file +geojson_file_path =r'C:\Users\a_gabald\PycharmProjects\summer_course_2024\out_files\building_type\updated_buildings.geojson' # Replace with the actual path +with open(geojson_file_path, 'r') as f: + geojson_data = json.load(f) + +# Define output path +output_path = (Path(__file__).parent / 'out_files').resolve() +output_path.mkdir(parents=True, exist_ok=True) + +# Load additional data from the CSV files +solar_radiation_tilted_path = r'C:\Users\a_gabald\PycharmProjects\summer_course_2024\out_files\solar_radiation_tilted_selected_buildings.csv' +solar_radiation_horizontal_path = r'C:\Users\a_gabald\PycharmProjects\summer_course_2024\out_files\solar_radiation_horizontal_selected_buildings.csv' + + +import csv + +def load_solar_data(file_path, key_name): + solar_data = {} + with open(file_path, 'r') as f: + reader = csv.reader(f) + headers = next(reader)[1:] # Skip the first header and get building IDs + + for row in reader: + for building_id, solar_value in zip(headers, row[1:]): # Skip the first column in each row + building_id = int(building_id) + solar_value = float(solar_value) + if building_id not in solar_data: + solar_data[building_id] = {} + if key_name not in solar_data[building_id]: + solar_data[building_id][key_name] = [] + solar_data[building_id][key_name].append(solar_value) + return solar_data + + +solar_radiation_tilted = load_solar_data(solar_radiation_tilted_path, 'solar_radiation_tilted') +solar_radiation_horizontal = load_solar_data(solar_radiation_horizontal_path, 'solar_radiation_horizontal') + +# Merge the solar data into a single dictionary +solar_data = {} +for building_id in set(solar_radiation_tilted.keys()).union(solar_radiation_horizontal.keys()): + solar_data[building_id] = {} + if building_id in solar_radiation_tilted: + solar_data[building_id]['solar_radiation_tilted'] = solar_radiation_tilted[building_id][ + 'solar_radiation_tilted'] + if building_id in solar_radiation_horizontal: + solar_data[building_id]['solar_radiation_horizontal'] = solar_radiation_horizontal[building_id][ + 'solar_radiation_horizontal'] + +# Example data for results (use actual results data in practice) +results = { + 1646: { + "appliances_peak_load_kW": 269.020198862769, + "domestic_hot_water_peak_load_kW": 1477.6420222203596, + "heating_peak_load_kW": 1650.4097261870008, + "cooling_peak_load_kW": 1441.1027982978985, + "lighting_peak_load_kW": 295.92221874904584, + "heating_demand_kWh_per_m2": 40.4922413088911, + "cooling_demand_kWh_per_m2": 20.33948801154316, + "domestic_hot_water_heat_demand_kWh_per_m2": 60.25215210051923, + "appliances_electrical_demand_kWh_per_m2": 19.352038723954898, + "lighting_electrical_demand_kWh_per_m2": 11.246090428260413, + } + # Add similar dictionaries for other building IDs +} + +# Update GeoJSON with percentage data, results, and solar data +for feature in geojson_data['features']: + building_id = int(feature['properties']['id']) + + # Update with percentage data + if building_id in percentage_data: + for key, value in percentage_data[building_id].items(): + feature['properties'][key] = value + + # Update with results data + if building_id in new_demands: + for key, value in new_demands[building_id].items(): + feature['properties'][key] = value + + # Update with solar data + if building_id in solar_data: + for key, value in solar_data[building_id].items(): + feature['properties'][key] = value + # Calculate and add the sums + feature['properties']['sum_solar_radiation_tilted_kWh_per_m2'] = sum(solar_data[building_id]['solar_radiation_tilted']) / 3.6e6 + feature['properties']['sum_solar_radiation_horizontal_kWh_per_m2'] = sum(solar_data[building_id]['solar_radiation_horizontal']) / 3.6e6 + # Add 8760 arrays divided by 3.6e6 + feature['properties']['solar_radiation_tilted_kWh_per_m2'] = [value / 3.6e6 for value in solar_data[building_id]['solar_radiation_tilted']] + feature['properties']['solar_radiation_horizontal_kWh_per_m2'] = [value / 3.6e6 for value in solar_data[building_id]['solar_radiation_horizontal']] + +# Save the updated GeoJSON data to a new file +updated_geojson_file_path = output_path / 'updated_buildings_with_all_data.geojson' +with open(updated_geojson_file_path, 'w') as f: + json.dump(geojson_data, f) + +print(f"Updated GeoJSON data saved to {updated_geojson_file_path}") -print('test') - # - # if building_id in percentage_data: - # percentages = percentage_data[building_id] - # new_demands = calculate_demands(building_id, percentages, - # gdf_building_outputs.get('building_type', gpd.GeoDataFrame()), - # gdf_building_outputs.get('building_type_2', gpd.GeoDataFrame()), - # gdf_building_outputs.get('building_type_3', gpd.GeoDataFrame())) - # - # # Update the properties of each feature - # gdf.at[idx, 'heating_demand_kWh'] = new_demands['heating_demand_kWh'] - # gdf.at[idx, 'cooling_demand_kWh'] = new_demands['cooling_demand_kWh'] - # gdf.at[idx, 'domestic_hot_water_heat_demand_kWh'] = new_demands['domestic_hot_water_heat_demand_kWh'] - # gdf.at[idx, 'appliances_electrical_demand_kWh'] = new_demands['appliances_electrical_demand_kWh'] - # gdf.at[idx, 'lighting_electrical_demand_kWh'] = new_demands['lighting_electrical_demand_kWh'] - # - # # Save the updated GeoDataFrame to the appropriate folder - # for folder, key in zip(output_folders, ['type1_%', 'type2_%', 'type3_%']): - # if percentages[key] > 0: - # output_gdf = gdf_building_outputs[folder] - # output_gdf = output_gdf.append(gdf.iloc[[idx]], ignore_index=True) - # output_gdf.to_file(output_paths[folder] / 'buildings.geojson', driver='GeoJSON') - #