Skip to content

Commit

Permalink
added query_unavailability_of_offshore_grid for offshore grid outages…
Browse files Browse the repository at this point in the history
…. not very flexible at the moment but its a start. closes #344
  • Loading branch information
fboerman committed Oct 24, 2024
1 parent 2b319b1 commit ec029e5
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 4 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ client.query_imbalance_prices(country_code, start, end, psr_type=None)
client.query_unavailability_of_generation_units(country_code, start, end, docstatus=None, periodstartupdate=None, periodendupdate=None)
client.query_unavailability_of_production_units(country_code, start, end, docstatus=None, periodstartupdate=None, periodendupdate=None)
client.query_unavailability_transmission(country_code_from, country_code_to, start, end, docstatus=None, periodstartupdate=None, periodendupdate=None)
client.query_unavailability_of_offshore_grid(area_code, start, end)
client.query_withdrawn_unavailability_of_generation_units(country_code, start, end)
```
#### Dump result to file
Expand Down Expand Up @@ -134,6 +135,7 @@ client.query_unavailability_of_generation_units(country_code, start=start, end=e
client.query_unavailability_of_production_units(country_code, start, end, docstatus=None, periodstartupdate=None, periodendupdate=None)
client.query_unavailability_transmission(country_code_from, country_code_to, start=start, end=end, docstatus=None, periodstartupdate=None, periodendupdate=None)
client.query_withdrawn_unavailability_of_generation_units(country_code, start, end)
client.query_unavailability_of_offshore_grid(area_code, start, end)
client.query_physical_crossborder_allborders(country_code, start, end, export=True)
client.query_generation_import(country_code, start, end)
client.query_procured_balancing_capacity(country_code, process_type, start=start, end=end, type_marketagreement_type=None)
Expand Down
20 changes: 18 additions & 2 deletions entsoe/entsoe.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,16 @@
parse_installed_capacity_per_plant, parse_crossborder_flows, \
parse_unavailabilities, parse_contracted_reserve, parse_imbalance_prices_zip, \
parse_imbalance_volumes_zip, parse_netpositions, parse_procured_balancing_capacity, \
parse_water_hydro,parse_aggregated_bids, parse_activated_balancing_energy_prices
parse_water_hydro,parse_aggregated_bids, parse_activated_balancing_energy_prices, \
parse_offshore_unavailability
from .decorators import retry, paginated, year_limited, day_limited, documents_limited
import warnings

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

__title__ = "entsoe-py"
__version__ = "0.6.14"
__version__ = "0.6.15"
__author__ = "EnergieID.be, Frank Boerman"
__license__ = "MIT"

Expand Down Expand Up @@ -1057,6 +1058,11 @@ def query_unavailability_of_generation_units(
periodendupdate=periodendupdate, mRID=mRID, offset=offset)
return content

def query_unavailability_of_offshore_grid(self, area_code: Union[Area, str], start: pd.Timestamp, end: pd.Timestamp):
return self._query_unavailability(
country_code=area_code, start=start, end=end, doctype='A79'
)

def query_unavailability_of_production_units(
self, country_code: Union[Area, str], start: pd.Timestamp,
end: pd.Timestamp, docstatus: Optional[str] = None,
Expand Down Expand Up @@ -2067,6 +2073,16 @@ def _query_unavailability(
df = df[(df['start'] < end) | (df['end'] > start)]
return df

def query_unavailability_of_offshore_grid(self, area_code: Union[Area, str],
start: pd.Timestamp, end: pd.Timestamp
) -> pd.DataFrame:
zipfile = super(EntsoePandasClient, self)._query_unavailability(
country_code=area_code, start=start, end=end, doctype='A79'
)
df = parse_offshore_unavailability(zipfile)
return df


def query_unavailability_of_generation_units(
self, country_code: Union[Area, str], start: pd.Timestamp,
end: pd.Timestamp, docstatus: Optional[str] = None,
Expand Down
15 changes: 15 additions & 0 deletions entsoe/parsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -942,6 +942,21 @@ def parse_unavailabilities(response: bytes, doctype: str) -> pd.DataFrame:
return df


def parse_offshore_unavailability(response: bytes) -> pd.DataFrame:
"""
offshore has slightly different structure so use seperate parser. this also enables using the new generic parsers as well
"""
df = {}
with zipfile.ZipFile(BytesIO(response), 'r') as arc:
for f in arc.infolist():
if f.filename.endswith('xml'):
for series in _extract_timeseries(arc.read(f)):
asset = series.find('Asset_RegisteredResource'.lower())
name = "|".join([asset.find(x).text for x in ['mrid', 'name', 'location.name']])
df[name] = _parse_timeseries_generic(series, merge_series=True, period_name='windpowerfeedin_period')
return pd.DataFrame(df)


def _available_period(timeseries: bs4.BeautifulSoup) -> list:
# if not timeseries:
# return
Expand Down
5 changes: 3 additions & 2 deletions entsoe/series_parsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ def _resolution_to_timedelta(res_text: str) -> str:
'P1D': '1D',
'P7D': '7D',
'P1M': '1MS',
'PT1M': '1min'
}
delta = resolutions.get(res_text)
if delta is None:
Expand Down Expand Up @@ -82,14 +83,14 @@ def _parse_datetimeindex(soup, tz=None):
return index


def _parse_timeseries_generic(soup, label='quantity', to_float=True, merge_series=False):
def _parse_timeseries_generic(soup, label='quantity', to_float=True, merge_series=False, period_name='period'):
series = {
'15min': [],
'30min': [],
'60min': []
}

for period in soup.find_all('period'):
for period in soup.find_all(period_name):
data = {}
start = pd.Timestamp(period.find('start').text)
end = pd.Timestamp(period.find('end').text)
Expand Down

0 comments on commit ec029e5

Please sign in to comment.