openenergyid 0.1.17__py2.py3-none-any.whl → 0.1.19__py2.py3-none-any.whl
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.
Potentially problematic release.
This version of openenergyid might be problematic. Click here for more details.
- openenergyid/__init__.py +1 -1
- openenergyid/dyntar/const.py +4 -0
- openenergyid/dyntar/main.py +93 -18
- openenergyid/dyntar/models.py +12 -5
- openenergyid/models.py +3 -15
- {openenergyid-0.1.17.dist-info → openenergyid-0.1.19.dist-info}/METADATA +1 -1
- {openenergyid-0.1.17.dist-info → openenergyid-0.1.19.dist-info}/RECORD +9 -9
- {openenergyid-0.1.17.dist-info → openenergyid-0.1.19.dist-info}/WHEEL +0 -0
- {openenergyid-0.1.17.dist-info → openenergyid-0.1.19.dist-info}/licenses/LICENSE +0 -0
openenergyid/__init__.py
CHANGED
openenergyid/dyntar/const.py
CHANGED
|
@@ -16,3 +16,7 @@ SPP_WEIGHTED_PRICE_EXPORTED = "spp_weighted_price_exported"
|
|
|
16
16
|
HEATMAP_DELIVERED = "heatmap_delivered"
|
|
17
17
|
HEATMAP_EXPORTED = "heatmap_exported"
|
|
18
18
|
HEATMAP_TOTAL = "heatmap_total"
|
|
19
|
+
|
|
20
|
+
HEATMAP_DELIVERED_DESCRIPTION = "heatmap_delivered_description"
|
|
21
|
+
HEATMAP_EXPORTED_DESCRIPTION = "heatmap_exported_description"
|
|
22
|
+
HEATMAP_TOTAL_DESCRIPTION = "heatmap_total_description"
|
openenergyid/dyntar/main.py
CHANGED
|
@@ -26,18 +26,18 @@ from .const import (
|
|
|
26
26
|
HEATMAP_DELIVERED,
|
|
27
27
|
HEATMAP_EXPORTED,
|
|
28
28
|
HEATMAP_TOTAL,
|
|
29
|
+
HEATMAP_DELIVERED_DESCRIPTION,
|
|
30
|
+
HEATMAP_EXPORTED_DESCRIPTION,
|
|
31
|
+
HEATMAP_TOTAL_DESCRIPTION,
|
|
29
32
|
)
|
|
30
33
|
|
|
31
34
|
|
|
32
|
-
def weigh_by_monthly_profile(
|
|
35
|
+
def weigh_by_monthly_profile(df: pd.DataFrame, series_name, profile_name) -> pd.Series:
|
|
33
36
|
"""Weigh a time series by a monthly profile."""
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
frame["weighted"] = frame["series"].sum() * (frame["profile"] / frame["profile"].sum())
|
|
39
|
-
results.append(frame)
|
|
40
|
-
return pd.concat(results)["weighted"]
|
|
37
|
+
grouped = df.groupby(pd.Grouper(freq="MS"))
|
|
38
|
+
return grouped[series_name].transform("sum") * grouped[profile_name].transform(
|
|
39
|
+
lambda x: x / x.sum()
|
|
40
|
+
)
|
|
41
41
|
|
|
42
42
|
|
|
43
43
|
def extend_dataframe_with_smr2(df: pd.DataFrame, inplace: bool = False) -> pd.DataFrame | None:
|
|
@@ -47,12 +47,8 @@ def extend_dataframe_with_smr2(df: pd.DataFrame, inplace: bool = False) -> pd.Da
|
|
|
47
47
|
else:
|
|
48
48
|
result_df = df
|
|
49
49
|
|
|
50
|
-
result_df[ELECTRICITY_DELIVERED_SMR2] = weigh_by_monthly_profile(
|
|
51
|
-
|
|
52
|
-
)
|
|
53
|
-
result_df[ELECTRICITY_EXPORTED_SMR2] = weigh_by_monthly_profile(
|
|
54
|
-
df[ELECTRICITY_EXPORTED], df[SPP]
|
|
55
|
-
)
|
|
50
|
+
result_df[ELECTRICITY_DELIVERED_SMR2] = weigh_by_monthly_profile(df, ELECTRICITY_DELIVERED, RLP)
|
|
51
|
+
result_df[ELECTRICITY_EXPORTED_SMR2] = weigh_by_monthly_profile(df, ELECTRICITY_EXPORTED, SPP)
|
|
56
52
|
|
|
57
53
|
result_df.rename(
|
|
58
54
|
columns={
|
|
@@ -78,14 +74,14 @@ def extend_dataframe_with_costs(df: pd.DataFrame, inplace: bool = False) -> pd.D
|
|
|
78
74
|
df[ELECTRICITY_DELIVERED_SMR2] * df[PRICE_ELECTRICITY_DELIVERED]
|
|
79
75
|
)
|
|
80
76
|
result_df[COST_ELECTRICITY_EXPORTED_SMR2] = (
|
|
81
|
-
df[ELECTRICITY_EXPORTED_SMR2] * df[PRICE_ELECTRICITY_EXPORTED]
|
|
77
|
+
df[ELECTRICITY_EXPORTED_SMR2] * df[PRICE_ELECTRICITY_EXPORTED] * -1
|
|
82
78
|
)
|
|
83
79
|
|
|
84
80
|
result_df[COST_ELECTRICITY_DELIVERED_SMR3] = (
|
|
85
81
|
df[ELECTRICITY_DELIVERED_SMR3] * df[PRICE_ELECTRICITY_DELIVERED]
|
|
86
82
|
)
|
|
87
83
|
result_df[COST_ELECTRICITY_EXPORTED_SMR3] = (
|
|
88
|
-
df[ELECTRICITY_EXPORTED_SMR3] * df[PRICE_ELECTRICITY_EXPORTED]
|
|
84
|
+
df[ELECTRICITY_EXPORTED_SMR3] * df[PRICE_ELECTRICITY_EXPORTED] * -1
|
|
89
85
|
)
|
|
90
86
|
|
|
91
87
|
if not inplace:
|
|
@@ -147,8 +143,7 @@ def extend_dataframe_with_heatmap(df: pd.DataFrame, inplace: bool = False) -> pd
|
|
|
147
143
|
|
|
148
144
|
# Invert scores so that positive values indicate a positive impact
|
|
149
145
|
heatmap_score_delivered = -heatmap_score_delivered
|
|
150
|
-
|
|
151
|
-
heatmap_score_combined = heatmap_score_delivered - heatmap_score_exported
|
|
146
|
+
heatmap_score_combined = heatmap_score_delivered + heatmap_score_exported
|
|
152
147
|
|
|
153
148
|
df[HEATMAP_DELIVERED] = heatmap_score_delivered
|
|
154
149
|
df[HEATMAP_EXPORTED] = heatmap_score_exported
|
|
@@ -159,6 +154,85 @@ def extend_dataframe_with_heatmap(df: pd.DataFrame, inplace: bool = False) -> pd
|
|
|
159
154
|
return None
|
|
160
155
|
|
|
161
156
|
|
|
157
|
+
def map_delivery_description(
|
|
158
|
+
price_delivered, price_rlp, electricity_delivered_smr3, electricity_delivered_smr2
|
|
159
|
+
):
|
|
160
|
+
"""Map the delivery description."""
|
|
161
|
+
if price_delivered > price_rlp and electricity_delivered_smr3 > electricity_delivered_smr2:
|
|
162
|
+
return 1
|
|
163
|
+
if price_delivered > price_rlp and electricity_delivered_smr3 < electricity_delivered_smr2:
|
|
164
|
+
return 2
|
|
165
|
+
if price_delivered < price_rlp and electricity_delivered_smr3 > electricity_delivered_smr2:
|
|
166
|
+
return 3
|
|
167
|
+
if price_delivered < price_rlp and electricity_delivered_smr3 < electricity_delivered_smr2:
|
|
168
|
+
return 4
|
|
169
|
+
return 0
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def map_export_description(
|
|
173
|
+
price_exported, price_spp, electricity_exported_smr3, electricity_exported_smr2
|
|
174
|
+
):
|
|
175
|
+
"""Map the export description."""
|
|
176
|
+
if price_exported > price_spp and electricity_exported_smr3 > electricity_exported_smr2:
|
|
177
|
+
return 5
|
|
178
|
+
if price_exported > price_spp and electricity_exported_smr3 < electricity_exported_smr2:
|
|
179
|
+
return 6
|
|
180
|
+
if price_exported < price_spp and electricity_exported_smr3 > electricity_exported_smr2:
|
|
181
|
+
return 7
|
|
182
|
+
if price_exported < price_spp and electricity_exported_smr3 < electricity_exported_smr2:
|
|
183
|
+
return 8
|
|
184
|
+
return 0
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def map_total_description(
|
|
188
|
+
abs_heatmap_delivered, abs_heatmap_exported, delivered_description, exported_description
|
|
189
|
+
):
|
|
190
|
+
"""Map the total description."""
|
|
191
|
+
if abs_heatmap_delivered > abs_heatmap_exported:
|
|
192
|
+
return delivered_description
|
|
193
|
+
return exported_description
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
def extend_dataframe_with_heatmap_description(
|
|
197
|
+
df: pd.DataFrame, inplace: bool = False
|
|
198
|
+
) -> pd.DataFrame | None:
|
|
199
|
+
"""Extend a DataFrame with the heatmap description columns."""
|
|
200
|
+
if not inplace:
|
|
201
|
+
df = df.copy()
|
|
202
|
+
|
|
203
|
+
df[HEATMAP_DELIVERED_DESCRIPTION] = list(
|
|
204
|
+
map(
|
|
205
|
+
map_delivery_description,
|
|
206
|
+
df[PRICE_ELECTRICITY_DELIVERED],
|
|
207
|
+
df[RLP_WEIGHTED_PRICE_DELIVERED],
|
|
208
|
+
df[ELECTRICITY_DELIVERED_SMR3],
|
|
209
|
+
df[ELECTRICITY_DELIVERED_SMR2],
|
|
210
|
+
)
|
|
211
|
+
)
|
|
212
|
+
df[HEATMAP_EXPORTED_DESCRIPTION] = list(
|
|
213
|
+
map(
|
|
214
|
+
map_export_description,
|
|
215
|
+
df[PRICE_ELECTRICITY_EXPORTED],
|
|
216
|
+
df[SPP_WEIGHTED_PRICE_EXPORTED],
|
|
217
|
+
df[ELECTRICITY_EXPORTED_SMR3],
|
|
218
|
+
df[ELECTRICITY_EXPORTED_SMR2],
|
|
219
|
+
)
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
df[HEATMAP_TOTAL_DESCRIPTION] = list(
|
|
223
|
+
map(
|
|
224
|
+
map_total_description,
|
|
225
|
+
df[HEATMAP_DELIVERED].abs(),
|
|
226
|
+
df[HEATMAP_EXPORTED].abs(),
|
|
227
|
+
df[HEATMAP_DELIVERED_DESCRIPTION],
|
|
228
|
+
df[HEATMAP_EXPORTED_DESCRIPTION],
|
|
229
|
+
)
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
if not inplace:
|
|
233
|
+
return df
|
|
234
|
+
|
|
235
|
+
|
|
162
236
|
def calculate_dyntar_columns(df: pd.DataFrame, inplace: bool = False) -> pd.DataFrame | None:
|
|
163
237
|
"""Calculate all columns required for the dynamic tariff analysis."""
|
|
164
238
|
if not inplace:
|
|
@@ -168,6 +242,7 @@ def calculate_dyntar_columns(df: pd.DataFrame, inplace: bool = False) -> pd.Data
|
|
|
168
242
|
extend_dataframe_with_costs(df, inplace=True)
|
|
169
243
|
extend_dataframe_with_weighted_prices(df, inplace=True)
|
|
170
244
|
extend_dataframe_with_heatmap(df, inplace=True)
|
|
245
|
+
extend_dataframe_with_heatmap_description(df, inplace=True)
|
|
171
246
|
|
|
172
247
|
if not inplace:
|
|
173
248
|
return df
|
openenergyid/dyntar/models.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""Models for dynamic tariff analysis."""
|
|
2
2
|
|
|
3
3
|
from typing import Literal
|
|
4
|
-
from pydantic import Field, conlist
|
|
4
|
+
from pydantic import Field, conlist, confloat
|
|
5
5
|
|
|
6
6
|
from openenergyid.models import TimeDataFrame
|
|
7
7
|
|
|
@@ -33,6 +33,9 @@ OutputColumns = Literal[
|
|
|
33
33
|
"heatmap_delivered",
|
|
34
34
|
"heatmap_exported",
|
|
35
35
|
"heatmap_total",
|
|
36
|
+
"heatmap_delivered_description",
|
|
37
|
+
"heatmap_exported_description",
|
|
38
|
+
"heatmap_total_description",
|
|
36
39
|
]
|
|
37
40
|
|
|
38
41
|
|
|
@@ -46,11 +49,11 @@ class DynamicTariffAnalysisInput(TimeDataFrame):
|
|
|
46
49
|
)
|
|
47
50
|
data: list[
|
|
48
51
|
conlist(
|
|
49
|
-
item_type=
|
|
52
|
+
item_type=confloat(allow_inf_nan=True),
|
|
50
53
|
min_length=len(RequiredColumns.__args__),
|
|
51
54
|
max_length=len(RequiredColumns.__args__),
|
|
52
55
|
) # type: ignore
|
|
53
|
-
] = Field(examples=[[0.0
|
|
56
|
+
] = Field(examples=[[0.0] * len(RequiredColumns.__args__)])
|
|
54
57
|
|
|
55
58
|
|
|
56
59
|
class DynamicTariffAnalysisOutput(TimeDataFrame):
|
|
@@ -62,5 +65,9 @@ class DynamicTariffAnalysisOutput(TimeDataFrame):
|
|
|
62
65
|
examples=[OutputColumns.__args__],
|
|
63
66
|
)
|
|
64
67
|
data: list[
|
|
65
|
-
conlist(
|
|
66
|
-
|
|
68
|
+
conlist(
|
|
69
|
+
item_type=confloat(allow_inf_nan=True),
|
|
70
|
+
min_length=1,
|
|
71
|
+
max_length=len(OutputColumns.__args__),
|
|
72
|
+
) # type: ignore
|
|
73
|
+
] = Field(examples=[[0.0] * len(OutputColumns.__args__)])
|
openenergyid/models.py
CHANGED
|
@@ -6,7 +6,7 @@ from typing import overload
|
|
|
6
6
|
from typing import Self
|
|
7
7
|
|
|
8
8
|
import pandas as pd
|
|
9
|
-
from pydantic import BaseModel
|
|
9
|
+
from pydantic import BaseModel
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class TimeSeriesBase(BaseModel):
|
|
@@ -78,13 +78,7 @@ class TimeSeries(TimeSeriesBase):
|
|
|
78
78
|
"""
|
|
79
79
|
|
|
80
80
|
name: str | None = None
|
|
81
|
-
data: list[float
|
|
82
|
-
|
|
83
|
-
@field_validator("data")
|
|
84
|
-
@classmethod
|
|
85
|
-
def replace_nan_with_none(cls, data: list[float]) -> list[float | None]:
|
|
86
|
-
"""Replace NaN values with None."""
|
|
87
|
-
return [None if pd.isna(value) else value for value in data]
|
|
81
|
+
data: list[float]
|
|
88
82
|
|
|
89
83
|
@classmethod
|
|
90
84
|
def from_pandas(cls, data: pd.Series) -> Self:
|
|
@@ -102,13 +96,7 @@ class TimeDataFrame(TimeSeriesBase):
|
|
|
102
96
|
"""Time series data with multiple columns."""
|
|
103
97
|
|
|
104
98
|
columns: list[str]
|
|
105
|
-
data: list[list[float
|
|
106
|
-
|
|
107
|
-
@field_validator("data")
|
|
108
|
-
@classmethod
|
|
109
|
-
def replace_nan_with_none(cls, data: list[list[float]]) -> list[list[float | None]]:
|
|
110
|
-
"""Replace NaN values with None."""
|
|
111
|
-
return [[None if pd.isna(value) else value for value in row] for row in data]
|
|
99
|
+
data: list[list[float]]
|
|
112
100
|
|
|
113
101
|
@classmethod
|
|
114
102
|
def from_pandas(cls, data: pd.DataFrame) -> Self:
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
openenergyid/__init__.py,sha256=
|
|
1
|
+
openenergyid/__init__.py,sha256=Rw7W-OZewpvJwVPQ0xjjsiXdeT-QpbmEmBER7arAMYo,193
|
|
2
2
|
openenergyid/const.py,sha256=D-xUnUyVuLmphClkePgxpFP6z0RDhw_6m7rX0BHBgrw,823
|
|
3
3
|
openenergyid/enums.py,sha256=jdw4CB1gkisx0re_SesrTEyh_T-UxYp6uieE7iYlHdA,357
|
|
4
|
-
openenergyid/models.py,sha256=
|
|
4
|
+
openenergyid/models.py,sha256=CO6VdthCOQ9hNXqVSan_4IOBpiQvOix-ea3U6TR7Vgc,4343
|
|
5
5
|
openenergyid/capacity/__init__.py,sha256=1En96HlPV8kd1hOJO9RjRbXNInp5ZSkmjsjp0jfZlcQ,221
|
|
6
6
|
openenergyid/capacity/main.py,sha256=G6_EtXs1k_W-fxS33pFrCNKajuH81skdI32zp5RX9bI,3674
|
|
7
7
|
openenergyid/capacity/models.py,sha256=qi0IFyF_QOVleSzN8g0U2Fzqcc9ZDfNKt8oteFLY6Q0,832
|
|
8
8
|
openenergyid/dyntar/__init__.py,sha256=iQXQXrEQOiVNeeF6LRmUf3oOhKlGjMNF7o4T04IWTGA,371
|
|
9
|
-
openenergyid/dyntar/const.py,sha256=
|
|
10
|
-
openenergyid/dyntar/main.py,sha256=
|
|
11
|
-
openenergyid/dyntar/models.py,sha256=
|
|
9
|
+
openenergyid/dyntar/const.py,sha256=17qL0-S0SImsqrDEDrGS2GLyJYcJRw6GmmcTiML7tR0,956
|
|
10
|
+
openenergyid/dyntar/main.py,sha256=yRPamC5dHwpiDj07RM2iVKk3gZk8a81zKSjOsjewACo,8247
|
|
11
|
+
openenergyid/dyntar/models.py,sha256=FZq7HI1F-3nVeHwPkuB38-8u32JzdvsZaCzrhirFD2g,2094
|
|
12
12
|
openenergyid/energysharing/__init__.py,sha256=A4JfrUYf-hBCzhUm0qL1GGlNMvpO8OwXJo80dJxFIvw,274
|
|
13
13
|
openenergyid/energysharing/const.py,sha256=X2zEPtTlsmZ66w6RmLS_h8NmdzObAEi5N6-0yrLN5V4,219
|
|
14
14
|
openenergyid/energysharing/data_formatting.py,sha256=Kwuhyn6ao_8Brdm9frlA6VzYOqimNYZsRbYwNXnE7yc,2583
|
|
@@ -19,7 +19,7 @@ openenergyid/mvlr/helpers.py,sha256=Uzbfrj3IpH26wA206KOl0hNucKE-n9guJNC_EROBVKA,
|
|
|
19
19
|
openenergyid/mvlr/main.py,sha256=cn7jZ98cHn2eh-0zG9q8Pad0Ft_FuI-u3a-eeHeF8jA,1304
|
|
20
20
|
openenergyid/mvlr/models.py,sha256=XvkViOLlYqi0ffgF3AD4Jvk3yL05gsoKdKgBAsGJ7L4,8581
|
|
21
21
|
openenergyid/mvlr/mvlr.py,sha256=F7WvWnZQtqUmK1vsguemsn9n8pDDk3tQ1weOlv-bo0c,18626
|
|
22
|
-
openenergyid-0.1.
|
|
23
|
-
openenergyid-0.1.
|
|
24
|
-
openenergyid-0.1.
|
|
25
|
-
openenergyid-0.1.
|
|
22
|
+
openenergyid-0.1.19.dist-info/METADATA,sha256=q8cD0GQr7JDOoStIRDI8r5z-9gvgt4dkuh98vBDWJBw,2477
|
|
23
|
+
openenergyid-0.1.19.dist-info/WHEEL,sha256=fl6v0VwpzfGBVsGtkAkhILUlJxROXbA3HvRL6Fe3140,105
|
|
24
|
+
openenergyid-0.1.19.dist-info/licenses/LICENSE,sha256=NgRdcNHwyXVCXZ8sJwoTp0DCowThJ9LWWl4xhbV1IUY,1074
|
|
25
|
+
openenergyid-0.1.19.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|