|
1
|
|
|
import os |
|
2
|
|
|
import matplotlib.colors as mcolors |
|
3
|
|
|
import matplotlib.pyplot as plt |
|
4
|
|
|
import numpy as np |
|
5
|
|
|
import pandas as pd |
|
6
|
|
|
|
|
7
|
|
|
# creates the icons in the grid view of the documentation |
|
8
|
|
|
|
|
9
|
|
|
|
|
10
|
|
|
def hex_from_rgb(rgb): |
|
11
|
|
|
"""makes rgb to hex""" |
|
12
|
|
|
return "#{:02X}{:02X}{:02X}".format( |
|
13
|
|
|
int(rgb[0] * 255), int(rgb[1] * 255), int(rgb[2] * 255) |
|
14
|
|
|
) |
|
15
|
|
|
|
|
16
|
|
|
|
|
17
|
|
|
# colors of the color palette |
|
18
|
|
|
dark_palette = { |
|
19
|
|
|
"color1": "#1F567D", |
|
20
|
|
|
"color2": "#8AA8A1", |
|
21
|
|
|
"color3": "#FA8334", |
|
22
|
|
|
"color4": "#FF006E", |
|
23
|
|
|
"color5": "#FFFD77", |
|
24
|
|
|
} |
|
25
|
|
|
|
|
26
|
|
|
# crates light mode color palet |
|
27
|
|
|
light_palette = {"color1": dark_palette["color1"]} |
|
28
|
|
|
for key in ["color2", "color3", "color4", "color5"]: |
|
29
|
|
|
rgb = mcolors.to_rgb(dark_palette[key]) |
|
30
|
|
|
new_rgb = [0.7 * c + 0.3 for c in rgb] |
|
31
|
|
|
light_palette[key] = hex_from_rgb(new_rgb) |
|
32
|
|
|
|
|
33
|
|
|
|
|
34
|
|
|
def draw_lin_vs_mixed_int(mode="dark"): |
|
35
|
|
|
""" |
|
36
|
|
|
draws plot for the linear optimization vs. Mix Integer section |
|
37
|
|
|
""" |
|
38
|
|
|
if mode == "dark": |
|
39
|
|
|
palette = dark_palette |
|
40
|
|
|
bg_color = "#121212" |
|
41
|
|
|
text_color = "#FFFFFF" |
|
42
|
|
|
else: |
|
43
|
|
|
palette = light_palette |
|
44
|
|
|
bg_color = "#FFFFFF" |
|
45
|
|
|
text_color = "#000000" |
|
46
|
|
|
|
|
47
|
|
|
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5)) |
|
48
|
|
|
fig.patch.set_facecolor(bg_color) |
|
49
|
|
|
|
|
50
|
|
|
for ax in [ax1, ax2]: |
|
51
|
|
|
ax.set_facecolor(bg_color) |
|
52
|
|
|
ax.tick_params(colors=text_color) |
|
53
|
|
|
for spine in ax.spines.values(): |
|
54
|
|
|
spine.set_color(text_color) |
|
55
|
|
|
|
|
56
|
|
|
# linear function |
|
57
|
|
|
x = np.linspace(-10, 10, 400) |
|
58
|
|
|
y = 2 * x + 1 |
|
59
|
|
|
ax1.plot(x, y, color=palette["color1"], linewidth=2) |
|
60
|
|
|
ax1.set_title("Linear Programming", color=text_color, fontsize=14) |
|
61
|
|
|
ax1.set_xticks([]) |
|
62
|
|
|
ax1.set_yticks([]) |
|
63
|
|
|
|
|
64
|
|
|
# function including a jump |
|
65
|
|
|
x_left = np.linspace(-10, -0.01, 200) |
|
66
|
|
|
x_right = np.linspace(0, 10, 200) |
|
67
|
|
|
y_left = 2 * x_left + 1 |
|
68
|
|
|
y_right = 2 * x_right + 1 + 5 |
|
69
|
|
|
|
|
70
|
|
|
ax2.plot(x_left, y_left, color=palette["color1"], linewidth=2) |
|
71
|
|
|
ax2.plot(x_right, y_right, color=palette["color3"], linewidth=2) |
|
72
|
|
|
|
|
73
|
|
|
# setting maker for the jump |
|
74
|
|
|
ax2.plot( |
|
75
|
|
|
x_left[-1], |
|
76
|
|
|
y_left[-1], |
|
77
|
|
|
marker="o", |
|
78
|
|
|
markersize=8, |
|
79
|
|
|
markerfacecolor=bg_color, |
|
80
|
|
|
markeredgecolor=palette["color4"], |
|
81
|
|
|
markeredgewidth=2, |
|
82
|
|
|
) |
|
83
|
|
|
ax2.plot( |
|
84
|
|
|
x_right[0], |
|
85
|
|
|
y_right[0], |
|
86
|
|
|
marker="o", |
|
87
|
|
|
markersize=8, |
|
88
|
|
|
markerfacecolor=palette["color4"], |
|
89
|
|
|
markeredgecolor=palette["color4"], |
|
90
|
|
|
) |
|
91
|
|
|
|
|
92
|
|
|
ax2.set_title("Mixed-Integer Problem", color=text_color, fontsize=14) |
|
93
|
|
|
ax2.set_xticks([]) |
|
94
|
|
|
ax2.set_yticks([]) |
|
95
|
|
|
|
|
96
|
|
|
plt.tight_layout() |
|
97
|
|
|
|
|
98
|
|
|
# save the plot |
|
99
|
|
|
if mode == "dark": |
|
100
|
|
|
|
|
101
|
|
|
plt.savefig("lin_vs_mixed_int_plot_dark.png") |
|
102
|
|
|
if mode == "light": |
|
103
|
|
|
|
|
104
|
|
|
plt.savefig("lin_vs_mixed_int_plot_light.png") |
|
105
|
|
|
|
|
106
|
|
|
|
|
107
|
|
|
def draw_timeline(mode="dark", savefig_filename=None): |
|
108
|
|
|
""" |
|
109
|
|
|
draws timeline for the multiperiod icon |
|
110
|
|
|
""" |
|
111
|
|
|
if mode == "dark": |
|
112
|
|
|
palette = dark_palette |
|
113
|
|
|
bg_color = "#121212" |
|
114
|
|
|
text_color = "#FFFFFF" |
|
115
|
|
|
else: |
|
116
|
|
|
palette = light_palette |
|
117
|
|
|
bg_color = "#FFFFFF" |
|
118
|
|
|
text_color = "#000000" |
|
119
|
|
|
|
|
120
|
|
|
fig, ax = plt.subplots(figsize=(10, 3)) |
|
121
|
|
|
fig.patch.set_facecolor(bg_color) |
|
122
|
|
|
ax.set_facecolor(bg_color) |
|
123
|
|
|
|
|
124
|
|
|
for spine in ax.spines.values(): |
|
125
|
|
|
spine.set_visible(False) |
|
126
|
|
|
ax.tick_params( |
|
127
|
|
|
left=False, bottom=False, labelbottom=False, labelleft=False |
|
128
|
|
|
) |
|
129
|
|
|
|
|
130
|
|
|
years = list(range(2020, 2031)) |
|
131
|
|
|
|
|
132
|
|
|
# draw line |
|
133
|
|
|
ax.plot( |
|
134
|
|
|
[years[0], years[-1]], [0, 0], color=palette["color1"], linewidth=2 |
|
135
|
|
|
) |
|
136
|
|
|
|
|
137
|
|
|
# set markings for every year |
|
138
|
|
|
for i, year in enumerate(years): |
|
139
|
|
|
ax.plot(year, 0, marker="o", markersize=8, color=palette["color3"]) |
|
140
|
|
|
ax.text( |
|
141
|
|
|
year, |
|
142
|
|
|
-0.3, |
|
143
|
|
|
str(year), |
|
144
|
|
|
ha="center", |
|
145
|
|
|
va="top", |
|
146
|
|
|
color=text_color, |
|
147
|
|
|
fontsize=10, |
|
148
|
|
|
) |
|
149
|
|
|
ax.text( |
|
150
|
|
|
year, |
|
151
|
|
|
0.3, |
|
152
|
|
|
f"Period {i+1}", |
|
153
|
|
|
ha="center", |
|
154
|
|
|
va="bottom", |
|
155
|
|
|
color=text_color, |
|
156
|
|
|
fontsize=10, |
|
157
|
|
|
) |
|
158
|
|
|
|
|
159
|
|
|
# Set title |
|
160
|
|
|
ax.text( |
|
161
|
|
|
(years[0] + years[-1]) / 2, |
|
162
|
|
|
0.8, |
|
163
|
|
|
"Multi-period Optimization", |
|
164
|
|
|
ha="center", |
|
165
|
|
|
va="bottom", |
|
166
|
|
|
color=text_color, |
|
167
|
|
|
fontsize=14, |
|
168
|
|
|
fontweight="bold", |
|
169
|
|
|
) |
|
170
|
|
|
|
|
171
|
|
|
ax.set_xlim(years[0] - 1, years[-1] + 1) |
|
172
|
|
|
ax.set_ylim(-1, 1) |
|
173
|
|
|
|
|
174
|
|
|
plt.tight_layout() |
|
175
|
|
|
|
|
176
|
|
|
# save png |
|
177
|
|
|
if mode == "dark": |
|
178
|
|
|
|
|
179
|
|
|
plt.savefig("timeline_dark.png") |
|
180
|
|
|
if mode == "light": |
|
181
|
|
|
|
|
182
|
|
|
plt.savefig("timeline_light.png") |
|
183
|
|
|
|
|
184
|
|
|
|
|
185
|
|
|
def plot_dispatch_invest(csv_path, mode="dark"): |
|
186
|
|
|
""" |
|
187
|
|
|
draws a demand timeseries next to an bar plot symbolizing the investment decisions |
|
188
|
|
|
""" |
|
189
|
|
|
|
|
190
|
|
|
df = pd.read_csv(csv_path) |
|
191
|
|
|
|
|
192
|
|
|
if "Time" not in df.columns: |
|
193
|
|
|
df["Time"] = pd.date_range( |
|
194
|
|
|
start="2020-01-01", periods=len(df), freq="H" |
|
195
|
|
|
) |
|
196
|
|
|
|
|
197
|
|
|
if mode.lower() == "dark": |
|
198
|
|
|
palette = dark_palette |
|
199
|
|
|
bg_color = "#121212" |
|
200
|
|
|
text_color = "#FFFFFF" |
|
201
|
|
|
else: |
|
202
|
|
|
palette = light_palette |
|
203
|
|
|
bg_color = "#FFFFFF" |
|
204
|
|
|
text_color = "#000000" |
|
205
|
|
|
|
|
206
|
|
|
# create two subplots |
|
207
|
|
|
fig, axs = plt.subplots(1, 2, figsize=(16, 6)) |
|
208
|
|
|
fig.patch.set_facecolor(bg_color) |
|
209
|
|
|
|
|
210
|
|
|
ax1 = axs[0] |
|
211
|
|
|
ax1.set_facecolor(bg_color) |
|
212
|
|
|
for spine in ax1.spines.values(): |
|
213
|
|
|
spine.set_color(text_color) |
|
214
|
|
|
ax1.tick_params(colors=text_color, labelleft=False) |
|
215
|
|
|
|
|
216
|
|
|
# draw dispatch timeseries |
|
217
|
|
|
ax1.plot( |
|
218
|
|
|
df["Time"], |
|
219
|
|
|
df["demand_th"], |
|
220
|
|
|
marker="o", |
|
221
|
|
|
linestyle="-", |
|
222
|
|
|
color=palette["color1"], |
|
223
|
|
|
linewidth=2, |
|
224
|
|
|
) |
|
225
|
|
|
ax1.set_title("Dispatch Time Series (kW)", color=text_color, fontsize=14) |
|
226
|
|
|
ax1.set_xlabel("Time", color=text_color) |
|
227
|
|
|
ax1.set_ylabel("kW", color=text_color) |
|
228
|
|
|
|
|
229
|
|
|
avg_pv = df["pv"].mean() if "pv" in df.columns else 0 |
|
230
|
|
|
avg_wind = df["wind"].mean() if "wind" in df.columns else 0 |
|
231
|
|
|
avg_heatpump = 0.3 |
|
232
|
|
|
avg_solarthermie = 0.09 |
|
233
|
|
|
|
|
234
|
|
|
labels = ["PV", "Wind", "Heat Pump", "Solarthermie"] |
|
235
|
|
|
values = [avg_pv, avg_wind, avg_heatpump, avg_solarthermie] |
|
236
|
|
|
|
|
237
|
|
|
bar_colors = [ |
|
238
|
|
|
palette["color3"], |
|
239
|
|
|
palette["color4"], |
|
240
|
|
|
palette["color2"], |
|
241
|
|
|
palette["color5"], |
|
242
|
|
|
] |
|
243
|
|
|
|
|
244
|
|
|
ax2 = axs[1] |
|
245
|
|
|
ax2.set_facecolor(bg_color) |
|
246
|
|
|
for spine in ax2.spines.values(): |
|
247
|
|
|
spine.set_color(text_color) |
|
248
|
|
|
ax2.tick_params(colors=text_color, labelleft=False) |
|
249
|
|
|
|
|
250
|
|
|
bars = ax2.bar( |
|
251
|
|
|
labels, values, color=bar_colors, edgecolor=text_color, linewidth=1.5 |
|
252
|
|
|
) |
|
253
|
|
|
|
|
254
|
|
|
ax2.set_title("Investment Technology Sizes", color=text_color, fontsize=14) |
|
255
|
|
|
ax2.set_ylabel("Average Value", color=text_color, fontsize=14) |
|
256
|
|
|
|
|
257
|
|
|
fig.suptitle( |
|
258
|
|
|
"Dispatch vs. Invest-Optimization", color=text_color, fontsize=16 |
|
259
|
|
|
) |
|
260
|
|
|
|
|
261
|
|
|
plt.tight_layout(rect=[0, 0, 1, 0.95]) |
|
262
|
|
|
|
|
263
|
|
|
# save plots |
|
264
|
|
|
if mode == "dark": |
|
265
|
|
|
|
|
266
|
|
|
plt.savefig("plot_dispatch_invest_dark.png") |
|
267
|
|
|
if mode == "light": |
|
268
|
|
|
|
|
269
|
|
|
plt.savefig("plot_dispatch_invest_light.png") |
|
270
|
|
|
|
|
271
|
|
|
|
|
272
|
|
|
# uncomment he needed funczion to redraw the icons |
|
273
|
|
|
|
|
274
|
|
|
# draw_lin_vs_mixed_int('light') |
|
275
|
|
|
# draw_lin_vs_mixed_int('dark') |
|
276
|
|
|
|
|
277
|
|
|
# draw_timeline("dark") # Speichert als "timeline_dark.png" |
|
278
|
|
|
# draw_timeline("light") # Speichert als "timeline_light.png" |
|
279
|
|
|
|
|
280
|
|
|
file_name = os.path.realpath( |
|
281
|
|
|
os.path.join( |
|
282
|
|
|
__file__, |
|
283
|
|
|
"..", |
|
284
|
|
|
"..", |
|
285
|
|
|
"..", |
|
286
|
|
|
"..", |
|
287
|
|
|
"tests/test_outputlib/input_data.csv", |
|
288
|
|
|
) |
|
289
|
|
|
) |
|
290
|
|
|
plot_dispatch_invest(file_name, mode="light") |
|
291
|
|
|
plot_dispatch_invest(file_name, mode="dark") |
|
292
|
|
|
|