From 1a86449e58000a7efd453169620551d99636256c Mon Sep 17 00:00:00 2001 From: Ruben Sanchez Date: Wed, 29 Nov 2023 13:09:32 -0500 Subject: [PATCH] Change of test to generate montreal cli file --- tests/test_city_merge.py | 108 ++++++++++++++++++++++++++++ tests/test_exports.py | 150 --------------------------------------- 2 files changed, 108 insertions(+), 150 deletions(-) create mode 100644 tests/test_city_merge.py delete mode 100644 tests/test_exports.py diff --git a/tests/test_city_merge.py b/tests/test_city_merge.py new file mode 100644 index 0000000..24bdc80 --- /dev/null +++ b/tests/test_city_merge.py @@ -0,0 +1,108 @@ +""" +TestCityMerge test and validate the merge of several cities into one +SPDX - License - Identifier: LGPL - 3.0 - or -later +Copyright © 2022 Concordia CERC group +Project Coder Guille Gutierrez Guillermo.GutierrezMorote@concordia.ca +""" + +import copy +import distutils.spawn +import subprocess +from pathlib import Path +from unittest import TestCase + +from hub.city_model_structure.city import City +from hub.imports.geometry_factory import GeometryFactory +from hub.imports.results_factory import ResultFactory +from hub.exports.exports_factory import ExportsFactory +import hub.helpers.constants as cte + + +class TestCityMerge(TestCase): + """ + Functional TestCityMerge + """ + def setUp(self) -> None: + """ + Test setup + :return: None + """ + self._example_path = (Path(__file__).parent / 'tests_data').resolve() + self._output_path = (Path(__file__).parent / 'tests_outputs').resolve() + self._executable = 'sra' + + def test_merge(self): + file_path = Path(self._example_path / 'test.geojson').resolve() + full_city = GeometryFactory('geojson', file_path, height_field='citygml_me').city + self.assertEqual(17, len(full_city.buildings), 'Wrong number of buildings') + odd_city = City(full_city.lower_corner, full_city.upper_corner, full_city.srs_name) + even_city = City(full_city.lower_corner, full_city.upper_corner, full_city.srs_name) + for building in full_city.buildings: + if int(building.name) % 2 == 0: + even_city.add_city_object(copy.deepcopy(building)) + else: + odd_city.add_city_object(copy.deepcopy(building)) + self.assertEqual(8, len(odd_city.buildings), 'Wrong number of odd buildings') + self.assertEqual(9, len(even_city.buildings), 'Wrong number of par buildings') + merged_city = odd_city.merge(even_city) + self.assertEqual(17, len(merged_city.buildings), 'Wrong number of buildings in merged city') + merged_city = even_city.merge(odd_city) + self.assertEqual(17, len(merged_city.buildings), 'Wrong number of buildings in merged city') + merged_city = full_city.merge(odd_city).merge(even_city) + self.assertEqual(17, len(merged_city.buildings), 'Wrong number of buildings in merged city') + + def test_merge_with_radiation(self): + sra = distutils.spawn.find_executable('sra') + file_path = Path(self._example_path / 'test.geojson').resolve() + + full_city = GeometryFactory('geojson', file_path, height_field='citygml_me').city + even_city = City(full_city.lower_corner, full_city.upper_corner, full_city.srs_name) + for building in full_city.buildings: + if int(building.name) % 2 == 0: + even_city.add_city_object(copy.deepcopy(building)) + ExportsFactory('sra', full_city, self._output_path).export() + sra_file = str((self._output_path / f'{full_city.name}_sra.xml').resolve()) + subprocess.run([sra, sra_file], stdout=subprocess.DEVNULL) + ResultFactory('sra', full_city, self._output_path).enrich() + self.assertEqual(17, len(full_city.buildings), 'Wrong number of buildings') + merged_city = full_city.merge(even_city) + + full_city_building_total_radiation = 0 + for building in merged_city.buildings: + for surface in building.surfaces: + if surface.global_irradiance: + full_city_building_total_radiation += surface.global_irradiance[cte.YEAR][0] + + merged_city_building_total_radiation = 0 + for building in merged_city.buildings: + for surface in building.surfaces: + if surface.global_irradiance: + merged_city_building_total_radiation += surface.global_irradiance[cte.YEAR][0] + self.assertEqual(full_city_building_total_radiation, merged_city_building_total_radiation) + + merged_city = even_city.merge(full_city) + merged_city_building_total_radiation = 0 + for building in merged_city.buildings: + for surface in building.surfaces: + if surface.global_irradiance: + merged_city_building_total_radiation += surface.global_irradiance[cte.YEAR][0] + self.assertEqual(full_city_building_total_radiation, merged_city_building_total_radiation) + + for building in even_city.buildings: + for surface in building.surfaces: + surface.global_irradiance[cte.YEAR] = [3] + + merged_city = full_city.merge(even_city) + first_merged_city_building_total_radiation = 0 + for building in merged_city.buildings: + for surface in building.surfaces: + if surface.global_irradiance: + first_merged_city_building_total_radiation += surface.global_irradiance[cte.YEAR][0] + merged_city = even_city.merge(full_city) + second_merged_city_building_total_radiation = 0 + for building in merged_city.buildings: + for surface in building.surfaces: + if surface.global_irradiance: + second_merged_city_building_total_radiation += surface.global_irradiance[cte.YEAR][0] + self.assertAlmostEqual(first_merged_city_building_total_radiation, second_merged_city_building_total_radiation, 8) + diff --git a/tests/test_exports.py b/tests/test_exports.py deleted file mode 100644 index e719790..0000000 --- a/tests/test_exports.py +++ /dev/null @@ -1,150 +0,0 @@ -""" -TestExports test and validate the city export formats -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2022 Concordia CERC group -Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca -Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca -""" -import json -import os -from pathlib import Path -from unittest import TestCase - -import hub.helpers.constants as cte -from hub.city_model_structure.city import City -from hub.exports.energy_building_exports_factory import EnergyBuildingsExportsFactory -from hub.exports.exports_factory import ExportsFactory -from hub.helpers.dictionaries import Dictionaries -from hub.imports.construction_factory import ConstructionFactory -from hub.imports.geometry_factory import GeometryFactory -from hub.imports.usage_factory import UsageFactory -from hub.imports.weather_factory import WeatherFactory - - -class TestExports(TestCase): - """ - TestExports class contains the unittest for export functionality - """ - def setUp(self) -> None: - """ - Test setup - :return: None - """ - self._city = None - self._complete_city = None - self._example_path = (Path(__file__).parent / 'tests_data').resolve() - self._output_path = (Path(__file__).parent / 'tests_outputs').resolve() - - def _get_citygml(self, file): - file_path = (self._example_path / file).resolve() - self._city = GeometryFactory('citygml', path=file_path).city - self.assertIsNotNone(self._city, 'city is none') - return self._city - - def _get_complete_city(self, from_pickle): - if self._complete_city is None: - if from_pickle: - file_path = (self._example_path / 'ConcordiaSWGcampus.pickle').resolve() - self._complete_city = City.load(file_path) - else: - file_path = (self._example_path / 'one_building_in_kelowna.gml').resolve() - self._complete_city = self._get_citygml(file_path) - for building in self._complete_city.buildings: - building.function = Dictionaries().hft_function_to_hub_function[building.function] - building.year_of_construction = 2006 - ConstructionFactory('nrel', self._complete_city).enrich() - UsageFactory('nrcan', self._complete_city).enrich() - cli = (self._example_path / 'weather' / 'inseldb_Summerland.cli').resolve() - self._complete_city.climate_file = Path(cli) - self._complete_city.climate_reference_city = 'Summerland' - dummy_measures = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] - for building in self._complete_city.buildings: - building.heating_demand[cte.MONTH] = dummy_measures - building.cooling_demand[cte.MONTH] = dummy_measures - building.heating_demand[cte.YEAR] = [0.0] - building.cooling_demand[cte.YEAR] = [0.0] - return self._complete_city - - def _export(self, export_type, from_pickle=False): - self._complete_city = self._get_complete_city(from_pickle) - ExportsFactory(export_type, self._complete_city, self._output_path, base_uri='../glb').export() - - def _export_building_energy(self, export_type, from_pickle=False): - self._complete_city = self._get_complete_city(from_pickle) - EnergyBuildingsExportsFactory(export_type, self._complete_city, self._output_path).export() - - def test_obj_export(self): - """ - export to obj - """ - self._export('obj', False) - - def test_cesiumjs_tileset_export(self): - """ - export to cesiumjs tileset - """ - self._export('cesiumjs_tileset', False) - tileset = Path(self._output_path / f'{self._city.name}.json') - self.assertTrue(tileset.exists()) - with open(tileset, 'r') as f: - json_tileset = json.load(f) - self.assertEqual(1, len(json_tileset['root']['children']), "Wrong number of children") - - def test_glb_export(self): - """ - export to glb format - """ - self._export('glb', False) - for building in self._city.buildings: - glb_file = Path(self._output_path / f'{building.name}.glb') - self.assertTrue(glb_file.exists(), f'{building.name} Building glb wasn\'t correctly generated') - - def test_geojson_export(self): - self._export('geojson', False) - geojson_file = Path(self._output_path / f'{self._city.name}.geojson') - self.assertTrue(geojson_file.exists(), f'{geojson_file} doesn\'t exists') - with open(geojson_file, 'r') as f: - geojson = json.load(f) - self.assertEqual(1, len(geojson['features']), 'Wrong number of buildings') - geometry = geojson['features'][0]['geometry'] - self.assertEqual('Polygon', geometry['type'], 'Wrong geometry type') - self.assertEqual(1, len(geometry['coordinates']), 'Wrong polygon structure') - self.assertEqual(11, len(geometry['coordinates'][0]), 'Wrong number of vertices') - os.unlink(geojson_file) # todo: this test need to cover a multipolygon example too - - def test_energy_ade_export(self): - """ - export to energy ADE - """ - self._export_building_energy('energy_ade') - - def test_sra_export(self): - """ - export to SRA - """ - self._export('sra') - - def test_idf_export(self): - """ - export to IDF - """ - file = 'test.geojson' - file_path = (self._example_path / file).resolve() - city = GeometryFactory('geojson', - path=file_path, - height_field='citygml_me', - year_of_construction_field='ANNEE_CONS', - function_field='CODE_UTILI', - function_to_hub=Dictionaries().montreal_function_to_hub_function).city - - self.assertIsNotNone(city, 'city is none') - EnergyBuildingsExportsFactory('idf', city, self._output_path).export() - ConstructionFactory('nrcan', city).enrich() - EnergyBuildingsExportsFactory('idf', city, self._output_path).export() - UsageFactory('nrcan', city).enrich() - WeatherFactory('epw', city).enrich() - print(self._output_path) - try: - EnergyBuildingsExportsFactory('idf', city, self._output_path).export() - except Exception: - self.fail("Idf ExportsFactory raised ExceptionType unexpectedly!")