From c482c306b6d8483341eb121172db1324116e9ad5 Mon Sep 17 00:00:00 2001 From: "Adam R. Jensen" <39184289+AdamRJensen@users.noreply.github.com> Date: Fri, 24 May 2024 16:42:44 +0200 Subject: [PATCH 1/3] Create meteonorm.py --- pvlib/iotools/meteonorm.py | 108 +++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 pvlib/iotools/meteonorm.py diff --git a/pvlib/iotools/meteonorm.py b/pvlib/iotools/meteonorm.py new file mode 100644 index 0000000000..3c6360ca2a --- /dev/null +++ b/pvlib/iotools/meteonorm.py @@ -0,0 +1,108 @@ +"""Functions to read and retrieve Meteonorm data.""" + +import requests +import pandas as pd + +URL = 'https://mdx.meteotest.ch/api_v1' + + +@dataclass +class ParameterMap: + meteonorm_name: str + pvlib_name: str + conversion: callable = lambda x: x + + +# define the conventions between Meteonorm and pvlib nomenclature and units +VARIABLE_MAP = [ + # 'Gh' is GHI without horizon effects + ParameterMap('Gh hor', 'ghi'), + ParameterMap('Gh max', 'ghi_clear'), + ParameterMap('Bn', 'dni'), + ParameterMap('Bh', 'bhi'), + # 'Dh' is 'DHI' without horizon effects + ParameterMap('Dh hor', 'dhi'), + ParameterMap('Dh min ', 'dhi_clear'), + # Check units of wind stuff XXX + ParameterMap('DD', 'wind_direction'), + ParameterMap('FF', 'wind_speed'), + ParameterMap('rh', 'relative_humidity'), + # surface_pressure (hPa) -> pressure (Pa) + ParameterMap('p', 'pressure', lambda x: x*100), + ParameterMap('w', 'precipitable_water'), # cm + ParameterMap('hs', 'solar_elevation'), + ParameterMap('az', 'solar_azimuth'), + ParameterMap('rho', 'albedo'), + ParameterMap('ta', 'temp_air'), + ParameterMap('td', 'temp_dew'), +] + +# inclination, azimuth, parameters, randomseed (default is 1), local situation, horname (optional, =auto -> topographic horizon) + + +def get_meteonorm_tmy(latitude, longitude, *, api_key, altitude=None, + parameters=None, map_variables=True, URL=URL): + """Get irradiance and weather for a Typical Meteorological Year (TMY) at a + requested location. + + Parameters + ---------- + latitude : float + in decimal degrees, between -90 and 90, north is positive + longitude : float + in decimal degrees, between -180 and 180, east is positive + api_key : str + To access Meteonorm data you will need an API key [2]_. + map_variables: bool, default: True + When true, renames columns of the DataFrame to pvlib variable names + where applicable. See variable :const:`VARIABLE_MAP`. + altitude : float, optional + DESCRIPTION. + parameters : list, optional + DESCRIPTION. + + Raises + ------ + requests + DESCRIPTION. + + Returns + ------- + data : pandas.DataFrame + DESCRIPTION. + meta : dict + DESCRIPTION. + + """ + params = { + 'key': api_key, + 'service': 'meteonorm', + 'action': 'calculatestandard', + 'lat': latitude, + 'lon': longitude, + 'format': 'json', + } + + # Optional variable, defaults to XXX + if altitude is not None: + params['altitude'] = altitude + + response = requests.get(URL, params=params) + + if not response.ok: + raise requests.HTTPError(response.json()) + + data = pd.DataFrame(response.json()['payload']['meteonorm']['target']).T + meta = response.json()['payload']['_metadata'] + + # rename and convert variables + for variable in VARIABLE_MAP: + if variable.meteonorm_name in data.columns: + data.rename( + columns={variable.meteonorm_name: variable.pvlib_name}, + inplace=True + ) + data[variable.pvlib_name] = data[ + variable.pvlib_name].apply(variable.conversion) + + return data, meta From bf61f9a44cdb85ce94c342a816cbdd549efbb28b Mon Sep 17 00:00:00 2001 From: "Adam R. Jensen" <39184289+AdamRJensen@users.noreply.github.com> Date: Fri, 24 May 2024 16:52:56 +0200 Subject: [PATCH 2/3] Add whatsnew and init entry --- docs/sphinx/source/reference/iotools.rst | 1 + docs/sphinx/source/whatsnew/v0.11.0.rst | 2 ++ pvlib/iotools/__init__.py | 1 + 3 files changed, 4 insertions(+) diff --git a/docs/sphinx/source/reference/iotools.rst b/docs/sphinx/source/reference/iotools.rst index 5f405d7536..6738b46007 100644 --- a/docs/sphinx/source/reference/iotools.rst +++ b/docs/sphinx/source/reference/iotools.rst @@ -54,6 +54,7 @@ of sources and file formats relevant to solar energy modeling. iotools.get_solcast_forecast iotools.get_solcast_live iotools.get_solargis + iotools.get_meteonorm_tmy A :py:class:`~pvlib.location.Location` object may be created from metadata diff --git a/docs/sphinx/source/whatsnew/v0.11.0.rst b/docs/sphinx/source/whatsnew/v0.11.0.rst index 142974ea78..9c38ff41b8 100644 --- a/docs/sphinx/source/whatsnew/v0.11.0.rst +++ b/docs/sphinx/source/whatsnew/v0.11.0.rst @@ -15,6 +15,8 @@ Deprecations Enhancements ~~~~~~~~~~~~ +* Add :py:func:`pvlib.iotools.get_meteonorm_tmy` for retrieving + Meteonorm weather and solar irradiance data. (:pull:`2066`) Bug fixes diff --git a/pvlib/iotools/__init__.py b/pvlib/iotools/__init__.py index 96259ecc24..33ec2ba7b8 100644 --- a/pvlib/iotools/__init__.py +++ b/pvlib/iotools/__init__.py @@ -35,3 +35,4 @@ 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 +from pvlib.iotools.meteonorm import get_meteonorm_tmy # noqa: F401 From 1c6c4352e3bde1b6980adde17780b3ba154ca564 Mon Sep 17 00:00:00 2001 From: "Adam R. Jensen" <39184289+AdamRJensen@users.noreply.github.com> Date: Fri, 31 May 2024 14:31:34 +0200 Subject: [PATCH 3/3] Add AOD mapping --- pvlib/iotools/meteonorm.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pvlib/iotools/meteonorm.py b/pvlib/iotools/meteonorm.py index 3c6360ca2a..d449182be6 100644 --- a/pvlib/iotools/meteonorm.py +++ b/pvlib/iotools/meteonorm.py @@ -30,6 +30,7 @@ class ParameterMap: # surface_pressure (hPa) -> pressure (Pa) ParameterMap('p', 'pressure', lambda x: x*100), ParameterMap('w', 'precipitable_water'), # cm + ParameterMap('aot', 'aod'), ParameterMap('hs', 'solar_elevation'), ParameterMap('az', 'solar_azimuth'), ParameterMap('rho', 'albedo'),