diff --git a/docs/sphinx/source/whatsnew/v0.15.2.rst b/docs/sphinx/source/whatsnew/v0.15.2.rst index 94cda592f9..513afcc96c 100644 --- a/docs/sphinx/source/whatsnew/v0.15.2.rst +++ b/docs/sphinx/source/whatsnew/v0.15.2.rst @@ -40,13 +40,18 @@ Bug fixes Enhancements ~~~~~~~~~~~~ +* Add the ``front_side_fraction`` parameter to + :py:func:`pvlib.snow.loss_townsend` to support Townsend snow-loss + workflows for bifacial systems. (:issue:`2755`, :pull:`2756`) +* Add ``dataset`` parameter to :py:func:`~pvlib.iotools.get_era5` + allowing for choosing between ERA5 and ERA5-Land datasets. + (pull:`2780`) * Add the following parameters to :py:func:`~pvlib.iotools.get_nasa_power` when ``map_variables=True``: ``temp_dew``, ``precipitable_water``, ``relative_humidity``, ``ghi_extra``, ``dhi_clear``, ``longwave_down``, and ``albedo``. (:issue:`2731`, :pull:`2753`, :pull:`2762`) - Documentation ~~~~~~~~~~~~~ * Clarifies that :py:func:`pvlib.soiling.hsu` has an implicit minimum diff --git a/pvlib/iotools/era5.py b/pvlib/iotools/era5.py index 525848bb27..c2a3198d35 100644 --- a/pvlib/iotools/era5.py +++ b/pvlib/iotools/era5.py @@ -58,6 +58,7 @@ def _m_to_cm(m): def get_era5(latitude, longitude, start, end, variables, api_key, + dataset="reanalysis-era5-single-levels-timeseries", map_variables=True, timeout=60, url='https://cds.climate.copernicus.eu/api/retrieve/v1/'): """ @@ -65,8 +66,9 @@ def get_era5(latitude, longitude, start, end, variables, api_key, A CDS API key is needed to access this API. Register for one at [1]_. - This API [2]_ provides a subset of the full ERA5 dataset. See [3]_ for - the available variables. Data are available on a 0.25° x 0.25° grid. + This API [2]_ provides a subset of parameters of the full ERA5 datasets, + see [3]_ for available variables. A comparison of ERA5 and ERA5-land is + available in [4]_. Parameters ---------- @@ -84,6 +86,10 @@ def get_era5(latitude, longitude, start, end, variables, api_key, See [1]_ for additional options. api_key : str ECMWF CDS API key. + dataset : str, default ``"reanalysis-era5-single-levels-timeseries"`` + The dataset to query. May be either + ``"reanalysis-era5-single-levels-timeseries"`` or + ``"reanalysis-era5-land-timeseries"``. See [4]_ for details. map_variables : bool, default True When true, renames columns of the DataFrame to pvlib variable names where applicable. Also converts units of some variables. See variable @@ -111,6 +117,7 @@ def get_era5(latitude, longitude, start, end, variables, api_key, .. [1] https://cds.climate.copernicus.eu/ .. [2] https://cds.climate.copernicus.eu/datasets/reanalysis-era5-single-levels-timeseries?tab=overview .. [3] https://confluence.ecmwf.int/pages/viewpage.action?pageId=505390919 + .. [4] https://confluence.ecmwf.int/display/CKB/The+family+of+ERA5+datasets """ # noqa: E501 def _to_utc_dt_notz(dt): @@ -137,7 +144,7 @@ def _to_utc_dt_notz(dt): "data_format": "csv" } } - slug = "processes/reanalysis-era5-single-levels-timeseries/execution" + slug = f"processes/{dataset}/execution" response = requests.post(url + slug, json=params, headers=headers, timeout=timeout) submission_response = response.json() diff --git a/tests/iotools/test_era5.py b/tests/iotools/test_era5.py index 452097c83c..532b38f9c3 100644 --- a/tests/iotools/test_era5.py +++ b/tests/iotools/test_era5.py @@ -3,6 +3,7 @@ """ import pandas as pd +import numpy as np import pytest import pvlib import requests @@ -43,11 +44,22 @@ def expected(): def test_get_era5(params, expected): df, meta = pvlib.iotools.get_era5(**params) pd.testing.assert_frame_equal(df, expected, check_freq=False, atol=0.1) - assert meta['longitude'] == -80.0 - assert meta['latitude'] == 40.0 + assert np.isclose(meta['longitude'], -80.0) + assert np.isclose(meta['latitude'], 40.0) assert isinstance(meta['jobID'], str) +@requires_ecmwf_credentials +@pytest.mark.remote_data +@pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY) +def test_get_era5_land(params, expected): + params['dataset'] = "reanalysis-era5-land-timeseries" + df, meta = pvlib.iotools.get_era5(**params) + assert np.isclose(meta['longitude'], -80.0) + assert np.isclose(meta['latitude'], 40.0) + assert pd.testing.assert_index_equal(df.index, expected.index) + + @requires_ecmwf_credentials @pytest.mark.remote_data @pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY)