Skip to content

Commit dea9f4e

Browse files
committed
Update for compatibility with demandlib v0.2.2
1 parent f796c68 commit dea9f4e

1 file changed

Lines changed: 80 additions & 32 deletions

File tree

lpagg/VDI4655.py

Lines changed: 80 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373

7474
import os
7575
import pandas as pd
76+
import numpy as np
7677
import functools
7778
import logging
7879
import pickle
@@ -99,10 +100,59 @@ def run_demandlib(weather_data, cfg):
99100
"""
100101
from demandlib import vdi
101102

103+
def climate_from_dwd_weather_file(fn_weather, try_region, hoy=8760):
104+
"""
105+
Create a demandlib climate object from a DWD weather file.
106+
107+
The weather file must adhere to the standard of the TRY weather
108+
data published in 2016 by the German weather service DWD,
109+
available at https://kunden.dwd.de/obt/.
110+
111+
.. note::
112+
113+
``climate_from_dwd_weather_file()`` enables users to load the
114+
most recent DWD test reference year weather files **at their
115+
own risk**. They still need to provide a TRY region number,
116+
which is required for loading the energy factors.
117+
These are used for scaling the typical days relative to each
118+
other, depending on the TRY region. But users need to be aware
119+
that they do not have the originally intended effect when
120+
used with different weather data.
121+
122+
Other file types are currently not supported. Instead, users
123+
need to create a ``Climate()`` object and provide temperature
124+
and cloud coverage time series, as well as matching energy
125+
factors.
126+
127+
Parameters
128+
----------
129+
fn_weather : str
130+
Name of the weather data file to load.
131+
try_region : int
132+
Number of the test-reference-year region where the building
133+
is located, as defined by the German weather service DWD.
134+
The module ``dwd_try`` provides the function ``find_try_region()``
135+
to find the correct region for given coordinates.
136+
hoy : int, optional
137+
Number of hours of the year. The default is 8760.
138+
"""
139+
weather = vdi.dwd_try.read_dwd_weather_file(fn_weather)
140+
weather = (
141+
weather.set_index(
142+
pd.date_range(
143+
dt.datetime(2010, 1, 1, 0),
144+
periods=hoy,
145+
freq="h",
146+
)
147+
)
148+
.resample("D")
149+
.mean()
150+
)
151+
climate = climate_from_custom_weather(weather, try_region)
152+
return climate
153+
102154
def climate_from_custom_weather(weather, try_region):
103155
"""Create a Climate object from a DataFrame with weather data."""
104-
vdi.Climate().check_try_region(try_region)
105-
106156
weather = weather.resample("D").mean()
107157

108158
weather.loc[weather["CCOVER"] >= 5, "cloud_category"] = "B"
@@ -163,6 +213,11 @@ def climate_from_custom_weather(weather, try_region):
163213
house_dict_demandlib.pop("copies", None)
164214
house_dict_demandlib.pop("sigma", None)
165215
house_dict_demandlib.pop("Q_Kalt_a", None)
216+
# This should not be necessary, but in demandlib v0.2.2 requries
217+
# even unused energies to be defined
218+
house_dict_demandlib.setdefault("Q_Heiz_a", np.nan)
219+
house_dict_demandlib.setdefault("W_a", np.nan)
220+
house_dict_demandlib.setdefault("Q_TWW_a", np.nan)
166221
my_houses.append(house_dict_demandlib)
167222

168223
if len(my_houses) == 0:
@@ -177,41 +232,34 @@ def climate_from_custom_weather(weather, try_region):
177232
dtype='float')
178233
df_empty.columns.set_names('name', inplace=True)
179234

180-
try:
181-
if settings['weather_file'] is None:
182-
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)
188-
else:
189-
climate = vdi.Climate().from_dwd_weather_file(
190-
settings['weather_file'], try_region)
191-
192-
my_region = vdi.Region(
193-
year,
194-
holidays=holidays_dict,
195-
climate=climate,
196-
houses=my_houses,
197-
resample_rule=pd.Timedelta(settings.get('intervall', '1 hours')),
198-
zero_summer_heat_demand=settings.get('zero_summer_heat_demand'),
199-
)
200-
except AttributeError:
201-
my_region = vdi.Region(
202-
year,
203-
holidays=holidays_dict,
204-
try_region=try_region,
205-
houses=my_houses,
206-
resample_rule=pd.Timedelta(settings.get('intervall', '1 hours')),
207-
file_weather=settings['weather_file'],
208-
zero_summer_heat_demand=settings.get('zero_summer_heat_demand'),
209-
)
235+
# Allow different options for creating the climate and region classes
236+
if settings['weather_file'] is None:
237+
climate = vdi.Climate().from_try_data(int(try_region))
238+
elif isinstance(settings['weather_file'], vdi.Climate):
239+
climate = settings['weather_file']
240+
elif isinstance(settings['weather_file'], pd.DataFrame):
241+
climate = climate_from_custom_weather(
242+
settings['weather_file'], try_region)
243+
else:
244+
climate = climate_from_dwd_weather_file(
245+
settings['weather_file'], try_region)
246+
247+
my_region = vdi.Region(
248+
year,
249+
holidays=holidays_dict,
250+
climate=climate,
251+
houses=my_houses,
252+
resample_rule=pd.Timedelta(settings.get('intervall', '1 hours')),
253+
zero_summer_heat_demand=settings.get('zero_summer_heat_demand'),
254+
)
210255

211256
# Calculate load profiles
212257
logger.info('Create %s VDI 4655 profiles with demandlib', len(my_houses))
213258
lc = my_region.get_load_curve_houses()
214259

260+
# Drop unused (nan) columns
261+
lc = lc.dropna(how='all', axis='columns')
262+
215263
# Demandlib uses a different time step notation then lpagg
216264
lc = lc.shift(periods=1, freq="infer").droplevel('house_type',
217265
axis='columns')

0 commit comments

Comments
 (0)