Skip to content

Commit 50080da

Browse files
committed
Enable usage of custom weather data
Instead of only DWD weather data files, custom weather data can now be used. In the config dictionary, set 'weather_data_type' to 'None' and store a DataFrame containing the columns 'TAMB' (ambient temperature in °C) and 'CCOVER' (cloud coverage in octas) in the key 'weather_file'.
1 parent 215c874 commit 50080da

3 files changed

Lines changed: 61 additions & 19 deletions

File tree

lpagg/VDI4655.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
called 'config_file', the location of which is defined down below.
7272
"""
7373

74+
import os
7475
import pandas as pd
7576
import functools
7677
import logging
@@ -98,6 +99,32 @@ def run_demandlib(weather_data, cfg):
9899
"""
99100
from demandlib import vdi
100101

102+
def climate_from_custom_weather(weather, try_region):
103+
"""Create a Climate object from a DataFrame with weather data."""
104+
vdi.Climate().check_try_region(try_region)
105+
106+
weather = weather.resample("D").mean()
107+
108+
weather.loc[weather["CCOVER"] >= 5, "cloud_category"] = "B"
109+
weather.loc[weather["CCOVER"] < 5, "cloud_category"] = "H"
110+
111+
fn_energy_factors = os.path.join(
112+
os.path.dirname(vdi.__file__),
113+
"vdi_data",
114+
"VDI_4655_Typtag-Faktoren.csv",
115+
)
116+
energy_factors = pd.read_csv(
117+
fn_energy_factors,
118+
index_col=[0, 1, 2],
119+
).loc[try_region]
120+
121+
climate = vdi.Climate(
122+
temperature=weather["TAMB"],
123+
cloud_coverage=weather["cloud_category"],
124+
energy_factors=energy_factors,
125+
)
126+
return climate
127+
101128
settings = cfg['settings']
102129
houses_list = settings['houses_list_VDI']
103130

@@ -153,6 +180,11 @@ def run_demandlib(weather_data, cfg):
153180
try:
154181
if settings['weather_file'] is None:
155182
climate = vdi.Climate().from_try_data(int(try_region))
183+
elif isinstance(settings['weather_file'], vdi.Climate):
184+
climate = settings['weather_file']
185+
elif isinstance(settings['weather_file'], pd.DataFrame):
186+
climate = climate_from_custom_weather(
187+
settings['weather_file'], try_region)
156188
else:
157189
climate = vdi.Climate().from_dwd_weather_file(
158190
settings['weather_file'], try_region)

lpagg/agg.py

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,10 @@ def perform_configuration(config_file='', cfg=None, ignore_errors=False):
135135
cfg['settings'].get('result_folder',
136136
'Result')))
137137

138-
weather_file = os.path.join(cfg['base_folder'], settings['weather_file'])
139-
cfg['settings']['weather_file'] = os.path.abspath(weather_file)
138+
if not isinstance(settings['weather_file'], pd.DataFrame):
139+
weather_file = os.path.join(cfg['base_folder'],
140+
settings['weather_file'])
141+
cfg['settings']['weather_file'] = os.path.abspath(weather_file)
140142

141143
language = cfg['settings'].get('language', 'en')
142144
if language == 'de':
@@ -522,7 +524,7 @@ def postprocess_unique_profiles(agg_dict, cfg,
522524
txt = ("Annual sums of individual profiles do not "
523525
"match the input sums. When using dtype 'float32', "
524526
"this can be expected to occur.")
525-
if df_unique.sum() == df_lc.sum().sum():
527+
if df_unique.sum().round(8) == df_lc.sum().sum().round(8):
526528
txt += (" However, the total annual sum of all profiles is "
527529
"correct.")
528530
logger.warning(txt)
@@ -601,15 +603,12 @@ def load_weather_file(cfg):
601603
except TypeError: # Read as Timestamp objects otherwise
602604
datetime_start = settings['start']
603605
datetime_end = settings['end']
604-
# datetime_start = datetime.datetime(2017,1,1,00,00,00) # Example
605-
# datetime_end = datetime.datetime(2018,1,1,00,00,00)
606+
606607
interpolation_freq = pd.Timedelta(settings['intervall'])
607-
# interpolation_freq = pd.Timedelta('14 minutes')
608-
# interpolation_freq = pd.Timedelta('1 hours')
609608
remove_leapyear = settings.get('remove_leapyear', False)
610-
611609
settings['interpolation_freq'] = interpolation_freq
612-
logger.info('Read and interpolate the data in weather file '+weather_file)
610+
logger.info('Read and interpolate the data in weather file %s',
611+
weather_file)
613612

614613
# Call external method in weather_converter.py:
615614
weather_data = lpagg.weather_converter.interpolate_weather_file(
@@ -620,11 +619,15 @@ def load_weather_file(cfg):
620619
interpolation_freq,
621620
remove_leapyear)
622621

623-
# Analyse weather data
624-
if logger.isEnabledFor(logging.INFO):
625-
lpagg.weather_converter.analyse_weather_file(
626-
weather_data, interpolation_freq, weather_file,
627-
print_folder=cfg['print_folder'])
622+
try:
623+
# Analyse weather data
624+
if logger.isEnabledFor(logging.INFO):
625+
lpagg.weather_converter.analyse_weather_file(
626+
weather_data, interpolation_freq, weather_file,
627+
print_folder=cfg['print_folder'])
628+
except KeyError:
629+
pass
630+
628631
weather_data.index.name = 'Time'
629632
return weather_data
630633

lpagg/weather_converter.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -484,23 +484,30 @@ def interpolate_weather_file(weather_file_path,
484484
# plot_value = 'CCOVER'
485485
# plot_value = 'PAMB'
486486

487-
weather_file = os.path.basename(weather_file_path)
488487

489488
# Read the file and store it in a DataFrame
490489
if weather_data_type == 'IGS' or weather_data_type == 'TRNSYS':
491490
weather_data = read_IGS_weather_file(weather_file_path)
492491
elif weather_data_type == 'DWD':
493492
weather_data = read_DWD_weather_file(weather_file_path)
493+
elif weather_data_type is None:
494+
# Assume the object already is a DataFrame with correct columns
495+
weather_data = weather_file_path
494496
else:
495497
logger.error('Weather data type "'+weather_data_type+'" unknown!')
496498
exit()
497499

498500
# Assumption: The IGS weather files always start at January 01.
499501
current_year = datetime_start.year
500502
newyear = datetime.datetime(current_year, 1, 1)
501-
# Convert hours of year to DateTime and make that the index of DataFrame
502-
weather_data.index = pd.to_timedelta(weather_data['HOUR'],
503-
unit='h') + newyear
503+
504+
if weather_data_type is not None:
505+
weather_file = os.path.basename(weather_file_path)
506+
# Convert hours of year to DateTime and make that the index of DataFrame
507+
weather_data.index = pd.to_timedelta(weather_data['HOUR'],
508+
unit='h') + newyear
509+
else:
510+
weather_file = "Weather Data"
504511

505512
# Infer the time frequency of the original data
506513
original_freq = pd.infer_freq(weather_data.index)
@@ -568,7 +575,7 @@ def interpolate_weather_file(weather_file_path,
568575

569576
# Remove leapyear from DataFrame (optional)
570577
if calendar.isleap(current_year) is True:
571-
logger.warn(str(current_year)+' is a leap year. Be careful!')
578+
logger.warning(str(current_year)+' is a leap year. Be careful!')
572579
if remove_leapyear is True:
573580
weather_data = weather_data[~((weather_data.index.month == 2) &
574581
(weather_data.index.day == 29))]

0 commit comments

Comments
 (0)