visualize: fix timestamps on diagrams (#430) Closes #387

* visualize: fix timestamps on diagrams
* set start time in all graphs to the same beginning hour

---------

Co-authored-by: Normann <github@koldrack.com>
This commit is contained in:
celle1234 2025-02-08 00:47:21 +01:00 committed by GitHub
parent 80a4079bbf
commit 6cc9a5fd44
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -13,6 +13,7 @@ import pendulum
from matplotlib.backends.backend_pdf import PdfPages from matplotlib.backends.backend_pdf import PdfPages
from akkudoktoreos.core.coreabc import ConfigMixin from akkudoktoreos.core.coreabc import ConfigMixin
from akkudoktoreos.core.ems import EnergieManagementSystem
from akkudoktoreos.core.logging import get_logger from akkudoktoreos.core.logging import get_logger
from akkudoktoreos.optimization.genetic import OptimizationParameters from akkudoktoreos.optimization.genetic import OptimizationParameters
from akkudoktoreos.utils.datetimeutil import to_datetime from akkudoktoreos.utils.datetimeutil import to_datetime
@ -147,14 +148,16 @@ class VisualizationReport(ConfigMixin):
# Format the time axis # Format the time axis
plt.gca().xaxis.set_major_formatter( plt.gca().xaxis.set_major_formatter(
mdates.DateFormatter("%Y-%m-%d") mdates.DateFormatter("%Y-%m-%d", tz=self.config.timezone)
) # Show date and time ) # Show date and time
plt.gca().xaxis.set_major_locator( plt.gca().xaxis.set_major_locator(
mdates.DayLocator(interval=1, tz=None) mdates.DayLocator(interval=1, tz=self.config.timezone)
) # Major ticks every day ) # Major ticks every day
plt.gca().xaxis.set_minor_locator(mdates.HourLocator(interval=3, tz=None)) plt.gca().xaxis.set_minor_locator(
mdates.HourLocator(interval=2, tz=self.config.timezone)
)
# Minor ticks every 6 hours # Minor ticks every 6 hours
plt.gca().xaxis.set_minor_formatter(mdates.DateFormatter("%H")) plt.gca().xaxis.set_minor_formatter(mdates.DateFormatter("%H", tz=self.config.timezone))
# plt.gcf().autofmt_xdate(rotation=45, which="major") # plt.gcf().autofmt_xdate(rotation=45, which="major")
# Auto-format the x-axis for readability # Auto-format the x-axis for readability
@ -174,6 +177,7 @@ class VisualizationReport(ConfigMixin):
# Add vertical line for the current date if within the axis range # Add vertical line for the current date if within the axis range
current_time = pendulum.now(self.config.timezone) current_time = pendulum.now(self.config.timezone)
# current_time = pendulum.now().add(hours=1)
if timestamps[0].subtract(hours=2) <= current_time <= timestamps[-1]: if timestamps[0].subtract(hours=2) <= current_time <= timestamps[-1]:
plt.axvline(current_time, color="r", linestyle="--", label="Now") plt.axvline(current_time, color="r", linestyle="--", label="Now")
plt.text(current_time, plt.ylim()[1], "Now", color="r", ha="center", va="bottom") plt.text(current_time, plt.ylim()[1], "Now", color="r", ha="center", va="bottom")
@ -187,8 +191,10 @@ class VisualizationReport(ConfigMixin):
hours_since_start = [(t - timestamps[0]).total_seconds() / 3600 for t in timestamps] hours_since_start = [(t - timestamps[0]).total_seconds() / 3600 for t in timestamps]
# ax2.set_xticks(timestamps[::48]) # Set ticks every 12 hours # ax2.set_xticks(timestamps[::48]) # Set ticks every 12 hours
# ax2.set_xticklabels([f"{int(h)}" for h in hours_since_start[::48]]) # ax2.set_xticklabels([f"{int(h)}" for h in hours_since_start[::48]])
ax2.set_xticks(timestamps[:: len(timestamps) // 24]) # Select 10 evenly spaced ticks # ax2.set_xticks(timestamps[:: len(timestamps) // 24]) # Select 10 evenly spaced ticks
ax2.set_xticklabels([f"{int(h)}" for h in hours_since_start[:: len(timestamps) // 24]]) ax2.set_xticks(timestamps[:: len(timestamps) // 12]) # Select 10 evenly spaced ticks
# ax2.set_xticklabels([f"{int(h)}" for h in hours_since_start[:: len(timestamps) // 24]])
ax2.set_xticklabels([f"{int(h)}" for h in hours_since_start[:: len(timestamps) // 12]])
if x2label: if x2label:
ax2.set_xlabel(x2label) ax2.set_xlabel(x2label)
@ -416,15 +422,17 @@ def prepare_visualize(
parameters: OptimizationParameters, parameters: OptimizationParameters,
results: dict, results: dict,
filename: str = "visualization_results.pdf", filename: str = "visualization_results.pdf",
start_hour: Optional[int] = 0, start_hour: int = 0,
) -> None: ) -> None:
report = VisualizationReport(filename) report = VisualizationReport(filename)
next_full_hour_date = pendulum.now(report.config.timezone).start_of("hour").add(hours=1) # next_full_hour_date = pendulum.now(report.config.timezone).start_of("day").add(hours=start_hour)
# next_full_hour_date = to_datetime().set(minute=0, second=0, microsecond=0)
next_full_hour_date = EnergieManagementSystem.set_start_datetime()
# Group 1: # Group 1:
report.create_line_chart_date( report.create_line_chart_date(
next_full_hour_date, # start_date next_full_hour_date,
[ [
parameters.ems.gesamtlast, parameters.ems.gesamtlast[start_hour:],
], ],
title="Load Profile", title="Load Profile",
# xlabel="Hours", # not enough space # xlabel="Hours", # not enough space
@ -432,9 +440,9 @@ def prepare_visualize(
labels=["Total Load (Wh)"], labels=["Total Load (Wh)"],
) )
report.create_line_chart_date( report.create_line_chart_date(
next_full_hour_date, # start_date next_full_hour_date,
[ [
parameters.ems.pv_prognose_wh, parameters.ems.pv_prognose_wh[start_hour:],
], ],
title="PV Forecast", title="PV Forecast",
# xlabel="Hours", # not enough space # xlabel="Hours", # not enough space
@ -442,8 +450,13 @@ def prepare_visualize(
) )
report.create_line_chart_date( report.create_line_chart_date(
next_full_hour_date, # start_date next_full_hour_date,
[np.full(len(parameters.ems.gesamtlast), parameters.ems.einspeiseverguetung_euro_pro_wh)], [
np.full(
len(parameters.ems.gesamtlast) - start_hour,
parameters.ems.einspeiseverguetung_euro_pro_wh,
)
],
title="Remuneration", title="Remuneration",
# xlabel="Hours", # not enough space # xlabel="Hours", # not enough space
ylabel="€/Wh", ylabel="€/Wh",
@ -451,9 +464,9 @@ def prepare_visualize(
) )
if parameters.temperature_forecast: if parameters.temperature_forecast:
report.create_line_chart_date( report.create_line_chart_date(
next_full_hour_date, # start_date next_full_hour_date,
[ [
parameters.temperature_forecast, parameters.temperature_forecast[start_hour:],
], ],
title="Temperature Forecast", title="Temperature Forecast",
# xlabel="Hours", # not enough space # xlabel="Hours", # not enough space
@ -502,21 +515,35 @@ def prepare_visualize(
) )
report.create_line_chart_date( report.create_line_chart_date(
next_full_hour_date, # start_date next_full_hour_date, # start_date
[parameters.ems.strompreis_euro_pro_wh], [parameters.ems.strompreis_euro_pro_wh[start_hour:]],
# title="Electricity Price", # not enough space # title="Electricity Price", # not enough space
# xlabel="Date", # not enough space # xlabel="Date", # not enough space
ylabel="Electricity Price (€/Wh)", ylabel="Electricity Price (€/Wh)",
x2label=None, # not enough space x2label=None, # not enough space
) )
labels = list(
item
for sublist in zip(
list(str(i) for i in range(0, 23, 2)), list(str(" ") for i in range(0, 23, 2))
)
for item in sublist
)
labels = labels[start_hour:] + labels
report.create_bar_chart( report.create_bar_chart(
list(str(i) for i in range(len(results["ac_charge"]))), labels,
[results["ac_charge"], results["dc_charge"], results["discharge_allowed"]], [
results["ac_charge"][start_hour:],
results["dc_charge"][start_hour:],
results["discharge_allowed"][start_hour:],
],
title="AC/DC Charging and Discharge Overview", title="AC/DC Charging and Discharge Overview",
ylabel="Relative Power (0-1) / Discharge (0 or 1)", ylabel="Relative Power (0-1) / Discharge (0 or 1)",
label_names=["AC Charging (relative)", "DC Charging (relative)", "Discharge Allowed"], label_names=["AC Charging (relative)", "DC Charging (relative)", "Discharge Allowed"],
colors=["blue", "green", "red"], colors=["blue", "green", "red"],
bottom=3, bottom=3,
xlabels=labels,
) )
report.finalize_group() report.finalize_group()