openenergyid 0.1.17__py2.py3-none-any.whl → 0.1.18__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 +115 -2
- openenergyid/dyntar/models.py +12 -5
- openenergyid/models.py +3 -15
- {openenergyid-0.1.17.dist-info → openenergyid-0.1.18.dist-info}/METADATA +1 -1
- {openenergyid-0.1.17.dist-info → openenergyid-0.1.18.dist-info}/RECORD +9 -9
- {openenergyid-0.1.17.dist-info → openenergyid-0.1.18.dist-info}/WHEEL +0 -0
- {openenergyid-0.1.17.dist-info → openenergyid-0.1.18.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,6 +26,9 @@ 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
|
|
|
@@ -147,8 +150,7 @@ def extend_dataframe_with_heatmap(df: pd.DataFrame, inplace: bool = False) -> pd
|
|
|
147
150
|
|
|
148
151
|
# Invert scores so that positive values indicate a positive impact
|
|
149
152
|
heatmap_score_delivered = -heatmap_score_delivered
|
|
150
|
-
|
|
151
|
-
heatmap_score_combined = heatmap_score_delivered - heatmap_score_exported
|
|
153
|
+
heatmap_score_combined = heatmap_score_delivered + heatmap_score_exported
|
|
152
154
|
|
|
153
155
|
df[HEATMAP_DELIVERED] = heatmap_score_delivered
|
|
154
156
|
df[HEATMAP_EXPORTED] = heatmap_score_exported
|
|
@@ -159,6 +161,116 @@ def extend_dataframe_with_heatmap(df: pd.DataFrame, inplace: bool = False) -> pd
|
|
|
159
161
|
return None
|
|
160
162
|
|
|
161
163
|
|
|
164
|
+
def extend_dataframe_with_heatmap_description(
|
|
165
|
+
df: pd.DataFrame, inplace: bool = False
|
|
166
|
+
) -> pd.DataFrame | None:
|
|
167
|
+
"""Extend a DataFrame with the heatmap description columns."""
|
|
168
|
+
if not inplace:
|
|
169
|
+
df = df.copy()
|
|
170
|
+
|
|
171
|
+
# Delivered
|
|
172
|
+
|
|
173
|
+
# Where Heatmap is 0, we put a desription of 0 (No impact)
|
|
174
|
+
df[HEATMAP_DELIVERED_DESCRIPTION] = df[HEATMAP_DELIVERED].apply(
|
|
175
|
+
lambda x: 0 if x == 0 else float("NaN")
|
|
176
|
+
)
|
|
177
|
+
# When the energy delta is positive, and the price delta is positive, we put a description of 1 (high consumption, high price)
|
|
178
|
+
df[HEATMAP_DELIVERED_DESCRIPTION] = df.apply(
|
|
179
|
+
lambda x: 1
|
|
180
|
+
if x[PRICE_ELECTRICITY_DELIVERED] > x[RLP_WEIGHTED_PRICE_DELIVERED]
|
|
181
|
+
and x[ELECTRICITY_DELIVERED_SMR3] > x[ELECTRICITY_DELIVERED_SMR2]
|
|
182
|
+
else x[HEATMAP_DELIVERED_DESCRIPTION],
|
|
183
|
+
axis=1,
|
|
184
|
+
)
|
|
185
|
+
# When the energy delta is negative, and the price delta is positive, we put a description of 2 (low consumption, high price)
|
|
186
|
+
df[HEATMAP_DELIVERED_DESCRIPTION] = df.apply(
|
|
187
|
+
lambda x: 2
|
|
188
|
+
if x[PRICE_ELECTRICITY_DELIVERED] > x[RLP_WEIGHTED_PRICE_DELIVERED]
|
|
189
|
+
and x[ELECTRICITY_DELIVERED_SMR3] < x[ELECTRICITY_DELIVERED_SMR2]
|
|
190
|
+
else x[HEATMAP_DELIVERED_DESCRIPTION],
|
|
191
|
+
axis=1,
|
|
192
|
+
)
|
|
193
|
+
# When the energy delta is positive, and the price delta is negative, we put a description of 3 (high consumption, low price)
|
|
194
|
+
df[HEATMAP_DELIVERED_DESCRIPTION] = df.apply(
|
|
195
|
+
lambda x: 3
|
|
196
|
+
if x[PRICE_ELECTRICITY_DELIVERED] < x[RLP_WEIGHTED_PRICE_DELIVERED]
|
|
197
|
+
and x[ELECTRICITY_DELIVERED_SMR3] > x[ELECTRICITY_DELIVERED_SMR2]
|
|
198
|
+
else x[HEATMAP_DELIVERED_DESCRIPTION],
|
|
199
|
+
axis=1,
|
|
200
|
+
)
|
|
201
|
+
# When the energy delta is negative, and the price delta is negative, we put a description of 4 (low consumption, low price)
|
|
202
|
+
df[HEATMAP_DELIVERED_DESCRIPTION] = df.apply(
|
|
203
|
+
lambda x: 4
|
|
204
|
+
if x[PRICE_ELECTRICITY_DELIVERED] < x[RLP_WEIGHTED_PRICE_DELIVERED]
|
|
205
|
+
and x[ELECTRICITY_DELIVERED_SMR3] < x[ELECTRICITY_DELIVERED_SMR2]
|
|
206
|
+
else x[HEATMAP_DELIVERED_DESCRIPTION],
|
|
207
|
+
axis=1,
|
|
208
|
+
)
|
|
209
|
+
# All other cases are put as 0
|
|
210
|
+
df[HEATMAP_DELIVERED_DESCRIPTION] = df[HEATMAP_DELIVERED_DESCRIPTION].replace(np.nan, 0)
|
|
211
|
+
|
|
212
|
+
# Exported
|
|
213
|
+
|
|
214
|
+
# Where Heatmap is 0, we put a desription of 0 (No impact)
|
|
215
|
+
df[HEATMAP_EXPORTED_DESCRIPTION] = df[HEATMAP_EXPORTED].apply(
|
|
216
|
+
lambda x: 0 if x == 0 else float("NaN")
|
|
217
|
+
)
|
|
218
|
+
# When the energy delta is positive, and the price delta is positive, we put a description of 5 (high injection, high price)
|
|
219
|
+
df[HEATMAP_EXPORTED_DESCRIPTION] = df.apply(
|
|
220
|
+
lambda x: 5
|
|
221
|
+
if x[PRICE_ELECTRICITY_EXPORTED] > x[SPP_WEIGHTED_PRICE_EXPORTED]
|
|
222
|
+
and x[ELECTRICITY_EXPORTED_SMR3] > x[ELECTRICITY_EXPORTED_SMR2]
|
|
223
|
+
else x[HEATMAP_EXPORTED_DESCRIPTION],
|
|
224
|
+
axis=1,
|
|
225
|
+
)
|
|
226
|
+
# When the energy delta is negative, and the price delta is positive, we put a description of 6 (low injection, high price)
|
|
227
|
+
df[HEATMAP_EXPORTED_DESCRIPTION] = df.apply(
|
|
228
|
+
lambda x: 6
|
|
229
|
+
if x[PRICE_ELECTRICITY_EXPORTED] > x[SPP_WEIGHTED_PRICE_EXPORTED]
|
|
230
|
+
and x[ELECTRICITY_EXPORTED_SMR3] < x[ELECTRICITY_EXPORTED_SMR2]
|
|
231
|
+
else x[HEATMAP_EXPORTED_DESCRIPTION],
|
|
232
|
+
axis=1,
|
|
233
|
+
)
|
|
234
|
+
# When the energy delta is positive, and the price delta is negative, we put a description of 7 (high injection, low price)
|
|
235
|
+
df[HEATMAP_EXPORTED_DESCRIPTION] = df.apply(
|
|
236
|
+
lambda x: 7
|
|
237
|
+
if x[PRICE_ELECTRICITY_EXPORTED] < x[SPP_WEIGHTED_PRICE_EXPORTED]
|
|
238
|
+
and x[ELECTRICITY_EXPORTED_SMR3] > x[ELECTRICITY_EXPORTED_SMR2]
|
|
239
|
+
else x[HEATMAP_EXPORTED_DESCRIPTION],
|
|
240
|
+
axis=1,
|
|
241
|
+
)
|
|
242
|
+
# When the energy delta is negative, and the price delta is negative, we put a description of 8 (low injection, low price)
|
|
243
|
+
df[HEATMAP_EXPORTED_DESCRIPTION] = df.apply(
|
|
244
|
+
lambda x: 8
|
|
245
|
+
if x[PRICE_ELECTRICITY_EXPORTED] < x[SPP_WEIGHTED_PRICE_EXPORTED]
|
|
246
|
+
and x[ELECTRICITY_EXPORTED_SMR3] < x[ELECTRICITY_EXPORTED_SMR2]
|
|
247
|
+
else x[HEATMAP_EXPORTED_DESCRIPTION],
|
|
248
|
+
axis=1,
|
|
249
|
+
)
|
|
250
|
+
# All other cases are put as 0
|
|
251
|
+
df[HEATMAP_EXPORTED_DESCRIPTION] = df[HEATMAP_EXPORTED_DESCRIPTION].replace(np.nan, 0)
|
|
252
|
+
|
|
253
|
+
# Total
|
|
254
|
+
|
|
255
|
+
# We see which of the individual heatmaps has the highest absolute value
|
|
256
|
+
# We put the description of the highest absolute value
|
|
257
|
+
df[HEATMAP_TOTAL_DESCRIPTION] = df.apply(
|
|
258
|
+
lambda x: x[HEATMAP_DELIVERED_DESCRIPTION]
|
|
259
|
+
if abs(x[HEATMAP_DELIVERED]) > abs(x[HEATMAP_EXPORTED])
|
|
260
|
+
else x[HEATMAP_EXPORTED_DESCRIPTION],
|
|
261
|
+
axis=1,
|
|
262
|
+
)
|
|
263
|
+
# Where Heatmap is 0, we put a desription of 0 (No impact)
|
|
264
|
+
df[HEATMAP_TOTAL_DESCRIPTION] = df.apply(
|
|
265
|
+
lambda x: 0 if x[HEATMAP_TOTAL] == 0 else x[HEATMAP_TOTAL_DESCRIPTION], axis=1
|
|
266
|
+
)
|
|
267
|
+
# All other cases are put as 0
|
|
268
|
+
df[HEATMAP_TOTAL_DESCRIPTION] = df[HEATMAP_TOTAL_DESCRIPTION].replace(np.nan, 0)
|
|
269
|
+
|
|
270
|
+
if not inplace:
|
|
271
|
+
return df
|
|
272
|
+
|
|
273
|
+
|
|
162
274
|
def calculate_dyntar_columns(df: pd.DataFrame, inplace: bool = False) -> pd.DataFrame | None:
|
|
163
275
|
"""Calculate all columns required for the dynamic tariff analysis."""
|
|
164
276
|
if not inplace:
|
|
@@ -168,6 +280,7 @@ def calculate_dyntar_columns(df: pd.DataFrame, inplace: bool = False) -> pd.Data
|
|
|
168
280
|
extend_dataframe_with_costs(df, inplace=True)
|
|
169
281
|
extend_dataframe_with_weighted_prices(df, inplace=True)
|
|
170
282
|
extend_dataframe_with_heatmap(df, inplace=True)
|
|
283
|
+
extend_dataframe_with_heatmap_description(df, inplace=True)
|
|
171
284
|
|
|
172
285
|
if not inplace:
|
|
173
286
|
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=ntL_zbXBUmsAcqrx7QRz8_g3CNWyjWhlg9osouG9a-k,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=z_F520eCsLcSYTo9e0iJBGpzoMo1G_TEECVCNi5rA_M,10732
|
|
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.18.dist-info/METADATA,sha256=d5UuJ8gqzwzSFx7aokbArsVr7RqetZoL8fJ3TwRuGlc,2477
|
|
23
|
+
openenergyid-0.1.18.dist-info/WHEEL,sha256=fl6v0VwpzfGBVsGtkAkhILUlJxROXbA3HvRL6Fe3140,105
|
|
24
|
+
openenergyid-0.1.18.dist-info/licenses/LICENSE,sha256=NgRdcNHwyXVCXZ8sJwoTp0DCowThJ9LWWl4xhbV1IUY,1074
|
|
25
|
+
openenergyid-0.1.18.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|