Compare commits
28 Commits
a147afe76f
...
6b89008698
Author | SHA1 | Date | |
---|---|---|---|
6b89008698 | |||
0f982df32e | |||
c38b025c2e | |||
4d0f247a83 | |||
e44abc2f3a | |||
421c69e97e | |||
2292bff1b8 | |||
1abf76125f | |||
ce995c375d | |||
2cc938e416 | |||
eb246a18e6 | |||
57322e1b19 | |||
24324988b6 | |||
ee419b0849 | |||
f95c45660e | |||
4add8b2cff | |||
5afb60e7c4 | |||
35e50cf551 | |||
066a25bfee | |||
0d63a6c4e9 | |||
e82d20bfd7 | |||
a3d4390a19 | |||
c5c298d708 | |||
1ae07cc14f | |||
37c09df932 | |||
92f0c81109 | |||
a8c961f7bc | |||
2c7fc66423 |
3
cerc_hub.egg-info/.gitignore
vendored
Normal file
3
cerc_hub.egg-info/.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# Except this file
|
||||||
|
*
|
||||||
|
!.gitignore
|
|
@ -34,7 +34,7 @@ class Archetype:
|
||||||
Get name
|
Get name
|
||||||
:return: string
|
:return: string
|
||||||
"""
|
"""
|
||||||
return f'{self._name}_lod{self._lod}'
|
return self._name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def systems(self) -> List[System]:
|
def systems(self) -> List[System]:
|
||||||
|
|
|
@ -55,7 +55,7 @@ class System:
|
||||||
Get name
|
Get name
|
||||||
:return: string
|
:return: string
|
||||||
"""
|
"""
|
||||||
return f'{self._name}_lod{self._lod}'
|
return self._name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def demand_types(self):
|
def demand_types(self):
|
||||||
|
|
|
@ -385,6 +385,42 @@ class Building(CityObject):
|
||||||
"""
|
"""
|
||||||
self._domestic_hot_water_heat_demand = value
|
self._domestic_hot_water_heat_demand = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def lighting_peak_load(self) -> Union[None, dict]:
|
||||||
|
"""
|
||||||
|
Get lighting peak load in W
|
||||||
|
:return: dict{[float]}
|
||||||
|
"""
|
||||||
|
results = {}
|
||||||
|
peak_lighting = 0
|
||||||
|
for thermal_zone in self.thermal_zones:
|
||||||
|
lighting = thermal_zone.lighting
|
||||||
|
for schedule in lighting.schedules:
|
||||||
|
peak = max(schedule.values) * lighting.density * thermal_zone.total_floor_area
|
||||||
|
if peak > peak_lighting:
|
||||||
|
peak_lighting = peak
|
||||||
|
results[cte.MONTH] = [peak for _ in range(0, 12)]
|
||||||
|
results[cte.YEAR] = [peak]
|
||||||
|
return results
|
||||||
|
|
||||||
|
@property
|
||||||
|
def appliances_peak_load(self) -> Union[None, dict]:
|
||||||
|
"""
|
||||||
|
Get appliances peak load in W
|
||||||
|
:return: dict{[float]}
|
||||||
|
"""
|
||||||
|
results = {}
|
||||||
|
peak_appliances = 0
|
||||||
|
for thermal_zone in self.thermal_zones:
|
||||||
|
appliances = thermal_zone.appliances
|
||||||
|
for schedule in appliances.schedules:
|
||||||
|
peak = max(schedule.values) * appliances.density * thermal_zone.total_floor_area
|
||||||
|
if peak > peak_appliances:
|
||||||
|
peak_appliances = peak
|
||||||
|
results[cte.MONTH] = [peak for _ in range(0, 12)]
|
||||||
|
results[cte.YEAR] = [peak]
|
||||||
|
return results
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def heating_peak_load(self) -> Union[None, dict]:
|
def heating_peak_load(self) -> Union[None, dict]:
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -7,10 +7,13 @@ Project Coder Pilar Monsalvete Alvarez de uribarri pilar.monsalvete@concordia.ca
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
import requests
|
||||||
|
|
||||||
from hub.exports.building_energy.energy_ade import EnergyAde
|
from hub.exports.building_energy.energy_ade import EnergyAde
|
||||||
from hub.exports.building_energy.idf import Idf
|
from hub.exports.building_energy.idf import Idf
|
||||||
from hub.exports.building_energy.insel.insel_monthly_energy_balance import InselMonthlyEnergyBalance
|
from hub.exports.building_energy.insel.insel_monthly_energy_balance import InselMonthlyEnergyBalance
|
||||||
from hub.helpers.utils import validate_import_export_type
|
from hub.helpers.utils import validate_import_export_type
|
||||||
|
from hub.imports.weather.helpers.weather import Weather as wh
|
||||||
|
|
||||||
|
|
||||||
class EnergyBuildingsExportsFactory:
|
class EnergyBuildingsExportsFactory:
|
||||||
|
@ -49,8 +52,11 @@ class EnergyBuildingsExportsFactory:
|
||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
idf_data_path = (Path(__file__).parent / './building_energy/idf_files/').resolve()
|
idf_data_path = (Path(__file__).parent / './building_energy/idf_files/').resolve()
|
||||||
# todo: create a get epw file function based on the city
|
url = wh().epw_file(self._city.region_code)
|
||||||
weather_path = (Path(__file__).parent / '../data/weather/epw/CAN_PQ_Montreal.Intl.AP.716270_CWEC.epw').resolve()
|
weather_path = (Path(__file__).parent.parent / f'data/weather/epw/{url.rsplit("/", 1)[1]}').resolve()
|
||||||
|
if not weather_path.exists():
|
||||||
|
with open(weather_path, 'wb') as epw_file:
|
||||||
|
epw_file.write(requests.get(url, allow_redirects=True).content)
|
||||||
return Idf(self._city, self._path, (idf_data_path / 'Minimal.idf'), (idf_data_path / 'Energy+.idd'), weather_path,
|
return Idf(self._city, self._path, (idf_data_path / 'Minimal.idf'), (idf_data_path / 'Energy+.idd'), weather_path,
|
||||||
target_buildings=self._target_buildings)
|
target_buildings=self._target_buildings)
|
||||||
|
|
||||||
|
|
28
hub/helpers/data/montreal_custom_fuel_to_hub_fuel.py
Normal file
28
hub/helpers/data/montreal_custom_fuel_to_hub_fuel.py
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
"""
|
||||||
|
Dictionaries module for montreal custom fuel to hub fuel
|
||||||
|
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||||
|
Copyright © 2022 Concordia CERC group
|
||||||
|
Project Coder Guille Gutierrez Guillermo.GutierrezMorote@concordia.ca
|
||||||
|
"""
|
||||||
|
|
||||||
|
import hub.helpers.constants as cte
|
||||||
|
|
||||||
|
|
||||||
|
class MontrealCustomFuelToHubFuel:
|
||||||
|
"""
|
||||||
|
Montreal custom fuel to hub fuel class
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
self._dictionary = {
|
||||||
|
'gas': cte.GAS,
|
||||||
|
'electricity': cte.ELECTRICITY,
|
||||||
|
'renewable': cte.RENEWABLE
|
||||||
|
}
|
||||||
|
|
||||||
|
@property
|
||||||
|
def dictionary(self) -> dict:
|
||||||
|
"""
|
||||||
|
Get the dictionary
|
||||||
|
:return: {}
|
||||||
|
"""
|
||||||
|
return self._dictionary
|
|
@ -6,6 +6,7 @@ Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from hub.helpers.data.hft_function_to_hub_function import HftFunctionToHubFunction
|
from hub.helpers.data.hft_function_to_hub_function import HftFunctionToHubFunction
|
||||||
|
from hub.helpers.data.montreal_custom_fuel_to_hub_fuel import MontrealCustomFuelToHubFuel
|
||||||
from hub.helpers.data.montreal_function_to_hub_function import MontrealFunctionToHubFunction
|
from hub.helpers.data.montreal_function_to_hub_function import MontrealFunctionToHubFunction
|
||||||
from hub.helpers.data.eilat_function_to_hub_function import EilatFunctionToHubFunction
|
from hub.helpers.data.eilat_function_to_hub_function import EilatFunctionToHubFunction
|
||||||
from hub.helpers.data.alkis_function_to_hub_function import AlkisFunctionToHubFunction
|
from hub.helpers.data.alkis_function_to_hub_function import AlkisFunctionToHubFunction
|
||||||
|
@ -141,3 +142,10 @@ class Dictionaries:
|
||||||
Get Eilat's function to hub function, transformation dictionary
|
Get Eilat's function to hub function, transformation dictionary
|
||||||
"""
|
"""
|
||||||
return EilatFunctionToHubFunction().dictionary
|
return EilatFunctionToHubFunction().dictionary
|
||||||
|
|
||||||
|
@property
|
||||||
|
def montreal_custom_fuel_to_hub_fuel(self) -> dict:
|
||||||
|
"""
|
||||||
|
Get hub fuel from montreal_custom catalog fuel
|
||||||
|
"""
|
||||||
|
return MontrealCustomFuelToHubFuel().dictionary
|
||||||
|
|
|
@ -13,10 +13,7 @@ class ConstructionHelper:
|
||||||
Construction helper
|
Construction helper
|
||||||
"""
|
"""
|
||||||
# NREL
|
# NREL
|
||||||
_nrel_standards = {
|
|
||||||
'ASHRAE Std189': 1,
|
|
||||||
'ASHRAE 90.1_2004': 2
|
|
||||||
}
|
|
||||||
_reference_city_to_nrel_climate_zone = {
|
_reference_city_to_nrel_climate_zone = {
|
||||||
'Miami': 'ASHRAE_2004:1A',
|
'Miami': 'ASHRAE_2004:1A',
|
||||||
'Houston': 'ASHRAE_2004:2A',
|
'Houston': 'ASHRAE_2004:2A',
|
||||||
|
@ -35,17 +32,6 @@ class ConstructionHelper:
|
||||||
'Duluth': 'ASHRAE_2004:7A',
|
'Duluth': 'ASHRAE_2004:7A',
|
||||||
'Fairbanks': 'ASHRAE_2004:8A'
|
'Fairbanks': 'ASHRAE_2004:8A'
|
||||||
}
|
}
|
||||||
nrel_window_types = [cte.WINDOW, cte.DOOR, cte.SKYLIGHT]
|
|
||||||
|
|
||||||
nrel_construction_types = {
|
|
||||||
cte.WALL: 'exterior wall',
|
|
||||||
cte.INTERIOR_WALL: 'interior wall',
|
|
||||||
cte.GROUND_WALL: 'ground wall',
|
|
||||||
cte.GROUND: 'exterior slab',
|
|
||||||
cte.ATTIC_FLOOR: 'attic floor',
|
|
||||||
cte.INTERIOR_SLAB: 'interior slab',
|
|
||||||
cte.ROOF: 'roof'
|
|
||||||
}
|
|
||||||
|
|
||||||
_reference_city_to_nrcan_climate_zone = {
|
_reference_city_to_nrcan_climate_zone = {
|
||||||
'Montreal': '6',
|
'Montreal': '6',
|
||||||
|
|
0
hub/imports/energy_systems/helpers/__init__.py
Normal file
0
hub/imports/energy_systems/helpers/__init__.py
Normal file
29
hub/imports/energy_systems/helpers/energy_systems_helper.py
Normal file
29
hub/imports/energy_systems/helpers/energy_systems_helper.py
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
"""
|
||||||
|
Energy systems helper
|
||||||
|
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||||
|
Copyright © 2022 Concordia CERC group
|
||||||
|
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||||
|
"""
|
||||||
|
|
||||||
|
from hub.helpers import constants as cte
|
||||||
|
|
||||||
|
|
||||||
|
class EnergySystemsHelper:
|
||||||
|
"""
|
||||||
|
EnergySystems helper
|
||||||
|
"""
|
||||||
|
_montreal_custom_fuel_to_hub_fuel = {
|
||||||
|
'gas': cte.GAS,
|
||||||
|
'electricity': cte.ELECTRICITY,
|
||||||
|
'renewable': cte.RENEWABLE
|
||||||
|
}
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def montreal_custom_fuel_to_hub_fuel(fuel):
|
||||||
|
"""
|
||||||
|
Get hub fuel from montreal_custom catalog fuel
|
||||||
|
:param fuel: str
|
||||||
|
:return: str
|
||||||
|
"""
|
||||||
|
return EnergySystemsHelper._montreal_custom_fuel_to_hub_fuel[fuel]
|
||||||
|
|
|
@ -19,6 +19,7 @@ from hub.city_model_structure.energy_systems.generation_system import Generation
|
||||||
from hub.city_model_structure.energy_systems.distribution_system import DistributionSystem
|
from hub.city_model_structure.energy_systems.distribution_system import DistributionSystem
|
||||||
from hub.city_model_structure.energy_systems.emission_system import EmissionSystem
|
from hub.city_model_structure.energy_systems.emission_system import EmissionSystem
|
||||||
from hub.helpers.dictionaries import Dictionaries
|
from hub.helpers.dictionaries import Dictionaries
|
||||||
|
from hub.imports.energy_systems.helpers.energy_systems_helper import EnergySystemsHelper
|
||||||
|
|
||||||
|
|
||||||
class MontrealCustomEnergySystemParameters:
|
class MontrealCustomEnergySystemParameters:
|
||||||
|
@ -45,7 +46,7 @@ class MontrealCustomEnergySystemParameters:
|
||||||
else:
|
else:
|
||||||
_generic_energy_systems = city.generic_energy_systems
|
_generic_energy_systems = city.generic_energy_systems
|
||||||
for building in city.buildings:
|
for building in city.buildings:
|
||||||
archetype_name = f'{building.energy_systems_archetype_name}_lod1.0'
|
archetype_name = building.energy_systems_archetype_name
|
||||||
try:
|
try:
|
||||||
archetype = self._search_archetypes(montreal_custom_catalog, archetype_name)
|
archetype = self._search_archetypes(montreal_custom_catalog, archetype_name)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
|
@ -53,9 +54,12 @@ class MontrealCustomEnergySystemParameters:
|
||||||
archetype_name)
|
archetype_name)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
_energy_systems_connection_table, _generic_energy_systems \
|
_energy_systems_connection_table, _generic_energy_systems = self._create_generic_systems(
|
||||||
= self._create_generic_systems(archetype, building,
|
archetype,
|
||||||
_energy_systems_connection_table, _generic_energy_systems)
|
building,
|
||||||
|
_energy_systems_connection_table,
|
||||||
|
_generic_energy_systems
|
||||||
|
)
|
||||||
city.energy_systems_connection_table = _energy_systems_connection_table
|
city.energy_systems_connection_table = _energy_systems_connection_table
|
||||||
city.generic_energy_systems = _generic_energy_systems
|
city.generic_energy_systems = _generic_energy_systems
|
||||||
|
|
||||||
|
@ -84,10 +88,11 @@ class MontrealCustomEnergySystemParameters:
|
||||||
energy_system.demand_types = _hub_demand_types
|
energy_system.demand_types = _hub_demand_types
|
||||||
_generation_system = GenericGenerationSystem()
|
_generation_system = GenericGenerationSystem()
|
||||||
archetype_generation_equipment = system.generation_system
|
archetype_generation_equipment = system.generation_system
|
||||||
_type = str(system.name).split('_', maxsplit=1)[0]
|
_type = system.name
|
||||||
_generation_system.type = Dictionaries().montreal_system_to_hub_energy_generation_system[
|
_generation_system.type = Dictionaries().montreal_system_to_hub_energy_generation_system[
|
||||||
_type]
|
_type]
|
||||||
_generation_system.fuel_type = archetype_generation_equipment.fuel_type
|
_fuel_type = Dictionaries().montreal_custom_fuel_to_hub_fuel[archetype_generation_equipment.fuel_type]
|
||||||
|
_generation_system.fuel_type = _fuel_type
|
||||||
_generation_system.source_types = archetype_generation_equipment.source_types
|
_generation_system.source_types = archetype_generation_equipment.source_types
|
||||||
_generation_system.heat_efficiency = archetype_generation_equipment.heat_efficiency
|
_generation_system.heat_efficiency = archetype_generation_equipment.heat_efficiency
|
||||||
_generation_system.cooling_efficiency = archetype_generation_equipment.cooling_efficiency
|
_generation_system.cooling_efficiency = archetype_generation_equipment.cooling_efficiency
|
||||||
|
|
|
@ -1,144 +0,0 @@
|
||||||
"""
|
|
||||||
Rhino module parses rhino files and import the geometry into the city model structure
|
|
||||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
|
||||||
Copyright © 2022 Concordia CERC group
|
|
||||||
Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.capip
|
|
||||||
"""
|
|
||||||
import numpy as np
|
|
||||||
from rhino3dm import *
|
|
||||||
from rhino3dm._rhino3dm import Extrusion, MeshType, File3dm
|
|
||||||
|
|
||||||
from hub.city_model_structure.attributes.point import Point
|
|
||||||
from hub.city_model_structure.attributes.polygon import Polygon
|
|
||||||
from hub.city_model_structure.building import Building
|
|
||||||
from hub.city_model_structure.building_demand.surface import Surface as HubSurface
|
|
||||||
from hub.city_model_structure.city import City
|
|
||||||
from hub.helpers.configuration_helper import ConfigurationHelper
|
|
||||||
from hub.imports.geometry.helpers.geometry_helper import GeometryHelper
|
|
||||||
|
|
||||||
|
|
||||||
class Rhino:
|
|
||||||
"""
|
|
||||||
Rhino class
|
|
||||||
"""
|
|
||||||
def __init__(self, path):
|
|
||||||
self._model = File3dm.Read(str(path))
|
|
||||||
max_float = float(ConfigurationHelper().max_coordinate)
|
|
||||||
min_float = float(ConfigurationHelper().min_coordinate)
|
|
||||||
self._min_x = self._min_y = self._min_z = max_float
|
|
||||||
self._max_x = self._max_y = self._max_z = min_float
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _in_perimeter(wall, corner):
|
|
||||||
res = wall.contains_point(Point(corner))
|
|
||||||
return res
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _add_hole(solid_polygon, hole):
|
|
||||||
first = solid_polygon.points[0]
|
|
||||||
points = first + hole.points + solid_polygon.points
|
|
||||||
return Polygon(points)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _solid_points(coordinates) -> np.ndarray:
|
|
||||||
solid_points = np.fromstring(coordinates, dtype=float, sep=' ')
|
|
||||||
solid_points = GeometryHelper.to_points_matrix(solid_points)
|
|
||||||
|
|
||||||
result = []
|
|
||||||
found = False
|
|
||||||
for row in solid_points:
|
|
||||||
for row2 in result:
|
|
||||||
if row[0] == row2[0] and row[1] == row2[1] and row[2] == row2[2]:
|
|
||||||
found = True
|
|
||||||
if not found:
|
|
||||||
result.append(row)
|
|
||||||
return solid_points
|
|
||||||
|
|
||||||
def _corners(self, point):
|
|
||||||
if point.X < self._min_x:
|
|
||||||
self._min_x = point.X
|
|
||||||
if point.Y < self._min_y:
|
|
||||||
self._min_y = point.Y
|
|
||||||
if point.Z < self._min_z:
|
|
||||||
self._min_z = point.Z
|
|
||||||
if point.X > self._max_x:
|
|
||||||
self._max_x = point.X
|
|
||||||
if point.Y > self._max_y:
|
|
||||||
self._max_y = point.Y
|
|
||||||
if point.Z > self._max_z:
|
|
||||||
self._max_z = point.Z
|
|
||||||
|
|
||||||
def _add_face(self, face):
|
|
||||||
hub_surfaces = []
|
|
||||||
_mesh = face.GetMesh(MeshType.Default)
|
|
||||||
for i in range(0, len(_mesh.Faces)):
|
|
||||||
mesh_faces = _mesh.Faces[i]
|
|
||||||
_points = ''
|
|
||||||
faces = []
|
|
||||||
for index in mesh_faces:
|
|
||||||
if index in faces:
|
|
||||||
continue
|
|
||||||
faces.append(index)
|
|
||||||
self._corners(_mesh.Vertices[index])
|
|
||||||
_points = _points + f'{_mesh.Vertices[index].X} {_mesh.Vertices[index].Y} {_mesh.Vertices[index].Z} '
|
|
||||||
polygon_points = Rhino._solid_points(_points.strip())
|
|
||||||
hub_surfaces.append(HubSurface(Polygon(polygon_points), Polygon(polygon_points)))
|
|
||||||
return hub_surfaces
|
|
||||||
|
|
||||||
@property
|
|
||||||
def city(self) -> City:
|
|
||||||
"""
|
|
||||||
Return a city based in the rhino file
|
|
||||||
:return: City
|
|
||||||
"""
|
|
||||||
buildings = []
|
|
||||||
city_objects = [] # building and "windows"
|
|
||||||
windows = []
|
|
||||||
_prev_name = ''
|
|
||||||
|
|
||||||
for obj in self._model.Objects:
|
|
||||||
name = obj.Attributes.Id
|
|
||||||
hub_surfaces = []
|
|
||||||
if isinstance(obj.Geometry, Extrusion):
|
|
||||||
surface = obj.Geometry
|
|
||||||
hub_surfaces = hub_surfaces + self._add_face(surface)
|
|
||||||
else:
|
|
||||||
for face in obj.Geometry.Faces:
|
|
||||||
if face is None:
|
|
||||||
break
|
|
||||||
hub_surfaces = hub_surfaces + self._add_face(face)
|
|
||||||
building = Building(name, hub_surfaces, 'unknown', 'unknown', [])
|
|
||||||
city_objects.append(building)
|
|
||||||
lower_corner = (self._min_x, self._min_y, self._min_z)
|
|
||||||
upper_corner = (self._max_x, self._max_y, self._max_z)
|
|
||||||
city = City(lower_corner, upper_corner, 'EPSG:26918')
|
|
||||||
for building in city_objects:
|
|
||||||
if len(building.surfaces) <= 2:
|
|
||||||
# is not a building but a window!
|
|
||||||
for surface in building.surfaces:
|
|
||||||
# add to windows the "hole" with the normal inverted
|
|
||||||
windows.append(Polygon(surface.perimeter_polygon.inverse))
|
|
||||||
else:
|
|
||||||
buildings.append(building)
|
|
||||||
|
|
||||||
# todo: this method will be pretty inefficient
|
|
||||||
for hole in windows:
|
|
||||||
corner = hole.coordinates[0]
|
|
||||||
for building in buildings:
|
|
||||||
for surface in building.surfaces:
|
|
||||||
plane = surface.perimeter_polygon.plane
|
|
||||||
# todo: this is a hack for dompark project it should not be done this way windows should be correctly modeled
|
|
||||||
# if the distance between the wall plane and the window is less than 2m
|
|
||||||
# and the window Z coordinate it's between the wall Z, it's a window of that wall
|
|
||||||
if plane.distance_to_point(corner) <= 2:
|
|
||||||
# check if the window is in the right high.
|
|
||||||
if surface.upper_corner[2] >= corner[2] >= surface.lower_corner[2]:
|
|
||||||
if surface.holes_polygons is None:
|
|
||||||
surface.holes_polygons = []
|
|
||||||
surface.holes_polygons.append(hole)
|
|
||||||
|
|
||||||
for building in buildings:
|
|
||||||
city.add_city_object(building)
|
|
||||||
building.level_of_detail.geometry = 3
|
|
||||||
city.level_of_detail.geometry = 3
|
|
||||||
return city
|
|
|
@ -12,7 +12,6 @@ from hub.imports.geometry.citygml import CityGml
|
||||||
from hub.imports.geometry.geojson import Geojson
|
from hub.imports.geometry.geojson import Geojson
|
||||||
from hub.imports.geometry.gpandas import GPandas
|
from hub.imports.geometry.gpandas import GPandas
|
||||||
from hub.imports.geometry.obj import Obj
|
from hub.imports.geometry.obj import Obj
|
||||||
from hub.imports.geometry.rhino import Rhino
|
|
||||||
|
|
||||||
|
|
||||||
class GeometryFactory:
|
class GeometryFactory:
|
||||||
|
@ -80,14 +79,6 @@ class GeometryFactory:
|
||||||
self._function_field,
|
self._function_field,
|
||||||
self._function_to_hub).city
|
self._function_to_hub).city
|
||||||
|
|
||||||
@property
|
|
||||||
def _rhino(self) -> City:
|
|
||||||
"""
|
|
||||||
Enrich the city by using Rhino information as data source
|
|
||||||
:return: City
|
|
||||||
"""
|
|
||||||
return Rhino(self._path).city
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def city(self) -> City:
|
def city(self) -> City:
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -7,9 +7,9 @@ Project CoderPeter Yefi peteryefi@gmail.com
|
||||||
import json
|
import json
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
|
||||||
from hub.city_model_structure.city import City
|
|
||||||
from hub.persistence.repositories.application import Application
|
from hub.persistence.repositories.application import Application
|
||||||
from hub.persistence.repositories.city import City as CityRepository
|
from hub.persistence.repositories.city import City
|
||||||
from hub.persistence.repositories.city_object import CityObject
|
from hub.persistence.repositories.city_object import CityObject
|
||||||
from hub.persistence.repositories.simulation_results import SimulationResults
|
from hub.persistence.repositories.simulation_results import SimulationResults
|
||||||
from hub.persistence.repositories.user import User
|
from hub.persistence.repositories.user import User
|
||||||
|
@ -22,7 +22,7 @@ class DBControl:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, db_name, app_env, dotenv_path):
|
def __init__(self, db_name, app_env, dotenv_path):
|
||||||
self._city_repository = CityRepository(db_name=db_name, dotenv_path=dotenv_path, app_env=app_env)
|
self._city = City(db_name=db_name, dotenv_path=dotenv_path, app_env=app_env)
|
||||||
self._application = Application(db_name=db_name, app_env=app_env, dotenv_path=dotenv_path)
|
self._application = Application(db_name=db_name, app_env=app_env, dotenv_path=dotenv_path)
|
||||||
self._user = User(db_name=db_name, app_env=app_env, dotenv_path=dotenv_path)
|
self._user = User(db_name=db_name, app_env=app_env, dotenv_path=dotenv_path)
|
||||||
self._city_object = CityObject(db_name=db_name, app_env=app_env, dotenv_path=dotenv_path)
|
self._city_object = CityObject(db_name=db_name, app_env=app_env, dotenv_path=dotenv_path)
|
||||||
|
@ -63,7 +63,23 @@ class DBControl:
|
||||||
:param application_id: Application id
|
:param application_id: Application id
|
||||||
:return: [City]
|
:return: [City]
|
||||||
"""
|
"""
|
||||||
return self._city_repository.get_by_user_id_and_application_id(user_id, application_id)
|
return self._city.get_by_user_id_and_application_id(user_id, application_id)
|
||||||
|
|
||||||
|
def building(self, name, user_id, application_id, scenario) -> CityObject:
|
||||||
|
"""
|
||||||
|
Retrieve the building from the database
|
||||||
|
:param name: Building name
|
||||||
|
:param user_id: User id
|
||||||
|
:param application_id: Application id
|
||||||
|
:param scenario: Scenario
|
||||||
|
:
|
||||||
|
"""
|
||||||
|
cities = self._city.get_by_user_id_application_id_and_scenario(user_id, application_id, scenario)
|
||||||
|
for city in cities:
|
||||||
|
result = self.building_info(name, city[0].id)
|
||||||
|
if result is not None:
|
||||||
|
return result
|
||||||
|
return None
|
||||||
|
|
||||||
def building_info(self, name, city_id) -> CityObject:
|
def building_info(self, name, city_id) -> CityObject:
|
||||||
"""
|
"""
|
||||||
|
@ -72,51 +88,71 @@ class DBControl:
|
||||||
:param city_id: City ID
|
:param city_id: City ID
|
||||||
:return: CityObject
|
:return: CityObject
|
||||||
"""
|
"""
|
||||||
return self._city_object.get_by_name_and_city(name, city_id)
|
return self._city_object.get_by_name_or_alias_and_city(name, city_id)
|
||||||
|
|
||||||
def results(self, user_id, application_id, cities, result_names=None) -> Dict:
|
def buildings_info(self, request_values, city_id) -> [CityObject]:
|
||||||
|
"""
|
||||||
|
Retrieve the buildings info from the database
|
||||||
|
:param request_values: Building names
|
||||||
|
:param city_id: City ID
|
||||||
|
:return: [CityObject]
|
||||||
|
"""
|
||||||
|
buildings = []
|
||||||
|
for name in request_values['names']:
|
||||||
|
buildings.append(self.building_info(name, city_id))
|
||||||
|
return buildings
|
||||||
|
|
||||||
|
def results(self, user_id, application_id, request_values, result_names=None) -> Dict:
|
||||||
"""
|
"""
|
||||||
Retrieve the simulation results for the given cities from the database
|
Retrieve the simulation results for the given cities from the database
|
||||||
:param user_id: the user id owning the results
|
:param user_id: the user id owning the results
|
||||||
:param application_id: the application id owning the results
|
:param application_id: the application id owning the results
|
||||||
:param cities: dictionary containing the city and building names for the results
|
:param request_values: dictionary containing the scenario and building names to grab the results
|
||||||
:param result_names: if given, filter the results to the selected names
|
:param result_names: if given, filter the results to the selected names
|
||||||
"""
|
"""
|
||||||
if result_names is None:
|
if result_names is None:
|
||||||
result_names = []
|
result_names = []
|
||||||
results = {}
|
results = {}
|
||||||
for city in cities['cities']:
|
for scenario in request_values['scenarios']:
|
||||||
city_name = next(iter(city))
|
scenario_name = next(iter(scenario))
|
||||||
result_set = self._city_repository.get_by_user_id_application_id_and_name(user_id, application_id, city_name)
|
result_sets = self._city.get_by_user_id_application_id_and_scenario(
|
||||||
if result_set is None:
|
user_id,
|
||||||
|
application_id,
|
||||||
|
scenario_name
|
||||||
|
)
|
||||||
|
if result_sets is None:
|
||||||
continue
|
continue
|
||||||
city_id = result_set.id
|
for result_set in result_sets:
|
||||||
results[city_name] = []
|
city_id = result_set[0].id
|
||||||
for building_name in city[city_name]:
|
|
||||||
if self._city_object.get_by_name_and_city(building_name, city_id) is None:
|
|
||||||
continue
|
|
||||||
city_object_id = self._city_object.get_by_name_and_city(building_name, city_id).id
|
|
||||||
_ = self._simulation_results.get_simulation_results_by_city_id_city_object_id_and_names(
|
|
||||||
city_id,
|
|
||||||
city_object_id,
|
|
||||||
result_names)
|
|
||||||
|
|
||||||
for value in _:
|
results[scenario_name] = []
|
||||||
values = json.loads(value.values)
|
for building_name in scenario[scenario_name]:
|
||||||
values["building"] = building_name
|
_building = self._city_object.get_by_name_or_alias_and_city(building_name, city_id)
|
||||||
results[city_name].append(values)
|
if _building is None:
|
||||||
|
continue
|
||||||
|
city_object_id = _building.id
|
||||||
|
_ = self._simulation_results.get_simulation_results_by_city_id_city_object_id_and_names(
|
||||||
|
city_id,
|
||||||
|
city_object_id,
|
||||||
|
result_names)
|
||||||
|
|
||||||
|
for value in _:
|
||||||
|
values = json.loads(value.values)
|
||||||
|
values["building"] = building_name
|
||||||
|
results[scenario_name].append(values)
|
||||||
return results
|
return results
|
||||||
|
|
||||||
def persist_city(self, city: City, pickle_path, application_id: int, user_id: int):
|
def persist_city(self, city: City, pickle_path, scenario, application_id: int, user_id: int):
|
||||||
"""
|
"""
|
||||||
Creates a city into the database
|
Creates a city into the database
|
||||||
:param city: City to be stored
|
:param city: City to be stored
|
||||||
:param pickle_path: Path to save the pickle file
|
:param pickle_path: Path to save the pickle file
|
||||||
|
:param scenario: Simulation scenario name
|
||||||
:param application_id: Application id owning this city
|
:param application_id: Application id owning this city
|
||||||
:param user_id: User who create the city
|
:param user_id: User who create the city
|
||||||
return identity_id
|
return identity_id
|
||||||
"""
|
"""
|
||||||
return self._city_repository.insert(city, pickle_path, application_id, user_id)
|
return self._city.insert(city, pickle_path, scenario, application_id, user_id)
|
||||||
|
|
||||||
def update_city(self, city_id, city):
|
def update_city(self, city_id, city):
|
||||||
"""
|
"""
|
||||||
|
@ -124,7 +160,7 @@ class DBControl:
|
||||||
:param city_id: the id of the city to update
|
:param city_id: the id of the city to update
|
||||||
:param city: the updated city object
|
:param city: the updated city object
|
||||||
"""
|
"""
|
||||||
return self._city_repository.update(city_id, city)
|
return self._city.update(city_id, city)
|
||||||
|
|
||||||
def persist_application(self, name: str, description: str, application_uuid: str):
|
def persist_application(self, name: str, description: str, application_uuid: str):
|
||||||
"""
|
"""
|
||||||
|
@ -194,7 +230,7 @@ class DBControl:
|
||||||
Deletes a single city from the database
|
Deletes a single city from the database
|
||||||
:param city_id: the id of the city to get
|
:param city_id: the id of the city to get
|
||||||
"""
|
"""
|
||||||
self._city_repository.delete(city_id)
|
self._city.delete(city_id)
|
||||||
|
|
||||||
def delete_results_by_name(self, name, city_id=None, city_object_id=None):
|
def delete_results_by_name(self, name, city_id=None, city_object_id=None):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -20,19 +20,17 @@ class City(Models):
|
||||||
id = Column(Integer, Sequence('city_id_seq'), primary_key=True)
|
id = Column(Integer, Sequence('city_id_seq'), primary_key=True)
|
||||||
pickle_path = Column(String, nullable=False)
|
pickle_path = Column(String, nullable=False)
|
||||||
name = Column(String, nullable=False)
|
name = Column(String, nullable=False)
|
||||||
level_of_detail = Column(Integer, nullable=False)
|
scenario = Column(String, nullable=False)
|
||||||
climate_file = Column(String, nullable=False)
|
|
||||||
application_id = Column(Integer, ForeignKey('application.id'), nullable=False)
|
application_id = Column(Integer, ForeignKey('application.id'), nullable=False)
|
||||||
user_id = Column(Integer, ForeignKey('user.id'), nullable=True)
|
user_id = Column(Integer, ForeignKey('user.id'), nullable=True)
|
||||||
hub_release = Column(String, nullable=False)
|
hub_release = Column(String, nullable=False)
|
||||||
created = Column(DateTime, default=datetime.datetime.utcnow)
|
created = Column(DateTime, default=datetime.datetime.utcnow)
|
||||||
updated = Column(DateTime, default=datetime.datetime.utcnow)
|
updated = Column(DateTime, default=datetime.datetime.utcnow)
|
||||||
|
|
||||||
def __init__(self, pickle_path, name, level_of_detail, climate_file, application_id, user_id, hub_release):
|
def __init__(self, pickle_path, name, scenario, application_id, user_id, hub_release):
|
||||||
self.pickle_path = str(pickle_path)
|
self.pickle_path = str(pickle_path)
|
||||||
self.name = name
|
self.name = name
|
||||||
self.level_of_detail = level_of_detail
|
self.scenario = scenario
|
||||||
self.climate_file = climate_file
|
|
||||||
self.application_id = application_id
|
self.application_id = application_id
|
||||||
self.user_id = user_id
|
self.user_id = user_id
|
||||||
self.hub_release = hub_release
|
self.hub_release = hub_release
|
||||||
|
|
|
@ -33,6 +33,7 @@ class CityObject(Models):
|
||||||
wall_area = Column(Float, nullable=False)
|
wall_area = Column(Float, nullable=False)
|
||||||
windows_area = Column(Float, nullable=False)
|
windows_area = Column(Float, nullable=False)
|
||||||
roof_area = Column(Float, nullable=False)
|
roof_area = Column(Float, nullable=False)
|
||||||
|
total_pv_area = Column(Float, nullable=False)
|
||||||
system_name = Column(String, nullable=False)
|
system_name = Column(String, nullable=False)
|
||||||
created = Column(DateTime, default=datetime.datetime.utcnow)
|
created = Column(DateTime, default=datetime.datetime.utcnow)
|
||||||
updated = Column(DateTime, default=datetime.datetime.utcnow)
|
updated = Column(DateTime, default=datetime.datetime.utcnow)
|
||||||
|
@ -48,6 +49,7 @@ class CityObject(Models):
|
||||||
self.volume = building.volume
|
self.volume = building.volume
|
||||||
self.area = building.floor_area
|
self.area = building.floor_area
|
||||||
self.roof_area = sum(roof.solid_polygon.area for roof in building.roofs)
|
self.roof_area = sum(roof.solid_polygon.area for roof in building.roofs)
|
||||||
|
self.total_pv_area = sum(roof.solid_polygon.area * roof.solar_collectors_area_reduction_factor for roof in building.roofs)
|
||||||
storeys = building.storeys_above_ground
|
storeys = building.storeys_above_ground
|
||||||
if storeys is None:
|
if storeys is None:
|
||||||
storeys = building.max_height / building.average_storey_height
|
storeys = building.max_height / building.average_storey_height
|
||||||
|
|
|
@ -34,11 +34,12 @@ class City(Repository):
|
||||||
cls._instance = super(City, cls).__new__(cls)
|
cls._instance = super(City, cls).__new__(cls)
|
||||||
return cls._instance
|
return cls._instance
|
||||||
|
|
||||||
def insert(self, city: CityHub, pickle_path, application_id, user_id: int):
|
def insert(self, city: CityHub, pickle_path, scenario, application_id, user_id: int):
|
||||||
"""
|
"""
|
||||||
Inserts a city
|
Inserts a city
|
||||||
:param city: The complete city instance
|
:param city: The complete city instance
|
||||||
:param pickle_path: Path to the pickle
|
:param pickle_path: Path to the pickle
|
||||||
|
:param scenario: Simulation scenario name
|
||||||
:param application_id: Application id owning the instance
|
:param application_id: Application id owning the instance
|
||||||
:param user_id: User id owning the instance
|
:param user_id: User id owning the instance
|
||||||
:return: Identity id
|
:return: Identity id
|
||||||
|
@ -48,8 +49,7 @@ class City(Repository):
|
||||||
db_city = Model(
|
db_city = Model(
|
||||||
pickle_path,
|
pickle_path,
|
||||||
city.name,
|
city.name,
|
||||||
city.level_of_detail.geometry,
|
scenario,
|
||||||
'None' if city.climate_file is None else str(city.climate_file),
|
|
||||||
application_id,
|
application_id,
|
||||||
user_id,
|
user_id,
|
||||||
__version__)
|
__version__)
|
||||||
|
@ -98,21 +98,19 @@ class City(Repository):
|
||||||
logging.error('Error while fetching city %s', err)
|
logging.error('Error while fetching city %s', err)
|
||||||
raise SQLAlchemyError from err
|
raise SQLAlchemyError from err
|
||||||
|
|
||||||
def get_by_user_id_application_id_and_name(self, user_id, application_id, city_name) -> Model:
|
def get_by_user_id_application_id_and_scenario(self, user_id, application_id, scenario) -> [Model]:
|
||||||
"""
|
"""
|
||||||
Fetch city based on the user who created it
|
Fetch city based on the user who created it
|
||||||
:param user_id: the user id
|
:param user_id: the user id
|
||||||
:param application_id: the application id
|
:param application_id: the application id
|
||||||
:param city_name: the city name
|
:param scenario: simulation scenario name
|
||||||
:return: ModelCity
|
:return: [ModelCity]
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
result_set = self.session.execute(select(Model).where(Model.user_id == user_id,
|
result_set = self.session.execute(select(Model).where(Model.user_id == user_id,
|
||||||
Model.application_id == application_id,
|
Model.application_id == application_id,
|
||||||
Model.name == city_name
|
Model.scenario == scenario
|
||||||
)).first()
|
)).all()
|
||||||
if result_set is not None:
|
|
||||||
result_set = result_set[0]
|
|
||||||
return result_set
|
return result_set
|
||||||
except SQLAlchemyError as err:
|
except SQLAlchemyError as err:
|
||||||
logging.error('Error while fetching city by name %s', err)
|
logging.error('Error while fetching city by name %s', err)
|
||||||
|
@ -133,3 +131,4 @@ class City(Repository):
|
||||||
except SQLAlchemyError as err:
|
except SQLAlchemyError as err:
|
||||||
logging.error('Error while fetching city by name %s', err)
|
logging.error('Error while fetching city by name %s', err)
|
||||||
raise SQLAlchemyError from err
|
raise SQLAlchemyError from err
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ Project Coder Guille Gutierrez Guillermo.GutierrezMorote@concordia.ca
|
||||||
import datetime
|
import datetime
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from sqlalchemy import select
|
from sqlalchemy import select, or_
|
||||||
from sqlalchemy.exc import SQLAlchemyError
|
from sqlalchemy.exc import SQLAlchemyError
|
||||||
|
|
||||||
from hub.city_model_structure.building import Building
|
from hub.city_model_structure.building import Building
|
||||||
|
@ -39,7 +39,7 @@ class CityObject(Repository):
|
||||||
:param building: the city object (only building for now) to be inserted
|
:param building: the city object (only building for now) to be inserted
|
||||||
return Identity id
|
return Identity id
|
||||||
"""
|
"""
|
||||||
city_object = self.get_by_name_and_city(building.name, city_id)
|
city_object = self.get_by_name_or_alias_and_city(building.name, city_id)
|
||||||
if city_object is not None:
|
if city_object is not None:
|
||||||
raise SQLAlchemyError(f'A city_object named {building.name} already exists in that city')
|
raise SQLAlchemyError(f'A city_object named {building.name} already exists in that city')
|
||||||
try:
|
try:
|
||||||
|
@ -96,19 +96,30 @@ class CityObject(Repository):
|
||||||
logging.error('Error while deleting application %s', err)
|
logging.error('Error while deleting application %s', err)
|
||||||
raise SQLAlchemyError from err
|
raise SQLAlchemyError from err
|
||||||
|
|
||||||
def get_by_name_and_city(self, name, city_id) -> Model:
|
def get_by_name_or_alias_and_city(self, name, city_id) -> Model:
|
||||||
"""
|
"""
|
||||||
Fetch a city object based on name and city id
|
Fetch a city object based on name and city id
|
||||||
:param name: city object name
|
:param name: city object name
|
||||||
:param city_id: a city identifier
|
:param city_id: a city identifier
|
||||||
:return: [CityObject] with the provided name belonging to the city with id city_id
|
:return: [CityObject] with the provided name or alias belonging to the city with id city_id
|
||||||
"""
|
"""
|
||||||
_city_object = None
|
|
||||||
try:
|
try:
|
||||||
_city_object = self.session.execute(select(Model).where(
|
# search by name first
|
||||||
Model.name == name, Model.city_id == city_id
|
city_object = self.session.execute(select(Model).where(Model.name == name, Model.city_id == city_id)).first()
|
||||||
)).first()
|
if city_object is not None:
|
||||||
return _city_object[0]
|
return city_object[0]
|
||||||
|
city_objects = self.session.execute(
|
||||||
|
select(Model).where(Model.aliases.contains(name), Model.city_id == city_id)
|
||||||
|
).all()
|
||||||
|
# name not found, so search by alias instead
|
||||||
|
for city_object in city_objects:
|
||||||
|
aliases = city_object[0].aliases.replace('{', '').replace('}', '').split(',')
|
||||||
|
for alias in aliases:
|
||||||
|
if alias == name:
|
||||||
|
# force the name as the alias
|
||||||
|
city_object[0].name = name
|
||||||
|
return city_object[0]
|
||||||
|
return None
|
||||||
except SQLAlchemyError as err:
|
except SQLAlchemyError as err:
|
||||||
logging.error('Error while fetching city object by name and city: %s', err)
|
logging.error('Error while fetching city object by name and city: %s', err)
|
||||||
raise SQLAlchemyError from err
|
raise SQLAlchemyError from err
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
"""
|
"""
|
||||||
Hub version number
|
Hub version number
|
||||||
"""
|
"""
|
||||||
__version__ = '0.1.7.23'
|
__version__ = '0.1.7.29'
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
xmltodict
|
xmltodict
|
||||||
numpy
|
numpy
|
||||||
trimesh[all]==3.12.0
|
trimesh[all]
|
||||||
pyproj
|
pyproj
|
||||||
pandas
|
pandas
|
||||||
requests
|
requests
|
||||||
|
@ -12,7 +12,6 @@ openpyxl
|
||||||
networkx
|
networkx
|
||||||
parseidf==1.0.0
|
parseidf==1.0.0
|
||||||
ply
|
ply
|
||||||
rhino3dm==7.7.0
|
|
||||||
scipy
|
scipy
|
||||||
PyYAML
|
PyYAML
|
||||||
pyecore==0.12.2
|
pyecore==0.12.2
|
||||||
|
|
1
setup.py
1
setup.py
|
@ -72,6 +72,7 @@ setup(
|
||||||
'hub.imports.construction',
|
'hub.imports.construction',
|
||||||
'hub.imports.construction.helpers',
|
'hub.imports.construction.helpers',
|
||||||
'hub.imports.energy_systems',
|
'hub.imports.energy_systems',
|
||||||
|
'hub.imports.energy_systems.helpers',
|
||||||
'hub.imports.geometry',
|
'hub.imports.geometry',
|
||||||
'hub.imports.geometry.citygml_classes',
|
'hub.imports.geometry.citygml_classes',
|
||||||
'hub.imports.geometry.helpers',
|
'hub.imports.geometry.helpers',
|
||||||
|
|
|
@ -33,7 +33,7 @@ class TestCityMerge(TestCase):
|
||||||
self._executable = 'sra'
|
self._executable = 'sra'
|
||||||
|
|
||||||
def test_merge(self):
|
def test_merge(self):
|
||||||
file_path = Path('./tests_data/test.geojson').resolve()
|
file_path = Path(self._example_path / 'test.geojson').resolve()
|
||||||
full_city = GeometryFactory('geojson', file_path, height_field='citygml_me').city
|
full_city = GeometryFactory('geojson', file_path, height_field='citygml_me').city
|
||||||
self.assertEqual(17, len(full_city.buildings), 'Wrong number of buildings')
|
self.assertEqual(17, len(full_city.buildings), 'Wrong number of buildings')
|
||||||
odd_city = City(full_city.lower_corner, full_city.upper_corner, full_city.srs_name)
|
odd_city = City(full_city.lower_corner, full_city.upper_corner, full_city.srs_name)
|
||||||
|
@ -54,17 +54,17 @@ class TestCityMerge(TestCase):
|
||||||
|
|
||||||
def test_merge_with_radiation(self):
|
def test_merge_with_radiation(self):
|
||||||
sra = distutils.spawn.find_executable('sra')
|
sra = distutils.spawn.find_executable('sra')
|
||||||
file_path = Path('./tests_data/test.geojson').resolve()
|
file_path = Path(self._example_path / 'test.geojson').resolve()
|
||||||
output_path = Path('./tests_outputs/')
|
|
||||||
full_city = GeometryFactory('geojson', file_path, height_field='citygml_me').city
|
full_city = GeometryFactory('geojson', file_path, height_field='citygml_me').city
|
||||||
even_city = City(full_city.lower_corner, full_city.upper_corner, full_city.srs_name)
|
even_city = City(full_city.lower_corner, full_city.upper_corner, full_city.srs_name)
|
||||||
for building in full_city.buildings:
|
for building in full_city.buildings:
|
||||||
if int(building.name) % 2 == 0:
|
if int(building.name) % 2 == 0:
|
||||||
even_city.add_city_object(copy.deepcopy(building))
|
even_city.add_city_object(copy.deepcopy(building))
|
||||||
ExportsFactory('sra', full_city, output_path).export()
|
ExportsFactory('sra', full_city, self._output_path).export()
|
||||||
sra_file = str((output_path / f'{full_city.name}_sra.xml').resolve())
|
sra_file = str((self._output_path / f'{full_city.name}_sra.xml').resolve())
|
||||||
subprocess.run([sra, sra_file], stdout=subprocess.DEVNULL)
|
subprocess.run([sra, sra_file], stdout=subprocess.DEVNULL)
|
||||||
ResultFactory('sra', full_city, output_path).enrich()
|
ResultFactory('sra', full_city, self._output_path).enrich()
|
||||||
self.assertEqual(17, len(full_city.buildings), 'Wrong number of buildings')
|
self.assertEqual(17, len(full_city.buildings), 'Wrong number of buildings')
|
||||||
merged_city = full_city.merge(even_city)
|
merged_city = full_city.merge(even_city)
|
||||||
|
|
||||||
|
|
|
@ -4,34 +4,34 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||||
Copyright © 2022 Concordia CERC group
|
Copyright © 2022 Concordia CERC group
|
||||||
Project Coder Peter Yefi peteryefi@gmail.com
|
Project Coder Peter Yefi peteryefi@gmail.com
|
||||||
"""
|
"""
|
||||||
|
import distutils.spawn
|
||||||
import glob
|
import glob
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import unittest
|
import unittest
|
||||||
from unittest import TestCase
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import sqlalchemy.exc
|
from unittest import TestCase
|
||||||
|
|
||||||
from hub.imports.geometry_factory import GeometryFactory
|
import sqlalchemy.exc
|
||||||
from hub.imports.construction_factory import ConstructionFactory
|
from sqlalchemy import create_engine
|
||||||
from hub.imports.usage_factory import UsageFactory
|
from sqlalchemy.exc import ProgrammingError
|
||||||
from hub.imports.results_factory import ResultFactory
|
|
||||||
from hub.imports.weather_factory import WeatherFactory
|
import hub.helpers.constants as cte
|
||||||
from hub.imports.energy_systems_factory import EnergySystemsFactory
|
|
||||||
from hub.exports.energy_building_exports_factory import EnergyBuildingsExportsFactory
|
from hub.exports.energy_building_exports_factory import EnergyBuildingsExportsFactory
|
||||||
from hub.exports.exports_factory import ExportsFactory
|
from hub.exports.exports_factory import ExportsFactory
|
||||||
|
from hub.helpers.data.montreal_function_to_hub_function import MontrealFunctionToHubFunction
|
||||||
|
from hub.imports.construction_factory import ConstructionFactory
|
||||||
|
from hub.imports.energy_systems_factory import EnergySystemsFactory
|
||||||
|
from hub.imports.geometry_factory import GeometryFactory
|
||||||
|
from hub.imports.results_factory import ResultFactory
|
||||||
|
from hub.imports.usage_factory import UsageFactory
|
||||||
|
from hub.imports.weather_factory import WeatherFactory
|
||||||
from hub.persistence.db_control import DBControl
|
from hub.persistence.db_control import DBControl
|
||||||
from hub.persistence.repository import Repository
|
|
||||||
from sqlalchemy import create_engine
|
|
||||||
from hub.persistence.models import City, Application, CityObject, SimulationResults
|
from hub.persistence.models import City, Application, CityObject, SimulationResults
|
||||||
from hub.persistence.models import User, UserRoles
|
from hub.persistence.models import User, UserRoles
|
||||||
from hub.helpers.dictionaries import Dictionaries
|
from hub.persistence.repository import Repository
|
||||||
from sqlalchemy.exc import ProgrammingError
|
|
||||||
import uuid
|
|
||||||
import hub.helpers.constants as cte
|
|
||||||
import distutils.spawn
|
|
||||||
|
|
||||||
|
|
||||||
class Control:
|
class Control:
|
||||||
|
@ -52,7 +52,7 @@ class Control:
|
||||||
self._skip_reason = f'.env file missing at {dotenv_path}'
|
self._skip_reason = f'.env file missing at {dotenv_path}'
|
||||||
return
|
return
|
||||||
dotenv_path = str(dotenv_path)
|
dotenv_path = str(dotenv_path)
|
||||||
repository = Repository(db_name='hub_unittests', app_env='TEST', dotenv_path=dotenv_path)
|
repository = Repository(db_name='montreal_retrofit_test', app_env='TEST', dotenv_path=dotenv_path)
|
||||||
engine = create_engine(repository.configuration.connection_string)
|
engine = create_engine(repository.configuration.connection_string)
|
||||||
try:
|
try:
|
||||||
# delete test database if it exists
|
# delete test database if it exists
|
||||||
|
@ -71,11 +71,16 @@ class Control:
|
||||||
CityObject.__table__.create(bind=repository.engine, checkfirst=True)
|
CityObject.__table__.create(bind=repository.engine, checkfirst=True)
|
||||||
SimulationResults.__table__.create(bind=repository.engine, checkfirst=True)
|
SimulationResults.__table__.create(bind=repository.engine, checkfirst=True)
|
||||||
|
|
||||||
city_file = "tests_data/FZK_Haus_LoD_2.gml"
|
city_file = Path('tests_data/test.geojson').resolve()
|
||||||
output_path = Path('tests_outputs/').resolve()
|
output_path = Path('tests_outputs/').resolve()
|
||||||
self._city = GeometryFactory('citygml',
|
self._city = GeometryFactory('geojson',
|
||||||
city_file,
|
city_file,
|
||||||
function_to_hub=Dictionaries().alkis_function_to_hub_function).city
|
height_field='citygml_me',
|
||||||
|
year_of_construction_field='ANNEE_CONS',
|
||||||
|
aliases_field=['ID_UEV', 'CIVIQUE_DE', 'NOM_RUE'],
|
||||||
|
function_field='CODE_UTILI',
|
||||||
|
function_to_hub=MontrealFunctionToHubFunction().dictionary).city
|
||||||
|
|
||||||
ConstructionFactory('nrcan', self._city).enrich()
|
ConstructionFactory('nrcan', self._city).enrich()
|
||||||
UsageFactory('nrcan', self._city).enrich()
|
UsageFactory('nrcan', self._city).enrich()
|
||||||
WeatherFactory('epw', self._city).enrich()
|
WeatherFactory('epw', self._city).enrich()
|
||||||
|
@ -84,7 +89,6 @@ class Control:
|
||||||
subprocess.run([self.sra, sra_file], stdout=subprocess.DEVNULL)
|
subprocess.run([self.sra, sra_file], stdout=subprocess.DEVNULL)
|
||||||
ResultFactory('sra', self._city, output_path).enrich()
|
ResultFactory('sra', self._city, output_path).enrich()
|
||||||
|
|
||||||
|
|
||||||
for building in self._city.buildings:
|
for building in self._city.buildings:
|
||||||
building.energy_systems_archetype_name = 'system 1 gas pv'
|
building.energy_systems_archetype_name = 'system 1 gas pv'
|
||||||
EnergySystemsFactory('montreal_custom', self._city).enrich()
|
EnergySystemsFactory('montreal_custom', self._city).enrich()
|
||||||
|
@ -99,9 +103,17 @@ class Control:
|
||||||
app_env='TEST',
|
app_env='TEST',
|
||||||
dotenv_path=dotenv_path)
|
dotenv_path=dotenv_path)
|
||||||
|
|
||||||
self._application_uuid = str(uuid.uuid4())
|
self._application_uuid = '60b7fc1b-f389-4254-9ffd-22a4cf32c7a3'
|
||||||
self._application_id = self._database.persist_application('test', 'test application', self.application_uuid)
|
self._application_id = 1
|
||||||
self._user_id = self._database.create_user('Admin', self._application_id, 'Admin@123', UserRoles.Admin)
|
self._user_id = 1
|
||||||
|
|
||||||
|
self._application_id = self._database.persist_application(
|
||||||
|
'City_layers',
|
||||||
|
'City layers test user',
|
||||||
|
self.application_uuid
|
||||||
|
)
|
||||||
|
self._user_id = self._database.create_user('city_layers', self._application_id, 'city_layers', UserRoles.Admin)
|
||||||
|
|
||||||
self._pickle_path = 'tests_data/pickle_path.bz2'
|
self._pickle_path = 'tests_data/pickle_path.bz2'
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -167,6 +179,7 @@ TestDBFactory
|
||||||
city_id = control.database.persist_city(
|
city_id = control.database.persist_city(
|
||||||
control.city,
|
control.city,
|
||||||
control.pickle_path,
|
control.pickle_path,
|
||||||
|
control.city.name,
|
||||||
control.application_id,
|
control.application_id,
|
||||||
control.user_id)
|
control.user_id)
|
||||||
control.database.delete_city(city_id)
|
control.database.delete_city(city_id)
|
||||||
|
@ -176,6 +189,7 @@ TestDBFactory
|
||||||
def test_get_update_city(self):
|
def test_get_update_city(self):
|
||||||
city_id = control.database.persist_city(control.city,
|
city_id = control.database.persist_city(control.city,
|
||||||
control.pickle_path,
|
control.pickle_path,
|
||||||
|
control.city.name,
|
||||||
control.application_id,
|
control.application_id,
|
||||||
control.user_id)
|
control.user_id)
|
||||||
control.city.name = "Ottawa"
|
control.city.name = "Ottawa"
|
||||||
|
@ -194,6 +208,7 @@ TestDBFactory
|
||||||
def test_save_results(self):
|
def test_save_results(self):
|
||||||
city_id = control.database.persist_city(control.city,
|
city_id = control.database.persist_city(control.city,
|
||||||
control.pickle_path,
|
control.pickle_path,
|
||||||
|
'current status',
|
||||||
control.application_id,
|
control.application_id,
|
||||||
control.user_id)
|
control.user_id)
|
||||||
city_objects_id = []
|
city_objects_id = []
|
||||||
|
@ -206,6 +221,10 @@ TestDBFactory
|
||||||
yearly_cooling_peak_load = building.cooling_peak_load[cte.YEAR]
|
yearly_cooling_peak_load = building.cooling_peak_load[cte.YEAR]
|
||||||
monthly_heating_peak_load = building.heating_peak_load[cte.MONTH]
|
monthly_heating_peak_load = building.heating_peak_load[cte.MONTH]
|
||||||
yearly_heating_peak_load = building.heating_peak_load[cte.YEAR]
|
yearly_heating_peak_load = building.heating_peak_load[cte.YEAR]
|
||||||
|
monthly_lighting_peak_load = building.lighting_peak_load[cte.MONTH]
|
||||||
|
yearly_lighting_peak_load = building.lighting_peak_load[cte.YEAR]
|
||||||
|
monthly_appliances_peak_load = building.appliances_peak_load[cte.MONTH]
|
||||||
|
yearly_appliances_peak_load = building.appliances_peak_load[cte.YEAR]
|
||||||
monthly_cooling_demand = building.cooling_demand[cte.MONTH][cte.INSEL_MEB]
|
monthly_cooling_demand = building.cooling_demand[cte.MONTH][cte.INSEL_MEB]
|
||||||
yearly_cooling_demand = building.cooling_demand[cte.YEAR][cte.INSEL_MEB]
|
yearly_cooling_demand = building.cooling_demand[cte.YEAR][cte.INSEL_MEB]
|
||||||
monthly_heating_demand = building.heating_demand[cte.MONTH][cte.INSEL_MEB]
|
monthly_heating_demand = building.heating_demand[cte.MONTH][cte.INSEL_MEB]
|
||||||
|
@ -222,50 +241,59 @@ TestDBFactory
|
||||||
yearly_cooling_consumption = building.cooling_consumption[cte.YEAR]
|
yearly_cooling_consumption = building.cooling_consumption[cte.YEAR]
|
||||||
monthly_domestic_hot_water_consumption = building.domestic_hot_water_consumption[cte.MONTH]
|
monthly_domestic_hot_water_consumption = building.domestic_hot_water_consumption[cte.MONTH]
|
||||||
yearly_domestic_hot_water_consumption = building._domestic_hot_water_consumption[cte.YEAR]
|
yearly_domestic_hot_water_consumption = building._domestic_hot_water_consumption[cte.YEAR]
|
||||||
monthly_distribution_systems_electrical_consumption = building.distribution_systems_electrical_consumption[cte.MONTH]
|
monthly_distribution_systems_electrical_consumption = building.distribution_systems_electrical_consumption[
|
||||||
yearly_distribution_systems_electrical_consumption = building.distribution_systems_electrical_consumption[cte.YEAR]
|
cte.MONTH]
|
||||||
|
yearly_distribution_systems_electrical_consumption = building.distribution_systems_electrical_consumption[
|
||||||
|
cte.YEAR]
|
||||||
monthly_on_site_electrical_production = building.onsite_electrical_production[cte.MONTH]
|
monthly_on_site_electrical_production = building.onsite_electrical_production[cte.MONTH]
|
||||||
yearly_on_site_electrical_production = building.onsite_electrical_production[cte.YEAR]
|
yearly_on_site_electrical_production = building.onsite_electrical_production[cte.YEAR]
|
||||||
results = json.dumps({cte.INSEL_MEB: [
|
results = json.dumps({cte.INSEL_MEB: [
|
||||||
{'monthly_cooling_peak_load': monthly_cooling_peak_load},
|
{'monthly_cooling_peak_load': monthly_cooling_peak_load},
|
||||||
{'yearly_cooling_peak_load': yearly_cooling_peak_load},
|
{'yearly_cooling_peak_load': yearly_cooling_peak_load},
|
||||||
{'monthly_heating_peak_load': monthly_heating_peak_load},
|
{'monthly_heating_peak_load': monthly_heating_peak_load},
|
||||||
{'yearly_heating_peak_load': yearly_heating_peak_load},
|
{'yearly_heating_peak_load': yearly_heating_peak_load},
|
||||||
{'monthly_cooling_demand': monthly_cooling_demand.tolist()},
|
{'monthly_lighting_peak_load': monthly_lighting_peak_load},
|
||||||
{'yearly_cooling_demand': yearly_cooling_demand.tolist()},
|
{'yearly_lighting_peak_load': yearly_lighting_peak_load},
|
||||||
{'monthly_heating_demand': monthly_heating_demand.tolist()},
|
{'monthly_appliances_peak_load': monthly_appliances_peak_load},
|
||||||
{'yearly_heating_demand': yearly_heating_demand.tolist()},
|
{'yearly_appliances_peak_load': yearly_appliances_peak_load},
|
||||||
{'monthly_lighting_electrical_demand': monthly_lighting_electrical_demand.tolist()},
|
{'monthly_cooling_demand': monthly_cooling_demand.tolist()},
|
||||||
{'yearly_lighting_electrical_demand': yearly_lighting_electrical_demand.tolist()},
|
{'yearly_cooling_demand': yearly_cooling_demand.tolist()},
|
||||||
{'monthly_appliances_electrical_demand': monthly_appliances_electrical_demand.tolist()},
|
{'monthly_heating_demand': monthly_heating_demand.tolist()},
|
||||||
{'yearly_appliances_electrical_demand': yearly_appliances_electrical_demand.tolist()},
|
{'yearly_heating_demand': yearly_heating_demand.tolist()},
|
||||||
{'monthly_domestic_hot_water_heat_demand': monthly_domestic_hot_water_heat_demand.tolist()},
|
{'monthly_lighting_electrical_demand': monthly_lighting_electrical_demand.tolist()},
|
||||||
{'yearly_domestic_hot_water_heat_demand': yearly_domestic_hot_water_heat_demand.tolist()},
|
{'yearly_lighting_electrical_demand': yearly_lighting_electrical_demand.tolist()},
|
||||||
{'monthly_heating_consumption': monthly_heating_consumption},
|
{'monthly_appliances_electrical_demand': monthly_appliances_electrical_demand.tolist()},
|
||||||
{'yearly_heating_consumption': yearly_heating_consumption},
|
{'yearly_appliances_electrical_demand': yearly_appliances_electrical_demand.tolist()},
|
||||||
{'monthly_cooling_consumption': monthly_cooling_consumption},
|
{'monthly_domestic_hot_water_heat_demand': monthly_domestic_hot_water_heat_demand.tolist()},
|
||||||
{'yearly_cooling_consumption': yearly_cooling_consumption},
|
{'yearly_domestic_hot_water_heat_demand': yearly_domestic_hot_water_heat_demand.tolist()},
|
||||||
{'monthly_domestic_hot_water_consumption': monthly_domestic_hot_water_consumption},
|
{'monthly_heating_consumption': monthly_heating_consumption},
|
||||||
{'yearly_domestic_hot_water_consumption': yearly_domestic_hot_water_consumption},
|
{'yearly_heating_consumption': yearly_heating_consumption},
|
||||||
{'monthly_distribution_systems_electrical_consumption': monthly_distribution_systems_electrical_consumption},
|
{'monthly_cooling_consumption': monthly_cooling_consumption},
|
||||||
{'yearly_distribution_systems_electrical_consumption': yearly_distribution_systems_electrical_consumption},
|
{'yearly_cooling_consumption': yearly_cooling_consumption},
|
||||||
{'monthly_on_site_electrical_production': monthly_on_site_electrical_production},
|
{'monthly_domestic_hot_water_consumption': monthly_domestic_hot_water_consumption},
|
||||||
{'yearly_on_site_electrical_production': yearly_on_site_electrical_production}
|
{'yearly_domestic_hot_water_consumption': yearly_domestic_hot_water_consumption},
|
||||||
]})
|
{'monthly_distribution_systems_electrical_consumption': monthly_distribution_systems_electrical_consumption},
|
||||||
|
{'yearly_distribution_systems_electrical_consumption': yearly_distribution_systems_electrical_consumption},
|
||||||
|
{'monthly_on_site_electrical_production': monthly_on_site_electrical_production},
|
||||||
|
{'yearly_on_site_electrical_production': yearly_on_site_electrical_production}
|
||||||
|
]})
|
||||||
|
|
||||||
db_building_id = _building.id
|
db_building_id = _building.id
|
||||||
city_objects_id.append(db_building_id)
|
city_objects_id.append(db_building_id)
|
||||||
control.database.add_simulation_results(
|
control.database.add_simulation_results(
|
||||||
cte.INSEL_MEB,
|
cte.INSEL_MEB,
|
||||||
results, city_object_id=db_building_id)
|
results, city_object_id=db_building_id)
|
||||||
self.assertEqual(1, len(city_objects_id), 'wrong number of results')
|
self.assertEqual(17, len(city_objects_id), 'wrong number of results')
|
||||||
self.assertIsNotNone(city_objects_id[0], 'city_object_id is None')
|
self.assertIsNotNone(city_objects_id[0], 'city_object_id is None')
|
||||||
|
"""
|
||||||
for _id in city_objects_id:
|
for _id in city_objects_id:
|
||||||
control.database.delete_results_by_name('insel meb', city_object_id=_id)
|
control.database.delete_results_by_name('insel meb', city_object_id=_id)
|
||||||
control.database.delete_city(city_id)
|
control.database.delete_city(city_id)
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@unittest.skipIf(control.skip_test, control.skip_reason)
|
@unittest.skipIf(control.skip_test, control.skip_reason)
|
||||||
def tearDownClass(cls):
|
def tearDownClass(cls):
|
||||||
control.database.delete_application(control.application_uuid)
|
control.database.delete_application(control.application_uuid)
|
||||||
control.database.delete_user(control.user_id)
|
control.database.delete_user(control.user_id)
|
||||||
|
"""
|
|
@ -4,6 +4,8 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||||
Copyright © 2022 Concordia CERC group
|
Copyright © 2022 Concordia CERC group
|
||||||
Project Coder Peter Yefi peteryefi@gmail.com
|
Project Coder Peter Yefi peteryefi@gmail.com
|
||||||
"""
|
"""
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
from unittest import TestCase
|
from unittest import TestCase
|
||||||
from hub.imports.geometry_factory import GeometryFactory
|
from hub.imports.geometry_factory import GeometryFactory
|
||||||
|
@ -38,8 +40,10 @@ class TestEnergySystemsFactory(TestCase):
|
||||||
Test setup
|
Test setup
|
||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
city_file = "tests_data/C40_Final.gml"
|
self._example_path = (Path(__file__).parent / 'tests_data').resolve()
|
||||||
self._output_path = "tests_data/as_user_output.csv"
|
self._output_path = (Path(__file__).parent / 'tests_outputs').resolve()
|
||||||
|
city_file = (self._example_path/"C40_Final.gml").resolve()
|
||||||
|
self._output_path = (self._output_path/"as_user_output.csv").resolve()
|
||||||
self._city = GeometryFactory('citygml', path=city_file).city
|
self._city = GeometryFactory('citygml', path=city_file).city
|
||||||
EnergySystemsFactory('air_source_hp', self._city).enrich()
|
EnergySystemsFactory('air_source_hp', self._city).enrich()
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||||
Copyright © 2022 Concordia CERC group
|
Copyright © 2022 Concordia CERC group
|
||||||
Project Coder Peter Yefi peteryefi@gmail.com
|
Project Coder Peter Yefi peteryefi@gmail.com
|
||||||
"""
|
"""
|
||||||
|
from pathlib import Path
|
||||||
from unittest import TestCase
|
from unittest import TestCase
|
||||||
|
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
@ -24,8 +25,10 @@ class TestEnergySystemsFactory(TestCase):
|
||||||
Test setup
|
Test setup
|
||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
city_file = "tests_data/C40_Final.gml"
|
self._example_path = (Path(__file__).parent / 'tests_data').resolve()
|
||||||
self._output_path = "tests_data/w2w_user_output.csv"
|
self._output_path = (Path(__file__).parent / 'tests_outputs').resolve()
|
||||||
|
city_file = (self._example_path / "C40_Final.gml").resolve()
|
||||||
|
self._output_path = (self._example_path / "w2w_user_output.csv").resolve()
|
||||||
self._city = GeometryFactory('citygml', path=city_file).city
|
self._city = GeometryFactory('citygml', path=city_file).city
|
||||||
EnergySystemsFactory('water_to_water_hp', self._city).enrich()
|
EnergySystemsFactory('water_to_water_hp', self._city).enrich()
|
||||||
|
|
||||||
|
|
|
@ -110,15 +110,6 @@ class TestGeometryFactory(TestCase):
|
||||||
self._check_surfaces(building)
|
self._check_surfaces(building)
|
||||||
city = ConstructionFactory('nrel', city).enrich()
|
city = ConstructionFactory('nrel', city).enrich()
|
||||||
|
|
||||||
def test_import_rhino(self):
|
|
||||||
"""
|
|
||||||
Test rhino import
|
|
||||||
"""
|
|
||||||
file = 'dompark.3dm'
|
|
||||||
city = self._get_city(file, 'rhino')
|
|
||||||
self.assertIsNotNone(city, 'city is none')
|
|
||||||
self.assertTrue(len(city.buildings) == 36)
|
|
||||||
|
|
||||||
def test_import_obj(self):
|
def test_import_obj(self):
|
||||||
"""
|
"""
|
||||||
Test obj import
|
Test obj import
|
||||||
|
|
|
@ -23,9 +23,10 @@ class GreeneryInIdf(TestCase):
|
||||||
GreeneryInIdf TestCase 1
|
GreeneryInIdf TestCase 1
|
||||||
"""
|
"""
|
||||||
def test_greenery_in_idf(self):
|
def test_greenery_in_idf(self):
|
||||||
city_file = "tests_data/one_building_in_kelowna.gml"
|
|
||||||
output_path = Path('tests_outputs/').resolve()
|
|
||||||
|
|
||||||
|
self._example_path = (Path(__file__).parent / 'tests_data').resolve()
|
||||||
|
output_path = (Path(__file__).parent / 'tests_outputs').resolve()
|
||||||
|
city_file = (self._example_path / "one_building_in_kelowna.gml").resolve()
|
||||||
city = GeometryFactory('citygml', path=city_file).city
|
city = GeometryFactory('citygml', path=city_file).city
|
||||||
for building in city.buildings:
|
for building in city.buildings:
|
||||||
building.year_of_construction = 2006
|
building.year_of_construction = 2006
|
||||||
|
|
|
@ -4,6 +4,7 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||||
Copyright © 2023 Concordia CERC group
|
Copyright © 2023 Concordia CERC group
|
||||||
Project Coder Peter Yefi peteryefi@gmail.com
|
Project Coder Peter Yefi peteryefi@gmail.com
|
||||||
"""
|
"""
|
||||||
|
from pathlib import Path
|
||||||
from unittest import TestCase
|
from unittest import TestCase
|
||||||
from hub.imports.geometry_factory import GeometryFactory
|
from hub.imports.geometry_factory import GeometryFactory
|
||||||
from hub.imports.energy_systems_factory import EnergySystemsFactory
|
from hub.imports.energy_systems_factory import EnergySystemsFactory
|
||||||
|
@ -38,8 +39,9 @@ class TestHeatPumpResults(TestCase):
|
||||||
Test setup
|
Test setup
|
||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
city_file = "tests_data/C40_Final.gml"
|
self._example_path = (Path(__file__).parent / 'tests_data').resolve()
|
||||||
self._output_path = "tests_data/as_user_output.csv"
|
self._output_path = (Path(__file__).parent / 'tests_outputs/as_user_output.csv').resolve()
|
||||||
|
city_file = (self._example_path / "C40_Final.gml").resolve()
|
||||||
self._city = GeometryFactory('citygml', path=city_file).city
|
self._city = GeometryFactory('citygml', path=city_file).city
|
||||||
EnergySystemsFactory('air_source_hp', self._city).enrich()
|
EnergySystemsFactory('air_source_hp', self._city).enrich()
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,10 @@ class TestResultsImport(TestCase):
|
||||||
self.assertIsNotNone(building.cooling_demand[cte.MONTH][cte.INSEL_MEB])
|
self.assertIsNotNone(building.cooling_demand[cte.MONTH][cte.INSEL_MEB])
|
||||||
self.assertIsNotNone(building.heating_demand[cte.YEAR][cte.INSEL_MEB])
|
self.assertIsNotNone(building.heating_demand[cte.YEAR][cte.INSEL_MEB])
|
||||||
self.assertIsNotNone(building.cooling_demand[cte.YEAR][cte.INSEL_MEB])
|
self.assertIsNotNone(building.cooling_demand[cte.YEAR][cte.INSEL_MEB])
|
||||||
|
self.assertIsNotNone(building.lighting_peak_load[cte.MONTH])
|
||||||
|
self.assertIsNotNone(building.lighting_peak_load[cte.YEAR])
|
||||||
|
self.assertIsNotNone(building.appliances_peak_load[cte.MONTH])
|
||||||
|
self.assertIsNotNone(building.appliances_peak_load[cte.YEAR])
|
||||||
|
|
||||||
def test_peak_loads(self):
|
def test_peak_loads(self):
|
||||||
# todo: this is not technically a import
|
# todo: this is not technically a import
|
||||||
|
|
Binary file not shown.
BIN
tests/tests_data/pickle_path.bz2
Normal file
BIN
tests/tests_data/pickle_path.bz2
Normal file
Binary file not shown.
1
tests/tests_outputs/.gitignore
vendored
1
tests/tests_outputs/.gitignore
vendored
|
@ -1,2 +1,3 @@
|
||||||
# Except this file
|
# Except this file
|
||||||
|
*
|
||||||
!.gitignore
|
!.gitignore
|
Loading…
Reference in New Issue
Block a user