import numpy as np
import xarray as xr
import pandas as pd
import logging
import pvlib
from feedinlib.cds_request_tools import get_cds_data_from_datespan_and_position
[docs]def load_era5_weatherdata(lat, lon, year):
"""
Loads era5 weather data and converts it into format required by pvlib.
Parameters
----------
lat: float or int
latitude in the range [-90, 90] relative to the
equator, north corresponds to positive latitude.
lon: float or int
longitude in the range [-180, 180] relative to
Greenwich Meridian, east relative to the meridian corresponds to
positive longitude.
year: str
year
Returns
---------
:pandas:`pandas.DataFrame<frame>`
"""
start_date = str(year) + "-01-01"
end_date = str(year) + "-12-31"
logging.info("loading era5 weatherdata for the year %s" % year)
weather_xarray = get_era5_data_from_datespan_and_position(
start_date=start_date,
end_date=end_date,
variable="pvcompare",
latitude=lat,
longitude=lon,
grid=None,
target_file=None,
chunks=None,
cds_client=None,
)
logging.info("era5 weatherdata successfully loaded.")
weather_df = format_pvcompare(weather_xarray)
spa = pvlib.solarposition.spa_python(
time=weather_df.index, latitude=lat, longitude=lon
)
weather_df["dni"] = pvlib.irradiance.dirint(
weather_df["ghi"], solar_zenith=spa["zenith"], times=weather_df.index
).fillna(0)
weather_df["dhi"] = weather_df["ghi"] - (
weather_df["dni"] * np.cos(np.deg2rad(spa["zenith"]))
)
logging.info("weatherdata successfully converted into pvlib format.")
return weather_df
[docs]def get_era5_data_from_datespan_and_position(
start_date,
end_date,
variable="pvcompare",
latitude=None,
longitude=None,
grid=None,
target_file=None,
chunks=None,
cds_client=None,
):
"""
Send request for era5 data to the Climate Data Store (CDS)
Parameters
----------
variable: (str or list of str) ERA5 variables to download. If you
want to download all variables necessary to use the pvlib, set
`variable` to 'pvlib'. If you want to download all variables necessary
to use the windpowerlib, set `variable` to 'windpowerlib'. To download
both variable sets for pvlib and windpowerlib, set `variable` to
'feedinlib'.
start_date: str
start date of the date span in YYYY-MM-DD format
end_date: str
end date of the date span in YYYY-MM-DD format
latitude: number
latitude in the range [-90, 90] relative to the
equator, north corresponds to positive latitude.
longitude: number
longitude in the range [-180, 180] relative to
Greenwich Meridian, east relative to the meridian corresponds to
positive longitude.
grid: list of float
provide the latitude and longitude grid resolutions in deg. It needs to
be an integer fraction of 90 deg.
target_file: str
name of the file in which to store downloaded data locally
chunks: dict
cds_client: handle to CDS client (if none is provided, then it is created)
Returns
---------
CDS data in an xarray format
"""
if variable == "pvcompare":
variable = ["fdir", "ssrd", "2t", "10u", "10v", "tcwv"]
elif variable == "pvlib":
variable = ["fdir", "ssrd", "2t", "10u", "10v"]
return get_cds_data_from_datespan_and_position(**locals())
[docs]def weather_df_from_era5(era5_netcdf_filename, lib, start=None, end=None):
"""
Gets ERA5 weather data from netcdf file and converts it to a pandas
dataframe as required by the spcified lib.
Parameters
-----------
era5_netcdf_filename : str
Filename including path of netcdf file containing ERA5 weather data
for specified time span and area.
start : None or anything `pandas.to_datetime` can convert to a timestamp
Get weather data starting from this date. Defaults to None in which
case start is set to first time step in the dataset.
end : None or anything `pandas.to_datetime` can convert to a timestamp
Get weather data upto this date.
Defaults to None in which case the end date is set to the last time
step in the dataset.
area : shapely compatible geometry object (i.e. Polygon, Multipolygon, etc...) or list(float) or list(tuple)
Area specifies for which geographic area to return weather data. Area
can either be a single location or an area.
In case you want data for a single location provide a list in the
form [lon, lat].
If you want data for an area you can provide a shape of this area or
specify a rectangular area giving a list of the
form [(lon west, lon east), (lat south, lat north)].
Returns
-------
:pandas:`pandas.DataFrame<frame>`
Dataframe with ERA5 weather data in format required by the lib. In
case a single location is provided in parameter `area` index of the
dataframe is a datetime index. Otherwise the index is a multiindex
with time, latitude and longitude levels.
"""
ds = xr.open_dataset(era5_netcdf_filename)
if lib == "pvcompare":
df = format_pvcompare(ds)
else:
raise ValueError(
"Unknown value for `lib`. "
"It must be either 'pvcopare' or 'windpowerlib'."
)
# drop latitude and longitude from index in case a single location
# is given in parameter `area`
if start is None:
start = df.index[0]
if end is None:
end = df.index[-1]
return df[start:end]