Skip to content

Commit 35f3b24

Browse files
author
AdamRJensen
committed
Add parser for pvgis_hourly csv and basic
1 parent 33451a1 commit 35f3b24

File tree

1 file changed

+65
-1
lines changed

1 file changed

+65
-1
lines changed

pvlib/iotools/pvgis.py

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,11 @@ def get_pvgis_hourly(lat, lon, angle=0, aspect=0,
175175
src = res.json()
176176
return _parse_pvgis_hourly_json(src)
177177
elif outputformat == 'csv':
178-
return _parse_pvgis_hourly_csv(src)
178+
with io.StringIO(res.content.decode('utf-8')) as src:
179+
return _parse_pvgis_hourly_csv(src)
180+
elif outputformat == 'basic':
181+
with io.BytesIO(res.content) as src:
182+
return _parse_pvgis_hourly_basic(src)
179183
else:
180184
# this line is never reached because if outputformat is not valid then
181185
# the response is HTTP/1.1 400 BAD REQUEST which is handled earlier
@@ -189,9 +193,69 @@ def _parse_pvgis_hourly_json(src):
189193
data = pd.DataFrame(src['outputs']['hourly'])
190194
data.index = pd.to_datetime(data['time'], format='%Y%m%d:%H%M', utc=True)
191195
data = data.drop('time', axis=1)
196+
data = data.astype(dtype={'Int': 'int'}) # The 'Int' column to be integer
192197
return data, inputs, meta
193198

194199

200+
def _parse_pvgis_hourly_basic(src):
201+
# Hourly data with outputformat='basic' does not include header or metadata
202+
data = pd.read_csv(src, header=None, skiprows=2)
203+
return data, None, None
204+
205+
206+
def _parse_pvgis_hourly_csv(src):
207+
# The first 4 rows are latitude, longitude, elevation, radiation database
208+
inputs = {}
209+
# 'Latitude (decimal degrees): 45.000\r\n'
210+
inputs['latitude'] = float(src.readline().split(':')[1])
211+
# 'Longitude (decimal degrees): 8.000\r\n'
212+
inputs['longitude'] = float(src.readline().split(':')[1])
213+
# Elevation (m): 1389.0\r\n
214+
inputs['elevation'] = float(src.readline().split(':')[1])
215+
# 'Radiation database: \tPVGIS-SARAH\r\n'
216+
inputs['radiation_database'] = str(src.readline().split(':')[1]
217+
.replace('\t', '').replace('\n', ''))
218+
219+
# Parse through the remaining metadata section (the number of lines for
220+
# this section depends on the requested parameters)
221+
while True:
222+
line = src.readline()
223+
if line.startswith('time,'): # The data header starts with 'time,'
224+
# The last line of the meta-data section contains the column names
225+
names = line.replace('\n', '').replace('\r', '').split(',')
226+
break
227+
# Only retrieve metadata from non-empty lines
228+
elif (line != '\n') & (line != '\r\n'):
229+
inputs[line.split(':')[0]] = str(line.split(':')[1]
230+
.replace('\n', '')
231+
.replace('\r', '').strip())
232+
233+
# The data section covers a variable number of lines (depends on requested
234+
# years) and ends with a blank line
235+
data_lines = []
236+
while True:
237+
line = src.readline()
238+
if (line == '\n') | (line == '\r\n'):
239+
break
240+
else:
241+
data_lines.append(line.replace('\n', '').replace('\r', '')
242+
.split(','))
243+
244+
data = pd.DataFrame(data_lines, columns=names)
245+
data.index = pd.to_datetime(data['time'], format='%Y%m%d:%H%M', utc=True)
246+
data = data.drop('time', axis=1)
247+
# All columns should have the dtype=float, except 'Int' which should be
248+
# integer. It is necessary to convert to float, before converting to int
249+
data = data.astype(float).astype(dtype={'Int': 'int'})
250+
251+
# Generate metadata dictionary containing description of parameters
252+
meta = {}
253+
for line in src.readlines():
254+
if ':' in line:
255+
meta[line.split(':')[0]] = line.split(':')[1].strip()
256+
257+
return data, inputs, meta
258+
195259
def get_pvgis_tmy(lat, lon, outputformat='json', usehorizon=True,
196260
userhorizon=None, startyear=None, endyear=None, url=URL,
197261
timeout=30):

0 commit comments

Comments
 (0)