From 145520c8a289ccacb278a89867d7afdc5c1b709d Mon Sep 17 00:00:00 2001 From: Guille Date: Thu, 11 Jun 2020 15:45:11 -0400 Subject: [PATCH] Add code comment to the classes and improve overall quality --- city_model_structure/surface.py | 16 +-- city_model_structure/thermal_boundary.py | 109 +++++++++++++++++- city_model_structure/thermal_opening.py | 109 +++++++++++++++--- city_model_structure/usage_zone.py | 65 ++++++++++- geometry/geometry_factory.py | 12 +- geometry/geometry_feeders/city_gml.py | 13 ++- helpers/configuration.py | 40 +++++++ helpers/geometry.py | 28 +++++ physics/physics_factory.py | 19 ++- .../helpers/us_pluto_to_function.py | 3 + .../helpers/us_to_library_types.py | 20 +++- .../us_base_physics_parameters.py | 27 +++-- .../us_new_york_city_physics_parameters.py | 3 + .../physics_feeders/us_physics_parameters.py | 3 + pylintrc | 3 + tests/test_geometry_factory.py | 44 ++++++- tests/test_physics_factory.py | 5 +- 17 files changed, 458 insertions(+), 61 deletions(-) diff --git a/city_model_structure/surface.py b/city_model_structure/surface.py index 384ea78b..0776461d 100644 --- a/city_model_structure/surface.py +++ b/city_model_structure/surface.py @@ -4,10 +4,10 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca """ from __future__ import annotations +from typing import Union import numpy as np import pyny3d.geoms as pn from helpers.geometry import Geometry -from typing import Union class Surface: @@ -207,9 +207,9 @@ class Surface: def _is_almost_same_terrain(self, terrain_points, ground_points): equal = 0 - for t in terrain_points: - for g in ground_points: - if self._geometry.almost_equal(t, g): + for terrain_point in terrain_points: + for ground_point in ground_points: + if self._geometry.almost_equal(terrain_point, ground_point): equal += 1 return equal == len(terrain_points) @@ -250,8 +250,8 @@ class Surface: """ if self._normal is None: points = self.points - n = np.cross(points[1] - points[0], points[2] - points[0]) - self._normal = n / np.linalg.norm(n) + cross_product = np.cross(points[1] - points[0], points[2] - points[0]) + self._normal = cross_product / np.linalg.norm(cross_product) return self._normal @property @@ -283,7 +283,7 @@ class Surface: """ if self._type is None: grad = np.rad2deg(self.inclination) - if 170 <= grad: + if grad >= 170: self._type = 'Ground' elif 80 <= grad <= 100: self._type = 'Wall' @@ -307,7 +307,7 @@ class Surface: :param surface: Surface :return: None """ - if self.type is not 'Wall' or surface.type is not 'Wall': + if self.type != 'Wall' or surface.type != 'Wall': return if self._geometry.is_almost_same_surface(self, surface): intersection_area = self.intersect(surface).area diff --git a/city_model_structure/thermal_boundary.py b/city_model_structure/thermal_boundary.py index 81268ccd..88048198 100644 --- a/city_model_structure/thermal_boundary.py +++ b/city_model_structure/thermal_boundary.py @@ -3,14 +3,17 @@ ThermalBoundary module SPDX - License - Identifier: LGPL - 3.0 - or -later Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca """ +from typing import List from city_model_structure.thermal_opening import ThermalOpening from city_model_structure.thermal_zone import ThermalZone from city_model_structure.layer import Layer from helpers.configuration import Configuration -from typing import List class ThermalBoundary: + """ + ThermalBoundary class + """ def __init__(self, surface, delimits): self._surface = surface self._delimits = delimits @@ -27,83 +30,169 @@ class ThermalBoundary: @property def delimits(self) -> List[ThermalZone]: + """ + Get the thermal zones delimited by the thermal boundary + :return: [ThermalZone] + """ return self._delimits @property def azimuth(self): + """ + Thermal boundary azimuth in radians + :return: float + """ return self._surface.azimuth - + @property def inclination(self): + """ + Thermal boundary inclination in radians + :return: float + """ return self._surface.inclination - + @property def area(self): + """ + Thermal boundary area in square meters + :return: float + """ return self._surface.area @property def area_above_ground(self): + """ + Thermal boundary area above ground in square meters + :return: float + """ return self._surface.area_above_ground @property def area_below_ground(self): + """ + Thermal boundary area below ground in square meters + :return: float + """ return self._surface.area_below_ground @property def outside_solar_absorptance(self): + """ + Get thermal boundary outside solar absorptance + :return: float + """ return self._outside_solar_absorptance @outside_solar_absorptance.setter def outside_solar_absorptance(self, value): + """ + Set thermal boundary outside solar absorptance + :param value: float + :return: None + """ self._outside_solar_absorptance = value self._shortwave_reflectance = 1.0 - float(value) @property def outside_thermal_absorptance(self): + """ + Get thermal boundary outside thermal absorptance + :return: float + """ return self._outside_thermal_absorptance @outside_thermal_absorptance.setter def outside_thermal_absorptance(self, value): + """ + Set thermal boundary outside thermal absorptance + :param value: float + :return: None + """ self._outside_thermal_absorptance = value @property def outside_visible_absorptance(self): + """ + Get thermal boundary outside visible absorptance + :return: float + """ return self._outside_visible_absorptance @outside_visible_absorptance.setter def outside_visible_absorptance(self, value): + """ + Set thermal boundary outside visible absorptance + :param value: float + :return: None + """ self._outside_visible_absorptance = value @property def thermal_openings(self) -> List[ThermalOpening]: + """ + Get thermal boundary thermal openings + :return: [ThermalOpening] + """ return self._thermal_openings @thermal_openings.setter def thermal_openings(self, value): + """ + Set thermal boundary thermal openings + :param value: [ThermalOpening] + :return: None + """ self._thermal_openings = value @property def layers(self) -> List[Layer]: + """ + Get thermal boundary layers + :return: [Layers] + """ return self._layers @layers.setter def layers(self, value): + """ + Set thermal boundary layers + :param value: [Layer] + :return: None + """ self._layers = value @property def type(self): + """ + Thermal boundary surface type + :return: str + """ return self._surface.type @property def window_ratio(self): + """ + Get thermal boundary window ratio + :return: float + """ return self._window_ratio @window_ratio.setter def window_ratio(self, value): + """ + Set thermal boundary window ratio + :param value: float + :return: None + """ self._window_ratio = value @property def window_area(self): + """ + Thermal boundary window area in square meters + :return: float + """ if self._window_area is None: try: self._window_area = float(self._surface.area) * float(self.window_ratio) @@ -113,6 +202,11 @@ class ThermalBoundary: @property def u_value(self): + """ + Thermal boundary u value in W/m2K + internal and external convective coefficient in W/m2K values, can be configured at configuration.ini + :return: float + """ if self._u_value is None: h_i = Configuration().h_i h_e = Configuration().h_e @@ -130,9 +224,18 @@ class ThermalBoundary: @property def shortwave_reflectance(self): + """ + Get thermal boundary shortwave reflectance + :return: float + """ return self._shortwave_reflectance @shortwave_reflectance.setter def shortwave_reflectance(self, value): + """ + Set thermal boundary shortwave reflectance + :param value: float + :return: + """ self._shortwave_reflectance = value self._outside_solar_absorptance = 1.0 - float(value) diff --git a/city_model_structure/thermal_opening.py b/city_model_structure/thermal_opening.py index 1cfecdfc..4623be31 100644 --- a/city_model_structure/thermal_opening.py +++ b/city_model_structure/thermal_opening.py @@ -7,90 +7,165 @@ from helpers.configuration import Configuration class ThermalOpening: + """ + ThermalOpening class + """ def __init__(self): self._openable_ratio = None - self._conductivity_w_mk = None + self._conductivity = None self._frame_ratio = Configuration().frame_ratio self._g_value = None - self._thickness_m = None + self._thickness = None self._front_side_solar_transmittance_at_normal_incidence = None self._back_side_solar_transmittance_at_normal_incidence = None self._overall_u_value = None @property def openable_ratio(self): + """ + Get thermal opening openable ratio, NOT IMPLEMENTED + :return: Exception + """ raise Exception('Not implemented') @openable_ratio.setter def openable_ratio(self, value): + """ + Set thermal opening openable ratio, NOT IMPLEMENTED + :param value: Any + :return: Exception + """ raise Exception('Not implemented') @property - def conductivity_w_mk(self): - return self._conductivity_w_mk + def conductivity(self): + """ + Get thermal opening conductivity in W/mK + :return: float + """ + return self._conductivity - @conductivity_w_mk.setter - def conductivity_w_mk(self, value): + @conductivity.setter + def conductivity(self, value): + """ + Get thermal opening conductivity in W/mK + :param value: float + :return: None + """ # 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_w_mk = value - if self._overall_u_value is None and self.thickness_m is not None: + self._conductivity = value + if self._overall_u_value is None and self.thickness is not None: h_i = Configuration().h_i h_e = Configuration().h_e - r_value = 1 / h_i + 1 / h_e + float(self.conductivity_w_mk) / float(self.thickness_m) + 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): + """ + Get thermal opening frame ratio + :return: float + """ return self._frame_ratio @frame_ratio.setter def frame_ratio(self, value): + """ + Set thermal opening frame ratio + :param value: float + :return: None + """ self._frame_ratio = value @property def g_value(self): + """ + Get thermal opening g value + :return: float + """ return self._g_value @g_value.setter def g_value(self, value): + """ + Set thermal opening g value + :param value: + :return: + """ self._g_value = value @property - def thickness_m(self): - return self._thickness_m + def thickness(self): + """ + Get thermal opening thickness in meters + :return: + """ + return self._thickness - @thickness_m.setter - def thickness_m(self, value): - # The code to calculate overall_u_value is duplicated here and in conductivity_w_mk. + @thickness.setter + def thickness(self, value): + """ + Set thermal opening thickness in meters + :param value: float + :return: None + """ + # 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_m = value - if self._overall_u_value is None and self.conductivity_w_mk is not None: + self._thickness = value + if self._overall_u_value is None and self.conductivity is not None: h_i = Configuration().h_i h_e = Configuration().h_e - r_value = 1 / h_i + 1 / h_e + float(self.conductivity_w_mk) / float(self.thickness_m) + 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): + """ + Get thermal opening front side solar transmittance at normal incidence + :return: float + """ return self._front_side_solar_transmittance_at_normal_incidence @front_side_solar_transmittance_at_normal_incidence.setter def front_side_solar_transmittance_at_normal_incidence(self, value): + """ + Set thermal opening front side solar transmittance at normal incidence + :param value: float + :return: None + """ self._front_side_solar_transmittance_at_normal_incidence = value @property def back_side_solar_transmittance_at_normal_incidence(self): + """ + Get thermal opening back side solar transmittance at normal incidence + :return: float + """ return self._back_side_solar_transmittance_at_normal_incidence @back_side_solar_transmittance_at_normal_incidence.setter def back_side_solar_transmittance_at_normal_incidence(self, value): + """ + Set thermal opening back side solar transmittance at normal incidence + :param value: float + :return: None + """ self._back_side_solar_transmittance_at_normal_incidence = value @property def overall_u_value(self): + """ + Get thermal opening overall u value + :return: float + """ return self._overall_u_value @overall_u_value.setter def overall_u_value(self, value): + """ + Get thermal opening overall u value + :param value: float + :return: None + """ self._overall_u_value = value diff --git a/city_model_structure/usage_zone.py b/city_model_structure/usage_zone.py index b203825b..21dacd82 100644 --- a/city_model_structure/usage_zone.py +++ b/city_model_structure/usage_zone.py @@ -3,8 +3,8 @@ UsageZone module SPDX - License - Identifier: LGPL - 3.0 - or -later Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca """ -from city_model_structure.internal_gains import InternalGains from typing import List +from city_model_structure.internal_gains import InternalGains class UsageZone: @@ -41,59 +41,118 @@ class UsageZone: @property def heating_setpoint(self): """ - - :return: + Get usage zone heating set point in celsius grads + :return: float """ return self._heating_setpoint @heating_setpoint.setter def heating_setpoint(self, value): + """ + Set usage zone heating set point in celsius grads + :param value: float + :return: None + """ self._heating_setpoint = value @property def heating_setback(self): + """ + Get usage zone heating setback in celsius grads + :return: float + """ return self._heating_setback @heating_setback.setter def heating_setback(self, value): + """ + Set usage zone heating setback in celsius grads + :param value: float + :return: None + """ self._heating_setback = value @property def cooling_setpoint(self): + """ + Get usage zone cooling setpoint in celsius grads + :return: float + """ return self._cooling_setpoint @cooling_setpoint.setter def cooling_setpoint(self, value): + """ + Set usage zone cooling setpoint in celsius grads + :param value: float + :return: None + """ self._cooling_setpoint = value @property def hours_day(self): + """ + Get usage zone usage hours per day + :return: float + """ return self._hours_day @hours_day.setter def hours_day(self, value): + """ + Set usage zone usage hours per day + :param value: float + :return: float + """ self._hours_day = value @property def days_year(self): + """ + Get usage zone usage days per year + :return: float + """ return self._days_year @days_year.setter def days_year(self, value): + """ + Set usage zone usage days per year + :param value: float + :return: None + """ self._days_year = value @property def mechanical_air_change(self): + """ + Set usage zone mechanical air change in air change per hour + :return: float + """ return self._mechanical_air_change @mechanical_air_change.setter def mechanical_air_change(self, value): + """ + Get usage zone mechanical air change in air change per hour + :param value: float + :return: None + """ self._mechanical_air_change = value @property def usage(self): + """ + Get usage zone usage + :return: str + """ return self._usage @usage.setter def usage(self, value): + """ + Get usage zone usage + :param value: str + :return: None + """ self._usage = value diff --git a/geometry/geometry_factory.py b/geometry/geometry_factory.py index 879b169f..3538e88a 100644 --- a/geometry/geometry_factory.py +++ b/geometry/geometry_factory.py @@ -9,21 +9,25 @@ from city_model_structure.city import City class GeometryFactory: def __init__(self, file_type, path): - self._file_type = file_type.lower() + self._file_type = '_' + file_type.lower() self._path = path @property - def citygml(self): + def _citygml(self): return CityGml(self._path).city @property - def geojson(self): + def _geojson(self): raise Exception('Not implemented') @property - def bim(self): + def _bim(self): raise Exception('Not implemented') @property def city(self) -> City: + """ + Geometry factory city model structure with geometry + :return: City + """ return getattr(self, self._file_type, lambda: None) diff --git a/geometry/geometry_feeders/city_gml.py b/geometry/geometry_feeders/city_gml.py index f5331b1b..b9948711 100644 --- a/geometry/geometry_feeders/city_gml.py +++ b/geometry/geometry_feeders/city_gml.py @@ -12,6 +12,9 @@ from helpers.geometry import Geometry class CityGml: + """ + CityGml class + """ def __init__(self, path): self._city = None with open(path) as gml: @@ -42,10 +45,18 @@ class CityGml: @property def content(self): + """ + CityGml raw content + :return: str + """ return self._gml @property - def city(self): + def city(self) -> City: + """ + City model structure enriched with the geometry information + :return: City + """ if self._city is None: self._city = City(self._lower_corner, self._upper_corner, self._srs_name) for o in self._gml['CityModel']['cityObjectMember']: diff --git a/helpers/configuration.py b/helpers/configuration.py index a140ef84..803266f1 100644 --- a/helpers/configuration.py +++ b/helpers/configuration.py @@ -8,6 +8,9 @@ from pathlib import Path class Configuration: + """ + Configuration class + """ def __init__(self): base_path = Path().resolve().parent config_file = Path(base_path / 'libs/config/configuration.ini').resolve() @@ -16,36 +19,73 @@ class Configuration: @property def h_i(self): + """ + Configured internal convective coefficient in W/m2K + :return: float + """ return self._config.getfloat('convective_fluxes', 'h_i') @property def h_e(self): + """ + Configured external convective coefficient in W/m2K + :return: float + """ return self._config.getfloat('convective_fluxes', 'h_e') @property def frame_ratio(self): + """ + Configured frame ratio + :return: float + """ return self._config.getfloat('windows', 'frame_ratio') @property def heated(self): + """ + Configured heated flag + :return: Boolean + """ return self._config.getboolean('thermal_zones', 'heated') @property def cooled(self): + """ + Configured cooled flag + :return: Boolean + """ return self._config.getboolean('thermal_zones', 'cooled') @property def additional_thermal_bridge_u_value(self): + """ + Configured additional thermal bridge u value W/m2K + :return: + """ return self._config.getfloat('thermal_zones', 'additional_thermal_bridge_u_value') @property def indirectly_heated_area_ratio(self): + """ + Configured indirectly heated area ratio + :return: float + """ + return self._config.getfloat('thermal_zones', 'indirectly_heated_area_ratio') @property def infiltration_rate_system_on(self): + """ + Configured infiltration rate system on in air change per hour + :return: float + """ return self._config.getfloat('thermal_zones', 'infiltration_rate_system_on') @property def outside_solar_absorptance(self): + """ + Configured infiltration rate system off in air change per hour + :return: float + """ return self._config.getfloat('thermal_zones', 'outside_solar_absorptance') diff --git a/helpers/geometry.py b/helpers/geometry.py index fedbf8cd..09689f26 100644 --- a/helpers/geometry.py +++ b/helpers/geometry.py @@ -11,14 +11,29 @@ import open3d as o3d class Geometry: + """ + Geometry helper class + """ def __init__(self, delta=0.5): self._delta = delta def almost_equal(self, v1, v2): + """ + Compare two points and decides if they are almost equal (quadratic error under delta) + :param v1: [x,y,z] + :param v2: [x,y,z] + :return: Boolean + """ delta = math.sqrt(pow((v1[0] - v2[0]), 2) + pow((v1[1] - v2[1]), 2) + pow((v1[2] - v2[2]), 2)) return delta <= self._delta def is_almost_same_surface(self, s1, s2): + """ + Compare two surfaces and decides if they are almost equal (quadratic error under delta) + :param s1: Surface + :param s2: Surface + :return: Boolean + """ # delta is grads an need to be converted into radians delta = np.rad2deg(self._delta) difference = (s1.inclination - s2.inclination) % math.pi @@ -49,6 +64,12 @@ class Geometry: @staticmethod def to_points_matrix(points, remove_last=False): + """ + Transform a point vector into a point matrix + :param points: [x, y, z, x, y, z ...] + :param remove_last: Boolean + :return: [[x,y,z],[x,y,z]...] + """ rows = points.size // 3 points = points.reshape(rows, 3) if remove_last: @@ -107,6 +128,13 @@ class Geometry: @staticmethod def divide_mesh_by_plane(mesh, normal_plane, point_plane): + """ + Divide a mesh by a plane + :param mesh: Trimesh + :param normal_plane: [x, y, z] + :param point_plane: [x, y, z] + :return: [Trimesh] + """ # The first mesh returns the positive side of the plane and the second the negative side. # If the plane does not divide the mesh (i.e. it does not touch it or it is coplanar with one or more faces), # then it returns only the original mesh. diff --git a/physics/physics_factory.py b/physics/physics_factory.py index f7beff08..7c2e80a9 100644 --- a/physics/physics_factory.py +++ b/physics/physics_factory.py @@ -8,26 +8,33 @@ from physics.physics_feeders.us_physics_parameters import UsPhysicsParameters class PhysicsFactory: + """ + PhysicsFactor class + """ def __init__(self, handler, city, base_path='data/physics'): - self._handler = handler.lower().replace(' ', '_') + self._handler = '_' + handler.lower().replace(' ', '_') self._city = city self._base_path = base_path self.factory() - def us_new_york_city(self): + def _us_new_york_city(self): UsNewYorkCityPhysicsParameters(self._city, self._base_path) - def us(self): + def _us(self): UsPhysicsParameters(self._city, self._base_path) - def ca(self): + def _ca(self): raise Exception('Not implemented') - def de(self): + def _de(self): raise Exception('Not implemented') - def es(self): + def _es(self): raise Exception('Not implemented') def factory(self): + """ + Enrich the city with the physics information + :return: None + """ getattr(self, self._handler, lambda: None)() diff --git a/physics/physics_feeders/helpers/us_pluto_to_function.py b/physics/physics_feeders/helpers/us_pluto_to_function.py index f16298e7..87352841 100644 --- a/physics/physics_feeders/helpers/us_pluto_to_function.py +++ b/physics/physics_feeders/helpers/us_pluto_to_function.py @@ -6,6 +6,9 @@ Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@conc class UsPlutoToFunction: + """ + UsPlutoToFunction + """ building_function = { 'A0': 'single family house', 'A1': 'single family house', diff --git a/physics/physics_feeders/helpers/us_to_library_types.py b/physics/physics_feeders/helpers/us_to_library_types.py index e9194271..1ccdfd5f 100644 --- a/physics/physics_feeders/helpers/us_to_library_types.py +++ b/physics/physics_feeders/helpers/us_to_library_types.py @@ -5,7 +5,10 @@ Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@conc """ -class UsToLibraryTypes(object): +class UsToLibraryTypes: + """ + UsToLibraryTypes + """ standards = { 'ASHRAE Std189': 1, 'ASHRAE 90.1-2004': 2 @@ -44,6 +47,11 @@ class UsToLibraryTypes(object): @staticmethod def yoc_to_standard(year_of_construction): + """ + Year of construction to standard + :param year_of_construction: int + :return: str + """ if int(year_of_construction) < 2009: standard = 'ASHRAE 90.1_2004' else: @@ -52,6 +60,11 @@ class UsToLibraryTypes(object): @staticmethod def city_to_reference_city(city): + """ + City name to reference city + :param city: str + :return: str + """ # ToDo: Dummy function that need to be implemented reference_city = 'Baltimore' if city is not None: @@ -60,5 +73,10 @@ class UsToLibraryTypes(object): @staticmethod def city_to_climate_zone(city): + """ + City name to climate zone + :param city: str + :return: str + """ reference_city = UsToLibraryTypes.city_to_reference_city(city) return UsToLibraryTypes.reference_city_climate_zone[reference_city] diff --git a/physics/physics_feeders/us_base_physics_parameters.py b/physics/physics_feeders/us_base_physics_parameters.py index b5ac02c1..b52b62b1 100644 --- a/physics/physics_feeders/us_base_physics_parameters.py +++ b/physics/physics_feeders/us_base_physics_parameters.py @@ -4,14 +4,17 @@ UsPhysicsParameters as base class SPDX - License - Identifier: LGPL - 3.0 - or -later Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca """ +from pathlib import Path import xmltodict from city_model_structure.layer import Layer from city_model_structure.material import Material -from pathlib import Path from physics.physics_feeders.helpers.us_to_library_types import UsToLibraryTypes class UsBasePhysicsParameters: + """ + UsBasePhysicsParameters class + """ def __init__(self, climate_zone, city_objects, function_to_type, base_path): self._climate_zone = climate_zone self._city_objects = city_objects @@ -29,9 +32,9 @@ class UsBasePhysicsParameters: building_type = function_to_type(city_object.function) if building_type is None: return - archetype = self.search_archetype(building_type, - UsToLibraryTypes.yoc_to_standard(city_object.year_of_construction), - self._climate_zone) + archetype = self._search_archetype(building_type, + UsToLibraryTypes.yoc_to_standard(city_object.year_of_construction), + self._climate_zone) # ToDo:remove this in the future # ToDo: Raise WrongArchetype if not all the surface types are defined for the given city_object if archetype is None: @@ -50,9 +53,9 @@ class UsBasePhysicsParameters: thermal_zone.infiltration_rate_system_on = archetype['infiltration_rate_for_ventilation_system_on']['#text'] for thermal_boundary in thermal_zone.bounded: construction_type = UsToLibraryTypes.construction_types[thermal_boundary.type] - construction = UsBasePhysicsParameters.search_construction_in_archetype(archetype, construction_type) + construction = UsBasePhysicsParameters._search_construction_in_archetype(archetype, construction_type) construction_id = construction['@id'] - c_lib = self.search_construction_type('construction', construction_id) + c_lib = self._search_construction_type('construction', construction_id) if 'outside_solar_absorptance' in c_lib: thermal_boundary.outside_solar_absorptance = c_lib['outside_solar_absorptance']['#text'] thermal_boundary.outside_thermal_absorptance = c_lib['outside_thermal_absorptance']['#text'] @@ -63,7 +66,7 @@ class UsBasePhysicsParameters: layer = Layer() if 'thickness' in current_layer: layer.thickness = current_layer['thickness']['#text'] - material_lib = self.search_construction_type('material', current_layer['material']) + material_lib = self._search_construction_type('material', current_layer['material']) material = Material() if 'conductivity' in material_lib: material.conductivity = material_lib['conductivity']['#text'] @@ -80,8 +83,8 @@ class UsBasePhysicsParameters: for opening in thermal_boundary.thermal_openings: if construction['window'] is None: continue - w_lib = self.search_construction_type('window', construction['window']) - opening.conductivity_w_mk = w_lib['conductivity']['#text'] + w_lib = self._search_construction_type('window', construction['window']) + opening.conductivity = w_lib['conductivity']['#text'] opening.frame_ratio = w_lib['frame_ratio']['#text'] opening.g_value = w_lib['solar_transmittance_at_normal_incidence']['#text'] opening.thickness = w_lib['thickness']['#text'] @@ -90,7 +93,7 @@ class UsBasePhysicsParameters: opening.front_side_solar_transmittance_at_normal_incidence = \ w_lib['front_side_solar_transmittance_at_normal_incidence']['#text'] - def search_archetype(self, building_type, standard, climate_zone): + def _search_archetype(self, building_type, standard, climate_zone): for archetype in self._archetypes['archetypes']['archetype']: a_yc = str(archetype['@reference_standard']) a_bt = str(archetype['@building_type']) @@ -99,14 +102,14 @@ class UsBasePhysicsParameters: return archetype return None - def search_construction_type(self, construction_type, construction_id): + def _search_construction_type(self, construction_type, construction_id): for c_lib in self._library['library'][construction_type + 's'][construction_type]: if construction_id == c_lib['@id']: return c_lib raise Exception('Archetype definition contains elements that does not exist in the library') @staticmethod - def search_construction_in_archetype(archetype, construction_type): + def _search_construction_in_archetype(archetype, construction_type): for construction in archetype['constructions']['construction']: if construction['@type'] == construction_type: return construction diff --git a/physics/physics_feeders/us_new_york_city_physics_parameters.py b/physics/physics_feeders/us_new_york_city_physics_parameters.py index b54e2e86..c6a87ae4 100644 --- a/physics/physics_feeders/us_new_york_city_physics_parameters.py +++ b/physics/physics_feeders/us_new_york_city_physics_parameters.py @@ -8,6 +8,9 @@ from physics.physics_feeders.helpers.us_pluto_to_function import UsPlutoToFuncti class UsNewYorkCityPhysicsParameters(UsBasePhysicsParameters): + """ + UsNewYorkCityPhysicsParameters class + """ def __init__(self, city, base_path): self._city = city climate_zone = 'ASHRAE_2004:4A' diff --git a/physics/physics_feeders/us_physics_parameters.py b/physics/physics_feeders/us_physics_parameters.py index aa877093..c2b7e6b5 100644 --- a/physics/physics_feeders/us_physics_parameters.py +++ b/physics/physics_feeders/us_physics_parameters.py @@ -8,6 +8,9 @@ from physics.physics_feeders.helpers.us_to_library_types import UsToLibraryTypes class UsPhysicsParameters(UsBasePhysicsParameters): + """ + UsPhysicsParameters class + """ def __init__(self, city, base_path): self._city = city self._climate_zone = UsToLibraryTypes.city_to_climate_zone(city.name) diff --git a/pylintrc b/pylintrc index 9f1f7c52..5da35412 100644 --- a/pylintrc +++ b/pylintrc @@ -140,6 +140,9 @@ disable=print-statement, exception-escape, comprehension-escape, import-error, + parse-error, + syntax-error, + bad-continuation, no-name-in-module # Enable the message, report, category or checker with the given id(s). You can diff --git a/tests/test_geometry_factory.py b/tests/test_geometry_factory.py index ae45ecf2..9fdcb4fa 100644 --- a/tests/test_geometry_factory.py +++ b/tests/test_geometry_factory.py @@ -7,15 +7,25 @@ from unittest import TestCase from pathlib import Path from geometry.geometry_factory import GeometryFactory import os -from city_model_structure.surface import Surface class TestGeometryFactory(TestCase): + """ + TestGeometryFactory TestCase + """ def setUp(self) -> None: + """ + Test setup + :return: None + """ self._city_gml = None self._example_path = (Path(__file__).parent.parent / 'tests_data').resolve() def get_citygml(self): + """ + Retrieve the test city gml + :return: City + """ if self._city_gml is None: file_path = (self._example_path / 'buildings.gml').resolve() self._city_gml = GeometryFactory('citygml', file_path).city @@ -23,6 +33,10 @@ class TestGeometryFactory(TestCase): return self._city_gml def test_citygml_city(self): + """ + Test the City parsing + :return: None + """ city = self.get_citygml() self.assertIsNotNone(city.city_objects, 'city_objects is none') for city_object in city.city_objects: @@ -34,6 +48,10 @@ class TestGeometryFactory(TestCase): self.assertIsNotNone(city.country_code, 'country code is none') def test_citygml_city_objects(self): + """ + Test city objects in the city + :return: None + """ city = self.get_citygml() for city_object in city.city_objects: self.assertIsNotNone(city_object.name, 'city_object name is none') @@ -58,6 +76,10 @@ class TestGeometryFactory(TestCase): os.remove(Path(self._example_path, city_object.name + '.stl').resolve()) def test_citygml_surfaces(self): + """ + Test surfaces in city objects + :return: None + """ city = self.get_citygml() for city_object in city.city_objects: for surface in city_object.surfaces: @@ -85,6 +107,10 @@ class TestGeometryFactory(TestCase): self.assertIsNotNone(surface.intersect(surface), 'self intersection is none') def test_citygml_thermal_zone(self): + """ + Test thermal zones in city objects + :return: None + """ city = self.get_citygml() for city_object in city.city_objects: for thermal_zone in city_object.thermal_zones: @@ -97,8 +123,8 @@ class TestGeometryFactory(TestCase): 'thermal_zone additional_thermal_bridge_u_value is not none') self.assertIsNone(thermal_zone.effective_thermal_capacity, 'thermal_zone effective_thermal_capacity is not none') - self.assertIsNone(thermal_zone.indirectly_heated_area_ratio - , 'thermal_zone indirectly_heated_area_ratio is not none') + self.assertIsNone(thermal_zone.indirectly_heated_area_ratio, + 'thermal_zone indirectly_heated_area_ratio is not none') self.assertIsNone(thermal_zone.infiltration_rate_system_off, 'thermal_zone infiltration_rate_system_off is not none') self.assertIsNone(thermal_zone.infiltration_rate_system_on, @@ -107,6 +133,10 @@ class TestGeometryFactory(TestCase): 'thermal_zone usage_zones are not none') def test_citygml_thermal_boundary(self): + """ + Test thermal boundaries in thermal zones + :return: None + """ city = self.get_citygml() for city_object in city.city_objects: for thermal_zone in city_object.thermal_zones: @@ -133,6 +163,10 @@ class TestGeometryFactory(TestCase): self.assertIsNone(thermal_boundary.window_ratio, 'thermal_boundary window_ratio was initialized') def test_citygml_thermal_opening(self): + """ + Test thermal openings in thermal zones + :return: None + """ city = self.get_citygml() for city_object in city.city_objects: for thermal_zone in city_object.thermal_zones: @@ -141,11 +175,11 @@ class TestGeometryFactory(TestCase): self.assertIsNone(thermal_opening.area, 'thermal_opening area was initialized') self.assertTrue(thermal_opening.frame_ratio == 0, 'thermal_opening frame_ratio was not 0') self.assertIsNone(thermal_opening.g_value, 'thermal_opening g_value was initialized') - self.assertIsNone(thermal_opening.conductivity_w_mk, 'thermal_opening conductivity_w_mk was initialized') + self.assertIsNone(thermal_opening.conductivity, 'thermal_opening conductivity_w_mk was initialized') self.assertIsNone(thermal_opening.inside_reflectance, 'thermal_opening inside_reflectance was initialized') self.assertRaises(Exception, lambda: thermal_opening.openable_ratio, 'thermal_opening openable_ratio is not raising an exception') self.assertIsNone(thermal_opening.outside_reflectance, 'thermal_opening outside_reflectance was initialized') - self.assertIsNone(thermal_opening.thickness_m, 'thermal_opening thickness_m was initialized') + self.assertIsNone(thermal_opening.thickness, 'thermal_opening thickness_m was initialized') self.assertRaises(Exception, lambda: thermal_opening.u_value, 'thermal_opening u_value was initialized') diff --git a/tests/test_physics_factory.py b/tests/test_physics_factory.py index 7c0bec48..355a07a5 100644 --- a/tests/test_physics_factory.py +++ b/tests/test_physics_factory.py @@ -10,7 +10,10 @@ from physics.physics_factory import PhysicsFactory class TestPhysicsFactory(TestCase): - def setUp(self) -> None: + """ + TestPhysicsFactory TestCase + """ + def setup(self) -> None: self._city_gml = None self._nyc_with_physics = None self._example_path = (Path(__file__).parent.parent / 'tests_data').resolve()