Compare commits

...

6 Commits

Author SHA1 Message Date
Felix Blanke
f1471e21a5 Set German Locale explicitely 2023-08-27 18:59:37 +02:00
Felix Blanke
e571c6178e Center xtick labels 2023-08-27 18:58:35 +02:00
Felix Blanke
19dd8c5f92 Add line plot 2023-08-27 18:57:29 +02:00
Felix Blanke
95ba5a57a7 Add img to base html 2023-08-27 16:22:22 +02:00
Felix Blanke
f7f2861682 Add bar plot to page 2023-08-27 16:22:06 +02:00
Felix Blanke
f24b1f9297 Remove image tag 2023-08-27 16:21:51 +02:00

129
wsgi.py
View File

@ -1,8 +1,17 @@
import base64
import datetime
import io
from itertools import chain
from pathlib import Path
import matplotlib.dates as mdates
import matplotlib.pyplot as plt
import matplotlib.ticker as mtick
import numpy as np
import pandas as pd
from flask import Flask, render_template, request
from flask_caching import Cache
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
from download_digital import construct_dataframe, get_bez_data
@ -12,7 +21,9 @@ config = {
"CACHE_THRESHOLD": 1000,
"CACHE_DIR": "cache",
}
import locale
locale.setlocale(locale.LC_ALL, "de_DE.UTF-8")
app = Flask(__name__)
app.config.from_mapping(config)
cache = Cache(app)
@ -34,6 +45,121 @@ def get_tables(url: str) -> tuple[pd.DataFrame, pd.DataFrame]:
return df, df_state
def plot(
current_df: pd.DataFrame | None = None,
data_folder: str = "data",
sheet_name: str = "digital",
total_target: int = 1500,
plot_all: bool = False,
alpha: float | None = None,
) -> str:
data_dict = {}
for f in sorted(Path(data_folder).iterdir()):
with f.open("rb") as ff:
df = pd.read_excel(ff, sheet_name=sheet_name)
df = df.astype({"Digitale Befragung": "Int32"})
sum_val = df[["Digitale Befragung"]].sum().iloc[0]
key = f.name[:10]
data_dict[key] = sum_val
data_dict["2023-08-15"] = 275
series = pd.Series(data_dict.values(), index=data_dict)
series.index = series.index.astype("datetime64[ns]") + pd.DateOffset(hours=10)
df = series.to_frame("Digitale Befragung")
df = df.reindex(
pd.date_range(start="2023-08-15", end=max(data_dict.keys()))
+ pd.DateOffset(hours=10)
)
if current_df is not None:
current_df = current_df.astype({"Digitale Befragung": "Int32"})
sum_val = current_df[["Digitale Befragung"]].sum().iloc[0]
df.loc[datetime.datetime.now()] = sum_val
plt.figure(dpi=300)
# fill weekends
max_date = max(data_dict.keys())
max_date = datetime.datetime.strptime(max_date, "%Y-%m-%d") + datetime.timedelta(
days=1
)
days = pd.date_range(start="2023-08-14", end=max_date)
for idx, day in enumerate(days[:-1]):
if day.weekday() >= 5:
plt.gca().axvspan(days[idx], days[idx + 1], alpha=0.2, color="gray")
if alpha is not None:
plt.fill_between(
df.dropna().index,
df.dropna()["Digitale Befragung"],
color="#e4004e",
alpha=alpha,
)
plt.plot(
df.dropna().index,
df.dropna()["Digitale Befragung"],
ls="--",
marker="o",
lw=1,
color="#e4004e",
markersize=4,
)
if current_df is not None:
plt.annotate(
"Jetzt",
(df.dropna().index[-1], df.dropna()["Digitale Befragung"][-1] * 1.03),
fontsize=8,
ha="center",
)
plt.plot(df.index, df["Digitale Befragung"], lw=1.5, color="#e4004e")
plt.title("Teilnahme an Digitaler Beschäftigtenbefragung")
plt.ylabel("# Teilnahmen")
plt.ylim(0, total_target + 100)
# plt.gcf().autofmt_xdate()
# use timezone offset to center tick labels
plt.gca().xaxis.set_major_locator(
mdates.WeekdayLocator([mdates.TU], tz="Etc/GMT+12")
)
plt.gca().xaxis.set_minor_locator(mdates.DayLocator())
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter("%a %d.%m."))
plt.grid(True, which="major", axis="y")
plt.grid(True, which="minor", axis="x")
plt.gca().tick_params("x", length=0, which="major")
def val_to_perc(val):
return 100 * val / total_target
def perc_to_val(perc):
return perc * total_target / 100
sec_ax = plt.gca().secondary_yaxis("right", functions=(val_to_perc, perc_to_val))
sec_ax.set_ylabel("# Teilnahmen [% Erfolg]")
sec_ax.yaxis.set_major_formatter(mtick.PercentFormatter())
plt.axhline(y=total_target, color="#48a9be", linestyle="--")
plt.tight_layout()
# Convert plot to PNG image
pngImage = io.BytesIO()
FigureCanvas(plt.gcf()).print_png(pngImage)
# Encode PNG image to base64 string
pngImageB64String = "data:image/png;base64,"
pngImageB64String += base64.b64encode(pngImage.getvalue()).decode("utf8")
return pngImageB64String
@app.route("/")
@cache.cached(timeout=50)
def tables(
@ -81,10 +207,13 @@ def tables(
_print_as_html(df_state)
_print_as_html(df)
image = plot(df_state, plot_all=True)
return render_template(
"base.html",
tables="\n".join(output_str),
timestamp=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
image=image,
)