From b29f3bf301fd0d941fd37fb0645377c548f01767 Mon Sep 17 00:00:00 2001 From: guille Date: Wed, 2 Jun 2021 09:30:01 -0400 Subject: [PATCH 1/2] small improvements in sensors modeling including the posibility to update the measured dataframes --- .../attributes/concordia_energy_sensor.py | 18 +++++++++++----- city_model_structure/attributes/sensor.py | 3 +++ city_model_structure/building.py | 11 ---------- city_model_structure/city_object.py | 21 +++++++++++++++++++ .../sensors/concordia_energy_consumption.py | 12 ++++++++++- non_functional_tests/test_sensors_factory.py | 16 +++++++++++--- 6 files changed, 61 insertions(+), 20 deletions(-) diff --git a/city_model_structure/attributes/concordia_energy_sensor.py b/city_model_structure/attributes/concordia_energy_sensor.py index c7419d63..1b951dc7 100644 --- a/city_model_structure/attributes/concordia_energy_sensor.py +++ b/city_model_structure/attributes/concordia_energy_sensor.py @@ -13,17 +13,21 @@ class ConcordiaEnergySensor(Sensor): Concordia energy sensor. """ - def __init__(self, name, measures): + def __init__(self, name): super().__init__() self._name = name self._interval = 5 self._interval_units = 'minutes' self._type = 'ConcordiaEnergySensor' - self._units = 'kW/h' - self._measures = measures + self._units = 'kWh' + self._measures = pd.DataFrame(columns=["Date time", "Energy consumption"]) @property def measures(self) -> pd.DataFrame: + """ + Sensor measures [yyyy-mm-dd, hh:mm:ss kWh] + :return: DataFrame["Date time", "Energy consumption"] + """ return self._measures @measures.deleter @@ -31,6 +35,10 @@ class ConcordiaEnergySensor(Sensor): self._measures.drop = None - def add_period(self, period): - self._measures.append(period) + def add_period(self, measures): + """ + Add or update a period measures to the dataframe + """ + measures = self._measures.append(measures, ignore_index=True) + self._measures = measures.drop_duplicates('Date time', keep='last') diff --git a/city_model_structure/attributes/sensor.py b/city_model_structure/attributes/sensor.py index cbbc6840..497788a1 100644 --- a/city_model_structure/attributes/sensor.py +++ b/city_model_structure/attributes/sensor.py @@ -5,6 +5,9 @@ Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@conc """ class Sensor: + """ + Sensor abstract class + """ def __init__(self): self._name = None self._type = None diff --git a/city_model_structure/building.py b/city_model_structure/building.py index 2a06ae43..c30a07b8 100644 --- a/city_model_structure/building.py +++ b/city_model_structure/building.py @@ -10,8 +10,6 @@ import sys from typing import List import numpy as np import math - -from city_model_structure.attributes.sensor import Sensor from city_model_structure.attributes.surface import Surface from city_model_structure.attributes.thermal_boundary import ThermalBoundary from city_model_structure.attributes.thermal_zone import ThermalZone @@ -47,7 +45,6 @@ class Building(CityObject): self._roofs = [] self._walls = [] self._internal_walls = [] - self._sensors = [] self._thermal_zones = [] zone_surfaces = None @@ -382,11 +379,3 @@ class Building(CityObject): @pv_plus_hp_installation.setter def pv_plus_hp_installation(self, 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 \ No newline at end of file diff --git a/city_model_structure/city_object.py b/city_model_structure/city_object.py index c2009b3f..67fa54e6 100644 --- a/city_model_structure/city_object.py +++ b/city_model_structure/city_object.py @@ -3,6 +3,7 @@ CityObject 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 from typing import List, Union from city_model_structure.attributes.surface import Surface from city_model_structure.attributes.polyhedron import Polyhedron @@ -32,6 +33,7 @@ class CityObject: self._global_horizontal = dict() self._diffuse = dict() self._beam = dict() + self._sensors = [] @property def lod(self): @@ -201,6 +203,25 @@ class CityObject: @property def city_object_lower_corner(self): + """ + City object lower corner coordinates [x, y, z] + """ if self._city_object_lower_corner is None: self._city_object_lower_corner = [self._min_x, self._min_y, self._min_z] return self._city_object_lower_corner + + @property + def sensors(self) -> List[Sensor]: + """ + Sensor list belonging to the city object + :return: [Sensor] + """ + return self._sensors + + @sensors.setter + def sensors(self, value): + """ + Sensor list belonging to the city object + :param value: [Sensor] + """ + self._sensors = value \ No newline at end of file diff --git a/imports/sensors/concordia_energy_consumption.py b/imports/sensors/concordia_energy_consumption.py index fd52783d..01101029 100644 --- a/imports/sensors/concordia_energy_consumption.py +++ b/imports/sensors/concordia_energy_consumption.py @@ -60,7 +60,17 @@ class ConcordiaEnergyConsumption: 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)) + sensor = ConcordiaEnergySensor(self._sensors[i]) + sensor_exist = False + for j in range(len(building.sensors)): + if building.sensors[j].name is sensor.name: + building.sensors[j].add_period(building_energy_consumption) + sensor_exist = True + break + if not sensor_exist: + sensor.add_period(building_energy_consumption) + building.sensors.append(sensor) + @staticmethod def clean_line(line): diff --git a/non_functional_tests/test_sensors_factory.py b/non_functional_tests/test_sensors_factory.py index b5ae3585..992be9cf 100644 --- a/non_functional_tests/test_sensors_factory.py +++ b/non_functional_tests/test_sensors_factory.py @@ -5,11 +5,13 @@ Copyright © 2021 Project Author Guille Gutierrez guillermo.gutierrezmorote@conc """ from pathlib import Path from unittest import TestCase +import pandas as pd 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 @@ -35,7 +37,7 @@ class TestSensorsFactory(TestCase): 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)) + buildings.append(Building("GM", lod, surfaces, year_of_construction, function, lower_corner)) return City(lower_corner, upper_corner, srs_name, buildings) @@ -44,5 +46,13 @@ class TestSensorsFactory(TestCase): 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) + # force update last row + update = pd.DataFrame([['2020-01-19 23:55:00', '12345.0']], columns=["Date time", "Energy consumption"]) + update = update.astype({"Date time": 'datetime64', "Energy consumption":'float64'}) + sensor.add_period(update) + row = sensor.measures.loc[sensor.measures["Date time"] == '2020-01-19 23:55:00'] + print(row["Energy consumption"][0]) + self.assertTrue(row[0]["Energy consumption"] is '12345.0') + + + From 30d5502b6361ad862b16e2c7d2248271c8caf76a Mon Sep 17 00:00:00 2001 From: guille Date: Wed, 2 Jun 2021 09:42:39 -0400 Subject: [PATCH 2/2] Correct failing unittest test_city_with_sensors --- non_functional_tests/test_sensors_factory.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/non_functional_tests/test_sensors_factory.py b/non_functional_tests/test_sensors_factory.py index 992be9cf..3e718572 100644 --- a/non_functional_tests/test_sensors_factory.py +++ b/non_functional_tests/test_sensors_factory.py @@ -50,9 +50,5 @@ class TestSensorsFactory(TestCase): update = pd.DataFrame([['2020-01-19 23:55:00', '12345.0']], columns=["Date time", "Energy consumption"]) update = update.astype({"Date time": 'datetime64', "Energy consumption":'float64'}) sensor.add_period(update) - row = sensor.measures.loc[sensor.measures["Date time"] == '2020-01-19 23:55:00'] - print(row["Energy consumption"][0]) - self.assertTrue(row[0]["Energy consumption"] is '12345.0') - - - + row = sensor.measures.loc[sensor.measures["Date time"] == '2020-01-19 23:55:00']['Energy consumption'].iloc[0] + self.assertTrue(f'{row}' == '12345.0')