OpenDHW 0.2.7__tar.gz → 0.2.9__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {opendhw-0.2.7 → opendhw-0.2.9}/OpenDHW/Data/prob_nonresidential.json +2 -2
- {opendhw-0.2.7 → opendhw-0.2.9}/OpenDHW/OpenDHW.py +81 -34
- {opendhw-0.2.7 → opendhw-0.2.9}/OpenDHW/__init__.py +1 -1
- {opendhw-0.2.7 → opendhw-0.2.9/OpenDHW.egg-info}/PKG-INFO +1 -1
- {opendhw-0.2.7/OpenDHW.egg-info → opendhw-0.2.9}/PKG-INFO +1 -1
- {opendhw-0.2.7 → opendhw-0.2.9}/LICENSE +0 -0
- {opendhw-0.2.7 → opendhw-0.2.9}/OpenDHW/Data/__init__.py +0 -0
- {opendhw-0.2.7 → opendhw-0.2.9}/OpenDHW/Data/prob_residential.json +0 -0
- {opendhw-0.2.7 → opendhw-0.2.9}/OpenDHW/utils/OpenDHW_Utilities.py +0 -0
- {opendhw-0.2.7 → opendhw-0.2.9}/OpenDHW/utils/__init__.py +0 -0
- {opendhw-0.2.7 → opendhw-0.2.9}/OpenDHW.egg-info/SOURCES.txt +0 -0
- {opendhw-0.2.7 → opendhw-0.2.9}/OpenDHW.egg-info/dependency_links.txt +0 -0
- {opendhw-0.2.7 → opendhw-0.2.9}/OpenDHW.egg-info/requires.txt +0 -0
- {opendhw-0.2.7 → opendhw-0.2.9}/OpenDHW.egg-info/top_level.txt +0 -0
- {opendhw-0.2.7 → opendhw-0.2.9}/README.md +0 -0
- {opendhw-0.2.7 → opendhw-0.2.9}/setup.cfg +0 -0
- {opendhw-0.2.7 → opendhw-0.2.9}/setup.py +0 -0
|
@@ -162,7 +162,7 @@ def import_from_dhwcalc(s_step, daylight_saving, categories,occupancy,
|
|
|
162
162
|
return timeseries_df
|
|
163
163
|
|
|
164
164
|
|
|
165
|
-
def generate_dhw_profile(s_step, categories, mean_drawoff_vol_per_day, occupancy, holidays, building_type, weekend_weekday_factor, initial_day=0):
|
|
165
|
+
def generate_dhw_profile(s_step, categories, mean_drawoff_vol_per_day, occupancy, holidays, building_type, weekend_weekday_factor, initial_day=0, occupancy_profile=None):
|
|
166
166
|
"""
|
|
167
167
|
Generates a DHW profile. The generation is split up in different
|
|
168
168
|
functions and generally follows the methodology described in the DHWcalc
|
|
@@ -178,7 +178,12 @@ def generate_dhw_profile(s_step, categories, mean_drawoff_vol_per_day, occupancy
|
|
|
178
178
|
:param categories: int: 1 or 4 (see DHWcalc)
|
|
179
179
|
:param weekend_weekday_factor: int: taken from DHWcalc
|
|
180
180
|
:param mean_drawoff_vol_per_day: int: daily water demand in Liters
|
|
181
|
+
:param occupancy: float: occupancy of the building, between 0 and 1, multiplies the water demand
|
|
182
|
+
:param holidays: list: list of holidays (day of year, 1-365)
|
|
183
|
+
:param building_type: string: type of building, determines which days are off days
|
|
181
184
|
:param initial_day: int: 0:Mon - 1:Tues ... 6:Sun
|
|
185
|
+
:param occupancy_profile: list: optional profile to adjust the probabilities, has to fit in length to p_final (s_step)
|
|
186
|
+
|
|
182
187
|
:return: timeseries_df df: dataframe with all timeseries
|
|
183
188
|
"""
|
|
184
189
|
|
|
@@ -199,7 +204,8 @@ def generate_dhw_profile(s_step, categories, mean_drawoff_vol_per_day, occupancy
|
|
|
199
204
|
weekend_weekday_factor=weekend_weekday_factor,
|
|
200
205
|
holidays = holidays,
|
|
201
206
|
initial_day=initial_day,
|
|
202
|
-
building_type=building_type
|
|
207
|
+
building_type=building_type,
|
|
208
|
+
occupancy_profile=occupancy_profile
|
|
203
209
|
)
|
|
204
210
|
|
|
205
211
|
# --- empty drawoffs list, will be filled afterwards
|
|
@@ -379,7 +385,7 @@ def generate_daily_probability_step_function(mode, s_step,building_type, save_fi
|
|
|
379
385
|
|
|
380
386
|
|
|
381
387
|
def generate_yearly_probability_profile(s_step, weekend_weekday_factor,building_type, holidays,
|
|
382
|
-
initial_day=0):
|
|
388
|
+
initial_day=0, occupancy_profile=None):
|
|
383
389
|
"""
|
|
384
390
|
generate a summed yearly probability profile. The whole function is
|
|
385
391
|
deterministic. The same inputs always produce the same outputs.
|
|
@@ -394,6 +400,10 @@ def generate_yearly_probability_profile(s_step, weekend_weekday_factor,building_
|
|
|
394
400
|
:param s_step: int: seconds in a timestep
|
|
395
401
|
:param weekend_weekday_factor: float: shift probabilities towards weekend
|
|
396
402
|
:param initial_day: int: Mon: 0 ... Sun: 6
|
|
403
|
+
:param holidays: list: list of holidays (day of year, 1-365)
|
|
404
|
+
:param building_type: string: type of building, determines which days are off days
|
|
405
|
+
:param occupancy_profile: list: optional profile to adjust the probabilities, has to fit in length to p_final
|
|
406
|
+
|
|
397
407
|
:return: timeseries_df: df: df that holds the yearly profile
|
|
398
408
|
"""
|
|
399
409
|
|
|
@@ -424,7 +434,8 @@ def generate_yearly_probability_profile(s_step, weekend_weekday_factor,building_
|
|
|
424
434
|
p_work_day=p_wd_weighted,
|
|
425
435
|
s_step=s_step,
|
|
426
436
|
holidays=holidays,
|
|
427
|
-
building_type=building_type
|
|
437
|
+
building_type=building_type,
|
|
438
|
+
occupancy_profile=occupancy_profile
|
|
428
439
|
)
|
|
429
440
|
|
|
430
441
|
# sum and normalize to range between 0 and 1.
|
|
@@ -460,7 +471,7 @@ def shift_weekend_weekday(p_work_day, p_off_day, factor):
|
|
|
460
471
|
|
|
461
472
|
assert p_wd_factor * 5 / 7 + p_we_factor * 2 / 7 == 1
|
|
462
473
|
|
|
463
|
-
p_wd_weighted = [p *
|
|
474
|
+
p_wd_weighted = [p * p_wd_factor for p in p_work_day]
|
|
464
475
|
p_we_weighted = [p * p_we_factor for p in p_off_day]
|
|
465
476
|
|
|
466
477
|
av_p_wd_weighted = statistics.mean(p_wd_weighted)
|
|
@@ -472,18 +483,20 @@ def shift_weekend_weekday(p_work_day, p_off_day, factor):
|
|
|
472
483
|
|
|
473
484
|
|
|
474
485
|
def generate_yearly_probabilities(initial_day, p_off_day, p_work_day,
|
|
475
|
-
s_step, holidays,building_type, plot_p_yearly=False):
|
|
486
|
+
s_step, holidays,building_type, plot_p_yearly=False, occupancy_profile=None):
|
|
476
487
|
"""
|
|
477
488
|
Takes the probabilities of a working days and a off days and generates a
|
|
478
489
|
list of yearly probabilities by adding a seasonal probability factor.
|
|
479
490
|
The seasonal factor is a sine-function, like in DHWcalc.
|
|
480
491
|
|
|
481
|
-
:param initial_day: int: 0: Mon, 1: Tue, 2: Wed, 3: Thur, 4: Fri,
|
|
482
|
-
5 : Sat, 6 : Sun
|
|
492
|
+
:param initial_day: int: 0: Mon, 1: Tue, 2: Wed, 3: Thur, 4: Fri, 5 : Sat, 6 : Sun
|
|
483
493
|
:param p_off_day: list: probabilities of an off day
|
|
484
494
|
:param p_work_day: list: probabilities of a working day
|
|
485
495
|
:param s_step: int: seconds within a timestep
|
|
486
496
|
:param plot_p_yearly: bool: plot the yearly probabilities
|
|
497
|
+
:param holidays: list: list of holidays (day of year, 1-365)
|
|
498
|
+
:param building_type: string: type of building, determines which days are off days
|
|
499
|
+
:param occupancy_profile: list: optional profile to adjust the probabilities, has to fit in length to p_final
|
|
487
500
|
|
|
488
501
|
:return: p_final: list: probabilities of a full year
|
|
489
502
|
"""
|
|
@@ -517,6 +530,40 @@ def generate_yearly_probabilities(initial_day, p_off_day, p_work_day,
|
|
|
517
530
|
probability = p_day[step] * probability_season
|
|
518
531
|
p_final.append(probability)
|
|
519
532
|
|
|
533
|
+
p_final = np.array(p_final)
|
|
534
|
+
|
|
535
|
+
if occupancy_profile is not None:
|
|
536
|
+
occupancy_profile = np.asarray(occupancy_profile, dtype=float)
|
|
537
|
+
|
|
538
|
+
if occupancy_profile.ndim != 1 or occupancy_profile.size == 0:
|
|
539
|
+
raise ValueError("occupancy_profile must be a non-empty 1-D array-like of numbers.")
|
|
540
|
+
if not np.all(np.isfinite(occupancy_profile)):
|
|
541
|
+
raise ValueError("occupancy_profile must not contain NaN or infinite values.")
|
|
542
|
+
if np.any(occupancy_profile < 0):
|
|
543
|
+
raise ValueError("occupancy_profile must not contain negative values.")
|
|
544
|
+
if not np.any(occupancy_profile):
|
|
545
|
+
raise ValueError(
|
|
546
|
+
"occupancy_profile is all zeros; this would zero out the entire "
|
|
547
|
+
"probability distribution and cause a division by zero downstream."
|
|
548
|
+
)
|
|
549
|
+
|
|
550
|
+
len_p = len(p_final)
|
|
551
|
+
len_occ = len(occupancy_profile)
|
|
552
|
+
if len_occ != len_p:
|
|
553
|
+
ratio = len_p / len_occ
|
|
554
|
+
if ratio.is_integer() and ratio > 1:
|
|
555
|
+
occupancy_profile = np.repeat(occupancy_profile, int(ratio))
|
|
556
|
+
else:
|
|
557
|
+
direction = "longer than" if len_occ > len_p else "not an integer divisor of"
|
|
558
|
+
raise ValueError(
|
|
559
|
+
f"occupancy_profile length ({len_occ}) is {direction} the target length "
|
|
560
|
+
f"({len_p}, from s_step={s_step}). occupancy_profile must either match "
|
|
561
|
+
f"the target length exactly, or be a shorter list whose length divides "
|
|
562
|
+
f"evenly into it (it will be upsampled via np.repeat); downsampling a "
|
|
563
|
+
f"longer profile is not supported."
|
|
564
|
+
)
|
|
565
|
+
p_final *= occupancy_profile
|
|
566
|
+
|
|
520
567
|
if plot_p_yearly:
|
|
521
568
|
fig, ax = plt.subplots()
|
|
522
569
|
plt.plot(p_final)
|
|
@@ -781,7 +828,7 @@ def draw_lineplot(timeseries_df, plot_var='water', start_plot='2019-02-01',
|
|
|
781
828
|
# compute some stats for figure title.
|
|
782
829
|
max_water_flow = timeseries_df['Water_LperH'].max() # in L/h
|
|
783
830
|
s_step = timeseries_df.index.freqstr
|
|
784
|
-
method = timeseries_df['method'][0]
|
|
831
|
+
method = timeseries_df['method'].iloc[0]
|
|
785
832
|
|
|
786
833
|
plt.title('Heat Time-series from {}, timestep = {}\n'
|
|
787
834
|
'with a Peak of {:.1f} L/h'.format(method, s_step,
|
|
@@ -797,10 +844,10 @@ def draw_lineplot(timeseries_df, plot_var='water', start_plot='2019-02-01',
|
|
|
797
844
|
plt.show()
|
|
798
845
|
|
|
799
846
|
if save_fig:
|
|
800
|
-
method = timeseries_df['method'][0]
|
|
847
|
+
method = timeseries_df['method'].iloc[0]
|
|
801
848
|
s_step = get_s_step(timeseries_df)
|
|
802
|
-
vol_per_day = timeseries_df['mean_drawoff_vol_per_day'][0]
|
|
803
|
-
cats = timeseries_df['categories'][0]
|
|
849
|
+
vol_per_day = timeseries_df['mean_drawoff_vol_per_day'].iloc[0]
|
|
850
|
+
cats = timeseries_df['categories'].iloc[0]
|
|
804
851
|
|
|
805
852
|
dir_output = Path.cwd() / "plots"
|
|
806
853
|
dir_output.mkdir(exist_ok=True)
|
|
@@ -825,7 +872,7 @@ def draw_histplot(timeseries_df, extra_kde=False, save_fig=False):
|
|
|
825
872
|
# get non-zero values of the profile
|
|
826
873
|
drawoffs_df = get_drawoffs(timeseries_df=timeseries_df, remove_cats=False)
|
|
827
874
|
|
|
828
|
-
cats = timeseries_df['categories'][0]
|
|
875
|
+
cats = timeseries_df['categories'].iloc[0]
|
|
829
876
|
if cats == 1:
|
|
830
877
|
drawoffs_df = drawoffs_df['Water_LperH']
|
|
831
878
|
|
|
@@ -848,10 +895,10 @@ def draw_histplot(timeseries_df, extra_kde=False, save_fig=False):
|
|
|
848
895
|
plt.show()
|
|
849
896
|
|
|
850
897
|
if save_fig:
|
|
851
|
-
method = timeseries_df['method'][0]
|
|
898
|
+
method = timeseries_df['method'].iloc[0]
|
|
852
899
|
s_step = get_s_step(timeseries_df)
|
|
853
|
-
vol_per_day = timeseries_df['mean_drawoff_vol_per_day'][0]
|
|
854
|
-
cats = timeseries_df['categories'][0]
|
|
900
|
+
vol_per_day = timeseries_df['mean_drawoff_vol_per_day'].iloc[0]
|
|
901
|
+
cats = timeseries_df['categories'].iloc[0]
|
|
855
902
|
|
|
856
903
|
dir_output = Path.cwd() / "plots"
|
|
857
904
|
dir_output.mkdir(exist_ok=True)
|
|
@@ -868,14 +915,14 @@ def draw_detailed_histplot(timeseries_df):
|
|
|
868
915
|
https://towardsdatascience.com/advanced-histogram-using-python-bceae288e715
|
|
869
916
|
plot to further analyse timeseries with 1 drawoff category.
|
|
870
917
|
"""
|
|
871
|
-
cats = timeseries_df['categories'][0]
|
|
872
|
-
method = timeseries_df['method'][0]
|
|
918
|
+
cats = timeseries_df['categories'].iloc[0]
|
|
919
|
+
method = timeseries_df['method'].iloc[0]
|
|
873
920
|
|
|
874
921
|
if cats == 1 and method == 'DHWcalc':
|
|
875
922
|
|
|
876
923
|
# create bin values
|
|
877
|
-
mean = timeseries_df['mean_drawoff_flow_rate_LperH'][0]
|
|
878
|
-
sdtdev = timeseries_df['sdtdev_drawoff_flow_rate_LperH'][0]
|
|
924
|
+
mean = timeseries_df['mean_drawoff_flow_rate_LperH'].iloc[0]
|
|
925
|
+
sdtdev = timeseries_df['sdtdev_drawoff_flow_rate_LperH'].iloc[0]
|
|
879
926
|
non_zero_min = timeseries_df[timeseries_df['Water_LperH'] > 0][
|
|
880
927
|
'Water_LperH'].min() # smallest entry that is not 0.
|
|
881
928
|
|
|
@@ -943,11 +990,11 @@ def add_additional_runs(timeseries_df, holidays, occupancy, building_type, total
|
|
|
943
990
|
added_runs = total_runs - 1
|
|
944
991
|
|
|
945
992
|
s_step = int(timeseries_df.index.freqstr[:-1])
|
|
946
|
-
mean_drawoff_vol_per_day = timeseries_df['mean_drawoff_vol_per_day'][0]
|
|
947
|
-
weekend_weekday_factor = timeseries_df['weekend_weekday_factor'][0]
|
|
948
|
-
initial_day = timeseries_df['initial_day'][0]
|
|
949
|
-
method = timeseries_df['method'][0]
|
|
950
|
-
categories = timeseries_df['categories'][0]
|
|
993
|
+
mean_drawoff_vol_per_day = timeseries_df['mean_drawoff_vol_per_day'].iloc[0]
|
|
994
|
+
weekend_weekday_factor = timeseries_df['weekend_weekday_factor'].iloc[0]
|
|
995
|
+
initial_day = timeseries_df['initial_day'].iloc[0]
|
|
996
|
+
method = timeseries_df['method'].iloc[0]
|
|
997
|
+
categories = timeseries_df['categories'].iloc[0]
|
|
951
998
|
|
|
952
999
|
if method == 'OpenDHW':
|
|
953
1000
|
|
|
@@ -1165,8 +1212,8 @@ def compare_generators(timeseries_df_1, timeseries_df_2,
|
|
|
1165
1212
|
:param save_fig: bool: save the plot
|
|
1166
1213
|
"""
|
|
1167
1214
|
|
|
1168
|
-
cats_1 = timeseries_df_1['categories'][0]
|
|
1169
|
-
cats_2 = timeseries_df_2['categories'][0]
|
|
1215
|
+
cats_1 = timeseries_df_1['categories'].iloc[0]
|
|
1216
|
+
cats_2 = timeseries_df_2['categories'].iloc[0]
|
|
1170
1217
|
if cats_1 or cats_2 == 1:
|
|
1171
1218
|
print("detailed distribution is designed to compare timeseries with "
|
|
1172
1219
|
"one drawoff category")
|
|
@@ -1307,8 +1354,8 @@ def compare_generators(timeseries_df_1, timeseries_df_2,
|
|
|
1307
1354
|
drawoffs_lst = [drawoffs_1, drawoffs_2]
|
|
1308
1355
|
|
|
1309
1356
|
# create bin values
|
|
1310
|
-
mean1 = timeseries_df_1['mean_drawoff_flow_rate_LperH'][0]
|
|
1311
|
-
sdtdev1 = timeseries_df_1['sdtdev_drawoff_flow_rate_LperH'][0]
|
|
1357
|
+
mean1 = timeseries_df_1['mean_drawoff_flow_rate_LperH'].iloc[0]
|
|
1358
|
+
sdtdev1 = timeseries_df_1['sdtdev_drawoff_flow_rate_LperH'].iloc[0]
|
|
1312
1359
|
non_zero_min1 = timeseries_df_1[timeseries_df_1['Water_LperH'] > 0][
|
|
1313
1360
|
'Water_LperH'].min() # smallest entry that is not 0.
|
|
1314
1361
|
|
|
@@ -1322,8 +1369,8 @@ def compare_generators(timeseries_df_1, timeseries_df_2,
|
|
|
1322
1369
|
bin_values1 = list(set(bin_values1)) # remove double entries
|
|
1323
1370
|
bin_values1.sort() # bins have to be sorted
|
|
1324
1371
|
|
|
1325
|
-
mean2 = timeseries_df_2['mean_drawoff_flow_rate_LperH'][0]
|
|
1326
|
-
sdtdev2 = timeseries_df_2['sdtdev_drawoff_flow_rate_LperH'][0]
|
|
1372
|
+
mean2 = timeseries_df_2['mean_drawoff_flow_rate_LperH'].iloc[0]
|
|
1373
|
+
sdtdev2 = timeseries_df_2['sdtdev_drawoff_flow_rate_LperH'].iloc[0]
|
|
1327
1374
|
non_zero_min2 = timeseries_df_2[timeseries_df_2['Water_LperH'] > 0][
|
|
1328
1375
|
'Water_LperH'].min() # smallest entry that is not 0.
|
|
1329
1376
|
|
|
@@ -1510,8 +1557,8 @@ def make_title_str(timeseries_df):
|
|
|
1510
1557
|
yearly_water_demand = timeseries_df['Water_L'].sum() # in L
|
|
1511
1558
|
drawoffs = timeseries_df[timeseries_df['Water_LperH'] != 0]['Water_LperH']
|
|
1512
1559
|
max_water_flow = timeseries_df['Water_LperH'].max()
|
|
1513
|
-
method = timeseries_df['method'][0]
|
|
1514
|
-
cats = timeseries_df['categories'][0]
|
|
1560
|
+
method = timeseries_df['method'].iloc[0]
|
|
1561
|
+
cats = timeseries_df['categories'].iloc[0]
|
|
1515
1562
|
|
|
1516
1563
|
if cats == 1:
|
|
1517
1564
|
method = "{} ({} cat)".format(method, cats)
|
|
@@ -1642,7 +1689,7 @@ def reduce_no_drawoffs(timeseries_df):
|
|
|
1642
1689
|
"""
|
|
1643
1690
|
|
|
1644
1691
|
# get the expected yearly water demand
|
|
1645
|
-
expected_yearly_water = timeseries_df['mean_drawoff_vol_per_day'][0] * 365
|
|
1692
|
+
expected_yearly_water = timeseries_df['mean_drawoff_vol_per_day'].iloc[0] * 365
|
|
1646
1693
|
actual_yearly_water = timeseries_df['Water_L'].sum()
|
|
1647
1694
|
|
|
1648
1695
|
if expected_yearly_water < actual_yearly_water:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: OpenDHW
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.9
|
|
4
4
|
Summary: Tool for generating domestic hot water profiles
|
|
5
5
|
Home-page: https://github.com/RWTH-EBC/OpenDHW
|
|
6
6
|
Author: RWTH Aachen University, E.ON Energy Research Center, Institute of Energy Efficient Buildings and Indoor Climate
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: OpenDHW
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.9
|
|
4
4
|
Summary: Tool for generating domestic hot water profiles
|
|
5
5
|
Home-page: https://github.com/RWTH-EBC/OpenDHW
|
|
6
6
|
Author: RWTH Aachen University, E.ON Energy Research Center, Institute of Energy Efficient Buildings and Indoor Climate
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|