diff --git a/city_model_structure/attributes/schedule.py b/city_model_structure/attributes/schedule.py index 49345b4d..76bbf47b 100644 --- a/city_model_structure/attributes/schedule.py +++ b/city_model_structure/attributes/schedule.py @@ -5,6 +5,7 @@ Copyright © 2021 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.mons """ import uuid +from typing import Union, List class Schedule: @@ -31,10 +32,10 @@ class Schedule: return self._id @property - def type(self): + def type(self) -> Union[None, str]: """ Get schedule type - :return: str + :return: None or str """ return self._type @@ -44,13 +45,14 @@ class Schedule: Set schedule type :param: str """ - self._type = str(value) + if value is not None: + self._type = str(value) @property def values(self): """ Get schedule values - :return: Union([float], [int]) + :return: [Any] """ return self._values @@ -58,16 +60,16 @@ class Schedule: def values(self, value): """ Set schedule values - :param: Union([float], [int]) + :param: [Any] """ self._values = value @property - def data_type(self): + def data_type(self) -> Union[None, str]: """ Get schedule data type from: ['any_number', 'fraction', 'on_off', 'temperature', 'humidity', 'control_type'] - :return: str + :return: None or str """ return self._data_type @@ -77,14 +79,15 @@ class Schedule: Set schedule data type :param: str """ - self._data_type = str(value) + if value is not None: + self._data_type = str(value) @property - def time_step(self): + def time_step(self) -> Union[None, str]: """ Get schedule time step from: ['second', 'minute', 'hour', 'day', 'week', 'month'] - :return: str + :return: None or str """ return self._time_step @@ -94,14 +97,15 @@ class Schedule: Set schedule time step :param: str """ - self._time_step = str(value) + if value is not None: + self._time_step = str(value) @property - def time_range(self): + def time_range(self) -> Union[None, str]: """ Get schedule time range from: ['minute', 'hour', 'day', 'week', 'month', 'year'] - :return: str + :return: None or str """ return self._time_range @@ -111,15 +115,16 @@ class Schedule: Set schedule time range :param: str """ - self._time_range = str(value) + if value is not None: + self._time_range = str(value) @property - def day_types(self): + def day_types(self) -> Union[None, List[str]]: """ Get schedule day types, as many as needed from: ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday', 'holiday', 'winter_design_day', 'summer_design_day'] - :return: [str] + :return: None or [str] """ return self._day_types @@ -129,4 +134,5 @@ class Schedule: Set schedule day types :param: [str] """ - self._day_types = [str(i) for i in value] + if value is not None: + self._day_types = [str(i) for i in value] diff --git a/city_model_structure/building.py b/city_model_structure/building.py index 27eb6316..7605dc03 100644 --- a/city_model_structure/building.py +++ b/city_model_structure/building.py @@ -5,7 +5,7 @@ Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@conc contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca """ -from typing import List +from typing import List, Union import numpy as np from city_model_structure.building_demand.surface import Surface from city_model_structure.building_demand.thermal_zone import ThermalZone @@ -124,10 +124,10 @@ class Building(CityObject): return self._terrains @property - def attic_heated(self): + def attic_heated(self) -> Union[None, int]: """ Get if the city object attic is heated - :return: Boolean + :return: None or int """ return self._attic_heated @@ -135,15 +135,16 @@ class Building(CityObject): def attic_heated(self, value): """ Set if the city object attic is heated - :param value: Boolean + :param value: int """ - self._attic_heated = bool(value) + if value is not None: + self._attic_heated = int(value) @property - def basement_heated(self): + def basement_heated(self) -> Union[None, int]: """ Get if the city object basement is heated - :return: Boolean + :return: None or int """ return self._basement_heated @@ -151,9 +152,10 @@ class Building(CityObject): def basement_heated(self, value): """ Set if the city object basement is heated - :param value: Boolean + :param value: int """ - self._basement_heated = bool(value) + if value is not None: + self._basement_heated = int(value) @property def name(self): @@ -191,10 +193,10 @@ class Building(CityObject): return self._year_of_construction @property - def function(self): + def function(self) -> Union[None, str]: """ Get building function - :return: str + :return: None or str """ return self._function @@ -204,13 +206,14 @@ class Building(CityObject): Set building function :param value: str """ - self._function = str(value) + if value is not None: + self._function = str(value) @property - def average_storey_height(self): + def average_storey_height(self) -> Union[None, float]: """ Get building average storey height in meters - :return: float + :return: None or float """ return self._average_storey_height @@ -220,13 +223,14 @@ class Building(CityObject): Set building average storey height in meters :param value: float """ - self._average_storey_height = float(value) + if value is not None: + self._average_storey_height = float(value) @property - def storeys_above_ground(self): + def storeys_above_ground(self) -> Union[None, int]: """ Get building storeys number above ground - :return: int + :return: None or int """ return self._storeys_above_ground @@ -236,7 +240,8 @@ class Building(CityObject): Set building storeys number above ground :param value: int """ - self._storeys_above_ground = int(value) + if value is not None: + self._storeys_above_ground = int(value) @staticmethod def _tuple_to_point(xy_tuple): diff --git a/city_model_structure/building_demand/internal_gains.py b/city_model_structure/building_demand/internal_gains.py index 718f056f..d2342a98 100644 --- a/city_model_structure/building_demand/internal_gains.py +++ b/city_model_structure/building_demand/internal_gains.py @@ -4,6 +4,8 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca """ +from typing import Union + class InternalGains: """ @@ -17,10 +19,10 @@ class InternalGains: self._latent_fraction = None @property - def average_internal_gain(self): + def average_internal_gain(self) -> Union[None, float]: """ Get internal gains average internal gain in W/m2 - :return: float + :return: None or float """ return self._average_internal_gain @@ -28,15 +30,16 @@ class InternalGains: def average_internal_gain(self, value): """ Set internal gains average internal gain in W/m2 - :param value: float + :param value:float """ - self._average_internal_gain = float(value) + if value is not None: + self._average_internal_gain = float(value) @property - def convective_fraction(self): + def convective_fraction(self) -> Union[None, float]: """ Get internal gains convective fraction - :return: float + :return: None or float """ return self._convective_fraction @@ -46,13 +49,14 @@ class InternalGains: Set internal gains convective fraction :param value: float """ - self._convective_fraction = float(value) + if value is not None: + self._convective_fraction = float(value) @property - def radiative_fraction(self): + def radiative_fraction(self) -> Union[None, float]: """ Get internal gains radiative fraction - :return: float + :return: None or float """ return self._radiative_fraction @@ -62,13 +66,14 @@ class InternalGains: Set internal gains convective fraction :param value: float """ - self._radiative_fraction = float(value) + if value is not None: + self._radiative_fraction = float(value) @property - def latent_fraction(self): + def latent_fraction(self) -> Union[None, float]: """ Get internal gains latent fraction - :return: float + :return: None or float """ return self._latent_fraction @@ -78,4 +83,5 @@ class InternalGains: Set internal gains latent fraction :param value: float """ - self._latent_fraction = float(value) + if value is not None: + self._latent_fraction = float(value) diff --git a/city_model_structure/building_demand/layer.py b/city_model_structure/building_demand/layer.py index f1a45073..608ebeb8 100644 --- a/city_model_structure/building_demand/layer.py +++ b/city_model_structure/building_demand/layer.py @@ -4,6 +4,7 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca """ import uuid +from typing import Union from city_model_structure.building_demand.material import Material @@ -43,10 +44,10 @@ class Layer: self._material = value @property - def thickness(self): + def thickness(self) -> Union[None, float]: """ Get layer thickness in meters - :return: float + :return: None or float """ return self._thickness @@ -56,4 +57,5 @@ class Layer: Get layer thickness in meters :param value: float """ - self._thickness = float(value) + if value is not None: + self._thickness = float(value) diff --git a/city_model_structure/building_demand/material.py b/city_model_structure/building_demand/material.py index e9fccbb3..2e847597 100644 --- a/city_model_structure/building_demand/material.py +++ b/city_model_structure/building_demand/material.py @@ -4,6 +4,9 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca """ +import ast +from typing import Union + class Material: """ @@ -37,10 +40,10 @@ class Material: self._name = str(value) @property - def conductivity(self): + def conductivity(self) -> Union[None, float]: """ Get material conductivity in W/mK - :return: float + :return: None or float """ return self._conductivity @@ -50,13 +53,14 @@ class Material: Set material conductivity in W/mK :param value: float """ - self._conductivity = float(value) + if value is not None: + self._conductivity = float(value) @property - def specific_heat(self): + def specific_heat(self) -> Union[None, float]: """ Get material conductivity in J/kgK - :return: float + :return: None or float """ return self._specific_heat @@ -66,13 +70,14 @@ class Material: Get material conductivity in J/kgK :param value: float """ - self._specific_heat = float(value) + if value is not None: + self._specific_heat = float(value) @property - def density(self): + def density(self) -> Union[None, float]: """ Get material density in kg/m3 - :return: float + :return: None or float """ return self._density @@ -82,13 +87,14 @@ class Material: Set material density in kg/m3 :param value: float """ - self._density = float(value) + if value is not None: + self._density = float(value) @property - def solar_absorptance(self): + def solar_absorptance(self) -> Union[None, float]: """ Get material solar absorptance - :return: float + :return: None or float """ return self._solar_absorptance @@ -98,13 +104,14 @@ class Material: Set material solar absorptance :param value: float """ - self._solar_absorptance = float(value) + if value is not None: + self._solar_absorptance = float(value) @property - def thermal_absorptance(self): + def thermal_absorptance(self) -> Union[None, float]: """ Get material thermal absorptance - :return: float + :return: None or float """ return self._thermal_absorptance @@ -114,13 +121,14 @@ class Material: Set material thermal absorptance :param value: float """ - self._thermal_absorptance = float(value) + if value is not None: + self._thermal_absorptance = float(value) @property - def visible_absorptance(self): + def visible_absorptance(self) -> Union[None, float]: """ Get material visible absorptance - :return: float + :return: None or float """ return self._visible_absorptance @@ -130,13 +138,14 @@ class Material: Set material visible absorptance :param value: float """ - self._visible_absorptance = float(value) + if value is not None: + self._visible_absorptance = float(value) @property - def no_mass(self): + def no_mass(self) -> Union[None, bool]: """ Get material no mass flag - :return: Boolean + :return: None or Boolean """ return self._no_mass @@ -146,13 +155,14 @@ class Material: Set material no mass flag :param value: Boolean """ - self._no_mass = bool(value) + if value is not None: + self._no_mass = value @property - def thermal_resistance(self): + def thermal_resistance(self) -> Union[None, float]: """ Get material thermal resistance in m2K/W - :return: float + :return: None or float """ return self._thermal_resistance @@ -162,4 +172,5 @@ class Material: Set material thermal resistance in m2K/W :param value: float """ - self._thermal_resistance = float(value) + if value is not None: + self._thermal_resistance = float(value) diff --git a/city_model_structure/building_demand/surface.py b/city_model_structure/building_demand/surface.py index c78e5ba4..cd8a6502 100644 --- a/city_model_structure/building_demand/surface.py +++ b/city_model_structure/building_demand/surface.py @@ -62,6 +62,15 @@ class Surface: raise ValueError('Undefined surface id') return self._id + @id.setter + def id(self, value): + """ + Set the surface id + :param value: str + """ + if value is not None: + self._id = str(value) + @property def share_surfaces(self): """ @@ -69,19 +78,11 @@ class Surface: """ raise NotImplementedError - @id.setter - def id(self, value): - """ - Set the surface id - :param value: str - """ - self._id = str(value) - @property - def swr(self): + def swr(self) -> Union[None, float]: """ Get surface short wave reflectance - :return: float + :return: None or float """ return self._swr @@ -91,7 +92,8 @@ class Surface: Set surface short wave reflectance :param value: float """ - self._swr = float(value) + if value is not None: + self._swr = float(value) def _max_coord(self, axis): if axis == 'x': diff --git a/city_model_structure/building_demand/thermal_boundary.py b/city_model_structure/building_demand/thermal_boundary.py index 081bf177..7b444a14 100644 --- a/city_model_structure/building_demand/thermal_boundary.py +++ b/city_model_structure/building_demand/thermal_boundary.py @@ -129,10 +129,10 @@ class ThermalBoundary: return self._thickness @property - def outside_solar_absorptance(self): + def outside_solar_absorptance(self) -> Union[None, float]: """ Get thermal boundary outside solar absorptance - :return: float + :return: None or float """ return self._outside_solar_absorptance @@ -142,11 +142,12 @@ class ThermalBoundary: Set thermal boundary outside solar absorptance :param value: float """ - self._outside_solar_absorptance = float(value) - self._shortwave_reflectance = 1.0 - value + if value is not None: + self._outside_solar_absorptance = float(value) + self._shortwave_reflectance = 1.0 - float(value) @property - def outside_thermal_absorptance(self): + def outside_thermal_absorptance(self) -> Union[None, float]: """ Get thermal boundary outside thermal absorptance :return: float @@ -159,13 +160,14 @@ class ThermalBoundary: Set thermal boundary outside thermal absorptance :param value: float """ - self._outside_thermal_absorptance = float(value) + if value is not None: + self._outside_thermal_absorptance = float(value) @property - def outside_visible_absorptance(self): + def outside_visible_absorptance(self) -> Union[None, float]: """ Get thermal boundary outside visible absorptance - :return: float + :return: None or float """ return self._outside_visible_absorptance @@ -175,7 +177,8 @@ class ThermalBoundary: Set thermal boundary outside visible absorptance :param value: float """ - self._outside_visible_absorptance = float(value) + if value is not None: + self._outside_visible_absorptance = float(value) @property def thermal_openings(self) -> List[ThermalOpening]: @@ -203,10 +206,10 @@ class ThermalBoundary: self._thermal_openings = value @property - def construction_name(self): + def construction_name(self) -> Union[None, str]: """ Get construction name - :return: str + :return: None or str """ return self._construction_name @@ -216,7 +219,8 @@ class ThermalBoundary: Set construction name :param value: str """ - self._construction_name = str(value) + if value is not None: + self._construction_name = str(value) @property def layers(self) -> List[Layer]: @@ -243,10 +247,10 @@ class ThermalBoundary: return self._surface.type @property - def window_ratio(self): + def window_ratio(self) -> Union[None, float]: """ Get thermal boundary window ratio - :return: float + :return: None or float """ return self._window_ratio @@ -256,14 +260,15 @@ class ThermalBoundary: Set thermal boundary window ratio :param value: float """ - self._window_ratio = float(value) + if value is not None: + self._window_ratio = float(value) @property - def u_value(self): + def u_value(self) -> Union[None, float]: """ Get thermal boundary U-value in W/m2K internal and external convective coefficient in W/m2K values, can be configured at configuration.ini - :return: float + :return: None or float """ if self._u_value is None: h_i = self.hi @@ -286,13 +291,14 @@ class ThermalBoundary: Set thermal boundary U-value in W/m2K :param value: float """ - self._u_value = float(value) + if value is not None: + self._u_value = float(value) @property - def shortwave_reflectance(self): + def shortwave_reflectance(self) -> Union[None, float]: """ Get thermal boundary shortwave reflectance - :return: float + :return: None or float """ return self._shortwave_reflectance @@ -302,14 +308,15 @@ class ThermalBoundary: Set thermal boundary shortwave reflectance :param value: float """ - self._shortwave_reflectance = float(value) - self._outside_solar_absorptance = 1.0 - value + if value is not None: + self._shortwave_reflectance = float(value) + self._outside_solar_absorptance = 1.0 - float(value) @property - def hi(self): + def hi(self) -> Union[None, float]: """ Get internal convective heat transfer coefficient (W/m2K) - :return: float + :return: None or float """ return self._hi @@ -319,13 +326,14 @@ class ThermalBoundary: Set internal convective heat transfer coefficient (W/m2K) :param value: float """ - self._hi = float(value) + if value is not None: + self._hi = float(value) @property - def he(self): + def he(self) -> Union[None, float]: """ Get external convective heat transfer coefficient (W/m2K) - :return: float + :return: None or float """ return self._he @@ -335,7 +343,8 @@ class ThermalBoundary: Set external convective heat transfer coefficient (W/m2K) :param value: float """ - self._he = float(value) + if value is not None: + self._he = float(value) @property def surface_geometry(self): @@ -356,10 +365,10 @@ class ThermalBoundary: # todo: need extract information from construction library or assume them at the beginning of workflows @property - def inside_emissivity(self): + def inside_emissivity(self) -> Union[None, float]: """ Get the short wave emissivity factor of the thermal boundary's internal surface (-) - :return: float + :return: None or float """ return self._inside_emissivity @@ -369,13 +378,14 @@ class ThermalBoundary: Set short wave emissivity factor of the thermal boundary's internal surface (-) :param value: float """ - self._inside_emissivity = float(value) + if value is not None: + self._inside_emissivity = float(value) @property - def alpha_coefficient(self): + def alpha_coefficient(self) -> Union[None, float]: """ Get the long wave emissivity factor of the thermal boundary's internal surface (-) - :return: float + :return: None or float """ return self._alpha_coefficient @@ -385,13 +395,14 @@ class ThermalBoundary: Set long wave emissivity factor of the thermal boundary's internal surface (-) :param value: float """ - self._alpha_coefficient = float(value) + if value is not None: + self._alpha_coefficient = float(value) @property - def radiative_coefficient(self): + def radiative_coefficient(self) -> Union[None, float]: """ Get the radiative coefficient of the thermal boundary's external surface (-) - :return: float + :return: None or float """ return self._radiative_coefficient @@ -401,4 +412,5 @@ class ThermalBoundary: Set radiative coefficient of the thermal boundary's external surface (-) :param value: float """ - self._radiative_coefficient = float(value) + if value is not None: + self._radiative_coefficient = float(value) diff --git a/city_model_structure/building_demand/thermal_opening.py b/city_model_structure/building_demand/thermal_opening.py index 76eccc1d..0683f095 100644 --- a/city_model_structure/building_demand/thermal_opening.py +++ b/city_model_structure/building_demand/thermal_opening.py @@ -5,7 +5,7 @@ Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@conc Contributors Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca """ import uuid -from typing import TypeVar +from typing import TypeVar, Union Polygon = TypeVar('Polygon') @@ -43,10 +43,10 @@ class ThermalOpening: return self._id @property - def area(self): + def area(self) -> Union[None, float]: """ Get thermal opening area in square meters - :return: float + :return: None or float """ return self._area @@ -56,7 +56,8 @@ class ThermalOpening: Set thermal opening area in square meters :param value: float """ - self._area = float(value) + if value is not None: + self._area = float(value) @property def openable_ratio(self): @@ -73,10 +74,10 @@ class ThermalOpening: raise NotImplementedError @property - def conductivity(self): + def conductivity(self) -> Union[None, float]: """ Get thermal opening conductivity in W/mK - :return: float + :return: None or float """ return self._conductivity @@ -88,18 +89,19 @@ class ThermalOpening: """ # The code to calculate overall_u_value is duplicated here and in thickness_m. # This ensures a more robust code that returns the overall_u_value regardless the order the parameters are read. - self._conductivity = float(value) - if self._overall_u_value is None and self.thickness is not None: - h_i = self.hi - h_e = self.he - r_value = 1 / h_i + 1 / h_e + float(self.conductivity) / float(self.thickness) - self._overall_u_value = 1 / r_value + if value is not None: + self._conductivity = float(value) + if self._overall_u_value is None and self.thickness is not None: + h_i = self.hi + h_e = self.he + r_value = 1 / h_i + 1 / h_e + float(self._conductivity) / float(self.thickness) + self._overall_u_value = 1 / r_value @property - def frame_ratio(self): + def frame_ratio(self) -> Union[None, float]: """ Get thermal opening frame ratio - :return: float + :return: None or float """ return self._frame_ratio @@ -109,13 +111,14 @@ class ThermalOpening: Set thermal opening frame ratio :param value: float """ - self._frame_ratio = float(value) + if value is not None: + self._frame_ratio = float(value) @property - def g_value(self): + def g_value(self) -> Union[None, float]: """ Get thermal opening g-value - :return: float + :return: None or float """ return self._g_value @@ -125,13 +128,14 @@ class ThermalOpening: Set thermal opening g-value :param value: float """ - self._g_value = float(value) + if value is not None: + self._g_value = float(value) @property - def thickness(self): + def thickness(self) -> Union[None, float]: """ Get thermal opening thickness in meters - :return: float + :return: None or float """ return self._thickness @@ -143,18 +147,19 @@ class ThermalOpening: """ # The code to calculate overall_u_value is duplicated here and in conductivity. # This ensures a more robust code that returns the overall_u_value regardless the order the parameters are read. - self._thickness = float(value) - if self._overall_u_value is None and self.conductivity is not None: - h_i = self.hi - h_e = self.he - r_value = 1 / h_i + 1 / h_e + float(self.conductivity) / float(self.thickness) - self._overall_u_value = 1 / r_value + if value is not None: + self._thickness = float(value) + if self._overall_u_value is None and self.conductivity is not None: + h_i = self.hi + h_e = self.he + r_value = 1 / h_i + 1 / h_e + float(self.conductivity) / float(self._thickness) + self._overall_u_value = 1 / r_value @property - def front_side_solar_transmittance_at_normal_incidence(self): + def front_side_solar_transmittance_at_normal_incidence(self) -> Union[None, float]: """ Get thermal opening front side solar transmittance at normal incidence - :return: float + :return: None or float """ return self._front_side_solar_transmittance_at_normal_incidence @@ -164,13 +169,14 @@ class ThermalOpening: Set thermal opening front side solar transmittance at normal incidence :param value: float """ - self._front_side_solar_transmittance_at_normal_incidence = float(value) + if value is not None: + self._front_side_solar_transmittance_at_normal_incidence = float(value) @property - def back_side_solar_transmittance_at_normal_incidence(self): + def back_side_solar_transmittance_at_normal_incidence(self) -> Union[None, float]: """ Get thermal opening back side solar transmittance at normal incidence - :return: float + :return: None or float """ return self._back_side_solar_transmittance_at_normal_incidence @@ -180,13 +186,14 @@ class ThermalOpening: Set thermal opening back side solar transmittance at normal incidence :param value: float """ - self._back_side_solar_transmittance_at_normal_incidence = float(value) + if value is not None: + self._back_side_solar_transmittance_at_normal_incidence = float(value) @property - def overall_u_value(self): + def overall_u_value(self) -> Union[None, float]: """ Get thermal opening overall U-value in W/m2K - :return: float + :return: None or float """ return self._overall_u_value @@ -196,13 +203,14 @@ class ThermalOpening: Set thermal opening overall U-value in W/m2K :param value: float """ - self._overall_u_value = float(value) + if value is not None: + self._overall_u_value = float(value) @property - def hi(self): + def hi(self) -> Union[None, float]: """ Get internal convective heat transfer coefficient (W/m2K) - :return: float + :return: None or float """ return self._hi @@ -212,13 +220,14 @@ class ThermalOpening: Set internal convective heat transfer coefficient (W/m2K) :param value: float """ - self._hi = float(value) + if value is not None: + self._hi = float(value) @property - def he(self): + def he(self) -> Union[None, float]: """ Get external convective heat transfer coefficient (W/m2K) - :return: float + :return: None or float """ return self._he @@ -228,7 +237,8 @@ class ThermalOpening: Set external convective heat transfer coefficient (W/m2K) :param value: float """ - self._he = float(value) + if value is not None: + self._he = float(value) @property def surface_geometry(self) -> Polygon: @@ -240,10 +250,10 @@ class ThermalOpening: # todo: need extract information from construction library or assume them at the beginning of workflows @property - def inside_emissivity(self): + def inside_emissivity(self) -> Union[None, float]: """ Get the short wave emissivity factor of the thermal opening's internal surface (-) - :return: float + :return: None or float """ return self._inside_emissivity @@ -253,13 +263,14 @@ class ThermalOpening: Set short wave emissivity factor of the thermal opening's internal surface (-) :param value: float """ - self._inside_emissivity = float(value) + if value is not None: + self._inside_emissivity = float(value) @property - def alpha_coefficient(self): + def alpha_coefficient(self) -> Union[None, float]: """ Get the long wave emissivity factor of the thermal opening's internal surface (-) - :return: float + :return: None or float """ return self._alpha_coefficient @@ -269,13 +280,14 @@ class ThermalOpening: Set long wave emissivity factor of the thermal opening's internal surface (-) :param value: float """ - self._alpha_coefficient = float(value) + if value is not None: + self._alpha_coefficient = float(value) @property - def radiative_coefficient(self): + def radiative_coefficient(self) -> Union[None, float]: """ Get the radiative coefficient of the thermal opening's external surface (-) - :return: float + :return: None or float """ return self._radiative_coefficient @@ -285,4 +297,5 @@ class ThermalOpening: Set radiative coefficient of the thermal opening's external surface (-) :param value: float """ - self._radiative_coefficient = float(value) + if value is not None: + self._radiative_coefficient = float(value) diff --git a/city_model_structure/building_demand/thermal_zone.py b/city_model_structure/building_demand/thermal_zone.py index 79d72148..a3ad26e1 100644 --- a/city_model_structure/building_demand/thermal_zone.py +++ b/city_model_structure/building_demand/thermal_zone.py @@ -5,8 +5,9 @@ Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@conc Contributors Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca """ import uuid -from typing import List, TypeVar +from typing import List, TypeVar, Union from city_model_structure.building_demand.usage_zone import UsageZone +import ast ThermalBoundary = TypeVar('ThermalBoundary') Polyhedron = TypeVar('Polyhedron') @@ -42,13 +43,22 @@ class ThermalZone: return self._id @property - def is_mechanically_ventilated(self): + def is_mechanically_ventilated(self) -> Union[None, bool]: """ Get thermal zone mechanical ventilation flag - :return: Boolean + :return: None or Boolean """ return self._is_mechanically_ventilated + @is_mechanically_ventilated.setter + def is_mechanically_ventilated(self, value): + """ + Set thermal zone mechanical ventilation flag + :param value: Boolean + """ + if value is not None: + self._is_mechanically_ventilated = ast.literal_eval(value) + @property def floor_area(self): """ @@ -72,10 +82,10 @@ class ThermalZone: return self._thermal_boundaries @property - def additional_thermal_bridge_u_value(self): + def additional_thermal_bridge_u_value(self) -> Union[None, float]: """ Get thermal zone additional thermal bridge u value W/m2K - :return: float + :return: None or float """ return self._additional_thermal_bridge_u_value @@ -85,13 +95,14 @@ class ThermalZone: Set thermal zone additional thermal bridge u value W/m2K :param value: float """ - self._additional_thermal_bridge_u_value = float(value) + if value is not None: + self._additional_thermal_bridge_u_value = float(value) @property - def effective_thermal_capacity(self): + def effective_thermal_capacity(self) -> Union[None, float]: """ Get thermal zone effective thermal capacity in J/m2K - :return: float + :return: None or float """ return self._effective_thermal_capacity @@ -101,13 +112,14 @@ class ThermalZone: Set thermal zone effective thermal capacity in J/m2K :param value: float """ - self._effective_thermal_capacity = float(value) + if value is not None: + self._effective_thermal_capacity = float(value) @property - def indirectly_heated_area_ratio(self): + def indirectly_heated_area_ratio(self) -> Union[None, float]: """ Get thermal zone indirectly heated area ratio - :return: float + :return: None or float """ return self._indirectly_heated_area_ratio @@ -117,13 +129,14 @@ class ThermalZone: Set thermal zone indirectly heated area ratio :param value: float """ - self._indirectly_heated_area_ratio = float(value) + if value is not None: + self._indirectly_heated_area_ratio = float(value) @property - def infiltration_rate_system_on(self): + def infiltration_rate_system_on(self) -> Union[None, float]: """ Get thermal zone infiltration rate system on in air changes per hour (ACH) - :return: float + :return: None or float """ return self._infiltration_rate_system_on @@ -133,13 +146,14 @@ class ThermalZone: Set thermal zone infiltration rate system on in air changes per hour (ACH) :param value: float """ - self._infiltration_rate_system_on = float(value) + if value is not None: + self._infiltration_rate_system_on = float(value) @property - def infiltration_rate_system_off(self): + def infiltration_rate_system_off(self) -> Union[None, float]: """ Get thermal zone infiltration rate system off in air changes per hour (ACH) - :return: float + :return: None or float """ return self._infiltration_rate_system_off @@ -149,7 +163,8 @@ class ThermalZone: Set thermal zone infiltration rate system on in air changes per hour (ACH) :param value: float """ - self._infiltration_rate_system_off = float(value) + if value is not None: + self._infiltration_rate_system_off = float(value) @property def usage_zones(self) -> List[UsageZone]: @@ -184,10 +199,10 @@ class ThermalZone: return self._volume_geometry @property - def ordinate_number(self): + def ordinate_number(self) -> Union[None, int]: """ Get the order in which the thermal_zones need to be enumerated - :return: int + :return: None or int """ return self._ordinate_number @@ -197,4 +212,5 @@ class ThermalZone: Set a specific order of the zones to be called :param value: int """ - self._ordinate_number = int(value) + if value is not None: + self._ordinate_number = int(value) diff --git a/city_model_structure/building_demand/usage_zone.py b/city_model_structure/building_demand/usage_zone.py index f265c697..a2c16435 100644 --- a/city_model_structure/building_demand/usage_zone.py +++ b/city_model_structure/building_demand/usage_zone.py @@ -5,7 +5,8 @@ Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.mons Contributors Guille Gutierrez guillermo.gutierrezmorote@concordia.ca """ import uuid -from typing import List, TypeVar +from typing import List, TypeVar, Union +import ast InternalGains = TypeVar('InternalGains') Occupants = TypeVar('Occupants') @@ -24,6 +25,7 @@ class UsageZone: self._heating_setpoint = None self._heating_setback = None self._cooling_setpoint = None + self._occupancy_density = None self._hours_day = None self._days_year = None self._dhw_average_volume_pers_day = None @@ -64,10 +66,10 @@ class UsageZone: self._internal_gains = value @property - def heating_setpoint(self): + def heating_setpoint(self) -> Union[None, float]: """ Get usage zone heating set point in Celsius - :return: float + :return: None or float """ return self._heating_setpoint @@ -77,13 +79,14 @@ class UsageZone: Set usage zone heating set point in Celsius :param value: float """ - self._heating_setpoint = float(value) + if value is not None: + self._heating_setpoint = float(value) @property - def heating_setback(self): + def heating_setback(self) -> Union[None, float]: """ Get usage zone heating setback in Celsius - :return: float + :return: None or float """ return self._heating_setback @@ -93,13 +96,14 @@ class UsageZone: Set usage zone heating setback in Celsius :param value: float """ - self._heating_setback = float(value) + if value is not None: + self._heating_setback = float(value) @property - def cooling_setpoint(self): + def cooling_setpoint(self) -> Union[None, float]: """ Get usage zone cooling setpoint in Celsius - :return: float + :return: None or float """ return self._cooling_setpoint @@ -109,13 +113,14 @@ class UsageZone: Set usage zone cooling setpoint in Celsius :param value: float """ - self._cooling_setpoint = float(value) + if value is not None: + self._cooling_setpoint = float(value) @property - def hours_day(self): + def hours_day(self) -> Union[None, float]: """ Get usage zone usage hours per day - :return: float + :return: None or float """ return self._hours_day @@ -125,13 +130,14 @@ class UsageZone: Set usage zone usage hours per day :param value: float """ - self._hours_day = float(value) + if value is not None: + self._hours_day = float(value) @property - def days_year(self): + def days_year(self) -> Union[None, float]: """ Get usage zone usage days per year - :return: float + :return: None or float """ return self._days_year @@ -141,13 +147,14 @@ class UsageZone: Set usage zone usage days per year :param value: float """ - self._days_year = float(value) + if value is not None: + self._days_year = float(value) @property - def mechanical_air_change(self): + def mechanical_air_change(self) -> Union[None, float]: """ Get usage zone mechanical air change in air change per hour (ACH) - :return: float + :return: None or float """ return self._mechanical_air_change @@ -157,13 +164,14 @@ class UsageZone: Set usage zone mechanical air change in air change per hour (ACH) :param value: float """ - self._mechanical_air_change = float(value) + if value is not None: + self._mechanical_air_change = float(value) @property - def usage(self): + def usage(self) -> Union[None, str]: """ Get usage zone usage - :return: str + :return: None or str """ return self._usage @@ -173,7 +181,8 @@ class UsageZone: Set usage zone usage :param value: str """ - self._usage = str(value) + if value is not None: + self._usage = str(value) @property def occupants(self) -> List[Occupants]: @@ -208,26 +217,44 @@ class UsageZone: self._schedules = values @property - def dhw_average_volume_pers_day(self): + def occupancy_density(self) -> Union[None, float]: + """ + Get density in persons per m2 + :return: None or float + """ + return self._occupancy_density + + @occupancy_density.setter + def occupancy_density(self, value): + """ + Set density in persons per m2 + :param value: float + """ + if value is not None: + self._occupancy_density = float(value) + + @property + def dhw_average_volume_pers_day(self) -> Union[None, float]: """ Get average DHW consumption in cubic meters per person per day - :return: float + :return: None or float """ return self._dhw_average_volume_pers_day @dhw_average_volume_pers_day.setter - def dhw_average_volume_pers_day(self, values): + def dhw_average_volume_pers_day(self, value): """ Set average DHW consumption in cubic meters per person per day - :param values: float + :param value: float """ - self._dhw_average_volume_pers_day = float(values) + if value is not None: + self._dhw_average_volume_pers_day = float(value) @property - def dhw_preparation_temperature(self): + def dhw_preparation_temperature(self) -> Union[None, float]: """ Get preparation temperature of the DHW in Celsius - :return: float + :return: None or float """ return self._dhw_preparation_temperature @@ -237,13 +264,14 @@ class UsageZone: Set preparation temperature of the DHW in Celsius :param value: float """ - self._dhw_preparation_temperature = float(value) + if value is not None: + self._dhw_preparation_temperature = float(value) @property - def electrical_app_average_consumption_sqm_year(self): + def electrical_app_average_consumption_sqm_year(self) -> Union[None, float]: """ Get average consumption of electrical appliances in Joules hour per square meter and year (J/m2yr) - :return: float + :return: None or float """ return self._electrical_app_average_consumption_sqm_year @@ -253,7 +281,8 @@ class UsageZone: Set average consumption of electrical appliances in Joules per square meter and year (J/m2yr) :param value: float """ - self._electrical_app_average_consumption_sqm_year = float(value) + if value is not None: + self._electrical_app_average_consumption_sqm_year = float(value) @property def volume_geometry(self) -> Polyhedron: @@ -264,10 +293,10 @@ class UsageZone: return self._volume_geometry @property - def volume(self): + def volume(self) -> Union[None, float]: """ Get the volume in cubic meters - :return: float + :return: None or float """ return self._volume @@ -277,13 +306,14 @@ class UsageZone: Set volume in cubic meters :param value: float """ - self._volume = float(value) + if value is not None: + self._volume = float(value) @property - def is_heated(self): + def is_heated(self) -> Union[None, bool]: """ Get thermal zone heated flag - :return: Boolean + :return: None or Boolean """ return self._is_heated @@ -293,13 +323,14 @@ class UsageZone: Set thermal zone heated flag :param value: Boolean """ - self._is_heated = bool(value) + if value is not None: + self._is_heated = ast.literal_eval(value) @property - def is_cooled(self): + def is_cooled(self) -> Union[None, bool]: """ Get thermal zone cooled flag - :return: Boolean + :return: None or Boolean """ return self._is_cooled @@ -309,4 +340,5 @@ class UsageZone: Set thermal zone cooled flag :param value: Boolean """ - self._is_cooled = bool(value) + if value is not None: + self._is_cooled = ast.literal_eval(value) diff --git a/city_model_structure/city.py b/city_model_structure/city.py index 9ffb8135..3b7e2cd2 100644 --- a/city_model_structure/city.py +++ b/city_model_structure/city.py @@ -7,10 +7,10 @@ from __future__ import annotations import sys import pickle import math -from typing import List, Union, TypeVar +from typing import List, Union import pyproj from pyproj import Transformer - +from pathlib import Path from city_model_structure.building import Building from city_model_structure.city_object import CityObject @@ -21,9 +21,6 @@ from helpers.geometry_helper import GeometryHelper from helpers.location import Location -Path = TypeVar('Path') - - class City: """ City class @@ -80,10 +77,10 @@ class City: return self._get_location().city @property - def climate_reference_city(self): + def climate_reference_city(self) -> Union[None, str]: """ Get the name for the climatic information reference city - :return: str + :return: None or str """ return self._climate_reference_city @@ -93,13 +90,14 @@ class City: Set the name for the climatic information reference city :param value: str """ - self._climate_reference_city = str(value) + if value is not None: + self._climate_reference_city = str(value) @property - def climate_file(self) -> Path: + def climate_file(self) -> Union[None, Path]: """ Get the climate file full path - :return: Path + :return: None or Path """ return self._climate_file @@ -109,7 +107,8 @@ class City: Set the climate file full path :param value: Path """ - self._climate_file = Path(value) + if value is not None: + self._climate_file = Path(value) @property def city_objects(self) -> Union[List[CityObject], None]: @@ -211,10 +210,10 @@ class City: self._buildings.remove(city_object) @property - def srs_name(self): + def srs_name(self) -> Union[None, str]: """ Get city srs name - :return: str + :return: None or str """ return self._srs_name @@ -224,7 +223,8 @@ class City: Set city name :param value:str """ - self._name = str(value) + if value is not None: + self._name = str(value) @staticmethod def load(city_filename) -> City: @@ -267,10 +267,10 @@ class City: return selected_region_city @property - def latitude(self): + def latitude(self) -> Union[None, float]: """ Get city latitude in degrees - :return: float + :return: None or float """ return self._latitude @@ -280,13 +280,14 @@ class City: Set city latitude in degrees :parameter value: float """ - self._latitude = float(value) + if value is not None: + self._latitude = float(value) @property - def longitude(self): + def longitude(self) -> Union[None, float]: """ Get city longitude in degrees - :return: float + :return: None or float """ return self._longitude @@ -296,13 +297,14 @@ class City: Set city longitude in degrees :parameter value: float """ - self._longitude = float(value) + if value is not None: + self._longitude = float(value) @property - def time_zone(self): + def time_zone(self) -> Union[None, float]: """ Get city time_zone - :return: float + :return: None or float """ return self._time_zone @@ -312,7 +314,8 @@ class City: Set city time_zone :parameter value: float """ - self._time_zone = float(value) + if value is not None: + self._time_zone = float(value) @property def buildings_clusters(self) -> Union[List[BuildingsCluster], None]: diff --git a/city_model_structure/energy_systems/heat_pump.py b/city_model_structure/energy_systems/heat_pump.py index 99443e83..753fa2ee 100644 --- a/city_model_structure/energy_systems/heat_pump.py +++ b/city_model_structure/energy_systems/heat_pump.py @@ -4,6 +4,8 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca """ +from typing import Union + class HeatPump: """ @@ -14,10 +16,10 @@ class HeatPump: self._seasonal_mean_coverage_factor = None @property - def seasonal_mean_cop(self): + def seasonal_mean_cop(self) -> Union[None, float]: """ Get seasonal mean COP (-) - :return: float + :return: None or float """ return self._seasonal_mean_cop @@ -27,13 +29,14 @@ class HeatPump: Set seasonal mean COP (-) :param value: float """ - self._seasonal_mean_cop = float(value) + if value is not None: + self._seasonal_mean_cop = float(value) @property - def seasonal_mean_coverage_factor(self): + def seasonal_mean_coverage_factor(self) -> Union[None, float]: """ Get percentage of demand covered by the hp (-) - :return: float + :return: None or float """ return self._seasonal_mean_coverage_factor @@ -43,4 +46,5 @@ class HeatPump: Set percentage of demand covered by the hp (-) :return: float """ - self._seasonal_mean_coverage_factor = float(value) + if value is not None: + self._seasonal_mean_coverage_factor = float(value) diff --git a/city_model_structure/energy_systems/pv_system.py b/city_model_structure/energy_systems/pv_system.py index 47f4909b..7e6b3870 100644 --- a/city_model_structure/energy_systems/pv_system.py +++ b/city_model_structure/energy_systems/pv_system.py @@ -4,6 +4,8 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca """ +from typing import Union + class PvSystem: """ @@ -18,10 +20,10 @@ class PvSystem: self._electricity_generation = None @property - def modules_mean_seasonal_efficiency(self): + def modules_mean_seasonal_efficiency(self) -> Union[None, float]: """ Get mean modules efficiency (-) - :return: float + :return: None or float """ return self._modules_mean_seasonal_efficiency @@ -31,13 +33,14 @@ class PvSystem: Set mean modules efficiency (-) :param value: float """ - self._modules_mean_seasonal_efficiency = float(value) + if value is not None: + self._modules_mean_seasonal_efficiency = float(value) @property - def total_area(self): + def total_area(self) -> Union[None, float]: """ Get total modules area in square meters - :return: float + :return: None or float """ return self._total_area @@ -47,13 +50,14 @@ class PvSystem: Set total modules area in square meters :param value: float """ - self._total_area = float(value) + if value is not None: + self._total_area = float(value) @property - def module_area(self): + def module_area(self) -> Union[None, float]: """ Get module area in square meters - :return: float + :return: None or float """ return self._module_area @@ -63,13 +67,14 @@ class PvSystem: Set module area in square meters :param value: float """ - self._module_area = float(value) + if value is not None: + self._module_area = float(value) @property - def number_of_modules(self): + def number_of_modules(self) -> Union[None, int]: """ Get number of modules - :return: int + :return: None or int """ return self._number_of_modules @@ -79,13 +84,14 @@ class PvSystem: Set number of modules :param value: int """ - self._number_of_modules = int(value) + if value is not None: + self._number_of_modules = int(value) @property - def overall_system_performance_ratio(self): + def overall_system_performance_ratio(self) -> Union[None, float]: """ Get overall system performance ratio (-) - :return: float + :return: None or float """ return self._overall_system_performance_ratio @@ -95,13 +101,14 @@ class PvSystem: Set overall system performance ratio (-) :param value: float """ - self._overall_system_performance_ratio = float(value) + if value is not None: + self._overall_system_performance_ratio = float(value) @property - def electricity_generation(self): + def electricity_generation(self) -> Union[None, float]: """ Get electricity generation in J - :return: float + :return: None or float """ return self._electricity_generation @@ -111,4 +118,5 @@ class PvSystem: Set electricity generation in J :param value: float """ - self._electricity_generation = float(value) + if value is not None: + self._electricity_generation = float(value) diff --git a/city_model_structure/iot/sensor.py b/city_model_structure/iot/sensor.py index c3919d80..4eceafd1 100644 --- a/city_model_structure/iot/sensor.py +++ b/city_model_structure/iot/sensor.py @@ -23,6 +23,8 @@ class Sensor: Get sensor name :return: str """ + if self._name is None: + raise ValueError('Undefined sensor name') return self._name @name.setter @@ -31,7 +33,8 @@ class Sensor: Set sensor name :param value: str """ - self._name = str(value) + if value is not None: + self._name = str(value) @property def type(self): diff --git a/city_model_structure/transport/connection.py b/city_model_structure/transport/connection.py index 7c31f19b..093fb4b8 100644 --- a/city_model_structure/transport/connection.py +++ b/city_model_structure/transport/connection.py @@ -5,6 +5,10 @@ Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.mons Contributor Milad milad.aghamohamadnia@concordia.ca Contributor Guille guille.gutierrezmorote@concordia.ca """ + +import ast +from typing import Union + from city_model_structure.attributes.edge import Edge from city_model_structure.transport.lane import Lane @@ -87,10 +91,10 @@ class Connection: self._to_lane = value @property - def pass_not_wait(self): + def pass_not_wait(self) -> Union[None, bool]: """ Get if the vehicles which pass this (lane to lane) connection will not wait - :return: Boolean + :return: None or Boolean """ return self._pass @@ -100,13 +104,14 @@ class Connection: Set if the vehicles which pass this (lane to lane) connection will not wait :param value: Boolean """ - self._pass = bool(value) + if value is not None: + self._pass = ast.literal_eval(value) @property - def keep_clear(self): + def keep_clear(self) -> Union[None, bool]: """ Get if vehicles which pass this (lane to lane) connection should keep the intersection clear - :return: Boolean + :return: None or Boolean """ return self._keep_clear @@ -116,4 +121,5 @@ class Connection: Set if vehicles which pass this (lane to lane) connection should keep the intersection clear :param value: Boolean """ - self._keep_clear = bool(value) + if value is not None: + self._keep_clear = ast.literal_eval(value) diff --git a/city_model_structure/transport/crossing.py b/city_model_structure/transport/crossing.py index 494c658b..9a28c8f8 100644 --- a/city_model_structure/transport/crossing.py +++ b/city_model_structure/transport/crossing.py @@ -6,7 +6,8 @@ Contributor Milad milad.aghamohamadnia@concordia.ca Contributor Guille guille.gutierrezmorote@concordia.ca """ -from typing import List +import ast +from typing import List, Union from city_model_structure.transport.traffic_node import TrafficNode @@ -22,10 +23,10 @@ class Crossing(TrafficNode): self._shape = shape @property - def priority(self): + def priority(self) -> Union[None, bool]: """ Get whether the pedestrians have priority over the vehicles - :return: bool + :return: None or bool """ return self._priority @@ -35,13 +36,14 @@ class Crossing(TrafficNode): Set whether the pedestrians have priority over the vehicles :param value: bool """ - self._priority = bool(value) + if value is not None: + self._priority = ast.literal_eval(value) @property - def width(self): + def width(self) -> Union[None, float]: """ Get crossing width in meters - :return: float + :return: None or float """ return self._width @@ -51,13 +53,14 @@ class Crossing(TrafficNode): Set crossing width in meters :param value: float """ - self._width = float(value) + if value is not None: + self._width = float(value) @property - def shape(self) -> List[List[float]]: + def shape(self) -> Union[None, List[List[float]]]: """ Get the list of positions - :return: [[x, y, (z)]] + :return: None or [[x, y, (z)]] """ return self._shape @@ -67,4 +70,5 @@ class Crossing(TrafficNode): Set the list of positions :param value: [[x, y, (z)]] """ - self._shape = [[float(i) for i in value]] + if value is not None: + self._shape = [[float(i) for i in value]] diff --git a/city_model_structure/transport/lane.py b/city_model_structure/transport/lane.py index 76199093..d68bcca0 100644 --- a/city_model_structure/transport/lane.py +++ b/city_model_structure/transport/lane.py @@ -5,7 +5,7 @@ Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.mons Contributor Milad milad.aghamohamadnia@concordia.ca """ -from typing import List +from typing import List, Union class Lane: @@ -23,11 +23,11 @@ class Lane: self._width = None @property - def index(self): + def index(self) -> Union[None, int]: """ Get lane index The enumeration index of the lane (0 is the rightmost lane, -1 is the leftmost one) - :return: int + :return: None or int """ return self._index @@ -38,13 +38,14 @@ class Lane: The enumeration index of the lane (0 is the rightmost lane, -1 is the leftmost one) :param value: int """ - self._index = int(value) + if value is not None: + self._index = int(value) @property - def allow(self) -> List[str]: + def allow(self) -> Union[None, List[str]]: """ Get the list of allowed vehicle classes - :return: [str] + :return: None or [str] """ return self._allow @@ -54,13 +55,14 @@ class Lane: Set the list of allowed vehicle classes setter :param value: [str] """ - self._allow = [str(i) for i in value] + if value is not None: + self._allow = [str(i) for i in value] @property - def disallow(self) -> List[str]: + def disallow(self) -> Union[None, List[str]]: """ Get the list of not allowed vehicle classes - :return: [str] + :return: None or [str] """ return self._disallow @@ -70,13 +72,14 @@ class Lane: Get the list of not allowed vehicle classes setter :param value: [str] """ - self._disallow = [str(i) for i in value] + if value is not None: + self._disallow = [str(i) for i in value] @property - def change_left(self) -> List[str]: + def change_left(self) -> Union[None, List[str]]: """ Get the list of vehicle classes that may change left from this lane - :return: [str] + :return: None or [str] """ return self._change_left @@ -86,13 +89,14 @@ class Lane: Set the list of vehicle classes that may change left from this lane :param value: [str] """ - self._change_left = [str(i) for i in value] + if value is not None: + self._change_left = [str(i) for i in value] @property - def change_right(self) -> List[str]: + def change_right(self) -> Union[None, List[str]]: """ Get the list of vehicle classes that may change right from this lane - :return: [str] + :return: None or [str] """ return self._change_right @@ -102,13 +106,14 @@ class Lane: Set the list of vehicle classes that may change right from this lane :param value: [str] """ - self._change_right = [str(i) for i in value] + if value is not None: + self._change_right = [str(i) for i in value] @property - def speed(self): + def speed(self) -> Union[None, float]: """ Get the lane speed in m/s - :return: float + :return: None or float """ return self._speed @@ -118,13 +123,14 @@ class Lane: Set the lane speed in m/s :param value: float """ - self._speed = float(value) + if value is not None: + self._speed = float(value) @property - def width(self): + def width(self) -> Union[None, float]: """ Get the lane width in meters - :return: float + :return: None or float """ return self._width @@ -134,4 +140,5 @@ class Lane: Set the lane width in meters :param value: float """ - self._width = float(value) + if value is not None: + self._width = float(value) diff --git a/city_model_structure/transport/phase.py b/city_model_structure/transport/phase.py index 95164606..559e0834 100644 --- a/city_model_structure/transport/phase.py +++ b/city_model_structure/transport/phase.py @@ -5,7 +5,7 @@ Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.mons Contributor Milad milad.aghamohamadnia@concordia.ca """ -from typing import List +from typing import List, Union class Phase: @@ -22,10 +22,10 @@ class Phase: self._next = None @property - def duration(self): + def duration(self) -> Union[None, int]: """ Get phase duration in seconds - :return: int + :return: None or int """ return self._duration @@ -35,13 +35,14 @@ class Phase: Set phase duration in seconds :param value: int """ - self._duration = int(value) + if value is not None: + self._duration = int(value) @property - def state(self): + def state(self) -> Union[None, List[str]]: """ Get the list of signal states - :return: [str] + :return: None or [str] """ return self._state @@ -51,13 +52,14 @@ class Phase: Set the list of signal states :param value: [str] """ - self._state = [str(i) for i in value] + if value is not None: + self._state = [str(i) for i in value] @property - def min_duration(self): + def min_duration(self) -> Union[None, int]: """ Get phase minimum duration in seconds - :return: int + :return: None or int """ if self._min_duration is None: self._min_duration = self._duration @@ -69,13 +71,14 @@ class Phase: Set phase minimum duration in seconds :param value: int """ - self._min_duration = int(value) + if value is not None: + self._min_duration = int(value) @property - def max_duration(self): + def max_duration(self) -> Union[None, int]: """ Get phase maximum duration in seconds - :return: int + :return: None or int """ if self._max_duration is None: self._max_duration = self._duration @@ -87,13 +90,14 @@ class Phase: Set phase maximum duration in seconds :param value: int """ - self._max_duration = int(value) + if value is not None: + self._max_duration = int(value) @property - def name(self): + def name(self) -> Union[None, str]: """ Get phase name - :return: str + :return: None or str """ return self._name @@ -103,16 +107,17 @@ class Phase: Set phase name :param value: str """ - self._name = str(value) + if value is not None: + self._name = str(value) @property - def next(self) -> List[int]: + def next(self) -> Union[None, List[int]]: """ Get the next phase in the cycle after the current. This is useful when adding extra transition phases to a traffic light plan which are not part of every cycle. Traffic lights of type 'actuated' can make use of a list of indices for selecting among alternative successor phases. - :return: [int] + :return: None or [int] """ return self._next @@ -125,4 +130,5 @@ class Phase: successor phases. :param value: [int] """ - self._next = [int(i) for i in value] + if value is not None: + self._next = [int(i) for i in value] diff --git a/city_model_structure/transport/traffic_edge.py b/city_model_structure/transport/traffic_edge.py index b403b80e..5f8578e5 100644 --- a/city_model_structure/transport/traffic_edge.py +++ b/city_model_structure/transport/traffic_edge.py @@ -6,7 +6,7 @@ Contributor Milad milad.aghamohamadnia@concordia.ca Contributor Guille guille.gutierrezmorote@concordia.ca """ -from typing import List +from typing import List, Union from city_model_structure.attributes.edge import Edge from city_model_structure.transport.lane import Lane @@ -54,11 +54,11 @@ class TrafficEdge(Edge): self._lanes = value @property - def priority(self): + def priority(self) -> Union[None, int]: """ Get the priority between different road types. It starts with one; higher numbers represent more important roads. - :return: int + :return: None or int """ return self._priority @@ -69,13 +69,14 @@ class TrafficEdge(Edge): It starts with one; higher numbers represent more important roads. :param value: int """ - self._priority = int(value) + if value is not None: + self._priority = int(value) @property - def speed(self): + def speed(self) -> Union[None, float]: """ Get he speed limit in m/s - :return: float + :return: None or float """ return self._speed @@ -85,13 +86,14 @@ class TrafficEdge(Edge): Set the speed limit in m/s :param value: float """ - self._speed = float(value) + if value is not None: + self._speed = float(value) @property - def length(self): + def length(self) -> Union[None, float]: """ Get the lane length in meters - :return: float + :return: None or float """ return self._length @@ -101,13 +103,14 @@ class TrafficEdge(Edge): Set the lane length in meters :param value: float """ - self._length = float(value) + if value is not None: + self._length = float(value) @property - def allows(self) -> List[str]: + def allows(self) -> Union[None, List[str]]: """ Get the list of allowed vehicle classes - :return: [str] + :return: None or [str] """ return self._allows @@ -117,13 +120,14 @@ class TrafficEdge(Edge): Set the list of allowed vehicle classes :param value: [str] """ - self._allows = [str(i) for i in value] + if value is not None: + self._allows = [str(i) for i in value] @property - def disallows(self) -> List[str]: + def disallows(self) -> Union[None, List[str]]: """ Get the list of not allowed vehicle classes - :return: [str] + :return: None or [str] """ return self._disallows @@ -133,4 +137,5 @@ class TrafficEdge(Edge): Set the list of not allowed vehicle classes :param value: [str] """ - self._disallows = [str(i) for i in value] + if value is not None: + self._disallows = [str(i) for i in value] diff --git a/city_model_structure/transport/traffic_light.py b/city_model_structure/transport/traffic_light.py index 9ad9f2da..7b7d4621 100644 --- a/city_model_structure/transport/traffic_light.py +++ b/city_model_structure/transport/traffic_light.py @@ -6,7 +6,8 @@ Contributor Milad milad.aghamohamadnia@concordia.ca Contributor Guille guille.gutierrezmorote@concordia.ca """ -from typing import List +import ast +from typing import List, Union from city_model_structure.transport.phase import Phase from city_model_structure.transport.traffic_node import TrafficNode @@ -24,10 +25,10 @@ class TrafficLight(TrafficNode): self._phases = phases @property - def right_on_red(self): + def right_on_red(self) -> Union[None, bool]: """ Get if is possible to turn right when the traffic light is red - :return: Boolean + :return: None or Boolean """ return self._right_on_red @@ -37,13 +38,14 @@ class TrafficLight(TrafficNode): Get if is possible to turn right when the traffic light is red :param value: Boolean """ - self._right_on_red = bool(value) + if value is not None: + self._right_on_red = ast.literal_eval(value) @property - def offset(self): + def offset(self) -> Union[None, int]: """ Get program initial time offset - :return: int + :return: None or int """ return self._offset @@ -53,7 +55,8 @@ class TrafficLight(TrafficNode): Set program initial time offset :param value: int """ - self._offset = int(value) + if value is not None: + self._offset = int(value) @property def phases(self) -> List[Phase]: diff --git a/city_model_structure/transport/walkway_node.py b/city_model_structure/transport/walkway_node.py index 066cd2ad..36ec90c6 100644 --- a/city_model_structure/transport/walkway_node.py +++ b/city_model_structure/transport/walkway_node.py @@ -6,7 +6,7 @@ Contributor Milad milad.aghamohamadnia@concordia.ca Contributor Guille guille.gutierrezmorote@concordia.ca """ -from typing import List +from typing import List, Union from city_model_structure.transport.traffic_node import TrafficNode @@ -20,10 +20,10 @@ class WalkwayNode(TrafficNode): self._shape = shape @property - def shape(self) -> List[List[float]]: + def shape(self) -> Union[None, List[List[float]]]: """ Get the list of positions - :return: [[x, y, (z)]] + :return: None or [[x, y, (z)]] """ return self._shape @@ -33,4 +33,5 @@ class WalkwayNode(TrafficNode): Set the list of positions :param value: [[x, y, (z)]] """ - self._shape = [[float(i) for i in value]] + if value is not None: + self._shape = [[float(i) for i in value]]