From 0dda0e45399769d95ecee41ebc3b126d994761bd Mon Sep 17 00:00:00 2001 From: "Adam R. Jensen" <39184289+AdamRJensen@users.noreply.github.com> Date: Sat, 10 Feb 2024 14:35:12 +0100 Subject: [PATCH 01/17] Initial commit --- docs/sphinx/source/reference/iotools.rst | 1 + docs/sphinx/source/whatsnew/v0.10.4.rst | 3 +- pvlib/iotools/__init__.py | 1 + pvlib/iotools/solargis.py | 162 +++++++++++++++++++++++ 4 files changed, 166 insertions(+), 1 deletion(-) create mode 100644 pvlib/iotools/solargis.py diff --git a/docs/sphinx/source/reference/iotools.rst b/docs/sphinx/source/reference/iotools.rst index cf6fbf4ac4..9e2c3bcd0f 100644 --- a/docs/sphinx/source/reference/iotools.rst +++ b/docs/sphinx/source/reference/iotools.rst @@ -52,6 +52,7 @@ of sources and file formats relevant to solar energy modeling. iotools.get_solcast_historic iotools.get_solcast_forecast iotools.get_solcast_live + iotools.get_solargis A :py:class:`~pvlib.location.Location` object may be created from metadata diff --git a/docs/sphinx/source/whatsnew/v0.10.4.rst b/docs/sphinx/source/whatsnew/v0.10.4.rst index 3cab3fc8ad..be97946a6d 100644 --- a/docs/sphinx/source/whatsnew/v0.10.4.rst +++ b/docs/sphinx/source/whatsnew/v0.10.4.rst @@ -8,7 +8,8 @@ v0.10.4 (Anticipated March, 2024) Enhancements ~~~~~~~~~~~~ * Added the Huld PV model used by PVGIS (:pull:`1940`) - +* Add :py:func:`pvlib.iotools.get_solargis` for retrieving Solargis + irradiance data. (:pull:`1969`) Bug fixes ~~~~~~~~~ diff --git a/pvlib/iotools/__init__.py b/pvlib/iotools/__init__.py index 2ec1753eb9..8b512019af 100644 --- a/pvlib/iotools/__init__.py +++ b/pvlib/iotools/__init__.py @@ -33,3 +33,4 @@ from pvlib.iotools.solcast import get_solcast_live # noqa: F401 from pvlib.iotools.solcast import get_solcast_historic # noqa: F401 from pvlib.iotools.solcast import get_solcast_tmy # noqa: F401 +from pvlib.iotools.solargis import get_solargis # noqa: F401 diff --git a/pvlib/iotools/solargis.py b/pvlib/iotools/solargis.py new file mode 100644 index 0000000000..9a3ee6fa58 --- /dev/null +++ b/pvlib/iotools/solargis.py @@ -0,0 +1,162 @@ +"""Functions to retrieve and parse irradiance data from Solargis.""" + +import pandas as pd +import requests +import io + +URL = 'https://solargis.info/ws/rest/datadelivery/request?' + +VARIABLE_MAP = { + 'GHI': 'ghi', + 'GHI_C': 'ghi_clear', # this is stated in documentation + 'GHIc': 'ghi_clear', # this is used in practice + 'DNI': 'dni', + 'DNI_C': 'dni_clear', + 'DNIc': 'dni_clear', + 'DIF': 'dhi', + 'GTI': 'poa_global', + 'GTI_C': 'poa_global_clear', + 'GTIc': 'poa_global_clear', + 'SE': 'solar_elevation', + 'SA': 'solar_azimuth', + 'TEMP': 'temp_air', + 'TD': 'temp_dew', + 'AP': 'pressure', + 'RH': 'relative_humidity', + 'WS': 'wind_speed', + 'WD': 'wind_direction', + 'INC': 'aoi', # angle of incidence of direct irradiance + 'PWAT': 'precipitable_water', # [kg/m2] + } + +METADATA_FIELDS = [ + 'issued', 'site name', 'latitude', 'longitude', 'elevation', + 'summarization type', 'summarization period' +] + + +def get_solargis(latitude, longitude, start, end, variables, summarization, + api_key, timestamp_type='center', tz='GMT+00', + terrain_shading=True, url=URL, map_variables=True, + timeout=30): + """ + Retrieve irradiance time series data from Solargis. + + The Solargis [1]_ API is described in [2]_. + + Parameters + ---------- + latitude: float + In decimal degrees, between -90 and 90, north is positive (ISO 19115) + longitude: float + In decimal degrees, between -180 and 180, east is positive (ISO 19115) + start : datetime-like + Start date of time series. Assumes UTC. + end : datetime-like + End date of time series. Assumes UTC. + variables : list + List of variables to request, see [2]_ for options. + summarization : str, {'MIN_5', 'MIN_10', 'MIN_15', 'MIN_30', 'HOURLY', 'DAILY', 'MONTHLY', 'YEARLY'} + DESCRIPTION. + api_key : str + API key. + timestamp_type : {'start', 'center', 'end'}, default: 'center' + How to label time intervals in the return data. + tz : str, default : 'GMT+00' + Timezone of `start` and `end` in the format "GMT+hh" or "GMT-hh". + terrain_shading : boolean, default: True + Whether to account for horizon shading. + url : str, default : :const:`pvlib.iotools.solargis.URL` + Base url of Solargis API. + map_variables : boolean, default: True + When true, renames columns of the Dataframe to pvlib variable names + where applicable. See variable :const:`VARIABLE_MAP`. + timeout : int or float, default: 30 + Time in seconds to wait for server response before timeout + + Returns + ------- + data : DataFrame + DataFrame containing time series data. + meta : dict + Dictionary containing metadata. + + Notes + ----- + Each XMl request is limited to retrieving 31 days of data. + + The variable units depends on the time frequency, e.g., the unit for + sub-hourly irradiance data is W/m^2, for hourly data it is Wh/m^2, and for + daily data it is kWh/m^2. + + Raises + ------ + HTTPError + If an incorrect request is made. + + References + ---------- + .. [1] `Solargis `_ + .. [2] `Solargis API User Guide + `_ + """ # noqa: E501 + # Use pd.to_datetime so that strings (e.g. '2021-01-01') are accepted + start = pd.to_datetime(start) + end = pd.to_datetime(end) + + headers = {'Content-Type': 'application/xml'} + + # Solargis recommends creating a unique site_id for each location request. + # The site_id does not impact the data retrieval and is used for debugging. + site_id = f"latitude_{latitude}_longitude_{longitude}" + + request_xml = f''' + + + + {timestamp_type.upper()} + {tz} + + ''' + response = requests.post(url + "key=" + api_key, headers=headers, + data=request_xml.encode('utf8'), timeout=timeout) + + if response.ok is False: + raise requests.HTTPError(response.json()) + + # Parse metadata + header = pd.read_xml(io.StringIO(response.text)) + meta_lines = header['metadata'].iloc[0].split('#') + meta_lines = [line.strip() for line in meta_lines] + meta = {} + for line in meta_lines: + if ':' in line: + key = line.split(':')[0].lower() + if key in METADATA_FIELDS: + meta[key] = ':'.join(line.split(':')[1:]) + meta['latitude'] = float(meta['latitude']) + meta['longitude'] = float(meta['longitude']) + meta['altitude'] = float(meta.pop('elevation').replace('m a.s.l.', '')) + + # Parse data + data = pd.read_xml(io.StringIO(response.text), xpath='.//doc:row', + namespaces={'doc': 'http://geomodel.eu/schema/ws/data'}) + data.index = pd.to_datetime(data['dateTime']) + data = data['values'].str.split(' ', expand=True) + data = data.astype(float) + data.columns = header['columns'].iloc[0].split() + + if map_variables: + data = data.rename(columns=VARIABLE_MAP) + + data = data.replace(-9, pd.NA) + + return data, meta From 9d1151ca5e89b17955d2be8ae56d99e9a97b6e36 Mon Sep 17 00:00:00 2001 From: "Adam R. Jensen" <39184289+AdamRJensen@users.noreply.github.com> Date: Sat, 10 Feb 2024 14:41:52 +0100 Subject: [PATCH 02/17] Linting --- pvlib/iotools/solargis.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pvlib/iotools/solargis.py b/pvlib/iotools/solargis.py index 9a3ee6fa58..c43ad7f4a5 100644 --- a/pvlib/iotools/solargis.py +++ b/pvlib/iotools/solargis.py @@ -27,7 +27,7 @@ 'WD': 'wind_direction', 'INC': 'aoi', # angle of incidence of direct irradiance 'PWAT': 'precipitable_water', # [kg/m2] - } +} METADATA_FIELDS = [ 'issued', 'site name', 'latitude', 'longitude', 'elevation', From 3a46cfbd533a250fa456e506864e944037e81429 Mon Sep 17 00:00:00 2001 From: "Adam R. Jensen" <39184289+AdamRJensen@users.noreply.github.com> Date: Sat, 10 Feb 2024 14:44:28 +0100 Subject: [PATCH 03/17] Include v0.10.4 whatsnew --- docs/sphinx/source/whatsnew.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/sphinx/source/whatsnew.rst b/docs/sphinx/source/whatsnew.rst index c614c0de98..7fad810f8e 100644 --- a/docs/sphinx/source/whatsnew.rst +++ b/docs/sphinx/source/whatsnew.rst @@ -6,6 +6,7 @@ What's New These are new features and improvements of note in each release. +.. include:: whatsnew/v0.10.4.rst .. include:: whatsnew/v0.10.3.rst .. include:: whatsnew/v0.10.2.rst .. include:: whatsnew/v0.10.1.rst From ab5a903f06d3e64ab9b7d1f53b3239fbb64c89ff Mon Sep 17 00:00:00 2001 From: "Adam R. Jensen" <39184289+AdamRJensen@users.noreply.github.com> Date: Sat, 10 Feb 2024 14:50:09 +0100 Subject: [PATCH 04/17] Add example --- pvlib/iotools/solargis.py | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/pvlib/iotools/solargis.py b/pvlib/iotools/solargis.py index c43ad7f4a5..87e4d87ec3 100644 --- a/pvlib/iotools/solargis.py +++ b/pvlib/iotools/solargis.py @@ -35,8 +35,8 @@ ] -def get_solargis(latitude, longitude, start, end, variables, summarization, - api_key, timestamp_type='center', tz='GMT+00', +def get_solargis(latitude, longitude, start, end, variables, api_key, + summarization, timestamp_type='center', tz='GMT+00', terrain_shading=True, url=URL, map_variables=True, timeout=30): """ @@ -51,17 +51,17 @@ def get_solargis(latitude, longitude, start, end, variables, summarization, longitude: float In decimal degrees, between -180 and 180, east is positive (ISO 19115) start : datetime-like - Start date of time series. Assumes UTC. + Start date of time series. end : datetime-like - End date of time series. Assumes UTC. + End date of time series. variables : list List of variables to request, see [2]_ for options. - summarization : str, {'MIN_5', 'MIN_10', 'MIN_15', 'MIN_30', 'HOURLY', 'DAILY', 'MONTHLY', 'YEARLY'} - DESCRIPTION. api_key : str API key. + summarization : str, {'MIN_5', 'MIN_10', 'MIN_15', 'MIN_30', 'HOURLY', 'DAILY', 'MONTHLY', 'YEARLY'} + DESCRIPTION. timestamp_type : {'start', 'center', 'end'}, default: 'center' - How to label time intervals in the return data. + Labeling of time stamps of the return data. tz : str, default : 'GMT+00' Timezone of `start` and `end` in the format "GMT+hh" or "GMT-hh". terrain_shading : boolean, default: True @@ -89,6 +89,14 @@ def get_solargis(latitude, longitude, start, end, variables, summarization, sub-hourly irradiance data is W/m^2, for hourly data it is Wh/m^2, and for daily data it is kWh/m^2. + Examples + -------- + >>> # Retrieve two days of irradiance data from Solargis + >>> data, neta = response = get_solargis( + >>> latitude=48.61259, longitude=20.827079, + >>> start='2022-01-01', end='2022-01-02', + >>> variables=['GHI', 'DNI'], summarization='MIN_5', api_key='demo') + Raises ------ HTTPError From 0d5835cb76866ebbd0977696f48a87b9d1d6b604 Mon Sep 17 00:00:00 2001 From: "Adam R. Jensen" <39184289+AdamRJensen@users.noreply.github.com> Date: Sat, 10 Feb 2024 14:51:29 +0100 Subject: [PATCH 05/17] Update raises message --- pvlib/iotools/solargis.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pvlib/iotools/solargis.py b/pvlib/iotools/solargis.py index 87e4d87ec3..c01670ef7f 100644 --- a/pvlib/iotools/solargis.py +++ b/pvlib/iotools/solargis.py @@ -99,8 +99,8 @@ def get_solargis(latitude, longitude, start, end, variables, api_key, Raises ------ - HTTPError - If an incorrect request is made. + requests.HTTPError + A message from the Solargis server if the request is rejected References ---------- From 12538baf0b29524ba9640b5564ef0e0c34fe9c09 Mon Sep 17 00:00:00 2001 From: "Adam R. Jensen" <39184289+AdamRJensen@users.noreply.github.com> Date: Sat, 10 Feb 2024 15:03:45 +0100 Subject: [PATCH 06/17] Update doc section order --- pvlib/iotools/solargis.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/pvlib/iotools/solargis.py b/pvlib/iotools/solargis.py index c01670ef7f..bfe2ffae1b 100644 --- a/pvlib/iotools/solargis.py +++ b/pvlib/iotools/solargis.py @@ -81,6 +81,11 @@ def get_solargis(latitude, longitude, start, end, variables, api_key, meta : dict Dictionary containing metadata. + Raises + ------ + requests.HTTPError + A message from the Solargis server if the request is rejected + Notes ----- Each XMl request is limited to retrieving 31 days of data. @@ -89,6 +94,12 @@ def get_solargis(latitude, longitude, start, end, variables, api_key, sub-hourly irradiance data is W/m^2, for hourly data it is Wh/m^2, and for daily data it is kWh/m^2. + References + ---------- + .. [1] `Solargis `_ + .. [2] `Solargis API User Guide + `_ + Examples -------- >>> # Retrieve two days of irradiance data from Solargis @@ -96,17 +107,6 @@ def get_solargis(latitude, longitude, start, end, variables, api_key, >>> latitude=48.61259, longitude=20.827079, >>> start='2022-01-01', end='2022-01-02', >>> variables=['GHI', 'DNI'], summarization='MIN_5', api_key='demo') - - Raises - ------ - requests.HTTPError - A message from the Solargis server if the request is rejected - - References - ---------- - .. [1] `Solargis `_ - .. [2] `Solargis API User Guide - `_ """ # noqa: E501 # Use pd.to_datetime so that strings (e.g. '2021-01-01') are accepted start = pd.to_datetime(start) From 76edf44b55399a5d824502dabd4d8d760bcdb75a Mon Sep 17 00:00:00 2001 From: "Adam R. Jensen" <39184289+AdamRJensen@users.noreply.github.com> Date: Mon, 12 Feb 2024 22:08:31 +0100 Subject: [PATCH 07/17] Set parser to etree --- pvlib/iotools/solargis.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pvlib/iotools/solargis.py b/pvlib/iotools/solargis.py index bfe2ffae1b..dde51c0559 100644 --- a/pvlib/iotools/solargis.py +++ b/pvlib/iotools/solargis.py @@ -103,7 +103,7 @@ def get_solargis(latitude, longitude, start, end, variables, api_key, Examples -------- >>> # Retrieve two days of irradiance data from Solargis - >>> data, neta = response = get_solargis( + >>> data, neta = response = pvlib.iotools.get_solargis( >>> latitude=48.61259, longitude=20.827079, >>> start='2022-01-01', end='2022-01-02', >>> variables=['GHI', 'DNI'], summarization='MIN_5', api_key='demo') @@ -141,7 +141,7 @@ def get_solargis(latitude, longitude, start, end, variables, api_key, raise requests.HTTPError(response.json()) # Parse metadata - header = pd.read_xml(io.StringIO(response.text)) + header = pd.read_xml(io.StringIO(response.text), parser='etree') meta_lines = header['metadata'].iloc[0].split('#') meta_lines = [line.strip() for line in meta_lines] meta = {} @@ -156,7 +156,8 @@ def get_solargis(latitude, longitude, start, end, variables, api_key, # Parse data data = pd.read_xml(io.StringIO(response.text), xpath='.//doc:row', - namespaces={'doc': 'http://geomodel.eu/schema/ws/data'}) + namespaces={'doc': 'http://geomodel.eu/schema/ws/data'}, + parser='etree') data.index = pd.to_datetime(data['dateTime']) data = data['values'].str.split(' ', expand=True) data = data.astype(float) From a4c48b6ec5bf1c479c519c3250b3443fc4fd719c Mon Sep 17 00:00:00 2001 From: "Adam R. Jensen" <39184289+AdamRJensen@users.noreply.github.com> Date: Mon, 12 Feb 2024 22:40:56 +0100 Subject: [PATCH 08/17] Add tests --- pvlib/iotools/solargis.py | 5 +- pvlib/tests/iotools/test_solargis.py | 68 ++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 pvlib/tests/iotools/test_solargis.py diff --git a/pvlib/iotools/solargis.py b/pvlib/iotools/solargis.py index dde51c0559..12af063430 100644 --- a/pvlib/iotools/solargis.py +++ b/pvlib/iotools/solargis.py @@ -103,7 +103,7 @@ def get_solargis(latitude, longitude, start, end, variables, api_key, Examples -------- >>> # Retrieve two days of irradiance data from Solargis - >>> data, neta = response = pvlib.iotools.get_solargis( + >>> data, meta = response = pvlib.iotools.get_solargis( >>> latitude=48.61259, longitude=20.827079, >>> start='2022-01-01', end='2022-01-02', >>> variables=['GHI', 'DNI'], summarization='MIN_5', api_key='demo') @@ -159,7 +159,8 @@ def get_solargis(latitude, longitude, start, end, variables, api_key, namespaces={'doc': 'http://geomodel.eu/schema/ws/data'}, parser='etree') data.index = pd.to_datetime(data['dateTime']) - data = data['values'].str.split(' ', expand=True) + # when requesting one variable, it is necessary to convert dataframe to str + data = data['values'].astype(str).str.split(' ', expand=True) data = data.astype(float) data.columns = header['columns'].iloc[0].split() diff --git a/pvlib/tests/iotools/test_solargis.py b/pvlib/tests/iotools/test_solargis.py new file mode 100644 index 0000000000..f60a1b2c89 --- /dev/null +++ b/pvlib/tests/iotools/test_solargis.py @@ -0,0 +1,68 @@ +import pandas as pd +import pytest +import pvlib +import requests +from ..conftest import (RERUNS, RERUNS_DELAY, assert_frame_equal, + assert_index_equal) + + +@pytest.fixture +def hourly_index(): + hourly_index = pd.date_range(start='2022-01-01 00:30+01:00', freq='60min', + periods=24, name='dateTime') + hourly_index.freq = None + return hourly_index + + +@pytest.fixture +def hourly_index_start_utc(): + hourly_index_left_utc = pd.date_range( + start='2023-01-01 00:00+00:00', freq='30min', periods=24*2, + name='dateTime') + hourly_index_left_utc.freq = None + return hourly_index_left_utc + + +@pytest.fixture +def hourly_dataframe(hourly_index): + ghi = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 5.0, 73.0, 152.0, 141.0, 105.0, + 62.0, 65.0, 62.0, 11.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] + dni = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.0, 233.0, 301.0, 136.0, 32.0, + 0.0, 3.0, 77.0, 5.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] + return pd.DataFrame(data={'ghi': ghi, 'dni': dni}, index=hourly_index) + + +@pytest.mark.remote_data +@pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY) +def test_get_solargis(hourly_dataframe): + data, meta = pvlib.iotools.get_solargis( + latitude=48.61259, longitude=20.827079, + start='2022-01-01', end='2022-01-01', + tz='GMT+01', variables=['GHI', 'DNI'], + summarization='HOURLY', api_key='demo') + assert_frame_equal(data, hourly_dataframe) + + +@pytest.mark.remote_data +@pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY) +def test_get_solargis_utc_start_timestamp(hourly_index_start_utc): + data, meta = pvlib.iotools.get_solargis( + latitude=48.61259, longitude=20.827079, + start='2023-01-01', end='2023-01-01', + variables=['GTI'], + timestamp_type='start', + summarization='MIN_30', + map_variables=False, api_key='demo') + assert 'GTI' in data.columns # assert that variables aren't mapped + assert_index_equal(data.index, hourly_index_start_utc) + + +@pytest.mark.remote_data +@pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY) +def test_get_solargis_http_error(): + # Test if HTTPError is raised if date outside range is specified + with pytest.raises(requests.HTTPError, match="data coverage"): + _, _ = pvlib.iotools.get_solargis( + latitude=48.61259, longitude=20.827079, + start='1920-01-01', end='1920-01-01', # date outside range + variables=['GHI', 'DNI'], summarization='HOURLY', api_key='demo') From c4a9e8e7f59295d2ec526fbffd90bc5e2023654d Mon Sep 17 00:00:00 2001 From: "Adam R. Jensen" <39184289+AdamRJensen@users.noreply.github.com> Date: Mon, 12 Feb 2024 23:06:41 +0100 Subject: [PATCH 09/17] Add test skip for pandas<1.3.0 --- pvlib/iotools/solargis.py | 2 +- pvlib/tests/iotools/test_solargis.py | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/pvlib/iotools/solargis.py b/pvlib/iotools/solargis.py index 12af063430..9894157da9 100644 --- a/pvlib/iotools/solargis.py +++ b/pvlib/iotools/solargis.py @@ -88,7 +88,7 @@ def get_solargis(latitude, longitude, start, end, variables, api_key, Notes ----- - Each XMl request is limited to retrieving 31 days of data. + Each XML request is limited to retrieving 31 days of data. The variable units depends on the time frequency, e.g., the unit for sub-hourly irradiance data is W/m^2, for hourly data it is Wh/m^2, and for diff --git a/pvlib/tests/iotools/test_solargis.py b/pvlib/tests/iotools/test_solargis.py index f60a1b2c89..27aaacad48 100644 --- a/pvlib/tests/iotools/test_solargis.py +++ b/pvlib/tests/iotools/test_solargis.py @@ -32,6 +32,8 @@ def hourly_dataframe(hourly_index): return pd.DataFrame(data={'ghi': ghi, 'dni': dni}, index=hourly_index) +@pytest.mark.skipif(pd.__version__ < '1.3.0', + reason='pd.read_xml is new as of 1.3.0') @pytest.mark.remote_data @pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY) def test_get_solargis(hourly_dataframe): @@ -43,6 +45,8 @@ def test_get_solargis(hourly_dataframe): assert_frame_equal(data, hourly_dataframe) +@pytest.mark.skipif(pd.__version__ < '1.3.0', + reason='pd.read_xml is new as of 1.3.0') @pytest.mark.remote_data @pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY) def test_get_solargis_utc_start_timestamp(hourly_index_start_utc): @@ -57,6 +61,8 @@ def test_get_solargis_utc_start_timestamp(hourly_index_start_utc): assert_index_equal(data.index, hourly_index_start_utc) +@pytest.mark.skipif(pd.__version__ < '1.3.0', + reason='pd.read_xml is new as of 1.3.0') @pytest.mark.remote_data @pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY) def test_get_solargis_http_error(): From 6c034d1feca1e6eebeeaaeb62f6a5af8332d9f37 Mon Sep 17 00:00:00 2001 From: "Adam R. Jensen" <39184289+AdamRJensen@users.noreply.github.com> Date: Mon, 12 Feb 2024 23:59:51 +0100 Subject: [PATCH 10/17] Fix nan replacement and add variable conversion --- pvlib/iotools/solargis.py | 86 +++++++++++++++++++++++++++------------ 1 file changed, 59 insertions(+), 27 deletions(-) diff --git a/pvlib/iotools/solargis.py b/pvlib/iotools/solargis.py index 9894157da9..fc4dadaea3 100644 --- a/pvlib/iotools/solargis.py +++ b/pvlib/iotools/solargis.py @@ -2,32 +2,48 @@ import pandas as pd import requests +from dataclasses import dataclass import io URL = 'https://solargis.info/ws/rest/datadelivery/request?' -VARIABLE_MAP = { - 'GHI': 'ghi', - 'GHI_C': 'ghi_clear', # this is stated in documentation - 'GHIc': 'ghi_clear', # this is used in practice - 'DNI': 'dni', - 'DNI_C': 'dni_clear', - 'DNIc': 'dni_clear', - 'DIF': 'dhi', - 'GTI': 'poa_global', - 'GTI_C': 'poa_global_clear', - 'GTIc': 'poa_global_clear', - 'SE': 'solar_elevation', - 'SA': 'solar_azimuth', - 'TEMP': 'temp_air', - 'TD': 'temp_dew', - 'AP': 'pressure', - 'RH': 'relative_humidity', - 'WS': 'wind_speed', - 'WD': 'wind_direction', - 'INC': 'aoi', # angle of incidence of direct irradiance - 'PWAT': 'precipitable_water', # [kg/m2] -} + +@dataclass +class ParameterMap: + solargis_name: str + pvlib_name: str + conversion: callable = lambda x: x + + +# define the conventions between Solargis and pvlib nomenclature and units +VARIABLE_MAP = [ + # Irradiance (unit varies based on time resolution) + ParameterMap('GHI', 'ghi'), + ParameterMap('GHI_C', 'ghi_clear'), # this is stated in documentation + ParameterMap('GHIc', 'ghi_clear'), # this is used in practice + ParameterMap('DNI', 'dni'), + ParameterMap('DNI_C', 'dni_clear'), + ParameterMap('DNIc', 'dni_clear'), + ParameterMap('DIF', 'dhi'), + ParameterMap('GTI', 'poa_global'), + ParameterMap('GTI_C', 'poa_global_clear'), + ParameterMap('GTIc', 'poa_global_clear'), + # Solar position + ParameterMap('SE', 'solar_elevation'), + # SA -> solar_azimuth (degrees) (different convention) + ParameterMap("SA", "solar_azimuth", lambda x: x + 180), + # Weather / atmospheric parameters + ParameterMap('TEMP', 'temp_air'), + ParameterMap('TD', 'temp_dew'), + # surface_pressure (hPa) -> pressure (Pa) + ParameterMap('AP', 'pressure', lambda x: x*100), + ParameterMap('RH', 'relative_humidity'), + ParameterMap('WS', 'wind_speed'), + ParameterMap('WD', 'wind_direction'), + ParameterMap('INC', 'aoi'), # angle of incidence of direct irradiance + # precipitable_water (kg/m2) -> precipitable_water (cm) + ParameterMap('PWAT', 'precipitable_water', lambda x: x*10), +] METADATA_FIELDS = [ 'issued', 'site name', 'latitude', 'longitude', 'elevation', @@ -35,6 +51,11 @@ ] +# Variables that use "-9" as nan values +NA_9_COLUMNS = ['GHI', 'GHIc', 'DNI', 'DNIc', 'DIF', 'GTI', 'GIc', 'KT', 'PAR', + 'PREC', 'PWAT', 'SDWE', 'SFWE'] + + def get_solargis(latitude, longitude, start, end, variables, api_key, summarization, timestamp_type='center', tz='GMT+00', terrain_shading=True, url=URL, map_variables=True, @@ -91,8 +112,8 @@ def get_solargis(latitude, longitude, start, end, variables, api_key, Each XML request is limited to retrieving 31 days of data. The variable units depends on the time frequency, e.g., the unit for - sub-hourly irradiance data is W/m^2, for hourly data it is Wh/m^2, and for - daily data it is kWh/m^2. + sub-hourly irradiance data is :math:`W/m^2`, for hourly data it is + :math:`Wh/m^2`, and for daily data it is :math:`kWh/m^2`. References ---------- @@ -164,9 +185,20 @@ def get_solargis(latitude, longitude, start, end, variables, api_key, data = data.astype(float) data.columns = header['columns'].iloc[0].split() - if map_variables: - data = data.rename(columns=VARIABLE_MAP) + # Replace "-9" with nan values for specific columns + for variable in data.columns: + if variable in NA_9_COLUMNS: + data[variable] = data[variable].replace(-9, pd.NA) - data = data.replace(-9, pd.NA) + # rename and convert variables + if map_variables: + for variable in VARIABLE_MAP: + if variable.solargis_name in data.columns: + data.rename( + columns={variable.solargis_name: variable.pvlib_name}, + inplace=True + ) + data[variable.pvlib_name] = data[ + variable.pvlib_name].apply(variable.conversion) return data, meta From 4a48ae1315ac36a2f61fc6fc1706648f21f3dd18 Mon Sep 17 00:00:00 2001 From: "Adam R. Jensen" <39184289+AdamRJensen@users.noreply.github.com> Date: Tue, 13 Feb 2024 17:24:41 +0100 Subject: [PATCH 11/17] Add time_resolution conversion --- pvlib/iotools/solargis.py | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/pvlib/iotools/solargis.py b/pvlib/iotools/solargis.py index fc4dadaea3..33c955ba6b 100644 --- a/pvlib/iotools/solargis.py +++ b/pvlib/iotools/solargis.py @@ -5,7 +5,14 @@ from dataclasses import dataclass import io -URL = 'https://solargis.info/ws/rest/datadelivery/request?' +URL = 'https://solargis.info/ws/rest/datadelivery/request' + + +TIME_RESOLUTION_MAP = { + 5: 'MIN_5', 10: 'MIN_10', 15: 'MIN_15', 30: 'MIN_30', 60: 'HOURLY', + 'PT05M': 'MIN_5', 'PT5M': 'MIN_5', 'PT10M': 'MIN_10', 'PT15M': 'MIN_15', + 'PT30': 'MIN_30', 'PT60M': 'HOURLY', 'PT1H': 'HOURLY', 'P1D': 'DAILY', + 'P1M': 'MONTHLY', 'P1Y': 'YEARLY'} @dataclass @@ -42,7 +49,7 @@ class ParameterMap: ParameterMap('WD', 'wind_direction'), ParameterMap('INC', 'aoi'), # angle of incidence of direct irradiance # precipitable_water (kg/m2) -> precipitable_water (cm) - ParameterMap('PWAT', 'precipitable_water', lambda x: x*10), + ParameterMap('PWAT', 'precipitable_water', lambda x: x/10), ] METADATA_FIELDS = [ @@ -57,7 +64,7 @@ class ParameterMap: def get_solargis(latitude, longitude, start, end, variables, api_key, - summarization, timestamp_type='center', tz='GMT+00', + time_resolution, timestamp_type='center', tz='GMT+00', terrain_shading=True, url=URL, map_variables=True, timeout=30): """ @@ -79,8 +86,8 @@ def get_solargis(latitude, longitude, start, end, variables, api_key, List of variables to request, see [2]_ for options. api_key : str API key. - summarization : str, {'MIN_5', 'MIN_10', 'MIN_15', 'MIN_30', 'HOURLY', 'DAILY', 'MONTHLY', 'YEARLY'} - DESCRIPTION. + time_resolution : str, {'PT05M', 'PT10M', 'PT15M', 'PT30', 'PT1H', 'P1D', 'P1M', 'P1Y'} + Time frequency in the time series data. timestamp_type : {'start', 'center', 'end'}, default: 'center' Labeling of time stamps of the return data. tz : str, default : 'GMT+00' @@ -127,7 +134,7 @@ def get_solargis(latitude, longitude, start, end, variables, api_key, >>> data, meta = response = pvlib.iotools.get_solargis( >>> latitude=48.61259, longitude=20.827079, >>> start='2022-01-01', end='2022-01-02', - >>> variables=['GHI', 'DNI'], summarization='MIN_5', api_key='demo') + >>> variables=['GHI', 'DNI'], time_resolution='PT05M', api_key='demo') """ # noqa: E501 # Use pd.to_datetime so that strings (e.g. '2021-01-01') are accepted start = pd.to_datetime(start) @@ -149,13 +156,14 @@ def get_solargis(latitude, longitude, start, end, variables, api_key, xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> - {timestamp_type.upper()} {tz} ''' - response = requests.post(url + "key=" + api_key, headers=headers, + response = requests.post(url + "?key=" + api_key, headers=headers, data=request_xml.encode('utf8'), timeout=timeout) if response.ok is False: From b9a1862d2277e710a734767dd84ab318f9f5d541 Mon Sep 17 00:00:00 2001 From: "Adam R. Jensen" <39184289+AdamRJensen@users.noreply.github.com> Date: Tue, 13 Feb 2024 17:24:51 +0100 Subject: [PATCH 12/17] Fix precipitable_water conversion in solcast --- pvlib/iotools/solcast.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pvlib/iotools/solcast.py b/pvlib/iotools/solcast.py index 4fcee40050..5abd9c724e 100644 --- a/pvlib/iotools/solcast.py +++ b/pvlib/iotools/solcast.py @@ -35,7 +35,7 @@ class ParameterMap: "azimuth", "solar_azimuth", lambda x: -x % 360 ), # precipitable_water (kg/m2) -> precipitable_water (cm) - ParameterMap("precipitable_water", "precipitable_water", lambda x: x*10), + ParameterMap("precipitable_water", "precipitable_water", lambda x: x/10), # zenith -> solar_zenith ParameterMap("zenith", "solar_zenith"), # clearsky From 8bce845a2d4247d3a73b3b078085430e75584a77 Mon Sep 17 00:00:00 2001 From: "Adam R. Jensen" <39184289+AdamRJensen@users.noreply.github.com> Date: Sat, 9 Mar 2024 13:52:51 +0100 Subject: [PATCH 13/17] Address reviewer comments --- docs/sphinx/source/whatsnew/v0.10.4.rst | 3 ++- pvlib/iotools/solargis.py | 4 +++- pvlib/tests/iotools/test_solargis.py | 6 ------ pyproject.toml | 2 +- 4 files changed, 6 insertions(+), 9 deletions(-) diff --git a/docs/sphinx/source/whatsnew/v0.10.4.rst b/docs/sphinx/source/whatsnew/v0.10.4.rst index 002622e0c8..39395dd76d 100644 --- a/docs/sphinx/source/whatsnew/v0.10.4.rst +++ b/docs/sphinx/source/whatsnew/v0.10.4.rst @@ -34,6 +34,7 @@ Bug fixes ``temperature_model_parameters`` are specified on the passed ``system`` instead of on its ``arrays``. (:issue:`1759`). * :py:func:`pvlib.irradiance.ghi_from_poa_driesse_2023` now correctly makes use of the ``xtol`` argument. Previously, it was ignored. (:issue:`1970`, :pull:`1971`) +* Fixed incorrect unit conversion of precipitable water used for the Solcast iotools functions. Testing ~~~~~~~ @@ -48,7 +49,7 @@ Documentation Requirements ~~~~~~~~~~~~ - +* Minimum version of pandas advanced from 0.25.0 to 1.3.0. (:pull:`1969`) Contributors ~~~~~~~~~~~~ diff --git a/pvlib/iotools/solargis.py b/pvlib/iotools/solargis.py index 33c955ba6b..1f3670defa 100644 --- a/pvlib/iotools/solargis.py +++ b/pvlib/iotools/solargis.py @@ -87,7 +87,8 @@ def get_solargis(latitude, longitude, start, end, variables, api_key, api_key : str API key. time_resolution : str, {'PT05M', 'PT10M', 'PT15M', 'PT30', 'PT1H', 'P1D', 'P1M', 'P1Y'} - Time frequency in the time series data. + Time resolution as an integer number of minutes (e.g. 5, 60) + or an ISO 8601 duration string (e.g. "PT05M", "PT60M", "P1M"). timestamp_type : {'start', 'center', 'end'}, default: 'center' Labeling of time stamps of the return data. tz : str, default : 'GMT+00' @@ -163,6 +164,7 @@ def get_solargis(latitude, longitude, start, end, variables, api_key, {tz} ''' + response = requests.post(url + "?key=" + api_key, headers=headers, data=request_xml.encode('utf8'), timeout=timeout) diff --git a/pvlib/tests/iotools/test_solargis.py b/pvlib/tests/iotools/test_solargis.py index 27aaacad48..f60a1b2c89 100644 --- a/pvlib/tests/iotools/test_solargis.py +++ b/pvlib/tests/iotools/test_solargis.py @@ -32,8 +32,6 @@ def hourly_dataframe(hourly_index): return pd.DataFrame(data={'ghi': ghi, 'dni': dni}, index=hourly_index) -@pytest.mark.skipif(pd.__version__ < '1.3.0', - reason='pd.read_xml is new as of 1.3.0') @pytest.mark.remote_data @pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY) def test_get_solargis(hourly_dataframe): @@ -45,8 +43,6 @@ def test_get_solargis(hourly_dataframe): assert_frame_equal(data, hourly_dataframe) -@pytest.mark.skipif(pd.__version__ < '1.3.0', - reason='pd.read_xml is new as of 1.3.0') @pytest.mark.remote_data @pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY) def test_get_solargis_utc_start_timestamp(hourly_index_start_utc): @@ -61,8 +57,6 @@ def test_get_solargis_utc_start_timestamp(hourly_index_start_utc): assert_index_equal(data.index, hourly_index_start_utc) -@pytest.mark.skipif(pd.__version__ < '1.3.0', - reason='pd.read_xml is new as of 1.3.0') @pytest.mark.remote_data @pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY) def test_get_solargis_http_error(): diff --git a/pyproject.toml b/pyproject.toml index 75970c9f92..030019b1f8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,7 +12,7 @@ authors = [ requires-python = ">=3.7" dependencies = [ 'numpy >= 1.16.0', - 'pandas >= 0.25.0', + 'pandas >= 1.3.0', 'pytz', 'requests', 'scipy >= 1.5.0', From 8260a1ead2a42d7ac3b5f854355834c58d6d1640 Mon Sep 17 00:00:00 2001 From: "Adam R. Jensen" <39184289+AdamRJensen@users.noreply.github.com> Date: Sat, 9 Mar 2024 14:27:17 +0100 Subject: [PATCH 14/17] Fix test issues --- pvlib/iotools/solargis.py | 4 ++-- pvlib/tests/iotools/test_solargis.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pvlib/iotools/solargis.py b/pvlib/iotools/solargis.py index 1f3670defa..375c7ed3e8 100644 --- a/pvlib/iotools/solargis.py +++ b/pvlib/iotools/solargis.py @@ -158,12 +158,12 @@ def get_solargis(latitude, longitude, start, end, variables, api_key, {timestamp_type.upper()} {tz} - ''' + ''' # noqa: E501 response = requests.post(url + "?key=" + api_key, headers=headers, data=request_xml.encode('utf8'), timeout=timeout) diff --git a/pvlib/tests/iotools/test_solargis.py b/pvlib/tests/iotools/test_solargis.py index f60a1b2c89..55882e91c5 100644 --- a/pvlib/tests/iotools/test_solargis.py +++ b/pvlib/tests/iotools/test_solargis.py @@ -39,7 +39,7 @@ def test_get_solargis(hourly_dataframe): latitude=48.61259, longitude=20.827079, start='2022-01-01', end='2022-01-01', tz='GMT+01', variables=['GHI', 'DNI'], - summarization='HOURLY', api_key='demo') + time_resolution='HOURLY', api_key='demo') assert_frame_equal(data, hourly_dataframe) @@ -51,7 +51,7 @@ def test_get_solargis_utc_start_timestamp(hourly_index_start_utc): start='2023-01-01', end='2023-01-01', variables=['GTI'], timestamp_type='start', - summarization='MIN_30', + time_resolution='MIN_30', map_variables=False, api_key='demo') assert 'GTI' in data.columns # assert that variables aren't mapped assert_index_equal(data.index, hourly_index_start_utc) @@ -65,4 +65,4 @@ def test_get_solargis_http_error(): _, _ = pvlib.iotools.get_solargis( latitude=48.61259, longitude=20.827079, start='1920-01-01', end='1920-01-01', # date outside range - variables=['GHI', 'DNI'], summarization='HOURLY', api_key='demo') + variables=['GHI', 'DNI'], time_resolution='HOURLY', api_key='demo') From 8fc8340398b8d11f6dbd2a94aa482e83b6153aea Mon Sep 17 00:00:00 2001 From: "Adam R. Jensen" <39184289+AdamRJensen@users.noreply.github.com> Date: Sat, 9 Mar 2024 14:58:46 +0100 Subject: [PATCH 15/17] Update pandas version in ci/requirements*.yml --- ci/requirements-py3.10.yml | 2 +- ci/requirements-py3.11.yml | 2 +- ci/requirements-py3.12.yml | 2 +- ci/requirements-py3.7-min.yml | 2 +- ci/requirements-py3.7.yml | 2 +- ci/requirements-py3.8.yml | 2 +- ci/requirements-py3.9.yml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ci/requirements-py3.10.yml b/ci/requirements-py3.10.yml index cc11e4cb8a..9f97f69aa5 100644 --- a/ci/requirements-py3.10.yml +++ b/ci/requirements-py3.10.yml @@ -9,7 +9,7 @@ dependencies: - h5py - numba - numpy >= 1.16.0 - - pandas >= 0.25.0 + - pandas >= 1.3.0 - pip - pytest - pytest-cov diff --git a/ci/requirements-py3.11.yml b/ci/requirements-py3.11.yml index 5bd43c6df7..0ad4447f97 100644 --- a/ci/requirements-py3.11.yml +++ b/ci/requirements-py3.11.yml @@ -9,7 +9,7 @@ dependencies: - h5py - numba - numpy >= 1.16.0 - - pandas >= 0.25.0 + - pandas >= 1.3.0 - pip - pytest - pytest-cov diff --git a/ci/requirements-py3.12.yml b/ci/requirements-py3.12.yml index 156a408f48..e81054ee06 100644 --- a/ci/requirements-py3.12.yml +++ b/ci/requirements-py3.12.yml @@ -9,7 +9,7 @@ dependencies: - h5py - numba - numpy >= 1.16.0 - - pandas >= 0.25.0 + - pandas >= 1.3.0 - pip - pytest - pytest-cov diff --git a/ci/requirements-py3.7-min.yml b/ci/requirements-py3.7-min.yml index 65dd6fa744..85995a132f 100644 --- a/ci/requirements-py3.7-min.yml +++ b/ci/requirements-py3.7-min.yml @@ -15,7 +15,7 @@ dependencies: - dataclasses - h5py==3.1.0 - numpy==1.16.0 - - pandas==0.25.0 + - pandas==1.3.0 - scipy==1.5.0 - pytest-rerunfailures # conda version is >3.6 - pytest-remotedata # conda package is 0.3.0, needs > 0.3.1 diff --git a/ci/requirements-py3.7.yml b/ci/requirements-py3.7.yml index 49da67f3de..339ea48e6e 100644 --- a/ci/requirements-py3.7.yml +++ b/ci/requirements-py3.7.yml @@ -9,7 +9,7 @@ dependencies: - h5py - numba - numpy >= 1.16.0 - - pandas >= 0.25.0 + - pandas >= 1.3.0 - pip - pytest - pytest-cov diff --git a/ci/requirements-py3.8.yml b/ci/requirements-py3.8.yml index 0f5d63fd4a..4cdc543635 100644 --- a/ci/requirements-py3.8.yml +++ b/ci/requirements-py3.8.yml @@ -9,7 +9,7 @@ dependencies: - h5py - numba - numpy >= 1.16.0 - - pandas >= 0.25.0 + - pandas >= 1.3.0 - pip - pytest - pytest-cov diff --git a/ci/requirements-py3.9.yml b/ci/requirements-py3.9.yml index 14151ce47a..39b453e4b5 100644 --- a/ci/requirements-py3.9.yml +++ b/ci/requirements-py3.9.yml @@ -9,7 +9,7 @@ dependencies: - h5py - numba - numpy >= 1.16.0 - - pandas >= 0.25.0 + - pandas >= 1.3.0 - pip - pytest - pytest-cov From 7bfba0dfb9a86de7cac566265101069345a8a85e Mon Sep 17 00:00:00 2001 From: "Adam R. Jensen" <39184289+AdamRJensen@users.noreply.github.com> Date: Sat, 9 Mar 2024 15:20:29 +0100 Subject: [PATCH 16/17] Update test_solcast.py --- pvlib/tests/iotools/test_solcast.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pvlib/tests/iotools/test_solcast.py b/pvlib/tests/iotools/test_solcast.py index 19b00b8611..3879d88b20 100644 --- a/pvlib/tests/iotools/test_solcast.py +++ b/pvlib/tests/iotools/test_solcast.py @@ -174,9 +174,9 @@ def test_get_solcast_tmy( ), pd.DataFrame( [[9.4200e+02, 8.4300e+02, 1.0174e+05, 3.0000e+01, 7.8000e+00, - 3.1600e+02, 1.0100e+03, 2.0000e+00, 4.6000e+00, 1.6400e+02, 90], + 3.1600e+02, 1.0100e+03, 2.0000e+00, 4.6000e+00, 1.6400e+00, 90], [9.3600e+02, 8.3200e+02, 1.0179e+05, 3.0000e+01, 7.9000e+00, - 3.1600e+02, 9.9600e+02, 1.4000e+01, 4.5000e+00, 1.6300e+02, 0]], + 3.1600e+02, 9.9600e+02, 1.4000e+01, 4.5000e+00, 1.6300e+00, 0]], columns=[ 'dni', 'ghi', 'pressure', 'temp_air', 'wind_speed', 'wind_direction', 'poa_global', 'solar_azimuth', From 982164bb7ac5028189effca004036108026eabed Mon Sep 17 00:00:00 2001 From: "Adam R. Jensen" <39184289+AdamRJensen@users.noreply.github.com> Date: Sat, 9 Mar 2024 15:32:12 +0100 Subject: [PATCH 17/17] Advance numpy requirement --- ci/requirements-py3.10.yml | 2 +- ci/requirements-py3.11.yml | 2 +- ci/requirements-py3.12.yml | 2 +- ci/requirements-py3.7-min.yml | 2 +- ci/requirements-py3.7.yml | 2 +- ci/requirements-py3.8.yml | 2 +- ci/requirements-py3.9.yml | 2 +- docs/sphinx/source/whatsnew/v0.10.4.rst | 2 ++ pyproject.toml | 2 +- 9 files changed, 10 insertions(+), 8 deletions(-) diff --git a/ci/requirements-py3.10.yml b/ci/requirements-py3.10.yml index 9f97f69aa5..617d89c755 100644 --- a/ci/requirements-py3.10.yml +++ b/ci/requirements-py3.10.yml @@ -8,7 +8,7 @@ dependencies: - ephem - h5py - numba - - numpy >= 1.16.0 + - numpy >= 1.17.3 - pandas >= 1.3.0 - pip - pytest diff --git a/ci/requirements-py3.11.yml b/ci/requirements-py3.11.yml index 0ad4447f97..2ffdd932bd 100644 --- a/ci/requirements-py3.11.yml +++ b/ci/requirements-py3.11.yml @@ -8,7 +8,7 @@ dependencies: - ephem - h5py - numba - - numpy >= 1.16.0 + - numpy >= 1.17.3 - pandas >= 1.3.0 - pip - pytest diff --git a/ci/requirements-py3.12.yml b/ci/requirements-py3.12.yml index e81054ee06..250a9344c0 100644 --- a/ci/requirements-py3.12.yml +++ b/ci/requirements-py3.12.yml @@ -8,7 +8,7 @@ dependencies: - ephem - h5py - numba - - numpy >= 1.16.0 + - numpy >= 1.17.3 - pandas >= 1.3.0 - pip - pytest diff --git a/ci/requirements-py3.7-min.yml b/ci/requirements-py3.7-min.yml index 85995a132f..6371d5afb9 100644 --- a/ci/requirements-py3.7-min.yml +++ b/ci/requirements-py3.7-min.yml @@ -14,7 +14,7 @@ dependencies: - pip: - dataclasses - h5py==3.1.0 - - numpy==1.16.0 + - numpy==1.17.3 - pandas==1.3.0 - scipy==1.5.0 - pytest-rerunfailures # conda version is >3.6 diff --git a/ci/requirements-py3.7.yml b/ci/requirements-py3.7.yml index 339ea48e6e..4b175ec532 100644 --- a/ci/requirements-py3.7.yml +++ b/ci/requirements-py3.7.yml @@ -8,7 +8,7 @@ dependencies: - ephem - h5py - numba - - numpy >= 1.16.0 + - numpy >= 1.17.3 - pandas >= 1.3.0 - pip - pytest diff --git a/ci/requirements-py3.8.yml b/ci/requirements-py3.8.yml index 4cdc543635..814708a911 100644 --- a/ci/requirements-py3.8.yml +++ b/ci/requirements-py3.8.yml @@ -8,7 +8,7 @@ dependencies: - ephem - h5py - numba - - numpy >= 1.16.0 + - numpy >= 1.17.3 - pandas >= 1.3.0 - pip - pytest diff --git a/ci/requirements-py3.9.yml b/ci/requirements-py3.9.yml index 39b453e4b5..24573894b7 100644 --- a/ci/requirements-py3.9.yml +++ b/ci/requirements-py3.9.yml @@ -8,7 +8,7 @@ dependencies: - ephem - h5py - numba - - numpy >= 1.16.0 + - numpy >= 1.17.3 - pandas >= 1.3.0 - pip - pytest diff --git a/docs/sphinx/source/whatsnew/v0.10.4.rst b/docs/sphinx/source/whatsnew/v0.10.4.rst index 39395dd76d..0d5a72320d 100644 --- a/docs/sphinx/source/whatsnew/v0.10.4.rst +++ b/docs/sphinx/source/whatsnew/v0.10.4.rst @@ -50,6 +50,8 @@ Documentation Requirements ~~~~~~~~~~~~ * Minimum version of pandas advanced from 0.25.0 to 1.3.0. (:pull:`1969`) +* Minimum version of numpy advanced from 1.16.0 to 1.17.3. (:pull:`1969`) + Contributors ~~~~~~~~~~~~ diff --git a/pyproject.toml b/pyproject.toml index 030019b1f8..0053f0e568 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,7 +11,7 @@ authors = [ ] requires-python = ">=3.7" dependencies = [ - 'numpy >= 1.16.0', + 'numpy >= 1.17.3', 'pandas >= 1.3.0', 'pytz', 'requests',