diff --git a/hub/catalog_factories/__init__.py b/hub/catalog_factories/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hub/catalog_factories/construction/__init__.py b/hub/catalog_factories/construction/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hub/catalog_factories/cost/__init__.py b/hub/catalog_factories/cost/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hub/catalog_factories/data_models/__init__.py b/hub/catalog_factories/data_models/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hub/catalog_factories/data_models/construction/__init__.py b/hub/catalog_factories/data_models/construction/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hub/catalog_factories/data_models/cost/__init__.py b/hub/catalog_factories/data_models/cost/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hub/catalog_factories/data_models/energy_systems/__init__.py b/hub/catalog_factories/data_models/energy_systems/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hub/catalog_factories/data_models/greenery/__init__.py b/hub/catalog_factories/data_models/greenery/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hub/catalog_factories/data_models/usages/__init__.py b/hub/catalog_factories/data_models/usages/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hub/catalog_factories/energy_systems/__init__.py b/hub/catalog_factories/energy_systems/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hub/catalog_factories/greenery/__init__.py b/hub/catalog_factories/greenery/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hub/catalog_factories/greenery/ecore_greenery/greenerycatalog.py b/hub/catalog_factories/greenery/ecore_greenery/greenerycatalog.py index 30ac116c..9d1551c7 100644 --- a/hub/catalog_factories/greenery/ecore_greenery/greenerycatalog.py +++ b/hub/catalog_factories/greenery/ecore_greenery/greenerycatalog.py @@ -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 diff --git a/hub/catalog_factories/greenery_catalog_factory.py b/hub/catalog_factories/greenery_catalog_factory.py index f9d16d79..467eb1bc 100644 --- a/hub/catalog_factories/greenery_catalog_factory.py +++ b/hub/catalog_factories/greenery_catalog_factory.py @@ -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 diff --git a/hub/catalog_factories/usage/__init__.py b/hub/catalog_factories/usage/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hub/catalog_factories/usage/comnet_catalog.py b/hub/catalog_factories/usage/comnet_catalog.py index df4b4975..27fefb6e 100644 --- a/hub/catalog_factories/usage/comnet_catalog.py +++ b/hub/catalog_factories/usage/comnet_catalog.py @@ -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 diff --git a/hub/catalog_factories/usage/usage_helper.py b/hub/catalog_factories/usage/usage_helper.py index 3aa665df..26677505 100644 --- a/hub/catalog_factories/usage/usage_helper.py +++ b/hub/catalog_factories/usage/usage_helper.py @@ -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') diff --git a/hub/city_model_structure/__init__.py b/hub/city_model_structure/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hub/city_model_structure/attributes/__init__.py b/hub/city_model_structure/attributes/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hub/city_model_structure/attributes/plane.py b/hub/city_model_structure/attributes/plane.py index 8dc0fa77..51cbbf0b 100644 --- a/hub/city_model_structure/attributes/plane.py +++ b/hub/city_model_structure/attributes/plane.py @@ -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): diff --git a/hub/city_model_structure/attributes/point.py b/hub/city_model_structure/attributes/point.py index 3aeb423c..9134bdbd 100644 --- a/hub/city_model_structure/attributes/point.py +++ b/hub/city_model_structure/attributes/point.py @@ -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 diff --git a/hub/city_model_structure/attributes/polygon.py b/hub/city_model_structure/attributes/polygon.py index 7a8e39a5..5a2cf685 100644 --- a/hub/city_model_structure/attributes/polygon.py +++ b/hub/city_model_structure/attributes/polygon.py @@ -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] diff --git a/hub/city_model_structure/attributes/polyhedron.py b/hub/city_model_structure/attributes/polyhedron.py index c88e91d0..a01cd2b6 100644 --- a/hub/city_model_structure/attributes/polyhedron.py +++ b/hub/city_model_structure/attributes/polyhedron.py @@ -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)) diff --git a/hub/city_model_structure/building.py b/hub/city_model_structure/building.py index 5bd1f94c..0959a249 100644 --- a/hub/city_model_structure/building.py +++ b/hub/city_model_structure/building.py @@ -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 diff --git a/hub/city_model_structure/building_demand/__init__.py b/hub/city_model_structure/building_demand/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hub/city_model_structure/building_demand/surface.py b/hub/city_model_structure/building_demand/surface.py index 467ffb7b..3b0113aa 100644 --- a/hub/city_model_structure/building_demand/surface.py +++ b/hub/city_model_structure/building_demand/surface.py @@ -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 diff --git a/hub/city_model_structure/building_demand/thermal_boundary.py b/hub/city_model_structure/building_demand/thermal_boundary.py index eb11a158..f38049ee 100644 --- a/hub/city_model_structure/building_demand/thermal_boundary.py +++ b/hub/city_model_structure/building_demand/thermal_boundary.py @@ -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 diff --git a/hub/city_model_structure/building_demand/thermal_zone.py b/hub/city_model_structure/building_demand/thermal_zone.py index 6deb291a..aad93286 100644 --- a/hub/city_model_structure/building_demand/thermal_zone.py +++ b/hub/city_model_structure/building_demand/thermal_zone.py @@ -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) diff --git a/hub/city_model_structure/city.py b/hub/city_model_structure/city.py index ed996343..3b00624f 100644 --- a/hub/city_model_structure/city.py +++ b/hub/city_model_structure/city.py @@ -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 diff --git a/hub/city_model_structure/city_object.py b/hub/city_model_structure/city_object.py index c8312d9a..2c3a6be0 100644 --- a/hub/city_model_structure/city_object.py +++ b/hub/city_model_structure/city_object.py @@ -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 diff --git a/hub/city_model_structure/energy_systems/__init__.py b/hub/city_model_structure/energy_systems/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hub/city_model_structure/energy_systems/control_system.py b/hub/city_model_structure/energy_systems/control_system.py index 0154a164..a1947511 100644 --- a/hub/city_model_structure/energy_systems/control_system.py +++ b/hub/city_model_structure/energy_systems/control_system.py @@ -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 diff --git a/hub/city_model_structure/energy_systems/generic_emission_system.py b/hub/city_model_structure/energy_systems/generic_emission_system.py index dc85a1ab..afc6b1e0 100644 --- a/hub/city_model_structure/energy_systems/generic_emission_system.py +++ b/hub/city_model_structure/energy_systems/generic_emission_system.py @@ -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 diff --git a/hub/city_model_structure/energy_systems/heat_pump.py b/hub/city_model_structure/energy_systems/heat_pump.py index 120155c5..067147fe 100644 --- a/hub/city_model_structure/energy_systems/heat_pump.py +++ b/hub/city_model_structure/energy_systems/heat_pump.py @@ -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 diff --git a/hub/city_model_structure/energy_systems/hvac_terminal_unit.py b/hub/city_model_structure/energy_systems/hvac_terminal_unit.py index 7583bdc4..6bb22ef7 100644 --- a/hub/city_model_structure/energy_systems/hvac_terminal_unit.py +++ b/hub/city_model_structure/energy_systems/hvac_terminal_unit.py @@ -30,4 +30,3 @@ class HvacTerminalUnit: """ if value is not None: self._type = str(value) - diff --git a/hub/city_model_structure/greenery/__init__.py b/hub/city_model_structure/greenery/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hub/city_model_structure/greenery/plant.py b/hub/city_model_structure/greenery/plant.py index 1d37f4d4..e1510912 100644 --- a/hub/city_model_structure/greenery/plant.py +++ b/hub/city_model_structure/greenery/plant.py @@ -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 diff --git a/hub/city_model_structure/greenery/soil.py b/hub/city_model_structure/greenery/soil.py index b938d0b2..818599c2 100644 --- a/hub/city_model_structure/greenery/soil.py +++ b/hub/city_model_structure/greenery/soil.py @@ -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): diff --git a/hub/city_model_structure/greenery/vegetation.py b/hub/city_model_structure/greenery/vegetation.py index 9f044540..b7d93f0a 100644 --- a/hub/city_model_structure/greenery/vegetation.py +++ b/hub/city_model_structure/greenery/vegetation.py @@ -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 diff --git a/hub/city_model_structure/iot/__init__.py b/hub/city_model_structure/iot/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hub/city_model_structure/iot/sensor_measure.py b/hub/city_model_structure/iot/sensor_measure.py index 12ab5811..cca700ad 100644 --- a/hub/city_model_structure/iot/sensor_measure.py +++ b/hub/city_model_structure/iot/sensor_measure.py @@ -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 diff --git a/hub/city_model_structure/iot/sensor_type.py b/hub/city_model_structure/iot/sensor_type.py index a9477779..8aad2b55 100644 --- a/hub/city_model_structure/iot/sensor_type.py +++ b/hub/city_model_structure/iot/sensor_type.py @@ -9,6 +9,9 @@ from enum import Enum class SensorType(Enum): + """ + Sensor type enumeration + """ HUMIDITY = 0 TEMPERATURE = 1 CO2 = 2 diff --git a/hub/city_model_structure/iot/station.py b/hub/city_model_structure/iot/station.py index 31d3fc10..32a9ee3b 100644 --- a/hub/city_model_structure/iot/station.py +++ b/hub/city_model_structure/iot/station.py @@ -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 diff --git a/hub/city_model_structure/transport/__init__.py b/hub/city_model_structure/transport/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hub/exports/__init__.py b/hub/exports/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hub/exports/building_energy/__init__.py b/hub/exports/building_energy/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hub/exports/building_energy/energy_ade.py b/hub/exports/building_energy/energy_ade.py index 825e1b6e..bd9dc735 100644 --- a/hub/exports/building_energy/energy_ade.py +++ b/hub/exports/building_energy/energy_ade.py @@ -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 diff --git a/hub/exports/building_energy/idf.py b/hub/exports/building_energy/idf.py index a70e5cc7..2b68f241 100644 --- a/hub/exports/building_energy/idf.py +++ b/hub/exports/building_energy/idf.py @@ -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 diff --git a/hub/exports/building_energy/insel/__init__.py b/hub/exports/building_energy/insel/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hub/exports/building_energy/insel/insel_monthly_energy_balance.py b/hub/exports/building_energy/insel/insel_monthly_energy_balance.py index db7c4fdf..4774dbf3 100644 --- a/hub/exports/building_energy/insel/insel_monthly_energy_balance.py +++ b/hub/exports/building_energy/insel/insel_monthly_energy_balance.py @@ -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): diff --git a/hub/exports/energy_building_exports_factory.py b/hub/exports/energy_building_exports_factory.py index 57aa10c1..517e6a52 100644 --- a/hub/exports/energy_building_exports_factory.py +++ b/hub/exports/energy_building_exports_factory.py @@ -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 diff --git a/hub/exports/energy_systems_factory.py b/hub/exports/energy_systems_factory.py index 0c6dd8a5..7e708e89 100644 --- a/hub/exports/energy_systems_factory.py +++ b/hub/exports/energy_systems_factory.py @@ -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'): diff --git a/hub/exports/exports_factory.py b/hub/exports/exports_factory.py index 719aeb3d..a4b073a3 100644 --- a/hub/exports/exports_factory.py +++ b/hub/exports/exports_factory.py @@ -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) \ No newline at end of file + return getattr(self, self._handler, lambda: None) diff --git a/hub/exports/formats/__init__.py b/hub/exports/formats/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hub/helpers/__init__.py b/hub/helpers/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hub/helpers/data/__init__.py b/hub/helpers/data/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hub/imports/construction/__init__.py b/hub/imports/construction/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hub/imports/construction/helpers/__init__.py b/hub/imports/construction/helpers/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hub/imports/construction/helpers/construction_helper.py b/hub/imports/construction/helpers/construction_helper.py index 21ecaf0d..d33f6c39 100644 --- a/hub/imports/construction/helpers/construction_helper.py +++ b/hub/imports/construction/helpers/construction_helper.py @@ -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] diff --git a/hub/imports/construction/helpers/storeys_generation.py b/hub/imports/construction/helpers/storeys_generation.py index d460f395..375516ac 100644 --- a/hub/imports/construction/helpers/storeys_generation.py +++ b/hub/imports/construction/helpers/storeys_generation.py @@ -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: diff --git a/hub/imports/construction_factory.py b/hub/imports/construction_factory.py index 0bb49bd6..81d10b76 100644 --- a/hub/imports/construction_factory.py +++ b/hub/imports/construction_factory.py @@ -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)() \ No newline at end of file + getattr(self, self._handler, lambda: None)() diff --git a/hub/imports/energy_systems/__init__.py b/hub/imports/energy_systems/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hub/imports/energy_systems/air_source_hp_parameters.py b/hub/imports/energy_systems/air_source_hp_parameters.py index 1c0c3547..829575d6 100644 --- a/hub/imports/energy_systems/air_source_hp_parameters.py +++ b/hub/imports/energy_systems/air_source_hp_parameters.py @@ -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 diff --git a/hub/imports/energy_systems/montreal_custom_energy_system_parameters.py b/hub/imports/energy_systems/montreal_custom_energy_system_parameters.py index ca067271..bba0aab5 100644 --- a/hub/imports/energy_systems/montreal_custom_energy_system_parameters.py +++ b/hub/imports/energy_systems/montreal_custom_energy_system_parameters.py @@ -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 diff --git a/hub/imports/energy_systems/water_to_water_hp_parameters.py b/hub/imports/energy_systems/water_to_water_hp_parameters.py index 66f6d29a..1a52fcbb 100644 --- a/hub/imports/energy_systems/water_to_water_hp_parameters.py +++ b/hub/imports/energy_systems/water_to_water_hp_parameters.py @@ -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] diff --git a/hub/imports/geometry/__init__.py b/hub/imports/geometry/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hub/imports/geometry/citygml.py b/hub/imports/geometry/citygml.py index bb84178d..ab36522f 100644 --- a/hub/imports/geometry/citygml.py +++ b/hub/imports/geometry/citygml.py @@ -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 diff --git a/hub/imports/geometry/citygml_classes/__init__.py b/hub/imports/geometry/citygml_classes/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hub/imports/geometry/citygml_classes/citygml_lod2.py b/hub/imports/geometry/citygml_classes/citygml_lod2.py index 1c4f6839..3705f99a 100644 --- a/hub/imports/geometry/citygml_classes/citygml_lod2.py +++ b/hub/imports/geometry/citygml_classes/citygml_lod2.py @@ -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): diff --git a/hub/imports/geometry/geojson.py b/hub/imports/geometry/geojson.py index acefc085..10bd0e72 100644 --- a/hub/imports/geometry/geojson.py +++ b/hub/imports/geometry/geojson.py @@ -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 diff --git a/hub/imports/geometry/gpandas.py b/hub/imports/geometry/gpandas.py index 3ae71eca..b13a648c 100644 --- a/hub/imports/geometry/gpandas.py +++ b/hub/imports/geometry/gpandas.py @@ -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]) diff --git a/hub/imports/geometry/helpers/__init__.py b/hub/imports/geometry/helpers/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hub/imports/geometry/helpers/geometry_helper.py b/hub/imports/geometry/helpers/geometry_helper.py index 717287fc..099fe9f7 100644 --- a/hub/imports/geometry/helpers/geometry_helper.py +++ b/hub/imports/geometry/helpers/geometry_helper.py @@ -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 diff --git a/hub/imports/geometry/obj.py b/hub/imports/geometry/obj.py index e8fc5298..efcecf34 100644 --- a/hub/imports/geometry/obj.py +++ b/hub/imports/geometry/obj.py @@ -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]) diff --git a/hub/imports/geometry/rhino.py b/hub/imports/geometry/rhino.py index 2c490886..b1f36138 100644 --- a/hub/imports/geometry/rhino.py +++ b/hub/imports/geometry/rhino.py @@ -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 = [] diff --git a/hub/imports/geometry_factory.py b/hub/imports/geometry_factory.py index 0d9bd42f..d276c539 100644 --- a/hub/imports/geometry_factory.py +++ b/hub/imports/geometry_factory.py @@ -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) \ No newline at end of file + 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 diff --git a/hub/imports/results/__init__.py b/hub/imports/results/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hub/imports/results/insel_heatpump_energy_demand.py b/hub/imports/results/insel_heatpump_energy_demand.py index 98cb439f..54556d70 100644 --- a/hub/imports/results/insel_heatpump_energy_demand.py +++ b/hub/imports/results/insel_heatpump_energy_demand.py @@ -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 - diff --git a/hub/imports/results/insel_monthly_energry_balance.py b/hub/imports/results/insel_monthly_energry_balance.py index 9ae6bb55..3446a44c 100644 --- a/hub/imports/results/insel_monthly_energry_balance.py +++ b/hub/imports/results/insel_monthly_energry_balance.py @@ -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() diff --git a/hub/imports/results/simplified_radiosity_algorithm.py b/hub/imports/results/simplified_radiosity_algorithm.py index 48682737..c5c77bf7 100644 --- a/hub/imports/results/simplified_radiosity_algorithm.py +++ b/hub/imports/results/simplified_radiosity_algorithm.py @@ -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) -> []: diff --git a/hub/imports/usage/__init__.py b/hub/imports/usage/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hub/imports/usage/comnet_usage_parameters.py b/hub/imports/usage/comnet_usage_parameters.py index 3921a896..71649e09 100644 --- a/hub/imports/usage/comnet_usage_parameters.py +++ b/hub/imports/usage/comnet_usage_parameters.py @@ -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) diff --git a/hub/imports/usage/nrcan_usage_parameters.py b/hub/imports/usage/nrcan_usage_parameters.py index b692eb13..afc24181 100644 --- a/hub/imports/usage/nrcan_usage_parameters.py +++ b/hub/imports/usage/nrcan_usage_parameters.py @@ -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 diff --git a/hub/imports/weather/__init__.py b/hub/imports/weather/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hub/imports/weather/epw_weather_parameters.py b/hub/imports/weather/epw_weather_parameters.py index fb535af5..7da27fc4 100644 --- a/hub/imports/weather/epw_weather_parameters.py +++ b/hub/imports/weather/epw_weather_parameters.py @@ -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: diff --git a/hub/imports/weather/helpers/__init__.py b/hub/imports/weather/helpers/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hub/imports/weather/helpers/weather.py b/hub/imports/weather/helpers/weather.py index 48bd13bc..cdeee232 100644 --- a/hub/imports/weather/helpers/weather.py +++ b/hub/imports/weather/helpers/weather.py @@ -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: diff --git a/hub/persistence/__init__.py b/hub/persistence/__init__.py index c209c0cc..e69de29b 100644 --- a/hub/persistence/__init__.py +++ b/hub/persistence/__init__.py @@ -1,3 +0,0 @@ -""" -Persistence package -""" \ No newline at end of file diff --git a/setup.py b/setup.py index 302f3b94..75c316cc 100644 --- a/setup.py +++ b/setup.py @@ -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')) + ], ) diff --git a/hub/unittests/test_city_merge.py b/tests/test_city_merge.py similarity index 100% rename from hub/unittests/test_city_merge.py rename to tests/test_city_merge.py diff --git a/hub/unittests/test_construction_catalog.py b/tests/test_construction_catalog.py similarity index 100% rename from hub/unittests/test_construction_catalog.py rename to tests/test_construction_catalog.py diff --git a/hub/unittests/test_construction_factory.py b/tests/test_construction_factory.py similarity index 100% rename from hub/unittests/test_construction_factory.py rename to tests/test_construction_factory.py diff --git a/hub/unittests/test_costs_catalog.py b/tests/test_costs_catalog.py similarity index 100% rename from hub/unittests/test_costs_catalog.py rename to tests/test_costs_catalog.py diff --git a/hub/unittests/test_db_factory.py b/tests/test_db_factory.py similarity index 99% rename from hub/unittests/test_db_factory.py rename to tests/test_db_factory.py index 2337ea73..424f786f 100644 --- a/hub/unittests/test_db_factory.py +++ b/tests/test_db_factory.py @@ -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 diff --git a/hub/unittests/test_energy_systems_air_source_hp.py b/tests/test_energy_systems_air_source_hp.py similarity index 100% rename from hub/unittests/test_energy_systems_air_source_hp.py rename to tests/test_energy_systems_air_source_hp.py diff --git a/hub/unittests/test_energy_systems_water_to_water_hp.py b/tests/test_energy_systems_water_to_water_hp.py similarity index 100% rename from hub/unittests/test_energy_systems_water_to_water_hp.py rename to tests/test_energy_systems_water_to_water_hp.py diff --git a/hub/unittests/test_enrichement.py b/tests/test_enrichement.py similarity index 100% rename from hub/unittests/test_enrichement.py rename to tests/test_enrichement.py diff --git a/hub/unittests/test_exports.py b/tests/test_exports.py similarity index 100% rename from hub/unittests/test_exports.py rename to tests/test_exports.py diff --git a/hub/unittests/test_geometry_factory.py b/tests/test_geometry_factory.py similarity index 100% rename from hub/unittests/test_geometry_factory.py rename to tests/test_geometry_factory.py diff --git a/hub/unittests/test_greenery_catalog.py b/tests/test_greenery_catalog.py similarity index 100% rename from hub/unittests/test_greenery_catalog.py rename to tests/test_greenery_catalog.py diff --git a/hub/unittests/test_greenery_in_idf.py b/tests/test_greenery_in_idf.py similarity index 100% rename from hub/unittests/test_greenery_in_idf.py rename to tests/test_greenery_in_idf.py diff --git a/hub/unittests/test_heat_pump_results.py b/tests/test_heat_pump_results.py similarity index 100% rename from hub/unittests/test_heat_pump_results.py rename to tests/test_heat_pump_results.py diff --git a/hub/unittests/test_insel_exports.py b/tests/test_insel_exports.py similarity index 100% rename from hub/unittests/test_insel_exports.py rename to tests/test_insel_exports.py diff --git a/hub/unittests/test_results_import.py b/tests/test_results_import.py similarity index 100% rename from hub/unittests/test_results_import.py rename to tests/test_results_import.py diff --git a/hub/unittests/test_systems_catalog.py b/tests/test_systems_catalog.py similarity index 100% rename from hub/unittests/test_systems_catalog.py rename to tests/test_systems_catalog.py diff --git a/hub/unittests/test_systems_factory.py b/tests/test_systems_factory.py similarity index 100% rename from hub/unittests/test_systems_factory.py rename to tests/test_systems_factory.py diff --git a/hub/unittests/test_usage_catalog.py b/tests/test_usage_catalog.py similarity index 100% rename from hub/unittests/test_usage_catalog.py rename to tests/test_usage_catalog.py diff --git a/hub/unittests/test_usage_factory.py b/tests/test_usage_factory.py similarity index 100% rename from hub/unittests/test_usage_factory.py rename to tests/test_usage_factory.py diff --git a/hub/unittests/tests_data/2000_buildings.geojson b/tests/tests_data/2000_buildings.geojson similarity index 100% rename from hub/unittests/tests_data/2000_buildings.geojson rename to tests/tests_data/2000_buildings.geojson diff --git a/hub/unittests/tests_data/C40_Final.gml b/tests/tests_data/C40_Final.gml similarity index 100% rename from hub/unittests/tests_data/C40_Final.gml rename to tests/tests_data/C40_Final.gml diff --git a/hub/unittests/tests_data/CAN_PQ_Montreal.Intl.AP.716270_CWEC.epw b/tests/tests_data/CAN_PQ_Montreal.Intl.AP.716270_CWEC.epw similarity index 100% rename from hub/unittests/tests_data/CAN_PQ_Montreal.Intl.AP.716270_CWEC.epw rename to tests/tests_data/CAN_PQ_Montreal.Intl.AP.716270_CWEC.epw diff --git a/hub/unittests/tests_data/FZK-Haus-LoD4-KIT-IAI-KHH-B36-V1.gml b/tests/tests_data/FZK-Haus-LoD4-KIT-IAI-KHH-B36-V1.gml similarity index 100% rename from hub/unittests/tests_data/FZK-Haus-LoD4-KIT-IAI-KHH-B36-V1.gml rename to tests/tests_data/FZK-Haus-LoD4-KIT-IAI-KHH-B36-V1.gml diff --git a/hub/unittests/tests_data/FZK_Haus_LoD_2.gml b/tests/tests_data/FZK_Haus_LoD_2.gml similarity index 100% rename from hub/unittests/tests_data/FZK_Haus_LoD_2.gml rename to tests/tests_data/FZK_Haus_LoD_2.gml diff --git a/hub/unittests/tests_data/New_York.cli b/tests/tests_data/New_York.cli similarity index 100% rename from hub/unittests/tests_data/New_York.cli rename to tests/tests_data/New_York.cli diff --git a/hub/unittests/tests_data/concordia.geojson b/tests/tests_data/concordia.geojson similarity index 100% rename from hub/unittests/tests_data/concordia.geojson rename to tests/tests_data/concordia.geojson diff --git a/hub/unittests/tests_data/dompark.3dm b/tests/tests_data/dompark.3dm similarity index 100% rename from hub/unittests/tests_data/dompark.3dm rename to tests/tests_data/dompark.3dm diff --git a/hub/unittests/tests_data/kelowna.obj b/tests/tests_data/kelowna.obj similarity index 100% rename from hub/unittests/tests_data/kelowna.obj rename to tests/tests_data/kelowna.obj diff --git a/hub/unittests/tests_data/neighbours.geojson b/tests/tests_data/neighbours.geojson similarity index 100% rename from hub/unittests/tests_data/neighbours.geojson rename to tests/tests_data/neighbours.geojson diff --git a/hub/unittests/tests_data/one_building_in_kelowna.gml b/tests/tests_data/one_building_in_kelowna.gml similarity index 100% rename from hub/unittests/tests_data/one_building_in_kelowna.gml rename to tests/tests_data/one_building_in_kelowna.gml diff --git a/hub/unittests/tests_data/one_building_in_kelowna_alkis.gml b/tests/tests_data/one_building_in_kelowna_alkis.gml similarity index 100% rename from hub/unittests/tests_data/one_building_in_kelowna_alkis.gml rename to tests/tests_data/one_building_in_kelowna_alkis.gml diff --git a/hub/unittests/tests_data/one_building_in_kelowna_sra_SW.out b/tests/tests_data/one_building_in_kelowna_sra_SW.out similarity index 100% rename from hub/unittests/tests_data/one_building_in_kelowna_sra_SW.out rename to tests/tests_data/one_building_in_kelowna_sra_SW.out diff --git a/hub/unittests/tests_data/pluto_building.gml b/tests/tests_data/pluto_building.gml similarity index 100% rename from hub/unittests/tests_data/pluto_building.gml rename to tests/tests_data/pluto_building.gml diff --git a/hub/unittests/tests_data/w2w_user_output.csv b/tests/tests_data/w2w_user_output.csv similarity index 100% rename from hub/unittests/tests_data/w2w_user_output.csv rename to tests/tests_data/w2w_user_output.csv diff --git a/hub/unittests/tests_outputs/.gitignore b/tests/tests_outputs/.gitignore similarity index 100% rename from hub/unittests/tests_outputs/.gitignore rename to tests/tests_outputs/.gitignore