Added the importer for sra results

This commit is contained in:
Guille Gutierrez 2023-02-07 13:01:49 -05:00
parent d91b6edfff
commit 11e8949b30
6 changed files with 197 additions and 4 deletions

View File

@ -101,13 +101,19 @@ class City:
""" """
return self._get_location().country return self._get_location().country
@property
def location(self):
return self._get_location().city
@property @property
def name(self): def name(self):
""" """
Get city name Get city name
:return: str :return: str
""" """
if self._name is None:
return self._get_location().city return self._get_location().city
return self._name
@property @property
def climate_reference_city(self) -> Union[None, str]: def climate_reference_city(self) -> Union[None, str]:

View File

@ -17,7 +17,11 @@ class ExportsFactory:
""" """
Exports factory class Exports factory class
""" """
def __init__(self, export_type, city, path, target_buildings=None, adjacent_buildings=None): def __init__(self, export_type, city, path,
target_buildings=None,
adjacent_buildings=None,
weather_file=None,
weather_format=None):
self._city = city self._city = city
self._export_type = '_' + export_type.lower() self._export_type = '_' + export_type.lower()
class_funcs = validate_import_export_type(ExportsFactory) class_funcs = validate_import_export_type(ExportsFactory)
@ -30,6 +34,8 @@ class ExportsFactory:
self._path = path self._path = path
self._target_buildings = target_buildings self._target_buildings = target_buildings
self._adjacent_buildings = adjacent_buildings self._adjacent_buildings = adjacent_buildings
self._weather_file = weather_file
self._weather_format = weather_format
@property @property
def _citygml(self): def _citygml(self):
@ -73,7 +79,10 @@ class ExportsFactory:
Export the city to Simplified Radiosity Algorithm xml format Export the city to Simplified Radiosity Algorithm xml format
:return: None :return: None
""" """
return SimplifiedRadiosityAlgorithm(self._city, (self._path / f'{self._city.name}_sra.xml'), return SimplifiedRadiosityAlgorithm(self._city,
(self._path / f'{self._city.name}_sra.xml'),
self._weather_file,
self._weather_format,
target_buildings=self._target_buildings) target_buildings=self._target_buildings)
def export(self): def export(self):

View File

@ -6,12 +6,25 @@ Project Coder Guillermo.GutierrezMorote@concordia.ca
""" """
import xmltodict import xmltodict
from hub.imports.weather_factory import WeatherFactory
import hub.helpers.constants as cte
class SimplifiedRadiosityAlgorithm: class SimplifiedRadiosityAlgorithm:
""" """
Export to SRA format Export to SRA format
""" """
def __init__(self, city, file_name, target_buildings=None, begin_month=1, begin_day=1, end_month=12, end_day=31):
def __init__(self,
city,
file_name,
weather_file,
weather_format,
target_buildings=None,
begin_month=1,
begin_day=1,
end_month=12,
end_day=31):
self._file_name = file_name self._file_name = file_name
self._begin_month = begin_month self._begin_month = begin_month
self._begin_day = begin_day self._begin_day = begin_day
@ -19,6 +32,8 @@ class SimplifiedRadiosityAlgorithm:
self._end_day = end_day self._end_day = end_day
self._city = city self._city = city
self._target_buildings = target_buildings self._target_buildings = target_buildings
self._weather_format = weather_format
self._weather_file = weather_file
self._export() self._export()
def _correct_point(self, point): def _correct_point(self, point):
@ -29,6 +44,34 @@ class SimplifiedRadiosityAlgorithm:
return [x, y, z] return [x, y, z]
def _export(self): def _export(self):
self._export_sra_xml()
self._export_sra_cli()
def _export_sra_cli(self):
file = self._city.climate_file
days_in_month = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
WeatherFactory(self._weather_format, self._city, file_name=self._weather_file).enrich()
content = self._city.name + '\n'
content += str(self._city.latitude) + ',' + str(self._city.longitude) + ',0.0,' + str(self._city.time_zone) + '\n'
content += '\ndm m h G_Dh G_Bn\n'
total_days = 0
for month in range(1, 13):
if month > 1:
total_days += days_in_month[month - 2]
for day in range(1, days_in_month[month - 1] + 1):
for hour in range(1, 25):
if month == 1:
i = 24 * (day - 1) + hour - 1
else:
i = (total_days + day - 1) * 24 + hour - 1
representative_building = self._city.buildings[0]
content += str(day) + ' ' + str(month) + ' ' + str(hour) + ' ' \
+ str(representative_building.global_horizontal[cte.HOUR].epw[i]) + ' ' \
+ str(representative_building.beam[cte.HOUR].epw[i]) + '\n'
with open(file, "w") as file:
file.write(content)
def _export_sra_xml(self):
buildings = [] buildings = []
for building_index, building in enumerate(self._city.buildings): for building_index, building in enumerate(self._city.buildings):
if self._target_buildings is None: if self._target_buildings is None:

View File

@ -0,0 +1,92 @@
"""
Simplified Radiosity Algorithm
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group
Project Coder Guillermo.GutierrezMorote@concordia.ca
"""
import pandas as pd
import numpy as np
import calendar as cal
import hub.helpers.constants as cte
class SimplifiedRadiosityAlgorithm:
"""
Import SRA results
"""
def __init__(self, city, base_path):
self._city = city
self._base_path = base_path
self._input_file_path = (self._base_path / f'{self._city.name}_sra_SW.out')
self._month_hour = self._month_hour_data_frame
self._results = self._read_results()
self._radiation_list = []
@property
def _month_hour_data_frame(self):
array = []
for i in range(0, 12):
days_of_month = cal.monthrange(2015, i+1)[1]
total_hours = days_of_month * 24
array = np.concatenate((array, np.full(total_hours, i + 1)))
return pd.DataFrame(array, columns=[cte.MONTH])
def _get_mean_values(self, values):
out = None
if values is not None:
if cte.MONTH not in values.columns:
values = pd.concat([self._month_hour, pd.DataFrame(values)], axis=1)
out = values.groupby(cte.MONTH, as_index=False).mean()
del out[cte.MONTH]
return out
def _read_results(self):
try:
return pd.read_csv(self._input_file_path, sep='\s+', header=0)
except Exception:
raise Exception('No SRA output file found')
@property
def _radiation(self) -> []:
if len(self._radiation_list) == 0:
id_building = ''
header_building = []
for column in self._results.columns.values:
if id_building != column.split(':')[1]:
id_building = column.split(':')[1]
if len(header_building) > 0:
self._radiation_list.append(pd.concat([self._month_hour, self._results[header_building]],axis=1))
header_building = [column]
else:
header_building.append(column)
self._radiation_list.append(pd.concat([self._month_hour, self._results[header_building]], axis=1))
return self._radiation_list
def enrich(self):
"""
saves in building surfaces the correspondent irradiance at different time-scales depending on the mode
if building is None, it saves all buildings' surfaces in file, if building is specified, it saves only that
specific building values
:return: none
"""
for radiation in self._radiation:
city_object_name = radiation.columns.values.tolist()[1].split(':')[1]
building = self._city.city_object(city_object_name)
for column in radiation.columns.values:
if column == cte.MONTH:
continue
header_id = column
surface_id = header_id.split(':')[2]
surface = building.surface_by_id(surface_id)
new_value = pd.DataFrame(radiation[[header_id]].to_numpy(), columns=['sra'])
month_new_value = self._get_mean_values(new_value)
if cte.MONTH not in surface.global_irradiance:
surface.global_irradiance[cte.MONTH] = month_new_value
else:
pd.concat([surface.global_irradiance[cte.MONTH], month_new_value], axis=1)
if cte.HOUR not in surface.global_irradiance:
surface.global_irradiance[cte.HOUR] = new_value
else:
pd.concat([surface.global_irradiance[cte.HOUR], new_value], axis=1)

View File

@ -0,0 +1,42 @@
"""
Result factory retrieve the specific tool results and store the data in the given city
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
"""
from pathlib import Path
from hub.helpers.utils import validate_import_export_type
from hub.hub_logger import logger
from hub.imports.results.simplified_radiosity_algorithm import SimplifiedRadiosityAlgorithm
class ResultFactory:
"""
UsageFactory class
"""
def __init__(self, handler, city, base_path=None):
if base_path is None:
base_path = Path(Path(__file__).parent.parent / 'data/results')
self._handler = '_' + handler.lower().replace(' ', '_')
class_funcs = validate_import_export_type(ResultFactory)
if self._handler not in class_funcs:
err_msg = f"Wrong import type [{self._handler}]. Valid functions include {class_funcs}"
logger.error(err_msg)
raise Exception(err_msg)
self._city = city
self._base_path = base_path
def _sra(self):
"""
Enrich the city with Simplified Radiosity Algorithm results
"""
SimplifiedRadiosityAlgorithm(self._city, self._base_path).enrich()
def enrich(self):
"""
Enrich the city given to the class using the usage factory given handler
:return: None
"""
getattr(self, self._handler, lambda: None)()

View File

@ -72,6 +72,7 @@ setup(
'hub.imports.geometry', 'hub.imports.geometry',
'hub.imports.geometry.citygml_classes', 'hub.imports.geometry.citygml_classes',
'hub.imports.geometry.helpers', 'hub.imports.geometry.helpers',
'hub.imports.results',
'hub.imports.usage', 'hub.imports.usage',
'hub.imports.weather', 'hub.imports.weather',
'hub.imports.weather.helpers', 'hub.imports.weather.helpers',