Skip to content

add read pvgis tmy #907

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Mar 1, 2020
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -78,15 +78,17 @@ coverage.xml
*.h5


#Datafiles
# Datafiles
*.csv
# Ignore some csv
!pvlib/data/*.csv

# vi
*.swp

#Ignore some notebooks
# Ignore some notebooks
*.ipynb
!docs/tutorials/*.ipynb

#Ignore Mac DS_store files
# Ignore Mac DS_store files
*.DS_Store
1 change: 1 addition & 0 deletions docs/sphinx/source/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,7 @@ relevant to solar energy modeling.
iotools.read_psm3
iotools.parse_psm3
iotools.get_pvgis_tmy
iotools.read_pvgis_tmy

A :py:class:`~pvlib.location.Location` object may be created from metadata
in some files.
Expand Down
2 changes: 2 additions & 0 deletions docs/sphinx/source/whatsnew/v0.7.2.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ Enhancements
the original ``Date (MM/DD/YYYY)`` and ``Time (HH:MM)`` columns that the
indices were parsed from (:pull:`866`)
* Add Kimber soiling model :py:func:`pvlib.losses.soiling_kimber` (:pull:`860`)
* Add :func:`~pvlib.iotools.read_pvgis_tmy` for files downloaded using the
PVGIS tool (:issue:`880`)

Bug fixes
~~~~~~~~~
Expand Down
8,789 changes: 8,789 additions & 0 deletions pvlib/data/tmy_45.000_8.000_2005_2016.csv

Large diffs are not rendered by default.

8,768 changes: 8,768 additions & 0 deletions pvlib/data/tmy_45.000_8.000_2005_2016.epw

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions pvlib/data/tmy_45.000_8.000_2005_2016.json

Large diffs are not rendered by default.

8,761 changes: 8,761 additions & 0 deletions pvlib/data/tmy_45.000_8.000_2005_2016.txt

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion pvlib/iotools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@
from pvlib.iotools.psm3 import get_psm3 # noqa: F401
from pvlib.iotools.psm3 import read_psm3 # noqa: F401
from pvlib.iotools.psm3 import parse_psm3 # noqa: F401
from pvlib.iotools.pvgis import get_pvgis_tmy # noqa: F401
from pvlib.iotools.pvgis import get_pvgis_tmy, read_pvgis_tmy # noqa: F401
52 changes: 51 additions & 1 deletion pvlib/iotools/pvgis.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@
<https://ec.europa.eu/jrc/en/PVGIS/tools/monthly-radiation>`_
"""
import io
import json
import requests
import pandas as pd
from pvlib.iotools import parse_epw
from pvlib.iotools import read_epw, parse_epw

URL = 'https://re.jrc.ec.europa.eu/api/'

Expand Down Expand Up @@ -174,3 +175,52 @@ def _parse_pvgis_tmy_basic(src):
data['time(UTC)'], format='%Y%m%d:%H%M', utc=True)
data = data.drop('time(UTC)', axis=1)
return data, None, None, None


def read_pvgis_tmy(filename, outputformat='csv'):
"""
Read a file downloaded from PVGIS.

Parameters
----------
filename : str, pathlib.Path, or file-like buffer
Name, path, or buffer of file downloaded from PVGIS.
outputformat : str, default 'csv'
Output format of PVGIS file. Must be in
``['csv', 'basic', 'epw', 'json']``.

Returns
-------
data : pandas.DataFrame
the weather data
months_selected : list
TMY year for each month, ``None`` for basic and EPW
inputs : dict
the inputs, ``None`` for basic and EPW
meta : list or dict
meta data, ``None`` for basic

See also
--------
get_pvgis_tmy
"""
if outputformat == 'epw':
try:
data, meta = parse_epw(filename)
except AttributeError: # str/path has no .read() attribute
data, meta = read_epw(filename)
return data, None, None, meta
pvgis_parser = globals()['_parse_pvgis_tmy_{:s}'.format(outputformat)]
if outputformat == 'json':
try:
src = json.load(filename)
except AttributeError: # str/path has no .read() attribute
with open(str(filename), 'r') as fbuf:
src = json.load(fbuf)
return pvgis_parser(src)
try:
pvgis_data = pvgis_parser(filename)
except AttributeError: # str/path has no .read() attribute
with open(str(filename), 'rb') as fbuf:
pvgis_data = pvgis_parser(fbuf)
return pvgis_data
78 changes: 71 additions & 7 deletions pvlib/tests/iotools/test_pvgis.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import pandas as pd
import pytest
import requests
from pvlib.iotools import get_pvgis_tmy
from pvlib.iotools import get_pvgis_tmy, read_pvgis_tmy
from conftest import DATA_DIR


Expand Down Expand Up @@ -70,7 +70,14 @@ def csv_meta(meta_expected):
@pytest.mark.remote_data
def test_get_pvgis_tmy(expected, month_year_expected, inputs_expected,
meta_expected):
data, months_selected, inputs, meta = get_pvgis_tmy(45, 8)
pvgis_data = get_pvgis_tmy(45, 8)
_compare_pvgis_tmy_json(expected, month_year_expected, inputs_expected,
meta_expected, pvgis_data)


def _compare_pvgis_tmy_json(expected, month_year_expected, inputs_expected,
meta_expected, pvgis_data):
data, months_selected, inputs, meta = pvgis_data
# check each column of output separately
for outvar in meta_expected['outputs']['tmy_hourly']['variables'].keys():
assert np.allclose(data[outvar], expected[outvar])
Expand Down Expand Up @@ -113,7 +120,12 @@ def test_get_pvgis_tmy_kwargs(userhorizon_expected):

@pytest.mark.remote_data
def test_get_pvgis_tmy_basic(expected, meta_expected):
data, _, _, _ = get_pvgis_tmy(45, 8, outputformat='basic')
pvgis_data = get_pvgis_tmy(45, 8, outputformat='basic')
_compare_pvgis_tmy_basic(expected, meta_expected, pvgis_data)


def _compare_pvgis_tmy_basic(expected, meta_expected, pvgis_data):
data, _, _, _ = pvgis_data
# check each column of output separately
for outvar in meta_expected['outputs']['tmy_hourly']['variables'].keys():
assert np.allclose(data[outvar], expected[outvar])
Expand All @@ -122,8 +134,14 @@ def test_get_pvgis_tmy_basic(expected, meta_expected):
@pytest.mark.remote_data
def test_get_pvgis_tmy_csv(expected, month_year_expected, inputs_expected,
meta_expected, csv_meta):
data, months_selected, inputs, meta = get_pvgis_tmy(
45, 8, outputformat='csv')
pvgis_data = get_pvgis_tmy(45, 8, outputformat='csv')
_compare_pvgis_tmy_csv(expected, month_year_expected, inputs_expected,
meta_expected, csv_meta, pvgis_data)


def _compare_pvgis_tmy_csv(expected, month_year_expected, inputs_expected,
meta_expected, csv_meta, pvgis_data):
data, months_selected, inputs, meta = pvgis_data
# check each column of output separately
for outvar in meta_expected['outputs']['tmy_hourly']['variables'].keys():
assert np.allclose(data[outvar], expected[outvar])
Expand All @@ -144,8 +162,12 @@ def test_get_pvgis_tmy_csv(expected, month_year_expected, inputs_expected,

@pytest.mark.remote_data
def test_get_pvgis_tmy_epw(expected, epw_meta):
data, _, _, meta = get_pvgis_tmy(
45, 8, outputformat='epw')
pvgis_data = get_pvgis_tmy(45, 8, outputformat='epw')
_compare_pvgis_tmy_epw(expected, epw_meta, pvgis_data)


def _compare_pvgis_tmy_epw(expected, epw_meta, pvgis_data):
data, _, _, meta = pvgis_data
assert np.allclose(data.ghi, expected['G(h)'])
assert np.allclose(data.dni, expected['Gb(n)'])
assert np.allclose(data.dhi, expected['Gd(h)'])
Expand All @@ -160,3 +182,45 @@ def test_get_pvgis_tmy_error():
get_pvgis_tmy(45, 8, outputformat='bad')
with pytest.raises(requests.HTTPError, match='404 Client Error'):
get_pvgis_tmy(45, 8, url='https://re.jrc.ec.europa.eu/')


def test_read_pvgis_tmy_json(expected, month_year_expected, inputs_expected,
meta_expected):
fn = DATA_DIR / 'tmy_45.000_8.000_2005_2016.json'
pvgis_data = read_pvgis_tmy(fn, outputformat='json')
_compare_pvgis_tmy_json(expected, month_year_expected, inputs_expected,
meta_expected, pvgis_data)
with fn.open('r') as fbuf:
pvgis_data = read_pvgis_tmy(fbuf, outputformat='json')
_compare_pvgis_tmy_json(expected, month_year_expected, inputs_expected,
meta_expected, pvgis_data)


def test_read_pvgis_tmy_epw(expected, epw_meta):
fn = DATA_DIR / 'tmy_45.000_8.000_2005_2016.epw'
pvgis_data = read_pvgis_tmy(fn, outputformat='epw')
_compare_pvgis_tmy_epw(expected, epw_meta, pvgis_data)
with fn.open('r') as fbuf:
pvgis_data = read_pvgis_tmy(fbuf, outputformat='epw')
_compare_pvgis_tmy_epw(expected, epw_meta, pvgis_data)


def test_read_pvgis_tmy_csv(expected, month_year_expected, inputs_expected,
meta_expected, csv_meta):
fn = DATA_DIR / 'tmy_45.000_8.000_2005_2016.csv'
pvgis_data = read_pvgis_tmy(fn, outputformat='csv')
_compare_pvgis_tmy_csv(expected, month_year_expected, inputs_expected,
meta_expected, csv_meta, pvgis_data)
with fn.open('rb') as fbuf:
pvgis_data = read_pvgis_tmy(fbuf, outputformat='csv')
_compare_pvgis_tmy_csv(expected, month_year_expected, inputs_expected,
meta_expected, csv_meta, pvgis_data)


def test_read_pvgis_tmy_basic(expected, meta_expected):
fn = DATA_DIR / 'tmy_45.000_8.000_2005_2016.txt'
pvgis_data = read_pvgis_tmy(fn, outputformat='basic')
_compare_pvgis_tmy_basic(expected, meta_expected, pvgis_data)
with fn.open('rb') as fbuf:
pvgis_data = read_pvgis_tmy(fbuf, outputformat='basic')
_compare_pvgis_tmy_basic(expected, meta_expected, pvgis_data)