domainiac 9.2.0__py3-none-any.whl → 9.3.1__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.
- domainiac/__init__.py +1 -0
- domainiac/managers/__init__.py +1 -0
- domainiac/managers/availability_manager.py +58 -0
- domainiac/managers/nwp_manager.py +62 -23
- domainiac/managers/outage_manager.py +4 -4
- domainiac/managers/plant_manager.py +3 -3
- {domainiac-9.2.0.dist-info → domainiac-9.3.1.dist-info}/METADATA +2 -2
- {domainiac-9.2.0.dist-info → domainiac-9.3.1.dist-info}/RECORD +9 -8
- {domainiac-9.2.0.dist-info → domainiac-9.3.1.dist-info}/WHEEL +1 -1
domainiac/__init__.py
CHANGED
domainiac/managers/__init__.py
CHANGED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import datamazing.pandas as pdz
|
|
2
|
+
import pandas as pd
|
|
3
|
+
|
|
4
|
+
from .outage_manager import OutageManager
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class AvailabilityManager:
|
|
8
|
+
"""
|
|
9
|
+
Manager which simplifies the process of getting availability data.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
def __init__(
|
|
13
|
+
self,
|
|
14
|
+
db: pdz.Database,
|
|
15
|
+
time_interval: pdz.TimeInterval,
|
|
16
|
+
resolution: pd.Timedelta,
|
|
17
|
+
) -> None:
|
|
18
|
+
self.db = db
|
|
19
|
+
self.time_interval = time_interval
|
|
20
|
+
self.resolution = resolution
|
|
21
|
+
self.outage_manager = OutageManager(db, time_interval, resolution)
|
|
22
|
+
|
|
23
|
+
def get_availability(self) -> pd.DataFrame:
|
|
24
|
+
df_availability = self.db.query("scheduleAvailability", self.time_interval)
|
|
25
|
+
df_outage = self.outage_manager.get_plant_outage_time_series()
|
|
26
|
+
|
|
27
|
+
# Rename resource_gsrn to plant_gsrn for consistent merge
|
|
28
|
+
df_availability = df_availability.rename(
|
|
29
|
+
columns={
|
|
30
|
+
"resource_gsrn": "plant_gsrn",
|
|
31
|
+
"schedule_resource_capacity_max_MW": "capacity_max_MW",
|
|
32
|
+
"schedule_resource_capacity_min_MW": "capacity_min_MW",
|
|
33
|
+
}
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
required_columns = [
|
|
37
|
+
"time_utc",
|
|
38
|
+
"plant_gsrn",
|
|
39
|
+
"capacity_max_MW",
|
|
40
|
+
"capacity_min_MW",
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
# Create an indicator column in outage to mark where outages exist
|
|
44
|
+
df_outage["has_outage"] = True
|
|
45
|
+
|
|
46
|
+
# Merge availability with outage data
|
|
47
|
+
df_available = df_availability.merge(
|
|
48
|
+
df_outage, on=["plant_gsrn", "time_utc"], how="outer"
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
# Where there's an outage, set capacity to zero
|
|
52
|
+
has_outage = df_available["has_outage"].fillna(False)
|
|
53
|
+
df_available.loc[has_outage, "capacity_max_MW"] = 0
|
|
54
|
+
df_available.loc[has_outage, "capacity_min_MW"] = 0
|
|
55
|
+
|
|
56
|
+
# Return only the required columns
|
|
57
|
+
df_available = df_available[required_columns]
|
|
58
|
+
return df_available
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from functools import lru_cache
|
|
2
|
+
|
|
1
3
|
import datamazing.pandas as pdz
|
|
2
4
|
import numpy as np
|
|
3
5
|
import pandas as pd
|
|
@@ -9,26 +11,36 @@ from ..modeling.nwp import Coordinate, Neighborhood, NWPParameter, NWPProvider
|
|
|
9
11
|
|
|
10
12
|
|
|
11
13
|
class NWPManager:
|
|
12
|
-
"""
|
|
13
|
-
Contains all logic concerning NWP data.
|
|
14
|
-
This includes:
|
|
15
|
-
- Getting NWP data
|
|
16
|
-
- Getting average NWP data
|
|
17
|
-
- Finding closest NWP coordinates
|
|
18
|
-
"""
|
|
19
|
-
|
|
20
14
|
def __init__(
|
|
21
15
|
self,
|
|
22
16
|
db: pdz.Database,
|
|
23
17
|
time_interval: pdz.TimeInterval,
|
|
24
18
|
resolution: pd.Timedelta,
|
|
19
|
+
cache_nwp: bool = True,
|
|
25
20
|
):
|
|
21
|
+
"""
|
|
22
|
+
Contains all logic concerning NWP data.
|
|
23
|
+
This includes:
|
|
24
|
+
- Getting NWP data
|
|
25
|
+
- Getting average NWP data
|
|
26
|
+
- Finding closest NWP coordinates
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
db (pdz.Database): Database backend
|
|
30
|
+
time_interval (pdz.TimeInterval): Time interval
|
|
31
|
+
resolution (pd.Timedelta): Time resolution
|
|
32
|
+
cache_nwp (bool, optional): Current implementation of this managers
|
|
33
|
+
is not very efficient when querying multiple coordinates. To mitigate
|
|
34
|
+
this, database queries can be cached. This is especially useful when
|
|
35
|
+
querying multiple coordinates. Defaults to True.
|
|
36
|
+
"""
|
|
26
37
|
self.db = db
|
|
27
38
|
self.time_interval = time_interval
|
|
28
39
|
self.resolution = resolution
|
|
29
40
|
|
|
30
41
|
self._nwp_coordinates_kd_tree = dict()
|
|
31
42
|
self._nwp_table_name_prefix = "forecastNwp"
|
|
43
|
+
self.cache_nwp = cache_nwp
|
|
32
44
|
|
|
33
45
|
@staticmethod
|
|
34
46
|
def calculate_wind_speed_from_vectors(u: pd.Series, v: pd.Series) -> pd.Series:
|
|
@@ -111,15 +123,24 @@ class NWPManager:
|
|
|
111
123
|
|
|
112
124
|
return coordinates
|
|
113
125
|
|
|
126
|
+
@lru_cache()
|
|
127
|
+
def _query_cached(
|
|
128
|
+
self,
|
|
129
|
+
table: str,
|
|
130
|
+
time_interval: pdz.TimeInterval,
|
|
131
|
+
) -> pd.DataFrame:
|
|
132
|
+
"""
|
|
133
|
+
Query the database with caching.
|
|
134
|
+
"""
|
|
135
|
+
df = self.db.query(table, time_interval)
|
|
136
|
+
return df
|
|
137
|
+
|
|
114
138
|
def _get_nwp_parameter(
|
|
115
139
|
self,
|
|
116
140
|
provider: NWPProvider,
|
|
117
141
|
parameter: NWPParameter,
|
|
118
142
|
coordinate: Coordinate,
|
|
119
143
|
) -> pd.DataFrame:
|
|
120
|
-
"""
|
|
121
|
-
Get NWP data for a given parameter, coordinate and altitude.
|
|
122
|
-
"""
|
|
123
144
|
table = self._get_table_name(provider, parameter)
|
|
124
145
|
|
|
125
146
|
filters = {
|
|
@@ -138,7 +159,13 @@ class NWPManager:
|
|
|
138
159
|
self.time_interval.right + query_margin,
|
|
139
160
|
)
|
|
140
161
|
|
|
141
|
-
|
|
162
|
+
# Cache query if specified
|
|
163
|
+
# This is useful when querying multiple coordinates.
|
|
164
|
+
if self.cache_nwp:
|
|
165
|
+
df = self._query_cached(table, padded_time_interval)
|
|
166
|
+
df = df.loc[(df[list(filters)] == pd.Series(filters)).all(axis=1)]
|
|
167
|
+
else:
|
|
168
|
+
df = self.db.query(table, padded_time_interval, filters=filters)
|
|
142
169
|
|
|
143
170
|
df = df.drop(
|
|
144
171
|
columns=[
|
|
@@ -160,10 +187,6 @@ class NWPManager:
|
|
|
160
187
|
parameter: NWPParameter,
|
|
161
188
|
coordinate: Coordinate,
|
|
162
189
|
):
|
|
163
|
-
"""
|
|
164
|
-
Get NWP data for a given parameter, coordinate and altitude,
|
|
165
|
-
using the proper interpolation technique.
|
|
166
|
-
"""
|
|
167
190
|
df = self._get_nwp_parameter(provider, parameter, coordinate)
|
|
168
191
|
|
|
169
192
|
df = df.sort_values(by="time_utc")
|
|
@@ -214,9 +237,12 @@ class NWPManager:
|
|
|
214
237
|
parameter: NWPParameter,
|
|
215
238
|
coordinate: Coordinate,
|
|
216
239
|
):
|
|
217
|
-
df_nwp = self._get_interpolated_nwp_parameter(
|
|
240
|
+
df_nwp = self._get_interpolated_nwp_parameter(
|
|
241
|
+
provider,
|
|
242
|
+
parameter,
|
|
243
|
+
coordinate,
|
|
244
|
+
)
|
|
218
245
|
|
|
219
|
-
# Ensure data is within time_interval defined by user
|
|
220
246
|
df_nwp = df_nwp.query(
|
|
221
247
|
f"time_utc >= '{self.time_interval.left}' "
|
|
222
248
|
f"and time_utc <= '{self.time_interval.right}'",
|
|
@@ -230,14 +256,15 @@ class NWPManager:
|
|
|
230
256
|
parameter: NWPParameter,
|
|
231
257
|
neighborhood: Neighborhood,
|
|
232
258
|
) -> pd.DataFrame:
|
|
233
|
-
"""
|
|
234
|
-
Get average NWP data for a given parameter, coordinates and altitude.
|
|
235
|
-
"""
|
|
236
259
|
dfs = []
|
|
237
260
|
|
|
238
261
|
neighbors = self.get_nwp_neighbors(provider, parameter, neighborhood)
|
|
239
262
|
for coordinate in neighbors:
|
|
240
|
-
df_coordinate = self.get_nwp_parameter(
|
|
263
|
+
df_coordinate = self.get_nwp_parameter(
|
|
264
|
+
provider,
|
|
265
|
+
parameter,
|
|
266
|
+
coordinate,
|
|
267
|
+
)
|
|
241
268
|
dfs.append(df_coordinate)
|
|
242
269
|
|
|
243
270
|
df = pd.concat(dfs)
|
|
@@ -252,7 +279,19 @@ class NWPManager:
|
|
|
252
279
|
neighborhood: Neighborhood,
|
|
253
280
|
) -> pd.DataFrame:
|
|
254
281
|
"""
|
|
255
|
-
Get
|
|
282
|
+
Get NWP data for multiple parameters over a neighborhood.
|
|
283
|
+
|
|
284
|
+
For each parameter, retrieves the average NWP data in the neighborhood, then
|
|
285
|
+
merges all results on the time_utc column.
|
|
286
|
+
|
|
287
|
+
Args:
|
|
288
|
+
provider (NWPProvider): The NWP data provider to use.
|
|
289
|
+
parameters (list[NWPParameter]): List of NWP parameters to retrieve.
|
|
290
|
+
neighborhood (Neighborhood): The neighborhood specifying the central
|
|
291
|
+
coordinate and number of neighbors.
|
|
292
|
+
|
|
293
|
+
Returns:
|
|
294
|
+
pd.DataFrame: DataFrame with merged parameter values, indexed by time_utc.
|
|
256
295
|
"""
|
|
257
296
|
dfs = []
|
|
258
297
|
for parameter in parameters:
|
|
@@ -22,7 +22,7 @@ class OutageManager:
|
|
|
22
22
|
|
|
23
23
|
df_outage = df_outage[~df_outage["is_unapproved"]]
|
|
24
24
|
|
|
25
|
-
df_outage = df_outage.dropna(subset="plant_gsrn")
|
|
25
|
+
df_outage = df_outage.dropna(subset=["plant_gsrn"])
|
|
26
26
|
|
|
27
27
|
# make placeholder dataframe to explode outage
|
|
28
28
|
# data to all time points for all plants
|
|
@@ -34,12 +34,12 @@ class OutageManager:
|
|
|
34
34
|
|
|
35
35
|
df_idx = df_times.merge(df_plants, how="cross")
|
|
36
36
|
|
|
37
|
-
df_outage = pdz.
|
|
37
|
+
df_outage = pdz.merge_point_interval(
|
|
38
38
|
df_idx,
|
|
39
39
|
df_outage,
|
|
40
40
|
on=["plant_gsrn"],
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
left_point="time_utc",
|
|
42
|
+
right_interval=("start_time_utc", "end_time_utc"),
|
|
43
43
|
)
|
|
44
44
|
|
|
45
45
|
df_outage = df_outage.filter(
|
|
@@ -72,11 +72,11 @@ class PlantManager(MasterdataManager):
|
|
|
72
72
|
df_plant = self.get_operational_entities("masterdataPlant")
|
|
73
73
|
df_plant = df_plant.query(f"masterdata_gsrn == '{gsrn}'")
|
|
74
74
|
|
|
75
|
-
df_plant = pdz.
|
|
75
|
+
df_plant = pdz.merge_point_interval(
|
|
76
76
|
df_times,
|
|
77
77
|
df_plant,
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
left_point="time_utc",
|
|
79
|
+
right_interval=("valid_from_date_utc", "valid_to_date_utc"),
|
|
80
80
|
)
|
|
81
81
|
|
|
82
82
|
return df_plant.filter(["time_utc", "installed_power_MW"]).reset_index(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: domainiac
|
|
3
|
-
Version: 9.
|
|
3
|
+
Version: 9.3.1
|
|
4
4
|
Summary: Package for working with Energinet data, but with specialized functions used for Enigma.
|
|
5
5
|
Author: Team Enigma
|
|
6
6
|
Author-email: enigma@energinet.dk
|
|
@@ -11,7 +11,7 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
11
11
|
Classifier: Programming Language :: Python :: 3.12
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.13
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.14
|
|
14
|
-
Requires-Dist: datamazing (>=
|
|
14
|
+
Requires-Dist: datamazing (>=6.0.0)
|
|
15
15
|
Requires-Dist: pandas (>=2.2.0)
|
|
16
16
|
Requires-Dist: pvlib (>=0.13.1)
|
|
17
17
|
Requires-Dist: scikit-learn (>=1.3.0)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
domainiac/__init__.py,sha256=
|
|
1
|
+
domainiac/__init__.py,sha256=Xaeq4K8dcStlSilXiL6Sr0fCNgtPgWCKi93n8Cu8Cjw,232
|
|
2
2
|
domainiac/functions/__init__.py,sha256=ZHNbj1aWRnUgM6TAlQqGLv2r-GdAvoaTrPIin1w5Dk0,137
|
|
3
3
|
domainiac/functions/conversions.py,sha256=RZU5cpHD4uBHeqFfiFplJCv5gN-xzEHvQCKrizi1hMA,490
|
|
4
4
|
domainiac/functions/interpolation.py,sha256=qj-sTEbez_IcXLY7eOS_KqAAd8GbhP5JBkdWrUPjWIQ,3720
|
|
@@ -6,12 +6,13 @@ domainiac/functions/solar.py,sha256=nU9ivDLA4gE0CTMttCb_7ztoQUQicWNe_11ZqVC7d-Y,
|
|
|
6
6
|
domainiac/functions/temperature.py,sha256=-t_zWYIhYwJpyZEQgwxgR9SkeYAAjvb6qeV8LtDtfmk,940
|
|
7
7
|
domainiac/functions/typing.py,sha256=gOvHUYIWSEv_aMttY1nMEyh-pdQKMJ8O31x9y47-U5U,229
|
|
8
8
|
domainiac/functions/wind.py,sha256=ZOxSMxjWV7LZsAQVW5Y-GPMhZzfvIsh3NOtSXB5lUAY,993
|
|
9
|
-
domainiac/managers/__init__.py,sha256=
|
|
9
|
+
domainiac/managers/__init__.py,sha256=A4KdK_LiukXKlJLIF1hf8HF7xh3QeFdBqAWstXc8CgI,352
|
|
10
|
+
domainiac/managers/availability_manager.py,sha256=zKRjZlG5wp3MlviIbNg3s5da9nUKjP7_r8R5g8hHRg4,1895
|
|
10
11
|
domainiac/managers/masterdata_manager.py,sha256=_xIHEWVYssdvC2VMujvR0ANXCI_Er3qOlfAX427yimk,2298
|
|
11
12
|
domainiac/managers/metering_manager.py,sha256=MauMncY_yaVPx8Y9CCD8nJiE1BGHFKTVC1bOtiyl2pI,1701
|
|
12
|
-
domainiac/managers/nwp_manager.py,sha256=
|
|
13
|
-
domainiac/managers/outage_manager.py,sha256=
|
|
14
|
-
domainiac/managers/plant_manager.py,sha256=
|
|
13
|
+
domainiac/managers/nwp_manager.py,sha256=h2J6ryXqplB_W6jC7aSenOa9MOxsYrd2HenU3WZnyu0,10040
|
|
14
|
+
domainiac/managers/outage_manager.py,sha256=KnBjsDFX8xQvA2UGh7gX2fTVwoQlF6PFoy5Uk_s3kfs,1436
|
|
15
|
+
domainiac/managers/plant_manager.py,sha256=Bh1jPwepDq_yO29QVZndjCXe3ScQndIsKwFZnjr9a8w,5101
|
|
15
16
|
domainiac/managers/resource_manager.py,sha256=QMkNcrgyXLLlkCR9kg4-nFjTaYHtlsldex-b_8lAmO0,3730
|
|
16
17
|
domainiac/managers/unit_manager.py,sha256=DYF-AiBHzUGZJE5XlTLcszvgIQkSzZs_s9o35l4bkVk,1219
|
|
17
18
|
domainiac/modeling/__init__.py,sha256=Ac5feYZ9gVLayU1Cb1ACqOyDrmvcxoOvZuUkOeXVKf8,101
|
|
@@ -19,6 +20,6 @@ domainiac/modeling/nwp.py,sha256=PolrBdQn8W-e1M0_pefvmLn2mr4HT0NqlYlkyCV0dds,438
|
|
|
19
20
|
domainiac/modeling/plant.py,sha256=Y0_Q6V6Lj3irJh5z-49r5gFJdD4Xl_pfHIMUhdaJVUI,2226
|
|
20
21
|
domainiac/wrappers/__init__.py,sha256=vZOw9maXgVoAvudZqioD-GTPkgPI6fm7_CUELQcR_-g,43
|
|
21
22
|
domainiac/wrappers/cache_wrapper.py,sha256=jDg-Lt_y-YzItyP-74tGULOxb07s_CcutmOHP1Ie00Q,355
|
|
22
|
-
domainiac-9.
|
|
23
|
-
domainiac-9.
|
|
24
|
-
domainiac-9.
|
|
23
|
+
domainiac-9.3.1.dist-info/METADATA,sha256=MonbkoqmH-AXby94IcR3J04hcDP9wiqeD3EUEM3hWlA,737
|
|
24
|
+
domainiac-9.3.1.dist-info/WHEEL,sha256=3ny-bZhpXrU6vSQ1UPG34FoxZBp3lVcvK0LkgUz6VLk,88
|
|
25
|
+
domainiac-9.3.1.dist-info/RECORD,,
|