forked from s_ranjbar/city_retrofit
created epw_weather_parameters.py
This commit is contained in:
parent
8fc66b7060
commit
ac902c6c97
|
@ -42,7 +42,6 @@ class Surface:
|
|||
self._name = uuid.uuid4()
|
||||
return self._name
|
||||
|
||||
|
||||
@property
|
||||
def swr(self):
|
||||
"""
|
||||
|
|
|
@ -32,6 +32,9 @@ class City:
|
|||
# todo: right now extracted at city level, in the future should be extracted also at building level if exist
|
||||
self._location = None
|
||||
self._country_code = None
|
||||
self._latitude = None
|
||||
self._longitude = None
|
||||
self._time_zone = None
|
||||
|
||||
@property
|
||||
def _get_location(self):
|
||||
|
@ -196,3 +199,11 @@ class City:
|
|||
if distance < radius:
|
||||
selected_region_city.add_city_object(city_object)
|
||||
return selected_region_city
|
||||
|
||||
@property
|
||||
def latitude(self):
|
||||
"""
|
||||
city latitude in degrees
|
||||
:return: real
|
||||
"""
|
||||
return self._latitude
|
||||
|
|
8768
data/weather/epw/CAN_BC_Summerland.717680_CWEC.epw
Normal file
8768
data/weather/epw/CAN_BC_Summerland.717680_CWEC.epw
Normal file
File diff suppressed because it is too large
Load Diff
|
@ -1,11 +1,12 @@
|
|||
"""
|
||||
WeatherFactory retrieve the specific weather module for the given source format
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2020 Project Author Pilar Monsalvete pilar_monsalvete@yahoo.es
|
||||
Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
from pathlib import Path
|
||||
from imports.weather_feeders.dat_weather_parameters import DatWeatherParameters
|
||||
from imports.weather_feeders.xls_weather_parameters import XlsWeatherParameters
|
||||
from imports.weather_feeders.epw_weather_parameters import EpwWeatherParameters
|
||||
|
||||
|
||||
class WeatherFactory:
|
||||
|
@ -13,18 +14,29 @@ class WeatherFactory:
|
|||
WeatherFactory class
|
||||
"""
|
||||
|
||||
def __init__(self, handler, city, city_name, base_path=Path(Path(__file__).parent.parent / 'data/weather')):
|
||||
def __init__(self, handler, city, base_path=Path(Path(__file__).parent.parent / 'data/weather'), file_name=None):
|
||||
self._handler = '_' + handler.lower().replace(' ', '_')
|
||||
self._city = city
|
||||
self._base_path = base_path
|
||||
self._city_name = city_name
|
||||
self._file_name = file_name
|
||||
|
||||
def _dat(self):
|
||||
DatWeatherParameters(self._city, self._base_path, self._city_name)
|
||||
DatWeatherParameters(self._city, self._base_path)
|
||||
|
||||
def _tmy(self):
|
||||
def _tmy3(self):
|
||||
raise Exception('Not implemented')
|
||||
|
||||
def _tm2(self):
|
||||
# Meteonorm (https://meteonorm.com/en/product/typical-years)
|
||||
raise Exception('Not implemented')
|
||||
|
||||
def _epw(self):
|
||||
# EnergyPlus Weather
|
||||
# to download files: https://energyplus.net/weather
|
||||
# description of the format: https://energyplus.net/sites/default/files/pdfs_v8.3.0/AuxiliaryPrograms.pdf
|
||||
_path = Path(self._base_path / 'epw').resolve()
|
||||
EpwWeatherParameters(self._city, _path, self._file_name)
|
||||
|
||||
def _xls(self):
|
||||
name = 'ISO_52016_1_BESTEST_ClimData_2016.08.24'
|
||||
XlsWeatherParameters(self._city, self._base_path, name)
|
||||
|
|
|
@ -13,10 +13,11 @@ class DatWeatherParameters:
|
|||
"""
|
||||
DatWeatherParameters class
|
||||
"""
|
||||
def __init__(self, city, path, name):
|
||||
def __init__(self, city, path):
|
||||
self._weather_values = None
|
||||
self._city = city
|
||||
self._city_name = name
|
||||
# todo: change it to reference_weather_city_name
|
||||
self._city_name = city.name
|
||||
file_name = 'inseldb_' + self._city_name + '.dat'
|
||||
self._path = Path(path / file_name)
|
||||
|
||||
|
|
109
imports/weather_feeders/epw_weather_parameters.py
Normal file
109
imports/weather_feeders/epw_weather_parameters.py
Normal file
|
@ -0,0 +1,109 @@
|
|||
"""
|
||||
EpwWeatherParameters class to extract weather parameters from a defined region in .epw format (EnergyPlus Weather)
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
|
||||
import pandas as pd
|
||||
from pathlib import Path
|
||||
import sys
|
||||
|
||||
|
||||
class EpwWeatherParameters:
|
||||
"""
|
||||
EpwWeatherParameters class
|
||||
"""
|
||||
def __init__(self, city, path, file_name):
|
||||
self._weather_values = None
|
||||
self._city = city
|
||||
self._path = Path(path / file_name)
|
||||
|
||||
try:
|
||||
file = open(self._path, 'r')
|
||||
line = file.readline().split(',')
|
||||
city_name = line[1]
|
||||
latitude = line[6]
|
||||
longitude = line[7]
|
||||
time_zone = line[8]
|
||||
for i in range(0, 2):
|
||||
line = file.readline().split(',')
|
||||
line = file.readline().split(',')
|
||||
number_records = int(line[1])
|
||||
depth_measurement_ground_temperature = []
|
||||
ground_temperature = []
|
||||
for i in range(0, number_records):
|
||||
depth_measurement_ground_temperature.append(line[i*16+2])
|
||||
temperatures = []
|
||||
for j in range(0, 12):
|
||||
temperatures.append(line[i*16+j+6])
|
||||
ground_temperature.append(temperatures)
|
||||
file.close()
|
||||
except SystemExit:
|
||||
sys.stderr.write(f'Error: weather file {self._path} not found. Please download it from '
|
||||
f'https://energyplus.net/weather and place it in folder data\weather\epw\n')
|
||||
sys.exit()
|
||||
|
||||
if self._weather_values is None:
|
||||
try:
|
||||
self._weather_values = pd.read_csv(self._path, header=0, skiprows=8,
|
||||
names=['year', 'month', 'day', 'hour', 'minute',
|
||||
'data_source_and_uncertainty_flags',
|
||||
'dry_bulb_temperature_c', 'dew_point_temperature_c',
|
||||
'relative_humidity_perc',
|
||||
'atmospheric_station_pressure_pa',
|
||||
'extraterrestrial_horizontal_radiation_wh_m2',
|
||||
'extraterrestrial_direct_normal_radiation_wh_m2',
|
||||
'horizontal_infrared_radiation_intensity_wh_m2',
|
||||
'global_horizontal_radiation_wh_m2', 'direct_normal_radiation_wh_m2',
|
||||
'diffuse_horizontal_radiation_wh_m2',
|
||||
'global_horizontal_illuminance_lux',
|
||||
'direct_normal_illuminance_lux', 'diffuse_horizontal_illuminance_lux',
|
||||
'zenith_luminance_cd_m2',
|
||||
'wind_direction_deg', 'wind_speed_m_s', 'total_sky_cover',
|
||||
'opaque_sky_cover', 'visibility_km',
|
||||
'ceiling_heigh_m_s', 'present_weather_observation',
|
||||
'present_weather_codes',
|
||||
'precipitable_water_mm', 'aerosol_optical_depth_10_3_ths',
|
||||
'snow_depth_cm',
|
||||
'days_since_last_snowfall', 'albedo', 'liquid_precipitation_depth_mm',
|
||||
'liquid_precipitation_quality_hr'])
|
||||
except SystemExit:
|
||||
sys.stderr.write(f'Error: wrong formatting of weather file {self._path}\n')
|
||||
sys.exit()
|
||||
|
||||
for building in self._city.buildings:
|
||||
new_value = pd.DataFrame(self._weather_values[['dry_bulb_temperature_c']].to_numpy(), columns=['epw'])
|
||||
number_invalid_records = new_value[new_value.epw == 99.9].count()['epw']
|
||||
if number_invalid_records > 0:
|
||||
sys.stderr.write(f'Warning: {self._path} invalid records (value of 99.9) in dry bulb temperature\n')
|
||||
if 'hour' not in building.external_temperature:
|
||||
building.external_temperature['hour'] = new_value
|
||||
else:
|
||||
pd.concat([building.external_temperature['hour'], new_value], axis=1)
|
||||
|
||||
new_value = pd.DataFrame(self._weather_values[['global_horizontal_radiation_wh_m2']].to_numpy(), columns=['epw'])
|
||||
number_invalid_records = new_value[new_value.epw == 9999].count()['epw']
|
||||
if number_invalid_records > 0:
|
||||
sys.stderr.write(f'Warning: {self._path} invalid records (value of 9999) in global horizontal radiation\n')
|
||||
if 'hour' not in building.global_horizontal:
|
||||
building.global_horizontal['hour'] = new_value
|
||||
else:
|
||||
pd.concat([building.global_horizontal['hour'], new_value], axis=1)
|
||||
|
||||
new_value = pd.DataFrame(self._weather_values[['diffuse_horizontal_radiation_wh_m2']].to_numpy(), columns=['epw'])
|
||||
number_invalid_records = new_value[new_value.epw == 9999].count()['epw']
|
||||
if number_invalid_records > 0:
|
||||
sys.stderr.write(f'Warning: {self._path} invalid records (value of 9999) in diffuse horizontal radiation\n')
|
||||
if 'hour' not in building.diffuse:
|
||||
building.diffuse['hour'] = new_value
|
||||
else:
|
||||
pd.concat([building.diffuse['hour'], new_value], axis=1)
|
||||
|
||||
new_value = pd.DataFrame(self._weather_values[['direct_normal_radiation_wh_m2']].to_numpy(), columns=['epw'])
|
||||
number_invalid_records = new_value[new_value.epw == 9999].count()['epw']
|
||||
if number_invalid_records > 0:
|
||||
sys.stderr.write(f'Warning: {self._path} invalid records (value of 9999) in direct horizontal radiation\n')
|
||||
if 'hour' not in building.beam:
|
||||
building.beam['hour'] = new_value
|
||||
else:
|
||||
pd.concat([building.beam['hour'], new_value], axis=1)
|
|
@ -22,7 +22,7 @@ class TestWeatherFactory(TestCase):
|
|||
self._city_gml = None
|
||||
self._city_with_weather = None
|
||||
self._city_name = 'new_york_city'
|
||||
self._example_path = (Path(__file__).parent / 'tests_data').resolve()
|
||||
self._example_path = (Path(__file__).parent.parent / 'data' / 'weather').resolve()
|
||||
|
||||
def _get_citygml(self, file_path):
|
||||
self._city_gml = GeometryFactory('citygml', file_path).city
|
||||
|
@ -33,7 +33,7 @@ class TestWeatherFactory(TestCase):
|
|||
if self._city_with_weather is None:
|
||||
file_path = (Path(__file__).parent / 'tests_data' / '20buildings.gml').resolve()
|
||||
self._city_with_weather = self._get_citygml(file_path)
|
||||
WeatherFactory('dat', self._city_with_weather, city_name=self._city_name, base_path=self._example_path).enrich()
|
||||
WeatherFactory('dat', self._city_with_weather, base_path=self._example_path).enrich()
|
||||
return self._city_with_weather
|
||||
|
||||
def test_city_with_weather(self):
|
||||
|
@ -55,9 +55,20 @@ class TestWeatherFactory(TestCase):
|
|||
def test_weather_xls(self):
|
||||
file_path = (Path(__file__).parent / 'tests_data' / 'iso_52016_1_2017_lod2.gml').resolve()
|
||||
city_with_weather = self._get_citygml(file_path)
|
||||
WeatherFactory('xls', city_with_weather, city_name=self._city_name, base_path=self._example_path).enrich()
|
||||
WeatherFactory('xls', city_with_weather, base_path=self._example_path).enrich()
|
||||
for building in city_with_weather.buildings:
|
||||
values = building.external_temperature['hour'][['iso52016']]
|
||||
self.assertFalse(values.empty, 'wrong value external_temperature')
|
||||
values = building.global_horizontal['hour'][['iso52016']]
|
||||
self.assertFalse(values.empty, 'wrong value global horizontal')
|
||||
|
||||
def test_weather_epw(self):
|
||||
file_path = (Path(__file__).parent / 'tests_data' / 'one_building_in_kelowna.gml').resolve()
|
||||
city_with_weather = self._get_citygml(file_path)
|
||||
_file_name = 'CAN_BC_Summerland.717680_CWEC.epw'
|
||||
WeatherFactory('epw', city_with_weather, base_path=self._example_path, file_name=_file_name).enrich()
|
||||
for building in city_with_weather.buildings:
|
||||
values = building.external_temperature['hour'][['epw']]
|
||||
self.assertFalse(values.empty, 'wrong value external_temperature')
|
||||
values = building.global_horizontal['hour'][['epw']]
|
||||
self.assertFalse(values.empty, 'wrong value global horizontal')
|
||||
|
|
Loading…
Reference in New Issue
Block a user