Create new factory to import concordia energy files into the libs.

Minor cosmetic changes
This commit is contained in:
Guille Gutierrez 2021-06-01 18:31:50 -04:00
parent 4b7ae34985
commit 5ea6a0f125
47 changed files with 2415 additions and 102 deletions

View File

@ -0,0 +1,36 @@
"""
Energy Sensor module
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
"""
from city_model_structure.attributes.sensor import Sensor
import pandas as pd
class ConcordiaEnergySensor(Sensor):
"""
Concordia energy sensor.
"""
def __init__(self, name, measures):
super().__init__()
self._name = name
self._interval = 5
self._interval_units = 'minutes'
self._type = 'ConcordiaEnergySensor'
self._units = 'kW/h'
self._measures = measures
@property
def measures(self) -> pd.DataFrame:
return self._measures
@measures.deleter
def measures(self):
self._measures.drop = None
def add_period(self, period):
self._measures.append(period)

View File

@ -96,7 +96,7 @@ class Occupants:
@property @property
def occupant_schedule(self): def occupant_schedule(self):
""" """
Get the schedule when an occupant is in a zone (24 values, 1 per hour of the day) Get the schedules when an occupant is in a zone (24 values, 1 per hour of the day)
:return: [float] :return: [float]
""" """
return self._occupant_schedule return self._occupant_schedule
@ -104,7 +104,7 @@ class Occupants:
@occupant_schedule.setter @occupant_schedule.setter
def occupant_schedule(self, value): def occupant_schedule(self, value):
""" """
Set the schedule when an occupant is in a zone (24 values, 1 per hour of the day) Set the schedules when an occupant is in a zone (24 values, 1 per hour of the day)
:param value: [float] :param value: [float]
:return: :return:
""" """
@ -201,7 +201,7 @@ class Occupants:
def get_complete_year_schedule(self, schedules): def get_complete_year_schedule(self, schedules):
""" """
Get the a non-leap year (8760 h), starting on Monday schedule out of archetypal days of week Get the a non-leap year (8760 h), starting on Monday schedules out of archetypal days of week
:return: [float] :return: [float]
""" """
if self._complete_year_schedule is None: if self._complete_year_schedule is None:

View File

@ -22,6 +22,9 @@ class Polygon:
@property @property
def points(self) -> np.ndarray: def points(self) -> np.ndarray:
"""
List of points belonging to the polygon [[x, y, z],...]
"""
return self._points return self._points
@property @property

View File

@ -0,0 +1,60 @@
"""
Sensor module
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
"""
class Sensor:
def __init__(self):
self._name = None
self._type = None
self._units = None
self._location = None
@property
def name(self):
"""
Get sensor name
"""
return self._name
@name.setter
def name(self, value):
"""
Set sensor name
"""
self._name = value
@property
def type(self):
"""
Get sensor type
"""
return self._type
@property
def units(self):
"""
Get sensor units
"""
return self._units
@property
def location(self):
"""
Get sensor location
"""
return self._location
@location.setter
def location(self, value):
"""
Set sensor location
"""
self._location = value
@property
def measures(self):
raise NotImplementedError

View File

@ -207,7 +207,7 @@ class ThermalZone:
@property @property
def usage_zones(self) -> List[UsageZone]: def usage_zones(self) -> List[UsageZone]:
""" """
Get thermal zone usage zones Get thermal zone usages zones
:return: [UsageZone] :return: [UsageZone]
""" """
return self._usage_zones return self._usage_zones
@ -215,7 +215,7 @@ class ThermalZone:
@usage_zones.setter @usage_zones.setter
def usage_zones(self, values): def usage_zones(self, values):
""" """
Set thermal zone usage zones Set thermal zone usages zones
:param values: [UsageZone] :param values: [UsageZone]
:return: None :return: None
""" """

View File

@ -52,7 +52,7 @@ class UsageZone:
@property @property
def internal_gains(self) -> List[InternalGains]: def internal_gains(self) -> List[InternalGains]:
""" """
Get usage zone internal gains Get usages zone internal gains
:return: [InternalGains] :return: [InternalGains]
""" """
return self._internal_gains return self._internal_gains
@ -60,7 +60,7 @@ class UsageZone:
@internal_gains.setter @internal_gains.setter
def internal_gains(self, value): def internal_gains(self, value):
""" """
Set usage zone internal gains Set usages zone internal gains
:param value: [InternalGains] :param value: [InternalGains]
:return: None :return: None
""" """
@ -69,7 +69,7 @@ class UsageZone:
@property @property
def heating_setpoint(self): def heating_setpoint(self):
""" """
Get usage zone heating set point in celsius grads Get usages zone heating set point in celsius grads
:return: float :return: float
""" """
return self._heating_setpoint return self._heating_setpoint
@ -77,7 +77,7 @@ class UsageZone:
@heating_setpoint.setter @heating_setpoint.setter
def heating_setpoint(self, value): def heating_setpoint(self, value):
""" """
Set usage zone heating set point in celsius grads Set usages zone heating set point in celsius grads
:param value: float :param value: float
:return: None :return: None
""" """
@ -86,7 +86,7 @@ class UsageZone:
@property @property
def heating_setback(self): def heating_setback(self):
""" """
Get usage zone heating setback in celsius grads Get usages zone heating setback in celsius grads
:return: float :return: float
""" """
return self._heating_setback return self._heating_setback
@ -94,7 +94,7 @@ class UsageZone:
@heating_setback.setter @heating_setback.setter
def heating_setback(self, value): def heating_setback(self, value):
""" """
Set usage zone heating setback in celsius grads Set usages zone heating setback in celsius grads
:param value: float :param value: float
:return: None :return: None
""" """
@ -103,7 +103,7 @@ class UsageZone:
@property @property
def cooling_setpoint(self): def cooling_setpoint(self):
""" """
Get usage zone cooling setpoint in celsius grads Get usages zone cooling setpoint in celsius grads
:return: float :return: float
""" """
return self._cooling_setpoint return self._cooling_setpoint
@ -111,7 +111,7 @@ class UsageZone:
@cooling_setpoint.setter @cooling_setpoint.setter
def cooling_setpoint(self, value): def cooling_setpoint(self, value):
""" """
Set usage zone cooling setpoint in celsius grads Set usages zone cooling setpoint in celsius grads
:param value: float :param value: float
:return: None :return: None
""" """
@ -120,7 +120,7 @@ class UsageZone:
@property @property
def hours_day(self): def hours_day(self):
""" """
Get usage zone usage hours per day Get usages zone usages hours per day
:return: float :return: float
""" """
return self._hours_day return self._hours_day
@ -128,7 +128,7 @@ class UsageZone:
@hours_day.setter @hours_day.setter
def hours_day(self, value): def hours_day(self, value):
""" """
Set usage zone usage hours per day Set usages zone usages hours per day
:param value: float :param value: float
:return: float :return: float
""" """
@ -137,7 +137,7 @@ class UsageZone:
@property @property
def days_year(self): def days_year(self):
""" """
Get usage zone usage days per year Get usages zone usages days per year
:return: float :return: float
""" """
return self._days_year return self._days_year
@ -145,7 +145,7 @@ class UsageZone:
@days_year.setter @days_year.setter
def days_year(self, value): def days_year(self, value):
""" """
Set usage zone usage days per year Set usages zone usages days per year
:param value: float :param value: float
:return: None :return: None
""" """
@ -154,7 +154,7 @@ class UsageZone:
@property @property
def mechanical_air_change(self): def mechanical_air_change(self):
""" """
Set usage zone mechanical air change in air change per hour (ACH) Set usages zone mechanical air change in air change per hour (ACH)
:return: float :return: float
""" """
return self._mechanical_air_change return self._mechanical_air_change
@ -162,7 +162,7 @@ class UsageZone:
@mechanical_air_change.setter @mechanical_air_change.setter
def mechanical_air_change(self, value): def mechanical_air_change(self, value):
""" """
Get usage zone mechanical air change in air change per hour (ACH) Get usages zone mechanical air change in air change per hour (ACH)
:param value: float :param value: float
:return: None :return: None
""" """
@ -171,7 +171,7 @@ class UsageZone:
@property @property
def usage(self): def usage(self):
""" """
Get usage zone usage Get usages zone usages
:return: str :return: str
""" """
return self._usage return self._usage
@ -179,7 +179,7 @@ class UsageZone:
@usage.setter @usage.setter
def usage(self, value): def usage(self, value):
""" """
Get usage zone usage Get usages zone usages
:param value: str :param value: str
:return: None :return: None
""" """
@ -204,7 +204,7 @@ class UsageZone:
@property @property
def heating_schedule(self): def heating_schedule(self):
""" """
Get heating schedule: list of 0, 1 that define whether the heating system should be OFF or ON Get heating schedules: list of 0, 1 that define whether the heating system should be OFF or ON
:return: dict{DataFrame(int)} :return: dict{DataFrame(int)}
""" """
return self._heating_schedule return self._heating_schedule
@ -212,7 +212,7 @@ class UsageZone:
@heating_schedule.setter @heating_schedule.setter
def heating_schedule(self, values): def heating_schedule(self, values):
""" """
heating schedule heating schedules
:param values: dict{DataFrame(int)} :param values: dict{DataFrame(int)}
""" """
self._heating_schedule = values self._heating_schedule = values
@ -220,7 +220,7 @@ class UsageZone:
@property @property
def cooling_schedule(self): def cooling_schedule(self):
""" """
Get cooling schedule: list of 0, 1 that define whether the cooling system should be OFF or ON Get cooling schedules: list of 0, 1 that define whether the cooling system should be OFF or ON
:return: dict{DataFrame(int)} :return: dict{DataFrame(int)}
""" """
return self._cooling_schedule return self._cooling_schedule
@ -228,7 +228,7 @@ class UsageZone:
@cooling_schedule.setter @cooling_schedule.setter
def cooling_schedule(self, values): def cooling_schedule(self, values):
""" """
cooling schedule cooling schedules
:param values: dict{DataFrame(int)} :param values: dict{DataFrame(int)}
""" """
self._cooling_schedule = values self._cooling_schedule = values
@ -236,7 +236,7 @@ class UsageZone:
@property @property
def ventilation_schedule(self): def ventilation_schedule(self):
""" """
Get ventilation schedule: list of 0, 1 that define whether the ventilation system should be OFF or ON Get ventilation schedules: list of 0, 1 that define whether the ventilation system should be OFF or ON
:return: dict{DataFrame(int)} :return: dict{DataFrame(int)}
""" """
return self._ventilation_schedule return self._ventilation_schedule
@ -244,7 +244,7 @@ class UsageZone:
@ventilation_schedule.setter @ventilation_schedule.setter
def ventilation_schedule(self, values): def ventilation_schedule(self, values):
""" """
ventilation_schedule schedule ventilation_schedule schedules
:param values: dict{DataFrame(int)} :param values: dict{DataFrame(int)}
""" """
self._ventilation_schedule = values self._ventilation_schedule = values

View File

@ -11,6 +11,7 @@ from typing import List
import numpy as np import numpy as np
import math import math
from city_model_structure.attributes.sensor import Sensor
from city_model_structure.attributes.surface import Surface from city_model_structure.attributes.surface import Surface
from city_model_structure.attributes.thermal_boundary import ThermalBoundary from city_model_structure.attributes.thermal_boundary import ThermalBoundary
from city_model_structure.attributes.thermal_zone import ThermalZone from city_model_structure.attributes.thermal_zone import ThermalZone
@ -46,6 +47,7 @@ class Building(CityObject):
self._roofs = [] self._roofs = []
self._walls = [] self._walls = []
self._internal_walls = [] self._internal_walls = []
self._sensors = []
self._thermal_zones = [] self._thermal_zones = []
zone_surfaces = None zone_surfaces = None
@ -121,7 +123,7 @@ class Building(CityObject):
@property @property
def usage_zones(self) -> List[UsageZone]: def usage_zones(self) -> List[UsageZone]:
""" """
Get city object usage zones Get city object usages zones
:return: [UsageZone] :return: [UsageZone]
""" """
return self._usage_zones return self._usage_zones
@ -129,7 +131,7 @@ class Building(CityObject):
@usage_zones.setter @usage_zones.setter
def usage_zones(self, values): def usage_zones(self, values):
""" """
Set city objects usage zones Set city objects usages zones
:param values: [UsageZones] :param values: [UsageZones]
:return: None :return: None
""" """
@ -380,3 +382,11 @@ class Building(CityObject):
@pv_plus_hp_installation.setter @pv_plus_hp_installation.setter
def pv_plus_hp_installation(self, value): def pv_plus_hp_installation(self, value):
self._pv_plus_hp_installation = value self._pv_plus_hp_installation = value
@property
def sensors(self) -> List[Sensor]:
return self._sensors
@sensors.setter
def sensors(self, value):
self._sensors = value

View File

@ -7,6 +7,7 @@ from typing import List, Union
from city_model_structure.attributes.surface import Surface from city_model_structure.attributes.surface import Surface
from city_model_structure.attributes.polyhedron import Polyhedron from city_model_structure.attributes.polyhedron import Polyhedron
from helpers.configuration_helper import ConfigurationHelper from helpers.configuration_helper import ConfigurationHelper
import math import math

View File

@ -0,0 +1,11 @@
{
"sensors": [
{ "building" : "EV",
"sensors": ["COMPTEUR.SQD.017.IC:POWER 3P", "COMPTEUR.SQD.B1.IC:POWER 3P", "COMPTEUR.SQD.B2.IC:POWER 3P",
"TOTKWEV-MB.IC"]
},
{ "building" : "GM",
"sensors": ["MDICOR.GM", "MDI.001-650.IC"]
}
]
}

View File

@ -166,7 +166,7 @@ class EnergyAde:
def _building_geometry(self, building, building_dic, city): def _building_geometry(self, building, building_dic, city):
building_dic['bldg:Building']['bldg:function'] = building.function 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:usages'] = ', '.join([u.usage for u in building.usage_zones])
building_dic['bldg:Building']['bldg:yearOfConstruction'] = building.year_of_construction building_dic['bldg:Building']['bldg:yearOfConstruction'] = building.year_of_construction
building_dic['bldg:Building']['bldg:roofType'] = building.roof_type building_dic['bldg:Building']['bldg:roofType'] = building.roof_type
building_dic['bldg:Building']['bldg:measuredHeight'] = { building_dic['bldg:Building']['bldg:measuredHeight'] = {

View File

@ -66,7 +66,7 @@ class Idf:
def add_schedule(self, building): def add_schedule(self, building):
schedule_occupancy = self._idf.newidfobject("SCHEDULE:DAY:HOURLY".upper()) schedule_occupancy = self._idf.newidfobject("SCHEDULE:DAY:HOURLY".upper())
schedule_occupancy.Name = 'occupant schedule' schedule_occupancy.Name = 'occupant schedules'
schedule_occupancy.Hour_1 = building.usage_zones[0].occupants.occupant_schedule[0] schedule_occupancy.Hour_1 = building.usage_zones[0].occupants.occupant_schedule[0]
schedule_occupancy.Hour_2 = building.usage_zones[0].occupants.occupant_schedule[1] schedule_occupancy.Hour_2 = building.usage_zones[0].occupants.occupant_schedule[1]
schedule_occupancy.Hour_3 = building.usage_zones[0].occupants.occupant_schedule[2] schedule_occupancy.Hour_3 = building.usage_zones[0].occupants.occupant_schedule[2]
@ -116,7 +116,7 @@ class Idf:
def _add_heating_system(self, building): def _add_heating_system(self, building):
for usage_zone in building.usage_zones: for usage_zone in building.usage_zones:
thermostat_name = f'Thermostat {building.name}' thermostat_name = f'Thermostat {building.name}'
# todo: this will fail for more than one usage zone # todo: this will fail for more than one usages zone
static_thermostat = self._idf.newidfobject(self._THERMOSTAT, static_thermostat = self._idf.newidfobject(self._THERMOSTAT,
Name=thermostat_name, Name=thermostat_name,
Constant_Heating_Setpoint=usage_zone.heating_setpoint, Constant_Heating_Setpoint=usage_zone.heating_setpoint,
@ -189,14 +189,14 @@ class Idf:
self._idf.newidfobject("PEOPLE", self._idf.newidfobject("PEOPLE",
Name=zone.Name + "_" + "schedules", Name=zone.Name + "_" + "schedules",
Zone_or_ZoneList_Name=zone.Name, Zone_or_ZoneList_Name=zone.Name,
Number_of_People_Schedule_Name='occupant schedule', Number_of_People_Schedule_Name='occupant schedules',
Number_of_People_Calculation_Method="People", Number_of_People_Calculation_Method="People",
Number_of_People=500, Number_of_People=500,
# Zone_Floor_Area_per_Person=31.41, # Zone_Floor_Area_per_Person=31.41,
# People_per_Zone_Floor_Area=17*0.05, # People_per_Zone_Floor_Area=17*0.05,
# Zone_Floor_Area_per_Person=1.65880764E+01, # Zone_Floor_Area_per_Person=1.65880764E+01,
Fraction_Radiant=0.3, Fraction_Radiant=0.3,
Activity_Level_Schedule_Name='occupant schedule' Activity_Level_Schedule_Name='occupant schedules'
) )
def add_equipment(self): def add_equipment(self):

View File

@ -3,8 +3,8 @@ ConstructionFactory (before PhysicsFactory) retrieve the specific construction m
SPDX - License - Identifier: LGPL - 3.0 - or -later SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
""" """
from imports.construction_feeders.us_physics_parameters import UsPhysicsParameters from imports.constructions.us_physics_parameters import UsPhysicsParameters
from imports.construction_feeders.ca_physics_parameters import CaPhysicsParameters from imports.constructions.ca_physics_parameters import CaPhysicsParameters
from pathlib import Path from pathlib import Path

View File

@ -5,8 +5,8 @@ Copyright © 2020 Project Author Pilar Monsalvete pilar_monsalvete@yahoo.es
""" """
import sys import sys
from imports.construction_feeders.nrel_physics_interface import NrelPhysicsInterface from imports.constructions.nrel_physics_interface import NrelPhysicsInterface
from imports.construction_feeders.helpers.construction_helper import ConstructionHelper from imports.constructions.helpers.construction_helper import ConstructionHelper
class CaPhysicsParameters(NrelPhysicsInterface): class CaPhysicsParameters(NrelPhysicsInterface):

View File

@ -4,7 +4,7 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Pilar Monsalvete pilar_monsalvete@yahoo.es Copyright © 2020 Project Author Pilar Monsalvete pilar_monsalvete@yahoo.es
""" """
from typing import List from typing import List
from imports.construction_feeders.data_classes.nrel_thermal_boundary_archetype import NrelThermalBoundaryArchetype from imports.constructions.data_classes.nrel_thermal_boundary_archetype import NrelThermalBoundaryArchetype
class NrelBuildingArchetype: class NrelBuildingArchetype:

View File

@ -5,8 +5,8 @@ Copyright © 2020 Project Author Pilar Monsalvete pilar_monsalvete@yahoo.es
""" """
from typing import List from typing import List
from imports.construction_feeders.data_classes.nrel_layer_archetype import NrelLayerArchetype from imports.constructions.data_classes.nrel_layer_archetype import NrelLayerArchetype
from imports.construction_feeders.data_classes.nrel_thermal_opening_archetype import NrelThermalOpeningArchetype from imports.constructions.data_classes.nrel_thermal_opening_archetype import NrelThermalOpeningArchetype
class NrelThermalBoundaryArchetype: class NrelThermalBoundaryArchetype:

View File

@ -6,10 +6,10 @@ Copyright © 2020 Project Author Pilar Monsalvete pilar_monsalvete@yahoo.es
""" """
import xmltodict import xmltodict
from imports.construction_feeders.data_classes.nrel_building_achetype import NrelBuildingArchetype as nba from imports.constructions.data_classes.nrel_building_achetype import NrelBuildingArchetype as nba
from imports.construction_feeders.data_classes.nrel_thermal_boundary_archetype import NrelThermalBoundaryArchetype as ntba from imports.constructions.data_classes.nrel_thermal_boundary_archetype import NrelThermalBoundaryArchetype as ntba
from imports.construction_feeders.data_classes.nrel_thermal_opening_archetype import NrelThermalOpeningArchetype as ntoa from imports.constructions.data_classes.nrel_thermal_opening_archetype import NrelThermalOpeningArchetype as ntoa
from imports.construction_feeders.data_classes.nrel_layer_archetype import NrelLayerArchetype as nla from imports.constructions.data_classes.nrel_layer_archetype import NrelLayerArchetype as nla
class NrelPhysicsInterface: class NrelPhysicsInterface:

View File

@ -6,8 +6,8 @@ Contributors Pilar Monsalvete pilar_monsalvete@yahoo.es
""" """
import sys import sys
from imports.construction_feeders.nrel_physics_interface import NrelPhysicsInterface from imports.constructions.nrel_physics_interface import NrelPhysicsInterface
from imports.construction_feeders.helpers.construction_helper import ConstructionHelper from imports.constructions.helpers.construction_helper import ConstructionHelper
from city_model_structure.attributes.layer import Layer from city_model_structure.attributes.layer import Layer
from city_model_structure.attributes.material import Material from city_model_structure.attributes.material import Material

View File

@ -245,7 +245,7 @@ class GeometryHelper:
'large office': 'large office' 'large office': 'large office'
} }
# usage # usages
fuction_to_usage = { fuction_to_usage = {
'full service restaurant': 'restaurant', 'full service restaurant': 'restaurant',
'highrise apartment': 'residential', 'highrise apartment': 'residential',
@ -288,7 +288,7 @@ class GeometryHelper:
@staticmethod @staticmethod
def usage_from_function(building_function): def usage_from_function(building_function):
""" """
Get the internal usage for the given internal building function Get the internal usages for the given internal building function
:param building_function: str :param building_function: str
:return: str :return: str
""" """

View File

@ -7,9 +7,9 @@ from trimesh.scene import Scene
from city_model_structure.city import City from city_model_structure.city import City
from city_model_structure.city_object import CityObject from city_model_structure.city_object import CityObject
from imports.geometry_feeders.citygml import CityGml from imports.geometry.citygml import CityGml
from imports.geometry_feeders.osm_subway import OsmSubway from imports.geometry.osm_subway import OsmSubway
from imports.geometry_feeders.obj import Obj from imports.geometry.obj import Obj
class GeometryFactory: class GeometryFactory:

View File

@ -1,11 +1,11 @@
""" """
Schedules retrieve the specific usage schedules module for the given standard Schedules retrieve the specific usages schedules module for the given standard
SPDX - License - Identifier: LGPL - 3.0 - or -later SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
contributors Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca contributors Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
""" """
import pandas as pd import pandas as pd
from imports.schedules_feeders.helpers.schedules_helper import SchedulesHelper from imports.schedules.helpers.schedules_helper import SchedulesHelper
class ComnetSchedules: class ComnetSchedules:

View File

@ -24,7 +24,7 @@ class SchedulesHelper:
@staticmethod @staticmethod
def comnet_from_usage(usage): def comnet_from_usage(usage):
""" """
Get Comnet usage from the given internal usage key Get Comnet usages from the given internal usages key
:param usage: str :param usage: str
:return: str :return: str
""" """

View File

@ -5,7 +5,7 @@ Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@conc
""" """
from pathlib import Path from pathlib import Path
from imports.schedules_feeders.comnet_schedules_parameters import ComnetSchedules from imports.schedules.comnet_schedules_parameters import ComnetSchedules
class SchedulesFactory: class SchedulesFactory:

View File

@ -0,0 +1,86 @@
"""
Concordia energy consumption
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2021 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
"""
import io
import json
from pathlib import Path
import pandas as pd
from city_model_structure.attributes.concordia_energy_sensor import ConcordiaEnergySensor
class ConcordiaEnergyConsumption:
def __init__(self, city, end_point, base_path):
self._buildings = []
self._sensors = []
self._sensor_point = {}
self._city = city
self._end_point = end_point
self._sensor_database = base_path
metadata = True
content = False
with open (Path(base_path / 'concordia.json').resolve()) as concordia_db:
self._sensor_database = json.load(concordia_db)
for building in self._sensor_database['sensors']:
building_name = building['building']
for sensor in building['sensors']:
self._buildings.append(building_name)
self._sensors.append(sensor)
buffer = ""
with open(end_point.resolve()) as data:
for line in data:
line = ConcordiaEnergyConsumption.clean_line(line)
if metadata:
fields = line.split(',')
if len(fields) > 2:
point = fields[0].replace(":","")
key = fields[1]
if fields[1] in self._sensors:
self._sensor_point[key] = point
if "End of Report" in line:
content = False
if content:
line = ConcordiaEnergyConsumption.merge_date_time(line)
buffer = buffer + line + '\n'
if line is '':
metadata = False
content = True
measures = pd.read_csv(io.StringIO(buffer), sep=',')
measures["Date time"] = pd.to_datetime(measures["Date time"])
measures = ConcordiaEnergyConsumption.force_format(measures)
for building in city.buildings:
for i in range(len(self._buildings)):
if self._buildings[i] == building.name:
building_measures = [measures["Date time"], measures[self._sensor_point[self._sensors[i]]]]
building_headers = ["Date time", "Energy consumption"]
building_energy_consumption = pd.concat(building_measures, keys=building_headers, axis=1)
building.sensors.append(ConcordiaEnergySensor( self._sensors[i], building_energy_consumption))
@staticmethod
def clean_line(line):
return line.replace('"', '').replace('\n', '')
@staticmethod
def merge_date_time(line):
fields = line.split(',')
date = fields[0]
time = fields[1]
if '<>'in date:
return line.replace(f'{date},{time}', 'Date time')
else:
date_fields = date.split('/')
format_date_time = f'"{int(date_fields[2])}-{int(date_fields[0]):02d}-{int(date_fields[1]):02d} {time}"'
return line.replace(f'{date},{time}', format_date_time)
@staticmethod
def force_format(df):
for head in df.head():
if 'Date time' not in head:
df = df.astype({head: 'float64'})
return df

View File

@ -0,0 +1,29 @@
"""
SensorsFactory retrieve sensors information
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2021 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
"""
from pathlib import Path
from imports.sensors.concordia_energy_consumption import ConcordiaEnergyConsumption
class SensorsFactory:
"""
UsageFactory class
"""
def __init__(self, handler, city, end_point, base_path=Path(Path(__file__).parent.parent / 'data/sensors')):
self._handler = '_' + handler.lower().replace(' ', '_')
self._city = city
self._end_point = end_point
self._base_path = base_path
def _cec(self):
ConcordiaEnergyConsumption(self._city, self._end_point, self._base_path)
def enrich(self):
"""
Enrich the city with the usages information
:return: None
"""
getattr(self, self._handler, lambda: None)()

View File

@ -1,17 +1,17 @@
""" """
UsageFactory retrieve the specific usage module for the given region UsageFactory retrieve the specific usages module for the given region
SPDX - License - Identifier: LGPL - 3.0 - or -later SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
""" """
from pathlib import Path from pathlib import Path
from imports.usage_feeders.hft_usage_parameters import HftUsageParameters from imports.usages.hft_usage_parameters import HftUsageParameters
class UsageFactory: class UsageFactory:
""" """
UsageFactory class UsageFactory class
""" """
def __init__(self, handler, city, base_path=Path(Path(__file__).parent.parent / 'data/usage')): def __init__(self, handler, city, base_path=Path(Path(__file__).parent.parent / 'data/usages')):
self._handler = '_' + handler.lower().replace(' ', '_') self._handler = '_' + handler.lower().replace(' ', '_')
self._city = city self._city = city
self._base_path = base_path self._base_path = base_path
@ -24,7 +24,7 @@ class UsageFactory:
def enrich(self): def enrich(self):
""" """
Enrich the city with the usage information Enrich the city with the usages information
:return: None :return: None
""" """
getattr(self, self._handler, lambda: None)() getattr(self, self._handler, lambda: None)()

View File

@ -1,10 +1,10 @@
""" """
HftUsageZoneArchetype stores usage information by building archetypes HftUsageZoneArchetype stores usages information by building archetypes
SPDX - License - Identifier: LGPL - 3.0 - or -later SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Pilar Monsalvete pilar_monsalvete@yahoo.es Copyright © 2020 Project Author Pilar Monsalvete pilar_monsalvete@yahoo.es
""" """
from typing import List from typing import List
from imports.usage_feeders.data_classes.hft_internal_gains_archetype import HftInternalGainsArchetype from imports.usages.data_classes.hft_internal_gains_archetype import HftInternalGainsArchetype
class HftUsageZoneArchetype: class HftUsageZoneArchetype:
@ -34,7 +34,7 @@ class HftUsageZoneArchetype:
@property @property
def internal_gains(self) -> List[HftInternalGainsArchetype]: def internal_gains(self) -> List[HftInternalGainsArchetype]:
""" """
Get usage zone internal gains Get usages zone internal gains
:return: [InternalGains] :return: [InternalGains]
""" """
return self._internal_gains return self._internal_gains
@ -42,7 +42,7 @@ class HftUsageZoneArchetype:
@property @property
def heating_setpoint(self): def heating_setpoint(self):
""" """
Get usage zone heating set point in celsius grads Get usages zone heating set point in celsius grads
:return: float :return: float
""" """
return self._heating_setpoint return self._heating_setpoint
@ -50,7 +50,7 @@ class HftUsageZoneArchetype:
@property @property
def heating_setback(self): def heating_setback(self):
""" """
Get usage zone heating setback in celsius grads Get usages zone heating setback in celsius grads
:return: float :return: float
""" """
return self._heating_setback return self._heating_setback
@ -58,7 +58,7 @@ class HftUsageZoneArchetype:
@property @property
def cooling_setpoint(self): def cooling_setpoint(self):
""" """
Get usage zone cooling setpoint in celsius grads Get usages zone cooling setpoint in celsius grads
:return: float :return: float
""" """
return self._cooling_setpoint return self._cooling_setpoint
@ -66,7 +66,7 @@ class HftUsageZoneArchetype:
@property @property
def hours_day(self): def hours_day(self):
""" """
Get usage zone usage hours per day Get usages zone usages hours per day
:return: float :return: float
""" """
return self._hours_day return self._hours_day
@ -74,7 +74,7 @@ class HftUsageZoneArchetype:
@property @property
def days_year(self): def days_year(self):
""" """
Get usage zone usage days per year Get usages zone usages days per year
:return: float :return: float
""" """
return self._days_year return self._days_year
@ -82,7 +82,7 @@ class HftUsageZoneArchetype:
@property @property
def mechanical_air_change(self): def mechanical_air_change(self):
""" """
Set usage zone mechanical air change in air change per hour (ACH) Set usages zone mechanical air change in air change per hour (ACH)
:return: float :return: float
""" """
return self._mechanical_air_change return self._mechanical_air_change
@ -90,7 +90,7 @@ class HftUsageZoneArchetype:
@property @property
def usage(self): def usage(self):
""" """
Get usage zone usage Get usages zone usages
:return: str :return: str
""" """
return self._usage return self._usage

View File

@ -23,12 +23,12 @@ class UsageHelper:
@staticmethod @staticmethod
def hft_from_usage(usage): def hft_from_usage(usage):
""" """
Get HfT usage from the given internal usage key Get HfT usages from the given internal usages key
:param usage: str :param usage: str
:return: str :return: str
""" """
try: try:
return UsageHelper.usage_to_hft[usage] return UsageHelper.usage_to_hft[usage]
except KeyError: except KeyError:
sys.stderr.write('Error: keyword not found. Returned default HfT usage "residential"\n') sys.stderr.write('Error: keyword not found. Returned default HfT usages "residential"\n')
return UsageHelper.hft_default_value return UsageHelper.hft_default_value

View File

@ -1,12 +1,12 @@
""" """
Hft-based interface, it reads format defined within the CERC team based on that one used in SimStadt and developed by Hft-based interface, it reads format defined within the CERC team based on that one used in SimStadt and developed by
the IAF team at hft-Stuttgart and enriches the city with usage parameters the IAF team at hft-Stuttgart and enriches the city with usages parameters
SPDX - License - Identifier: LGPL - 3.0 - or -later SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
""" """
import xmltodict import xmltodict
from imports.usage_feeders.data_classes.hft_usage_zone_archetype import HftUsageZoneArchetype as huza from imports.usages.data_classes.hft_usage_zone_archetype import HftUsageZoneArchetype as huza
from imports.usage_feeders.data_classes.hft_internal_gains_archetype import HftInternalGainsArchetype as higa from imports.usages.data_classes.hft_internal_gains_archetype import HftInternalGainsArchetype as higa
class HftUsageInterface: class HftUsageInterface:

View File

@ -1,12 +1,12 @@
""" """
HftUsageParameters model the usage properties HftUsageParameters model the usages properties
SPDX - License - Identifier: LGPL - 3.0 - or -later SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
""" """
import sys import sys
from imports.geometry_feeders.helpers.geometry_helper import GeometryHelper as gh from imports.geometry.helpers.geometry_helper import GeometryHelper as gh
from imports.usage_feeders.hft_usage_interface import HftUsageInterface from imports.usages.hft_usage_interface import HftUsageInterface
from city_model_structure.attributes.usage_zone import UsageZone from city_model_structure.attributes.usage_zone import UsageZone
from city_model_structure.attributes.internal_gains import InternalGains from city_model_structure.attributes.internal_gains import InternalGains
@ -25,7 +25,7 @@ class HftUsageParameters(HftUsageInterface):
def enrich_buildings(self): def enrich_buildings(self):
""" """
Returns the city with the usage parameters assigned to the buildings Returns the city with the usages parameters assigned to the buildings
:return: :return:
""" """
city = self._city city = self._city
@ -33,10 +33,10 @@ class HftUsageParameters(HftUsageInterface):
archetype = self._search_archetype(gh.usage_from_function(building.function)) archetype = self._search_archetype(gh.usage_from_function(building.function))
if archetype is None: if archetype is None:
sys.stderr.write(f'Building {building.name} has unknown archetype for building function:' sys.stderr.write(f'Building {building.name} has unknown archetype for building function:'
f' {building.function}, that assigns building usage as ' f' {building.function}, that assigns building usages as '
f'{gh.usage_from_function(building.function)}\n') f'{gh.usage_from_function(building.function)}\n')
continue continue
# todo: what to do with mix-usage usages from gml? # todo: what to do with mix-usages usages from gml?
mix_usage = False mix_usage = False
if not mix_usage: if not mix_usage:
# just one usage_zone # just one usage_zone

View File

@ -4,8 +4,8 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
""" """
from pathlib import Path from pathlib import Path
from imports.weather_feeders.xls_weather_parameters import XlsWeatherParameters from imports.weather.xls_weather_parameters import XlsWeatherParameters
from imports.weather_feeders.epw_weather_parameters import EpwWeatherParameters from imports.weather.epw_weather_parameters import EpwWeatherParameters
class WeatherFactory: class WeatherFactory:
@ -39,7 +39,7 @@ class WeatherFactory:
def enrich(self): def enrich(self):
""" """
Enrich the city with the usage information Enrich the city with the usages information
:return: None :return: None
""" """
getattr(self, self._handler, lambda: None)() getattr(self, self._handler, lambda: None)()

View File

@ -8,7 +8,7 @@ from unittest import TestCase
from imports.geometry_factory import GeometryFactory from imports.geometry_factory import GeometryFactory
from imports.construction_factory import ConstructionFactory from imports.construction_factory import ConstructionFactory
from imports.geometry_feeders.helpers.geometry_helper import GeometryHelper from imports.geometry.helpers.geometry_helper import GeometryHelper
class TestConstructionFactory(TestCase): class TestConstructionFactory(TestCase):

View File

@ -6,7 +6,7 @@ Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.mons
from pathlib import Path from pathlib import Path
from unittest import TestCase from unittest import TestCase
from imports.geometry_factory import GeometryFactory from imports.geometry_factory import GeometryFactory
from imports.geometry_feeders.helpers.geometry_helper import GeometryHelper from imports.geometry.helpers.geometry_helper import GeometryHelper
class TestGeometryFactory(TestCase): class TestGeometryFactory(TestCase):

View File

@ -1,7 +1,7 @@
""" """
TestSchedulesFactory test and validate the city model structure schedules TestSchedulesFactory test and validate the city model structure schedules
SPDX - License - Identifier: LGPL - 3.0 - or -later SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
""" """
from pathlib import Path from pathlib import Path
from unittest import TestCase from unittest import TestCase
@ -9,7 +9,7 @@ from unittest import TestCase
from imports.geometry_factory import GeometryFactory from imports.geometry_factory import GeometryFactory
from imports.usage_factory import UsageFactory from imports.usage_factory import UsageFactory
from imports.schedules_factory import SchedulesFactory from imports.schedules_factory import SchedulesFactory
from imports.geometry_feeders.helpers.geometry_helper import GeometryHelper from imports.geometry.helpers.geometry_helper import GeometryHelper
class TestSchedulesFactory(TestCase): class TestSchedulesFactory(TestCase):

View File

@ -0,0 +1,48 @@
"""
TestSensorsFactory test and validate the city model structure schedules
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2021 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
"""
from pathlib import Path
from unittest import TestCase
from city_model_structure.city import City
from city_model_structure.building import Building
from imports.sensors_factory import SensorsFactory
class TestSensorsFactory(TestCase):
"""
TestSchedulesFactory TestCase
"""
def setUp(self) -> None:
"""
Configure test environment
:return:
"""
self._city = TestSensorsFactory._mockup_city()
self._end_point = (Path(__file__).parent / 'tests_data/EV-GM energy demand weekly report_01-26-20_04-30.csv').resolve()
@staticmethod
def _mockup_city():
lower_corner = [0, 0, 0]
upper_corner = [10, 10, 10]
srs_name = 'Mockup_city'
buildings = []
lod = 2
surfaces = []
year_of_construction = 2021
function = "office"
buildings.append(Building("EV", lod, surfaces, year_of_construction, function, lower_corner))
buildings.append(Building("GM_2", lod, surfaces, year_of_construction, function, lower_corner))
return City(lower_corner, upper_corner, srs_name, buildings)
def test_city_with_sensors(self):
SensorsFactory('cec', self._city, self._end_point).enrich()
for building in self._city.buildings:
for sensor in building.sensors:
self.assertTrue(sensor.type is 'ConcordiaEnergySensor')
print(f'{building.name} {sensor.name} {sensor.type}')
print(sensor.measures)

View File

@ -1,5 +1,5 @@
""" """
TestUsageFactory test and validate the city model structure usage parameters TestUsageFactory test and validate the city model structure usages parameters
SPDX - License - Identifier: LGPL - 3.0 - or -later SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
""" """
@ -8,7 +8,7 @@ from unittest import TestCase
from imports.geometry_factory import GeometryFactory from imports.geometry_factory import GeometryFactory
from imports.usage_factory import UsageFactory from imports.usage_factory import UsageFactory
from imports.geometry_feeders.helpers.geometry_helper import GeometryHelper from imports.geometry.helpers.geometry_helper import GeometryHelper
class TestUsageFactory(TestCase): class TestUsageFactory(TestCase):
@ -31,7 +31,7 @@ class TestUsageFactory(TestCase):
def test_city_with_usage(self): def test_city_with_usage(self):
""" """
Enrich the city with the usage information and verify it Enrich the city with the usages information and verify it
:return: None :return: None
""" """
file = 'pluto_building.gml' file = 'pluto_building.gml'
@ -44,14 +44,14 @@ class TestUsageFactory(TestCase):
for building in city.buildings: for building in city.buildings:
self.assertIsNotNone(building.usage_zones, 'usage_zones not created') self.assertIsNotNone(building.usage_zones, 'usage_zones not created')
for usage_zone in building.usage_zones: for usage_zone in building.usage_zones:
self.assertIsNotNone(usage_zone.usage, 'usage is none') self.assertIsNotNone(usage_zone.usage, 'usages is none')
self.assertIsNotNone(usage_zone.internal_gains, 'usage is none') self.assertIsNotNone(usage_zone.internal_gains, 'usages is none')
self.assertIsNotNone(usage_zone.cooling_setpoint, 'usage is none') self.assertIsNotNone(usage_zone.cooling_setpoint, 'usages is none')
self.assertIsNotNone(usage_zone.heating_setback, 'usage is none') self.assertIsNotNone(usage_zone.heating_setback, 'usages is none')
self.assertIsNotNone(usage_zone.heating_setpoint, 'usage is none') self.assertIsNotNone(usage_zone.heating_setpoint, 'usages is none')
self.assertIsNotNone(usage_zone.occupancy_density, 'usage is none') self.assertIsNotNone(usage_zone.occupancy_density, 'usages is none')
self.assertIsNotNone(usage_zone.hours_day, 'usage is none') self.assertIsNotNone(usage_zone.hours_day, 'usages is none')
self.assertIsNotNone(usage_zone.days_year, 'usage is none') self.assertIsNotNone(usage_zone.days_year, 'usages is none')
self.assertIsNotNone(usage_zone.dhw_average_volume_pers_day, 'usage is none') self.assertIsNotNone(usage_zone.dhw_average_volume_pers_day, 'usages is none')
self.assertIsNotNone(usage_zone.dhw_preparation_temperature, 'usage is none') self.assertIsNotNone(usage_zone.dhw_preparation_temperature, 'usages is none')
self.assertIsNotNone(usage_zone.electrical_app_average_consumption_sqm_year, 'usage is none') self.assertIsNotNone(usage_zone.electrical_app_average_consumption_sqm_year, 'usages is none')