forked from s_ranjbar/city_retrofit
Saved local changes
This commit is contained in:
commit
f4ce207284
8
hub/.gitignore
vendored
8
hub/.gitignore
vendored
|
@ -1,10 +1,12 @@
|
|||
!.gitignore
|
||||
/venv/
|
||||
**/venv/
|
||||
.idea/
|
||||
/development_tests/
|
||||
/data/energy_systems/heat_pumps/*.csv
|
||||
/data/energy_systems/heat_pumps/*.insel
|
||||
.DS_Store
|
||||
.env
|
||||
hub/logs
|
||||
**/.env
|
||||
**/hub/logs/
|
||||
**/__pycache__/
|
||||
**/.idea/
|
||||
|
||||
|
|
|
@ -1,5 +1,20 @@
|
|||
## Installing PostgreSQL Database Server on Linux (Ubuntu) ##
|
||||
Execute the *install_postgresql_linux.sh* script to install PostgreSQL database
|
||||
|
||||
In the terminal, add the key to the keyring
|
||||
|
||||
`
|
||||
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
|
||||
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
|
||||
`
|
||||
|
||||
Update your repositories with
|
||||
|
||||
`sudo apt-get update`
|
||||
|
||||
Install postgresql
|
||||
|
||||
sudo apt-get install postgresql
|
||||
`
|
||||
*NB: PostgreSQL DB Server runs on a default port of 5432.*
|
||||
|
||||
## Installing PostgreSQL Database Server on Windows ##
|
||||
|
@ -59,7 +74,7 @@ from hub.persistence import DBSetup
|
|||
from pathlib import Path
|
||||
|
||||
dotenv_path = (Path(__file__).parent / '.env').resolve()
|
||||
DBSetup(db_name='hub_db', app_env='PROD', dotenv_path=dotenv_path)
|
||||
DBSetup(db_name='hub_db', app_env='PROD', dotenv_path=dotenv_path, admin_password="your password here", application_uuid="your admin application uuid")
|
||||
```
|
||||
The *DBSetUp* class also creates a default admin user with default credentials that can be changed.
|
||||
with the import UserFactory class. The admin user (name, email, password and role) is logged into the console after it is created by the
|
||||
|
|
46
hub/catalog_factories/construction/construction_helper.py
Normal file
46
hub/catalog_factories/construction/construction_helper.py
Normal file
|
@ -0,0 +1,46 @@
|
|||
from hub.helpers import constants as cte
|
||||
|
||||
|
||||
class ConstructionHelper:
|
||||
"""
|
||||
Construction helper class
|
||||
"""
|
||||
_reference_standard_to_construction_period = {
|
||||
'non_standard_dompark': '1900 - 2004',
|
||||
'ASHRAE 90.1_2004': '2004 - 2009',
|
||||
'ASHRAE 189.1_2009': '2009 - PRESENT'
|
||||
}
|
||||
|
||||
_nrel_surfaces_types_to_hub_types = {
|
||||
'exterior wall': cte.WALL,
|
||||
'interior wall': cte.INTERIOR_WALL,
|
||||
'ground wall': cte.GROUND_WALL,
|
||||
'exterior slab': cte.GROUND,
|
||||
'attic floor': cte.ATTIC_FLOOR,
|
||||
'interior slab': cte.INTERIOR_SLAB,
|
||||
'roof': cte.ROOF
|
||||
}
|
||||
|
||||
_nrcan_surfaces_types_to_hub_types = {
|
||||
'Wall_Outdoors': cte.WALL,
|
||||
'RoofCeiling_Outdoors': cte.ROOF,
|
||||
'Floor_Outdoors': cte.ATTIC_FLOOR,
|
||||
'Window_Outdoors': cte.WINDOW,
|
||||
'Skylight_Outdoors': cte.SKYLIGHT,
|
||||
'Door_Outdoors': cte.DOOR,
|
||||
'Wall_Ground': cte.GROUND_WALL,
|
||||
'RoofCeiling_Ground': cte.GROUND_WALL,
|
||||
'Floor_Ground': cte.GROUND
|
||||
}
|
||||
|
||||
@property
|
||||
def reference_standard_to_construction_period(self):
|
||||
return self._reference_standard_to_construction_period
|
||||
|
||||
@property
|
||||
def nrel_surfaces_types_to_hub_types(self):
|
||||
return self._nrel_surfaces_types_to_hub_types
|
||||
|
||||
@property
|
||||
def nrcan_surfaces_types_to_hub_types(self):
|
||||
return self._nrcan_surfaces_types_to_hub_types
|
|
@ -1,43 +0,0 @@
|
|||
from hub.helpers import constants as cte
|
||||
|
||||
nrel_to_function = {
|
||||
'residential': cte.RESIDENTIAL,
|
||||
'midrise apartment': cte.MID_RISE_APARTMENT,
|
||||
'high-rise apartment': cte.HIGH_RISE_APARTMENT,
|
||||
'small office': cte.SMALL_OFFICE,
|
||||
'medium office': cte.MEDIUM_OFFICE,
|
||||
'large office': cte.LARGE_OFFICE,
|
||||
'primary school': cte.PRIMARY_SCHOOL,
|
||||
'secondary school': cte.SECONDARY_SCHOOL,
|
||||
'stand-alone retail': cte.STAND_ALONE_RETAIL,
|
||||
'hospital': cte.HOSPITAL,
|
||||
'outpatient healthcare': cte.OUT_PATIENT_HEALTH_CARE,
|
||||
'strip mall': cte.STRIP_MALL,
|
||||
'supermarket': cte.SUPERMARKET,
|
||||
'warehouse': cte.WAREHOUSE,
|
||||
'quick service restaurant': cte.QUICK_SERVICE_RESTAURANT,
|
||||
'full service restaurant': cte.FULL_SERVICE_RESTAURANT,
|
||||
'small hotel': cte.SMALL_HOTEL,
|
||||
'large hotel': cte.LARGE_HOTEL,
|
||||
'industry': cte.INDUSTRY
|
||||
}
|
||||
|
||||
nrcan_to_function = {
|
||||
'residential': cte.RESIDENTIAL,
|
||||
}
|
||||
|
||||
reference_standard_to_construction_period = {
|
||||
'non_standard_dompark': '1900 - 2004',
|
||||
'ASHRAE 90.1_2004': '2004 - 2009',
|
||||
'ASHRAE 189.1_2009': '2009 - PRESENT'
|
||||
}
|
||||
|
||||
nrel_surfaces_types_to_hub_types = {
|
||||
'exterior wall': cte.WALL,
|
||||
'interior wall': cte.INTERIOR_WALL,
|
||||
'ground wall': cte.GROUND_WALL,
|
||||
'exterior slab': cte.GROUND,
|
||||
'attic floor': cte.ATTIC_FLOOR,
|
||||
'interior slab': cte.INTERIOR_SLAB,
|
||||
'roof': cte.ROOF
|
||||
}
|
124
hub/catalog_factories/construction/nrcan_catalog.py
Normal file
124
hub/catalog_factories/construction/nrcan_catalog.py
Normal file
|
@ -0,0 +1,124 @@
|
|||
"""
|
||||
NRCAN construction catalog
|
||||
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 json
|
||||
import urllib.request
|
||||
import xmltodict
|
||||
|
||||
from hub.catalog_factories.catalog import Catalog
|
||||
from hub.catalog_factories.data_models.usages.content import Content
|
||||
from hub.catalog_factories.construction.construction_helper import ConstructionHelper
|
||||
from hub.catalog_factories.data_models.construction.construction import Construction
|
||||
from hub.catalog_factories.data_models.construction.archetype import Archetype
|
||||
|
||||
|
||||
class NrcanCatalog(Catalog):
|
||||
def __init__(self, path):
|
||||
path = str(path / 'nrcan.xml')
|
||||
self._content = None
|
||||
self._g_value_per_hdd = []
|
||||
self._thermal_transmittance_per_hdd_and_surface = {}
|
||||
self._window_ratios = {}
|
||||
with open(path) as xml:
|
||||
self._metadata = xmltodict.parse(xml.read())
|
||||
self._base_url_archetypes = self._metadata['nrcan']['@base_url_archetypes']
|
||||
self._base_url_construction = self._metadata['nrcan']['@base_url_construction']
|
||||
self._load_window_ratios()
|
||||
self._load_construction_values()
|
||||
self._content = Content(self._load_archetypes())
|
||||
|
||||
def _load_window_ratios(self):
|
||||
for standard in self._metadata['nrcan']['standards_per_function']['standard']:
|
||||
url = f'{self._base_url_archetypes}{standard["file_location"]}'
|
||||
# todo: read from file
|
||||
self._window_ratios = {'Mean': 0.2, 'North': 0.2, 'East': 0.2, 'South': 0.2, 'West': 0.2}
|
||||
|
||||
def _load_construction_values(self):
|
||||
for standard in self._metadata['nrcan']['standards_per_period']['standard']:
|
||||
g_value_url = f'{self._base_url_construction}{standard["g_value_location"]}'
|
||||
punc = '()<?:'
|
||||
with urllib.request.urlopen(g_value_url) as json_file:
|
||||
text = json.load(json_file)['tables']['SHGC']['table'][0]['formula']
|
||||
values = ''.join([o for o in list(text) if o not in punc]).split()
|
||||
for index in range(int((len(values) - 1)/3)):
|
||||
self._g_value_per_hdd.append([values[3*index+1], values[3*index+2]])
|
||||
self._g_value_per_hdd.append(['15000', values[len(values)-1]])
|
||||
|
||||
construction_url = f'{self._base_url_construction}{standard["constructions_location"]}'
|
||||
with urllib.request.urlopen(construction_url) as json_file:
|
||||
cases = json.load(json_file)['tables']['surface_thermal_transmittance']['table']
|
||||
# W/m2K
|
||||
for case in cases:
|
||||
surface = \
|
||||
ConstructionHelper().nrcan_surfaces_types_to_hub_types[f"{case['surface']}_{case['boundary_condition']}"]
|
||||
thermal_transmittance_per_hdd = []
|
||||
text = case['formula']
|
||||
values = ''.join([o for o in list(text) if o not in punc]).split()
|
||||
for index in range(int((len(values) - 1)/3)):
|
||||
thermal_transmittance_per_hdd.append([values[3*index+1], values[3*index+2]])
|
||||
thermal_transmittance_per_hdd.append(['15000', values[len(values)-1]])
|
||||
self._thermal_transmittance_per_hdd_and_surface[surface] = thermal_transmittance_per_hdd
|
||||
|
||||
def _load_constructions(self, window_ratio_standard, construction_standard):
|
||||
constructions = []
|
||||
# todo: we need to save the total transmittance somehow, we don't do it yet in our archetypes
|
||||
# todo: it has to be selected the specific thermal_transmittance from
|
||||
# self._thermal_transmittance_per_hdd_and_surface and window_ratios from self._window_ratios for each standard case
|
||||
for i, surface_type in enumerate(self._thermal_transmittance_per_hdd_and_surface):
|
||||
constructions.append(Construction(i, surface_type, None, None, self._window_ratios))
|
||||
return constructions
|
||||
|
||||
def _load_archetypes(self):
|
||||
archetypes = []
|
||||
archetype_id = 0
|
||||
for window_ratio_standard in self._metadata['nrcan']['standards_per_function']['standard']:
|
||||
for construction_standard in self._metadata['nrcan']['standards_per_period']['standard']:
|
||||
archetype_id += 1
|
||||
function = window_ratio_standard['@function']
|
||||
climate_zone = 'Montreal'
|
||||
construction_period = construction_standard['@period_of_construction']
|
||||
constructions = self._load_constructions(window_ratio_standard, construction_standard)
|
||||
archetypes.append(Archetype(archetype_id,
|
||||
None,
|
||||
function,
|
||||
climate_zone,
|
||||
construction_period,
|
||||
constructions,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None))
|
||||
return archetypes
|
||||
|
||||
def names(self, category=None):
|
||||
"""
|
||||
Get the catalog elements names
|
||||
:parm: for usage catalog category filter does nothing as there is only one category (usages)
|
||||
"""
|
||||
_names = {'usages': []}
|
||||
for usage in self._content.usages:
|
||||
_names['usages'].append(usage.name)
|
||||
return _names
|
||||
|
||||
def entries(self, category=None):
|
||||
"""
|
||||
Get the catalog elements
|
||||
:parm: for usage catalog category filter does nothing as there is only one category (usages)
|
||||
"""
|
||||
return self._content
|
||||
|
||||
def get_entry(self, name):
|
||||
"""
|
||||
Get one catalog element by names
|
||||
:parm: entry name
|
||||
"""
|
||||
for usage in self._content.usages:
|
||||
if usage.name.lower() == name.lower():
|
||||
return usage
|
||||
raise IndexError(f"{name} doesn't exists in the catalog")
|
|
@ -14,9 +14,7 @@ from hub.catalog_factories.data_models.construction.layer import Layer
|
|||
from hub.catalog_factories.data_models.construction.construction import Construction
|
||||
from hub.catalog_factories.data_models.construction.content import Content
|
||||
from hub.catalog_factories.data_models.construction.archetype import Archetype
|
||||
from hub.catalog_factories.construction.construction_helpers import nrel_to_function
|
||||
from hub.catalog_factories.construction.construction_helpers import reference_standard_to_construction_period
|
||||
from hub.catalog_factories.construction.construction_helpers import nrel_surfaces_types_to_hub_types
|
||||
from hub.catalog_factories.construction.construction_helper import ConstructionHelper
|
||||
|
||||
|
||||
class NrelCatalog(Catalog):
|
||||
|
@ -89,7 +87,7 @@ class NrelCatalog(Catalog):
|
|||
constructions = self._constructions['library']['constructions']['construction']
|
||||
for construction in constructions:
|
||||
construction_id = construction['@id']
|
||||
construction_type = nrel_surfaces_types_to_hub_types[construction['@type']]
|
||||
construction_type = ConstructionHelper().nrel_surfaces_types_to_hub_types[construction['@type']]
|
||||
name = construction['@name']
|
||||
layers = []
|
||||
for layer in construction['layers']['layer']:
|
||||
|
@ -111,10 +109,11 @@ class NrelCatalog(Catalog):
|
|||
archetypes = self._archetypes['archetypes']['archetype']
|
||||
for archetype in archetypes:
|
||||
archetype_id = archetype['@id']
|
||||
function = nrel_to_function[archetype['@building_type']]
|
||||
function = archetype['@building_type']
|
||||
name = f"{function} {archetype['@climate_zone']} {archetype['@reference_standard']}"
|
||||
climate_zone = archetype['@climate_zone']
|
||||
construction_period = reference_standard_to_construction_period[archetype['@reference_standard']]
|
||||
construction_period = \
|
||||
ConstructionHelper().reference_standard_to_construction_period[archetype['@reference_standard']]
|
||||
average_storey_height = archetype['average_storey_height']['#text']
|
||||
thermal_capacity = str(float(archetype['thermal_capacity']['#text']) * 1000)
|
||||
extra_loses_due_to_thermal_bridges = archetype['extra_loses_due_to_thermal_bridges']['#text']
|
||||
|
|
|
@ -8,6 +8,9 @@ Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
|||
from pathlib import Path
|
||||
from typing import TypeVar
|
||||
from hub.catalog_factories.construction.nrel_catalog import NrelCatalog
|
||||
from hub.hub_logger import logger
|
||||
from hub.helpers.utils import validate_import_export_type
|
||||
from hub.catalog_factories.construction.nrcan_catalog import NrcanCatalog
|
||||
Catalog = TypeVar('Catalog')
|
||||
|
||||
|
||||
|
@ -16,6 +19,11 @@ class ConstructionCatalogFactory:
|
|||
if base_path is None:
|
||||
base_path = Path(Path(__file__).parent.parent / 'data/construction')
|
||||
self._catalog_type = '_' + file_type.lower()
|
||||
class_funcs = validate_import_export_type(ConstructionCatalogFactory)
|
||||
if self._catalog_type not in class_funcs:
|
||||
err_msg = f"Wrong import type. Valid functions include {class_funcs}"
|
||||
logger.error(err_msg)
|
||||
raise Exception(err_msg)
|
||||
self._path = base_path
|
||||
|
||||
@property
|
||||
|
@ -25,6 +33,13 @@ class ConstructionCatalogFactory:
|
|||
"""
|
||||
return NrelCatalog(self._path)
|
||||
|
||||
@property
|
||||
def _nrcan(self):
|
||||
"""
|
||||
Retrieve NREL catalog
|
||||
"""
|
||||
return NrcanCatalog(self._path)
|
||||
|
||||
@property
|
||||
def catalog(self) -> Catalog:
|
||||
"""
|
||||
|
|
170
hub/catalog_factories/cost/montreal_custom_catalog.py
Normal file
170
hub/catalog_factories/cost/montreal_custom_catalog.py
Normal file
|
@ -0,0 +1,170 @@
|
|||
"""
|
||||
Cost catalog
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Atiya atiya.atiya@mail.concordia.ca
|
||||
Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
|
||||
import xmltodict
|
||||
from hub.catalog_factories.catalog import Catalog
|
||||
from hub.catalog_factories.data_models.cost.capital_cost import CapitalCost
|
||||
from hub.catalog_factories.data_models.cost.envelope import Envelope
|
||||
from hub.catalog_factories.data_models.cost.systems import Systems
|
||||
from hub.catalog_factories.data_models.cost.hvac import Hvac
|
||||
from hub.catalog_factories.data_models.cost.operational_cost import OperationalCost
|
||||
from hub.catalog_factories.data_models.cost.income import Income
|
||||
from hub.catalog_factories.data_models.cost.archetype import Archetype
|
||||
from hub.catalog_factories.data_models.cost.content import Content
|
||||
|
||||
|
||||
class MontrealCustomCatalog(Catalog):
|
||||
def __init__(self, path):
|
||||
path = str(path / 'montreal_costs.xml')
|
||||
with open(path) as xml:
|
||||
self._archetypes = xmltodict.parse(xml.read(), force_list='archetype')
|
||||
|
||||
# store the full catalog data model in self._content
|
||||
self._content = Content(self._load_archetypes())
|
||||
|
||||
@staticmethod
|
||||
def _get_threesome(entry):
|
||||
_reposition = float(entry['reposition']['#text'])
|
||||
_investment = float(entry['initial_investment']['#text'])
|
||||
_lifetime = float(entry['lifetime_equipment']['#text'])
|
||||
return _reposition, _investment, _lifetime
|
||||
|
||||
def _get_capital_costs(self, entry):
|
||||
structural = float(entry['structural']['#text'])
|
||||
sub_structural = float(entry['sub_structural']['#text'])
|
||||
surface_finish = float(entry['surface_finish']['#text'])
|
||||
engineer = float(entry['engineer']['#text'])
|
||||
opaque_reposition, opaque_initial_investment, opaque_lifetime = \
|
||||
self._get_threesome(entry['envelope']['opaque'])
|
||||
transparent_reposition, transparent_initial_investment, transparent_lifetime = \
|
||||
self._get_threesome(entry['envelope']['transparent'])
|
||||
envelope = Envelope(opaque_reposition,
|
||||
opaque_initial_investment,
|
||||
opaque_lifetime,
|
||||
transparent_reposition,
|
||||
transparent_initial_investment,
|
||||
transparent_lifetime)
|
||||
heating_equipment_reposition, heating_equipment_initial_investment, heating_equipment_lifetime = \
|
||||
self._get_threesome(entry['systems']['hvac']['heating_equipment_cost'])
|
||||
heating_equipment_reposition = heating_equipment_reposition / 1000
|
||||
heating_equipment_initial_investment = heating_equipment_initial_investment / 1000
|
||||
cooling_equipment_reposition, cooling_equipment_initial_investment, cooling_equipment_lifetime = \
|
||||
self._get_threesome(entry['systems']['hvac']['cooling_equipment_cost'])
|
||||
cooling_equipment_reposition = cooling_equipment_reposition / 1000
|
||||
cooling_equipment_initial_investment = cooling_equipment_initial_investment / 1000
|
||||
general_hvac_equipment_reposition, general_hvac_equipment_initial_investment, general_hvac_equipment_lifetime = \
|
||||
self._get_threesome(entry['systems']['hvac']['general_hvac_equipment_cost'])
|
||||
general_hvac_equipment_reposition = general_hvac_equipment_reposition * 3600
|
||||
general_hvac_equipment_initial_investment = general_hvac_equipment_initial_investment * 3600
|
||||
hvac = Hvac(heating_equipment_reposition, heating_equipment_initial_investment, heating_equipment_lifetime,
|
||||
cooling_equipment_reposition, cooling_equipment_initial_investment, cooling_equipment_lifetime,
|
||||
general_hvac_equipment_reposition, general_hvac_equipment_initial_investment,
|
||||
general_hvac_equipment_lifetime)
|
||||
|
||||
photovoltaic_system_reposition, photovoltaic_system_initial_investment, photovoltaic_system_lifetime = \
|
||||
self._get_threesome(entry['systems']['photovoltaic_system'])
|
||||
other_conditioning_systems_reposition, other_conditioning_systems_initial_investment, \
|
||||
other_conditioning_systems_lifetime = self._get_threesome(entry['systems']['other_systems'])
|
||||
lighting_reposition, lighting_initial_investment, lighting_lifetime = \
|
||||
self._get_threesome(entry['systems']['lighting'])
|
||||
systems = Systems(hvac,
|
||||
photovoltaic_system_reposition,
|
||||
photovoltaic_system_initial_investment,
|
||||
photovoltaic_system_lifetime,
|
||||
other_conditioning_systems_reposition,
|
||||
other_conditioning_systems_initial_investment,
|
||||
other_conditioning_systems_lifetime,
|
||||
lighting_reposition,
|
||||
lighting_initial_investment,
|
||||
lighting_lifetime)
|
||||
_capital_cost = CapitalCost(structural,
|
||||
sub_structural,
|
||||
envelope,
|
||||
systems,
|
||||
surface_finish,
|
||||
engineer)
|
||||
|
||||
return _capital_cost
|
||||
|
||||
@staticmethod
|
||||
def _get_operational_costs(entry):
|
||||
fuel_type = entry['fuel']['@fuel_type']
|
||||
fuel_fixed_operational_monthly = float(entry['fuel']['fixed']['fixed_monthly']['#text'])
|
||||
fuel_fixed_operational_peak = float(entry['fuel']['fixed']['fixed_power']['#text']) / 1000
|
||||
fuel_variable_operational = float(entry['fuel']['variable']['#text']) / 1000 / 3600
|
||||
heating_equipment_maintenance = float(entry['maintenance']['heating_equipment']['#text']) / 1000
|
||||
cooling_equipment_maintenance = float(entry['maintenance']['cooling_equipment']['#text']) / 1000
|
||||
general_hvac_equipment_maintenance = float(entry['maintenance']['general_hvac_equipment']['#text']) * 3600
|
||||
photovoltaic_system_maintenance = float(entry['maintenance']['photovoltaic_system']['#text'])
|
||||
other_systems_maintenance = float(entry['maintenance']['other_systems']['#text'])
|
||||
co2_emissions = float(entry['CO2_cost']['#text'])
|
||||
_operational_cost = OperationalCost(fuel_type,
|
||||
fuel_fixed_operational_monthly,
|
||||
fuel_fixed_operational_peak,
|
||||
fuel_variable_operational,
|
||||
heating_equipment_maintenance,
|
||||
cooling_equipment_maintenance,
|
||||
general_hvac_equipment_maintenance,
|
||||
photovoltaic_system_maintenance,
|
||||
other_systems_maintenance,
|
||||
co2_emissions)
|
||||
return _operational_cost
|
||||
|
||||
def _load_archetypes(self):
|
||||
_catalog_archetypes = []
|
||||
archetypes = self._archetypes['archetypes']['archetype']
|
||||
for archetype in archetypes:
|
||||
function = archetype['@function']
|
||||
municipality = archetype['@municipality']
|
||||
currency = archetype['@currency']
|
||||
capital_cost = self._get_capital_costs(archetype['capital_cost'])
|
||||
operational_cost = self._get_operational_costs(archetype['operational_cost'])
|
||||
end_of_life_cost = float(archetype['end_of_life_cost']['#text'])
|
||||
construction = float(archetype['incomes']['subsidies']['construction_subsidy']['#text'])
|
||||
hvac = float(archetype['incomes']['subsidies']['hvac_subsidy']['#text'])
|
||||
photovoltaic_system = float(archetype['incomes']['subsidies']['photovoltaic_subsidy']['#text'])
|
||||
electricity_exports = float(archetype['incomes']['energy_exports']['electricity']['#text']) / 1000 / 3600
|
||||
heat_exports = float(archetype['incomes']['energy_exports']['heat']['#text']) / 1000 / 3600
|
||||
co2 = float(archetype['incomes']['CO2_income']['#text'])
|
||||
income = Income(construction, hvac, photovoltaic_system, electricity_exports, heat_exports, co2)
|
||||
_catalog_archetypes.append(Archetype(function,
|
||||
municipality,
|
||||
currency,
|
||||
capital_cost,
|
||||
operational_cost,
|
||||
end_of_life_cost,
|
||||
income))
|
||||
|
||||
return _catalog_archetypes
|
||||
|
||||
def names(self, category=None):
|
||||
"""
|
||||
Get the catalog elements names
|
||||
:parm: for costs catalog category filter does nothing as there is only one category (archetypes)
|
||||
"""
|
||||
_names = {'archetypes': []}
|
||||
for archetype in self._content.archetypes:
|
||||
_names['archetypes'].append(archetype.name)
|
||||
return _names
|
||||
|
||||
def entries(self, category=None):
|
||||
"""
|
||||
Get the catalog elements
|
||||
:parm: for costs catalog category filter does nothing as there is only one category (archetypes)
|
||||
"""
|
||||
return self._content
|
||||
|
||||
def get_entry(self, name):
|
||||
"""
|
||||
Get one catalog element by names
|
||||
:parm: entry name
|
||||
"""
|
||||
for entry in self._content.archetypes:
|
||||
if entry.name.lower() == name.lower():
|
||||
return entry
|
||||
raise IndexError(f"{name} doesn't exists in the catalog")
|
39
hub/catalog_factories/costs_catalog_factory.py
Normal file
39
hub/catalog_factories/costs_catalog_factory.py
Normal file
|
@ -0,0 +1,39 @@
|
|||
"""
|
||||
Cost catalog publish the life cycle cost
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Atiya atiya.atiya@mail.concordia.ca
|
||||
Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
from typing import TypeVar
|
||||
from hub.catalog_factories.cost.montreal_custom_catalog import MontrealCustomCatalog
|
||||
|
||||
Catalog = TypeVar('Catalog')
|
||||
|
||||
|
||||
class CostCatalogFactory:
|
||||
"""
|
||||
CostsCatalogFactory class
|
||||
"""
|
||||
def __init__(self, file_type, base_path=None):
|
||||
if base_path is None:
|
||||
base_path = Path(Path(__file__).parent.parent / 'data/costs')
|
||||
self._catalog_type = '_' + file_type.lower()
|
||||
self._path = base_path
|
||||
|
||||
@property
|
||||
def _montreal_custom(self):
|
||||
"""
|
||||
Retrieve Montreal Custom catalog
|
||||
"""
|
||||
return MontrealCustomCatalog(self._path)
|
||||
|
||||
@property
|
||||
def catalog(self) -> Catalog:
|
||||
"""
|
||||
Return a cost catalog
|
||||
:return: CostCatalog
|
||||
"""
|
||||
return getattr(self, self._catalog_type, lambda: None)
|
|
@ -16,7 +16,7 @@ class Content:
|
|||
@property
|
||||
def archetypes(self):
|
||||
"""
|
||||
All archetypes in the catalogUsageZone
|
||||
All archetypes in the catalog
|
||||
"""
|
||||
return self._archetypes
|
||||
|
||||
|
|
85
hub/catalog_factories/data_models/cost/archetype.py
Normal file
85
hub/catalog_factories/data_models/cost/archetype.py
Normal file
|
@ -0,0 +1,85 @@
|
|||
"""
|
||||
Archetype catalog Cost
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Atiya atiya.atiya@mail.concordia.ca
|
||||
"""
|
||||
|
||||
from hub.catalog_factories.data_models.cost.capital_cost import CapitalCost
|
||||
from hub.catalog_factories.data_models.cost.operational_cost import OperationalCost
|
||||
from hub.catalog_factories.data_models.cost.income import Income
|
||||
|
||||
|
||||
class Archetype:
|
||||
def __init__(self, function, municipality, currency, capital_cost, operational_cost, end_of_life_cost, income):
|
||||
self._function = function
|
||||
self._municipality = municipality
|
||||
self._currency = currency
|
||||
self._capital_cost = capital_cost
|
||||
self._operational_cost = operational_cost
|
||||
self._end_of_life_cost = end_of_life_cost
|
||||
self._income = income
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""
|
||||
Get name
|
||||
:return: string
|
||||
"""
|
||||
return f'{self._municipality}_{self._function}'
|
||||
|
||||
@property
|
||||
def function(self):
|
||||
"""
|
||||
Get function
|
||||
:return: string
|
||||
"""
|
||||
return self._function
|
||||
|
||||
@property
|
||||
def municipality(self):
|
||||
"""
|
||||
Get municipality
|
||||
:return: string
|
||||
"""
|
||||
return self._municipality
|
||||
|
||||
@property
|
||||
def currency(self):
|
||||
"""
|
||||
Get currency
|
||||
:return: string
|
||||
"""
|
||||
return self._currency
|
||||
|
||||
@property
|
||||
def capital_cost(self) -> CapitalCost:
|
||||
"""
|
||||
Get capital cost
|
||||
:return: CapitalCost
|
||||
"""
|
||||
return self._capital_cost
|
||||
|
||||
@property
|
||||
def operational_cost(self) -> OperationalCost:
|
||||
"""
|
||||
Get operational cost
|
||||
:return: OperationalCost
|
||||
"""
|
||||
return self._operational_cost
|
||||
|
||||
@property
|
||||
def end_of_life_cost(self):
|
||||
"""
|
||||
Get end of life cost in given currency
|
||||
:return: float
|
||||
"""
|
||||
return self._end_of_life_cost
|
||||
|
||||
@property
|
||||
def income(self) -> Income:
|
||||
"""
|
||||
Get income
|
||||
:return: Income
|
||||
"""
|
||||
return self._income
|
68
hub/catalog_factories/data_models/cost/capital_cost.py
Normal file
68
hub/catalog_factories/data_models/cost/capital_cost.py
Normal file
|
@ -0,0 +1,68 @@
|
|||
"""
|
||||
Cost catalog CapitalCost
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Atiya atiya.atiya@mail.concordia.ca
|
||||
Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
|
||||
from hub.catalog_factories.data_models.cost.envelope import Envelope
|
||||
from hub.catalog_factories.data_models.cost.systems import Systems
|
||||
|
||||
|
||||
class CapitalCost:
|
||||
def __init__(self, structural, sub_structural, envelope, systems, surface_finish, engineer):
|
||||
self._structural = structural
|
||||
self._sub_structural = sub_structural
|
||||
self._envelope = envelope
|
||||
self._systems = systems
|
||||
self._surface_finish = surface_finish
|
||||
self._engineer = engineer
|
||||
|
||||
@property
|
||||
def structural(self):
|
||||
"""
|
||||
Get structural cost per building volume in currency/m3
|
||||
:return: float
|
||||
"""
|
||||
return self._structural
|
||||
|
||||
@property
|
||||
def sub_structural(self):
|
||||
"""
|
||||
Get sub structural cost per building foot-print in currency/m2
|
||||
:return: float
|
||||
"""
|
||||
return self._sub_structural
|
||||
|
||||
@property
|
||||
def envelope(self) -> Envelope:
|
||||
"""
|
||||
Get envelope cost
|
||||
:return: Envelope
|
||||
"""
|
||||
return self._envelope
|
||||
|
||||
@property
|
||||
def systems(self) -> Systems:
|
||||
"""
|
||||
Get systems cost
|
||||
:return: Systems
|
||||
"""
|
||||
return self._systems
|
||||
|
||||
@property
|
||||
def surface_finish(self):
|
||||
"""
|
||||
Get surface finish cost per external surfaces areas in currency/m2
|
||||
:return: float
|
||||
"""
|
||||
return self._surface_finish
|
||||
|
||||
@property
|
||||
def engineer(self):
|
||||
"""
|
||||
Get engineer cost in %
|
||||
:return: float
|
||||
"""
|
||||
return self._engineer
|
19
hub/catalog_factories/data_models/cost/content.py
Normal file
19
hub/catalog_factories/data_models/cost/content.py
Normal file
|
@ -0,0 +1,19 @@
|
|||
"""
|
||||
Cost catalog content
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Atiya atiya.atiya@mail.concordia.ca
|
||||
Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
|
||||
|
||||
class Content:
|
||||
def __init__(self, archetypes):
|
||||
self._archetypes = archetypes
|
||||
|
||||
@property
|
||||
def archetypes(self):
|
||||
"""
|
||||
All archetypes in the catalog
|
||||
"""
|
||||
return self._archetypes
|
66
hub/catalog_factories/data_models/cost/envelope.py
Normal file
66
hub/catalog_factories/data_models/cost/envelope.py
Normal file
|
@ -0,0 +1,66 @@
|
|||
"""
|
||||
Envelope costs from Cost catalog
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Atiya atiya.atiya@mail.concordia.ca
|
||||
Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
|
||||
|
||||
class Envelope:
|
||||
def __init__(self, opaque_reposition, opaque_initial_investment, opaque_lifetime,
|
||||
transparent_reposition, transparent_initial_investment, transparent_lifetime):
|
||||
self._opaque_reposition = opaque_reposition
|
||||
self._opaque_initial_investment = opaque_initial_investment
|
||||
self._opaque_lifetime = opaque_lifetime
|
||||
self._transparent_reposition = transparent_reposition
|
||||
self._transparent_initial_investment = transparent_initial_investment
|
||||
self._transparent_lifetime = transparent_lifetime
|
||||
|
||||
@property
|
||||
def opaque_reposition(self):
|
||||
"""
|
||||
Get reposition costs for opaque envelope per area of external opaque surfaces in currency/m2
|
||||
:return: float
|
||||
"""
|
||||
return self._opaque_reposition
|
||||
|
||||
@property
|
||||
def opaque_initial_investment(self):
|
||||
"""
|
||||
Get initial investment for opaque envelope per area of external opaque surfaces in currency/m2
|
||||
:return: float
|
||||
"""
|
||||
return self._opaque_initial_investment
|
||||
|
||||
@property
|
||||
def opaque_lifetime(self):
|
||||
"""
|
||||
Get lifetime of opaque envelope in years
|
||||
:return: float
|
||||
"""
|
||||
return self._opaque_lifetime
|
||||
|
||||
@property
|
||||
def transparent_reposition(self):
|
||||
"""
|
||||
Get reposition costs for transparent envelope per area of windows in currency/m2
|
||||
:return: float
|
||||
"""
|
||||
return self._transparent_reposition
|
||||
|
||||
@property
|
||||
def transparent_initial_investment(self):
|
||||
"""
|
||||
Get initial investment for transparent envelope per area of windows in currency/m2
|
||||
:return: float
|
||||
"""
|
||||
return self._transparent_initial_investment
|
||||
|
||||
@property
|
||||
def transparent_lifetime(self):
|
||||
"""
|
||||
Get lifetime of transparent envelope in years
|
||||
:return: float
|
||||
"""
|
||||
return self._transparent_lifetime
|
96
hub/catalog_factories/data_models/cost/hvac.py
Normal file
96
hub/catalog_factories/data_models/cost/hvac.py
Normal file
|
@ -0,0 +1,96 @@
|
|||
"""
|
||||
Hvac costs
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Pilar Monsalvete Álvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
|
||||
|
||||
class Hvac:
|
||||
def __init__(self, heating_equipment_reposition, heating_equipment_initial_investment,
|
||||
heating_equipment_lifetime, cooling_equipment_reposition,
|
||||
cooling_equipment_initial_investment, cooling_equipment_lifetime,
|
||||
general_hvac_equipment_reposition, general_hvac_equipment_initial_investment,
|
||||
general_hvac_equipment_lifetime):
|
||||
|
||||
self._heating_equipment_reposition = heating_equipment_reposition
|
||||
self._heating_equipment_initial_investment = heating_equipment_initial_investment
|
||||
self._heating_equipment_lifetime = heating_equipment_lifetime
|
||||
self._cooling_equipment_reposition = cooling_equipment_reposition
|
||||
self._cooling_equipment_initial_investment = cooling_equipment_initial_investment
|
||||
self._cooling_equipment_lifetime = cooling_equipment_lifetime
|
||||
self._general_hvac_equipment_reposition = general_hvac_equipment_reposition
|
||||
self._general_hvac_equipment_initial_investment = general_hvac_equipment_initial_investment
|
||||
self._general_hvac_equipment_lifetime = general_hvac_equipment_lifetime
|
||||
|
||||
@property
|
||||
def heating_equipment_reposition(self):
|
||||
"""
|
||||
Get reposition costs of heating equipment per peak-load in currency/W
|
||||
:return: float
|
||||
"""
|
||||
return self._heating_equipment_reposition
|
||||
|
||||
@property
|
||||
def heating_equipment_initial_investment(self):
|
||||
"""
|
||||
Get initial investment costs of heating equipment per peak-load in currency/W
|
||||
:return: float
|
||||
"""
|
||||
return self._heating_equipment_initial_investment
|
||||
|
||||
@property
|
||||
def heating_equipment_lifetime(self):
|
||||
"""
|
||||
Get lifetime of heating equipment in years
|
||||
:return: float
|
||||
"""
|
||||
return self._heating_equipment_lifetime
|
||||
|
||||
@property
|
||||
def cooling_equipment_reposition(self):
|
||||
"""
|
||||
Get reposition costs of cooling equipment per peak-load in currency/W
|
||||
:return: float
|
||||
"""
|
||||
return self._cooling_equipment_reposition
|
||||
|
||||
@property
|
||||
def cooling_equipment_initial_investment(self):
|
||||
"""
|
||||
Get initial investment costs of cooling equipment per peak-load in currency/W
|
||||
:return: float
|
||||
"""
|
||||
return self._cooling_equipment_initial_investment
|
||||
|
||||
@property
|
||||
def cooling_equipment_lifetime(self):
|
||||
"""
|
||||
Get lifetime of cooling equipment in years
|
||||
:return: float
|
||||
"""
|
||||
return self._cooling_equipment_lifetime
|
||||
|
||||
@property
|
||||
def general_hvac_equipment_reposition(self):
|
||||
"""
|
||||
Get reposition costs of general hvac equipment per peak-air-flow in currency/(m3/s)
|
||||
:return: float
|
||||
"""
|
||||
return self._general_hvac_equipment_reposition
|
||||
|
||||
@property
|
||||
def general_hvac_equipment_initial_investment(self):
|
||||
"""
|
||||
Get initial investment costs of cooling equipment per peak-air-flow in currency/(m3/s)
|
||||
:return: float
|
||||
"""
|
||||
return self._general_hvac_equipment_initial_investment
|
||||
|
||||
@property
|
||||
def general_hvac_equipment_lifetime(self):
|
||||
"""
|
||||
Get lifetime of cooling equipment in years
|
||||
:return: float
|
||||
"""
|
||||
return self._general_hvac_equipment_lifetime
|
64
hub/catalog_factories/data_models/cost/income.py
Normal file
64
hub/catalog_factories/data_models/cost/income.py
Normal file
|
@ -0,0 +1,64 @@
|
|||
"""
|
||||
Income from costs catalog
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Pilar Monsalvete Álvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
|
||||
|
||||
class Income:
|
||||
def __init__(self, construction, hvac, photovoltaic_system, electricity_exports, heat_exports, co2):
|
||||
self._construction = construction
|
||||
self._hvac = hvac
|
||||
self._photovoltaic_system = photovoltaic_system
|
||||
self._electricity_exports = electricity_exports
|
||||
self._heat_exports = heat_exports
|
||||
self._co2 = co2
|
||||
|
||||
@property
|
||||
def construction(self):
|
||||
"""
|
||||
Get construction subsidy in % of total investment construction cost
|
||||
:return: float
|
||||
"""
|
||||
return self._construction
|
||||
|
||||
@property
|
||||
def hvac(self):
|
||||
"""
|
||||
Get hvac subsidy in % of total investment HVAC cost
|
||||
:return: float
|
||||
"""
|
||||
return self._hvac
|
||||
|
||||
@property
|
||||
def photovoltaic_system(self):
|
||||
"""
|
||||
Get photovoltaic system subsidy in % of total investment photovoltaic cost
|
||||
:return: float
|
||||
"""
|
||||
return self._photovoltaic_system
|
||||
|
||||
@property
|
||||
def electricity_exports(self):
|
||||
"""
|
||||
Get electricity exports gains in currency/J
|
||||
:return: float
|
||||
"""
|
||||
return self._construction
|
||||
|
||||
@property
|
||||
def heat_exports(self):
|
||||
"""
|
||||
Get heat exports gains in currency/J
|
||||
:return: float
|
||||
"""
|
||||
return self._heat_exports
|
||||
|
||||
@property
|
||||
def co2(self):
|
||||
"""
|
||||
Get co2 income in currency/kg
|
||||
:return: float
|
||||
"""
|
||||
return self._co2
|
104
hub/catalog_factories/data_models/cost/operational_cost.py
Normal file
104
hub/catalog_factories/data_models/cost/operational_cost.py
Normal file
|
@ -0,0 +1,104 @@
|
|||
"""
|
||||
Cost catalog OperationalCost
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Atiya atiya.atiya@mail.concordia.ca
|
||||
Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
|
||||
|
||||
class OperationalCost:
|
||||
def __init__(self, fuel_type, fuel_fixed_operational_monthly, fuel_fixed_operational_peak,
|
||||
fuel_variable_operational, heating_equipment_maintenance, cooling_equipment_maintenance,
|
||||
general_hvac_equipment_maintenance, photovoltaic_system_maintenance, other_systems_maintenance,
|
||||
co2_emissions):
|
||||
self._fuel_type = fuel_type
|
||||
self._fuel_fixed_operational_monthly = fuel_fixed_operational_monthly
|
||||
self._fuel_fixed_operational_peak = fuel_fixed_operational_peak
|
||||
self._fuel_variable_operational = fuel_variable_operational
|
||||
self._heating_equipment_maintenance = heating_equipment_maintenance
|
||||
self._cooling_equipment_maintenance = cooling_equipment_maintenance
|
||||
self._general_hvac_equipment_maintenance = general_hvac_equipment_maintenance
|
||||
self._photovoltaic_system_maintenance = photovoltaic_system_maintenance
|
||||
self._other_systems_maintenance = other_systems_maintenance
|
||||
self._co2_emissions = co2_emissions
|
||||
|
||||
@property
|
||||
def fuel_type(self):
|
||||
"""
|
||||
Get fuel type
|
||||
:return: string
|
||||
"""
|
||||
return self._fuel_type
|
||||
|
||||
@property
|
||||
def fuel_fixed_operational_monthly(self):
|
||||
"""
|
||||
Get fuel fixed operational cost in currency/month
|
||||
:return: float
|
||||
"""
|
||||
return self._fuel_fixed_operational_monthly
|
||||
|
||||
@property
|
||||
def fuel_fixed_operational_peak(self):
|
||||
"""
|
||||
Get fuel fixed operational cost per peak power in currency/W
|
||||
:return: float
|
||||
"""
|
||||
return self._fuel_fixed_operational_peak
|
||||
|
||||
@property
|
||||
def fuel_variable_operational(self):
|
||||
"""
|
||||
Get fuel variable operational cost in currency/J
|
||||
:return: float
|
||||
"""
|
||||
return self._fuel_variable_operational
|
||||
|
||||
@property
|
||||
def heating_equipment_maintenance(self):
|
||||
"""
|
||||
Get heating equipment maintenance cost per peak power in currency/W
|
||||
:return: float
|
||||
"""
|
||||
return self._heating_equipment_maintenance
|
||||
|
||||
@property
|
||||
def cooling_equipment_maintenance(self):
|
||||
"""
|
||||
Get cooling equipment maintenance cost per peak power in currency/W
|
||||
:return: float
|
||||
"""
|
||||
return self._cooling_equipment_maintenance
|
||||
|
||||
@property
|
||||
def general_hvac_equipment_maintenance(self):
|
||||
"""
|
||||
Get general hvac equipment maintenance cost per peak-air-flow in currency/(m3/s)
|
||||
:return: float
|
||||
"""
|
||||
return self._general_hvac_equipment_maintenance
|
||||
|
||||
@property
|
||||
def photovoltaic_system_maintenance(self):
|
||||
"""
|
||||
Get photovoltaic system maintenance cost per panels area in currency/m2
|
||||
:return: float
|
||||
"""
|
||||
return self._photovoltaic_system_maintenance
|
||||
|
||||
@property
|
||||
def other_systems_maintenance(self):
|
||||
"""
|
||||
Get other systems' maintenance cost per building's foot-print area in currency/m2
|
||||
:return: float
|
||||
"""
|
||||
return self._other_systems_maintenance
|
||||
|
||||
@property
|
||||
def co2_emissions(self):
|
||||
"""
|
||||
Get CO2 emissions cost in currency/kg
|
||||
:return: float
|
||||
"""
|
||||
return self._co2_emissions
|
106
hub/catalog_factories/data_models/cost/systems.py
Normal file
106
hub/catalog_factories/data_models/cost/systems.py
Normal file
|
@ -0,0 +1,106 @@
|
|||
"""
|
||||
Systems cost catalog
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Atiya atiya.atiya@mail.concordia.ca
|
||||
Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
|
||||
from hub.catalog_factories.data_models.cost.hvac import Hvac
|
||||
|
||||
|
||||
class Systems:
|
||||
def __init__(self, hvac, photovoltaic_system_reposition, photovoltaic_system_initial_investment,
|
||||
photovoltaic_system_lifetime, other_conditioning_systems_reposition,
|
||||
other_conditioning_systems_initial_investment, other_conditioning_systems_lifetime,
|
||||
lighting_reposition, lighting_initial_investment, lighting_lifetime):
|
||||
self._hvac = hvac
|
||||
self._photovoltaic_system_reposition = photovoltaic_system_reposition
|
||||
self._photovoltaic_system_initial_investment = photovoltaic_system_initial_investment
|
||||
self._photovoltaic_system_lifetime = photovoltaic_system_lifetime
|
||||
self._other_conditioning_systems_reposition = other_conditioning_systems_reposition
|
||||
self._other_conditioning_systems_initial_investment = other_conditioning_systems_initial_investment
|
||||
self._other_conditioning_systems_lifetime = other_conditioning_systems_lifetime
|
||||
self._lighting_reposition = lighting_reposition
|
||||
self._lighting_initial_investment = lighting_initial_investment
|
||||
self._lighting_lifetime = lighting_lifetime
|
||||
|
||||
@property
|
||||
def hvac(self) -> Hvac:
|
||||
"""
|
||||
Get hvac capital cost
|
||||
:return: Hvac
|
||||
"""
|
||||
return self._hvac
|
||||
|
||||
@property
|
||||
def photovoltaic_system_reposition(self):
|
||||
"""
|
||||
Get photovoltaic system reposition cost per area of panels in currency/m2
|
||||
:return: float
|
||||
"""
|
||||
return self._photovoltaic_system_reposition
|
||||
|
||||
@property
|
||||
def photovoltaic_system_initial_investment(self):
|
||||
"""
|
||||
Get photovoltaic system initial investment per area of panels in currency/m2
|
||||
:return: float
|
||||
"""
|
||||
return self._photovoltaic_system_initial_investment
|
||||
|
||||
@property
|
||||
def photovoltaic_system_lifetime(self):
|
||||
"""
|
||||
Get photovoltaic system lifetime in years
|
||||
:return: float
|
||||
"""
|
||||
return self._photovoltaic_system_lifetime
|
||||
|
||||
@property
|
||||
def other_conditioning_systems_reposition(self):
|
||||
"""
|
||||
Get other conditioning systems reposition cost per building's foot-print area in currency/m2
|
||||
:return: float
|
||||
"""
|
||||
return self._other_conditioning_systems_reposition
|
||||
|
||||
@property
|
||||
def other_conditioning_systems_initial_investment(self):
|
||||
"""
|
||||
Get other conditioning systems initial investment per building's foot-print area in currency/m2
|
||||
:return: float
|
||||
"""
|
||||
return self._other_conditioning_systems_initial_investment
|
||||
|
||||
@property
|
||||
def other_conditioning_systems_lifetime(self):
|
||||
"""
|
||||
Get other conditioning systems lifetime in years
|
||||
:return: float
|
||||
"""
|
||||
return self._other_conditioning_systems_lifetime
|
||||
|
||||
@property
|
||||
def lighting_reposition(self):
|
||||
"""
|
||||
Get lighting reposition cost per building's foot-print area in currency/m2
|
||||
:return: float
|
||||
"""
|
||||
return self._lighting_reposition
|
||||
|
||||
@property
|
||||
def lighting_initial_investment(self):
|
||||
"""
|
||||
Get lighting initial investment per building's foot-print area in currency/m2
|
||||
:return: float
|
||||
"""
|
||||
return self._lighting_initial_investment
|
||||
|
||||
@property
|
||||
def lighting_lifetime(self):
|
||||
"""
|
||||
Get lighting lifetime in years
|
||||
:return: float
|
||||
"""
|
||||
return self._lighting_lifetime
|
|
@ -5,6 +5,7 @@ Copyright © 2022 Concordia CERC group
|
|||
Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
||||
"""
|
||||
|
||||
|
||||
class InternalGain:
|
||||
"""
|
||||
InternalGain class
|
||||
|
|
|
@ -13,7 +13,7 @@ from hub.catalog_factories.data_models.usages.thermal_control import ThermalCont
|
|||
|
||||
|
||||
class Usage:
|
||||
def __init__(self, usage,
|
||||
def __init__(self, name,
|
||||
hours_day,
|
||||
days_year,
|
||||
mechanical_air_change,
|
||||
|
@ -22,7 +22,7 @@ class Usage:
|
|||
lighting,
|
||||
appliances,
|
||||
thermal_control):
|
||||
self._usage = usage
|
||||
self._name = name
|
||||
self._hours_day = hours_day
|
||||
self._days_year = days_year
|
||||
self._mechanical_air_change = mechanical_air_change
|
||||
|
@ -34,12 +34,12 @@ class Usage:
|
|||
self._thermal_control = thermal_control
|
||||
|
||||
@property
|
||||
def usage(self) -> Union[None, str]:
|
||||
def name(self) -> Union[None, str]:
|
||||
"""
|
||||
Get usage zone usage
|
||||
Get usage zone usage name
|
||||
:return: None or str
|
||||
"""
|
||||
return self._usage
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def hours_day(self) -> Union[None, float]:
|
||||
|
|
|
@ -8,8 +8,11 @@ Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
|||
from pathlib import Path
|
||||
from typing import TypeVar
|
||||
from hub.catalog_factories.greenery.greenery_catalog import GreeneryCatalog
|
||||
from hub.hub_logger import logger
|
||||
from hub.helpers.utils import validate_import_export_type
|
||||
Catalog = TypeVar('Catalog')
|
||||
|
||||
|
||||
class GreeneryCatalogFactory:
|
||||
"""
|
||||
GreeneryCatalogFactory class
|
||||
|
@ -18,6 +21,11 @@ class GreeneryCatalogFactory:
|
|||
if base_path is None:
|
||||
base_path = Path(Path(__file__).parent.parent / 'data/greenery')
|
||||
self._catalog_type = '_' + file_type.lower()
|
||||
class_funcs = validate_import_export_type(GreeneryCatalogFactory)
|
||||
if self._catalog_type not in class_funcs:
|
||||
err_msg = f"Wrong import type. Valid functions include {class_funcs}"
|
||||
logger.error(err_msg)
|
||||
raise Exception(err_msg)
|
||||
self._path = base_path
|
||||
|
||||
@property
|
||||
|
|
|
@ -28,6 +28,7 @@ class ComnetCatalog(Catalog):
|
|||
self._archetypes = self._read_archetype_file()
|
||||
self._schedules = self._read_schedules_file()
|
||||
|
||||
# todo: comment with @Guille, this hypotheses should go in the import factory?
|
||||
sensible_convective = ch().comnet_occupancy_sensible_convective
|
||||
sensible_radiative = ch().comnet_occupancy_sensible_radiant
|
||||
lighting_convective = ch().comnet_lighting_convective
|
||||
|
@ -41,7 +42,8 @@ class ComnetCatalog(Catalog):
|
|||
for schedule_key in self._archetypes['schedules_key']:
|
||||
comnet_usage = schedule_key
|
||||
schedule_name = self._archetypes['schedules_key'][schedule_key]
|
||||
hours_day = self._calculate_hours_day(schedule_name)
|
||||
hours_day = None
|
||||
days_year = None
|
||||
occupancy_archetype = self._archetypes['occupancy'][comnet_usage]
|
||||
lighting_archetype = self._archetypes['lighting'][comnet_usage]
|
||||
appliances_archetype = self._archetypes['plug loads'][comnet_usage]
|
||||
|
@ -86,29 +88,9 @@ class ComnetCatalog(Catalog):
|
|||
self._schedules[schedule_name]['Receptacle'])
|
||||
|
||||
# get thermal control
|
||||
max_heating_setpoint = cte.MIN_FLOAT
|
||||
min_heating_setpoint = cte.MAX_FLOAT
|
||||
|
||||
for schedule in self._schedules[schedule_name]['HtgSetPt']:
|
||||
if schedule.values is None:
|
||||
max_heating_setpoint = None
|
||||
min_heating_setpoint = None
|
||||
break
|
||||
if max(schedule.values) > max_heating_setpoint:
|
||||
max_heating_setpoint = max(schedule.values)
|
||||
if min(schedule.values) < min_heating_setpoint:
|
||||
min_heating_setpoint = min(schedule.values)
|
||||
|
||||
min_cooling_setpoint = cte.MAX_FLOAT
|
||||
for schedule in self._schedules[schedule_name]['ClgSetPt']:
|
||||
if schedule.values is None:
|
||||
min_cooling_setpoint = None
|
||||
break
|
||||
if min(schedule.values) < min_cooling_setpoint:
|
||||
min_cooling_setpoint = min(schedule.values)
|
||||
thermal_control = ThermalControl(max_heating_setpoint,
|
||||
min_heating_setpoint,
|
||||
min_cooling_setpoint,
|
||||
thermal_control = ThermalControl(None,
|
||||
None,
|
||||
None,
|
||||
self._schedules[schedule_name]['HVAC Avail'],
|
||||
self._schedules[schedule_name]['HtgSetPt'],
|
||||
self._schedules[schedule_name]['ClgSetPt']
|
||||
|
@ -116,7 +98,7 @@ class ComnetCatalog(Catalog):
|
|||
|
||||
usages.append(Usage(comnet_usage,
|
||||
hours_day,
|
||||
365,
|
||||
days_year,
|
||||
mechanical_air_change,
|
||||
ventilation_rate,
|
||||
occupancy,
|
||||
|
@ -202,16 +184,6 @@ class ComnetCatalog(Catalog):
|
|||
'schedules_key': schedules_key
|
||||
}
|
||||
|
||||
def _calculate_hours_day(self, function):
|
||||
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]
|
||||
total = 0
|
||||
for schedule in self._schedules[function]['HVAC Avail']:
|
||||
yearly_days = number_of_days_per_type[days.index(schedule.day_types[0])]
|
||||
for value in schedule.values:
|
||||
total += value * yearly_days
|
||||
return total / 365
|
||||
|
||||
def names(self, category=None):
|
||||
"""
|
||||
Get the catalog elements names
|
||||
|
@ -219,7 +191,7 @@ class ComnetCatalog(Catalog):
|
|||
"""
|
||||
_names = {'usages': []}
|
||||
for usage in self._content.usages:
|
||||
_names['usages'].append(usage.usage)
|
||||
_names['usages'].append(usage.name)
|
||||
return _names
|
||||
|
||||
def entries(self, category=None):
|
||||
|
@ -235,6 +207,6 @@ class ComnetCatalog(Catalog):
|
|||
:parm: entry name
|
||||
"""
|
||||
for usage in self._content.usages:
|
||||
if usage.usage.lower() == name.lower():
|
||||
if usage.name.lower() == name.lower():
|
||||
return usage
|
||||
raise IndexError(f"{name} doesn't exists in the catalog")
|
||||
|
|
|
@ -3,6 +3,7 @@ NRCAN usage catalog
|
|||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
||||
Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
|
||||
import json
|
||||
|
@ -32,10 +33,6 @@ class NrcanCatalog(Catalog):
|
|||
self._load_schedules()
|
||||
self._content = Content(self._load_archetypes())
|
||||
|
||||
def _calculate_hours_day(self, function):
|
||||
# todo: pilar need to check how to calculate this value
|
||||
return 24
|
||||
|
||||
@staticmethod
|
||||
def _extract_schedule(raw):
|
||||
nrcan_schedule_type = raw['category']
|
||||
|
@ -54,59 +51,84 @@ class NrcanCatalog(Catalog):
|
|||
return Schedule(hub_type, raw['values'], data_type, time_step, time_range, day_types)
|
||||
|
||||
def _load_schedules(self):
|
||||
usage = self._metadata['nrcan']['standards']['usage']
|
||||
usage = self._metadata['nrcan']
|
||||
url = f'{self._base_url}{usage["schedules_location"]}'
|
||||
_schedule_types = []
|
||||
with urllib.request.urlopen(url) as json_file:
|
||||
schedules_type = json.load(json_file)
|
||||
for schedule_type in schedules_type['tables']['schedules']['table']:
|
||||
schedule = NrcanCatalog._extract_schedule(schedule_type)
|
||||
if schedule is not None:
|
||||
self._schedules[schedule_type['name']] = schedule
|
||||
if schedule_type['name'] not in _schedule_types:
|
||||
_schedule_types.append(schedule_type['name'])
|
||||
if schedule is not None:
|
||||
self._schedules[schedule_type['name']] = [schedule]
|
||||
else:
|
||||
if schedule is not None:
|
||||
_schedules = self._schedules[schedule_type['name']]
|
||||
_schedules.append(schedule)
|
||||
self._schedules[schedule_type['name']] = _schedules
|
||||
|
||||
def _get_schedule(self, name):
|
||||
def _get_schedules(self, name):
|
||||
if name in self._schedules:
|
||||
return self._schedules[name]
|
||||
|
||||
def _load_archetypes(self):
|
||||
usages = []
|
||||
usage = self._metadata['nrcan']['standards']['usage']
|
||||
url = f'{self._base_url}{usage["space_types_location"]}'
|
||||
name = self._metadata['nrcan']
|
||||
url = f'{self._base_url}{name["space_types_location"]}'
|
||||
with urllib.request.urlopen(url) as json_file:
|
||||
space_types = json.load(json_file)['tables']['space_types']['table']
|
||||
space_types = [st for st in space_types if st['building_type'] == 'Space Function']
|
||||
# space_types = [st for st in space_types if st['building_type'] == 'Space Function']
|
||||
space_types = [st for st in space_types if st['space_type'] == 'WholeBuilding']
|
||||
for space_type in space_types:
|
||||
usage_type = space_type['space_type']
|
||||
mechanical_air_change = space_type['ventilation_air_changes']
|
||||
ventilation_rate = space_type['ventilation_per_area']
|
||||
if ventilation_rate == 0:
|
||||
ventilation_rate = space_type['ventilation_per_person']
|
||||
hours_day = self._calculate_hours_day(usage_type)
|
||||
days_year = 365
|
||||
# usage_type = space_type['space_type']
|
||||
usage_type = space_type['building_type']
|
||||
occupancy_schedule_name = space_type['occupancy_schedule']
|
||||
lighting_schedule_name = space_type['lighting_schedule']
|
||||
appliance_schedule_name = space_type['electric_equipment_schedule']
|
||||
# thermal control
|
||||
hvac_schedule_name = space_type['exhaust_schedule']
|
||||
if 'FAN' in hvac_schedule_name:
|
||||
hvac_schedule_name = hvac_schedule_name.replace('FAN', 'Fan')
|
||||
heating_setpoint_schedule_name = space_type['heating_setpoint_schedule']
|
||||
cooling_setpoint_schedule_name = space_type['cooling_setpoint_schedule']
|
||||
occupancy_schedule = self._get_schedule(occupancy_schedule_name)
|
||||
lighting_schedule = self._get_schedule(lighting_schedule_name)
|
||||
appliance_schedule = self._get_schedule(appliance_schedule_name)
|
||||
heating_schedule = self._get_schedule(heating_setpoint_schedule_name)
|
||||
cooling_schedule = self._get_schedule(cooling_setpoint_schedule_name)
|
||||
occupancy_schedule = self._get_schedules(occupancy_schedule_name)
|
||||
lighting_schedule = self._get_schedules(lighting_schedule_name)
|
||||
appliance_schedule = self._get_schedules(appliance_schedule_name)
|
||||
heating_schedule = self._get_schedules(heating_setpoint_schedule_name)
|
||||
cooling_schedule = self._get_schedules(cooling_setpoint_schedule_name)
|
||||
hvac_availability = self._get_schedules(hvac_schedule_name)
|
||||
|
||||
occupancy_density = space_type['occupancy_per_area']
|
||||
lighting_density = space_type['lighting_per_area']
|
||||
|
||||
# ACH
|
||||
mechanical_air_change = space_type['ventilation_air_changes']
|
||||
# cfm/ft2 to m3/m2.s
|
||||
ventilation_rate = space_type['ventilation_per_area'] / (cte.METERS_TO_FEET * cte.MINUTES_TO_SECONDS)
|
||||
if ventilation_rate == 0:
|
||||
# cfm/person to m3/m2.s
|
||||
ventilation_rate = space_type['ventilation_per_person'] / occupancy_density\
|
||||
/ (cte.METERS_TO_FEET * cte.MINUTES_TO_SECONDS)
|
||||
|
||||
# W/sqft to W/m2
|
||||
lighting_density = space_type['lighting_per_area'] * cte.METERS_TO_FEET * cte.METERS_TO_FEET
|
||||
lighting_radiative_fraction = space_type['lighting_fraction_radiant']
|
||||
lighting_convective_fraction = 0
|
||||
if lighting_radiative_fraction is not None:
|
||||
lighting_convective_fraction = 1 - lighting_radiative_fraction
|
||||
lighting_latent_fraction = 0
|
||||
appliances_density = space_type['electric_equipment_per_area']
|
||||
# W/sqft to W/m2
|
||||
appliances_density = space_type['electric_equipment_per_area'] * cte.METERS_TO_FEET * cte.METERS_TO_FEET
|
||||
appliances_radiative_fraction = space_type['electric_equipment_fraction_radiant']
|
||||
if appliances_radiative_fraction is not None:
|
||||
appliances_convective_fraction = 1 - appliances_radiative_fraction
|
||||
appliances_latent_fraction = space_type['electric_equipment_fraction_latent']
|
||||
appliances_convective_fraction = 0
|
||||
if appliances_radiative_fraction is not None and appliances_latent_fraction is not None:
|
||||
appliances_convective_fraction = 1 - appliances_radiative_fraction - appliances_latent_fraction
|
||||
|
||||
occupancy = Occupancy(occupancy_density, 0, 0, 0, occupancy_schedule)
|
||||
occupancy = Occupancy(occupancy_density,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
occupancy_schedule)
|
||||
lighting = Lighting(lighting_density,
|
||||
lighting_convective_fraction,
|
||||
lighting_radiative_fraction,
|
||||
|
@ -117,20 +139,14 @@ class NrcanCatalog(Catalog):
|
|||
appliances_radiative_fraction,
|
||||
appliances_latent_fraction,
|
||||
appliance_schedule)
|
||||
if heating_schedule is not None:
|
||||
thermal_control = ThermalControl(max(heating_schedule.values),
|
||||
min(heating_schedule.values),
|
||||
min(cooling_schedule.values),
|
||||
None,
|
||||
heating_schedule,
|
||||
cooling_schedule)
|
||||
else:
|
||||
thermal_control = ThermalControl(None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None)
|
||||
thermal_control = ThermalControl(None,
|
||||
None,
|
||||
None,
|
||||
hvac_availability,
|
||||
heating_schedule,
|
||||
cooling_schedule)
|
||||
hours_day = None
|
||||
days_year = None
|
||||
usages.append(Usage(usage_type,
|
||||
hours_day,
|
||||
days_year,
|
||||
|
@ -149,7 +165,7 @@ class NrcanCatalog(Catalog):
|
|||
"""
|
||||
_names = {'usages': []}
|
||||
for usage in self._content.usages:
|
||||
_names['usages'].append(usage.usage)
|
||||
_names['usages'].append(usage.name)
|
||||
return _names
|
||||
|
||||
def entries(self, category=None):
|
||||
|
@ -165,6 +181,6 @@ class NrcanCatalog(Catalog):
|
|||
:parm: entry name
|
||||
"""
|
||||
for usage in self._content.usages:
|
||||
if usage.usage.lower() == name.lower():
|
||||
if usage.name.lower() == name.lower():
|
||||
return usage
|
||||
raise IndexError(f"{name} doesn't exists in the catalog")
|
||||
|
|
|
@ -19,6 +19,7 @@ class UsageHelper:
|
|||
'Equipment': cte.APPLIANCES,
|
||||
'Thermostat Setpoint Cooling': cte.COOLING_SET_POINT, # Compose 'Thermostat Setpoint' + 'Cooling'
|
||||
'Thermostat Setpoint Heating': cte.HEATING_SET_POINT, # Compose 'Thermostat Setpoint' + 'Heating'
|
||||
'Fan': cte.HVAC_AVAILABILITY
|
||||
}
|
||||
_nrcan_data_type_to_hub_data_type = {
|
||||
'FRACTION': cte.FRACTION,
|
||||
|
@ -58,31 +59,6 @@ class UsageHelper:
|
|||
|
||||
}
|
||||
|
||||
_usage_to_hft = {
|
||||
cte.RESIDENTIAL: 'residential',
|
||||
cte.SINGLE_FAMILY_HOUSE: 'Single family house',
|
||||
cte.MULTI_FAMILY_HOUSE: 'Multi-family house',
|
||||
cte.EDUCATION: 'education',
|
||||
cte.SCHOOL_WITHOUT_SHOWER: 'school without shower',
|
||||
cte.SCHOOL_WITH_SHOWER: 'school with shower',
|
||||
cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD: 'retail',
|
||||
cte.RETAIL_SHOP_WITH_REFRIGERATED_FOOD: 'retail shop / refrigerated food',
|
||||
cte.HOTEL: 'hotel',
|
||||
cte.HOTEL_MEDIUM_CLASS: 'hotel (Medium-class)',
|
||||
cte.DORMITORY: 'dormitory',
|
||||
cte.INDUSTRY: 'industry',
|
||||
cte.RESTAURANT: 'restaurant',
|
||||
cte.HEALTH_CARE: 'health care',
|
||||
cte.RETIREMENT_HOME_OR_ORPHANAGE: 'Home for the aged or orphanage',
|
||||
cte.OFFICE_AND_ADMINISTRATION: 'office and administration',
|
||||
cte.EVENT_LOCATION: 'event location',
|
||||
cte.HALL: 'hall',
|
||||
cte.SPORTS_LOCATION: 'sport location',
|
||||
cte.LABOR: 'Labor',
|
||||
cte.GREEN_HOUSE: 'green house',
|
||||
cte.NON_HEATED: 'non-heated'
|
||||
}
|
||||
|
||||
_comnet_days = [cte.MONDAY,
|
||||
cte.TUESDAY,
|
||||
cte.WEDNESDAY,
|
||||
|
@ -92,31 +68,6 @@ class UsageHelper:
|
|||
cte.SUNDAY,
|
||||
cte.HOLIDAY]
|
||||
|
||||
_usage_to_comnet = {
|
||||
cte.RESIDENTIAL: 'BA Multifamily',
|
||||
cte.SINGLE_FAMILY_HOUSE: 'BA Multifamily',
|
||||
cte.MULTI_FAMILY_HOUSE: 'BA Multifamily',
|
||||
cte.EDUCATION: 'BA School/University',
|
||||
cte.SCHOOL_WITHOUT_SHOWER: 'BA School/University',
|
||||
cte.SCHOOL_WITH_SHOWER: 'BA School/University',
|
||||
cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD: 'BA Retail',
|
||||
cte.RETAIL_SHOP_WITH_REFRIGERATED_FOOD: 'BA Retail',
|
||||
cte.HOTEL: 'BA Hotel',
|
||||
cte.HOTEL_MEDIUM_CLASS: 'BA Hotel',
|
||||
cte.DORMITORY: 'BA Dormitory',
|
||||
cte.INDUSTRY: 'BA Manufacturing Facility',
|
||||
cte.RESTAURANT: 'BA Dining: Family',
|
||||
cte.HEALTH_CARE: 'BA Hospital',
|
||||
cte.RETIREMENT_HOME_OR_ORPHANAGE: 'BA Multifamily',
|
||||
cte.OFFICE_AND_ADMINISTRATION: 'BA Office',
|
||||
cte.EVENT_LOCATION: 'BA Convention Center',
|
||||
cte.HALL: 'BA Convention Center',
|
||||
cte.SPORTS_LOCATION: 'BA Sports Arena',
|
||||
cte.LABOR: 'BA Gymnasium',
|
||||
cte.GREEN_HOUSE: cte.GREEN_HOUSE,
|
||||
cte.NON_HEATED: cte.NON_HEATED
|
||||
}
|
||||
|
||||
_comnet_data_type_to_hub_data_type = {
|
||||
'Fraction': cte.FRACTION,
|
||||
'OnOff': cte.ON_OFF,
|
||||
|
@ -166,18 +117,6 @@ class UsageHelper:
|
|||
def comnet_days(self):
|
||||
return self._comnet_days
|
||||
|
||||
@staticmethod
|
||||
def comnet_from_hub_usage(usage):
|
||||
"""
|
||||
Get Comnet usage from the given internal usage key
|
||||
:param usage: str
|
||||
:return: str
|
||||
"""
|
||||
try:
|
||||
return UsageHelper._usage_to_comnet[usage]
|
||||
except KeyError:
|
||||
sys.stderr.write('Error: keyword not found to translate from hub_usage to comnet usage.\n')
|
||||
|
||||
@staticmethod
|
||||
def schedules_key(usage):
|
||||
"""
|
||||
|
@ -190,15 +129,3 @@ class UsageHelper:
|
|||
except KeyError:
|
||||
sys.stderr.write('Error: Comnet keyword not found. An update of the Comnet files might have been '
|
||||
'done changing the keywords.\n')
|
||||
|
||||
@staticmethod
|
||||
def hft_from_hub_usage(usage):
|
||||
"""
|
||||
Get HfT usage from the given internal usage key
|
||||
:param usage: str
|
||||
:return: str
|
||||
"""
|
||||
try:
|
||||
return UsageHelper._usage_to_hft[usage]
|
||||
except KeyError:
|
||||
sys.stderr.write('Error: keyword not found to translate from hub_usage to hft usage.\n')
|
||||
|
|
|
@ -9,6 +9,8 @@ from pathlib import Path
|
|||
from typing import TypeVar
|
||||
from hub.catalog_factories.usage.comnet_catalog import ComnetCatalog
|
||||
from hub.catalog_factories.usage.nrcan_catalog import NrcanCatalog
|
||||
from hub.hub_logger import logger
|
||||
from hub.helpers.utils import validate_import_export_type
|
||||
Catalog = TypeVar('Catalog')
|
||||
|
||||
|
||||
|
@ -17,6 +19,11 @@ class UsageCatalogFactory:
|
|||
if base_path is None:
|
||||
base_path = Path(Path(__file__).parent.parent / 'data/usage')
|
||||
self._catalog_type = '_' + file_type.lower()
|
||||
class_funcs = validate_import_export_type(UsageCatalogFactory)
|
||||
if self._catalog_type not in class_funcs:
|
||||
err_msg = f"Wrong import type. Valid functions include {class_funcs}"
|
||||
logger.error(err_msg)
|
||||
raise Exception(err_msg)
|
||||
self._path = base_path
|
||||
|
||||
@property
|
||||
|
|
|
@ -9,9 +9,13 @@ from __future__ import annotations
|
|||
import math
|
||||
import sys
|
||||
from typing import List
|
||||
from hub.hub_logger import logger
|
||||
import numpy as np
|
||||
from trimesh import Trimesh
|
||||
import trimesh.intersections
|
||||
import trimesh.creation
|
||||
import trimesh.geometry
|
||||
from shapely.geometry.polygon import Polygon as shapley_polygon
|
||||
|
||||
from hub.city_model_structure.attributes.plane import Plane
|
||||
from hub.city_model_structure.attributes.point import Point
|
||||
|
@ -22,6 +26,7 @@ class Polygon:
|
|||
"""
|
||||
Polygon class
|
||||
"""
|
||||
# todo: review with @Guille: Points, Coordinates, Vertices, Faces
|
||||
|
||||
def __init__(self, coordinates):
|
||||
self._area = None
|
||||
|
@ -66,20 +71,6 @@ class Polygon:
|
|||
"""
|
||||
return self._coordinates
|
||||
|
||||
@staticmethod
|
||||
def _module(vector):
|
||||
x2 = vector[0] ** 2
|
||||
y2 = vector[1] ** 2
|
||||
z2 = vector[2] ** 2
|
||||
return math.sqrt(x2+y2+z2)
|
||||
|
||||
@staticmethod
|
||||
def _scalar_product(vector_0, vector_1):
|
||||
x = vector_0[0] * vector_1[0]
|
||||
y = vector_0[1] * vector_1[1]
|
||||
z = vector_0[2] * vector_1[2]
|
||||
return x+y+z
|
||||
|
||||
def contains_point(self, point):
|
||||
"""
|
||||
Determines if the given point is contained by the current polygon
|
||||
|
@ -98,9 +89,9 @@ class Polygon:
|
|||
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 = Polygon._module(vector_0) * Polygon._module(vector_1)
|
||||
module = np.linalg.norm(vector_0) * np.linalg.norm(vector_1)
|
||||
|
||||
scalar_product = Polygon._scalar_product(vector_0, vector_1)
|
||||
scalar_product = np.dot(vector_0, vector_1)
|
||||
angle = np.pi/2
|
||||
if module != 0:
|
||||
angle = abs(np.arcsin(scalar_product / module))
|
||||
|
@ -150,69 +141,17 @@ class Polygon:
|
|||
Get surface area in square meters
|
||||
:return: float
|
||||
"""
|
||||
# New method to calculate area
|
||||
if self._area is None:
|
||||
if len(self.points) < 3:
|
||||
sys.stderr.write('Warning: the area of a line or point cannot be calculated 1. Area = 0\n')
|
||||
return 0
|
||||
alpha = 0
|
||||
vec_1 = self.points[1].coordinates - self.points[0].coordinates
|
||||
for i in range(2, len(self.points)):
|
||||
vec_2 = self.points[i].coordinates - self.points[0].coordinates
|
||||
alpha += self._angle_between_vectors(vec_1, vec_2)
|
||||
if alpha == 0:
|
||||
sys.stderr.write('Warning: the area of a line or point cannot be calculated 2. Area = 0\n')
|
||||
return 0
|
||||
horizontal_points = self._points_rotated_to_horizontal
|
||||
area = 0
|
||||
for i in range(0, len(horizontal_points) - 1):
|
||||
point = horizontal_points[i]
|
||||
next_point = horizontal_points[i + 1]
|
||||
area += (next_point[1] + point[1]) / 2 * (next_point[0] - point[0])
|
||||
next_point = horizontal_points[0]
|
||||
point = horizontal_points[len(horizontal_points) - 1]
|
||||
area += (next_point[1] + point[1]) / 2 * (next_point[0] - point[0])
|
||||
self._area = abs(area)
|
||||
self._area = 0
|
||||
for triangle in self.triangles:
|
||||
ab = np.zeros(3)
|
||||
ac = 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
|
||||
return self._area
|
||||
|
||||
@property
|
||||
def _points_rotated_to_horizontal(self):
|
||||
"""
|
||||
polygon points rotated to horizontal
|
||||
:return: [float]
|
||||
"""
|
||||
z_vector = [0, 0, 1]
|
||||
normal_vector = self.normal
|
||||
horizontal_points = []
|
||||
x = normal_vector[0]
|
||||
y = normal_vector[1]
|
||||
|
||||
if x == 0 and y == 0:
|
||||
# Already horizontal
|
||||
for point in self.points:
|
||||
horizontal_points.append([point.coordinates[0], point.coordinates[1], 0])
|
||||
else:
|
||||
alpha = self._angle_between_vectors(normal_vector, z_vector)
|
||||
rotation_line = np.cross(normal_vector, z_vector)
|
||||
third_axis = np.cross(normal_vector, rotation_line)
|
||||
w_1 = rotation_line / np.linalg.norm(rotation_line)
|
||||
w_2 = normal_vector
|
||||
w_3 = third_axis / np.linalg.norm(third_axis)
|
||||
rotation_matrix = np.array([[1, 0, 0],
|
||||
[0, np.cos(alpha), -np.sin(alpha)],
|
||||
[0, np.sin(alpha), np.cos(alpha)]])
|
||||
base_matrix = np.array([w_1, w_2, w_3])
|
||||
rotation_base_matrix = np.matmul(base_matrix.transpose(), rotation_matrix.transpose())
|
||||
rotation_base_matrix = np.matmul(rotation_base_matrix, base_matrix)
|
||||
|
||||
if rotation_base_matrix is None:
|
||||
sys.stderr.write('Warning: rotation base matrix returned None\n')
|
||||
else:
|
||||
for point in self.points:
|
||||
new_point = np.matmul(rotation_base_matrix, point.coordinates)
|
||||
horizontal_points.append(new_point)
|
||||
return horizontal_points
|
||||
|
||||
@property
|
||||
def normal(self) -> np.ndarray:
|
||||
"""
|
||||
|
@ -275,283 +214,74 @@ class Polygon:
|
|||
return alpha
|
||||
return -alpha
|
||||
|
||||
def triangulate(self) -> List[Polygon]:
|
||||
"""
|
||||
Triangulates a polygon following the ear clipping methodology
|
||||
:return: list[triangles]
|
||||
"""
|
||||
# todo: review triangulate_polygon in
|
||||
# https://github.com/mikedh/trimesh/blob/dad11126742e140ef46ba12f8cb8643c83356467/trimesh/creation.py#L415,
|
||||
# it had a problem with a class called 'triangle', but, if solved,
|
||||
# it could be a very good substitute of this method
|
||||
# this method is very dirty and has an infinite loop solved with a counter!!
|
||||
if self._triangles is None:
|
||||
points_list = self.points_list
|
||||
normal = self.normal
|
||||
if np.linalg.norm(normal) == 0:
|
||||
sys.stderr.write('Not able to triangulate polygon\n')
|
||||
return [self]
|
||||
# are points concave or convex?
|
||||
total_points_list, concave_points, convex_points = self._starting_lists(points_list, normal)
|
||||
|
||||
# list of ears
|
||||
ears = []
|
||||
j = 0
|
||||
while (len(concave_points) > 3 or len(convex_points) != 0) and j < 100:
|
||||
j += 1
|
||||
for i in range(0, len(concave_points)):
|
||||
ear = self._triangle(points_list, total_points_list, concave_points[i])
|
||||
rest_points = []
|
||||
for points in total_points_list:
|
||||
rest_points.append(list(self.coordinates[points]))
|
||||
if self._is_ear(ear, rest_points):
|
||||
ears.append(ear)
|
||||
point_to_remove = concave_points[i]
|
||||
previous_point_in_list, next_point_in_list = self._enveloping_points(point_to_remove,
|
||||
total_points_list)
|
||||
total_points_list.remove(point_to_remove)
|
||||
concave_points.remove(point_to_remove)
|
||||
# Was any of the adjacent points convex? -> check if changed status to concave
|
||||
for convex_point in convex_points:
|
||||
if convex_point == previous_point_in_list:
|
||||
concave_points, convex_points, end_loop = self._if_concave_change_status(normal,
|
||||
points_list,
|
||||
convex_point,
|
||||
total_points_list,
|
||||
concave_points,
|
||||
convex_points,
|
||||
previous_point_in_list)
|
||||
if end_loop:
|
||||
break
|
||||
continue
|
||||
if convex_point == next_point_in_list:
|
||||
concave_points, convex_points, end_loop = self._if_concave_change_status(normal,
|
||||
points_list,
|
||||
convex_point,
|
||||
total_points_list,
|
||||
concave_points,
|
||||
convex_points,
|
||||
next_point_in_list)
|
||||
if end_loop:
|
||||
break
|
||||
continue
|
||||
break
|
||||
if len(total_points_list) <= 3 and len(convex_points) > 0:
|
||||
sys.stderr.write('Not able to triangulate polygon\n')
|
||||
return [self]
|
||||
if j >= 100:
|
||||
sys.stderr.write('Not able to triangulate polygon\n')
|
||||
return [self]
|
||||
last_ear = self._triangle(points_list, total_points_list, concave_points[1])
|
||||
ears.append(last_ear)
|
||||
self._triangles = ears
|
||||
return self._triangles
|
||||
|
||||
@staticmethod
|
||||
def _starting_lists(points_list, normal) -> [List[float], List[float], List[float]]:
|
||||
"""
|
||||
creates the list of vertices (points) that define the polygon (total_points_list), together with other two lists
|
||||
separating points between convex and concave
|
||||
:param points_list: points_list
|
||||
:param normal: normal
|
||||
:return: list[point], list[point], list[point]
|
||||
"""
|
||||
concave_points = []
|
||||
convex_points = []
|
||||
# lists of concave and convex points
|
||||
# case 1: first point
|
||||
point = points_list[0:3]
|
||||
previous_point = points_list[len(points_list) - 3:]
|
||||
next_point = points_list[3:6]
|
||||
index = 0
|
||||
total_points_list = [index]
|
||||
if Polygon._point_is_concave(normal, point, previous_point, next_point):
|
||||
concave_points.append(index)
|
||||
else:
|
||||
convex_points.append(index)
|
||||
# case 2: all points except first and last
|
||||
for i in range(0, int((len(points_list) - 6) / 3)):
|
||||
point = points_list[(i + 1) * 3:(i + 2) * 3]
|
||||
previous_point = points_list[i * 3:(i + 1) * 3]
|
||||
next_point = points_list[(i + 2) * 3:(i + 3) * 3]
|
||||
index = i + 1
|
||||
total_points_list.append(index)
|
||||
if Polygon._point_is_concave(normal, point, previous_point, next_point):
|
||||
concave_points.append(index)
|
||||
else:
|
||||
convex_points.append(index)
|
||||
# case 3: last point
|
||||
point = points_list[len(points_list) - 3:]
|
||||
previous_point = points_list[len(points_list) - 6:len(points_list) - 3]
|
||||
next_point = points_list[0:3]
|
||||
index = int(len(points_list) / 3) - 1
|
||||
total_points_list.append(index)
|
||||
if Polygon._point_is_concave(normal, point, previous_point, next_point):
|
||||
concave_points.append(index)
|
||||
else:
|
||||
convex_points.append(index)
|
||||
return total_points_list, concave_points, convex_points
|
||||
def triangle_mesh(vertices, normal):
|
||||
min_x = 1e16
|
||||
min_y = 1e16
|
||||
min_z = 1e16
|
||||
for vertex in vertices:
|
||||
if vertex[0] < min_x:
|
||||
min_x = vertex[0]
|
||||
if vertex[1] < min_y:
|
||||
min_y = vertex[1]
|
||||
if vertex[2] < min_z:
|
||||
min_z = vertex[2]
|
||||
|
||||
@staticmethod
|
||||
def _triangle(points_list, total_points_list, point_position) -> Polygon:
|
||||
"""
|
||||
creates a triangular polygon out of three points
|
||||
:param points_list: points_list
|
||||
:param total_points_list: [point]
|
||||
:param point_position: int
|
||||
:return: polygon
|
||||
"""
|
||||
index = point_position * 3
|
||||
previous_point_index, next_point_index = Polygon._enveloping_points_indices(point_position, total_points_list)
|
||||
points = points_list[previous_point_index:previous_point_index + 3]
|
||||
points = np.append(points, points_list[index:index + 3])
|
||||
points = np.append(points, points_list[next_point_index:next_point_index + 3])
|
||||
rows = points.size // 3
|
||||
points = points.reshape(rows, 3)
|
||||
triangle = Polygon(points)
|
||||
return triangle
|
||||
new_vertices = []
|
||||
for vertex in vertices:
|
||||
vertex = [vertex[0]-min_x, vertex[1]-min_y, vertex[2]-min_z]
|
||||
new_vertices.append(vertex)
|
||||
|
||||
@staticmethod
|
||||
def _enveloping_points_indices(point_position, total_points_list):
|
||||
"""
|
||||
due to the fact that the lists are not circular, a method to find the previous and next points
|
||||
of an specific one is needed
|
||||
:param point_position: int
|
||||
:param total_points_list: [point]
|
||||
:return: int, int
|
||||
"""
|
||||
previous_point_index = None
|
||||
next_point_index = None
|
||||
if point_position == total_points_list[0]:
|
||||
previous_point_index = total_points_list[len(total_points_list) - 1] * 3
|
||||
next_point_index = total_points_list[1] * 3
|
||||
if point_position == total_points_list[len(total_points_list) - 1]:
|
||||
previous_point_index = total_points_list[len(total_points_list) - 2] * 3
|
||||
next_point_index = total_points_list[0] * 3
|
||||
for i in range(1, len(total_points_list) - 1):
|
||||
if point_position == total_points_list[i]:
|
||||
previous_point_index = total_points_list[i - 1] * 3
|
||||
next_point_index = total_points_list[i + 1] * 3
|
||||
return previous_point_index, next_point_index
|
||||
transformation_matrix = trimesh.geometry.plane_transform(origin=new_vertices[0], normal=normal)
|
||||
|
||||
@staticmethod
|
||||
def _enveloping_points(point_to_remove, total_points_list):
|
||||
"""
|
||||
due to the fact that the lists are not circular, a method to find the previous and next points
|
||||
of an specific one is needed
|
||||
:param point_to_remove: point
|
||||
:param total_points_list: [point]
|
||||
:return: point, point
|
||||
"""
|
||||
index = total_points_list.index(point_to_remove)
|
||||
if index == 0:
|
||||
previous_point_in_list = total_points_list[len(total_points_list) - 1]
|
||||
next_point_in_list = total_points_list[1]
|
||||
elif index == len(total_points_list) - 1:
|
||||
previous_point_in_list = total_points_list[len(total_points_list) - 2]
|
||||
next_point_in_list = total_points_list[0]
|
||||
else:
|
||||
previous_point_in_list = total_points_list[index - 1]
|
||||
next_point_in_list = total_points_list[index + 1]
|
||||
return previous_point_in_list, next_point_in_list
|
||||
coordinates = []
|
||||
for vertex in vertices:
|
||||
transformed_vertex = [vertex[0]-min_x, vertex[1]-min_y, vertex[2]-min_z, 1]
|
||||
transformed_vertex = np.dot(transformation_matrix, transformed_vertex)
|
||||
coordinate = [transformed_vertex[0], transformed_vertex[1]]
|
||||
coordinates.append(coordinate)
|
||||
|
||||
@staticmethod
|
||||
def _is_ear(ear, points) -> bool:
|
||||
"""
|
||||
finds whether a triangle is an ear of the polygon
|
||||
:param ear: polygon
|
||||
:param points: [point]
|
||||
:return: boolean
|
||||
"""
|
||||
area_ear = ear.area
|
||||
for point in points:
|
||||
area_points = 0
|
||||
point_is_not_vertex = True
|
||||
polygon = shapley_polygon(coordinates)
|
||||
|
||||
try:
|
||||
vertices_2d, faces = trimesh.creation.triangulate_polygon(polygon, engine='triangle')
|
||||
mesh = Trimesh(vertices=vertices, faces=faces)
|
||||
|
||||
# check orientation
|
||||
normal_sum = 0
|
||||
for i in range(0, 3):
|
||||
if abs(np.linalg.norm(point) - np.linalg.norm(ear.coordinates[i])) < 0.0001:
|
||||
point_is_not_vertex = False
|
||||
break
|
||||
if point_is_not_vertex:
|
||||
for i in range(0, 3):
|
||||
if i != 2:
|
||||
new_points = ear.coordinates[i][:]
|
||||
new_points = np.append(new_points, ear.coordinates[i + 1][:])
|
||||
new_points = np.append(new_points, point[:])
|
||||
else:
|
||||
new_points = ear.coordinates[i][:]
|
||||
new_points = np.append(new_points, point[:])
|
||||
new_points = np.append(new_points, ear.coordinates[0][:])
|
||||
rows = new_points.size // 3
|
||||
new_points = new_points.reshape(rows, 3)
|
||||
new_triangle = Polygon(new_points)
|
||||
area_points += new_triangle.area
|
||||
if abs(area_points - area_ear) < 1e-6:
|
||||
# point_inside_ear = True
|
||||
return False
|
||||
return True
|
||||
normal_sum += normal[i] + mesh.face_normals[0][i]
|
||||
|
||||
@staticmethod
|
||||
def _if_concave_change_status(normal, points_list, convex_point, total_points_list,
|
||||
concave_points, convex_points, point_in_list) -> [List[float], List[float], bool]:
|
||||
"""
|
||||
checks whether an convex specific point change its status to concave after removing one ear in the polygon
|
||||
returning the new convex and concave points lists together with a flag advising that the list of total points
|
||||
already 3 and, therefore, the triangulation must be finished.
|
||||
:param normal: normal
|
||||
:param points_list: points_list
|
||||
:param convex_point: int
|
||||
:param total_points_list: [point]
|
||||
:param concave_points: [point]
|
||||
:param convex_points: [point]
|
||||
:param point_in_list: int
|
||||
:return: list[points], list[points], boolean
|
||||
"""
|
||||
end_loop = False
|
||||
point = points_list[point_in_list * 3:(point_in_list + 1) * 3]
|
||||
pointer = total_points_list.index(point_in_list) - 1
|
||||
if pointer < 0:
|
||||
pointer = len(total_points_list) - 1
|
||||
previous_point = points_list[total_points_list[pointer] * 3:total_points_list[pointer] * 3 + 3]
|
||||
pointer = total_points_list.index(point_in_list) + 1
|
||||
if pointer >= len(total_points_list):
|
||||
pointer = 0
|
||||
next_point = points_list[total_points_list[pointer] * 3:total_points_list[pointer] * 3 + 3]
|
||||
if Polygon._point_is_concave(normal, point, previous_point, next_point):
|
||||
if concave_points[0] > convex_point:
|
||||
concave_points.insert(0, convex_point)
|
||||
elif concave_points[len(concave_points) - 1] < convex_point:
|
||||
concave_points.append(convex_point)
|
||||
else:
|
||||
for point_index in range(0, len(concave_points) - 1):
|
||||
if concave_points[point_index] < convex_point < concave_points[point_index + 1]:
|
||||
concave_points.insert(point_index + 1, convex_point)
|
||||
convex_points.remove(convex_point)
|
||||
end_loop = True
|
||||
return concave_points, convex_points, end_loop
|
||||
if abs(normal_sum) <= 1E-10:
|
||||
new_faces = []
|
||||
for face in faces:
|
||||
new_face = []
|
||||
for i in range(0, len(face)):
|
||||
new_face.append(face[len(face)-i-1])
|
||||
new_faces.append(new_face)
|
||||
mesh = Trimesh(vertices=vertices, faces=new_faces)
|
||||
|
||||
@staticmethod
|
||||
def _point_is_concave(normal, point, previous_point, next_point) -> bool:
|
||||
"""
|
||||
returns whether a point is concave
|
||||
:param normal: normal
|
||||
:param point: point
|
||||
:param previous_point: point
|
||||
:param next_point: point
|
||||
:return: boolean
|
||||
"""
|
||||
is_concave = False
|
||||
accepted_error = 0.1
|
||||
points = np.append(previous_point, point)
|
||||
points = np.append(points, next_point)
|
||||
rows = points.size // 3
|
||||
points = points.reshape(rows, 3)
|
||||
triangle = Polygon(points)
|
||||
error_sum = 0
|
||||
for i in range(0, len(normal)):
|
||||
error_sum += triangle.normal[i] - normal[i]
|
||||
if np.abs(error_sum) < accepted_error:
|
||||
is_concave = True
|
||||
return is_concave
|
||||
return mesh
|
||||
|
||||
except ValueError:
|
||||
logger.error(f'Not able to triangulate polygon\n')
|
||||
sys.stderr.write(f'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]:
|
||||
if self._triangles is None:
|
||||
self._triangles = []
|
||||
_mesh = self.triangle_mesh(self.coordinates, self.normal)
|
||||
for face in _mesh.faces:
|
||||
points = []
|
||||
for vertex in face:
|
||||
points.append(self.coordinates[vertex])
|
||||
polygon = Polygon(points)
|
||||
self._triangles.append(polygon)
|
||||
return self._triangles
|
||||
|
||||
@staticmethod
|
||||
def _angle_between_vectors(vec_1, vec_2):
|
||||
|
@ -652,12 +382,12 @@ class Polygon:
|
|||
@property
|
||||
def vertices(self) -> np.ndarray:
|
||||
"""
|
||||
Get polyhedron vertices
|
||||
Get polygon vertices
|
||||
:return: np.ndarray(int)
|
||||
"""
|
||||
if self._vertices is None:
|
||||
vertices, self._vertices = [], []
|
||||
_ = [vertices.extend(s.coordinates) for s in self.triangulate()]
|
||||
_ = [vertices.extend(s.coordinates) for s in self.triangles]
|
||||
for vertex_1 in vertices:
|
||||
found = False
|
||||
for vertex_2 in self._vertices:
|
||||
|
@ -677,17 +407,17 @@ class Polygon:
|
|||
@property
|
||||
def faces(self) -> List[List[int]]:
|
||||
"""
|
||||
Get polyhedron triangular faces
|
||||
Get polygon triangular faces
|
||||
:return: [face]
|
||||
"""
|
||||
if self._faces is None:
|
||||
self._faces = []
|
||||
|
||||
for polygon in self.triangulate():
|
||||
for polygon in self.triangles:
|
||||
face = []
|
||||
points = polygon.coordinates
|
||||
if len(points) != 3:
|
||||
sub_polygons = polygon.triangulate()
|
||||
sub_polygons = polygon.triangles
|
||||
# todo: I modified this! To be checked @Guille
|
||||
if len(sub_polygons) >= 1:
|
||||
for sub_polygon in sub_polygons:
|
||||
|
|
|
@ -91,7 +91,7 @@ class Polyhedron:
|
|||
face = []
|
||||
points = polygon.coordinates
|
||||
if len(points) != 3:
|
||||
sub_polygons = polygon.triangulate()
|
||||
sub_polygons = polygon.triangles
|
||||
# todo: I modified this! To be checked @Guille
|
||||
if len(sub_polygons) >= 1:
|
||||
for sub_polygon in sub_polygons:
|
||||
|
|
|
@ -6,8 +6,10 @@ Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
|||
Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
|
||||
import sys
|
||||
from typing import List, Union
|
||||
import numpy as np
|
||||
from hub.hub_logger import logger
|
||||
import hub.helpers.constants as cte
|
||||
from hub.city_model_structure.building_demand.surface import Surface
|
||||
from hub.city_model_structure.city_object import CityObject
|
||||
|
@ -34,7 +36,7 @@ class Building(CityObject):
|
|||
self._roof_type = None
|
||||
self._internal_zones = None
|
||||
self._shell = None
|
||||
self._human_readable_name = None
|
||||
self._alias = None
|
||||
self._type = 'building'
|
||||
self._heating = dict()
|
||||
self._cooling = dict()
|
||||
|
@ -46,20 +48,31 @@ class Building(CityObject):
|
|||
self._roofs = []
|
||||
self._walls = []
|
||||
self._internal_walls = []
|
||||
self._ground_walls = []
|
||||
self._attic_floors = []
|
||||
self._interior_slabs = []
|
||||
for surface_id, surface in enumerate(self.surfaces):
|
||||
self._min_x = min(self._min_x, surface.lower_corner[0])
|
||||
self._min_y = min(self._min_y, surface.lower_corner[1])
|
||||
self._min_z = min(self._min_z, surface.lower_corner[2])
|
||||
surface.id = surface_id
|
||||
# todo: consider all type of surfaces, not only these four
|
||||
if surface.type == cte.GROUND:
|
||||
self._grounds.append(surface)
|
||||
elif surface.type == cte.WALL:
|
||||
self._walls.append(surface)
|
||||
elif surface.type == cte.ROOF:
|
||||
self._roofs.append(surface)
|
||||
else:
|
||||
elif surface.type == cte.INTERIOR_WALL:
|
||||
self._internal_walls.append(surface)
|
||||
elif surface.type == cte.GROUND_WALL:
|
||||
self._ground_walls.append(surface)
|
||||
elif surface.type == cte.ATTIC_FLOOR:
|
||||
self._attic_floors.append(surface)
|
||||
elif surface.type == cte.INTERIOR_SLAB:
|
||||
self._interior_slabs.append(surface)
|
||||
else:
|
||||
logger.error(f'Building {self.name} [alias {self.alias}] has an unexpected surface type {surface.type}.\n')
|
||||
sys.stderr.write(f'Building {self.name} [alias {self.alias}] has an unexpected surface type {surface.type}.\n')
|
||||
|
||||
@property
|
||||
def shell(self) -> Polyhedron:
|
||||
|
@ -397,23 +410,34 @@ class Building(CityObject):
|
|||
if self.internal_zones is None:
|
||||
return False
|
||||
for internal_zone in self.internal_zones:
|
||||
if internal_zone.usage_zones is not None:
|
||||
for usage_zone in internal_zone.usage_zones:
|
||||
if usage_zone.thermal_control is not None:
|
||||
if internal_zone.usages is not None:
|
||||
for usage in internal_zone.usages:
|
||||
if usage.thermal_control is not None:
|
||||
return True
|
||||
return False
|
||||
|
||||
@property
|
||||
def human_readable_name(self):
|
||||
def alias(self):
|
||||
"""
|
||||
Get the human-readable name for the building
|
||||
Get the alias name for the building
|
||||
:return: str
|
||||
"""
|
||||
return self._human_readable_name
|
||||
return self._alias
|
||||
|
||||
@human_readable_name.setter
|
||||
def human_readable_name(self, value):
|
||||
@alias.setter
|
||||
def alias(self, value):
|
||||
"""
|
||||
Set the human-readable name for the building
|
||||
Set the alias name for the building
|
||||
"""
|
||||
self._human_readable_name = value
|
||||
self._alias = value
|
||||
|
||||
@property
|
||||
def usages_percentage(self):
|
||||
"""
|
||||
Get the usages and percentages for the building
|
||||
"""
|
||||
_usage = ''
|
||||
for internal_zone in self.internal_zones:
|
||||
for usage in internal_zone.usages:
|
||||
_usage = f'{_usage}{usage.name}_{usage.percentage} '
|
||||
return _usage.rstrip()
|
||||
|
|
|
@ -7,7 +7,7 @@ Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
|||
|
||||
import uuid
|
||||
from typing import Union, List
|
||||
from hub.city_model_structure.building_demand.usage_zone import UsageZone
|
||||
from hub.city_model_structure.building_demand.usage import Usage
|
||||
from hub.city_model_structure.building_demand.thermal_zone import ThermalZone
|
||||
from hub.city_model_structure.attributes.polyhedron import Polyhedron
|
||||
from hub.city_model_structure.energy_systems.hvac_system import HvacSystem
|
||||
|
@ -24,7 +24,7 @@ class InternalZone:
|
|||
self._volume = None
|
||||
self._area = area
|
||||
self._thermal_zones = None
|
||||
self._usage_zones = None
|
||||
self._usages = None
|
||||
self._hvac_system = None
|
||||
|
||||
@property
|
||||
|
@ -75,20 +75,20 @@ class InternalZone:
|
|||
return self._area
|
||||
|
||||
@property
|
||||
def usage_zones(self) -> [UsageZone]:
|
||||
def usages(self) -> [Usage]:
|
||||
"""
|
||||
Get internal zone usage zones
|
||||
:return: [UsageZone]
|
||||
"""
|
||||
return self._usage_zones
|
||||
return self._usages
|
||||
|
||||
@usage_zones.setter
|
||||
def usage_zones(self, value):
|
||||
@usages.setter
|
||||
def usages(self, value):
|
||||
"""
|
||||
Set internal zone usage zones
|
||||
:param value: [UsageZone]
|
||||
"""
|
||||
self._usage_zones = value
|
||||
self._usages = value
|
||||
|
||||
@property
|
||||
def hvac_system(self) -> Union[None, HvacSystem]:
|
||||
|
|
|
@ -6,7 +6,6 @@ Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
|||
"""
|
||||
from typing import Union, List
|
||||
from hub.city_model_structure.attributes.schedule import Schedule
|
||||
from hub.city_model_structure.building_demand.occupant import Occupant
|
||||
|
||||
|
||||
class Occupancy:
|
||||
|
@ -106,19 +105,3 @@ class Occupancy:
|
|||
:param value: [Schedule]
|
||||
"""
|
||||
self._occupancy_schedules = value
|
||||
|
||||
@property
|
||||
def occupants(self) -> Union[None, List[Occupant]]:
|
||||
"""
|
||||
Get list of occupants
|
||||
:return: None or List of Occupant
|
||||
"""
|
||||
return self._occupants
|
||||
|
||||
@occupants.setter
|
||||
def occupants(self, value):
|
||||
"""
|
||||
Set list of occupants
|
||||
:param value: [Occupant]
|
||||
"""
|
||||
self._occupants = value
|
||||
|
|
|
@ -1,147 +0,0 @@
|
|||
"""
|
||||
Occupant module
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Sanam Dabirian sanam.dabirian@mail.concordia.ca
|
||||
Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
|
||||
import calendar as cal
|
||||
|
||||
|
||||
class Occupant:
|
||||
"""
|
||||
Occupant class
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
|
||||
self._heat_dissipation = None
|
||||
self._occupancy_rate = None
|
||||
self._occupant_type = None
|
||||
self._arrival_time = None
|
||||
self._departure_time = None
|
||||
self._break_time = None
|
||||
self._day_of_week = None
|
||||
self._pd_of_meetings_duration = None
|
||||
|
||||
@property
|
||||
def heat_dissipation(self):
|
||||
"""
|
||||
Get heat dissipation of occupants in W/person
|
||||
:return: float
|
||||
"""
|
||||
return self._heat_dissipation
|
||||
|
||||
@heat_dissipation.setter
|
||||
def heat_dissipation(self, value):
|
||||
"""
|
||||
Set heat dissipation of occupants in W/person
|
||||
:param value: float
|
||||
"""
|
||||
self._heat_dissipation = float(value)
|
||||
|
||||
@property
|
||||
def occupancy_rate(self):
|
||||
"""
|
||||
Get rate of schedules
|
||||
:return: float
|
||||
"""
|
||||
return self._occupancy_rate
|
||||
|
||||
@occupancy_rate.setter
|
||||
def occupancy_rate(self, value):
|
||||
"""
|
||||
Set rate of schedules
|
||||
:param value: float
|
||||
"""
|
||||
self._occupancy_rate = float(value)
|
||||
|
||||
@property
|
||||
def occupant_type(self):
|
||||
"""
|
||||
Get type of schedules
|
||||
:return: str
|
||||
"""
|
||||
return self._occupant_type
|
||||
|
||||
@occupant_type.setter
|
||||
def occupant_type(self, value):
|
||||
"""
|
||||
Set type of schedules
|
||||
:param value: float
|
||||
"""
|
||||
self._occupant_type = float(value)
|
||||
|
||||
@property
|
||||
def arrival_time(self):
|
||||
"""
|
||||
Get the arrival time of the occupant (for office building) in UTC with format YYYYMMDD HH:mm:ss
|
||||
:return: time
|
||||
"""
|
||||
return self._arrival_time
|
||||
|
||||
@arrival_time.setter
|
||||
def arrival_time(self, value):
|
||||
"""
|
||||
Set the arrival time of the occupant (for office building) in UTC with format YYYYMMDD HH:mm:ss
|
||||
:param value: time
|
||||
"""
|
||||
self._arrival_time = value
|
||||
|
||||
@property
|
||||
def departure_time(self):
|
||||
"""
|
||||
Get the departure time of the occupant (for office building) in UTC with format YYYYMMDD HH:mm:ss
|
||||
:return: time
|
||||
"""
|
||||
return self._departure_time
|
||||
|
||||
@departure_time.setter
|
||||
def departure_time(self, value):
|
||||
"""
|
||||
Set the departure time of the occupant (for office building) in UTC with format YYYYMMDD HH:mm:ss
|
||||
:param value: str
|
||||
"""
|
||||
self._departure_time = value
|
||||
|
||||
@property
|
||||
def break_time(self):
|
||||
"""
|
||||
Get the lunch or break time of the occupant (for office building) in UTC with format ????
|
||||
:return: break time
|
||||
"""
|
||||
# todo @Sanam: define this format, is it the starting time? is it a list with both, starting and ending time?
|
||||
return self._break_time
|
||||
|
||||
@property
|
||||
def day_of_week(self):
|
||||
"""
|
||||
Get the day of the week (MON, TUE, WED, THU, FRI, SAT, SUN)
|
||||
:return: str
|
||||
"""
|
||||
# todo @Sanam: is this a property or should it be a function
|
||||
# to get the day of the week of an specific day of the year?
|
||||
return self._day_of_week
|
||||
|
||||
@property
|
||||
def pd_of_meetings_duration(self):
|
||||
"""
|
||||
Get the probability distribution of the meeting duration
|
||||
:return: ??
|
||||
"""
|
||||
# todo @Sanam: what format are you expecting here??
|
||||
return self._pd_of_meetings_duration
|
||||
|
||||
@pd_of_meetings_duration.setter
|
||||
def pd_of_meetings_duration(self, value):
|
||||
"""
|
||||
Get the probability distribution of the meeting duration
|
||||
:param value: ??
|
||||
:return:
|
||||
"""
|
||||
# todo @Sanam: what format are you expecting here??
|
||||
self._pd_of_meetings_duration = value
|
|
@ -72,14 +72,6 @@ class Surface:
|
|||
if value is not None:
|
||||
self._id = str(value)
|
||||
|
||||
# todo: implement share surfaces
|
||||
@property
|
||||
def share_surfaces(self):
|
||||
"""
|
||||
Raises not implemented error
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def _max_coord(self, axis):
|
||||
if axis == 'x':
|
||||
axis = 0
|
||||
|
@ -163,11 +155,11 @@ class Surface:
|
|||
@property
|
||||
def type(self):
|
||||
"""
|
||||
Get surface type Ground, Wall or Roof
|
||||
Get surface type Ground, Ground wall, Wall, Attic floor, Interior slab, Interior wall, Roof or Virtual internal
|
||||
If the geometrical LoD is lower than 4,
|
||||
the surfaces' types are not defined in the importer and can only be Ground, Wall or Roof
|
||||
:return: str
|
||||
"""
|
||||
|
||||
# todo: there are more types: internal wall, internal floor... this method must be redefined
|
||||
if self._type is None:
|
||||
grad = np.rad2deg(self.inclination)
|
||||
if grad >= 170:
|
||||
|
@ -304,7 +296,7 @@ class Surface:
|
|||
:return: Surface, Surface, Any
|
||||
"""
|
||||
# todo: check return types
|
||||
# todo: recheck this method for LoD3 (windows)
|
||||
# recheck this method for LoD3 (windows)
|
||||
origin = Point([0, 0, z])
|
||||
normal = np.array([0, 0, 1])
|
||||
plane = Plane(normal=normal, origin=origin)
|
||||
|
|
|
@ -26,7 +26,8 @@ class ThermalZone:
|
|||
"""
|
||||
ThermalZone class
|
||||
"""
|
||||
def __init__(self, thermal_boundaries, parent_internal_zone, volume, footprint_area, usage=None):
|
||||
|
||||
def __init__(self, thermal_boundaries, parent_internal_zone, volume, footprint_area, usage_name=None):
|
||||
self._id = None
|
||||
self._parent_internal_zone = parent_internal_zone
|
||||
self._footprint_area = footprint_area
|
||||
|
@ -40,9 +41,9 @@ class ThermalZone:
|
|||
self._ordinate_number = None
|
||||
self._view_factors_matrix = None
|
||||
self._total_floor_area = None
|
||||
self._usage = usage
|
||||
self._usage_name = usage_name
|
||||
self._usage_from_parent = False
|
||||
if usage is None:
|
||||
if usage_name is None:
|
||||
self._usage_from_parent = True
|
||||
self._hours_day = None
|
||||
self._days_year = None
|
||||
|
@ -55,21 +56,21 @@ class ThermalZone:
|
|||
self._usages = None
|
||||
|
||||
@property
|
||||
def usage_zones(self):
|
||||
def usages(self):
|
||||
# example 70-office_30-residential
|
||||
if self._usage_from_parent:
|
||||
self._usages = copy.deepcopy(self._parent_internal_zone.usage_zones)
|
||||
self._usages = copy.deepcopy(self._parent_internal_zone.usages)
|
||||
else:
|
||||
values = self._usage.split('_')
|
||||
values = self._usage_name.split('_')
|
||||
usages = []
|
||||
for value in values:
|
||||
usages.append(value.split('-'))
|
||||
self._usages = []
|
||||
for parent_usage in self._parent_internal_zone.usage_zones:
|
||||
for parent_usage in self._parent_internal_zone.usages:
|
||||
for value in usages:
|
||||
if parent_usage.usage == value[1]:
|
||||
if parent_usage.name == value[1]:
|
||||
new_usage = copy.deepcopy(parent_usage)
|
||||
new_usage.percentage = float(value[0])/100
|
||||
new_usage.percentage = float(value[0]) / 100
|
||||
self._usages.append(new_usage)
|
||||
return self._usages
|
||||
|
||||
|
@ -224,19 +225,19 @@ class ThermalZone:
|
|||
self._view_factors_matrix = value
|
||||
|
||||
@property
|
||||
def usage(self) -> Union[None, str]:
|
||||
def usage_name(self) -> Union[None, str]:
|
||||
"""
|
||||
Get thermal zone usage
|
||||
Get thermal zone usage name
|
||||
:return: None or str
|
||||
"""
|
||||
if self._usage_from_parent:
|
||||
if self._parent_internal_zone.usage_zones is None:
|
||||
if self._parent_internal_zone.usages is None:
|
||||
return None
|
||||
self._usage = ''
|
||||
for usage_zone in self._parent_internal_zone.usage_zones:
|
||||
self._usage += str(round(usage_zone.percentage * 100)) + '-' + usage_zone.usage + '_'
|
||||
self._usage = self._usage[:-1]
|
||||
return self._usage
|
||||
self._usage_name = ''
|
||||
for usage in self._parent_internal_zone.usages:
|
||||
self._usage_name += str(round(usage.percentage * 100)) + '-' + usage.name + '_'
|
||||
self._usage_name = self._usage_name[:-1]
|
||||
return self._usage_name
|
||||
|
||||
@staticmethod
|
||||
def _get_schedule_of_day(requested_day_type, schedules):
|
||||
|
@ -252,12 +253,12 @@ class ThermalZone:
|
|||
Get thermal zone usage hours per day
|
||||
:return: None or float
|
||||
"""
|
||||
if self.usage_zones is None:
|
||||
if self.usages is None:
|
||||
return None
|
||||
if self._hours_day is None:
|
||||
self._hours_day = 0
|
||||
for usage_zone in self.usage_zones:
|
||||
self._hours_day += usage_zone.percentage * usage_zone.hours_day
|
||||
for usage in self.usages:
|
||||
self._hours_day += usage.percentage * usage.hours_day
|
||||
return self._hours_day
|
||||
|
||||
@property
|
||||
|
@ -266,12 +267,12 @@ class ThermalZone:
|
|||
Get thermal zone usage days per year
|
||||
:return: None or float
|
||||
"""
|
||||
if self.usage_zones is None:
|
||||
if self.usages is None:
|
||||
return None
|
||||
if self._days_year is None:
|
||||
self._days_year = 0
|
||||
for usage_zone in self.usage_zones:
|
||||
self._days_year += usage_zone.percentage * usage_zone.days_year
|
||||
for usage in self.usages:
|
||||
self._days_year += usage.percentage * usage.days_year
|
||||
return self._days_year
|
||||
|
||||
@property
|
||||
|
@ -280,14 +281,14 @@ class ThermalZone:
|
|||
Get thermal zone mechanical air change in air change per hour (ACH)
|
||||
:return: None or float
|
||||
"""
|
||||
if self.usage_zones is None:
|
||||
if self.usages is None:
|
||||
return None
|
||||
if self._mechanical_air_change is None:
|
||||
self._mechanical_air_change = 0
|
||||
for usage_zone in self.usage_zones:
|
||||
if usage_zone.mechanical_air_change is None:
|
||||
for usage in self.usages:
|
||||
if usage.mechanical_air_change is None:
|
||||
return None
|
||||
self._mechanical_air_change += usage_zone.percentage * usage_zone.mechanical_air_change
|
||||
self._mechanical_air_change += usage.percentage * usage.mechanical_air_change
|
||||
return self._mechanical_air_change
|
||||
|
||||
@property
|
||||
|
@ -296,7 +297,7 @@ class ThermalZone:
|
|||
Get occupancy in the thermal zone
|
||||
:return: None or Occupancy
|
||||
"""
|
||||
if self.usage_zones is None:
|
||||
if self.usages is None:
|
||||
return None
|
||||
|
||||
if self._occupancy is None:
|
||||
|
@ -305,29 +306,35 @@ class ThermalZone:
|
|||
_convective_part = 0
|
||||
_radiative_part = 0
|
||||
_latent_part = 0
|
||||
for usage_zone in self.usage_zones:
|
||||
if usage_zone.occupancy is None:
|
||||
for usage in self.usages:
|
||||
if usage.occupancy is None:
|
||||
return None
|
||||
_occupancy_density += usage_zone.percentage * usage_zone.occupancy.occupancy_density
|
||||
if usage_zone.occupancy.sensible_convective_internal_gain is not None:
|
||||
_convective_part += usage_zone.percentage * usage_zone.occupancy.sensible_convective_internal_gain
|
||||
_radiative_part += usage_zone.percentage * usage_zone.occupancy.sensible_radiative_internal_gain
|
||||
_latent_part += usage_zone.percentage * usage_zone.occupancy.latent_internal_gain
|
||||
_occupancy_density += usage.percentage * usage.occupancy.occupancy_density
|
||||
if usage.occupancy.sensible_convective_internal_gain is not None:
|
||||
_convective_part += usage.percentage * usage.occupancy.sensible_convective_internal_gain
|
||||
_radiative_part += usage.percentage * usage.occupancy.sensible_radiative_internal_gain
|
||||
_latent_part += usage.percentage * usage.occupancy.latent_internal_gain
|
||||
self._occupancy.occupancy_density = _occupancy_density
|
||||
self._occupancy.sensible_convective_internal_gain = _convective_part
|
||||
self._occupancy.sensible_radiative_internal_gain = _radiative_part
|
||||
self._occupancy.latent_internal_gain = _latent_part
|
||||
|
||||
_occupancy_reference = self.usage_zones[0].occupancy
|
||||
_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)):
|
||||
schedule = copy.deepcopy(_occupancy_reference.occupancy_schedules[i_schedule])
|
||||
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
|
||||
|
||||
new_values = []
|
||||
for i_value in range(0, len(_occupancy_reference.occupancy_schedules[i_schedule].values)):
|
||||
_new_value = 0
|
||||
for usage_zone in self.usage_zones:
|
||||
_new_value += usage_zone.percentage * usage_zone.occupancy.occupancy_schedules[i_schedule].values[i_value]
|
||||
for usage in self.usages:
|
||||
_new_value += usage.percentage * usage.occupancy.occupancy_schedules[i_schedule].values[i_value]
|
||||
new_values.append(_new_value)
|
||||
schedule.values = new_values
|
||||
_schedules.append(schedule)
|
||||
|
@ -340,7 +347,7 @@ class ThermalZone:
|
|||
Get lighting information
|
||||
:return: None or Lighting
|
||||
"""
|
||||
if self.usage_zones is None:
|
||||
if self.usages is None:
|
||||
return None
|
||||
|
||||
if self._lighting is None:
|
||||
|
@ -349,17 +356,17 @@ class ThermalZone:
|
|||
_convective_part = 0
|
||||
_radiative_part = 0
|
||||
_latent_part = 0
|
||||
for usage_zone in self.usage_zones:
|
||||
if usage_zone.lighting is None:
|
||||
for usage in self.usages:
|
||||
if usage.lighting is None:
|
||||
return None
|
||||
_lighting_density += usage_zone.percentage * usage_zone.lighting.density
|
||||
if usage_zone.lighting.convective_fraction is not None:
|
||||
_convective_part += usage_zone.percentage * usage_zone.lighting.density \
|
||||
* usage_zone.lighting.convective_fraction
|
||||
_radiative_part += usage_zone.percentage * usage_zone.lighting.density \
|
||||
* usage_zone.lighting.radiative_fraction
|
||||
_latent_part += usage_zone.percentage * usage_zone.lighting.density \
|
||||
* usage_zone.lighting.latent_fraction
|
||||
_lighting_density += usage.percentage * usage.lighting.density
|
||||
if usage.lighting.convective_fraction is not None:
|
||||
_convective_part += usage.percentage * usage.lighting.density \
|
||||
* usage.lighting.convective_fraction
|
||||
_radiative_part += usage.percentage * usage.lighting.density \
|
||||
* usage.lighting.radiative_fraction
|
||||
_latent_part += usage.percentage * usage.lighting.density \
|
||||
* usage.lighting.latent_fraction
|
||||
self._lighting.density = _lighting_density
|
||||
if _lighting_density > 0:
|
||||
self._lighting.convective_fraction = _convective_part / _lighting_density
|
||||
|
@ -370,16 +377,22 @@ class ThermalZone:
|
|||
self._lighting.radiative_fraction = 0
|
||||
self._lighting.latent_fraction = 0
|
||||
|
||||
_lighting_reference = self.usage_zones[0].lighting
|
||||
_lighting_reference = self.usages[0].lighting
|
||||
if _lighting_reference.schedules is not None:
|
||||
_schedules = []
|
||||
for i_schedule in range(0, len(_lighting_reference.schedules)):
|
||||
schedule = copy.deepcopy(_lighting_reference.schedules[i_schedule])
|
||||
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
|
||||
|
||||
new_values = []
|
||||
for i_value in range(0, len(_lighting_reference.schedules[i_schedule].values)):
|
||||
_new_value = 0
|
||||
for usage_zone in self.usage_zones:
|
||||
_new_value += usage_zone.percentage * usage_zone.lighting.schedules[i_schedule].values[i_value]
|
||||
for usage in self.usages:
|
||||
_new_value += usage.percentage * usage.lighting.schedules[i_schedule].values[i_value]
|
||||
new_values.append(_new_value)
|
||||
schedule.values = new_values
|
||||
_schedules.append(schedule)
|
||||
|
@ -392,7 +405,7 @@ class ThermalZone:
|
|||
Get appliances information
|
||||
:return: None or Appliances
|
||||
"""
|
||||
if self.usage_zones is None:
|
||||
if self.usages is None:
|
||||
return None
|
||||
|
||||
if self._appliances is None:
|
||||
|
@ -401,17 +414,17 @@ class ThermalZone:
|
|||
_convective_part = 0
|
||||
_radiative_part = 0
|
||||
_latent_part = 0
|
||||
for usage_zone in self.usage_zones:
|
||||
if usage_zone.appliances is None:
|
||||
for usage in self.usages:
|
||||
if usage.appliances is None:
|
||||
return None
|
||||
_appliances_density += usage_zone.percentage * usage_zone.appliances.density
|
||||
if usage_zone.appliances.convective_fraction is not None:
|
||||
_convective_part += usage_zone.percentage * usage_zone.appliances.density \
|
||||
* usage_zone.appliances.convective_fraction
|
||||
_radiative_part += usage_zone.percentage * usage_zone.appliances.density \
|
||||
* usage_zone.appliances.radiative_fraction
|
||||
_latent_part += usage_zone.percentage * usage_zone.appliances.density \
|
||||
* usage_zone.appliances.latent_fraction
|
||||
_appliances_density += usage.percentage * usage.appliances.density
|
||||
if usage.appliances.convective_fraction is not None:
|
||||
_convective_part += usage.percentage * usage.appliances.density \
|
||||
* usage.appliances.convective_fraction
|
||||
_radiative_part += usage.percentage * usage.appliances.density \
|
||||
* usage.appliances.radiative_fraction
|
||||
_latent_part += usage.percentage * usage.appliances.density \
|
||||
* usage.appliances.latent_fraction
|
||||
self._appliances.density = _appliances_density
|
||||
if _appliances_density > 0:
|
||||
self._appliances.convective_fraction = _convective_part / _appliances_density
|
||||
|
@ -422,16 +435,22 @@ class ThermalZone:
|
|||
self._appliances.radiative_fraction = 0
|
||||
self._appliances.latent_fraction = 0
|
||||
|
||||
_appliances_reference = self.usage_zones[0].appliances
|
||||
_appliances_reference = self.usages[0].appliances
|
||||
if _appliances_reference.schedules is not None:
|
||||
_schedules = []
|
||||
for i_schedule in range(0, len(_appliances_reference.schedules)):
|
||||
schedule = copy.deepcopy(_appliances_reference.schedules[i_schedule])
|
||||
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
|
||||
|
||||
new_values = []
|
||||
for i_value in range(0, len(_appliances_reference.schedules[i_schedule].values)):
|
||||
_new_value = 0
|
||||
for usage_zone in self.usage_zones:
|
||||
_new_value += usage_zone.percentage * usage_zone.appliances.schedules[i_schedule].values[i_value]
|
||||
for usage in self.usages:
|
||||
_new_value += usage.percentage * usage.appliances.schedules[i_schedule].values[i_value]
|
||||
new_values.append(_new_value)
|
||||
schedule.values = new_values
|
||||
_schedules.append(schedule)
|
||||
|
@ -444,7 +463,7 @@ class ThermalZone:
|
|||
Calculates and returns the list of all internal gains defined
|
||||
:return: [InternalGain]
|
||||
"""
|
||||
if self.usage_zones is None:
|
||||
if self.usages is None:
|
||||
return None
|
||||
|
||||
if self._internal_gains is None:
|
||||
|
@ -462,17 +481,17 @@ class ThermalZone:
|
|||
_base_schedule.data_type = cte.ANY_NUMBER
|
||||
_schedules_defined = True
|
||||
values = numpy.zeros([24, 8])
|
||||
for usage_zone in self.usage_zones:
|
||||
for internal_gain in usage_zone.internal_gains:
|
||||
_average_internal_gain += internal_gain.average_internal_gain * usage_zone.percentage
|
||||
_convective_fraction += internal_gain.average_internal_gain * usage_zone.percentage \
|
||||
for usage in self.usages:
|
||||
for internal_gain in usage.internal_gains:
|
||||
_average_internal_gain += internal_gain.average_internal_gain * usage.percentage
|
||||
_convective_fraction += internal_gain.average_internal_gain * usage.percentage \
|
||||
* internal_gain.convective_fraction
|
||||
_radiative_fraction += internal_gain.average_internal_gain * usage_zone.percentage \
|
||||
_radiative_fraction += internal_gain.average_internal_gain * usage.percentage \
|
||||
* internal_gain.radiative_fraction
|
||||
_latent_fraction += internal_gain.average_internal_gain * usage_zone.percentage \
|
||||
_latent_fraction += internal_gain.average_internal_gain * usage.percentage \
|
||||
* internal_gain.latent_fraction
|
||||
for usage_zone in self.usage_zones:
|
||||
for internal_gain in usage_zone.internal_gains:
|
||||
for usage in self.usages:
|
||||
for internal_gain in usage.internal_gains:
|
||||
if internal_gain.schedules is None:
|
||||
_schedules_defined = False
|
||||
break
|
||||
|
@ -481,7 +500,7 @@ class ThermalZone:
|
|||
break
|
||||
for day, _schedule in enumerate(internal_gain.schedules):
|
||||
for v, value in enumerate(_schedule.values):
|
||||
values[v, day] += value * usage_zone.percentage
|
||||
values[v, day] += value * usage.percentage
|
||||
|
||||
if _schedules_defined:
|
||||
_schedules = []
|
||||
|
@ -506,7 +525,7 @@ class ThermalZone:
|
|||
Get thermal control of this thermal zone
|
||||
:return: None or ThermalControl
|
||||
"""
|
||||
if self.usage_zones is None:
|
||||
if self.usages is None:
|
||||
return None
|
||||
|
||||
if self._thermal_control is None:
|
||||
|
@ -514,15 +533,15 @@ class ThermalZone:
|
|||
_mean_heating_set_point = 0
|
||||
_heating_set_back = 0
|
||||
_mean_cooling_set_point = 0
|
||||
for usage_zone in self.usage_zones:
|
||||
_mean_heating_set_point += usage_zone.percentage * usage_zone.thermal_control.mean_heating_set_point
|
||||
_heating_set_back += usage_zone.percentage * usage_zone.thermal_control.heating_set_back
|
||||
_mean_cooling_set_point += usage_zone.percentage * usage_zone.thermal_control.mean_cooling_set_point
|
||||
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.usage_zones[0].thermal_control
|
||||
_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])
|
||||
|
@ -535,20 +554,26 @@ class ThermalZone:
|
|||
_schedules = []
|
||||
_schedule_type = _types_reference[i_type][1]
|
||||
for i_schedule in range(0, len(_schedule_type)):
|
||||
schedule = copy.deepcopy(_schedule_type[i_schedule])
|
||||
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_zone in self.usage_zones:
|
||||
for usage in self.usages:
|
||||
if _types_reference[i_type][0] == cte.HVAC_AVAILABILITY:
|
||||
_new_value += usage_zone.percentage * \
|
||||
usage_zone.thermal_control.hvac_availability_schedules[i_schedule].values[i_value]
|
||||
_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_zone.percentage * \
|
||||
usage_zone.thermal_control.heating_set_point_schedules[i_schedule].values[i_value]
|
||||
_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_zone.percentage * \
|
||||
usage_zone.thermal_control.cooling_set_point_schedules[i_schedule].values[i_value]
|
||||
_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)
|
||||
|
|
246
hub/city_model_structure/building_demand/usage.py
Normal file
246
hub/city_model_structure/building_demand/usage.py
Normal file
|
@ -0,0 +1,246 @@
|
|||
"""
|
||||
Usage 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
|
||||
Code contributors: Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
||||
"""
|
||||
import uuid
|
||||
from typing import Union, List
|
||||
import hub.helpers.constants as cte
|
||||
from hub.city_model_structure.building_demand.occupancy import Occupancy
|
||||
from hub.city_model_structure.building_demand.lighting import Lighting
|
||||
from hub.city_model_structure.building_demand.appliances import Appliances
|
||||
from hub.city_model_structure.building_demand.thermal_control import ThermalControl
|
||||
from hub.city_model_structure.building_demand.internal_gain import InternalGain
|
||||
|
||||
|
||||
class Usage:
|
||||
"""
|
||||
Usage class
|
||||
"""
|
||||
def __init__(self):
|
||||
self._id = None
|
||||
self._name = None
|
||||
self._percentage = None
|
||||
self._internal_gains = None
|
||||
self._hours_day = None
|
||||
self._days_year = None
|
||||
self._mechanical_air_change = None
|
||||
self._occupancy = None
|
||||
self._lighting = None
|
||||
self._appliances = None
|
||||
self._thermal_control = None
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
"""
|
||||
Get usage zone id, a universally unique identifier randomly generated
|
||||
:return: str
|
||||
"""
|
||||
if self._id is None:
|
||||
self._id = uuid.uuid4()
|
||||
return self._id
|
||||
|
||||
@property
|
||||
def name(self) -> Union[None, str]:
|
||||
"""
|
||||
Get usage zone usage
|
||||
:return: None or str
|
||||
"""
|
||||
return self._name
|
||||
|
||||
@name.setter
|
||||
def name(self, value):
|
||||
"""
|
||||
Set usage zone usage
|
||||
:param value: str
|
||||
"""
|
||||
if value is not None:
|
||||
self._name = str(value)
|
||||
|
||||
@property
|
||||
def percentage(self):
|
||||
"""
|
||||
Get usage zone percentage in range[0,1]
|
||||
:return: float
|
||||
"""
|
||||
return self._percentage
|
||||
|
||||
@percentage.setter
|
||||
def percentage(self, value):
|
||||
"""
|
||||
Set usage zone percentage in range[0,1]
|
||||
:param value: float
|
||||
"""
|
||||
if value is not None:
|
||||
self._percentage = float(value)
|
||||
|
||||
@property
|
||||
def internal_gains(self) -> List[InternalGain]:
|
||||
"""
|
||||
Calculates and returns the list of all internal gains defined
|
||||
:return: InternalGains
|
||||
"""
|
||||
if self._internal_gains is None:
|
||||
if self.occupancy is not None:
|
||||
if self.occupancy.latent_internal_gain is not None:
|
||||
_internal_gain = InternalGain()
|
||||
_internal_gain.type = cte.OCCUPANCY
|
||||
_total_heat_gain = (self.occupancy.sensible_convective_internal_gain
|
||||
+ self.occupancy.sensible_radiative_internal_gain
|
||||
+ self.occupancy.latent_internal_gain)
|
||||
_internal_gain.average_internal_gain = _total_heat_gain
|
||||
_internal_gain.latent_fraction = self.occupancy.latent_internal_gain / _total_heat_gain
|
||||
_internal_gain.radiative_fraction = self.occupancy.sensible_radiative_internal_gain / _total_heat_gain
|
||||
_internal_gain.convective_fraction = self.occupancy.sensible_convective_internal_gain / _total_heat_gain
|
||||
_internal_gain.schedules = self.occupancy.occupancy_schedules
|
||||
self._internal_gains = [_internal_gain]
|
||||
if self.lighting is not None:
|
||||
_internal_gain = InternalGain()
|
||||
_internal_gain.type = cte.LIGHTING
|
||||
_internal_gain.average_internal_gain = self.lighting.density
|
||||
_internal_gain.latent_fraction = self.lighting.latent_fraction
|
||||
_internal_gain.radiative_fraction = self.lighting.radiative_fraction
|
||||
_internal_gain.convective_fraction = self.lighting.convective_fraction
|
||||
_internal_gain.schedules = self.lighting.schedules
|
||||
if self._internal_gains is not None:
|
||||
self._internal_gains.append(_internal_gain)
|
||||
else:
|
||||
self._internal_gains = [_internal_gain]
|
||||
if self.appliances is not None:
|
||||
_internal_gain = InternalGain()
|
||||
_internal_gain.type = cte.APPLIANCES
|
||||
_internal_gain.average_internal_gain = self.appliances.density
|
||||
_internal_gain.latent_fraction = self.appliances.latent_fraction
|
||||
_internal_gain.radiative_fraction = self.appliances.radiative_fraction
|
||||
_internal_gain.convective_fraction = self.appliances.convective_fraction
|
||||
_internal_gain.schedules = self.appliances.schedules
|
||||
if self._internal_gains is not None:
|
||||
self._internal_gains.append(_internal_gain)
|
||||
else:
|
||||
self._internal_gains = [_internal_gain]
|
||||
return self._internal_gains
|
||||
|
||||
@internal_gains.setter
|
||||
def internal_gains(self, value):
|
||||
"""
|
||||
Set usage zone internal gains
|
||||
:param value: [InternalGain]
|
||||
"""
|
||||
self._internal_gains = value
|
||||
|
||||
@property
|
||||
def hours_day(self) -> Union[None, float]:
|
||||
"""
|
||||
Get usage zone usage hours per day
|
||||
:return: None or float
|
||||
"""
|
||||
return self._hours_day
|
||||
|
||||
@hours_day.setter
|
||||
def hours_day(self, value):
|
||||
"""
|
||||
Set usage zone usage hours per day
|
||||
:param value: float
|
||||
"""
|
||||
if value is not None:
|
||||
self._hours_day = float(value)
|
||||
|
||||
@property
|
||||
def days_year(self) -> Union[None, float]:
|
||||
"""
|
||||
Get usage zone usage days per year
|
||||
:return: None or float
|
||||
"""
|
||||
return self._days_year
|
||||
|
||||
@days_year.setter
|
||||
def days_year(self, value):
|
||||
"""
|
||||
Set usage zone usage days per year
|
||||
:param value: float
|
||||
"""
|
||||
if value is not None:
|
||||
self._days_year = float(value)
|
||||
|
||||
@property
|
||||
def mechanical_air_change(self) -> Union[None, float]:
|
||||
"""
|
||||
Get usage zone mechanical air change in air change per hour (ACH)
|
||||
:return: None or float
|
||||
"""
|
||||
return self._mechanical_air_change
|
||||
|
||||
@mechanical_air_change.setter
|
||||
def mechanical_air_change(self, value):
|
||||
"""
|
||||
Set usage zone mechanical air change in air change per hour (ACH)
|
||||
:param value: float
|
||||
"""
|
||||
if value is not None:
|
||||
self._mechanical_air_change = float(value)
|
||||
|
||||
@property
|
||||
def occupancy(self) -> Union[None, Occupancy]:
|
||||
"""
|
||||
Get occupancy in the usage zone
|
||||
:return: None or Occupancy
|
||||
"""
|
||||
return self._occupancy
|
||||
|
||||
@occupancy.setter
|
||||
def occupancy(self, value):
|
||||
"""
|
||||
Set occupancy in the usage zone
|
||||
:param value: Occupancy
|
||||
"""
|
||||
self._occupancy = value
|
||||
|
||||
@property
|
||||
def lighting(self) -> Union[None, Lighting]:
|
||||
"""
|
||||
Get lighting information
|
||||
:return: None or Lighting
|
||||
"""
|
||||
return self._lighting
|
||||
|
||||
@lighting.setter
|
||||
def lighting(self, value):
|
||||
"""
|
||||
Set lighting information
|
||||
:param value: Lighting
|
||||
"""
|
||||
self._lighting = value
|
||||
|
||||
@property
|
||||
def appliances(self) -> Union[None, Appliances]:
|
||||
"""
|
||||
Get appliances information
|
||||
:return: None or Appliances
|
||||
"""
|
||||
return self._appliances
|
||||
|
||||
@appliances.setter
|
||||
def appliances(self, value):
|
||||
"""
|
||||
Set appliances information
|
||||
:param value: Appliances
|
||||
"""
|
||||
self._appliances = value
|
||||
|
||||
@property
|
||||
def thermal_control(self) -> Union[None, ThermalControl]:
|
||||
"""
|
||||
Get thermal control of this thermal zone
|
||||
:return: None or ThermalControl
|
||||
"""
|
||||
return self._thermal_control
|
||||
|
||||
@thermal_control.setter
|
||||
def thermal_control(self, value):
|
||||
"""
|
||||
Set thermal control for this thermal zone
|
||||
:param value: ThermalControl
|
||||
"""
|
||||
self._thermal_control = value
|
|
@ -26,7 +26,6 @@ class UsageZone:
|
|||
self._internal_gains = None
|
||||
self._hours_day = None
|
||||
self._days_year = None
|
||||
# self._electrical_app_average_consumption_sqm_year = None
|
||||
self._mechanical_air_change = None
|
||||
self._occupancy = None
|
||||
self._lighting = None
|
||||
|
|
|
@ -17,8 +17,8 @@ class BusSystem(CityObject):
|
|||
"""
|
||||
BusSystem(CityObject) class
|
||||
"""
|
||||
def __init__(self, name, surfaces, city_lower_corner):
|
||||
super().__init__(name, surfaces, city_lower_corner)
|
||||
def __init__(self, name, surfaces):
|
||||
super().__init__(name, surfaces)
|
||||
self._bus_routes = None
|
||||
self._bus_network = None
|
||||
self._buses = None
|
||||
|
|
|
@ -6,6 +6,8 @@ Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
|||
Code contributors: Peter Yefi peteryefi@gmail.com
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import bz2
|
||||
import sys
|
||||
import pickle
|
||||
import math
|
||||
|
@ -23,7 +25,6 @@ from hub.city_model_structure.iot.station import Station
|
|||
from hub.city_model_structure.level_of_detail import LevelOfDetail
|
||||
from hub.city_model_structure.machine import Machine
|
||||
from hub.city_model_structure.parts_consisting_building import PartsConsistingBuilding
|
||||
from hub.city_model_structure.subway_entrance import SubwayEntrance
|
||||
from hub.helpers.geometry_helper import GeometryHelper
|
||||
from hub.helpers.location import Location
|
||||
from hub.city_model_structure.energy_system import EnergySystem
|
||||
|
@ -40,10 +41,7 @@ class City:
|
|||
self._lower_corner = lower_corner
|
||||
self._upper_corner = upper_corner
|
||||
self._buildings = None
|
||||
self._subway_entrances = None
|
||||
self._srs_name = srs_name
|
||||
self._geometry = GeometryHelper()
|
||||
# todo: right now extracted at city level, in the future should be extracted also at building level if exist
|
||||
self._location = None
|
||||
self._country_code = None
|
||||
self._climate_reference_city = None
|
||||
|
@ -102,13 +100,19 @@ class City:
|
|||
"""
|
||||
return self._get_location().country
|
||||
|
||||
@property
|
||||
def location(self):
|
||||
return self._get_location().city
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""
|
||||
Get city name
|
||||
:return: str
|
||||
"""
|
||||
return self._get_location().city
|
||||
if self._name is None:
|
||||
return self._get_location().city
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def climate_reference_city(self) -> Union[None, str]:
|
||||
|
@ -158,9 +162,6 @@ class City:
|
|||
if self.buildings is not None:
|
||||
for building in self.buildings:
|
||||
self._city_objects.append(building)
|
||||
if self.subway_entrances is not None:
|
||||
for subway_entrance in self.subway_entrances:
|
||||
self._city_objects.append(subway_entrance)
|
||||
if self.energy_systems is not None:
|
||||
for energy_system in self.energy_systems:
|
||||
self._city_objects.append(energy_system)
|
||||
|
@ -174,14 +175,6 @@ class City:
|
|||
"""
|
||||
return self._buildings
|
||||
|
||||
@property
|
||||
def subway_entrances(self) -> Union[List[SubwayEntrance], None]:
|
||||
"""
|
||||
Get the subway entrances belonging to the city
|
||||
:return: a list of subway entrances objects or none
|
||||
"""
|
||||
return self._subway_entrances
|
||||
|
||||
@property
|
||||
def lower_corner(self) -> List[float]:
|
||||
"""
|
||||
|
@ -219,10 +212,6 @@ class City:
|
|||
if self._buildings is None:
|
||||
self._buildings = []
|
||||
self._buildings.append(new_city_object)
|
||||
elif new_city_object.type == 'subway_entrance':
|
||||
if self._subway_entrances is None:
|
||||
self._subway_entrances = []
|
||||
self._subway_entrances.append(new_city_object)
|
||||
elif new_city_object.type == 'energy_system':
|
||||
if self._energy_systems is None:
|
||||
self._energy_systems = []
|
||||
|
@ -280,6 +269,15 @@ class City:
|
|||
with open(city_filename, 'wb') as file:
|
||||
pickle.dump(self, file)
|
||||
|
||||
def save_compressed(self, city_filename):
|
||||
"""
|
||||
Save a city into the given filename
|
||||
:param city_filename: destination city filename
|
||||
:return: None
|
||||
"""
|
||||
with bz2.BZ2File(city_filename, 'wb') as f:
|
||||
pickle.dump(self, f)
|
||||
|
||||
def region(self, center, radius) -> City:
|
||||
"""
|
||||
Get a region from the city
|
||||
|
|
|
@ -224,5 +224,3 @@ class CityObject:
|
|||
:param value: [Sensor]
|
||||
"""
|
||||
self._sensors = value
|
||||
|
||||
|
||||
|
|
|
@ -43,4 +43,3 @@ class Fuel:
|
|||
:return: str
|
||||
"""
|
||||
return self._unit
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ Copyright © 2022 Concordia CERC group
|
|||
Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
||||
"""
|
||||
|
||||
|
||||
class SensorMeasure:
|
||||
def __init__(self, latitude, longitude, utc_timestamp, value):
|
||||
self._latitude = latitude
|
||||
|
|
|
@ -7,6 +7,7 @@ Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
|||
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class SensorType(Enum):
|
||||
HUMIDITY = 0
|
||||
TEMPERATURE = 1
|
||||
|
|
|
@ -26,7 +26,7 @@ class Station:
|
|||
return self._id
|
||||
|
||||
@property
|
||||
def _mobile(self):
|
||||
def mobile(self):
|
||||
"""
|
||||
Get if the station is mobile or not
|
||||
:return: bool
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
"""
|
||||
LifeCycleAssessment retrieve the specific Life Cycle Assessment module for the given region
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Atiya atiya.atiya@mail.concordia.ca
|
||||
"""
|
||||
from hub.city_model_structure.machine import Machine
|
||||
|
||||
|
||||
class LcaCalculations:
|
||||
"""
|
||||
LCA Calculations class
|
||||
"""
|
||||
def emission_disposal_machines(self, ):
|
||||
return Machine.work_efficiency * Machine.energy_consumption_rate * Machine.carbon_emission_factor
|
||||
|
||||
def emission_transportation(self, weight, distance ):
|
||||
return weight * distance * Machine.energy_consumption_rate * Machine.carbon_emission_factor
|
||||
|
||||
|
||||
|
|
@ -14,6 +14,8 @@ class LevelOfDetail:
|
|||
self._geometry = None
|
||||
self._construction = None
|
||||
self._usage = None
|
||||
self._weather = None
|
||||
self._surface_radiation = None
|
||||
|
||||
@property
|
||||
def geometry(self):
|
||||
|
@ -59,3 +61,33 @@ class LevelOfDetail:
|
|||
Set the city minimal usage level of detail, 1 or 2
|
||||
"""
|
||||
self._usage = value
|
||||
|
||||
@property
|
||||
def weather(self):
|
||||
"""
|
||||
Get the city minimal weather level of detail, 0 (yearly), 1 (monthly), 2 (hourly)
|
||||
:return: int
|
||||
"""
|
||||
return self._weather
|
||||
|
||||
@weather.setter
|
||||
def weather(self, value):
|
||||
"""
|
||||
Set the city minimal weather level of detail, 0 (yearly), 1 (monthly), 2 (hourly)
|
||||
"""
|
||||
self._usage = value
|
||||
|
||||
@property
|
||||
def surface_radiation(self):
|
||||
"""
|
||||
Get the city minimal surface radiation level of detail, 0 (yearly), 1 (monthly), 2 (hourly)
|
||||
:return: int
|
||||
"""
|
||||
return self._surface_radiation
|
||||
|
||||
@surface_radiation.setter
|
||||
def surface_radiation(self, value):
|
||||
"""
|
||||
Set the city minimal surface radiation level of detail, 0 (yearly), 1 (monthly), 2 (hourly)
|
||||
"""
|
||||
self._surface_radiation = value
|
||||
|
|
|
@ -11,8 +11,8 @@ class Machine:
|
|||
Machine class
|
||||
"""
|
||||
|
||||
def __init__(self, machine_id, name, work_efficiency, work_efficiency_unit, energy_consumption_rate, energy_consumption_unit,
|
||||
carbon_emission_factor, carbon_emission_unit):
|
||||
def __init__(self, machine_id, name, work_efficiency, work_efficiency_unit, energy_consumption_rate,
|
||||
energy_consumption_unit, carbon_emission_factor, carbon_emission_unit):
|
||||
self._machine_id = machine_id
|
||||
self._name = name
|
||||
self._work_efficiency = work_efficiency
|
||||
|
@ -85,4 +85,3 @@ class Machine:
|
|||
:return: str
|
||||
"""
|
||||
return self._carbon_emission_unit
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ class Network(CityObject):
|
|||
Generic network class to be used as base for the network models
|
||||
"""
|
||||
def __init__(self, name, edges=None, nodes=None):
|
||||
super().__init__(name, 0, [], None)
|
||||
super().__init__(name, 0)
|
||||
if nodes is None:
|
||||
nodes = []
|
||||
if edges is None:
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
"""
|
||||
Subway entrance 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
|
||||
"""
|
||||
from hub.city_model_structure.city_object import CityObject
|
||||
|
||||
|
||||
class SubwayEntrance(CityObject):
|
||||
"""
|
||||
SubwayEntrance(CityObject) class
|
||||
"""
|
||||
def __init__(self, name, latitude, longitude):
|
||||
super().__init__(name, 0, [])
|
||||
self._name = name
|
||||
self._latitude = latitude
|
||||
self._longitude = longitude
|
||||
self._type = 'subway_entrance'
|
||||
|
||||
@property
|
||||
def latitude(self):
|
||||
# todo: to be defined the spacial point and the units
|
||||
"""
|
||||
Get latitude
|
||||
:return: float
|
||||
"""
|
||||
return self._latitude
|
||||
|
||||
@property
|
||||
def longitude(self):
|
||||
# todo: to be defined the spacial point and the units
|
||||
"""
|
||||
Get longitude
|
||||
:return: float
|
||||
"""
|
||||
return self._longitude
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""
|
||||
Get name
|
||||
:return: str
|
||||
"""
|
||||
return self._name
|
|
@ -10,7 +10,8 @@ class Vehicle:
|
|||
Vehicle class
|
||||
"""
|
||||
|
||||
def __init__(self, vehicle_id, name, fuel_consumption_rate, fuel_consumption_unit, carbon_emission_factor, carbon_emission_factor_unit):
|
||||
def __init__(self, vehicle_id, name, fuel_consumption_rate, fuel_consumption_unit, carbon_emission_factor,
|
||||
carbon_emission_factor_unit):
|
||||
self._vehicle_id = vehicle_id
|
||||
self._name = name
|
||||
self._fuel_consumption_rate = fuel_consumption_rate
|
||||
|
@ -59,10 +60,9 @@ class Vehicle:
|
|||
return self._carbon_emission_factor
|
||||
|
||||
@property
|
||||
def carbon_emission_unit(self) -> str:
|
||||
def carbon_emission_factor_unit(self) -> str:
|
||||
"""
|
||||
Get carbon emission units
|
||||
:return: str
|
||||
"""
|
||||
return self._carbon_emission_unit
|
||||
|
||||
return self._carbon_emission_factor_unit
|
||||
|
|
76
hub/data/construction/nrcan.xml
Normal file
76
hub/data/construction/nrcan.xml
Normal file
|
@ -0,0 +1,76 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<nrcan base_url_archetypes="https://raw.githubusercontent.com/canmet-energy/necb-2011-baselines/master/output/"
|
||||
base_url_construction="https://raw.githubusercontent.com/NREL/openstudio-standards/master/lib/openstudio-standards/standards/necb/">
|
||||
<standards_per_period>
|
||||
<standard period_of_construction="1000_1979">
|
||||
<constructions_location>BTAPPRE1980/data/surface_thermal_transmittance.json</constructions_location>
|
||||
<g_value_location>BTAPPRE1980/data/window_characteristics.json</g_value_location>
|
||||
</standard>
|
||||
<standard period_of_construction="1980_2010">
|
||||
<constructions_location>BTAP1980TO2010/data/surface_thermal_transmittance.json</constructions_location>
|
||||
<g_value_location>BTAP1980TO2010/data/window_characteristics.json</g_value_location>
|
||||
</standard>
|
||||
<standard period_of_construction="2011_2016">
|
||||
<constructions_location>NECB2011/data/surface_thermal_transmittance.json</constructions_location>
|
||||
<g_value_location>BTAP1980TO2010/data/window_characteristics.json</g_value_location>
|
||||
</standard>
|
||||
<standard period_of_construction="2017_2019">
|
||||
<constructions_location>NECB2017/data/surface_thermal_transmittance.json</constructions_location>
|
||||
<g_value_location>BTAP1980TO2010/data/window_characteristics.json</g_value_location>
|
||||
</standard>
|
||||
<standard period_of_construction="2020_3000">
|
||||
<constructions_location>NECB2020/data/surface_thermal_transmittance.json</constructions_location>
|
||||
<g_value_location>BTAP1980TO2010/data/window_characteristics.json</g_value_location>
|
||||
</standard>
|
||||
</standards_per_period>
|
||||
<standards_per_function>
|
||||
<standard function="FullServiceRestaurant">
|
||||
<file_location>FullServiceRestaurant/CAN_PQ_Montreal.Intl.AP.716270_CWEC/os_report/8414706d-3ba9-4d70-ad3c-4db62d865e1b-os-report.html</file_location>
|
||||
</standard>
|
||||
<standard function="HighriseApartment">
|
||||
<file_location>HighriseApartment/CAN_PQ_Montreal.Intl.AP.716270_CWEC/os_report/83ab3764-046e-48a8-85cd-a3c0ac761efa-os-report.html</file_location>
|
||||
</standard>
|
||||
<standard function="Hospital">
|
||||
<file_location>Hospital/CAN_PQ_Montreal.Intl.AP.716270_CWEC/os_report/210dac7e-2d51-40a9-bc78-ad0bc1c57a89-os-report.html</file_location>
|
||||
</standard>
|
||||
<standard function="LargeHotel">
|
||||
<file_location>LargeHotel/CAN_PQ_Montreal.Intl.AP.716270_CWEC/os_report/d0185276-7fe0-4da9-bb5d-8c8a7c13c405-os-report.html</file_location>
|
||||
</standard>
|
||||
<standard function="LargeOffice">
|
||||
<file_location>LargeOffice/CAN_PQ_Montreal.Intl.AP.716270_CWEC/os_report/2da33707-50a7-4554-91ed-c5fdbc1ce3b9-os-report.html</file_location>
|
||||
</standard>
|
||||
<standard function="MediumOffice">
|
||||
<file_location>MediumOffice/CAN_PQ_Montreal.Intl.AP.716270_CWEC/os_report/65d97bf8-8749-410b-b53d-5a9c60e0227c-os-report.html</file_location>
|
||||
</standard>
|
||||
<standard function="MidriseApartment">
|
||||
<file_location>MidriseApartment/CAN_PQ_Montreal.Intl.AP.716270_CWEC/os_report/19518153-9c28-4e40-8bbd-98ef949c1bdb-os-report.html</file_location>
|
||||
</standard>
|
||||
<standard function="Outpatient">
|
||||
<file_location>Outpatient/CAN_PQ_Montreal.Intl.AP.716270_CWEC/os_report/deab93c7-d086-432d-bb90-33c8c4e1fab3-os-report.html</file_location>
|
||||
</standard>
|
||||
<standard function="PrimarySchool">
|
||||
<file_location>PrimarySchool/CAN_PQ_Montreal.Intl.AP.716270_CWEC/os_report/87f45397-5ef4-4df9-be41-d33c4b6d2fb7-os-report.html</file_location>
|
||||
</standard>
|
||||
<standard function="QuickServiceRestaurant">
|
||||
<file_location>QuickServiceRestaurant/CAN_PQ_Montreal.Intl.AP.716270_CWEC/ 0bc55858-a81b-4d07-9923-1d84e8a23194-os-report.html</file_location>
|
||||
</standard>
|
||||
<standard function="RetailStandalone">
|
||||
<file_location>RetailStandalone/CAN_PQ_Montreal.Intl.AP.716270_CWEC/os_report/a3643bcb-0eea-47d4-b6b9-253ed188ec0c-os-report.html</file_location>
|
||||
</standard>
|
||||
<standard function="RetailStripmall">
|
||||
<file_location>RetailStripmall/CAN_PQ_Montreal.Intl.AP.716270_CWEC/os_report/ebaf5a16-00af-49de-9672-6b373fc825be-os-report.html</file_location>
|
||||
</standard>
|
||||
<standard function="SecondarySchool">
|
||||
<file_location>SecondarySchool/CAN_PQ_Montreal.Intl.AP.716270_CWEC/os_report/3a4f105f-93ed-4b8b-9eb3-c8ca40c5de6e-os-report.html</file_location>
|
||||
</standard>
|
||||
<standard function="SmallHotel">
|
||||
<file_location>SmallHotel/CAN_PQ_Montreal.Intl.AP.716270_CWEC/os_report/dff0a3fc-d9e5-4866-9e6a-dee9a0da60b2-os-report.html</file_location>
|
||||
</standard>
|
||||
<standard function="SmallOffice">
|
||||
<file_location>SmallOffice/CAN_PQ_Montreal.Intl.AP.716270_CWEC/os_report/a9a3669d-beb8-4951-aa11-c27dbc61a344-os-report.html</file_location>
|
||||
</standard>
|
||||
<standard function="Warehouse">
|
||||
<file_location>Warehouse/CAN_PQ_Montreal.Intl.AP.716270_CWEC/os_report/569ec649-8017-4a3c-bd0a-337eba3ec488-os-report.html</file_location>
|
||||
</standard>
|
||||
</standards_per_function>
|
||||
</nrcan>
|
89
hub/data/costs/montreal_costs.xml
Normal file
89
hub/data/costs/montreal_costs.xml
Normal file
|
@ -0,0 +1,89 @@
|
|||
<archetypes>
|
||||
<archetype function="residential" municipality="montreal" currency="CAD">
|
||||
<capital_cost>
|
||||
<structural cost_unit="currency/m3"> 56 </structural>
|
||||
<sub_structural cost_unit="currency/m2"> 9.8 </sub_structural>
|
||||
<envelope>
|
||||
<opaque>
|
||||
<reposition cost_unit="currency/m2"> 43.4 </reposition>
|
||||
<initial_investment cost_unit="currency/m2"> 36 </initial_investment>
|
||||
<lifetime_equipment lifetime="years"> 50 </lifetime_equipment>
|
||||
</opaque>
|
||||
<transparent>
|
||||
<reposition cost_unit="currency/m2"> 78 </reposition>
|
||||
<initial_investment cost_unit="currency/m2"> 984.5 </initial_investment>
|
||||
<lifetime_equipment lifetime="years"> 20 </lifetime_equipment>
|
||||
</transparent>
|
||||
</envelope>
|
||||
<systems>
|
||||
<hvac>
|
||||
<heating_equipment_cost>
|
||||
<initial_investment cost_unit="currency/kW"> 363.5 </initial_investment>
|
||||
<reposition cost_unit="currency/kW"> 363.5 </reposition>
|
||||
<lifetime_equipment lifetime="years"> 15 </lifetime_equipment>
|
||||
</heating_equipment_cost>
|
||||
<cooling_equipment_cost>
|
||||
<initial_investment cost_unit="currency/kW"> 363.5 </initial_investment>
|
||||
<reposition cost_unit="currency/kW"> 363.5 </reposition>
|
||||
<lifetime_equipment lifetime="years"> 15 </lifetime_equipment>
|
||||
</cooling_equipment_cost>
|
||||
<general_hvac_equipment_cost>
|
||||
<initial_investment cost_unit="currency/(m3/h)"> 363.5 </initial_investment>
|
||||
<reposition cost_unit="currency/(m3/h)"> 363.5 </reposition>
|
||||
<lifetime_equipment lifetime="years"> 15 </lifetime_equipment>
|
||||
</general_hvac_equipment_cost>
|
||||
</hvac>
|
||||
<photovoltaic_system>
|
||||
<initial_investment cost_unit="currency/m2"> 17 </initial_investment>
|
||||
<reposition cost_unit="currency/m2"> 17 </reposition>
|
||||
<lifetime_equipment lifetime="years"> 15 </lifetime_equipment>
|
||||
</photovoltaic_system>
|
||||
<other_systems>
|
||||
<initial_investment cost_unit="currency/m2"> 365 </initial_investment>
|
||||
<reposition cost_unit="currency/m2"> 365 </reposition>
|
||||
<lifetime_equipment lifetime="years"> 15 </lifetime_equipment>
|
||||
</other_systems>
|
||||
<lighting>
|
||||
<initial_investment cost_unit="currency/m2"> 365 </initial_investment>
|
||||
<reposition cost_unit="currency/m2"> 365 </reposition>
|
||||
<lifetime_equipment lifetime="years"> 15 </lifetime_equipment>
|
||||
</lighting>
|
||||
</systems>
|
||||
<surface_finish cost_unit="currency/m2"> 88 </surface_finish>
|
||||
<engineer cost_unit="%"> 2.5 </engineer>
|
||||
</capital_cost>
|
||||
<operational_cost>
|
||||
<fuel fuel_type="electricity">
|
||||
<fixed>
|
||||
<fixed_monthly cost_unit="currency/month"> 0 </fixed_monthly>
|
||||
<fixed_power cost_unit="currency/kW"> 0 </fixed_power>
|
||||
</fixed>
|
||||
<variable cost_unit="currency/kWh"> 5.6 </variable>
|
||||
</fuel>
|
||||
<maintenance>
|
||||
<heating_equipment cost_unit="currency/kW"> 40 </heating_equipment>
|
||||
<cooling_equipment cost_unit="currency/kW"> 40 </cooling_equipment>
|
||||
<general_hvac_equipment cost_unit="currency/(m3/h)"> 0.05 </general_hvac_equipment>
|
||||
<photovoltaic_system cost_unit="currency/m2"> 1 </photovoltaic_system>
|
||||
<other_systems cost_unit="currency/m2"> 4.6 </other_systems>
|
||||
</maintenance>
|
||||
<CO2_cost cost_unit="currency/kgCO2"> 30 </CO2_cost>
|
||||
</operational_cost>
|
||||
<end_of_life_cost cost_unit="currency/m2"> 6.3 </end_of_life_cost>
|
||||
<incomes>
|
||||
<subsidies>
|
||||
<construction_subsidy cost_unit="%"> 2 </construction_subsidy>
|
||||
<hvac_subsidy cost_unit="%"> 1.5 </hvac_subsidy>
|
||||
<photovoltaic_subsidy cost_unit="%"> 3.6 </photovoltaic_subsidy>
|
||||
</subsidies>
|
||||
<energy_exports>
|
||||
<electricity cost_unit="currency/kWh"> 0 </electricity>
|
||||
<heat cost_unit="currency/kWh"> 0 </heat>
|
||||
</energy_exports>
|
||||
<tax_reductions>
|
||||
<reductions_taxes cost_unit="%"> 2 </reductions_taxes>
|
||||
</tax_reductions>
|
||||
<CO2_income cost_unit="currency/kgCO2exported"> 0 </CO2_income>
|
||||
</incomes>
|
||||
</archetype>
|
||||
</archetypes>
|
|
@ -1,35 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<buildingUsageLibrary>
|
||||
<name>Building Usage Library Reduced</name>
|
||||
<description>Library created by Sanam from HOT200 and ecobee</description>
|
||||
<source>https://www.engineeringtoolbox.com/metabolic-heat-persons-d_706.html</source>
|
||||
<zoneUsageType>
|
||||
<id>residential</id>
|
||||
<description>All residential buildings</description>
|
||||
<occupancy>
|
||||
<occupancyDensity>0.03</occupancyDensity>
|
||||
<usageDaysPerYear>365</usageDaysPerYear>
|
||||
<usageHoursPerDay>14</usageHoursPerDay>
|
||||
<internGains>
|
||||
<description>Persons and home appliances</description>
|
||||
<averageInternGainPerSqm>9.69</averageInternGainPerSqm>
|
||||
<convectiveFraction>0.40</convectiveFraction>
|
||||
<radiantFraction>0.50</radiantFraction>
|
||||
<latentFraction>0.10</latentFraction>
|
||||
</internGains>
|
||||
</occupancy>
|
||||
<appliance units="kWh/day">19.5</appliance>
|
||||
<endUses>
|
||||
<space_heating>
|
||||
<heatingSetPointTemperature>19.0</heatingSetPointTemperature>
|
||||
<heatingSetBackTemperature>18.0</heatingSetBackTemperature>
|
||||
</space_heating>
|
||||
<space_cooling>
|
||||
<coolingSetPointTemperature>21.0</coolingSetPointTemperature>
|
||||
</space_cooling>
|
||||
<ventilation>
|
||||
<mechanicalAirChangeRate>0</mechanicalAirChangeRate>
|
||||
</ventilation>
|
||||
</endUses>
|
||||
</zoneUsageType>
|
||||
</buildingUsageLibrary>
|
File diff suppressed because it is too large
Load Diff
|
@ -1,9 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<nrcan base_url="https://raw.githubusercontent.com/NREL/openstudio-standards/master/lib/openstudio-standards/standards/necb/">
|
||||
<standards>
|
||||
<usage>
|
||||
<space_types_location>NECB2020/data/space_types.json</space_types_location>
|
||||
<schedules_location>NECB2015/data/schedules.json</schedules_location>
|
||||
</usage>
|
||||
</standards>
|
||||
<space_types_location>NECB2020/data/space_types.json</space_types_location>
|
||||
<schedules_location>NECB2015/data/schedules.json</schedules_location>
|
||||
</nrcan>
|
|
@ -75,7 +75,7 @@ class EnergyAde:
|
|||
'energy:type': 'grossVolume',
|
||||
'energy:value': {
|
||||
'@uom': 'm3',
|
||||
'energy:value': building.volume
|
||||
'#text': f'{building.volume}'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -169,7 +169,7 @@ class EnergyAde:
|
|||
def _building_geometry(self, building, building_dic, city):
|
||||
|
||||
building_dic['bldg:Building']['bldg:function'] = building.function
|
||||
building_dic['bldg:Building']['bldg:usage'] = ', '.join([u.usage for u in building.usage_zones])
|
||||
building_dic['bldg:Building']['bldg:usage'] = building.usages_percentage
|
||||
building_dic['bldg:Building']['bldg:yearOfConstruction'] = building.year_of_construction
|
||||
building_dic['bldg:Building']['bldg:roofType'] = building.roof_type
|
||||
building_dic['bldg:Building']['bldg:measuredHeight'] = {
|
||||
|
@ -178,16 +178,86 @@ class EnergyAde:
|
|||
}
|
||||
building_dic['bldg:Building']['bldg:storeysAboveGround'] = building.storeys_above_ground
|
||||
|
||||
if building.lod == 1:
|
||||
if city.level_of_detail.geometry == 1:
|
||||
building_dic = self._lod1(building, building_dic, city)
|
||||
elif building.lod == 2:
|
||||
elif city.level_of_detail.geometry == 2:
|
||||
building_dic = self._lod2(building, building_dic, city)
|
||||
else:
|
||||
raise NotImplementedError('Only lod 1 and 2 can be exported')
|
||||
return building_dic
|
||||
|
||||
def _lod1(self, building, building_dic, city):
|
||||
raise NotImplementedError('Only lod 1 and 2 can be exported')
|
||||
self._surface_members = []
|
||||
boundaries = [{
|
||||
'gml:Envelope': {
|
||||
'@srsName': city.srs_name,
|
||||
'@srsDimension': 3,
|
||||
'gml:lowerCorner': ' '.join([str(e) for e in city.lower_corner]),
|
||||
'gml:upperCorner': ' '.join([str(e) for e in city.upper_corner])
|
||||
}}]
|
||||
for surface in building.surfaces:
|
||||
surface_member = {'@xlink:href': f'#PolyId{surface.name}'}
|
||||
self._surface_members.append(surface_member)
|
||||
if surface.type == 'Wall':
|
||||
surface_type = 'bldg:WallSurface'
|
||||
elif surface.type == 'Ground':
|
||||
surface_type = 'bldg:GroundSurface'
|
||||
else:
|
||||
surface_type = 'bldg:RoofSurface'
|
||||
surface_dic = {
|
||||
surface_type: {
|
||||
'@gml:id': f'GML_{uuid.uuid4()}',
|
||||
'gml:name': f'{surface.name} ({surface.type})',
|
||||
'gml:boundedBy': {
|
||||
'gml:Envelope': {
|
||||
'@srsName': city.srs_name,
|
||||
'gml:lowerCorner': f'{surface.lower_corner[0]} {surface.lower_corner[1]}'
|
||||
f' {surface.lower_corner[2]}',
|
||||
'gml:upperCorner': f'{surface.upper_corner[0]} {surface.upper_corner[1]}'
|
||||
f' {surface.upper_corner[2]}'
|
||||
}
|
||||
},
|
||||
'bldg:lod1MultiSurface': {
|
||||
'gml:MultiSurface': {
|
||||
'@srsName': city.srs_name,
|
||||
'@gml:id': f'GML_{uuid.uuid4()}',
|
||||
'surfaceMember': {
|
||||
'gml:Polygon': {
|
||||
'@srsName': city.srs_name,
|
||||
'@gml:id': f'PolyId{surface.name}',
|
||||
'gml:exterior': {
|
||||
'gml:LinearRing': {
|
||||
'@gml:id': f'PolyId{surface.name}_0',
|
||||
'gml:posList': {
|
||||
'@srsDimension': '3',
|
||||
'@count': len(surface.solid_polygon.coordinates) + 1,
|
||||
'#text': f'{" ".join(map(str, surface.solid_polygon.points_list))} '
|
||||
f'{" ".join(map(str, surface.solid_polygon.coordinates[0]))}'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
boundaries.append(surface_dic)
|
||||
building_dic['bldg:Building']['bldg:lod1Solid'] = {
|
||||
'gml:Solid': {
|
||||
'@gml:id': f'GML_{uuid.uuid4()}',
|
||||
'gml:exterior': {
|
||||
'gml:CompositeSurface': {
|
||||
'@srsName': city.srs_name,
|
||||
'@gml:id': f'GML_{uuid.uuid4()}',
|
||||
'gml:surfaceMember': self._surface_members
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
building_dic['bldg:Building']['gml:boundedBy'] = boundaries
|
||||
return building_dic
|
||||
|
||||
def _lod2(self, building, building_dic, city):
|
||||
self._surface_members = []
|
||||
|
@ -264,56 +334,57 @@ class EnergyAde:
|
|||
|
||||
def _thermal_zones(self, building, city):
|
||||
thermal_zones = []
|
||||
for index, thermal_zone in enumerate(building.thermal_zones):
|
||||
usage_zones = []
|
||||
for usage_zone in thermal_zone.usage_zones:
|
||||
usage_zones.append({'@xlink:href': f'#GML_{usage_zone.id}'})
|
||||
thermal_zone_dic = {
|
||||
'energy:ThermalZone': {
|
||||
'@gml:id': f'GML_{thermal_zone.id}',
|
||||
'gml:name': f'Thermal zone {index} in {building.name} building',
|
||||
'energy:contains': [],
|
||||
'energy:floorArea': {
|
||||
'energy:FloorArea': {
|
||||
'energy:type': 'grossFloorArea',
|
||||
'energy:value': {
|
||||
'@uom': 'm2',
|
||||
'#text': f'{thermal_zone.footprint_area}'
|
||||
}
|
||||
}
|
||||
},
|
||||
'energy:volume': {
|
||||
'energy:VolumeType': {
|
||||
'energy:type': 'grossVolume',
|
||||
'energy:value': {
|
||||
'@uom': 'm3',
|
||||
# todo: for now we have just one thermal zone, therefore is the building volume, this need to be changed
|
||||
'#text': f'{building.volume}'
|
||||
}
|
||||
}
|
||||
},
|
||||
'energy:isCooled': f'{thermal_zone.is_cooled}',
|
||||
'energy:isHeated': f'{thermal_zone.is_heated}',
|
||||
'energy:volumeGeometry': {
|
||||
'gml:Solid': {
|
||||
'@gml:id': f'GML_{uuid.uuid4()}',
|
||||
'gml:exterior': {
|
||||
'gml:CompositeSurface': {
|
||||
'@srsName': f'{city.srs_name}',
|
||||
'@gml:id': f'GML_{uuid.uuid4()}',
|
||||
'gml:surfaceMember': self._surface_members
|
||||
for internal_zone in building.internal_zones:
|
||||
for index, thermal_zone in enumerate(internal_zone.thermal_zones):
|
||||
usages = []
|
||||
for usage in internal_zone.usages:
|
||||
usages.append({'@xlink:href': f'#GML_{usage.id}'})
|
||||
thermal_zone_dic = {
|
||||
'energy:ThermalZone': {
|
||||
'@gml:id': f'GML_{thermal_zone.id}',
|
||||
'gml:name': f'Thermal zone {index} in {building.name} building',
|
||||
'energy:contains': [],
|
||||
'energy:floorArea': {
|
||||
'energy:FloorArea': {
|
||||
'energy:type': 'grossFloorArea',
|
||||
'energy:value': {
|
||||
'@uom': 'm2',
|
||||
'#text': f'{thermal_zone.footprint_area}'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
'energy:boundedBy': self._thermal_boundaries(city, thermal_zone)
|
||||
},
|
||||
'energy:volume': {
|
||||
'energy:VolumeType': {
|
||||
'energy:type': 'grossVolume',
|
||||
'energy:value': {
|
||||
'@uom': 'm3',
|
||||
'#text': f'{thermal_zone.volume}'
|
||||
}
|
||||
}
|
||||
},
|
||||
'energy:isCooled': f'{building.is_conditioned}'.lower(),
|
||||
'energy:isHeated': f'{building.is_conditioned}'.lower(),
|
||||
'energy:volumeGeometry': {
|
||||
'gml:Solid': {
|
||||
'@gml:id': f'GML_{uuid.uuid4()}',
|
||||
'gml:exterior': {
|
||||
'gml:CompositeSurface': {
|
||||
'@srsName': f'{city.srs_name}',
|
||||
'@gml:id': f'GML_{uuid.uuid4()}',
|
||||
'gml:surfaceMember': self._surface_members
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
'energy:boundedBy': self._thermal_boundaries(city, thermal_zone)
|
||||
}
|
||||
}
|
||||
}
|
||||
thermal_zone_dic['energy:ThermalZone']['energy:contains'] = usage_zones
|
||||
thermal_zones.append(thermal_zone_dic)
|
||||
thermal_zone_dic['energy:ThermalZone']['energy:contains'] = usages
|
||||
thermal_zones.append(thermal_zone_dic)
|
||||
return thermal_zones
|
||||
|
||||
def _thermal_boundaries(self, city, thermal_zone):
|
||||
@staticmethod
|
||||
def _thermal_boundaries(city, thermal_zone):
|
||||
thermal_boundaries = []
|
||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||
thermal_boundary_dic = {
|
||||
|
@ -322,11 +393,11 @@ class EnergyAde:
|
|||
'energy:thermalBoundaryType': thermal_boundary.type,
|
||||
'energy:azumuth': {
|
||||
'@uom': 'rad',
|
||||
'#text': f'{thermal_boundary.azimuth}'
|
||||
'#text': f'{thermal_boundary.parent_surface.azimuth}'
|
||||
},
|
||||
'energy:inclination': {
|
||||
'@uom': 'rad',
|
||||
'#text': f'{thermal_boundary.inclination}'
|
||||
'#text': f'{thermal_boundary.parent_surface.inclination}'
|
||||
},
|
||||
'energy:area': {
|
||||
'@uom': 'm2',
|
||||
|
@ -345,9 +416,9 @@ class EnergyAde:
|
|||
'@gml:id': f'GML_{uuid.uuid4()}',
|
||||
'gml:posList': {
|
||||
'@srsDimension': '3',
|
||||
'@count': len(thermal_boundary.surface.solid_polygon.coordinates) + 1,
|
||||
'#text': f'{" ".join(map(str, thermal_boundary.surface.solid_polygon.points_list))} '
|
||||
f'{" ".join(map(str, thermal_boundary.surface.solid_polygon.coordinates[0]))}'
|
||||
'@count': len(thermal_boundary.parent_surface.solid_polygon.coordinates) + 1,
|
||||
'#text': f'{" ".join(map(str, thermal_boundary.parent_surface.solid_polygon.points_list))} '
|
||||
f'{" ".join(map(str, thermal_boundary.parent_surface.solid_polygon.coordinates[0]))}'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -364,7 +435,7 @@ class EnergyAde:
|
|||
'@xlink:href': f'#GML_{construction[0]}'
|
||||
}
|
||||
if thermal_boundary.thermal_openings is not None:
|
||||
for opening in thermal_boundary.thermal_openings:
|
||||
for _ in thermal_boundary.thermal_openings:
|
||||
opening_construction.append(uuid.uuid4())
|
||||
thermal_boundary_dic['energy:contains'] = {
|
||||
'energy:ThermalOpening': {
|
||||
|
|
|
@ -206,9 +206,9 @@ class Idf:
|
|||
_schedule.values = _infiltration_values
|
||||
_infiltration_schedules.append(_schedule)
|
||||
for schedule in self._idf.idfobjects[self._HOURLY_SCHEDULE]:
|
||||
if schedule.Name == f'Infiltration schedules {thermal_zone.usage}':
|
||||
if schedule.Name == f'Infiltration schedules {thermal_zone.usage_name}':
|
||||
return
|
||||
return self._add_standard_compact_hourly_schedule(thermal_zone.usage, 'Infiltration', _infiltration_schedules)
|
||||
return self._add_standard_compact_hourly_schedule(thermal_zone.usage_name, 'Infiltration', _infiltration_schedules)
|
||||
|
||||
def _add_people_activity_level_schedules(self, thermal_zone):
|
||||
_occ = thermal_zone.occupancy
|
||||
|
@ -218,9 +218,9 @@ class Idf:
|
|||
_total_heat = (_occ.sensible_convective_internal_gain + _occ.sensible_radiative_internal_gain
|
||||
+ _occ.latent_internal_gain) / _occ.occupancy_density
|
||||
for schedule in self._idf.idfobjects[self._COMPACT_SCHEDULE]:
|
||||
if schedule.Name == f'Activity Level schedules {thermal_zone.usage}':
|
||||
if schedule.Name == f'Activity Level schedules {thermal_zone.usage_name}':
|
||||
return
|
||||
_kwargs = {'Name': f'Activity Level schedules {thermal_zone.usage}',
|
||||
_kwargs = {'Name': f'Activity Level schedules {thermal_zone.usage_name}',
|
||||
'Schedule_Type_Limits_Name': self.idf_type_limits[cte.ANY_NUMBER],
|
||||
'Field_1': 'Through: 12/31',
|
||||
'Field_2': 'For AllDays',
|
||||
|
@ -299,15 +299,15 @@ class Idf:
|
|||
self._add_heating_system(thermal_zone, name)
|
||||
|
||||
def _add_thermostat(self, thermal_zone):
|
||||
thermostat_name = f'Thermostat {thermal_zone.usage}'
|
||||
thermostat_name = f'Thermostat {thermal_zone.usage_name}'
|
||||
for thermostat in self._idf.idfobjects[self._THERMOSTAT]:
|
||||
if thermostat.Name == thermostat_name:
|
||||
return thermostat
|
||||
# todo: change schedules to schedule name and create schedules using the add_schedule function
|
||||
return self._idf.newidfobject(self._THERMOSTAT,
|
||||
Name=thermostat_name,
|
||||
Heating_Setpoint_Schedule_Name=f'Heating thermostat schedules {thermal_zone.usage}',
|
||||
Cooling_Setpoint_Schedule_Name=f'Cooling thermostat schedules {thermal_zone.usage}')
|
||||
Heating_Setpoint_Schedule_Name=f'Heating thermostat schedules {thermal_zone.usage_name}',
|
||||
Cooling_Setpoint_Schedule_Name=f'Cooling thermostat schedules {thermal_zone.usage_name}')
|
||||
|
||||
def _add_heating_system(self, thermal_zone, zone_name):
|
||||
for air_system in self._idf.idfobjects[self._IDEAL_LOAD_AIR_SYSTEM]:
|
||||
|
@ -316,9 +316,9 @@ class Idf:
|
|||
thermostat = self._add_thermostat(thermal_zone)
|
||||
self._idf.newidfobject(self._IDEAL_LOAD_AIR_SYSTEM,
|
||||
Zone_Name=zone_name,
|
||||
System_Availability_Schedule_Name=f'HVAC AVAIL SCHEDULES {thermal_zone.usage}',
|
||||
Heating_Availability_Schedule_Name=f'HVAC AVAIL SCHEDULES {thermal_zone.usage}',
|
||||
Cooling_Availability_Schedule_Name=f'HVAC AVAIL SCHEDULES {thermal_zone.usage}',
|
||||
System_Availability_Schedule_Name=f'HVAC AVAIL SCHEDULES {thermal_zone.usage_name}',
|
||||
Heating_Availability_Schedule_Name=f'HVAC AVAIL SCHEDULES {thermal_zone.usage_name}',
|
||||
Cooling_Availability_Schedule_Name=f'HVAC AVAIL SCHEDULES {thermal_zone.usage_name}',
|
||||
Template_Thermostat_Name=thermostat.Name)
|
||||
|
||||
def _add_occupancy(self, thermal_zone, zone_name):
|
||||
|
@ -329,11 +329,11 @@ class Idf:
|
|||
self._idf.newidfobject(self._PEOPLE,
|
||||
Name=f'{zone_name}_occupancy',
|
||||
Zone_or_ZoneList_Name=zone_name,
|
||||
Number_of_People_Schedule_Name=f'Occupancy schedules {thermal_zone.usage}',
|
||||
Number_of_People_Schedule_Name=f'Occupancy schedules {thermal_zone.usage_name}',
|
||||
Number_of_People_Calculation_Method="People",
|
||||
Number_of_People=number_of_people,
|
||||
Fraction_Radiant=fraction_radiant,
|
||||
Activity_Level_Schedule_Name=f'Activity Level schedules {thermal_zone.usage}'
|
||||
Activity_Level_Schedule_Name=f'Activity Level schedules {thermal_zone.usage_name}'
|
||||
)
|
||||
|
||||
def _add_infiltration(self, thermal_zone, zone_name):
|
||||
|
@ -343,7 +343,7 @@ class Idf:
|
|||
self._idf.newidfobject(self._INFILTRATION,
|
||||
Name=f'{zone_name}_infiltration',
|
||||
Zone_or_ZoneList_Name=zone_name,
|
||||
Schedule_Name=f'Infiltration schedules {thermal_zone.usage}',
|
||||
Schedule_Name=f'Infiltration schedules {thermal_zone.usage_name}',
|
||||
Design_Flow_Rate_Calculation_Method='AirChanges/Hour',
|
||||
Air_Changes_per_Hour=thermal_zone.mechanical_air_change
|
||||
)
|
||||
|
@ -386,7 +386,7 @@ class Idf:
|
|||
self._add_vegetation_material(thermal_boundary.parent_surface.vegetation)
|
||||
for thermal_opening in thermal_boundary.thermal_openings:
|
||||
self._add_window_construction_and_material(thermal_opening)
|
||||
usage = thermal_zone.usage
|
||||
usage = thermal_zone.usage_name
|
||||
if building.name in self._target_buildings or building.name in self._adjacent_buildings:
|
||||
self._add_infiltration_schedules(thermal_zone)
|
||||
self._add_schedules(usage, 'Occupancy', thermal_zone.occupancy.occupancy_schedules)
|
||||
|
@ -461,8 +461,8 @@ class Idf:
|
|||
if surface.Type == self.idf_surfaces[boundary.surface.type]:
|
||||
surface.Construction_Name = boundary.construction_name
|
||||
break
|
||||
for usage_zone in thermal_zone.usage_zones:
|
||||
surface.Zone_Name = usage_zone.id
|
||||
for usage in thermal_zone.usages:
|
||||
surface.Zone_Name = usage.id
|
||||
break
|
||||
break
|
||||
self._idf.intersect_match()
|
||||
|
|
|
@ -77,25 +77,25 @@ class InselMonthlyEnergyBalance(Insel):
|
|||
parameters.append('1 % BP(9) Usage type (0=standard, 1=IWU)')
|
||||
|
||||
# ZONES AND SURFACES
|
||||
parameters.append(f'{len(internal_zone.usage_zones)} % BP(10) Number of zones')
|
||||
parameters.append(f'{len(internal_zone.usages)} % BP(10) Number of zones')
|
||||
|
||||
for i, usage_zone in enumerate(internal_zone.usage_zones):
|
||||
percentage_usage = usage_zone.percentage
|
||||
for i, usage in enumerate(internal_zone.usages):
|
||||
percentage_usage = usage.percentage
|
||||
parameters.append(f'{float(internal_zone.area) * percentage_usage} % BP(11) #1 Area of zone {i + 1} (m2)')
|
||||
total_internal_gain = 0
|
||||
for ig in usage_zone.internal_gains:
|
||||
for ig in usage.internal_gains:
|
||||
total_internal_gain += float(ig.average_internal_gain) * \
|
||||
(float(ig.convective_fraction) + float(ig.radiative_fraction))
|
||||
parameters.append(f'{total_internal_gain} % BP(12) #2 Internal gains of zone {i + 1}')
|
||||
parameters.append(f'{usage_zone.thermal_control.mean_heating_set_point} % BP(13) #3 Heating setpoint temperature '
|
||||
parameters.append(f'{usage.thermal_control.mean_heating_set_point} % BP(13) #3 Heating setpoint temperature '
|
||||
f'zone {i + 1} (degree Celsius)')
|
||||
parameters.append(f'{usage_zone.thermal_control.heating_set_back} % BP(14) #4 Heating setback temperature '
|
||||
parameters.append(f'{usage.thermal_control.heating_set_back} % BP(14) #4 Heating setback temperature '
|
||||
f'zone {i + 1} (degree Celsius)')
|
||||
parameters.append(f'{usage_zone.thermal_control.mean_cooling_set_point} % BP(15) #5 Cooling setpoint temperature '
|
||||
parameters.append(f'{usage.thermal_control.mean_cooling_set_point} % BP(15) #5 Cooling setpoint temperature '
|
||||
f'zone {i + 1} (degree Celsius)')
|
||||
parameters.append(f'{usage_zone.hours_day} % BP(16) #6 Usage hours per day zone {i + 1}')
|
||||
parameters.append(f'{usage_zone.days_year} % BP(17) #7 Usage days per year zone {i + 1}')
|
||||
parameters.append(f'{usage_zone.mechanical_air_change} % BP(18) #8 Minimum air change rate zone {i + 1} (ACH)')
|
||||
parameters.append(f'{usage.hours_day} % BP(16) #6 Usage hours per day zone {i + 1}')
|
||||
parameters.append(f'{usage.days_year} % BP(17) #7 Usage days per year zone {i + 1}')
|
||||
parameters.append(f'{usage.mechanical_air_change} % BP(18) #8 Minimum air change rate zone {i + 1} (ACH)')
|
||||
|
||||
parameters.append(f'{len(thermal_zone.thermal_boundaries)} % Number of surfaces = BP(11+8z) \n'
|
||||
f'% 1. Surface type (1=wall, 2=ground 3=roof, 4=flat roof)\n'
|
||||
|
@ -167,6 +167,8 @@ class InselMonthlyEnergyBalance(Insel):
|
|||
f'inclination {np.rad2deg(surface.inclination)} (degrees)']
|
||||
|
||||
if surface.type != 'Ground':
|
||||
if cte.MONTH not in surface.global_irradiance:
|
||||
raise ValueError(f'surface: {surface.name} from building {building.name} has no global irradiance!')
|
||||
global_irradiance = surface.global_irradiance[cte.MONTH]
|
||||
for j in range(0, len(global_irradiance)):
|
||||
parameters.append(f'{j + 1} {global_irradiance.at[j, radiation_calculation_method]}')
|
||||
|
@ -176,15 +178,17 @@ class InselMonthlyEnergyBalance(Insel):
|
|||
|
||||
file = Insel._add_block(file, i_block, 'polyg', inputs=inputs, parameters=parameters)
|
||||
|
||||
i_block = 300
|
||||
i_block = 300 + len(surfaces)
|
||||
inputs = ['4.1', '4.2']
|
||||
file = Insel._add_block(file, i_block, 'cum', inputs=inputs)
|
||||
|
||||
i_block = 303
|
||||
inputs = ['300.1', '300.2']
|
||||
in_1 = f'{i_block}.1'
|
||||
in_2 = f'{i_block}.2'
|
||||
i_block = 303 + len(surfaces)
|
||||
inputs = [in_1, in_2]
|
||||
file = Insel._add_block(file, i_block, 'atend', inputs=inputs)
|
||||
|
||||
i_block = 310
|
||||
i_block = 310 + len(surfaces)
|
||||
inputs = ['4.1', '4.2']
|
||||
parameters = ['1 % Mode',
|
||||
'0 % Suppress FNQ inputs',
|
||||
|
|
|
@ -4,8 +4,10 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
|
|||
Copyright © 2022 Concordia CERC group
|
||||
Project CoderPeter Yefi peteryefi@gmail.com
|
||||
"""
|
||||
from hub.persistence import CityRepo
|
||||
from hub.persistence import HeatPumpSimulationRepo
|
||||
from hub.persistence import City
|
||||
from hub.persistence import Application
|
||||
from hub.persistence import User
|
||||
from hub.persistence import CityObject
|
||||
|
||||
|
||||
class DBFactory:
|
||||
|
@ -14,40 +16,38 @@ class DBFactory:
|
|||
"""
|
||||
|
||||
def __init__(self, db_name, app_env, dotenv_path):
|
||||
self._city_repo = CityRepo(db_name=db_name, app_env=app_env, dotenv_path=dotenv_path)
|
||||
self._hp_simulation_repo = HeatPumpSimulationRepo(db_name=db_name, app_env=app_env, dotenv_path=dotenv_path)
|
||||
self._city = City(db_name=db_name, app_env=app_env, dotenv_path=dotenv_path)
|
||||
self._application = Application(db_name=db_name, app_env=app_env, dotenv_path=dotenv_path)
|
||||
self._user = User(db_name=db_name, app_env=app_env, dotenv_path=dotenv_path)
|
||||
self._city_object = CityObject(db_name=db_name, app_env=app_env, dotenv_path=dotenv_path)
|
||||
|
||||
def get_city(self, city_id):
|
||||
"""
|
||||
Retrieve a single city from postgres
|
||||
:param city_id: the id of the city to get
|
||||
"""
|
||||
return self._city_repo.get_by_id(city_id)
|
||||
return self._city.get_by_id(city_id)
|
||||
|
||||
def get_city_by_name(self, city_name):
|
||||
"""
|
||||
Retrieve a single city from postgres
|
||||
:param city_name: the name of the city to get
|
||||
"""
|
||||
return self._city_repo.get_by_name(city_name)
|
||||
return self._city.get_by_name(city_name)
|
||||
|
||||
def get_city_by_user(self, user_id):
|
||||
"""
|
||||
Retrieve cities created by user
|
||||
:param user_id: the id of the user
|
||||
"""
|
||||
return self._city_repo.get_by_user(user_id)
|
||||
return self._city.get_by_user(user_id)
|
||||
|
||||
def get_hp_simulation(self, hp_sim_id: int):
|
||||
"""
|
||||
Retrieve a single heat pump simulation from postgres
|
||||
:param hp_sim_id: the id of the heat pump to get
|
||||
"""
|
||||
return self._hp_simulation_repo.get_by_id(hp_sim_id)
|
||||
def application_info(self, application_uuid):
|
||||
return self._application.get_by_uuid(application_uuid)
|
||||
|
||||
def user_info(self, name, password, application_id):
|
||||
return self._user.get_by_name_application_and_password(name, password, application_id)
|
||||
|
||||
def building_info(self, name, city_id):
|
||||
return self._city_object.get_by_name_and_city(name, city_id)
|
||||
|
||||
def get_hp_simulation_by_city(self, city_id: int):
|
||||
"""
|
||||
Retrieve a single city from postgres
|
||||
:param city_id: the id of the city
|
||||
"""
|
||||
return self._hp_simulation_repo.get_by_city(city_id)
|
||||
|
|
|
@ -9,6 +9,8 @@ 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
|
||||
from hub.helpers.utils import validate_import_export_type
|
||||
from hub.hub_logger import logger
|
||||
|
||||
|
||||
class EnergyBuildingsExportsFactory:
|
||||
|
@ -18,6 +20,11 @@ class EnergyBuildingsExportsFactory:
|
|||
def __init__(self, export_type, city, path, target_buildings=None, adjacent_buildings=None):
|
||||
self._city = city
|
||||
self._export_type = '_' + export_type.lower()
|
||||
class_funcs = validate_import_export_type(EnergyBuildingsExportsFactory)
|
||||
if self._export_type not in class_funcs:
|
||||
err_msg = f"Wrong import type [{self._export_type}]. Valid functions include {class_funcs}"
|
||||
logger.error(err_msg)
|
||||
raise Exception(err_msg)
|
||||
if isinstance(path, str):
|
||||
path = Path(path)
|
||||
self._path = path
|
||||
|
|
|
@ -64,8 +64,8 @@ class HeatPumpExport:
|
|||
# User output
|
||||
return self._get_user_out_put()
|
||||
except IOError as err:
|
||||
print("I/O exception: {}".format(err))
|
||||
logger.error(f'An I/O error occurred while running insel: {err}')
|
||||
print("I/O exception: {}".format(str(err)))
|
||||
logger.error(f'An I/O error occurred while running insel: {str(err)}')
|
||||
finally:
|
||||
insel_file_handler.close()
|
||||
insel_template_handler.close()
|
||||
|
@ -252,5 +252,3 @@ class HeatPumpExport:
|
|||
s = pd.Series(["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec", "Total"])
|
||||
df = df.set_index([s])
|
||||
df.to_csv(self._output_path)
|
||||
|
||||
|
||||
|
|
|
@ -9,20 +9,33 @@ 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
|
||||
from hub.hub_logger import logger
|
||||
from hub.helpers.utils import validate_import_export_type
|
||||
|
||||
|
||||
class ExportsFactory:
|
||||
"""
|
||||
Exports factory class
|
||||
"""
|
||||
def __init__(self, export_type, city, path, target_buildings=None, adjacent_buildings=None):
|
||||
def __init__(self, export_type, city, path,
|
||||
target_buildings=None,
|
||||
adjacent_buildings=None,
|
||||
weather_file=None,
|
||||
weather_format=None):
|
||||
self._city = city
|
||||
self._export_type = '_' + export_type.lower()
|
||||
class_funcs = validate_import_export_type(ExportsFactory)
|
||||
if self._export_type not in class_funcs:
|
||||
err_msg = f"Wrong export type [{self._export_type}]. Valid functions include {class_funcs}"
|
||||
logger.error(err_msg)
|
||||
raise Exception(err_msg)
|
||||
if isinstance(path, str):
|
||||
path = Path(path)
|
||||
self._path = path
|
||||
self._target_buildings = target_buildings
|
||||
self._adjacent_buildings = adjacent_buildings
|
||||
self._weather_file = weather_file
|
||||
self._weather_format = weather_format
|
||||
|
||||
@property
|
||||
def _citygml(self):
|
||||
|
@ -66,7 +79,10 @@ class ExportsFactory:
|
|||
Export the city to Simplified Radiosity Algorithm xml format
|
||||
:return: None
|
||||
"""
|
||||
return SimplifiedRadiosityAlgorithm(self._city, (self._path / f'{self._city.name}_sra.xml'),
|
||||
return SimplifiedRadiosityAlgorithm(self._city,
|
||||
(self._path / f'{self._city.name}_sra.xml'),
|
||||
self._weather_file,
|
||||
self._weather_format,
|
||||
target_buildings=self._target_buildings)
|
||||
|
||||
def export(self):
|
||||
|
|
|
@ -27,4 +27,3 @@ class Insel(ABC):
|
|||
|
||||
def _export(self):
|
||||
raise NotImplementedError
|
||||
|
||||
|
|
|
@ -26,7 +26,8 @@ class Obj(Triangular):
|
|||
file_name_out = self._city.name + '_ground.' + self._triangular_format
|
||||
file_path_in = (Path(self._path).resolve() / file_name_in).resolve()
|
||||
file_path_out = (Path(self._path).resolve() / file_name_out).resolve()
|
||||
scene = GeometryFactory('obj', path=file_path_in).scene
|
||||
obj = GeometryFactory('obj', path=file_path_in)
|
||||
scene = obj.scene
|
||||
scene.rezero()
|
||||
obj_file = trimesh.exchange.obj.export_obj(scene)
|
||||
with open(file_path_out, 'w') as file:
|
||||
|
|
|
@ -6,12 +6,25 @@ Project Coder Guillermo.GutierrezMorote@concordia.ca
|
|||
"""
|
||||
import xmltodict
|
||||
|
||||
from hub.imports.weather_factory import WeatherFactory
|
||||
import hub.helpers.constants as cte
|
||||
|
||||
|
||||
class SimplifiedRadiosityAlgorithm:
|
||||
"""
|
||||
Export to SRA format
|
||||
"""
|
||||
def __init__(self, city, file_name, target_buildings=None, begin_month=1, begin_day=1, end_month=12, end_day=31):
|
||||
|
||||
def __init__(self,
|
||||
city,
|
||||
file_name,
|
||||
weather_file,
|
||||
weather_format,
|
||||
target_buildings=None,
|
||||
begin_month=1,
|
||||
begin_day=1,
|
||||
end_month=12,
|
||||
end_day=31):
|
||||
self._file_name = file_name
|
||||
self._begin_month = begin_month
|
||||
self._begin_day = begin_day
|
||||
|
@ -19,6 +32,8 @@ class SimplifiedRadiosityAlgorithm:
|
|||
self._end_day = end_day
|
||||
self._city = city
|
||||
self._target_buildings = target_buildings
|
||||
self._weather_format = weather_format
|
||||
self._weather_file = weather_file
|
||||
self._export()
|
||||
|
||||
def _correct_point(self, point):
|
||||
|
@ -29,6 +44,34 @@ class SimplifiedRadiosityAlgorithm:
|
|||
return [x, y, z]
|
||||
|
||||
def _export(self):
|
||||
self._export_sra_xml()
|
||||
self._export_sra_cli()
|
||||
|
||||
def _export_sra_cli(self):
|
||||
file = self._city.climate_file
|
||||
days_in_month = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
|
||||
WeatherFactory(self._weather_format, self._city, file_name=self._weather_file).enrich()
|
||||
content = self._city.name + '\n'
|
||||
content += str(self._city.latitude) + ',' + str(self._city.longitude) + ',0.0,' + str(self._city.time_zone) + '\n'
|
||||
content += '\ndm m h G_Dh G_Bn\n'
|
||||
total_days = 0
|
||||
for month in range(1, 13):
|
||||
if month > 1:
|
||||
total_days += days_in_month[month - 2]
|
||||
for day in range(1, days_in_month[month - 1] + 1):
|
||||
for hour in range(1, 25):
|
||||
if month == 1:
|
||||
i = 24 * (day - 1) + hour - 1
|
||||
else:
|
||||
i = (total_days + day - 1) * 24 + hour - 1
|
||||
representative_building = self._city.buildings[0]
|
||||
content += str(day) + ' ' + str(month) + ' ' + str(hour) + ' ' \
|
||||
+ str(representative_building.global_horizontal[cte.HOUR].epw[i]) + ' ' \
|
||||
+ str(representative_building.beam[cte.HOUR].epw[i]) + '\n'
|
||||
with open(file, "w") as file:
|
||||
file.write(content)
|
||||
|
||||
def _export_sra_xml(self):
|
||||
buildings = []
|
||||
for building_index, building in enumerate(self._city.buildings):
|
||||
if self._target_buildings is None:
|
||||
|
|
|
@ -1,23 +1,16 @@
|
|||
"""
|
||||
Constant module
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2023 Concordia CERC group
|
||||
Project Coder Peter Yefi peteryefi@gmail.com
|
||||
"""
|
||||
|
||||
import bcrypt
|
||||
import re
|
||||
|
||||
|
||||
class Auth(object):
|
||||
|
||||
@staticmethod
|
||||
def validate_password(password: str) -> bool:
|
||||
"""
|
||||
Validates a password
|
||||
:param password: the password to validate
|
||||
:return:
|
||||
"""
|
||||
pattern = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!#%*?&]{6,20}$"
|
||||
pattern = re.compile(pattern)
|
||||
if not re.search(pattern, password):
|
||||
raise ValueError("Password must be between 6 to 20 characters and must have at least a number, an uppercase "
|
||||
"letter, a lowercase letter, and a special character")
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def hash_password(password: str) -> str:
|
||||
"""
|
||||
|
|
|
@ -66,45 +66,64 @@ DOOR = 'Door'
|
|||
SKYLIGHT = 'Skylight'
|
||||
|
||||
# functions and usages
|
||||
RESIDENTIAL = 'residential'
|
||||
SINGLE_FAMILY_HOUSE = 'single family house'
|
||||
MULTI_FAMILY_HOUSE = 'multifamily house'
|
||||
ROW_HOSE = 'row house'
|
||||
ROW_HOUSE = 'row house'
|
||||
MID_RISE_APARTMENT = 'mid rise apartment'
|
||||
HIGH_RISE_APARTMENT = 'high rise apartment'
|
||||
OFFICE_AND_ADMINISTRATION = 'office and administration'
|
||||
SMALL_OFFICE = 'small office'
|
||||
MEDIUM_OFFICE = 'medium office'
|
||||
LARGE_OFFICE = 'large office'
|
||||
COURTHOUSE = 'courthouse'
|
||||
FIRE_STATION = 'fire station'
|
||||
PENITENTIARY = 'penitentiary'
|
||||
POLICE_STATION = 'police station'
|
||||
POST_OFFICE = 'post office'
|
||||
LIBRARY = 'library'
|
||||
EDUCATION = 'education'
|
||||
PRIMARY_SCHOOL = 'primary school'
|
||||
PRIMARY_SCHOOL_WITH_SHOWER = 'school with shower'
|
||||
SECONDARY_SCHOOL = 'secondary school'
|
||||
UNIVERSITY = 'university'
|
||||
LABORATORY_AND_RESEARCH_CENTER = 'laboratory and research centers'
|
||||
STAND_ALONE_RETAIL = 'stand alone retail'
|
||||
HOSPITAL = 'hospital'
|
||||
OUT_PATIENT_HEALTH_CARE = 'out-patient health care'
|
||||
STRIP_MALL = 'strip mall'
|
||||
SUPERMARKET = 'supermarket'
|
||||
WAREHOUSE = 'warehouse'
|
||||
QUICK_SERVICE_RESTAURANT = 'quick service restaurant'
|
||||
FULL_SERVICE_RESTAURANT = 'full service restaurant'
|
||||
SMALL_HOTEL = 'small hotel'
|
||||
LARGE_HOTEL = 'large hotel'
|
||||
RESIDENTIAL = 'residential'
|
||||
EDUCATION = 'education'
|
||||
SCHOOL_WITHOUT_SHOWER = 'school without shower'
|
||||
SCHOOL_WITH_SHOWER = 'school with shower'
|
||||
RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD = 'retail shop without refrigerated food'
|
||||
RETAIL_SHOP_WITH_REFRIGERATED_FOOD = 'retail shop with refrigerated food'
|
||||
HOTEL = 'hotel'
|
||||
HOTEL_MEDIUM_CLASS = 'hotel medium class'
|
||||
DORMITORY = 'dormitory'
|
||||
INDUSTRY = 'industry'
|
||||
RESTAURANT = 'restaurant'
|
||||
HEALTH_CARE = 'health care'
|
||||
RETIREMENT_HOME_OR_ORPHANAGE = 'retirement home or orphanage'
|
||||
OFFICE_AND_ADMINISTRATION = 'office and administration'
|
||||
COMMERCIAL = 'commercial'
|
||||
STRIP_MALL = 'strip mall'
|
||||
SUPERMARKET = 'supermarket'
|
||||
RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD = 'retail shop without refrigerated food'
|
||||
RETAIL_SHOP_WITH_REFRIGERATED_FOOD = 'retail shop with refrigerated food'
|
||||
RESTAURANT = 'restaurant'
|
||||
QUICK_SERVICE_RESTAURANT = 'quick service restaurant'
|
||||
FULL_SERVICE_RESTAURANT = 'full service restaurant'
|
||||
HOTEL = 'hotel'
|
||||
HOTEL_MEDIUM_CLASS = 'hotel medium class'
|
||||
SMALL_HOTEL = 'small hotel'
|
||||
LARGE_HOTEL = 'large hotel'
|
||||
DORMITORY = 'dormitory'
|
||||
EVENT_LOCATION = 'event location'
|
||||
CONVENTION_CENTER = 'convention center'
|
||||
HALL = 'hall'
|
||||
SPORTS_LOCATION = 'sports location'
|
||||
LABOR = 'labor'
|
||||
GREEN_HOUSE = 'green house'
|
||||
INDUSTRY = 'industry'
|
||||
WORKSHOP = 'workshop'
|
||||
WAREHOUSE = 'warehouse'
|
||||
WAREHOUSE_REFRIGERATED = 'warehouse refrigerated'
|
||||
SPORTS_LOCATION = 'sports location'
|
||||
SPORTS_ARENA = 'sports arena'
|
||||
GYMNASIUM = 'gymnasium'
|
||||
MOTION_PICTURE_THEATRE = 'motion picture theatre'
|
||||
MUSEUM = 'museum'
|
||||
PERFORMING_ARTS_THEATRE = 'performing arts theatre'
|
||||
TRANSPORTATION = 'transportation'
|
||||
AUTOMOTIVE_FACILITY = 'automotive facility'
|
||||
PARKING_GARAGE = 'parking garage'
|
||||
RELIGIOUS = 'religious'
|
||||
NON_HEATED = 'non-heated'
|
||||
|
||||
LIGHTING = 'Lights'
|
||||
|
@ -133,3 +152,7 @@ FULL_HVAC = 'Heating and cooling and ventilation'
|
|||
# Floats
|
||||
MAX_FLOAT = float('inf')
|
||||
MIN_FLOAT = float('-inf')
|
||||
|
||||
# Tools
|
||||
SRA = 'sra'
|
||||
INSEL_MEB = 'insel meb'
|
||||
|
|
185
hub/helpers/data/alkis_function_to_hub_function.py
Normal file
185
hub/helpers/data/alkis_function_to_hub_function.py
Normal file
|
@ -0,0 +1,185 @@
|
|||
"""
|
||||
Dictionaries module for Alkis function to hub function
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Guille Gutierrez Guillermo.GutierrezMorote@concordia.ca
|
||||
"""
|
||||
|
||||
|
||||
import hub.helpers.constants as cte
|
||||
|
||||
class AlkisFunctionToHubFunction:
|
||||
|
||||
def __init__(self):
|
||||
self._dictionary = {"1000": cte.RESIDENTIAL,
|
||||
"1010": "tenement",
|
||||
"1020": "hostel",
|
||||
"1030": "residential- and administration building",
|
||||
"1040": "residential- and office building",
|
||||
"1050": "residential- and business building",
|
||||
"1060": "residential- and plant building",
|
||||
"1070": "agrarian- and forestry building",
|
||||
"1080": "residential- and commercial building",
|
||||
"1090": "forester's lodge",
|
||||
"1100": "holiday house",
|
||||
"1110": "summer house",
|
||||
"1120": "office building",
|
||||
"1130": "credit institution",
|
||||
"1140": "insurance",
|
||||
"1150": "business building",
|
||||
"1160": "department store",
|
||||
"1170": "shopping centre",
|
||||
"1180": "kiosk",
|
||||
"1190": "pharmacy",
|
||||
"1200": "pavilion",
|
||||
"1210": cte.HOTEL,
|
||||
"1220": "youth hostel",
|
||||
"1230": "campsite building",
|
||||
"1240": "restaurant",
|
||||
"1250": "cantine",
|
||||
"1260": "recreational site",
|
||||
"1270": "function room",
|
||||
"1280": "cinema",
|
||||
"1290": "bowling alley",
|
||||
"1300": "casino",
|
||||
"1310": "industrial building",
|
||||
"1320": "factory",
|
||||
"1330": cte.WORKSHOP,
|
||||
"1340": "petrol / gas station",
|
||||
"1350": "washing plant",
|
||||
"1360": "cold store",
|
||||
"1370": "depot",
|
||||
"1380": "building for research purposes",
|
||||
"1390": "quarry",
|
||||
"1400": "salt works",
|
||||
"1410": "miscellaneous industrial building",
|
||||
"1420": "mill",
|
||||
"1430": "windmill",
|
||||
"1440": "water mill",
|
||||
"1450": "bucket elevator",
|
||||
"1460": "weather station",
|
||||
"1470": "traffic assets office",
|
||||
"1480": "street maintenance",
|
||||
"1490": "waiting hall",
|
||||
"1500": "signal control box",
|
||||
"1510": "engine shed",
|
||||
"1520": "signal box or stop signal",
|
||||
"1530": "plant building for air traffic",
|
||||
"1540": "hangar",
|
||||
"1550": "plant building for shipping",
|
||||
"1560": "shipyard",
|
||||
"1570": "dock",
|
||||
"1580": "plant building for canal lock",
|
||||
"1590": "boathouse",
|
||||
"1600": "plant building for cablecar",
|
||||
"1610": "multi-storey car park",
|
||||
"1620": "parking level",
|
||||
"1630": "garage",
|
||||
"1640": "vehicle hall",
|
||||
"1650": "underground garage",
|
||||
"1660": "building for supply",
|
||||
"1670": "waterworks",
|
||||
"1680": "pump station",
|
||||
"1690": "water basin",
|
||||
"1700": "electric power station",
|
||||
"1710": "transformer station",
|
||||
"1720": "converter",
|
||||
"1730": "reactor",
|
||||
"1740": "turbine house",
|
||||
"1750": "boiler house",
|
||||
"1760": "building for telecommunications",
|
||||
"1770": "gas works",
|
||||
"1780": "heat plant",
|
||||
"1790": "pumping station",
|
||||
"1800": "building for disposal",
|
||||
"1810": "building for effluent disposal",
|
||||
"1820": "building for filter plant",
|
||||
"1830": "toilet",
|
||||
"1840": "rubbish bunker",
|
||||
"1850": "building for rubbish incineration",
|
||||
"1860": "building for rubbish disposal",
|
||||
"1870": "building for agrarian and forestry",
|
||||
"1880": "barn",
|
||||
"1890": "stall",
|
||||
"1900": "equestrian hall",
|
||||
"1910": "alpine cabin",
|
||||
"1920": "hunting lodge",
|
||||
"1930": "arboretum",
|
||||
"1940": "glass house",
|
||||
"1950": "moveable glass house",
|
||||
"1960": "public building",
|
||||
"1970": "administration building",
|
||||
"1980": "parliament",
|
||||
"1990": "guildhall",
|
||||
"2000": "post office",
|
||||
"2010": "customs office",
|
||||
"2020": "court",
|
||||
"2030": "embassy or consulate",
|
||||
"2040": "district administration",
|
||||
"2050": "district government",
|
||||
"2060": "tax office",
|
||||
"2070": "building for education and research",
|
||||
"2080": "comprehensive school",
|
||||
"2090": "vocational school",
|
||||
"2100": "college or university",
|
||||
"2110": "research establishment",
|
||||
"2120": "building for cultural purposes",
|
||||
"2130": "castle",
|
||||
"2140": "theatre or opera",
|
||||
"2150": "concert building",
|
||||
"2160": cte.MUSEUM,
|
||||
"2170": "broadcasting building",
|
||||
"2180": "activity building",
|
||||
"2190": cte.LIBRARY,
|
||||
"2200": "fort",
|
||||
"2210": "religious building",
|
||||
"2220": "church",
|
||||
"2230": "synagogue",
|
||||
"2240": "chapel",
|
||||
"2250": "community center",
|
||||
"2260": "place of worship",
|
||||
"2270": "mosque",
|
||||
"2280": "temple",
|
||||
"2290": "convent",
|
||||
"2300": "building for health care",
|
||||
"2310": cte.HOSPITAL,
|
||||
"2320": "healing centre or care home",
|
||||
"2330": "health centre or outpatients clinic",
|
||||
"2340": "building for social purposes",
|
||||
"2350": "youth centre",
|
||||
"2360": "seniors centre",
|
||||
"2370": "homeless shelter",
|
||||
"2380": "kindergarten or nursery",
|
||||
"2390": "asylum seekers home",
|
||||
"2400": cte.POLICE_STATION,
|
||||
"2410": cte.FIRE_STATION,
|
||||
"2420": "barracks",
|
||||
"2430": "bunker",
|
||||
"2440": cte.PENITENTIARY,
|
||||
"2450": "cemetery building",
|
||||
"2460": "funeral parlor",
|
||||
"2470": "crematorium",
|
||||
"2480": "train station",
|
||||
"2490": "airport building",
|
||||
"2500": "building for underground station",
|
||||
"2510": "building for tramway",
|
||||
"2520": "building for bus station",
|
||||
"2530": "shipping terminal",
|
||||
"2540": "building for recuperation purposes",
|
||||
"2550": "building for sport purposes",
|
||||
"2560": "sports hall",
|
||||
"2570": "building for sports field",
|
||||
"2580": "swimming baths",
|
||||
"2590": "indoor swimming pool",
|
||||
"2600": "sanatorium",
|
||||
"2610": "zoo building",
|
||||
"2620": cte.GREEN_HOUSE,
|
||||
"2630": "botanical show house",
|
||||
"2640": "bothy",
|
||||
"2650": "tourist information centre",
|
||||
"2700": "others",
|
||||
}
|
||||
|
||||
@property
|
||||
def dictionary(self) -> dict:
|
||||
return self._dictionary
|
32
hub/helpers/data/hft_function_to_hub_function.py
Normal file
32
hub/helpers/data/hft_function_to_hub_function.py
Normal file
|
@ -0,0 +1,32 @@
|
|||
"""
|
||||
Dictionaries module for Hft function to hub function
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Guille Gutierrez Guillermo.GutierrezMorote@concordia.ca
|
||||
"""
|
||||
|
||||
import hub.helpers.constants as cte
|
||||
|
||||
|
||||
class HftFunctionToHubFunction:
|
||||
|
||||
def __init__(self):
|
||||
self._dictionary = {
|
||||
'residential': cte.RESIDENTIAL,
|
||||
'single family house': cte.SINGLE_FAMILY_HOUSE,
|
||||
'multifamily house': cte.MULTI_FAMILY_HOUSE,
|
||||
'hotel': cte.HOTEL,
|
||||
'hospital': cte.HOSPITAL,
|
||||
'outpatient': cte.OUT_PATIENT_HEALTH_CARE,
|
||||
'commercial': cte.SUPERMARKET,
|
||||
'strip mall': cte.STRIP_MALL,
|
||||
'warehouse': cte.WAREHOUSE,
|
||||
'primary school': cte.PRIMARY_SCHOOL,
|
||||
'secondary school': cte.EDUCATION,
|
||||
'office': cte.MEDIUM_OFFICE,
|
||||
'large office': cte.LARGE_OFFICE
|
||||
}
|
||||
|
||||
@property
|
||||
def dictionary(self) -> dict:
|
||||
return self._dictionary
|
|
@ -0,0 +1,78 @@
|
|||
"""
|
||||
Dictionaries module for hub function to nrcan construction function
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Guille Gutierrez Guillermo.GutierrezMorote@concordia.ca
|
||||
"""
|
||||
|
||||
import hub.helpers.constants as cte
|
||||
|
||||
|
||||
class HubFunctionToNrcanConstructionFunction:
|
||||
|
||||
def __init__(self):
|
||||
self._dictionary = {
|
||||
cte.RESIDENTIAL: 'MidriseApartment',
|
||||
cte.SINGLE_FAMILY_HOUSE: 'MidriseApartment',
|
||||
cte.MULTI_FAMILY_HOUSE: 'HighriseApartment',
|
||||
cte.ROW_HOUSE: 'MidriseApartment',
|
||||
cte.MID_RISE_APARTMENT: 'MidriseApartment',
|
||||
cte.HIGH_RISE_APARTMENT: 'HighriseApartment',
|
||||
cte.OFFICE_AND_ADMINISTRATION: 'MediumOffice',
|
||||
cte.SMALL_OFFICE: 'SmallOffice',
|
||||
cte.MEDIUM_OFFICE: 'MediumOffice',
|
||||
cte.LARGE_OFFICE: 'LargeOffice',
|
||||
cte.COURTHOUSE: 'MediumOffice',
|
||||
cte.FIRE_STATION: 'n/a',
|
||||
cte.PENITENTIARY: 'LargeHotel',
|
||||
cte.POLICE_STATION: 'n/a',
|
||||
cte.POST_OFFICE: 'MediumOffice',
|
||||
cte.LIBRARY: 'MediumOffice',
|
||||
cte.EDUCATION: 'SecondarySchool',
|
||||
cte.PRIMARY_SCHOOL: 'PrimarySchool',
|
||||
cte.PRIMARY_SCHOOL_WITH_SHOWER: 'PrimarySchool',
|
||||
cte.SECONDARY_SCHOOL: 'SecondarySchool',
|
||||
cte.UNIVERSITY: 'SecondarySchool',
|
||||
cte.LABORATORY_AND_RESEARCH_CENTER: 'SecondarySchool',
|
||||
cte.STAND_ALONE_RETAIL: 'RetailStandalone',
|
||||
cte.HOSPITAL: 'Hospital',
|
||||
cte.OUT_PATIENT_HEALTH_CARE: 'Outpatient',
|
||||
cte.HEALTH_CARE: 'Outpatient',
|
||||
cte.RETIREMENT_HOME_OR_ORPHANAGE: 'SmallHotel',
|
||||
cte.COMMERCIAL: 'RetailStripmall',
|
||||
cte.STRIP_MALL: 'RetailStripmall',
|
||||
cte.SUPERMARKET: 'RetailStripmall',
|
||||
cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD: 'RetailStandalone',
|
||||
cte.RETAIL_SHOP_WITH_REFRIGERATED_FOOD: 'RetailStandalone',
|
||||
cte.RESTAURANT: 'FullServiceRestaurant',
|
||||
cte.QUICK_SERVICE_RESTAURANT: 'QuickServiceRestaurant',
|
||||
cte.FULL_SERVICE_RESTAURANT: 'FullServiceRestaurant',
|
||||
cte.HOTEL: 'SmallHotel',
|
||||
cte.HOTEL_MEDIUM_CLASS: 'SmallHotel',
|
||||
cte.SMALL_HOTEL: 'SmallHotel',
|
||||
cte.LARGE_HOTEL: 'LargeHotel',
|
||||
cte.DORMITORY: 'SmallHotel',
|
||||
cte.EVENT_LOCATION: 'n/a',
|
||||
cte.CONVENTION_CENTER: 'n/a',
|
||||
cte.HALL: 'n/a',
|
||||
cte.GREEN_HOUSE: 'n/a',
|
||||
cte.INDUSTRY: 'n/a',
|
||||
cte.WORKSHOP: 'n/a',
|
||||
cte.WAREHOUSE: 'Warehouse',
|
||||
cte.WAREHOUSE_REFRIGERATED: 'Warehouse',
|
||||
cte.SPORTS_LOCATION: 'n/a',
|
||||
cte.SPORTS_ARENA: 'n/a',
|
||||
cte.GYMNASIUM: 'n/a',
|
||||
cte.MOTION_PICTURE_THEATRE: 'n/a',
|
||||
cte.MUSEUM: 'n/a',
|
||||
cte.PERFORMING_ARTS_THEATRE: 'n/a',
|
||||
cte.TRANSPORTATION: 'n/a',
|
||||
cte.AUTOMOTIVE_FACILITY: 'n/a',
|
||||
cte.PARKING_GARAGE: 'n/a',
|
||||
cte.RELIGIOUS: 'n/a',
|
||||
cte.NON_HEATED: 'n/a'
|
||||
}
|
||||
|
||||
@property
|
||||
def dictionary(self) -> dict:
|
||||
return self._dictionary
|
|
@ -0,0 +1,78 @@
|
|||
"""
|
||||
Dictionaries module for hub function to NREL construction function
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Guille Gutierrez Guillermo.GutierrezMorote@concordia.ca
|
||||
"""
|
||||
|
||||
import hub.helpers.constants as cte
|
||||
|
||||
|
||||
class HubFunctionToNrelConstructionFunction:
|
||||
|
||||
def __init__(self):
|
||||
self._dictionary = {
|
||||
cte.RESIDENTIAL: 'residential',
|
||||
cte.SINGLE_FAMILY_HOUSE: 'residential',
|
||||
cte.MULTI_FAMILY_HOUSE: 'midrise apartment',
|
||||
cte.ROW_HOUSE: 'midrise apartment',
|
||||
cte.MID_RISE_APARTMENT: 'midrise apartment',
|
||||
cte.HIGH_RISE_APARTMENT: 'high-rise apartment',
|
||||
cte.OFFICE_AND_ADMINISTRATION: 'medium office',
|
||||
cte.SMALL_OFFICE: 'small office',
|
||||
cte.MEDIUM_OFFICE: 'medium office',
|
||||
cte.LARGE_OFFICE: 'large office',
|
||||
cte.COURTHOUSE: 'medium office',
|
||||
cte.FIRE_STATION: 'n/a',
|
||||
cte.PENITENTIARY: 'large hotel',
|
||||
cte.POLICE_STATION: 'n/a',
|
||||
cte.POST_OFFICE: 'medium office',
|
||||
cte.LIBRARY: 'medium office',
|
||||
cte.EDUCATION: 'secondary school',
|
||||
cte.PRIMARY_SCHOOL: 'primary school',
|
||||
cte.PRIMARY_SCHOOL_WITH_SHOWER: 'primary school',
|
||||
cte.SECONDARY_SCHOOL: 'secondary school',
|
||||
cte.UNIVERSITY: 'secondary school',
|
||||
cte.LABORATORY_AND_RESEARCH_CENTER: 'secondary school',
|
||||
cte.STAND_ALONE_RETAIL: 'stand-alone retail',
|
||||
cte.HOSPITAL: 'hospital',
|
||||
cte.OUT_PATIENT_HEALTH_CARE: 'outpatient healthcare',
|
||||
cte.HEALTH_CARE: 'outpatient healthcare',
|
||||
cte.RETIREMENT_HOME_OR_ORPHANAGE: 'small hotel',
|
||||
cte.COMMERCIAL: 'strip mall',
|
||||
cte.STRIP_MALL: 'strip mall',
|
||||
cte.SUPERMARKET: 'supermarket',
|
||||
cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD: 'stand-alone retail',
|
||||
cte.RETAIL_SHOP_WITH_REFRIGERATED_FOOD: 'stand-alone retail',
|
||||
cte.RESTAURANT: 'full service restaurant',
|
||||
cte.QUICK_SERVICE_RESTAURANT: 'quick service restaurant',
|
||||
cte.FULL_SERVICE_RESTAURANT: 'full service restaurant',
|
||||
cte.HOTEL: 'small hotel',
|
||||
cte.HOTEL_MEDIUM_CLASS: 'small hotel',
|
||||
cte.SMALL_HOTEL: 'small hotel',
|
||||
cte.LARGE_HOTEL: 'large hotel',
|
||||
cte.DORMITORY: 'small hotel',
|
||||
cte.EVENT_LOCATION: 'n/a',
|
||||
cte.CONVENTION_CENTER: 'n/a',
|
||||
cte.HALL: 'n/a',
|
||||
cte.GREEN_HOUSE: 'n/a',
|
||||
cte.INDUSTRY: 'n/a',
|
||||
cte.WORKSHOP: 'n/a',
|
||||
cte.WAREHOUSE: 'warehouse',
|
||||
cte.WAREHOUSE_REFRIGERATED: 'warehouse',
|
||||
cte.SPORTS_LOCATION: 'n/a',
|
||||
cte.SPORTS_ARENA: 'n/a',
|
||||
cte.GYMNASIUM: 'n/a',
|
||||
cte.MOTION_PICTURE_THEATRE: 'n/a',
|
||||
cte.MUSEUM: 'n/a',
|
||||
cte.PERFORMING_ARTS_THEATRE: 'n/a',
|
||||
cte.TRANSPORTATION: 'n/a',
|
||||
cte.AUTOMOTIVE_FACILITY: 'n/aquebec_to_hub',
|
||||
cte.PARKING_GARAGE: 'n/a',
|
||||
cte.RELIGIOUS: 'n/a',
|
||||
cte.NON_HEATED: 'n/a'
|
||||
}
|
||||
|
||||
@property
|
||||
def dictionary(self) -> dict:
|
||||
return self._dictionary
|
78
hub/helpers/data/hub_usage_to_comnet_usage.py
Normal file
78
hub/helpers/data/hub_usage_to_comnet_usage.py
Normal file
|
@ -0,0 +1,78 @@
|
|||
"""
|
||||
Dictionaries module for hub usage to Comnet usage
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Guille Gutierrez Guillermo.GutierrezMorote@concordia.ca
|
||||
"""
|
||||
|
||||
import hub.helpers.constants as cte
|
||||
|
||||
|
||||
class HubUsageToComnetUsage:
|
||||
|
||||
def __init__(self):
|
||||
self._dictionary = {
|
||||
cte.RESIDENTIAL: 'BA Multifamily',
|
||||
cte.SINGLE_FAMILY_HOUSE: 'BA Multifamily',
|
||||
cte.MULTI_FAMILY_HOUSE: 'BA Multifamily',
|
||||
cte.ROW_HOUSE: 'BA Multifamily',
|
||||
cte.MID_RISE_APARTMENT: 'BA Multifamily',
|
||||
cte.HIGH_RISE_APARTMENT: 'BA Multifamily',
|
||||
cte.OFFICE_AND_ADMINISTRATION: 'BA Office',
|
||||
cte.SMALL_OFFICE: 'BA Office',
|
||||
cte.MEDIUM_OFFICE: 'BA Office',
|
||||
cte.LARGE_OFFICE: 'BA Office',
|
||||
cte.COURTHOUSE: 'BA Courthouse',
|
||||
cte.FIRE_STATION: 'BA Fire Station',
|
||||
cte.PENITENTIARY: 'BA Penitentiary',
|
||||
cte.POLICE_STATION: 'BA Police Station',
|
||||
cte.POST_OFFICE: 'BA Post Office',
|
||||
cte.LIBRARY: 'BA Library',
|
||||
cte.EDUCATION: 'BA School/University',
|
||||
cte.PRIMARY_SCHOOL: 'BA School/University',
|
||||
cte.PRIMARY_SCHOOL_WITH_SHOWER: 'BA School/University',
|
||||
cte.SECONDARY_SCHOOL: 'BA School/University',
|
||||
cte.UNIVERSITY: 'BA School/University',
|
||||
cte.LABORATORY_AND_RESEARCH_CENTER: 'BA School/University',
|
||||
cte.STAND_ALONE_RETAIL: 'BA Retail',
|
||||
cte.HOSPITAL: 'BA Hospital',
|
||||
cte.OUT_PATIENT_HEALTH_CARE: 'BA Healthcare Clinic',
|
||||
cte.HEALTH_CARE: 'BA Healthcare Clinic',
|
||||
cte.RETIREMENT_HOME_OR_ORPHANAGE: 'BA Healthcare Clinic',
|
||||
cte.COMMERCIAL: 'BA Retail',
|
||||
cte.STRIP_MALL: 'BA Retail',
|
||||
cte.SUPERMARKET: 'BA Retail',
|
||||
cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD: 'BA Retail',
|
||||
cte.RETAIL_SHOP_WITH_REFRIGERATED_FOOD: 'BA Retail',
|
||||
cte.RESTAURANT: 'BA Dining: Bar Lounge/Leisure',
|
||||
cte.QUICK_SERVICE_RESTAURANT: 'BA Dining: Cafeteria/Fast Food',
|
||||
cte.FULL_SERVICE_RESTAURANT: 'BA Dining: Bar Lounge/Leisure',
|
||||
cte.HOTEL: 'BA Hotel',
|
||||
cte.HOTEL_MEDIUM_CLASS: 'BA Motel',
|
||||
cte.SMALL_HOTEL: 'BA Motel',
|
||||
cte.LARGE_HOTEL: 'BA Hotel',
|
||||
cte.DORMITORY: 'BA Dormitory',
|
||||
cte.EVENT_LOCATION: 'BA Convention Center',
|
||||
cte.CONVENTION_CENTER: 'BA Convention Center',
|
||||
cte.HALL: 'BA Town Hall',
|
||||
cte.GREEN_HOUSE: 'n/a',
|
||||
cte.INDUSTRY: 'BA Manufacturing Facility',
|
||||
cte.WORKSHOP: 'BA Workshop',
|
||||
cte.WAREHOUSE: 'BA Warehouse',
|
||||
cte.WAREHOUSE_REFRIGERATED: 'BA Warehouse',
|
||||
cte.SPORTS_LOCATION: 'BA Exercise Center',
|
||||
cte.SPORTS_ARENA: 'BA Sports Arena',
|
||||
cte.GYMNASIUM: 'BA Gymnasium',
|
||||
cte.MOTION_PICTURE_THEATRE: 'BA Motion Picture Theater',
|
||||
cte.MUSEUM: 'BA Museum',
|
||||
cte.PERFORMING_ARTS_THEATRE: 'BA Performing Arts Theater',
|
||||
cte.TRANSPORTATION: 'BA Transportation',
|
||||
cte.AUTOMOTIVE_FACILITY: 'BA Automotive Facility',
|
||||
cte.PARKING_GARAGE: 'BA Parking Garage',
|
||||
cte.RELIGIOUS: 'BA Religious Building',
|
||||
cte.NON_HEATED: 'n/a'
|
||||
}
|
||||
|
||||
@property
|
||||
def dictionary(self) -> dict:
|
||||
return self._dictionary
|
78
hub/helpers/data/hub_usage_to_hft_usage.py
Normal file
78
hub/helpers/data/hub_usage_to_hft_usage.py
Normal file
|
@ -0,0 +1,78 @@
|
|||
"""
|
||||
Dictionaries module for hub usage to Hft usage
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Guille Gutierrez Guillermo.GutierrezMorote@concordia.ca
|
||||
"""
|
||||
|
||||
import hub.helpers.constants as cte
|
||||
|
||||
|
||||
class HubUsageToHftUsage:
|
||||
|
||||
def __init__(self):
|
||||
self._dictionary = {
|
||||
cte.RESIDENTIAL: 'residential',
|
||||
cte.SINGLE_FAMILY_HOUSE: 'single family house',
|
||||
cte.MULTI_FAMILY_HOUSE: 'multifamily house',
|
||||
cte.ROW_HOUSE: 'single family house',
|
||||
cte.MID_RISE_APARTMENT: 'multifamily house',
|
||||
cte.HIGH_RISE_APARTMENT: 'multifamily house',
|
||||
cte.OFFICE_AND_ADMINISTRATION: 'office and administration',
|
||||
cte.SMALL_OFFICE: 'office and administration',
|
||||
cte.MEDIUM_OFFICE: 'office and administration',
|
||||
cte.LARGE_OFFICE: 'office and administration',
|
||||
cte.COURTHOUSE: 'office and administration',
|
||||
cte.FIRE_STATION: 'office and administration',
|
||||
cte.PENITENTIARY: 'school with shower',
|
||||
cte.POLICE_STATION: 'office and administration',
|
||||
cte.POST_OFFICE: 'office and administration',
|
||||
cte.LIBRARY: 'office and administration',
|
||||
cte.EDUCATION: 'education',
|
||||
cte.PRIMARY_SCHOOL: 'school without shower',
|
||||
cte.PRIMARY_SCHOOL_WITH_SHOWER: 'school with shower',
|
||||
cte.SECONDARY_SCHOOL: 'education',
|
||||
cte.UNIVERSITY: 'education',
|
||||
cte.LABORATORY_AND_RESEARCH_CENTER: 'laboratory and research centers',
|
||||
cte.STAND_ALONE_RETAIL: 'retail',
|
||||
cte.HOSPITAL: 'health care',
|
||||
cte.OUT_PATIENT_HEALTH_CARE: 'health care',
|
||||
cte.HEALTH_CARE: 'health care',
|
||||
cte.RETIREMENT_HOME_OR_ORPHANAGE: 'Home for the aged or orphanage',
|
||||
cte.COMMERCIAL: 'retail',
|
||||
cte.STRIP_MALL: 'retail',
|
||||
cte.SUPERMARKET: 'retail shop / refrigerated food',
|
||||
cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD: 'retail',
|
||||
cte.RETAIL_SHOP_WITH_REFRIGERATED_FOOD: 'retail shop / refrigerated food',
|
||||
cte.RESTAURANT: 'restaurant',
|
||||
cte.QUICK_SERVICE_RESTAURANT: 'restaurant',
|
||||
cte.FULL_SERVICE_RESTAURANT: 'restaurant',
|
||||
cte.HOTEL: 'hotel',
|
||||
cte.HOTEL_MEDIUM_CLASS: 'hotel (Medium-class)',
|
||||
cte.SMALL_HOTEL: 'hotel',
|
||||
cte.LARGE_HOTEL: 'hotel',
|
||||
cte.DORMITORY: 'dormitory',
|
||||
cte.EVENT_LOCATION: 'event location',
|
||||
cte.CONVENTION_CENTER: 'event location',
|
||||
cte.HALL: 'hall',
|
||||
cte.GREEN_HOUSE: 'green house',
|
||||
cte.INDUSTRY: 'industry',
|
||||
cte.WORKSHOP: 'industry',
|
||||
cte.WAREHOUSE: 'industry',
|
||||
cte.WAREHOUSE_REFRIGERATED: 'industry',
|
||||
cte.SPORTS_LOCATION: 'sport location',
|
||||
cte.SPORTS_ARENA: 'sport location',
|
||||
cte.GYMNASIUM: 'sport location',
|
||||
cte.MOTION_PICTURE_THEATRE: 'event location',
|
||||
cte.MUSEUM: 'event location',
|
||||
cte.PERFORMING_ARTS_THEATRE: 'event location',
|
||||
cte.TRANSPORTATION: 'n/a',
|
||||
cte.AUTOMOTIVE_FACILITY: 'n/a',
|
||||
cte.PARKING_GARAGE: 'n/a',
|
||||
cte.RELIGIOUS: 'event location',
|
||||
cte.NON_HEATED: 'non-heated'
|
||||
}
|
||||
|
||||
@property
|
||||
def dictionary(self) -> dict:
|
||||
return self._dictionary
|
78
hub/helpers/data/hub_usage_to_nrcan_usage.py
Normal file
78
hub/helpers/data/hub_usage_to_nrcan_usage.py
Normal file
|
@ -0,0 +1,78 @@
|
|||
"""
|
||||
Dictionaries module for hub usage to NRCAN usage
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Guille Gutierrez Guillermo.GutierrezMorote@concordia.ca
|
||||
"""
|
||||
|
||||
import hub.helpers.constants as cte
|
||||
|
||||
|
||||
class HubUsageToNrcanUsage:
|
||||
|
||||
def __init__(self):
|
||||
self._dictionary = {
|
||||
cte.RESIDENTIAL: 'Multi-unit residential building',
|
||||
cte.SINGLE_FAMILY_HOUSE: 'Multi-unit residential building',
|
||||
cte.MULTI_FAMILY_HOUSE: 'Multi-unit residential building',
|
||||
cte.ROW_HOUSE: 'Multi-unit residential building',
|
||||
cte.MID_RISE_APARTMENT: 'Multi-unit residential building',
|
||||
cte.HIGH_RISE_APARTMENT: 'Multi-unit residential building',
|
||||
cte.OFFICE_AND_ADMINISTRATION: 'Office',
|
||||
cte.SMALL_OFFICE: 'Office',
|
||||
cte.MEDIUM_OFFICE: 'Office',
|
||||
cte.LARGE_OFFICE: 'Office',
|
||||
cte.COURTHOUSE: 'Courthouse',
|
||||
cte.FIRE_STATION: 'Fire station',
|
||||
cte.PENITENTIARY: 'Penitentiary',
|
||||
cte.POLICE_STATION: 'Police station',
|
||||
cte.POST_OFFICE: 'Post office',
|
||||
cte.LIBRARY: 'Library',
|
||||
cte.EDUCATION: 'School/university',
|
||||
cte.PRIMARY_SCHOOL: 'School/university',
|
||||
cte.PRIMARY_SCHOOL_WITH_SHOWER: 'School/university',
|
||||
cte.SECONDARY_SCHOOL: 'School/university',
|
||||
cte.UNIVERSITY: 'School/university',
|
||||
cte.LABORATORY_AND_RESEARCH_CENTER: 'School/university',
|
||||
cte.STAND_ALONE_RETAIL: 'Retail',
|
||||
cte.HOSPITAL: 'Hospital',
|
||||
cte.OUT_PATIENT_HEALTH_CARE: 'Health-care clinic',
|
||||
cte.HEALTH_CARE: 'Health-care clinic',
|
||||
cte.RETIREMENT_HOME_OR_ORPHANAGE: 'Health-care clinic',
|
||||
cte.COMMERCIAL: 'Retail',
|
||||
cte.STRIP_MALL: 'Retail',
|
||||
cte.SUPERMARKET: 'Retail',
|
||||
cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD: 'Retail',
|
||||
cte.RETAIL_SHOP_WITH_REFRIGERATED_FOOD: 'Retail',
|
||||
cte.RESTAURANT: 'Dining - bar/lounge',
|
||||
cte.QUICK_SERVICE_RESTAURANT: 'Dining - cafeteria',
|
||||
cte.FULL_SERVICE_RESTAURANT: 'Dining - bar/lounge',
|
||||
cte.HOTEL: 'Hotel',
|
||||
cte.HOTEL_MEDIUM_CLASS: 'Motel',
|
||||
cte.SMALL_HOTEL: 'Motel',
|
||||
cte.LARGE_HOTEL: 'Hotel',
|
||||
cte.DORMITORY: 'Dormitory',
|
||||
cte.EVENT_LOCATION: 'Convention centre',
|
||||
cte.CONVENTION_CENTER: 'Convention centre',
|
||||
cte.HALL: 'Town hall',
|
||||
cte.GREEN_HOUSE: 'n/a',
|
||||
cte.INDUSTRY: 'Manufacturing facility',
|
||||
cte.WORKSHOP: 'Workshop',
|
||||
cte.WAREHOUSE: 'Warehouse',
|
||||
cte.WAREHOUSE_REFRIGERATED: 'Warehouse - refrigerated',
|
||||
cte.SPORTS_LOCATION: 'Exercise centre',
|
||||
cte.SPORTS_ARENA: 'Sports arena',
|
||||
cte.GYMNASIUM: 'Gymnasium',
|
||||
cte.MOTION_PICTURE_THEATRE: 'Motion picture theatre',
|
||||
cte.MUSEUM: 'Museum',
|
||||
cte.PERFORMING_ARTS_THEATRE: 'Performing arts theatre',
|
||||
cte.TRANSPORTATION: 'Transportation',
|
||||
cte.AUTOMOTIVE_FACILITY: 'Automotive facility',
|
||||
cte.PARKING_GARAGE: 'Parking garage',
|
||||
cte.RELIGIOUS: 'Religious',
|
||||
cte.NON_HEATED: 'n/a'
|
||||
}
|
||||
|
||||
@property
|
||||
def dictionary(self) -> dict:
|
||||
return self._dictionary
|
557
hub/helpers/data/montreal_function_to_hub_function.py
Normal file
557
hub/helpers/data/montreal_function_to_hub_function.py
Normal file
|
@ -0,0 +1,557 @@
|
|||
"""
|
||||
Dictionaries module for Montreal function to hub function
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Guille Gutierrez Guillermo.GutierrezMorote@concordia.ca
|
||||
"""
|
||||
|
||||
import hub.helpers.constants as cte
|
||||
|
||||
|
||||
class MontrealFunctionToHubFunction:
|
||||
|
||||
# Todo: "office" "Mausolée" and "hotel/motel" need to be replaced for a constant value.
|
||||
def __init__(self):
|
||||
self._dictionary = {
|
||||
"Administration publique municipale et régionale": "Office",
|
||||
"Administration publique provinciale": "Office",
|
||||
"Agence de voyages ou d'expéditions": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Aiguillage et cour de triage de chemins de fer": cte.WAREHOUSE,
|
||||
"Amphithéâtre et auditorium": cte.EVENT_LOCATION,
|
||||
"Archives (incluant cinémathèquevidéothèque)": cte.EVENT_LOCATION,
|
||||
"Aréna et activités connexes (patinage sur glace)": cte.SPORTS_LOCATION,
|
||||
"Association civiquesociale et fraternelle": cte.OFFICE_AND_ADMINISTRATION,
|
||||
"Associationunion ou coop d'épargne et de prêt (inclus caisses populaires locales)": cte.OFFICE_AND_ADMINISTRATION,
|
||||
"Atelier d'artiste": cte.WAREHOUSE,
|
||||
"Atelier d'artiste ou d'artisan": cte.WAREHOUSE,
|
||||
"Atelier d'usinage": cte.WAREHOUSE,
|
||||
"Atelier de mécanicien-dentiste": cte.WAREHOUSE,
|
||||
"Auberge ou gîte touristique (Hôtel à caractère familiald'au plus 3 étages en hauteur de bâtiment)": cte.SMALL_HOTEL,
|
||||
"Autoroute": cte.WAREHOUSE,
|
||||
"Autres activités agricoles": cte.INDUSTRY,
|
||||
"Autres activités culturelles": cte.EVENT_LOCATION,
|
||||
"Autres activités d'hébergement": cte.MULTI_FAMILY_HOUSE,
|
||||
"Autres activités d'impression commerciale": cte.WAREHOUSE,
|
||||
"Autres activités de la restauration": cte.WAREHOUSE,
|
||||
"Autres activités de récupération et de triage": cte.WAREHOUSE,
|
||||
"Autres activités de vente au détail (inclus les kiosques d'autres choses que vêtements et accessoires de vêtements)": cte.STAND_ALONE_RETAIL,
|
||||
"Autres activités de vente au détail de produits de l'alimentation": cte.STAND_ALONE_RETAIL,
|
||||
"Autres activités de vente au détail de vêtements comme les accessoires": cte.STAND_ALONE_RETAIL,
|
||||
"Autres activités de vente au détail reliées aux automobilesaux embarcationsaux avions et à leurs accessoires": cte.STAND_ALONE_RETAIL,
|
||||
"Autres activités de vente en gros": cte.WAREHOUSE,
|
||||
"Autres activités minières et extraction de carrières de minerais non métalliques (sauf le pétrole)": cte.INDUSTRY,
|
||||
"Autres activités nautiques": cte.WAREHOUSE,
|
||||
"Autres activités religieuses": cte.OFFICE_AND_ADMINISTRATION,
|
||||
"Autres activités reliées au transport de matériaux par camion": cte.WAREHOUSE,
|
||||
"Autres activités reliées au transport par autobus": cte.WAREHOUSE,
|
||||
"Autres activités reliées au transport par chemin de fer": cte.WAREHOUSE,
|
||||
"Autres activités sportives (inclus centres de tir à l'arc)": cte.SPORTS_LOCATION,
|
||||
"Autres aménagements d'assemblées publiques": cte.OFFICE_AND_ADMINISTRATION,
|
||||
"Autres aménagements publics pour différentes activités": cte.OFFICE_AND_ADMINISTRATION,
|
||||
"Autres aéroports": cte.WAREHOUSE,
|
||||
"Autres bases et réserves militaires": cte.WAREHOUSE,
|
||||
"Autres centres de recherche": cte.SECONDARY_SCHOOL,
|
||||
"Autres centres de services sociaux ou bureaux de travailleurs sociaux": cte.OFFICE_AND_ADMINISTRATION,
|
||||
"Autres centres et réseaux de télévision et de radiodiffusion (système combiné)": "Office",
|
||||
"Autres entreposages": cte.WAREHOUSE,
|
||||
"Autres espaces de plancher inoccupé": cte.WAREHOUSE,
|
||||
"Autres espaces de terrain et étendues d'eau inexploités": cte.WAREHOUSE,
|
||||
"Autres expositions d'objets culturels": cte.EVENT_LOCATION,
|
||||
"Autres immeubles résidentiels": cte.MID_RISE_APARTMENT,
|
||||
"Autres industries d'appareils d'éclairage": cte.INDUSTRY,
|
||||
"Autres industries de boissons": cte.INDUSTRY,
|
||||
"Autres industries de la fabrication d'éléments de charpentes métalliques": cte.INDUSTRY,
|
||||
"Autres industries de la fonte et de l'affinage de métaux non-ferreux": cte.INDUSTRY,
|
||||
"Autres industries de la machinerie industrielle et de l'équipement industriel": cte.INDUSTRY,
|
||||
"Autres industries de pièces et d'accessoires pour véhicules automobiles": cte.INDUSTRY,
|
||||
"Autres industries de produits alimentaires": cte.INDUSTRY,
|
||||
"Autres industries de produits alimentaires à base de fruits et de légumes": cte.INDUSTRY,
|
||||
"Autres industries de produits chimiques": cte.INDUSTRY,
|
||||
"Autres industries de produits du pétrole et du charbon": cte.INDUSTRY,
|
||||
"Autres industries de produits en béton": cte.INDUSTRY,
|
||||
"Autres industries de produits en caoutchouc": cte.INDUSTRY,
|
||||
"Autres industries de produits en fil métallique": cte.INDUSTRY,
|
||||
"Autres industries de produits en plastique": cte.INDUSTRY,
|
||||
"Autres industries de produits manufacturés": cte.INDUSTRY,
|
||||
"Autres industries de produits métalliques d'ornement et d'architecture": cte.INDUSTRY,
|
||||
"Autres industries de produits métalliques divers": cte.INDUSTRY,
|
||||
"Autres industries de produits textiles": cte.INDUSTRY,
|
||||
"Autres industries de produits électriques.": cte.INDUSTRY,
|
||||
"Autres industries de vêtements coupés cousus pour femmes et filles": cte.INDUSTRY,
|
||||
"Autres industries du bois": cte.INDUSTRY,
|
||||
"Autres industries du laminagedu moulage et de l'extrusion de métaux non-ferreux": cte.INDUSTRY,
|
||||
"Autres industries du matériel de transport": cte.INDUSTRY,
|
||||
"Autres industries du matériel scientifique et professionnel": cte.INDUSTRY,
|
||||
"Autres industries du matériel électrique d'usage industriel": cte.INDUSTRY,
|
||||
"Autres industries du matériel électronique et de communication": cte.INDUSTRY,
|
||||
"Autres industries du meuble de bureau": cte.INDUSTRY,
|
||||
"Autres industries du meuble et d'articles d'ameublement": cte.INDUSTRY,
|
||||
"Autres industries du meuble résidentiel.": cte.INDUSTRY,
|
||||
"Autres industries du papier": cte.INDUSTRY,
|
||||
"Autres industries sidérurgiques": cte.INDUSTRY,
|
||||
"Autres infrastructures de transport maritime": cte.INDUSTRY,
|
||||
"Autres installations inhérentes aux ordures": cte.WAREHOUSE,
|
||||
"Autres installations pour les sports": cte.SPORTS_LOCATION,
|
||||
"Autres institutions de formation spécialisée (inclus écoles de langues de coutured'arts martiaux de combats et autres)": cte.SECONDARY_SCHOOL,
|
||||
"Autres lieux d'assemblée pour les loisirs": cte.OFFICE_AND_ADMINISTRATION,
|
||||
"Autres locaux de groupes": cte.OFFICE_AND_ADMINISTRATION,
|
||||
"Autres maisons d'institutions religieuses": cte.OFFICE_AND_ADMINISTRATION,
|
||||
"Autres maisons et locaux fraternels": cte.OFFICE_AND_ADMINISTRATION,
|
||||
"Autres maisons pour personnes retraitées": cte.OFFICE_AND_ADMINISTRATION,
|
||||
"Autres parcs": cte.WAREHOUSE,
|
||||
"Autres routes et voies publiques": "Office",
|
||||
"Autres résidences d'étudiants": "Office",
|
||||
"Autres résidences provisoires": "Office",
|
||||
"Autres services connexes aux valeurs mobilières et aux marchandises": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Autres services d'affaires": "Office",
|
||||
"Autres services d'aqueduc et d'irrigation": cte.WAREHOUSE,
|
||||
"Autres services de construction de bâtiments": cte.WAREHOUSE,
|
||||
"Autres services de génie civil (entrepreneur général)": cte.WAREHOUSE,
|
||||
"Autres services de l'automobile": cte.WAREHOUSE,
|
||||
"Autres services de location (sauf entreposage)": cte.WAREHOUSE,
|
||||
"Autres services de nettoyage": cte.WAREHOUSE,
|
||||
"Autres services de réparation et d'entretien d'articles personnels et ménagers": cte.STAND_ALONE_RETAIL,
|
||||
"Autres services de soins thérapeutiques": cte.OUT_PATIENT_HEALTH_CARE,
|
||||
"Autres services de travaux de construction spécialisés": cte.WAREHOUSE,
|
||||
"Autres services de travaux de finition de bâtiment (entrepreneur spécialisé)": cte.WAREHOUSE,
|
||||
"Autres services de télécommunications": cte.STAND_ALONE_RETAIL,
|
||||
"Autres services divers": cte.WAREHOUSE,
|
||||
"Autres services du pétrole": cte.WAREHOUSE,
|
||||
"Autres services gouvernementaux": cte.OFFICE_AND_ADMINISTRATION,
|
||||
"Autres services immobiliersfinanciers et d'assurance": cte.OFFICE_AND_ADMINISTRATION,
|
||||
"Autres services médicaux et de santé": cte.OUT_PATIENT_HEALTH_CARE,
|
||||
"Autres services personnels": cte.OUT_PATIENT_HEALTH_CARE,
|
||||
"Autres services pour animaux domestiques": cte.OUT_PATIENT_HEALTH_CARE,
|
||||
"Autres services pour le transport": cte.WAREHOUSE,
|
||||
"Autres services pour les bâtiments": cte.WAREHOUSE,
|
||||
"Autres services professionnels": cte.OFFICE_AND_ADMINISTRATION,
|
||||
"Autres services publics (infrastructure)": cte.WAREHOUSE,
|
||||
"Autres services reliés à la foresterie": cte.WAREHOUSE,
|
||||
"Autres terrains de jeux et pistes athlétiques": cte.SPORTS_LOCATION,
|
||||
"Autres transports par avion (infrastructure)": cte.WAREHOUSE,
|
||||
"Autres transports par véhicule automobile": cte.WAREHOUSE,
|
||||
"Autres transportscommunications et services publics (infrastructure)": cte.GREEN_HOUSE,
|
||||
"Autres types de production végétale": cte.GREEN_HOUSE,
|
||||
"Autres ventes au détail de marchandises en général": cte.STAND_ALONE_RETAIL,
|
||||
"Autres établissements avec service complet ou restreint": cte.STAND_ALONE_RETAIL,
|
||||
"Autres établissements de débits de boissons alcoolisées": cte.STAND_ALONE_RETAIL,
|
||||
"Aéroport et aérodrome": cte.EVENT_LOCATION,
|
||||
"Bar à crème glacée": cte.QUICK_SERVICE_RESTAURANT,
|
||||
"Bar à spectacles": cte.FULL_SERVICE_RESTAURANT,
|
||||
"Bibliothèque": cte.OFFICE_AND_ADMINISTRATION,
|
||||
"Bureau de poste": cte.OFFICE_AND_ADMINISTRATION,
|
||||
"Bâtiment incendié et inutilisable": cte.NON_HEATED,
|
||||
"C.E.G.E.P. (collège d'enseignement général et professionnel)": cte.SECONDARY_SCHOOL,
|
||||
"Centre commercial de quartier (15 à 44 magasins)": cte.STRIP_MALL,
|
||||
"Centre commercial de voisinage (14 magasins et moins)": cte.STAND_ALONE_RETAIL,
|
||||
"Centre commercial local (45 à 99 magasins)": cte.STRIP_MALL,
|
||||
"Centre commercial régional (100 à 199 magasins)": cte.STRIP_MALL,
|
||||
"Centre commercial super régional (200 magasins et plus)": cte.STRIP_MALL,
|
||||
"Centre communautaire ou de quartier (inclus Centre diocésain)": cte.OFFICE_AND_ADMINISTRATION,
|
||||
"Centre d'accueil ou établissement curatif (inclus centre de réadaptation pour handicapés physiques et mentaux)": cte.OUT_PATIENT_HEALTH_CARE,
|
||||
"Centre d'appels téléphoniques": "Office",
|
||||
"Centre d'entraide et de ressources communautaires (inclus ressources d'hébergement de meubles et d'alimentation)": cte.OUT_PATIENT_HEALTH_CARE,
|
||||
"Centre d'entreposage de produits pétroliers (pétrole brutgaz pétrole liquéfiémazout domestique et autres produits raffinés)": cte.WAREHOUSE,
|
||||
"Centre d'entreposage du gaz (avant distrib.aux consommateurs)": cte.WAREHOUSE,
|
||||
"Centre de distribution ou d'expédition de marchandises diverses": cte.WAREHOUSE,
|
||||
"Centre de recherche d'activités émergentes (inclus technologies langagières et la photonique)": cte.SECONDARY_SCHOOL,
|
||||
"Centre de santé (inclus saunas spas et bains thérapeutiques ou turcs)": cte.OUT_PATIENT_HEALTH_CARE,
|
||||
"Centre de services sociaux (C.S.S. et C.R.S.S.S.)": cte.OUT_PATIENT_HEALTH_CARE,
|
||||
"Centre de transfert ou d'entreposage de déchets dangereux": cte.WAREHOUSE,
|
||||
"Centre de tri postal": cte.WAREHOUSE,
|
||||
"Centre de vérification technique d'automobiles et d'estimation": cte.WAREHOUSE,
|
||||
"Centre local de services communautaires (C.L.S.C.)": cte.OFFICE_AND_ADMINISTRATION,
|
||||
"Centre militaire de transport et d'entreposage": cte.WAREHOUSE,
|
||||
"Centre récréatif en général (activités récréatives diversifiées pour tous groupes d'âge)": cte.EVENT_LOCATION,
|
||||
"Centre sportif multidisciplinaire (couvert).": cte.SPORTS_LOCATION,
|
||||
"Chalet ou maison de villégiature": cte.SINGLE_FAMILY_HOUSE,
|
||||
"Chemin de fer (sauf train touristiqueaiguillage et cour de triage)": cte.WAREHOUSE,
|
||||
"Cimetière": cte.WAREHOUSE,
|
||||
"Cinéma": cte.EVENT_LOCATION,
|
||||
"Clinique médicale (cabinet de médecins généralistes)": cte.OUT_PATIENT_HEALTH_CARE,
|
||||
"Commission scolaire": cte.OFFICE_AND_ADMINISTRATION,
|
||||
"Conserveriemarinagesaumurage et séchage de fruits et de légumes": cte.WAREHOUSE,
|
||||
"Construction d'immeubles pour revente": cte.WAREHOUSE,
|
||||
"Couvent": cte.EVENT_LOCATION,
|
||||
"Dépanneur (sans vente d'essence)": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Entreposage de tout genre": cte.WAREHOUSE,
|
||||
"Entreposage du mobilier et d'appareils ménagersincluant les mini-entrepôts": cte.WAREHOUSE,
|
||||
"Entreposage en vrac à l'extérieur": cte.WAREHOUSE,
|
||||
"Entreposage frigorifique (sauf les armoires frigorifiques)": cte.WAREHOUSE,
|
||||
"Entreprise d'excavationde nivellementde défrichage et installation de fosses septiques": cte.WAREHOUSE,
|
||||
"Entrepôt pour le transport par camion": cte.WAREHOUSE,
|
||||
"Entretien et équipement de chemins de fer": cte.WAREHOUSE,
|
||||
"Espace de plancher inoccupé dont l'usage serait commercial autre": cte.NON_HEATED,
|
||||
"Espace de plancher inoccupé dont l'usage serait industriel": cte.NON_HEATED,
|
||||
"Espace de plancher inoccupé dont l'usage serait pour des fins culturelles": cte.NON_HEATED,
|
||||
"Espace de plancher inoccupé dont l'usage serait pour services publics": cte.NON_HEATED,
|
||||
"Espace de rangement (condo non résidentiel)": cte.NON_HEATED,
|
||||
"Espace de rangement (condo)": cte.NON_HEATED,
|
||||
"Espace de terrain non aménagé et non exploité (sauf l'exploitation non commerciale de la forêt)": cte.NON_HEATED,
|
||||
"Espace pour le séchage des boues provenant de l'usine d'épuration": cte.WAREHOUSE,
|
||||
"Fabrication de crème glacée et de desserts congelés": cte.INDUSTRY,
|
||||
"Fondations et organismes de charité": cte.OFFICE_AND_ADMINISTRATION,
|
||||
"Galerie d'art": cte.EVENT_LOCATION,
|
||||
"Garage d'autobus et équipement d'entretien": cte.WAREHOUSE,
|
||||
"Garage de stationnement pour automobiles (infrastructure)": cte.WAREHOUSE,
|
||||
"Garage de stationnement pour véhicules lourds (Infrastructure)": cte.WAREHOUSE,
|
||||
"Garage et équipement d'entretien pour le transport par camion (incluant garages municipaux)": cte.WAREHOUSE,
|
||||
"Gare d'autobus pour passagers": cte.WAREHOUSE,
|
||||
"Gare de chemins de fer": cte.WAREHOUSE,
|
||||
"Gymnase et formation athlétique": cte.SPORTS_LOCATION,
|
||||
"Hangar à avion": cte.WAREHOUSE,
|
||||
"Hôtel (incluant les hôtels-motels)": "Hotel/Motel",
|
||||
"Hôtel résidentiel": "Hotel/Motel",
|
||||
"Immeuble commercial": cte.STAND_ALONE_RETAIL,
|
||||
"Immeuble non résidentiel en construction": "Office",
|
||||
"Immeuble résidentiel en construction": cte.RESIDENTIAL,
|
||||
"Immeuble à bureaux": "Office",
|
||||
"Immeuble à temps partagé («time share») Propriété ou copropriété ou groupe d'usufruitier ont chacun droit de jouissancepériodique et successif.": "Office",
|
||||
"Incinérateur": cte.INDUSTRY,
|
||||
"Industrie d'accessoires vestimentaires et d'autres vêtements": cte.INDUSTRY,
|
||||
"Industrie d'alcools destinés à la consommation (distillerie)": cte.INDUSTRY,
|
||||
"Industrie d'appareils d'éclairage (sauf ampoules et tubes)": cte.INDUSTRY,
|
||||
"Industrie d'appareils orthopédiques et chirurgicaux": cte.INDUSTRY,
|
||||
"Industrie d'armoires de placards de cuisine et de coiffeuses de salle de bains en bois": cte.INDUSTRY,
|
||||
"Industrie d'articles de maison en textile et d'articles d'hygiène en textile": cte.INDUSTRY,
|
||||
"Industrie d'articles de sport et d'athlétisme": cte.INDUSTRY,
|
||||
"Industrie d'assaisonnements et de vinaigrettes": cte.INDUSTRY,
|
||||
"Industrie d'autres produits de boulangerie et de pâtisseries": cte.INDUSTRY,
|
||||
"Industrie d'autres vêtements coupés cousus pour hommes et garçons": cte.INDUSTRY,
|
||||
"Industrie d'engrais chimique et d'engrais composé": cte.INDUSTRY,
|
||||
"Industrie d'enseignes au néon (excluant les enseignes en bois) éclairage interne": cte.INDUSTRY,
|
||||
"Industrie d'équipements de télécommunication": cte.INDUSTRY,
|
||||
"Industrie de bas et de chaussettes": cte.INDUSTRY,
|
||||
"Industrie de boissons gazeuses": cte.INDUSTRY,
|
||||
"Industrie de boîtes en carton ondulé et en carton compact": cte.INDUSTRY,
|
||||
"Industrie de boîtes pliantes et rigides": cte.INDUSTRY,
|
||||
"Industrie de carrosseries de véhicules automobiles": cte.INDUSTRY,
|
||||
"Industrie de chaudièresd'échangeurs de chaleur et de plaques métalliques": cte.INDUSTRY,
|
||||
"Industrie de contenants en plastique (sauf en mousse)": cte.INDUSTRY,
|
||||
"Industrie de contreplaqués en bois": cte.INDUSTRY,
|
||||
"Industrie de fabrication de gaz industriel": cte.INDUSTRY,
|
||||
"Industrie de fils et de câbles électriques": cte.INDUSTRY,
|
||||
"Industrie de filés et de tissus tissés (coton)": cte.INDUSTRY,
|
||||
"Industrie de garnitures et de raccords de plomberie en métal": cte.INDUSTRY,
|
||||
"Industrie de jouets et de jeux": cte.INDUSTRY,
|
||||
"Industrie de l'abattage et du conditionnement de la viande (sauf la volaille et le petit gibier)": cte.INDUSTRY,
|
||||
"Industrie de l'abattage et du conditionnement de la volaille et du petit gibier": cte.INDUSTRY,
|
||||
"Industrie de l'impression de formulaires commerciaux": cte.INDUSTRY,
|
||||
"Industrie de l'équipement de manutention": cte.INDUSTRY,
|
||||
"Industrie de l'étirage de l'extrusion et alliage de l'aluminiumfabriqué à partir d'aluminium acheté": cte.INDUSTRY,
|
||||
"Industrie de la bijouterie et de l'orfèvrerie (sauf l'affinage secondaire de métaux précieux)": cte.INDUSTRY,
|
||||
"Industrie de la bière": cte.INDUSTRY,
|
||||
"Industrie de la chaussure": cte.INDUSTRY,
|
||||
"Industrie de la confection à forfait de vêtements pour femmes et filles": cte.INDUSTRY,
|
||||
"Industrie de la construction et de la réparation de navires": cte.INDUSTRY,
|
||||
"Industrie de la fabrication de supports d'enregistrement de la reproduction du son et des instruments de musique": cte.INDUSTRY,
|
||||
"Industrie de la glace": cte.INDUSTRY,
|
||||
"Industrie de la machinerie pour la construction et du matériel d'entretien": cte.INDUSTRY,
|
||||
"Industrie de la préparation et du conditionnement de poissons et de fruits de mer": cte.INDUSTRY,
|
||||
"Industrie de la quincaillerie de base": cte.INDUSTRY,
|
||||
"Industrie de la transformation de la viande et de la fonte des graisses animales": cte.INDUSTRY,
|
||||
"Industrie de la tôlerie pour ventilation": cte.INDUSTRY,
|
||||
"Industrie de lampes électriques (ampoules et tubes)": cte.INDUSTRY,
|
||||
"Industrie de moteurs et de pièces de moteurs de véhicules automobiles": cte.INDUSTRY,
|
||||
"Industrie de mélange de farine et de pâte": cte.INDUSTRY,
|
||||
"Industrie de peinturede teinture et de vernis": cte.INDUSTRY,
|
||||
"Industrie de pellicules et de feuilles non renforcées en plastique": cte.INDUSTRY,
|
||||
"Industrie de pièces en plastique pour véhicules automobiles": cte.INDUSTRY,
|
||||
"Industrie de pièces et de composantes électroniques": cte.INDUSTRY,
|
||||
"Industrie de pneus et de chambres à air": cte.INDUSTRY,
|
||||
"Industrie de portes et de fenêtres en métal": cte.INDUSTRY,
|
||||
"Industrie de portes et fenêtres en plastique": cte.INDUSTRY,
|
||||
"Industrie de produits chimiques inorganiques d'usage industriel": cte.INDUSTRY,
|
||||
"Industrie de produits d'architecture en plastique": cte.INDUSTRY,
|
||||
"Industrie de produits de boulangerie commerciale de produits de boulangerie congelés et de pâtisseries": cte.INDUSTRY,
|
||||
"Industrie de produits de toilette": cte.INDUSTRY,
|
||||
"Industrie de produits en pierre": cte.INDUSTRY,
|
||||
"Industrie de produits en plastique stratifié sous pression ou renforcé": cte.INDUSTRY,
|
||||
"Industrie de produits en verre fabriqué à partir de verre acheté": cte.INDUSTRY,
|
||||
"Industrie de produits pharmaceutiques et de médicaments": cte.INDUSTRY,
|
||||
"Industrie de produits pétrochimiques": cte.INDUSTRY,
|
||||
"Industrie de produits pétroliers raffinés (sauf les huiles de graissage et les graisses lubrifiantes)": cte.INDUSTRY,
|
||||
"Industrie de pâtes alimentaires sèches": cte.INDUSTRY,
|
||||
"Industrie de récipients et de boîtes en métal": cte.INDUSTRY,
|
||||
"Industrie de résines synthétiques et de caoutchouc synthétique": cte.INDUSTRY,
|
||||
"Industrie de sacs et de poches en matière textile": cte.INDUSTRY,
|
||||
"Industrie de sacs et de sachets en plastique": cte.INDUSTRY,
|
||||
"Industrie de savons et de détachants pour le nettoyage": cte.INDUSTRY,
|
||||
"Industrie de sommiers et de matelas": cte.INDUSTRY,
|
||||
"Industrie de soupapes en métal": cte.INDUSTRY,
|
||||
"Industrie de tapis carpettes et moquettes": cte.INDUSTRY,
|
||||
"Industrie de tous les autres produits divers en bois": cte.INDUSTRY,
|
||||
"Industrie de tous les autres produits en papier transformé (sauf pour le bureau)": cte.INDUSTRY,
|
||||
"Industrie de ventilateursde soufflantes et de purificateurs d'air industriels et commerciaux": cte.INDUSTRY,
|
||||
"Industrie de vêtements de sport pour femmes et filles": cte.INDUSTRY,
|
||||
"Industrie de vêtements professionnels coupés cousus": cte.INDUSTRY,
|
||||
"Industrie des pièces et accessoires d'aéronefs (incluant avions et hélicoptères)": cte.INDUSTRY,
|
||||
"Industrie du béton préparé": cte.INDUSTRY,
|
||||
"Industrie du cannabis": cte.INDUSTRY,
|
||||
"Industrie du ciment": cte.INDUSTRY,
|
||||
"Industrie du clichagede la composition de la reliure et de la lithographie": cte.INDUSTRY,
|
||||
"Industrie du fromage": cte.INDUSTRY,
|
||||
"Industrie du lait de consommation": cte.INDUSTRY,
|
||||
"Industrie du laminagede l'étirage et de l'extrusion du cuivre et de ses alliages": cte.INDUSTRY,
|
||||
"Industrie du matériel de chauffage et du matériel de réfrigération commerciale": cte.INDUSTRY,
|
||||
"Industrie du matériel de transport": cte.INDUSTRY,
|
||||
"Industrie du matériel ferroviaire roulant": cte.INDUSTRY,
|
||||
"Industrie du matériel électrique de communication et de protection": cte.INDUSTRY,
|
||||
"Industrie du meuble de maison en bois": cte.INDUSTRY,
|
||||
"Industrie du meuble et d'articles d'ameublement pour hôtelsrestaurants et institutions": cte.INDUSTRY,
|
||||
"Industrie du pain": cte.INDUSTRY,
|
||||
"Industrie du revêtement métallique sur commande": cte.INDUSTRY,
|
||||
"Industrie du sucre de canne et de betterave à sucre": cte.INDUSTRY,
|
||||
"Industrie du thé et du café": cte.INDUSTRY,
|
||||
"Industries des appareils d'aéronefs (incluant avions et hélicoptères)": cte.INDUSTRY,
|
||||
"Installation d'équipements de réfrigération commerciale": cte.WAREHOUSE,
|
||||
"Installation portuaire en général": cte.WAREHOUSE,
|
||||
"Jardin botanique": cte.WAREHOUSE,
|
||||
"Ligne de l'oléoduc": cte.WAREHOUSE,
|
||||
"Local pour les associations fraternelles": "Office",
|
||||
"Logement": cte.RESIDENTIAL,
|
||||
"Logement vacant dans un bâtiment comportant plusieurs logements ou autres locaux": cte.RESIDENTIAL,
|
||||
"Loisir et autres activités culturelles": "Office",
|
||||
"Maison d'agentsde courtiers et de services d'administration des biens-fonds": "Office",
|
||||
"Maison d'étudiants (collège et université)": "Office",
|
||||
"Maison de chambres et pension": "Office",
|
||||
"Maison de chambres pour personnes ayant une déficience intellectuelle": "Office",
|
||||
"Maison de courtiers et de négociants de marchandises": "Office",
|
||||
"Maison de réhabilitation": "Office",
|
||||
"Maison des jeunes": "Office",
|
||||
"Maison pour personnes en difficulté (séjours périodes limitées)": "Office",
|
||||
"Maison pour personnes retraitées autonomes": cte.DORMITORY,
|
||||
"Maison pour personnes retraitées non autonomes (inclus les CHLSD)": cte.DORMITORY,
|
||||
"Marché public": cte.STRIP_MALL,
|
||||
"Meunerie et minoterie": "Office",
|
||||
"Monastère": cte.DORMITORY,
|
||||
"Monument et site historique": cte.EVENT_LOCATION,
|
||||
"Motel": "hotel/Motel",
|
||||
"Musée": cte.EVENT_LOCATION,
|
||||
"Organisme international et autres organismes extraterritoriaux": "Office",
|
||||
"Parc d'amusement (extérieur)": cte.NON_HEATED,
|
||||
"Parc de maisons mobiles (fonds de terre seulement)": cte.NON_HEATED,
|
||||
"Parc pour la récréation en général": cte.NON_HEATED,
|
||||
"Parc à caractère récréatif et ornemental": cte.NON_HEATED,
|
||||
"Passage": cte.NON_HEATED,
|
||||
"Piscine extérieure et activités connexes": cte.NON_HEATED,
|
||||
"Piscine intérieure et activités connexes": cte.SPORTS_LOCATION,
|
||||
"Pose et réparation de parement métalliques et autres (entrepreneur spécialisé)": cte.WAREHOUSE,
|
||||
"Poste et bureau de douanes": cte.OFFICE_AND_ADMINISTRATION,
|
||||
"Pouponnière ou garderie de nuit": cte.HOSPITAL,
|
||||
"Presbytère": cte.OFFICE_AND_ADMINISTRATION,
|
||||
"Prison provinciale": cte.DORMITORY,
|
||||
"Protection contre l'incendie et activités connexes": cte.WAREHOUSE,
|
||||
"Raffinerie de pétrole": cte.INDUSTRY,
|
||||
"Restaurant et établissement avec service complet (avec terrasse) - Établissements avec permis alcool inclus pub café et brasserie": cte.FULL_SERVICE_RESTAURANT,
|
||||
"Restaurant et établissement avec service complet (sans terrasse) -Établissements avec permis alcoolinclus pub café et brasserie": cte.FULL_SERVICE_RESTAURANT,
|
||||
"Restaurant et établissement avec service restreint ( commande au comptoir ou par téléphone)": cte.QUICK_SERVICE_RESTAURANT,
|
||||
"Restaurant et établissement offrant des repas à libre-service (cafétéria cantine)": cte.QUICK_SERVICE_RESTAURANT,
|
||||
"Rue et avenue pour l'accès local": cte.NON_HEATED,
|
||||
"Ruelle": cte.NON_HEATED,
|
||||
"Récupération et triage de matières polluantes et toxiques": cte.WAREHOUSE,
|
||||
"Récupération et triage de métaux": cte.WAREHOUSE,
|
||||
"Réparation et entretien des avions": cte.WAREHOUSE,
|
||||
"Réserve pour la protection de la faune": cte.NON_HEATED,
|
||||
"Réservoir d'eau (installation d'emmagasinage de l'eau par retenue et réservoirs)": cte.NON_HEATED,
|
||||
"Résidence de tourismeappartement maison ou chalet (meublé et équipé pour repas)": "hotel/Motel",
|
||||
"Salle d'exposition": cte.EVENT_LOCATION,
|
||||
"Salle et terrain de squash de racquetball et de tennis": cte.SPORTS_LOCATION,
|
||||
"Salle ou salon de quilles": cte.NON_HEATED,
|
||||
"Salon de beauté (maquillagemanucureetc..)": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Salon de coiffure": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Salon funéraire": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Service bancaire (dépôts et prêtsincluant banque à charte)": cte.OFFICE_AND_ADMINISTRATION,
|
||||
"Service d'ambulance": cte.WAREHOUSE,
|
||||
"Service d'architecture": cte.OFFICE_AND_ADMINISTRATION,
|
||||
"Service d'assainissement de l'environnement": cte.WAREHOUSE,
|
||||
"Service d'emballage et de protection de marchandises": cte.WAREHOUSE,
|
||||
"Service d'envoi de marchandises": cte.WAREHOUSE,
|
||||
"Service d'hébergement des données (sites Web diffusion audio et vidéo en continu services d'application)": cte.WAREHOUSE,
|
||||
"Service d'hôpital (inclus hôpitaux psychiatriques)": cte.HOSPITAL,
|
||||
"Service d'optométrie": cte.OUT_PATIENT_HEALTH_CARE,
|
||||
"Service de buanderie de nettoyage à sec et de teinture (sauf les tapis)": cte.WAREHOUSE,
|
||||
"Service de comptabilitéde vérification et de tenue de livre": cte.OFFICE_AND_ADMINISTRATION,
|
||||
"Service de construction de routesde rues et de pontsde trottoirs et de pistes (entrepreneur général)": cte.WAREHOUSE,
|
||||
"Service de construction non résidentiellecommerciale et institutionnelle (entrepreneur général)": cte.WAREHOUSE,
|
||||
"Service de construction non résidentielleindustrielle (entrepreneur général)": cte.WAREHOUSE,
|
||||
"Service de construction résidentielle (entrepreneur)": cte.WAREHOUSE,
|
||||
"Service de débosselage et de peinture d'automobiles": cte.WAREHOUSE,
|
||||
"Service de garderie (prématernelle moins de 50 % de poupons)": cte.PRIMARY_SCHOOL,
|
||||
"Service de génie": cte.OFFICE_AND_ADMINISTRATION,
|
||||
"Service de holding et d'investissement et de fiducie": cte.OFFICE_AND_ADMINISTRATION,
|
||||
"Service de laboratoire dentaire": cte.OUT_PATIENT_HEALTH_CARE,
|
||||
"Service de laboratoire médical": cte.OUT_PATIENT_HEALTH_CARE,
|
||||
"Service de lavage d'automobiles": cte.WAREHOUSE,
|
||||
"Service de limousine": cte.WAREHOUSE,
|
||||
"Service de lingerie et de buanderie industrielle": cte.WAREHOUSE,
|
||||
"Service de location d'automobiles": cte.WAREHOUSE,
|
||||
"Service de location d'outils ou d'équipements": cte.WAREHOUSE,
|
||||
"Service de location d'équipements": cte.WAREHOUSE,
|
||||
"Service de location de boites postales (sauf le publipostage) et centre de courrier privé": cte.OFFICE_AND_ADMINISTRATION,
|
||||
"Service de location de camions de remorques utilitaires et de véhicules de plaisance": cte.WAREHOUSE,
|
||||
"Service de maçonnerie (entrepreneur spécialisé)": cte.INDUSTRY,
|
||||
"Service de messagers": "Office",
|
||||
"Service de notaires": "Office",
|
||||
"Service de paysagement ou de déneigement": cte.WAREHOUSE,
|
||||
"Service de petite menuiserie et de finition (entrepreneur spécialisé)": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Service de plomberie de chauffagede climatisation et de ventilation (entrepreneur spécialisé)": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Service de police fédérale et activités connexes": cte.OFFICE_AND_ADMINISTRATION,
|
||||
"Service de police municipale et activités connexes": cte.OFFICE_AND_ADMINISTRATION,
|
||||
"Service de pose de portesde fenêtres et de panneaux de verre": cte.WAREHOUSE,
|
||||
"Service de publicité en général": "Office",
|
||||
"Service de recherche de développement et d'essais": cte.SECONDARY_SCHOOL,
|
||||
"Service de remplacement de pièces et d'accessoires d'automobiles (amortisseurs silencieux toits ouvrants glacespare-brises...)": cte.WAREHOUSE,
|
||||
"Service de revêtement en asphalte et en bitume": cte.WAREHOUSE,
|
||||
"Service de réparation d'automobiles (garage) sans pompes à essence(5531)": cte.WAREHOUSE,
|
||||
"Service de réparation d'autres véhicules légers": cte.WAREHOUSE,
|
||||
"Service de réparation de véhicules légers motorisés (motocyclettemotoneige véhicule tout terrain)": cte.WAREHOUSE,
|
||||
"Service de réparation et d'entretien de machines et de matériel d'usage commercial et industriel": "Office",
|
||||
"Service de réparation et d'entretien de matériel informatique": "Office",
|
||||
"Service de réparation et d'entretien de systèmes de plomberieschauffageventilation et climatisation.(entrepreneur spécialisé)": cte.WAREHOUSE,
|
||||
"Service de réparation et d'entretien de véhicules lourds": cte.WAREHOUSE,
|
||||
"Service de réparation et de rembourrage de meubles": cte.WAREHOUSE,
|
||||
"Service de soudure": cte.WAREHOUSE,
|
||||
"Service de toilettage pour animaux domestiques": cte.OUT_PATIENT_HEALTH_CARE,
|
||||
"Service de traitement pour automobiles (antirouilleetc.)": cte.WAREHOUSE,
|
||||
"Service de travaux d'électricité et installation de câblage (entrepreneur spécialisé)": cte.WAREHOUSE,
|
||||
"Service de travaux de toiture (entrepreneur spécialisé)": cte.WAREHOUSE,
|
||||
"Service de télécommunication sans fil (appareil mobile sauf par Internet)": cte.WAREHOUSE,
|
||||
"Service de vétérinaires (animaux domestiques)": cte.OUT_PATIENT_HEALTH_CARE,
|
||||
"Service de vétérinaires et d'hôpital pour animaux de ferme": cte.OUT_PATIENT_HEALTH_CARE,
|
||||
"Service dentaire (inclus chirurgie et hygiène)": cte.OUT_PATIENT_HEALTH_CARE,
|
||||
"Service en santé mentale (cabinet) (comprend tous services professionnelspsychiatre psychologuepsychanalyste)": cte.OUT_PATIENT_HEALTH_CARE,
|
||||
"Service en travaux de fondation et de structures en béton (entrepreneur spécialisé)": "Office",
|
||||
"Service informatique (location ou utilisation partagée services auxiliaires programmation planification et analyse de système)": "Office",
|
||||
"Service médical (cabinet de médecins et chirurgiens spécialisés)": cte.OUT_PATIENT_HEALTH_CARE,
|
||||
"Service photographique (incluant les services commerciaux)": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Service pour l'entretien ménager": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Service éducationnel et de recherche scientifique": cte.SECONDARY_SCHOOL,
|
||||
"Services spécialisés reliés à l'activité bancaire": cte.OFFICE_AND_ADMINISTRATION,
|
||||
"Stade": cte.SPORTS_LOCATION,
|
||||
"Station de contrôle de la pression de l'eau": cte.WAREHOUSE,
|
||||
"Station de contrôle de la pression des eaux usées": cte.WAREHOUSE,
|
||||
"Station de métro": cte.WAREHOUSE,
|
||||
"Station libre-serviceou avec service et dépanneur sans réparation de véhicules automobiles": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Station libre-serviceou avec service sans réparation de véhicules automobiles": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Station-service avec réparation de véhicules automobiles": cte.WAREHOUSE,
|
||||
"Stationnement extérieur (condo non résidentiel)": cte.NON_HEATED,
|
||||
"Stationnement extérieur (condo)": cte.NON_HEATED,
|
||||
"Stationnement intérieur ( condo non résidentiel)": cte.WAREHOUSE,
|
||||
"Stationnement intérieur (condo)": cte.WAREHOUSE,
|
||||
"Studio d'enregistrement du son (disque cassette et disque compact)": "Office",
|
||||
"Studio de production de filmsde vidéos ou de publicités (ne comprends pas le laboratoire de production)": "Office",
|
||||
"Studio de télévision (sans public)": "Office",
|
||||
"Syndicat et organisation similaire": "Office",
|
||||
"Terminus maritime (passagers) incluant les gares de traversiers": cte.WAREHOUSE,
|
||||
"Terrain de golf (avec chalet et autres aménagements sportifs)": cte.NON_HEATED,
|
||||
"Terrain de sport (jeux et pistes pour compétitions et sportgradins)": cte.NON_HEATED,
|
||||
"Terrain de stationnement pour automobiles": cte.WAREHOUSE,
|
||||
"Terrains de stationnement pour véhicules lourds": cte.WAREHOUSE,
|
||||
"Théâtre": cte.EVENT_LOCATION,
|
||||
"Tour de relais (micro-ondes)": cte.NON_HEATED,
|
||||
"Tous les autres services d'information": cte.NON_HEATED,
|
||||
"Transport et gestion d'électricité en bloc": cte.NON_HEATED,
|
||||
"Transport et gestion du gaz par canalisation": cte.NON_HEATED,
|
||||
"Université": cte.SECONDARY_SCHOOL,
|
||||
"Usine de traitement des eaux (filtration)": cte.INDUSTRY,
|
||||
"Usine de traitement des eaux usées (épuration)": cte.INDUSTRY,
|
||||
"Vente au détail (fleuriste)": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Vente au détail d'accessoires pour femmes": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Vente au détail d'animaux de maison (animalerie)": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Vente au détail d'antiquités (sauf le marché aux puces)": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Vente au détail d'appareils orthopédiques et articles spécialisés de santé": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Vente au détail d'articles de sport": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Vente au détail d'articles d'accessoires d'aménagement paysager et de jardin": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Vente au détail d'instruments et de matériel médical": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Vente au détail d'équipements de ferme": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Vente au détail d'équipements de plomberie de chauffagede ventilationde climatisation et de foyer": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Vente au détail d'équipements et d'accessoires de chasse et pêche": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Vente au détail de bicyclettes": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Vente au détail de boissons alcoolisées": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Vente au détail de chaussures": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Vente au détail de fruits et de légumes": cte.RETAIL_SHOP_WITH_REFRIGERATED_FOOD,
|
||||
"Vente au détail de la viande": cte.RETAIL_SHOP_WITH_REFRIGERATED_FOOD,
|
||||
"Vente au détail de livres et de papeterie": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Vente au détail de marchandises en général (sauf les marchés aux puces)": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Vente au détail de matériaux de construction": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Vente au détail de matériaux de construction (cour à bois)": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Vente au détail de matériel électrique": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Vente au détail de meubles": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Vente au détail de motocyclettes de motoneiges et de leurs accessoires": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Vente au détail de médicaments et d'articles divers (pharmacie)": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Vente au détail de peinturede verre et de papier tenture": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Vente au détail de piscinesde spas et leurs accessoires": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Vente au détail de pièces de véhicules automobiles et d'accessoires usagés": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Vente au détail de pneus de batteries et d'accessoires": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Vente au détail de produits d'épicerie (avec boucherie)": cte.RETAIL_SHOP_WITH_REFRIGERATED_FOOD,
|
||||
"Vente au détail de produits d'épicerie (sans boucherie)": cte.RETAIL_SHOP_WITH_REFRIGERATED_FOOD,
|
||||
"Vente au détail de produits de la boulangerie et de la pâtisserie (manufacturés sur place en totalité ou non)": cte.RETAIL_SHOP_WITH_REFRIGERATED_FOOD,
|
||||
"Vente au détail de quincaillerie": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Vente au détail de radiosde téléviseurssystèmes de son et appareils électroniques": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Vente au détail de revêtements de planchers et de murs (bois franc plancher flottant carreaux céramiques tapisserie)": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Vente au détail de serruresde clés et d'accessoires": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Vente au détail de véhicules automobiles neufs et usagés": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Vente au détail de véhicules automobiles usagés seulement": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Vente au détail de vêtement prêt-à-porter pour femmes": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Vente au détail de vêtements et d'accessoires pour hommes": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Vente au détail de vêtements et d'articles usagésfriperies (sauf le marché aux puces)": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Vente au détail de vêtements unisexes": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Vente au détail du cafédu théd'épices et d'aromates": cte.RETAIL_SHOP_WITH_REFRIGERATED_FOOD,
|
||||
"Vente au détailclubs de gros et hypermarchés (entrepôt-club)": cte.RETAIL_SHOP_WITH_REFRIGERATED_FOOD,
|
||||
"Vente au détailfournitures pour la maison et l'auto": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Vente au détailmagasin à rayons": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
"Vente en gros d'ameublements de matériels de bureau et de magasin": cte.STRIP_MALL,
|
||||
"Vente en gros d'appareils et d'équipements de plomberie et de chauffage": cte.STRIP_MALL,
|
||||
"Vente en gros d'appareils et d'équipements électriques de fils et de matériel électronique de construction": cte.STRIP_MALL,
|
||||
"Vente en gros d'appareils électriquesde téléviseurs et de radios": cte.STRIP_MALL,
|
||||
"Vente en gros d'automobiles et autres véhicules automobiles neufs ou d'occasions incluent VR)": cte.STRIP_MALL,
|
||||
"Vente en gros d'autres appareils ou matériels électriques et électroniques": cte.STRIP_MALL,
|
||||
"Vente en gros d'autres médicaments de produits chimiques et de produits connexes": cte.STRIP_MALL,
|
||||
"Vente en gros d'autres pièces d'équipement ou de machinerie (incluant machinerie lourde)": cte.STRIP_MALL,
|
||||
"Vente en gros d'autres produits reliés à l'épicerie": cte.STRIP_MALL,
|
||||
"Vente en gros d'équipements et de pièces de machinerie commercialeindustrielle ou agricole (incluant machinerie lourde)": cte.STRIP_MALL,
|
||||
"Vente en gros d'équipements et de pièces pour la réfrigération ventilation la climatisation et le chauffage (système combiné)": cte.STRIP_MALL,
|
||||
"Vente en gros d'équipements et de pièces pour les entreprises de services": cte.STRIP_MALL,
|
||||
"Vente en gros de bois et de matériaux de construction": cte.STRIP_MALL,
|
||||
"Vente en gros de chaussures": cte.STRIP_MALL,
|
||||
"Vente en gros de fruits et de légumes frais": cte.STRIP_MALL,
|
||||
"Vente en gros de médicaments et de produits médicamenteux": cte.STRIP_MALL,
|
||||
"Vente en gros de pièces et d'accessoires neufs pour véhicules automobiles": cte.STRIP_MALL,
|
||||
"Vente en gros de pièces et d'équipements électroniques": cte.STRIP_MALL,
|
||||
"Vente en gros de pneus et de chambres à air": cte.STRIP_MALL,
|
||||
"Vente en gros de poissons et de fruits de mer": cte.STRIP_MALL,
|
||||
"Vente en gros de produits de beauté": cte.STRIP_MALL,
|
||||
"Vente en gros de produits de boulangerie et de pâtisserie": cte.STRIP_MALL,
|
||||
"Vente en gros de produits laitiers": cte.STRIP_MALL,
|
||||
"Vente en gros de quincaillerie": cte.STRIP_MALL,
|
||||
"Vente en gros de tissus et de textiles": cte.STRIP_MALL,
|
||||
"Vente en gros de viandes et de produits de la viande": cte.STRIP_MALL,
|
||||
"Vente en gros de vêtements de lingerie de bas et d'accessoires": cte.STRIP_MALL,
|
||||
"Vente en gros pour l'épicerie en général": cte.STRIP_MALL,
|
||||
"École commerciale et de secrétariat (non intégrée aux polyvalentes)": cte.SECONDARY_SCHOOL,
|
||||
"École de beaux-arts et de musique (exclus arts publicitaires arts graphiques et photographie publicitaire)": cte.SECONDARY_SCHOOL,
|
||||
"École de danse": cte.SECONDARY_SCHOOL,
|
||||
"École de métiers (non intégrée aux polyvalentes)": cte.SECONDARY_SCHOOL,
|
||||
"École maternelle": cte.SECONDARY_SCHOOL,
|
||||
"École polyvalente": cte.SECONDARY_SCHOOL,
|
||||
"École secondaire": cte.SECONDARY_SCHOOL,
|
||||
"École à caractère familial (exploité par une personne physique dans sa résidence moins de 15 élèves)": cte.SECONDARY_SCHOOL,
|
||||
"École élémentaire": cte.SECONDARY_SCHOOL,
|
||||
"École élémentaire et secondaire": cte.SECONDARY_SCHOOL,
|
||||
"Église synagogue mosquée et temple": cte.EVENT_LOCATION,
|
||||
"Établissement avec salle de réception ou de banquet": cte.FULL_SERVICE_RESTAURANT,
|
||||
"Établissement avec service de boissons alcoolisées (Bar)": cte.QUICK_SERVICE_RESTAURANT,
|
||||
"Établissement dont l'activité principale est la danse (discothèque avec service alcool boite de nuit) sans alcool code 7397": cte.QUICK_SERVICE_RESTAURANT,
|
||||
"Mausolée": cte.NON_HEATED,
|
||||
"Auberge ou gîte touristique (Hôtel à caractère familial, d'au plus 3 étages en hauteur de bâtiment)": cte.HOTEL,
|
||||
"Service de garderie (prématernelle, moins de 50 % de poupons)": cte.PRIMARY_SCHOOL,
|
||||
"Église, synagogue, mosquée et temple": cte.CONVENTION_CENTER
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@property
|
||||
def dictionary(self) -> dict:
|
||||
return self._dictionary
|
217
hub/helpers/data/pluto_function_to_hub_function.py
Normal file
217
hub/helpers/data/pluto_function_to_hub_function.py
Normal file
|
@ -0,0 +1,217 @@
|
|||
"""
|
||||
Dictionaries module for Pluto function to hub function
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Guille Gutierrez Guillermo.GutierrezMorote@concordia.ca
|
||||
"""
|
||||
|
||||
import hub.helpers.constants as cte
|
||||
|
||||
|
||||
class PlutoFunctionToHubFunction:
|
||||
|
||||
def __init__(self):
|
||||
self._dictionary = {
|
||||
'A0': cte.SINGLE_FAMILY_HOUSE,
|
||||
'A1': cte.SINGLE_FAMILY_HOUSE,
|
||||
'A2': cte.SINGLE_FAMILY_HOUSE,
|
||||
'A3': cte.SINGLE_FAMILY_HOUSE,
|
||||
'A4': cte.SINGLE_FAMILY_HOUSE,
|
||||
'A5': cte.SINGLE_FAMILY_HOUSE,
|
||||
'A6': cte.SINGLE_FAMILY_HOUSE,
|
||||
'A7': cte.SINGLE_FAMILY_HOUSE,
|
||||
'A8': cte.SINGLE_FAMILY_HOUSE,
|
||||
'A9': cte.SINGLE_FAMILY_HOUSE,
|
||||
'B1': cte.MULTI_FAMILY_HOUSE,
|
||||
'B2': cte.MULTI_FAMILY_HOUSE,
|
||||
'B3': cte.MULTI_FAMILY_HOUSE,
|
||||
'B9': cte.MULTI_FAMILY_HOUSE,
|
||||
'C0': cte.RESIDENTIAL,
|
||||
'C1': cte.RESIDENTIAL,
|
||||
'C2': cte.RESIDENTIAL,
|
||||
'C3': cte.RESIDENTIAL,
|
||||
'C4': cte.RESIDENTIAL,
|
||||
'C5': cte.RESIDENTIAL,
|
||||
'C6': cte.RESIDENTIAL,
|
||||
'C7': cte.RESIDENTIAL,
|
||||
'C8': cte.RESIDENTIAL,
|
||||
'C9': cte.RESIDENTIAL,
|
||||
'D0': cte.RESIDENTIAL,
|
||||
'D1': cte.RESIDENTIAL,
|
||||
'D2': cte.RESIDENTIAL,
|
||||
'D3': cte.RESIDENTIAL,
|
||||
'D4': cte.RESIDENTIAL,
|
||||
'D5': cte.RESIDENTIAL,
|
||||
'D6': cte.RESIDENTIAL,
|
||||
'D7': cte.RESIDENTIAL,
|
||||
'D8': cte.RESIDENTIAL,
|
||||
'D9': cte.RESIDENTIAL,
|
||||
'E1': cte.WAREHOUSE,
|
||||
'E3': cte.WAREHOUSE,
|
||||
'E4': cte.WAREHOUSE,
|
||||
'E5': cte.WAREHOUSE,
|
||||
'E7': cte.WAREHOUSE,
|
||||
'E9': cte.WAREHOUSE,
|
||||
'F1': cte.WAREHOUSE,
|
||||
'F2': cte.WAREHOUSE,
|
||||
'F4': cte.WAREHOUSE,
|
||||
'F5': cte.WAREHOUSE,
|
||||
'F8': cte.WAREHOUSE,
|
||||
'F9': cte.WAREHOUSE,
|
||||
'G0': cte.SMALL_OFFICE,
|
||||
'G1': cte.SMALL_OFFICE,
|
||||
'G2': cte.SMALL_OFFICE,
|
||||
'G3': cte.SMALL_OFFICE,
|
||||
'G4': cte.SMALL_OFFICE,
|
||||
'G5': cte.SMALL_OFFICE,
|
||||
'G6': cte.SMALL_OFFICE,
|
||||
'G7': cte.SMALL_OFFICE,
|
||||
'G8': cte.SMALL_OFFICE,
|
||||
'G9': cte.SMALL_OFFICE,
|
||||
'H1': cte.HOTEL,
|
||||
'H2': cte.HOTEL,
|
||||
'H3': cte.HOTEL,
|
||||
'H4': cte.HOTEL,
|
||||
'H5': cte.HOTEL,
|
||||
'H6': cte.HOTEL,
|
||||
'H7': cte.HOTEL,
|
||||
'H8': cte.HOTEL,
|
||||
'H9': cte.HOTEL,
|
||||
'HB': cte.HOTEL,
|
||||
'HH': cte.HOTEL,
|
||||
'HR': cte.HOTEL,
|
||||
'HS': cte.HOTEL,
|
||||
'I1': cte.HOSPITAL,
|
||||
'I2': cte.OUT_PATIENT_HEALTH_CARE,
|
||||
'I3': cte.OUT_PATIENT_HEALTH_CARE,
|
||||
'I4': cte.RESIDENTIAL,
|
||||
'I5': cte.OUT_PATIENT_HEALTH_CARE,
|
||||
'I6': cte.OUT_PATIENT_HEALTH_CARE,
|
||||
'I7': cte.OUT_PATIENT_HEALTH_CARE,
|
||||
'I9': cte.OUT_PATIENT_HEALTH_CARE,
|
||||
'J1': cte.LARGE_OFFICE,
|
||||
'J2': cte.LARGE_OFFICE,
|
||||
'J3': cte.LARGE_OFFICE,
|
||||
'J4': cte.LARGE_OFFICE,
|
||||
'J5': cte.LARGE_OFFICE,
|
||||
'J6': cte.LARGE_OFFICE,
|
||||
'J7': cte.LARGE_OFFICE,
|
||||
'J8': cte.LARGE_OFFICE,
|
||||
'J9': cte.LARGE_OFFICE,
|
||||
'K1': cte.STRIP_MALL,
|
||||
'K2': cte.STRIP_MALL,
|
||||
'K3': cte.STRIP_MALL,
|
||||
'K4': cte.RESIDENTIAL,
|
||||
'K5': cte.RESTAURANT,
|
||||
'K6': cte.SUPERMARKET,
|
||||
'K7': cte.SUPERMARKET,
|
||||
'K8': cte.SUPERMARKET,
|
||||
'K9': cte.SUPERMARKET,
|
||||
'L1': cte.RESIDENTIAL,
|
||||
'L2': cte.RESIDENTIAL,
|
||||
'L3': cte.RESIDENTIAL,
|
||||
'L8': cte.RESIDENTIAL,
|
||||
'L9': cte.RESIDENTIAL,
|
||||
'M1': cte.LARGE_OFFICE,
|
||||
'M2': cte.LARGE_OFFICE,
|
||||
'M3': cte.LARGE_OFFICE,
|
||||
'M4': cte.LARGE_OFFICE,
|
||||
'M9': cte.LARGE_OFFICE,
|
||||
'N1': cte.RESIDENTIAL,
|
||||
'N2': cte.RESIDENTIAL,
|
||||
'N3': cte.RESIDENTIAL,
|
||||
'N4': cte.RESIDENTIAL,
|
||||
'N9': cte.RESIDENTIAL,
|
||||
'O1': cte.SMALL_OFFICE,
|
||||
'O2': cte.SMALL_OFFICE,
|
||||
'O3': cte.SMALL_OFFICE,
|
||||
'O4': cte.SMALL_OFFICE,
|
||||
'O5': cte.SMALL_OFFICE,
|
||||
'O6': cte.SMALL_OFFICE,
|
||||
'O7': cte.SMALL_OFFICE,
|
||||
'O8': cte.SMALL_OFFICE,
|
||||
'O9': cte.SMALL_OFFICE,
|
||||
'P1': cte.LARGE_OFFICE,
|
||||
'P2': cte.HOTEL,
|
||||
'P3': cte.SMALL_OFFICE,
|
||||
'P4': cte.SMALL_OFFICE,
|
||||
'P5': cte.SMALL_OFFICE,
|
||||
'P6': cte.SMALL_OFFICE,
|
||||
'P7': cte.LARGE_OFFICE,
|
||||
'P8': cte.LARGE_OFFICE,
|
||||
'P9': cte.SMALL_OFFICE,
|
||||
'Q0': cte.SMALL_OFFICE,
|
||||
'Q1': cte.SMALL_OFFICE,
|
||||
'Q2': cte.SMALL_OFFICE,
|
||||
'Q3': cte.SMALL_OFFICE,
|
||||
'Q4': cte.SMALL_OFFICE,
|
||||
'Q5': cte.SMALL_OFFICE,
|
||||
'Q6': cte.SMALL_OFFICE,
|
||||
'Q7': cte.SMALL_OFFICE,
|
||||
'Q8': cte.SMALL_OFFICE,
|
||||
'Q9': cte.SMALL_OFFICE,
|
||||
'R0': cte.RESIDENTIAL,
|
||||
'R1': cte.RESIDENTIAL,
|
||||
'R2': cte.RESIDENTIAL,
|
||||
'R3': cte.RESIDENTIAL,
|
||||
'R4': cte.RESIDENTIAL,
|
||||
'R5': cte.RESIDENTIAL,
|
||||
'R6': cte.RESIDENTIAL,
|
||||
'R7': cte.RESIDENTIAL,
|
||||
'R8': cte.RESIDENTIAL,
|
||||
'R9': cte.RESIDENTIAL,
|
||||
'RA': cte.RESIDENTIAL,
|
||||
'RB': cte.RESIDENTIAL,
|
||||
'RC': cte.RESIDENTIAL,
|
||||
'RD': cte.RESIDENTIAL,
|
||||
'RG': cte.RESIDENTIAL,
|
||||
'RH': cte.RESIDENTIAL,
|
||||
'RI': cte.RESIDENTIAL,
|
||||
'RK': cte.RESIDENTIAL,
|
||||
'RM': cte.RESIDENTIAL,
|
||||
'RR': cte.RESIDENTIAL,
|
||||
'RS': cte.RESIDENTIAL,
|
||||
'RW': cte.RESIDENTIAL,
|
||||
'RX': cte.RESIDENTIAL,
|
||||
'RZ': cte.RESIDENTIAL,
|
||||
'S0': cte.RESIDENTIAL,
|
||||
'S1': cte.RESIDENTIAL,
|
||||
'S2': cte.RESIDENTIAL,
|
||||
'S3': cte.RESIDENTIAL,
|
||||
'S4': cte.RESIDENTIAL,
|
||||
'S5': cte.RESIDENTIAL,
|
||||
'S9': cte.RESIDENTIAL,
|
||||
'U0': cte.WAREHOUSE,
|
||||
'U1': cte.WAREHOUSE,
|
||||
'U2': cte.WAREHOUSE,
|
||||
'U3': cte.WAREHOUSE,
|
||||
'U4': cte.WAREHOUSE,
|
||||
'U5': cte.WAREHOUSE,
|
||||
'U6': cte.WAREHOUSE,
|
||||
'U7': cte.WAREHOUSE,
|
||||
'U8': cte.WAREHOUSE,
|
||||
'U9': cte.WAREHOUSE,
|
||||
'W1': cte.PRIMARY_SCHOOL,
|
||||
'W2': cte.PRIMARY_SCHOOL,
|
||||
'W3': cte.SECONDARY_SCHOOL,
|
||||
'W4': cte.EDUCATION,
|
||||
'W5': cte.SECONDARY_SCHOOL,
|
||||
'W6': cte.SECONDARY_SCHOOL,
|
||||
'W7': cte.SECONDARY_SCHOOL,
|
||||
'W8': cte.PRIMARY_SCHOOL,
|
||||
'W9': cte.SECONDARY_SCHOOL,
|
||||
'Y1': cte.LARGE_OFFICE,
|
||||
'Y2': cte.LARGE_OFFICE,
|
||||
'Y3': cte.LARGE_OFFICE,
|
||||
'Y4': cte.LARGE_OFFICE,
|
||||
'Y5': cte.LARGE_OFFICE,
|
||||
'Y6': cte.LARGE_OFFICE,
|
||||
'Y7': cte.LARGE_OFFICE,
|
||||
'Y8': cte.LARGE_OFFICE,
|
||||
'Y9': cte.LARGE_OFFICE,
|
||||
'Z1': cte.LARGE_OFFICE
|
||||
}
|
||||
|
||||
@property
|
||||
def dictionary(self) -> dict:
|
||||
return self._dictionary
|
92
hub/helpers/dictionaries.py
Normal file
92
hub/helpers/dictionaries.py
Normal file
|
@ -0,0 +1,92 @@
|
|||
"""
|
||||
Dictionaries module saves all transformations of functions and usages to access the catalogs
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
|
||||
from hub.helpers.data.hft_function_to_hub_function import HftFunctionToHubFunction
|
||||
from hub.helpers.data.montreal_function_to_hub_function import MontrealFunctionToHubFunction
|
||||
from hub.helpers.data.alkis_function_to_hub_function import AlkisFunctionToHubFunction
|
||||
from hub.helpers.data.pluto_function_to_hub_function import PlutoFunctionToHubFunction
|
||||
from hub.helpers.data.hub_function_to_nrel_construction_function import HubFunctionToNrelConstructionFunction
|
||||
from hub.helpers.data.hub_function_to_nrcan_construction_function import HubFunctionToNrcanConstructionFunction
|
||||
from hub.helpers.data.hub_usage_to_comnet_usage import HubUsageToComnetUsage
|
||||
from hub.helpers.data.hub_usage_to_hft_usage import HubUsageToHftUsage
|
||||
from hub.helpers.data.hub_usage_to_nrcan_usage import HubUsageToNrcanUsage
|
||||
|
||||
class Dictionaries:
|
||||
"""
|
||||
Dictionaries class
|
||||
"""
|
||||
|
||||
@property
|
||||
def hub_usage_to_hft_usage(self) -> dict:
|
||||
"""
|
||||
Hub usage to HfT usage, transformation dictionary
|
||||
:return: dict
|
||||
"""
|
||||
return HubUsageToHftUsage().dictionary
|
||||
|
||||
@property
|
||||
def hub_usage_to_comnet_usage(self) -> dict:
|
||||
"""
|
||||
Hub usage to Comnet usage, transformation dictionary
|
||||
:return: dict
|
||||
"""
|
||||
return HubUsageToComnetUsage().dictionary
|
||||
|
||||
@property
|
||||
def hub_usage_to_nrcan_usage(self) -> dict:
|
||||
"""
|
||||
Get hub usage to NRCAN usage, transformation dictionary
|
||||
:return: dict
|
||||
"""
|
||||
return HubUsageToNrcanUsage().dictionary
|
||||
|
||||
@property
|
||||
def hub_function_to_nrcan_construction_function(self) -> dict:
|
||||
"""
|
||||
Get hub function to NRCAN construction function, transformation dictionary
|
||||
:return: dict
|
||||
"""
|
||||
return HubFunctionToNrcanConstructionFunction().dictionary
|
||||
|
||||
@property
|
||||
def hub_function_to_nrel_construction_function(self) -> dict:
|
||||
"""
|
||||
Get hub function to NREL construction function, transformation dictionary
|
||||
:return: dict
|
||||
"""
|
||||
return HubFunctionToNrelConstructionFunction().dictionary
|
||||
|
||||
@property
|
||||
def pluto_function_to_hub_function(self) -> dict:
|
||||
"""
|
||||
Get Pluto function to hub function, transformation dictionary
|
||||
:return: dict
|
||||
"""
|
||||
return PlutoFunctionToHubFunction().dictionary
|
||||
|
||||
@property
|
||||
def hft_function_to_hub_function(self) -> dict:
|
||||
"""
|
||||
Get Hft function to hub function, transformation dictionary
|
||||
:return: dict
|
||||
"""
|
||||
return HftFunctionToHubFunction().dictionary
|
||||
|
||||
@property
|
||||
def montreal_function_to_hub_function(self) -> dict:
|
||||
"""
|
||||
Get Montreal function to hub function, transformation dictionary
|
||||
"""
|
||||
return MontrealFunctionToHubFunction().dictionary
|
||||
|
||||
@property
|
||||
def alkis_function_to_hub_function(self) -> dict:
|
||||
"""
|
||||
Get Alkis function to hub function, transformation dictionary
|
||||
"""
|
||||
return AlkisFunctionToHubFunction().dictionary
|
||||
|
|
@ -39,59 +39,12 @@ class GeometryHelper:
|
|||
max_distance = ConfigurationHelper().max_location_distance_for_shared_walls
|
||||
return GeometryHelper.distance_between_points(location1, location2) < max_distance
|
||||
|
||||
def almost_same_area(self, area_1, area_2):
|
||||
"""
|
||||
Compare two areas and decides if they are almost equal (absolute error under delta)
|
||||
:param area_1
|
||||
:param area_2
|
||||
:return: Boolean
|
||||
"""
|
||||
if area_1 == 0 or area_2 == 0:
|
||||
return False
|
||||
delta = math.fabs(area_1 - area_2)
|
||||
return delta <= self._area_delta
|
||||
|
||||
def is_almost_same_surface(self, surface_1, surface_2):
|
||||
"""
|
||||
Compare two surfaces and decides if they are almost equal (quadratic error under delta)
|
||||
:param surface_1: Surface
|
||||
:param surface_2: Surface
|
||||
:return: Boolean
|
||||
"""
|
||||
|
||||
# delta is grads an need to be converted into radians
|
||||
delta = np.rad2deg(self._delta)
|
||||
difference = (surface_1.inclination - surface_2.inclination) % math.pi
|
||||
if abs(difference) > delta:
|
||||
return False
|
||||
# s1 and s2 are at least almost parallel surfaces
|
||||
# calculate distance point to plane using all the vertex
|
||||
# select surface1 value for the point (X,Y,Z) where two of the values are 0
|
||||
minimum_distance = self._delta + 1
|
||||
parametric = surface_2.polygon.get_parametric()
|
||||
normal_2 = surface_2.normal
|
||||
for point in surface_1.points:
|
||||
distance = abs(
|
||||
(point[0] * parametric[0]) + (point[1] * parametric[1]) + (point[2] * parametric[2]) + parametric[3])
|
||||
normal_module = math.sqrt(pow(normal_2[0], 2) + pow(normal_2[1], 2) + pow(normal_2[2], 2))
|
||||
|
||||
if normal_module == 0:
|
||||
continue
|
||||
distance = distance / normal_module
|
||||
if distance < minimum_distance:
|
||||
minimum_distance = distance
|
||||
if minimum_distance <= self._delta:
|
||||
break
|
||||
|
||||
if minimum_distance > self._delta or surface_1.intersect(surface_2) is None:
|
||||
return False
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def segment_list_to_trimesh(lines) -> Trimesh:
|
||||
"""
|
||||
Transform a list of segments into a Trimesh
|
||||
"""
|
||||
# todo: trimesh has a method for this
|
||||
line_points = [lines[0][0], lines[0][1]]
|
||||
lines.remove(lines[0])
|
||||
while len(lines) > 1:
|
||||
|
@ -106,7 +59,7 @@ class GeometryHelper:
|
|||
line_points.append(line[0])
|
||||
lines.pop(i - 1)
|
||||
break
|
||||
polyhedron = Polyhedron(Polygon(line_points).triangulate())
|
||||
polyhedron = Polyhedron(Polygon(line_points).triangles)
|
||||
trimesh = Trimesh(polyhedron.vertices, polyhedron.faces)
|
||||
return trimesh
|
||||
|
||||
|
|
|
@ -1,138 +0,0 @@
|
|||
"""
|
||||
monthly_to_hourly_demand 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
|
||||
"""
|
||||
import calendar as cal
|
||||
import pandas as pd
|
||||
from hub.city_model_structure.building_demand.occupant import Occupant
|
||||
import hub.helpers.constants as cte
|
||||
|
||||
|
||||
class MonthlyToHourlyDemand:
|
||||
"""
|
||||
MonthlyToHourlyDemand class
|
||||
"""
|
||||
def __init__(self, building, conditioning_seasons):
|
||||
self._hourly_heating = pd.DataFrame()
|
||||
self._hourly_cooling = pd.DataFrame()
|
||||
self._building = building
|
||||
self._conditioning_seasons = conditioning_seasons
|
||||
|
||||
def hourly_heating(self, key):
|
||||
"""
|
||||
hourly distribution of the monthly heating of a building
|
||||
:param key: string
|
||||
:return: [hourly_heating]
|
||||
"""
|
||||
# todo: this method and the insel model have to be reviewed for more than one thermal zone
|
||||
external_temp = self._building.external_temperature[cte.HOUR]
|
||||
# todo: review index depending on how the schedules are defined, either 8760 or 24 hours
|
||||
for usage_zone in self._building.usage_zones:
|
||||
temp_set = float(usage_zone.heating_setpoint)-3
|
||||
temp_back = float(usage_zone.heating_setback)-3
|
||||
# todo: if these are data frames, then they should be called as (Occupancy should be in low case):
|
||||
# usage_zone.schedules.Occupancy
|
||||
# self._conditioning_seasons.heating
|
||||
occupancy = Occupant().get_complete_year_schedule(usage_zone.schedules['Occupancy'])
|
||||
heating_schedule = self._conditioning_seasons['heating']
|
||||
|
||||
hourly_heating = []
|
||||
i = 0
|
||||
j = 0
|
||||
temp_grad_day = []
|
||||
for month in range(1, 13):
|
||||
temp_grad_month = 0
|
||||
month_range = cal.monthrange(2015, month)[1]
|
||||
for _ in range(1, month_range+1):
|
||||
external_temp_med = 0
|
||||
for hour in range(0, 24):
|
||||
external_temp_med += external_temp[key][i]/24
|
||||
for hour in range(0, 24):
|
||||
if external_temp_med < temp_set and heating_schedule[month-1] == 1:
|
||||
if occupancy[hour] > 0:
|
||||
hdd = temp_set - external_temp[key][i]
|
||||
if hdd < 0:
|
||||
hdd = 0
|
||||
temp_grad_day.append(hdd)
|
||||
else:
|
||||
hdd = temp_back - external_temp[key][i]
|
||||
if hdd < 0:
|
||||
hdd = 0
|
||||
temp_grad_day.append(hdd)
|
||||
else:
|
||||
temp_grad_day.append(0)
|
||||
|
||||
temp_grad_month += temp_grad_day[i]
|
||||
i += 1
|
||||
|
||||
for _ in range(1, month_range + 1):
|
||||
for hour in range(0, 24):
|
||||
monthly_demand = self._building.heating[cte.MONTH][month-1]
|
||||
if monthly_demand == 'NaN':
|
||||
monthly_demand = 0
|
||||
if temp_grad_month == 0:
|
||||
hourly_demand = 0
|
||||
else:
|
||||
hourly_demand = float(monthly_demand)*float(temp_grad_day[j])/float(temp_grad_month)
|
||||
hourly_heating.append(hourly_demand)
|
||||
j += 1
|
||||
self._hourly_heating = pd.DataFrame(data=hourly_heating, columns=['monthly to hourly'])
|
||||
return self._hourly_heating
|
||||
|
||||
def hourly_cooling(self, key):
|
||||
"""
|
||||
hourly distribution of the monthly cooling of a building
|
||||
:param key: string
|
||||
:return: [hourly_cooling]
|
||||
"""
|
||||
# todo: this method and the insel model have to be reviewed for more than one thermal zone
|
||||
external_temp = self._building.external_temperature[cte.HOUR]
|
||||
# todo: review index depending on how the schedules are defined, either 8760 or 24 hours
|
||||
for usage_zone in self._building.usage_zones:
|
||||
temp_set = float(usage_zone.cooling_setpoint)
|
||||
temp_back = 100
|
||||
occupancy = Occupant().get_complete_year_schedule(usage_zone.schedules['Occupancy'])
|
||||
cooling_schedule = self._conditioning_seasons['cooling']
|
||||
|
||||
hourly_cooling = []
|
||||
i = 0
|
||||
j = 0
|
||||
temp_grad_day = []
|
||||
for month in range(1, 13):
|
||||
temp_grad_month = 0
|
||||
month_range = cal.monthrange(2015, month)[1]
|
||||
for _ in range(1, month_range[1] + 1):
|
||||
for hour in range(0, 24):
|
||||
if external_temp[key][i] > temp_set and cooling_schedule[month - 1] == 1:
|
||||
if occupancy[hour] > 0:
|
||||
cdd = external_temp[key][i] - temp_set
|
||||
if cdd < 0:
|
||||
cdd = 0
|
||||
temp_grad_day.append(cdd)
|
||||
else:
|
||||
cdd = external_temp[key][i] - temp_back
|
||||
if cdd < 0:
|
||||
cdd = 0
|
||||
temp_grad_day.append(cdd)
|
||||
else:
|
||||
temp_grad_day.append(0)
|
||||
|
||||
temp_grad_month += temp_grad_day[i]
|
||||
i += 1
|
||||
|
||||
for _ in range(1, month_range[1] + 1):
|
||||
for hour in range(0, 24):
|
||||
# monthly_demand = self._building.heating[cte.MONTH]['INSEL'][month-1]
|
||||
monthly_demand = self._building.cooling[cte.MONTH][month - 1]
|
||||
if monthly_demand == 'NaN':
|
||||
monthly_demand = 0
|
||||
if temp_grad_month == 0:
|
||||
hourly_demand = 0
|
||||
else:
|
||||
hourly_demand = float(monthly_demand) * float(temp_grad_day[j]) / float(temp_grad_month)
|
||||
hourly_cooling.append(hourly_demand)
|
||||
j += 1
|
||||
self._hourly_cooling = pd.DataFrame(data=hourly_cooling, columns=['monthly to hourly'])
|
||||
return self._hourly_cooling
|
18
hub/helpers/utils.py
Normal file
18
hub/helpers/utils.py
Normal file
|
@ -0,0 +1,18 @@
|
|||
"""
|
||||
Constant module
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2023 Concordia CERC group
|
||||
Project Coder Peter Yefi peteryefi@gmail.com
|
||||
"""
|
||||
|
||||
|
||||
def validate_import_export_type(cls_name: type):
|
||||
"""
|
||||
Retrieves all the function names in a class which are property types (decoration)
|
||||
and normal functions
|
||||
:param cls_name: the class name
|
||||
:return: [str], a list of functions in the class
|
||||
"""
|
||||
return [func for func in dir(cls_name)
|
||||
if (type(getattr(cls_name, func)) is property or callable(getattr(cls_name, func)))
|
||||
and func in cls_name.__dict__ and func[0] == '_' and func != '__init__']
|
|
@ -1,98 +0,0 @@
|
|||
"""
|
||||
BuildingArchetype stores construction information by building archetypes
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
from typing import List
|
||||
from hub.imports.construction.data_classes.thermal_boundary_archetype import ThermalBoundaryArchetype
|
||||
|
||||
|
||||
class BuildingArchetype:
|
||||
"""
|
||||
BuildingArchetype class
|
||||
"""
|
||||
def __init__(self, archetype_keys, average_storey_height, storeys_above_ground, effective_thermal_capacity,
|
||||
additional_thermal_bridge_u_value, indirectly_heated_area_ratio, infiltration_rate_system_off,
|
||||
infiltration_rate_system_on, thermal_boundary_archetypes):
|
||||
self._archetype_keys = archetype_keys
|
||||
self._average_storey_height = average_storey_height
|
||||
self._storeys_above_ground = storeys_above_ground
|
||||
self._effective_thermal_capacity = effective_thermal_capacity
|
||||
self._additional_thermal_bridge_u_value = additional_thermal_bridge_u_value
|
||||
self._indirectly_heated_area_ratio = indirectly_heated_area_ratio
|
||||
self._infiltration_rate_system_off = infiltration_rate_system_off
|
||||
self._infiltration_rate_system_on = infiltration_rate_system_on
|
||||
self._thermal_boundary_archetypes = thermal_boundary_archetypes
|
||||
|
||||
@property
|
||||
def archetype_keys(self) -> {}:
|
||||
"""
|
||||
Get keys that define the archetype
|
||||
:return: dictionary
|
||||
"""
|
||||
return self._archetype_keys
|
||||
|
||||
@property
|
||||
def average_storey_height(self):
|
||||
"""
|
||||
Get archetype's building storey height in meters
|
||||
:return: float
|
||||
"""
|
||||
return self._average_storey_height
|
||||
|
||||
@property
|
||||
def storeys_above_ground(self):
|
||||
"""
|
||||
Get archetype's building storey height in meters
|
||||
:return: float
|
||||
"""
|
||||
return self._storeys_above_ground
|
||||
|
||||
@property
|
||||
def effective_thermal_capacity(self):
|
||||
"""
|
||||
Get archetype's effective thermal capacity in J/m2K
|
||||
:return: float
|
||||
"""
|
||||
return self._effective_thermal_capacity
|
||||
|
||||
@property
|
||||
def additional_thermal_bridge_u_value(self):
|
||||
"""
|
||||
Get archetype's additional U value due to thermal bridges per area of shell in W/m2K
|
||||
:return: float
|
||||
"""
|
||||
return self._additional_thermal_bridge_u_value
|
||||
|
||||
@property
|
||||
def indirectly_heated_area_ratio(self):
|
||||
"""
|
||||
Get archetype's indirectly heated area ratio
|
||||
:return: float
|
||||
"""
|
||||
return self._indirectly_heated_area_ratio
|
||||
|
||||
@property
|
||||
def infiltration_rate_system_off(self):
|
||||
"""
|
||||
Get archetype's infiltration rate when conditioning systems OFF in air changes per hour (ACH)
|
||||
:return: float
|
||||
"""
|
||||
return self._infiltration_rate_system_off
|
||||
|
||||
@property
|
||||
def infiltration_rate_system_on(self):
|
||||
"""
|
||||
Get archetype's infiltration rate when conditioning systems ON in air changes per hour (ACH)
|
||||
:return: float
|
||||
"""
|
||||
return self._infiltration_rate_system_on
|
||||
|
||||
@property
|
||||
def thermal_boundary_archetypes(self) -> List[ThermalBoundaryArchetype]:
|
||||
"""
|
||||
Get thermal boundary archetypes associated to the building archetype
|
||||
:return: list of boundary archetypes
|
||||
"""
|
||||
return self._thermal_boundary_archetypes
|
|
@ -1,104 +0,0 @@
|
|||
"""
|
||||
LayerArchetype stores layer and materials information, complementing the BuildingArchetype class
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
|
||||
|
||||
class LayerArchetype:
|
||||
"""
|
||||
LayerArchetype class
|
||||
"""
|
||||
def __init__(self, name, solar_absorptance, thermal_absorptance, visible_absorptance, thickness=None,
|
||||
conductivity=None, specific_heat=None, density=None, no_mass=False, thermal_resistance=None):
|
||||
self._thickness = thickness
|
||||
self._conductivity = conductivity
|
||||
self._specific_heat = specific_heat
|
||||
self._density = density
|
||||
self._solar_absorptance = solar_absorptance
|
||||
self._thermal_absorptance = thermal_absorptance
|
||||
self._visible_absorptance = visible_absorptance
|
||||
self._no_mass = no_mass
|
||||
self._name = name
|
||||
self._thermal_resistance = thermal_resistance
|
||||
|
||||
@property
|
||||
def thickness(self):
|
||||
"""
|
||||
Get thickness in meters
|
||||
:return: float
|
||||
"""
|
||||
return self._thickness
|
||||
|
||||
@property
|
||||
def conductivity(self):
|
||||
"""
|
||||
Get conductivity in W/mK
|
||||
:return: float
|
||||
"""
|
||||
return self._conductivity
|
||||
|
||||
@property
|
||||
def specific_heat(self):
|
||||
"""
|
||||
Get specific heat in J/kgK
|
||||
:return: float
|
||||
"""
|
||||
return self._specific_heat
|
||||
|
||||
@property
|
||||
def density(self):
|
||||
"""
|
||||
Get density in kg/m3
|
||||
:return: float
|
||||
"""
|
||||
return self._density
|
||||
|
||||
@property
|
||||
def solar_absorptance(self):
|
||||
"""
|
||||
Get solar absorptance
|
||||
:return: float
|
||||
"""
|
||||
return self._solar_absorptance
|
||||
|
||||
@property
|
||||
def thermal_absorptance(self):
|
||||
"""
|
||||
Get thermal absorptance
|
||||
:return: float
|
||||
"""
|
||||
return self._thermal_absorptance
|
||||
|
||||
@property
|
||||
def visible_absorptance(self):
|
||||
"""
|
||||
Get visible absorptance
|
||||
:return: float
|
||||
"""
|
||||
return self._visible_absorptance
|
||||
|
||||
@property
|
||||
def no_mass(self) -> bool:
|
||||
"""
|
||||
Get no mass flag
|
||||
:return: Boolean
|
||||
"""
|
||||
return self._no_mass
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""
|
||||
Get name
|
||||
:return: str
|
||||
"""
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def thermal_resistance(self):
|
||||
"""
|
||||
Get thermal resistance in m2K/W
|
||||
:return: float
|
||||
"""
|
||||
return self._thermal_resistance
|
|
@ -1,137 +0,0 @@
|
|||
"""
|
||||
ThermalBoundaryArchetype stores thermal boundaries information, complementing the BuildingArchetype class
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
from typing import List
|
||||
|
||||
from hub.imports.construction.data_classes.layer_archetype import LayerArchetype
|
||||
from hub.imports.construction.data_classes.thermal_opening_archetype import ThermalOpeningArchetype
|
||||
|
||||
|
||||
class ThermalBoundaryArchetype:
|
||||
"""
|
||||
ThermalBoundaryArchetype class
|
||||
"""
|
||||
def __init__(self, boundary_type, window_ratio, construction_name, layers, thermal_opening,
|
||||
outside_solar_absorptance=None, outside_thermal_absorptance=None, outside_visible_absorptance=None,
|
||||
overall_u_value=None, shortwave_reflectance=None, inside_emissivity=None, alpha_coefficient=None,
|
||||
radiative_coefficient=None):
|
||||
self._boundary_type = boundary_type
|
||||
self._outside_solar_absorptance = outside_solar_absorptance
|
||||
self._outside_thermal_absorptance = outside_thermal_absorptance
|
||||
self._outside_visible_absorptance = outside_visible_absorptance
|
||||
self._window_ratio = window_ratio
|
||||
self._construction_name = construction_name
|
||||
self._overall_u_value = overall_u_value
|
||||
self._layers = layers
|
||||
self._thermal_opening_archetype = thermal_opening
|
||||
self._shortwave_reflectance = shortwave_reflectance
|
||||
self._inside_emissivity = inside_emissivity
|
||||
self._alpha_coefficient = alpha_coefficient
|
||||
self._radiative_coefficient = radiative_coefficient
|
||||
|
||||
@property
|
||||
def boundary_type(self):
|
||||
"""
|
||||
Get type
|
||||
:return: str
|
||||
"""
|
||||
return self._boundary_type
|
||||
|
||||
@property
|
||||
def outside_solar_absorptance(self):
|
||||
"""
|
||||
Get outside solar absorptance
|
||||
:return: float
|
||||
"""
|
||||
return self._outside_solar_absorptance
|
||||
|
||||
@property
|
||||
def outside_thermal_absorptance(self):
|
||||
"""
|
||||
Get outside thermal absorptance
|
||||
:return: float
|
||||
"""
|
||||
return self._outside_thermal_absorptance
|
||||
|
||||
@property
|
||||
def outside_visible_absorptance(self):
|
||||
"""
|
||||
Get outside visible absorptance
|
||||
:return: float
|
||||
"""
|
||||
return self._outside_visible_absorptance
|
||||
|
||||
@property
|
||||
def window_ratio(self):
|
||||
"""
|
||||
Get window ratio
|
||||
:return: float
|
||||
"""
|
||||
return self._window_ratio
|
||||
|
||||
@property
|
||||
def construction_name(self):
|
||||
"""
|
||||
Get construction name
|
||||
:return: str
|
||||
"""
|
||||
return self._construction_name
|
||||
|
||||
@property
|
||||
def layers(self) -> List[LayerArchetype]:
|
||||
"""
|
||||
Get layers
|
||||
:return: [NrelLayerArchetype]
|
||||
"""
|
||||
return self._layers
|
||||
|
||||
@property
|
||||
def thermal_opening_archetype(self) -> ThermalOpeningArchetype:
|
||||
"""
|
||||
Get thermal opening archetype
|
||||
:return: ThermalOpeningArchetype
|
||||
"""
|
||||
return self._thermal_opening_archetype
|
||||
|
||||
@property
|
||||
def overall_u_value(self):
|
||||
"""
|
||||
Get overall U-value in W/m2K
|
||||
:return: float
|
||||
"""
|
||||
return self._overall_u_value
|
||||
|
||||
@property
|
||||
def shortwave_reflectance(self):
|
||||
"""
|
||||
Get shortwave reflectance
|
||||
:return: float
|
||||
"""
|
||||
return self._shortwave_reflectance
|
||||
|
||||
@property
|
||||
def inside_emissivity(self):
|
||||
"""
|
||||
Get emissivity inside
|
||||
:return: float
|
||||
"""
|
||||
return self._inside_emissivity
|
||||
|
||||
@property
|
||||
def alpha_coefficient(self):
|
||||
"""
|
||||
Get alpha coefficient
|
||||
:return: float
|
||||
"""
|
||||
return self._alpha_coefficient
|
||||
|
||||
@property
|
||||
def radiative_coefficient(self):
|
||||
"""
|
||||
Get radiative coefficient
|
||||
:return: float
|
||||
"""
|
||||
return self._radiative_coefficient
|
|
@ -1,131 +0,0 @@
|
|||
"""
|
||||
ThermalOpeningArchetype stores thermal openings information, complementing the BuildingArchetype class
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
|
||||
|
||||
class ThermalOpeningArchetype:
|
||||
"""
|
||||
ThermalOpeningArchetype class
|
||||
"""
|
||||
def __init__(self, conductivity=None, frame_ratio=None, g_value=None, thickness=None,
|
||||
back_side_solar_transmittance_at_normal_incidence=None,
|
||||
front_side_solar_transmittance_at_normal_incidence=None, overall_u_value=None,
|
||||
openable_ratio=None, inside_emissivity=None, alpha_coefficient=None, radiative_coefficient=None,
|
||||
construction_name=None):
|
||||
self._conductivity = conductivity
|
||||
self._frame_ratio = frame_ratio
|
||||
self._g_value = g_value
|
||||
self._thickness = thickness
|
||||
self._back_side_solar_transmittance_at_normal_incidence = back_side_solar_transmittance_at_normal_incidence
|
||||
self._front_side_solar_transmittance_at_normal_incidence = front_side_solar_transmittance_at_normal_incidence
|
||||
self._overall_u_value = overall_u_value
|
||||
self._openable_ratio = openable_ratio
|
||||
self._inside_emissivity = inside_emissivity
|
||||
self._alpha_coefficient = alpha_coefficient
|
||||
self._radiative_coefficient = radiative_coefficient
|
||||
self._construction_name = construction_name
|
||||
|
||||
@property
|
||||
def conductivity(self):
|
||||
"""
|
||||
Get conductivity in W/mK
|
||||
:return: float
|
||||
"""
|
||||
return self._conductivity
|
||||
|
||||
@property
|
||||
def frame_ratio(self):
|
||||
"""
|
||||
Get frame ratio
|
||||
:return: float
|
||||
"""
|
||||
return self._frame_ratio
|
||||
|
||||
@property
|
||||
def g_value(self):
|
||||
"""
|
||||
Get g-value, also called shgc
|
||||
:return: float
|
||||
"""
|
||||
return self._g_value
|
||||
|
||||
@property
|
||||
def thickness(self):
|
||||
"""
|
||||
Get thickness in meters
|
||||
:return: float
|
||||
"""
|
||||
return self._thickness
|
||||
|
||||
@property
|
||||
def back_side_solar_transmittance_at_normal_incidence(self):
|
||||
"""
|
||||
Get back side solar transmittance at normal incidence
|
||||
:return: float
|
||||
"""
|
||||
return self._back_side_solar_transmittance_at_normal_incidence
|
||||
|
||||
@property
|
||||
def front_side_solar_transmittance_at_normal_incidence(self):
|
||||
"""
|
||||
Get front side solar transmittance at normal incidence
|
||||
:return: float
|
||||
"""
|
||||
return self._front_side_solar_transmittance_at_normal_incidence
|
||||
|
||||
@property
|
||||
def overall_u_value(self):
|
||||
"""
|
||||
Get overall U-value in W/m2K
|
||||
:return: float
|
||||
"""
|
||||
return self._overall_u_value
|
||||
|
||||
@property
|
||||
def openable_ratio(self):
|
||||
"""
|
||||
Get openable ratio
|
||||
:return: float
|
||||
"""
|
||||
return self._openable_ratio
|
||||
|
||||
@property
|
||||
def inside_emissivity(self):
|
||||
"""
|
||||
Get emissivity inside
|
||||
:return: float
|
||||
"""
|
||||
return self._inside_emissivity
|
||||
|
||||
@property
|
||||
def alpha_coefficient(self):
|
||||
"""
|
||||
Get alpha coefficient
|
||||
:return: float
|
||||
"""
|
||||
return self._alpha_coefficient
|
||||
|
||||
@property
|
||||
def radiative_coefficient(self):
|
||||
"""
|
||||
Get radiative coefficient
|
||||
:return: float
|
||||
"""
|
||||
return self._radiative_coefficient
|
||||
|
||||
@property
|
||||
def construction_name(self):
|
||||
"""
|
||||
Get thermal opening construction name
|
||||
"""
|
||||
return self._construction_name
|
||||
|
||||
@construction_name.setter
|
||||
def construction_name(self, value):
|
||||
"""
|
||||
Set thermal opening construction name
|
||||
"""
|
||||
self._construction_name = value
|
|
@ -4,7 +4,7 @@ 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
|
||||
|
||||
from hub.helpers import constants as cte
|
||||
|
||||
|
||||
|
@ -13,30 +13,6 @@ class ConstructionHelper:
|
|||
Construction helper
|
||||
"""
|
||||
# NREL
|
||||
_function_to_nrel = {
|
||||
cte.RESIDENTIAL: 'residential',
|
||||
cte.SINGLE_FAMILY_HOUSE: 'residential',
|
||||
cte.MULTI_FAMILY_HOUSE: 'residential',
|
||||
cte.ROW_HOSE: 'residential',
|
||||
cte.MID_RISE_APARTMENT: 'midrise apartment',
|
||||
cte.HIGH_RISE_APARTMENT: 'high-rise apartment',
|
||||
cte.SMALL_OFFICE: 'small office',
|
||||
cte.MEDIUM_OFFICE: 'medium office',
|
||||
cte.LARGE_OFFICE: 'large office',
|
||||
cte.PRIMARY_SCHOOL: 'primary school',
|
||||
cte.SECONDARY_SCHOOL: 'secondary school',
|
||||
cte.STAND_ALONE_RETAIL: 'stand-alone retail',
|
||||
cte.HOSPITAL: 'hospital',
|
||||
cte.OUT_PATIENT_HEALTH_CARE: 'outpatient healthcare',
|
||||
cte.STRIP_MALL: 'strip mall',
|
||||
cte.SUPERMARKET: 'supermarket',
|
||||
cte.WAREHOUSE: 'warehouse',
|
||||
cte.QUICK_SERVICE_RESTAURANT: 'quick service restaurant',
|
||||
cte.FULL_SERVICE_RESTAURANT: 'full service restaurant',
|
||||
cte.SMALL_HOTEL: 'small hotel',
|
||||
cte.LARGE_HOTEL: 'large hotel'
|
||||
}
|
||||
|
||||
_nrel_standards = {
|
||||
'ASHRAE Std189': 1,
|
||||
'ASHRAE 90.1_2004': 2
|
||||
|
@ -71,18 +47,6 @@ class ConstructionHelper:
|
|||
cte.ROOF: 'roof'
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def nrel_from_libs_function(function):
|
||||
"""
|
||||
Get NREL function from the given internal function key
|
||||
:param function: str
|
||||
:return: str
|
||||
"""
|
||||
try:
|
||||
return ConstructionHelper._function_to_nrel[function]
|
||||
except KeyError:
|
||||
sys.stderr.write('Error: keyword not found.\n')
|
||||
|
||||
@staticmethod
|
||||
def yoc_to_nrel_standard(year_of_construction):
|
||||
"""
|
||||
|
@ -117,4 +81,4 @@ class ConstructionHelper:
|
|||
:return: str
|
||||
"""
|
||||
reference_city = ConstructionHelper.city_to_reference_city(city)
|
||||
return ConstructionHelper._reference_city_to_nrel_climate_zone[reference_city]
|
||||
return ConstructionHelper._reference_city_to_nrel_climate_zone[reference_city]
|
||||
|
|
|
@ -49,7 +49,7 @@ class StoreysGeneration:
|
|||
thermal_zones = [storey.thermal_zone]
|
||||
else:
|
||||
# internal thermal boundary -> two thermal zones
|
||||
grad = np.rad2deg(thermal_boundary.inclination)
|
||||
grad = np.rad2deg(thermal_boundary.parent_surface.inclination)
|
||||
if grad >= 170:
|
||||
thermal_zones = [storey.thermal_zone, storey.neighbours[0]]
|
||||
else:
|
||||
|
@ -116,7 +116,7 @@ class StoreysGeneration:
|
|||
thermal_zones = [storey.thermal_zone]
|
||||
else:
|
||||
# internal thermal boundary -> two thermal zones
|
||||
grad = np.rad2deg(thermal_boundary.inclination)
|
||||
grad = np.rad2deg(thermal_boundary.parent_surface.inclination)
|
||||
if grad >= 170:
|
||||
thermal_zones = [storey.thermal_zone, storey.neighbours[0]]
|
||||
else:
|
||||
|
|
189
hub/imports/construction/nrcan_physics_parameters.py
Normal file
189
hub/imports/construction/nrcan_physics_parameters.py
Normal file
|
@ -0,0 +1,189 @@
|
|||
"""
|
||||
NrcanPhysicsParameters import the construction and material information defined by NRCAN
|
||||
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
|
||||
|
||||
from hub.catalog_factories.construction_catalog_factory import ConstructionCatalogFactory
|
||||
from hub.city_model_structure.building_demand.layer import Layer
|
||||
from hub.city_model_structure.building_demand.material import Material
|
||||
from hub.helpers.dictionaries import Dictionaries
|
||||
from hub.imports.construction.helpers.construction_helper import ConstructionHelper
|
||||
from hub.imports.construction.helpers.storeys_generation import StoreysGeneration
|
||||
|
||||
|
||||
class NrcanPhysicsParameters:
|
||||
"""
|
||||
NrcanPhysicsParameters class
|
||||
"""
|
||||
def __init__(self, city, base_path, divide_in_storeys=False):
|
||||
self._city = city
|
||||
self._path = base_path
|
||||
self._divide_in_storeys = divide_in_storeys
|
||||
self._climate_zone = ConstructionHelper.city_to_nrel_climate_zone(city.name)
|
||||
|
||||
def enrich_buildings(self):
|
||||
"""
|
||||
Returns the city with the construction parameters assigned to the buildings
|
||||
"""
|
||||
city = self._city
|
||||
canel_catalog = ConstructionCatalogFactory('nrcan').catalog
|
||||
for building in city.buildings:
|
||||
try:
|
||||
function = Dictionaries().hub_function_to_nrcan_construction_function[building.function]
|
||||
archetype = self._search_archetype(canel_catalog, function, building.year_of_construction,
|
||||
self._climate_zone)
|
||||
except KeyError:
|
||||
sys.stderr.write(f'Building {building.name} has unknown construction archetype for building function: '
|
||||
f'{building.function} and building year of construction: {building.year_of_construction} '
|
||||
f'and climate zone reference norm {self._climate_zone}\n')
|
||||
return
|
||||
|
||||
# if building has no thermal zones defined from geometry, and the building will be divided in storeys,
|
||||
# one thermal zone per storey is assigned
|
||||
if len(building.internal_zones) == 1:
|
||||
if building.internal_zones[0].thermal_zones is None:
|
||||
self._create_storeys(building, archetype, self._divide_in_storeys)
|
||||
if self._divide_in_storeys:
|
||||
for internal_zone in building.internal_zones:
|
||||
for thermal_zone in internal_zone.thermal_zones:
|
||||
thermal_zone.total_floor_area = thermal_zone.footprint_area
|
||||
else:
|
||||
number_of_storeys = int(float(building.eave_height) / float(building.average_storey_height))
|
||||
thermal_zone = building.internal_zones[0].thermal_zones[0]
|
||||
thermal_zone.total_floor_area = thermal_zone.footprint_area * number_of_storeys
|
||||
else:
|
||||
for internal_zone in building.internal_zones:
|
||||
for thermal_zone in internal_zone.thermal_zones:
|
||||
thermal_zone.total_floor_area = thermal_zone.footprint_area
|
||||
|
||||
for internal_zone in building.internal_zones:
|
||||
self._assign_values(internal_zone.thermal_zones, archetype)
|
||||
for thermal_zone in internal_zone.thermal_zones:
|
||||
self._calculate_view_factors(thermal_zone)
|
||||
|
||||
@staticmethod
|
||||
def _search_archetype(nrel_catalog, function, year_of_construction, climate_zone):
|
||||
nrel_archetypes = nrel_catalog.entries('archetypes')
|
||||
for building_archetype in nrel_archetypes:
|
||||
construction_period_limits = building_archetype.construction_period.split(' - ')
|
||||
if construction_period_limits[1] == 'PRESENT':
|
||||
construction_period_limits[1] = 3000
|
||||
if int(construction_period_limits[0]) <= int(year_of_construction) < int(construction_period_limits[1]):
|
||||
if (str(function) == str(building_archetype.function)) and \
|
||||
(climate_zone == str(building_archetype.climate_zone)):
|
||||
return building_archetype
|
||||
raise KeyError('archetype not found')
|
||||
|
||||
@staticmethod
|
||||
def _search_construction_in_archetype(archetype, construction_type):
|
||||
construction_archetypes = archetype.constructions
|
||||
for construction_archetype in construction_archetypes:
|
||||
if str(construction_type) == str(construction_archetype.type):
|
||||
return construction_archetype
|
||||
return None
|
||||
|
||||
def _assign_values(self, thermal_zones, archetype):
|
||||
for thermal_zone in thermal_zones:
|
||||
thermal_zone.additional_thermal_bridge_u_value = archetype.extra_loses_due_to_thermal_bridges
|
||||
thermal_zone.effective_thermal_capacity = archetype.thermal_capacity
|
||||
thermal_zone.indirectly_heated_area_ratio = archetype.indirect_heated_ratio
|
||||
thermal_zone.infiltration_rate_system_on = archetype.infiltration_rate_for_ventilation_system_on
|
||||
thermal_zone.infiltration_rate_system_off = archetype.infiltration_rate_for_ventilation_system_off
|
||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||
construction_archetype = self._search_construction_in_archetype(archetype, thermal_boundary.type)
|
||||
thermal_boundary.construction_name = construction_archetype.name
|
||||
try:
|
||||
thermal_boundary.window_ratio = construction_archetype.window_ratio
|
||||
except ValueError:
|
||||
# This is the normal operation way when the windows are defined in the geometry
|
||||
continue
|
||||
thermal_boundary.layers = []
|
||||
for layer_archetype in construction_archetype.layers:
|
||||
layer = Layer()
|
||||
layer.thickness = layer_archetype.thickness
|
||||
material = Material()
|
||||
archetype_material = layer_archetype.material
|
||||
material.name = archetype_material.name
|
||||
material.id = archetype_material.id
|
||||
material.no_mass = archetype_material.no_mass
|
||||
if archetype_material.no_mass:
|
||||
material.thermal_resistance = archetype_material.thermal_resistance
|
||||
else:
|
||||
material.density = archetype_material.density
|
||||
material.conductivity = archetype_material.conductivity
|
||||
material.specific_heat = archetype_material.specific_heat
|
||||
material.solar_absorptance = archetype_material.solar_absorptance
|
||||
material.thermal_absorptance = archetype_material.thermal_absorptance
|
||||
material.visible_absorptance = archetype_material.visible_absorptance
|
||||
layer.material = material
|
||||
thermal_boundary.layers.append(layer)
|
||||
# The agreement is that the layers are defined from outside to inside
|
||||
external_layer = construction_archetype.layers[0]
|
||||
external_surface = thermal_boundary.parent_surface
|
||||
external_surface.short_wave_reflectance = 1 - float(external_layer.material.solar_absorptance)
|
||||
external_surface.long_wave_emittance = 1 - float(external_layer.material.solar_absorptance)
|
||||
internal_layer = construction_archetype.layers[len(construction_archetype.layers) - 1]
|
||||
internal_surface = thermal_boundary.internal_surface
|
||||
internal_surface.short_wave_reflectance = 1 - float(internal_layer.material.solar_absorptance)
|
||||
internal_surface.long_wave_emittance = 1 - float(internal_layer.material.solar_absorptance)
|
||||
|
||||
for thermal_opening in thermal_boundary.thermal_openings:
|
||||
if construction_archetype.window is not None:
|
||||
window_archetype = construction_archetype.window
|
||||
thermal_opening.construction_name = window_archetype.name
|
||||
thermal_opening.frame_ratio = window_archetype.frame_ratio
|
||||
thermal_opening.g_value = window_archetype.g_value
|
||||
thermal_opening.overall_u_value = window_archetype.overall_u_value
|
||||
|
||||
# todo: verify windows
|
||||
@staticmethod
|
||||
def _calculate_view_factors(thermal_zone):
|
||||
"""
|
||||
Get thermal zone view factors matrix
|
||||
:return: [[float]]
|
||||
"""
|
||||
total_area = 0
|
||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||
total_area += thermal_boundary.opaque_area
|
||||
for thermal_opening in thermal_boundary.thermal_openings:
|
||||
total_area += thermal_opening.area
|
||||
|
||||
view_factors_matrix = []
|
||||
for thermal_boundary_1 in thermal_zone.thermal_boundaries:
|
||||
values = []
|
||||
for thermal_boundary_2 in thermal_zone.thermal_boundaries:
|
||||
value = 0
|
||||
if thermal_boundary_1.id != thermal_boundary_2.id:
|
||||
value = thermal_boundary_2.opaque_area / (total_area - thermal_boundary_1.opaque_area)
|
||||
values.append(value)
|
||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||
for thermal_opening in thermal_boundary.thermal_openings:
|
||||
value = thermal_opening.area / (total_area - thermal_boundary_1.opaque_area)
|
||||
values.append(value)
|
||||
view_factors_matrix.append(values)
|
||||
|
||||
for thermal_boundary_1 in thermal_zone.thermal_boundaries:
|
||||
values = []
|
||||
for thermal_opening_1 in thermal_boundary_1.thermal_openings:
|
||||
for thermal_boundary_2 in thermal_zone.thermal_boundaries:
|
||||
value = thermal_boundary_2.opaque_area / (total_area - thermal_opening_1.area)
|
||||
values.append(value)
|
||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||
for thermal_opening_2 in thermal_boundary.thermal_openings:
|
||||
value = 0
|
||||
if thermal_opening_1.id != thermal_opening_2.id:
|
||||
value = thermal_opening_2.area / (total_area - thermal_opening_1.area)
|
||||
values.append(value)
|
||||
view_factors_matrix.append(values)
|
||||
thermal_zone.view_factors_matrix = view_factors_matrix
|
||||
|
||||
@staticmethod
|
||||
def _create_storeys(building, archetype, divide_in_storeys):
|
||||
building.average_storey_height = archetype.average_storey_height
|
||||
building.storeys_above_ground = 1
|
||||
thermal_zones = StoreysGeneration(building, building.internal_zones[0],
|
||||
divide_in_storeys=divide_in_storeys).thermal_zones
|
||||
building.internal_zones[0].thermal_zones = thermal_zones
|
|
@ -1,71 +0,0 @@
|
|||
"""
|
||||
Nrel-based interface, it reads format defined within the CERC team based on NREL structure
|
||||
and enriches the city with archetypes and materials
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
|
||||
from hub.imports.construction.helpers.storeys_generation import StoreysGeneration
|
||||
|
||||
|
||||
class NrelPhysicsInterface:
|
||||
"""
|
||||
NrelPhysicsInterface abstract class
|
||||
"""
|
||||
|
||||
# todo: verify windows
|
||||
@staticmethod
|
||||
def _calculate_view_factors(thermal_zone):
|
||||
"""
|
||||
Get thermal zone view factors matrix
|
||||
:return: [[float]]
|
||||
"""
|
||||
total_area = 0
|
||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||
total_area += thermal_boundary.opaque_area
|
||||
for thermal_opening in thermal_boundary.thermal_openings:
|
||||
total_area += thermal_opening.area
|
||||
|
||||
view_factors_matrix = []
|
||||
for thermal_boundary_1 in thermal_zone.thermal_boundaries:
|
||||
values = []
|
||||
for thermal_boundary_2 in thermal_zone.thermal_boundaries:
|
||||
value = 0
|
||||
if thermal_boundary_1.id != thermal_boundary_2.id:
|
||||
value = thermal_boundary_2.opaque_area / (total_area - thermal_boundary_1.opaque_area)
|
||||
values.append(value)
|
||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||
for thermal_opening in thermal_boundary.thermal_openings:
|
||||
value = thermal_opening.area / (total_area - thermal_boundary_1.opaque_area)
|
||||
values.append(value)
|
||||
view_factors_matrix.append(values)
|
||||
|
||||
for thermal_boundary_1 in thermal_zone.thermal_boundaries:
|
||||
values = []
|
||||
for thermal_opening_1 in thermal_boundary_1.thermal_openings:
|
||||
for thermal_boundary_2 in thermal_zone.thermal_boundaries:
|
||||
value = thermal_boundary_2.opaque_area / (total_area - thermal_opening_1.area)
|
||||
values.append(value)
|
||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||
for thermal_opening_2 in thermal_boundary.thermal_openings:
|
||||
value = 0
|
||||
if thermal_opening_1.id != thermal_opening_2.id:
|
||||
value = thermal_opening_2.area / (total_area - thermal_opening_1.area)
|
||||
values.append(value)
|
||||
view_factors_matrix.append(values)
|
||||
thermal_zone.view_factors_matrix = view_factors_matrix
|
||||
|
||||
@staticmethod
|
||||
def _create_storeys(building, archetype, divide_in_storeys):
|
||||
building.average_storey_height = archetype.average_storey_height
|
||||
building.storeys_above_ground = 1
|
||||
thermal_zones = StoreysGeneration(building, building.internal_zones[0],
|
||||
divide_in_storeys=divide_in_storeys).thermal_zones
|
||||
building.internal_zones[0].thermal_zones = thermal_zones
|
||||
|
||||
def enrich_buildings(self):
|
||||
"""
|
||||
Raise not implemented error
|
||||
"""
|
||||
raise NotImplementedError
|
|
@ -1,5 +1,5 @@
|
|||
"""
|
||||
UsPhysicsParameters import the construction and material information for US
|
||||
NrelPhysicsParameters import the construction and material information defined by NREL
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
||||
|
@ -7,38 +7,41 @@ Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concord
|
|||
"""
|
||||
import sys
|
||||
|
||||
from hub.imports.construction.nrel_physics_interface import NrelPhysicsInterface
|
||||
from hub.hub_logger import logger
|
||||
from hub.catalog_factories.construction_catalog_factory import ConstructionCatalogFactory
|
||||
from hub.city_model_structure.building_demand.layer import Layer
|
||||
from hub.city_model_structure.building_demand.material import Material
|
||||
from hub.helpers.dictionaries import Dictionaries
|
||||
from hub.imports.construction.helpers.construction_helper import ConstructionHelper
|
||||
from hub.hub_logger import logger
|
||||
from hub.imports.construction.helpers.storeys_generation import StoreysGeneration
|
||||
|
||||
|
||||
class UsPhysicsParameters(NrelPhysicsInterface):
|
||||
class NrelPhysicsParameters:
|
||||
"""
|
||||
UsPhysicsParameters class
|
||||
NrelPhysicsParameters class
|
||||
"""
|
||||
|
||||
def __init__(self, city, base_path, divide_in_storeys=False):
|
||||
self._city = city
|
||||
self._path = base_path
|
||||
self._divide_in_storeys = divide_in_storeys
|
||||
self._climate_zone = ConstructionHelper.city_to_nrel_climate_zone(city.name)
|
||||
super().__init__()
|
||||
|
||||
def enrich_buildings(self):
|
||||
"""
|
||||
Returns the city with the construction parameters assigned to the buildings
|
||||
"""
|
||||
city = self._city
|
||||
nrel_catalog = ConstructionCatalogFactory('nrel').catalog
|
||||
for building in city.buildings:
|
||||
try:
|
||||
archetype = self._search_archetype(building.function, building.year_of_construction, self._climate_zone)
|
||||
function = Dictionaries().hub_function_to_nrel_construction_function[building.function]
|
||||
archetype = self._search_archetype(nrel_catalog, function, building.year_of_construction,
|
||||
self._climate_zone)
|
||||
except KeyError:
|
||||
|
||||
logger.error(f'Building {building.name} has unknown archetype for building function: {building.function} '
|
||||
f'and building year of construction: {building.year_of_construction} '
|
||||
f'and climate zone reference norm {self._climate_zone}\n')
|
||||
f'and building year of construction: {building.year_of_construction} '
|
||||
f'and climate zone reference norm {self._climate_zone}\n')
|
||||
sys.stderr.write(f'Building {building.name} has unknown archetype for building function: {building.function} '
|
||||
f'and building year of construction: {building.year_of_construction} '
|
||||
f'and climate zone reference norm {self._climate_zone}\n')
|
||||
|
@ -69,8 +72,7 @@ class UsPhysicsParameters(NrelPhysicsInterface):
|
|||
self._calculate_view_factors(thermal_zone)
|
||||
|
||||
@staticmethod
|
||||
def _search_archetype(function, year_of_construction, climate_zone):
|
||||
nrel_catalog = ConstructionCatalogFactory('nrel').catalog
|
||||
def _search_archetype(nrel_catalog, function, year_of_construction, climate_zone):
|
||||
nrel_archetypes = nrel_catalog.entries('archetypes')
|
||||
for building_archetype in nrel_archetypes:
|
||||
construction_period_limits = building_archetype.construction_period.split(' - ')
|
||||
|
@ -142,3 +144,53 @@ class UsPhysicsParameters(NrelPhysicsInterface):
|
|||
thermal_opening.frame_ratio = window_archetype.frame_ratio
|
||||
thermal_opening.g_value = window_archetype.g_value
|
||||
thermal_opening.overall_u_value = window_archetype.overall_u_value
|
||||
|
||||
# todo: verify windows
|
||||
@staticmethod
|
||||
def _calculate_view_factors(thermal_zone):
|
||||
"""
|
||||
Get thermal zone view factors matrix
|
||||
:return: [[float]]
|
||||
"""
|
||||
total_area = 0
|
||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||
total_area += thermal_boundary.opaque_area
|
||||
for thermal_opening in thermal_boundary.thermal_openings:
|
||||
total_area += thermal_opening.area
|
||||
|
||||
view_factors_matrix = []
|
||||
for thermal_boundary_1 in thermal_zone.thermal_boundaries:
|
||||
values = []
|
||||
for thermal_boundary_2 in thermal_zone.thermal_boundaries:
|
||||
value = 0
|
||||
if thermal_boundary_1.id != thermal_boundary_2.id:
|
||||
value = thermal_boundary_2.opaque_area / (total_area - thermal_boundary_1.opaque_area)
|
||||
values.append(value)
|
||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||
for thermal_opening in thermal_boundary.thermal_openings:
|
||||
value = thermal_opening.area / (total_area - thermal_boundary_1.opaque_area)
|
||||
values.append(value)
|
||||
view_factors_matrix.append(values)
|
||||
|
||||
for thermal_boundary_1 in thermal_zone.thermal_boundaries:
|
||||
values = []
|
||||
for thermal_opening_1 in thermal_boundary_1.thermal_openings:
|
||||
for thermal_boundary_2 in thermal_zone.thermal_boundaries:
|
||||
value = thermal_boundary_2.opaque_area / (total_area - thermal_opening_1.area)
|
||||
values.append(value)
|
||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||
for thermal_opening_2 in thermal_boundary.thermal_openings:
|
||||
value = 0
|
||||
if thermal_opening_1.id != thermal_opening_2.id:
|
||||
value = thermal_opening_2.area / (total_area - thermal_opening_1.area)
|
||||
values.append(value)
|
||||
view_factors_matrix.append(values)
|
||||
thermal_zone.view_factors_matrix = view_factors_matrix
|
||||
|
||||
@staticmethod
|
||||
def _create_storeys(building, archetype, divide_in_storeys):
|
||||
building.average_storey_height = archetype.average_storey_height
|
||||
building.storeys_above_ground = 1
|
||||
thermal_zones = StoreysGeneration(building, building.internal_zones[0],
|
||||
divide_in_storeys=divide_in_storeys).thermal_zones
|
||||
building.internal_zones[0].thermal_zones = thermal_zones
|
|
@ -3,19 +3,29 @@ ConstructionFactory (before PhysicsFactory) retrieve the specific construction m
|
|||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
||||
Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
from hub.imports.construction.us_physics_parameters import UsPhysicsParameters
|
||||
from hub.hub_logger import logger
|
||||
from hub.helpers.utils import validate_import_export_type
|
||||
from hub.imports.construction.nrel_physics_parameters import NrelPhysicsParameters
|
||||
from hub.imports.construction.nrcan_physics_parameters import NrcanPhysicsParameters
|
||||
|
||||
|
||||
class ConstructionFactory:
|
||||
"""
|
||||
PhysicsFactor class
|
||||
ConstructionFactory class
|
||||
"""
|
||||
def __init__(self, handler, city, base_path=None):
|
||||
if base_path is None:
|
||||
base_path = Path(Path(__file__).parent.parent / 'data/construction')
|
||||
self._handler = '_' + handler.lower().replace(' ', '_')
|
||||
class_funcs = validate_import_export_type(ConstructionFactory)
|
||||
if self._handler not in class_funcs:
|
||||
err_msg = f"Wrong import type [{self._handler}]. Valid functions include {class_funcs}"
|
||||
logger.error(err_msg)
|
||||
raise Exception(err_msg)
|
||||
self._city = city
|
||||
self._base_path = base_path
|
||||
|
||||
|
@ -23,7 +33,14 @@ class ConstructionFactory:
|
|||
"""
|
||||
Enrich the city by using NREL information
|
||||
"""
|
||||
UsPhysicsParameters(self._city, self._base_path).enrich_buildings()
|
||||
NrelPhysicsParameters(self._city, self._base_path).enrich_buildings()
|
||||
self._city.level_of_detail.construction = 2
|
||||
|
||||
def _nrcan(self):
|
||||
"""
|
||||
Enrich the city by using NRCAN information
|
||||
"""
|
||||
NrcanPhysicsParameters(self._city, self._base_path).enrich_buildings()
|
||||
self._city.level_of_detail.construction = 2
|
||||
|
||||
def enrich(self):
|
||||
|
@ -38,4 +55,4 @@ class ConstructionFactory:
|
|||
Enrich the city given to the class using the class given handler
|
||||
:return: None
|
||||
"""
|
||||
UsPhysicsParameters(self._city, self._base_path).enrich_buildings()
|
||||
NrelPhysicsParameters(self._city, self._base_path).enrich_buildings()
|
||||
|
|
|
@ -4,10 +4,9 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
|
|||
Copyright © 2022 Concordia CERC group
|
||||
Project CoderPeter Yefi peteryefi@gmail.com
|
||||
"""
|
||||
from hub.persistence import CityRepo
|
||||
from hub.persistence import HeatPumpSimulationRepo
|
||||
from typing import Dict
|
||||
from hub.city_model_structure.city import City
|
||||
from hub.persistence import City as CityRepository
|
||||
from hub.persistence import SimulationResults
|
||||
|
||||
|
||||
class DBFactory:
|
||||
|
@ -16,14 +15,18 @@ class DBFactory:
|
|||
"""
|
||||
|
||||
def __init__(self, db_name, dotenv_path, app_env):
|
||||
self._city_repo = CityRepo(db_name=db_name, dotenv_path=dotenv_path, app_env=app_env)
|
||||
self._hp_simulation_repo = HeatPumpSimulationRepo(db_name=db_name, dotenv_path=dotenv_path, app_env=app_env)
|
||||
self._city_repository = CityRepository(db_name=db_name, dotenv_path=dotenv_path, app_env=app_env)
|
||||
self._simulation_results = SimulationResults(db_name=db_name, dotenv_path=dotenv_path, app_env=app_env)
|
||||
|
||||
def persist_city(self, user_id: int, city: City):
|
||||
def persist_city(self, city: City, pickle_path, application_id: int, user_id: int):
|
||||
"""
|
||||
Persist city into postgres database
|
||||
:param city: City to be stored
|
||||
:param pickle_path: Path to save the pickle file
|
||||
:param application_id: Application id owning this city
|
||||
:param user_id: User who create the city
|
||||
"""
|
||||
return self._city_repo.insert(city, user_id)
|
||||
return self._city_repository.insert(city, pickle_path, application_id, user_id)
|
||||
|
||||
def update_city(self, city_id, city):
|
||||
"""
|
||||
|
@ -31,27 +34,21 @@ class DBFactory:
|
|||
:param city_id: the id of the city to update
|
||||
:param city: the updated city object
|
||||
"""
|
||||
return self._city_repo.update(city_id, city)
|
||||
return self._city_repository.update(city_id, city)
|
||||
|
||||
def delete_city(self, city_id):
|
||||
"""
|
||||
Deletes a single city from postgres
|
||||
:param city_id: the id of the city to get
|
||||
"""
|
||||
self._city_repo.delete_city(city_id)
|
||||
self._city_repository.delete(city_id)
|
||||
|
||||
def persist_hp_simulation(self, hp_simulation_data: Dict, city_id: int):
|
||||
def add_simulation_results(self, name, values, city_id=None, city_object_id=None):
|
||||
"""
|
||||
Persist heat pump simulation results
|
||||
:param hp_simulation_data: the simulation results
|
||||
:param city_id: the city object used in running the simulation
|
||||
:return: HeatPumpSimulation object
|
||||
Add simulation results to the city or to the city_object
|
||||
:param name: simulation and simulation engine name
|
||||
:param values: simulation values in json format
|
||||
:param city_id: city id or None
|
||||
:param city_object_id: city object id or None
|
||||
"""
|
||||
return self._hp_simulation_repo.insert(hp_simulation_data, city_id)
|
||||
|
||||
def delete_hp_simulation(self, hp_sim_id):
|
||||
"""
|
||||
Deletes a single heat pump simulation from postgres
|
||||
:param hp_sim_id: the id of the heat pump simulation to get
|
||||
"""
|
||||
self._hp_simulation_repo.delete_hp_simulation(hp_sim_id)
|
||||
self._simulation_results.insert(name, values,city_id, city_object_id)
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
AirSourceHeatPumpParameters import the heat pump information
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Peter Yefi peteryefi@gmail.comCode contributor Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
Project Coder Peter Yefi peteryefi@gmail.comCode
|
||||
contributor Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
|
||||
import pandas as pd
|
||||
|
@ -41,7 +42,7 @@ class AirSourceHeatPumpParameters:
|
|||
for sheet, dataframe in heat_pump_dfs.items():
|
||||
|
||||
if 'Summary' in sheet:
|
||||
continue
|
||||
continue
|
||||
|
||||
# Remove nan rows and columns and extract cooling and heating data
|
||||
# for each sheet
|
||||
|
@ -69,8 +70,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), (k_heat, 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)
|
||||
|
@ -87,7 +87,8 @@ class AirSourceHeatPumpParameters:
|
|||
self._city.add_city_object(energy_system)
|
||||
return self._city
|
||||
|
||||
def _extract_heat_pump_data(self, heat_pump_capacity_data: Dict) -> [List, List]:
|
||||
@staticmethod
|
||||
def _extract_heat_pump_data(heat_pump_capacity_data: Dict) -> [List, List]:
|
||||
"""
|
||||
Fetches a list of metric based data for heat pump for various temperature,
|
||||
eg. cooling capacity data for 12 capacity heat pump
|
||||
|
@ -123,15 +124,16 @@ class AirSourceHeatPumpParameters:
|
|||
x_values = x_values.tolist()
|
||||
# convert list of lists to one list
|
||||
|
||||
hp_data = [i/j for i, j in
|
||||
zip(list(itertools.chain.from_iterable(heat_pump_data[0])),
|
||||
list(itertools.chain.from_iterable(heat_pump_data[1])))]
|
||||
hp_data = [i / j for i, j in
|
||||
zip(list(itertools.chain.from_iterable(heat_pump_data[0])),
|
||||
list(itertools.chain.from_iterable(heat_pump_data[1])))]
|
||||
|
||||
# Compute heat output coefficients
|
||||
popt, _ = curve_fit(self._objective_function, [x_values, out_temp], hp_data)
|
||||
return popt.tolist()
|
||||
|
||||
def _objective_function(self, xdata: List, a1: float, a2: float, a3: float, a4: float, a5: float, a6: float) -> float:
|
||||
@staticmethod
|
||||
def _objective_function(xdata: List, a1: float, a2: float, a3: float, a4: float, a5: float, a6: float) -> float:
|
||||
"""
|
||||
Objective function for computing coefficients
|
||||
:param xdata:
|
||||
|
|
|
@ -71,7 +71,8 @@ class WaterToWaterHPParameters:
|
|||
# range values for extracting data
|
||||
return data
|
||||
|
||||
def _extract_hp_data(self, df, columns, ranges):
|
||||
@staticmethod
|
||||
def _extract_hp_data(df, columns, ranges):
|
||||
"""
|
||||
Extract variable specific (LWT, PD or TC) data from water to water hp
|
||||
:param df: the dataframe
|
||||
|
@ -88,7 +89,8 @@ class WaterToWaterHPParameters:
|
|||
|
||||
return data.dropna().values.tolist()
|
||||
|
||||
def _extract_flow_and_ewt(self, df, ranges, columns, flow_rates):
|
||||
@staticmethod
|
||||
def _extract_flow_and_ewt(df, ranges, columns, flow_rates):
|
||||
"""
|
||||
Create the flow and ewt data based on the length of the various
|
||||
columns for the variables being extracted
|
||||
|
@ -148,7 +150,8 @@ class WaterToWaterHPParameters:
|
|||
demand)
|
||||
return popt.tolist()
|
||||
|
||||
def _objective_function(self, xdata: List, a1: float, a2: float, a3: float, a4: float, a5: float, a6: float,
|
||||
@staticmethod
|
||||
def _objective_function(xdata: List, a1: float, a2: float, a3: float, a4: float, a5: float, a6: float,
|
||||
a7: float, a8: float, a9: float, a10: float, a11: float) -> float:
|
||||
"""
|
||||
Objective function for computing coefficients
|
||||
|
@ -169,4 +172,3 @@ class WaterToWaterHPParameters:
|
|||
x, y, t = xdata
|
||||
return (a1 * x ** 2) + (a2 * x) + (a3 * y ** 2) + (a4 * y) + (a5 * t ** 2) + (a6 * t) + (a7 * x * y) + (
|
||||
a8 * x * t) + (a9 * y * t) + (a10 * x * y * t) + a11
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@ Code contributors: Peter Yefi peteryefi@gmail.com
|
|||
from pathlib import Path
|
||||
from hub.imports.energy_systems.air_source_hp_parameters import AirSourceHeatPumpParameters
|
||||
from hub.imports.energy_systems.water_to_water_hp_parameters import WaterToWaterHPParameters
|
||||
from hub.helpers.utils import validate_import_export_type
|
||||
from hub.hub_logger import logger
|
||||
|
||||
|
||||
class EnergySystemsFactory:
|
||||
|
@ -19,6 +21,11 @@ class EnergySystemsFactory:
|
|||
if base_path is None:
|
||||
base_path = Path(Path(__file__).parent.parent / 'data/energy_systems')
|
||||
self._handler = '_' + handler.lower().replace(' ', '_')
|
||||
class_funcs = validate_import_export_type(EnergySystemsFactory)
|
||||
if self._handler not in class_funcs:
|
||||
err_msg = f"Wrong import type. Valid functions include {class_funcs}"
|
||||
logger.error(err_msg)
|
||||
raise Exception(err_msg)
|
||||
self._city = city
|
||||
self._base_path = base_path
|
||||
|
||||
|
|
|
@ -7,26 +7,35 @@ Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
|||
|
||||
import numpy as np
|
||||
import xmltodict
|
||||
from hub.city_model_structure.city import City
|
||||
|
||||
from hub.city_model_structure.building import Building
|
||||
from hub.city_model_structure.city import City
|
||||
from hub.city_model_structure.parts_consisting_building import PartsConsistingBuilding
|
||||
from hub.helpers.geometry_helper import GeometryHelper
|
||||
from hub.imports.geometry.citygml_classes.citygml_lod2 import CityGmlLod2
|
||||
from hub.imports.geometry.citygml_classes.citygml_lod1 import CityGmlLod1
|
||||
from hub.imports.geometry.citygml_classes.citygml_lod2 import CityGmlLod2
|
||||
|
||||
|
||||
class CityGml:
|
||||
"""
|
||||
CityGml class
|
||||
"""
|
||||
def __init__(self, path, extrusion_height_field=None, year_of_construction_field=None, function_field=None):
|
||||
def __init__(self,
|
||||
path,
|
||||
extrusion_height_field=None,
|
||||
year_of_construction_field='yearOfConstruction',
|
||||
function_field='function',
|
||||
function_to_hub=None):
|
||||
self._city = None
|
||||
self._lod = None
|
||||
self._lod1_tags = ['lod1Solid', 'lod1MultiSurface']
|
||||
self._lod2_tags = ['lod2Solid', 'lod2MultiSurface', 'lod2MultiCurve']
|
||||
self._extrusion_height_field = extrusion_height_field
|
||||
self._function_to_hub = function_to_hub
|
||||
self._year_of_construction_field = year_of_construction_field
|
||||
if function_field is None:
|
||||
function_field = 'function'
|
||||
self._function_field = function_field
|
||||
|
||||
self._lower_corner = None
|
||||
self._upper_corner = None
|
||||
with open(path) as gml:
|
||||
|
@ -54,7 +63,6 @@ class CityGml:
|
|||
}, force_list=force_list)
|
||||
|
||||
self._city_objects = None
|
||||
self._geometry = GeometryHelper()
|
||||
if 'boundedBy' in self._gml['CityModel']:
|
||||
for bound in self._gml['CityModel']['boundedBy']:
|
||||
envelope = bound['Envelope']
|
||||
|
@ -108,10 +116,16 @@ class CityGml:
|
|||
name = city_object['@id']
|
||||
function = None
|
||||
year_of_construction = None
|
||||
if 'yearOfConstruction' in city_object:
|
||||
year_of_construction = city_object['yearOfConstruction']
|
||||
if 'function' in city_object:
|
||||
function = city_object['function']
|
||||
if self._year_of_construction_field in city_object:
|
||||
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:
|
||||
function = function['#text']
|
||||
if self._function_to_hub is not None:
|
||||
# use the transformation dictionary to retrieve the proper function
|
||||
function = self._function_to_hub[function]
|
||||
|
||||
if any(key in city_object for key in self._lod1_tags):
|
||||
if self._lod is None or self._lod > 1:
|
||||
self._lod = 1
|
||||
|
|
|
@ -26,7 +26,12 @@ class Geojson:
|
|||
X = 0
|
||||
Y = 1
|
||||
|
||||
def __init__(self, path, extrusion_height_field=None, year_of_construction_field=None, function_field=None):
|
||||
def __init__(self,
|
||||
path,
|
||||
extrusion_height_field=None,
|
||||
year_of_construction_field=None,
|
||||
function_field=None,
|
||||
function_to_hub=None):
|
||||
# todo: destination epsg should change according actual the location
|
||||
self._transformer = Transformer.from_crs('epsg:4326', 'epsg:26911')
|
||||
self._min_x = cte.MAX_FLOAT
|
||||
|
@ -38,6 +43,7 @@ class Geojson:
|
|||
self._extrusion_height_field = extrusion_height_field
|
||||
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:
|
||||
self._geojson = json.loads(json_file.read())
|
||||
|
||||
|
@ -118,6 +124,9 @@ class Geojson:
|
|||
function = None
|
||||
if self._function_field is not None:
|
||||
function = feature['properties'][self._function_field]
|
||||
if self._function_to_hub is not None:
|
||||
# use the transformation dictionary to retrieve the proper function
|
||||
function = self._function_to_hub[function]
|
||||
geometry = feature['geometry']
|
||||
if 'id' in feature:
|
||||
building_name = feature['id']
|
||||
|
@ -125,6 +134,7 @@ class Geojson:
|
|||
building_name = f'building_{building_id}'
|
||||
building_id += 1
|
||||
polygons = []
|
||||
lod = 1
|
||||
for part, coordinates in enumerate(geometry['coordinates']):
|
||||
polygons = self._get_polygons(polygons, coordinates)
|
||||
for zone, polygon in enumerate(polygons):
|
||||
|
@ -133,6 +143,7 @@ class Geojson:
|
|||
year_of_construction,
|
||||
function,
|
||||
[polygon])
|
||||
lod = 0
|
||||
else:
|
||||
if self._max_z < extrusion_height:
|
||||
self._max_z = extrusion_height
|
||||
|
@ -145,4 +156,5 @@ class Geojson:
|
|||
self._city = City([self._min_x, self._min_y, 0.0], [self._max_x, self._max_y, self._max_z], 'epsg:26911')
|
||||
for building in buildings:
|
||||
self._city.add_city_object(building)
|
||||
self._city.level_of_detail.geometry = lod
|
||||
return self._city
|
||||
|
|
|
@ -57,6 +57,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():
|
||||
polygon = bldg.geometry
|
||||
height = float(bldg['height'])
|
||||
|
|
|
@ -5,7 +5,6 @@ Copyright © 2022 Concordia CERC group
|
|||
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
|
||||
import hub.helpers.constants as cte
|
||||
import numpy as np
|
||||
|
||||
|
||||
|
@ -13,276 +12,6 @@ class GeometryHelper:
|
|||
"""
|
||||
Geometry helper
|
||||
"""
|
||||
# function
|
||||
_pluto_to_function = {
|
||||
'A0': cte.SINGLE_FAMILY_HOUSE,
|
||||
'A1': cte.SINGLE_FAMILY_HOUSE,
|
||||
'A2': cte.SINGLE_FAMILY_HOUSE,
|
||||
'A3': cte.SINGLE_FAMILY_HOUSE,
|
||||
'A4': cte.SINGLE_FAMILY_HOUSE,
|
||||
'A5': cte.SINGLE_FAMILY_HOUSE,
|
||||
'A6': cte.SINGLE_FAMILY_HOUSE,
|
||||
'A7': cte.SINGLE_FAMILY_HOUSE,
|
||||
'A8': cte.SINGLE_FAMILY_HOUSE,
|
||||
'A9': cte.SINGLE_FAMILY_HOUSE,
|
||||
'B1': cte.MULTI_FAMILY_HOUSE,
|
||||
'B2': cte.MULTI_FAMILY_HOUSE,
|
||||
'B3': cte.MULTI_FAMILY_HOUSE,
|
||||
'B9': cte.MULTI_FAMILY_HOUSE,
|
||||
'C0': cte.RESIDENTIAL,
|
||||
'C1': cte.RESIDENTIAL,
|
||||
'C2': cte.RESIDENTIAL,
|
||||
'C3': cte.RESIDENTIAL,
|
||||
'C4': cte.RESIDENTIAL,
|
||||
'C5': cte.RESIDENTIAL,
|
||||
'C6': cte.RESIDENTIAL,
|
||||
'C7': cte.RESIDENTIAL,
|
||||
'C8': cte.RESIDENTIAL,
|
||||
'C9': cte.RESIDENTIAL,
|
||||
'D0': cte.RESIDENTIAL,
|
||||
'D1': cte.RESIDENTIAL,
|
||||
'D2': cte.RESIDENTIAL,
|
||||
'D3': cte.RESIDENTIAL,
|
||||
'D4': cte.RESIDENTIAL,
|
||||
'D5': cte.RESIDENTIAL,
|
||||
'D6': cte.RESIDENTIAL,
|
||||
'D7': cte.RESIDENTIAL,
|
||||
'D8': cte.RESIDENTIAL,
|
||||
'D9': cte.RESIDENTIAL,
|
||||
'E1': cte.WAREHOUSE,
|
||||
'E3': cte.WAREHOUSE,
|
||||
'E4': cte.WAREHOUSE,
|
||||
'E5': cte.WAREHOUSE,
|
||||
'E7': cte.WAREHOUSE,
|
||||
'E9': cte.WAREHOUSE,
|
||||
'F1': cte.WAREHOUSE,
|
||||
'F2': cte.WAREHOUSE,
|
||||
'F4': cte.WAREHOUSE,
|
||||
'F5': cte.WAREHOUSE,
|
||||
'F8': cte.WAREHOUSE,
|
||||
'F9': cte.WAREHOUSE,
|
||||
'G0': cte.SMALL_OFFICE,
|
||||
'G1': cte.SMALL_OFFICE,
|
||||
'G2': cte.SMALL_OFFICE,
|
||||
'G3': cte.SMALL_OFFICE,
|
||||
'G4': cte.SMALL_OFFICE,
|
||||
'G5': cte.SMALL_OFFICE,
|
||||
'G6': cte.SMALL_OFFICE,
|
||||
'G7': cte.SMALL_OFFICE,
|
||||
'G8': cte.SMALL_OFFICE,
|
||||
'G9': cte.SMALL_OFFICE,
|
||||
'H1': cte.HOTEL,
|
||||
'H2': cte.HOTEL,
|
||||
'H3': cte.HOTEL,
|
||||
'H4': cte.HOTEL,
|
||||
'H5': cte.HOTEL,
|
||||
'H6': cte.HOTEL,
|
||||
'H7': cte.HOTEL,
|
||||
'H8': cte.HOTEL,
|
||||
'H9': cte.HOTEL,
|
||||
'HB': cte.HOTEL,
|
||||
'HH': cte.HOTEL,
|
||||
'HR': cte.HOTEL,
|
||||
'HS': cte.HOTEL,
|
||||
'I1': cte.HOSPITAL,
|
||||
'I2': cte.OUT_PATIENT_HEALTH_CARE,
|
||||
'I3': cte.OUT_PATIENT_HEALTH_CARE,
|
||||
'I4': cte.RESIDENTIAL,
|
||||
'I5': cte.OUT_PATIENT_HEALTH_CARE,
|
||||
'I6': cte.OUT_PATIENT_HEALTH_CARE,
|
||||
'I7': cte.OUT_PATIENT_HEALTH_CARE,
|
||||
'I9': cte.OUT_PATIENT_HEALTH_CARE,
|
||||
'J1': cte.LARGE_OFFICE,
|
||||
'J2': cte.LARGE_OFFICE,
|
||||
'J3': cte.LARGE_OFFICE,
|
||||
'J4': cte.LARGE_OFFICE,
|
||||
'J5': cte.LARGE_OFFICE,
|
||||
'J6': cte.LARGE_OFFICE,
|
||||
'J7': cte.LARGE_OFFICE,
|
||||
'J8': cte.LARGE_OFFICE,
|
||||
'J9': cte.LARGE_OFFICE,
|
||||
'K1': cte.STRIP_MALL,
|
||||
'K2': cte.STRIP_MALL,
|
||||
'K3': cte.STRIP_MALL,
|
||||
'K4': cte.RESIDENTIAL,
|
||||
'K5': cte.RESTAURANT,
|
||||
'K6': cte.SUPERMARKET,
|
||||
'K7': cte.SUPERMARKET,
|
||||
'K8': cte.SUPERMARKET,
|
||||
'K9': cte.SUPERMARKET,
|
||||
'L1': cte.RESIDENTIAL,
|
||||
'L2': cte.RESIDENTIAL,
|
||||
'L3': cte.RESIDENTIAL,
|
||||
'L8': cte.RESIDENTIAL,
|
||||
'L9': cte.RESIDENTIAL,
|
||||
'M1': cte.LARGE_OFFICE,
|
||||
'M2': cte.LARGE_OFFICE,
|
||||
'M3': cte.LARGE_OFFICE,
|
||||
'M4': cte.LARGE_OFFICE,
|
||||
'M9': cte.LARGE_OFFICE,
|
||||
'N1': cte.RESIDENTIAL,
|
||||
'N2': cte.RESIDENTIAL,
|
||||
'N3': cte.RESIDENTIAL,
|
||||
'N4': cte.RESIDENTIAL,
|
||||
'N9': cte.RESIDENTIAL,
|
||||
'O1': cte.SMALL_OFFICE,
|
||||
'O2': cte.SMALL_OFFICE,
|
||||
'O3': cte.SMALL_OFFICE,
|
||||
'O4': cte.SMALL_OFFICE,
|
||||
'O5': cte.SMALL_OFFICE,
|
||||
'O6': cte.SMALL_OFFICE,
|
||||
'O7': cte.SMALL_OFFICE,
|
||||
'O8': cte.SMALL_OFFICE,
|
||||
'O9': cte.SMALL_OFFICE,
|
||||
'P1': cte.LARGE_OFFICE,
|
||||
'P2': cte.HOTEL,
|
||||
'P3': cte.SMALL_OFFICE,
|
||||
'P4': cte.SMALL_OFFICE,
|
||||
'P5': cte.SMALL_OFFICE,
|
||||
'P6': cte.SMALL_OFFICE,
|
||||
'P7': cte.LARGE_OFFICE,
|
||||
'P8': cte.LARGE_OFFICE,
|
||||
'P9': cte.SMALL_OFFICE,
|
||||
'Q0': cte.SMALL_OFFICE,
|
||||
'Q1': cte.SMALL_OFFICE,
|
||||
'Q2': cte.SMALL_OFFICE,
|
||||
'Q3': cte.SMALL_OFFICE,
|
||||
'Q4': cte.SMALL_OFFICE,
|
||||
'Q5': cte.SMALL_OFFICE,
|
||||
'Q6': cte.SMALL_OFFICE,
|
||||
'Q7': cte.SMALL_OFFICE,
|
||||
'Q8': cte.SMALL_OFFICE,
|
||||
'Q9': cte.SMALL_OFFICE,
|
||||
'R0': cte.RESIDENTIAL,
|
||||
'R1': cte.RESIDENTIAL,
|
||||
'R2': cte.RESIDENTIAL,
|
||||
'R3': cte.RESIDENTIAL,
|
||||
'R4': cte.RESIDENTIAL,
|
||||
'R5': cte.RESIDENTIAL,
|
||||
'R6': cte.RESIDENTIAL,
|
||||
'R7': cte.RESIDENTIAL,
|
||||
'R8': cte.RESIDENTIAL,
|
||||
'R9': cte.RESIDENTIAL,
|
||||
'RA': cte.RESIDENTIAL,
|
||||
'RB': cte.RESIDENTIAL,
|
||||
'RC': cte.RESIDENTIAL,
|
||||
'RD': cte.RESIDENTIAL,
|
||||
'RG': cte.RESIDENTIAL,
|
||||
'RH': cte.RESIDENTIAL,
|
||||
'RI': cte.RESIDENTIAL,
|
||||
'RK': cte.RESIDENTIAL,
|
||||
'RM': cte.RESIDENTIAL,
|
||||
'RR': cte.RESIDENTIAL,
|
||||
'RS': cte.RESIDENTIAL,
|
||||
'RW': cte.RESIDENTIAL,
|
||||
'RX': cte.RESIDENTIAL,
|
||||
'RZ': cte.RESIDENTIAL,
|
||||
'S0': cte.RESIDENTIAL,
|
||||
'S1': cte.RESIDENTIAL,
|
||||
'S2': cte.RESIDENTIAL,
|
||||
'S3': cte.RESIDENTIAL,
|
||||
'S4': cte.RESIDENTIAL,
|
||||
'S5': cte.RESIDENTIAL,
|
||||
'S9': cte.RESIDENTIAL,
|
||||
'U0': cte.WAREHOUSE,
|
||||
'U1': cte.WAREHOUSE,
|
||||
'U2': cte.WAREHOUSE,
|
||||
'U3': cte.WAREHOUSE,
|
||||
'U4': cte.WAREHOUSE,
|
||||
'U5': cte.WAREHOUSE,
|
||||
'U6': cte.WAREHOUSE,
|
||||
'U7': cte.WAREHOUSE,
|
||||
'U8': cte.WAREHOUSE,
|
||||
'U9': cte.WAREHOUSE,
|
||||
'W1': cte.PRIMARY_SCHOOL,
|
||||
'W2': cte.PRIMARY_SCHOOL,
|
||||
'W3': cte.SECONDARY_SCHOOL,
|
||||
'W4': cte.SECONDARY_SCHOOL,
|
||||
'W5': cte.SECONDARY_SCHOOL,
|
||||
'W6': cte.SECONDARY_SCHOOL,
|
||||
'W7': cte.SECONDARY_SCHOOL,
|
||||
'W8': cte.PRIMARY_SCHOOL,
|
||||
'W9': cte.SECONDARY_SCHOOL,
|
||||
'Y1': cte.LARGE_OFFICE,
|
||||
'Y2': cte.LARGE_OFFICE,
|
||||
'Y3': cte.LARGE_OFFICE,
|
||||
'Y4': cte.LARGE_OFFICE,
|
||||
'Y5': cte.LARGE_OFFICE,
|
||||
'Y6': cte.LARGE_OFFICE,
|
||||
'Y7': cte.LARGE_OFFICE,
|
||||
'Y8': cte.LARGE_OFFICE,
|
||||
'Y9': cte.LARGE_OFFICE,
|
||||
'Z1': cte.LARGE_OFFICE
|
||||
}
|
||||
_hft_to_function = {
|
||||
'residential': cte.RESIDENTIAL,
|
||||
'single family house': cte.SINGLE_FAMILY_HOUSE,
|
||||
'multifamily house': cte.MULTI_FAMILY_HOUSE,
|
||||
'hotel': cte.HOTEL,
|
||||
'hospital': cte.HOSPITAL,
|
||||
'outpatient': cte.OUT_PATIENT_HEALTH_CARE,
|
||||
'commercial': cte.SUPERMARKET,
|
||||
'strip mall': cte.STRIP_MALL,
|
||||
'warehouse': cte.WAREHOUSE,
|
||||
'primary school': cte.PRIMARY_SCHOOL,
|
||||
'secondary school': cte.SECONDARY_SCHOOL,
|
||||
'office': cte.MEDIUM_OFFICE,
|
||||
'large office': cte.LARGE_OFFICE
|
||||
}
|
||||
|
||||
# usage
|
||||
_function_to_usage = {
|
||||
cte.RESIDENTIAL: cte.RESIDENTIAL,
|
||||
cte.SINGLE_FAMILY_HOUSE: cte.SINGLE_FAMILY_HOUSE,
|
||||
cte.MULTI_FAMILY_HOUSE: cte.MULTI_FAMILY_HOUSE,
|
||||
cte.ROW_HOSE: cte.RESIDENTIAL,
|
||||
cte.MID_RISE_APARTMENT: cte.RESIDENTIAL,
|
||||
cte.HIGH_RISE_APARTMENT: cte.RESIDENTIAL,
|
||||
cte.SMALL_OFFICE: cte.OFFICE_AND_ADMINISTRATION,
|
||||
cte.MEDIUM_OFFICE: cte.OFFICE_AND_ADMINISTRATION,
|
||||
cte.LARGE_OFFICE: cte.OFFICE_AND_ADMINISTRATION,
|
||||
cte.PRIMARY_SCHOOL: cte.EDUCATION,
|
||||
cte.SECONDARY_SCHOOL: cte.EDUCATION,
|
||||
cte.STAND_ALONE_RETAIL: cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
cte.HOSPITAL: cte.HEALTH_CARE,
|
||||
cte.OUT_PATIENT_HEALTH_CARE: cte.HEALTH_CARE,
|
||||
cte.STRIP_MALL: cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
cte.SUPERMARKET: cte.RETAIL_SHOP_WITH_REFRIGERATED_FOOD,
|
||||
cte.WAREHOUSE: cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD,
|
||||
cte.QUICK_SERVICE_RESTAURANT: cte.RESTAURANT,
|
||||
cte.FULL_SERVICE_RESTAURANT: cte.RESTAURANT,
|
||||
cte.SMALL_HOTEL: cte.HOTEL,
|
||||
cte.LARGE_HOTEL: cte.HOTEL,
|
||||
cte.INDUSTRY:cte.INDUSTRY
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def libs_function_from_hft(building_hft_function):
|
||||
"""
|
||||
Get internal function from the given HfT function
|
||||
:param building_hft_function: str
|
||||
:return: str
|
||||
"""
|
||||
return GeometryHelper._hft_to_function[building_hft_function]
|
||||
|
||||
@staticmethod
|
||||
def libs_function_from_pluto(building_pluto_function):
|
||||
"""
|
||||
Get internal function from the given pluto function
|
||||
:param building_pluto_function: str
|
||||
:return: str
|
||||
"""
|
||||
return GeometryHelper._pluto_to_function[building_pluto_function]
|
||||
|
||||
@staticmethod
|
||||
def libs_usage_from_libs_function(building_function):
|
||||
"""
|
||||
Get the internal usage for the given internal building function
|
||||
:param building_function: str
|
||||
:return: str
|
||||
"""
|
||||
return GeometryHelper._function_to_usage[building_function]
|
||||
|
||||
@staticmethod
|
||||
def to_points_matrix(points):
|
||||
"""
|
||||
|
|
|
@ -51,6 +51,7 @@ class Obj:
|
|||
"""
|
||||
Get city out of an obj file
|
||||
"""
|
||||
lod = 0
|
||||
if self._city is None:
|
||||
# todo: refactor this method to clearly choose the obj type
|
||||
# todo: where do we get this information from?
|
||||
|
|
|
@ -1,58 +0,0 @@
|
|||
"""
|
||||
OsmSubway module parses osm files and import the metro location into the city model structure
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
||||
"""
|
||||
|
||||
import sys
|
||||
import xmltodict
|
||||
from pyproj import Transformer
|
||||
from hub.city_model_structure.city import City
|
||||
from hub.city_model_structure.subway_entrance import SubwayEntrance
|
||||
|
||||
|
||||
class OsmSubway:
|
||||
"""
|
||||
Open street map subway
|
||||
"""
|
||||
def __init__(self, path):
|
||||
self._city = None
|
||||
self._subway_entrances = []
|
||||
with open(path) as osm:
|
||||
self._osm = xmltodict.parse(osm.read(), force_list='tag')
|
||||
for node in self._osm['osm']['node']:
|
||||
if 'tag' not in node:
|
||||
continue
|
||||
for tag in node['tag']:
|
||||
if '@v' not in tag:
|
||||
continue
|
||||
if tag['@v'] == 'subway_entrance':
|
||||
subway_entrance = SubwayEntrance(node['@id'], node['@lat'], node['@lon'])
|
||||
self._subway_entrances.append(subway_entrance)
|
||||
|
||||
@property
|
||||
def city(self) -> City:
|
||||
"""
|
||||
Get a city with subway entrances
|
||||
"""
|
||||
transformer = Transformer.from_crs("EPSG:4326", "EPSG:3857")
|
||||
lower_corner = [sys.float_info.max, sys.float_info.max, 0]
|
||||
upper_corner = [sys.float_info.min, sys.float_info.min, 0]
|
||||
x = 0
|
||||
y = 1
|
||||
for subway_entrance in self._subway_entrances:
|
||||
coordinate = transformer.transform(subway_entrance.longitude, subway_entrance.latitude)
|
||||
if coordinate[x] >= upper_corner[x]:
|
||||
upper_corner[x] = coordinate[x]
|
||||
if coordinate[y] >= upper_corner[y]:
|
||||
upper_corner[y] = coordinate[y]
|
||||
if coordinate[x] < lower_corner[x]:
|
||||
lower_corner[x] = coordinate[x]
|
||||
if coordinate[y] < lower_corner[y]:
|
||||
lower_corner[y] = coordinate[y]
|
||||
|
||||
city = City(lower_corner, upper_corner, 'unknown')
|
||||
for subway_entrance in self._subway_entrances:
|
||||
city.add_city_object(subway_entrance)
|
||||
return city
|
|
@ -9,10 +9,11 @@ import geopandas
|
|||
from hub.city_model_structure.city import City
|
||||
from hub.imports.geometry.citygml import CityGml
|
||||
from hub.imports.geometry.obj import Obj
|
||||
from hub.imports.geometry.osm_subway import OsmSubway
|
||||
from hub.imports.geometry.rhino import Rhino
|
||||
from hub.imports.geometry.gpandas import GPandas
|
||||
from hub.imports.geometry.geojson import Geojson
|
||||
from hub.helpers.utils import validate_import_export_type
|
||||
from hub.hub_logger import logger
|
||||
|
||||
|
||||
class GeometryFactory:
|
||||
|
@ -24,13 +25,20 @@ class GeometryFactory:
|
|||
data_frame=None,
|
||||
height_field=None,
|
||||
year_of_construction_field=None,
|
||||
function_field=None):
|
||||
function_field=None,
|
||||
function_to_hub=None):
|
||||
self._file_type = '_' + file_type.lower()
|
||||
class_funcs = validate_import_export_type(GeometryFactory)
|
||||
if self._file_type not in class_funcs:
|
||||
err_msg = f"Wrong import type. Valid functions include {class_funcs}"
|
||||
logger.error(err_msg)
|
||||
raise Exception(err_msg)
|
||||
self._path = path
|
||||
self._data_frame = data_frame
|
||||
self._height_field = height_field
|
||||
self._year_of_construction_field = year_of_construction_field
|
||||
self._function_field = function_field
|
||||
self._function_to_hub = function_to_hub
|
||||
|
||||
@property
|
||||
def _citygml(self) -> City:
|
||||
|
@ -38,7 +46,11 @@ class GeometryFactory:
|
|||
Enrich the city by using CityGML information as data source
|
||||
:return: City
|
||||
"""
|
||||
return CityGml(self._path, self._height_field, self._year_of_construction_field, self._function_field).city
|
||||
return CityGml(self._path,
|
||||
self._height_field,
|
||||
self._year_of_construction_field,
|
||||
self._function_field,
|
||||
self._function_to_hub).city
|
||||
|
||||
@property
|
||||
def _obj(self) -> City:
|
||||
|
@ -64,15 +76,11 @@ class GeometryFactory:
|
|||
Enrich the city by using Geojson information as data source
|
||||
:return: City
|
||||
"""
|
||||
return Geojson(self._path, self._height_field, self._year_of_construction_field, self._function_field).city
|
||||
|
||||
@property
|
||||
def _osm_subway(self) -> City:
|
||||
"""
|
||||
Enrich the city by using OpenStreetMap information as data source
|
||||
:return: City
|
||||
"""
|
||||
return OsmSubway(self._path).city
|
||||
return Geojson(self._path,
|
||||
self._height_field,
|
||||
self._year_of_construction_field,
|
||||
self._function_field,
|
||||
self._function_to_hub).city
|
||||
|
||||
@property
|
||||
def _rhino(self) -> City:
|
||||
|
|
|
@ -8,6 +8,7 @@ import xmltodict
|
|||
from pathlib import Path
|
||||
from hub.city_model_structure.machine import Machine
|
||||
|
||||
|
||||
class LcaMachine:
|
||||
def __init__(self, city, base_path):
|
||||
self._city = city
|
||||
|
@ -22,6 +23,8 @@ class LcaMachine:
|
|||
self._lca = xmltodict.parse(xml.read())
|
||||
for machine in self._lca["library"]["machines"]['machine']:
|
||||
self._city.machines.append(Machine(machine['@id'], machine['@name'], machine['work_efficiency']['#text'],
|
||||
machine['work_efficiency']['@unit'], machine['energy_consumption_rate']['#text'],
|
||||
machine['energy_consumption_rate']['@unit'], machine['carbon_emission_factor']['#text'],
|
||||
machine['carbon_emission_factor']['@unit']))
|
||||
machine['work_efficiency']['@unit'],
|
||||
machine['energy_consumption_rate']['#text'],
|
||||
machine['energy_consumption_rate']['@unit'],
|
||||
machine['carbon_emission_factor']['#text'],
|
||||
machine['carbon_emission_factor']['@unit']))
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user