Refactor and code quality improvements

This commit is contained in:
Guille Gutierrez 2023-05-30 17:13:49 -04:00
parent 82b72e78c7
commit 891b660824
123 changed files with 826 additions and 766 deletions

View File

View File

View File

@ -15,304 +15,304 @@ getEClassifier = partial(Ecore.getEClassifier, searchspace=eClassifiers)
Management = EEnum('Management', literals=['Intensive', 'Extensive', 'SemiIntensive', 'NA'])
Roughness = EEnum('Roughness', literals=['VeryRough', 'Rough',
'MediumRough', 'MediumSmooth', 'Smooth', 'VerySmooth'])
'MediumRough', 'MediumSmooth', 'Smooth', 'VerySmooth'])
class Soil(EObject, metaclass=MetaEClass):
name = EAttribute(eType=EString, unique=True, derived=False, changeable=True)
roughness = EAttribute(eType=Roughness, unique=True, derived=False,
changeable=True, default_value=Roughness.MediumRough)
conductivityOfDrySoil = EAttribute(
eType=EString, unique=True, derived=False, changeable=True, default_value='1.0 W/(m*K)')
densityOfDrySoil = EAttribute(eType=EString, unique=True, derived=False,
changeable=True, default_value='1100 kg/m³')
specificHeatOfDrySoil = EAttribute(
eType=EString, unique=True, derived=False, changeable=True, default_value='1200 J/(kg*K)')
thermalAbsorptance = EAttribute(eType=EString, unique=True,
derived=False, changeable=True, default_value='0.9')
solarAbsorptance = EAttribute(eType=EString, unique=True,
derived=False, changeable=True, default_value='0.7')
visibleAbsorptance = EAttribute(eType=EString, unique=True,
derived=False, changeable=True, default_value='0.75')
saturationVolumetricMoistureContent = EAttribute(
eType=EString, unique=True, derived=False, changeable=True, default_value='0.0')
residualVolumetricMoistureContent = EAttribute(
eType=EString, unique=True, derived=False, changeable=True, default_value='0.05')
initialVolumetricMoistureContent = EAttribute(
eType=EString, unique=True, derived=False, changeable=True, default_value='0.1')
name = EAttribute(eType=EString, unique=True, derived=False, changeable=True)
roughness = EAttribute(eType=Roughness, unique=True, derived=False,
changeable=True, default_value=Roughness.MediumRough)
conductivityOfDrySoil = EAttribute(
eType=EString, unique=True, derived=False, changeable=True, default_value='1.0 W/(m*K)')
densityOfDrySoil = EAttribute(eType=EString, unique=True, derived=False,
changeable=True, default_value='1100 kg/m³')
specificHeatOfDrySoil = EAttribute(
eType=EString, unique=True, derived=False, changeable=True, default_value='1200 J/(kg*K)')
thermalAbsorptance = EAttribute(eType=EString, unique=True,
derived=False, changeable=True, default_value='0.9')
solarAbsorptance = EAttribute(eType=EString, unique=True,
derived=False, changeable=True, default_value='0.7')
visibleAbsorptance = EAttribute(eType=EString, unique=True,
derived=False, changeable=True, default_value='0.75')
saturationVolumetricMoistureContent = EAttribute(
eType=EString, unique=True, derived=False, changeable=True, default_value='0.0')
residualVolumetricMoistureContent = EAttribute(
eType=EString, unique=True, derived=False, changeable=True, default_value='0.05')
initialVolumetricMoistureContent = EAttribute(
eType=EString, unique=True, derived=False, changeable=True, default_value='0.1')
def __init__(self, *, name=None, roughness=None, conductivityOfDrySoil=None, densityOfDrySoil=None, specificHeatOfDrySoil=None, thermalAbsorptance=None, solarAbsorptance=None, visibleAbsorptance=None, saturationVolumetricMoistureContent=None, residualVolumetricMoistureContent=None, initialVolumetricMoistureContent=None):
# if kwargs:
# raise AttributeError('unexpected arguments: {}'.format(kwargs))
def __init__(self, *, name=None, roughness=None, conductivityOfDrySoil=None, densityOfDrySoil=None, specificHeatOfDrySoil=None, thermalAbsorptance=None, solarAbsorptance=None, visibleAbsorptance=None, saturationVolumetricMoistureContent=None, residualVolumetricMoistureContent=None, initialVolumetricMoistureContent=None):
# if kwargs:
# raise AttributeError('unexpected arguments: {}'.format(kwargs))
super().__init__()
super().__init__()
if name is not None:
self.name = name
if name is not None:
self.name = name
if roughness is not None:
self.roughness = roughness
if roughness is not None:
self.roughness = roughness
if conductivityOfDrySoil is not None:
self.conductivityOfDrySoil = conductivityOfDrySoil
if conductivityOfDrySoil is not None:
self.conductivityOfDrySoil = conductivityOfDrySoil
if densityOfDrySoil is not None:
self.densityOfDrySoil = densityOfDrySoil
if densityOfDrySoil is not None:
self.densityOfDrySoil = densityOfDrySoil
if specificHeatOfDrySoil is not None:
self.specificHeatOfDrySoil = specificHeatOfDrySoil
if specificHeatOfDrySoil is not None:
self.specificHeatOfDrySoil = specificHeatOfDrySoil
if thermalAbsorptance is not None:
self.thermalAbsorptance = thermalAbsorptance
if thermalAbsorptance is not None:
self.thermalAbsorptance = thermalAbsorptance
if solarAbsorptance is not None:
self.solarAbsorptance = solarAbsorptance
if solarAbsorptance is not None:
self.solarAbsorptance = solarAbsorptance
if visibleAbsorptance is not None:
self.visibleAbsorptance = visibleAbsorptance
if visibleAbsorptance is not None:
self.visibleAbsorptance = visibleAbsorptance
if saturationVolumetricMoistureContent is not None:
self.saturationVolumetricMoistureContent = saturationVolumetricMoistureContent
if saturationVolumetricMoistureContent is not None:
self.saturationVolumetricMoistureContent = saturationVolumetricMoistureContent
if residualVolumetricMoistureContent is not None:
self.residualVolumetricMoistureContent = residualVolumetricMoistureContent
if residualVolumetricMoistureContent is not None:
self.residualVolumetricMoistureContent = residualVolumetricMoistureContent
if initialVolumetricMoistureContent is not None:
self.initialVolumetricMoistureContent = initialVolumetricMoistureContent
if initialVolumetricMoistureContent is not None:
self.initialVolumetricMoistureContent = initialVolumetricMoistureContent
class Plant(EObject, metaclass=MetaEClass):
name = EAttribute(eType=EString, unique=True, derived=False, changeable=True)
height = EAttribute(eType=EString, unique=True, derived=False,
changeable=True, default_value='0.1 m')
leafAreaIndex = EAttribute(eType=EString, unique=True, derived=False,
changeable=True, default_value='2.5')
leafReflectivity = EAttribute(eType=EString, unique=True,
derived=False, changeable=True, default_value='0.1')
leafEmissivity = EAttribute(eType=EString, unique=True, derived=False,
changeable=True, default_value='0.9')
minimalStomatalResistance = EAttribute(
eType=EString, unique=True, derived=False, changeable=True, default_value='100.0 s/m')
co2Sequestration = EAttribute(eType=EString, unique=True, derived=False,
changeable=True, default_value='kgCO₂eq')
growsOn = EReference(ordered=True, unique=True, containment=False, derived=False, upper=-1)
name = EAttribute(eType=EString, unique=True, derived=False, changeable=True)
height = EAttribute(eType=EString, unique=True, derived=False,
changeable=True, default_value='0.1 m')
leafAreaIndex = EAttribute(eType=EString, unique=True, derived=False,
changeable=True, default_value='2.5')
leafReflectivity = EAttribute(eType=EString, unique=True,
derived=False, changeable=True, default_value='0.1')
leafEmissivity = EAttribute(eType=EString, unique=True, derived=False,
changeable=True, default_value='0.9')
minimalStomatalResistance = EAttribute(
eType=EString, unique=True, derived=False, changeable=True, default_value='100.0 s/m')
co2Sequestration = EAttribute(eType=EString, unique=True, derived=False,
changeable=True, default_value='kgCO₂eq')
growsOn = EReference(ordered=True, unique=True, containment=False, derived=False, upper=-1)
def __init__(self, *, name=None, height=None, leafAreaIndex=None, leafReflectivity=None, leafEmissivity=None, minimalStomatalResistance=None, growsOn=None, co2Sequestration=None):
# if kwargs:
# raise AttributeError('unexpected arguments: {}'.format(kwargs))
def __init__(self, *, name=None, height=None, leafAreaIndex=None, leafReflectivity=None, leafEmissivity=None, minimalStomatalResistance=None, growsOn=None, co2Sequestration=None):
# if kwargs:
# raise AttributeError('unexpected arguments: {}'.format(kwargs))
super().__init__()
super().__init__()
if name is not None:
self.name = name
if name is not None:
self.name = name
if height is not None:
self.height = height
if height is not None:
self.height = height
if leafAreaIndex is not None:
self.leafAreaIndex = leafAreaIndex
if leafAreaIndex is not None:
self.leafAreaIndex = leafAreaIndex
if leafReflectivity is not None:
self.leafReflectivity = leafReflectivity
if leafReflectivity is not None:
self.leafReflectivity = leafReflectivity
if leafEmissivity is not None:
self.leafEmissivity = leafEmissivity
if leafEmissivity is not None:
self.leafEmissivity = leafEmissivity
if minimalStomatalResistance is not None:
self.minimalStomatalResistance = minimalStomatalResistance
if minimalStomatalResistance is not None:
self.minimalStomatalResistance = minimalStomatalResistance
if co2Sequestration is not None:
self.co2Sequestration = co2Sequestration
if co2Sequestration is not None:
self.co2Sequestration = co2Sequestration
if growsOn:
self.growsOn.extend(growsOn)
if growsOn:
self.growsOn.extend(growsOn)
class SupportEnvelope(EObject, metaclass=MetaEClass):
roughness = EAttribute(eType=Roughness, unique=True, derived=False,
changeable=True, default_value=Roughness.MediumRough)
solarAbsorptance = EAttribute(eType=EDouble, unique=True,
roughness = EAttribute(eType=Roughness, unique=True, derived=False,
changeable=True, default_value=Roughness.MediumRough)
solarAbsorptance = EAttribute(eType=EDouble, unique=True,
derived=False, changeable=True, default_value=0.0)
conductivity = EAttribute(eType=EDouble, unique=True, derived=False,
changeable=True, default_value=0.0)
visibleAbsorptance = EAttribute(eType=EDouble, unique=True,
derived=False, changeable=True, default_value=0.0)
specificHeat = EAttribute(eType=EDouble, unique=True, derived=False,
changeable=True, default_value=0.0)
density = EAttribute(eType=EDouble, unique=True, derived=False,
changeable=True, default_value=0.0)
thermalAbsorptance = EAttribute(eType=EDouble, unique=True,
derived=False, changeable=True, default_value=0.0)
conductivity = EAttribute(eType=EDouble, unique=True, derived=False,
changeable=True, default_value=0.0)
visibleAbsorptance = EAttribute(eType=EDouble, unique=True,
derived=False, changeable=True, default_value=0.0)
specificHeat = EAttribute(eType=EDouble, unique=True, derived=False,
changeable=True, default_value=0.0)
density = EAttribute(eType=EDouble, unique=True, derived=False,
changeable=True, default_value=0.0)
thermalAbsorptance = EAttribute(eType=EDouble, unique=True,
derived=False, changeable=True, default_value=0.0)
def __init__(self, *, roughness=None, solarAbsorptance=None, conductivity=None, visibleAbsorptance=None, specificHeat=None, density=None, thermalAbsorptance=None):
# if kwargs:
# raise AttributeError('unexpected arguments: {}'.format(kwargs))
def __init__(self, *, roughness=None, solarAbsorptance=None, conductivity=None, visibleAbsorptance=None, specificHeat=None, density=None, thermalAbsorptance=None):
# if kwargs:
# raise AttributeError('unexpected arguments: {}'.format(kwargs))
super().__init__()
super().__init__()
if roughness is not None:
self.roughness = roughness
if roughness is not None:
self.roughness = roughness
if solarAbsorptance is not None:
self.solarAbsorptance = solarAbsorptance
if solarAbsorptance is not None:
self.solarAbsorptance = solarAbsorptance
if conductivity is not None:
self.conductivity = conductivity
if conductivity is not None:
self.conductivity = conductivity
if visibleAbsorptance is not None:
self.visibleAbsorptance = visibleAbsorptance
if visibleAbsorptance is not None:
self.visibleAbsorptance = visibleAbsorptance
if specificHeat is not None:
self.specificHeat = specificHeat
if specificHeat is not None:
self.specificHeat = specificHeat
if density is not None:
self.density = density
if density is not None:
self.density = density
if thermalAbsorptance is not None:
self.thermalAbsorptance = thermalAbsorptance
if thermalAbsorptance is not None:
self.thermalAbsorptance = thermalAbsorptance
class GreeneryCatalog(EObject, metaclass=MetaEClass):
name = EAttribute(eType=EString, unique=True, derived=False, changeable=True)
description = EAttribute(eType=EString, unique=True, derived=False, changeable=True)
source = EAttribute(eType=EString, unique=True, derived=False, changeable=True)
plantCategories = EReference(ordered=True, unique=True,
containment=True, derived=False, upper=-1)
vegetationCategories = EReference(ordered=True, unique=True,
containment=True, derived=False, upper=-1)
soils = EReference(ordered=True, unique=True, containment=True, derived=False, upper=-1)
name = EAttribute(eType=EString, unique=True, derived=False, changeable=True)
description = EAttribute(eType=EString, unique=True, derived=False, changeable=True)
source = EAttribute(eType=EString, unique=True, derived=False, changeable=True)
plantCategories = EReference(ordered=True, unique=True,
containment=True, derived=False, upper=-1)
vegetationCategories = EReference(ordered=True, unique=True,
containment=True, derived=False, upper=-1)
soils = EReference(ordered=True, unique=True, containment=True, derived=False, upper=-1)
def __init__(self, *, name=None, description=None, source=None, plantCategories=None, vegetationCategories=None, soils=None):
# if kwargs:
# raise AttributeError('unexpected arguments: {}'.format(kwargs))
def __init__(self, *, name=None, description=None, source=None, plantCategories=None, vegetationCategories=None, soils=None):
# if kwargs:
# raise AttributeError('unexpected arguments: {}'.format(kwargs))
super().__init__()
super().__init__()
if name is not None:
self.name = name
if name is not None:
self.name = name
if description is not None:
self.description = description
if description is not None:
self.description = description
if source is not None:
self.source = source
if source is not None:
self.source = source
if plantCategories:
self.plantCategories.extend(plantCategories)
if plantCategories:
self.plantCategories.extend(plantCategories)
if vegetationCategories:
self.vegetationCategories.extend(vegetationCategories)
if vegetationCategories:
self.vegetationCategories.extend(vegetationCategories)
if soils:
self.soils.extend(soils)
if soils:
self.soils.extend(soils)
class PlantCategory(EObject, metaclass=MetaEClass):
"""Excluding (that is non-overlapping) categories like Trees, Hedeges, Grasses that help users finding a specific biol. plant species."""
name = EAttribute(eType=EString, unique=True, derived=False, changeable=True)
plants = EReference(ordered=True, unique=True, containment=True, derived=False, upper=-1)
"""Excluding (that is non-overlapping) categories like Trees, Hedeges, Grasses that help users finding a specific biol. plant species."""
name = EAttribute(eType=EString, unique=True, derived=False, changeable=True)
plants = EReference(ordered=True, unique=True, containment=True, derived=False, upper=-1)
def __init__(self, *, name=None, plants=None):
# if kwargs:
# raise AttributeError('unexpected arguments: {}'.format(kwargs))
def __init__(self, *, name=None, plants=None):
# if kwargs:
# raise AttributeError('unexpected arguments: {}'.format(kwargs))
super().__init__()
super().__init__()
if name is not None:
self.name = name
if name is not None:
self.name = name
if plants:
self.plants.extend(plants)
if plants:
self.plants.extend(plants)
class IrrigationSchedule(EObject, metaclass=MetaEClass):
name = EAttribute(eType=EString, unique=True, derived=False, changeable=True)
name = EAttribute(eType=EString, unique=True, derived=False, changeable=True)
def __init__(self, *, name=None):
# if kwargs:
# raise AttributeError('unexpected arguments: {}'.format(kwargs))
def __init__(self, *, name=None):
# if kwargs:
# raise AttributeError('unexpected arguments: {}'.format(kwargs))
super().__init__()
super().__init__()
if name is not None:
self.name = name
if name is not None:
self.name = name
class Vegetation(EObject, metaclass=MetaEClass):
"""Plant life or total plant cover (as of an area)"""
name = EAttribute(eType=EString, unique=True, derived=False, changeable=True)
thicknessOfSoil = EAttribute(eType=EString, unique=True, derived=False,
changeable=True, default_value='20 cm')
management = EAttribute(eType=Management, unique=True, derived=False,
changeable=True, default_value=Management.NA)
airGap = EAttribute(eType=EString, unique=True, derived=False,
changeable=True, default_value='0.0 cm')
soil = EReference(ordered=True, unique=True, containment=False, derived=False)
plants = EReference(ordered=True, unique=True, containment=True, derived=False, upper=-1)
"""Plant life or total plant cover (as of an area)"""
name = EAttribute(eType=EString, unique=True, derived=False, changeable=True)
thicknessOfSoil = EAttribute(eType=EString, unique=True, derived=False,
changeable=True, default_value='20 cm')
management = EAttribute(eType=Management, unique=True, derived=False,
changeable=True, default_value=Management.NA)
airGap = EAttribute(eType=EString, unique=True, derived=False,
changeable=True, default_value='0.0 cm')
soil = EReference(ordered=True, unique=True, containment=False, derived=False)
plants = EReference(ordered=True, unique=True, containment=True, derived=False, upper=-1)
def __init__(self, *, name=None, thicknessOfSoil=None, soil=None, plants=None, management=None, airGap=None):
# if kwargs:
# raise AttributeError('unexpected arguments: {}'.format(kwargs))
def __init__(self, *, name=None, thicknessOfSoil=None, soil=None, plants=None, management=None, airGap=None):
# if kwargs:
# raise AttributeError('unexpected arguments: {}'.format(kwargs))
super().__init__()
super().__init__()
if name is not None:
self.name = name
if name is not None:
self.name = name
if thicknessOfSoil is not None:
self.thicknessOfSoil = thicknessOfSoil
if thicknessOfSoil is not None:
self.thicknessOfSoil = thicknessOfSoil
if management is not None:
self.management = management
if management is not None:
self.management = management
if airGap is not None:
self.airGap = airGap
if airGap is not None:
self.airGap = airGap
if soil is not None:
self.soil = soil
if soil is not None:
self.soil = soil
if plants:
self.plants.extend(plants)
if plants:
self.plants.extend(plants)
class VegetationCategory(EObject, metaclass=MetaEClass):
"""Excluding (that is non-overlapping) categories to help users finding a specific vegetation template."""
name = EAttribute(eType=EString, unique=True, derived=False, changeable=True)
vegetationTemplates = EReference(ordered=True, unique=True,
containment=True, derived=False, upper=-1)
"""Excluding (that is non-overlapping) categories to help users finding a specific vegetation template."""
name = EAttribute(eType=EString, unique=True, derived=False, changeable=True)
vegetationTemplates = EReference(ordered=True, unique=True,
containment=True, derived=False, upper=-1)
def __init__(self, *, vegetationTemplates=None, name=None):
# if kwargs:
# raise AttributeError('unexpected arguments: {}'.format(kwargs))
def __init__(self, *, vegetationTemplates=None, name=None):
# if kwargs:
# raise AttributeError('unexpected arguments: {}'.format(kwargs))
super().__init__()
super().__init__()
if name is not None:
self.name = name
if name is not None:
self.name = name
if vegetationTemplates:
self.vegetationTemplates.extend(vegetationTemplates)
if vegetationTemplates:
self.vegetationTemplates.extend(vegetationTemplates)
class PlantPercentage(EObject, metaclass=MetaEClass):
percentage = EAttribute(eType=EString, unique=True, derived=False,
changeable=True, default_value='100')
plant = EReference(ordered=True, unique=True, containment=False, derived=False)
percentage = EAttribute(eType=EString, unique=True, derived=False,
changeable=True, default_value='100')
plant = EReference(ordered=True, unique=True, containment=False, derived=False)
def __init__(self, *, percentage=None, plant=None):
# if kwargs:
# raise AttributeError('unexpected arguments: {}'.format(kwargs))
def __init__(self, *, percentage=None, plant=None):
# if kwargs:
# raise AttributeError('unexpected arguments: {}'.format(kwargs))
super().__init__()
super().__init__()
if percentage is not None:
self.percentage = percentage
if percentage is not None:
self.percentage = percentage
if plant is not None:
self.plant = plant
if plant is not None:
self.plant = plant

View File

@ -4,12 +4,12 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group
Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
"""
import logging
from pathlib import Path
from typing import TypeVar
from hub.catalog_factories.greenery.greenery_catalog import GreeneryCatalog
from hub.helpers.utils import validate_import_export_type
Catalog = TypeVar('Catalog')
@ -19,9 +19,8 @@ class GreeneryCatalogFactory:
"""
def __init__(self, handler, base_path=None):
if base_path is None:
base_path = Path(Path(__file__).parent.parent / 'data/greenery')
base_path = (Path(__file__).parent.parent / 'data/greenery').resolve()
self._handler = '_' + handler.lower()
class_funcs = validate_import_export_type(GreeneryCatalogFactory, handler)
self._path = base_path
@property

View File

View File

@ -148,13 +148,13 @@ class ComnetCatalog(Catalog):
if day == cte.SATURDAY:
start = start + 1
end = end + 1
elif day == cte.SUNDAY or day == cte.HOLIDAY:
elif day in (cte.SUNDAY, cte.HOLIDAY):
start = start + 2
end = end + 2
_schedule_values[day] = _extracted_data.iloc[start:end, 3:27].to_numpy().tolist()[0]
_schedule = []
for day in _schedule_values:
if schedule_name == 'ClgSetPt' or schedule_name == 'HtgSetPt' or schedule_name == 'WtrHtrSetPt':
if schedule_name in ('ClgSetPt', 'HtgSetPt', 'WtrHtrSetPt'):
# to celsius
if 'n.a.' in _schedule_values[day]:
_schedule_values[day] = None

View File

@ -4,10 +4,10 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
import sys
import hub.helpers.constants as cte
from typing import Dict
import hub.helpers.constants as cte
class UsageHelper:
"""
@ -92,41 +92,49 @@ class UsageHelper:
@property
def nrcan_day_type_to_hub_days(self):
"""
Get a dictionary to convert nrcan day types to hub day types
"""
return self._nrcan_day_type_to_hub_days
@property
def nrcan_schedule_type_to_hub_schedule_type(self):
"""
Get a dictionary to convert nrcan schedule types to hub schedule types
"""
return self._nrcan_schedule_type_to_hub_schedule_type
@property
def nrcan_data_type_to_hub_data_type(self):
"""
Get a dictionary to convert nrcan data types to hub data types
"""
return self._nrcan_data_type_to_hub_data_type
@property
def nrcan_time_to_hub_time(self):
"""
Get a dictionary to convert nrcan time to hub time
"""
return self._nrcan_time_to_hub_time
@property
def comnet_data_type_to_hub_data_type(self):
def comnet_data_type_to_hub_data_type(self) -> Dict:
"""
Get a dictionary to convert comnet data types to hub data types
"""
return self._comnet_data_type_to_hub_data_type
@property
def comnet_schedules_key_to_comnet_schedules(self) -> Dict:
"""
Get a dictionary to convert hub schedules to comnet schedules
"""
return self._comnet_schedules_key_to_comnet_schedules
@property
def comnet_days(self):
def comnet_days(self) -> [str]:
"""
Get the list of days used in comnet
"""
return self._comnet_days
@staticmethod
def schedules_key(usage):
"""
Get Comnet schedules key from the list found in the Comnet usage file
:param usage: str
:return: str
"""
try:
return UsageHelper._comnet_schedules_key_to_comnet_schedules[usage]
except KeyError:
sys.stderr.write('Error: Comnet keyword not found. An update of the Comnet files might have been '
'done changing the keywords.\n')

View File

View File

@ -45,14 +45,13 @@ class Plane:
:return: (A, B, C, D)
"""
if self._equation is None:
a = self.normal[0]
b = self.normal[1]
c = self.normal[2]
d = ((-1 * self.origin.coordinates[0]) * self.normal[0])
d += ((-1 * self.origin.coordinates[1]) * self.normal[1])
d += ((-1 * self.origin.coordinates[2]) * self.normal[2])
self._equation = (a, b, c, d)
d = -1 * self.origin.coordinates[0] * self.normal[0]
d += -1 * self.origin.coordinates[1] * self.normal[1]
d += -1 * self.origin.coordinates[2] * self.normal[2]
self._equation = a, b, c, d
return self._equation
def distance_to_point(self, point):

View File

@ -31,7 +31,7 @@ class Point:
:return: float
"""
power = 0
for dimension in range(0, len(self.coordinates)):
for dimension in enumerate(self.coordinates):
power += math.pow(other_point.coordinates[dimension]-self.coordinates[dimension], 2)
distance = math.sqrt(power)
return distance

View File

@ -6,20 +6,21 @@ Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
from __future__ import annotations
import logging
import math
import sys
from typing import List
import numpy as np
from trimesh import Trimesh
import trimesh.intersections
import trimesh.creation
import trimesh.geometry
import trimesh.intersections
from shapely.geometry.polygon import Polygon as shapley_polygon
from trimesh import Trimesh
from hub.city_model_structure.attributes.plane import Plane
from hub.city_model_structure.attributes.point import Point
import hub.helpers.constants as cte
class Polygon:
@ -69,44 +70,6 @@ class Polygon:
"""
return self._coordinates
def contains_point(self, point):
"""
Determines if the given point is contained by the current polygon
:return: boolean
"""
# fixme: This method doesn't seems to work.
n = len(self.vertices)
angle_sum = 0
for i in range(0, n):
vector_0 = self.vertices[i]
vector_1 = self.vertices[(i+1) % n]
# set to origin
vector_0[0] = vector_0[0] - point.coordinates[0]
vector_0[1] = vector_0[1] - point.coordinates[1]
vector_0[2] = vector_0[2] - point.coordinates[2]
vector_1[0] = vector_1[0] - point.coordinates[0]
vector_1[1] = vector_1[1] - point.coordinates[1]
vector_1[2] = vector_1[2] - point.coordinates[2]
module = np.linalg.norm(vector_0) * np.linalg.norm(vector_1)
scalar_product = np.dot(vector_0, vector_1)
angle = np.pi/2
if module != 0:
angle = abs(np.arcsin(scalar_product / module))
angle_sum += angle
return abs(angle_sum - math.pi*2) < cte.EPSILON
def contains_polygon(self, polygon):
"""
Determines if the given polygon is contained by the current polygon
:return: boolean
"""
for point in polygon.points:
if not self.contains_point(point):
return False
return True
@property
def points_list(self) -> np.ndarray:
"""
@ -142,12 +105,12 @@ class Polygon:
if self._area is None:
self._area = 0
for triangle in self.triangles:
ab = np.zeros(3)
ac = np.zeros(3)
a_b = np.zeros(3)
a_c = np.zeros(3)
for i in range(0, 3):
ab[i] = triangle.coordinates[1][i] - triangle.coordinates[0][i]
ac[i] = triangle.coordinates[2][i] - triangle.coordinates[0][i]
self._area += np.linalg.norm(np.cross(ab, ac)) / 2
a_b[i] = triangle.coordinates[1][i] - triangle.coordinates[0][i]
a_c[i] = triangle.coordinates[2][i] - triangle.coordinates[0][i]
self._area += np.linalg.norm(np.cross(a_b, a_c)) / 2
return self._area
@area.setter
@ -217,7 +180,11 @@ class Polygon:
return -alpha
@staticmethod
def triangle_mesh(vertices, normal):
def triangle_mesh(vertices, normal) -> Trimesh:
"""
Get the triangulated mesh for the polygon
:return: Trimesh
"""
min_x = 1e16
min_y = 1e16
min_z = 1e16
@ -246,8 +213,7 @@ class Polygon:
polygon = shapley_polygon(coordinates)
try:
vertices_2d, faces = trimesh.creation.triangulate_polygon(polygon, engine='triangle')
_, faces = trimesh.creation.triangulate_polygon(polygon, engine='triangle')
mesh = Trimesh(vertices=vertices, faces=faces)
@ -267,13 +233,17 @@ class Polygon:
return mesh
except ValueError:
logging.error(f'Not able to triangulate polygon\n')
logging.error('Not able to triangulate polygon\n')
_vertices = [[0, 0, 0], [0, 0, 1], [0, 1, 0]]
_faces = [[0, 1, 2]]
return Trimesh(vertices=_vertices, faces=_faces)
@property
def triangles(self) -> List[Polygon]:
"""
Triangulate the polygon and return a list of triangular polygons
:return: [Polygon]
"""
if self._triangles is None:
self._triangles = []
_mesh = self.triangle_mesh(self.coordinates, self.normal)
@ -336,7 +306,7 @@ class Polygon:
def _reshape(self, triangles) -> Polygon:
edges_list = []
for i in range(0, len(triangles)):
for i in enumerate(triangles):
for edge in triangles[i].edges:
if not self._edge_in_edges_list(edge, edges_list):
edges_list.append(edge)
@ -421,13 +391,14 @@ class Polygon:
if len(points) != 3:
sub_polygons = polygon.triangles
# todo: I modified this! To be checked @Guille
if len(sub_polygons) >= 1:
for sub_polygon in sub_polygons:
face = []
points = sub_polygon.coordinates
for point in points:
face.append(self._position_of(point, face))
self._faces.append(face)
if len(sub_polygons) < 1:
continue
for sub_polygon in sub_polygons:
face = []
points = sub_polygon.coordinates
for point in points:
face.append(self._position_of(point, face))
self._faces.append(face)
else:
for point in points:
face.append(self._position_of(point, face))
@ -440,7 +411,7 @@ class Polygon:
:return: int
"""
vertices = self.vertices
for i in range(len(vertices)):
for i in enumerate(vertices):
# ensure not duplicated vertex
power = 0
vertex2 = vertices[i]

View File

@ -41,10 +41,10 @@ class Polyhedron:
:return: int
"""
vertices = self.vertices
for i in range(len(vertices)):
for i, vertex in enumerate(vertices):
# ensure not duplicated vertex
power = 0
vertex2 = vertices[i]
vertex2 = vertex
for dimension in range(0, 3):
power += math.pow(vertex2[dimension] - point[dimension], 2)
distance = math.sqrt(power)
@ -92,13 +92,14 @@ class Polyhedron:
points = polygon.coordinates
if len(points) != 3:
sub_polygons = polygon.triangles
if len(sub_polygons) >= 1:
for sub_polygon in sub_polygons:
face = []
points = sub_polygon.coordinates
for point in points:
face.append(self._position_of(point, face))
self._faces.append(face)
if len(sub_polygons) < 1:
continue
for sub_polygon in sub_polygons:
face = []
points = sub_polygon.coordinates
for point in points:
face.append(self._position_of(point, face))
self._faces.append(face)
else:
for point in points:
face.append(self._position_of(point, face))

View File

@ -45,17 +45,17 @@ class Building(CityObject):
self._shell = None
self._aliases = None
self._type = 'building'
self._cold_water_temperature = dict()
self._heating = dict()
self._cooling = dict()
self._lighting_electrical_demand = dict()
self._appliances_electrical_demand = dict()
self._domestic_hot_water_heat_demand = dict()
self._heating_consumption = dict()
self._cooling_consumption = dict()
self._domestic_hot_water_consumption = dict()
self._distribution_systems_electrical_consumption = dict()
self._onsite_electrical_production = dict()
self._cold_water_temperature = {}
self._heating = {}
self._cooling = {}
self._lighting_electrical_demand = {}
self._appliances_electrical_demand = {}
self._domestic_hot_water_heat_demand = {}
self._heating_consumption = {}
self._cooling_consumption = {}
self._domestic_hot_water_consumption = {}
self._distribution_systems_electrical_consumption = {}
self._onsite_electrical_production = {}
self._eave_height = None
self._energy_systems = None
self._systems_archetype_name = None
@ -86,7 +86,8 @@ class Building(CityObject):
elif surface.type == cte.INTERIOR_SLAB:
self._interior_slabs.append(surface)
else:
logging.error(f'Building {self.name} [{self.aliases}] has an unexpected surface type {surface.type}.\n')
error = f'Building {self.name} [{self.aliases}] has an unexpected surface type {surface.type}.\n'
logging.error(error)
@property
def shell(self) -> Polyhedron:
@ -612,11 +613,11 @@ class Building(CityObject):
if len(_working_hours) == 0:
_working_hours = _working_hours_per_thermal_zone
else:
for key in _working_hours.keys():
for key, item in _working_hours.items():
saved_values = _working_hours_per_thermal_zone[key]
for i, value in enumerate(_working_hours[key]):
for i, value in enumerate(item):
if saved_values[i] == 1:
_working_hours[key][i] = 1
value = 1
_total_hours = 0
for key in _working_hours:
_total_hours += _working_hours[key] * cte.DAYS_A_YEAR[key]
@ -628,43 +629,44 @@ class Building(CityObject):
Get total electricity consumption for distribution and emission systems in Wh
return: dict
"""
if len(self._distribution_systems_electrical_consumption) == 0:
_peak_load = self.heating_peak_load[cte.YEAR]['heating peak loads'][0]
_peak_load_type = cte.HEATING
if _peak_load < self.cooling_peak_load[cte.YEAR]['cooling peak loads'][0]:
_peak_load = self.cooling_peak_load[cte.YEAR]['cooling peak loads'][0]
_peak_load_type = cte.COOLING
if len(self._distribution_systems_electrical_consumption) != 0:
return self._distribution_systems_electrical_consumption
_peak_load = self.heating_peak_load[cte.YEAR]['heating peak loads'][0]
_peak_load_type = cte.HEATING
if _peak_load < self.cooling_peak_load[cte.YEAR]['cooling peak loads'][0]:
_peak_load = self.cooling_peak_load[cte.YEAR]['cooling peak loads'][0]
_peak_load_type = cte.COOLING
_consumption_fix_flow = 0
for energy_system in self.energy_systems:
emission_system = energy_system.emission_system.generic_emission_system
parasitic_energy_consumption = emission_system.parasitic_energy_consumption
distribution_system = energy_system.distribution_system.generic_distribution_system
consumption_variable_flow = distribution_system.distribution_consumption_variable_flow
for demand_type in energy_system.demand_types:
if demand_type.lower() == cte.HEATING:
if _peak_load_type == cte.HEATING:
_consumption_fix_flow = distribution_system.distribution_consumption_fix_flow
for heating_demand_key in self.heating:
_consumption = [0]*len(self.heating)
_demand = self.heating[heating_demand_key][cte.INSEL_MEB]
for i in range(0, len(_consumption)):
_consumption[i] += (parasitic_energy_consumption + consumption_variable_flow) * _demand[i]
self._distribution_systems_electrical_consumption[heating_demand_key] = _consumption
if demand_type.lower() == cte.COOLING:
if _peak_load_type == cte.COOLING:
_consumption_fix_flow = distribution_system.distribution_consumption_fix_flow
for demand_key in self.cooling:
_consumption = self._distribution_systems_electrical_consumption[demand_key]
_demand = self.cooling[demand_key][cte.INSEL_MEB]
for i in range(0, len(_consumption)):
_consumption[i] += (parasitic_energy_consumption + consumption_variable_flow) * _demand[i]
self._distribution_systems_electrical_consumption[demand_key] = _consumption
_consumption_fix_flow = 0
for energy_system in self.energy_systems:
emission_system = energy_system.emission_system.generic_emission_system
parasitic_energy_consumption = emission_system.parasitic_energy_consumption
distribution_system = energy_system.distribution_system.generic_distribution_system
consumption_variable_flow = distribution_system.distribution_consumption_variable_flow
for demand_type in energy_system.demand_types:
if demand_type.lower() == cte.HEATING:
if _peak_load_type == cte.HEATING:
_consumption_fix_flow = distribution_system.distribution_consumption_fix_flow
for heating_demand_key in self.heating:
_consumption = [0]*len(self.heating)
_demand = self.heating[heating_demand_key][cte.INSEL_MEB]
for i in enumerate(_consumption):
_consumption[i] += (parasitic_energy_consumption + consumption_variable_flow) * _demand[i]
self._distribution_systems_electrical_consumption[heating_demand_key] = _consumption
if demand_type.lower() == cte.COOLING:
if _peak_load_type == cte.COOLING:
_consumption_fix_flow = distribution_system.distribution_consumption_fix_flow
for demand_key in self.cooling:
_consumption = self._distribution_systems_electrical_consumption[demand_key]
_demand = self.cooling[demand_key][cte.INSEL_MEB]
for i in enumerate(_consumption):
_consumption[i] += (parasitic_energy_consumption + consumption_variable_flow) * _demand[i]
self._distribution_systems_electrical_consumption[demand_key] = _consumption
for key in self._distribution_systems_electrical_consumption:
for i in range(0, len(self._distribution_systems_electrical_consumption[key])):
self._distribution_systems_electrical_consumption[key][i] += _peak_load * _consumption_fix_flow \
* self._calculate_working_hours()
for key, item in self._distribution_systems_electrical_consumption.items():
for i in range(0, len(item)):
self._distribution_systems_electrical_consumption[key][i] += _peak_load * _consumption_fix_flow \
* self._calculate_working_hours()
return self._distribution_systems_electrical_consumption
def _calculate_consumption(self, consumption_type, demand):
@ -673,7 +675,7 @@ class Building(CityObject):
for energy_system in self.energy_systems:
for demand_type in energy_system.demand_types:
if demand_type.lower() == consumption_type.lower():
if consumption_type == cte.HEATING or consumption_type == cte.DOMESTIC_HOT_WATER:
if consumption_type in (cte.HEATING, cte.DOMESTIC_HOT_WATER):
coefficient_of_performance = energy_system.generation_system.generic_generation_system.heat_efficiency
elif consumption_type == cte.COOLING:
coefficient_of_performance = energy_system.generation_system.generic_generation_system.cooling_efficiency

View File

@ -10,8 +10,8 @@ from __future__ import annotations
import math
import uuid
import numpy as np
from typing import List, Union
import numpy as np
from hub.city_model_structure.attributes.polygon import Polygon
from hub.city_model_structure.attributes.plane import Plane
from hub.city_model_structure.attributes.point import Point
@ -34,7 +34,7 @@ class Surface:
self._area = None
self._lower_corner = None
self._upper_corner = None
self._global_irradiance = dict()
self._global_irradiance = {}
self._perimeter_polygon = perimeter_polygon
self._holes_polygons = holes_polygons
self._solid_polygon = solid_polygon

View File

@ -226,7 +226,7 @@ class ThermalBoundary:
r_value += float(layer.thickness) / float(layer.material.conductivity)
self._u_value = 1.0/r_value
except TypeError:
raise Exception('Constructions layers are not initialized') from TypeError
raise TypeError('Constructions layers are not initialized') from TypeError
return self._u_value
@u_value.setter

View File

@ -8,8 +8,9 @@ Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concord
import uuid
import copy
import numpy
from typing import List, Union, TypeVar
import numpy
from hub.city_model_structure.building_demand.occupancy import Occupancy
from hub.city_model_structure.building_demand.appliances import Appliances
from hub.city_model_structure.building_demand.lighting import Lighting
@ -59,7 +60,11 @@ class ThermalZone:
@property
def usages(self):
# example 70-office_30-residential
"""
Get the thermal zone usages including percentage with the format [percentage]-usage_[percentage]-usage...
Eg: 70-office_30-residential
:return: str
"""
if self._usage_from_parent:
self._usages = copy.deepcopy(self._parent_internal_zone.usages)
else:
@ -324,19 +329,19 @@ class ThermalZone:
_occupancy_reference = self.usages[0].occupancy
if _occupancy_reference.occupancy_schedules is not None:
_schedules = []
for i_schedule in range(0, len(_occupancy_reference.occupancy_schedules)):
for schedule_index, schedule_value in enumerate(_occupancy_reference.occupancy_schedules):
schedule = Schedule()
schedule.type = _occupancy_reference.occupancy_schedules[i_schedule].type
schedule.day_types = _occupancy_reference.occupancy_schedules[i_schedule].day_types
schedule.data_type = _occupancy_reference.occupancy_schedules[i_schedule].data_type
schedule.time_step = _occupancy_reference.occupancy_schedules[i_schedule].time_step
schedule.time_range = _occupancy_reference.occupancy_schedules[i_schedule].time_range
schedule.type = schedule_value.type
schedule.day_types = schedule_value.day_types
schedule.data_type = schedule_value.data_type
schedule.time_step = schedule_value.time_step
schedule.time_range = schedule_value.time_range
new_values = []
for i_value in range(0, len(_occupancy_reference.occupancy_schedules[i_schedule].values)):
for i_value, _ in enumerate(schedule_value.values):
_new_value = 0
for usage in self.usages:
_new_value += usage.percentage * usage.occupancy.occupancy_schedules[i_schedule].values[i_value]
_new_value += usage.percentage * usage.occupancy.occupancy_schedules[schedule_index].values[i_value]
new_values.append(_new_value)
schedule.values = new_values
_schedules.append(schedule)
@ -385,19 +390,19 @@ class ThermalZone:
_lighting_reference = self.usages[0].lighting
if _lighting_reference.schedules is not None:
_schedules = []
for i_schedule in range(0, len(_lighting_reference.schedules)):
for schedule_index, schedule_value in enumerate(_lighting_reference.schedules):
schedule = Schedule()
schedule.type = _lighting_reference.schedules[i_schedule].type
schedule.day_types = _lighting_reference.schedules[i_schedule].day_types
schedule.data_type = _lighting_reference.schedules[i_schedule].data_type
schedule.time_step = _lighting_reference.schedules[i_schedule].time_step
schedule.time_range = _lighting_reference.schedules[i_schedule].time_range
schedule.type = schedule_value.type
schedule.day_types = schedule_value.day_types
schedule.data_type = schedule_value.data_type
schedule.time_step = schedule_value.time_step
schedule.time_range = schedule_value.time_range
new_values = []
for i_value in range(0, len(_lighting_reference.schedules[i_schedule].values)):
for i_value, _ in enumerate(schedule_value.values):
_new_value = 0
for usage in self.usages:
_new_value += usage.percentage * usage.lighting.schedules[i_schedule].values[i_value]
_new_value += usage.percentage * usage.lighting.schedules[schedule_index].values[i_value]
new_values.append(_new_value)
schedule.values = new_values
_schedules.append(schedule)
@ -446,19 +451,19 @@ class ThermalZone:
_appliances_reference = self.usages[0].appliances
if _appliances_reference.schedules is not None:
_schedules = []
for i_schedule in range(0, len(_appliances_reference.schedules)):
for schedule_index, schedule_value in enumerate(_appliances_reference.schedules):
schedule = Schedule()
schedule.type = _appliances_reference.schedules[i_schedule].type
schedule.day_types = _appliances_reference.schedules[i_schedule].day_types
schedule.data_type = _appliances_reference.schedules[i_schedule].data_type
schedule.time_step = _appliances_reference.schedules[i_schedule].time_step
schedule.time_range = _appliances_reference.schedules[i_schedule].time_range
schedule.type = schedule_value.type
schedule.day_types = schedule_value.day_types
schedule.data_type = schedule_value.data_type
schedule.time_step = schedule_value.time_step
schedule.time_range = schedule_value.time_range
new_values = []
for i_value in range(0, len(_appliances_reference.schedules[i_schedule].values)):
for i_value, _ in enumerate(schedule_value.values):
_new_value = 0
for usage in self.usages:
_new_value += usage.percentage * usage.appliances.schedules[i_schedule].values[i_value]
_new_value += usage.percentage * usage.appliances.schedules[schedule_index].values[i_value]
new_values.append(_new_value)
schedule.values = new_values
_schedules.append(schedule)
@ -510,12 +515,12 @@ class ThermalZone:
_schedules_defined = False
break
for day, _schedule in enumerate(internal_gain.schedules):
for v, value in enumerate(_schedule.values):
values[v, day] += value * usage.percentage
for v_index, value in enumerate(_schedule.values):
values[v_index, day] += value * usage.percentage
if _schedules_defined:
_schedules = []
for day in range(0, len(_days)):
for day, _ in enumerate(_days):
_schedule = copy.deepcopy(_base_schedule)
_schedule.day_types = [_days[day]]
_schedule.values = values[:day]
@ -543,62 +548,62 @@ class ThermalZone:
if self.usages is None:
return None
if self._thermal_control is None:
self._thermal_control = ThermalControl()
_mean_heating_set_point = 0
_heating_set_back = 0
_mean_cooling_set_point = 0
for usage in self.usages:
_mean_heating_set_point += usage.percentage * usage.thermal_control.mean_heating_set_point
_heating_set_back += usage.percentage * usage.thermal_control.heating_set_back
_mean_cooling_set_point += usage.percentage * usage.thermal_control.mean_cooling_set_point
self._thermal_control.mean_heating_set_point = _mean_heating_set_point
self._thermal_control.heating_set_back = _heating_set_back
self._thermal_control.mean_cooling_set_point = _mean_cooling_set_point
if self._thermal_control is not None:
return self._thermal_control
self._thermal_control = ThermalControl()
_mean_heating_set_point = 0
_heating_set_back = 0
_mean_cooling_set_point = 0
for usage in self.usages:
_mean_heating_set_point += usage.percentage * usage.thermal_control.mean_heating_set_point
_heating_set_back += usage.percentage * usage.thermal_control.heating_set_back
_mean_cooling_set_point += usage.percentage * usage.thermal_control.mean_cooling_set_point
self._thermal_control.mean_heating_set_point = _mean_heating_set_point
self._thermal_control.heating_set_back = _heating_set_back
self._thermal_control.mean_cooling_set_point = _mean_cooling_set_point
_thermal_control_reference = self.usages[0].thermal_control
_types_reference = []
if _thermal_control_reference.hvac_availability_schedules is not None:
_types_reference.append([cte.HVAC_AVAILABILITY, _thermal_control_reference.hvac_availability_schedules])
if _thermal_control_reference.heating_set_point_schedules is not None:
_types_reference.append([cte.HEATING_SET_POINT, _thermal_control_reference.heating_set_point_schedules])
if _thermal_control_reference.cooling_set_point_schedules is not None:
_types_reference.append([cte.COOLING_SET_POINT, _thermal_control_reference.cooling_set_point_schedules])
_thermal_control_reference = self.usages[0].thermal_control
_types_reference = []
if _thermal_control_reference.hvac_availability_schedules is not None:
_types_reference.append([cte.HVAC_AVAILABILITY, _thermal_control_reference.hvac_availability_schedules])
if _thermal_control_reference.heating_set_point_schedules is not None:
_types_reference.append([cte.HEATING_SET_POINT, _thermal_control_reference.heating_set_point_schedules])
if _thermal_control_reference.cooling_set_point_schedules is not None:
_types_reference.append([cte.COOLING_SET_POINT, _thermal_control_reference.cooling_set_point_schedules])
for i_type in range(0, len(_types_reference)):
_schedules = []
_schedule_type = _types_reference[i_type][1]
for i_schedule in range(0, len(_schedule_type)):
schedule = Schedule()
schedule.type = _schedule_type[i_schedule].type
schedule.day_types = _schedule_type[i_schedule].day_types
schedule.data_type = _schedule_type[i_schedule].data_type
schedule.time_step = _schedule_type[i_schedule].time_step
schedule.time_range = _schedule_type[i_schedule].time_range
new_values = []
for i_value in range(0, len(_schedule_type[i_schedule].values)):
_new_value = 0
for usage in self.usages:
if _types_reference[i_type][0] == cte.HVAC_AVAILABILITY:
_new_value += usage.percentage * \
usage.thermal_control.hvac_availability_schedules[i_schedule].values[i_value]
elif _types_reference[i_type][0] == cte.HEATING_SET_POINT:
_new_value += usage.percentage * \
usage.thermal_control.heating_set_point_schedules[i_schedule].values[i_value]
elif _types_reference[i_type][0] == cte.COOLING_SET_POINT:
_new_value += usage.percentage * \
usage.thermal_control.cooling_set_point_schedules[i_schedule].values[i_value]
new_values.append(_new_value)
schedule.values = new_values
_schedules.append(schedule)
if i_type == 0:
self._thermal_control.hvac_availability_schedules = _schedules
elif i_type == 1:
self._thermal_control.heating_set_point_schedules = _schedules
elif i_type == 2:
self._thermal_control.cooling_set_point_schedules = _schedules
for i_type, _ in enumerate(_types_reference):
_schedules = []
_schedule_type = _types_reference[i_type][1]
for i_schedule, schedule_value in enumerate(_schedule_type):
schedule = Schedule()
schedule.type = schedule_value.type
schedule.day_types = schedule_value.day_types
schedule.data_type = schedule_value.data_type
schedule.time_step = schedule_value.time_step
schedule.time_range = schedule_value.time_range
new_values = []
for i_value, _ in enumerate(schedule_value.values):
_new_value = 0
for usage in self.usages:
if _types_reference[i_type][0] == cte.HVAC_AVAILABILITY:
_new_value += usage.percentage * \
usage.thermal_control.hvac_availability_schedules[i_schedule].values[i_value]
elif _types_reference[i_type][0] == cte.HEATING_SET_POINT:
_new_value += usage.percentage * \
usage.thermal_control.heating_set_point_schedules[i_schedule].values[i_value]
elif _types_reference[i_type][0] == cte.COOLING_SET_POINT:
_new_value += usage.percentage * \
usage.thermal_control.cooling_set_point_schedules[i_schedule].values[i_value]
new_values.append(_new_value)
schedule.values = new_values
_schedules.append(schedule)
if i_type == 0:
self._thermal_control.hvac_availability_schedules = _schedules
elif i_type == 1:
self._thermal_control.heating_set_point_schedules = _schedules
elif i_type == 2:
self._thermal_control.cooling_set_point_schedules = _schedules
return self._thermal_control
@property
@ -622,19 +627,19 @@ class ThermalZone:
_domestic_hot_water_reference = self.usages[0].domestic_hot_water
if _domestic_hot_water_reference.schedules is not None:
_schedules = []
for i_schedule in range(0, len(_domestic_hot_water_reference.schedules)):
for schedule_index, schedule_value in enumerate(_domestic_hot_water_reference.schedules):
schedule = Schedule()
schedule.type = _domestic_hot_water_reference.schedules[i_schedule].type
schedule.day_types = _domestic_hot_water_reference.schedules[i_schedule].day_types
schedule.data_type = _domestic_hot_water_reference.schedules[i_schedule].data_type
schedule.time_step = _domestic_hot_water_reference.schedules[i_schedule].time_step
schedule.time_range = _domestic_hot_water_reference.schedules[i_schedule].time_range
schedule.type = schedule_value.type
schedule.day_types = schedule_value.day_types
schedule.data_type = schedule_value.data_type
schedule.time_step = schedule_value.time_step
schedule.time_range = schedule_value.time_range
new_values = []
for i_value in range(0, len(_domestic_hot_water_reference.schedules[i_schedule].values)):
for i_value, _ in enumerate(schedule_value.values):
_new_value = 0
for usage in self.usages:
_new_value += usage.percentage * usage.domestic_hot_water.schedules[i_schedule].values[i_value]
_new_value += usage.percentage * usage.domestic_hot_water.schedules[schedule_index].values[i_value]
new_values.append(_new_value)
schedule.values = new_values
_schedules.append(schedule)

View File

@ -8,29 +8,27 @@ Code contributors: Peter Yefi peteryefi@gmail.com
from __future__ import annotations
import bz2
import logging
import sys
import pickle
import math
import copy
import pyproj
from typing import List, Union
from pyproj import Transformer
import logging
import math
import pickle
from pathlib import Path
from typing import List, Union
import pyproj
from pandas import DataFrame
from pyproj import Transformer
from hub.city_model_structure.building import Building
from hub.city_model_structure.buildings_cluster import BuildingsCluster
from hub.city_model_structure.city_object import CityObject
from hub.city_model_structure.city_objects_cluster import CityObjectsCluster
from hub.city_model_structure.buildings_cluster import BuildingsCluster
from hub.city_model_structure.energy_system import EnergySystem
from hub.city_model_structure.iot.station import Station
from hub.city_model_structure.level_of_detail import LevelOfDetail
from hub.city_model_structure.parts_consisting_building import PartsConsistingBuilding
from hub.helpers.geometry_helper import GeometryHelper
from hub.helpers.location import Location
import hub.helpers.constants as cte
from hub.city_model_structure.energy_system import EnergySystem
import pandas as pd
class City:
@ -70,11 +68,11 @@ class City:
if self._location is None:
gps = pyproj.CRS('EPSG:4326') # LatLon with WGS84 datum used by GPS units and Google Earth
try:
if self._srs_name in GeometryHelper.srs_transformations.keys():
if self._srs_name in GeometryHelper.srs_transformations:
self._srs_name = GeometryHelper.srs_transformations[self._srs_name]
input_reference = pyproj.CRS(self.srs_name) # Projected coordinate system from input data
except pyproj.exceptions.CRSError as err:
logging.error('Invalid projection reference system, please check the input data. (e.g. in CityGML files: srs_name)')
logging.error('Invalid projection reference system, please check the input data.')
raise pyproj.exceptions.CRSError from err
transformer = Transformer.from_crs(input_reference, gps)
coordinates = transformer.transform(self.lower_corner[0], self.lower_corner[1])
@ -90,7 +88,11 @@ class City:
return self._get_location().country
@property
def location(self):
def location(self) -> Location:
"""
Get city location
:return: Location
"""
return self._get_location().city
@property
@ -203,8 +205,11 @@ class City:
return None
def add_building_alias(self, building, alias):
"""
Add an alias to the building
"""
building_index = self._city_objects_dictionary[building.name]
if alias in self._city_objects_alias_dictionary.keys():
if alias in self._city_objects_alias_dictionary:
self._city_objects_alias_dictionary[alias].append(building_index)
else:
self._city_objects_alias_dictionary[alias] = [building_index]
@ -218,7 +223,6 @@ class City:
if new_city_object.type == 'building':
if self._buildings is None:
self._buildings = []
new_city_object._alias_dictionary = self._city_objects_alias_dictionary
self._buildings.append(new_city_object)
self._city_objects_dictionary[new_city_object.name] = len(self._buildings) - 1
if new_city_object.aliases is not None:
@ -242,17 +246,17 @@ class City:
"""
if city_object.type != 'building':
raise NotImplementedError(city_object.type)
if self._buildings is None or self._buildings == []:
sys.stderr.write('Warning: impossible to remove city_object, the city is empty\n')
if not self._buildings:
logging.warning('impossible to remove city_object, the city is empty\n')
else:
if city_object in self._buildings:
self._buildings.remove(city_object)
# regenerate hash map
self._city_objects_dictionary.clear()
self._city_objects_alias_dictionary.clear()
for i, city_object in enumerate(self._buildings):
self._city_objects_dictionary[city_object.name] = i
for alias in city_object.aliases:
for i, _building in enumerate(self._buildings):
self._city_objects_dictionary[_building.name] = i
for alias in _building.aliases:
if alias in self._city_objects_alias_dictionary:
self._city_objects_alias_dictionary[alias].append(i)
else:
@ -300,8 +304,8 @@ class City:
:param city_filename: destination city filename
:return: None
"""
with bz2.BZ2File(city_filename, 'wb') as f:
pickle.dump(self, f)
with bz2.BZ2File(city_filename, 'wb') as file:
pickle.dump(self, file)
def region(self, center, radius) -> City:
"""
@ -446,6 +450,10 @@ class City:
return copy.deepcopy(self)
def merge(self, city) -> City:
"""
Return a merged city combining the current city and the given one
:return: City
"""
raise NotImplementedError('This method needs to be reimplemented')
@property

View File

@ -37,11 +37,11 @@ class CityObject:
self._max_z = ConfigurationHelper().min_coordinate
self._centroid = None
self._volume = None
self._external_temperature = dict()
self._ground_temperature = dict()
self._global_horizontal = dict()
self._diffuse = dict()
self._beam = dict()
self._external_temperature = {}
self._ground_temperature = {}
self._global_horizontal = {}
self._diffuse = {}
self._beam = {}
self._sensors = []
self._neighbours = None

View File

@ -1,5 +1,5 @@
"""
Energy control system definition
Energy control system module
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2023 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca

View File

@ -1,5 +1,5 @@
"""
Generic energy emission system definition
Generic energy emission system module
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2023 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca

View File

@ -46,7 +46,7 @@ class HeatPump:
@hp_monthly_fossil_consumption.setter
def hp_monthly_fossil_consumption(self, value):
if type(value) is Series:
if isinstance(value, Series):
self._hp_monthly_fossil_consumption = value
@property
@ -60,5 +60,5 @@ class HeatPump:
@hp_monthly_electricity_demand.setter
def hp_monthly_electricity_demand(self, value):
if type(value) == Series:
if isinstance(value, Series):
self._hp_monthly_electricity_demand = value

View File

@ -30,4 +30,3 @@ class HvacTerminalUnit:
"""
if value is not None:
self._type = str(value)

View File

@ -1,5 +1,5 @@
"""
Plant class
Plant module
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
@ -10,6 +10,9 @@ from hub.city_model_structure.greenery.soil import Soil
class Plant:
"""
Plant class
"""
def __init__(self, name, height, leaf_area_index, leaf_reflectivity, leaf_emissivity, minimal_stomatal_resistance,
co2_sequestration, grows_on_soils):
self._name = name

View File

@ -1,5 +1,5 @@
"""
Soil class
Soil module
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
@ -7,6 +7,9 @@ Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
class Soil:
"""
Soil class
"""
def __init__(self, name, roughness, dry_conductivity, dry_density, dry_specific_heat, thermal_absorptance,
solar_absorptance, visible_absorptance, saturation_volumetric_moisture_content,
residual_volumetric_moisture_content):

View File

@ -1,5 +1,5 @@
"""
Vegetation class
Vegetation module
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
@ -11,6 +11,9 @@ from hub.city_model_structure.greenery.plant import Plant
class Vegetation:
"""
Vegetation class
"""
def __init__(self, name, soil, soil_thickness, plants):
self._name = name
self._management = None

View File

View File

@ -7,6 +7,9 @@ Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
class SensorMeasure:
"""
Sensor measure class
"""
def __init__(self, latitude, longitude, utc_timestamp, value):
self._latitude = latitude
self._longitude = longitude

View File

@ -9,6 +9,9 @@ from enum import Enum
class SensorType(Enum):
"""
Sensor type enumeration
"""
HUMIDITY = 0
TEMPERATURE = 1
CO2 = 2

View File

@ -1,5 +1,5 @@
"""
Station
Station module
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group
Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
@ -10,6 +10,9 @@ from hub.city_model_structure.iot.sensor import Sensor
class Station:
"""
Station class
"""
def __init__(self, station_id=None, _mobile=False):
self._id = station_id
self._mobile = _mobile

0
hub/exports/__init__.py Normal file
View File

View File

View File

@ -93,7 +93,7 @@ class EnergyAde:
file_name = self._city.name + '_ade.gml'
file_path = Path(self._path / file_name).resolve()
with open(file_path, 'w') as file:
with open(file_path, 'w', encoding='utf8') as file:
file.write(xmltodict.unparse(energy_ade, pretty=True, short_empty_elements=True))
@staticmethod

View File

@ -247,16 +247,16 @@ class Idf:
_new_field += f' {self.idf_day_types[day_type]}'
_kwargs[f'Field_{j * 25 + 2}'] = f'For:{_new_field}'
counter += 1
for i in range(0, len(_val)):
for i, _ in enumerate(_val):
_kwargs[f'Field_{j * 25 + 3 + i}'] = f'Until: {i + 1:02d}:00,{_val[i]}'
counter += 1
_kwargs[f'Field_{counter + 1}'] = f'For AllOtherDays'
_kwargs[f'Field_{counter + 2}'] = f'Until: 24:00,0.0'
_kwargs[f'Field_{counter + 1}'] = 'For AllOtherDays'
_kwargs[f'Field_{counter + 2}'] = 'Until: 24:00,0.0'
self._idf.newidfobject(self._COMPACT_SCHEDULE, **_kwargs)
def _write_schedules_file(self, usage, schedule):
file_name = str((Path(self._output_path) / f'{schedule.type} schedules {usage}.dat').resolve())
with open(file_name, 'w') as file:
with open(file_name, 'w', encoding='utf8') as file:
for value in schedule.values:
file.write(f'{str(value)},\n')
return file_name
@ -284,12 +284,14 @@ class Idf:
if schedule.Name == f'{schedule_type} schedules {usage}':
return
file_name = self._write_schedules_file(usage, new_schedules[0])
return self._add_file_schedule(usage, new_schedules[0], file_name)
else:
for schedule in self._idf.idfobjects[self._HOURLY_SCHEDULE]:
if schedule.Name == f'{schedule_type} schedules {usage}':
return
return self._add_standard_compact_hourly_schedule(usage, schedule_type, new_schedules)
self._add_file_schedule(usage, new_schedules[0], file_name)
return
for schedule in self._idf.idfobjects[self._HOURLY_SCHEDULE]:
if schedule.Name == f'{schedule_type} schedules {usage}':
return
self._add_standard_compact_hourly_schedule(usage, schedule_type, new_schedules)
return
def _add_construction(self, thermal_boundary):
vegetation_name = f'{thermal_boundary.construction_name}_{thermal_boundary.parent_surface.vegetation.name}'
@ -441,7 +443,7 @@ class Idf:
def _add_ventilation(self, thermal_zone, zone_name):
for zone in self._idf.idfobjects["ZONE"]:
if zone.Name == f'{zone_name}_ventilation':
return
return
schedule = f'Ventilation schedules {thermal_zone.usage_name}'
#if schedule not in self._idf.idfobjects[self._HOURLY_SCHEDULE]:
# return

View File

@ -27,7 +27,9 @@ _NUMBER_DAYS_PER_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
class InselMonthlyEnergyBalance:
"""
Insel monthly energy balance class
"""
def __init__(self, city, path, radiation_calculation_method='sra', weather_format='epw'):
self._city = city
self._path = path
@ -44,7 +46,7 @@ class InselMonthlyEnergyBalance:
if building.internal_zones is not None:
for internal_zone in building.internal_zones:
if internal_zone.thermal_zones is None:
logging.error(f'Building {building.name} has missing values. Monthly Energy Balance cannot be processed\n')
logging.warning(f'Building %s has missing values. Monthly Energy Balance cannot be processed', building.name)
break
self._contents.append(
self._generate_meb_template(building, output_path, self._radiation_calculation_method, self._weather_format)
@ -65,33 +67,33 @@ class InselMonthlyEnergyBalance:
def _export(self):
for i_file, content in enumerate(self._contents):
file_name = self._insel_files_paths[i_file]
with open(Path(self._path / file_name).resolve(), 'w') as insel_file:
with open(Path(self._path / file_name).resolve(), 'w', encoding='utf8') as insel_file:
insel_file.write(content)
return
def _sanity_check(self):
levels_of_detail = self._city.level_of_detail
if levels_of_detail.geometry is None:
raise Exception(f'Level of detail of geometry not assigned')
raise AttributeError('Level of detail of geometry not assigned')
if levels_of_detail.geometry < 1:
raise Exception(f'Level of detail of geometry = {levels_of_detail.geometry}. Required minimum level 0.5')
raise AttributeError(f'Level of detail of geometry = {levels_of_detail.geometry}. Required minimum level 0.5')
if levels_of_detail.construction is None:
raise Exception(f'Level of detail of construction not assigned')
raise AttributeError('Level of detail of construction not assigned')
if levels_of_detail.construction < 1:
raise Exception(f'Level of detail of construction = {levels_of_detail.construction}. Required minimum level 1')
raise AttributeError(f'Level of detail of construction = {levels_of_detail.construction}. Required minimum level 1')
if levels_of_detail.usage is None:
raise Exception(f'Level of detail of usage not assigned')
raise AttributeError('Level of detail of usage not assigned')
if levels_of_detail.usage < 1:
raise Exception(f'Level of detail of usage = {levels_of_detail.usage}. Required minimum level 1')
raise AttributeError(f'Level of detail of usage = {levels_of_detail.usage}. Required minimum level 1')
if levels_of_detail.weather is None:
raise Exception(f'Level of detail of weather not assigned')
raise AttributeError('Level of detail of weather not assigned')
if levels_of_detail.weather < 1:
raise Exception(f'Level of detail of weather = {levels_of_detail.weather}. Required minimum level 1')
raise AttributeError(f'Level of detail of weather = {levels_of_detail.weather}. Required minimum level 1')
if levels_of_detail.surface_radiation is None:
raise Exception(f'Level of detail of surface radiation not assigned')
raise AttributeError('Level of detail of surface radiation not assigned')
if levels_of_detail.surface_radiation < 1:
raise Exception(f'Level of detail of surface radiation = {levels_of_detail.surface_radiation}. '
f'Required minimum level 1')
raise AttributeError(f'Level of detail of surface radiation = {levels_of_detail.surface_radiation}. '
f'Required minimum level 1')
@staticmethod
def _generate_meb_template(building, insel_outputs_path, radiation_calculation_method, weather_format):

View File

@ -5,8 +5,8 @@ Copyright © 2022 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de uribarri pilar.monsalvete@concordia.ca
"""
import logging
from pathlib import Path
from hub.exports.building_energy.energy_ade import EnergyAde
from hub.exports.building_energy.idf import Idf
from hub.exports.building_energy.insel.insel_monthly_energy_balance import InselMonthlyEnergyBalance

View File

@ -49,8 +49,8 @@ class EnergySystemsExportFactory:
if self._source == 'air':
return AirSourceHPExport(self._base_path, self._city, self._output_path, self._sim_type, self._demand_path)\
.execute_insel(self._handler, self._hp_model, self._data_type)
elif self._source == 'water':
return WaterToWaterHPExport(self._base_path, self._city, self._output_path, self._sim_type, self._demand_path)\
return WaterToWaterHPExport(self._base_path, self._city, self._output_path, self._sim_type, self._demand_path)\
.execute_insel(self._handler, self._hp_model)
def export(self, source='air'):

View File

@ -5,8 +5,8 @@ Copyright © 2022 Concordia CERC group
Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
"""
import logging
from pathlib import Path
from hub.exports.formats.obj import Obj
from hub.exports.formats.simplified_radiosity_algorithm import SimplifiedRadiosityAlgorithm
from hub.exports.formats.stl import Stl
@ -78,4 +78,4 @@ class ExportsFactory:
Export the city given to the class using the given export type handler
:return: None
"""
return getattr(self, self._handler, lambda: None)
return getattr(self, self._handler, lambda: None)

View File

0
hub/helpers/__init__.py Normal file
View File

View File

View File

View File

@ -85,7 +85,7 @@ class ConstructionHelper:
:return: str
"""
reference_city = ConstructionHelper.city_to_reference_city(city)
if reference_city not in ConstructionHelper._reference_city_to_nrel_climate_zone.keys():
if reference_city not in ConstructionHelper._reference_city_to_nrel_climate_zone:
reference_city = 'Baltimore'
return ConstructionHelper._reference_city_to_nrel_climate_zone[reference_city]

View File

@ -59,7 +59,7 @@ class StoreysGeneration:
return [storey.thermal_zone]
if number_of_storeys == 0:
raise Exception('Number of storeys cannot be 0')
raise ArithmeticError('Number of storeys cannot be 0')
storeys = []
surfaces_child_last_storey = []
@ -106,7 +106,7 @@ class StoreysGeneration:
neighbours = ['storey_' + str(number_of_storeys - 2), None]
volume = self._building.volume - total_volume
if volume < 0:
raise Exception('Error in storeys creation, volume of last storey cannot be lower that 0')
raise ArithmeticError('Error in storeys creation, volume of last storey cannot be lower that 0')
storeys.append(Storey(name, surfaces_child_last_storey, neighbours, volume, self._internal_zone, self._floor_area))
for storey in storeys:

View File

@ -43,4 +43,4 @@ class ConstructionFactory:
Enrich the city given to the class using the class given handler
:return: None
"""
getattr(self, self._handler, lambda: None)()
getattr(self, self._handler, lambda: None)()

View File

View File

@ -7,14 +7,14 @@ contributor Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
import io
import pandas as pd
import itertools
from typing import List
from typing import Dict
import pandas as pd
import numpy as np
from scipy.optimize import curve_fit
from hub.city_model_structure.energy_systems.air_source_hp import AirSourceHP
from hub.city_model_structure.energy_system import EnergySystem
from scipy.optimize import curve_fit
import numpy as np
from typing import List
import itertools
class AirSourceHeatPumpParameters:
@ -24,7 +24,7 @@ class AirSourceHeatPumpParameters:
def __init__(self, city, base_path):
self._city = city
self._base_path = (base_path / 'heat_pumps/air_source.xlsx')
self._base_path = (base_path / 'heat_pumps/air_source.xlsx').resolve()
def _read_file(self) -> Dict:
"""
@ -38,7 +38,7 @@ class AirSourceHeatPumpParameters:
cooling_data = {}
heating_data = {}
for sheet, dataframe in xl_file.items():
for sheet, _ in xl_file.items():
if 'Summary' in sheet:
continue
@ -68,7 +68,7 @@ class AirSourceHeatPumpParameters:
Enriches the city with information from file
"""
heat_pump_data = self._read_file()
for (k_cool, v_cool), (k_heat, v_heat) in zip(heat_pump_data["cooling"].items(), heat_pump_data["heating"].items()):
for (k_cool, v_cool), (_, v_heat) in zip(heat_pump_data["cooling"].items(), heat_pump_data["heating"].items()):
heat_pump = AirSourceHP()
heat_pump.model = k_cool
h_data = self._extract_heat_pump_data(v_heat)
@ -80,7 +80,7 @@ class AirSourceHeatPumpParameters:
heat_pump.heating_comp_power = h_data[1]
heat_pump.heating_capacity_coff = self._compute_coefficients(h_data)
energy_system = EnergySystem('{} capacity heat pump'.format(heat_pump.model), [])
energy_system = EnergySystem(f'{heat_pump.model} capacity heat pump', [])
energy_system.air_source_hp = heat_pump
self._city.add_city_object(energy_system)
return self._city

View File

@ -43,7 +43,8 @@ class MontrealCustomEnergySystemParameters:
try:
archetype = self._search_archetypes(montreal_custom_catalog, archetype_name)
except KeyError:
logging.error(f'Building {building.name} has unknown energy system archetype for system name: {archetype_name}')
logging.error('Building %s has unknown energy system archetype for system name %s', building.name,
archetype_name)
continue
building_systems = []
@ -58,7 +59,7 @@ class MontrealCustomEnergySystemParameters:
energy_system.demand_types = _hub_demand_types
_generation_system = GenericGenerationSystem()
archetype_generation_equipment = equipment.generation_system
_type = str(equipment.name).split('_')[0]
_type = str(equipment.name).split('_', maxsplit=1)[0]
_generation_system.type = Dictionaries().montreal_system_to_hub_energy_generation_system[
_type]
_generation_system.fuel_type = archetype_generation_equipment.fuel_type

View File

@ -23,7 +23,7 @@ class WaterToWaterHPParameters:
def __init__(self, city, base_path):
self._city = city
self._base_path = (base_path / 'heat_pumps/water_to_water.xlsx')
self._base_path = (base_path / 'heat_pumps/water_to_water.xlsx').resolve()
def _read_file(self) -> Dict:
# todo: this method is keeping the excel file open and should be either corrected or removed
@ -38,7 +38,7 @@ class WaterToWaterHPParameters:
'335': [6.62, 9.97, 12.93],
}
for sheet, dataframe in heat_pump_dfs.items():
for sheet, _ in heat_pump_dfs.items():
df = heat_pump_dfs[sheet].dropna(axis=1, how='all')
df = df.iloc[3:, 6:35]

View File

View File

@ -41,7 +41,7 @@ class CityGml:
self._lower_corner = None
self._upper_corner = None
with open(path) as gml:
with open(path, 'r', encoding='utf8') as gml:
# Clean the namespaces is an important task to prevent wrong ns:field due poor citygml_classes implementations
force_list = ('cityObjectMember', 'curveMember', 'boundedBy', 'surfaceMember', 'consistsOfBuildingPart')
self._gml = xmltodict.parse(gml.read(), process_namespaces=True, xml_attribs=True, namespaces={
@ -123,7 +123,7 @@ class CityGml:
year_of_construction = city_object[self._year_of_construction_field]
if self._function_field in city_object:
function = city_object[self._function_field]
if type(function) != str:
if not isinstance(function, str):
function = function['#text']
if self._function_to_hub is not None:
# use the transformation dictionary to retrieve the proper function

View File

@ -74,7 +74,7 @@ class CityGmlLod2(CityGmlBase):
gml_points = gml_points_string.lstrip(' ')
solid_points = GeometryHelper.points_from_string(GeometryHelper.remove_last_point_from_string(gml_points))
polygon = Polygon(solid_points)
return Surface(polygon, polygon, surface_type=GeometryHelper.gml_surface_to_libs(surface_type))
return Surface(polygon, polygon, surface_type=GeometryHelper.gml_surface_to_hub(surface_type))
@classmethod
def _multi_curve(cls, city_object_member):

View File

@ -47,7 +47,7 @@ class Geojson:
self._year_of_construction_field = year_of_construction_field
self._function_field = function_field
self._function_to_hub = function_to_hub
with open(path) as json_file:
with open(path, 'r', encoding='utf8') as json_file:
self._geojson = json.loads(json_file.read())
def _save_bounds(self, x, y):
@ -98,8 +98,7 @@ class Geojson:
GeometryHelper.distance_between_points(line[0], neighbour_line[1])) / 2
percentage_ground = line_shared / GeometryHelper.distance_between_points(line[0], line[1])
percentage_height = neighbour_height / building.max_height
if percentage_height > 1:
percentage_height = 1
percentage_height = min(percentage_height, 1)
percentage += percentage_ground * percentage_height
wall.percentage_shared = percentage
@ -215,40 +214,40 @@ class Geojson:
building.add_alias(alias)
if extrusion_height == 0:
return building
else:
volume = 0
for ground in building.grounds:
volume += ground.solid_polygon.area * extrusion_height
roof_coordinates = []
# adding a roof means invert the polygon coordinates and change the Z value
for coordinate in ground.solid_polygon.coordinates:
roof_coordinate = np.array([coordinate[0], coordinate[1], extrusion_height])
# insert the roof rotated already
roof_coordinates.insert(0, roof_coordinate)
roof_polygon = Polygon(roof_coordinates)
roof_polygon.area = ground.solid_polygon.area
roof = Surface(roof_polygon, roof_polygon)
surfaces.append(roof)
# adding a wall means add the point coordinates and the next point coordinates with Z's height and 0
coordinates_length = len(roof.solid_polygon.coordinates)
for i, coordinate in enumerate(roof.solid_polygon.coordinates):
j = i + 1
if j == coordinates_length:
j = 0
next_coordinate = roof.solid_polygon.coordinates[j]
wall_coordinates = [
np.array([coordinate[0], coordinate[1], 0.0]),
np.array([next_coordinate[0], next_coordinate[1], 0.0]),
np.array([next_coordinate[0], next_coordinate[1], next_coordinate[2]]),
np.array([coordinate[0], coordinate[1], coordinate[2]])
]
polygon = Polygon(wall_coordinates)
wall = Surface(polygon, polygon)
surfaces.append(wall)
building = Building(f'{building_name}', surfaces, year_of_construction, function)
for alias in building_aliases:
building.add_alias(alias)
building.volume = volume
volume = 0
for ground in building.grounds:
volume += ground.solid_polygon.area * extrusion_height
roof_coordinates = []
# adding a roof means invert the polygon coordinates and change the Z value
for coordinate in ground.solid_polygon.coordinates:
roof_coordinate = np.array([coordinate[0], coordinate[1], extrusion_height])
# insert the roof rotated already
roof_coordinates.insert(0, roof_coordinate)
roof_polygon = Polygon(roof_coordinates)
roof_polygon.area = ground.solid_polygon.area
roof = Surface(roof_polygon, roof_polygon)
surfaces.append(roof)
# adding a wall means add the point coordinates and the next point coordinates with Z's height and 0
coordinates_length = len(roof.solid_polygon.coordinates)
for i, coordinate in enumerate(roof.solid_polygon.coordinates):
j = i + 1
if j == coordinates_length:
j = 0
next_coordinate = roof.solid_polygon.coordinates[j]
wall_coordinates = [
np.array([coordinate[0], coordinate[1], 0.0]),
np.array([next_coordinate[0], next_coordinate[1], 0.0]),
np.array([next_coordinate[0], next_coordinate[1], next_coordinate[2]]),
np.array([coordinate[0], coordinate[1], coordinate[2]])
]
polygon = Polygon(wall_coordinates)
wall = Surface(polygon, polygon)
surfaces.append(wall)
building = Building(f'{building_name}', surfaces, year_of_construction, function)
for alias in building_aliases:
building.add_alias(alias)
building.volume = volume
return building
def _parse_multi_polygon(self, polygons_coordinates, building_name, building_aliases, function, year_of_construction, extrusion_height):
@ -289,38 +288,38 @@ class Geojson:
building.add_alias(alias)
if extrusion_height == 0:
return building
else:
volume = 0
for ground in building.grounds:
volume += ground.solid_polygon.area * extrusion_height
roof_coordinates = []
# adding a roof means invert the polygon coordinates and change the Z value
for coordinate in ground.solid_polygon.coordinates:
roof_coordinate = np.array([coordinate[0], coordinate[1], extrusion_height])
# insert the roof rotated already
roof_coordinates.insert(0, roof_coordinate)
roof_polygon = Polygon(roof_coordinates)
roof_polygon.area = ground.solid_polygon.area
roof = Surface(roof_polygon, roof_polygon)
surfaces.append(roof)
# adding a wall means add the point coordinates and the next point coordinates with Z's height and 0
coordinates_length = len(roof.solid_polygon.coordinates)
for i, coordinate in enumerate(roof.solid_polygon.coordinates):
j = i + 1
if j == coordinates_length:
j = 0
next_coordinate = roof.solid_polygon.coordinates[j]
wall_coordinates = [
np.array([coordinate[0], coordinate[1], 0.0]),
np.array([next_coordinate[0], next_coordinate[1], 0.0]),
np.array([next_coordinate[0], next_coordinate[1], next_coordinate[2]]),
np.array([coordinate[0], coordinate[1], coordinate[2]])
]
polygon = Polygon(wall_coordinates)
wall = Surface(polygon, polygon)
surfaces.append(wall)
building = Building(f'{building_name}', surfaces, year_of_construction, function)
for alias in building_aliases:
building.add_alias(alias)
building.volume = volume
volume = 0
for ground in building.grounds:
volume += ground.solid_polygon.area * extrusion_height
roof_coordinates = []
# adding a roof means invert the polygon coordinates and change the Z value
for coordinate in ground.solid_polygon.coordinates:
roof_coordinate = np.array([coordinate[0], coordinate[1], extrusion_height])
# insert the roof rotated already
roof_coordinates.insert(0, roof_coordinate)
roof_polygon = Polygon(roof_coordinates)
roof_polygon.area = ground.solid_polygon.area
roof = Surface(roof_polygon, roof_polygon)
surfaces.append(roof)
# adding a wall means add the point coordinates and the next point coordinates with Z's height and 0
coordinates_length = len(roof.solid_polygon.coordinates)
for i, coordinate in enumerate(roof.solid_polygon.coordinates):
j = i + 1
if j == coordinates_length:
j = 0
next_coordinate = roof.solid_polygon.coordinates[j]
wall_coordinates = [
np.array([coordinate[0], coordinate[1], 0.0]),
np.array([next_coordinate[0], next_coordinate[1], 0.0]),
np.array([next_coordinate[0], next_coordinate[1], next_coordinate[2]]),
np.array([coordinate[0], coordinate[1], coordinate[2]])
]
polygon = Polygon(wall_coordinates)
wall = Surface(polygon, polygon)
surfaces.append(wall)
building = Building(f'{building_name}', surfaces, year_of_construction, function)
for alias in building_aliases:
building.add_alias(alias)
building.volume = volume
return building

View File

@ -58,7 +58,7 @@ class GPandas:
if self._city is None:
self._city = City(self._lower_corner, self._upper_corner, self._srs_name)
lod = 0
for scene_index, bldg in self._scene.iterrows():
for _, bldg in self._scene.iterrows():
polygon = bldg.geometry
height = float(bldg['height'])
building_mesh = trimesh.creation.extrude_polygon(polygon, height)
@ -72,7 +72,7 @@ class GPandas:
else:
function = cte.INDUSTRY
surfaces = []
for face_index, face in enumerate(building_mesh.faces):
for _, face in enumerate(building_mesh.faces):
points = []
for vertex_index in face:
points.append(building_mesh.vertices[vertex_index])

View File

View File

@ -8,7 +8,7 @@ import math
import sys
import numpy as np
from numpy import ndarray
class GeometryHelper:
"""
@ -26,7 +26,7 @@ class GeometryHelper:
return points
@staticmethod
def gml_surface_to_libs(surface):
def gml_surface_to_hub(surface):
"""
Transform citygml surface names into hub names
"""
@ -38,21 +38,33 @@ class GeometryHelper:
@staticmethod
def points_from_string(coordinates) -> np.ndarray:
"""
Creates a ndarray from a string
:return: [Point]
"""
points = np.fromstring(coordinates, dtype=float, sep=' ')
points = GeometryHelper.to_points_matrix(points)
return points
@staticmethod
def remove_last_point_from_string(points):
def remove_last_point_from_string(points) -> [ndarray]:
"""
Return the point list without the last element
:return [ndarray]
"""
array = points.split(' ')
res = " "
return res.join(array[0:len(array) - 3])
@staticmethod
def invert_points(points):
def invert_points(points) -> [ndarray]:
"""
Invert the point list
:return: [ndarray]
"""
res = []
for point in points:
res.insert(0,point)
res.insert(0, point)
return res
@staticmethod

View File

@ -19,7 +19,7 @@ class Obj:
"""
def __init__(self, path):
self._city = None
with open(path, 'r') as file:
with open(path, 'r', encoding='utf8') as file:
self._scene = trimesh.exchange.load.load(file, file_type='obj', force='scene')
self._corners = self._scene.bounds_corners
_bound_corner_min = None
@ -70,7 +70,6 @@ class Obj:
obj = scene[key]
surfaces = []
for face in obj.faces:
# todo: review for obj with windows
points = []
for vertex_index in face:
points.append(obj.vertices[vertex_index])

View File

@ -6,8 +6,7 @@ Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.capip
"""
import numpy as np
from rhino3dm import *
from rhino3dm._rhino3dm import Extrusion
from rhino3dm._rhino3dm import MeshType
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
@ -19,6 +18,9 @@ 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)
@ -85,6 +87,10 @@ class Rhino:
@property
def city(self) -> City:
"""
Return a city based in the rhino file
:return: City
"""
buildings = []
city_objects = [] # building and "windows"
windows = []

View File

@ -94,4 +94,13 @@ class GeometryFactory:
Enrich the city given to the class using the class given handler
:return: City
"""
return getattr(self, self._file_type, lambda: None)
return getattr(self, self._file_type, lambda: None)
@property
def city_debug(self) -> City:
"""
Enrich the city given to the class using the class given handler
:return: City
"""
print('rhino')
return Rhino(self._path).city

View File

View File

@ -21,12 +21,15 @@ class InselHeatPumpEnergyDemand:
"""
self._city = city
self._hp_model = hp_model
with open(Path(base_path).resolve()) as csv_file:
with open(Path(base_path).resolve(), 'r', encoding='utf8') as csv_file:
df = pd.read_csv(csv_file)
self._monthly_electricity_demand = df.iloc[:, 1]
self._monthly_fossil_fuel_consumption = df.iloc[:, 2]
def enrich(self):
"""
Enrich the city with the heat pump information
"""
for energy_system in self._city.energy_systems:
if energy_system.air_source_hp is not None:
if energy_system.air_source_hp.model == self._hp_model:
@ -35,4 +38,3 @@ class InselHeatPumpEnergyDemand:
if energy_system.water_to_water_hp is not None:
if energy_system.water_to_water_hp.model == self._hp_model:
energy_system.water_to_water_hp.hp_monthly_electricity_demand = self._monthly_electricity_demand

View File

@ -5,8 +5,9 @@ Copyright © 2022 Concordia CERC group
Project Coder Guillermo.GutierrezMorote@concordia.ca
"""
from pathlib import Path
import pandas as pd
import csv
import pandas as pd
import hub.helpers.constants as cte
@ -23,7 +24,7 @@ class InselMonthlyEnergyBalance:
def _conditioning_demand(insel_output_file_path):
heating = []
cooling = []
with open(Path(insel_output_file_path).resolve()) as csv_file:
with open(Path(insel_output_file_path).resolve(), 'r', encoding='utf8') as csv_file:
csv_reader = csv.reader(csv_file)
for line in csv_reader:
demand = str(line).replace("['", '').replace("']", '').split()
@ -108,6 +109,10 @@ class InselMonthlyEnergyBalance:
)
def enrich(self):
"""
Enrich the city by using the insel monthly energy balance output files
:return: None
"""
for building in self._city.buildings:
file_name = building.name + '.out'
insel_output_file_path = Path(self._base_path / file_name).resolve()

View File

@ -4,9 +4,9 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group
Project Coder Guillermo.GutierrezMorote@concordia.ca
"""
import calendar as cal
import pandas as pd
import numpy as np
import calendar as cal
import hub.helpers.constants as cte
@ -18,7 +18,7 @@ class SimplifiedRadiosityAlgorithm:
self._city = city
self._base_path = base_path
self._input_file_path = (self._base_path / f'{self._city.name}_sra_SW.out')
self._input_file_path = (self._base_path / f'{self._city.name}_sra_SW.out').resolve()
self._month_hour = self._month_hour_data_frame
self._results = self._read_results()
self._radiation_list = []
@ -48,8 +48,8 @@ class SimplifiedRadiosityAlgorithm:
def _read_results(self):
try:
return pd.read_csv(self._input_file_path, sep='\s+', header=0)
except Exception:
raise Exception('No SRA output file found')
except FileNotFoundError as err:
raise FileNotFoundError('No SRA output file found') from err
@property
def _radiation(self) -> []:

View File

View File

@ -5,9 +5,8 @@ Copyright © 2022 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
import copy
import numpy
import logging
import numpy
import hub.helpers.constants as cte
from hub.helpers.dictionaries import Dictionaries
from hub.city_model_structure.building_demand.usage import Usage
@ -40,16 +39,16 @@ class ComnetUsageParameters:
try:
archetype_usage = self._search_archetypes(comnet_catalog, usage_name)
except KeyError:
logging.error(f'Building {building.name} has unknown usage archetype for usage: {usage_name}')
logging.error('Building %s has unknown usage archetype for usage %s', building.name, usage_name)
continue
for internal_zone in building.internal_zones:
if internal_zone.area is None:
raise Exception('Internal zone area not defined, ACH cannot be calculated')
raise TypeError('Internal zone area not defined, ACH cannot be calculated')
if internal_zone.volume is None:
raise Exception('Internal zone volume not defined, ACH cannot be calculated')
raise TypeError('Internal zone volume not defined, ACH cannot be calculated')
if internal_zone.area <= 0:
raise Exception('Internal zone area is zero, ACH cannot be calculated')
raise TypeError('Internal zone area is zero, ACH cannot be calculated')
volume_per_area = internal_zone.volume / internal_zone.area
usage = Usage()
usage.name = usage_name
@ -160,7 +159,7 @@ class ComnetUsageParameters:
@staticmethod
def _calculate_internal_gains(archetype):
_DAYS = [cte.MONDAY, cte.TUESDAY, cte.WEDNESDAY, cte.THURSDAY, cte.FRIDAY, cte.SATURDAY, cte.SUNDAY, cte.HOLIDAY]
_days = [cte.MONDAY, cte.TUESDAY, cte.WEDNESDAY, cte.THURSDAY, cte.FRIDAY, cte.SATURDAY, cte.SUNDAY, cte.HOLIDAY]
_number_of_days_per_type = [51, 50, 50, 50, 50, 52, 52, 10]
_mean_internal_gain = InternalGain()
@ -174,13 +173,13 @@ class ComnetUsageParameters:
_latent_heat_gain = archetype.occupancy.latent_internal_gain
_convective_heat_gain = archetype.occupancy.sensible_convective_internal_gain
_radiative_heat_gain = archetype.occupancy.sensible_radiative_internal_gain
_total_heat_gain = (_latent_heat_gain + _convective_heat_gain + _radiative_heat_gain)
_total_heat_gain = _latent_heat_gain + _convective_heat_gain + _radiative_heat_gain
_schedule_values = numpy.zeros([24, 8])
_sum = 0
for day, _schedule in enumerate(archetype.occupancy.schedules):
for v, value in enumerate(_schedule.values):
_schedule_values[v, day] = value * _total_heat_gain
for v_index, value in enumerate(_schedule.values):
_schedule_values[v_index, day] = value * _total_heat_gain
_sum += value * _total_heat_gain * _number_of_days_per_type[day]
_total_heat_gain += archetype.lighting.density + archetype.appliances.density
@ -198,13 +197,13 @@ class ComnetUsageParameters:
)
for day, _schedule in enumerate(archetype.lighting.schedules):
for v, value in enumerate(_schedule.values):
_schedule_values[v, day] += value * archetype.lighting.density
for v_index, value in enumerate(_schedule.values):
_schedule_values[v_index, day] += value * archetype.lighting.density
_sum += value * archetype.lighting.density * _number_of_days_per_type[day]
for day, _schedule in enumerate(archetype.appliances.schedules):
for v, value in enumerate(_schedule.values):
_schedule_values[v, day] += value * archetype.appliances.density
for v_index, value in enumerate(_schedule.values):
_schedule_values[v_index, day] += value * archetype.appliances.density
_sum += value * archetype.appliances.density * _number_of_days_per_type[day]
_latent_fraction = 0
@ -218,9 +217,9 @@ class ComnetUsageParameters:
_average_internal_gain = _sum / _total_heat_gain
_schedules = []
for day in range(0, len(_DAYS)):
for day, current_day in enumerate(_days):
_schedule = copy.deepcopy(_base_schedule)
_schedule.day_types = [_DAYS[day]]
_schedule.day_types = [current_day]
_schedule.values = _schedule_values[:day]
_schedules.append(_schedule)

View File

@ -39,36 +39,36 @@ class NrcanUsageParameters:
try:
archetype_usage = self._search_archetypes(nrcan_catalog, usage_name)
except KeyError:
logging.error(f'Building {building.name} has unknown usage archetype for usage: {usage_name}\n')
logging.error('Building %s has unknown usage archetype for usage %s', building.name, usage_name)
continue
comnet_usage_name = Dictionaries().hub_usage_to_comnet_usage[building.function]
try:
comnet_archetype_usage = self._search_archetypes(comnet_catalog, comnet_usage_name)
except KeyError:
logging.error(f'Building {building.name} has unknown usage archetype for usage: {comnet_usage_name}\n')
logging.error('Building %s has unknown usage archetype for usage %s', building.name, comnet_usage_name)
continue
for internal_zone in building.internal_zones:
if len(building.internal_zones) > 1:
volume_per_area = 0
if internal_zone.area is None:
logging.error(f'Building {building.name} has internal zone area not defined, '
f'ACH cannot be calculated for usage: {usage_name}\n')
logging.error('Building %s has internal zone area not defined, ACH cannot be calculated for usage %s',
building.name, usage_name)
continue
if internal_zone.volume is None:
logging.error(f'Building {building.name} has internal zone volume not defined, '
f'ACH cannot be calculated for usage: {usage_name}\n')
logging.error('Building %s has internal zone volume not defined, ACH cannot be calculated for usage %s',
building.name, usage_name)
continue
if internal_zone.area <= 0:
logging.error(f'Building {building.name} has internal zone area equal to 0, '
f'ACH cannot be calculated for usage: {usage_name}\n')
logging.error('Building %s has internal zone area equal to 0, ACH cannot be calculated for usage %s',
building.name, usage_name)
continue
volume_per_area += internal_zone.volume / internal_zone.area
else:
if building.storeys_above_ground is None:
logging.error(f'Building {building.name} no number of storeys assigned, '
f'ACH cannot be calculated for usage: {usage_name}\n')
logging.error('Building %s no number of storeys assigned, ACH cannot be calculated for usage %s',
building.name, usage_name)
continue
volume_per_area = building.volume / building.floor_area / building.storeys_above_ground

View File

View File

@ -22,27 +22,26 @@ class EpwWeatherParameters:
self._path = Path(path / file_name)
try:
file = open(self._path, 'r')
line = file.readline().split(',')
city.climate_reference_city = line[1]
city.latitude = line[6]
city.longitude = line[7]
city.time_zone = line[8]
for i in range(0, 2):
_ = file.readline().split(',')
line = file.readline().split(',')
number_records = int(line[1])
ground_temperature = {}
for i in range(0, number_records):
depth_measurement_ground_temperature = line[i*16+2]
temperatures = []
for j in range(0, 12):
temperatures.append(float(line[i*16+j+6]))
ground_temperature[depth_measurement_ground_temperature] = temperatures
file.close()
with open(self._path, 'r', encoding='utf8') as file:
line = file.readline().split(',')
city.climate_reference_city = line[1]
city.latitude = line[6]
city.longitude = line[7]
city.time_zone = line[8]
for i in range(0, 2):
_ = file.readline().split(',')
line = file.readline().split(',')
number_records = int(line[1])
ground_temperature = {}
for i in range(0, number_records):
depth_measurement_ground_temperature = line[i*16+2]
temperatures = []
for j in range(0, 12):
temperatures.append(float(line[i*16+j+6]))
ground_temperature[depth_measurement_ground_temperature] = temperatures
except SystemExit:
logging.error(f'Error: weather file {self._path} not found. Please download it from '
f'https://energyplus.net/weather and place it in folder data\\weather\\epw\n')
logging.error('Error: weather file %s not found. Please download it from https://energyplus.net/weather and place'
' it in folder data\\weather\\epw', self._path)
sys.exit()
try:

View File

View File

@ -6,10 +6,10 @@ Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
import math
import hub.helpers.constants as cte
import pandas as pd
import calendar as cal
import pandas as pd
import numpy as np
import hub.helpers.constants as cte
class Weather:
@ -65,6 +65,10 @@ class Weather:
return pd.DataFrame(cold_temperature, columns=['epw'])
def get_monthly_mean_values(self, values):
"""
Get the monthly mean for the given values
:return: float
"""
out = None
if values is not None:
if 'month' not in values.columns:
@ -75,9 +79,17 @@ class Weather:
@staticmethod
def get_yearly_mean_values(values):
"""
Get the yearly mean for the given values
:return: float
"""
return values.mean()
def get_total_month(self, values):
"""
Get the total value the given values
:return: float
"""
out = None
if values is not None:
if 'month' not in values.columns:

View File

@ -1,3 +0,0 @@
"""
Persistence package
"""

184
setup.py
View File

@ -16,97 +16,103 @@ install_requires.append('setuptools')
main_ns = {}
version = convert_path('hub/version.py')
with open(version) as f:
exec(f.read(), main_ns)
exec(f.read(), main_ns)
setup(
name='cerc-hub',
version=main_ns['__version__'],
description="CERC Hub consist in a set of classes (Central data model), importers and exporters to help researchers "
"to create better and sustainable cities",
long_description="CERC Hub consist in a set of classes (Central data model), importers and exporters to help "
"researchers to create better and sustainable cities.\n\nDevelop at Concordia university in canada "
"as part of the research group from the next generation cities institute our aim among others it's "
"to provide a comprehensive set of tools to help researchers and urban developers to make decisions "
"to improve the livability and efficiency of our cities",
classifiers=[
"License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
],
include_package_data=True,
packages=['hub',
'hub.catalog_factories',
'hub.catalog_factories.construction',
'hub.catalog_factories.data_models',
'hub.catalog_factories.data_models.construction',
'hub.catalog_factories.data_models.greenery',
'hub.catalog_factories.data_models.usages',
'hub.catalog_factories.greenery',
'hub.catalog_factories.greenery.ecore_greenery',
'hub.catalog_factories.usage',
'hub.city_model_structure',
'hub.city_model_structure.attributes',
'hub.city_model_structure.building_demand',
'hub.city_model_structure.energy_systems',
'hub.city_model_structure.greenery',
'hub.city_model_structure.iot',
'hub.city_model_structure.transport',
'hub.config',
'hub.data',
'hub.exports',
'hub.exports.building_energy',
'hub.exports.building_energy.idf_files',
'hub.exports.building_energy.insel',
'hub.exports.energy_systems',
'hub.exports.formats',
'hub.helpers',
'hub.helpers.peak_calculation',
'hub.helpers.data',
'hub.imports',
'hub.imports.construction',
'hub.imports.construction.helpers',
'hub.imports.energy_systems',
'hub.imports.geometry',
'hub.imports.geometry.citygml_classes',
'hub.imports.geometry.helpers',
'hub.imports.results',
'hub.imports.usage',
'hub.imports.weather',
'hub.imports.weather.helpers',
'hub.persistence',
'hub.persistence.models',
'hub.persistence.repositories',
'hub.imports'
],
setup_requires=install_requires,
install_requires=install_requires,
data_files=[
('hub', glob.glob('requirements.txt')),
('hub/config', glob.glob('hub/config/*.ini')),
('hub/catalog_factories/greenery/ecore_greenery', glob.glob('hub/catalog_factories/greenery/ecore_greenery/*.ecore')),
('hub/data/construction.', glob.glob('hub/data/construction/*')),
('hub/data/customized_imports', glob.glob('hub/data/customized_imports/*.xml')),
('data/geolocation', glob.glob('hub/data/geolocation/*.txt')),
('hub/data/energy_systems', glob.glob('hub/data/energy_systems/*.xml')),
('hub/data/energy_systems', glob.glob('hub/data/energy_systems/*.insel')),
('hub/data/energy_systems', glob.glob('hub/data/energy_systems/*.xlsx')),
('hub/data/energy_systems', glob.glob('hub/data/energy_systems/*.txt')),
('hub/data/energy_systems', glob.glob('hub/data/energy_systems/*.yaml')),
('hub/data/greenery', glob.glob('hub/data/greenery/*.xml')),
('hub/data/life_cycle_assessment', glob.glob('hub/data/life_cycle_assessment/*.xml')),
('hub/data/schedules', glob.glob('hub/data/schedules/*.xml')),
('hub/data/schedules', glob.glob('hub/data/schedules/*.xlsx')),
('hub/data/schedules/idf_files', glob.glob('hub/data/schedules/idf_files/*.idf')),
('hub/data/sensors', glob.glob('hub/data/sensors/*.json')),
('hub/data/usage', glob.glob('hub/data/usage/*.xml')),
('hub/data/usage', glob.glob('hub/data/usage/*.xlsx')),
('hub/data/weather', glob.glob('hub/data/weather/*.dat')),
('hub/data/weather/epw', glob.glob('hub/data/weather/epw/*.epw')),
('hub/data/weather', glob.glob('hub/data/weather/*.dat')),
('hub/exports/building_energy/idf_files', glob.glob('hub/exports/building_energy/idf_files/*.idf')),
('hub/exports/building_energy/idf_files', glob.glob('hub/exports/building_energy/idf_files/*.idd')),
('hub/helpers/data', glob.glob('hub/helpers/data/quebec_to_hub.json'))
],
name='cerc-hub',
version=main_ns['__version__'],
description="CERC Hub consist in a set of classes (Central data model), importers and exporters to help researchers "
"to create better and sustainable cities",
long_description="CERC Hub consist in a set of classes (Central data model), importers and exporters to help "
"researchers to create better and sustainable cities.\n\nDevelop at Concordia university in canada "
"as part of the research group from the next generation cities institute our aim among others it's "
"to provide a comprehensive set of tools to help researchers and urban developers to make decisions "
"to improve the livability and efficiency of our cities",
classifiers=[
"License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
],
include_package_data=True,
packages=['hub',
'hub.catalog_factories',
'hub.catalog_factories.construction',
'hub.catalog_factories.cost',
'hub.catalog_factories.data_models',
'hub.catalog_factories.data_models.construction',
'hub.catalog_factories.data_models.cost',
'hub.catalog_factories.data_models.energy_systems',
'hub.catalog_factories.data_models.greenery',
'hub.catalog_factories.data_models.usages',
'hub.catalog_factories.energy_systems',
'hub.catalog_factories.greenery',
'hub.catalog_factories.greenery.ecore_greenery',
'hub.catalog_factories.usage',
'hub.city_model_structure',
'hub.city_model_structure.attributes',
'hub.city_model_structure.building_demand',
'hub.city_model_structure.energy_systems',
'hub.city_model_structure.greenery',
'hub.city_model_structure.iot',
'hub.city_model_structure.transport',
'hub.config',
'hub.data',
'hub.exports',
'hub.exports.building_energy',
'hub.exports.building_energy.idf_files',
'hub.exports.building_energy.insel',
'hub.exports.energy_systems',
'hub.exports.formats',
'hub.helpers',
'hub.helpers.peak_calculation',
'hub.helpers.data',
'hub.imports',
'hub.imports.construction',
'hub.imports.construction.helpers',
'hub.imports.energy_systems',
'hub.imports.geometry',
'hub.imports.geometry.citygml_classes',
'hub.imports.geometry.helpers',
'hub.imports.results',
'hub.imports.usage',
'hub.imports.weather',
'hub.imports.weather.helpers',
'hub.persistence',
'hub.persistence.models',
'hub.persistence.repositories',
'hub.imports'
],
setup_requires=install_requires,
install_requires=install_requires,
data_files=[
('hub', glob.glob('requirements.txt')),
('hub/config', glob.glob('hub/config/*.ini')),
('hub/catalog_factories/greenery/ecore_greenery', glob.glob('hub/catalog_factories/greenery/ecore_greenery/*.ecore')),
('hub/data/construction.', glob.glob('hub/data/construction/*')),
('hub/data/customized_imports', glob.glob('hub/data/customized_imports/*.xml')),
('data/geolocation', glob.glob('hub/data/geolocation/*.txt')),
('hub/data/energy_systems', glob.glob('hub/data/energy_systems/*.xml')),
('hub/data/energy_systems', glob.glob('hub/data/energy_systems/*.insel')),
('hub/data/energy_systems', glob.glob('hub/data/energy_systems/*.xlsx')),
('hub/data/energy_systems', glob.glob('hub/data/energy_systems/*.txt')),
('hub/data/energy_systems', glob.glob('hub/data/energy_systems/*.yaml')),
('hub/data/greenery', glob.glob('hub/data/greenery/*.xml')),
('hub/data/life_cycle_assessment', glob.glob('hub/data/life_cycle_assessment/*.xml')),
('hub/data/schedules', glob.glob('hub/data/schedules/*.xml')),
('hub/data/schedules', glob.glob('hub/data/schedules/*.xlsx')),
('hub/data/schedules/idf_files', glob.glob('hub/data/schedules/idf_files/*.idf')),
('hub/data/sensors', glob.glob('hub/data/sensors/*.json')),
('hub/data/usage', glob.glob('hub/data/usage/*.xml')),
('hub/data/usage', glob.glob('hub/data/usage/*.xlsx')),
('hub/data/weather', glob.glob('hub/data/weather/*.dat')),
('hub/data/weather/epw', glob.glob('hub/data/weather/epw/*.epw')),
('hub/data/weather', glob.glob('hub/data/weather/*.dat')),
('hub/exports/building_energy/idf_files', glob.glob('hub/exports/building_energy/idf_files/*.idf')),
('hub/exports/building_energy/idf_files', glob.glob('hub/exports/building_energy/idf_files/*.idd')),
('hub/helpers/data', glob.glob('hub/helpers/data/quebec_to_hub.json'))
],
)

View File

@ -72,7 +72,7 @@ class Control:
city_file = "tests_data/FZK_Haus_LoD_2.gml"
weather_file = 'CAN_PQ_Montreal.Intl.AP.716270_CWEC.epw'
output_path = Path('./tests_outputs/').resolve()
output_path = Path('tests_outputs/').resolve()
self._city = GeometryFactory('citygml',
city_file,
function_to_hub=Dictionaries().alkis_function_to_hub_function).city

Some files were not shown because too many files have changed in this diff Show More