Skip to content

Commit 4101bb2

Browse files
bgpiercBenkdebrabcwhansePierce
authored
Adding PVGIS horizon data retrieval method (#1395)
* added horizon model first draft * added get horizon function * fixing stickler items & updates * stickler whitespace * finishing up stickler * finishing up stickler, 2 * added optional deps, changed argument of horizon_map from path to array * stickler * Update pvlib/iotools/pvgis.py Co-authored-by: Karel De Brabandere <[email protected]> * Update pvlib/horizon.py Co-authored-by: Cliff Hansen <[email protected]> * Update pvlib/horizon.py Co-authored-by: Cliff Hansen <[email protected]> * Update pvlib/horizon.py Co-authored-by: Cliff Hansen <[email protected]> * Update pvlib/horizon.py Co-authored-by: Cliff Hansen <[email protected]> * Update pvlib/horizon.py Co-authored-by: Cliff Hansen <[email protected]> * Update pvlib/horizon.py Co-authored-by: Cliff Hansen <[email protected]> * Update pvlib/horizon.py Co-authored-by: Cliff Hansen <[email protected]> * Update pvlib/horizon.py Co-authored-by: Cliff Hansen <[email protected]> * Update pvlib/horizon.py Co-authored-by: Cliff Hansen <[email protected]> * Update pvlib/horizon.py Co-authored-by: Cliff Hansen <[email protected]> * Update pvlib/horizon.py Co-authored-by: Cliff Hansen <[email protected]> * Update pvlib/horizon.py Co-authored-by: Cliff Hansen <[email protected]> * Update pvlib/horizon.py Co-authored-by: Cliff Hansen <[email protected]> * Update pvlib/horizon.py Co-authored-by: Cliff Hansen <[email protected]> * updates * cleaning up stickler * cleaning up stickler 2 * cleaning up stickler 3 * updated math for angle calculation * removed old comment * updated angle maximization method * one of these days I'll remember stickler before pushing * changed variable names to make clear that we're working in pixels * added module to download SRTM DEM data * spelling/spacing * stickler * stickler3 * fixed f string formatting stickler doesn't like it but it doesn't work with spaces * added horizon retrival, functions, dem retrival * stickler * stickler2 * stickler3 * Revert "merge2" This reverts commit 6f9ad5e, reversing changes made to 43951a2. * fix formatting * fix formatting, 2 * removing horizon.py * tests added * updated test * fixed stickler * minor formatting/stickler * Update v0.9.6.rst * Update iotools.rst * Apply suggestions from code review Co-authored-by: Kevin Anderson <[email protected]> * Change assert to use np builtin * correct docstring for hidden function * Chnage proxy settings to passing through kwargs * Changed proxy settings to pass kwargs * Change assertion to use assert_series_equal from conftest * Added horizon profile contributions * Update v0.9.6.rst * Delete cgiar.py * Delete test_cgiar.py * Update shading.py * Update setup.py * Update __init__.py * Update iotools.rst * Update test_pvgis.py * return only two columns and makde bytes->utf-8 implicit * Use JSON to streamline processing * Update pvgis.py * added url default info * remove np dependency * Apply suggestions from code review Co-authored-by: Adam R. Jensen <[email protected]> * Moved ref for consistency * Updated name of horizon data variable * Add CSV for horizon tests * Test whole dataframe * Change coordinate system to pvlib * fix test to read in csv properly * Apply suggestions from code review Co-authored-by: Adam R. Jensen <[email protected]> * Changed names for consistency * Match column names in test dataframe * stickler * Set horizon_azimuth to the index * Added invalid coords test * update test to reflect change to index * forgot xfail flag * Update test_read_pvgis_horzion_invalid_coords * return metadata object * Update pvgis.py * fix tests for metadata update * Remove index column from test file * Convert output to pd.Series * Update tests to assert pd.Series * Remove duplicate north value (0, 360) --------- Co-authored-by: Ben <[email protected]> Co-authored-by: Karel De Brabandere <[email protected]> Co-authored-by: Cliff Hansen <[email protected]> Co-authored-by: Pierce <[email protected]> Co-authored-by: Kevin Anderson <[email protected]> Co-authored-by: Adam R. Jensen <[email protected]>
1 parent 909f86d commit 4101bb2

File tree

6 files changed

+135
-3
lines changed

6 files changed

+135
-3
lines changed

docs/sphinx/source/reference/iotools.rst

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ of sources and file formats relevant to solar energy modeling.
3131
iotools.read_pvgis_tmy
3232
iotools.get_pvgis_hourly
3333
iotools.read_pvgis_hourly
34+
iotools.get_pvgis_horizon
3435
iotools.get_bsrn
3536
iotools.read_bsrn
3637
iotools.parse_bsrn

docs/sphinx/source/whatsnew/v0.9.6.rst

+11-2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ Deprecations
2121

2222
Enhancements
2323
~~~~~~~~~~~~
24+
* Added function to retrieve horizon data from PVGIS
25+
:py:func:`pvlib.iotools.get_pvgis_horizon`. (:issue:`1290`, :pull:`1395`)
2426
* Added ``map_variables`` argument to the :py:func:`pvlib.iotools.read_tmy3` in
2527
order to offer the option of mapping column names to standard pvlib names.
2628
(:issue:`1517`, :pull:`1623`)
@@ -31,7 +33,6 @@ Enhancements
3133
* :py:func:`pvlib.iotools.get_psm3` now uses the new NSRDB 3.2.2 endpoint for
3234
hourly and half-hourly single-year datasets. (:issue:`1591`, :pull:`1736`)
3335

34-
3536
Bug fixes
3637
~~~~~~~~~
3738
* `data` can no longer be left unspecified in
@@ -59,9 +60,17 @@ Contributors
5960
~~~~~~~~~~~~
6061
* Lakshya Garg (:ghuser:`Lakshyadevelops`)
6162
* Adam R. Jensen (:ghuser:`adamrjensen`)
63+
* Ben Pierce (:ghuser:`bgpierc`)
64+
* Joseph Palakapilly (:ghuser:`JPalakapillyKWH`)
65+
* Cliff Hansen (:ghuser:`cwhanse`)
66+
* Anton Driesse (:ghuser:`adriesse`)
67+
* Will Holmgren (:ghuser:`wholmgren`)
68+
* Mark Mikofski (:ghuser:`mikofski`)
69+
* Karel De Brabandere (:ghuser:`kdebrab`)
70+
* Josh Stein (:ghuser:`jsstein`)
71+
* Kevin Anderson (:ghuser:`kandersolar`)
6272
* Siddharth Kaul (:ghuser:`k10blogger`)
6373
* Kshitiz Gupta (:ghuser:`kshitiz305`)
6474
* Stefan de Lange (:ghuser:`langestefan`)
6575
* :ghuser:`ooprathamm`
6676
* Kevin Anderson (:ghuser:`kandersolar`)
67-
+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
horizon_azimuth,horizon_elevation
2+
0,9.9
3+
7.5,13
4+
15,14.5
5+
22.5,15.7
6+
30,14.9
7+
37.5,15.3
8+
45,15.7
9+
52.5,15.7
10+
60,13
11+
67.5,11.5
12+
75,11.1
13+
82.5,11.5
14+
90,10.3
15+
97.5,11.5
16+
105,10.3
17+
112.5,9.5
18+
120,10.7
19+
127.5,11.8
20+
135,11.8
21+
142.5,8.8
22+
150,8.4
23+
157.5,7.3
24+
165,5.7
25+
172.5,5.7
26+
180,4.6
27+
187.5,3.4
28+
195,0.8
29+
202.5,0
30+
210,0
31+
217.5,0
32+
225,0
33+
232.5,0
34+
240,0
35+
247.5,0
36+
255,0
37+
262.5,0
38+
270,0
39+
277.5,0
40+
285,0
41+
292.5,0
42+
300,0
43+
307.5,0
44+
315,1.1
45+
322.5,1.9
46+
330,3.8
47+
337.5,5
48+
345,6.5
49+
352.5,9.2

pvlib/iotools/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from pvlib.iotools.pvgis import get_pvgis_tmy, read_pvgis_tmy # noqa: F401
1616
from pvlib.iotools.pvgis import read_pvgis_hourly # noqa: F401
1717
from pvlib.iotools.pvgis import get_pvgis_hourly # noqa: F401
18+
from pvlib.iotools.pvgis import get_pvgis_horizon # noqa: F401
1819
from pvlib.iotools.bsrn import get_bsrn # noqa: F401
1920
from pvlib.iotools.bsrn import read_bsrn # noqa: F401
2021
from pvlib.iotools.bsrn import parse_bsrn # noqa: F401

pvlib/iotools/pvgis.py

+54
Original file line numberDiff line numberDiff line change
@@ -665,3 +665,57 @@ def read_pvgis_tmy(filename, pvgis_format=None, map_variables=None):
665665
data = data.rename(columns=VARIABLE_MAP)
666666

667667
return data, months_selected, inputs, meta
668+
669+
670+
def get_pvgis_horizon(latitude, longitude, url=URL, **kwargs):
671+
"""Get horizon data from PVGIS.
672+
673+
Parameters
674+
----------
675+
latitude : float
676+
Latitude in degrees north
677+
longitude : float
678+
Longitude in degrees east
679+
url: str, default: :const:`pvlib.iotools.pvgis.URL`
680+
Base URL for PVGIS
681+
kwargs:
682+
Passed to requests.get
683+
684+
Returns
685+
-------
686+
data : pd.Series
687+
Pandas Series of the retrived horizon elevation angles. Index is the
688+
corresponding horizon azimuth angles.
689+
metadata : dict
690+
Metadata returned by PVGIS.
691+
692+
Notes
693+
-----
694+
The horizon azimuths are specified clockwise from north, e.g., south=180.
695+
This is the standard pvlib convention, although the PVGIS website specifies
696+
south=0.
697+
698+
References
699+
----------
700+
.. [1] `PVGIS horizon profile tool
701+
<https://ec.europa.eu/jrc/en/PVGIS/tools/horizon>`_
702+
"""
703+
params = {'lat': latitude, 'lon': longitude, 'outputformat': 'json'}
704+
res = requests.get(url + 'printhorizon', params=params, **kwargs)
705+
if not res.ok:
706+
try:
707+
err_msg = res.json()
708+
except Exception:
709+
res.raise_for_status()
710+
else:
711+
raise requests.HTTPError(err_msg['message'])
712+
json_output = res.json()
713+
metadata = json_output['meta']
714+
data = pd.DataFrame(json_output['outputs']['horizon_profile'])
715+
data.columns = ['horizon_azimuth', 'horizon_elevation']
716+
# Convert azimuth to pvlib convention (north=0, south=180)
717+
data['horizon_azimuth'] += 180
718+
data.set_index('horizon_azimuth', inplace=True)
719+
data = data['horizon_elevation'] # convert to pd.Series
720+
data = data[data.index < 360] # remove duplicate north point (0 and 360)
721+
return data, metadata

pvlib/tests/iotools/test_pvgis.py

+19-1
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@
99
import requests
1010
from pvlib.iotools import get_pvgis_tmy, read_pvgis_tmy
1111
from pvlib.iotools import get_pvgis_hourly, read_pvgis_hourly
12+
from pvlib.iotools import get_pvgis_horizon
1213
from ..conftest import (DATA_DIR, RERUNS, RERUNS_DELAY, assert_frame_equal,
13-
fail_on_pvlib_version)
14+
fail_on_pvlib_version, assert_series_equal)
1415
from pvlib._deprecation import pvlibDeprecationWarning
1516

1617

@@ -509,6 +510,23 @@ def test_get_pvgis_map_variables(pvgis_tmy_mapped_columns):
509510
assert all([c in pvgis_tmy_mapped_columns for c in actual.columns])
510511

511512

513+
@pytest.mark.remote_data
514+
@pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY)
515+
def test_read_pvgis_horizon():
516+
pvgis_data, _ = get_pvgis_horizon(35.171051, -106.465158)
517+
horizon_data = pd.read_csv(DATA_DIR / 'test_read_pvgis_horizon.csv',
518+
index_col=0)
519+
horizon_data = horizon_data['horizon_elevation']
520+
assert_series_equal(pvgis_data, horizon_data)
521+
522+
523+
@pytest.mark.remote_data
524+
@pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY)
525+
def test_read_pvgis_horizon_invalid_coords():
526+
with pytest.raises(requests.HTTPError, match='lat: Incorrect value'):
527+
_, _ = get_pvgis_horizon(100, 50) # unfeasible latitude
528+
529+
512530
def test_read_pvgis_tmy_map_variables(pvgis_tmy_mapped_columns):
513531
fn = DATA_DIR / 'tmy_45.000_8.000_2005_2016.json'
514532
actual, _, _, _ = read_pvgis_tmy(fn, map_variables=True)

0 commit comments

Comments
 (0)