Skip to content

Commit ec029e5

Browse files
committed
added query_unavailability_of_offshore_grid for offshore grid outages. not very flexible at the moment but its a start. closes #344
1 parent 2b319b1 commit ec029e5

File tree

4 files changed

+38
-4
lines changed

4 files changed

+38
-4
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ client.query_imbalance_prices(country_code, start, end, psr_type=None)
5757
client.query_unavailability_of_generation_units(country_code, start, end, docstatus=None, periodstartupdate=None, periodendupdate=None)
5858
client.query_unavailability_of_production_units(country_code, start, end, docstatus=None, periodstartupdate=None, periodendupdate=None)
5959
client.query_unavailability_transmission(country_code_from, country_code_to, start, end, docstatus=None, periodstartupdate=None, periodendupdate=None)
60+
client.query_unavailability_of_offshore_grid(area_code, start, end)
6061
client.query_withdrawn_unavailability_of_generation_units(country_code, start, end)
6162
```
6263
#### Dump result to file
@@ -134,6 +135,7 @@ client.query_unavailability_of_generation_units(country_code, start=start, end=e
134135
client.query_unavailability_of_production_units(country_code, start, end, docstatus=None, periodstartupdate=None, periodendupdate=None)
135136
client.query_unavailability_transmission(country_code_from, country_code_to, start=start, end=end, docstatus=None, periodstartupdate=None, periodendupdate=None)
136137
client.query_withdrawn_unavailability_of_generation_units(country_code, start, end)
138+
client.query_unavailability_of_offshore_grid(area_code, start, end)
137139
client.query_physical_crossborder_allborders(country_code, start, end, export=True)
138140
client.query_generation_import(country_code, start, end)
139141
client.query_procured_balancing_capacity(country_code, process_type, start=start, end=end, type_marketagreement_type=None)

entsoe/entsoe.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,16 @@
1515
parse_installed_capacity_per_plant, parse_crossborder_flows, \
1616
parse_unavailabilities, parse_contracted_reserve, parse_imbalance_prices_zip, \
1717
parse_imbalance_volumes_zip, parse_netpositions, parse_procured_balancing_capacity, \
18-
parse_water_hydro,parse_aggregated_bids, parse_activated_balancing_energy_prices
18+
parse_water_hydro,parse_aggregated_bids, parse_activated_balancing_energy_prices, \
19+
parse_offshore_unavailability
1920
from .decorators import retry, paginated, year_limited, day_limited, documents_limited
2021
import warnings
2122

2223
logger = logging.getLogger(__name__)
2324
warnings.filterwarnings('ignore', category=XMLParsedAsHTMLWarning)
2425

2526
__title__ = "entsoe-py"
26-
__version__ = "0.6.14"
27+
__version__ = "0.6.15"
2728
__author__ = "EnergieID.be, Frank Boerman"
2829
__license__ = "MIT"
2930

@@ -1057,6 +1058,11 @@ def query_unavailability_of_generation_units(
10571058
periodendupdate=periodendupdate, mRID=mRID, offset=offset)
10581059
return content
10591060

1061+
def query_unavailability_of_offshore_grid(self, area_code: Union[Area, str], start: pd.Timestamp, end: pd.Timestamp):
1062+
return self._query_unavailability(
1063+
country_code=area_code, start=start, end=end, doctype='A79'
1064+
)
1065+
10601066
def query_unavailability_of_production_units(
10611067
self, country_code: Union[Area, str], start: pd.Timestamp,
10621068
end: pd.Timestamp, docstatus: Optional[str] = None,
@@ -2067,6 +2073,16 @@ def _query_unavailability(
20672073
df = df[(df['start'] < end) | (df['end'] > start)]
20682074
return df
20692075

2076+
def query_unavailability_of_offshore_grid(self, area_code: Union[Area, str],
2077+
start: pd.Timestamp, end: pd.Timestamp
2078+
) -> pd.DataFrame:
2079+
zipfile = super(EntsoePandasClient, self)._query_unavailability(
2080+
country_code=area_code, start=start, end=end, doctype='A79'
2081+
)
2082+
df = parse_offshore_unavailability(zipfile)
2083+
return df
2084+
2085+
20702086
def query_unavailability_of_generation_units(
20712087
self, country_code: Union[Area, str], start: pd.Timestamp,
20722088
end: pd.Timestamp, docstatus: Optional[str] = None,

entsoe/parsers.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -942,6 +942,21 @@ def parse_unavailabilities(response: bytes, doctype: str) -> pd.DataFrame:
942942
return df
943943

944944

945+
def parse_offshore_unavailability(response: bytes) -> pd.DataFrame:
946+
"""
947+
offshore has slightly different structure so use seperate parser. this also enables using the new generic parsers as well
948+
"""
949+
df = {}
950+
with zipfile.ZipFile(BytesIO(response), 'r') as arc:
951+
for f in arc.infolist():
952+
if f.filename.endswith('xml'):
953+
for series in _extract_timeseries(arc.read(f)):
954+
asset = series.find('Asset_RegisteredResource'.lower())
955+
name = "|".join([asset.find(x).text for x in ['mrid', 'name', 'location.name']])
956+
df[name] = _parse_timeseries_generic(series, merge_series=True, period_name='windpowerfeedin_period')
957+
return pd.DataFrame(df)
958+
959+
945960
def _available_period(timeseries: bs4.BeautifulSoup) -> list:
946961
# if not timeseries:
947962
# return

entsoe/series_parsers.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ def _resolution_to_timedelta(res_text: str) -> str:
3131
'P1D': '1D',
3232
'P7D': '7D',
3333
'P1M': '1MS',
34+
'PT1M': '1min'
3435
}
3536
delta = resolutions.get(res_text)
3637
if delta is None:
@@ -82,14 +83,14 @@ def _parse_datetimeindex(soup, tz=None):
8283
return index
8384

8485

85-
def _parse_timeseries_generic(soup, label='quantity', to_float=True, merge_series=False):
86+
def _parse_timeseries_generic(soup, label='quantity', to_float=True, merge_series=False, period_name='period'):
8687
series = {
8788
'15min': [],
8889
'30min': [],
8990
'60min': []
9091
}
9192

92-
for period in soup.find_all('period'):
93+
for period in soup.find_all(period_name):
9394
data = {}
9495
start = pd.Timestamp(period.find('start').text)
9596
end = pd.Timestamp(period.find('end').text)

0 commit comments

Comments
 (0)