Py.Cafe

maartenbreddels/

solara-meterstand-analysis

Meterstand Time Series Analysis

DocsPricing
  • app.py
  • etmgeg_277.txt
  • meter_readings.csv
  • requirements.txt
app.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# check out https://solara.dev/ for documentation
# or https://github.com/widgetti/solara/
# And check out https://py.cafe/maartenbreddels for more examples
import solara
import pandas as pd
import matplotlib.pyplot as plt

# Replace 'meterstand.csv' with the actual path or filename of your CSV
csv_file = 'meter_readings.csv'

# Read the CSV
# - sep=';' handles the semicolon as a delimiter.
# - decimal=',' converts commas to periods so they can be interpreted as floats.
df = pd.read_csv(csv_file, sep=';', decimal=',')

# Convert the 'Datum/tijd' column to datetime
df["Date"] = df['Datum/tijd'] = pd.to_datetime(df['Datum/tijd'])
df['Usage'] = df['Meterstand'].diff()

# data downloaded from https://www.knmi.nl/nederland-nu/klimatologie/daggegevens
# (this file is for Lauwersoog)
# Read the KNMI daily data
file_path = "etmgeg_277.txt"  # Replace this with your file path
data_all = pd.read_csv(file_path, skiprows=51, delimiter=",")  # Read the file, skipping the header rows
data_all.columns = data_all.columns.str.strip()

# Convert temperature to degrees Celsius
data_all["TG"] = (data_all["TG"] / 10).rolling(4).mean()
data_all["TN"] = data_all["TN"] / 10
data_all["Date"] = pd.to_datetime(data_all["YYYYMMDD"], format="%Y%m%d")

df = pd.merge(df, data_all, on="Date", how="left")


# df["TG"] = df["TG"].rolling(7).mean()
# df["Usage"] = df["Usage"].rolling(7).mean()
# df["SQ"] = df["SQ"].rolling(7).mean()

# reactive variables will trigger a component rerender
# when changed.
# When you change the default (now 0), hit the embedded browser
# refresh button to reset the state
clicks = solara.reactive(0)


@solara.component
def Page():

    # Create the plot
    # plt.figure(figsize=(10,6))
    fig, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=(14, 12))
    # ax1.plot(df['Datum/tijd'], df['Meterstand'], marker='o')
    # ax1.set_title('Meterstand Over Time')
    # ax1.set_xlabel('Datum/tijd')
    # ax1.set_ylabel('Meterstand')
    ax1.plot(df['Datum/tijd'], df['TG'], marker='o')
    ax1.plot(df['Datum/tijd'], df['SQ']*0.1, marker='o')
    # ax1.plot(df['Datum/tijd'], df['FG']*0.1, marker='o')
    ax1.set_title('Meterstand Over Time')
    ax1.set_xlabel('Datum/tijd')
    ax1.set_ylabel('TG')

    ax1.grid(True)

    # Format the x-axis labels to make them more readable
    # ax1.set_xticks(rotation=45)

    # Adjust layout so labels don’t get cut off
    # ax1.tight_layout()

    # Show the plot
    # fig.show()

    ax2.plot(df['Datum/tijd'], df['Usage'], marker='o', label="gas usage")
    ax2.set_title('Meterstand Over Time')
    ax2.set_xlabel('Datum/tijd')
    ax2.set_ylabel('Gasgebruik')
    ax2.set_ylim(0, 30)
    ax2.plot(df['Datum/tijd'], (20-df['TG']), marker='o', label="predicted")
    ax2.legend()
    ax2.grid(True)

    warm_water_usage = 2
    degdays = df["Degdays"] = (20-df["TG"])
    f = -0.04
    gudd = df["GUDD"]  = (df['Usage']-warm_water_usage - df["SQ"] * f)/df["Degdays"]

    ax3.scatter(df['Datum/tijd'], (gudd), marker='o')
    ax3.scatter(df['Datum/tijd'], (gudd.rolling(14).mean()), marker='x')
    ax3.set_title('Meterstand Over Time')
    ax3.set_xlabel('Datum/tijd')
    ax3.set_ylabel('Meterstand')
    ax3.set_ylim(-0.5, 1.5)
    ax3.axhline(y=1.0, color="tab:red", linestyle="--", label="Desired Indoor Temperature")
    ax3.grid(True)


    plt.tight_layout()
    plt.show()
    df_show = df[["Date", "Meterstand", "Usage", "TG", "Degdays", "GUDD"]]
    df_show = df_show.sort_values(by='Date', ascending=False)

    solara.DataFrame(df_show)



        # print("The component render function gets called")
        # # change this code, and see the output refresh
        # color = "green"
        # if clicks.value >= 5:
        #     color = "red"

        # def increment():
        #     clicks.value += 1
        #     print("clicks", clicks)  # noqa

        # solara.Button(label=f"Clicked: {clicks}", on_click=increment, color=color)