Compare commits

...

21 Commits

Author SHA1 Message Date
ae981362d8 feature: summer school analysis 2024-08-16 09:04:35 -04:00
Majid Rezaei
1999449738 feature: add converting to csv to simultaneity factor calculations 2024-08-16 09:04:15 -04:00
Majid Rezaei
7a1a3fbef1 feature: process road and building geojson files 2024-08-16 09:04:05 -04:00
Majid Rezaei
05b45328aa feature: add district heating network creator 2024-08-16 09:03:53 -04:00
Majid Rezaei
098c9aa338 feature: add simultinity factor calculations 2024-08-16 09:03:28 -04:00
9af87fe482 feature: add district heating network sizing workflow
Reviewed-on: https://nextgenerations-cities.encs.concordia.ca/gitea/s_ranjbar/energy_system_modelling_workflow/pulls/18
2024-08-15 15:50:16 -04:00
eb26c48627 feature: add pipe sizing to dhn analysis 2024-08-15 15:44:22 -04:00
2ca52c157a fix: replace id with name in node attributes 2024-08-12 12:30:26 -04:00
62c70b9c9f feature: add dhn factory to enrich graph with city.buildings 2024-08-12 12:30:16 -04:00
a62f5e6f38 test: add jupyter notebook for some tests 2024-08-12 12:30:16 -04:00
6deffa9323 chore: fix indentation and change building id to name 2024-08-12 12:30:16 -04:00
c046eacc63 chore: fixing some bugs in the pv assessment 2024-08-12 12:30:16 -04:00
05b9a42672 chore: changing building_id to building_name in dhn generator 2024-08-12 12:30:16 -04:00
90a7f5648b (WIP) feature: enrich graph with building demand 2024-08-12 12:30:16 -04:00
4e75024817 feature: update dhn generator with the parent repo 2024-08-12 12:30:16 -04:00
904fe91e5a feature: add directory manager 2024-08-12 12:29:56 -04:00
Majid Rezaei
d2e20312b2 feature: add district heating network creator 2024-08-12 12:29:18 -04:00
Majid Rezaei
74cf47e3e1 feature: add simultinity factor calculations 2024-08-12 12:29:18 -04:00
1a43e65992 Merge pull request 'optimization' (#17) from optimization into main
Reviewed-on: https://nextgenerations-cities.encs.concordia.ca/gitea/s_ranjbar/energy_system_modelling_workflow/pulls/17
2024-08-08 12:26:48 -04:00
3b5e12efaf feat: started optimization but had to stop to clean simulation models 2024-08-08 12:21:56 -04:00
435fc4c679 fix: small bug in archetype 1 simulation is fixed 2024-08-01 14:43:49 -04:00
28 changed files with 6596 additions and 209 deletions

111
district_heating_network.py Normal file
View File

@ -0,0 +1,111 @@
from scripts.district_heating_network.directory_manager import DirectoryManager
import subprocess
from scripts.ep_run_enrich import energy_plus_workflow
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
from hub.imports.results_factory import ResultFactory
from scripts.energy_system_retrofit_report import EnergySystemRetrofitReport
from scripts.geojson_creator import process_geojson
from scripts import random_assignation
from hub.imports.energy_systems_factory import EnergySystemsFactory
from scripts.energy_system_sizing import SystemSizing
from scripts.solar_angles import CitySolarAngles
from scripts.pv_sizing_and_simulation import PVSizingSimulation
from scripts.energy_system_retrofit_results import consumption_data, cost_data
from scripts.energy_system_sizing_and_simulation_factory import EnergySystemsSimulationFactory
from scripts.costs.cost import Cost
from scripts.costs.constants import SKIN_RETROFIT_AND_SYSTEM_RETROFIT_AND_PV, SYSTEM_RETROFIT_AND_PV, CURRENT_STATUS
import hub.helpers.constants as cte
from hub.exports.exports_factory import ExportsFactory
from scripts.pv_feasibility import pv_feasibility
import matplotlib.pyplot as plt
import numpy as np
from scripts.district_heating_network.district_heating_network_creator import DistrictHeatingNetworkCreator
from scripts.district_heating_network.district_heating_factory import DistrictHeatingFactory
import json
#%% --------------------------------------------------------------------------------------------------------------------
# Manage File Path
base_path = "./"
dir_manager = DirectoryManager(base_path)
# Input files directory
input_files_path = dir_manager.create_directory('input_files')
geojson_file_path = input_files_path / 'output_buildings.geojson'
pipe_data_file = input_files_path / 'pipe_data.json'
# Output files directory
output_path = dir_manager.create_directory('out_files')
# Subdirectories for output files
energy_plus_output_path = dir_manager.create_directory('out_files/energy_plus_outputs')
simulation_results_path = dir_manager.create_directory('out_files/simulation_results')
sra_output_path = dir_manager.create_directory('out_files/sra_outputs')
cost_analysis_output_path = dir_manager.create_directory('out_files/cost_analysis')
#%% --------------------------------------------------------------------------------------------------------------------
# Area Under Study
location = [45.4934614681437, -73.57982834742518]
#%% --------------------------------------------------------------------------------------------------------------------
# Create geojson of buildings
process_geojson(x=location[1], y=location[0], diff=0.001)
#%% --------------------------------------------------------------------------------------------------------------------
# Create ciry and run energyplus workflow
city = GeometryFactory(file_type='geojson',
path=geojson_file_path,
height_field='height',
year_of_construction_field='year_of_construction',
function_field='function',
function_to_hub=Dictionaries().montreal_function_to_hub_function).city
ConstructionFactory('nrcan', city).enrich()
UsageFactory('nrcan', city).enrich()
WeatherFactory('epw', city).enrich()
# SRA
ExportsFactory('sra', city, output_path).export()
sra_path = (output_path / f'{city.name}_sra.xml').resolve()
subprocess.run(['sra', str(sra_path)])
ResultFactory('sra', city, output_path).enrich()
# EP Workflow
energy_plus_workflow(city, energy_plus_output_path)
#%% --------------------------------------------------------------------------------------------------------------------
# District Heating Network Creator
central_plant_locations = [(-73.57812571080625, 45.49499447346277)] # Add at least one location
roads_file = "./input_files/roads.json"
dhn_creator = DistrictHeatingNetworkCreator(geojson_file_path, roads_file, central_plant_locations)
network_graph = dhn_creator.run()
#%% --------------------------------------------------------------------------------------------------------------------
# Pipe and pump sizing
with open(pipe_data_file, 'r') as f:
pipe_data = json.load(f)
factory = DistrictHeatingFactory(
city=city,
graph=network_graph,
supply_temperature=80 + 273, # in Kelvin
return_temperature=60 + 273, # in Kelvin
simultaneity_factor=0.9
)
factory.enrich()
factory.sizing()
factory.calculate_diameters_and_costs(pipe_data)
pipe_groups, total_cost = factory.analyze_costs()
# Save the pipe groups with total costs to a CSV file
factory.save_pipe_groups_to_csv('pipe_groups.csv')
#%% --------------------------------------------------------------------------------------------------------------------

View File

@ -92,9 +92,8 @@ for building in city.buildings:
fuel_tariffs=['Electricity-D', 'Gas-Energir']).life_cycle
lcc_dataframe.to_csv(cost_analysis_output_path / f'{building.name}_retrofitted_lcc.csv')
retrofitted_life_cycle_cost[f'{building.name}'] = cost_data(building, lcc_dataframe, cost_retrofit_scenario)
for i in range(12):
dhw_consumption = 0
for building in city.buildings:
dhw_consumption += building.domestic_hot_water_consumption[cte.MONTH][i] / 3.6e6
EnergySystemRetrofitReport(city, output_path, 'PV Implementation and System Retrofit',
current_status_energy_consumption, retrofitted_energy_consumption,
current_status_life_cycle_cost, retrofitted_life_cycle_cost).create_report()

View File

@ -0,0 +1,81 @@
{
"type": "FeatureCollection",
"name": "lachine_group_mach_buildings",
"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },
"features": [
{ "type": "Feature", "properties": { "id": 1 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.665576136530092, 45.435517165119393 ], [ -73.665576136530092, 45.435901290585491 ], [ -73.665308918814546, 45.435901290585491 ], [ -73.665308918814546, 45.435517165119393 ], [ -73.665576136530092, 45.435517165119393 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 2 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.665576136530092, 45.43643906623803 ], [ -73.665576136530092, 45.436936759233234 ], [ -73.665302238371666, 45.436936759233234 ], [ -73.665302238371666, 45.43643906623803 ], [ -73.665576136530092, 45.43643906623803 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 3 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.665158608849552, 45.436672881739128 ], [ -73.665158608849552, 45.436839892811349 ], [ -73.664574070096791, 45.436839892811349 ], [ -73.664574070096791, 45.436672881739128 ], [ -73.665158608849552, 45.436672881739128 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 4 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.664821246483683, 45.436512551109814 ], [ -73.664821246483683, 45.43657434520653 ], [ -73.664590771204018, 45.43657434520653 ], [ -73.664590771204018, 45.436512551109814 ], [ -73.664821246483683, 45.436512551109814 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 5 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.664816236151509, 45.436448251847004 ], [ -73.664816236151509, 45.43650253044548 ], [ -73.664592441314738, 45.43650253044548 ], [ -73.664592441314738, 45.436448251847004 ], [ -73.664816236151509, 45.436448251847004 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 6 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.664815401096149, 45.436378107196674 ], [ -73.664815401096149, 45.43643489096123 ], [ -73.664594111425458, 45.43643489096123 ], [ -73.664594111425458, 45.436378107196674 ], [ -73.664815401096149, 45.436378107196674 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 7 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.664814566040789, 45.436312972878511 ], [ -73.664814566040789, 45.436370591698427 ], [ -73.664594111425458, 45.436370591698427 ], [ -73.664594111425458, 45.436312972878511 ], [ -73.664814566040789, 45.436312972878511 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 8 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.664816236151509, 45.436248673615708 ], [ -73.664816236151509, 45.436299611992737 ], [ -73.664592441314738, 45.436299611992737 ], [ -73.664592441314738, 45.436248673615708 ], [ -73.664816236151509, 45.436248673615708 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 9 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.664815401096149, 45.436177693910018 ], [ -73.664815401096149, 45.436235312729927 ], [ -73.664592441314738, 45.436235312729927 ], [ -73.664592441314738, 45.436177693910018 ], [ -73.664815401096149, 45.436177693910018 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 10 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.664813730985429, 45.436109219370408 ], [ -73.664813730985429, 45.436169343356404 ], [ -73.664593276370098, 45.436169343356404 ], [ -73.664593276370098, 45.436109219370408 ], [ -73.664813730985429, 45.436109219370408 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 11 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.665584487083734, 45.436100868816794 ], [ -73.665584487083734, 45.43628124077479 ], [ -73.664913102573422, 45.43628124077479 ], [ -73.664913102573422, 45.436100868816794 ], [ -73.665584487083734, 45.436100868816794 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 11 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.66557947675156, 45.43537604076338 ], [ -73.66529722803952, 45.435372700541933 ], [ -73.665293887818066, 45.434841605332281 ], [ -73.665582816973, 45.434661233374285 ], [ -73.66557947675156, 45.43537604076338 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 12 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.66516695940318, 45.435753485786591 ], [ -73.66516695940318, 45.435917156637359 ], [ -73.664530647218029, 45.435917156637359 ], [ -73.664530647218029, 45.435753485786591 ], [ -73.66516695940318, 45.435753485786591 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 13 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.664857988919579, 45.435593155157257 ], [ -73.664587430982593, 45.435591485046537 ], [ -73.664589101093313, 45.435324267330991 ], [ -73.664857988919579, 45.435157256258769 ], [ -73.664857988919579, 45.435593155157257 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 14 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.665409960513287, 45.434485871748457 ], [ -73.665227918444572, 45.434611130052616 ], [ -73.664611647588089, 45.434125127832466 ], [ -73.664788679324644, 45.434004879860467 ], [ -73.665409960513287, 45.434485871748457 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 15 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.665122701469073, 45.434667913817172 ], [ -73.664730225449361, 45.434928451089831 ], [ -73.6645598741557, 45.434796512342778 ], [ -73.664954020286132, 45.434537645180839 ], [ -73.665122701469073, 45.434667913817172 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 16 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.664749431722669, 45.434258736690239 ], [ -73.66469264795812, 45.434303829679735 ], [ -73.664553193712806, 45.434181911597015 ], [ -73.664611647588089, 45.43413598355216 ], [ -73.664749431722669, 45.434258736690239 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 17 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.664679287072332, 45.434305499790462 ], [ -73.664619998141703, 45.434352262890677 ], [ -73.664486389283923, 45.434232014918685 ], [ -73.664543173048472, 45.434189427095269 ], [ -73.664679287072332, 45.434305499790462 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 18 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.664606637255915, 45.434355603112124 ], [ -73.664547348325286, 45.434399025990899 ], [ -73.664409564190706, 45.434278778018907 ], [ -73.664464677844535, 45.434234520084765 ], [ -73.664606637255915, 45.434355603112124 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 19 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.664533152384152, 45.434401531156986 ], [ -73.664478038730309, 45.434439943703595 ], [ -73.664334409208209, 45.434324706063762 ], [ -73.664396203304932, 45.434279613074267 ], [ -73.664533152384152, 45.434401531156986 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 20 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.664464677844535, 45.434442448869675 ], [ -73.664405388913892, 45.434486706803817 ], [ -73.664265099613232, 45.434367293887178 ], [ -73.664323553488515, 45.434325541119122 ], [ -73.664464677844535, 45.434442448869675 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 21 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.664389522862038, 45.434490047025257 ], [ -73.664336914374289, 45.434531799793312 ], [ -73.664187439464655, 45.4344140569874 ], [ -73.664248398506018, 45.434373139274705 ], [ -73.664389522862038, 45.434490047025257 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 21 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.664316873045621, 45.434532634848672 ], [ -73.664264264557872, 45.434576057727455 ], [ -73.664121470091132, 45.434464160309062 ], [ -73.664179088911041, 45.434421572485647 ], [ -73.664316873045621, 45.434532634848672 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 22 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.664525636885912, 45.435077090944098 ], [ -73.663657179310391, 45.435634907925305 ], [ -73.663523570452611, 45.435528020839087 ], [ -73.664385347585252, 45.434956842972106 ], [ -73.664525636885912, 45.435077090944098 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 23 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.664248398506032, 45.434890038543216 ], [ -73.664098088541039, 45.434996925629434 ], [ -73.663747365289382, 45.434729707913888 ], [ -73.663901015475815, 45.434632841492004 ], [ -73.664248398506032, 45.434890038543216 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 24 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.663470126909502, 45.4355213403962 ], [ -73.663293095172946, 45.435621547039531 ], [ -73.662895608821074, 45.435224060687652 ], [ -73.663089341664843, 45.435087111608432 ], [ -73.663470126909502, 45.4355213403962 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 26 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.663733169348234, 45.434914463912534 ], [ -73.663676385583685, 45.43495705173595 ], [ -73.663538601449105, 45.434849329594364 ], [ -73.663588704770774, 45.434804236604869 ], [ -73.663733169348234, 45.434914463912534 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 27 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.663665529863991, 45.43495872184667 ], [ -73.663602900711908, 45.435004649891532 ], [ -73.663461776355874, 45.434891082362419 ], [ -73.663518560120437, 45.434848494539004 ], [ -73.663665529863991, 45.43495872184667 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 28 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.663592880047574, 45.435007990112979 ], [ -73.663534426172291, 45.435049742881034 ], [ -73.663395806982351, 45.434937845462642 ], [ -73.66345008558082, 45.434896092694586 ], [ -73.663592880047574, 45.435007990112979 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 29 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.663516890009717, 45.435051412991754 ], [ -73.663464281521968, 45.43509233070445 ], [ -73.663316476723054, 45.434978763175337 ], [ -73.663381611041217, 45.434937010407282 ], [ -73.663516890009717, 45.435051412991754 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 30 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.66344758041474, 45.43509483587053 ], [ -73.663389126539457, 45.435138258749312 ], [ -73.663248002183437, 45.43502302110948 ], [ -73.66330645605872, 45.434979598230697 ], [ -73.66344758041474, 45.43509483587053 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 31 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.663374930598323, 45.435141598970752 ], [ -73.663317311778414, 45.435184186794174 ], [ -73.6631736822563, 45.435074794541869 ], [ -73.663237146463743, 45.435028866497007 ], [ -73.663374930598323, 45.435141598970752 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 33 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.663299775615826, 45.435188362070974 ], [ -73.663253012515597, 45.435225939562223 ], [ -73.66312775421143, 45.435100681258064 ], [ -73.663164496647326, 45.435074794541869 ], [ -73.663299775615826, 45.435188362070974 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 34 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.664583255705864, 45.433868139545069 ], [ -73.664172408468204, 45.434123666485561 ], [ -73.664018758281756, 45.433881500430843 ], [ -73.664464677844592, 45.433757912237397 ], [ -73.664583255705864, 45.433868139545069 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 36 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.663997046842368, 45.434095274603287 ], [ -73.663908530974098, 45.434299028111397 ], [ -73.663263868235319, 45.4338180362234 ], [ -73.663449250525488, 45.433677746922733 ], [ -73.663997046842368, 45.434095274603287 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 37 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.6637064475767, 45.434445997854951 ], [ -73.663504364179317, 45.43456624582695 ], [ -73.662851350886925, 45.434083583828233 ], [ -73.663046753841428, 45.433941624416846 ], [ -73.6637064475767, 45.434445997854951 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 38 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.662968258637491, 45.434270636229108 ], [ -73.662757824686494, 45.434439317412057 ], [ -73.662552401067657, 45.434307378664997 ], [ -73.662782876347322, 45.434150388257109 ], [ -73.662968258637491, 45.434270636229108 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 39 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.66293652653377, 45.434915298967887 ], [ -73.662712731696985, 45.435022186054105 ], [ -73.662311905123659, 45.434559565384056 ], [ -73.662473905863706, 45.434394224422554 ], [ -73.66293652653377, 45.434915298967887 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 40 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.663361569712563, 45.434631380145106 ], [ -73.663303950892654, 45.434673132913161 ], [ -73.66315948631518, 45.434562070550136 ], [ -73.66321543502437, 45.434516142505274 ], [ -73.663361569712563, 45.434631380145106 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 41 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.663290590006866, 45.434677308189968 ], [ -73.663232136131597, 45.434720731068744 ], [ -73.663091846830923, 45.434609668705718 ], [ -73.663146125429407, 45.434566245826943 ], [ -73.663290590006866, 45.434677308189968 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 42 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.663216270079729, 45.434723236234831 ], [ -73.66316449664734, 45.434764153947526 ], [ -73.663019197014521, 45.434652256529134 ], [ -73.66307514572371, 45.434610503761078 ], [ -73.663216270079729, 45.434723236234831 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 43 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.663141115097233, 45.434767494168966 ], [ -73.663085166388043, 45.434810917047749 ], [ -73.662943206976649, 45.434697349518636 ], [ -73.662999155685853, 45.434655596750581 ], [ -73.663141115097233, 45.434767494168966 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 44 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.663070135391536, 45.434816762435275 ], [ -73.663019197014521, 45.434858515203331 ], [ -73.662871392215592, 45.434744947674218 ], [ -73.662927340924796, 45.434701524795443 ], [ -73.663070135391536, 45.434816762435275 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 45 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.662996650519759, 45.434860185314051 ], [ -73.662951557530263, 45.434894422583859 ], [ -73.662833814724351, 45.434779184944027 ], [ -73.662863041661993, 45.434745782729578 ], [ -73.662996650519759, 45.434860185314051 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 46 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.663172847200954, 45.435882293076048 ], [ -73.662980784467905, 45.435974149165773 ], [ -73.662469730586906, 45.435426352848886 ], [ -73.662670143873569, 45.435326146205554 ], [ -73.663172847200954, 45.435882293076048 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 47 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.662810433174229, 45.43604596392683 ], [ -73.662235915085787, 45.436202954334718 ], [ -73.662090615452954, 45.436059324812604 ], [ -73.662660123209236, 45.435883963186775 ], [ -73.662810433174229, 45.43604596392683 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 49 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.662297709182511, 45.435972479055053 ], [ -73.662105646449461, 45.436029262819609 ], [ -73.661788325412232, 45.435740333664661 ], [ -73.661988738698909, 45.435651817796384 ], [ -73.662297709182511, 45.435972479055053 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 50 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.662593318780353, 45.435580838090694 ], [ -73.662531524683629, 45.435615075360495 ], [ -73.662412946822357, 45.435490652111696 ], [ -73.6624805863066, 45.435453909675807 ], [ -73.662593318780353, 45.435580838090694 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 51 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.662513153465682, 45.435615910415862 ], [ -73.662448854202879, 45.435650982741024 ], [ -73.66233946195058, 45.435532404879751 ], [ -73.662402091102663, 45.435497332554583 ], [ -73.662513153465682, 45.435615910415862 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 52 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.662432988151025, 45.435650982741024 ], [ -73.662369523943582, 45.435684384955472 ], [ -73.662258461580549, 45.435568312260273 ], [ -73.662323595898712, 45.435533239935111 ], [ -73.662432988151025, 45.435650982741024 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 53 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.662352822836354, 45.435686890121552 ], [ -73.662289358628911, 45.435719457280634 ], [ -73.662175791099799, 45.435603384585441 ], [ -73.662237585196522, 45.43556914731564 ], [ -73.662352822836354, 45.435686890121552 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 55 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.66194114054332, 45.436273098985055 ], [ -73.661677263049199, 45.436343243635385 ], [ -73.661206291825536, 45.435825509311499 ], [ -73.661329880018982, 45.435608394917615 ], [ -73.66194114054332, 45.436273098985055 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 56 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.66139668444788, 45.436279779427942 ], [ -73.660862249016759, 45.43652027537194 ], [ -73.660715279273205, 45.436369965406946 ], [ -73.661122786289425, 45.435985839940834 ], [ -73.66139668444788, 45.436279779427942 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 57 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.662522339074641, 45.435170825908394 ], [ -73.662298544237871, 45.435284393437506 ], [ -73.661954501429094, 45.43490360819284 ], [ -73.662118172279875, 45.434716555791951 ], [ -73.662522339074641, 45.435170825908394 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 58 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.661974542757761, 45.435144104136839 ], [ -73.661837593678541, 45.435317795651947 ], [ -73.661937800321866, 45.435448064288281 ], [ -73.661633840170424, 45.435578332924614 ], [ -73.661476849762536, 45.435397960966611 ], [ -73.661857635007209, 45.434987113728951 ], [ -73.661974542757761, 45.435144104136839 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 59 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.661874336114423, 45.434512802283841 ], [ -73.661557015077207, 45.434873546199839 ], [ -73.661276436475873, 45.434596307819952 ], [ -73.661730706592309, 45.434339110768732 ], [ -73.661874336114423, 45.434512802283841 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 60 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.661430086662321, 45.434997134393285 ], [ -73.661279776697313, 45.435174166129841 ], [ -73.660915692559868, 45.434796721106615 ], [ -73.661126126510879, 45.434666452470282 ], [ -73.661430086662321, 45.434997134393285 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 61 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.661116105846546, 45.435397960966611 ], [ -73.660999198095979, 45.435591693810395 ], [ -73.660474783329207, 45.435050577936394 ], [ -73.660688557501658, 45.434916969078614 ], [ -73.661116105846546, 45.435397960966611 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 62 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.660895651231215, 45.435731983111054 ], [ -73.660367896242988, 45.435969138833613 ], [ -73.660204225392206, 45.435808808204278 ], [ -73.660765382594874, 45.435554951374499 ], [ -73.660895651231215, 45.435731983111054 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 63 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.660384597350216, 45.435625096024836 ], [ -73.660144101406217, 45.435728642889615 ], [ -73.65980673904032, 45.435357878309283 ], [ -73.660060595870107, 45.435240970558723 ], [ -73.660384597350216, 45.435625096024836 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 64 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.664149026918068, 45.43368108714418 ], [ -73.664008737617408, 45.433764592680291 ], [ -73.663905190752629, 45.433641004486844 ], [ -73.664022098503182, 45.433567519615067 ], [ -73.664149026918068, 45.43368108714418 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 65 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.665702229889732, 45.434185460582285 ], [ -73.665541899260404, 45.434289007447063 ], [ -73.66499076272207, 45.433878160209403 ], [ -73.665151093351398, 45.433767932901738 ], [ -73.665702229889732, 45.434185460582285 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 67 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.666320170856977, 45.433948304859719 ], [ -73.666116417348874, 45.434091934381826 ], [ -73.665458393724322, 45.433600921829495 ], [ -73.665672167896759, 45.433420549871499 ], [ -73.666320170856977, 45.433948304859719 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 68 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.667141865332312, 45.433403848764272 ], [ -73.666363593735753, 45.433928263531051 ], [ -73.666186561999197, 45.433787974230384 ], [ -73.666948132488528, 45.433276920349385 ], [ -73.667141865332312, 45.433403848764272 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 69 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.666854606288084, 45.43323349747061 ], [ -73.666650852779981, 45.433380467214164 ], [ -73.666386975285874, 45.433193414813275 ], [ -73.666667553887208, 45.43309654839139 ], [ -73.666854606288084, 45.43323349747061 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 70 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.666557326579536, 45.433019723298166 ], [ -73.666103056463101, 45.433126610384384 ], [ -73.666062973805765, 45.433086527727056 ], [ -73.66488387563588, 45.433373786771277 ], [ -73.664810390764103, 45.433223476806276 ], [ -73.66597278782676, 45.432929537319168 ], [ -73.665889282290649, 45.432729124032498 ], [ -73.666066314027205, 45.432672340267942 ], [ -73.666557326579536, 45.433019723298166 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 71 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.666499707759627, 45.433347900055082 ], [ -73.666428728053944, 45.43336627127303 ], [ -73.666371944289381, 45.433208445809782 ], [ -73.666382800009075, 45.433205940643695 ], [ -73.666499707759627, 45.433347900055082 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 72 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.66641870738961, 45.43336710632839 ], [ -73.666365263846487, 45.433379632158804 ], [ -73.666308480081938, 45.433234332525977 ], [ -73.666358583403607, 45.433215961308029 ], [ -73.66641870738961, 45.43336710632839 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 73 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.666347727683913, 45.433381302269531 ], [ -73.66628676864255, 45.433395498210665 ], [ -73.666231654988721, 45.433251868688558 ], [ -73.66628342842111, 45.43322932219381 ], [ -73.666347727683913, 45.433381302269531 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 74 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.666273407756776, 45.433394663155305 ], [ -73.666216623992213, 45.433409694151806 ], [ -73.666164850559824, 45.433286105958359 ], [ -73.666220799269027, 45.433265229574332 ], [ -73.666273407756776, 45.433394663155305 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 75 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.666198252774265, 45.433413034373253 ], [ -73.666139798898996, 45.433431405591193 ], [ -73.666081345023713, 45.433293621456613 ], [ -73.666144809231156, 45.433272745072586 ], [ -73.666198252774265, 45.433413034373253 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 77 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.666128108123942, 45.43343307570192 ], [ -73.666069654248659, 45.433449776809141 ], [ -73.66601454059483, 45.433305312231667 ], [ -73.666063808861139, 45.433289446179806 ], [ -73.666128108123942, 45.43343307570192 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 78 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.666054623252165, 45.433449776809141 ], [ -73.665997839487602, 45.433469818137809 ], [ -73.665944395944493, 45.433337879390749 ], [ -73.666004519930496, 45.433312827729921 ], [ -73.666054623252165, 45.433449776809141 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 79 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -73.665984478601828, 45.433469818137809 ], [ -73.665933540224799, 45.433484014078942 ], [ -73.665870911072716, 45.433348735110442 ], [ -73.665926024726545, 45.433331198947862 ], [ -73.665984478601828, 45.433469818137809 ] ] ] ] } }
]
}

12
input_files/new.geojson Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
{"type": "FeatureCollection", "features": []}

191
input_files/pipe_data.json Normal file
View File

@ -0,0 +1,191 @@
[
{
"DN": 16,
"inner_diameter": 16.1,
"outer_diameter": 21.3,
"thickness": 2.6,
"cost_per_meter": 320
},
{
"DN": 20,
"inner_diameter": 21.7,
"outer_diameter": 26.9,
"thickness": 2.6,
"cost_per_meter": 320
},
{
"DN": 25,
"inner_diameter": 27.3,
"outer_diameter": 33.7,
"thickness": 3.2,
"cost_per_meter": 320
},
{
"DN": 32,
"inner_diameter": 37.2,
"outer_diameter": 42.4,
"thickness": 2.6,
"cost_per_meter": 350
},
{
"DN": 40,
"inner_diameter": 43.1,
"outer_diameter": 48.3,
"thickness": 2.6,
"cost_per_meter": 375
},
{
"DN": 50,
"inner_diameter": 54.5,
"outer_diameter": 60.3,
"thickness": 2.9,
"cost_per_meter": 400
},
{
"DN": 65,
"inner_diameter": 70.3,
"outer_diameter": 76.1,
"thickness": 2.9,
"cost_per_meter": 450
},
{
"DN": 80,
"inner_diameter": 82.5,
"outer_diameter": 88.9,
"thickness": 3.2,
"cost_per_meter": 480
},
{
"DN": 90,
"inner_diameter": 100.8,
"outer_diameter": 108,
"thickness": 3.6,
"cost_per_meter": 480
},
{
"DN": 100,
"inner_diameter": 107.1,
"outer_diameter": 114.3,
"thickness": 3.6,
"cost_per_meter": 550
},
{
"DN": 110,
"inner_diameter": 125.8,
"outer_diameter": 133,
"thickness": 3.6,
"cost_per_meter": 550
},
{
"DN": 125,
"inner_diameter": 132.5,
"outer_diameter": 139.7,
"thickness": 3.6,
"cost_per_meter": 630
},
{
"DN": 140,
"inner_diameter": 151,
"outer_diameter": 159,
"thickness": 4,
"cost_per_meter": 700
},
{
"DN": 150,
"inner_diameter": 160.3,
"outer_diameter": 168.3,
"thickness": 4,
"cost_per_meter": 700
},
{
"DN": 180,
"inner_diameter": 184.7,
"outer_diameter": 193.7,
"thickness": 4.5,
"cost_per_meter": 700
},
{
"DN": 200,
"inner_diameter": 210.1,
"outer_diameter": 219.1,
"thickness": 4.5,
"cost_per_meter": 860
},
{
"DN": 250,
"inner_diameter": 263,
"outer_diameter": 273,
"thickness": 5,
"cost_per_meter": 860
},
{
"DN": 300,
"inner_diameter": 312.7,
"outer_diameter": 323.9,
"thickness": 5.6,
"cost_per_meter": 860
},
{
"DN": 350,
"inner_diameter": 344.4,
"outer_diameter": 355.6,
"thickness": 5.6,
"cost_per_meter": 860
},
{
"DN": 400,
"inner_diameter": 393.8,
"outer_diameter": 406.4,
"thickness": 6.3,
"cost_per_meter": 860
},
{
"DN": 450,
"inner_diameter": 444.4,
"outer_diameter": 457,
"thickness": 6.3,
"cost_per_meter": 860
},
{
"DN": 500,
"inner_diameter": 495.4,
"outer_diameter": 508,
"thickness": 6.3,
"cost_per_meter": 860
},
{
"DN": 600,
"inner_diameter": 595.8,
"outer_diameter": 610,
"thickness": 7.1,
"cost_per_meter": 860
},
{
"DN": 700,
"inner_diameter": 696.8,
"outer_diameter": 711,
"thickness": 7.1,
"cost_per_meter": 860
},
{
"DN": 800,
"inner_diameter": 797,
"outer_diameter": 813,
"thickness": 8,
"cost_per_meter": 860
},
{
"DN": 900,
"inner_diameter": 894,
"outer_diameter": 914,
"thickness": 10,
"cost_per_meter": 860
},
{
"DN": 1000,
"inner_diameter": 996,
"outer_diameter": 1016,
"thickness": 10,
"cost_per_meter": 860
}
]

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,628 @@
{
"type": "FeatureCollection",
"name": "lachine_roadfs",
"crs": {
"type": "name",
"properties": {
"name": "urn:ogc:def:crs:OGC:1.3:CRS84"
}
},
"features": [
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66582797080785,
45.43501726460131
],
[
-73.66582043211604,
45.436102836222425
],
[
-73.66582043211604,
45.436102836222425
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66582043211604,
45.436102836222425
],
[
-73.66582043211604,
45.437203485227165
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66582043211604,
45.437203485227165
],
[
-73.66583550949966,
45.43833428899916
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66583550949966,
45.43833428899916
],
[
-73.66679292335995,
45.43815336039564
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66679292335995,
45.43815336039564
],
[
-73.66676276859269,
45.437226101302606
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66676276859269,
45.437226101302606
],
[
-73.66582043211604,
45.437203485227165
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66676276859269,
45.437226101302606
],
[
-73.66677030728451,
45.43677377979381
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66677030728451,
45.43677377979381
],
[
-73.66753925384947,
45.43675116371837
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66753925384947,
45.43675116371837
],
[
-73.66756186992491,
45.436102836222425
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66756186992491,
45.436102836222425
],
[
-73.66582043211604,
45.436102836222425
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66756186992491,
45.436102836222425
],
[
-73.66754679254127,
45.435032341984936
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66754679254127,
45.435032341984936
],
[
-73.66582797080785,
45.43501726460131
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66754679254127,
45.435032341984936
],
[
-73.66858713201151,
45.435024803293125
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66858713201151,
45.435024803293125
],
[
-73.6694314654946,
45.435039880676754
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66858713201151,
45.435024803293125
],
[
-73.66860974808695,
45.436087758838795
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66860974808695,
45.436087758838795
],
[
-73.66862482547057,
45.43723363999442
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66862482547057,
45.43723363999442
],
[
-73.66944654287822,
45.43723363999442
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66944654287822,
45.43723363999442
],
[
-73.66943900418642,
45.43609529753061
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66943900418642,
45.43609529753061
],
[
-73.66860974808695,
45.436087758838795
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66943900418642,
45.43609529753061
],
[
-73.6694314654946,
45.435039880676754
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66862482547057,
45.43723363999442
],
[
-73.66770510506936,
45.437226101302606
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66770510506936,
45.437226101302606
],
[
-73.66676276859269,
45.437226101302606
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66770510506936,
45.437226101302606
],
[
-73.66771264376118,
45.43797243179212
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66771264376118,
45.43797243179212
],
[
-73.66679292335995,
45.43815336039564
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66771264376118,
45.43797243179212
],
[
-73.66863990285421,
45.4377915031886
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66863990285421,
45.4377915031886
],
[
-73.66862482547057,
45.43723363999442
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66863990285421,
45.4377915031886
],
[
-73.66945408157004,
45.43764826804415
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66945408157004,
45.43764826804415
],
[
-73.66944654287822,
45.43723363999442
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.6694314654946,
45.435039880676754
],
[
-73.66938623334372,
45.433622606615856
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66938623334372,
45.433622606615856
],
[
-73.66870021238871,
45.43365276138311
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66870021238871,
45.43365276138311
],
[
-73.66868513500509,
45.43390907690476
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66868513500509,
45.43390907690476
],
[
-73.66870021238871,
45.43406738943284
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66868513500509,
45.43390907690476
],
[
-73.66839112602436,
45.43389399952113
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66870021238871,
45.43406738943284
],
[
-73.6681272718109,
45.43442924663987
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66870021238871,
45.43365276138311
],
[
-73.6676749503021,
45.43365276138311
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66938623334372,
45.433622606615856
],
[
-73.66930330773377,
45.43118007046835
]
]
},
"properties": {}
}
]
}

43
input_files/roads.geojson Normal file
View File

@ -0,0 +1,43 @@
{
"type": "FeatureCollection",
"name": "roads",
"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },
"features": [
{ "type": "Feature", "properties": { "id": 1 }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ -73.665827970807854, 45.435017264601314 ], [ -73.665820432116035, 45.436102836222425 ], [ -73.665820432116035, 45.436102836222425 ] ] ] } },
{ "type": "Feature", "properties": { "id": 2 }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ -73.665820432116035, 45.436102836222425 ], [ -73.665820432116035, 45.437203485227165 ] ] ] } },
{ "type": "Feature", "properties": { "id": 3 }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ -73.665820432116035, 45.437203485227165 ], [ -73.665835509499658, 45.438334288999158 ] ] ] } },
{ "type": "Feature", "properties": { "id": 4 }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ -73.665835509499658, 45.438334288999158 ], [ -73.666792923359949, 45.438153360395638 ] ] ] } },
{ "type": "Feature", "properties": { "id": 5 }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ -73.666792923359949, 45.438153360395638 ], [ -73.66676276859269, 45.437226101302606 ] ] ] } },
{ "type": "Feature", "properties": { "id": 6 }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ -73.66676276859269, 45.437226101302606 ], [ -73.665820432116035, 45.437203485227165 ] ] ] } },
{ "type": "Feature", "properties": { "id": 7 }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ -73.66676276859269, 45.437226101302606 ], [ -73.666770307284509, 45.43677377979381 ] ] ] } },
{ "type": "Feature", "properties": { "id": 8 }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ -73.666770307284509, 45.43677377979381 ], [ -73.667539253849469, 45.43675116371837 ] ] ] } },
{ "type": "Feature", "properties": { "id": 8 }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ -73.667539253849469, 45.43675116371837 ], [ -73.66756186992491, 45.436102836222425 ] ] ] } },
{ "type": "Feature", "properties": { "id": 9 }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ -73.66756186992491, 45.436102836222425 ], [ -73.665820432116035, 45.436102836222425 ] ] ] } },
{ "type": "Feature", "properties": { "id": 10 }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ -73.66756186992491, 45.436102836222425 ], [ -73.667546792541273, 45.435032341984936 ] ] ] } },
{ "type": "Feature", "properties": { "id": 11 }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ -73.667546792541273, 45.435032341984936 ], [ -73.665827970807854, 45.435017264601314 ] ] ] } },
{ "type": "Feature", "properties": { "id": 12 }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ -73.667546792541273, 45.435032341984936 ], [ -73.66858713201151, 45.435024803293125 ] ] ] } },
{ "type": "Feature", "properties": { "id": 13 }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ -73.66858713201151, 45.435024803293125 ], [ -73.669431465494597, 45.435039880676754 ] ] ] } },
{ "type": "Feature", "properties": { "id": 14 }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ -73.66858713201151, 45.435024803293125 ], [ -73.668609748086951, 45.436087758838795 ] ] ] } },
{ "type": "Feature", "properties": { "id": 15 }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ -73.668609748086951, 45.436087758838795 ], [ -73.668624825470573, 45.437233639994417 ] ] ] } },
{ "type": "Feature", "properties": { "id": 17 }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ -73.668624825470573, 45.437233639994417 ], [ -73.669446542878219, 45.437233639994417 ] ] ] } },
{ "type": "Feature", "properties": { "id": 18 }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ -73.669446542878219, 45.437233639994417 ], [ -73.669439004186415, 45.436095297530613 ] ] ] } },
{ "type": "Feature", "properties": { "id": 19 }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ -73.669439004186415, 45.436095297530613 ], [ -73.668609748086951, 45.436087758838795 ] ] ] } },
{ "type": "Feature", "properties": { "id": 20 }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ -73.669439004186415, 45.436095297530613 ], [ -73.669431465494597, 45.435039880676754 ] ] ] } },
{ "type": "Feature", "properties": { "id": 21 }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ -73.668624825470573, 45.437233639994417 ], [ -73.667705105069359, 45.437226101302606 ] ] ] } },
{ "type": "Feature", "properties": { "id": 22 }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ -73.667705105069359, 45.437226101302606 ], [ -73.66676276859269, 45.437226101302606 ] ] ] } },
{ "type": "Feature", "properties": { "id": 23 }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ -73.667705105069359, 45.437226101302606 ], [ -73.667712643761178, 45.437972431792119 ] ] ] } },
{ "type": "Feature", "properties": { "id": 24 }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ -73.667712643761178, 45.437972431792119 ], [ -73.666792923359949, 45.438153360395638 ] ] ] } },
{ "type": "Feature", "properties": { "id": 24 }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ -73.667712643761178, 45.437972431792119 ], [ -73.66863990285421, 45.437791503188599 ] ] ] } },
{ "type": "Feature", "properties": { "id": 26 }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ -73.66863990285421, 45.437791503188599 ], [ -73.668624825470573, 45.437233639994417 ] ] ] } },
{ "type": "Feature", "properties": { "id": 27 }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ -73.66863990285421, 45.437791503188599 ], [ -73.669454081570038, 45.43764826804415 ] ] ] } },
{ "type": "Feature", "properties": { "id": 28 }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ -73.669454081570038, 45.43764826804415 ], [ -73.669446542878219, 45.437233639994417 ] ] ] } },
{ "type": "Feature", "properties": { "id": 29 }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ -73.669431465494597, 45.435039880676754 ], [ -73.669386233343715, 45.433622606615856 ] ] ] } },
{ "type": "Feature", "properties": { "id": 30 }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ -73.669386233343715, 45.433622606615856 ], [ -73.668700212388714, 45.433652761383108 ] ] ] } },
{ "type": "Feature", "properties": { "id": 31 }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ -73.668700212388714, 45.433652761383108 ], [ -73.668685135005092, 45.433909076904762 ] ] ] } },
{ "type": "Feature", "properties": { "id": 32 }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ -73.668685135005092, 45.433909076904762 ], [ -73.668700212388714, 45.43406738943284 ] ] ] } },
{ "type": "Feature", "properties": { "id": 33 }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ -73.668685135005092, 45.433909076904762 ], [ -73.66839112602436, 45.433893999521132 ] ] ] } },
{ "type": "Feature", "properties": { "id": 34 }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ -73.668700212388714, 45.43406738943284 ], [ -73.668127271810903, 45.434429246639873 ] ] ] } },
{ "type": "Feature", "properties": { "id": 35 }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ -73.668700212388714, 45.433652761383108 ], [ -73.6676749503021, 45.433652761383108 ] ] ] } },
{ "type": "Feature", "properties": { "id": 35 }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ -73.669386233343715, 45.433622606615856 ], [ -73.66930330773377, 45.431180070468351 ] ] ] } }
]
}

View File

@ -0,0 +1,900 @@
{
"type": "FeatureCollection",
"name": "lachine_roadfs",
"crs": {
"type": "name",
"properties": {
"name": "urn:ogc:def:crs:OGC:1.3:CRS84"
}
},
"features": [
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.65594139216809,
45.43892504130949
],
[
-73.65715220401293,
45.43822016359244
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.65799428420533,
45.43987516845119
],
[
-73.65715220401293,
45.43822016359244
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.65715220401293,
45.43822016359244
],
[
-73.6580217247004,
45.43767649878391
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.6580217247004,
45.43767649878391
],
[
-73.65945549056768,
45.436925315231434
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.65945549056768,
45.436925315231434
],
[
-73.65973332558023,
45.437405523895116
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.65973332558023,
45.437405523895116
],
[
-73.6597607660753,
45.43955617269603
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.65945549056768,
45.436925315231434
],
[
-73.66077606439278,
45.43661832469285
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66077606439278,
45.43661832469285
],
[
-73.66216180939368,
45.43631476421617
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66216180939368,
45.43631476421617
],
[
-73.66223898578612,
45.43707109286148
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66223898578612,
45.43707109286148
],
[
-73.66113450585965,
45.437331777564616
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66113450585965,
45.437331777564616
],
[
-73.6611486548649,
45.438600578893194
],
[
-73.66115508623095,
45.43917029073414
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66223898578612,
45.43707109286148
],
[
-73.66229386677625,
45.43858718021396
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66229386677625,
45.43858718021396
],
[
-73.6611486548649,
45.438600578893194
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66216180939368,
45.43631476421617
],
[
-73.66160281649616,
45.435697031508866
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66160281649616,
45.435697031508866
],
[
-73.66132155142171,
45.43540890631066
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66132155142171,
45.43540890631066
],
[
-73.66073158077776,
45.43475033442904
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66216180939368,
45.43631476421617
],
[
-73.66346191003697,
45.43590969534564
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66346191003697,
45.43590969534564
],
[
-73.66272101667016,
45.435203102597654
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66272101667016,
45.435203102597654
],
[
-73.66160281649616,
45.435697031508866
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66272101667016,
45.435203102597654
],
[
-73.66211732577867,
45.43452395034473
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66211732577867,
45.43452395034473
],
[
-73.66132155142171,
45.43540890631066
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66211732577867,
45.43452395034473
],
[
-73.66177431959032,
45.43418780428016
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66177431959032,
45.43418780428016
],
[
-73.66073158077776,
45.43475033442904
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66077606439278,
45.43661832469285
],
[
-73.66053949731229,
45.436314442647884
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66053949731229,
45.436314442647884
],
[
-73.66132155142171,
45.43540890631066
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66053949731229,
45.436314442647884
],
[
-73.65957907998492,
45.435306004454155
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.65957907998492,
45.435306004454155
],
[
-73.66073158077776,
45.43475033442904
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66346191003697,
45.43590969534564
],
[
-73.66442232736433,
45.435326584825454
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66442232736433,
45.435326584825454
],
[
-73.66471731268632,
45.43508648049362
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66471731268632,
45.43508648049362
],
[
-73.66579435211771,
45.43442104848823
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66272101667016,
45.435203102597654
],
[
-73.66391467820559,
45.43443476873576
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66391467820559,
45.43443476873576
],
[
-73.66471731268632,
45.43508648049362
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66442232736433,
45.435326584825454
],
[
-73.66444976785941,
45.43599887695461
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66444976785941,
45.43599887695461
],
[
-73.66444976785941,
45.43695929428197
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66444976785941,
45.43695929428197
],
[
-73.66575319137512,
45.437000455024574
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66444976785941,
45.43599887695461
],
[
-73.66576691162264,
45.436005737078375
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66391467820559,
45.43443476873576
],
[
-73.66305030261097,
45.43377619685415
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66305030261097,
45.43377619685415
],
[
-73.66211732577867,
45.43452395034473
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66391467820559,
45.43443476873576
],
[
-73.6651357802361,
45.43365271462634
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.6651357802361,
45.43365271462634
],
[
-73.66387351746299,
45.43332342868553
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66387351746299,
45.43332342868553
],
[
-73.66305030261097,
45.43377619685415
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.6651357802361,
45.43365271462634
],
[
-73.66565714964237,
45.43398886069092
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66565714964237,
45.43398886069092
],
[
-73.66579435211771,
45.43442104848823
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66579435211771,
45.43442104848823
],
[
-73.66576691162264,
45.436005737078375
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66576691162264,
45.436005737078375
],
[
-73.66575319137512,
45.437000455024574
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66387351746299,
45.43332342868553
],
[
-73.66611677793476,
45.43254823469987
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66611677793476,
45.43254823469987
],
[
-73.66736532046032,
45.43350179190347
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.66736532046032,
45.43350179190347
],
[
-73.66579435211771,
45.43442104848823
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.6651357802361,
45.43365271462634
],
[
-73.6657120306325,
45.43328226794293
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.6657120306325,
45.43328226794293
],
[
-73.6667307590119,
45.43303530348731
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.6667307590119,
45.43303530348731
],
[
-73.66611677793476,
45.43254823469987
]
]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.6667307590119,
45.43303530348731
],
[
-73.66736532046032,
45.43350179190347
]
]
},
"properties": {}
}
]
}

View File

@ -1,55 +0,0 @@
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-73.58000127109773,
45.49613461675315
],
[
-73.57962787855432,
45.496524875557746
],
[
-73.57996357265695,
45.49668114195629
],
[
-73.57996427397713,
45.496680342403664
],
[
-73.58034707390021,
45.49625804233725
],
[
-73.58034697395713,
45.496257942524835
],
[
-73.58000127109773,
45.49613461675315
]
]
]
},
"id": 179764,
"properties": {
"name": "01119274",
"address": "rue Guy (MTL) 2157",
"function": "Mixed use",
"mixed_type_1": "commercial",
"mixed_type_1_percentage": 50,
"mixed_type_2": "6000",
"mixed_type_2_percentage": 50,
"height": 62,
"year_of_construction": 1954
}
}
]
}

View File

@ -1,52 +0,0 @@
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-73.58000127109773,
45.49613461675315
],
[
-73.57962787855432,
45.496524875557746
],
[
-73.57996357265695,
45.49668114195629
],
[
-73.57996427397713,
45.496680342403664
],
[
-73.58034707390021,
45.49625804233725
],
[
-73.58034697395713,
45.496257942524835
],
[
-73.58000127109773,
45.49613461675315
]
]
]
},
"id": 179764,
"properties": {
"name": "01119274",
"address": "rue Guy (MTL) 2157",
"function": "Mixed use",
"usages": [{"usage": "commercial", "percentage": 50}, {"usage": "6000", "percentage": 50}],
"height": 62,
"year_of_construction": 1954
}
}
]
}

64
main.py
View File

@ -1,4 +1,5 @@
from pathlib import Path
from scripts.district_heating_network.directory_manager import DirectoryManager
import subprocess
from scripts.ep_run_enrich import energy_plus_workflow
from hub.imports.geometry_factory import GeometryFactory
@ -6,47 +7,46 @@ 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
from hub.imports.results_factory import ResultFactory
from scripts.energy_system_retrofit_report import EnergySystemRetrofitReport
from scripts.geojson_creator import process_geojson
from scripts import random_assignation
from hub.imports.energy_systems_factory import EnergySystemsFactory
from scripts.energy_system_sizing import SystemSizing
from scripts.solar_angles import CitySolarAngles
from scripts.pv_sizing_and_simulation import PVSizingSimulation
from scripts.energy_system_retrofit_results import consumption_data, cost_data
from scripts.energy_system_sizing_and_simulation_factory import EnergySystemsSimulationFactory
from scripts.costs.cost import Cost
from scripts.costs.constants import SKIN_RETROFIT_AND_SYSTEM_RETROFIT_AND_PV, SYSTEM_RETROFIT_AND_PV, CURRENT_STATUS
from scripts.district_heating_network.road_processor import road_processor
from scripts.district_heating_network.district_heating_network_creator import DistrictHeatingNetworkCreator
from scripts.district_heating_network.geojson_graph_creator import networkx_to_geojson
import hub.helpers.constants as cte
from hub.exports.exports_factory import ExportsFactory
from scripts.pv_feasibility import pv_feasibility
import matplotlib.pyplot as plt
import numpy as np
# Specify the GeoJSON file path
data = {}
input_files_path = (Path(__file__).parent / 'input_files')
input_files_path.mkdir(parents=True, exist_ok=True)
# geojson_file = process_geojson(x=-73.58001358793511, y=45.496445294438715, diff=0.0001)
geojson_file_path = input_files_path / 'test_geojson1.geojson'
output_path = (Path(__file__).parent / 'out_files').resolve()
output_path.mkdir(parents=True, exist_ok=True)
energy_plus_output_path = output_path / 'energy_plus_outputs'
energy_plus_output_path.mkdir(parents=True, exist_ok=True)
simulation_results_path = (Path(__file__).parent / 'out_files' / 'simulation_results').resolve()
simulation_results_path.mkdir(parents=True, exist_ok=True)
sra_output_path = output_path / 'sra_outputs'
sra_output_path.mkdir(parents=True, exist_ok=True)
cost_analysis_output_path = output_path / 'cost_analysis'
cost_analysis_output_path.mkdir(parents=True, exist_ok=True)
from scripts.district_heating_network.district_heating_network_creator import DistrictHeatingNetworkCreator
from scripts.district_heating_network.road_processor import road_processor
from scripts.district_heating_network.district_heating_factory import DistrictHeatingFactory
base_path = Path(__file__).parent
dir_manager = DirectoryManager(base_path)
# Input files directory
input_files_path = dir_manager.create_directory('input_files')
geojson_file_path = input_files_path / 'output_buildings.geojson'
# Output files directory
output_path = dir_manager.create_directory('out_files')
# Subdirectories for output files
energy_plus_output_path = dir_manager.create_directory('out_files/energy_plus_outputs')
simulation_results_path = dir_manager.create_directory('out_files/simulation_results')
sra_output_path = dir_manager.create_directory('out_files/sra_outputs')
cost_analysis_output_path = dir_manager.create_directory('out_files/cost_analysis')
# Select city area
location = [45.53067276979674, -73.70234652694087]
process_geojson(x=location[1], y=location[0], diff=0.001)
# Create city object
city = GeometryFactory(file_type='geojson',
path=geojson_file_path,
height_field='height',
year_of_construction_field='year_of_construction',
function_field='function',
function_to_hub=Dictionaries().montreal_function_to_hub_function).city
# ConstructionFactory('nrcan', city).enrich()
# UsageFactory('nrcan', city).enrich()
ConstructionFactory('nrcan', city).enrich()
UsageFactory('nrcan', city).enrich()
# WeatherFactory('epw', city).enrich()
# energy_plus_workflow(city, energy_plus_output_path)
# data[f'{city.buildings[0].function}'] = city.buildings[0].heating_demand[cte.YEAR][0] / 3.6e9
@ -83,4 +83,4 @@ city = GeometryFactory(file_type='geojson',
# # Save the plot
# plt.savefig('plot_nrcan.png', bbox_inches='tight')
# plt.close()
print('test')
print('test')

View File

@ -14,7 +14,7 @@ import hub.helpers.constants as cte
from hub.exports.exports_factory import ExportsFactory
from scripts.pv_sizing_and_simulation import PVSizingSimulation
# Specify the GeoJSON file path
geojson_file = process_geojson(x=-73.5681295982132, y=45.49218262677643, diff=0.0005)
geojson_file = process_geojson(x=-73.5681295982132, y=45.49218262677643, diff=0.0001)
file_path = (Path(__file__).parent / 'input_files' / 'output_buildings.geojson')
# Specify the output path for the PDF file
output_path = (Path(__file__).parent / 'out_files').resolve()
@ -34,7 +34,7 @@ ExportsFactory('sra', city, output_path).export()
sra_path = (output_path / f'{city.name}_sra.xml').resolve()
subprocess.run(['sra', str(sra_path)])
ResultFactory('sra', city, output_path).enrich()
energy_plus_workflow(city)
energy_plus_workflow(city, output_path=output_path)
solar_angles = CitySolarAngles(city.name,
city.latitude,
city.longitude,

View File

@ -0,0 +1,16 @@
from pathlib import Path
class DirectoryManager:
def __init__(self, base_path):
self.base_path = Path(base_path)
self.directories = {}
def create_directory(self, relative_path):
full_path = self.base_path / relative_path
full_path.mkdir(parents=True, exist_ok=True)
self.directories[relative_path] = full_path
return full_path
def get_directory(self, relative_path):
return self.directories.get(relative_path, None)

View File

@ -0,0 +1,248 @@
import CoolProp.CoolProp as CP
import math
import logging
import numpy as np
import csv
class DistrictHeatingFactory:
"""
DistrictHeatingFactory class
This class is responsible for managing the district heating network, including
enriching the network graph with building data, calculating flow rates,
sizing pipes, and analyzing costs.
"""
def __init__(self, city, graph, supply_temperature, return_temperature, simultaneity_factor):
"""
Initialize the DistrictHeatingFactory object.
:param city: The city object containing buildings and their heating demands.
:param graph: The network graph representing the district heating network.
:param supply_temperature: The supply temperature of the heating fluid in the network (°C).
:param return_temperature: The return temperature of the heating fluid in the network (°C).
:param simultaneity_factor: The simultaneity factor used to adjust flow rates for non-building pipes.
"""
self._city = city
self._network_graph = graph
self._supply_temperature = supply_temperature
self._return_temperature = return_temperature
self.simultaneity_factor = simultaneity_factor
self.fluid = "Water" # The fluid used in the heating network
def enrich(self):
"""
Enrich the network graph nodes with the whole building object from the city buildings.
This method associates each building node in the network graph with its corresponding
building object from the city, allowing access to heating demand data during calculations.
"""
for node_id, node_attrs in self._network_graph.nodes(data=True):
if node_attrs.get('type') == 'building':
building_name = node_attrs.get('name')
building_found = False
for building in self._city.buildings:
if building.name == building_name:
self._network_graph.nodes[node_id]['building_obj'] = building
building_found = True
break
if not building_found:
logging.error(msg=f"Building with name '{building_name}' not found in city.")
def calculate_flow_rates(self, A, Gext):
"""
Solve the linear system to find the flow rates in each branch.
:param A: The incidence matrix representing the network connections.
:param Gext: The external flow rates for each node in the network.
:return: The calculated flow rates for each edge, or None if an error occurs.
"""
try:
G = np.linalg.lstsq(A, Gext, rcond=None)[0]
return G
except np.linalg.LinAlgError as e:
logging.error(f"Error solving the linear system: {e}")
return None
def switch_nodes(self, A, edge_index, node_index, edge):
"""
Switch the in and out nodes for the given edge in the incidence matrix A.
:param A: The incidence matrix representing the network connections.
:param edge_index: The index of edges in the incidence matrix.
:param node_index: The index of nodes in the incidence matrix.
:param edge: The edge (u, v) to switch.
"""
u, v = edge
i = node_index[u]
j = node_index[v]
k = edge_index[edge]
A[i, k], A[j, k] = -A[i, k], -A[j, k]
def sizing(self):
"""
Calculate the hourly mass flow rates, assign them to the edges, and determine the pipe diameters.
This method generates the flow rates for each hour, adjusting the incidence matrix as needed to
ensure all flow rates are positive. It also applies the simultaneity factor to non-building pipes.
"""
num_nodes = self._network_graph.number_of_nodes()
num_edges = self._network_graph.number_of_edges()
A = np.zeros((num_nodes, num_edges)) # Initialize incidence matrix
node_index = {node: i for i, node in enumerate(self._network_graph.nodes())}
edge_index = {edge: i for i, edge in enumerate(self._network_graph.edges())}
# Initialize mass flow rate attribute for each edge
for u, v, data in self._network_graph.edges(data=True):
self._network_graph.edges[u, v]['mass_flow_rate'] = {"hour": [], "peak": None}
# Get the length of the hourly demand for the first building (assuming all buildings have the same length)
building = next(iter(self._city.buildings))
num_hours = len(building.heating_demand['hour'])
# Loop through each hour to generate Gext and solve AG = Gext
for hour in range(8760):
Gext = np.zeros(num_nodes)
# Calculate the hourly mass flow rates for each edge and fill Gext
for edge in self._network_graph.edges(data=True):
u, v, data = edge
for node in [u, v]:
if self._network_graph.nodes[node].get('type') == 'building':
building = self._network_graph.nodes[node].get('building_obj')
if building and "hour" in building.heating_demand:
hourly_demand = building.heating_demand["hour"][hour] # Get demand for current hour
specific_heat_capacity = CP.PropsSI('C', 'T', (self._supply_temperature + self._return_temperature) / 2,
'P', 101325, self.fluid)
mass_flow_rate = hourly_demand / 3600 / (
specific_heat_capacity * (self._supply_temperature - self._return_temperature))
Gext[node_index[node]] += mass_flow_rate
# Update incidence matrix A
i = node_index[u]
j = node_index[v]
k = edge_index[(u, v)]
A[i, k] = 1
A[j, k] = -1
# Solve for G (flow rates)
G = self.calculate_flow_rates(A, Gext)
if G is None:
return
# Check for negative flow rates and adjust A accordingly
iterations = 0
max_iterations = num_edges * 2
while any(flow_rate < 0 for flow_rate in G) and iterations < max_iterations:
for idx, flow_rate in enumerate(G):
if flow_rate < 0:
G[idx] = -G[idx] # Invert the sign directly
iterations += 1
# Store the final flow rates in the edges for this hour
for idx, (edge, flow_rate) in enumerate(zip(self._network_graph.edges(), G)):
u, v = edge
if not (self._network_graph.nodes[u].get('type') == 'building' or self._network_graph.nodes[v].get(
'type') == 'building'):
flow_rate *= self.simultaneity_factor # Apply simultaneity factor for non-building pipes
data = self._network_graph.edges[u, v]
data['mass_flow_rate']["hour"].append(flow_rate) # Append the calculated flow rate
# Calculate the peak flow rate for each edge
for u, v, data in self._network_graph.edges(data=True):
data['mass_flow_rate']['peak'] = max(data['mass_flow_rate']['hour'])
def calculate_diameters_and_costs(self, pipe_data):
"""
Calculate the diameter and costs of the pipes based on the maximum flow rate in each edge.
:param pipe_data: A list of dictionaries containing pipe specifications, including inner diameters
and costs per meter for different nominal diameters (DN).
"""
for u, v, data in self._network_graph.edges(data=True):
flow_rate = data.get('mass_flow_rate', {}).get('peak')
if flow_rate is not None:
try:
# Calculate the density of the fluid
density = CP.PropsSI('D', 'T', (self._supply_temperature + self._return_temperature) / 2, 'P', 101325,
self.fluid)
velocity = 0.9 # Desired fluid velocity in m/s
# Calculate the diameter of the pipe required for the given flow rate
diameter = math.sqrt((4 * abs(flow_rate)) / (density * velocity * math.pi)) * 1000 # Convert to mm
self._network_graph.edges[u, v]['diameter'] = diameter
# Match to the closest nominal diameter from the pipe data
closest_pipe = self.match_nominal_diameter(diameter, pipe_data)
self._network_graph.edges[u, v]['nominal_diameter'] = closest_pipe['DN']
self._network_graph.edges[u, v]['cost_per_meter'] = closest_pipe['cost_per_meter']
except Exception as e:
logging.error(f"Error calculating diameter or matching nominal diameter for edge ({u}, {v}): {e}")
def match_nominal_diameter(self, diameter, pipe_data):
"""
Match the calculated diameter to the closest nominal diameter.
:param diameter: The calculated diameter of the pipe (in mm).
:param pipe_data: A list of dictionaries containing pipe specifications, including inner diameters
and costs per meter for different nominal diameters (DN).
:return: The dictionary representing the pipe with the closest nominal diameter.
"""
closest_pipe = min(pipe_data, key=lambda x: abs(x['inner_diameter'] - diameter))
return closest_pipe
def analyze_costs(self):
"""
Analyze the costs based on the nominal diameters of the pipes.
This method calculates the total cost of piping for each nominal diameter group
and returns a summary of the grouped pipes and the total cost.
:return: A tuple containing the grouped pipe data and the total cost of piping.
"""
pipe_groups = {}
total_cost = 0 # Initialize total cost
for u, v, data in self._network_graph.edges(data=True):
dn = data.get('nominal_diameter')
if dn is not None:
pipe_length = self._network_graph.edges[u, v].get('length', 1) * 2 # Multiply by 2 for supply and return
cost_per_meter = data.get('cost_per_meter', 0)
if dn not in pipe_groups:
pipe_groups[dn] = {
'DN': dn,
'total_length': 0,
'cost_per_meter': cost_per_meter
}
pipe_groups[dn]['total_length'] += pipe_length
group_cost = pipe_length * cost_per_meter
total_cost += group_cost # Add to total cost
# Calculate total cost for each group
for group in pipe_groups.values():
group['total_cost'] = group['total_length'] * group['cost_per_meter']
return pipe_groups, total_cost # Return both the grouped data and total cost
def save_pipe_groups_to_csv(self, filename):
"""
Save the pipe groups and their total lengths to a CSV file.
:param filename: The name of the CSV file to save the data to.
"""
pipe_groups, _ = self.analyze_costs()
with open(filename, mode='w', newline='') as file:
writer = csv.writer(file)
# Write the header
writer.writerow(["Nominal Diameter (DN)", "Total Length (m)", "Cost per Meter", "Total Cost"])
# Write the data for each pipe group
for group in pipe_groups.values():
writer.writerow([
group['DN'],
group['total_length'],
group['cost_per_meter'],
group['total_cost']
])

View File

@ -0,0 +1,372 @@
import json
import math
import logging
import matplotlib.pyplot as plt
import networkx as nx
from shapely.geometry import Polygon, Point, LineString
from typing import List, Tuple
from rtree import index
# Configure logging
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
logging.getLogger("numexpr").setLevel(logging.ERROR)
def haversine(lon1, lat1, lon2, lat2):
"""
Calculate the great-circle distance between two points
on the Earth specified by their longitude and latitude.
"""
R = 6371000 # Radius of the Earth in meters
phi1 = math.radians(lat1)
phi2 = math.radians(lat2)
delta_phi = math.radians(lat2 - lat1)
delta_lambda = math.radians(lon2 - lon1)
a = math.sin(delta_phi / 2.0) ** 2 + \
math.cos(phi1) * math.cos(phi2) * \
math.sin(delta_lambda / 2.0) ** 2
c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
return R * c # Output distance in meters
class DistrictHeatingNetworkCreator:
def __init__(self, buildings_file: str, roads_file: str, central_plant_locations: List[Tuple[float, float]]):
"""
Initialize the class with paths to the buildings and roads data files, and central plant locations.
:param buildings_file: Path to the GeoJSON file containing building data.
:param roads_file: Path to the GeoJSON file containing roads data.
:param central_plant_locations: List of tuples containing the coordinates of central plant locations.
"""
if len(central_plant_locations) < 1:
raise ValueError("The list of central plant locations must have at least one member.")
self.buildings_file = buildings_file
self.roads_file = roads_file
self.central_plant_locations = central_plant_locations
def run(self) -> nx.Graph:
"""
Main method to execute the district heating network creation process.
:return: NetworkX graph with nodes and edges representing the network.
"""
try:
self._load_and_process_data()
self._find_nearest_roads()
self._find_nearest_points()
self._break_down_roads()
self._create_graph()
self._create_mst()
self._iteratively_remove_edges()
self._add_centroids_to_mst()
self._convert_edge_weights_to_meters()
self._create_final_network_graph()
return self.network_graph
except Exception as e:
logging.error(f"Error during network creation: {e}")
raise
def _load_and_process_data(self):
"""
Load and process the building and road data.
"""
try:
# Load building data
with open(self.buildings_file, 'r') as file:
city = json.load(file)
self.centroids = []
self.building_names = []
self.building_positions = []
buildings = city['features']
for building in buildings:
coordinates = building['geometry']['coordinates'][0]
building_polygon = Polygon(coordinates)
centroid = building_polygon.centroid
self.centroids.append(centroid)
self.building_names.append(str(building['id']))
self.building_positions.append((centroid.x, centroid.y))
# Add central plant locations as centroids
for i, loc in enumerate(self.central_plant_locations, start=1):
centroid = Point(loc)
self.centroids.append(centroid)
self.building_names.append(f'central_plant_{i}')
self.building_positions.append((centroid.x, centroid.y))
# Load road data
with open(self.roads_file, 'r') as file:
roads = json.load(file)
line_features = [feature for feature in roads['features'] if feature['geometry']['type'] == 'LineString']
self.lines = [LineString(feature['geometry']['coordinates']) for feature in line_features]
self.cleaned_lines = [LineString([line.coords[0], line.coords[-1]]) for line in self.lines]
except Exception as e:
logging.error(f"Error loading and processing data: {e}")
raise
def _find_nearest_roads(self):
"""
Find the nearest road for each building centroid.
"""
try:
self.closest_roads = []
unique_roads_set = set()
# Create spatial index for roads
idx = index.Index()
for pos, line in enumerate(self.cleaned_lines):
idx.insert(pos, line.bounds)
for centroid in self.centroids:
min_distance = float('inf')
closest_road = None
for pos in idx.nearest(centroid.bounds, 10):
road = self.cleaned_lines[pos]
distance = road.distance(centroid)
if distance < min_distance:
min_distance = distance
closest_road = road
if closest_road and closest_road.wkt not in unique_roads_set:
unique_roads_set.add(closest_road.wkt)
self.closest_roads.append(closest_road)
except Exception as e:
logging.error(f"Error finding nearest roads: {e}")
raise
def _find_nearest_points(self):
"""
Find the nearest point on each closest road for each centroid.
"""
def find_nearest_point_on_line(point: Point, line: LineString) -> Point:
return line.interpolate(line.project(point))
try:
self.nearest_points = []
for centroid in self.centroids:
min_distance = float('inf')
closest_road = None
for road in self.closest_roads:
distance = centroid.distance(road)
if distance < min_distance:
min_distance = distance
closest_road = road
if closest_road:
nearest_point = find_nearest_point_on_line(centroid, closest_road)
self.nearest_points.append(nearest_point)
except Exception as e:
logging.error(f"Error finding nearest points: {e}")
raise
def _break_down_roads(self):
"""
Break down roads into segments connecting nearest points.
"""
def break_down_roads(closest_roads: List[LineString], nearest_points_list: List[Point]) -> List[LineString]:
new_segments = []
for road in closest_roads:
coords = list(road.coords)
points_on_road = [point for point in nearest_points_list if road.distance(point) < 0.000000001]
sorted_points = sorted(points_on_road, key=lambda point: road.project(point))
sorted_points.insert(0, Point(coords[0]))
sorted_points.append(Point(coords[-1]))
for i in range(len(sorted_points) - 1):
segment = LineString([sorted_points[i], sorted_points[i + 1]])
new_segments.append(segment)
return new_segments
try:
self.new_segments = break_down_roads(self.closest_roads, self.nearest_points)
self.cleaned_lines = [line for line in self.cleaned_lines if line not in self.closest_roads]
self.cleaned_lines.extend(self.new_segments)
except Exception as e:
logging.error(f"Error breaking down roads: {e}")
raise
def _create_graph(self):
"""
Create a NetworkX graph from the cleaned lines.
"""
try:
self.G = nx.Graph()
for line in self.cleaned_lines:
coords = list(line.coords)
for i in range(len(coords) - 1):
u = coords[i]
v = coords[i + 1]
self.G.add_edge(u, v, weight=Point(coords[i]).distance(Point(coords[i + 1])))
except Exception as e:
logging.error(f"Error creating graph: {e}")
raise
def _create_mst(self):
"""
Create a Minimum Spanning Tree (MST) from the graph.
"""
def find_paths_between_nearest_points(g: nx.Graph, nearest_points: List[Point]) -> List[Tuple]:
edges = []
for i, start_point in enumerate(nearest_points):
start = (start_point.x, start_point.y)
for end_point in nearest_points[i + 1:]:
end = (end_point.x, end_point.y)
if nx.has_path(g, start, end):
path = nx.shortest_path(g, source=start, target=end, weight='weight')
path_edges = list(zip(path[:-1], path[1:]))
edges.extend((u, v, g[u][v]['weight']) for u, v in path_edges)
return edges
try:
edges = find_paths_between_nearest_points(self.G, self.nearest_points)
h = nx.Graph()
h.add_weighted_edges_from(edges)
mst = nx.minimum_spanning_tree(h, weight='weight')
final_edges = []
for u, v in mst.edges():
if nx.has_path(self.G, u, v):
path = nx.shortest_path(self.G, source=u, target=v, weight='weight')
path_edges = list(zip(path[:-1], path[1:]))
final_edges.extend((x, y, self.G[x][y]['weight']) for x, y in path_edges)
self.final_mst = nx.Graph()
self.final_mst.add_weighted_edges_from(final_edges)
except Exception as e:
logging.error(f"Error creating MST: {e}")
raise
def _iteratively_remove_edges(self):
"""
Iteratively remove edges that do not have any nearest points and have one end with only one connection.
Also remove nodes that don't have any connections and street nodes with only one connection.
"""
nearest_points_tuples = [(point.x, point.y) for point in self.nearest_points]
def find_edges_to_remove(graph: nx.Graph) -> List[Tuple]:
edges_to_remove = []
for u, v, d in graph.edges(data=True):
if u not in nearest_points_tuples and v not in nearest_points_tuples:
if graph.degree(u) == 1 or graph.degree(v) == 1:
edges_to_remove.append((u, v, d))
return edges_to_remove
def find_nodes_to_remove(graph: nx.Graph) -> List[Tuple]:
nodes_to_remove = []
for node in graph.nodes():
if graph.degree(node) == 0:
nodes_to_remove.append(node)
return nodes_to_remove
try:
edges_to_remove = find_edges_to_remove(self.final_mst)
self.final_mst_steps = [list(self.final_mst.edges(data=True))]
while edges_to_remove or find_nodes_to_remove(self.final_mst):
self.final_mst.remove_edges_from(edges_to_remove)
nodes_to_remove = find_nodes_to_remove(self.final_mst)
self.final_mst.remove_nodes_from(nodes_to_remove)
edges_to_remove = find_edges_to_remove(self.final_mst)
self.final_mst_steps.append(list(self.final_mst.edges(data=True)))
def find_single_connection_street_nodes(graph: nx.Graph) -> List[Tuple]:
single_connection_street_nodes = []
for node in graph.nodes():
if node not in nearest_points_tuples and graph.degree(node) == 1:
single_connection_street_nodes.append(node)
return single_connection_street_nodes
single_connection_street_nodes = find_single_connection_street_nodes(self.final_mst)
while single_connection_street_nodes:
for node in single_connection_street_nodes:
neighbors = list(self.final_mst.neighbors(node))
self.final_mst.remove_node(node)
for neighbor in neighbors:
if self.final_mst.degree(neighbor) == 0:
self.final_mst.remove_node(neighbor)
single_connection_street_nodes = find_single_connection_street_nodes(self.final_mst)
self.final_mst_steps.append(list(self.final_mst.edges(data=True)))
except Exception as e:
logging.error(f"Error iteratively removing edges: {e}")
raise
def _add_centroids_to_mst(self):
"""
Add centroids to the final MST graph and connect them to their associated node on the graph.
"""
try:
for i, centroid in enumerate(self.centroids):
building_name = self.building_names[i]
pos = (centroid.x, centroid.y)
node_type = 'building' if 'central_plant' not in building_name else 'generation'
self.final_mst.add_node(pos, type=node_type, name=building_name, pos=pos)
nearest_point = None
min_distance = float('inf')
for node in self.final_mst.nodes():
if self.final_mst.nodes[node].get('type') != 'building' and self.final_mst.nodes[node].get('type') != 'generation':
distance = centroid.distance(Point(node))
if distance < min_distance:
min_distance = distance
nearest_point = node
if nearest_point:
self.final_mst.add_edge(pos, nearest_point, weight=min_distance)
except Exception as e:
logging.error(f"Error adding centroids to MST: {e}")
raise
def _convert_edge_weights_to_meters(self):
"""
Convert all edge weights in the final MST graph to meters using the Haversine formula.
"""
try:
for u, v, data in self.final_mst.edges(data=True):
distance = haversine(u[0], u[1], v[0], v[1])
self.final_mst[u][v]['weight'] = distance
except Exception as e:
logging.error(f"Error converting edge weights to meters: {e}")
raise
def _create_final_network_graph(self):
"""
Create the final network graph with the required attributes from the final MST.
"""
self.network_graph = nx.Graph()
node_id = 1
node_mapping = {}
for node in self.final_mst.nodes:
pos = node
if 'type' in self.final_mst.nodes[node]:
if self.final_mst.nodes[node]['type'] == 'building':
name = self.final_mst.nodes[node]['name']
node_type = 'building'
elif self.final_mst.nodes[node]['type'] == 'generation':
name = self.final_mst.nodes[node]['name']
node_type = 'generation'
else:
name = f'junction_{node_id}'
node_type = 'junction'
self.network_graph.add_node(node_id, name=name, type=node_type, pos=pos)
node_mapping[node] = node_id
node_id += 1
for u, v, data in self.final_mst.edges(data=True):
u_new = node_mapping[u]
v_new = node_mapping[v]
length = data['weight']
self.network_graph.add_edge(u_new, v_new, length=length)
def plot_network_graph(self):
"""
Plot the network graph using matplotlib and networkx.
"""
plt.figure(figsize=(15, 10))
pos = {node: data['pos'] for node, data in self.network_graph.nodes(data=True)}
nx.draw_networkx_nodes(self.network_graph, pos, node_color='blue', node_size=50)
nx.draw_networkx_edges(self.network_graph, pos, edge_color='gray')
plt.title('District Heating Network Graph')
plt.axis('off')
plt.show()

View File

@ -0,0 +1,61 @@
import json
import random
def right_hand_rule(polygon):
"""
Ensure coordinates follow the right-hand rule for polygons.
The right-hand rule implies that the vertices of the exterior ring of the polygon are ordered counterclockwise.
"""
def is_clockwise(coords):
total = 0
for i in range(len(coords)):
x1, y1 = coords[i]
x2, y2 = coords[(i + 1) % len(coords)]
total += (x2 - x1) * (y2 + y1)
return total > 0
for coords in polygon:
if is_clockwise(coords):
coords.reverse()
def process_geojson(geojson):
for i, feature in enumerate(geojson['features']):
# Check and correct the coordinate order
if feature['geometry']['type'] == "MultiPolygon":
for polygon in feature['geometry']['coordinates']:
right_hand_rule(polygon)
# Change geometry type to Polygon
feature['geometry']['type'] = "Polygon"
feature['geometry']['coordinates'] = feature['geometry']['coordinates'][0]
# Remove 'id' attribute from properties
if 'id' in feature['properties']:
del feature['properties']['id']
# Add new properties
feature['id'] = i + 1
feature['properties'].update({
"name": str(i + 1),
"address": "",
"function": random.choice([1000, 6199]),
"height": round(random.uniform(13, 30), 2),
"year_of_construction": 2023
})
# Load the GeoJSON file
with open('../../input_files/lachine_group_mach_buildings.geojson', 'r') as file:
geojson = json.load(file)
# Process the GeoJSON data
process_geojson(geojson)
# Save the processed GeoJSON to a new file
with open('processed_output.geojson', 'w') as file:
json.dump(geojson, file, indent=4)
print("GeoJSON processing complete.")

View File

@ -0,0 +1,54 @@
import json
from shapely import LineString, Point
import networkx as nx
from pathlib import Path
def networkx_to_geojson(graph: nx.Graph) -> Path:
"""
Convert a NetworkX graph to GeoJSON format.
:param graph: A NetworkX graph.
:return: GeoJSON formatted dictionary.
"""
features = []
for u, v, data in graph.edges(data=True):
line = LineString([u, v])
feature = {
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": list(line.coords)
},
"properties": {
"weight": data.get("weight", 1.0)
}
}
features.append(feature)
for node, data in graph.nodes(data=True):
point = Point(node)
feature = {
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": list(point.coords)[0]
},
"properties": {
"type": data.get("type", "unknown"),
"id": data.get("id", "N/A")
}
}
features.append(feature)
geojson = {
"type": "FeatureCollection",
"features": features
}
output_geojson_file = Path('./out_files/network_graph.geojson').resolve()
with open(output_geojson_file, 'w') as file:
json.dump(geojson, file, indent=4)
return output_geojson_file

View File

@ -0,0 +1,48 @@
import json
import random
# Function to process the GeoJSON for roads
def process_roads_geojson(geojson):
# Create the new structure
new_geojson = {
"type": "FeatureCollection",
"name": "lachine_roadfs",
"crs": {"type": "name", "properties": {"name": "urn:ogc:def:crs:OGC:1.3:CRS84"}},
"features": []
}
for i, feature in enumerate(geojson['features']):
# Convert MultiLineString to LineString if necessary
coordinates = feature['geometry']['coordinates']
if feature['geometry']['type'] == "MultiLineString":
coordinates = coordinates[0]
# Add the new properties
new_feature = {
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": coordinates
},
"properties": {
}
}
new_geojson['features'].append(new_feature)
return new_geojson
# Load the original GeoJSON file
with open('../../input_files/roads.geojson', 'r') as file:
original_geojson = json.load(file)
# Process the GeoJSON data
processed_geojson = process_roads_geojson(original_geojson)
# Save the processed GeoJSON to a new file
with open('../../input_files/processed_roads_output.geojson', 'w') as file:
json.dump(processed_geojson, file, indent=4)
print("GeoJSON roads processing complete.")

View File

@ -0,0 +1,56 @@
from pathlib import Path
from shapely.geometry import Polygon, Point, shape
import json
def road_processor(x, y, diff):
"""
Processes a .JSON file to find roads that have at least one node within a specified polygon.
Parameters:
x (float): The x-coordinate of the center of the selection box.
y (float): The y-coordinate of the center of the selection box.
diff (float): The half-width of the selection box.
Returns:
str: The file path of the output GeoJSON file containing the selected roads.
"""
diff += 2 * diff
# Define the selection polygon
selection_box = Polygon([
[x + diff, y - diff],
[x - diff, y - diff],
[x - diff, y + diff],
[x + diff, y + diff]
])
# Define input and output file paths
geojson_file = Path("./input_files/roads.geojson").resolve()
output_file = Path('./input_files/output_roads.geojson').resolve()
# Initialize a list to store the roads in the region
roads_in_region = []
# Read the GeoJSON file
with open(geojson_file, 'r') as file:
roads = json.load(file)
line_features = [feature for feature in roads['features'] if feature['geometry']['type'] == 'LineString']
# Check each road feature
for feature in line_features:
road_shape = shape(feature['geometry'])
# Check if any node of the road is inside the selection box
if any(selection_box.contains(Point(coord)) for coord in road_shape.coords):
roads_in_region.append(feature)
# Create a new GeoJSON structure with the selected roads
output_geojson = {
"type": "FeatureCollection",
"features": roads_in_region
}
# Write the selected roads to the output file
with open(output_file, 'w') as outfile:
json.dump(output_geojson, outfile)
return output_file

View File

@ -0,0 +1,86 @@
import pandas as pd
import numpy as np
class DemandShiftProcessor:
def __init__(self, city):
self.city = city
def random_shift(self, series):
shift_amount = np.random.randint(0, round(0.005 * len(series)))
return series.shift(shift_amount).fillna(series.shift(shift_amount - len(series)))
def process_demands(self):
heating_dfs = []
cooling_dfs = []
for building in self.city.buildings:
heating_df = self.convert_building_to_dataframe(building, 'heating')
cooling_df = self.convert_building_to_dataframe(building, 'cooling')
heating_df.set_index('Date/Time', inplace=True)
cooling_df.set_index('Date/Time', inplace=True)
shifted_heating_demands = heating_df.apply(self.random_shift, axis=0)
shifted_cooling_demands = cooling_df.apply(self.random_shift, axis=0)
self.update_building_demands(building, shifted_heating_demands, 'heating')
self.update_building_demands(building, shifted_cooling_demands, 'cooling')
heating_dfs.append(shifted_heating_demands)
cooling_dfs.append(shifted_cooling_demands)
combined_heating_df = pd.concat(heating_dfs, axis=1)
combined_cooling_df = pd.concat(cooling_dfs, axis=1)
self.calculate_and_set_simultaneity_factor(combined_heating_df, 'heating')
self.calculate_and_set_simultaneity_factor(combined_cooling_df, 'cooling')
self.save_demands_to_csv(combined_heating_df, 'heating_demands.csv')
self.save_demands_to_csv(combined_cooling_df, 'cooling_demands.csv')
def convert_building_to_dataframe(self, building, demand_type):
if demand_type == 'heating':
data = {
"Date/Time": self.generate_date_time_index(),
"Heating_Demand": building.heating_demand["hour"]
}
else: # cooling
data = {
"Date/Time": self.generate_date_time_index(),
"Cooling_Demand": building.cooling_demand["hour"]
}
return pd.DataFrame(data)
def generate_date_time_index(self):
# Generate hourly date time index for a full year in 2024
date_range = pd.date_range(start="2013-01-01 00:00:00", end="2013-12-31 23:00:00", freq='H')
return date_range.strftime('%m/%d %H:%M:%S').tolist()
def update_building_demands(self, building, shifted_demands, demand_type):
if demand_type == 'heating':
shifted_series = shifted_demands["Heating_Demand"]
building.heating_demand = self.calculate_new_demands(shifted_series)
else: # cooling
shifted_series = shifted_demands["Cooling_Demand"]
building.cooling_demand = self.calculate_new_demands(shifted_series)
def calculate_new_demands(self, shifted_series):
new_demand = {
"hour": shifted_series.tolist(),
"month": self.calculate_monthly_demand(shifted_series),
"year": [shifted_series.sum()]
}
return new_demand
def calculate_monthly_demand(self, series):
series.index = pd.to_datetime(series.index, format='%m/%d %H:%M:%S')
monthly_demand = series.resample('M').sum()
return monthly_demand.tolist()
def calculate_and_set_simultaneity_factor(self, combined_df, demand_type):
total_demand_original = combined_df.sum(axis=1)
peak_total_demand_original = total_demand_original.max()
individual_peak_demands = combined_df.max(axis=0)
sum_individual_peak_demands = individual_peak_demands.sum()
if demand_type == 'heating':
self.city.simultaneity_factor_heating = peak_total_demand_original / sum_individual_peak_demands
else: # cooling
self.city.simultaneity_factor_cooling = peak_total_demand_original / sum_individual_peak_demands
def save_demands_to_csv(self, df, filename):
df.to_csv(filename)

View File

@ -0,0 +1,26 @@
import random
import numpy as np
import hub.helpers.constants as cte
class EnergySystemOptimizer:
def __init__(self, building, objectives, population_size=20, number_of_generations=100, crossover_rate=0.8,
mutation_rate=0.1):
self.building = building
self.objectives = objectives
self.population_size = population_size
self.num_gen = number_of_generations
self.crossover_rate = crossover_rate
self.mutation_rate = mutation_rate
# Initialize population
def initialize_population(self):
population = []
for _ in range(self.population_size):
individual = [
random.uniform(0.1, 10.0), # hp_size
random.uniform(0.1, 10.0), # boiler_size
random.uniform(0.1, 10.0), # tes_size
random.uniform(40, 60) # cutoff_temp
]
population.append(individual)
return population

View File

@ -0,0 +1,16 @@
# Objective functions
MINIMUM_LCC = 1
MINIMUM_EC = 2
MINIMUM_EMISSIONS = 3
MINIMUM_LCC_MINIMUM_EC = 4
MINIMUM_LCC_MINIMUM_EMISSIONS = 5
MINIMUM_EC_MINIMUM_EMISSIONS = 6
MINIMUM_LCC_MINIMUM_EC_MINIMUM_EMISSIONS = 7
OBJECTIVE_FUNCTIONS = [MINIMUM_LCC,
MINIMUM_EC,
MINIMUM_EMISSIONS,
MINIMUM_LCC_MINIMUM_EC,
MINIMUM_LCC_MINIMUM_EMISSIONS,
MINIMUM_EC_MINIMUM_EMISSIONS,
MINIMUM_LCC_MINIMUM_EC_MINIMUM_EMISSIONS]

View File

@ -28,8 +28,8 @@ residential_systems_percentage = {'system 1 gas': 15,
'system 8 gas': 15,
'system 8 electricity': 35}
residential_new_systems_percentage = {'PV+ASHP+GasBoiler+TES': 100,
'PV+4Pipe+DHW': 0,
residential_new_systems_percentage = {'PV+ASHP+GasBoiler+TES': 0,
'PV+4Pipe+DHW': 100,
'PV+ASHP+ElectricBoiler+TES': 0,
'PV+GSHP+GasBoiler+TES': 0,
'PV+GSHP+ElectricBoiler+TES': 0,

View File

@ -5,7 +5,7 @@ from hub.helpers.monthly_values import MonthlyValues
class Archetype13:
def __init__(self, building, output_path):
def __init__(self, building, output_path, csv_output=True,):
self._building = building
self._name = building.name
self._pv_system = building.energy_systems[0]
@ -25,6 +25,7 @@ class Archetype13:
self._t_out = building.external_temperature[cte.HOUR]
self.results = {}
self.dt = 900
self.csv_output = csv_output
def hvac_sizing(self):
storage_factor = 3
@ -374,10 +375,11 @@ class Archetype13:
MonthlyValues.get_total_month(self._building.domestic_hot_water_consumption[cte.HOUR]))
self._building.domestic_hot_water_consumption[cte.YEAR] = [
sum(self._building.domestic_hot_water_consumption[cte.MONTH])]
file_name = f'energy_system_simulation_results_{self._name}.csv'
with open(self._output_path / file_name, 'w', newline='') as csvfile:
output_file = csv.writer(csvfile)
# Write header
output_file.writerow(self.results.keys())
# Write data
output_file.writerows(zip(*self.results.values()))
if self.csv_output:
file_name = f'energy_system_simulation_results_{self._name}.csv'
with open(self._output_path / file_name, 'w', newline='') as csvfile:
output_file = csv.writer(csvfile)
# Write header
output_file.writerow(self.results.keys())
# Write data
output_file.writerows(zip(*self.results.values()))

View File

@ -1,54 +0,0 @@
from pathlib import Path
import subprocess
from scripts.ep_run_enrich import energy_plus_workflow
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
from hub.imports.results_factory import ResultFactory
from scripts.energy_system_retrofit_report import EnergySystemRetrofitReport
from scripts.geojson_creator import process_geojson
from scripts import random_assignation
from hub.imports.energy_systems_factory import EnergySystemsFactory
from scripts.energy_system_sizing import SystemSizing
from scripts.solar_angles import CitySolarAngles
from scripts.pv_sizing_and_simulation import PVSizingSimulation
from scripts.energy_system_retrofit_results import consumption_data, cost_data
from scripts.energy_system_sizing_and_simulation_factory import EnergySystemsSimulationFactory
from scripts.costs.cost import Cost
from scripts.costs.constants import SKIN_RETROFIT_AND_SYSTEM_RETROFIT_AND_PV, SYSTEM_RETROFIT_AND_PV, CURRENT_STATUS
import hub.helpers.constants as cte
from hub.exports.exports_factory import ExportsFactory
from scripts.pv_feasibility import pv_feasibility
# Specify the GeoJSON file path
input_files_path = (Path(__file__).parent / 'input_files')
input_files_path.mkdir(parents=True, exist_ok=True)
geojson_file = process_geojson(x=-73.5681295982132, y=45.49218262677643, diff=0.0001)
geojson_file_path = input_files_path / 'output_buildings.geojson'
output_path = (Path(__file__).parent / 'out_files').resolve()
output_path.mkdir(parents=True, exist_ok=True)
energy_plus_output_path = output_path / 'energy_plus_outputs'
energy_plus_output_path.mkdir(parents=True, exist_ok=True)
simulation_results_path = (Path(__file__).parent / 'out_files' / 'simulation_results').resolve()
simulation_results_path.mkdir(parents=True, exist_ok=True)
sra_output_path = output_path / 'sra_outputs'
sra_output_path.mkdir(parents=True, exist_ok=True)
cost_analysis_output_path = output_path / 'cost_analysis'
cost_analysis_output_path.mkdir(parents=True, exist_ok=True)
city = GeometryFactory(file_type='geojson',
path=geojson_file_path,
height_field='height',
year_of_construction_field='year_of_construction',
function_field='function',
function_to_hub=Dictionaries().montreal_function_to_hub_function).city
ConstructionFactory('nrcan', city).enrich()
UsageFactory('nrcan', city).enrich()
WeatherFactory('epw', city).enrich()
energy_plus_workflow(city, energy_plus_output_path)
random_assignation.call_random(city.buildings, random_assignation.residential_new_systems_percentage)
EnergySystemsFactory('montreal_future', city).enrich()
for building in city.buildings:
EnergySystemsSimulationFactory('archetype1', building=building, output_path=simulation_results_path).enrich()

749
summer_school.py Normal file
View File

@ -0,0 +1,749 @@
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
from pathlib import Path
import subprocess
from hub.imports.results_factory import ResultFactory
from hub.imports.energy_systems_factory import EnergySystemsFactory
from scripts.energy_system_sizing_and_simulation_factory import EnergySystemsSimulationFactory
from scripts.solar_angles import CitySolarAngles
import hub.helpers.constants as cte
from hub.exports.exports_factory import ExportsFactory
from scripts.pv_sizing_and_simulation import PVSizingSimulation
import pandas as pd
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)
energy_plus_output_path = output_path / 'energy_plus_outputs'
energy_plus_output_path.mkdir(parents=True, exist_ok=True)
simulation_results_path = (Path(__file__).parent / 'out_files' / 'simulation_results').resolve()
simulation_results_path.mkdir(parents=True, exist_ok=True)
sra_output_path = output_path / 'sra_outputs'
sra_output_path.mkdir(parents=True, exist_ok=True)
cost_analysis_output_path = output_path / 'cost_analysis'
cost_analysis_output_path.mkdir(parents=True, exist_ok=True)
#%%-----------------------------------------------
#"""add geojson paths and create city for Baseline"""
#%% # -----------------------------------------------
geojson_file_path_baseline = output_path / 'updated_buildings_with_all_data_baseline.geojson'
geojson_file_path_2024 = output_path / 'updated_buildings_with_all_data_2024.geojson'
with open(geojson_file_path_baseline , 'r') as f:
building_type_data = json.load(f)
with open(geojson_file_path_2024, 'r') as f:
building_type_data_2024 = json.load(f)
# Create city object from GeoJSON file
city = GeometryFactory('geojson',
path=geojson_file_path_baseline,
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)
#%% # -----------------------------------------------
#"""Enrich city with geojson file data"""
#%% # -----------------------------------------------
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)
print('test')
#%%-----------------------------------------------
# """ADD energy systems"""
#%% # -----------------------------------------------
for building in city.buildings:
building.energy_systems_archetype_name = 'system 1 electricity'
EnergySystemsFactory('montreal_custom', city).enrich()
def baseline_to_dict(building):
return {
'heating_consumption_kWh': [x / (cte.WATTS_HOUR_TO_JULES * 1000) for x in building.heating_consumption[cte.HOUR]],
'cooling_consumption_kWh':[x / (cte.WATTS_HOUR_TO_JULES * 1000) for x in building.cooling_consumption[cte.HOUR]],
'domestic_hot_water_consumption_kWh': [x / (cte.WATTS_HOUR_TO_JULES * 1000) for x in building.domestic_hot_water_consumption[cte.HOUR]],
'appliances_consumption_kWh':[x / (cte.WATTS_HOUR_TO_JULES * 1000) for x in building.appliances_electrical_demand[cte.HOUR]],
'lighting_consumption_kWh': [x / (cte.WATTS_HOUR_TO_JULES * 1000) for x in building.lighting_electrical_demand[cte.HOUR]]
}
buildings_dic={}
for building in city.buildings:
buildings_dic[building.name]=baseline_to_dict(building)
scenario={}
scenario['baseline']=buildings_dic
print("Scenario 1: Baseline is performed successfully")
del city
del buildings_dic
del building_type_data
#%%-----------------------------------------------
# Scenario 2
#%% # -----------------------------------------------
# Create city object from GeoJSON file
city = GeometryFactory('geojson',
path=geojson_file_path_2024,
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()
enrich_buildings_with_geojson_data (building_type_data_2024, city)
def to_dict(building,hourly_pv):
return {
'heating_consumption_kWh': [x / (cte.WATTS_HOUR_TO_JULES * 1000) for x in building.heating_consumption[cte.HOUR]],
'cooling_consumption_kWh':[x / (cte.WATTS_HOUR_TO_JULES * 1000) for x in building.cooling_consumption[cte.HOUR]],
'domestic_hot_water_consumption_kWh': [x / (cte.WATTS_HOUR_TO_JULES * 1000) for x in building.domestic_hot_water_consumption[cte.HOUR]],
'appliances_consumption_kWh':[x / (cte.WATTS_HOUR_TO_JULES * 1000) for x in building.appliances_electrical_demand[cte.HOUR]],
'lighting_consumption_kWh': [x / (cte.WATTS_HOUR_TO_JULES * 1000) for x in building.lighting_electrical_demand[cte.HOUR]],
'hourly_pv_kWh': [x /(cte.WATTS_HOUR_TO_JULES * 1000) for x in hourly_pv]
}
buildings_dic={}
for building in city.buildings:
building.energy_systems_archetype_name = 'system 1 electricity pv'
EnergySystemsFactory('montreal_custom', city).enrich()
# #%%-----------------------------------------------
# # """SRA"""
# #%% # -----------------------------------------------
ExportsFactory('sra', city, output_path).export()
sra_path = (output_path / f'{city.name}_sra.xml').resolve()
subprocess.run(['sra', str(sra_path)])
ResultFactory('sra', city, output_path).enrich()
solar_angles = CitySolarAngles(city.name,
city.latitude,
city.longitude,
tilt_angle=45,
surface_azimuth_angle=180).calculate
df = pd.DataFrame()
df.index = ['yearly lighting (kWh)', 'yearly appliance (kWh)', 'yearly heating (kWh)', 'yearly cooling (kWh)',
'yearly dhw (kWh)', 'roof area (m2)', 'used area for pv (m2)', 'number of panels', 'pv production (kWh)']
for building in city.buildings:
ghi = [x / cte.WATTS_HOUR_TO_JULES for x in building.roofs[0].global_irradiance[cte.HOUR]]
pv_sizing_simulation = PVSizingSimulation(building,
solar_angles,
tilt_angle=45,
module_height=1,
module_width=2,
ghi=ghi)
pv_sizing_simulation.pv_output()
yearly_lighting = building.lighting_electrical_demand[cte.YEAR][0] / 1000
yearly_appliance = building.appliances_electrical_demand[cte.YEAR][0] / 1000
yearly_heating = building.heating_demand[cte.YEAR][0] / (3.6e6 * 3)
yearly_cooling = building.cooling_demand[cte.YEAR][0] / (3.6e6 * 4.5)
yearly_dhw = building.domestic_hot_water_heat_demand[cte.YEAR][0] / 1000
roof_area = building.roofs[0].perimeter_area
used_roof = pv_sizing_simulation.available_space()
number_of_pv_panels = pv_sizing_simulation.total_number_of_panels
yearly_pv = building.onsite_electrical_production[cte.YEAR][0] / (3.6e6)
hourly_pv = building.onsite_electrical_production[cte.HOUR]
df[f'{building.name}'] = [yearly_lighting, yearly_appliance, yearly_heating, yearly_cooling, yearly_dhw, roof_area,
used_roof, number_of_pv_panels, yearly_pv]
buildings_dic[building.name]=to_dict(building,hourly_pv)
# %%-----------------------------------------------
# """South facing facades"""
# %% # -----------------------------------------------
# Function to convert radians to degrees
import math
def radians_to_degrees(radians):
return radians * (180 / math.pi)
# Step 1: Create the walls_id dictionary
walls_id={}
for building in city.buildings:
ids = {}
for walls in building.walls:
id=walls.id
azimuth_degree=radians_to_degrees(float(walls.azimuth))
if azimuth_degree>90.0 or azimuth_degree <float(-90.0):
ids[id]= {
'azimuth': azimuth_degree,
'global_irradiance': walls.global_irradiance[cte.HOUR],
'area': walls.perimeter_area
}
walls_id[building.name] = ids
# Step 2: Calculate pv_on_facade for each wall
for building_id, ids in walls_id.items():
for wall_id, wall_data in ids.items():
if 'global_irradiance' in wall_data:
ghi = [x / cte.WATTS_HOUR_TO_JULES/1000 for x in wall_data['global_irradiance']]
wall_data['pv_on_facade'] = [x * 0.6 * wall_data['area']*0.22 for x in ghi]
walls_dic = output_path / 'walls_id.json'
with open(walls_dic , 'w') as json_file:
json.dump(walls_id, json_file, indent=4)
import pandas as pd
#### EXPORT
# Convert walls_id dictionary to a DataFrame
# Convert walls_id dictionary to DataFrames for static and hourly data
# def convert_walls_id_to_dfs(walls_id):
# static_data = {}
# hourly_data = {}
#
# for building_id, ids in walls_id.items():
# for wall_id, wall_data in ids.items():
# # Static data
# static_data[f"{building_id}_{wall_id}_azimuth"] = wall_data.get('azimuth', None)
# static_data[f"{building_id}_{wall_id}_area"] = wall_data.get('area', None)
#
# if 'pv_on_facade' in wall_data:
# hourly_data[f"{building_id}_{wall_id}_pv_on_facade"] = wall_data['pv_on_facade']
#
# # Create DataFrames
# static_df = pd.DataFrame([static_data])
# hourly_df = pd.DataFrame(hourly_data)
#
# return static_df, hourly_df
# output_path_walls_id_dic =output_path / 'walls_id_data.xlsx'
#
# static_df, hourly_df = convert_walls_id_to_dfs(walls_id)
# with pd.ExcelWriter(output_path_walls_id_dic) as writer:
# static_df.to_excel(writer, sheet_name='Static Data', index=False)
# hourly_df.to_excel(writer, sheet_name='Hourly Data', index=False)
# print(f"Data successfully exported to {output_path}")
# # Save the DataFrame to an Excel file
df.to_csv(output_path / 'pv.csv')
scenario['efficient with PV']=buildings_dic
print("Scenario 2: efficient with PV run successfully")
#%%-----------------------------------------------
# Scenario 3
#%% # -----------------------------------------------
for building in city.buildings:
building.energy_systems_archetype_name = 'PV+4Pipe+DHW'
EnergySystemsFactory('montreal_future', city).enrich()
buildings_dic = {}
for building in city.buildings:
EnergySystemsSimulationFactory('archetype13', building=building, output_path=simulation_results_path).enrich()
buildings_dic[building.name] = to_dict(building, hourly_pv)
scenario['efficient with PV+4Pipe+DHW']=buildings_dic
print("Scenario 3: efficient with PV+4Pipe+DHW run successfully")
def extract_HP_size(building):
dic={
# Heat Pump Rated Heating and Cooling Output
'hp_heat_size': building.energy_systems[1].generation_systems[1].nominal_heat_output/1000,
'hp_cooling_output': building.energy_systems[1].generation_systems[1].nominal_cooling_output/1000,
# Boiler Rated Heat Output
'boiler_heat_output': building.energy_systems[1].generation_systems[0].nominal_heat_output/1000,
# TES characteristics
'tes_volume':building.energy_systems[1].generation_systems[0].energy_storage_systems[0].volume,
'tes_height':building.energy_systems[1].generation_systems[0].energy_storage_systems[0].height,
# DHW HP
'dhw_hp_heat_output': building.energy_systems[-1].generation_systems[0].nominal_heat_output/1000,
# DHW TES Characteristics
'dhw_tes_volume': building.energy_systems[-1].generation_systems[0].energy_storage_systems[0].volume,
'dhw_tes_height': building.energy_systems[-1].generation_systems[0].energy_storage_systems[0].height,
}
return dic
HPs={}
for building in city.buildings:
HPs[building.name]=extract_HP_size(building)
#%%-------------------------------------------------------
#""""EXPORTERS"""
#%%-------------------------------------------------------
# Convert the dictionary to a DataFrame
df = pd.DataFrame.from_dict(HPs, orient='index')
# Save the DataFrame to an Excel file
output_path_HPs =output_path/ 'HPs_data.xlsx'
df.to_excel(output_path_HPs, index_label='building_id')
print(f"Data successfully exported to {output_path}")
import pandas as pd
districts_demands={}
def extract_and_sum_demand_data(scenario, demand_types):
# Conversion factor constant
conversion_factor = 1 / (cte.WATTS_HOUR_TO_JULES * 1000)
# Loop through each scenario
for scenario_key, buildings in scenario.items():
# Loop through each building in the scenario
# Initialize an empty dictionary to store the district demand sums
district_demand = {demand_type: [0] * 8760 for demand_type in demand_types}
district_demand['hourly_pv_kWh']= [0] * 8760
for building_id, building_data in buildings.items():
# Loop through each demand type and sum up the data
for demand_type in demand_types:
if demand_type in building_data:
district_demand[demand_type] = [sum(x) for x in zip(district_demand[demand_type], building_data[demand_type])]
# If PV data is available and relevant
if scenario_key == "efficient with PV":
district_demand['hourly_pv_kWh'] = [sum(x) for x in zip(district_demand['hourly_pv_kWh'], building_data['hourly_pv_kWh'])]
if scenario_key == 'efficient with PV+4Pipe+DHW':
district_demand['hourly_pv_kWh'] = districts_demands["efficient with PV"]['hourly_pv_kWh']
districts_demands[scenario_key]=district_demand
return districts_demands
# Example usage
# Assuming 'scenario' is a dictionary with the required structure and 'cte' is defined somewhere with WATTS_HOUR_TO_JULES constant
demand_types = [
'heating_consumption_kWh',
'cooling_consumption_kWh',
'domestic_hot_water_consumption_kWh',
'appliances_consumption_kWh',
'lighting_consumption_kWh',
# 'hourly_pv_kWh' # Include this only if you want to consider PV data
]
# # Call the function with your scenario data
district_demand = extract_and_sum_demand_data(scenario, demand_types)
#
# """"EXPORTERS"""
# import pandas as pd
#
#
# Export the DataFrame to an Excel file
excel_file_path = r'C:\Users\a_gabald\PycharmProjects\summer_course_2024\out_files\districts_balance.xlsx'
# df.to_excel(excel_file_path, index=True, index_label='Building')
# Create an Excel writer object
with pd.ExcelWriter(excel_file_path, engine='xlsxwriter') as writer:
for scenarios,demands in district_demand.items():
# Convert demands to a DataFrame
df_demands = pd.DataFrame(demands)
# Convert building_id to string and check its length
sheet_name = str(scenarios)
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)
print("district balance data is exported successfully")
import pandas as pd
# Assuming your scenario dictionary is already defined as follows:
# scenario = {
# 'baseline': { ... },
# 'efficient with PV': { ... }
# }
def dict_to_df_col_wise(building_data):
"""
Converts a dictionary of building data to a DataFrame.
Args:
building_data (dict): Dictionary containing building data where keys are building ids and values are dictionaries
with hourly data for various demand types.
Returns:
pd.DataFrame: DataFrame with columns for each building and demand type.
"""
# Create a dictionary to hold DataFrames for each demand type
df_dict= {}
# Loop over each building
for building_id, data in building_data.items():
# Create a DataFrame for this building's data
building_df = pd.DataFrame(data)
# Rename columns to include building_id
building_df.columns = [f"{building_id}_{col}" for col in building_df.columns]
# Add this DataFrame to the dictionary
df_dict[building_id] = building_df
# Concatenate all building DataFrames column-wise
result_df = pd.concat(df_dict.values(), axis=1)
return result_df
# Create DataFrames for each scenario
baseline_df = dict_to_df_col_wise(scenario['baseline'])
efficient_with_pv_df = dict_to_df_col_wise(scenario['efficient with PV'])
efficient_with_pv_hps = dict_to_df_col_wise(scenario['efficient with PV+4Pipe+DHW'])
# Write the DataFrames to an Excel file with two separate sheets
with pd.ExcelWriter(r'C:\Users\a_gabald\PycharmProjects\summer_course_2024\out_files\scenario_data.xlsx') as writer:
baseline_df.to_excel(writer, sheet_name='baseline', index=True)
efficient_with_pv_df.to_excel(writer, sheet_name='efficient with PV', index=True)
efficient_with_pv_hps.to_excel(writer, sheet_name='efficient with HPs', index=True)
print("hourly data has been successfully exported per building to scenario_data.xlsx")
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
def convert_hourly_to_monthly(hourly_data):
"""
Converts hourly data to monthly data by summing up the values for each month.
Args:
hourly_data (list): List of hourly data (length 8760).
Returns:
list: List of monthly data (length 12).
"""
hourly_series = pd.Series(hourly_data, index=pd.date_range(start='1/1/2023', periods=8760, freq='H'))
monthly_data = hourly_series.resample('M').sum()
return monthly_data.tolist()
import os
def plot_stacked_demands_vs_pv(district_demand, demand_types, output_path, pv_type='hourly_pv_kWh'):
"""
Plots the stacked monthly demand for each scenario and compares it to the PV data.
Args:
district_demand (dict): Dictionary with scenario keys and demand data.
demand_types (list): List of demand types to plot.
output_path (str): Path to save the plots.
pv_type (str): The PV data type to compare against.
"""
os.makedirs(output_path, exist_ok=True)
for scenario_key, demand_data in district_demand.items():
# Convert hourly data to monthly data for each demand type
monthly_data = {demand_type: convert_hourly_to_monthly(demand_data[demand_type]) for demand_type in
demand_types}
monthly_pv = convert_hourly_to_monthly(demand_data.get(pv_type, [0] * 8760))
# Create a DataFrame for easier plotting
combined_data = pd.DataFrame(monthly_data)
combined_data['Month'] = range(1, 13)
combined_data['PV'] = monthly_pv
# Plotting
fig, ax1 = plt.subplots(figsize=(14, 8))
# Plot stacked demands
combined_data.set_index('Month', inplace=True)
combined_data[demand_types].plot(kind='bar', stacked=True, ax=ax1, colormap='tab20')
ax1.set_xlabel('Month')
ax1.set_ylabel('Energy Demand (kWh)')
ax1.set_title(f'Monthly Energy Demand and PV Generation for {scenario_key}')
# Plot PV data on the secondary y-axis
ax2 = ax1.twinx()
ax2.plot(combined_data.index, combined_data['PV'], color='black', linestyle='-', marker='o',
label='PV Generation')
ax2.set_ylabel('PV Generation (kWh)')
# Add legends
ax1.legend(loc='upper left')
ax2.legend(loc='upper right')
ax1.set_xticks(combined_data.index)
ax1.set_xticklabels(['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'])
# Save the plot
plt.savefig(os.path.join(output_path, f'{scenario_key}_monthly_demand_vs_pv.png'))
plt.close()
# Example usage
# district_demand = extract_and_sum_demand_data(scenario, demand_types)
# Specify the demand types and PV type
demand_types = [
'heating_consumption_kWh',
'cooling_consumption_kWh',
'domestic_hot_water_consumption_kWh',
'appliances_consumption_kWh',
'lighting_consumption_kWh'
]
# Plot the data
plot_stacked_demands_vs_pv(district_demand, demand_types, output_path)
# Plot the data
print('test')
import csv
clusters=pd.read_csv(output_path/'clusters.csv')
# Step 2: Extract the demand data for each building
def extract_building_demand(city):
building_demand = {}
for building in city.buildings:
demands = {
'heating_demand': [x / 1000 * cte.WATTS_HOUR_TO_JULES for x in building.heating_demand[cte.HOUR]],
'cooling_demand': [x / 1000 * cte.WATTS_HOUR_TO_JULES for x in building.cooling_demand[cte.HOUR]],
'domestic_hot_water_demand': [x / 1000 * cte.WATTS_HOUR_TO_JULES for x in building.domestic_hot_water_heat_demand[cte.HOUR]],
'appliances_electrical_demand': [x / 1000 * cte.WATTS_HOUR_TO_JULES for x in building.appliances_electrical_demand[cte.HOUR]],
'lighting_electrical_demand': [x / 1000 * cte.WATTS_HOUR_TO_JULES for x in building.lighting_electrical_demand[cte.HOUR]]
}
building_demand[building.name] = demands
return building_demand
# Step 3: Sum the demand types for each cluster
def sum_demands_by_cluster(building_demand, clusters, demand_types):
cluster_demands = {cluster: {demand_type: [0] * 8760 for demand_type in demand_types} for cluster in clusters['cluster'].unique()}
for _, row in clusters.iterrows():
building_id = str(row['id'])
cluster = row['cluster']
if building_id in building_demand:
for demand_type in demand_types:
cluster_demands[cluster][demand_type] = [sum(x) for x in zip(cluster_demands[cluster][demand_type], building_demand[building_id][demand_type])]
return cluster_demands
def plot_demands_by_cluster(cluster_demands, demand_types, output_folder):
import os
os.makedirs(output_folder, exist_ok=True)
for cluster, demands in cluster_demands.items():
plt.figure(figsize=(15, 10))
for demand_type in demand_types:
plt.plot(demands[demand_type], label=demand_type)
plt.title(f'Summed Demands for Cluster {cluster}')
plt.xlabel('Hour of the Year')
plt.ylabel('Demand (kWh)')
plt.legend(loc='upper right')
plt.grid(True)
plt.tight_layout()
plt.savefig(os.path.join(output_folder, f'cluster_{cluster}_summed_demands.png'))
plt.close()
# Example usage
demand_types = [
'heating_demand',
'cooling_demand',
'domestic_hot_water_demand',
'appliances_electrical_demand',
'lighting_electrical_demand'
]
# Extract the building demand data
building_demand = extract_building_demand(city)
cluster_demands = sum_demands_by_cluster(building_demand, clusters, demand_types)
# Create a DataFrame to export the results
cluster_demands_df = {f"{cluster}_{demand_type}": data for cluster, demands in cluster_demands.items() for
demand_type, data in demands.items()}
cluster_demands_df = pd.DataFrame(cluster_demands_df)
# Save the results to an Excel file
cluster_demands_df.to_excel(output_path/'cluster_demands.xlsx', index=False)
print(f"Clustered demand data successfully exported to {output_path}")
#%%-----------------------------------------------
# Scenario 4
#%% # -----------------------------------------------
del city
del buildings_dic
geojson_file_path_clusters= output_path / 'new.geojson'
with open(geojson_file_path_clusters , 'r') as f:
building_type_data_new = json.load(f)
# Create city object from GeoJSON file
city = GeometryFactory('geojson',
path=geojson_file_path_clusters,
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()
buildings_clusters={
1651: 4,
1662: 0,
1667: 1,
1674: 2,
1688: 3
}
for building_id in buildings_clusters:
cluster=buildings_clusters[building_id]
for idx, feature in enumerate(building_type_data_new['features']):
if feature['properties']['id'] == str(building_id):
building_type_data_new['features'][idx]['properties']['heating_demand_kWh']=cluster_demands[cluster]['heating_demand']
building_type_data_new['features'][idx]['properties']['cooling_demand_kWh'] = cluster_demands[cluster]['cooling_demand']
building_type_data_new['features'][idx]['properties']['domestic_hot_water_heat_demand_kWh'] = cluster_demands[cluster]['domestic_hot_water_demand']
building_type_data_new['features'][idx]['properties']['appliances_electrical_demand_kWh'] = cluster_demands[cluster]['appliances_electrical_demand']
building_type_data_new['features'][idx]['properties']['lighting_electrical_demand_kWh'] = cluster_demands[cluster]['lighting_electrical_demand']
enrich_buildings_with_geojson_data (building_type_data_new, city)
for building in city.buildings:
building.energy_systems_archetype_name = 'PV+4Pipe+DHW'
EnergySystemsFactory('montreal_future', city).enrich()
buildings_dic = {}
for building in city.buildings:
EnergySystemsSimulationFactory('archetype13', building=building, output_path=simulation_results_path).enrich()
buildings_dic[building.name] = to_dict(building, hourly_pv)
scenario['efficient with PV+4Pipe+DHW']=buildings_dic
print("Scenario 4: efficient with PV+4Pipe+DHW run successfully for Clusters")
def extract_HP_size(building):
dic={
# Heat Pump Rated Heating and Cooling Output
'hp_heat_size': building.energy_systems[1].generation_systems[1].nominal_heat_output/1000,
'hp_cooling_output': building.energy_systems[1].generation_systems[1].nominal_cooling_output/1000,
# Boiler Rated Heat Output
'boiler_heat_output': building.energy_systems[1].generation_systems[0].nominal_heat_output/1000,
# TES characteristics
'tes_volume':building.energy_systems[1].generation_systems[0].energy_storage_systems[0].volume,
'tes_height':building.energy_systems[1].generation_systems[0].energy_storage_systems[0].height,
# DHW HP
'dhw_hp_heat_output': building.energy_systems[-1].generation_systems[0].nominal_heat_output/1000,
# DHW TES Characteristics
'dhw_tes_volume': building.energy_systems[-1].generation_systems[0].energy_storage_systems[0].volume,
'dhw_tes_height': building.energy_systems[-1].generation_systems[0].energy_storage_systems[0].height,
}
return dic
HPs={}
for building in city.buildings:
HPs[building.name]=extract_HP_size(building)
#%%-------------------------------------------------------
#""""EXPORTERS"""
#%%-------------------------------------------------------
# Convert the dictionary to a DataFrame
df = pd.DataFrame.from_dict(HPs, orient='index')
# Save the DataFrame to an Excel file
output_path_HPs =output_path/ 'HPs_data_sc4.xlsx'
df.to_excel(output_path_HPs, index_label='building_id')
print(f"Data successfully exported to {output_path}")